libgo patch committed: Rewrite interface code into Go

Ian Lance Taylor iant@golang.org
Thu Oct 20 18:51:00 GMT 2016


This patch to libgo rewrites the interface code from C to 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.

Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu.  Committed
to mainline.

Ian
-------------- next part --------------
Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE	(revision 241347)
+++ gcc/go/gofrontend/MERGE	(working copy)
@@ -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.
Index: gcc/go/gofrontend/escape.cc
===================================================================
--- gcc/go/gofrontend/escape.cc	(revision 241341)
+++ gcc/go/gofrontend/escape.cc	(working copy)
@@ -1874,7 +1874,7 @@ Escape_analysis_assign::assign(Node* dst
 		  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
 		    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.
Index: gcc/go/gofrontend/expressions.cc
===================================================================
--- gcc/go/gofrontend/expressions.cc	(revision 241341)
+++ gcc/go/gofrontend/expressions.cc	(working copy)
@@ -323,9 +323,8 @@ Expression::convert_interface_to_interfa
   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_interfa
     {
       // 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(Ty
   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_backe
       && !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
 
   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
           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
       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()
Index: gcc/go/gofrontend/runtime.def
===================================================================
--- gcc/go/gofrontend/runtime.def	(revision 241341)
+++ gcc/go/gofrontend/runtime.def	(working copy)
@@ -50,8 +50,11 @@ DEF_GO_RUNTIME(CONCATSTRING4, "runtime.c
 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.iface
 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.iface
 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).
Index: gcc/go/gofrontend/statements.cc
===================================================================
--- gcc/go/gofrontend/statements.cc	(revision 241341)
+++ gcc/go/gofrontend/statements.cc	(working copy)
@@ -3894,7 +3894,7 @@ Type_case_clauses::Type_case_clause::low
       else
 	cond = Runtime::make_call((type->interface_type() == NULL
 				   ? Runtime::IFACETYPEEQ
-				   : Runtime::IFACEI2TP),
+				   : Runtime::IFACET2IP),
 				  loc, 2,
 				  Expression::make_type_descriptor(type, loc),
 				  ref);
Index: gcc/go/gofrontend/types.cc
===================================================================
--- gcc/go/gofrontend/types.cc	(revision 241341)
+++ gcc/go/gofrontend/types.cc	(working copy)
@@ -1710,13 +1710,13 @@ Type::type_functions(Gogo* gogo, Named_t
 	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;
 
Index: libgo/Makefile.am
===================================================================
--- libgo/Makefile.am	(revision 241341)
+++ libgo/Makefile.am	(working copy)
@@ -430,26 +430,17 @@ endif
 runtime_files = \
 	runtime/go-append.c \
 	runtime/go-assert.c \
-	runtime/go-assert-interface.c \
 	runtime/go-breakpoint.c \
 	runtime/go-caller.c \
 	runtime/go-callers.c \
-	runtime/go-can-convert-interface.c \
 	runtime/go-cdiv.c \
 	runtime/go-cgo.c \
-	runtime/go-check-interface.c \
 	runtime/go-construct-map.c \
-	runtime/go-convert-interface.c \
 	runtime/go-copy.c \
 	runtime/go-defer.c \
 	runtime/go-deferred-recover.c \
-	runtime/go-eface-compare.c \
-	runtime/go-eface-val-compare.c \
 	runtime/go-ffi.c \
 	runtime/go-fieldtrack.c \
-	runtime/go-interface-compare.c \
-	runtime/go-interface-eface-compare.c \
-	runtime/go-interface-val-compare.c \
 	runtime/go-make-slice.c \
 	runtime/go-matherr.c \
 	runtime/go-memclr.c \
@@ -466,13 +457,10 @@ runtime_files = \
 	runtime/go-runtime-error.c \
 	runtime/go-setenv.c \
 	runtime/go-signal.c \
-	runtime/go-strcmp.c \
 	runtime/go-strslice.c \
 	runtime/go-type-complex.c \
-	runtime/go-type-eface.c \
 	runtime/go-type-float.c \
 	runtime/go-type-identity.c \
-	runtime/go-type-interface.c \
 	runtime/go-type-string.c \
 	runtime/go-typedesc-equal.c \
 	runtime/go-unsafe-new.c \
@@ -500,10 +488,8 @@ runtime_files = \
 	$(runtime_thread_files) \
 	runtime/yield.c \
 	$(rtems_task_variable_add_file) \
-	go-iface.c \
 	lfstack.c \
 	malloc.c \
-	reflect.c \
 	runtime1.c \
 	sigqueue.c \
 	$(runtime_getncpu_file)
@@ -518,10 +504,6 @@ malloc.c: $(srcdir)/runtime/malloc.goc g
 	./goc2c $< > $@.tmp
 	mv -f $@.tmp $@
 
-reflect.c: $(srcdir)/runtime/reflect.goc goc2c
-	./goc2c $< > $@.tmp
-	mv -f $@.tmp $@
-
 runtime1.c: $(srcdir)/runtime/runtime1.goc goc2c
 	./goc2c $< > $@.tmp
 	mv -f $@.tmp $@
Index: libgo/go/runtime/alg.go
===================================================================
--- libgo/go/runtime/alg.go	(revision 0)
+++ libgo/go/runtime/alg.go	(working copy)
@@ -0,0 +1,204 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import (
+	"runtime/internal/sys"
+	"unsafe"
+)
+
+// For gccgo, use go:linkname to rename compiler-called functions to
+// themselves, so that the compiler will export them.
+//
+//go:linkname interhash runtime.interhash
+//go:linkname nilinterhash runtime.nilinterhash
+//go:linkname interequal runtime.interequal
+//go:linkname nilinterequal runtime.nilinterequal
+//go:linkname efaceeq runtime.efaceeq
+//go:linkname ifaceeq runtime.ifaceeq
+//go:linkname ifacevaleq runtime.ifacevaleq
+//go:linkname ifaceefaceeq runtime.ifaceefaceeq
+//go:linkname efacevaleq runtime.efacevaleq
+//go:linkname eqstring runtime.eqstring
+//go:linkname cmpstring runtime.cmpstring
+
+const (
+	c0 = uintptr((8-sys.PtrSize)/4*2860486313 + (sys.PtrSize-4)/4*33054211828000289)
+	c1 = uintptr((8-sys.PtrSize)/4*3267000013 + (sys.PtrSize-4)/4*23344194077549503)
+)
+
+func interhash(p unsafe.Pointer, h uintptr, size uintptr) uintptr {
+	a := (*iface)(p)
+	tab := a.tab
+	if tab == nil {
+		return h
+	}
+	t := *(**_type)(tab)
+	fn := t.hashfn
+	if fn == nil {
+		panic(errorString("hash of unhashable type " + *t.string))
+	}
+	if isDirectIface(t) {
+		return c1 * fn(unsafe.Pointer(&a.data), h^c0, t.size)
+	} else {
+		return c1 * fn(a.data, h^c0, t.size)
+	}
+}
+
+func nilinterhash(p unsafe.Pointer, h uintptr, size uintptr) uintptr {
+	a := (*eface)(p)
+	t := a._type
+	if t == nil {
+		return h
+	}
+	fn := t.hashfn
+	if fn == nil {
+		panic(errorString("hash of unhashable type " + *t.string))
+	}
+	if isDirectIface(t) {
+		return c1 * fn(unsafe.Pointer(&a.data), h^c0, t.size)
+	} else {
+		return c1 * fn(a.data, h^c0, t.size)
+	}
+}
+
+func interequal(p, q unsafe.Pointer, size uintptr) bool {
+	return ifaceeq(*(*iface)(p), *(*iface)(q))
+}
+
+func nilinterequal(p, q unsafe.Pointer, size uintptr) bool {
+	return efaceeq(*(*eface)(p), *(*eface)(q))
+}
+
+func efaceeq(x, y eface) bool {
+	t := x._type
+	if !eqtype(t, y._type) {
+		return false
+	}
+	if t == nil {
+		return true
+	}
+	eq := t.equalfn
+	if eq == nil {
+		panic(errorString("comparing uncomparable type " + *t.string))
+	}
+	if isDirectIface(t) {
+		return x.data == y.data
+	}
+	return eq(x.data, y.data, t.size)
+}
+
+func ifaceeq(x, y iface) bool {
+	xtab := x.tab
+	if xtab == nil && y.tab == nil {
+		return true
+	}
+	if xtab == nil || y.tab == nil {
+		return false
+	}
+	t := *(**_type)(xtab)
+	if !eqtype(t, *(**_type)(y.tab)) {
+		return false
+	}
+	eq := t.equalfn
+	if eq == nil {
+		panic(errorString("comparing uncomparable type " + *t.string))
+	}
+	if isDirectIface(t) {
+		return x.data == y.data
+	}
+	return eq(x.data, y.data, t.size)
+}
+
+func ifacevaleq(x iface, t *_type, p unsafe.Pointer) bool {
+	if x.tab == nil {
+		return false
+	}
+	xt := *(**_type)(x.tab)
+	if !eqtype(xt, t) {
+		return false
+	}
+	eq := t.equalfn
+	if eq == nil {
+		panic(errorString("comparing uncomparable type " + *t.string))
+	}
+	if isDirectIface(t) {
+		return x.data == p
+	}
+	return eq(x.data, p, t.size)
+}
+
+func ifaceefaceeq(x iface, y eface) bool {
+	if x.tab == nil && y._type == nil {
+		return true
+	}
+	if x.tab == nil || y._type == nil {
+		return false
+	}
+	xt := *(**_type)(x.tab)
+	if !eqtype(xt, y._type) {
+		return false
+	}
+	eq := xt.equalfn
+	if eq == nil {
+		panic(errorString("comparing uncomparable type " + *xt.string))
+	}
+	if isDirectIface(xt) {
+		return x.data == y.data
+	}
+	return eq(x.data, y.data, xt.size)
+}
+
+func efacevaleq(x eface, t *_type, p unsafe.Pointer) bool {
+	if x._type == nil {
+		return false
+	}
+	if !eqtype(x._type, t) {
+		return false
+	}
+	eq := t.equalfn
+	if eq == nil {
+		panic(errorString("comparing uncomparable type " + *t.string))
+	}
+	if isDirectIface(t) {
+		return x.data == p
+	}
+	return eq(x.data, p, t.size)
+}
+
+func eqstring(x, y string) bool {
+	a := stringStructOf(&x)
+	b := stringStructOf(&y)
+	if a.len != b.len {
+		return false
+	}
+	return memcmp(unsafe.Pointer(a.str), unsafe.Pointer(b.str), uintptr(a.len)) == 0
+}
+
+func cmpstring(x, y string) int {
+	a := stringStructOf(&x)
+	b := stringStructOf(&y)
+	l := a.len
+	if l > b.len {
+		l = b.len
+	}
+	i := memcmp(unsafe.Pointer(a.str), unsafe.Pointer(b.str), uintptr(l))
+	if i != 0 {
+		return int(i)
+	}
+	if a.len < b.len {
+		return -1
+	} else if a.len > b.len {
+		return 1
+	}
+	return 0
+}
+
+// Force the creation of function descriptors for equality and hash
+// functions.  These will be referenced directly by the compiler.
+var _ = interhash
+var _ = interequal
+var _ = nilinterhash
+var _ = nilinterequal
Index: libgo/go/runtime/iface.go
===================================================================
--- libgo/go/runtime/iface.go	(revision 0)
+++ libgo/go/runtime/iface.go	(working copy)
@@ -0,0 +1,334 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import (
+	"unsafe"
+)
+
+// For gccgo, use go:linkname to rename compiler-called functions to
+// themselves, so that the compiler will export them.
+//
+//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 ifaceE2E2 runtime.ifaceE2E2
+//go:linkname ifaceI2E2 runtime.ifaceI2E2
+//go:linkname ifaceE2I2 runtime.ifaceE2I2
+//go:linkname ifaceI2I2 runtime.ifaceI2I2
+//go:linkname ifaceE2T2P runtime.ifaceE2T2P
+//go:linkname ifaceI2T2P runtime.ifaceI2T2P
+//go:linkname ifaceE2T2 runtime.ifaceE2T2
+//go:linkname ifaceI2T2 runtime.ifaceI2T2
+//go:linkname ifaceT2Ip runtime.ifaceT2Ip
+// Temporary for C code to call:
+//go:linkname getitab runtime.getitab
+
+// The gccgo itab structure is different than the gc one.
+//
+// Both gccgo and gc represent empty interfaces the same way:
+// a two field struct, where the first field points to a type descriptor
+// (a *_type) and the second field is the data pointer.
+//
+// Non-empty interfaces are also two-field structs, and the second
+// field is the data pointer. However, for gccgo, the first field, the
+// itab field, is different. The itab field points to the interface
+// method table, which is the implemention of a specific interface
+// type for a specific dynamic non-interface type.  An interface
+// method table is a list of pointer values. The first pointer is the
+// type descriptor (a *_type) for the dynamic type. The subsequent
+// pointers are pointers to function code, which implement the methods
+// required by the interface. The pointers are sorted by name.
+//
+// The method pointers in the itab are C function pointers, not Go
+// function pointers; they may be called directly, and they have no
+// closures. The receiver is always passed as a pointer, and it is
+// always the same pointer stored in the interface value. A value
+// method starts by copying the receiver value out of the pointer into
+// a local variable.
+//
+// A method call on an interface value is by definition calling a
+// method at a known index m in the list of methods. Given a non-empty
+// interface value i, the call i.m(args) looks like
+//     i.itab[m+1](i.iface, args)
+
+// Both an empty interface and a non-empty interface have a data
+// pointer field. The meaning of this field is determined by the
+// kindDirectIface bit in the `kind` field of the type descriptor of
+// the value stored in the interface. If kindDirectIface is set, then
+// the data pointer field in the interface value is exactly the value
+// stored in the interface. Otherwise, the data pointer field is a
+// pointer to memory that holds the value. It follows from this that
+// kindDirectIface can only be set for a type whose representation is
+// simply a pointer. In the current gccgo implementation, this is set
+// only for pointer types (including unsafe.Pointer). In the future it
+// could also be set for other types: channels, maps, functions,
+// single-field structs and single-element arrays whose single field
+// is simply a pointer.
+
+// For a nil interface value both fields in the interface struct are nil.
+
+// Return the interface method table for a value of type rhs converted
+// to an interface of type lhs.
+func getitab(lhs, rhs *_type, canfail bool) unsafe.Pointer {
+	if rhs == nil {
+		return nil
+	}
+
+	if lhs.kind&kindMask != kindInterface {
+		throw("getitab called for non-interface type")
+	}
+
+	lhsi := (*interfacetype)(unsafe.Pointer(lhs))
+
+	if len(lhsi.methods) == 0 {
+		throw("getitab called for empty interface type")
+	}
+
+	if rhs.uncommontype == nil || len(rhs.methods) == 0 {
+		if canfail {
+			return nil
+		}
+		panic(&TypeAssertionError{"", *rhs.string, *lhs.string, *lhsi.methods[0].name})
+	}
+
+	methods := make([]unsafe.Pointer, len(lhsi.methods)+1)
+	methods[0] = unsafe.Pointer(rhs)
+
+	ri := 0
+	for li := range lhsi.methods {
+		lhsMethod := &lhsi.methods[li]
+		var rhsMethod *method
+
+		for {
+			if ri >= len(rhs.methods) {
+				if canfail {
+					return nil
+				}
+				panic(&TypeAssertionError{"", *rhs.string, *lhs.string, *lhsMethod.name})
+			}
+
+			rhsMethod = &rhs.methods[ri]
+			if (lhsMethod.name == rhsMethod.name || *lhsMethod.name == *rhsMethod.name) &&
+				(lhsMethod.pkgPath == rhsMethod.pkgPath || *lhsMethod.pkgPath == *rhsMethod.pkgPath) {
+				break
+			}
+
+			ri++
+		}
+
+		if !eqtype(lhsMethod.typ, rhsMethod.mtyp) {
+			if canfail {
+				return nil
+			}
+			panic(&TypeAssertionError{"", *rhs.string, *lhs.string, *lhsMethod.name})
+		}
+
+		methods[li+1] = unsafe.Pointer(rhsMethod.tfn)
+		ri++
+	}
+
+	return unsafe.Pointer(&methods[0])
+}
+
+// Return the interface method table for a value of type rhs converted
+// to an interface of type lhs.  Panics if the conversion is impossible.
+func requireitab(lhs, rhs *_type) unsafe.Pointer {
+	return getitab(lhs, rhs, false)
+}
+
+// Return the interface method table for a value of type rhs converted
+// to an interface of type lhs.  Panics if the conversion is
+// impossible or if the rhs type is nil.
+func assertitab(lhs, rhs *_type) unsafe.Pointer {
+	if rhs == nil {
+		panic(&TypeAssertionError{"", "", *lhs.string, ""})
+	}
+
+	if lhs.kind&kindMask != kindInterface {
+		throw("assertitab called for non-interface type")
+	}
+
+	lhsi := (*interfacetype)(unsafe.Pointer(lhs))
+
+	if len(lhsi.methods) == 0 {
+		return unsafe.Pointer(rhs)
+	}
+
+	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{"", "", *lhs.string, ""})
+	}
+	if !eqtype(lhs, rhs) {
+		panic(&TypeAssertionError{*inter.string, *rhs.string, *lhs.string, ""})
+	}
+}
+
+// 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)
+}
+
+// Convert an empty interface to an empty interface, for a comma-ok
+// type assertion.
+func ifaceE2E2(e eface) (eface, bool) {
+	return e, e._type != nil
+}
+
+// Convert a non-empty interface to an empty interface, for a comma-ok
+// type assertion.
+func ifaceI2E2(i iface) (eface, bool) {
+	if i.tab == nil {
+		return eface{nil, nil}, false
+	} else {
+		return eface{*(**_type)(i.tab), i.data}, true
+	}
+}
+
+// Convert an empty interface to a non-empty interface, for a comma-ok
+// type assertion.
+func ifaceE2I2(inter *_type, e eface) (iface, bool) {
+	if e._type == nil {
+		return iface{nil, nil}, false
+	} else {
+		itab := getitab(inter, e._type, true)
+		if itab == nil {
+			return iface{nil, nil}, false
+		} else {
+			return iface{itab, e.data}, true
+		}
+	}
+}
+
+// Convert a non-empty interface to a non-empty interface, for a
+// comma-ok type assertion.
+func ifaceI2I2(inter *_type, i iface) (iface, bool) {
+	if i.tab == nil {
+		return iface{nil, nil}, false
+	} else {
+		itab := getitab(inter, *(**_type)(i.tab), true)
+		if itab == nil {
+			return iface{nil, nil}, false
+		} else {
+			return iface{itab, i.data}, true
+		}
+	}
+}
+
+// Convert an empty interface to a pointer non-interface type.
+func ifaceE2T2P(t *_type, e eface) (unsafe.Pointer, bool) {
+	if !eqtype(t, e._type) {
+		return nil, false
+	} else {
+		return e.data, true
+	}
+}
+
+// Convert a non-empty interface to a pointer non-interface type.
+func ifaceI2T2P(t *_type, i iface) (unsafe.Pointer, bool) {
+	if i.tab == nil || !eqtype(t, *(**_type)(i.tab)) {
+		return nil, false
+	} else {
+		return i.data, true
+	}
+}
+
+// Convert an empty interface to a non-pointer non-interface type.
+func ifaceE2T2(t *_type, e eface, ret unsafe.Pointer) bool {
+	if !eqtype(t, e._type) {
+		memclr(ret, t.size)
+		return false
+	} else {
+		typedmemmove(t, ret, e.data)
+		return true
+	}
+}
+
+// Convert a non-empty interface to a non-pointer non-interface type.
+func ifaceI2T2(t *_type, i iface, ret unsafe.Pointer) bool {
+	if i.tab == nil || !eqtype(t, *(**_type)(i.tab)) {
+		memclr(ret, t.size)
+		return false
+	} else {
+		typedmemmove(t, ret, i.data)
+		return true
+	}
+}
+
+// Return whether we can convert a type to an interface type.
+func ifaceT2Ip(to, from *_type) bool {
+	if from == nil {
+		return false
+	}
+
+	if to.kind&kindMask != kindInterface {
+		throw("ifaceT2Ip called with non-interface type")
+	}
+	toi := (*interfacetype)(unsafe.Pointer(to))
+
+	if from.uncommontype == nil || len(from.methods) == 0 {
+		return len(toi.methods) == 0
+	}
+
+	ri := 0
+	for li := range toi.methods {
+		toMethod := &toi.methods[li]
+		var fromMethod *method
+		for {
+			if ri >= len(from.methods) {
+				return false
+			}
+
+			fromMethod = &from.methods[ri]
+			if (toMethod.name == fromMethod.name || *toMethod.name == *fromMethod.name) &&
+				(toMethod.pkgPath == fromMethod.pkgPath || *toMethod.pkgPath == *fromMethod.pkgPath) {
+				break
+			}
+
+			ri++
+		}
+
+		if !eqtype(fromMethod.mtyp, toMethod.typ) {
+			return false
+		}
+
+		ri++
+	}
+
+	return true
+}
+
+//go:linkname reflect_ifaceE2I reflect.ifaceE2I
+func reflect_ifaceE2I(inter *interfacetype, e eface, dst *iface) {
+	t := e._type
+	if t == nil {
+		panic(TypeAssertionError{"", "", *inter.typ.string, ""})
+	}
+	dst.tab = requireitab((*_type)(unsafe.Pointer(inter)), t)
+	dst.data = e.data
+}
Index: libgo/go/runtime/runtime2.go
===================================================================
--- libgo/go/runtime/runtime2.go	(revision 241341)
+++ libgo/go/runtime/runtime2.go	(working copy)
@@ -138,11 +138,15 @@ type funcval struct {
 	// variable-size, fn-specific data here
 }
 
