unix: add gccgo support

With these changes the package builds, and the tests pass, using gccgo
on amd64 GNU/Linux.  I have not tested other systems but I don't know
why they wouldn't work.

Change-Id: I727365daef55f158657eb89afbfcdbf3334610d1
Reviewed-on: https://go-review.googlesource.com/9842
Reviewed-by: Minux Ma <minux@golang.org>
Reviewed-by: Rob Pike <r@golang.org>
diff --git a/unix/asm.s b/unix/asm.s
index d4ca868..8ed2fdb 100644
--- a/unix/asm.s
+++ b/unix/asm.s
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build !gccgo
+
 #include "textflag.h"
 
 TEXT ·use(SB),NOSPLIT,$0
diff --git a/unix/asm_darwin_386.s b/unix/asm_darwin_386.s
index f9338da..8a72783 100644
--- a/unix/asm_darwin_386.s
+++ b/unix/asm_darwin_386.s
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build !gccgo
+
 #include "textflag.h"
 
 //
diff --git a/unix/asm_darwin_amd64.s b/unix/asm_darwin_amd64.s
index aa13768..6321421 100644
--- a/unix/asm_darwin_amd64.s
+++ b/unix/asm_darwin_amd64.s
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build !gccgo
+
 #include "textflag.h"
 
 //
diff --git a/unix/asm_dragonfly_386.s b/unix/asm_dragonfly_386.s
index 68aa5e4..7e55e0d 100644
--- a/unix/asm_dragonfly_386.s
+++ b/unix/asm_dragonfly_386.s
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build !gccgo
+
 #include "textflag.h"
 
 //
diff --git a/unix/asm_dragonfly_amd64.s b/unix/asm_dragonfly_amd64.s
index 77b1bf9..d5ed672 100644
--- a/unix/asm_dragonfly_amd64.s
+++ b/unix/asm_dragonfly_amd64.s
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build !gccgo
+
 #include "textflag.h"
 
 //
diff --git a/unix/asm_freebsd_386.s b/unix/asm_freebsd_386.s
index 1146f0b..c9a0a26 100644
--- a/unix/asm_freebsd_386.s
+++ b/unix/asm_freebsd_386.s
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build !gccgo
+
 #include "textflag.h"
 
 //
diff --git a/unix/asm_freebsd_amd64.s b/unix/asm_freebsd_amd64.s
index d80fd12..3517247 100644
--- a/unix/asm_freebsd_amd64.s
+++ b/unix/asm_freebsd_amd64.s
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build !gccgo
+
 #include "textflag.h"
 
 //
diff --git a/unix/asm_freebsd_arm.s b/unix/asm_freebsd_arm.s
index aca3f3f..9227c87 100644
--- a/unix/asm_freebsd_arm.s
+++ b/unix/asm_freebsd_arm.s
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build !gccgo
+
 #include "textflag.h"
 
 //
diff --git a/unix/asm_linux_386.s b/unix/asm_linux_386.s
index 5d3ad9a..4db2909 100644
--- a/unix/asm_linux_386.s
+++ b/unix/asm_linux_386.s
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build !gccgo
+
 #include "textflag.h"
 
 //
diff --git a/unix/asm_linux_amd64.s b/unix/asm_linux_amd64.s
index 0c8c778..44e25c6 100644
--- a/unix/asm_linux_amd64.s
+++ b/unix/asm_linux_amd64.s
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build !gccgo
+
 #include "textflag.h"
 
 //
diff --git a/unix/asm_linux_arm.s b/unix/asm_linux_arm.s
index 4137b58..cf0b574 100644
--- a/unix/asm_linux_arm.s
+++ b/unix/asm_linux_arm.s
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build !gccgo
+
 #include "textflag.h"
 
 //
diff --git a/unix/asm_netbsd_386.s b/unix/asm_netbsd_386.s
index 682e4bd..48bdcd7 100644
--- a/unix/asm_netbsd_386.s
+++ b/unix/asm_netbsd_386.s
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build !gccgo
+
 #include "textflag.h"
 
 //
diff --git a/unix/asm_netbsd_amd64.s b/unix/asm_netbsd_amd64.s
index e80eadd..2ede05c 100644
--- a/unix/asm_netbsd_amd64.s
+++ b/unix/asm_netbsd_amd64.s
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build !gccgo
+
 #include "textflag.h"
 
 //
diff --git a/unix/asm_netbsd_arm.s b/unix/asm_netbsd_arm.s
index 0b673a3..e892857 100644
--- a/unix/asm_netbsd_arm.s
+++ b/unix/asm_netbsd_arm.s
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build !gccgo
+
 #include "textflag.h"
 
 //
diff --git a/unix/asm_openbsd_386.s b/unix/asm_openbsd_386.s
index 65b0e42..00576f3 100644
--- a/unix/asm_openbsd_386.s
+++ b/unix/asm_openbsd_386.s
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build !gccgo
+
 #include "textflag.h"
 
 //
