aboutsummaryrefslogtreecommitdiff
path: root/gcc/go
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2022-03-06 16:28:20 +0100
committerMartin Liska <mliska@suse.cz>2022-03-06 16:28:20 +0100
commit1a576b7ac609d4225a3833e3a9c84a9439d0e45e (patch)
tree7172f94eacd2615a13f0579119f3cd5f42fdcd8e /gcc/go
parentf015156d6662c3ce367c5834eb109a0a77b56f39 (diff)
parent98cd717fca9f21625b9c79c9231c2e909d1d93a3 (diff)
downloadgcc-1a576b7ac609d4225a3833e3a9c84a9439d0e45e.zip
gcc-1a576b7ac609d4225a3833e3a9c84a9439d0e45e.tar.gz
gcc-1a576b7ac609d4225a3833e3a9c84a9439d0e45e.tar.bz2
Merge branch 'master' into devel/sphinx
Diffstat (limited to 'gcc/go')
-rw-r--r--gcc/go/ChangeLog18
-rw-r--r--gcc/go/go-gcc.cc14
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/expressions.cc223
-rw-r--r--gcc/go/gofrontend/gogo.cc16
-rw-r--r--gcc/go/gofrontend/runtime.def4
-rw-r--r--gcc/go/gofrontend/types.cc34
-rw-r--r--gcc/go/gofrontend/types.h5
8 files changed, 288 insertions, 28 deletions
diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog
index b996df8..f50a60b7 100644
--- a/gcc/go/ChangeLog
+++ b/gcc/go/ChangeLog
@@ -1,3 +1,21 @@
+2022-02-13 Ian Lance Taylor <iant@golang.org>
+
+ * gospec.cc: Revert 2022-02-09 change:
+ (RTLIB, RT_LIBRARY): Don't define.
+ (lang_specific_driver): Don't add -lrt if linking statically
+ on GNU/Linux.
+
+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.
diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc
index 6319960..f3de7a8 100644
--- a/gcc/go/go-gcc.cc
+++ b/gcc/go/go-gcc.cc
@@ -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/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index a42d88d..e68d2d9 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-7d510bf5fcec9b0ccc0282f4193a80c0a164df63
+787fd4475f9d9101bc138d0b9763b0f5ecca89a9
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 7970282..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;
@@ -10326,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();
@@ -11613,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");
@@ -11629,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.
@@ -11694,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.
@@ -11713,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
@@ -11743,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)
@@ -11913,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"))
@@ -11972,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();
@@ -12012,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);
@@ -12177,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;
}
diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc
index e2fd509..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),
@@ -8860,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;
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 1c67ea0..8267f15 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -2513,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();
@@ -2530,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"));
@@ -2576,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"));
@@ -2803,6 +2816,9 @@ class Ptrmask
void
Ptrmask::set_from(Gogo* gogo, Type* type, int64_t ptrsize, int64_t offset)
{
+ if (!type->has_pointer())
+ return;
+
switch (type->base()->classification())
{
default:
@@ -2845,9 +2861,6 @@ Ptrmask::set_from(Gogo* gogo, Type* type, int64_t ptrsize, int64_t offset)
case Type::TYPE_STRUCT:
{
- if (!type->has_pointer())
- return;
-
const Struct_field_list* fields = type->struct_type()->fields();
int64_t soffset = 0;
for (Struct_field_list::const_iterator pf = fields->begin();
@@ -2885,9 +2898,6 @@ Ptrmask::set_from(Gogo* gogo, Type* type, int64_t ptrsize, int64_t offset)
}
else
{
- if (!type->has_pointer())
- return;
-
int64_t len;
if (!type->array_type()->int_length(&len))
{
@@ -10894,6 +10904,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*)