aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2019-06-21 22:00:57 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2019-06-21 22:00:57 +0000
commit0514cb33749fefd2542e7294a35d0ef0ccae30b3 (patch)
tree7c947df211513d9ca430a41d1980e1b9e624177d /gcc
parentfd4e7255b60901581961b62e364ce85baf52d631 (diff)
downloadgcc-0514cb33749fefd2542e7294a35d0ef0ccae30b3.zip
gcc-0514cb33749fefd2542e7294a35d0ef0ccae30b3.tar.gz
gcc-0514cb33749fefd2542e7294a35d0ef0ccae30b3.tar.bz2
compiler: open code some type assertions
Now that type equality is just simple pointer equality, we can open code some type assertions instead of making runtime calls. Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/182977 From-SVN: r272577
Diffstat (limited to 'gcc')
-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
6 files changed, 41 insertions, 38 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)