diff --git a/unix/asm_openbsd_amd64.s b/unix/asm_openbsd_amd64.s
index 55aada1..790ef77 100644
--- a/unix/asm_openbsd_amd64.s
+++ b/unix/asm_openbsd_amd64.s
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build !gccgo
+
 #include "textflag.h"
 
 //
diff --git a/unix/asm_solaris_amd64.s b/unix/asm_solaris_amd64.s
index f612131..a33708f 100644
--- a/unix/asm_solaris_amd64.s
+++ b/unix/asm_solaris_amd64.s
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build !gccgo
+
 //
 // System calls for amd64, Solaris are implemented in runtime/syscall_solaris.goc
 //
diff --git a/unix/gccgo.go b/unix/gccgo.go
new file mode 100644
index 0000000..5fc9bc9
--- /dev/null
+++ b/unix/gccgo.go
@@ -0,0 +1,39 @@
+// Copyright 2015 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.
+
+// +build gccgo
+
+package unix
+
+import "syscall"
+
+// We can't use the gc-syntax .s files for gccgo.  On the plus side
+// much of the functionality can be written directly in Go.
+
+//extern gccgoRealSyscall
+func realSyscall(trap, a1, a2, a3, a4, a5, a6 uintptr) (r, errno uintptr)
+
+func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
+	syscall.Entersyscall()
+	r, errno := realSyscall(trap, a1, a2, a3, 0, 0, 0)
+	syscall.Exitsyscall()
+	return r, 0, syscall.Errno(errno)
+}
+
+func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno) {
+	syscall.Entersyscall()
+	r, errno := realSyscall(trap, a1, a2, a3, a4, a5, a6)
+	syscall.Exitsyscall()
+	return r, 0, syscall.Errno(errno)
+}
+
+func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
+	r, errno := realSyscall(trap, a1, a2, a3, 0, 0, 0)
+	return r, 0, syscall.Errno(errno)
+}
+
+func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno) {
+	r, errno := realSyscall(trap, a1, a2, a3, a4, a5, a6)
+	return r, 0, syscall.Errno(errno)
+}
diff --git a/unix/gccgo_c.c b/unix/gccgo_c.c
new file mode 100644
index 0000000..991980e
--- /dev/null
+++ b/unix/gccgo_c.c
@@ -0,0 +1,41 @@
+// Copyright 2015 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.
+
+// +build gccgo
+
+#include <errno.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#define _STRINGIFY2_(x) #x
+#define _STRINGIFY_(x) _STRINGIFY2_(x)
+#define GOSYM_PREFIX _STRINGIFY_(__USER_LABEL_PREFIX__)
+
+// Call syscall from C code because the gccgo support for calling from
+// Go to C does not support varargs functions.
+
+struct ret {
+	uintptr_t r;
+	uintptr_t err;
+};
+
+struct ret
+gccgoRealSyscall(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6)
+{
+	struct ret r;
+
+	errno = 0;
+	r.r = syscall(trap, a1, a2, a3, a4, a5, a6);
+	r.err = errno;
+	return r;
+}
+
+// Define the use function in C so that it is not inlined.
+
+extern void use(void *) __asm__ (GOSYM_PREFIX GOPKGPATH ".use") __attribute__((noinline));
+
+void
+use(void *p __attribute__ ((unused)))
+{
+}
diff --git a/unix/gccgo_linux_amd64.go b/unix/gccgo_linux_amd64.go
new file mode 100644
index 0000000..bffe1a7
--- /dev/null
+++ b/unix/gccgo_linux_amd64.go
@@ -0,0 +1,20 @@
+// Copyright 2015 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.
+
+// +build gccgo,linux,amd64
+
+package unix
+
+import "syscall"
+
+//extern gettimeofday
+func realGettimeofday(*Timeval, *byte) int32
+
+func gettimeofday(tv *Timeval) (err syscall.Errno) {
+	r := realGettimeofday(tv, nil)
+	if r < 0 {
+		return syscall.GetErrno()
+	}
+	return 0
+}
diff --git a/unix/syscall_unix_test.go b/unix/syscall_unix_test.go
index ad9a5d7..bcc79d1 100644
--- a/unix/syscall_unix_test.go
+++ b/unix/syscall_unix_test.go
@@ -118,6 +118,9 @@
 
 	cmd := exec.Command(os.Args[0], "-test.run=^TestPassFD$", "--", tempDir)
 	cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"}
+	if lp := os.Getenv("LD_LIBRARY_PATH"); lp != "" {
+		cmd.Env = append(cmd.Env, "LD_LIBRARY_PATH="+lp)
+	}
 	cmd.ExtraFiles = []*os.File{writeFile}
 
 	out, err := cmd.CombinedOutput()