diff options
author | Ian Lance Taylor <iant@golang.org> | 2018-01-09 01:23:08 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2018-01-09 01:23:08 +0000 |
commit | 1a2f01efa63036a5104f203a4789e682c0e0915d (patch) | |
tree | 373e15778dc8295354584e1f86915ae493b604ff /gcc | |
parent | 8799df67f2dab88f9fda11739c501780a85575e2 (diff) | |
download | gcc-1a2f01efa63036a5104f203a4789e682c0e0915d.zip gcc-1a2f01efa63036a5104f203a4789e682c0e0915d.tar.gz gcc-1a2f01efa63036a5104f203a4789e682c0e0915d.tar.bz2 |
libgo: update to Go1.10beta1
Update the Go library to the 1.10beta1 release.
Requires a few changes to the compiler for modifications to the map
runtime code, and to handle some nowritebarrier cases in the runtime.
Reviewed-on: https://go-review.googlesource.com/86455
gotools/:
* Makefile.am (go_cmd_vet_files): New variable.
(go_cmd_buildid_files, go_cmd_test2json_files): New variables.
(s-zdefaultcc): Change from constants to functions.
(noinst_PROGRAMS): Add vet, buildid, and test2json.
(cgo$(EXEEXT)): Link against $(LIBGOTOOL).
(vet$(EXEEXT)): New target.
(buildid$(EXEEXT)): New target.
(test2json$(EXEEXT)): New target.
(install-exec-local): Install all $(noinst_PROGRAMS).
(uninstall-local): Uninstasll all $(noinst_PROGRAMS).
(check-go-tool): Depend on $(noinst_PROGRAMS). Copy down
objabi.go.
(check-runtime): Depend on $(noinst_PROGRAMS).
(check-cgo-test, check-carchive-test): Likewise.
(check-vet): New target.
(check): Depend on check-vet. Look at cmd_vet-testlog.
(.PHONY): Add check-vet.
* Makefile.in: Rebuild.
From-SVN: r256365
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/go/gofrontend/MERGE | 2 | ||||
-rw-r--r-- | gcc/go/gofrontend/expressions.cc | 43 | ||||
-rw-r--r-- | gcc/go/gofrontend/runtime.def | 11 | ||||
-rw-r--r-- | gcc/go/gofrontend/types.cc | 20 | ||||
-rw-r--r-- | gcc/go/gofrontend/types.h | 4 | ||||
-rw-r--r-- | gcc/go/gofrontend/wb.cc | 49 |
6 files changed, 97 insertions, 32 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index b03c3fb..d836309 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -1319f36ccc65cf802b8e17ddd3d2da3ca6d82f4c +dbc0c7e4329aada2ae3554c20cfb8cfa48041213 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 f5adc18..c34a5b0 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -7483,6 +7483,7 @@ Builtin_call_expression::lower_make(Statement_inserter* inserter) return Expression::make_error(this->location()); } len_arg = Expression::make_integer_ul(0, NULL, loc); + len_small = true; } else { @@ -7551,9 +7552,23 @@ Builtin_call_expression::lower_make(Statement_inserter* inserter) else if (is_map) { Expression* type_arg = Expression::make_type_descriptor(type, type_loc); - call = Runtime::make_call(Runtime::MAKEMAP, loc, 4, type_arg, len_arg, - Expression::make_nil(loc), - Expression::make_nil(loc)); + if (!len_small) + call = Runtime::make_call(Runtime::MAKEMAP64, loc, 3, type_arg, + len_arg, + Expression::make_nil(loc)); + else + { + Numeric_constant nclen; + unsigned long vlen; + if (len_arg->numeric_constant_value(&nclen) + && nclen.to_unsigned_long(&vlen) == Numeric_constant::NC_UL_VALID + && vlen <= Map_type::bucket_size) + call = Runtime::make_call(Runtime::MAKEMAP_SMALL, loc, 0); + else + call = Runtime::make_call(Runtime::MAKEMAP, loc, 3, type_arg, + len_arg, + Expression::make_nil(loc)); + } } else if (is_chan) { @@ -9503,14 +9518,8 @@ Call_expression::do_lower(Gogo* gogo, Named_object* function, // could implement them in normal code, but then we would have to // explicitly unwind the stack. These functions are intended to be // efficient. Note that this technique obviously only works for - // direct calls, but that is the only way they are used. The actual - // argument to these functions is always the address of a parameter; - // we don't need that for the GCC builtin functions, so we just - // ignore it. - if (gogo->compiling_runtime() - && this->args_ != NULL - && this->args_->size() == 1 - && gogo->package_name() == "runtime") + // direct calls, but that is the only way they are used. + if (gogo->compiling_runtime() && gogo->package_name() == "runtime") { Func_expression* fe = this->fn_->func_expression(); if (fe != NULL @@ -9518,15 +9527,21 @@ Call_expression::do_lower(Gogo* gogo, Named_object* function, && fe->named_object()->package() == NULL) { std::string n = Gogo::unpack_hidden_name(fe->named_object()->name()); - if (n == "getcallerpc") + if ((this->args_ == NULL || this->args_->size() == 0) + && n == "getcallerpc") { static Named_object* builtin_return_address; return this->lower_to_builtin(&builtin_return_address, "__builtin_return_address", 0); } - else if (n == "getcallersp") + else if (this->args_ != NULL + && this->args_->size() == 1 + && n == "getcallersp") { + // The actual argument to getcallersp is always the + // address of a parameter; we don't need that for the + // GCC builtin function, so we just ignore it. static Named_object* builtin_frame_address; return this->lower_to_builtin(&builtin_frame_address, "__builtin_frame_address", @@ -10027,7 +10042,7 @@ Call_expression::do_check_types(Gogo*) } const Typed_identifier_list* parameters = fntype->parameters(); - if (this->args_ == NULL) + if (this->args_ == NULL || this->args_->size() == 0) { if (parameters != NULL && !parameters->empty()) this->report_error(_("not enough arguments")); diff --git a/gcc/go/gofrontend/runtime.def b/gcc/go/gofrontend/runtime.def index ef148ee..605bcff 100644 --- a/gcc/go/gofrontend/runtime.def +++ b/gcc/go/gofrontend/runtime.def @@ -91,9 +91,14 @@ DEF_GO_RUNTIME(MAKESLICE64, "runtime.makeslice64", P3(TYPE, INT64, INT64), R1(SLICE)) -// Make a map. -DEF_GO_RUNTIME(MAKEMAP, "runtime.makemap", P4(TYPE, INT64, POINTER, POINTER), - R1(MAP)) +// Make a map with a hint and an (optional, unused) map structure. +DEF_GO_RUNTIME(MAKEMAP, "runtime.makemap", P3(TYPE, INT, POINTER), + R1(MAP)) +DEF_GO_RUNTIME(MAKEMAP64, "runtime.makemap64", P3(TYPE, INT64, POINTER), + R1(MAP)) + +// Make a map with no hint, or a small constant hint. +DEF_GO_RUNTIME(MAKEMAP_SMALL, "runtime.makemap_small", P0(), R1(MAP)) // Build a map from a composite literal. DEF_GO_RUNTIME(CONSTRUCT_MAP, "__go_construct_map", diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index 2274c31..85273bf 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -7830,7 +7830,7 @@ Map_type::do_get_backend(Gogo* gogo) bfields[7].btype = uintptr_type->get_backend(gogo); bfields[7].location = bloc; - bfields[8].name = "overflow"; + bfields[8].name = "extra"; bfields[8].btype = bpvt; bfields[8].location = bloc; @@ -8144,21 +8144,23 @@ Map_type::hmap_type(Type* bucket_type) Type* int_type = Type::lookup_integer_type("int"); Type* uint8_type = Type::lookup_integer_type("uint8"); + Type* uint16_type = Type::lookup_integer_type("uint16"); Type* uint32_type = Type::lookup_integer_type("uint32"); Type* uintptr_type = Type::lookup_integer_type("uintptr"); Type* void_ptr_type = Type::make_pointer_type(Type::make_void_type()); Type* ptr_bucket_type = Type::make_pointer_type(bucket_type); - Struct_type* ret = make_builtin_struct_type(8, + Struct_type* ret = make_builtin_struct_type(9, "count", int_type, "flags", uint8_type, "B", uint8_type, + "noverflow", uint16_type, "hash0", uint32_type, "buckets", ptr_bucket_type, "oldbuckets", ptr_bucket_type, "nevacuate", uintptr_type, - "overflow", void_ptr_type); + "extra", void_ptr_type); ret->set_is_struct_incomparable(); this->hmap_type_ = ret; return ret; @@ -8191,18 +8193,22 @@ Map_type::hiter_type(Gogo* gogo) Type* hmap_type = this->hmap_type(bucket_type); Type* hmap_ptr_type = Type::make_pointer_type(hmap_type); Type* void_ptr_type = Type::make_pointer_type(Type::make_void_type()); + Type* bool_type = Type::lookup_bool_type(); - Struct_type* ret = make_builtin_struct_type(12, + Struct_type* ret = make_builtin_struct_type(15, "key", key_ptr_type, "val", val_ptr_type, "t", uint8_ptr_type, "h", hmap_ptr_type, "buckets", bucket_ptr_type, "bptr", bucket_ptr_type, - "overflow0", void_ptr_type, - "overflow1", void_ptr_type, + "overflow", void_ptr_type, + "oldoverflow", void_ptr_type, "startBucket", uintptr_type, - "stuff", uintptr_type, + "offset", uint8_type, + "wrapped", bool_type, + "B", uint8_type, + "i", uint8_type, "bucket", uintptr_type, "checkBucket", uintptr_type); ret->set_is_struct_incomparable(); diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h index a1e3884..08e5701 100644 --- a/gcc/go/gofrontend/types.h +++ b/gcc/go/gofrontend/types.h @@ -2826,6 +2826,9 @@ class Map_type : public Type static Type* make_map_type_descriptor_type(); + // This must be in sync with libgo/go/runtime/hashmap.go. + static const int bucket_size = 8; + protected: int do_traverse(Traverse*); @@ -2867,7 +2870,6 @@ class Map_type : public Type private: // These must be in sync with libgo/go/runtime/hashmap.go. - static const int bucket_size = 8; static const int max_key_size = 128; static const int max_val_size = 128; static const int max_zero_size = 1024; diff --git a/gcc/go/gofrontend/wb.cc b/gcc/go/gofrontend/wb.cc index 0085667..5870661 100644 --- a/gcc/go/gofrontend/wb.cc +++ b/gcc/go/gofrontend/wb.cc @@ -331,6 +331,25 @@ Gogo::assign_needs_write_barrier(Expression* lhs) if (!lhs->type()->has_pointer()) return false; + // An assignment to a field is handled like an assignment to the + // struct. + while (true) + { + // Nothing to do for a type that can not be in the heap, or a + // pointer to a type that can not be in the heap. We check this + // at each level of a struct. + if (!lhs->type()->in_heap()) + return false; + if (lhs->type()->points_to() != NULL + && !lhs->type()->points_to()->in_heap()) + return false; + + Field_reference_expression* fre = lhs->field_reference_expression(); + if (fre == NULL) + break; + lhs = fre->expr(); + } + // Nothing to do for an assignment to a temporary. if (lhs->temporary_reference_expression() != NULL) return false; @@ -359,12 +378,30 @@ Gogo::assign_needs_write_barrier(Expression* lhs) } } - // Nothing to do for a type that can not be in the heap, or a - // pointer to a type that can not be in the heap. - if (!lhs->type()->in_heap()) - return false; - if (lhs->type()->points_to() != NULL && !lhs->type()->points_to()->in_heap()) - return false; + // For a struct assignment, we don't need a write barrier if all the + // pointer types can not be in the heap. + Struct_type* st = lhs->type()->struct_type(); + if (st != NULL) + { + bool in_heap = false; + const Struct_field_list* fields = st->fields(); + for (Struct_field_list::const_iterator p = fields->begin(); + p != fields->end(); + p++) + { + Type* ft = p->type(); + if (!ft->has_pointer()) + continue; + if (!ft->in_heap()) + continue; + if (ft->points_to() != NULL && !ft->points_to()->in_heap()) + continue; + in_heap = true; + break; + } + if (!in_heap) + return false; + } // Write barrier needed in other cases. return true; |