diff options
author | ian <ian@138bc75d-0d04-0410-961f-82ee72b054a4> | 2017-01-14 00:05:42 +0000 |
---|---|---|
committer | ian <ian@138bc75d-0d04-0410-961f-82ee72b054a4> | 2017-01-14 00:05:42 +0000 |
commit | ccea2b367771831e9877ec31e0656d153818bf3f (patch) | |
tree | e183ae81a1f48a02945cb6de463a70c5be1b06f6 /gcc/go | |
parent | fd961cec64a5807cd6375d5c4042bca4256c5fda (diff) | |
download | gcc-ccea2b367771831e9877ec31e0656d153818bf3f.tar.gz |
libgo: update to Go 1.8 release candidate 1
Compiler changes:
* Change map assignment to use mapassign and assign value directly.
* Change string iteration to use decoderune, faster for ASCII strings.
* Change makeslice to take int, and use makeslice64 for larger values.
* Add new noverflow field to hmap struct used for maps.
Unresolved problems, to be fixed later:
* Commented out test in go/types/sizes_test.go that doesn't compile.
* Commented out reflect.TestStructOf test for padding after zero-sized field.
Reviewed-on: https://go-review.googlesource.com/35231
gotools/:
Updates for Go 1.8rc1.
* Makefile.am (go_cmd_go_files): Add bug.go.
(s-zdefaultcc): Write defaultPkgConfig.
* Makefile.in: Rebuild.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@244456 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/go')
-rw-r--r-- | gcc/go/gofrontend/MERGE | 2 | ||||
-rw-r--r-- | gcc/go/gofrontend/escape.cc | 7 | ||||
-rw-r--r-- | gcc/go/gofrontend/expressions.cc | 36 | ||||
-rw-r--r-- | gcc/go/gofrontend/runtime.def | 18 | ||||
-rw-r--r-- | gcc/go/gofrontend/statements.cc | 168 | ||||
-rw-r--r-- | gcc/go/gofrontend/statements.h | 2 | ||||
-rw-r--r-- | gcc/go/gofrontend/types.cc | 33 |
7 files changed, 164 insertions, 102 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 443de8bb240..d594ded36b3 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -153f7b68c0c4d3cf3da0becf82eb1a3eb8b47d6e +0ba4563a4b0dec4c01b90d7b3c9e2ce2cd58a96f 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/escape.cc b/gcc/go/gofrontend/escape.cc index 6429a9a73d5..a90c527a361 100644 --- a/gcc/go/gofrontend/escape.cc +++ b/gcc/go/gofrontend/escape.cc @@ -297,6 +297,7 @@ Node::op_format() const case Runtime::MAKECHAN: case Runtime::MAKEMAP: case Runtime::MAKESLICE: + case Runtime::MAKESLICE64: op << "make"; break; @@ -418,7 +419,8 @@ Node::is_big(Escape_context* context) const Func_expression* fn = call->fn()->func_expression(); if (fn != NULL && fn->is_runtime_function() - && fn->runtime_code() == Runtime::MAKESLICE) + && (fn->runtime_code() == Runtime::MAKESLICE + || fn->runtime_code() == Runtime::MAKESLICE64)) { // Second argument is length. Expression_list::iterator p = call->args()->begin(); @@ -1240,6 +1242,7 @@ Escape_analysis_assign::expression(Expression** pexpr) case Runtime::MAKECHAN: case Runtime::MAKEMAP: case Runtime::MAKESLICE: + case Runtime::MAKESLICE64: case Runtime::SLICEBYTETOSTRING: case Runtime::SLICERUNETOSTRING: case Runtime::STRINGTOSLICEBYTE: @@ -1849,6 +1852,7 @@ Escape_analysis_assign::assign(Node* dst, Node* src) case Runtime::MAKECHAN: case Runtime::MAKEMAP: case Runtime::MAKESLICE: + case Runtime::MAKESLICE64: // DST = make(...). case Runtime::SLICEBYTETOSTRING: // DST = string([]byte{...}). @@ -2623,6 +2627,7 @@ Escape_analysis_flood::flood(Level level, Node* dst, Node* src, case Runtime::MAKECHAN: case Runtime::MAKEMAP: case Runtime::MAKESLICE: + case Runtime::MAKESLICE64: case Runtime::SLICEBYTETOSTRING: case Runtime::SLICERUNETOSTRING: case Runtime::STRINGTOSLICEBYTE: diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index fe4d07bec20..8006888b02a 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -7091,7 +7091,7 @@ class Builtin_call_expression : public Call_expression Expression* flatten_append(Gogo*, Named_object*, Statement_inserter*); bool - check_int_value(Expression*, bool is_length); + check_int_value(Expression*, bool is_length, bool* small); // A pointer back to the general IR structure. This avoids a global // variable, or passing it around everywhere. @@ -7462,6 +7462,7 @@ Builtin_call_expression::lower_make(Statement_inserter* inserter) ++parg; Expression* len_arg; + bool len_small = false; if (parg == args->end()) { if (is_slice) @@ -7475,17 +7476,18 @@ Builtin_call_expression::lower_make(Statement_inserter* inserter) { len_arg = *parg; len_arg->determine_type(&int_context); - if (!this->check_int_value(len_arg, true)) + if (!this->check_int_value(len_arg, true, &len_small)) return Expression::make_error(this->location()); ++parg; } Expression* cap_arg = NULL; + bool cap_small = false; if (is_slice && parg != args->end()) { cap_arg = *parg; cap_arg->determine_type(&int_context); - if (!this->check_int_value(cap_arg, false)) + if (!this->check_int_value(cap_arg, false, &cap_small)) return Expression::make_error(this->location()); Numeric_constant nclen; @@ -7526,9 +7528,13 @@ Builtin_call_expression::lower_make(Statement_inserter* inserter) inserter->insert(temp); len_arg = Expression::make_temporary_reference(temp, loc); cap_arg = Expression::make_temporary_reference(temp, loc); + cap_small = len_small; } - call = Runtime::make_call(Runtime::MAKESLICE, loc, 3, type_arg, - len_arg, cap_arg); + + Runtime::Function code = Runtime::MAKESLICE; + if (!len_small || !cap_small) + code = Runtime::MAKESLICE64; + call = Runtime::make_call(code, loc, 3, type_arg, len_arg, cap_arg); } else if (is_map) { @@ -7744,11 +7750,14 @@ Builtin_call_expression::flatten_append(Gogo* gogo, Named_object* function, // Return whether an expression has an integer value. Report an error // if not. This is used when handling calls to the predeclared make -// function. +// function. Set *SMALL if the value is known to fit in type "int". bool -Builtin_call_expression::check_int_value(Expression* e, bool is_length) +Builtin_call_expression::check_int_value(Expression* e, bool is_length, + bool *small) { + *small = false; + Numeric_constant nc; if (e->numeric_constant_value(&nc)) { @@ -7784,11 +7793,22 @@ Builtin_call_expression::check_int_value(Expression* e, bool is_length) return false; } + *small = true; return true; } if (e->type()->integer_type() != NULL) - return true; + { + int ebits = e->type()->integer_type()->bits(); + int intbits = Type::lookup_integer_type("int")->integer_type()->bits(); + + // We can treat ebits == intbits as small even for an unsigned + // integer type, because we will convert the value to int and + // then reject it in the runtime if it is negative. + *small = ebits <= intbits; + + return true; + } go_error_at(e->location(), "non-integer %s argument to make", is_length ? "len" : "cap"); diff --git a/gcc/go/gofrontend/runtime.def b/gcc/go/gofrontend/runtime.def index 7027989810c..90bf34f7e99 100644 --- a/gcc/go/gofrontend/runtime.def +++ b/gcc/go/gofrontend/runtime.def @@ -31,12 +31,9 @@ // The standard C memcmp function, used for struct comparisons. DEF_GO_RUNTIME(MEMCMP, "__go_memcmp", P3(POINTER, POINTER, UINTPTR), R1(INT)) -// Range over a string, returning the next index. -DEF_GO_RUNTIME(STRINGITER, "runtime.stringiter", P2(STRING, INT), R1(INT)) - -// Range over a string, returning the next index and character. -DEF_GO_RUNTIME(STRINGITER2, "runtime.stringiter2", P2(STRING, INT), - R2(INT, RUNE)) +// Decode a non-ASCII rune from a string. +DEF_GO_RUNTIME(DECODERUNE, "runtime.decoderune", P2(STRING, INT), + R2(RUNE, INT)) // Concatenate strings. DEF_GO_RUNTIME(CONCATSTRINGS, "runtime.concatstrings", P2(POINTER, SLICE), @@ -87,7 +84,10 @@ DEF_GO_RUNTIME(COMPLEX128_DIV, "__go_complex128_div", P2(COMPLEX128, COMPLEX128), R1(COMPLEX128)) // Make a slice. -DEF_GO_RUNTIME(MAKESLICE, "runtime.makeslice", P3(TYPE, INT64, INT64), +DEF_GO_RUNTIME(MAKESLICE, "runtime.makeslice", P3(TYPE, INT, INT), + R1(SLICE)) + +DEF_GO_RUNTIME(MAKESLICE64, "runtime.makeslice64", P3(TYPE, INT64, INT64), R1(SLICE)) @@ -119,8 +119,8 @@ DEF_GO_RUNTIME(MAPACCESS2_FAT, "runtime.mapaccess2_fat", P4(TYPE, MAP, POINTER, POINTER), R2(POINTER, BOOL)) // Assignment to a key in a map. -DEF_GO_RUNTIME(MAPASSIGN, "runtime.mapassign1", - P4(TYPE, MAP, POINTER, POINTER), R0()) +DEF_GO_RUNTIME(MAPASSIGN, "runtime.mapassign", P3(TYPE, MAP, POINTER), + R1(POINTER)) // Delete a key from a map. DEF_GO_RUNTIME(MAPDELETE, "runtime.mapdelete", P3(TYPE, MAP, POINTER), R0()) diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc index dc226e8b21e..d6ab4ccd674 100644 --- a/gcc/go/gofrontend/statements.cc +++ b/gcc/go/gofrontend/statements.cc @@ -707,8 +707,8 @@ Assignment_statement::do_lower(Gogo*, Named_object*, Block* enclosing, Move_ordered_evals moe(b); mie->traverse_subexpressions(&moe); - // Copy key and value into temporaries so that we can take their - // address without pushing the value onto the heap. + // Copy the key into a temporary so that we can take its address + // without pushing the value onto the heap. // var key_temp KEY_TYPE = MAP_INDEX Temporary_statement* key_temp = Statement::make_temporary(mt->key_type(), @@ -716,23 +716,29 @@ Assignment_statement::do_lower(Gogo*, Named_object*, Block* enclosing, loc); b->add_statement(key_temp); + // Copy the value into a temporary to ensure that it is + // evaluated before we add the key to the map. This may matter + // if the value is itself a reference to the map. + // var val_temp VAL_TYPE = RHS Temporary_statement* val_temp = Statement::make_temporary(mt->val_type(), this->rhs_, loc); b->add_statement(val_temp); - // mapassign1(TYPE, MAP, &key_temp, &val_temp) + // *mapassign(TYPE, MAP, &key_temp) = RHS Expression* a1 = Expression::make_type_descriptor(mt, loc); Expression* a2 = mie->map(); Temporary_reference_expression* ref = Expression::make_temporary_reference(key_temp, loc); Expression* a3 = Expression::make_unary(OPERATOR_AND, ref, loc); + Expression* call = Runtime::make_call(Runtime::MAPASSIGN, loc, 3, + a1, a2, a3); + Type* ptrval_type = Type::make_pointer_type(mt->val_type()); + call = Expression::make_cast(ptrval_type, call, loc); + Expression* indir = Expression::make_unary(OPERATOR_MULT, call, loc); ref = Expression::make_temporary_reference(val_temp, loc); - Expression* a4 = Expression::make_unary(OPERATOR_AND, ref, loc); - Expression* call = Runtime::make_call(Runtime::MAPASSIGN, loc, 4, - a1, a2, a3, a4); - b->add_statement(Statement::make_statement(call, false)); + b->add_statement(Statement::make_assignment(indir, ref, loc)); return Statement::make_block_statement(b, loc); } @@ -5313,7 +5319,7 @@ For_range_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing, else if (range_type->is_string_type()) { index_type = Type::lookup_integer_type("int"); - value_type = Type::lookup_integer_type("int32"); + value_type = gogo->lookup_global("rune")->type_value(); } else if (range_type->map_type() != NULL) { @@ -5458,7 +5464,7 @@ For_range_statement::make_range_ref(Named_object* range_object, // Return a call to the predeclared function FUNCNAME passing a // reference to the temporary variable ARG. -Expression* +Call_expression* For_range_statement::call_builtin(Gogo* gogo, const char* funcname, Expression* arg, Location loc) @@ -5664,7 +5670,7 @@ For_range_statement::lower_range_slice(Gogo* gogo, // Lower a for range over a string. void -For_range_statement::lower_range_string(Gogo*, +For_range_statement::lower_range_string(Gogo* gogo, Block* enclosing, Block* body_block, Named_object* range_object, @@ -5679,94 +5685,121 @@ For_range_statement::lower_range_string(Gogo*, Location loc = this->location(); // The loop we generate: + // len_temp := len(range) // var next_index_temp int - // for index_temp = 0; ; index_temp = next_index_temp { - // next_index_temp, value_temp = stringiter2(range, index_temp) - // if next_index_temp == 0 { - // break + // for index_temp = 0; index_temp < len_temp; index_temp = next_index_temp { + // value_temp = rune(range[index_temp]) + // if value_temp < utf8.RuneSelf { + // next_index_temp = index_temp + 1 + // } else { + // value_temp, next_index_temp = decoderune(range, index_temp) // } // index = index_temp // value = value_temp - // original body + // // original body // } // Set *PINIT to + // len_temp := len(range) // var next_index_temp int // index_temp = 0 + // var value_temp rune // if value_temp not passed in Block* init = new Block(enclosing, loc); + Expression* ref = this->make_range_ref(range_object, range_temp, loc); + Call_expression* call = this->call_builtin(gogo, "len", ref, loc); + Temporary_statement* len_temp = + Statement::make_temporary(index_temp->type(), call, loc); + init->add_statement(len_temp); + Temporary_statement* next_index_temp = Statement::make_temporary(index_temp->type(), NULL, loc); init->add_statement(next_index_temp); - Expression* zexpr = Expression::make_integer_ul(0, NULL, loc); - - Temporary_reference_expression* ref = + Temporary_reference_expression* index_ref = Expression::make_temporary_reference(index_temp, loc); - ref->set_is_lvalue(); - Statement* s = Statement::make_assignment(ref, zexpr, loc); - + index_ref->set_is_lvalue(); + Expression* zexpr = Expression::make_integer_ul(0, index_temp->type(), loc); + Statement* s = Statement::make_assignment(index_ref, zexpr, loc); init->add_statement(s); + + Type* rune_type; + if (value_temp != NULL) + rune_type = value_temp->type(); + else + { + rune_type = gogo->lookup_global("rune")->type_value(); + value_temp = Statement::make_temporary(rune_type, NULL, loc); + init->add_statement(value_temp); + } + *pinit = init; - // The loop has no condition. + // Set *PCOND to + // index_temp < len_temp - *pcond = NULL; + index_ref = Expression::make_temporary_reference(index_temp, loc); + Expression* len_ref = + Expression::make_temporary_reference(len_temp, loc); + *pcond = Expression::make_binary(OPERATOR_LT, index_ref, len_ref, loc); // Set *PITER_INIT to - // next_index_temp = runtime.stringiter(range, index_temp) - // or - // next_index_temp, value_temp = runtime.stringiter2(range, index_temp) - // followed by - // if next_index_temp == 0 { - // break + // value_temp = rune(range[index_temp]) + // if value_temp < utf8.RuneSelf { + // next_index_temp = index_temp + 1 + // } else { + // value_temp, next_index_temp = decoderune(range, index_temp) // } Block* iter_init = new Block(body_block, loc); - Expression* p1 = this->make_range_ref(range_object, range_temp, loc); - Expression* p2 = Expression::make_temporary_reference(index_temp, loc); - Call_expression* call = Runtime::make_call((value_temp == NULL - ? Runtime::STRINGITER - : Runtime::STRINGITER2), - loc, 2, p1, p2); + ref = this->make_range_ref(range_object, range_temp, loc); + index_ref = Expression::make_temporary_reference(index_temp, loc); + ref = Expression::make_string_index(ref, index_ref, NULL, loc); + ref = Expression::make_cast(rune_type, ref, loc); + Temporary_reference_expression* value_ref = + Expression::make_temporary_reference(value_temp, loc); + value_ref->set_is_lvalue(); + s = Statement::make_assignment(value_ref, ref, loc); + iter_init->add_statement(s); - if (value_temp == NULL) - { - ref = Expression::make_temporary_reference(next_index_temp, loc); - ref->set_is_lvalue(); - s = Statement::make_assignment(ref, call, loc); - } - else - { - Expression_list* lhs = new Expression_list(); + value_ref = Expression::make_temporary_reference(value_temp, loc); + Expression* rune_self = Expression::make_integer_ul(0x80, rune_type, loc); + Expression* cond = Expression::make_binary(OPERATOR_LT, value_ref, rune_self, + loc); - ref = Expression::make_temporary_reference(next_index_temp, loc); - ref->set_is_lvalue(); - lhs->push_back(ref); + Block* then_block = new Block(iter_init, loc); - ref = Expression::make_temporary_reference(value_temp, loc); - ref->set_is_lvalue(); - lhs->push_back(ref); + Temporary_reference_expression* lhs = + Expression::make_temporary_reference(next_index_temp, loc); + lhs->set_is_lvalue(); + index_ref = Expression::make_temporary_reference(index_temp, loc); + Expression* one = Expression::make_integer_ul(1, index_temp->type(), loc); + Expression* sum = Expression::make_binary(OPERATOR_PLUS, index_ref, one, + loc); + s = Statement::make_assignment(lhs, sum, loc); + then_block->add_statement(s); - Expression_list* rhs = new Expression_list(); - rhs->push_back(Expression::make_call_result(call, 0)); - rhs->push_back(Expression::make_call_result(call, 1)); + Block* else_block = new Block(iter_init, loc); - s = Statement::make_tuple_assignment(lhs, rhs, loc); - } - iter_init->add_statement(s); + ref = this->make_range_ref(range_object, range_temp, loc); + index_ref = Expression::make_temporary_reference(index_temp, loc); + call = Runtime::make_call(Runtime::DECODERUNE, loc, 2, ref, index_ref); - ref = Expression::make_temporary_reference(next_index_temp, loc); - zexpr = Expression::make_integer_ul(0, NULL, loc); - Expression* equals = Expression::make_binary(OPERATOR_EQEQ, ref, zexpr, loc); + value_ref = Expression::make_temporary_reference(value_temp, loc); + value_ref->set_is_lvalue(); + Expression* res = Expression::make_call_result(call, 0); + s = Statement::make_assignment(value_ref, res, loc); + else_block->add_statement(s); - Block* then_block = new Block(iter_init, loc); - s = Statement::make_break_statement(this->break_label(), loc); - then_block->add_statement(s); + lhs = Expression::make_temporary_reference(next_index_temp, loc); + lhs->set_is_lvalue(); + res = Expression::make_call_result(call, 1); + s = Statement::make_assignment(lhs, res, loc); + else_block->add_statement(s); - s = Statement::make_if_statement(equals, then_block, NULL, loc); + s = Statement::make_if_statement(cond, then_block, else_block, loc); iter_init->add_statement(s); *piter_init = iter_init; @@ -5776,11 +5809,10 @@ For_range_statement::lower_range_string(Gogo*, Block* post = new Block(enclosing, loc); - Temporary_reference_expression* lhs = - Expression::make_temporary_reference(index_temp, loc); - lhs->set_is_lvalue(); - Expression* rhs = Expression::make_temporary_reference(next_index_temp, loc); - s = Statement::make_assignment(lhs, rhs, loc); + index_ref = Expression::make_temporary_reference(index_temp, loc); + index_ref->set_is_lvalue(); + ref = Expression::make_temporary_reference(next_index_temp, loc); + s = Statement::make_assignment(index_ref, ref, loc); post->add_statement(s); *ppost = post; diff --git a/gcc/go/gofrontend/statements.h b/gcc/go/gofrontend/statements.h index 2d395d077ba..dac99de4cae 100644 --- a/gcc/go/gofrontend/statements.h +++ b/gcc/go/gofrontend/statements.h @@ -1500,7 +1500,7 @@ class For_range_statement : public Statement Expression* make_range_ref(Named_object*, Temporary_statement*, Location); - Expression* + Call_expression* call_builtin(Gogo*, const char* funcname, Expression* arg, Location); void diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index ace23d0c27b..0d14adf65b5 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -7319,7 +7319,7 @@ Map_type::do_get_backend(Gogo* gogo) static Btype* backend_map_type; if (backend_map_type == NULL) { - std::vector<Backend::Btyped_identifier> bfields(8); + std::vector<Backend::Btyped_identifier> bfields(9); Location bloc = Linemap::predeclared_location(); @@ -7337,30 +7337,35 @@ Map_type::do_get_backend(Gogo* gogo) bfields[2].btype = bfields[1].btype; bfields[2].location = bloc; - Type* uint32_type = Type::lookup_integer_type("uint32"); - bfields[3].name = "hash0"; - bfields[3].btype = uint32_type->get_backend(gogo); + Type* uint16_type = Type::lookup_integer_type("uint16"); + bfields[3].name = "noverflow"; + bfields[3].btype = uint16_type->get_backend(gogo); bfields[3].location = bloc; - Btype* bvt = gogo->backend()->void_type(); - Btype* bpvt = gogo->backend()->pointer_type(bvt); - bfields[4].name = "buckets"; - bfields[4].btype = bpvt; + Type* uint32_type = Type::lookup_integer_type("uint32"); + bfields[4].name = "hash0"; + bfields[4].btype = uint32_type->get_backend(gogo); bfields[4].location = bloc; - bfields[5].name = "oldbuckets"; + Btype* bvt = gogo->backend()->void_type(); + Btype* bpvt = gogo->backend()->pointer_type(bvt); + bfields[5].name = "buckets"; bfields[5].btype = bpvt; bfields[5].location = bloc; - Type* uintptr_type = Type::lookup_integer_type("uintptr"); - bfields[6].name = "nevacuate"; - bfields[6].btype = uintptr_type->get_backend(gogo); + bfields[6].name = "oldbuckets"; + bfields[6].btype = bpvt; bfields[6].location = bloc; - bfields[7].name = "overflow"; - bfields[7].btype = bpvt; + Type* uintptr_type = Type::lookup_integer_type("uintptr"); + bfields[7].name = "nevacuate"; + bfields[7].btype = uintptr_type->get_backend(gogo); bfields[7].location = bloc; + bfields[8].name = "overflow"; + bfields[8].btype = bpvt; + bfields[8].location = bloc; + Btype *bt = gogo->backend()->struct_type(bfields); bt = gogo->backend()->named_type("runtime.hmap", bt, bloc); backend_map_type = gogo->backend()->pointer_type(bt); |