aboutsummaryrefslogtreecommitdiff
path: root/gcc/go
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2022-02-11 15:02:44 -0800
committerIan Lance Taylor <iant@golang.org>2022-02-11 15:02:44 -0800
commit9a510fb0970d3d9a4201bce8965cabe67850386b (patch)
tree43d7fd2bbfd7ad8c9625a718a5e8718889351994 /gcc/go
parenta6d3012b274f38b20e2a57162106f625746af6c6 (diff)
parent8dc2499aa62f768c6395c9754b8cabc1ce25c494 (diff)
downloadgcc-9a510fb0970d3d9a4201bce8965cabe67850386b.zip
gcc-9a510fb0970d3d9a4201bce8965cabe67850386b.tar.gz
gcc-9a510fb0970d3d9a4201bce8965cabe67850386b.tar.bz2
Merge from trunk revision 8dc2499aa62f768c6395c9754b8cabc1ce25c494
Diffstat (limited to 'gcc/go')
-rw-r--r--gcc/go/ChangeLog43
-rw-r--r--gcc/go/Make-lang.in6
-rw-r--r--gcc/go/config-lang.in4
-rw-r--r--gcc/go/gccgo.texi6
-rw-r--r--gcc/go/go-backend.cc (renamed from gcc/go/go-backend.c)4
-rw-r--r--gcc/go/go-c.h2
-rw-r--r--gcc/go/go-gcc-diagnostics.cc2
-rw-r--r--gcc/go/go-gcc.cc16
-rw-r--r--gcc/go/go-gcc.h2
-rw-r--r--gcc/go/go-lang.cc (renamed from gcc/go/go-lang.c)4
-rw-r--r--gcc/go/go-sha1.cc2
-rw-r--r--gcc/go/go-system.h2
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/expressions.cc280
-rw-r--r--gcc/go/gofrontend/expressions.h8
-rw-r--r--gcc/go/gofrontend/gogo.cc266
-rw-r--r--gcc/go/gofrontend/gogo.h4
-rw-r--r--gcc/go/gofrontend/runtime.def4
-rw-r--r--gcc/go/gofrontend/types.cc43
-rw-r--r--gcc/go/gofrontend/types.h5
-rw-r--r--gcc/go/gospec.cc (renamed from gcc/go/gospec.c)46
-rw-r--r--gcc/go/lang-specs.h4
-rw-r--r--gcc/go/lang.opt2
23 files changed, 541 insertions, 216 deletions
diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog
index c17e3a4..dd94ab3 100644
--- a/gcc/go/ChangeLog
+++ b/gcc/go/ChangeLog
@@ -1,3 +1,44 @@
+2022-02-09 Ian Lance Taylor <iant@golang.org>
+
+ * gospec.cc (RTLIB, RT_LIBRARY): Define.
+ (lang_specific_driver): Add -lrt if linking statically on
+ GNU/Linux.
+
+2022-02-09 Ian Lance Taylor <iant@golang.org>
+
+ * go-gcc.cc (Gcc_backend::Gcc_backend): Define builtins
+ __atomic_load_1 and __atomic_store_1.
+
+2022-01-17 Martin Liska <mliska@suse.cz>
+
+ * config-lang.in: Rename .c names to .cc.
+ * go-backend.cc: Likewise.
+ * go-lang.cc: Likewise.
+ * gospec.cc: Likewise.
+ * lang-specs.h: Likewise.
+
+2022-01-17 Martin Liska <mliska@suse.cz>
+
+ * go-backend.c: Moved to...
+ * go-backend.cc: ...here.
+ * go-lang.c: Moved to...
+ * go-lang.cc: ...here.
+ * gospec.c: Moved to...
+ * gospec.cc: ...here.
+
+2022-01-03 Jakub Jelinek <jakub@redhat.com>
+
+ * gccgo.texi: Bump @copyrights-go year.
+
+2021-12-28 Martin Liska <mliska@suse.cz>
+
+ * gccgo.texi: Replace http:// with https.
+
+2021-11-29 Eric Gallager <egallager@gcc.gnu.org>
+
+ PR other/103021
+ * Make-lang.in: Use ETAGS variable in TAGS target.
+
2021-09-27 Martin Liska <mliska@suse.cz>
* go-lang.c (go_langhook_init_options_struct): Set also
@@ -1792,7 +1833,7 @@
Go frontend added to gcc repository.
-Copyright (C) 2010-2021 Free Software Foundation, Inc.
+Copyright (C) 2010-2022 Free Software Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
diff --git a/gcc/go/Make-lang.in b/gcc/go/Make-lang.in
index 4bdc8f6..31c6773 100644
--- a/gcc/go/Make-lang.in
+++ b/gcc/go/Make-lang.in
@@ -1,6 +1,6 @@
# Make-lang.in -- Top level -*- makefile -*- fragment for gcc Go frontend.
-# Copyright (C) 2009-2021 Free Software Foundation, Inc.
+# Copyright (C) 2009-2022 Free Software Foundation, Inc.
# This file is part of GCC.
@@ -133,8 +133,8 @@ go.srcinfo: doc/gccgo.info
go.srcextra:
go.tags: force
cd $(srcdir)/go; \
- etags -o TAGS.sub *.c *.h gofrontend/*.h gofrontend/*.cc; \
- etags --include TAGS.sub --include ../TAGS.sub
+ $(ETAGS) -o TAGS.sub *.c *.h gofrontend/*.h gofrontend/*.cc; \
+ $(ETAGS) --include TAGS.sub --include ../TAGS.sub
go.man: doc/gccgo.1
go.srcman: doc/gccgo.1
-cp -p $^ $(srcdir)/doc
diff --git a/gcc/go/config-lang.in b/gcc/go/config-lang.in
index 18fcaba..19fdbc3 100644
--- a/gcc/go/config-lang.in
+++ b/gcc/go/config-lang.in
@@ -1,6 +1,6 @@
# config-lang.in -- Top level configure fragment for gcc Go frontend.
-# Copyright (C) 2009-2021 Free Software Foundation, Inc.
+# Copyright (C) 2009-2022 Free Software Foundation, Inc.
# This file is part of GCC.
@@ -31,7 +31,7 @@ compilers="go1\$(exeext)"
target_libs="target-libgo target-libffi target-libbacktrace"
lang_dirs="gotools"
-gtfiles="\$(srcdir)/go/go-lang.c \$(srcdir)/go/go-c.h"
+gtfiles="\$(srcdir)/go/go-lang.cc \$(srcdir)/go/go-c.h"
# Do not build by default.
build_by_default="no"
diff --git a/gcc/go/gccgo.texi b/gcc/go/gccgo.texi
index fa0e488..66020aa7 100644
--- a/gcc/go/gccgo.texi
+++ b/gcc/go/gccgo.texi
@@ -12,7 +12,7 @@
@include gcc-common.texi
@c Copyright years for this manual.
-@set copyrights-go 2010-2021
+@set copyrights-go 2010-2022
@copying
@c man begin COPYRIGHT
@@ -80,7 +80,7 @@ This manual describes how to use @command{gccgo}, the GNU compiler for
the Go programming language. This manual is specifically about
@command{gccgo}. For more information about the Go programming
language in general, including language specifications and standard
-package documentation, see @uref{http://golang.org/}.
+package documentation, see @uref{https://golang.org/}.
@menu
* Copying:: The GNU General Public License.
@@ -382,7 +382,7 @@ or with C++ code compiled using @code{extern "C"}.
This information is provided largely for documentation purposes. For
ordinary use it is best to build programs with the go tool and then
use @code{import "C"}, as described at
-@url{http://golang.org/cmd/cgo}.
+@url{https://golang.org/cmd/cgo}.
@menu
* C Type Interoperability:: How C and Go types match up.
diff --git a/gcc/go/go-backend.c b/gcc/go/go-backend.cc
index 7a223e5..7eed943 100644
--- a/gcc/go/go-backend.c
+++ b/gcc/go/go-backend.cc
@@ -1,5 +1,5 @@
-/* go-backend.c -- Go frontend interface to gcc backend.
- Copyright (C) 2010-2021 Free Software Foundation, Inc.
+/* go-backend.cc -- Go frontend interface to gcc backend.
+ Copyright (C) 2010-2022 Free Software Foundation, Inc.
This file is part of GCC.
diff --git a/gcc/go/go-c.h b/gcc/go/go-c.h
index 5930ead..d2de9e7 100644
--- a/gcc/go/go-c.h
+++ b/gcc/go/go-c.h
@@ -1,5 +1,5 @@
/* go-c.h -- Header file for go frontend gcc C interface.
- Copyright (C) 2009-2021 Free Software Foundation, Inc.
+ Copyright (C) 2009-2022 Free Software Foundation, Inc.
This file is part of GCC.
diff --git a/gcc/go/go-gcc-diagnostics.cc b/gcc/go/go-gcc-diagnostics.cc
index 1a678ed..23c3c07 100644
--- a/gcc/go/go-gcc-diagnostics.cc
+++ b/gcc/go/go-gcc-diagnostics.cc
@@ -1,5 +1,5 @@
// go-gcc-diagnostics.cc -- GCC implementation of go diagnostics interface.
-// Copyright (C) 2016-2021 Free Software Foundation, Inc.
+// Copyright (C) 2016-2022 Free Software Foundation, Inc.
// Contributed by Than McIntosh, Google.
// This file is part of GCC.
diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc
index f812796..f3de7a8 100644
--- a/gcc/go/go-gcc.cc
+++ b/gcc/go/go-gcc.cc
@@ -1,5 +1,5 @@
// go-gcc.cc -- Go frontend to gcc IR.
-// Copyright (C) 2011-2021 Free Software Foundation, Inc.
+// Copyright (C) 2011-2022 Free Software Foundation, Inc.
// Contributed by Ian Lance Taylor, Google.
// This file is part of GCC.
@@ -898,6 +898,20 @@ Gcc_backend::Gcc_backend()
t, 0);
t = build_function_type_list(unsigned_char_type_node,
+ ptr_type_node,
+ integer_type_node,
+ NULL_TREE);
+ this->define_builtin(BUILT_IN_ATOMIC_LOAD_1, "__atomic_load_1", NULL, t, 0);
+
+ t = build_function_type_list(void_type_node,
+ ptr_type_node,
+ unsigned_char_type_node,
+ integer_type_node,
+ NULL_TREE);
+ this->define_builtin(BUILT_IN_ATOMIC_STORE_1, "__atomic_store_1", NULL,
+ t, 0);
+
+ t = build_function_type_list(unsigned_char_type_node,
ptr_type_node,
unsigned_char_type_node,
integer_type_node,
diff --git a/gcc/go/go-gcc.h b/gcc/go/go-gcc.h
index bff4307..86f027d 100644
--- a/gcc/go/go-gcc.h
+++ b/gcc/go/go-gcc.h
@@ -1,5 +1,5 @@
/* go-gcc.h -- Header file for go backend-specific interfaces.
- Copyright (C) 2016-2021 Free Software Foundation, Inc.
+ Copyright (C) 2016-2022 Free Software Foundation, Inc.
This file is part of GCC.
diff --git a/gcc/go/go-lang.c b/gcc/go/go-lang.cc
index c3ae6f0..c8365d2 100644
--- a/gcc/go/go-lang.c
+++ b/gcc/go/go-lang.cc
@@ -1,5 +1,5 @@
-/* go-lang.c -- Go frontend gcc interface.
- Copyright (C) 2009-2021 Free Software Foundation, Inc.
+/* go-lang.cc -- Go frontend gcc interface.
+ Copyright (C) 2009-2022 Free Software Foundation, Inc.
This file is part of GCC.
diff --git a/gcc/go/go-sha1.cc b/gcc/go/go-sha1.cc
index 1d6f7de..ab74414 100644
--- a/gcc/go/go-sha1.cc
+++ b/gcc/go/go-sha1.cc
@@ -1,5 +1,5 @@
/* go-sha1.cc -- Go frontend interface to gcc backend.
- Copyright (C) 2016-2021 Free Software Foundation, Inc.
+ Copyright (C) 2016-2022 Free Software Foundation, Inc.
This file is part of GCC.
diff --git a/gcc/go/go-system.h b/gcc/go/go-system.h
index 9b0d18f..7ea1057 100644
--- a/gcc/go/go-system.h
+++ b/gcc/go/go-system.h
@@ -1,5 +1,5 @@
// go-system.h -- Go frontend inclusion of gcc header files -*- C++ -*-
-// Copyright (C) 2009-2021 Free Software Foundation, Inc.
+// Copyright (C) 2009-2022 Free Software Foundation, Inc.
// This file is part of GCC.
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index e7ff670..4e6bac7 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-128ea3dce9b8753167f33d0a96bd093a6cbd58b8
+47380f733ca932384e59492d2f04374edd8ec95e
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/expressions.cc b/gcc/go/gofrontend/expressions.cc
index ddb1d91..1b3b3bf 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -2123,9 +2123,15 @@ String_expression::do_get_backend(Translate_context* context)
Location loc = this->location();
std::vector<Bexpression*> init(2);
- Bexpression* str_cst =
- gogo->backend()->string_constant_expression(this->val_);
- init[0] = gogo->backend()->address_expression(str_cst, loc);
+
+ if (this->val_.size() == 0)
+ init[0] = gogo->backend()->nil_pointer_expression();
+ else
+ {
+ Bexpression* str_cst =
+ gogo->backend()->string_constant_expression(this->val_);
+ init[0] = gogo->backend()->address_expression(str_cst, loc);
+ }
Btype* int_btype = Type::lookup_integer_type("int")->get_backend(gogo);
mpz_t lenval;
@@ -7981,7 +7987,7 @@ Bound_method_expression::do_check_types(Gogo*)
Bound_method_expression::Method_value_thunks
Bound_method_expression::method_value_thunks;
-// Find or create the thunk for METHOD.
+// Find or create the thunk for FN.
Named_object*
Bound_method_expression::create_thunk(Gogo* gogo, const Method* method,
@@ -8078,14 +8084,28 @@ Bound_method_expression::create_thunk(Gogo* gogo, const Method* method,
gogo->add_statement(s);
Block* b = gogo->finish_block(loc);
gogo->add_block(b, loc);
+
+ // This is called after lowering but before determine_types.
gogo->lower_block(new_no, b);
- gogo->flatten_block(new_no, b);
+
gogo->finish_function(loc);
ins.first->second = new_no;
return new_no;
}
+// Look up a thunk for FN.
+
+Named_object*
+Bound_method_expression::lookup_thunk(Named_object* fn)
+{
+ Method_value_thunks::const_iterator p =
+ Bound_method_expression::method_value_thunks.find(fn);
+ if (p == Bound_method_expression::method_value_thunks.end())
+ return NULL;
+ return p->second;
+}
+
// Return an expression to check *REF for nil while dereferencing
// according to FIELD_INDEXES. Update *REF to build up the field
// reference. This is a static function so that we don't have to
@@ -8129,10 +8149,11 @@ Bound_method_expression::do_flatten(Gogo* gogo, Named_object*,
{
Location loc = this->location();
- Named_object* thunk = Bound_method_expression::create_thunk(gogo,
- this->method_,
- this->function_);
- if (thunk->is_erroneous())
+ Named_object* thunk = Bound_method_expression::lookup_thunk(this->function_);
+
+ // The thunk should have been created during the
+ // create_function_descriptors pass.
+ if (thunk == NULL || thunk->is_erroneous())
{
go_assert(saw_errors());
return Expression::make_error(loc);
@@ -10311,16 +10332,7 @@ Builtin_call_expression::do_check_types(Gogo*)
case BUILTIN_PRINTLN:
{
const Expression_list* args = this->args();
- if (args == NULL)
- {
- if (this->code_ == BUILTIN_PRINT)
- go_warning_at(this->location(), 0,
- "no arguments for built-in function %<%s%>",
- (this->code_ == BUILTIN_PRINT
- ? "print"
- : "println"));
- }
- else
+ if (args != NULL)
{
for (Expression_list::const_iterator p = args->begin();
p != args->end();
@@ -11598,12 +11610,16 @@ Call_expression::intrinsify(Gogo* gogo,
std::string package = (no->package() != NULL
? no->package()->pkgpath()
: gogo->pkgpath());
+ bool is_method = ((no->is_function() && no->func_value()->is_method())
+ || (no->is_function_declaration()
+ && no->func_declaration_value()->is_method()));
Location loc = this->location();
Type* int_type = Type::lookup_integer_type("int");
Type* int32_type = Type::lookup_integer_type("int32");
Type* int64_type = Type::lookup_integer_type("int64");
Type* uint_type = Type::lookup_integer_type("uint");
+ Type* uint8_type = Type::lookup_integer_type("uint8");
Type* uint32_type = Type::lookup_integer_type("uint32");
Type* uint64_type = Type::lookup_integer_type("uint64");
Type* uintptr_type = Type::lookup_integer_type("uintptr");
@@ -11614,6 +11630,9 @@ Call_expression::intrinsify(Gogo* gogo,
if (package == "sync/atomic")
{
+ if (is_method)
+ return NULL;
+
// sync/atomic functions and runtime/internal/atomic functions
// are very similar. In order not to duplicate code, we just
// redirect to the latter and let the code below to handle them.
@@ -11679,6 +11698,9 @@ Call_expression::intrinsify(Gogo* gogo,
if (package == "runtime/internal/sys")
{
+ if (is_method)
+ return NULL;
+
// runtime/internal/sys functions and math/bits functions
// are very similar. In order not to duplicate code, we just
// redirect to the latter and let the code below to handle them.
@@ -11698,6 +11720,9 @@ Call_expression::intrinsify(Gogo* gogo,
if (package == "runtime")
{
+ if (is_method)
+ return NULL;
+
// Handle a couple of special runtime functions. In the runtime
// package, getcallerpc returns the PC of the caller, and
// getcallersp returns the frame pointer of the caller. Implement
@@ -11728,6 +11753,9 @@ Call_expression::intrinsify(Gogo* gogo,
}
else if (package == "math/bits")
{
+ if (is_method)
+ return NULL;
+
if ((name == "ReverseBytes16" || name == "ReverseBytes32"
|| name == "ReverseBytes64" || name == "ReverseBytes")
&& this->args_ != NULL && this->args_->size() == 1)
@@ -11898,9 +11926,137 @@ Call_expression::intrinsify(Gogo* gogo,
{
int memorder = __ATOMIC_SEQ_CST;
+ if (is_method)
+ {
+ Function_type* ftype = (no->is_function()
+ ? no->func_value()->type()
+ : no->func_declaration_value()->type());
+ Type* rtype = ftype->receiver()->type()->deref();
+ go_assert(rtype->named_type() != NULL);
+ const std::string& rname(rtype->named_type()->name());
+ if (rname == "Int32")
+ {
+ if (name == "Load")
+ name = "LoadInt32";
+ else if (name == "Store")
+ name = "Storeint32";
+ else if (name == "CompareAndSwap")
+ name = "Casint32";
+ else if (name == "Swap")
+ name = "Xchgint32";
+ else if (name == "Add")
+ name = "Xaddint32";
+ else
+ go_unreachable();
+ }
+ else if (rname == "Int64")
+ {
+ if (name == "Load")
+ name = "LoadInt64";
+ else if (name == "Store")
+ name = "Storeint64";
+ else if (name == "CompareAndSwap")
+ name = "Casint64";
+ else if (name == "Swap")
+ name = "Xchgint64";
+ else if (name == "Add")
+ name = "Xaddint64";
+ else
+ go_unreachable();
+ }
+ else if (rname == "Uint8")
+ {
+ if (name == "Load")
+ name = "Load8";
+ else if (name == "Store")
+ name = "Store8";
+ else if (name == "And")
+ name = "And8";
+ else if (name == "Or")
+ name = "Or8";
+ else
+ go_unreachable();
+ }
+ else if (rname == "Uint32")
+ {
+ if (name == "Load")
+ name = "Load";
+ else if (name == "LoadAcquire")
+ name = "LoadAcq";
+ else if (name == "Store")
+ name = "Store";
+ else if (name == "CompareAndSwap")
+ name = "Cas";
+ else if (name == "CompareAndSwapRelease")
+ name = "CasRel";
+ else if (name == "Swap")
+ name = "Xchg";
+ else if (name == "And")
+ name = "And";
+ else if (name == "Or")
+ name = "Or";
+ else if (name == "Add")
+ name = "Xadd";
+ else
+ go_unreachable();
+ }
+ else if (rname == "Uint64")
+ {
+ if (name == "Load")
+ name = "Load64";
+ else if (name == "Store")
+ name = "Store64";
+ else if (name == "CompareAndSwap")
+ name = "Cas64";
+ else if (name == "Swap")
+ name = "Xchgt64";
+ else if (name == "Add")
+ name = "Xadd64";
+ else
+ go_unreachable();
+ }
+ else if (rname == "Uintptr")
+ {
+ if (name == "Load")
+ name = "Loaduintptr";
+ else if (name == "LoadAcquire")
+ name = "Loadacquintptr";
+ else if (name == "Store")
+ name = "Storeuintptr";
+ else if (name == "StoreRelease")
+ name = "StoreReluintptr";
+ else if (name == "CompareAndSwap")
+ name = "Casuintptr";
+ else if (name == "Swap")
+ name = "Xchguintptr";
+ else if (name == "Add")
+ name = "Xadduintptr";
+ else
+ go_unreachable();
+ }
+ else if (rname == "Float64")
+ {
+ // Needs unsafe type conversion. Don't intrinsify for now.
+ return NULL;
+ }
+ else if (rname == "UnsafePointer")
+ {
+ if (name == "Load")
+ name = "Loadp";
+ else if (name == "StoreNoWB")
+ name = "StorepoWB";
+ else if (name == "CompareAndSwapNoWB")
+ name = "Casp1";
+ else
+ go_unreachable();
+ }
+ else
+ go_unreachable();
+ }
+
if ((name == "Load" || name == "Load64" || name == "Loadint64" || name == "Loadp"
|| name == "Loaduint" || name == "Loaduintptr" || name == "LoadAcq"
- || name == "Loadint32")
+ || name == "Loadint32" || name == "Load8")
&& this->args_ != NULL && this->args_->size() == 1)
{
if (int_size < 8 && (name == "Load64" || name == "Loadint64"))
@@ -11957,6 +12113,11 @@ Call_expression::intrinsify(Gogo* gogo,
res_type = uint32_type;
memorder = __ATOMIC_ACQUIRE;
}
+ else if (name == "Load8")
+ {
+ code = Runtime::ATOMIC_LOAD_1;
+ res_type = uint8_type;
+ }
else
go_unreachable();
Expression* a1 = this->args_->front();
@@ -11997,6 +12158,8 @@ Call_expression::intrinsify(Gogo* gogo,
code = Runtime::ATOMIC_STORE_4;
memorder = __ATOMIC_RELEASE;
}
+ else if (name == "Store8")
+ code = Runtime::ATOMIC_STORE_1;
else
go_unreachable();
Expression* a3 = Expression::make_integer_ul(memorder, int32_type, loc);
@@ -12162,6 +12325,53 @@ Call_expression::intrinsify(Gogo* gogo,
return Runtime::make_call(code, loc, 3, a1, a2, a3);
}
}
+ else if (package == "internal/abi")
+ {
+ if (is_method)
+ return NULL;
+
+ if ((name == "FuncPCABI0" || name == "FuncPCABIInternal")
+ && this->args_ != NULL
+ && this->args_->size() == 1)
+ {
+ // We expect to see a conversion from the expression to "any".
+ Expression* expr = this->args_->front();
+ Type_conversion_expression* tce = expr->conversion_expression();
+ if (tce != NULL)
+ expr = tce->expr();
+ Func_expression* fe = expr->func_expression();
+ Interface_field_reference_expression* interface_method =
+ expr->interface_field_reference_expression();
+ if (fe != NULL)
+ {
+ Named_object* no = fe->named_object();
+ Expression* ref = Expression::make_func_code_reference(no, loc);
+ Type* uintptr_type = Type::lookup_integer_type("uintptr");
+ return Expression::make_cast(uintptr_type, ref, loc);
+ }
+ else if (interface_method != NULL)
+ return interface_method->get_function();
+ else
+ {
+ expr = this->args_->front();
+ go_assert(expr->type()->interface_type() != NULL
+ && expr->type()->interface_type()->is_empty());
+ expr = Expression::make_interface_info(expr,
+ INTERFACE_INFO_OBJECT,
+ loc);
+ // Trust that this is a function type, which means that
+ // it is a direct iface type and we can use EXPR
+ // directly. The backend representation of this
+ // function is a pointer to a struct whose first field
+ // is the actual function to call.
+ Type* pvoid = Type::make_pointer_type(Type::make_void_type());
+ Type* pfntype = Type::make_pointer_type(pvoid);
+ Expression* ref = make_unsafe_cast(pfntype, expr, loc);
+ return Expression::make_dereference(ref, NIL_CHECK_NOT_NEEDED,
+ loc);
+ }
+ }
+ }
return NULL;
}
@@ -14757,14 +14967,34 @@ Interface_field_reference_expression::create_thunk(Gogo* gogo,
gogo->add_statement(s);
Block* b = gogo->finish_block(loc);
gogo->add_block(b, loc);
+
+ // This is called after lowering but before determine_types.
gogo->lower_block(new_no, b);
- gogo->flatten_block(new_no, b);
+
gogo->finish_function(loc);
ins.first->second->push_back(std::make_pair(name, new_no));
return new_no;
}
+// Lookup a thunk to call method NAME on TYPE.
+
+Named_object*
+Interface_field_reference_expression::lookup_thunk(Interface_type* type,
+ const std::string& name)
+{
+ Interface_method_thunks::const_iterator p =
+ Interface_field_reference_expression::interface_method_thunks.find(type);
+ if (p == Interface_field_reference_expression::interface_method_thunks.end())
+ return NULL;
+ for (Method_thunks::const_iterator pm = p->second->begin();
+ pm != p->second->end();
+ ++pm)
+ if (pm->first == name)
+ return pm->second;
+ return NULL;
+}
+
// Get the backend representation for a method value.
Bexpression*
@@ -14778,9 +15008,11 @@ Interface_field_reference_expression::do_get_backend(Translate_context* context)
}
Named_object* thunk =
- Interface_field_reference_expression::create_thunk(context->gogo(),
- type, this->name_);
- if (thunk->is_erroneous())
+ Interface_field_reference_expression::lookup_thunk(type, this->name_);
+
+ // The thunk should have been created during the
+ // create_function_descriptors pass.
+ if (thunk == NULL || thunk->is_erroneous())
{
go_assert(saw_errors());
return context->backend()->error_expression();
diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h
index 9348354..92e8d8d 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -3405,6 +3405,10 @@ class Bound_method_expression : public Expression
static Named_object*
create_thunk(Gogo*, const Method* method, Named_object* function);
+ // Look up a thunk.
+ static Named_object*
+ lookup_thunk(Named_object* function);
+
protected:
int
do_traverse(Traverse*);
@@ -3578,6 +3582,10 @@ class Interface_field_reference_expression : public Expression
static Named_object*
create_thunk(Gogo*, Interface_type* type, const std::string& name);
+ // Look up a thunk.
+ static Named_object*
+ lookup_thunk(Interface_type* type, const std::string& name);
+
// Return an expression for the pointer to the function to call.
Expression*
get_function();
diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc
index 95b76bd..30d5c9f 100644
--- a/gcc/go/gofrontend/gogo.cc
+++ b/gcc/go/gofrontend/gogo.cc
@@ -141,6 +141,15 @@ Gogo::Gogo(Backend* backend, Linemap* linemap, int, int pointer_size)
this->add_named_type(error_type);
}
+ // "any" is an alias for the empty interface type.
+ {
+ Type* empty = Type::make_empty_interface_type(loc);
+ Named_object* no = Named_object::make_type("any", NULL, empty, loc);
+ Named_type* nt = no->type_value();
+ nt->set_is_alias();
+ this->add_named_type(nt);
+ }
+
this->globals_->add_constant(Typed_identifier("true",
Type::make_boolean_type(),
loc),
@@ -3430,6 +3439,11 @@ Create_function_descriptors::expression(Expression** pexpr)
if (args->traverse(this) == TRAVERSE_EXIT)
return TRAVERSE_EXIT;
}
+
+ // Traverse the subexpressions of the function, if any.
+ if (fn->traverse_subexpressions(this) == TRAVERSE_EXIT)
+ return TRAVERSE_EXIT;
+
return TRAVERSE_SKIP_COMPONENTS;
}
}
@@ -6885,80 +6899,12 @@ Block::traverse(Traverse* traverse)
| Traverse::traverse_expressions
| Traverse::traverse_types)) != 0)
{
- const unsigned int e_or_t = (Traverse::traverse_expressions
- | Traverse::traverse_types);
- const unsigned int e_or_t_or_s = (e_or_t
- | Traverse::traverse_statements);
for (Bindings::const_definitions_iterator pb =
this->bindings_->begin_definitions();
pb != this->bindings_->end_definitions();
++pb)
{
- int t = TRAVERSE_CONTINUE;
- switch ((*pb)->classification())
- {
- case Named_object::NAMED_OBJECT_CONST:
- if ((traverse_mask & Traverse::traverse_constants) != 0)
- t = traverse->constant(*pb, false);
- if (t == TRAVERSE_CONTINUE
- && (traverse_mask & e_or_t) != 0)
- {
- Type* tc = (*pb)->const_value()->type();
- if (tc != NULL
- && Type::traverse(tc, traverse) == TRAVERSE_EXIT)
- return TRAVERSE_EXIT;
- t = (*pb)->const_value()->traverse_expression(traverse);
- }
- break;
-
- case Named_object::NAMED_OBJECT_VAR:
- case Named_object::NAMED_OBJECT_RESULT_VAR:
- if ((traverse_mask & Traverse::traverse_variables) != 0)
- t = traverse->variable(*pb);
- if (t == TRAVERSE_CONTINUE
- && (traverse_mask & e_or_t) != 0)
- {
- if ((*pb)->is_result_variable()
- || (*pb)->var_value()->has_type())
- {
- Type* tv = ((*pb)->is_variable()
- ? (*pb)->var_value()->type()
- : (*pb)->result_var_value()->type());
- if (tv != NULL
- && Type::traverse(tv, traverse) == TRAVERSE_EXIT)
- return TRAVERSE_EXIT;
- }
- }
- if (t == TRAVERSE_CONTINUE
- && (traverse_mask & e_or_t_or_s) != 0
- && (*pb)->is_variable())
- t = (*pb)->var_value()->traverse_expression(traverse,
- traverse_mask);
- break;
-
- case Named_object::NAMED_OBJECT_FUNC:
- case Named_object::NAMED_OBJECT_FUNC_DECLARATION:
- go_unreachable();
-
- case Named_object::NAMED_OBJECT_TYPE:
- if ((traverse_mask & e_or_t) != 0)
- t = Type::traverse((*pb)->type_value(), traverse);
- break;
-
- case Named_object::NAMED_OBJECT_TYPE_DECLARATION:
- case Named_object::NAMED_OBJECT_UNKNOWN:
- case Named_object::NAMED_OBJECT_ERRONEOUS:
- break;
-
- case Named_object::NAMED_OBJECT_PACKAGE:
- case Named_object::NAMED_OBJECT_SINK:
- go_unreachable();
-
- default:
- go_unreachable();
- }
-
- if (t == TRAVERSE_EXIT)
+ if ((*pb)->traverse(traverse, false) == TRAVERSE_EXIT)
return TRAVERSE_EXIT;
}
}
@@ -8668,6 +8614,99 @@ Named_object::location() const
}
}
+// Traverse a Named_object.
+
+int
+Named_object::traverse(Traverse* traverse, bool is_global)
+{
+ const unsigned int traverse_mask = traverse->traverse_mask();
+ const unsigned int e_or_t = (Traverse::traverse_expressions
+ | Traverse::traverse_types);
+ const unsigned int e_or_t_or_s = (e_or_t
+ | Traverse::traverse_statements);
+
+ int t = TRAVERSE_CONTINUE;
+ switch (this->classification_)
+ {
+ case Named_object::NAMED_OBJECT_CONST:
+ if ((traverse_mask & Traverse::traverse_constants) != 0)
+ t = traverse->constant(this, is_global);
+ if (t == TRAVERSE_CONTINUE
+ && (traverse_mask & e_or_t) != 0)
+ {
+ Type* tc = this->const_value()->type();
+ if (tc != NULL)
+ {
+ if (Type::traverse(tc, traverse) == TRAVERSE_EXIT)
+ return TRAVERSE_EXIT;
+ }
+ t = this->const_value()->traverse_expression(traverse);
+ }
+ break;
+
+ case Named_object::NAMED_OBJECT_VAR:
+ case Named_object::NAMED_OBJECT_RESULT_VAR:
+ if ((traverse_mask & Traverse::traverse_variables) != 0)
+ t = traverse->variable(this);
+ if (t == TRAVERSE_CONTINUE
+ && (traverse_mask & e_or_t) != 0)
+ {
+ if (this->is_result_variable() || this->var_value()->has_type())
+ {
+ Type* tv = (this->is_variable()
+ ? this->var_value()->type()
+ : this->result_var_value()->type());
+ if (tv != NULL)
+ {
+ if (Type::traverse(tv, traverse) == TRAVERSE_EXIT)
+ return TRAVERSE_EXIT;
+ }
+ }
+ }
+ if (t == TRAVERSE_CONTINUE
+ && (traverse_mask & e_or_t_or_s) != 0
+ && this->is_variable())
+ t = this->var_value()->traverse_expression(traverse,
+ traverse_mask);
+ break;
+
+ case Named_object::NAMED_OBJECT_FUNC:
+ if ((traverse_mask & Traverse::traverse_functions) != 0)
+ t = traverse->function(this);
+ if (t == TRAVERSE_CONTINUE
+ && (traverse_mask
+ & (Traverse::traverse_variables
+ | Traverse::traverse_constants
+ | Traverse::traverse_functions
+ | Traverse::traverse_blocks
+ | Traverse::traverse_statements
+ | Traverse::traverse_expressions
+ | Traverse::traverse_types)) != 0)
+ t = this->func_value()->traverse(traverse);
+ break;
+
+ case Named_object::NAMED_OBJECT_TYPE:
+ if ((traverse_mask & e_or_t) != 0)
+ t = Type::traverse(this->type_value(), traverse);
+ break;
+
+ case Named_object::NAMED_OBJECT_PACKAGE:
+ case Named_object::NAMED_OBJECT_FUNC_DECLARATION:
+ case Named_object::NAMED_OBJECT_TYPE_DECLARATION:
+ case Named_object::NAMED_OBJECT_UNKNOWN:
+ case Named_object::NAMED_OBJECT_ERRONEOUS:
+ break;
+
+ case Named_object::NAMED_OBJECT_SINK:
+ go_unreachable();
+
+ default:
+ go_unreachable();
+ }
+
+ return t;
+}
+
// Export a named object.
void
@@ -8830,10 +8869,13 @@ Named_object::get_backend(Gogo* gogo, std::vector<Bexpression*>& const_decls,
{
named_type->
type_descriptor_pointer(gogo, Linemap::predeclared_location());
- named_type->gc_symbol_pointer(gogo);
Type* pn = Type::make_pointer_type(named_type);
pn->type_descriptor_pointer(gogo, Linemap::predeclared_location());
- pn->gc_symbol_pointer(gogo);
+ if (named_type->in_heap())
+ {
+ named_type->gc_symbol_pointer(gogo);
+ pn->gc_symbol_pointer(gogo);
+ }
}
}
break;
@@ -9193,90 +9235,10 @@ Bindings::traverse(Traverse* traverse, bool is_global)
// new global objects.
const unsigned int e_or_t = (Traverse::traverse_expressions
| Traverse::traverse_types);
- const unsigned int e_or_t_or_s = (e_or_t
- | Traverse::traverse_statements);
for (size_t i = 0; i < this->named_objects_.size(); ++i)
{
Named_object* p = this->named_objects_[i];
- int t = TRAVERSE_CONTINUE;
- switch (p->classification())
- {
- case Named_object::NAMED_OBJECT_CONST:
- if ((traverse_mask & Traverse::traverse_constants) != 0)
- t = traverse->constant(p, is_global);
- if (t == TRAVERSE_CONTINUE
- && (traverse_mask & e_or_t) != 0)
- {
- Type* tc = p->const_value()->type();
- if (tc != NULL
- && Type::traverse(tc, traverse) == TRAVERSE_EXIT)
- return TRAVERSE_EXIT;
- t = p->const_value()->traverse_expression(traverse);
- }
- break;
-
- case Named_object::NAMED_OBJECT_VAR:
- case Named_object::NAMED_OBJECT_RESULT_VAR:
- if ((traverse_mask & Traverse::traverse_variables) != 0)
- t = traverse->variable(p);
- if (t == TRAVERSE_CONTINUE
- && (traverse_mask & e_or_t) != 0)
- {
- if (p->is_result_variable()
- || p->var_value()->has_type())
- {
- Type* tv = (p->is_variable()
- ? p->var_value()->type()
- : p->result_var_value()->type());
- if (tv != NULL
- && Type::traverse(tv, traverse) == TRAVERSE_EXIT)
- return TRAVERSE_EXIT;
- }
- }
- if (t == TRAVERSE_CONTINUE
- && (traverse_mask & e_or_t_or_s) != 0
- && p->is_variable())
- t = p->var_value()->traverse_expression(traverse, traverse_mask);
- break;
-
- case Named_object::NAMED_OBJECT_FUNC:
- if ((traverse_mask & Traverse::traverse_functions) != 0)
- t = traverse->function(p);
-
- if (t == TRAVERSE_CONTINUE
- && (traverse_mask
- & (Traverse::traverse_variables
- | Traverse::traverse_constants
- | Traverse::traverse_functions
- | Traverse::traverse_blocks
- | Traverse::traverse_statements
- | Traverse::traverse_expressions
- | Traverse::traverse_types)) != 0)
- t = p->func_value()->traverse(traverse);
- break;
-
- case Named_object::NAMED_OBJECT_PACKAGE:
- // These are traversed in Gogo::traverse.
- go_assert(is_global);
- break;
-
- case Named_object::NAMED_OBJECT_TYPE:
- if ((traverse_mask & e_or_t) != 0)
- t = Type::traverse(p->type_value(), traverse);
- break;
-
- case Named_object::NAMED_OBJECT_TYPE_DECLARATION:
- case Named_object::NAMED_OBJECT_FUNC_DECLARATION:
- case Named_object::NAMED_OBJECT_UNKNOWN:
- case Named_object::NAMED_OBJECT_ERRONEOUS:
- break;
-
- case Named_object::NAMED_OBJECT_SINK:
- default:
- go_unreachable();
- }
-
- if (t == TRAVERSE_EXIT)
+ if (p->traverse(traverse, is_global) == TRAVERSE_EXIT)
return TRAVERSE_EXIT;
}
diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h
index 9ffd120..2ee0fda 100644
--- a/gcc/go/gofrontend/gogo.h
+++ b/gcc/go/gofrontend/gogo.h
@@ -3047,6 +3047,10 @@ class Named_object
Location
location() const;
+ // Traverse a Named_object.
+ int
+ traverse(Traverse*, bool is_global);
+
// Convert a variable to the backend representation.
Bvariable*
get_backend_variable(Gogo*, Named_object* function);
diff --git a/gcc/go/gofrontend/runtime.def b/gcc/go/gofrontend/runtime.def
index 87a2708..b7dd445 100644
--- a/gcc/go/gofrontend/runtime.def
+++ b/gcc/go/gofrontend/runtime.def
@@ -478,6 +478,10 @@ DEF_GO_RUNTIME(ATOMIC_ADD_FETCH_4, "__atomic_add_fetch_4",
DEF_GO_RUNTIME(ATOMIC_ADD_FETCH_8, "__atomic_add_fetch_8",
P3(POINTER, UINT64, INT32),
R1(UINT64))
+DEF_GO_RUNTIME(ATOMIC_LOAD_1, "__atomic_load_1", P2(POINTER, INT32),
+ R1(UINT8))
+DEF_GO_RUNTIME(ATOMIC_STORE_1, "__atomic_store_1", P3(POINTER, UINT8, INT32),
+ R0())
DEF_GO_RUNTIME(ATOMIC_AND_FETCH_1, "__atomic_and_fetch_1",
P3(POINTER, UINT8, INT32),
R1(UINT8))
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc
index 0f66661..ee34676 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -791,8 +791,7 @@ Type::are_convertible(const Type* lhs, const Type* rhs, std::string* reason)
// The types are convertible if they have identical underlying
// types, ignoring struct field tags.
- if ((lhs->named_type() != NULL || rhs->named_type() != NULL)
- && Type::are_identical(lhs->base(), rhs->base(), 0, reason))
+ if (Type::are_identical(lhs->base(), rhs->base(), 0, reason))
return true;
// The types are convertible if they are both unnamed pointer types
@@ -2514,13 +2513,18 @@ Type::type_descriptor_constructor(Gogo* gogo, int runtime_type_kind,
Expression_list* vals = new Expression_list();
vals->reserve(12);
- if (!this->has_pointer())
+ bool has_pointer;
+ if (name != NULL)
+ has_pointer = name->has_pointer();
+ else
+ has_pointer = this->has_pointer();
+ if (!has_pointer)
runtime_type_kind |= RUNTIME_TYPE_KIND_NO_POINTERS;
if (this->is_direct_iface_type())
runtime_type_kind |= RUNTIME_TYPE_KIND_DIRECT_IFACE;
int64_t ptrsize;
int64_t ptrdata;
- if (this->needs_gcprog(gogo, &ptrsize, &ptrdata))
+ if (has_pointer && this->needs_gcprog(gogo, &ptrsize, &ptrdata))
runtime_type_kind |= RUNTIME_TYPE_KIND_GC_PROG;
Struct_field_list::const_iterator p = fields->begin();
@@ -2531,7 +2535,10 @@ Type::type_descriptor_constructor(Gogo* gogo, int runtime_type_kind,
++p;
go_assert(p->is_field_name("ptrdata"));
type_info = Expression::TYPE_INFO_DESCRIPTOR_PTRDATA;
- vals->push_back(Expression::make_type_info(this, type_info));
+ if (has_pointer)
+ vals->push_back(Expression::make_type_info(this, type_info));
+ else
+ vals->push_back(Expression::make_integer_ul(0, p->type(), bloc));
++p;
go_assert(p->is_field_name("hash"));
@@ -2577,7 +2584,12 @@ Type::type_descriptor_constructor(Gogo* gogo, int runtime_type_kind,
++p;
go_assert(p->is_field_name("gcdata"));
- vals->push_back(Expression::make_gc_symbol(this));
+ if (has_pointer)
+ vals->push_back(Expression::make_gc_symbol(this));
+ else
+ vals->push_back(Expression::make_cast(p->type(),
+ Expression::make_nil(bloc),
+ bloc));
++p;
go_assert(p->is_field_name("string"));
@@ -6454,9 +6466,18 @@ get_backend_struct_fields(Gogo* gogo, Struct_type* type, bool use_placeholder,
? p->type()->get_backend_placeholder(gogo)
: p->type()->get_backend(gogo));
(*bfields)[i].location = p->location();
- lastsize = gogo->backend()->type_size((*bfields)[i].btype);
- if (lastsize != 0)
- saw_nonzero = true;
+ int64_t size = gogo->backend()->type_size((*bfields)[i].btype);
+ if (size != 0)
+ saw_nonzero = true;
+
+ if (size > 0 || !Gogo::is_sink_name(p->field_name()))
+ lastsize = size;
+ else
+ {
+ // There is an unreferenceable field of zero size. This
+ // doesn't affect whether we may need zero padding, so leave
+ // lastsize unchanged.
+ }
}
go_assert(i == fields->size());
if (saw_nonzero && lastsize == 0 && !type->is_results_struct())
@@ -10886,6 +10907,10 @@ Named_type::do_verify()
bool
Named_type::do_has_pointer() const
{
+ // A type that is not in the heap has no pointers that we care about.
+ if (!this->in_heap_)
+ return false;
+
if (this->seen_)
return false;
this->seen_ = true;
diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h
index a33453a..c55345a 100644
--- a/gcc/go/gofrontend/types.h
+++ b/gcc/go/gofrontend/types.h
@@ -2300,9 +2300,12 @@ class Pointer_type : public Type
do_verify()
{ return this->to_type_->verify(); }
+ // If this is a pointer to a type that can't be in the heap, then
+ // the garbage collector does not have to look at this, so pretend
+ // that this is not a pointer at all.
bool
do_has_pointer() const
- { return true; }
+ { return this->to_type_->in_heap(); }
bool
do_compare_is_identity(Gogo*)
diff --git a/gcc/go/gospec.c b/gcc/go/gospec.cc
index cf8d0f2..ba7ba4e 100644
--- a/gcc/go/gospec.c
+++ b/gcc/go/gospec.cc
@@ -1,5 +1,5 @@
-/* gospec.c -- Specific flags and argument handling of the gcc Go front end.
- Copyright (C) 2009-2021 Free Software Foundation, Inc.
+/* gospec.cc -- Specific flags and argument handling of the gcc Go front end.
+ Copyright (C) 2009-2022 Free Software Foundation, Inc.
This file is part of GCC.
@@ -29,10 +29,12 @@ along with GCC; see the file COPYING3. If not see
#define MATHLIB (1<<2)
/* This bit is set if they did `-lpthread'. */
#define THREADLIB (1<<3)
+/* This bit is set if they did `-lrt'. */
+#define RTLIB (1<<4)
/* This bit is set if they did `-lc'. */
-#define WITHLIBC (1<<4)
+#define WITHLIBC (1<<5)
/* Skip this option. */
-#define SKIPOPT (1<<5)
+#define SKIPOPT (1<<6)
#ifndef MATH_LIBRARY
#define MATH_LIBRARY "m"
@@ -44,6 +46,8 @@ along with GCC; see the file COPYING3. If not see
#define THREAD_LIBRARY "pthread"
#define THREAD_LIBRARY_PROFILE THREAD_LIBRARY
+#define RT_LIBRARY "rt"
+
#define LIBGO "go"
#define LIBGO_PROFILE LIBGO
#define LIBGOBEGIN "gobegin"
@@ -74,6 +78,9 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
/* "-lpthread" if it appears on the command line. */
const struct cl_decoded_option *saw_thread = 0;
+ /* "-lrt" if it appears on the command line. */
+ const struct cl_decoded_option *saw_rt = 0;
+
/* "-lc" if it appears on the command line. */
const struct cl_decoded_option *saw_libc = 0;
@@ -84,6 +91,9 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
/* Whether we need the thread library. */
int need_thread = 0;
+ /* Whether we need the rt library. */
+ int need_rt = 0;
+
/* By default, we throw on the math library if we have one. */
int need_math = (MATH_LIBRARY[0] != '\0');
@@ -156,6 +166,8 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
}
else if (strcmp (arg, THREAD_LIBRARY) == 0)
args[i] |= THREADLIB;
+ else if (strcmp (arg, RT_LIBRARY) == 0)
+ args[i] |= RTLIB;
else if (strcmp (arg, "c") == 0)
args[i] |= WITHLIBC;
else
@@ -260,7 +272,7 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
#endif
/* Make sure to have room for the trailing NULL argument. */
- num_args = argc + need_math + shared_libgcc + (library > 0) * 5 + 10;
+ num_args = argc + need_math + shared_libgcc + (library > 0) * 6 + 10;
new_decoded_options = XNEWVEC (struct cl_decoded_option, num_args);
i = 0;
@@ -314,6 +326,12 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
saw_thread = &decoded_options[i];
}
+ if (!saw_rt && (args[i] & RTLIB) && library > 0)
+ {
+ --j;
+ saw_rt = &decoded_options[i];
+ }
+
if (!saw_libc && (args[i] & WITHLIBC) && library > 0)
{
--j;
@@ -395,9 +413,23 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
#endif
/* When linking libgo statically we also need to link with the
- pthread library. */
+ pthread and (on GNU/Linux) the rt library. */
if (library > 1 || static_link)
- need_thread = 1;
+ {
+ need_thread = 1;
+ if (strstr (DEFAULT_TARGET_MACHINE, "linux") != NULL)
+ need_rt = 1;
+ }
+ }
+
+ if (saw_rt)
+ new_decoded_options[j++] = *saw_rt;
+ else if (library > 0 && need_rt)
+ {
+ generate_option (OPT_l, RT_LIBRARY, 1, CL_DRIVER,
+ &new_decoded_options[j]);
+ added_libraries++;
+ j++;
}
if (saw_thread)
diff --git a/gcc/go/lang-specs.h b/gcc/go/lang-specs.h
index 09df4aa..0c6005a 100644
--- a/gcc/go/lang-specs.h
+++ b/gcc/go/lang-specs.h
@@ -1,5 +1,5 @@
/* lang-specs.h -- gcc driver specs for Go frontend.
- Copyright (C) 2009-2021 Free Software Foundation, Inc.
+ Copyright (C) 2009-2022 Free Software Foundation, Inc.
This file is part of GCC.
@@ -17,7 +17,7 @@ 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.c
+/* This is the contribution to the `default_compilers' array in gcc.cc
for the Go language. */
{".go", "@go", 0, 1, 0},
diff --git a/gcc/go/lang.opt b/gcc/go/lang.opt
index c870acf..e487319 100644
--- a/gcc/go/lang.opt
+++ b/gcc/go/lang.opt
@@ -1,6 +1,6 @@
; lang.opt -- Options for the gcc Go front end.
-; Copyright (C) 2009-2021 Free Software Foundation, Inc.
+; Copyright (C) 2009-2022 Free Software Foundation, Inc.
;
; This file is part of GCC.
;