/* Mapper name.  */
 static const char *module_mapper_name;
 
+/* Deferred import queue (FIFO).  */
+static vec<module_state *, va_heap, vl_embed> *pending_imports;
+
 /* CMI repository path and workspace.  */
 static char *cmi_repo;
 static size_t cmi_repo_length;
   gcc_assert (global_namespace == current_scope ());
 
   module_state *current = (*modules)[0];
-  if (module_purview_p () || module->loadedness != ML_NONE)
+  if (module_purview_p () || module->loadedness > ML_CONFIG)
     {
       error_at (from_loc, module_purview_p ()
                ? G_("module already declared")
     }
 }
 
+/* Process the pending_import queue, making sure we know the
+   filenames.   */
+
+static void
+name_pending_imports (cpp_reader *reader, bool at_end)
+{
+  auto *mapper = get_mapper (cpp_main_loc (reader));
+
+  bool only_headers = (flag_preprocess_only
+                      && !bool (mapper->get_flags () & Cody::Flags::NameOnly)
+                      && !cpp_get_deps (reader));
+  if (at_end
+      && (!vec_safe_length (pending_imports) || only_headers))
+    /* Not doing anything.  */
+    return;
+
+  timevar_start (TV_MODULE_MAPPER);
+
+  dump.push (NULL);
+  dump () && dump ("Resolving direct import names");
+
+  mapper->Cork ();
+  for (unsigned ix = 0; ix != pending_imports->length (); ix++)
+    {
+      module_state *module = (*pending_imports)[ix];
+      gcc_checking_assert (module->is_direct ());
+      if (!module->filename)
+       {
+         Cody::Flags flags
+           = (flag_preprocess_only ? Cody::Flags::None
+              : Cody::Flags::NameOnly);
+
+         if (only_headers && !module->is_header ())
+           ;
+         else if (module->module_p
+                  && (module->is_partition () || module->exported_p))
+           mapper->ModuleExport (module->get_flatname (), flags);
+         else
+           mapper->ModuleImport (module->get_flatname (), flags);
+       }
+    }
+  
+  auto response = mapper->Uncork ();
+  auto r_iter = response.begin ();
+  for (unsigned ix = 0; ix != pending_imports->length (); ix++)
+    {
+      module_state *module = (*pending_imports)[ix];
+      gcc_checking_assert (module->is_direct ());
+      if (only_headers && !module->is_header ())
+       ;
+      else if (!module->filename)
+       {
+         Cody::Packet const &p = *r_iter;
+         ++r_iter;
+
+         module->set_filename (p);
+       }
+    }
+
+  dump.pop (0);
+
+  timevar_stop (TV_MODULE_MAPPER);
+}
+
 /* We've just lexed a module-specific control line for MODULE.  Mark
    the module as a direct import, and possibly load up its macro
    state.  Returns the primary module, if this is a module
        }
     }
 
+  auto desired = ML_CONFIG;
   if (is_import
-      && !module->is_module () && module->is_header ()
-      && module->loadedness < ML_PREPROCESSOR
+      && module->is_header ()
       && (!cpp_get_options (reader)->preprocessed
          || cpp_get_options (reader)->directives_only))
+    /* We need preprocessor state now.  */
+    desired = ML_PREPROCESSOR;
+
+  if (!is_import || module->loadedness < desired)
     {
-      timevar_start (TV_MODULE_IMPORT);
-      unsigned n = dump.push (module);
+      vec_safe_push (pending_imports, module);
 
-      if (module->loadedness == ML_NONE)
+      if (desired == ML_PREPROCESSOR)
        {
+         name_pending_imports (reader, false);
+
          unsigned pre_hwm = 0;
 
          /* Preserve the state of the line-map.  */
          spans.maybe_init ();
          spans.close ();
 
-         if (!module->filename)
+         timevar_start (TV_MODULE_IMPORT);
+
+         /* Load the config of each pending import -- we must assign
+            module numbers monotonically.  */
+         for (unsigned ix = 0; ix != pending_imports->length (); ix++)
            {
-             auto *mapper = get_mapper (cpp_main_loc (reader));
-             auto packet = mapper->ModuleImport (module->get_flatname ());
-             module->set_filename (packet);
+             auto *import = (*pending_imports)[ix];
+             if (!(import->module_p
+                   && (import->is_partition () || import->exported_p))
+                 && import->loadedness == ML_NONE
+                 && (import->is_header () || !flag_preprocess_only))
+               {
+                 unsigned n = dump.push (import);
+                 import->do_import (reader, true);
+                 dump.pop (n);
+               }
            }
-         module->do_import (reader, true);
+         vec_free (pending_imports);
 
          /* Restore the line-map state.  */
          linemap_module_restore (line_table, pre_hwm);
          spans.open ();
-       }
 
-      if (module->loadedness < ML_PREPROCESSOR)
-       if (module->read_preprocessor (true))
-         module->import_macros ();
+         /* Now read the preprocessor state of this particular
+            import.  */
+         unsigned n = dump.push (module);
+         if (module->read_preprocessor (true))
+           module->import_macros ();
+         dump.pop (n);
 
-      dump.pop (n);
-      timevar_stop (TV_MODULE_IMPORT);
+         timevar_stop (TV_MODULE_IMPORT);
+       }
     }
 
   return is_import ? NULL : get_primary (module);
 void
 preprocessed_module (cpp_reader *reader)
 {
-  auto *mapper = get_mapper (cpp_main_loc (reader));
+  name_pending_imports (reader, true);
+  vec_free (pending_imports);
 
   spans.maybe_init ();
   spans.close ();
 
-  /* Stupid GTY doesn't grok a typedef here.  And using type = is, too
-     modern.  */
-#define iterator hash_table<module_state_hash>::iterator
-  /* using iterator = hash_table<module_state_hash>::iterator;  */
-
-  /* Walk the module hash, asking for the names of all unknown
-     direct imports and informing of an export (if that's what we
-     are).  Notice these are emitted even when preprocessing as they
-     inform the server of dependency edges.  */
-  timevar_start (TV_MODULE_MAPPER);
-
-  dump.push (NULL);
-  dump () && dump ("Resolving direct import names");
-
-  if (!flag_preprocess_only
-      || bool (mapper->get_flags () & Cody::Flags::NameOnly)
-      || cpp_get_deps (reader))
-    {
-      mapper->Cork ();
-      iterator end = modules_hash->end ();
-      for (iterator iter = modules_hash->begin (); iter != end; ++iter)
-       {
-         module_state *module = *iter;
-         if (module->is_direct () && !module->filename)
-           {
-             Cody::Flags flags
-               = (flag_preprocess_only ? Cody::Flags::None
-                  : Cody::Flags::NameOnly);
-
-             if (module->module_p
-                 && (module->is_partition () || module->exported_p))
-               mapper->ModuleExport (module->get_flatname (), flags);
-             else
-               mapper->ModuleImport (module->get_flatname (), flags);
-           }
-       }
-
-      auto response = mapper->Uncork ();
-      auto r_iter = response.begin ();
-      for (iterator iter = modules_hash->begin (); iter != end; ++iter)
-       {
-         module_state *module = *iter;
-
-         if (module->is_direct () && !module->filename)
-           {
-             Cody::Packet const &p = *r_iter;
-             ++r_iter;
-
-             module->set_filename (p);
-           }
-       }
-    }
-
-  dump.pop (0);
-
-  timevar_stop (TV_MODULE_MAPPER);
-
+  using iterator = hash_table<module_state_hash>::iterator;
   if (mkdeps *deps = cpp_get_deps (reader))
     {
       /* Walk the module hash, informing the dependency machinery.  */
 
   if (flag_header_unit && !flag_preprocess_only)
     {
+      /* Find the main module -- remember, it's not yet in the module
+        array.  */
       iterator end = modules_hash->end ();
       for (iterator iter = modules_hash->begin (); iter != end; ++iter)
        {
            }
        }
     }
-#undef iterator
 }
 
 /* VAL is a global tree, add it to the global vec if it is