diff --git a/config/gcc-plugin.m4 b/config/gcc-plugin.m4
index dd06a58cd13..38b2ae6e12e 100644
--- a/config/gcc-plugin.m4
+++ b/config/gcc-plugin.m4
@@ -19,8 +19,21 @@ AC_DEFUN([GCC_ENABLE_PLUGINS],
    enable_plugin=yes; default_plugin=yes)
 
    pluginlibs=
+   plugin_check=yes
 
    case "${host}" in
+     *-*-mingw*)
+       # Since plugin support under MinGW is not as straightforward as on
+       # other platforms (e.g., we have to link import library, etc), we
+       # only enable it if explicitly requested.
+       if test x"$default_plugin" = x"yes"; then
+         enable_plugin=no
+       elif test x"$enable_plugin" = x"yes"; then
+         # Use make's target variable to derive import library name.
+         pluginlibs='-Wl,--export-all-symbols -Wl,--out-implib=[$]@.a'
+	 plugin_check=no
+       fi
+     ;;
      *-*-darwin*)
        if test x$build = x$host; then
 	 export_sym_check="nm${exeext} -g"
@@ -41,7 +54,7 @@ AC_DEFUN([GCC_ENABLE_PLUGINS],
      ;;
    esac
 
-   if test x"$enable_plugin" = x"yes"; then
+   if test x"$enable_plugin" = x"yes" -a x"$plugin_check" = x"yes"; then
 
      AC_MSG_CHECKING([for exported symbols])
      if test "x$export_sym_check" != x; then
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 824cf3e3ea0..fe71d010483 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -57,6 +57,7 @@ MAKEOVERRIDES =
 build=@build@
 host=@host@
 host_noncanonical=@host_noncanonical@
+host_os=@host_os@
 target=@target@
 target_noncanonical:=@target_noncanonical@
 
@@ -393,6 +394,11 @@ PLUGINLIBS = @pluginlibs@
 
 enable_plugin = @enable_plugin@
 
+# On MinGW plugin installation involves installing import libraries.
+ifeq ($(enable_plugin),yes)
+  plugin_implib := $(if $(strip $(filter mingw%,$(host_os))),yes,no)
+endif
+
 enable_host_shared = @enable_host_shared@
 
 enable_as_accelerator = @enable_as_accelerator@
@@ -2826,11 +2832,15 @@ $(genprog:%=build/gen%$(build_exeext)): build/gen%$(build_exeext): build/gen%.o
 	    $(filter-out $(BUILD_LIBDEPS), $^) $(BUILD_LIBS)
 
 # Generated source files for gengtype.  Prepend inclusion of
-# bconfig.h because AIX requires _LARGE_FILES to be defined before
+# config.h/bconfig.h because AIX requires _LARGE_FILES to be defined before
 # any system header is included.
 gengtype-lex.c : gengtype-lex.l
 	-$(FLEX) $(FLEXFLAGS) -o$@ $< && { \
-	  echo '#include "bconfig.h"' > $@.tmp; \
+          echo '#ifdef HOST_GENERATOR_FILE' > $@.tmp; \
+          echo '#include "config.h"'       >> $@.tmp; \
+          echo '#else'                     >> $@.tmp; \
+          echo '#include "bconfig.h"'      >> $@.tmp; \
+          echo '#endif'                    >> $@.tmp; \
           cat $@ >> $@.tmp; \
           mv $@.tmp $@; \
 	}
diff --git a/gcc/c/Make-lang.in b/gcc/c/Make-lang.in
index cfd8cd2b169..6b029d47cae 100644
--- a/gcc/c/Make-lang.in
+++ b/gcc/c/Make-lang.in
@@ -125,7 +125,14 @@ check-c : check-gcc
 
 c.install-common:
 c.install-man:
-c.install-plugin:
+
+c.install-plugin: installdirs
+# Install import library.
+ifeq ($(plugin_implib),yes)
+	$(mkinstalldirs) $(DESTDIR)$(plugin_resourcesdir)
+	$(INSTALL_DATA) cc1$(exeext).a $(DESTDIR)/$(plugin_resourcesdir)/cc1$(exeext).a
+endif
+
 c.uninstall:
 
 #
diff --git a/gcc/configure b/gcc/configure
index fb40ead9204..4d09b99948f 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -29619,8 +29619,21 @@ fi
 
 
    pluginlibs=
+   plugin_check=yes
 
    case "${host}" in
+     *-*-mingw*)
+       # Since plugin support under MinGW is not as straightforward as on
+       # other platforms (e.g., we have to link import library, etc), we
+       # only enable it if explicitly requested.
+       if test x"$default_plugin" = x"yes"; then
+         enable_plugin=no
+       elif test x"$enable_plugin" = x"yes"; then
+         # Use make's target variable to derive import library name.
+         pluginlibs='-Wl,--export-all-symbols -Wl,--out-implib=$@.a'
+	 plugin_check=no
+       fi
+     ;;
      *-*-darwin*)
        if test x$build = x$host; then
 	 export_sym_check="nm${exeext} -g"
