diff options
author | Martin Liska <mliska@suse.cz> | 2022-03-06 16:28:20 +0100 |
---|---|---|
committer | Martin Liska <mliska@suse.cz> | 2022-03-06 16:28:20 +0100 |
commit | 1a576b7ac609d4225a3833e3a9c84a9439d0e45e (patch) | |
tree | 7172f94eacd2615a13f0579119f3cd5f42fdcd8e /gcc/go | |
parent | f015156d6662c3ce367c5834eb109a0a77b56f39 (diff) | |
parent | 98cd717fca9f21625b9c79c9231c2e909d1d93a3 (diff) | |
download | gcc-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/ChangeLog | 18 | ||||
-rw-r--r-- | gcc/go/go-gcc.cc | 14 | ||||
-rw-r--r-- | gcc/go/gofrontend/MERGE | 2 | ||||
-rw-r--r-- | gcc/go/gofrontend/expressions.cc | 223 | ||||
-rw-r--r-- | gcc/go/gofrontend/gogo.cc | 16 | ||||
-rw-r--r-- | gcc/go/gofrontend/runtime.def | 4 | ||||
-rw-r--r-- | gcc/go/gofrontend/types.cc | 34 | ||||
-rw-r--r-- | gcc/go/gofrontend/types.h | 5 |
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*) |