aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2018-01-09 01:23:08 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2018-01-09 01:23:08 +0000
commit1a2f01efa63036a5104f203a4789e682c0e0915d (patch)
tree373e15778dc8295354584e1f86915ae493b604ff /gcc
parent8799df67f2dab88f9fda11739c501780a85575e2 (diff)
downloadgcc-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/MERGE2
-rw-r--r--gcc/go/gofrontend/expressions.cc43
-rw-r--r--gcc/go/gofrontend/runtime.def11
-rw-r--r--gcc/go/gofrontend/types.cc20
-rw-r--r--gcc/go/gofrontend/types.h4
-rw-r--r--gcc/go/gofrontend/wb.cc49
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;