aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorClément Chigot <chigot.c@gmail.com>2020-05-29 11:39:42 +0200
committerIan Lance Taylor <iant@golang.org>2020-08-10 16:45:16 -0700
commitf4b9b136808c31118c52c0addafb3fd323484d1b (patch)
treecc518ef3fc753c719afdcd1c2eb5476188f3c027 /gcc
parent636686662326496f68451e7eb91882fe462f850a (diff)
downloadgcc-f4b9b136808c31118c52c0addafb3fd323484d1b.zip
gcc-f4b9b136808c31118c52c0addafb3fd323484d1b.tar.gz
gcc-f4b9b136808c31118c52c0addafb3fd323484d1b.tar.bz2
runtime: revert eqtype for AIX
AIX linker is not able to merge identical type descriptors in a single symbol if there are coming from different object or shared object files. This results into several pointers referencing the same type descriptors. Thus, eqtype is needed to ensure that these different symbols will be considered as the same type descriptor. Fixes golang/go#39276 gcc/go/ChangeLog: * go-c.h (struct go_create_gogo_args): Add need_eqtype field. * go-lang.c (go_langhook_init): Set need_eqtype. Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/235697
Diffstat (limited to 'gcc')
-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))