aboutsummaryrefslogtreecommitdiff
path: root/gcc/go
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2016-10-20 18:51:35 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2016-10-20 18:51:35 +0000
commit6b752cfac4ecf8b620726bfcd703844ebfaca6ea (patch)
tree458f96322bb64b331d71a3304f09cd7c032efa9c /gcc/go
parentfceabe505cf0dc7030602e582fadadcce73dd6de (diff)
downloadgcc-6b752cfac4ecf8b620726bfcd703844ebfaca6ea.zip
gcc-6b752cfac4ecf8b620726bfcd703844ebfaca6ea.tar.gz
gcc-6b752cfac4ecf8b620726bfcd703844ebfaca6ea.tar.bz2
runtime: rewrite interface code into Go
I started to copy the Go 1.7 interface code, but the gc and gccgo representations of interfaces are too different. So instead I rewrote the gccgo interface code from C to Go. The code is largely the same as it was, but the names are more like those used in the gc runtime. I also copied over the string comparison functions, and tweaked the compiler to use eqstring when comparing strings for equality. Reviewed-on: https://go-review.googlesource.com/31591 From-SVN: r241384
Diffstat (limited to 'gcc/go')
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/escape.cc4
-rw-r--r--gcc/go/gofrontend/expressions.cc49
-rw-r--r--gcc/go/gofrontend/runtime.def51
-rw-r--r--gcc/go/gofrontend/statements.cc2
-rw-r--r--gcc/go/gofrontend/types.cc8
6 files changed, 66 insertions, 50 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 5c125c7..a331db6 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-5346c7d15362a16efa0defaaeca63b1fce1c1523
+14dc8052a09ad0a2226e64ab6b5af69c6923b830
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/escape.cc b/gcc/go/gofrontend/escape.cc
index 73be757..ba55ea3 100644
--- a/gcc/go/gofrontend/escape.cc
+++ b/gcc/go/gofrontend/escape.cc
@@ -1874,7 +1874,7 @@ Escape_analysis_assign::assign(Node* dst, Node* src)
case Runtime::IFACEI2T2P:
case Runtime::IFACEE2T2:
case Runtime::IFACEI2T2:
- case Runtime::CONVERT_INTERFACE:
+ case Runtime::REQUIREITAB:
// All versions of interface conversion that might result
// from a type assertion. Some of these are the result of
// a tuple type assertion statement and may not be covered
@@ -2633,7 +2633,7 @@ Escape_analysis_flood::flood(Level level, Node* dst, Node* src,
case Runtime::CONCATSTRING5:
case Runtime::CONSTRUCT_MAP:
case Runtime::INTSTRING:
- case Runtime::CONVERT_INTERFACE:
+ case Runtime::REQUIREITAB:
// All runtime calls that involve allocation of memory
// except new. Runtime::NEW gets lowered into an
// allocation expression.
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 261129f..241dc36 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -323,9 +323,8 @@ Expression::convert_interface_to_interface(Type *lhs_type, Expression* rhs,
if (for_type_guard)
{
// A type assertion fails when converting a nil interface.
- first_field =
- Runtime::make_call(Runtime::ASSERT_INTERFACE, location, 2,
- lhs_type_expr, rhs_type_expr);
+ first_field = Runtime::make_call(Runtime::ASSERTITAB, location, 2,
+ lhs_type_expr, rhs_type_expr);
}
else if (lhs_is_empty)
{
@@ -337,9 +336,8 @@ Expression::convert_interface_to_interface(Type *lhs_type, Expression* rhs,
{
// A conversion to a non-empty interface may fail, but unlike a
// type assertion converting nil will always succeed.
- first_field =
- Runtime::make_call(Runtime::CONVERT_INTERFACE, location, 2,
- lhs_type_expr, rhs_type_expr);
+ first_field = Runtime::make_call(Runtime::REQUIREITAB, location, 2,
+ lhs_type_expr, rhs_type_expr);
}
// The second field is simply the object pointer.
@@ -370,7 +368,7 @@ 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::CHECK_INTERFACE_TYPE,
+ Expression* check_iface = Runtime::make_call(Runtime::ASSERTI2T,
location, 3, lhs_type_expr,
rhs_descriptor, rhs_inter_expr);
@@ -1290,7 +1288,10 @@ Func_descriptor_expression::do_get_backend(Translate_context* context)
&& !no->func_declaration_value()->asm_name().empty()
&& Linemap::is_predeclared_location(no->location()))
{
- var_name = no->func_declaration_value()->asm_name() + "_descriptor";
+ if (no->func_declaration_value()->asm_name().substr(0, 8) != "runtime.")
+ var_name = no->func_declaration_value()->asm_name() + "_descriptor";
+ else
+ var_name = no->func_declaration_value()->asm_name() + "$descriptor";
is_descriptor = true;
}
else
@@ -6196,9 +6197,18 @@ Expression::comparison(Translate_context* context, Type* result_type,
if (left_type->is_string_type() && right_type->is_string_type())
{
- left = Runtime::make_call(Runtime::STRCMP, location, 2,
- left, right);
- right = zexpr;
+ if (op == OPERATOR_EQEQ || op == OPERATOR_NOTEQ)
+ {
+ left = Runtime::make_call(Runtime::EQSTRING, location, 2,
+ left, right);
+ right = Expression::make_boolean(true, location);
+ }
+ else
+ {
+ left = Runtime::make_call(Runtime::CMPSTRING, location, 2,
+ left, right);
+ right = zexpr;
+ }
}
else if ((left_type->interface_type() != NULL
&& right_type->interface_type() == NULL
@@ -6230,11 +6240,12 @@ Expression::comparison(Translate_context* context, Type* result_type,
Expression::make_type_descriptor(right_type, location);
left =
Runtime::make_call((left_type->interface_type()->is_empty()
- ? Runtime::EMPTY_INTERFACE_VALUE_COMPARE
- : Runtime::INTERFACE_VALUE_COMPARE),
+ ? Runtime::EFACEVALEQ
+ : Runtime::IFACEVALEQ),
location, 3, left, descriptor,
pointer_arg);
- right = zexpr;
+ go_assert(op == OPERATOR_EQEQ || op == OPERATOR_NOTEQ);
+ right = Expression::make_boolean(true, location);
}
else if (left_type->interface_type() != NULL
&& right_type->interface_type() != NULL)
@@ -6242,25 +6253,25 @@ Expression::comparison(Translate_context* context, Type* result_type,
Runtime::Function compare_function;
if (left_type->interface_type()->is_empty()
&& right_type->interface_type()->is_empty())
- compare_function = Runtime::EMPTY_INTERFACE_COMPARE;
+ compare_function = Runtime::EFACEEQ;
else if (!left_type->interface_type()->is_empty()
&& !right_type->interface_type()->is_empty())
- compare_function = Runtime::INTERFACE_COMPARE;
+ compare_function = Runtime::IFACEEQ;
else
{
if (left_type->interface_type()->is_empty())
{
- go_assert(op == OPERATOR_EQEQ || op == OPERATOR_NOTEQ);
std::swap(left_type, right_type);
std::swap(left, right);
}
go_assert(!left_type->interface_type()->is_empty());
go_assert(right_type->interface_type()->is_empty());
- compare_function = Runtime::INTERFACE_EMPTY_COMPARE;
+ compare_function = Runtime::IFACEEFACEEQ;
}
left = Runtime::make_call(compare_function, location, 2, left, right);
- right = zexpr;
+ go_assert(op == OPERATOR_EQEQ || op == OPERATOR_NOTEQ);
+ right = Expression::make_boolean(true, location);
}
if (left_type->is_nil_type()
diff --git a/gcc/go/gofrontend/runtime.def b/gcc/go/gofrontend/runtime.def
index 4e4c3e3..3051624b 100644
--- a/gcc/go/gofrontend/runtime.def
+++ b/gcc/go/gofrontend/runtime.def
@@ -50,8 +50,11 @@ DEF_GO_RUNTIME(CONCATSTRING4, "runtime.concatstring4",
DEF_GO_RUNTIME(CONCATSTRING5, "runtime.concatstring5",
P2(POINTER, ARRAY5STRING), R1(STRING))
+// Compare two strings for equality.
+DEF_GO_RUNTIME(EQSTRING, "runtime.eqstring", P2(STRING, STRING), R1(BOOL))
+
// Compare two strings.
-DEF_GO_RUNTIME(STRCMP, "__go_strcmp", P2(STRING, STRING), R1(INT))
+DEF_GO_RUNTIME(CMPSTRING, "runtime.cmpstring", P2(STRING, STRING), R1(INT))
// Take a slice of a string.
DEF_GO_RUNTIME(STRING_SLICE, "__go_string_slice", P3(STRING, INT, INT),
@@ -259,22 +262,27 @@ DEF_GO_RUNTIME(IFACEE2T2, "runtime.ifaceE2T2", P3(TYPE, EFACE, POINTER),
DEF_GO_RUNTIME(IFACEI2T2, "runtime.ifaceI2T2", P3(TYPE, IFACE, POINTER),
R1(BOOL))
-// A type assertion from one interface type to another. This is
-// used for a type assertion.
-DEF_GO_RUNTIME(ASSERT_INTERFACE, "__go_assert_interface", P2(TYPE, TYPE), R1(POINTER))
-
-// Convert one interface type to another. This is used for an
-// assignment.
-DEF_GO_RUNTIME(CONVERT_INTERFACE, "__go_convert_interface", P2(TYPE, TYPE),
+// Return the interface method table for the second type converted to
+// the first type which is a (possibly empty) interface type. Panics
+// if the second type is nil (indicating a nil interface value) or if
+// the conversion is not possible. Used for type assertions. This is
+// like REQUIREITAB, but for type assertions.
+DEF_GO_RUNTIME(ASSERTITAB, "runtime.assertitab", P2(TYPE, TYPE), R1(POINTER))
+
+// Return the interface method table for the second type converted to
+// the first type, which is a non-empty interface type. Return nil if
+// the second type is nil, indicating a nil interface value. Panics
+// if the conversion is not possible. Used for assignments. This is
+// like ASSERTITAB, but for assignments.
+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(CHECK_INTERFACE_TYPE, "__go_check_interface_type",
- P3(TYPE, TYPE, TYPE), R0())
+DEF_GO_RUNTIME(ASSERTI2T, "runtime.assertI2T", P3(TYPE, TYPE, TYPE), R0())
-// Return whether we can convert an interface type to a type.
-DEF_GO_RUNTIME(IFACEI2TP, "runtime.ifaceI2Tp", P2(TYPE, TYPE), R1(BOOL))
+// 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))
@@ -287,25 +295,22 @@ DEF_GO_RUNTIME(IFACETYPE, "runtime.ifacetype", P1(IFACE), R1(TYPE))
DEF_GO_RUNTIME(IFACETYPEEQ, "runtime.ifacetypeeq", P2(TYPE, TYPE), R1(BOOL))
// Compare two empty interface values.
-DEF_GO_RUNTIME(EMPTY_INTERFACE_COMPARE, "__go_empty_interface_compare",
- P2(EFACE, EFACE), R1(INT))
+DEF_GO_RUNTIME(EFACEEQ, "runtime.efaceeq", P2(EFACE, EFACE), R1(BOOL))
// Compare an empty interface value to a non-interface value.
-DEF_GO_RUNTIME(EMPTY_INTERFACE_VALUE_COMPARE,
- "__go_empty_interface_value_compare",
- P3(EFACE, TYPE, POINTER), R1(INT))
+DEF_GO_RUNTIME(EFACEVALEQ, "runtime.efacevaleq", P3(EFACE, TYPE, POINTER),
+ R1(BOOL))
// Compare two non-empty interface values.
-DEF_GO_RUNTIME(INTERFACE_COMPARE, "__go_interface_compare",
- P2(IFACE, IFACE), R1(INT))
+DEF_GO_RUNTIME(IFACEEQ, "runtime.ifaceeq", P2(IFACE, IFACE), R1(BOOL))
// Compare a non-empty interface value to a non-interface value.
-DEF_GO_RUNTIME(INTERFACE_VALUE_COMPARE, "__go_interface_value_compare",
- P3(IFACE, TYPE, POINTER), R1(INT))
+DEF_GO_RUNTIME(IFACEVALEQ, "runtime.ifacevaleq", P3(IFACE, TYPE, POINTER),
+ R1(BOOL))
// Compare a non-empty interface value to an interface value.
-DEF_GO_RUNTIME(INTERFACE_EMPTY_COMPARE, "__go_interface_empty_compare",
- P2(IFACE, EFACE), R1(INT))
+DEF_GO_RUNTIME(IFACEEFACEEQ, "runtime.ifaceefaceeq", P2(IFACE, EFACE),
+ R1(BOOL))
// Lock the printer (for print/println).
diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc
index 41f1ffb..e36262d 100644
--- a/gcc/go/gofrontend/statements.cc
+++ b/gcc/go/gofrontend/statements.cc
@@ -3894,7 +3894,7 @@ Type_case_clauses::Type_case_clause::lower(Type* switch_val_type,
else
cond = Runtime::make_call((type->interface_type() == NULL
? Runtime::IFACETYPEEQ
- : Runtime::IFACEI2TP),
+ : Runtime::IFACET2IP),
loc, 2,
Expression::make_type_descriptor(type, loc),
ref);
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc
index d99c834..1635709 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -1710,13 +1710,13 @@ Type::type_functions(Gogo* gogo, Named_type* name, Function_type* hash_fntype,
case Type::TYPE_INTERFACE:
if (this->interface_type()->is_empty())
{
- hash_fnname = "__go_type_hash_empty_interface";
- equal_fnname = "__go_type_equal_empty_interface";
+ hash_fnname = "runtime.nilinterhash";
+ equal_fnname = "runtime.nilinterequal";
}
else
{
- hash_fnname = "__go_type_hash_interface";
- equal_fnname = "__go_type_equal_interface";
+ hash_fnname = "runtime.interhash";
+ equal_fnname = "runtime.interequal";
}
break;