+// The representation of a non-empty interface.
+// See comment in iface.go for more details on this struct.
 type iface struct {
 	tab  unsafe.Pointer
 	data unsafe.Pointer
 }
 
+// The representation of an empty interface.
+// See comment in iface.go for more details on this struct.
 type eface struct {
 	_type *_type
 	data  unsafe.Pointer
Index: libgo/go/runtime/stubs.go
===================================================================
--- libgo/go/runtime/stubs.go	(revision 241341)
+++ libgo/go/runtime/stubs.go	(working copy)
@@ -73,7 +73,6 @@ func reflect_memclr(ptr unsafe.Pointer,
 }
 
 // memmove copies n bytes from "from" to "to".
-// in memmove_*.s
 //go:noescape
 func memmove(to, from unsafe.Pointer, n uintptr)
 
@@ -82,6 +81,10 @@ func reflect_memmove(to, from unsafe.Poi
 	memmove(to, from, n)
 }
 
+//go:noescape
+//extern __builtin_memcmp
+func memcmp(a, b unsafe.Pointer, size uintptr) int32
+
 // exported value for testing
 var hashLoad = loadFactor
 
@@ -466,3 +469,8 @@ func setMaxThreads(in int) (out int) {
 func atomicstorep(ptr unsafe.Pointer, new unsafe.Pointer) {
 	atomic.StorepNoWB(noescape(ptr), new)
 }
+
+// Temporary for gccgo until we port mbarrier.go
+func writebarrierptr(dst *uintptr, src uintptr) {
+	*dst = src
+}
Index: libgo/go/runtime/type.go
===================================================================
--- libgo/go/runtime/type.go	(revision 241341)
+++ libgo/go/runtime/type.go	(working copy)
@@ -25,6 +25,22 @@ type _type struct {
 	ptrToThis *_type
 }
 
+// Return whether two type descriptors are equal.
+// This is gccgo-specific, as gccgo, unlike gc, permits multiple
+// independent descriptors for a single type.
+func eqtype(t1, t2 *_type) bool {
+	switch {
+	case t1 == t2:
+		return true
+	case t1 == nil || t2 == nil:
+		return false
+	case t1.kind != t2.kind || t1.hash != t2.hash:
+		return false
+	default:
+		return *t1.string == *t2.string
+	}
+}
+
 type method struct {
 	name    *string
 	pkgPath *string
Index: libgo/runtime/go-assert-interface.c
===================================================================
--- libgo/runtime/go-assert-interface.c	(revision 241341)
+++ libgo/runtime/go-assert-interface.c	(working copy)
@@ -1,45 +0,0 @@
-/* go-assert-interface.c -- interface type assertion for Go.
-
-   Copyright 2010 The Go Authors. All rights reserved.
-   Use of this source code is governed by a BSD-style
-   license that can be found in the LICENSE file.  */
-
-#include "runtime.h"
-#include "go-alloc.h"
-#include "go-assert.h"
-#include "go-panic.h"
-#include "go-type.h"
-#include "interface.h"
-
-/* This is called by the compiler to implement a type assertion from
-   one interface type to another.  This returns the value that should
-   go in the first field of the result tuple.  The result may be an
-   empty or a non-empty interface.  */
-
-const void *
-__go_assert_interface (const struct __go_type_descriptor *lhs_descriptor,
-		       const struct __go_type_descriptor *rhs_descriptor)
-{
-  const struct __go_interface_type *lhs_interface;
-
-  if (rhs_descriptor == NULL)
-    {
-      struct __go_empty_interface panic_arg;
-
-      /* A type assertion is not permitted with a nil interface.  */
-
-      runtime_newTypeAssertionError (NULL, NULL, lhs_descriptor->__reflection,
-				     NULL, &panic_arg);
-      __go_panic (panic_arg);
-    }
-
-  /* A type assertion to an empty interface just returns the object
-     descriptor.  */
-
-  __go_assert ((lhs_descriptor->__code & GO_CODE_MASK) == GO_INTERFACE);
-  lhs_interface = (const struct __go_interface_type *) lhs_descriptor;
-  if (lhs_interface->__methods.__count == 0)
-    return rhs_descriptor;
-
-  return __go_convert_interface_2 (lhs_descriptor, rhs_descriptor, 0);
-}
Index: libgo/runtime/go-can-convert-interface.c
===================================================================
--- libgo/runtime/go-can-convert-interface.c	(revision 241341)
+++ libgo/runtime/go-can-convert-interface.c	(working copy)
@@ -1,78 +0,0 @@
-/* go-can-convert-interface.c -- can we convert to an interface?
-
-   Copyright 2009 The Go Authors. All rights reserved.
-   Use of this source code is governed by a BSD-style
-   license that can be found in the LICENSE file.  */
-
-#include "runtime.h"
-#include "go-assert.h"
-#include "go-string.h"
-#include "go-type.h"
-#include "interface.h"
-
-/* Return whether we can convert from the type in FROM_DESCRIPTOR to
-   the interface in TO_DESCRIPTOR.  This is used for type
-   switches.  */
-
-_Bool
-__go_can_convert_to_interface (
-    const struct __go_type_descriptor *to_descriptor,
-    const struct __go_type_descriptor *from_descriptor)
-{
-  const struct __go_interface_type *to_interface;
-  int to_method_count;
-  const struct __go_interface_method *to_method;
-  const struct __go_uncommon_type *from_uncommon;
-  int from_method_count;
-  const struct __go_method *from_method;
-  int i;
-
-  /* In a type switch FROM_DESCRIPTOR can be NULL.  */
-  if (from_descriptor == NULL)
-    return 0;
-
-  __go_assert ((to_descriptor->__code & GO_CODE_MASK) == GO_INTERFACE);
-  to_interface = (const struct __go_interface_type *) to_descriptor;
-  to_method_count = to_interface->__methods.__count;
-  to_method = ((const struct __go_interface_method *)
-	       to_interface->__methods.__values);
-
-  from_uncommon = from_descriptor->__uncommon;
-  if (from_uncommon == NULL)
-    {
-      from_method_count = 0;
-      from_method = NULL;
-    }
-  else
-    {
-      from_method_count = from_uncommon->__methods.__count;
-      from_method = ((const struct __go_method *)
-		     from_uncommon->__methods.__values);
-    }
-
-  for (i = 0; i < to_method_count; ++i)
-    {
-      while (from_method_count > 0
-	     && (!__go_ptr_strings_equal (from_method->__name,
-					  to_method->__name)
-		 || !__go_ptr_strings_equal (from_method->__pkg_path,
-					     to_method->__pkg_path)))
-	{
-	  ++from_method;
-	  --from_method_count;
-	}
-
-      if (from_method_count == 0)
-	return 0;
-
-      if (!__go_type_descriptors_equal (from_method->__mtype,
-					to_method->__type))
-	return 0;
-
-      ++to_method;
-      ++from_method;
-      --from_method_count;
-    }
-
-  return 1;
-}
Index: libgo/runtime/go-cgo.c
===================================================================
--- libgo/runtime/go-cgo.c	(revision 241341)
+++ libgo/runtime/go-cgo.c	(working copy)
@@ -6,7 +6,6 @@
 
 #include "runtime.h"
 #include "go-alloc.h"
-#include "interface.h"
 #include "go-panic.h"
 #include "go-type.h"
 
@@ -170,7 +169,8 @@ _cgo_panic (const char *p)
   intgo len;
   unsigned char *data;
   String *ps;
-  struct __go_empty_interface e;
+  Eface e;
+  const struct __go_type_descriptor *td;
 
   runtime_exitsyscall (0);
   len = __builtin_strlen (p);
@@ -179,8 +179,9 @@ _cgo_panic (const char *p)
   ps = alloc_saved (sizeof *ps);
   ps->str = data;
   ps->len = len;
-  e.__type_descriptor = &string_type_descriptor;
-  e.__object = ps;
+  td = &string_type_descriptor;
+  memcpy(&e._type, &td, sizeof td); /* This is a const_cast.  */
+  e.data = ps;
 
   /* We don't call runtime_entersyscall here, because normally what
      will happen is that we will walk up the stack to a Go deferred
Index: libgo/runtime/go-check-interface.c
===================================================================
--- libgo/runtime/go-check-interface.c	(revision 241341)
+++ libgo/runtime/go-check-interface.c	(working copy)
@@ -1,46 +0,0 @@
-/* go-check-interface.c -- check an interface type for a conversion
-
-   Copyright 2010 The Go Authors. All rights reserved.
-   Use of this source code is governed by a BSD-style
-   license that can be found in the LICENSE file.  */
-
-#include "runtime.h"
-#include "go-panic.h"
-#include "go-type.h"
-#include "interface.h"
-
-/* Check that an interface type matches for a conversion to a
-   non-interface type.  This panics if the types are bad.  The actual
-   extraction of the object is inlined.  */
-
-void
-__go_check_interface_type (
-    const struct __go_type_descriptor *lhs_descriptor,
-    const struct __go_type_descriptor *rhs_descriptor,
-    const struct __go_type_descriptor *rhs_inter_descriptor)
-{
-  if (rhs_descriptor == NULL)
-    {
-      struct __go_empty_interface panic_arg;
-
-      runtime_newTypeAssertionError(NULL, NULL, lhs_descriptor->__reflection,
-				    NULL, &panic_arg);
-      __go_panic(panic_arg);
-    }
-
-  if (lhs_descriptor != rhs_descriptor
-      && !__go_type_descriptors_equal (lhs_descriptor, rhs_descriptor)
-      && ((lhs_descriptor->__code & GO_CODE_MASK) != GO_UNSAFE_POINTER
-	  || !__go_is_pointer_type (rhs_descriptor))
-      && ((rhs_descriptor->__code & GO_CODE_MASK) != GO_UNSAFE_POINTER
-	  || !__go_is_pointer_type (lhs_descriptor)))
-    {
-      struct __go_empty_interface panic_arg;
-
-      runtime_newTypeAssertionError(rhs_inter_descriptor->__reflection,
-				    rhs_descriptor->__reflection,
-				    lhs_descriptor->__reflection,
-				    NULL, &panic_arg);
-      __go_panic(panic_arg);
-    }
-}
Index: libgo/runtime/go-convert-interface.c
===================================================================
--- libgo/runtime/go-convert-interface.c	(revision 241341)
+++ libgo/runtime/go-convert-interface.c	(working copy)
@@ -1,132 +0,0 @@
-/* go-convert-interface.c -- convert interfaces for Go.
-
-   Copyright 2009 The Go Authors. All rights reserved.
-   Use of this source code is governed by a BSD-style
-   license that can be found in the LICENSE file.  */
-
-#include "runtime.h"
-#include "go-alloc.h"
-#include "go-assert.h"
-#include "go-panic.h"
-#include "go-string.h"
-#include "go-type.h"
-#include "interface.h"
-
-/* This is called when converting one interface type into another
-   interface type.  LHS_DESCRIPTOR is the type descriptor of the
-   resulting interface.  RHS_DESCRIPTOR is the type descriptor of the
-   object being converted.  This builds and returns a new interface
-   method table.  If any method in the LHS_DESCRIPTOR interface is not
-   implemented by the object, the conversion fails.  If the conversion
-   fails, then if MAY_FAIL is true this returns NULL; otherwise, it
-   panics.  */
-
-void *
-__go_convert_interface_2 (const struct __go_type_descriptor *lhs_descriptor,
-			  const struct __go_type_descriptor *rhs_descriptor,
-			  _Bool may_fail)
-{
-  const struct __go_interface_type *lhs_interface;
-  int lhs_method_count;
-  const struct __go_interface_method* lhs_methods;
-  const void **methods;
-  const struct __go_uncommon_type *rhs_uncommon;
-  int rhs_method_count;
-  const struct __go_method *p_rhs_method;
-  int i;
-
-  if (rhs_descriptor == NULL)
-    {
-      /* A nil value always converts to nil.  */
-      return NULL;
-    }
-
-  __go_assert ((lhs_descriptor->__code & GO_CODE_MASK) == GO_INTERFACE);
-  lhs_interface = (const struct __go_interface_type *) lhs_descriptor;
-  lhs_method_count = lhs_interface->__methods.__count;
-  lhs_methods = ((const struct __go_interface_method *)
-		 lhs_interface->__methods.__values);
-
-  /* This should not be called for an empty interface.  */
-  __go_assert (lhs_method_count > 0);
-
-  rhs_uncommon = rhs_descriptor->__uncommon;
-  if (rhs_uncommon == NULL || rhs_uncommon->__methods.__count == 0)
-    {
-      struct __go_empty_interface panic_arg;
-
-      if (may_fail)
-	return NULL;
-
-      runtime_newTypeAssertionError (NULL, rhs_descriptor->__reflection,
-				     lhs_descriptor->__reflection,
-				     lhs_methods[0].__name,
-				     &panic_arg);
-      __go_panic (panic_arg);
-    }
-
-  rhs_method_count = rhs_uncommon->__methods.__count;
-  p_rhs_method = ((const struct __go_method *)
-		  rhs_uncommon->__methods.__values);
-
-  methods = NULL;
-
-  for (i = 0; i < lhs_method_count; ++i)
-    {
-      const struct __go_interface_method *p_lhs_method;
-
-      p_lhs_method = &lhs_methods[i];
-
-      while (rhs_method_count > 0
-	     && (!__go_ptr_strings_equal (p_lhs_method->__name,
-					  p_rhs_method->__name)
-		 || !__go_ptr_strings_equal (p_lhs_method->__pkg_path,
-					     p_rhs_method->__pkg_path)))
-	{
-	  ++p_rhs_method;
-	  --rhs_method_count;
-	}
-
-      if (rhs_method_count == 0
-	  || !__go_type_descriptors_equal (p_lhs_method->__type,
-					   p_rhs_method->__mtype))
-	{
-	  struct __go_empty_interface panic_arg;
-
-	  if (methods != NULL)
-	    __go_free (methods);
-
-	  if (may_fail)
-	    return NULL;
-
-	  runtime_newTypeAssertionError (NULL, rhs_descriptor->__reflection,
-					 lhs_descriptor->__reflection,
-					 p_lhs_method->__name, &panic_arg);
-	  __go_panic (panic_arg);
-	}
-
-      if (methods == NULL)
-	{
-	  methods = (const void **) __go_alloc ((lhs_method_count + 1)
-						* sizeof (void *));
-
-	  /* The first field in the method table is always the type of
-	     the object.  */
-	  methods[0] = rhs_descriptor;
-	}
-
-      methods[i + 1] = p_rhs_method->__function;
-    }
-
-  return methods;
-}
-
-/* This is called by the compiler to convert a value from one
-   interface type to another.  */
-
-void *
-__go_convert_interface (const struct __go_type_descriptor *lhs_descriptor,
-			const struct __go_type_descriptor *rhs_descriptor)
-{
-  return __go_convert_interface_2 (lhs_descriptor, rhs_descriptor, 0);
-}
Index: libgo/runtime/go-deferred-recover.c
===================================================================
--- libgo/runtime/go-deferred-recover.c	(revision 241341)
+++ libgo/runtime/go-deferred-recover.c	(working copy)
@@ -75,7 +75,7 @@
    because you are not permitted to take the address of a predeclared
    function like recover.  */
 
-struct __go_empty_interface
+Eface
 __go_deferred_recover ()
 {
   G *g;
@@ -83,10 +83,10 @@ __go_deferred_recover ()
   g = runtime_g ();
   if (g->_defer == NULL || g->_defer->_panic != g->_panic)
     {
-      struct __go_empty_interface ret;
+      Eface ret;
 
-      ret.__type_descriptor = NULL;
-      ret.__object = NULL;
+      ret._type = NULL;
+      ret.data = NULL;
       return ret;
     }
   return __go_recover ();
Index: libgo/runtime/go-eface-compare.c
===================================================================
--- libgo/runtime/go-eface-compare.c	(revision 241341)
+++ libgo/runtime/go-eface-compare.c	(working copy)
@@ -1,37 +0,0 @@
-/* go-eface-compare.c -- compare two empty values.
-
-   Copyright 2010 The Go Authors. All rights reserved.
-   Use of this source code is governed by a BSD-style
-   license that can be found in the LICENSE file.  */
-
-#include "runtime.h"
-#include "go-type.h"
-#include "interface.h"
-
-/* Compare two interface values.  Return 0 for equal, not zero for not
-   equal (return value is like strcmp).  */
-
-intgo
-__go_empty_interface_compare (struct __go_empty_interface left,
-			      struct __go_empty_interface right)
-{
-  const struct __go_type_descriptor *left_descriptor;
-
-  left_descriptor = left.__type_descriptor;
-
-  if (left_descriptor == NULL && right.__type_descriptor == NULL)
-    return 0;
-  if (left_descriptor == NULL || right.__type_descriptor == NULL)
-    return 1;
-  if (!__go_type_descriptors_equal (left_descriptor,
-				    right.__type_descriptor))
-    return 1;
-  if (left_descriptor->__equalfn == NULL)
-    runtime_panicstring ("comparing uncomparable types");
-  if (__go_is_pointer_type (left_descriptor))
-    return left.__object == right.__object ? 0 : 1;
-  if (!__go_call_equalfn (left_descriptor->__equalfn, left.__object,
-			  right.__object, left_descriptor->__size))
-    return 1;
-  return 0;
-}
Index: libgo/runtime/go-eface-val-compare.c
===================================================================
--- libgo/runtime/go-eface-val-compare.c	(revision 241341)
+++ libgo/runtime/go-eface-val-compare.c	(working copy)
@@ -1,35 +0,0 @@
-/* go-eface-val-compare.c -- compare an empty interface with a value.
-
-   Copyright 2010 The Go Authors. All rights reserved.
-   Use of this source code is governed by a BSD-style
-   license that can be found in the LICENSE file.  */
-
-#include "runtime.h"
-#include "go-type.h"
-#include "interface.h"
-
-/* Compare an empty interface with a value.  Return 0 for equal, not
-   zero for not equal (return value is like strcmp).  */
-
-intgo
-__go_empty_interface_value_compare (
-    struct __go_empty_interface left,
-    const struct __go_type_descriptor *right_descriptor,
-    const void *val)
-{
-  const struct __go_type_descriptor *left_descriptor;
-
-  left_descriptor = left.__type_descriptor;
-  if (left_descriptor == NULL)
-    return 1;
-  if (!__go_type_descriptors_equal (left_descriptor, right_descriptor))
-    return 1;
-  if (left_descriptor->__equalfn == NULL)
-    runtime_panicstring ("comparing uncomparable types");
-  if (__go_is_pointer_type (left_descriptor))
-    return left.__object == val ? 0 : 1;
-  if (!__go_call_equalfn (left_descriptor->__equalfn, left.__object, val,
-			  left_descriptor->__size))
-    return 1;
-  return 0;
-}
Index: libgo/runtime/go-iface.goc
===================================================================
--- libgo/runtime/go-iface.goc	(revision 241341)
+++ libgo/runtime/go-iface.goc	(working copy)
@@ -1,130 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package runtime
-#include "runtime.h"
-#include "go-type.h"
-#include "interface.h"
-
-typedef struct __go_type_descriptor descriptor;
-typedef const struct __go_type_descriptor const_descriptor;
-typedef struct __go_interface interface;
-typedef struct __go_empty_interface empty_interface;
-
-// Compare two type descriptors.
-func ifacetypeeq(a *descriptor, b *descriptor) (eq bool) {
-	eq = __go_type_descriptors_equal(a, b);
-}
-
-// Return the descriptor for an empty interface type.n
-func efacetype(e empty_interface) (d *const_descriptor) {
-	return e.__type_descriptor;
-}
-
-// Return the descriptor for a non-empty interface type.
-func ifacetype(i interface) (d *const_descriptor) {
-	if (i.__methods == nil) {
-		return nil;
-	}
-	d = i.__methods[0];
-}
-
-// Convert an empty interface to an empty interface.
-func ifaceE2E2(e empty_interface) (ret empty_interface, ok bool) {
-	ret = e;
-	ok = ret.__type_descriptor != nil;
-}
-
-// Convert a non-empty interface to an empty interface.
-func ifaceI2E2(i interface) (ret empty_interface, ok bool) {
-	if (i.__methods == nil) {
-		ret.__type_descriptor = nil;
-		ret.__object = nil;
-		ok = 0;
-	} else {
-		ret.__type_descriptor = i.__methods[0];
-		ret.__object = i.__object;
-		ok = 1;
-	}
-}
-
-// Convert an empty interface to a non-empty interface.
-func ifaceE2I2(inter *descriptor, e empty_interface) (ret interface, ok bool) {
-	if (e.__type_descriptor == nil) {
-		ret.__methods = nil;
-		ret.__object = nil;
-		ok = 0;
-	} else {
-		ret.__methods = __go_convert_interface_2(inter,
-							 e.__type_descriptor,
-							 1);
-		ret.__object = e.__object;
-		ok = ret.__methods != nil;
-	}
-}
-
-// Convert a non-empty interface to a non-empty interface.
-func ifaceI2I2(inter *descriptor, i interface) (ret interface, ok bool) {
-	if (i.__methods == nil) {
-		ret.__methods = nil;
-		ret.__object = nil;
-		ok = 0;
-	} else {
-		ret.__methods = __go_convert_interface_2(inter,
-							 i.__methods[0], 1);
-		ret.__object = i.__object;
-		ok = ret.__methods != nil;
-	}
-}
-
-// Convert an empty interface to a pointer type.
-func ifaceE2T2P(inter *descriptor, e empty_interface) (ret *void, ok bool) {
-	if (!__go_type_descriptors_equal(inter, e.__type_descriptor)) {
-		ret = nil;
-		ok = 0;
-	} else {
-		ret = e.__object;
-		ok = 1;
-	}
-}
-
-// Convert a non-empty interface to a pointer type.
-func ifaceI2T2P(inter *descriptor, i interface) (ret *void, ok bool) {
-	if (i.__methods == nil
-	    || !__go_type_descriptors_equal(inter, i.__methods[0])) {
-		ret = nil;
-		ok = 0;
-	} else {
-		ret = i.__object;
-		ok = 1;
-	}
-}
-
-// Convert an empty interface to a non-pointer type.
-func ifaceE2T2(inter *descriptor, e empty_interface, ret *void) (ok bool) {
-	if (!__go_type_descriptors_equal(inter, e.__type_descriptor)) {
-		__builtin_memset(ret, 0, inter->__size);
-		ok = 0;
-	} else {
-		__builtin_memcpy(ret, e.__object, inter->__size);
-		ok = 1;
-	}
-}
-
-// Convert a non-empty interface to a non-pointer type.
-func ifaceI2T2(inter *descriptor, i interface, ret *void) (ok bool) {
-	if (i.__methods == nil
-	    || !__go_type_descriptors_equal(inter, i.__methods[0])) {
-		__builtin_memset(ret, 0, inter->__size);
-		ok = 0;
-	} else {
-		__builtin_memcpy(ret, i.__object, inter->__size);
-		ok = 1;
-	}
-}
-
-// Return whether we can convert an interface to a type.
-func ifaceI2Tp(to *descriptor, from *descriptor) (ok bool) {
-	ok = __go_can_convert_to_interface(to, from);
-}
Index: libgo/runtime/go-interface-compare.c
===================================================================
--- libgo/runtime/go-interface-compare.c	(revision 241341)
+++ libgo/runtime/go-interface-compare.c	(working copy)
@@ -1,37 +0,0 @@
-/* go-interface-compare.c -- compare two interface values.
-
-   Copyright 2009 The Go Authors. All rights reserved.
-   Use of this source code is governed by a BSD-style
-   license that can be found in the LICENSE file.  */
-
-#include <stddef.h>
-
-#include "runtime.h"
-#include "go-type.h"
-#include "interface.h"
-
-/* Compare two interface values.  Return 0 for equal, not zero for not
-   equal (return value is like strcmp).  */
-
-int
-__go_interface_compare (struct __go_interface left,
-			struct __go_interface right)
-{
-  const struct __go_type_descriptor *left_descriptor;
-
-  if (left.__methods == NULL && right.__methods == NULL)
-    return 0;
-  if (left.__methods == NULL || right.__methods == NULL)
-    return 1;
-  left_descriptor = left.__methods[0];
-  if (!__go_type_descriptors_equal (left_descriptor, right.__methods[0]))
-    return 1;
-  if (left_descriptor->__equalfn == NULL)
-    runtime_panicstring ("comparing uncomparable types");
-  if (__go_is_pointer_type (left_descriptor))
-    return left.__object == right.__object ? 0 : 1;
-  if (!__go_call_equalfn (left_descriptor->__equalfn, left.__object,
-			  right.__object, left_descriptor->__size))
-    return 1;
-  return 0;
-}
Index: libgo/runtime/go-interface-eface-compare.c
===================================================================
--- libgo/runtime/go-interface-eface-compare.c	(revision 241341)
+++ libgo/runtime/go-interface-eface-compare.c	(working copy)
@@ -1,36 +0,0 @@
-/* go-interface-eface-compare.c -- compare non-empty and empty interface.
-
-   Copyright 2011 The Go Authors. All rights reserved.
-   Use of this source code is governed by a BSD-style
-   license that can be found in the LICENSE file.  */
-
-#include "runtime.h"
-#include "go-type.h"
-#include "interface.h"
-
-/* Compare a non-empty interface value with an empty interface value.
-   Return 0 for equal, not zero for not equal (return value is like
-   strcmp).  */
-
-intgo
-__go_interface_empty_compare (struct __go_interface left,
-			      struct __go_empty_interface right)
-{
-  const struct __go_type_descriptor *left_descriptor;
-
-  if (left.__methods == NULL && right.__type_descriptor == NULL)
-    return 0;
-  if (left.__methods == NULL || right.__type_descriptor == NULL)
-    return 1;
-  left_descriptor = left.__methods[0];
-  if (!__go_type_descriptors_equal (left_descriptor, right.__type_descriptor))
-    return 1;
-  if (left_descriptor->__equalfn == NULL)
-    runtime_panicstring ("comparing uncomparable types");
-  if (__go_is_pointer_type (left_descriptor))
-    return left.__object == right.__object ? 0 : 1;
-  if (!__go_call_equalfn (left_descriptor->__equalfn, left.__object,
-			  right.__object, left_descriptor->__size))
-    return 1;
-  return 0;
-}
Index: libgo/runtime/go-interface-val-compare.c
===================================================================
--- libgo/runtime/go-interface-val-compare.c	(revision 241341)
+++ libgo/runtime/go-interface-val-compare.c	(working copy)
@@ -1,35 +0,0 @@
-/* go-interface-val-compare.c -- compare an interface to a value.
-
-   Copyright 2009 The Go Authors. All rights reserved.
-   Use of this source code is governed by a BSD-style
-   license that can be found in the LICENSE file.  */
-
-#include "runtime.h"
-#include "go-type.h"
-#include "interface.h"
-
-/* Compare two interface values.  Return 0 for equal, not zero for not
-   equal (return value is like strcmp).  */
-
-intgo
-__go_interface_value_compare (
-    struct __go_interface left,
-    const struct __go_type_descriptor *right_descriptor,
-    const void *val)
-{
-  const struct __go_type_descriptor *left_descriptor;
-
-  if (left.__methods == NULL)
-    return 1;
-  left_descriptor = left.__methods[0];
-  if (!__go_type_descriptors_equal (left_descriptor, right_descriptor))
-    return 1;
-  if (left_descriptor->__equalfn == NULL)
-    runtime_panicstring ("comparing uncomparable types");
-  if (__go_is_pointer_type (left_descriptor))
-    return left.__object == val ? 0 : 1;
-  if (!__go_call_equalfn (left_descriptor->__equalfn, left.__object, val,
-			  left_descriptor->__size))
-    return 1;
-  return 0;
-}
Index: libgo/runtime/go-panic.c
===================================================================
--- libgo/runtime/go-panic.c	(revision 241341)
+++ libgo/runtime/go-panic.c	(working copy)
@@ -12,7 +12,6 @@
 #include "malloc.h"
 #include "go-alloc.h"
 #include "go-panic.h"
-#include "interface.h"
 
 /* Print the panic stack.  This is used when there is no recover.  */
 
@@ -35,7 +34,7 @@ __printpanics (Panic *p)
    function.  */
 
 void
-__go_panic (struct __go_empty_interface arg)
+__go_panic (Eface arg)
 {
   G *g;
   Panic *n;
Index: libgo/runtime/go-panic.h
===================================================================
--- libgo/runtime/go-panic.h	(revision 241341)
+++ libgo/runtime/go-panic.h	(working copy)
@@ -7,24 +7,18 @@
 #ifndef LIBGO_GO_PANIC_H
 #define LIBGO_GO_PANIC_H
 
-#include "interface.h"
-
-struct String;
-struct __go_type_descriptor;
-
-extern void __go_panic (struct __go_empty_interface)
+extern void __go_panic (Eface)
   __attribute__ ((noreturn));
 
-extern void __go_print_string (struct String);
+extern void __go_print_string (String);
 
-extern struct __go_empty_interface __go_recover (void);
+extern Eface __go_recover (void);
 
 extern _Bool __go_can_recover (void *);
 
 extern void __go_makefunc_can_recover (void *retaddr);
 
-struct location;
-extern void __go_makefunc_ffi_can_recover (struct location *, int);
+extern void __go_makefunc_ffi_can_recover (Location*, int);
 
 extern void __go_makefunc_returning (void);
 
Index: libgo/runtime/go-recover.c
===================================================================
--- libgo/runtime/go-recover.c	(revision 241341)
+++ libgo/runtime/go-recover.c	(working copy)
@@ -5,7 +5,6 @@
    license that can be found in the LICENSE file.  */
 
 #include "runtime.h"
-#include "interface.h"
 #include "go-panic.h"
 
 /* If the top of the defer stack can be recovered, then return it.
@@ -200,7 +199,7 @@ __go_makefunc_can_recover (void *retaddr
    make the same decision.  */
 
 void
-__go_makefunc_ffi_can_recover (struct location *loc, int n)
+__go_makefunc_ffi_can_recover (Location *loc, int n)
 {
   Defer *d;
   const byte *name;
@@ -252,7 +251,7 @@ __go_makefunc_returning (void)
 /* This is only called when it is valid for the caller to recover the
    value on top of the panic stack, if there is one.  */
 
-struct __go_empty_interface
+Eface
 __go_recover ()
 {
   G *g;
@@ -262,10 +261,10 @@ __go_recover ()
 
   if (g->_panic == NULL || g->_panic->recovered)
     {
-      struct __go_empty_interface ret;
+      Eface ret;
 
-      ret.__type_descriptor = NULL;
-      ret.__object = NULL;
+      ret._type = NULL;
+      ret.data = NULL;
       return ret;
     }
   p = g->_panic;
Index: libgo/runtime/go-strcmp.c
===================================================================
--- libgo/runtime/go-strcmp.c	(revision 241341)
+++ libgo/runtime/go-strcmp.c	(working copy)
@@ -1,25 +0,0 @@
-/* go-strcmp.c -- the go string comparison function.
-
-   Copyright 2009 The Go Authors. All rights reserved.
-   Use of this source code is governed by a BSD-style
-   license that can be found in the LICENSE file.  */
-
-#include "runtime.h"
-
-intgo
-__go_strcmp(String s1, String s2)
-{
-  int i;
-
-  i = __builtin_memcmp(s1.str, s2.str,
-		       (s1.len < s2.len ? s1.len : s2.len));
-  if (i != 0)
-    return i;
-
-  if (s1.len < s2.len)
-    return -1;
-  else if (s1.len > s2.len)
-    return 1;
-  else
-    return 0;
-}
Index: libgo/runtime/go-strslice.c
===================================================================
--- libgo/runtime/go-strslice.c	(revision 241341)
+++ libgo/runtime/go-strslice.c	(working copy)
@@ -4,8 +4,8 @@
    Use of this source code is governed by a BSD-style
    license that can be found in the LICENSE file.  */
 
-#include "go-panic.h"
 #include "runtime.h"
+#include "go-panic.h"
 #include "arch.h"
 #include "malloc.h"
 
Index: libgo/runtime/go-type-eface.c
===================================================================
--- libgo/runtime/go-type-eface.c	(revision 241341)
+++ libgo/runtime/go-type-eface.c	(working copy)
@@ -1,66 +0,0 @@
-/* go-type-eface.c -- hash and equality empty interface functions.
-
-   Copyright 2010 The Go Authors. All rights reserved.
-   Use of this source code is governed by a BSD-style
-   license that can be found in the LICENSE file.  */
-
-#include "runtime.h"
-#include "interface.h"
-#include "go-type.h"
-
-/* A hash function for an empty interface.  */
-
-uintptr_t
-__go_type_hash_empty_interface (const void *vval, uintptr_t seed,
-				uintptr_t key_size __attribute__ ((unused)))
-{
-  const struct __go_empty_interface *val;
-  const struct __go_type_descriptor *descriptor;
-  uintptr_t size;
-
-  val = (const struct __go_empty_interface *) vval;
-  descriptor = val->__type_descriptor;
-  if (descriptor == NULL)
-    return 0;
-  if (descriptor->__hashfn == NULL)
-    runtime_panicstring ("hash of unhashable type");
-  size = descriptor->__size;
-  if (__go_is_pointer_type (descriptor))
-    return __go_call_hashfn (descriptor->__hashfn, &val->__object, seed, size);
-  else
-    return __go_call_hashfn (descriptor->__hashfn, val->__object, seed, size);
-}
-
-const FuncVal __go_type_hash_empty_interface_descriptor =
-  { (void *) __go_type_hash_empty_interface };
-
-/* An equality function for an empty interface.  */
-
-_Bool
-__go_type_equal_empty_interface (const void *vv1, const void *vv2,
-				 uintptr_t key_size __attribute__ ((unused)))
-{
-  const struct __go_empty_interface *v1;
-  const struct __go_empty_interface *v2;
-  const struct __go_type_descriptor* v1_descriptor;
-  const struct __go_type_descriptor* v2_descriptor;
-
-  v1 = (const struct __go_empty_interface *) vv1;
-  v2 = (const struct __go_empty_interface *) vv2;
-  v1_descriptor = v1->__type_descriptor;
-  v2_descriptor = v2->__type_descriptor;
-  if (v1_descriptor == NULL || v2_descriptor == NULL)
-    return v1_descriptor == v2_descriptor;
-  if (!__go_type_descriptors_equal (v1_descriptor, v2_descriptor))
-    return 0;
-  if (v1_descriptor->__equalfn == NULL)
-    runtime_panicstring ("comparing uncomparable types");
-  if (__go_is_pointer_type (v1_descriptor))
-    return v1->__object == v2->__object;
-  else
-    return __go_call_equalfn (v1_descriptor->__equalfn, v1->__object,
-			      v2->__object, v1_descriptor->__size);
-}
-
-const FuncVal __go_type_equal_empty_interface_descriptor =
-  { (void *) __go_type_equal_empty_interface };
Index: libgo/runtime/go-type-interface.c
===================================================================
--- libgo/runtime/go-type-interface.c	(revision 241341)
+++ libgo/runtime/go-type-interface.c	(working copy)
@@ -1,66 +0,0 @@
-/* go-type-interface.c -- hash and equality interface functions.
-
-   Copyright 2009 The Go Authors. All rights reserved.
-   Use of this source code is governed by a BSD-style
-   license that can be found in the LICENSE file.  */
-
-#include "runtime.h"
-#include "interface.h"
-#include "go-type.h"
-
-/* A hash function for an interface.  */
-
-uintptr_t
-__go_type_hash_interface (const void *vval, uintptr_t seed,
-			  uintptr_t key_size __attribute__ ((unused)))
-{
-  const struct __go_interface *val;
-  const struct __go_type_descriptor *descriptor;
-  uintptr_t size;
-
-  val = (const struct __go_interface *) vval;
-  if (val->__methods == NULL)
-    return 0;
-  descriptor = (const struct __go_type_descriptor *) val->__methods[0];
-  if (descriptor->__hashfn == NULL)
-    runtime_panicstring ("hash of unhashable type");
-  size = descriptor->__size;
-  if (__go_is_pointer_type (descriptor))
-    return __go_call_hashfn (descriptor->__hashfn, &val->__object, seed, size);
-  else
-    return __go_call_hashfn (descriptor->__hashfn, val->__object, seed, size);
-}
-
-const FuncVal __go_type_hash_interface_descriptor =
-  { (void *) __go_type_hash_interface };
-
-/* An equality function for an interface.  */
-
-_Bool
-__go_type_equal_interface (const void *vv1, const void *vv2,
-			   uintptr_t key_size __attribute__ ((unused)))
-{
-  const struct __go_interface *v1;
-  const struct __go_interface *v2;
-  const struct __go_type_descriptor* v1_descriptor;
-  const struct __go_type_descriptor* v2_descriptor;
-
-  v1 = (const struct __go_interface *) vv1;
-  v2 = (const struct __go_interface *) vv2;
-  if (v1->__methods == NULL || v2->__methods == NULL)
-    return v1->__methods == v2->__methods;
-  v1_descriptor = (const struct __go_type_descriptor *) v1->__methods[0];
-  v2_descriptor = (const struct __go_type_descriptor *) v2->__methods[0];
-  if (!__go_type_descriptors_equal (v1_descriptor, v2_descriptor))
-    return 0;
-  if (v1_descriptor->__equalfn == NULL)
-    runtime_panicstring ("comparing uncomparable types");
-  if (__go_is_pointer_type (v1_descriptor))
-    return v1->__object == v2->__object;
-  else
-    return __go_call_equalfn (v1_descriptor->__equalfn, v1->__object,
-			      v2->__object, v1_descriptor->__size);
-}
-
-const FuncVal __go_type_equal_interface_descriptor =
-  { (void *) __go_type_equal_interface };
Index: libgo/runtime/go-unsafe-new.c
===================================================================
--- libgo/runtime/go-unsafe-new.c	(revision 241341)
+++ libgo/runtime/go-unsafe-new.c	(working copy)
@@ -8,7 +8,6 @@
 #include "arch.h"
 #include "malloc.h"
 #include "go-type.h"
-#include "interface.h"
 
 /* Implement unsafe_New, called from the reflect package.  */
 
Index: libgo/runtime/go-unsafe-newarray.c
===================================================================
--- libgo/runtime/go-unsafe-newarray.c	(revision 241341)
+++ libgo/runtime/go-unsafe-newarray.c	(working copy)
@@ -8,7 +8,6 @@
 #include "arch.h"
 #include "malloc.h"
 #include "go-type.h"
-#include "interface.h"
 
 /* Implement unsafe_NewArray, called from the reflect package.  */
 
Index: libgo/runtime/go-unwind.c
===================================================================
--- libgo/runtime/go-unwind.c	(revision 241341)
+++ libgo/runtime/go-unwind.c	(working copy)
@@ -67,8 +67,8 @@ __go_check_defer (_Bool *frame)
 
       n = (Panic *) __go_alloc (sizeof (Panic));
 
-      n->arg.__type_descriptor = NULL;
-      n->arg.__object = NULL;
+      n->arg._type = NULL;
+      n->arg.data = NULL;
       n->recovered = 0;
       n->isforeign = 1;
       n->next = g->_panic;
Index: libgo/runtime/heapdump.c
===================================================================
--- libgo/runtime/heapdump.c	(revision 241341)
+++ libgo/runtime/heapdump.c	(working copy)
@@ -298,8 +298,8 @@ dumpgoroutine(G *gp)
 		dumpint(TagPanic);
 		dumpint((uintptr)p);
 		dumpint((uintptr)gp);
-		dumpint((uintptr)p->arg.__type_descriptor);
-		dumpint((uintptr)p->arg.__object);
+		dumpint((uintptr)p->arg._type);
+		dumpint((uintptr)p->arg.data);
 		dumpint((uintptr)0);
 		dumpint((uintptr)p->next);
 	}
Index: libgo/runtime/interface.h
===================================================================
--- libgo/runtime/interface.h	(revision 241341)
+++ libgo/runtime/interface.h	(working copy)
@@ -1,57 +0,0 @@
-/* interface.h -- the interface type for Go.
-
-   Copyright 2009 The Go Authors. All rights reserved.
-   Use of this source code is governed by a BSD-style
-   license that can be found in the LICENSE file.  */
-
-#ifndef LIBGO_INTERFACE_H
-#define LIBGO_INTERFACE_H
-
-struct __go_type_descriptor;
-
-/* A variable of interface type is an instance of this struct, if the
-   interface has any methods.  */
-
-struct __go_interface
-{
-  /* A pointer to the interface method table.  The first pointer is
-     the type descriptor of the object.  Subsequent pointers are
-     pointers to functions.  This is effectively the vtable for this
-     interface.  The function pointers are in the same order as the
-     list in the internal representation of the interface, which sorts
-     them by name.  */
-  const void **__methods;
-
-  /* The object.  If the object is a pointer--if the type descriptor
-     code is GO_PTR or GO_UNSAFE_POINTER--then this field is the value
-     of the object itself.  Otherwise this is a pointer to memory
-     which holds the value.  */
-  void *__object;
-};
-
-/* A variable of an empty interface type is an instance of this
-   struct.  */
-
-struct __go_empty_interface
-{
-  /* The type descriptor of the object.  */
-  const struct __go_type_descriptor *__type_descriptor;
-
-  /* The object.  This is the same as __go_interface above.  */
-  void *__object;
-};
-
-extern void *
-__go_convert_interface (const struct __go_type_descriptor *,
-			const struct __go_type_descriptor *);
-
-extern void *
-__go_convert_interface_2 (const struct __go_type_descriptor *,
-			  const struct __go_type_descriptor *,
-			  _Bool may_fail);
-
-extern _Bool
-__go_can_convert_to_interface(const struct __go_type_descriptor *,
-			      const struct __go_type_descriptor *);
-
-#endif /* !defined(LIBGO_INTERFACE_H) */
Index: libgo/runtime/malloc.goc
===================================================================
--- libgo/runtime/malloc.goc	(revision 241341)
+++ libgo/runtime/malloc.goc	(working copy)
@@ -14,12 +14,9 @@ package runtime
 #include "runtime.h"
 #include "arch.h"
 #include "malloc.h"
-#include "interface.h"
 #include "go-type.h"
 
 // Map gccgo field names to gc field names.
-// Eface aka __go_empty_interface.
-#define type __type_descriptor
 // Type aka __go_type_descriptor
 #define kind __code
 #define string __reflection
@@ -917,15 +914,15 @@ func SetFinalizer(obj Eface, finalizer E
 	const Type *fint;
 	const PtrType *ot;
 
-	if(obj.__type_descriptor == nil) {
+	if((Type*)obj._type == nil) {
 		runtime_printf("runtime.SetFinalizer: first argument is nil interface\n");
 		goto throw;
 	}
-	if((obj.__type_descriptor->kind&kindMask) != GO_PTR) {
-		runtime_printf("runtime.SetFinalizer: first argument is %S, not pointer\n", *obj.__type_descriptor->__reflection);
+	if((((Type*)obj._type)->kind&kindMask) != GO_PTR) {
+		runtime_printf("runtime.SetFinalizer: first argument is %S, not pointer\n", *((Type*)obj._type)->__reflection);
 		goto throw;
 	}
-	ot = (const PtrType*)obj.type;
+	ot = (const PtrType*)obj._type;
 	// As an implementation detail we do not run finalizers for zero-sized objects,
 	// because we use &runtime_zerobase for all such allocations.
 	if(ot->__element_type != nil && ot->__element_type->__size == 0)
@@ -937,49 +934,49 @@ func SetFinalizer(obj Eface, finalizer E
 	//		runtime.SetFinalizer(Foo, nil)
 	//	}
 	// See issue 7656.
-	if((byte*)obj.__object < runtime_mheap.arena_start || runtime_mheap.arena_used <= (byte*)obj.__object)
+	if((byte*)obj.data < runtime_mheap.arena_start || runtime_mheap.arena_used <= (byte*)obj.data)
 		return;
-	if(!runtime_mlookup(obj.__object, &base, &size, nil) || obj.__object != base) {
+	if(!runtime_mlookup(obj.data, &base, &size, nil) || obj.data != base) {
 		// As an implementation detail we allow to set finalizers for an inner byte
 		// of an object if it could come from tiny alloc (see mallocgc for details).
 		if(ot->__element_type == nil || (ot->__element_type->kind&kindNoPointers) == 0 || ot->__element_type->__size >= TinySize) {
-			runtime_printf("runtime.SetFinalizer: pointer not at beginning of allocated block (%p)\n", obj.__object);
+			runtime_printf("runtime.SetFinalizer: pointer not at beginning of allocated block (%p)\n", obj.data);
 			goto throw;
 		}
 	}
-	if(finalizer.__type_descriptor != nil) {
+	if((Type*)finalizer._type != nil) {
 		runtime_createfing();
-		if((finalizer.__type_descriptor->kind&kindMask) != GO_FUNC)
+		if((((Type*)finalizer._type)->kind&kindMask) != GO_FUNC)
 			goto badfunc;
-		ft = (const FuncType*)finalizer.__type_descriptor;
+		ft = (const FuncType*)finalizer._type;
 		if(ft->__dotdotdot || ft->__in.__count != 1)
 			goto badfunc;
 		fint = *(Type**)ft->__in.__values;
-		if(__go_type_descriptors_equal(fint, obj.__type_descriptor)) {
+		if(__go_type_descriptors_equal(fint, (Type*)obj._type)) {
 			// ok - same type
-		} else if((fint->kind&kindMask) == GO_PTR && (fint->__uncommon == nil || fint->__uncommon->__name == nil || obj.type->__uncommon == nil || obj.type->__uncommon->__name == nil) && __go_type_descriptors_equal(((const PtrType*)fint)->__element_type, ((const PtrType*)obj.type)->__element_type)) {
+		} else if((fint->kind&kindMask) == GO_PTR && (fint->__uncommon == nil || fint->__uncommon->__name == nil || ((Type*)obj._type)->__uncommon == nil || ((Type*)obj._type)->__uncommon->__name == nil) && __go_type_descriptors_equal(((const PtrType*)fint)->__element_type, ((const PtrType*)obj._type)->__element_type)) {
 			// ok - not same type, but both pointers,
 			// one or the other is unnamed, and same element type, so assignable.
 		} else if((fint->kind&kindMask) == GO_INTERFACE && ((const InterfaceType*)fint)->__methods.__count == 0) {
 			// ok - satisfies empty interface
-		} else if((fint->kind&kindMask) == GO_INTERFACE && __go_convert_interface_2(fint, obj.__type_descriptor, 1) != nil) {
+		} else if((fint->kind&kindMask) == GO_INTERFACE && getitab(fint, (Type*)obj._type, true) != nil) {
 			// ok - satisfies non-empty interface
 		} else
 			goto badfunc;
 
-		ot = (const PtrType*)obj.__type_descriptor;
-		if(!runtime_addfinalizer(obj.__object, *(FuncVal**)finalizer.__object, ft, ot)) {
+		ot = (const PtrType*)obj._type;
+		if(!runtime_addfinalizer(obj.data, *(FuncVal**)finalizer.data, ft, ot)) {
 			runtime_printf("runtime.SetFinalizer: finalizer already set\n");
 			goto throw;
 		}
 	} else {
 		// NOTE: asking to remove a finalizer when there currently isn't one set is OK.
-		runtime_removefinalizer(obj.__object);
+		runtime_removefinalizer(obj.data);
 	}
 	return;
 
 badfunc:
-	runtime_printf("runtime.SetFinalizer: cannot pass %S to finalizer %S\n", *obj.__type_descriptor->__reflection, *finalizer.__type_descriptor->__reflection);
+	runtime_printf("runtime.SetFinalizer: cannot pass %S to finalizer %S\n", *((Type*)obj._type)->__reflection, *((Type*)finalizer._type)->__reflection);
 throw:
 	runtime_throw("runtime.SetFinalizer");
 }
Index: libgo/runtime/mgc0.c
===================================================================
--- libgo/runtime/mgc0.c	(revision 241341)
+++ libgo/runtime/mgc0.c	(working copy)
@@ -62,8 +62,6 @@
 // Slice aka __go_open_array.
 #define array __values
 #define cap __capacity
-// Iface aka __go_interface
-#define tab __methods
 // Hmap aka __go_map
 typedef struct __go_map Hmap;
 // Type aka __go_type_descriptor
@@ -907,12 +905,12 @@ scanblock(Workbuf *wbuf, bool keepworkin
 			eface = (Eface*)(stack_top.b + pc[1]);
 			pc += 2;
 			if(Debug > 2)
-				runtime_printf("gc_eface @%p: %p %p\n", stack_top.b+pc[1], eface->__type_descriptor, eface->__object);
-			if(eface->__type_descriptor == nil)
+				runtime_printf("gc_eface @%p: %p %p\n", stack_top.b+pc[1], eface->_type, eface->data);
+			if(eface->_type == nil)
 				continue;
 
 			// eface->type
-			t = eface->__type_descriptor;
+			t = eface->_type;
 			if((const byte*)t >= arena_start && (const byte*)t < arena_used) {
 				union { const Type *tc; Type *tr; } u;
 				u.tc = t;
@@ -921,13 +919,13 @@ scanblock(Workbuf *wbuf, bool keepworkin
 					flushptrbuf(&sbuf);
 			}
 
-			// eface->__object
-			if((byte*)eface->__object >= arena_start && (byte*)eface->__object < arena_used) {
+			// eface->data
+			if((byte*)eface->data >= arena_start && (byte*)eface->data < arena_used) {
 				if(__go_is_pointer_type(t)) {
 					if((t->__code & kindNoPointers))
 						continue;
 
-					obj = eface->__object;
+					obj = eface->data;
 					if((t->__code & kindMask) == kindPtr) {
 						// Only use type information if it is a pointer-containing type.
 						// This matches the GC programs written by cmd/gc/reflect.c's
@@ -937,7 +935,7 @@ scanblock(Workbuf *wbuf, bool keepworkin
 							objti = (uintptr)((const PtrType*)t)->elem->__gc;
 					}
 				} else {
-					obj = eface->__object;
+					obj = eface->data;
 					objti = (uintptr)t->__gc;
 				}
 			}
@@ -947,7 +945,7 @@ scanblock(Workbuf *wbuf, bool keepworkin
 			iface = (Iface*)(stack_top.b + pc[1]);
 			pc += 2;
 			if(Debug > 2)
-				runtime_printf("gc_iface @%p: %p/%p %p\n", stack_top.b+pc[1], iface->__methods[0], nil, iface->__object);
+				runtime_printf("gc_iface @%p: %p/%p %p\n", stack_top.b+pc[1], *(Type**)iface->tab, nil, iface->data);
 			if(iface->tab == nil)
 				continue;
 			
@@ -959,13 +957,13 @@ scanblock(Workbuf *wbuf, bool keepworkin
 			}
 
 			// iface->data
-			if((byte*)iface->__object >= arena_start && (byte*)iface->__object < arena_used) {
-				t = (const Type*)iface->tab[0];
+			if((byte*)iface->data >= arena_start && (byte*)iface->data < arena_used) {
+				t = *(Type**)iface->tab;
 				if(__go_is_pointer_type(t)) {
 					if((t->__code & kindNoPointers))
 						continue;
 
-					obj = iface->__object;
+					obj = iface->data;
 					if((t->__code & kindMask) == kindPtr) {
 						// Only use type information if it is a pointer-containing type.
 						// This matches the GC programs written by cmd/gc/reflect.c's
@@ -975,7 +973,7 @@ scanblock(Workbuf *wbuf, bool keepworkin
 							objti = (uintptr)((const PtrType*)t)->elem->__gc;
 					}
 				} else {
-					obj = iface->__object;
+					obj = iface->data;
 					objti = (uintptr)t->__gc;
 				}
 			}
@@ -2448,8 +2446,8 @@ runfinq(void* dummy __attribute__ ((unus
 	fb = nil;
 	next = nil;
 	i = 0;
-	ef.__type_descriptor = nil;
-	ef.__object = nil;
+	ef._type = nil;
+	ef.data = nil;
 	
 	// force flush to memory
 	USED(&f);
@@ -2483,16 +2481,18 @@ runfinq(void* dummy __attribute__ ((unus
 					param = &f->arg;
 				} else if(((const InterfaceType*)fint)->__methods.__count == 0) {
 					// convert to empty interface
-					ef.__type_descriptor = (const Type*)f->ot;
-					ef.__object = f->arg;
+					// using memcpy as const_cast.
+					memcpy(&ef._type, &f->ot,
+					       sizeof ef._type);
+					ef.data = f->arg;
 					param = &ef;
 				} else {
 					// convert to interface with methods
-					iface.__methods = __go_convert_interface_2((const Type*)fint,
-										   (const Type*)f->ot,
-										   1);
-					iface.__object = f->arg;
-					if(iface.__methods == nil)
+					iface.tab = getitab(fint,
+							    (const Type*)f->ot,
+							    true);
+					iface.data = f->arg;
+					if(iface.data == nil)
 						runtime_throw("invalid type conversion in runfinq");
 					param = &iface;
 				}
@@ -2514,8 +2514,8 @@ runfinq(void* dummy __attribute__ ((unus
 		fb = nil;
 		next = nil;
 		i = 0;
-		ef.__type_descriptor = nil;
-		ef.__object = nil;
+		ef._type = nil;
+		ef.data = nil;
 		runtime_gc(1);	// trigger another gc to clean up the finalized objects, if possible
 	}
 }
Index: libgo/runtime/reflect.goc
===================================================================
--- libgo/runtime/reflect.goc	(revision 241341)
+++ libgo/runtime/reflect.goc	(working copy)
@@ -1,25 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package reflect
-#include "runtime.h"
-#include "go-type.h"
-#include "interface.h"
-#include "go-panic.h"
-
-func ifaceE2I(inter *Type, e Eface, ret *Iface) {
-	const Type *t;
-	Eface err;
-
-	t = e.__type_descriptor;
-	if(t == nil) {
-		// explicit conversions require non-nil interface value.
-		runtime_newTypeAssertionError(
-			nil, nil, inter->__reflection,
-			nil, &err);
-		runtime_panic(err);
-	}
-	ret->__object = e.__object;
-	ret->__methods = __go_convert_interface(inter, t);
-}
Index: libgo/runtime/runtime.h
===================================================================
--- libgo/runtime/runtime.h	(revision 241341)
+++ libgo/runtime/runtime.h	(working copy)
@@ -22,7 +22,6 @@
 #include <sys/mman.h>
 #endif
 
-#include "interface.h"
 #include "go-alloc.h"
 
 #define _STRINGIFY2_(x) #x
@@ -76,8 +75,8 @@ typedef	struct	PollDesc	PollDesc;
 typedef	struct	sudog		SudoG;
 
 typedef	struct	__go_open_array		Slice;
-typedef struct	__go_interface		Iface;
-typedef	struct	__go_empty_interface	Eface;
+typedef	struct	iface			Iface;
+typedef	struct	eface			Eface;
 typedef	struct	__go_type_descriptor	Type;
 typedef	struct	_defer			Defer;
 typedef	struct	_panic			Panic;
@@ -105,7 +104,6 @@ struct FuncVal
 };
 
 #include "array.h"
-#include "interface.h"
 
 // Rename Go types generated by mkrsysinfo.sh from C types, to avoid
 // the name conflict.
@@ -587,3 +585,7 @@ extern _Bool runtime_iscgo;
 extern _Bool runtime_cgoHasExtraM;
 extern Hchan *runtime_main_init_done;
 extern uintptr __go_end __attribute__ ((weak));
+extern void *getitab(const struct __go_type_descriptor *,
+		     const struct __go_type_descriptor *,
+		     _Bool)
+  __asm__ (GOSYM_PREFIX "runtime.getitab");
Index: libgo/runtime/runtime1.goc
===================================================================
--- libgo/runtime/runtime1.goc	(revision 241341)
+++ libgo/runtime/runtime1.goc	(working copy)
@@ -40,7 +40,7 @@ func parForIters(desc *ParFor, tid uintp
 }
 
 func typestring(e Eface) (s String) {
-	s = *e.__type_descriptor->__reflection;
+	s = *((Type*)e._type)->__reflection;
 }
 
 func golockedOSThread() (ret bool) {


More information about the Gcc-patches mailing list