summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2014-11-24 12:07:11 -0500
committerRuss Cox <rsc@golang.org>2014-11-24 12:07:11 -0500
commite5fc9ffb729e31c4eb0a6518e819e9fc70f14818 (patch)
tree5f67f9fb6c209085505b8fa6a01a245942ea45c3
parentdf7d4576f312e1b646af4f5f1a32412a4221b785 (diff)
parentdb6a11ff558add790779fdef118b5ad899f77137 (diff)
downloadgo-e5fc9ffb729e31c4eb0a6518e819e9fc70f14818.tar.gz
[dev.garbage] all: merge dev.cc (493ad916c3b1) into dev.garbage
TBR=austin CC=golang-codereviews https://codereview.appspot.com/179290043
-rw-r--r--AUTHORS2
-rw-r--r--CONTRIBUTORS3
-rw-r--r--doc/go1.4.html65
-rw-r--r--doc/go_spec.html68
-rw-r--r--doc/gopher/fiveyears.jpgbin0 -> 220526 bytes
-rw-r--r--doc/install.html2
-rw-r--r--include/link.h9
-rw-r--r--misc/makerelease/makerelease.go4
-rw-r--r--src/cmd/5g/opt.h30
-rw-r--r--src/cmd/5g/reg.c47
-rw-r--r--src/cmd/5l/5.out.h2
-rw-r--r--src/cmd/6g/opt.h32
-rw-r--r--src/cmd/6g/reg.c43
-rw-r--r--src/cmd/6l/6.out.h2
-rw-r--r--src/cmd/8g/opt.h32
-rw-r--r--src/cmd/8g/reg.c53
-rw-r--r--src/cmd/8l/8.out.h2
-rw-r--r--src/cmd/9a/lex.c3
-rw-r--r--src/cmd/9c/Makefile5
-rw-r--r--src/cmd/9c/Notes14
-rw-r--r--src/cmd/9c/cgen.c1147
-rw-r--r--src/cmd/9c/doc.go17
-rw-r--r--src/cmd/9c/gc.h350
-rw-r--r--src/cmd/9c/list.c37
-rw-r--r--src/cmd/9c/machcap.c105
-rw-r--r--src/cmd/9c/mul.c638
-rw-r--r--src/cmd/9c/peep.c1076
-rw-r--r--src/cmd/9c/reg.c1163
-rw-r--r--src/cmd/9c/sgen.c291
-rw-r--r--src/cmd/9c/swt.c407
-rw-r--r--src/cmd/9c/txt.c1537
-rw-r--r--src/cmd/9g/prog.c9
-rw-r--r--src/cmd/9g/reg.c7
-rw-r--r--src/cmd/9l/9.out.h2
-rw-r--r--src/cmd/cgo/doc.go2
-rw-r--r--src/cmd/dist/build.c7
-rw-r--r--src/cmd/dist/buildgc.c87
-rw-r--r--src/cmd/dist/buildruntime.c60
-rw-r--r--src/cmd/gc/walk.c1
-rw-r--r--src/cmd/go/tool.go12
-rw-r--r--src/cmd/internal/goobj/read.go (renamed from src/debug/goobj/read.go)0
-rw-r--r--src/cmd/internal/goobj/read_test.go (renamed from src/debug/goobj/read_test.go)0
-rw-r--r--src/cmd/internal/objfile/goobj.go2
-rw-r--r--src/cmd/link/auto.go2
-rw-r--r--src/cmd/link/auto_test.go2
-rw-r--r--src/cmd/link/dead.go2
-rw-r--r--src/cmd/link/dead_test.go2
-rw-r--r--src/cmd/link/layout.go2
-rw-r--r--src/cmd/link/link_test.go2
-rw-r--r--src/cmd/link/pclntab.go2
-rw-r--r--src/cmd/link/pclntab_test.go2
-rw-r--r--src/cmd/link/prog.go2
-rw-r--r--src/cmd/link/runtime.go2
-rw-r--r--src/cmd/link/scan.go4
-rw-r--r--src/cmd/pprof/internal/report/source.go6
-rw-r--r--src/crypto/x509/root_unix.go1
-rw-r--r--src/go/parser/error_test.go27
-rw-r--r--src/go/parser/parser_test.go20
-rw-r--r--src/hash/crc32/crc32.go4
-rw-r--r--src/image/jpeg/reader.go3
-rw-r--r--src/image/jpeg/reader_test.go46
-rw-r--r--src/liblink/list6.c38
-rw-r--r--src/liblink/list9.c41
-rw-r--r--src/net/http/fs.go8
-rw-r--r--src/net/url/example_test.go30
-rw-r--r--src/regexp/syntax/regexp.go2
-rwxr-xr-xsrc/run.bash38
-rw-r--r--src/run.bat8
-rw-r--r--src/runtime/arch1_386.go2
-rw-r--r--src/runtime/arch1_amd64.go2
-rw-r--r--src/runtime/arch1_amd64p32.go15
-rw-r--r--src/runtime/arch1_arm.go2
-rw-r--r--src/runtime/arch1_power64.go15
-rw-r--r--src/runtime/arch1_power64le.go15
-rw-r--r--src/runtime/arch_amd64p32.h17
-rw-r--r--src/runtime/arch_power64.h14
-rw-r--r--src/runtime/asm_amd64p32.s2
-rw-r--r--src/runtime/asm_power64x.s59
-rw-r--r--src/runtime/atomic_power64x.go69
-rw-r--r--src/runtime/chan.go1
-rw-r--r--src/runtime/defs1_netbsd_386.go22
-rw-r--r--src/runtime/defs1_netbsd_amd64.go20
-rw-r--r--src/runtime/defs_linux_386.go9
-rw-r--r--src/runtime/defs_linux_amd64.go10
-rw-r--r--src/runtime/defs_linux_arm.go9
-rw-r--r--src/runtime/defs_linux_power64.go198
-rw-r--r--src/runtime/defs_linux_power64.h204
-rw-r--r--src/runtime/defs_linux_power64le.go198
-rw-r--r--src/runtime/defs_linux_power64le.h204
-rw-r--r--src/runtime/defs_plan9_386.go2
-rw-r--r--src/runtime/defs_plan9_amd64.go2
-rw-r--r--src/runtime/env_plan9.go3
-rw-r--r--src/runtime/gengoos.go84
-rw-r--r--src/runtime/heapdump.go2
-rw-r--r--src/runtime/lfstack.go4
-rw-r--r--src/runtime/lfstack_32bit.go2
-rw-r--r--src/runtime/lfstack_linux_power64x.go20
-rw-r--r--src/runtime/malloc.go11
-rw-r--r--src/runtime/malloc2.go2
-rw-r--r--src/runtime/mem_bsd.go4
-rw-r--r--src/runtime/mem_nacl.c120
-rw-r--r--src/runtime/mem_plan9.c121
-rw-r--r--src/runtime/mem_plan9.go70
-rw-r--r--src/runtime/mgc0.go16
-rw-r--r--src/runtime/netpoll_stub.go (renamed from src/runtime/netpoll_stub.c)9
-rw-r--r--src/runtime/netpoll_windows.go4
-rw-r--r--src/runtime/os1_nacl.go197
-rw-r--r--src/runtime/os1_netbsd.go265
-rw-r--r--src/runtime/os1_netbsd_386.go16
-rw-r--r--src/runtime/os1_netbsd_amd64.go16
-rw-r--r--src/runtime/os1_plan9.go270
-rw-r--r--src/runtime/os1_windows.go564
-rw-r--r--src/runtime/os1_windows_386.go118
-rw-r--r--src/runtime/os1_windows_amd64.go137
-rw-r--r--src/runtime/os2_nacl.go154
-rw-r--r--src/runtime/os2_netbsd.go18
-rw-r--r--src/runtime/os2_plan9.go72
-rw-r--r--src/runtime/os2_windows.go25
-rw-r--r--src/runtime/os_android.h1
-rw-r--r--src/runtime/os_android_arm.go (renamed from src/runtime/os_android.c)11
-rw-r--r--src/runtime/os_nacl.c315
-rw-r--r--src/runtime/os_nacl.go21
-rw-r--r--src/runtime/os_nacl.h162
-rw-r--r--src/runtime/os_nacl_arm.go (renamed from src/runtime/os_nacl_arm.c)19
-rw-r--r--src/runtime/os_netbsd.c371
-rw-r--r--src/runtime/os_netbsd.go32
-rw-r--r--src/runtime/os_netbsd.h31
-rw-r--r--src/runtime/os_netbsd_386.c17
-rw-r--r--src/runtime/os_netbsd_amd64.c18
-rw-r--r--src/runtime/os_plan9.c368
-rw-r--r--src/runtime/os_plan9.go27
-rw-r--r--src/runtime/os_plan9.h93
-rw-r--r--src/runtime/os_plan9_386.c150
-rw-r--r--src/runtime/os_plan9_386.go131
-rw-r--r--src/runtime/os_plan9_amd64.c158
-rw-r--r--src/runtime/os_plan9_amd64.go139
-rw-r--r--src/runtime/os_windows.c636
-rw-r--r--src/runtime/os_windows.go16
-rw-r--r--src/runtime/os_windows.h42
-rw-r--r--src/runtime/os_windows_386.c128
-rw-r--r--src/runtime/os_windows_amd64.c150
-rw-r--r--src/runtime/panic.go2
-rw-r--r--src/runtime/proc.go22
-rw-r--r--src/runtime/race/race_unix_test.go30
-rw-r--r--src/runtime/race1.go37
-rw-r--r--src/runtime/race_amd64.s43
-rw-r--r--src/runtime/runtime2.go16
-rw-r--r--src/runtime/select.go2
-rw-r--r--src/runtime/sema.go2
-rw-r--r--src/runtime/signal_android_386.h1
-rw-r--r--src/runtime/signal_android_arm.h1
-rw-r--r--src/runtime/signal_linux_386.go2
-rw-r--r--src/runtime/signal_linux_amd64.go2
-rw-r--r--src/runtime/signal_linux_arm.go2
-rw-r--r--src/runtime/signal_linux_power64.h49
-rw-r--r--src/runtime/signal_linux_power64le.h49
-rw-r--r--src/runtime/signal_linux_power64x.go71
-rw-r--r--src/runtime/signal_nacl.go45
-rw-r--r--src/runtime/signal_nacl_386.go34
-rw-r--r--src/runtime/signal_nacl_386.h23
-rw-r--r--src/runtime/signal_nacl_amd64p32.go44
-rw-r--r--src/runtime/signal_nacl_amd64p32.h31
-rw-r--r--src/runtime/signal_nacl_arm.go47
-rw-r--r--src/runtime/signal_nacl_arm.h28
-rw-r--r--src/runtime/signal_netbsd.go46
-rw-r--r--src/runtime/signal_netbsd_386.go38
-rw-r--r--src/runtime/signal_netbsd_386.h23
-rw-r--r--src/runtime/signal_netbsd_amd64.go48
-rw-r--r--src/runtime/signal_netbsd_amd64.h31
-rw-r--r--src/runtime/signal_plan9.go (renamed from src/runtime/signals_plan9.h)57
-rw-r--r--src/runtime/signal_power64x.c137
-rw-r--r--src/runtime/signal_power64x.go144
-rw-r--r--src/runtime/signals_android.h1
-rw-r--r--src/runtime/signals_nacl.h53
-rw-r--r--src/runtime/signals_netbsd.h54
-rw-r--r--src/runtime/stack1.go2
-rw-r--r--src/runtime/stack2.go2
-rw-r--r--src/runtime/stubs.go2
-rw-r--r--src/runtime/stubs2.go3
-rw-r--r--src/runtime/stubs3.go (renamed from src/runtime/arch_power64le.h)16
-rw-r--r--src/runtime/sys_linux_power64x.s3
-rw-r--r--src/runtime/sys_power64x.c38
-rw-r--r--src/runtime/sys_power64x.go37
-rw-r--r--src/runtime/sys_windows_386.s16
-rw-r--r--src/runtime/sys_windows_amd64.s14
-rw-r--r--src/runtime/syscall_windows.go18
-rw-r--r--src/runtime/zgoarch_386.go12
-rw-r--r--src/runtime/zgoarch_amd64.go12
-rw-r--r--src/runtime/zgoarch_amd64p32.go12
-rw-r--r--src/runtime/zgoarch_arm.go12
-rw-r--r--src/runtime/zgoarch_power64.go12
-rw-r--r--src/runtime/zgoarch_power64le.go12
-rw-r--r--src/runtime/zgoos_android.go17
-rw-r--r--src/runtime/zgoos_darwin.go17
-rw-r--r--src/runtime/zgoos_dragonfly.go17
-rw-r--r--src/runtime/zgoos_freebsd.go17
-rw-r--r--src/runtime/zgoos_linux.go19
-rw-r--r--src/runtime/zgoos_nacl.go17
-rw-r--r--src/runtime/zgoos_netbsd.go17
-rw-r--r--src/runtime/zgoos_openbsd.go17
-rw-r--r--src/runtime/zgoos_plan9.go17
-rw-r--r--src/runtime/zgoos_solaris.go17
-rw-r--r--src/runtime/zgoos_windows.go17
-rw-r--r--src/syscall/exec_bsd.go40
-rw-r--r--src/syscall/exec_linux.go36
-rw-r--r--test/fixedbugs/issue9110.go90
206 files changed, 4733 insertions, 11182 deletions
diff --git a/AUTHORS b/AUTHORS
index 48a262bbd..46fd9fd29 100644
--- 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>
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index ec69858b6..b5e709ed6 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -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>
diff --git a/doc/go1.4.html b/doc/go1.4.html
index ac63ade60..883352e34 100644
--- a/doc/go1.4.html
+++ b/doc/go1.4.html
@@ -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
@@ -638,11 +638,28 @@ 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>
@@ -666,6 +683,16 @@ 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.
</li>
@@ -686,6 +713,11 @@ 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
to structs, arrays, and so on.
@@ -694,6 +726,28 @@ For instance, <code>&amp;map[string]int{"one":</code> <code>1}</code> now prints
</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
has a new <a href="/pkg/net/http/#Request.BasicAuth"><code>BasicAuth</code></a> method
@@ -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>
diff --git a/doc/go_spec.html b/doc/go_spec.html
index 050c06465..ca0deb56a 100644
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -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
@@ -2554,18 +2564,6 @@ causes a <a href="#Run_time_panics">run-time panic</a>.
</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
index 000000000..df1064868
--- /dev/null
+++ b/doc/gopher/fiveyears.jpg
Binary files differ
diff --git a/doc/install.html b/doc/install.html
index d6984c244..9561fdde2 100644
--- a/doc/install.html
+++ b/doc/install.html
@@ -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>
diff --git a/include/link.h b/include/link.h
index 06f3ebb48..2b1d02102 100644
--- a/include/link.h
+++ b/include/link.h
@@ -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*
diff --git a/misc/makerelease/makerelease.go b/misc/makerelease/makerelease.go
index e94efdbce..8cf6be2a4 100644
--- a/misc/makerelease/makerelease.go
+++ b/misc/makerelease/makerelease.go
@@ -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.
diff --git a/src/cmd/5g/opt.h b/src/cmd/5g/opt.h
index 5016d1cc8..a606f1d31 100644
--- a/src/cmd/5g/opt.h
+++ b/src/cmd/5g/opt.h
@@ -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,
diff --git a/src/cmd/5g/reg.c b/src/cmd/5g/reg.c
index 441792873..611310f12 100644
--- a/src/cmd/5g/reg.c
+++ b/src/cmd/5g/reg.c
@@ -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");
+ }
}
}
diff --git a/src/cmd/5l/5.out.h b/src/cmd/5l/5.out.h
index 7b16ac446..38a33db64 100644
--- a/src/cmd/5l/5.out.h
+++ b/src/cmd/5l/5.out.h
@@ -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),
};
/*
diff --git a/src/cmd/6g/opt.h b/src/cmd/6g/opt.h
index 4c9bb89fc..493171ef8 100644
--- a/src/cmd/6g/opt.h
+++ b/src/cmd/6g/opt.h
@@ -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,
diff --git a/src/cmd/6g/reg.c b/src/cmd/6g/reg.c
index 4ce2f4db0..75f9573b2 100644
--- a/src/cmd/6g/reg.c
+++ b/src/cmd/6g/reg.c
@@ -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");
+ }
}
}
diff --git a/src/cmd/6l/6.out.h b/src/cmd/6l/6.out.h
index af72784e8..c09ac2824 100644
--- a/src/cmd/6l/6.out.h
+++ b/src/cmd/6l/6.out.h
@@ -865,6 +865,8 @@ enum
D_INDIR, /* additive */
+ D_LAST,
+
T_TYPE = 1<<0,
T_INDEX = 1<<1,
T_OFFSET = 1<<2,
diff --git a/src/cmd/8g/opt.h b/src/cmd/8g/opt.h
index 0e2d165b1..5445f9127 100644
--- a/src/cmd/8g/opt.h
+++ b/src/cmd/8g/opt.h
@@ -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,
diff --git a/src/cmd/8g/reg.c b/src/cmd/8g/reg.c
index 79d60bed5..d7394a16d 100644
--- a/src/cmd/8g/reg.c
+++ b/src/cmd/8g/reg.c
@@ -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");
+ }
}
}
diff --git a/src/cmd/8l/8.out.h b/src/cmd/8l/8.out.h
index ed54f6744..596c5f61a 100644
--- a/src/cmd/8l/8.out.h
+++ b/src/cmd/8l/8.out.h
@@ -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,
diff --git a/src/cmd/9a/lex.c b/src/cmd/9a/lex.c
index 26f21f743..e2945ef89 100644
--- a/src/cmd/9a/lex.c
+++ b/src/cmd/9a/lex.c
@@ -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
index 3f528d751..000000000
--- a/src/cmd/9c/Makefile
+++ /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
index 92dd9deb3..000000000
--- a/src/cmd/9c/Notes
+++ /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
index bd1f7b28f..000000000
--- a/src/cmd/9c/cgen.c
+++ /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
index 6c9b4762d..000000000
--- a/src/cmd/9c/doc.go
+++ /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
index fbe5099fe..000000000
--- a/src/cmd/9c/gc.h
+++ /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
index 5cfc442cb..000000000
--- a/src/cmd/9c/list.c
+++ /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
index af44bc820..000000000
--- a/src/cmd/9c/machcap.c
+++ /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
index 353376f15..000000000
--- a/src/cmd/9c/mul.c
+++ /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
index 2e8e2adcc..000000000
--- a/src/cmd/9c/peep.c
+++ /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
index 81a7c7fe4..000000000
--- a/src/cmd/9c/reg.c
+++ /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
index b03c17267..000000000
--- a/src/cmd/9c/sgen.c
+++ /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
index a63db60b2..000000000
--- a/src/cmd/9c/swt.c
+++ /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
index e46aba84e..000000000
--- a/src/cmd/9c/txt.c
+++ /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] */
-};
diff --git a/src/cmd/9g/prog.c b/src/cmd/9g/prog.c
index e3e50f28a..51c132d18 100644
--- a/src/cmd/9g/prog.c
+++ b/src/cmd/9g/prog.c
@@ -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);
}
}
diff --git a/src/cmd/9g/reg.c b/src/cmd/9g/reg.c
index b911a2399..2e546a95b 100644
--- a/src/cmd/9g/reg.c
+++ b/src/cmd/9g/reg.c
@@ -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);
diff --git a/src/cmd/9l/9.out.h b/src/cmd/9l/9.out.h
index 08a339318..87917f88a 100644
--- a/src/cmd/9l/9.out.h
+++ b/src/cmd/9l/9.out.h
@@ -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
diff --git a/src/cmd/cgo/doc.go b/src/cmd/cgo/doc.go
index 69c7ce893..6179c7afd 100644
--- a/src/cmd/cgo/doc.go
+++ b/src/cmd/cgo/doc.go
@@ -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:
diff --git a/src/cmd/dist/build.c b/src/cmd/dist/build.c
index e4f307bee..bfb3d15b8 100644
--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -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]));
}
diff --git a/src/cmd/dist/buildgc.c b/src/cmd/dist/buildgc.c
index 1c3329758..64434d51e 100644
--- a/src/cmd/dist/buildgc.c
+++ b/src/cmd/dist/buildgc.c
@@ -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]);
}
diff --git a/src/cmd/dist/buildruntime.c b/src/cmd/dist/buildruntime.c
index e561937fb..38e99e116 100644
--- a/src/cmd/dist/buildruntime.c
+++ b/src/cmd/dist/buildruntime.c
@@ -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,
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index 37bd62dea..061089349 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -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;
diff --git a/src/cmd/go/tool.go b/src/cmd/go/tool.go
index c96161e0f..3f11c3e3d 100644
--- a/src/cmd/go/tool.go
+++ b/src/cmd/go/tool.go
@@ -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
diff --git a/src/debug/goobj/read.go b/src/cmd/internal/goobj/read.go
index 79a83e59a..79a83e59a 100644
--- a/src/debug/goobj/read.go
+++ b/src/cmd/internal/goobj/read.go
diff --git a/src/debug/goobj/read_test.go b/src/cmd/internal/goobj/read_test.go
index cc991e5d9..cc991e5d9 100644
--- a/src/debug/goobj/read_test.go
+++ b/src/cmd/internal/goobj/read_test.go
diff --git a/src/cmd/internal/objfile/goobj.go b/src/cmd/internal/objfile/goobj.go
index a1d773023..6b1607a17 100644
--- a/src/cmd/internal/objfile/goobj.go
+++ b/src/cmd/internal/objfile/goobj.go
@@ -7,7 +7,7 @@
package objfile
import (
- "debug/goobj"
+ "cmd/internal/goobj"
"fmt"
"os"
)
diff --git a/src/cmd/link/auto.go b/src/cmd/link/auto.go
index f9228e8ca..21f6d6082 100644
--- a/src/cmd/link/auto.go
+++ b/src/cmd/link/auto.go
@@ -10,7 +10,7 @@
package main
import (
- "debug/goobj"
+ "cmd/internal/goobj"
"strconv"
"strings"
)
diff --git a/src/cmd/link/auto_test.go b/src/cmd/link/auto_test.go
index 27f8e2b96..f99e097a9 100644
--- a/src/cmd/link/auto_test.go
+++ b/src/cmd/link/auto_test.go
@@ -13,7 +13,7 @@ package main
import (
"bytes"
- "debug/goobj"
+ "cmd/internal/goobj"
"testing"
)
diff --git a/src/cmd/link/dead.go b/src/cmd/link/dead.go
index e1e775eb3..ee23a61f8 100644
--- a/src/cmd/link/dead.go
+++ b/src/cmd/link/dead.go
@@ -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
diff --git a/src/cmd/link/dead_test.go b/src/cmd/link/dead_test.go
index 2e179b453..eb34d0580 100644
--- a/src/cmd/link/dead_test.go
+++ b/src/cmd/link/dead_test.go
@@ -5,7 +5,7 @@
package main
import (
- "debug/goobj"
+ "cmd/internal/goobj"
"reflect"
"strings"
"testing"
diff --git a/src/cmd/link/layout.go b/src/cmd/link/layout.go
index 149ebced0..d5c291e25 100644
--- a/src/cmd/link/layout.go
+++ b/src/cmd/link/layout.go
@@ -7,7 +7,7 @@
package main
import (
- "debug/goobj"
+ "cmd/internal/goobj"
)
// A layoutSection describes a single section to add to the
diff --git a/src/cmd/link/link_test.go b/src/cmd/link/link_test.go
index 984796784..b5ae15fc7 100644
--- a/src/cmd/link/link_test.go
+++ b/src/cmd/link/link_test.go
@@ -6,7 +6,7 @@ package main
import (
"bytes"
- "debug/goobj"
+ "cmd/internal/goobj"
"io/ioutil"
"testing"
)
diff --git a/src/cmd/link/pclntab.go b/src/cmd/link/pclntab.go
index 232d586bf..2d131781f 100644
--- a/src/cmd/link/pclntab.go
+++ b/src/cmd/link/pclntab.go
@@ -7,7 +7,7 @@
package main
import (
- "debug/goobj"
+ "cmd/internal/goobj"
"encoding/binary"
"os"
"sort"
diff --git a/src/cmd/link/pclntab_test.go b/src/cmd/link/pclntab_test.go
index 19953f579..ea8080674 100644
--- a/src/cmd/link/pclntab_test.go
+++ b/src/cmd/link/pclntab_test.go
@@ -6,7 +6,7 @@ package main
import (
"bytes"
- "debug/goobj"
+ "cmd/internal/goobj"
"fmt"
"math/rand"
"sort"
diff --git a/src/cmd/link/prog.go b/src/cmd/link/prog.go
index a52b5ff9b..77fb1ece5 100644
--- a/src/cmd/link/prog.go
+++ b/src/cmd/link/prog.go
@@ -5,7 +5,7 @@
package main
import (
- "debug/goobj"
+ "cmd/internal/goobj"
"encoding/binary"
"fmt"
"go/build"
diff --git a/src/cmd/link/runtime.go b/src/cmd/link/runtime.go
index b0c1ac98a..acda2d24d 100644
--- a/src/cmd/link/runtime.go
+++ b/src/cmd/link/runtime.go
@@ -7,7 +7,7 @@
package main
-import "debug/goobj"
+import "cmd/internal/goobj"
func (p *Prog) runtime() {
p.pclntab()
diff --git a/src/cmd/link/scan.go b/src/cmd/link/scan.go
index 0720e039b..7feb0d890 100644
--- a/src/cmd/link/scan.go
+++ b/src/cmd/link/scan.go
@@ -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
diff --git a/src/cmd/pprof/internal/report/source.go b/src/cmd/pprof/internal/report/source.go
index 57300dd91..73ae1b4ea 100644
--- a/src/cmd/pprof/internal/report/source.go
+++ b/src/cmd/pprof/internal/report/source.go
@@ -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])
diff --git a/src/crypto/x509/root_unix.go b/src/crypto/x509/root_unix.go
index c65f626ac..f77d6c0c5 100644
--- a/src/crypto/x509/root_unix.go
+++ b/src/crypto/x509/root_unix.go
@@ -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
diff --git a/src/go/parser/error_test.go b/src/go/parser/error_test.go
index 48fb53e5b..1a08d5a6b 100644
--- a/src/go/parser/error_test.go
+++ b/src/go/parser/error_test.go
@@ -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) {
diff --git a/src/go/parser/parser_test.go b/src/go/parser/parser_test.go
index 85065fd18..51ce1a933 100644
--- a/src/go/parser/parser_test.go
+++ b/src/go/parser/parser_test.go
@@ -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 */
diff --git a/src/hash/crc32/crc32.go b/src/hash/crc32/crc32.go
index a2a21a06f..6a6b9473b 100644
--- a/src/hash/crc32/crc32.go
+++ b/src/hash/crc32/crc32.go
@@ -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.
diff --git a/src/image/jpeg/reader.go b/src/image/jpeg/reader.go
index c8fae3cea..6d8b1d1d0 100644
--- a/src/image/jpeg/reader.go
+++ b/src/image/jpeg/reader.go
@@ -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
}
diff --git a/src/image/jpeg/reader_test.go b/src/image/jpeg/reader_test.go
index 93f4adab9..4de2e8ee7 100644
--- a/src/image/jpeg/reader_test.go
+++ b/src/image/jpeg/reader_test.go
@@ -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 {
diff --git a/src/liblink/list6.c b/src/liblink/list6.c
index 0635fdf1f..ff22273c4 100644
--- a/src/liblink/list6.c
+++ b/src/liblink/list6.c
@@ -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);
diff --git a/src/liblink/list9.c b/src/liblink/list9.c
index 512ed5a11..32fcf8f87 100644
--- a/src/liblink/list9.c
+++ b/src/liblink/list9.c
@@ -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));
diff --git a/src/net/http/fs.go b/src/net/http/fs.go
index 7bd777b71..e322f710a 100644
--- a/src/net/http/fs.go
+++ b/src/net/http/fs.go
@@ -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
diff --git a/src/net/url/example_test.go b/src/net/url/example_test.go
index 56c5dc696..e55c1aa16 100644
--- a/src/net/url/example_test.go
+++ b/src/net/url/example_test.go
@@ -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
+ //
+}
diff --git a/src/regexp/syntax/regexp.go b/src/regexp/syntax/regexp.go
index 329a90e01..cea7d9e04 100644
--- a/src/regexp/syntax/regexp.go
+++ b/src/regexp/syntax/regexp.go
@@ -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
diff --git a/src/run.bash b/src/run.bash
index 54b209591..b8ce417a0 100755
--- a/src/run.bash
+++ b/src/run.bash
@@ -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.
diff --git a/src/run.bat b/src/run.bat
index 14c1b45fd..efa97662f 100644
--- a/src/run.bat
+++ b/src/run.bat
@@ -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
diff --git a/src/runtime/arch1_386.go b/src/runtime/arch1_386.go
index 7746dfbf0..a73e207ed 100644
--- a/src/runtime/arch1_386.go
+++ b/src/runtime/arch1_386.go
@@ -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
)
diff --git a/src/runtime/arch1_amd64.go b/src/runtime/arch1_amd64.go
index 83c9c2dc9..794b7f65c 100644
--- a/src/runtime/arch1_amd64.go
+++ b/src/runtime/arch1_amd64.go
@@ -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
index 000000000..2cee21f0c
--- /dev/null
+++ b/src/runtime/arch1_amd64p32.go
@@ -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
+)
diff --git a/src/runtime/arch1_arm.go b/src/runtime/arch1_arm.go
index 5cb79fd68..6662eaeac 100644
--- a/src/runtime/arch1_arm.go
+++ b/src/runtime/arch1_arm.go
@@ -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
index 000000000..01e2b70f9
--- /dev/null
+++ b/src/runtime/arch1_power64.go
@@ -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
index 000000000..6580732a3
--- /dev/null
+++ b/src/runtime/arch1_power64le.go
@@ -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
index d3e864987..000000000
--- a/src/runtime/arch_amd64p32.h
+++ /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
index 7cfb9da2f..000000000
--- a/src/runtime/arch_power64.h
+++ /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
-};
-
diff --git a/src/runtime/asm_amd64p32.s b/src/runtime/asm_amd64p32.s
index 60c438c1d..c87d848fe 100644
--- a/src/runtime/asm_amd64p32.s
+++ b/src/runtime/asm_amd64p32.s
@@ -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
diff --git a/src/runtime/asm_power64x.s b/src/runtime/asm_power64x.s
index 6169202ea..548c88e47 100644
--- a/src/runtime/asm_power64x.s
+++ b/src/runtime/asm_power64x.s
@@ -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
index 000000000..a0dcf514b
--- /dev/null
+++ b/src/runtime/atomic_power64x.go
@@ -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)
diff --git a/src/runtime/chan.go b/src/runtime/chan.go
index bb0110f94..330422ad0 100644
--- a/src/runtime/chan.go
+++ b/src/runtime/chan.go
@@ -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
}
diff --git a/src/runtime/defs1_netbsd_386.go b/src/runtime/defs1_netbsd_386.go
index e39fd04c7..f222bed99 100644
--- a/src/runtime/defs1_netbsd_386.go
+++ b/src/runtime/defs1_netbsd_386.go
@@ -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
}
diff --git a/src/runtime/defs1_netbsd_amd64.go b/src/runtime/defs1_netbsd_amd64.go
index cca701e5b..c2bde4dab 100644
--- a/src/runtime/defs1_netbsd_amd64.go
+++ b/src/runtime/defs1_netbsd_amd64.go
@@ -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
diff --git a/src/runtime/defs_linux_386.go b/src/runtime/defs_linux_386.go
index ddf592c91..f55924b61 100644
--- a/src/runtime/defs_linux_386.go
+++ b/src/runtime/defs_linux_386.go
@@ -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 {
diff --git a/src/runtime/defs_linux_amd64.go b/src/runtime/defs_linux_amd64.go
index 7f8f5816c..a73f47514 100644
--- a/src/runtime/defs_linux_amd64.go
+++ b/src/runtime/defs_linux_amd64.go
@@ -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 {
diff --git a/src/runtime/defs_linux_arm.go b/src/runtime/defs_linux_arm.go
index a874b1594..c3a6e2f01 100644
--- a/src/runtime/defs_linux_arm.go
+++ b/src/runtime/defs_linux_arm.go
@@ -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
index 000000000..f90b84874
--- /dev/null
+++ b/src/runtime/defs_linux_power64.go
@@ -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
index 93742fa34..000000000
--- a/src/runtime/defs_linux_power64.h
+++ /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
index 000000000..f90b84874
--- /dev/null
+++ b/src/runtime/defs_linux_power64le.go
@@ -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
index 93742fa34..000000000
--- a/src/runtime/defs_linux_power64le.h
+++ /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_plan9_386.go b/src/runtime/defs_plan9_386.go
index 170506b23..212ecdf14 100644
--- a/src/runtime/defs_plan9_386.go
+++ b/src/runtime/defs_plan9_386.go
@@ -1,5 +1,7 @@
package runtime
+const _PAGESIZE = 0x1000
+
type ureg struct {
di uint32 /* general registers */
si uint32 /* ... */
diff --git a/src/runtime/defs_plan9_amd64.go b/src/runtime/defs_plan9_amd64.go
index 17becfb66..510da0e99 100644
--- a/src/runtime/defs_plan9_amd64.go
+++ b/src/runtime/defs_plan9_amd64.go
@@ -1,5 +1,7 @@
package runtime
+const _PAGESIZE = 0x1000
+
type ureg struct {
ax uint64
bx uint64
diff --git a/src/runtime/env_plan9.go b/src/runtime/env_plan9.go
index e442c3483..ec50cac48 100644
--- a/src/runtime/env_plan9.go
+++ b/src/runtime/env_plan9.go
@@ -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
index 000000000..06621c8db
--- /dev/null
+++ b/src/runtime/gengoos.go
@@ -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)
+ }
+ }
+}
diff --git a/src/runtime/heapdump.go b/src/runtime/heapdump.go
index c6f97025f..e1693d40f 100644
--- a/src/runtime/heapdump.go
+++ b/src/runtime/heapdump.go
@@ -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
diff --git a/src/runtime/lfstack.go b/src/runtime/lfstack.go
index a4ad8a10c..fd3325972 100644
--- a/src/runtime/lfstack.go
+++ b/src/runtime/lfstack.go
@@ -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
diff --git a/src/runtime/lfstack_32bit.go b/src/runtime/lfstack_32bit.go
index 61d8678d9..4b8bcbac6 100644
--- a/src/runtime/lfstack_32bit.go
+++ b/src/runtime/lfstack_32bit.go
@@ -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
diff --git a/src/runtime/lfstack_linux_power64x.go b/src/runtime/lfstack_linux_power64x.go
index 7a122bf92..89e389fc7 100644
--- a/src/runtime/lfstack_linux_power64x.go
+++ b/src/runtime/lfstack_linux_power64x.go
@@ -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
}
diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go
index 86e20b249..e9fec7bb1 100644
--- a/src/runtime/malloc.go
+++ b/src/runtime/malloc.go
@@ -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")
diff --git a/src/runtime/malloc2.go b/src/runtime/malloc2.go
index 511638d3d..a9d40de30 100644
--- a/src/runtime/malloc2.go
+++ b/src/runtime/malloc2.go
@@ -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)
diff --git a/src/runtime/mem_bsd.go b/src/runtime/mem_bsd.go
index 4bd40a39f..e9be5ec8c 100644
--- a/src/runtime/mem_bsd.go
+++ b/src/runtime/mem_bsd.go
@@ -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
index 6c836f18a..000000000
--- a/src/runtime/mem_nacl.c
+++ /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
index d673d6f83..000000000
--- a/src/runtime/mem_plan9.c
+++ /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
index 000000000..a5d7c1a4c
--- /dev/null
+++ b/src/runtime/mem_plan9.go
@@ -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)
+}
diff --git a/src/runtime/mgc0.go b/src/runtime/mgc0.go
index 00e64c0ff..7797894fc 100644
--- a/src/runtime/mgc0.go
+++ b/src/runtime/mgc0.go
@@ -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
}
}
diff --git a/src/runtime/netpoll_stub.c b/src/runtime/netpoll_stub.go
index b7a8f2944..6c7e79ea3 100644
--- a/src/runtime/netpoll_stub.c
+++ b/src/runtime/netpoll_stub.go
@@ -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
}
diff --git a/src/runtime/netpoll_windows.go b/src/runtime/netpoll_windows.go
index 88e878137..23d5dc00f 100644
--- a/src/runtime/netpoll_windows.go
+++ b/src/runtime/netpoll_windows.go
@@ -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
index 000000000..7b4c99a3d
--- /dev/null
+++ b/src/runtime/os1_nacl.go
@@ -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
index 000000000..493be30fa
--- /dev/null
+++ b/src/runtime/os1_netbsd.go
@@ -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
index 000000000..037f7e36d
--- /dev/null
+++ b/src/runtime/os1_netbsd_386.go
@@ -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
index 000000000..5118b0c4f
--- /dev/null
+++ b/src/runtime/os1_netbsd_amd64.go
@@ -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
index 000000000..0f8da03f2
--- /dev/null
+++ b/src/runtime/os1_plan9.go
@@ -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
index 000000000..57ea050f2
--- /dev/null
+++ b/src/runtime/os1_windows.go
@@ -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
index 000000000..0afef9156
--- /dev/null
+++ b/src/runtime/os1_windows_386.go
@@ -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
index 000000000..0d21b3881
--- /dev/null
+++ b/src/runtime/os1_windows_amd64.go
@@ -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
index 000000000..0c91e0f73
--- /dev/null
+++ b/src/runtime/os2_nacl.go
@@ -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
index 000000000..46576b9bc
--- /dev/null
+++ b/src/runtime/os2_netbsd.go
@@ -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
index 000000000..f64f4c8da
--- /dev/null
+++ b/src/runtime/os2_plan9.go
@@ -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
index 000000000..d5b1f471f
--- /dev/null
+++ b/src/runtime/os2_windows.go
@@ -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
index c7c1098e8..000000000
--- a/src/runtime/os_android.h
+++ /dev/null
@@ -1 +0,0 @@
-#include "os_linux.h"
diff --git a/src/runtime/os_android.c b/src/runtime/os_android_arm.go
index 5805f6871..132832236 100644
--- a/src/runtime/os_android.c
+++ b/src/runtime/os_android_arm.go
@@ -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
index ad72cc7c6..000000000
--- a/src/runtime/os_nacl.c
+++ /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);
-*/
diff --git a/src/runtime/os_nacl.go b/src/runtime/os_nacl.go
index 8dd43ff06..eff9ec30e 100644
--- a/src/runtime/os_nacl.go
+++ b/src/runtime/os_nacl.go
@@ -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
index 7c9d9c242..000000000
--- a/src/runtime/os_nacl.h
+++ /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);
diff --git a/src/runtime/os_nacl_arm.c b/src/runtime/os_nacl_arm.go
index 1248ea644..a43e7c47b 100644
--- a/src/runtime/os_nacl_arm.c
+++ b/src/runtime/os_nacl_arm.go
@@ -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
index 28929ea57..000000000
--- a/src/runtime/os_netbsd.c
+++ /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;
-}
diff --git a/src/runtime/os_netbsd.go b/src/runtime/os_netbsd.go
index f000c5e9f..a153bf2eb 100644
--- a/src/runtime/os_netbsd.go
+++ b/src/runtime/os_netbsd.go
@@ -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
index f95db325f..000000000
--- a/src/runtime/os_netbsd.h
+++ /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
index 23e9db3c1..000000000
--- a/src/runtime/os_netbsd_386.c
+++ /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
index 226846cbb..000000000
--- a/src/runtime/os_netbsd_amd64.c
+++ /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
index 18460fc12..000000000
--- a/src/runtime/os_plan9.c
+++ /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);
-}
diff --git a/src/runtime/os_plan9.go b/src/runtime/os_plan9.go
index 20e47bf42..2dcdfc009 100644
--- a/src/runtime/os_plan9.go
+++ b/src/runtime/os_plan9.go
@@ -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
index 6d1802483..000000000
--- a/src/runtime/os_plan9.h
+++ /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
index 42c6d161c..000000000
--- a/src/runtime/os_plan9_386.c
+++ /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
index 000000000..7dda13931
--- /dev/null
+++ b/src/runtime/os_plan9_386.go
@@ -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
index a9dc0eb96..000000000
--- a/src/runtime/os_plan9_amd64.c
+++ /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
index 000000000..8727dcc20
--- /dev/null
+++ b/src/runtime/os_plan9_amd64.go
@@ -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
index b8b8eda5f..000000000
--- a/src/runtime/os_windows.c
+++ /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.
-}
diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go
index fcd8f44cc..097b5d629 100644
--- a/src/runtime/os_windows.go
+++ b/src/runtime/os_windows.go
@@ -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
index d5d168d77..000000000
--- a/src/runtime/os_windows.h
+++ /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
index 9962f0dc2..000000000
--- a/src/runtime/os_windows_386.c
+++ /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
index e4617e4ce..000000000
--- a/src/runtime/os_windows_amd64.c
+++ /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);
-}
diff --git a/src/runtime/panic.go b/src/runtime/panic.go
index 892946702..95e780b1d 100644
--- a/src/runtime/panic.go
+++ b/src/runtime/panic.go
@@ -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))
diff --git a/src/runtime/proc.go b/src/runtime/proc.go
index 12e2e71e9..64f6a3520 100644
--- a/src/runtime/proc.go
+++ b/src/runtime/proc.go
@@ -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
index 000000000..84f0acece
--- /dev/null
+++ b/src/runtime/race/race_unix_test.go
@@ -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)
+}
diff --git a/src/runtime/race1.go b/src/runtime/race1.go
index 4c580429c..2ec2bee65 100644
--- a/src/runtime/race1.go
+++ b/src/runtime/race1.go
@@ -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
}
diff --git a/src/runtime/race_amd64.s b/src/runtime/race_amd64.s
index a7f44870a..d54d9798f 100644
--- a/src/runtime/race_amd64.s
+++ b/src/runtime/race_amd64.s
@@ -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)(...), ...)
diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go
index 7625a2dd8..d18178d09 100644
--- a/src/runtime/runtime2.go
+++ b/src/runtime/runtime2.go
@@ -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 {
diff --git a/src/runtime/select.go b/src/runtime/select.go
index e918b734a..5e5047bc1 100644
--- a/src/runtime/select.go
+++ b/src/runtime/select.go
@@ -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
diff --git a/src/runtime/sema.go b/src/runtime/sema.go
index d2a028c01..26dbd30ea 100644
--- a/src/runtime/sema.go
+++ b/src/runtime/sema.go
@@ -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
index 2a1bb4b3e..000000000
--- a/src/runtime/signal_android_386.h
+++ /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
index 8a05e21e5..000000000
--- a/src/runtime/signal_android_arm.h
+++ /dev/null
@@ -1 +0,0 @@
-#include "signal_linux_arm.h"
diff --git a/src/runtime/signal_linux_386.go b/src/runtime/signal_linux_386.go
index 41eae80ea..085f66e89 100644
--- a/src/runtime/signal_linux_386.go
+++ b/src/runtime/signal_linux_386.go
@@ -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 }
diff --git a/src/runtime/signal_linux_amd64.go b/src/runtime/signal_linux_amd64.go
index d94b19102..5e339b8a4 100644
--- a/src/runtime/signal_linux_amd64.go
+++ b/src/runtime/signal_linux_amd64.go
@@ -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 }
diff --git a/src/runtime/signal_linux_arm.go b/src/runtime/signal_linux_arm.go
index 4a5670e74..bdb4314fa 100644
--- a/src/runtime/signal_linux_arm.go
+++ b/src/runtime/signal_linux_arm.go
@@ -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
index 840648920..000000000
--- a/src/runtime/signal_linux_power64.h
+++ /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
index 840648920..000000000
--- a/src/runtime/signal_linux_power64le.h
+++ /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
index 000000000..0a406b31f
--- /dev/null
+++ b/src/runtime/signal_linux_power64x.go
@@ -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
index 000000000..122648bc3
--- /dev/null
+++ b/src/runtime/signal_nacl.go
@@ -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
index 000000000..0a1e7c6ea
--- /dev/null
+++ b/src/runtime/signal_nacl_386.go
@@ -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
index c9481b5f4..000000000
--- a/src/runtime/signal_nacl_386.h
+++ /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
index 000000000..024cebadd
--- /dev/null
+++ b/src/runtime/signal_nacl_amd64p32.go
@@ -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
index f62305cb5..000000000
--- a/src/runtime/signal_nacl_amd64p32.h
+++ /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
index 000000000..1aeaa4e42
--- /dev/null
+++ b/src/runtime/signal_nacl_arm.go
@@ -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
index e5bbb211d..000000000
--- a/src/runtime/signal_nacl_arm.h
+++ /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
index 000000000..78afc59ef
--- /dev/null
+++ b/src/runtime/signal_netbsd.go
@@ -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
index 000000000..6702336ab
--- /dev/null
+++ b/src/runtime/signal_netbsd_386.go
@@ -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
index d5a8a0c4b..000000000
--- a/src/runtime/signal_netbsd_386.h
+++ /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
index 000000000..e22f4a724
--- /dev/null
+++ b/src/runtime/signal_netbsd_amd64.go
@@ -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
index 7ec4cd98c..000000000
--- a/src/runtime/signal_netbsd_amd64.h
+++ /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])
diff --git a/src/runtime/signals_plan9.h b/src/runtime/signal_plan9.go
index 4ee8e542c..37d24359b 100644
--- a/src/runtime/signals_plan9.h
+++ b/src/runtime/signal_plan9.go
@@ -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
index c0bf1c4a5..000000000
--- a/src/runtime/signal_power64x.c
+++ /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
index 000000000..fc83beb1b
--- /dev/null
+++ b/src/runtime/signal_power64x.go
@@ -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
index 5140d8a18..000000000
--- a/src/runtime/signals_android.h
+++ /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
index 8761e1bd9..000000000
--- a/src/runtime/signals_nacl.h
+++ /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
index 950a2fe62..000000000
--- a/src/runtime/signals_netbsd.h
+++ /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
diff --git a/src/runtime/stack1.go b/src/runtime/stack1.go
index 57d0f8c65..c14347dbd 100644
--- a/src/runtime/stack1.go
+++ b/src/runtime/stack1.go
@@ -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
}
diff --git a/src/runtime/stack2.go b/src/runtime/stack2.go
index c3718c205..e50b32c78 100644
--- a/src/runtime/stack2.go
+++ b/src/runtime/stack2.go
@@ -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
diff --git a/src/runtime/stubs.go b/src/runtime/stubs.go
index 4063e5434..4408e22bf 100644
--- a/src/runtime/stubs.go
+++ b/src/runtime/stubs.go
@@ -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
diff --git a/src/runtime/stubs2.go b/src/runtime/stubs2.go
index 526b3c569..60751dd34 100644
--- a/src/runtime/stubs2.go
+++ b/src/runtime/stubs2.go
@@ -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
diff --git a/src/runtime/arch_power64le.h b/src/runtime/stubs3.go
index 684ac9953..ffaa28775 100644
--- a/src/runtime/arch_power64le.h
+++ b/src/runtime/stubs3.go
@@ -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
diff --git a/src/runtime/sys_linux_power64x.s b/src/runtime/sys_linux_power64x.s
index fb24d3e79..395f657bf 100644
--- a/src/runtime/sys_linux_power64x.s
+++ b/src/runtime/sys_linux_power64x.s
@@ -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
index 79d976255..000000000
--- a/src/runtime/sys_power64x.c
+++ /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
index 000000000..90ebde7b4
--- /dev/null
+++ b/src/runtime/sys_power64x.go
@@ -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")
+}
diff --git a/src/runtime/sys_windows_386.s b/src/runtime/sys_windows_386.s
index 2793e5221..c8a830cdf 100644
--- a/src/runtime/sys_windows_386.s
+++ b/src/runtime/sys_windows_386.s
@@ -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
diff --git a/src/runtime/sys_windows_amd64.s b/src/runtime/sys_windows_amd64.s
index 5e5c2e7f5..68f7cd392 100644
--- a/src/runtime/sys_windows_amd64.s
+++ b/src/runtime/sys_windows_amd64.s
@@ -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
diff --git a/src/runtime/syscall_windows.go b/src/runtime/syscall_windows.go
index efbcab510..661ee59d7 100644
--- a/src/runtime/syscall_windows.go
+++ b/src/runtime/syscall_windows.go
@@ -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
index 000000000..057a746bb
--- /dev/null
+++ b/src/runtime/zgoarch_386.go
@@ -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
index 000000000..a71240726
--- /dev/null
+++ b/src/runtime/zgoarch_amd64.go
@@ -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
index 000000000..2b6a142bb
--- /dev/null
+++ b/src/runtime/zgoarch_amd64p32.go
@@ -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
index 000000000..403021005
--- /dev/null
+++ b/src/runtime/zgoarch_arm.go
@@ -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
index 000000000..cc361f050
--- /dev/null
+++ b/src/runtime/zgoarch_power64.go
@@ -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
index 000000000..41294e61b
--- /dev/null
+++ b/src/runtime/zgoarch_power64le.go
@@ -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
index 000000000..0590bd9ab
--- /dev/null
+++ b/src/runtime/zgoos_android.go
@@ -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
index 000000000..c0a7cd6e7
--- /dev/null
+++ b/src/runtime/zgoos_darwin.go
@@ -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
index 000000000..008d6de81
--- /dev/null
+++ b/src/runtime/zgoos_dragonfly.go
@@ -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
index 000000000..247894035
--- /dev/null
+++ b/src/runtime/zgoos_freebsd.go
@@ -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
index 000000000..c775ab538
--- /dev/null
+++ b/src/runtime/zgoos_linux.go
@@ -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
index 000000000..d9d88f450
--- /dev/null
+++ b/src/runtime/zgoos_nacl.go
@@ -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
index 000000000..ff2c5cb8f
--- /dev/null
+++ b/src/runtime/zgoos_netbsd.go
@@ -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
index 000000000..b071dc63a
--- /dev/null
+++ b/src/runtime/zgoos_openbsd.go
@@ -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
index 000000000..4306b0f1e
--- /dev/null
+++ b/src/runtime/zgoos_plan9.go
@@ -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
index 000000000..10f9537d0
--- /dev/null
+++ b/src/runtime/zgoos_solaris.go
@@ -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
index 000000000..56f5c58ce
--- /dev/null
+++ b/src/runtime/zgoos_windows.go
@@ -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
diff --git a/src/syscall/exec_bsd.go b/src/syscall/exec_bsd.go
index 7c2c1f707..ff78f197f 100644
--- a/src/syscall/exec_bsd.go
+++ b/src/syscall/exec_bsd.go
@@ -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
diff --git a/src/syscall/exec_linux.go b/src/syscall/exec_linux.go
index 72e2f0b69..042c20a46 100644
--- a/src/syscall/exec_linux.go
+++ b/src/syscall/exec_linux.go
@@ -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
index 000000000..729463305
--- /dev/null
+++ b/test/fixedbugs/issue9110.go
@@ -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")
+ }
+}