Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE	(revision 240942)
+++ gcc/go/gofrontend/MERGE	(working copy)
@@ -1,4 +1,4 @@
-f3658aea2493c7f1c4a72502f9e7da562c7764c4
+ecf9b645cefc5c3b4e6339adeb452b2d8642cf3e
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
Index: gcc/go/gofrontend/expressions.cc
===================================================================
--- gcc/go/gofrontend/expressions.cc	(revision 240942)
+++ gcc/go/gofrontend/expressions.cc	(working copy)
@@ -7018,6 +7018,26 @@ Builtin_call_expression::do_lower(Gogo*
 	  }
       }
       break;
+
+    case BUILTIN_PRINT:
+    case BUILTIN_PRINTLN:
+      // Force all the arguments into temporary variables, so that we
+      // don't try to evaluate something while holding the print lock.
+      if (this->args() == NULL)
+	break;
+      for (Expression_list::iterator pa = this->args()->begin();
+	   pa != this->args()->end();
+	   ++pa)
+	{
+	  if (!(*pa)->is_variable())
+	    {
+	      Temporary_statement* temp =
+		Statement::make_temporary(NULL, *pa, loc);
+	      inserter->insert(temp);
+	      *pa = Expression::make_temporary_reference(temp, loc);
+	    }
+	}
+      break;
     }
 
   return this;
