]> Cypherpunks.ru repositories - gostls13.git/commitdiff
[dev.garbage] all: merge dev.cc (493ad916c3b1) into dev.garbage
authorRuss Cox <rsc@golang.org>
Mon, 24 Nov 2014 17:07:11 +0000 (12:07 -0500)
committerRuss Cox <rsc@golang.org>
Mon, 24 Nov 2014 17:07:11 +0000 (12:07 -0500)
TBR=austin
CC=golang-codereviews
https://golang.org/cl/179290043

207 files changed:
.hgtags
AUTHORS
CONTRIBUTORS
doc/go1.4.html
doc/go_spec.html
doc/gopher/fiveyears.jpg [new file with mode: 0644]
doc/install.html
include/link.h
misc/makerelease/makerelease.go
src/cmd/5g/opt.h
src/cmd/5g/reg.c
src/cmd/5l/5.out.h
src/cmd/6g/opt.h
src/cmd/6g/reg.c
src/cmd/6l/6.out.h
src/cmd/8g/opt.h
src/cmd/8g/reg.c
src/cmd/8l/8.out.h
src/cmd/9a/lex.c
src/cmd/9c/Makefile [deleted file]
src/cmd/9c/Notes [deleted file]
src/cmd/9c/cgen.c [deleted file]
src/cmd/9c/doc.go [deleted file]
src/cmd/9c/gc.h [deleted file]
src/cmd/9c/list.c [deleted file]
src/cmd/9c/machcap.c [deleted file]
src/cmd/9c/mul.c [deleted file]
src/cmd/9c/peep.c [deleted file]
src/cmd/9c/reg.c [deleted file]
src/cmd/9c/sgen.c [deleted file]
src/cmd/9c/swt.c [deleted file]
src/cmd/9c/txt.c [deleted file]
src/cmd/9g/prog.c
src/cmd/9g/reg.c
src/cmd/9l/9.out.h
src/cmd/cgo/doc.go
src/cmd/dist/build.c
src/cmd/dist/buildgc.c
src/cmd/dist/buildruntime.c
src/cmd/gc/walk.c
src/cmd/go/tool.go
src/cmd/internal/goobj/read.go [moved from src/debug/goobj/read.go with 100% similarity]
src/cmd/internal/goobj/read_test.go [moved from src/debug/goobj/read_test.go with 100% similarity]
src/cmd/internal/objfile/goobj.go
src/cmd/link/auto.go
src/cmd/link/auto_test.go
src/cmd/link/dead.go
src/cmd/link/dead_test.go
src/cmd/link/layout.go
src/cmd/link/link_test.go
src/cmd/link/pclntab.go
src/cmd/link/pclntab_test.go
src/cmd/link/prog.go
src/cmd/link/runtime.go
src/cmd/link/scan.go
src/cmd/pprof/internal/report/source.go
src/crypto/x509/root_unix.go
src/go/parser/error_test.go
src/go/parser/parser_test.go
src/hash/crc32/crc32.go
src/image/jpeg/reader.go
src/image/jpeg/reader_test.go
src/liblink/list6.c
src/liblink/list9.c
src/net/http/fs.go
src/net/url/example_test.go
src/regexp/syntax/regexp.go
src/run.bash
src/run.bat
src/runtime/arch1_386.go
src/runtime/arch1_amd64.go
src/runtime/arch1_amd64p32.go [new file with mode: 0644]
src/runtime/arch1_arm.go
src/runtime/arch1_power64.go [new file with mode: 0644]
src/runtime/arch1_power64le.go [new file with mode: 0644]
src/runtime/arch_amd64p32.h [deleted file]
src/runtime/arch_power64.h [deleted file]
src/runtime/asm_amd64p32.s
src/runtime/asm_power64x.s
src/runtime/atomic_power64x.go [new file with mode: 0644]
src/runtime/chan.go
src/runtime/defs1_netbsd_386.go
src/runtime/defs1_netbsd_amd64.go
src/runtime/defs_linux_386.go
src/runtime/defs_linux_amd64.go
src/runtime/defs_linux_arm.go
src/runtime/defs_linux_power64.go [new file with mode: 0644]
src/runtime/defs_linux_power64.h [deleted file]
src/runtime/defs_linux_power64le.go [new file with mode: 0644]
src/runtime/defs_linux_power64le.h [deleted file]
src/runtime/defs_plan9_386.go
src/runtime/defs_plan9_amd64.go
src/runtime/env_plan9.go
src/runtime/gengoos.go [new file with mode: 0644]
src/runtime/heapdump.go
src/runtime/lfstack.go
src/runtime/lfstack_32bit.go
src/runtime/lfstack_linux_power64x.go
src/runtime/malloc.go
src/runtime/malloc2.go
src/runtime/mem_bsd.go
src/runtime/mem_nacl.c [deleted file]
src/runtime/mem_plan9.c [deleted file]
src/runtime/mem_plan9.go [new file with mode: 0644]
src/runtime/mgc0.go
src/runtime/netpoll_stub.go [moved from src/runtime/netpoll_stub.c with 81% similarity]
src/runtime/netpoll_windows.go
src/runtime/os1_nacl.go [new file with mode: 0644]
src/runtime/os1_netbsd.go [new file with mode: 0644]
src/runtime/os1_netbsd_386.go [new file with mode: 0644]
src/runtime/os1_netbsd_amd64.go [new file with mode: 0644]
src/runtime/os1_plan9.go [new file with mode: 0644]
src/runtime/os1_windows.go [new file with mode: 0644]
src/runtime/os1_windows_386.go [new file with mode: 0644]
src/runtime/os1_windows_amd64.go [new file with mode: 0644]
src/runtime/os2_nacl.go [new file with mode: 0644]
src/runtime/os2_netbsd.go [new file with mode: 0644]
src/runtime/os2_plan9.go [new file with mode: 0644]
src/runtime/os2_windows.go [new file with mode: 0644]
src/runtime/os_android.h [deleted file]
src/runtime/os_android_arm.go [moved from src/runtime/os_android.c with 64% similarity]
src/runtime/os_nacl.c [deleted file]
src/runtime/os_nacl.go
src/runtime/os_nacl.h [deleted file]
src/runtime/os_nacl_arm.go [moved from src/runtime/os_nacl_arm.c with 61% similarity]
src/runtime/os_netbsd.c [deleted file]
src/runtime/os_netbsd.go
src/runtime/os_netbsd.h [deleted file]
src/runtime/os_netbsd_386.c [deleted file]
src/runtime/os_netbsd_amd64.c [deleted file]
src/runtime/os_plan9.c [deleted file]
src/runtime/os_plan9.go
src/runtime/os_plan9.h [deleted file]
src/runtime/os_plan9_386.c [deleted file]
src/runtime/os_plan9_386.go [new file with mode: 0644]
src/runtime/os_plan9_amd64.c [deleted file]
src/runtime/os_plan9_amd64.go [new file with mode: 0644]
src/runtime/os_windows.c [deleted file]
src/runtime/os_windows.go
src/runtime/os_windows.h [deleted file]
src/runtime/os_windows_386.c [deleted file]
src/runtime/os_windows_amd64.c [deleted file]
src/runtime/panic.go
src/runtime/proc.go
src/runtime/race/race_unix_test.go [new file with mode: 0644]
src/runtime/race1.go
src/runtime/race_amd64.s
src/runtime/runtime2.go
src/runtime/select.go
src/runtime/sema.go
src/runtime/signal_android_386.h [deleted file]
src/runtime/signal_android_arm.h [deleted file]
src/runtime/signal_linux_386.go
src/runtime/signal_linux_amd64.go
src/runtime/signal_linux_arm.go
src/runtime/signal_linux_power64.h [deleted file]
src/runtime/signal_linux_power64le.h [deleted file]
src/runtime/signal_linux_power64x.go [new file with mode: 0644]
src/runtime/signal_nacl.go [new file with mode: 0644]
src/runtime/signal_nacl_386.go [new file with mode: 0644]
src/runtime/signal_nacl_386.h [deleted file]
src/runtime/signal_nacl_amd64p32.go [new file with mode: 0644]
src/runtime/signal_nacl_amd64p32.h [deleted file]
src/runtime/signal_nacl_arm.go [new file with mode: 0644]
src/runtime/signal_nacl_arm.h [deleted file]
src/runtime/signal_netbsd.go [new file with mode: 0644]
src/runtime/signal_netbsd_386.go [new file with mode: 0644]
src/runtime/signal_netbsd_386.h [deleted file]
src/runtime/signal_netbsd_amd64.go [new file with mode: 0644]
src/runtime/signal_netbsd_amd64.h [deleted file]
src/runtime/signal_plan9.go [moved from src/runtime/signals_plan9.h with 54% similarity]
src/runtime/signal_power64x.c [deleted file]
src/runtime/signal_power64x.go [new file with mode: 0644]
src/runtime/signals_android.h [deleted file]
src/runtime/signals_nacl.h [deleted file]
src/runtime/signals_netbsd.h [deleted file]
src/runtime/stack1.go
src/runtime/stack2.go
src/runtime/stubs.go
src/runtime/stubs2.go
src/runtime/stubs3.go [moved from src/runtime/arch_power64le.h with 53% similarity]
src/runtime/sys_linux_power64x.s
src/runtime/sys_power64x.c [deleted file]
src/runtime/sys_power64x.go [new file with mode: 0644]
src/runtime/sys_windows_386.s
src/runtime/sys_windows_amd64.s
src/runtime/syscall_windows.go
src/runtime/zgoarch_386.go [new file with mode: 0644]
src/runtime/zgoarch_amd64.go [new file with mode: 0644]
src/runtime/zgoarch_amd64p32.go [new file with mode: 0644]
src/runtime/zgoarch_arm.go [new file with mode: 0644]
src/runtime/zgoarch_power64.go [new file with mode: 0644]
src/runtime/zgoarch_power64le.go [new file with mode: 0644]
src/runtime/zgoos_android.go [new file with mode: 0644]
src/runtime/zgoos_darwin.go [new file with mode: 0644]
src/runtime/zgoos_dragonfly.go [new file with mode: 0644]
src/runtime/zgoos_freebsd.go [new file with mode: 0644]
src/runtime/zgoos_linux.go [new file with mode: 0644]
src/runtime/zgoos_nacl.go [new file with mode: 0644]
src/runtime/zgoos_netbsd.go [new file with mode: 0644]
src/runtime/zgoos_openbsd.go [new file with mode: 0644]
src/runtime/zgoos_plan9.go [new file with mode: 0644]
src/runtime/zgoos_solaris.go [new file with mode: 0644]
src/runtime/zgoos_windows.go [new file with mode: 0644]
src/syscall/exec_bsd.go
src/syscall/exec_linux.go
test/fixedbugs/issue9110.go [new file with mode: 0644]

diff --git a/.hgtags b/.hgtags
index edd2163f701248fa6ce3debb20409531c8bc0c53..9867bc339f9a316448888652756f371270d66d97 100644 (file)
--- a/.hgtags
+++ b/.hgtags
@@ -136,3 +136,4 @@ f8b50ad4cac4d4c4ecf48324b4f512f65e82cc1c go1.3beta1
 f44017549ff9c3cc5eef74ebe7276cd0dfc066b6 go1.3.3
 f44017549ff9c3cc5eef74ebe7276cd0dfc066b6 release
 1fdfd7dfaedb1b7702141617e621ab7328a236a1 go1.4beta1
+bffdd0cae380ce1ccf3e98ed6b6cd53fece7ba72 go1.4rc1
diff --git a/AUTHORS b/AUTHORS
index 48a262bbd7c52a257d778273994d83cfb02d6a37..46fd9fd2951798f2a1a5c8b8ca81f1bf83a03f47 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -145,7 +145,7 @@ Egon Elbre <egonelbre@gmail.com>
 Ehren Kret <ehren.kret@gmail.com>
 Eivind Uggedal <eivind@uggedal.com>
 Elias Naur <elias.naur@gmail.com>
-Emil Hessman <c.emil.hessman@gmail.com>
+Emil Hessman <c.emil.hessman@gmail.com> <emil@hessman.se>
 Eoghan Sherry <ejsherry@gmail.com>
 Eric Clark <zerohp@gmail.com>
 Eric Milliken <emilliken@gmail.com>
index ec69858b605ede830e06ec7a81670181c021b0f2..b5e709ed6e6faf557f456ab2a282f7c5127c0780 100644 (file)
@@ -214,7 +214,7 @@ Egon Elbre <egonelbre@gmail.com>
 Ehren Kret <ehren.kret@gmail.com>
 Eivind Uggedal <eivind@uggedal.com>
 Elias Naur <elias.naur@gmail.com>
-Emil Hessman <c.emil.hessman@gmail.com>
+Emil Hessman <c.emil.hessman@gmail.com> <emil@hessman.se>
 Eoghan Sherry <ejsherry@gmail.com>
 Eric Clark <zerohp@gmail.com>
 Eric Milliken <emilliken@gmail.com>
@@ -452,6 +452,7 @@ Nicholas Katsaros <nick@nickkatsaros.com>
 Nicholas Presta <nick@nickpresta.ca> <nick1presta@gmail.com>
 Nicholas Sullivan <nicholas.sullivan@gmail.com>
 Nicholas Waples <nwaples@gmail.com>
+Nick Cooper <nmvc@google.com>
 Nick Craig-Wood <nick@craig-wood.com> <nickcw@gmail.com>
 Nicolas Kaiser <nikai@nikai.net>
 Nicolas Owens <mischief@offblast.org>
index ac63ade60adc2f9834e973a91cde4eb42c110cc7..883352e34fe4b1e8d579bcbc568a46c6a8720e3f 100644 (file)
@@ -7,10 +7,10 @@
 <h2 id="introduction">Introduction to Go 1.4</h2>
 
 <p>
-The latest Go release, version 1.4, arrives as scheduled six months after 1.3
-and contains only one tiny language change,
-a possibly breaking change to the compiler,
-a backwards-compatible simple form of <code>for</code>-<code>range</code> loop.
+The latest Go release, version 1.4, arrives as scheduled six months after 1.3.
+It contains only one tiny language change,
+in the form of a backwards-compatible simple variant of <code>for</code>-<code>range</code> loop,
+and a possibly breaking change to the compiler involving methods on pointers-to-pointers.
 The release focuses primarily on implementation work, improving the garbage collector
 and preparing the ground for a fully concurrent collector to be rolled out in the
 next few releases.
@@ -20,7 +20,7 @@ this release therefore eliminates the notorious "hot stack split" problem.
 There are some new tools available including support in the <code>go</code> command
 for build-time source code generation.
 The release also adds support for ARM processors on Android and Native Client (NaCl)
-and AMD64 on Plan 9.
+and for AMD64 on Plan 9.
 As always, Go 1.4 keeps the <a href="/doc/go1compat.html">promise
 of compatibility</a>,
 and almost everything 
@@ -637,12 +637,29 @@ See the relevant package documentation for more information about each change.
 
 <ul>
 
+<li>
+The <a href="/pkg/archive/zip/"><code>archive/zip</code></a> package's
+<a href="/pkg/archive/zip/#Writer"><code>Writer</code></a> now supports a
+<a href="/pkg/archive/zip/#Writer.Flush"><code>Flush</code></a> method.
+</li>
+
 <li>
 The <a href="/pkg/compress/flate/"><code>compress/flate</code></a>,
 <a href="/pkg/compress/gzip/"><code>compress/gzip</code></a>,
 and <a href="/pkg/compress/zlib/"><code>compress/zlib</code></a>
 packages now support a <code>Reset</code> method
 for the decompressors, allowing them to reuse buffers and improve performance.
+The <a href="/pkg/compress/gzip/"><code>compress/gzip</code></a> package also has a
+<a href="/pkg/compress/gzip/#Reader.Multistream"><code>Multistream</code></a> method to control support
+for multistream files.
+</li>
+
+<li>
+The <a href="/pkg/crypto/"><code>crypto</code></a> package now has a
+<a href="/pkg/crypto/#Signer"><code>Signer</code></a> interface, implemented by the
+<code>PrivateKey</code> types in
+<a href="/pkg/crypto/ecdsa"><code>crypto/ecdsa</code></a> and
+<a href="/pkg/crypto/rsa"><code>crypto/rsa</code></a>.
 </li>
 
 <li>
@@ -665,6 +682,16 @@ to help clients detect fallback attacks.
 those attacks.)
 </li>
 
+<li>
+The <a href="/pkg/database/sql/"><code>database/sql</code></a> package can now list all registered
+<a href="/pkg/database/sql/#Drivers"><code>Drivers</code></a>.
+</li>
+
+<li>
+The <a href="/pkg/debug/dwarf/"><code>debug/dwarf</code></a> package now supports
+<a href="/pkg/debug/dwarf/#UnspecifiedType"><code>UnspecifiedType</code></a>s.
+</li>
+
 <li>
 In the <a href="/pkg/encoding/asn1/"><code>encoding/asn1</code></a> package,
 optional elements with a default value will now only be omitted if they have that value.
@@ -685,6 +712,11 @@ in some cases, especially involving arrays, it can be faster.
 There is no functional change.
 </li>
 
+<li>
+The <a href="/pkg/encoding/xml/"><code>encoding/xml</code></a> package's
+<a href="/pkg/encoding/xml/#Decoder"><code>Decoder</code></a> can now report its input offset.
+</li>
+
 <li>
 In the <a href="/pkg/fmt/"><code>fmt</code></a> package,
 formatting of pointers to maps has changed to be consistent with that of pointers
@@ -693,6 +725,28 @@ For instance, <code>&amp;map[string]int{"one":</code> <code>1}</code> now prints
 <code>&amp;map[one:</code> <code>1]</code> rather than as a hexadecimal pointer value.
 </li>
 
+<li>
+The <a href="/pkg/image/"><code>image</code></a> package's
+<a href="/pkg/image/#Image"><code>Image</code></a>
+implementations like
+<a href="/pkg/image/#RGBA"><code>RGBA</code></a> and
+<a href="/pkg/image/#Gray"><code>Gray</code></a> have specialized
+<a href="/pkg/image/#RGBA.RGBAAt"><code>RGBAAt</code></a> and
+<a href="/pkg/image/#Gray.GrayAt"><code>GrayAt</code></a> methods alongside the general
+<a href="/pkg/image/#Image.At"><code>At</code></a> method.
+</li>
+
+<li>
+The <a href="/pkg/image/png/"><code>image/png</code></a> package now has an
+<a href="/pkg/image/png/#Encoder"><code>Encoder</code></a>
+type to control the compression level used for encoding.
+</li>
+
+<li>
+The <a href="/pkg/math/"><code>math</code></a> package now has a
+<a href="/pkg/math/#Nextafter32"><code>Nextafter32</code><a/> function.
+</li>
+
 <li>
 The <a href="/pkg/net/http/"><code>net/http</code></a> package's
 <a href="/pkg/net/http/#Request"><code>Request</code></a> type
@@ -721,6 +775,7 @@ The <a href="/pkg/os/"><code>os</code></a> package
 now implements symbolic links on the Windows operating system
 through the <a href="/pkg/os/#Symlink"><code>Symlink</code></a> function.
 Other operating systems already have this functionality.
+There is also a new <a href="/pkg/os/#Unsetenv"><code>Unsetenv</code></a> function.
 </li>
 
 <li>
index 050c06465de602daf2f79e28a2cc2abf181fae1d..ca0deb56a3ebd24c442a4dbb3ed5c207673ad220 100644 (file)
@@ -1,6 +1,6 @@
 <!--{
        "Title": "The Go Programming Language Specification",
-       "Subtitle": "Version of October 27, 2014",
+       "Subtitle": "Version of November 11, 2014",
        "Path": "/ref/spec"
 }-->
 
@@ -2521,30 +2521,40 @@ The following rules apply to selectors:
 <ol>
 <li>
 For a value <code>x</code> of type <code>T</code> or <code>*T</code>
-where <code>T</code> is not an interface type,
+where <code>T</code> is not a pointer or interface type,
 <code>x.f</code> denotes the field or method at the shallowest depth
 in <code>T</code> where there
 is such an <code>f</code>.
 If there is not exactly <a href="#Uniqueness_of_identifiers">one <code>f</code></a>
 with shallowest depth, the selector expression is illegal.
 </li>
+
 <li>
-For a variable <code>x</code> of type <code>I</code> where <code>I</code>
+For a value <code>x</code> of type <code>I</code> where <code>I</code>
 is an interface type, <code>x.f</code> denotes the actual method with name
-<code>f</code> of the value assigned to <code>x</code>.
+<code>f</code> of the dynamic value of <code>x</code>.
 If there is no method with name <code>f</code> in the
 <a href="#Method_sets">method set</a> of <code>I</code>, the selector
 expression is illegal.
 </li>
+
+<li>
+As an exception, if the type of <code>x</code> is a named pointer type
+and <code>(*x).f</code> is a valid selector expression denoting a field
+(but not a method), <code>x.f</code> is shorthand for <code>(*x).f</code>.
+</li>
+
 <li>
 In all other cases, <code>x.f</code> is illegal.
 </li>
+
 <li>
 If <code>x</code> is of pointer type and has the value
 <code>nil</code> and <code>x.f</code> denotes a struct field,
 assigning to or evaluating <code>x.f</code>
 causes a <a href="#Run_time_panics">run-time panic</a>.
 </li>
+
 <li>
 If <code>x</code> is of interface type and has the value
 <code>nil</code>, <a href="#Calls">calling</a> or
@@ -2553,18 +2563,6 @@ causes a <a href="#Run_time_panics">run-time panic</a>.
 </li>
 </ol>
 
-<p>
-Selectors automatically <a href="#Address_operators">dereference</a>
-pointers to structs.
-If <code>x</code> is a pointer to a struct, <code>x.y</code>
-is shorthand for <code>(*x).y</code>; if the field <code>y</code>
-is also a pointer to a struct, <code>x.y.z</code> is shorthand
-for <code>(*(*x).y).z</code>, and so on.
-If <code>x</code> contains an anonymous field of type <code>*A</code>,
-where <code>A</code> is also a struct type,
-<code>x.f</code> is shorthand for <code>(*x.A).f</code>.
-</p>
-
 <p>
 For example, given the declarations:
 </p>
@@ -2574,13 +2572,13 @@ type T0 struct {
        x int
 }
 
-func (recv *T0) M0()
+func (*T0) M0()
 
 type T1 struct {
        y int
 }
 
-func (recv T1) M1()
+func (T1) M1()
 
 type T2 struct {
        z int
@@ -2588,9 +2586,13 @@ type T2 struct {
        *T0
 }
 
-func (recv *T2) M2()
+func (*T2) M2()
 
-var p *T2  // with p != nil and p.T0 != nil
+type Q *T2
+
+var t T2     // with t.T0 != nil
+var p *T2    // with p != nil and (*p).T0 != nil
+var q Q = p
 </pre>
 
 <p>
@@ -2598,13 +2600,27 @@ one may write:
 </p>
 
 <pre>
-p.z   // (*p).z
-p.y   // ((*p).T1).y
-p.x   // (*(*p).T0).x
+t.z          // t.z
+t.y          // t.T1.y
+t.x          // (*t.TO).x
+
+p.z          // (*p).z
+p.y          // (*p).T1.y
+p.x          // (*(*p).T0).x
+
+q.x          // (*(*q).T0).x        (*q).x is a valid field selector
+
+p.M2()       // p.M2()              M2 expects *T2 receiver
+p.M1()       // ((*p).T1).M1()      M1 expects T1 receiver
+p.M0()       // ((&(*p).T0)).M0()   M0 expects *T0 receiver, see section on Calls
+</pre>
 
-p.M2()  // (*p).M2()
-p.M1()  // ((*p).T1).M1()
-p.M0()  // ((*p).T0).M0()
+<p>
+but the following is invalid:
+</p>
+
+<pre>
+q.M0()       // (*q).M0 is valid but not a field selector
 </pre>
 
 
diff --git a/doc/gopher/fiveyears.jpg b/doc/gopher/fiveyears.jpg
new file mode 100644 (file)
index 0000000..df10648
Binary files /dev/null and b/doc/gopher/fiveyears.jpg differ
index d6984c2447b3df6708cd96d8d593234f2a6bd8a4..9561fdde21063c4e7b1995fa53171c74cc929960 100644 (file)
@@ -47,7 +47,7 @@ proceeding. If your OS or architecture is not on the list, it's possible that
 <tr><td>FreeBSD 8 or later</td> <td>amd64, 386, arm</td> <td>Debian GNU/kFreeBSD not supported; FreeBSD/ARM needs FreeBSD 10 or later</td></tr>
 <tr><td>Linux 2.6.23 or later with glibc</td> <td>amd64, 386, arm</td> <td>CentOS/RHEL 5.x not supported; no binary distribution for ARM yet</td></tr>
 <tr><td>Mac OS X 10.6 or later</td> <td>amd64, 386</td> <td>use the gcc<sup>&#8224;</sup> that comes with Xcode<sup>&#8225;</sup></td></tr>
-<tr><td>Windows XP or later</td> <td>amd64, 386</td> <td>use MinGW gcc<sup>&#8224;</sup>. No need for cgywin or msys.</td></tr>
+<tr><td>Windows XP or later</td> <td>amd64, 386</td> <td>use MinGW gcc<sup>&#8224;</sup>. No need for cygwin or msys.</td></tr>
 </table>
 
 <p>
index 06f3ebb489408ebd26038c693b89c16e1163c30c..2b1d02102b5f5505a172b75ba63f8fdd324735cb 100644 (file)
@@ -62,7 +62,7 @@ struct        Addr
        short   type;
        uint8   index;
        int8    scale;
-       int8    reg;    // for 5l, 9l
+       int8    reg;    // for 5l, 9l; GPRs and FPRs both start at 0
        int8    name; // for 5l, 9l
        int8    class;  // for 5l, 9l
        uint8   etype; // for 5g, 6g, 8g
@@ -94,6 +94,7 @@ struct        Prog
        // operands
        Addr    from;
        uchar   reg; // arm, power64 only (e.g., ADD from, reg, to);
+                    // starts at 0 for both GPRs and FPRs;
                     // also used for ADATA width on arm, power64
        Addr    from3; // power64 only (e.g., RLWM/FMADD from, reg, from3, to)
        Addr    to;
@@ -626,6 +627,11 @@ extern     char*   anames9[];
 extern char*   cnames5[];
 extern char*   cnames9[];
 
+extern char*   dnames5[];
+extern char*   dnames6[];
+extern char*   dnames8[];
+extern char*   dnames9[];
+
 extern LinkArch        link386;
 extern LinkArch        linkamd64;
 extern LinkArch        linkamd64p32;
@@ -634,6 +640,7 @@ extern      LinkArch        linkpower64;
 extern LinkArch        linkpower64le;
 
 #pragma        varargck        type    "A"     int
+#pragma        varargck        type    "E"     uint
 #pragma        varargck        type    "D"     Addr*
 #pragma        varargck        type    "lD"    Addr*
 #pragma        varargck        type    "P"     Prog*
index e94efdbceeed48e327cef832f875859dce5cab75..8cf6be2a434d35eb2b3d0b6624ce554006e90627 100644 (file)
@@ -56,8 +56,8 @@ const (
        blogPath       = "golang.org/x/blog"
        toolPath       = "golang.org/x/tools"
        tourPath       = "code.google.com/p/go-tour"
-       defaultToolTag = "release-branch.go1.3"
-       defaultTourTag = "release-branch.go1.3"
+       defaultToolTag = "release-branch.go1.4"
+       defaultTourTag = "release-branch.go1.4"
 )
 
 // Import paths for tool commands.
index 5016d1cc83b7e11f49c8bf7f03a3bb71a7432163..a606f1d3105e969afc034d7cafe42f2fa09653c0 100644 (file)
@@ -75,12 +75,18 @@ struct      Reg
 {
        Flow    f;
 
-       Bits    set;            // variables written by this instruction.
-       Bits    use1;           // variables read by prog->from.
-       Bits    use2;           // variables read by prog->to.
+       Bits    set;            // regopt variables written by this instruction.
+       Bits    use1;           // regopt variables read by prog->from.
+       Bits    use2;           // regopt variables read by prog->to.
 
+       // refahead/refbehind are the regopt variables whose current
+       // value may be used in the following/preceding instructions
+       // up to a CALL (or the value is clobbered).
        Bits    refbehind;
        Bits    refahead;
+       // calahead/calbehind are similar, but for variables in
+       // instructions that are reachable after hitting at least one
+       // CALL.
        Bits    calbehind;
        Bits    calahead;
        Bits    regdiff;
@@ -93,6 +99,16 @@ struct       Reg
 
 #define        NRGN    600
 /*c2go enum { NRGN = 600 }; */
+
+// A Rgn represents a single regopt variable over a region of code
+// where a register could potentially be dedicated to that variable.
+// The code encompassed by a Rgn is defined by the flow graph,
+// starting at enter, flood-filling forward while varno is refahead
+// and backward while varno is refbehind, and following branches.  A
+// single variable may be represented by multiple disjoint Rgns and
+// each Rgn may choose a different register for that variable.
+// Registers are allocated to regions greedily in order of descending
+// cost.
 struct Rgn
 {
        Reg*    enter;
@@ -144,7 +160,7 @@ void        prop(Reg*, Bits, Bits);
 void   synch(Reg*, Bits);
 uint32 allreg(uint32, Rgn*);
 void   paint1(Reg*, int);
-uint32 paint2(Reg*, int);
+uint32 paint2(Reg*, int, int);
 void   paint3(Reg*, int, uint32, int);
 void   addreg(Adr*, int);
 void   dumpit(char *str, Flow *r0, int);
@@ -187,16 +203,16 @@ enum
        SizeF = 1<<7, // float aka float32
        SizeD = 1<<8, // double aka float64
 
-       // Left side: address taken, read, write.
+       // Left side (Prog.from): address taken, read, write.
        LeftAddr = 1<<9,
        LeftRead = 1<<10,
        LeftWrite = 1<<11,
        
-       // Register in middle; never written.
+       // Register in middle (Prog.reg); only ever read.
        RegRead = 1<<12,
        CanRegRead = 1<<13,
        
-       // Right side: address taken, read, write.
+       // Right side (Prog.to): address taken, read, write.
        RightAddr = 1<<14,
        RightRead = 1<<15,
        RightWrite = 1<<16,
index 4417928731d3c67a97ec8b7d5f4aecad27f23ca3..611310f124f75134dafddd93c7df0e245498deff 100644 (file)
@@ -230,7 +230,7 @@ regopt(Prog *firstp)
 
                /* the mod/div runtime routines smash R12 */
                if(p->as == ADIV || p->as == ADIVU || p->as == AMOD || p->as == AMODU)
-                       r->set.b[z] |= RtoB(12);
+                       r->set.b[0] |= RtoB(12);
        }
        if(firstr == R)
                return;
@@ -454,9 +454,13 @@ brk:
         * replace code (paint3)
         */
        rgp = region;
+       if(debug['R'] && debug['v'])
+               print("\nregisterizing\n");
        for(i=0; i<nregion; i++) {
+               if(debug['R'] && debug['v'])
+                       print("region %d: cost %d varno %d enter %d\n", i, rgp->cost, rgp->varno, rgp->enter->f.prog->pc);
                bit = blsh(rgp->varno);
-               vreg = paint2(rgp->enter, rgp->varno);
+               vreg = paint2(rgp->enter, rgp->varno, 0);
                vreg = allreg(vreg, rgp);
                if(debug['R']) {
                        if(rgp->regno >= NREG)
@@ -477,9 +481,6 @@ brk:
                rgp++;
        }
 
-       if(debug['R'] && debug['v'])
-               dumpit("pass6", &firstr->f, 1);
-
        /*
         * free aux structures. peep allocates new ones.
         */
@@ -488,6 +489,15 @@ brk:
        flowend(g);
        firstr = R;
 
+       if(debug['R'] && debug['v']) {
+               // Rebuild flow graph, since we inserted instructions
+               g = flowstart(firstp, sizeof(Reg));
+               firstr = (Reg*)g->start;
+               dumpit("pass6", &firstr->f, 1);
+               flowend(g);
+               firstr = R;
+       }
+
        /*
         * pass 7
         * peep-hole on basic block
@@ -1189,7 +1199,7 @@ paint1(Reg *r, int bn)
 }
 
 uint32
-paint2(Reg *r, int bn)
+paint2(Reg *r, int bn, int depth)
 {
        Reg *r1;
        int z;
@@ -1213,6 +1223,9 @@ paint2(Reg *r, int bn)
                r = r1;
        }
        for(;;) {
+               if(debug['R'] && debug['v'])
+                       print("  paint2 %d %P\n", depth, r->f.prog);
+
                r->act.b[z] &= ~bb;
 
                vreg |= r->regu;
@@ -1220,14 +1233,14 @@ paint2(Reg *r, int bn)
                if(r->refbehind.b[z] & bb)
                        for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link)
                                if(r1->refahead.b[z] & bb)
-                                       vreg |= paint2(r1, bn);
+                                       vreg |= paint2(r1, bn, depth+1);
 
                if(!(r->refahead.b[z] & bb))
                        break;
                r1 = (Reg*)r->f.s2;
                if(r1 != R)
                        if(r1->refbehind.b[z] & bb)
-                               vreg |= paint2(r1, bn);
+                               vreg |= paint2(r1, bn, depth+1);
                r = (Reg*)r->f.s1;
                if(r == R)
                        break;
@@ -1344,6 +1357,8 @@ RtoB(int r)
 int
 BtoR(uint32 b)
 {
+       // TODO Allow R0 and R1, but be careful with a 0 return
+       // TODO Allow R9. Only R10 is reserved now (just g, not m).
        b &= 0x11fcL;   // excluded R9 and R10 for m and g, but not R12
        if(b == 0)
                return 0;
@@ -1442,12 +1457,14 @@ dumpit(char *str, Flow *r0, int isreg)
                                print(" (only)");
                        print("\n");
                }
-//             r1 = r->s1;
-//             if(r1 != nil) {
-//                     print(" succ:");
-//                     for(; r1 != R; r1 = r1->s1)
-//                             print(" %.4ud", (int)r1->prog->pc);
-//                     print("\n");
-//             }
+               // Print successors if it's not just the next one
+               if(r->s1 != r->link || r->s2 != nil) {
+                       print(" succ:");
+                       if(r->s1 != nil)
+                               print(" %.4ud", (int)r->s1->prog->pc);
+                       if(r->s2 != nil)
+                               print(" %.4ud", (int)r->s2->prog->pc);
+                       print("\n");
+               }
        }
 }
index 7b16ac4468f87e2f9ee414a403626340610d78fe..38a33db6429dd7f3503d7b07fb65ba614bbdc48c 100644 (file)
@@ -338,6 +338,8 @@ enum
        D_STATIC = (D_NONE+4),
        D_AUTO = (D_NONE+5),
        D_PARAM = (D_NONE+6),
+
+       D_LAST = (D_NONE+26),
 };
 
 /*
index 4c9bb89fc86e4cb3de41ce5865c2802ade814cb7..493171ef82db80ff7b6ba1bb8a9662ee06dce717 100644 (file)
@@ -75,12 +75,18 @@ struct      Reg
 {
        Flow    f;
 
-       Bits    set;            // variables written by this instruction.
-       Bits    use1;           // variables read by prog->from.
-       Bits    use2;           // variables read by prog->to.
+       Bits    set;            // regopt variables written by this instruction.
+       Bits    use1;           // regopt variables read by prog->from.
+       Bits    use2;           // regopt variables read by prog->to.
 
+       // refahead/refbehind are the regopt variables whose current
+       // value may be used in the following/preceding instructions
+       // up to a CALL (or the value is clobbered).
        Bits    refbehind;
        Bits    refahead;
+       // calahead/calbehind are similar, but for variables in
+       // instructions that are reachable after hitting at least one
+       // CALL.
        Bits    calbehind;
        Bits    calahead;
        Bits    regdiff;
@@ -93,6 +99,16 @@ struct       Reg
 
 #define        NRGN    600
 /*c2go enum { NRGN = 600 }; */
+
+// A Rgn represents a single regopt variable over a region of code
+// where a register could potentially be dedicated to that variable.
+// The code encompassed by a Rgn is defined by the flow graph,
+// starting at enter, flood-filling forward while varno is refahead
+// and backward while varno is refbehind, and following branches.  A
+// single variable may be represented by multiple disjoint Rgns and
+// each Rgn may choose a different register for that variable.
+// Registers are allocated to regions greedily in order of descending
+// cost.
 struct Rgn
 {
        Reg*    enter;
@@ -140,7 +156,7 @@ void        prop(Reg*, Bits, Bits);
 void   synch(Reg*, Bits);
 uint32 allreg(uint32, Rgn*);
 void   paint1(Reg*, int);
-uint32 paint2(Reg*, int);
+uint32 paint2(Reg*, int, int);
 void   paint3(Reg*, int, uint32, int);
 void   addreg(Adr*, int);
 void   dumpone(Flow*, int);
@@ -165,8 +181,8 @@ typedef struct ProgInfo ProgInfo;
 struct ProgInfo
 {
        uint32 flags; // the bits below
-       uint32 reguse; // required registers used by this instruction
-       uint32 regset; // required registers set by this instruction
+       uint32 reguse; // registers implicitly used by this instruction
+       uint32 regset; // registers implicitly set by this instruction
        uint32 regindex; // registers used by addressing mode
 };
 
@@ -187,12 +203,12 @@ enum
        SizeF = 1<<7, // float aka float32
        SizeD = 1<<8, // double aka float64
 
-       // Left side: address taken, read, write.
+       // Left side (Prog.from): address taken, read, write.
        LeftAddr = 1<<9,
        LeftRead = 1<<10,
        LeftWrite = 1<<11,
        
-       // Right side: address taken, read, write.
+       // Right side (Prog.to): address taken, read, write.
        RightAddr = 1<<12,
        RightRead = 1<<13,
        RightWrite = 1<<14,
index 4ce2f4db00177805e29122315712494f6e109112..75f9573b2e5d5572c18fd3799a70abee94dcdfcd 100644 (file)
@@ -389,9 +389,13 @@ brk:
         * replace code (paint3)
         */
        rgp = region;
+       if(debug['R'] && debug['v'])
+               print("\nregisterizing\n");
        for(i=0; i<nregion; i++) {
+               if(debug['R'] && debug['v'])
+                       print("region %d: cost %d varno %d enter %d\n", i, rgp->cost, rgp->varno, rgp->enter->f.prog->pc);
                bit = blsh(rgp->varno);
-               vreg = paint2(rgp->enter, rgp->varno);
+               vreg = paint2(rgp->enter, rgp->varno, 0);
                vreg = allreg(vreg, rgp);
                if(rgp->regno != 0) {
                        if(debug['R'] && debug['v']) {
@@ -406,9 +410,6 @@ brk:
                rgp++;
        }
 
-       if(debug['R'] && debug['v'])
-               dumpit("pass6", &firstr->f, 1);
-       
        /*
         * free aux structures. peep allocates new ones.
         */
@@ -417,6 +418,15 @@ brk:
        flowend(g);
        firstr = R;
 
+       if(debug['R'] && debug['v']) {
+               // Rebuild flow graph, since we inserted instructions
+               g = flowstart(firstp, sizeof(Reg));
+               firstr = (Reg*)g->start;
+               dumpit("pass6", &firstr->f, 1);
+               flowend(g);
+               firstr = R;
+       }
+
        /*
         * pass 7
         * peep-hole on basic block
@@ -1020,7 +1030,7 @@ paint1(Reg *r, int bn)
 }
 
 uint32
-paint2(Reg *r, int bn)
+paint2(Reg *r, int bn, int depth)
 {
        Reg *r1;
        int z;
@@ -1044,6 +1054,9 @@ paint2(Reg *r, int bn)
                r = r1;
        }
        for(;;) {
+               if(debug['R'] && debug['v'])
+                       print("  paint2 %d %P\n", depth, r->f.prog);
+
                r->act.b[z] &= ~bb;
 
                vreg |= r->regu;
@@ -1051,14 +1064,14 @@ paint2(Reg *r, int bn)
                if(r->refbehind.b[z] & bb)
                        for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link)
                                if(r1->refahead.b[z] & bb)
-                                       vreg |= paint2(r1, bn);
+                                       vreg |= paint2(r1, bn, depth+1);
 
                if(!(r->refahead.b[z] & bb))
                        break;
                r1 = (Reg*)r->f.s2;
                if(r1 != R)
                        if(r1->refbehind.b[z] & bb)
-                               vreg |= paint2(r1, bn);
+                               vreg |= paint2(r1, bn, depth+1);
                r = (Reg*)r->f.s1;
                if(r == R)
                        break;
@@ -1259,12 +1272,14 @@ dumpit(char *str, Flow *r0, int isreg)
                                print(" %.4ud", (int)r1->prog->pc);
                        print("\n");
                }
-//             r1 = r->s1;
-//             if(r1 != R) {
-//                     print(" succ:");
-//                     for(; r1 != R; r1 = r1->s1)
-//                             print(" %.4ud", (int)r1->prog->pc);
-//                     print("\n");
-//             }
+               // Print successors if it's not just the next one
+               if(r->s1 != r->link || r->s2 != nil) {
+                       print(" succ:");
+                       if(r->s1 != nil)
+                               print(" %.4ud", (int)r->s1->prog->pc);
+                       if(r->s2 != nil)
+                               print(" %.4ud", (int)r->s2->prog->pc);
+                       print("\n");
+               }
        }
 }
index af72784e84a13d19447b01ae5ecfe7cbeea33084..c09ac282424d543ca59dcaf91464dc189877e271 100644 (file)
@@ -865,6 +865,8 @@ enum
 
        D_INDIR,        /* additive */
 
+       D_LAST,
+
        T_TYPE          = 1<<0,
        T_INDEX         = 1<<1,
        T_OFFSET        = 1<<2,
index 0e2d165b17eb5e5f5264666143682af448f5da00..5445f91275e792fa8c76534a57e743e017053ded 100644 (file)
@@ -75,12 +75,18 @@ struct      Reg
 {
        Flow    f;
 
-       Bits    set;            // variables written by this instruction.
-       Bits    use1;           // variables read by prog->from.
-       Bits    use2;           // variables read by prog->to.
+       Bits    set;            // regopt variables written by this instruction.
+       Bits    use1;           // regopt variables read by prog->from.
+       Bits    use2;           // regopt variables read by prog->to.
 
+       // refahead/refbehind are the regopt variables whose current
+       // value may be used in the following/preceding instructions
+       // up to a CALL (or the value is clobbered).
        Bits    refbehind;
        Bits    refahead;
+       // calahead/calbehind are similar, but for variables in
+       // instructions that are reachable after hitting at least one
+       // CALL.
        Bits    calbehind;
        Bits    calahead;
        Bits    regdiff;
@@ -106,6 +112,16 @@ struct     Reg
 
 #define        NRGN    600
 /*c2go enum { NRGN = 600 }; */
+
+// A Rgn represents a single regopt variable over a region of code
+// where a register could potentially be dedicated to that variable.
+// The code encompassed by a Rgn is defined by the flow graph,
+// starting at enter, flood-filling forward while varno is refahead
+// and backward while varno is refbehind, and following branches.  A
+// single variable may be represented by multiple disjoint Rgns and
+// each Rgn may choose a different register for that variable.
+// Registers are allocated to regions greedily in order of descending
+// cost.
 struct Rgn
 {
        Reg*    enter;
@@ -158,7 +174,7 @@ void        loopit(Reg*, int32);
 void   synch(Reg*, Bits);
 uint32 allreg(uint32, Rgn*);
 void   paint1(Reg*, int);
-uint32 paint2(Reg*, int);
+uint32 paint2(Reg*, int, int);
 void   paint3(Reg*, int, uint32, int);
 void   addreg(Adr*, int);
 void   dumpone(Flow*, int);
@@ -183,8 +199,8 @@ typedef struct ProgInfo ProgInfo;
 struct ProgInfo
 {
        uint32 flags; // the bits below
-       uint32 reguse; // required registers used by this instruction
-       uint32 regset; // required registers set by this instruction
+       uint32 reguse; // registers implicitly used by this instruction
+       uint32 regset; // registers implicitly set by this instruction
        uint32 regindex; // registers used by addressing mode
 };
 
@@ -205,12 +221,12 @@ enum
        SizeF = 1<<7, // float aka float32
        SizeD = 1<<8, // double aka float64
 
-       // Left side: address taken, read, write.
+       // Left side (Prog.from): address taken, read, write.
        LeftAddr = 1<<9,
        LeftRead = 1<<10,
        LeftWrite = 1<<11,
        
-       // Right side: address taken, read, write.
+       // Right side (Prog.to): address taken, read, write.
        RightAddr = 1<<12,
        RightRead = 1<<13,
        RightWrite = 1<<14,
index 79d60bed55205b7c2710f60acf99b8be9213fe30..d7394a16d254c7f4cd8ad33c07a38892ffa7ec00 100644 (file)
@@ -358,18 +358,19 @@ brk:
         * replace code (paint3)
         */
        rgp = region;
+       if(debug['R'] && debug['v'])
+               print("\nregisterizing\n");
        for(i=0; i<nregion; i++) {
+               if(debug['R'] && debug['v'])
+                       print("region %d: cost %d varno %d enter %lld\n", i, rgp->cost, rgp->varno, rgp->enter->f.prog->pc);
                bit = blsh(rgp->varno);
-               vreg = paint2(rgp->enter, rgp->varno);
+               vreg = paint2(rgp->enter, rgp->varno, 0);
                vreg = allreg(vreg, rgp);
                if(rgp->regno != 0)
                        paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
                rgp++;
        }
 
-       if(debug['R'] && debug['v'])
-               dumpit("pass6", &firstr->f, 1);
-
        /*
         * free aux structures. peep allocates new ones.
         */
@@ -378,6 +379,15 @@ brk:
        flowend(g);
        firstr = R;
 
+       if(debug['R'] && debug['v']) {
+               // Rebuild flow graph, since we inserted instructions
+               g = flowstart(firstp, sizeof(Reg));
+               firstr = (Reg*)g->start;
+               dumpit("pass6", &firstr->f, 1);
+               flowend(g);
+               firstr = R;
+       }
+
        /*
         * pass 7
         * peep-hole on basic block
@@ -926,7 +936,7 @@ paint1(Reg *r, int bn)
        Reg *r1;
        Prog *p;
        int z;
-       uint64 bb;
+       uint64 bb, rbz;
 
        z = bn/64;
        bb = 1LL<<(bn%64);
@@ -945,7 +955,8 @@ paint1(Reg *r, int bn)
                r = r1;
        }
 
-       if(LOAD(r) & ~(r->set.b[z]&~(r->use1.b[z]|r->use2.b[z])) & bb) {
+       rbz = ~(r->set.b[z]&~(r->use1.b[z]|r->use2.b[z]));
+       if(LOAD(r) & rbz & bb) {
                change -= CLOAD * r->f.loop;
        }
        for(;;) {
@@ -996,7 +1007,7 @@ paint1(Reg *r, int bn)
 }
 
 uint32
-paint2(Reg *r, int bn)
+paint2(Reg *r, int bn, int depth)
 {
        Reg *r1;
        int z;
@@ -1020,6 +1031,9 @@ paint2(Reg *r, int bn)
                r = r1;
        }
        for(;;) {
+               if(debug['R'] && debug['v'])
+                       print("  paint2 %d %P\n", depth, r->f.prog);
+
                r->act.b[z] &= ~bb;
 
                vreg |= r->regu;
@@ -1027,14 +1041,14 @@ paint2(Reg *r, int bn)
                if(r->refbehind.b[z] & bb)
                        for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link)
                                if(r1->refahead.b[z] & bb)
-                                       vreg |= paint2(r1, bn);
+                                       vreg |= paint2(r1, bn, depth+1);
 
                if(!(r->refahead.b[z] & bb))
                        break;
                r1 = (Reg*)r->f.s2;
                if(r1 != R)
                        if(r1->refbehind.b[z] & bb)
-                               vreg |= paint2(r1, bn);
+                               vreg |= paint2(r1, bn, depth+1);
                r = (Reg*)r->f.s1;
                if(r == R)
                        break;
@@ -1053,7 +1067,7 @@ paint3(Reg *r, int bn, uint32 rb, int rn)
        Reg *r1;
        Prog *p;
        int z;
-       uint64 bb;
+       uint64 bb, rbz;
 
        z = bn/64;
        bb = 1LL << (bn%64);
@@ -1072,7 +1086,8 @@ paint3(Reg *r, int bn, uint32 rb, int rn)
                r = r1;
        }
 
-       if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb)
+       rbz = ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z]));
+       if(LOAD(r) & rbz & bb)
                addmove(r, bn, rn, 0);
        for(;;) {
                r->act.b[z] |= bb;
@@ -1227,12 +1242,14 @@ dumpit(char *str, Flow *r0, int isreg)
                                print(" %.4ud", (int)r1->prog->pc);
                        print("\n");
                }
-//             r1 = r->s1;
-//             if(r1 != nil) {
-//                     print(" succ:");
-//                     for(; r1 != R; r1 = r1->s1)
-//                             print(" %.4ud", (int)r1->prog->pc);
-//                     print("\n");
-//             }
+               // Print successors if it's not just the next one
+               if(r->s1 != r->link || r->s2 != nil) {
+                       print(" succ:");
+                       if(r->s1 != nil)
+                               print(" %.4ud", (int)r->s1->prog->pc);
+                       if(r->s2 != nil)
+                               print(" %.4ud", (int)r->s2->prog->pc);
+                       print("\n");
+               }
        }
 }
index ed54f6744abfa35121b12671dd877d4837214953..596c5f61a8f9a32f15911d4c7b387eefa4d8be7a 100644 (file)
@@ -654,6 +654,8 @@ enum
 
        D_CONST2 = D_INDIR+D_INDIR,
 
+       D_LAST,
+
        T_TYPE          = 1<<0,
        T_INDEX         = 1<<1,
        T_OFFSET        = 1<<2,
index 26f21f7436c35e898fcab66db14dbbe15cdf1d7f..e2945ef89dff4ce9c22f46fd6b57420473b428b1 100644 (file)
@@ -250,7 +250,7 @@ struct
        "R27",          LREG,   27,
        "R28",          LREG,   28,
        "R29",          LREG,   29,
-       "R30",          LREG,   30,
+       "g",            LREG,   30, // avoid unintentionally clobbering g using R30
        "R31",          LREG,   31,
 
        "F",            LF,     0,
@@ -488,6 +488,7 @@ struct
        "SYSCALL",      LNOP, ASYSCALL,
        "UNDEF",        LNOP, AUNDEF,
 
+       "RET",          LRETRN, ARETURN,
        "RETURN",       LRETRN, ARETURN,
        "RFI",          LRETRN, ARFI,
        "RFCI",         LRETRN, ARFCI,
diff --git a/src/cmd/9c/Makefile b/src/cmd/9c/Makefile
deleted file mode 100644 (file)
index 3f528d7..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright 2012 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 ../../Make.dist
diff --git a/src/cmd/9c/Notes b/src/cmd/9c/Notes
deleted file mode 100644 (file)
index 92dd9de..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
--      effect of register expansion on 32-bit shifts and masks etc
-9c
--      multab
--      floating-point conversions
--      conversions of constants
--      nodtype for loads
--      sign-extension instruction (32-64) when in register?
--      double indexing
--      SLW (eg, in cat)
--      scheduling
-
-9l
--      D_QCONST, DWORD
--      maskgen
diff --git a/src/cmd/9c/cgen.c b/src/cmd/9c/cgen.c
deleted file mode 100644 (file)
index bd1f7b2..0000000
+++ /dev/null
@@ -1,1147 +0,0 @@
-// cmd/9c/cgen.c from Vita Nuova.
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2008 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-#include "../../runtime/funcdata.h"
-
-void
-cgen(Node *n, Node *nn)
-{
-       Node *l, *r;
-       Prog *p1;
-       Node nod, nod1, nod2, nod3, nod4;
-       int o;
-       int32 v, curs;
-
-       if(debug['g']) {
-               prtree(nn, "cgen lhs");
-               prtree(n, "cgen");
-       }
-       if(n == Z || n->type == T)
-               return;
-       if(typesu[n->type->etype] && (n->op != OFUNC || nn != Z)) {
-               sugen(n, nn, n->type->width);
-               return;
-       }
-       l = n->left;
-       r = n->right;
-       o = n->op;
-       if(n->addable >= INDEXED) {
-               if(nn == Z) {
-                       switch(o) {
-                       default:
-                               nullwarn(Z, Z);
-                               break;
-                       case OINDEX:
-                               nullwarn(l, r);
-                               break;
-                       }
-                       return;
-               }
-               gmove(n, nn);
-               return;
-       }
-       curs = cursafe;
-
-       if(n->complex >= FNX)
-       if(l->complex >= FNX)
-       if(r != Z && r->complex >= FNX)
-       switch(o) {
-       default:
-               regret(&nod, r, 0, 0);
-               cgen(r, &nod);
-
-               regsalloc(&nod1, r);
-               gopcode(OAS, &nod, Z, &nod1);
-
-               regfree(&nod);
-               nod = *n;
-               nod.right = &nod1;
-               cgen(&nod, nn);
-               return;
-
-       case OFUNC:
-       case OCOMMA:
-       case OANDAND:
-       case OOROR:
-       case OCOND:
-       case ODOT:
-               break;
-       }
-
-       switch(o) {
-       default:
-               diag(n, "unknown op in cgen: %O", o);
-               break;
-
-       case OAS:
-               if(l->op == OBIT)
-                       goto bitas;
-               if(l->addable >= INDEXED) {
-                       if(nn != Z || r->addable < INDEXED) {
-                               regalloc(&nod, r, nn);
-                               cgen(r, &nod);
-                               gmove(&nod, l);
-                               regfree(&nod);
-                       } else
-                               gmove(r, l);
-                       break;
-               }
-               if(l->complex >= r->complex) {
-                       reglcgen(&nod1, l, Z);
-                       if(r->addable >= INDEXED) {
-                               gmove(r, &nod1);
-                               if(nn != Z)
-                                       gmove(r, nn);
-                               regfree(&nod1);
-                               break;
-                       }
-                       regalloc(&nod, r, nn);
-                       cgen(r, &nod);
-               } else {
-                       regalloc(&nod, r, nn);
-                       cgen(r, &nod);
-                       reglcgen(&nod1, l, Z);
-               }
-               gmove(&nod, &nod1);
-               regfree(&nod);
-               regfree(&nod1);
-               break;
-
-       bitas:
-               n = l->left;
-               regalloc(&nod, r, nn);
-               if(l->complex >= r->complex) {
-                       reglcgen(&nod1, n, Z);
-                       cgen(r, &nod);
-               } else {
-                       cgen(r, &nod);
-                       reglcgen(&nod1, n, Z);
-               }
-               regalloc(&nod2, n, Z);
-               gopcode(OAS, &nod1, Z, &nod2);
-               bitstore(l, &nod, &nod1, &nod2, nn);
-               break;
-
-       case OBIT:
-               if(nn == Z) {
-                       nullwarn(l, Z);
-                       break;
-               }
-               bitload(n, &nod, Z, Z, nn);
-               gopcode(OAS, &nod, Z, nn);
-               regfree(&nod);
-               break;
-
-       case OXOR:
-               if(nn != Z)
-               if(r->op == OCONST && r->vconst == -1){
-                       cgen(l, nn);
-                       gopcode(OCOM, nn, Z, nn);
-                       break;
-               }
-
-       case OADD:
-       case OSUB:
-       case OAND:
-       case OOR:
-       case OLSHR:
-       case OASHL:
-       case OASHR:
-               /*
-                * immediate operands
-                */
-               if(nn != Z &&
-                  r->op == OCONST &&
-                  !typefd[n->type->etype] &&
-                  immconst(r)) {
-                       cgen(l, nn);
-                       if(r->vconst == 0)
-                       if(o != OAND)
-                               break;
-                       if(nn != Z)
-                               gopcode(o, r, Z, nn);
-                       break;
-               }
-
-       case OMUL:
-       case OLMUL:
-       case OLDIV:
-       case OLMOD:
-       case ODIV:
-       case OMOD:
-               if(nn == Z) {
-                       nullwarn(l, r);
-                       break;
-               }
-               if(o == OMUL || o == OLMUL) {
-                       if(mulcon(n, nn))
-                               break;
-                       if(debug['M'])
-                               print("%L multiply\n", n->lineno);
-               }
-               if(l->complex >= r->complex) {
-                       regalloc(&nod, l, nn);
-                       cgen(l, &nod);
-                       regalloc(&nod1, l, Z);          /* note: l used for type, so shifts work! */
-                       cgen(r, &nod1);
-                       gopcode(o, &nod1, Z, &nod);
-               } else {
-                       regalloc(&nod, l, nn);          /* note: l used for type, so shifts work! */
-                       cgen(r, &nod);
-                       regalloc(&nod1, l, Z);
-                       cgen(l, &nod1);
-                       gopcode(o, &nod, &nod1, &nod);
-               }
-               gopcode(OAS, &nod, Z, nn);
-               regfree(&nod);
-               regfree(&nod1);
-               break;
-
-       case OASLSHR:
-       case OASASHL:
-       case OASASHR:
-       case OASAND:
-       case OASADD:
-       case OASSUB:
-       case OASXOR:
-       case OASOR:
-               if(l->op == OBIT)
-                       goto asbitop;
-               if(r->op == OCONST &&
-                  !typefd[n->type->etype] &&
-                  immconst(r)) {
-                       if(l->addable < INDEXED)
-                               reglcgen(&nod2, l, Z);
-                       else
-                               nod2 = *l;
-                       regalloc(&nod, l, nn);          /* note: l used for type, so shifts work! */
-                       gopcode(OAS, &nod2, Z, &nod);
-                       gopcode(o, r, Z, &nod);
-                       gopcode(OAS, &nod, Z, &nod2);
-       
-                       regfree(&nod);
-                       if(l->addable < INDEXED)
-                               regfree(&nod2);
-                       break;
-               }
-
-       case OASLMUL:
-       case OASLDIV:
-       case OASLMOD:
-       case OASMUL:
-       case OASDIV:
-       case OASMOD:
-               if(l->op == OBIT)
-                       goto asbitop;
-               if(l->complex >= r->complex) {
-                       if(l->addable < INDEXED)
-                               reglcgen(&nod2, l, Z);
-                       else
-                               nod2 = *l;
-                       regalloc(&nod, n, nn);
-                       cgen(r, &nod);
-               } else {
-                       regalloc(&nod, n, nn);
-                       cgen(r, &nod);
-                       if(l->addable < INDEXED)
-                               reglcgen(&nod2, l, Z);
-                       else
-                               nod2 = *l;
-               }
-               regalloc(&nod1, n, Z);
-               gopcode(OAS, &nod2, Z, &nod1);
-               if(nod1.type->etype != nod.type->etype){
-                       regalloc(&nod3, &nod, Z);
-                       gmove(&nod1, &nod3);
-                       regfree(&nod1);
-                       nod1 = nod3;
-               }
-               gopcode(o, &nod, &nod1, &nod);
-               gmove(&nod, &nod2);
-               if(nn != Z)
-                       gmove(&nod, nn);
-               regfree(&nod);
-               regfree(&nod1);
-               if(l->addable < INDEXED)
-                       regfree(&nod2);
-               break;
-
-       asbitop:
-               regalloc(&nod4, n, nn);
-               regalloc(&nod3, r, Z);
-               if(l->complex >= r->complex) {
-                       bitload(l, &nod, &nod1, &nod2, &nod4);
-                       cgen(r, &nod3);
-               } else {
-                       cgen(r, &nod3);
-                       bitload(l, &nod, &nod1, &nod2, &nod4);
-               }
-               gmove(&nod, &nod4);
-               gopcode(n->op, &nod3, Z, &nod4);
-               regfree(&nod3);
-               gmove(&nod4, &nod);
-               regfree(&nod4);
-               bitstore(l, &nod, &nod1, &nod2, nn);
-               break;
-
-       case OADDR:
-               if(nn == Z) {
-                       nullwarn(l, Z);
-                       break;
-               }
-               lcgen(l, nn);
-               break;
-
-       case OFUNC:
-               if(l->complex >= FNX) {
-                       if(l->op != OIND)
-                               diag(n, "bad function call");
-
-                       regret(&nod, l->left, 0, 0);
-                       cgen(l->left, &nod);
-                       regsalloc(&nod1, l->left);
-                       gopcode(OAS, &nod, Z, &nod1);
-                       regfree(&nod);
-
-                       nod = *n;
-                       nod.left = &nod2;
-                       nod2 = *l;
-                       nod2.left = &nod1;
-                       nod2.complex = 1;
-                       cgen(&nod, nn);
-
-                       return;
-               }
-               if(REGARG >= 0)
-                       o = reg[REGARG];
-               gargs(r, &nod, &nod1);
-               if(l->addable < INDEXED) {
-                       reglcgen(&nod, l, Z);
-                       gopcode(OFUNC, Z, Z, &nod);
-                       regfree(&nod);
-               } else
-                       gopcode(OFUNC, Z, Z, l);
-               if(REGARG>=0)
-                       if(o != reg[REGARG])
-                               reg[REGARG]--;
-               regret(&nod, n, l->type, 1); // update maxarg if nothing else
-               if(nn != Z)
-                       gopcode(OAS, &nod, Z, nn);
-               if(nod.op == OREGISTER)
-                       regfree(&nod);
-               break;
-
-       case OIND:
-               if(nn == Z) {
-                       cgen(l, nn);
-                       break;
-               }
-               regialloc(&nod, n, nn);
-               r = l;
-               while(r->op == OADD)
-                       r = r->right;
-               if(sconst(r)) {
-                       v = r->vconst;
-                       r->vconst = 0;
-                       cgen(l, &nod);
-                       nod.xoffset += v;
-                       r->vconst = v;
-               } else
-                       cgen(l, &nod);
-               regind(&nod, n);
-               gopcode(OAS, &nod, Z, nn);
-               regfree(&nod);
-               break;
-
-       case OEQ:
-       case ONE:
-       case OLE:
-       case OLT:
-       case OGE:
-       case OGT:
-       case OLO:
-       case OLS:
-       case OHI:
-       case OHS:
-               if(nn == Z) {
-                       nullwarn(l, r);
-                       break;
-               }
-               boolgen(n, 1, nn);
-               break;
-
-       case OANDAND:
-       case OOROR:
-               boolgen(n, 1, nn);
-               if(nn == Z)
-                       patch(p, pc);
-               break;
-
-       case ONOT:
-               if(nn == Z) {
-                       nullwarn(l, Z);
-                       break;
-               }
-               boolgen(n, 1, nn);
-               break;
-
-       case OCOMMA:
-               cgen(l, Z);
-               cgen(r, nn);
-               break;
-
-       case OCAST:
-               if(nn == Z) {
-                       nullwarn(l, Z);
-                       break;
-               }
-               /*
-                * convert from types l->n->nn
-                */
-               if(nocast(l->type, n->type) && nocast(n->type, nn->type)) {
-                       /* both null, gen l->nn */
-                       cgen(l, nn);
-                       break;
-               }
-               regalloc(&nod, l, nn);
-               cgen(l, &nod);
-               regalloc(&nod1, n, &nod);
-               gopcode(OAS, &nod, Z, &nod1);
-               gopcode(OAS, &nod1, Z, nn);
-               regfree(&nod1);
-               regfree(&nod);
-               break;
-
-       case ODOT:
-               sugen(l, nodrat, l->type->width);
-               if(nn != Z) {
-                       warn(n, "non-interruptable temporary");
-                       nod = *nodrat;
-                       if(!r || r->op != OCONST) {
-                               diag(n, "DOT and no offset");
-                               break;
-                       }
-                       nod.xoffset += (int32)r->vconst;
-                       nod.type = n->type;
-                       cgen(&nod, nn);
-               }
-               break;
-
-       case OCOND:
-               bcgen(l, 1);
-               p1 = p;
-               cgen(r->left, nn);
-               gbranch(OGOTO);
-               patch(p1, pc);
-               p1 = p;
-               cgen(r->right, nn);
-               patch(p1, pc);
-               break;
-
-       case OPOSTINC:
-       case OPOSTDEC:
-               v = 1;
-               if(l->type->etype == TIND)
-                       v = l->type->link->width;
-               if(o == OPOSTDEC)
-                       v = -v;
-               if(l->op == OBIT)
-                       goto bitinc;
-               if(nn == Z)
-                       goto pre;
-
-               if(l->addable < INDEXED)
-                       reglcgen(&nod2, l, Z);
-               else
-                       nod2 = *l;
-
-               regalloc(&nod, l, nn);
-               gopcode(OAS, &nod2, Z, &nod);
-               regalloc(&nod1, l, Z);
-               if(typefd[l->type->etype]) {
-                       regalloc(&nod3, l, Z);
-                       if(v < 0) {
-                               gopcode(OAS, nodfconst(-v), Z, &nod3);
-                               gopcode(OSUB, &nod3, &nod, &nod1);
-                       } else {
-                               gopcode(OAS, nodfconst(v), Z, &nod3);
-                               gopcode(OADD, &nod3, &nod, &nod1);
-                       }
-                       regfree(&nod3);
-               } else
-                       gopcode(OADD, nodconst(v), &nod, &nod1);
-               gopcode(OAS, &nod1, Z, &nod2);
-
-               regfree(&nod);
-               regfree(&nod1);
-               if(l->addable < INDEXED)
-                       regfree(&nod2);
-               break;
-
-       case OPREINC:
-       case OPREDEC:
-               v = 1;
-               if(l->type->etype == TIND)
-                       v = l->type->link->width;
-               if(o == OPREDEC)
-                       v = -v;
-               if(l->op == OBIT)
-                       goto bitinc;
-
-       pre:
-               if(l->addable < INDEXED)
-                       reglcgen(&nod2, l, Z);
-               else
-                       nod2 = *l;
-
-               regalloc(&nod, l, nn);
-               gopcode(OAS, &nod2, Z, &nod);
-               if(typefd[l->type->etype]) {
-                       regalloc(&nod3, l, Z);
-                       if(v < 0) {
-                               gopcode(OAS, nodfconst(-v), Z, &nod3);
-                               gopcode(OSUB, &nod3, Z, &nod);
-                       } else {
-                               gopcode(OAS, nodfconst(v), Z, &nod3);
-                               gopcode(OADD, &nod3, Z, &nod);
-                       }
-                       regfree(&nod3);
-               } else
-                       gopcode(OADD, nodconst(v), Z, &nod);
-               gopcode(OAS, &nod, Z, &nod2);
-               if(nn && l->op == ONAME)        /* in x=++i, emit USED(i) */
-                       gins(ANOP, l, Z);
-
-               regfree(&nod);
-               if(l->addable < INDEXED)
-                       regfree(&nod2);
-               break;
-
-       bitinc:
-               if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
-                       bitload(l, &nod, &nod1, &nod2, Z);
-                       gopcode(OAS, &nod, Z, nn);
-                       gopcode(OADD, nodconst(v), Z, &nod);
-                       bitstore(l, &nod, &nod1, &nod2, Z);
-                       break;
-               }
-               bitload(l, &nod, &nod1, &nod2, nn);
-               gopcode(OADD, nodconst(v), Z, &nod);
-               bitstore(l, &nod, &nod1, &nod2, nn);
-               break;
-       }
-       cursafe = curs;
-}
-
-void
-reglcgen(Node *t, Node *n, Node *nn)
-{
-       Node *r;
-       int32 v;
-
-       regialloc(t, n, nn);
-       if(n->op == OIND) {
-               r = n->left;
-               while(r->op == OADD)
-                       r = r->right;
-               if(sconst(r)) {
-                       v = r->vconst;
-                       r->vconst = 0;
-                       lcgen(n, t);
-                       t->xoffset += v;
-                       r->vconst = v;
-                       regind(t, n);
-                       return;
-               }
-       }
-       lcgen(n, t);
-       regind(t, n);
-}
-
-void
-lcgen(Node *n, Node *nn)
-{
-       Prog *p1;
-       Node nod;
-
-       if(debug['g']) {
-               prtree(nn, "lcgen lhs");
-               prtree(n, "lcgen");
-       }
-       if(n == Z || n->type == T)
-               return;
-       if(nn == Z) {
-               nn = &nod;
-               regalloc(&nod, n, Z);
-       }
-       switch(n->op) {
-       default:
-               if(n->addable < INDEXED) {
-                       diag(n, "unknown op in lcgen: %O", n->op);
-                       break;
-               }
-               nod = *n;
-               nod.op = OADDR;
-               nod.left = n;
-               nod.right = Z;
-               nod.type = types[TIND];
-               gopcode(OAS, &nod, Z, nn);
-               break;
-
-       case OCOMMA:
-               cgen(n->left, n->left);
-               lcgen(n->right, nn);
-               break;
-
-       case OIND:
-               cgen(n->left, nn);
-               break;
-
-       case OCOND:
-               bcgen(n->left, 1);
-               p1 = p;
-               lcgen(n->right->left, nn);
-               gbranch(OGOTO);
-               patch(p1, pc);
-               p1 = p;
-               lcgen(n->right->right, nn);
-               patch(p1, pc);
-               break;
-       }
-}
-
-void
-bcgen(Node *n, int true)
-{
-
-       if(n->type == T)
-               gbranch(OGOTO);
-       else
-               boolgen(n, true, Z);
-}
-
-void
-boolgen(Node *n, int true, Node *nn)
-{
-       int o;
-       Prog *p1, *p2;
-       Node *l, *r, nod, nod1;
-       int32 curs;
-
-       if(debug['g']) {
-               prtree(nn, "boolgen lhs");
-               prtree(n, "boolgen");
-       }
-       curs = cursafe;
-       l = n->left;
-       r = n->right;
-       switch(n->op) {
-
-       default:
-               if(n->op == OCONST) {
-                       o = vconst(n);
-                       if(!true)
-                               o = !o;
-                       gbranch(OGOTO);
-                       if(o) {
-                               p1 = p;
-                               gbranch(OGOTO);
-                               patch(p1, pc);
-                       }
-                       goto com;
-               }
-               regalloc(&nod, n, nn);
-               cgen(n, &nod);
-               o = ONE;
-               if(true)
-                       o = comrel[relindex(o)];
-               if(typefd[n->type->etype]) {
-                       nodreg(&nod1, n, NREG+FREGZERO);
-                       gopcode(o, &nod, Z, &nod1);
-               } else
-                       gopcode(o, &nod, Z, nodconst(0));
-               regfree(&nod);
-               goto com;
-
-       case OCOMMA:
-               cgen(l, Z);
-               boolgen(r, true, nn);
-               break;
-
-       case ONOT:
-               boolgen(l, !true, nn);
-               break;
-
-       case OCOND:
-               bcgen(l, 1);
-               p1 = p;
-               bcgen(r->left, true);
-               p2 = p;
-               gbranch(OGOTO);
-               patch(p1, pc);
-               p1 = p;
-               bcgen(r->right, !true);
-               patch(p2, pc);
-               p2 = p;
-               gbranch(OGOTO);
-               patch(p1, pc);
-               patch(p2, pc);
-               goto com;
-
-       case OANDAND:
-               if(!true)
-                       goto caseor;
-
-       caseand:
-               bcgen(l, true);
-               p1 = p;
-               bcgen(r, !true);
-               p2 = p;
-               patch(p1, pc);
-               gbranch(OGOTO);
-               patch(p2, pc);
-               goto com;
-
-       case OOROR:
-               if(!true)
-                       goto caseand;
-
-       caseor:
-               bcgen(l, !true);
-               p1 = p;
-               bcgen(r, !true);
-               p2 = p;
-               gbranch(OGOTO);
-               patch(p1, pc);
-               patch(p2, pc);
-               goto com;
-
-       case OEQ:
-       case ONE:
-       case OLE:
-       case OLT:
-       case OGE:
-       case OGT:
-       case OHI:
-       case OHS:
-       case OLO:
-       case OLS:
-               o = n->op;
-               if(true)
-                       o = comrel[relindex(o)];
-               if(l->complex >= FNX && r->complex >= FNX) {
-                       regret(&nod, r, 0, 0);
-                       cgen(r, &nod);
-                       regsalloc(&nod1, r);
-                       gopcode(OAS, &nod, Z, &nod1);
-                       regfree(&nod);
-                       nod = *n;
-                       nod.right = &nod1;
-                       boolgen(&nod, true, nn);
-                       break;
-               }
-               if(sconst(r)) {
-                       regalloc(&nod, l, nn);
-                       cgen(l, &nod);
-                       gopcode(o, &nod, Z, r);
-                       regfree(&nod);
-                       goto com;
-               }
-               if(l->complex >= r->complex) {
-                       regalloc(&nod1, l, nn);
-                       cgen(l, &nod1);
-                       regalloc(&nod, r, Z);
-                       cgen(r, &nod);
-               } else {
-                       regalloc(&nod, r, nn);
-                       cgen(r, &nod);
-                       regalloc(&nod1, l, Z);
-                       cgen(l, &nod1);
-               }
-               gopcode(o, &nod1, Z, &nod);
-               regfree(&nod);
-               regfree(&nod1);
-
-       com:
-               if(nn != Z) {
-                       p1 = p;
-                       gopcode(OAS, nodconst(1L), Z, nn);
-                       gbranch(OGOTO);
-                       p2 = p;
-                       patch(p1, pc);
-                       gopcode(OAS, nodconst(0L), Z, nn);
-                       patch(p2, pc);
-               }
-               break;
-       }
-       cursafe = curs;
-}
-
-void
-sugen(Node *n, Node *nn, int32 w)
-{
-       Prog *p1;
-       Node nod0, nod1, nod2, nod3, nod4, *l, *r;
-       Type *t;
-       int32 pc1;
-       int i, m, c;
-
-       if(n == Z || n->type == T)
-               return;
-       if(debug['g']) {
-               prtree(nn, "sugen lhs");
-               prtree(n, "sugen");
-       }
-       if(nn == nodrat)
-               if(w > nrathole)
-                       nrathole = w;
-       switch(n->op) {
-       case OIND:
-               if(nn == Z) {
-                       nullwarn(n->left, Z);
-                       break;
-               }
-
-       default:
-               goto copy;
-
-       case OCONST:
-               if(n->type && typev[n->type->etype]) {
-                       if(nn == Z) {
-                               nullwarn(n->left, Z);
-                               break;
-                       }
-
-                       t = nn->type;
-                       nn->type = types[TLONG];
-                       reglcgen(&nod1, nn, Z);
-                       nn->type = t;
-
-                       if(align(0, types[TCHAR], Aarg1, nil))  /* isbigendian */
-                               gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
-                       else
-                               gopcode(OAS, nod32const(n->vconst), Z, &nod1);
-                       nod1.xoffset += SZ_LONG;
-                       if(align(0, types[TCHAR], Aarg1, nil))  /* isbigendian */
-                               gopcode(OAS, nod32const(n->vconst), Z, &nod1);
-                       else
-                               gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
-
-                       regfree(&nod1);
-                       break;
-               }
-               goto copy;
-
-       case ODOT:
-               l = n->left;
-               sugen(l, nodrat, l->type->width);
-               if(nn != Z) {
-                       warn(n, "non-interruptable temporary");
-                       nod1 = *nodrat;
-                       r = n->right;
-                       if(!r || r->op != OCONST) {
-                               diag(n, "DOT and no offset");
-                               break;
-                       }
-                       nod1.xoffset += (int32)r->vconst;
-                       nod1.type = n->type;
-                       sugen(&nod1, nn, w);
-               }
-               break;
-
-       case OSTRUCT:
-               /*
-                * rewrite so lhs has no side effects
-                */
-               if(nn != Z && side(nn)) {
-                       nod1 = *n;
-                       nod1.type = typ(TIND, n->type);
-                       regalloc(&nod2, &nod1, Z);
-                       lcgen(nn, &nod2);
-                       regsalloc(&nod0, &nod1);
-                       gopcode(OAS, &nod2, Z, &nod0);
-                       regfree(&nod2);
-
-                       nod1 = *n;
-                       nod1.op = OIND;
-                       nod1.left = &nod0;
-                       nod1.right = Z;
-                       nod1.complex = 1;
-
-                       sugen(n, &nod1, w);
-                       return;
-               }
-
-               r = n->left;
-               for(t = n->type->link; t != T; t = t->down) {
-                       l = r;
-                       if(r->op == OLIST) {
-                               l = r->left;
-                               r = r->right;
-                       }
-                       if(nn == Z) {
-                               cgen(l, nn);
-                               continue;
-                       }
-                       /*
-                        * hand craft *(&nn + o) = l
-                        */
-                       nod0 = znode;
-                       nod0.op = OAS;
-                       nod0.type = t;
-                       nod0.left = &nod1;
-                       nod0.right = l;
-
-                       nod1 = znode;
-                       nod1.op = OIND;
-                       nod1.type = t;
-                       nod1.left = &nod2;
-
-                       nod2 = znode;
-                       nod2.op = OADD;
-                       nod2.type = typ(TIND, t);
-                       nod2.left = &nod3;
-                       nod2.right = &nod4;
-
-                       nod3 = znode;
-                       nod3.op = OADDR;
-                       nod3.type = nod2.type;
-                       nod3.left = nn;
-
-                       nod4 = znode;
-                       nod4.op = OCONST;
-                       nod4.type = nod2.type;
-                       nod4.vconst = t->offset;
-
-                       ccom(&nod0);
-                       acom(&nod0);
-                       xcom(&nod0);
-                       nod0.addable = 0;
-
-                       /* prtree(&nod0, "hand craft"); /* */
-                       cgen(&nod0, Z);
-               }
-               break;
-
-       case OAS:
-               if(nn == Z) {
-                       if(n->addable < INDEXED)
-                               sugen(n->right, n->left, w);
-                       break;
-               }
-               /* BOTCH -- functions can clobber rathole */
-               sugen(n->right, nodrat, w);
-               warn(n, "non-interruptable temporary");
-               sugen(nodrat, n->left, w);
-               sugen(nodrat, nn, w);
-               break;
-
-       case OFUNC:
-               if(!hasdotdotdot(n->left->type)) {
-                       cgen(n, Z);
-                       if(nn != Z) {
-                               curarg -= n->type->width;
-                               regret(&nod1, n, n->left->type, 1);
-                               if(nn->complex >= FNX) {
-                                       regsalloc(&nod2, n);
-                                       cgen(&nod1, &nod2);
-                                       nod1 = nod2;
-                               }
-                               cgen(&nod1, nn);
-                       }
-                       break;
-               }
-               if(nn == Z) {
-                       sugen(n, nodrat, w);
-                       break;
-               }
-               if(nn->op != OIND) {
-                       nn = new1(OADDR, nn, Z);
-                       nn->type = types[TIND];
-                       nn->addable = 0;
-               } else
-                       nn = nn->left;
-               n = new(OFUNC, n->left, new(OLIST, nn, n->right));
-               n->type = types[TVOID];
-               n->left->type = types[TVOID];
-               cgen(n, Z);
-               break;
-
-       case OCOND:
-               bcgen(n->left, 1);
-               p1 = p;
-               sugen(n->right->left, nn, w);
-               gbranch(OGOTO);
-               patch(p1, pc);
-               p1 = p;
-               sugen(n->right->right, nn, w);
-               patch(p1, pc);
-               break;
-
-       case OCOMMA:
-               cgen(n->left, Z);
-               sugen(n->right, nn, w);
-               break;
-       }
-       return;
-
-copy:
-       if(nn == Z)
-               return;
-       if(n->complex >= FNX && nn->complex >= FNX) {
-               t = nn->type;
-               nn->type = types[TLONG];
-               regialloc(&nod1, nn, Z);
-               lcgen(nn, &nod1);
-               regsalloc(&nod2, nn);
-               nn->type = t;
-
-               gopcode(OAS, &nod1, Z, &nod2);
-               regfree(&nod1);
-
-               nod2.type = typ(TIND, t);
-
-               nod1 = nod2;
-               nod1.op = OIND;
-               nod1.left = &nod2;
-               nod1.right = Z;
-               nod1.complex = 1;
-               nod1.type = t;
-
-               sugen(n, &nod1, w);
-               return;
-       }
-
-       if(n->complex > nn->complex) {
-               t = n->type;
-               n->type = types[TLONG];
-               reglcgen(&nod1, n, Z);
-               n->type = t;
-
-               t = nn->type;
-               nn->type = types[TLONG];
-               reglcgen(&nod2, nn, Z);
-               nn->type = t;
-       } else {
-               t = nn->type;
-               nn->type = types[TLONG];
-               reglcgen(&nod2, nn, Z);
-               nn->type = t;
-
-               t = n->type;
-               n->type = types[TLONG];
-               reglcgen(&nod1, n, Z);
-               n->type = t;
-       }
-
-       w /= SZ_LONG;
-       if(w <= 5) {
-               layout(&nod1, &nod2, w, 0, Z);
-               goto out;
-       }
-
-       /*
-        * minimize space for unrolling loop
-        * 3,4,5 times. (6 or more is never minimum)
-        * if small structure, try 2 also.
-        */
-       c = 0; /* set */
-       m = 100;
-       i = 3;
-       if(w <= 15)
-               i = 2;
-       for(; i<=5; i++)
-               if(i + w%i <= m) {
-                       c = i;
-                       m = c + w%c;
-               }
-
-       regalloc(&nod3, &regnode, Z);
-       layout(&nod1, &nod2, w%c, w/c, &nod3);
-       
-       pc1 = pc;
-       layout(&nod1, &nod2, c, 0, Z);
-
-       gopcode(OSUB, nodconst(1L), Z, &nod3);
-       nod1.op = OREGISTER;
-       gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod1);
-       nod2.op = OREGISTER;
-       gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod2);
-       
-       gopcode(OGT, &nod3, Z, nodconst(0));
-       patch(p, pc1);
-
-       regfree(&nod3);
-out:
-       regfree(&nod1);
-       regfree(&nod2);
-}
-
-void
-layout(Node *f, Node *t, int c, int cv, Node *cn)
-{
-       Node t1, t2;
-
-       while(c > 3) {
-               layout(f, t, 2, 0, Z);
-               c -= 2;
-       }
-
-       regalloc(&t1, &regnode, Z);
-       regalloc(&t2, &regnode, Z);
-       if(c > 0) {
-               gopcode(OAS, f, Z, &t1);
-               f->xoffset += SZ_LONG;
-       }
-       if(cn != Z)
-               gopcode(OAS, nodconst(cv), Z, cn);
-       if(c > 1) {
-               gopcode(OAS, f, Z, &t2);
-               f->xoffset += SZ_LONG;
-       }
-       if(c > 0) {
-               gopcode(OAS, &t1, Z, t);
-               t->xoffset += SZ_LONG;
-       }
-       if(c > 2) {
-               gopcode(OAS, f, Z, &t1);
-               f->xoffset += SZ_LONG;
-       }
-       if(c > 1) {
-               gopcode(OAS, &t2, Z, t);
-               t->xoffset += SZ_LONG;
-       }
-       if(c > 2) {
-               gopcode(OAS, &t1, Z, t);
-               t->xoffset += SZ_LONG;
-       }
-       regfree(&t1);
-       regfree(&t2);
-}
diff --git a/src/cmd/9c/doc.go b/src/cmd/9c/doc.go
deleted file mode 100644 (file)
index 6c9b476..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// 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.
-
-// +build ignore
-
-/*
-
-9c is a version of the Plan 9 C compiler.  The original is documented at
-
-       http://plan9.bell-labs.com/magic/man2html/1/8c
-
-Its target architecture is the Power64, referred to by these tools as
-power64 (big endian) or power64le (little endian).
-
-*/
-package main
diff --git a/src/cmd/9c/gc.h b/src/cmd/9c/gc.h
deleted file mode 100644 (file)
index fbe5099..0000000
+++ /dev/null
@@ -1,350 +0,0 @@
-// cmd/9c/gc.h from Vita Nuova.
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2008 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include       <u.h>
-#include       "../cc/cc.h"
-#include       "../9l/9.out.h"
-
-/*
- * 9c/powerpc64
- */
-#define        SZ_CHAR         1
-#define        SZ_SHORT        2
-#define        SZ_INT          4
-#define        SZ_LONG         4
-#define        SZ_IND          8
-#define        SZ_FLOAT        4
-#define        SZ_VLONG        8
-#define        SZ_DOUBLE       8
-#define        FNX             100
-
-typedef        struct  Case    Case;
-typedef        struct  C1      C1;
-typedef        struct  Multab  Multab;
-typedef        struct  Hintab  Hintab;
-typedef        struct  Reg     Reg;
-typedef        struct  Rgn     Rgn;
-
-#define        A       ((Adr*)0)
-
-#define        INDEXED 9
-#define        P       ((Prog*)0)
-
-struct Case
-{
-       Case*   link;
-       vlong   val;
-       int32   label;
-       char    def;
-       char isv;
-};
-#define        C       ((Case*)0)
-
-struct C1
-{
-       vlong   val;
-       int32   label;
-};
-
-struct Multab
-{
-       int32   val;
-       char    code[20];
-};
-
-struct Hintab
-{
-       ushort  val;
-       char    hint[10];
-};
-
-struct Reg
-{
-       int32   pc;
-       int32   rpo;            /* reverse post ordering */
-
-       Bits    set;
-       Bits    use1;
-       Bits    use2;
-
-       Bits    refbehind;
-       Bits    refahead;
-       Bits    calbehind;
-       Bits    calahead;
-       Bits    regdiff;
-       Bits    act;
-
-       int32   regu;
-       int32   loop;           /* could be shorter */
-
-       union
-       {
-               Reg*    log5;
-               int32   active;
-       };
-       Reg*    p1;
-       Reg*    p2;
-       Reg*    p2link;
-       Reg*    s1;
-       Reg*    s2;
-       Reg*    link;
-       Prog*   prog;
-};
-#define        R       ((Reg*)0)
-
-#define        NRGN    600
-struct Rgn
-{
-       Reg*    enter;
-       short   cost;
-       short   varno;
-       short   regno;
-};
-
-EXTERN int32   breakpc;
-EXTERN int32   nbreak;
-EXTERN Case*   cases;
-EXTERN Node    constnode;
-EXTERN Node    fconstnode;
-EXTERN Node    vconstnode;
-EXTERN int32   continpc;
-EXTERN int32   curarg;
-EXTERN int32   cursafe;
-EXTERN Prog*   lastp;
-extern int     hintabsize;
-EXTERN int32   maxargsafe;
-EXTERN Multab  multab[20];
-EXTERN int     mnstring;
-EXTERN Node*   nodrat;
-EXTERN Node*   nodret;
-EXTERN Node*   nodsafe;
-EXTERN int32   nrathole;
-EXTERN int32   nstring;
-EXTERN Prog*   p;
-EXTERN int32   pc;
-EXTERN Node    regnode;
-EXTERN Node    qregnode;
-EXTERN char    string[NSNAME];
-EXTERN Sym*    symrathole;
-EXTERN Node    znode;
-EXTERN Prog    zprog;
-EXTERN int     reg[NREG+NREG];
-EXTERN int32   exregoffset;
-EXTERN int32   exfregoffset;
-EXTERN uchar   typechlpv[NTYPE];
-
-#define        BLOAD(r)        band(bnot(r->refbehind), r->refahead)
-#define        BSTORE(r)       band(bnot(r->calbehind), r->calahead)
-#define        LOAD(r)         (~r->refbehind.b[z] & r->refahead.b[z])
-#define        STORE(r)        (~r->calbehind.b[z] & r->calahead.b[z])
-
-#define        bset(a,n)       ((a).b[(n)/32]&(1L<<(n)%32))
-
-#define        CLOAD   5
-#define        CREF    5
-#define        CINF    1000
-#define        LOOP    3
-
-EXTERN Rgn     region[NRGN];
-EXTERN Rgn*    rgp;
-EXTERN int     nregion;
-EXTERN int     nvar;
-
-EXTERN Bits    externs;
-EXTERN Bits    params;
-EXTERN Bits    consts;
-EXTERN Bits    addrs;
-
-EXTERN int32   regbits;
-EXTERN int32   exregbits;
-
-EXTERN int     change;
-EXTERN int     suppress;
-
-EXTERN Reg*    firstr;
-EXTERN Reg*    lastr;
-EXTERN Reg     zreg;
-EXTERN Reg*    freer;
-EXTERN Var     var[NVAR];
-EXTERN int32*  idom;
-EXTERN Reg**   rpo2r;
-EXTERN int32   maxnr;
-
-#define        R0ISZERO        (debug['0']==0)
-
-extern char*   anames[];
-extern Hintab  hintab[];
-
-/*
- * sgen.c
- */
-void   codgen(Node*, Node*);
-void   gen(Node*);
-void   usedset(Node*, int);
-void   noretval(int);
-void   xcom(Node*);
-int    bcomplex(Node*, Node*);
-Prog*  gtext(Sym*, int32);
-vlong  argsize(int);
-
-/*
- * cgen.c
- */
-void   cgen(Node*, Node*);
-void   reglcgen(Node*, Node*, Node*);
-void   lcgen(Node*, Node*);
-void   bcgen(Node*, int);
-void   boolgen(Node*, int, Node*);
-void   sugen(Node*, Node*, int32);
-void   layout(Node*, Node*, int, int, Node*);
-
-/*
- * txt.c
- */
-void   ginit(void);
-void   gclean(void);
-void   nextpc(void);
-void   gargs(Node*, Node*, Node*);
-void   garg1(Node*, Node*, Node*, int, Node**);
-Node*  nodconst(int32);
-Node*  nod32const(vlong);
-Node*  nodfconst(double);
-Node*  nodgconst(vlong v, Type *t);
-void   nodreg(Node*, Node*, int);
-void   regret(Node*, Node*, Type*, int);
-void   regalloc(Node*, Node*, Node*);
-void   regfree(Node*);
-void   regialloc(Node*, Node*, Node*);
-void   regsalloc(Node*, Node*);
-void   regaalloc1(Node*, Node*);
-void   regaalloc(Node*, Node*);
-void   regind(Node*, Node*);
-void   gprep(Node*, Node*);
-void   raddr(Node*, Prog*);
-void   naddr(Node*, Addr*);
-void   gmove(Node*, Node*);
-void   gins(int a, Node*, Node*);
-void   gopcode(int, Node*, Node*, Node*);
-int    samaddr(Node*, Node*);
-void   gbranch(int);
-int    immconst(Node*);
-void   patch(Prog*, int32);
-int    sconst(Node*);
-int    sval(int32);
-int    uconst(Node*);
-void   gpseudo(int, Sym*, Node*);
-void   gprefetch(Node*);
-void   gpcdata(int, int);
-
-/*
- * swt.c
- */
-int    swcmp(const void*, const void*);
-void   doswit(Node*);
-void   swit1(C1*, int, int32, Node*);
-void   swit2(C1*, int, int32, Node*, Node*);
-void   newcase(void);
-void   bitload(Node*, Node*, Node*, Node*, Node*);
-void   bitstore(Node*, Node*, Node*, Node*, Node*);
-int32  outstring(char*, int32);
-int    mulcon(Node*, Node*);
-Multab*        mulcon0(Node*, int32);
-int    mulcon1(Node*, int32, Node*);
-void   nullwarn(Node*, Node*);
-void   sextern(Sym*, Node*, int32, int32);
-void   gextern(Sym*, Node*, int32, int32);
-void   outcode(void);
-
-/*
- * list
- */
-void   listinit(void);
-int    Pconv(Fmt*);
-int    Aconv(Fmt*);
-int    Dconv(Fmt*);
-int    Sconv(Fmt*);
-int    Nconv(Fmt*);
-int    Bconv(Fmt*);
-
-/*
- * reg.c
- */
-Reg*   rega(void);
-int    rcmp(const void*, const void*);
-void   regopt(Prog*);
-void   addmove(Reg*, int, int, int);
-Bits   mkvar(Addr*, int);
-void   prop(Reg*, Bits, Bits);
-void   loopit(Reg*, int32);
-void   synch(Reg*, Bits);
-uint32 allreg(uint32, Rgn*);
-void   paint1(Reg*, int);
-uint32 paint2(Reg*, int);
-void   paint3(Reg*, int, int32, int);
-void   addreg(Addr*, int);
-
-/*
- * peep.c
- */
-void   peep(void);
-void   excise(Reg*);
-Reg*   uniqp(Reg*);
-Reg*   uniqs(Reg*);
-int    regtyp(Addr*);
-int    regzer(Addr*);
-int    anyvar(Addr*);
-int    subprop(Reg*);
-int    copyprop(Reg*);
-int    copy1(Addr*, Addr*, Reg*, int);
-int    copyu(Prog*, Addr*, Addr*);
-
-int    copyas(Addr*, Addr*);
-int    copyau(Addr*, Addr*);
-int    copyau1(Prog*, Addr*);
-int    copysub(Addr*, Addr*, Addr*, int);
-int    copysub1(Prog*, Addr*, Addr*, int);
-
-int32  RtoB(int);
-int32  FtoB(int);
-int    BtoR(int32);
-int    BtoF(int32);
-
-/*
- * com64.c
- */
-int    com64(Node*);
-void   com64init(void);
-void   bool64(Node*);
-
-#pragma        varargck        type    "A"     int
-#pragma        varargck        type    "B"     Bits
-#pragma        varargck        type    "D"     Addr*
-#pragma        varargck        type    "N"     Addr*
-#pragma        varargck        type    "P"     Prog*
-#pragma        varargck        type    "S"     char*
diff --git a/src/cmd/9c/list.c b/src/cmd/9c/list.c
deleted file mode 100644 (file)
index 5cfc442..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-// cmd/9c/list.c from Vita Nuova.
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2008 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#define EXTERN
-#include "gc.h"
-
-void
-listinit(void)
-{
-       listinit9();
-}
diff --git a/src/cmd/9c/machcap.c b/src/cmd/9c/machcap.c
deleted file mode 100644 (file)
index af44bc8..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-// cmd/9c/machcap.c from Vita Nuova.
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2008 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-int
-machcap(Node *n)
-{
-
-       if(n == Z)
-               return 1;       /* test */
-
-       switch(n->op) {
-       case OMUL:
-       case OLMUL:
-       case OASMUL:
-       case OASLMUL:
-               if(typechlv[n->type->etype])
-                       return 1;
-               break;
-
-       case OADD:
-       case OAND:
-       case OOR:
-       case OSUB:
-       case OXOR:
-       case OASHL:
-       case OLSHR:
-       case OASHR:
-               if(typechlv[n->left->type->etype])
-                       return 1;
-               break;
-
-       case OCAST:
-               return 1;
-
-       case OCOND:
-       case OCOMMA:
-       case OLIST:
-       case OANDAND:
-       case OOROR:
-       case ONOT:
-               return 1;
-
-       case OASADD:
-       case OASSUB:
-       case OASAND:
-       case OASOR:
-       case OASXOR:
-               return 1;
-
-       case OASASHL:
-       case OASASHR:
-       case OASLSHR:
-               return 1;
-
-       case OPOSTINC:
-       case OPOSTDEC:
-       case OPREINC:
-       case OPREDEC:
-               return 1;
-
-       case OEQ:
-       case ONE:
-       case OLE:
-       case OGT:
-       case OLT:
-       case OGE:
-       case OHI:
-       case OHS:
-       case OLO:
-       case OLS:
-               return 1;
-       case ONEG:
-       case OCOM:
-               break;
-       }
-       return 0;
-}
diff --git a/src/cmd/9c/mul.c b/src/cmd/9c/mul.c
deleted file mode 100644 (file)
index 353376f..0000000
+++ /dev/null
@@ -1,638 +0,0 @@
-// cmd/9c/mul.c from Vita Nuova.
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2008 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-/*
- * code sequences for multiply by constant.
- * [a-l][0-3]
- *     lsl     $(A-'a'),r0,r1
- * [+][0-7]
- *     add     r0,r1,r2
- * [-][0-7]
- *     sub     r0,r1,r2
- */
-
-static int     multabp;
-static int32   mulval;
-static char*   mulcp;
-static int32   valmax;
-static int     shmax;
-
-static int     docode(char *hp, char *cp, int r0, int r1);
-static int     gen1(int len);
-static int     gen2(int len, int32 r1);
-static int     gen3(int len, int32 r0, int32 r1, int flag);
-enum
-{
-       SR1     = 1<<0,         /* r1 has been shifted */
-       SR0     = 1<<1,         /* r0 has been shifted */
-       UR1     = 1<<2,         /* r1 has not been used */
-       UR0     = 1<<3,         /* r0 has not been used */
-};
-
-Multab*
-mulcon0(Node *n, int32 v)
-{
-       int a1, a2, g;
-       Multab *m, *m1;
-       char hint[10];
-
-       if(v < 0)
-               v = -v;
-
-       /*
-        * look in cache
-        */
-       m = multab;
-       for(g=0; g<nelem(multab); g++) {
-               if(m->val == v) {
-                       if(m->code[0] == 0)
-                               return 0;
-                       return m;
-               }
-               m++;
-       }
-
-       /*
-        * select a spot in cache to overwrite
-        */
-       multabp++;
-       if(multabp < 0 || multabp >= nelem(multab))
-               multabp = 0;
-       m = multab+multabp;
-       m->val = v;
-       mulval = v;
-
-       /*
-        * look in execption hint table
-        */
-       a1 = 0;
-       a2 = hintabsize;
-       for(;;) {
-               if(a1 >= a2)
-                       goto no;
-               g = (a2 + a1)/2;
-               if(v < hintab[g].val) {
-                       a2 = g;
-                       continue;
-               }
-               if(v > hintab[g].val) {
-                       a1 = g+1;
-                       continue;
-               }
-               break;
-       }
-
-       if(docode(hintab[g].hint, m->code, 1, 0))
-               return m;
-       print("%L: multiply table failure %ld\n", n->lineno, v);
-       m->code[0] = 0;
-       return 0;
-
-no:
-       /*
-        * try to search
-        */
-       hint[0] = 0;
-       for(g=1; g<=6; g++) {
-               if(g >= 6 && v >= 65535)
-                       break;
-               mulcp = hint+g;
-               *mulcp = 0;
-               if(gen1(g)) {
-                       if(docode(hint, m->code, 1, 0))
-                               return m;
-                       print("%L: multiply table failure (g=%d h=%s) %ld\n",
-                               n->lineno, g, hint, v);
-                       break;
-               }
-       }
-
-       /*
-        * try a recur followed by a shift
-        */
-       g = 0;
-       while(!(v & 1)) {
-               g++;
-               v >>= 1;
-       }
-       if(g) {
-               m1 = mulcon0(n, v);
-               if(m1) {
-                       strcpy(m->code, m1->code);
-                       sprint(strchr(m->code, 0), "%c0", g+'a');
-                       return m;
-               }
-       }
-       m->code[0] = 0;
-       return 0;
-}
-
-static int
-docode(char *hp, char *cp, int r0, int r1)
-{
-       int c, i;
-
-       c = *hp++;
-       *cp = c;
-       cp += 2;
-       switch(c) {
-       default:
-               c -= 'a';
-               if(c < 1 || c >= 30)
-                       break;
-               for(i=0; i<4; i++) {
-                       switch(i) {
-                       case 0:
-                               if(docode(hp, cp, r0<<c, r1))
-                                       goto out;
-                               break;
-                       case 1:
-                               if(docode(hp, cp, r1<<c, r1))
-                                       goto out;
-                               break;
-                       case 2:
-                               if(docode(hp, cp, r0, r0<<c))
-                                       goto out;
-                               break;
-                       case 3:
-                               if(docode(hp, cp, r0, r1<<c))
-                                       goto out;
-                               break;
-                       }
-               }
-               break;
-
-       case '+':
-               for(i=0; i<8; i++) {
-                       cp[-1] = i+'0';
-                       switch(i) {
-                       case 1:
-                               if(docode(hp, cp, r0+r1, r1))
-                                       goto out;
-                               break;
-                       case 5:
-                               if(docode(hp, cp, r0, r0+r1))
-                                       goto out;
-                               break;
-                       }
-               }
-               break;
-
-       case '-':
-               for(i=0; i<8; i++) {
-                       cp[-1] = i+'0';
-                       switch(i) {
-                       case 1:
-                               if(docode(hp, cp, r0-r1, r1))
-                                       goto out;
-                               break;
-                       case 2:
-                               if(docode(hp, cp, r1-r0, r1))
-                                       goto out;
-                               break;
-                       case 5:
-                               if(docode(hp, cp, r0, r0-r1))
-                                       goto out;
-                               break;
-                       case 6:
-                               if(docode(hp, cp, r0, r1-r0))
-                                       goto out;
-                               break;
-                       }
-               }
-               break;
-
-       case 0:
-               if(r0 == mulval)
-                       return 1;
-       }
-       return 0;
-
-out:
-       cp[-1] = i+'0';
-       return 1;
-}
-
-static int
-gen1(int len)
-{
-       int i;
-
-       for(shmax=1; shmax<30; shmax++) {
-               valmax = 1<<shmax;
-               if(valmax >= mulval)
-                       break;
-       }
-       if(mulval == 1)
-               return 1;
-
-       len--;
-       for(i=1; i<=shmax; i++)
-               if(gen2(len, 1<<i)) {
-                       *--mulcp = 'a'+i;
-                       return 1;
-               }
-       return 0;
-}
-
-static int
-gen2(int len, int32 r1)
-{
-       int i;
-
-       if(len <= 0) {
-               if(r1 == mulval)
-                       return 1;
-               return 0;
-       }
-
-       len--;
-       if(len == 0)
-               goto calcr0;
-
-       if(gen3(len, r1, r1+1, UR1)) {
-               i = '+';
-               goto out;
-       }
-       if(gen3(len, r1-1, r1, UR0)) {
-               i = '-';
-               goto out;
-       }
-       if(gen3(len, 1, r1+1, UR1)) {
-               i = '+';
-               goto out;
-       }
-       if(gen3(len, 1, r1-1, UR1)) {
-               i = '-';
-               goto out;
-       }
-
-       return 0;
-
-calcr0:
-       if(mulval == r1+1) {
-               i = '+';
-               goto out;
-       }
-       if(mulval == r1-1) {
-               i = '-';
-               goto out;
-       }
-       return 0;
-
-out:
-       *--mulcp = i;
-       return 1;
-}
-
-static int
-gen3(int len, int32 r0, int32 r1, int flag)
-{
-       int i, f1, f2;
-       int32 x;
-
-       if(r0 <= 0 ||
-          r0 >= r1 ||
-          r1 > valmax)
-               return 0;
-
-       len--;
-       if(len == 0)
-               goto calcr0;
-
-       if(!(flag & UR1)) {
-               f1 = UR1|SR1;
-               for(i=1; i<=shmax; i++) {
-                       x = r0<<i;
-                       if(x > valmax)
-                               break;
-                       if(gen3(len, r0, x, f1)) {
-                               i += 'a';
-                               goto out;
-                       }
-               }
-       }
-
-       if(!(flag & UR0)) {
-               f1 = UR1|SR1;
-               for(i=1; i<=shmax; i++) {
-                       x = r1<<i;
-                       if(x > valmax)
-                               break;
-                       if(gen3(len, r1, x, f1)) {
-                               i += 'a';
-                               goto out;
-                       }
-               }
-       }
-
-       if(!(flag & SR1)) {
-               f1 = UR1|SR1|(flag&UR0);
-               for(i=1; i<=shmax; i++) {
-                       x = r1<<i;
-                       if(x > valmax)
-                               break;
-                       if(gen3(len, r0, x, f1)) {
-                               i += 'a';
-                               goto out;
-                       }
-               }
-       }
-
-       if(!(flag & SR0)) {
-               f1 = UR0|SR0|(flag&(SR1|UR1));
-
-               f2 = UR1|SR1;
-               if(flag & UR1)
-                       f2 |= UR0;
-               if(flag & SR1)
-                       f2 |= SR0;
-
-               for(i=1; i<=shmax; i++) {
-                       x = r0<<i;
-                       if(x > valmax)
-                               break;
-                       if(x > r1) {
-                               if(gen3(len, r1, x, f2)) {
-                                       i += 'a';
-                                       goto out;
-                               }
-                       } else
-                               if(gen3(len, x, r1, f1)) {
-                                       i += 'a';
-                                       goto out;
-                               }
-               }
-       }
-
-       x = r1+r0;
-       if(gen3(len, r0, x, UR1)) {
-               i = '+';
-               goto out;
-       }
-
-       if(gen3(len, r1, x, UR1)) {
-               i = '+';
-               goto out;
-       }
-
-       x = r1-r0;
-       if(gen3(len, x, r1, UR0)) {
-               i = '-';
-               goto out;
-       }
-
-       if(x > r0) {
-               if(gen3(len, r0, x, UR1)) {
-                       i = '-';
-                       goto out;
-               }
-       } else
-               if(gen3(len, x, r0, UR0)) {
-                       i = '-';
-                       goto out;
-               }
-
-       return 0;
-
-calcr0:
-       f1 = flag & (UR0|UR1);
-       if(f1 == UR1) {
-               for(i=1; i<=shmax; i++) {
-                       x = r1<<i;
-                       if(x >= mulval) {
-                               if(x == mulval) {
-                                       i += 'a';
-                                       goto out;
-                               }
-                               break;
-                       }
-               }
-       }
-
-       if(mulval == r1+r0) {
-               i = '+';
-               goto out;
-       }
-       if(mulval == r1-r0) {
-               i = '-';
-               goto out;
-       }
-
-       return 0;
-
-out:
-       *--mulcp = i;
-       return 1;
-}
-
-/*
- * hint table has numbers that
- * the search algorithm fails on.
- * <1000:
- *     all numbers
- * <5000:
- *     Ã· by 5
- * <10000:
- *     Ã· by 50
- * <65536:
- *     Ã· by 250
- */
-Hintab hintab[] =
-{
-       683,    "b++d+e+",
-       687,    "b+e++e-",
-       691,    "b++d+e+",
-       731,    "b++d+e+",
-       811,    "b++d+i+",
-       821,    "b++e+e+",
-       843,    "b+d++e+",
-       851,    "b+f-+e-",
-       853,    "b++e+e+",
-       877,    "c++++g-",
-       933,    "b+c++g-",
-       981,    "c-+e-d+",
-       1375,   "b+c+b+h-",
-       1675,   "d+b++h+",
-       2425,   "c++f-e+",
-       2675,   "c+d++f-",
-       2750,   "b+d-b+h-",
-       2775,   "c-+g-e-",
-       3125,   "b++e+g+",
-       3275,   "b+c+g+e+",
-       3350,   "c++++i+",
-       3475,   "c-+e-f-",
-       3525,   "c-+d+g-",
-       3625,   "c-+e-j+",
-       3675,   "b+d+d+e+",
-       3725,   "b+d-+h+",
-       3925,   "b+d+f-d-",
-       4275,   "b+g++e+",
-       4325,   "b+h-+d+",
-       4425,   "b+b+g-j-",
-       4525,   "b+d-d+f+",
-       4675,   "c++d-g+",
-       4775,   "b+d+b+g-",
-       4825,   "c+c-+i-",
-       4850,   "c++++i-",
-       4925,   "b++e-g-",
-       4975,   "c+f++e-",
-       5500,   "b+g-c+d+",
-       6700,   "d+b++i+",
-       9700,   "d++++j-",
-       11000,  "b+f-c-h-",
-       11750,  "b+d+g+j-",
-       12500,  "b+c+e-k+",
-       13250,  "b+d+e-f+",
-       13750,  "b+h-c-d+",
-       14250,  "b+g-c+e-",
-       14500,  "c+f+j-d-",
-       14750,  "d-g--f+",
-       16750,  "b+e-d-n+",
-       17750,  "c+h-b+e+",
-       18250,  "d+b+h-d+",
-       18750,  "b+g-++f+",
-       19250,  "b+e+b+h+",
-       19750,  "b++h--f-",
-       20250,  "b+e-l-c+",
-       20750,  "c++bi+e-",
-       21250,  "b+i+l+c+",
-       22000,  "b+e+d-g-",
-       22250,  "b+d-h+k-",
-       22750,  "b+d-e-g+",
-       23250,  "b+c+h+e-",
-       23500,  "b+g-c-g-",
-       23750,  "b+g-b+h-",
-       24250,  "c++g+m-",
-       24750,  "b+e+e+j-",
-       25000,  "b++dh+g+",
-       25250,  "b+e+d-g-",
-       25750,  "b+e+b+j+",
-       26250,  "b+h+c+e+",
-       26500,  "b+h+c+g+",
-       26750,  "b+d+e+g-",
-       27250,  "b+e+e+f+",
-       27500,  "c-i-c-d+",
-       27750,  "b+bd++j+",
-       28250,  "d-d-++i-",
-       28500,  "c+c-h-e-",
-       29000,  "b+g-d-f+",
-       29500,  "c+h+++e-",
-       29750,  "b+g+f-c+",
-       30250,  "b+f-g-c+",
-       33500,  "c-f-d-n+",
-       33750,  "b+d-b+j-",
-       34250,  "c+e+++i+",
-       35250,  "e+b+d+k+",
-       35500,  "c+e+d-g-",
-       35750,  "c+i-++e+",
-       36250,  "b+bh-d+e+",
-       36500,  "c+c-h-e-",
-       36750,  "d+e--i+",
-       37250,  "b+g+g+b+",
-       37500,  "b+h-b+f+",
-       37750,  "c+be++j-",
-       38500,  "b+e+b+i+",
-       38750,  "d+i-b+d+",
-       39250,  "b+g-l-+d+",
-       39500,  "b+g-c+g-",
-       39750,  "b+bh-c+f-",
-       40250,  "b+bf+d+g-",
-       40500,  "b+g-c+g+",
-       40750,  "c+b+i-e+",
-       41250,  "d++bf+h+",
-       41500,  "b+j+c+d-",
-       41750,  "c+f+b+h-",
-       42500,  "c+h++g+",
-       42750,  "b+g+d-f-",
-       43250,  "b+l-e+d-",
-       43750,  "c+bd+h+f-",
-       44000,  "b+f+g-d-",
-       44250,  "b+d-g--f+",
-       44500,  "c+e+c+h+",
-       44750,  "b+e+d-h-",
-       45250,  "b++g+j-g+",
-       45500,  "c+d+e-g+",
-       45750,  "b+d-h-e-",
-       46250,  "c+bd++j+",
-       46500,  "b+d-c-j-",
-       46750,  "e-e-b+g-",
-       47000,  "b+c+d-j-",
-       47250,  "b+e+e-g-",
-       47500,  "b+g-c-h-",
-       47750,  "b+f-c+h-",
-       48250,  "d--h+n-",
-       48500,  "b+c-g+m-",
-       48750,  "b+e+e-g+",
-       49500,  "c-f+e+j-",
-       49750,  "c+c+g++f-",
-       50000,  "b+e+e+k+",
-       50250,  "b++i++g+",
-       50500,  "c+g+f-i+",
-       50750,  "b+e+d+k-",
-       51500,  "b+i+c-f+",
-       51750,  "b+bd+g-e-",
-       52250,  "b+d+g-j+",
-       52500,  "c+c+f+g+",
-       52750,  "b+c+e+i+",
-       53000,  "b+i+c+g+",
-       53500,  "c+g+g-n+",
-       53750,  "b+j+d-c+",
-       54250,  "b+d-g-j-",
-       54500,  "c-f+e+f+",
-       54750,  "b+f-+c+g+",
-       55000,  "b+g-d-g-",
-       55250,  "b+e+e+g+",
-       55500,  "b+cd++j+",
-       55750,  "b+bh-d-f-",
-       56250,  "c+d-b+j-",
-       56500,  "c+d+c+i+",
-       56750,  "b+e+d++h-",
-       57000,  "b+d+g-f+",
-       57250,  "b+f-m+d-",
-       57750,  "b+i+c+e-",
-       58000,  "b+e+d+h+",
-       58250,  "c+b+g+g+",
-       58750,  "d-e-j--e+",
-       59000,  "d-i-+e+",
-       59250,  "e--h-m+",
-       59500,  "c+c-h+f-",
-       59750,  "b+bh-e+i-",
-       60250,  "b+bh-e-e-",
-       60500,  "c+c-g-g-",
-       60750,  "b+e-l-e-",
-       61250,  "b+g-g-c+",
-       61750,  "b+g-c+g+",
-       62250,  "f--+c-i-",
-       62750,  "e+f--+g+",
-       64750,  "b+f+d+p-",
-};
-int    hintabsize      = nelem(hintab);
diff --git a/src/cmd/9c/peep.c b/src/cmd/9c/peep.c
deleted file mode 100644 (file)
index 2e8e2ad..0000000
+++ /dev/null
@@ -1,1076 +0,0 @@
-// cmd/9c/peep.c from Vita Nuova.
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2008 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-/*
-static Reg*
-rnops(Reg *r)
-{
-       Prog *p;
-       Reg *r1;
-
-       if(r != R)
-       for(;;){
-               p = r->prog;
-               if(p->as != ANOP || p->from.type != D_NONE || p->to.type != D_NONE)
-                       break;
-               r1 = uniqs(r);
-               if(r1 == R)
-                       break;
-               r = r1;
-       }
-       return r;
-}
-*/
-
-void
-peep(void)
-{
-       Reg *r, *r1, *r2;
-       Prog *p, *p1;
-       int t;
-/*
- * complete R structure
- */
-       t = 0;
-       for(r=firstr; r!=R; r=r1) {
-               r1 = r->link;
-               if(r1 == R)
-                       break;
-               p = r->prog->link;
-               while(p != r1->prog)
-               switch(p->as) {
-               default:
-                       r2 = rega();
-                       r->link = r2;
-                       r2->link = r1;
-
-                       r2->prog = p;
-                       r2->p1 = r;
-                       r->s1 = r2;
-                       r2->s1 = r1;
-                       r1->p1 = r2;
-
-                       r = r2;
-                       t++;
-
-               case ADATA:
-               case AGLOBL:
-               case ANAME:
-               case ASIGNAME:
-                       p = p->link;
-               }
-       }
-
-loop1:
-       t = 0;
-       for(r=firstr; r!=R; r=r->link) {
-               p = r->prog;
-               if(p->as == AMOVW || p->as == AMOVD || p->as == AFMOVS || p->as == AFMOVD)
-               if(regtyp(&p->to)) {
-                       if(regtyp(&p->from))
-                       if(p->from.type == p->to.type) {
-                               if(copyprop(r)) {
-                                       excise(r);
-                                       t++;
-                               } else
-                               if(subprop(r) && copyprop(r)) {
-                                       excise(r);
-                                       t++;
-                               }
-                       }
-                       if(regzer(&p->from))
-                       if(p->to.type == D_REG) {
-                               p->from.type = D_REG;
-                               p->from.reg = REGZERO;
-                               if(copyprop(r)) {
-                                       excise(r);
-                                       t++;
-                               } else
-                               if(subprop(r) && copyprop(r)) {
-                                       excise(r);
-                                       t++;
-                               }
-                       }
-               }
-       }
-       if(t)
-               goto loop1;
-       /*
-        * look for MOVB x,R; MOVB R,R
-        */
-       for(r=firstr; r!=R; r=r->link) {
-               p = r->prog;
-               switch(p->as) {
-               default:
-                       continue;
-               case AMOVH:
-               case AMOVHZ:
-               case AMOVB:
-               case AMOVBZ:
-               case AMOVW:
-               case AMOVWZ:
-                       if(p->to.type != D_REG)
-                               continue;
-                       break;
-               }
-               r1 = r->link;
-               if(r1 == R)
-                       continue;
-               p1 = r1->prog;
-               if(p1->as != p->as)
-                       continue;
-               if(p1->from.type != D_REG || p1->from.reg != p->to.reg)
-                       continue;
-               if(p1->to.type != D_REG || p1->to.reg != p->to.reg)
-                       continue;
-               excise(r1);
-       }
-
-       if(debug['D'] > 1)
-               return; /* allow following code improvement to be suppressed */
-
-       /*
-        * look for OP x,y,R; CMP R, $0 -> OPCC x,y,R
-        * when OP can set condition codes correctly
-        */
-       for(r=firstr; r!=R; r=r->link) {
-               p = r->prog;
-               switch(p->as) {
-               case ACMP:
-               case ACMPW:             /* always safe? */
-                       if(!regzer(&p->to))
-                               continue;
-                       r1 = r->s1;
-                       if(r1 == R)
-                               continue;
-                       switch(r1->prog->as) {
-                       default:
-                               continue;
-                       case ABCL:
-                       case ABC:
-                               /* the conditions can be complex and these are currently little used */
-                               continue;
-                       case ABEQ:
-                       case ABGE:
-                       case ABGT:
-                       case ABLE:
-                       case ABLT:
-                       case ABNE:
-                       case ABVC:
-                       case ABVS:
-                               break;
-                       }
-                       r1 = r;
-                       do
-                               r1 = uniqp(r1);
-                       while (r1 != R && r1->prog->as == ANOP);
-                       if(r1 == R)
-                               continue;
-                       p1 = r1->prog;
-                       if(p1->to.type != D_REG || p1->to.reg != p->from.reg)
-                               continue;
-                       switch(p1->as) {
-                       case ASUB:
-                       case AADD:
-                       case AXOR:
-                       case AOR:
-                               /* irregular instructions */
-                               if(p1->from.type == D_CONST)
-                                       continue;
-                               break;
-                       }
-                       switch(p1->as) {
-                       default:
-                               continue;
-                       case AMOVW:
-                       case AMOVD:
-                               if(p1->from.type != D_REG)
-                                       continue;
-                               continue;
-                       case AANDCC:
-                       case AANDNCC:
-                       case AORCC:
-                       case AORNCC:
-                       case AXORCC:
-                       case ASUBCC:
-                       case ASUBECC:
-                       case ASUBMECC:
-                       case ASUBZECC:
-                       case AADDCC:
-                       case AADDCCC:
-                       case AADDECC:
-                       case AADDMECC:
-                       case AADDZECC:
-                       case ARLWMICC:
-                       case ARLWNMCC:
-                               t = p1->as;
-                               break;
-                       /* don't deal with floating point instructions for now */
-/*
-                       case AFABS:     t = AFABSCC; break;
-                       case AFADD:     t = AFADDCC; break;
-                       case AFADDS:    t = AFADDSCC; break;
-                       case AFCTIW:    t = AFCTIWCC; break;
-                       case AFCTIWZ:   t = AFCTIWZCC; break;
-                       case AFDIV:     t = AFDIVCC; break;
-                       case AFDIVS:    t = AFDIVSCC; break;
-                       case AFMADD:    t = AFMADDCC; break;
-                       case AFMADDS:   t = AFMADDSCC; break;
-                       case AFMOVD:    t = AFMOVDCC; break;
-                       case AFMSUB:    t = AFMSUBCC; break;
-                       case AFMSUBS:   t = AFMSUBSCC; break;
-                       case AFMUL:     t = AFMULCC; break;
-                       case AFMULS:    t = AFMULSCC; break;
-                       case AFNABS:    t = AFNABSCC; break;
-                       case AFNEG:     t = AFNEGCC; break;
-                       case AFNMADD:   t = AFNMADDCC; break;
-                       case AFNMADDS:  t = AFNMADDSCC; break;
-                       case AFNMSUB:   t = AFNMSUBCC; break;
-                       case AFNMSUBS:  t = AFNMSUBSCC; break;
-                       case AFRSP:     t = AFRSPCC; break;
-                       case AFSUB:     t = AFSUBCC; break;
-                       case AFSUBS:    t = AFSUBSCC; break;
-                       case ACNTLZW:   t = ACNTLZWCC; break;
-                       case AMTFSB0:   t = AMTFSB0CC; break;
-                       case AMTFSB1:   t = AMTFSB1CC; break;
-*/
-                       case AADD:      t = AADDCC; break;
-                       case AADDV:     t = AADDVCC; break;
-                       case AADDC:     t = AADDCCC; break;
-                       case AADDCV:    t = AADDCVCC; break;
-                       case AADDME:    t = AADDMECC; break;
-                       case AADDMEV:   t = AADDMEVCC; break;
-                       case AADDE:     t = AADDECC; break;
-                       case AADDEV:    t = AADDEVCC; break;
-                       case AADDZE:    t = AADDZECC; break;
-                       case AADDZEV:   t = AADDZEVCC; break;
-                       case AAND:      t = AANDCC; break;
-                       case AANDN:     t = AANDNCC; break;
-                       case ADIVW:     t = ADIVWCC; break;
-                       case ADIVWV:    t = ADIVWVCC; break;
-                       case ADIVWU:    t = ADIVWUCC; break;
-                       case ADIVWUV:   t = ADIVWUVCC; break;
-                       case ADIVD:     t = ADIVDCC; break;
-                       case ADIVDV:    t = ADIVDVCC; break;
-                       case ADIVDU:    t = ADIVDUCC; break;
-                       case ADIVDUV:   t = ADIVDUVCC; break;
-                       case AEQV:      t = AEQVCC; break;
-                       case AEXTSB:    t = AEXTSBCC; break;
-                       case AEXTSH:    t = AEXTSHCC; break;
-                       case AEXTSW:    t = AEXTSWCC; break;
-                       case AMULHW:    t = AMULHWCC; break;
-                       case AMULHWU:   t = AMULHWUCC; break;
-                       case AMULLW:    t = AMULLWCC; break;
-                       case AMULLWV:   t = AMULLWVCC; break;
-                       case AMULHD:    t = AMULHDCC; break;
-                       case AMULHDU:   t = AMULHDUCC; break;
-                       case AMULLD:    t = AMULLDCC; break;
-                       case AMULLDV:   t = AMULLDVCC; break;
-                       case ANAND:     t = ANANDCC; break;
-                       case ANEG:      t = ANEGCC; break;
-                       case ANEGV:     t = ANEGVCC; break;
-                       case ANOR:      t = ANORCC; break;
-                       case AOR:       t = AORCC; break;
-                       case AORN:      t = AORNCC; break;
-                       case AREM:      t = AREMCC; break;
-                       case AREMV:     t = AREMVCC; break;
-                       case AREMU:     t = AREMUCC; break;
-                       case AREMUV:    t = AREMUVCC; break;
-                       case AREMD:     t = AREMDCC; break;
-                       case AREMDV:    t = AREMDVCC; break;
-                       case AREMDU:    t = AREMDUCC; break;
-                       case AREMDUV:   t = AREMDUVCC; break;
-                       case ARLWMI:    t = ARLWMICC; break;
-                       case ARLWNM:    t = ARLWNMCC; break;
-                       case ASLW:      t = ASLWCC; break;
-                       case ASRAW:     t = ASRAWCC; break;
-                       case ASRW:      t = ASRWCC; break;
-                       case ASLD:      t = ASLDCC; break;
-                       case ASRAD:     t = ASRADCC; break;
-                       case ASRD:      t = ASRDCC; break;
-                       case ASUB:      t = ASUBCC; break;
-                       case ASUBV:     t = ASUBVCC; break;
-                       case ASUBC:     t = ASUBCCC; break;
-                       case ASUBCV:    t = ASUBCVCC; break;
-                       case ASUBME:    t = ASUBMECC; break;
-                       case ASUBMEV:   t = ASUBMEVCC; break;
-                       case ASUBE:     t = ASUBECC; break;
-                       case ASUBEV:    t = ASUBEVCC; break;
-                       case ASUBZE:    t = ASUBZECC; break;
-                       case ASUBZEV:   t = ASUBZEVCC; break;
-                       case AXOR:      t = AXORCC; break;
-                               break;
-                       }
-                       if(debug['D'])
-                               print("cmp %P; %P -> ", p1, p);
-                       p1->as = t;
-                       if(debug['D'])
-                               print("%P\n", p1);
-                       excise(r);
-                       continue;
-               }
-       }
-}
-
-void
-excise(Reg *r)
-{
-       Prog *p;
-
-       p = r->prog;
-       p->as = ANOP;
-       p->from = zprog.from;
-       p->from3 = zprog.from3;
-       p->to = zprog.to;
-       p->reg = zprog.reg; /**/
-}
-
-Reg*
-uniqp(Reg *r)
-{
-       Reg *r1;
-
-       r1 = r->p1;
-       if(r1 == R) {
-               r1 = r->p2;
-               if(r1 == R || r1->p2link != R)
-                       return R;
-       } else
-               if(r->p2 != R)
-                       return R;
-       return r1;
-}
-
-Reg*
-uniqs(Reg *r)
-{
-       Reg *r1;
-
-       r1 = r->s1;
-       if(r1 == R) {
-               r1 = r->s2;
-               if(r1 == R)
-                       return R;
-       } else
-               if(r->s2 != R)
-                       return R;
-       return r1;
-}
-
-/*
- * if the system forces R0 to be zero,
- * convert references to $0 to references to R0.
- */
-int
-regzer(Addr *a)
-{
-       if(R0ISZERO) {
-               if(a->type == D_CONST)
-                       if(a->sym == nil)
-                               if(a->offset == 0)
-                                       return 1;
-               if(a->type == D_REG)
-                       if(a->reg == REGZERO)
-                               return 1;
-       }
-       return 0;
-}
-
-int
-regtyp(Addr *a)
-{
-
-       if(a->type == D_REG) {
-               if(!R0ISZERO || a->reg != REGZERO)
-                       return 1;
-               return 0;
-       }
-       if(a->type == D_FREG)
-               return 1;
-       return 0;
-}
-
-/*
- * the idea is to substitute
- * one register for another
- * from one MOV to another
- *     MOV     a, R0
- *     ADD     b, R0   / no use of R1
- *     MOV     R0, R1
- * would be converted to
- *     MOV     a, R1
- *     ADD     b, R1
- *     MOV     R1, R0
- * hopefully, then the former or latter MOV
- * will be eliminated by copy propagation.
- */
-int
-subprop(Reg *r0)
-{
-       Prog *p;
-       Addr *v1, *v2;
-       Reg *r;
-       int t;
-
-       p = r0->prog;
-       v1 = &p->from;
-       if(!regtyp(v1))
-               return 0;
-       v2 = &p->to;
-       if(!regtyp(v2))
-               return 0;
-       for(r=uniqp(r0); r!=R; r=uniqp(r)) {
-               if(uniqs(r) == R)
-                       break;
-               p = r->prog;
-               switch(p->as) {
-               case ABL:
-                       return 0;
-
-               case AADD:
-               case AADDC:
-               case AADDCC:
-               case AADDE:
-               case AADDECC:
-               case ASUB:
-               case ASUBCC:
-               case ASUBC:
-               case ASUBCCC:
-               case ASUBE:
-               case ASUBECC:
-               case ASLW:
-               case ASRW:
-               case ASRWCC:
-               case ASRAW:
-               case ASRAWCC:
-               case ASLD:
-               case ASRD:
-               case ASRAD:
-               case AOR:
-               case AORCC:
-               case AORN:
-               case AORNCC:
-               case AAND:
-               case AANDCC:
-               case AANDN:
-               case AANDNCC:
-               case ANAND:
-               case ANANDCC:
-               case ANOR:
-               case ANORCC:
-               case AXOR:
-               case AXORCC:
-               case AMULHW:
-               case AMULHWU:
-               case AMULLW:
-               case AMULLD:
-               case ADIVW:
-               case ADIVWU:
-               case ADIVD:
-               case ADIVDU:
-               case AREM:
-               case AREMU:
-               case AREMD:
-               case AREMDU:
-               case ARLWNM:
-               case ARLWNMCC:
-
-               case AFADD:
-               case AFADDS:
-               case AFSUB:
-               case AFSUBS:
-               case AFMUL:
-               case AFMULS:
-               case AFDIV:
-               case AFDIVS:
-                       if(p->to.type == v1->type)
-                       if(p->to.reg == v1->reg) {
-                               if(p->reg == NREG)
-                                       p->reg = p->to.reg;
-                               goto gotit;
-                       }
-                       break;
-
-               case AADDME:
-               case AADDMECC:
-               case AADDZE:
-               case AADDZECC:
-               case ASUBME:
-               case ASUBMECC:
-               case ASUBZE:
-               case ASUBZECC:
-               case ANEG:
-               case ANEGCC:
-               case AFNEG:
-               case AFNEGCC:
-               case AFMOVS:
-               case AFMOVD:
-               case AMOVW:
-               case AMOVD:
-                       if(p->to.type == v1->type)
-                       if(p->to.reg == v1->reg)
-                               goto gotit;
-                       break;
-               }
-               if(copyau(&p->from, v2) ||
-                  copyau1(p, v2) ||
-                  copyau(&p->to, v2))
-                       break;
-               if(copysub(&p->from, v1, v2, 0) ||
-                  copysub1(p, v1, v2, 0) ||
-                  copysub(&p->to, v1, v2, 0))
-                       break;
-       }
-       return 0;
-
-gotit:
-       copysub(&p->to, v1, v2, 1);
-       if(debug['P']) {
-               print("gotit: %D->%D\n%P", v1, v2, r->prog);
-               if(p->from.type == v2->type)
-                       print(" excise");
-               print("\n");
-       }
-       for(r=uniqs(r); r!=r0; r=uniqs(r)) {
-               p = r->prog;
-               copysub(&p->from, v1, v2, 1);
-               copysub1(p, v1, v2, 1);
-               copysub(&p->to, v1, v2, 1);
-               if(debug['P'])
-                       print("%P\n", r->prog);
-       }
-       t = v1->reg;
-       v1->reg = v2->reg;
-       v2->reg = t;
-       if(debug['P'])
-               print("%P last\n", r->prog);
-       return 1;
-}
-
-/*
- * The idea is to remove redundant copies.
- *     v1->v2  F=0
- *     (use v2 s/v2/v1/)*
- *     set v1  F=1
- *     use v2  return fail
- *     -----------------
- *     v1->v2  F=0
- *     (use v2 s/v2/v1/)*
- *     set v1  F=1
- *     set v2  return success
- */
-int
-copyprop(Reg *r0)
-{
-       Prog *p;
-       Addr *v1, *v2;
-       Reg *r;
-
-       p = r0->prog;
-       v1 = &p->from;
-       v2 = &p->to;
-       if(copyas(v1, v2))
-               return 1;
-       for(r=firstr; r!=R; r=r->link)
-               r->active = 0;
-       return copy1(v1, v2, r0->s1, 0);
-}
-
-int
-copy1(Addr *v1, Addr *v2, Reg *r, int f)
-{
-       int t;
-       Prog *p;
-
-       if(r->active) {
-               if(debug['P'])
-                       print("act set; return 1\n");
-               return 1;
-       }
-       r->active = 1;
-       if(debug['P'])
-               print("copy %D->%D f=%d\n", v1, v2, f);
-       for(; r != R; r = r->s1) {
-               p = r->prog;
-               if(debug['P'])
-                       print("%P", p);
-               if(!f && uniqp(r) == R) {
-                       f = 1;
-                       if(debug['P'])
-                               print("; merge; f=%d", f);
-               }
-               t = copyu(p, v2, nil);
-               switch(t) {
-               case 2: /* rar, cant split */
-                       if(debug['P'])
-                               print("; %Drar; return 0\n", v2);
-                       return 0;
-
-               case 3: /* set */
-                       if(debug['P'])
-                               print("; %Dset; return 1\n", v2);
-                       return 1;
-
-               case 1: /* used, substitute */
-               case 4: /* use and set */
-                       if(f) {
-                               if(!debug['P'])
-                                       return 0;
-                               if(t == 4)
-                                       print("; %Dused+set and f=%d; return 0\n", v2, f);
-                               else
-                                       print("; %Dused and f=%d; return 0\n", v2, f);
-                               return 0;
-                       }
-                       if(copyu(p, v2, v1)) {
-                               if(debug['P'])
-                                       print("; sub fail; return 0\n");
-                               return 0;
-                       }
-                       if(debug['P'])
-                               print("; sub%D/%D", v2, v1);
-                       if(t == 4) {
-                               if(debug['P'])
-                                       print("; %Dused+set; return 1\n", v2);
-                               return 1;
-                       }
-                       break;
-               }
-               if(!f) {
-                       t = copyu(p, v1, nil);
-                       if(!f && (t == 2 || t == 3 || t == 4)) {
-                               f = 1;
-                               if(debug['P'])
-                                       print("; %Dset and !f; f=%d", v1, f);
-                       }
-               }
-               if(debug['P'])
-                       print("\n");
-               if(r->s2)
-                       if(!copy1(v1, v2, r->s2, f))
-                               return 0;
-       }
-       return 1;
-}
-
-/*
- * return
- * 1 if v only used (and substitute),
- * 2 if read-alter-rewrite
- * 3 if set
- * 4 if set and used
- * 0 otherwise (not touched)
- */
-int
-copyu(Prog *p, Addr *v, Addr *s)
-{
-
-       switch(p->as) {
-
-       default:
-               if(debug['P'])
-                       print(" (\?\?\?)");
-               return 2;
-
-
-       case ANOP:      /* read, write */
-       case AMOVH:
-       case AMOVHZ:
-       case AMOVB:
-       case AMOVBZ:
-       case AMOVW:
-       case AMOVWZ:
-       case AMOVD:
-
-       case ANEG:
-       case ANEGCC:
-       case AADDME:
-       case AADDMECC:
-       case AADDZE:
-       case AADDZECC:
-       case ASUBME:
-       case ASUBMECC:
-       case ASUBZE:
-       case ASUBZECC:
-
-       case AFCTIW:
-       case AFCTIWZ:
-       case AFMOVS:
-       case AFMOVD:
-       case AFRSP:
-       case AFNEG:
-       case AFNEGCC:
-               if(s != nil) {
-                       if(copysub(&p->from, v, s, 1))
-                               return 1;
-                       if(!copyas(&p->to, v))
-                               if(copysub(&p->to, v, s, 1))
-                                       return 1;
-                       return 0;
-               }
-               if(copyas(&p->to, v)) {
-                       if(copyau(&p->from, v))
-                               return 4;
-                       return 3;
-               }
-               if(copyau(&p->from, v))
-                       return 1;
-               if(copyau(&p->to, v))
-                       return 1;
-               return 0;
-
-       case ARLWMI:    /* read read rar */
-       case ARLWMICC:
-               if(copyas(&p->to, v))
-                       return 2;
-               /* fall through */
-
-       case AADD:      /* read read write */
-       case AADDC:
-       case AADDE:
-       case ASUB:
-       case ASLW:
-       case ASRW:
-       case ASRAW:
-       case ASLD:
-       case ASRD:
-       case ASRAD:
-       case AOR:
-       case AORCC:
-       case AORN:
-       case AORNCC:
-       case AAND:
-       case AANDCC:
-       case AANDN:
-       case AANDNCC:
-       case ANAND:
-       case ANANDCC:
-       case ANOR:
-       case ANORCC:
-       case AXOR:
-       case AMULHW:
-       case AMULHWU:
-       case AMULLW:
-       case AMULLD:
-       case ADIVW:
-       case ADIVD:
-       case ADIVWU:
-       case ADIVDU:
-       case AREM:
-       case AREMU:
-       case AREMD:
-       case AREMDU:
-       case ARLWNM:
-       case ARLWNMCC:
-
-       case AFADDS:
-       case AFADD:
-       case AFSUBS:
-       case AFSUB:
-       case AFMULS:
-       case AFMUL:
-       case AFDIVS:
-       case AFDIV:
-               if(s != nil) {
-                       if(copysub(&p->from, v, s, 1))
-                               return 1;
-                       if(copysub1(p, v, s, 1))
-                               return 1;
-                       if(!copyas(&p->to, v))
-                               if(copysub(&p->to, v, s, 1))
-                                       return 1;
-                       return 0;
-               }
-               if(copyas(&p->to, v)) {
-                       if(p->reg == NREG)
-                               p->reg = p->to.reg;
-                       if(copyau(&p->from, v))
-                               return 4;
-                       if(copyau1(p, v))
-                               return 4;
-                       return 3;
-               }
-               if(copyau(&p->from, v))
-                       return 1;
-               if(copyau1(p, v))
-                       return 1;
-               if(copyau(&p->to, v))
-                       return 1;
-               return 0;
-
-       case ABEQ:
-       case ABGT:
-       case ABGE:
-       case ABLT:
-       case ABLE:
-       case ABNE:
-       case ABVC:
-       case ABVS:
-               break;
-
-       case ACMP:      /* read read */
-       case ACMPU:
-       case ACMPW:
-       case ACMPWU:
-       case AFCMPO:
-       case AFCMPU:
-               if(s != nil) {
-                       if(copysub(&p->from, v, s, 1))
-                               return 1;
-                       return copysub(&p->to, v, s, 1);
-               }
-               if(copyau(&p->from, v))
-                       return 1;
-               if(copyau(&p->to, v))
-                       return 1;
-               break;
-
-       case ABR:       /* funny */
-               if(s != nil) {
-                       if(copysub(&p->to, v, s, 1))
-                               return 1;
-                       return 0;
-               }
-               if(copyau(&p->to, v))
-                       return 1;
-               return 0;
-
-       case ARETURN:   /* funny */
-               if(v->type == D_REG)
-                       if(v->reg == REGRET)
-                               return 2;
-               if(v->type == D_FREG)
-                       if(v->reg == FREGRET)
-                               return 2;
-
-       case ABL:       /* funny */
-               if(v->type == D_REG) {
-                       if(v->reg <= REGEXT && v->reg > exregoffset)
-                               return 2;
-                       if(v->reg == REGARG)
-                               return 2;
-               }
-               if(v->type == D_FREG) {
-                       if(v->reg <= FREGEXT && v->reg > exfregoffset)
-                               return 2;
-               }
-
-               if(s != nil) {
-                       if(copysub(&p->to, v, s, 1))
-                               return 1;
-                       return 0;
-               }
-               if(copyau(&p->to, v))
-                       return 4;
-               return 3;
-
-       case ATEXT:     /* funny */
-               if(v->type == D_REG)
-                       if(v->reg == REGARG)
-                               return 3;
-               return 0;
-       }
-       return 0;
-}
-
-int
-a2type(Prog *p)
-{
-
-       switch(p->as) {
-       case AADD:
-       case AADDC:
-       case AADDCC:
-       case AADDCCC:
-       case AADDE:
-       case AADDECC:
-       case AADDME:
-       case AADDMECC:
-       case AADDZE:
-       case AADDZECC:
-       case ASUB:
-       case ASUBC:
-       case ASUBCC:
-       case ASUBCCC:
-       case ASUBE:
-       case ASUBECC:
-       case ASUBME:
-       case ASUBMECC:
-       case ASUBZE:
-       case ASUBZECC:
-       case ASLW:
-       case ASLWCC:
-       case ASRW:
-       case ASRWCC:
-       case ASRAW:
-       case ASRAWCC:
-       case ASLD:
-       case ASLDCC:
-       case ASRD:
-       case ASRDCC:
-       case ASRAD:
-       case ASRADCC:
-       case AOR:
-       case AORCC:
-       case AORN:
-       case AORNCC:
-       case AAND:
-       case AANDCC:
-       case AANDN:
-       case AANDNCC:
-       case AXOR:
-       case AXORCC:
-       case ANEG:
-       case ANEGCC:
-       case AMULHW:
-       case AMULHWU:
-       case AMULLW:
-       case AMULLWCC:
-       case ADIVW:
-       case ADIVWCC:
-       case ADIVWU:
-       case ADIVWUCC:
-       case AREM:
-       case AREMCC:
-       case AREMU:
-       case AREMUCC:
-       case AMULLD:
-       case AMULLDCC:
-       case ADIVD:
-       case ADIVDCC:
-       case ADIVDU:
-       case ADIVDUCC:
-       case AREMD:
-       case AREMDCC:
-       case AREMDU:
-       case AREMDUCC:
-       case ANAND:
-       case ANANDCC:
-       case ANOR:
-       case ANORCC:
-       case ARLWMI:
-       case ARLWMICC:
-       case ARLWNM:
-       case ARLWNMCC:
-               return D_REG;
-
-       case AFADDS:
-       case AFADDSCC:
-       case AFADD:
-       case AFADDCC:
-       case AFSUBS:
-       case AFSUBSCC:
-       case AFSUB:
-       case AFSUBCC:
-       case AFMULS:
-       case AFMULSCC:
-       case AFMUL:
-       case AFMULCC:
-       case AFDIVS:
-       case AFDIVSCC:
-       case AFDIV:
-       case AFDIVCC:
-       case AFNEG:
-       case AFNEGCC:
-               return D_FREG;
-       }
-       return D_NONE;
-}
-
-/*
- * direct reference,
- * could be set/use depending on
- * semantics
- */
-int
-copyas(Addr *a, Addr *v)
-{
-
-       if(regtyp(v))
-               if(a->type == v->type)
-               if(a->reg == v->reg)
-                       return 1;
-       return 0;
-}
-
-/*
- * either direct or indirect
- */
-int
-copyau(Addr *a, Addr *v)
-{
-
-       if(copyas(a, v))
-               return 1;
-       if(v->type == D_REG)
-               if(a->type == D_OREG)
-                       if(v->reg == a->reg)
-                               return 1;
-       return 0;
-}
-
-int
-copyau1(Prog *p, Addr *v)
-{
-
-       if(regtyp(v))
-               if(p->from.type == v->type || p->to.type == v->type)
-               if(p->reg == v->reg) {
-                       if(a2type(p) != v->type)
-                               print("botch a2type %P\n", p);
-                       return 1;
-               }
-       return 0;
-}
-
-/*
- * substitute s for v in a
- * return failure to substitute
- */
-int
-copysub(Addr *a, Addr *v, Addr *s, int f)
-{
-
-       if(f)
-       if(copyau(a, v))
-               a->reg = s->reg;
-       return 0;
-}
-
-int
-copysub1(Prog *p1, Addr *v, Addr *s, int f)
-{
-
-       if(f)
-       if(copyau1(p1, v))
-               p1->reg = s->reg;
-       return 0;
-}
diff --git a/src/cmd/9c/reg.c b/src/cmd/9c/reg.c
deleted file mode 100644 (file)
index 81a7c7f..0000000
+++ /dev/null
@@ -1,1163 +0,0 @@
-// cmd/9c/reg.c from Vita Nuova.
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2008 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-Reg*
-rega(void)
-{
-       Reg *r;
-
-       r = freer;
-       if(r == R) {
-               r = alloc(sizeof(*r));
-       } else
-               freer = r->link;
-
-       *r = zreg;
-       return r;
-}
-
-int
-rcmp(const void *a1, const void *a2)
-{
-       const Rgn *p1, *p2;
-       int c1, c2;
-
-       p1 = a1;
-       p2 = a2;
-       c1 = p2->cost;
-       c2 = p1->cost;
-       if(c1 -= c2)
-               return c1;
-       return p2->varno - p1->varno;
-}
-
-void
-regopt(Prog *p)
-{
-       Reg *r, *r1, *r2;
-       Prog *p1;
-       int i, z;
-       int32 initpc, val, npc;
-       uint32 vreg;
-       Bits bit;
-       struct
-       {
-               int32   m;
-               int32   c;
-               Reg*    p;
-       } log5[6], *lp;
-
-       firstr = R;
-       lastr = R;
-       nvar = 0;
-       regbits = 0;
-       for(z=0; z<BITS; z++) {
-               externs.b[z] = 0;
-               params.b[z] = 0;
-               consts.b[z] = 0;
-               addrs.b[z] = 0;
-       }
-
-       /*
-        * pass 1
-        * build aux data structure
-        * allocate pcs
-        * find use and set of variables
-        */
-       val = 5L * 5L * 5L * 5L * 5L;
-       lp = log5;
-       for(i=0; i<5; i++) {
-               lp->m = val;
-               lp->c = 0;
-               lp->p = R;
-               val /= 5L;
-               lp++;
-       }
-       val = 0;
-       for(; p != P; p = p->link) {
-               switch(p->as) {
-               case ADATA:
-               case AGLOBL:
-               case ANAME:
-               case ASIGNAME:
-               case AFUNCDATA:
-                       continue;
-               }
-               r = rega();
-               if(firstr == R) {
-                       firstr = r;
-                       lastr = r;
-               } else {
-                       lastr->link = r;
-                       r->p1 = lastr;
-                       lastr->s1 = r;
-                       lastr = r;
-               }
-               r->prog = p;
-               r->pc = val;
-               val++;
-
-               lp = log5;
-               for(i=0; i<5; i++) {
-                       lp->c--;
-                       if(lp->c <= 0) {
-                               lp->c = lp->m;
-                               if(lp->p != R)
-                                       lp->p->log5 = r;
-                               lp->p = r;
-                               (lp+1)->c = 0;
-                               break;
-                       }
-                       lp++;
-               }
-
-               r1 = r->p1;
-               if(r1 != R)
-               switch(r1->prog->as) {
-               case ARETURN:
-               case ABR:
-               case ARFI:
-               case ARFCI:
-               case ARFID:
-                       r->p1 = R;
-                       r1->s1 = R;
-               }
-
-               /*
-                * left side always read
-                */
-               bit = mkvar(&p->from, p->as==AMOVW || p->as == AMOVWZ || p->as == AMOVD);
-               for(z=0; z<BITS; z++)
-                       r->use1.b[z] |= bit.b[z];
-
-               /*
-                * right side depends on opcode
-                */
-               bit = mkvar(&p->to, 0);
-               if(bany(&bit))
-               switch(p->as) {
-               default:
-                       diag(Z, "reg: unknown asop: %A", p->as);
-                       break;
-
-               /*
-                * right side write
-                */
-               case ANOP:
-               case AMOVB:
-               case AMOVBU:
-               case AMOVBZ:
-               case AMOVBZU:
-               case AMOVH:
-               case AMOVHBR:
-               case AMOVWBR:
-               case AMOVHU:
-               case AMOVHZ:
-               case AMOVHZU:
-               case AMOVW:
-               case AMOVWU:
-               case AMOVWZ:
-               case AMOVWZU:
-               case AMOVD:
-               case AMOVDU:
-               case AFMOVD:
-               case AFMOVDCC:
-               case AFMOVDU:
-               case AFMOVS:
-               case AFMOVSU:
-               case AFRSP:
-                       for(z=0; z<BITS; z++)
-                               r->set.b[z] |= bit.b[z];
-                       break;
-
-               /*
-                * funny
-                */
-               case ABL:
-                       for(z=0; z<BITS; z++)
-                               addrs.b[z] |= bit.b[z];
-                       break;
-               }
-       }
-       if(firstr == R)
-               return;
-       initpc = pc - val;
-       npc = val;
-
-       /*
-        * pass 2
-        * turn branch references to pointers
-        * build back pointers
-        */
-       for(r = firstr; r != R; r = r->link) {
-               p = r->prog;
-               if(p->to.type == D_BRANCH) {
-                       val = p->to.offset - initpc;
-                       r1 = firstr;
-                       while(r1 != R) {
-                               r2 = r1->log5;
-                               if(r2 != R && val >= r2->pc) {
-                                       r1 = r2;
-                                       continue;
-                               }
-                               if(r1->pc == val)
-                                       break;
-                               r1 = r1->link;
-                       }
-                       if(r1 == R) {
-                               nearln = p->lineno;
-                               diag(Z, "ref not found\n%P", p);
-                               continue;
-                       }
-                       if(r1 == r) {
-                               nearln = p->lineno;
-                               diag(Z, "ref to self\n%P", p);
-                               continue;
-                       }
-                       r->s2 = r1;
-                       r->p2link = r1->p2;
-                       r1->p2 = r;
-               }
-       }
-       if(debug['R']) {
-               p = firstr->prog;
-               print("\n%L %D\n", p->lineno, &p->from);
-       }
-
-       /*
-        * pass 2.5
-        * find looping structure
-        */
-       for(r = firstr; r != R; r = r->link)
-               r->active = 0;
-       change = 0;
-       loopit(firstr, npc);
-       if(debug['R'] && debug['v']) {
-               print("\nlooping structure:\n");
-               for(r = firstr; r != R; r = r->link) {
-                       print("%ld:%P", r->loop, r->prog);
-                       for(z=0; z<BITS; z++)
-                               bit.b[z] = r->use1.b[z] |
-                                       r->use2.b[z] | r->set.b[z];
-                       if(bany(&bit)) {
-                               print("\t");
-                               if(bany(&r->use1))
-                                       print(" u1=%B", r->use1);
-                               if(bany(&r->use2))
-                                       print(" u2=%B", r->use2);
-                               if(bany(&r->set))
-                                       print(" st=%B", r->set);
-                       }
-                       print("\n");
-               }
-       }
-
-       /*
-        * pass 3
-        * iterate propagating usage
-        *      back until flow graph is complete
-        */
-loop1:
-       change = 0;
-       for(r = firstr; r != R; r = r->link)
-               r->active = 0;
-       for(r = firstr; r != R; r = r->link)
-               if(r->prog->as == ARETURN)
-                       prop(r, zbits, zbits);
-loop11:
-       /* pick up unreachable code */
-       i = 0;
-       for(r = firstr; r != R; r = r1) {
-               r1 = r->link;
-               if(r1 && r1->active && !r->active) {
-                       prop(r, zbits, zbits);
-                       i = 1;
-               }
-       }
-       if(i)
-               goto loop11;
-       if(change)
-               goto loop1;
-
-
-       /*
-        * pass 4
-        * iterate propagating register/variable synchrony
-        *      forward until graph is complete
-        */
-loop2:
-       change = 0;
-       for(r = firstr; r != R; r = r->link)
-               r->active = 0;
-       synch(firstr, zbits);
-       if(change)
-               goto loop2;
-
-
-       /*
-        * pass 5
-        * isolate regions
-        * calculate costs (paint1)
-        */
-       r = firstr;
-       if(r) {
-               for(z=0; z<BITS; z++)
-                       bit.b[z] = (r->refahead.b[z] | r->calahead.b[z]) &
-                         ~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]);
-               if(bany(&bit)) {
-                       nearln = r->prog->lineno;
-                       warn(Z, "used and not set: %B", bit);
-                       if(debug['R'] && !debug['w'])
-                               print("used and not set: %B\n", bit);
-               }
-       }
-       if(debug['R'] && debug['v'])
-               print("\nprop structure:\n");
-       for(r = firstr; r != R; r = r->link)
-               r->act = zbits;
-       rgp = region;
-       nregion = 0;
-       for(r = firstr; r != R; r = r->link) {
-               if(debug['R'] && debug['v'])
-                       print("%P\n     set = %B; rah = %B; cal = %B\n",
-                               r->prog, r->set, r->refahead, r->calahead);
-               for(z=0; z<BITS; z++)
-                       bit.b[z] = r->set.b[z] &
-                         ~(r->refahead.b[z] | r->calahead.b[z] | addrs.b[z]);
-               if(bany(&bit)) {
-                       nearln = r->prog->lineno;
-                       warn(Z, "set and not used: %B", bit);
-                       if(debug['R'])
-                               print("set an not used: %B\n", bit);
-                       excise(r);
-               }
-               for(z=0; z<BITS; z++)
-                       bit.b[z] = LOAD(r) & ~(r->act.b[z] | addrs.b[z]);
-               while(bany(&bit)) {
-                       i = bnum(bit);
-                       rgp->enter = r;
-                       rgp->varno = i;
-                       change = 0;
-                       if(debug['R'] && debug['v'])
-                               print("\n");
-                       paint1(r, i);
-                       bit.b[i/32] &= ~(1L<<(i%32));
-                       if(change <= 0) {
-                               if(debug['R'])
-                                       print("%L$%d: %B\n",
-                                               r->prog->lineno, change, blsh(i));
-                               continue;
-                       }
-                       rgp->cost = change;
-                       nregion++;
-                       if(nregion >= NRGN)
-                               fatal(Z, "too many regions");
-                       rgp++;
-               }
-       }
-       qsort(region, nregion, sizeof(region[0]), rcmp);
-
-       /*
-        * pass 6
-        * determine used registers (paint2)
-        * replace code (paint3)
-        */
-       rgp = region;
-       for(i=0; i<nregion; i++) {
-               bit = blsh(rgp->varno);
-               vreg = paint2(rgp->enter, rgp->varno);
-               vreg = allreg(vreg, rgp);
-               if(debug['R']) {
-                       if(rgp->regno >= NREG)
-                               print("%L$%d F%d: %B\n",
-                                       rgp->enter->prog->lineno,
-                                       rgp->cost,
-                                       rgp->regno-NREG,
-                                       bit);
-                       else
-                               print("%L$%d R%d: %B\n",
-                                       rgp->enter->prog->lineno,
-                                       rgp->cost,
-                                       rgp->regno,
-                                       bit);
-               }
-               if(rgp->regno != 0)
-                       paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
-               rgp++;
-       }
-       /*
-        * pass 7
-        * peep-hole on basic block
-        */
-       if(!debug['R'] || debug['P'])
-               peep();
-
-       /*
-        * pass 8
-        * recalculate pc
-        */
-       val = initpc;
-       for(r = firstr; r != R; r = r1) {
-               r->pc = val;
-               p = r->prog;
-               p1 = P;
-               r1 = r->link;
-               if(r1 != R)
-                       p1 = r1->prog;
-               for(; p != p1; p = p->link) {
-                       switch(p->as) {
-                       default:
-                               val++;
-                               break;
-
-                       case ANOP:
-                       case ADATA:
-                       case AGLOBL:
-                       case ANAME:
-                       case ASIGNAME:
-                       case AFUNCDATA:
-                               break;
-                       }
-               }
-       }
-       pc = val;
-
-       /*
-        * fix up branches
-        */
-       if(debug['R'])
-               if(bany(&addrs))
-                       print("addrs: %B\n", addrs);
-
-       r1 = 0; /* set */
-       for(r = firstr; r != R; r = r->link) {
-               p = r->prog;
-               if(p->to.type == D_BRANCH) {
-                       p->to.offset = r->s2->pc;
-                       p->to.u.branch = r->s2->prog;
-               }
-               r1 = r;
-       }
-
-       /*
-        * last pass
-        * eliminate nops
-        * free aux structures
-        */
-       for(p = firstr->prog; p != P; p = p->link){
-               while(p->link && p->link->as == ANOP)
-                       p->link = p->link->link;
-       }
-       if(r1 != R) {
-               r1->link = freer;
-               freer = firstr;
-       }
-}
-
-/*
- * add mov b,rn
- * just after r
- */
-void
-addmove(Reg *r, int bn, int rn, int f)
-{
-       Prog *p, *p1;
-       Addr *a;
-       Var *v;
-
-       p1 = alloc(sizeof(*p1));
-       *p1 = zprog;
-       p = r->prog;
-
-       p1->link = p->link;
-       p->link = p1;
-       p1->lineno = p->lineno;
-
-       v = var + bn;
-
-       a = &p1->to;
-       a->sym = v->sym;
-       a->name = v->name;
-       a->offset = v->offset;
-       a->etype = v->etype;
-       a->type = D_OREG;
-       if(a->etype == TARRAY || a->sym == nil)
-               a->type = D_CONST;
-
-       p1->as = AMOVW;
-       if(v->etype == TCHAR || v->etype == TUCHAR)
-               p1->as = AMOVB;
-       if(v->etype == TSHORT || v->etype == TUSHORT)
-               p1->as = AMOVH;
-       if(v->etype == TVLONG || v->etype == TUVLONG || v->etype == TIND)
-               p1->as = AMOVD;
-       if(v->etype == TFLOAT)
-               p1->as = AFMOVS;
-       if(v->etype == TDOUBLE)
-               p1->as = AFMOVD;
-
-       p1->from.type = D_REG;
-       p1->from.reg = rn;
-       if(rn >= NREG) {
-               p1->from.type = D_FREG;
-               p1->from.reg = rn-NREG;
-       }
-       if(!f) {
-               p1->from = *a;
-               *a = zprog.from;
-               a->type = D_REG;
-               a->reg = rn;
-               if(rn >= NREG) {
-                       a->type = D_FREG;
-                       a->reg = rn-NREG;
-               }
-               if(v->etype == TUCHAR)
-                       p1->as = AMOVBZ;
-               if(v->etype == TUSHORT)
-                       p1->as = AMOVHZ;
-               if(v->etype == TUINT || v->etype == TULONG)
-                       p1->as = AMOVWZ;
-       }
-       if(debug['R'])
-               print("%P\t.a%P\n", p, p1);
-}
-
-Bits
-mkvar(Addr *a, int docon)
-{
-       Var *v;
-       int i, t, n, et, z;
-       int64 o;
-       Bits bit;
-       LSym *s;
-
-       t = a->type;
-       if(t == D_REG && a->reg != NREG)
-               regbits |= RtoB(a->reg);
-       if(t == D_FREG && a->reg != NREG)
-               regbits |= FtoB(a->reg);
-       s = a->sym;
-       o = a->offset;
-       et = a->etype;
-       if(s == nil) {
-               if(t != D_CONST || !docon || a->reg != NREG)
-                       goto none;
-               et = TLONG;
-       }
-       if(t == D_CONST) {
-               if(s == nil && sval(o))
-                       goto none;
-       }
-       n = a->name;
-       v = var;
-       for(i=0; i<nvar; i++) {
-               if(s == v->sym)
-               if(n == v->name)
-               if(o == v->offset)
-                       goto out;
-               v++;
-       }
-       if(s)
-               if(s->name[0] == '.')
-                       goto none;
-       if(nvar >= NVAR)
-               fatal(Z, "variable not optimized: %s", s->name);
-       i = nvar;
-       nvar++;
-       v = &var[i];
-       v->sym = s;
-       v->offset = o;
-       v->etype = et;
-       v->name = n;
-       if(debug['R'])
-               print("bit=%2d et=%2d %D\n", i, et, a);
-out:
-       bit = blsh(i);
-       if(n == D_EXTERN || n == D_STATIC)
-               for(z=0; z<BITS; z++)
-                       externs.b[z] |= bit.b[z];
-       if(n == D_PARAM)
-               for(z=0; z<BITS; z++)
-                       params.b[z] |= bit.b[z];
-       if(v->etype != et || !(typechlpfd[et] || typev[et]))    /* funny punning */
-               for(z=0; z<BITS; z++)
-                       addrs.b[z] |= bit.b[z];
-       if(t == D_CONST) {
-               if((int32)o != o)
-                       v->etype = TVLONG;
-               if(s == nil) {
-                       for(z=0; z<BITS; z++)
-                               consts.b[z] |= bit.b[z];
-                       return bit;
-               }
-               if(et != TARRAY)
-                       for(z=0; z<BITS; z++)
-                               addrs.b[z] |= bit.b[z];
-               for(z=0; z<BITS; z++)
-                       params.b[z] |= bit.b[z];
-               return bit;
-       }
-       if(t == D_OREG)
-               return bit;
-
-none:
-       return zbits;
-}
-
-void
-prop(Reg *r, Bits ref, Bits cal)
-{
-       Reg *r1, *r2;
-       int z;
-
-       for(r1 = r; r1 != R; r1 = r1->p1) {
-               for(z=0; z<BITS; z++) {
-                       ref.b[z] |= r1->refahead.b[z];
-                       if(ref.b[z] != r1->refahead.b[z]) {
-                               r1->refahead.b[z] = ref.b[z];
-                               change++;
-                       }
-                       cal.b[z] |= r1->calahead.b[z];
-                       if(cal.b[z] != r1->calahead.b[z]) {
-                               r1->calahead.b[z] = cal.b[z];
-                               change++;
-                       }
-               }
-               switch(r1->prog->as) {
-               case ABL:
-                       for(z=0; z<BITS; z++) {
-                               cal.b[z] |= ref.b[z] | externs.b[z];
-                               ref.b[z] = 0;
-                       }
-                       break;
-
-               case ATEXT:
-                       for(z=0; z<BITS; z++) {
-                               cal.b[z] = 0;
-                               ref.b[z] = 0;
-                       }
-                       break;
-
-               case ARETURN:
-                       for(z=0; z<BITS; z++) {
-                               cal.b[z] = externs.b[z];
-                               ref.b[z] = 0;
-                       }
-               }
-               for(z=0; z<BITS; z++) {
-                       ref.b[z] = (ref.b[z] & ~r1->set.b[z]) |
-                               r1->use1.b[z] | r1->use2.b[z];
-                       cal.b[z] &= ~(r1->set.b[z] | r1->use1.b[z] | r1->use2.b[z]);
-                       r1->refbehind.b[z] = ref.b[z];
-                       r1->calbehind.b[z] = cal.b[z];
-               }
-               if(r1->active)
-                       break;
-               r1->active = 1;
-       }
-       for(; r != r1; r = r->p1)
-               for(r2 = r->p2; r2 != R; r2 = r2->p2link)
-                       prop(r2, r->refbehind, r->calbehind);
-}
-
-/*
- * find looping structure
- *
- * 1) find reverse postordering
- * 2) find approximate dominators,
- *     the actual dominators if the flow graph is reducible
- *     otherwise, dominators plus some other non-dominators.
- *     See Matthew S. Hecht and Jeffrey D. Ullman,
- *     "Analysis of a Simple Algorithm for Global Data Flow Problems",
- *     Conf.  Record of ACM Symp. on Principles of Prog. Langs, Boston, Massachusetts,
- *     Oct. 1-3, 1973, pp.  207-217.
- * 3) find all nodes with a predecessor dominated by the current node.
- *     such a node is a loop head.
- *     recursively, all preds with a greater rpo number are in the loop
- */
-int32
-postorder(Reg *r, Reg **rpo2r, int32 n)
-{
-       Reg *r1;
-
-       r->rpo = 1;
-       r1 = r->s1;
-       if(r1 && !r1->rpo)
-               n = postorder(r1, rpo2r, n);
-       r1 = r->s2;
-       if(r1 && !r1->rpo)
-               n = postorder(r1, rpo2r, n);
-       rpo2r[n] = r;
-       n++;
-       return n;
-}
-
-int32
-rpolca(int32 *idom, int32 rpo1, int32 rpo2)
-{
-       int32 t;
-
-       if(rpo1 == -1)
-               return rpo2;
-       while(rpo1 != rpo2){
-               if(rpo1 > rpo2){
-                       t = rpo2;
-                       rpo2 = rpo1;
-                       rpo1 = t;
-               }
-               while(rpo1 < rpo2){
-                       t = idom[rpo2];
-                       if(t >= rpo2)
-                               fatal(Z, "bad idom");
-                       rpo2 = t;
-               }
-       }
-       return rpo1;
-}
-
-int
-doms(int32 *idom, int32 r, int32 s)
-{
-       while(s > r)
-               s = idom[s];
-       return s == r;
-}
-
-int
-loophead(int32 *idom, Reg *r)
-{
-       int32 src;
-
-       src = r->rpo;
-       if(r->p1 != R && doms(idom, src, r->p1->rpo))
-               return 1;
-       for(r = r->p2; r != R; r = r->p2link)
-               if(doms(idom, src, r->rpo))
-                       return 1;
-       return 0;
-}
-
-void
-loopmark(Reg **rpo2r, int32 head, Reg *r)
-{
-       if(r->rpo < head || r->active == head)
-               return;
-       r->active = head;
-       r->loop += LOOP;
-       if(r->p1 != R)
-               loopmark(rpo2r, head, r->p1);
-       for(r = r->p2; r != R; r = r->p2link)
-               loopmark(rpo2r, head, r);
-}
-
-void
-loopit(Reg *r, int32 nr)
-{
-       Reg *r1;
-       int32 i, d, me;
-
-       if(nr > maxnr) {
-               rpo2r = alloc(nr * sizeof(Reg*));
-               idom = alloc(nr * sizeof(int32));
-               maxnr = nr;
-       }
-
-       d = postorder(r, rpo2r, 0);
-       if(d > nr)
-               fatal(Z, "too many reg nodes");
-       nr = d;
-       for(i = 0; i < nr / 2; i++){
-               r1 = rpo2r[i];
-               rpo2r[i] = rpo2r[nr - 1 - i];
-               rpo2r[nr - 1 - i] = r1;
-       }
-       for(i = 0; i < nr; i++)
-               rpo2r[i]->rpo = i;
-
-       idom[0] = 0;
-       for(i = 0; i < nr; i++){
-               r1 = rpo2r[i];
-               me = r1->rpo;
-               d = -1;
-               if(r1->p1 != R && r1->p1->rpo < me)
-                       d = r1->p1->rpo;
-               for(r1 = r1->p2; r1 != nil; r1 = r1->p2link)
-                       if(r1->rpo < me)
-                               d = rpolca(idom, d, r1->rpo);
-               idom[i] = d;
-       }
-
-       for(i = 0; i < nr; i++){
-               r1 = rpo2r[i];
-               r1->loop++;
-               if(r1->p2 != R && loophead(idom, r1))
-                       loopmark(rpo2r, i, r1);
-       }
-}
-
-void
-synch(Reg *r, Bits dif)
-{
-       Reg *r1;
-       int z;
-
-       for(r1 = r; r1 != R; r1 = r1->s1) {
-               for(z=0; z<BITS; z++) {
-                       dif.b[z] = (dif.b[z] &
-                               ~(~r1->refbehind.b[z] & r1->refahead.b[z])) |
-                                       r1->set.b[z] | r1->regdiff.b[z];
-                       if(dif.b[z] != r1->regdiff.b[z]) {
-                               r1->regdiff.b[z] = dif.b[z];
-                               change++;
-                       }
-               }
-               if(r1->active)
-                       break;
-               r1->active = 1;
-               for(z=0; z<BITS; z++)
-                       dif.b[z] &= ~(~r1->calbehind.b[z] & r1->calahead.b[z]);
-               if(r1->s2 != R)
-                       synch(r1->s2, dif);
-       }
-}
-
-uint32
-allreg(uint32 b, Rgn *r)
-{
-       Var *v;
-       int i;
-
-       v = var + r->varno;
-       r->regno = 0;
-       switch(v->etype) {
-
-       default:
-               diag(Z, "unknown etype %d/%d", bitno(b), v->etype);
-               break;
-
-       case TCHAR:
-       case TUCHAR:
-       case TSHORT:
-       case TUSHORT:
-       case TINT:
-       case TUINT:
-       case TLONG:
-       case TULONG:
-       case TIND:
-       case TVLONG:
-       case TUVLONG:
-       case TARRAY:
-               i = BtoR(~b);
-               if(i && r->cost > 0) {
-                       r->regno = i;
-                       return RtoB(i);
-               }
-               break;
-
-       case TDOUBLE:
-       case TFLOAT:
-               i = BtoF(~b);
-               if(i && r->cost > 0) {
-                       r->regno = i+NREG;
-                       return FtoB(i);
-               }
-               break;
-       }
-       return 0;
-}
-
-void
-paint1(Reg *r, int bn)
-{
-       Reg *r1;
-       Prog *p;
-       int z;
-       uint32 bb;
-
-       z = bn/32;
-       bb = 1L<<(bn%32);
-       if(r->act.b[z] & bb)
-               return;
-       for(;;) {
-               if(!(r->refbehind.b[z] & bb))
-                       break;
-               r1 = r->p1;
-               if(r1 == R)
-                       break;
-               if(!(r1->refahead.b[z] & bb))
-                       break;
-               if(r1->act.b[z] & bb)
-                       break;
-               r = r1;
-       }
-
-       if(LOAD(r) & ~(r->set.b[z]&~(r->use1.b[z]|r->use2.b[z])) & bb) {
-               change -= CLOAD * r->loop;
-               if(debug['R'] && debug['v'])
-                       print("%ld%P\tld %B $%d\n", r->loop,
-                               r->prog, blsh(bn), change);
-       }
-       for(;;) {
-               r->act.b[z] |= bb;
-               p = r->prog;
-
-               if(r->use1.b[z] & bb) {
-                       change += CREF * r->loop;
-                       if(p->to.type == D_FREG && (p->as == AMOVW || p->as == AMOVD))
-                               change = -CINF;         /* cant go Rreg to Freg */
-                       if(debug['R'] && debug['v'])
-                               print("%ld%P\tu1 %B $%d\n", r->loop,
-                                       p, blsh(bn), change);
-               }
-
-               if((r->use2.b[z]|r->set.b[z]) & bb) {
-                       change += CREF * r->loop;
-                       if(p->from.type == D_FREG && (p->as == AMOVW || p->as == AMOVD))
-                               change = -CINF;         /* cant go Rreg to Freg */
-                       if(debug['R'] && debug['v'])
-                               print("%ld%P\tu2 %B $%d\n", r->loop,
-                                       p, blsh(bn), change);
-               }
-
-               if(STORE(r) & r->regdiff.b[z] & bb) {
-                       change -= CLOAD * r->loop;
-                       if(debug['R'] && debug['v'])
-                               print("%ld%P\tst %B $%d\n", r->loop,
-                                       p, blsh(bn), change);
-               }
-
-               if(r->refbehind.b[z] & bb)
-                       for(r1 = r->p2; r1 != R; r1 = r1->p2link)
-                               if(r1->refahead.b[z] & bb)
-                                       paint1(r1, bn);
-
-               if(!(r->refahead.b[z] & bb))
-                       break;
-               r1 = r->s2;
-               if(r1 != R)
-                       if(r1->refbehind.b[z] & bb)
-                               paint1(r1, bn);
-               r = r->s1;
-               if(r == R)
-                       break;
-               if(r->act.b[z] & bb)
-                       break;
-               if(!(r->refbehind.b[z] & bb))
-                       break;
-       }
-}
-
-uint32
-paint2(Reg *r, int bn)
-{
-       Reg *r1;
-       int z;
-       uint32 bb, vreg;
-
-       z = bn/32;
-       bb = 1L << (bn%32);
-       vreg = regbits;
-       if(!(r->act.b[z] & bb))
-               return vreg;
-       for(;;) {
-               if(!(r->refbehind.b[z] & bb))
-                       break;
-               r1 = r->p1;
-               if(r1 == R)
-                       break;
-               if(!(r1->refahead.b[z] & bb))
-                       break;
-               if(!(r1->act.b[z] & bb))
-                       break;
-               r = r1;
-       }
-       for(;;) {
-               r->act.b[z] &= ~bb;
-
-               vreg |= r->regu;
-
-               if(r->refbehind.b[z] & bb)
-                       for(r1 = r->p2; r1 != R; r1 = r1->p2link)
-                               if(r1->refahead.b[z] & bb)
-                                       vreg |= paint2(r1, bn);
-
-               if(!(r->refahead.b[z] & bb))
-                       break;
-               r1 = r->s2;
-               if(r1 != R)
-                       if(r1->refbehind.b[z] & bb)
-                               vreg |= paint2(r1, bn);
-               r = r->s1;
-               if(r == R)
-                       break;
-               if(!(r->act.b[z] & bb))
-                       break;
-               if(!(r->refbehind.b[z] & bb))
-                       break;
-       }
-       return vreg;
-}
-
-void
-paint3(Reg *r, int bn, int32 rb, int rn)
-{
-       Reg *r1;
-       Prog *p;
-       int z;
-       uint32 bb;
-
-       z = bn/32;
-       bb = 1L << (bn%32);
-       if(r->act.b[z] & bb)
-               return;
-       for(;;) {
-               if(!(r->refbehind.b[z] & bb))
-                       break;
-               r1 = r->p1;
-               if(r1 == R)
-                       break;
-               if(!(r1->refahead.b[z] & bb))
-                       break;
-               if(r1->act.b[z] & bb)
-                       break;
-               r = r1;
-       }
-
-       if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb)
-               addmove(r, bn, rn, 0);
-       for(;;) {
-               r->act.b[z] |= bb;
-               p = r->prog;
-
-               if(r->use1.b[z] & bb) {
-                       if(debug['R'])
-                               print("%P", p);
-                       addreg(&p->from, rn);
-                       if(debug['R'])
-                               print("\t.c%P\n", p);
-               }
-               if((r->use2.b[z]|r->set.b[z]) & bb) {
-                       if(debug['R'])
-                               print("%P", p);
-                       addreg(&p->to, rn);
-                       if(debug['R'])
-                               print("\t.c%P\n", p);
-               }
-
-               if(STORE(r) & r->regdiff.b[z] & bb)
-                       addmove(r, bn, rn, 1);
-               r->regu |= rb;
-
-               if(r->refbehind.b[z] & bb)
-                       for(r1 = r->p2; r1 != R; r1 = r1->p2link)
-                               if(r1->refahead.b[z] & bb)
-                                       paint3(r1, bn, rb, rn);
-
-               if(!(r->refahead.b[z] & bb))
-                       break;
-               r1 = r->s2;
-               if(r1 != R)
-                       if(r1->refbehind.b[z] & bb)
-                               paint3(r1, bn, rb, rn);
-               r = r->s1;
-               if(r == R)
-                       break;
-               if(r->act.b[z] & bb)
-                       break;
-               if(!(r->refbehind.b[z] & bb))
-                       break;
-       }
-}
-
-void
-addreg(Addr *a, int rn)
-{
-
-       a->sym = 0;
-       a->name = D_NONE;
-       a->type = D_REG;
-       a->reg = rn;
-       if(rn >= NREG) {
-               a->type = D_FREG;
-               a->reg = rn-NREG;
-       }
-}
-
-/*
- * track register variables including external registers:
- *     bit     reg
- *     0       R7
- *     1       R8
- *     ...     ...
- *     21      R28
- */
-int32
-RtoB(int r)
-{
-
-       if(r >= REGMIN && r <= REGMAX)
-               return 1L << (r-REGMIN);
-       return 0;
-}
-
-int
-BtoR(int32 b)
-{
-       b &= 0x001fffffL;
-       if(b == 0)
-               return 0;
-       return bitno(b) + REGMIN;
-}
-
-/*
- *     bit     reg
- *     22      F17
- *     23      F18
- *     ...     ...
- *     31      F26
- */
-int32
-FtoB(int f)
-{
-       if(f < FREGMIN || f > FREGEXT)
-               return 0;
-       return 1L << (f - FREGMIN + 22);
-}
-
-int
-BtoF(int32 b)
-{
-
-       b &= 0xffc00000L;
-       if(b == 0)
-               return 0;
-       return bitno(b) - 22 + FREGMIN;
-}
diff --git a/src/cmd/9c/sgen.c b/src/cmd/9c/sgen.c
deleted file mode 100644 (file)
index b03c172..0000000
+++ /dev/null
@@ -1,291 +0,0 @@
-// cmd/9c/sgen.c from Vita Nuova.
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2008 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-Prog*
-gtext(Sym *s, int32 stkoff)
-{
-       vlong v;
-
-       v = ((uvlong)argsize(1) << 32) | (stkoff & 0xffffffff);
-       if((textflag & NOSPLIT) && stkoff >= 128)
-               yyerror("stack frame too large for NOSPLIT function");
-
-       gpseudo(ATEXT, s, nodgconst(v, types[TVLONG]));
-       return p;
-}
-
-
-void
-noretval(int n)
-{
-
-       if(n & 1) {
-               gins(ANOP, Z, Z);
-               p->to.type = D_REG;
-               p->to.reg = REGRET;
-       }
-       if(n & 2) {
-               gins(ANOP, Z, Z);
-               p->to.type = D_FREG;
-               p->to.reg = FREGRET;
-       }
-}
-
-/*
- *     calculate addressability as follows
- *             CONST ==> 20            $value
- *             NAME ==> 10             name
- *             REGISTER ==> 11         register
- *             INDREG ==> 12           *[(reg)+offset]
- *             &10 ==> 2               $name
- *             ADD(2, 20) ==> 2        $name+offset
- *             ADD(3, 20) ==> 3        $(reg)+offset
- *             &12 ==> 3               $(reg)+offset
- *             *11 ==> 11              ??
- *             *2 ==> 10               name
- *             *3 ==> 12               *(reg)+offset
- *     calculate complexity (number of registers)
- */
-void
-xcom(Node *n)
-{
-       Node *l, *r;
-       int v;
-
-       if(n == Z)
-               return;
-       l = n->left;
-       r = n->right;
-       n->addable = 0;
-       n->complex = 0;
-       switch(n->op) {
-       case OCONST:
-               n->addable = 20;
-               return;
-
-       case OREGISTER:
-               n->addable = 11;
-               return;
-
-       case OINDREG:
-               n->addable = 12;
-               return;
-
-       case ONAME:
-               n->addable = 10;
-               return;
-
-       case OADDR:
-               xcom(l);
-               if(l->addable == 10)
-                       n->addable = 2;
-               if(l->addable == 12)
-                       n->addable = 3;
-               break;
-
-       case OIND:
-               xcom(l);
-               if(l->addable == 11)
-                       n->addable = 12;
-               if(l->addable == 3)
-                       n->addable = 12;
-               if(l->addable == 2)
-                       n->addable = 10;
-               break;
-
-       case OADD:
-               xcom(l);
-               xcom(r);
-               if(l->addable == 20) {
-                       if(r->addable == 2)
-                               n->addable = 2;
-                       if(r->addable == 3)
-                               n->addable = 3;
-               }
-               if(r->addable == 20) {
-                       if(l->addable == 2)
-                               n->addable = 2;
-                       if(l->addable == 3)
-                               n->addable = 3;
-               }
-               break;
-
-       case OASMUL:
-       case OASLMUL:
-               xcom(l);
-               xcom(r);
-               v = vlog(r);
-               if(v >= 0) {
-                       n->op = OASASHL;
-                       r->vconst = v;
-                       r->type = types[TINT];
-               }
-               break;
-
-       case OMUL:
-       case OLMUL:
-               xcom(l);
-               xcom(r);
-               v = vlog(r);
-               if(v >= 0) {
-                       n->op = OASHL;
-                       r->vconst = v;
-                       r->type = types[TINT];
-               }
-               v = vlog(l);
-               if(v >= 0) {
-                       n->op = OASHL;
-                       n->left = r;
-                       n->right = l;
-                       r = l;
-                       l = n->left;
-                       r->vconst = v;
-                       r->type = types[TINT];
-                       simplifyshift(n);
-               }
-               break;
-
-       case OASLDIV:
-               xcom(l);
-               xcom(r);
-               v = vlog(r);
-               if(v >= 0) {
-                       n->op = OASLSHR;
-                       r->vconst = v;
-                       r->type = types[TINT];
-               }
-               break;
-
-       case OLDIV:
-               xcom(l);
-               xcom(r);
-               v = vlog(r);
-               if(v >= 0) {
-                       n->op = OLSHR;
-                       r->vconst = v;
-                       r->type = types[TINT];
-                       simplifyshift(n);
-               }
-               break;
-
-       case OASLMOD:
-               xcom(l);
-               xcom(r);
-               v = vlog(r);
-               if(v >= 0) {
-                       n->op = OASAND;
-                       r->vconst--;
-               }
-               break;
-
-       case OLMOD:
-               xcom(l);
-               xcom(r);
-               v = vlog(r);
-               if(v >= 0) {
-                       n->op = OAND;
-                       r->vconst--;
-               }
-               break;
-
-       case OLSHR:
-       case OASHL:
-       case OASHR:
-               xcom(l);
-               xcom(r);
-               simplifyshift(n);
-               break;
-
-       default:
-               if(l != Z)
-                       xcom(l);
-               if(r != Z)
-                       xcom(r);
-               break;
-       }
-       if(n->addable >= 10)
-               return;
-       if(l != Z)
-               n->complex = l->complex;
-       if(r != Z) {
-               if(r->complex == n->complex)
-                       n->complex = r->complex+1;
-               else
-               if(r->complex > n->complex)
-                       n->complex = r->complex;
-       }
-       if(n->complex == 0)
-               n->complex++;
-
-//     if(com64(n))
-//             return;
-
-       switch(n->op) {
-
-       case OFUNC:
-               n->complex = FNX;
-               break;
-
-       case OEQ:
-       case ONE:
-       case OLE:
-       case OLT:
-       case OGE:
-       case OGT:
-       case OHI:
-       case OHS:
-       case OLO:
-       case OLS:
-               /*
-                * immediate operators, make const on right
-                */
-               if(l->op == OCONST) {
-                       n->left = r;
-                       n->right = l;
-                       n->op = invrel[relindex(n->op)];
-               }
-               break;
-
-       case OADD:
-       case OXOR:
-       case OAND:
-       case OOR:
-               /*
-                * immediate operators, make const on right
-                */
-               if(l->op == OCONST) {
-                       n->left = r;
-                       n->right = l;
-               }
-               break;
-       }
-}
-
diff --git a/src/cmd/9c/swt.c b/src/cmd/9c/swt.c
deleted file mode 100644 (file)
index a63db60..0000000
+++ /dev/null
@@ -1,407 +0,0 @@
-// cmd/9c/swt.c from Vita Nuova.
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2008 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-void
-swit1(C1 *q, int nc, int32 def, Node *n)
-{
-       Node tn, nod;
-
-       regalloc(&nod, n, Z);
-       /* always signed */
-       if(typev[n->type->etype])
-               nod.type = types[TVLONG];
-       else
-               nod.type = types[TLONG];
-       cgen(n, &nod);
-       regalloc(&tn, &regnode, Z);
-       swit2(q, nc, def, &nod, &tn);
-       regfree(&tn);
-       regfree(&nod);
-}
-
-void
-swit2(C1 *q, int nc, int32 def, Node *n, Node *tn)
-{
-       C1 *r;
-       int i;
-       Prog *sp;
-
-       if(nc < 5) {
-               for(i=0; i<nc; i++) {
-                       if(sval(q->val)) {
-                               gopcode(OEQ, n, Z, nodconst(q->val));
-                       } else {
-                               gopcode(OSUB, nodconst(q->val), n, tn);
-                               gopcode(OEQ, tn, Z, nodconst(0));
-                       }
-                       patch(p, q->label);
-                       q++;
-               }
-               gbranch(OGOTO);
-               patch(p, def);
-               return;
-       }
-       i = nc / 2;
-       r = q+i;
-       if(sval(r->val)) {
-               gopcode(OGT, n, Z, nodconst(r->val));
-               sp = p;
-       } else {
-               gopcode(OSUB, nodconst(r->val), n, tn);
-               gopcode(OGT, tn, Z, nodconst(0));
-               sp = p;
-       }
-       gbranch(OGOTO);
-       p->as = ABEQ;
-       patch(p, r->label);
-       swit2(q, i, def, n, tn);
-
-       patch(sp, pc);
-       swit2(r+1, nc-i-1, def, n, tn);
-}
-
-void
-bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
-{
-       int sh;
-       int32 v;
-       Node *l;
-
-       /*
-        * n1 gets adjusted/masked value
-        * n2 gets address of cell
-        * n3 gets contents of cell
-        */
-       l = b->left;
-       if(n2 != Z) {
-               regalloc(n1, l, nn);
-               reglcgen(n2, l, Z);
-               regalloc(n3, l, Z);
-               gopcode(OAS, n2, Z, n3);
-               gopcode(OAS, n3, Z, n1);
-       } else {
-               regalloc(n1, l, nn);
-               cgen(l, n1);
-       }
-       if(b->type->shift == 0 && typeu[b->type->etype]) {
-               v = ~0 + (1L << b->type->nbits);
-               gopcode(OAND, nodconst(v), Z, n1);
-       } else {
-               sh = 32 - b->type->shift - b->type->nbits;
-               if(sh > 0)
-                       gopcode(OASHL, nodconst(sh), Z, n1);
-               sh += b->type->shift;
-               if(sh > 0)
-                       if(typeu[b->type->etype])
-                               gopcode(OLSHR, nodconst(sh), Z, n1);
-                       else
-                               gopcode(OASHR, nodconst(sh), Z, n1);
-       }
-}
-
-void
-bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
-{
-       int32 v;
-       Node nod, *l;
-       int sh;
-
-       /*
-        * n1 has adjusted/masked value
-        * n2 has address of cell
-        * n3 has contents of cell
-        */
-       l = b->left;
-       regalloc(&nod, l, Z);
-       v = ~0 + (1L << b->type->nbits);
-       gopcode(OAND, nodconst(v), Z, n1);
-       gopcode(OAS, n1, Z, &nod);
-       if(nn != Z)
-               gopcode(OAS, n1, Z, nn);
-       sh = b->type->shift;
-       if(sh > 0)
-               gopcode(OASHL, nodconst(sh), Z, &nod);
-       v <<= sh;
-       gopcode(OAND, nodconst(~v), Z, n3);
-       gopcode(OOR, n3, Z, &nod);
-       gopcode(OAS, &nod, Z, n2);
-
-       regfree(&nod);
-       regfree(n1);
-       regfree(n2);
-       regfree(n3);
-}
-
-int32
-outstring(char *s, int32 n)
-{
-       int32 r;
-
-       if(suppress)
-               return nstring;
-       r = nstring;
-       while(n) {
-               string[mnstring] = *s++;
-               mnstring++;
-               nstring++;
-               if(mnstring >= NSNAME) {
-                       gpseudo(ADATA, symstring, nodconst(0L));
-                       p->from.offset += nstring - NSNAME;
-                       p->reg = NSNAME;
-                       p->to.type = D_SCONST;
-                       memmove(p->to.u.sval, string, NSNAME);
-                       mnstring = 0;
-               }
-               n--;
-       }
-       return r;
-}
-
-int
-mulcon(Node *n, Node *nn)
-{
-       Node *l, *r, nod1, nod2;
-       Multab *m;
-       int32 v;
-       int o;
-       char code[sizeof(m->code)+2], *p;
-
-       if(typefd[n->type->etype])
-               return 0;
-       l = n->left;
-       r = n->right;
-       if(l->op == OCONST) {
-               l = r;
-               r = n->left;
-       }
-       if(r->op != OCONST)
-               return 0;
-       v = convvtox(r->vconst, n->type->etype);
-       if(v != r->vconst) {
-               if(debug['M'])
-                       print("%L multiply conv: %lld\n", n->lineno, r->vconst);
-               return 0;
-       }
-       m = mulcon0(n, v);
-       if(!m) {
-               if(debug['M'])
-                       print("%L multiply table: %lld\n", n->lineno, r->vconst);
-               return 0;
-       }
-
-       memmove(code, m->code, sizeof(m->code));
-       code[sizeof(m->code)] = 0;
-
-       p = code;
-       if(p[1] == 'i')
-               p += 2;
-       regalloc(&nod1, n, nn);
-       cgen(l, &nod1);
-       if(v < 0)
-               gopcode(ONEG, &nod1, Z, &nod1);
-       regalloc(&nod2, n, Z);
-
-loop:
-       switch(*p) {
-       case 0:
-               regfree(&nod2);
-               gopcode(OAS, &nod1, Z, nn);
-               regfree(&nod1);
-               return 1;
-       case '+':
-               o = OADD;
-               goto addsub;
-       case '-':
-               o = OSUB;
-       addsub: /* number is r,n,l */
-               v = p[1] - '0';
-               r = &nod1;
-               if(v&4)
-                       r = &nod2;
-               n = &nod1;
-               if(v&2)
-                       n = &nod2;
-               l = &nod1;
-               if(v&1)
-                       l = &nod2;
-               gopcode(o, l, n, r);
-               break;
-       default: /* op is shiftcount, number is r,l */
-               v = p[1] - '0';
-               r = &nod1;
-               if(v&2)
-                       r = &nod2;
-               l = &nod1;
-               if(v&1)
-                       l = &nod2;
-               v = *p - 'a';
-               if(v < 0 || v >= 32) {
-                       diag(n, "mulcon unknown op: %c%c", p[0], p[1]);
-                       break;
-               }
-               gopcode(OASHL, nodconst(v), l, r);
-               break;
-       }
-       p += 2;
-       goto loop;
-}
-
-void
-sextern(Sym *s, Node *a, int32 o, int32 w)
-{
-       int32 e, lw;
-
-       for(e=0; e<w; e+=NSNAME) {
-               lw = NSNAME;
-               if(w-e < lw)
-                       lw = w-e;
-               gpseudo(ADATA, s, nodconst(0));
-               p->from.offset += o+e;
-               p->reg = lw;
-               p->to.type = D_SCONST;
-               memmove(p->to.u.sval, a->cstring+e, lw);
-       }
-}
-
-void
-gextern(Sym *s, Node *a, int32 o, int32 w)
-{
-       gpseudo(ADATA, s, a);
-       p->from.offset += o;
-       p->reg = w;
-       if(p->to.type == D_OREG)
-               p->to.type = D_CONST;
-}
-
-void
-outcode(void)
-{
-       Bprint(&outbuf, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion());
-       if(pragcgobuf.to > pragcgobuf.start) {
-               Bprint(&outbuf, "\n");
-               Bprint(&outbuf, "$$  // exports\n\n");
-               Bprint(&outbuf, "$$  // local types\n\n");
-               Bprint(&outbuf, "$$  // cgo\n");
-               Bprint(&outbuf, "%s", fmtstrflush(&pragcgobuf));
-               Bprint(&outbuf, "\n$$\n\n");
-       }
-       Bprint(&outbuf, "!\n");
-
-       writeobj(ctxt, &outbuf);
-       lastp = nil;
-}
-
-int32
-align(int32 i, Type *t, int op, int32 *maxalign)
-{
-       int32 o;
-       Type *v;
-       int w, packw;
-
-       o = i;
-       w = 1;
-       packw = 0;
-       switch(op) {
-       default:
-               diag(Z, "unknown align opcode %d", op);
-               break;
-
-       case Asu2:      /* padding at end of a struct */
-               w = *maxalign;
-               if(w < 1)
-                       w = 1;
-               if(packflg)
-                       packw = packflg;
-               break;
-
-       case Ael1:      /* initial allign of struct element */
-               for(v=t; v->etype==TARRAY; v=v->link)
-                       ;
-               if(v->etype == TSTRUCT || v->etype == TUNION)
-                       w = v->align;
-               else
-                       w = ewidth[v->etype];
-               if(w < 1 || w > SZ_VLONG)
-                       fatal(Z, "align");
-               if(packflg)
-                       packw = packflg;
-               break;
-
-       case Ael2:      /* width of a struct element */
-               o += t->width;
-               break;
-
-       case Aarg0:     /* initial passbyptr argument in arg list */
-               if(typesu[t->etype]) {
-                       o = align(o, types[TIND], Aarg1, nil);
-                       o = align(o, types[TIND], Aarg2, nil);
-               }
-               break;
-
-       case Aarg1:     /* initial align of parameter */
-               w = ewidth[t->etype];
-               if(w <= 0 || w >= SZ_VLONG) {
-                       w = SZ_VLONG;
-                       break;
-               }
-               w = 1;
-               break;
-
-       case Aarg2:     /* width of a parameter */
-               o += t->width;
-               w = t->width;
-               if(w > SZ_VLONG)
-                       w = SZ_VLONG;
-               break;
-
-       case Aaut3:     /* total align of automatic */
-               o = align(o, t, Ael1, nil);
-               o = align(o, t, Ael2, nil);
-               break;
-       }
-       if(packw != 0 && xround(o, w) != xround(o, packw))
-               diag(Z, "#pragma pack changes offset of %T", t);
-       o = xround(o, w);
-       if(maxalign && *maxalign < w)
-               *maxalign = w;
-       if(debug['A'])
-               print("align %s %ld %T = %ld\n", bnames[op], i, t, o);
-       return o;
-}
-
-int32
-maxround(int32 max, int32 v)
-{
-       v = xround(v, SZ_VLONG);
-       if(v > max)
-               return v;
-       return max;
-}
diff --git a/src/cmd/9c/txt.c b/src/cmd/9c/txt.c
deleted file mode 100644 (file)
index e46aba8..0000000
+++ /dev/null
@@ -1,1537 +0,0 @@
-// cmd/9c/txt.c from Vita Nuova.
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2008 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-static int     resvreg[nelem(reg)];
-
-#define        isv(et) ((et) == TVLONG || (et) == TUVLONG || (et) == TIND)
-
-int thechar = '9';
-char *thestring = "power64";
-
-LinkArch       *thelinkarch;
-
-void
-linkarchinit(void)
-{
-       thestring = getgoarch();
-       if(strcmp(thestring, "power64le") == 0)
-               thelinkarch = &linkpower64le;
-       else
-               thelinkarch = &linkpower64;
-}
-
-
-void
-ginit(void)
-{
-       Type *t;
-
-       dodefine("_64BITREG");
-       dodefine("_64BIT");
-       exregoffset = REGEXT;
-       exfregoffset = FREGEXT;
-       listinit();
-       nstring = 0;
-       mnstring = 0;
-       nrathole = 0;
-       pc = 0;
-       breakpc = -1;
-       continpc = -1;
-       cases = C;
-       lastp = P;
-       tfield = types[TLONG];
-
-       typeword = typechlvp;
-       typecmplx = typesu;
-       /* TO DO */
-       memmove(typechlpv, typechlp, sizeof(typechlpv));
-       typechlpv[TVLONG] = 1;
-       typechlpv[TUVLONG] = 1;
-
-       zprog.link = P;
-       zprog.as = AGOK;
-       zprog.reg = NREG;
-       zprog.from.type = D_NONE;
-       zprog.from.name = D_NONE;
-       zprog.from.reg = NREG;
-       zprog.from3 = zprog.from;
-       zprog.to = zprog.from;
-
-       regnode.op = OREGISTER;
-       regnode.class = CEXREG;
-       regnode.reg = 0;
-       regnode.complex = 0;
-       regnode.addable = 11;
-       regnode.type = types[TLONG];
-
-       qregnode = regnode;
-       qregnode.type = types[TVLONG];
-
-       constnode.op = OCONST;
-       constnode.class = CXXX;
-       constnode.complex = 0;
-       constnode.addable = 20;
-       constnode.type = types[TLONG];
-
-       vconstnode = constnode;
-       vconstnode.type = types[TVLONG];
-
-       fconstnode.op = OCONST;
-       fconstnode.class = CXXX;
-       fconstnode.complex = 0;
-       fconstnode.addable = 20;
-       fconstnode.type = types[TDOUBLE];
-
-       nodsafe = new(ONAME, Z, Z);
-       nodsafe->sym = slookup(".safe");
-       nodsafe->type = types[TINT];
-       nodsafe->etype = types[TINT]->etype;
-       nodsafe->class = CAUTO;
-       complex(nodsafe);
-
-       t = typ(TARRAY, types[TCHAR]);
-       symrathole = slookup(".rathole");
-       symrathole->class = CGLOBL;
-       symrathole->type = t;
-
-       nodrat = new(ONAME, Z, Z);
-       nodrat->sym = symrathole;
-       nodrat->type = types[TIND];
-       nodrat->etype = TVOID;
-       nodrat->class = CGLOBL;
-       complex(nodrat);
-       nodrat->type = t;
-
-       nodret = new(ONAME, Z, Z);
-       nodret->sym = slookup(".ret");
-       nodret->type = types[TIND];
-       nodret->etype = TIND;
-       nodret->class = CPARAM;
-       nodret = new(OIND, nodret, Z);
-       complex(nodret);
-
-       com64init();
-
-       memset(reg, 0, sizeof(reg));
-       reg[REGZERO] = 1;       /* don't use */
-       reg[REGTMP] = 1;
-       reg[FREGCVI+NREG] = 1;
-       reg[FREGZERO+NREG] = 1;
-       reg[FREGHALF+NREG] = 1;
-       reg[FREGONE+NREG] = 1;
-       reg[FREGTWO+NREG] = 1;
-       memmove(resvreg, reg, sizeof(reg));
-}
-
-void
-gclean(void)
-{
-       int i;
-       Sym *s;
-
-       for(i=0; i<NREG; i++)
-               if(reg[i] && !resvreg[i])
-                       diag(Z, "reg %d left allocated", i);
-       for(i=NREG; i<NREG+NREG; i++)
-               if(reg[i] && !resvreg[i])
-                       diag(Z, "freg %d left allocated", i-NREG);
-       while(mnstring)
-               outstring("", 1L);
-       symstring->type->width = nstring;
-       symrathole->type->width = nrathole;
-       for(i=0; i<NHASH; i++)
-       for(s = hash[i]; s != S; s = s->link) {
-               if(s->type == T)
-                       continue;
-               if(s->type->width == 0)
-                       continue;
-               if(s->class != CGLOBL && s->class != CSTATIC)
-                       continue;
-               if(s->type == types[TENUM])
-                       continue;
-               gpseudo(AGLOBL, s, nodconst(s->type->width));
-       }
-       nextpc();
-       p->as = AEND;
-       outcode();
-}
-
-void
-nextpc(void)
-{
-       Plist *pl;
-
-       p = alloc(sizeof(*p));
-       *p = zprog;
-       p->lineno = nearln;
-       p->pc = pc;
-       pc++;
-       if(lastp == P) {
-               pl = linknewplist(ctxt);
-               pl->firstpc = p;
-       } else
-               lastp->link = p;
-       lastp = p;
-}
-
-void
-gargs(Node *n, Node *tn1, Node *tn2)
-{
-       int32 regs;
-       Node fnxargs[20], *fnxp;
-
-       regs = cursafe;
-
-       fnxp = fnxargs;
-       garg1(n, tn1, tn2, 0, &fnxp);   /* compile fns to temps */
-
-       curarg = 0;
-       fnxp = fnxargs;
-       garg1(n, tn1, tn2, 1, &fnxp);   /* compile normal args and temps */
-
-       cursafe = regs;
-}
-
-void
-garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp)
-{
-       Node nod;
-
-       if(n == Z)
-               return;
-       if(n->op == OLIST) {
-               garg1(n->left, tn1, tn2, f, fnxp);
-               garg1(n->right, tn1, tn2, f, fnxp);
-               return;
-       }
-       if(f == 0) {
-               if(n->complex >= FNX) {
-                       regsalloc(*fnxp, n);
-                       nod = znode;
-                       nod.op = OAS;
-                       nod.left = *fnxp;
-                       nod.right = n;
-                       nod.type = n->type;
-                       cgen(&nod, Z);
-                       (*fnxp)++;
-               }
-               return;
-       }
-       if(typesu[n->type->etype]) {
-               regaalloc(tn2, n);
-               if(n->complex >= FNX) {
-                       sugen(*fnxp, tn2, n->type->width);
-                       (*fnxp)++;
-               } else
-                       sugen(n, tn2, n->type->width);
-               return;
-       }
-       if(REGARG>=0 && curarg == 0 && typechlpv[n->type->etype]) {
-               regaalloc1(tn1, n);
-               if(n->complex >= FNX) {
-                       cgen(*fnxp, tn1);
-                       (*fnxp)++;
-               } else
-                       cgen(n, tn1);
-               return;
-       }
-       if(vconst(n) == 0) {
-               regaalloc(tn2, n);
-               gopcode(OAS, n, Z, tn2);
-               return;
-       }
-       regalloc(tn1, n, Z);
-       if(n->complex >= FNX) {
-               cgen(*fnxp, tn1);
-               (*fnxp)++;
-       } else
-               cgen(n, tn1);
-       regaalloc(tn2, n);
-       gopcode(OAS, tn1, Z, tn2);
-       regfree(tn1);
-}
-
-Node*
-nod32const(vlong v)
-{
-       constnode.vconst = v & MASK(32);
-       return &constnode;
-}
-
-Node*
-nodgconst(vlong v, Type *t)
-{
-       if(!typev[t->etype])
-               return nodconst((int32)v);
-       vconstnode.vconst = v;
-       return &vconstnode;
-}
-
-Node*
-nodconst(int32 v)
-{
-       constnode.vconst = v;
-       return &constnode;
-}
-
-Node*
-nodfconst(double d)
-{
-       fconstnode.fconst = d;
-       return &fconstnode;
-}
-
-void
-nodreg(Node *n, Node *nn, int reg)
-{
-       *n = qregnode;
-       n->reg = reg;
-       n->type = nn->type;
-       n->lineno = nn->lineno;
-}
-
-void
-regret(Node *n, Node *nn, Type *t, int mode)
-{
-       int r;
-       
-       if(mode == 0 || hasdotdotdot(t) || nn->type->width == 0) {
-               r = REGRET;
-               if(typefd[nn->type->etype])
-                       r = FREGRET+NREG;
-               nodreg(n, nn, r);
-               reg[r]++;
-               return;
-       }
-       
-       if(mode == 1) {
-               // fetch returned value after call.
-               // already called gargs, so curarg is set.
-               curarg = (curarg+7) & ~7;
-               regaalloc(n, nn);
-               return;
-       }
-
-       if(mode == 2) {
-               // store value to be returned.
-               // must compute arg offset.
-               if(t->etype != TFUNC)
-                       fatal(Z, "bad regret func %T", t);
-               *n = *nn;
-               n->op = ONAME;
-               n->class = CPARAM;
-               n->sym = slookup(".ret");
-               n->complex = nodret->complex;
-               n->addable = 20;
-               n->xoffset = argsize(0);
-               return;
-       }
-       
-       fatal(Z, "bad regret"); 
-}
-
-void
-regalloc(Node *n, Node *tn, Node *o)
-{
-       int i, j;
-       static int lasti;
-
-       switch(tn->type->etype) {
-       case TCHAR:
-       case TUCHAR:
-       case TSHORT:
-       case TUSHORT:
-       case TINT:
-       case TUINT:
-       case TLONG:
-       case TULONG:
-       case TVLONG:
-       case TUVLONG:
-       case TIND:
-               if(o != Z && o->op == OREGISTER) {
-                       i = o->reg;
-                       if(i > 0 && i < NREG)
-                               goto out;
-               }
-               j = lasti + REGRET+1;
-               for(i=REGRET+1; i<NREG; i++) {
-                       if(j >= NREG)
-                               j = REGRET+1;
-                       if(reg[j] == 0) {
-                               i = j;
-                               goto out;
-                       }
-                       j++;
-               }
-               diag(tn, "out of fixed registers");
-               goto err;
-
-       case TFLOAT:
-       case TDOUBLE:
-               if(o != Z && o->op == OREGISTER) {
-                       i = o->reg;
-                       if(i >= NREG && i < NREG+NREG)
-                               goto out;
-               }
-               j = lasti + NREG;
-               for(i=NREG; i<NREG+NREG; i++) {
-                       if(j >= NREG+NREG)
-                               j = NREG;
-                       if(reg[j] == 0) {
-                               i = j;
-                               goto out;
-                       }
-                       j++;
-               }
-               diag(tn, "out of float registers");
-               goto err;
-       }
-       diag(tn, "unknown type in regalloc: %T", tn->type);
-err:
-       i = 0;
-out:
-       if(i)
-               reg[i]++;
-       lasti++;
-       if(lasti >= 5)
-               lasti = 0;
-       nodreg(n, tn, i);
-}
-
-void
-regialloc(Node *n, Node *tn, Node *o)
-{
-       Node nod;
-
-       nod = *tn;
-       nod.type = types[TIND];
-       regalloc(n, &nod, o);
-}
-
-void
-regfree(Node *n)
-{
-       int i;
-
-       i = 0;
-       if(n->op != OREGISTER && n->op != OINDREG)
-               goto err;
-       i = n->reg;
-       if(i < 0 || i >= sizeof(reg))
-               goto err;
-       if(reg[i] <= 0)
-               goto err;
-       reg[i]--;
-       return;
-err:
-       diag(n, "error in regfree: %d", i);
-}
-
-void
-regsalloc(Node *n, Node *nn)
-{
-       cursafe = align(cursafe, nn->type, Aaut3, nil);
-       maxargsafe = maxround(maxargsafe, cursafe+curarg);
-       *n = *nodsafe;
-       n->xoffset = -(stkoff + cursafe);
-       n->type = nn->type;
-       n->etype = nn->type->etype;
-       n->lineno = nn->lineno;
-}
-
-void
-regaalloc1(Node *n, Node *nn)
-{
-       if(REGARG < 0)
-               return;
-       nodreg(n, nn, REGARG);
-       reg[REGARG]++;
-       curarg = align(curarg, nn->type, Aarg1, nil);
-       curarg = align(curarg, nn->type, Aarg2, nil);
-       maxargsafe = maxround(maxargsafe, cursafe+curarg);
-}
-
-void
-regaalloc(Node *n, Node *nn)
-{
-       curarg = align(curarg, nn->type, Aarg1, nil);
-       *n = *nn;
-       n->op = OINDREG;
-       n->reg = REGSP;
-       n->xoffset = curarg + SZ_VLONG;
-       n->complex = 0;
-       n->addable = 20;
-       curarg = align(curarg, nn->type, Aarg2, nil);
-       maxargsafe = maxround(maxargsafe, cursafe+curarg);
-}
-
-void
-regind(Node *n, Node *nn)
-{
-
-       if(n->op != OREGISTER) {
-               diag(n, "regind not OREGISTER");
-               return;
-       }
-       n->op = OINDREG;
-       n->type = nn->type;
-}
-
-void
-raddr(Node *n, Prog *p)
-{
-       Addr a;
-
-       naddr(n, &a);
-       if(R0ISZERO && a.type == D_CONST && a.offset == 0) {
-               a.type = D_REG;
-               a.reg = REGZERO;
-       }
-       if(a.type != D_REG && a.type != D_FREG) {
-               if(n)
-                       diag(n, "bad in raddr: %O", n->op);
-               else
-                       diag(n, "bad in raddr: <null>");
-               p->reg = NREG;
-       } else
-               p->reg = a.reg;
-}
-
-void
-naddr(Node *n, Addr *a)
-{
-       int32 v;
-
-       a->type = D_NONE;
-       if(n == Z)
-               return;
-       switch(n->op) {
-       default:
-       bad:
-               prtree(n, "naddr");
-               diag(n, "%L: !bad in naddr: %O", n->lineno, n->op);
-               break;
-
-       case OREGISTER:
-               a->type = D_REG;
-               a->sym = nil;
-               a->reg = n->reg;
-               if(a->reg >= NREG) {
-                       a->type = D_FREG;
-                       a->reg -= NREG;
-               }
-               break;
-
-       case OIND:
-               naddr(n->left, a);
-               if(a->type == D_REG) {
-                       a->type = D_OREG;
-                       break;
-               }
-               if(a->type == D_CONST) {
-                       a->type = D_OREG;
-                       break;
-               }
-               goto bad;
-
-       case OINDREG:
-               a->type = D_OREG;
-               a->sym = nil;
-               a->offset = n->xoffset;
-               a->reg = n->reg;
-               break;
-
-       case ONAME:
-               a->etype = n->etype;
-               a->type = D_OREG;
-               a->name = D_STATIC;
-               a->sym = linksym(n->sym);
-               a->offset = n->xoffset;
-               if(n->class == CSTATIC)
-                       break;
-               if(n->class == CEXTERN || n->class == CGLOBL) {
-                       a->name = D_EXTERN;
-                       break;
-               }
-               if(n->class == CAUTO) {
-                       a->name = D_AUTO;
-                       break;
-               }
-               if(n->class == CPARAM) {
-                       a->name = D_PARAM;
-                       break;
-               }
-               goto bad;
-
-       case OCONST:
-               a->sym = nil;
-               a->reg = NREG;
-               if(typefd[n->type->etype]) {
-                       a->type = D_FCONST;
-                       a->u.dval = n->fconst;
-               } else {
-                       a->type = D_CONST;
-                       a->offset = n->vconst;
-               }
-               break;
-
-       case OADDR:
-               naddr(n->left, a);
-               if(a->type == D_OREG) {
-                       a->type = D_CONST;
-                       break;
-               }
-               goto bad;
-
-       case OADD:
-               if(n->left->op == OCONST) {
-                       naddr(n->left, a);
-                       v = a->offset;
-                       naddr(n->right, a);
-               } else {
-                       naddr(n->right, a);
-                       v = a->offset;
-                       naddr(n->left, a);
-               }
-               a->offset += v;
-               break;
-
-       }
-}
-
-void
-fop(int as, int f1, int f2, Node *t)
-{
-       Node nod1, nod2, nod3;
-
-       nodreg(&nod1, t, NREG+f1);
-       nodreg(&nod2, t, NREG+f2);
-       regalloc(&nod3, t, t);
-       gopcode(as, &nod1, &nod2, &nod3);
-       gmove(&nod3, t);
-       regfree(&nod3);
-}
-
-void
-gmove(Node *f, Node *t)
-{
-       int ft, tt, a;
-       Node nod, fxc0, fxc1, fxc2, fxrat;
-       Prog *p1;
-       double d;
-
-       ft = f->type->etype;
-       tt = t->type->etype;
-
-       if(ft == TDOUBLE && f->op == OCONST) {
-               d = f->fconst;
-               if(d == 0.0) {
-                       a = FREGZERO;
-                       goto ffreg;
-               }
-               if(d == 0.5) {
-                       a = FREGHALF;
-                       goto ffreg;
-               }
-               if(d == 1.0) {
-                       a = FREGONE;
-                       goto ffreg;
-               }
-               if(d == 2.0) {
-                       a = FREGTWO;
-                       goto ffreg;
-               }
-               if(d == -.5) {
-                       fop(OSUB, FREGHALF, FREGZERO, t);
-                       return;
-               }
-               if(d == -1.0) {
-                       fop(OSUB, FREGONE, FREGZERO, t);
-                       return;
-               }
-               if(d == -2.0) {
-                       fop(OSUB, FREGTWO, FREGZERO, t);
-                       return;
-               }
-               if(d == 1.5) {
-                       fop(OADD, FREGONE, FREGHALF, t);
-                       return;
-               }
-               if(d == 2.5) {
-                       fop(OADD, FREGTWO, FREGHALF, t);
-                       return;
-               }
-               if(d == 3.0) {
-                       fop(OADD, FREGTWO, FREGONE, t);
-                       return;
-               }
-       }
-       if(ft == TFLOAT && f->op == OCONST) {
-               d = f->fconst;
-               if(d == 0) {
-                       a = FREGZERO;
-               ffreg:
-                       nodreg(&nod, f, NREG+a);
-                       gmove(&nod, t);
-                       return;
-               }
-       }
-       /*
-        * a load --
-        * put it into a register then
-        * worry what to do with it.
-        */
-       if(f->op == ONAME || f->op == OINDREG || f->op == OIND) {
-               switch(ft) {
-               default:
-                       if(ewidth[ft] == 4){
-                               if(typeu[ft])
-                                       a = AMOVWZ;
-                               else
-                                       a = AMOVW;
-                       }else
-                               a = AMOVD;
-                       break;
-               case TINT:
-                       a = AMOVW;
-                       break;
-               case TUINT:
-                       a = AMOVWZ;
-                       break;
-               case TFLOAT:
-                       a = AFMOVS;
-                       break;
-               case TDOUBLE:
-                       a = AFMOVD;
-                       break;
-               case TCHAR:
-                       a = AMOVB;
-                       break;
-               case TUCHAR:
-                       a = AMOVBZ;
-                       break;
-               case TSHORT:
-                       a = AMOVH;
-                       break;
-               case TUSHORT:
-                       a = AMOVHZ;
-                       break;
-               }
-               regalloc(&nod, f, t);
-               gins(a, f, &nod);
-               gmove(&nod, t);
-               regfree(&nod);
-               return;
-       }
-
-       /*
-        * a store --
-        * put it into a register then
-        * store it.
-        */
-       if(t->op == ONAME || t->op == OINDREG || t->op == OIND) {
-               switch(tt) {
-               default:
-                       if(ewidth[tt] == 4)
-                               a = AMOVW;
-                       else
-                               a = AMOVD;
-                       break;
-               case TINT:
-                       a = AMOVW;
-                       break;
-               case TUINT:
-                       a = AMOVWZ;
-                       break;
-               case TUCHAR:
-                       a = AMOVBZ;
-                       break;
-               case TCHAR:
-                       a = AMOVB;
-                       break;
-               case TUSHORT:
-                       a = AMOVHZ;
-                       break;
-               case TSHORT:
-                       a = AMOVH;
-                       break;
-               case TFLOAT:
-                       a = AFMOVS;
-                       break;
-               case TDOUBLE:
-                       a = AFMOVD;
-                       break;
-               }
-               if(!typefd[ft] && vconst(f) == 0) {
-                       gins(a, f, t);
-                       return;
-               }
-               if(ft == tt)
-                       regalloc(&nod, t, f);
-               else
-                       regalloc(&nod, t, Z);
-               gmove(f, &nod);
-               gins(a, &nod, t);
-               regfree(&nod);
-               return;
-       }
-
-       /*
-        * type x type cross table
-        */
-       a = AGOK;
-       switch(ft) {
-       case TDOUBLE:
-       case TFLOAT:
-               switch(tt) {
-               case TDOUBLE:
-                       a = AFMOVD;
-                       if(ft == TFLOAT)
-                               a = AFMOVS;     /* AFMOVSD */
-                       break;
-               case TFLOAT:
-                       a = AFRSP;
-                       if(ft == TFLOAT)
-                               a = AFMOVS;
-                       break;
-               case TINT:
-               case TUINT:
-               case TLONG:
-               case TULONG:
-               case TIND:
-               case TSHORT:
-               case TUSHORT:
-               case TCHAR:
-               case TUCHAR:
-                       /* BUG: not right for unsigned int32 */
-                       regalloc(&nod, f, Z);   /* should be type float */
-                       regsalloc(&fxrat, f);
-                       gins(AFCTIWZ, f, &nod);
-                       gins(AFMOVD, &nod, &fxrat);
-                       regfree(&nod);
-                       fxrat.type = nodrat->type;
-                       fxrat.etype = nodrat->etype;
-                       fxrat.xoffset += 4;
-                       gins(AMOVW, &fxrat, t); /* TO DO */
-                       gmove(t, t);
-                       return;
-               case TVLONG:
-               case TUVLONG:
-                       /* BUG: not right for unsigned int32 */
-                       regalloc(&nod, f, Z);   /* should be type float */
-                       regsalloc(&fxrat, f);
-                       gins(AFCTIDZ, f, &nod);
-                       gins(AFMOVD, &nod, &fxrat);
-                       regfree(&nod);
-                       fxrat.type = nodrat->type;
-                       fxrat.etype = nodrat->etype;
-                       gins(AMOVD, &fxrat, t);
-                       gmove(t, t);
-                       return;
-               }
-               break;
-       case TINT:
-       case TUINT:
-       case TLONG:
-       case TULONG:
-               switch(tt) {
-               case TDOUBLE:
-               case TFLOAT:
-                       goto fxtofl;
-               case TINT:
-               case TUINT:
-               case TLONG:
-               case TULONG:
-               case TSHORT:
-               case TUSHORT:
-               case TCHAR:
-               case TUCHAR:
-                       if(typeu[tt])
-                               a = AMOVWZ;
-                       else
-                               a = AMOVW;
-                       break;
-               case TVLONG:
-               case TUVLONG:
-               case TIND:
-                       a = AMOVD;
-                       break;
-               }
-               break;
-       case TVLONG:
-       case TUVLONG:
-       case TIND:
-               switch(tt) {
-               case TDOUBLE:
-               case TFLOAT:
-                       goto fxtofl;
-               case TINT:
-               case TUINT:
-               case TLONG:
-               case TULONG:
-               case TVLONG:
-               case TUVLONG:
-               case TIND:
-               case TSHORT:
-               case TUSHORT:
-               case TCHAR:
-               case TUCHAR:
-                       a = AMOVD;      /* TO DO: conversion done? */
-                       break;
-               }
-               break;
-       case TSHORT:
-               switch(tt) {
-               case TDOUBLE:
-               case TFLOAT:
-                       goto fxtofl;
-               case TINT:
-               case TUINT:
-               case TLONG:
-               case TULONG:
-               case TVLONG:
-               case TUVLONG:
-               case TIND:
-                       a = AMOVH;
-                       break;
-               case TSHORT:
-               case TUSHORT:
-               case TCHAR:
-               case TUCHAR:
-                       a = AMOVD;
-                       break;
-               }
-               break;
-       case TUSHORT:
-               switch(tt) {
-               case TDOUBLE:
-               case TFLOAT:
-                       goto fxtofl;
-               case TINT:
-               case TUINT:
-               case TLONG:
-               case TULONG:
-               case TVLONG:
-               case TUVLONG:
-               case TIND:
-                       a = AMOVHZ;
-                       break;
-               case TSHORT:
-               case TUSHORT:
-               case TCHAR:
-               case TUCHAR:
-                       a = AMOVD;
-                       break;
-               }
-               break;
-       case TCHAR:
-               switch(tt) {
-               case TDOUBLE:
-               case TFLOAT:
-                       goto fxtofl;
-               case TINT:
-               case TUINT:
-               case TLONG:
-               case TULONG:
-               case TVLONG:
-               case TUVLONG:
-               case TIND:
-               case TSHORT:
-               case TUSHORT:
-                       a = AMOVB;
-                       break;
-               case TCHAR:
-               case TUCHAR:
-                       a = AMOVD;
-                       break;
-               }
-               break;
-       case TUCHAR:
-               switch(tt) {
-               case TDOUBLE:
-               case TFLOAT:
-               fxtofl:
-                       /*
-                        * rat[0] = 0x43300000; rat[1] = f^0x80000000;
-                        * t = *(double*)rat - FREGCVI;
-                        * is-unsigned(t) => if(t<0) t += 2^32;
-                        * could be streamlined for int-to-float
-                        */
-                       regalloc(&fxc0, f, Z);
-                       regalloc(&fxc2, f, Z);
-                       regsalloc(&fxrat, t);   /* should be type float */
-                       gins(AMOVW, nodconst(0x43300000L), &fxc0);
-                       gins(AMOVW, f, &fxc2);
-                       gins(AXOR, nodconst(0x80000000L), &fxc2);
-                       if(ctxt->arch->endian == BigEndian) {
-                               gins(AMOVW, &fxc0, &fxrat);
-                               fxc1 = fxrat;
-                               fxc1.type = nodrat->type;
-                               fxc1.etype = nodrat->etype;
-                               fxc1.xoffset += SZ_LONG;
-                               gins(AMOVW, &fxc2, &fxc1);
-                       } else {
-                               gins(AMOVW, &fxc2, &fxrat);
-                               fxc1 = fxrat;
-                               fxc1.type = nodrat->type;
-                               fxc1.etype = nodrat->etype;
-                               fxc1.xoffset += SZ_LONG;
-                               gins(AMOVW, &fxc0, &fxc1);
-                       }
-                       regfree(&fxc2);
-                       regfree(&fxc0);
-                       regalloc(&nod, t, t);   /* should be type float */
-                       gins(AFMOVD, &fxrat, &nod);
-                       nodreg(&fxc1, t, NREG+FREGCVI);
-                       gins(AFSUB, &fxc1, &nod);
-                       a = AFMOVD;
-                       if(tt == TFLOAT)
-                               a = AFRSP;
-                       gins(a, &nod, t);
-                       regfree(&nod);
-                       if(ft == TULONG) {
-                               regalloc(&nod, t, Z);
-                               if(tt == TFLOAT) {
-                                       gins(AFCMPU, t, Z);
-                                       p->to.type = D_FREG;
-                                       p->to.reg = FREGZERO;
-                                       gins(ABGE, Z, Z);
-                                       p1 = p;
-                                       gins(AFMOVS, nodfconst(4294967296.), &nod);
-                                       gins(AFADDS, &nod, t);
-                               } else {
-                                       gins(AFCMPU, t, Z);
-                                       p->to.type = D_FREG;
-                                       p->to.reg = FREGZERO;
-                                       gins(ABGE, Z, Z);
-                                       p1 = p;
-                                       gins(AFMOVD, nodfconst(4294967296.), &nod);
-                                       gins(AFADD, &nod, t);
-                               }
-                               patch(p1, pc);
-                               regfree(&nod);
-                       }
-                       return;
-               case TINT:
-               case TUINT:
-               case TLONG:
-               case TULONG:
-               case TVLONG:
-               case TUVLONG:
-               case TIND:
-               case TSHORT:
-               case TUSHORT:
-                       a = AMOVBZ;
-                       break;
-               case TCHAR:
-               case TUCHAR:
-                       a = AMOVD;
-                       break;
-               }
-               break;
-       }
-       if(a == AGOK)
-               diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type);
-       if(a == AMOVD || (a == AMOVW || a == AMOVWZ) && ewidth[ft] == ewidth[tt] || a == AFMOVS || a == AFMOVD)
-       if(samaddr(f, t))
-               return;
-       gins(a, f, t);
-}
-
-void
-gins(int a, Node *f, Node *t)
-{
-
-       nextpc();
-       p->as = a;
-       if(f != Z)
-               naddr(f, &p->from);
-       if(t != Z)
-               naddr(t, &p->to);
-       if(debug['g'])
-               print("%P\n", p);
-}
-
-void
-gopcode(int o, Node *f1, Node *f2, Node *t)
-{
-       int a, et;
-       Addr ta;
-       int uns;
-
-       uns = 0;
-       et = TLONG;
-       if(f1 != Z && f1->type != T) {
-               if(f1->op == OCONST && t != Z && t->type != T)
-                       et = t->type->etype;
-               else
-                       et = f1->type->etype;
-       }
-       a = AGOK;
-       switch(o) {
-       case OAS:
-               gmove(f1, t);
-               return;
-
-       case OASADD:
-       case OADD:
-               a = AADD;
-               if(et == TFLOAT)
-                       a = AFADDS;
-               else
-               if(et == TDOUBLE)
-                       a = AFADD;
-               break;
-
-       case OASSUB:
-       case OSUB:
-               a = ASUB;
-               if(et == TFLOAT)
-                       a = AFSUBS;
-               else
-               if(et == TDOUBLE)
-                       a = AFSUB;
-               break;
-
-       case OASOR:
-       case OOR:
-               a = AOR;
-               break;
-
-       case OASAND:
-       case OAND:
-               a = AAND;
-               if(f1->op == OCONST)
-                       a = AANDCC;
-               break;
-
-       case OASXOR:
-       case OXOR:
-               a = AXOR;
-               break;
-
-       case OASLSHR:
-       case OLSHR:
-               a = ASRW;
-               if(isv(et))
-                       a = ASRD;
-               break;
-
-       case OASASHR:
-       case OASHR:
-               a = ASRAW;
-               if(isv(et))
-                       a = ASRAD;
-               break;
-
-       case OASASHL:
-       case OASHL:
-               a = ASLW;
-               if(isv(et))
-                       a = ASLD;
-               break;
-
-       case OFUNC:
-               a = ABL;
-               break;
-
-       case OASLMUL:
-       case OLMUL:
-       case OASMUL:
-       case OMUL:
-               if(et == TFLOAT) {
-                       a = AFMULS;
-                       break;
-               } else
-               if(et == TDOUBLE) {
-                       a = AFMUL;
-                       break;
-               }
-               a = AMULLW;
-               if(isv(et))
-                       a = AMULLD;
-               break;
-
-       case OASDIV:
-       case ODIV:
-               if(et == TFLOAT) {
-                       a = AFDIVS;
-                       break;
-               } else
-               if(et == TDOUBLE) {
-                       a = AFDIV;
-                       break;
-               } else
-               a = ADIVW;
-               if(isv(et))
-                       a = ADIVD;
-               break;
-
-       case OASMOD:
-       case OMOD:
-               a = AREM;
-               if(isv(et))
-                       a = AREMD;
-               break;
-
-       case OASLMOD:
-       case OLMOD:
-               a = AREMU;
-               if(isv(et))
-                       a = AREMDU;
-               break;
-
-       case OASLDIV:
-       case OLDIV:
-               a = ADIVWU;
-               if(isv(et))
-                       a = ADIVDU;
-               break;
-
-       case OCOM:
-               a = ANOR;
-               break;
-
-       case ONEG:
-               a = ANEG;
-               if(et == TFLOAT || et == TDOUBLE)
-                       a = AFNEG;
-               break;
-
-       case OEQ:
-               a = ABEQ;
-               goto cmp;
-
-       case ONE:
-               a = ABNE;
-               goto cmp;
-
-       case OLT:
-               a = ABLT;
-               goto cmp;
-
-       case OLE:
-               a = ABLE;
-               goto cmp;
-
-       case OGE:
-               a = ABGE;
-               goto cmp;
-
-       case OGT:
-               a = ABGT;
-               goto cmp;
-
-       case OLO:
-               a = ABLT;
-               goto cmpu;
-
-       case OLS:
-               a = ABLE;
-               goto cmpu;
-
-       case OHS:
-               a = ABGE;
-               goto cmpu;
-
-       case OHI:
-               a = ABGT;
-               goto cmpu;
-
-       cmpu:
-               uns = 1;
-       cmp:
-               nextpc();
-               switch(et){
-               case TINT:
-               case TLONG:
-                       p->as = ACMPW;
-                       break;
-               case TUINT:
-               case TULONG:
-                       p->as = ACMPWU;
-                       break;
-               case TFLOAT:
-               case TDOUBLE:
-                       p->as = AFCMPU;
-                       break;
-               default:
-                       p->as = uns? ACMPU: ACMP;
-                       break;
-               }
-               if(f1 != Z)
-                       naddr(f1, &p->from);
-               if(t != Z)
-                       naddr(t, &p->to);
-               if(f1 == Z || t == Z || f2 != Z)
-                       diag(Z, "bad cmp in gopcode %O", o);
-               if(debug['g'])
-                       print("%P\n", p);
-               f1 = Z;
-               f2 = Z;
-               t = Z;
-               break;
-       }
-       if(a == AGOK)
-               diag(Z, "bad in gopcode %O", o);
-       nextpc();
-       p->as = a;
-       if(f1 != Z)
-               naddr(f1, &p->from);
-       if(f2 != Z) {
-               naddr(f2, &ta);
-               p->reg = ta.reg;
-               if(ta.type == D_CONST && ta.offset == 0) {
-                       if(R0ISZERO)
-                               p->reg = REGZERO;
-                       else
-                               diag(Z, "REGZERO in gopcode %O", o);
-               }
-       }
-       if(t != Z)
-               naddr(t, &p->to);
-       if(debug['g'])
-               print("%P\n", p);
-}
-
-int
-samaddr(Node *f, Node *t)
-{
-       return f->op == OREGISTER && t->op == OREGISTER && f->reg == t->reg;
-}
-
-void
-gbranch(int o)
-{
-       int a;
-
-       a = AGOK;
-       switch(o) {
-       case ORETURN:
-               a = ARETURN;
-               break;
-       case OGOTO:
-               a = ABR;
-               break;
-       }
-       nextpc();
-       if(a == AGOK) {
-               diag(Z, "bad in gbranch %O",  o);
-               nextpc();
-       }
-       p->as = a;
-}
-
-void
-patch(Prog *op, int32 pc)
-{
-
-       op->to.offset = pc;
-       op->to.type = D_BRANCH;
-}
-
-void
-gpseudo(int a, Sym *s, Node *n)
-{
-
-       nextpc();
-       p->as = a;
-       p->from.type = D_OREG;
-       p->from.sym = linksym(s);
-
-       switch(a) {
-       case ATEXT:
-               p->reg = textflag;
-               textflag = 0;
-               break;
-       case AGLOBL:
-               p->reg = s->dataflag;
-               break;
-       }
-
-       p->from.name = D_EXTERN;
-       if(s->class == CSTATIC)
-               p->from.name = D_STATIC;
-       naddr(n, &p->to);
-       if(a == ADATA || a == AGLOBL)
-               pc--;
-}
-
-int
-sval(int32 v)
-{
-
-       if(v >= -(1<<15) && v < (1<<15))
-               return 1;
-       return 0;
-}
-
-void
-gpcdata(int index, int value)
-{
-       Node n1;
-
-       n1 = *nodconst(index);
-       gins(APCDATA, &n1, nodconst(value));
-}
-
-void
-gprefetch(Node *n)
-{
-       // TODO(minux)
-       USED(n);
-       /*
-       Node n1;
-
-       regalloc(&n1, n, Z);
-       gmove(n, &n1);
-       n1.op = OINDREG;
-       gins(ADCBT, &n1, Z);
-       regfree(&n1);
-       */
-}
-
-
-int
-sconst(Node *n)
-{
-       vlong vv;
-
-       if(n->op == OCONST) {
-               if(!typefd[n->type->etype]) {
-                       vv = n->vconst;
-                       if(vv >= -(((vlong)1)<<15) && vv < (((vlong)1)<<15))
-                               return 1;
-               }
-       }
-       return 0;
-}
-
-int
-uconst(Node *n)
-{
-       vlong vv;
-
-       if(n->op == OCONST) {
-               if(!typefd[n->type->etype]) {
-                       vv = n->vconst;
-                       if(vv >= 0 && vv < (((vlong)1)<<16))
-                               return 1;
-               }
-       }
-       return 0;
-}
-
-int
-immconst(Node *n)
-{
-       vlong v;
-
-       if(n->op != OCONST || typefd[n->type->etype])
-               return 0;
-       v = n->vconst;
-       if((v & 0xFFFF) == 0)
-               v >>= 16;
-       if(v >= 0 && v < ((vlong)1<<16))
-               return 1;
-       if(v >= -((vlong)1<<15) && v <= ((vlong)1<<15))
-               return 1;
-       return 0;
-}
-
-int32
-exreg(Type *t)
-{
-       int32 o;
-
-       if(typechlpv[t->etype]) {
-               if(exregoffset <= 3)
-                       return 0;
-               o = exregoffset;
-               exregoffset--;
-               return o;
-       }
-       if(typefd[t->etype]) {
-               if(exfregoffset <= 16)
-                       return 0;
-               o = exfregoffset + NREG;
-               exfregoffset--;
-               return o;
-       }
-       return 0;
-}
-
-schar  ewidth[NTYPE] =
-{
-       -1,             /* [TXXX] */
-       SZ_CHAR,        /* [TCHAR] */
-       SZ_CHAR,        /* [TUCHAR] */
-       SZ_SHORT,       /* [TSHORT] */
-       SZ_SHORT,       /* [TUSHORT] */
-       SZ_INT,         /* [TINT] */
-       SZ_INT,         /* [TUINT] */
-       SZ_LONG,        /* [TLONG] */
-       SZ_LONG,        /* [TULONG] */
-       SZ_VLONG,       /* [TVLONG] */
-       SZ_VLONG,       /* [TUVLONG] */
-       SZ_FLOAT,       /* [TFLOAT] */
-       SZ_DOUBLE,      /* [TDOUBLE] */
-       SZ_IND,         /* [TIND] */
-       0,              /* [TFUNC] */
-       -1,             /* [TARRAY] */
-       0,              /* [TVOID] */
-       -1,             /* [TSTRUCT] */
-       -1,             /* [TUNION] */
-       SZ_INT,         /* [TENUM] */
-};
-int32  ncast[NTYPE] =
-{
-       0,                              /* [TXXX] */
-       BCHAR|BUCHAR,                   /* [TCHAR] */
-       BCHAR|BUCHAR,                   /* [TUCHAR] */
-       BSHORT|BUSHORT,                 /* [TSHORT] */
-       BSHORT|BUSHORT,                 /* [TUSHORT] */
-       BINT|BUINT|BLONG|BULONG,        /* [TINT] */
-       BINT|BUINT|BLONG|BULONG,        /* [TUINT] */
-       BINT|BUINT|BLONG|BULONG,        /* [TLONG] */
-       BINT|BUINT|BLONG|BULONG,        /* [TULONG] */
-       BVLONG|BUVLONG|BIND,                    /* [TVLONG] */
-       BVLONG|BUVLONG|BIND,                    /* [TUVLONG] */
-       BFLOAT,                         /* [TFLOAT] */
-       BDOUBLE,                        /* [TDOUBLE] */
-       BVLONG|BUVLONG|BIND,            /* [TIND] */
-       0,                              /* [TFUNC] */
-       0,                              /* [TARRAY] */
-       0,                              /* [TVOID] */
-       BSTRUCT,                        /* [TSTRUCT] */
-       BUNION,                         /* [TUNION] */
-       0,                              /* [TENUM] */
-};
index e3e50f28a9329f678539aad8a109ef9e9fe39380..51c132d183d1b5172d537e1a0bc1ff2082de80fd 100644 (file)
@@ -134,11 +134,12 @@ proginfo(ProgInfo *info, Prog *p)
        }
 
        if(p->as == ADUFFZERO) {
-               info->reguse |= RtoB(0) | RtoB(2);
-               info->regset |= RtoB(2);
+               info->reguse |= (1<<D_R0) | RtoB(3);
+               info->regset |= RtoB(3);
        }
        if(p->as == ADUFFCOPY) {
-               info->reguse |= RtoB(0) | RtoB(2) | RtoB(3);
-               info->regset |= RtoB(2) | RtoB(3);
+               // TODO(austin) Revisit when duffcopy is implemented
+               info->reguse |= RtoB(3) | RtoB(4) | RtoB(5);
+               info->regset |= RtoB(3) | RtoB(4);
        }
 }
index b911a23998364ebc75d46834f268cdde0748ebe2..2e546a95bb19dd605ccdd06958c4e38490e778e5 100644 (file)
@@ -1322,7 +1322,6 @@ void
 dumpit(char *str, Flow *r0, int isreg)
 {
        Flow *r, *r1;
-       int s1v, s2v;
 
        print("\n%s\n", str);
        for(r = r0; r != nil; r = r->link) {
@@ -1334,10 +1333,8 @@ dumpit(char *str, Flow *r0, int isreg)
                                print(" %.4ud", (int)r1->prog->pc);
                        print("\n");
                }
-               // If at least one successor is "interesting", print both
-               s1v = (r->s1 != nil) && (r->s1->prog != r->prog->link);
-               s2v = (r->s2 != nil) && (r->s2->prog != r->prog->link);
-               if(s1v || s2v) {
+               // Print successors if it's not just the next one
+               if(r->s1 != r->link || r->s2 != nil) {
                        print(" succ:");
                        if(r->s1 != nil)
                                print(" %.4ud", (int)r->s1->prog->pc);
index 08a339318de8ce54369b00c93aa4b90fa3fce773..87917f88ac6ac7e6676aa6ba83b892fad5ed0b1b 100644 (file)
@@ -497,6 +497,8 @@ enum
        D_DCONST,
        D_ADDR, // not used, use D_CONST with non-empty sym.
 
+       D_LAST,
+
 /* reg names for 9g OREGISTER */
        D_R0 = 0, // type is D_REG
        D_F0 = D_R0+NREG, // type is D_FREG
index 69c7ce893c3d1516c8fba1316f3c128c9bbd988a..6179c7afd19eb1d587c5bedce46d5b375c64834b 100644 (file)
@@ -152,7 +152,7 @@ In C, a function argument written as a fixed size array
 actually requires a pointer to the first element of the array.
 C compilers are aware of this calling convention and adjust
 the call accordingly, but Go cannot.  In Go, you must pass
-the pointer to the first element explicitly: C.f(&x[0]).
+the pointer to the first element explicitly: C.f(&C.x[0]).
 
 A few special functions convert between Go and C types
 by making copies of the data.  In pseudo-Go definitions:
index e4f307bee593a4089d5d59c1556f9ca8234c95c2..bfb3d15b826b9f2799106cb3accafe4de9d5c70a 100644 (file)
@@ -615,8 +615,6 @@ static struct {
        {"anames9.c", mkanames},
        {"zdefaultcc.go", mkzdefaultcc},
        {"zsys_", mkzsys},
-       {"zgoarch_", mkzgoarch},
-       {"zgoos_", mkzgoos},
        {"zversion.go", mkzversion},
        {"zaexperiment.h", mkzexperiment},
 
@@ -1419,12 +1417,13 @@ clean(void)
                        xremove(bpathf(&b, "%s/%s", bstr(&path), cleantab[i]+4));
        }
 
-       // remove src/runtime/z* unconditionally
+       // remove src/runtime/z* unconditionally,
+       // except leave zgoos and zgoarch, now maintained with go generate.
        vreset(&dir);
        bpathf(&path, "%s/src/runtime", goroot);
        xreaddir(&dir, bstr(&path));
        for(j=0; j<dir.len; j++) {
-               if(hasprefix(dir.p[j], "z"))
+               if(hasprefix(dir.p[j], "z") && !hasprefix(dir.p[j], "zg"))
                        xremove(bpathf(&b, "%s/%s", bstr(&path), dir.p[j]));
        }
 
index 1c3329758733a18ab591233b1d739d5b9b32fc25..64434d51e16852112ee26aa63a503a0b3fa7bdaf 100644 (file)
@@ -63,22 +63,36 @@ gcopnames(char *dir, char *file)
        vfree(&fields);
 }
 
+static int
+xatoi(char *s, char **end)
+{
+       int val = 0;
+       for(; *s && *s >= '0' && *s <= '9'; ++s)
+               val = val * 10 + (*s - '0');
+       *end = s;
+       return val;
+}
+
 // mkanames reads [5689].out.h and writes anames[5689].c
 // The format is much the same as the Go opcodes above.
-// it also writes out cnames array for C_* constants.
+// It also writes out cnames array for C_* constants and the dnames
+// array for D_* constants.
 void
 mkanames(char *dir, char *file)
 {
-       int i, j, ch;
+       int i, j, ch, n, unknown;
        Buf in, b, out, out2;
        Vec lines;
-       char *p;
+       char *p, *p2;
+       Vec dnames[128];
 
        binit(&b);
        binit(&in);
        binit(&out);
        binit(&out2);
        vinit(&lines);
+       for(i=0; i<nelem(dnames); i++)
+               vinit(&dnames[i]);
 
        ch = file[xstrlen(file)-3];
        bprintf(&b, "%s/../cmd/%cl/%c.out.h", dir, ch, ch);
@@ -87,10 +101,12 @@ mkanames(char *dir, char *file)
        
        // Include link.h so that the extern declaration there is
        // checked against the non-extern declaration we are generating.
+       bwritestr(&out, bprintf(&b, "// auto generated by go tool dist\n"));
        bwritestr(&out, bprintf(&b, "#include <u.h>\n"));
        bwritestr(&out, bprintf(&b, "#include <libc.h>\n"));
        bwritestr(&out, bprintf(&b, "#include <bio.h>\n"));
        bwritestr(&out, bprintf(&b, "#include <link.h>\n"));
+       bwritestr(&out, bprintf(&b, "#include \"../cmd/%cl/%c.out.h\"\n", ch, ch));
        bwritestr(&out, bprintf(&b, "\n"));
 
        bwritestr(&out, bprintf(&b, "char*      anames%c[] = {\n", ch));
@@ -127,6 +143,69 @@ mkanames(char *dir, char *file)
        if(j>0)
                bwriteb(&out, &out2);
 
+       j=unknown=0;
+       n=-1;
+       for(i=0; i<lines.len; i++) {
+               if(hasprefix(lines.p[i], "\tD_")) {
+                       p = xstrstr(lines.p[i], ",");
+                       if(p)
+                               *p = '\0';
+                       p = xstrstr(lines.p[i], "\n");
+                       if(p)
+                               *p = '\0';
+
+                       // Parse explicit value, if any
+                       p = xstrstr(lines.p[i], "=");
+                       if(p) {
+                               // Skip space after '='
+                               p2 = p + 1;
+                               while(*p2 == ' ' || *p2 == '\t')
+                                       p2++;
+                               n = xatoi(p2, &p2);
+                               // We can't do anything about
+                               // non-numeric values or anything that
+                               // follows
+                               while(*p2 == ' ' || *p2 == '\t')
+                                       p2++;
+                               if(*p2 != 0) {
+                                       unknown = 1;
+                                       continue;
+                               }
+                               // Truncate space before '='
+                               while(*(p-1) == ' ' || *(p-1) == '\t')
+                                       p--;
+                               *p = '\0';
+                               unknown = 0;
+                       } else {
+                               n++;
+                       }
+
+                       if(unknown || n >= nelem(dnames))
+                               continue;
+
+                       p = lines.p[i] + 3;
+                       if(xstrcmp(p, "LAST") == 0)
+                               continue;
+                       vadd(&dnames[n], p);
+                       j++;
+               }
+       }
+       if(j>0){
+               bwritestr(&out, bprintf(&b, "char*      dnames%c[D_LAST] = {\n", ch));
+               for(i=0; i<nelem(dnames); i++) {
+                       if(dnames[i].len == 0)
+                               continue;
+                       bwritestr(&out, bprintf(&b, "\t[D_%s] = \"", dnames[i].p[0]));
+                       for(j=0; j<dnames[i].len; j++) {
+                               if(j != 0)
+                                       bwritestr(&out, "/");
+                               bwritestr(&out, dnames[i].p[j]);
+                       }
+                       bwritestr(&out, "\",\n");
+               }
+               bwritestr(&out, "};\n");
+       }
+
        writefile(&out, file, 0);
 
        bfree(&b);
@@ -134,4 +213,6 @@ mkanames(char *dir, char *file)
        bfree(&out);
        bfree(&out2);
        vfree(&lines);
+       for(i=0; i<nelem(dnames); i++)
+               vfree(&dnames[i]);
 }
index e561937fb7282fbc4a23888a862e444b9bc30d97..38e99e11628fcd45d8d74b549365a9da93006d1e 100644 (file)
@@ -67,66 +67,6 @@ mkzexperiment(char *dir, char *file)
        bfree(&exp);
 }
 
-// mkzgoarch writes zgoarch_$GOARCH.go:
-//
-//     package runtime
-//     const theGoarch = <goarch>
-//
-void
-mkzgoarch(char *dir, char *file)
-{
-       Buf b, out;
-
-       USED(dir);
-       
-       binit(&b);
-       binit(&out);
-       
-       bwritestr(&out, bprintf(&b,
-               "// auto generated by go tool dist\n"
-               "\n"
-               "package runtime\n"
-               "\n"
-               "const theGoarch = `%s`\n", goarch));
-
-       writefile(&out, file, 0);
-       
-       bfree(&b);
-       bfree(&out);
-}
-
-// mkzgoos writes zgoos_$GOOS.go:
-//
-//     package runtime
-//     const theGoos = <goos>
-//
-void
-mkzgoos(char *dir, char *file)
-{
-       Buf b, out;
-
-       USED(dir);
-       
-       binit(&b);
-       binit(&out);
-
-       bwritestr(&out, "// auto generated by go tool dist\n\n");
-
-       if(streq(goos, "linux")) {
-               bwritestr(&out, "// +build !android\n\n");
-       }
-       
-       bwritestr(&out, bprintf(&b,
-               "package runtime\n"
-               "\n"
-               "const theGoos = `%s`\n", goos));
-
-       writefile(&out, file, 0);
-       
-       bfree(&b);
-       bfree(&out);
-}
-
 #define MAXWINCB 2000 /* maximum number of windows callbacks allowed */
 
 // mkzsys writes zsys_$GOOS_$GOARCH.s,
index 37bd62dead35c206d5b598ec6990f3ed190a10d9..0610893494b081a7cee5ff0473faffd114df3a70 100644 (file)
@@ -1776,7 +1776,6 @@ walkprint(Node *nn, NodeList **init)
        int notfirst, et, op;
        NodeList *calls;
 
-       on = nil;
        op = nn->op;
        all = nn->list;
        calls = nil;
index c96161e0f9d523965e87f1c11dbff93e73937b4f..3f11c3e3d44a4c9cb70d56749f72570c7c4a3324 100644 (file)
@@ -47,7 +47,7 @@ const toolWindowsExtension = ".exe"
 
 func tool(toolName string) string {
        toolPath := filepath.Join(toolDir, toolName)
-       if toolIsWindows && toolName != "pprof" {
+       if toolIsWindows {
                toolPath += toolWindowsExtension
        }
        // Give a nice message if there is no tool with that name.
@@ -91,16 +91,6 @@ func runTool(cmd *Command, args []string) {
        if toolPath == "" {
                return
        }
-       if toolIsWindows && toolName == "pprof" {
-               args = append([]string{"perl", toolPath}, args[1:]...)
-               var err error
-               toolPath, err = exec.LookPath("perl")
-               if err != nil {
-                       fmt.Fprintf(os.Stderr, "go tool: perl not found\n")
-                       setExitStatus(3)
-                       return
-               }
-       }
        if toolN {
                fmt.Printf("%s %s\n", toolPath, strings.Join(args[1:], " "))
                return
index a1d773023dc551bbfd4103b3b186e3b128306d34..6b1607a1725a5b598bb0f1fcbac2cb77080db9c0 100644 (file)
@@ -7,7 +7,7 @@
 package objfile
 
 import (
-       "debug/goobj"
+       "cmd/internal/goobj"
        "fmt"
        "os"
 )
index f9228e8cab179d0e1771e691f0afb42c0f89d8a9..21f6d6082722d923beb93b47a797e246ebcb8908 100644 (file)
@@ -10,7 +10,7 @@
 package main
 
 import (
-       "debug/goobj"
+       "cmd/internal/goobj"
        "strconv"
        "strings"
 )
index 27f8e2b96d63b38ff430158b7c8168dd0b07a58c..f99e097a9c382f3d936beadd05b41855e86437ab 100644 (file)
@@ -13,7 +13,7 @@ package main
 
 import (
        "bytes"
-       "debug/goobj"
+       "cmd/internal/goobj"
        "testing"
 )
 
index e1e775eb3be4ebd28e462e884170d4c2e42ad4ce..ee23a61f81f96c097fc367e3e4e603bf6b848611 100644 (file)
@@ -6,7 +6,7 @@
 
 package main
 
-import "debug/goobj"
+import "cmd/internal/goobj"
 
 // dead removes unreachable code and data from the program.
 // It is basically a mark-sweep garbage collection: traverse all the
index 2e179b453b1d5a8af8accd6813f66f07141e5b69..eb34d0580d1889e486ee29c220d01b4f7c1b5c2b 100644 (file)
@@ -5,7 +5,7 @@
 package main
 
 import (
-       "debug/goobj"
+       "cmd/internal/goobj"
        "reflect"
        "strings"
        "testing"
index 149ebced0fd2e931ae1aa4eb56eeb52196234a3d..d5c291e255370ff36ed1bb8eb45fa6e09545ecc0 100644 (file)
@@ -7,7 +7,7 @@
 package main
 
 import (
-       "debug/goobj"
+       "cmd/internal/goobj"
 )
 
 // A layoutSection describes a single section to add to the
index 984796784e7c40cb017012c22e00061fe4964066..b5ae15fc7108a008fd44096895ef3e7e053eef2c 100644 (file)
@@ -6,7 +6,7 @@ package main
 
 import (
        "bytes"
-       "debug/goobj"
+       "cmd/internal/goobj"
        "io/ioutil"
        "testing"
 )
index 232d586bf28ec1529ac8f55f331b76df28a7248c..2d131781f2badbc4a045548432290589d023c064 100644 (file)
@@ -7,7 +7,7 @@
 package main
 
 import (
-       "debug/goobj"
+       "cmd/internal/goobj"
        "encoding/binary"
        "os"
        "sort"
index 19953f5797b238e93a4a07a9cd9a0a1a657650bd..ea808067427e0b98e65b97d354d5768c8e170d77 100644 (file)
@@ -6,7 +6,7 @@ package main
 
 import (
        "bytes"
-       "debug/goobj"
+       "cmd/internal/goobj"
        "fmt"
        "math/rand"
        "sort"
index a52b5ff9b214d2a5a44bd4963e0c9665fe3a7ac0..77fb1ece5b1685c09358973870dadf7001830621 100644 (file)
@@ -5,7 +5,7 @@
 package main
 
 import (
-       "debug/goobj"
+       "cmd/internal/goobj"
        "encoding/binary"
        "fmt"
        "go/build"
index b0c1ac98a68eeca2b1185f2be7b6b203d5568b46..acda2d24d6c6cc0c5ecbc8dc0099ce2b0057b315 100644 (file)
@@ -7,7 +7,7 @@
 
 package main
 
-import "debug/goobj"
+import "cmd/internal/goobj"
 
 func (p *Prog) runtime() {
        p.pclntab()
index 0720e039b83c1df6c668cf969e930e8232c0194e..7feb0d89002abf0b25c522fb79bf35032079f19d 100644 (file)
@@ -11,7 +11,7 @@
 package main
 
 import (
-       "debug/goobj"
+       "cmd/internal/goobj"
        "os"
        "sort"
        "strings"
@@ -69,7 +69,7 @@ func (p *Prog) scanFile(pkgpath string, file string) {
                return
        }
 
-       // TODO(rsc): Change debug/goobj to record package name as gp.Name.
+       // TODO(rsc): Change cmd/internal/goobj to record package name as gp.Name.
        // TODO(rsc): If pkgpath == "main", check that gp.Name == "main".
 
        pkg.Package = gp
index 57300dd91a8d4e9a179a0f856c29c0aa08b2b8b7..73ae1b4ea2efadf747beab8629dff90cd7a72acc 100644 (file)
@@ -358,9 +358,13 @@ func getFunctionSource(fun, file string, fns nodes, start, end int) (nodes, stri
        for {
                line, err := buf.ReadString('\n')
                if err != nil {
-                       if line == "" || err != io.EOF {
+                       if err != io.EOF {
                                return nil, file, err
                        }
+                       if line == "" {
+                               // end was at or past EOF; that's okay
+                               break
+                       }
                }
                if lineno >= start {
                        flat, cum := sumNodes(lineNodes[lineno])
index c65f626ac8bfb6fd2111735b7645abf82614ea77..f77d6c0c57f79e386349801cb57ed2baa88e3c3c 100644 (file)
@@ -16,6 +16,7 @@ var certFiles = []string{
        "/etc/ssl/cert.pem",                      // OpenBSD
        "/usr/local/share/certs/ca-root-nss.crt", // FreeBSD/DragonFly
        "/etc/pki/tls/cacert.pem",                // OpenELEC
+       "/etc/certs/ca-certificates.crt",         // Solaris 11.2+
 }
 
 // Possible directories with certificate files; stop after successfully
index 48fb53e5b0d80951f0a431b2e9d81bb93c1a0526..1a08d5a6b1181f8e66f2bef1bb061e5b536b5a9a 100644 (file)
@@ -34,11 +34,9 @@ import (
 
 const testdata = "testdata"
 
-var fsetErrs = token.NewFileSet()
-
 // getFile assumes that each filename occurs at most once
-func getFile(filename string) (file *token.File) {
-       fsetErrs.Iterate(func(f *token.File) bool {
+func getFile(fset *token.FileSet, filename string) (file *token.File) {
+       fset.Iterate(func(f *token.File) bool {
                if f.Name() == filename {
                        if file != nil {
                                panic(filename + " used multiple times")
@@ -50,8 +48,8 @@ func getFile(filename string) (file *token.File) {
        return file
 }
 
-func getPos(filename string, offset int) token.Pos {
-       if f := getFile(filename); f != nil {
+func getPos(fset *token.FileSet, filename string, offset int) token.Pos {
+       if f := getFile(fset, filename); f != nil {
                return f.Pos(offset)
        }
        return token.NoPos
@@ -68,14 +66,14 @@ var errRx = regexp.MustCompile(`^/\* *ERROR *(HERE)? *"([^"]*)" *\*/$`)
 // expectedErrors collects the regular expressions of ERROR comments found
 // in files and returns them as a map of error positions to error messages.
 //
-func expectedErrors(t *testing.T, filename string, src []byte) map[token.Pos]string {
+func expectedErrors(t *testing.T, fset *token.FileSet, filename string, src []byte) map[token.Pos]string {
        errors := make(map[token.Pos]string)
 
        var s scanner.Scanner
        // file was parsed already - do not add it again to the file
        // set otherwise the position information returned here will
        // not match the position information collected by the parser
-       s.Init(getFile(filename), src, nil, scanner.ScanComments)
+       s.Init(getFile(fset, filename), src, nil, scanner.ScanComments)
        var prev token.Pos // position of last non-comment, non-semicolon token
        var here token.Pos // position immediately after the token at position prev
 
@@ -109,11 +107,11 @@ func expectedErrors(t *testing.T, filename string, src []byte) map[token.Pos]str
 // compareErrors compares the map of expected error messages with the list
 // of found errors and reports discrepancies.
 //
-func compareErrors(t *testing.T, expected map[token.Pos]string, found scanner.ErrorList) {
+func compareErrors(t *testing.T, fset *token.FileSet, expected map[token.Pos]string, found scanner.ErrorList) {
        for _, error := range found {
                // error.Pos is a token.Position, but we want
                // a token.Pos so we can do a map lookup
-               pos := getPos(error.Pos.Filename, error.Pos.Offset)
+               pos := getPos(fset, error.Pos.Filename, error.Pos.Offset)
                if msg, found := expected[pos]; found {
                        // we expect a message at pos; check if it matches
                        rx, err := regexp.Compile(msg)
@@ -140,7 +138,7 @@ func compareErrors(t *testing.T, expected map[token.Pos]string, found scanner.Er
        if len(expected) > 0 {
                t.Errorf("%d errors not reported:", len(expected))
                for pos, msg := range expected {
-                       t.Errorf("%s: %s\n", fsetErrs.Position(pos), msg)
+                       t.Errorf("%s: %s\n", fset.Position(pos), msg)
                }
        }
 }
@@ -152,7 +150,8 @@ func checkErrors(t *testing.T, filename string, input interface{}) {
                return
        }
 
-       _, err = ParseFile(fsetErrs, filename, src, DeclarationErrors|AllErrors)
+       fset := token.NewFileSet()
+       _, err = ParseFile(fset, filename, src, DeclarationErrors|AllErrors)
        found, ok := err.(scanner.ErrorList)
        if err != nil && !ok {
                t.Error(err)
@@ -162,10 +161,10 @@ func checkErrors(t *testing.T, filename string, input interface{}) {
 
        // we are expecting the following errors
        // (collect these after parsing a file so that it is found in the file set)
-       expected := expectedErrors(t, filename, src)
+       expected := expectedErrors(t, fset, filename, src)
 
        // verify errors returned by the parser
-       compareErrors(t, expected, found)
+       compareErrors(t, fset, expected, found)
 }
 
 func TestErrors(t *testing.T) {
index 85065fd1829c995be20f647f03d7bb80f86dc070..51ce1a9337ee1fb8ae689c905dc76a87a954fed4 100644 (file)
@@ -14,8 +14,6 @@ import (
        "testing"
 )
 
-var fset = token.NewFileSet()
-
 var validFiles = []string{
        "parser.go",
        "parser_test.go",
@@ -25,7 +23,7 @@ var validFiles = []string{
 
 func TestParse(t *testing.T) {
        for _, filename := range validFiles {
-               _, err := ParseFile(fset, filename, nil, DeclarationErrors)
+               _, err := ParseFile(token.NewFileSet(), filename, nil, DeclarationErrors)
                if err != nil {
                        t.Fatalf("ParseFile(%s): %v", filename, err)
                }
@@ -46,7 +44,7 @@ func dirFilter(f os.FileInfo) bool { return nameFilter(f.Name()) }
 
 func TestParseDir(t *testing.T) {
        path := "."
-       pkgs, err := ParseDir(fset, path, dirFilter, 0)
+       pkgs, err := ParseDir(token.NewFileSet(), path, dirFilter, 0)
        if err != nil {
                t.Fatalf("ParseDir(%s): %v", path, err)
        }
@@ -131,7 +129,7 @@ func TestParseExpr(t *testing.T) {
 }
 
 func TestColonEqualsScope(t *testing.T) {
-       f, err := ParseFile(fset, "", `package p; func f() { x, y, z := x, y, z }`, 0)
+       f, err := ParseFile(token.NewFileSet(), "", `package p; func f() { x, y, z := x, y, z }`, 0)
        if err != nil {
                t.Fatal(err)
        }
@@ -153,7 +151,7 @@ func TestColonEqualsScope(t *testing.T) {
 }
 
 func TestVarScope(t *testing.T) {
-       f, err := ParseFile(fset, "", `package p; func f() { var x, y, z = x, y, z }`, 0)
+       f, err := ParseFile(token.NewFileSet(), "", `package p; func f() { var x, y, z = x, y, z }`, 0)
        if err != nil {
                t.Fatal(err)
        }
@@ -183,7 +181,7 @@ var x int
 func f() { L: }
 `
 
-       f, err := ParseFile(fset, "", src, 0)
+       f, err := ParseFile(token.NewFileSet(), "", src, 0)
        if err != nil {
                t.Fatal(err)
        }
@@ -221,7 +219,7 @@ func f() { L: }
 }
 
 func TestUnresolved(t *testing.T) {
-       f, err := ParseFile(fset, "", `
+       f, err := ParseFile(token.NewFileSet(), "", `
 package p
 //
 func f1a(int)
@@ -316,7 +314,7 @@ var imports = map[string]bool{
 func TestImports(t *testing.T) {
        for path, isValid := range imports {
                src := fmt.Sprintf("package p; import %s", path)
-               _, err := ParseFile(fset, "", src, 0)
+               _, err := ParseFile(token.NewFileSet(), "", src, 0)
                switch {
                case err != nil && isValid:
                        t.Errorf("ParseFile(%s): got %v; expected no error", src, err)
@@ -327,7 +325,7 @@ func TestImports(t *testing.T) {
 }
 
 func TestCommentGroups(t *testing.T) {
-       f, err := ParseFile(fset, "", `
+       f, err := ParseFile(token.NewFileSet(), "", `
 package p /* 1a */ /* 1b */      /* 1c */ // 1d
 /* 2a
 */
@@ -421,7 +419,7 @@ func checkFieldComments(t *testing.T, file *ast.File, fieldname, lead, line stri
 }
 
 func TestLeadAndLineComments(t *testing.T) {
-       f, err := ParseFile(fset, "", `
+       f, err := ParseFile(token.NewFileSet(), "", `
 package p
 type T struct {
        /* F1 lead comment */
index a2a21a06f950bf722f78adf70a46867b2c0d9042..6a6b9473bea45b9db127a5c03eb0809f061e9147 100644 (file)
@@ -17,8 +17,8 @@ const Size = 4
 
 // Predefined polynomials.
 const (
-       // Far and away the most common CRC-32 polynomial.
-       // Used by ethernet (IEEE 802.3), v.42, fddi, gzip, zip, png, mpeg-2, ...
+       // IEEE is by far and away the most common CRC-32 polynomial.
+       // Used by ethernet (IEEE 802.3), v.42, fddi, gzip, zip, png, ...
        IEEE = 0xedb88320
 
        // Castagnoli's polynomial, used in iSCSI.
index c8fae3cea96562be1f184a730e28bb22ad88ec2d..6d8b1d1d036c84b57e53e937f780b8663d999fa3 100644 (file)
@@ -143,6 +143,9 @@ func (d *decoder) fill() error {
        // Fill in the rest of the buffer.
        n, err := d.r.Read(d.bytes.buf[d.bytes.j:])
        d.bytes.j += n
+       if n > 0 {
+               err = nil
+       }
        return err
 }
 
index 93f4adab9dc88dac047b00e4da888bedbcae1b07..4de2e8ee7371585bdd625a7bb03c094845623ff9 100644 (file)
@@ -9,6 +9,7 @@ import (
        "fmt"
        "image"
        "image/color"
+       "io"
        "io/ioutil"
        "math/rand"
        "os"
@@ -88,6 +89,51 @@ func decodeFile(filename string) (image.Image, error) {
        return Decode(f)
 }
 
+type eofReader struct {
+       data     []byte // deliver from Read without EOF
+       dataEOF  []byte // then deliver from Read with EOF on last chunk
+       lenAtEOF int
+}
+
+func (r *eofReader) Read(b []byte) (n int, err error) {
+       if len(r.data) > 0 {
+               n = copy(b, r.data)
+               r.data = r.data[n:]
+       } else {
+               n = copy(b, r.dataEOF)
+               r.dataEOF = r.dataEOF[n:]
+               if len(r.dataEOF) == 0 {
+                       err = io.EOF
+                       if r.lenAtEOF == -1 {
+                               r.lenAtEOF = n
+                       }
+               }
+       }
+       return
+}
+
+func TestDecodeEOF(t *testing.T) {
+       // Check that if reader returns final data and EOF at same time, jpeg handles it.
+       data, err := ioutil.ReadFile("../testdata/video-001.jpeg")
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       n := len(data)
+       for i := 0; i < n; {
+               r := &eofReader{data[:n-i], data[n-i:], -1}
+               _, err := Decode(r)
+               if err != nil {
+                       t.Errorf("Decode with Read() = %d, EOF: %v", r.lenAtEOF, err)
+               }
+               if i == 0 {
+                       i = 1
+               } else {
+                       i *= 2
+               }
+       }
+}
+
 // check checks that the two pix data are equal, within the given bounds.
 func check(bounds image.Rectangle, pix0, pix1 []byte, stride0, stride1 int) error {
        if stride0 <= 0 || stride0%8 != 0 {
index 0635fdf1feb55d45c65cabd6f8a639c7e7417225..ff22273c4a36cb39a272df94aa18f6aa20414a89 100644 (file)
@@ -82,6 +82,19 @@ Pconv(Fmt *fp)
 
        p = va_arg(fp->args, Prog*);
        bigP = p;
+
+       if(fp->flags & FmtSharp) {
+               char *s = str;
+               s += sprint(s, "%.5lld (%L) %A", p->pc, p->lineno, p->as);
+               if(p->from.type != D_NONE)
+                       s += sprint(s, " from={%#D}", &p->from);
+               if(p->reg)
+                       s += sprint(s, " reg=%d", p->reg);
+               if(p->to.type != D_NONE)
+                       sprint(s, " to={%#D}", &p->to);
+               return fmtstrcpy(fp, str);
+       }
+
        switch(p->as) {
        case ADATA:
                sprint(str, "%.5lld (%L)        %A      %D/%d,%D",
@@ -126,6 +139,31 @@ Dconv(Fmt *fp)
        a = va_arg(fp->args, Addr*);
        i = a->type;
 
+       if(fp->flags & FmtSharp) {
+               char *s = str;
+               s += sprint(s, "type=");
+               if(i == D_NONE) {
+                       sprint(s, "NONE");
+                       goto brk;
+               }
+               if(i >= D_INDIR) {
+                       i -= D_INDIR;
+                       s += sprint(s, "INDIR+");
+               }
+               if(i >= 0 && i < D_LAST && dnames6[i] != nil)
+                       s += sprint(s, "%s ", dnames6[i]);
+               else
+                       s += sprint(s, "%d ", i);
+               s += sprint(s, "offset=%lld etype=%E width=%lld", a->offset, a->etype, a->width);
+               if(a->class != 0)
+                       s += sprint(s, " class=%s", cnames9[(int)a->class]);
+               if(a->sym != nil)
+                       s += sprint(s, " sym=%s", a->sym->name);
+               if(a->type == D_BRANCH && a->u.branch != nil)
+                       sprint(s, " branch=%.5lld", a->u.branch->pc);
+               goto brk;
+       }
+
        if(fp->flags & FmtLong) {
                if(i == D_CONST)
                        sprint(str, "$%lld-%lld", a->offset&0xffffffffLL, a->offset>>32);
index 512ed5a1199125239c9971d7b1c4e56fe7ed936a..32fcf8f87bbc4733ecf3c0b023cdd60b11798f96 100644 (file)
@@ -91,6 +91,21 @@ Pconv(Fmt *fp)
        p = va_arg(fp->args, Prog*);
        bigP = p;
        a = p->as;
+
+       if(fp->flags & FmtSharp) {
+               s = str;
+               s += sprint(s, "%.5lld (%L) %A", p->pc, p->lineno, a);
+               if(p->from.type != D_NONE)
+                       s += sprint(s, " from={%#D}", &p->from);
+               if(p->reg)
+                       s += sprint(s, " reg=%d", p->reg);
+               if(p->from3.type != D_NONE)
+                       s += sprint(s, " from3={%#D}", &p->from3);
+               if(p->to.type != D_NONE)
+                       sprint(s, " to={%#D}", &p->to);
+               return fmtstrcpy(fp, str);
+       }
+
        if(a == ADATA || a == AINIT || a == ADYNT)
                sprint(str, "%.5lld (%L)        %A      %D/%d,%D", p->pc, p->lineno, a, &p->from, p->reg, &p->to);
        else if(a == ATEXT) {
@@ -153,6 +168,32 @@ Dconv(Fmt *fp)
 
        a = va_arg(fp->args, Addr*);
 
+       if(fp->flags & FmtSharp) {
+               char *s = str;
+               if(a->type == D_NONE) {
+                       sprint(s, "type=NONE");
+                       goto ret;
+               }
+               if(a->type >= 0 && a->type < D_LAST && dnames9[a->type] != nil)
+                       s += sprint(s, "type=%s ", dnames9[a->type]);
+               else
+                       s += sprint(s, "type=%d ", a->type);
+               if(a->name >= 0 && a->name < D_LAST && dnames9[(int)a->name] != nil)
+                       s += sprint(s, "name=%s ", dnames9[(int)a->name]);
+               else
+                       s += sprint(s, "name=%d ", a->name);
+               s += sprint(s, "offset=%lld etype=%E width=%lld", a->offset, a->etype, a->width);
+               if(a->class != 0)
+                       s += sprint(s, " class=%s", cnames9[(int)a->class]);
+               if(a->reg != NREG)
+                       s += sprint(s, " reg=%d", a->reg);
+               if(a->sym != nil)
+                       s += sprint(s, " sym=%s", a->sym->name);
+               if(a->type == D_BRANCH && a->u.branch != nil)
+                       sprint(s, " branch=%.5lld", a->u.branch->pc);
+               goto ret;
+       }
+
        if(fp->flags & FmtLong) {
                if(a->type == D_CONST)
                        sprint(str, "$%d-%d", (int32)a->offset, (int32)(a->offset>>32));
index 7bd777b712da9ff5961ea28dacd9f1c204ea28b7..e322f710a5d95361e9e6c0055641137b1b05b65d 100644 (file)
@@ -22,8 +22,12 @@ import (
        "time"
 )
 
-// A Dir implements http.FileSystem using the native file
-// system restricted to a specific directory tree.
+// A Dir implements FileSystem using the native file system restricted to a
+// specific directory tree.
+//
+// While the FileSystem.Open method takes '/'-separated paths, a Dir's string
+// value is a filename on the native file system, not a URL, so it is separated
+// by filepath.Separator, which isn't necessarily '/'.
 //
 // An empty Dir is treated as ".".
 type Dir string
index 56c5dc696a20e747c140c62a0536c65023d18397..e55c1aa166ea5ceab78004c87cae3fdb0f4f9816 100644 (file)
@@ -7,7 +7,10 @@ package url_test
 import (
        "fmt"
        "log"
+       "net/http"
+       "net/http/httputil"
        "net/url"
+       "strings"
 )
 
 func ExampleValues() {
@@ -39,3 +42,30 @@ func ExampleURL() {
        fmt.Println(u)
        // Output: https://google.com/search?q=golang
 }
+
+func ExampleURL_opaque() {
+       // Sending a literal '%' in an HTTP request's Path
+       req := &http.Request{
+               Method: "GET",
+               Host:   "example.com", // takes precendence over URL.Host
+               URL: &url.URL{
+                       Host:   "ignored",
+                       Scheme: "https",
+                       Opaque: "/%2f/",
+               },
+               Header: http.Header{
+                       "User-Agent": {"godoc-example/0.1"},
+               },
+       }
+       out, err := httputil.DumpRequestOut(req, true)
+       if err != nil {
+               log.Fatal(err)
+       }
+       fmt.Println(strings.Replace(string(out), "\r", "", -1))
+       // Output:
+       // GET /%2f/ HTTP/1.1
+       // Host: example.com
+       // User-Agent: godoc-example/0.1
+       // Accept-Encoding: gzip
+       //
+}
index 329a90e01294076d07f12086237d8b8669234fd7..cea7d9e04fec70ac66435c0aae94398b07a57ba2 100644 (file)
@@ -39,7 +39,7 @@ const (
        OpEmptyMatch                   // matches empty string
        OpLiteral                      // matches Runes sequence
        OpCharClass                    // matches Runes interpreted as range pair list
-       OpAnyCharNotNL                 // matches any character
+       OpAnyCharNotNL                 // matches any character except newline
        OpAnyChar                      // matches any character
        OpBeginLine                    // matches empty string at beginning of line
        OpEndLine                      // matches empty string at end of line
index 54b209591a6637b7c33d034fe1e7d63ef77f1ee7..b8ce417a0a823089fc13102d8ff589a67fe8c4a5 100755 (executable)
@@ -64,18 +64,6 @@ echo
 echo '# sync -cpu=10'
 go test sync -short -timeout=$(expr 120 \* $timeout_scale)s -cpu=10
 
-# Race detector only supported on Linux, FreeBSD and OS X,
-# and only on amd64, and only when cgo is enabled.
-# DISABLED until we get garbage collection working.
-case "$GOHOSTOS-$GOOS-$GOARCH-$CGO_ENABLED-XXX-DISABLED" in
-linux-linux-amd64-1 | freebsd-freebsd-amd64-1 | darwin-darwin-amd64-1)
-       echo
-       echo '# Testing race detector.'
-       go test -race -i runtime/race flag
-       go test -race -run=Output runtime/race
-       go test -race -short flag
-esac
-
 xcd() {
        echo
        echo '#' $1
@@ -121,6 +109,7 @@ go run $GOROOT/test/run.go - . || exit 1
 [ "$CGO_ENABLED" != 1 ] ||
 (xcd ../misc/cgo/test
 # cgo tests inspect the traceback for runtime functions
+extlink=0
 export GOTRACEBACK=2
 go test -ldflags '-linkmode=auto' || exit 1
 # linkmode=internal fails on dragonfly since errno is a TLS relocation.
@@ -129,19 +118,24 @@ case "$GOHOSTOS-$GOARCH" in
 openbsd-386 | openbsd-amd64)
        # test linkmode=external, but __thread not supported, so skip testtls.
        go test -ldflags '-linkmode=external' || exit 1
+       extlink=1
        ;;
 darwin-386 | darwin-amd64)
        # linkmode=external fails on OS X 10.6 and earlier == Darwin
        # 10.8 and earlier.
        case $(uname -r) in
        [0-9].* | 10.*) ;;
-       *) go test -ldflags '-linkmode=external'  || exit 1;;
+       *)
+               go test -ldflags '-linkmode=external'  || exit 1
+               extlink=1
+               ;;
        esac
        ;;
 android-arm | dragonfly-386 | dragonfly-amd64 | freebsd-386 | freebsd-amd64 | freebsd-arm | linux-386 | linux-amd64 | linux-arm | netbsd-386 | netbsd-amd64)
        go test -ldflags '-linkmode=external' || exit 1
        go test -ldflags '-linkmode=auto' ../testtls || exit 1
        go test -ldflags '-linkmode=external' ../testtls || exit 1
+       extlink=1
        
        case "$GOHOSTOS-$GOARCH" in
        netbsd-386 | netbsd-amd64) ;; # no static linking
@@ -165,6 +159,24 @@ android-arm | dragonfly-386 | dragonfly-amd64 | freebsd-386 | freebsd-amd64 | fr
 esac
 ) || exit $?
 
+# Race detector only supported on Linux, FreeBSD and OS X,
+# and only on amd64, and only when cgo is enabled.
+# Delayed until here so we know whether to try external linking.
+# DISABLED until we get garbage collection working.
+case "$GOHOSTOS-$GOOS-$GOARCH-$CGO_ENABLED-XXX-DISABLED" in
+linux-linux-amd64-1 | freebsd-freebsd-amd64-1 | darwin-darwin-amd64-1)
+       echo
+       echo '# Testing race detector.'
+       go test -race -i runtime/race flag os/exec
+       go test -race -run=Output runtime/race
+       go test -race -short flag os/exec
+       
+       # Test with external linking; see issue 9133.
+       if [ "$extlink" = 1 ]; then
+               go test -race -short -ldflags=-linkmode=external flag os/exec
+       fi
+esac
+
 # This tests cgo -cdefs. That mode is not supported,
 # so it's okay if it doesn't work on some systems.
 # In particular, it works badly with clang on OS X.
index 14c1b45fdad40a09fd2bdd837c9c41db603ddee8..efa97662f875466be70b8cd965a6f58984fb6300 100644 (file)
@@ -134,9 +134,11 @@ if %FAIL%==1 goto fail
 set GOMAXPROCS=%OLDGOMAXPROCS%
 set OLDGOMAXPROCS=
 
-echo # Checking API compatibility.
-go run "%GOROOT%\src\cmd\api\run.go"
-if errorlevel 1 goto fail
+:: echo # Checking API compatibility.
+:: go run "%GOROOT%\src\cmd\api\run.go"
+:: if errorlevel 1 goto fail
+:: echo.
+echo # SKIPPING API COMPATIBILITY UNTIL ALL SYSTEMS BUILD.
 echo.
 
 echo ALL TESTS PASSED
index 7746dfbf061844428c556f47c840d2e4142ea990..a73e207eddce825ef40d28884d743daa07d975df 100644 (file)
@@ -9,7 +9,7 @@ const (
        _BigEndian        = 0
        _CacheLineSize    = 64
        _RuntimeGogoBytes = 64
-       _PhysPageSize     = _NaCl*65536 + (1-_NaCl)*4096 // 4k normally; 64k on NaCl
+       _PhysPageSize     = goos_nacl*65536 + (1-goos_nacl)*4096 // 4k normally; 64k on NaCl
        _PCQuantum        = 1
        _Int64Align       = 4
 )
index 83c9c2dc9c623ce8bb523557d15a6d636323e476..794b7f65c4899c0b716e91d110aee7bae140db41 100644 (file)
@@ -8,7 +8,7 @@ const (
        thechar           = '6'
        _BigEndian        = 0
        _CacheLineSize    = 64
-       _RuntimeGogoBytes = 64 + (_Plan9|_Solaris|_Windows)*16
+       _RuntimeGogoBytes = 64 + (goos_plan9|goos_solaris|goos_windows)*16
        _PhysPageSize     = 4096
        _PCQuantum        = 1
        _Int64Align       = 8
diff --git a/src/runtime/arch1_amd64p32.go b/src/runtime/arch1_amd64p32.go
new file mode 100644 (file)
index 0000000..2cee21f
--- /dev/null
@@ -0,0 +1,15 @@
+// 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.
+
+package runtime
+
+const (
+       thechar           = '6'
+       _BigEndian        = 0
+       _CacheLineSize    = 64
+       _RuntimeGogoBytes = 64
+       _PhysPageSize     = 65536*goos_nacl + 4096*(1-goos_nacl)
+       _PCQuantum        = 1
+       _Int64Align       = 8
+)
index 5cb79fd686e7dfbe49e2cfdd544742d64d446ab1..6662eaeac396a8938aa1daf412eb592abd2f98e7 100644 (file)
@@ -9,7 +9,7 @@ const (
        _BigEndian        = 0
        _CacheLineSize    = 32
        _RuntimeGogoBytes = 60
-       _PhysPageSize     = 65536*_NaCl + 4096*(1-_NaCl)
+       _PhysPageSize     = 65536*goos_nacl + 4096*(1-goos_nacl)
        _PCQuantum        = 4
        _Int64Align       = 4
 )
diff --git a/src/runtime/arch1_power64.go b/src/runtime/arch1_power64.go
new file mode 100644 (file)
index 0000000..01e2b70
--- /dev/null
@@ -0,0 +1,15 @@
+// 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
+
+const (
+       thechar           = '9'
+       _BigEndian        = 1
+       _CacheLineSize    = 64
+       _RuntimeGogoBytes = 64
+       _PhysPageSize     = 65536
+       _PCQuantum        = 4
+       _Int64Align       = 8
+)
diff --git a/src/runtime/arch1_power64le.go b/src/runtime/arch1_power64le.go
new file mode 100644 (file)
index 0000000..6580732
--- /dev/null
@@ -0,0 +1,15 @@
+// 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
+
+const (
+       thechar           = '9'
+       _BigEndian        = 0
+       _CacheLineSize    = 64
+       _RuntimeGogoBytes = 64
+       _PhysPageSize     = 65536
+       _PCQuantum        = 4
+       _Int64Align       = 8
+)
diff --git a/src/runtime/arch_amd64p32.h b/src/runtime/arch_amd64p32.h
deleted file mode 100644 (file)
index d3e8649..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// 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.
-
-enum {
-       thechar = '6',
-       BigEndian = 0,
-       CacheLineSize = 64,
-       RuntimeGogoBytes = 64,
-#ifdef GOOS_nacl
-       PhysPageSize = 65536,
-#else
-       PhysPageSize = 4096,
-#endif
-       PCQuantum = 1,
-       Int64Align = 8
-};
diff --git a/src/runtime/arch_power64.h b/src/runtime/arch_power64.h
deleted file mode 100644 (file)
index 7cfb9da..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// 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.
-
-enum {
-       thechar = '9',
-       BigEndian = 1,
-       CacheLineSize = 64,
-       RuntimeGogoBytes = 64,
-       PhysPageSize = 65536,
-       PCQuantum = 4,
-       Int64Align = 8
-};
-
index 60c438c1d85912353505a8975e205aea0235b0f6..c87d848fec39f0b64ef517bff658f51d9ad0b08a 100644 (file)
@@ -169,7 +169,7 @@ TEXT runtime·mcall(SB), NOSPLIT, $0-4
 // of the G stack.  We need to distinguish the routine that
 // lives at the bottom of the G stack from the one that lives
 // at the top of the system stack because the one at the top of
-// the M stack terminates the stack walk (see topofstack()).
+// the system stack terminates the stack walk (see topofstack()).
 TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
        RET
 
index 6169202ea6d169eb8a57e58d1f2aa9a5f92c012b..548c88e47d0b34a25c7dd5b9779cdb9afbbb3467 100644 (file)
@@ -4,7 +4,8 @@
 
 // +build power64 power64le
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "funcdata.h"
 #include "textflag.h"
 
@@ -144,58 +145,44 @@ TEXT runtime·mcall(SB), NOSPLIT, $-8-8
        BL      (CTR)
        BR      runtime·badmcall2(SB)
 
-// switchtoM is a dummy routine that onM leaves at the bottom
+// systemstack_switch is a dummy routine that systemstack leaves at the bottom
 // of the G stack.  We need to distinguish the routine that
 // lives at the bottom of the G stack from the one that lives
-// at the top of the M stack because the one at the top of
-// the M stack terminates the stack walk (see topofstack()).
-TEXT runtime·switchtoM(SB), NOSPLIT, $0-0
+// at the top of the system stack because the one at the top of
+// the system stack terminates the stack walk (see topofstack()).
+TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
        UNDEF
        BL      (LR)    // make sure this function is not leaf
        RETURN
 
-// func onM_signalok(fn func())
-TEXT runtime·onM_signalok(SB), NOSPLIT, $8-8
-       MOVD    g, R3                   // R3 = g
-       MOVD    g_m(R3), R4             // R4 = g->m
-       MOVD    m_gsignal(R4), R4       // R4 = g->m->gsignal
-       MOVD    fn+0(FP), R11           // context for call below
-       CMP     R3, R4
-       BEQ     onsignal
-       MOVD    R11, 8(R1)
-       BL      runtime·onM(SB)
-       RETURN
-
-onsignal:
-       MOVD    0(R11), R3              // code pointer
-       MOVD    R3, CTR
-       BL      (CTR)
-       RETURN
-
-// void onM(fn func())
-TEXT runtime·onM(SB), NOSPLIT, $0-8
+// func systemstack(fn func())
+TEXT runtime·systemstack(SB), NOSPLIT, $0-8
        MOVD    fn+0(FP), R3    // R3 = fn
        MOVD    R3, R11         // context
        MOVD    g_m(g), R4      // R4 = m
 
+       MOVD    m_gsignal(R4), R5       // R5 = gsignal
+       CMP     g, R5
+       BEQ     noswitch
+
        MOVD    m_g0(R4), R5    // R5 = g0
        CMP     g, R5
-       BEQ     onm
+       BEQ     noswitch
 
        MOVD    m_curg(R4), R6
        CMP     g, R6
-       BEQ     oncurg
+       BEQ     switch
 
-       // Not g0, not curg. Must be gsignal, but that's not allowed.
+       // Bad: g is not gsignal, not g0, not curg. What is it?
        // Hide call from linker nosplit analysis.
-       MOVD    $runtime·badonm(SB), R3
+       MOVD    $runtime·badsystemstack(SB), R3
        MOVD    R3, CTR
        BL      (CTR)
 
-oncurg:
+switch:
        // save our state in g->sched.  Pretend to
-       // be switchtoM if the G stack is scanned.
-       MOVD    $runtime·switchtoM(SB), R6
+       // be systemstack_switch if the G stack is scanned.
+       MOVD    $runtime·systemstack_switch(SB), R6
        ADD     $8, R6  // get past prologue
        MOVD    R6, (g_sched+gobuf_pc)(g)
        MOVD    R1, (g_sched+gobuf_sp)(g)
@@ -205,7 +192,7 @@ oncurg:
        // switch to g0
        MOVD    R5, g
        MOVD    (g_sched+gobuf_sp)(g), R3
-       // make it look like mstart called onM on g0, to stop traceback
+       // make it look like mstart called systemstack on g0, to stop traceback
        SUB     $8, R3
        MOVD    $runtime·mstart(SB), R4
        MOVD    R4, 0(R3)
@@ -223,7 +210,7 @@ oncurg:
        MOVD    R0, (g_sched+gobuf_sp)(g)
        RETURN
 
-onm:
+noswitch:
        // already on m stack, just call directly
        MOVD    0(R11), R3      // code pointer
        MOVD    R3, CTR
@@ -987,6 +974,10 @@ TEXT runtime·goexit(SB),NOSPLIT,$-8-0
        MOVD    R0, R0  // NOP
        BL      runtime·goexit1(SB)    // does not return
 
+TEXT runtime·getg(SB),NOSPLIT,$-8-8
+       MOVD    g, ret+0(FP)
+       RETURN
+
 TEXT runtime·prefetcht0(SB),NOSPLIT,$0-8
        RETURN
 
diff --git a/src/runtime/atomic_power64x.go b/src/runtime/atomic_power64x.go
new file mode 100644 (file)
index 0000000..a0dcf51
--- /dev/null
@@ -0,0 +1,69 @@
+// 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.
+
+// +build power64 power64le
+
+package runtime
+
+import "unsafe"
+
+//go:noescape
+func xadd(ptr *uint32, delta int32) uint32
+
+//go:noescape
+func xadd64(ptr *uint64, delta int64) uint64
+
+//go:noescape
+func xchg(ptr *uint32, new uint32) uint32
+
+//go:noescape
+func xchg64(ptr *uint64, new uint64) uint64
+
+// xchgp cannot have a go:noescape annotation, because
+// while ptr does not escape, new does. If new is marked as
+// not escaping, the compiler will make incorrect escape analysis
+// decisions about the value being xchg'ed.
+// Instead, make xchgp a wrapper around the actual atomic.
+// When calling the wrapper we mark ptr as noescape explicitly.
+
+//go:nosplit
+func xchgp(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer {
+       return xchgp1(noescape(ptr), new)
+}
+
+func xchgp1(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer
+
+//go:noescape
+func xchguintptr(ptr *uintptr, new uintptr) uintptr
+
+//go:noescape
+func atomicload(ptr *uint32) uint32
+
+//go:noescape
+func atomicload64(ptr *uint64) uint64
+
+//go:noescape
+func atomicloadp(ptr unsafe.Pointer) unsafe.Pointer
+
+//go:noescape
+func atomicor8(ptr *uint8, val uint8)
+
+//go:noescape
+func cas64(ptr *uint64, old, new uint64) bool
+
+//go:noescape
+func atomicstore(ptr *uint32, val uint32)
+
+//go:noescape
+func atomicstore64(ptr *uint64, val uint64)
+
+// atomicstorep cannot have a go:noescape annotation.
+// See comment above for xchgp.
+
+//go:nosplit
+func atomicstorep(ptr unsafe.Pointer, new unsafe.Pointer) {
+       atomicstorep1(noescape(ptr), new)
+}
+
+func atomicstorep1(ptr unsafe.Pointer, val unsafe.Pointer)
index bb0110f94cf1b5a5c6939b9d860e7455a8477bdb..330422ad0908d6ab5391e8dd0e8e83ca4a94539b 100644 (file)
@@ -630,6 +630,7 @@ func (q *waitq) dequeue() *sudog {
                        return nil
                }
                q.first = sgp.next
+               sgp.next = nil
                if q.last == sgp {
                        q.last = nil
                }
index e39fd04c7a8f46b471166f5d6a1bf26e6c85db40..f222bed9964eed280e800465ac5406286f215190 100644 (file)
@@ -84,8 +84,8 @@ const (
 )
 
 type sigaltstackt struct {
-       ss_sp    *byte
-       ss_size  uint32
+       ss_sp    uintptr
+       ss_size  uintptr
        ss_flags int32
 }
 
@@ -101,8 +101,8 @@ type siginfo struct {
 }
 
 type stackt struct {
-       ss_sp    *byte
-       ss_size  uint32
+       ss_sp    uintptr
+       ss_size  uintptr
        ss_flags int32
 }
 
@@ -111,18 +111,30 @@ type timespec struct {
        tv_nsec int32
 }
 
+func (ts *timespec) set_sec(x int32) {
+       ts.tv_sec = int64(x)
+}
+
+func (ts *timespec) set_nsec(x int32) {
+       ts.tv_nsec = x
+}
+
 type timeval struct {
        tv_sec  int64
        tv_usec int32
 }
 
+func (tv *timeval) set_usec(x int32) {
+       tv.tv_usec = x
+}
+
 type itimerval struct {
        it_interval timeval
        it_value    timeval
 }
 
 type mcontextt struct {
-       __gregs     [19]int32
+       __gregs     [19]uint32
        __fpregs    [644]byte
        _mc_tlsbase int32
 }
index cca701e5bc5ac1f0432485d2d8b24c2cfebe0c3e..c2bde4dabe12ff40f5efd0054892e82f2b37c7ac 100644 (file)
@@ -84,8 +84,8 @@ const (
 )
 
 type sigaltstackt struct {
-       ss_sp     *byte
-       ss_size   uint64
+       ss_sp     uintptr
+       ss_size   uintptr
        ss_flags  int32
        pad_cgo_0 [4]byte
 }
@@ -103,8 +103,8 @@ type siginfo struct {
 }
 
 type stackt struct {
-       ss_sp     *byte
-       ss_size   uint64
+       ss_sp     uintptr
+       ss_size   uintptr
        ss_flags  int32
        pad_cgo_0 [4]byte
 }
@@ -114,12 +114,24 @@ type timespec struct {
        tv_nsec int64
 }
 
+func (ts *timespec) set_sec(x int32) {
+       ts.tv_sec = int64(x)
+}
+
+func (ts *timespec) set_nsec(x int32) {
+       ts.tv_nsec = int64(x)
+}
+
 type timeval struct {
        tv_sec    int64
        tv_usec   int32
        pad_cgo_0 [4]byte
 }
 
+func (tv *timeval) set_usec(x int32) {
+       tv.tv_usec = x
+}
+
 type itimerval struct {
        it_interval timeval
        it_value    timeval
index ddf592c91bd350193f56a3d7ffbd80d73b150400..f55924b61cbb75657590df47c8b53812fcc00fa6 100644 (file)
@@ -155,10 +155,11 @@ type sigactiont struct {
 }
 
 type siginfo struct {
-       si_signo  int32
-       si_errno  int32
-       si_code   int32
-       _sifields [116]byte
+       si_signo int32
+       si_errno int32
+       si_code  int32
+       // below here is a union; si_addr is the only field we use
+       si_addr uint32
 }
 
 type sigaltstackt struct {
index 7f8f5816c62b566656e2800f470a527e724d53d3..a73f475148201ec3899ca4f852be1bdac3400c51 100644 (file)
@@ -117,11 +117,11 @@ type sigactiont struct {
 }
 
 type siginfo struct {
-       si_signo  int32
-       si_errno  int32
-       si_code   int32
-       pad_cgo_0 [4]byte
-       _sifields [112]byte
+       si_signo int32
+       si_errno int32
+       si_code  int32
+       // below here is a union; si_addr is the only field we use
+       si_addr uint64
 }
 
 type itimerval struct {
index a874b15941310e99d6785711b6f35a5317423dfd..c3a6e2f01962cdde0ac9bcafa4846805ee416065 100644 (file)
@@ -147,10 +147,11 @@ type itimerval struct {
 }
 
 type siginfo struct {
-       si_signo  int32
-       si_errno  int32
-       si_code   int32
-       _sifields [4]uint8
+       si_signo int32
+       si_errno int32
+       si_code  int32
+       // below here is a union; si_addr is the only field we use
+       si_addr uint32
 }
 
 type sigactiont struct {
diff --git a/src/runtime/defs_linux_power64.go b/src/runtime/defs_linux_power64.go
new file mode 100644 (file)
index 0000000..f90b848
--- /dev/null
@@ -0,0 +1,198 @@
+// created by cgo -cdefs and then converted to Go
+// cgo -cdefs defs_linux.go defs3_linux.go
+
+package runtime
+
+const (
+       _EINTR  = 0x4
+       _EAGAIN = 0xb
+       _ENOMEM = 0xc
+
+       _PROT_NONE  = 0x0
+       _PROT_READ  = 0x1
+       _PROT_WRITE = 0x2
+       _PROT_EXEC  = 0x4
+
+       _MAP_ANON    = 0x20
+       _MAP_PRIVATE = 0x2
+       _MAP_FIXED   = 0x10
+
+       _MADV_DONTNEED = 0x4
+
+       _SA_RESTART = 0x10000000
+       _SA_ONSTACK = 0x8000000
+       _SA_SIGINFO = 0x4
+
+       _SIGHUP    = 0x1
+       _SIGINT    = 0x2
+       _SIGQUIT   = 0x3
+       _SIGILL    = 0x4
+       _SIGTRAP   = 0x5
+       _SIGABRT   = 0x6
+       _SIGBUS    = 0x7
+       _SIGFPE    = 0x8
+       _SIGKILL   = 0x9
+       _SIGUSR1   = 0xa
+       _SIGSEGV   = 0xb
+       _SIGUSR2   = 0xc
+       _SIGPIPE   = 0xd
+       _SIGALRM   = 0xe
+       _SIGSTKFLT = 0x10
+       _SIGCHLD   = 0x11
+       _SIGCONT   = 0x12
+       _SIGSTOP   = 0x13
+       _SIGTSTP   = 0x14
+       _SIGTTIN   = 0x15
+       _SIGTTOU   = 0x16
+       _SIGURG    = 0x17
+       _SIGXCPU   = 0x18
+       _SIGXFSZ   = 0x19
+       _SIGVTALRM = 0x1a
+       _SIGPROF   = 0x1b
+       _SIGWINCH  = 0x1c
+       _SIGIO     = 0x1d
+       _SIGPWR    = 0x1e
+       _SIGSYS    = 0x1f
+
+       _FPE_INTDIV = 0x1
+       _FPE_INTOVF = 0x2
+       _FPE_FLTDIV = 0x3
+       _FPE_FLTOVF = 0x4
+       _FPE_FLTUND = 0x5
+       _FPE_FLTRES = 0x6
+       _FPE_FLTINV = 0x7
+       _FPE_FLTSUB = 0x8
+
+       _BUS_ADRALN = 0x1
+       _BUS_ADRERR = 0x2
+       _BUS_OBJERR = 0x3
+
+       _SEGV_MAPERR = 0x1
+       _SEGV_ACCERR = 0x2
+
+       _ITIMER_REAL    = 0x0
+       _ITIMER_VIRTUAL = 0x1
+       _ITIMER_PROF    = 0x2
+
+       _EPOLLIN       = 0x1
+       _EPOLLOUT      = 0x4
+       _EPOLLERR      = 0x8
+       _EPOLLHUP      = 0x10
+       _EPOLLRDHUP    = 0x2000
+       _EPOLLET       = 0x80000000
+       _EPOLL_CLOEXEC = 0x80000
+       _EPOLL_CTL_ADD = 0x1
+       _EPOLL_CTL_DEL = 0x2
+       _EPOLL_CTL_MOD = 0x3
+)
+
+//struct Sigset {
+//     uint64  sig[1];
+//};
+//typedef uint64 Sigset;
+
+type timespec struct {
+       tv_sec  int64
+       tv_nsec int64
+}
+
+func (ts *timespec) set_sec(x int64) {
+       ts.tv_sec = x
+}
+
+func (ts *timespec) set_nsec(x int32) {
+       ts.tv_nsec = int64(x)
+}
+
+type timeval struct {
+       tv_sec  int64
+       tv_usec int64
+}
+
+func (tv *timeval) set_usec(x int32) {
+       tv.tv_usec = int64(x)
+}
+
+type sigactiont struct {
+       sa_handler  uintptr
+       sa_flags    uint64
+       sa_restorer uintptr
+       sa_mask     uint64
+}
+
+type siginfo struct {
+       si_signo int32
+       si_errno int32
+       si_code  int32
+       // below here is a union; si_addr is the only field we use
+       si_addr uint64
+}
+
+type itimerval struct {
+       it_interval timeval
+       it_value    timeval
+}
+
+type epollevent struct {
+       events    uint32
+       pad_cgo_0 [4]byte
+       data      [8]byte // unaligned uintptr
+}
+
+// created by cgo -cdefs and then converted to Go
+// cgo -cdefs defs_linux.go defs3_linux.go
+
+const (
+       _O_RDONLY    = 0x0
+       _O_CLOEXEC   = 0x80000
+       _SA_RESTORER = 0
+)
+
+type ptregs struct {
+       gpr       [32]uint64
+       nip       uint64
+       msr       uint64
+       orig_gpr3 uint64
+       ctr       uint64
+       link      uint64
+       xer       uint64
+       ccr       uint64
+       softe     uint64
+       trap      uint64
+       dar       uint64
+       dsisr     uint64
+       result    uint64
+}
+
+type vreg struct {
+       u [4]uint32
+}
+
+type sigaltstackt struct {
+       ss_sp     *byte
+       ss_flags  int32
+       pad_cgo_0 [4]byte
+       ss_size   uintptr
+}
+
+type sigcontext struct {
+       _unused     [4]uint64
+       signal      int32
+       _pad0       int32
+       handler     uint64
+       oldmask     uint64
+       regs        *ptregs
+       gp_regs     [48]uint64
+       fp_regs     [33]float64
+       v_regs      *vreg
+       vmx_reserve [101]int64
+}
+
+type ucontext struct {
+       uc_flags    uint64
+       uc_link     *ucontext
+       uc_stack    sigaltstackt
+       uc_sigmask  uint64
+       __unused    [15]uint64
+       uc_mcontext sigcontext
+}
diff --git a/src/runtime/defs_linux_power64.h b/src/runtime/defs_linux_power64.h
deleted file mode 100644 (file)
index 93742fa..0000000
+++ /dev/null
@@ -1,204 +0,0 @@
-// Created by cgo -cdefs - DO NOT EDIT
-// cgo -cdefs defs_linux.go defs3_linux.go
-
-
-enum {
-       EINTR   = 0x4,
-       EAGAIN  = 0xb,
-       ENOMEM  = 0xc,
-
-       PROT_NONE       = 0x0,
-       PROT_READ       = 0x1,
-       PROT_WRITE      = 0x2,
-       PROT_EXEC       = 0x4,
-
-       MAP_ANON        = 0x20,
-       MAP_PRIVATE     = 0x2,
-       MAP_FIXED       = 0x10,
-
-       MADV_DONTNEED   = 0x4,
-
-       SA_RESTART      = 0x10000000,
-       SA_ONSTACK      = 0x8000000,
-       SA_SIGINFO      = 0x4,
-
-       SIGHUP          = 0x1,
-       SIGINT          = 0x2,
-       SIGQUIT         = 0x3,
-       SIGILL          = 0x4,
-       SIGTRAP         = 0x5,
-       SIGABRT         = 0x6,
-       SIGBUS          = 0x7,
-       SIGFPE          = 0x8,
-       SIGKILL         = 0x9,
-       SIGUSR1         = 0xa,
-       SIGSEGV         = 0xb,
-       SIGUSR2         = 0xc,
-       SIGPIPE         = 0xd,
-       SIGALRM         = 0xe,
-       SIGSTKFLT       = 0x10,
-       SIGCHLD         = 0x11,
-       SIGCONT         = 0x12,
-       SIGSTOP         = 0x13,
-       SIGTSTP         = 0x14,
-       SIGTTIN         = 0x15,
-       SIGTTOU         = 0x16,
-       SIGURG          = 0x17,
-       SIGXCPU         = 0x18,
-       SIGXFSZ         = 0x19,
-       SIGVTALRM       = 0x1a,
-       SIGPROF         = 0x1b,
-       SIGWINCH        = 0x1c,
-       SIGIO           = 0x1d,
-       SIGPWR          = 0x1e,
-       SIGSYS          = 0x1f,
-
-       FPE_INTDIV      = 0x1,
-       FPE_INTOVF      = 0x2,
-       FPE_FLTDIV      = 0x3,
-       FPE_FLTOVF      = 0x4,
-       FPE_FLTUND      = 0x5,
-       FPE_FLTRES      = 0x6,
-       FPE_FLTINV      = 0x7,
-       FPE_FLTSUB      = 0x8,
-
-       BUS_ADRALN      = 0x1,
-       BUS_ADRERR      = 0x2,
-       BUS_OBJERR      = 0x3,
-
-       SEGV_MAPERR     = 0x1,
-       SEGV_ACCERR     = 0x2,
-
-       ITIMER_REAL     = 0x0,
-       ITIMER_VIRTUAL  = 0x1,
-       ITIMER_PROF     = 0x2,
-
-       EPOLLIN         = 0x1,
-       EPOLLOUT        = 0x4,
-       EPOLLERR        = 0x8,
-       EPOLLHUP        = 0x10,
-       EPOLLRDHUP      = 0x2000,
-       EPOLLET         = -0x80000000,
-       EPOLL_CLOEXEC   = 0x80000,
-       EPOLL_CTL_ADD   = 0x1,
-       EPOLL_CTL_DEL   = 0x2,
-       EPOLL_CTL_MOD   = 0x3,
-};
-
-typedef struct Sigset Sigset;
-typedef struct Timespec Timespec;
-typedef struct Timeval Timeval;
-typedef struct SigactionT SigactionT;
-typedef struct Siginfo Siginfo;
-typedef struct Itimerval Itimerval;
-typedef struct EpollEvent EpollEvent;
-
-#pragma pack on
-
-//struct Sigset {
-//     uint64  sig[1];
-//};
-//typedef uint64 Sigset;
-
-struct Timespec {
-       int64   tv_sec;
-       int64   tv_nsec;
-};
-struct Timeval {
-       int64   tv_sec;
-       int64   tv_usec;
-};
-struct SigactionT {
-       void    *sa_handler;
-       uint64  sa_flags;
-       void    *sa_restorer;
-       uint64  sa_mask;
-};
-struct Siginfo {
-       int32   si_signo;
-       int32   si_errno;
-       int32   si_code;
-       byte    Pad_cgo_0[4];
-       byte    _sifields[112];
-};
-struct Itimerval {
-       Timeval it_interval;
-       Timeval it_value;
-};
-struct EpollEvent {
-       uint32  events;
-       byte    Pad_cgo_0[4];
-       byte    data[8]; // unaligned uintptr
-};
-
-
-#pragma pack off
-// Created by cgo -cdefs - DO NOT EDIT
-// cgo -cdefs defs_linux.go defs3_linux.go
-
-
-enum {
-       O_RDONLY        = 0x0,
-       O_CLOEXEC       = 0x80000,
-       SA_RESTORER     = 0,
-};
-
-typedef struct Ptregs Ptregs;
-typedef struct Vreg Vreg;
-typedef struct SigaltstackT SigaltstackT;
-typedef struct Sigcontext Sigcontext;
-typedef struct Ucontext Ucontext;
-
-#pragma pack on
-
-struct Ptregs {
-       uint64  gpr[32];
-       uint64  nip;
-       uint64  msr;
-       uint64  orig_gpr3;
-       uint64  ctr;
-       uint64  link;
-       uint64  xer;
-       uint64  ccr;
-       uint64  softe;
-       uint64  trap;
-       uint64  dar;
-       uint64  dsisr;
-       uint64  result;
-};
-typedef        uint64  Gregset[48];
-typedef        float64 FPregset[33];
-struct Vreg {
-       uint32  u[4];
-};
-
-struct SigaltstackT {
-       byte    *ss_sp;
-       int32   ss_flags;
-       byte    Pad_cgo_0[4];
-       uint64  ss_size;
-};
-
-struct Sigcontext {
-       uint64  _unused[4];
-       int32   signal;
-       int32   _pad0;
-       uint64  handler;
-       uint64  oldmask;
-       Ptregs  *regs;
-       uint64  gp_regs[48];
-       float64 fp_regs[33];
-       Vreg    *v_regs;
-       int64   vmx_reserve[101];
-};
-struct Ucontext {
-       uint64  uc_flags;
-       Ucontext        *uc_link;
-       SigaltstackT    uc_stack;
-       uint64  uc_sigmask;
-       uint64  __unused[15];
-       Sigcontext      uc_mcontext;
-};
-
-
-#pragma pack off
diff --git a/src/runtime/defs_linux_power64le.go b/src/runtime/defs_linux_power64le.go
new file mode 100644 (file)
index 0000000..f90b848
--- /dev/null
@@ -0,0 +1,198 @@
+// created by cgo -cdefs and then converted to Go
+// cgo -cdefs defs_linux.go defs3_linux.go
+
+package runtime
+
+const (
+       _EINTR  = 0x4
+       _EAGAIN = 0xb
+       _ENOMEM = 0xc
+
+       _PROT_NONE  = 0x0
+       _PROT_READ  = 0x1
+       _PROT_WRITE = 0x2
+       _PROT_EXEC  = 0x4
+
+       _MAP_ANON    = 0x20
+       _MAP_PRIVATE = 0x2
+       _MAP_FIXED   = 0x10
+
+       _MADV_DONTNEED = 0x4
+
+       _SA_RESTART = 0x10000000
+       _SA_ONSTACK = 0x8000000
+       _SA_SIGINFO = 0x4
+
+       _SIGHUP    = 0x1
+       _SIGINT    = 0x2
+       _SIGQUIT   = 0x3
+       _SIGILL    = 0x4
+       _SIGTRAP   = 0x5
+       _SIGABRT   = 0x6
+       _SIGBUS    = 0x7
+       _SIGFPE    = 0x8
+       _SIGKILL   = 0x9
+       _SIGUSR1   = 0xa
+       _SIGSEGV   = 0xb
+       _SIGUSR2   = 0xc
+       _SIGPIPE   = 0xd
+       _SIGALRM   = 0xe
+       _SIGSTKFLT = 0x10
+       _SIGCHLD   = 0x11
+       _SIGCONT   = 0x12
+       _SIGSTOP   = 0x13
+       _SIGTSTP   = 0x14
+       _SIGTTIN   = 0x15
+       _SIGTTOU   = 0x16
+       _SIGURG    = 0x17
+       _SIGXCPU   = 0x18
+       _SIGXFSZ   = 0x19
+       _SIGVTALRM = 0x1a
+       _SIGPROF   = 0x1b
+       _SIGWINCH  = 0x1c
+       _SIGIO     = 0x1d
+       _SIGPWR    = 0x1e
+       _SIGSYS    = 0x1f
+
+       _FPE_INTDIV = 0x1
+       _FPE_INTOVF = 0x2
+       _FPE_FLTDIV = 0x3
+       _FPE_FLTOVF = 0x4
+       _FPE_FLTUND = 0x5
+       _FPE_FLTRES = 0x6
+       _FPE_FLTINV = 0x7
+       _FPE_FLTSUB = 0x8
+
+       _BUS_ADRALN = 0x1
+       _BUS_ADRERR = 0x2
+       _BUS_OBJERR = 0x3
+
+       _SEGV_MAPERR = 0x1
+       _SEGV_ACCERR = 0x2
+
+       _ITIMER_REAL    = 0x0
+       _ITIMER_VIRTUAL = 0x1
+       _ITIMER_PROF    = 0x2
+
+       _EPOLLIN       = 0x1
+       _EPOLLOUT      = 0x4
+       _EPOLLERR      = 0x8
+       _EPOLLHUP      = 0x10
+       _EPOLLRDHUP    = 0x2000
+       _EPOLLET       = 0x80000000
+       _EPOLL_CLOEXEC = 0x80000
+       _EPOLL_CTL_ADD = 0x1
+       _EPOLL_CTL_DEL = 0x2
+       _EPOLL_CTL_MOD = 0x3
+)
+
+//struct Sigset {
+//     uint64  sig[1];
+//};
+//typedef uint64 Sigset;
+
+type timespec struct {
+       tv_sec  int64
+       tv_nsec int64
+}
+
+func (ts *timespec) set_sec(x int64) {
+       ts.tv_sec = x
+}
+
+func (ts *timespec) set_nsec(x int32) {
+       ts.tv_nsec = int64(x)
+}
+
+type timeval struct {
+       tv_sec  int64
+       tv_usec int64
+}
+
+func (tv *timeval) set_usec(x int32) {
+       tv.tv_usec = int64(x)
+}
+
+type sigactiont struct {
+       sa_handler  uintptr
+       sa_flags    uint64
+       sa_restorer uintptr
+       sa_mask     uint64
+}
+
+type siginfo struct {
+       si_signo int32
+       si_errno int32
+       si_code  int32
+       // below here is a union; si_addr is the only field we use
+       si_addr uint64
+}
+
+type itimerval struct {
+       it_interval timeval
+       it_value    timeval
+}
+
+type epollevent struct {
+       events    uint32
+       pad_cgo_0 [4]byte
+       data      [8]byte // unaligned uintptr
+}
+
+// created by cgo -cdefs and then converted to Go
+// cgo -cdefs defs_linux.go defs3_linux.go
+
+const (
+       _O_RDONLY    = 0x0
+       _O_CLOEXEC   = 0x80000
+       _SA_RESTORER = 0
+)
+
+type ptregs struct {
+       gpr       [32]uint64
+       nip       uint64
+       msr       uint64
+       orig_gpr3 uint64
+       ctr       uint64
+       link      uint64
+       xer       uint64
+       ccr       uint64
+       softe     uint64
+       trap      uint64
+       dar       uint64
+       dsisr     uint64
+       result    uint64
+}
+
+type vreg struct {
+       u [4]uint32
+}
+
+type sigaltstackt struct {
+       ss_sp     *byte
+       ss_flags  int32
+       pad_cgo_0 [4]byte
+       ss_size   uintptr
+}
+
+type sigcontext struct {
+       _unused     [4]uint64
+       signal      int32
+       _pad0       int32
+       handler     uint64
+       oldmask     uint64
+       regs        *ptregs
+       gp_regs     [48]uint64
+       fp_regs     [33]float64
+       v_regs      *vreg
+       vmx_reserve [101]int64
+}
+
+type ucontext struct {
+       uc_flags    uint64
+       uc_link     *ucontext
+       uc_stack    sigaltstackt
+       uc_sigmask  uint64
+       __unused    [15]uint64
+       uc_mcontext sigcontext
+}
diff --git a/src/runtime/defs_linux_power64le.h b/src/runtime/defs_linux_power64le.h
deleted file mode 100644 (file)
index 93742fa..0000000
+++ /dev/null
@@ -1,204 +0,0 @@
-// Created by cgo -cdefs - DO NOT EDIT
-// cgo -cdefs defs_linux.go defs3_linux.go
-
-
-enum {
-       EINTR   = 0x4,
-       EAGAIN  = 0xb,
-       ENOMEM  = 0xc,
-
-       PROT_NONE       = 0x0,
-       PROT_READ       = 0x1,
-       PROT_WRITE      = 0x2,
-       PROT_EXEC       = 0x4,
-
-       MAP_ANON        = 0x20,
-       MAP_PRIVATE     = 0x2,
-       MAP_FIXED       = 0x10,
-
-       MADV_DONTNEED   = 0x4,
-
-       SA_RESTART      = 0x10000000,
-       SA_ONSTACK      = 0x8000000,
-       SA_SIGINFO      = 0x4,
-
-       SIGHUP          = 0x1,
-       SIGINT          = 0x2,
-       SIGQUIT         = 0x3,
-       SIGILL          = 0x4,
-       SIGTRAP         = 0x5,
-       SIGABRT         = 0x6,
-       SIGBUS          = 0x7,
-       SIGFPE          = 0x8,
-       SIGKILL         = 0x9,
-       SIGUSR1         = 0xa,
-       SIGSEGV         = 0xb,
-       SIGUSR2         = 0xc,
-       SIGPIPE         = 0xd,
-       SIGALRM         = 0xe,
-       SIGSTKFLT       = 0x10,
-       SIGCHLD         = 0x11,
-       SIGCONT         = 0x12,
-       SIGSTOP         = 0x13,
-       SIGTSTP         = 0x14,
-       SIGTTIN         = 0x15,
-       SIGTTOU         = 0x16,
-       SIGURG          = 0x17,
-       SIGXCPU         = 0x18,
-       SIGXFSZ         = 0x19,
-       SIGVTALRM       = 0x1a,
-       SIGPROF         = 0x1b,
-       SIGWINCH        = 0x1c,
-       SIGIO           = 0x1d,
-       SIGPWR          = 0x1e,
-       SIGSYS          = 0x1f,
-
-       FPE_INTDIV      = 0x1,
-       FPE_INTOVF      = 0x2,
-       FPE_FLTDIV      = 0x3,
-       FPE_FLTOVF      = 0x4,
-       FPE_FLTUND      = 0x5,
-       FPE_FLTRES      = 0x6,
-       FPE_FLTINV      = 0x7,
-       FPE_FLTSUB      = 0x8,
-
-       BUS_ADRALN      = 0x1,
-       BUS_ADRERR      = 0x2,
-       BUS_OBJERR      = 0x3,
-
-       SEGV_MAPERR     = 0x1,
-       SEGV_ACCERR     = 0x2,
-
-       ITIMER_REAL     = 0x0,
-       ITIMER_VIRTUAL  = 0x1,
-       ITIMER_PROF     = 0x2,
-
-       EPOLLIN         = 0x1,
-       EPOLLOUT        = 0x4,
-       EPOLLERR        = 0x8,
-       EPOLLHUP        = 0x10,
-       EPOLLRDHUP      = 0x2000,
-       EPOLLET         = -0x80000000,
-       EPOLL_CLOEXEC   = 0x80000,
-       EPOLL_CTL_ADD   = 0x1,
-       EPOLL_CTL_DEL   = 0x2,
-       EPOLL_CTL_MOD   = 0x3,
-};
-
-typedef struct Sigset Sigset;
-typedef struct Timespec Timespec;
-typedef struct Timeval Timeval;
-typedef struct SigactionT SigactionT;
-typedef struct Siginfo Siginfo;
-typedef struct Itimerval Itimerval;
-typedef struct EpollEvent EpollEvent;
-
-#pragma pack on
-
-//struct Sigset {
-//     uint64  sig[1];
-//};
-//typedef uint64 Sigset;
-
-struct Timespec {
-       int64   tv_sec;
-       int64   tv_nsec;
-};
-struct Timeval {
-       int64   tv_sec;
-       int64   tv_usec;
-};
-struct SigactionT {
-       void    *sa_handler;
-       uint64  sa_flags;
-       void    *sa_restorer;
-       uint64  sa_mask;
-};
-struct Siginfo {
-       int32   si_signo;
-       int32   si_errno;
-       int32   si_code;
-       byte    Pad_cgo_0[4];
-       byte    _sifields[112];
-};
-struct Itimerval {
-       Timeval it_interval;
-       Timeval it_value;
-};
-struct EpollEvent {
-       uint32  events;
-       byte    Pad_cgo_0[4];
-       byte    data[8]; // unaligned uintptr
-};
-
-
-#pragma pack off
-// Created by cgo -cdefs - DO NOT EDIT
-// cgo -cdefs defs_linux.go defs3_linux.go
-
-
-enum {
-       O_RDONLY        = 0x0,
-       O_CLOEXEC       = 0x80000,
-       SA_RESTORER     = 0,
-};
-
-typedef struct Ptregs Ptregs;
-typedef struct Vreg Vreg;
-typedef struct SigaltstackT SigaltstackT;
-typedef struct Sigcontext Sigcontext;
-typedef struct Ucontext Ucontext;
-
-#pragma pack on
-
-struct Ptregs {
-       uint64  gpr[32];
-       uint64  nip;
-       uint64  msr;
-       uint64  orig_gpr3;
-       uint64  ctr;
-       uint64  link;
-       uint64  xer;
-       uint64  ccr;
-       uint64  softe;
-       uint64  trap;
-       uint64  dar;
-       uint64  dsisr;
-       uint64  result;
-};
-typedef        uint64  Gregset[48];
-typedef        float64 FPregset[33];
-struct Vreg {
-       uint32  u[4];
-};
-
-struct SigaltstackT {
-       byte    *ss_sp;
-       int32   ss_flags;
-       byte    Pad_cgo_0[4];
-       uint64  ss_size;
-};
-
-struct Sigcontext {
-       uint64  _unused[4];
-       int32   signal;
-       int32   _pad0;
-       uint64  handler;
-       uint64  oldmask;
-       Ptregs  *regs;
-       uint64  gp_regs[48];
-       float64 fp_regs[33];
-       Vreg    *v_regs;
-       int64   vmx_reserve[101];
-};
-struct Ucontext {
-       uint64  uc_flags;
-       Ucontext        *uc_link;
-       SigaltstackT    uc_stack;
-       uint64  uc_sigmask;
-       uint64  __unused[15];
-       Sigcontext      uc_mcontext;
-};
-
-
-#pragma pack off
index 170506b230a242f765a142145551891398e3222d..212ecdf14aba8163de7ef0e19b07d7852377bd26 100644 (file)
@@ -1,5 +1,7 @@
 package runtime
 
+const _PAGESIZE = 0x1000
+
 type ureg struct {
        di    uint32 /* general registers */
        si    uint32 /* ... */
index 17becfb66f13bd3d8cf74554309cbdfa2d309702..510da0e994b98a4bddee8a849b0ebe0b17738d0c 100644 (file)
@@ -1,5 +1,7 @@
 package runtime
 
+const _PAGESIZE = 0x1000
+
 type ureg struct {
        ax  uint64
        bx  uint64
index e442c34835ef9c5b79d3ad9fe6fe7e514d827236..ec50cac484a61d12a488a51310f0006a18a99eb9 100644 (file)
@@ -54,3 +54,6 @@ func gogetenv(key string) string {
        sp.len = int(r)
        return s
 }
+
+var _cgo_setenv unsafe.Pointer   // pointer to C function
+var _cgo_unsetenv unsafe.Pointer // pointer to C function
diff --git a/src/runtime/gengoos.go b/src/runtime/gengoos.go
new file mode 100644 (file)
index 0000000..06621c8
--- /dev/null
@@ -0,0 +1,84 @@
+// 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.
+
+// +build ignore
+
+package main
+
+import (
+       "bytes"
+       "fmt"
+       "io/ioutil"
+       "log"
+       "strconv"
+       "strings"
+)
+
+var gooses, goarches []string
+
+func main() {
+       data, err := ioutil.ReadFile("../go/build/syslist.go")
+       if err != nil {
+               log.Fatal(err)
+       }
+       const (
+               goosPrefix   = `const goosList = `
+               goarchPrefix = `const goarchList = `
+       )
+       for _, line := range strings.Split(string(data), "\n") {
+               if strings.HasPrefix(line, goosPrefix) {
+                       text, err := strconv.Unquote(strings.TrimPrefix(line, goosPrefix))
+                       if err != nil {
+                               log.Fatalf("parsing goosList %#q: %v", strings.TrimPrefix(line, goosPrefix), err)
+                       }
+                       gooses = strings.Fields(text)
+               }
+               if strings.HasPrefix(line, goarchPrefix) {
+                       text, err := strconv.Unquote(strings.TrimPrefix(line, goarchPrefix))
+                       if err != nil {
+                               log.Fatal("parsing goarchList: %v", err)
+                       }
+                       goarches = strings.Fields(text)
+               }
+       }
+
+       for _, target := range gooses {
+               var buf bytes.Buffer
+               fmt.Fprintf(&buf, "// generated by gengoos.go using 'go generate'\n\n")
+               if target == "linux" {
+                       fmt.Fprintf(&buf, "// +build !android\n\n") // must explicitly exclude android for linux
+               }
+               fmt.Fprintf(&buf, "package runtime\n\n")
+               fmt.Fprintf(&buf, "const theGoos = `%s`\n\n", target)
+               for _, goos := range gooses {
+                       value := 0
+                       if goos == target {
+                               value = 1
+                       }
+                       fmt.Fprintf(&buf, "const goos_%s = %d\n", goos, value)
+               }
+               err := ioutil.WriteFile("zgoos_"+target+".go", buf.Bytes(), 0666)
+               if err != nil {
+                       log.Fatal(err)
+               }
+       }
+
+       for _, target := range goarches {
+               var buf bytes.Buffer
+               fmt.Fprintf(&buf, "// generated by gengoos.go using 'go generate'\n\n")
+               fmt.Fprintf(&buf, "package runtime\n\n")
+               fmt.Fprintf(&buf, "const theGoarch = `%s`\n\n", target)
+               for _, goarch := range goarches {
+                       value := 0
+                       if goarch == target {
+                               value = 1
+                       }
+                       fmt.Fprintf(&buf, "const goarch_%s = %d\n", goarch, value)
+               }
+               err := ioutil.WriteFile("zgoarch_"+target+".go", buf.Bytes(), 0666)
+               if err != nil {
+                       log.Fatal(err)
+               }
+       }
+}
index c6f97025f46342e2fda6e869b4a196ad1d42081b..e1693d40f1ae33e0f2092afa0d36417f580dcd1c 100644 (file)
@@ -7,7 +7,7 @@
 // finalizers, etc.) to a file.
 
 // The format of the dumped file is described at
-// http://code.google.com/p/go-wiki/wiki/heapdump14
+// http://golang.org/s/go14heapdump.
 
 package runtime
 
index a4ad8a10c69584aa3d4f2408757a00bbed4879c7..fd3325972a855fb4bd965765db316ce53f615c7a 100644 (file)
@@ -12,6 +12,10 @@ import "unsafe"
 func lfstackpush(head *uint64, node *lfnode) {
        node.pushcnt++
        new := lfstackPack(node, node.pushcnt)
+       if node1, _ := lfstackUnpack(new); node1 != node {
+               println("runtime: lfstackpush invalid packing: node=", node, " cnt=", hex(node.pushcnt), " packed=", hex(new), " -> node=", node1, "\n")
+               gothrow("lfstackpush")
+       }
        for {
                old := atomicload64(head)
                node.next = old
index 61d8678d9c2b3fd1b73c658a5567062e9d2766dc..4b8bcbac6a2b52828a893dd2cadf107553ff5d65 100644 (file)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build 386 arm
+// +build 386 arm nacl
 
 package runtime
 
index 7a122bf92c12659d7b248515db12a8d9df03331f..89e389fc726f664768d250ea0bda9b9cc2ef2fd9 100644 (file)
@@ -9,18 +9,24 @@ package runtime
 
 import "unsafe"
 
-// On Power64, Linux limits the user address space to 43 bits.
-// (https://www.kernel.org/doc/ols/2001/ppc64.pdf)
-// In addition to the 21 bits taken from the top, we can take 3 from the
-// bottom, because node must be pointer-aligned, giving a total of 24 bits
+// On Power64, Linux limits the user address space to 46 bits (see
+// TASK_SIZE_USER64 in the Linux kernel).  This has grown over time,
+// so here we allow 48 bit addresses.
+//
+// In addition to the 16 bits taken from the top, we can take 3 from the
+// bottom, because node must be pointer-aligned, giving a total of 19 bits
 // of count.
+const (
+       addrBits = 48
+       cntBits  = 64 - addrBits + 3
+)
 
 func lfstackPack(node *lfnode, cnt uintptr) uint64 {
-       return uint64(uintptr(unsafe.Pointer(node)))<<21 | uint64(cnt&(1<<24-1))
+       return uint64(uintptr(unsafe.Pointer(node)))<<(64-addrBits) | uint64(cnt&(1<<cntBits-1))
 }
 
 func lfstackUnpack(val uint64) (node *lfnode, cnt uintptr) {
-       node = (*lfnode)(unsafe.Pointer(uintptr(val >> 24 << 3)))
-       cnt = uintptr(val & (1<<24 - 1))
+       node = (*lfnode)(unsafe.Pointer(uintptr(val >> cntBits << 3)))
+       cnt = uintptr(val & (1<<cntBits - 1))
        return
 }
index 86e20b24906afa36f628d1fe39d94df1392203e7..e9fec7bb142ae2a9a569ec00eecf9424a7f818c9 100644 (file)
@@ -546,6 +546,8 @@ func GC() {
 
 // linker-provided
 var noptrdata struct{}
+var enoptrdata struct{}
+var noptrbss struct{}
 var enoptrbss struct{}
 
 // SetFinalizer sets the finalizer associated with x to f.
@@ -622,8 +624,13 @@ func SetFinalizer(obj interface{}, finalizer interface{}) {
                //      func main() {
                //              runtime.SetFinalizer(Foo, nil)
                //      }
-               // The segments are, in order: text, rodata, noptrdata, data, bss, noptrbss.
-               if uintptr(unsafe.Pointer(&noptrdata)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&enoptrbss)) {
+               // The relevant segments are: noptrdata, data, bss, noptrbss.
+               // We cannot assume they are in any order or even contiguous,
+               // due to external linking.
+               if uintptr(unsafe.Pointer(&noptrdata)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&enoptrdata)) ||
+                       uintptr(unsafe.Pointer(&data)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&edata)) ||
+                       uintptr(unsafe.Pointer(&bss)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&ebss)) ||
+                       uintptr(unsafe.Pointer(&noptrbss)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&enoptrbss)) {
                        return
                }
                gothrow("runtime.SetFinalizer: pointer not in allocated block")
index 511638d3d34a94b9ab14d8993e3acdc922172acf..a9d40de30638ee2390fed023f59f9e93cfcd97a1 100644 (file)
@@ -126,7 +126,7 @@ const (
        // See http://golang.org/issue/5402 and http://golang.org/issue/5236.
        // On other 64-bit platforms, we limit the arena to 128GB, or 37 bits.
        // On 32-bit, we don't bother limiting anything, so we use the full 32-bit address.
-       _MHeapMap_TotalBits = (_64bit*_Windows)*35 + (_64bit*(1-_Windows))*37 + (1-_64bit)*32
+       _MHeapMap_TotalBits = (_64bit*goos_windows)*35 + (_64bit*(1-goos_windows))*37 + (1-_64bit)*32
        _MHeapMap_Bits      = _MHeapMap_TotalBits - _PageShift
 
        _MaxMem = uintptr(1<<_MHeapMap_TotalBits - 1)
index 4bd40a39fcb2859c77f0ec84f977b14ea5adf823..e9be5ec8c9686222a64d75a4173d4a7448be5c7a 100644 (file)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build dragonfly freebsd netbsd openbsd solaris
+// +build dragonfly freebsd nacl netbsd openbsd solaris
 
 package runtime
 
@@ -38,7 +38,7 @@ func sysReserve(v unsafe.Pointer, n uintptr, reserved *bool) unsafe.Pointer {
        // On 64-bit, people with ulimit -v set complain if we reserve too
        // much address space.  Instead, assume that the reservation is okay
        // and check the assumption in SysMap.
-       if ptrSize == 8 && uint64(n) > 1<<32 {
+       if ptrSize == 8 && uint64(n) > 1<<32 || goos_nacl != 0 {
                *reserved = false
                return v
        }
diff --git a/src/runtime/mem_nacl.c b/src/runtime/mem_nacl.c
deleted file mode 100644 (file)
index 6c836f1..0000000
+++ /dev/null
@@ -1,120 +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.
-
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "malloc.h"
-#include "textflag.h"
-
-enum
-{
-       Debug = 0,
-};
-
-#pragma textflag NOSPLIT
-void*
-runtime·sysAlloc(uintptr n, uint64 *stat)
-{
-       void *v;
-
-       v = runtime·mmap(nil, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
-       if(v < (void*)4096) {
-               if(Debug)
-                       runtime·printf("sysAlloc(%p): %p\n", n, v);
-               return nil;
-       }
-       runtime·xadd64(stat, n);
-       if(Debug)
-               runtime·printf("sysAlloc(%p) = %p\n", n, v);
-       return v;
-}
-
-void
-runtime·SysUnused(void *v, uintptr n)
-{
-       if(Debug)
-               runtime·printf("SysUnused(%p, %p)\n", v, n);
-}
-
-void
-runtime·SysUsed(void *v, uintptr n)
-{
-       USED(v);
-       USED(n);
-}
-
-void
-runtime·SysFree(void *v, uintptr n, uint64 *stat)
-{
-       if(Debug)
-               runtime·printf("SysFree(%p, %p)\n", v, n);
-       runtime·xadd64(stat, -(uint64)n);
-       runtime·munmap(v, n);
-}
-
-void
-runtime·SysFault(void *v, uintptr n)
-{
-       runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, 0);
-}
-
-void*
-runtime·SysReserve(void *v, uintptr n, bool *reserved)
-{
-       void *p;
-
-       // On 64-bit, people with ulimit -v set complain if we reserve too
-       // much address space.  Instead, assume that the reservation is okay
-       // and check the assumption in SysMap.
-       if(NaCl || sizeof(void*) == 8) {
-               *reserved = false;
-               return v;
-       }
-       
-       p = runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
-       if(p < (void*)4096)
-               return nil;
-       *reserved = true;
-       return p;
-}
-
-void
-runtime·SysMap(void *v, uintptr n, bool reserved, uint64 *stat)
-{
-       void *p;
-       
-       runtime·xadd64(stat, n);
-
-       // On 64-bit, we don't actually have v reserved, so tread carefully.
-       if(!reserved) {
-               p = runtime·mmap(v, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
-               if(p == (void*)ENOMEM) {
-                       runtime·printf("SysMap(%p, %p): %p\n", v, n, p);
-                       runtime·throw("runtime: out of memory");
-               }
-               if(p != v) {
-                       runtime·printf("SysMap(%p, %p): %p\n", v, n, p);
-                       runtime·printf("runtime: address space conflict: map(%p) = %p\n", v, p);
-                       runtime·throw("runtime: address space conflict");
-               }
-               if(Debug)
-                       runtime·printf("SysMap(%p, %p) = %p\n", v, n, p);
-               return;
-       }
-
-       p = runtime·mmap(v, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
-       if(p == (void*)ENOMEM) {
-               runtime·printf("SysMap(%p, %p): %p\n", v, n, p);
-               runtime·throw("runtime: out of memory");
-       }
-       if(p != v) {
-               runtime·printf("SysMap(%p, %p): %p\n", v, n, p);
-               runtime·printf("mmap MAP_FIXED %p returned %p\n", v, p);
-               runtime·throw("runtime: cannot map pages in arena address space");
-       }
-       if(Debug)
-               runtime·printf("SysMap(%p, %p) = %p\n", v, n, p);
-}
diff --git a/src/runtime/mem_plan9.c b/src/runtime/mem_plan9.c
deleted file mode 100644 (file)
index d673d6f..0000000
+++ /dev/null
@@ -1,121 +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.
-
-#include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "arch_GOARCH.h"
-#include "malloc.h"
-#include "os_GOOS.h"
-#include "textflag.h"
-
-extern byte runtime·end[];
-#pragma dataflag NOPTR
-static byte *bloc = { runtime·end };
-static Mutex memlock;
-
-enum
-{
-       Round = PAGESIZE-1
-};
-
-static void*
-brk(uintptr nbytes)
-{
-       uintptr bl;
-
-       runtime·lock(&memlock);
-       // Plan 9 sbrk from /sys/src/libc/9sys/sbrk.c
-       bl = ((uintptr)bloc + Round) & ~Round;
-       if(runtime·brk_((void*)(bl + nbytes)) < 0) {
-               runtime·unlock(&memlock);
-               return nil;
-       }
-       bloc = (byte*)bl + nbytes;
-       runtime·unlock(&memlock);
-       return (void*)bl;       
-}
-
-static void
-sysalloc(void)
-{
-       uintptr nbytes;
-       uint64 *stat;
-       void *p;
-
-       nbytes = g->m->scalararg[0];
-       stat = g->m->ptrarg[0];
-       g->m->scalararg[0] = 0;
-       g->m->ptrarg[0] = nil;
-
-       p = brk(nbytes);
-       if(p != nil)
-               runtime·xadd64(stat, nbytes);
-
-       g->m->ptrarg[0] = p;
-}
-
-#pragma textflag NOSPLIT
-void*
-runtime·sysAlloc(uintptr nbytes, uint64 *stat)
-{
-       void (*fn)(void);
-       void *p;
-
-       g->m->scalararg[0] = nbytes;
-       g->m->ptrarg[0] = stat;
-       fn = sysalloc;
-       runtime·onM(&fn);
-       p = g->m->ptrarg[0];
-       g->m->ptrarg[0] = nil;
-       return p;
-}
-
-void
-runtime·SysFree(void *v, uintptr nbytes, uint64 *stat)
-{
-       runtime·xadd64(stat, -(uint64)nbytes);
-       runtime·lock(&memlock);
-       // from tiny/mem.c
-       // Push pointer back if this is a free
-       // of the most recent sysAlloc.
-       nbytes += (nbytes + Round) & ~Round;
-       if(bloc == (byte*)v+nbytes)
-               bloc -= nbytes;
-       runtime·unlock(&memlock);
-}
-
-void
-runtime·SysUnused(void *v, uintptr nbytes)
-{
-       USED(v, nbytes);
-}
-
-void
-runtime·SysUsed(void *v, uintptr nbytes)
-{
-       USED(v, nbytes);
-}
-
-void
-runtime·SysMap(void *v, uintptr nbytes, bool reserved, uint64 *stat)
-{
-       // SysReserve has already allocated all heap memory,
-       // but has not adjusted stats.
-       USED(v, reserved);
-       runtime·xadd64(stat, nbytes);
-}
-
-void
-runtime·SysFault(void *v, uintptr nbytes)
-{
-       USED(v, nbytes);
-}
-
-void*
-runtime·SysReserve(void *v, uintptr nbytes, bool *reserved)
-{
-       USED(v);
-       *reserved = true;
-       return brk(nbytes);
-}
diff --git a/src/runtime/mem_plan9.go b/src/runtime/mem_plan9.go
new file mode 100644 (file)
index 0000000..a5d7c1a
--- /dev/null
@@ -0,0 +1,70 @@
+// 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
+
+import "unsafe"
+
+var bloc uintptr
+var memlock mutex
+
+const memRound = _PAGESIZE - 1
+
+func initBloc() {
+       bloc = uintptr(unsafe.Pointer(&end))
+}
+
+func sbrk(n uintptr) unsafe.Pointer {
+       lock(&memlock)
+       // Plan 9 sbrk from /sys/src/libc/9sys/sbrk.c
+       bl := (bloc + memRound) &^ memRound
+       if brk_(unsafe.Pointer(bl+n)) < 0 {
+               unlock(&memlock)
+               return nil
+       }
+       bloc = bl + n
+       unlock(&memlock)
+       return unsafe.Pointer(bl)
+}
+
+func sysAlloc(n uintptr, stat *uint64) unsafe.Pointer {
+       p := sbrk(n)
+       if p != nil {
+               xadd64(stat, int64(n))
+       }
+       return p
+}
+
+func sysFree(v unsafe.Pointer, n uintptr, stat *uint64) {
+       xadd64(stat, -int64(n))
+       lock(&memlock)
+       // from tiny/mem.c
+       // Push pointer back if this is a free
+       // of the most recent sysAlloc.
+       n += (n + memRound) &^ memRound
+       if bloc == uintptr(v)+n {
+               bloc -= n
+       }
+       unlock(&memlock)
+}
+
+func sysUnused(v unsafe.Pointer, n uintptr) {
+}
+
+func sysUsed(v unsafe.Pointer, n uintptr) {
+}
+
+func sysMap(v unsafe.Pointer, n uintptr, reserved bool, stat *uint64) {
+       // sysReserve has already allocated all heap memory,
+       // but has not adjusted stats.
+       xadd64(stat, int64(n))
+}
+
+func sysFault(v unsafe.Pointer, n uintptr) {
+}
+
+func sysReserve(v unsafe.Pointer, n uintptr, reserved *bool) unsafe.Pointer {
+       *reserved = true
+       return sbrk(n)
+}
index 00e64c0fff2940062c285fc7d0e1d987b4920e35..7797894fc5fbb9b50135a5a94e0f517d535278be 100644 (file)
@@ -51,10 +51,26 @@ func clearpools() {
                if c := p.mcache; c != nil {
                        c.tiny = nil
                        c.tinysize = 0
+
+                       // disconnect cached list before dropping it on the floor,
+                       // so that a dangling ref to one entry does not pin all of them.
+                       var sg, sgnext *sudog
+                       for sg = c.sudogcache; sg != nil; sg = sgnext {
+                               sgnext = sg.next
+                               sg.next = nil
+                       }
                        c.sudogcache = nil
                }
+
                // clear defer pools
                for i := range p.deferpool {
+                       // disconnect cached list before dropping it on the floor,
+                       // so that a dangling ref to one entry does not pin all of them.
+                       var d, dlink *_defer
+                       for d = p.deferpool[i]; d != nil; d = dlink {
+                               dlink = d.link
+                               d.link = nil
+                       }
                        p.deferpool[i] = nil
                }
        }
similarity index 81%
rename from src/runtime/netpoll_stub.c
rename to src/runtime/netpoll_stub.go
index b7a8f2944c3f78690962a96eefb93cfba0d703b7..6c7e79ea372919614f2ee860b1b2a5d8a217f573 100644 (file)
@@ -4,15 +4,12 @@
 
 // +build plan9
 
-#include "runtime.h"
+package runtime
 
 // Polls for ready network connections.
 // Returns list of goroutines that become runnable.
-G*
-runtime·netpoll(bool block)
-{
+func netpoll(block bool) (gp *g) {
        // Implementation for platforms that do not support
        // integrated network poller.
-       USED(block);
-       return nil;
+       return
 }
index 88e878137621f363071cdee53f5ecdd1e5d2e891..23d5dc00f07fd9e4195dd1691f1bb1b1285a3b08 100644 (file)
@@ -108,7 +108,7 @@ retry:
                        op = entries[i].op
                        errno = 0
                        qty = 0
-                       if stdcall5(_WSAGetOverlappedResult, netpollfd(op.pd), uintptr(unsafe.Pointer(op)), uintptr(unsafe.Pointer(&qty)), 0, uintptr(unsafe.Pointer(&flags))) == 0 {
+                       if stdcall5(_WSAGetOverlappedResult, op.pd.fd, uintptr(unsafe.Pointer(op)), uintptr(unsafe.Pointer(&qty)), 0, uintptr(unsafe.Pointer(&flags))) == 0 {
                                errno = int32(getlasterror())
                        }
                        handlecompletion(&gp, op, errno, qty)
@@ -152,5 +152,5 @@ func handlecompletion(gpp **g, op *net_op, errno int32, qty uint32) {
        }
        op.errno = errno
        op.qty = qty
-       netpollready(gpp, op.pd, mode)
+       netpollready((**g)(noescape(unsafe.Pointer(gpp))), op.pd, mode)
 }
diff --git a/src/runtime/os1_nacl.go b/src/runtime/os1_nacl.go
new file mode 100644 (file)
index 0000000..7b4c99a
--- /dev/null
@@ -0,0 +1,197 @@
+// 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
+
+import "unsafe"
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
+func mpreinit(mp *m) {
+       mp.gsignal = malg(32 * 1024)
+       mp.gsignal.m = mp
+}
+
+func sigtramp()
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the new thread, can not allocate memory.
+func minit() {
+       _g_ := getg()
+
+       // Initialize signal handling
+       ret := nacl_exception_stack(_g_.m.gsignal.stack.lo, 32*1024)
+       if ret < 0 {
+               print("runtime: nacl_exception_stack: error ", -ret, "\n")
+       }
+
+       ret = nacl_exception_handler(funcPC(sigtramp), nil)
+       if ret < 0 {
+               print("runtime: nacl_exception_handler: error ", -ret, "\n")
+       }
+}
+
+// Called from dropm to undo the effect of an minit.
+func unminit() {
+}
+
+func osinit() {
+       ncpu = 1
+       getg().m.procid = 2
+       //nacl_exception_handler(funcPC(sigtramp), nil);
+}
+
+func crash() {
+       *(*int32)(nil) = 0
+}
+
+//go:nosplit
+func get_random_data(rnd *unsafe.Pointer, rnd_len *int32) {
+       *rnd = nil
+       *rnd_len = 0
+}
+
+func goenvs() {
+       goenvs_unix()
+}
+
+func initsig() {
+}
+
+//go:nosplit
+func usleep(us uint32) {
+       var ts timespec
+
+       ts.tv_sec = int64(us / 1e6)
+       ts.tv_nsec = int32(us%1e6) * 1e3
+       nacl_nanosleep(&ts, nil)
+}
+
+func mstart_nacl()
+
+func newosproc(mp *m, stk unsafe.Pointer) {
+       tls := (*[3]unsafe.Pointer)(unsafe.Pointer(&mp.tls))
+       tls[0] = unsafe.Pointer(mp.g0)
+       tls[1] = unsafe.Pointer(mp)
+       ret := nacl_thread_create(funcPC(mstart_nacl), stk, unsafe.Pointer(&tls[2]), nil)
+       if ret < 0 {
+               print("nacl_thread_create: error ", -ret, "\n")
+               gothrow("newosproc")
+       }
+}
+
+//go:nosplit
+func semacreate() uintptr {
+       var cond uintptr
+       systemstack(func() {
+               mu := nacl_mutex_create(0)
+               if mu < 0 {
+                       print("nacl_mutex_create: error ", -mu, "\n")
+                       gothrow("semacreate")
+               }
+               c := nacl_cond_create(0)
+               if c < 0 {
+                       print("nacl_cond_create: error ", -cond, "\n")
+                       gothrow("semacreate")
+               }
+               cond = uintptr(c)
+               _g_ := getg()
+               _g_.m.waitsemalock = uint32(mu)
+       })
+       return cond
+}
+
+//go:nosplit
+func semasleep(ns int64) int32 {
+       var ret int32
+
+       systemstack(func() {
+               _g_ := getg()
+               if nacl_mutex_lock(int32(_g_.m.waitsemalock)) < 0 {
+                       gothrow("semasleep")
+               }
+
+               for _g_.m.waitsemacount == 0 {
+                       if ns < 0 {
+                               if nacl_cond_wait(int32(_g_.m.waitsema), int32(_g_.m.waitsemalock)) < 0 {
+                                       gothrow("semasleep")
+                               }
+                       } else {
+                               var ts timespec
+                               end := ns + nanotime()
+                               ts.tv_sec = end / 1e9
+                               ts.tv_nsec = int32(end % 1e9)
+                               r := nacl_cond_timed_wait_abs(int32(_g_.m.waitsema), int32(_g_.m.waitsemalock), &ts)
+                               if r == -_ETIMEDOUT {
+                                       nacl_mutex_unlock(int32(_g_.m.waitsemalock))
+                                       ret = -1
+                                       return
+                               }
+                               if r < 0 {
+                                       gothrow("semasleep")
+                               }
+                       }
+               }
+
+               _g_.m.waitsemacount = 0
+               nacl_mutex_unlock(int32(_g_.m.waitsemalock))
+               ret = 0
+       })
+       return ret
+}
+
+//go:nosplit
+func semawakeup(mp *m) {
+       systemstack(func() {
+               if nacl_mutex_lock(int32(mp.waitsemalock)) < 0 {
+                       gothrow("semawakeup")
+               }
+               if mp.waitsemacount != 0 {
+                       gothrow("semawakeup")
+               }
+               mp.waitsemacount = 1
+               nacl_cond_signal(int32(mp.waitsema))
+               nacl_mutex_unlock(int32(mp.waitsemalock))
+       })
+}
+
+func memlimit() uintptr {
+       return 0
+}
+
+// This runs on a foreign stack, without an m or a g.  No stack split.
+//go:nosplit
+func badsignal2() {
+       write(2, unsafe.Pointer(&badsignal1[0]), int32(len(badsignal1)))
+       exit(2)
+}
+
+var badsignal1 = []byte("runtime: signal received on thread not created by Go.\n")
+
+func madvise(addr unsafe.Pointer, n uintptr, flags int32) {}
+func munmap(addr unsafe.Pointer, n uintptr)               {}
+func resetcpuprofiler(hz int32)                           {}
+func sigdisable(uint32)                                   {}
+func sigenable(uint32)                                    {}
+func closeonexec(int32)                                   {}
+
+var writelock uint32 // test-and-set spin lock for write
+
+/*
+An attempt at IRT. Doesn't work. See end of sys_nacl_amd64.s.
+
+void (*nacl_irt_query)(void);
+
+int8 nacl_irt_basic_v0_1_str[] = "nacl-irt-basic-0.1";
+void *nacl_irt_basic_v0_1[6]; // exit, gettod, clock, nanosleep, sched_yield, sysconf
+int32 nacl_irt_basic_v0_1_size = sizeof(nacl_irt_basic_v0_1);
+
+int8 nacl_irt_memory_v0_3_str[] = "nacl-irt-memory-0.3";
+void *nacl_irt_memory_v0_3[3]; // mmap, munmap, mprotect
+int32 nacl_irt_memory_v0_3_size = sizeof(nacl_irt_memory_v0_3);
+
+int8 nacl_irt_thread_v0_1_str[] = "nacl-irt-thread-0.1";
+void *nacl_irt_thread_v0_1[3]; // thread_create, thread_exit, thread_nice
+int32 nacl_irt_thread_v0_1_size = sizeof(nacl_irt_thread_v0_1);
+*/
diff --git a/src/runtime/os1_netbsd.go b/src/runtime/os1_netbsd.go
new file mode 100644 (file)
index 0000000..493be30
--- /dev/null
@@ -0,0 +1,265 @@
+// 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.
+
+package runtime
+
+import "unsafe"
+
+const (
+       _ESRCH   = 3
+       _ENOTSUP = 91
+
+       // From NetBSD's <sys/time.h>
+       _CLOCK_REALTIME  = 0
+       _CLOCK_VIRTUAL   = 1
+       _CLOCK_PROF      = 2
+       _CLOCK_MONOTONIC = 3
+)
+
+var sigset_none = sigset{}
+var sigset_all = sigset{[4]uint32{^uint32(0), ^uint32(0), ^uint32(0), ^uint32(0)}}
+
+// From NetBSD's <sys/sysctl.h>
+const (
+       _CTL_HW  = 6
+       _HW_NCPU = 3
+)
+
+func getncpu() int32 {
+       mib := [2]uint32{_CTL_HW, _HW_NCPU}
+       out := uint32(0)
+       nout := unsafe.Sizeof(out)
+       ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
+       if ret >= 0 {
+               return int32(out)
+       }
+       return 1
+}
+
+//go:nosplit
+func semacreate() uintptr {
+       return 1
+}
+
+//go:nosplit
+func semasleep(ns int64) int32 {
+       _g_ := getg()
+
+       // spin-mutex lock
+       for {
+               if xchg(&_g_.m.waitsemalock, 1) == 0 {
+                       break
+               }
+               osyield()
+       }
+
+       for {
+               // lock held
+               if _g_.m.waitsemacount == 0 {
+                       // sleep until semaphore != 0 or timeout.
+                       // thrsleep unlocks m.waitsemalock.
+                       if ns < 0 {
+                               // TODO(jsing) - potential deadlock!
+                               //
+                               // There is a potential deadlock here since we
+                               // have to release the waitsemalock mutex
+                               // before we call lwp_park() to suspend the
+                               // thread. This allows another thread to
+                               // release the lock and call lwp_unpark()
+                               // before the thread is actually suspended.
+                               // If this occurs the current thread will end
+                               // up sleeping indefinitely. Unfortunately
+                               // the NetBSD kernel does not appear to provide
+                               // a mechanism for unlocking the userspace
+                               // mutex once the thread is actually parked.
+                               atomicstore(&_g_.m.waitsemalock, 0)
+                               lwp_park(nil, 0, unsafe.Pointer(&_g_.m.waitsemacount), nil)
+                       } else {
+                               var ts timespec
+                               var nsec int32
+                               ns += nanotime()
+                               ts.set_sec(timediv(ns, 1000000000, &nsec))
+                               ts.set_nsec(nsec)
+                               // TODO(jsing) - potential deadlock!
+                               // See above for details.
+                               atomicstore(&_g_.m.waitsemalock, 0)
+                               lwp_park(&ts, 0, unsafe.Pointer(&_g_.m.waitsemacount), nil)
+                       }
+                       // reacquire lock
+                       for {
+                               if xchg(&_g_.m.waitsemalock, 1) == 0 {
+                                       break
+                               }
+                               osyield()
+                       }
+               }
+
+               // lock held (again)
+               if _g_.m.waitsemacount != 0 {
+                       // semaphore is available.
+                       _g_.m.waitsemacount--
+                       // spin-mutex unlock
+                       atomicstore(&_g_.m.waitsemalock, 0)
+                       return 0
+               }
+
+               // semaphore not available.
+               // if there is a timeout, stop now.
+               // otherwise keep trying.
+               if ns >= 0 {
+                       break
+               }
+       }
+
+       // lock held but giving up
+       // spin-mutex unlock
+       atomicstore(&_g_.m.waitsemalock, 0)
+       return -1
+}
+
+//go:nosplit
+func semawakeup(mp *m) {
+       // spin-mutex lock
+       for {
+               if xchg(&mp.waitsemalock, 1) == 0 {
+                       break
+               }
+               osyield()
+       }
+
+       mp.waitsemacount++
+       // TODO(jsing) - potential deadlock, see semasleep() for details.
+       // Confirm that LWP is parked before unparking...
+       ret := lwp_unpark(int32(mp.procid), unsafe.Pointer(&mp.waitsemacount))
+       if ret != 0 && ret != _ESRCH {
+               // semawakeup can be called on signal stack.
+               systemstack(func() {
+                       print("thrwakeup addr=", &mp.waitsemacount, " sem=", mp.waitsemacount, " ret=", ret, "\n")
+               })
+       }
+
+       // spin-mutex unlock
+       atomicstore(&mp.waitsemalock, 0)
+}
+
+func newosproc(mp *m, stk unsafe.Pointer) {
+       if false {
+               print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " id=", mp.id, "/", int32(mp.tls[0]), " ostk=", &mp, "\n")
+       }
+
+       mp.tls[0] = uintptr(mp.id) // so 386 asm can find it
+
+       var uc ucontextt
+       getcontext(unsafe.Pointer(&uc))
+
+       uc.uc_flags = _UC_SIGMASK | _UC_CPU
+       uc.uc_link = nil
+       uc.uc_sigmask = sigset_all
+
+       lwp_mcontext_init(&uc.uc_mcontext, stk, mp, mp.g0, funcPC(mstart))
+
+       ret := lwp_create(unsafe.Pointer(&uc), 0, unsafe.Pointer(&mp.procid))
+       if ret < 0 {
+               print("runtime: failed to create new OS thread (have ", mcount()-1, " already; errno=", -ret, ")\n")
+               gothrow("runtime.newosproc")
+       }
+}
+
+func osinit() {
+       ncpu = getncpu()
+}
+
+var urandom_data [_HashRandomBytes]byte
+var urandom_dev = []byte("/dev/urandom\x00")
+
+//go:nosplit
+func get_random_data(rnd *unsafe.Pointer, rnd_len *int32) {
+       fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0)
+       if read(fd, unsafe.Pointer(&urandom_data), _HashRandomBytes) == _HashRandomBytes {
+               *rnd = unsafe.Pointer(&urandom_data[0])
+               *rnd_len = _HashRandomBytes
+       } else {
+               *rnd = nil
+               *rnd_len = 0
+       }
+       close(fd)
+}
+
+func goenvs() {
+       goenvs_unix()
+}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
+func mpreinit(mp *m) {
+       mp.gsignal = malg(32 * 1024)
+       mp.gsignal.m = mp
+}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the new thread, can not allocate memory.
+func minit() {
+       _g_ := getg()
+       _g_.m.procid = uint64(lwp_self())
+
+       // Initialize signal handling
+       signalstack((*byte)(unsafe.Pointer(_g_.m.gsignal.stack.lo)), 32*1024)
+       sigprocmask(_SIG_SETMASK, &sigset_none, nil)
+}
+
+// Called from dropm to undo the effect of an minit.
+func unminit() {
+       signalstack(nil, 0)
+}
+
+func memlimit() uintptr {
+       return 0
+}
+
+func sigtramp()
+
+type sigactiont struct {
+       sa_sigaction uintptr
+       sa_mask      sigset
+       sa_flags     int32
+}
+
+func setsig(i int32, fn uintptr, restart bool) {
+       var sa sigactiont
+       sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK
+       if restart {
+               sa.sa_flags |= _SA_RESTART
+       }
+       sa.sa_mask = sigset_all
+       if fn == funcPC(sighandler) {
+               fn = funcPC(sigtramp)
+       }
+       sa.sa_sigaction = fn
+       sigaction(i, &sa, nil)
+}
+
+func getsig(i int32) uintptr {
+       var sa sigactiont
+       sigaction(i, nil, &sa)
+       if sa.sa_sigaction == funcPC(sigtramp) {
+               return funcPC(sighandler)
+       }
+       return sa.sa_sigaction
+}
+
+func signalstack(p *byte, n int32) {
+       var st sigaltstackt
+
+       st.ss_sp = uintptr(unsafe.Pointer(p))
+       st.ss_size = uintptr(n)
+       st.ss_flags = 0
+       if p == nil {
+               st.ss_flags = _SS_DISABLE
+       }
+       sigaltstack(&st, nil)
+}
+
+func unblocksignals() {
+       sigprocmask(_SIG_SETMASK, &sigset_none, nil)
+}
diff --git a/src/runtime/os1_netbsd_386.go b/src/runtime/os1_netbsd_386.go
new file mode 100644 (file)
index 0000000..037f7e3
--- /dev/null
@@ -0,0 +1,16 @@
+// 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.
+
+package runtime
+
+import "unsafe"
+
+func lwp_mcontext_init(mc *mcontextt, stk unsafe.Pointer, mp *m, gp *g, fn uintptr) {
+       // Machine dependent mcontext initialisation for LWP.
+       mc.__gregs[_REG_EIP] = uint32(funcPC(lwp_tramp))
+       mc.__gregs[_REG_UESP] = uint32(uintptr(stk))
+       mc.__gregs[_REG_EBX] = uint32(uintptr(unsafe.Pointer(mp)))
+       mc.__gregs[_REG_EDX] = uint32(uintptr(unsafe.Pointer(gp)))
+       mc.__gregs[_REG_ESI] = uint32(fn)
+}
diff --git a/src/runtime/os1_netbsd_amd64.go b/src/runtime/os1_netbsd_amd64.go
new file mode 100644 (file)
index 0000000..5118b0c
--- /dev/null
@@ -0,0 +1,16 @@
+// 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.
+
+package runtime
+
+import "unsafe"
+
+func lwp_mcontext_init(mc *mcontextt, stk unsafe.Pointer, mp *m, gp *g, fn uintptr) {
+       // Machine dependent mcontext initialisation for LWP.
+       mc.__gregs[_REG_RIP] = uint64(funcPC(lwp_tramp))
+       mc.__gregs[_REG_RSP] = uint64(uintptr(stk))
+       mc.__gregs[_REG_R8] = uint64(uintptr(unsafe.Pointer(mp)))
+       mc.__gregs[_REG_R9] = uint64(uintptr(unsafe.Pointer(gp)))
+       mc.__gregs[_REG_R12] = uint64(fn)
+}
diff --git a/src/runtime/os1_plan9.go b/src/runtime/os1_plan9.go
new file mode 100644 (file)
index 0000000..0f8da03
--- /dev/null
@@ -0,0 +1,270 @@
+// 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
+
+import "unsafe"
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
+func mpreinit(mp *m) {
+       // Initialize stack and goroutine for note handling.
+       mp.gsignal = malg(32 * 1024)
+       mp.gsignal.m = mp
+       mp.notesig = (*int8)(mallocgc(_ERRMAX, nil, _FlagNoScan))
+       // Initialize stack for handling strings from the
+       // errstr system call, as used in package syscall.
+       mp.errstr = (*byte)(mallocgc(_ERRMAX, nil, _FlagNoScan))
+}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the new thread, can not allocate memory.
+func minit() {
+       // Mask all SSE floating-point exceptions
+       // when running on the 64-bit kernel.
+       setfpmasks()
+}
+
+// Called from dropm to undo the effect of an minit.
+func unminit() {
+}
+
+var sysstat = []byte("/dev/sysstat\x00")
+
+func getproccount() int32 {
+       var buf [2048]byte
+       fd := open(&sysstat[0], _OREAD, 0)
+       if fd < 0 {
+               return 1
+       }
+       ncpu := int32(0)
+       for {
+               n := read(fd, unsafe.Pointer(&buf), int32(len(buf)))
+               if n <= 0 {
+                       break
+               }
+               for i := int32(0); i < n; i++ {
+                       if buf[i] == '\n' {
+                               ncpu++
+                       }
+               }
+       }
+       close(fd)
+       if ncpu == 0 {
+               ncpu = 1
+       }
+       return ncpu
+}
+
+var pid = []byte("#c/pid\x00")
+
+func getpid() uint64 {
+       var b [20]byte
+       fd := open(&pid[0], 0, 0)
+       if fd >= 0 {
+               read(fd, unsafe.Pointer(&b), int32(len(b)))
+               close(fd)
+       }
+       c := b[:]
+       for c[0] == ' ' || c[0] == '\t' {
+               c = c[1:]
+       }
+       return uint64(atoi(c))
+}
+
+func osinit() {
+       initBloc()
+       ncpu = getproccount()
+       getg().m.procid = getpid()
+       notify(unsafe.Pointer(funcPC(sigtramp)))
+}
+
+func crash() {
+       notify(nil)
+       *(*int)(nil) = 0
+}
+
+var random_data [_HashRandomBytes]byte
+var random_dev = []byte("/dev/random\x00")
+
+//go:nosplit
+func get_random_data(rnd *unsafe.Pointer, rnd_len *int32) {
+       fd := open(&random_dev[0], 0 /* O_RDONLY */, 0)
+       if read(fd, unsafe.Pointer(&random_data), _HashRandomBytes) == _HashRandomBytes {
+               *rnd = unsafe.Pointer(&random_data[0])
+               *rnd_len = _HashRandomBytes
+       } else {
+               *rnd = nil
+               *rnd_len = 0
+       }
+       close(fd)
+}
+
+func goenvs() {
+}
+
+func initsig() {
+}
+
+//go:nosplit
+func osyield() {
+       sleep(0)
+}
+
+//go:nosplit
+func usleep(µs uint32) {
+       ms := int32(µs / 1000)
+       if ms == 0 {
+               ms = 1
+       }
+       sleep(ms)
+}
+
+//go:nosplit
+func nanotime() int64 {
+       var scratch int64
+       ns := nsec(&scratch)
+       // TODO(aram): remove hack after I fix _nsec in the pc64 kernel.
+       if ns == 0 {
+               return scratch
+       }
+       return ns
+}
+
+//go:nosplit
+func itoa(buf []byte, val uint64) []byte {
+       i := len(buf) - 1
+       for val >= 10 {
+               buf[i] = byte(val%10 + '0')
+               i--
+               val /= 10
+       }
+       buf[i] = byte(val + '0')
+       return buf[i:]
+}
+
+var goexits = []byte("go: exit ")
+
+func goexitsall(status *byte) {
+       var buf [_ERRMAX]byte
+       n := copy(buf[:], goexits)
+       n = copy(buf[n:], gostringnocopy(status))
+       pid := getpid()
+       for mp := (*m)(atomicloadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink {
+               if mp.procid != pid {
+                       postnote(mp.procid, buf[:])
+               }
+       }
+}
+
+var procdir = []byte("/proc/")
+var notefile = []byte("/note\x00")
+
+func postnote(pid uint64, msg []byte) int {
+       var buf [128]byte
+       var tmp [32]byte
+       n := copy(buf[:], procdir)
+       n += copy(buf[n:], itoa(tmp[:], pid))
+       copy(buf[n:], notefile)
+       fd := open(&buf[0], _OWRITE, 0)
+       if fd < 0 {
+               return -1
+       }
+       len := findnull(&msg[0])
+       if write(uintptr(fd), (unsafe.Pointer)(&msg[0]), int32(len)) != int64(len) {
+               close(fd)
+               return -1
+       }
+       close(fd)
+       return 0
+}
+
+//go:nosplit
+func exit(e int) {
+       var status []byte
+       if e == 0 {
+               status = []byte("\x00")
+       } else {
+               // build error string
+               var tmp [32]byte
+               status = []byte(gostringnocopy(&itoa(tmp[:], uint64(e))[0]) + "\x00")
+       }
+       goexitsall(&status[0])
+       exits(&status[0])
+}
+
+func newosproc(mp *m, stk unsafe.Pointer) {
+       if false {
+               print("newosproc mp=", mp, " ostk=", &mp, "\n")
+       }
+       pid := rfork(_RFPROC | _RFMEM | _RFNOWAIT)
+       if pid < 0 {
+               gothrow("newosproc: rfork failed")
+       }
+       if pid == 0 {
+               tstart_plan9(mp)
+       }
+}
+
+//go:nosplit
+func semacreate() uintptr {
+       return 1
+}
+
+//go:nosplit
+func semasleep(ns int64) int {
+       _g_ := getg()
+       if ns >= 0 {
+               ms := timediv(ns, 1000000, nil)
+               if ms == 0 {
+                       ms = 1
+               }
+               ret := plan9_tsemacquire(&_g_.m.waitsemacount, ms)
+               if ret == 1 {
+                       return 0 // success
+               }
+               return -1 // timeout or interrupted
+       }
+       for plan9_semacquire(&_g_.m.waitsemacount, 1) < 0 {
+               // interrupted; try again (c.f. lock_sema.go)
+       }
+       return 0 // success
+}
+
+//go:nosplit
+func semawakeup(mp *m) {
+       plan9_semrelease(&mp.waitsemacount, 1)
+}
+
+//go:nosplit
+func read(fd int32, buf unsafe.Pointer, n int32) int32 {
+       return pread(fd, buf, n, -1)
+}
+
+//go:nosplit
+func write(fd uintptr, buf unsafe.Pointer, n int32) int64 {
+       return int64(pwrite(int32(fd), buf, n, -1))
+}
+
+func memlimit() uint64 {
+       return 0
+}
+
+var _badsignal = []byte("runtime: signal received on thread not created by Go.\n")
+
+// This runs on a foreign stack, without an m or a g.  No stack split.
+//go:nosplit
+func badsignal2() {
+       pwrite(2, unsafe.Pointer(&_badsignal[0]), int32(len(_badsignal)), -1)
+       exits(&_badsignal[0])
+}
+
+func atoi(b []byte) int {
+       n := 0
+       for len(b) > 0 && '0' <= b[0] && b[0] <= '9' {
+               n = n*10 + int(b[0]) - '0'
+               b = b[1:]
+       }
+       return n
+}
diff --git a/src/runtime/os1_windows.go b/src/runtime/os1_windows.go
new file mode 100644 (file)
index 0000000..57ea050
--- /dev/null
@@ -0,0 +1,564 @@
+// 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.
+
+package runtime
+
+import (
+       "unsafe"
+)
+
+//go:cgo_import_dynamic runtime._AddVectoredExceptionHandler AddVectoredExceptionHandler "kernel32.dll"
+//go:cgo_import_dynamic runtime._CloseHandle CloseHandle "kernel32.dll"
+//go:cgo_import_dynamic runtime._CreateEventA CreateEventA "kernel32.dll"
+//go:cgo_import_dynamic runtime._CreateThread CreateThread "kernel32.dll"
+//go:cgo_import_dynamic runtime._CreateWaitableTimerA CreateWaitableTimerA "kernel32.dll"
+//go:cgo_import_dynamic runtime._CryptAcquireContextW CryptAcquireContextW "advapi32.dll"
+//go:cgo_import_dynamic runtime._CryptGenRandom CryptGenRandom "advapi32.dll"
+//go:cgo_import_dynamic runtime._CryptReleaseContext CryptReleaseContext "advapi32.dll"
+//go:cgo_import_dynamic runtime._DuplicateHandle DuplicateHandle "kernel32.dll"
+//go:cgo_import_dynamic runtime._ExitProcess ExitProcess "kernel32.dll"
+//go:cgo_import_dynamic runtime._FreeEnvironmentStringsW FreeEnvironmentStringsW "kernel32.dll"
+//go:cgo_import_dynamic runtime._GetEnvironmentStringsW GetEnvironmentStringsW "kernel32.dll"
+//go:cgo_import_dynamic runtime._GetProcAddress GetProcAddress "kernel32.dll"
+//go:cgo_import_dynamic runtime._GetStdHandle GetStdHandle "kernel32.dll"
+//go:cgo_import_dynamic runtime._GetSystemInfo GetSystemInfo "kernel32.dll"
+//go:cgo_import_dynamic runtime._GetThreadContext GetThreadContext "kernel32.dll"
+//go:cgo_import_dynamic runtime._LoadLibraryW LoadLibraryW "kernel32.dll"
+//go:cgo_import_dynamic runtime._LoadLibraryA LoadLibraryA "kernel32.dll"
+//go:cgo_import_dynamic runtime._NtWaitForSingleObject NtWaitForSingleObject "ntdll.dll"
+//go:cgo_import_dynamic runtime._ResumeThread ResumeThread "kernel32.dll"
+//go:cgo_import_dynamic runtime._SetConsoleCtrlHandler SetConsoleCtrlHandler "kernel32.dll"
+//go:cgo_import_dynamic runtime._SetEvent SetEvent "kernel32.dll"
+//go:cgo_import_dynamic runtime._SetProcessPriorityBoost SetProcessPriorityBoost "kernel32.dll"
+//go:cgo_import_dynamic runtime._SetThreadPriority SetThreadPriority "kernel32.dll"
+//go:cgo_import_dynamic runtime._SetUnhandledExceptionFilter SetUnhandledExceptionFilter "kernel32.dll"
+//go:cgo_import_dynamic runtime._SetWaitableTimer SetWaitableTimer "kernel32.dll"
+//go:cgo_import_dynamic runtime._Sleep Sleep "kernel32.dll"
+//go:cgo_import_dynamic runtime._SuspendThread SuspendThread "kernel32.dll"
+//go:cgo_import_dynamic runtime._WaitForSingleObject WaitForSingleObject "kernel32.dll"
+//go:cgo_import_dynamic runtime._WriteFile WriteFile "kernel32.dll"
+//go:cgo_import_dynamic runtime._timeBeginPeriod timeBeginPeriod "winmm.dll"
+
+var (
+       _AddVectoredExceptionHandler,
+       _CloseHandle,
+       _CreateEventA,
+       _CreateThread,
+       _CreateWaitableTimerA,
+       _CryptAcquireContextW,
+       _CryptGenRandom,
+       _CryptReleaseContext,
+       _DuplicateHandle,
+       _ExitProcess,
+       _FreeEnvironmentStringsW,
+       _GetEnvironmentStringsW,
+       _GetProcAddress,
+       _GetStdHandle,
+       _GetSystemInfo,
+       _GetThreadContext,
+       _LoadLibraryW,
+       _LoadLibraryA,
+       _NtWaitForSingleObject,
+       _ResumeThread,
+       _SetConsoleCtrlHandler,
+       _SetEvent,
+       _SetProcessPriorityBoost,
+       _SetThreadPriority,
+       _SetUnhandledExceptionFilter,
+       _SetWaitableTimer,
+       _Sleep,
+       _SuspendThread,
+       _WaitForSingleObject,
+       _WriteFile,
+       _timeBeginPeriod stdFunction
+)
+
+var _GetQueuedCompletionStatusEx stdFunction
+
+// in sys_windows_386.s and sys_windows_amd64.s
+func externalthreadhandler()
+func exceptiontramp()
+func firstcontinuetramp()
+func lastcontinuetramp()
+
+//go:nosplit
+func getLoadLibrary() uintptr {
+       return uintptr(unsafe.Pointer(_LoadLibraryW))
+}
+
+//go:nosplit
+func getGetProcAddress() uintptr {
+       return uintptr(unsafe.Pointer(_GetProcAddress))
+}
+
+func getproccount() int32 {
+       var info systeminfo
+       stdcall1(_GetSystemInfo, uintptr(unsafe.Pointer(&info)))
+       return int32(info.dwnumberofprocessors)
+}
+
+const (
+       currentProcess = ^uintptr(0) // -1 = current process
+       currentThread  = ^uintptr(1) // -2 = current thread
+)
+
+var (
+       kernel32Name                    = []byte("kernel32.dll\x00")
+       addVectoredContinueHandlerName  = []byte("AddVectoredContinueHandler\x00")
+       getQueuedCompletionStatusExName = []byte("GetQueuedCompletionStatusEx\x00")
+)
+
+func osinit() {
+       setBadSignalMsg()
+
+       kernel32 := stdcall1(_LoadLibraryA, uintptr(unsafe.Pointer(&kernel32Name[0])))
+
+       externalthreadhandlerp = funcPC(externalthreadhandler)
+
+       stdcall2(_AddVectoredExceptionHandler, 1, funcPC(exceptiontramp))
+       addVectoredContinueHandler := uintptr(0)
+       if kernel32 != 0 {
+               addVectoredContinueHandler = stdcall2(_GetProcAddress, kernel32, uintptr(unsafe.Pointer(&addVectoredContinueHandlerName[0])))
+       }
+       if addVectoredContinueHandler == 0 || unsafe.Sizeof(&kernel32) == 4 {
+               // use SetUnhandledExceptionFilter for windows-386 or
+               // if VectoredContinueHandler is unavailable.
+               // note: SetUnhandledExceptionFilter handler won't be called, if debugging.
+               stdcall1(_SetUnhandledExceptionFilter, funcPC(lastcontinuetramp))
+       } else {
+               stdcall2(stdFunction(unsafe.Pointer(addVectoredContinueHandler)), 1, funcPC(firstcontinuetramp))
+               stdcall2(stdFunction(unsafe.Pointer(addVectoredContinueHandler)), 0, funcPC(lastcontinuetramp))
+       }
+
+       stdcall2(_SetConsoleCtrlHandler, funcPC(ctrlhandler), 1)
+
+       stdcall1(_timeBeginPeriod, 1)
+
+       ncpu = getproccount()
+
+       // Windows dynamic priority boosting assumes that a process has different types
+       // of dedicated threads -- GUI, IO, computational, etc. Go processes use
+       // equivalent threads that all do a mix of GUI, IO, computations, etc.
+       // In such context dynamic priority boosting does nothing but harm, so we turn it off.
+       stdcall2(_SetProcessPriorityBoost, currentProcess, 1)
+
+       if kernel32 != 0 {
+               _GetQueuedCompletionStatusEx = stdFunction(unsafe.Pointer(stdcall2(_GetProcAddress, kernel32, uintptr(unsafe.Pointer(&getQueuedCompletionStatusExName[0])))))
+       }
+}
+
+var random_data [_HashRandomBytes]byte
+
+//go:nosplit
+func get_random_data(rnd *unsafe.Pointer, rnd_len *int32) {
+       const (
+               prov_rsa_full       = 1
+               crypt_verifycontext = 0xF0000000
+       )
+       var handle uintptr
+       *rnd = nil
+       *rnd_len = 0
+       if stdcall5(_CryptAcquireContextW, uintptr(unsafe.Pointer(&handle)), 0, 0, prov_rsa_full, crypt_verifycontext) != 0 {
+               if stdcall3(_CryptGenRandom, handle, _HashRandomBytes, uintptr(unsafe.Pointer(&random_data[0]))) != 0 {
+                       *rnd = unsafe.Pointer(&random_data[0])
+                       *rnd_len = _HashRandomBytes
+               }
+               stdcall2(_CryptReleaseContext, handle, 0)
+       }
+}
+
+func goenvs() {
+       var p *uint16
+
+       env := (*uint16)(unsafe.Pointer(stdcall0(_GetEnvironmentStringsW)))
+
+       n := 0
+       for p = env; *p != 0; n++ {
+               p = (*uint16)(add(unsafe.Pointer(p), uintptr(findnullw(p)+1)*unsafe.Sizeof(*p)))
+       }
+
+       envs = makeStringSlice(int(n))
+
+       p = env
+       for i := 0; i < n; i++ {
+               envs[i] = gostringw(p)
+               p = (*uint16)(add(unsafe.Pointer(p), uintptr(findnullw(p)+1)*unsafe.Sizeof(*p)))
+       }
+
+       stdcall1(_FreeEnvironmentStringsW, uintptr(unsafe.Pointer(env)))
+}
+
+//go:nosplit
+func exit(code int32) {
+       stdcall1(_ExitProcess, uintptr(code))
+}
+
+//go:nosplit
+func write(fd uintptr, buf unsafe.Pointer, n int32) int32 {
+       const (
+               _STD_OUTPUT_HANDLE = ^uintptr(10) // -11
+               _STD_ERROR_HANDLE  = ^uintptr(11) // -12
+       )
+       var handle uintptr
+       switch fd {
+       case 1:
+               handle = stdcall1(_GetStdHandle, _STD_OUTPUT_HANDLE)
+       case 2:
+               handle = stdcall1(_GetStdHandle, _STD_ERROR_HANDLE)
+       default:
+               // assume fd is real windows handle.
+               handle = fd
+       }
+       var written uint32
+       stdcall5(_WriteFile, handle, uintptr(buf), uintptr(n), uintptr(unsafe.Pointer(&written)), 0)
+       return int32(written)
+}
+
+//go:nosplit
+func semasleep(ns int64) int32 {
+       // store ms in ns to save stack space
+       if ns < 0 {
+               ns = _INFINITE
+       } else {
+               ns = int64(timediv(ns, 1000000, nil))
+               if ns == 0 {
+                       ns = 1
+               }
+       }
+       if stdcall2(_WaitForSingleObject, getg().m.waitsema, uintptr(ns)) != 0 {
+               return -1 // timeout
+       }
+       return 0
+}
+
+//go:nosplit
+func semawakeup(mp *m) {
+       stdcall1(_SetEvent, mp.waitsema)
+}
+
+//go:nosplit
+func semacreate() uintptr {
+       return stdcall4(_CreateEventA, 0, 0, 0, 0)
+}
+
+func newosproc(mp *m, stk unsafe.Pointer) {
+       const _STACK_SIZE_PARAM_IS_A_RESERVATION = 0x00010000
+       thandle := stdcall6(_CreateThread, 0, 0x20000,
+               funcPC(tstart_stdcall), uintptr(unsafe.Pointer(mp)),
+               _STACK_SIZE_PARAM_IS_A_RESERVATION, 0)
+       if thandle == 0 {
+               println("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", getlasterror(), ")")
+               gothrow("runtime.newosproc")
+       }
+}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
+func mpreinit(mp *m) {
+}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the new thread, can not allocate memory.
+func minit() {
+       var thandle uintptr
+       stdcall7(_DuplicateHandle, currentProcess, currentThread, currentProcess, uintptr(unsafe.Pointer(&thandle)), 0, 0, _DUPLICATE_SAME_ACCESS)
+       atomicstoreuintptr(&getg().m.thread, thandle)
+}
+
+// Called from dropm to undo the effect of an minit.
+func unminit() {
+       tp := &getg().m.thread
+       stdcall1(_CloseHandle, *tp)
+       *tp = 0
+}
+
+// Described in http://www.dcl.hpi.uni-potsdam.de/research/WRK/2007/08/getting-os-information-the-kuser_shared_data-structure/
+type _KSYSTEM_TIME struct {
+       LowPart   uint32
+       High1Time int32
+       High2Time int32
+}
+
+const (
+       _INTERRUPT_TIME = 0x7ffe0008
+       _SYSTEM_TIME    = 0x7ffe0014
+)
+
+//go:nosplit
+func systime(addr uintptr) int64 {
+       timeaddr := (*_KSYSTEM_TIME)(unsafe.Pointer(addr))
+
+       var t _KSYSTEM_TIME
+       for i := 1; i < 10000; i++ {
+               // these fields must be read in that order (see URL above)
+               t.High1Time = timeaddr.High1Time
+               t.LowPart = timeaddr.LowPart
+               t.High2Time = timeaddr.High2Time
+               if t.High1Time == t.High2Time {
+                       return int64(t.High1Time)<<32 | int64(t.LowPart)
+               }
+               if (i % 100) == 0 {
+                       osyield()
+               }
+       }
+       systemstack(func() {
+               gothrow("interrupt/system time is changing too fast")
+       })
+       return 0
+}
+
+//go:nosplit
+func unixnano() int64 {
+       return (systime(_SYSTEM_TIME) - 116444736000000000) * 100
+}
+
+//go:nosplit
+func nanotime() int64 {
+       return systime(_INTERRUPT_TIME) * 100
+}
+
+// Calling stdcall on os stack.
+//go:nosplit
+func stdcall(fn stdFunction) uintptr {
+       gp := getg()
+       mp := gp.m
+       mp.libcall.fn = uintptr(unsafe.Pointer(fn))
+
+       if mp.profilehz != 0 {
+               // leave pc/sp for cpu profiler
+               mp.libcallg = gp
+               mp.libcallpc = getcallerpc(unsafe.Pointer(&fn))
+               // sp must be the last, because once async cpu profiler finds
+               // all three values to be non-zero, it will use them
+               mp.libcallsp = getcallersp(unsafe.Pointer(&fn))
+       }
+       asmcgocall(unsafe.Pointer(funcPC(asmstdcall)), unsafe.Pointer(&mp.libcall))
+       mp.libcallsp = 0
+       return mp.libcall.r1
+}
+
+//go:nosplit
+func stdcall0(fn stdFunction) uintptr {
+       mp := getg().m
+       mp.libcall.n = 0
+       mp.libcall.args = uintptr(noescape(unsafe.Pointer(&fn))) // it's unused but must be non-nil, otherwise crashes
+       return stdcall(fn)
+}
+
+//go:nosplit
+func stdcall1(fn stdFunction, a0 uintptr) uintptr {
+       mp := getg().m
+       mp.libcall.n = 1
+       mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
+       return stdcall(fn)
+}
+
+//go:nosplit
+func stdcall2(fn stdFunction, a0, a1 uintptr) uintptr {
+       mp := getg().m
+       mp.libcall.n = 2
+       mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
+       return stdcall(fn)
+}
+
+//go:nosplit
+func stdcall3(fn stdFunction, a0, a1, a2 uintptr) uintptr {
+       mp := getg().m
+       mp.libcall.n = 3
+       mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
+       return stdcall(fn)
+}
+
+//go:nosplit
+func stdcall4(fn stdFunction, a0, a1, a2, a3 uintptr) uintptr {
+       mp := getg().m
+       mp.libcall.n = 4
+       mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
+       return stdcall(fn)
+}
+
+//go:nosplit
+func stdcall5(fn stdFunction, a0, a1, a2, a3, a4 uintptr) uintptr {
+       mp := getg().m
+       mp.libcall.n = 5
+       mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
+       return stdcall(fn)
+}
+
+//go:nosplit
+func stdcall6(fn stdFunction, a0, a1, a2, a3, a4, a5 uintptr) uintptr {
+       mp := getg().m
+       mp.libcall.n = 6
+       mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
+       return stdcall(fn)
+}
+
+//go:nosplit
+func stdcall7(fn stdFunction, a0, a1, a2, a3, a4, a5, a6 uintptr) uintptr {
+       mp := getg().m
+       mp.libcall.n = 7
+       mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
+       return stdcall(fn)
+}
+
+// in sys_windows_386.s and sys_windows_amd64.s
+func usleep1(usec uint32)
+
+//go:nosplit
+func osyield() {
+       usleep1(1)
+}
+
+//go:nosplit
+func usleep(us uint32) {
+       // Have 1us units; want 100ns units.
+       usleep1(10 * us)
+}
+
+func issigpanic(code uint32) uint32 {
+       switch code {
+       default:
+               return 0
+       case _EXCEPTION_ACCESS_VIOLATION:
+       case _EXCEPTION_INT_DIVIDE_BY_ZERO:
+       case _EXCEPTION_INT_OVERFLOW:
+       case _EXCEPTION_FLT_DENORMAL_OPERAND:
+       case _EXCEPTION_FLT_DIVIDE_BY_ZERO:
+       case _EXCEPTION_FLT_INEXACT_RESULT:
+       case _EXCEPTION_FLT_OVERFLOW:
+       case _EXCEPTION_FLT_UNDERFLOW:
+       case _EXCEPTION_BREAKPOINT:
+       }
+       return 1
+}
+
+func initsig() {
+       /*
+               // TODO(brainman): I don't think we need that bit of code
+               // following line keeps these functions alive at link stage
+               // if there's a better way please write it here
+               void *e = runtime·exceptiontramp;
+               void *f = runtime·firstcontinuetramp;
+               void *l = runtime·lastcontinuetramp;
+               USED(e);
+               USED(f);
+               USED(l);
+       */
+}
+
+func ctrlhandler1(_type uint32) uint32 {
+       var s uint32
+
+       switch _type {
+       case _CTRL_C_EVENT, _CTRL_BREAK_EVENT:
+               s = _SIGINT
+       default:
+               return 0
+       }
+
+       if sigsend(s) {
+               return 1
+       }
+       exit(2) // SIGINT, SIGTERM, etc
+       return 0
+}
+
+// in sys_windows_386.s and sys_windows_amd64.s
+func profileloop()
+
+var profiletimer uintptr
+
+func profilem(mp *m) {
+       var r *context
+       rbuf := make([]byte, unsafe.Sizeof(*r)+15)
+
+       tls := &mp.tls[0]
+       if mp == &m0 {
+               tls = &tls0[0]
+       }
+       gp := *((**g)(unsafe.Pointer(tls)))
+
+       // align Context to 16 bytes
+       r = (*context)(unsafe.Pointer((uintptr(unsafe.Pointer(&rbuf[15]))) &^ 15))
+       r.contextflags = _CONTEXT_CONTROL
+       stdcall2(_GetThreadContext, mp.thread, uintptr(unsafe.Pointer(r)))
+       dosigprof(r, gp, mp)
+}
+
+func profileloop1() {
+       stdcall2(_SetThreadPriority, currentThread, _THREAD_PRIORITY_HIGHEST)
+
+       for {
+               stdcall2(_WaitForSingleObject, profiletimer, _INFINITE)
+               first := (*m)(atomicloadp(unsafe.Pointer(&allm)))
+               for mp := first; mp != nil; mp = mp.alllink {
+                       thread := atomicloaduintptr(&mp.thread)
+                       // Do not profile threads blocked on Notes,
+                       // this includes idle worker threads,
+                       // idle timer thread, idle heap scavenger, etc.
+                       if thread == 0 || mp.profilehz == 0 || mp.blocked {
+                               continue
+                       }
+                       stdcall1(_SuspendThread, thread)
+                       if mp.profilehz != 0 && !mp.blocked {
+                               profilem(mp)
+                       }
+                       stdcall1(_ResumeThread, thread)
+               }
+       }
+}
+
+var cpuprofilerlock mutex
+
+func resetcpuprofiler(hz int32) {
+       lock(&cpuprofilerlock)
+       if profiletimer == 0 {
+               timer := stdcall3(_CreateWaitableTimerA, 0, 0, 0)
+               atomicstoreuintptr(&profiletimer, timer)
+               thread := stdcall6(_CreateThread, 0, 0, funcPC(profileloop), 0, 0, 0)
+               stdcall2(_SetThreadPriority, thread, _THREAD_PRIORITY_HIGHEST)
+               stdcall1(_CloseHandle, thread)
+       }
+       unlock(&cpuprofilerlock)
+
+       ms := int32(0)
+       due := ^int64(^uint64(1 << 63))
+       if hz > 0 {
+               ms = 1000 / hz
+               if ms == 0 {
+                       ms = 1
+               }
+               due = int64(ms) * -10000
+       }
+       stdcall6(_SetWaitableTimer, profiletimer, uintptr(unsafe.Pointer(&due)), uintptr(ms), 0, 0, 0)
+       atomicstore((*uint32)(unsafe.Pointer(&getg().m.profilehz)), uint32(hz))
+}
+
+func memlimit() uintptr {
+       return 0
+}
+
+var (
+       badsignalmsg [100]byte
+       badsignallen int32
+)
+
+func setBadSignalMsg() {
+       const msg = "runtime: signal received on thread not created by Go.\n"
+       for i, c := range msg {
+               badsignalmsg[i] = byte(c)
+               badsignallen++
+       }
+}
+
+func crash() {
+       // TODO: This routine should do whatever is needed
+       // to make the Windows program abort/crash as it
+       // would if Go was not intercepting signals.
+       // On Unix the routine would remove the custom signal
+       // handler and then raise a signal (like SIGABRT).
+       // Something like that should happen here.
+       // It's okay to leave this empty for now: if crash returns
+       // the ordinary exit-after-panic happens.
+}
diff --git a/src/runtime/os1_windows_386.go b/src/runtime/os1_windows_386.go
new file mode 100644 (file)
index 0000000..0afef91
--- /dev/null
@@ -0,0 +1,118 @@
+// 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.
+
+package runtime
+
+import (
+       "unsafe"
+)
+
+var text struct{}
+
+func dumpregs(r *context) {
+       print("eax     ", hex(r.eax), "\n")
+       print("ebx     ", hex(r.ebx), "\n")
+       print("ecx     ", hex(r.ecx), "\n")
+       print("edx     ", hex(r.edx), "\n")
+       print("edi     ", hex(r.edi), "\n")
+       print("esi     ", hex(r.esi), "\n")
+       print("ebp     ", hex(r.ebp), "\n")
+       print("esp     ", hex(r.esp), "\n")
+       print("eip     ", hex(r.eip), "\n")
+       print("eflags  ", hex(r.eflags), "\n")
+       print("cs      ", hex(r.segcs), "\n")
+       print("fs      ", hex(r.segfs), "\n")
+       print("gs      ", hex(r.seggs), "\n")
+}
+
+func isgoexception(info *exceptionrecord, r *context) bool {
+       // Only handle exception if executing instructions in Go binary
+       // (not Windows library code).
+       if r.eip < uint32(uintptr(unsafe.Pointer(&text))) || uint32(uintptr(unsafe.Pointer(&etext))) < r.eip {
+               return false
+       }
+
+       if issigpanic(info.exceptioncode) == 0 {
+               return false
+       }
+
+       return true
+}
+
+// Called by sigtramp from Windows VEH handler.
+// Return value signals whether the exception has been handled (EXCEPTION_CONTINUE_EXECUTION)
+// or should be made available to other handlers in the chain (EXCEPTION_CONTINUE_SEARCH).
+func exceptionhandler(info *exceptionrecord, r *context, gp *g) int32 {
+       if !isgoexception(info, r) {
+               return _EXCEPTION_CONTINUE_SEARCH
+       }
+
+       // Make it look like a call to the signal func.
+       // Have to pass arguments out of band since
+       // augmenting the stack frame would break
+       // the unwinding code.
+       gp.sig = info.exceptioncode
+       gp.sigcode0 = uintptr(info.exceptioninformation[0])
+       gp.sigcode1 = uintptr(info.exceptioninformation[1])
+       gp.sigpc = uintptr(r.eip)
+
+       // Only push runtime·sigpanic if r->eip != 0.
+       // If r->eip == 0, probably panicked because of a
+       // call to a nil func.  Not pushing that onto sp will
+       // make the trace look like a call to runtime·sigpanic instead.
+       // (Otherwise the trace will end at runtime·sigpanic and we
+       // won't get to see who faulted.)
+       if r.eip != 0 {
+               sp := unsafe.Pointer(uintptr(r.esp))
+               sp = add(sp, ^uintptr(unsafe.Sizeof(uintptr(0))-1)) // sp--
+               *((*uintptr)(sp)) = uintptr(r.eip)
+               r.esp = uint32(uintptr(sp))
+       }
+       r.eip = uint32(funcPC(sigpanic))
+       return _EXCEPTION_CONTINUE_EXECUTION
+}
+
+// lastcontinuehandler is reached, because runtime cannot handle
+// current exception. lastcontinuehandler will print crash info and exit.
+func lastcontinuehandler(info *exceptionrecord, r *context, gp *g) uint32 {
+       _g_ := getg()
+
+       if panicking != 0 { // traceback already printed
+               exit(2)
+       }
+       panicking = 1
+
+       print("Exception ", hex(info.exceptioncode), " ", hex(info.exceptioninformation[0]), " ", hex(info.exceptioninformation[1]), " ", hex(r.eip), "\n")
+
+       print("PC=", hex(r.eip), "\n")
+       if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 {
+               print("signal arrived during cgo execution\n")
+               gp = _g_.m.lockedg
+       }
+       print("\n")
+
+       var docrash bool
+       if gotraceback(&docrash) > 0 {
+               tracebacktrap(uintptr(r.eip), uintptr(r.esp), 0, gp)
+               tracebackothers(gp)
+               dumpregs(r)
+       }
+
+       if docrash {
+               crash()
+       }
+
+       exit(2)
+       return 0 // not reached
+}
+
+func sigenable(sig uint32) {
+}
+
+func sigdisable(sig uint32) {
+}
+
+func dosigprof(r *context, gp *g, mp *m) {
+       sigprof((*byte)(unsafe.Pointer(uintptr(r.eip))), (*byte)(unsafe.Pointer(uintptr(r.esp))), nil, gp, mp)
+}
diff --git a/src/runtime/os1_windows_amd64.go b/src/runtime/os1_windows_amd64.go
new file mode 100644 (file)
index 0000000..0d21b38
--- /dev/null
@@ -0,0 +1,137 @@
+// 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.
+
+package runtime
+
+import (
+       "unsafe"
+)
+
+var text struct{}
+
+func dumpregs(r *context) {
+       print("rax     ", hex(r.rax), "\n")
+       print("rbx     ", hex(r.rbx), "\n")
+       print("rcx     ", hex(r.rcx), "\n")
+       print("rdi     ", hex(r.rdi), "\n")
+       print("rsi     ", hex(r.rsi), "\n")
+       print("rbp     ", hex(r.rbp), "\n")
+       print("rsp     ", hex(r.rsp), "\n")
+       print("r8      ", hex(r.r8), "\n")
+       print("r9      ", hex(r.r9), "\n")
+       print("r10     ", hex(r.r10), "\n")
+       print("r11     ", hex(r.r11), "\n")
+       print("r12     ", hex(r.r12), "\n")
+       print("r13     ", hex(r.r13), "\n")
+       print("r14     ", hex(r.r14), "\n")
+       print("r15     ", hex(r.r15), "\n")
+       print("rip     ", hex(r.rip), "\n")
+       print("rflags  ", hex(r.eflags), "\n")
+       print("cs      ", hex(r.segcs), "\n")
+       print("fs      ", hex(r.segfs), "\n")
+       print("gs      ", hex(r.seggs), "\n")
+}
+
+func isgoexception(info *exceptionrecord, r *context) bool {
+       // Only handle exception if executing instructions in Go binary
+       // (not Windows library code).
+       if r.rip < uint64(uintptr(unsafe.Pointer(&text))) || uint64(uintptr(unsafe.Pointer(&etext))) < r.rip {
+               return false
+       }
+
+       if issigpanic(info.exceptioncode) == 0 {
+               return false
+       }
+
+       return true
+}
+
+// Called by sigtramp from Windows VEH handler.
+// Return value signals whether the exception has been handled (EXCEPTION_CONTINUE_EXECUTION)
+// or should be made available to other handlers in the chain (EXCEPTION_CONTINUE_SEARCH).
+
+func exceptionhandler(info *exceptionrecord, r *context, gp *g) int32 {
+       if !isgoexception(info, r) {
+               return _EXCEPTION_CONTINUE_SEARCH
+       }
+
+       // Make it look like a call to the signal func.
+       // Have to pass arguments out of band since
+       // augmenting the stack frame would break
+       // the unwinding code.
+       gp.sig = info.exceptioncode
+       gp.sigcode0 = uintptr(info.exceptioninformation[0])
+       gp.sigcode1 = uintptr(info.exceptioninformation[1])
+       gp.sigpc = uintptr(r.rip)
+
+       // Only push runtime·sigpanic if r->rip != 0.
+       // If r->rip == 0, probably panicked because of a
+       // call to a nil func.  Not pushing that onto sp will
+       // make the trace look like a call to runtime·sigpanic instead.
+       // (Otherwise the trace will end at runtime·sigpanic and we
+       // won't get to see who faulted.)
+       if r.rip != 0 {
+               sp := unsafe.Pointer(uintptr(r.rsp))
+               sp = add(sp, ^uintptr(unsafe.Sizeof(uintptr(0))-1)) // sp--
+               *((*uintptr)(sp)) = uintptr(r.rip)
+               r.rsp = uint64(uintptr(sp))
+       }
+       r.rip = uint64(funcPC(sigpanic))
+       return _EXCEPTION_CONTINUE_EXECUTION
+}
+
+// It seems Windows searches ContinueHandler's list even
+// if ExceptionHandler returns EXCEPTION_CONTINUE_EXECUTION.
+// firstcontinuehandler will stop that search,
+// if exceptionhandler did the same earlier.
+func firstcontinuehandler(info *exceptionrecord, r *context, gp *g) int32 {
+       if !isgoexception(info, r) {
+               return _EXCEPTION_CONTINUE_SEARCH
+       }
+       return _EXCEPTION_CONTINUE_EXECUTION
+}
+
+// lastcontinuehandler is reached, because runtime cannot handle
+// current exception. lastcontinuehandler will print crash info and exit.
+func lastcontinuehandler(info *exceptionrecord, r *context, gp *g) uint32 {
+       _g_ := getg()
+
+       if panicking != 0 { // traceback already printed
+               exit(2)
+       }
+       panicking = 1
+
+       print("Exception ", hex(info.exceptioncode), " ", hex(info.exceptioninformation[0]), " ", hex(info.exceptioninformation[1]), " ", hex(r.rip), "\n")
+
+       print("PC=", hex(r.rip), "\n")
+       if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 {
+               print("signal arrived during cgo execution\n")
+               gp = _g_.m.lockedg
+       }
+       print("\n")
+
+       var docrash bool
+       if gotraceback(&docrash) > 0 {
+               tracebacktrap(uintptr(r.rip), uintptr(r.rsp), 0, gp)
+               tracebackothers(gp)
+               dumpregs(r)
+       }
+
+       if docrash {
+               crash()
+       }
+
+       exit(2)
+       return 0 // not reached
+}
+
+func sigenable(sig uint32) {
+}
+
+func sigdisable(sig uint32) {
+}
+
+func dosigprof(r *context, gp *g, mp *m) {
+       sigprof((*byte)(unsafe.Pointer(uintptr(r.rip))), (*byte)(unsafe.Pointer(uintptr(r.rsp))), nil, gp, mp)
+}
diff --git a/src/runtime/os2_nacl.go b/src/runtime/os2_nacl.go
new file mode 100644 (file)
index 0000000..0c91e0f
--- /dev/null
@@ -0,0 +1,154 @@
+// 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
+
+const (
+       _NSIG    = 32
+       _SI_USER = 1
+
+       // native_client/src/trusted/service_runtime/include/sys/errno.h
+       // The errors are mainly copied from Linux.
+       _EPERM           = 1        /* Operation not permitted */
+       _ENOENT          = 2        /* No such file or directory */
+       _ESRCH           = 3        /* No such process */
+       _EINTR           = 4        /* Interrupted system call */
+       _EIO             = 5        /* I/O error */
+       _ENXIO           = 6        /* No such device or address */
+       _E2BIG           = 7        /* Argument list too long */
+       _ENOEXEC         = 8        /* Exec format error */
+       _EBADF           = 9        /* Bad file number */
+       _ECHILD          = 10       /* No child processes */
+       _EAGAIN          = 11       /* Try again */
+       _ENOMEM          = 12       /* Out of memory */
+       _EACCES          = 13       /* Permission denied */
+       _EFAULT          = 14       /* Bad address */
+       _EBUSY           = 16       /* Device or resource busy */
+       _EEXIST          = 17       /* File exists */
+       _EXDEV           = 18       /* Cross-device link */
+       _ENODEV          = 19       /* No such device */
+       _ENOTDIR         = 20       /* Not a directory */
+       _EISDIR          = 21       /* Is a directory */
+       _EINVAL          = 22       /* Invalid argument */
+       _ENFILE          = 23       /* File table overflow */
+       _EMFILE          = 24       /* Too many open files */
+       _ENOTTY          = 25       /* Not a typewriter */
+       _EFBIG           = 27       /* File too large */
+       _ENOSPC          = 28       /* No space left on device */
+       _ESPIPE          = 29       /* Illegal seek */
+       _EROFS           = 30       /* Read-only file system */
+       _EMLINK          = 31       /* Too many links */
+       _EPIPE           = 32       /* Broken pipe */
+       _ENAMETOOLONG    = 36       /* File name too long */
+       _ENOSYS          = 38       /* Function not implemented */
+       _EDQUOT          = 122      /* Quota exceeded */
+       _EDOM            = 33       /* Math arg out of domain of func */
+       _ERANGE          = 34       /* Math result not representable */
+       _EDEADLK         = 35       /* Deadlock condition */
+       _ENOLCK          = 37       /* No record locks available */
+       _ENOTEMPTY       = 39       /* Directory not empty */
+       _ELOOP           = 40       /* Too many symbolic links */
+       _ENOMSG          = 42       /* No message of desired type */
+       _EIDRM           = 43       /* Identifier removed */
+       _ECHRNG          = 44       /* Channel number out of range */
+       _EL2NSYNC        = 45       /* Level 2 not synchronized */
+       _EL3HLT          = 46       /* Level 3 halted */
+       _EL3RST          = 47       /* Level 3 reset */
+       _ELNRNG          = 48       /* Link number out of range */
+       _EUNATCH         = 49       /* Protocol driver not attached */
+       _ENOCSI          = 50       /* No CSI structure available */
+       _EL2HLT          = 51       /* Level 2 halted */
+       _EBADE           = 52       /* Invalid exchange */
+       _EBADR           = 53       /* Invalid request descriptor */
+       _EXFULL          = 54       /* Exchange full */
+       _ENOANO          = 55       /* No anode */
+       _EBADRQC         = 56       /* Invalid request code */
+       _EBADSLT         = 57       /* Invalid slot */
+       _EDEADLOCK       = _EDEADLK /* File locking deadlock error */
+       _EBFONT          = 59       /* Bad font file fmt */
+       _ENOSTR          = 60       /* Device not a stream */
+       _ENODATA         = 61       /* No data (for no delay io) */
+       _ETIME           = 62       /* Timer expired */
+       _ENOSR           = 63       /* Out of streams resources */
+       _ENONET          = 64       /* Machine is not on the network */
+       _ENOPKG          = 65       /* Package not installed */
+       _EREMOTE         = 66       /* The object is remote */
+       _ENOLINK         = 67       /* The link has been severed */
+       _EADV            = 68       /* Advertise error */
+       _ESRMNT          = 69       /* Srmount error */
+       _ECOMM           = 70       /* Communication error on send */
+       _EPROTO          = 71       /* Protocol error */
+       _EMULTIHOP       = 72       /* Multihop attempted */
+       _EDOTDOT         = 73       /* Cross mount point (not really error) */
+       _EBADMSG         = 74       /* Trying to read unreadable message */
+       _EOVERFLOW       = 75       /* Value too large for defined data type */
+       _ENOTUNIQ        = 76       /* Given log. name not unique */
+       _EBADFD          = 77       /* f.d. invalid for this operation */
+       _EREMCHG         = 78       /* Remote address changed */
+       _ELIBACC         = 79       /* Can't access a needed shared lib */
+       _ELIBBAD         = 80       /* Accessing a corrupted shared lib */
+       _ELIBSCN         = 81       /* .lib section in a.out corrupted */
+       _ELIBMAX         = 82       /* Attempting to link in too many libs */
+       _ELIBEXEC        = 83       /* Attempting to exec a shared library */
+       _EILSEQ          = 84
+       _EUSERS          = 87
+       _ENOTSOCK        = 88  /* Socket operation on non-socket */
+       _EDESTADDRREQ    = 89  /* Destination address required */
+       _EMSGSIZE        = 90  /* Message too long */
+       _EPROTOTYPE      = 91  /* Protocol wrong type for socket */
+       _ENOPROTOOPT     = 92  /* Protocol not available */
+       _EPROTONOSUPPORT = 93  /* Unknown protocol */
+       _ESOCKTNOSUPPORT = 94  /* Socket type not supported */
+       _EOPNOTSUPP      = 95  /* Operation not supported on transport endpoint */
+       _EPFNOSUPPORT    = 96  /* Protocol family not supported */
+       _EAFNOSUPPORT    = 97  /* Address family not supported by protocol family */
+       _EADDRINUSE      = 98  /* Address already in use */
+       _EADDRNOTAVAIL   = 99  /* Address not available */
+       _ENETDOWN        = 100 /* Network interface is not configured */
+       _ENETUNREACH     = 101 /* Network is unreachable */
+       _ENETRESET       = 102
+       _ECONNABORTED    = 103 /* Connection aborted */
+       _ECONNRESET      = 104 /* Connection reset by peer */
+       _ENOBUFS         = 105 /* No buffer space available */
+       _EISCONN         = 106 /* Socket is already connected */
+       _ENOTCONN        = 107 /* Socket is not connected */
+       _ESHUTDOWN       = 108 /* Can't send after socket shutdown */
+       _ETOOMANYREFS    = 109
+       _ETIMEDOUT       = 110 /* Connection timed out */
+       _ECONNREFUSED    = 111 /* Connection refused */
+       _EHOSTDOWN       = 112 /* Host is down */
+       _EHOSTUNREACH    = 113 /* Host is unreachable */
+       _EALREADY        = 114 /* Socket already connected */
+       _EINPROGRESS     = 115 /* Connection already in progress */
+       _ESTALE          = 116
+       _ENOTSUP         = _EOPNOTSUPP /* Not supported */
+       _ENOMEDIUM       = 123         /* No medium (in tape drive) */
+       _ECANCELED       = 125         /* Operation canceled. */
+       _ELBIN           = 2048        /* Inode is remote (not really error) */
+       _EFTYPE          = 2049        /* Inappropriate file type or format */
+       _ENMFILE         = 2050        /* No more files */
+       _EPROCLIM        = 2051
+       _ENOSHARE        = 2052    /* No such host or network path */
+       _ECASECLASH      = 2053    /* Filename exists with different case */
+       _EWOULDBLOCK     = _EAGAIN /* Operation would block */
+
+       // native_client/src/trusted/service_runtime/include/bits/mman.h.
+       // NOTE: DO NOT USE native_client/src/shared/imc/nacl_imc_c.h.
+       // Those MAP_*values are different from these.
+       _PROT_NONE  = 0x0
+       _PROT_READ  = 0x1
+       _PROT_WRITE = 0x2
+       _PROT_EXEC  = 0x4
+
+       _MAP_SHARED  = 0x1
+       _MAP_PRIVATE = 0x2
+       _MAP_FIXED   = 0x10
+       _MAP_ANON    = 0x20
+
+       _MADV_FREE  = 0
+       _SIGFPE     = 8
+       _FPE_INTDIV = 0
+)
+
+type siginfo struct{}
diff --git a/src/runtime/os2_netbsd.go b/src/runtime/os2_netbsd.go
new file mode 100644 (file)
index 0000000..46576b9
--- /dev/null
@@ -0,0 +1,18 @@
+// 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
+
+const (
+       _SS_DISABLE  = 4
+       _SIG_BLOCK   = 1
+       _SIG_UNBLOCK = 2
+       _SIG_SETMASK = 3
+       _NSIG        = 33
+       _SI_USER     = 0
+
+       // From NetBSD's <sys/ucontext.h>
+       _UC_SIGMASK = 0x01
+       _UC_CPU     = 0x04
+)
diff --git a/src/runtime/os2_plan9.go b/src/runtime/os2_plan9.go
new file mode 100644 (file)
index 0000000..f64f4c8
--- /dev/null
@@ -0,0 +1,72 @@
+// 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.
+
+// Plan 9-specific system calls
+
+package runtime
+
+// open
+const (
+       _OREAD   = 0
+       _OWRITE  = 1
+       _ORDWR   = 2
+       _OEXEC   = 3
+       _OTRUNC  = 16
+       _OCEXEC  = 32
+       _ORCLOSE = 64
+       _OEXCL   = 0x1000
+)
+
+// rfork
+const (
+       _RFNAMEG  = 1 << 0
+       _RFENVG   = 1 << 1
+       _RFFDG    = 1 << 2
+       _RFNOTEG  = 1 << 3
+       _RFPROC   = 1 << 4
+       _RFMEM    = 1 << 5
+       _RFNOWAIT = 1 << 6
+       _RFCNAMEG = 1 << 10
+       _RFCENVG  = 1 << 11
+       _RFCFDG   = 1 << 12
+       _RFREND   = 1 << 13
+       _RFNOMNT  = 1 << 14
+)
+
+// notify
+const (
+       _NCONT = 0
+       _NDFLT = 1
+)
+
+type uinptr _Plink
+
+type tos struct {
+       prof struct { // Per process profiling
+               pp    *_Plink // known to be 0(ptr)
+               next  *_Plink // known to be 4(ptr)
+               last  *_Plink
+               first *_Plink
+               pid   uint32
+               what  uint32
+       }
+       cyclefreq uint64 // cycle clock frequency if there is one, 0 otherwise
+       kcycles   int64  // cycles spent in kernel
+       pcycles   int64  // cycles spent in process (kernel + user)
+       pid       uint32 // might as well put the pid here
+       clock     uint32
+       // top of stack is here
+}
+
+const (
+       _NSIG   = 14  // number of signals in sigtable array
+       _ERRMAX = 128 // max length of note string
+
+       // Notes in runtime·sigtab that are handled by runtime·sigpanic.
+       _SIGRFAULT = 2
+       _SIGWFAULT = 3
+       _SIGINTDIV = 4
+       _SIGFLOAT  = 5
+       _SIGTRAP   = 6
+)
diff --git a/src/runtime/os2_windows.go b/src/runtime/os2_windows.go
new file mode 100644 (file)
index 0000000..d5b1f47
--- /dev/null
@@ -0,0 +1,25 @@
+// 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.
+
+package runtime
+
+import "unsafe"
+
+// Call a Windows function with stdcall conventions,
+// and switch to os stack during the call.
+func asmstdcall(fn unsafe.Pointer)
+
+func getlasterror() uint32
+func setlasterror(err uint32)
+
+// Function to be called by windows CreateThread
+// to start new os thread.
+func tstart_stdcall(newm *m) uint32
+
+func ctrlhandler(_type uint32) uint32
+
+// TODO(brainman): should not need those
+const (
+       _NSIG = 65
+)
diff --git a/src/runtime/os_android.h b/src/runtime/os_android.h
deleted file mode 100644 (file)
index c7c1098..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include "os_linux.h"
similarity index 64%
rename from src/runtime/os_android.c
rename to src/runtime/os_android_arm.go
index 5805f687130fca344e7d00357a42e231e0fedf60..132832236abd108c0283a54e70f1902ead11b4ee 100644 (file)
@@ -2,15 +2,14 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-#include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
+package runtime
+
+import _ "unsafe"
 
 // Export the runtime entry point symbol.
 //
 // Used by the app package to start the Go runtime after loading
 // a shared library via JNI. See golang.org/x/mobile/app.
 
-void _rt0_arm_linux1();
-#pragma cgo_export_static _rt0_arm_linux1
-#pragma cgo_export_dynamic _rt0_arm_linux1
+//go:cgo_export_static _rt0_arm_linux1
+//go:cgo_export_dynamic _rt0_arm_linux1
diff --git a/src/runtime/os_nacl.c b/src/runtime/os_nacl.c
deleted file mode 100644 (file)
index ad72cc7..0000000
+++ /dev/null
@@ -1,315 +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.
-
-#include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "arch_GOARCH.h"
-#include "textflag.h"
-#include "stack.h"
-
-int8 *goos = "nacl";
-extern SigTab runtime·sigtab[];
-
-void runtime·sigtramp(void);
-
-// Called to initialize a new m (including the bootstrap m).
-// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
-void
-runtime·mpreinit(M *mp)
-{
-       mp->gsignal = runtime·malg(32*1024);   // OS X wants >=8K, Linux >=2K
-       runtime·writebarrierptr_nostore(&mp->gsignal, mp->gsignal);
-
-       mp->gsignal->m = mp;
-       runtime·writebarrierptr_nostore(&mp->gsignal->m, mp->gsignal->m);
-}
-
-// Called to initialize a new m (including the bootstrap m).
-// Called on the new thread, can not allocate memory.
-void
-runtime·minit(void)
-{
-       int32 ret;
-
-       // Initialize signal handling
-       ret = runtime·nacl_exception_stack((byte*)g->m->gsignal->stack.lo, 32*1024);
-       if(ret < 0)
-               runtime·printf("runtime: nacl_exception_stack: error %d\n", -ret);
-
-       ret = runtime·nacl_exception_handler(runtime·sigtramp, nil);
-       if(ret < 0)
-               runtime·printf("runtime: nacl_exception_handler: error %d\n", -ret);
-}
-
-// Called from dropm to undo the effect of an minit.
-void
-runtime·unminit(void)
-{
-}
-
-int8 runtime·sigtrampf[] = "runtime: signal at PC=%X AX=%X CX=%X DX=%X BX=%X DI=%X R15=%X *SP=%X\n";
-int8 runtime·sigtrampp[] = "runtime: sigtramp";
-
-extern byte runtime·tls0[];
-
-void
-runtime·osinit(void)
-{
-       runtime·ncpu = 1;
-       g->m->procid = 2;
-//runtime·nacl_exception_handler(runtime·sigtramp, nil);
-}
-
-void
-runtime·crash(void)
-{
-       *(int32*)0 = 0;
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·get_random_data(byte **rnd, int32 *rnd_len)
-{
-       *rnd = nil;
-       *rnd_len = 0;
-}
-
-void
-runtime·goenvs(void)
-{
-       runtime·goenvs_unix();
-}
-
-void
-runtime·initsig(void)
-{
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·usleep(uint32 us)
-{
-       Timespec ts;
-       
-       ts.tv_sec = us/1000000;
-       ts.tv_nsec = (us%1000000)*1000;
-       runtime·nacl_nanosleep(&ts, nil);
-}
-
-void runtime·mstart_nacl(void);
-
-void
-runtime·newosproc(M *mp, void *stk)
-{
-       int32 ret;
-       void **tls;
-
-       tls = (void**)mp->tls;
-       tls[0] = mp->g0;
-       tls[1] = mp;
-       ret = runtime·nacl_thread_create(runtime·mstart_nacl, stk, tls+2, 0);
-       if(ret < 0) {
-               runtime·printf("nacl_thread_create: error %d\n", -ret);
-               runtime·throw("newosproc");
-       }
-}
-
-static void
-semacreate(void)
-{
-       int32 mu, cond;
-       
-       mu = runtime·nacl_mutex_create(0);
-       if(mu < 0) {
-               runtime·printf("nacl_mutex_create: error %d\n", -mu);
-               runtime·throw("semacreate");
-       }
-       cond = runtime·nacl_cond_create(0);
-       if(cond < 0) {
-               runtime·printf("nacl_cond_create: error %d\n", -cond);
-               runtime·throw("semacreate");
-       }
-       g->m->waitsemalock = mu;
-       g->m->scalararg[0] = cond; // assigned to m->waitsema
-}
-
-#pragma textflag NOSPLIT
-uint32
-runtime·semacreate(void)
-{
-       void (*fn)(void);
-       uint32 x;
-       
-       fn = semacreate;
-       runtime·onM(&fn);
-       x = g->m->scalararg[0];
-       g->m->scalararg[0] = 0;
-       return x;
-}
-
-static void
-semasleep(void)
-{
-       int32 ret;
-       int64 ns;
-       
-       ns = (int64)(uint32)g->m->scalararg[0] | (int64)(uint32)g->m->scalararg[1]<<32;
-       g->m->scalararg[0] = 0;
-       g->m->scalararg[1] = 0;
-       
-       ret = runtime·nacl_mutex_lock(g->m->waitsemalock);
-       if(ret < 0) {
-               //runtime·printf("nacl_mutex_lock: error %d\n", -ret);
-               runtime·throw("semasleep");
-       }
-       if(g->m->waitsemacount > 0) {
-               g->m->waitsemacount = 0;
-               runtime·nacl_mutex_unlock(g->m->waitsemalock);
-               g->m->scalararg[0] = 0;
-               return;
-       }
-
-       while(g->m->waitsemacount == 0) {
-               if(ns < 0) {
-                       ret = runtime·nacl_cond_wait(g->m->waitsema, g->m->waitsemalock);
-                       if(ret < 0) {
-                               //runtime·printf("nacl_cond_wait: error %d\n", -ret);
-                               runtime·throw("semasleep");
-                       }
-               } else {
-                       Timespec ts;
-                       
-                       ns += runtime·nanotime();
-                       ts.tv_sec = runtime·timediv(ns, 1000000000, (int32*)&ts.tv_nsec);
-                       ret = runtime·nacl_cond_timed_wait_abs(g->m->waitsema, g->m->waitsemalock, &ts);
-                       if(ret == -ETIMEDOUT) {
-                               runtime·nacl_mutex_unlock(g->m->waitsemalock);
-                               g->m->scalararg[0] = -1;
-                               return;
-                       }
-                       if(ret < 0) {
-                               //runtime·printf("nacl_cond_timed_wait_abs: error %d\n", -ret);
-                               runtime·throw("semasleep");
-                       }
-               }
-       }
-                       
-       g->m->waitsemacount = 0;
-       runtime·nacl_mutex_unlock(g->m->waitsemalock);
-       g->m->scalararg[0] = 0;
-}
-
-#pragma textflag NOSPLIT
-int32
-runtime·semasleep(int64 ns)
-{
-       int32 r;
-       void (*fn)(void);
-
-       g->m->scalararg[0] = (uint32)ns;
-       g->m->scalararg[1] = (uint32)(ns>>32);
-       fn = semasleep;
-       runtime·onM(&fn);
-       r = g->m->scalararg[0];
-       g->m->scalararg[0] = 0;
-       return r;
-}
-
-static void
-semawakeup(void)
-{
-       int32 ret;
-       M *mp;
-       
-       mp = g->m->ptrarg[0];
-       g->m->ptrarg[0] = nil;
-
-       ret = runtime·nacl_mutex_lock(mp->waitsemalock);
-       if(ret < 0) {
-               //runtime·printf("nacl_mutex_lock: error %d\n", -ret);
-               runtime·throw("semawakeup");
-       }
-       if(mp->waitsemacount != 0) {
-               //runtime·printf("semawakeup: double wakeup\n");
-               runtime·throw("semawakeup");
-       }
-       mp->waitsemacount = 1;
-       runtime·nacl_cond_signal(mp->waitsema);
-       runtime·nacl_mutex_unlock(mp->waitsemalock);
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·semawakeup(M *mp)
-{
-       void (*fn)(void);
-
-       g->m->ptrarg[0] = mp;
-       fn = semawakeup;
-       runtime·onM(&fn);
-}
-
-uintptr
-runtime·memlimit(void)
-{
-       runtime·printf("memlimit\n");
-       return 0;
-}
-
-#pragma dataflag NOPTR
-static int8 badsignal[] = "runtime: signal received on thread not created by Go.\n";
-
-// This runs on a foreign stack, without an m or a g.  No stack split.
-#pragma textflag NOSPLIT
-void
-runtime·badsignal2(void)
-{
-       runtime·write(2, badsignal, sizeof badsignal - 1);
-       runtime·exit(2);
-}
-
-void   runtime·madvise(byte*, uintptr, int32) { }
-void runtime·munmap(byte*, uintptr) {}
-
-void
-runtime·resetcpuprofiler(int32 hz)
-{
-       USED(hz);
-}
-
-void
-runtime·sigdisable(uint32)
-{
-}
-
-void
-runtime·sigenable(uint32)
-{
-}
-
-void
-runtime·closeonexec(int32)
-{
-}
-
-uint32 runtime·writelock; // test-and-set spin lock for runtime.write
-
-/*
-An attempt at IRT. Doesn't work. See end of sys_nacl_amd64.s.
-
-void (*runtime·nacl_irt_query)(void);
-
-int8 runtime·nacl_irt_basic_v0_1_str[] = "nacl-irt-basic-0.1";
-void *runtime·nacl_irt_basic_v0_1[6]; // exit, gettod, clock, nanosleep, sched_yield, sysconf
-int32 runtime·nacl_irt_basic_v0_1_size = sizeof(runtime·nacl_irt_basic_v0_1);
-
-int8 runtime·nacl_irt_memory_v0_3_str[] = "nacl-irt-memory-0.3";
-void *runtime·nacl_irt_memory_v0_3[3]; // mmap, munmap, mprotect
-int32 runtime·nacl_irt_memory_v0_3_size = sizeof(runtime·nacl_irt_memory_v0_3);
-
-int8 runtime·nacl_irt_thread_v0_1_str[] = "nacl-irt-thread-0.1";
-void *runtime·nacl_irt_thread_v0_1[3]; // thread_create, thread_exit, thread_nice
-int32 runtime·nacl_irt_thread_v0_1_size = sizeof(runtime·nacl_irt_thread_v0_1);
-*/
index 8dd43ff06f1e58a295b709802ac42cd048980551..eff9ec30e4dc588ffb4a7997caefdab326abfcfb 100644 (file)
@@ -6,8 +6,8 @@ package runtime
 
 import "unsafe"
 
-func nacl_exception_stack(p unsafe.Pointer, size int32) int32
-func nacl_exception_handler(fn, arg unsafe.Pointer) int32
+func nacl_exception_stack(p uintptr, size int32) int32
+func nacl_exception_handler(fn uintptr, arg unsafe.Pointer) int32
 func nacl_sem_create(flag int32) int32
 func nacl_sem_wait(sem int32) int32
 func nacl_sem_post(sem int32) int32
@@ -19,9 +19,20 @@ func nacl_cond_create(flag int32) int32
 func nacl_cond_wait(cond, n int32) int32
 func nacl_cond_signal(cond int32) int32
 func nacl_cond_broadcast(cond int32) int32
-func nacl_cond_timed_wait_abs(cond, lock int32, ts unsafe.Pointer) int32
-func nacl_thread_create(fn, stk, tls, xx unsafe.Pointer) int32
-func nacl_nanosleep(ts, extra unsafe.Pointer) int32
+
+//go:noescape
+func nacl_cond_timed_wait_abs(cond, lock int32, ts *timespec) int32
+func nacl_thread_create(fn uintptr, stk, tls, xx unsafe.Pointer) int32
+
+//go:noescape
+func nacl_nanosleep(ts, extra *timespec) int32
+func nanotime() int64
+func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) unsafe.Pointer
+func exit(code int32)
+func osyield()
+
+//go:noescape
+func write(fd uintptr, p unsafe.Pointer, n int32) int32
 
 func os_sigpipe() {
        gothrow("too many writes on closed pipe")
diff --git a/src/runtime/os_nacl.h b/src/runtime/os_nacl.h
deleted file mode 100644 (file)
index 7c9d9c2..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-enum {
-       NSIG = 32,
-       SI_USER = 1,
-
-       // native_client/src/trusted/service_runtime/include/sys/errno.h
-       // The errors are mainly copied from Linux.
-       EPERM = 1,  /* Operation not permitted */
-       ENOENT = 2,  /* No such file or directory */
-       ESRCH = 3,  /* No such process */
-       EINTR = 4,  /* Interrupted system call */
-       EIO = 5,  /* I/O error */
-       ENXIO = 6,  /* No such device or address */
-       E2BIG = 7,  /* Argument list too long */
-       ENOEXEC = 8,  /* Exec format error */
-       EBADF = 9,  /* Bad file number */
-       ECHILD = 10,  /* No child processes */
-       EAGAIN = 11,  /* Try again */
-       ENOMEM = 12,  /* Out of memory */
-       EACCES = 13,  /* Permission denied */
-       EFAULT = 14,  /* Bad address */
-       EBUSY = 16,  /* Device or resource busy */
-       EEXIST = 17,  /* File exists */
-       EXDEV = 18,  /* Cross-device link */
-       ENODEV = 19,  /* No such device */
-       ENOTDIR = 20,  /* Not a directory */
-       EISDIR = 21,  /* Is a directory */
-       EINVAL = 22,  /* Invalid argument */
-       ENFILE = 23,  /* File table overflow */
-       EMFILE = 24,  /* Too many open files */
-       ENOTTY = 25,  /* Not a typewriter */
-       EFBIG = 27,  /* File too large */
-       ENOSPC = 28,  /* No space left on device */
-       ESPIPE = 29,  /* Illegal seek */
-       EROFS = 30,  /* Read-only file system */
-       EMLINK = 31,  /* Too many links */
-       EPIPE = 32,  /* Broken pipe */
-       ENAMETOOLONG = 36,  /* File name too long */
-       ENOSYS = 38,  /* Function not implemented */
-       EDQUOT = 122, /* Quota exceeded */
-       EDOM = 33,   /* Math arg out of domain of func */
-       ERANGE = 34, /* Math result not representable */
-       EDEADLK = 35,  /* Deadlock condition */
-       ENOLCK = 37, /* No record locks available */
-       ENOTEMPTY = 39,  /* Directory not empty */
-       ELOOP = 40,  /* Too many symbolic links */
-       ENOMSG = 42, /* No message of desired type */
-       EIDRM = 43,  /* Identifier removed */
-       ECHRNG = 44, /* Channel number out of range */
-       EL2NSYNC = 45, /* Level 2 not synchronized */
-       EL3HLT = 46, /* Level 3 halted */
-       EL3RST = 47, /* Level 3 reset */
-       ELNRNG = 48, /* Link number out of range */
-       EUNATCH = 49,  /* Protocol driver not attached */
-       ENOCSI = 50, /* No CSI structure available */
-       EL2HLT = 51, /* Level 2 halted */
-       EBADE = 52,  /* Invalid exchange */
-       EBADR = 53,  /* Invalid request descriptor */
-       EXFULL = 54, /* Exchange full */
-       ENOANO = 55, /* No anode */
-       EBADRQC = 56,  /* Invalid request code */
-       EBADSLT = 57,  /* Invalid slot */
-       EDEADLOCK = EDEADLK,  /* File locking deadlock error */
-       EBFONT = 59, /* Bad font file fmt */
-       ENOSTR = 60, /* Device not a stream */
-       ENODATA = 61,  /* No data (for no delay io) */
-       ETIME = 62,  /* Timer expired */
-       ENOSR = 63,  /* Out of streams resources */
-       ENONET = 64, /* Machine is not on the network */
-       ENOPKG = 65, /* Package not installed */
-       EREMOTE = 66,  /* The object is remote */
-       ENOLINK = 67,  /* The link has been severed */
-       EADV = 68,   /* Advertise error */
-       ESRMNT = 69, /* Srmount error */
-       ECOMM = 70,  /* Communication error on send */
-       EPROTO = 71, /* Protocol error */
-       EMULTIHOP = 72,  /* Multihop attempted */
-       EDOTDOT = 73,  /* Cross mount point (not really error) */
-       EBADMSG = 74,  /* Trying to read unreadable message */
-       EOVERFLOW = 75, /* Value too large for defined data type */
-       ENOTUNIQ = 76, /* Given log. name not unique */
-       EBADFD = 77, /* f.d. invalid for this operation */
-       EREMCHG = 78,  /* Remote address changed */
-       ELIBACC = 79,  /* Can't access a needed shared lib */
-       ELIBBAD = 80,  /* Accessing a corrupted shared lib */
-       ELIBSCN = 81,  /* .lib section in a.out corrupted */
-       ELIBMAX = 82,  /* Attempting to link in too many libs */
-       ELIBEXEC = 83, /* Attempting to exec a shared library */
-       EILSEQ = 84,
-       EUSERS = 87,
-       ENOTSOCK = 88,  /* Socket operation on non-socket */
-       EDESTADDRREQ = 89,  /* Destination address required */
-       EMSGSIZE = 90,    /* Message too long */
-       EPROTOTYPE = 91,  /* Protocol wrong type for socket */
-       ENOPROTOOPT = 92, /* Protocol not available */
-       EPROTONOSUPPORT = 93, /* Unknown protocol */
-       ESOCKTNOSUPPORT = 94, /* Socket type not supported */
-       EOPNOTSUPP = 95, /* Operation not supported on transport endpoint */
-       EPFNOSUPPORT = 96, /* Protocol family not supported */
-       EAFNOSUPPORT = 97, /* Address family not supported by protocol family */
-       EADDRINUSE = 98,    /* Address already in use */
-       EADDRNOTAVAIL = 99, /* Address not available */
-       ENETDOWN = 100,    /* Network interface is not configured */
-       ENETUNREACH = 101,   /* Network is unreachable */
-       ENETRESET = 102,
-       ECONNABORTED = 103,  /* Connection aborted */
-       ECONNRESET = 104,  /* Connection reset by peer */
-       ENOBUFS = 105, /* No buffer space available */
-       EISCONN = 106,   /* Socket is already connected */
-       ENOTCONN = 107,    /* Socket is not connected */
-       ESHUTDOWN = 108, /* Can't send after socket shutdown */
-       ETOOMANYREFS = 109,
-       ETIMEDOUT = 110,   /* Connection timed out */
-       ECONNREFUSED = 111,  /* Connection refused */
-       EHOSTDOWN = 112,   /* Host is down */
-       EHOSTUNREACH = 113,  /* Host is unreachable */
-       EALREADY = 114,    /* Socket already connected */
-       EINPROGRESS = 115,   /* Connection already in progress */
-       ESTALE = 116,
-       ENOTSUP = EOPNOTSUPP,   /* Not supported */
-       ENOMEDIUM = 123,   /* No medium (in tape drive) */
-       ECANCELED = 125, /* Operation canceled. */
-       ELBIN = 2048,  /* Inode is remote (not really error) */
-       EFTYPE = 2049,  /* Inappropriate file type or format */
-       ENMFILE = 2050,  /* No more files */
-       EPROCLIM = 2051,
-       ENOSHARE = 2052,  /* No such host or network path */
-       ECASECLASH = 2053,  /* Filename exists with different case */
-       EWOULDBLOCK = EAGAIN,      /* Operation would block */
-
-       // native_client/src/trusted/service_runtime/include/bits/mman.h.
-       // NOTE: DO NOT USE native_client/src/shared/imc/nacl_imc_c.h.
-       // Those MAP_*values are different from these.
-       PROT_NONE       = 0x0,
-       PROT_READ       = 0x1,
-       PROT_WRITE      = 0x2,
-       PROT_EXEC       = 0x4,
-
-       MAP_SHARED      = 0x1,
-       MAP_PRIVATE     = 0x2,
-       MAP_FIXED       = 0x10,
-       MAP_ANON        = 0x20,
-};
-typedef byte* kevent_udata;
-
-int32  runtime·nacl_exception_stack(byte*, int32);
-int32  runtime·nacl_exception_handler(void*, void*);
-int32  runtime·nacl_sem_create(int32);
-int32  runtime·nacl_sem_wait(int32);
-int32  runtime·nacl_sem_post(int32);
-int32  runtime·nacl_mutex_create(int32);
-int32  runtime·nacl_mutex_lock(int32);
-int32  runtime·nacl_mutex_trylock(int32);
-int32  runtime·nacl_mutex_unlock(int32);
-int32  runtime·nacl_cond_create(int32);
-int32  runtime·nacl_cond_wait(int32, int32);
-int32  runtime·nacl_cond_signal(int32);
-int32  runtime·nacl_cond_broadcast(int32);
-int32  runtime·nacl_cond_timed_wait_abs(int32, int32, Timespec*);
-int32  runtime·nacl_thread_create(void*, void*, void*, void*);
-int32  runtime·nacl_nanosleep(Timespec*, Timespec*);
-
-void   runtime·sigpanic(void);
similarity index 61%
rename from src/runtime/os_nacl_arm.c
rename to src/runtime/os_nacl_arm.go
index 1248ea6449449b68918035794be01842da8a7909..a43e7c47b7a5fac9d4b7de0148f10f2fba2e3a2d 100644 (file)
@@ -2,23 +2,16 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-#include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "textflag.h"
+package runtime
 
-void
-runtime·checkgoarm(void)
-{
-       return; // NaCl/ARM only supports ARMv7
+func checkgoarm() {
+       return // NaCl/ARM only supports ARMv7
 }
 
-#pragma textflag NOSPLIT
-int64
-runtime·cputicks(void)
-{
+//go:nosplit
+func cputicks() int64 {
        // Currently cputicks() is used in blocking profiler and to seed runtime·fastrand1().
        // runtime·nanotime() is a poor approximation of CPU ticks that is enough for the profiler.
        // TODO: need more entropy to better seed fastrand1.
-       return runtime·nanotime();
+       return nanotime()
 }
diff --git a/src/runtime/os_netbsd.c b/src/runtime/os_netbsd.c
deleted file mode 100644 (file)
index 28929ea..0000000
+++ /dev/null
@@ -1,371 +0,0 @@
-// 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 "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "signal_unix.h"
-#include "stack.h"
-#include "textflag.h"
-
-enum
-{
-       ESRCH = 3,
-       ENOTSUP = 91,
-
-       // From NetBSD's <sys/time.h>
-       CLOCK_REALTIME = 0,
-       CLOCK_VIRTUAL = 1,
-       CLOCK_PROF = 2,
-       CLOCK_MONOTONIC = 3
-};
-
-extern SigTab runtime·sigtab[];
-
-static Sigset sigset_none;
-static Sigset sigset_all = { ~(uint32)0, ~(uint32)0, ~(uint32)0, ~(uint32)0, };
-
-extern void runtime·getcontext(UcontextT *context);
-extern int32 runtime·lwp_create(UcontextT *context, uintptr flags, void *lwpid);
-extern void runtime·lwp_mcontext_init(void *mc, void *stack, M *mp, G *gp, void (*fn)(void));
-extern int32 runtime·lwp_park(Timespec *abstime, int32 unpark, void *hint, void *unparkhint);
-extern int32 runtime·lwp_unpark(int32 lwp, void *hint);
-extern int32 runtime·lwp_self(void);
-
-// From NetBSD's <sys/sysctl.h>
-#define        CTL_HW  6
-#define        HW_NCPU 3
-
-static int32
-getncpu(void)
-{
-       uint32 mib[2];
-       uint32 out;
-       int32 ret;
-       uintptr nout;
-
-       // Fetch hw.ncpu via sysctl.
-       mib[0] = CTL_HW;
-       mib[1] = HW_NCPU;
-       nout = sizeof out;
-       out = 0;
-       ret = runtime·sysctl(mib, 2, (byte*)&out, &nout, nil, 0);
-       if(ret >= 0)
-               return out;
-       else
-               return 1;
-}
-
-#pragma textflag NOSPLIT
-uintptr
-runtime·semacreate(void)
-{
-       return 1;
-}
-
-static void
-semasleep(void)
-{
-       int64 ns;
-       Timespec ts;
-
-       ns = (int64)(uint32)g->m->scalararg[0] | (int64)(uint32)g->m->scalararg[1]<<32;
-       g->m->scalararg[0] = 0;
-       g->m->scalararg[1] = 0;
-
-       // spin-mutex lock
-       while(runtime·xchg(&g->m->waitsemalock, 1))
-               runtime·osyield();
-
-       for(;;) {
-               // lock held
-               if(g->m->waitsemacount == 0) {
-                       // sleep until semaphore != 0 or timeout.
-                       // thrsleep unlocks m->waitsemalock.
-                       if(ns < 0) {
-                               // TODO(jsing) - potential deadlock!
-                               //
-                               // There is a potential deadlock here since we
-                               // have to release the waitsemalock mutex
-                               // before we call lwp_park() to suspend the
-                               // thread. This allows another thread to
-                               // release the lock and call lwp_unpark()
-                               // before the thread is actually suspended.
-                               // If this occurs the current thread will end
-                               // up sleeping indefinitely. Unfortunately
-                               // the NetBSD kernel does not appear to provide
-                               // a mechanism for unlocking the userspace
-                               // mutex once the thread is actually parked.
-                               runtime·atomicstore(&g->m->waitsemalock, 0);
-                               runtime·lwp_park(nil, 0, &g->m->waitsemacount, nil);
-                       } else {
-                               ns = ns + runtime·nanotime();
-                               // NOTE: tv_nsec is int64 on amd64, so this assumes a little-endian system.
-                               ts.tv_nsec = 0;
-                               ts.tv_sec = runtime·timediv(ns, 1000000000, (int32*)&ts.tv_nsec);
-                               // TODO(jsing) - potential deadlock!
-                               // See above for details.
-                               runtime·atomicstore(&g->m->waitsemalock, 0);
-                               runtime·lwp_park(&ts, 0, &g->m->waitsemacount, nil);
-                       }
-                       // reacquire lock
-                       while(runtime·xchg(&g->m->waitsemalock, 1))
-                               runtime·osyield();
-               }
-
-               // lock held (again)
-               if(g->m->waitsemacount != 0) {
-                       // semaphore is available.
-                       g->m->waitsemacount--;
-                       // spin-mutex unlock
-                       runtime·atomicstore(&g->m->waitsemalock, 0);
-                       g->m->scalararg[0] = 0; // semaphore acquired
-                       return;
-               }
-
-               // semaphore not available.
-               // if there is a timeout, stop now.
-               // otherwise keep trying.
-               if(ns >= 0)
-                       break;
-       }
-
-       // lock held but giving up
-       // spin-mutex unlock
-       runtime·atomicstore(&g->m->waitsemalock, 0);
-       g->m->scalararg[0] = -1;
-       return;
-}
-
-#pragma textflag NOSPLIT
-int32
-runtime·semasleep(int64 ns)
-{
-       int32 r;
-       void (*fn)(void);
-
-       g->m->scalararg[0] = (uint32)ns;
-       g->m->scalararg[1] = (uint32)(ns>>32);
-       fn = semasleep;
-       runtime·onM(&fn);
-       r = g->m->scalararg[0];
-       g->m->scalararg[0] = 0;
-       return r;
-}
-
-static void badsemawakeup(void);
-
-#pragma textflag NOSPLIT
-void
-runtime·semawakeup(M *mp)
-{
-       uint32 ret;
-       void (*fn)(void);
-       void *oldptr;
-       uintptr oldscalar;
-
-       // spin-mutex lock
-       while(runtime·xchg(&mp->waitsemalock, 1))
-               runtime·osyield();
-       mp->waitsemacount++;
-       // TODO(jsing) - potential deadlock, see semasleep() for details.
-       // Confirm that LWP is parked before unparking...
-       ret = runtime·lwp_unpark(mp->procid, &mp->waitsemacount);
-       if(ret != 0 && ret != ESRCH) {
-               // semawakeup can be called on signal stack.
-               // Save old ptrarg/scalararg so we can restore them.
-               oldptr = g->m->ptrarg[0];
-               oldscalar = g->m->scalararg[0];
-               g->m->ptrarg[0] = mp;
-               g->m->scalararg[0] = ret;
-               fn = badsemawakeup;
-               if(g == g->m->gsignal)
-                       fn();
-               else
-                       runtime·onM(&fn);
-               g->m->ptrarg[0] = oldptr;
-               g->m->scalararg[0] = oldscalar;
-       }
-       // spin-mutex unlock
-       runtime·atomicstore(&mp->waitsemalock, 0);
-}
-
-static void
-badsemawakeup(void)
-{
-       M *mp;
-       int32 ret;
-
-       mp = g->m->ptrarg[0];
-       g->m->ptrarg[0] = nil;
-       ret = g->m->scalararg[0];
-       g->m->scalararg[0] = 0;
-
-       runtime·printf("thrwakeup addr=%p sem=%d ret=%d\n", &mp->waitsemacount, mp->waitsemacount, ret);
-}
-
-void
-runtime·newosproc(M *mp, void *stk)
-{
-       UcontextT uc;
-       int32 ret;
-
-       if(0) {
-               runtime·printf(
-                       "newosproc stk=%p m=%p g=%p id=%d/%d ostk=%p\n",
-                       stk, mp, mp->g0, mp->id, (int32)mp->tls[0], &mp);
-       }
-
-       mp->tls[0] = mp->id;    // so 386 asm can find it
-
-       runtime·getcontext(&uc);
-       
-       uc.uc_flags = _UC_SIGMASK | _UC_CPU;
-       uc.uc_link = nil;
-       uc.uc_sigmask = sigset_all;
-
-       runtime·lwp_mcontext_init(&uc.uc_mcontext, stk, mp, mp->g0, runtime·mstart);
-
-       ret = runtime·lwp_create(&uc, 0, &mp->procid);
-
-       if(ret < 0) {
-               runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount() - 1, -ret);
-               runtime·throw("runtime.newosproc");
-       }
-}
-
-void
-runtime·osinit(void)
-{
-       runtime·ncpu = getncpu();
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·get_random_data(byte **rnd, int32 *rnd_len)
-{
-       #pragma dataflag NOPTR
-       static byte urandom_data[HashRandomBytes];
-       int32 fd;
-       fd = runtime·open("/dev/urandom", 0 /* O_RDONLY */, 0);
-       if(runtime·read(fd, urandom_data, HashRandomBytes) == HashRandomBytes) {
-               *rnd = urandom_data;
-               *rnd_len = HashRandomBytes;
-       } else {
-               *rnd = nil;
-               *rnd_len = 0;
-       }
-       runtime·close(fd);
-}
-
-void
-runtime·goenvs(void)
-{
-       runtime·goenvs_unix();
-}
-
-// Called to initialize a new m (including the bootstrap m).
-// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
-void
-runtime·mpreinit(M *mp)
-{
-       mp->gsignal = runtime·malg(32*1024);
-       runtime·writebarrierptr_nostore(&mp->gsignal, mp->gsignal);
-
-       mp->gsignal->m = mp;
-       runtime·writebarrierptr_nostore(&mp->gsignal->m, mp->gsignal->m);
-}
-
-// Called to initialize a new m (including the bootstrap m).
-// Called on the new thread, can not allocate memory.
-void
-runtime·minit(void)
-{
-       g->m->procid = runtime·lwp_self();
-
-       // Initialize signal handling
-       runtime·signalstack((byte*)g->m->gsignal->stack.lo, 32*1024);
-       runtime·sigprocmask(SIG_SETMASK, &sigset_none, nil);
-}
-
-// Called from dropm to undo the effect of an minit.
-void
-runtime·unminit(void)
-{
-       runtime·signalstack(nil, 0);
-}
-
-uintptr
-runtime·memlimit(void)
-{
-       return 0;
-}
-
-extern void runtime·sigtramp(void);
-
-typedef struct sigaction {
-       union {
-               void    (*_sa_handler)(int32);
-               void    (*_sa_sigaction)(int32, Siginfo*, void *);
-       } _sa_u;                        /* signal handler */
-       uint32  sa_mask[4];             /* signal mask to apply */
-       int32   sa_flags;               /* see signal options below */
-} SigactionT;
-
-void
-runtime·setsig(int32 i, GoSighandler *fn, bool restart)
-{
-       SigactionT sa;
-
-       runtime·memclr((byte*)&sa, sizeof sa);
-       sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
-       if(restart)
-               sa.sa_flags |= SA_RESTART;
-       sa.sa_mask[0] = ~0U;
-       sa.sa_mask[1] = ~0U;
-       sa.sa_mask[2] = ~0U;
-       sa.sa_mask[3] = ~0U;
-       if (fn == runtime·sighandler)
-               fn = (void*)runtime·sigtramp;
-       sa._sa_u._sa_sigaction = (void*)fn;
-       runtime·sigaction(i, &sa, nil);
-}
-
-GoSighandler*
-runtime·getsig(int32 i)
-{
-       SigactionT sa;
-
-       runtime·memclr((byte*)&sa, sizeof sa);
-       runtime·sigaction(i, nil, &sa);
-       if((void*)sa._sa_u._sa_sigaction == runtime·sigtramp)
-               return runtime·sighandler;
-       return (void*)sa._sa_u._sa_sigaction;
-}
-
-void
-runtime·signalstack(byte *p, int32 n)
-{
-       StackT st;
-
-       st.ss_sp = (void*)p;
-       st.ss_size = n;
-       st.ss_flags = 0;
-       if(p == nil)
-               st.ss_flags = SS_DISABLE;
-       runtime·sigaltstack(&st, nil);
-}
-
-void
-runtime·unblocksignals(void)
-{
-       runtime·sigprocmask(SIG_SETMASK, &sigset_none, nil);
-}
-
-#pragma textflag NOSPLIT
-int8*
-runtime·signame(int32 sig)
-{
-       return runtime·sigtab[sig].name;
-}
index f000c5e9f64fe04e2df9a986fbfe4d0fe3e6a760..a153bf2ebcfa025121c0443aecb8881341ab9e9d 100644 (file)
@@ -6,15 +6,37 @@ package runtime
 
 import "unsafe"
 
-func setitimer(mode int32, new, old unsafe.Pointer)
-func sigaction(sig int32, new, old unsafe.Pointer)
-func sigaltstack(new, old unsafe.Pointer)
-func sigprocmask(mode int32, new, old unsafe.Pointer)
+//go:noescape
+func setitimer(mode int32, new, old *itimerval)
+
+//go:noescape
+func sigaction(sig int32, new, old *sigactiont)
+
+//go:noescape
+func sigaltstack(new, old *sigaltstackt)
+
+//go:noescape
+func sigprocmask(mode int32, new, old *sigset)
+
+//go:noescape
 func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
+
 func lwp_tramp()
+
 func raise(sig int32)
+
+//go:noescape
 func getcontext(ctxt unsafe.Pointer)
+
+//go:noescape
 func lwp_create(ctxt unsafe.Pointer, flags uintptr, lwpid unsafe.Pointer) int32
-func lwp_park(abstime unsafe.Pointer, unpark int32, hint, unparkhint unsafe.Pointer) int32
+
+//go:noescape
+func lwp_park(abstime *timespec, unpark int32, hint, unparkhint unsafe.Pointer) int32
+
+//go:noescape
 func lwp_unpark(lwp int32, hint unsafe.Pointer) int32
+
 func lwp_self() int32
+
+func osyield()
diff --git a/src/runtime/os_netbsd.h b/src/runtime/os_netbsd.h
deleted file mode 100644 (file)
index f95db32..0000000
+++ /dev/null
@@ -1,31 +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.
-
-
-typedef uintptr kevent_udata;
-
-struct sigaction;
-
-void   runtime·sigpanic(void);
-
-void   runtime·setitimer(int32, Itimerval*, Itimerval*);
-void   runtime·sigaction(int32, struct sigaction*, struct sigaction*);
-void   runtime·sigaltstack(SigaltstackT*, SigaltstackT*);
-void   runtime·sigprocmask(int32, Sigset*, Sigset*);
-void   runtime·unblocksignals(void);
-int32  runtime·sysctl(uint32*, uint32, byte*, uintptr*, byte*, uintptr);
-extern void runtime·lwp_tramp(void);
-
-enum {
-       SS_DISABLE = 4,
-       SIG_BLOCK = 1,
-       SIG_UNBLOCK = 2,
-       SIG_SETMASK = 3,
-       NSIG = 33,
-       SI_USER = 0,
-
-       // From NetBSD's <sys/ucontext.h>
-       _UC_SIGMASK = 0x01,
-       _UC_CPU = 0x04,
-};
diff --git a/src/runtime/os_netbsd_386.c b/src/runtime/os_netbsd_386.c
deleted file mode 100644 (file)
index 23e9db3..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// 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 "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-
-void
-runtime·lwp_mcontext_init(McontextT *mc, void *stack, M *mp, G *gp, void (*fn)(void))
-{
-       mc->__gregs[REG_EIP] = (uint32)runtime·lwp_tramp;
-       mc->__gregs[REG_UESP] = (uint32)stack;
-       mc->__gregs[REG_EBX] = (uint32)mp;
-       mc->__gregs[REG_EDX] = (uint32)gp;
-       mc->__gregs[REG_ESI] = (uint32)fn;
-}
diff --git a/src/runtime/os_netbsd_amd64.c b/src/runtime/os_netbsd_amd64.c
deleted file mode 100644 (file)
index 226846c..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// 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 "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-
-void
-runtime·lwp_mcontext_init(McontextT *mc, void *stack, M *mp, G *gp, void (*fn)(void))
-{
-       // Machine dependent mcontext initialisation for LWP.
-       mc->__gregs[REG_RIP] = (uint64)runtime·lwp_tramp;
-       mc->__gregs[REG_RSP] = (uint64)stack;
-       mc->__gregs[REG_R8] = (uint64)mp;
-       mc->__gregs[REG_R9] = (uint64)gp;
-       mc->__gregs[REG_R12] = (uint64)fn;
-}
diff --git a/src/runtime/os_plan9.c b/src/runtime/os_plan9.c
deleted file mode 100644 (file)
index 18460fc..0000000
+++ /dev/null
@@ -1,368 +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.
-
-#include "runtime.h"
-#include "os_GOOS.h"
-#include "arch_GOARCH.h"
-#include "textflag.h"
-#include "malloc.h"
-
-int8 *goos = "plan9";
-extern SigTab runtime·sigtab[];
-
-int32 runtime·postnote(int32, int8*);
-
-// Called to initialize a new m (including the bootstrap m).
-// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
-void
-runtime·mpreinit(M *mp)
-{
-       // Initialize stack and goroutine for note handling.
-       mp->gsignal = runtime·malg(32*1024);
-       runtime·writebarrierptr_nostore(&mp->gsignal, mp->gsignal);
-
-       mp->gsignal->m = mp;
-       runtime·writebarrierptr_nostore(&mp->gsignal->m, mp->gsignal->m);
-
-       mp->notesig = (int8*)runtime·mallocgc(ERRMAX*sizeof(int8), nil, FlagNoScan);
-       runtime·writebarrierptr_nostore(&mp->notesig, mp->notesig);
-
-       // Initialize stack for handling strings from the
-       // errstr system call, as used in package syscall.
-       mp->errstr = (byte*)runtime·mallocgc(ERRMAX*sizeof(byte), nil, FlagNoScan);
-       runtime·writebarrierptr_nostore(&mp->errstr, mp->errstr);
-}
-
-// Called to initialize a new m (including the bootstrap m).
-// Called on the new thread, can not allocate memory.
-void
-runtime·minit(void)
-{
-       // Mask all SSE floating-point exceptions
-       // when running on the 64-bit kernel.
-       runtime·setfpmasks();
-}
-
-// Called from dropm to undo the effect of an minit.
-void
-runtime·unminit(void)
-{
-}
-
-
-static int32
-getproccount(void)
-{
-       int32 fd, i, n, ncpu;
-       byte buf[2048];
-
-       fd = runtime·open("/dev/sysstat", OREAD, 0);
-       if(fd < 0)
-               return 1;
-       ncpu = 0;
-       for(;;) {
-               n = runtime·read(fd, buf, sizeof buf);
-               if(n <= 0)
-                       break;
-               for(i = 0; i < n; i++) {
-                       if(buf[i] == '\n')
-                               ncpu++;
-               }
-       }
-       runtime·close(fd);
-       return ncpu > 0 ? ncpu : 1;
-}
-
-static int32
-getpid(void)
-{
-       byte b[20], *c;
-       int32 fd;
-
-       runtime·memclr(b, sizeof(b));
-       fd = runtime·open("#c/pid", 0, 0);
-       if(fd >= 0) {
-               runtime·read(fd, b, sizeof(b));
-               runtime·close(fd);
-       }
-       c = b;
-       while(*c == ' ' || *c == '\t')
-               c++;
-       return runtime·atoi(c);
-}
-
-void
-runtime·osinit(void)
-{
-       runtime·ncpu = getproccount();
-       g->m->procid = getpid();
-       runtime·notify(runtime·sigtramp);
-}
-
-void
-runtime·crash(void)
-{
-       runtime·notify(nil);
-       *(int32*)0 = 0;
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·get_random_data(byte **rnd, int32 *rnd_len)
-{
-       static byte random_data[HashRandomBytes];
-       int32 fd;
-
-       fd = runtime·open("/dev/random", 0 /* O_RDONLY */, 0);
-       if(runtime·read(fd, random_data, HashRandomBytes) == HashRandomBytes) {
-               *rnd = random_data;
-               *rnd_len = HashRandomBytes;
-       } else {
-               *rnd = nil;
-               *rnd_len = 0;
-       }
-       runtime·close(fd);
-}
-
-void
-runtime·goenvs(void)
-{
-}
-
-void
-runtime·initsig(void)
-{
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·osyield(void)
-{
-       runtime·sleep(0);
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·usleep(uint32 Âµs)
-{
-       uint32 ms;
-
-       ms = Âµs/1000;
-       if(ms == 0)
-               ms = 1;
-       runtime·sleep(ms);
-}
-
-#pragma textflag NOSPLIT
-int64
-runtime·nanotime(void)
-{
-       int64 ns, scratch;
-
-       ns = runtime·nsec(&scratch);
-       // TODO(aram): remove hack after I fix _nsec in the pc64 kernel.
-       if(ns == 0)
-               return scratch;
-       return ns;
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·itoa(int32 n, byte *p, uint32 len)
-{
-       byte *q, c;
-       uint32 i;
-
-       if(len <= 1)
-               return;
-
-       runtime·memclr(p, len);
-       q = p;
-
-       if(n==0) {
-               *q++ = '0';
-               USED(q);
-               return;
-       }
-       if(n < 0) {
-               *q++ = '-';
-               p++;
-               n = -n;
-       }
-       for(i=0; n > 0 && i < len; i++) {
-               *q++ = '0' + (n%10);
-               n = n/10;
-       }
-       for(q--; q >= p; ) {
-               c = *p;
-               *p++ = *q;
-               *q-- = c;
-       }
-}
-
-void
-runtime·goexitsall(int8 *status)
-{
-       int8 buf[ERRMAX];
-       M *mp;
-       int32 pid;
-
-       runtime·snprintf((byte*)buf, sizeof buf, "go: exit %s", status);
-       pid = getpid();
-       for(mp=runtime·atomicloadp(&runtime·allm); mp; mp=mp->alllink)
-               if(mp->procid != pid)
-                       runtime·postnote(mp->procid, buf);
-}
-
-int32
-runtime·postnote(int32 pid, int8* msg)
-{
-       int32 fd;
-       intgo len;
-       uint8 buf[128];
-       uint8 tmp[16];
-       uint8 *p, *q;
-
-       runtime·memclr(buf, sizeof buf);
-
-       /* build path string /proc/pid/note */
-       q = tmp;
-       p = buf;
-       runtime·itoa(pid, tmp, sizeof tmp);
-       runtime·memmove((void*)p, (void*)"/proc/", 6);
-       for(p += 6; *p++ = *q++; );
-       p--;
-       runtime·memmove((void*)p, (void*)"/note", 5);
-
-       fd = runtime·open((int8*)buf, OWRITE, 0);
-       if(fd < 0)
-               return -1;
-
-       len = runtime·findnull((byte*)msg);
-       if(runtime·write(fd, msg, len) != len) {
-               runtime·close(fd);
-               return -1;
-       }
-       runtime·close(fd);
-       return 0;
-}
-
-static void exit(void);
-
-#pragma textflag NOSPLIT
-void
-runtime·exit(int32 e)
-{
-       void (*fn)(void);
-
-       g->m->scalararg[0] = e;
-       fn = exit;
-       runtime·onM(&fn);
-}
-
-static void
-exit(void)
-{
-       int32 e;
-       byte tmp[16];
-       int8 *status;
-       e = g->m->scalararg[0];
-       g->m->scalararg[0] = 0;
-
-       if(e == 0)
-               status = "";
-       else {
-               /* build error string */
-               runtime·itoa(e, tmp, sizeof tmp);
-               status = (int8*)tmp;
-       }
-
-       runtime·goexitsall(status);
-       runtime·exits(status);
-}
-
-void
-runtime·newosproc(M *mp, void *stk)
-{
-       int32 pid;
-
-       if(0)
-               runtime·printf("newosproc mp=%p ostk=%p\n", mp, &mp);
-
-       USED(stk);
-       if((pid = runtime·rfork(RFPROC|RFMEM|RFNOWAIT)) < 0)
-               runtime·throw("newosproc: rfork failed\n");
-       if(pid == 0)
-               runtime·tstart_plan9(mp);
-}
-
-#pragma textflag NOSPLIT
-uintptr
-runtime·semacreate(void)
-{
-       return 1;
-}
-
-#pragma textflag NOSPLIT
-int32
-runtime·semasleep(int64 ns)
-{
-       int32 ret;
-       int32 ms;
-
-       if(ns >= 0) {
-               ms = runtime·timediv(ns, 1000000, nil);
-               if(ms == 0)
-                       ms = 1;
-               ret = runtime·plan9_tsemacquire(&g->m->waitsemacount, ms);
-               if(ret == 1)
-                       return 0;  // success
-               return -1;  // timeout or interrupted
-       }
-
-       while(runtime·plan9_semacquire(&g->m->waitsemacount, 1) < 0) {
-               /* interrupted; try again (c.f. lock_sema.c) */
-       }
-       return 0;  // success
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·semawakeup(M *mp)
-{
-       runtime·plan9_semrelease(&mp->waitsemacount, 1);
-}
-
-#pragma textflag NOSPLIT
-int32
-runtime·read(int32 fd, void *buf, int32 nbytes)
-{
-       return runtime·pread(fd, buf, nbytes, -1LL);
-}
-
-#pragma textflag NOSPLIT
-int32
-runtime·write(uintptr fd, void *buf, int32 nbytes)
-{
-       return runtime·pwrite((int32)fd, buf, nbytes, -1LL);
-}
-
-uintptr
-runtime·memlimit(void)
-{
-       return 0;
-}
-
-#pragma dataflag NOPTR
-static int8 badsignal[] = "runtime: signal received on thread not created by Go.\n";
-
-// This runs on a foreign stack, without an m or a g.  No stack split.
-#pragma textflag NOSPLIT
-void
-runtime·badsignal2(void)
-{
-       runtime·pwrite(2, badsignal, sizeof badsignal - 1, -1LL);
-       runtime·exits(badsignal);
-}
index 20e47bf42e5cd20bf451be7e0c3c1dc61f12949f..2dcdfc009ab140f7130198bfb6c7c7ed72ab56ff 100644 (file)
@@ -6,22 +6,49 @@ package runtime
 
 import "unsafe"
 
+//go:noescape
 func pread(fd int32, buf unsafe.Pointer, nbytes int32, offset int64) int32
+
+//go:noescape
 func pwrite(fd int32, buf unsafe.Pointer, nbytes int32, offset int64) int32
+
 func seek(fd int32, offset int64, whence int32) int64
+
+//go:noescape
 func exits(msg *byte)
+
+//go:noescape
 func brk_(addr unsafe.Pointer) uintptr
+
 func sleep(ms int32) int32
+
 func rfork(flags int32) int32
+
+//go:noescape
 func plan9_semacquire(addr *uint32, block int32) int32
+
+//go:noescape
 func plan9_tsemacquire(addr *uint32, ms int32) int32
+
+//go:noescape
 func plan9_semrelease(addr *uint32, count int32) int32
+
+//go:noescape
 func notify(fn unsafe.Pointer) int32
+
 func noted(mode int32) int32
+
+//go:noescape
 func nsec(*int64) int64
+
+//go:noescape
 func sigtramp(ureg, msg unsafe.Pointer)
+
 func setfpmasks()
+
+//go:noescape
 func tstart_plan9(newm *m)
+
 func errstr() string
 
 type _Plink uintptr
diff --git a/src/runtime/os_plan9.h b/src/runtime/os_plan9.h
deleted file mode 100644 (file)
index 6d18024..0000000
+++ /dev/null
@@ -1,93 +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.
-
-// Plan 9-specific system calls
-int32  runtime·pread(int32 fd, void *buf, int32 nbytes, int64 offset);
-int32  runtime·pwrite(int32 fd, void *buf, int32 nbytes, int64 offset);
-int64  runtime·seek(int32 fd, int64 offset, int32 whence);
-void   runtime·exits(int8* msg);
-intptr runtime·brk_(void*);
-int32  runtime·sleep(int32 ms);
-int32  runtime·rfork(int32 flags);
-int32  runtime·plan9_semacquire(uint32 *addr, int32 block);
-int32  runtime·plan9_tsemacquire(uint32 *addr, int32 ms);
-int32  runtime·plan9_semrelease(uint32 *addr, int32 count);
-int32  runtime·notify(void (*fn)(void*, int8*));
-int32  runtime·noted(int32);
-int64  runtime·nsec(int64*);
-void   runtime·sigtramp(void*, int8*);
-void   runtime·sigpanic(void);
-void   runtime·goexitsall(int8*);
-void   runtime·setfpmasks(void);
-void   runtime·tstart_plan9(M *newm);
-
-/* open */
-enum
-{
-       OREAD   = 0,
-       OWRITE  = 1,
-       ORDWR   = 2,
-       OEXEC   = 3,
-       OTRUNC  = 16,
-       OCEXEC  = 32,
-       ORCLOSE = 64,
-       OEXCL   = 0x1000
-};
-
-/* rfork */
-enum
-{
-       RFNAMEG         = (1<<0),
-       RFENVG          = (1<<1),
-       RFFDG           = (1<<2),
-       RFNOTEG         = (1<<3),
-       RFPROC          = (1<<4),
-       RFMEM           = (1<<5),
-       RFNOWAIT        = (1<<6),
-       RFCNAMEG        = (1<<10),
-       RFCENVG         = (1<<11),
-       RFCFDG          = (1<<12),
-       RFREND          = (1<<13),
-       RFNOMNT         = (1<<14)
-};
-
-/* notify */
-enum
-{
-       NCONT   = 0,
-       NDFLT   = 1
-};
-
-typedef struct Tos Tos;
-typedef intptr _Plink;
-
-struct Tos {
-       struct TosProf                  /* Per process profiling */
-       {
-               _Plink  *pp;    /* known to be 0(ptr) */
-               _Plink  *next;  /* known to be 4(ptr) */
-               _Plink  *last;
-               _Plink  *first;
-               uint32  pid;
-               uint32  what;
-       } prof;
-       uint64  cyclefreq;      /* cycle clock frequency if there is one, 0 otherwise */
-       int64   kcycles;        /* cycles spent in kernel */
-       int64   pcycles;        /* cycles spent in process (kernel + user) */
-       uint32  pid;            /* might as well put the pid here */
-       uint32  clock;
-       /* top of stack is here */
-};
-
-enum {
-       NSIG = 14, /* number of signals in runtime·SigTab array */
-       ERRMAX = 128, /* max length of note string */
-
-       /* Notes in runtime·sigtab that are handled by runtime·sigpanic. */
-       SIGRFAULT = 2,
-       SIGWFAULT = 3,
-       SIGINTDIV = 4,
-       SIGFLOAT = 5,
-       SIGTRAP = 6,
-};
diff --git a/src/runtime/os_plan9_386.c b/src/runtime/os_plan9_386.c
deleted file mode 100644 (file)
index 42c6d16..0000000
+++ /dev/null
@@ -1,150 +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. 
-
-#include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "signals_GOOS.h"
-
-void
-runtime·dumpregs(Ureg *u)
-{
-       runtime·printf("ax     %x\n", u->ax);
-       runtime·printf("bx     %x\n", u->bx);
-       runtime·printf("cx     %x\n", u->cx);
-       runtime·printf("dx     %x\n", u->dx);
-       runtime·printf("di     %x\n", u->di);
-       runtime·printf("si     %x\n", u->si);
-       runtime·printf("bp     %x\n", u->bp);
-       runtime·printf("sp     %x\n", u->sp);
-       runtime·printf("pc     %x\n", u->pc);
-       runtime·printf("flags  %x\n", u->flags);
-       runtime·printf("cs     %x\n", u->cs);
-       runtime·printf("fs     %x\n", u->fs);
-       runtime·printf("gs     %x\n", u->gs);
-}
-
-int32
-runtime·sighandler(void *v, int8 *note, G *gp)
-{
-       uintptr *sp;
-       SigTab *t;
-       bool crash;
-       Ureg *ureg;
-       intgo len, n;
-       int32 sig, flags;
-
-       ureg = (Ureg*)v;
-
-       // The kernel will never pass us a nil note or ureg so we probably
-       // made a mistake somewhere in runtime·sigtramp.
-       if(ureg == nil || note == nil) {
-               runtime·printf("sighandler: ureg %p note %p\n", ureg, note);
-               goto Throw;
-       }
-
-       // Check that the note is no more than ERRMAX bytes (including
-       // the trailing NUL). We should never receive a longer note.
-       len = runtime·findnull((byte*)note);
-       if(len > ERRMAX-1) {
-               runtime·printf("sighandler: note is longer than ERRMAX\n");
-               goto Throw;
-       }
-
-       // See if the note matches one of the patterns in runtime·sigtab.
-       // Notes that do not match any pattern can be handled at a higher
-       // level by the program but will otherwise be ignored.
-       flags = SigNotify;
-       for(sig = 0; sig < nelem(runtime·sigtab); sig++) {
-               t = &runtime·sigtab[sig];
-               n = runtime·findnull((byte*)t->name);
-               if(len < n)
-                       continue;
-               if(runtime·strncmp((byte*)note, (byte*)t->name, n) == 0) {
-                       flags = t->flags;
-                       break;
-               }
-       }
-
-       if(flags & SigGoExit)
-               runtime·exits(note+9); // Strip "go: exit " prefix.
-
-       if(flags & SigPanic) {
-               // Copy the error string from sigtramp's stack into m->notesig so
-               // we can reliably access it from the panic routines.
-               runtime·memmove(g->m->notesig, note, len+1);
-
-               gp->sig = sig;
-               gp->sigpc = ureg->pc;
-
-               // Only push runtime·sigpanic if PC != 0.
-               //
-               // If PC == 0, probably panicked because of a call to a nil func.
-               // Not pushing that onto SP will make the trace look like a call
-               // to runtime·sigpanic instead. (Otherwise the trace will end at
-               // runtime·sigpanic and we won't get to see who faulted).
-               if(ureg->pc != 0) {
-                       sp = (uintptr*)ureg->sp;
-                       *--sp = ureg->pc;
-                       ureg->sp = (uint32)sp;
-               }
-               ureg->pc = (uintptr)runtime·sigpanic;
-               return NCONT;
-       }
-
-       if(flags & SigNotify) {
-               // TODO(ality): See if os/signal wants it.
-               //if(runtime·sigsend(...))
-               //      return NCONT;
-       }
-       if(flags & SigKill)
-               goto Exit;
-       if(!(flags & SigThrow))
-               return NCONT;
-
-Throw:
-       g->m->throwing = 1;
-       g->m->caughtsig = gp;
-       runtime·startpanic();
-
-       runtime·printf("%s\n", note);
-       runtime·printf("PC=%x\n", ureg->pc);
-       runtime·printf("\n");
-
-       if(runtime·gotraceback(&crash)) {
-               runtime·goroutineheader(gp);
-               runtime·tracebacktrap(ureg->pc, ureg->sp, 0, gp);
-               runtime·tracebackothers(gp);
-               runtime·printf("\n");
-               runtime·dumpregs(ureg);
-       }
-       
-       if(crash)
-               runtime·crash();
-
-Exit:
-       runtime·goexitsall(note);
-       runtime·exits(note);
-       return NDFLT; // not reached
-}
-
-void
-runtime·sigenable(uint32 sig)
-{
-       USED(sig);
-}
-
-void
-runtime·sigdisable(uint32 sig)
-{
-       USED(sig);
-}
-
-void
-runtime·resetcpuprofiler(int32 hz)
-{
-       // TODO: Enable profiling interrupts.
-       
-       g->m->profilehz = hz;
-}
diff --git a/src/runtime/os_plan9_386.go b/src/runtime/os_plan9_386.go
new file mode 100644 (file)
index 0000000..7dda139
--- /dev/null
@@ -0,0 +1,131 @@
+// 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
+
+import "unsafe"
+
+func dumpregs(u *ureg) {
+       print("ax    ", hex(u.ax), "\n")
+       print("bx    ", hex(u.bx), "\n")
+       print("cx    ", hex(u.cx), "\n")
+       print("dx    ", hex(u.dx), "\n")
+       print("di    ", hex(u.di), "\n")
+       print("si    ", hex(u.si), "\n")
+       print("bp    ", hex(u.bp), "\n")
+       print("sp    ", hex(u.sp), "\n")
+       print("pc    ", hex(u.pc), "\n")
+       print("flags ", hex(u.flags), "\n")
+       print("cs    ", hex(u.cs), "\n")
+       print("fs    ", hex(u.fs), "\n")
+       print("gs    ", hex(u.gs), "\n")
+}
+
+func sighandler(_ureg *ureg, note *byte, gp *g) int {
+       _g_ := getg()
+       var t sigTabT
+       var docrash bool
+       var length int
+       var sig int
+       var flags int
+
+       // The kernel will never pass us a nil note or ureg so we probably
+       // made a mistake somewhere in sigtramp.
+       if _ureg == nil || note == nil {
+               print("sighandler: ureg ", _ureg, " note ", note, "\n")
+               goto Throw
+       }
+       // Check that the note is no more than ERRMAX bytes (including
+       // the trailing NUL). We should never receive a longer note.
+       length = findnull(note)
+       if length > _ERRMAX-1 {
+               print("sighandler: note is longer than ERRMAX\n")
+               goto Throw
+       }
+       // See if the note matches one of the patterns in sigtab.
+       // Notes that do not match any pattern can be handled at a higher
+       // level by the program but will otherwise be ignored.
+       flags = _SigNotify
+       for sig, t = range sigtable {
+               n := len(t.name)
+               if length < n {
+                       continue
+               }
+               if strncmp(note, &t.name[0], uintptr(n)) == 0 {
+                       flags = t.flags
+                       break
+               }
+       }
+       if flags&_SigGoExit != 0 {
+               exits((*byte)(add(unsafe.Pointer(note), 9))) // Strip "go: exit " prefix.
+       }
+       if flags&_SigPanic != 0 {
+               // Copy the error string from sigtramp's stack into m->notesig so
+               // we can reliably access it from the panic routines.
+               memmove(unsafe.Pointer(_g_.m.notesig), unsafe.Pointer(note), uintptr(length+1))
+               gp.sig = uint32(sig)
+               gp.sigpc = uintptr(_ureg.pc)
+               // Only push sigpanic if PC != 0.
+               //
+               // If PC == 0, probably panicked because of a call to a nil func.
+               // Not pushing that onto SP will make the trace look like a call
+               // to sigpanic instead. (Otherwise the trace will end at
+               // sigpanic and we won't get to see who faulted).
+               if _ureg.pc != 0 {
+                       sp := _ureg.sp
+                       if regSize > ptrSize {
+                               sp -= ptrSize
+                               *(*uintptr)(unsafe.Pointer(uintptr(sp))) = 0
+                       }
+                       sp -= ptrSize
+                       *(*uintptr)(unsafe.Pointer(uintptr(sp))) = uintptr(_ureg.pc)
+                       _ureg.sp = sp
+               }
+               _ureg.pc = uint32(funcPC(sigpanic))
+               return _NCONT
+       }
+       if flags&_SigNotify != 0 {
+               // TODO(ality): See if os/signal wants it.
+               //if(sigsend(...))
+               //      return _NCONT;
+       }
+       if flags&_SigKill != 0 {
+               goto Exit
+       }
+       if flags&_SigThrow == 0 {
+               return _NCONT
+       }
+Throw:
+       _g_.m.throwing = 1
+       _g_.m.caughtsig = gp
+       startpanic()
+       print(gostringnocopy(note), "\n")
+       print("PC=", hex(_ureg.pc), "\n")
+       print("\n")
+       if gotraceback(&docrash) > 0 {
+               goroutineheader(gp)
+               tracebacktrap(uintptr(_ureg.pc), uintptr(_ureg.sp), 0, gp)
+               tracebackothers(gp)
+               print("\n")
+               dumpregs(_ureg)
+       }
+       if docrash {
+               crash()
+       }
+Exit:
+       goexitsall(note)
+       exits(note)
+       return _NDFLT // not reached
+}
+
+func sigenable(sig uint32) {
+}
+
+func sigdisable(sig uint32) {
+}
+
+func resetcpuprofiler(hz int32) {
+       // TODO: Enable profiling interrupts.
+       getg().m.profilehz = hz
+}
diff --git a/src/runtime/os_plan9_amd64.c b/src/runtime/os_plan9_amd64.c
deleted file mode 100644 (file)
index a9dc0eb..0000000
+++ /dev/null
@@ -1,158 +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. 
-
-#include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "signals_GOOS.h"
-
-void
-runtime·dumpregs(Ureg *u)
-{
-       runtime·printf("ax     %X\n", u->ax);
-       runtime·printf("bx     %X\n", u->bx);
-       runtime·printf("cx     %X\n", u->cx);
-       runtime·printf("dx     %X\n", u->dx);
-       runtime·printf("di     %X\n", u->di);
-       runtime·printf("si     %X\n", u->si);
-       runtime·printf("bp     %X\n", u->bp);
-       runtime·printf("sp     %X\n", u->sp);
-       runtime·printf("r8     %X\n", u->r8);
-       runtime·printf("r9     %X\n", u->r9);
-       runtime·printf("r10    %X\n", u->r10);
-       runtime·printf("r11    %X\n", u->r11);
-       runtime·printf("r12    %X\n", u->r12);
-       runtime·printf("r13    %X\n", u->r13);
-       runtime·printf("r14    %X\n", u->r14);
-       runtime·printf("r15    %X\n", u->r15);
-       runtime·printf("ip     %X\n", u->ip);
-       runtime·printf("flags  %X\n", u->flags);
-       runtime·printf("cs     %X\n", (uint64)u->cs);
-       runtime·printf("fs     %X\n", (uint64)u->fs);
-       runtime·printf("gs     %X\n", (uint64)u->gs);
-}
-
-int32
-runtime·sighandler(void *v, int8 *note, G *gp)
-{
-       uintptr *sp;
-       SigTab *t;
-       bool crash;
-       Ureg *ureg;
-       intgo len, n;
-       int32 sig, flags;
-
-       ureg = (Ureg*)v;
-
-       // The kernel will never pass us a nil note or ureg so we probably
-       // made a mistake somewhere in runtime·sigtramp.
-       if(ureg == nil || note == nil) {
-               runtime·printf("sighandler: ureg %p note %p\n", ureg, note);
-               goto Throw;
-       }
-
-       // Check that the note is no more than ERRMAX bytes (including
-       // the trailing NUL). We should never receive a longer note.
-       len = runtime·findnull((byte*)note);
-       if(len > ERRMAX-1) {
-               runtime·printf("sighandler: note is longer than ERRMAX\n");
-               goto Throw;
-       }
-
-       // See if the note matches one of the patterns in runtime·sigtab.
-       // Notes that do not match any pattern can be handled at a higher
-       // level by the program but will otherwise be ignored.
-       flags = SigNotify;
-       for(sig = 0; sig < nelem(runtime·sigtab); sig++) {
-               t = &runtime·sigtab[sig];
-               n = runtime·findnull((byte*)t->name);
-               if(len < n)
-                       continue;
-               if(runtime·strncmp((byte*)note, (byte*)t->name, n) == 0) {
-                       flags = t->flags;
-                       break;
-               }
-       }
-
-       if(flags & SigGoExit)
-               runtime·exits(note+9); // Strip "go: exit " prefix.
-
-       if(flags & SigPanic) {
-               // Copy the error string from sigtramp's stack into m->notesig so
-               // we can reliably access it from the panic routines.
-               runtime·memmove(g->m->notesig, note, len+1);
-
-               gp->sig = sig;
-               gp->sigpc = ureg->ip;
-
-               // Only push runtime·sigpanic if PC != 0.
-               //
-               // If PC == 0, probably panicked because of a call to a nil func.
-               // Not pushing that onto SP will make the trace look like a call
-               // to runtime·sigpanic instead. (Otherwise the trace will end at
-               // runtime·sigpanic and we won't get to see who faulted).
-               if(ureg->ip != 0) {
-                       sp = (uintptr*)ureg->sp;
-                       *--sp = ureg->ip;
-                       ureg->sp = (uint64)sp;
-               }
-               ureg->ip = (uintptr)runtime·sigpanic;
-               return NCONT;
-       }
-
-       if(flags & SigNotify) {
-               // TODO(ality): See if os/signal wants it.
-               //if(runtime·sigsend(...))
-               //      return NCONT;
-       }
-       if(flags & SigKill)
-               goto Exit;
-       if(!(flags & SigThrow))
-               return NCONT;
-
-Throw:
-       g->m->throwing = 1;
-       g->m->caughtsig = gp;
-       runtime·startpanic();
-
-       runtime·printf("%s\n", note);
-       runtime·printf("PC=%X\n", ureg->ip);
-       runtime·printf("\n");
-
-       if(runtime·gotraceback(&crash)) {
-               runtime·goroutineheader(gp);
-               runtime·tracebacktrap(ureg->ip, ureg->sp, 0, gp);
-               runtime·tracebackothers(gp);
-               runtime·printf("\n");
-               runtime·dumpregs(ureg);
-       }
-       
-       if(crash)
-               runtime·crash();
-
-Exit:
-       runtime·goexitsall(note);
-       runtime·exits(note);
-       return NDFLT; // not reached
-}
-
-void
-runtime·sigenable(uint32 sig)
-{
-       USED(sig);
-}
-
-void
-runtime·sigdisable(uint32 sig)
-{
-       USED(sig);
-}
-
-void
-runtime·resetcpuprofiler(int32 hz)
-{
-       // TODO: Enable profiling interrupts.
-       
-       g->m->profilehz = hz;
-}
diff --git a/src/runtime/os_plan9_amd64.go b/src/runtime/os_plan9_amd64.go
new file mode 100644 (file)
index 0000000..8727dcc
--- /dev/null
@@ -0,0 +1,139 @@
+// 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
+
+import "unsafe"
+
+func dumpregs(u *ureg) {
+       print("ax    ", hex(u.ax), "\n")
+       print("bx    ", hex(u.bx), "\n")
+       print("cx    ", hex(u.cx), "\n")
+       print("dx    ", hex(u.dx), "\n")
+       print("di    ", hex(u.di), "\n")
+       print("si    ", hex(u.si), "\n")
+       print("bp    ", hex(u.bp), "\n")
+       print("sp    ", hex(u.sp), "\n")
+       print("r8    ", hex(u.r8), "\n")
+       print("r9    ", hex(u.r9), "\n")
+       print("r10   ", hex(u.r10), "\n")
+       print("r11   ", hex(u.r11), "\n")
+       print("r12   ", hex(u.r12), "\n")
+       print("r13   ", hex(u.r13), "\n")
+       print("r14   ", hex(u.r14), "\n")
+       print("r15   ", hex(u.r15), "\n")
+       print("ip    ", hex(u.ip), "\n")
+       print("flags ", hex(u.flags), "\n")
+       print("cs    ", hex(uint64(u.cs)), "\n")
+       print("fs    ", hex(uint64(u.fs)), "\n")
+       print("gs    ", hex(uint64(u.gs)), "\n")
+}
+
+func sighandler(_ureg *ureg, note *byte, gp *g) int {
+       _g_ := getg()
+       var t sigTabT
+       var docrash bool
+       var length int
+       var sig int
+       var flags int
+
+       // The kernel will never pass us a nil note or ureg so we probably
+       // made a mistake somewhere in sigtramp.
+       if _ureg == nil || note == nil {
+               print("sighandler: ureg ", _ureg, " note ", note, "\n")
+               goto Throw
+       }
+       // Check that the note is no more than ERRMAX bytes (including
+       // the trailing NUL). We should never receive a longer note.
+       length = findnull(note)
+       if length > _ERRMAX-1 {
+               print("sighandler: note is longer than ERRMAX\n")
+               goto Throw
+       }
+       // See if the note matches one of the patterns in sigtab.
+       // Notes that do not match any pattern can be handled at a higher
+       // level by the program but will otherwise be ignored.
+       flags = _SigNotify
+       for sig, t = range sigtable {
+               n := len(t.name)
+               if length < n {
+                       continue
+               }
+               if strncmp(note, &t.name[0], uintptr(n)) == 0 {
+                       flags = t.flags
+                       break
+               }
+       }
+       if flags&_SigGoExit != 0 {
+               exits((*byte)(add(unsafe.Pointer(note), 9))) // Strip "go: exit " prefix.
+       }
+       if flags&_SigPanic != 0 {
+               // Copy the error string from sigtramp's stack into m->notesig so
+               // we can reliably access it from the panic routines.
+               memmove(unsafe.Pointer(_g_.m.notesig), unsafe.Pointer(note), uintptr(length+1))
+               gp.sig = uint32(sig)
+               gp.sigpc = uintptr(_ureg.ip)
+               // Only push sigpanic if PC != 0.
+               //
+               // If PC == 0, probably panicked because of a call to a nil func.
+               // Not pushing that onto SP will make the trace look like a call
+               // to sigpanic instead. (Otherwise the trace will end at
+               // sigpanic and we won't get to see who faulted).
+               if _ureg.ip != 0 {
+                       sp := _ureg.sp
+                       if regSize > ptrSize {
+                               sp -= ptrSize
+                               *(*uintptr)(unsafe.Pointer(uintptr(sp))) = 0
+                       }
+                       sp -= ptrSize
+                       *(*uintptr)(unsafe.Pointer(uintptr(sp))) = uintptr(_ureg.ip)
+                       _ureg.sp = sp
+               }
+               _ureg.ip = uint64(funcPC(sigpanic))
+               return _NCONT
+       }
+       if flags&_SigNotify != 0 {
+               // TODO(ality): See if os/signal wants it.
+               //if(sigsend(...))
+               //      return _NCONT;
+       }
+       if flags&_SigKill != 0 {
+               goto Exit
+       }
+       if flags&_SigThrow == 0 {
+               return _NCONT
+       }
+Throw:
+       _g_.m.throwing = 1
+       _g_.m.caughtsig = gp
+       startpanic()
+       print(gostringnocopy(note), "\n")
+       print("PC=", hex(_ureg.ip), "\n")
+       print("\n")
+       if gotraceback(&docrash) > 0 {
+               goroutineheader(gp)
+               tracebacktrap(uintptr(_ureg.ip), uintptr(_ureg.sp), 0, gp)
+               tracebackothers(gp)
+               print("\n")
+               dumpregs(_ureg)
+       }
+       if docrash {
+               crash()
+       }
+Exit:
+       goexitsall(note)
+       exits(note)
+       return _NDFLT // not reached
+}
+
+func sigenable(sig uint32) {
+}
+
+func sigdisable(sig uint32) {
+}
+
+func resetcpuprofiler(hz int32) {
+       // TODO: Enable profiling interrupts.
+       getg().m.profilehz = hz
+}
diff --git a/src/runtime/os_windows.c b/src/runtime/os_windows.c
deleted file mode 100644 (file)
index b8b8eda..0000000
+++ /dev/null
@@ -1,636 +0,0 @@
-// 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 "type.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "textflag.h"
-#include "arch_GOARCH.h"
-#include "malloc.h"
-
-#pragma dynimport runtime·AddVectoredExceptionHandler AddVectoredExceptionHandler "kernel32.dll"
-#pragma dynimport runtime·CloseHandle CloseHandle "kernel32.dll"
-#pragma dynimport runtime·CreateEvent CreateEventA "kernel32.dll"
-#pragma dynimport runtime·CreateThread CreateThread "kernel32.dll"
-#pragma dynimport runtime·CreateWaitableTimer CreateWaitableTimerA "kernel32.dll"
-#pragma dynimport runtime·CryptAcquireContextW CryptAcquireContextW "advapi32.dll"
-#pragma dynimport runtime·CryptGenRandom CryptGenRandom "advapi32.dll"
-#pragma dynimport runtime·CryptReleaseContext CryptReleaseContext "advapi32.dll"
-#pragma dynimport runtime·DuplicateHandle DuplicateHandle "kernel32.dll"
-#pragma dynimport runtime·ExitProcess ExitProcess "kernel32.dll"
-#pragma dynimport runtime·FreeEnvironmentStringsW FreeEnvironmentStringsW "kernel32.dll"
-#pragma dynimport runtime·GetEnvironmentStringsW GetEnvironmentStringsW "kernel32.dll"
-#pragma dynimport runtime·GetProcAddress GetProcAddress "kernel32.dll"
-#pragma dynimport runtime·GetStdHandle GetStdHandle "kernel32.dll"
-#pragma dynimport runtime·GetSystemInfo GetSystemInfo "kernel32.dll"
-#pragma dynimport runtime·GetThreadContext GetThreadContext "kernel32.dll"
-#pragma dynimport runtime·LoadLibrary LoadLibraryW "kernel32.dll"
-#pragma dynimport runtime·LoadLibraryA LoadLibraryA "kernel32.dll"
-#pragma dynimport runtime·NtWaitForSingleObject NtWaitForSingleObject "ntdll.dll"
-#pragma dynimport runtime·ResumeThread ResumeThread "kernel32.dll"
-#pragma dynimport runtime·SetConsoleCtrlHandler SetConsoleCtrlHandler "kernel32.dll"
-#pragma dynimport runtime·SetEvent SetEvent "kernel32.dll"
-#pragma dynimport runtime·SetProcessPriorityBoost SetProcessPriorityBoost "kernel32.dll"
-#pragma dynimport runtime·SetThreadPriority SetThreadPriority "kernel32.dll"
-#pragma dynimport runtime·SetUnhandledExceptionFilter SetUnhandledExceptionFilter "kernel32.dll"
-#pragma dynimport runtime·SetWaitableTimer SetWaitableTimer "kernel32.dll"
-#pragma dynimport runtime·Sleep Sleep "kernel32.dll"
-#pragma dynimport runtime·SuspendThread SuspendThread "kernel32.dll"
-#pragma dynimport runtime·WaitForSingleObject WaitForSingleObject "kernel32.dll"
-#pragma dynimport runtime·WriteFile WriteFile "kernel32.dll"
-#pragma dynimport runtime·timeBeginPeriod timeBeginPeriod "winmm.dll"
-
-extern void *runtime·AddVectoredExceptionHandler;
-extern void *runtime·CloseHandle;
-extern void *runtime·CreateEvent;
-extern void *runtime·CreateThread;
-extern void *runtime·CreateWaitableTimer;
-extern void *runtime·CryptAcquireContextW;
-extern void *runtime·CryptGenRandom;
-extern void *runtime·CryptReleaseContext;
-extern void *runtime·DuplicateHandle;
-extern void *runtime·ExitProcess;
-extern void *runtime·FreeEnvironmentStringsW;
-extern void *runtime·GetEnvironmentStringsW;
-extern void *runtime·GetProcAddress;
-extern void *runtime·GetStdHandle;
-extern void *runtime·GetSystemInfo;
-extern void *runtime·GetThreadContext;
-extern void *runtime·LoadLibrary;
-extern void *runtime·LoadLibraryA;
-extern void *runtime·NtWaitForSingleObject;
-extern void *runtime·ResumeThread;
-extern void *runtime·SetConsoleCtrlHandler;
-extern void *runtime·SetEvent;
-extern void *runtime·SetProcessPriorityBoost;
-extern void *runtime·SetThreadPriority;
-extern void *runtime·SetUnhandledExceptionFilter;
-extern void *runtime·SetWaitableTimer;
-extern void *runtime·Sleep;
-extern void *runtime·SuspendThread;
-extern void *runtime·WaitForSingleObject;
-extern void *runtime·WriteFile;
-extern void *runtime·timeBeginPeriod;
-
-#pragma dataflag NOPTR
-void *runtime·GetQueuedCompletionStatusEx;
-
-extern uintptr runtime·externalthreadhandlerp;
-void runtime·externalthreadhandler(void);
-void runtime·exceptiontramp(void);
-void runtime·firstcontinuetramp(void);
-void runtime·lastcontinuetramp(void);
-
-#pragma textflag NOSPLIT
-uintptr
-runtime·getLoadLibrary(void)
-{
-       return (uintptr)runtime·LoadLibrary;
-}
-
-#pragma textflag NOSPLIT
-uintptr
-runtime·getGetProcAddress(void)
-{
-       return (uintptr)runtime·GetProcAddress;
-}
-
-static int32
-getproccount(void)
-{
-       SystemInfo info;
-
-       runtime·stdcall1(runtime·GetSystemInfo, (uintptr)&info);
-       return info.dwNumberOfProcessors;
-}
-
-void
-runtime·osinit(void)
-{
-       void *kernel32;
-       void *addVectoredContinueHandler;
-
-       kernel32 = runtime·stdcall1(runtime·LoadLibraryA, (uintptr)"kernel32.dll");
-
-       runtime·externalthreadhandlerp = (uintptr)runtime·externalthreadhandler;
-
-       runtime·stdcall2(runtime·AddVectoredExceptionHandler, 1, (uintptr)runtime·exceptiontramp);
-       addVectoredContinueHandler = nil;
-       if(kernel32 != nil)
-               addVectoredContinueHandler = runtime·stdcall2(runtime·GetProcAddress, (uintptr)kernel32, (uintptr)"AddVectoredContinueHandler");
-       if(addVectoredContinueHandler == nil || sizeof(void*) == 4) {
-               // use SetUnhandledExceptionFilter for windows-386 or
-               // if VectoredContinueHandler is unavailable.
-               // note: SetUnhandledExceptionFilter handler won't be called, if debugging.
-               runtime·stdcall1(runtime·SetUnhandledExceptionFilter, (uintptr)runtime·lastcontinuetramp);
-       } else {
-               runtime·stdcall2(addVectoredContinueHandler, 1, (uintptr)runtime·firstcontinuetramp);
-               runtime·stdcall2(addVectoredContinueHandler, 0, (uintptr)runtime·lastcontinuetramp);
-       }
-
-       runtime·stdcall2(runtime·SetConsoleCtrlHandler, (uintptr)runtime·ctrlhandler, 1);
-
-       runtime·stdcall1(runtime·timeBeginPeriod, 1);
-
-       runtime·ncpu = getproccount();
-       
-       // Windows dynamic priority boosting assumes that a process has different types
-       // of dedicated threads -- GUI, IO, computational, etc. Go processes use
-       // equivalent threads that all do a mix of GUI, IO, computations, etc.
-       // In such context dynamic priority boosting does nothing but harm, so we turn it off.
-       runtime·stdcall2(runtime·SetProcessPriorityBoost, -1, 1);
-
-       if(kernel32 != nil) {
-               runtime·GetQueuedCompletionStatusEx = runtime·stdcall2(runtime·GetProcAddress, (uintptr)kernel32, (uintptr)"GetQueuedCompletionStatusEx");
-       }
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·get_random_data(byte **rnd, int32 *rnd_len)
-{
-       uintptr handle;
-       *rnd = nil;
-       *rnd_len = 0;
-       if(runtime·stdcall5(runtime·CryptAcquireContextW, (uintptr)&handle, (uintptr)nil, (uintptr)nil,
-                          1 /* PROV_RSA_FULL */,
-                          0xf0000000U /* CRYPT_VERIFYCONTEXT */) != 0) {
-               static byte random_data[HashRandomBytes];
-               if(runtime·stdcall3(runtime·CryptGenRandom, handle, HashRandomBytes, (uintptr)&random_data[0])) {
-                       *rnd = random_data;
-                       *rnd_len = HashRandomBytes;
-               }
-               runtime·stdcall2(runtime·CryptReleaseContext, handle, 0);
-       }
-}
-
-void
-runtime·goenvs(void)
-{
-       extern Slice runtime·envs;
-
-       uint16 *env;
-       String *s;
-       int32 i, n;
-       uint16 *p;
-
-       env = runtime·stdcall0(runtime·GetEnvironmentStringsW);
-
-       n = 0;
-       for(p=env; *p; n++)
-               p += runtime·findnullw(p)+1;
-
-       runtime·envs = runtime·makeStringSlice(n);
-       s = (String*)runtime·envs.array;
-
-       p = env;
-       for(i=0; i<n; i++) {
-               s[i] = runtime·gostringw(p);
-               p += runtime·findnullw(p)+1;
-       }
-
-       runtime·stdcall1(runtime·FreeEnvironmentStringsW, (uintptr)env);
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·exit(int32 code)
-{
-       runtime·stdcall1(runtime·ExitProcess, code);
-}
-
-#pragma textflag NOSPLIT
-int32
-runtime·write(uintptr fd, void *buf, int32 n)
-{
-       void *handle;
-       uint32 written;
-
-       written = 0;
-       switch(fd) {
-       case 1:
-               handle = runtime·stdcall1(runtime·GetStdHandle, -11);
-               break;
-       case 2:
-               handle = runtime·stdcall1(runtime·GetStdHandle, -12);
-               break;
-       default:
-               // assume fd is real windows handle.
-               handle = (void*)fd;
-               break;
-       }
-       runtime·stdcall5(runtime·WriteFile, (uintptr)handle, (uintptr)buf, n, (uintptr)&written, 0);
-       return written;
-}
-
-#define INFINITE ((uintptr)0xFFFFFFFF)
-
-#pragma textflag NOSPLIT
-int32
-runtime·semasleep(int64 ns)
-{
-       // store ms in ns to save stack space
-       if(ns < 0)
-               ns = INFINITE;
-       else {
-               ns = runtime·timediv(ns, 1000000, nil);
-               if(ns == 0)
-                       ns = 1;
-       }
-       if(runtime·stdcall2(runtime·WaitForSingleObject, (uintptr)g->m->waitsema, ns) != 0)
-               return -1;  // timeout
-       return 0;
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·semawakeup(M *mp)
-{
-       runtime·stdcall1(runtime·SetEvent, mp->waitsema);
-}
-
-#pragma textflag NOSPLIT
-uintptr
-runtime·semacreate(void)
-{
-       return (uintptr)runtime·stdcall4(runtime·CreateEvent, 0, 0, 0, 0);
-}
-
-#define STACK_SIZE_PARAM_IS_A_RESERVATION ((uintptr)0x00010000)
-
-void
-runtime·newosproc(M *mp, void *stk)
-{
-       void *thandle;
-
-       USED(stk);
-
-       thandle = runtime·stdcall6(runtime·CreateThread,
-               (uintptr)nil, 0x20000, (uintptr)runtime·tstart_stdcall, (uintptr)mp,
-               STACK_SIZE_PARAM_IS_A_RESERVATION, (uintptr)nil);
-       if(thandle == nil) {
-               runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount(), runtime·getlasterror());
-               runtime·throw("runtime.newosproc");
-       }
-}
-
-// Called to initialize a new m (including the bootstrap m).
-// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
-void
-runtime·mpreinit(M *mp)
-{
-       USED(mp);
-}
-
-// Called to initialize a new m (including the bootstrap m).
-// Called on the new thread, can not allocate memory.
-void
-runtime·minit(void)
-{
-       uintptr thandle;
-
-       // -1 = current process, -2 = current thread
-       runtime·stdcall7(runtime·DuplicateHandle, -1, -2, -1, (uintptr)&thandle, 0, 0, DUPLICATE_SAME_ACCESS);
-       runtime·atomicstoreuintptr(&g->m->thread, thandle);
-}
-
-// Called from dropm to undo the effect of an minit.
-void
-runtime·unminit(void)
-{
-       runtime·stdcall1(runtime·CloseHandle, g->m->thread);
-       g->m->thread = 0;
-}
-
-// Described in http://www.dcl.hpi.uni-potsdam.de/research/WRK/2007/08/getting-os-information-the-kuser_shared_data-structure/
-typedef struct KSYSTEM_TIME {
-       uint32  LowPart;
-       int32   High1Time;
-       int32   High2Time;
-} KSYSTEM_TIME;
-
-#pragma dataflag NOPTR
-const KSYSTEM_TIME* INTERRUPT_TIME     = (KSYSTEM_TIME*)0x7ffe0008;
-#pragma dataflag NOPTR
-const KSYSTEM_TIME* SYSTEM_TIME                = (KSYSTEM_TIME*)0x7ffe0014;
-
-static void badsystime(void);
-
-#pragma textflag NOSPLIT
-int64
-runtime·systime(KSYSTEM_TIME *timeaddr)
-{
-       KSYSTEM_TIME t;
-       int32 i;
-       void (*fn)(void);
-
-       for(i = 1; i < 10000; i++) {
-               // these fields must be read in that order (see URL above)
-               t.High1Time = timeaddr->High1Time;
-               t.LowPart = timeaddr->LowPart;
-               t.High2Time = timeaddr->High2Time;
-               if(t.High1Time == t.High2Time)
-                       return (int64)t.High1Time<<32 | t.LowPart;
-               if((i%100) == 0)
-                       runtime·osyield();
-       }
-       fn = badsystime;
-       runtime·onM(&fn);
-       return 0;
-}
-
-#pragma textflag NOSPLIT
-int64
-runtime·unixnano(void)
-{
-       return (runtime·systime(SYSTEM_TIME) - 116444736000000000LL) * 100LL;
-}
-
-static void
-badsystime(void)
-{
-       runtime·throw("interrupt/system time is changing too fast");
-}
-
-#pragma textflag NOSPLIT
-int64
-runtime·nanotime(void)
-{
-       return runtime·systime(INTERRUPT_TIME) * 100LL;
-}
-
-// Calling stdcall on os stack.
-#pragma textflag NOSPLIT
-static void*
-stdcall(void *fn)
-{
-       g->m->libcall.fn = (uintptr)fn;
-       if(g->m->profilehz != 0) {
-               // leave pc/sp for cpu profiler
-               g->m->libcallg = g;
-               g->m->libcallpc = (uintptr)runtime·getcallerpc(&fn);
-               // sp must be the last, because once async cpu profiler finds
-               // all three values to be non-zero, it will use them
-               g->m->libcallsp = (uintptr)runtime·getcallersp(&fn);
-       }
-       runtime·asmcgocall(runtime·asmstdcall, &g->m->libcall);
-       g->m->libcallsp = 0;
-       return (void*)g->m->libcall.r1;
-}
-
-#pragma textflag NOSPLIT
-void*
-runtime·stdcall0(void *fn)
-{
-       g->m->libcall.n = 0;
-       g->m->libcall.args = (uintptr)&fn;  // it's unused but must be non-nil, otherwise crashes
-       return stdcall(fn);
-}
-
-#pragma textflag NOSPLIT
-void*
-runtime·stdcall1(void *fn, uintptr a0)
-{
-       USED(a0);
-       g->m->libcall.n = 1;
-       g->m->libcall.args = (uintptr)&a0;
-       return stdcall(fn);
-}
-
-#pragma textflag NOSPLIT
-void*
-runtime·stdcall2(void *fn, uintptr a0, uintptr a1)
-{
-       USED(a0, a1);
-       g->m->libcall.n = 2;
-       g->m->libcall.args = (uintptr)&a0;
-       return stdcall(fn);
-}
-
-#pragma textflag NOSPLIT
-void*
-runtime·stdcall3(void *fn, uintptr a0, uintptr a1, uintptr a2)
-{
-       USED(a0, a1, a2);
-       g->m->libcall.n = 3;
-       g->m->libcall.args = (uintptr)&a0;
-       return stdcall(fn);
-}
-
-#pragma textflag NOSPLIT
-void*
-runtime·stdcall4(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3)
-{
-       USED(a0, a1, a2, a3);
-       g->m->libcall.n = 4;
-       g->m->libcall.args = (uintptr)&a0;
-       return stdcall(fn);
-}
-
-#pragma textflag NOSPLIT
-void*
-runtime·stdcall5(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3, uintptr a4)
-{
-       USED(a0, a1, a2, a3, a4);
-       g->m->libcall.n = 5;
-       g->m->libcall.args = (uintptr)&a0;
-       return stdcall(fn);
-}
-
-#pragma textflag NOSPLIT
-void*
-runtime·stdcall6(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3, uintptr a4, uintptr a5)
-{
-       USED(a0, a1, a2, a3, a4, a5);
-       g->m->libcall.n = 6;
-       g->m->libcall.args = (uintptr)&a0;
-       return stdcall(fn);
-}
-
-#pragma textflag NOSPLIT
-void*
-runtime·stdcall7(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3, uintptr a4, uintptr a5, uintptr a6)
-{
-       USED(a0, a1, a2, a3, a4, a5, a6);
-       g->m->libcall.n = 7;
-       g->m->libcall.args = (uintptr)&a0;
-       return stdcall(fn);
-}
-
-extern void runtime·usleep1(uint32);
-
-#pragma textflag NOSPLIT
-void
-runtime·osyield(void)
-{
-       runtime·usleep1(1);
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·usleep(uint32 us)
-{
-       // Have 1us units; want 100ns units.
-       runtime·usleep1(10*us);
-}
-
-uint32
-runtime·issigpanic(uint32 code)
-{
-       switch(code) {
-       case EXCEPTION_ACCESS_VIOLATION:
-       case EXCEPTION_INT_DIVIDE_BY_ZERO:
-       case EXCEPTION_INT_OVERFLOW:
-       case EXCEPTION_FLT_DENORMAL_OPERAND:
-       case EXCEPTION_FLT_DIVIDE_BY_ZERO:
-       case EXCEPTION_FLT_INEXACT_RESULT:
-       case EXCEPTION_FLT_OVERFLOW:
-       case EXCEPTION_FLT_UNDERFLOW:
-       case EXCEPTION_BREAKPOINT:
-               return 1;
-       }
-       return 0;
-}
-
-void
-runtime·initsig(void)
-{
-       // following line keeps these functions alive at link stage
-       // if there's a better way please write it here
-       void *e = runtime·exceptiontramp;
-       void *f = runtime·firstcontinuetramp;
-       void *l = runtime·lastcontinuetramp;
-       USED(e);
-       USED(f);
-       USED(l);
-}
-
-uint32
-runtime·ctrlhandler1(uint32 type)
-{
-       int32 s;
-
-       switch(type) {
-       case CTRL_C_EVENT:
-       case CTRL_BREAK_EVENT:
-               s = SIGINT;
-               break;
-       default:
-               return 0;
-       }
-
-       if(runtime·sigsend(s))
-               return 1;
-       runtime·exit(2);       // SIGINT, SIGTERM, etc
-       return 0;
-}
-
-extern void runtime·dosigprof(Context *r, G *gp, M *mp);
-extern void runtime·profileloop(void);
-#pragma dataflag NOPTR
-static void *profiletimer;
-
-static void
-profilem(M *mp)
-{
-       extern M runtime·m0;
-       extern uint32 runtime·tls0[];
-       byte rbuf[sizeof(Context)+15];
-       Context *r;
-       void *tls;
-       G *gp;
-
-       tls = mp->tls;
-       if(mp == &runtime·m0)
-               tls = runtime·tls0;
-       gp = *(G**)tls;
-
-       // align Context to 16 bytes
-       r = (Context*)((uintptr)(&rbuf[15]) & ~15);
-       r->ContextFlags = CONTEXT_CONTROL;
-       runtime·stdcall2(runtime·GetThreadContext, (uintptr)mp->thread, (uintptr)r);
-       runtime·dosigprof(r, gp, mp);
-}
-
-void
-runtime·profileloop1(void)
-{
-       M *mp, *allm;
-       uintptr thread;
-
-       runtime·stdcall2(runtime·SetThreadPriority, -2, THREAD_PRIORITY_HIGHEST);
-
-       for(;;) {
-               runtime·stdcall2(runtime·WaitForSingleObject, (uintptr)profiletimer, -1);
-               allm = runtime·atomicloadp(&runtime·allm);
-               for(mp = allm; mp != nil; mp = mp->alllink) {
-                       thread = runtime·atomicloaduintptr(&mp->thread);
-                       // Do not profile threads blocked on Notes,
-                       // this includes idle worker threads,
-                       // idle timer thread, idle heap scavenger, etc.
-                       if(thread == 0 || mp->profilehz == 0 || mp->blocked)
-                               continue;
-                       runtime·stdcall1(runtime·SuspendThread, (uintptr)thread);
-                       if(mp->profilehz != 0 && !mp->blocked)
-                               profilem(mp);
-                       runtime·stdcall1(runtime·ResumeThread, (uintptr)thread);
-               }
-       }
-}
-
-void
-runtime·resetcpuprofiler(int32 hz)
-{
-       static Mutex lock;
-       void *timer, *thread;
-       int32 ms;
-       int64 due;
-
-       runtime·lock(&lock);
-       if(profiletimer == nil) {
-               timer = runtime·stdcall3(runtime·CreateWaitableTimer, (uintptr)nil, (uintptr)nil, (uintptr)nil);
-               runtime·atomicstorep(&profiletimer, timer);
-               thread = runtime·stdcall6(runtime·CreateThread,
-                       (uintptr)nil, (uintptr)nil, (uintptr)runtime·profileloop, (uintptr)nil, (uintptr)nil, (uintptr)nil);
-               runtime·stdcall2(runtime·SetThreadPriority, (uintptr)thread, THREAD_PRIORITY_HIGHEST);
-               runtime·stdcall1(runtime·CloseHandle, (uintptr)thread);
-       }
-       runtime·unlock(&lock);
-
-       ms = 0;
-       due = 1LL<<63;
-       if(hz > 0) {
-               ms = 1000 / hz;
-               if(ms == 0)
-                       ms = 1;
-               due = ms * -10000;
-       }
-       runtime·stdcall6(runtime·SetWaitableTimer,
-               (uintptr)profiletimer, (uintptr)&due, ms, (uintptr)nil, (uintptr)nil, (uintptr)nil);
-       runtime·atomicstore((uint32*)&g->m->profilehz, hz);
-}
-
-uintptr
-runtime·memlimit(void)
-{
-       return 0;
-}
-
-#pragma dataflag NOPTR
-int8 runtime·badsignalmsg[] = "runtime: signal received on thread not created by Go.\n";
-int32 runtime·badsignallen = sizeof runtime·badsignalmsg - 1;
-
-void
-runtime·crash(void)
-{
-       // TODO: This routine should do whatever is needed
-       // to make the Windows program abort/crash as it
-       // would if Go was not intercepting signals.
-       // On Unix the routine would remove the custom signal
-       // handler and then raise a signal (like SIGABRT).
-       // Something like that should happen here.
-       // It's okay to leave this empty for now: if crash returns
-       // the ordinary exit-after-panic happens.
-}
index fcd8f44cc416525f33398291be64766f333bccd3..097b5d6290f2f4a5361b1dc55c5ffb48f541c2bd 100644 (file)
@@ -4,24 +4,8 @@
 
 package runtime
 
-import "unsafe"
-
 type stdFunction *byte
 
-func stdcall0(fn stdFunction) uintptr
-func stdcall1(fn stdFunction, a0 uintptr) uintptr
-func stdcall2(fn stdFunction, a0, a1 uintptr) uintptr
-func stdcall3(fn stdFunction, a0, a1, a2 uintptr) uintptr
-func stdcall4(fn stdFunction, a0, a1, a2, a3 uintptr) uintptr
-func stdcall5(fn stdFunction, a0, a1, a2, a3, a4 uintptr) uintptr
-func stdcall6(fn stdFunction, a0, a1, a2, a3, a4, a5 uintptr) uintptr
-func stdcall7(fn stdFunction, a0, a1, a2, a3, a4, a5, a6 uintptr) uintptr
-
-func asmstdcall(fn unsafe.Pointer)
-func getlasterror() uint32
-func setlasterror(err uint32)
-func usleep1(usec uint32)
-
 func os_sigpipe() {
        gothrow("too many writes on closed pipe")
 }
diff --git a/src/runtime/os_windows.h b/src/runtime/os_windows.h
deleted file mode 100644 (file)
index d5d168d..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-// 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.
-
-extern void *runtime·LoadLibrary;
-extern void *runtime·GetProcAddress;
-extern void *runtime·GetQueuedCompletionStatusEx;
-
-// Call a Windows function with stdcall conventions,
-// and switch to os stack during the call.
-void runtime·asmstdcall(void *c);
-void *runtime·stdcall0(void *fn);
-void *runtime·stdcall1(void *fn, uintptr a0);
-void *runtime·stdcall2(void *fn, uintptr a0, uintptr a1);
-void *runtime·stdcall3(void *fn, uintptr a0, uintptr a1, uintptr a2);
-void *runtime·stdcall4(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3);
-void *runtime·stdcall5(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3, uintptr a4);
-void *runtime·stdcall6(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3, uintptr a4, uintptr a5);
-void *runtime·stdcall7(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3, uintptr a4, uintptr a5, uintptr a6);
-
-uint32 runtime·getlasterror(void);
-void runtime·setlasterror(uint32 err);
-
-// Function to be called by windows CreateThread
-// to start new os thread.
-uint32 runtime·tstart_stdcall(M *newm);
-
-uint32 runtime·issigpanic(uint32);
-void runtime·sigpanic(void);
-uint32 runtime·ctrlhandler(uint32 type);
-
-// Windows dll function to go callback entry.
-byte *runtime·compilecallback(Eface fn, bool cleanstack);
-void *runtime·callbackasm(void);
-
-void runtime·install_exception_handler(void);
-void runtime·remove_exception_handler(void);
-
-// TODO(brainman): should not need those
-enum {
-       NSIG = 65,
-};
diff --git a/src/runtime/os_windows_386.c b/src/runtime/os_windows_386.c
deleted file mode 100644 (file)
index 9962f0d..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-// 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 "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-
-void
-runtime·dumpregs(Context *r)
-{
-       runtime·printf("eax     %x\n", r->Eax);
-       runtime·printf("ebx     %x\n", r->Ebx);
-       runtime·printf("ecx     %x\n", r->Ecx);
-       runtime·printf("edx     %x\n", r->Edx);
-       runtime·printf("edi     %x\n", r->Edi);
-       runtime·printf("esi     %x\n", r->Esi);
-       runtime·printf("ebp     %x\n", r->Ebp);
-       runtime·printf("esp     %x\n", r->Esp);
-       runtime·printf("eip     %x\n", r->Eip);
-       runtime·printf("eflags  %x\n", r->EFlags);
-       runtime·printf("cs      %x\n", r->SegCs);
-       runtime·printf("fs      %x\n", r->SegFs);
-       runtime·printf("gs      %x\n", r->SegGs);
-}
-
-bool
-runtime·isgoexception(ExceptionRecord *info, Context *r)
-{
-       extern byte runtime·text[], runtime·etext[];
-
-       // Only handle exception if executing instructions in Go binary
-       // (not Windows library code). 
-       if(r->Eip < (uint32)runtime·text || (uint32)runtime·etext < r->Eip)
-               return false;
-
-       if(!runtime·issigpanic(info->ExceptionCode))
-               return false;
-
-       return true;
-}
-
-// Called by sigtramp from Windows VEH handler.
-// Return value signals whether the exception has been handled (EXCEPTION_CONTINUE_EXECUTION)
-// or should be made available to other handlers in the chain (EXCEPTION_CONTINUE_SEARCH).
-uint32
-runtime·exceptionhandler(ExceptionRecord *info, Context *r, G *gp)
-{
-       uintptr *sp;
-
-       if(!runtime·isgoexception(info, r))
-               return EXCEPTION_CONTINUE_SEARCH;
-
-       // Make it look like a call to the signal func.
-       // Have to pass arguments out of band since
-       // augmenting the stack frame would break
-       // the unwinding code.
-       gp->sig = info->ExceptionCode;
-       gp->sigcode0 = info->ExceptionInformation[0];
-       gp->sigcode1 = info->ExceptionInformation[1];
-       gp->sigpc = r->Eip;
-
-       // Only push runtime·sigpanic if r->eip != 0.
-       // If r->eip == 0, probably panicked because of a
-       // call to a nil func.  Not pushing that onto sp will
-       // make the trace look like a call to runtime·sigpanic instead.
-       // (Otherwise the trace will end at runtime·sigpanic and we
-       // won't get to see who faulted.)
-       if(r->Eip != 0) {
-               sp = (uintptr*)r->Esp;
-               *--sp = r->Eip;
-               r->Esp = (uintptr)sp;
-       }
-       r->Eip = (uintptr)runtime·sigpanic;
-       return EXCEPTION_CONTINUE_EXECUTION;
-}
-
-// lastcontinuehandler is reached, because runtime cannot handle
-// current exception. lastcontinuehandler will print crash info and exit.
-uint32
-runtime·lastcontinuehandler(ExceptionRecord *info, Context *r, G *gp)
-{
-       bool crash;
-
-       if(runtime·panicking)  // traceback already printed
-               runtime·exit(2);
-       runtime·panicking = 1;
-
-       runtime·printf("Exception %x %p %p %p\n", info->ExceptionCode,
-               (uintptr)info->ExceptionInformation[0], (uintptr)info->ExceptionInformation[1], (uintptr)r->Eip);
-
-       runtime·printf("PC=%x\n", r->Eip);
-       if(g->m->lockedg != nil && g->m->ncgo > 0 && gp == g->m->g0) {
-               runtime·printf("signal arrived during cgo execution\n");
-               gp = g->m->lockedg;
-       }
-       runtime·printf("\n");
-
-       if(runtime·gotraceback(&crash)){
-               runtime·tracebacktrap(r->Eip, r->Esp, 0, gp);
-               runtime·tracebackothers(gp);
-               runtime·dumpregs(r);
-       }
-       
-       if(crash)
-               runtime·crash();
-
-       runtime·exit(2);
-       return 0; // not reached
-}
-
-void
-runtime·sigenable(uint32 sig)
-{
-       USED(sig);
-}
-
-void
-runtime·sigdisable(uint32 sig)
-{
-       USED(sig);
-}
-
-void
-runtime·dosigprof(Context *r, G *gp, M *mp)
-{
-       runtime·sigprof((uint8*)r->Eip, (uint8*)r->Esp, nil, gp, mp);
-}
diff --git a/src/runtime/os_windows_amd64.c b/src/runtime/os_windows_amd64.c
deleted file mode 100644 (file)
index e4617e4..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-// 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 "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-
-void
-runtime·dumpregs(Context *r)
-{
-       runtime·printf("rax     %X\n", r->Rax);
-       runtime·printf("rbx     %X\n", r->Rbx);
-       runtime·printf("rcx     %X\n", r->Rcx);
-       runtime·printf("rdx     %X\n", r->Rdx);
-       runtime·printf("rdi     %X\n", r->Rdi);
-       runtime·printf("rsi     %X\n", r->Rsi);
-       runtime·printf("rbp     %X\n", r->Rbp);
-       runtime·printf("rsp     %X\n", r->Rsp);
-       runtime·printf("r8      %X\n", r->R8 );
-       runtime·printf("r9      %X\n", r->R9 );
-       runtime·printf("r10     %X\n", r->R10);
-       runtime·printf("r11     %X\n", r->R11);
-       runtime·printf("r12     %X\n", r->R12);
-       runtime·printf("r13     %X\n", r->R13);
-       runtime·printf("r14     %X\n", r->R14);
-       runtime·printf("r15     %X\n", r->R15);
-       runtime·printf("rip     %X\n", r->Rip);
-       runtime·printf("rflags  %X\n", r->EFlags);
-       runtime·printf("cs      %X\n", (uint64)r->SegCs);
-       runtime·printf("fs      %X\n", (uint64)r->SegFs);
-       runtime·printf("gs      %X\n", (uint64)r->SegGs);
-}
-
-bool
-runtime·isgoexception(ExceptionRecord *info, Context *r)
-{
-       extern byte runtime·text[], runtime·etext[];
-
-       // Only handle exception if executing instructions in Go binary
-       // (not Windows library code). 
-       if(r->Rip < (uint64)runtime·text || (uint64)runtime·etext < r->Rip)
-               return false;
-
-       if(!runtime·issigpanic(info->ExceptionCode))
-               return false;
-
-       return true;
-}
-
-// Called by sigtramp from Windows VEH handler.
-// Return value signals whether the exception has been handled (EXCEPTION_CONTINUE_EXECUTION)
-// or should be made available to other handlers in the chain (EXCEPTION_CONTINUE_SEARCH).
-uint32
-runtime·exceptionhandler(ExceptionRecord *info, Context *r, G *gp)
-{
-       uintptr *sp;
-
-       if(!runtime·isgoexception(info, r))
-               return EXCEPTION_CONTINUE_SEARCH;
-
-       // Make it look like a call to the signal func.
-       // Have to pass arguments out of band since
-       // augmenting the stack frame would break
-       // the unwinding code.
-       gp->sig = info->ExceptionCode;
-       gp->sigcode0 = info->ExceptionInformation[0];
-       gp->sigcode1 = info->ExceptionInformation[1];
-       gp->sigpc = r->Rip;
-
-       // Only push runtime·sigpanic if r->rip != 0.
-       // If r->rip == 0, probably panicked because of a
-       // call to a nil func.  Not pushing that onto sp will
-       // make the trace look like a call to runtime·sigpanic instead.
-       // (Otherwise the trace will end at runtime·sigpanic and we
-       // won't get to see who faulted.)
-       if(r->Rip != 0) {
-               sp = (uintptr*)r->Rsp;
-               *--sp = r->Rip;
-               r->Rsp = (uintptr)sp;
-       }
-       r->Rip = (uintptr)runtime·sigpanic;
-       return EXCEPTION_CONTINUE_EXECUTION;
-}
-
-// It seems Windows searches ContinueHandler's list even
-// if ExceptionHandler returns EXCEPTION_CONTINUE_EXECUTION.
-// firstcontinuehandler will stop that search,
-// if exceptionhandler did the same earlier.
-uint32
-runtime·firstcontinuehandler(ExceptionRecord *info, Context *r, G *gp)
-{
-       USED(gp);
-       if(!runtime·isgoexception(info, r))
-               return EXCEPTION_CONTINUE_SEARCH;
-       return EXCEPTION_CONTINUE_EXECUTION;
-}
-
-// lastcontinuehandler is reached, because runtime cannot handle
-// current exception. lastcontinuehandler will print crash info and exit.
-uint32
-runtime·lastcontinuehandler(ExceptionRecord *info, Context *r, G *gp)
-{
-       bool crash;
-
-       if(runtime·panicking)  // traceback already printed
-               runtime·exit(2);
-       runtime·panicking = 1;
-
-       runtime·printf("Exception %x %p %p %p\n", info->ExceptionCode,
-               info->ExceptionInformation[0], info->ExceptionInformation[1], r->Rip);
-
-
-       runtime·printf("PC=%X\n", r->Rip);
-       if(g->m->lockedg != nil && g->m->ncgo > 0 && gp == g->m->g0) {
-               runtime·printf("signal arrived during cgo execution\n");
-               gp = g->m->lockedg;
-       }
-       runtime·printf("\n");
-
-       if(runtime·gotraceback(&crash)){
-               runtime·tracebacktrap(r->Rip, r->Rsp, 0, gp);
-               runtime·tracebackothers(gp);
-               runtime·dumpregs(r);
-       }
-       
-       if(crash)
-               runtime·crash();
-
-       runtime·exit(2);
-       return 0; // not reached
-}
-
-void
-runtime·sigenable(uint32 sig)
-{
-       USED(sig);
-}
-
-void
-runtime·sigdisable(uint32 sig)
-{
-       USED(sig);
-}
-
-void
-runtime·dosigprof(Context *r, G *gp, M *mp)
-{
-       runtime·sigprof((uint8*)r->Rip, (uint8*)r->Rsp, nil, gp, mp);
-}
index 8929467025e5f7b2276a473374a33c9bcdf58129..95e780b1d954de26a12c7df8ad0d9232caa613bd 100644 (file)
@@ -162,7 +162,7 @@ func init() {
 
 // Allocate a Defer, usually using per-P pool.
 // Each defer must be released with freedefer.
-// Note: runs on M stack
+// Note: runs on g0 stack
 func newdefer(siz int32) *_defer {
        var d *_defer
        sc := deferclass(uintptr(siz))
index 12e2e71e999f4fd51979d0ffe6f0d661da8bcff6..64f6a352091f9b8b29e9a30574124fd33148b4cd 100644 (file)
@@ -63,11 +63,13 @@ func main() {
                if _cgo_free == nil {
                        gothrow("_cgo_free missing")
                }
-               if _cgo_setenv == nil {
-                       gothrow("_cgo_setenv missing")
-               }
-               if _cgo_unsetenv == nil {
-                       gothrow("_cgo_unsetenv missing")
+               if GOOS != "windows" {
+                       if _cgo_setenv == nil {
+                               gothrow("_cgo_setenv missing")
+                       }
+                       if _cgo_unsetenv == nil {
+                               gothrow("_cgo_unsetenv missing")
+                       }
                }
        }
 
@@ -165,6 +167,7 @@ func acquireSudog() *sudog {
                        gothrow("acquireSudog: found s.elem != nil in cache")
                }
                c.sudogcache = s.next
+               s.next = nil
                return s
        }
 
@@ -193,6 +196,15 @@ func releaseSudog(s *sudog) {
        if s.selectdone != nil {
                gothrow("runtime: sudog with non-nil selectdone")
        }
+       if s.next != nil {
+               gothrow("runtime: sudog with non-nil next")
+       }
+       if s.prev != nil {
+               gothrow("runtime: sudog with non-nil prev")
+       }
+       if s.waitlink != nil {
+               gothrow("runtime: sudog with non-nil waitlink")
+       }
        gp := getg()
        if gp.param != nil {
                gothrow("runtime: releaseSudog with non-nil gp.param")
diff --git a/src/runtime/race/race_unix_test.go b/src/runtime/race/race_unix_test.go
new file mode 100644 (file)
index 0000000..84f0ace
--- /dev/null
@@ -0,0 +1,30 @@
+// 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.
+
+// +build race
+// +build darwin freebsd linux
+
+package race_test
+
+import (
+       "sync/atomic"
+       "syscall"
+       "testing"
+       "unsafe"
+)
+
+// Test that race detector does not crash when accessing non-Go allocated memory (issue 9136).
+func TestNonGoMemory(t *testing.T) {
+       data, err := syscall.Mmap(-1, 0, 4096, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_ANON|syscall.MAP_PRIVATE)
+       if err != nil {
+               t.Fatalf("failed to mmap memory: %v", err)
+       }
+       p := (*uint32)(unsafe.Pointer(&data[0]))
+       atomic.AddUint32(p, 1)
+       (*p)++
+       if *p != 2 {
+               t.Fatalf("data[0] = %v, expect 2", *p)
+       }
+       syscall.Munmap(data)
+}
index 4c580429c8690dd478783f8a837617b5259cdf09..2ec2bee65b6e9fc9d8042765b67c92e09d93383a 100644 (file)
@@ -81,6 +81,10 @@ var __tsan_go_ignore_sync_end byte
 //go:cgo_import_static __tsan_go_atomic32_compare_exchange
 //go:cgo_import_static __tsan_go_atomic64_compare_exchange
 
+// start/end of global data (data+bss).
+var racedatastart uintptr
+var racedataend uintptr
+
 // start/end of heap for race_amd64.s
 var racearenastart uintptr
 var racearenaend uintptr
@@ -99,7 +103,7 @@ func racecall(*byte, uintptr, uintptr, uintptr, uintptr)
 //go:nosplit
 func isvalidaddr(addr unsafe.Pointer) bool {
        return racearenastart <= uintptr(addr) && uintptr(addr) < racearenaend ||
-               uintptr(unsafe.Pointer(&noptrdata)) <= uintptr(addr) && uintptr(addr) < uintptr(unsafe.Pointer(&enoptrbss))
+               racedatastart <= uintptr(addr) && uintptr(addr) < racedataend
 }
 
 //go:nosplit
@@ -113,9 +117,36 @@ func raceinit() uintptr {
        racecall(&__tsan_init, uintptr(unsafe.Pointer(&racectx)), funcPC(racesymbolizethunk), 0, 0)
 
        // Round data segment to page boundaries, because it's used in mmap().
-       start := uintptr(unsafe.Pointer(&noptrdata)) &^ (_PageSize - 1)
-       size := round(uintptr(unsafe.Pointer(&enoptrbss))-start, _PageSize)
+       start := ^uintptr(0)
+       end := uintptr(0)
+       if start > uintptr(unsafe.Pointer(&noptrdata)) {
+               start = uintptr(unsafe.Pointer(&noptrdata))
+       }
+       if start > uintptr(unsafe.Pointer(&data)) {
+               start = uintptr(unsafe.Pointer(&data))
+       }
+       if start > uintptr(unsafe.Pointer(&noptrbss)) {
+               start = uintptr(unsafe.Pointer(&noptrbss))
+       }
+       if start > uintptr(unsafe.Pointer(&bss)) {
+               start = uintptr(unsafe.Pointer(&bss))
+       }
+       if end < uintptr(unsafe.Pointer(&enoptrdata)) {
+               end = uintptr(unsafe.Pointer(&enoptrdata))
+       }
+       if end < uintptr(unsafe.Pointer(&edata)) {
+               end = uintptr(unsafe.Pointer(&edata))
+       }
+       if end < uintptr(unsafe.Pointer(&enoptrbss)) {
+               end = uintptr(unsafe.Pointer(&enoptrbss))
+       }
+       if end < uintptr(unsafe.Pointer(&ebss)) {
+               end = uintptr(unsafe.Pointer(&ebss))
+       }
+       size := round(end-start, _PageSize)
        racecall(&__tsan_map_shadow, start, size, 0, 0)
+       racedatastart = start
+       racedataend = start + size
 
        return racectx
 }
index a7f44870a8671e908efe3d6497ad7b5639a5ad86..d54d9798f032ccc6c2f8043e3ab9c6d87f008a07 100644 (file)
@@ -139,17 +139,15 @@ TEXT      racecalladdr<>(SB), NOSPLIT, $0-0
        get_tls(R12)
        MOVQ    g(R12), R14
        MOVQ    g_racectx(R14), RARG0   // goroutine context
-       // Check that addr is within [arenastart, arenaend) or within [noptrdata, enoptrbss).
+       // Check that addr is within [arenastart, arenaend) or within [racedatastart, racedataend).
        CMPQ    RARG1, runtime·racearenastart(SB)
        JB      data
        CMPQ    RARG1, runtime·racearenaend(SB)
        JB      call
 data:
-       MOVQ    $runtime·noptrdata(SB), R13
-       CMPQ    RARG1, R13
+       CMPQ    RARG1, runtime·racedatastart(SB)
        JB      ret
-       MOVQ    $runtime·enoptrbss(SB), R13
-       CMPQ    RARG1, R13
+       CMPQ    RARG1, runtime·racedataend(SB)
        JAE     ret
 call:
        MOVQ    AX, AX          // w/o this 6a miscompiles this function
@@ -167,6 +165,7 @@ TEXT        runtime·racefuncenter(SB), NOSPLIT, $0-8
        MOVQ    callpc+0(FP), RARG1
        // void __tsan_func_enter(ThreadState *thr, void *pc);
        MOVQ    $__tsan_func_enter(SB), AX
+       // racecall<> preserves R15
        CALL    racecall<>(SB)
        MOVQ    R15, DX // restore function entry context
        RET
@@ -307,13 +306,45 @@ TEXT      sync∕atomic·CompareAndSwapPointer(SB), NOSPLIT, $0-0
 TEXT   racecallatomic<>(SB), NOSPLIT, $0-0
        // Trigger SIGSEGV early.
        MOVQ    16(SP), R12
-       MOVL    (R12), R12
+       MOVL    (R12), R13
+       // Check that addr is within [arenastart, arenaend) or within [racedatastart, racedataend).
+       CMPQ    R12, runtime·racearenastart(SB)
+       JB      racecallatomic_data
+       CMPQ    R12, runtime·racearenaend(SB)
+       JB      racecallatomic_ok
+racecallatomic_data:
+       CMPQ    R12, runtime·racedatastart(SB)
+       JB      racecallatomic_ignore
+       CMPQ    R12, runtime·racedataend(SB)
+       JAE     racecallatomic_ignore
+racecallatomic_ok:
+       // Addr is within the good range, call the atomic function.
        get_tls(R12)
        MOVQ    g(R12), R14
        MOVQ    g_racectx(R14), RARG0   // goroutine context
        MOVQ    8(SP), RARG1    // caller pc
        MOVQ    (SP), RARG2     // pc
        LEAQ    16(SP), RARG3   // arguments
+       JMP     racecall<>(SB)  // does not return
+racecallatomic_ignore:
+       // Addr is outside the good range.
+       // Call __tsan_go_ignore_sync_begin to ignore synchronization during the atomic op.
+       // An attempt to synchronize on the address would cause crash.
+       MOVQ    AX, R15 // remember the original function
+       MOVQ    $__tsan_go_ignore_sync_begin(SB), AX
+       MOVQ    g(R12), R14
+       MOVQ    g_racectx(R14), RARG0   // goroutine context
+       CALL    racecall<>(SB)
+       MOVQ    R15, AX // restore the original function
+       // Call the atomic function.
+       MOVQ    g_racectx(R14), RARG0   // goroutine context
+       MOVQ    8(SP), RARG1    // caller pc
+       MOVQ    (SP), RARG2     // pc
+       LEAQ    16(SP), RARG3   // arguments
+       CALL    racecall<>(SB)
+       // Call __tsan_go_ignore_sync_end.
+       MOVQ    $__tsan_go_ignore_sync_end(SB), AX
+       MOVQ    g_racectx(R14), RARG0   // goroutine context
        JMP     racecall<>(SB)
 
 // void runtime·racecall(void(*f)(...), ...)
index 7625a2dd81f9d1ee28750ebc343feef75ac087a5..d18178d0939475eab1d66b46ea3282f82966af0c 100644 (file)
@@ -45,7 +45,13 @@ const (
        _Pdead
 )
 
-// XXX inserting below here
+// The next line makes 'go generate' write the zgen_*.go files with
+// per-OS and per-arch information, including constants
+// named goos_$GOOS and goarch_$GOARCH for every
+// known GOOS and GOARCH. The constant is 1 on the
+// current system, 0 otherwise; multiplying by them is
+// useful for defining GOOS- or GOARCH-specific constants.
+//go:generate go run gengoos.go
 
 type mutex struct {
        // Futex-based impl treats it as uint32 key,
@@ -397,14 +403,6 @@ type itab struct {
        fun    [0]uintptr
 }
 
-const (
-       // TODO: Generate in cmd/dist.
-       _NaCl    = 0
-       _Windows = 0
-       _Solaris = 0
-       _Plan9   = 0
-)
-
 // Lock-free stack node.
 // // Also known to export_test.go.
 type lfnode struct {
index e918b734a8e80bd7ca2445a61785185e03416f8c..5e5047bc10a58c915fe86b8e34f13cfe94454207 100644 (file)
@@ -399,6 +399,7 @@ loop:
                        }
                }
                sgnext = sglist.waitlink
+               sglist.waitlink = nil
                releaseSudog(sglist)
                sglist = sgnext
        }
@@ -636,6 +637,7 @@ func (q *waitq) dequeueSudoG(s *sudog) {
                        if q.last == sgp {
                                q.last = prevsgp
                        }
+                       s.next = nil
                        return
                }
                l = &sgp.next
index d2a028c01b1fe9f5e5332dd915fa11a201db7f11..26dbd30ea3f9375f1d2ca843014556f267d857a2 100644 (file)
@@ -201,6 +201,7 @@ func syncsemacquire(s *syncSema) {
                }
                unlock(&s.lock)
                if wake != nil {
+                       wake.next = nil
                        goready(wake.g)
                }
        } else {
@@ -242,6 +243,7 @@ func syncsemrelease(s *syncSema, n uint32) {
                if wake.releasetime != 0 {
                        wake.releasetime = cputicks()
                }
+               wake.next = nil
                goready(wake.g)
                n--
        }
diff --git a/src/runtime/signal_android_386.h b/src/runtime/signal_android_386.h
deleted file mode 100644 (file)
index 2a1bb4b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include "signal_linux_386.h"
diff --git a/src/runtime/signal_android_arm.h b/src/runtime/signal_android_arm.h
deleted file mode 100644 (file)
index 8a05e21..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include "signal_linux_arm.h"
index 41eae80ea2bacf5c8b17229a7426e3dfdb939921..085f66e8984cfe12a4d844bcde734c39c9f9898f 100644 (file)
@@ -26,7 +26,7 @@ func (c *sigctxt) cs() uint32        { return uint32(c.regs().cs) }
 func (c *sigctxt) fs() uint32        { return uint32(c.regs().fs) }
 func (c *sigctxt) gs() uint32        { return uint32(c.regs().gs) }
 func (c *sigctxt) sigcode() uint32   { return uint32(c.info.si_code) }
-func (c *sigctxt) sigaddr() uint32   { return uint32(*(*uintptr)(add(unsafe.Pointer(c.info), 2*ptrSize))) }
+func (c *sigctxt) sigaddr() uint32   { return c.info.si_addr }
 
 func (c *sigctxt) set_eip(x uint32)     { c.regs().eip = x }
 func (c *sigctxt) set_esp(x uint32)     { c.regs().esp = x }
index d94b191024a2672b59523f7fc1979b9606dc66ed..5e339b8a46fe1718c2c8d6d7a02a3e1dc89e50e2 100644 (file)
@@ -36,7 +36,7 @@ func (c *sigctxt) cs() uint64      { return uint64(c.regs().cs) }
 func (c *sigctxt) fs() uint64      { return uint64(c.regs().fs) }
 func (c *sigctxt) gs() uint64      { return uint64(c.regs().gs) }
 func (c *sigctxt) sigcode() uint64 { return uint64(c.info.si_code) }
-func (c *sigctxt) sigaddr() uint64 { return uint64(*(*uintptr)(add(unsafe.Pointer(c.info), 2*ptrSize))) }
+func (c *sigctxt) sigaddr() uint64 { return c.info.si_addr }
 
 func (c *sigctxt) set_rip(x uint64)     { c.regs().rip = x }
 func (c *sigctxt) set_rsp(x uint64)     { c.regs().rsp = x }
index 4a5670e740a11bc08918e5825fe223a5f9f3a4ad..bdb4314fa8dd27e0aea5ce73359416bd9ab73a0c 100644 (file)
@@ -35,7 +35,7 @@ func (c *sigctxt) error() uint32     { return c.regs().error_code }
 func (c *sigctxt) oldmask() uint32   { return c.regs().oldmask }
 
 func (c *sigctxt) sigcode() uint32 { return uint32(c.info.si_code) }
-func (c *sigctxt) sigaddr() uint32 { return uint32(*(*uintptr)(add(unsafe.Pointer(c.info), 2*ptrSize))) }
+func (c *sigctxt) sigaddr() uint32 { return c.info.si_addr }
 
 func (c *sigctxt) set_pc(x uint32)  { c.regs().pc = x }
 func (c *sigctxt) set_sp(x uint32)  { c.regs().sp = x }
diff --git a/src/runtime/signal_linux_power64.h b/src/runtime/signal_linux_power64.h
deleted file mode 100644 (file)
index 8406489..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-// 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.
-
-#define SIG_REGS(ctxt) (*((Sigcontext*)&((Ucontext*)(ctxt))->uc_mcontext)->regs)
-
-#define SIG_R0(info, ctxt) (SIG_REGS(ctxt).gpr[0])
-#define SIG_R1(info, ctxt) (SIG_REGS(ctxt).gpr[1])
-#define SIG_R2(info, ctxt) (SIG_REGS(ctxt).gpr[2])
-#define SIG_R3(info, ctxt) (SIG_REGS(ctxt).gpr[3])
-#define SIG_R4(info, ctxt) (SIG_REGS(ctxt).gpr[4])
-#define SIG_R5(info, ctxt) (SIG_REGS(ctxt).gpr[5])
-#define SIG_R6(info, ctxt) (SIG_REGS(ctxt).gpr[6])
-#define SIG_R7(info, ctxt) (SIG_REGS(ctxt).gpr[7])
-#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).gpr[8])
-#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).gpr[9])
-#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).gpr[10])
-#define SIG_R11(info, ctxt) (SIG_REGS(ctxt).gpr[11])
-#define SIG_R12(info, ctxt) (SIG_REGS(ctxt).gpr[12])
-#define SIG_R13(info, ctxt) (SIG_REGS(ctxt).gpr[13])
-#define SIG_R14(info, ctxt) (SIG_REGS(ctxt).gpr[14])
-#define SIG_R15(info, ctxt) (SIG_REGS(ctxt).gpr[15])
-#define SIG_R16(info, ctxt) (SIG_REGS(ctxt).gpr[16])
-#define SIG_R17(info, ctxt) (SIG_REGS(ctxt).gpr[17])
-#define SIG_R18(info, ctxt) (SIG_REGS(ctxt).gpr[18])
-#define SIG_R19(info, ctxt) (SIG_REGS(ctxt).gpr[19])
-#define SIG_R20(info, ctxt) (SIG_REGS(ctxt).gpr[20])
-#define SIG_R21(info, ctxt) (SIG_REGS(ctxt).gpr[21])
-#define SIG_R22(info, ctxt) (SIG_REGS(ctxt).gpr[22])
-#define SIG_R23(info, ctxt) (SIG_REGS(ctxt).gpr[23])
-#define SIG_R24(info, ctxt) (SIG_REGS(ctxt).gpr[24])
-#define SIG_R25(info, ctxt) (SIG_REGS(ctxt).gpr[25])
-#define SIG_R26(info, ctxt) (SIG_REGS(ctxt).gpr[26])
-#define SIG_R27(info, ctxt) (SIG_REGS(ctxt).gpr[27])
-#define SIG_R28(info, ctxt) (SIG_REGS(ctxt).gpr[28])
-#define SIG_R29(info, ctxt) (SIG_REGS(ctxt).gpr[29])
-#define SIG_R30(info, ctxt) (SIG_REGS(ctxt).gpr[30])
-#define SIG_R31(info, ctxt) (SIG_REGS(ctxt).gpr[31])
-
-#define SIG_SP(info, ctxt) (SIG_REGS(ctxt).gpr[1])
-#define SIG_PC(info, ctxt) (SIG_REGS(ctxt).nip)
-#define SIG_TRAP(info, ctxt) (SIG_REGS(ctxt).trap)
-#define SIG_CTR(info, ctxt) (SIG_REGS(ctxt).ctr)
-#define SIG_LINK(info, ctxt) (SIG_REGS(ctxt).link)
-#define SIG_XER(info, ctxt) (SIG_REGS(ctxt).xer)
-#define SIG_CCR(info, ctxt) (SIG_REGS(ctxt).ccr)
-
-#define SIG_CODE0(info, ctxt) ((uintptr)(info)->si_code)
-#define SIG_FAULT(info, ctxt) (SIG_REGS(ctxt).dar)
diff --git a/src/runtime/signal_linux_power64le.h b/src/runtime/signal_linux_power64le.h
deleted file mode 100644 (file)
index 8406489..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-// 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.
-
-#define SIG_REGS(ctxt) (*((Sigcontext*)&((Ucontext*)(ctxt))->uc_mcontext)->regs)
-
-#define SIG_R0(info, ctxt) (SIG_REGS(ctxt).gpr[0])
-#define SIG_R1(info, ctxt) (SIG_REGS(ctxt).gpr[1])
-#define SIG_R2(info, ctxt) (SIG_REGS(ctxt).gpr[2])
-#define SIG_R3(info, ctxt) (SIG_REGS(ctxt).gpr[3])
-#define SIG_R4(info, ctxt) (SIG_REGS(ctxt).gpr[4])
-#define SIG_R5(info, ctxt) (SIG_REGS(ctxt).gpr[5])
-#define SIG_R6(info, ctxt) (SIG_REGS(ctxt).gpr[6])
-#define SIG_R7(info, ctxt) (SIG_REGS(ctxt).gpr[7])
-#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).gpr[8])
-#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).gpr[9])
-#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).gpr[10])
-#define SIG_R11(info, ctxt) (SIG_REGS(ctxt).gpr[11])
-#define SIG_R12(info, ctxt) (SIG_REGS(ctxt).gpr[12])
-#define SIG_R13(info, ctxt) (SIG_REGS(ctxt).gpr[13])
-#define SIG_R14(info, ctxt) (SIG_REGS(ctxt).gpr[14])
-#define SIG_R15(info, ctxt) (SIG_REGS(ctxt).gpr[15])
-#define SIG_R16(info, ctxt) (SIG_REGS(ctxt).gpr[16])
-#define SIG_R17(info, ctxt) (SIG_REGS(ctxt).gpr[17])
-#define SIG_R18(info, ctxt) (SIG_REGS(ctxt).gpr[18])
-#define SIG_R19(info, ctxt) (SIG_REGS(ctxt).gpr[19])
-#define SIG_R20(info, ctxt) (SIG_REGS(ctxt).gpr[20])
-#define SIG_R21(info, ctxt) (SIG_REGS(ctxt).gpr[21])
-#define SIG_R22(info, ctxt) (SIG_REGS(ctxt).gpr[22])
-#define SIG_R23(info, ctxt) (SIG_REGS(ctxt).gpr[23])
-#define SIG_R24(info, ctxt) (SIG_REGS(ctxt).gpr[24])
-#define SIG_R25(info, ctxt) (SIG_REGS(ctxt).gpr[25])
-#define SIG_R26(info, ctxt) (SIG_REGS(ctxt).gpr[26])
-#define SIG_R27(info, ctxt) (SIG_REGS(ctxt).gpr[27])
-#define SIG_R28(info, ctxt) (SIG_REGS(ctxt).gpr[28])
-#define SIG_R29(info, ctxt) (SIG_REGS(ctxt).gpr[29])
-#define SIG_R30(info, ctxt) (SIG_REGS(ctxt).gpr[30])
-#define SIG_R31(info, ctxt) (SIG_REGS(ctxt).gpr[31])
-
-#define SIG_SP(info, ctxt) (SIG_REGS(ctxt).gpr[1])
-#define SIG_PC(info, ctxt) (SIG_REGS(ctxt).nip)
-#define SIG_TRAP(info, ctxt) (SIG_REGS(ctxt).trap)
-#define SIG_CTR(info, ctxt) (SIG_REGS(ctxt).ctr)
-#define SIG_LINK(info, ctxt) (SIG_REGS(ctxt).link)
-#define SIG_XER(info, ctxt) (SIG_REGS(ctxt).xer)
-#define SIG_CCR(info, ctxt) (SIG_REGS(ctxt).ccr)
-
-#define SIG_CODE0(info, ctxt) ((uintptr)(info)->si_code)
-#define SIG_FAULT(info, ctxt) (SIG_REGS(ctxt).dar)
diff --git a/src/runtime/signal_linux_power64x.go b/src/runtime/signal_linux_power64x.go
new file mode 100644 (file)
index 0000000..0a406b3
--- /dev/null
@@ -0,0 +1,71 @@
+// 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.
+
+// +build linux
+// +build power64 power64le
+
+package runtime
+
+import "unsafe"
+
+type sigctxt struct {
+       info *siginfo
+       ctxt unsafe.Pointer
+}
+
+func (c *sigctxt) regs() *ptregs { return (*ucontext)(c.ctxt).uc_mcontext.regs }
+func (c *sigctxt) r0() uint64    { return c.regs().gpr[0] }
+func (c *sigctxt) r1() uint64    { return c.regs().gpr[1] }
+func (c *sigctxt) r2() uint64    { return c.regs().gpr[2] }
+func (c *sigctxt) r3() uint64    { return c.regs().gpr[3] }
+func (c *sigctxt) r4() uint64    { return c.regs().gpr[4] }
+func (c *sigctxt) r5() uint64    { return c.regs().gpr[5] }
+func (c *sigctxt) r6() uint64    { return c.regs().gpr[6] }
+func (c *sigctxt) r7() uint64    { return c.regs().gpr[7] }
+func (c *sigctxt) r8() uint64    { return c.regs().gpr[8] }
+func (c *sigctxt) r9() uint64    { return c.regs().gpr[9] }
+func (c *sigctxt) r10() uint64   { return c.regs().gpr[10] }
+func (c *sigctxt) r11() uint64   { return c.regs().gpr[11] }
+func (c *sigctxt) r12() uint64   { return c.regs().gpr[12] }
+func (c *sigctxt) r13() uint64   { return c.regs().gpr[13] }
+func (c *sigctxt) r14() uint64   { return c.regs().gpr[14] }
+func (c *sigctxt) r15() uint64   { return c.regs().gpr[15] }
+func (c *sigctxt) r16() uint64   { return c.regs().gpr[16] }
+func (c *sigctxt) r17() uint64   { return c.regs().gpr[17] }
+func (c *sigctxt) r18() uint64   { return c.regs().gpr[18] }
+func (c *sigctxt) r19() uint64   { return c.regs().gpr[19] }
+func (c *sigctxt) r20() uint64   { return c.regs().gpr[20] }
+func (c *sigctxt) r21() uint64   { return c.regs().gpr[21] }
+func (c *sigctxt) r22() uint64   { return c.regs().gpr[22] }
+func (c *sigctxt) r23() uint64   { return c.regs().gpr[23] }
+func (c *sigctxt) r24() uint64   { return c.regs().gpr[24] }
+func (c *sigctxt) r25() uint64   { return c.regs().gpr[25] }
+func (c *sigctxt) r26() uint64   { return c.regs().gpr[26] }
+func (c *sigctxt) r27() uint64   { return c.regs().gpr[27] }
+func (c *sigctxt) r28() uint64   { return c.regs().gpr[28] }
+func (c *sigctxt) r29() uint64   { return c.regs().gpr[29] }
+func (c *sigctxt) r30() uint64   { return c.regs().gpr[30] }
+func (c *sigctxt) r31() uint64   { return c.regs().gpr[31] }
+func (c *sigctxt) sp() uint64    { return c.regs().gpr[1] }
+func (c *sigctxt) pc() uint64    { return c.regs().nip }
+func (c *sigctxt) trap() uint64  { return c.regs().trap }
+func (c *sigctxt) ctr() uint64   { return c.regs().ctr }
+func (c *sigctxt) link() uint64  { return c.regs().link }
+func (c *sigctxt) xer() uint64   { return c.regs().xer }
+func (c *sigctxt) ccr() uint64   { return c.regs().ccr }
+
+func (c *sigctxt) sigcode() uint32 { return uint32(c.info.si_code) }
+func (c *sigctxt) sigaddr() uint64 { return c.info.si_addr }
+func (c *sigctxt) fault() uint64   { return c.regs().dar }
+
+func (c *sigctxt) set_r0(x uint64)   { c.regs().gpr[0] = x }
+func (c *sigctxt) set_r30(x uint64)  { c.regs().gpr[30] = x }
+func (c *sigctxt) set_pc(x uint64)   { c.regs().nip = x }
+func (c *sigctxt) set_sp(x uint64)   { c.regs().gpr[1] = x }
+func (c *sigctxt) set_link(x uint64) { c.regs().link = x }
+
+func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) }
+func (c *sigctxt) set_sigaddr(x uint64) {
+       *(*uintptr)(add(unsafe.Pointer(c.info), 2*ptrSize)) = uintptr(x)
+}
diff --git a/src/runtime/signal_nacl.go b/src/runtime/signal_nacl.go
new file mode 100644 (file)
index 0000000..122648b
--- /dev/null
@@ -0,0 +1,45 @@
+// 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.
+
+package runtime
+
+type sigTabT struct {
+       flags int32
+       name  string
+}
+
+var sigtable = [...]sigTabT{
+       /* 0 */ {0, "SIGNONE: no trap"},
+       /* 1 */ {_SigNotify + _SigKill, "SIGHUP: terminal line hangup"},
+       /* 2 */ {_SigNotify + _SigKill, "SIGINT: interrupt"},
+       /* 3 */ {_SigNotify + _SigThrow, "SIGQUIT: quit"},
+       /* 4 */ {_SigThrow, "SIGILL: illegal instruction"},
+       /* 5 */ {_SigThrow, "SIGTRAP: trace trap"},
+       /* 6 */ {_SigNotify + _SigThrow, "SIGABRT: abort"},
+       /* 7 */ {_SigThrow, "SIGEMT: emulate instruction executed"},
+       /* 8 */ {_SigPanic, "SIGFPE: floating-point exception"},
+       /* 9 */ {0, "SIGKILL: kill"},
+       /* 10 */ {_SigPanic, "SIGBUS: bus error"},
+       /* 11 */ {_SigPanic, "SIGSEGV: segmentation violation"},
+       /* 12 */ {_SigThrow, "SIGSYS: bad system call"},
+       /* 13 */ {_SigNotify, "SIGPIPE: write to broken pipe"},
+       /* 14 */ {_SigNotify, "SIGALRM: alarm clock"},
+       /* 15 */ {_SigNotify + _SigKill, "SIGTERM: termination"},
+       /* 16 */ {_SigNotify, "SIGURG: urgent condition on socket"},
+       /* 17 */ {0, "SIGSTOP: stop"},
+       /* 18 */ {_SigNotify + _SigDefault, "SIGTSTP: keyboard stop"},
+       /* 19 */ {0, "SIGCONT: continue after stop"},
+       /* 20 */ {_SigNotify, "SIGCHLD: child status has changed"},
+       /* 21 */ {_SigNotify + _SigDefault, "SIGTTIN: background read from tty"},
+       /* 22 */ {_SigNotify + _SigDefault, "SIGTTOU: background write to tty"},
+       /* 23 */ {_SigNotify, "SIGIO: i/o now possible"},
+       /* 24 */ {_SigNotify, "SIGXCPU: cpu limit exceeded"},
+       /* 25 */ {_SigNotify, "SIGXFSZ: file size limit exceeded"},
+       /* 26 */ {_SigNotify, "SIGVTALRM: virtual alarm clock"},
+       /* 27 */ {_SigNotify, "SIGPROF: profiling alarm clock"},
+       /* 28 */ {_SigNotify, "SIGWINCH: window size change"},
+       /* 29 */ {_SigNotify, "SIGINFO: status request from keyboard"},
+       /* 30 */ {_SigNotify, "SIGUSR1: user-defined signal 1"},
+       /* 31 */ {_SigNotify, "SIGUSR2: user-defined signal 2"},
+}
diff --git a/src/runtime/signal_nacl_386.go b/src/runtime/signal_nacl_386.go
new file mode 100644 (file)
index 0000000..0a1e7c6
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2013 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"
+
+type sigctxt struct {
+       info *siginfo
+       ctxt unsafe.Pointer
+}
+
+func (c *sigctxt) regs() *excregs386 { return &(*exccontext)(c.ctxt).regs }
+func (c *sigctxt) eax() uint32       { return c.regs().eax }
+func (c *sigctxt) ebx() uint32       { return c.regs().ebx }
+func (c *sigctxt) ecx() uint32       { return c.regs().ecx }
+func (c *sigctxt) edx() uint32       { return c.regs().edx }
+func (c *sigctxt) edi() uint32       { return c.regs().edi }
+func (c *sigctxt) esi() uint32       { return c.regs().esi }
+func (c *sigctxt) ebp() uint32       { return c.regs().ebp }
+func (c *sigctxt) esp() uint32       { return c.regs().esp }
+func (c *sigctxt) eip() uint32       { return c.regs().eip }
+func (c *sigctxt) eflags() uint32    { return c.regs().eflags }
+func (c *sigctxt) cs() uint32        { return ^uint32(0) }
+func (c *sigctxt) fs() uint32        { return ^uint32(0) }
+func (c *sigctxt) gs() uint32        { return ^uint32(0) }
+func (c *sigctxt) sigcode() uint32   { return ^uint32(0) }
+func (c *sigctxt) sigaddr() uint32   { return 0 }
+
+func (c *sigctxt) set_eip(x uint32)     { c.regs().eip = x }
+func (c *sigctxt) set_esp(x uint32)     { c.regs().esp = x }
+func (c *sigctxt) set_sigcode(x uint32) {}
+func (c *sigctxt) set_sigaddr(x uint32) {}
diff --git a/src/runtime/signal_nacl_386.h b/src/runtime/signal_nacl_386.h
deleted file mode 100644 (file)
index c9481b5..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2013 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.
-
-#define SIG_REGS(ctxt) (((ExcContext*)(ctxt))->regs)
-
-#define SIG_EAX(info, ctxt) (SIG_REGS(ctxt).eax)
-#define SIG_EBX(info, ctxt) (SIG_REGS(ctxt).ebx)
-#define SIG_ECX(info, ctxt) (SIG_REGS(ctxt).ecx)
-#define SIG_EDX(info, ctxt) (SIG_REGS(ctxt).edx)
-#define SIG_EDI(info, ctxt) (SIG_REGS(ctxt).edi)
-#define SIG_ESI(info, ctxt) (SIG_REGS(ctxt).esi)
-#define SIG_EBP(info, ctxt) (SIG_REGS(ctxt).ebp)
-#define SIG_ESP(info, ctxt) (SIG_REGS(ctxt).esp)
-#define SIG_EIP(info, ctxt) (SIG_REGS(ctxt).eip)
-#define SIG_EFLAGS(info, ctxt) (SIG_REGS(ctxt).eflags)
-
-#define SIG_CS(info, ctxt) (~0)
-#define SIG_FS(info, ctxt) (~0)
-#define SIG_GS(info, ctxt) (~0)
-
-#define SIG_CODE0(info, ctxt) (~0)
-#define SIG_CODE1(info, ctxt) (0)
diff --git a/src/runtime/signal_nacl_amd64p32.go b/src/runtime/signal_nacl_amd64p32.go
new file mode 100644 (file)
index 0000000..024ceba
--- /dev/null
@@ -0,0 +1,44 @@
+// 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"
+
+type sigctxt struct {
+       info *siginfo
+       ctxt unsafe.Pointer
+}
+
+func (c *sigctxt) regs() *excregsamd64 {
+       return &(*exccontext)(c.ctxt).regs
+}
+func (c *sigctxt) rax() uint64     { return c.regs().rax }
+func (c *sigctxt) rbx() uint64     { return c.regs().rbx }
+func (c *sigctxt) rcx() uint64     { return c.regs().rcx }
+func (c *sigctxt) rdx() uint64     { return c.regs().rdx }
+func (c *sigctxt) rdi() uint64     { return c.regs().rdi }
+func (c *sigctxt) rsi() uint64     { return c.regs().rsi }
+func (c *sigctxt) rbp() uint64     { return c.regs().rbp }
+func (c *sigctxt) rsp() uint64     { return c.regs().rsp }
+func (c *sigctxt) r8() uint64      { return c.regs().r8 }
+func (c *sigctxt) r9() uint64      { return c.regs().r9 }
+func (c *sigctxt) r10() uint64     { return c.regs().r10 }
+func (c *sigctxt) r11() uint64     { return c.regs().r11 }
+func (c *sigctxt) r12() uint64     { return c.regs().r12 }
+func (c *sigctxt) r13() uint64     { return c.regs().r13 }
+func (c *sigctxt) r14() uint64     { return c.regs().r14 }
+func (c *sigctxt) r15() uint64     { return c.regs().r15 }
+func (c *sigctxt) rip() uint64     { return c.regs().rip }
+func (c *sigctxt) rflags() uint64  { return uint64(c.regs().rflags) }
+func (c *sigctxt) cs() uint64      { return ^uint64(0) }
+func (c *sigctxt) fs() uint64      { return ^uint64(0) }
+func (c *sigctxt) gs() uint64      { return ^uint64(0) }
+func (c *sigctxt) sigcode() uint64 { return ^uint64(0) }
+func (c *sigctxt) sigaddr() uint64 { return 0 }
+
+func (c *sigctxt) set_rip(x uint64)     { c.regs().rip = x }
+func (c *sigctxt) set_rsp(x uint64)     { c.regs().rsp = x }
+func (c *sigctxt) set_sigcode(x uint64) {}
+func (c *sigctxt) set_sigaddr(x uint64) {}
diff --git a/src/runtime/signal_nacl_amd64p32.h b/src/runtime/signal_nacl_amd64p32.h
deleted file mode 100644 (file)
index f62305c..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2013 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.
-
-#define SIG_REGS(ctxt) (((ExcContext*)(ctxt))->regs.regs64)
-
-#define SIG_RAX(info, ctxt) (SIG_REGS(ctxt).rax)
-#define SIG_RBX(info, ctxt) (SIG_REGS(ctxt).rbx)
-#define SIG_RCX(info, ctxt) (SIG_REGS(ctxt).rcx)
-#define SIG_RDX(info, ctxt) (SIG_REGS(ctxt).rdx)
-#define SIG_RDI(info, ctxt) (SIG_REGS(ctxt).rdi)
-#define SIG_RSI(info, ctxt) (SIG_REGS(ctxt).rsi)
-#define SIG_RBP(info, ctxt) (SIG_REGS(ctxt).rbp)
-#define SIG_RSP(info, ctxt) (SIG_REGS(ctxt).rsp)
-#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).r8)
-#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).r9)
-#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).r10)
-#define SIG_R11(info, ctxt) (SIG_REGS(ctxt).r11)
-#define SIG_R12(info, ctxt) (SIG_REGS(ctxt).r12)
-#define SIG_R13(info, ctxt) (SIG_REGS(ctxt).r13)
-#define SIG_R14(info, ctxt) (SIG_REGS(ctxt).r14)
-#define SIG_R15(info, ctxt) (SIG_REGS(ctxt).r15)
-#define SIG_RIP(info, ctxt) (SIG_REGS(ctxt).rip)
-#define SIG_RFLAGS(info, ctxt) (SIG_REGS(ctxt).rflags)
-
-#define SIG_CS(info, ctxt) (~0)
-#define SIG_FS(info, ctxt) (~0)
-#define SIG_GS(info, ctxt) (~0)
-
-#define SIG_CODE0(info, ctxt) (~0)
-#define SIG_CODE1(info, ctxt) (0)
diff --git a/src/runtime/signal_nacl_arm.go b/src/runtime/signal_nacl_arm.go
new file mode 100644 (file)
index 0000000..1aeaa4e
--- /dev/null
@@ -0,0 +1,47 @@
+// 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"
+
+type sigctxt struct {
+       info *siginfo
+       ctxt unsafe.Pointer
+}
+
+func (c *sigctxt) regs() *excregsarm { return &(*exccontext)(c.ctxt).regs }
+
+func (c *sigctxt) r0() uint32      { return c.regs().r0 }
+func (c *sigctxt) r1() uint32      { return c.regs().r1 }
+func (c *sigctxt) r2() uint32      { return c.regs().r2 }
+func (c *sigctxt) r3() uint32      { return c.regs().r3 }
+func (c *sigctxt) r4() uint32      { return c.regs().r4 }
+func (c *sigctxt) r5() uint32      { return c.regs().r5 }
+func (c *sigctxt) r6() uint32      { return c.regs().r6 }
+func (c *sigctxt) r7() uint32      { return c.regs().r7 }
+func (c *sigctxt) r8() uint32      { return c.regs().r8 }
+func (c *sigctxt) r9() uint32      { return c.regs().r9 }
+func (c *sigctxt) r10() uint32     { return c.regs().r10 }
+func (c *sigctxt) fp() uint32      { return c.regs().r11 }
+func (c *sigctxt) ip() uint32      { return c.regs().r12 }
+func (c *sigctxt) sp() uint32      { return c.regs().sp }
+func (c *sigctxt) lr() uint32      { return c.regs().lr }
+func (c *sigctxt) pc() uint32      { return c.regs().pc }
+func (c *sigctxt) cpsr() uint32    { return c.regs().cpsr }
+func (c *sigctxt) fault() uint32   { return ^uint32(0) }
+func (c *sigctxt) trap() uint32    { return ^uint32(0) }
+func (c *sigctxt) error() uint32   { return ^uint32(0) }
+func (c *sigctxt) oldmask() uint32 { return ^uint32(0) }
+
+func (c *sigctxt) sigcode() uint32 { return 0 }
+func (c *sigctxt) sigaddr() uint32 { return 0 }
+
+func (c *sigctxt) set_pc(x uint32)  { c.regs().pc = x }
+func (c *sigctxt) set_sp(x uint32)  { c.regs().sp = x }
+func (c *sigctxt) set_lr(x uint32)  { c.regs().lr = x }
+func (c *sigctxt) set_r10(x uint32) { c.regs().r10 = x }
+
+func (c *sigctxt) set_sigcode(x uint32) {}
+func (c *sigctxt) set_sigaddr(x uint32) {}
diff --git a/src/runtime/signal_nacl_arm.h b/src/runtime/signal_nacl_arm.h
deleted file mode 100644 (file)
index e5bbb21..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-// 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.
-
-#define SIG_REGS(ctxt) (((ExcContext*)(ctxt))->regs)
-
-#define SIG_R0(info, ctxt) (SIG_REGS(ctxt).r0)
-#define SIG_R1(info, ctxt) (SIG_REGS(ctxt).r1)
-#define SIG_R2(info, ctxt) (SIG_REGS(ctxt).r2)
-#define SIG_R3(info, ctxt) (SIG_REGS(ctxt).r3)
-#define SIG_R4(info, ctxt) (SIG_REGS(ctxt).r4)
-#define SIG_R5(info, ctxt) (SIG_REGS(ctxt).r5)
-#define SIG_R6(info, ctxt) (SIG_REGS(ctxt).r6)
-#define SIG_R7(info, ctxt) (SIG_REGS(ctxt).r7)
-#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).r8)
-#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).r9)
-#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).r10)
-#define SIG_FP(info, ctxt) (SIG_REGS(ctxt).r11)
-#define SIG_IP(info, ctxt) (SIG_REGS(ctxt).r12)
-#define SIG_SP(info, ctxt) (SIG_REGS(ctxt).sp)
-#define SIG_LR(info, ctxt) (SIG_REGS(ctxt).lr)
-#define SIG_PC(info, ctxt) (SIG_REGS(ctxt).pc)
-#define SIG_CPSR(info, ctxt) (SIG_REGS(ctxt).cpsr)
-#define SIG_FAULT(info, ctxt) (~0)
-#define SIG_TRAP(info, ctxt) (~0)
-#define SIG_ERROR(info, ctxt) (~0)
-#define SIG_OLDMASK(info, ctxt) (~0)
-#define SIG_CODE0(info, ctxt) (~0)
diff --git a/src/runtime/signal_netbsd.go b/src/runtime/signal_netbsd.go
new file mode 100644 (file)
index 0000000..78afc59
--- /dev/null
@@ -0,0 +1,46 @@
+// 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.
+
+package runtime
+
+type sigTabT struct {
+       flags int32
+       name  string
+}
+
+var sigtable = [...]sigTabT{
+       /*  0 */ {0, "SIGNONE: no trap"},
+       /*  1 */ {_SigNotify + _SigKill, "SIGHUP: terminal line hangup"},
+       /*  2 */ {_SigNotify + _SigKill, "SIGINT: interrupt"},
+       /*  3 */ {_SigNotify + _SigThrow, "SIGQUIT: quit"},
+       /*  4 */ {_SigThrow, "SIGILL: illegal instruction"},
+       /*  5 */ {_SigThrow, "SIGTRAP: trace trap"},
+       /*  6 */ {_SigNotify + _SigThrow, "SIGABRT: abort"},
+       /*  7 */ {_SigThrow, "SIGEMT: emulate instruction executed"},
+       /*  8 */ {_SigPanic, "SIGFPE: floating-point exception"},
+       /*  9 */ {0, "SIGKILL: kill"},
+       /* 10 */ {_SigPanic, "SIGBUS: bus error"},
+       /* 11 */ {_SigPanic, "SIGSEGV: segmentation violation"},
+       /* 12 */ {_SigThrow, "SIGSYS: bad system call"},
+       /* 13 */ {_SigNotify, "SIGPIPE: write to broken pipe"},
+       /* 14 */ {_SigNotify, "SIGALRM: alarm clock"},
+       /* 15 */ {_SigNotify + _SigKill, "SIGTERM: termination"},
+       /* 16 */ {_SigNotify, "SIGURG: urgent condition on socket"},
+       /* 17 */ {0, "SIGSTOP: stop"},
+       /* 18 */ {_SigNotify + _SigDefault, "SIGTSTP: keyboard stop"},
+       /* 19 */ {0, "SIGCONT: continue after stop"},
+       /* 20 */ {_SigNotify, "SIGCHLD: child status has changed"},
+       /* 21 */ {_SigNotify + _SigDefault, "SIGTTIN: background read from tty"},
+       /* 22 */ {_SigNotify + _SigDefault, "SIGTTOU: background write to tty"},
+       /* 23 */ {_SigNotify, "SIGIO: i/o now possible"},
+       /* 24 */ {_SigNotify, "SIGXCPU: cpu limit exceeded"},
+       /* 25 */ {_SigNotify, "SIGXFSZ: file size limit exceeded"},
+       /* 26 */ {_SigNotify, "SIGVTALRM: virtual alarm clock"},
+       /* 27 */ {_SigNotify, "SIGPROF: profiling alarm clock"},
+       /* 28 */ {_SigNotify, "SIGWINCH: window size change"},
+       /* 29 */ {_SigNotify, "SIGINFO: status request from keyboard"},
+       /* 30 */ {_SigNotify, "SIGUSR1: user-defined signal 1"},
+       /* 31 */ {_SigNotify, "SIGUSR2: user-defined signal 2"},
+       /* 32 */ {_SigNotify, "SIGTHR: reserved"},
+}
diff --git a/src/runtime/signal_netbsd_386.go b/src/runtime/signal_netbsd_386.go
new file mode 100644 (file)
index 0000000..6702336
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2013 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"
+
+type sigctxt struct {
+       info *siginfo
+       ctxt unsafe.Pointer
+}
+
+func (c *sigctxt) regs() *mcontextt { return &(*ucontextt)(c.ctxt).uc_mcontext }
+func (c *sigctxt) eax() uint32      { return c.regs().__gregs[_REG_EAX] }
+func (c *sigctxt) ebx() uint32      { return c.regs().__gregs[_REG_EBX] }
+func (c *sigctxt) ecx() uint32      { return c.regs().__gregs[_REG_ECX] }
+func (c *sigctxt) edx() uint32      { return c.regs().__gregs[_REG_EDX] }
+func (c *sigctxt) edi() uint32      { return c.regs().__gregs[_REG_EDI] }
+func (c *sigctxt) esi() uint32      { return c.regs().__gregs[_REG_ESI] }
+func (c *sigctxt) ebp() uint32      { return c.regs().__gregs[_REG_EBP] }
+func (c *sigctxt) esp() uint32      { return c.regs().__gregs[_REG_UESP] }
+func (c *sigctxt) eip() uint32      { return c.regs().__gregs[_REG_EIP] }
+func (c *sigctxt) eflags() uint32   { return c.regs().__gregs[_REG_EFL] }
+func (c *sigctxt) cs() uint32       { return uint32(c.regs().__gregs[_REG_CS]) }
+func (c *sigctxt) fs() uint32       { return uint32(c.regs().__gregs[_REG_FS]) }
+func (c *sigctxt) gs() uint32       { return uint32(c.regs().__gregs[_REG_GS]) }
+func (c *sigctxt) sigcode() uint32  { return uint32(c.info._code) }
+func (c *sigctxt) sigaddr() uint32 {
+       return uint32(*(*uint32)(unsafe.Pointer(&c.info._reason[0])))
+}
+
+func (c *sigctxt) set_eip(x uint32)     { c.regs().__gregs[_REG_EIP] = x }
+func (c *sigctxt) set_esp(x uint32)     { c.regs().__gregs[_REG_UESP] = x }
+func (c *sigctxt) set_sigcode(x uint32) { c.info._code = int32(x) }
+func (c *sigctxt) set_sigaddr(x uint32) {
+       *(*uint32)(unsafe.Pointer(&c.info._reason[0])) = x
+}
diff --git a/src/runtime/signal_netbsd_386.h b/src/runtime/signal_netbsd_386.h
deleted file mode 100644 (file)
index d5a8a0c..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2013 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.
-
-#define SIG_REGS(ctxt) (((UcontextT*)(ctxt))->uc_mcontext)
-
-#define SIG_EAX(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_EAX])
-#define SIG_EBX(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_EBX])
-#define SIG_ECX(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_ECX])
-#define SIG_EDX(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_EDX])
-#define SIG_EDI(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_EDI])
-#define SIG_ESI(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_ESI])
-#define SIG_EBP(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_EBP])
-#define SIG_ESP(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_UESP])
-#define SIG_EIP(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_EIP])
-#define SIG_EFLAGS(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_EFL])
-
-#define SIG_CS(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_CS])
-#define SIG_FS(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_FS])
-#define SIG_GS(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_GS])
-
-#define SIG_CODE0(info, ctxt) ((info)->_code)
-#define SIG_CODE1(info, ctxt) (*(uintptr*)&(info)->_reason[0])
diff --git a/src/runtime/signal_netbsd_amd64.go b/src/runtime/signal_netbsd_amd64.go
new file mode 100644 (file)
index 0000000..e22f4a7
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright 2013 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"
+
+type sigctxt struct {
+       info *siginfo
+       ctxt unsafe.Pointer
+}
+
+func (c *sigctxt) regs() *mcontextt {
+       return (*mcontextt)(unsafe.Pointer(&(*ucontextt)(c.ctxt).uc_mcontext))
+}
+func (c *sigctxt) rax() uint64     { return c.regs().__gregs[_REG_RAX] }
+func (c *sigctxt) rbx() uint64     { return c.regs().__gregs[_REG_RBX] }
+func (c *sigctxt) rcx() uint64     { return c.regs().__gregs[_REG_RCX] }
+func (c *sigctxt) rdx() uint64     { return c.regs().__gregs[_REG_RDX] }
+func (c *sigctxt) rdi() uint64     { return c.regs().__gregs[_REG_RDI] }
+func (c *sigctxt) rsi() uint64     { return c.regs().__gregs[_REG_RSI] }
+func (c *sigctxt) rbp() uint64     { return c.regs().__gregs[_REG_RBP] }
+func (c *sigctxt) rsp() uint64     { return c.regs().__gregs[_REG_RSP] }
+func (c *sigctxt) r8() uint64      { return c.regs().__gregs[_REG_R8] }
+func (c *sigctxt) r9() uint64      { return c.regs().__gregs[_REG_R8] }
+func (c *sigctxt) r10() uint64     { return c.regs().__gregs[_REG_R10] }
+func (c *sigctxt) r11() uint64     { return c.regs().__gregs[_REG_R11] }
+func (c *sigctxt) r12() uint64     { return c.regs().__gregs[_REG_R12] }
+func (c *sigctxt) r13() uint64     { return c.regs().__gregs[_REG_R13] }
+func (c *sigctxt) r14() uint64     { return c.regs().__gregs[_REG_R14] }
+func (c *sigctxt) r15() uint64     { return c.regs().__gregs[_REG_R15] }
+func (c *sigctxt) rip() uint64     { return c.regs().__gregs[_REG_RIP] }
+func (c *sigctxt) rflags() uint64  { return c.regs().__gregs[_REG_RFLAGS] }
+func (c *sigctxt) cs() uint64      { return c.regs().__gregs[_REG_CS] }
+func (c *sigctxt) fs() uint64      { return c.regs().__gregs[_REG_FS] }
+func (c *sigctxt) gs() uint64      { return c.regs().__gregs[_REG_GS] }
+func (c *sigctxt) sigcode() uint64 { return uint64(c.info._code) }
+func (c *sigctxt) sigaddr() uint64 {
+       return uint64(*(*uint64)(unsafe.Pointer(&c.info._reason[0])))
+}
+
+func (c *sigctxt) set_rip(x uint64)     { c.regs().__gregs[_REG_RIP] = x }
+func (c *sigctxt) set_rsp(x uint64)     { c.regs().__gregs[_REG_RSP] = x }
+func (c *sigctxt) set_sigcode(x uint64) { c.info._code = int32(x) }
+func (c *sigctxt) set_sigaddr(x uint64) {
+       *(*uint64)(unsafe.Pointer(&c.info._reason[0])) = x
+}
diff --git a/src/runtime/signal_netbsd_amd64.h b/src/runtime/signal_netbsd_amd64.h
deleted file mode 100644 (file)
index 7ec4cd9..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2013 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.
-
-#define SIG_REGS(ctxt) (((UcontextT*)(ctxt))->uc_mcontext)
-
-#define SIG_RAX(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RAX])
-#define SIG_RBX(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RBX])
-#define SIG_RCX(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RCX])
-#define SIG_RDX(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RDX])
-#define SIG_RDI(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RDI])
-#define SIG_RSI(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RSI])
-#define SIG_RBP(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RBP])
-#define SIG_RSP(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RSP])
-#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R8])
-#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R9])
-#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R10])
-#define SIG_R11(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R11])
-#define SIG_R12(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R12])
-#define SIG_R13(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R13])
-#define SIG_R14(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R14])
-#define SIG_R15(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R15])
-#define SIG_RIP(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RIP])
-#define SIG_RFLAGS(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RFLAGS])
-
-#define SIG_CS(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_CS])
-#define SIG_FS(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_FS])
-#define SIG_GS(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_GS])
-
-#define SIG_CODE0(info, ctxt) ((info)->_code)
-#define SIG_CODE1(info, ctxt) (*(uintptr*)&(info)->_reason[0])
similarity index 54%
rename from src/runtime/signals_plan9.h
rename to src/runtime/signal_plan9.go
index 4ee8e542c901fc511bbda89a2e4a8a1ff05ac1d2..37d24359bfdf3578666956a062149d6e1c92db2f 100644 (file)
@@ -2,62 +2,53 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-#include "textflag.h"
+package runtime
 
-#define N SigNotify
-#define K SigKill
-#define T SigThrow
-#define P SigPanic
-#define E SigGoExit
+type sigTabT struct {
+       flags int
+       name  []byte
+}
 
 // Incoming notes are compared against this table using strncmp, so the
 // order matters: longer patterns must appear before their prefixes.
-// There are #defined SIG constants in os_plan9.h for the table index of
-// some of these.
+// There are _SIG constants in os2_plan9.go for the table index of some
+// of these.
 //
 // If you add entries to this table, you must respect the prefix ordering
-// and also update the constant values is os_plan9.h.
-
-#pragma dataflag NOPTR
-SigTab runtime·sigtab[] = {
+// and also update the constant values is os2_plan9.go.
+var sigtable = [...]sigTabT{
        // Traps that we cannot be recovered.
-       T,      "sys: trap: debug exception",
-       T,      "sys: trap: invalid opcode",
+       {_SigThrow, []byte("sys: trap: debug exception")},
+       {_SigThrow, []byte("sys: trap: invalid opcode")},
 
        // We can recover from some memory errors in runtime·sigpanic.
-       P,      "sys: trap: fault read addr",   // SIGRFAULT
-       P,      "sys: trap: fault write addr",  // SIGWFAULT
+       {_SigPanic, []byte("sys: trap: fault read addr")},  // SIGRFAULT
+       {_SigPanic, []byte("sys: trap: fault write addr")}, // SIGWFAULT
 
        // We can also recover from math errors.
-       P,      "sys: trap: divide error",      // SIGINTDIV
-       P,      "sys: fp:",     // SIGFLOAT
+       {_SigPanic, []byte("sys: trap: divide error")}, // SIGINTDIV
+       {_SigPanic, []byte("sys: fp:")},                // SIGFLOAT
 
        // All other traps are normally handled as if they were marked SigThrow.
        // We mark them SigPanic here so that debug.SetPanicOnFault will work.
-       P,      "sys: trap:",   // SIGTRAP
+       {_SigPanic, []byte("sys: trap:")}, // SIGTRAP
 
        // Writes to a closed pipe can be handled if desired, otherwise they're ignored.
-       N,      "sys: write on closed pipe",
+       {_SigNotify, []byte("sys: write on closed pipe")},
 
        // Other system notes are more serious and cannot be recovered.
-       T,      "sys:",
+       {_SigThrow, []byte("sys:")},
 
        // Issued to all other procs when calling runtime·exit.
-       E,      "go: exit ",
+       {_SigGoExit, []byte("go: exit ")},
 
        // Kill is sent by external programs to cause an exit.
-       K,      "kill",
+       {_SigKill, []byte("kill")},
 
        // Interrupts can be handled if desired, otherwise they cause an exit.
-       N+K,    "interrupt",
-       N+K,    "hangup",
+       {_SigNotify + _SigKill, []byte("interrupt")},
+       {_SigNotify + _SigKill, []byte("hangup")},
 
        // Alarms can be handled if desired, otherwise they're ignored.
-       N,      "alarm",
-};
-
-#undef N
-#undef K
-#undef T
-#undef P
-#undef E
+       {_SigNotify, []byte("alarm")},
+}
diff --git a/src/runtime/signal_power64x.c b/src/runtime/signal_power64x.c
deleted file mode 100644 (file)
index c0bf1c4..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-// 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.
-
-// +build linux
-// +build power64 power64le
-
-#include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "signal_GOOS_GOARCH.h"
-#include "signals_GOOS.h"
-
-void
-runtime·dumpregs(Siginfo *info, void *ctxt)
-{
-       USED(info); USED(ctxt);
-       runtime·printf("r0  %X\t", SIG_R0(info, ctxt));
-       runtime·printf("r1  %X\n", SIG_R1(info, ctxt));
-       runtime·printf("r2  %X\t", SIG_R2(info, ctxt));
-       runtime·printf("r3  %X\n", SIG_R3(info, ctxt));
-       runtime·printf("r4  %X\t", SIG_R4(info, ctxt));
-       runtime·printf("r5  %X\n", SIG_R5(info, ctxt));
-       runtime·printf("r6  %X\t", SIG_R6(info, ctxt));
-       runtime·printf("r7  %X\n", SIG_R7(info, ctxt));
-       runtime·printf("r8  %X\t", SIG_R8(info, ctxt));
-       runtime·printf("r9  %X\n", SIG_R9(info, ctxt));
-       runtime·printf("r10  %X\t", SIG_R10(info, ctxt));
-       runtime·printf("r11  %X\n", SIG_R11(info, ctxt));
-       runtime·printf("r12  %X\t", SIG_R12(info, ctxt));
-       runtime·printf("r13  %X\n", SIG_R13(info, ctxt));
-       runtime·printf("r14  %X\t", SIG_R14(info, ctxt));
-       runtime·printf("r15  %X\n", SIG_R15(info, ctxt));
-       runtime·printf("r16  %X\t", SIG_R16(info, ctxt));
-       runtime·printf("r17  %X\n", SIG_R17(info, ctxt));
-       runtime·printf("r18  %X\t", SIG_R18(info, ctxt));
-       runtime·printf("r19  %X\n", SIG_R19(info, ctxt));
-       runtime·printf("r20  %X\t", SIG_R20(info, ctxt));
-       runtime·printf("r21  %X\n", SIG_R21(info, ctxt));
-       runtime·printf("r22  %X\t", SIG_R22(info, ctxt));
-       runtime·printf("r23  %X\n", SIG_R23(info, ctxt));
-       runtime·printf("r24  %X\t", SIG_R24(info, ctxt));
-       runtime·printf("r25  %X\n", SIG_R25(info, ctxt));
-       runtime·printf("r26  %X\t", SIG_R26(info, ctxt));
-       runtime·printf("r27  %X\n", SIG_R27(info, ctxt));
-       runtime·printf("r28  %X\t", SIG_R28(info, ctxt));
-       runtime·printf("r29  %X\n", SIG_R29(info, ctxt));
-       runtime·printf("r30  %X\t", SIG_R30(info, ctxt));
-       runtime·printf("r31  %X\n", SIG_R31(info, ctxt));
-       runtime·printf("pc   %X\t", SIG_PC(info, ctxt));
-       runtime·printf("ctr  %X\n", SIG_CTR(info, ctxt));
-       runtime·printf("link %X\t", SIG_LINK(info, ctxt));
-       runtime·printf("xer  %X\n", SIG_XER(info, ctxt));
-       runtime·printf("ccr  %X\t", SIG_CCR(info, ctxt));
-       runtime·printf("trap %X\n", SIG_TRAP(info, ctxt));
-}
-
-void
-runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
-{
-       SigTab *t;
-       bool crash;
-
-       if(sig == SIGPROF) {
-               runtime·sigprof((uint8*)SIG_PC(info, ctxt), (uint8*)SIG_SP(info, ctxt), (uint8*)SIG_LINK(info, ctxt), gp, g->m);
-               return;
-       }
-       t = &runtime·sigtab[sig];
-       if(SIG_CODE0(info, ctxt) != SI_USER && (t->flags & SigPanic)) {
-               // Make it look like a call to the signal func.
-               // Have to pass arguments out of band since
-               // augmenting the stack frame would break
-               // the unwinding code.
-               gp->sig = sig;
-               gp->sigcode0 = SIG_CODE0(info, ctxt);
-               gp->sigcode1 = SIG_FAULT(info, ctxt);
-               gp->sigpc = SIG_PC(info, ctxt);
-
-               // We arrange link, and pc to pretend the panicking
-               // function calls sigpanic directly.
-               // Always save LINK to stack so that panics in leaf
-               // functions are correctly handled. This smashes
-               // the stack frame but we're not going back there
-               // anyway.
-               SIG_SP(info, ctxt) -= sizeof(uintptr);
-               *(uintptr*)SIG_SP(info, ctxt) = SIG_LINK(info, ctxt);
-               // Don't bother saving PC if it's zero, which is
-               // probably a call to a nil func: the old link register
-               // is more useful in the stack trace.
-               if(gp->sigpc != 0)
-                       SIG_LINK(info, ctxt) = gp->sigpc;
-               // In case we are panicking from external C code
-               SIG_R0(info, ctxt) = 0;
-               SIG_R30(info, ctxt) = (uintptr)gp;
-               SIG_PC(info, ctxt) = (uintptr)runtime·sigpanic;
-               return;
-       }
-
-       if(SIG_CODE0(info, ctxt) == SI_USER || (t->flags & SigNotify))
-               if(runtime·sigsend(sig))
-                       return;
-       if(t->flags & SigKill)
-               runtime·exit(2);
-       if(!(t->flags & SigThrow))
-               return;
-
-       g->m->throwing = 1;
-       g->m->caughtsig = gp;
-       if(runtime·panicking)  // traceback already printed
-               runtime·exit(2);
-       runtime·panicking = 1;
-
-       if(sig < 0 || sig >= NSIG)
-               runtime·printf("Signal %d\n", sig);
-       else
-               runtime·printf("%s\n", runtime·sigtab[sig].name);
-
-       runtime·printf("PC=%x\n", SIG_PC(info, ctxt));
-       if(g->m->lockedg != nil && g->m->ncgo > 0 && gp == g->m->g0) {
-               runtime·printf("signal arrived during cgo execution\n");
-               gp = g->m->lockedg;
-       }
-       runtime·printf("\n");
-
-       if(runtime·gotraceback(&crash)){
-               runtime·goroutineheader(gp);
-               runtime·tracebacktrap(SIG_PC(info, ctxt), SIG_SP(info, ctxt), SIG_LINK(info, ctxt), gp);
-               runtime·tracebackothers(gp);
-               runtime·printf("\n");
-               runtime·dumpregs(info, ctxt);
-       }
-       
-       if(crash)
-               runtime·crash();
-
-       runtime·exit(2);
-}
diff --git a/src/runtime/signal_power64x.go b/src/runtime/signal_power64x.go
new file mode 100644 (file)
index 0000000..fc83beb
--- /dev/null
@@ -0,0 +1,144 @@
+// 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.
+
+// +build linux
+// +build power64 power64le
+
+package runtime
+
+import "unsafe"
+
+func dumpregs(c *sigctxt) {
+       print("r0   ", hex(c.r0()), "\t")
+       print("r1   ", hex(c.r1()), "\n")
+       print("r2   ", hex(c.r2()), "\t")
+       print("r3   ", hex(c.r3()), "\n")
+       print("r4   ", hex(c.r4()), "\t")
+       print("r5   ", hex(c.r5()), "\n")
+       print("r6   ", hex(c.r6()), "\t")
+       print("r7   ", hex(c.r7()), "\n")
+       print("r8   ", hex(c.r8()), "\t")
+       print("r9   ", hex(c.r9()), "\n")
+       print("r10  ", hex(c.r10()), "\t")
+       print("r11  ", hex(c.r11()), "\n")
+       print("r12  ", hex(c.r12()), "\t")
+       print("r13  ", hex(c.r13()), "\n")
+       print("r14  ", hex(c.r14()), "\t")
+       print("r15  ", hex(c.r15()), "\n")
+       print("r16  ", hex(c.r16()), "\t")
+       print("r17  ", hex(c.r17()), "\n")
+       print("r18  ", hex(c.r18()), "\t")
+       print("r19  ", hex(c.r19()), "\n")
+       print("r20  ", hex(c.r20()), "\t")
+       print("r21  ", hex(c.r21()), "\n")
+       print("r22  ", hex(c.r22()), "\t")
+       print("r23  ", hex(c.r23()), "\n")
+       print("r24  ", hex(c.r24()), "\t")
+       print("r25  ", hex(c.r25()), "\n")
+       print("r26  ", hex(c.r26()), "\t")
+       print("r27  ", hex(c.r27()), "\n")
+       print("r28  ", hex(c.r28()), "\t")
+       print("r29  ", hex(c.r29()), "\n")
+       print("r30  ", hex(c.r30()), "\t")
+       print("r31  ", hex(c.r31()), "\n")
+       print("pc   ", hex(c.pc()), "\t")
+       print("ctr  ", hex(c.ctr()), "\n")
+       print("link ", hex(c.link()), "\t")
+       print("xer  ", hex(c.xer()), "\n")
+       print("ccr  ", hex(c.ccr()), "\t")
+       print("trap ", hex(c.trap()), "\n")
+}
+
+func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
+       _g_ := getg()
+       c := &sigctxt{info, ctxt}
+
+       if sig == _SIGPROF {
+               sigprof((*byte)(unsafe.Pointer(uintptr(c.pc()))), (*byte)(unsafe.Pointer(uintptr(c.sp()))), (*byte)(unsafe.Pointer(uintptr(c.link()))), gp, _g_.m)
+               return
+       }
+       flags := int32(_SigThrow)
+       if sig < uint32(len(sigtable)) {
+               flags = sigtable[sig].flags
+       }
+       if c.sigcode() != _SI_USER && flags&_SigPanic != 0 {
+               // Make it look like a call to the signal func.
+               // Have to pass arguments out of band since
+               // augmenting the stack frame would break
+               // the unwinding code.
+               gp.sig = sig
+               gp.sigcode0 = uintptr(c.sigcode())
+               gp.sigcode1 = uintptr(c.fault())
+               gp.sigpc = uintptr(c.pc())
+
+               // We arrange link, and pc to pretend the panicking
+               // function calls sigpanic directly.
+               // Always save LINK to stack so that panics in leaf
+               // functions are correctly handled. This smashes
+               // the stack frame but we're not going back there
+               // anyway.
+               sp := c.sp() - ptrSize
+               c.set_sp(sp)
+               *(*uint64)(unsafe.Pointer(uintptr(sp))) = c.link()
+
+               // Don't bother saving PC if it's zero, which is
+               // probably a call to a nil func: the old link register
+               // is more useful in the stack trace.
+               if gp.sigpc != 0 {
+                       c.set_link(uint64(gp.sigpc))
+               }
+
+               // In case we are panicking from external C code
+               c.set_r0(0)
+               c.set_r30(uint64(uintptr(unsafe.Pointer(gp))))
+               c.set_pc(uint64(funcPC(sigpanic)))
+               return
+       }
+
+       if c.sigcode() == _SI_USER || flags&_SigNotify != 0 {
+               if sigsend(sig) {
+                       return
+               }
+       }
+
+       if flags&_SigKill != 0 {
+               exit(2)
+       }
+
+       if flags&_SigThrow == 0 {
+               return
+       }
+
+       _g_.m.throwing = 1
+       _g_.m.caughtsig = gp
+       startpanic()
+
+       if sig < uint32(len(sigtable)) {
+               print(sigtable[sig].name, "\n")
+       } else {
+               print("Signal ", sig, "\n")
+       }
+
+       print("PC=", hex(c.pc()), "\n")
+       if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 {
+               print("signal arrived during cgo execution\n")
+               gp = _g_.m.lockedg
+       }
+       print("\n")
+
+       var docrash bool
+       if gotraceback(&docrash) > 0 {
+               goroutineheader(gp)
+               tracebacktrap(uintptr(c.pc()), uintptr(c.sp()), uintptr(c.link()), gp)
+               tracebackothers(gp)
+               print("\n")
+               dumpregs(c)
+       }
+
+       if docrash {
+               crash()
+       }
+
+       exit(2)
+}
diff --git a/src/runtime/signals_android.h b/src/runtime/signals_android.h
deleted file mode 100644 (file)
index 5140d8a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include "signals_linux.h"
diff --git a/src/runtime/signals_nacl.h b/src/runtime/signals_nacl.h
deleted file mode 100644 (file)
index 8761e1b..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-// 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 "textflag.h"
-
-#define N SigNotify
-#define K SigKill
-#define T SigThrow
-#define P SigPanic
-#define D SigDefault
-
-#pragma dataflag NOPTR
-SigTab runtime·sigtab[] = {
-       /* 0 */ 0, "SIGNONE: no trap",
-       /* 1 */ N+K, "SIGHUP: terminal line hangup",
-       /* 2 */ N+K, "SIGINT: interrupt",
-       /* 3 */ N+T, "SIGQUIT: quit",
-       /* 4 */ T, "SIGILL: illegal instruction",
-       /* 5 */ T, "SIGTRAP: trace trap",
-       /* 6 */ N+T, "SIGABRT: abort",
-       /* 7 */ T, "SIGEMT: emulate instruction executed",
-       /* 8 */ P, "SIGFPE: floating-point exception",
-       /* 9 */ 0, "SIGKILL: kill",
-       /* 10 */        P, "SIGBUS: bus error",
-       /* 11 */        P, "SIGSEGV: segmentation violation",
-       /* 12 */        T, "SIGSYS: bad system call",
-       /* 13 */        N, "SIGPIPE: write to broken pipe",
-       /* 14 */        N, "SIGALRM: alarm clock",
-       /* 15 */        N+K, "SIGTERM: termination",
-       /* 16 */        N, "SIGURG: urgent condition on socket",
-       /* 17 */        0, "SIGSTOP: stop",
-       /* 18 */        N+D, "SIGTSTP: keyboard stop",
-       /* 19 */        0, "SIGCONT: continue after stop",
-       /* 20 */        N, "SIGCHLD: child status has changed",
-       /* 21 */        N+D, "SIGTTIN: background read from tty",
-       /* 22 */        N+D, "SIGTTOU: background write to tty",
-       /* 23 */        N, "SIGIO: i/o now possible",
-       /* 24 */        N, "SIGXCPU: cpu limit exceeded",
-       /* 25 */        N, "SIGXFSZ: file size limit exceeded",
-       /* 26 */        N, "SIGVTALRM: virtual alarm clock",
-       /* 27 */        N, "SIGPROF: profiling alarm clock",
-       /* 28 */        N, "SIGWINCH: window size change",
-       /* 29 */        N, "SIGINFO: status request from keyboard",
-       /* 30 */        N, "SIGUSR1: user-defined signal 1",
-       /* 31 */        N, "SIGUSR2: user-defined signal 2",
-};
-
-#undef N
-#undef K
-#undef T
-#undef P
-#undef D
diff --git a/src/runtime/signals_netbsd.h b/src/runtime/signals_netbsd.h
deleted file mode 100644 (file)
index 950a2fe..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-// 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 "textflag.h"
-
-#define N SigNotify
-#define K SigKill
-#define T SigThrow
-#define P SigPanic
-#define D SigDefault
-
-#pragma dataflag NOPTR
-SigTab runtime·sigtab[] = {
-       /*  0 */        0, "SIGNONE: no trap",
-       /*  1 */        N+K, "SIGHUP: terminal line hangup",
-       /*  2 */        N+K, "SIGINT: interrupt",
-       /*  3 */        N+T, "SIGQUIT: quit",
-       /*  4 */        T, "SIGILL: illegal instruction",
-       /*  5 */        T, "SIGTRAP: trace trap",
-       /*  6 */        N+T, "SIGABRT: abort",
-       /*  7 */        T, "SIGEMT: emulate instruction executed",
-       /*  8 */        P, "SIGFPE: floating-point exception",
-       /*  9 */        0, "SIGKILL: kill",
-       /* 10 */        P, "SIGBUS: bus error",
-       /* 11 */        P, "SIGSEGV: segmentation violation",
-       /* 12 */        T, "SIGSYS: bad system call",
-       /* 13 */        N, "SIGPIPE: write to broken pipe",
-       /* 14 */        N, "SIGALRM: alarm clock",
-       /* 15 */        N+K, "SIGTERM: termination",
-       /* 16 */        N, "SIGURG: urgent condition on socket",
-       /* 17 */        0, "SIGSTOP: stop",
-       /* 18 */        N+D, "SIGTSTP: keyboard stop",
-       /* 19 */        0, "SIGCONT: continue after stop",
-       /* 20 */        N, "SIGCHLD: child status has changed",
-       /* 21 */        N+D, "SIGTTIN: background read from tty",
-       /* 22 */        N+D, "SIGTTOU: background write to tty",
-       /* 23 */        N, "SIGIO: i/o now possible",
-       /* 24 */        N, "SIGXCPU: cpu limit exceeded",
-       /* 25 */        N, "SIGXFSZ: file size limit exceeded",
-       /* 26 */        N, "SIGVTALRM: virtual alarm clock",
-       /* 27 */        N, "SIGPROF: profiling alarm clock",
-       /* 28 */        N, "SIGWINCH: window size change",
-       /* 29 */        N, "SIGINFO: status request from keyboard",
-       /* 30 */        N, "SIGUSR1: user-defined signal 1",
-       /* 31 */        N, "SIGUSR2: user-defined signal 2",
-       /* 32 */        N, "SIGTHR: reserved",
-};
-
-#undef N
-#undef K
-#undef T
-#undef P
-#undef D
index 57d0f8c65ef271520b9480f576678a2f5ddcdd29..c14347dbdfc80ad71aca2512168e3469e42099cf 100644 (file)
@@ -781,7 +781,7 @@ func shrinkstack(gp *g) {
        if gp.syscallsp != 0 {
                return
        }
-       if _Windows != 0 && gp.m != nil && gp.m.libcallsp != 0 {
+       if goos_windows != 0 && gp.m != nil && gp.m.libcallsp != 0 {
                return
        }
 
index c3718c205e5e48e8110cb65ecc249a0a99601e2e..e50b32c784ab655781be39cceb72d213e4181917 100644 (file)
@@ -59,7 +59,7 @@ const (
        // to each stack below the usual guard area for OS-specific
        // purposes like signal handling. Used on Windows and on
        // Plan 9 because they do not use a separate stack.
-       _StackSystem = _Windows*512*ptrSize + _Plan9*512
+       _StackSystem = goos_windows*512*ptrSize + goos_plan9*512
 
        // The minimum size of stack used by Go code
        _StackMin = 2048
index 4063e5434b103c68b33c92741b94b372c3d34bfd..4408e22bffdf9ed1d584c72045cb9fc4bd6413c6 100644 (file)
@@ -154,7 +154,7 @@ func setcallerpc(argp unsafe.Pointer, pc uintptr)
 //
 //     func f(arg1, arg2, arg3 int) {
 //             pc := getcallerpc(unsafe.Pointer(&arg1))
-//             sp := getcallerpc(unsafe.Pointer(&arg2))
+//             sp := getcallersp(unsafe.Pointer(&arg1))
 //     }
 //
 // These two lines find the PC and SP immediately following
index 526b3c56916d73e2a6e2ebbf4d7abbfe8e4bf216..60751dd343dc76fbff9c3045e3c2b65fb7b0a35e 100644 (file)
@@ -2,7 +2,10 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build !plan9
 // +build !solaris
+// +build !windows
+// +build !nacl
 
 package runtime
 
similarity index 53%
rename from src/runtime/arch_power64le.h
rename to src/runtime/stubs3.go
index 684ac9953bae7eb9d9eaca3dc0a5c848cf198af8..ffaa28775dc7a41983c1f5eaf4e262479fa3dfc6 100644 (file)
@@ -2,13 +2,11 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-enum {
-       thechar = '9',
-       BigEndian = 0,
-       CacheLineSize = 64,
-       RuntimeGogoBytes = 64,
-       PhysPageSize = 65536,
-       PCQuantum = 4,
-       Int64Align = 8
-};
+// +build plan9
 
+package runtime
+
+func close(fd int32) int32
+
+//go:noescape
+func open(name *byte, mode, perm int32) int32
index fb24d3e795c6fab6d264785b71b5f81da194f2dd..395f657bf796944a63ec9605c573db5a866b7ef2 100644 (file)
@@ -9,7 +9,8 @@
 // System calls and other sys.stuff for Power64, Linux
 //
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "textflag.h"
 
 #define SYS_exit                 1
diff --git a/src/runtime/sys_power64x.c b/src/runtime/sys_power64x.c
deleted file mode 100644 (file)
index 79d9762..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-// 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.
-
-// +build power64 power64le
-
-#include "runtime.h"
-
-// adjust Gobuf as if it executed a call to fn with context ctxt
-// and then did an immediate Gosave.
-void
-runtime·gostartcall(Gobuf *gobuf, void (*fn)(void), void *ctxt)
-{
-       if(gobuf->lr != 0)
-               runtime·throw("invalid use of gostartcall");
-       gobuf->lr = gobuf->pc;
-       gobuf->pc = (uintptr)fn;
-       gobuf->ctxt = ctxt;
-}
-
-// Called to rewind context saved during morestack back to beginning of function.
-// To help us, the linker emits a jmp back to the beginning right after the
-// call to morestack. We just have to decode and apply that jump.
-void
-runtime·rewindmorestack(Gobuf *gobuf)
-{
-       uint32 inst;
-
-       inst = *(uint32*)gobuf->pc;
-       if((gobuf->pc&3) == 0 && (inst>>24) == 0x4b && (inst&3) == 0) {
-               //runtime·printf("runtime: rewind pc=%p to pc=%p\n", gobuf->pc, gobuf->pc + ((int32)(inst<<8)>>8));
-               gobuf->pc += (int32)(inst<<8)>>8;
-               return;
-       }
-       runtime·printf("runtime: pc=%p %x\n", gobuf->pc, inst);
-       runtime·throw("runtime: misuse of rewindmorestack");
-}
-
diff --git a/src/runtime/sys_power64x.go b/src/runtime/sys_power64x.go
new file mode 100644 (file)
index 0000000..90ebde7
--- /dev/null
@@ -0,0 +1,37 @@
+// 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.
+
+// +build power64 power64le
+
+package runtime
+
+import "unsafe"
+
+// adjust Gobuf as if it executed a call to fn with context ctxt
+// and then did an immediate Gosave.
+func gostartcall(buf *gobuf, fn, ctxt unsafe.Pointer) {
+       if buf.lr != 0 {
+               gothrow("invalid use of gostartcall")
+       }
+       buf.lr = buf.pc
+       buf.pc = uintptr(fn)
+       buf.ctxt = ctxt
+}
+
+// Called to rewind context saved during morestack back to beginning of function.
+// To help us, the linker emits a jmp back to the beginning right after the
+// call to morestack. We just have to decode and apply that jump.
+func rewindmorestack(buf *gobuf) {
+       var inst uint32
+       if buf.pc&3 == 0 && buf.pc != 0 {
+               inst = *(*uint32)(unsafe.Pointer(buf.pc))
+               if inst>>26 == 18 && inst&3 == 0 {
+                       //print("runtime: rewind pc=", hex(buf.pc), " to pc=", hex(uintptr(buf.pc + int32(inst<<6)>>6)), "\n");
+                       buf.pc += uintptr(int32(inst<<6) >> 6)
+                       return
+               }
+       }
+       print("runtime: pc=", hex(buf.pc), " ", hex(inst), "\n")
+       gothrow("runtime: misuse of rewindmorestack")
+}
index 2793e5221628c3e64eab6bcf38478b05d11cbaff..c8a830cdf8e36fb6f649acc8e31a335cea5d3fd3 100644 (file)
@@ -44,7 +44,7 @@ TEXT  runtime·badsignal2(SB),NOSPLIT,$24
        // stderr
        MOVL    $-12, 0(SP)
        MOVL    SP, BP
-       CALL    *runtime·GetStdHandle(SB)
+       CALL    *runtime·_GetStdHandle(SB)
        MOVL    BP, SP
 
        MOVL    AX, 0(SP)       // handle
@@ -56,7 +56,7 @@ TEXT  runtime·badsignal2(SB),NOSPLIT,$24
        MOVL    $0, 0(DX)
        MOVL    DX, 12(SP)
        MOVL    $0, 16(SP) // overlapped
-       CALL    *runtime·WriteFile(SB)
+       CALL    *runtime·_WriteFile(SB)
        MOVL    BP, SI
        RET
 
@@ -208,7 +208,7 @@ TEXT runtime·externalthreadhandler(SB),NOSPLIT,$0
        MOVL    BX, g_m(SP)
        LEAL    -8192(SP), CX
        MOVL    CX, (g_stack+stack_lo)(SP)
-       ADDL    $const_StackGuard, CX
+       ADDL    $const__StackGuard, CX
        MOVL    CX, g_stackguard0(SP)
        MOVL    CX, g_stackguard1(SP)
        MOVL    DX, (g_stack+stack_hi)(SP)
@@ -255,8 +255,8 @@ TEXT runtime·callbackasm1+0(SB),NOSPLIT,$0
        MOVL    -4(BX)(AX*4), BX
 
        // extract callback context
-       MOVL    cbctxt_gobody(BX), AX
-       MOVL    cbctxt_argsize(BX), DX
+       MOVL    wincallbackcontext_gobody(BX), AX
+       MOVL    wincallbackcontext_argsize(BX), DX
 
        // preserve whatever's at the memory location that
        // the callback will use to store the return value
@@ -266,7 +266,7 @@ TEXT runtime·callbackasm1+0(SB),NOSPLIT,$0
        ADDL    $4, DX
 
        // remember how to restore stack on return
-       MOVL    cbctxt_restorestack(BX), BX
+       MOVL    wincallbackcontext_restorestack(BX), BX
        PUSHL   BX
 
        // call target Go function
@@ -314,7 +314,7 @@ TEXT runtime·tstart(SB),NOSPLIT,$0
        MOVL    AX, (g_stack+stack_hi)(DX)
        SUBL    $(64*1024), AX          // stack size
        MOVL    AX, (g_stack+stack_lo)(DX)
-       ADDL    $const_StackGuard, AX
+       ADDL    $const__StackGuard, AX
        MOVL    AX, g_stackguard0(DX)
        MOVL    AX, g_stackguard1(DX)
 
@@ -415,7 +415,7 @@ TEXT runtime·usleep2(SB),NOSPLIT,$20
        MOVL    $0, alertable-16(SP)
        MOVL    $-1, handle-20(SP)
        MOVL    SP, BP
-       MOVL    runtime·NtWaitForSingleObject(SB), AX
+       MOVL    runtime·_NtWaitForSingleObject(SB), AX
        CALL    AX
        MOVL    BP, SP
        RET
index 5e5c2e7f5a54109363412a73478413a9d45e727c..68f7cd3924d62d58441ff507d1fa35e5f20f7fc7 100644 (file)
@@ -66,7 +66,7 @@ TEXT runtime·badsignal2(SB),NOSPLIT,$48
        // stderr
        MOVQ    $-12, CX // stderr
        MOVQ    CX, 0(SP)
-       MOVQ    runtime·GetStdHandle(SB), AX
+       MOVQ    runtime·_GetStdHandle(SB), AX
        CALL    AX
 
        MOVQ    AX, CX  // handle
@@ -79,7 +79,7 @@ TEXT runtime·badsignal2(SB),NOSPLIT,$48
        MOVQ    $0, 0(R9)
        MOVQ    R9, 24(SP)
        MOVQ    $0, 32(SP)      // overlapped
-       MOVQ    runtime·WriteFile(SB), AX
+       MOVQ    runtime·_WriteFile(SB), AX
        CALL    AX
        
        RET
@@ -245,7 +245,7 @@ TEXT runtime·externalthreadhandler(SB),NOSPLIT,$0
 
        LEAQ    -8192(SP), CX
        MOVQ    CX, (g_stack+stack_lo)(SP)
-       ADDQ    $const_StackGuard, CX
+       ADDQ    $const__StackGuard, CX
        MOVQ    CX, g_stackguard0(SP)
        MOVQ    CX, g_stackguard1(SP)
        MOVQ    DX, (g_stack+stack_hi)(SP)
@@ -294,8 +294,8 @@ TEXT runtime·callbackasm1(SB),NOSPLIT,$0
        MOVQ    -8(CX)(AX*8), AX
 
        // extract callback context
-       MOVQ    cbctxt_argsize(AX), DX
-       MOVQ    cbctxt_gobody(AX), AX
+       MOVQ    wincallbackcontext_argsize(AX), DX
+       MOVQ    wincallbackcontext_gobody(AX), AX
 
        // preserve whatever's at the memory location that
        // the callback will use to store the return value
@@ -355,7 +355,7 @@ TEXT runtime·tstart_stdcall(SB),NOSPLIT,$0
        MOVQ    AX, (g_stack+stack_hi)(DX)
        SUBQ    $(64*1024), AX          // stack size
        MOVQ    AX, (g_stack+stack_lo)(DX)
-       ADDQ    $const_StackGuard, AX
+       ADDQ    $const__StackGuard, AX
        MOVQ    AX, g_stackguard0(DX)
        MOVQ    AX, g_stackguard1(DX)
 
@@ -436,7 +436,7 @@ TEXT runtime·usleep2(SB),NOSPLIT,$16
        MOVQ    BX, (R8)
        MOVQ    $-1, CX // handle
        MOVQ    $0, DX // alertable
-       MOVQ    runtime·NtWaitForSingleObject(SB), AX
+       MOVQ    runtime·_NtWaitForSingleObject(SB), AX
        CALL    AX
        MOVQ    8(SP), SP
        RET
index efbcab510dad875dc2ee8decd33b96304a5ff43f..661ee59d7b5f419c63fc2a5aa75406def6a2a499 100644 (file)
@@ -41,20 +41,20 @@ func callbackasmAddr(i int) uintptr {
 
 func compileCallback(fn eface, cleanstack bool) (code uintptr) {
        if fn._type == nil || (fn._type.kind&kindMask) != kindFunc {
-               panic("compilecallback: not a function")
+               panic("compileCallback: not a function")
        }
        ft := (*functype)(unsafe.Pointer(fn._type))
-       if len(ft.out) != 1 {
-               panic("compilecallback: function must have one output parameter")
+       if ft.out.len != 1 {
+               panic("compileCallback: function must have one output parameter")
        }
        uintptrSize := unsafe.Sizeof(uintptr(0))
-       if t := (**_type)(unsafe.Pointer(&ft.out[0])); (*t).size != uintptrSize {
-               panic("compilecallback: output parameter size is wrong")
+       if t := (**_type)(unsafe.Pointer(ft.out.array)); (*t).size != uintptrSize {
+               panic("compileCallback: output parameter size is wrong")
        }
        argsize := uintptr(0)
-       for _, t := range (*[1024](*_type))(unsafe.Pointer(&ft.in[0]))[:len(ft.in)] {
+       for _, t := range (*[1024](*_type))(unsafe.Pointer(ft.in.array))[:ft.in.len] {
                if (*t).size > uintptrSize {
-                       panic("compilecallback: input parameter size is wrong")
+                       panic("compileCallback: input parameter size is wrong")
                }
                argsize += uintptrSize
        }
@@ -87,8 +87,6 @@ func compileCallback(fn eface, cleanstack bool) (code uintptr) {
        return callbackasmAddr(n)
 }
 
-func getLoadLibrary() uintptr
-
 //go:nosplit
 func syscall_loadlibrary(filename *uint16) (handle, err uintptr) {
        var c libcall
@@ -103,8 +101,6 @@ func syscall_loadlibrary(filename *uint16) (handle, err uintptr) {
        return
 }
 
-func getGetProcAddress() uintptr
-
 //go:nosplit
 func syscall_getprocaddress(handle uintptr, procname *byte) (outhandle, err uintptr) {
        var c libcall
diff --git a/src/runtime/zgoarch_386.go b/src/runtime/zgoarch_386.go
new file mode 100644 (file)
index 0000000..057a746
--- /dev/null
@@ -0,0 +1,12 @@
+// generated by gengoos.go using 'go generate'
+
+package runtime
+
+const theGoarch = `386`
+
+const goarch_386 = 1
+const goarch_amd64 = 0
+const goarch_amd64p32 = 0
+const goarch_arm = 0
+const goarch_power64 = 0
+const goarch_power64le = 0
diff --git a/src/runtime/zgoarch_amd64.go b/src/runtime/zgoarch_amd64.go
new file mode 100644 (file)
index 0000000..a712407
--- /dev/null
@@ -0,0 +1,12 @@
+// generated by gengoos.go using 'go generate'
+
+package runtime
+
+const theGoarch = `amd64`
+
+const goarch_386 = 0
+const goarch_amd64 = 1
+const goarch_amd64p32 = 0
+const goarch_arm = 0
+const goarch_power64 = 0
+const goarch_power64le = 0
diff --git a/src/runtime/zgoarch_amd64p32.go b/src/runtime/zgoarch_amd64p32.go
new file mode 100644 (file)
index 0000000..2b6a142
--- /dev/null
@@ -0,0 +1,12 @@
+// generated by gengoos.go using 'go generate'
+
+package runtime
+
+const theGoarch = `amd64p32`
+
+const goarch_386 = 0
+const goarch_amd64 = 0
+const goarch_amd64p32 = 1
+const goarch_arm = 0
+const goarch_power64 = 0
+const goarch_power64le = 0
diff --git a/src/runtime/zgoarch_arm.go b/src/runtime/zgoarch_arm.go
new file mode 100644 (file)
index 0000000..4030210
--- /dev/null
@@ -0,0 +1,12 @@
+// generated by gengoos.go using 'go generate'
+
+package runtime
+
+const theGoarch = `arm`
+
+const goarch_386 = 0
+const goarch_amd64 = 0
+const goarch_amd64p32 = 0
+const goarch_arm = 1
+const goarch_power64 = 0
+const goarch_power64le = 0
diff --git a/src/runtime/zgoarch_power64.go b/src/runtime/zgoarch_power64.go
new file mode 100644 (file)
index 0000000..cc361f0
--- /dev/null
@@ -0,0 +1,12 @@
+// generated by gengoos.go using 'go generate'
+
+package runtime
+
+const theGoarch = `power64`
+
+const goarch_386 = 0
+const goarch_amd64 = 0
+const goarch_amd64p32 = 0
+const goarch_arm = 0
+const goarch_power64 = 1
+const goarch_power64le = 0
diff --git a/src/runtime/zgoarch_power64le.go b/src/runtime/zgoarch_power64le.go
new file mode 100644 (file)
index 0000000..41294e6
--- /dev/null
@@ -0,0 +1,12 @@
+// generated by gengoos.go using 'go generate'
+
+package runtime
+
+const theGoarch = `power64le`
+
+const goarch_386 = 0
+const goarch_amd64 = 0
+const goarch_amd64p32 = 0
+const goarch_arm = 0
+const goarch_power64 = 0
+const goarch_power64le = 1
diff --git a/src/runtime/zgoos_android.go b/src/runtime/zgoos_android.go
new file mode 100644 (file)
index 0000000..0590bd9
--- /dev/null
@@ -0,0 +1,17 @@
+// generated by gengoos.go using 'go generate'
+
+package runtime
+
+const theGoos = `android`
+
+const goos_android = 1
+const goos_darwin = 0
+const goos_dragonfly = 0
+const goos_freebsd = 0
+const goos_linux = 0
+const goos_nacl = 0
+const goos_netbsd = 0
+const goos_openbsd = 0
+const goos_plan9 = 0
+const goos_solaris = 0
+const goos_windows = 0
diff --git a/src/runtime/zgoos_darwin.go b/src/runtime/zgoos_darwin.go
new file mode 100644 (file)
index 0000000..c0a7cd6
--- /dev/null
@@ -0,0 +1,17 @@
+// generated by gengoos.go using 'go generate'
+
+package runtime
+
+const theGoos = `darwin`
+
+const goos_android = 0
+const goos_darwin = 1
+const goos_dragonfly = 0
+const goos_freebsd = 0
+const goos_linux = 0
+const goos_nacl = 0
+const goos_netbsd = 0
+const goos_openbsd = 0
+const goos_plan9 = 0
+const goos_solaris = 0
+const goos_windows = 0
diff --git a/src/runtime/zgoos_dragonfly.go b/src/runtime/zgoos_dragonfly.go
new file mode 100644 (file)
index 0000000..008d6de
--- /dev/null
@@ -0,0 +1,17 @@
+// generated by gengoos.go using 'go generate'
+
+package runtime
+
+const theGoos = `dragonfly`
+
+const goos_android = 0
+const goos_darwin = 0
+const goos_dragonfly = 1
+const goos_freebsd = 0
+const goos_linux = 0
+const goos_nacl = 0
+const goos_netbsd = 0
+const goos_openbsd = 0
+const goos_plan9 = 0
+const goos_solaris = 0
+const goos_windows = 0
diff --git a/src/runtime/zgoos_freebsd.go b/src/runtime/zgoos_freebsd.go
new file mode 100644 (file)
index 0000000..2478940
--- /dev/null
@@ -0,0 +1,17 @@
+// generated by gengoos.go using 'go generate'
+
+package runtime
+
+const theGoos = `freebsd`
+
+const goos_android = 0
+const goos_darwin = 0
+const goos_dragonfly = 0
+const goos_freebsd = 1
+const goos_linux = 0
+const goos_nacl = 0
+const goos_netbsd = 0
+const goos_openbsd = 0
+const goos_plan9 = 0
+const goos_solaris = 0
+const goos_windows = 0
diff --git a/src/runtime/zgoos_linux.go b/src/runtime/zgoos_linux.go
new file mode 100644 (file)
index 0000000..c775ab5
--- /dev/null
@@ -0,0 +1,19 @@
+// generated by gengoos.go using 'go generate'
+
+// +build !android
+
+package runtime
+
+const theGoos = `linux`
+
+const goos_android = 0
+const goos_darwin = 0
+const goos_dragonfly = 0
+const goos_freebsd = 0
+const goos_linux = 1
+const goos_nacl = 0
+const goos_netbsd = 0
+const goos_openbsd = 0
+const goos_plan9 = 0
+const goos_solaris = 0
+const goos_windows = 0
diff --git a/src/runtime/zgoos_nacl.go b/src/runtime/zgoos_nacl.go
new file mode 100644 (file)
index 0000000..d9d88f4
--- /dev/null
@@ -0,0 +1,17 @@
+// generated by gengoos.go using 'go generate'
+
+package runtime
+
+const theGoos = `nacl`
+
+const goos_android = 0
+const goos_darwin = 0
+const goos_dragonfly = 0
+const goos_freebsd = 0
+const goos_linux = 0
+const goos_nacl = 1
+const goos_netbsd = 0
+const goos_openbsd = 0
+const goos_plan9 = 0
+const goos_solaris = 0
+const goos_windows = 0
diff --git a/src/runtime/zgoos_netbsd.go b/src/runtime/zgoos_netbsd.go
new file mode 100644 (file)
index 0000000..ff2c5cb
--- /dev/null
@@ -0,0 +1,17 @@
+// generated by gengoos.go using 'go generate'
+
+package runtime
+
+const theGoos = `netbsd`
+
+const goos_android = 0
+const goos_darwin = 0
+const goos_dragonfly = 0
+const goos_freebsd = 0
+const goos_linux = 0
+const goos_nacl = 0
+const goos_netbsd = 1
+const goos_openbsd = 0
+const goos_plan9 = 0
+const goos_solaris = 0
+const goos_windows = 0
diff --git a/src/runtime/zgoos_openbsd.go b/src/runtime/zgoos_openbsd.go
new file mode 100644 (file)
index 0000000..b071dc6
--- /dev/null
@@ -0,0 +1,17 @@
+// generated by gengoos.go using 'go generate'
+
+package runtime
+
+const theGoos = `openbsd`
+
+const goos_android = 0
+const goos_darwin = 0
+const goos_dragonfly = 0
+const goos_freebsd = 0
+const goos_linux = 0
+const goos_nacl = 0
+const goos_netbsd = 0
+const goos_openbsd = 1
+const goos_plan9 = 0
+const goos_solaris = 0
+const goos_windows = 0
diff --git a/src/runtime/zgoos_plan9.go b/src/runtime/zgoos_plan9.go
new file mode 100644 (file)
index 0000000..4306b0f
--- /dev/null
@@ -0,0 +1,17 @@
+// generated by gengoos.go using 'go generate'
+
+package runtime
+
+const theGoos = `plan9`
+
+const goos_android = 0
+const goos_darwin = 0
+const goos_dragonfly = 0
+const goos_freebsd = 0
+const goos_linux = 0
+const goos_nacl = 0
+const goos_netbsd = 0
+const goos_openbsd = 0
+const goos_plan9 = 1
+const goos_solaris = 0
+const goos_windows = 0
diff --git a/src/runtime/zgoos_solaris.go b/src/runtime/zgoos_solaris.go
new file mode 100644 (file)
index 0000000..10f9537
--- /dev/null
@@ -0,0 +1,17 @@
+// generated by gengoos.go using 'go generate'
+
+package runtime
+
+const theGoos = `solaris`
+
+const goos_android = 0
+const goos_darwin = 0
+const goos_dragonfly = 0
+const goos_freebsd = 0
+const goos_linux = 0
+const goos_nacl = 0
+const goos_netbsd = 0
+const goos_openbsd = 0
+const goos_plan9 = 0
+const goos_solaris = 1
+const goos_windows = 0
diff --git a/src/runtime/zgoos_windows.go b/src/runtime/zgoos_windows.go
new file mode 100644 (file)
index 0000000..56f5c58
--- /dev/null
@@ -0,0 +1,17 @@
+// generated by gengoos.go using 'go generate'
+
+package runtime
+
+const theGoos = `windows`
+
+const goos_android = 0
+const goos_darwin = 0
+const goos_dragonfly = 0
+const goos_freebsd = 0
+const goos_linux = 0
+const goos_nacl = 0
+const goos_netbsd = 0
+const goos_openbsd = 0
+const goos_plan9 = 0
+const goos_solaris = 0
+const goos_windows = 1
index 7c2c1f7071a8094a43ff89ccb73a42ea103849ef..ff78f197f1fb30af337e1618264f56aa701a1302 100644 (file)
@@ -19,8 +19,6 @@ type SysProcAttr struct {
        Setpgid    bool        // Set process group ID to new pid (SYSV setpgrp)
        Setctty    bool        // Set controlling terminal to fd 0
        Noctty     bool        // Detach fd 0 from controlling terminal
-       Foreground bool        // Set foreground process group to child's pid. (Implies Setpgid. Stdin should be a TTY)
-       Joinpgrp   int         // If != 0, child's process group ID. (Setpgid must not be set)
 }
 
 // Implemented in runtime package.
@@ -81,22 +79,7 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
        if r1 != 0 {
                // parent; return PID
                runtime_AfterFork()
-               pid = int(r1)
-
-               if sys.Joinpgrp != 0 {
-                       // Place the child in the specified process group.
-                       RawSyscall(SYS_SETPGID, r1, uintptr(sys.Joinpgrp), 0)
-               } else if sys.Foreground || sys.Setpgid {
-                       // Place the child in a new process group.
-                       RawSyscall(SYS_SETPGID, 0, 0, 0)
-
-                       if sys.Foreground {
-                               // Set new foreground process group.
-                               RawSyscall(SYS_IOCTL, uintptr(Stdin), TIOCSPGRP, uintptr(unsafe.Pointer(&pid)))
-                       }
-               }
-
-               return pid, 0
+               return int(r1), 0
        }
 
        // Fork succeeded, now in child.
@@ -118,30 +101,11 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
        }
 
        // Set process group
-       if sys.Joinpgrp != 0 {
-               // Place the child in the specified process group.
-               _, _, err1 = RawSyscall(SYS_SETPGID, r1, uintptr(sys.Joinpgrp), 0)
-               if err1 != 0 {
-                       goto childerror
-               }
-       } else if sys.Foreground || sys.Setpgid {
-               // Place the child in a new process group.
+       if sys.Setpgid {
                _, _, err1 = RawSyscall(SYS_SETPGID, 0, 0, 0)
                if err1 != 0 {
                        goto childerror
                }
-
-               if sys.Foreground {
-                       r1, _, _ = RawSyscall(SYS_GETPID, 0, 0, 0)
-
-                       pid := int(r1)
-
-                       // Set new foreground process group.
-                       _, _, err1 = RawSyscall(SYS_IOCTL, uintptr(Stdin), TIOCSPGRP, uintptr(unsafe.Pointer(&pid)))
-                       if err1 != 0 {
-                               goto childerror
-                       }
-               }
        }
 
        // Chroot
index 72e2f0b69c82f64bf191515d6af4d5bc9d8949b6..042c20a46812feb1d88e0f928e7e61382480e64a 100644 (file)
@@ -29,8 +29,6 @@ type SysProcAttr struct {
        Ctty        int            // Controlling TTY fd (Linux only)
        Pdeathsig   Signal         // Signal that the process will get when its parent dies (Linux only)
        Cloneflags  uintptr        // Flags for clone calls (Linux only)
-       Foreground  bool           // Set foreground process group to child's pid. (Implies Setpgid. Stdin should be a TTY)
-       Joinpgrp    int            // If != 0, child's process group ID. (Setpgid must not be set)
        UidMappings []SysProcIDMap // User ID mappings for user namespaces.
        GidMappings []SysProcIDMap // Group ID mappings for user namespaces.
 }
@@ -105,19 +103,6 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
                        Close(p[1])
                }
 
-               if sys.Joinpgrp != 0 {
-                       // Place the child in the specified process group.
-                       RawSyscall(SYS_SETPGID, r1, uintptr(sys.Joinpgrp), 0)
-               } else if sys.Foreground || sys.Setpgid {
-                       // Place the child in a new process group.
-                       RawSyscall(SYS_SETPGID, 0, 0, 0)
-
-                       if sys.Foreground {
-                               // Set new foreground process group.
-                               RawSyscall(SYS_IOCTL, uintptr(Stdin), TIOCSPGRP, uintptr(unsafe.Pointer(&pid)))
-                       }
-               }
-
                return pid, 0
        }
 
@@ -179,30 +164,11 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
        }
 
        // Set process group
-       if sys.Joinpgrp != 0 {
-               // Place the child in the specified process group.
-               _, _, err1 = RawSyscall(SYS_SETPGID, r1, uintptr(sys.Joinpgrp), 0)
-               if err1 != 0 {
-                       goto childerror
-               }
-       } else if sys.Foreground || sys.Setpgid {
-               // Place the child in a new process group.
+       if sys.Setpgid {
                _, _, err1 = RawSyscall(SYS_SETPGID, 0, 0, 0)
                if err1 != 0 {
                        goto childerror
                }
-
-               if sys.Foreground {
-                       r1, _, _ = RawSyscall(SYS_GETPID, 0, 0, 0)
-
-                       pid := int(r1)
-
-                       // Set new foreground process group.
-                       _, _, err1 = RawSyscall(SYS_IOCTL, uintptr(Stdin), TIOCSPGRP, uintptr(unsafe.Pointer(&pid)))
-                       if err1 != 0 {
-                               goto childerror
-                       }
-               }
        }
 
        // Chroot
diff --git a/test/fixedbugs/issue9110.go b/test/fixedbugs/issue9110.go
new file mode 100644 (file)
index 0000000..7294633
--- /dev/null
@@ -0,0 +1,90 @@
+// run
+
+// 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.
+
+// Scenario that used to leak arbitrarily many SudoG structs.
+// See golang.org/issue/9110.
+
+package main
+
+import (
+       "runtime"
+       "runtime/debug"
+       "sync"
+       "time"
+)
+
+func main() {
+       debug.SetGCPercent(1000000) // only GC when we ask for GC
+
+       var stats, stats1, stats2 runtime.MemStats
+
+       release := func() {}
+       for i := 0; i < 20; i++ {
+               if i == 10 {
+                       // Should be warmed up by now.
+                       runtime.ReadMemStats(&stats1)
+               }
+
+               c := make(chan int)
+               for i := 0; i < 10; i++ {
+                       go func() {
+                               select {
+                               case <-c:
+                               case <-c:
+                               case <-c:
+                               }
+                       }()
+               }
+               time.Sleep(1 * time.Millisecond)
+               release()
+
+               close(c) // let select put its sudog's into the cache
+               time.Sleep(1 * time.Millisecond)
+
+               // pick up top sudog
+               var cond1 sync.Cond
+               var mu1 sync.Mutex
+               cond1.L = &mu1
+               go func() {
+                       mu1.Lock()
+                       cond1.Wait()
+                       mu1.Unlock()
+               }()
+               time.Sleep(1 * time.Millisecond)
+
+               // pick up next sudog
+               var cond2 sync.Cond
+               var mu2 sync.Mutex
+               cond2.L = &mu2
+               go func() {
+                       mu2.Lock()
+                       cond2.Wait()
+                       mu2.Unlock()
+               }()
+               time.Sleep(1 * time.Millisecond)
+
+               // put top sudog back
+               cond1.Broadcast()
+               time.Sleep(1 * time.Millisecond)
+
+               // drop cache on floor
+               runtime.GC()
+
+               // release cond2 after select has gotten to run
+               release = func() {
+                       cond2.Broadcast()
+                       time.Sleep(1 * time.Millisecond)
+               }
+       }
+
+       runtime.GC()
+
+       runtime.ReadMemStats(&stats2)
+
+       if int(stats2.HeapObjects)-int(stats1.HeapObjects) > 20 { // normally at most 1 or 2; was 300 with leak
+               print("BUG: object leak: ", stats.HeapObjects, " -> ", stats1.HeapObjects, " -> ", stats2.HeapObjects, "\n")
+       }
+}