public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r14-2108] compiler: support -fgo-importcfg
@ 2023-06-26 16:56 Ian Lance Taylor
  0 siblings, 0 replies; only message in thread
From: Ian Lance Taylor @ 2023-06-26 16:56 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:3a39a31b8ae9c6465434aefa657f7fcc86f905c0

commit r14-2108-g3a39a31b8ae9c6465434aefa657f7fcc86f905c0
Author: Ian Lance Taylor <iant@golang.org>
Date:   Sun Jun 25 20:16:01 2023 -0700

    compiler: support -fgo-importcfg
    
            * lang.opt (fgo-importcfg): New option.
            * go-c.h (struct go_create_gogo_args): Add importcfg field.
            * go-lang.cc (go_importcfg): New static variable.
            (go_langhook_init): Set args.importcfg.
            (go_langhook_handle_option): Handle -fgo-importcfg.
            * gccgo.texi (Invoking gccgo): Document -fgo-importcfg.
    
    Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/506095

Diff:
---
 gcc/go/gccgo.texi           |   8 +++
 gcc/go/go-c.h               |   1 +
 gcc/go/go-lang.cc           |   6 +++
 gcc/go/gofrontend/MERGE     |   2 +-
 gcc/go/gofrontend/embed.cc  |  11 ++--
 gcc/go/gofrontend/go.cc     |   2 +
 gcc/go/gofrontend/gogo.cc   |  19 ++++++-
 gcc/go/gofrontend/gogo.h    |  12 +++++
 gcc/go/gofrontend/import.cc | 124 ++++++++++++++++++++++++++++++++++++++++++++
 gcc/go/lang.opt             |   4 ++
 10 files changed, 182 insertions(+), 7 deletions(-)

