aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/expressions.cc25
-rw-r--r--gcc/go/gofrontend/expressions.h8
-rw-r--r--gcc/go/gofrontend/gogo.cc3
-rw-r--r--gcc/go/gofrontend/runtime.def16
-rw-r--r--gcc/go/gofrontend/statements.cc25
-rw-r--r--libgo/go/runtime/iface.go37
7 files changed, 45 insertions, 71 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 4bc337c..252e9b1 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-593f94f008c24f5abfe7f917a717cf2b0a2585e2
+5bca69ab3b41df535193474baecc3a8a4c0b3dbe
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 a764d06..b9cf0f3 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -486,9 +486,11 @@ Expression::convert_interface_to_type(Type *lhs_type, Expression* rhs,
// We are going to evaluate RHS multiple times.
go_assert(rhs->is_variable());
- // Call a function to check that the type is valid. The function
- // will panic with an appropriate runtime type error if the type is
- // not valid.
+ // 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*/)
Expression* lhs_type_expr = Expression::make_type_descriptor(lhs_type,
location);
Expression* rhs_descriptor =
@@ -498,11 +500,18 @@ Expression::convert_interface_to_type(Type *lhs_type, Expression* rhs,
Expression* rhs_inter_expr = Expression::make_type_descriptor(rhs_type,
location);
- Expression* check_iface = Runtime::make_call(Runtime::ASSERTI2T,
- location, 3, lhs_type_expr,
- rhs_descriptor, rhs_inter_expr);
+ Expression* cond = Expression::make_binary(OPERATOR_NOTEQ, 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,
+ location);
- // If the call succeeds, pull out the value.
+ // If the conversion succeeds, pull out the value.
Expression* obj = Expression::make_interface_info(rhs, INTERFACE_INFO_OBJECT,
location);
@@ -517,7 +526,7 @@ Expression::convert_interface_to_type(Type *lhs_type, Expression* rhs,
obj = Expression::make_dereference(obj, NIL_CHECK_NOT_NEEDED,
location);
}
- return Expression::make_compound(check_iface, obj, location);
+ return Expression::make_compound(check, obj, location);
}
// Convert an expression to its backend representation. This is implemented by
diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h
index 2c505a9..2c6a080 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -1074,6 +1074,11 @@ class Expression
static Expression*
unpack_direct_iface(Expression*, Location);
+ // Return an expression representing the type descriptor field of an
+ // interface.
+ static Expression*
+ get_interface_type_descriptor(Expression*);
+
// Look through the expression of a Slice_value_expression's valmem to
// find an call to makeslice.
static std::pair<Call_expression*, Temporary_statement*>
@@ -1257,9 +1262,6 @@ class Expression
}
static Expression*
- get_interface_type_descriptor(Expression*);
-
- static Expression*
convert_interface_to_type(Type*, Expression*, Location);
static Expression*
diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc
index 42a7674..b135a69 100644
--- a/gcc/go/gofrontend/gogo.cc
+++ b/gcc/go/gofrontend/gogo.cc
@@ -6243,7 +6243,8 @@ Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no)
}
if (this->asm_name_ == "runtime.gopanic"
- || this->asm_name_ == "__go_runtime_error")
+ || this->asm_name_ == "__go_runtime_error"
+ || this->asm_name_ == "runtime.panicdottype")
flags |= Backend::function_does_not_return;
}
diff --git a/gcc/go/gofrontend/runtime.def b/gcc/go/gofrontend/runtime.def
index ffc747b..a966cd4 100644
--- a/gcc/go/gofrontend/runtime.def
+++ b/gcc/go/gofrontend/runtime.def
@@ -320,23 +320,13 @@ DEF_GO_RUNTIME(ASSERTITAB, "runtime.assertitab", P2(TYPE, TYPE), R1(POINTER))
DEF_GO_RUNTIME(REQUIREITAB, "runtime.requireitab", P2(TYPE, TYPE),
R1(POINTER))
-// Check whether an interface type may be converted to a
-// non-interface type.
-DEF_GO_RUNTIME(ASSERTI2T, "runtime.assertI2T", P3(TYPE, TYPE, TYPE), R0())
+// Panic when an interface type to non-interface type conversion fails.
+DEF_GO_RUNTIME(PANICDOTTYPE, "runtime.panicdottype", P3(TYPE, TYPE, TYPE),
+ R0())
// Return whether we can convert a type to an interface type.
DEF_GO_RUNTIME(IFACET2IP, "runtime.ifaceT2Ip", P2(TYPE, TYPE), R1(BOOL))
-// Get the type descriptor of an empty interface.
-DEF_GO_RUNTIME(EFACETYPE, "runtime.efacetype", P1(EFACE), R1(TYPE))
-
-// Get the type descriptor of a non-empty interface.
-DEF_GO_RUNTIME(IFACETYPE, "runtime.ifacetype", P1(IFACE), R1(TYPE))
-
-
-// Compare two type descriptors for equality.
-DEF_GO_RUNTIME(IFACETYPEEQ, "runtime.ifacetypeeq", 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/statements.cc b/gcc/go/gofrontend/statements.cc
index e8380be..ad4a353 100644
--- a/gcc/go/gofrontend/statements.cc
+++ b/gcc/go/gofrontend/statements.cc
@@ -4614,11 +4614,12 @@ Type_case_clauses::Type_case_clause::lower(Type* switch_val_type,
cond = Expression::make_binary(OPERATOR_EQEQ, ref,
Expression::make_nil(loc),
loc);
+ else if (type->interface_type() == NULL)
+ cond = Expression::make_binary(OPERATOR_EQEQ, ref,
+ Expression::make_type_descriptor(type, loc),
+ loc);
else
- cond = Runtime::make_call((type->interface_type() == NULL
- ? Runtime::IFACETYPEEQ
- : Runtime::IFACET2IP),
- loc, 2,
+ cond = Runtime::make_call(Runtime::IFACET2IP, loc, 2,
Expression::make_type_descriptor(type, loc),
ref);
@@ -4871,23 +4872,23 @@ Type_switch_statement::do_lower(Gogo*, Named_object*, Block* enclosing,
return Statement::make_error_statement(loc);
}
+ Temporary_statement* val_temp =
+ Statement::make_temporary(NULL, this->expr_, loc);
+ b->add_statement(val_temp);
+
// var descriptor_temp DESCRIPTOR_TYPE
Type* descriptor_type = Type::make_type_descriptor_ptr_type();
Temporary_statement* descriptor_temp =
Statement::make_temporary(descriptor_type, NULL, loc);
b->add_statement(descriptor_temp);
- // descriptor_temp = ifacetype(val_temp) FIXME: This should be
- // inlined.
- bool is_empty = val_type->interface_type()->is_empty();
- Expression* call = Runtime::make_call((is_empty
- ? Runtime::EFACETYPE
- : Runtime::IFACETYPE),
- loc, 1, this->expr_);
+ // descriptor_temp = ifacetype(val_temp)
+ Expression* ref = Expression::make_temporary_reference(val_temp, loc);
+ Expression* td = Expression::get_interface_type_descriptor(ref);
Temporary_reference_expression* lhs =
Expression::make_temporary_reference(descriptor_temp, loc);
lhs->set_is_lvalue();
- Statement* s = Statement::make_assignment(lhs, call, loc);
+ Statement* s = Statement::make_assignment(lhs, td, loc);
b->add_statement(s);
if (this->clauses_ != NULL)
diff --git a/libgo/go/runtime/iface.go b/libgo/go/runtime/iface.go
index 1c3a5f3..6def738 100644
--- a/libgo/go/runtime/iface.go
+++ b/libgo/go/runtime/iface.go
@@ -15,10 +15,7 @@ import (
//
//go:linkname requireitab runtime.requireitab
//go:linkname assertitab runtime.assertitab
-//go:linkname assertI2T runtime.assertI2T
-//go:linkname ifacetypeeq runtime.ifacetypeeq
-//go:linkname efacetype runtime.efacetype
-//go:linkname ifacetype runtime.ifacetype
+//go:linkname panicdottype runtime.panicdottype
//go:linkname ifaceE2E2 runtime.ifaceE2E2
//go:linkname ifaceI2E2 runtime.ifaceI2E2
//go:linkname ifaceE2I2 runtime.ifaceE2I2
@@ -356,35 +353,9 @@ func assertitab(lhs, rhs *_type) unsafe.Pointer {
return getitab(lhs, rhs, false)
}
-// Check whether an interface type may be converted to a non-interface
-// type, panicing if not.
-func assertI2T(lhs, rhs, inter *_type) {
- if rhs == nil {
- panic(&TypeAssertionError{nil, nil, lhs, ""})
- }
- if !eqtype(lhs, rhs) {
- panic(&TypeAssertionError{inter, rhs, lhs, ""})
- }
-}
-
-// Compare two type descriptors for equality.
-func ifacetypeeq(a, b *_type) bool {
- return eqtype(a, b)
-}
-
-// Return the type descriptor of an empty interface.
-// FIXME: This should be inlined by the compiler.
-func efacetype(e eface) *_type {
- return e._type
-}
-
-// Return the type descriptor of a non-empty interface.
-// FIXME: This should be inlined by the compiler.
-func ifacetype(i iface) *_type {
- if i.tab == nil {
- return nil
- }
- return *(**_type)(i.tab)
+// panicdottype is called when doing an i.(T) conversion and the conversion fails.
+func panicdottype(lhs, rhs, inter *_type) {
+ panic(&TypeAssertionError{inter, rhs, lhs, ""})
}
// Convert an empty interface to an empty interface, for a comma-ok