[Rust,front-end,v1,1/4] Add skeleton Rust front-end folder

Message ID 20220727134040.843750-2-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 is a skeleton front-end which is used so we can ensure each patch is
buildable:

gcc/rust/ChangeLog:

	* Make-lang.in
	* config-lang.in
	* lang-specs.h
	* lang.opt
	* rust-lang.cc
	* rustspec.cc
---
 gcc/rust/Make-lang.in   | 308 +++++++++++++++++++++++++++++++++++++
 gcc/rust/config-lang.in |  30 ++++
 gcc/rust/lang-specs.h   |  26 ++++
 gcc/rust/lang.opt       |  45 ++++++
 gcc/rust/rust-lang.cc   | 332 ++++++++++++++++++++++++++++++++++++++++
 gcc/rust/rustspec.cc    | 285 ++++++++++++++++++++++++++++++++++
 6 files changed, 1026 insertions(+)
 create mode 100644 gcc/rust/Make-lang.in
 create mode 100644 gcc/rust/config-lang.in
 create mode 100644 gcc/rust/lang-specs.h
 create mode 100644 gcc/rust/lang.opt
 create mode 100644 gcc/rust/rust-lang.cc
 create mode 100644 gcc/rust/rustspec.cc
  

Patch

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
new file mode 100644
index 00000000000..759960544c8
--- /dev/null
+++ b/gcc/rust/Make-lang.in
@@ -0,0 +1,308 @@ 
+# Make-lang.in -- Top level -*- makefile -*- fragment for GCC Rust frontend.
+
+# Copyright (C) 2009-2022 Free Software Foundation, Inc.
+
+# This file is part of GCC.
+
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# This file provides the language dependent support in the main Makefile.
+
+#RUST_EXES = rust
+
+# Use strict warnings for this front end.
+rust-warn = $(STRICT_WARN)
+
+# Installation name. Useful for cross compilers and used during install.
+GCCRS_INSTALL_NAME := $(shell echo gccrs|sed '$(program_transform_name)')
+GCCRS_TARGET_INSTALL_NAME := $(target_noncanonical)-$(shell echo gccrs|sed '$(program_transform_name)')
+
+# Define the names for selecting rust in LANGUAGES.
+rust: rust1$(exeext)
+
+# Tell GNU make to ignore files by these names if they exist.
+.PHONY: rust
+
+# removed GRS_CFLAGS from here
+
+CFLAGS-rust/rustspec.o += $(DRIVER_DEFINES)
+
+# Create the compiler driver gccrs.
+# A compiler driver is the program that interprets command argument and can be called from the command
+# line - e.g. gcc or g++, and not cc1, which is the actual compiler
+
+# Create driver objects
+GCCRS_D_OBJS = \
+   $(GCC_OBJS) \
+   rust/rustspec.o \
+   $(END)
+
+gccrs$(exeext): $(GCCRS_D_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBDEPS)
+	+$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
+	  $(GCCRS_D_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a \
+	  $(EXTRA_GCC_LIBS) $(LIBS)
+
+# List of host object files used by the rust language - files for translation from the parse tree
+# to GENERIC
+# The compiler proper, not driver
+GRS_OBJS = \
+    rust/rust-lang.o \
+    $(END)
+# removed object files from here
+
+# All language-specific object files for Rust.
+RUST_ALL_OBJS = $(GRS_OBJS) $(RUST_TARGET_OBJS)
+
+rust_OBJS = $(RUST_ALL_OBJS) rust/rustspec.o
+
+# The compiler itself is called rust1 (formerly grs1)
+rust1$(exeext): $(RUST_ALL_OBJS) attribs.o $(BACKEND) $(LIBDEPS)
+	+$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
+	      $(RUST_ALL_OBJS) attribs.o $(BACKEND) $(LIBS) $(BACKENDLIBS)
+
+# Build hooks.
+
+lang_checks += check-rust
+lang_checks_parallelized += check-rust
+check_rust_parallelize = 10
+
+# Copies its dependencies into the source directory. This generally should be used for generated files
+# such as Bison output files which are not version-controlled, but should be included in any release
+# tarballs. This target will be executed during a bootstrap if ‘--enable-generated-files-in-srcdir’
+# was specified as a configure option.
+rust.srcextra:
+
+rust.all.cross: gccrs$(exeext)
+
+# idk what this does but someone used it
+rust.start.encap: gccrs$(exeext)
+rust.rest.encap:
+
+# Build generated man pages for the front end from Texinfo manuals (see Man Page Generation), in the
+# build directory. This target is only called if the necessary tools are available, but should ignore
+# errors so as not to stop the build if errors occur; man pages are optional and the tools involved
+# may be installed in a broken way.
+rust.man:
+
+# Copies its dependencies into the source directory. These targets will be executed during a bootstrap
+# if ‘--enable-generated-files-in-srcdir’ was specified as a configure option.
+rust.srcman:
+
+# Clean hooks.
+
+rust.mostlyclean:
+#	cd $(srcdir)/rust; rm -f *.o y.tab.h y.tab.c lex.yy.c
+
+rust.clean: rust.mostlyclean
+
+# Builds an etags TAGS file in the language subdirectory in the source tree.
+# TODO: add more directories if I add more
+rust.tags: force
+	cd $(srcdir)/rust; \
+	etags -o TAGS.sub *.y *.l *.cc *.h ast/*.h ast/*.cc lex/*.h lex/*.cc parse/*.h parse/*.cc; \
+	etags --include TAGS.sub --include ../TAGS.sub
+
+# Build documentation hooks.
+
+# Build info documentation for the front end, in the build directory. This target is only called by
+# ‘make bootstrap’ if a suitable version of makeinfo is available, so does not need to check for this,
+# and should fail if an error occurs.
+rust.info:
+
+rust.srcinfo:
+
+# Build DVI documentation for the front end, in the build directory. This should be done using
+# $(TEXI2DVI), with appropriate -I arguments pointing to directories of included files.
+rust.dvi:
+
+# Build PDF documentation for the front end, in the build directory. This should be done using
+# $(TEXI2PDF), with appropriate -I arguments pointing to directories of included files.
+rust.pdf:
+
+doc/rust.info:
+doc/rust.dvi:
+doc/rust.pdf:
+
+# Build HTML documentation for the front end, in the build directory.
+rust.html:
+
+# Install hooks.
+
+# Install everything that is part of the front end, apart from the compiler executables listed in
+# compilers in config-lang.in.
+rust.install-common: installdirs
+#	-rm -f $(DESTDIR)$(bindir)/$(GCCRS_INSTALL_NAME)$(exeext)
+#	-rm -f $(DESTDIR)$(bindir)/$(GCCRS_TARGET_INSTALL_NAME)$(exeext)
+#	$(INSTALL_PROGRAM) gccrs$(exeext) $(DESTDIR)$(bindir)/$(GCCRS_INSTALL_NAME)$(exeext)
+#	if test -f $(DESTDIR)$(bindir)$(GCCRS_TARGET_INSTALL_NAME)$(exeext); then \
+#	  :; \
+#	else \
+#	  cd $(DESTDIR)$(bindir) && \
+#	   $(LN) $(GCCRS_INSTALL_NAME)$(exeext) $(GCCRS_TARGET_INSTALL_NAME)$(exeext); \
+#	fi
+	-rm -f $(DESTDIR)$(bindir)/$(GCCRS_INSTALL_NAME)$(exeext)
+	$(INSTALL_PROGRAM) gccrs$(exeext) $(DESTDIR)$(bindir)/$(GCCRS_INSTALL_NAME)$(exeext)
+	rm -f $(DESTDIR)$(bindir)/$(GCCRS_TARGET_INSTALL_NAME)$(exeext); \
+	( cd $(DESTDIR)$(bindir) && \
+      $(LN) $(GCCRS_INSTALL_NAME)$(exeext) $(GCCRS_TARGET_INSTALL_NAME)$(exeext) ); \
+
+# Install headers needed for plugins.
+rust.install-plugin:
+
+# Uninstall files installed by installing the compiler. This is currently documented not to be
+# supported, so the hook need not do anything.
+rust.uninstall:
+#	-rm -rf $(DESTDIR)/$(bindir)/$(GCCRS_INSTALL_NAME)$(exeext)
+	-rm -f gccrs$(exeext) grs1$(exeext)
+	-rm -f $(RUST_ALL_OBJS)
+# ^those two are a maybe
+
+# Enable selftests for the rust frontend
+selftest-rust: s-selftest-rust
+
+RUST_SELFTEST_FLAGS = -xrs $(SELFTEST_FLAGS)
+RUST_SELFTEST_DEPS = rust1$(exeext) $(SELFTEST_DEPS)
+
+# Run the rust selftests
+s-selftest-rust: $(RUST_SELFTEST_DEPS)
+	$(GCC_FOR_TARGET) $(RUST_SELFTEST_FLAGS)
+	$(STAMP) $@
+
+# Install info documentation for the front end, if it is present in the source directory. This target
+# should have dependencies on info files that should be installed.
+rust.install-info:
+
+rust.install-pdf:
+
+# Install man pages for the front end. This target should ignore errors.
+rust.install-man:
+
+# Stage hooks:
+# The toplevel makefile has already created stage?/rust at this point.
+# Used for handling bootstrap
+
+rust.stage1: stage1-start
+	-mv rust/*$(objext) stage1/rust
+rust.stage2: stage2-start
+	-mv rust/*$(objext) stage2/rust
+rust.stage3: stage3-start
+	-mv rust/*$(objext) stage3/rust
+rust.stage4: stage4-start
+	-mv rust/*$(objext) stage4/rust
+rust.stageprofile: stageprofile-start
+	-mv rust/*$(objext) stageprofile/rust
+rust.stagefeedback: stagefeedback-start
+	-mv rust/*$(objext) stagefeedback/rust
+
+CFLAGS-rust/rust-lang.o += -DDEFAULT_TARGET_VERSION=\"$(version)\" \
+	-DDEFAULT_TARGET_MACHINE=\"$(target_noncanonical)\"
+
+# cross-folder includes - add new folders later
+RUST_INCLUDES = -I $(srcdir)/rust \
+	-I $(srcdir)/rust/lex \
+	-I $(srcdir)/rust/parse \
+	-I $(srcdir)/rust/ast \
+	-I $(srcdir)/rust/analysis \
+	-I $(srcdir)/rust/backend \
+	-I $(srcdir)/rust/expand \
+	-I $(srcdir)/rust/hir/tree \
+	-I $(srcdir)/rust/hir \
+	-I $(srcdir)/rust/resolve \
+	-I $(srcdir)/rust/util \
+	-I $(srcdir)/rust/typecheck \
+	-I $(srcdir)/rust/checks/lints \
+	-I $(srcdir)/rust/checks/errors \
+	-I $(srcdir)/rust/checks/errors/privacy \
+	-I $(srcdir)/rust/util \
+        -I $(srcdir)/rust/metadata
+
+# add files that require cross-folder includes - currently rust-lang.o, rust-lex.o
+CFLAGS-rust/rust-lang.o += $(RUST_INCLUDES)
+CFLAGS-rust/rust-lex.o += $(RUST_INCLUDES)
+CFLAGS-rust/rust-parse.o += $(RUST_INCLUDES)
+CFLAGS-rust/rust-session-manager.o += $(RUST_INCLUDES)
+
+# TODO: possibly find a way to ensure C++11 compilation level here?
+RUST_CXXFLAGS = -std=c++11 -Wno-unused-parameter -Werror=overloaded-virtual
+
+# build all rust/lex files in rust folder, add cross-folder includes
+rust/%.o: rust/lex/%.cc
+	$(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
+	$(POSTCOMPILE)
+
+# build all rust/parse files in rust folder, add cross-folder includes
+rust/%.o: rust/parse/%.cc
+	$(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
+	$(POSTCOMPILE)
+
+# build rust/ast files in rust folder
+rust/%.o: rust/ast/%.cc
+	$(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
+	$(POSTCOMPILE)
+
+# build rust/backend files in rust folder
+rust/%.o: rust/backend/%.cc
+	$(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
+	$(POSTCOMPILE)
+
+# build rust/expand files in rust folder
+rust/%.o: rust/expand/%.cc
+	$(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
+	$(POSTCOMPILE)
+
+# build rust/util files in rust folder
+rust/%.o: rust/util/%.cc
+	$(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
+	$(POSTCOMPILE)
+
+# build rust/hir files in rust folder
+rust/%.o: rust/hir/%.cc
+	$(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
+	$(POSTCOMPILE)
+
+# build rust/hir/tree files in rust folder
+rust/%.o: rust/hir/tree/%.cc
+	$(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
+	$(POSTCOMPILE)
+
+# build rust/resolve files in rust folder
+rust/%.o: rust/resolve/%.cc
+	$(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
+	$(POSTCOMPILE)
+
+# build rust/typecheck files in rust folder
+rust/%.o: rust/typecheck/%.cc
+	$(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
+	$(POSTCOMPILE)
+
+# build rust/checks/lints files in rust folder
+rust/%.o: rust/checks/lints/%.cc
+	$(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
+	$(POSTCOMPILE)
+
+# build rust/checks/errors files in rust folder
+rust/%.o: rust/checks/errors/%.cc
+	$(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
+	$(POSTCOMPILE)
+
+# build privacy pass files in rust folder
+rust/%.o: rust/checks/errors/privacy/%.cc
+	$(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
+	$(POSTCOMPILE)
+
+# build rust/metadata files in rust folder
+rust/%.o: rust/metadata/%.cc
+	$(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
+	$(POSTCOMPILE)
diff --git a/gcc/rust/config-lang.in b/gcc/rust/config-lang.in
new file mode 100644
index 00000000000..9196b6cf417
--- /dev/null
+++ b/gcc/rust/config-lang.in
@@ -0,0 +1,30 @@ 
+# config-lang.in -- Top level configure fragment for gcc Rust frontend.
+
+# Copyright (C) 2009-2022 Free Software Foundation, Inc.
+
+# This file is part of GCC.
+
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# Configure looks for the existence of this file to auto-config each language.
+# We define several parameters used by configure:
+#
+# language	- name of language as it would appear in $(LANGUAGES)
+# compilers	- value to add to $(COMPILERS)
+
+language="rust"
+compilers="rust1\$(exeext)"
+build_by_default="no"
+gtfiles="\$(srcdir)/rust/rust-lang.cc"
diff --git a/gcc/rust/lang-specs.h b/gcc/rust/lang-specs.h
new file mode 100644
index 00000000000..9b14a559dd6
--- /dev/null
+++ b/gcc/rust/lang-specs.h
@@ -0,0 +1,26 @@ 
+/* lang-specs.h -- gcc driver specs for Rust frontend.
+   Copyright (C) 2009-2022 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This is the contribution to the `default_compilers' array in gcc.cc
+   for the Rust language.  */
+
+{".rs", "@rs", 0, 1, 0},
+  {"@rs",
+   "rust1 %i %(cc1_options) %{I*} %{L*} %D %{!fsyntax-only:%(invoke_as)}", 0, 1,
+   0},
diff --git a/gcc/rust/lang.opt b/gcc/rust/lang.opt
new file mode 100644
index 00000000000..5a23711278e
--- /dev/null
+++ b/gcc/rust/lang.opt
@@ -0,0 +1,45 @@ 
+; Options for the Rust front end.
+; Copyright (C) 2003-2022 Free Software Foundation, Inc.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 3, or (at your option) any later
+; version.
+; 
+; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+; WARRANTY; without even the implied warranty of MERCHANTABILITY or
+; FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+; for more details.
+; 
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING3.  If not see
+; <http://www.gnu.org/licenses/>.
+
+; See the GCC internals manual for a description of this file's format.
+
+; Please try to keep this file in ASCII collating order.
+
+; Describes command-line options used by this frontend
+
+Language
+Rust
+
+I
+Rust Joined Separate
+; Documented in c.opt
+
+L
+Rust Joined Separate
+; Not documented
+
+Wall
+Rust
+; Documented in c.opt
+
+o
+Rust Joined Separate
+; Documented in common.opt
+
+; This comment is to ensure we retain the blank line above.
diff --git a/gcc/rust/rust-lang.cc b/gcc/rust/rust-lang.cc
new file mode 100644
index 00000000000..5592129addf
--- /dev/null
+++ b/gcc/rust/rust-lang.cc
@@ -0,0 +1,332 @@ 
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "target.h"
+#include "tree.h"
+#include "gimple-expr.h"
+#include "diagnostic.h"
+#include "opts.h"
+#include "fold-const.h"
+#include "gimplify.h"
+#include "stor-layout.h"
+#include "debug.h"
+#include "convert.h"
+#include "langhooks.h"
+#include "langhooks-def.h"
+#include "options.h"
+#include <mpfr.h>
+
+// Language-dependent contents of a type. GTY() mark used for garbage collector.
+struct GTY (()) lang_type
+{
+  char dummy;
+};
+
+// Language-dependent contents of a decl.
+struct GTY (()) lang_decl
+{
+  char dummy;
+};
+
+// Language-dependent contents of an identifier.  This must include a
+// tree_identifier.
+struct GTY (()) lang_identifier
+{
+  struct tree_identifier common;
+};
+
+// The resulting tree type.
+union GTY ((
+  desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
+  chain_next (
+    "CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), "
+    "TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN (&%h.generic)) : NULL")))
+  lang_tree_node
+{
+  union tree_node GTY ((tag ("0"), desc ("tree_node_structure (&%h)"))) generic;
+  struct lang_identifier GTY ((tag ("1"))) identifier;
+};
+
+// We don't use language_function.
+struct GTY (()) language_function
+{
+  int dummy;
+};
+
+/* Language hooks.  */
+
+tree
+convert (tree type, tree expr)
+{
+  if (type == error_mark_node || expr == error_mark_node
+      || TREE_TYPE (expr) == error_mark_node)
+    return error_mark_node;
+
+  if (type == TREE_TYPE (expr))
+    return expr;
+
+  if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr)))
+    return fold_convert (type, expr);
+
+  switch (TREE_CODE (type))
+    {
+    case VOID_TYPE:
+    case BOOLEAN_TYPE:
+      return fold_convert (type, expr);
+    case INTEGER_TYPE:
+      return fold (convert_to_integer (type, expr));
+    case POINTER_TYPE:
+      return fold (convert_to_pointer (type, expr));
+    case REAL_TYPE:
+      return fold (convert_to_real (type, expr));
+    case COMPLEX_TYPE:
+      return fold (convert_to_complex (type, expr));
+    default:
+      break;
+    }
+
+  gcc_unreachable ();
+}
+
+/* Initial lang hook called (possibly), used for initialisation.
+ * Must call build_common_tree_nodes, set_sizetype, build_common_tree_nodes_2,
+ * and build_common_builtin_nodes, as well as set global variable
+ * void_list_node. Apparently called after option handling? */
+static bool
+grs_langhook_init (void)
+{
+  /* Something to do with this:
+   This allows the code in d-builtins.cc to not have to worry about
+   converting (C signed char *) to (D char *) for string arguments of
+   built-in functions. The parameter (signed_char = false) specifies
+   whether char is signed.  */
+  build_common_tree_nodes (false);
+
+  // Creates a new TREE_LIST node with purpose NULL_TREE and value
+  // void_type_node
+  void_list_node = build_tree_list (NULL_TREE, void_type_node);
+
+  // Builds built-ins for middle-end after all front-end built-ins are already
+  // instantiated
+  build_common_builtin_nodes ();
+
+  mpfr_set_default_prec (128);
+
+  using_eh_for_cleanups ();
+
+  return true;
+}
+
+/* The option mask (something to do with options for specific frontends or
+ * something). */
+static unsigned int
+grs_langhook_option_lang_mask (void)
+{
+  return CL_Rust;
+}
+
+/* Initialize the options structure. */
+static void
+grs_langhook_init_options_struct (struct gcc_options * /* opts */)
+{}
+
+/* Main entry point for front-end, apparently. Finds input file names in global
+ * vars in_fnames and num_in_fnames. From this, frontend can take over and do
+ * actual parsing and initial compilation. This function must create a complete
+ * parse tree in a global var, and then return.
+ *
+ * Some consider this the "start of compilation". */
+static void
+grs_langhook_parse_file (void)
+{}
+
+/* Seems to get the exact type for a specific type - e.g. for scalar float with
+ * 32-bit bitsize, it returns float, and for 64-bit bitsize, it returns double.
+ * Used to map RTL nodes to machine modes or something like that. */
+static tree
+grs_langhook_type_for_mode (machine_mode mode, int unsignedp)
+{
+  if (mode == TYPE_MODE (float_type_node))
+    return float_type_node;
+
+  if (mode == TYPE_MODE (double_type_node))
+    return double_type_node;
+
+  if (mode == TYPE_MODE (intQI_type_node)) // quarter integer mode - single byte
+					   // treated as integer
+    return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
+  if (mode
+      == TYPE_MODE (intHI_type_node)) // half integer mode - two-byte integer
+    return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
+  if (mode
+      == TYPE_MODE (intSI_type_node)) // single integer mode - four-byte integer
+    return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
+  if (mode
+      == TYPE_MODE (
+	intDI_type_node)) // double integer mode - eight-byte integer
+    return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
+  if (mode
+      == TYPE_MODE (intTI_type_node)) // tetra integer mode - 16-byte integer
+    return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
+
+  if (mode == TYPE_MODE (integer_type_node))
+    return unsignedp ? unsigned_type_node : integer_type_node;
+
+  if (mode == TYPE_MODE (long_integer_type_node))
+    return unsignedp ? long_unsigned_type_node : long_integer_type_node;
+
+  if (mode == TYPE_MODE (long_long_integer_type_node))
+    return unsignedp ? long_long_unsigned_type_node
+		     : long_long_integer_type_node;
+
+  if (COMPLEX_MODE_P (mode))
+    {
+      if (mode == TYPE_MODE (complex_float_type_node))
+	return complex_float_type_node;
+      if (mode == TYPE_MODE (complex_double_type_node))
+	return complex_double_type_node;
+      if (mode == TYPE_MODE (complex_long_double_type_node))
+	return complex_long_double_type_node;
+      if (mode == TYPE_MODE (complex_integer_type_node) && !unsignedp)
+	return complex_integer_type_node;
+    }
+  /* gcc_unreachable */
+  return NULL;
+}
+
+// Record a builtin function. We just ignore builtin functions.
+static tree
+grs_langhook_builtin_function (tree decl ATTRIBUTE_UNUSED)
+{
+  return decl;
+}
+
+static bool
+grs_langhook_global_bindings_p (void)
+{
+  return false;
+}
+
+static tree
+grs_langhook_pushdecl (tree decl ATTRIBUTE_UNUSED)
+{
+  gcc_unreachable ();
+  return NULL;
+}
+
+static tree
+grs_langhook_getdecls (void)
+{
+  return NULL;
+}
+
+static bool
+grs_langhook_handle_option (
+  size_t scode ATTRIBUTE_UNUSED, const char *arg ATTRIBUTE_UNUSED,
+  HOST_WIDE_INT value ATTRIBUTE_UNUSED, int kind ATTRIBUTE_UNUSED,
+  location_t loc ATTRIBUTE_UNUSED,
+  const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED)
+{
+  return false;
+}
+
+static bool
+grs_langhook_post_options (const char **pfilename ATTRIBUTE_UNUSED)
+{
+  /* Returning false means that the backend should be used.  */
+  return false;
+}
+
+/* Rust-specific gimplification. May need to gimplify e.g.
+ * CALL_EXPR_STATIC_CHAIN */
+static int
+grs_langhook_gimplify_expr (tree *expr_p ATTRIBUTE_UNUSED,
+			    gimple_seq *pre_p ATTRIBUTE_UNUSED,
+			    gimple_seq *post_p ATTRIBUTE_UNUSED)
+{
+  return GS_UNHANDLED;
+}
+
+static tree
+grs_langhook_eh_personality (void)
+{
+  return error_mark_node;
+}
+
+/* FIXME: This is a hack to preserve trees that we create from the
+   garbage collector.  */
+
+static GTY (()) tree rust_gc_root;
+
+void
+rust_preserve_from_gc (tree t)
+{
+  rust_gc_root = tree_cons (NULL_TREE, t, rust_gc_root);
+}
+
+/* Convert an identifier for use in an error message.  */
+
+const char *
+rust_localize_identifier (const char *ident)
+{
+  return identifier_to_locale (ident);
+}
+
+/* The language hooks data structure. This is the main interface between the GCC
+ * front-end and the GCC middle-end/back-end. A list of language hooks could be
+ * found in <gcc>/langhooks.h
+ */
+#undef LANG_HOOKS_NAME
+#undef LANG_HOOKS_INIT
+#undef LANG_HOOKS_OPTION_LANG_MASK
+#undef LANG_HOOKS_INIT_OPTIONS_STRUCT
+#undef LANG_HOOKS_HANDLE_OPTION
+#undef LANG_HOOKS_POST_OPTIONS
+#undef LANG_HOOKS_PARSE_FILE
+#undef LANG_HOOKS_TYPE_FOR_MODE
+#undef LANG_HOOKS_BUILTIN_FUNCTION
+#undef LANG_HOOKS_GLOBAL_BINDINGS_P
+#undef LANG_HOOKS_PUSHDECL
+#undef LANG_HOOKS_GETDECLS
+#undef LANG_HOOKS_WRITE_GLOBALS
+#undef LANG_HOOKS_GIMPLIFY_EXPR
+#undef LANG_HOOKS_EH_PERSONALITY
+
+#define LANG_HOOKS_NAME "GNU Rust"
+#define LANG_HOOKS_INIT grs_langhook_init
+#define LANG_HOOKS_OPTION_LANG_MASK grs_langhook_option_lang_mask
+#define LANG_HOOKS_INIT_OPTIONS_STRUCT grs_langhook_init_options_struct
+#define LANG_HOOKS_HANDLE_OPTION grs_langhook_handle_option
+#define LANG_HOOKS_POST_OPTIONS grs_langhook_post_options
+#define LANG_HOOKS_PARSE_FILE grs_langhook_parse_file
+#define LANG_HOOKS_TYPE_FOR_MODE grs_langhook_type_for_mode
+#define LANG_HOOKS_BUILTIN_FUNCTION grs_langhook_builtin_function
+#define LANG_HOOKS_GLOBAL_BINDINGS_P grs_langhook_global_bindings_p
+#define LANG_HOOKS_PUSHDECL grs_langhook_pushdecl
+#define LANG_HOOKS_GETDECLS grs_langhook_getdecls
+#define LANG_HOOKS_GIMPLIFY_EXPR grs_langhook_gimplify_expr
+#define LANG_HOOKS_EH_PERSONALITY grs_langhook_eh_personality
+
+// Expands all LANG_HOOKS_x of GCC
+struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
+
+#include "gt-rust-rust-lang.h"
+#include "gtype-rust.h"
diff --git a/gcc/rust/rustspec.cc b/gcc/rust/rustspec.cc
new file mode 100644
index 00000000000..eb49444cade
--- /dev/null
+++ b/gcc/rust/rustspec.cc
@@ -0,0 +1,285 @@ 
+/* rustspec.c -- Specific flags and argument handling of the gcc Rust front end.
+   Copyright (C) 2009-2022 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "opts.h"
+
+// satisfy intellisense
+#include "options.h"
+
+/* This bit is set if we saw a `-xfoo' language specification.  */
+#define LANGSPEC (1 << 1)
+/* This bit is set if they did `-lc'.  */
+#define WITHLIBC (1 << 2)
+/* Skip this option.  */
+#define SKIPOPT (1 << 3)
+
+void
+lang_specific_driver (struct cl_decoded_option **in_decoded_options,
+		      unsigned int *in_decoded_options_count,
+		      int *in_added_libraries)
+{
+  unsigned int i, j;
+
+  /* This is a tristate:
+     -1 means we should not link in librust
+     0  means we should link in librust if it is needed
+     1  means librust is needed and should be linked in.
+     2  means librust is needed and should be linked statically.  */
+  int library = 0;
+
+  /* The new argument list will be contained in this.  */
+  struct cl_decoded_option *new_decoded_options;
+
+  /* "-lc" if it appears on the command line.  */
+  const struct cl_decoded_option *saw_libc = 0;
+
+  /* An array used to flag each argument that needs a bit set for
+     LANGSPEC or WITHLIBC.  */
+  int *args;
+
+  /* True if we saw -static.  */
+  int static_link = 0;
+
+  /* True if we should add -shared-libgcc to the command-line.  */
+  int shared_libgcc = 1;
+
+  /* The total number of arguments with the new stuff.  */
+  unsigned int argc;
+
+  /* The argument list.  */
+  struct cl_decoded_option *decoded_options;
+
+  /* The number of libraries added in.  */
+  int added_libraries;
+
+  /* The total number of arguments with the new stuff.  */
+  int num_args = 1;
+
+  /* Whether the -o option was used.  */
+  bool saw_opt_o = false;
+
+  /* Whether the -c option was used.  Also used for -E, -fsyntax-only,
+     in general anything which implies only compilation and not
+     linking.  */
+  bool saw_opt_c = false;
+
+  /* Whether the -S option was used.  */
+  bool saw_opt_S = false;
+
+  /* The first input file with an extension of .rs.  */
+  const char *first_rust_file = NULL;
+
+  argc = *in_decoded_options_count;
+  decoded_options = *in_decoded_options;
+  added_libraries = *in_added_libraries;
+
+  args = XCNEWVEC (int, argc);
+
+  for (i = 1; i < argc; i++)
+    {
+      const char *arg = decoded_options[i].arg;
+
+      switch (decoded_options[i].opt_index)
+	{
+	case OPT_r:
+	case OPT_nostdlib:
+	case OPT_nodefaultlibs:
+	  library = -1;
+	  break;
+
+	case OPT_l:
+	  if (strcmp (arg, "c") == 0)
+	    args[i] |= WITHLIBC;
+	  else
+	    /* Unrecognized libraries (e.g. -lfoo) may require librust.  */
+	    library = (library == 0) ? 1 : library;
+	  break;
+
+	case OPT_x:
+	  if (library == 0 && strcmp (arg, "rust") == 0)
+	    library = 1;
+	  break;
+
+	case OPT_Xlinker:
+	case OPT_Wl_:
+	  /* Arguments that go directly to the linker might be .o files,
+	     or something, and so might cause librust to be needed.  */
+	  if (library == 0)
+	    library = 1;
+	  break;
+
+	case OPT_c:
+	case OPT_E:
+	case OPT_M:
+	case OPT_MM:
+	case OPT_fsyntax_only:
+	  /* Don't specify libraries if we won't link, since that would
+	     cause a warning.  */
+	  saw_opt_c = true;
+	  library = -1;
+	  break;
+
+	case OPT_S:
+	  saw_opt_S = true;
+	  library = -1;
+	  break;
+
+	case OPT_o:
+	  saw_opt_o = true;
+	  break;
+
+	case OPT_static:
+	  static_link = 1;
+	  break;
+
+	case OPT_static_libgcc:
+	  shared_libgcc = 0;
+	  break;
+
+	case OPT_SPECIAL_input_file:
+	  if (library == 0)
+	    library = 1;
+
+	  if (first_rust_file == NULL)
+	    {
+	      int len;
+
+	      len = strlen (arg);
+	      if (len > 3 && strcmp (arg + len - 3, ".rs") == 0)
+		first_rust_file = arg;
+	    }
+
+	  break;
+	}
+    }
+
+    /* There's no point adding -shared-libgcc if we don't have a shared
+       libgcc.  */
+#ifndef ENABLE_SHARED_LIBGCC
+  shared_libgcc = 0;
+#endif
+
+  /* Make sure to have room for the trailing NULL argument.  */
+  num_args = argc + shared_libgcc + (library > 0) * 5 + 10;
+  new_decoded_options = XNEWVEC (struct cl_decoded_option, num_args);
+
+  i = 0;
+  j = 0;
+
+  /* Copy the 0th argument, i.e., the name of the program itself.  */
+  new_decoded_options[j++] = decoded_options[i++];
+
+  /* NOTE: We start at 1 now, not 0.  */
+  while (i < argc)
+    {
+      new_decoded_options[j] = decoded_options[i];
+
+      if (!saw_libc && (args[i] & WITHLIBC) && library > 0)
+	{
+	  --j;
+	  saw_libc = &decoded_options[i];
+	}
+
+      if ((args[i] & SKIPOPT) != 0)
+	--j;
+
+      i++;
+      j++;
+    }
+
+  /* If we didn't see a -o option, add one.  This is because we need
+     the driver to pass all .rs files to rust1.  Without a -o option the
+     driver will invoke rust1 separately for each input file.  FIXME:
+     This should probably use some other interface to force the driver
+     to set combine_inputs.  */
+  if (first_rust_file != NULL && !saw_opt_o)
+    {
+      if (saw_opt_c || saw_opt_S)
+	{
+	  const char *base;
+	  int baselen;
+	  int alen;
+	  char *out;
+
+	  base = lbasename (first_rust_file);
+	  baselen = strlen (base) - 3;
+	  alen = baselen + 3;
+	  out = XNEWVEC (char, alen);
+	  memcpy (out, base, baselen);
+	  /* The driver will convert .o to some other suffix (e.g.,
+	     .obj) if appropriate.  */
+	  out[baselen] = '.';
+	  if (saw_opt_S)
+	    out[baselen + 1] = 's';
+	  else
+	    out[baselen + 1] = 'o';
+	  out[baselen + 2] = '\0';
+	  generate_option (OPT_o, out, 1, CL_DRIVER, &new_decoded_options[j]);
+	}
+      else
+	generate_option (OPT_o, "a.out", 1, CL_DRIVER, &new_decoded_options[j]);
+      j++;
+    }
+
+  /* Add `-lrust' if we haven't already done so.  */
+  if (library > 0)
+    {
+#ifdef HAVE_LD_STATIC_DYNAMIC
+      if (library > 1 && !static_link)
+	{
+	  generate_option (OPT_Wl_, LD_STATIC_OPTION, 1, CL_DRIVER,
+			   &new_decoded_options[j]);
+	  j++;
+	}
+#endif
+
+#ifdef HAVE_LD_STATIC_DYNAMIC
+      if (library > 1 && !static_link)
+	{
+	  generate_option (OPT_Wl_, LD_DYNAMIC_OPTION, 1, CL_DRIVER,
+			   &new_decoded_options[j]);
+	  j++;
+	}
+#endif
+    }
+
+  if (saw_libc)
+    new_decoded_options[j++] = *saw_libc;
+  if (shared_libgcc && !static_link)
+    generate_option (OPT_shared_libgcc, NULL, 1, CL_DRIVER,
+		     &new_decoded_options[j++]);
+
+  *in_decoded_options_count = j;
+  *in_decoded_options = new_decoded_options;
+  *in_added_libraries = added_libraries;
+}
+
+/* Called before linking.  Returns 0 on success and -1 on failure.  */
+int
+lang_specific_pre_link (void) /* Not used for Rust.  */
+{
+  return 0;
+}
+
+/* Number of extra output files that lang_specific_pre_link may generate.  */
+int lang_specific_extra_outfiles = 0; /* Not used for Rust.  */