@@ -29641,7 +29654,7 @@ fi
      ;;
    esac
 
-   if test x"$enable_plugin" = x"yes"; then
+   if test x"$enable_plugin" = x"yes" -a x"$plugin_check" = x"yes"; then
 
      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for exported symbols" >&5
 $as_echo_n "checking for exported symbols... " >&6; }
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index c852f6a38b4..a84e37f6075 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -238,6 +238,11 @@ c++.install-plugin: installdirs
 	  $(mkinstalldirs) $(DESTDIR)$$dir; \
 	  $(INSTALL_DATA) $$path $(DESTDIR)$$dest; \
 	done
+# Install import library.
+ifeq ($(plugin_implib),yes)
+	$(mkinstalldirs) $(DESTDIR)$(plugin_resourcesdir)
+	$(INSTALL_DATA) cc1plus$(exeext).a $(DESTDIR)/$(plugin_resourcesdir)/cc1plus$(exeext).a
+endif
 
 c++.uninstall:
 	-rm -rf $(DESTDIR)$(bindir)/$(CXX_INSTALL_NAME)$(exeext)
diff --git a/gcc/doc/plugins.texi b/gcc/doc/plugins.texi
index 6fc7b9ae9a2..20e161f77ad 100644
--- a/gcc/doc/plugins.texi
+++ b/gcc/doc/plugins.texi
@@ -34,14 +34,17 @@ can be quite useful.
 @section Loading Plugins
 
 Plugins are supported on platforms that support @option{-ldl
--rdynamic}.  They are loaded by the compiler using @code{dlopen}
-and invoked at pre-determined locations in the compilation
-process.
+-rdynamic} as well as Windows/MinGW. They are loaded by the compiler
+using @code{dlopen} or equivalent and invoked at pre-determined
+locations in the compilation process.
 
 Plugins are loaded with
 
-@option{-fplugin=/path/to/@var{name}.so} @option{-fplugin-arg-@var{name}-@var{key1}[=@var{value1}]}
+@option{-fplugin=/path/to/@var{name}.@var{ext}} @option{-fplugin-arg-@var{name}-@var{key1}[=@var{value1}]}
 
+Where @var{name} is the plugin name and @var{ext} is the platform-specific
+dynamic library extension. It should be @code{dll} on Windows/MinGW,
+@code{dylib} on Darwin/Mac OS X, and @code{so} on all other platforms.
 The plugin arguments are parsed by GCC and passed to respective
 plugins as key-value pairs. Multiple plugins can be invoked by
 specifying multiple @option{-fplugin} arguments.
@@ -49,7 +52,7 @@ specifying multiple @option{-fplugin} arguments.
 A plugin can be simply given by its short name (no dots or
 slashes). When simply passing @option{-fplugin=@var{name}}, the plugin is
 loaded from the @file{plugin} directory, so @option{-fplugin=@var{name}} is
-the same as @option{-fplugin=`gcc -print-file-name=plugin`/@var{name}.so},
+the same as @option{-fplugin=`gcc -print-file-name=plugin`/@var{name}.@var{ext}},
 using backquote shell syntax to query the @file{plugin} directory.
 
 @node Plugin API