@@ -8336,7 +8356,9 @@ Builtin_call_expression::do_get_backend(
     case BUILTIN_PRINTLN:
       {
 	const bool is_ln = this->code_ == BUILTIN_PRINTLN;
-        Expression* print_stmts = NULL;
+
+	Expression* print_stmts = Runtime::make_call(Runtime::PRINTLOCK,
+						     location, 0);
 
 	const Expression_list* call_args = this->args();
 	if (call_args != NULL)
@@ -8348,8 +8370,7 @@ Builtin_call_expression::do_get_backend(
 		if (is_ln && p != call_args->begin())
 		  {
                     Expression* print_space =
-                        Runtime::make_call(Runtime::PRINT_SPACE,
-                                           this->location(), 0);
+		      Runtime::make_call(Runtime::PRINTSP, location, 0);
 
                     print_stmts =
                         Expression::make_compound(print_stmts, print_space,
@@ -8360,51 +8381,51 @@ Builtin_call_expression::do_get_backend(
 		Type* type = arg->type();
                 Runtime::Function code;
 		if (type->is_string_type())
-                  code = Runtime::PRINT_STRING;
+                  code = Runtime::PRINTSTRING;
 		else if (type->integer_type() != NULL
 			 && type->integer_type()->is_unsigned())
 		  {
 		    Type* itype = Type::lookup_integer_type("uint64");
 		    arg = Expression::make_cast(itype, arg, location);
-                    code = Runtime::PRINT_UINT64;
+                    code = Runtime::PRINTUINT;
 		  }
 		else if (type->integer_type() != NULL)
 		  {
 		    Type* itype = Type::lookup_integer_type("int64");
 		    arg = Expression::make_cast(itype, arg, location);
-                    code = Runtime::PRINT_INT64;
+                    code = Runtime::PRINTINT;
 		  }
 		else if (type->float_type() != NULL)
 		  {
                     Type* dtype = Type::lookup_float_type("float64");
                     arg = Expression::make_cast(dtype, arg, location);
-                    code = Runtime::PRINT_DOUBLE;
+                    code = Runtime::PRINTFLOAT;
 		  }
 		else if (type->complex_type() != NULL)
 		  {
                     Type* ctype = Type::lookup_complex_type("complex128");
                     arg = Expression::make_cast(ctype, arg, location);
-                    code = Runtime::PRINT_COMPLEX;
+                    code = Runtime::PRINTCOMPLEX;
 		  }
 		else if (type->is_boolean_type())
-                  code = Runtime::PRINT_BOOL;
+                  code = Runtime::PRINTBOOL;
 		else if (type->points_to() != NULL
 			 || type->channel_type() != NULL
 			 || type->map_type() != NULL
 			 || type->function_type() != NULL)
 		  {
                     arg = Expression::make_cast(type, arg, location);
-                    code = Runtime::PRINT_POINTER;
+                    code = Runtime::PRINTPOINTER;
 		  }
 		else if (type->interface_type() != NULL)
 		  {
 		    if (type->interface_type()->is_empty())
-                      code = Runtime::PRINT_EMPTY_INTERFACE;
+                      code = Runtime::PRINTEFACE;
 		    else
-                      code = Runtime::PRINT_INTERFACE;
+                      code = Runtime::PRINTIFACE;
 		  }
 		else if (type->is_slice_type())
-                  code = Runtime::PRINT_SLICE;
+                  code = Runtime::PRINTSLICE;
 		else
 		  {
 		    go_assert(saw_errors());
@@ -8412,30 +8433,22 @@ Builtin_call_expression::do_get_backend(
 		  }
 
                 Expression* call = Runtime::make_call(code, location, 1, arg);
-                if (print_stmts == NULL)
-                  print_stmts = call;
-                else
-                  print_stmts = Expression::make_compound(print_stmts, call,
-                                                          location);
+		print_stmts = Expression::make_compound(print_stmts, call,
+							location);
 	      }
 	  }
 
 	if (is_ln)
 	  {
             Expression* print_nl =
-                Runtime::make_call(Runtime::PRINT_NL, location, 0);
-            if (print_stmts == NULL)
-              print_stmts = print_nl;
-            else
-              print_stmts = Expression::make_compound(print_stmts, print_nl,
-                                                      location);
+                Runtime::make_call(Runtime::PRINTNL, location, 0);
+	    print_stmts = Expression::make_compound(print_stmts, print_nl,
+						    location);
 	  }
 
-        // There aren't any arguments to the print builtin.  The compiler
-        // issues a warning for this so we should avoid getting the backend
-        // representation for this call.  Instead, perform a no-op.
-        if (print_stmts == NULL)
-          return context->backend()->boolean_constant_expression(false);
+	Expression* unlock = Runtime::make_call(Runtime::PRINTUNLOCK,
+						location, 0);
+	print_stmts = Expression::make_compound(print_stmts, unlock, location);
 
         return print_stmts->get_backend(context);
       }
Index: gcc/go/gofrontend/runtime.def
===================================================================
--- gcc/go/gofrontend/runtime.def	(revision 240942)
+++ gcc/go/gofrontend/runtime.def	(working copy)
@@ -299,42 +299,47 @@ DEF_GO_RUNTIME(INTERFACE_EMPTY_COMPARE,
 	       P2(IFACE, EFACE), R1(INT))
 
 
+// Lock the printer (for print/println).
+DEF_GO_RUNTIME(PRINTLOCK, "runtime.printlock", P0(), R0())
+
+// Unlock the printer (for print/println).
+DEF_GO_RUNTIME(PRINTUNLOCK, "runtime.printunlock", P0(), R0())
+
 // Print a string (for print/println).
-DEF_GO_RUNTIME(PRINT_STRING, "__go_print_string", P1(STRING), R0())
+DEF_GO_RUNTIME(PRINTSTRING, "runtime.printstring", P1(STRING), R0())
 
 // Print a uint64 (for print/println).
-DEF_GO_RUNTIME(PRINT_UINT64, "__go_print_uint64", P1(UINT64), R0())
+DEF_GO_RUNTIME(PRINTUINT, "runtime.printuint", P1(UINT64), R0())
 
 // Print a int64 (for print/println).
-DEF_GO_RUNTIME(PRINT_INT64, "__go_print_int64", P1(INT64), R0())
+DEF_GO_RUNTIME(PRINTINT, "runtime.printint", P1(INT64), R0())
 
 // Print a float64 (for print/println).
-DEF_GO_RUNTIME(PRINT_DOUBLE, "__go_print_double", P1(FLOAT64), R0())
+DEF_GO_RUNTIME(PRINTFLOAT, "runtime.printfloat", P1(FLOAT64), R0())
 
 // Print a complex128 (for print/println).
-DEF_GO_RUNTIME(PRINT_COMPLEX, "__go_print_complex", P1(COMPLEX128), R0())
+DEF_GO_RUNTIME(PRINTCOMPLEX, "runtime.printcomplex", P1(COMPLEX128), R0())
 
 // Print a bool (for print/println).
-DEF_GO_RUNTIME(PRINT_BOOL, "__go_print_bool", P1(BOOL), R0())
+DEF_GO_RUNTIME(PRINTBOOL, "runtime.printbool", P1(BOOL), R0())
 
 // Print a pointer/map/channel/function (for print/println).
-DEF_GO_RUNTIME(PRINT_POINTER, "__go_print_pointer", P1(POINTER), R0())
+DEF_GO_RUNTIME(PRINTPOINTER, "runtime.printpointer", P1(POINTER), R0())
 
 // Print an empty interface (for print/println).
-DEF_GO_RUNTIME(PRINT_EMPTY_INTERFACE, "__go_print_empty_interface",
-	       P1(EFACE), R0())
+DEF_GO_RUNTIME(PRINTEFACE, "runtime.printeface", P1(EFACE), R0())
 
 // Print a non-empty interface (for print/println).
-DEF_GO_RUNTIME(PRINT_INTERFACE, "__go_print_interface", P1(IFACE), R0())
+DEF_GO_RUNTIME(PRINTIFACE, "runtime.printiface", P1(IFACE), R0())
 
 // Print a slice (for print/println).
-DEF_GO_RUNTIME(PRINT_SLICE, "__go_print_slice", P1(SLICE), R0())
+DEF_GO_RUNTIME(PRINTSLICE, "runtime.printslice", P1(SLICE), R0())
 
 // Print a space (for println).
-DEF_GO_RUNTIME(PRINT_SPACE, "__go_print_space", P0(), R0())
+DEF_GO_RUNTIME(PRINTSP, "runtime.printsp", P0(), R0())
 
 // Print a newline (for println).
-DEF_GO_RUNTIME(PRINT_NL, "__go_print_nl", P0(), R0())
+DEF_GO_RUNTIME(PRINTNL, "runtime.printnl", P0(), R0())
 
 
 // Used for field tracking for data analysis.
Index: libgo/Makefile.am
===================================================================
--- libgo/Makefile.am	(revision 240942)
+++ libgo/Makefile.am	(working copy)
@@ -474,7 +474,6 @@ runtime_files = \
 	runtime/go-new.c \
 	runtime/go-nosys.c \
 	runtime/go-panic.c \
-	runtime/go-print.c \
 	runtime/go-recover.c \
 	runtime/go-reflect-call.c \
 	runtime/go-rune.c \
Index: libgo/go/runtime/print.go
===================================================================
--- libgo/go/runtime/print.go	(revision 240942)
+++ libgo/go/runtime/print.go	(working copy)
@@ -2,12 +2,32 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build ignore
-
 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 printbool runtime.printbool
+//go:linkname printfloat runtime.printfloat
+//go:linkname printint runtime.printint
+//go:linkname printhex runtime.printhex
+//go:linkname printuint runtime.printuint
+//go:linkname printcomplex runtime.printcomplex
+//go:linkname printstring runtime.printstring
+//go:linkname printpointer runtime.printpointer
+//go:linkname printiface runtime.printiface
+//go:linkname printeface runtime.printeface
+//go:linkname printslice runtime.printslice
+//go:linkname printnl runtime.printnl
+//go:linkname printsp runtime.printsp
+//go:linkname printlock runtime.printlock
+//go:linkname printunlock runtime.printunlock
+// Temporary for C code to call:
+//go:linkname gwrite runtime.gwrite
+//go:linkname printhex runtime.printhex
+
 // The compiler knows that a print of a value of this type
 // should use printhex instead of printuint (decimal).
 type hex uint64
@@ -201,10 +221,6 @@ func printpointer(p unsafe.Pointer) {
 }
 
 func printstring(s string) {
-	if uintptr(len(s)) > maxstring {
-		gwrite(bytes("[string too long]"))
-		return
-	}
 	gwrite(bytes(s))
 }
 
Index: libgo/go/runtime/runtime2.go
===================================================================
--- libgo/go/runtime/runtime2.go	(revision 240942)
+++ libgo/go/runtime/runtime2.go	(working copy)
@@ -347,20 +347,14 @@ type g struct {
 	tracelastp     puintptr // last P emitted an event for this goroutine
 	lockedm        *m
 	sig            uint32
-
-	// Temporary gccgo field.
-	writenbuf int32
-	// Not for gccgo yet: writebuf       []byte
-	// Temporary different type for gccgo.
-	writebuf *byte
-
-	sigcode0 uintptr
-	sigcode1 uintptr
-	sigpc    uintptr
-	gopc     uintptr // pc of go statement that created this goroutine
-	startpc  uintptr // pc of goroutine function
-	racectx  uintptr
-	waiting  *sudog // sudog structures this g is waiting on (that have a valid elem ptr); in lock order
+	writebuf       []byte
+	sigcode0       uintptr
+	sigcode1       uintptr
+	sigpc          uintptr
+	gopc           uintptr // pc of go statement that created this goroutine
+	startpc        uintptr // pc of goroutine function
+	racectx        uintptr
+	waiting        *sudog // sudog structures this g is waiting on (that have a valid elem ptr); in lock order
 	// Not for gccgo: cgoCtxt        []uintptr // cgo traceback context
 
 	// Per-G GC state
Index: libgo/go/runtime/stubs.go
===================================================================
--- libgo/go/runtime/stubs.go	(revision 240942)
+++ libgo/go/runtime/stubs.go	(working copy)
@@ -445,6 +445,3 @@ func releaseSudog(s *sudog) {
 
 // Temporary hack for gccgo until we port the garbage collector.
 func typeBitsBulkBarrier(typ *_type, p, size uintptr) {}
-
-// Temporary for gccgo until we port print.go.
-type hex uint64
Index: libgo/runtime/mprof.goc
===================================================================
--- libgo/runtime/mprof.goc	(revision 240942)
+++ libgo/runtime/mprof.goc	(working copy)
@@ -419,17 +419,19 @@ func Stack(b Slice, all bool) (n int) {
 		n = 0;
 	else{
 		G* g = runtime_g();
-		g->writebuf = (byte*)b.__values;
-		g->writenbuf = b.__count;
+		g->writebuf.__values = b.__values;
+		g->writebuf.__count = 0;
+		g->writebuf.__capacity = b.__count;
 		USED(pc);
 		runtime_goroutineheader(g);
 		runtime_traceback();
 		runtime_printcreatedby(g);
 		if(all)
 			runtime_tracebackothers(g);
-		n = b.__count - g->writenbuf;
-		g->writebuf = nil;
-		g->writenbuf = 0;
+		n = g->writebuf.__count;
+		g->writebuf.__values = nil;
+		g->writebuf.__count = 0;
+		g->writebuf.__capacity = 0;
 	}
 	
 	if(all) {
Index: libgo/runtime/panic.c
===================================================================
--- libgo/runtime/panic.c	(revision 240942)
+++ libgo/runtime/panic.c	(working copy)
@@ -72,9 +72,11 @@ __go_rundefer(void)
 void
 runtime_startpanic(void)
 {
+	G *g;
 	M *m;
 
-	m = runtime_m();
+	g = runtime_g();
+	m = g->m;
 	if(runtime_mheap.cachealloc.size == 0) { // very early
 		runtime_printf("runtime: panic before malloc heap initialized\n");
 		m->mallocing = 1; // tell rest of panic not to try to malloc
@@ -83,8 +85,9 @@ runtime_startpanic(void)
 	switch(m->dying) {
 	case 0:
 		m->dying = 1;
-		if(runtime_g() != nil)
-			runtime_g()->writebuf = nil;
+		g->writebuf.__values = nil;
+		g->writebuf.__count = 0;
+		g->writebuf.__capacity = 0;
 		runtime_xadd(&runtime_panicking, 1);
 		runtime_lock(&paniclk);
 		if(runtime_debug.schedtrace > 0 || runtime_debug.scheddetail > 0)
Index: libgo/runtime/print.c
===================================================================
--- libgo/runtime/print.c	(revision 240942)
+++ libgo/runtime/print.c	(working copy)
@@ -9,58 +9,60 @@
 #include "array.h"
 #include "go-type.h"
 
-//static Lock debuglock;
+extern void runtime_printlock(void)
+  __asm__(GOSYM_PREFIX "runtime.printlock");
+extern void runtime_printunlock(void)
+  __asm__(GOSYM_PREFIX "runtime.printunlock");
+extern void gwrite(Slice)
+  __asm__(GOSYM_PREFIX "runtime.gwrite");
+extern void runtime_printint(int64)
+  __asm__(GOSYM_PREFIX "runtime.printint");
+extern void runtime_printuint(uint64)
+  __asm__(GOSYM_PREFIX "runtime.printuint");
+extern void runtime_printhex(uint64)
+  __asm__(GOSYM_PREFIX "runtime.printhex");
+extern void runtime_printfloat(float64)
+  __asm__(GOSYM_PREFIX "runtime.printfloat");
+extern void runtime_printcomplex(complex double)
+  __asm__(GOSYM_PREFIX "runtime.printcomplex");
+extern void runtime_printbool(_Bool)
+  __asm__(GOSYM_PREFIX "runtime.printbool");
+extern void runtime_printstring(String)
+  __asm__(GOSYM_PREFIX "runtime.printstring");
+extern void runtime_printpointer(void *)
+  __asm__(GOSYM_PREFIX "runtime.printpointer");
+extern void runtime_printslice(Slice)
+  __asm__(GOSYM_PREFIX "runtime.printslice");
+extern void runtime_printeface(Eface)
+  __asm__(GOSYM_PREFIX "runtime.printeface");
+extern void runtime_printiface(Iface)
+  __asm__(GOSYM_PREFIX "runtime.printiface");
 
 // Clang requires this function to not be inlined (see below).
 static void go_vprintf(const char*, va_list)
 __attribute__((noinline));
 
-// write to goroutine-local buffer if diverting output,
-// or else standard error.
 static void
-gwrite(const void *v, intgo n)
+runtime_prints(const char *s)
 {
-	G* g = runtime_g();
-
-	if(g == nil || g->writebuf == nil) {
-		// Avoid -D_FORTIFY_SOURCE problems.
-		int rv __attribute__((unused));
-
-		rv = runtime_write(2, v, n);
-		return;
-	}
-
-	if(g->writenbuf == 0)
-		return;
+	Slice sl;
 
-	if(n > g->writenbuf)
-		n = g->writenbuf;
-	runtime_memmove(g->writebuf, v, n);
-	g->writebuf += n;
-	g->writenbuf -= n;
+	// Use memcpy to avoid const-cast warning.
+	memcpy(&sl.__values, &s, sizeof(char*));
+	sl.__count = runtime_findnull((const byte*)s);
+	sl.__capacity = sl.__count;
+	gwrite(sl);
 }
 
-void
-runtime_dump(byte *p, int32 n)
+static void
+runtime_printbyte(int8 c)
 {
-	int32 i;
+	Slice sl;
 
-	for(i=0; i<n; i++) {
-		runtime_printpointer((byte*)(uintptr)(p[i]>>4));
-		runtime_printpointer((byte*)(uintptr)(p[i]&0xf));
-		if((i&15) == 15)
-			runtime_prints("\n");
-		else
-			runtime_prints(" ");
-	}
-	if(n & 15)
-		runtime_prints("\n");
-}
-
-void
-runtime_prints(const char *s)
-{
-	gwrite(s, runtime_findnull((const byte*)s));
+	sl.__values = &c;
+	sl.__count = 1;
+	sl.__capacity = 1;
+	gwrite(sl);
 }
 
 #if defined (__clang__) && (defined (__i386__) || defined (__x86_64__))
@@ -104,15 +106,17 @@ runtime_snprintf(byte *buf, int32 n, con
 	va_list va;
 	int32 m;
 
-	g->writebuf = buf;
-	g->writenbuf = n-1;
+	g->writebuf.__values = buf;
+	g->writebuf.__count = 0;
+	g->writebuf.__capacity = n-1;
 	va_start(va, s);
 	go_vprintf(s, va);
 	va_end(va);
-	*g->writebuf = '\0';
-	m = g->writebuf - buf;
-	g->writenbuf = 0;
-	g->writebuf = nil;
+	m = g->writebuf.__count;
+	((byte*)g->writebuf.__values)[m] = '\0';
+	g->writebuf.__values = nil;
+	g->writebuf.__count = 0;
+	g->writebuf.__capacity = 0;
 	return m;
 }
 
@@ -122,15 +126,21 @@ static void
 go_vprintf(const char *s, va_list va)
 {
 	const char *p, *lp;
+	Slice sl;
 
-	//runtime_lock(&debuglock);
+	runtime_printlock();
 
 	lp = p = s;
 	for(; *p; p++) {
 		if(*p != '%')
 			continue;
-		if(p > lp)
-			gwrite(lp, p-lp);
+		if(p > lp) {
+			// Use memcpy to avoid const-cast warning.
+			memcpy(&sl.__values, &lp, sizeof(char*));
+			sl.__count = p - lp;
+			sl.__capacity = p - lp;
+			gwrite(sl);
+		}
 		p++;
 		switch(*p) {
 		case 'a':
@@ -181,192 +191,13 @@ go_vprintf(const char *s, va_list va)
 		}
 		lp = p+1;
 	}
-	if(p > lp)
-		gwrite(lp, p-lp);
-
-	//runtime_unlock(&debuglock);
-}
-
-void
-runtime_printpc(void *p __attribute__ ((unused)))
-{
-	runtime_prints("PC=");
-	runtime_printhex((uint64)(uintptr)runtime_getcallerpc(p));
-}
-
-void
-runtime_printbool(_Bool v)
-{
-	if(v) {
-		gwrite("true", 4);
-		return;
-	}
-	gwrite("false", 5);
-}
-
-void
-runtime_printbyte(int8 c)
-{
-	gwrite(&c, 1);
-}
-
-void
-runtime_printfloat(double v)
-{
-	byte buf[20];
-	int32 e, s, i, n;
-	float64 h;
-
-	if(ISNAN(v)) {
-		gwrite("NaN", 3);
-		return;
-	}
-	if(isinf(v)) {
-		if(signbit(v)) {
-			gwrite("-Inf", 4);
-		} else {
-			gwrite("+Inf", 4);
-		}
-		return;
-	}
-
-	n = 7;	// digits printed
-	e = 0;	// exp
-	s = 0;	// sign
-	if(v == 0) {
-		if(isinf(1/v) && 1/v < 0)
-			s = 1;
-	} else {
-		// sign
-		if(v < 0) {
-			v = -v;
-			s = 1;
-		}
-
-		// normalize
-		while(v >= 10) {
-			e++;
-			v /= 10;
-		}
-		while(v < 1) {
-			e--;
-			v *= 10;
-		}
-
-		// round
-		h = 5;
-		for(i=0; i<n; i++)
-			h /= 10;
-
-		v += h;
-		if(v >= 10) {
-			e++;
-			v /= 10;
-		}
-	}
-
-	// format +d.dddd+edd
-	buf[0] = '+';
-	if(s)
-		buf[0] = '-';
-	for(i=0; i<n; i++) {
-		s = v;
-		buf[i+2] = s+'0';
-		v -= s;
-		v *= 10.;
-	}
-	buf[1] = buf[2];
-	buf[2] = '.';
-
-	buf[n+2] = 'e';
-	buf[n+3] = '+';
-	if(e < 0) {
-		e = -e;
-		buf[n+3] = '-';
-	}
-
-	buf[n+4] = (e/100) + '0';
-	buf[n+5] = (e/10)%10 + '0';
-	buf[n+6] = (e%10) + '0';
-	gwrite(buf, n+7);
-}
-
-void
-runtime_printcomplex(complex double v)
-{
-	gwrite("(", 1);
-	runtime_printfloat(creal(v));
-	runtime_printfloat(cimag(v));
-	gwrite("i)", 2);
-}
-
-void
-runtime_printuint(uint64 v)
-{
-	byte buf[100];
-	int32 i;
-
-	for(i=nelem(buf)-1; i>0; i--) {
-		buf[i] = v%10 + '0';
-		if(v < 10)
-			break;
-		v = v/10;
-	}
-	gwrite(buf+i, nelem(buf)-i);
-}
-
-void
-runtime_printint(int64 v)
-{
-	if(v < 0) {
-		gwrite("-", 1);
-		v = -v;
+	if(p > lp) {
+		// Use memcpy to avoid const-cast warning.
+		memcpy(&sl.__values, &lp, sizeof(char*));
+		sl.__count = p - lp;
+		sl.__capacity = p - lp;
+		gwrite(sl);
 	}
-	runtime_printuint(v);
-}
-
-void
-runtime_printhex(uint64 v)
-{
-	static const char *dig = "0123456789abcdef";
-	byte buf[100];
-	int32 i;
-
-	i=nelem(buf);
-	for(; v>0; v/=16)
-		buf[--i] = dig[v%16];
-	if(i == nelem(buf))
-		buf[--i] = '0';
-	buf[--i] = 'x';
-	buf[--i] = '0';
-	gwrite(buf+i, nelem(buf)-i);
-}
-
-void
-runtime_printpointer(void *p)
-{
-	runtime_printhex((uintptr)p);
-}
 
-void
-runtime_printstring(String v)
-{
-	// if(v.len > runtime_maxstring) {
-	//	gwrite("[string too long]", 17);
-	//	return;
-	// }
-	if(v.len > 0)
-		gwrite(v.str, v.len);
-}
-
-void
-__go_print_space(void)
-{
-	gwrite(" ", 1);
-}
-
-void
-__go_print_nl(void)
-{
-	gwrite("\n", 1);
+	runtime_printunlock();
 }
Index: libgo/runtime/proc.c
===================================================================
--- libgo/runtime/proc.c	(revision 240942)
+++ libgo/runtime/proc.c	(working copy)
@@ -2037,8 +2037,9 @@ goexit0(G *gp)
 	gp->paniconfault = 0;
 	gp->_defer = nil; // should be true already but just in case.
 	gp->_panic = nil; // non-nil for Goexit during panic. points at stack-allocated data.
-	gp->writenbuf = 0;
-	gp->writebuf = nil;
+	gp->writebuf.__values = nil;
+	gp->writebuf.__count = 0;
+	gp->writebuf.__capacity = 0;
 	gp->waitreason = runtime_gostringnocopy(nil);
 	gp->param = nil;
 	m->curg = nil;
Index: libgo/runtime/runtime.h
===================================================================
--- libgo/runtime/runtime.h	(revision 240942)
+++ libgo/runtime/runtime.h	(working copy)
@@ -309,7 +309,6 @@ extern	bool	runtime_isarchive;
 #define runtime_strstr(s1, s2) __builtin_strstr((s1), (s2))
 intgo	runtime_findnull(const byte*);
 intgo	runtime_findnullw(const uint16*);
-void	runtime_dump(byte*, int32);
 
 void	runtime_gogo(G*);
 struct __go_func_type;
@@ -324,7 +323,6 @@ void	runtime_goenvs_unix(void)
 void	runtime_throw(const char*) __attribute__ ((noreturn));
 void	runtime_panicstring(const char*) __attribute__ ((noreturn));
 bool	runtime_canpanic(G*);
-void	runtime_prints(const char*);
 void	runtime_printf(const char*, ...);
 int32	runtime_snprintf(byte*, int32, const char*, ...);
 #define runtime_mcmp(a, b, s) __builtin_memcmp((a), (b), (s))
@@ -534,35 +532,8 @@ void __wrap_rtems_task_variable_add(void
 #endif
 
 /*
- * Names generated by gccgo.
- */
-#define runtime_printbool	__go_print_bool
-#define runtime_printfloat	__go_print_double
-#define runtime_printint	__go_print_int64
-#define runtime_printiface	__go_print_interface
-#define runtime_printeface	__go_print_empty_interface
-#define runtime_printstring	__go_print_string
-#define runtime_printpointer	__go_print_pointer
-#define runtime_printuint	__go_print_uint64
-#define runtime_printslice	__go_print_slice
-#define runtime_printcomplex	__go_print_complex
-
-/*
  * runtime go-called
  */
-void	runtime_printbool(_Bool);
-void	runtime_printbyte(int8);
-void	runtime_printfloat(double);
-void	runtime_printint(int64);
-void	runtime_printiface(Iface);
-void	runtime_printeface(Eface);
-void	runtime_printstring(String);
-void	runtime_printpc(void*);
-void	runtime_printpointer(void*);
-void	runtime_printuint(uint64);
-void	runtime_printhex(uint64);
-void	runtime_printslice(Slice);
-void	runtime_printcomplex(complex double);
 void reflect_call(const struct __go_func_type *, FuncVal *, _Bool, _Bool,
 		  void **, void **)
   __asm__ (GOSYM_PREFIX "reflect.call");
