aboutsummaryrefslogtreecommitdiff
path: root/gcc/go
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/go')
-rw-r--r--gcc/go/ChangeLog5
-rw-r--r--gcc/go/gccgo.texi8
-rw-r--r--gcc/go/go-backend.cc6
-rw-r--r--gcc/go/go-c.h1
-rw-r--r--gcc/go/go-lang.cc14
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/embed.cc11
-rw-r--r--gcc/go/gofrontend/expressions.cc13
-rw-r--r--gcc/go/gofrontend/expressions.h5
-rw-r--r--gcc/go/gofrontend/go.cc2
-rw-r--r--gcc/go/gofrontend/gogo.cc50
-rw-r--r--gcc/go/gofrontend/gogo.h12
-rw-r--r--gcc/go/gofrontend/import.cc124
-rw-r--r--gcc/go/lang.opt4
14 files changed, 238 insertions, 19 deletions
diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog
index 507e2d3..931c3be 100644
--- a/gcc/go/ChangeLog
+++ b/gcc/go/ChangeLog
@@ -1,3 +1,8 @@
+2023-06-22 Paul E. Murphy <murphyp@linux.ibm.com>
+
+ * go-backend.cc [TARGET_AIX]: Rename and update usage to TARGET_AIX_OS.
+ * go-lang.cc: Likewise.
+
2023-03-24 Jakub Jelinek <jakub@redhat.com>
PR middle-end/109258
diff --git a/gcc/go/gccgo.texi b/gcc/go/gccgo.texi
index 4ab1a76..90651af 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-backend.cc b/gcc/go/go-backend.cc
index c6a1a2b..6e2c919 100644
--- a/gcc/go/go-backend.cc
+++ b/gcc/go/go-backend.cc
@@ -45,8 +45,8 @@ along with GCC; see the file COPYING3. If not see
#define GO_EXPORT_SECTION_NAME ".go_export"
#endif
-#ifndef TARGET_AIX
-#define TARGET_AIX 0
+#ifndef TARGET_AIX_OS
+#define TARGET_AIX_OS 0
#endif
/* This file holds all the cases where the Go frontend needs
@@ -107,7 +107,7 @@ go_write_export_data (const char *bytes, unsigned int size)
{
gcc_assert (targetm_common.have_named_sections);
sec = get_section (GO_EXPORT_SECTION_NAME,
- TARGET_AIX ? SECTION_EXCLUDE : SECTION_DEBUG,
+ TARGET_AIX_OS ? SECTION_EXCLUDE : SECTION_DEBUG,
NULL);
}
diff --git a/gcc/go/go-c.h b/gcc/go/go-c.h
index c605038..6a2b57b 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 b6e8c37..e85a4bf 100644
--- a/gcc/go/go-lang.cc
+++ b/gcc/go/go-lang.cc
@@ -39,8 +39,8 @@ along with GCC; see the file COPYING3. If not see
#include "go-c.h"
#include "go-gcc.h"
-#ifndef TARGET_AIX
-#define TARGET_AIX 0
+#ifndef TARGET_AIX_OS
+#define TARGET_AIX_OS 0
#endif
/* Language-dependent contents of a type. */
@@ -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,14 +112,15 @@ 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;
args.debug_escape_level = go_debug_escape_level;
args.debug_escape_hash = go_debug_escape_hash;
- args.nil_check_size_threshold = TARGET_AIX ? -1 : 4096;
+ args.nil_check_size_threshold = TARGET_AIX_OS ? -1 : 4096;
args.debug_optimization = go_debug_optimization;
- args.need_eqtype = TARGET_AIX ? true : false;
+ args.need_eqtype = TARGET_AIX_OS ? true : false;
args.linemap = go_get_linemap();
args.backend = go_get_backend();
go_create_gogo (&args);
@@ -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 dbb2d68..c44cdc2 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-6a1d165c2218cd127ee937a1f45599075762f716
+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 0584f70..6dada5e 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/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 4ac55af..d276bd8 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -12272,7 +12272,8 @@ Call_expression::intrinsify(Gogo* gogo,
return Runtime::make_call(code, loc, 3, a1, a2, a3);
}
}
- else if (package == "internal/abi")
+ else if (package == "internal/abi"
+ || package == "bootstrap/internal/abi") // for bootstrapping gc
{
if (is_method)
return NULL;
@@ -18307,6 +18308,16 @@ Slice_value_expression::do_traverse(Traverse* traverse)
return TRAVERSE_CONTINUE;
}
+// Determine type of a slice value.
+
+void
+Slice_value_expression::do_determine_type(const Type_context*)
+{
+ this->valmem_->determine_type_no_context();
+ this->len_->determine_type_no_context();
+ this->cap_->determine_type_no_context();
+}
+
Expression*
Slice_value_expression::do_copy()
{
diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h
index 3d7e787..bdb7ccd 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -4364,8 +4364,7 @@ class Slice_value_expression : public Expression
{ return this->type_; }
void
- do_determine_type(const Type_context*)
- { }
+ do_determine_type(const Type_context*);
Expression*
do_copy();
@@ -4419,7 +4418,7 @@ class Slice_info_expression : public Expression
void
do_determine_type(const Type_context*)
- { }
+ { this->slice_->determine_type_no_context(); }
Expression*
do_copy()
diff --git a/gcc/go/gofrontend/go.cc b/gcc/go/gofrontend/go.cc
index 1512770..66d4816 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 9197eef..fa3cd6e 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)
{
@@ -3296,6 +3313,9 @@ class Create_function_descriptors : public Traverse
int
expression(Expression**);
+ static bool
+ skip_descriptor(Gogo* gogo, const Named_object*);
+
private:
Gogo* gogo_;
};
@@ -3306,6 +3326,9 @@ class Create_function_descriptors : public Traverse
int
Create_function_descriptors::function(Named_object* no)
{
+ if (Create_function_descriptors::skip_descriptor(this->gogo_, no))
+ return TRAVERSE_CONTINUE;
+
if (no->is_function()
&& no->func_value()->enclosing() == NULL
&& !no->func_value()->is_method()
@@ -3393,6 +3416,28 @@ Create_function_descriptors::expression(Expression** pexpr)
return TRAVERSE_CONTINUE;
}
+// The gc compiler has some special cases that it always compiles as
+// intrinsics. For those we don't want to generate a function
+// descriptor, as there will be no code for it to refer to.
+
+bool
+Create_function_descriptors::skip_descriptor(Gogo* gogo,
+ const Named_object* no)
+{
+ const std::string& pkgpath(no->package() == NULL
+ ? gogo->pkgpath()
+ : no->package()->pkgpath());
+
+ // internal/abi is the standard library package,
+ // bootstrap/internal/abi is the name used when bootstrapping the gc
+ // compiler.
+
+ return ((pkgpath == "internal/abi"
+ || pkgpath == "bootstrap/internal/abi")
+ && (no->name() == "FuncPCABI0"
+ || no->name() == "FuncPCABIInternal"));
+}
+
// Create function descriptors as needed. We need a function
// descriptor for all exported functions and for all functions that
// are referenced without being called.
@@ -3414,7 +3459,8 @@ Gogo::create_function_descriptors()
if (no->is_function_declaration()
&& !no->func_declaration_value()->type()->is_method()
&& !Linemap::is_predeclared_location(no->location())
- && !Gogo::is_hidden_name(no->name()))
+ && !Gogo::is_hidden_name(no->name())
+ && !Create_function_descriptors::skip_descriptor(this, no))
fndecls.push_back(no);
}
for (std::vector<Named_object*>::const_iterator p = fndecls.begin();
diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h
index c08a16b..4fd45bf 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 6a5491b..21691fa 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 4ca989c..0d658fc 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.