@@ -508,6 +511,48 @@ A single source file plugin may be built with @code{g++ -I`gcc
 plugin.so}, using backquote shell syntax to query the @file{plugin}
 directory.
 
+Plugin support on Windows/MinGW has a number of limitations and
+additional requirements. When building a plugin on Windows we have to
+link an import library for the corresponding backend executable, for
+example, @file{cc1.exe}, @file{cc1plus.exe}, etc., in order to gain
+access to the symbols provided by GCC. This means that on Windows a
+plugin is language-specific, for example, for C, C++, etc. If you wish
+to use your plugin with multiple languages, then you will need to
+build multiple plugin libraries and either instruct your users on how
+to load the correct version or provide a compiler wrapper that does
+this automatically.
+
+Additionally, on Windows the plugin library has to export the
+@code{plugin_is_GPL_compatible} and @code{plugin_init} symbols. If you
+do not wish to modify the source code of your plugin, then you can use
+the @option{-Wl,--export-all-symbols} option or provide a suitable DEF
+file. Alternatively, you can export just these two symbols by decorating
+them with @code{__declspec(dllexport)}, for example:
+
+@smallexample
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int plugin_is_GPL_compatible;
+
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int plugin_init (plugin_name_args *, plugin_gcc_version *)
+@end smallexample
+
+The import libraries are installed into the @code{plugin} directory
+and their names are derived by appending the @code{.a} extension to
+the backend executable names, for example, @file{cc1.exe.a},
+@file{cc1plus.exe.a}, etc. The following command line shows how to
+build the single source file plugin on Windows to be used with the C++
+compiler:
+
+@smallexample
+g++ -I`gcc -print-file-name=plugin`/include -shared -Wl,--export-all-symbols \
+-o plugin.dll plugin.c `gcc -print-file-name=plugin`/cc1plus.exe.a
+@end smallexample
+
 When a plugin needs to use @command{gengtype}, be sure that both
 @file{gengtype} and @file{gtype.state} have the same version as the
 GCC for which the plugin is built.
diff --git a/gcc/plugin.c b/gcc/plugin.c
index 9892748cd15..fb3e3590537 100644
--- a/gcc/plugin.c
+++ b/gcc/plugin.c
@@ -34,6 +34,16 @@ along with GCC; see the file COPYING3.  If not see
 #include "plugin-version.h"
 #endif
 
+#ifdef __MINGW32__
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+#include <windows.h>
+#endif
+
 #define GCC_PLUGIN_STRINGIFY0(X) #X
 #define GCC_PLUGIN_STRINGIFY1(X) GCC_PLUGIN_STRINGIFY0 (X)
 
@@ -144,7 +154,7 @@ get_plugin_base_name (const char *full_name)
   /* First get the base name part of the full-path name, i.e. NAME.so.  */
   char *base_name = xstrdup (lbasename (full_name));
 
-  /* Then get rid of '.so' part of the name.  */
+  /* Then get rid of the extension in the name, e.g., .so.  */
   strip_off_ending (base_name, strlen (base_name));
 
   return base_name;
@@ -175,12 +185,27 @@ add_new_plugin (const char* plugin_name)
   if (name_is_short)
     {
       base_name = CONST_CAST (char*, plugin_name);
-      /* FIXME: the ".so" suffix is currently builtin, since plugins
-	 only work on ELF host systems like e.g. Linux or Solaris.
-	 When plugins shall be available on non ELF systems such as
-	 Windows or MacOS, this code has to be greatly improved.  */
+
+#if defined(__MINGW32__)
+      static const char plugin_ext[] = ".dll";
+#elif defined(__APPLE__)
+      /* Mac OS has two types of libraries: dynamic libraries (.dylib) and
+         plugins (.bundle). Both can be used with dlopen()/dlsym() but the
+         former cannot be linked at build time (i.e., with the -lfoo linker
+         option). A GCC plugin is therefore probably a Mac OS plugin but their
+         use seems to be quite rare and the .bundle extension is more of a
+         recommendation rather than the rule. This raises the questions of how
+         well they are supported by tools (e.g., libtool). So to avoid
+         complications let's use the .dylib extension for now. In the future,
+         if this proves to be an issue, we can always check for both
+         extensions.  */
+      static const char plugin_ext[] = ".dylib";
+#else
+      static const char plugin_ext[] = ".so";
+#endif
+
       plugin_name = concat (default_plugin_dir_name (), "/",
-			    plugin_name, ".so", NULL);
+			    plugin_name, plugin_ext, NULL);
       if (access (plugin_name, R_OK))
 	fatal_error
 	  (input_location,
@@ -573,6 +598,85 @@ invoke_plugin_callbacks_full (int event, void *gcc_data)
 }
 
 #ifdef ENABLE_PLUGIN
+
+/* Try to initialize PLUGIN. Return true if successful. */
+
+#ifdef __MINGW32__
+
+// Return a message string for last error or NULL if unknown. Must be freed
+// with LocalFree().
+static inline char *
+win32_error_msg ()
+{
+  char *msg;
+  return FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER |
+			 FORMAT_MESSAGE_FROM_SYSTEM |
+			 FORMAT_MESSAGE_IGNORE_INSERTS |
+			 FORMAT_MESSAGE_MAX_WIDTH_MASK,
+			 0,
+			 GetLastError (),
+			 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
+			 (char*)&msg,
+			 0,
+			 0)
+    ? msg
+    : NULL;
+}
+
+static bool
+try_init_one_plugin (struct plugin_name_args *plugin)
+{
+  HMODULE dl_handle;
+  plugin_init_func plugin_init;
+
+  dl_handle = LoadLibrary (plugin->full_name);
+  if (!dl_handle)
+    {
+      char *err = win32_error_msg ();
+      error ("cannot load plugin %s\n%s", plugin->full_name, err);
+      LocalFree (err);
+      return false;
+    }
+
+  /* Check the plugin license. Unlike the name suggests, GetProcAddress()
+     can be used for both functions and variables.  */
+  if (GetProcAddress (dl_handle, str_license) == NULL)
+    {
+      char *err = win32_error_msg ();
+      fatal_error (input_location,
+		   "plugin %s is not licensed under a GPL-compatible license\n"
+		   "%s", plugin->full_name, err);
+    }
+
+  /* Unlike dlsym(), GetProcAddress() returns a pointer to a function so we
+     can cast directly without union tricks.  */
+  plugin_init = (plugin_init_func)
+    GetProcAddress (dl_handle, str_plugin_init_func_name);
+
+  if (plugin_init == NULL)
+    {
+      char *err = win32_error_msg ();
+      FreeLibrary (dl_handle);
+      error ("cannot find %s in plugin %s\n%s", str_plugin_init_func_name,
+             plugin->full_name, err);
+      LocalFree (err);
+      return false;
+    }
+
+  /* Call the plugin-provided initialization routine with the arguments.  */
+  if ((*plugin_init) (plugin, &gcc_version))
+    {
+      FreeLibrary (dl_handle);
+      error ("fail to initialize plugin %s", plugin->full_name);
+      return false;
+    }
+  /* Leak dl_handle on purpose to ensure the plugin is loaded for the
+     entire run of the compiler. */
+  return true;
+}
+
+#else // POSIX-like with dlopen()/dlsym().
+
 /* We need a union to cast dlsym return value to a function pointer
    as ISO C forbids assignment between function pointer and 'void *'.
    Use explicit union instead of __extension__(<union_cast>) for
@@ -581,8 +685,6 @@ invoke_plugin_callbacks_full (int event, void *gcc_data)
 #define PTR_UNION_AS_VOID_PTR(NAME) (NAME._q)
 #define PTR_UNION_AS_CAST_PTR(NAME) (NAME._nq)
 
-/* Try to initialize PLUGIN. Return true if successful. */
-
 static bool
 try_init_one_plugin (struct plugin_name_args *plugin)
 {
@@ -634,7 +736,7 @@ try_init_one_plugin (struct plugin_name_args *plugin)
      entire run of the compiler. */
   return true;
 }
-
+#endif
 
 /* Routine to dlopen and initialize one plugin. This function is passed to
    (and called by) the hash table traverse routine. Return 1 for the
diff --git a/libcc1/configure b/libcc1/configure
index d6f480fe930..23d1a7645ff 100755
--- a/libcc1/configure
+++ b/libcc1/configure
@@ -14552,8 +14552,21 @@ fi
 
 
    pluginlibs=
+   plugin_check=yes
 
    case "${host}" in
+     *-*-mingw*)
+       # Since plugin support under MinGW is not as straightforward as on
+       # other platforms (e.g., we have to link import library, etc), we
+       # only enable it if explicitly requested.
+       if test x"$default_plugin" = x"yes"; then
+         enable_plugin=no
+       elif test x"$enable_plugin" = x"yes"; then
+         # Use make's target variable to derive import library name.
+         pluginlibs='-Wl,--export-all-symbols -Wl,--out-implib=$@.a'
+	 plugin_check=no
+       fi
+     ;;
      *-*-darwin*)
        if test x$build = x$host; then
 	 export_sym_check="nm${exeext} -g"
@@ -14574,7 +14587,7 @@ fi
      ;;
    esac
 
-   if test x"$enable_plugin" = x"yes"; then
+   if test x"$enable_plugin" = x"yes" -a x"$plugin_check" = x"yes"; then
 
      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for exported symbols" >&5
 $as_echo_n "checking for exported symbols... " >&6; }
