diff options
Diffstat (limited to 'gcc/go')
-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/expressions.cc | 27 | ||||
-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 | 1 | ||||
-rw-r--r-- | gcc/go/gofrontend/gogo.h | 14 | ||||
-rw-r--r-- | gcc/go/gofrontend/runtime.def | 3 |
9 files changed, 43 insertions, 10 deletions
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 b6089f3..93aa18c 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -307665073fce992ea8112f74b91954e770afcc70 +c512af85eb8c75a759b5e4fc6b72041fe09b75f1 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 7e7fb8c..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. diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h index a4f892ac..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 4c8c55f..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_(), diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h index 2fb8a3a..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. @@ -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/runtime.def b/gcc/go/gofrontend/runtime.def index a950079..0796cba 100644 --- a/gcc/go/gofrontend/runtime.def +++ b/gcc/go/gofrontend/runtime.def @@ -340,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)) |