diff options
author | Giuliano Belinassi <giuliano.belinassi@usp.br> | 2020-08-22 17:43:43 -0300 |
---|---|---|
committer | Giuliano Belinassi <giuliano.belinassi@usp.br> | 2020-08-22 17:43:43 -0300 |
commit | a926878ddbd5a98b272c22171ce58663fc04c3e0 (patch) | |
tree | 86af256e5d9a9c06263c00adc90e5fe348008c43 /gcc/go | |
parent | 542730f087133690b47e036dfd43eb0db8a650ce (diff) | |
parent | 07cbaed8ba7d1b6e4ab3a9f44175502a4e1ecdb1 (diff) | |
download | gcc-devel/autopar_devel.zip gcc-devel/autopar_devel.tar.gz gcc-devel/autopar_devel.tar.bz2 |
Merge branch 'autopar_rebase2' into autopar_develdevel/autopar_devel
Quickly commit changes in the rebase branch.
Diffstat (limited to 'gcc/go')
-rw-r--r-- | gcc/go/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/go/go-c.h | 1 | ||||
-rw-r--r-- | gcc/go/go-lang.c | 1 | ||||
-rw-r--r-- | gcc/go/gofrontend/MERGE | 2 | ||||
-rw-r--r-- | gcc/go/gofrontend/escape.cc | 29 | ||||
-rw-r--r-- | gcc/go/gofrontend/expressions.cc | 101 | ||||
-rw-r--r-- | gcc/go/gofrontend/expressions.h | 2 | ||||
-rw-r--r-- | gcc/go/gofrontend/go.cc | 2 | ||||
-rw-r--r-- | gcc/go/gofrontend/gogo.cc | 44 | ||||
-rw-r--r-- | gcc/go/gofrontend/gogo.h | 18 | ||||
-rw-r--r-- | gcc/go/gofrontend/names.cc | 11 | ||||
-rw-r--r-- | gcc/go/gofrontend/runtime.def | 16 | ||||
-rw-r--r-- | gcc/go/gofrontend/types.cc | 31 |
13 files changed, 177 insertions, 86 deletions
diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog index 5be05e9..bda9993 100644 --- a/gcc/go/ChangeLog +++ b/gcc/go/ChangeLog @@ -1,3 +1,8 @@ +2020-08-10 Clément Chigot <chigot.c@gmail.com> + + * go-c.h (struct go_create_gogo_args): Add need_eqtype field. + * go-lang.c (go_langhook_init): Set need_eqtype. + 2020-04-15 Ian Lance Taylor <iant@golang.org> PR go/94607 diff --git a/gcc/go/go-c.h b/gcc/go/go-c.h index 7e46f4b..3a005d5 100644 --- a/gcc/go/go-c.h +++ b/gcc/go/go-c.h @@ -50,6 +50,7 @@ struct go_create_gogo_args const char* debug_escape_hash; int64_t nil_check_size_threshold; bool debug_optimization; + bool need_eqtype; }; extern void go_create_gogo (const struct go_create_gogo_args*); diff --git a/gcc/go/go-lang.c b/gcc/go/go-lang.c index 387694e..2cfb410 100644 --- a/gcc/go/go-lang.c +++ b/gcc/go/go-lang.c @@ -119,6 +119,7 @@ go_langhook_init (void) args.debug_escape_hash = go_debug_escape_hash; args.nil_check_size_threshold = TARGET_AIX ? -1 : 4096; args.debug_optimization = go_debug_optimization; + args.need_eqtype = TARGET_AIX ? true : false; args.linemap = go_get_linemap(); args.backend = go_get_backend(); go_create_gogo (&args); diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 5aecee1..e443282 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -761d68dacefc578e45ff299761f20989aef67823 +fe5d94c5792f7f990004c3dee0ea501835512200 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 0d38858..8962f3f 100644 --- a/gcc/go/gofrontend/escape.cc +++ b/gcc/go/gofrontend/escape.cc @@ -142,18 +142,22 @@ Node::ast_format(Gogo* gogo) const else if (this->expr() != NULL) { Expression* e = this->expr(); + bool is_call = e->call_expression() != NULL; if (is_call) - e->call_expression()->fn(); + e = e->call_expression()->fn(); Func_expression* fe = e->func_expression();; - - bool is_closure = fe != NULL && fe->closure() != NULL; - if (is_closure) + if (fe != NULL) { - if (is_call) - return "(func literal)()"; - return "func literal"; + Named_object* no = fe->named_object(); + if (no->is_function() && no->func_value()->enclosing() != NULL) + { + if (is_call) + return "(func literal)()"; + return "func literal"; + } } + Ast_dump_context::dump_to_stream(this->expr(), &ss); } else if (this->statement() != NULL) @@ -1172,11 +1176,14 @@ Escape_discover_expr::expression(Expression** pexpr) // Method call or function call. fn = e->call_expression()->fn()->func_expression()->named_object(); } - else if (e->func_expression() != NULL - && e->func_expression()->closure() != NULL) + else if (e->func_expression() != NULL) { - // Closure. - fn = e->func_expression()->named_object(); + Named_object* no = e->func_expression()->named_object(); + if (no->is_function() && no->func_value()->enclosing() != NULL) + { + // Nested function. + fn = no; + } } if (fn != NULL) diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index deac874..d295fd1 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -208,7 +208,7 @@ Expression::is_same_variable(Expression* a, Expression* b) // assignment. Expression* -Expression::convert_for_assignment(Gogo*, Type* lhs_type, +Expression::convert_for_assignment(Gogo* gogo, Type* lhs_type, Expression* rhs, Location location) { Type* rhs_type = rhs->type(); @@ -229,7 +229,7 @@ Expression::convert_for_assignment(Gogo*, Type* lhs_type, location); } else if (!are_identical && rhs_type->interface_type() != NULL) - return Expression::convert_interface_to_type(lhs_type, rhs, location); + return Expression::convert_interface_to_type(gogo, lhs_type, rhs, location); else if (lhs_type->is_slice_type() && rhs_type->is_nil_type()) { // Assigning nil to a slice. @@ -498,7 +498,7 @@ Expression::convert_interface_to_interface(Type *lhs_type, Expression* rhs, // non-interface type. Expression* -Expression::convert_interface_to_type(Type *lhs_type, Expression* rhs, +Expression::convert_interface_to_type(Gogo* gogo, Type *lhs_type, Expression* rhs, Location location) { // We are going to evaluate RHS multiple times. @@ -507,8 +507,11 @@ Expression::convert_interface_to_type(Type *lhs_type, Expression* rhs, // Build an expression to check that the type is valid. It will // panic with an appropriate runtime type error if the type is not // valid. - // (lhs_type != rhs_type ? panicdottype(lhs_type, rhs_type, inter_type) : - // nil /*dummy*/) + // (lhs_type == rhs_type ? nil /*dummy*/ : + // panicdottype(lhs_type, rhs_type, inter_type)) + // For some Oses, we need to call runtime.eqtype instead of + // lhs_type == rhs_type, as we may have unmerged type descriptors + // from shared libraries. Expression* lhs_type_expr = Expression::make_type_descriptor(lhs_type, location); Expression* rhs_descriptor = @@ -518,15 +521,23 @@ Expression::convert_interface_to_type(Type *lhs_type, Expression* rhs, Expression* rhs_inter_expr = Expression::make_type_descriptor(rhs_type, location); - Expression* cond = Expression::make_binary(OPERATOR_NOTEQ, lhs_type_expr, - rhs_descriptor, location); + Expression* cond; + if (gogo->need_eqtype()) { + cond = Runtime::make_call(Runtime::EQTYPE, location, + 2, lhs_type_expr, + rhs_descriptor); + } else { + cond = Expression::make_binary(OPERATOR_EQEQ, lhs_type_expr, + rhs_descriptor, location); + } + rhs_descriptor = Expression::get_interface_type_descriptor(rhs); Expression* panic = Runtime::make_call(Runtime::PANICDOTTYPE, location, 3, lhs_type_expr->copy(), rhs_descriptor, rhs_inter_expr); Expression* nil = Expression::make_nil(location); - Expression* check = Expression::make_conditional(cond, panic, nil, + Expression* check = Expression::make_conditional(cond, nil, panic, location); // If the conversion succeeds, pull out the value. @@ -556,7 +567,10 @@ Expression::get_backend(Translate_context* context) { // The child may have marked this expression as having an error. if (this->classification_ == EXPRESSION_ERROR) - return context->backend()->error_expression(); + { + go_assert(saw_errors()); + return context->backend()->error_expression(); + } return this->do_get_backend(context); } @@ -4157,45 +4171,43 @@ Type_conversion_expression::do_get_backend(Translate_context* context) go_assert(e->integer_type() != NULL); go_assert(this->expr_->is_variable()); - Runtime::Function code; + Expression* buf; + if (this->no_escape_ && !this->no_copy_) + { + Type* byte_type = Type::lookup_integer_type("uint8"); + Expression* buflen = + Expression::make_integer_ul(tmp_string_buf_size, NULL, loc); + Type* array_type = Type::make_array_type(byte_type, buflen); + buf = Expression::make_allocation(array_type, loc); + buf->allocation_expression()->set_allocate_on_stack(); + buf->allocation_expression()->set_no_zero(); + } + else + buf = Expression::make_nil(loc); + if (e->integer_type()->is_byte()) { + Expression* ptr = + Expression::make_slice_info(this->expr_, SLICE_INFO_VALUE_POINTER, + loc); + Expression* len = + Expression::make_slice_info(this->expr_, SLICE_INFO_LENGTH, loc); if (this->no_copy_) { if (gogo->debug_optimization()) go_debug(loc, "no copy string([]byte)"); - Expression* ptr = Expression::make_slice_info(this->expr_, - SLICE_INFO_VALUE_POINTER, - loc); - Expression* len = Expression::make_slice_info(this->expr_, - SLICE_INFO_LENGTH, - loc); Expression* str = Expression::make_string_value(ptr, len, loc); return str->get_backend(context); } - code = Runtime::SLICEBYTETOSTRING; + return Runtime::make_call(Runtime::SLICEBYTETOSTRING, loc, 3, buf, + ptr, len)->get_backend(context); } else { go_assert(e->integer_type()->is_rune()); - code = Runtime::SLICERUNETOSTRING; - } - - Expression* buf; - if (this->no_escape_) - { - Type* byte_type = Type::lookup_integer_type("uint8"); - Expression* buflen = - Expression::make_integer_ul(tmp_string_buf_size, NULL, loc); - Type* array_type = Type::make_array_type(byte_type, buflen); - buf = Expression::make_allocation(array_type, loc); - buf->allocation_expression()->set_allocate_on_stack(); - buf->allocation_expression()->set_no_zero(); - } - else - buf = Expression::make_nil(loc); - return Runtime::make_call(code, loc, 2, buf, - this->expr_)->get_backend(context); + return Runtime::make_call(Runtime::SLICERUNETOSTRING, loc, 2, buf, + this->expr_)->get_backend(context); + } } else if (type->is_slice_type() && expr_type->is_string_type()) { @@ -6041,10 +6053,7 @@ Binary_expression::do_lower(Gogo* gogo, Named_object*, &right_nc, location, &result)) return this; - return Expression::make_cast(Type::make_boolean_type(), - Expression::make_boolean(result, - location), - location); + return Expression::make_boolean(result, location); } else { @@ -6085,6 +6094,8 @@ Binary_expression::do_lower(Gogo* gogo, Named_object*, Type* result_type = (left->type()->named_type() != NULL ? left->type() : right->type()); + delete left; + delete right; return Expression::make_string_typed(left_string + right_string, result_type, location); } @@ -6092,6 +6103,8 @@ Binary_expression::do_lower(Gogo* gogo, Named_object*, { int cmp = left_string.compare(right_string); bool r = Binary_expression::cmp_to_bool(op, cmp); + delete left; + delete right; return Expression::make_boolean(r, location); } } @@ -8400,8 +8413,16 @@ Builtin_call_expression::do_flatten(Gogo* gogo, Named_object* function, if (et->has_pointer()) { Expression* td = Expression::make_type_descriptor(et, loc); + Expression* pd = + Expression::make_slice_info(arg1, SLICE_INFO_VALUE_POINTER, loc); + Expression* ld = + Expression::make_slice_info(arg1, SLICE_INFO_LENGTH, loc); + Expression* ps = + Expression::make_slice_info(arg2, SLICE_INFO_VALUE_POINTER, loc); + Expression* ls = + Expression::make_slice_info(arg2, SLICE_INFO_LENGTH, loc); ret = Runtime::make_call(Runtime::TYPEDSLICECOPY, loc, - 3, td, arg1, arg2); + 5, td, pd, ld, ps, ls); } else { diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h index a4f892a..acb2732 100644 --- a/gcc/go/gofrontend/expressions.h +++ b/gcc/go/gofrontend/expressions.h @@ -1273,7 +1273,7 @@ class Expression } static Expression* - convert_interface_to_type(Type*, Expression*, Location); + convert_interface_to_type(Gogo*, Type*, Expression*, Location); static Expression* import_identifier(Import_function_body*, Location); diff --git a/gcc/go/gofrontend/go.cc b/gcc/go/gofrontend/go.cc index 12205bd..e026d65 100644 --- a/gcc/go/gofrontend/go.cc +++ b/gcc/go/gofrontend/go.cc @@ -46,6 +46,8 @@ go_create_gogo(const struct go_create_gogo_args* args) ::gogo->set_nil_check_size_threshold(args->nil_check_size_threshold); if (args->debug_optimization) ::gogo->set_debug_optimization(args->debug_optimization); + if (args->need_eqtype) + ::gogo->set_need_eqtype(args->need_eqtype); } // Parse the input files. diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index 212ef45..13de74b 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -57,6 +57,7 @@ Gogo::Gogo(Backend* backend, Linemap* linemap, int, int pointer_size) debug_escape_level_(0), debug_optimization_(false), nil_check_size_threshold_(4096), + need_eqtype_(false), verify_types_(), interface_types_(), specific_type_functions_(), @@ -1622,16 +1623,31 @@ Gogo::write_globals() // The initializer is constant if it is the zero-value of the // variable's type or if the initial value is an immutable value // that is not copied to the heap. - bool is_static_initializer = false; - if (var->init() == NULL) + Expression* init = var->init(); + + // If we see "a = b; b = x", and x is a static + // initializer, just set a to x. + while (init != NULL && init->var_expression() != NULL) + { + Named_object* ino = init->var_expression()->named_object(); + if (!ino->is_variable() || ino->package() != NULL) + break; + Expression* ino_init = ino->var_value()->init(); + if (ino->var_value()->has_pre_init() + || ino_init == NULL + || !ino_init->is_static_initializer()) + break; + init = ino_init; + } + + bool is_static_initializer; + if (init == NULL) is_static_initializer = true; else { Type* var_type = var->type(); - Expression* init = var->init(); - Expression* init_cast = - Expression::make_cast(var_type, init, var->location()); - is_static_initializer = init_cast->is_static_initializer(); + init = Expression::make_cast(var_type, init, var->location()); + is_static_initializer = init->is_static_initializer(); } // Non-constant variable initializations might need to create @@ -1650,7 +1666,15 @@ Gogo::write_globals() } var_init_fn = init_fndecl; } - Bexpression* var_binit = var->get_init(this, var_init_fn); + + Bexpression* var_binit; + if (init == NULL) + var_binit = NULL; + else + { + Translate_context context(this, var_init_fn, NULL, NULL); + var_binit = init->get_backend(&context); + } if (var_binit == NULL) ; @@ -3309,7 +3333,11 @@ Remove_deadcode::expression(Expression** pexpr) && be->boolean_constant_value(&bval) && (be->op() == OPERATOR_ANDAND || be->op() == OPERATOR_OROR)) - *pexpr = Expression::make_boolean(bval, be->location()); + { + *pexpr = Expression::make_boolean(bval, be->location()); + Type_context context(NULL, false); + (*pexpr)->determine_type(&context); + } return TRAVERSE_CONTINUE; } diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h index 7d83119..45be173 100644 --- a/gcc/go/gofrontend/gogo.h +++ b/gcc/go/gofrontend/gogo.h @@ -360,6 +360,17 @@ class Gogo set_nil_check_size_threshold(int64_t bytes) { this->nil_check_size_threshold_ = bytes; } + // Return whether runtime.eqtype calls are needed when comparing + // type descriptors. + bool + need_eqtype() const + { return this->need_eqtype_; } + + // Set if calls to runtime.eqtype are needed. + void + set_need_eqtype(bool b) + { this->need_eqtype_ = b; } + // Import a package. FILENAME is the file name argument, LOCAL_NAME // is the local name to give to the package. If LOCAL_NAME is empty // the declarations are added to the global scope. @@ -958,7 +969,7 @@ class Gogo // Return the name of the type descriptor list symbol of a package. std::string - type_descriptor_list_symbol(std::string); + type_descriptor_list_symbol(const std::string&); // Return the name of the list of all type descriptor lists. std::string @@ -1073,7 +1084,7 @@ class Gogo Specific_type_function(Type* atype, Named_type* aname, int64_t asize, Specific_type_function_kind akind, - const std::string afnname, + const std::string& afnname, Function_type* afntype) : type(atype), name(aname), size(asize), kind(akind), fnname(afnname), fntype(afntype) @@ -1161,6 +1172,9 @@ class Gogo bool debug_optimization_; // Nil-check size threshhold. int64_t nil_check_size_threshold_; + // Whether runtime.eqtype calls are needed when comparing type + // descriptors. + bool need_eqtype_; // A list of types to verify. std::vector<Type*> verify_types_; // A list of interface types defined while parsing. diff --git a/gcc/go/gofrontend/names.cc b/gcc/go/gofrontend/names.cc index f4ad1815..1f0a545 100644 --- a/gcc/go/gofrontend/names.cc +++ b/gcc/go/gofrontend/names.cc @@ -975,7 +975,14 @@ Gogo::type_descriptor_name(const Type* type, Named_type* nt) return "unsafe.Pointer..d"; if (nt == NULL) - return "type.." + type->mangled_name(this); + { + // Sanity check: we should never generate a type descriptor for + // an unnamed primitive type. For those we should always be + // using a named type, like "int". + go_assert(!type->is_basic_type()); + + return "type.." + type->mangled_name(this); + } std::string ret; Named_object* no = nt->named_object(); @@ -1024,7 +1031,7 @@ Gogo::type_descriptor_name(const Type* type, Named_type* nt) // Return the name of the type descriptor list symbol of a package. std::string -Gogo::type_descriptor_list_symbol(std::string pkgpath) +Gogo::type_descriptor_list_symbol(const std::string& pkgpath) { return pkgpath + "..types"; } diff --git a/gcc/go/gofrontend/runtime.def b/gcc/go/gofrontend/runtime.def index 2ef0f94..0796cba 100644 --- a/gcc/go/gofrontend/runtime.def +++ b/gcc/go/gofrontend/runtime.def @@ -47,7 +47,7 @@ DEF_GO_RUNTIME(INTSTRING, "runtime.intstring", P2(POINTER, INT64), R1(STRING)) // Convert a []byte to a string. DEF_GO_RUNTIME(SLICEBYTETOSTRING, "runtime.slicebytetostring", - P2(POINTER, SLICE), R1(STRING)) + P3(POINTER, POINTER, INT), R1(STRING)) // Convert a []rune to a string. DEF_GO_RUNTIME(SLICERUNETOSTRING, "runtime.slicerunetostring", @@ -249,17 +249,16 @@ DEF_GO_RUNTIME(CLOSE, "runtime.closechan", P1(CHAN), R0()) // Copy. -DEF_GO_RUNTIME(SLICECOPY, "runtime.slicecopy", P3(SLICE, SLICE, UINTPTR), - R1(INT)) +DEF_GO_RUNTIME(SLICECOPY, "runtime.slicecopy", + P5(POINTER, INT, POINTER, INT, UINTPTR), R1(INT)) // Copy from string. -DEF_GO_RUNTIME(SLICESTRINGCOPY, "runtime.slicestringcopy", P2(SLICE, STRING), - R1(INT)) +DEF_GO_RUNTIME(SLICESTRINGCOPY, "runtime.slicestringcopy", + P3(POINTER, INT, STRING), R1(INT)) // Copy of value containing pointers. DEF_GO_RUNTIME(TYPEDSLICECOPY, "runtime.typedslicecopy", - P3(TYPE, SLICE, SLICE), R1(INT)) - + P5(TYPE, POINTER, INT, POINTER, INT), R1(INT)) // Grow a slice for append. DEF_GO_RUNTIME(GROWSLICE, "runtime.growslice", @@ -341,6 +340,9 @@ DEF_GO_RUNTIME(PANICDOTTYPE, "runtime.panicdottype", P3(TYPE, TYPE, TYPE), // Return whether we can convert a type to an interface type. DEF_GO_RUNTIME(IFACET2IP, "runtime.ifaceT2Ip", P2(TYPE, TYPE), R1(BOOL)) +// Compare two type descriptors for equality. +DEF_GO_RUNTIME(EQTYPE, "runtime.eqtype", P2(TYPE, TYPE), R1(BOOL)) + // Compare two empty interface values. DEF_GO_RUNTIME(EFACEEQ, "runtime.efaceeq", P2(EFACE, EFACE), R1(BOOL)) diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index d6cd326..7f65b4a 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -9208,6 +9208,7 @@ Interface_type::implements_interface(const Type* t, std::string* reason) const if (this->all_methods_ == NULL) return true; + t = t->unalias(); bool is_pointer = false; const Named_type* nt = t->named_type(); const Struct_type* st = t->struct_type(); @@ -9220,6 +9221,7 @@ Interface_type::implements_interface(const Type* t, std::string* reason) const { // If T is a pointer to a named type, then we need to look at // the type to which it points. + pt = pt->unalias(); is_pointer = true; nt = pt->named_type(); st = pt->struct_type(); @@ -10408,19 +10410,24 @@ Named_type::interface_method_table(Interface_type* interface, bool is_pointer) return Expression::make_error(this->location_); if (this->is_alias_) { - if (this->type_->named_type() != NULL) + Type* t = this->type_; + if (!is_pointer && t->points_to() != NULL) + { + t = t->points_to(); + is_pointer = true; + } + if (t->named_type() != NULL) { if (this->seen_alias_) return Expression::make_error(this->location_); this->seen_alias_ = true; - Named_type* nt = this->type_->named_type(); + Named_type* nt = t->named_type(); Expression* ret = nt->interface_method_table(interface, is_pointer); this->seen_alias_ = false; return ret; } - if (this->type_->struct_type() != NULL) - return this->type_->struct_type()->interface_method_table(interface, - is_pointer); + if (t->struct_type() != NULL) + return t->struct_type()->interface_method_table(interface, is_pointer); go_unreachable(); } return Type::interface_method_table(this, interface, is_pointer, @@ -11106,15 +11113,11 @@ Named_type::do_type_descriptor(Gogo* gogo, Named_type* name) { if (this->is_error_) return Expression::make_error(this->location_); - if (name == NULL && this->is_alias_) - { - if (this->seen_alias_) - return Expression::make_error(this->location_); - this->seen_alias_ = true; - Expression* ret = this->type_->type_descriptor(gogo, NULL); - this->seen_alias_ = false; - return ret; - } + + // We shouldn't see unnamed type aliases here. They should have + // been removed by the call to unalias in Type::type_descriptor_pointer. + // We can see named type aliases via Type::named_type_descriptor. + go_assert(name != NULL || !this->is_alias_); // If NAME is not NULL, then we don't really want the type // descriptor for this type; we want the descriptor for the |