diff --git a/gcc/go/gccgo.texi b/gcc/go/gccgo.texi
index 4ab1a76818f..90651af8384 100644
--- a/gcc/go/gccgo.texi
+++ b/gcc/go/gccgo.texi
@@ -271,6 +271,14 @@ pattern to a list of file names, and @code{Files} maps each file name
 to a full path to the file.  This option is intended for use by the
 @command{go} command to implement @code{//go:embed}.
 
+@cindex @option{-fgo-importcfg}
+@item -fgo-importcfg=@var{file}
+Identify a file that provides mappings for import package paths found
+in the Go source files.  The file can contain two commands:
+@code{importpath} to rename import paths for vendoring and
+@code{packagefile} to map from package path to files containing export
+data.  This option is intended for use by the @command{go} command.
+
 @cindex @option{-g for gccgo}
 @item -g
 This is the standard @command{gcc} option (@pxref{Debugging Options, ,
diff --git a/gcc/go/go-c.h b/gcc/go/go-c.h
index c6050382aa8..6a2b57b3b44 100644
--- a/gcc/go/go-c.h
+++ b/gcc/go/go-c.h
@@ -41,6 +41,7 @@ struct go_create_gogo_args
   const char* prefix;
   const char* relative_import_path;
   const char* c_header;
+  const char* importcfg;
   const char* embedcfg;
   Backend* backend;
   Linemap* linemap;
diff --git a/gcc/go/go-lang.cc b/gcc/go/go-lang.cc
index c6c147b20a5..e85a4bfe949 100644
--- a/gcc/go/go-lang.cc
+++ b/gcc/go/go-lang.cc
@@ -90,6 +90,7 @@ static const char *go_prefix = NULL;
 static const char *go_relative_import_path = NULL;
 static const char *go_c_header = NULL;
 static const char *go_embedcfg = NULL;
+static const char *go_importcfg = NULL;
 
 /* Language hooks.  */
 
@@ -111,6 +112,7 @@ go_langhook_init (void)
   args.relative_import_path = go_relative_import_path;
   args.c_header = go_c_header;
   args.embedcfg = go_embedcfg;
+  args.importcfg = go_importcfg;
   args.check_divide_by_zero = go_check_divide_zero;
   args.check_divide_overflow = go_check_divide_overflow;
   args.compiling_runtime = go_compiling_runtime;
@@ -286,6 +288,10 @@ go_langhook_handle_option (
       go_embedcfg = arg;
       break;
 
+    case OPT_fgo_importcfg_:
+      go_importcfg = arg;
+      break;
+
     default:
       /* Just return 1 to indicate that the option is valid.  */
       break;
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index ff07b1a1fa6..c44cdc2baac 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-68a756b6aadc901534cfddddad2b1e73fae9e34f
+92152c88ea8e2dd9e8c67e91bf4ae5e3edf1b506
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
diff --git a/gcc/go/gofrontend/embed.cc b/gcc/go/gofrontend/embed.cc
index 0584f707ce6..6dada5efc2a 100644
--- a/gcc/go/gofrontend/embed.cc
+++ b/gcc/go/gofrontend/embed.cc
@@ -19,8 +19,8 @@
 
 // Read a file into *DATA.  Returns false on error.
 
-static bool
-read_file(const char* filename, Location loc, std::string* data)
+bool
+Gogo::read_file(const char* filename, Location loc, std::string* data)
 {
   int fd = open(filename, O_RDONLY | O_BINARY);
   if (fd < 0)
@@ -346,7 +346,8 @@ Gogo::read_embedcfg(const char *filename)
 bool
 Embedcfg_reader::initialize_from_file()
 {
-  if (!read_file(this->filename_, Linemap::unknown_location(), &this->data_))
+  if (!Gogo::read_file(this->filename_, Linemap::unknown_location(),
+		       &this->data_))
     return false;
   if (this->data_.empty())
     {
@@ -849,7 +850,7 @@ Gogo::initializer_for_embeds(Type* type,
 	}
 
       std::string data;
-      if (!read_file(this->embed_files_[paths[0]].c_str(), loc, &data))
+      if (!Gogo::read_file(this->embed_files_[paths[0]].c_str(), loc, &data))
 	return Expression::make_error(loc);
 
       Expression* e = Expression::make_string(data, loc);
@@ -909,7 +910,7 @@ Gogo::initializer_for_embeds(Type* type,
       std::string data;
       if ((*pp)[pp->size() - 1] != '/')
 	{
-	  if (!read_file(this->embed_files_[*pp].c_str(), loc, &data))
+	  if (!Gogo::read_file(this->embed_files_[*pp].c_str(), loc, &data))
 	    return Expression::make_error(loc);
 	}
 
diff --git a/gcc/go/gofrontend/go.cc b/gcc/go/gofrontend/go.cc
index 1512770af29..66d481681f3 100644
--- a/gcc/go/gofrontend/go.cc
+++ b/gcc/go/gofrontend/go.cc
@@ -40,6 +40,8 @@ go_create_gogo(const struct go_create_gogo_args* args)
     ::gogo->set_compiling_runtime(args->compiling_runtime);
   if (args->c_header != NULL)
     ::gogo->set_c_header(args->c_header);
+  if (args->importcfg != NULL)
+    ::gogo->read_importcfg(args->importcfg);
   if (args->embedcfg != NULL)
     ::gogo->read_embedcfg(args->embedcfg);
   ::gogo->set_debug_escape_level(args->debug_escape_level);
diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc
index 980db1ea07e..fa3cd6ebe9f 100644
--- a/gcc/go/gofrontend/gogo.cc
+++ b/gcc/go/gofrontend/gogo.cc
@@ -52,6 +52,10 @@ Gogo::Gogo(Backend* backend, Linemap* linemap, int, int pointer_size)
     prefix_from_option_(false),
     relative_import_path_(),
     c_header_(),
+    import_map_(),
+    package_file_(),
+    embed_patterns_(),
+    embed_files_(),
     check_divide_by_zero_(true),
     check_divide_overflow_(true),
     compiling_runtime_(false),
@@ -517,7 +521,20 @@ Gogo::import_package(const std::string& filename,
       return;
     }
 
-  Import::Stream* stream = Import::open_package(filename, location,
+  // If we are using an importcfg file we have to check two mappings.
+  // IMPORT_MAP_ is a mapping from package path to real package path,
+  // for vendoring.  PACKAGE_FILE_ is a mapping from package path to
+  // file name, to find the file in the build cache.
+  std::string path = filename;
+  Unordered_map(std::string, std::string)::const_iterator pi;
+  pi = this->import_map_.find(filename);
+  if (pi != this->import_map_.end())
+    path = pi->second;
+  pi = this->package_file_.find(path);
+  if (pi != this->package_file_.end())
+    path = pi->second;
+
+  Import::Stream* stream = Import::open_package(path, location,
 						this->relative_import_path_);
   if (stream == NULL)
     {
diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h
index c08a16b74c2..4fd45bfa040 100644
--- a/gcc/go/gofrontend/gogo.h
+++ b/gcc/go/gofrontend/gogo.h
@@ -393,6 +393,10 @@ class Gogo
   set_c_header(const std::string& s)
   { this->c_header_ = s; }
 
+  // Read an importcfg file.
+  void
+  read_importcfg(const char* filename);
+
   // Read an embedcfg file.
   void
   read_embedcfg(const char* filename);
@@ -1126,6 +1130,10 @@ class Gogo
   static size_t
   special_name_pos(const std::string& name);
 
+  // Read a file into memory.
+  static bool
+  read_file(const char* filename, Location loc, std::string* data);
+
  private:
   // During parsing, we keep a stack of functions.  Each function on
   // the stack is one that we are currently parsing.  For each
@@ -1295,6 +1303,10 @@ class Gogo
   std::string relative_import_path_;
   // The C header file to write, from the -fgo-c-header option.
   std::string c_header_;
+  // Mapping from imports in the source file to the real import paths.
+  Unordered_map(std::string, std::string) import_map_;
+  // Mapping from import paths to files to read.
+  Unordered_map(std::string, std::string) package_file_;
   // Patterns from an embedcfg file.
   Embed_patterns embed_patterns_;
   // Mapping from file to full path from an embedcfg file.
diff --git a/gcc/go/gofrontend/import.cc b/gcc/go/gofrontend/import.cc
index 6a5491be949..21691fa5ff4 100644
--- a/gcc/go/gofrontend/import.cc
+++ b/gcc/go/gofrontend/import.cc
@@ -34,6 +34,130 @@ go_add_search_path(const char* path)
   search_path.push_back(std::string(path));
 }
 
+// Read an importcfg file.
+
+void
+Gogo::read_importcfg(const char* filename)
+{
+  std::string data;
+  if (!Gogo::read_file(filename, Linemap::unknown_location(), &data))
+    return;
+  const char* p = data.data();
+  const char* pend = p + data.length();
+  int lineno = 0;
+  const char *pnext = NULL;
+  for (; p < pend; p = pnext)
+    {
+      // Line numbers start at 1.
+      lineno++;
+
+      // Find end of line.
+      const char* pnl = static_cast<const char*>(memchr(p, '\n', pend - p));
+      if (pnl != NULL)
+	pnext = pnl + 1;
+      else
+	{
+	  pnl = pend;
+	  pnext = pnl;
+	}
+
+      // Trim leading spaces.
+      while (p < pnl)
+	{
+	  unsigned int rune;
+	  int rune_len = Lex::fetch_char(p, &rune);
+	  if (rune_len == 0)
+	    {
+	      go_error_at(Linemap::unknown_location(),
+			  "%s:%d: invalid character in importcfg file",
+			  filename, lineno);
+	      return;
+	    }
+	  if (!Lex::is_unicode_space(rune))
+	    break;
+	  p += rune_len;
+	}
+
+      // Trim trailing spaces.
+      while (pnl > p)
+	{
+	  size_t start = pnl - p - 1;
+	  unsigned int rune = (unsigned char)p[start];
+	  int rune_len = 1;
+	  if (rune > 0x7f)
+	    {
+	      for (start--; start > 0; start--)
+		{
+		  unsigned char c = p[start];
+		  if ((c & 0xc0) != 0x80)
+		    break;
+		}
+	      rune_len = Lex::fetch_char(p + start, &rune);
+	      if (static_cast<size_t>(rune_len) != (pnl - p) - start)
+		{
+		  go_error_at(Linemap::unknown_location(),
+			      "%s:%d: invalid character in importcfg file",
+			      filename, lineno);
+		  return;
+		}
+	    }
+	  if (!Lex::is_unicode_space(rune))
+	    break;
+	  pnl -= rune_len;
+	}
+
+      // Skip empty lines and comment lines.
+      if (p == pnl || *p == '#')
+	continue;
+
+      size_t verb_len;
+      const char* psp = static_cast<const char*>(memchr(p, ' ', pnl - p));
+      if (psp == NULL)
+	verb_len = pnl - p;
+      else
+	verb_len = psp - p;
+
+      bool importmap = false;
+      bool packagefile = false;
+      if (strncmp(p, "importmap", verb_len) == 0)
+	importmap = true;
+      else if (strncmp(p, "packagefile", verb_len) == 0)
+	packagefile = true;
+      else
+	{
+	  go_error_at(Linemap::unknown_location(),
+		      "%s:%d: unknown directive in importcfg file",
+		      filename, lineno);
+	  return;
+	}
+
+      const char* peq;
+      if (psp == NULL)
+	peq = NULL;
+      else
+	{
+	  psp++;
+	  peq = static_cast<const char*>(memchr(psp, '=', pnl - psp));
+	}
+      if (peq == NULL || peq + 1 == pnl)
+	{
+	  go_error_at(Linemap::unknown_location(),
+		      "%s:%d: invalid syntax in importcfg file",
+		      filename, lineno);
+	  return;
+	}
+
+      std::string first(psp, peq - psp);
+      std::string second(peq + 1, pnl - (peq + 1));
+      if (importmap)
+	this->import_map_[first] = second;
+      else if (packagefile)
+	this->package_file_[first] = second;
+      else
+	go_unreachable();
+    }
+}
+
 // Find import data.  This searches the file system for FILENAME and
 // returns a pointer to a Stream object to read the data that it
 // exports.  If the file is not found, it returns NULL.
diff --git a/gcc/go/lang.opt b/gcc/go/lang.opt
index 4ca989c62e0..0d658fcbfbf 100644
--- a/gcc/go/lang.opt
+++ b/gcc/go/lang.opt
@@ -61,6 +61,10 @@ fgo-embedcfg=
 Go Joined RejectNegative
 -fgo-embedcfg=<file>	List embedded files via go:embed.
 
+fgo-importcfg=
+Go Joined RejectNegative
+-fgo-importcfg=<file>	Provide file that tells where to find imports.
+
 fgo-optimize-
 Go Joined
 -fgo-optimize-<type>	Turn on optimization passes in the frontend.

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-06-26 16:56 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-26 16:56 [gcc r14-2108] compiler: support -fgo-importcfg Ian Lance Taylor

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).