aboutsummaryrefslogtreecommitdiff
path: root/gcc/go
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/go')
-rw-r--r--gcc/go/go-c.h1
-rw-r--r--gcc/go/go-lang.c1
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/expressions.cc27
-rw-r--r--gcc/go/gofrontend/expressions.h2
-rw-r--r--gcc/go/gofrontend/go.cc2
-rw-r--r--gcc/go/gofrontend/gogo.cc1
-rw-r--r--gcc/go/gofrontend/gogo.h14
-rw-r--r--gcc/go/gofrontend/runtime.def3
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))