mirror of
https://github.com/golang/go.git
synced 2026-02-05 18:35:03 +03:00
Compare commits
249 Commits
go1.8beta1
...
dev.garbag
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1d4942afe0 | ||
|
|
8b25a00e6d | ||
|
|
d9a0579156 | ||
|
|
2817e77024 | ||
|
|
7f1ff65c39 | ||
|
|
f412bd31ce | ||
|
|
a8871194f2 | ||
|
|
ffedff7e50 | ||
|
|
3156736189 | ||
|
|
1ede11d13a | ||
|
|
067bab00a8 | ||
|
|
8fa2344e98 | ||
|
|
1fbdae5c3a | ||
|
|
66063b2da8 | ||
|
|
5ddfa69fef | ||
|
|
116da1c64a | ||
|
|
41d2278eef | ||
|
|
a37b9e8e70 | ||
|
|
b902a63ade | ||
|
|
5dd978a283 | ||
|
|
618c291544 | ||
|
|
cb91dccd86 | ||
|
|
7aefdfded0 | ||
|
|
867dcb5570 | ||
|
|
b07363da16 | ||
|
|
b03dce927b | ||
|
|
ea53e61c6c | ||
|
|
7d977e4279 | ||
|
|
b820ef5c33 | ||
|
|
a2b615d527 | ||
|
|
f5608c20f7 | ||
|
|
c3fc9b4b81 | ||
|
|
2547aec42a | ||
|
|
2815045a50 | ||
|
|
ecac827573 | ||
|
|
7fb1640613 | ||
|
|
3fa53f1229 | ||
|
|
20cdb62c49 | ||
|
|
f64b7d301d | ||
|
|
6a1cac2700 | ||
|
|
d698e614a2 | ||
|
|
161cd34f78 | ||
|
|
f09462707f | ||
|
|
155d314e50 | ||
|
|
af7bc07049 | ||
|
|
9def857072 | ||
|
|
f78cd569f5 | ||
|
|
e776975ae6 | ||
|
|
b63ca1e974 | ||
|
|
9e199702c8 | ||
|
|
9719ca9c0e | ||
|
|
5bfba30d33 | ||
|
|
d160982a2e | ||
|
|
a3f4cc0669 | ||
|
|
c8f1436948 | ||
|
|
db07c9ecb6 | ||
|
|
8887be4654 | ||
|
|
6e36811c37 | ||
|
|
f419b56354 | ||
|
|
17190343e3 | ||
|
|
d2512aff87 | ||
|
|
d51046b37c | ||
|
|
f24384f686 | ||
|
|
c44da14440 | ||
|
|
d296c3235d | ||
|
|
0ef4815150 | ||
|
|
8599c0da1f | ||
|
|
09c411da1d | ||
|
|
27fb26c77c | ||
|
|
9c6a5ef922 | ||
|
|
86f2c5fe93 | ||
|
|
985a574991 | ||
|
|
6e87f88961 | ||
|
|
2eae691d56 | ||
|
|
8df54c92c0 | ||
|
|
2f9dee9293 | ||
|
|
0c942e8f2c | ||
|
|
860c9c0b8d | ||
|
|
5a72bad87a | ||
|
|
c5f16d4e40 | ||
|
|
3357daa96e | ||
|
|
4d02833c2e | ||
|
|
a1c835f57b | ||
|
|
5df59a4fc9 | ||
|
|
7eee512773 | ||
|
|
a0667be8ef | ||
|
|
ddd558e7e4 | ||
|
|
8d21691044 | ||
|
|
0919fd7068 | ||
|
|
75d367e34b | ||
|
|
12979345b1 | ||
|
|
1ec64e9b63 | ||
|
|
1106512db5 | ||
|
|
61db2e4efa | ||
|
|
1716add3dc | ||
|
|
7799022cdd | ||
|
|
ecc4474341 | ||
|
|
115e9cac80 | ||
|
|
29cb72154d | ||
|
|
c1d449c42c | ||
|
|
0cd2bf4f98 | ||
|
|
6e542dce21 | ||
|
|
9cd3c0662a | ||
|
|
651d392308 | ||
|
|
94e0f06fbc | ||
|
|
92fb0a00c2 | ||
|
|
01b006fc18 | ||
|
|
34bd7d5d4b | ||
|
|
7e4ef4ebfc | ||
|
|
6f5a77bf5f | ||
|
|
c1ada22bc1 | ||
|
|
2adc2d1b8b | ||
|
|
3444e5b355 | ||
|
|
cd2b6bd3c4 | ||
|
|
627af57b54 | ||
|
|
ffc836bcbb | ||
|
|
49e5bdfe79 | ||
|
|
c74392634c | ||
|
|
b909d01152 | ||
|
|
a3b670e333 | ||
|
|
96414ca39f | ||
|
|
901005e8fc | ||
|
|
1da1e43281 | ||
|
|
afb350811e | ||
|
|
d0501f1da9 | ||
|
|
fe07091f9e | ||
|
|
232991e8a7 | ||
|
|
79a748fae8 | ||
|
|
73151700b4 | ||
|
|
10f3b09027 | ||
|
|
4284edb999 | ||
|
|
386b66f5bd | ||
|
|
990cda59f8 | ||
|
|
48b42d29dc | ||
|
|
3fb1e0bd7f | ||
|
|
ec80737bdf | ||
|
|
b00b214e0d | ||
|
|
1657d76d5b | ||
|
|
c06b10ae9d | ||
|
|
d986daec13 | ||
|
|
48a5d9938c | ||
|
|
b9ffcf961e | ||
|
|
9fe2291efd | ||
|
|
bc61026c3f | ||
|
|
fded5dbb2f | ||
|
|
265e547658 | ||
|
|
0716fefad3 | ||
|
|
f91ddaabe6 | ||
|
|
cbcc1db41c | ||
|
|
ab5a2173f9 | ||
|
|
4c71af71b4 | ||
|
|
8c190e5854 | ||
|
|
454c234397 | ||
|
|
c586630d99 | ||
|
|
c6228ef7e2 | ||
|
|
3a067cc812 | ||
|
|
3c0466136d | ||
|
|
2eb976eb2a | ||
|
|
4bf7d1e722 | ||
|
|
e12ce1e400 | ||
|
|
9ad47c4f67 | ||
|
|
00efa446e1 | ||
|
|
4c4201f0e2 | ||
|
|
51a75a01f8 | ||
|
|
9296d4efe7 | ||
|
|
67b2927990 | ||
|
|
291254414b | ||
|
|
d4b46aa1b8 | ||
|
|
f28eea89e0 | ||
|
|
51a6d3e074 | ||
|
|
01c6a19e04 | ||
|
|
d4177877c6 | ||
|
|
6623988eb7 | ||
|
|
be8a6fd2e3 | ||
|
|
1ea60c136a | ||
|
|
8e0c4639f1 | ||
|
|
850e55b8c0 | ||
|
|
bc075e61cb | ||
|
|
26aa7422e5 | ||
|
|
2641cffd41 | ||
|
|
0be4ef3ea6 | ||
|
|
94a4485f70 | ||
|
|
ac9962fb23 | ||
|
|
6c7978fc89 | ||
|
|
f251708a73 | ||
|
|
348a7c5397 | ||
|
|
10f43a1f4f | ||
|
|
749720a036 | ||
|
|
8adff32bac | ||
|
|
6c9f600d49 | ||
|
|
8016808562 | ||
|
|
80acfe950f | ||
|
|
a303f05f86 | ||
|
|
14f18e5b6f | ||
|
|
7cba779cea | ||
|
|
8c31f40a4c | ||
|
|
42afbd9e63 | ||
|
|
7e9fa3c321 | ||
|
|
ed0b232cdc | ||
|
|
af67f7de3f | ||
|
|
d54b60a2b2 | ||
|
|
37dbc7b49c | ||
|
|
d29f72f472 | ||
|
|
93726522ef | ||
|
|
e7a0df35b3 | ||
|
|
6270c5ac28 | ||
|
|
5c9035acc1 | ||
|
|
130ad87ab7 | ||
|
|
9e0f3a1459 | ||
|
|
c676b0f9cf | ||
|
|
bcacb6d3f4 | ||
|
|
64969c8ef5 | ||
|
|
f52e20582a | ||
|
|
4bc7b5aeba | ||
|
|
7736cbafd9 | ||
|
|
fd483b6f62 | ||
|
|
e3a1d0cb7c | ||
|
|
ae9712c766 | ||
|
|
2d136ae82e | ||
|
|
751c8903d2 | ||
|
|
1102c70bc4 | ||
|
|
2cfb6d5442 | ||
|
|
b42d4a8b0e | ||
|
|
63a7ee7823 | ||
|
|
c96e94e69d | ||
|
|
7e5b2e0ec1 | ||
|
|
9fbfe7cca0 | ||
|
|
3c2e4ed8d3 | ||
|
|
612469ab0b | ||
|
|
208d4d2227 | ||
|
|
e5e0562774 | ||
|
|
ea1b90f855 | ||
|
|
8a103bd4ce | ||
|
|
583b72dea1 | ||
|
|
85bcf7f59d | ||
|
|
0b2daa5650 | ||
|
|
16c33992e0 | ||
|
|
3a369a0f59 | ||
|
|
9ea306a10c | ||
|
|
f9f6c90ed1 | ||
|
|
69161e279e | ||
|
|
fb4c718209 | ||
|
|
81b74bf9c5 | ||
|
|
edb54c300f | ||
|
|
312aa09996 | ||
|
|
d491e550c3 | ||
|
|
641c32dafa | ||
|
|
2e495a1df6 | ||
|
|
344476d23c |
48
.gitignore
vendored
48
.gitignore
vendored
@@ -18,28 +18,28 @@ _cgo_*
|
||||
_obj
|
||||
_test
|
||||
_testmain.go
|
||||
build.out
|
||||
test.out
|
||||
doc/articles/wiki/*.bin
|
||||
misc/cgo/life/run.out
|
||||
misc/cgo/stdio/run.out
|
||||
misc/cgo/testso/main
|
||||
src/cmd/cgo/zdefaultcc.go
|
||||
src/cmd/go/zdefaultcc.go
|
||||
src/cmd/go/zosarch.go
|
||||
src/cmd/internal/obj/zbootstrap.go
|
||||
src/go/build/zcgo.go
|
||||
src/go/doc/headscan
|
||||
src/runtime/internal/sys/zversion.go
|
||||
src/unicode/maketables
|
||||
src/*.*/
|
||||
test/pass.out
|
||||
test/run.out
|
||||
test/times.out
|
||||
test/garbage/*.out
|
||||
goinstall.log
|
||||
last-change
|
||||
VERSION.cache
|
||||
|
||||
bin/
|
||||
pkg/
|
||||
/VERSION.cache
|
||||
/bin/
|
||||
/build.out
|
||||
/doc/articles/wiki/*.bin
|
||||
/goinstall.log
|
||||
/last-change
|
||||
/misc/cgo/life/run.out
|
||||
/misc/cgo/stdio/run.out
|
||||
/misc/cgo/testso/main
|
||||
/pkg/
|
||||
/src/*.*/
|
||||
/src/cmd/cgo/zdefaultcc.go
|
||||
/src/cmd/go/zdefaultcc.go
|
||||
/src/cmd/go/zosarch.go
|
||||
/src/cmd/internal/obj/zbootstrap.go
|
||||
/src/go/build/zcgo.go
|
||||
/src/go/doc/headscan
|
||||
/src/runtime/internal/sys/zversion.go
|
||||
/src/unicode/maketables
|
||||
/test.out
|
||||
/test/garbage/*.out
|
||||
/test/pass.out
|
||||
/test/run.out
|
||||
/test/times.out
|
||||
|
||||
38
AUTHORS
38
AUTHORS
@@ -29,11 +29,13 @@ Akshat Kumar <seed@mail.nanosouffle.net>
|
||||
Alan Shreve <alan@inconshreveable.com>
|
||||
Albert Nigmatzianov <albertnigma@gmail.com>
|
||||
Albert Strasheim <fullung@gmail.com>
|
||||
Albert Yu <yukinying@gmail.com>
|
||||
Alberto Bertogli <albertito@blitiri.com.ar>
|
||||
Alberto Donizetti <alb.donizetti@gmail.com>
|
||||
Alberto García Hierro <alberto@garciahierro.com> <alberto.garcia.hierro@gmail.com>
|
||||
Aleksandar Dezelin <dezelin@gmail.com>
|
||||
Alessandro Arzilli <alessandro.arzilli@gmail.com>
|
||||
Alessandro Baffa <alessandro.baffa@gmail.com>
|
||||
Alex A Skinner <alex@lx.lc>
|
||||
Alex Brainman <alex.brainman@gmail.com>
|
||||
Alex Browne <stephenalexbrowne@gmail.com>
|
||||
@@ -45,6 +47,7 @@ Alex Sergeyev <abc@alexsergeyev.com>
|
||||
Alexander Demakin <alexander.demakin@gmail.com>
|
||||
Alexander Döring <email@alexd.ch>
|
||||
Alexander Larsson <alexander.larsson@gmail.com>
|
||||
Alexander Menzhinsky <amenzhinsky@gmail.com>
|
||||
Alexander Morozov <lk4d4math@gmail.com>
|
||||
Alexander Neumann <alexander@bumpern.de>
|
||||
Alexander Orlov <alexander.orlov@loxal.net>
|
||||
@@ -53,6 +56,7 @@ Alexander Surma <surma@surmair.de>
|
||||
Alexander Zhavnerchik <alex.vizor@gmail.com>
|
||||
Alexander Zolotov <goldifit@gmail.com>
|
||||
Alexandre Cesaro <alexandre.cesaro@gmail.com>
|
||||
Alexandre Fiori <fiorix@gmail.com>
|
||||
Alexandre Normand <alexandre.normand@gmail.com>
|
||||
Alexei Sholik <alcosholik@gmail.com>
|
||||
Alexey Borzenkov <snaury@gmail.com>
|
||||
@@ -69,6 +73,7 @@ Andreas Auernhammer <aead@mail.de>
|
||||
Andreas Litt <andreas.litt@gmail.com>
|
||||
Andrei Korzhevskii <a.korzhevskiy@gmail.com>
|
||||
Andrei Vieru <euvieru@gmail.com>
|
||||
Andrew Austin <andrewaclt@gmail.com>
|
||||
Andrew Balholm <andybalholm@gmail.com>
|
||||
Andrew Bonventre <andybons@chromium.org>
|
||||
Andrew Bursavich <abursavich@gmail.com>
|
||||
@@ -88,6 +93,7 @@ Andrey Petrov <andrey.petrov@shazow.net>
|
||||
Andriy Lytvynov <lytvynov.a.v@gmail.com>
|
||||
Andy Balholm <andy@balholm.com>
|
||||
Andy Davis <andy@bigandian.com>
|
||||
Andy Finkenstadt <afinkenstadt@zynga.com>
|
||||
Andy Maloney <asmaloney@gmail.com>
|
||||
Anfernee Yongkun Gui <anfernee.gui@gmail.com>
|
||||
Angelo Bulfone <mbulfone@gmail.com>
|
||||
@@ -98,6 +104,8 @@ Anthony Canino <anthony.canino1@gmail.com>
|
||||
Anthony Eufemio <anthony.eufemio@gmail.com>
|
||||
Anthony Martin <ality@pbrane.org>
|
||||
Anthony Starks <ajstarks@gmail.com>
|
||||
Anthony Woods <awoods@raintank.io>
|
||||
Antonio Bibiano <antbbn@gmail.com>
|
||||
Apisak Darakananda <pongad@gmail.com>
|
||||
Aram Hăvărneanu <aram@mgk.ro>
|
||||
Areski Belaid <areski@gmail.com>
|
||||
@@ -117,7 +125,9 @@ Aulus Egnatius Varialus <varialus@gmail.com>
|
||||
awaw fumin <awawfumin@gmail.com>
|
||||
Ayanamist Yang <ayanamist@gmail.com>
|
||||
Aymerick Jéhanne <aymerick@jehanne.org>
|
||||
Baiju Muthukadan <baiju.m.mail@gmail.com>
|
||||
Ben Burkert <ben@benburkert.com>
|
||||
Ben Lubar <ben.lubar@gmail.com>
|
||||
Ben Olive <sionide21@gmail.com>
|
||||
Benjamin Black <b@b3k.us>
|
||||
Benny Siegert <bsiegert@gmail.com>
|
||||
@@ -163,6 +173,7 @@ Chris Jones <chris@cjones.org>
|
||||
Chris Kastorff <encryptio@gmail.com>
|
||||
Chris Lennert <calennert@gmail.com>
|
||||
Chris McGee <sirnewton_01@yahoo.ca> <newton688@gmail.com>
|
||||
Chris Stockton <chrisstocktonaz@gmail.com>
|
||||
Christian Couder <chriscool@tuxfamily.org>
|
||||
Christian Himpel <chressie@googlemail.com>
|
||||
Christine Hansmann <chhansmann@gmail.com>
|
||||
@@ -258,6 +269,7 @@ Egon Elbre <egonelbre@gmail.com>
|
||||
Ehren Kret <ehren.kret@gmail.com>
|
||||
Eivind Uggedal <eivind@uggedal.com>
|
||||
Elias Naur <elias.naur@gmail.com>
|
||||
Elliot Morrison-Reed <elliotmr@gmail.com>
|
||||
Emil Hessman <c.emil.hessman@gmail.com> <emil@hessman.se>
|
||||
Emmanuel Odeke <emm.odeke@gmail.com> <odeke@ualberta.ca>
|
||||
Empirical Interfaces Inc.
|
||||
@@ -273,6 +285,7 @@ Erik St. Martin <alakriti@gmail.com>
|
||||
Erik Westrup <erik.westrup@gmail.com>
|
||||
Ernest Chiang <ernest_chiang@htc.com>
|
||||
Esko Luontola <esko.luontola@gmail.com>
|
||||
Euan Kemp <euank@euank.com>
|
||||
Evan Phoenix <evan@phx.io>
|
||||
Evan Shaw <chickencha@gmail.com>
|
||||
Ewan Chou <coocood@gmail.com>
|
||||
@@ -328,6 +341,7 @@ Hajime Hoshi <hajimehoshi@gmail.com>
|
||||
Hari haran <hariharan.uno@gmail.com>
|
||||
Hariharan Srinath <srinathh@gmail.com>
|
||||
Harley Laue <losinggeneration@gmail.com>
|
||||
Harry Moreno <morenoh149@gmail.com>
|
||||
Harshavardhana <hrshvardhana@gmail.com>
|
||||
Håvard Haugen <havard.haugen@gmail.com>
|
||||
Hector Chu <hectorchu@gmail.com>
|
||||
@@ -395,6 +409,7 @@ Jens Frederich <jfrederich@gmail.com>
|
||||
Jeremy Jackins <jeremyjackins@gmail.com>
|
||||
Jeroen Bobbeldijk <jerbob92@gmail.com>
|
||||
Jess Frazelle <me@jessfraz.com>
|
||||
Jesse Szwedko <jesse.szwedko@gmail.com>
|
||||
Jihyun Yu <yjh0502@gmail.com>
|
||||
Jim McGrath <jimmc2@gmail.com>
|
||||
Jimmy Zelinskie <jimmyzelinskie@gmail.com>
|
||||
@@ -429,6 +444,8 @@ Jonathan Rudenberg <jonathan@titanous.com>
|
||||
Jonathan Wills <runningwild@gmail.com>
|
||||
Jongmin Kim <atomaths@gmail.com>
|
||||
Joonas Kuorilehto <joneskoo@derbian.fi>
|
||||
Joop Kiefte <ikojba@gmail.com> <joop@kiefte.net>
|
||||
Jordan Lewis <jordanthelewis@gmail.com>
|
||||
Jose Luis Vázquez González <josvazg@gmail.com>
|
||||
Joseph Holsten <joseph@josephholsten.com>
|
||||
Josh Bleecher Snyder <josharian@gmail.com>
|
||||
@@ -450,6 +467,8 @@ Kamil Kisiel <kamil@kamilkisiel.net> <kamil.kisiel@gmail.com>
|
||||
Kang Hu <hukangustc@gmail.com>
|
||||
Kato Kazuyoshi <kato.kazuyoshi@gmail.com>
|
||||
Katrina Owen <katrina.owen@gmail.com>
|
||||
Kaviraj Kanagaraj <kavirajkanagaraj@gmail.com>
|
||||
Keegan Carruthers-Smith <keegan.csmith@gmail.com>
|
||||
Kei Son <hey.calmdown@gmail.com>
|
||||
Keith Ball <inflatablewoman@gmail.com>
|
||||
Keith Rarick <kr@xph.us>
|
||||
@@ -492,12 +511,15 @@ Luigi Riefolo <luigi.riefolo@gmail.com>
|
||||
Luit van Drongelen <luitvd@gmail.com>
|
||||
Luka Zakrajšek <tr00.g33k@gmail.com>
|
||||
Luke Curley <qpingu@gmail.com>
|
||||
Maksym Trykur <maksym.trykur@gmail.com>
|
||||
Mal Curtis <mal@mal.co.nz>
|
||||
Manfred Touron <m@42.am>
|
||||
Manu S Ajith <neo@codingarena.in>
|
||||
Manuel Mendez <mmendez534@gmail.com>
|
||||
Marc Weistroff <marc@weistroff.net>
|
||||
Marcel Edmund Franke <marcel.edmund.franke@gmail.com>
|
||||
Marco Hennings <marco.hennings@freiheit.com>
|
||||
Marin Bašić <marin.basic02@gmail.com>
|
||||
Mark Bucciarelli <mkbucc@gmail.com>
|
||||
Mark Severson <miquella@gmail.com>
|
||||
Mark Theunissen <mark.theunissen@gmail.com>
|
||||
@@ -535,6 +557,8 @@ Matthew Denton <mdenton@skyportsystems.com>
|
||||
Matthew Holt <Matthew.Holt+git@gmail.com>
|
||||
Matthew Horsnell <matthew.horsnell@gmail.com>
|
||||
Matthieu Hauglustaine <matt.hauglustaine@gmail.com>
|
||||
Matthieu Olivier <olivier.matthieu@gmail.com>
|
||||
Max Riveiro <kavu13@gmail.com>
|
||||
Maxim Khitrov <max@mxcrypt.com>
|
||||
Maxwell Krohn <themax@gmail.com>
|
||||
MediaMath, Inc
|
||||
@@ -599,6 +623,7 @@ Nicholas Presta <nick@nickpresta.ca> <nick1presta@gmail.com>
|
||||
Nicholas Sullivan <nicholas.sullivan@gmail.com>
|
||||
Nicholas Waples <nwaples@gmail.com>
|
||||
Nick Craig-Wood <nick@craig-wood.com> <nickcw@gmail.com>
|
||||
Nick Leli <nicholasleli@gmail.com>
|
||||
Nick Patavalis <nick.patavalis@gmail.com>
|
||||
Nick Petroni <npetroni@cs.umd.edu>
|
||||
Nicolas Kaiser <nikai@nikai.net>
|
||||
@@ -606,10 +631,12 @@ Nicolas Owens <mischief@offblast.org>
|
||||
Nicolas S. Dade <nic.dade@gmail.com>
|
||||
Niels Widger <niels.widger@gmail.com>
|
||||
Nigel Kerr <nigel.kerr@gmail.com>
|
||||
Nik Nyby <nnyby@columbia.edu>
|
||||
Niko Dziemba <niko@dziemba.com>
|
||||
Nikolay Turpitko <nikolay@turpitko.com>
|
||||
Noah Campbell <noahcampbell@gmail.com>
|
||||
Norberto Lopes <nlopes.ml@gmail.com>
|
||||
Odin Ugedal <odin@ugedal.com>
|
||||
Oleg Vakheta <helginet@gmail.com>
|
||||
Oleku Konko <oleku.konko@gmail.com>
|
||||
Oling Cat <olingcat@gmail.com>
|
||||
@@ -630,6 +657,7 @@ Pascal S. de Kloe <pascal@quies.net>
|
||||
Patrick Crosby <patrick@stathat.com>
|
||||
Patrick Gavlin <pgavlin@gmail.com>
|
||||
Patrick Higgins <patrick.allen.higgins@gmail.com>
|
||||
Patrick Lee <pattyshack101@gmail.com>
|
||||
Patrick Mézard <patrick@mezard.eu>
|
||||
Patrick Mylund Nielsen <patrick@patrickmn.com>
|
||||
Patrick Smith <pat42smith@gmail.com>
|
||||
@@ -673,9 +701,11 @@ Quentin Perez <qperez@ocs.online.net>
|
||||
Quoc-Viet Nguyen <afelion@gmail.com>
|
||||
RackTop Systems Inc.
|
||||
Radu Berinde <radu@cockroachlabs.com>
|
||||
Rafal Jeczalik <rjeczalik@gmail.com>
|
||||
Raif S. Naffah <go@naffah-raif.name>
|
||||
Rajat Goel <rajat.goel2010@gmail.com>
|
||||
Ralph Corderoy <ralph@inputplus.co.uk>
|
||||
Raphael Geronimi <raphael.geronimi@gmail.com>
|
||||
Red Hat, Inc.
|
||||
Reinaldo de Souza Jr <juniorz@gmail.com>
|
||||
Rémy Oudompheng <oudomphe@phare.normalesup.org>
|
||||
@@ -706,10 +736,12 @@ Ron Minnich <rminnich@gmail.com>
|
||||
Ross Light <rlight2@gmail.com>
|
||||
Rowan Worth <sqweek@gmail.com>
|
||||
Russell Haering <russellhaering@gmail.com>
|
||||
Ryan Bagwell <ryanbagwell@outlook.com>
|
||||
Ryan Hitchman <hitchmanr@gmail.com>
|
||||
Ryan Lower <rpjlower@gmail.com>
|
||||
Ryan Seys <ryan@ryanseys.com>
|
||||
Ryan Slade <ryanslade@gmail.com>
|
||||
Ryuzo Yamamoto <ryuzo.yamamoto@gmail.com>
|
||||
S.Çağlar Onur <caglar@10ur.org>
|
||||
Salmān Aljammāz <s@0x65.net>
|
||||
Sam Hug <samuel.b.hug@gmail.com>
|
||||
@@ -744,6 +776,7 @@ Simon Whitehead <chemnova@gmail.com>
|
||||
Sina Siadat <siadat@gmail.com>
|
||||
Sokolov Yura <funny.falcon@gmail.com>
|
||||
Song Gao <song@gao.io>
|
||||
Sourcegraph Inc
|
||||
Spencer Nelson <s@spenczar.com>
|
||||
Spring Mc <heresy.mc@gmail.com>
|
||||
Square, Inc.
|
||||
@@ -767,6 +800,7 @@ Szabolcs Nagy <nsz@port70.net>
|
||||
Tad Glines <tad.glines@gmail.com>
|
||||
Taj Khattra <taj.khattra@gmail.com>
|
||||
Takeshi YAMANASHI <9.nashi@gmail.com>
|
||||
Takuya Ueda <uedatakuya@gmail.com>
|
||||
Tal Shprecher <tshprecher@gmail.com>
|
||||
Tamir Duberstein <tamird@gmail.com>
|
||||
Tarmigan Casebolt <tarmigan@gmail.com>
|
||||
@@ -780,6 +814,7 @@ Thomas de Zeeuw <thomasdezeeuw@gmail.com>
|
||||
Thomas Desrosiers <thomasdesr@gmail.com>
|
||||
Thomas Kappler <tkappler@gmail.com>
|
||||
Thorben Krueger <thorben.krueger@gmail.com>
|
||||
Thordur Bjornsson <thorduri@secnorth.net>
|
||||
Tilman Dilo <tilman.dilo@gmail.com>
|
||||
Tim Cooijmans <timcooijmans@gmail.com>
|
||||
Tim Ebringer <tim.ebringer@gmail.com>
|
||||
@@ -798,6 +833,7 @@ Totoro W <tw19881113@gmail.com>
|
||||
Travis Cline <travis.cline@gmail.com>
|
||||
Trey Lawrence <lawrence.trey@gmail.com>
|
||||
Trey Tacon <ttacon@gmail.com>
|
||||
Tristan Colgate <tcolgate@gmail.com>
|
||||
Tristan Ooohry <ooohry@gmail.com>
|
||||
Tudor Golubenco <tudor.g@gmail.com>
|
||||
Tuo Shan <sturbo89@gmail.com>
|
||||
@@ -845,8 +881,10 @@ Yoshiyuki Kanno <nekotaroh@gmail.com> <yoshiyuki.kanno@stoic.co.jp>
|
||||
Yusuke Kagiwada <block.rxckin.beats@gmail.com>
|
||||
Yuusei Kuwana <kuwana@kumama.org>
|
||||
Yuval Pavel Zholkover <paulzhol@gmail.com>
|
||||
Zac Bergquist <zbergquist99@gmail.com>
|
||||
Zemanta d.o.o.
|
||||
Zev Goldstein <zev.goldstein@gmail.com>
|
||||
Ziad Hatahet <hatahet@gmail.com>
|
||||
Zorion Arrizabalaga <zorionk@gmail.com>
|
||||
Фахриддин Балтаев <faxriddinjon@gmail.com>
|
||||
申习之 <bronze1man@gmail.com>
|
||||
|
||||
@@ -7,6 +7,11 @@ It is the work of hundreds of contributors. We appreciate your help!
|
||||
|
||||
## Filing issues
|
||||
|
||||
General questions should go to the
|
||||
[golang-nuts mailing list](https://groups.google.com/group/golang-nuts) or
|
||||
[other forum](https://golang.org/wiki/Questions) instead of the issue tracker.
|
||||
The gophers there will answer or ask you to file an issue if you've tripped over a bug.
|
||||
|
||||
When filing an issue, make sure to answer these five questions:
|
||||
|
||||
1. What version of Go are you using (`go version`)?
|
||||
@@ -15,8 +20,7 @@ When filing an issue, make sure to answer these five questions:
|
||||
4. What did you expect to see?
|
||||
5. What did you see instead?
|
||||
|
||||
General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker.
|
||||
The gophers there will answer or ask you to file an issue if you've tripped over a bug.
|
||||
For change proposals, see [Proposing Changes To Go](https://github.com/golang/proposal/).
|
||||
|
||||
Sensitive security-related issues should be reported to [security@golang.org](mailto:security@golang.org).
|
||||
|
||||
@@ -28,6 +32,7 @@ before sending patches.
|
||||
**We do not accept GitHub pull requests**
|
||||
(we use [an instance](https://go-review.googlesource.com/) of the
|
||||
[Gerrit](https://www.gerritcodereview.com/) code review system instead).
|
||||
Also, please do not post patches on the issue tracker.
|
||||
|
||||
Unless otherwise noted, the Go source files are distributed under
|
||||
the BSD-style license found in the LICENSE file.
|
||||
|
||||
44
CONTRIBUTORS
44
CONTRIBUTORS
@@ -55,11 +55,13 @@ Alan Donovan <adonovan@google.com>
|
||||
Alan Shreve <alan@inconshreveable.com>
|
||||
Albert Nigmatzianov <albertnigma@gmail.com>
|
||||
Albert Strasheim <fullung@gmail.com>
|
||||
Albert Yu <yukinying@gmail.com>
|
||||
Alberto Bertogli <albertito@blitiri.com.ar>
|
||||
Alberto Donizetti <alb.donizetti@gmail.com>
|
||||
Alberto García Hierro <alberto@garciahierro.com> <alberto.garcia.hierro@gmail.com>
|
||||
Aleksandar Dezelin <dezelin@gmail.com>
|
||||
Alessandro Arzilli <alessandro.arzilli@gmail.com>
|
||||
Alessandro Baffa <alessandro.baffa@gmail.com>
|
||||
Alex A Skinner <alex@lx.lc>
|
||||
Alex Brainman <alex.brainman@gmail.com>
|
||||
Alex Bramley <abramley@google.com>
|
||||
@@ -73,6 +75,7 @@ Alex Vaghin <crhyme@google.com>
|
||||
Alexander Demakin <alexander.demakin@gmail.com>
|
||||
Alexander Döring <email@alexd.ch>
|
||||
Alexander Larsson <alexander.larsson@gmail.com>
|
||||
Alexander Menzhinsky <amenzhinsky@gmail.com>
|
||||
Alexander Morozov <lk4d4math@gmail.com>
|
||||
Alexander Neumann <alexander@bumpern.de>
|
||||
Alexander Orlov <alexander.orlov@loxal.net>
|
||||
@@ -81,6 +84,7 @@ Alexander Surma <surma@surmair.de>
|
||||
Alexander Zhavnerchik <alex.vizor@gmail.com>
|
||||
Alexander Zolotov <goldifit@gmail.com>
|
||||
Alexandre Cesaro <alexandre.cesaro@gmail.com>
|
||||
Alexandre Fiori <fiorix@gmail.com>
|
||||
Alexandre Normand <alexandre.normand@gmail.com>
|
||||
Alexandru Moșoi <brtzsnr@gmail.com>
|
||||
Alexei Sholik <alcosholik@gmail.com>
|
||||
@@ -101,6 +105,7 @@ Andreas Litt <andreas.litt@gmail.com>
|
||||
Andrei Korzhevskii <a.korzhevskiy@gmail.com>
|
||||
Andrei Vieru <euvieru@gmail.com>
|
||||
Andres Erbsen <andreser@google.com>
|
||||
Andrew Austin <andrewaclt@gmail.com>
|
||||
Andrew Balholm <andybalholm@gmail.com>
|
||||
Andrew Bonventre <andybons@chromium.org>
|
||||
Andrew Bursavich <abursavich@gmail.com>
|
||||
@@ -123,6 +128,7 @@ Andrey Petrov <andrey.petrov@shazow.net>
|
||||
Andriy Lytvynov <lytvynov.a.v@gmail.com>
|
||||
Andy Balholm <andy@balholm.com>
|
||||
Andy Davis <andy@bigandian.com>
|
||||
Andy Finkenstadt <afinkenstadt@zynga.com>
|
||||
Andy Maloney <asmaloney@gmail.com>
|
||||
Anfernee Yongkun Gui <anfernee.gui@gmail.com>
|
||||
Angelo Bulfone <mbulfone@gmail.com>
|
||||
@@ -133,6 +139,8 @@ Anthony Canino <anthony.canino1@gmail.com>
|
||||
Anthony Eufemio <anthony.eufemio@gmail.com>
|
||||
Anthony Martin <ality@pbrane.org>
|
||||
Anthony Starks <ajstarks@gmail.com>
|
||||
Anthony Woods <awoods@raintank.io>
|
||||
Antonio Bibiano <antbbn@gmail.com>
|
||||
Antonio Murdaca <runcom@redhat.com>
|
||||
Apisak Darakananda <pongad@gmail.com>
|
||||
Aram Hăvărneanu <aram@mgk.ro>
|
||||
@@ -155,10 +163,12 @@ Austin Clements <austin@google.com> <aclements@csail.mit.edu>
|
||||
awaw fumin <awawfumin@gmail.com>
|
||||
Ayanamist Yang <ayanamist@gmail.com>
|
||||
Aymerick Jéhanne <aymerick@jehanne.org>
|
||||
Baiju Muthukadan <baiju.m.mail@gmail.com>
|
||||
Balazs Lecz <leczb@google.com>
|
||||
Ben Burkert <ben@benburkert.com>
|
||||
Ben Eitzen <eitzenb@golang.org>
|
||||
Ben Fried <ben.fried@gmail.com>
|
||||
Ben Lubar <ben.lubar@gmail.com>
|
||||
Ben Lynn <benlynn@gmail.com>
|
||||
Ben Olive <sionide21@gmail.com>
|
||||
Benjamin Black <b@b3k.us>
|
||||
@@ -233,6 +243,7 @@ Chris Kastorff <encryptio@gmail.com>
|
||||
Chris Lennert <calennert@gmail.com>
|
||||
Chris Manghane <cmang@golang.org>
|
||||
Chris McGee <sirnewton_01@yahoo.ca> <newton688@gmail.com>
|
||||
Chris Stockton <chrisstocktonaz@gmail.com>
|
||||
Chris Zou <chriszou@ca.ibm.com>
|
||||
Christian Couder <chriscool@tuxfamily.org>
|
||||
Christian Himpel <chressie@googlemail.com> <chressie@gmail.com>
|
||||
@@ -305,6 +316,7 @@ David Glasser <glasser@meteor.com>
|
||||
David Howden <dhowden@gmail.com>
|
||||
David Hubbard <dsp@google.com>
|
||||
David Jakob Fritz <david.jakob.fritz@gmail.com>
|
||||
David Lazar <lazard@golang.org>
|
||||
David Leon Gil <coruus@gmail.com>
|
||||
David McLeish <davemc@google.com>
|
||||
David Presotto <presotto@gmail.com>
|
||||
@@ -360,6 +372,7 @@ Egon Elbre <egonelbre@gmail.com>
|
||||
Ehren Kret <ehren.kret@gmail.com>
|
||||
Eivind Uggedal <eivind@uggedal.com>
|
||||
Elias Naur <elias.naur@gmail.com>
|
||||
Elliot Morrison-Reed <elliotmr@gmail.com>
|
||||
Emil Hessman <c.emil.hessman@gmail.com> <emil@hessman.se>
|
||||
Emmanuel Odeke <emm.odeke@gmail.com> <odeke@ualberta.ca>
|
||||
Eoghan Sherry <ejsherry@gmail.com>
|
||||
@@ -379,6 +392,7 @@ Ernest Chiang <ernest_chiang@htc.com>
|
||||
Esko Luontola <esko.luontola@gmail.com>
|
||||
Ethan Burns <eaburns@google.com>
|
||||
Ethan Miller <eamiller@us.ibm.com>
|
||||
Euan Kemp <euank@euank.com>
|
||||
Evan Broder <evan@stripe.com>
|
||||
Evan Brown <evanbrown@google.com>
|
||||
Evan Kroske <evankroske@google.com>
|
||||
@@ -449,6 +463,7 @@ Han-Wen Nienhuys <hanwen@google.com>
|
||||
Hari haran <hariharan.uno@gmail.com>
|
||||
Hariharan Srinath <srinathh@gmail.com>
|
||||
Harley Laue <losinggeneration@gmail.com>
|
||||
Harry Moreno <morenoh149@gmail.com>
|
||||
Harshavardhana <hrshvardhana@gmail.com>
|
||||
Håvard Haugen <havard.haugen@gmail.com>
|
||||
Hector Chu <hectorchu@gmail.com>
|
||||
@@ -470,6 +485,7 @@ Ian Gudger <ian@loosescre.ws>
|
||||
Ian Lance Taylor <iant@golang.org>
|
||||
Icarus Sparry <golang@icarus.freeuk.com>
|
||||
Idora Shinatose <idora.shinatose@gmail.com>
|
||||
Igor Bernstein <igorbernstein@google.com>
|
||||
Igor Dolzhikov <bluesriverz@gmail.com>
|
||||
Ilya Tocar <ilya.tocar@intel.com>
|
||||
INADA Naoki <songofacandy@gmail.com>
|
||||
@@ -518,6 +534,7 @@ Jan Ziak <0xe2.0x9a.0x9b@gmail.com>
|
||||
Jani Monoses <jani.monoses@ubuntu.com> <jani.monoses@gmail.com>
|
||||
Jaroslavas Počepko <jp@webmaster.ms>
|
||||
Jason Barnett <jason.w.barnett@gmail.com>
|
||||
Jason Buberel <jbuberel@google.com>
|
||||
Jason Del Ponte <delpontej@gmail.com>
|
||||
Jason Hall <jasonhall@google.com>
|
||||
Jason Smale <jsmale@zendesk.com>
|
||||
@@ -537,6 +554,7 @@ Jeremy Jackins <jeremyjackins@gmail.com>
|
||||
Jeremy Schlatter <jeremy.schlatter@gmail.com>
|
||||
Jeroen Bobbeldijk <jerbob92@gmail.com>
|
||||
Jess Frazelle <me@jessfraz.com>
|
||||
Jesse Szwedko <jesse.szwedko@gmail.com>
|
||||
Jihyun Yu <yjh0502@gmail.com>
|
||||
Jim Cote <jfcote87@gmail.com>
|
||||
Jim Kingdon <jim@bolt.me>
|
||||
@@ -586,6 +604,8 @@ Jonathan Rudenberg <jonathan@titanous.com>
|
||||
Jonathan Wills <runningwild@gmail.com>
|
||||
Jongmin Kim <atomaths@gmail.com>
|
||||
Joonas Kuorilehto <joneskoo@derbian.fi>
|
||||
Joop Kiefte <ikojba@gmail.com> <joop@kiefte.net>
|
||||
Jordan Lewis <jordanthelewis@gmail.com>
|
||||
Jos Visser <josv@google.com>
|
||||
Jose Luis Vázquez González <josvazg@gmail.com>
|
||||
Joseph Bonneau <jcb@google.com>
|
||||
@@ -617,8 +637,10 @@ Kang Hu <hukangustc@gmail.com>
|
||||
Karan Dhiman <karandhi@ca.ibm.com>
|
||||
Kato Kazuyoshi <kato.kazuyoshi@gmail.com>
|
||||
Katrina Owen <katrina.owen@gmail.com>
|
||||
Kaviraj Kanagaraj <kavirajkanagaraj@gmail.com>
|
||||
Kay Zhu <kayzhu@google.com>
|
||||
KB Sriram <kbsriram@google.com>
|
||||
Keegan Carruthers-Smith <keegan.csmith@gmail.com>
|
||||
Kei Son <hey.calmdown@gmail.com>
|
||||
Keith Ball <inflatablewoman@gmail.com>
|
||||
Keith Randall <khr@golang.org>
|
||||
@@ -670,6 +692,7 @@ Luke Curley <qpingu@gmail.com>
|
||||
Luna Duclos <luna.duclos@palmstonegames.com>
|
||||
Luuk van Dijk <lvd@golang.org> <lvd@google.com>
|
||||
Lynn Boger <laboger@linux.vnet.ibm.com>
|
||||
Maksym Trykur <maksym.trykur@gmail.com>
|
||||
Mal Curtis <mal@mal.co.nz>
|
||||
Manfred Touron <m@42.am>
|
||||
Manoj Dayaram <platform-dev@moovweb.com> <manoj.dayaram@moovweb.com>
|
||||
@@ -678,9 +701,11 @@ Manu S Ajith <neo@codingarena.in>
|
||||
Manuel Mendez <mmendez534@gmail.com>
|
||||
Marc Weistroff <marc@weistroff.net>
|
||||
Marc-Antoine Ruel <maruel@chromium.org>
|
||||
Marcel Edmund Franke <marcel.edmund.franke@gmail.com>
|
||||
Marcel van Lohuizen <mpvl@golang.org>
|
||||
Marco Hennings <marco.hennings@freiheit.com>
|
||||
Marga Manterola <marga@google.com>
|
||||
Marin Bašić <marin.basic02@gmail.com>
|
||||
Marius Nuennerich <mnu@google.com>
|
||||
Mark Bucciarelli <mkbucc@gmail.com>
|
||||
Mark Severson <miquella@gmail.com>
|
||||
@@ -695,6 +720,7 @@ Markus Zimmermann <zimmski@gmail.com>
|
||||
Martin Bertschler <mbertschler@gmail.com>
|
||||
Martin Garton <garton@gmail.com>
|
||||
Martin Hamrle <martin.hamrle@gmail.com>
|
||||
Martin Kreichgauer <martinkr@google.com>
|
||||
Martin Möhrmann <moehrmann@google.com> <martisch@uos.de>
|
||||
Martin Neubauer <m.ne@gmx.net>
|
||||
Martin Olsson <martin@minimum.se>
|
||||
@@ -723,6 +749,8 @@ Matthew Denton <mdenton@skyportsystems.com>
|
||||
Matthew Holt <Matthew.Holt+git@gmail.com>
|
||||
Matthew Horsnell <matthew.horsnell@gmail.com>
|
||||
Matthieu Hauglustaine <matt.hauglustaine@gmail.com>
|
||||
Matthieu Olivier <olivier.matthieu@gmail.com>
|
||||
Max Riveiro <kavu13@gmail.com>
|
||||
Maxim Khitrov <max@mxcrypt.com>
|
||||
Maxim Pimenov <mpimenov@google.com>
|
||||
Maxim Ushakov <ushakov@google.com>
|
||||
@@ -806,6 +834,7 @@ Nicholas Waples <nwaples@gmail.com>
|
||||
Nick Cooper <nmvc@google.com>
|
||||
Nick Craig-Wood <nick@craig-wood.com> <nickcw@gmail.com>
|
||||
Nick Harper <nharper@google.com>
|
||||
Nick Leli <nicholasleli@gmail.com>
|
||||
Nick Patavalis <nick.patavalis@gmail.com>
|
||||
Nick Petroni <npetroni@cs.umd.edu>
|
||||
Nicolas Kaiser <nikai@nikai.net>
|
||||
@@ -814,11 +843,13 @@ Nicolas S. Dade <nic.dade@gmail.com>
|
||||
Niels Widger <niels.widger@gmail.com>
|
||||
Nigel Kerr <nigel.kerr@gmail.com>
|
||||
Nigel Tao <nigeltao@golang.org>
|
||||
Nik Nyby <nnyby@columbia.edu>
|
||||
Niko Dziemba <niko@dziemba.com>
|
||||
Nikolay Turpitko <nikolay@turpitko.com>
|
||||
Noah Campbell <noahcampbell@gmail.com>
|
||||
Nodir Turakulov <nodir@google.com>
|
||||
Norberto Lopes <nlopes.ml@gmail.com>
|
||||
Odin Ugedal <odin@ugedal.com>
|
||||
Oleg Vakheta <helginet@gmail.com>
|
||||
Oleku Konko <oleku.konko@gmail.com>
|
||||
Oling Cat <olingcat@gmail.com>
|
||||
@@ -837,6 +868,7 @@ Pascal S. de Kloe <pascal@quies.net>
|
||||
Patrick Crosby <patrick@stathat.com>
|
||||
Patrick Gavlin <pgavlin@gmail.com>
|
||||
Patrick Higgins <patrick.allen.higgins@gmail.com>
|
||||
Patrick Lee <pattyshack101@gmail.com>
|
||||
Patrick Mézard <patrick@mezard.eu>
|
||||
Patrick Mylund Nielsen <patrick@patrickmn.com>
|
||||
Patrick Riley <pfr@google.com>
|
||||
@@ -894,15 +926,19 @@ Quan Tran <qeed.quan@gmail.com>
|
||||
Quan Yong Zhai <qyzhai@gmail.com>
|
||||
Quentin Perez <qperez@ocs.online.net>
|
||||
Quentin Smith <quentin@golang.org>
|
||||
Quinn Slack <sqs@sourcegraph.com>
|
||||
Quoc-Viet Nguyen <afelion@gmail.com>
|
||||
Radu Berinde <radu@cockroachlabs.com>
|
||||
Rafal Jeczalik <rjeczalik@gmail.com>
|
||||
Rahul Chaudhry <rahulchaudhry@chromium.org>
|
||||
Raif S. Naffah <go@naffah-raif.name>
|
||||
Rajat Goel <rajat.goel2010@gmail.com>
|
||||
Ralph Corderoy <ralph@inputplus.co.uk>
|
||||
Ramesh Dharan <dharan@google.com>
|
||||
Raph Levien <raph@google.com>
|
||||
Raphael Geronimi <raphael.geronimi@gmail.com>
|
||||
Raul Silvera <rsilvera@google.com>
|
||||
Rebecca Stambler <rstambler@golang.org>
|
||||
Reinaldo de Souza Jr <juniorz@gmail.com>
|
||||
Rémy Oudompheng <oudomphe@phare.normalesup.org> <remyoudompheng@gmail.com>
|
||||
Rhys Hiltner <rhys@justin.tv>
|
||||
@@ -943,12 +979,14 @@ Rowan Worth <sqweek@gmail.com>
|
||||
Rui Ueyama <ruiu@google.com>
|
||||
Russ Cox <rsc@golang.org>
|
||||
Russell Haering <russellhaering@gmail.com>
|
||||
Ryan Bagwell <ryanbagwell@outlook.com>
|
||||
Ryan Barrett <ryanb@google.com>
|
||||
Ryan Brown <ribrdb@google.com>
|
||||
Ryan Hitchman <hitchmanr@gmail.com>
|
||||
Ryan Lower <rpjlower@gmail.com>
|
||||
Ryan Seys <ryan@ryanseys.com>
|
||||
Ryan Slade <ryanslade@gmail.com>
|
||||
Ryuzo Yamamoto <ryuzo.yamamoto@gmail.com>
|
||||
S.Çağlar Onur <caglar@10ur.org>
|
||||
Sai Cheemalapati <saicheems@google.com>
|
||||
Salmān Aljammāz <s@0x65.net>
|
||||
@@ -1012,6 +1050,7 @@ Stéphane Travostino <stephane.travostino@gmail.com>
|
||||
Stephen Ma <stephenm@golang.org>
|
||||
Stephen McQuay <stephen@mcquay.me>
|
||||
Stephen Weinberg <stephen@q5comm.com>
|
||||
Steve Francia <spf@golang.org>
|
||||
Steve McCoy <mccoyst@gmail.com>
|
||||
Steve Newman <snewman@google.com>
|
||||
Steve Phillips <elimisteve@gmail.com>
|
||||
@@ -1029,6 +1068,7 @@ Tad Glines <tad.glines@gmail.com>
|
||||
Taj Khattra <taj.khattra@gmail.com>
|
||||
Takashi Matsuo <tmatsuo@google.com>
|
||||
Takeshi YAMANASHI <9.nashi@gmail.com>
|
||||
Takuya Ueda <uedatakuya@gmail.com>
|
||||
Tal Shprecher <tshprecher@gmail.com>
|
||||
Tamir Duberstein <tamird@gmail.com>
|
||||
Tarmigan Casebolt <tarmigan@gmail.com>
|
||||
@@ -1044,6 +1084,7 @@ Thomas Desrosiers <thomasdesr@gmail.com>
|
||||
Thomas Habets <habets@google.com>
|
||||
Thomas Kappler <tkappler@gmail.com>
|
||||
Thorben Krueger <thorben.krueger@gmail.com>
|
||||
Thordur Bjornsson <thorduri@secnorth.net>
|
||||
Tilman Dilo <tilman.dilo@gmail.com>
|
||||
Tim Cooijmans <timcooijmans@gmail.com>
|
||||
Tim Ebringer <tim.ebringer@gmail.com>
|
||||
@@ -1072,6 +1113,7 @@ Trevor Strohman <trevor.strohman@gmail.com>
|
||||
Trey Lawrence <lawrence.trey@gmail.com>
|
||||
Trey Tacon <ttacon@gmail.com>
|
||||
Tristan Amini <tamini01@ca.ibm.com>
|
||||
Tristan Colgate <tcolgate@gmail.com>
|
||||
Tristan Ooohry <ooohry@gmail.com>
|
||||
Tudor Golubenco <tudor.g@gmail.com>
|
||||
Tuo Shan <sturbo89@gmail.com> <shantuo@google.com>
|
||||
@@ -1132,8 +1174,10 @@ Yusuke Kagiwada <block.rxckin.beats@gmail.com>
|
||||
Yuusei Kuwana <kuwana@kumama.org>
|
||||
Yuval Pavel Zholkover <paulzhol@gmail.com>
|
||||
Yves Junqueira <yvesj@google.com> <yves.junqueira@gmail.com>
|
||||
Zac Bergquist <zbergquist99@gmail.com>
|
||||
Zev Goldstein <zev.goldstein@gmail.com>
|
||||
Zhongwei Yao <zhongwei.yao@arm.com>
|
||||
Ziad Hatahet <hatahet@gmail.com>
|
||||
Zorion Arrizabalaga <zorionk@gmail.com>
|
||||
Фахриддин Балтаев <faxriddinjon@gmail.com>
|
||||
申习之 <bronze1man@gmail.com>
|
||||
|
||||
@@ -338,3 +338,7 @@ pkg unicode, const Version = "6.2.0"
|
||||
pkg unicode, const Version = "6.3.0"
|
||||
pkg unicode, const Version = "7.0.0"
|
||||
pkg unicode, const Version = "8.0.0"
|
||||
pkg syscall (openbsd-386), const SYS_KILL = 37
|
||||
pkg syscall (openbsd-386-cgo), const SYS_KILL = 37
|
||||
pkg syscall (openbsd-amd64), const SYS_KILL = 37
|
||||
pkg syscall (openbsd-amd64-cgo), const SYS_KILL = 37
|
||||
|
||||
@@ -73,10 +73,8 @@ pkg database/sql, const LevelSnapshot = 5
|
||||
pkg database/sql, const LevelSnapshot IsolationLevel
|
||||
pkg database/sql, const LevelWriteCommitted = 3
|
||||
pkg database/sql, const LevelWriteCommitted IsolationLevel
|
||||
pkg database/sql/driver, func IsolationFromContext(context.Context) (IsolationLevel, bool)
|
||||
pkg database/sql/driver, func ReadOnlyFromContext(context.Context) bool
|
||||
pkg database/sql/driver, type ConnBeginContext interface { BeginContext }
|
||||
pkg database/sql/driver, type ConnBeginContext interface, BeginContext(context.Context) (Tx, error)
|
||||
pkg database/sql/driver, type ConnBeginTx interface { BeginTx }
|
||||
pkg database/sql/driver, type ConnBeginTx interface, BeginTx(context.Context, TxOptions) (Tx, error)
|
||||
pkg database/sql/driver, type ConnPrepareContext interface { PrepareContext }
|
||||
pkg database/sql/driver, type ConnPrepareContext interface, PrepareContext(context.Context, string) (Stmt, error)
|
||||
pkg database/sql/driver, type ExecerContext interface { ExecContext }
|
||||
@@ -125,16 +123,17 @@ pkg database/sql/driver, type StmtExecContext interface { ExecContext }
|
||||
pkg database/sql/driver, type StmtExecContext interface, ExecContext(context.Context, []NamedValue) (Result, error)
|
||||
pkg database/sql/driver, type StmtQueryContext interface { QueryContext }
|
||||
pkg database/sql/driver, type StmtQueryContext interface, QueryContext(context.Context, []NamedValue) (Rows, error)
|
||||
pkg database/sql, func IsolationContext(context.Context, IsolationLevel) context.Context
|
||||
pkg database/sql/driver, type TxOptions struct
|
||||
pkg database/sql/driver, type TxOptions struct, Isolation IsolationLevel
|
||||
pkg database/sql/driver, type TxOptions struct, ReadOnly bool
|
||||
pkg database/sql, func Named(string, interface{}) NamedArg
|
||||
pkg database/sql, func ReadOnlyContext(context.Context) context.Context
|
||||
pkg database/sql, method (*ColumnType) DatabaseTypeName() string
|
||||
pkg database/sql, method (*ColumnType) DecimalSize() (int64, int64, bool)
|
||||
pkg database/sql, method (*ColumnType) Length() (int64, bool)
|
||||
pkg database/sql, method (*ColumnType) Name() string
|
||||
pkg database/sql, method (*ColumnType) Nullable() (bool, bool)
|
||||
pkg database/sql, method (*ColumnType) ScanType() reflect.Type
|
||||
pkg database/sql, method (*DB) BeginContext(context.Context) (*Tx, error)
|
||||
pkg database/sql, method (*DB) BeginTx(context.Context, *TxOptions) (*Tx, error)
|
||||
pkg database/sql, method (*DB) ExecContext(context.Context, string, ...interface{}) (Result, error)
|
||||
pkg database/sql, method (*DB) PingContext(context.Context) error
|
||||
pkg database/sql, method (*DB) PrepareContext(context.Context, string) (*Stmt, error)
|
||||
@@ -155,7 +154,9 @@ pkg database/sql, type IsolationLevel int
|
||||
pkg database/sql, type NamedArg struct
|
||||
pkg database/sql, type NamedArg struct, Name string
|
||||
pkg database/sql, type NamedArg struct, Value interface{}
|
||||
pkg debug/gosym, func PCValue([]uint8, uint64, int) int
|
||||
pkg database/sql, type TxOptions struct
|
||||
pkg database/sql, type TxOptions struct, Isolation IsolationLevel
|
||||
pkg database/sql, type TxOptions struct, ReadOnly bool
|
||||
pkg debug/pe, method (*COFFSymbol) FullName(StringTable) (string, error)
|
||||
pkg debug/pe, method (StringTable) String(uint32) (string, error)
|
||||
pkg debug/pe, type File struct, COFFSymbols []COFFSymbol
|
||||
@@ -175,7 +176,6 @@ pkg expvar, method (*Float) Value() float64
|
||||
pkg expvar, method (Func) Value() interface{}
|
||||
pkg expvar, method (*Int) Value() int64
|
||||
pkg expvar, method (*String) Value() string
|
||||
pkg go/build, type NoGoError struct, Ignored bool
|
||||
pkg go/doc, func IsPredeclared(string) bool
|
||||
pkg go/types, func Default(Type) Type
|
||||
pkg go/types, func IdenticalIgnoreTags(Type, Type) bool
|
||||
@@ -239,21 +239,23 @@ pkg plugin, type Symbol interface {}
|
||||
pkg reflect, func Swapper(interface{}) func(int, int)
|
||||
pkg runtime, func MutexProfile([]BlockProfileRecord) (int, bool)
|
||||
pkg runtime, func SetMutexProfileFraction(int) int
|
||||
pkg runtime, type MemStats struct, NumForcedGC uint32
|
||||
pkg sort, func Slice(interface{}, func(int, int) bool)
|
||||
pkg sort, func SliceIsSorted(interface{}, func(int, int) bool) bool
|
||||
pkg sort, func SliceStable(interface{}, func(int, int) bool)
|
||||
pkg syscall (linux-arm-cgo), func TimevalToNsec(Timeval) int64
|
||||
pkg syscall (linux-arm), func TimevalToNsec(Timeval) int64
|
||||
pkg syscall (openbsd-386), const SYS_KILL = 122
|
||||
pkg syscall (openbsd-386-cgo), const SYS_KILL = 122
|
||||
pkg syscall (openbsd-amd64), const SYS_KILL = 122
|
||||
pkg syscall (openbsd-amd64-cgo), const SYS_KILL = 122
|
||||
pkg syscall (windows-386), const ERROR_DIR_NOT_EMPTY = 145
|
||||
pkg syscall (windows-386), const ERROR_DIR_NOT_EMPTY Errno
|
||||
pkg syscall (windows-amd64), const ERROR_DIR_NOT_EMPTY = 145
|
||||
pkg syscall (windows-amd64), const ERROR_DIR_NOT_EMPTY Errno
|
||||
pkg testing, func CoverMode() string
|
||||
pkg testing, func MainStart(testDeps, []InternalTest, []InternalBenchmark, []InternalExample) *M
|
||||
pkg testing, method (*B) Context() context.Context
|
||||
pkg testing, method (*B) Name() string
|
||||
pkg testing, method (*T) Context() context.Context
|
||||
pkg testing, method (*T) Name() string
|
||||
pkg testing, type TB interface, Context() context.Context
|
||||
pkg testing, type TB interface, Name() string
|
||||
pkg time, func Until(Time) Duration
|
||||
|
||||
38
doc/asm.html
38
doc/asm.html
@@ -838,6 +838,44 @@ It is a scaled mode as on the x86, but the only scale allowed is <code>1</code>.
|
||||
|
||||
</ul>
|
||||
|
||||
<h3 id="mips">MIPS, MIPS64</h3>
|
||||
|
||||
<p>
|
||||
General purpose registers are named <code>R0</code> through <code>R31</code>,
|
||||
floating point registers are <code>F0</code> through <code>F31</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<code>R30</code> is reserved to point to <code>g</code>.
|
||||
<code>R23</code> is used as a temporary register.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In a <code>TEXT</code> directive, the frame size <code>$-4</code> for MIPS or
|
||||
<code>$-8</code> for MIPS64 instructs the linker not to save <code>LR</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<code>SP</code> refers to the virtual stack pointer.
|
||||
For the hardware register, use <code>R29</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Addressing modes:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
<code>16(R1)</code>: The location at <code>R1</code> plus 16.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<code>(R1)</code>: Alias for <code>0(R1)</code>.
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<h3 id="unsupported_opcodes">Unsupported opcodes</h3>
|
||||
|
||||
<p>
|
||||
|
||||
@@ -160,9 +160,13 @@ $ <b>export GOPATH=$(go env GOPATH)</b>
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
To learn more about setting up the <code>GOPATH</code> environment variable,
|
||||
please see
|
||||
<a href="/cmd/go/#hdr-GOPATH_environment_variable"><code>'go help gopath'</code></a>
|
||||
To learn more about the <code>GOPATH</code> environment variable, see
|
||||
<a href="/cmd/go/#hdr-GOPATH_environment_variable"><code>'go help gopath'</code></a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To use a custom workspace location,
|
||||
<a href="https://golang.org/wiki/SettingGOPATH">set the <code>GOPATH</code> environment variable</a>.
|
||||
</p>
|
||||
|
||||
<h3 id="ImportPaths">Import paths</h3>
|
||||
|
||||
@@ -67,7 +67,6 @@ official forums operated by the Go project (“Go spaces”):
|
||||
<li>The <a href="https://groups.google.com/group/golang-nuts">golang-nuts</a> and
|
||||
<a href="https://groups.google.com/group/golang-dev">golang-dev</a> mailing lists.
|
||||
<li>The #go-nuts IRC channel on Freenode.
|
||||
<li>The <a href="https://reddit.com/r/golang">/r/golang subreddit</a>.
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
|
||||
@@ -50,11 +50,23 @@ See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.7.1">Go
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.7.2 (released 2016/10/17) includes fixes to the compiler, runtime,
|
||||
go1.7.2 should not be used. It was tagged but not fully released.
|
||||
The release was deferred due to a last minute bug report.
|
||||
Use go1.7.3 instead, and refer to the summary of changes below.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.7.3 (released 2016/10/19) includes fixes to the compiler, runtime,
|
||||
and the <code>crypto/cipher</code>, <code>crypto/tls</code>,
|
||||
<code>net/http</code>, and <code>strings</code> packages.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.7.2">Go
|
||||
1.7.2 milestone</a> on our issue tracker for details.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.7.3">Go
|
||||
1.7.3 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.7.4 (released 2016/12/01) includes two security fixes.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.7.4">Go
|
||||
1.7.4 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<h2 id="go1.6">go1.6 (released 2016/02/17)</h2>
|
||||
@@ -88,6 +100,13 @@ See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.6.3">Go
|
||||
1.6.3 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.6.4 (released 2016/12/01) includes two security fixes.
|
||||
It contains the same fixes as Go 1.7.4 and was released at the same time.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.7.4">Go
|
||||
1.7.4 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<h2 id="go1.5">go1.5 (released 2015/08/19)</h2>
|
||||
|
||||
<p>
|
||||
|
||||
@@ -519,7 +519,7 @@ Other changes:
|
||||
fix FreeBSD signal handling around thread creation (thanks Devon H. O'Dell),
|
||||
goroutine profile, stack dumps,
|
||||
implement runtime.osyield on FreeBSD 386, amd64 (thanks Devon H. O'Dell),
|
||||
permit default behaviour of SIGTSTP, SIGTTIN, SIGTTOU,
|
||||
permit default behavior of SIGTSTP, SIGTTIN, SIGTTOU,
|
||||
release unused memory to the OS (thanks Sébastien Paolacci),
|
||||
remove an obsolete file (thanks Mikio Hara).
|
||||
* spec: make all comparison results untyped bool,
|
||||
@@ -4157,7 +4157,7 @@ Other changes in this release:
|
||||
* suffixarray: use binary search for both ends of Lookup (thanks Eric Eisner).
|
||||
* syscall: add missing network interface constants (thanks Mikio Hara).
|
||||
* template: treat map keys as zero, not non-existent (thanks Roger Peppe).
|
||||
* time: allow cancelling of After events (thanks Roger Peppe),
|
||||
* time: allow canceling of After events (thanks Roger Peppe),
|
||||
support Solaris zoneinfo directory.
|
||||
* token/position: added SetLinesForContent.
|
||||
* unicode: update to unicode 6.0.0.
|
||||
@@ -5696,7 +5696,7 @@ This release contains many changes:
|
||||
* cmath: new complex math library (thanks Charles L. Dorian).
|
||||
* docs: update to match current coding style (thanks Christopher Wedgwood).
|
||||
* exp/eval: fix example and add target to Makefile (thanks Evan Shaw).
|
||||
* fmt: change behaviour of format verb %b to match %x when negative (thanks Andrei Vieru).
|
||||
* fmt: change behavior of format verb %b to match %x when negative (thanks Andrei Vieru).
|
||||
* gc: compile s == "" as len(s) == 0,
|
||||
distinguish fatal compiler bug from error+exit,
|
||||
fix alignment on non-amd64,
|
||||
|
||||
444
doc/go1.8.html
444
doc/go1.8.html
@@ -25,7 +25,7 @@ release notes. Go 1.8 is expected to be released in February 2017.
|
||||
<p>
|
||||
The latest Go release, version 1.8, arrives six months after <a href="go1.7">Go 1.7</a>.
|
||||
Most of its changes are in the implementation of the toolchain, runtime, and libraries.
|
||||
There is one minor change to the language specification.
|
||||
There are <a href="#language">two minor changes</a> to the language specification.
|
||||
As always, the release maintains the Go 1 <a href="/doc/go1compat.html">promise of compatibility</a>.
|
||||
We expect almost all Go programs to continue to compile and run as before.
|
||||
</p>
|
||||
@@ -44,8 +44,9 @@ and <a href="#sort_slice">simplifies sorting slices</a>.
|
||||
<h2 id="language">Changes to the language</h2>
|
||||
|
||||
<p>
|
||||
When explicitly converting a value from one struct type to another, as of Go 1. 8 the tags are ignored.
|
||||
Thus two structs that differ only in their tags may be converted from one to the other:
|
||||
When explicitly converting a value from one struct type to another,
|
||||
as of Go 1.8 the tags are ignored. Thus two structs that differ
|
||||
only in their tags may be converted from one to the other:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
@@ -76,13 +77,19 @@ func example() {
|
||||
<p>
|
||||
Go now supports 32-bit MIPS on Linux for both big-endian
|
||||
(<code>linux/mips</code>) and little-endian machines
|
||||
(<code>linux/mipsle</code>).
|
||||
(<code>linux/mipsle</code>) that implement the MIPS32r1 instruction set with FPU
|
||||
or kernel FPU emulation. Note that many common MIPS-based routers lack an FPU and
|
||||
have firmware that doesn't enable kernel FPU emulation; Go won't run on such machines.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
On DragonFly BSD, Go now requires DragonFly 4.4.4 or later. <!-- CL 29491, CL 29971 -->
|
||||
</p>
|
||||
|
||||
<p>
|
||||
On OpenBSD, Go now requires OpenBSD 5.9 or later. <!-- CL 34093 -->
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The Plan 9 port's networking support is now much more complete
|
||||
and matches the behavior of Unix and Windows with respect to deadlines
|
||||
@@ -95,6 +102,18 @@ and cancelation.
|
||||
binaries on older OS X versions is untested.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Go 1.8 will be the last release to support Linux on ARMv5E and ARMv6 processors:
|
||||
Go 1.9 will likely require the ARMv6K (as found in the Raspberry Pi 1) or later.
|
||||
To identify whether a Linux system is ARMv6K or later, run
|
||||
“<code>go</code> <code>tool</code> <code>dist</code> <code>-check-armv6k</code>”
|
||||
(to facilitate testing, it is also possible to just copy the <code>dist</code> command to the
|
||||
system without installing a full copy of Go 1.8)
|
||||
and if the program terminates with output "ARMv6K supported." then the system
|
||||
implements ARMv6K or later.
|
||||
Go on non-Linux ARM systems already requires ARMv6K or later.
|
||||
</p>
|
||||
|
||||
|
||||
<h3 id="known_issues">Known Issues</h3>
|
||||
|
||||
@@ -102,8 +121,7 @@ and cancelation.
|
||||
There are some instabilities on FreeBSD and NetBSD that are known but not understood.
|
||||
These can lead to program crashes in rare cases.
|
||||
See
|
||||
<a href="https://golang.org/issue/15658">issue 15658</a>,
|
||||
<a href="https://golang.org/issue/16396">issue 16396</a>, and
|
||||
<a href="https://golang.org/issue/15658">issue 15658</a> and
|
||||
<a href="https://golang.org/issue/16511">issue 16511</a>.
|
||||
Any help in solving these issues would be appreciated.
|
||||
</p>
|
||||
@@ -120,8 +138,9 @@ For 64-bit x86 systems, the following instructions have been added:
|
||||
<code>MOVSHDUP</code>,
|
||||
<code>MOVSLDUP</code>,
|
||||
<code>VMOVDDUP</code>,
|
||||
<code>VMOVSHDUP</code>,
|
||||
and <code>VMOVSLDUP</code>.</p>
|
||||
<code>VMOVSHDUP</code>, and
|
||||
<code>VMOVSLDUP</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For 64-bit PPC systems, the common vector scalar instructions have been
|
||||
@@ -203,7 +222,7 @@ added:
|
||||
<code>XXSEL</code>,
|
||||
<code>XXSI</code>,
|
||||
<code>XXSLDWI</code>,
|
||||
<code>XXSPLT</code>, and
|
||||
<code>XXSPLT</code>, and
|
||||
<code>XXSPLTW</code>.
|
||||
</p>
|
||||
|
||||
@@ -211,8 +230,8 @@ added:
|
||||
|
||||
<p> <!-- CL 27324, CL 27325 -->
|
||||
The <code>yacc</code> tool (previously available by running
|
||||
“<code>go</code> <code>tool</code> <code>yacc</code>”)
|
||||
has been removed. As of Go 1.7 it was no longer used by the Go compiler.
|
||||
“<code>go</code> <code>tool</code> <code>yacc</code>”) has been removed.
|
||||
As of Go 1.7 it was no longer used by the Go compiler.
|
||||
It has moved to the “tools” repository and is now available at
|
||||
<code><a href="https://godoc.org/golang.org/x/tools/cmd/goyacc">golang.org/x/tools/cmd/goyacc</a></code>.
|
||||
</p>
|
||||
@@ -229,7 +248,7 @@ It has moved to the “tools” repository and is now available at
|
||||
|
||||
<p> <!-- CL 33157 -->
|
||||
The <code>pprof</code> tool can now profile TLS servers
|
||||
and skip certificate validation by using the "<code>https+insecure</code>"
|
||||
and skip certificate validation by using the “<code>https+insecure</code>”
|
||||
URL scheme.
|
||||
</p>
|
||||
|
||||
@@ -237,37 +256,32 @@ It has moved to the “tools” repository and is now available at
|
||||
The callgrind output now has instruction-level granularity.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
TODO: more. proto? standalone profiles with symbols?
|
||||
<pre>
|
||||
runtime/pprof: output CPU profiles in pprof protobuf format (CL 33071)
|
||||
runtime/pprof: write profiles in protobuf format. (CL 32257)
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<h3 id="tool_trace">Trace</h3>
|
||||
|
||||
<p>TODO:</p>
|
||||
<pre>
|
||||
cmd/trace: add option to output pprof files (CL 23324)
|
||||
cmd/trace: fix a runnable goroutine count bug (CL 25552)
|
||||
cmd/trace: move process-wide GC events to their own row (CL 30017)
|
||||
internal/trace: fix analysis of EvGoWaiting/EvGoInSyscall events (CL 25572)
|
||||
cmd/trace: annotate different mark worker types (CL 30702)
|
||||
</pre>
|
||||
<p> <!-- CL 23324 -->
|
||||
The <code>trace</code> tool has a new <code>-pprof</code> flag for
|
||||
producing pprof-compatible blocking and latency profiles from an
|
||||
execution trace.
|
||||
</p>
|
||||
|
||||
<p> <!-- CL 30017, CL 30702 -->
|
||||
Garbage collection events are now shown more clearly in the
|
||||
execution trace viewer. Garbage collection activity is shown on its
|
||||
own row and GC helper goroutines are annotated with their roles.
|
||||
</p>
|
||||
|
||||
<h3 id="tool_vet">Vet</h3>
|
||||
|
||||
<p>Vet is stricter in some ways and looser where it
|
||||
previously caused false positives.</p>
|
||||
|
||||
<p>Vet now checks copying of array of locks,
|
||||
<p>Vet now checks for copying an array of locks,
|
||||
duplicate JSON and XML struct field tags,
|
||||
non-space-separated struct tags,
|
||||
deferred calls to HTTP <code>Response.Body.Close</code>
|
||||
before checking errors,
|
||||
indexed arguments in <code>Printf</code>,
|
||||
and improves existing checks.</p>
|
||||
before checking errors, and
|
||||
indexed arguments in <code>Printf</code>.
|
||||
It also improves existing checks.</p>
|
||||
</p>
|
||||
|
||||
<h3 id="compiler">Compiler Toolchain</h3>
|
||||
@@ -286,14 +300,14 @@ and provides a better platform for optimizations
|
||||
such as bounds check elimination.
|
||||
The new back end reduces the CPU time required by
|
||||
<a href="https://golang.org/test/bench/go1/">our benchmark programs</a> by 20-30%
|
||||
on 32-bit ARM systems. For 64-bit x86 systems, which already used the SSA backend in
|
||||
on 32-bit ARM systems. For 64-bit x86 systems, which already used the SSA back end in
|
||||
Go 1.7, the gains are a more modest 0-10%. Other architectures will likely
|
||||
see improvements closer to the 32-bit ARM numbers.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The temporary <code>-ssa=0</code> compiler flag introduced in Go 1.7
|
||||
to disable the new backend has been removed in Go 1.8.
|
||||
to disable the new back end has been removed in Go 1.8.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -313,9 +327,21 @@ see improvements closer to the 32-bit ARM numbers.
|
||||
|
||||
<h3 id="cmd_cgo">Cgo</h3>
|
||||
|
||||
<p> <!-- CL 31141 -->
|
||||
The Go tool now remembers the value of the <code>CGO_ENABLED</code> environment
|
||||
variable set during <code>make.bash</code> and applies it to all future compilations
|
||||
by default to fix issue <a href="https://golang.org/issue/12808">#12808</a>.
|
||||
When doing native compilation, it is rarely necessary to explicitly set
|
||||
the <code>CGO_ENABLED</code> environment variable as <code>make.bash</code>
|
||||
will detect the correct setting automatically. The main reason to explicitly
|
||||
set the <code>CGO_ENABLED</code> environment variable is when your environment
|
||||
supports cgo, but you explicitly do not want cgo support, in which case, set
|
||||
<code>CGO_ENABLED=0</code> during <code>make.bash</code> or <code>all.bash</code>.
|
||||
</p>
|
||||
|
||||
<p> <!-- CL 29991 -->
|
||||
The environment variable <code>PKG_CONFIG</code> may now be used to
|
||||
set the program to run to handle <code>#cgo pkg-config</code>
|
||||
set the program to run to handle <code>#cgo</code> <code>pkg-config</code>
|
||||
directives. The default is <code>pkg-config</code>, the program
|
||||
always used by earlier releases. This is intended to make it easier
|
||||
to cross-compile
|
||||
@@ -365,12 +391,21 @@ version of gccgo.
|
||||
<code>%USERPROFILE%/go</code> on Windows.
|
||||
</p>
|
||||
|
||||
<h3 id="go_get">Go get</h3>
|
||||
|
||||
<p> <!-- CL 34818 -->
|
||||
The “<code>go</code> <code>get</code>” command now always respects
|
||||
HTTP proxy environment variables, regardless of whether
|
||||
the <code style='white-space:nowrap'>-insecure</code> flag is used. In previous releases, the
|
||||
<code style='white-space:nowrap'>-insecure</code> flag had the side effect of not using proxies.
|
||||
</p>
|
||||
|
||||
<h3 id="go_bug">Go bug</h3>
|
||||
|
||||
<p>
|
||||
The new
|
||||
“<a href="/cmd/go/#hdr-Print_information_for_bug_reports"><code>go</code>
|
||||
<code>bug</code></a>” command starts a bug report on GitHub, prefilled
|
||||
“<a href="/cmd/go/#hdr-Print_information_for_bug_reports"><code>go</code> <code>bug</code></a>”
|
||||
command starts a bug report on GitHub, prefilled
|
||||
with information about the current system.
|
||||
</p>
|
||||
|
||||
@@ -378,9 +413,8 @@ version of gccgo.
|
||||
|
||||
<p> <!-- CL 25419 -->
|
||||
The
|
||||
“<a href="/cmd/go/#hdr-Show_documentation_for_package_or_symbol"><code>go</code>
|
||||
<code>doc</code></a>” command
|
||||
now groups constants and variables with their type,
|
||||
“<a href="/cmd/go/#hdr-Show_documentation_for_package_or_symbol"><code>go</code> <code>doc</code></a>”
|
||||
command now groups constants and variables with their type,
|
||||
following the behavior of
|
||||
<a href="/cmd/godoc/"><code>godoc</code></a>.
|
||||
</p>
|
||||
@@ -404,7 +438,7 @@ version of gccgo.
|
||||
plugins written in Go, and a
|
||||
new <a href="/pkg/plugin/"><code>plugin</code></a> package for
|
||||
loading such plugins at run time. Plugin support is only currently
|
||||
available on Linux and macOS.
|
||||
available on Linux.
|
||||
</p>
|
||||
|
||||
<h2 id="runtime">Runtime</h2>
|
||||
@@ -429,10 +463,30 @@ version of gccgo.
|
||||
documentation</a> and its example for more details.
|
||||
</p>
|
||||
|
||||
<h3 id="mapiter">Concurrent Map Misuse</h3>
|
||||
|
||||
<p>
|
||||
In Go 1.6, the runtime
|
||||
<a href="/doc/go1.6#runtime">added lightweight,
|
||||
best-effort detection of concurrent misuse of maps</a>. This release
|
||||
improves that detector with support for detecting programs that
|
||||
concurrently write to and iterate over a map.
|
||||
</p>
|
||||
<p>
|
||||
As always, if one goroutine is writing to a map, no other goroutine should be
|
||||
reading (which includes iterating) or writing the map concurrently.
|
||||
If the runtime detects this condition, it prints a diagnosis and crashes the program.
|
||||
The best way to find out more about the problem is to run the program
|
||||
under the
|
||||
<a href="https://blog.golang.org/race-detector">race detector</a>,
|
||||
which will more reliably identify the race
|
||||
and give more detail.
|
||||
</p>
|
||||
|
||||
<h3 id="memstats">MemStats Documentation</h3>
|
||||
|
||||
<p> <!-- CL 28972 -->
|
||||
The runtime's <a href="/pkg/runtime/#MemStats"><code>MemStats</code></a>
|
||||
The <a href="/pkg/runtime/#MemStats"><code>runtime.MemStats</code></a>
|
||||
type has been more thoroughly documented.
|
||||
</p>
|
||||
|
||||
@@ -470,7 +524,7 @@ There have been optimizations to implementations in the
|
||||
<a href="/pkg/strings/"><code>strings</code></a>,
|
||||
<a href="/pkg/syscall/"><code>syscall</code></a>,
|
||||
<a href="/pkg/text/template/"><code>text/template</code></a>, and
|
||||
<a href="/pkg/unicode/utf8/"><code>unicode/utf8</code></a>,
|
||||
<a href="/pkg/unicode/utf8/"><code>unicode/utf8</code></a>
|
||||
packages.
|
||||
</p>
|
||||
|
||||
@@ -562,9 +616,6 @@ now implements the new
|
||||
takes a context argument.</li>
|
||||
<li>There have been <a href="#database_sql">significant additions</a> to the
|
||||
<a href="/pkg/database/sql/">database/sql</a> package with context support.</li>
|
||||
<li>The new <a href="/pkg/testing/#T.Context"><code>T.Context</code></a>
|
||||
method in the <a href="/pkg/testing/">testing</a> package now returns a context for
|
||||
the active test or benchmark.</li>
|
||||
<li>All nine of the new <code>Lookup</code> methods on the new
|
||||
<a href="/pkg/net/#Resolver"><code>net.Resolver</code></a> now
|
||||
take a context.</li>
|
||||
@@ -578,7 +629,7 @@ now implements the new
|
||||
|
||||
<p>
|
||||
Most users will want to use the new <code>-mutexprofile</code>
|
||||
flag with <a href="/cmd/go/#hdr-Description_of_testing_flags"><code>go</code> <code>test</code></a>,
|
||||
flag with “<a href="/cmd/go/#hdr-Description_of_testing_flags"><code>go</code> <code>test</code></a>”,
|
||||
and then use <a href="/cmd/pprof/">pprof</a> on the resultant file.
|
||||
</p>
|
||||
|
||||
@@ -589,13 +640,20 @@ now implements the new
|
||||
<a href="/pkg/runtime/#SetMutexProfileFraction"><code>SetMutexProfileFraction</code></a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A known limitation for Go 1.8 is that the profile only reports contention for
|
||||
<a href="/pkg/sync/#Mutex"><code>sync.Mutex</code></a>,
|
||||
not
|
||||
<a href="/pkg/sync/#RWMutex"><code>sync.RWMutex</code></a>.
|
||||
</p>
|
||||
|
||||
<h3 id="minor_library_changes">Minor changes to the library</h3>
|
||||
|
||||
<p>
|
||||
As always, there are various minor changes and updates to the library,
|
||||
made with the Go 1 <a href="/doc/go1compat">promise of compatibility</a>
|
||||
in mind. The follow sections list the user visible changes and additions.
|
||||
Optimizations and bug fixes are not listed.
|
||||
in mind. The following sections list the user visible changes and additions.
|
||||
Optimizations and minor bug fixes are not listed.
|
||||
</p>
|
||||
|
||||
<dl id="archive_tar"><dt><a href="/pkg/archive/tar/">archive/tar</a></dt>
|
||||
@@ -612,20 +670,6 @@ Optimizations and bug fixes are not listed.
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl id="archive_zip"><dt><a href="/pkg/archive/zip/">archive/zip</a></dt>
|
||||
<dd>
|
||||
|
||||
<p> <!-- CL 18274 -->
|
||||
The zip <code>Reader</code> now supports modification times in
|
||||
the NTFS, UNIX, and Extended Time Stamp metadata fields.
|
||||
<!-- CL 30811 -->
|
||||
When writing zip files, the Extended Time Stamp field is written
|
||||
for files with non-zero modification times.
|
||||
</p>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl id="compress_flate"><dt><a href="/pkg/compress/flate/">compress/flate</a></dt>
|
||||
<dd>
|
||||
|
||||
@@ -633,11 +677,11 @@ Optimizations and bug fixes are not listed.
|
||||
There have been some minor fixes to the encoder to improve the
|
||||
compression ratio in certain situations. As a result, the exact
|
||||
encoded output of <code>DEFLATE</code> may be different from Go 1.7. Since
|
||||
DEFLATE is the underlying compression of gzip, png, zlib, and zip,
|
||||
<code>DEFLATE</code> is the underlying compression of gzip, png, zlib, and zip,
|
||||
those formats may have changed outputs.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<p> <!-- CL 31174 -->
|
||||
The encoder, when operating in
|
||||
<a href="/pkg/compress/flate/#NoCompression"><code>NoCompression</code></a>
|
||||
mode, now produces a consistent output that is not dependent on
|
||||
@@ -751,14 +795,14 @@ Optimizations and bug fixes are not listed.
|
||||
X25519 and <!-- CL 30824, CL 30825 -->
|
||||
ChaCha20-Poly1305. <!-- CL 30957, CL 30958 -->
|
||||
ChaCha20-Poly1305 is now prioritized unless <!-- CL 32871 -->
|
||||
AES-GCM when hardware support is present.
|
||||
hardware support for AES-GCM is present.
|
||||
</p>
|
||||
|
||||
<p> <!-- CL 27315 -->
|
||||
AES-128-CBC cipher suites with SHA-256 are also
|
||||
now supported.
|
||||
</p>
|
||||
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
@@ -799,87 +843,85 @@ crypto/x509: return error for missing SerialNumber (CL 27238)
|
||||
at <code>/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem</code>
|
||||
on Linux, to support RHEL and CentOS.
|
||||
</p>
|
||||
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
<dl id="database_sql"><dt><a href="/pkg/database/sql/">database/sql</a></dt>
|
||||
<dd>
|
||||
<p>
|
||||
The package now supports <code>context.Context</code>. There are new methods
|
||||
ending in <code>Context</code> such as
|
||||
<a href="/pkg/database/sql/#DB.QueryContext"><code>DB.QueryContext</code></a> and
|
||||
<a href="/pkg/database/sql/#DB.PrepareContext"><code>DB.PrepareContext</code></a>
|
||||
that take context arguments. Using the new <code>Context</code> methods ensures that
|
||||
connections are closed and returned to the connection pool when the
|
||||
request is done; enables canceling in-progress queries
|
||||
should the driver support that; and allows the database
|
||||
pool to cancel waiting for the next available connection.
|
||||
The package now supports <code>context.Context</code>. There are new methods
|
||||
ending in <code>Context</code> such as
|
||||
<a href="/pkg/database/sql/#DB.QueryContext"><code>DB.QueryContext</code></a> and
|
||||
<a href="/pkg/database/sql/#DB.PrepareContext"><code>DB.PrepareContext</code></a>
|
||||
that take context arguments. Using the new <code>Context</code> methods ensures that
|
||||
connections are closed and returned to the connection pool when the
|
||||
request is done; enables canceling in-progress queries
|
||||
should the driver support that; and allows the database
|
||||
pool to cancel waiting for the next available connection.
|
||||
</p>
|
||||
<p>
|
||||
The <a href="/pkg/database/sql#IsolationLevel"><code>IsolationLevel</code></a>
|
||||
can now be set when starting a transaction by setting the isolation level
|
||||
on the <code>Context</code> then passing that <code>Context</code> to
|
||||
<a href="/pkg/database/sql#DB.BeginContext"><code>DB.BeginContext</code></a>.
|
||||
An error will be returned if an isolation level is selected that the driver
|
||||
does not support. A read-only attribute may also be set on the transaction
|
||||
with <a href="/pkg/database/sql/#ReadOnlyContext"><code>ReadOnlyContext</code></a>.
|
||||
</p>
|
||||
<p>
|
||||
Queries now expose the SQL column type information for drivers that support it.
|
||||
Rows can return <a href="/pkg/database/sql#Rows.ColumnTypes"><code>ColumnTypes</code></a>
|
||||
which can include SQL type information, column type lengths, and the Go type.
|
||||
can now be set when starting a transaction by setting the isolation level
|
||||
on the <code>Context</code> then passing that <code>Context</code> to
|
||||
<a href="/pkg/database/sql#DB.BeginContext"><code>DB.BeginContext</code></a>.
|
||||
An error will be returned if an isolation level is selected that the driver
|
||||
does not support. A read-only attribute may also be set on the transaction
|
||||
with <a href="/pkg/database/sql/#ReadOnlyContext"><code>ReadOnlyContext</code></a>.
|
||||
</p>
|
||||
<p>
|
||||
A <a href="/pkg/database/sql/#Rows"><code>Rows</code></a>
|
||||
can now represent multiple result sets. After
|
||||
<a href="/pkg/database/sql/#Rows.Next"><code>Rows.Next</code></a> returns false,
|
||||
<a href="/pkg/database/sql/#Rows.NextResultSet"><code>Rows.NextResultSet</code></a>
|
||||
may be called to advance to the next result set. The existing <code>Rows</code>
|
||||
should continue to be used after it advances to the next result set.
|
||||
</p>
|
||||
<p>
|
||||
<a href="/pkg/database/sql/#NamedParam"><code>NamedParam</code></a> may be used
|
||||
as query arguments. The new function <a href="/pkg/database/sql/#Param"><code>Param</code></a>
|
||||
helps create a <a href="/pkg/database/sql/#NamedParam"><code>NamedParam</code></a>
|
||||
more succinctly.
|
||||
<p>
|
||||
If a driver supports the new
|
||||
<a href="/pkg/database/sql/driver/#Pinger"><code>Pinger</code></a>
|
||||
interface, the <code>DB</code>'s
|
||||
<a href="/pkg/database/sql/#DB.Ping"><code>DB.Ping</code></a>
|
||||
and
|
||||
<a href="/pkg/database/sql/#DB.PingContext"><code>DB.PingContext</code></a>
|
||||
methods will use that interface to check whether a
|
||||
database connection is still valid.
|
||||
</p>
|
||||
<p>
|
||||
The new <code>Context</code> query methods work for all drivers, but
|
||||
<code>Context</code> cancelation is not responsive unless the driver has been
|
||||
updated to use them. The other features require driver support in
|
||||
<a href="/pkg/database/sql/driver"><code>database/sql/driver</code></a>.
|
||||
Driver authors should review the new interfaces. Users of existing
|
||||
driver should review the driver documentation to see what
|
||||
it supports and any system specific documentation on each feature.
|
||||
</p>
|
||||
Queries now expose the SQL column type information for drivers that support it.
|
||||
Rows can return <a href="/pkg/database/sql#Rows.ColumnTypes"><code>ColumnTypes</code></a>
|
||||
which can include SQL type information, column type lengths, and the Go type.
|
||||
</p>
|
||||
<p>
|
||||
A <a href="/pkg/database/sql/#Rows"><code>Rows</code></a>
|
||||
can now represent multiple result sets. After
|
||||
<a href="/pkg/database/sql/#Rows.Next"><code>Rows.Next</code></a> returns false,
|
||||
<a href="/pkg/database/sql/#Rows.NextResultSet"><code>Rows.NextResultSet</code></a>
|
||||
may be called to advance to the next result set. The existing <code>Rows</code>
|
||||
should continue to be used after it advances to the next result set.
|
||||
</p>
|
||||
<p>
|
||||
<a href="/pkg/database/sql/#NamedArg"><code>NamedArg</code></a> may be used
|
||||
as query arguments. The new function <a href="/pkg/database/sql/#Named"><code>Named</code></a>
|
||||
helps create a <a href="/pkg/database/sql/#NamedArg"><code>NamedArg</code></a>
|
||||
more succinctly.
|
||||
<p>
|
||||
If a driver supports the new
|
||||
<a href="/pkg/database/sql/driver/#Pinger"><code>Pinger</code></a>
|
||||
interface, the
|
||||
<a href="/pkg/database/sql/#DB.Ping"><code>DB.Ping</code></a>
|
||||
and
|
||||
<a href="/pkg/database/sql/#DB.PingContext"><code>DB.PingContext</code></a>
|
||||
methods will use that interface to check whether a
|
||||
database connection is still valid.
|
||||
</p>
|
||||
<p>
|
||||
The new <code>Context</code> query methods work for all drivers, but
|
||||
<code>Context</code> cancelation is not responsive unless the driver has been
|
||||
updated to use them. The other features require driver support in
|
||||
<a href="/pkg/database/sql/driver"><code>database/sql/driver</code></a>.
|
||||
Driver authors should review the new interfaces. Users of existing
|
||||
driver should review the driver documentation to see what
|
||||
it supports and any system specific documentation on each feature.
|
||||
</p>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl id="debug_pe"><dt><a href="/pkg/debug/pe/">debug/pe</a></dt>
|
||||
<dd>
|
||||
<p> <!-- CL 22720, CL 27212, CL 22181, CL 22332, CL 22336, Issue 15345 -->
|
||||
The package has been fleshed out and is now used by <a href="/cmd/link/">the Go linker</a>.
|
||||
New are
|
||||
<a href="/pkg/debug/pe/#Reloc"><code>Reloc</code></a>,
|
||||
<a href="/pkg/debug/pe/#Section"><code>Section</code></a>,
|
||||
<a href="/pkg/debug/pe/#StringTable"><code>StringTable</code></a>,
|
||||
the method
|
||||
<a href="/pkg/debug/pe/#COFFSymbol.FullName"><code>COFFSymbol.FullName</code></a>,
|
||||
The package has been extended and is now used by
|
||||
<a href="/cmd/link/">the Go linker</a> to read <code>gcc</code>-generated object files.
|
||||
The new
|
||||
<a href="/pkg/debug/pe/#File.StringTable"><code>File.StringTable</code></a>
|
||||
and
|
||||
<a href="/pkg/debug/pe/#File"><code>File</code></a>
|
||||
fields
|
||||
<a href="/pkg/debug/pe/#File.COFFSymbols"><code>COFFSymbols</code></a> and
|
||||
<a href="/pkg/debug/pe/#File.StringTable"><code>StringTable</code></a>.
|
||||
<a href="/pkg/debug/pe/#Section.Relocs"><code>Section.Relocs</code></a>
|
||||
fields provide access to the COFF string table and COFF relocations.
|
||||
The new
|
||||
<a href="/pkg/debug/pe/#File.COFFSymbols"><code>File.COFFSymbols</code></a>
|
||||
allows low-level access to the COFF symbol table.
|
||||
</p>
|
||||
</dd>
|
||||
</dl>
|
||||
@@ -933,9 +975,8 @@ crypto/x509: return error for missing SerialNumber (CL 27238)
|
||||
</p>
|
||||
|
||||
<p> <!-- CL 30944 -->
|
||||
|
||||
In previous versions of Go, unmarshaling a JSON <code>null</code> into an
|
||||
of <a href="/pkg/encoding/json/#Unmarshaler"><code>Unmarshaler</code></a>
|
||||
<a href="/pkg/encoding/json/#Unmarshaler"><code>Unmarshaler</code></a>
|
||||
was considered a no-op; now the <code>Unmarshaler</code>'s
|
||||
<code>UnmarshalJSON</code> method is called with the JSON literal
|
||||
<code>null</code> and can define the semantics of that case.
|
||||
@@ -1065,7 +1106,7 @@ crypto/x509: return error for missing SerialNumber (CL 27238)
|
||||
<a href="/pkg/math/big/#Int.ModInverse"><code>Int.ModInverse</code></a>
|
||||
now supports negative numbers.
|
||||
</p>
|
||||
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
@@ -1092,9 +1133,9 @@ crypto/x509: return error for missing SerialNumber (CL 27238)
|
||||
<a href="/pkg/mime/#ParseMediaType"><code>ParseMediaType</code></a>
|
||||
now preserves unnecessary backslash escapes as literals,
|
||||
in order to support MSIE.
|
||||
When MSIE sends a full file path (in "intranet mode"), it does not
|
||||
escape backslashes: <code>"C:\dev\go\foo.txt"</code>, not
|
||||
<code>"C:\\dev\\go\\foo.txt"</code>.
|
||||
When MSIE sends a full file path (in “intranet mode”), it does not
|
||||
escape backslashes: “<code>C:\dev\go\foo.txt</code>”, not
|
||||
“<code>C:\\dev\\go\\foo.txt</code>”.
|
||||
If we see an unnecessary backslash escape, we now assume it is from MSIE
|
||||
and intended as a literal backslash.
|
||||
No known MIME generators emit unnecessary backslash escapes
|
||||
@@ -1126,7 +1167,7 @@ crypto/x509: return error for missing SerialNumber (CL 27238)
|
||||
|
||||
<dl id="net"><dt><a href="/pkg/net/">net</a></dt>
|
||||
<dd>
|
||||
|
||||
|
||||
<p><!-- CL 30164, CL 33473 -->
|
||||
The <a href="/pkg/net/#Conn"><code>Conn</code></a> documentation
|
||||
has been updated to clarify expectations of an interface
|
||||
@@ -1147,8 +1188,8 @@ crypto/x509: return error for missing SerialNumber (CL 27238)
|
||||
</p>
|
||||
|
||||
<p><!-- CL 29951 -->
|
||||
The new <a href="/pkg/net/#Buffers"><code>Buffers</code></a> types permits
|
||||
more efficiently writing to the network from multiple discontiguous buffers
|
||||
The new <a href="/pkg/net/#Buffers"><code>Buffers</code></a> type permits
|
||||
writing to the network more efficiently from multiple discontiguous buffers
|
||||
in memory. On certain machines, for certain types of connections,
|
||||
this is optimized into an OS-specific batch write operation (such as <code>writev</code>).
|
||||
</p>
|
||||
@@ -1165,8 +1206,8 @@ crypto/x509: return error for missing SerialNumber (CL 27238)
|
||||
</p>
|
||||
|
||||
<p><!-- CL 29233, CL 24901 -->
|
||||
The Go DNS resolver now supports <code>resolv.conf</code>'s "<code>rotate</code>"
|
||||
and "<code>option ndots:0</code>" options. The "<code>ndots</code>" option is
|
||||
The Go DNS resolver now supports <code>resolv.conf</code>'s “<code>rotate</code>”
|
||||
and “<code>option</code> <code>ndots:0</code>” options. The “<code>ndots</code>” option is
|
||||
now respected in the same way as <code>libresolve</code>.
|
||||
</p>
|
||||
|
||||
@@ -1193,7 +1234,7 @@ crypto/x509: return error for missing SerialNumber (CL 27238)
|
||||
<a href="/pkg/net/http/#ServeContent"><code>ServeContent</code></a>
|
||||
now support HTTP <code>If-Match</code> conditional requests,
|
||||
in addition to the previous <code>If-None-Match</code>
|
||||
support.
|
||||
support for ETags properly formatted according to RFC 7232, section 2.3.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -1213,11 +1254,11 @@ crypto/x509: return error for missing SerialNumber (CL 27238)
|
||||
existing <a href="/pkg/net/http/#CloseNotifier"><code>CloseNotifier</code></a>
|
||||
support. This functionality requires that the underlying
|
||||
<a href="/pkg/net/#Conn"><code>net.Conn</code></a> implements
|
||||
<a href="#net">recently-clarified interface documentation</a>.
|
||||
<a href="#net">recently clarified interface documentation</a>.
|
||||
</li>
|
||||
|
||||
<li><!-- CL 32479 -->
|
||||
To serve trailers known after the header has been written,
|
||||
To serve trailers produced after the header has already been written,
|
||||
see the new
|
||||
<a href="/pkg/net/http/#TrailerPrefix"><code>TrailerPrefix</code></a>
|
||||
mechanism.
|
||||
@@ -1244,7 +1285,7 @@ crypto/x509: return error for missing SerialNumber (CL 27238)
|
||||
|
||||
<p>Client & Transport changes:</p>
|
||||
<ul>
|
||||
<li><!-- CL 28930 -->
|
||||
<li><!-- CL 28930, CL 31435 -->
|
||||
The <a href="/pkg/net/http/#Client"><code>Client</code></a>
|
||||
now copies most request headers on redirect. See
|
||||
<a href="/pkg/net/http/#Client">the documentation</a>
|
||||
@@ -1258,9 +1299,17 @@ crypto/x509: return error for missing SerialNumber (CL 27238)
|
||||
</li>
|
||||
|
||||
<li><!-- CL 31733, CL 29852 -->
|
||||
The <code>Client</code> now supports 307 and 308 redirects.
|
||||
If the redirect requires resending the request body,
|
||||
the request must have the new
|
||||
The <code>Client</code> now supports 301, 307, and 308 redirects.
|
||||
|
||||
For example, <code>Client.Post</code> now follows 301
|
||||
redirects, converting them to <code>GET</code> requests
|
||||
without bodies, like it did for 302 and 303 redirect responses
|
||||
previously.
|
||||
|
||||
The <code>Client</code> now also follows 307 and 308
|
||||
redirects, preserving the original request method and body, if
|
||||
any. If the redirect requires resending the request body, the
|
||||
request must have the new
|
||||
<a href="/pkg/net/http/#Request"><code>Request.GetBody</code></a>
|
||||
field defined.
|
||||
<a href="pkg/net/http/#NewRequest"><code>NewRequest</code></a>
|
||||
@@ -1275,7 +1324,8 @@ crypto/x509: return error for missing SerialNumber (CL 27238)
|
||||
|
||||
<li><!-- CL 27117 -->
|
||||
The <code>Transport</code> will now retry non-idempotent
|
||||
requests if no bytes were written before a network failure.
|
||||
requests if no bytes were written before a network failure
|
||||
and the request has no body.
|
||||
</li>
|
||||
|
||||
<li><!-- CL 32481 -->
|
||||
@@ -1288,9 +1338,25 @@ crypto/x509: return error for missing SerialNumber (CL 27238)
|
||||
<li> <!-- CL 28077 -->
|
||||
The <a href="/pkg/net/http/#DefaultTransport"><code>DefaultTransport.Dialer</code></a>
|
||||
now enables <code>DualStack</code> ("<a href="https://tools.ietf.org/html/rfc6555">Happy Eyeballs</a>") support,
|
||||
to use IPv4 as a backup if it looks like IPv6 might be
|
||||
allowing the use of IPv4 as a backup if it looks like IPv6 might be
|
||||
failing.
|
||||
</li>
|
||||
|
||||
<li> <!-- CL 31726 -->
|
||||
The <a href="/pkg/net/http/#Transport"><code>Transport</code></a>
|
||||
no longer reads a byte of a non-nil
|
||||
<a href="/pkg/net/http/#Request.Body"><code>Request.Body</code></a>
|
||||
when the
|
||||
<a href="/pkg/net/http/#Request.ContentLength"><code>Request.ContentLength</code></a>
|
||||
is zero to determine whether the <code>ContentLength</code>
|
||||
is actually zero or just undefined.
|
||||
To explicitly signal that a body has zero length,
|
||||
either set it to <code>nil</code>, or set it to the new value
|
||||
<a href="/pkg/net/http/#NoBody"><code>NoBody</code></a>.
|
||||
The new <code>NoBody</code> value is intended for use by <code>Request</code>
|
||||
constructor functions; it is used by
|
||||
<a href="/pkg/net/http/#NewRequest"><code>NewRequest</code></a>.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</dd>
|
||||
@@ -1314,9 +1380,9 @@ crypto/x509: return error for missing SerialNumber (CL 27238)
|
||||
The <a href="/pkg/net/http/httputil/#ReverseProxy"><code>ReverseProxy</code></a>
|
||||
has a new optional hook,
|
||||
<a href="/pkg/net/http/httputil/#ReverseProxy.ModifyResponse"><code>ModifyResponse</code></a>,
|
||||
for modifying the response from the backend before proxying it to the client.
|
||||
for modifying the response from the back end before proxying it to the client.
|
||||
</p>
|
||||
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
@@ -1326,7 +1392,7 @@ crypto/x509: return error for missing SerialNumber (CL 27238)
|
||||
<p> <!-- CL 32176 -->
|
||||
Empty quoted strings are once again allowed in the name part of
|
||||
an address. That is, Go 1.4 and earlier accepted
|
||||
<code>"" <gopher@example.com></code>,
|
||||
<code>""</code> <code><gopher@example.com></code>,
|
||||
but Go 1.5 introduced a bug that rejected this address.
|
||||
The address is recognized again.
|
||||
</p>
|
||||
@@ -1341,7 +1407,7 @@ crypto/x509: return error for missing SerialNumber (CL 27238)
|
||||
allows parsing dates found in other
|
||||
header lines, such as the <code>Resent-Date:</code> header.
|
||||
</p>
|
||||
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
@@ -1349,10 +1415,10 @@ crypto/x509: return error for missing SerialNumber (CL 27238)
|
||||
<dd>
|
||||
|
||||
<p> <!-- CL 33143 -->
|
||||
If an implementation of
|
||||
the <a href="/pkg/net/smtp/#Auth"><code>Auth</code></a>
|
||||
interface's <code>Start</code> method returns an
|
||||
empty <code>toServer</code> value, the package no longer sends
|
||||
If an implementation of the
|
||||
<a href="/pkg/net/smtp/#Auth"><code>Auth.Start</code></a>
|
||||
method returns an empty <code>toServer</code> value,
|
||||
the package no longer sends
|
||||
trailing whitespace in the SMTP <code>AUTH</code> command,
|
||||
which some servers rejected.
|
||||
</p>
|
||||
@@ -1363,14 +1429,17 @@ crypto/x509: return error for missing SerialNumber (CL 27238)
|
||||
<dl id="net_url"><dt><a href="/pkg/net/url/">net/url</a></dt>
|
||||
<dd>
|
||||
|
||||
<p> <!-- CL 31322 --> The new functions
|
||||
<p> <!-- CL 31322 -->
|
||||
The new functions
|
||||
<a href="/pkg/net/url/#PathEscape"><code>PathEscape</code></a>
|
||||
and
|
||||
<a href="/pkg/net/url/#PathUnescape"><code>PathUnescape</code></a>
|
||||
are similar to the query escaping and unescaping functions but
|
||||
for path elements.</p>
|
||||
for path elements.
|
||||
</p>
|
||||
|
||||
<p> <!-- CL 28933 --> The new methods
|
||||
<p> <!-- CL 28933 -->
|
||||
The new methods
|
||||
<a href="/pkg/net/url/#URL.Hostname"><code>URL.Hostname</code></a>
|
||||
and
|
||||
<a href="/pkg/net/url/#URL.Port"><code>URL.Port</code></a>
|
||||
@@ -1378,7 +1447,8 @@ crypto/x509: return error for missing SerialNumber (CL 27238)
|
||||
correctly handling the case where the port may not be present.
|
||||
</p>
|
||||
|
||||
<p> <!-- CL 28343 --> The existing method
|
||||
<p> <!-- CL 28343 -->
|
||||
The existing method
|
||||
<a href="/pkg/net/url/#URL.ResolveReference"><code>URL.ResolveReference</code></a>
|
||||
now properly handles paths with escaped bytes without losing
|
||||
the escaping.
|
||||
@@ -1397,7 +1467,7 @@ crypto/x509: return error for missing SerialNumber (CL 27238)
|
||||
now rejects URLs like <code>this_that:other/thing</code> instead of
|
||||
interpreting them as relative paths (<code>this_that</code> is not a valid scheme).
|
||||
To force interpretation as a relative path,
|
||||
such URLs should be prefixed with <code>"./"</code>.
|
||||
such URLs should be prefixed with “<code>./</code>”.
|
||||
The <code>URL.String</code> method now inserts this prefix as needed.
|
||||
</p>
|
||||
|
||||
@@ -1406,7 +1476,7 @@ crypto/x509: return error for missing SerialNumber (CL 27238)
|
||||
|
||||
<dl id="os"><dt><a href="/pkg/os/">os</a></dt>
|
||||
<dd>
|
||||
<p>
|
||||
<p> <!-- CL 16551 -->
|
||||
The new function
|
||||
<a href="/pkg/os/#Executable"><code>Executable</code></a> returns
|
||||
the path name of the running executable.
|
||||
@@ -1427,12 +1497,12 @@ crypto/x509: return error for missing SerialNumber (CL 27238)
|
||||
existing empty directory.
|
||||
Previously it would fail when renaming to a non-empty directory
|
||||
but succeed when renaming to an empty directory.
|
||||
This makes the behavior on Unix correspond to that on other systems.
|
||||
This makes the behavior on Unix correspond to that of other systems.
|
||||
</p>
|
||||
|
||||
<p> <!-- CL 32451 -->
|
||||
On Windows, long absolute paths are now transparently converted to
|
||||
extended-length paths (paths that start with <code>\\?\</code>).
|
||||
extended-length paths (paths that start with “<code>\\?\</code>”).
|
||||
This permits the package to work with files whose path names are
|
||||
longer than 260 characters.
|
||||
</p>
|
||||
@@ -1454,32 +1524,18 @@ crypto/x509: return error for missing SerialNumber (CL 27238)
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl id="os_signal"><dt><a href="/pkg/os/signal/">os/signal</a></dt>
|
||||
<dd>
|
||||
<p> <!-- CL 32796 -->
|
||||
In a Go library built with <code>-buildmode=c-archive</code>
|
||||
or <code>c-shared</code>, when C code calls a Go function,
|
||||
the <code>SIGPIPE</code> signal will be treated as usual for Go code.
|
||||
In particular, when <code>SIGPIPE</code> is triggered by a write
|
||||
to a closed Go network connection, it will not cause the program
|
||||
to exit.
|
||||
</p>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl id="path_filepath"><dt><a href="/pkg/path/filepath/">path/filepath</a></dt>
|
||||
<dd>
|
||||
<p>
|
||||
<p>A number of bugs and corner cases on Windows were fixed:
|
||||
<a href="/pkg/path/filepath/#Abs"><code>Abs</code></a> now calls <code>Clean</code> paths as documented,
|
||||
A number of bugs and corner cases on Windows were fixed:
|
||||
<a href="/pkg/path/filepath/#Abs"><code>Abs</code></a> now calls <code>Clean</code> as documented,
|
||||
<a href="/pkg/path/filepath/#Glob"><code>Glob</code></a> now matches
|
||||
"<code>\\?\c:\*</code>",
|
||||
“<code>\\?\c:\*</code>”,
|
||||
<a href="/pkg/path/filepath/#EvalSymlinks"><code>EvalSymlinks</code></a> now
|
||||
correctly handles "<code>C:.</code>", and
|
||||
correctly handles “<code>C:.</code>”, and
|
||||
<a href="/pkg/path/filepath/#Clean"><code>Clean</code></a> now properly
|
||||
handles a leading "<code>..</code>" in the path.
|
||||
<p>
|
||||
|
||||
handles a leading “<code>..</code>” in the path.
|
||||
</p>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
@@ -1580,14 +1636,6 @@ crypto/x509: return error for missing SerialNumber (CL 27238)
|
||||
test or benchmark.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 31724 -->
|
||||
The new method
|
||||
<a href="/pkg/testing/#T.Context"><code>T.Context</code></a>
|
||||
(and <code>B.Context</code>) returns
|
||||
a <a href="/pkg/context/#Context"><code>Context</code></a> for
|
||||
the current running test or benchmark.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 32483 -->
|
||||
The new function
|
||||
<a href="/pkg/testing/#CoverMode"><code>CoverMode</code></a>
|
||||
@@ -1600,15 +1648,15 @@ crypto/x509: return error for missing SerialNumber (CL 27238)
|
||||
Previously, individual test cases would appear to pass,
|
||||
and only the overall execution of the test binary would fail.
|
||||
</p>
|
||||
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl id="unicode"><dt><a href="/pkg/unicode/">unicode</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 30935 -->
|
||||
<code>SimpleFold</code> now returns its argument unchanged
|
||||
if the provided input was an invalid rune.
|
||||
<a href="/pkg/unicode/#SimpleFold"><code>SimpleFold</code></a>
|
||||
now returns its argument unchanged if the provided input was an invalid rune.
|
||||
Previously, the implementation failed with an index bounds check panic.
|
||||
</p>
|
||||
</dd>
|
||||
|
||||
@@ -29,7 +29,6 @@ cmd/link: fix -buildmode=pie / -linkshared combination (CL 28996)
|
||||
cmd/link: for -buildmode=exe pass -no-pie to external linker (CL 33106)
|
||||
cmd/link: insert trampolines for too-far jumps on ARM (CL 29397)
|
||||
cmd/link: non-executable stack support for Solaris (CL 24142)
|
||||
cmd/link: plugin support on darwin/amd64 (CL 29394)
|
||||
cmd/link: put text at address 0x1000000 on darwin/amd64 (CL 32185)
|
||||
cmd/link: remove the -shared flag (CL 28852)
|
||||
cmd/link: split large elf text sections on ppc64x (CL 27790)
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
|
||||
<h3 id="mailinglist"><a href="https://groups.google.com/group/golang-nuts">Go Nuts Mailing List</a></h3>
|
||||
<p>
|
||||
Get help from Go users, and share your work on the official mailing list.
|
||||
</p>
|
||||
<p>
|
||||
Search the <a href="https://groups.google.com/group/golang-nuts">golang-nuts</a>
|
||||
archives and consult the <a href="/doc/go_faq.html">FAQ</a> and
|
||||
<a href="//golang.org/wiki">wiki</a> before posting.
|
||||
@@ -18,12 +21,12 @@ archives and consult the <a href="/doc/go_faq.html">FAQ</a> and
|
||||
|
||||
<h3 id="forum"><a href="https://forum.golangbridge.org/">Go Forum</a></h3>
|
||||
<p>
|
||||
The <a href="https://forum.golangbridge.org/">Go Forum</a> is an alternate discussion
|
||||
The <a href="https://forum.golangbridge.org/">Go Forum</a> is a discussion
|
||||
forum for Go programmers.
|
||||
</p>
|
||||
|
||||
<h3 id="slack"><a href="https://blog.gopheracademy.com/gophers-slack-community/">Gopher Slack</a></h3>
|
||||
<p>Get live support from the official Go slack channel.</p>
|
||||
<p>Get live support from other users in the Go slack channel.</p>
|
||||
|
||||
<h3 id="irc"><a href="irc:irc.freenode.net/go-nuts">Go IRC Channel</a></h3>
|
||||
<p>Get live support at <b>#go-nuts</b> on <b>irc.freenode.net</b>, the official
|
||||
|
||||
@@ -33,7 +33,7 @@ compiler using the GCC back end, see
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The Go compilers support seven instruction sets.
|
||||
The Go compilers support eight instruction sets.
|
||||
There are important differences in the quality of the compilers for the different
|
||||
architectures.
|
||||
</p>
|
||||
@@ -55,7 +55,7 @@ architectures.
|
||||
<code>arm</code> (<code>ARM</code>)
|
||||
</dt>
|
||||
<dd>
|
||||
Supports Linux, FreeBSD, NetBSD and Darwin binaries. Less widely used than the other ports.
|
||||
Supports Linux, FreeBSD, NetBSD, OpenBSD and Darwin binaries. Less widely used than the other ports.
|
||||
</dd>
|
||||
<dt>
|
||||
<code>arm64</code> (<code>AArch64</code>)
|
||||
@@ -69,6 +69,12 @@ architectures.
|
||||
<dd>
|
||||
Supports Linux binaries. New in 1.5 and not as well exercised as other ports.
|
||||
</dd>
|
||||
<dt>
|
||||
<code>mips, mipsle</code> (32-bit MIPS big- and little-endian)
|
||||
</dt>
|
||||
<dd>
|
||||
Supports Linux binaries. New in 1.8 and not as well exercised as other ports.
|
||||
</dd>
|
||||
<dt>
|
||||
<code>mips64, mips64le</code> (64-bit MIPS big- and little-endian)
|
||||
</dt>
|
||||
@@ -212,7 +218,7 @@ To build without <code>cgo</code>, set the environment variable
|
||||
Change to the directory that will be its parent
|
||||
and make sure the <code>go</code> directory does not exist.
|
||||
Then clone the repository and check out the latest release tag
|
||||
(<code class="versionTag">go1.7.2</code>, for example):</p>
|
||||
(<code class="versionTag">go1.7.4</code>, for example):</p>
|
||||
|
||||
<pre>
|
||||
$ git clone https://go.googlesource.com/go
|
||||
@@ -329,7 +335,7 @@ You just need to do a little more setup.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The <a href="/doc/code.html">How to Write Go Code</a> document
|
||||
The <a href="/doc/code.html">How to Write Go Code</a> document
|
||||
provides <b>essential setup instructions</b> for using the Go tools.
|
||||
</p>
|
||||
|
||||
@@ -355,7 +361,7 @@ $ go get golang.org/x/tools/cmd/godoc
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
To install these tools, the <code>go</code> <code>get</code> command requires
|
||||
To install these tools, the <code>go</code> <code>get</code> command requires
|
||||
that <a href="#git">Git</a> be installed locally.
|
||||
</p>
|
||||
|
||||
@@ -400,7 +406,7 @@ New releases are announced on the
|
||||
<a href="//groups.google.com/group/golang-announce">golang-announce</a>
|
||||
mailing list.
|
||||
Each announcement mentions the latest release tag, for instance,
|
||||
<code class="versionTag">go1.7.2</code>.
|
||||
<code class="versionTag">go1.7.4</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -443,7 +449,7 @@ The value assumed by installed binaries and scripts when
|
||||
<code>$GOROOT</code> is not set explicitly.
|
||||
It defaults to the value of <code>$GOROOT</code>.
|
||||
If you want to build the Go tree in one location
|
||||
but move it elsewhere after the build, set
|
||||
but move it elsewhere after the build, set
|
||||
<code>$GOROOT_FINAL</code> to the eventual location.
|
||||
</p>
|
||||
|
||||
@@ -463,6 +469,7 @@ Choices for <code>$GOARCH</code> are
|
||||
<code>386</code> (32-bit x86), <code>arm</code> (32-bit ARM), <code>arm64</code> (64-bit ARM),
|
||||
<code>ppc64le</code> (PowerPC 64-bit, little-endian), <code>ppc64</code> (PowerPC 64-bit, big-endian),
|
||||
<code>mips64le</code> (MIPS 64-bit, little-endian), and <code>mips64</code> (MIPS 64-bit, big-endian).
|
||||
<code>mipsle</code> (MIPS 32-bit, little-endian), and <code>mips</code> (MIPS 32-bit, big-endian).
|
||||
The valid combinations of <code>$GOOS</code> and <code>$GOARCH</code> are:
|
||||
<table cellpadding="0">
|
||||
<tr>
|
||||
@@ -514,6 +521,12 @@ The valid combinations of <code>$GOOS</code> and <code>$GOARCH</code> are:
|
||||
<td></td><td><code>linux</code></td> <td><code>ppc64le</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td><td><code>linux</code></td> <td><code>mips</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td><td><code>linux</code></td> <td><code>mipsle</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td><td><code>linux</code></td> <td><code>mips64</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -566,7 +579,7 @@ architecture.
|
||||
Valid choices are the same as for <code>$GOOS</code> and
|
||||
<code>$GOARCH</code>, listed above.
|
||||
The specified values must be compatible with the local system.
|
||||
For example, you should not set <code>$GOHOSTARCH</code> to
|
||||
For example, you should not set <code>$GOHOSTARCH</code> to
|
||||
<code>arm</code> on an x86 system.
|
||||
</p>
|
||||
|
||||
@@ -627,7 +640,7 @@ not <code>amd64</code>.
|
||||
<p>
|
||||
If you choose to override the defaults,
|
||||
set these variables in your shell profile (<code>$HOME/.bashrc</code>,
|
||||
<code>$HOME/.profile</code>, or equivalent). The settings might look
|
||||
<code>$HOME/.profile</code>, or equivalent). The settings might look
|
||||
something like this:
|
||||
</p>
|
||||
|
||||
|
||||
@@ -47,8 +47,8 @@ If your OS or architecture is not on the list, you may be able to
|
||||
<th align="center">Notes</th>
|
||||
</tr>
|
||||
<tr><td colspan="3"><hr></td></tr>
|
||||
<tr><td>FreeBSD 8-STABLE or later</td> <td>amd64</td> <td>Debian GNU/kFreeBSD not supported</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</td></tr>
|
||||
<tr><td>FreeBSD 8-STABLE or later</td> <td>amd64, 386</td> <td>Debian GNU/kFreeBSD not supported</td></tr>
|
||||
<tr><td>Linux 2.6.23 or later with glibc</td> <td>amd64, 386, arm, s390x, ppc64le</td> <td>CentOS/RHEL 5.x not supported</td></tr>
|
||||
<tr><td>Mac OS X 10.8 or later</td> <td>amd64</td> <td>use the clang or gcc<sup>†</sup> that comes with Xcode<sup>‡</sup> for <code>cgo</code> support</td></tr>
|
||||
<tr><td>Windows XP or later</td> <td>amd64, 386</td> <td>use MinGW gcc<sup>†</sup>. No need for cygwin or msys.</td></tr>
|
||||
</table>
|
||||
@@ -246,12 +246,12 @@ Then build it with the <code>go</code> tool:
|
||||
</p>
|
||||
|
||||
<pre class="testUnix">
|
||||
$ <b>cd $HOME/go/src/hello
|
||||
$ <b>cd $HOME/go/src/hello</b>
|
||||
$ <b>go build</b>
|
||||
</pre>
|
||||
|
||||
<pre class="testWindows" style="display: none">
|
||||
C:\> <b>cd %USERPROFILE%\go\src\hello<b>
|
||||
C:\> <b>cd %USERPROFILE%\go\src\hello</b>
|
||||
C:\Users\Gopher\go\src\hello> <b>go build</b>
|
||||
</pre>
|
||||
|
||||
@@ -313,16 +313,10 @@ environment variables under Windows</a>.
|
||||
<h2 id="help">Getting help</h2>
|
||||
|
||||
<p>
|
||||
For real-time help, ask the helpful gophers in <code>#go-nuts</code> on the
|
||||
<a href="http://freenode.net/">Freenode</a> IRC server.
|
||||
For help, see the <a href="/help/">list of Go mailing lists, forums, and places to chat</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The official mailing list for discussion of the Go language is
|
||||
<a href="//groups.google.com/group/golang-nuts">Go Nuts</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Report bugs using the
|
||||
<a href="//golang.org/issue">Go issue tracker</a>.
|
||||
Report bugs either by running “<b><code>go</code> <code>bug</code></b>”, or
|
||||
manually at the <a href="https://golang.org/issue">Go issue tracker</a>.
|
||||
</p>
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
# Consult http://www.iana.org/time-zones for the latest versions.
|
||||
|
||||
# Versions to use.
|
||||
CODE=2016i
|
||||
DATA=2016i
|
||||
CODE=2016j
|
||||
DATA=2016j
|
||||
|
||||
set -e
|
||||
rm -rf work
|
||||
|
||||
Binary file not shown.
@@ -10,3 +10,4 @@ import "testing"
|
||||
|
||||
func TestSigaltstack(t *testing.T) { testSigaltstack(t) }
|
||||
func TestSigprocmask(t *testing.T) { testSigprocmask(t) }
|
||||
func Test18146(t *testing.T) { test18146(t) }
|
||||
|
||||
@@ -23,6 +23,18 @@ int I17537(S17537 *p);
|
||||
const int F17537(const char **p) {
|
||||
return **p;
|
||||
}
|
||||
|
||||
// Calling this function used to trigger an error from the C compiler
|
||||
// (issue 18298).
|
||||
void F18298(const void *const *p) {
|
||||
}
|
||||
|
||||
// Test that conversions between typedefs work as they used to.
|
||||
typedef const void *T18298_1;
|
||||
struct S18298 { int i; };
|
||||
typedef const struct S18298 *T18298_2;
|
||||
void G18298(T18298_1 t) {
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
@@ -39,4 +51,8 @@ func test17537(t *testing.T) {
|
||||
if got, want := C.F17537(&p), C.int(17); got != want {
|
||||
t.Errorf("got %d, want %d", got, want)
|
||||
}
|
||||
|
||||
C.F18298(nil)
|
||||
var v18298 C.T18298_2
|
||||
C.G18298(C.T18298_1(v18298))
|
||||
}
|
||||
|
||||
128
misc/cgo/test/issue18146.go
Normal file
128
misc/cgo/test/issue18146.go
Normal file
@@ -0,0 +1,128 @@
|
||||
// Copyright 2016 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 !windows
|
||||
|
||||
// Issue 18146: pthread_create failure during syscall.Exec.
|
||||
|
||||
package cgotest
|
||||
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func test18146(t *testing.T) {
|
||||
if runtime.GOOS == "darwin" {
|
||||
t.Skipf("skipping flaky test on %s; see golang.org/issue/18202", runtime.GOOS)
|
||||
}
|
||||
|
||||
if runtime.GOARCH == "mips" || runtime.GOARCH == "mips64" {
|
||||
t.Skipf("skipping on %s", runtime.GOARCH)
|
||||
}
|
||||
|
||||
attempts := 1000
|
||||
threads := 4
|
||||
|
||||
if testing.Short() {
|
||||
attempts = 100
|
||||
}
|
||||
|
||||
// Restrict the number of attempts based on RLIMIT_NPROC.
|
||||
// Tediously, RLIMIT_NPROC was left out of the syscall package,
|
||||
// probably because it is not in POSIX.1, so we define it here.
|
||||
// It is not defined on Solaris.
|
||||
var nproc int
|
||||
setNproc := true
|
||||
switch runtime.GOOS {
|
||||
default:
|
||||
setNproc = false
|
||||
case "linux":
|
||||
nproc = 6
|
||||
case "darwin", "dragonfly", "freebsd", "netbsd", "openbsd":
|
||||
nproc = 7
|
||||
}
|
||||
if setNproc {
|
||||
var rlim syscall.Rlimit
|
||||
if syscall.Getrlimit(nproc, &rlim) == nil {
|
||||
max := int(rlim.Cur) / (threads + 5)
|
||||
if attempts > max {
|
||||
t.Logf("lowering attempts from %d to %d for RLIMIT_NPROC", attempts, max)
|
||||
attempts = max
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if os.Getenv("test18146") == "exec" {
|
||||
runtime.GOMAXPROCS(1)
|
||||
for n := threads; n > 0; n-- {
|
||||
go func() {
|
||||
for {
|
||||
_ = md5.Sum([]byte("Hello, !"))
|
||||
}
|
||||
}()
|
||||
}
|
||||
runtime.GOMAXPROCS(threads)
|
||||
argv := append(os.Args, "-test.run=NoSuchTestExists")
|
||||
if err := syscall.Exec(os.Args[0], argv, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
var cmds []*exec.Cmd
|
||||
defer func() {
|
||||
for _, cmd := range cmds {
|
||||
cmd.Process.Kill()
|
||||
}
|
||||
}()
|
||||
|
||||
args := append(append([]string(nil), os.Args[1:]...), "-test.run=Test18146")
|
||||
for n := attempts; n > 0; n-- {
|
||||
cmd := exec.Command(os.Args[0], args...)
|
||||
cmd.Env = append(os.Environ(), "test18146=exec")
|
||||
buf := bytes.NewBuffer(nil)
|
||||
cmd.Stdout = buf
|
||||
cmd.Stderr = buf
|
||||
if err := cmd.Start(); err != nil {
|
||||
// We are starting so many processes that on
|
||||
// some systems (problem seen on Darwin,
|
||||
// Dragonfly, OpenBSD) the fork call will fail
|
||||
// with EAGAIN.
|
||||
if pe, ok := err.(*os.PathError); ok {
|
||||
err = pe.Err
|
||||
}
|
||||
if se, ok := err.(syscall.Errno); ok && (se == syscall.EAGAIN || se == syscall.EMFILE) {
|
||||
time.Sleep(time.Millisecond)
|
||||
continue
|
||||
}
|
||||
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
cmds = append(cmds, cmd)
|
||||
}
|
||||
|
||||
failures := 0
|
||||
for _, cmd := range cmds {
|
||||
err := cmd.Wait()
|
||||
if err == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
t.Errorf("syscall.Exec failed: %v\n%s", err, cmd.Stdout)
|
||||
failures++
|
||||
}
|
||||
|
||||
if failures > 0 {
|
||||
t.Logf("Failed %v of %v attempts.", failures, len(cmds))
|
||||
}
|
||||
}
|
||||
31
misc/cgo/test/issue9400/asm_mipsx.s
Normal file
31
misc/cgo/test/issue9400/asm_mipsx.s
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright 2016 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 mips mipsle
|
||||
// +build !gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
TEXT ·RewindAndSetgid(SB),NOSPLIT,$-4-0
|
||||
// Rewind stack pointer so anything that happens on the stack
|
||||
// will clobber the test pattern created by the caller
|
||||
ADDU $(1024*8), R29
|
||||
|
||||
// Ask signaller to setgid
|
||||
MOVW $1, R1
|
||||
SYNC
|
||||
MOVW R1, ·Baton(SB)
|
||||
SYNC
|
||||
|
||||
// Wait for setgid completion
|
||||
loop:
|
||||
SYNC
|
||||
MOVW ·Baton(SB), R1
|
||||
OR R2, R2, R2 // hint that we're in a spin loop
|
||||
BNE R1, loop
|
||||
SYNC
|
||||
|
||||
// Restore stack
|
||||
ADDU $(-1024*8), R29
|
||||
RET
|
||||
@@ -265,25 +265,6 @@ func TestSignalForwarding(t *testing.T) {
|
||||
t.Logf("%s", out)
|
||||
t.Errorf("got %v; expected SIGSEGV", ee)
|
||||
}
|
||||
|
||||
// Test SIGPIPE forwarding
|
||||
cmd = exec.Command(bin[0], append(bin[1:], "3")...)
|
||||
|
||||
out, err = cmd.CombinedOutput()
|
||||
|
||||
if err == nil {
|
||||
t.Logf("%s", out)
|
||||
t.Error("test program succeeded unexpectedly")
|
||||
} else if ee, ok := err.(*exec.ExitError); !ok {
|
||||
t.Logf("%s", out)
|
||||
t.Errorf("error (%v) has type %T; expected exec.ExitError", err, err)
|
||||
} else if ws, ok := ee.Sys().(syscall.WaitStatus); !ok {
|
||||
t.Logf("%s", out)
|
||||
t.Errorf("error.Sys (%v) has type %T; expected syscall.WaitStatus", ee.Sys(), ee.Sys())
|
||||
} else if !ws.Signaled() || ws.Signal() != syscall.SIGPIPE {
|
||||
t.Logf("%s", out)
|
||||
t.Errorf("got %v; expected SIGPIPE", ee)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSignalForwardingExternal(t *testing.T) {
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include <unistd.h>
|
||||
#include <sched.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "libgo2.h"
|
||||
|
||||
@@ -27,7 +26,6 @@ static void die(const char* msg) {
|
||||
}
|
||||
|
||||
static volatile sig_atomic_t sigioSeen;
|
||||
static volatile sig_atomic_t sigpipeSeen;
|
||||
|
||||
// Use up some stack space.
|
||||
static void recur(int i, char *p) {
|
||||
@@ -39,11 +37,6 @@ static void recur(int i, char *p) {
|
||||
}
|
||||
}
|
||||
|
||||
// Signal handler that uses up more stack space than a goroutine will have.
|
||||
static void pipeHandler(int signo, siginfo_t* info, void* ctxt) {
|
||||
sigpipeSeen = 1;
|
||||
}
|
||||
|
||||
// Signal handler that uses up more stack space than a goroutine will have.
|
||||
static void ioHandler(int signo, siginfo_t* info, void* ctxt) {
|
||||
char a[1024];
|
||||
@@ -113,10 +106,6 @@ static void init() {
|
||||
die("sigaction");
|
||||
}
|
||||
|
||||
sa.sa_sigaction = pipeHandler;
|
||||
if (sigaction(SIGPIPE, &sa, NULL) < 0) {
|
||||
die("sigaction");
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
@@ -178,30 +167,7 @@ int main(int argc, char** argv) {
|
||||
nanosleep(&ts, NULL);
|
||||
i++;
|
||||
if (i > 5000) {
|
||||
fprintf(stderr, "looping too long waiting for SIGIO\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
printf("provoking SIGPIPE\n");
|
||||
}
|
||||
|
||||
GoRaiseSIGPIPE();
|
||||
|
||||
if (verbose) {
|
||||
printf("waiting for sigpipeSeen\n");
|
||||
}
|
||||
|
||||
// Wait until the signal has been delivered.
|
||||
i = 0;
|
||||
while (!sigpipeSeen) {
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 1000000;
|
||||
nanosleep(&ts, NULL);
|
||||
i++;
|
||||
if (i > 1000) {
|
||||
fprintf(stderr, "looping too long waiting for SIGPIPE\n");
|
||||
fprintf(stderr, "looping too long waiting for signal\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,13 +34,6 @@ int main(int argc, char** argv) {
|
||||
verbose = argc > 2;
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
|
||||
if (verbose) {
|
||||
printf("raising SIGPIPE\n");
|
||||
}
|
||||
|
||||
// Test that the Go runtime handles SIGPIPE.
|
||||
ProvokeSIGPIPE();
|
||||
|
||||
if (verbose) {
|
||||
printf("calling sigaction\n");
|
||||
}
|
||||
|
||||
@@ -68,24 +68,6 @@ int main(int argc, char** argv) {
|
||||
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
if (verbose) {
|
||||
printf("attempting SIGPIPE\n");
|
||||
}
|
||||
|
||||
int fd[2];
|
||||
if (pipe(fd) != 0) {
|
||||
printf("pipe(2) failed\n");
|
||||
return 0;
|
||||
}
|
||||
// Close the reading end.
|
||||
close(fd[0]);
|
||||
// Expect that write(2) fails (EPIPE)
|
||||
if (write(fd[1], "some data", 9) != -1) {
|
||||
printf("write(2) unexpectedly succeeded\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
default:
|
||||
printf("Unknown test: %d\n", test);
|
||||
return 0;
|
||||
|
||||
@@ -4,30 +4,6 @@
|
||||
|
||||
package main
|
||||
|
||||
/*
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// Raise SIGPIPE.
|
||||
static void CRaiseSIGPIPE() {
|
||||
int fds[2];
|
||||
|
||||
if (pipe(fds) == -1) {
|
||||
perror("pipe");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
// Close the reader end
|
||||
close(fds[0]);
|
||||
// Write to the writer end to provoke a SIGPIPE
|
||||
if (write(fds[1], "some data", 9) != -1) {
|
||||
fprintf(stderr, "write to a closed pipe succeeded\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
close(fds[1]);
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
@@ -70,11 +46,5 @@ func TestSEGV() {
|
||||
func Noop() {
|
||||
}
|
||||
|
||||
// Raise SIGPIPE.
|
||||
//export GoRaiseSIGPIPE
|
||||
func GoRaiseSIGPIPE() {
|
||||
C.CRaiseSIGPIPE()
|
||||
}
|
||||
|
||||
func main() {
|
||||
}
|
||||
|
||||
@@ -40,17 +40,5 @@ func SawSIGIO() C.int {
|
||||
}
|
||||
}
|
||||
|
||||
// ProvokeSIGPIPE provokes a kernel-initiated SIGPIPE
|
||||
//export ProvokeSIGPIPE
|
||||
func ProvokeSIGPIPE() {
|
||||
r, w, err := os.Pipe()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
r.Close()
|
||||
defer w.Close()
|
||||
w.Write([]byte("some data"))
|
||||
}
|
||||
|
||||
func main() {
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ int main(void) {
|
||||
|
||||
// The descriptor will be initialized in a thread, so we have to
|
||||
// give a chance to get opened.
|
||||
for (i = 0; i < 100; i++) {
|
||||
for (i = 0; i < 1000; i++) {
|
||||
n = read(fd, buf, sizeof buf);
|
||||
if (n >= 0)
|
||||
break;
|
||||
|
||||
@@ -9,7 +9,10 @@ import "C"
|
||||
|
||||
import "common"
|
||||
|
||||
func F() int { return 3 }
|
||||
func F() int {
|
||||
_ = make([]byte, 1<<21) // trigger stack unwind, Issue #18190.
|
||||
return 3
|
||||
}
|
||||
|
||||
func ReadCommonX() int {
|
||||
return common.X
|
||||
|
||||
@@ -4,12 +4,21 @@
|
||||
|
||||
package main
|
||||
|
||||
// // No C code required.
|
||||
//#include <errno.h>
|
||||
//#include <string.h>
|
||||
import "C"
|
||||
|
||||
import "common"
|
||||
// #include
|
||||
// void cfunc() {} // uses cgo_topofstack
|
||||
|
||||
import (
|
||||
"common"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func init() {
|
||||
_ = strings.NewReplacer() // trigger stack unwind, Issue #18190.
|
||||
C.strerror(C.EIO) // uses cgo_topofstack
|
||||
common.X = 2
|
||||
}
|
||||
|
||||
|
||||
@@ -24,8 +24,14 @@ msan=yes
|
||||
|
||||
TMPDIR=${TMPDIR:-/tmp}
|
||||
echo 'int main() { return 0; }' > ${TMPDIR}/testsanitizers$$.c
|
||||
if $CC -fsanitize=memory -c ${TMPDIR}/testsanitizers$$.c -o ${TMPDIR}/testsanitizers$$.o 2>&1 | grep "unrecognized" >& /dev/null; then
|
||||
echo "skipping msan tests: -fsanitize=memory not supported"
|
||||
if $CC -fsanitize=memory -o ${TMPDIR}/testsanitizers$$ ${TMPDIR}/testsanitizers$$.c 2>&1 | grep "unrecognized" >& /dev/null; then
|
||||
echo "skipping msan tests: $CC -fsanitize=memory not supported"
|
||||
msan=no
|
||||
elif ! test -x ${TMPDIR}/testsanitizers$$; then
|
||||
echo "skipping msan tests: $CC -fsanitize-memory did not generate an executable"
|
||||
msan=no
|
||||
elif ! ${TMPDIR}/testsanitizers$$ >/dev/null 2>&1; then
|
||||
echo "skipping msan tests: $CC -fsanitize-memory generates broken executable"
|
||||
msan=no
|
||||
fi
|
||||
rm -f ${TMPDIR}/testsanitizers$$.*
|
||||
@@ -145,6 +151,7 @@ if test "$tsan" = "yes"; then
|
||||
testtsan tsan3.go
|
||||
testtsan tsan4.go
|
||||
testtsan tsan8.go
|
||||
testtsan tsan9.go
|
||||
|
||||
# These tests are only reliable using clang or GCC version 7 or later.
|
||||
# Otherwise runtime/cgo/libcgo.h can't tell whether TSAN is in use.
|
||||
|
||||
67
misc/cgo/testsanitizers/tsan9.go
Normal file
67
misc/cgo/testsanitizers/tsan9.go
Normal file
@@ -0,0 +1,67 @@
|
||||
// Copyright 2016 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 main
|
||||
|
||||
// This program failed when run under the C/C++ ThreadSanitizer. The
|
||||
// TSAN library was not keeping track of whether signals should be
|
||||
// delivered on the alternate signal stack, and the Go signal handler
|
||||
// was not preserving callee-saved registers from C callers.
|
||||
|
||||
/*
|
||||
#cgo CFLAGS: -g -fsanitize=thread
|
||||
#cgo LDFLAGS: -g -fsanitize=thread
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
void spin() {
|
||||
size_t n;
|
||||
struct timeval tvstart, tvnow;
|
||||
int diff;
|
||||
void *prev = NULL, *cur;
|
||||
|
||||
gettimeofday(&tvstart, NULL);
|
||||
for (n = 0; n < 1<<20; n++) {
|
||||
cur = malloc(n);
|
||||
free(prev);
|
||||
prev = cur;
|
||||
|
||||
gettimeofday(&tvnow, NULL);
|
||||
diff = (tvnow.tv_sec - tvstart.tv_sec) * 1000 * 1000 + (tvnow.tv_usec - tvstart.tv_usec);
|
||||
|
||||
// Profile frequency is 100Hz so we should definitely
|
||||
// get a signal in 50 milliseconds.
|
||||
if (diff > 50 * 1000) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(prev);
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"runtime/pprof"
|
||||
"time"
|
||||
)
|
||||
|
||||
func goSpin() {
|
||||
start := time.Now()
|
||||
for n := 0; n < 1<<20; n++ {
|
||||
_ = make([]byte, n)
|
||||
if time.Since(start) > 50*time.Millisecond {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
pprof.StartCPUProfile(ioutil.Discard)
|
||||
go C.spin()
|
||||
goSpin()
|
||||
pprof.StopCPUProfile()
|
||||
}
|
||||
@@ -7,6 +7,18 @@ import (
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// Having a function declared in the main package triggered
|
||||
// golang.org/issue/18250
|
||||
func DeclaredInMain() {
|
||||
}
|
||||
|
||||
type C struct {
|
||||
}
|
||||
|
||||
func F() *C {
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
defer depBase.ImplementedInAsm()
|
||||
// This code below causes various go.itab.* symbols to be generated in
|
||||
@@ -15,4 +27,9 @@ func main() {
|
||||
reflect.TypeOf(os.Stdout).Elem()
|
||||
runtime.GC()
|
||||
depBase.V = depBase.F() + 1
|
||||
|
||||
var c *C
|
||||
if reflect.TypeOf(F).Out(0) != reflect.TypeOf(c) {
|
||||
panic("bad reflection results, see golang.org/issue/18252")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,4 +17,4 @@ else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exec $CLANG -arch $CLANGARCH -isysroot $SDK_PATH "$@"
|
||||
exec $CLANG -arch $CLANGARCH -isysroot $SDK_PATH -mios-version-min=6.0 "$@"
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"hash/crc32"
|
||||
"io"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -290,16 +289,13 @@ func readDirectoryHeader(f *File, r io.Reader) error {
|
||||
// Other zip authors might not even follow the basic format,
|
||||
// and we'll just ignore the Extra content in that case.
|
||||
b := readBuf(f.Extra)
|
||||
|
||||
Extras:
|
||||
for len(b) >= 4 { // need at least tag and size
|
||||
tag := b.uint16()
|
||||
size := b.uint16()
|
||||
if int(size) > len(b) {
|
||||
break
|
||||
}
|
||||
switch tag {
|
||||
case zip64ExtraId:
|
||||
if tag == zip64ExtraId {
|
||||
// update directory values from the zip64 extra block.
|
||||
// They should only be consulted if the sizes read earlier
|
||||
// are maxed out.
|
||||
@@ -327,42 +323,7 @@ func readDirectoryHeader(f *File, r io.Reader) error {
|
||||
}
|
||||
f.headerOffset = int64(eb.uint64())
|
||||
}
|
||||
break Extras
|
||||
|
||||
case ntfsExtraId:
|
||||
if size == 32 {
|
||||
eb := readBuf(b[:size])
|
||||
eb.uint32() // reserved
|
||||
eb.uint16() // tag1
|
||||
size1 := eb.uint16()
|
||||
if size1 == 24 {
|
||||
sub := readBuf(eb[:size1])
|
||||
lo := sub.uint32()
|
||||
hi := sub.uint32()
|
||||
tick := (uint64(uint64(lo)|uint64(hi)<<32) - 116444736000000000) / 10000000
|
||||
f.SetModTime(time.Unix(int64(tick), 0))
|
||||
}
|
||||
}
|
||||
break Extras
|
||||
|
||||
case unixExtraId:
|
||||
if size >= 12 {
|
||||
eb := readBuf(b[:size])
|
||||
eb.uint32() // AcTime
|
||||
epoch := eb.uint32() // ModTime
|
||||
f.SetModTime(time.Unix(int64(epoch), 0))
|
||||
break Extras
|
||||
}
|
||||
case exttsExtraId:
|
||||
if size >= 3 {
|
||||
eb := readBuf(b[:size])
|
||||
flags := eb.uint8() // Flags
|
||||
epoch := eb.uint32() // AcTime/ModTime/CrTime
|
||||
if flags&1 != 0 {
|
||||
f.SetModTime(time.Unix(int64(epoch), 0))
|
||||
}
|
||||
break Extras
|
||||
}
|
||||
break
|
||||
}
|
||||
b = b[size:]
|
||||
}
|
||||
@@ -547,12 +508,6 @@ func findSignatureInBlock(b []byte) int {
|
||||
|
||||
type readBuf []byte
|
||||
|
||||
func (b *readBuf) uint8() uint8 {
|
||||
v := uint8((*b)[0])
|
||||
*b = (*b)[1:]
|
||||
return v
|
||||
}
|
||||
|
||||
func (b *readBuf) uint16() uint16 {
|
||||
v := binary.LittleEndian.Uint16(*b)
|
||||
*b = (*b)[2:]
|
||||
|
||||
@@ -65,13 +65,13 @@ var tests = []ZipTest{
|
||||
{
|
||||
Name: "test.txt",
|
||||
Content: []byte("This is a test text file.\n"),
|
||||
Mtime: "09-05-10 02:12:00",
|
||||
Mtime: "09-05-10 12:12:02",
|
||||
Mode: 0644,
|
||||
},
|
||||
{
|
||||
Name: "gophercolor16x16.png",
|
||||
File: "gophercolor16x16.png",
|
||||
Mtime: "09-05-10 05:52:58",
|
||||
Mtime: "09-05-10 15:52:58",
|
||||
Mode: 0644,
|
||||
},
|
||||
},
|
||||
@@ -83,13 +83,13 @@ var tests = []ZipTest{
|
||||
{
|
||||
Name: "test.txt",
|
||||
Content: []byte("This is a test text file.\n"),
|
||||
Mtime: "09-05-10 02:12:00",
|
||||
Mtime: "09-05-10 12:12:02",
|
||||
Mode: 0644,
|
||||
},
|
||||
{
|
||||
Name: "gophercolor16x16.png",
|
||||
File: "gophercolor16x16.png",
|
||||
Mtime: "09-05-10 05:52:58",
|
||||
Mtime: "09-05-10 15:52:58",
|
||||
Mode: 0644,
|
||||
},
|
||||
},
|
||||
@@ -144,17 +144,6 @@ var tests = []ZipTest{
|
||||
Name: "unix.zip",
|
||||
File: crossPlatform,
|
||||
},
|
||||
{
|
||||
Name: "extra-timestamp.zip",
|
||||
File: []ZipTestFile{
|
||||
{
|
||||
Name: "hello.txt",
|
||||
Content: []byte(""),
|
||||
Mtime: "01-06-16 12:25:56",
|
||||
Mode: 0666,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
// created by Go, before we wrote the "optional" data
|
||||
// descriptor signatures (which are required by OS X)
|
||||
@@ -163,13 +152,13 @@ var tests = []ZipTest{
|
||||
{
|
||||
Name: "foo.txt",
|
||||
Content: []byte("foo\n"),
|
||||
Mtime: "03-09-12 00:59:10",
|
||||
Mtime: "03-08-12 16:59:10",
|
||||
Mode: 0644,
|
||||
},
|
||||
{
|
||||
Name: "bar.txt",
|
||||
Content: []byte("bar\n"),
|
||||
Mtime: "03-09-12 00:59:12",
|
||||
Mtime: "03-08-12 16:59:12",
|
||||
Mode: 0644,
|
||||
},
|
||||
},
|
||||
@@ -216,13 +205,13 @@ var tests = []ZipTest{
|
||||
{
|
||||
Name: "foo.txt",
|
||||
Content: []byte("foo\n"),
|
||||
Mtime: "03-09-12 00:59:10",
|
||||
Mtime: "03-08-12 16:59:10",
|
||||
Mode: 0644,
|
||||
},
|
||||
{
|
||||
Name: "bar.txt",
|
||||
Content: []byte("bar\n"),
|
||||
Mtime: "03-09-12 00:59:12",
|
||||
Mtime: "03-08-12 16:59:12",
|
||||
Mode: 0644,
|
||||
},
|
||||
},
|
||||
@@ -236,14 +225,14 @@ var tests = []ZipTest{
|
||||
{
|
||||
Name: "foo.txt",
|
||||
Content: []byte("foo\n"),
|
||||
Mtime: "03-09-12 00:59:10",
|
||||
Mtime: "03-08-12 16:59:10",
|
||||
Mode: 0644,
|
||||
ContentErr: ErrChecksum,
|
||||
},
|
||||
{
|
||||
Name: "bar.txt",
|
||||
Content: []byte("bar\n"),
|
||||
Mtime: "03-09-12 00:59:12",
|
||||
Mtime: "03-08-12 16:59:12",
|
||||
Mode: 0644,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -63,9 +63,6 @@ const (
|
||||
|
||||
// extra header id's
|
||||
zip64ExtraId = 0x0001 // zip64 Extended Information Extra Field
|
||||
ntfsExtraId = 0x000a // NTFS Extra Field
|
||||
unixExtraId = 0x000d // UNIX Extra Field
|
||||
exttsExtraId = 0x5455 // Extended Timestamp Extra Field
|
||||
)
|
||||
|
||||
// FileHeader describes a file within a zip file.
|
||||
|
||||
BIN
src/archive/zip/testdata/extra-timestamp.zip
vendored
BIN
src/archive/zip/testdata/extra-timestamp.zip
vendored
Binary file not shown.
@@ -103,18 +103,6 @@ func (w *Writer) Close() error {
|
||||
b.uint32(h.UncompressedSize)
|
||||
}
|
||||
|
||||
// use Extended Timestamp Extra Field.
|
||||
if h.ModifiedTime != 0 || h.ModifiedDate != 0 {
|
||||
mt := uint32(h.ModTime().Unix())
|
||||
var mbuf [9]byte // 2x uint16 + uint8 + uint32
|
||||
eb := writeBuf(mbuf[:])
|
||||
eb.uint16(exttsExtraId)
|
||||
eb.uint16(5) // size = uint8 + uint32
|
||||
eb.uint8(1) // flags = modtime
|
||||
eb.uint32(mt) // ModTime
|
||||
h.Extra = append(h.Extra, mbuf[:]...)
|
||||
}
|
||||
|
||||
b.uint16(uint16(len(h.Name)))
|
||||
b.uint16(uint16(len(h.Extra)))
|
||||
b.uint16(uint16(len(h.Comment)))
|
||||
@@ -397,11 +385,6 @@ func (w nopCloser) Close() error {
|
||||
|
||||
type writeBuf []byte
|
||||
|
||||
func (b *writeBuf) uint8(v uint8) {
|
||||
(*b)[0] = v
|
||||
*b = (*b)[1:]
|
||||
}
|
||||
|
||||
func (b *writeBuf) uint16(v uint16) {
|
||||
binary.LittleEndian.PutUint16(*b, v)
|
||||
*b = (*b)[2:]
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"math/rand"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TODO(adg): a more sophisticated test suite
|
||||
@@ -21,7 +20,6 @@ type WriteTest struct {
|
||||
Data []byte
|
||||
Method uint16
|
||||
Mode os.FileMode
|
||||
Mtime string
|
||||
}
|
||||
|
||||
var writeTests = []WriteTest{
|
||||
@@ -30,35 +28,30 @@ var writeTests = []WriteTest{
|
||||
Data: []byte("Rabbits, guinea pigs, gophers, marsupial rats, and quolls."),
|
||||
Method: Store,
|
||||
Mode: 0666,
|
||||
Mtime: "02-01-08 00:01:02",
|
||||
},
|
||||
{
|
||||
Name: "bar",
|
||||
Data: nil, // large data set in the test
|
||||
Method: Deflate,
|
||||
Mode: 0644,
|
||||
Mtime: "03-02-08 01:02:03",
|
||||
},
|
||||
{
|
||||
Name: "setuid",
|
||||
Data: []byte("setuid file"),
|
||||
Method: Deflate,
|
||||
Mode: 0755 | os.ModeSetuid,
|
||||
Mtime: "04-03-08 02:03:04",
|
||||
},
|
||||
{
|
||||
Name: "setgid",
|
||||
Data: []byte("setgid file"),
|
||||
Method: Deflate,
|
||||
Mode: 0755 | os.ModeSetgid,
|
||||
Mtime: "05-04-08 03:04:04",
|
||||
},
|
||||
{
|
||||
Name: "symlink",
|
||||
Data: []byte("../link/target"),
|
||||
Method: Deflate,
|
||||
Mode: 0755 | os.ModeSymlink,
|
||||
Mtime: "03-02-08 11:22:33",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -155,11 +148,6 @@ func testCreate(t *testing.T, w *Writer, wt *WriteTest) {
|
||||
if wt.Mode != 0 {
|
||||
header.SetMode(wt.Mode)
|
||||
}
|
||||
mtime, err := time.Parse("01-02-06 15:04:05", wt.Mtime)
|
||||
if err != nil {
|
||||
t.Fatal("time.Parse:", err)
|
||||
}
|
||||
header.SetModTime(mtime)
|
||||
f, err := w.CreateHeader(header)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -190,21 +178,6 @@ func testReadFile(t *testing.T, f *File, wt *WriteTest) {
|
||||
if !bytes.Equal(b, wt.Data) {
|
||||
t.Errorf("File contents %q, want %q", b, wt.Data)
|
||||
}
|
||||
|
||||
mtime, err := time.Parse("01-02-06 15:04:05", wt.Mtime)
|
||||
if err != nil {
|
||||
t.Fatal("time.Parse:", err)
|
||||
}
|
||||
|
||||
diff := mtime.Sub(f.ModTime())
|
||||
if diff < 0 {
|
||||
diff = -diff
|
||||
}
|
||||
|
||||
// allow several time span
|
||||
if diff > 5*time.Second {
|
||||
t.Errorf("File modtime %v, want %v", mtime, f.ModTime())
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCompressedZipGarbage(b *testing.B) {
|
||||
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
"internal/testenv"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -114,44 +113,6 @@ func TestFileHeaderRoundTrip64(t *testing.T) {
|
||||
testHeaderRoundTrip(fh, uint32max, fh.UncompressedSize64, t)
|
||||
}
|
||||
|
||||
func TestZeroFileRoundTrip(t *testing.T) {
|
||||
var b bytes.Buffer
|
||||
w := NewWriter(&b)
|
||||
if _, err := w.Create(""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := w.Close(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
r, err := NewReader(bytes.NewReader(b.Bytes()), int64(b.Len()))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Verify that fields that should reasonably be the zero value stays
|
||||
// as the zero value.
|
||||
var want FileHeader
|
||||
if len(r.File) != 1 {
|
||||
t.Fatalf("len(r.File) = %d, want 1", len(r.File))
|
||||
}
|
||||
fh := r.File[0].FileHeader
|
||||
got := FileHeader{
|
||||
Name: fh.Name,
|
||||
ModifiedTime: fh.ModifiedTime,
|
||||
ModifiedDate: fh.ModifiedDate,
|
||||
UncompressedSize: fh.UncompressedSize,
|
||||
UncompressedSize64: fh.UncompressedSize64,
|
||||
ExternalAttrs: fh.ExternalAttrs,
|
||||
Comment: fh.Comment,
|
||||
}
|
||||
if len(fh.Extra) > 0 {
|
||||
got.Extra = fh.Extra
|
||||
}
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("FileHeader mismatch:\ngot %#v\nwant %#v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
type repeatedByte struct {
|
||||
off int64
|
||||
b byte
|
||||
|
||||
@@ -23,7 +23,7 @@ type Buffer struct {
|
||||
|
||||
// The readOp constants describe the last action performed on
|
||||
// the buffer, so that UnreadRune and UnreadByte can check for
|
||||
// invalid usage. opReadRuneX constants are choosen such that
|
||||
// invalid usage. opReadRuneX constants are chosen such that
|
||||
// converted to int they correspond to the rune size that was read.
|
||||
type readOp int
|
||||
|
||||
|
||||
@@ -1210,6 +1210,8 @@ func (p *Package) gccMachine() []string {
|
||||
return []string{"-m64"}
|
||||
case "mips64", "mips64le":
|
||||
return []string{"-mabi=64"}
|
||||
case "mips", "mipsle":
|
||||
return []string{"-mabi=32"}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1727,6 +1729,15 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
|
||||
if _, ok := base(dt.Type).(*dwarf.VoidType); ok {
|
||||
t.Go = c.goVoidPtr
|
||||
t.C.Set("void*")
|
||||
dq := dt.Type
|
||||
for {
|
||||
if d, ok := dq.(*dwarf.QualType); ok {
|
||||
t.C.Set(d.Qual + " " + t.C.String())
|
||||
dq = d.Type
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
@@ -175,6 +175,14 @@ func f(b []byte, i int) uint64 {
|
||||
},
|
||||
{"amd64", "linux", `
|
||||
import "encoding/binary"
|
||||
func f(b []byte, v uint64) {
|
||||
binary.BigEndian.PutUint64(b, v)
|
||||
}
|
||||
`,
|
||||
[]string{"\tBSWAPQ\t"},
|
||||
},
|
||||
{"amd64", "linux", `
|
||||
import "encoding/binary"
|
||||
func f(b []byte) uint32 {
|
||||
return binary.BigEndian.Uint32(b)
|
||||
}
|
||||
@@ -186,6 +194,14 @@ import "encoding/binary"
|
||||
func f(b []byte, i int) uint32 {
|
||||
return binary.BigEndian.Uint32(b[i:])
|
||||
}
|
||||
`,
|
||||
[]string{"\tBSWAPL\t"},
|
||||
},
|
||||
{"amd64", "linux", `
|
||||
import "encoding/binary"
|
||||
func f(b []byte, v uint32) {
|
||||
binary.BigEndian.PutUint32(b, v)
|
||||
}
|
||||
`,
|
||||
[]string{"\tBSWAPL\t"},
|
||||
},
|
||||
@@ -205,6 +221,19 @@ func f(b []byte, i int) uint32 {
|
||||
`,
|
||||
[]string{"\tMOVL\t\\(.*\\)\\(.*\\*1\\),"},
|
||||
},
|
||||
|
||||
// Structure zeroing. See issue #18370.
|
||||
{"amd64", "linux", `
|
||||
type T struct {
|
||||
a, b, c int
|
||||
}
|
||||
func f(t *T) {
|
||||
*t = T{}
|
||||
}
|
||||
`,
|
||||
[]string{"\tMOVQ\t\\$0, \\(.*\\)", "\tMOVQ\t\\$0, 8\\(.*\\)", "\tMOVQ\t\\$0, 16\\(.*\\)"},
|
||||
},
|
||||
// TODO: add a test for *t = T{3,4,5} when we fix that.
|
||||
}
|
||||
|
||||
// mergeEnvLists merges the two environment lists such that
|
||||
|
||||
@@ -1000,7 +1000,7 @@ func parName(f *Field, numbered bool) string {
|
||||
Fatalf("invalid symbol name: %s", name)
|
||||
}
|
||||
|
||||
// Functions that can be inlined use numbered parameters so we can distingish them
|
||||
// Functions that can be inlined use numbered parameters so we can distinguish them
|
||||
// from other names in their context after inlining (i.e., the parameter numbering
|
||||
// is a form of parameter rewriting). See issue 4326 for an example and test case.
|
||||
if forceObjFileStability || numbered {
|
||||
|
||||
@@ -15,6 +15,7 @@ var runtimeDecls = [...]struct {
|
||||
{"panicwrap", funcTag, 7},
|
||||
{"gopanic", funcTag, 9},
|
||||
{"gorecover", funcTag, 12},
|
||||
{"goschedguarded", funcTag, 5},
|
||||
{"printbool", funcTag, 14},
|
||||
{"printfloat", funcTag, 16},
|
||||
{"printint", funcTag, 18},
|
||||
|
||||
@@ -21,6 +21,7 @@ func panicwrap(string, string, string)
|
||||
|
||||
func gopanic(interface{})
|
||||
func gorecover(*int32) interface{}
|
||||
func goschedguarded()
|
||||
|
||||
func printbool(bool)
|
||||
func printfloat(float64)
|
||||
|
||||
@@ -107,6 +107,12 @@ func caninl(fn *Node) {
|
||||
return
|
||||
}
|
||||
|
||||
// If marked "go:cgo_unsafe_args", don't inline
|
||||
if fn.Func.Pragma&CgoUnsafeArgs != 0 {
|
||||
reason = "marked go:cgo_unsafe_args"
|
||||
return
|
||||
}
|
||||
|
||||
// If fn has no body (is defined outside of Go), cannot inline it.
|
||||
if fn.Nbody.Len() == 0 {
|
||||
reason = "no function body"
|
||||
|
||||
@@ -1022,13 +1022,14 @@ func (p *noder) error(err error) {
|
||||
func (p *noder) pragma(pos, line int, text string) syntax.Pragma {
|
||||
switch {
|
||||
case strings.HasPrefix(text, "line "):
|
||||
i := strings.IndexByte(text, ':')
|
||||
// Want to use LastIndexByte below but it's not defined in Go1.4 and bootstrap fails.
|
||||
i := strings.LastIndex(text, ":") // look from right (Windows filenames may contain ':')
|
||||
if i < 0 {
|
||||
break
|
||||
}
|
||||
n, err := strconv.Atoi(text[i+1:])
|
||||
if err != nil {
|
||||
// todo: make this an error instead? it is almost certainly a bug.
|
||||
// TODO: make this an error instead? it is almost certainly a bug.
|
||||
break
|
||||
}
|
||||
if n > 1e8 {
|
||||
@@ -1054,6 +1055,7 @@ func (p *noder) pragma(pos, line int, text string) syntax.Pragma {
|
||||
lookup(f[1]).Linkname = f[2]
|
||||
|
||||
case strings.HasPrefix(text, "go:cgo_"):
|
||||
lineno = p.baseline + int32(line) - 1 // pragcgo may call yyerror
|
||||
pragcgobuf += pragcgo(text)
|
||||
fallthrough // because of //go:cgo_unsafe_args
|
||||
default:
|
||||
@@ -1061,6 +1063,7 @@ func (p *noder) pragma(pos, line int, text string) syntax.Pragma {
|
||||
if i := strings.Index(text, " "); i >= 0 {
|
||||
verb = verb[:i]
|
||||
}
|
||||
lineno = p.baseline + int32(line) - 1 // pragmaValue may call yyerror
|
||||
return syntax.Pragma(pragmaValue(verb))
|
||||
}
|
||||
|
||||
|
||||
@@ -380,6 +380,9 @@ func compile(fn *Node) {
|
||||
if fn.Func.Wrapper {
|
||||
ptxt.From3.Offset |= obj.WRAPPER
|
||||
}
|
||||
if fn.Func.NoFramePointer {
|
||||
ptxt.From3.Offset |= obj.NOFRAME
|
||||
}
|
||||
if fn.Func.Needctxt {
|
||||
ptxt.From3.Offset |= obj.NEEDCTXT
|
||||
}
|
||||
|
||||
@@ -998,7 +998,6 @@ func itabname(t, itype *Type) *Node {
|
||||
Fatalf("itabname(%v, %v)", t, itype)
|
||||
}
|
||||
s := Pkglookup(t.tconv(FmtLeft)+","+itype.tconv(FmtLeft), itabpkg)
|
||||
Linksym(s).Set(obj.AttrLocal, true)
|
||||
if s.Def == nil {
|
||||
n := newname(s)
|
||||
n.Type = Types[TUINT8]
|
||||
@@ -1411,15 +1410,15 @@ func dumptypestructs() {
|
||||
// }
|
||||
o := dsymptr(i.sym, 0, dtypesym(i.itype), 0)
|
||||
o = dsymptr(i.sym, o, dtypesym(i.t), 0)
|
||||
o += Widthptr + 8 // skip link/bad/unused fields
|
||||
o += Widthptr + 8 // skip link/bad/inhash fields
|
||||
o += len(imethods(i.itype)) * Widthptr // skip fun method pointers
|
||||
// at runtime the itab will contain pointers to types, other itabs and
|
||||
// method functions. None are allocated on heap, so we can use obj.NOPTR.
|
||||
ggloblsym(i.sym, int32(o), int16(obj.DUPOK|obj.NOPTR|obj.LOCAL))
|
||||
ggloblsym(i.sym, int32(o), int16(obj.DUPOK|obj.NOPTR))
|
||||
|
||||
ilink := Pkglookup(i.t.tconv(FmtLeft)+","+i.itype.tconv(FmtLeft), itablinkpkg)
|
||||
dsymptr(ilink, 0, i.sym, 0)
|
||||
ggloblsym(ilink, int32(Widthptr), int16(obj.DUPOK|obj.RODATA|obj.LOCAL))
|
||||
ggloblsym(ilink, int32(Widthptr), int16(obj.DUPOK|obj.RODATA))
|
||||
}
|
||||
|
||||
// process ptabs
|
||||
|
||||
@@ -295,7 +295,9 @@ func staticcopy(l *Node, r *Node, out *[]*Node) bool {
|
||||
if staticcopy(l, r, out) {
|
||||
return true
|
||||
}
|
||||
*out = append(*out, nod(OAS, l, r))
|
||||
// We may have skipped past one or more OCONVNOPs, so
|
||||
// use conv to ensure r is assignable to l (#13263).
|
||||
*out = append(*out, nod(OAS, l, conv(r, l.Type)))
|
||||
return true
|
||||
|
||||
case OLITERAL:
|
||||
@@ -1076,6 +1078,8 @@ func anylit(n *Node, var_ *Node, init *Nodes) {
|
||||
|
||||
var r *Node
|
||||
if n.Right != nil {
|
||||
// n.Right is stack temporary used as backing store.
|
||||
init.Append(nod(OAS, n.Right, nil)) // zero backing store, just in case (#18410)
|
||||
r = nod(OADDR, n.Right, nil)
|
||||
r = typecheck(r, Erv)
|
||||
} else {
|
||||
@@ -1193,7 +1197,7 @@ func getlit(lit *Node) int {
|
||||
return -1
|
||||
}
|
||||
|
||||
// stataddr sets nam to the static address of n and reports whether it succeeeded.
|
||||
// stataddr sets nam to the static address of n and reports whether it succeeded.
|
||||
func stataddr(nam *Node, n *Node) bool {
|
||||
if n == nil {
|
||||
return false
|
||||
|
||||
@@ -64,6 +64,9 @@ func buildssa(fn *Node) *ssa.Func {
|
||||
s.config = initssa()
|
||||
s.f = s.config.NewFunc()
|
||||
s.f.Name = name
|
||||
if fn.Func.Pragma&Nosplit != 0 {
|
||||
s.f.NoSplit = true
|
||||
}
|
||||
s.exitCode = fn.Func.Exit
|
||||
s.panics = map[funcLine]*ssa.Block{}
|
||||
s.config.DebugTest = s.config.DebugHashMatch("GOSSAHASH", name)
|
||||
|
||||
@@ -1810,6 +1810,8 @@ func genwrapper(rcvr *Type, method *Field, newnam *Sym, iface int) {
|
||||
n := nod(ORETJMP, nil, nil)
|
||||
n.Left = newname(methodsym(method.Sym, methodrcvr, 0))
|
||||
fn.Nbody.Append(n)
|
||||
// When tail-calling, we can't use a frame pointer.
|
||||
fn.Func.NoFramePointer = true
|
||||
} else {
|
||||
fn.Func.Wrapper = true // ignore frame for panic+recover matching
|
||||
call := nod(OCALL, dot, nil)
|
||||
|
||||
@@ -317,6 +317,7 @@ type Func struct {
|
||||
Needctxt bool // function uses context register (has closure variables)
|
||||
ReflectMethod bool // function calls reflect.Type.Method or MethodByName
|
||||
IsHiddenClosure bool
|
||||
NoFramePointer bool // Must not use a frame pointer for this function
|
||||
}
|
||||
|
||||
type Op uint8
|
||||
|
||||
@@ -106,7 +106,7 @@ func testSliceSetElement() {
|
||||
func testSlicePanic1() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
println("paniced as expected")
|
||||
println("panicked as expected")
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -119,7 +119,7 @@ func testSlicePanic1() {
|
||||
func testSlicePanic2() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
println("paniced as expected")
|
||||
println("panicked as expected")
|
||||
}
|
||||
}()
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ func testStructSlice() {
|
||||
func testStringSlicePanic() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
println("paniced as expected")
|
||||
println("panicked as expected")
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -148,7 +148,7 @@ func testInt64Index() {
|
||||
func testInt64IndexPanic() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
println("paniced as expected")
|
||||
println("panicked as expected")
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -161,7 +161,7 @@ func testInt64IndexPanic() {
|
||||
func testInt64SlicePanic() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
println("paniced as expected")
|
||||
println("panicked as expected")
|
||||
}
|
||||
}()
|
||||
|
||||
|
||||
@@ -213,7 +213,7 @@ func (t *Type) FuncType() *FuncType {
|
||||
return t.Extra.(*FuncType)
|
||||
}
|
||||
|
||||
// InterMethType contains Type fields specific to interface method psuedo-types.
|
||||
// InterMethType contains Type fields specific to interface method pseudo-types.
|
||||
type InterMethType struct {
|
||||
Nname *Node
|
||||
}
|
||||
|
||||
@@ -859,7 +859,7 @@ OpSwitch:
|
||||
}
|
||||
|
||||
if n.Type.Etype != TFUNC || !n.IsMethod() {
|
||||
yyerror("type %v has no method %S", n.Left.Type, n.Right.Sym)
|
||||
yyerror("type %v has no method %S", n.Left.Type, n.Sym)
|
||||
n.Type = nil
|
||||
return n
|
||||
}
|
||||
|
||||
@@ -694,6 +694,10 @@ opswitch:
|
||||
break
|
||||
}
|
||||
|
||||
if !instrumenting && iszero(n.Right) && !needwritebarrier(n.Left, n.Right) {
|
||||
break
|
||||
}
|
||||
|
||||
switch n.Right.Op {
|
||||
default:
|
||||
n.Right = walkexpr(n.Right, init)
|
||||
|
||||
@@ -6,7 +6,7 @@ package ssa
|
||||
|
||||
// checkbce prints all bounds checks that are present in the function.
|
||||
// Useful to find regressions. checkbce is only activated when with
|
||||
// corresponsing debug options, so it's off by default.
|
||||
// corresponding debug options, so it's off by default.
|
||||
// See test/checkbce.go
|
||||
func checkbce(f *Func) {
|
||||
if f.pass.debug <= 0 {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
package ssa
|
||||
|
||||
import (
|
||||
"cmd/internal/obj"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
@@ -349,6 +350,8 @@ var passes = [...]pass{
|
||||
{name: "writebarrier", fn: writebarrier, required: true}, // expand write barrier ops
|
||||
{name: "fuse", fn: fuse},
|
||||
{name: "dse", fn: dse},
|
||||
{name: "insert resched checks", fn: insertLoopReschedChecks,
|
||||
disabled: obj.Preemptibleloops_enabled == 0}, // insert resched checks in loops.
|
||||
{name: "tighten", fn: tighten}, // move values closer to their uses
|
||||
{name: "lower", fn: lower, required: true},
|
||||
{name: "lowered cse", fn: cse},
|
||||
@@ -378,7 +381,13 @@ type constraint struct {
|
||||
}
|
||||
|
||||
var passOrder = [...]constraint{
|
||||
// prove reliese on common-subexpression elimination for maximum benefits.
|
||||
// "insert resched checks" uses mem, better to clean out stores first.
|
||||
{"dse", "insert resched checks"},
|
||||
// insert resched checks adds new blocks containing generic instructions
|
||||
{"insert resched checks", "lower"},
|
||||
{"insert resched checks", "tighten"},
|
||||
|
||||
// prove relies on common-subexpression elimination for maximum benefits.
|
||||
{"generic cse", "prove"},
|
||||
// deadcode after prove to eliminate all new dead blocks.
|
||||
{"prove", "generic deadcode"},
|
||||
|
||||
@@ -93,7 +93,7 @@ type Logger interface {
|
||||
// Warnl writes compiler messages in the form expected by "errorcheck" tests
|
||||
Warnl(line int32, fmt_ string, args ...interface{})
|
||||
|
||||
// Fowards the Debug flags from gc
|
||||
// Forwards the Debug flags from gc
|
||||
Debug_checknil() bool
|
||||
Debug_wb() bool
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ package ssa
|
||||
|
||||
import (
|
||||
"cmd/internal/obj"
|
||||
"cmd/internal/obj/x86"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -16,7 +17,7 @@ var Deadcode = deadcode
|
||||
var Copyelim = copyelim
|
||||
|
||||
func testConfig(t testing.TB) *Config {
|
||||
testCtxt := &obj.Link{}
|
||||
testCtxt := &obj.Link{Arch: &x86.Linkamd64}
|
||||
return NewConfig("amd64", DummyFrontend{t}, testCtxt, true)
|
||||
}
|
||||
|
||||
@@ -67,7 +68,7 @@ func (DummyFrontend) Line(line int32) string {
|
||||
func (DummyFrontend) AllocFrame(f *Func) {
|
||||
}
|
||||
func (DummyFrontend) Syslook(s string) interface{} {
|
||||
return nil
|
||||
return DummySym(s)
|
||||
}
|
||||
|
||||
func (d DummyFrontend) Logf(msg string, args ...interface{}) { d.t.Logf(msg, args...) }
|
||||
@@ -98,3 +99,7 @@ func (d DummyFrontend) CanSSA(t Type) bool {
|
||||
// There are no un-SSAable types in dummy land.
|
||||
return true
|
||||
}
|
||||
|
||||
type DummySym string
|
||||
|
||||
func (s DummySym) String() string { return string(s) }
|
||||
|
||||
@@ -24,6 +24,7 @@ type Func struct {
|
||||
vid idAlloc // value ID allocator
|
||||
|
||||
scheduled bool // Values in Blocks are in final order
|
||||
NoSplit bool // true if function is marked as nosplit. Used by schedule check pass.
|
||||
|
||||
// when register allocation is done, maps value ids to locations
|
||||
RegAlloc []Location
|
||||
|
||||
@@ -12,7 +12,7 @@ import "strings"
|
||||
// - Integer types live in the low portion of registers. Upper portions are junk.
|
||||
// - Boolean types use the low-order byte of a register. 0=false, 1=true.
|
||||
// Upper bytes are junk.
|
||||
// - *const instructions may use a constant larger than the instuction can encode.
|
||||
// - *const instructions may use a constant larger than the instruction can encode.
|
||||
// In this case the assembler expands to multiple instructions and uses tmp
|
||||
// register (R27).
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import "strings"
|
||||
// - Integer types live in the low portion of registers. Upper portions are junk.
|
||||
// - Boolean types use the low-order byte of a register. 0=false, 1=true.
|
||||
// Upper bytes are junk.
|
||||
// - *const instructions may use a constant larger than the instuction can encode.
|
||||
// - *const instructions may use a constant larger than the instruction can encode.
|
||||
// In this case the assembler expands to multiple instructions and uses tmp
|
||||
// register (R11).
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import "strings"
|
||||
// - Integer types live in the low portion of registers. Upper portions are junk.
|
||||
// - Boolean types use the low-order byte of a register. 0=false, 1=true.
|
||||
// Upper bytes are junk.
|
||||
// - *const instructions may use a constant larger than the instuction can encode.
|
||||
// - *const instructions may use a constant larger than the instruction can encode.
|
||||
// In this case the assembler expands to multiple instructions and uses tmp
|
||||
// register (R23).
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import "strings"
|
||||
// - Boolean types use the low-order byte of a register. 0=false, 1=true.
|
||||
// Upper bytes are junk.
|
||||
// - Unused portions of AuxInt are filled by sign-extending the used portion.
|
||||
// - *const instructions may use a constant larger than the instuction can encode.
|
||||
// - *const instructions may use a constant larger than the instruction can encode.
|
||||
// In this case the assembler expands to multiple instructions and uses tmp
|
||||
// register (R23).
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import "strings"
|
||||
// - Less-than-64-bit integer types live in the low portion of registers.
|
||||
// For now, the upper portion is junk; sign/zero-extension might be optimized in the future, but not yet.
|
||||
// - Boolean types are zero or 1; stored in a byte, but loaded with AMOVBZ so the upper bytes of a register are zero.
|
||||
// - *const instructions may use a constant larger than the instuction can encode.
|
||||
// - *const instructions may use a constant larger than the instruction can encode.
|
||||
// In this case the assembler expands to multiple instructions and uses tmp
|
||||
// register (R31).
|
||||
|
||||
|
||||
517
src/cmd/compile/internal/ssa/loopreschedchecks.go
Normal file
517
src/cmd/compile/internal/ssa/loopreschedchecks.go
Normal file
@@ -0,0 +1,517 @@
|
||||
// Copyright 2016 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 ssa
|
||||
|
||||
import "fmt"
|
||||
|
||||
// an edgeMemCtr records a backedge, together with the memory and
|
||||
// counter phi functions at the target of the backedge that must
|
||||
// be updated when a rescheduling check replaces the backedge.
|
||||
type edgeMemCtr struct {
|
||||
e Edge
|
||||
m *Value // phi for memory at dest of e
|
||||
c *Value // phi for counter at dest of e
|
||||
}
|
||||
|
||||
// a rewriteTarget is a a value-argindex pair indicating
|
||||
// where a rewrite is applied. Note that this is for values,
|
||||
// not for block controls, because block controls are not targets
|
||||
// for the rewrites performed in inserting rescheduling checks.
|
||||
type rewriteTarget struct {
|
||||
v *Value
|
||||
i int
|
||||
}
|
||||
|
||||
type rewrite struct {
|
||||
before, after *Value // before is the expected value before rewrite, after is the new value installed.
|
||||
rewrites []rewriteTarget // all the targets for this rewrite.
|
||||
}
|
||||
|
||||
func (r *rewrite) String() string {
|
||||
s := "\n\tbefore=" + r.before.String() + ", after=" + r.after.String()
|
||||
for _, rw := range r.rewrites {
|
||||
s += ", (i=" + fmt.Sprint(rw.i) + ", v=" + rw.v.LongString() + ")"
|
||||
}
|
||||
s += "\n"
|
||||
return s
|
||||
}
|
||||
|
||||
const initialRescheduleCounterValue = 1021 // Largest 10-bit prime. 97 nSec loop bodies will check every 100 uSec.
|
||||
|
||||
// insertLoopReschedChecks inserts rescheduling checks on loop backedges.
|
||||
func insertLoopReschedChecks(f *Func) {
|
||||
// TODO: when split information is recorded in export data, insert checks only on backedges that can be reached on a split-call-free path.
|
||||
|
||||
// Loop reschedule checks decrement a per-function counter
|
||||
// shared by all loops, and when the counter becomes non-positive
|
||||
// a call is made to a rescheduling check in the runtime.
|
||||
//
|
||||
// Steps:
|
||||
// 1. locate backedges.
|
||||
// 2. Record memory definitions at block end so that
|
||||
// the SSA graph for mem can be prperly modified.
|
||||
// 3. Define a counter and record its future uses (at backedges)
|
||||
// (Same process as 2, applied to a single definition of the counter.
|
||||
// difference for mem is that there are zero-to-many existing mem
|
||||
// definitions, versus exactly one for the new counter.)
|
||||
// 4. Ensure that phi functions that will-be-needed for mem and counter
|
||||
// are present in the graph, initially with trivial inputs.
|
||||
// 5. Record all to-be-modified uses of mem and counter;
|
||||
// apply modifications (split into two steps to simplify and
|
||||
// avoided nagging order-dependences).
|
||||
// 6. Rewrite backedges to include counter check, reschedule check,
|
||||
// and modify destination phi function appropriately with new
|
||||
// definitions for mem and counter.
|
||||
|
||||
if f.NoSplit { // nosplit functions don't reschedule.
|
||||
return
|
||||
}
|
||||
|
||||
backedges := backedges(f)
|
||||
if len(backedges) == 0 { // no backedges means no rescheduling checks.
|
||||
return
|
||||
}
|
||||
|
||||
lastMems := findLastMems(f)
|
||||
|
||||
idom := f.Idom()
|
||||
sdom := f.sdom()
|
||||
|
||||
if f.pass.debug > 2 {
|
||||
fmt.Printf("before %s = %s\n", f.Name, sdom.treestructure(f.Entry))
|
||||
}
|
||||
|
||||
tofixBackedges := []edgeMemCtr{}
|
||||
|
||||
for _, e := range backedges { // TODO: could filter here by calls in loops, if declared and inferred nosplit are recorded in export data.
|
||||
tofixBackedges = append(tofixBackedges, edgeMemCtr{e, nil, nil})
|
||||
}
|
||||
|
||||
// It's possible that there is no memory state (no global/pointer loads/stores or calls)
|
||||
if lastMems[f.Entry.ID] == nil {
|
||||
lastMems[f.Entry.ID] = f.Entry.NewValue0(f.Entry.Line, OpInitMem, TypeMem)
|
||||
}
|
||||
|
||||
memDefsAtBlockEnds := make([]*Value, f.NumBlocks()) // For each block, the mem def seen at its bottom. Could be from earlier block.
|
||||
|
||||
// Propagate last mem definitions forward through successor blocks.
|
||||
po := f.postorder()
|
||||
for i := len(po) - 1; i >= 0; i-- {
|
||||
b := po[i]
|
||||
mem := lastMems[b.ID]
|
||||
for j := 0; mem == nil; j++ { // if there's no def, then there's no phi, so the visible mem is identical in all predecessors.
|
||||
// loop because there might be backedges that haven't been visited yet.
|
||||
mem = memDefsAtBlockEnds[b.Preds[j].b.ID]
|
||||
}
|
||||
memDefsAtBlockEnds[b.ID] = mem
|
||||
}
|
||||
|
||||
// Set up counter. There are no phis etc pre-existing for it.
|
||||
counter0 := f.Entry.NewValue0I(f.Entry.Line, OpConst32, f.Config.fe.TypeInt32(), initialRescheduleCounterValue)
|
||||
ctrDefsAtBlockEnds := make([]*Value, f.NumBlocks()) // For each block, def visible at its end, if that def will be used.
|
||||
|
||||
// There's a minor difference between memDefsAtBlockEnds and ctrDefsAtBlockEnds;
|
||||
// because the counter only matter for loops and code that reaches them, it is nil for blocks where the ctr is no
|
||||
// longer live. This will avoid creation of dead phi functions. This optimization is ignored for the mem variable
|
||||
// because it is harder and also less likely to be helpful, though dead code elimination ought to clean this out anyhow.
|
||||
|
||||
for _, emc := range tofixBackedges {
|
||||
e := emc.e
|
||||
// set initial uses of counter zero (note available-at-bottom and use are the same thing initially.)
|
||||
// each back-edge will be rewritten to include a reschedule check, and that will use the counter.
|
||||
src := e.b.Preds[e.i].b
|
||||
ctrDefsAtBlockEnds[src.ID] = counter0
|
||||
}
|
||||
|
||||
// Push uses towards root
|
||||
for _, b := range f.postorder() {
|
||||
bd := ctrDefsAtBlockEnds[b.ID]
|
||||
if bd == nil {
|
||||
continue
|
||||
}
|
||||
for _, e := range b.Preds {
|
||||
p := e.b
|
||||
if ctrDefsAtBlockEnds[p.ID] == nil {
|
||||
ctrDefsAtBlockEnds[p.ID] = bd
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Maps from block to newly-inserted phi function in block.
|
||||
newmemphis := make(map[*Block]rewrite)
|
||||
newctrphis := make(map[*Block]rewrite)
|
||||
|
||||
// Insert phi functions as necessary for future changes to flow graph.
|
||||
for i, emc := range tofixBackedges {
|
||||
e := emc.e
|
||||
h := e.b
|
||||
|
||||
// find the phi function for the memory input at "h", if there is one.
|
||||
var headerMemPhi *Value // look for header mem phi
|
||||
|
||||
for _, v := range h.Values {
|
||||
if v.Op == OpPhi && v.Type.IsMemory() {
|
||||
headerMemPhi = v
|
||||
}
|
||||
}
|
||||
|
||||
if headerMemPhi == nil {
|
||||
// if the header is nil, make a trivial phi from the dominator
|
||||
mem0 := memDefsAtBlockEnds[idom[h.ID].ID]
|
||||
headerMemPhi = newPhiFor(h, mem0)
|
||||
newmemphis[h] = rewrite{before: mem0, after: headerMemPhi}
|
||||
addDFphis(mem0, h, h, f, memDefsAtBlockEnds, newmemphis)
|
||||
|
||||
}
|
||||
tofixBackedges[i].m = headerMemPhi
|
||||
|
||||
var headerCtrPhi *Value
|
||||
rw, ok := newctrphis[h]
|
||||
if !ok {
|
||||
headerCtrPhi = newPhiFor(h, counter0)
|
||||
newctrphis[h] = rewrite{before: counter0, after: headerCtrPhi}
|
||||
addDFphis(counter0, h, h, f, ctrDefsAtBlockEnds, newctrphis)
|
||||
} else {
|
||||
headerCtrPhi = rw.after
|
||||
}
|
||||
tofixBackedges[i].c = headerCtrPhi
|
||||
}
|
||||
|
||||
rewriteNewPhis(f.Entry, f.Entry, f, memDefsAtBlockEnds, newmemphis)
|
||||
rewriteNewPhis(f.Entry, f.Entry, f, ctrDefsAtBlockEnds, newctrphis)
|
||||
|
||||
if f.pass.debug > 0 {
|
||||
for b, r := range newmemphis {
|
||||
fmt.Printf("b=%s, rewrite=%s\n", b, r.String())
|
||||
}
|
||||
|
||||
for b, r := range newctrphis {
|
||||
fmt.Printf("b=%s, rewrite=%s\n", b, r.String())
|
||||
}
|
||||
}
|
||||
|
||||
// Apply collected rewrites.
|
||||
for _, r := range newmemphis {
|
||||
for _, rw := range r.rewrites {
|
||||
rw.v.SetArg(rw.i, r.after)
|
||||
}
|
||||
}
|
||||
|
||||
for _, r := range newctrphis {
|
||||
for _, rw := range r.rewrites {
|
||||
rw.v.SetArg(rw.i, r.after)
|
||||
}
|
||||
}
|
||||
|
||||
zero := f.Entry.NewValue0I(f.Entry.Line, OpConst32, f.Config.fe.TypeInt32(), 0)
|
||||
one := f.Entry.NewValue0I(f.Entry.Line, OpConst32, f.Config.fe.TypeInt32(), 1)
|
||||
|
||||
// Rewrite backedges to include reschedule checks.
|
||||
for _, emc := range tofixBackedges {
|
||||
e := emc.e
|
||||
headerMemPhi := emc.m
|
||||
headerCtrPhi := emc.c
|
||||
h := e.b
|
||||
i := e.i
|
||||
p := h.Preds[i]
|
||||
bb := p.b
|
||||
mem0 := headerMemPhi.Args[i]
|
||||
ctr0 := headerCtrPhi.Args[i]
|
||||
// bb e->p h,
|
||||
// Because we're going to insert a rare-call, make sure the
|
||||
// looping edge still looks likely.
|
||||
likely := BranchLikely
|
||||
if p.i != 0 {
|
||||
likely = BranchUnlikely
|
||||
}
|
||||
bb.Likely = likely
|
||||
|
||||
// rewrite edge to include reschedule check
|
||||
// existing edges:
|
||||
//
|
||||
// bb.Succs[p.i] == Edge{h, i}
|
||||
// h.Preds[i] == p == Edge{bb,p.i}
|
||||
//
|
||||
// new block(s):
|
||||
// test:
|
||||
// ctr1 := ctr0 - 1
|
||||
// if ctr1 <= 0 { goto sched }
|
||||
// goto join
|
||||
// sched:
|
||||
// mem1 := call resched (mem0)
|
||||
// goto join
|
||||
// join:
|
||||
// ctr2 := phi(ctr1, counter0) // counter0 is the constant
|
||||
// mem2 := phi(mem0, mem1)
|
||||
// goto h
|
||||
//
|
||||
// and correct arg i of headerMemPhi and headerCtrPhi
|
||||
//
|
||||
// EXCEPT: block containing only phi functions is bad
|
||||
// for the register allocator. Therefore, there is no
|
||||
// join, and instead branches targeting join instead target
|
||||
// the header, and the other phi functions within header are
|
||||
// adjusted for the additional input.
|
||||
|
||||
test := f.NewBlock(BlockIf)
|
||||
sched := f.NewBlock(BlockPlain)
|
||||
|
||||
test.Line = bb.Line
|
||||
sched.Line = bb.Line
|
||||
|
||||
// ctr1 := ctr0 - 1
|
||||
// if ctr1 <= 0 { goto sched }
|
||||
// goto header
|
||||
ctr1 := test.NewValue2(bb.Line, OpSub32, f.Config.fe.TypeInt32(), ctr0, one)
|
||||
cmp := test.NewValue2(bb.Line, OpLeq32, f.Config.fe.TypeBool(), ctr1, zero)
|
||||
test.SetControl(cmp)
|
||||
test.AddEdgeTo(sched) // if true
|
||||
// if false -- rewrite edge to header.
|
||||
// do NOT remove+add, because that will perturb all the other phi functions
|
||||
// as well as messing up other edges to the header.
|
||||
test.Succs = append(test.Succs, Edge{h, i})
|
||||
h.Preds[i] = Edge{test, 1}
|
||||
headerMemPhi.SetArg(i, mem0)
|
||||
headerCtrPhi.SetArg(i, ctr1)
|
||||
|
||||
test.Likely = BranchUnlikely
|
||||
|
||||
// sched:
|
||||
// mem1 := call resched (mem0)
|
||||
// goto header
|
||||
resched := f.Config.fe.Syslook("goschedguarded")
|
||||
mem1 := sched.NewValue1A(bb.Line, OpStaticCall, TypeMem, resched, mem0)
|
||||
sched.AddEdgeTo(h)
|
||||
headerMemPhi.AddArg(mem1)
|
||||
headerCtrPhi.AddArg(counter0)
|
||||
|
||||
bb.Succs[p.i] = Edge{test, 0}
|
||||
test.Preds = append(test.Preds, Edge{bb, p.i})
|
||||
|
||||
// Must correct all the other phi functions in the header for new incoming edge.
|
||||
// Except for mem and counter phis, it will be the same value seen on the original
|
||||
// backedge at index i.
|
||||
for _, v := range h.Values {
|
||||
if v.Op == OpPhi && v != headerMemPhi && v != headerCtrPhi {
|
||||
v.AddArg(v.Args[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
f.invalidateCFG()
|
||||
|
||||
if f.pass.debug > 2 {
|
||||
sdom = newSparseTree(f, f.Idom())
|
||||
fmt.Printf("after %s = %s\n", f.Name, sdom.treestructure(f.Entry))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// newPhiFor inserts a new Phi function into b,
|
||||
// with all inputs set to v.
|
||||
func newPhiFor(b *Block, v *Value) *Value {
|
||||
phiV := b.NewValue0(b.Line, OpPhi, v.Type)
|
||||
|
||||
for range b.Preds {
|
||||
phiV.AddArg(v)
|
||||
}
|
||||
return phiV
|
||||
}
|
||||
|
||||
// rewriteNewPhis updates newphis[h] to record all places where the new phi function inserted
|
||||
// in block h will replace a previous definition. Block b is the block currently being processed;
|
||||
// if b has its own phi definition then it takes the place of h.
|
||||
// defsForUses provides information about other definitions of the variable that are present
|
||||
// (and if nil, indicates that the variable is no longer live)
|
||||
func rewriteNewPhis(h, b *Block, f *Func, defsForUses []*Value, newphis map[*Block]rewrite) {
|
||||
// If b is a block with a new phi, then a new rewrite applies below it in the dominator tree.
|
||||
if _, ok := newphis[b]; ok {
|
||||
h = b
|
||||
}
|
||||
change := newphis[h]
|
||||
x := change.before
|
||||
y := change.after
|
||||
|
||||
// Apply rewrites to this block
|
||||
if x != nil { // don't waste time on the common case of no definition.
|
||||
p := &change.rewrites
|
||||
for _, v := range b.Values {
|
||||
if v == y { // don't rewrite self -- phi inputs are handled below.
|
||||
continue
|
||||
}
|
||||
for i, w := range v.Args {
|
||||
if w != x {
|
||||
continue
|
||||
}
|
||||
*p = append(*p, rewriteTarget{v, i})
|
||||
}
|
||||
}
|
||||
|
||||
// Rewrite appropriate inputs of phis reached in successors
|
||||
// in dominance frontier, self, and dominated.
|
||||
// If the variable def reaching uses in b is itself defined in b, then the new phi function
|
||||
// does not reach the successors of b. (This assumes a bit about the structure of the
|
||||
// phi use-def graph, but it's true for memory and the inserted counter.)
|
||||
if dfu := defsForUses[b.ID]; dfu != nil && dfu.Block != b {
|
||||
for _, e := range b.Succs {
|
||||
s := e.b
|
||||
if sphi, ok := newphis[s]; ok { // saves time to find the phi this way.
|
||||
*p = append(*p, rewriteTarget{sphi.after, e.i})
|
||||
continue
|
||||
}
|
||||
for _, v := range s.Values {
|
||||
if v.Op == OpPhi && v.Args[e.i] == x {
|
||||
*p = append(*p, rewriteTarget{v, e.i})
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
newphis[h] = change
|
||||
}
|
||||
|
||||
sdom := f.sdom()
|
||||
|
||||
for c := sdom[b.ID].child; c != nil; c = sdom[c.ID].sibling {
|
||||
rewriteNewPhis(h, c, f, defsForUses, newphis) // TODO: convert to explicit stack from recursion.
|
||||
}
|
||||
}
|
||||
|
||||
// addDFphis creates new trivial phis that are necessary to correctly reflect (within SSA)
|
||||
// a new definition for variable "x" inserted at h (usually but not necessarily a phi).
|
||||
// These new phis can only occur at the dominance frontier of h; block s is in the dominance
|
||||
// frontier of h if h does not strictly dominate s and if s is a successor of a block b where
|
||||
// either b = h or h strictly dominates b.
|
||||
// These newly created phis are themselves new definitions that may require addition of their
|
||||
// own trivial phi functions in their own dominance frontier, and this is handled recursively.
|
||||
func addDFphis(x *Value, h, b *Block, f *Func, defForUses []*Value, newphis map[*Block]rewrite) {
|
||||
oldv := defForUses[b.ID]
|
||||
if oldv != x { // either a new definition replacing x, or nil if it is proven that there are no uses reachable from b
|
||||
return
|
||||
}
|
||||
sdom := f.sdom()
|
||||
idom := f.Idom()
|
||||
outer:
|
||||
for _, e := range b.Succs {
|
||||
s := e.b
|
||||
// check phi functions in the dominance frontier
|
||||
if sdom.isAncestor(h, s) {
|
||||
continue // h dominates s, successor of b, therefore s is not in the frontier.
|
||||
}
|
||||
if _, ok := newphis[s]; ok {
|
||||
continue // successor s of b already has a new phi function, so there is no need to add another.
|
||||
}
|
||||
if x != nil {
|
||||
for _, v := range s.Values {
|
||||
if v.Op == OpPhi && v.Args[e.i] == x {
|
||||
continue outer // successor s of b has an old phi function, so there is no need to add another.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
old := defForUses[idom[s.ID].ID] // new phi function is correct-but-redundant, combining value "old" on all inputs.
|
||||
headerPhi := newPhiFor(s, old)
|
||||
// the new phi will replace "old" in block s and all blocks dominated by s.
|
||||
newphis[s] = rewrite{before: old, after: headerPhi} // record new phi, to have inputs labeled "old" rewritten to "headerPhi"
|
||||
addDFphis(old, s, s, f, defForUses, newphis) // the new definition may also create new phi functions.
|
||||
}
|
||||
for c := sdom[b.ID].child; c != nil; c = sdom[c.ID].sibling {
|
||||
addDFphis(x, h, c, f, defForUses, newphis) // TODO: convert to explicit stack from recursion.
|
||||
}
|
||||
}
|
||||
|
||||
// findLastMems maps block ids to last memory-output op in a block, if any
|
||||
func findLastMems(f *Func) []*Value {
|
||||
|
||||
var stores []*Value
|
||||
lastMems := make([]*Value, f.NumBlocks())
|
||||
storeUse := f.newSparseSet(f.NumValues())
|
||||
defer f.retSparseSet(storeUse)
|
||||
for _, b := range f.Blocks {
|
||||
// Find all the stores in this block. Categorize their uses:
|
||||
// storeUse contains stores which are used by a subsequent store.
|
||||
storeUse.clear()
|
||||
stores = stores[:0]
|
||||
var memPhi *Value
|
||||
for _, v := range b.Values {
|
||||
if v.Op == OpPhi {
|
||||
if v.Type.IsMemory() {
|
||||
memPhi = v
|
||||
}
|
||||
continue
|
||||
}
|
||||
if v.Type.IsMemory() {
|
||||
stores = append(stores, v)
|
||||
if v.Op == OpSelect1 {
|
||||
// Use the arg of the tuple-generating op.
|
||||
v = v.Args[0]
|
||||
}
|
||||
for _, a := range v.Args {
|
||||
if a.Block == b && a.Type.IsMemory() {
|
||||
storeUse.add(a.ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(stores) == 0 {
|
||||
lastMems[b.ID] = memPhi
|
||||
continue
|
||||
}
|
||||
|
||||
// find last store in the block
|
||||
var last *Value
|
||||
for _, v := range stores {
|
||||
if storeUse.contains(v.ID) {
|
||||
continue
|
||||
}
|
||||
if last != nil {
|
||||
b.Fatalf("two final stores - simultaneous live stores %s %s", last, v)
|
||||
}
|
||||
last = v
|
||||
}
|
||||
if last == nil {
|
||||
b.Fatalf("no last store found - cycle?")
|
||||
}
|
||||
lastMems[b.ID] = last
|
||||
}
|
||||
return lastMems
|
||||
}
|
||||
|
||||
type backedgesState struct {
|
||||
b *Block
|
||||
i int
|
||||
}
|
||||
|
||||
// backedges returns a slice of successor edges that are back
|
||||
// edges. For reducible loops, edge.b is the header.
|
||||
func backedges(f *Func) []Edge {
|
||||
edges := []Edge{}
|
||||
mark := make([]markKind, f.NumBlocks())
|
||||
stack := []backedgesState{}
|
||||
|
||||
mark[f.Entry.ID] = notExplored
|
||||
stack = append(stack, backedgesState{f.Entry, 0})
|
||||
|
||||
for len(stack) > 0 {
|
||||
l := len(stack)
|
||||
x := stack[l-1]
|
||||
if x.i < len(x.b.Succs) {
|
||||
e := x.b.Succs[x.i]
|
||||
stack[l-1].i++
|
||||
s := e.b
|
||||
if mark[s.ID] == notFound {
|
||||
mark[s.ID] = notExplored
|
||||
stack = append(stack, backedgesState{s, 0})
|
||||
} else if mark[s.ID] == notExplored {
|
||||
edges = append(edges, e)
|
||||
}
|
||||
} else {
|
||||
mark[x.b.ID] = done
|
||||
stack = stack[0 : l-1]
|
||||
}
|
||||
}
|
||||
return edges
|
||||
}
|
||||
@@ -132,6 +132,8 @@ func nilcheckelim(f *Func) {
|
||||
}
|
||||
|
||||
// All platforms are guaranteed to fault if we load/store to anything smaller than this address.
|
||||
//
|
||||
// This should agree with minLegalPointer in the runtime.
|
||||
const minZeroPage = 4096
|
||||
|
||||
// nilcheckelim2 eliminates unnecessary nil checks.
|
||||
|
||||
@@ -21,7 +21,7 @@ type opInfo struct {
|
||||
name string
|
||||
reg regInfo
|
||||
auxType auxType
|
||||
argLen int32 // the number of arugments, -1 if variable length
|
||||
argLen int32 // the number of arguments, -1 if variable length
|
||||
asm obj.As
|
||||
generic bool // this is a generic (arch-independent) opcode
|
||||
rematerializeable bool // this op is rematerializeable
|
||||
|
||||
@@ -759,7 +759,7 @@ func (s *regAllocState) regalloc(f *Func) {
|
||||
liveSet.add(e.ID)
|
||||
}
|
||||
if v := b.Control; v != nil && s.values[v.ID].needReg {
|
||||
s.addUse(v.ID, int32(len(b.Values)), b.Line) // psuedo-use by control value
|
||||
s.addUse(v.ID, int32(len(b.Values)), b.Line) // pseudo-use by control value
|
||||
liveSet.add(v.ID)
|
||||
}
|
||||
for i := len(b.Values) - 1; i >= 0; i-- {
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
|
||||
package ssa
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type SparseTreeNode struct {
|
||||
child *Block
|
||||
@@ -67,6 +70,34 @@ func newSparseTree(f *Func, parentOf []*Block) SparseTree {
|
||||
return t
|
||||
}
|
||||
|
||||
// treestructure provides a string description of the dominator
|
||||
// tree and flow structure of block b and all blocks that it
|
||||
// dominates.
|
||||
func (t SparseTree) treestructure(b *Block) string {
|
||||
return t.treestructure1(b, 0)
|
||||
}
|
||||
func (t SparseTree) treestructure1(b *Block, i int) string {
|
||||
s := "\n" + strings.Repeat("\t", i) + b.String() + "->["
|
||||
for i, e := range b.Succs {
|
||||
if i > 0 {
|
||||
s = s + ","
|
||||
}
|
||||
s = s + e.b.String()
|
||||
}
|
||||
s += "]"
|
||||
if c0 := t[b.ID].child; c0 != nil {
|
||||
s += "("
|
||||
for c := c0; c != nil; c = t[c.ID].sibling {
|
||||
if c != c0 {
|
||||
s += " "
|
||||
}
|
||||
s += t.treestructure1(c, i+1)
|
||||
}
|
||||
s += ")"
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// numberBlock assigns entry and exit numbers for b and b's
|
||||
// children in an in-order walk from a gappy sequence, where n
|
||||
// is the first number not yet assigned or reserved. N should
|
||||
|
||||
@@ -44,7 +44,7 @@ func (t *TypeImpl) IsVoid() bool { return false }
|
||||
func (t *TypeImpl) String() string { return t.Name }
|
||||
func (t *TypeImpl) SimpleString() string { return t.Name }
|
||||
func (t *TypeImpl) ElemType() Type { return t.Elem_ }
|
||||
func (t *TypeImpl) PtrTo() Type { panic("not implemented") }
|
||||
func (t *TypeImpl) PtrTo() Type { return TypeBytePtr }
|
||||
func (t *TypeImpl) NumFields() int { panic("not implemented") }
|
||||
func (t *TypeImpl) FieldType(i int) Type { panic("not implemented") }
|
||||
func (t *TypeImpl) FieldOff(i int) int64 { panic("not implemented") }
|
||||
|
||||
@@ -78,7 +78,6 @@ func writebarrier(f *Func) {
|
||||
defer f.retSparseSet(wbs)
|
||||
}
|
||||
|
||||
mem := v.Args[2]
|
||||
line := v.Line
|
||||
|
||||
// there may be a sequence of WB stores in the current block. find them.
|
||||
@@ -106,6 +105,20 @@ func writebarrier(f *Func) {
|
||||
}
|
||||
}
|
||||
|
||||
// find the memory before the WB stores
|
||||
// this memory is not a WB store but it is used in a WB store.
|
||||
var mem *Value
|
||||
for _, w := range storeWBs {
|
||||
a := w.Args[len(w.Args)-1]
|
||||
if wbs.contains(a.ID) {
|
||||
continue
|
||||
}
|
||||
if mem != nil {
|
||||
b.Fatalf("two stores live simultaneously: %s, %s", mem, a)
|
||||
}
|
||||
mem = a
|
||||
}
|
||||
|
||||
b.Values = append(b.Values[:i], others...) // move WB ops out of this block
|
||||
|
||||
bThen := f.NewBlock(BlockPlain)
|
||||
@@ -177,20 +190,39 @@ func writebarrier(f *Func) {
|
||||
// which may be used in subsequent blocks. Other memories in the
|
||||
// sequence must be dead after this block since there can be only
|
||||
// one memory live.
|
||||
v = storeWBs[len(storeWBs)-1]
|
||||
bEnd.Values = append(bEnd.Values, v)
|
||||
v.Block = bEnd
|
||||
v.reset(OpPhi)
|
||||
v.Type = TypeMem
|
||||
v.AddArg(memThen)
|
||||
v.AddArg(memElse)
|
||||
for _, w := range storeWBs[:len(storeWBs)-1] {
|
||||
for _, a := range w.Args {
|
||||
a.Uses--
|
||||
last := storeWBs[0]
|
||||
if len(storeWBs) > 1 {
|
||||
// find the last store
|
||||
last = nil
|
||||
wbs.clear() // we reuse wbs to record WB stores that is used in another WB store
|
||||
for _, w := range storeWBs {
|
||||
wbs.add(w.Args[len(w.Args)-1].ID)
|
||||
}
|
||||
for _, w := range storeWBs {
|
||||
if wbs.contains(w.ID) {
|
||||
continue
|
||||
}
|
||||
if last != nil {
|
||||
b.Fatalf("two stores live simultaneously: %s, %s", last, w)
|
||||
}
|
||||
last = w
|
||||
}
|
||||
}
|
||||
for _, w := range storeWBs[:len(storeWBs)-1] {
|
||||
f.freeValue(w)
|
||||
bEnd.Values = append(bEnd.Values, last)
|
||||
last.Block = bEnd
|
||||
last.reset(OpPhi)
|
||||
last.Type = TypeMem
|
||||
last.AddArg(memThen)
|
||||
last.AddArg(memElse)
|
||||
for _, w := range storeWBs {
|
||||
if w != last {
|
||||
w.resetArgs()
|
||||
}
|
||||
}
|
||||
for _, w := range storeWBs {
|
||||
if w != last {
|
||||
f.freeValue(w)
|
||||
}
|
||||
}
|
||||
|
||||
if f.Config.fe.Debug_wb() {
|
||||
|
||||
29
src/cmd/compile/internal/ssa/writebarrier_test.go
Normal file
29
src/cmd/compile/internal/ssa/writebarrier_test.go
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright 2016 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 ssa
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestWriteBarrierStoreOrder(t *testing.T) {
|
||||
// Make sure writebarrier phase works even StoreWB ops are not in dependency order
|
||||
c := testConfig(t)
|
||||
ptrType := &TypeImpl{Size_: 8, Ptr: true, Name: "testptr"} // dummy for testing
|
||||
fun := Fun(c, "entry",
|
||||
Bloc("entry",
|
||||
Valu("start", OpInitMem, TypeMem, 0, nil),
|
||||
Valu("sb", OpSB, TypeInvalid, 0, nil),
|
||||
Valu("sp", OpSP, TypeInvalid, 0, nil),
|
||||
Valu("v", OpConstNil, ptrType, 0, nil),
|
||||
Valu("addr1", OpAddr, ptrType, 0, nil, "sb"),
|
||||
Valu("wb2", OpStoreWB, TypeMem, 8, nil, "addr1", "v", "wb1"),
|
||||
Valu("wb1", OpStoreWB, TypeMem, 8, nil, "addr1", "v", "start"), // wb1 and wb2 are out of order
|
||||
Goto("exit")),
|
||||
Bloc("exit",
|
||||
Exit("wb2")))
|
||||
|
||||
CheckFunc(fun.f)
|
||||
writebarrier(fun.f)
|
||||
CheckFunc(fun.f)
|
||||
}
|
||||
@@ -26,8 +26,6 @@ type parser struct {
|
||||
indent []byte // tracing support
|
||||
}
|
||||
|
||||
type parserError string // for error recovery if no error handler was installed
|
||||
|
||||
func (p *parser) init(src io.Reader, errh ErrorHandler, pragh PragmaHandler) {
|
||||
p.scanner.init(src, errh, pragh)
|
||||
|
||||
|
||||
@@ -151,11 +151,12 @@ type Block struct {
|
||||
// File is a wrapper for the state of a file used in the parser.
|
||||
// The basic parse tree walker is a method of this type.
|
||||
type File struct {
|
||||
fset *token.FileSet
|
||||
name string // Name of file.
|
||||
astFile *ast.File
|
||||
blocks []Block
|
||||
atomicPkg string // Package name for "sync/atomic" in this file.
|
||||
fset *token.FileSet
|
||||
name string // Name of file.
|
||||
astFile *ast.File
|
||||
blocks []Block
|
||||
atomicPkg string // Package name for "sync/atomic" in this file.
|
||||
directives map[*ast.Comment]bool // Map of compiler directives to whether it's processed in ast.Visitor or not.
|
||||
}
|
||||
|
||||
// Visit implements the ast.Visitor interface.
|
||||
@@ -247,8 +248,11 @@ func (f *File) Visit(node ast.Node) ast.Visitor {
|
||||
// to appear in syntactically incorrect places. //go: appears at the beginning of
|
||||
// the line and is syntactically safe.
|
||||
for _, c := range n.List {
|
||||
if strings.HasPrefix(c.Text, "//go:") && f.fset.Position(c.Slash).Column == 1 {
|
||||
if f.isDirective(c) {
|
||||
list = append(list, c)
|
||||
|
||||
// Mark compiler directive as handled.
|
||||
f.directives[c] = true
|
||||
}
|
||||
}
|
||||
n.List = list
|
||||
@@ -360,17 +364,27 @@ func annotate(name string) {
|
||||
if err != nil {
|
||||
log.Fatalf("cover: %s: %s", name, err)
|
||||
}
|
||||
// Remove comments. Or else they interfere with new AST.
|
||||
parsedFile.Comments = nil
|
||||
|
||||
file := &File{
|
||||
fset: fset,
|
||||
name: name,
|
||||
astFile: parsedFile,
|
||||
fset: fset,
|
||||
name: name,
|
||||
astFile: parsedFile,
|
||||
directives: map[*ast.Comment]bool{},
|
||||
}
|
||||
if *mode == "atomic" {
|
||||
file.atomicPkg = file.addImport(atomicPackagePath)
|
||||
}
|
||||
|
||||
for _, cg := range parsedFile.Comments {
|
||||
for _, c := range cg.List {
|
||||
if file.isDirective(c) {
|
||||
file.directives[c] = false
|
||||
}
|
||||
}
|
||||
}
|
||||
// Remove comments. Or else they interfere with new AST.
|
||||
parsedFile.Comments = nil
|
||||
|
||||
ast.Walk(file, file.astFile)
|
||||
fd := os.Stdout
|
||||
if *output != "" {
|
||||
@@ -381,6 +395,17 @@ func annotate(name string) {
|
||||
}
|
||||
}
|
||||
fd.Write(initialComments(content)) // Retain '// +build' directives.
|
||||
|
||||
// Retain compiler directives that are not processed in ast.Visitor.
|
||||
// Some compiler directives like "go:linkname" and "go:cgo_"
|
||||
// can be not attached to anything in the tree and hence will not be printed by printer.
|
||||
// So, we have to explicitly print them here.
|
||||
for cd, handled := range file.directives {
|
||||
if !handled {
|
||||
fmt.Fprintln(fd, cd.Text)
|
||||
}
|
||||
}
|
||||
|
||||
file.print(fd)
|
||||
// After printing the source tree, add some declarations for the counters etc.
|
||||
// We could do this by adding to the tree, but it's easier just to print the text.
|
||||
@@ -391,6 +416,11 @@ func (f *File) print(w io.Writer) {
|
||||
printer.Fprint(w, f.fset, f.astFile)
|
||||
}
|
||||
|
||||
// isDirective reports whether a comment is a compiler directive.
|
||||
func (f *File) isDirective(c *ast.Comment) bool {
|
||||
return strings.HasPrefix(c.Text, "//go:") && f.fset.Position(c.Slash).Column == 1
|
||||
}
|
||||
|
||||
// intLiteral returns an ast.BasicLit representing the integer value.
|
||||
func (f *File) intLiteral(i int) *ast.BasicLit {
|
||||
node := &ast.BasicLit{
|
||||
|
||||
@@ -90,6 +90,11 @@ func TestCover(t *testing.T) {
|
||||
if got, err := regexp.MatchString(".*\n//go:nosplit\nfunc someFunction().*", string(file)); err != nil || !got {
|
||||
t.Errorf("misplaced compiler directive: got=(%v, %v); want=(true; nil)", got, err)
|
||||
}
|
||||
// "go:linkname" compiler directive should be present.
|
||||
if got, err := regexp.MatchString(`.*go\:linkname some\_name some\_name.*`, string(file)); err != nil || !got {
|
||||
t.Errorf("'go:linkname' compiler directive not found: got=(%v, %v); want=(true; nil)", got, err)
|
||||
}
|
||||
|
||||
// No other comments should be present in generated code.
|
||||
c := ".*// This comment shouldn't appear in generated go code.*"
|
||||
if got, err := regexp.MatchString(c, string(file)); err != nil || got {
|
||||
|
||||
4
src/cmd/cover/testdata/test.go
vendored
4
src/cmd/cover/testdata/test.go
vendored
@@ -10,6 +10,10 @@
|
||||
|
||||
package main
|
||||
|
||||
import _ "unsafe" // for go:linkname
|
||||
|
||||
//go:linkname some_name some_name
|
||||
|
||||
const anything = 1e9 // Just some unlikely value that means "we got here, don't care how often"
|
||||
|
||||
func testAll() {
|
||||
|
||||
4
src/cmd/dist/build.go
vendored
4
src/cmd/dist/build.go
vendored
@@ -1107,8 +1107,8 @@ var cgoEnabled = map[string]bool{
|
||||
"linux/arm64": true,
|
||||
"linux/ppc64": false,
|
||||
"linux/ppc64le": true,
|
||||
"linux/mips": false,
|
||||
"linux/mipsle": false,
|
||||
"linux/mips": true,
|
||||
"linux/mipsle": true,
|
||||
"linux/mips64": true,
|
||||
"linux/mips64le": true,
|
||||
"linux/s390x": true,
|
||||
|
||||
38
src/cmd/dist/test.go
vendored
38
src/cmd/dist/test.go
vendored
@@ -15,6 +15,7 @@ import (
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -152,8 +153,11 @@ func (t *tester) run() {
|
||||
}
|
||||
|
||||
t.timeoutScale = 1
|
||||
if t.goarch == "arm" || t.goos == "windows" {
|
||||
switch t.goarch {
|
||||
case "arm":
|
||||
t.timeoutScale = 2
|
||||
case "mips", "mipsle", "mips64", "mips64le":
|
||||
t.timeoutScale = 4
|
||||
}
|
||||
if s := os.Getenv("GO_TEST_TIMEOUT_SCALE"); s != "" {
|
||||
t.timeoutScale, err = strconv.Atoi(s)
|
||||
@@ -328,6 +332,10 @@ func (t *tester) registerRaceBenchTest(pkg string) {
|
||||
})
|
||||
}
|
||||
|
||||
// stdOutErrAreTerminals is defined in test_linux.go, to report
|
||||
// whether stdout & stderr are terminals.
|
||||
var stdOutErrAreTerminals func() bool
|
||||
|
||||
func (t *tester) registerTests() {
|
||||
if strings.HasSuffix(os.Getenv("GO_BUILDER_NAME"), "-vetall") {
|
||||
// Run vet over std and cmd and call it quits.
|
||||
@@ -344,6 +352,27 @@ func (t *tester) registerTests() {
|
||||
return
|
||||
}
|
||||
|
||||
// This test needs its stdout/stderr to be terminals, so we don't run it from cmd/go's tests.
|
||||
// See issue 18153.
|
||||
if runtime.GOOS == "linux" {
|
||||
t.tests = append(t.tests, distTest{
|
||||
name: "cmd_go_test_terminal",
|
||||
heading: "cmd/go terminal test",
|
||||
fn: func(dt *distTest) error {
|
||||
t.runPending(dt)
|
||||
if !stdOutErrAreTerminals() {
|
||||
fmt.Println("skipping terminal test; stdout/stderr not terminals")
|
||||
return nil
|
||||
}
|
||||
cmd := exec.Command("go", "test")
|
||||
cmd.Dir = filepath.Join(os.Getenv("GOROOT"), "src/cmd/go/testdata/testterminal18153")
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
return cmd.Run()
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Fast path to avoid the ~1 second of `go list std cmd` when
|
||||
// the caller lists specific tests to run. (as the continuous
|
||||
// build coordinator does).
|
||||
@@ -675,7 +704,7 @@ func (t *tester) extLink() bool {
|
||||
"darwin-arm", "darwin-arm64",
|
||||
"dragonfly-386", "dragonfly-amd64",
|
||||
"freebsd-386", "freebsd-amd64", "freebsd-arm",
|
||||
"linux-386", "linux-amd64", "linux-arm", "linux-arm64", "linux-ppc64le", "linux-mips64", "linux-mips64le",
|
||||
"linux-386", "linux-amd64", "linux-arm", "linux-arm64", "linux-ppc64le", "linux-mips64", "linux-mips64le", "linux-mips", "linux-mipsle", "linux-s390x",
|
||||
"netbsd-386", "netbsd-amd64",
|
||||
"openbsd-386", "openbsd-amd64",
|
||||
"windows-386", "windows-amd64":
|
||||
@@ -712,7 +741,7 @@ func (t *tester) internalLink() bool {
|
||||
// Internally linking cgo is incomplete on some architectures.
|
||||
// https://golang.org/issue/10373
|
||||
// https://golang.org/issue/14449
|
||||
if t.goarch == "arm64" || t.goarch == "mips64" || t.goarch == "mips64le" {
|
||||
if t.goarch == "arm64" || t.goarch == "mips64" || t.goarch == "mips64le" || t.goarch == "mips" || t.goarch == "mipsle" {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@@ -757,8 +786,7 @@ func (t *tester) supportedBuildmode(mode string) bool {
|
||||
// linux-arm64 is missing because it causes the external linker
|
||||
// to crash, see https://golang.org/issue/17138
|
||||
switch pair {
|
||||
case "linux-386", "linux-amd64", "linux-arm",
|
||||
"darwin-amd64":
|
||||
case "linux-386", "linux-amd64", "linux-arm":
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
27
src/cmd/dist/test_linux.go
vendored
Normal file
27
src/cmd/dist/test_linux.go
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
// Copyright 2016 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
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const ioctlReadTermios = syscall.TCGETS
|
||||
|
||||
// isTerminal reports whether fd is a terminal.
|
||||
func isTerminal(fd uintptr) bool {
|
||||
var termios syscall.Termios
|
||||
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
|
||||
return err == 0
|
||||
}
|
||||
|
||||
func init() {
|
||||
stdOutErrAreTerminals = func() bool {
|
||||
return isTerminal(1) && isTerminal(2)
|
||||
}
|
||||
}
|
||||
8
src/cmd/dist/util.go
vendored
8
src/cmd/dist/util.go
vendored
@@ -393,6 +393,14 @@ func errprintf(format string, args ...interface{}) {
|
||||
func main() {
|
||||
os.Setenv("TERM", "dumb") // disable escape codes in clang errors
|
||||
|
||||
// provide -check-armv6k first, before checking for $GOROOT so that
|
||||
// it is possible to run this check without having $GOROOT available.
|
||||
if len(os.Args) > 1 && os.Args[1] == "-check-armv6k" {
|
||||
useARMv6K() // might fail with SIGILL
|
||||
println("ARMv6K supported.")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
slash = string(filepath.Separator)
|
||||
|
||||
gohostos = runtime.GOOS
|
||||
|
||||
5
src/cmd/dist/util_gc.go
vendored
5
src/cmd/dist/util_gc.go
vendored
@@ -25,3 +25,8 @@ func useVFPv1()
|
||||
// useVFPv3 tries to execute one VFPv3 instruction on ARM.
|
||||
// It will crash the current process if VFPv3 is missing.
|
||||
func useVFPv3()
|
||||
|
||||
// useARMv6K tries to run ARMv6K instructions on ARM.
|
||||
// It will crash the current process if it doesn't implement
|
||||
// ARMv6K or above.
|
||||
func useARMv6K()
|
||||
|
||||
2
src/cmd/dist/util_gccgo.go
vendored
2
src/cmd/dist/util_gccgo.go
vendored
@@ -22,3 +22,5 @@ func cansse2() bool { return C.supports_sse2() != 0 }
|
||||
func useVFPv1() {}
|
||||
|
||||
func useVFPv3() {}
|
||||
|
||||
func useARMv6K() {}
|
||||
|
||||
9
src/cmd/dist/vfp_arm.s
vendored
9
src/cmd/dist/vfp_arm.s
vendored
@@ -15,3 +15,12 @@ TEXT ·useVFPv1(SB),NOSPLIT,$0
|
||||
TEXT ·useVFPv3(SB),NOSPLIT,$0
|
||||
WORD $0xeeb70b00 // vmov.f64 d0, #112
|
||||
RET
|
||||
|
||||
// try to run ARMv6K (or above) "ldrexd" instruction
|
||||
TEXT ·useARMv6K(SB),NOSPLIT,$32
|
||||
MOVW R13, R2
|
||||
BIC $15, R13
|
||||
WORD $0xe1bd0f9f // ldrexd r0, r1, [sp]
|
||||
WORD $0xf57ff01f // clrex
|
||||
MOVW R2, R13
|
||||
RET
|
||||
|
||||
3
src/cmd/dist/vfp_default.s
vendored
3
src/cmd/dist/vfp_default.s
vendored
@@ -11,3 +11,6 @@ TEXT ·useVFPv1(SB),NOSPLIT,$0
|
||||
|
||||
TEXT ·useVFPv3(SB),NOSPLIT,$0
|
||||
RET
|
||||
|
||||
TEXT ·useARMv6K(SB),NOSPLIT,$0
|
||||
RET
|
||||
|
||||
@@ -935,6 +935,8 @@
|
||||
// unless that directory holds a Go distribution.
|
||||
// Run "go env GOPATH" to see the current GOPATH.
|
||||
//
|
||||
// See https://golang.org/wiki/SettingGOPATH to set a custom GOPATH.
|
||||
//
|
||||
// Each directory listed in GOPATH must have a prescribed structure:
|
||||
//
|
||||
// The src directory holds source code. The path below src
|
||||
@@ -1474,7 +1476,7 @@
|
||||
// text from Log and Logf calls even if the test succeeds.
|
||||
//
|
||||
// The following flags are also recognized by 'go test' and can be used to
|
||||
// profile the tests during execution::
|
||||
// profile the tests during execution:
|
||||
//
|
||||
// -benchmem
|
||||
// Print memory allocation statistics for benchmarks.
|
||||
@@ -1517,7 +1519,7 @@
|
||||
// Writes test binary as -c would.
|
||||
//
|
||||
// -mutexprofilefraction n
|
||||
// Sample 1 in n stack traces of goroutines holding a
|
||||
// Sample 1 in n stack traces of goroutines holding a
|
||||
// contended mutex.
|
||||
//
|
||||
// -outputdir directory
|
||||
@@ -1606,7 +1608,8 @@
|
||||
// is compared exactly against the comment (see examples below). If the last
|
||||
// comment begins with "Unordered output:" then the output is compared to the
|
||||
// comment, however the order of the lines is ignored. An example with no such
|
||||
// comment, or with no text after "Output:" is compiled but not executed.
|
||||
// comment is compiled but not executed. An example with no text after
|
||||
// "Output:" is compiled, executed, and expected to produce no output.
|
||||
//
|
||||
// Godoc displays the body of ExampleXXX to demonstrate the use
|
||||
// of the function, constant, or variable XXX. An example of a method M with
|
||||
|
||||
@@ -42,7 +42,11 @@ func runBug(cmd *Command, args []string) {
|
||||
env := newEnv
|
||||
env = append(env, extraEnvVars()...)
|
||||
for _, e := range env {
|
||||
fmt.Fprintf(&buf, "%s=\"%s\"\n", e.name, e.value)
|
||||
// Hide the TERM environment variable from "go bug".
|
||||
// See issue #18128
|
||||
if e.name != "TERM" {
|
||||
fmt.Fprintf(&buf, "%s=\"%s\"\n", e.name, e.value)
|
||||
}
|
||||
}
|
||||
printGoDetails(&buf)
|
||||
printOSDetails(&buf)
|
||||
|
||||
@@ -413,8 +413,7 @@ func buildModeInit() {
|
||||
} else {
|
||||
switch platform {
|
||||
case "linux/amd64", "linux/arm", "linux/arm64", "linux/386",
|
||||
"android/amd64", "android/arm", "android/arm64", "android/386",
|
||||
"darwin/amd64":
|
||||
"android/amd64", "android/arm", "android/arm64", "android/386":
|
||||
default:
|
||||
fatalf("-buildmode=plugin not supported on %s\n", platform)
|
||||
}
|
||||
@@ -2406,8 +2405,7 @@ func (gcToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool,
|
||||
func (gcToolchain) asm(b *builder, p *Package, obj string, sfiles []string) ([]string, error) {
|
||||
// Add -I pkg/GOOS_GOARCH so #include "textflag.h" works in .s files.
|
||||
inc := filepath.Join(goroot, "pkg", "include")
|
||||
ofile := obj + "asm.o"
|
||||
args := []interface{}{buildToolExec, tool("asm"), "-o", ofile, "-trimpath", b.work, "-I", obj, "-I", inc, "-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch, buildAsmflags}
|
||||
args := []interface{}{buildToolExec, tool("asm"), "-trimpath", b.work, "-I", obj, "-I", inc, "-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch, buildAsmflags}
|
||||
if p.ImportPath == "runtime" && goarch == "386" {
|
||||
for _, arg := range buildAsmflags {
|
||||
if arg == "-dynlink" {
|
||||
@@ -2415,13 +2413,16 @@ func (gcToolchain) asm(b *builder, p *Package, obj string, sfiles []string) ([]s
|
||||
}
|
||||
}
|
||||
}
|
||||
var ofiles []string
|
||||
for _, sfile := range sfiles {
|
||||
args = append(args, mkAbs(p.Dir, sfile))
|
||||
ofile := obj + sfile[:len(sfile)-len(".s")] + ".o"
|
||||
ofiles = append(ofiles, ofile)
|
||||
a := append(args, "-o", ofile, mkAbs(p.Dir, sfile))
|
||||
if err := b.run(p.Dir, p.ImportPath, nil, a...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if err := b.run(p.Dir, p.ImportPath, nil, args...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []string{ofile}, nil
|
||||
return ofiles, nil
|
||||
}
|
||||
|
||||
// toolVerify checks that the command line args writes the same output file
|
||||
@@ -3218,6 +3219,8 @@ func (b *builder) gccArchArgs() []string {
|
||||
return []string{"-m64", "-march=z196"}
|
||||
case "mips64", "mips64le":
|
||||
return []string{"-mabi=64"}
|
||||
case "mips", "mipsle":
|
||||
return []string{"-mabi=32", "-march=mips32"}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -3773,7 +3776,11 @@ func instrumentInit() {
|
||||
return
|
||||
}
|
||||
if buildRace && buildMSan {
|
||||
fmt.Fprintf(os.Stderr, "go %s: may not use -race and -msan simultaneously", flag.Args()[0])
|
||||
fmt.Fprintf(os.Stderr, "go %s: may not use -race and -msan simultaneously\n", flag.Args()[0])
|
||||
os.Exit(2)
|
||||
}
|
||||
if buildMSan && (goos != "linux" || goarch != "amd64") {
|
||||
fmt.Fprintf(os.Stderr, "-msan is not supported on %s/%s\n", goos, goarch)
|
||||
os.Exit(2)
|
||||
}
|
||||
if goarch != "amd64" || goos != "linux" && goos != "freebsd" && goos != "darwin" && goos != "windows" {
|
||||
|
||||
@@ -205,6 +205,10 @@ var downloadRootCache = map[string]bool{}
|
||||
// download runs the download half of the get command
|
||||
// for the package named by the argument.
|
||||
func download(arg string, parent *Package, stk *importStack, mode int) {
|
||||
if mode&useVendor != 0 {
|
||||
// Caller is responsible for expanding vendor paths.
|
||||
panic("internal error: download mode has useVendor set")
|
||||
}
|
||||
load := func(path string, mode int) *Package {
|
||||
if parent == nil {
|
||||
return loadPackage(path, stk)
|
||||
@@ -315,33 +319,43 @@ func download(arg string, parent *Package, stk *importStack, mode int) {
|
||||
}
|
||||
|
||||
// Process dependencies, now that we know what they are.
|
||||
for _, path := range p.Imports {
|
||||
imports := p.Imports
|
||||
if mode&getTestDeps != 0 {
|
||||
// Process test dependencies when -t is specified.
|
||||
// (But don't get test dependencies for test dependencies:
|
||||
// we always pass mode 0 to the recursive calls below.)
|
||||
imports = stringList(imports, p.TestImports, p.XTestImports)
|
||||
}
|
||||
for i, path := range imports {
|
||||
if path == "C" {
|
||||
continue
|
||||
}
|
||||
// Don't get test dependencies recursively.
|
||||
// Imports is already vendor-expanded.
|
||||
// Fail fast on import naming full vendor path.
|
||||
// Otherwise expand path as needed for test imports.
|
||||
// Note that p.Imports can have additional entries beyond p.build.Imports.
|
||||
orig := path
|
||||
if i < len(p.build.Imports) {
|
||||
orig = p.build.Imports[i]
|
||||
}
|
||||
if j, ok := findVendor(orig); ok {
|
||||
stk.push(path)
|
||||
err := &PackageError{
|
||||
ImportStack: stk.copy(),
|
||||
Err: "must be imported as " + path[j+len("vendor/"):],
|
||||
}
|
||||
stk.pop()
|
||||
errorf("%s", err)
|
||||
continue
|
||||
}
|
||||
// If this is a test import, apply vendor lookup now.
|
||||
// We cannot pass useVendor to download, because
|
||||
// download does caching based on the value of path,
|
||||
// so it must be the fully qualified path already.
|
||||
if i >= len(p.Imports) {
|
||||
path = vendoredImportPath(p, path)
|
||||
}
|
||||
download(path, p, stk, 0)
|
||||
}
|
||||
if mode&getTestDeps != 0 {
|
||||
// Process test dependencies when -t is specified.
|
||||
// (Don't get test dependencies for test dependencies.)
|
||||
// We pass useVendor here because p.load does not
|
||||
// vendor-expand TestImports and XTestImports.
|
||||
// The call to loadImport inside download needs to do that.
|
||||
for _, path := range p.TestImports {
|
||||
if path == "C" {
|
||||
continue
|
||||
}
|
||||
download(path, p, stk, useVendor)
|
||||
}
|
||||
for _, path := range p.XTestImports {
|
||||
if path == "C" {
|
||||
continue
|
||||
}
|
||||
download(path, p, stk, useVendor)
|
||||
}
|
||||
}
|
||||
|
||||
if isWildcard {
|
||||
stk.pop()
|
||||
|
||||
@@ -1700,6 +1700,8 @@ func TestMissingGOPATHEnvShowsDefault(t *testing.T) {
|
||||
|
||||
// Test go get missing GOPATH causes go get to warn if directory doesn't exist.
|
||||
func TestMissingGOPATHGetWarnsIfNotExists(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
|
||||
if _, err := exec.LookPath("git"); err != nil {
|
||||
t.Skip("skipping because git binary not found")
|
||||
}
|
||||
@@ -1727,6 +1729,8 @@ func TestMissingGOPATHGetWarnsIfNotExists(t *testing.T) {
|
||||
|
||||
// Test go get missing GOPATH causes no warning if directory exists.
|
||||
func TestMissingGOPATHGetDoesntWarnIfExists(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
|
||||
if _, err := exec.LookPath("git"); err != nil {
|
||||
t.Skip("skipping because git binary not found")
|
||||
}
|
||||
@@ -1757,6 +1761,8 @@ func TestMissingGOPATHGetDoesntWarnIfExists(t *testing.T) {
|
||||
|
||||
// Test go get missing GOPATH fails if pointed file is not a directory.
|
||||
func TestMissingGOPATHGetFailsIfItsNotDirectory(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
|
||||
@@ -1879,6 +1885,26 @@ func TestGoTestCpuprofileDashOControlsBinaryLocation(t *testing.T) {
|
||||
tg.wantExecutable("myerrors.test"+exeSuffix, "go test -cpuprofile -o myerrors.test did not create myerrors.test")
|
||||
}
|
||||
|
||||
func TestGoTestMutexprofileLeavesBinaryBehind(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
// TODO: tg.parallel()
|
||||
tg.makeTempdir()
|
||||
tg.cd(tg.path("."))
|
||||
tg.run("test", "-mutexprofile", "errors.prof", "errors")
|
||||
tg.wantExecutable("errors.test"+exeSuffix, "go test -mutexprofile did not create errors.test")
|
||||
}
|
||||
|
||||
func TestGoTestMutexprofileDashOControlsBinaryLocation(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
// TODO: tg.parallel()
|
||||
tg.makeTempdir()
|
||||
tg.cd(tg.path("."))
|
||||
tg.run("test", "-mutexprofile", "errors.prof", "-o", "myerrors.test"+exeSuffix, "errors")
|
||||
tg.wantExecutable("myerrors.test"+exeSuffix, "go test -mutexprofile -o myerrors.test did not create myerrors.test")
|
||||
}
|
||||
|
||||
func TestGoTestDashCDashOControlsBinaryLocation(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
@@ -2067,9 +2093,7 @@ func TestCaseCollisions(t *testing.T) {
|
||||
|
||||
// Issue 8181.
|
||||
func TestGoGetDashTIssue8181(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping test that uses network in short mode")
|
||||
}
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
@@ -2083,9 +2107,7 @@ func TestGoGetDashTIssue8181(t *testing.T) {
|
||||
|
||||
func TestIssue11307(t *testing.T) {
|
||||
// go get -u was not working except in checkout directory
|
||||
if testing.Short() {
|
||||
t.Skip("skipping test that uses network in short mode")
|
||||
}
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
@@ -2245,6 +2267,28 @@ func TestCoverageImportMainLoop(t *testing.T) {
|
||||
tg.grepStderr("not an importable package", "did not detect import main")
|
||||
}
|
||||
|
||||
func TestTestEmpty(t *testing.T) {
|
||||
if !canRace {
|
||||
t.Skip("no race detector")
|
||||
}
|
||||
|
||||
wd, _ := os.Getwd()
|
||||
testdata := filepath.Join(wd, "testdata")
|
||||
|
||||
for _, dir := range []string{"pkg", "test", "xtest", "pkgtest", "pkgxtest", "pkgtestxtest", "testxtest"} {
|
||||
t.Run(dir, func(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.setenv("GOPATH", testdata)
|
||||
tg.cd(filepath.Join(testdata, "src/empty/"+dir))
|
||||
tg.run("test", "-cover", "-coverpkg=.", "-race")
|
||||
})
|
||||
if testing.Short() {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildDryRunWithCgo(t *testing.T) {
|
||||
if !canCgo {
|
||||
t.Skip("skipping because cgo not enabled")
|
||||
@@ -3355,9 +3399,11 @@ func TestCgoConsistentResults(t *testing.T) {
|
||||
if !canCgo {
|
||||
t.Skip("skipping because cgo not enabled")
|
||||
}
|
||||
if runtime.GOOS == "solaris" {
|
||||
// See https://golang.org/issue/13247
|
||||
t.Skip("skipping because Solaris builds are known to be inconsistent; see #13247")
|
||||
switch runtime.GOOS {
|
||||
case "freebsd":
|
||||
testenv.SkipFlaky(t, 15405)
|
||||
case "solaris":
|
||||
testenv.SkipFlaky(t, 13247)
|
||||
}
|
||||
|
||||
tg := testgo(t)
|
||||
@@ -3716,3 +3762,28 @@ func TestLinkXImportPathEscape(t *testing.T) {
|
||||
tg.t.Fatal(`incorrect output: expected "linkXworked\n"`)
|
||||
}
|
||||
}
|
||||
|
||||
// Issue 18044.
|
||||
func TestLdBindNow(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
tg.setenv("LD_BIND_NOW", "1")
|
||||
tg.run("help")
|
||||
}
|
||||
|
||||
// Issue 18225.
|
||||
// This is really a cmd/asm issue but this is a convenient place to test it.
|
||||
func TestConcurrentAsm(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
asm := `DATA ·constants<>+0x0(SB)/8,$0
|
||||
GLOBL ·constants<>(SB),8,$8
|
||||
`
|
||||
tg.tempFile("go/src/p/a.s", asm)
|
||||
tg.tempFile("go/src/p/b.s", asm)
|
||||
tg.tempFile("go/src/p/p.go", `package p`)
|
||||
tg.setenv("GOPATH", tg.path("go"))
|
||||
tg.run("build", "p")
|
||||
}
|
||||
|
||||
@@ -295,6 +295,8 @@ to a subdirectory named "go" in the user's home directory
|
||||
unless that directory holds a Go distribution.
|
||||
Run "go env GOPATH" to see the current GOPATH.
|
||||
|
||||
See https://golang.org/wiki/SettingGOPATH to set a custom GOPATH.
|
||||
|
||||
Each directory listed in GOPATH must have a prescribed structure:
|
||||
|
||||
The src directory holds source code. The path below src
|
||||
|
||||
@@ -33,6 +33,7 @@ var httpClient = http.DefaultClient
|
||||
var impatientInsecureHTTPClient = &http.Client{
|
||||
Timeout: 5 * time.Second,
|
||||
Transport: &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
|
||||
@@ -178,7 +178,9 @@ func (p *Package) copyBuild(pp *build.Package) {
|
||||
p.CgoCXXFLAGS = pp.CgoCXXFLAGS
|
||||
p.CgoLDFLAGS = pp.CgoLDFLAGS
|
||||
p.CgoPkgConfig = pp.CgoPkgConfig
|
||||
p.Imports = pp.Imports
|
||||
// We modify p.Imports in place, so make copy now.
|
||||
p.Imports = make([]string, len(pp.Imports))
|
||||
copy(p.Imports, pp.Imports)
|
||||
p.TestGoFiles = pp.TestGoFiles
|
||||
p.TestImports = pp.TestImports
|
||||
p.XTestGoFiles = pp.XTestGoFiles
|
||||
@@ -953,6 +955,10 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
|
||||
if p.Name == "main" && goarch == "arm" {
|
||||
importPaths = append(importPaths, "math")
|
||||
}
|
||||
// In coverage atomic mode everything depends on sync/atomic.
|
||||
if testCoverMode == "atomic" && (!p.Standard || (p.ImportPath != "runtime/cgo" && p.ImportPath != "runtime/race" && p.ImportPath != "sync/atomic")) {
|
||||
importPaths = append(importPaths, "sync/atomic")
|
||||
}
|
||||
}
|
||||
|
||||
// Runtime and its internal packages depend on runtime/internal/sys,
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"go/doc"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
@@ -201,7 +200,7 @@ const testFlag2 = `
|
||||
text from Log and Logf calls even if the test succeeds.
|
||||
|
||||
The following flags are also recognized by 'go test' and can be used to
|
||||
profile the tests during execution::
|
||||
profile the tests during execution:
|
||||
|
||||
-benchmem
|
||||
Print memory allocation statistics for benchmarks.
|
||||
@@ -244,7 +243,7 @@ profile the tests during execution::
|
||||
Writes test binary as -c would.
|
||||
|
||||
-mutexprofilefraction n
|
||||
Sample 1 in n stack traces of goroutines holding a
|
||||
Sample 1 in n stack traces of goroutines holding a
|
||||
contended mutex.
|
||||
|
||||
-outputdir directory
|
||||
@@ -335,7 +334,8 @@ If the last comment in the function starts with "Output:" then the output
|
||||
is compared exactly against the comment (see examples below). If the last
|
||||
comment begins with "Unordered output:" then the output is compared to the
|
||||
comment, however the order of the lines is ignored. An example with no such
|
||||
comment, or with no text after "Output:" is compiled but not executed.
|
||||
comment is compiled but not executed. An example with no text after
|
||||
"Output:" is compiled, executed, and expected to produce no output.
|
||||
|
||||
Godoc displays the body of ExampleXXX to demonstrate the use
|
||||
of the function, constant, or variable XXX. An example of a method M with
|
||||
@@ -1122,12 +1122,8 @@ func (b *builder) runTest(a *action) error {
|
||||
cmd.Env = envForDir(cmd.Dir, origEnv)
|
||||
var buf bytes.Buffer
|
||||
if testStreamOutput {
|
||||
// The only way to keep the ordering of the messages and still
|
||||
// intercept its contents. os/exec will share the same Pipe for
|
||||
// both Stdout and Stderr when running the test program.
|
||||
mw := io.MultiWriter(os.Stdout, &buf)
|
||||
cmd.Stdout = mw
|
||||
cmd.Stderr = mw
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
} else {
|
||||
cmd.Stdout = &buf
|
||||
cmd.Stderr = &buf
|
||||
@@ -1192,7 +1188,7 @@ func (b *builder) runTest(a *action) error {
|
||||
t := fmt.Sprintf("%.3fs", time.Since(t0).Seconds())
|
||||
if err == nil {
|
||||
norun := ""
|
||||
if testShowPass && !testStreamOutput {
|
||||
if testShowPass {
|
||||
a.testOutput.Write(out)
|
||||
}
|
||||
if bytes.HasPrefix(out, noTestsToRun[1:]) || bytes.Contains(out, noTestsToRun) {
|
||||
@@ -1204,9 +1200,7 @@ func (b *builder) runTest(a *action) error {
|
||||
|
||||
setExitStatus(1)
|
||||
if len(out) > 0 {
|
||||
if !testStreamOutput {
|
||||
a.testOutput.Write(out)
|
||||
}
|
||||
a.testOutput.Write(out)
|
||||
// assume printing the test binary's exit status is superfluous
|
||||
} else {
|
||||
fmt.Fprintf(a.testOutput, "%s\n", err)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user