diff options
Diffstat (limited to 'gcc/go')
-rw-r--r-- | gcc/go/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/go/go-backend.c | 8 | ||||
-rw-r--r-- | gcc/go/gofrontend/MERGE | 2 | ||||
-rw-r--r-- | gcc/go/gofrontend/expressions.cc | 194 | ||||
-rw-r--r-- | gcc/go/gofrontend/expressions.h | 18 | ||||
-rw-r--r-- | gcc/go/gofrontend/gogo.cc | 2 | ||||
-rw-r--r-- | gcc/go/gofrontend/types.cc | 51 | ||||
-rw-r--r-- | gcc/go/gofrontend/types.h | 12 |
8 files changed, 148 insertions, 144 deletions
diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog index ac0dbe3f99d..1925111f169 100644 --- a/gcc/go/ChangeLog +++ b/gcc/go/ChangeLog @@ -1,3 +1,8 @@ +2017-07-27 Tony Reix <tony.reix@atos.net> + + * go-backend.c (go_write_export_data): Use EXCLUDE section for + AIX. + 2017-06-09 Ian Lance Taylor <iant@golang.org> * go-lang.c (go_langhook_post_options): If -fsplit-stack is turned diff --git a/gcc/go/go-backend.c b/gcc/go/go-backend.c index 2f8d2f405da..21277ea2eb9 100644 --- a/gcc/go/go-backend.c +++ b/gcc/go/go-backend.c @@ -45,6 +45,10 @@ along with GCC; see the file COPYING3. If not see #define GO_EXPORT_SECTION_NAME ".go_export" #endif +#ifndef TARGET_AIX +#define TARGET_AIX 0 +#endif + /* This file holds all the cases where the Go frontend needs information from gcc's backend. */ @@ -101,7 +105,9 @@ go_write_export_data (const char *bytes, unsigned int size) if (sec == NULL) { gcc_assert (targetm_common.have_named_sections); - sec = get_section (GO_EXPORT_SECTION_NAME, SECTION_DEBUG, NULL); + sec = get_section (GO_EXPORT_SECTION_NAME, + TARGET_AIX ? SECTION_EXCLUDE : SECTION_DEBUG, + NULL); } switch_to_section (sec); diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 416a5876da8..685cff9935b 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -0a20181d00d43a423c55f4e772b759fba0619478 +f7c36b27a49131f60eedde260896d310d735d408 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 12505b23939..eb23ec26ecf 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -1204,7 +1204,14 @@ Func_expression::do_get_backend(Translate_context* context) // expression. It is a pointer to a struct whose first field points // to the function code and whose remaining fields are the addresses // of the closed-over variables. - return this->closure_->get_backend(context); + Bexpression *bexpr = this->closure_->get_backend(context); + + // Introduce a backend type conversion, to account for any differences + // between the argument type (function descriptor, struct with a + // single field) and the closure (struct with multiple fields). + Gogo* gogo = context->gogo(); + Btype *btype = this->type()->get_backend(gogo); + return gogo->backend()->convert_expression(btype, bexpr, this->location()); } // Ast dump for function. @@ -9456,24 +9463,28 @@ Call_expression::do_lower(Gogo* gogo, Named_object* function, this->is_varargs_, loc); // If this call returns multiple results, create a temporary - // variable for each result. - size_t rc = this->result_count(); - if (rc > 1 && this->results_ == NULL) + // variable to hold them. + if (this->result_count() > 1 && this->call_temp_ == NULL) { - std::vector<Temporary_statement*>* temps = - new std::vector<Temporary_statement*>; - temps->reserve(rc); + Struct_field_list* sfl = new Struct_field_list(); + Function_type* fntype = this->get_function_type(); const Typed_identifier_list* results = fntype->results(); + Location loc = this->location(); + + int i = 0; + char buf[20]; for (Typed_identifier_list::const_iterator p = results->begin(); - p != results->end(); - ++p) - { - Temporary_statement* temp = Statement::make_temporary(p->type(), - NULL, loc); - inserter->insert(temp); - temps->push_back(temp); - } - this->results_ = temps; + p != results->end(); + ++p, ++i) + { + snprintf(buf, sizeof buf, "res%d", i); + sfl->push_back(Struct_field(Typed_identifier(buf, p->type(), loc))); + } + + Struct_type* st = Type::make_struct_type(sfl, loc); + st->set_is_struct_incomparable(); + this->call_temp_ = Statement::make_temporary(st, NULL, loc); + inserter->insert(this->call_temp_); } // Handle a call to a varargs function by packaging up the extra @@ -9772,30 +9783,6 @@ Call_expression::do_flatten(Gogo* gogo, Named_object*, this->args_ = args; } - size_t rc = this->result_count(); - if (rc > 1 && this->call_temp_ == NULL) - { - Struct_field_list* sfl = new Struct_field_list(); - Function_type* fntype = this->get_function_type(); - const Typed_identifier_list* results = fntype->results(); - Location loc = this->location(); - - int i = 0; - char buf[20]; - for (Typed_identifier_list::const_iterator p = results->begin(); - p != results->end(); - ++p, ++i) - { - snprintf(buf, sizeof buf, "res%d", i); - sfl->push_back(Struct_field(Typed_identifier(buf, p->type(), loc))); - } - - Struct_type* st = Type::make_struct_type(sfl, loc); - st->set_is_struct_incomparable(); - this->call_temp_ = Statement::make_temporary(st, NULL, loc); - inserter->insert(this->call_temp_); - } - return this; } @@ -9820,17 +9807,18 @@ Call_expression::result_count() const return fntype->results()->size(); } -// Return the temporary which holds a result. +// Return the temporary that holds the result for a call with multiple +// results. Temporary_statement* -Call_expression::result(size_t i) const +Call_expression::results() const { - if (this->results_ == NULL || this->results_->size() <= i) + if (this->call_temp_ == NULL) { go_assert(saw_errors()); return NULL; } - return (*this->results_)[i]; + return this->call_temp_; } // Set the number of results expected from a call expression. @@ -10184,8 +10172,21 @@ Call_expression::interface_method_function( Bexpression* Call_expression::do_get_backend(Translate_context* context) { + Location location = this->location(); + if (this->call_ != NULL) - return this->call_; + { + // If the call returns multiple results, make a new reference to + // the temporary. + if (this->call_temp_ != NULL) + { + Expression* ref = + Expression::make_temporary_reference(this->call_temp_, location); + return ref->get_backend(context); + } + + return this->call_; + } Function_type* fntype = this->get_function_type(); if (fntype == NULL) @@ -10195,7 +10196,6 @@ Call_expression::do_get_backend(Translate_context* context) return context->backend()->error_expression(); Gogo* gogo = context->gogo(); - Location location = this->location(); Func_expression* func = this->fn_->func_expression(); Interface_field_reference_expression* interface_method = @@ -10316,91 +10316,28 @@ Call_expression::do_get_backend(Translate_context* context) fn_args, bclosure, location); - if (this->results_ != NULL) + if (this->call_temp_ != NULL) { - Bexpression* bcall_ref = this->call_result_ref(context); - Bstatement* assn_stmt = - gogo->backend()->assignment_statement(bfunction, - bcall_ref, call, location); + // This case occurs when the call returns multiple results. - this->call_ = this->set_results(context); + Expression* ref = Expression::make_temporary_reference(this->call_temp_, + location); + Bexpression* bref = ref->get_backend(context); + Bstatement* bassn = gogo->backend()->assignment_statement(bfunction, + bref, call, + location); - Bexpression* set_and_call = - gogo->backend()->compound_expression(assn_stmt, this->call_, - location); - return set_and_call; + ref = Expression::make_temporary_reference(this->call_temp_, location); + this->call_ = ref->get_backend(context); + + return gogo->backend()->compound_expression(bassn, this->call_, + location); } this->call_ = call; return this->call_; } -// Return the backend representation of a reference to the struct used -// to capture the result of a multiple-output call. - -Bexpression* -Call_expression::call_result_ref(Translate_context* context) -{ - go_assert(this->call_temp_ != NULL); - Location location = this->location(); - Expression* call_ref = - Expression::make_temporary_reference(this->call_temp_, location); - Bexpression* bcall_ref = call_ref->get_backend(context); - return bcall_ref; -} - -// Set the result variables if this call returns multiple results. - -Bexpression* -Call_expression::set_results(Translate_context* context) -{ - Gogo* gogo = context->gogo(); - - Bexpression* results = NULL; - Location loc = this->location(); - - go_assert(this->call_temp_ != NULL); - - size_t rc = this->result_count(); - for (size_t i = 0; i < rc; ++i) - { - Temporary_statement* temp = this->result(i); - if (temp == NULL) - { - go_assert(saw_errors()); - return gogo->backend()->error_expression(); - } - Temporary_reference_expression* ref = - Expression::make_temporary_reference(temp, loc); - ref->set_is_lvalue(); - - Bfunction* bfunction = context->function()->func_value()->get_decl(); - Bexpression* result_ref = ref->get_backend(context); - Bexpression* bcall_ref = this->call_result_ref(context); - Bexpression* call_result = - gogo->backend()->struct_field_expression(bcall_ref, i, loc); - Bstatement* assn_stmt = - gogo->backend()->assignment_statement(bfunction, - result_ref, call_result, loc); - - bcall_ref = this->call_result_ref(context); - call_result = gogo->backend()->struct_field_expression(bcall_ref, i, loc); - Bexpression* result = - gogo->backend()->compound_expression(assn_stmt, call_result, loc); - - if (results == NULL) - results = result; - else - { - Bstatement* expr_stmt = - gogo->backend()->expression_statement(bfunction, result); - results = - gogo->backend()->compound_expression(expr_stmt, results, loc); - } - } - return results; -} - // Dump ast representation for a call expressin. void @@ -10521,13 +10458,14 @@ Call_result_expression::do_get_backend(Translate_context* context) go_assert(this->call_->is_error_expression()); return context->backend()->error_expression(); } - Temporary_statement* ts = ce->result(this->index_); + Temporary_statement* ts = ce->results(); if (ts == NULL) { go_assert(saw_errors()); return context->backend()->error_expression(); } Expression* ref = Expression::make_temporary_reference(ts, this->location()); + ref = Expression::make_field_reference(ref, this->index_, this->location()); return ref->get_backend(context); } @@ -12119,12 +12057,15 @@ Interface_field_reference_expression::do_get_backend(Translate_context* context) Bexpression* bclosure = Expression::make_heap_expression(expr, loc)->get_backend(context); + Gogo* gogo = context->gogo(); + Btype* btype = this->type()->get_backend(gogo); + bclosure = gogo->backend()->convert_expression(btype, bclosure, loc); + Expression* nil_check = Expression::make_binary(OPERATOR_EQEQ, this->expr_, Expression::make_nil(loc), loc); Bexpression* bnil_check = nil_check->get_backend(context); - Gogo* gogo = context->gogo(); Bexpression* bcrash = gogo->runtime_error(RUNTIME_ERROR_NIL_DEREFERENCE, loc)->get_backend(context); @@ -14300,7 +14241,10 @@ Type_guard_expression::do_get_backend(Translate_context* context) Expression::convert_for_assignment(context->gogo(), this->type_, this->expr_, this->location()); - return conversion->get_backend(context); + Gogo* gogo = context->gogo(); + Btype* bt = this->type_->get_backend(gogo); + Bexpression* bexpr = conversion->get_backend(context); + return gogo->backend()->convert_expression(bt, bexpr, this->location()); } // Dump ast representation for a type guard expression. diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h index a144ff4168b..0c742fd92df 100644 --- a/gcc/go/gofrontend/expressions.h +++ b/gcc/go/gofrontend/expressions.h @@ -2115,8 +2115,8 @@ class Call_expression : public Expression Call_expression(Expression* fn, Expression_list* args, bool is_varargs, Location location) : Expression(EXPRESSION_CALL, location), - fn_(fn), args_(args), type_(NULL), results_(NULL), call_(NULL), - call_temp_(NULL), expected_result_count_(0), is_varargs_(is_varargs), + fn_(fn), args_(args), type_(NULL), call_(NULL), call_temp_(NULL) + , expected_result_count_(0), is_varargs_(is_varargs), varargs_are_lowered_(false), types_are_determined_(false), is_deferred_(false), is_concurrent_(false), issued_error_(false), is_multi_value_arg_(false), is_flattened_(false) @@ -2144,11 +2144,11 @@ class Call_expression : public Expression size_t result_count() const; - // Return the temporary variable which holds result I. This is only - // valid after the expression has been lowered, and is only valid - // for calls which return multiple results. + // Return the temporary variable that holds the results. This is + // only valid after the expression has been lowered, and is only + // valid for calls which return multiple results. Temporary_statement* - result(size_t i) const; + results() const; // Set the number of results expected from this call. This is used // when the call appears in a context that expects multiple results, @@ -2292,9 +2292,6 @@ class Call_expression : public Expression Bexpression* set_results(Translate_context*); - Bexpression* - call_result_ref(Translate_context* context); - // The function to call. Expression* fn_; // The arguments to pass. This may be NULL if there are no @@ -2302,9 +2299,6 @@ class Call_expression : public Expression Expression_list* args_; // The type of the expression, to avoid recomputing it. Type* type_; - // The list of temporaries which will hold the results if the - // function returns a tuple. - std::vector<Temporary_statement*>* results_; // The backend expression for the call, used for a call which returns a tuple. Bexpression* call_; // A temporary variable to store this call if the function returns a tuple. diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index a9d72ff4aa0..ca4b454a238 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -4824,6 +4824,8 @@ Gogo::convert_named_types() Runtime::convert_types(this); this->named_types_are_converted_ = true; + + Type::finish_pointer_types(this); } // Convert all names types in a set of bindings. diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index b2756fde048..4d923733667 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -1057,6 +1057,8 @@ Type::get_backend_placeholder(Gogo* gogo) { Location loc = Linemap::unknown_location(); bt = gogo->backend()->placeholder_pointer_type("", loc, false); + Pointer_type* pt = this->convert<Pointer_type, TYPE_POINTER>(); + Type::placeholder_pointers.push_back(pt); } break; @@ -5516,14 +5518,22 @@ Pointer_type::do_import(Import* imp) return Type::make_pointer_type(to); } +// Cache of pointer types. Key is "to" type, value is pointer type +// that points to key. + +Type::Pointer_type_table Type::pointer_types; + +// A list of placeholder pointer types. We keep this so we can ensure +// they are finalized. + +std::vector<Pointer_type*> Type::placeholder_pointers; + // Make a pointer type. Pointer_type* Type::make_pointer_type(Type* to_type) { - typedef Unordered_map(Type*, Pointer_type*) Hashtable; - static Hashtable pointer_types; - Hashtable::const_iterator p = pointer_types.find(to_type); + Pointer_type_table::const_iterator p = pointer_types.find(to_type); if (p != pointer_types.end()) return p->second; Pointer_type* ret = new Pointer_type(to_type); @@ -5531,6 +5541,37 @@ Type::make_pointer_type(Type* to_type) return ret; } +// This helper is invoked immediately after named types have been +// converted, to clean up any unresolved pointer types remaining in +// the pointer type cache. +// +// The motivation for this routine: occasionally the compiler creates +// some specific pointer type as part of a lowering operation (ex: +// pointer-to-void), then Type::backend_type_size() is invoked on the +// type (which creates a Btype placeholder for it), that placeholder +// passed somewhere along the line to the back end, but since there is +// no reference to the type in user code, there is never a call to +// Type::finish_backend for the type (hence the Btype remains as an +// unresolved placeholder). Calling this routine will clean up such +// instances. + +void +Type::finish_pointer_types(Gogo* gogo) +{ + // We don't use begin() and end() because it is possible to add new + // placeholder pointer types as we finalized existing ones. + for (size_t i = 0; i < Type::placeholder_pointers.size(); i++) + { + Pointer_type* pt = Type::placeholder_pointers[i]; + Type_btypes::iterator tbti = Type::type_btypes.find(pt); + if (tbti != Type::type_btypes.end() && tbti->second.is_placeholder) + { + pt->finish_backend(gogo, tbti->second.btype); + tbti->second.is_placeholder = false; + } + } +} + // The nil type. We use a special type for nil because it is not the // same as any other type. In C term nil has type void*, but there is // no such type in Go. @@ -10994,13 +11035,13 @@ Named_type::do_get_backend(Gogo* gogo) if (this->seen_in_get_backend_) { this->is_circular_ = true; - return gogo->backend()->circular_pointer_type(bt, false); + return gogo->backend()->circular_pointer_type(bt, true); } this->seen_in_get_backend_ = true; bt1 = Type::get_named_base_btype(gogo, base); this->seen_in_get_backend_ = false; if (this->is_circular_) - bt1 = gogo->backend()->circular_pointer_type(bt, false); + bt1 = gogo->backend()->circular_pointer_type(bt, true); if (!gogo->backend()->set_placeholder_pointer_type(bt, bt1)) bt = gogo->backend()->error_type(); return bt; diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h index aeb04d6c50f..f15f08ae4f0 100644 --- a/gcc/go/gofrontend/types.h +++ b/gcc/go/gofrontend/types.h @@ -504,6 +504,9 @@ class Type static Pointer_type* make_pointer_type(Type*); + static void + finish_pointer_types(Gogo* gogo); + static Type* make_nil_type(); @@ -1341,6 +1344,15 @@ class Type static Type_functions type_functions_table; + // Cache for reusing existing pointer types; maps from pointed-to-type + // to pointer type. + typedef Unordered_map(Type*, Pointer_type*) Pointer_type_table; + + static Pointer_type_table pointer_types; + + // List of placeholder pointer types. + static std::vector<Pointer_type*> placeholder_pointers; + // The type classification. Type_classification classification_; // The backend representation of the type, once it has been |