mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.link] all: merge branch 'master' into dev.link
It has been a while we have not done this.
Merge conflict resolution:
- deleted/rewritten code modified on master
- CL 214286, ported in CL 217317
(cmd/internal/obj/objfile.go)
- CL 210678, it already includes a fix to new code
(cmd/link/internal/ld/deadcode.go)
- CL 209317, applied in this CL
(cmd/link/internal/loadelf/ldelf.go)
Change-Id: Ie927ea6a1d69ce49e8d03e56148cb2725e377876
This commit is contained in:
commit
ee04d45b8f
452 changed files with 18116 additions and 11162 deletions
6
.github/ISSUE_TEMPLATE
vendored
6
.github/ISSUE_TEMPLATE
vendored
|
|
@ -1,4 +1,7 @@
|
||||||
<!-- Please answer these questions before submitting your issue. Thanks! -->
|
<!--
|
||||||
|
Please answer these questions before submitting your issue. Thanks!
|
||||||
|
For questions please use one of our forums: https://github.com/golang/go/wiki/Questions
|
||||||
|
-->
|
||||||
|
|
||||||
### What version of Go are you using (`go version`)?
|
### What version of Go are you using (`go version`)?
|
||||||
|
|
||||||
|
|
@ -33,4 +36,3 @@ A link on play.golang.org is best.
|
||||||
|
|
||||||
|
|
||||||
### What did you see instead?
|
### What did you see instead?
|
||||||
|
|
||||||
|
|
|
||||||
126
CONTRIBUTORS
126
CONTRIBUTORS
|
|
@ -25,6 +25,7 @@
|
||||||
# Please keep the list sorted.
|
# Please keep the list sorted.
|
||||||
|
|
||||||
Aamir Khan <syst3m.w0rm@gmail.com>
|
Aamir Khan <syst3m.w0rm@gmail.com>
|
||||||
|
Aaron Beitch <aaronb@arista.com>
|
||||||
Aaron Cannon <cannona@fireantproductions.com>
|
Aaron Cannon <cannona@fireantproductions.com>
|
||||||
Aaron France <aaron.l.france@gmail.com>
|
Aaron France <aaron.l.france@gmail.com>
|
||||||
Aaron Jacobs <jacobsa@google.com>
|
Aaron Jacobs <jacobsa@google.com>
|
||||||
|
|
@ -44,10 +45,12 @@ Adam Kisala <adam.kisala@gmail.com>
|
||||||
Adam Langley <agl@golang.org>
|
Adam Langley <agl@golang.org>
|
||||||
Adam Medzinski <adam.medzinski@gmail.com>
|
Adam Medzinski <adam.medzinski@gmail.com>
|
||||||
Adam Shannon <adamkshannon@gmail.com>
|
Adam Shannon <adamkshannon@gmail.com>
|
||||||
|
Adam Shelton <aashelt90@gmail.com>
|
||||||
Adam Sindelar <adamsh@google.com>
|
Adam Sindelar <adamsh@google.com>
|
||||||
Adam Thomason <athomason@gmail.com>
|
Adam Thomason <athomason@gmail.com>
|
||||||
Adam Woodbeck <adam@woodbeck.net>
|
Adam Woodbeck <adam@woodbeck.net>
|
||||||
Adarsh Ravichandran <adarshravichandran91@gmail.com>
|
Adarsh Ravichandran <adarshravichandran91@gmail.com>
|
||||||
|
Aditya Harindar <aditya.harindar@gmail.com>
|
||||||
Aditya Mukerjee <dev@chimeracoder.net>
|
Aditya Mukerjee <dev@chimeracoder.net>
|
||||||
Adrian Hesketh <adrianhesketh@hushmail.com>
|
Adrian Hesketh <adrianhesketh@hushmail.com>
|
||||||
Adrian Nos <nos.adrian@gmail.com>
|
Adrian Nos <nos.adrian@gmail.com>
|
||||||
|
|
@ -81,6 +84,7 @@ Albert Yu <yukinying@gmail.com>
|
||||||
Alberto Bertogli <albertito@blitiri.com.ar>
|
Alberto Bertogli <albertito@blitiri.com.ar>
|
||||||
Alberto Donizetti <alb.donizetti@gmail.com>
|
Alberto Donizetti <alb.donizetti@gmail.com>
|
||||||
Alberto García Hierro <alberto@garciahierro.com> <alberto.garcia.hierro@gmail.com>
|
Alberto García Hierro <alberto@garciahierro.com> <alberto.garcia.hierro@gmail.com>
|
||||||
|
Alec Benzer <alec.benzer@gmail.com>
|
||||||
Aleksa Sarai <cyphar@cyphar.com>
|
Aleksa Sarai <cyphar@cyphar.com>
|
||||||
Aleksandar Dezelin <dezelin@gmail.com>
|
Aleksandar Dezelin <dezelin@gmail.com>
|
||||||
Aleksandr Lukinykh <a.lukinykh@xsolla.com>
|
Aleksandr Lukinykh <a.lukinykh@xsolla.com>
|
||||||
|
|
@ -92,7 +96,10 @@ Alex A Skinner <alex@lx.lc>
|
||||||
Alex Brainman <alex.brainman@gmail.com>
|
Alex Brainman <alex.brainman@gmail.com>
|
||||||
Alex Bramley <abramley@google.com>
|
Alex Bramley <abramley@google.com>
|
||||||
Alex Browne <stephenalexbrowne@gmail.com>
|
Alex Browne <stephenalexbrowne@gmail.com>
|
||||||
|
Alex Buchanan <buchanae@gmail.com>
|
||||||
Alex Carol <alex.carol.c@gmail.com>
|
Alex Carol <alex.carol.c@gmail.com>
|
||||||
|
Alex Gaynor <alex@alloy.us>
|
||||||
|
Alex Harford <alex.harford@saucelabs.com>
|
||||||
Alex Jin <toalexjin@gmail.com>
|
Alex Jin <toalexjin@gmail.com>
|
||||||
Alex Kohler <alexjohnkohler@gmail.com>
|
Alex Kohler <alexjohnkohler@gmail.com>
|
||||||
Alex Myasoedov <msoedov@gmail.com>
|
Alex Myasoedov <msoedov@gmail.com>
|
||||||
|
|
@ -101,6 +108,7 @@ Alex Schroeder <alex@gnu.org>
|
||||||
Alex Sergeyev <abc@alexsergeyev.com>
|
Alex Sergeyev <abc@alexsergeyev.com>
|
||||||
Alex Tokarev <aleksator@gmail.com>
|
Alex Tokarev <aleksator@gmail.com>
|
||||||
Alex Vaghin <crhyme@google.com>
|
Alex Vaghin <crhyme@google.com>
|
||||||
|
Alex Zhirov <azhirov@google.com>
|
||||||
Alexander Demakin <alexander.demakin@gmail.com>
|
Alexander Demakin <alexander.demakin@gmail.com>
|
||||||
Alexander Döring <email@alexd.ch>
|
Alexander Döring <email@alexd.ch>
|
||||||
Alexander F Rødseth <alexander.rodseth@appeartv.com>
|
Alexander F Rødseth <alexander.rodseth@appeartv.com>
|
||||||
|
|
@ -121,6 +129,7 @@ Alexander Surma <surma@surmair.de>
|
||||||
Alexander Zhavnerchik <alex.vizor@gmail.com>
|
Alexander Zhavnerchik <alex.vizor@gmail.com>
|
||||||
Alexander Zillion <alex@alexzillion.com>
|
Alexander Zillion <alex@alexzillion.com>
|
||||||
Alexander Zolotov <goldifit@gmail.com>
|
Alexander Zolotov <goldifit@gmail.com>
|
||||||
|
Alexandr Mayorskiy <a.mayorskiy@corp.mail.ru>
|
||||||
Alexandre Cesaro <alexandre.cesaro@gmail.com>
|
Alexandre Cesaro <alexandre.cesaro@gmail.com>
|
||||||
Alexandre Fiori <fiorix@gmail.com>
|
Alexandre Fiori <fiorix@gmail.com>
|
||||||
Alexandre Maari <draeron@gmail.com>
|
Alexandre Maari <draeron@gmail.com>
|
||||||
|
|
@ -147,6 +156,7 @@ Aman Gupta <aman@tmm1.net>
|
||||||
Amir Mohammad Saied <amir@gluegadget.com>
|
Amir Mohammad Saied <amir@gluegadget.com>
|
||||||
Amr Mohammed <merodiro@gmail.com>
|
Amr Mohammed <merodiro@gmail.com>
|
||||||
Amrut Joshi <amrut.joshi@gmail.com>
|
Amrut Joshi <amrut.joshi@gmail.com>
|
||||||
|
An Xiao <hac@zju.edu.cn>
|
||||||
Anand K. Mistry <anand@mistry.ninja>
|
Anand K. Mistry <anand@mistry.ninja>
|
||||||
Anders Pearson <anders@columbia.edu>
|
Anders Pearson <anders@columbia.edu>
|
||||||
Anderson Queiroz <contato@andersonq.eti.br>
|
Anderson Queiroz <contato@andersonq.eti.br>
|
||||||
|
|
@ -157,6 +167,7 @@ Andrea Spadaccini <spadaccio@google.com>
|
||||||
Andreas Auernhammer <aead@mail.de>
|
Andreas Auernhammer <aead@mail.de>
|
||||||
Andreas Jellinghaus <andreas@ionisiert.de> <anj@google.com>
|
Andreas Jellinghaus <andreas@ionisiert.de> <anj@google.com>
|
||||||
Andreas Litt <andreas.litt@gmail.com>
|
Andreas Litt <andreas.litt@gmail.com>
|
||||||
|
Andrei Enshin <b1os@bk.ru>
|
||||||
Andrei Gherzan <andrei@resin.io>
|
Andrei Gherzan <andrei@resin.io>
|
||||||
Andrei Korzhevskii <a.korzhevskiy@gmail.com>
|
Andrei Korzhevskii <a.korzhevskiy@gmail.com>
|
||||||
Andrei Matei <andrei@cockroachlabs.com>
|
Andrei Matei <andrei@cockroachlabs.com>
|
||||||
|
|
@ -177,12 +188,14 @@ Andrew Gerrand <adg@golang.org>
|
||||||
Andrew Harding <andrew@spacemonkey.com>
|
Andrew Harding <andrew@spacemonkey.com>
|
||||||
Andrew Jackura <ajackura@google.com>
|
Andrew Jackura <ajackura@google.com>
|
||||||
Andrew Lutomirski <andy@luto.us>
|
Andrew Lutomirski <andy@luto.us>
|
||||||
|
Andrew Medvedev <andrew.y.medvedev@gmail.com>
|
||||||
Andrew Pilloud <andrewpilloud@igneoussystems.com>
|
Andrew Pilloud <andrewpilloud@igneoussystems.com>
|
||||||
Andrew Pogrebnoy <absourd.noise@gmail.com>
|
Andrew Pogrebnoy <absourd.noise@gmail.com>
|
||||||
Andrew Poydence <apoydence@pivotal.io>
|
Andrew Poydence <apoydence@pivotal.io>
|
||||||
Andrew Pritchard <awpritchard@gmail.com>
|
Andrew Pritchard <awpritchard@gmail.com>
|
||||||
Andrew Radev <andrey.radev@gmail.com>
|
Andrew Radev <andrey.radev@gmail.com>
|
||||||
Andrew Skiba <skibaa@gmail.com>
|
Andrew Skiba <skibaa@gmail.com>
|
||||||
|
Andrew Stormont <astormont@racktopsystems.com>
|
||||||
Andrew Stribblehill <ads@wompom.org>
|
Andrew Stribblehill <ads@wompom.org>
|
||||||
Andrew Szeto <andrew@jabagawee.com>
|
Andrew Szeto <andrew@jabagawee.com>
|
||||||
Andrew Todd <andrew.todd@wework.com>
|
Andrew Todd <andrew.todd@wework.com>
|
||||||
|
|
@ -225,12 +238,14 @@ Anton Gyllenberg <anton@iki.fi>
|
||||||
Antonin Amand <antonin.amand@gmail.com>
|
Antonin Amand <antonin.amand@gmail.com>
|
||||||
Antonio Antelo <aantelov87@gmail.com>
|
Antonio Antelo <aantelov87@gmail.com>
|
||||||
Antonio Bibiano <antbbn@gmail.com>
|
Antonio Bibiano <antbbn@gmail.com>
|
||||||
|
Antonio Huete Jimenez <tuxillo@quantumachine.net>
|
||||||
Antonio Murdaca <runcom@redhat.com>
|
Antonio Murdaca <runcom@redhat.com>
|
||||||
Antonio Troina <thoeni@gmail.com>
|
Antonio Troina <thoeni@gmail.com>
|
||||||
Aofei Sheng <aofei@aofeisheng.com>
|
Aofei Sheng <aofei@aofeisheng.com>
|
||||||
Apisak Darakananda <pongad@gmail.com>
|
Apisak Darakananda <pongad@gmail.com>
|
||||||
Aram Hăvărneanu <aram@mgk.ro>
|
Aram Hăvărneanu <aram@mgk.ro>
|
||||||
Arash Bina <arash@arash.io>
|
Arash Bina <arash@arash.io>
|
||||||
|
Arda Güçlü <ardaguclu@gmail.com>
|
||||||
Areski Belaid <areski@gmail.com>
|
Areski Belaid <areski@gmail.com>
|
||||||
Ariel Mashraki <ariel@mashraki.co.il>
|
Ariel Mashraki <ariel@mashraki.co.il>
|
||||||
Arkadi Pyuro <arkadi@google.com>
|
Arkadi Pyuro <arkadi@google.com>
|
||||||
|
|
@ -239,6 +254,7 @@ Arnaud Ysmal <arnaud.ysmal@gmail.com>
|
||||||
Arne Hormann <arnehormann@gmail.com>
|
Arne Hormann <arnehormann@gmail.com>
|
||||||
Arnout Engelen <arnout@bzzt.net>
|
Arnout Engelen <arnout@bzzt.net>
|
||||||
Aron Nopanen <aron.nopanen@gmail.com>
|
Aron Nopanen <aron.nopanen@gmail.com>
|
||||||
|
Artem Alekseev <artem.alekseev@intel.com>
|
||||||
Artem Kolin <artemkaxboy@gmail.com>
|
Artem Kolin <artemkaxboy@gmail.com>
|
||||||
Arthur Fabre <arthur@arthurfabre.com>
|
Arthur Fabre <arthur@arthurfabre.com>
|
||||||
Arthur Khashaev <arthur@khashaev.ru>
|
Arthur Khashaev <arthur@khashaev.ru>
|
||||||
|
|
@ -258,6 +274,7 @@ Avi Flax <avi@timehop.com>
|
||||||
awaw fumin <awawfumin@gmail.com>
|
awaw fumin <awawfumin@gmail.com>
|
||||||
Awn Umar <awn@cryptolosophy.io>
|
Awn Umar <awn@cryptolosophy.io>
|
||||||
Axel Wagner <axel.wagner.hh@googlemail.com>
|
Axel Wagner <axel.wagner.hh@googlemail.com>
|
||||||
|
Ayan George <ayan@ayan.net>
|
||||||
Ayanamist Yang <ayanamist@gmail.com>
|
Ayanamist Yang <ayanamist@gmail.com>
|
||||||
Aymerick Jéhanne <aymerick@jehanne.org>
|
Aymerick Jéhanne <aymerick@jehanne.org>
|
||||||
Azat Kaumov <kaumov.a.r@gmail.com>
|
Azat Kaumov <kaumov.a.r@gmail.com>
|
||||||
|
|
@ -265,6 +282,7 @@ Baiju Muthukadan <baiju.m.mail@gmail.com>
|
||||||
Balaram Makam <bmakam.qdt@qualcommdatacenter.com>
|
Balaram Makam <bmakam.qdt@qualcommdatacenter.com>
|
||||||
Balazs Lecz <leczb@google.com>
|
Balazs Lecz <leczb@google.com>
|
||||||
Baokun Lee <nototon@gmail.com>
|
Baokun Lee <nototon@gmail.com>
|
||||||
|
Barnaby Keene <accounts@southcla.ws>
|
||||||
Bartosz Grzybowski <melkorm@gmail.com>
|
Bartosz Grzybowski <melkorm@gmail.com>
|
||||||
Bartosz Oler <brtsz@google.com>
|
Bartosz Oler <brtsz@google.com>
|
||||||
Bastian Ike <bastian.ike@gmail.com>
|
Bastian Ike <bastian.ike@gmail.com>
|
||||||
|
|
@ -279,12 +297,14 @@ Ben Lynn <benlynn@gmail.com>
|
||||||
Ben Olive <sionide21@gmail.com>
|
Ben Olive <sionide21@gmail.com>
|
||||||
Ben Schwartz <bemasc@google.com>
|
Ben Schwartz <bemasc@google.com>
|
||||||
Ben Shi <powerman1st@163.com>
|
Ben Shi <powerman1st@163.com>
|
||||||
|
Ben Toews <mastahyeti@gmail.com>
|
||||||
Benjamin Black <b@b3k.us>
|
Benjamin Black <b@b3k.us>
|
||||||
Benjamin Cable <cable.benjamin@gmail.com>
|
Benjamin Cable <cable.benjamin@gmail.com>
|
||||||
Benjamin Hsieh <tanookiben@users.noreply.github.com>
|
Benjamin Hsieh <tanookiben@users.noreply.github.com>
|
||||||
Benjamin Peterson <benjamin@python.org>
|
Benjamin Peterson <benjamin@python.org>
|
||||||
Benjamin Prosnitz <bprosnitz@google.com>
|
Benjamin Prosnitz <bprosnitz@google.com>
|
||||||
Benjamin Wester <bwester@squareup.com>
|
Benjamin Wester <bwester@squareup.com>
|
||||||
|
Benjamin Wuethrich <benjamin.wuethrich@gmail.com>
|
||||||
Benny Siegert <bsiegert@gmail.com>
|
Benny Siegert <bsiegert@gmail.com>
|
||||||
Benoit Sigoure <tsunanet@gmail.com>
|
Benoit Sigoure <tsunanet@gmail.com>
|
||||||
Berengar Lehr <Berengar.Lehr@gmx.de>
|
Berengar Lehr <Berengar.Lehr@gmx.de>
|
||||||
|
|
@ -323,6 +343,7 @@ Brady Catherman <brady@gmail.com>
|
||||||
Brady Sullivan <brady@bsull.com>
|
Brady Sullivan <brady@bsull.com>
|
||||||
Brandon Bennett <bbennett@fb.com>
|
Brandon Bennett <bbennett@fb.com>
|
||||||
Brandon Gilmore <varz@google.com>
|
Brandon Gilmore <varz@google.com>
|
||||||
|
Brandon Philips <brandon@ifup.org>
|
||||||
Brandon Ryan <bjryan19@gmail.com>
|
Brandon Ryan <bjryan19@gmail.com>
|
||||||
Brendan Daniel Tracey <tracey.brendan@gmail.com>
|
Brendan Daniel Tracey <tracey.brendan@gmail.com>
|
||||||
Brendan O'Dea <bod@golang.org>
|
Brendan O'Dea <bod@golang.org>
|
||||||
|
|
@ -357,6 +378,7 @@ Carl Mastrangelo <notcarl@google.com>
|
||||||
Carl Shapiro <cshapiro@google.com> <cshapiro@golang.org>
|
Carl Shapiro <cshapiro@google.com> <cshapiro@golang.org>
|
||||||
Carlisia Campos <carlisia@grokkingtech.io>
|
Carlisia Campos <carlisia@grokkingtech.io>
|
||||||
Carlo Alberto Ferraris <cafxx@strayorange.com>
|
Carlo Alberto Ferraris <cafxx@strayorange.com>
|
||||||
|
Carlos Amedee <carlos@golang.org>
|
||||||
Carlos Castillo <cookieo9@gmail.com>
|
Carlos Castillo <cookieo9@gmail.com>
|
||||||
Carlos Cirello <uldericofilho@gmail.com>
|
Carlos Cirello <uldericofilho@gmail.com>
|
||||||
Carlos Eduardo <me@carlosedp.com>
|
Carlos Eduardo <me@carlosedp.com>
|
||||||
|
|
@ -374,12 +396,14 @@ Cedric Staub <cs@squareup.com>
|
||||||
Cezar Sá Espinola <cezarsa@gmail.com>
|
Cezar Sá Espinola <cezarsa@gmail.com>
|
||||||
Chad Rosier <mrosier.qdt@qualcommdatacenter.com>
|
Chad Rosier <mrosier.qdt@qualcommdatacenter.com>
|
||||||
ChaiShushan <chaishushan@gmail.com>
|
ChaiShushan <chaishushan@gmail.com>
|
||||||
|
Changkun Ou <hi@changkun.us>
|
||||||
Channing Kimble-Brown <channing@golang.org>
|
Channing Kimble-Brown <channing@golang.org>
|
||||||
Charles Fenwick Elliott <Charles@FenwickElliott.io>
|
Charles Fenwick Elliott <Charles@FenwickElliott.io>
|
||||||
Charles Kenney <charlesc.kenney@gmail.com>
|
Charles Kenney <charlesc.kenney@gmail.com>
|
||||||
Charles L. Dorian <cldorian@gmail.com>
|
Charles L. Dorian <cldorian@gmail.com>
|
||||||
Charles Lee <zombie.fml@gmail.com>
|
Charles Lee <zombie.fml@gmail.com>
|
||||||
Charles Weill <weill@google.com>
|
Charles Weill <weill@google.com>
|
||||||
|
Chauncy Cullitan <chauncyc@google.com>
|
||||||
Cherry Zhang <cherryyz@google.com>
|
Cherry Zhang <cherryyz@google.com>
|
||||||
Chew Choon Keat <choonkeat@gmail.com>
|
Chew Choon Keat <choonkeat@gmail.com>
|
||||||
Cholerae Hu <choleraehyq@gmail.com>
|
Cholerae Hu <choleraehyq@gmail.com>
|
||||||
|
|
@ -428,6 +452,7 @@ Christy Perez <christy@linux.vnet.ibm.com>
|
||||||
CL Sung <clsung@gmail.com> <cl_sung@htc.com>
|
CL Sung <clsung@gmail.com> <cl_sung@htc.com>
|
||||||
Clément Chigot <clement.chigot@atos.net>
|
Clément Chigot <clement.chigot@atos.net>
|
||||||
Clement Skau <clementskau@gmail.com>
|
Clement Skau <clementskau@gmail.com>
|
||||||
|
Clint J. Edwards <clint.j.edwards@gmail.com>
|
||||||
Cody Oss <the.cody.oss@gmail.com>
|
Cody Oss <the.cody.oss@gmail.com>
|
||||||
Colby Ranger <cranger@google.com>
|
Colby Ranger <cranger@google.com>
|
||||||
Colin Arnott <colin@urandom.co.uk>
|
Colin Arnott <colin@urandom.co.uk>
|
||||||
|
|
@ -448,6 +473,7 @@ Cristian Staretu <unclejacksons@gmail.com>
|
||||||
Cuihtlauac ALVARADO <cuihtlauac.alvarado@orange.com>
|
Cuihtlauac ALVARADO <cuihtlauac.alvarado@orange.com>
|
||||||
Cyrill Schumacher <cyrill@schumacher.fm>
|
Cyrill Schumacher <cyrill@schumacher.fm>
|
||||||
Daisuke Fujita <dtanshi45@gmail.com>
|
Daisuke Fujita <dtanshi45@gmail.com>
|
||||||
|
Daisuke Suzuki <daisuzu@gmail.com>
|
||||||
Daker Fernandes Pinheiro <daker.fernandes.pinheiro@intel.com>
|
Daker Fernandes Pinheiro <daker.fernandes.pinheiro@intel.com>
|
||||||
Damian Gryski <dgryski@gmail.com>
|
Damian Gryski <dgryski@gmail.com>
|
||||||
Damien Lespiau <damien.lespiau@gmail.com> <damien.lespiau@intel.com>
|
Damien Lespiau <damien.lespiau@gmail.com> <damien.lespiau@intel.com>
|
||||||
|
|
@ -462,6 +488,7 @@ Dan Jacques <dnj@google.com>
|
||||||
Dan Johnson <computerdruid@google.com>
|
Dan Johnson <computerdruid@google.com>
|
||||||
Dan Peterson <dpiddy@gmail.com>
|
Dan Peterson <dpiddy@gmail.com>
|
||||||
Dan Pupius <dan@medium.com>
|
Dan Pupius <dan@medium.com>
|
||||||
|
Dan Scales <danscales@google.com>
|
||||||
Dan Sinclair <dan.sinclair@gmail.com>
|
Dan Sinclair <dan.sinclair@gmail.com>
|
||||||
Daniel Cormier <danielc@knowbe4.com>
|
Daniel Cormier <danielc@knowbe4.com>
|
||||||
Daniël de Kok <me@danieldk.eu>
|
Daniël de Kok <me@danieldk.eu>
|
||||||
|
|
@ -501,6 +528,7 @@ Dave Russell <forfuncsake@gmail.com>
|
||||||
David Anderson <danderson@google.com>
|
David Anderson <danderson@google.com>
|
||||||
David Barnett <dbarnett@google.com>
|
David Barnett <dbarnett@google.com>
|
||||||
David Benjamin <davidben@google.com>
|
David Benjamin <davidben@google.com>
|
||||||
|
David Bond <davidsbond93@gmail.com>
|
||||||
David Brophy <dave@brophy.uk>
|
David Brophy <dave@brophy.uk>
|
||||||
David Bürgin <676c7473@gmail.com>
|
David Bürgin <676c7473@gmail.com>
|
||||||
David Calavera <david.calavera@gmail.com>
|
David Calavera <david.calavera@gmail.com>
|
||||||
|
|
@ -541,6 +569,7 @@ Dean Prichard <dean.prichard@gmail.com>
|
||||||
Deepak Jois <deepak.jois@gmail.com>
|
Deepak Jois <deepak.jois@gmail.com>
|
||||||
Denis Bernard <db047h@gmail.com>
|
Denis Bernard <db047h@gmail.com>
|
||||||
Denis Brandolini <denis.brandolini@gmail.com>
|
Denis Brandolini <denis.brandolini@gmail.com>
|
||||||
|
Denis Isaev <idenx@yandex.com>
|
||||||
Denis Nagorny <denis.nagorny@intel.com>
|
Denis Nagorny <denis.nagorny@intel.com>
|
||||||
Dennis Kuhnert <mail.kuhnert@gmail.com>
|
Dennis Kuhnert <mail.kuhnert@gmail.com>
|
||||||
Denys Honsiorovskyi <honsiorovskyi@gmail.com>
|
Denys Honsiorovskyi <honsiorovskyi@gmail.com>
|
||||||
|
|
@ -581,6 +610,7 @@ Dmitry Mottl <dmitry.mottl@gmail.com>
|
||||||
Dmitry Neverov <dmitry.neverov@gmail.com>
|
Dmitry Neverov <dmitry.neverov@gmail.com>
|
||||||
Dmitry Savintsev <dsavints@gmail.com>
|
Dmitry Savintsev <dsavints@gmail.com>
|
||||||
Dmitry Yakunin <nonamezeil@gmail.com>
|
Dmitry Yakunin <nonamezeil@gmail.com>
|
||||||
|
Domas Tamašauskas <puerdomus@gmail.com>
|
||||||
Domen Ipavec <domen@ipavec.net>
|
Domen Ipavec <domen@ipavec.net>
|
||||||
Dominic Green <dominicgreen1@gmail.com>
|
Dominic Green <dominicgreen1@gmail.com>
|
||||||
Dominik Honnef <dominik.honnef@gmail.com>
|
Dominik Honnef <dominik.honnef@gmail.com>
|
||||||
|
|
@ -594,6 +624,7 @@ Doug Fawley <dfawley@google.com>
|
||||||
Douglas Danger Manley <doug.manley@gmail.com>
|
Douglas Danger Manley <doug.manley@gmail.com>
|
||||||
Drew Flower <drewvanstone@gmail.com>
|
Drew Flower <drewvanstone@gmail.com>
|
||||||
Drew Hintz <adhintz@google.com>
|
Drew Hintz <adhintz@google.com>
|
||||||
|
Duco van Amstel <duco.vanamstel@gmail.com>
|
||||||
Duncan Holm <mail@frou.org>
|
Duncan Holm <mail@frou.org>
|
||||||
Dustin Carlino <dcarlino@google.com>
|
Dustin Carlino <dcarlino@google.com>
|
||||||
Dustin Herbison <djherbis@gmail.com>
|
Dustin Herbison <djherbis@gmail.com>
|
||||||
|
|
@ -607,6 +638,7 @@ Eddie Scholtz <escholtz@google.com>
|
||||||
Eden Li <eden.li@gmail.com>
|
Eden Li <eden.li@gmail.com>
|
||||||
Eduard Urbach <e.urbach@gmail.com>
|
Eduard Urbach <e.urbach@gmail.com>
|
||||||
Eduardo Ramalho <eduardo.ramalho@gmail.com>
|
Eduardo Ramalho <eduardo.ramalho@gmail.com>
|
||||||
|
Eduardo Villaseñor <evillasrmx@gmail.com>
|
||||||
Edward Muller <edwardam@interlix.com>
|
Edward Muller <edwardam@interlix.com>
|
||||||
Egon Elbre <egonelbre@gmail.com>
|
Egon Elbre <egonelbre@gmail.com>
|
||||||
Ehren Kret <ehren.kret@gmail.com>
|
Ehren Kret <ehren.kret@gmail.com>
|
||||||
|
|
@ -625,6 +657,8 @@ Emilien Kenler <hello@emilienkenler.com>
|
||||||
Emmanuel Odeke <emm.odeke@gmail.com> <odeke@ualberta.ca>
|
Emmanuel Odeke <emm.odeke@gmail.com> <odeke@ualberta.ca>
|
||||||
Eno Compton <enocom@google.com>
|
Eno Compton <enocom@google.com>
|
||||||
Eoghan Sherry <ejsherry@gmail.com>
|
Eoghan Sherry <ejsherry@gmail.com>
|
||||||
|
Eric Biggers <ebiggers@google.com>
|
||||||
|
Eric Brown <browne@vmware.com>
|
||||||
Eric Chiang <eric.chiang.m@gmail.com>
|
Eric Chiang <eric.chiang.m@gmail.com>
|
||||||
Eric Clark <zerohp@gmail.com>
|
Eric Clark <zerohp@gmail.com>
|
||||||
Eric Daniels <eric@erdaniels.com>
|
Eric Daniels <eric@erdaniels.com>
|
||||||
|
|
@ -637,6 +671,7 @@ Eric Pauley <eric@pauley.me>
|
||||||
Eric Ponce <tricokun@gmail.com>
|
Eric Ponce <tricokun@gmail.com>
|
||||||
Eric Rescorla <ekr@rtfm.com>
|
Eric Rescorla <ekr@rtfm.com>
|
||||||
Eric Roshan-Eisner <eric.d.eisner@gmail.com>
|
Eric Roshan-Eisner <eric.d.eisner@gmail.com>
|
||||||
|
Eric Rutherford <erutherford@gmail.com>
|
||||||
Eric Rykwalder <e.rykwalder@gmail.com>
|
Eric Rykwalder <e.rykwalder@gmail.com>
|
||||||
Erik Aigner <aigner.erik@gmail.com>
|
Erik Aigner <aigner.erik@gmail.com>
|
||||||
Erik Dubbelboer <erik@dubbelboer.com>
|
Erik Dubbelboer <erik@dubbelboer.com>
|
||||||
|
|
@ -718,6 +753,7 @@ Gabriel Aszalos <gabriel.aszalos@gmail.com>
|
||||||
Gabriel Guzman <gabe.guzman@gmail.com>
|
Gabriel Guzman <gabe.guzman@gmail.com>
|
||||||
Gabriel Nelle <tehsphinx@web.de>
|
Gabriel Nelle <tehsphinx@web.de>
|
||||||
Gabriel Nicolas Avellaneda <avellaneda.gabriel@gmail.com>
|
Gabriel Nicolas Avellaneda <avellaneda.gabriel@gmail.com>
|
||||||
|
Gabriel Rosenhouse <rosenhouse@gmail.com>
|
||||||
Gabriel Russell <gabriel.russell@gmail.com>
|
Gabriel Russell <gabriel.russell@gmail.com>
|
||||||
Gareth Paul Jones <gpj@foursquare.com>
|
Gareth Paul Jones <gpj@foursquare.com>
|
||||||
Garret Kelly <gdk@google.com>
|
Garret Kelly <gdk@google.com>
|
||||||
|
|
@ -735,18 +771,23 @@ Geoffroy Lorieux <lorieux.g@gmail.com>
|
||||||
Geon Kim <geon0250@gmail.com>
|
Geon Kim <geon0250@gmail.com>
|
||||||
Georg Reinke <guelfey@gmail.com>
|
Georg Reinke <guelfey@gmail.com>
|
||||||
George Gkirtsou <ggirtsou@gmail.com>
|
George Gkirtsou <ggirtsou@gmail.com>
|
||||||
|
George Hartzell <hartzell@alerce.com>
|
||||||
George Shammas <george@shamm.as> <georgyo@gmail.com>
|
George Shammas <george@shamm.as> <georgyo@gmail.com>
|
||||||
Gerasimos (Makis) Maropoulos <kataras2006@hotmail.com>
|
Gerasimos (Makis) Maropoulos <kataras2006@hotmail.com>
|
||||||
Gerasimos Dimitriadis <gedimitr@gmail.com>
|
Gerasimos Dimitriadis <gedimitr@gmail.com>
|
||||||
Gergely Brautigam <skarlso777@gmail.com>
|
Gergely Brautigam <skarlso777@gmail.com>
|
||||||
Gernot Vormayr <gvormayr@gmail.com>
|
Gernot Vormayr <gvormayr@gmail.com>
|
||||||
|
Gert Cuykens <gert.cuykens@gmail.com>
|
||||||
Getulio Sánchez <valentin2507@gmail.com>
|
Getulio Sánchez <valentin2507@gmail.com>
|
||||||
|
Ghazni Nattarshah <ghazni.nattarshah@gmail.com>
|
||||||
Gianguido Sora` <g.sora4@gmail.com>
|
Gianguido Sora` <g.sora4@gmail.com>
|
||||||
Gideon Jan-Wessel Redelinghuys <gjredelinghuys@gmail.com>
|
Gideon Jan-Wessel Redelinghuys <gjredelinghuys@gmail.com>
|
||||||
Giles Lean <giles.lean@pobox.com>
|
Giles Lean <giles.lean@pobox.com>
|
||||||
Giovanni Bajo <rasky@develer.com>
|
Giovanni Bajo <rasky@develer.com>
|
||||||
GitHub User @ajnirp (1688456) <ajnirp@users.noreply.github.com>
|
GitHub User @ajnirp (1688456) <ajnirp@users.noreply.github.com>
|
||||||
|
GitHub User @ajz01 (4744634) <ajzdenek@gmail.com>
|
||||||
GitHub User @alkesh26 (1019076) <alkesh26@gmail.com>
|
GitHub User @alkesh26 (1019076) <alkesh26@gmail.com>
|
||||||
|
GitHub User @andig (184815) <cpuidle@gmx.de>
|
||||||
GitHub User @andrius4669 (4699695) <andrius4669@gmail.com>
|
GitHub User @andrius4669 (4699695) <andrius4669@gmail.com>
|
||||||
GitHub User @as (8127015) <as.utf8@gmail.com>
|
GitHub User @as (8127015) <as.utf8@gmail.com>
|
||||||
GitHub User @bakape (7851952) <bakape@gmail.com>
|
GitHub User @bakape (7851952) <bakape@gmail.com>
|
||||||
|
|
@ -754,31 +795,41 @@ GitHub User @bgadrian (830001) <aditza8@gmail.com>
|
||||||
GitHub User @bontequero (2674999) <bontequero@gmail.com>
|
GitHub User @bontequero (2674999) <bontequero@gmail.com>
|
||||||
GitHub User @cch123 (384546) <buaa.cch@gmail.com>
|
GitHub User @cch123 (384546) <buaa.cch@gmail.com>
|
||||||
GitHub User @chanxuehong (3416908) <chanxuehong@gmail.com>
|
GitHub User @chanxuehong (3416908) <chanxuehong@gmail.com>
|
||||||
|
GitHub User @DQNEO (188741) <dqneoo@gmail.com>
|
||||||
GitHub User @dupoxy (1143957) <dupoxy@users.noreply.github.com>
|
GitHub User @dupoxy (1143957) <dupoxy@users.noreply.github.com>
|
||||||
GitHub User @erifan (31343225) <eric.fang@arm.com>
|
GitHub User @erifan (31343225) <eric.fang@arm.com>
|
||||||
GitHub User @esell (9735165) <eujon.sellers@gmail.com>
|
GitHub User @esell (9735165) <eujon.sellers@gmail.com>
|
||||||
GitHub User @frennkie (6499251) <mail@rhab.de>
|
GitHub User @frennkie (6499251) <mail@rhab.de>
|
||||||
GitHub User @hengwu0 (41297446) <41297446+hengwu0@users.noreply.github.com>
|
GitHub User @hengwu0 (41297446) <41297446+hengwu0@users.noreply.github.com>
|
||||||
GitHub User @itchyny (375258) <itchyny@hatena.ne.jp>
|
GitHub User @itchyny (375258) <itchyny@hatena.ne.jp>
|
||||||
|
GitHub User @jinmiaoluo (39730824) <jinmiaoluo@icloud.com>
|
||||||
GitHub User @kazyshr (30496953) <kazyshr0301@gmail.com>
|
GitHub User @kazyshr (30496953) <kazyshr0301@gmail.com>
|
||||||
GitHub User @kc1212 (1093806) <kc1212@users.noreply.github.com>
|
GitHub User @kc1212 (1093806) <kc1212@users.noreply.github.com>
|
||||||
GitHub User @Kropekk (13366453) <kamilkropiewnicki@gmail.com>
|
GitHub User @Kropekk (13366453) <kamilkropiewnicki@gmail.com>
|
||||||
GitHub User @linguohua (3434367) <lghchinaidea@gmail.com>
|
GitHub User @linguohua (3434367) <lghchinaidea@gmail.com>
|
||||||
GitHub User @LotusFenn (13775899) <fenn.lotus@gmail.com>
|
GitHub User @LotusFenn (13775899) <fenn.lotus@gmail.com>
|
||||||
GitHub User @madiganz (18340029) <zacharywmadigan@gmail.com>
|
GitHub User @madiganz (18340029) <zacharywmadigan@gmail.com>
|
||||||
|
GitHub User @maltalex (10195391) <code@bit48.net>
|
||||||
|
GitHub User @Matts966 (28551465) <Matts966@users.noreply.github.com>
|
||||||
GitHub User @micnncim (21333876) <micnncim@gmail.com>
|
GitHub User @micnncim (21333876) <micnncim@gmail.com>
|
||||||
GitHub User @mkishere (224617) <224617+mkishere@users.noreply.github.com>
|
GitHub User @mkishere (224617) <224617+mkishere@users.noreply.github.com>
|
||||||
GitHub User @OlgaVlPetrova (44112727) <OVPpetrova@gmail.com>
|
GitHub User @OlgaVlPetrova (44112727) <OVPpetrova@gmail.com>
|
||||||
GitHub User @pityonline (438222) <pityonline@gmail.com>
|
GitHub User @pityonline (438222) <pityonline@gmail.com>
|
||||||
|
GitHub User @po3rin (29445112) <abctail30@gmail.com>
|
||||||
|
GitHub User @pokutuna (57545) <popopopopokutuna@gmail.com>
|
||||||
GitHub User @pytimer (17105586) <lixin20101023@gmail.com>
|
GitHub User @pytimer (17105586) <lixin20101023@gmail.com>
|
||||||
|
GitHub User @ramenjuniti (32011829) <ramenjuniti@gmail.com>
|
||||||
GitHub User @saitarunreddy (21041941) <saitarunreddypalla@gmail.com>
|
GitHub User @saitarunreddy (21041941) <saitarunreddypalla@gmail.com>
|
||||||
GitHub User @shogo-ma (9860598) <Choroma194@gmail.com>
|
GitHub User @shogo-ma (9860598) <Choroma194@gmail.com>
|
||||||
|
GitHub User @skanehira (7888591) <sho19921005@gmail.com>
|
||||||
GitHub User @tatsumack (4510569) <tatsu.mack@gmail.com>
|
GitHub User @tatsumack (4510569) <tatsu.mack@gmail.com>
|
||||||
GitHub User @tell-k (26263) <ffk2005@gmail.com>
|
GitHub User @tell-k (26263) <ffk2005@gmail.com>
|
||||||
GitHub User @uhei (2116845) <uhei@users.noreply.github.com>
|
GitHub User @uhei (2116845) <uhei@users.noreply.github.com>
|
||||||
GitHub User @uropek (39370426) <uropek@gmail.com>
|
GitHub User @uropek (39370426) <uropek@gmail.com>
|
||||||
GitHub User @utkarsh-extc (53217283) <utkarsh.extc@gmail.com>
|
GitHub User @utkarsh-extc (53217283) <utkarsh.extc@gmail.com>
|
||||||
|
GitHub User @witchard (4994659) <witchard@hotmail.co.uk>
|
||||||
GitHub User @yuanhh (1298735) <yuan415030@gmail.com>
|
GitHub User @yuanhh (1298735) <yuan415030@gmail.com>
|
||||||
|
GitHub User @zikaeroh (48577114) <zikaeroh@gmail.com>
|
||||||
GitHub User @ZZMarquis (7624583) <zhonglingjian3821@163.com>
|
GitHub User @ZZMarquis (7624583) <zhonglingjian3821@163.com>
|
||||||
Giulio Iotti <dullgiulio@gmail.com>
|
Giulio Iotti <dullgiulio@gmail.com>
|
||||||
Giulio Micheloni <giulio.micheloni@gmail.com>
|
Giulio Micheloni <giulio.micheloni@gmail.com>
|
||||||
|
|
@ -802,6 +853,7 @@ Guilherme Garnier <guilherme.garnier@gmail.com>
|
||||||
Guilherme Goncalves <guilhermeaugustosg@gmail.com>
|
Guilherme Goncalves <guilhermeaugustosg@gmail.com>
|
||||||
Guilherme Rezende <guilhermebr@gmail.com>
|
Guilherme Rezende <guilhermebr@gmail.com>
|
||||||
Guillaume J. Charmes <guillaume@charmes.net>
|
Guillaume J. Charmes <guillaume@charmes.net>
|
||||||
|
Günther Noack <gnoack@google.com>
|
||||||
Guobiao Mei <meiguobiao@gmail.com>
|
Guobiao Mei <meiguobiao@gmail.com>
|
||||||
Guoliang Wang <iamwgliang@gmail.com>
|
Guoliang Wang <iamwgliang@gmail.com>
|
||||||
Gustav Paul <gustav.paul@gmail.com>
|
Gustav Paul <gustav.paul@gmail.com>
|
||||||
|
|
@ -825,6 +877,7 @@ Harley Laue <losinggeneration@gmail.com>
|
||||||
Harry Moreno <morenoh149@gmail.com>
|
Harry Moreno <morenoh149@gmail.com>
|
||||||
Harshavardhana <hrshvardhana@gmail.com>
|
Harshavardhana <hrshvardhana@gmail.com>
|
||||||
Hasan Ozgan <hasan@ozgan.net>
|
Hasan Ozgan <hasan@ozgan.net>
|
||||||
|
Hasit Bhatt <hasit.p.bhatt@gmail.com>
|
||||||
Hauke Löffler <hloeffler@users.noreply.github.com>
|
Hauke Löffler <hloeffler@users.noreply.github.com>
|
||||||
Håvard Haugen <havard.haugen@gmail.com>
|
Håvard Haugen <havard.haugen@gmail.com>
|
||||||
He Liu <liulonnie@gmail.com>
|
He Liu <liulonnie@gmail.com>
|
||||||
|
|
@ -852,9 +905,11 @@ Hong Ruiqi <hongruiqi@gmail.com>
|
||||||
Hongfei Tan <feilengcui008@gmail.com>
|
Hongfei Tan <feilengcui008@gmail.com>
|
||||||
Horst Rutter <hhrutter@gmail.com>
|
Horst Rutter <hhrutter@gmail.com>
|
||||||
Hossein Sheikh Attar <hattar@google.com>
|
Hossein Sheikh Attar <hattar@google.com>
|
||||||
|
Howard Zhang <howard.zhang@arm.com>
|
||||||
Hsin Tsao <tsao@google.com>
|
Hsin Tsao <tsao@google.com>
|
||||||
Hsin-Ho Yeh <yhh92u@gmail.com>
|
Hsin-Ho Yeh <yhh92u@gmail.com>
|
||||||
Hu Keping <hukeping@huawei.com>
|
Hu Keping <hukeping@huawei.com>
|
||||||
|
Huan Du <i@huandu.me>
|
||||||
Hugues Bruant <hugues.bruant@gmail.com>
|
Hugues Bruant <hugues.bruant@gmail.com>
|
||||||
Huy Le <huy.dinh.le.89@gmail.com>
|
Huy Le <huy.dinh.le.89@gmail.com>
|
||||||
Hyang-Ah Hana Kim <hakim@google.com> <hyangah@gmail.com>
|
Hyang-Ah Hana Kim <hakim@google.com> <hyangah@gmail.com>
|
||||||
|
|
@ -870,11 +925,13 @@ Ibrahim AshShohail <ibra.sho@gmail.com>
|
||||||
Icarus Sparry <golang@icarus.freeuk.com>
|
Icarus Sparry <golang@icarus.freeuk.com>
|
||||||
Iccha Sethi <icchasethi@gmail.com>
|
Iccha Sethi <icchasethi@gmail.com>
|
||||||
Idora Shinatose <idora.shinatose@gmail.com>
|
Idora Shinatose <idora.shinatose@gmail.com>
|
||||||
|
Ignacio Hagopian <jsign.uy@gmail.com>
|
||||||
Igor Bernstein <igorbernstein@google.com>
|
Igor Bernstein <igorbernstein@google.com>
|
||||||
Igor Dolzhikov <bluesriverz@gmail.com>
|
Igor Dolzhikov <bluesriverz@gmail.com>
|
||||||
Igor Vashyst <ivashyst@gmail.com>
|
Igor Vashyst <ivashyst@gmail.com>
|
||||||
Igor Zhilianin <igor.zhilianin@gmail.com>
|
Igor Zhilianin <igor.zhilianin@gmail.com>
|
||||||
Illya Yalovyy <yalovoy@gmail.com>
|
Illya Yalovyy <yalovoy@gmail.com>
|
||||||
|
Ilya Sinelnikov <sidhmangh@gmail.com>
|
||||||
Ilya Tocar <ilya.tocar@intel.com>
|
Ilya Tocar <ilya.tocar@intel.com>
|
||||||
INADA Naoki <songofacandy@gmail.com>
|
INADA Naoki <songofacandy@gmail.com>
|
||||||
Inanc Gumus <m@inanc.io>
|
Inanc Gumus <m@inanc.io>
|
||||||
|
|
@ -882,10 +939,12 @@ Ingo Gottwald <in.gottwald@gmail.com>
|
||||||
Ingo Krabbe <ikrabbe.ask@gmail.com>
|
Ingo Krabbe <ikrabbe.ask@gmail.com>
|
||||||
Ingo Oeser <nightlyone@googlemail.com> <nightlyone@gmail.com>
|
Ingo Oeser <nightlyone@googlemail.com> <nightlyone@gmail.com>
|
||||||
Ioannis Georgoulas <geototti21@hotmail.com>
|
Ioannis Georgoulas <geototti21@hotmail.com>
|
||||||
|
Irbe Krumina <irbekrm@gmail.com>
|
||||||
Irfan Sharif <irfanmahmoudsharif@gmail.com>
|
Irfan Sharif <irfanmahmoudsharif@gmail.com>
|
||||||
Irieda Noboru <irieda@gmail.com>
|
Irieda Noboru <irieda@gmail.com>
|
||||||
Isaac Ardis <isaac.ardis@gmail.com>
|
Isaac Ardis <isaac.ardis@gmail.com>
|
||||||
Isaac Wagner <ibw@isaacwagner.me>
|
Isaac Wagner <ibw@isaacwagner.me>
|
||||||
|
Isfan Azhabil <isfan.azhabil@tokopedia.com>
|
||||||
Iskander Sharipov <iskander.sharipov@intel.com> <quasilyte@gmail.com>
|
Iskander Sharipov <iskander.sharipov@intel.com> <quasilyte@gmail.com>
|
||||||
Issac Trotts <issactrotts@google.com>
|
Issac Trotts <issactrotts@google.com>
|
||||||
Ivan Babrou <ivan@cloudflare.com>
|
Ivan Babrou <ivan@cloudflare.com>
|
||||||
|
|
@ -896,9 +955,11 @@ Ivan Markin <sw@nogoegst.net>
|
||||||
Ivan Moscoso <moscoso@gmail.com>
|
Ivan Moscoso <moscoso@gmail.com>
|
||||||
Ivan Osadchiy <ivan.osadchii@gmail.com>
|
Ivan Osadchiy <ivan.osadchii@gmail.com>
|
||||||
Ivan Sharavuev <shpiwan@gmail.com>
|
Ivan Sharavuev <shpiwan@gmail.com>
|
||||||
|
Ivan Trubach <mr.trubach@icloud.com>
|
||||||
Ivan Ukhov <ivan.ukhov@gmail.com>
|
Ivan Ukhov <ivan.ukhov@gmail.com>
|
||||||
Ivy Evans <ivy@ivyevans.net>
|
Ivy Evans <ivy@ivyevans.net>
|
||||||
Jaana Burcu Dogan <jbd@google.com> <jbd@golang.org> <burcujdogan@gmail.com>
|
Jaana Burcu Dogan <jbd@google.com> <jbd@golang.org> <burcujdogan@gmail.com>
|
||||||
|
Jaap Aarts <jaap.aarts1@gmail.com>
|
||||||
Jack Britton <jackxbritton@gmail.com>
|
Jack Britton <jackxbritton@gmail.com>
|
||||||
Jack Lindamood <jlindamo@justin.tv>
|
Jack Lindamood <jlindamo@justin.tv>
|
||||||
Jacob Baskin <jbaskin@google.com>
|
Jacob Baskin <jbaskin@google.com>
|
||||||
|
|
@ -982,6 +1043,7 @@ Jean-Francois Cantin <jfcantin@gmail.com>
|
||||||
Jean-Marc Eurin <jmeurin@google.com>
|
Jean-Marc Eurin <jmeurin@google.com>
|
||||||
Jean-Nicolas Moal <jn.moal@gmail.com>
|
Jean-Nicolas Moal <jn.moal@gmail.com>
|
||||||
Jed Denlea <jed@fastly.com>
|
Jed Denlea <jed@fastly.com>
|
||||||
|
Jędrzej Szczepaniak <jbszczepaniak@gmail.com>
|
||||||
Jeet Parekh <jeetparekh96@gmail.com>
|
Jeet Parekh <jeetparekh96@gmail.com>
|
||||||
Jeevanandam M <jeeva@myjeeva.com>
|
Jeevanandam M <jeeva@myjeeva.com>
|
||||||
Jeff (Zhefu) Jiang <jeffjiang@google.com>
|
Jeff (Zhefu) Jiang <jeffjiang@google.com>
|
||||||
|
|
@ -998,6 +1060,7 @@ Jens Frederich <jfrederich@gmail.com>
|
||||||
Jeremiah Harmsen <jeremiah@google.com>
|
Jeremiah Harmsen <jeremiah@google.com>
|
||||||
Jeremy Banks <_@jeremy.ca>
|
Jeremy Banks <_@jeremy.ca>
|
||||||
Jeremy Canady <jcanady@gmail.com>
|
Jeremy Canady <jcanady@gmail.com>
|
||||||
|
Jeremy Faller <jeremy@golang.org>
|
||||||
Jeremy Jackins <jeremyjackins@gmail.com>
|
Jeremy Jackins <jeremyjackins@gmail.com>
|
||||||
Jeremy Jay <jeremy@pbnjay.com>
|
Jeremy Jay <jeremy@pbnjay.com>
|
||||||
Jeremy Schlatter <jeremy.schlatter@gmail.com>
|
Jeremy Schlatter <jeremy.schlatter@gmail.com>
|
||||||
|
|
@ -1042,6 +1105,7 @@ Joel Stemmer <stemmertech@gmail.com>
|
||||||
Joey Geiger <jgeiger@users.noreply.github.com>
|
Joey Geiger <jgeiger@users.noreply.github.com>
|
||||||
Johan Brandhorst <johan.brandhorst@gmail.com>
|
Johan Brandhorst <johan.brandhorst@gmail.com>
|
||||||
Johan Euphrosine <proppy@google.com>
|
Johan Euphrosine <proppy@google.com>
|
||||||
|
Johan Jansson <johan.jansson@iki.fi>
|
||||||
Johan Sageryd <j@1616.se>
|
Johan Sageryd <j@1616.se>
|
||||||
John Asmuth <jasmuth@gmail.com>
|
John Asmuth <jasmuth@gmail.com>
|
||||||
John Beisley <huin@google.com>
|
John Beisley <huin@google.com>
|
||||||
|
|
@ -1057,6 +1121,7 @@ John Jenkins <twodopeshaggy@gmail.com>
|
||||||
John Leidegren <john.leidegren@gmail.com>
|
John Leidegren <john.leidegren@gmail.com>
|
||||||
John Moore <johnkenneth.moore@gmail.com>
|
John Moore <johnkenneth.moore@gmail.com>
|
||||||
John Newlin <jnewlin@google.com>
|
John Newlin <jnewlin@google.com>
|
||||||
|
John Papandriopoulos <jpap.code@gmail.com>
|
||||||
John Potocny <johnp@vividcortex.com>
|
John Potocny <johnp@vividcortex.com>
|
||||||
John R. Lenton <jlenton@gmail.com>
|
John R. Lenton <jlenton@gmail.com>
|
||||||
John Schnake <schnake.john@gmail.com>
|
John Schnake <schnake.john@gmail.com>
|
||||||
|
|
@ -1090,7 +1155,9 @@ Jordan Liggitt <liggitt@google.com>
|
||||||
Jordan Rhee <jordanrh@microsoft.com>
|
Jordan Rhee <jordanrh@microsoft.com>
|
||||||
Jordi Martin <jordimartin@gmail.com>
|
Jordi Martin <jordimartin@gmail.com>
|
||||||
Jorge Araya <jorgejavieran@yahoo.com.mx>
|
Jorge Araya <jorgejavieran@yahoo.com.mx>
|
||||||
|
Jorge L. Fatta <jorge.fatta@auth0.com>
|
||||||
Jos Visser <josv@google.com>
|
Jos Visser <josv@google.com>
|
||||||
|
Josa Gesell <josa@gesell.me>
|
||||||
Jose Luis Vázquez González <josvazg@gmail.com>
|
Jose Luis Vázquez González <josvazg@gmail.com>
|
||||||
Joseph Bonneau <jcb@google.com>
|
Joseph Bonneau <jcb@google.com>
|
||||||
Joseph Holsten <joseph@josephholsten.com>
|
Joseph Holsten <joseph@josephholsten.com>
|
||||||
|
|
@ -1119,11 +1186,13 @@ Julia Hansbrough <flowerhack@google.com>
|
||||||
Julian Kornberger <jk+github@digineo.de>
|
Julian Kornberger <jk+github@digineo.de>
|
||||||
Julian Pastarmov <pastarmovj@google.com>
|
Julian Pastarmov <pastarmovj@google.com>
|
||||||
Julian Phillips <julian@quantumfyre.co.uk>
|
Julian Phillips <julian@quantumfyre.co.uk>
|
||||||
|
Julian Tibble <julian.tibble@gmail.com>
|
||||||
Julie Qiu <julie@golang.org>
|
Julie Qiu <julie@golang.org>
|
||||||
Julien Kauffmann <julien.kauffmann@freelan.org>
|
Julien Kauffmann <julien.kauffmann@freelan.org>
|
||||||
Julien Salleyron <julien.salleyron@gmail.com>
|
Julien Salleyron <julien.salleyron@gmail.com>
|
||||||
Julien Schmidt <google@julienschmidt.com>
|
Julien Schmidt <google@julienschmidt.com>
|
||||||
Julio Montes <julio.montes@intel.com>
|
Julio Montes <julio.montes@intel.com>
|
||||||
|
Jun Zhang <jim.zoumo@gmail.com>
|
||||||
Junda Liu <junda@celer.network>
|
Junda Liu <junda@celer.network>
|
||||||
Jungho Ahn <jhahn@google.com>
|
Jungho Ahn <jhahn@google.com>
|
||||||
Junya Hayashi <ledmonster@gmail.com>
|
Junya Hayashi <ledmonster@gmail.com>
|
||||||
|
|
@ -1133,12 +1202,12 @@ Justin Gracenin <jgracenin@gmail.com>
|
||||||
Justin Li <git@justinli.net>
|
Justin Li <git@justinli.net>
|
||||||
Justin Nuß <nuss.justin@gmail.com>
|
Justin Nuß <nuss.justin@gmail.com>
|
||||||
Justyn Temme <justyntemme@gmail.com>
|
Justyn Temme <justyntemme@gmail.com>
|
||||||
Kelly Heller <pestophagous@gmail.com>
|
|
||||||
Kai Backman <kaib@golang.org>
|
Kai Backman <kaib@golang.org>
|
||||||
Kai Dong <dokia2357@gmail.com>
|
Kai Dong <dokia2357@gmail.com>
|
||||||
Kai Trukenmüller <ktye78@gmail.com>
|
Kai Trukenmüller <ktye78@gmail.com>
|
||||||
Kale Blankenship <kale@lemnisys.com>
|
Kale Blankenship <kale@lemnisys.com>
|
||||||
Kaleb Elwert <kelwert@atlassian.com>
|
Kaleb Elwert <kelwert@atlassian.com>
|
||||||
|
Kalman Bekesi <kalmanb@google.com>
|
||||||
Kamal Aboul-Hosn <aboulhosn@google.com>
|
Kamal Aboul-Hosn <aboulhosn@google.com>
|
||||||
Kamil Chmielewski <kamil.chm@gmail.com>
|
Kamil Chmielewski <kamil.chm@gmail.com>
|
||||||
Kamil Kisiel <kamil@kamilkisiel.net> <kamil.kisiel@gmail.com>
|
Kamil Kisiel <kamil@kamilkisiel.net> <kamil.kisiel@gmail.com>
|
||||||
|
|
@ -1151,6 +1220,7 @@ Karsten Köhler <karsten.koehler95@gmail.com>
|
||||||
Karthik Nayak <karthik.188@gmail.com>
|
Karthik Nayak <karthik.188@gmail.com>
|
||||||
Kashav Madan <kshvmdn@gmail.com>
|
Kashav Madan <kshvmdn@gmail.com>
|
||||||
Kate Manson <kate.manson@izettle.com>
|
Kate Manson <kate.manson@izettle.com>
|
||||||
|
Katharine Berry <ktbry@google.com>
|
||||||
Katie Hockman <katie@golang.org>
|
Katie Hockman <katie@golang.org>
|
||||||
Kato Kazuyoshi <kato.kazuyoshi@gmail.com>
|
Kato Kazuyoshi <kato.kazuyoshi@gmail.com>
|
||||||
Katrina Owen <katrina.owen@gmail.com>
|
Katrina Owen <katrina.owen@gmail.com>
|
||||||
|
|
@ -1161,9 +1231,11 @@ KB Sriram <kbsriram@google.com>
|
||||||
Keegan Carruthers-Smith <keegan.csmith@gmail.com>
|
Keegan Carruthers-Smith <keegan.csmith@gmail.com>
|
||||||
Kei Son <hey.calmdown@gmail.com>
|
Kei Son <hey.calmdown@gmail.com>
|
||||||
Keiji Yoshida <keijiyoshida.mail@gmail.com>
|
Keiji Yoshida <keijiyoshida.mail@gmail.com>
|
||||||
|
Keisuke Kishimoto <keisuke.kishimoto@gmail.com>
|
||||||
Keith Ball <inflatablewoman@gmail.com>
|
Keith Ball <inflatablewoman@gmail.com>
|
||||||
Keith Randall <khr@golang.org>
|
Keith Randall <khr@golang.org>
|
||||||
Keith Rarick <kr@xph.us>
|
Keith Rarick <kr@xph.us>
|
||||||
|
Kelly Heller <pestophagous@gmail.com>
|
||||||
Kelsey Hightower <kelsey.hightower@gmail.com>
|
Kelsey Hightower <kelsey.hightower@gmail.com>
|
||||||
Kelvin Foo Chuan Lyi <vmirage@gmail.com>
|
Kelvin Foo Chuan Lyi <vmirage@gmail.com>
|
||||||
Ken Friedenbach <kenliz@cruzio.com>
|
Ken Friedenbach <kenliz@cruzio.com>
|
||||||
|
|
@ -1177,6 +1249,7 @@ Kenneth Shaw <kenshaw@gmail.com>
|
||||||
Kenny Grant <kennygrant@gmail.com>
|
Kenny Grant <kennygrant@gmail.com>
|
||||||
Kenta Mori <zoncoen@gmail.com>
|
Kenta Mori <zoncoen@gmail.com>
|
||||||
Ketan Parmar <ketanbparmar@gmail.com>
|
Ketan Parmar <ketanbparmar@gmail.com>
|
||||||
|
Kevan Swanberg <kevswanberg@gmail.com>
|
||||||
Kevin Ballard <kevin@sb.org>
|
Kevin Ballard <kevin@sb.org>
|
||||||
Kevin Burke <kev@inburke.com>
|
Kevin Burke <kev@inburke.com>
|
||||||
Kevin Gillette <extemporalgenome@gmail.com>
|
Kevin Gillette <extemporalgenome@gmail.com>
|
||||||
|
|
@ -1198,9 +1271,11 @@ Klaus Post <klauspost@gmail.com>
|
||||||
Kodie Goodwin <kodiegoodwin@gmail.com>
|
Kodie Goodwin <kodiegoodwin@gmail.com>
|
||||||
Koichi Shiraishi <zchee.io@gmail.com>
|
Koichi Shiraishi <zchee.io@gmail.com>
|
||||||
Koki Ide <niconegoto@yahoo.co.jp>
|
Koki Ide <niconegoto@yahoo.co.jp>
|
||||||
|
Koki Tomoshige <tomocy.dev@gmail.com>
|
||||||
Komu Wairagu <komuw05@gmail.com>
|
Komu Wairagu <komuw05@gmail.com>
|
||||||
Konstantin <konstantin8105@gmail.com>
|
Konstantin <konstantin8105@gmail.com>
|
||||||
Konstantin Shaposhnikov <k.shaposhnikov@gmail.com>
|
Konstantin Shaposhnikov <k.shaposhnikov@gmail.com>
|
||||||
|
Koya IWAMURA <kiwamura0314@gmail.com>
|
||||||
Kris Kwiatkowski <kris@cloudflare.com>
|
Kris Kwiatkowski <kris@cloudflare.com>
|
||||||
Kris Nova <kris@nivenly.com>
|
Kris Nova <kris@nivenly.com>
|
||||||
Kris Rousey <krousey@google.com>
|
Kris Rousey <krousey@google.com>
|
||||||
|
|
@ -1245,8 +1320,10 @@ Leonel Quinteros <leonel.quinteros@gmail.com>
|
||||||
Lev Shamardin <shamardin@gmail.com>
|
Lev Shamardin <shamardin@gmail.com>
|
||||||
Lewin Bormann <lewin.bormann@gmail.com>
|
Lewin Bormann <lewin.bormann@gmail.com>
|
||||||
Lion Yang <lion@aosc.xyz>
|
Lion Yang <lion@aosc.xyz>
|
||||||
|
Liz Rice <liz@lizrice.com>
|
||||||
Lloyd Dewolf <foolswisdom@gmail.com>
|
Lloyd Dewolf <foolswisdom@gmail.com>
|
||||||
Lorenz Bauer <lmb@cloudflare.com>
|
Lorenz Bauer <lmb@cloudflare.com>
|
||||||
|
Lorenz Brun <lorenz@brun.one>
|
||||||
Lorenz Nickel <mail@lorenznickel.de>
|
Lorenz Nickel <mail@lorenznickel.de>
|
||||||
Lorenzo Masini <rugginoso@develer.com>
|
Lorenzo Masini <rugginoso@develer.com>
|
||||||
Lorenzo Stoakes <lstoakes@gmail.com>
|
Lorenzo Stoakes <lstoakes@gmail.com>
|
||||||
|
|
@ -1268,6 +1345,7 @@ Lukasz Milewski <lmmilewski@gmail.com>
|
||||||
Luke Champine <luke.champine@gmail.com>
|
Luke Champine <luke.champine@gmail.com>
|
||||||
Luke Curley <qpingu@gmail.com>
|
Luke Curley <qpingu@gmail.com>
|
||||||
Luke Granger-Brown <git@lukegb.com>
|
Luke Granger-Brown <git@lukegb.com>
|
||||||
|
Luke Young <bored-engineer@users.noreply.github.com>
|
||||||
Luna Duclos <luna.duclos@palmstonegames.com>
|
Luna Duclos <luna.duclos@palmstonegames.com>
|
||||||
Luuk van Dijk <lvd@golang.org> <lvd@google.com>
|
Luuk van Dijk <lvd@golang.org> <lvd@google.com>
|
||||||
Lyle Franklin <lylejfranklin@gmail.com>
|
Lyle Franklin <lylejfranklin@gmail.com>
|
||||||
|
|
@ -1290,6 +1368,7 @@ Manu Garg <manugarg@google.com>
|
||||||
Manu S Ajith <neo@codingarena.in>
|
Manu S Ajith <neo@codingarena.in>
|
||||||
Manuel Mendez <mmendez534@gmail.com>
|
Manuel Mendez <mmendez534@gmail.com>
|
||||||
Marat Khabibullin <marat.khabibullin@jetbrains.com>
|
Marat Khabibullin <marat.khabibullin@jetbrains.com>
|
||||||
|
Marc Sanmiquel <marcsanmiquel@gmail.com>
|
||||||
Marc Weistroff <marc@weistroff.net>
|
Marc Weistroff <marc@weistroff.net>
|
||||||
Marc-Antoine Ruel <maruel@chromium.org>
|
Marc-Antoine Ruel <maruel@chromium.org>
|
||||||
Marcel Edmund Franke <marcel.edmund.franke@gmail.com>
|
Marcel Edmund Franke <marcel.edmund.franke@gmail.com>
|
||||||
|
|
@ -1318,6 +1397,7 @@ Mark Wolfe <mark@wolfe.id.au>
|
||||||
Mark Zavislak <zavislak@google.com>
|
Mark Zavislak <zavislak@google.com>
|
||||||
Marko Juhani Silokunnas <marko.silokunnas@gmail.com>
|
Marko Juhani Silokunnas <marko.silokunnas@gmail.com>
|
||||||
Marko Kevac <marko@kevac.org>
|
Marko Kevac <marko@kevac.org>
|
||||||
|
Marko Kungla <marko.kungla@gmail.com>
|
||||||
Marko Mikulicic <mkm@google.com>
|
Marko Mikulicic <mkm@google.com>
|
||||||
Marko Mudrinic <mudrinic.mare@gmail.com>
|
Marko Mudrinic <mudrinic.mare@gmail.com>
|
||||||
Marko Tiikkaja <marko@joh.to>
|
Marko Tiikkaja <marko@joh.to>
|
||||||
|
|
@ -1473,6 +1553,7 @@ Mike Solomon <msolo@gmail.com>
|
||||||
Mike Strosaker <strosake@us.ibm.com>
|
Mike Strosaker <strosake@us.ibm.com>
|
||||||
Mike Tsao <mike@sowbug.com>
|
Mike Tsao <mike@sowbug.com>
|
||||||
Mike Wiacek <mjwiacek@google.com>
|
Mike Wiacek <mjwiacek@google.com>
|
||||||
|
Mikhail Fesenko <proggga@gmail.com>
|
||||||
Mikhail Gusarov <dottedmag@dottedmag.net>
|
Mikhail Gusarov <dottedmag@dottedmag.net>
|
||||||
Mikhail Panchenko <m@mihasya.com>
|
Mikhail Panchenko <m@mihasya.com>
|
||||||
Miki Tebeka <miki.tebeka@gmail.com>
|
Miki Tebeka <miki.tebeka@gmail.com>
|
||||||
|
|
@ -1488,9 +1569,11 @@ Miroslav Genov <mgenov@gmail.com>
|
||||||
Misty De Meo <mistydemeo@gmail.com>
|
Misty De Meo <mistydemeo@gmail.com>
|
||||||
Mohit Agarwal <mohit@sdf.org>
|
Mohit Agarwal <mohit@sdf.org>
|
||||||
Mohit kumar Bajoria <mohitbajo36@gmail.com>
|
Mohit kumar Bajoria <mohitbajo36@gmail.com>
|
||||||
|
Mohit Verma <vmohit.93@gmail.com>
|
||||||
Momchil Velikov <momchil.velikov@gmail.com>
|
Momchil Velikov <momchil.velikov@gmail.com>
|
||||||
Monis Khan <mkhan@redhat.com>
|
Monis Khan <mkhan@redhat.com>
|
||||||
Monty Taylor <mordred@inaugust.com>
|
Monty Taylor <mordred@inaugust.com>
|
||||||
|
Moritz Fain <moritz@fain.io>
|
||||||
Moriyoshi Koizumi <mozo@mozo.jp>
|
Moriyoshi Koizumi <mozo@mozo.jp>
|
||||||
Morten Siebuhr <sbhr@sbhr.dk>
|
Morten Siebuhr <sbhr@sbhr.dk>
|
||||||
Môshe van der Sterre <moshevds@gmail.com>
|
Môshe van der Sterre <moshevds@gmail.com>
|
||||||
|
|
@ -1507,6 +1590,7 @@ Naoki Kanatani <k12naoki@gmail.com>
|
||||||
Nate Wilkinson <nathanwilk7@gmail.com>
|
Nate Wilkinson <nathanwilk7@gmail.com>
|
||||||
Nathan Cantelmo <n.cantelmo@gmail.com>
|
Nathan Cantelmo <n.cantelmo@gmail.com>
|
||||||
Nathan Caza <mastercactapus@gmail.com>
|
Nathan Caza <mastercactapus@gmail.com>
|
||||||
|
Nathan Dias <nathan.dias@orijtech.com>
|
||||||
Nathan Humphreys <nkhumphreys@gmail.com>
|
Nathan Humphreys <nkhumphreys@gmail.com>
|
||||||
Nathan John Youngman <nj@nathany.com>
|
Nathan John Youngman <nj@nathany.com>
|
||||||
Nathan Otterness <otternes@cs.unc.edu>
|
Nathan Otterness <otternes@cs.unc.edu>
|
||||||
|
|
@ -1551,6 +1635,7 @@ Nigel Tao <nigeltao@golang.org>
|
||||||
Nik Nyby <nnyby@columbia.edu>
|
Nik Nyby <nnyby@columbia.edu>
|
||||||
Nikhil Benesch <nikhil.benesch@gmail.com>
|
Nikhil Benesch <nikhil.benesch@gmail.com>
|
||||||
Nikita Kryuchkov <nkryuchkov10@gmail.com>
|
Nikita Kryuchkov <nkryuchkov10@gmail.com>
|
||||||
|
Nikita Vanyasin <nikita.vanyasin@gmail.com>
|
||||||
Niklas Schnelle <niklas.schnelle@gmail.com>
|
Niklas Schnelle <niklas.schnelle@gmail.com>
|
||||||
Niko Dziemba <niko@dziemba.com>
|
Niko Dziemba <niko@dziemba.com>
|
||||||
Nikolay Turpitko <nikolay@turpitko.com>
|
Nikolay Turpitko <nikolay@turpitko.com>
|
||||||
|
|
@ -1564,12 +1649,14 @@ Nodir Turakulov <nodir@google.com>
|
||||||
Noel Georgi <git@frezbo.com>
|
Noel Georgi <git@frezbo.com>
|
||||||
Norberto Lopes <nlopes.ml@gmail.com>
|
Norberto Lopes <nlopes.ml@gmail.com>
|
||||||
Norman B. Lancaster <qbradq@gmail.com>
|
Norman B. Lancaster <qbradq@gmail.com>
|
||||||
|
Nuno Cruces <ncruces@users.noreply.github.com>
|
||||||
Odin Ugedal <odin@ugedal.com>
|
Odin Ugedal <odin@ugedal.com>
|
||||||
Oleg Bulatov <dmage@yandex-team.ru>
|
Oleg Bulatov <dmage@yandex-team.ru>
|
||||||
Oleg Vakheta <helginet@gmail.com>
|
Oleg Vakheta <helginet@gmail.com>
|
||||||
Oleku Konko <oleku.konko@gmail.com>
|
Oleku Konko <oleku.konko@gmail.com>
|
||||||
Oling Cat <olingcat@gmail.com>
|
Oling Cat <olingcat@gmail.com>
|
||||||
Oliver Hookins <ohookins@gmail.com>
|
Oliver Hookins <ohookins@gmail.com>
|
||||||
|
Oliver Powell <oliverpowell84@gmail.com>
|
||||||
Oliver Stenbom <ostenbom@pivotal.io>
|
Oliver Stenbom <ostenbom@pivotal.io>
|
||||||
Oliver Tonnhofer <olt@bogosoft.com>
|
Oliver Tonnhofer <olt@bogosoft.com>
|
||||||
Olivier Antoine <olivier.antoine@gmail.com>
|
Olivier Antoine <olivier.antoine@gmail.com>
|
||||||
|
|
@ -1585,6 +1672,8 @@ Pablo Rozas Larraondo <pablo.larraondo@anu.edu.au>
|
||||||
Pablo Santiago Blum de Aguiar <scorphus@gmail.com>
|
Pablo Santiago Blum de Aguiar <scorphus@gmail.com>
|
||||||
Padraig Kitterick <padraigkitterick@gmail.com>
|
Padraig Kitterick <padraigkitterick@gmail.com>
|
||||||
Pallat Anchaleechamaikorn <yod.pallat@gmail.com>
|
Pallat Anchaleechamaikorn <yod.pallat@gmail.com>
|
||||||
|
Panos Georgiadis <pgeorgiadis@suse.de>
|
||||||
|
Pantelis Sampaziotis <psampaz@gmail.com>
|
||||||
Paolo Giarrusso <p.giarrusso@gmail.com>
|
Paolo Giarrusso <p.giarrusso@gmail.com>
|
||||||
Paolo Martini <mrtnpaolo@gmail.com>
|
Paolo Martini <mrtnpaolo@gmail.com>
|
||||||
Parker Moore <parkrmoore@gmail.com>
|
Parker Moore <parkrmoore@gmail.com>
|
||||||
|
|
@ -1626,6 +1715,7 @@ Paul van Brouwershaven <paul@vanbrouwershaven.com>
|
||||||
Paul Wankadia <junyer@google.com>
|
Paul Wankadia <junyer@google.com>
|
||||||
Paulo Casaretto <pcasaretto@gmail.com>
|
Paulo Casaretto <pcasaretto@gmail.com>
|
||||||
Paulo Flabiano Smorigo <pfsmorigo@linux.vnet.ibm.com>
|
Paulo Flabiano Smorigo <pfsmorigo@linux.vnet.ibm.com>
|
||||||
|
Paulo Gomes <paulo.gomes.uk@gmail.com>
|
||||||
Pavel Paulau <pavel.paulau@gmail.com>
|
Pavel Paulau <pavel.paulau@gmail.com>
|
||||||
Pavel Zinovkin <pavel.zinovkin@gmail.com>
|
Pavel Zinovkin <pavel.zinovkin@gmail.com>
|
||||||
Pavlo Sumkin <ymkins@gmail.com>
|
Pavlo Sumkin <ymkins@gmail.com>
|
||||||
|
|
@ -1679,6 +1769,7 @@ Piyush Mishra <piyush@codeitout.com>
|
||||||
Plekhanov Maxim <kishtatix@gmail.com>
|
Plekhanov Maxim <kishtatix@gmail.com>
|
||||||
Pontus Leitzler <leitzler@gmail.com>
|
Pontus Leitzler <leitzler@gmail.com>
|
||||||
Prasanna Swaminathan <prasanna@mediamath.com>
|
Prasanna Swaminathan <prasanna@mediamath.com>
|
||||||
|
Prashant Agrawal <prashant.a.vjti@gmail.com>
|
||||||
Prashant Varanasi <prashant@prashantv.com>
|
Prashant Varanasi <prashant@prashantv.com>
|
||||||
Pravendra Singh <hackpravj@gmail.com>
|
Pravendra Singh <hackpravj@gmail.com>
|
||||||
Preetam Jinka <pj@preet.am>
|
Preetam Jinka <pj@preet.am>
|
||||||
|
|
@ -1720,6 +1811,7 @@ Rémy Oudompheng <oudomphe@phare.normalesup.org> <remyoudompheng@gmail.com>
|
||||||
Rens Rikkerink <Ikkerens@users.noreply.github.com>
|
Rens Rikkerink <Ikkerens@users.noreply.github.com>
|
||||||
Rhys Hiltner <rhys@justin.tv>
|
Rhys Hiltner <rhys@justin.tv>
|
||||||
Ricardo Padilha <ricardospadilha@gmail.com>
|
Ricardo Padilha <ricardospadilha@gmail.com>
|
||||||
|
Ricardo Seriani <ricardo.seriani@gmail.com>
|
||||||
Richard Barnes <rlb@ipv.sx>
|
Richard Barnes <rlb@ipv.sx>
|
||||||
Richard Crowley <r@rcrowley.org>
|
Richard Crowley <r@rcrowley.org>
|
||||||
Richard Dingwall <rdingwall@gmail.com>
|
Richard Dingwall <rdingwall@gmail.com>
|
||||||
|
|
@ -1734,6 +1826,7 @@ Rijnard van Tonder <rvantonder@gmail.com>
|
||||||
Riku Voipio <riku.voipio@linaro.org>
|
Riku Voipio <riku.voipio@linaro.org>
|
||||||
Risto Jaakko Saarelma <rsaarelm@gmail.com>
|
Risto Jaakko Saarelma <rsaarelm@gmail.com>
|
||||||
Rob Earhart <earhart@google.com>
|
Rob Earhart <earhart@google.com>
|
||||||
|
Rob Findley <rfindley@google.com>
|
||||||
Rob Norman <rob.norman@infinitycloud.com>
|
Rob Norman <rob.norman@infinitycloud.com>
|
||||||
Rob Phoenix <rob@robphoenix.com>
|
Rob Phoenix <rob@robphoenix.com>
|
||||||
Rob Pike <r@golang.org>
|
Rob Pike <r@golang.org>
|
||||||
|
|
@ -1753,17 +1846,20 @@ Robert-André Mauchin <zebob.m@gmail.com>
|
||||||
Roberto Clapis <robclap8@gmail.com>
|
Roberto Clapis <robclap8@gmail.com>
|
||||||
Roberto Selbach <roberto@selbach.ca>
|
Roberto Selbach <roberto@selbach.ca>
|
||||||
Robin Eklind <r.eklind.87@gmail.com>
|
Robin Eklind <r.eklind.87@gmail.com>
|
||||||
|
Robin Zhong <robin@robinzhong.co>
|
||||||
Rodolfo Carvalho <rhcarvalho@gmail.com>
|
Rodolfo Carvalho <rhcarvalho@gmail.com>
|
||||||
Rodolfo Rodriguez <rodolfobgibson@gmail.com>
|
Rodolfo Rodriguez <rodolfobgibson@gmail.com>
|
||||||
Rodrigo Moraes de Oliveira <rodrigo.moraes@gmail.com>
|
Rodrigo Moraes de Oliveira <rodrigo.moraes@gmail.com>
|
||||||
Rodrigo Rafael Monti Kochenburger <divoxx@gmail.com>
|
Rodrigo Rafael Monti Kochenburger <divoxx@gmail.com>
|
||||||
Roger Pau Monné <royger@gmail.com>
|
Roger Pau Monné <royger@gmail.com>
|
||||||
Roger Peppe <rogpeppe@gmail.com>
|
Roger Peppe <rogpeppe@gmail.com>
|
||||||
|
Rohan Challa <rohan@golang.org>
|
||||||
Rohan Verma <rohanverma2004@gmail.com>
|
Rohan Verma <rohanverma2004@gmail.com>
|
||||||
Roland Illig <roland.illig@gmx.de>
|
Roland Illig <roland.illig@gmx.de>
|
||||||
Roland Shoemaker <rolandshoemaker@gmail.com>
|
Roland Shoemaker <rolandshoemaker@gmail.com>
|
||||||
Romain Baugue <romain.baugue@elwinar.com>
|
Romain Baugue <romain.baugue@elwinar.com>
|
||||||
Roman Budnikov <romanyx90@yandex.ru>
|
Roman Budnikov <romanyx90@yandex.ru>
|
||||||
|
Roman Kollár <roman.kollar.0@gmail.com>
|
||||||
Roman Shchekin <mrqtros@gmail.com>
|
Roman Shchekin <mrqtros@gmail.com>
|
||||||
Ron Hashimoto <mail@h2so5.net>
|
Ron Hashimoto <mail@h2so5.net>
|
||||||
Ron Minnich <rminnich@gmail.com>
|
Ron Minnich <rminnich@gmail.com>
|
||||||
|
|
@ -1774,6 +1870,7 @@ Rowan Marshall <rowanajmarshall@gmail.com>
|
||||||
Rowan Worth <sqweek@gmail.com>
|
Rowan Worth <sqweek@gmail.com>
|
||||||
Rudi Kramer <rudi.kramer@gmail.com>
|
Rudi Kramer <rudi.kramer@gmail.com>
|
||||||
Rui Ueyama <ruiu@google.com>
|
Rui Ueyama <ruiu@google.com>
|
||||||
|
Ruixin Bao <ruixin.bao@ibm.com>
|
||||||
Ruslan Nigmatullin <elessar@dropbox.com>
|
Ruslan Nigmatullin <elessar@dropbox.com>
|
||||||
Russ Cox <rsc@golang.org>
|
Russ Cox <rsc@golang.org>
|
||||||
Russell Haering <russellhaering@gmail.com>
|
Russell Haering <russellhaering@gmail.com>
|
||||||
|
|
@ -1815,6 +1912,7 @@ Sander van Harmelen <sander@vanharmelen.nl>
|
||||||
Sanjay Menakuru <balasanjay@gmail.com>
|
Sanjay Menakuru <balasanjay@gmail.com>
|
||||||
Santhosh Kumar Tekuri <santhosh.tekuri@gmail.com>
|
Santhosh Kumar Tekuri <santhosh.tekuri@gmail.com>
|
||||||
Sarah Adams <shadams@google.com>
|
Sarah Adams <shadams@google.com>
|
||||||
|
Sardorbek Pulatov <sardorbek.pulatov@outlook.com>
|
||||||
Sascha Brawer <sascha@brawer.ch>
|
Sascha Brawer <sascha@brawer.ch>
|
||||||
Sasha Lionheart <lionhearts@google.com>
|
Sasha Lionheart <lionhearts@google.com>
|
||||||
Sasha Sobol <sasha@scaledinference.com>
|
Sasha Sobol <sasha@scaledinference.com>
|
||||||
|
|
@ -1824,6 +1922,7 @@ Scott Crunkleton <crunk1@gmail.com>
|
||||||
Scott Ferguson <scottwferg@gmail.com>
|
Scott Ferguson <scottwferg@gmail.com>
|
||||||
Scott Lawrence <bytbox@gmail.com>
|
Scott Lawrence <bytbox@gmail.com>
|
||||||
Scott Mansfield <smansfield@netflix.com>
|
Scott Mansfield <smansfield@netflix.com>
|
||||||
|
Scott Ragan <ragansa@fb.com>
|
||||||
Scott Schwartz <scotts@golang.org>
|
Scott Schwartz <scotts@golang.org>
|
||||||
Scott Van Woudenberg <scottvw@google.com>
|
Scott Van Woudenberg <scottvw@google.com>
|
||||||
Sean Burford <sburford@google.com>
|
Sean Burford <sburford@google.com>
|
||||||
|
|
@ -1832,14 +1931,18 @@ Sean Chittenden <seanc@joyent.com>
|
||||||
Sean Christopherson <sean.j.christopherson@intel.com>
|
Sean Christopherson <sean.j.christopherson@intel.com>
|
||||||
Sean Dolphin <Sean.Dolphin@kpcompass.com>
|
Sean Dolphin <Sean.Dolphin@kpcompass.com>
|
||||||
Sean Harger <sharger@google.com>
|
Sean Harger <sharger@google.com>
|
||||||
|
Sean Liao <seankhliao@gmail.com>
|
||||||
Sean Rees <sean@erifax.org>
|
Sean Rees <sean@erifax.org>
|
||||||
Sebastiaan van Stijn <github@gone.nl>
|
Sebastiaan van Stijn <github@gone.nl>
|
||||||
|
Sebastian Chlopecki <sebsebmc@gmail.com>
|
||||||
|
Sebastian Kinne <skinne@google.com>
|
||||||
Sebastian Schmidt <yath@google.com>
|
Sebastian Schmidt <yath@google.com>
|
||||||
Sebastien Binet <seb.binet@gmail.com>
|
Sebastien Binet <seb.binet@gmail.com>
|
||||||
Sébastien Paolacci <sebastien.paolacci@gmail.com>
|
Sébastien Paolacci <sebastien.paolacci@gmail.com>
|
||||||
Sebastien Williams-Wynn <sebastien@cytora.com>
|
Sebastien Williams-Wynn <sebastien@cytora.com>
|
||||||
Segev Finer <segev208@gmail.com>
|
Segev Finer <segev208@gmail.com>
|
||||||
Seiji Takahashi <timaki.st@gmail.com>
|
Seiji Takahashi <timaki.st@gmail.com>
|
||||||
|
Sergei Lemeshkin <sergeilem@gmail.com>
|
||||||
Sergei Skorobogatov <skorobo@rambler.ru>
|
Sergei Skorobogatov <skorobo@rambler.ru>
|
||||||
Sergei Zagurskii <gvozdoder@gmail.com>
|
Sergei Zagurskii <gvozdoder@gmail.com>
|
||||||
Sergey 'SnakE' Gromov <snake.scaly@gmail.com>
|
Sergey 'SnakE' Gromov <snake.scaly@gmail.com>
|
||||||
|
|
@ -1853,6 +1956,7 @@ Sergey Semin <gray12511@gmail.com>
|
||||||
Sergey Yanykin <syanykin@ozon.ru>
|
Sergey Yanykin <syanykin@ozon.ru>
|
||||||
Sergio Luis O. B. Correia <sergio@correia.cc>
|
Sergio Luis O. B. Correia <sergio@correia.cc>
|
||||||
Sergiusz Bazanski <bazanski@gmail.com>
|
Sergiusz Bazanski <bazanski@gmail.com>
|
||||||
|
Serhat Giydiren <serhatgiydiren@gmail.com>
|
||||||
Serhii Aheienko <serhii.aheienko@gmail.com>
|
Serhii Aheienko <serhii.aheienko@gmail.com>
|
||||||
Seth Hoenig <seth.a.hoenig@gmail.com>
|
Seth Hoenig <seth.a.hoenig@gmail.com>
|
||||||
Seth Vargo <sethvargo@gmail.com>
|
Seth Vargo <sethvargo@gmail.com>
|
||||||
|
|
@ -1875,21 +1979,28 @@ Shintaro Kaneko <kaneshin0120@gmail.com>
|
||||||
Shivakumar GN <shivakumar.gn@gmail.com>
|
Shivakumar GN <shivakumar.gn@gmail.com>
|
||||||
Shivani Singhal <shivani.singhal2804@gmail.com>
|
Shivani Singhal <shivani.singhal2804@gmail.com>
|
||||||
Shivansh Rai <shivansh@freebsd.org>
|
Shivansh Rai <shivansh@freebsd.org>
|
||||||
|
Shivashis Padhi <shivashispadhi@gmail.com>
|
||||||
Shubham Sharma <shubham.sha12@gmail.com>
|
Shubham Sharma <shubham.sha12@gmail.com>
|
||||||
Shun Fan <sfan@google.com>
|
Shun Fan <sfan@google.com>
|
||||||
Silvan Jegen <s.jegen@gmail.com>
|
Silvan Jegen <s.jegen@gmail.com>
|
||||||
|
Simarpreet Singh <simar@linux.com>
|
||||||
|
Simon Ferquel <simon.ferquel@docker.com>
|
||||||
Simon Jefford <simon.jefford@gmail.com>
|
Simon Jefford <simon.jefford@gmail.com>
|
||||||
Simon Rawet <simon@rawet.se>
|
Simon Rawet <simon@rawet.se>
|
||||||
|
Simon Rozman <simon@rozman.si>
|
||||||
Simon Thulbourn <simon+github@thulbourn.com>
|
Simon Thulbourn <simon+github@thulbourn.com>
|
||||||
Simon Whitehead <chemnova@gmail.com>
|
Simon Whitehead <chemnova@gmail.com>
|
||||||
Sina Siadat <siadat@gmail.com>
|
Sina Siadat <siadat@gmail.com>
|
||||||
|
Sjoerd Siebinga <sjoerd.siebinga@gmail.com>
|
||||||
Sokolov Yura <funny.falcon@gmail.com>
|
Sokolov Yura <funny.falcon@gmail.com>
|
||||||
Song Gao <song@gao.io>
|
Song Gao <song@gao.io>
|
||||||
|
Spencer Kocot <spencerkocot@gmail.com>
|
||||||
Spencer Nelson <s@spenczar.com>
|
Spencer Nelson <s@spenczar.com>
|
||||||
Spencer Tung <spencertung@google.com>
|
Spencer Tung <spencertung@google.com>
|
||||||
Spring Mc <heresy.mc@gmail.com>
|
Spring Mc <heresy.mc@gmail.com>
|
||||||
Srdjan Petrovic <spetrovic@google.com>
|
Srdjan Petrovic <spetrovic@google.com>
|
||||||
Sridhar Venkatakrishnan <sridhar@laddoo.net>
|
Sridhar Venkatakrishnan <sridhar@laddoo.net>
|
||||||
|
Srinidhi Kaushik <shrinidhi.kaushik@gmail.com>
|
||||||
StalkR <stalkr@stalkr.net>
|
StalkR <stalkr@stalkr.net>
|
||||||
Stan Schwertly <stan@schwertly.com>
|
Stan Schwertly <stan@schwertly.com>
|
||||||
Stanislav Afanasev <php.progger@gmail.com>
|
Stanislav Afanasev <php.progger@gmail.com>
|
||||||
|
|
@ -1931,6 +2042,7 @@ Suyash <dextrous93@gmail.com>
|
||||||
Suzy Mueller <suzmue@golang.org>
|
Suzy Mueller <suzmue@golang.org>
|
||||||
Sven Almgren <sven@tras.se>
|
Sven Almgren <sven@tras.se>
|
||||||
Sven Blumenstein <svbl@google.com>
|
Sven Blumenstein <svbl@google.com>
|
||||||
|
Sven Taute <sven.taute@gmail.com>
|
||||||
Sylvain Zimmer <sylvain@sylvainzimmer.com>
|
Sylvain Zimmer <sylvain@sylvainzimmer.com>
|
||||||
Syohei YOSHIDA <syohex@gmail.com>
|
Syohei YOSHIDA <syohex@gmail.com>
|
||||||
Szabolcs Nagy <nsz@port70.net>
|
Szabolcs Nagy <nsz@port70.net>
|
||||||
|
|
@ -1948,6 +2060,7 @@ Takuto Ikuta <tikuta@google.com>
|
||||||
Takuya Ueda <uedatakuya@gmail.com>
|
Takuya Ueda <uedatakuya@gmail.com>
|
||||||
Tal Shprecher <tshprecher@gmail.com>
|
Tal Shprecher <tshprecher@gmail.com>
|
||||||
Tamir Duberstein <tamird@gmail.com>
|
Tamir Duberstein <tamird@gmail.com>
|
||||||
|
Tao Qingyun <qingyunha@gmail.com>
|
||||||
Tao Shen <shentaoskyking@gmail.com>
|
Tao Shen <shentaoskyking@gmail.com>
|
||||||
Tao Wang <twang2218@gmail.com>
|
Tao Wang <twang2218@gmail.com>
|
||||||
Tarmigan Casebolt <tarmigan@gmail.com>
|
Tarmigan Casebolt <tarmigan@gmail.com>
|
||||||
|
|
@ -1981,6 +2094,7 @@ Thomas Wanielista <tomwans@gmail.com>
|
||||||
Thorben Krueger <thorben.krueger@gmail.com>
|
Thorben Krueger <thorben.krueger@gmail.com>
|
||||||
Thordur Bjornsson <thorduri@secnorth.net>
|
Thordur Bjornsson <thorduri@secnorth.net>
|
||||||
Tiago Queiroz <contato@tiago.eti.br>
|
Tiago Queiroz <contato@tiago.eti.br>
|
||||||
|
Tianji Wu <the729@gmail.com>
|
||||||
Tianon Gravi <admwiggin@gmail.com>
|
Tianon Gravi <admwiggin@gmail.com>
|
||||||
Tilman Dilo <tilman.dilo@gmail.com>
|
Tilman Dilo <tilman.dilo@gmail.com>
|
||||||
Tim Cooijmans <timcooijmans@gmail.com>
|
Tim Cooijmans <timcooijmans@gmail.com>
|
||||||
|
|
@ -2014,6 +2128,7 @@ Tom Payne <twpayne@gmail.com>
|
||||||
Tom Szymanski <tgs@google.com>
|
Tom Szymanski <tgs@google.com>
|
||||||
Tom Thorogood <me+google@tomthorogood.co.uk>
|
Tom Thorogood <me+google@tomthorogood.co.uk>
|
||||||
Tom Wilkie <tom@weave.works>
|
Tom Wilkie <tom@weave.works>
|
||||||
|
Tomas Dabasinskas <tomas@dabasinskas.net>
|
||||||
Tommy Schaefer <tommy.schaefer@teecom.com>
|
Tommy Schaefer <tommy.schaefer@teecom.com>
|
||||||
Tomoya Ishizaki <zaq1tomo@gmail.com>
|
Tomoya Ishizaki <zaq1tomo@gmail.com>
|
||||||
Tonis Tiigi <tonistiigi@gmail.com>
|
Tonis Tiigi <tonistiigi@gmail.com>
|
||||||
|
|
@ -2064,6 +2179,7 @@ Victor Chudnovsky <vchudnov@google.com>
|
||||||
Victor Vrantchan <vrancean+github@gmail.com>
|
Victor Vrantchan <vrancean+github@gmail.com>
|
||||||
Vignesh Ramachandra <vickyramachandra@gmail.com>
|
Vignesh Ramachandra <vickyramachandra@gmail.com>
|
||||||
Vikas Kedia <vikask@google.com>
|
Vikas Kedia <vikask@google.com>
|
||||||
|
Ville Skyttä <ville.skytta@iki.fi>
|
||||||
Vincent Ambo <tazjin@googlemail.com>
|
Vincent Ambo <tazjin@googlemail.com>
|
||||||
Vincent Batts <vbatts@hashbangbash.com> <vbatts@gmail.com>
|
Vincent Batts <vbatts@hashbangbash.com> <vbatts@gmail.com>
|
||||||
Vincent Vanackere <vincent.vanackere@gmail.com>
|
Vincent Vanackere <vincent.vanackere@gmail.com>
|
||||||
|
|
@ -2071,15 +2187,18 @@ Vinu Rajashekhar <vinutheraj@gmail.com>
|
||||||
Vish Subramanian <vish@google.com>
|
Vish Subramanian <vish@google.com>
|
||||||
Vishvananda Ishaya <vishvananda@gmail.com>
|
Vishvananda Ishaya <vishvananda@gmail.com>
|
||||||
Visweswara R <r.visweswara@gmail.com>
|
Visweswara R <r.visweswara@gmail.com>
|
||||||
|
Vitaly Zdanevich <zdanevich.vitaly@ya.ru>
|
||||||
Vitor De Mario <vitordemario@gmail.com>
|
Vitor De Mario <vitordemario@gmail.com>
|
||||||
Vivek Sekhar <vsekhar@google.com>
|
Vivek Sekhar <vsekhar@google.com>
|
||||||
Vlad Krasnov <vlad@cloudflare.com>
|
Vlad Krasnov <vlad@cloudflare.com>
|
||||||
|
Vladimir Evgrafov <evgrafov.vladimir@gmail.com>
|
||||||
Vladimir Kovpak <cn007b@gmail.com>
|
Vladimir Kovpak <cn007b@gmail.com>
|
||||||
Vladimir Kuzmin <vkuzmin@uber.com>
|
Vladimir Kuzmin <vkuzmin@uber.com>
|
||||||
Vladimir Mihailenco <vladimir.webdev@gmail.com>
|
Vladimir Mihailenco <vladimir.webdev@gmail.com>
|
||||||
Vladimir Nikishenko <vova616@gmail.com>
|
Vladimir Nikishenko <vova616@gmail.com>
|
||||||
Vladimir Stefanovic <vladimir.stefanovic@imgtec.com>
|
Vladimir Stefanovic <vladimir.stefanovic@imgtec.com>
|
||||||
Vladimir Varankin <nek.narqo@gmail.com>
|
Vladimir Varankin <nek.narqo@gmail.com>
|
||||||
|
Vojtech Bocek <vbocek@gmail.com>
|
||||||
Volker Dobler <dr.volker.dobler@gmail.com>
|
Volker Dobler <dr.volker.dobler@gmail.com>
|
||||||
Volodymyr Paprotski <vpaprots@ca.ibm.com>
|
Volodymyr Paprotski <vpaprots@ca.ibm.com>
|
||||||
W. Trevor King <wking@tremily.us>
|
W. Trevor King <wking@tremily.us>
|
||||||
|
|
@ -2087,6 +2206,7 @@ Wade Simmons <wade@wades.im>
|
||||||
Wagner Riffel <wgrriffel@gmail.com>
|
Wagner Riffel <wgrriffel@gmail.com>
|
||||||
Walter Poupore <wpoupore@google.com>
|
Walter Poupore <wpoupore@google.com>
|
||||||
Wander Lairson Costa <wcosta@mozilla.com>
|
Wander Lairson Costa <wcosta@mozilla.com>
|
||||||
|
Wang Xuerui <git@xen0n.name>
|
||||||
Warren Fernandes <warren.f.fernandes@gmail.com>
|
Warren Fernandes <warren.f.fernandes@gmail.com>
|
||||||
Wayne Ashley Berry <wayneashleyberry@gmail.com>
|
Wayne Ashley Berry <wayneashleyberry@gmail.com>
|
||||||
Wedson Almeida Filho <wedsonaf@google.com>
|
Wedson Almeida Filho <wedsonaf@google.com>
|
||||||
|
|
@ -2113,10 +2233,12 @@ William Chan <willchan@chromium.org>
|
||||||
William Chang <mr.williamchang@gmail.com>
|
William Chang <mr.williamchang@gmail.com>
|
||||||
William Josephson <wjosephson@gmail.com>
|
William Josephson <wjosephson@gmail.com>
|
||||||
William Orr <will@worrbase.com> <ay1244@gmail.com>
|
William Orr <will@worrbase.com> <ay1244@gmail.com>
|
||||||
|
William Poussier <william.poussier@gmail.com>
|
||||||
Wisdom Omuya <deafgoat@gmail.com>
|
Wisdom Omuya <deafgoat@gmail.com>
|
||||||
Wu Yunzhou <yunzhouwu@gmail.com>
|
Wu Yunzhou <yunzhouwu@gmail.com>
|
||||||
Xi Ruoyao <xry23333@gmail.com>
|
Xi Ruoyao <xry23333@gmail.com>
|
||||||
Xia Bin <snyh@snyh.org>
|
Xia Bin <snyh@snyh.org>
|
||||||
|
Xiangdong Ji <xiangdong.ji@arm.com>
|
||||||
Xing Xing <mikespook@gmail.com>
|
Xing Xing <mikespook@gmail.com>
|
||||||
Xu Fei <badgangkiller@gmail.com>
|
Xu Fei <badgangkiller@gmail.com>
|
||||||
Xudong Zhang <felixmelon@gmail.com>
|
Xudong Zhang <felixmelon@gmail.com>
|
||||||
|
|
@ -2148,6 +2270,7 @@ Yoshiyuki Mineo <yoshiyuki.mineo@gmail.com>
|
||||||
Yosuke Akatsuka <yosuke.akatsuka@gmail.com>
|
Yosuke Akatsuka <yosuke.akatsuka@gmail.com>
|
||||||
Yu Heng Zhang <annita.zhang@cn.ibm.com>
|
Yu Heng Zhang <annita.zhang@cn.ibm.com>
|
||||||
Yu Xuan Zhang <zyxsh@cn.ibm.com>
|
Yu Xuan Zhang <zyxsh@cn.ibm.com>
|
||||||
|
Yuichi Nishiwaki <yuichi.nishiwaki@gmail.com>
|
||||||
Yuji Yaginuma <yuuji.yaginuma@gmail.com>
|
Yuji Yaginuma <yuuji.yaginuma@gmail.com>
|
||||||
Yuki OKUSHI <huyuumi.dev@gmail.com>
|
Yuki OKUSHI <huyuumi.dev@gmail.com>
|
||||||
Yuki Yugui Sonoda <yugui@google.com>
|
Yuki Yugui Sonoda <yugui@google.com>
|
||||||
|
|
@ -2175,6 +2298,7 @@ Zhongtao Chen <chenzhongtao@126.com>
|
||||||
Zhongwei Yao <zhongwei.yao@arm.com>
|
Zhongwei Yao <zhongwei.yao@arm.com>
|
||||||
Zhou Peng <p@ctriple.cn>
|
Zhou Peng <p@ctriple.cn>
|
||||||
Ziad Hatahet <hatahet@gmail.com>
|
Ziad Hatahet <hatahet@gmail.com>
|
||||||
|
Ziheng Liu <lzhfromustc@gmail.com>
|
||||||
Zorion Arrizabalaga <zorionk@gmail.com>
|
Zorion Arrizabalaga <zorionk@gmail.com>
|
||||||
Максадбек Ахмедов <a.maksadbek@gmail.com>
|
Максадбек Ахмедов <a.maksadbek@gmail.com>
|
||||||
Максим Федосеев <max.faceless.frei@gmail.com>
|
Максим Федосеев <max.faceless.frei@gmail.com>
|
||||||
|
|
|
||||||
197
api/go1.14.txt
Normal file
197
api/go1.14.txt
Normal file
|
|
@ -0,0 +1,197 @@
|
||||||
|
pkg crypto/tls, const TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 52393
|
||||||
|
pkg crypto/tls, const TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 uint16
|
||||||
|
pkg crypto/tls, const TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 52392
|
||||||
|
pkg crypto/tls, const TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 uint16
|
||||||
|
pkg crypto/tls, func CipherSuiteName(uint16) string
|
||||||
|
pkg crypto/tls, func CipherSuites() []*CipherSuite
|
||||||
|
pkg crypto/tls, func InsecureCipherSuites() []*CipherSuite
|
||||||
|
pkg crypto/tls, method (*CertificateRequestInfo) SupportsCertificate(*Certificate) error
|
||||||
|
pkg crypto/tls, method (*ClientHelloInfo) SupportsCertificate(*Certificate) error
|
||||||
|
pkg crypto/tls, type Certificate struct, SupportedSignatureAlgorithms []SignatureScheme
|
||||||
|
pkg crypto/tls, type CertificateRequestInfo struct, Version uint16
|
||||||
|
pkg crypto/tls, type CipherSuite struct
|
||||||
|
pkg crypto/tls, type CipherSuite struct, ID uint16
|
||||||
|
pkg crypto/tls, type CipherSuite struct, Insecure bool
|
||||||
|
pkg crypto/tls, type CipherSuite struct, Name string
|
||||||
|
pkg crypto/tls, type CipherSuite struct, SupportedVersions []uint16
|
||||||
|
pkg debug/dwarf, const AttrAddrBase = 115
|
||||||
|
pkg debug/dwarf, const AttrAddrBase Attr
|
||||||
|
pkg debug/dwarf, const AttrAlignment = 136
|
||||||
|
pkg debug/dwarf, const AttrAlignment Attr
|
||||||
|
pkg debug/dwarf, const AttrBinaryScale = 91
|
||||||
|
pkg debug/dwarf, const AttrBinaryScale Attr
|
||||||
|
pkg debug/dwarf, const AttrCallAllCalls = 122
|
||||||
|
pkg debug/dwarf, const AttrCallAllCalls Attr
|
||||||
|
pkg debug/dwarf, const AttrCallAllSourceCalls = 123
|
||||||
|
pkg debug/dwarf, const AttrCallAllSourceCalls Attr
|
||||||
|
pkg debug/dwarf, const AttrCallAllTailCalls = 124
|
||||||
|
pkg debug/dwarf, const AttrCallAllTailCalls Attr
|
||||||
|
pkg debug/dwarf, const AttrCallDataLocation = 133
|
||||||
|
pkg debug/dwarf, const AttrCallDataLocation Attr
|
||||||
|
pkg debug/dwarf, const AttrCallDataValue = 134
|
||||||
|
pkg debug/dwarf, const AttrCallDataValue Attr
|
||||||
|
pkg debug/dwarf, const AttrCallOrigin = 127
|
||||||
|
pkg debug/dwarf, const AttrCallOrigin Attr
|
||||||
|
pkg debug/dwarf, const AttrCallPC = 129
|
||||||
|
pkg debug/dwarf, const AttrCallPC Attr
|
||||||
|
pkg debug/dwarf, const AttrCallParameter = 128
|
||||||
|
pkg debug/dwarf, const AttrCallParameter Attr
|
||||||
|
pkg debug/dwarf, const AttrCallReturnPC = 125
|
||||||
|
pkg debug/dwarf, const AttrCallReturnPC Attr
|
||||||
|
pkg debug/dwarf, const AttrCallTailCall = 130
|
||||||
|
pkg debug/dwarf, const AttrCallTailCall Attr
|
||||||
|
pkg debug/dwarf, const AttrCallTarget = 131
|
||||||
|
pkg debug/dwarf, const AttrCallTarget Attr
|
||||||
|
pkg debug/dwarf, const AttrCallTargetClobbered = 132
|
||||||
|
pkg debug/dwarf, const AttrCallTargetClobbered Attr
|
||||||
|
pkg debug/dwarf, const AttrCallValue = 126
|
||||||
|
pkg debug/dwarf, const AttrCallValue Attr
|
||||||
|
pkg debug/dwarf, const AttrConstExpr = 108
|
||||||
|
pkg debug/dwarf, const AttrConstExpr Attr
|
||||||
|
pkg debug/dwarf, const AttrDataBitOffset = 107
|
||||||
|
pkg debug/dwarf, const AttrDataBitOffset Attr
|
||||||
|
pkg debug/dwarf, const AttrDecimalScale = 92
|
||||||
|
pkg debug/dwarf, const AttrDecimalScale Attr
|
||||||
|
pkg debug/dwarf, const AttrDecimalSign = 94
|
||||||
|
pkg debug/dwarf, const AttrDecimalSign Attr
|
||||||
|
pkg debug/dwarf, const AttrDefaulted = 139
|
||||||
|
pkg debug/dwarf, const AttrDefaulted Attr
|
||||||
|
pkg debug/dwarf, const AttrDeleted = 138
|
||||||
|
pkg debug/dwarf, const AttrDeleted Attr
|
||||||
|
pkg debug/dwarf, const AttrDigitCount = 95
|
||||||
|
pkg debug/dwarf, const AttrDigitCount Attr
|
||||||
|
pkg debug/dwarf, const AttrDwoName = 118
|
||||||
|
pkg debug/dwarf, const AttrDwoName Attr
|
||||||
|
pkg debug/dwarf, const AttrElemental = 102
|
||||||
|
pkg debug/dwarf, const AttrElemental Attr
|
||||||
|
pkg debug/dwarf, const AttrEndianity = 101
|
||||||
|
pkg debug/dwarf, const AttrEndianity Attr
|
||||||
|
pkg debug/dwarf, const AttrEnumClass = 109
|
||||||
|
pkg debug/dwarf, const AttrEnumClass Attr
|
||||||
|
pkg debug/dwarf, const AttrExplicit = 99
|
||||||
|
pkg debug/dwarf, const AttrExplicit Attr
|
||||||
|
pkg debug/dwarf, const AttrExportSymbols = 137
|
||||||
|
pkg debug/dwarf, const AttrExportSymbols Attr
|
||||||
|
pkg debug/dwarf, const AttrLinkageName = 110
|
||||||
|
pkg debug/dwarf, const AttrLinkageName Attr
|
||||||
|
pkg debug/dwarf, const AttrLoclistsBase = 140
|
||||||
|
pkg debug/dwarf, const AttrLoclistsBase Attr
|
||||||
|
pkg debug/dwarf, const AttrMacros = 121
|
||||||
|
pkg debug/dwarf, const AttrMacros Attr
|
||||||
|
pkg debug/dwarf, const AttrMainSubprogram = 106
|
||||||
|
pkg debug/dwarf, const AttrMainSubprogram Attr
|
||||||
|
pkg debug/dwarf, const AttrMutable = 97
|
||||||
|
pkg debug/dwarf, const AttrMutable Attr
|
||||||
|
pkg debug/dwarf, const AttrNoreturn = 135
|
||||||
|
pkg debug/dwarf, const AttrNoreturn Attr
|
||||||
|
pkg debug/dwarf, const AttrObjectPointer = 100
|
||||||
|
pkg debug/dwarf, const AttrObjectPointer Attr
|
||||||
|
pkg debug/dwarf, const AttrPictureString = 96
|
||||||
|
pkg debug/dwarf, const AttrPictureString Attr
|
||||||
|
pkg debug/dwarf, const AttrPure = 103
|
||||||
|
pkg debug/dwarf, const AttrPure Attr
|
||||||
|
pkg debug/dwarf, const AttrRank = 113
|
||||||
|
pkg debug/dwarf, const AttrRank Attr
|
||||||
|
pkg debug/dwarf, const AttrRecursive = 104
|
||||||
|
pkg debug/dwarf, const AttrRecursive Attr
|
||||||
|
pkg debug/dwarf, const AttrReference = 119
|
||||||
|
pkg debug/dwarf, const AttrReference Attr
|
||||||
|
pkg debug/dwarf, const AttrRnglistsBase = 116
|
||||||
|
pkg debug/dwarf, const AttrRnglistsBase Attr
|
||||||
|
pkg debug/dwarf, const AttrRvalueReference = 120
|
||||||
|
pkg debug/dwarf, const AttrRvalueReference Attr
|
||||||
|
pkg debug/dwarf, const AttrSignature = 105
|
||||||
|
pkg debug/dwarf, const AttrSignature Attr
|
||||||
|
pkg debug/dwarf, const AttrSmall = 93
|
||||||
|
pkg debug/dwarf, const AttrSmall Attr
|
||||||
|
pkg debug/dwarf, const AttrStrOffsetsBase = 114
|
||||||
|
pkg debug/dwarf, const AttrStrOffsetsBase Attr
|
||||||
|
pkg debug/dwarf, const AttrStringLengthBitSize = 111
|
||||||
|
pkg debug/dwarf, const AttrStringLengthBitSize Attr
|
||||||
|
pkg debug/dwarf, const AttrStringLengthByteSize = 112
|
||||||
|
pkg debug/dwarf, const AttrStringLengthByteSize Attr
|
||||||
|
pkg debug/dwarf, const AttrThreadsScaled = 98
|
||||||
|
pkg debug/dwarf, const AttrThreadsScaled Attr
|
||||||
|
pkg debug/dwarf, const ClassAddrPtr = 15
|
||||||
|
pkg debug/dwarf, const ClassAddrPtr Class
|
||||||
|
pkg debug/dwarf, const ClassLocList = 16
|
||||||
|
pkg debug/dwarf, const ClassLocList Class
|
||||||
|
pkg debug/dwarf, const ClassRngList = 17
|
||||||
|
pkg debug/dwarf, const ClassRngList Class
|
||||||
|
pkg debug/dwarf, const ClassRngListsPtr = 18
|
||||||
|
pkg debug/dwarf, const ClassRngListsPtr Class
|
||||||
|
pkg debug/dwarf, const ClassStrOffsetsPtr = 19
|
||||||
|
pkg debug/dwarf, const ClassStrOffsetsPtr Class
|
||||||
|
pkg debug/dwarf, const TagAtomicType = 71
|
||||||
|
pkg debug/dwarf, const TagAtomicType Tag
|
||||||
|
pkg debug/dwarf, const TagCallSite = 72
|
||||||
|
pkg debug/dwarf, const TagCallSite Tag
|
||||||
|
pkg debug/dwarf, const TagCallSiteParameter = 73
|
||||||
|
pkg debug/dwarf, const TagCallSiteParameter Tag
|
||||||
|
pkg debug/dwarf, const TagCoarrayType = 68
|
||||||
|
pkg debug/dwarf, const TagCoarrayType Tag
|
||||||
|
pkg debug/dwarf, const TagDynamicType = 70
|
||||||
|
pkg debug/dwarf, const TagDynamicType Tag
|
||||||
|
pkg debug/dwarf, const TagGenericSubrange = 69
|
||||||
|
pkg debug/dwarf, const TagGenericSubrange Tag
|
||||||
|
pkg debug/dwarf, const TagImmutableType = 75
|
||||||
|
pkg debug/dwarf, const TagImmutableType Tag
|
||||||
|
pkg debug/dwarf, const TagSkeletonUnit = 74
|
||||||
|
pkg debug/dwarf, const TagSkeletonUnit Tag
|
||||||
|
pkg debug/dwarf, method (*Data) AddSection(string, []uint8) error
|
||||||
|
pkg debug/dwarf, method (*LineReader) Files() []*LineFile
|
||||||
|
pkg debug/dwarf, method (*Reader) ByteOrder() binary.ByteOrder
|
||||||
|
pkg encoding/asn1, const TagBMPString = 30
|
||||||
|
pkg encoding/asn1, const TagBMPString ideal-int
|
||||||
|
pkg encoding/json, method (*Decoder) InputOffset() int64
|
||||||
|
pkg go/build, type Context struct, Dir string
|
||||||
|
pkg go/doc, func NewFromFiles(*token.FileSet, []*ast.File, string, ...interface{}) (*Package, error)
|
||||||
|
pkg go/doc, type Example struct, Suffix string
|
||||||
|
pkg go/doc, type Func struct, Examples []*Example
|
||||||
|
pkg go/doc, type Package struct, Examples []*Example
|
||||||
|
pkg go/doc, type Type struct, Examples []*Example
|
||||||
|
pkg hash/maphash, func MakeSeed() Seed
|
||||||
|
pkg hash/maphash, method (*Hash) BlockSize() int
|
||||||
|
pkg hash/maphash, method (*Hash) Reset()
|
||||||
|
pkg hash/maphash, method (*Hash) Seed() Seed
|
||||||
|
pkg hash/maphash, method (*Hash) SetSeed(Seed)
|
||||||
|
pkg hash/maphash, method (*Hash) Size() int
|
||||||
|
pkg hash/maphash, method (*Hash) Sum([]uint8) []uint8
|
||||||
|
pkg hash/maphash, method (*Hash) Sum64() uint64
|
||||||
|
pkg hash/maphash, method (*Hash) Write([]uint8) (int, error)
|
||||||
|
pkg hash/maphash, method (*Hash) WriteByte(uint8) error
|
||||||
|
pkg hash/maphash, method (*Hash) WriteString(string) (int, error)
|
||||||
|
pkg hash/maphash, type Hash struct
|
||||||
|
pkg hash/maphash, type Seed struct
|
||||||
|
pkg log, const Lmsgprefix = 64
|
||||||
|
pkg log, const Lmsgprefix ideal-int
|
||||||
|
pkg math, func FMA(float64, float64, float64) float64
|
||||||
|
pkg math/bits, func Rem(uint, uint, uint) uint
|
||||||
|
pkg math/bits, func Rem32(uint32, uint32, uint32) uint32
|
||||||
|
pkg math/bits, func Rem64(uint64, uint64, uint64) uint64
|
||||||
|
pkg mime/multipart, method (*Reader) NextRawPart() (*Part, error)
|
||||||
|
pkg net/http, method (Header) Values(string) []string
|
||||||
|
pkg net/http, type Transport struct, DialTLSContext func(context.Context, string, string) (net.Conn, error)
|
||||||
|
pkg net/http/httptest, type Server struct, EnableHTTP2 bool
|
||||||
|
pkg net/textproto, method (MIMEHeader) Values(string) []string
|
||||||
|
pkg strconv, method (*NumError) Unwrap() error
|
||||||
|
pkg syscall (windows-386), const CTRL_CLOSE_EVENT = 2
|
||||||
|
pkg syscall (windows-386), const CTRL_CLOSE_EVENT ideal-int
|
||||||
|
pkg syscall (windows-386), const CTRL_LOGOFF_EVENT = 5
|
||||||
|
pkg syscall (windows-386), const CTRL_LOGOFF_EVENT ideal-int
|
||||||
|
pkg syscall (windows-386), const CTRL_SHUTDOWN_EVENT = 6
|
||||||
|
pkg syscall (windows-386), const CTRL_SHUTDOWN_EVENT ideal-int
|
||||||
|
pkg syscall (windows-amd64), const CTRL_CLOSE_EVENT = 2
|
||||||
|
pkg syscall (windows-amd64), const CTRL_CLOSE_EVENT ideal-int
|
||||||
|
pkg syscall (windows-amd64), const CTRL_LOGOFF_EVENT = 5
|
||||||
|
pkg syscall (windows-amd64), const CTRL_LOGOFF_EVENT ideal-int
|
||||||
|
pkg syscall (windows-amd64), const CTRL_SHUTDOWN_EVENT = 6
|
||||||
|
pkg syscall (windows-amd64), const CTRL_SHUTDOWN_EVENT ideal-int
|
||||||
|
pkg testing, method (*B) Cleanup(func())
|
||||||
|
pkg testing, method (*T) Cleanup(func())
|
||||||
|
pkg testing, type TB interface, Cleanup(func())
|
||||||
|
pkg unicode, const Version = "12.0.0"
|
||||||
|
pkg unicode, var Elymaic *RangeTable
|
||||||
|
pkg unicode, var Nandinagari *RangeTable
|
||||||
|
pkg unicode, var Nyiakeng_Puachue_Hmong *RangeTable
|
||||||
|
pkg unicode, var Wancho *RangeTable
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
pkg unicode, const Version = "12.0.0"
|
|
||||||
pkg unicode, var Elymaic *RangeTable
|
|
||||||
pkg unicode, var Nandinagari *RangeTable
|
|
||||||
pkg unicode, var Nyiakeng_Puachue_Hmong *RangeTable
|
|
||||||
pkg unicode, var Wancho *RangeTable
|
|
||||||
|
|
@ -74,7 +74,7 @@ important, the use of the tool itself.</p>
|
||||||
<p>The <code>go</code> command requires that code adheres to a few key,
|
<p>The <code>go</code> command requires that code adheres to a few key,
|
||||||
well-established conventions.</p>
|
well-established conventions.</p>
|
||||||
|
|
||||||
<p>First, the import path is derived in an known way from the URL of the
|
<p>First, the import path is derived in a known way from the URL of the
|
||||||
source code. For Bitbucket, GitHub, Google Code, and Launchpad, the
|
source code. For Bitbucket, GitHub, Google Code, and Launchpad, the
|
||||||
root directory of the repository is identified by the repository's
|
root directory of the repository is identified by the repository's
|
||||||
main URL, without the <code>http://</code> prefix. Subdirectories are named by
|
main URL, without the <code>http://</code> prefix. Subdirectories are named by
|
||||||
|
|
|
||||||
|
|
@ -133,6 +133,11 @@ cost of increased memory usage.
|
||||||
<code>halt_on_error</code> (default <code>0</code>): Controls whether the program
|
<code>halt_on_error</code> (default <code>0</code>): Controls whether the program
|
||||||
exits after reporting first data race.
|
exits after reporting first data race.
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<code>atexit_sleep_ms</code> (default <code>1000</code>): Amount of milliseconds
|
||||||
|
to sleep in the main goroutine before exiting.
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
|
||||||
211
doc/conduct.html
211
doc/conduct.html
|
|
@ -1,211 +0,0 @@
|
||||||
<!--{
|
|
||||||
"Title": "Go Community Code of Conduct",
|
|
||||||
"Path": "/conduct",
|
|
||||||
"Template": true
|
|
||||||
}-->
|
|
||||||
|
|
||||||
<style>
|
|
||||||
ul {
|
|
||||||
max-width: 800px;
|
|
||||||
}
|
|
||||||
ul ul {
|
|
||||||
margin: 0 0 5px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<h2 id="about">About</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Online communities include people from many different backgrounds.
|
|
||||||
The Go contributors are committed to providing a friendly, safe and welcoming
|
|
||||||
environment for all, regardless of gender identity and expression, sexual orientation,
|
|
||||||
disabilities, neurodiversity, physical appearance, body size, ethnicity, nationality,
|
|
||||||
race, age, religion, or similar personal characteristics.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The first goal of the Code of Conduct is to specify a baseline standard
|
|
||||||
of behavior so that people with different social values and communication
|
|
||||||
styles can talk about Go effectively, productively, and respectfully.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The second goal is to provide a mechanism for resolving conflicts in the
|
|
||||||
community when they arise.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The third goal of the Code of Conduct is to make our community welcoming to
|
|
||||||
people from different backgrounds.
|
|
||||||
Diversity is critical to the project; for Go to be successful, it needs
|
|
||||||
contributors and users from all backgrounds.
|
|
||||||
(See <a href="https://blog.golang.org/open-source">Go, Open Source, Community</a>.)
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
We believe that healthy debate and disagreement are essential to a healthy project and community.
|
|
||||||
However, it is never ok to be disrespectful.
|
|
||||||
We value diverse opinions, but we value respectful behavior more.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h2 id="values">Gopher values</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
These are the values to which people in the Go community (“Gophers”) should aspire.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>Be friendly and welcoming
|
|
||||||
<li>Be patient
|
|
||||||
<ul>
|
|
||||||
<li>Remember that people have varying communication styles and that not
|
|
||||||
everyone is using their native language.
|
|
||||||
(Meaning and tone can be lost in translation.)
|
|
||||||
</ul>
|
|
||||||
<li>Be thoughtful
|
|
||||||
<ul>
|
|
||||||
<li>Productive communication requires effort.
|
|
||||||
Think about how your words will be interpreted.
|
|
||||||
<li>Remember that sometimes it is best to refrain entirely from commenting.
|
|
||||||
</ul>
|
|
||||||
<li>Be respectful
|
|
||||||
<ul>
|
|
||||||
<li>In particular, respect differences of opinion.
|
|
||||||
</ul>
|
|
||||||
<li>Be charitable
|
|
||||||
<ul>
|
|
||||||
<li>Interpret the arguments of others in good faith, do not seek to disagree.
|
|
||||||
<li>When we do disagree, try to understand why.
|
|
||||||
</ul>
|
|
||||||
<li>Avoid destructive behavior:
|
|
||||||
<ul>
|
|
||||||
<li>Derailing: stay on topic; if you want to talk about something else,
|
|
||||||
start a new conversation.
|
|
||||||
<li>Unconstructive criticism: don't merely decry the current state of affairs;
|
|
||||||
offer—or at least solicit—suggestions as to how things may be improved.
|
|
||||||
<li>Snarking (pithy, unproductive, sniping comments)
|
|
||||||
<li>Discussing potentially offensive or sensitive issues;
|
|
||||||
this all too often leads to unnecessary conflict.
|
|
||||||
<li>Microaggressions: brief and commonplace verbal, behavioral and
|
|
||||||
environmental indignities that communicate hostile, derogatory or negative
|
|
||||||
slights and insults to a person or group.
|
|
||||||
</ul>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
People are complicated.
|
|
||||||
You should expect to be misunderstood and to misunderstand others;
|
|
||||||
when this inevitably occurs, resist the urge to be defensive or assign blame.
|
|
||||||
Try not to take offense where no offense was intended.
|
|
||||||
Give people the benefit of the doubt.
|
|
||||||
Even if the intent was to provoke, do not rise to it.
|
|
||||||
It is the responsibility of <i>all parties</i> to de-escalate conflict when it arises.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h2 id="code">Code of Conduct</h2>
|
|
||||||
|
|
||||||
<h3 id="our-pledge">Our Pledge</h3>
|
|
||||||
|
|
||||||
<p>In the interest of fostering an open and welcoming environment, we as
|
|
||||||
contributors and maintainers pledge to making participation in our project and
|
|
||||||
our community a harassment-free experience for everyone, regardless of age, body
|
|
||||||
size, disability, ethnicity, gender identity and expression, level of
|
|
||||||
experience, education, socio-economic status, nationality, personal appearance,
|
|
||||||
race, religion, or sexual identity and orientation.</p>
|
|
||||||
|
|
||||||
<h3 id="our-standards">Our Standards</h3>
|
|
||||||
|
|
||||||
<p>Examples of behavior that contributes to creating a positive environment
|
|
||||||
include:</p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>Using welcoming and inclusive language</li>
|
|
||||||
<li>Being respectful of differing viewpoints and experiences</li>
|
|
||||||
<li>Gracefully accepting constructive criticism</li>
|
|
||||||
<li>Focusing on what is best for the community</li>
|
|
||||||
<li>Showing empathy towards other community members</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>Examples of unacceptable behavior by participants include:</p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>The use of sexualized language or imagery and unwelcome sexual attention or
|
|
||||||
advances</li>
|
|
||||||
<li>Trolling, insulting/derogatory comments, and personal or political attacks</li>
|
|
||||||
<li>Public or private harassment</li>
|
|
||||||
<li>Publishing others’ private information, such as a physical or electronic
|
|
||||||
address, without explicit permission</li>
|
|
||||||
<li>Other conduct which could reasonably be considered inappropriate in a
|
|
||||||
professional setting</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 id="our-responsibilities">Our Responsibilities</h3>
|
|
||||||
|
|
||||||
<p>Project maintainers are responsible for clarifying the standards of acceptable
|
|
||||||
behavior and are expected to take appropriate and fair corrective action in
|
|
||||||
response to any instances of unacceptable behavior.</p>
|
|
||||||
|
|
||||||
<p>Project maintainers have the right and responsibility to remove, edit, or reject
|
|
||||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
|
||||||
not aligned to this Code of Conduct, or to ban temporarily or permanently any
|
|
||||||
contributor for other behaviors that they deem inappropriate, threatening,
|
|
||||||
offensive, or harmful.</p>
|
|
||||||
|
|
||||||
<h3 id="scope">Scope</h3>
|
|
||||||
|
|
||||||
<p>This Code of Conduct applies both within project spaces and in public spaces
|
|
||||||
when an individual is representing the project or its community. Examples of
|
|
||||||
representing a project or community include using an official project e-mail
|
|
||||||
address, posting via an official social media account, or acting as an appointed
|
|
||||||
representative at an online or offline event. Representation of a project may be
|
|
||||||
further defined and clarified by project maintainers.</p>
|
|
||||||
|
|
||||||
<p>This Code of Conduct also applies outside the project spaces when the Project
|
|
||||||
Steward has a reasonable belief that an individual’s behavior may have a
|
|
||||||
negative impact on the project or its community.</p>
|
|
||||||
|
|
||||||
<h3 id="conflict-resolution"></a>Conflict Resolution</h3>
|
|
||||||
|
|
||||||
<p>We do not believe that all conflict is bad; healthy debate and disagreement
|
|
||||||
often yield positive results. However, it is never okay to be disrespectful or
|
|
||||||
to engage in behavior that violates the project’s code of conduct.</p>
|
|
||||||
|
|
||||||
<p>If you see someone violating the code of conduct, you are encouraged to address
|
|
||||||
the behavior directly with those involved. Many issues can be resolved quickly
|
|
||||||
and easily, and this gives people more control over the outcome of their
|
|
||||||
dispute. If you are unable to resolve the matter for any reason, or if the
|
|
||||||
behavior is threatening or harassing, report it. We are dedicated to providing
|
|
||||||
an environment where participants feel welcome and safe.</p>
|
|
||||||
|
|
||||||
<p id="reporting">Reports should be directed to Cassandra Salisbury, the
|
|
||||||
Go Project Steward, at <i>conduct@golang.org</i>.
|
|
||||||
It is the Project Steward’s duty to
|
|
||||||
receive and address reported violations of the code of conduct. They will then
|
|
||||||
work with a committee consisting of representatives from the Open Source
|
|
||||||
Programs Office and the Google Open Source Strategy team. If for any reason you
|
|
||||||
are uncomfortable reaching out the Project Steward, please email
|
|
||||||
the Google Open Source Programs Office at <i>opensource@google.com</i>.</p>
|
|
||||||
|
|
||||||
<p>We will investigate every complaint, but you may not receive a direct response.
|
|
||||||
We will use our discretion in determining when and how to follow up on reported
|
|
||||||
incidents, which may range from not taking action to permanent expulsion from
|
|
||||||
the project and project-sponsored spaces. We will notify the accused of the
|
|
||||||
report and provide them an opportunity to discuss it before any action is taken.
|
|
||||||
The identity of the reporter will be omitted from the details of the report
|
|
||||||
supplied to the accused. In potentially harmful situations, such as ongoing
|
|
||||||
harassment or threats to anyone’s safety, we may take action without notice.</p>
|
|
||||||
|
|
||||||
<h3 id="attribution">Attribution</h3>
|
|
||||||
|
|
||||||
<p>This Code of Conduct is adapted from the Contributor Covenant, version 1.4,
|
|
||||||
available at
|
|
||||||
<a href="https://www.contributor-covenant.org/version/1/4/code-of-conduct.html">https://www.contributor-covenant.org/version/1/4/code-of-conduct.html</a></p>
|
|
||||||
|
|
||||||
<h2 id="summary">Summary</h2>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>Treat everyone with respect and kindness.
|
|
||||||
<li>Be thoughtful in how you communicate.
|
|
||||||
<li>Don’t be destructive or inflammatory.
|
|
||||||
<li>If you encounter an issue, please mail <a href="mailto:conduct@golang.org">conduct@golang.org</a>.
|
|
||||||
</ul>
|
|
||||||
|
|
@ -925,13 +925,13 @@ New files that you contribute should use the standard copyright header:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
// Copyright 2019 The Go Authors. All rights reserved.
|
// Copyright 2020 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
(Use the current year if you're reading this in 2020 or beyond.)
|
(Use the current year if you're reading this in 2021 or beyond.)
|
||||||
Files in the repository are copyrighted the year they are added.
|
Files in the repository are copyrighted the year they are added.
|
||||||
Do not update the copyright year on files that you change.
|
Do not update the copyright year on files that you change.
|
||||||
</p>
|
</p>
|
||||||
|
|
|
||||||
|
|
@ -1,455 +0,0 @@
|
||||||
<!--{
|
|
||||||
"Title": "Pre-Go 1 Release History"
|
|
||||||
}-->
|
|
||||||
|
|
||||||
<p>
|
|
||||||
This page summarizes the changes between stable releases of Go prior to Go 1.
|
|
||||||
See the <a href="release.html">Release History</a> page for notes on recent releases.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h2 id="r60">r60 (released 2011/09/07)</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The r60 release corresponds to
|
|
||||||
<code><a href="weekly.html#2011-08-17">weekly.2011-08-17</a></code>.
|
|
||||||
This section highlights the most significant changes in this release.
|
|
||||||
For a more detailed summary, see the
|
|
||||||
<a href="weekly.html#2011-08-17">weekly release notes</a>.
|
|
||||||
For complete information, see the
|
|
||||||
<a href="//code.google.com/p/go/source/list?r=release-branch.r60">Mercurial change list</a>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="r60.lang">Language</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
An "else" block is now required to have braces except if the body of the "else"
|
|
||||||
is another "if". Since gofmt always puts those braces in anyway,
|
|
||||||
gofmt-formatted programs will not be affected.
|
|
||||||
To fix other programs, run gofmt.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="r60.pkg">Packages</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="/pkg/http/">Package http</a>'s URL parsing and query escaping code
|
|
||||||
(such as <code>ParseURL</code> and <code>URLEscape</code>) has been moved to
|
|
||||||
the new <a href="/pkg/url/">url package</a>, with several simplifications to
|
|
||||||
the names. Client code can be updated automatically with gofix.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="/pkg/image/">Package image</a> has had significant changes made to the
|
|
||||||
<code>Pix</code> field of struct types such as
|
|
||||||
<a href="/pkg/image/#RGBA">image.RGBA</a> and
|
|
||||||
<a href="/pkg/image/#NRGBA">image.NRGBA</a>.
|
|
||||||
The <a href="/pkg/image/#Image">image.Image</a> interface type has not changed,
|
|
||||||
though, and you should not need to change your code if you don't explicitly
|
|
||||||
refer to <code>Pix</code> fields. For example, if you decode a number of images
|
|
||||||
using the <a href="/pkg/image/jpeg/">image/jpeg</a> package, compose them using
|
|
||||||
<a href="/pkg/image/draw/">image/draw</a>, and then encode the result using
|
|
||||||
<a href="/pkg/img/png">image/png</a>, then your code should still work as
|
|
||||||
before.
|
|
||||||
If your code <i>does</i> refer to <code>Pix</code> fields see the
|
|
||||||
<a href="/doc/devel/weekly.html#2011-07-19">weekly.2011-07-19</a>
|
|
||||||
snapshot notes for how to update your code.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="/pkg/template/">Package template</a> has been replaced with a new
|
|
||||||
templating package (formerly <code>exp/template</code>). The original template
|
|
||||||
package is still available as <a href="/pkg/old/template/">old/template</a>.
|
|
||||||
The <code>old/template</code> package is deprecated and will be removed.
|
|
||||||
The Go tree has been updated to use the new template package. We encourage
|
|
||||||
users of the old template package to switch to the new one. Code that uses
|
|
||||||
<code>template</code> or <code>exp/template</code> will need to change its
|
|
||||||
import lines to <code>"old/template"</code> or <code>"template"</code>,
|
|
||||||
respectively.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="r60.cmd">Tools</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="/cmd/goinstall/">Goinstall</a> now uses a new tag selection scheme.
|
|
||||||
When downloading or updating, goinstall looks for a tag or branch with the
|
|
||||||
<code>"go."</code> prefix that corresponds to the local Go version. For Go
|
|
||||||
<code>release.r58</code> it looks for <code>go.r58</code>. For
|
|
||||||
<code>weekly.2011-06-03</code> it looks for <code>go.weekly.2011-06-03</code>.
|
|
||||||
If the specific <code>go.X</code> tag or branch is not found, it chooses the
|
|
||||||
closest earlier version. If an appropriate tag or branch is found, goinstall
|
|
||||||
uses that version of the code. Otherwise it uses the default version selected
|
|
||||||
by the version control system. Library authors are encouraged to use the
|
|
||||||
appropriate tag or branch names in their repositories to make their libraries
|
|
||||||
more accessible.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="r60.minor">Minor revisions</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
r60.1 includes a
|
|
||||||
<a href="//golang.org/change/1824581bf62d">linker
|
|
||||||
fix</a>, a pair of
|
|
||||||
<a href="//golang.org/change/9ef4429c2c64">goplay</a>
|
|
||||||
<a href="//golang.org/change/d42ed8c3098e">fixes</a>,
|
|
||||||
and a <code>json</code> package
|
|
||||||
<a href="//golang.org/change/d5e97874fe84">fix</a> and
|
|
||||||
a new
|
|
||||||
<a href="//golang.org/change/4f0e6269213f">struct tag
|
|
||||||
option</a>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
r60.2
|
|
||||||
<a href="//golang.org/change/ff19536042ac">fixes</a>
|
|
||||||
a memory leak involving maps.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
r60.3 fixes a
|
|
||||||
<a href="//golang.org/change/01fa62f5e4e5">reflect bug</a>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h2 id="r59">r59 (released 2011/08/01)</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The r59 release corresponds to
|
|
||||||
<code><a href="weekly.html#2011-07-07">weekly.2011-07-07</a></code>.
|
|
||||||
This section highlights the most significant changes in this release.
|
|
||||||
For a more detailed summary, see the
|
|
||||||
<a href="weekly.html#2011-07-07">weekly release notes</a>.
|
|
||||||
For complete information, see the
|
|
||||||
<a href="//code.google.com/p/go/source/list?r=release-branch.r59">Mercurial change list</a>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="r59.lang">Language</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
This release includes a language change that restricts the use of
|
|
||||||
<code>goto</code>. In essence, a <code>goto</code> statement outside a block
|
|
||||||
cannot jump to a label inside that block. Your code may require changes if it
|
|
||||||
uses <code>goto</code>.
|
|
||||||
See <a href="//golang.org/change/dc6d3cf9279d">this
|
|
||||||
changeset</a> for how the new rule affected the Go tree.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="r59.pkg">Packages</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
As usual, <a href="/cmd/gofix/">gofix</a> will handle the bulk of the rewrites
|
|
||||||
necessary for these changes to package APIs.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="/pkg/http">Package http</a> has a new
|
|
||||||
<a href="/pkg/http/#FileSystem">FileSystem</a> interface that provides access
|
|
||||||
to files. The <a href="/pkg/http/#FileServer">FileServer</a> helper now takes a
|
|
||||||
<code>FileSystem</code> argument instead of an explicit file system root. By
|
|
||||||
implementing your own <code>FileSystem</code> you can use the
|
|
||||||
<code>FileServer</code> to serve arbitrary data.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="/pkg/os/">Package os</a>'s <code>ErrorString</code> type has been
|
|
||||||
hidden. Most uses of <code>os.ErrorString</code> can be replaced with
|
|
||||||
<a href="/pkg/os/#NewError">os.NewError</a>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="/pkg/reflect/">Package reflect</a> supports a new struct tag scheme
|
|
||||||
that enables sharing of struct tags between multiple packages.
|
|
||||||
In this scheme, the tags must be of the form:
|
|
||||||
</p>
|
|
||||||
<pre>
|
|
||||||
`key:"value" key2:"value2"`
|
|
||||||
</pre>
|
|
||||||
<p>
|
|
||||||
The <a href="/pkg/reflect/#StructField">StructField</a> type's Tag field now
|
|
||||||
has type <a href="/pkg/reflect/#StructTag">StructTag</a>, which has a
|
|
||||||
<code>Get</code> method. Clients of <a href="/pkg/json">json</a> and
|
|
||||||
<a href="/pkg/xml">xml</a> will need to be updated. Code that says
|
|
||||||
</p>
|
|
||||||
<pre>
|
|
||||||
type T struct {
|
|
||||||
X int "name"
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
<p>
|
|
||||||
should become
|
|
||||||
</p>
|
|
||||||
<pre>
|
|
||||||
type T struct {
|
|
||||||
X int `json:"name"` // or `xml:"name"`
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
<p>
|
|
||||||
Use <a href="/cmd/govet/">govet</a> to identify struct tags that need to be
|
|
||||||
changed to use the new syntax.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="/pkg/sort/">Package sort</a>'s <code>IntArray</code> type has been
|
|
||||||
renamed to <a href="/pkg/sort/#IntSlice">IntSlice</a>, and similarly for
|
|
||||||
<a href="/pkg/sort/#Float64Slice">Float64Slice</a> and
|
|
||||||
<a href="/pkg/sort/#StringSlice">StringSlice</a>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="/pkg/strings/">Package strings</a>'s <code>Split</code> function has
|
|
||||||
itself been split into <a href="/pkg/strings/#Split">Split</a> and
|
|
||||||
<a href="/pkg/strings/#SplitN">SplitN</a>.
|
|
||||||
<code>SplitN</code> is the same as the old <code>Split</code>.
|
|
||||||
The new <code>Split</code> is equivalent to <code>SplitN</code> with a final
|
|
||||||
argument of -1.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<a href="/pkg/image/draw/">Package image/draw</a>'s
|
|
||||||
<a href="/pkg/image/draw/#Draw">Draw</a> function now takes an additional
|
|
||||||
argument, a compositing operator.
|
|
||||||
If in doubt, use <a href="/pkg/image/draw/#Op">draw.Over</a>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="r59.cmd">Tools</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="/cmd/goinstall/">Goinstall</a> now installs packages and commands from
|
|
||||||
arbitrary remote repositories (not just Google Code, Github, and so on).
|
|
||||||
See the <a href="/cmd/goinstall/">goinstall documentation</a> for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h2 id="r58">r58 (released 2011/06/29)</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The r58 release corresponds to
|
|
||||||
<code><a href="weekly.html#2011-06-09">weekly.2011-06-09</a></code>
|
|
||||||
with additional bug fixes.
|
|
||||||
This section highlights the most significant changes in this release.
|
|
||||||
For a more detailed summary, see the
|
|
||||||
<a href="weekly.html#2011-06-09">weekly release notes</a>.
|
|
||||||
For complete information, see the
|
|
||||||
<a href="//code.google.com/p/go/source/list?r=release-branch.r58">Mercurial change list</a>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="r58.lang">Language</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
This release fixes a <a href="//golang.org/change/b720749486e1">use of uninitialized memory in programs that misuse <code>goto</code></a>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="r58.pkg">Packages</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
As usual, <a href="/cmd/gofix/">gofix</a> will handle the bulk of the rewrites
|
|
||||||
necessary for these changes to package APIs.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="/pkg/http/">Package http</a> drops the <code>finalURL</code> return
|
|
||||||
value from the <a href="/pkg/http/#Client.Get">Client.Get</a> method. The value
|
|
||||||
is now available via the new <code>Request</code> field on <a
|
|
||||||
href="/pkg/http/#Response">http.Response</a>.
|
|
||||||
Most instances of the type map[string][]string in have been
|
|
||||||
replaced with the new <a href="/pkg/http/#Values">Values</a> type.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="/pkg/exec/">Package exec</a> has been redesigned with a more
|
|
||||||
convenient and succinct API.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="/pkg/strconv/">Package strconv</a>'s <a href="/pkg/strconv/#Quote">Quote</a>
|
|
||||||
function now escapes only those Unicode code points not classified as printable
|
|
||||||
by <a href="/pkg/unicode/#IsPrint">unicode.IsPrint</a>.
|
|
||||||
Previously Quote would escape all non-ASCII characters.
|
|
||||||
This also affects the <a href="/pkg/fmt/">fmt</a> package's <code>"%q"</code>
|
|
||||||
formatting directive. The previous quoting behavior is still available via
|
|
||||||
strconv's new <a href="/pkg/strconv/#QuoteToASCII">QuoteToASCII</a> function.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="/pkg/os/signal/">Package os/signal</a>'s
|
|
||||||
<a href="/pkg/os/#Signal">Signal</a> and
|
|
||||||
<a href="/pkg/os/#UnixSignal">UnixSignal</a> types have been moved to the
|
|
||||||
<a href="/pkg/os/">os</a> package.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="/pkg/image/draw/">Package image/draw</a> is the new name for
|
|
||||||
<code>exp/draw</code>. The GUI-related code from <code>exp/draw</code> is now
|
|
||||||
located in the <a href="/pkg/exp/gui/">exp/gui</a> package.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="r58.cmd">Tools</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="/cmd/goinstall/">Goinstall</a> now observes the GOPATH environment
|
|
||||||
variable to build and install your own code and external libraries outside of
|
|
||||||
the Go tree (and avoid writing Makefiles).
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="r58.minor">Minor revisions</h3>
|
|
||||||
|
|
||||||
<p>r58.1 adds
|
|
||||||
<a href="//golang.org/change/293c25943586">build</a> and
|
|
||||||
<a href="//golang.org/change/bf17e96b6582">runtime</a>
|
|
||||||
changes to make Go run on OS X 10.7 Lion.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h2 id="r57">r57 (released 2011/05/03)</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The r57 release corresponds to
|
|
||||||
<code><a href="weekly.html#2011-04-27">weekly.2011-04-27</a></code>
|
|
||||||
with additional bug fixes.
|
|
||||||
This section highlights the most significant changes in this release.
|
|
||||||
For a more detailed summary, see the
|
|
||||||
<a href="weekly.html#2011-04-27">weekly release notes</a>.
|
|
||||||
For complete information, see the
|
|
||||||
<a href="//code.google.com/p/go/source/list?r=release-branch.r57">Mercurial change list</a>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>The new <a href="/cmd/gofix">gofix</a> tool finds Go programs that use old APIs and rewrites them to use
|
|
||||||
newer ones. After you update to a new Go release, gofix helps make the
|
|
||||||
necessary changes to your programs. Gofix will handle the http, os, and syscall
|
|
||||||
package changes described below, and we will update the program to keep up with
|
|
||||||
future changes to the libraries.
|
|
||||||
Gofix can’t
|
|
||||||
handle all situations perfectly, so read and test the changes it makes before
|
|
||||||
committing them.
|
|
||||||
See <a href="//blog.golang.org/2011/04/introducing-gofix.html">the gofix blog post</a> for more
|
|
||||||
information.</p>
|
|
||||||
|
|
||||||
<h3 id="r57.lang">Language</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="/doc/go_spec.html#Receive_operator">Multiple assignment syntax</a> replaces the <code>closed</code> function.
|
|
||||||
The syntax for channel
|
|
||||||
receives allows an optional second assigned value, a boolean value
|
|
||||||
indicating whether the channel is closed. This code:
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
v := <-ch
|
|
||||||
if closed(ch) {
|
|
||||||
// channel is closed
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>should now be written as:</p>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
v, ok := <-ch
|
|
||||||
if !ok {
|
|
||||||
// channel is closed
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p><a href="/doc/go_spec.html#Label_scopes">Unused labels are now illegal</a>, just as unused local variables are.</p>
|
|
||||||
|
|
||||||
<h3 id="r57.pkg">Packages</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="/pkg/gob/">Package gob</a> will now encode and decode values of types that implement the
|
|
||||||
<a href="/pkg/gob/#GobEncoder">GobEncoder</a> and
|
|
||||||
<a href="/pkg/gob/#GobDecoder">GobDecoder</a> interfaces. This allows types with unexported
|
|
||||||
fields to transmit self-consistent descriptions; examples include
|
|
||||||
<a href="/pkg/big/#Int.GobDecode">big.Int</a> and <a href="/pkg/big/#Rat.GobDecode">big.Rat</a>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="/pkg/http/">Package http</a> has been redesigned.
|
|
||||||
For clients, there are new
|
|
||||||
<a href="/pkg/http/#Client">Client</a> and <a href="/pkg/http/#Transport">Transport</a>
|
|
||||||
abstractions that give more control over HTTP details such as headers sent
|
|
||||||
and redirections followed. These abstractions make it easy to implement
|
|
||||||
custom clients that add functionality such as <a href="//code.google.com/p/goauth2/source/browse/oauth/oauth.go">OAuth2</a>.
|
|
||||||
For servers, <a href="/pkg/http/#ResponseWriter">ResponseWriter</a>
|
|
||||||
has dropped its non-essential methods.
|
|
||||||
The Hijack and Flush methods are no longer required;
|
|
||||||
code can test for them by checking whether a specific value implements
|
|
||||||
<a href="/pkg/http/#Hijacker">Hijacker</a> or <a href="/pkg/http/#Flusher">Flusher</a>.
|
|
||||||
The RemoteAddr and UsingTLS methods are replaced by <a href="/pkg/http/#Request">Request</a>'s
|
|
||||||
RemoteAddr and TLS fields.
|
|
||||||
The SetHeader method is replaced by a Header method;
|
|
||||||
its result, of type <a href="/pkg/http/#Header">Header</a>,
|
|
||||||
implements Set and other methods.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="/pkg/net/">Package net</a>
|
|
||||||
drops the <code>laddr</code> argument from <a href="/pkg/net/#Conn.Dial">Dial</a>
|
|
||||||
and drops the <code>cname</code> return value
|
|
||||||
from <a href="/pkg/net/#LookupHost">LookupHost</a>.
|
|
||||||
The implementation now uses <a href="/cmd/cgo/">cgo</a> to implement
|
|
||||||
network name lookups using the C library getaddrinfo(3)
|
|
||||||
function when possible. This ensures that Go and C programs
|
|
||||||
resolve names the same way and also avoids the OS X
|
|
||||||
application-level firewall.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="/pkg/os/">Package os</a>
|
|
||||||
introduces simplified <a href="/pkg/os/#File.Open">Open</a>
|
|
||||||
and <a href="/pkg/os/#File.Create">Create</a> functions.
|
|
||||||
The original Open is now available as <a href="/pkg/os/#File.OpenFile">OpenFile</a>.
|
|
||||||
The final three arguments to <a href="/pkg/os/#Process.StartProcess">StartProcess</a>
|
|
||||||
have been replaced by a pointer to a <a href="/pkg/os/#ProcAttr">ProcAttr</a>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="/pkg/reflect/">Package reflect</a> has been redesigned.
|
|
||||||
<a href="/pkg/reflect/#Type">Type</a> is now an interface that implements
|
|
||||||
all the possible type methods.
|
|
||||||
Instead of a type switch on a Type <code>t</code>, switch on <code>t.Kind()</code>.
|
|
||||||
<a href="/pkg/reflect/#Value">Value</a> is now a struct value that
|
|
||||||
implements all the possible value methods.
|
|
||||||
Instead of a type switch on a Value <code>v</code>, switch on <code>v.Kind()</code>.
|
|
||||||
Typeof and NewValue are now called <a href="/pkg/reflect/#Type.TypeOf">TypeOf</a> and <a href="/pkg/reflect/#Value.ValueOf">ValueOf</a>
|
|
||||||
To create a writable Value, use <code>New(t).Elem()</code> instead of <code>Zero(t)</code>.
|
|
||||||
See <a href="//golang.org/change/843855f3c026">the change description</a>
|
|
||||||
for the full details.
|
|
||||||
The new API allows a more efficient implementation of Value
|
|
||||||
that avoids many of the allocations required by the previous API.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Remember that gofix will handle the bulk of the rewrites
|
|
||||||
necessary for these changes to package APIs.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="r57.cmd">Tools</h3>
|
|
||||||
|
|
||||||
<p><a href="/cmd/gofix/">Gofix</a>, a new command, is described above.</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="/cmd/gotest/">Gotest</a> is now a Go program instead of a shell script.
|
|
||||||
The new <code>-test.short</code> flag in combination with package testing's Short function
|
|
||||||
allows you to write tests that can be run in normal or “short” mode;
|
|
||||||
all.bash runs tests in short mode to reduce installation time.
|
|
||||||
The Makefiles know about the flag: use <code>make testshort</code>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The run-time support now implements CPU and memory profiling.
|
|
||||||
Gotest's new
|
|
||||||
<a href="/cmd/gotest/"><code>-test.cpuprofile</code> and
|
|
||||||
<code>-test.memprofile</code> flags</a> make it easy to
|
|
||||||
profile tests.
|
|
||||||
To add profiling to your web server, see the <a href="/pkg/http/pprof/">http/pprof</a>
|
|
||||||
documentation.
|
|
||||||
For other uses, see the <a href="/pkg/runtime/pprof/">runtime/pprof</a> documentation.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="r57.minor">Minor revisions</h3>
|
|
||||||
|
|
||||||
<p>r57.1 fixes a <a href="//golang.org/change/ff2bc62726e7145eb2ecc1e0f076998e4a8f86f0">nil pointer dereference in http.FormFile</a>.</p>
|
|
||||||
<p>r57.2 fixes a <a href="//golang.org/change/063b0ff67d8277df03c956208abc068076818dae">use of uninitialized memory in programs that misuse <code>goto</code></a>.</p>
|
|
||||||
|
|
||||||
<h2 id="r56">r56 (released 2011/03/16)</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The r56 release was the first stable release and corresponds to
|
|
||||||
<code><a href="weekly.html#2011-03-07">weekly.2011-03-07.1</a></code>.
|
|
||||||
The numbering starts at 56 because before this release,
|
|
||||||
what we now consider weekly snapshots were called releases.
|
|
||||||
</p>
|
|
||||||
|
|
@ -1,745 +0,0 @@
|
||||||
<!--{
|
|
||||||
"Title": "Release History"
|
|
||||||
}-->
|
|
||||||
|
|
||||||
<p>This page summarizes the changes between official stable releases of Go.
|
|
||||||
The <a href="//golang.org/change">change log</a> has the full details.</p>
|
|
||||||
|
|
||||||
<p>To update to a specific release, use:</p>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
git pull
|
|
||||||
git checkout <i>release-branch</i>
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<h2 id="policy">Release Policy</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Each major Go release is supported until there are two newer major releases.
|
|
||||||
For example, Go 1.5 was supported until the Go 1.7 release, and Go 1.6 was
|
|
||||||
supported until the Go 1.8 release.
|
|
||||||
We fix critical problems, including <a href="/security">critical security problems</a>,
|
|
||||||
in supported releases as needed by issuing minor revisions
|
|
||||||
(for example, Go 1.6.1, Go 1.6.2, and so on).
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h2 id="go1.13">go1.13 (released 2019/09/03)</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Go 1.13 is a major release of Go.
|
|
||||||
Read the <a href="/doc/go1.13">Go 1.13 Release Notes</a> for more information.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="go1.13.minor">Minor revisions</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.13.1 (released 2019/09/25) includes security fixes to the
|
|
||||||
<code>net/http</code> and <code>net/textproto</code> packages.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.13.1">Go
|
|
||||||
1.13.1 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.13.2 (released 2019/10/17) includes security fixes to the
|
|
||||||
<code>crypto/dsa</code> package and the compiler.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.13.2">Go
|
|
||||||
1.13.2 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.13.3 (released 2019/10/17) includes fixes to the go command,
|
|
||||||
the toolchain, the runtime, <code>syscall</code>, <code>net</code>,
|
|
||||||
<code>net/http</code>, and <code>crypto/ecdsa</code> packages.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.13.3">Go
|
|
||||||
1.13.3 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.13.4 (released 2019/10/31) includes fixes to the <code>net/http</code> and
|
|
||||||
<code>syscall</code> packages. It also fixes an issue on macOS 10.15 Catalina
|
|
||||||
where the non-notarized installer and binaries were being
|
|
||||||
<a href="https://golang.org/issue/34986">rejected by Gatekeeper</a>.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.13.4">Go
|
|
||||||
1.13.4 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h2 id="go1.12">go1.12 (released 2019/02/25)</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Go 1.12 is a major release of Go.
|
|
||||||
Read the <a href="/doc/go1.12">Go 1.12 Release Notes</a> for more information.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="go1.12.minor">Minor revisions</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.12.1 (released 2019/03/14) includes fixes to cgo, the compiler, the go
|
|
||||||
command, and the <code>fmt</code>, <code>net/smtp</code>, <code>os</code>,
|
|
||||||
<code>path/filepath</code>, <code>sync</code>, and <code>text/template</code>
|
|
||||||
packages. See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.12.1">Go
|
|
||||||
1.12.1 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.12.2 (released 2019/04/05) includes fixes to the compiler, the go
|
|
||||||
command, the runtime, and the <code>doc</code>, <code>net</code>,
|
|
||||||
<code>net/http/httputil</code>, and <code>os</code> packages. See the
|
|
||||||
<a href="https://github.com/golang/go/issues?q=milestone%3AGo1.12.2">Go
|
|
||||||
1.12.2 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.12.3 (released 2019/04/08) was accidentally released without its
|
|
||||||
intended fix. It is identical to go1.12.2, except for its version
|
|
||||||
number. The intended fix is in go1.12.4.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.12.4 (released 2019/04/11) fixes an issue where using the prebuilt binary
|
|
||||||
releases on older versions of GNU/Linux
|
|
||||||
<a href="https://golang.org/issues/31293">led to failures</a>
|
|
||||||
when linking programs that used cgo.
|
|
||||||
Only Linux users who hit this issue need to update.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.12.5 (released 2019/05/06) includes fixes to the compiler, the linker,
|
|
||||||
the go command, the runtime, and the <code>os</code> package. See the
|
|
||||||
<a href="https://github.com/golang/go/issues?q=milestone%3AGo1.12.5">Go
|
|
||||||
1.12.5 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.12.6 (released 2019/06/11) includes fixes to the compiler, the linker,
|
|
||||||
the go command, and the <code>crypto/x509</code>, <code>net/http</code>, and
|
|
||||||
<code>os</code> packages. See the
|
|
||||||
<a href="https://github.com/golang/go/issues?q=milestone%3AGo1.12.6">Go
|
|
||||||
1.12.6 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.12.7 (released 2019/07/08) includes fixes to cgo, the compiler,
|
|
||||||
and the linker.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.12.7">Go
|
|
||||||
1.12.7 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.12.8 (released 2019/08/13) includes security fixes to the
|
|
||||||
<code>net/http</code> and <code>net/url</code> packages.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.12.8">Go
|
|
||||||
1.12.8 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.12.9 (released 2019/08/15) includes fixes to the linker,
|
|
||||||
and the <code>os</code> and <code>math/big</code> packages.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.12.9+label%3ACherryPickApproved">Go
|
|
||||||
1.12.9 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.12.10 (released 2019/09/25) includes security fixes to the
|
|
||||||
<code>net/http</code> and <code>net/textproto</code> packages.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.12.10">Go
|
|
||||||
1.12.10 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.12.11 (released 2019/10/17) includes security fixes to the
|
|
||||||
<code>crypto/dsa</code> package.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.12.11">Go
|
|
||||||
1.12.11 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.12.12 (released 2019/10/17) includes fixes to the go command,
|
|
||||||
runtime, <code>syscall</code> and <code>net</code> packages.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.12.12">Go
|
|
||||||
1.12.12 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.12.13 (released 2019/10/31) fixes an issue on macOS 10.15 Catalina
|
|
||||||
where the non-notarized installer and binaries were being
|
|
||||||
<a href="https://golang.org/issue/34986">rejected by Gatekeeper</a>.
|
|
||||||
Only macOS users who hit this issue need to update.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h2 id="go1.11">go1.11 (released 2018/08/24)</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Go 1.11 is a major release of Go.
|
|
||||||
Read the <a href="/doc/go1.11">Go 1.11 Release Notes</a> for more information.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="go1.11.minor">Minor revisions</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.11.1 (released 2018/10/01) includes fixes to the compiler, documentation, go
|
|
||||||
command, runtime, and the <code>crypto/x509</code>, <code>encoding/json</code>,
|
|
||||||
<code>go/types</code>, <code>net</code>, <code>net/http</code>, and
|
|
||||||
<code>reflect</code> packages.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.1">Go
|
|
||||||
1.11.1 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.11.2 (released 2018/11/02) includes fixes to the compiler, linker,
|
|
||||||
documentation, go command, and the <code>database/sql</code> and
|
|
||||||
<code>go/types</code> packages.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.2">Go
|
|
||||||
1.11.2 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.11.3 (released 2018/12/12) includes three security fixes to "go get" and
|
|
||||||
the <code>crypto/x509</code> package.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.3">Go
|
|
||||||
1.11.3 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.11.4 (released 2018/12/14) includes fixes to cgo, the compiler, linker,
|
|
||||||
runtime, documentation, go command, and the <code>net/http</code> and
|
|
||||||
<code>go/types</code> packages.
|
|
||||||
It includes a fix to a bug introduced in Go 1.11.3 that broke <code>go</code>
|
|
||||||
<code>get</code> for import path patterns containing "<code>...</code>".
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.4+label%3ACherryPickApproved">Go
|
|
||||||
1.11.4 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.11.5 (released 2019/01/23) includes a security fix to the
|
|
||||||
<code>crypto/elliptic</code> package. See
|
|
||||||
the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.5">Go
|
|
||||||
1.11.5 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.11.6 (released 2019/03/14) includes fixes to cgo, the compiler, linker,
|
|
||||||
runtime, go command, and the <code>crypto/x509</code>, <code>encoding/json</code>,
|
|
||||||
<code>net</code>, and <code>net/url</code> packages. See the
|
|
||||||
<a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.6">Go
|
|
||||||
1.11.6 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.11.7 (released 2019/04/05) includes fixes to the runtime and the
|
|
||||||
<code>net</code> packages. See the
|
|
||||||
<a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.7">Go
|
|
||||||
1.11.7 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.11.8 (released 2019/04/08) was accidentally released without its
|
|
||||||
intended fix. It is identical to go1.11.7, except for its version
|
|
||||||
number. The intended fix is in go1.11.9.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.11.9 (released 2019/04/11) fixes an issue where using the prebuilt binary
|
|
||||||
releases on older versions of GNU/Linux
|
|
||||||
<a href="https://golang.org/issues/31293">led to failures</a>
|
|
||||||
when linking programs that used cgo.
|
|
||||||
Only Linux users who hit this issue need to update.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.11.10 (released 2019/05/06) includes fixes to the runtime and the linker.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.10">Go
|
|
||||||
1.11.10 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.11.11 (released 2019/06/11) includes a fix to the <code>crypto/x509</code> package.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.11">Go
|
|
||||||
1.11.11 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.11.12 (released 2019/07/08) includes fixes to the compiler and the linker.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.12">Go
|
|
||||||
1.11.12 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.11.13 (released 2019/08/13) includes security fixes to the
|
|
||||||
<code>net/http</code> and <code>net/url</code> packages.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.13">Go
|
|
||||||
1.11.13 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h2 id="go1.10">go1.10 (released 2018/02/16)</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Go 1.10 is a major release of Go.
|
|
||||||
Read the <a href="/doc/go1.10">Go 1.10 Release Notes</a> for more information.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="go1.10.minor">Minor revisions</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.10.1 (released 2018/03/28) includes fixes to the compiler, runtime, and the
|
|
||||||
<code>archive/zip</code>, <code>crypto/tls</code>, <code>crypto/x509</code>,
|
|
||||||
<code>encoding/json</code>, <code>net</code>, <code>net/http</code>, and
|
|
||||||
<code>net/http/pprof</code> packages.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.10.1">Go
|
|
||||||
1.10.1 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.10.2 (released 2018/05/01) includes fixes to the compiler, linker, and go
|
|
||||||
command.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.10.2">Go
|
|
||||||
1.10.2 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.10.3 (released 2018/06/05) includes fixes to the go command, and the
|
|
||||||
<code>crypto/tls</code>, <code>crypto/x509</code>, and <code>strings</code> packages.
|
|
||||||
In particular, it adds <a href="https://go.googlesource.com/go/+/d4e21288e444d3ffd30d1a0737f15ea3fc3b8ad9">
|
|
||||||
minimal support to the go command for the vgo transition</a>.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.10.3">Go
|
|
||||||
1.10.3 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.10.4 (released 2018/08/24) includes fixes to the go command, linker, and the
|
|
||||||
<code>net/http</code>, <code>mime/multipart</code>, <code>ld/macho</code>,
|
|
||||||
<code>bytes</code>, and <code>strings</code> packages.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.10.4">Go
|
|
||||||
1.10.4 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.10.5 (released 2018/11/02) includes fixes to the go command, linker, runtime
|
|
||||||
and the <code>database/sql</code> package.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.10.5">Go
|
|
||||||
1.10.5 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.10.6 (released 2018/12/12) includes three security fixes to "go get" and
|
|
||||||
the <code>crypto/x509</code> package.
|
|
||||||
It contains the same fixes as Go 1.11.3 and was released at the same time.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.10.6">Go
|
|
||||||
1.10.6 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.10.7 (released 2018/12/14) includes a fix to a bug introduced in Go 1.10.6
|
|
||||||
that broke <code>go</code> <code>get</code> for import path patterns containing
|
|
||||||
"<code>...</code>".
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.10.7+label%3ACherryPickApproved">
|
|
||||||
Go 1.10.7 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.10.8 (released 2019/01/23) includes a security fix to the
|
|
||||||
<code>crypto/elliptic</code> package. See
|
|
||||||
the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.10.8">Go
|
|
||||||
1.10.8 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h2 id="go1.9">go1.9 (released 2017/08/24)</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Go 1.9 is a major release of Go.
|
|
||||||
Read the <a href="/doc/go1.9">Go 1.9 Release Notes</a> for more information.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="go1.9.minor">Minor revisions</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.9.1 (released 2017/10/04) includes two security fixes.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.9.1">Go
|
|
||||||
1.9.1 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.9.2 (released 2017/10/25) includes fixes to the compiler, linker, runtime,
|
|
||||||
documentation, <code>go</code> command,
|
|
||||||
and the <code>crypto/x509</code>, <code>database/sql</code>, <code>log</code>,
|
|
||||||
and <code>net/smtp</code> packages.
|
|
||||||
It includes a fix to a bug introduced in Go 1.9.1 that broke <code>go</code> <code>get</code>
|
|
||||||
of non-Git repositories under certain conditions.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.9.2">Go
|
|
||||||
1.9.2 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.9.3 (released 2018/01/22) includes fixes to the compiler, runtime,
|
|
||||||
and the <code>database/sql</code>, <code>math/big</code>, <code>net/http</code>,
|
|
||||||
and <code>net/url</code> packages.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.9.3">Go
|
|
||||||
1.9.3 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.9.4 (released 2018/02/07) includes a security fix to “go get”.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.9.4">Go
|
|
||||||
1.9.4</a> milestone on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.9.5 (released 2018/03/28) includes fixes to the compiler, go command, and
|
|
||||||
<code>net/http/pprof</code> package.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.9.5">Go
|
|
||||||
1.9.5 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.9.6 (released 2018/05/01) includes fixes to the compiler and go command.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.9.6">Go
|
|
||||||
1.9.6 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.9.7 (released 2018/06/05) includes fixes to the go command, and the
|
|
||||||
<code>crypto/x509</code>, and <code>strings</code> packages.
|
|
||||||
In particular, it adds <a href="https://go.googlesource.com/go/+/d4e21288e444d3ffd30d1a0737f15ea3fc3b8ad9">
|
|
||||||
minimal support to the go command for the vgo transition</a>.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.9.7">Go
|
|
||||||
1.9.7 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="go1.8">go1.8 (released 2017/02/16)</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Go 1.8 is a major release of Go.
|
|
||||||
Read the <a href="/doc/go1.8">Go 1.8 Release Notes</a> for more information.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="go1.8.minor">Minor revisions</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.8.1 (released 2017/04/07) includes fixes to the compiler, linker, runtime,
|
|
||||||
documentation, <code>go</code> command and the <code>crypto/tls</code>,
|
|
||||||
<code>encoding/xml</code>, <code>image/png</code>, <code>net</code>,
|
|
||||||
<code>net/http</code>, <code>reflect</code>, <code>text/template</code>,
|
|
||||||
and <code>time</code> packages.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.8.1">Go
|
|
||||||
1.8.1 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.8.2 (released 2017/05/23) includes a security fix to the
|
|
||||||
<code>crypto/elliptic</code> package.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.8.2">Go
|
|
||||||
1.8.2 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.8.3 (released 2017/05/24) includes fixes to the compiler, runtime,
|
|
||||||
documentation, and the <code>database/sql</code> package.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.8.3">Go
|
|
||||||
1.8.3 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.8.4 (released 2017/10/04) includes two security fixes.
|
|
||||||
It contains the same fixes as Go 1.9.1 and was released at the same time.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.8.4">Go
|
|
||||||
1.8.4 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.8.5 (released 2017/10/25) includes fixes to the compiler, linker, runtime,
|
|
||||||
documentation, <code>go</code> command,
|
|
||||||
and the <code>crypto/x509</code> and <code>net/smtp</code> packages.
|
|
||||||
It includes a fix to a bug introduced in Go 1.8.4 that broke <code>go</code> <code>get</code>
|
|
||||||
of non-Git repositories under certain conditions.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.8.5">Go
|
|
||||||
1.8.5 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.8.6 (released 2018/01/22) includes the same fix in <code>math/big</code>
|
|
||||||
as Go 1.9.3 and was released at the same time.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.8.6">Go
|
|
||||||
1.8.6 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.8.7 (released 2018/02/07) includes a security fix to “go get”.
|
|
||||||
It contains the same fix as Go 1.9.4 and was released at the same time.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.8.7">Go
|
|
||||||
1.8.7</a> milestone on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h2 id="go1.7">go1.7 (released 2016/08/15)</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Go 1.7 is a major release of Go.
|
|
||||||
Read the <a href="/doc/go1.7">Go 1.7 Release Notes</a> for more information.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="go1.7.minor">Minor revisions</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.7.1 (released 2016/09/07) includes fixes to the compiler, runtime,
|
|
||||||
documentation, and the <code>compress/flate</code>, <code>hash/crc32</code>,
|
|
||||||
<code>io</code>, <code>net</code>, <code>net/http</code>,
|
|
||||||
<code>path/filepath</code>, <code>reflect</code>, and <code>syscall</code>
|
|
||||||
packages.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.7.1">Go
|
|
||||||
1.7.1 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
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.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>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.7.5 (released 2017/01/26) includes fixes to the compiler, runtime,
|
|
||||||
and the <code>crypto/x509</code> and <code>time</code> packages.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.7.5">Go
|
|
||||||
1.7.5 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.7.6 (released 2017/05/23) includes the same security fix as Go 1.8.2 and
|
|
||||||
was released at the same time.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.8.2">Go
|
|
||||||
1.8.2 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h2 id="go1.6">go1.6 (released 2016/02/17)</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Go 1.6 is a major release of Go.
|
|
||||||
Read the <a href="/doc/go1.6">Go 1.6 Release Notes</a> for more information.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="go1.6.minor">Minor revisions</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.6.1 (released 2016/04/12) includes two security fixes.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.6.1">Go
|
|
||||||
1.6.1 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.6.2 (released 2016/04/20) includes fixes to the compiler, runtime, tools,
|
|
||||||
documentation, and the <code>mime/multipart</code>, <code>net/http</code>, and
|
|
||||||
<code>sort</code> packages.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.6.2">Go
|
|
||||||
1.6.2 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.6.3 (released 2016/07/17) includes security fixes to the
|
|
||||||
<code>net/http/cgi</code> package and <code>net/http</code> package when used in
|
|
||||||
a CGI environment.
|
|
||||||
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>
|
|
||||||
Go 1.5 is a major release of Go.
|
|
||||||
Read the <a href="/doc/go1.5">Go 1.5 Release Notes</a> for more information.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="go1.5.minor">Minor revisions</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.5.1 (released 2015/09/08) includes bug fixes to the compiler, assembler, and
|
|
||||||
the <code>fmt</code>, <code>net/textproto</code>, <code>net/http</code>, and
|
|
||||||
<code>runtime</code> packages.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.5.1">Go
|
|
||||||
1.5.1 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.5.2 (released 2015/12/02) includes bug fixes to the compiler, linker, and
|
|
||||||
the <code>mime/multipart</code>, <code>net</code>, and <code>runtime</code>
|
|
||||||
packages.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.5.2">Go
|
|
||||||
1.5.2 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.5.3 (released 2016/01/13) includes a security fix to the <code>math/big</code> package
|
|
||||||
affecting the <code>crypto/tls</code> package.
|
|
||||||
See the <a href="https://golang.org/s/go153announce">release announcement</a> for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.5.4 (released 2016/04/12) includes two security fixes.
|
|
||||||
It contains the same fixes as Go 1.6.1 and was released at the same time.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.6.1">Go
|
|
||||||
1.6.1 milestone</a> on our issue tracker for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h2 id="go1.4">go1.4 (released 2014/12/10)</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Go 1.4 is a major release of Go.
|
|
||||||
Read the <a href="/doc/go1.4">Go 1.4 Release Notes</a> for more information.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="go1.4.minor">Minor revisions</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.4.1 (released 2015/01/15) includes bug fixes to the linker and the <code>log</code>, <code>syscall</code>, and <code>runtime</code> packages.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.4.1">Go 1.4.1 milestone on our issue tracker</a> for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.4.2 (released 2015/02/17) includes bug fixes to the <code>go</code> command, the compiler and linker, and the <code>runtime</code>, <code>syscall</code>, <code>reflect</code>, and <code>math/big</code> packages.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.4.2">Go 1.4.2 milestone on our issue tracker</a> for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.4.3 (released 2015/09/22) includes security fixes to the <code>net/http</code> package and bug fixes to the <code>runtime</code> package.
|
|
||||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.4.3">Go 1.4.3 milestone on our issue tracker</a> for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h2 id="go1.3">go1.3 (released 2014/06/18)</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Go 1.3 is a major release of Go.
|
|
||||||
Read the <a href="/doc/go1.3">Go 1.3 Release Notes</a> for more information.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="go1.3.minor">Minor revisions</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.3.1 (released 2014/08/13) includes bug fixes to the compiler and the <code>runtime</code>, <code>net</code>, and <code>crypto/rsa</code> packages.
|
|
||||||
See the <a href="https://github.com/golang/go/commits/go1.3.1">change history</a> for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.3.2 (released 2014/09/25) includes bug fixes to cgo and the crypto/tls packages.
|
|
||||||
See the <a href="https://github.com/golang/go/commits/go1.3.2">change history</a> for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.3.3 (released 2014/09/30) includes further bug fixes to cgo, the runtime package, and the nacl port.
|
|
||||||
See the <a href="https://github.com/golang/go/commits/go1.3.3">change history</a> for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h2 id="go1.2">go1.2 (released 2013/12/01)</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Go 1.2 is a major release of Go.
|
|
||||||
Read the <a href="/doc/go1.2">Go 1.2 Release Notes</a> for more information.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="go1.2.minor">Minor revisions</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.2.1 (released 2014/03/02) includes bug fixes to the <code>runtime</code>, <code>net</code>, and <code>database/sql</code> packages.
|
|
||||||
See the <a href="https://github.com/golang/go/commits/go1.2.1">change history</a> for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.2.2 (released 2014/05/05) includes a
|
|
||||||
<a href="https://github.com/golang/go/commits/go1.2.2">security fix</a>
|
|
||||||
that affects the tour binary included in the binary distributions (thanks to Guillaume T).
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h2 id="go1.1">go1.1 (released 2013/05/13)</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Go 1.1 is a major release of Go.
|
|
||||||
Read the <a href="/doc/go1.1">Go 1.1 Release Notes</a> for more information.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="go1.1.minor">Minor revisions</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.1.1 (released 2013/06/13) includes several compiler and runtime bug fixes.
|
|
||||||
See the <a href="https://github.com/golang/go/commits/go1.1.1">change history</a> for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.1.2 (released 2013/08/13) includes fixes to the <code>gc</code> compiler
|
|
||||||
and <code>cgo</code>, and the <code>bufio</code>, <code>runtime</code>,
|
|
||||||
<code>syscall</code>, and <code>time</code> packages.
|
|
||||||
See the <a href="https://github.com/golang/go/commits/go1.1.2">change history</a> for details.
|
|
||||||
If you use package syscall's <code>Getrlimit</code> and <code>Setrlimit</code>
|
|
||||||
functions under Linux on the ARM or 386 architectures, please note change
|
|
||||||
<a href="//golang.org/cl/11803043">11803043</a>
|
|
||||||
that fixes <a href="//golang.org/issue/5949">issue 5949</a>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h2 id="go1">go1 (released 2012/03/28)</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Go 1 is a major release of Go that will be stable in the long term.
|
|
||||||
Read the <a href="/doc/go1.html">Go 1 Release Notes</a> for more information.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
It is intended that programs written for Go 1 will continue to compile and run
|
|
||||||
correctly, unchanged, under future versions of Go 1.
|
|
||||||
Read the <a href="/doc/go1compat.html">Go 1 compatibility document</a> for more
|
|
||||||
about the future of Go 1.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The go1 release corresponds to
|
|
||||||
<code><a href="weekly.html#2012-03-27">weekly.2012-03-27</a></code>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="go1.minor">Minor revisions</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.0.1 (released 2012/04/25) was issued to
|
|
||||||
<a href="//golang.org/cl/6061043">fix</a> an
|
|
||||||
<a href="//golang.org/issue/3545">escape analysis bug</a>
|
|
||||||
that can lead to memory corruption.
|
|
||||||
It also includes several minor code and documentation fixes.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.0.2 (released 2012/06/13) was issued to fix two bugs in the implementation
|
|
||||||
of maps using struct or array keys:
|
|
||||||
<a href="//golang.org/issue/3695">issue 3695</a> and
|
|
||||||
<a href="//golang.org/issue/3573">issue 3573</a>.
|
|
||||||
It also includes many minor code and documentation fixes.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
go1.0.3 (released 2012/09/21) includes minor code and documentation fixes.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
See the <a href="https://github.com/golang/go/commits/release-branch.go1">go1 release branch history</a> for the complete list of changes.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h2 id="pre.go1">Older releases</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
See the <a href="pre_go1.html">Pre-Go 1 Release History</a> page for notes
|
|
||||||
on earlier releases.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load diff
504
doc/go1.14.html
504
doc/go1.14.html
|
|
@ -24,10 +24,30 @@ Do not send CLs removing the interior tags from such phrases.
|
||||||
</strong>
|
</strong>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Module support in the <code>go</code> command is now ready for production use,
|
||||||
|
and we encourage all users to migrate to Go modules for dependency management.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If you are unable to migrate due to a problem in the Go toolchain,
|
||||||
|
please ensure that the problem has an
|
||||||
|
<a href="https://golang.org/issue?q=is%3Aissue+is%3Aopen+label%3Amodules">open issue</a>
|
||||||
|
filed. (If the issue is not on the <code>Go1.15</code> milestone, please let us
|
||||||
|
know why it prevents you from migrating so that we can prioritize it
|
||||||
|
appropriately.)
|
||||||
|
</p>
|
||||||
|
|
||||||
<h2 id="language">Changes to the language</h2>
|
<h2 id="language">Changes to the language</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
TODO
|
Per the <a href="https://github.com/golang/proposal/blob/master/design/6977-overlapping-interfaces.md">overlapping interfaces proposal</a>,
|
||||||
|
Go 1.14 now permits embedding of interfaces with overlapping method sets:
|
||||||
|
methods from an embedded interface may have the same names and identical signatures
|
||||||
|
as methods already present in the (embedding) interface. This solves problems that typically
|
||||||
|
(but not exclusively) occur with diamond-shaped embedding graphs.
|
||||||
|
Explicitly declared methods in an interface must remain
|
||||||
|
<a href="https://tip.golang.org/ref/spec#Uniqueness_of_identifiers">unique</a>, as before.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2 id="ports">Ports</h2>
|
<h2 id="ports">Ports</h2>
|
||||||
|
|
@ -52,6 +72,11 @@ TODO
|
||||||
|
|
||||||
<h3 id="darwin">Darwin</h3>
|
<h3 id="darwin">Darwin</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Go 1.14 is the last release that will run on macOS 10.11 El Capitan.
|
||||||
|
Go 1.15 will require macOS 10.12 Sierra or later.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p><!-- golang.org/issue/34749 -->
|
<p><!-- golang.org/issue/34749 -->
|
||||||
Go 1.14 is the last Go release to support 32-bit binaries on
|
Go 1.14 is the last Go release to support 32-bit binaries on
|
||||||
macOS (the <code>darwin/386</code> port). They are no longer
|
macOS (the <code>darwin/386</code> port). They are no longer
|
||||||
|
|
@ -66,6 +91,49 @@ TODO
|
||||||
64-bit <code>darwin/arm64</code> port.
|
64-bit <code>darwin/arm64</code> port.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<h3 id="windows">Windows</h3>
|
||||||
|
|
||||||
|
<p><!-- CL 203601 -->
|
||||||
|
Go binaries on Windows now
|
||||||
|
have <a href="https://docs.microsoft.com/en-us/windows/win32/memory/data-execution-prevention">DEP
|
||||||
|
(Data Execution Prevention)</a> enabled.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="wasm">WebAssembly</h3>
|
||||||
|
|
||||||
|
<p><!-- CL 203600 -->
|
||||||
|
JavaScript values referenced from Go via <code>js.Value</code>
|
||||||
|
objects can now be garbage collected.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 203600 -->
|
||||||
|
<code>js.Value</code> values can no longer be compared using
|
||||||
|
the <code>==</code> operator, and instead must be compared using
|
||||||
|
their <code>Equal</code> method.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 203600 -->
|
||||||
|
<code>js.Value</code> now
|
||||||
|
has <code>IsUndefined</code>, <code>IsNull</code>,
|
||||||
|
and <code>IsNaN</code> methods.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="riscv">RISC-V</h3>
|
||||||
|
|
||||||
|
<p><!-- Issue 27532 -->
|
||||||
|
Go 1.14 contains experimental support for 64-bit RISC-V on Linux
|
||||||
|
(<code>GOOS=linux</code>, <code>GOARCH=riscv64</code>). Be aware
|
||||||
|
that performance, assembly syntax stability, and possibly
|
||||||
|
correctness are a work in progress.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="freebsd">FreeBSD</h3>
|
||||||
|
|
||||||
|
<p><!-- CL 199919 -->
|
||||||
|
Go now supports the 64-bit ARM architecture on FreeBSD (the
|
||||||
|
<code>freebsd/arm64</code> port).
|
||||||
|
</p>
|
||||||
|
|
||||||
<h3 id="nacl">Native Client (NaCl)</h3>
|
<h3 id="nacl">Native Client (NaCl)</h3>
|
||||||
|
|
||||||
<p><!-- golang.org/issue/30439 -->
|
<p><!-- golang.org/issue/30439 -->
|
||||||
|
|
@ -73,12 +141,17 @@ TODO
|
||||||
Go 1.14 drops support for the Native Client platform (<code>GOOS=nacl</code>).
|
Go 1.14 drops support for the Native Client platform (<code>GOOS=nacl</code>).
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2 id="tools">Tools</h2>
|
<h3 id="illumos">Illumos</h3>
|
||||||
|
|
||||||
<p>
|
<p><!-- CL 203758 -->
|
||||||
TODO
|
The runtime now respects zone CPU caps
|
||||||
|
(the <code>zone.cpu-cap</code> resource control)
|
||||||
|
for <code>runtime.NumCPU</code> and the default value
|
||||||
|
of <code>GOMAXPROCS</code>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<h2 id="tools">Tools</h2>
|
||||||
|
|
||||||
<h3 id="go-command">Go command</h3>
|
<h3 id="go-command">Go command</h3>
|
||||||
|
|
||||||
<h4 id="vendor">Vendoring</h4>
|
<h4 id="vendor">Vendoring</h4>
|
||||||
|
|
@ -105,7 +178,8 @@ TODO
|
||||||
<code>go</code> <code>list</code> <code>-m</code> no longer silently omits
|
<code>go</code> <code>list</code> <code>-m</code> no longer silently omits
|
||||||
transitive dependencies that do not provide packages in
|
transitive dependencies that do not provide packages in
|
||||||
the <code>vendor</code> directory. It now fails explicitly if
|
the <code>vendor</code> directory. It now fails explicitly if
|
||||||
<code>-mod=vendor</code> is set.
|
<code>-mod=vendor</code> is set and information is requested for a module not
|
||||||
|
mentioned in <code>vendor/modules.txt</code>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h4 id="go-flags">Flags</h4>
|
<h4 id="go-flags">Flags</h4>
|
||||||
|
|
@ -117,6 +191,11 @@ TODO
|
||||||
<a href="https://golang.org/issue/32502">caused the build to fail</a>.
|
<a href="https://golang.org/issue/32502">caused the build to fail</a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p><!-- golang.org/issue/33326 -->
|
||||||
|
<code>-mod=readonly</code> is now set by default when the <code>go.mod</code>
|
||||||
|
file is read-only and no top-level <code>vendor</code> directory is present.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p><!-- golang.org/issue/31481 -->
|
<p><!-- golang.org/issue/31481 -->
|
||||||
<code>-modcacherw</code> is a new flag that instructs the <code>go</code>
|
<code>-modcacherw</code> is a new flag that instructs the <code>go</code>
|
||||||
command to leave newly-created directories in the module cache at their
|
command to leave newly-created directories in the module cache at their
|
||||||
|
|
@ -130,12 +209,48 @@ TODO
|
||||||
|
|
||||||
<p><!-- golang.org/issue/34506 -->
|
<p><!-- golang.org/issue/34506 -->
|
||||||
<code>-modfile=file</code> is a new flag that instructs the <code>go</code>
|
<code>-modfile=file</code> is a new flag that instructs the <code>go</code>
|
||||||
command to read (and possibly write) an alternate go.mod file instead of the
|
command to read (and possibly write) an alternate <code>go.mod</code> file
|
||||||
one in the module root directory. A file named "go.mod" must still be present
|
instead of the one in the module root directory. A file
|
||||||
in order to determine the module root directory, but it is not
|
named <code>go.mod</code> must still be present in order to determine the
|
||||||
accessed. When <code>-modfile</code> is specified, an alternate go.sum file
|
module root directory, but it is not accessed. When <code>-modfile</code> is
|
||||||
is also used: its path is derived from the <code>-modfile</code> flag by
|
specified, an alternate <code>go.sum</code> file is also used: its path is
|
||||||
trimming the ".mod" extension and appending ".sum".
|
derived from the <code>-modfile</code> flag by trimming the <code>.mod</code>
|
||||||
|
extension and appending <code>.sum</code>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h4 id="go-env-vars">Environment variables</h4>
|
||||||
|
|
||||||
|
<p><!-- golang.org/issue/32966 -->
|
||||||
|
<code>GOINSECURE</code> is a new environment variable that instructs
|
||||||
|
the <code>go</code> command to not require an HTTPS connection, and to skip
|
||||||
|
certificate validation, when fetching certain modules directly from their
|
||||||
|
origins. Like the existing <code>GOPRIVATE</code> variable, the value
|
||||||
|
of <code>GOINSECURE</code> is a comma-separated list of glob patterns.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h4 id="commands-outside-modules">Commands outside modules</h4>
|
||||||
|
|
||||||
|
<p><!-- golang.org/issue/32027 -->
|
||||||
|
When module-aware mode is enabled explicitly (by setting
|
||||||
|
<code>GO111MODULE=on</code>), most module commands have more
|
||||||
|
limited functionality if no <code>go.mod</code> file is present. For
|
||||||
|
example, <code>go</code> <code>build</code>,
|
||||||
|
<code>go</code> <code>run</code>, and other build commands can only build
|
||||||
|
packages in the standard library and packages specified as <code>.go</code>
|
||||||
|
files on the command line.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Previously, the <code>go</code> command would resolve each package path
|
||||||
|
to the latest version of a module but would not record the module path
|
||||||
|
or version. This resulted in <a href="https://golang.org/issue/32027">slow,
|
||||||
|
non-reproducible builds</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<code>go</code> <code>get</code> continues to work as before, as do
|
||||||
|
<code>go</code> <code>mod</code> <code>download</code> and
|
||||||
|
<code>go</code> <code>list</code> <code>-m</code> with explicit versions.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h4 id="incompatible-versions"><code>+incompatible</code> versions</h4>
|
<h4 id="incompatible-versions"><code>+incompatible</code> versions</h4>
|
||||||
|
|
@ -152,6 +267,30 @@ TODO
|
||||||
include them if reported by a proxy.
|
include them if reported by a proxy.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<h4 id="go.mod"><code>go.mod</code> file maintenance</h4>
|
||||||
|
<!-- golang.org/issue/34822 -->
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<code>go</code> commands other than
|
||||||
|
<code>go</code> <code>mod</code> <code>tidy</code> no longer
|
||||||
|
remove a <code>require</code> directive that specifies a version of an indirect dependency
|
||||||
|
that is already implied by other (transitive) dependencies of the main
|
||||||
|
module.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<code>go</code> commands other than
|
||||||
|
<code>go</code> <code>mod</code> <code>tidy</code> no longer
|
||||||
|
edit the <code>go.mod</code> file if the changes are only cosmetic.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
When <code>-mod=readonly</code> is set, <code>go</code> commands will no
|
||||||
|
longer fail due to a missing <code>go</code> directive or an erroneous
|
||||||
|
<code>// indirect</code> comment.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h4 id="module-downloading">Module downloading</h4>
|
<h4 id="module-downloading">Module downloading</h4>
|
||||||
|
|
||||||
<p><!-- golang.org/issue/26092 -->
|
<p><!-- golang.org/issue/26092 -->
|
||||||
|
|
@ -165,10 +304,54 @@ TODO
|
||||||
graphic characters and spaces.
|
graphic characters and spaces.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<h4 id="go-test">Testing</h4>
|
||||||
|
|
||||||
|
<p><!-- golang.org/issue/24929 -->
|
||||||
|
<code>go test -v</code> now streams <code>t.Log</code> output as it happens,
|
||||||
|
rather than at the end of all tests.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h2 id="runtime">Runtime</h2>
|
<h2 id="runtime">Runtime</h2>
|
||||||
|
|
||||||
|
<p><!-- CL 190098 -->
|
||||||
|
This release improves the performance of most uses
|
||||||
|
of <code>defer</code> to incur almost zero overhead compared to
|
||||||
|
calling the deferred function directly.
|
||||||
|
As a result, <code>defer</code> can now be used in
|
||||||
|
performance-critical code without overhead concerns.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 201760, CL 201762 and many others -->
|
||||||
|
Goroutines are now asynchronously preemptible.
|
||||||
|
As a result, loops without function calls no longer potentially
|
||||||
|
deadlock the scheduler or significantly delay garbage collection.
|
||||||
|
This is supported on all platforms except <code>windows/arm</code>,
|
||||||
|
<code>darwin/arm</code>, <code>js/wasm</code>, and
|
||||||
|
<code>plan9/*</code>.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
TODO
|
A consequence of the implementation of preemption is that on Unix
|
||||||
|
systems, including Linux and macOS systems, programs built with Go
|
||||||
|
1.14 will receive more signals than programs built with earlier
|
||||||
|
releases.
|
||||||
|
This means that programs that use packages
|
||||||
|
like <a href="/pkg/syscall/"><code>syscall</code></a>
|
||||||
|
or <a href="https://godoc.org/golang.org/x/sys/unix"><code>golang.org/x/sys/unix</code></a>
|
||||||
|
will see more slow system calls fail with <code>EINTR</code> errors.
|
||||||
|
Those programs will have to handle those errors in some way, most
|
||||||
|
likely looping to try the system call again. For more
|
||||||
|
information about this
|
||||||
|
see <a href="http://man7.org/linux/man-pages/man7/signal.7.html"><code>man
|
||||||
|
7 signal</code></a> for Linux systems or similar documentation for
|
||||||
|
other systems.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 201765, CL 195701 and many others -->
|
||||||
|
The page allocator is more efficient and incurs significantly less
|
||||||
|
lock contention at high values of <code>GOMAXPROCS</code>.
|
||||||
|
This is most noticeable as lower latency and higher throughput for
|
||||||
|
large allocations being done in parallel and at a high rate.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><!-- CL 171844 and many others -->
|
<p><!-- CL 171844 and many others -->
|
||||||
|
|
@ -182,19 +365,82 @@ TODO
|
||||||
visible changes.
|
visible changes.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<!-- TODO: Maybe CL 200439? -->
|
||||||
|
|
||||||
|
<h2 id="compiler">Compiler</h2>
|
||||||
|
|
||||||
|
<p><!-- CL 162237 -->
|
||||||
|
This release adds <code>-d=checkptr</code> as a compile-time option
|
||||||
|
for adding instrumentation to check that Go code is following
|
||||||
|
<code>unsafe.Pointer</code> safety rules dynamically.
|
||||||
|
This option is enabled by default (except on Windows) with
|
||||||
|
the <code>-race</code> or <code>-msan</code> flags, and can be
|
||||||
|
disabled with <code>-gcflags=all=-d=checkptr=0</code>.
|
||||||
|
Specifically, <code>-d=checkptr</code> checks the following:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ol>
|
||||||
|
<li>
|
||||||
|
When converting <code>unsafe.Pointer</code> to <code>*T</code>,
|
||||||
|
the resulting pointer must be aligned appropriately
|
||||||
|
for <code>T</code>.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
If the result of pointer arithmetic points into a Go heap object,
|
||||||
|
one of the <code>unsafe.Pointer</code>-typed operands must point
|
||||||
|
into the same object.
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Using <code>-d=checkptr</code> is not currently recommended on
|
||||||
|
Windows because it causes false alerts in the standard library.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 204338 -->
|
||||||
|
The compiler can now emit machine-readable logs of key optimizations
|
||||||
|
using the <code>-json</code> flag, including inlining, escape
|
||||||
|
analysis, bounds-check elimination, and nil-check elimination
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 196959 -->
|
||||||
|
Detailed escape analysis diagnostics (<code>-m=2</code>) now work again.
|
||||||
|
This had been dropped from the new escape analysis implementation in
|
||||||
|
the previous release.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 196217 -->
|
||||||
|
All Go symbols in macOS binaries now begin with an underscore,
|
||||||
|
following platform conventions.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 202117 -->
|
||||||
|
This release includes experimental support for compiler-inserted
|
||||||
|
coverage instrumentation for fuzzing.
|
||||||
|
See <a href="https://golang.org/issue/14565">the issue</a> for more
|
||||||
|
details.
|
||||||
|
This API may change in future releases.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h2 id="library">Core library</h2>
|
<h2 id="library">Core library</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
TODO
|
TODO
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<dl id="bytes/hash"><dt><a href="/pkg/bytes/hash/">bytes/hash</a></dt>
|
<dl id="hash/maphash"><dt><a href="/pkg/hash/maphash">hash/maphash</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p><!-- CL 186877 -->
|
<p><!-- CL 186877 -->
|
||||||
TODO: <a href="https://golang.org/cl/186877">https://golang.org/cl/186877</a>: add hashing package for bytes and strings
|
This new package provides hash functions on byte sequences.
|
||||||
|
These hash functions are intended to be used to implement hash tables or
|
||||||
|
other data structures that need to map arbitrary strings or byte
|
||||||
|
sequences to a uniform distribution of integers.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The hash functions are collision-resistant but not cryptographically secure.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</dl><!-- bytes/hash -->
|
</dl><!-- hash/maphash -->
|
||||||
|
|
||||||
<dl id="crypto/tls"><dt><a href="/pkg/crypto/tls/">crypto/tls</a></dt>
|
<dl id="crypto/tls"><dt><a href="/pkg/crypto/tls/">crypto/tls</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
|
|
@ -224,13 +470,60 @@ TODO
|
||||||
|
|
||||||
</dl><!-- encoding/asn1 -->
|
</dl><!-- encoding/asn1 -->
|
||||||
|
|
||||||
<dl id="mime"><dt><a href="/pkg/mime/">mime</a></dt>
|
<dl id="encoding/json"><dt><a href="/pkg/encoding/json/">encoding/json</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p><!-- CL 186927 -->
|
<p><!-- CL 200217 -->
|
||||||
TODO: <a href="https://golang.org/cl/186927">https://golang.org/cl/186927</a>: update type of .js and .mjs files to text/javascript
|
<a href="/pkg/encoding/json/#Compact"><code>Compact</code></a> no longer
|
||||||
|
escapes the <code>U+2028</code> and <code>U+2029</code> characters, which
|
||||||
|
was never a documented feature. For proper escaping, see <a
|
||||||
|
href="/pkg/encoding/json/#HTMLEscape"><code>HTMLEscape</code></a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</dl><!-- mime -->
|
</dl><!-- encoding/json -->
|
||||||
|
|
||||||
|
<dl id="go/build"><dt><a href="/pkg/go/build/">go/build</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 203820, 211657 -->
|
||||||
|
The <a href="/pkg/go/build/#Context"><code>Context</code></a>
|
||||||
|
type has a new field <code>Dir</code> which may be used to set
|
||||||
|
the working directory for the build.
|
||||||
|
The default is the current directory of the running process.
|
||||||
|
In module mode, this is used to locate the main module.
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- go/build -->
|
||||||
|
|
||||||
|
<dl id="log"><dt><a href="/pkg/log/">log</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 186182 -->
|
||||||
|
The
|
||||||
|
new <a href="https://tip.golang.org/pkg/log/#pkg-constants"><code>Lmsgprefix</code></a>
|
||||||
|
flag may be used to tell the logging functions to emit the
|
||||||
|
optional output prefix immediately before the log message rather
|
||||||
|
than at the start of the line.
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- log -->
|
||||||
|
|
||||||
|
<dl id="go/doc"><dt><a href="/go/doc/">go/doc</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 204830 -->
|
||||||
|
The new
|
||||||
|
function <a href="/pkg/go/doc/#NewFromFiles"><code>NewFromFiles</code></a>
|
||||||
|
computes package documentation from a list
|
||||||
|
of <code>*ast.File</code>'s and associates examples with the
|
||||||
|
appropriate package elements.
|
||||||
|
The new information is available in a new <code>Examples</code>
|
||||||
|
field
|
||||||
|
in the <a href="/pkg/go/doc/#Package"><code>Package</code></a>, <a href="/pkg/go/doc/#Type"><code>Type</code></a>,
|
||||||
|
and <a href="/pkg/go/doc/#Func"><code>Func</code></a> types, and a
|
||||||
|
new <a href="/pkg/go/doc/#Example.Suffix"><code>Suffix</code></a>
|
||||||
|
field in
|
||||||
|
the <a href="/pkg/go/doc/#Example"><code>Example</code></a>
|
||||||
|
type.
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- go/doc -->
|
||||||
|
|
||||||
<dl id="math"><dt><a href="/pkg/math/">math</a></dt>
|
<dl id="math"><dt><a href="/pkg/math/">math</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
|
|
@ -244,10 +537,105 @@ TODO
|
||||||
|
|
||||||
</dl><!-- math -->
|
</dl><!-- math -->
|
||||||
|
|
||||||
|
<dl id="math/big"><dt><a href="/pkg/math/big">math/big</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 164972 -->
|
||||||
|
The <a href="/pkg/math/big/#GCD"><code>GCD</code></a> function
|
||||||
|
now allows the inputs <code>a</code> and <code>b</code> to be
|
||||||
|
zero or negative.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</dl><!-- math/big -->
|
||||||
|
|
||||||
|
<dl id="math/bits"><dt><a href="/pkg/math/bits/">math/bits</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 197838 -->
|
||||||
|
The new functions
|
||||||
|
<a href="/pkg/math/bits/#Rem"><code>Rem</code></a>,
|
||||||
|
<a href="/pkg/math/bits/#Rem32"><code>Rem32</code></a>, and
|
||||||
|
<a href="/pkg/math/bits/#Rem64"><code>Rem64</code></a>
|
||||||
|
support computing a remainder even when the quotient overflows.
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- math/bits -->
|
||||||
|
|
||||||
|
<dl id="mime"><dt><a href="/pkg/mime/">mime</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 186927 -->
|
||||||
|
The default type of <code>.js</code> and <code>.mjs</code> files
|
||||||
|
is now <code>text/javascript</code> rather
|
||||||
|
than <code>application/javascript</code>.
|
||||||
|
This is in accordance
|
||||||
|
with <a href="https://datatracker.ietf.org/doc/draft-ietf-dispatch-javascript-mjs/">an
|
||||||
|
IETF draft</a> that treats <code>application/javascript</code> as obsolete.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</dl><!-- mime -->
|
||||||
|
|
||||||
|
<dl id="mime/multipart"><dt><a href="/pkg/mime/multipart/">mime/multipart</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p>
|
||||||
|
The
|
||||||
|
new <a href="/pkg/mime/multipart/#Reader"><code>Reader</code></a>
|
||||||
|
method <a href="/pkg/mime/multipart/#Reader.NextRawPart"><code>NextRawPart</code></a>
|
||||||
|
supports fetching the next MIME part without transparently
|
||||||
|
decoding <code>quoted-printable</code> data.
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- mime/multipart -->
|
||||||
|
|
||||||
|
<dl id="net/http"><dt><a href="/pkg/net/http/">net/http</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 200760 -->
|
||||||
|
The new <a href="/pkg/net/http/#Header"><code>Header</code></a>
|
||||||
|
method <a href="/pkg/net/http/#Header.Values"><code>Values</code></a>
|
||||||
|
can be used to fetch all values associated with a
|
||||||
|
canonicalized key.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 61291 -->
|
||||||
|
The
|
||||||
|
new <a href="/pkg/net/http/#Transport"><code>Transport</code></a>
|
||||||
|
field <a href="/pkg/net/http/#Transport.DialTLSContext"><code>DialTLSContext</code></a>
|
||||||
|
can be used to specify an optional dial function for creating
|
||||||
|
TLS connections for non-proxied HTTPS requests.
|
||||||
|
This new field can be used instead
|
||||||
|
of <a href="/pkg/net/http/#Transport.DialTLS"><code>DialTLS</code></a>,
|
||||||
|
which is now considered deprecated; <code>DialTLS</code> will
|
||||||
|
continue to work, but new code should
|
||||||
|
use <code>DialTLSContext</code>, which allows the transport to
|
||||||
|
cancel dials as soon as they are no longer needed.
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- net/http -->
|
||||||
|
|
||||||
|
<dl id="net/http/httptest"><dt><a href="/net/http/httptest/">net/http/httptest</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 201557 -->
|
||||||
|
The
|
||||||
|
new <a href="/pkg/net/http/httptest/#Server"><code>Server</code></a>
|
||||||
|
field <a href="/pkg/net/http/httptest/#Server.EnableHTTP2"><code>EnableHTTP2</code></a>
|
||||||
|
supports enabling HTTP/2 on the test server.
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- net/http/httptest -->
|
||||||
|
|
||||||
|
<dl id="net/textproto"><dt><a href="/pkg/net/textproto/">net/textproto</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 200760 -->
|
||||||
|
The
|
||||||
|
new <a href="/pkg/net/textproto/#MIMEHeader"><code>MIMEHeader</code></a>
|
||||||
|
method <a href="/pkg/net/textproto/#MIMEHeader.Values"><code>Values</code></a>
|
||||||
|
can be used to fetch all values associated with a canonicalized
|
||||||
|
key.
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- net/textproto -->
|
||||||
|
|
||||||
<dl id="plugin"><dt><a href="/pkg/plugin/">plugin</a></dt>
|
<dl id="plugin"><dt><a href="/pkg/plugin/">plugin</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p><!-- CL 191617 -->
|
<p><!-- CL 191617 -->
|
||||||
TODO: <a href="https://golang.org/cl/191617">https://golang.org/cl/191617</a>: add freebsd/amd64 plugin support
|
The <code>plugin</code> package now supports <code>freebsd/amd64</code>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</dl><!-- plugin -->
|
</dl><!-- plugin -->
|
||||||
|
|
@ -267,16 +655,73 @@ TODO
|
||||||
|
|
||||||
<dl id="runtime"><dt><a href="/pkg/runtime/">runtime</a></dt>
|
<dl id="runtime"><dt><a href="/pkg/runtime/">runtime</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p><!-- CL 187739 -->
|
<p><!-- CL 200081 -->
|
||||||
TODO: <a href="https://golang.org/cl/187739">https://golang.org/cl/187739</a>: treat CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT, CTRL_SHUTDOWN_EVENT as SIGTERM on Windows
|
<code>runtime.Goexit</code> can no longer be aborted by a
|
||||||
|
recursive <code>panic</code>/<code>recover</code>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><!-- CL 188297 -->
|
<p><!-- CL 188297, CL 191785 -->
|
||||||
TODO: <a href="https://golang.org/cl/188297">https://golang.org/cl/188297</a>: don't forward SIGPIPE on macOS
|
On macOS, <code>SIGPIPE</code> is no longer forwarded to signal
|
||||||
|
handlers installed before the Go runtime is initialized.
|
||||||
|
This is necessary because macOS delivers <code>SIGPIPE</code>
|
||||||
|
<a href="https://golang.org/issue/33384">to the main thread</a>
|
||||||
|
rather than the thread writing to the closed pipe.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</dl><!-- runtime -->
|
</dl><!-- runtime -->
|
||||||
|
|
||||||
|
<dl id="runtime/pprof"><dt><a href="/pkg/runtime/pprof">runtime/pprof</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 204636, 205097 -->
|
||||||
|
The generated profile no longer includes the pseudo-PCs used for inline
|
||||||
|
marks. Symbol information of inlined functions is encoded in
|
||||||
|
<a href="https://github.com/google/pprof/blob/5e96527/proto/profile.proto#L177-L184">the format</a>
|
||||||
|
the pprof tool expects. This is a fix for the regression introduced
|
||||||
|
during recent releases.
|
||||||
|
</p>
|
||||||
|
</dl><!-- runtime/pprof -->
|
||||||
|
|
||||||
|
<dl id="signal"><dt><a href="/pkg/signal/">signal</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 187739 -->
|
||||||
|
On Windows,
|
||||||
|
the <code>CTRL_CLOSE_EVENT</code>, <code>CTRL_LOGOFF_EVENT</code>,
|
||||||
|
and <code>CTRL_SHUTDOWN_EVENT</code> events now generate
|
||||||
|
a <code>syscall.SIGTERM</code> signal, similar to how Control-C
|
||||||
|
and Control-Break generate a <code>syscall.SIGINT</code> signal.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</dl><!-- signal -->
|
||||||
|
|
||||||
|
<dl id="strconv"><dt><a href="/pkg/strconv/">strconv</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p>
|
||||||
|
The <a href="/pkg/strconv/#NumError"><code>NumError</code></a>
|
||||||
|
type now has
|
||||||
|
an <a href="/pkg/strconv/#NumError.Unwrap"><code>Unwrap</code></a>
|
||||||
|
method that may be used to retrieve the reason that a conversion
|
||||||
|
failed.
|
||||||
|
This supports using <code>NumError</code> values
|
||||||
|
with <a href="/pkg/errors/#Is"><code>errors.Is</code></a> to see
|
||||||
|
if the underlying error
|
||||||
|
is <a href="/pkg/strconv/#pkg-variables"><code>strconv.ErrRange</code></a>
|
||||||
|
or <a href="/pkg/strconv/#pkg-variables"><code>strconv.ErrSyntax</code></a>.
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- strconv -->
|
||||||
|
|
||||||
|
<dl id="sync"><dt><a href="/pkg/sync/">sync</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 200577 -->
|
||||||
|
Unlocking a highly contended <code>Mutex</code> now directly
|
||||||
|
yields the CPU to the next goroutine waiting for
|
||||||
|
that <code>Mutex</code>. This significantly improves the
|
||||||
|
performance of highly contended mutexes on high CPU count
|
||||||
|
machines.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</dl><!-- sync -->
|
||||||
|
|
||||||
<dl id="testing"><dt><a href="/pkg/testing/">testing</a></dt>
|
<dl id="testing"><dt><a href="/pkg/testing/">testing</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p><!-- CL 201359 -->
|
<p><!-- CL 201359 -->
|
||||||
|
|
@ -287,6 +732,17 @@ TODO
|
||||||
</p>
|
</p>
|
||||||
</dl><!-- testing -->
|
</dl><!-- testing -->
|
||||||
|
|
||||||
|
<dl id="unicode"><dt><a href="/pkg/unicode/">unicode</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p>
|
||||||
|
The <a href="/pkg/unicode/"><code>unicode</code></a> package and associated
|
||||||
|
support throughout the system has been upgraded from Unicode 11.0 to
|
||||||
|
<a href="https://www.unicode.org/versions/Unicode12.0.0/">Unicode 12.0</a>,
|
||||||
|
which adds 554 new characters, including four new scripts, and 61 new emoji.
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- unicode -->
|
||||||
|
|
||||||
<h3 id="minor_library_changes">Minor changes to the library</h3>
|
<h3 id="minor_library_changes">Minor changes to the library</h3>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<!--{
|
<!--{
|
||||||
"Title": "The Go Programming Language Specification",
|
"Title": "The Go Programming Language Specification",
|
||||||
"Subtitle": "Version of Sep 4, 2019",
|
"Subtitle": "Version of Jan 14, 2020",
|
||||||
"Path": "/ref/spec"
|
"Path": "/ref/spec"
|
||||||
}-->
|
}-->
|
||||||
|
|
||||||
|
|
@ -20,8 +20,8 @@ dependencies.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The grammar is compact and regular, allowing for easy analysis by
|
The grammar is compact and simple to parse, allowing for easy analysis
|
||||||
automatic tools such as integrated development environments.
|
by automatic tools such as integrated development environments.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2 id="Notation">Notation</h2>
|
<h2 id="Notation">Notation</h2>
|
||||||
|
|
@ -2042,7 +2042,7 @@ of the last non-empty expression list.
|
||||||
<p>
|
<p>
|
||||||
A type declaration binds an identifier, the <i>type name</i>, to a <a href="#Types">type</a>.
|
A type declaration binds an identifier, the <i>type name</i>, to a <a href="#Types">type</a>.
|
||||||
Type declarations come in two forms: alias declarations and type definitions.
|
Type declarations come in two forms: alias declarations and type definitions.
|
||||||
<p>
|
</p>
|
||||||
|
|
||||||
<pre class="ebnf">
|
<pre class="ebnf">
|
||||||
TypeDecl = "type" ( TypeSpec | "(" { TypeSpec ";" } ")" ) .
|
TypeDecl = "type" ( TypeSpec | "(" { TypeSpec ";" } ")" ) .
|
||||||
|
|
@ -2553,7 +2553,7 @@ does not have the same effect as allocating a new slice or map value with
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
p1 := &[]int{} // p1 points to an initialized, empty slice with value []int{} and length 0
|
p1 := &[]int{} // p1 points to an initialized, empty slice with value []int{} and length 0
|
||||||
p2 := new([]int) // p2 points to an uninitialized slice with value nil and length 0
|
p2 := new([]int) // p2 points to an uninitialized slice with value nil and length 0
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
@ -3290,8 +3290,8 @@ array with the operand.
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
var a [10]int
|
var a [10]int
|
||||||
s1 := a[3:7] // underlying array of s1 is array a; &s1[2] == &a[5]
|
s1 := a[3:7] // underlying array of s1 is array a; &s1[2] == &a[5]
|
||||||
s2 := s1[1:4] // underlying array of s2 is underlying array of s1 which is array a; &s2[1] == &a[5]
|
s2 := s1[1:4] // underlying array of s2 is underlying array of s1 which is array a; &s2[1] == &a[5]
|
||||||
s2[1] = 42 // s2[1] == s1[2] == a[5] == 42; they all refer to the same underlying array element
|
s2[1] = 42 // s2[1] == s1[2] == a[5] == 42; they all refer to the same underlying array element
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -247,10 +247,12 @@ that if Go is checked out in <code>$HOME/go</code>, it will conflict with
|
||||||
the default location of <code>$GOPATH</code>.
|
the default location of <code>$GOPATH</code>.
|
||||||
See <a href="#gopath"><code>GOPATH</code></a> below.</p>
|
See <a href="#gopath"><code>GOPATH</code></a> below.</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
Reminder: If you opted to also compile the bootstrap binaries from source (in an
|
Reminder: If you opted to also compile the bootstrap binaries from source (in an
|
||||||
earlier section), you still need to <code>git clone</code> again at this point
|
earlier section), you still need to <code>git clone</code> again at this point
|
||||||
(to checkout the latest <code><tag></code>), because you must keep your
|
(to checkout the latest <code><tag></code>), because you must keep your
|
||||||
go1.4 repository distinct.
|
go1.4 repository distinct.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h2 id="head">(Optional) Switch to the master branch</h2>
|
<h2 id="head">(Optional) Switch to the master branch</h2>
|
||||||
|
|
||||||
|
|
|
||||||
164
doc/modules.md
164
doc/modules.md
|
|
@ -276,6 +276,10 @@ list. The `go` command does not fall back to later proxies in response to other
|
||||||
4xx and 5xx errors. This allows a proxy to act as a gatekeeper, for example, by
|
4xx and 5xx errors. This allows a proxy to act as a gatekeeper, for example, by
|
||||||
responding with error 403 (Forbidden) for modules not on an approved list.
|
responding with error 403 (Forbidden) for modules not on an approved list.
|
||||||
|
|
||||||
|
<!-- TODO(katiehockman): why only fall back for 410/404? Either add the details
|
||||||
|
here, or write a blog post about how to build multiple types of proxies. e.g.
|
||||||
|
a "privacy preserving one" and an "authorization one" -->
|
||||||
|
|
||||||
The table below specifies queries that a module proxy must respond to. For each
|
The table below specifies queries that a module proxy must respond to. For each
|
||||||
path, `$base` is the path portion of a proxy URL,`$module` is a module path, and
|
path, `$base` is the path portion of a proxy URL,`$module` is a module path, and
|
||||||
`$version` is a version. For example, if the proxy URL is
|
`$version` is a version. For example, if the proxy URL is
|
||||||
|
|
@ -425,12 +429,170 @@ setting `GOPROXY` to `https://example.com/proxy`.
|
||||||
<a id="authenticating"></a>
|
<a id="authenticating"></a>
|
||||||
## Authenticating modules
|
## Authenticating modules
|
||||||
|
|
||||||
|
<!-- TODO: continue this section -->
|
||||||
|
When deciding whether to trust the source code for a module version just
|
||||||
|
fetched from a proxy or origin server, the `go` command first consults the
|
||||||
|
`go.sum` lines in the `go.sum` file of the current module. If the `go.sum` file
|
||||||
|
does not contain an entry for that module version, then it may consult the
|
||||||
|
checksum database.
|
||||||
|
|
||||||
<a id="go.sum-file-format"></a>
|
<a id="go.sum-file-format"></a>
|
||||||
### go.sum file format
|
### go.sum file format
|
||||||
|
|
||||||
<a id="checksum-database"></a>
|
<a id="checksum-database"></a>
|
||||||
### Checksum database
|
### Checksum database
|
||||||
|
|
||||||
|
The checksum database is a global source of `go.sum` lines. The `go` command can
|
||||||
|
use this in many situations to detect misbehavior by proxies or origin servers.
|
||||||
|
|
||||||
|
The checksum database allows for global consistency and reliability for all
|
||||||
|
publicly available module versions. It makes untrusted proxies possible since
|
||||||
|
they can't serve the wrong code without it going unnoticed. It also ensures
|
||||||
|
that the bits associated with a specific version do not change from one day to
|
||||||
|
the next, even if the module's author subsequently alters the tags in their
|
||||||
|
repository.
|
||||||
|
|
||||||
|
The checksum database is served by [sum.golang.org](https://sum.golang.org),
|
||||||
|
which is run by Google. It is a [Transparent
|
||||||
|
Log](https://research.swtch.com/tlog) (or “Merkle Tree”) of `go.sum` line
|
||||||
|
hashes, which is backed by [Trillian](https://github.com/google/trillian). The
|
||||||
|
main advantage of a Merkle tree is that independent auditors can verify that it
|
||||||
|
hasn't been tampered with, so it is more trustworthy than a simple database.
|
||||||
|
|
||||||
|
The `go` command interacts with the checksum database using the protocol
|
||||||
|
originally outlined in [Proposal: Secure the Public Go Module
|
||||||
|
Ecosystem](https://go.googlesource.com/proposal/+/master/design/25530-sumdb.md#checksum-database).
|
||||||
|
|
||||||
|
The table below specifies queries that the checksum database must respond to.
|
||||||
|
For each path, `$base` is the path portion of the checksum database URL,
|
||||||
|
`$module` is a module path, and `$version` is a version. For example, if the
|
||||||
|
checksum database URL is `https://sum.golang.org`, and the client is requesting
|
||||||
|
the record for the module `golang.org/x/text` at version `v0.3.2`, the client
|
||||||
|
would send a `GET` request for
|
||||||
|
`https://sum.golang.org/lookup/golang.org/x/text@v0.3.2`.
|
||||||
|
|
||||||
|
To avoid ambiguity when serving from case-insensitive file systems,
|
||||||
|
the `$module` and `$version` elements are
|
||||||
|
[case-encoded](https://pkg.go.dev/golang.org/x/mod/module#EscapePath)
|
||||||
|
by replacing every uppercase letter with an exclamation mark followed by the
|
||||||
|
corresponding lower-case letter. This allows modules `example.com/M` and
|
||||||
|
`example.com/m` to both be stored on disk, since the former is encoded as
|
||||||
|
`example.com/!m`.
|
||||||
|
|
||||||
|
Parts of the path surrounded by square brakets, like `[.p/$W]` denote optional
|
||||||
|
values.
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Path</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><code>$base/latest</code></td>
|
||||||
|
<td>
|
||||||
|
Returns a signed, encoded tree description for the latest log. This
|
||||||
|
signed description is in the form of a
|
||||||
|
<a href="https://pkg.go.dev/golang.org/x/mod/sumdb/note">note</a>,
|
||||||
|
which is text that has been signed by one or more server keys and can
|
||||||
|
be verified using the server's public key. The tree description
|
||||||
|
provides the size of the tree and the hash of the tree head at that
|
||||||
|
size. This encoding is described in
|
||||||
|
<code><a href="https://pkg.go.dev/golang.org/x/mod/sumdb/tlog#FormatTree">
|
||||||
|
golang.org/x/mod/sumdb/tlog#FormatTree</a></code>.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>$base/lookup/$module@$version</code></td>
|
||||||
|
<td>
|
||||||
|
Returns the log record number for the entry about <code>$module</code>
|
||||||
|
at <code>$version</code>, followed by the data for the record (that is,
|
||||||
|
the <code>go.sum</code> lines for <code>$module</code> at
|
||||||
|
<code>$version</code>) and a signed, encoded tree description that
|
||||||
|
contains the record.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>$base/tile/$H/$L/$K[.p/$W]</code></td>
|
||||||
|
<td>
|
||||||
|
Returns a [log tile](https://research.swtch.com/tlog#serving_tiles),
|
||||||
|
which is a set of hashes that make up a section of the log. Each tile
|
||||||
|
is defined in a two-dimensional coordinate at tile level
|
||||||
|
<code>$L</code>, <code>$K</code>th from the left, with a tile height of
|
||||||
|
<code>$H</code>. The optional <code>.p/$W</code> suffix indicates a
|
||||||
|
partial log tile with only <code>$W</code> hashes. Clients must fall
|
||||||
|
back to fetching the full tile if a partial tile is not found.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>$base/tile/$H/data/$K[.p/$W]</code></td>
|
||||||
|
<td>
|
||||||
|
Returns the record data for the leaf hashes in
|
||||||
|
<code>/tile/$H/0/$K[.p/$W]</code> (with a literal <code>data</code> path
|
||||||
|
element).
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
If the `go` command consults the checksum database, then the first
|
||||||
|
step is to retrieve the record data through the `/lookup` endpoint. If the
|
||||||
|
module version is not yet recorded in the log, the checksum database will try
|
||||||
|
to fetch it from the origin server before replying. This `/lookup` data
|
||||||
|
provides the sum for this module version as well as its position in the log,
|
||||||
|
which informs the client of which tiles should be fetched to perform proofs.
|
||||||
|
The `go` command performs “inclusion” proofs (that a specific record exists in
|
||||||
|
the log) and “consistency” proofs (that the tree hasn’t been tampered with)
|
||||||
|
before adding new `go.sum` lines to the main module’s `go.sum` file. It's
|
||||||
|
important that the data from `/lookup` should never be used without first
|
||||||
|
authenticating it against the signed tree hash and authenticating the signed
|
||||||
|
tree hash against the client's timeline of signed tree hashes.
|
||||||
|
|
||||||
|
Signed tree hashes and new tiles served by the checksum database are stored
|
||||||
|
in the module cache, so the `go` command only needs to fetch tiles that are
|
||||||
|
missing.
|
||||||
|
|
||||||
|
The `go` command doesn't need to directly connect to the checksum database. It
|
||||||
|
can request module sums via a module proxy that
|
||||||
|
[mirrors the checksum database](https://go.googlesource.com/proposal/+/master/design/25530-sumdb.md#proxying-a-checksum-database)
|
||||||
|
and supports the protocol above. This can be particularly helpful for private,
|
||||||
|
corporate proxies which block requests outside the organization.
|
||||||
|
|
||||||
|
The `GOSUMDB` environment variable identifies the name of checksum database to use
|
||||||
|
and optionally its public key and URL, as in:
|
||||||
|
|
||||||
|
```
|
||||||
|
GOSUMDB="sum.golang.org"
|
||||||
|
GOSUMDB="sum.golang.org+<publickey>"
|
||||||
|
GOSUMDB="sum.golang.org+<publickey> https://sum.golang.org"
|
||||||
|
```
|
||||||
|
|
||||||
|
The `go` command knows the public key of `sum.golang.org`, and also that the
|
||||||
|
name `sum.golang.google.cn` (available inside mainland China) connects to the
|
||||||
|
`sum.golang.org` checksum database; use of any other database requires giving
|
||||||
|
the public key explicitly. The URL defaults to `https://` followed by the
|
||||||
|
database name.
|
||||||
|
|
||||||
|
`GOSUMDB` defaults to `sum.golang.org`, the Go checksum database run by Google.
|
||||||
|
See https://sum.golang.org/privacy for the service's privacy policy.
|
||||||
|
|
||||||
|
If `GOSUMDB` is set to `off`, or if `go get` is invoked with the `-insecure`
|
||||||
|
flag, the checksum database is not consulted, and all unrecognized modules are
|
||||||
|
accepted, at the cost of giving up the security guarantee of verified
|
||||||
|
repeatable downloads for all modules. A better way to bypass the checksum
|
||||||
|
database for specific modules is to use the `GOPRIVATE` or `GONOSUMDB`
|
||||||
|
environment variables. See [Private Modules](#private-modules) for details.
|
||||||
|
|
||||||
|
The `go env -w` command can be used to
|
||||||
|
[set these variables](/pkg/cmd/go/#hdr-Print_Go_environment_information)
|
||||||
|
for future `go` command invocations.
|
||||||
|
|
||||||
<a id="privacy"></a>
|
<a id="privacy"></a>
|
||||||
## Privacy
|
## Privacy
|
||||||
|
|
||||||
|
|
@ -449,7 +611,7 @@ using [minimal version selection](#glos-minimal-version-selection). The build
|
||||||
list contains versions for all modules in the [module
|
list contains versions for all modules in the [module
|
||||||
graph](#glos-module-graph), not just those relevant to a specific command.
|
graph](#glos-module-graph), not just those relevant to a specific command.
|
||||||
|
|
||||||
<a id="glos-canonical-version">
|
<a id="glos-canonical-version"></a>
|
||||||
**canonical version:** A correctly formatted [version](#glos-version) without
|
**canonical version:** A correctly formatted [version](#glos-version) without
|
||||||
a build metadata suffix other than `+incompatible`. For example, `v1.2.3`
|
a build metadata suffix other than `+incompatible`. For example, `v1.2.3`
|
||||||
is a canonical version, but `v1.2.3+meta` is not.
|
is a canonical version, but `v1.2.3+meta` is not.
|
||||||
|
|
|
||||||
164
doc/root.html
164
doc/root.html
|
|
@ -1,164 +0,0 @@
|
||||||
<!--{
|
|
||||||
"Path": "/",
|
|
||||||
"Template": true
|
|
||||||
}-->
|
|
||||||
|
|
||||||
<div class="left">
|
|
||||||
|
|
||||||
<div id="learn">
|
|
||||||
{{if not $.GoogleCN}}
|
|
||||||
<a class="popout share">Pop-out</a>
|
|
||||||
{{end}}
|
|
||||||
<div class="rootHeading">Try Go</div>
|
|
||||||
<div class="input">
|
|
||||||
<textarea spellcheck="false" class="code">// You can edit this code!
|
|
||||||
// Click here and start typing.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
fmt.Println("Hello, 世界")
|
|
||||||
}</textarea>
|
|
||||||
</div>
|
|
||||||
<div class="output">
|
|
||||||
<pre>
|
|
||||||
Hello, 世界
|
|
||||||
</pre>
|
|
||||||
</div>
|
|
||||||
<div class="buttons">
|
|
||||||
<a class="run" href="#" title="Run this code [shift-enter]">Run</a>
|
|
||||||
{{if not $.GoogleCN}}
|
|
||||||
<a class="share" href="#" title="Share this code">Share</a>
|
|
||||||
<a class="tour" href="//tour.golang.org/" title="Learn Go from your browser">Tour</a>
|
|
||||||
{{end}}
|
|
||||||
</div>
|
|
||||||
<div class="toys">
|
|
||||||
<select>
|
|
||||||
<option value="hello.go">Hello, World!</option>
|
|
||||||
<option value="life.go">Conway's Game of Life</option>
|
|
||||||
<option value="fib.go">Fibonacci Closure</option>
|
|
||||||
<option value="peano.go">Peano Integers</option>
|
|
||||||
<option value="pi.go">Concurrent pi</option>
|
|
||||||
<option value="sieve.go">Concurrent Prime Sieve</option>
|
|
||||||
<option value="solitaire.go">Peg Solitaire Solver</option>
|
|
||||||
<option value="tree.go">Tree Comparison</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="right">
|
|
||||||
|
|
||||||
<div id="about">
|
|
||||||
Go is an open source programming language that makes it easy to build
|
|
||||||
simple, reliable, and efficient software.
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="gopher"></div>
|
|
||||||
|
|
||||||
<a href="/dl/" id="start">
|
|
||||||
<span class="big">Download Go</span>
|
|
||||||
<span class="desc">
|
|
||||||
Binary distributions available for<br>
|
|
||||||
Linux, macOS, Windows, and more.
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="clear: both"></div>
|
|
||||||
|
|
||||||
{{if not $.GoogleCN}}
|
|
||||||
<div class="left">
|
|
||||||
<div id="video">
|
|
||||||
<div class="rootHeading">Featured video</div>
|
|
||||||
<div class="js-frontpage-video" style="--aspect-ratio-padding: 58.07%;"><iframe width="415" height="241" src="//www.youtube.com/embed/ytEkHepK08c" frameborder="0" allowfullscreen></iframe></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="right">
|
|
||||||
<div id="blog">
|
|
||||||
<div class="rootHeading">Featured articles</div>
|
|
||||||
<div class="read"><a href="//blog.golang.org/">Read more</a></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
<div style="clear: both;"></div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
window.initFuncs.push(function() {
|
|
||||||
// Set up playground if enabled.
|
|
||||||
if (window.playground) {
|
|
||||||
window.playground({
|
|
||||||
"codeEl": "#learn .code",
|
|
||||||
"outputEl": "#learn .output",
|
|
||||||
"runEl": "#learn .run",
|
|
||||||
"shareEl": "#learn .share",
|
|
||||||
"shareRedirect": "//play.golang.org/p/",
|
|
||||||
"toysEl": "#learn .toys select"
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
$('#learn').hide()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
{{if not $.GoogleCN}}
|
|
||||||
|
|
||||||
function readableTime(t) {
|
|
||||||
var m = ["January", "February", "March", "April", "May", "June", "July",
|
|
||||||
"August", "September", "October", "November", "December"];
|
|
||||||
var p = t.substring(0, t.indexOf("T")).split("-");
|
|
||||||
var d = new Date(p[0], p[1]-1, p[2]);
|
|
||||||
return d.getDate() + " " + m[d.getMonth()] + " " + d.getFullYear();
|
|
||||||
}
|
|
||||||
|
|
||||||
window.feedLoaded = function(result) {
|
|
||||||
var blog = document.getElementById("blog");
|
|
||||||
var read = blog.getElementsByClassName("read")[0];
|
|
||||||
for (var i = 0; i < result.length && i < 2; i++) {
|
|
||||||
var entry = result[i];
|
|
||||||
var title = document.createElement("a");
|
|
||||||
title.className = "title";
|
|
||||||
title.href = entry.Link;
|
|
||||||
title.innerHTML = entry.Title;
|
|
||||||
blog.insertBefore(title, read);
|
|
||||||
var extract = document.createElement("div");
|
|
||||||
extract.className = "extract";
|
|
||||||
extract.innerHTML = entry.Summary;
|
|
||||||
blog.insertBefore(extract, read);
|
|
||||||
var when = document.createElement("div");
|
|
||||||
when.className = "when";
|
|
||||||
when.innerHTML = "Published " + readableTime(entry.Time);
|
|
||||||
blog.insertBefore(when, read);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
window.initFuncs.push(function() {
|
|
||||||
// Load blog feed.
|
|
||||||
$('<script/>').attr('text', 'text/javascript')
|
|
||||||
.attr('src', '//blog.golang.org/.json?jsonp=feedLoaded')
|
|
||||||
.appendTo('body');
|
|
||||||
|
|
||||||
// Set the video at random.
|
|
||||||
var videos = [
|
|
||||||
{h: 241, s: "//www.youtube.com/embed/ytEkHepK08c"}, // Tour of Go
|
|
||||||
{h: 241, s: "//www.youtube.com/embed/f6kdp27TYZs"}, // Concurrency Patterns
|
|
||||||
{h: 233, s: "//player.vimeo.com/video/69237265"} // Simple environment
|
|
||||||
];
|
|
||||||
var v = videos[Math.floor(Math.random()*videos.length)];
|
|
||||||
$('#video iframe').attr('height', v.h).attr('src', v.s);
|
|
||||||
// Compute the aspect ratio (as a percentage) of the video
|
|
||||||
// using the fixed width 415 and the height of the current video, v.h.
|
|
||||||
var ar = 100*v.h/415;
|
|
||||||
$('.js-frontpage-video').attr('style', '--aspect-ratio-padding: ' + ar + '%;');
|
|
||||||
});
|
|
||||||
|
|
||||||
{{end}}
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
|
|
@ -1,184 +0,0 @@
|
||||||
<!--{
|
|
||||||
"Title": "Go Security Policy",
|
|
||||||
"Path": "/security",
|
|
||||||
"Template": true
|
|
||||||
}-->
|
|
||||||
|
|
||||||
<h2>Implementation</h2>
|
|
||||||
|
|
||||||
<h3>Reporting a Security Bug</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Please report to us any issues you find.
|
|
||||||
This document explains how to do that and what to expect in return.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
All security bugs in the Go distribution should be reported by email to
|
|
||||||
<a href="mailto:security@golang.org">security@golang.org</a>.
|
|
||||||
This mail is delivered to a small security team.
|
|
||||||
Your email will be acknowledged within 24 hours, and you'll receive a more
|
|
||||||
detailed response to your email within 72 hours indicating the next steps in
|
|
||||||
handling your report.
|
|
||||||
For critical problems, you can encrypt your report using our PGP key (listed below).
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
To ensure your report is not marked as spam, please include the word "vulnerability"
|
|
||||||
anywhere in your email. Please use a descriptive subject line for your report email.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
After the initial reply to your report, the security team will endeavor to keep
|
|
||||||
you informed of the progress being made towards a fix and full announcement.
|
|
||||||
These updates will be sent at least every five days.
|
|
||||||
In reality, this is more likely to be every 24-48 hours.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
If you have not received a reply to your email within 48 hours or you have not
|
|
||||||
heard from the security team for the past five days please contact the Go
|
|
||||||
security team directly:
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>Primary security coordinator: <a href="mailto:filippo@golang.org">Filippo Valsorda</a> (<a href="https://keybase.io/filippo/pgp_keys.asc">public key</a>).</li>
|
|
||||||
<li>Secondary coordinator: <a href="mailto:agl@golang.org">Adam Langley</a> (<a href="https://www.imperialviolet.org/key.asc">public key</a>).</li>
|
|
||||||
<li>If you receive no response, mail <a href="mailto:golang-dev@googlegroups.com">golang-dev@googlegroups.com</a> or use the <a href="https://groups.google.com/forum/#!forum/golang-dev">golang-dev web interface</a>.</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Please note that golang-dev is a public discussion forum.
|
|
||||||
When escalating on this list, please do not disclose the details of the issue.
|
|
||||||
Simply state that you're trying to reach a member of the security team.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3>Flagging Existing Issues as Security-related</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
If you believe that an <a href="https://golang.org/issue">existing issue</a>
|
|
||||||
is security-related, we ask that you send an email to
|
|
||||||
<a href="mailto:security@golang.org">security@golang.org</a>.
|
|
||||||
The email should include the issue ID and a short description of why it should
|
|
||||||
be handled according to this security policy.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3>Disclosure Process</h3>
|
|
||||||
|
|
||||||
<p>The Go project uses the following disclosure process:</p>
|
|
||||||
|
|
||||||
<ol>
|
|
||||||
<li>Once the security report is received it is assigned a primary handler.
|
|
||||||
This person coordinates the fix and release process.</li>
|
|
||||||
<li>The issue is confirmed and a list of affected software is determined.</li>
|
|
||||||
<li>Code is audited to find any potential similar problems.</li>
|
|
||||||
<li>If it is determined, in consultation with the submitter, that a CVE-ID is
|
|
||||||
required, the primary handler obtains one via email to
|
|
||||||
<a href="https://oss-security.openwall.org/wiki/mailing-lists/distros">oss-distros</a>.</li>
|
|
||||||
<li>Fixes are prepared for the two most recent major releases and the head/master
|
|
||||||
revision. These fixes are not yet committed to the public repository.</li>
|
|
||||||
<li>A notification is sent to the
|
|
||||||
<a href="https://groups.google.com/group/golang-announce">golang-announce</a>
|
|
||||||
mailing list to give users time to prepare their systems for the update.</li>
|
|
||||||
<li>Three working days following this notification, the fixes are applied to
|
|
||||||
the <a href="https://go.googlesource.com/go">public repository</a> and a new
|
|
||||||
Go release is issued.</li>
|
|
||||||
<li>On the date that the fixes are applied, announcements are sent to
|
|
||||||
<a href="https://groups.google.com/group/golang-announce">golang-announce</a>,
|
|
||||||
<a href="https://groups.google.com/group/golang-dev">golang-dev</a>, and
|
|
||||||
<a href="https://groups.google.com/group/golang-nuts">golang-nuts</a>.
|
|
||||||
</ol>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
This process can take some time, especially when coordination is required with
|
|
||||||
maintainers of other projects. Every effort will be made to handle the bug in
|
|
||||||
as timely a manner as possible, however it's important that we follow the
|
|
||||||
process described above to ensure that disclosures are handled consistently.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
For security issues that include the assignment of a CVE-ID,
|
|
||||||
the issue is listed publicly under the
|
|
||||||
<a href="https://www.cvedetails.com/vulnerability-list/vendor_id-14185/Golang.html">"Golang" product on the CVEDetails website</a>
|
|
||||||
as well as the
|
|
||||||
<a href="https://web.nvd.nist.gov/view/vuln/search">National Vulnerability Disclosure site</a>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3>Receiving Security Updates</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The best way to receive security announcements is to subscribe to the
|
|
||||||
<a href="https://groups.google.com/forum/#!forum/golang-announce">golang-announce</a>
|
|
||||||
mailing list. Any messages pertaining to a security issue will be prefixed
|
|
||||||
with <code>[security]</code>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3>Comments on This Policy</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
If you have any suggestions to improve this policy, please send an email to
|
|
||||||
<a href="mailto:golang-dev@golang.org">golang-dev@golang.org</a> for discussion.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3>PGP Key for <a href="mailto:security@golang.org">security@golang.org</a></h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
We accept PGP-encrypted email, but the majority of the security team
|
|
||||||
are not regular PGP users so it's somewhat inconvenient. Please only
|
|
||||||
use PGP for critical security reports.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
|
||||||
Comment: GPGTools - https://gpgtools.org
|
|
||||||
|
|
||||||
mQINBFXI1h0BEADZdm05GDFWvjmQKutUVb0cJKS+VR+6XU3g/YQZGC8tnIL6i7te
|
|
||||||
+fPJHfQc2uIw0xeBgZX4Ni/S8yIqsbIjqYeaToX7QFUufJDQwrmlQRDVAvvT5HBT
|
|
||||||
J80JEs7yHRreFoLzB6dnWehWXzWle4gFKeIy+hvLrYquZVvbeEYTnX7fNzZg0+5L
|
|
||||||
ksvj7lnQlJIy1l3sL/7uPr9qsm45/hzd0WjTQS85Ry6Na3tMwRpqGENDh25Blz75
|
|
||||||
8JgK9JmtTJa00my1zzeCXU04CKKEMRbkMLozzudOH4ZLiLWcFiKRpeCn860wC8l3
|
|
||||||
oJcyyObuTSbr9o05ra3On+epjCEFkknGX1WxPv+TV34i0a23AtuVyTCloKb7RYXc
|
|
||||||
7mUaskZpU2rFBqIkzZ4MQJ7RDtGlm5oBy36j2QL63jAZ1cKoT/yvjJNp2ObmWaVF
|
|
||||||
X3tk/nYw2H0YDjTkTCgGtyAOj3Cfqrtsa5L0jG5K2p4RY8mtVgQ5EOh7QxuS+rmN
|
|
||||||
JiA39SWh7O6uFCwkz/OCXzqeh6/nP10HAb9S9IC34QQxm7Fhd0ZXzEv9IlBTIRzk
|
|
||||||
xddSdACPnLE1gJcFHxBd2LTqS/lmAFShCsf8S252kagKJfHRebQJZHCIs6kT9PfE
|
|
||||||
0muq6KRKeDXv01afAUvoB4QW/3chUrtgL2HryyO8ugMu7leVGmoZhFkIrQARAQAB
|
|
||||||
tCZHbyBTZWN1cml0eSBUZWFtIDxzZWN1cml0eUBnb2xhbmcub3JnPokCPQQTAQoA
|
|
||||||
JwUCVcjWHQIbAwUJB4YfgAULCQgHAwUVCgkICwUWAgMBAAIeAQIXgAAKCRA6RtGR
|
|
||||||
eVpYOLnDD/9YVTd6DTwdJq6irVfM/ICPlPTXB0JLERqCI1Veptcp56eQoJ0XWGQp
|
|
||||||
tkGlgbvmCzFo0B+65Te7YA4R3oyBCXd6JgyWQQPy5p60FHyuuCPVAReclSWyt9f2
|
|
||||||
Yj/u4DjghKhELOvPiI96egcU3g9jrEEcPjm7JYkc9M2gVSNOnnJvcD7wpQJNCzon
|
|
||||||
51eMZ1ZyfA5UCBTa0SaT9eXg5zwNlYQnB6ZF6TjXezkhLqlTsBuHxoNVf+9vCC0o
|
|
||||||
ZKIM2ovptMx9eEguTDKWaQ7tero7Zs/q5fwk/MDzM/LGJ9aXy2RCtqBxv46vDS7G
|
|
||||||
fCNq+aPD/wyFd6hxQkvkua6hgZwYT+cJWHYA2Yv0LO3BYOJdjfc+j2hjv+mC9lF0
|
|
||||||
UpWhCVJv3hHoFaxnz62GdROzf2wXz6aR9Saj1rYSvqT9jC20VInxqMufXNN2sbpo
|
|
||||||
Kyk6MTbAeepphQpfAWQv+ltWgBiEjuFxYdwv/vmw20996JV7O8nqkeCUW84B6su+
|
|
||||||
Y3bbdP9o3DBtOT0j9LTB/FucmdNCNHoO+EnNBKJd6FoYTGLWi3Rq9DLx2V9tdJHo
|
|
||||||
Bn67dymcl+iyp337HJNY+qS+KCgoqAWlxkzXRiXKb/yluhXdIkqhg4kL8JPAJvfS
|
|
||||||
cs7Zn67Mx04ixJnRMYCDmxtD4xPsFMzM7g8m3PQp+nE7WhujM/ImM7kCDQRVyNYd
|
|
||||||
ARAAlw9H/1ybQs4K3XKA1joII16rta9KS7ew76+agXo0jeSRwMEQfItOxYvfhmo8
|
|
||||||
+ydn5TWsTbifGU8L3+EBTMRRyzWhbaGO0Wizw7BTVJ7n5JW+ndPrcUpp/ilUk6AU
|
|
||||||
VxaO/8/R+9+VJZpoeoLHXYloFGNuX58GLIy1jSBvLsLl/Ki5IOrHvD1GK6TftOl5
|
|
||||||
j8IPC1LSBrwGJO803x7wUdQP/tsKN/QPR8pnBntrEgrQFSI+Q3qrCvVMmXnBlYum
|
|
||||||
jfOBt8pKMgB9/ix+HWN8piQNQiJxD+XjEM6XwUmQqIR7y5GINKWgundCmtYIzVgY
|
|
||||||
9p2Br6UPrTJi12LfKv5s2R6NnxFHv/ad29CpPTeLJRsSqFfqBL969BCpj/isXmQE
|
|
||||||
m4FtziZidARXo12KiGAnPF9otirNHp4+8hwNB3scf7cI53y8nZivO9cwI7BoClY6
|
|
||||||
ZIabjDcJxjK+24emoz3mJ5SHpZpQLSb9o8GbLLfXOq+4uzEX2A30fhrtsQb/x0GM
|
|
||||||
4v3EU1aP2mjuksyYbgldtY64tD35wqAA9mVl5Ux+g1HoUBvLw0h+lzwh370NJw//
|
|
||||||
ITvBQVUtDMB96rfIP4fL5pYl5pmRz+vsuJ0iXzm05qBgKfSqO7To9SWxQPdX89R4
|
|
||||||
u0/XVAlw0Ak9Zceq3W96vseEUTR3aoZCMIPiwfcDaq60rWUAEQEAAYkCJQQYAQoA
|
|
||||||
DwUCVcjWHQIbDAUJB4YfgAAKCRA6RtGReVpYOEg/EADZcIYw4q1jAbDkDy3LQG07
|
|
||||||
AR8QmLp/RDp72RKbCSIYyvyXEnmrhUg98lUG676qTH+Y7dlEX107dLhFuKEYyV8D
|
|
||||||
ZalrFQO/3WpLWdIAmWrj/wq14qii1rgmy96Nh3EqG3CS50HEMGkW1llRx2rgBvGl
|
|
||||||
pgoTcwOfT+h8s0HlZdIS/cv2wXqwPgMWr1PIk3as1fu1OH8n/BjeGQQnNJEaoBV7
|
|
||||||
El2C/hz3oqf2uYQ1QvpU23F1NrstekxukO8o2Y/fqsgMJqAiNJApUCl/dNhK+W57
|
|
||||||
iicjvPirUQk8MUVEHXKhWIzYxon6aEUTx+xyNMBpRJIZlJ61FxtnZhoPiAFtXVPb
|
|
||||||
+95BRJA9npidlVFjqz9QDK/4NSnJ3KaERR9tTDcvq4zqT22Z1Ai5gWQKqogTz5Mk
|
|
||||||
F+nZwVizW0yi33id9qDpAuApp8o6AiyH5Ql1Bo23bvqS2lMrXPIS/QmPPsA76CBs
|
|
||||||
lYjQwwz8abUD1pPdzyYtMKZUMwhicSFOHFDM4oQN16k2KJuntuih8BKVDCzIOq+E
|
|
||||||
KHyeh1BqWplUtFh1ckxZlXW9p9F7TsWjtfcKaY8hkX0Cr4uVjwAFIjLcAxk67ROe
|
|
||||||
huEb3Gt+lwJz6aNnZUU87ukMAxRVR2LL0btdxgc6z8spl66GXro/LUkXmAdyOEMV
|
|
||||||
UDrmjf9pr7o00hC7lCHFzw==
|
|
||||||
=WE0r
|
|
||||||
-----END PGP PUBLIC KEY BLOCK-----
|
|
||||||
</pre>
|
|
||||||
|
|
@ -2,16 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// We skip this test in race mode because, for unknown reasons,
|
// +build darwin,cgo,!internal
|
||||||
// linking against CoreFoundation on macOS 10.10 causes mmap to ignore
|
|
||||||
// the hint address, which makes the Go allocator incompatible with
|
|
||||||
// TSAN. See golang.org/issue/26475.
|
|
||||||
//
|
|
||||||
// TODO(austin): Once support for macOS 10.10 is dropped, remove the
|
|
||||||
// race constraint (and the one in issue21897b.go). See
|
|
||||||
// golang.org/issue/26513.
|
|
||||||
|
|
||||||
// +build darwin,cgo,!internal,!race
|
|
||||||
|
|
||||||
package cgotest
|
package cgotest
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build !darwin !cgo internal race
|
// +build !darwin !cgo internal
|
||||||
|
|
||||||
package cgotest
|
package cgotest
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build gccgo
|
|
||||||
|
|
||||||
package cgotest
|
|
||||||
|
|
||||||
//typedef void (*PFunc)();
|
|
||||||
//PFunc success_cb;
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
//export Test
|
|
||||||
func Test() {
|
|
||||||
_ = C.success_cb
|
|
||||||
}
|
|
||||||
|
|
@ -562,6 +562,11 @@ void issue8811Execute() {
|
||||||
issue8811Init();
|
issue8811Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// issue 8945
|
||||||
|
|
||||||
|
typedef void (*PFunc8945)();
|
||||||
|
PFunc8945 func8945;
|
||||||
|
|
||||||
// issue 9557
|
// issue 9557
|
||||||
|
|
||||||
struct issue9557_t {
|
struct issue9557_t {
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,6 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// See issue21897.go and golang.org/issue/26475 for why this is
|
|
||||||
// skipped in race mode.
|
|
||||||
//
|
|
||||||
// TODO(austin): Once support for macOS 10.10 is dropped, remove the
|
|
||||||
// race constraint. See golang.org/issue/26513.
|
|
||||||
|
|
||||||
// +build !race
|
|
||||||
|
|
||||||
package cgotest
|
package cgotest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
||||||
2
misc/cgo/test/testdata/issue24161e0/main.go
vendored
2
misc/cgo/test/testdata/issue24161e0/main.go
vendored
|
|
@ -12,7 +12,7 @@ package issue24161e0
|
||||||
#include <TargetConditionals.h>
|
#include <TargetConditionals.h>
|
||||||
#include <CoreFoundation/CoreFoundation.h>
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
#include <Security/Security.h>
|
#include <Security/Security.h>
|
||||||
#if TARGET_OS_IPHONE == 0 && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101200
|
#if TARGET_OS_IPHONE == 0 && __MAC_OS_X_VERSION_MAX_ALLOWED < 101200
|
||||||
typedef CFStringRef SecKeyAlgorithm;
|
typedef CFStringRef SecKeyAlgorithm;
|
||||||
static CFDataRef SecKeyCreateSignature(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef dataToSign, CFErrorRef *error){return NULL;}
|
static CFDataRef SecKeyCreateSignature(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef dataToSign, CFErrorRef *error){return NULL;}
|
||||||
#define kSecKeyAlgorithmECDSASignatureDigestX962SHA1 foo()
|
#define kSecKeyAlgorithmECDSASignatureDigestX962SHA1 foo()
|
||||||
|
|
|
||||||
2
misc/cgo/test/testdata/issue24161e1/main.go
vendored
2
misc/cgo/test/testdata/issue24161e1/main.go
vendored
|
|
@ -12,7 +12,7 @@ package issue24161e1
|
||||||
#include <TargetConditionals.h>
|
#include <TargetConditionals.h>
|
||||||
#include <CoreFoundation/CoreFoundation.h>
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
#include <Security/Security.h>
|
#include <Security/Security.h>
|
||||||
#if TARGET_OS_IPHONE == 0 && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101200
|
#if TARGET_OS_IPHONE == 0 && __MAC_OS_X_VERSION_MAX_ALLOWED < 101200
|
||||||
typedef CFStringRef SecKeyAlgorithm;
|
typedef CFStringRef SecKeyAlgorithm;
|
||||||
static CFDataRef SecKeyCreateSignature(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef dataToSign, CFErrorRef *error){return NULL;}
|
static CFDataRef SecKeyCreateSignature(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef dataToSign, CFErrorRef *error){return NULL;}
|
||||||
#define kSecKeyAlgorithmECDSASignatureDigestX962SHA1 foo()
|
#define kSecKeyAlgorithmECDSASignatureDigestX962SHA1 foo()
|
||||||
|
|
|
||||||
2
misc/cgo/test/testdata/issue24161e2/main.go
vendored
2
misc/cgo/test/testdata/issue24161e2/main.go
vendored
|
|
@ -12,7 +12,7 @@ package issue24161e2
|
||||||
#include <TargetConditionals.h>
|
#include <TargetConditionals.h>
|
||||||
#include <CoreFoundation/CoreFoundation.h>
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
#include <Security/Security.h>
|
#include <Security/Security.h>
|
||||||
#if TARGET_OS_IPHONE == 0 && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101200
|
#if TARGET_OS_IPHONE == 0 && __MAC_OS_X_VERSION_MAX_ALLOWED < 101200
|
||||||
typedef CFStringRef SecKeyAlgorithm;
|
typedef CFStringRef SecKeyAlgorithm;
|
||||||
static CFDataRef SecKeyCreateSignature(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef dataToSign, CFErrorRef *error){return NULL;}
|
static CFDataRef SecKeyCreateSignature(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef dataToSign, CFErrorRef *error){return NULL;}
|
||||||
#define kSecKeyAlgorithmECDSASignatureDigestX962SHA1 foo()
|
#define kSecKeyAlgorithmECDSASignatureDigestX962SHA1 foo()
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,9 @@ package issue9026
|
||||||
// per-package counter used to create fresh identifiers.
|
// per-package counter used to create fresh identifiers.
|
||||||
|
|
||||||
/*
|
/*
|
||||||
typedef struct {} git_merge_file_input;
|
typedef struct { int i; } git_merge_file_input;
|
||||||
|
|
||||||
typedef struct {} git_merge_file_options;
|
typedef struct { int j; } git_merge_file_options;
|
||||||
|
|
||||||
void git_merge_file(
|
void git_merge_file(
|
||||||
git_merge_file_input *in,
|
git_merge_file_input *in,
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,11 @@ static void issue7978c(uint32_t *sync) {
|
||||||
// #include'd twice. No runtime test; just make sure it compiles.
|
// #include'd twice. No runtime test; just make sure it compiles.
|
||||||
#include "issue8331.h"
|
#include "issue8331.h"
|
||||||
|
|
||||||
|
// issue 8945
|
||||||
|
|
||||||
|
typedef void (*PFunc8945)();
|
||||||
|
extern PFunc8945 func8945; // definition is in test.go
|
||||||
|
|
||||||
// issue 20910
|
// issue 20910
|
||||||
void callMulti(void);
|
void callMulti(void);
|
||||||
|
|
||||||
|
|
@ -514,6 +519,13 @@ func test7978(t *testing.T) {
|
||||||
|
|
||||||
var issue8331Var C.issue8331
|
var issue8331Var C.issue8331
|
||||||
|
|
||||||
|
// issue 8945
|
||||||
|
|
||||||
|
//export Test8945
|
||||||
|
func Test8945() {
|
||||||
|
_ = C.func8945
|
||||||
|
}
|
||||||
|
|
||||||
// issue 20910
|
// issue 20910
|
||||||
|
|
||||||
//export multi
|
//export multi
|
||||||
|
|
|
||||||
|
|
@ -433,7 +433,7 @@ func (tr *Reader) readHeader() (*Header, *block, error) {
|
||||||
// files generated by a pre-Go1.8 toolchain. If the generated file
|
// files generated by a pre-Go1.8 toolchain. If the generated file
|
||||||
// happened to have a prefix field that parses as valid
|
// happened to have a prefix field that parses as valid
|
||||||
// atime and ctime fields (e.g., when they are valid octal strings),
|
// atime and ctime fields (e.g., when they are valid octal strings),
|
||||||
// then it is impossible to distinguish between an valid GNU file
|
// then it is impossible to distinguish between a valid GNU file
|
||||||
// and an invalid pre-Go1.8 file.
|
// and an invalid pre-Go1.8 file.
|
||||||
//
|
//
|
||||||
// See https://golang.org/issues/12594
|
// See https://golang.org/issues/12594
|
||||||
|
|
|
||||||
57
src/cmd/asm/internal/asm/testdata/riscvenc.s
vendored
57
src/cmd/asm/internal/asm/testdata/riscvenc.s
vendored
|
|
@ -60,11 +60,13 @@ start:
|
||||||
AUIPC $0, X10 // 17050000
|
AUIPC $0, X10 // 17050000
|
||||||
AUIPC $0, X11 // 97050000
|
AUIPC $0, X11 // 97050000
|
||||||
AUIPC $1, X10 // 17150000
|
AUIPC $1, X10 // 17150000
|
||||||
AUIPC $1048575, X10 // 17f5ffff
|
AUIPC $-524288, X15 // 97070080
|
||||||
|
AUIPC $524287, X10 // 17f5ff7f
|
||||||
|
|
||||||
LUI $0, X15 // b7070000
|
LUI $0, X15 // b7070000
|
||||||
LUI $167, X15 // b7770a00
|
LUI $167, X15 // b7770a00
|
||||||
LUI $1048575, X15 // b7f7ffff
|
LUI $-524288, X15 // b7070080
|
||||||
|
LUI $524287, X15 // b7f7ff7f
|
||||||
|
|
||||||
SLL X6, X5, X7 // b3936200
|
SLL X6, X5, X7 // b3936200
|
||||||
SLL X5, X6 // 33135300
|
SLL X5, X6 // 33135300
|
||||||
|
|
@ -89,15 +91,15 @@ start:
|
||||||
// to 2 because they transfer control to the second instruction
|
// to 2 because they transfer control to the second instruction
|
||||||
// in the function (the first instruction being an invisible
|
// in the function (the first instruction being an invisible
|
||||||
// stack pointer adjustment).
|
// stack pointer adjustment).
|
||||||
JAL X5, start // JAL X5, 2 // eff2dff0
|
JAL X5, start // JAL X5, 2 // eff25ff0
|
||||||
JALR X6, (X5) // 67830200
|
JALR X6, (X5) // 67830200
|
||||||
JALR X6, 4(X5) // 67834200
|
JALR X6, 4(X5) // 67834200
|
||||||
BEQ X5, X6, start // BEQ X5, X6, 2 // e38062f0
|
BEQ X5, X6, start // BEQ X5, X6, 2 // e38c62ee
|
||||||
BNE X5, X6, start // BNE X5, X6, 2 // e39e62ee
|
BNE X5, X6, start // BNE X5, X6, 2 // e39a62ee
|
||||||
BLT X5, X6, start // BLT X5, X6, 2 // e3cc62ee
|
BLT X5, X6, start // BLT X5, X6, 2 // e3c862ee
|
||||||
BLTU X5, X6, start // BLTU X5, X6, 2 // e3ea62ee
|
BLTU X5, X6, start // BLTU X5, X6, 2 // e3e662ee
|
||||||
BGE X5, X6, start // BGE X5, X6, 2 // e3d862ee
|
BGE X5, X6, start // BGE X5, X6, 2 // e3d462ee
|
||||||
BGEU X5, X6, start // BGEU X5, X6, 2 // e3f662ee
|
BGEU X5, X6, start // BGEU X5, X6, 2 // e3f262ee
|
||||||
|
|
||||||
// 2.6: Load and Store Instructions
|
// 2.6: Load and Store Instructions
|
||||||
LW (X5), X6 // 03a30200
|
LW (X5), X6 // 03a30200
|
||||||
|
|
@ -267,3 +269,40 @@ start:
|
||||||
MOVD 4(X5), F0 // 07b04200
|
MOVD 4(X5), F0 // 07b04200
|
||||||
MOVD F0, 4(X5) // 27b20200
|
MOVD F0, 4(X5) // 27b20200
|
||||||
MOVD F0, F1 // d3000022
|
MOVD F0, F1 // d3000022
|
||||||
|
|
||||||
|
// These jumps can get printed as jumps to 2 because they go to the
|
||||||
|
// second instruction in the function (the first instruction is an
|
||||||
|
// invisible stack pointer adjustment).
|
||||||
|
JMP start // JMP 2 // 6ff0dfcc
|
||||||
|
JMP (X5) // 67800200
|
||||||
|
JMP 4(X5) // 67804200
|
||||||
|
|
||||||
|
// JMP and CALL to symbol are encoded as:
|
||||||
|
// AUIPC $0, TMP
|
||||||
|
// JALR $0, TMP
|
||||||
|
// with a R_RISCV_PCREL_ITYPE relocation - the linker resolves the
|
||||||
|
// real address and updates the immediates for both instructions.
|
||||||
|
CALL asmtest(SB) // 970f0000
|
||||||
|
JMP asmtest(SB) // 970f0000
|
||||||
|
|
||||||
|
SEQZ X15, X15 // 93b71700
|
||||||
|
SNEZ X15, X15 // b337f000
|
||||||
|
|
||||||
|
// F extension
|
||||||
|
FNEGS F0, F1 // d3100020
|
||||||
|
|
||||||
|
// TODO(jsing): FNES gets encoded as FEQS+XORI - this should
|
||||||
|
// be handled as a single *obj.Prog so that the full two
|
||||||
|
// instruction encoding is tested here.
|
||||||
|
FNES F0, F1, X7 // d3a300a0
|
||||||
|
|
||||||
|
// D extension
|
||||||
|
FNEGD F0, F1 // d3100022
|
||||||
|
FEQD F0, F1, X5 // d3a200a2
|
||||||
|
FLTD F0, F1, X5 // d39200a2
|
||||||
|
FLED F0, F1, X5 // d38200a2
|
||||||
|
|
||||||
|
// TODO(jsing): FNED gets encoded as FEQD+XORI - this should
|
||||||
|
// be handled as a single *obj.Prog so that the full two
|
||||||
|
// instruction encoding is tested here.
|
||||||
|
FNED F0, F1, X5 // d3a200a2
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,14 @@
|
||||||
package gc
|
package gc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"cmd/compile/internal/types"
|
"cmd/compile/internal/types"
|
||||||
"cmd/internal/src"
|
"cmd/internal/src"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -650,23 +652,64 @@ var basicnames = []string{
|
||||||
TBLANK: "blank",
|
TBLANK: "blank",
|
||||||
}
|
}
|
||||||
|
|
||||||
func typefmt(t *types.Type, flag FmtFlag, mode fmtMode, depth int) string {
|
var tconvBufferPool = sync.Pool{
|
||||||
if t == nil {
|
New: func() interface{} {
|
||||||
return "<T>"
|
return new(bytes.Buffer)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func tconv(t *types.Type, flag FmtFlag, mode fmtMode) string {
|
||||||
|
buf := tconvBufferPool.Get().(*bytes.Buffer)
|
||||||
|
buf.Reset()
|
||||||
|
defer tconvBufferPool.Put(buf)
|
||||||
|
|
||||||
|
tconv2(buf, t, flag, mode, nil)
|
||||||
|
return types.InternString(buf.Bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
// tconv2 writes a string representation of t to b.
|
||||||
|
// flag and mode control exactly what is printed.
|
||||||
|
// Any types x that are already in the visited map get printed as @%d where %d=visited[x].
|
||||||
|
// See #16897 before changing the implementation of tconv.
|
||||||
|
func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode fmtMode, visited map[*types.Type]int) {
|
||||||
|
if off, ok := visited[t]; ok {
|
||||||
|
// We've seen this type before, so we're trying to print it recursively.
|
||||||
|
// Print a reference to it instead.
|
||||||
|
fmt.Fprintf(b, "@%d", off)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if t == nil {
|
||||||
|
b.WriteString("<T>")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if t.Etype == types.TSSA {
|
||||||
|
b.WriteString(t.Extra.(string))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if t.Etype == types.TTUPLE {
|
||||||
|
b.WriteString(t.FieldType(0).String())
|
||||||
|
b.WriteByte(',')
|
||||||
|
b.WriteString(t.FieldType(1).String())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
flag, mode = flag.update(mode)
|
||||||
|
if mode == FTypeIdName {
|
||||||
|
flag |= FmtUnsigned
|
||||||
|
}
|
||||||
if t == types.Bytetype || t == types.Runetype {
|
if t == types.Bytetype || t == types.Runetype {
|
||||||
// in %-T mode collapse rune and byte with their originals.
|
// in %-T mode collapse rune and byte with their originals.
|
||||||
switch mode {
|
switch mode {
|
||||||
case FTypeIdName, FTypeId:
|
case FTypeIdName, FTypeId:
|
||||||
t = types.Types[t.Etype]
|
t = types.Types[t.Etype]
|
||||||
default:
|
default:
|
||||||
return sconv(t.Sym, FmtShort, mode)
|
b.WriteString(sconv(t.Sym, FmtShort, mode))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if t == types.Errortype {
|
if t == types.Errortype {
|
||||||
return "error"
|
b.WriteString("error")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unless the 'L' flag was specified, if the type has a name, just print that name.
|
// Unless the 'L' flag was specified, if the type has a name, just print that name.
|
||||||
|
|
@ -675,161 +718,197 @@ func typefmt(t *types.Type, flag FmtFlag, mode fmtMode, depth int) string {
|
||||||
case FTypeId, FTypeIdName:
|
case FTypeId, FTypeIdName:
|
||||||
if flag&FmtShort != 0 {
|
if flag&FmtShort != 0 {
|
||||||
if t.Vargen != 0 {
|
if t.Vargen != 0 {
|
||||||
return mode.Sprintf("%v·%d", sconv(t.Sym, FmtShort, mode), t.Vargen)
|
fmt.Fprintf(b, "%s·%d", sconv(t.Sym, FmtShort, mode), t.Vargen)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
return sconv(t.Sym, FmtShort, mode)
|
b.WriteString(sconv(t.Sym, FmtShort, mode))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if mode == FTypeIdName {
|
if mode == FTypeIdName {
|
||||||
return sconv(t.Sym, FmtUnsigned, mode)
|
b.WriteString(sconv(t.Sym, FmtUnsigned, mode))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.Sym.Pkg == localpkg && t.Vargen != 0 {
|
if t.Sym.Pkg == localpkg && t.Vargen != 0 {
|
||||||
return mode.Sprintf("%v·%d", t.Sym, t.Vargen)
|
b.WriteString(mode.Sprintf("%v·%d", t.Sym, t.Vargen))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return smodeString(t.Sym, mode)
|
b.WriteString(smodeString(t.Sym, mode))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if int(t.Etype) < len(basicnames) && basicnames[t.Etype] != "" {
|
if int(t.Etype) < len(basicnames) && basicnames[t.Etype] != "" {
|
||||||
|
var name string
|
||||||
switch t {
|
switch t {
|
||||||
case types.Idealbool:
|
case types.Idealbool:
|
||||||
return "untyped bool"
|
name = "untyped bool"
|
||||||
case types.Idealstring:
|
case types.Idealstring:
|
||||||
return "untyped string"
|
name = "untyped string"
|
||||||
case types.Idealint:
|
case types.Idealint:
|
||||||
return "untyped int"
|
name = "untyped int"
|
||||||
case types.Idealrune:
|
case types.Idealrune:
|
||||||
return "untyped rune"
|
name = "untyped rune"
|
||||||
case types.Idealfloat:
|
case types.Idealfloat:
|
||||||
return "untyped float"
|
name = "untyped float"
|
||||||
case types.Idealcomplex:
|
case types.Idealcomplex:
|
||||||
return "untyped complex"
|
name = "untyped complex"
|
||||||
|
default:
|
||||||
|
name = basicnames[t.Etype]
|
||||||
}
|
}
|
||||||
return basicnames[t.Etype]
|
b.WriteString(name)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// At this point, we might call tconv2 recursively. Add the current type to the visited list so we don't
|
||||||
|
// try to print it recursively.
|
||||||
|
// We record the offset in the result buffer where the type's text starts. This offset serves as a reference
|
||||||
|
// point for any later references to the same type.
|
||||||
|
// Note that we remove the type from the visited map as soon as the recursive call is done.
|
||||||
|
// This prevents encoding types like map[*int]*int as map[*int]@4. (That encoding would work,
|
||||||
|
// but I'd like to use the @ notation only when strictly necessary.)
|
||||||
|
if visited == nil {
|
||||||
|
visited = map[*types.Type]int{}
|
||||||
|
}
|
||||||
|
visited[t] = b.Len()
|
||||||
|
defer delete(visited, t)
|
||||||
|
|
||||||
if mode == FDbg {
|
if mode == FDbg {
|
||||||
return t.Etype.String() + "-" + typefmt(t, flag, FErr, depth)
|
b.WriteString(t.Etype.String())
|
||||||
|
b.WriteByte('-')
|
||||||
|
tconv2(b, t, flag, FErr, visited)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
switch t.Etype {
|
switch t.Etype {
|
||||||
case TPTR:
|
case TPTR:
|
||||||
|
b.WriteByte('*')
|
||||||
switch mode {
|
switch mode {
|
||||||
case FTypeId, FTypeIdName:
|
case FTypeId, FTypeIdName:
|
||||||
if flag&FmtShort != 0 {
|
if flag&FmtShort != 0 {
|
||||||
return "*" + tconv(t.Elem(), FmtShort, mode, depth)
|
tconv2(b, t.Elem(), FmtShort, mode, visited)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "*" + tmodeString(t.Elem(), mode, depth)
|
tconv2(b, t.Elem(), 0, mode, visited)
|
||||||
|
|
||||||
case TARRAY:
|
case TARRAY:
|
||||||
return "[" + strconv.FormatInt(t.NumElem(), 10) + "]" + tmodeString(t.Elem(), mode, depth)
|
b.WriteByte('[')
|
||||||
|
b.WriteString(strconv.FormatInt(t.NumElem(), 10))
|
||||||
|
b.WriteByte(']')
|
||||||
|
tconv2(b, t.Elem(), 0, mode, visited)
|
||||||
|
|
||||||
case TSLICE:
|
case TSLICE:
|
||||||
return "[]" + tmodeString(t.Elem(), mode, depth)
|
b.WriteString("[]")
|
||||||
|
tconv2(b, t.Elem(), 0, mode, visited)
|
||||||
|
|
||||||
case TCHAN:
|
case TCHAN:
|
||||||
switch t.ChanDir() {
|
switch t.ChanDir() {
|
||||||
case types.Crecv:
|
case types.Crecv:
|
||||||
return "<-chan " + tmodeString(t.Elem(), mode, depth)
|
b.WriteString("<-chan ")
|
||||||
|
tconv2(b, t.Elem(), 0, mode, visited)
|
||||||
case types.Csend:
|
case types.Csend:
|
||||||
return "chan<- " + tmodeString(t.Elem(), mode, depth)
|
b.WriteString("chan<- ")
|
||||||
}
|
tconv2(b, t.Elem(), 0, mode, visited)
|
||||||
|
default:
|
||||||
|
b.WriteString("chan ")
|
||||||
if t.Elem() != nil && t.Elem().IsChan() && t.Elem().Sym == nil && t.Elem().ChanDir() == types.Crecv {
|
if t.Elem() != nil && t.Elem().IsChan() && t.Elem().Sym == nil && t.Elem().ChanDir() == types.Crecv {
|
||||||
return "chan (" + tmodeString(t.Elem(), mode, depth) + ")"
|
b.WriteByte('(')
|
||||||
|
tconv2(b, t.Elem(), 0, mode, visited)
|
||||||
|
b.WriteByte(')')
|
||||||
|
} else {
|
||||||
|
tconv2(b, t.Elem(), 0, mode, visited)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return "chan " + tmodeString(t.Elem(), mode, depth)
|
|
||||||
|
|
||||||
case TMAP:
|
case TMAP:
|
||||||
return "map[" + tmodeString(t.Key(), mode, depth) + "]" + tmodeString(t.Elem(), mode, depth)
|
b.WriteString("map[")
|
||||||
|
tconv2(b, t.Key(), 0, mode, visited)
|
||||||
|
b.WriteByte(']')
|
||||||
|
tconv2(b, t.Elem(), 0, mode, visited)
|
||||||
|
|
||||||
case TINTER:
|
case TINTER:
|
||||||
if t.IsEmptyInterface() {
|
if t.IsEmptyInterface() {
|
||||||
return "interface {}"
|
b.WriteString("interface {}")
|
||||||
|
break
|
||||||
}
|
}
|
||||||
buf := make([]byte, 0, 64)
|
b.WriteString("interface {")
|
||||||
buf = append(buf, "interface {"...)
|
|
||||||
for i, f := range t.Fields().Slice() {
|
for i, f := range t.Fields().Slice() {
|
||||||
if i != 0 {
|
if i != 0 {
|
||||||
buf = append(buf, ';')
|
b.WriteByte(';')
|
||||||
}
|
}
|
||||||
buf = append(buf, ' ')
|
b.WriteByte(' ')
|
||||||
switch {
|
switch {
|
||||||
case f.Sym == nil:
|
case f.Sym == nil:
|
||||||
// Check first that a symbol is defined for this type.
|
// Check first that a symbol is defined for this type.
|
||||||
// Wrong interface definitions may have types lacking a symbol.
|
// Wrong interface definitions may have types lacking a symbol.
|
||||||
break
|
break
|
||||||
case types.IsExported(f.Sym.Name):
|
case types.IsExported(f.Sym.Name):
|
||||||
buf = append(buf, sconv(f.Sym, FmtShort, mode)...)
|
b.WriteString(sconv(f.Sym, FmtShort, mode))
|
||||||
default:
|
default:
|
||||||
flag1 := FmtLeft
|
flag1 := FmtLeft
|
||||||
if flag&FmtUnsigned != 0 {
|
if flag&FmtUnsigned != 0 {
|
||||||
flag1 = FmtUnsigned
|
flag1 = FmtUnsigned
|
||||||
}
|
}
|
||||||
buf = append(buf, sconv(f.Sym, flag1, mode)...)
|
b.WriteString(sconv(f.Sym, flag1, mode))
|
||||||
}
|
}
|
||||||
buf = append(buf, tconv(f.Type, FmtShort, mode, depth)...)
|
tconv2(b, f.Type, FmtShort, mode, visited)
|
||||||
}
|
}
|
||||||
if t.NumFields() != 0 {
|
if t.NumFields() != 0 {
|
||||||
buf = append(buf, ' ')
|
b.WriteByte(' ')
|
||||||
}
|
}
|
||||||
buf = append(buf, '}')
|
b.WriteByte('}')
|
||||||
return string(buf)
|
|
||||||
|
|
||||||
case TFUNC:
|
case TFUNC:
|
||||||
buf := make([]byte, 0, 64)
|
|
||||||
if flag&FmtShort != 0 {
|
if flag&FmtShort != 0 {
|
||||||
// no leading func
|
// no leading func
|
||||||
} else {
|
} else {
|
||||||
if t.Recv() != nil {
|
if t.Recv() != nil {
|
||||||
buf = append(buf, "method"...)
|
b.WriteString("method")
|
||||||
buf = append(buf, tmodeString(t.Recvs(), mode, depth)...)
|
tconv2(b, t.Recvs(), 0, mode, visited)
|
||||||
buf = append(buf, ' ')
|
b.WriteByte(' ')
|
||||||
}
|
}
|
||||||
buf = append(buf, "func"...)
|
b.WriteString("func")
|
||||||
}
|
}
|
||||||
buf = append(buf, tmodeString(t.Params(), mode, depth)...)
|
tconv2(b, t.Params(), 0, mode, visited)
|
||||||
|
|
||||||
switch t.NumResults() {
|
switch t.NumResults() {
|
||||||
case 0:
|
case 0:
|
||||||
// nothing to do
|
// nothing to do
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
buf = append(buf, ' ')
|
b.WriteByte(' ')
|
||||||
buf = append(buf, tmodeString(t.Results().Field(0).Type, mode, depth)...) // struct->field->field's type
|
tconv2(b, t.Results().Field(0).Type, 0, mode, visited) // struct->field->field's type
|
||||||
|
|
||||||
default:
|
default:
|
||||||
buf = append(buf, ' ')
|
b.WriteByte(' ')
|
||||||
buf = append(buf, tmodeString(t.Results(), mode, depth)...)
|
tconv2(b, t.Results(), 0, mode, visited)
|
||||||
}
|
}
|
||||||
return string(buf)
|
|
||||||
|
|
||||||
case TSTRUCT:
|
case TSTRUCT:
|
||||||
if m := t.StructType().Map; m != nil {
|
if m := t.StructType().Map; m != nil {
|
||||||
mt := m.MapType()
|
mt := m.MapType()
|
||||||
// Format the bucket struct for map[x]y as map.bucket[x]y.
|
// Format the bucket struct for map[x]y as map.bucket[x]y.
|
||||||
// This avoids a recursive print that generates very long names.
|
// This avoids a recursive print that generates very long names.
|
||||||
var subtype string
|
|
||||||
switch t {
|
switch t {
|
||||||
case mt.Bucket:
|
case mt.Bucket:
|
||||||
subtype = "bucket"
|
b.WriteString("map.bucket[")
|
||||||
case mt.Hmap:
|
case mt.Hmap:
|
||||||
subtype = "hdr"
|
b.WriteString("map.hdr[")
|
||||||
case mt.Hiter:
|
case mt.Hiter:
|
||||||
subtype = "iter"
|
b.WriteString("map.iter[")
|
||||||
default:
|
default:
|
||||||
Fatalf("unknown internal map type")
|
Fatalf("unknown internal map type")
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("map.%s[%s]%s", subtype, tmodeString(m.Key(), mode, depth), tmodeString(m.Elem(), mode, depth))
|
tconv2(b, m.Key(), 0, mode, visited)
|
||||||
|
b.WriteByte(']')
|
||||||
|
tconv2(b, m.Elem(), 0, mode, visited)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := make([]byte, 0, 64)
|
|
||||||
if funarg := t.StructType().Funarg; funarg != types.FunargNone {
|
if funarg := t.StructType().Funarg; funarg != types.FunargNone {
|
||||||
buf = append(buf, '(')
|
b.WriteByte('(')
|
||||||
var flag1 FmtFlag
|
var flag1 FmtFlag
|
||||||
switch mode {
|
switch mode {
|
||||||
case FTypeId, FTypeIdName, FErr:
|
case FTypeId, FTypeIdName, FErr:
|
||||||
|
|
@ -838,42 +917,42 @@ func typefmt(t *types.Type, flag FmtFlag, mode fmtMode, depth int) string {
|
||||||
}
|
}
|
||||||
for i, f := range t.Fields().Slice() {
|
for i, f := range t.Fields().Slice() {
|
||||||
if i != 0 {
|
if i != 0 {
|
||||||
buf = append(buf, ", "...)
|
b.WriteString(", ")
|
||||||
}
|
}
|
||||||
buf = append(buf, fldconv(f, flag1, mode, depth, funarg)...)
|
fldconv(b, f, flag1, mode, visited, funarg)
|
||||||
}
|
}
|
||||||
buf = append(buf, ')')
|
b.WriteByte(')')
|
||||||
} else {
|
} else {
|
||||||
buf = append(buf, "struct {"...)
|
b.WriteString("struct {")
|
||||||
for i, f := range t.Fields().Slice() {
|
for i, f := range t.Fields().Slice() {
|
||||||
if i != 0 {
|
if i != 0 {
|
||||||
buf = append(buf, ';')
|
b.WriteByte(';')
|
||||||
}
|
}
|
||||||
buf = append(buf, ' ')
|
b.WriteByte(' ')
|
||||||
buf = append(buf, fldconv(f, FmtLong, mode, depth, funarg)...)
|
fldconv(b, f, FmtLong, mode, visited, funarg)
|
||||||
}
|
}
|
||||||
if t.NumFields() != 0 {
|
if t.NumFields() != 0 {
|
||||||
buf = append(buf, ' ')
|
b.WriteByte(' ')
|
||||||
}
|
}
|
||||||
buf = append(buf, '}')
|
b.WriteByte('}')
|
||||||
}
|
}
|
||||||
return string(buf)
|
|
||||||
|
|
||||||
case TFORW:
|
case TFORW:
|
||||||
|
b.WriteString("undefined")
|
||||||
if t.Sym != nil {
|
if t.Sym != nil {
|
||||||
return "undefined " + smodeString(t.Sym, mode)
|
b.WriteByte(' ')
|
||||||
|
b.WriteString(smodeString(t.Sym, mode))
|
||||||
}
|
}
|
||||||
return "undefined"
|
|
||||||
|
|
||||||
case TUNSAFEPTR:
|
case TUNSAFEPTR:
|
||||||
return "unsafe.Pointer"
|
b.WriteString("unsafe.Pointer")
|
||||||
|
|
||||||
case Txxx:
|
case Txxx:
|
||||||
return "Txxx"
|
b.WriteString("Txxx")
|
||||||
}
|
default:
|
||||||
|
|
||||||
// Don't know how to handle - fall back to detailed prints.
|
// Don't know how to handle - fall back to detailed prints.
|
||||||
return mode.Sprintf("%v <%v>", t.Etype, t.Sym)
|
b.WriteString(mode.Sprintf("%v <%v>", t.Etype, t.Sym))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Statements which may be rendered with a simplestmt as init.
|
// Statements which may be rendered with a simplestmt as init.
|
||||||
|
|
@ -1657,15 +1736,11 @@ func sconv(s *types.Sym, flag FmtFlag, mode fmtMode) string {
|
||||||
return symfmt(s, flag, mode)
|
return symfmt(s, flag, mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
func tmodeString(t *types.Type, mode fmtMode, depth int) string {
|
func fldconv(b *bytes.Buffer, f *types.Field, flag FmtFlag, mode fmtMode, visited map[*types.Type]int, funarg types.Funarg) {
|
||||||
return tconv(t, 0, mode, depth)
|
|
||||||
}
|
|
||||||
|
|
||||||
func fldconv(f *types.Field, flag FmtFlag, mode fmtMode, depth int, funarg types.Funarg) string {
|
|
||||||
if f == nil {
|
if f == nil {
|
||||||
return "<T>"
|
b.WriteString("<T>")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
flag, mode = flag.update(mode)
|
flag, mode = flag.update(mode)
|
||||||
if mode == FTypeIdName {
|
if mode == FTypeIdName {
|
||||||
flag |= FmtUnsigned
|
flag |= FmtUnsigned
|
||||||
|
|
@ -1694,27 +1769,26 @@ func fldconv(f *types.Field, flag FmtFlag, mode fmtMode, depth int, funarg types
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var typ string
|
if name != "" {
|
||||||
|
b.WriteString(name)
|
||||||
|
b.WriteString(" ")
|
||||||
|
}
|
||||||
|
|
||||||
if f.IsDDD() {
|
if f.IsDDD() {
|
||||||
var et *types.Type
|
var et *types.Type
|
||||||
if f.Type != nil {
|
if f.Type != nil {
|
||||||
et = f.Type.Elem()
|
et = f.Type.Elem()
|
||||||
}
|
}
|
||||||
typ = "..." + tmodeString(et, mode, depth)
|
b.WriteString("...")
|
||||||
|
tconv2(b, et, 0, mode, visited)
|
||||||
} else {
|
} else {
|
||||||
typ = tmodeString(f.Type, mode, depth)
|
tconv2(b, f.Type, 0, mode, visited)
|
||||||
}
|
|
||||||
|
|
||||||
str := typ
|
|
||||||
if name != "" {
|
|
||||||
str = name + " " + typ
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if flag&FmtShort == 0 && funarg == types.FunargNone && f.Note != "" {
|
if flag&FmtShort == 0 && funarg == types.FunargNone && f.Note != "" {
|
||||||
str += " " + strconv.Quote(f.Note)
|
b.WriteString(" ")
|
||||||
|
b.WriteString(strconv.Quote(f.Note))
|
||||||
}
|
}
|
||||||
|
|
||||||
return str
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// "%L" print definition, not name
|
// "%L" print definition, not name
|
||||||
|
|
@ -1722,45 +1796,12 @@ func fldconv(f *types.Field, flag FmtFlag, mode fmtMode, depth int, funarg types
|
||||||
func typeFormat(t *types.Type, s fmt.State, verb rune, mode fmtMode) {
|
func typeFormat(t *types.Type, s fmt.State, verb rune, mode fmtMode) {
|
||||||
switch verb {
|
switch verb {
|
||||||
case 'v', 'S', 'L':
|
case 'v', 'S', 'L':
|
||||||
// This is an external entry point, so we pass depth 0 to tconv.
|
fmt.Fprint(s, tconv(t, fmtFlag(s, verb), mode))
|
||||||
// See comments in Type.String.
|
|
||||||
fmt.Fprint(s, tconv(t, fmtFlag(s, verb), mode, 0))
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fmt.Fprintf(s, "%%!%c(*Type=%p)", verb, t)
|
fmt.Fprintf(s, "%%!%c(*Type=%p)", verb, t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// See #16897 before changing the implementation of tconv.
|
|
||||||
func tconv(t *types.Type, flag FmtFlag, mode fmtMode, depth int) string {
|
|
||||||
if t == nil {
|
|
||||||
return "<T>"
|
|
||||||
}
|
|
||||||
if t.Etype == types.TSSA {
|
|
||||||
return t.Extra.(string)
|
|
||||||
}
|
|
||||||
if t.Etype == types.TTUPLE {
|
|
||||||
return t.FieldType(0).String() + "," + t.FieldType(1).String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Avoid endless recursion by setting an upper limit. This also
|
|
||||||
// limits the depths of valid composite types, but they are likely
|
|
||||||
// artificially created.
|
|
||||||
// TODO(gri) should have proper cycle detection here, eventually (issue #29312)
|
|
||||||
if depth > 250 {
|
|
||||||
return "<...>"
|
|
||||||
}
|
|
||||||
|
|
||||||
flag, mode = flag.update(mode)
|
|
||||||
if mode == FTypeIdName {
|
|
||||||
flag |= FmtUnsigned
|
|
||||||
}
|
|
||||||
|
|
||||||
str := typefmt(t, flag, mode, depth+1)
|
|
||||||
|
|
||||||
return str
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *Node) String() string { return fmt.Sprint(n) }
|
func (n *Node) String() string { return fmt.Sprint(n) }
|
||||||
func (n *Node) modeString(mode fmtMode) string { return mode.Sprint(n) }
|
func (n *Node) modeString(mode fmtMode) string { return mode.Sprint(n) }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -175,7 +175,7 @@ func TestIntendedInlining(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch runtime.GOARCH {
|
switch runtime.GOARCH {
|
||||||
case "386", "wasm", "arm":
|
case "386", "wasm", "arm", "riscv64":
|
||||||
default:
|
default:
|
||||||
// TODO(mvdan): As explained in /test/inline_sync.go, some
|
// TODO(mvdan): As explained in /test/inline_sync.go, some
|
||||||
// architectures don't have atomic intrinsics, so these go over
|
// architectures don't have atomic intrinsics, so these go over
|
||||||
|
|
|
||||||
|
|
@ -511,8 +511,8 @@ func Main(archInit func(*Arch)) {
|
||||||
types.Sconv = func(s *types.Sym, flag, mode int) string {
|
types.Sconv = func(s *types.Sym, flag, mode int) string {
|
||||||
return sconv(s, FmtFlag(flag), fmtMode(mode))
|
return sconv(s, FmtFlag(flag), fmtMode(mode))
|
||||||
}
|
}
|
||||||
types.Tconv = func(t *types.Type, flag, mode, depth int) string {
|
types.Tconv = func(t *types.Type, flag, mode int) string {
|
||||||
return tconv(t, FmtFlag(flag), fmtMode(mode), depth)
|
return tconv(t, FmtFlag(flag), fmtMode(mode))
|
||||||
}
|
}
|
||||||
types.FormatSym = func(sym *types.Sym, s fmt.State, verb rune, mode int) {
|
types.FormatSym = func(sym *types.Sym, s fmt.State, verb rune, mode int) {
|
||||||
symFormat(sym, s, verb, fmtMode(mode))
|
symFormat(sym, s, verb, fmtMode(mode))
|
||||||
|
|
|
||||||
|
|
@ -705,6 +705,12 @@ func (lv *Liveness) markUnsafePoints() {
|
||||||
v = v.Args[0]
|
v = v.Args[0]
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
case ssa.OpRISCV64SUB:
|
||||||
|
// RISCV64 lowers Neq32 to include a SUB with multiple arguments.
|
||||||
|
// TODO(jsing): it would be preferable not to use Neq32 for
|
||||||
|
// writeBuffer.enabled checks on this platform.
|
||||||
|
v = v.Args[0]
|
||||||
|
continue
|
||||||
case ssa.Op386MOVLload, ssa.OpARM64MOVWUload, ssa.OpPPC64MOVWZload, ssa.OpWasmI64Load32U:
|
case ssa.Op386MOVLload, ssa.OpARM64MOVWUload, ssa.OpPPC64MOVWZload, ssa.OpWasmI64Load32U:
|
||||||
// Args[0] is the address of the write
|
// Args[0] is the address of the write
|
||||||
// barrier control. Ignore Args[1],
|
// barrier control. Ignore Args[1],
|
||||||
|
|
|
||||||
|
|
@ -340,7 +340,8 @@ func buildssa(fn *Node, worker int) *ssa.Func {
|
||||||
s.startmem = s.entryNewValue0(ssa.OpInitMem, types.TypeMem)
|
s.startmem = s.entryNewValue0(ssa.OpInitMem, types.TypeMem)
|
||||||
|
|
||||||
s.hasOpenDefers = Debug['N'] == 0 && s.hasdefer && !s.curfn.Func.OpenCodedDeferDisallowed()
|
s.hasOpenDefers = Debug['N'] == 0 && s.hasdefer && !s.curfn.Func.OpenCodedDeferDisallowed()
|
||||||
if s.hasOpenDefers && (Ctxt.Flag_shared || Ctxt.Flag_dynlink) && thearch.LinkArch.Name == "386" {
|
switch {
|
||||||
|
case s.hasOpenDefers && (Ctxt.Flag_shared || Ctxt.Flag_dynlink) && thearch.LinkArch.Name == "386":
|
||||||
// Don't support open-coded defers for 386 ONLY when using shared
|
// Don't support open-coded defers for 386 ONLY when using shared
|
||||||
// libraries, because there is extra code (added by rewriteToUseGot())
|
// libraries, because there is extra code (added by rewriteToUseGot())
|
||||||
// preceding the deferreturn/ret code that is generated by gencallret()
|
// preceding the deferreturn/ret code that is generated by gencallret()
|
||||||
|
|
@ -5968,23 +5969,22 @@ func genssa(f *ssa.Func, pp *Progs) {
|
||||||
// Emit basic blocks
|
// Emit basic blocks
|
||||||
for i, b := range f.Blocks {
|
for i, b := range f.Blocks {
|
||||||
s.bstart[b.ID] = s.pp.next
|
s.bstart[b.ID] = s.pp.next
|
||||||
s.pp.nextLive = LivenessInvalid
|
|
||||||
s.lineRunStart = nil
|
s.lineRunStart = nil
|
||||||
|
|
||||||
|
// Attach a "default" liveness info. Normally this will be
|
||||||
|
// overwritten in the Values loop below for each Value. But
|
||||||
|
// for an empty block this will be used for its control
|
||||||
|
// instruction. We won't use the actual liveness map on a
|
||||||
|
// control instruction. Just mark it something that is
|
||||||
|
// preemptible.
|
||||||
|
s.pp.nextLive = LivenessIndex{-1, -1}
|
||||||
|
|
||||||
// Emit values in block
|
// Emit values in block
|
||||||
thearch.SSAMarkMoves(&s, b)
|
thearch.SSAMarkMoves(&s, b)
|
||||||
for _, v := range b.Values {
|
for _, v := range b.Values {
|
||||||
x := s.pp.next
|
x := s.pp.next
|
||||||
s.DebugFriendlySetPosFrom(v)
|
s.DebugFriendlySetPosFrom(v)
|
||||||
// Attach this safe point to the next
|
|
||||||
// instruction.
|
|
||||||
s.pp.nextLive = s.livenessMap.Get(v)
|
|
||||||
|
|
||||||
// Remember the liveness index of the first defer call of
|
|
||||||
// the last defer exit
|
|
||||||
if v.Block.Func.LastDeferExit != nil && v == v.Block.Func.LastDeferExit {
|
|
||||||
s.lastDeferLiveness = s.pp.nextLive
|
|
||||||
}
|
|
||||||
switch v.Op {
|
switch v.Op {
|
||||||
case ssa.OpInitMem:
|
case ssa.OpInitMem:
|
||||||
// memory arg needs no code
|
// memory arg needs no code
|
||||||
|
|
@ -6018,12 +6018,22 @@ func genssa(f *ssa.Func, pp *Progs) {
|
||||||
inlMarksByPos[pos] = append(inlMarksByPos[pos], p)
|
inlMarksByPos[pos] = append(inlMarksByPos[pos], p)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// let the backend handle it
|
// Attach this safe point to the next
|
||||||
|
// instruction.
|
||||||
|
s.pp.nextLive = s.livenessMap.Get(v)
|
||||||
|
|
||||||
|
// Remember the liveness index of the first defer call of
|
||||||
|
// the last defer exit
|
||||||
|
if v.Block.Func.LastDeferExit != nil && v == v.Block.Func.LastDeferExit {
|
||||||
|
s.lastDeferLiveness = s.pp.nextLive
|
||||||
|
}
|
||||||
|
|
||||||
// Special case for first line in function; move it to the start.
|
// Special case for first line in function; move it to the start.
|
||||||
if firstPos != src.NoXPos {
|
if firstPos != src.NoXPos {
|
||||||
s.SetPos(firstPos)
|
s.SetPos(firstPos)
|
||||||
firstPos = src.NoXPos
|
firstPos = src.NoXPos
|
||||||
}
|
}
|
||||||
|
// let the backend handle it
|
||||||
thearch.SSAGenValue(&s, v)
|
thearch.SSAGenValue(&s, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -6524,7 +6534,7 @@ func (s *SSAGenState) Call(v *ssa.Value) *obj.Prog {
|
||||||
} else {
|
} else {
|
||||||
// TODO(mdempsky): Can these differences be eliminated?
|
// TODO(mdempsky): Can these differences be eliminated?
|
||||||
switch thearch.LinkArch.Family {
|
switch thearch.LinkArch.Family {
|
||||||
case sys.AMD64, sys.I386, sys.PPC64, sys.S390X, sys.Wasm:
|
case sys.AMD64, sys.I386, sys.PPC64, sys.RISCV64, sys.S390X, sys.Wasm:
|
||||||
p.To.Type = obj.TYPE_REG
|
p.To.Type = obj.TYPE_REG
|
||||||
case sys.ARM, sys.ARM64, sys.MIPS, sys.MIPS64:
|
case sys.ARM, sys.ARM64, sys.MIPS, sys.MIPS64:
|
||||||
p.To.Type = obj.TYPE_MEM
|
p.To.Type = obj.TYPE_MEM
|
||||||
|
|
|
||||||
|
|
@ -1705,7 +1705,6 @@ func mkdotargslice(typ *types.Type, args []*Node, init *Nodes, ddd *Node) *Node
|
||||||
if ddd != nil {
|
if ddd != nil {
|
||||||
esc = ddd.Esc
|
esc = ddd.Esc
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
n := nodnil()
|
n := nodnil()
|
||||||
n.Type = typ
|
n.Type = typ
|
||||||
|
|
@ -1740,6 +1739,9 @@ func walkCall(n *Node, init *Nodes) {
|
||||||
// then assign the remaining arguments as a slice.
|
// then assign the remaining arguments as a slice.
|
||||||
if nf := params.NumFields(); nf > 0 {
|
if nf := params.NumFields(); nf > 0 {
|
||||||
if last := params.Field(nf - 1); last.IsDDD() && !n.IsDDD() {
|
if last := params.Field(nf - 1); last.IsDDD() && !n.IsDDD() {
|
||||||
|
// The callsite does not use a ..., but the called function is declared
|
||||||
|
// with a final argument that has a ... . Build the slice that we will
|
||||||
|
// pass as the ... argument.
|
||||||
tail := args[nf-1:]
|
tail := args[nf-1:]
|
||||||
slice := mkdotargslice(last.Type, tail, init, n.Right)
|
slice := mkdotargslice(last.Type, tail, init, n.Right)
|
||||||
// Allow immediate GC.
|
// Allow immediate GC.
|
||||||
|
|
@ -4067,11 +4069,15 @@ func walkCheckPtrArithmetic(n *Node, init *Nodes) *Node {
|
||||||
|
|
||||||
n = cheapexpr(n, init)
|
n = cheapexpr(n, init)
|
||||||
|
|
||||||
slice := mkdotargslice(types.NewSlice(types.Types[TUNSAFEPTR]), originals, init, nil)
|
ddd := nodl(n.Pos, ODDDARG, nil, nil)
|
||||||
slice.Esc = EscNone
|
ddd.Type = types.NewPtr(types.NewArray(types.Types[TUNSAFEPTR], int64(len(originals))))
|
||||||
slice.SetTransient(true)
|
ddd.Esc = EscNone
|
||||||
|
slice := mkdotargslice(types.NewSlice(types.Types[TUNSAFEPTR]), originals, init, ddd)
|
||||||
|
|
||||||
init.Append(mkcall("checkptrArithmetic", nil, init, convnop(n, types.Types[TUNSAFEPTR]), slice))
|
init.Append(mkcall("checkptrArithmetic", nil, init, convnop(n, types.Types[TUNSAFEPTR]), slice))
|
||||||
|
// TODO(khr): Mark backing store of slice as dead. This will allow us to reuse
|
||||||
|
// the backing store for multiple calls to checkptrArithmetic.
|
||||||
|
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -325,7 +325,9 @@ type byPos struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x byPos) Len() int { return len(x.a) }
|
func (x byPos) Len() int { return len(x.a) }
|
||||||
func (x byPos) Less(i, j int) bool { return x.ctxt.OutermostPos(x.a[i].pos).Before(x.ctxt.OutermostPos(x.a[j].pos)) }
|
func (x byPos) Less(i, j int) bool {
|
||||||
|
return x.ctxt.OutermostPos(x.a[i].pos).Before(x.ctxt.OutermostPos(x.a[j].pos))
|
||||||
|
}
|
||||||
func (x byPos) Swap(i, j int) { x.a[i], x.a[j] = x.a[j], x.a[i] }
|
func (x byPos) Swap(i, j int) { x.a[i], x.a[j] = x.a[j], x.a[i] }
|
||||||
|
|
||||||
func writerForLSP(subdirpath, file string) io.WriteCloser {
|
func writerForLSP(subdirpath, file string) io.WriteCloser {
|
||||||
|
|
|
||||||
25
src/cmd/compile/internal/riscv64/galign.go
Normal file
25
src/cmd/compile/internal/riscv64/galign.go
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
// 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 riscv64
|
||||||
|
|
||||||
|
import (
|
||||||
|
"cmd/compile/internal/gc"
|
||||||
|
"cmd/internal/obj/riscv"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Init(arch *gc.Arch) {
|
||||||
|
arch.LinkArch = &riscv.LinkRISCV64
|
||||||
|
|
||||||
|
arch.REGSP = riscv.REG_SP
|
||||||
|
arch.MAXWIDTH = 1 << 50
|
||||||
|
|
||||||
|
arch.Ginsnop = ginsnop
|
||||||
|
arch.Ginsnopdefer = ginsnop
|
||||||
|
arch.ZeroRange = zeroRange
|
||||||
|
|
||||||
|
arch.SSAMarkMoves = ssaMarkMoves
|
||||||
|
arch.SSAGenValue = ssaGenValue
|
||||||
|
arch.SSAGenBlock = ssaGenBlock
|
||||||
|
}
|
||||||
48
src/cmd/compile/internal/riscv64/ggen.go
Normal file
48
src/cmd/compile/internal/riscv64/ggen.go
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
// 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 riscv64
|
||||||
|
|
||||||
|
import (
|
||||||
|
"cmd/compile/internal/gc"
|
||||||
|
"cmd/internal/obj"
|
||||||
|
"cmd/internal/obj/riscv"
|
||||||
|
)
|
||||||
|
|
||||||
|
func zeroRange(pp *gc.Progs, p *obj.Prog, off, cnt int64, _ *uint32) *obj.Prog {
|
||||||
|
if cnt == 0 {
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjust the frame to account for LR.
|
||||||
|
off += gc.Ctxt.FixedFrameSize()
|
||||||
|
|
||||||
|
if cnt < int64(4*gc.Widthptr) {
|
||||||
|
for i := int64(0); i < cnt; i += int64(gc.Widthptr) {
|
||||||
|
p = pp.Appendpp(p, riscv.AMOV, obj.TYPE_REG, riscv.REG_ZERO, 0, obj.TYPE_MEM, riscv.REG_SP, off+i)
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(jsing): Add a duff zero implementation for medium sized ranges.
|
||||||
|
|
||||||
|
// Loop, zeroing pointer width bytes at a time.
|
||||||
|
// ADD $(off), SP, T0
|
||||||
|
// ADD $(cnt), T0, T1
|
||||||
|
// loop:
|
||||||
|
// MOV ZERO, (T0)
|
||||||
|
// ADD $Widthptr, T0
|
||||||
|
// BNE T0, T1, loop
|
||||||
|
p = pp.Appendpp(p, riscv.AADD, obj.TYPE_CONST, 0, off, obj.TYPE_REG, riscv.REG_T0, 0)
|
||||||
|
p.Reg = riscv.REG_SP
|
||||||
|
p = pp.Appendpp(p, riscv.AADD, obj.TYPE_CONST, 0, cnt, obj.TYPE_REG, riscv.REG_T1, 0)
|
||||||
|
p.Reg = riscv.REG_T0
|
||||||
|
p = pp.Appendpp(p, riscv.AMOV, obj.TYPE_REG, riscv.REG_ZERO, 0, obj.TYPE_MEM, riscv.REG_T0, 0)
|
||||||
|
loop := p
|
||||||
|
p = pp.Appendpp(p, riscv.AADD, obj.TYPE_CONST, 0, int64(gc.Widthptr), obj.TYPE_REG, riscv.REG_T0, 0)
|
||||||
|
p = pp.Appendpp(p, riscv.ABNE, obj.TYPE_REG, riscv.REG_T0, 0, obj.TYPE_BRANCH, 0, 0)
|
||||||
|
p.Reg = riscv.REG_T1
|
||||||
|
gc.Patch(p, loop)
|
||||||
|
return p
|
||||||
|
}
|
||||||
20
src/cmd/compile/internal/riscv64/gsubr.go
Normal file
20
src/cmd/compile/internal/riscv64/gsubr.go
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
// 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 riscv64
|
||||||
|
|
||||||
|
import (
|
||||||
|
"cmd/compile/internal/gc"
|
||||||
|
"cmd/internal/obj"
|
||||||
|
"cmd/internal/obj/riscv"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ginsnop(pp *gc.Progs) *obj.Prog {
|
||||||
|
// Hardware nop is ADD $0, ZERO
|
||||||
|
p := pp.Prog(riscv.AADD)
|
||||||
|
p.From.Type = obj.TYPE_CONST
|
||||||
|
p.Reg = riscv.REG_ZERO
|
||||||
|
p.To = obj.Addr{Type: obj.TYPE_REG, Reg: riscv.REG_ZERO}
|
||||||
|
return p
|
||||||
|
}
|
||||||
496
src/cmd/compile/internal/riscv64/ssa.go
Normal file
496
src/cmd/compile/internal/riscv64/ssa.go
Normal file
|
|
@ -0,0 +1,496 @@
|
||||||
|
// 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 riscv64
|
||||||
|
|
||||||
|
import (
|
||||||
|
"cmd/compile/internal/gc"
|
||||||
|
"cmd/compile/internal/ssa"
|
||||||
|
"cmd/compile/internal/types"
|
||||||
|
"cmd/internal/obj"
|
||||||
|
"cmd/internal/obj/riscv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ssaRegToReg maps ssa register numbers to obj register numbers.
|
||||||
|
var ssaRegToReg = []int16{
|
||||||
|
riscv.REG_X0,
|
||||||
|
// X1 (LR): unused
|
||||||
|
riscv.REG_X2,
|
||||||
|
riscv.REG_X3,
|
||||||
|
riscv.REG_X4,
|
||||||
|
riscv.REG_X5,
|
||||||
|
riscv.REG_X6,
|
||||||
|
riscv.REG_X7,
|
||||||
|
riscv.REG_X8,
|
||||||
|
riscv.REG_X9,
|
||||||
|
riscv.REG_X10,
|
||||||
|
riscv.REG_X11,
|
||||||
|
riscv.REG_X12,
|
||||||
|
riscv.REG_X13,
|
||||||
|
riscv.REG_X14,
|
||||||
|
riscv.REG_X15,
|
||||||
|
riscv.REG_X16,
|
||||||
|
riscv.REG_X17,
|
||||||
|
riscv.REG_X18,
|
||||||
|
riscv.REG_X19,
|
||||||
|
riscv.REG_X20,
|
||||||
|
riscv.REG_X21,
|
||||||
|
riscv.REG_X22,
|
||||||
|
riscv.REG_X23,
|
||||||
|
riscv.REG_X24,
|
||||||
|
riscv.REG_X25,
|
||||||
|
riscv.REG_X26,
|
||||||
|
riscv.REG_X27,
|
||||||
|
riscv.REG_X28,
|
||||||
|
riscv.REG_X29,
|
||||||
|
riscv.REG_X30,
|
||||||
|
riscv.REG_X31,
|
||||||
|
riscv.REG_F0,
|
||||||
|
riscv.REG_F1,
|
||||||
|
riscv.REG_F2,
|
||||||
|
riscv.REG_F3,
|
||||||
|
riscv.REG_F4,
|
||||||
|
riscv.REG_F5,
|
||||||
|
riscv.REG_F6,
|
||||||
|
riscv.REG_F7,
|
||||||
|
riscv.REG_F8,
|
||||||
|
riscv.REG_F9,
|
||||||
|
riscv.REG_F10,
|
||||||
|
riscv.REG_F11,
|
||||||
|
riscv.REG_F12,
|
||||||
|
riscv.REG_F13,
|
||||||
|
riscv.REG_F14,
|
||||||
|
riscv.REG_F15,
|
||||||
|
riscv.REG_F16,
|
||||||
|
riscv.REG_F17,
|
||||||
|
riscv.REG_F18,
|
||||||
|
riscv.REG_F19,
|
||||||
|
riscv.REG_F20,
|
||||||
|
riscv.REG_F21,
|
||||||
|
riscv.REG_F22,
|
||||||
|
riscv.REG_F23,
|
||||||
|
riscv.REG_F24,
|
||||||
|
riscv.REG_F25,
|
||||||
|
riscv.REG_F26,
|
||||||
|
riscv.REG_F27,
|
||||||
|
riscv.REG_F28,
|
||||||
|
riscv.REG_F29,
|
||||||
|
riscv.REG_F30,
|
||||||
|
riscv.REG_F31,
|
||||||
|
0, // SB isn't a real register. We fill an Addr.Reg field with 0 in this case.
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadByType(t *types.Type) obj.As {
|
||||||
|
width := t.Size()
|
||||||
|
|
||||||
|
if t.IsFloat() {
|
||||||
|
switch width {
|
||||||
|
case 4:
|
||||||
|
return riscv.AMOVF
|
||||||
|
case 8:
|
||||||
|
return riscv.AMOVD
|
||||||
|
default:
|
||||||
|
gc.Fatalf("unknown float width for load %d in type %v", width, t)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch width {
|
||||||
|
case 1:
|
||||||
|
if t.IsSigned() {
|
||||||
|
return riscv.AMOVB
|
||||||
|
} else {
|
||||||
|
return riscv.AMOVBU
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
if t.IsSigned() {
|
||||||
|
return riscv.AMOVH
|
||||||
|
} else {
|
||||||
|
return riscv.AMOVHU
|
||||||
|
}
|
||||||
|
case 4:
|
||||||
|
if t.IsSigned() {
|
||||||
|
return riscv.AMOVW
|
||||||
|
} else {
|
||||||
|
return riscv.AMOVWU
|
||||||
|
}
|
||||||
|
case 8:
|
||||||
|
return riscv.AMOV
|
||||||
|
default:
|
||||||
|
gc.Fatalf("unknown width for load %d in type %v", width, t)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// storeByType returns the store instruction of the given type.
|
||||||
|
func storeByType(t *types.Type) obj.As {
|
||||||
|
width := t.Size()
|
||||||
|
|
||||||
|
if t.IsFloat() {
|
||||||
|
switch width {
|
||||||
|
case 4:
|
||||||
|
return riscv.AMOVF
|
||||||
|
case 8:
|
||||||
|
return riscv.AMOVD
|
||||||
|
default:
|
||||||
|
gc.Fatalf("unknown float width for store %d in type %v", width, t)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch width {
|
||||||
|
case 1:
|
||||||
|
return riscv.AMOVB
|
||||||
|
case 2:
|
||||||
|
return riscv.AMOVH
|
||||||
|
case 4:
|
||||||
|
return riscv.AMOVW
|
||||||
|
case 8:
|
||||||
|
return riscv.AMOV
|
||||||
|
default:
|
||||||
|
gc.Fatalf("unknown width for store %d in type %v", width, t)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// largestMove returns the largest move instruction possible and its size,
|
||||||
|
// given the alignment of the total size of the move.
|
||||||
|
//
|
||||||
|
// e.g., a 16-byte move may use MOV, but an 11-byte move must use MOVB.
|
||||||
|
//
|
||||||
|
// Note that the moves may not be on naturally aligned addresses depending on
|
||||||
|
// the source and destination.
|
||||||
|
//
|
||||||
|
// This matches the calculation in ssa.moveSize.
|
||||||
|
func largestMove(alignment int64) (obj.As, int64) {
|
||||||
|
switch {
|
||||||
|
case alignment%8 == 0:
|
||||||
|
return riscv.AMOV, 8
|
||||||
|
case alignment%4 == 0:
|
||||||
|
return riscv.AMOVW, 4
|
||||||
|
case alignment%2 == 0:
|
||||||
|
return riscv.AMOVH, 2
|
||||||
|
default:
|
||||||
|
return riscv.AMOVB, 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// markMoves marks any MOVXconst ops that need to avoid clobbering flags.
|
||||||
|
// RISC-V has no flags, so this is a no-op.
|
||||||
|
func ssaMarkMoves(s *gc.SSAGenState, b *ssa.Block) {}
|
||||||
|
|
||||||
|
func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||||
|
s.SetPos(v.Pos)
|
||||||
|
|
||||||
|
switch v.Op {
|
||||||
|
case ssa.OpInitMem:
|
||||||
|
// memory arg needs no code
|
||||||
|
case ssa.OpArg:
|
||||||
|
// input args need no code
|
||||||
|
case ssa.OpPhi:
|
||||||
|
gc.CheckLoweredPhi(v)
|
||||||
|
case ssa.OpCopy, ssa.OpRISCV64MOVconvert:
|
||||||
|
if v.Type.IsMemory() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rs := v.Args[0].Reg()
|
||||||
|
rd := v.Reg()
|
||||||
|
if rs == rd {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
as := riscv.AMOV
|
||||||
|
if v.Type.IsFloat() {
|
||||||
|
as = riscv.AMOVD
|
||||||
|
}
|
||||||
|
p := s.Prog(as)
|
||||||
|
p.From.Type = obj.TYPE_REG
|
||||||
|
p.From.Reg = rs
|
||||||
|
p.To.Type = obj.TYPE_REG
|
||||||
|
p.To.Reg = rd
|
||||||
|
case ssa.OpLoadReg:
|
||||||
|
if v.Type.IsFlags() {
|
||||||
|
v.Fatalf("load flags not implemented: %v", v.LongString())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p := s.Prog(loadByType(v.Type))
|
||||||
|
gc.AddrAuto(&p.From, v.Args[0])
|
||||||
|
p.To.Type = obj.TYPE_REG
|
||||||
|
p.To.Reg = v.Reg()
|
||||||
|
case ssa.OpStoreReg:
|
||||||
|
if v.Type.IsFlags() {
|
||||||
|
v.Fatalf("store flags not implemented: %v", v.LongString())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p := s.Prog(storeByType(v.Type))
|
||||||
|
p.From.Type = obj.TYPE_REG
|
||||||
|
p.From.Reg = v.Args[0].Reg()
|
||||||
|
gc.AddrAuto(&p.To, v)
|
||||||
|
case ssa.OpSP, ssa.OpSB, ssa.OpGetG:
|
||||||
|
// nothing to do
|
||||||
|
case ssa.OpRISCV64ADD, ssa.OpRISCV64SUB, ssa.OpRISCV64XOR, ssa.OpRISCV64OR, ssa.OpRISCV64AND,
|
||||||
|
ssa.OpRISCV64SLL, ssa.OpRISCV64SRA, ssa.OpRISCV64SRL,
|
||||||
|
ssa.OpRISCV64SLT, ssa.OpRISCV64SLTU, ssa.OpRISCV64MUL, ssa.OpRISCV64MULW, ssa.OpRISCV64MULH,
|
||||||
|
ssa.OpRISCV64MULHU, ssa.OpRISCV64DIV, ssa.OpRISCV64DIVU, ssa.OpRISCV64DIVW,
|
||||||
|
ssa.OpRISCV64DIVUW, ssa.OpRISCV64REM, ssa.OpRISCV64REMU, ssa.OpRISCV64REMW,
|
||||||
|
ssa.OpRISCV64REMUW,
|
||||||
|
ssa.OpRISCV64FADDS, ssa.OpRISCV64FSUBS, ssa.OpRISCV64FMULS, ssa.OpRISCV64FDIVS,
|
||||||
|
ssa.OpRISCV64FEQS, ssa.OpRISCV64FNES, ssa.OpRISCV64FLTS, ssa.OpRISCV64FLES,
|
||||||
|
ssa.OpRISCV64FADDD, ssa.OpRISCV64FSUBD, ssa.OpRISCV64FMULD, ssa.OpRISCV64FDIVD,
|
||||||
|
ssa.OpRISCV64FEQD, ssa.OpRISCV64FNED, ssa.OpRISCV64FLTD, ssa.OpRISCV64FLED:
|
||||||
|
r := v.Reg()
|
||||||
|
r1 := v.Args[0].Reg()
|
||||||
|
r2 := v.Args[1].Reg()
|
||||||
|
p := s.Prog(v.Op.Asm())
|
||||||
|
p.From.Type = obj.TYPE_REG
|
||||||
|
p.From.Reg = r2
|
||||||
|
p.Reg = r1
|
||||||
|
p.To.Type = obj.TYPE_REG
|
||||||
|
p.To.Reg = r
|
||||||
|
case ssa.OpRISCV64FSQRTS, ssa.OpRISCV64FNEGS, ssa.OpRISCV64FSQRTD, ssa.OpRISCV64FNEGD,
|
||||||
|
ssa.OpRISCV64FMVSX, ssa.OpRISCV64FMVDX,
|
||||||
|
ssa.OpRISCV64FCVTSW, ssa.OpRISCV64FCVTSL, ssa.OpRISCV64FCVTWS, ssa.OpRISCV64FCVTLS,
|
||||||
|
ssa.OpRISCV64FCVTDW, ssa.OpRISCV64FCVTDL, ssa.OpRISCV64FCVTWD, ssa.OpRISCV64FCVTLD, ssa.OpRISCV64FCVTDS, ssa.OpRISCV64FCVTSD:
|
||||||
|
p := s.Prog(v.Op.Asm())
|
||||||
|
p.From.Type = obj.TYPE_REG
|
||||||
|
p.From.Reg = v.Args[0].Reg()
|
||||||
|
p.To.Type = obj.TYPE_REG
|
||||||
|
p.To.Reg = v.Reg()
|
||||||
|
case ssa.OpRISCV64ADDI, ssa.OpRISCV64XORI, ssa.OpRISCV64ORI, ssa.OpRISCV64ANDI,
|
||||||
|
ssa.OpRISCV64SLLI, ssa.OpRISCV64SRAI, ssa.OpRISCV64SRLI, ssa.OpRISCV64SLTI,
|
||||||
|
ssa.OpRISCV64SLTIU:
|
||||||
|
p := s.Prog(v.Op.Asm())
|
||||||
|
p.From.Type = obj.TYPE_CONST
|
||||||
|
p.From.Offset = v.AuxInt
|
||||||
|
p.Reg = v.Args[0].Reg()
|
||||||
|
p.To.Type = obj.TYPE_REG
|
||||||
|
p.To.Reg = v.Reg()
|
||||||
|
case ssa.OpRISCV64MOVBconst, ssa.OpRISCV64MOVHconst, ssa.OpRISCV64MOVWconst, ssa.OpRISCV64MOVDconst:
|
||||||
|
p := s.Prog(v.Op.Asm())
|
||||||
|
p.From.Type = obj.TYPE_CONST
|
||||||
|
p.From.Offset = v.AuxInt
|
||||||
|
p.To.Type = obj.TYPE_REG
|
||||||
|
p.To.Reg = v.Reg()
|
||||||
|
case ssa.OpRISCV64MOVaddr:
|
||||||
|
p := s.Prog(v.Op.Asm())
|
||||||
|
p.From.Type = obj.TYPE_ADDR
|
||||||
|
p.To.Type = obj.TYPE_REG
|
||||||
|
p.To.Reg = v.Reg()
|
||||||
|
|
||||||
|
var wantreg string
|
||||||
|
// MOVW $sym+off(base), R
|
||||||
|
switch v.Aux.(type) {
|
||||||
|
default:
|
||||||
|
v.Fatalf("aux is of unknown type %T", v.Aux)
|
||||||
|
case *obj.LSym:
|
||||||
|
wantreg = "SB"
|
||||||
|
gc.AddAux(&p.From, v)
|
||||||
|
case *gc.Node:
|
||||||
|
wantreg = "SP"
|
||||||
|
gc.AddAux(&p.From, v)
|
||||||
|
case nil:
|
||||||
|
// No sym, just MOVW $off(SP), R
|
||||||
|
wantreg = "SP"
|
||||||
|
p.From.Reg = riscv.REG_SP
|
||||||
|
p.From.Offset = v.AuxInt
|
||||||
|
}
|
||||||
|
if reg := v.Args[0].RegName(); reg != wantreg {
|
||||||
|
v.Fatalf("bad reg %s for symbol type %T, want %s", reg, v.Aux, wantreg)
|
||||||
|
}
|
||||||
|
case ssa.OpRISCV64MOVBload, ssa.OpRISCV64MOVHload, ssa.OpRISCV64MOVWload, ssa.OpRISCV64MOVDload,
|
||||||
|
ssa.OpRISCV64MOVBUload, ssa.OpRISCV64MOVHUload, ssa.OpRISCV64MOVWUload,
|
||||||
|
ssa.OpRISCV64FMOVWload, ssa.OpRISCV64FMOVDload:
|
||||||
|
p := s.Prog(v.Op.Asm())
|
||||||
|
p.From.Type = obj.TYPE_MEM
|
||||||
|
p.From.Reg = v.Args[0].Reg()
|
||||||
|
gc.AddAux(&p.From, v)
|
||||||
|
p.To.Type = obj.TYPE_REG
|
||||||
|
p.To.Reg = v.Reg()
|
||||||
|
case ssa.OpRISCV64MOVBstore, ssa.OpRISCV64MOVHstore, ssa.OpRISCV64MOVWstore, ssa.OpRISCV64MOVDstore,
|
||||||
|
ssa.OpRISCV64FMOVWstore, ssa.OpRISCV64FMOVDstore:
|
||||||
|
p := s.Prog(v.Op.Asm())
|
||||||
|
p.From.Type = obj.TYPE_REG
|
||||||
|
p.From.Reg = v.Args[1].Reg()
|
||||||
|
p.To.Type = obj.TYPE_MEM
|
||||||
|
p.To.Reg = v.Args[0].Reg()
|
||||||
|
gc.AddAux(&p.To, v)
|
||||||
|
case ssa.OpRISCV64SEQZ, ssa.OpRISCV64SNEZ:
|
||||||
|
p := s.Prog(v.Op.Asm())
|
||||||
|
p.From.Type = obj.TYPE_REG
|
||||||
|
p.From.Reg = v.Args[0].Reg()
|
||||||
|
p.To.Type = obj.TYPE_REG
|
||||||
|
p.To.Reg = v.Reg()
|
||||||
|
case ssa.OpRISCV64CALLstatic, ssa.OpRISCV64CALLclosure, ssa.OpRISCV64CALLinter:
|
||||||
|
s.Call(v)
|
||||||
|
case ssa.OpRISCV64LoweredWB:
|
||||||
|
p := s.Prog(obj.ACALL)
|
||||||
|
p.To.Type = obj.TYPE_MEM
|
||||||
|
p.To.Name = obj.NAME_EXTERN
|
||||||
|
p.To.Sym = v.Aux.(*obj.LSym)
|
||||||
|
case ssa.OpRISCV64LoweredPanicBoundsA, ssa.OpRISCV64LoweredPanicBoundsB, ssa.OpRISCV64LoweredPanicBoundsC:
|
||||||
|
p := s.Prog(obj.ACALL)
|
||||||
|
p.To.Type = obj.TYPE_MEM
|
||||||
|
p.To.Name = obj.NAME_EXTERN
|
||||||
|
p.To.Sym = gc.BoundsCheckFunc[v.AuxInt]
|
||||||
|
s.UseArgs(16) // space used in callee args area by assembly stubs
|
||||||
|
case ssa.OpRISCV64LoweredZero:
|
||||||
|
mov, sz := largestMove(v.AuxInt)
|
||||||
|
|
||||||
|
// mov ZERO, (Rarg0)
|
||||||
|
// ADD $sz, Rarg0
|
||||||
|
// BGEU Rarg1, Rarg0, -2(PC)
|
||||||
|
|
||||||
|
p := s.Prog(mov)
|
||||||
|
p.From.Type = obj.TYPE_REG
|
||||||
|
p.From.Reg = riscv.REG_ZERO
|
||||||
|
p.To.Type = obj.TYPE_MEM
|
||||||
|
p.To.Reg = v.Args[0].Reg()
|
||||||
|
|
||||||
|
p2 := s.Prog(riscv.AADD)
|
||||||
|
p2.From.Type = obj.TYPE_CONST
|
||||||
|
p2.From.Offset = sz
|
||||||
|
p2.To.Type = obj.TYPE_REG
|
||||||
|
p2.To.Reg = v.Args[0].Reg()
|
||||||
|
|
||||||
|
p3 := s.Prog(riscv.ABGEU)
|
||||||
|
p3.To.Type = obj.TYPE_BRANCH
|
||||||
|
p3.Reg = v.Args[0].Reg()
|
||||||
|
p3.From.Type = obj.TYPE_REG
|
||||||
|
p3.From.Reg = v.Args[1].Reg()
|
||||||
|
gc.Patch(p3, p)
|
||||||
|
|
||||||
|
case ssa.OpRISCV64LoweredMove:
|
||||||
|
mov, sz := largestMove(v.AuxInt)
|
||||||
|
|
||||||
|
// mov (Rarg1), T2
|
||||||
|
// mov T2, (Rarg0)
|
||||||
|
// ADD $sz, Rarg0
|
||||||
|
// ADD $sz, Rarg1
|
||||||
|
// BGEU Rarg2, Rarg0, -4(PC)
|
||||||
|
|
||||||
|
p := s.Prog(mov)
|
||||||
|
p.From.Type = obj.TYPE_MEM
|
||||||
|
p.From.Reg = v.Args[1].Reg()
|
||||||
|
p.To.Type = obj.TYPE_REG
|
||||||
|
p.To.Reg = riscv.REG_T2
|
||||||
|
|
||||||
|
p2 := s.Prog(mov)
|
||||||
|
p2.From.Type = obj.TYPE_REG
|
||||||
|
p2.From.Reg = riscv.REG_T2
|
||||||
|
p2.To.Type = obj.TYPE_MEM
|
||||||
|
p2.To.Reg = v.Args[0].Reg()
|
||||||
|
|
||||||
|
p3 := s.Prog(riscv.AADD)
|
||||||
|
p3.From.Type = obj.TYPE_CONST
|
||||||
|
p3.From.Offset = sz
|
||||||
|
p3.To.Type = obj.TYPE_REG
|
||||||
|
p3.To.Reg = v.Args[0].Reg()
|
||||||
|
|
||||||
|
p4 := s.Prog(riscv.AADD)
|
||||||
|
p4.From.Type = obj.TYPE_CONST
|
||||||
|
p4.From.Offset = sz
|
||||||
|
p4.To.Type = obj.TYPE_REG
|
||||||
|
p4.To.Reg = v.Args[1].Reg()
|
||||||
|
|
||||||
|
p5 := s.Prog(riscv.ABGEU)
|
||||||
|
p5.To.Type = obj.TYPE_BRANCH
|
||||||
|
p5.Reg = v.Args[1].Reg()
|
||||||
|
p5.From.Type = obj.TYPE_REG
|
||||||
|
p5.From.Reg = v.Args[2].Reg()
|
||||||
|
gc.Patch(p5, p)
|
||||||
|
|
||||||
|
case ssa.OpRISCV64LoweredNilCheck:
|
||||||
|
// Issue a load which will fault if arg is nil.
|
||||||
|
// TODO: optimizations. See arm and amd64 LoweredNilCheck.
|
||||||
|
p := s.Prog(riscv.AMOVB)
|
||||||
|
p.From.Type = obj.TYPE_MEM
|
||||||
|
p.From.Reg = v.Args[0].Reg()
|
||||||
|
gc.AddAux(&p.From, v)
|
||||||
|
p.To.Type = obj.TYPE_REG
|
||||||
|
p.To.Reg = riscv.REG_ZERO
|
||||||
|
if gc.Debug_checknil != 0 && v.Pos.Line() > 1 { // v.Pos == 1 in generated wrappers
|
||||||
|
gc.Warnl(v.Pos, "generated nil check")
|
||||||
|
}
|
||||||
|
|
||||||
|
case ssa.OpRISCV64LoweredGetClosurePtr:
|
||||||
|
// Closure pointer is S4 (riscv.REG_CTXT).
|
||||||
|
gc.CheckLoweredGetClosurePtr(v)
|
||||||
|
|
||||||
|
case ssa.OpRISCV64LoweredGetCallerSP:
|
||||||
|
// caller's SP is FixedFrameSize below the address of the first arg
|
||||||
|
p := s.Prog(riscv.AMOV)
|
||||||
|
p.From.Type = obj.TYPE_ADDR
|
||||||
|
p.From.Offset = -gc.Ctxt.FixedFrameSize()
|
||||||
|
p.From.Name = obj.NAME_PARAM
|
||||||
|
p.To.Type = obj.TYPE_REG
|
||||||
|
p.To.Reg = v.Reg()
|
||||||
|
|
||||||
|
case ssa.OpRISCV64LoweredGetCallerPC:
|
||||||
|
p := s.Prog(obj.AGETCALLERPC)
|
||||||
|
p.To.Type = obj.TYPE_REG
|
||||||
|
p.To.Reg = v.Reg()
|
||||||
|
|
||||||
|
default:
|
||||||
|
v.Fatalf("Unhandled op %v", v.Op)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
|
||||||
|
s.SetPos(b.Pos)
|
||||||
|
|
||||||
|
switch b.Kind {
|
||||||
|
case ssa.BlockDefer:
|
||||||
|
// defer returns in A0:
|
||||||
|
// 0 if we should continue executing
|
||||||
|
// 1 if we should jump to deferreturn call
|
||||||
|
p := s.Prog(riscv.ABNE)
|
||||||
|
p.To.Type = obj.TYPE_BRANCH
|
||||||
|
p.From.Type = obj.TYPE_REG
|
||||||
|
p.From.Reg = riscv.REG_ZERO
|
||||||
|
p.Reg = riscv.REG_A0
|
||||||
|
s.Branches = append(s.Branches, gc.Branch{P: p, B: b.Succs[1].Block()})
|
||||||
|
if b.Succs[0].Block() != next {
|
||||||
|
p := s.Prog(obj.AJMP)
|
||||||
|
p.To.Type = obj.TYPE_BRANCH
|
||||||
|
s.Branches = append(s.Branches, gc.Branch{P: p, B: b.Succs[0].Block()})
|
||||||
|
}
|
||||||
|
case ssa.BlockPlain:
|
||||||
|
if b.Succs[0].Block() != next {
|
||||||
|
p := s.Prog(obj.AJMP)
|
||||||
|
p.To.Type = obj.TYPE_BRANCH
|
||||||
|
s.Branches = append(s.Branches, gc.Branch{P: p, B: b.Succs[0].Block()})
|
||||||
|
}
|
||||||
|
case ssa.BlockExit:
|
||||||
|
case ssa.BlockRet:
|
||||||
|
s.Prog(obj.ARET)
|
||||||
|
case ssa.BlockRetJmp:
|
||||||
|
p := s.Prog(obj.AJMP)
|
||||||
|
p.To.Type = obj.TYPE_MEM
|
||||||
|
p.To.Name = obj.NAME_EXTERN
|
||||||
|
p.To.Sym = b.Aux.(*obj.LSym)
|
||||||
|
case ssa.BlockRISCV64BNE:
|
||||||
|
var p *obj.Prog
|
||||||
|
switch next {
|
||||||
|
case b.Succs[0].Block():
|
||||||
|
p = s.Br(riscv.ABNE, b.Succs[1].Block())
|
||||||
|
p.As = riscv.InvertBranch(p.As)
|
||||||
|
case b.Succs[1].Block():
|
||||||
|
p = s.Br(riscv.ABNE, b.Succs[0].Block())
|
||||||
|
default:
|
||||||
|
if b.Likely != ssa.BranchUnlikely {
|
||||||
|
p = s.Br(riscv.ABNE, b.Succs[0].Block())
|
||||||
|
s.Br(obj.AJMP, b.Succs[1].Block())
|
||||||
|
} else {
|
||||||
|
p = s.Br(riscv.ABNE, b.Succs[1].Block())
|
||||||
|
p.As = riscv.InvertBranch(p.As)
|
||||||
|
s.Br(obj.AJMP, b.Succs[0].Block())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.Reg = b.Controls[0].Reg()
|
||||||
|
p.From.Type = obj.TYPE_REG
|
||||||
|
p.From.Reg = riscv.REG_ZERO
|
||||||
|
|
||||||
|
default:
|
||||||
|
b.Fatalf("Unhandled block: %s", b.LongString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -305,6 +305,16 @@ func NewConfig(arch string, types Types, ctxt *obj.Link, optimize bool) *Config
|
||||||
c.LinkReg = linkRegMIPS
|
c.LinkReg = linkRegMIPS
|
||||||
c.hasGReg = true
|
c.hasGReg = true
|
||||||
c.noDuffDevice = true
|
c.noDuffDevice = true
|
||||||
|
case "riscv64":
|
||||||
|
c.PtrSize = 8
|
||||||
|
c.RegSize = 8
|
||||||
|
c.lowerBlock = rewriteBlockRISCV64
|
||||||
|
c.lowerValue = rewriteValueRISCV64
|
||||||
|
c.registers = registersRISCV64[:]
|
||||||
|
c.gpRegMask = gpRegMaskRISCV64
|
||||||
|
c.fpRegMask = fpRegMaskRISCV64
|
||||||
|
c.FPReg = framepointerRegRISCV64
|
||||||
|
c.hasGReg = true
|
||||||
case "wasm":
|
case "wasm":
|
||||||
c.PtrSize = 8
|
c.PtrSize = 8
|
||||||
c.RegSize = 8
|
c.RegSize = 8
|
||||||
|
|
|
||||||
|
|
@ -153,7 +153,7 @@ func init() {
|
||||||
// TODO(josharian): move universe initialization to the types package,
|
// TODO(josharian): move universe initialization to the types package,
|
||||||
// so this test setup can share it.
|
// so this test setup can share it.
|
||||||
|
|
||||||
types.Tconv = func(t *types.Type, flag, mode, depth int) string {
|
types.Tconv = func(t *types.Type, flag, mode int) string {
|
||||||
return t.Etype.String()
|
return t.Etype.String()
|
||||||
}
|
}
|
||||||
types.Sconv = func(s *types.Sym, flag, mode int) string {
|
types.Sconv = func(s *types.Sym, flag, mode int) string {
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,7 @@ func fuseBlockIf(b *Block) bool {
|
||||||
// There may be false positives.
|
// There may be false positives.
|
||||||
func isEmpty(b *Block) bool {
|
func isEmpty(b *Block) bool {
|
||||||
for _, v := range b.Values {
|
for _, v := range b.Values {
|
||||||
if v.Uses > 0 || v.Type.IsVoid() {
|
if v.Uses > 0 || v.Op.IsCall() || v.Op.HasSideEffects() || v.Type.IsVoid() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ func TestFuseEliminatesBothBranches(t *testing.T) {
|
||||||
t.Errorf("then was not eliminated, but should have")
|
t.Errorf("then was not eliminated, but should have")
|
||||||
}
|
}
|
||||||
if b == fun.blocks["else"] && b.Kind != BlockInvalid {
|
if b == fun.blocks["else"] && b.Kind != BlockInvalid {
|
||||||
t.Errorf("then was not eliminated, but should have")
|
t.Errorf("else was not eliminated, but should have")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -97,7 +97,7 @@ func TestFuseHandlesPhis(t *testing.T) {
|
||||||
t.Errorf("then was not eliminated, but should have")
|
t.Errorf("then was not eliminated, but should have")
|
||||||
}
|
}
|
||||||
if b == fun.blocks["else"] && b.Kind != BlockInvalid {
|
if b == fun.blocks["else"] && b.Kind != BlockInvalid {
|
||||||
t.Errorf("then was not eliminated, but should have")
|
t.Errorf("else was not eliminated, but should have")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -131,6 +131,40 @@ func TestFuseEliminatesEmptyBlocks(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFuseSideEffects(t *testing.T) {
|
||||||
|
// Test that we don't fuse branches that have side effects but
|
||||||
|
// have no use (e.g. followed by infinite loop).
|
||||||
|
// See issue #36005.
|
||||||
|
c := testConfig(t)
|
||||||
|
fun := c.Fun("entry",
|
||||||
|
Bloc("entry",
|
||||||
|
Valu("mem", OpInitMem, types.TypeMem, 0, nil),
|
||||||
|
Valu("b", OpArg, c.config.Types.Bool, 0, nil),
|
||||||
|
If("b", "then", "else")),
|
||||||
|
Bloc("then",
|
||||||
|
Valu("call1", OpStaticCall, types.TypeMem, 0, nil, "mem"),
|
||||||
|
Goto("empty")),
|
||||||
|
Bloc("else",
|
||||||
|
Valu("call2", OpStaticCall, types.TypeMem, 0, nil, "mem"),
|
||||||
|
Goto("empty")),
|
||||||
|
Bloc("empty",
|
||||||
|
Goto("loop")),
|
||||||
|
Bloc("loop",
|
||||||
|
Goto("loop")))
|
||||||
|
|
||||||
|
CheckFunc(fun.f)
|
||||||
|
fuseAll(fun.f)
|
||||||
|
|
||||||
|
for _, b := range fun.f.Blocks {
|
||||||
|
if b == fun.blocks["then"] && b.Kind == BlockInvalid {
|
||||||
|
t.Errorf("then is eliminated, but should not")
|
||||||
|
}
|
||||||
|
if b == fun.blocks["else"] && b.Kind == BlockInvalid {
|
||||||
|
t.Errorf("else is eliminated, but should not")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkFuse(b *testing.B) {
|
func BenchmarkFuse(b *testing.B) {
|
||||||
for _, n := range [...]int{1, 10, 100, 1000, 10000} {
|
for _, n := range [...]int{1, 10, 100, 1000, 10000} {
|
||||||
b.Run(strconv.Itoa(n), func(b *testing.B) {
|
b.Run(strconv.Itoa(n), func(b *testing.B) {
|
||||||
|
|
|
||||||
|
|
@ -813,7 +813,7 @@
|
||||||
(MFVSRD x:(FMOVDload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVDload [off] {sym} ptr mem)
|
(MFVSRD x:(FMOVDload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVDload [off] {sym} ptr mem)
|
||||||
|
|
||||||
// Fold offsets for stores.
|
// Fold offsets for stores.
|
||||||
(MOVDstore [off1] {sym} (ADDconst [off2] x) val mem) && is16Bit(off1+off2) -> (MOVDstore [off1+off2] {sym} x val mem)
|
(MOVDstore [off1] {sym} (ADDconst [off2] x) val mem) && is16Bit(off1+off2) && (off1+off2)%4 == 0 -> (MOVDstore [off1+off2] {sym} x val mem)
|
||||||
(MOVWstore [off1] {sym} (ADDconst [off2] x) val mem) && is16Bit(off1+off2) -> (MOVWstore [off1+off2] {sym} x val mem)
|
(MOVWstore [off1] {sym} (ADDconst [off2] x) val mem) && is16Bit(off1+off2) -> (MOVWstore [off1+off2] {sym} x val mem)
|
||||||
(MOVHstore [off1] {sym} (ADDconst [off2] x) val mem) && is16Bit(off1+off2) -> (MOVHstore [off1+off2] {sym} x val mem)
|
(MOVHstore [off1] {sym} (ADDconst [off2] x) val mem) && is16Bit(off1+off2) -> (MOVHstore [off1+off2] {sym} x val mem)
|
||||||
(MOVBstore [off1] {sym} (ADDconst [off2] x) val mem) && is16Bit(off1+off2) -> (MOVBstore [off1+off2] {sym} x val mem)
|
(MOVBstore [off1] {sym} (ADDconst [off2] x) val mem) && is16Bit(off1+off2) -> (MOVBstore [off1+off2] {sym} x val mem)
|
||||||
|
|
@ -836,7 +836,7 @@
|
||||||
&& (ptr.Op != OpSB || p.Uses == 1) ->
|
&& (ptr.Op != OpSB || p.Uses == 1) ->
|
||||||
(MOVWstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
|
(MOVWstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
|
||||||
(MOVDstore [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2)
|
(MOVDstore [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2)
|
||||||
&& (ptr.Op != OpSB || p.Uses == 1) ->
|
&& (ptr.Op != OpSB || p.Uses == 1) && (off1+off2)%4 == 0 ->
|
||||||
(MOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
|
(MOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
|
||||||
|
|
||||||
(FMOVSstore [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2)
|
(FMOVSstore [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2)
|
||||||
|
|
@ -856,13 +856,13 @@
|
||||||
&& (ptr.Op != OpSB || p.Uses == 1) ->
|
&& (ptr.Op != OpSB || p.Uses == 1) ->
|
||||||
(MOVHZload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
(MOVHZload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||||
(MOVWload [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
|
(MOVWload [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
|
||||||
&& (ptr.Op != OpSB || p.Uses == 1) ->
|
&& (ptr.Op != OpSB || p.Uses == 1) && (off1+off2)%4 == 0 ->
|
||||||
(MOVWload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
(MOVWload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||||
(MOVWZload [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
|
(MOVWZload [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
|
||||||
&& (ptr.Op != OpSB || p.Uses == 1) ->
|
&& (ptr.Op != OpSB || p.Uses == 1) ->
|
||||||
(MOVWZload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
(MOVWZload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||||
(MOVDload [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
|
(MOVDload [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
|
||||||
&& (ptr.Op != OpSB || p.Uses == 1) ->
|
&& (ptr.Op != OpSB || p.Uses == 1) && (off1+off2)%4 == 0 ->
|
||||||
(MOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
(MOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||||
(FMOVSload [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
|
(FMOVSload [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
|
||||||
&& (ptr.Op != OpSB || p.Uses == 1) ->
|
&& (ptr.Op != OpSB || p.Uses == 1) ->
|
||||||
|
|
@ -875,8 +875,8 @@
|
||||||
(FMOVSload [off1] {sym} (ADDconst [off2] ptr) mem) && is16Bit(off1+off2) -> (FMOVSload [off1+off2] {sym} ptr mem)
|
(FMOVSload [off1] {sym} (ADDconst [off2] ptr) mem) && is16Bit(off1+off2) -> (FMOVSload [off1+off2] {sym} ptr mem)
|
||||||
(FMOVDload [off1] {sym} (ADDconst [off2] ptr) mem) && is16Bit(off1+off2) -> (FMOVDload [off1+off2] {sym} ptr mem)
|
(FMOVDload [off1] {sym} (ADDconst [off2] ptr) mem) && is16Bit(off1+off2) -> (FMOVDload [off1+off2] {sym} ptr mem)
|
||||||
|
|
||||||
(MOVDload [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(off1+off2) -> (MOVDload [off1+off2] {sym} x mem)
|
(MOVDload [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(off1+off2) && (off1+off2)%4 == 0 -> (MOVDload [off1+off2] {sym} x mem)
|
||||||
(MOVWload [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(off1+off2) -> (MOVWload [off1+off2] {sym} x mem)
|
(MOVWload [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(off1+off2) && (off1+off2)%4 == 0 -> (MOVWload [off1+off2] {sym} x mem)
|
||||||
(MOVWZload [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(off1+off2) -> (MOVWZload [off1+off2] {sym} x mem)
|
(MOVWZload [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(off1+off2) -> (MOVWZload [off1+off2] {sym} x mem)
|
||||||
(MOVHload [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(off1+off2) -> (MOVHload [off1+off2] {sym} x mem)
|
(MOVHload [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(off1+off2) -> (MOVHload [off1+off2] {sym} x mem)
|
||||||
(MOVHZload [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(off1+off2) -> (MOVHZload [off1+off2] {sym} x mem)
|
(MOVHZload [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(off1+off2) -> (MOVHZload [off1+off2] {sym} x mem)
|
||||||
|
|
@ -886,9 +886,10 @@
|
||||||
(MOV(D|W|WZ|H|HZ|BZ)load [0] {sym} p:(ADD ptr idx) mem) && sym == nil && p.Uses == 1 -> (MOV(D|W|WZ|H|HZ|BZ)loadidx ptr idx mem)
|
(MOV(D|W|WZ|H|HZ|BZ)load [0] {sym} p:(ADD ptr idx) mem) && sym == nil && p.Uses == 1 -> (MOV(D|W|WZ|H|HZ|BZ)loadidx ptr idx mem)
|
||||||
|
|
||||||
// Determine indexed loads with constant values that can be done without index
|
// Determine indexed loads with constant values that can be done without index
|
||||||
(MOV(D|W|WZ|H|HZ|BZ)loadidx ptr (MOVDconst [c]) mem) && is16Bit(c) -> (MOV(D|W|WZ|H|HZ|BZ)load [c] ptr mem)
|
(MOV(D|W)loadidx ptr (MOVDconst [c]) mem) && is16Bit(c) && c%4 == 0 -> (MOV(D|W)load [c] ptr mem)
|
||||||
(MOV(D|W|WZ|H|HZ|BZ)loadidx (MOVDconst [c]) ptr mem) && is16Bit(c) -> (MOV(D|W|WZ|H|HZ|BZ)load [c] ptr mem)
|
(MOV(WZ|H|HZ|BZ)loadidx ptr (MOVDconst [c]) mem) && is16Bit(c) -> (MOV(WZ|H|HZ|BZ)load [c] ptr mem)
|
||||||
|
(MOV(D|W)loadidx (MOVDconst [c]) ptr mem) && is16Bit(c) && c%4 == 0 -> (MOV(D|W)load [c] ptr mem)
|
||||||
|
(MOV(WZ|H|HZ|BZ)loadidx (MOVDconst [c]) ptr mem) && is16Bit(c) -> (MOV(WZ|H|HZ|BZ)load [c] ptr mem)
|
||||||
|
|
||||||
// Store of zero -> storezero
|
// Store of zero -> storezero
|
||||||
(MOVDstore [off] {sym} ptr (MOVDconst [0]) mem) -> (MOVDstorezero [off] {sym} ptr mem)
|
(MOVDstore [off] {sym} ptr (MOVDconst [0]) mem) -> (MOVDstorezero [off] {sym} ptr mem)
|
||||||
|
|
@ -897,7 +898,7 @@
|
||||||
(MOVBstore [off] {sym} ptr (MOVDconst [0]) mem) -> (MOVBstorezero [off] {sym} ptr mem)
|
(MOVBstore [off] {sym} ptr (MOVDconst [0]) mem) -> (MOVBstorezero [off] {sym} ptr mem)
|
||||||
|
|
||||||
// Fold offsets for storezero
|
// Fold offsets for storezero
|
||||||
(MOVDstorezero [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(off1+off2) ->
|
(MOVDstorezero [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(off1+off2) && (off1+off2)%4 == 0 ->
|
||||||
(MOVDstorezero [off1+off2] {sym} x mem)
|
(MOVDstorezero [off1+off2] {sym} x mem)
|
||||||
(MOVWstorezero [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(off1+off2) ->
|
(MOVWstorezero [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(off1+off2) ->
|
||||||
(MOVWstorezero [off1+off2] {sym} x mem)
|
(MOVWstorezero [off1+off2] {sym} x mem)
|
||||||
|
|
@ -910,12 +911,14 @@
|
||||||
(MOV(D|W|H|B)store [off] {sym} p:(ADD ptr idx) val mem) && off == 0 && sym == nil && p.Uses == 1 -> (MOV(D|W|H|B)storeidx ptr idx val mem)
|
(MOV(D|W|H|B)store [off] {sym} p:(ADD ptr idx) val mem) && off == 0 && sym == nil && p.Uses == 1 -> (MOV(D|W|H|B)storeidx ptr idx val mem)
|
||||||
|
|
||||||
// Stores with constant index values can be done without indexed instructions
|
// Stores with constant index values can be done without indexed instructions
|
||||||
(MOV(D|W|H|B)storeidx ptr (MOVDconst [c]) val mem) && is16Bit(c) -> (MOV(D|W|H|B)store [c] ptr val mem)
|
(MOVDstoreidx ptr (MOVDconst [c]) val mem) && is16Bit(c) && c%4 == 0 -> (MOVDstore [c] ptr val mem)
|
||||||
(MOV(D|W|H|B)storeidx (MOVDconst [c]) ptr val mem) && is16Bit(c) -> (MOV(D|W|H|B)store [c] ptr val mem)
|
(MOV(W|H|B)storeidx ptr (MOVDconst [c]) val mem) && is16Bit(c) -> (MOV(W|H|B)store [c] ptr val mem)
|
||||||
|
(MOVDstoreidx (MOVDconst [c]) ptr val mem) && is16Bit(c) && c%4 == 0 -> (MOVDstore [c] ptr val mem)
|
||||||
|
(MOV(W|H|B)storeidx (MOVDconst [c]) ptr val mem) && is16Bit(c) -> (MOV(W|H|B)store [c] ptr val mem)
|
||||||
|
|
||||||
// Fold symbols into storezero
|
// Fold symbols into storezero
|
||||||
(MOVDstorezero [off1] {sym1} p:(MOVDaddr [off2] {sym2} x) mem) && canMergeSym(sym1,sym2)
|
(MOVDstorezero [off1] {sym1} p:(MOVDaddr [off2] {sym2} x) mem) && canMergeSym(sym1,sym2)
|
||||||
&& (x.Op != OpSB || p.Uses == 1) ->
|
&& (x.Op != OpSB || p.Uses == 1) && (off1+off2)%4 == 0 ->
|
||||||
(MOVDstorezero [off1+off2] {mergeSym(sym1,sym2)} x mem)
|
(MOVDstorezero [off1+off2] {mergeSym(sym1,sym2)} x mem)
|
||||||
(MOVWstorezero [off1] {sym1} p:(MOVDaddr [off2] {sym2} x) mem) && canMergeSym(sym1,sym2)
|
(MOVWstorezero [off1] {sym1} p:(MOVDaddr [off2] {sym2} x) mem) && canMergeSym(sym1,sym2)
|
||||||
&& (x.Op != OpSB || p.Uses == 1) ->
|
&& (x.Op != OpSB || p.Uses == 1) ->
|
||||||
|
|
|
||||||
478
src/cmd/compile/internal/ssa/gen/RISCV64.rules
Normal file
478
src/cmd/compile/internal/ssa/gen/RISCV64.rules
Normal file
|
|
@ -0,0 +1,478 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// Optimizations TODO:
|
||||||
|
// * Somehow track when values are already zero/signed-extended, avoid re-extending.
|
||||||
|
// * Use SLTI and SLTIU for comparisons to constants, instead of SLT/SLTU with constants in registers
|
||||||
|
// * Find a more efficient way to do zero/sign extension than left+right shift.
|
||||||
|
// There are many other options (store then load-extend, LUI+ANDI for zero extend, special case 32->64, ...),
|
||||||
|
// but left+right shift is simple and uniform, and we don't have real hardware to do perf testing on anyway.
|
||||||
|
// * Use the zero register instead of moving 0 into a register.
|
||||||
|
// * Add rules to avoid generating a temp bool value for (If (SLT[U] ...) ...).
|
||||||
|
// * Optimize left and right shift by simplifying SLTIU, Neg, and ADD for constants.
|
||||||
|
// * Arrange for non-trivial Zero and Move lowerings to use aligned loads and stores.
|
||||||
|
// * Eliminate zero immediate shifts, adds, etc.
|
||||||
|
// * Use a Duff's device for some moves and zeros.
|
||||||
|
// * Avoid using Neq32 for writeBarrier.enabled checks.
|
||||||
|
|
||||||
|
// Lowering arithmetic
|
||||||
|
(Add64 x y) -> (ADD x y)
|
||||||
|
(AddPtr x y) -> (ADD x y)
|
||||||
|
(Add32 x y) -> (ADD x y)
|
||||||
|
(Add16 x y) -> (ADD x y)
|
||||||
|
(Add8 x y) -> (ADD x y)
|
||||||
|
(Add32F x y) -> (FADDS x y)
|
||||||
|
(Add64F x y) -> (FADDD x y)
|
||||||
|
|
||||||
|
(Sub64 x y) -> (SUB x y)
|
||||||
|
(SubPtr x y) -> (SUB x y)
|
||||||
|
(Sub32 x y) -> (SUB x y)
|
||||||
|
(Sub16 x y) -> (SUB x y)
|
||||||
|
(Sub8 x y) -> (SUB x y)
|
||||||
|
(Sub32F x y) -> (FSUBS x y)
|
||||||
|
(Sub64F x y) -> (FSUBD x y)
|
||||||
|
|
||||||
|
(Mul64 x y) -> (MUL x y)
|
||||||
|
(Mul32 x y) -> (MULW x y)
|
||||||
|
(Mul16 x y) -> (MULW (SignExt16to32 x) (SignExt16to32 y))
|
||||||
|
(Mul8 x y) -> (MULW (SignExt8to32 x) (SignExt8to32 y))
|
||||||
|
(Mul32F x y) -> (FMULS x y)
|
||||||
|
(Mul64F x y) -> (FMULD x y)
|
||||||
|
|
||||||
|
(Div32F x y) -> (FDIVS x y)
|
||||||
|
(Div64F x y) -> (FDIVD x y)
|
||||||
|
|
||||||
|
(Div64 x y) -> (DIV x y)
|
||||||
|
(Div64u x y) -> (DIVU x y)
|
||||||
|
(Div32 x y) -> (DIVW x y)
|
||||||
|
(Div32u x y) -> (DIVUW x y)
|
||||||
|
(Div16 x y) -> (DIVW (SignExt16to32 x) (SignExt16to32 y))
|
||||||
|
(Div16u x y) -> (DIVUW (ZeroExt16to32 x) (ZeroExt16to32 y))
|
||||||
|
(Div8 x y) -> (DIVW (SignExt8to32 x) (SignExt8to32 y))
|
||||||
|
(Div8u x y) -> (DIVUW (ZeroExt8to32 x) (ZeroExt8to32 y))
|
||||||
|
|
||||||
|
(Hmul64 x y) -> (MULH x y)
|
||||||
|
(Hmul64u x y) -> (MULHU x y)
|
||||||
|
(Hmul32 x y) -> (SRAI [32] (MUL (SignExt32to64 x) (SignExt32to64 y)))
|
||||||
|
(Hmul32u x y) -> (SRLI [32] (MUL (ZeroExt32to64 x) (ZeroExt32to64 y)))
|
||||||
|
|
||||||
|
// (x + y) / 2 -> (x / 2) + (y / 2) + (x & y & 1)
|
||||||
|
(Avg64u <t> x y) -> (ADD (ADD <t> (SRLI <t> [1] x) (SRLI <t> [1] y)) (ANDI <t> [1] (AND <t> x y)))
|
||||||
|
|
||||||
|
(Mod64 x y) -> (REM x y)
|
||||||
|
(Mod64u x y) -> (REMU x y)
|
||||||
|
(Mod32 x y) -> (REMW x y)
|
||||||
|
(Mod32u x y) -> (REMUW x y)
|
||||||
|
(Mod16 x y) -> (REMW (SignExt16to32 x) (SignExt16to32 y))
|
||||||
|
(Mod16u x y) -> (REMUW (ZeroExt16to32 x) (ZeroExt16to32 y))
|
||||||
|
(Mod8 x y) -> (REMW (SignExt8to32 x) (SignExt8to32 y))
|
||||||
|
(Mod8u x y) -> (REMUW (ZeroExt8to32 x) (ZeroExt8to32 y))
|
||||||
|
|
||||||
|
(And64 x y) -> (AND x y)
|
||||||
|
(And32 x y) -> (AND x y)
|
||||||
|
(And16 x y) -> (AND x y)
|
||||||
|
(And8 x y) -> (AND x y)
|
||||||
|
|
||||||
|
(Or64 x y) -> (OR x y)
|
||||||
|
(Or32 x y) -> (OR x y)
|
||||||
|
(Or16 x y) -> (OR x y)
|
||||||
|
(Or8 x y) -> (OR x y)
|
||||||
|
|
||||||
|
(Xor64 x y) -> (XOR x y)
|
||||||
|
(Xor32 x y) -> (XOR x y)
|
||||||
|
(Xor16 x y) -> (XOR x y)
|
||||||
|
(Xor8 x y) -> (XOR x y)
|
||||||
|
|
||||||
|
(Neg64 x) -> (SUB (MOVDconst) x)
|
||||||
|
(Neg32 x) -> (SUB (MOVWconst) x)
|
||||||
|
(Neg16 x) -> (SUB (MOVHconst) x)
|
||||||
|
(Neg8 x) -> (SUB (MOVBconst) x)
|
||||||
|
(Neg32F x) -> (FNEGS x)
|
||||||
|
(Neg64F x) -> (FNEGD x)
|
||||||
|
|
||||||
|
(Com64 x) -> (XORI [int64(-1)] x)
|
||||||
|
(Com32 x) -> (XORI [int64(-1)] x)
|
||||||
|
(Com16 x) -> (XORI [int64(-1)] x)
|
||||||
|
(Com8 x) -> (XORI [int64(-1)] x)
|
||||||
|
|
||||||
|
(Sqrt x) -> (FSQRTD x)
|
||||||
|
|
||||||
|
// Zero and sign extension
|
||||||
|
// Shift left until the bits we want are at the top of the register.
|
||||||
|
// Then logical/arithmetic shift right for zero/sign extend.
|
||||||
|
// We always extend to 64 bits; there's no reason not to,
|
||||||
|
// and optimization rules can then collapse some extensions.
|
||||||
|
|
||||||
|
(SignExt8to16 <t> x) -> (SRAI [56] (SLLI <t> [56] x))
|
||||||
|
(SignExt8to32 <t> x) -> (SRAI [56] (SLLI <t> [56] x))
|
||||||
|
(SignExt8to64 <t> x) -> (SRAI [56] (SLLI <t> [56] x))
|
||||||
|
(SignExt16to32 <t> x) -> (SRAI [48] (SLLI <t> [48] x))
|
||||||
|
(SignExt16to64 <t> x) -> (SRAI [48] (SLLI <t> [48] x))
|
||||||
|
(SignExt32to64 <t> x) -> (SRAI [32] (SLLI <t> [32] x))
|
||||||
|
|
||||||
|
(ZeroExt8to16 <t> x) -> (SRLI [56] (SLLI <t> [56] x))
|
||||||
|
(ZeroExt8to32 <t> x) -> (SRLI [56] (SLLI <t> [56] x))
|
||||||
|
(ZeroExt8to64 <t> x) -> (SRLI [56] (SLLI <t> [56] x))
|
||||||
|
(ZeroExt16to32 <t> x) -> (SRLI [48] (SLLI <t> [48] x))
|
||||||
|
(ZeroExt16to64 <t> x) -> (SRLI [48] (SLLI <t> [48] x))
|
||||||
|
(ZeroExt32to64 <t> x) -> (SRLI [32] (SLLI <t> [32] x))
|
||||||
|
|
||||||
|
(Cvt32to32F x) -> (FCVTSW x)
|
||||||
|
(Cvt32to64F x) -> (FCVTDW x)
|
||||||
|
(Cvt64to32F x) -> (FCVTSL x)
|
||||||
|
(Cvt64to64F x) -> (FCVTDL x)
|
||||||
|
|
||||||
|
(Cvt32Fto32 x) -> (FCVTWS x)
|
||||||
|
(Cvt32Fto64 x) -> (FCVTLS x)
|
||||||
|
(Cvt64Fto32 x) -> (FCVTWD x)
|
||||||
|
(Cvt64Fto64 x) -> (FCVTLD x)
|
||||||
|
|
||||||
|
(Cvt32Fto64F x) -> (FCVTDS x)
|
||||||
|
(Cvt64Fto32F x) -> (FCVTSD x)
|
||||||
|
|
||||||
|
(Round32F x) -> x
|
||||||
|
(Round64F x) -> x
|
||||||
|
|
||||||
|
// From genericOps.go:
|
||||||
|
// "0 if arg0 == 0, -1 if arg0 > 0, undef if arg0<0"
|
||||||
|
//
|
||||||
|
// Like other arches, we compute ~((x-1) >> 63), with arithmetic right shift.
|
||||||
|
// For positive x, bit 63 of x-1 is always 0, so the result is -1.
|
||||||
|
// For zero x, bit 63 of x-1 is 1, so the result is 0.
|
||||||
|
//
|
||||||
|
// TODO(prattmic): Use XORconst etc instead of XOR (MOVDconst).
|
||||||
|
(Slicemask <t> x) -> (XOR (MOVDconst [-1]) (SRA <t> (SUB <t> x (MOVDconst [1])) (MOVDconst [63])))
|
||||||
|
|
||||||
|
// Truncations
|
||||||
|
// We ignore the unused high parts of registers, so truncates are just copies.
|
||||||
|
(Trunc16to8 x) -> x
|
||||||
|
(Trunc32to8 x) -> x
|
||||||
|
(Trunc32to16 x) -> x
|
||||||
|
(Trunc64to8 x) -> x
|
||||||
|
(Trunc64to16 x) -> x
|
||||||
|
(Trunc64to32 x) -> x
|
||||||
|
|
||||||
|
// Shifts
|
||||||
|
|
||||||
|
// SLL only considers the bottom 6 bits of y. If y > 64, the result should
|
||||||
|
// always be 0.
|
||||||
|
//
|
||||||
|
// Breaking down the operation:
|
||||||
|
//
|
||||||
|
// (SLL x y) generates x << (y & 63).
|
||||||
|
//
|
||||||
|
// If y < 64, this is the value we want. Otherwise, we want zero.
|
||||||
|
//
|
||||||
|
// So, we AND with -1 * uint64(y < 64), which is 0xfffff... if y < 64 and 0 otherwise.
|
||||||
|
(Lsh8x8 <t> x y) -> (AND (SLL <t> x y) (Neg8 <t> (SLTIU <t> [64] (ZeroExt8to64 y))))
|
||||||
|
(Lsh8x16 <t> x y) -> (AND (SLL <t> x y) (Neg8 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
|
||||||
|
(Lsh8x32 <t> x y) -> (AND (SLL <t> x y) (Neg8 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
|
||||||
|
(Lsh8x64 <t> x y) -> (AND (SLL <t> x y) (Neg8 <t> (SLTIU <t> [64] y)))
|
||||||
|
(Lsh16x8 <t> x y) -> (AND (SLL <t> x y) (Neg16 <t> (SLTIU <t> [64] (ZeroExt8to64 y))))
|
||||||
|
(Lsh16x16 <t> x y) -> (AND (SLL <t> x y) (Neg16 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
|
||||||
|
(Lsh16x32 <t> x y) -> (AND (SLL <t> x y) (Neg16 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
|
||||||
|
(Lsh16x64 <t> x y) -> (AND (SLL <t> x y) (Neg16 <t> (SLTIU <t> [64] y)))
|
||||||
|
(Lsh32x8 <t> x y) -> (AND (SLL <t> x y) (Neg32 <t> (SLTIU <t> [64] (ZeroExt8to64 y))))
|
||||||
|
(Lsh32x16 <t> x y) -> (AND (SLL <t> x y) (Neg32 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
|
||||||
|
(Lsh32x32 <t> x y) -> (AND (SLL <t> x y) (Neg32 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
|
||||||
|
(Lsh32x64 <t> x y) -> (AND (SLL <t> x y) (Neg32 <t> (SLTIU <t> [64] y)))
|
||||||
|
(Lsh64x8 <t> x y) -> (AND (SLL <t> x y) (Neg64 <t> (SLTIU <t> [64] (ZeroExt8to64 y))))
|
||||||
|
(Lsh64x16 <t> x y) -> (AND (SLL <t> x y) (Neg64 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
|
||||||
|
(Lsh64x32 <t> x y) -> (AND (SLL <t> x y) (Neg64 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
|
||||||
|
(Lsh64x64 <t> x y) -> (AND (SLL <t> x y) (Neg64 <t> (SLTIU <t> [64] y)))
|
||||||
|
|
||||||
|
// SRL only considers the bottom 6 bits of y. If y > 64, the result should
|
||||||
|
// always be 0. See Lsh above for a detailed description.
|
||||||
|
(Rsh8Ux8 <t> x y) -> (AND (SRL <t> (ZeroExt8to64 x) y) (Neg8 <t> (SLTIU <t> [64] (ZeroExt8to64 y))))
|
||||||
|
(Rsh8Ux16 <t> x y) -> (AND (SRL <t> (ZeroExt8to64 x) y) (Neg8 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
|
||||||
|
(Rsh8Ux32 <t> x y) -> (AND (SRL <t> (ZeroExt8to64 x) y) (Neg8 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
|
||||||
|
(Rsh8Ux64 <t> x y) -> (AND (SRL <t> (ZeroExt8to64 x) y) (Neg8 <t> (SLTIU <t> [64] y)))
|
||||||
|
(Rsh16Ux8 <t> x y) -> (AND (SRL <t> (ZeroExt16to64 x) y) (Neg16 <t> (SLTIU <t> [64] (ZeroExt8to64 y))))
|
||||||
|
(Rsh16Ux16 <t> x y) -> (AND (SRL <t> (ZeroExt16to64 x) y) (Neg16 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
|
||||||
|
(Rsh16Ux32 <t> x y) -> (AND (SRL <t> (ZeroExt16to64 x) y) (Neg16 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
|
||||||
|
(Rsh16Ux64 <t> x y) -> (AND (SRL <t> (ZeroExt16to64 x) y) (Neg16 <t> (SLTIU <t> [64] y)))
|
||||||
|
(Rsh32Ux8 <t> x y) -> (AND (SRL <t> (ZeroExt32to64 x) y) (Neg32 <t> (SLTIU <t> [64] (ZeroExt8to64 y))))
|
||||||
|
(Rsh32Ux16 <t> x y) -> (AND (SRL <t> (ZeroExt32to64 x) y) (Neg32 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
|
||||||
|
(Rsh32Ux32 <t> x y) -> (AND (SRL <t> (ZeroExt32to64 x) y) (Neg32 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
|
||||||
|
(Rsh32Ux64 <t> x y) -> (AND (SRL <t> (ZeroExt32to64 x) y) (Neg32 <t> (SLTIU <t> [64] y)))
|
||||||
|
(Rsh64Ux8 <t> x y) -> (AND (SRL <t> x y) (Neg64 <t> (SLTIU <t> [64] (ZeroExt8to64 y))))
|
||||||
|
(Rsh64Ux16 <t> x y) -> (AND (SRL <t> x y) (Neg64 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
|
||||||
|
(Rsh64Ux32 <t> x y) -> (AND (SRL <t> x y) (Neg64 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
|
||||||
|
(Rsh64Ux64 <t> x y) -> (AND (SRL <t> x y) (Neg64 <t> (SLTIU <t> [64] y)))
|
||||||
|
|
||||||
|
// SRA only considers the bottom 6 bits of y. If y > 64, the result should
|
||||||
|
// be either 0 or -1 based on the sign bit.
|
||||||
|
//
|
||||||
|
// We implement this by performing the max shift (-1) if y >= 64.
|
||||||
|
//
|
||||||
|
// We OR (uint64(y < 64) - 1) into y before passing it to SRA. This leaves
|
||||||
|
// us with -1 (0xffff...) if y >= 64.
|
||||||
|
//
|
||||||
|
// We don't need to sign-extend the OR result, as it will be at minimum 8 bits,
|
||||||
|
// more than the 6 bits SRA cares about.
|
||||||
|
(Rsh8x8 <t> x y) -> (SRA <t> (SignExt8to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt8to64 y)))))
|
||||||
|
(Rsh8x16 <t> x y) -> (SRA <t> (SignExt8to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt16to64 y)))))
|
||||||
|
(Rsh8x32 <t> x y) -> (SRA <t> (SignExt8to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt32to64 y)))))
|
||||||
|
(Rsh8x64 <t> x y) -> (SRA <t> (SignExt8to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] y))))
|
||||||
|
(Rsh16x8 <t> x y) -> (SRA <t> (SignExt16to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt8to64 y)))))
|
||||||
|
(Rsh16x16 <t> x y) -> (SRA <t> (SignExt16to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt16to64 y)))))
|
||||||
|
(Rsh16x32 <t> x y) -> (SRA <t> (SignExt16to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt32to64 y)))))
|
||||||
|
(Rsh16x64 <t> x y) -> (SRA <t> (SignExt16to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] y))))
|
||||||
|
(Rsh32x8 <t> x y) -> (SRA <t> (SignExt32to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt8to64 y)))))
|
||||||
|
(Rsh32x16 <t> x y) -> (SRA <t> (SignExt32to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt16to64 y)))))
|
||||||
|
(Rsh32x32 <t> x y) -> (SRA <t> (SignExt32to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt32to64 y)))))
|
||||||
|
(Rsh32x64 <t> x y) -> (SRA <t> (SignExt32to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] y))))
|
||||||
|
(Rsh64x8 <t> x y) -> (SRA <t> x (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt8to64 y)))))
|
||||||
|
(Rsh64x16 <t> x y) -> (SRA <t> x (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt16to64 y)))))
|
||||||
|
(Rsh64x32 <t> x y) -> (SRA <t> x (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt32to64 y)))))
|
||||||
|
(Rsh64x64 <t> x y) -> (SRA <t> x (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] y))))
|
||||||
|
|
||||||
|
// rotates
|
||||||
|
(RotateLeft8 <t> x (MOVBconst [c])) -> (Or8 (Lsh8x64 <t> x (MOVBconst [c&7])) (Rsh8Ux64 <t> x (MOVBconst [-c&7])))
|
||||||
|
(RotateLeft16 <t> x (MOVHconst [c])) -> (Or16 (Lsh16x64 <t> x (MOVHconst [c&15])) (Rsh16Ux64 <t> x (MOVHconst [-c&15])))
|
||||||
|
(RotateLeft32 <t> x (MOVWconst [c])) -> (Or32 (Lsh32x64 <t> x (MOVWconst [c&31])) (Rsh32Ux64 <t> x (MOVWconst [-c&31])))
|
||||||
|
(RotateLeft64 <t> x (MOVDconst [c])) -> (Or64 (Lsh64x64 <t> x (MOVDconst [c&63])) (Rsh64Ux64 <t> x (MOVDconst [-c&63])))
|
||||||
|
|
||||||
|
(Less64 x y) -> (SLT x y)
|
||||||
|
(Less32 x y) -> (SLT (SignExt32to64 x) (SignExt32to64 y))
|
||||||
|
(Less16 x y) -> (SLT (SignExt16to64 x) (SignExt16to64 y))
|
||||||
|
(Less8 x y) -> (SLT (SignExt8to64 x) (SignExt8to64 y))
|
||||||
|
(Less64U x y) -> (SLTU x y)
|
||||||
|
(Less32U x y) -> (SLTU (ZeroExt32to64 x) (ZeroExt32to64 y))
|
||||||
|
(Less16U x y) -> (SLTU (ZeroExt16to64 x) (ZeroExt16to64 y))
|
||||||
|
(Less8U x y) -> (SLTU (ZeroExt8to64 x) (ZeroExt8to64 y))
|
||||||
|
(Less64F x y) -> (FLTD x y)
|
||||||
|
(Less32F x y) -> (FLTS x y)
|
||||||
|
|
||||||
|
// Convert x <= y to !(y > x).
|
||||||
|
(Leq64 x y) -> (Not (Less64 y x))
|
||||||
|
(Leq32 x y) -> (Not (Less32 y x))
|
||||||
|
(Leq16 x y) -> (Not (Less16 y x))
|
||||||
|
(Leq8 x y) -> (Not (Less8 y x))
|
||||||
|
(Leq64U x y) -> (Not (Less64U y x))
|
||||||
|
(Leq32U x y) -> (Not (Less32U y x))
|
||||||
|
(Leq16U x y) -> (Not (Less16U y x))
|
||||||
|
(Leq8U x y) -> (Not (Less8U y x))
|
||||||
|
(Leq64F x y) -> (FLED x y)
|
||||||
|
(Leq32F x y) -> (FLES x y)
|
||||||
|
|
||||||
|
// Convert x > y to y < x.
|
||||||
|
(Greater64 x y) -> (Less64 y x)
|
||||||
|
(Greater32 x y) -> (Less32 y x)
|
||||||
|
(Greater16 x y) -> (Less16 y x)
|
||||||
|
(Greater8 x y) -> (Less8 y x)
|
||||||
|
(Greater64U x y) -> (Less64U y x)
|
||||||
|
(Greater32U x y) -> (Less32U y x)
|
||||||
|
(Greater16U x y) -> (Less16U y x)
|
||||||
|
(Greater8U x y) -> (Less8U y x)
|
||||||
|
(Greater64F x y) -> (FLTD y x)
|
||||||
|
(Greater32F x y) -> (FLTS y x)
|
||||||
|
|
||||||
|
// Convert x >= y to !(x < y)
|
||||||
|
(Geq64 x y) -> (Not (Less64 x y))
|
||||||
|
(Geq32 x y) -> (Not (Less32 x y))
|
||||||
|
(Geq16 x y) -> (Not (Less16 x y))
|
||||||
|
(Geq8 x y) -> (Not (Less8 x y))
|
||||||
|
(Geq64U x y) -> (Not (Less64U x y))
|
||||||
|
(Geq32U x y) -> (Not (Less32U x y))
|
||||||
|
(Geq16U x y) -> (Not (Less16U x y))
|
||||||
|
(Geq8U x y) -> (Not (Less8U x y))
|
||||||
|
(Geq64F x y) -> (FLED y x)
|
||||||
|
(Geq32F x y) -> (FLES y x)
|
||||||
|
|
||||||
|
(EqPtr x y) -> (SEQZ (SUB <x.Type> x y))
|
||||||
|
(Eq64 x y) -> (SEQZ (SUB <x.Type> x y))
|
||||||
|
(Eq32 x y) -> (SEQZ (ZeroExt32to64 (SUB <x.Type> x y)))
|
||||||
|
(Eq16 x y) -> (SEQZ (ZeroExt16to64 (SUB <x.Type> x y)))
|
||||||
|
(Eq8 x y) -> (SEQZ (ZeroExt8to64 (SUB <x.Type> x y)))
|
||||||
|
(Eq64F x y) -> (FEQD x y)
|
||||||
|
(Eq32F x y) -> (FEQS x y)
|
||||||
|
|
||||||
|
(NeqPtr x y) -> (SNEZ (SUB <x.Type> x y))
|
||||||
|
(Neq64 x y) -> (SNEZ (SUB <x.Type> x y))
|
||||||
|
(Neq32 x y) -> (SNEZ (ZeroExt32to64 (SUB <x.Type> x y)))
|
||||||
|
(Neq16 x y) -> (SNEZ (ZeroExt16to64 (SUB <x.Type> x y)))
|
||||||
|
(Neq8 x y) -> (SNEZ (ZeroExt8to64 (SUB <x.Type> x y)))
|
||||||
|
(Neq64F x y) -> (FNED x y)
|
||||||
|
(Neq32F x y) -> (FNES x y)
|
||||||
|
|
||||||
|
// Loads
|
||||||
|
(Load <t> ptr mem) && t.IsBoolean() -> (MOVBUload ptr mem)
|
||||||
|
(Load <t> ptr mem) && ( is8BitInt(t) && isSigned(t)) -> (MOVBload ptr mem)
|
||||||
|
(Load <t> ptr mem) && ( is8BitInt(t) && !isSigned(t)) -> (MOVBUload ptr mem)
|
||||||
|
(Load <t> ptr mem) && (is16BitInt(t) && isSigned(t)) -> (MOVHload ptr mem)
|
||||||
|
(Load <t> ptr mem) && (is16BitInt(t) && !isSigned(t)) -> (MOVHUload ptr mem)
|
||||||
|
(Load <t> ptr mem) && (is32BitInt(t) && isSigned(t)) -> (MOVWload ptr mem)
|
||||||
|
(Load <t> ptr mem) && (is32BitInt(t) && !isSigned(t)) -> (MOVWUload ptr mem)
|
||||||
|
(Load <t> ptr mem) && (is64BitInt(t) || isPtr(t)) -> (MOVDload ptr mem)
|
||||||
|
(Load <t> ptr mem) && is32BitFloat(t) -> (FMOVWload ptr mem)
|
||||||
|
(Load <t> ptr mem) && is64BitFloat(t) -> (FMOVDload ptr mem)
|
||||||
|
|
||||||
|
// Stores
|
||||||
|
(Store {t} ptr val mem) && t.(*types.Type).Size() == 1 -> (MOVBstore ptr val mem)
|
||||||
|
(Store {t} ptr val mem) && t.(*types.Type).Size() == 2 -> (MOVHstore ptr val mem)
|
||||||
|
(Store {t} ptr val mem) && t.(*types.Type).Size() == 4 && !is32BitFloat(val.Type) -> (MOVWstore ptr val mem)
|
||||||
|
(Store {t} ptr val mem) && t.(*types.Type).Size() == 8 && !is64BitFloat(val.Type) -> (MOVDstore ptr val mem)
|
||||||
|
(Store {t} ptr val mem) && t.(*types.Type).Size() == 4 && is32BitFloat(val.Type) -> (FMOVWstore ptr val mem)
|
||||||
|
(Store {t} ptr val mem) && t.(*types.Type).Size() == 8 && is64BitFloat(val.Type) -> (FMOVDstore ptr val mem)
|
||||||
|
|
||||||
|
// We need to fold MOVaddr into the LD/MOVDstore ops so that the live variable analysis
|
||||||
|
// knows what variables are being read/written by the ops.
|
||||||
|
(MOVBUload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) ->
|
||||||
|
(MOVBUload [off1+off2] {mergeSym(sym1,sym2)} base mem)
|
||||||
|
(MOVBload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) ->
|
||||||
|
(MOVBload [off1+off2] {mergeSym(sym1,sym2)} base mem)
|
||||||
|
(MOVHUload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) ->
|
||||||
|
(MOVHUload [off1+off2] {mergeSym(sym1,sym2)} base mem)
|
||||||
|
(MOVHload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) ->
|
||||||
|
(MOVHload [off1+off2] {mergeSym(sym1,sym2)} base mem)
|
||||||
|
(MOVWUload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) ->
|
||||||
|
(MOVWUload [off1+off2] {mergeSym(sym1,sym2)} base mem)
|
||||||
|
(MOVWload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) ->
|
||||||
|
(MOVWload [off1+off2] {mergeSym(sym1,sym2)} base mem)
|
||||||
|
(MOVDload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) ->
|
||||||
|
(MOVDload [off1+off2] {mergeSym(sym1,sym2)} base mem)
|
||||||
|
|
||||||
|
(MOVBstore [off1] {sym1} (MOVaddr [off2] {sym2} base) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) ->
|
||||||
|
(MOVBstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
|
||||||
|
(MOVHstore [off1] {sym1} (MOVaddr [off2] {sym2} base) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) ->
|
||||||
|
(MOVHstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
|
||||||
|
(MOVWstore [off1] {sym1} (MOVaddr [off2] {sym2} base) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) ->
|
||||||
|
(MOVWstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
|
||||||
|
(MOVDstore [off1] {sym1} (MOVaddr [off2] {sym2} base) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) ->
|
||||||
|
(MOVDstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
|
||||||
|
|
||||||
|
(MOVBUload [off1] {sym} (ADDI [off2] base) mem) && is32Bit(off1+off2) ->
|
||||||
|
(MOVBUload [off1+off2] {sym} base mem)
|
||||||
|
(MOVBload [off1] {sym} (ADDI [off2] base) mem) && is32Bit(off1+off2) ->
|
||||||
|
(MOVBload [off1+off2] {sym} base mem)
|
||||||
|
(MOVHUload [off1] {sym} (ADDI [off2] base) mem) && is32Bit(off1+off2) ->
|
||||||
|
(MOVHUload [off1+off2] {sym} base mem)
|
||||||
|
(MOVHload [off1] {sym} (ADDI [off2] base) mem) && is32Bit(off1+off2) ->
|
||||||
|
(MOVHload [off1+off2] {sym} base mem)
|
||||||
|
(MOVWUload [off1] {sym} (ADDI [off2] base) mem) && is32Bit(off1+off2) ->
|
||||||
|
(MOVWUload [off1+off2] {sym} base mem)
|
||||||
|
(MOVWload [off1] {sym} (ADDI [off2] base) mem) && is32Bit(off1+off2) ->
|
||||||
|
(MOVWload [off1+off2] {sym} base mem)
|
||||||
|
(MOVDload [off1] {sym} (ADDI [off2] base) mem) && is32Bit(off1+off2) ->
|
||||||
|
(MOVDload [off1+off2] {sym} base mem)
|
||||||
|
|
||||||
|
(MOVBstore [off1] {sym} (ADDI [off2] base) val mem) && is32Bit(off1+off2) ->
|
||||||
|
(MOVBstore [off1+off2] {sym} base val mem)
|
||||||
|
(MOVHstore [off1] {sym} (ADDI [off2] base) val mem) && is32Bit(off1+off2) ->
|
||||||
|
(MOVHstore [off1+off2] {sym} base val mem)
|
||||||
|
(MOVWstore [off1] {sym} (ADDI [off2] base) val mem) && is32Bit(off1+off2) ->
|
||||||
|
(MOVWstore [off1+off2] {sym} base val mem)
|
||||||
|
(MOVDstore [off1] {sym} (ADDI [off2] base) val mem) && is32Bit(off1+off2) ->
|
||||||
|
(MOVDstore [off1+off2] {sym} base val mem)
|
||||||
|
|
||||||
|
// Similarly, fold ADDI into MOVaddr to avoid confusing live variable analysis
|
||||||
|
// with OffPtr -> ADDI.
|
||||||
|
(ADDI [c] (MOVaddr [d] {s} x)) && is32Bit(c+d) -> (MOVaddr [c+d] {s} x)
|
||||||
|
|
||||||
|
// Zeroing
|
||||||
|
// TODO: more optimized zeroing, including attempting to use aligned accesses.
|
||||||
|
(Zero [0] _ mem) -> mem
|
||||||
|
(Zero [1] ptr mem) -> (MOVBstore ptr (MOVBconst) mem)
|
||||||
|
(Zero [2] ptr mem) -> (MOVHstore ptr (MOVHconst) mem)
|
||||||
|
(Zero [4] ptr mem) -> (MOVWstore ptr (MOVWconst) mem)
|
||||||
|
(Zero [8] ptr mem) -> (MOVDstore ptr (MOVDconst) mem)
|
||||||
|
|
||||||
|
// Generic zeroing uses a loop
|
||||||
|
(Zero [s] {t} ptr mem) ->
|
||||||
|
(LoweredZero [t.(*types.Type).Alignment()]
|
||||||
|
ptr
|
||||||
|
(ADD <ptr.Type> ptr (MOVDconst [s-moveSize(t.(*types.Type).Alignment(), config)]))
|
||||||
|
mem)
|
||||||
|
|
||||||
|
(Convert x mem) -> (MOVconvert x mem)
|
||||||
|
|
||||||
|
// Checks
|
||||||
|
(IsNonNil p) -> (NeqPtr (MOVDconst) p)
|
||||||
|
(IsInBounds idx len) -> (Less64U idx len)
|
||||||
|
(IsSliceInBounds idx len) -> (Leq64U idx len)
|
||||||
|
|
||||||
|
// Trivial lowering
|
||||||
|
(NilCheck ptr mem) -> (LoweredNilCheck ptr mem)
|
||||||
|
(GetClosurePtr) -> (LoweredGetClosurePtr)
|
||||||
|
(GetCallerSP) -> (LoweredGetCallerSP)
|
||||||
|
(GetCallerPC) -> (LoweredGetCallerPC)
|
||||||
|
|
||||||
|
// Write barrier.
|
||||||
|
(WB {fn} destptr srcptr mem) -> (LoweredWB {fn} destptr srcptr mem)
|
||||||
|
|
||||||
|
(PanicBounds [kind] x y mem) && boundsABI(kind) == 0 -> (LoweredPanicBoundsA [kind] x y mem)
|
||||||
|
(PanicBounds [kind] x y mem) && boundsABI(kind) == 1 -> (LoweredPanicBoundsB [kind] x y mem)
|
||||||
|
(PanicBounds [kind] x y mem) && boundsABI(kind) == 2 -> (LoweredPanicBoundsC [kind] x y mem)
|
||||||
|
|
||||||
|
// Moves
|
||||||
|
// TODO: more optimized moves, including attempting to use aligned accesses.
|
||||||
|
(Move [0] _ _ mem) -> mem
|
||||||
|
(Move [1] dst src mem) -> (MOVBstore dst (MOVBload src mem) mem)
|
||||||
|
(Move [2] dst src mem) -> (MOVHstore dst (MOVHload src mem) mem)
|
||||||
|
(Move [4] dst src mem) -> (MOVWstore dst (MOVWload src mem) mem)
|
||||||
|
(Move [8] dst src mem) -> (MOVDstore dst (MOVDload src mem) mem)
|
||||||
|
|
||||||
|
// Generic move uses a loop
|
||||||
|
(Move [s] {t} dst src mem) ->
|
||||||
|
(LoweredMove [t.(*types.Type).Alignment()]
|
||||||
|
dst
|
||||||
|
src
|
||||||
|
(ADDI <src.Type> [s-moveSize(t.(*types.Type).Alignment(), config)] src)
|
||||||
|
mem)
|
||||||
|
|
||||||
|
// Boolean ops; 0=false, 1=true
|
||||||
|
(AndB x y) -> (AND x y)
|
||||||
|
(OrB x y) -> (OR x y)
|
||||||
|
(EqB x y) -> (XORI [1] (XOR <typ.Bool> x y))
|
||||||
|
(NeqB x y) -> (XOR x y)
|
||||||
|
(Not x) -> (XORI [1] x)
|
||||||
|
|
||||||
|
// Lowering pointer arithmetic
|
||||||
|
// TODO: Special handling for SP offsets, like ARM
|
||||||
|
(OffPtr [off] ptr:(SP)) -> (MOVaddr [off] ptr)
|
||||||
|
(OffPtr [off] ptr) && is32Bit(off) -> (ADDI [off] ptr)
|
||||||
|
(OffPtr [off] ptr) -> (ADD (MOVDconst [off]) ptr)
|
||||||
|
|
||||||
|
(Const8 [val]) -> (MOVBconst [val])
|
||||||
|
(Const16 [val]) -> (MOVHconst [val])
|
||||||
|
(Const32 [val]) -> (MOVWconst [val])
|
||||||
|
(Const64 [val]) -> (MOVDconst [val])
|
||||||
|
(Const32F [val]) -> (FMVSX (MOVWconst [int64(int32(math.Float32bits(float32(math.Float64frombits(uint64(val))))))]))
|
||||||
|
(Const64F [val]) -> (FMVDX (MOVDconst [val]))
|
||||||
|
(ConstNil) -> (MOVDconst [0])
|
||||||
|
(ConstBool [b]) -> (MOVBconst [b])
|
||||||
|
|
||||||
|
// Convert 64 bit immediate to two 32 bit immediates, combine with add and shift.
|
||||||
|
// The lower 32 bit immediate will be treated as signed,
|
||||||
|
// so if it is negative, adjust for the borrow by incrementing the top half.
|
||||||
|
// We don't have to worry about overflow from the increment,
|
||||||
|
// because if the top half is all 1s, and int32(c) is negative,
|
||||||
|
// then the overall constant fits in an int32.
|
||||||
|
(MOVDconst <t> [c]) && !is32Bit(c) && int32(c) < 0 -> (ADD (SLLI <t> [32] (MOVDconst [c>>32+1])) (MOVDconst [int64(int32(c))]))
|
||||||
|
(MOVDconst <t> [c]) && !is32Bit(c) && int32(c) >= 0 -> (ADD (SLLI <t> [32] (MOVDconst [c>>32+0])) (MOVDconst [int64(int32(c))]))
|
||||||
|
|
||||||
|
// Fold ADD+MOVDconst into ADDI where possible.
|
||||||
|
(ADD (MOVDconst [off]) ptr) && is32Bit(off) -> (ADDI [off] ptr)
|
||||||
|
|
||||||
|
(Addr {sym} base) -> (MOVaddr {sym} base)
|
||||||
|
(LocalAddr {sym} base _) -> (MOVaddr {sym} base)
|
||||||
|
|
||||||
|
// Conditional branches
|
||||||
|
//
|
||||||
|
// cond is 1 if true. BNE compares against 0.
|
||||||
|
//
|
||||||
|
// TODO(prattmic): RISCV branch instructions take two operands to compare,
|
||||||
|
// so we could generate more efficient code by computing the condition in the
|
||||||
|
// branch itself. This should be revisited now that the compiler has support
|
||||||
|
// for two control values (https://golang.org/cl/196557).
|
||||||
|
(If cond yes no) -> (BNE cond yes no)
|
||||||
|
|
||||||
|
// Calls
|
||||||
|
(StaticCall [argwid] {target} mem) -> (CALLstatic [argwid] {target} mem)
|
||||||
|
(ClosureCall [argwid] entry closure mem) -> (CALLclosure [argwid] entry closure mem)
|
||||||
|
(InterCall [argwid] entry mem) -> (CALLinter [argwid] entry mem)
|
||||||
|
|
||||||
|
// remove redundant *const ops
|
||||||
|
(ADDI [0] x) -> x
|
||||||
338
src/cmd/compile/internal/ssa/gen/RISCV64Ops.go
Normal file
338
src/cmd/compile/internal/ssa/gen/RISCV64Ops.go
Normal file
|
|
@ -0,0 +1,338 @@
|
||||||
|
// 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 ignore
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Suffixes encode the bit width of various instructions:
|
||||||
|
//
|
||||||
|
// D (double word) = 64 bit int
|
||||||
|
// W (word) = 32 bit int
|
||||||
|
// H (half word) = 16 bit int
|
||||||
|
// B (byte) = 8 bit int
|
||||||
|
// S (single) = 32 bit float
|
||||||
|
// D (double) = 64 bit float
|
||||||
|
// L = 64 bit int, used when the opcode starts with F
|
||||||
|
|
||||||
|
const (
|
||||||
|
riscv64REG_G = 4
|
||||||
|
riscv64REG_CTXT = 20
|
||||||
|
riscv64REG_LR = 1
|
||||||
|
riscv64REG_SP = 2
|
||||||
|
riscv64REG_TMP = 31
|
||||||
|
riscv64REG_ZERO = 0
|
||||||
|
)
|
||||||
|
|
||||||
|
func riscv64RegName(r int) string {
|
||||||
|
switch {
|
||||||
|
case r == riscv64REG_G:
|
||||||
|
return "g"
|
||||||
|
case r == riscv64REG_SP:
|
||||||
|
return "SP"
|
||||||
|
case 0 <= r && r <= 31:
|
||||||
|
return fmt.Sprintf("X%d", r)
|
||||||
|
case 32 <= r && r <= 63:
|
||||||
|
return fmt.Sprintf("F%d", r-32)
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unknown register %d", r))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
var regNamesRISCV64 []string
|
||||||
|
var gpMask, fpMask, gpspMask, gpspsbMask regMask
|
||||||
|
regNamed := make(map[string]regMask)
|
||||||
|
|
||||||
|
// Build the list of register names, creating an appropriately indexed
|
||||||
|
// regMask for the gp and fp registers as we go.
|
||||||
|
//
|
||||||
|
// If name is specified, use it rather than the riscv reg number.
|
||||||
|
addreg := func(r int, name string) regMask {
|
||||||
|
mask := regMask(1) << uint(len(regNamesRISCV64))
|
||||||
|
if name == "" {
|
||||||
|
name = riscv64RegName(r)
|
||||||
|
}
|
||||||
|
regNamesRISCV64 = append(regNamesRISCV64, name)
|
||||||
|
regNamed[name] = mask
|
||||||
|
return mask
|
||||||
|
}
|
||||||
|
|
||||||
|
// General purpose registers.
|
||||||
|
for r := 0; r <= 31; r++ {
|
||||||
|
if r == riscv64REG_LR {
|
||||||
|
// LR is not used by regalloc, so we skip it to leave
|
||||||
|
// room for pseudo-register SB.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
mask := addreg(r, "")
|
||||||
|
|
||||||
|
// Add general purpose registers to gpMask.
|
||||||
|
switch r {
|
||||||
|
// ZERO, g, and TMP are not in any gp mask.
|
||||||
|
case riscv64REG_ZERO, riscv64REG_G, riscv64REG_TMP:
|
||||||
|
case riscv64REG_SP:
|
||||||
|
gpspMask |= mask
|
||||||
|
gpspsbMask |= mask
|
||||||
|
default:
|
||||||
|
gpMask |= mask
|
||||||
|
gpspMask |= mask
|
||||||
|
gpspsbMask |= mask
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Floating pointer registers.
|
||||||
|
for r := 32; r <= 63; r++ {
|
||||||
|
mask := addreg(r, "")
|
||||||
|
fpMask |= mask
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pseudo-register: SB
|
||||||
|
mask := addreg(-1, "SB")
|
||||||
|
gpspsbMask |= mask
|
||||||
|
|
||||||
|
if len(regNamesRISCV64) > 64 {
|
||||||
|
// regMask is only 64 bits.
|
||||||
|
panic("Too many RISCV64 registers")
|
||||||
|
}
|
||||||
|
|
||||||
|
regCtxt := regNamed["X20"]
|
||||||
|
callerSave := gpMask | fpMask | regNamed["g"]
|
||||||
|
|
||||||
|
var (
|
||||||
|
gpstore = regInfo{inputs: []regMask{gpspsbMask, gpspMask, 0}} // SB in first input so we can load from a global, but not in second to avoid using SB as a temporary register
|
||||||
|
gp01 = regInfo{outputs: []regMask{gpMask}}
|
||||||
|
gp11 = regInfo{inputs: []regMask{gpMask}, outputs: []regMask{gpMask}}
|
||||||
|
gp21 = regInfo{inputs: []regMask{gpMask, gpMask}, outputs: []regMask{gpMask}}
|
||||||
|
gpload = regInfo{inputs: []regMask{gpspsbMask, 0}, outputs: []regMask{gpMask}}
|
||||||
|
gp11sb = regInfo{inputs: []regMask{gpspsbMask}, outputs: []regMask{gpMask}}
|
||||||
|
|
||||||
|
fp11 = regInfo{inputs: []regMask{fpMask}, outputs: []regMask{fpMask}}
|
||||||
|
fp21 = regInfo{inputs: []regMask{fpMask, fpMask}, outputs: []regMask{fpMask}}
|
||||||
|
gpfp = regInfo{inputs: []regMask{gpMask}, outputs: []regMask{fpMask}}
|
||||||
|
fpgp = regInfo{inputs: []regMask{fpMask}, outputs: []regMask{gpMask}}
|
||||||
|
fpstore = regInfo{inputs: []regMask{gpspsbMask, fpMask, 0}}
|
||||||
|
fpload = regInfo{inputs: []regMask{gpspsbMask, 0}, outputs: []regMask{fpMask}}
|
||||||
|
fp2gp = regInfo{inputs: []regMask{fpMask, fpMask}, outputs: []regMask{gpMask}}
|
||||||
|
|
||||||
|
call = regInfo{clobbers: callerSave}
|
||||||
|
callClosure = regInfo{inputs: []regMask{gpspMask, regCtxt, 0}, clobbers: callerSave}
|
||||||
|
callInter = regInfo{inputs: []regMask{gpMask}, clobbers: callerSave}
|
||||||
|
)
|
||||||
|
|
||||||
|
RISCV64ops := []opData{
|
||||||
|
{name: "ADD", argLength: 2, reg: gp21, asm: "ADD", commutative: true}, // arg0 + arg1
|
||||||
|
{name: "ADDI", argLength: 1, reg: gp11sb, asm: "ADDI", aux: "Int64"}, // arg0 + auxint
|
||||||
|
{name: "SUB", argLength: 2, reg: gp21, asm: "SUB"}, // arg0 - arg1
|
||||||
|
|
||||||
|
// M extension. H means high (i.e., it returns the top bits of
|
||||||
|
// the result). U means unsigned. W means word (i.e., 32-bit).
|
||||||
|
{name: "MUL", argLength: 2, reg: gp21, asm: "MUL", commutative: true, typ: "Int64"}, // arg0 * arg1
|
||||||
|
{name: "MULW", argLength: 2, reg: gp21, asm: "MULW", commutative: true, typ: "Int32"},
|
||||||
|
{name: "MULH", argLength: 2, reg: gp21, asm: "MULH", commutative: true, typ: "Int64"},
|
||||||
|
{name: "MULHU", argLength: 2, reg: gp21, asm: "MULHU", commutative: true, typ: "UInt64"},
|
||||||
|
{name: "DIV", argLength: 2, reg: gp21, asm: "DIV", typ: "Int64"}, // arg0 / arg1
|
||||||
|
{name: "DIVU", argLength: 2, reg: gp21, asm: "DIVU", typ: "UInt64"},
|
||||||
|
{name: "DIVW", argLength: 2, reg: gp21, asm: "DIVW", typ: "Int32"},
|
||||||
|
{name: "DIVUW", argLength: 2, reg: gp21, asm: "DIVUW", typ: "UInt32"},
|
||||||
|
{name: "REM", argLength: 2, reg: gp21, asm: "REM", typ: "Int64"}, // arg0 % arg1
|
||||||
|
{name: "REMU", argLength: 2, reg: gp21, asm: "REMU", typ: "UInt64"},
|
||||||
|
{name: "REMW", argLength: 2, reg: gp21, asm: "REMW", typ: "Int32"},
|
||||||
|
{name: "REMUW", argLength: 2, reg: gp21, asm: "REMUW", typ: "UInt32"},
|
||||||
|
|
||||||
|
{name: "MOVaddr", argLength: 1, reg: gp11sb, asm: "MOV", aux: "SymOff", rematerializeable: true, symEffect: "RdWr"}, // arg0 + auxint + offset encoded in aux
|
||||||
|
// auxint+aux == add auxint and the offset of the symbol in aux (if any) to the effective address
|
||||||
|
|
||||||
|
{name: "MOVBconst", reg: gp01, asm: "MOV", typ: "UInt8", aux: "Int8", rematerializeable: true}, // 8 low bits of auxint
|
||||||
|
{name: "MOVHconst", reg: gp01, asm: "MOV", typ: "UInt16", aux: "Int16", rematerializeable: true}, // 16 low bits of auxint
|
||||||
|
{name: "MOVWconst", reg: gp01, asm: "MOV", typ: "UInt32", aux: "Int32", rematerializeable: true}, // 32 low bits of auxint
|
||||||
|
{name: "MOVDconst", reg: gp01, asm: "MOV", typ: "UInt64", aux: "Int64", rematerializeable: true}, // auxint
|
||||||
|
|
||||||
|
// Loads: load <size> bits from arg0+auxint+aux and extend to 64 bits; arg1=mem
|
||||||
|
{name: "MOVBload", argLength: 2, reg: gpload, asm: "MOVB", aux: "SymOff", typ: "Int8", faultOnNilArg0: true, symEffect: "Read"}, // 8 bits, sign extend
|
||||||
|
{name: "MOVHload", argLength: 2, reg: gpload, asm: "MOVH", aux: "SymOff", typ: "Int16", faultOnNilArg0: true, symEffect: "Read"}, // 16 bits, sign extend
|
||||||
|
{name: "MOVWload", argLength: 2, reg: gpload, asm: "MOVW", aux: "SymOff", typ: "Int32", faultOnNilArg0: true, symEffect: "Read"}, // 32 bits, sign extend
|
||||||
|
{name: "MOVDload", argLength: 2, reg: gpload, asm: "MOV", aux: "SymOff", typ: "Int64", faultOnNilArg0: true, symEffect: "Read"}, // 64 bits
|
||||||
|
{name: "MOVBUload", argLength: 2, reg: gpload, asm: "MOVBU", aux: "SymOff", typ: "UInt8", faultOnNilArg0: true, symEffect: "Read"}, // 8 bits, zero extend
|
||||||
|
{name: "MOVHUload", argLength: 2, reg: gpload, asm: "MOVHU", aux: "SymOff", typ: "UInt16", faultOnNilArg0: true, symEffect: "Read"}, // 16 bits, zero extend
|
||||||
|
{name: "MOVWUload", argLength: 2, reg: gpload, asm: "MOVWU", aux: "SymOff", typ: "UInt32", faultOnNilArg0: true, symEffect: "Read"}, // 32 bits, zero extend
|
||||||
|
|
||||||
|
// Stores: store <size> lowest bits in arg1 to arg0+auxint+aux; arg2=mem
|
||||||
|
{name: "MOVBstore", argLength: 3, reg: gpstore, asm: "MOVB", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 8 bits
|
||||||
|
{name: "MOVHstore", argLength: 3, reg: gpstore, asm: "MOVH", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 16 bits
|
||||||
|
{name: "MOVWstore", argLength: 3, reg: gpstore, asm: "MOVW", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 32 bits
|
||||||
|
{name: "MOVDstore", argLength: 3, reg: gpstore, asm: "MOV", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 64 bits
|
||||||
|
|
||||||
|
// Shift ops
|
||||||
|
{name: "SLL", argLength: 2, reg: gp21, asm: "SLL"}, // arg0 << aux1
|
||||||
|
{name: "SRA", argLength: 2, reg: gp21, asm: "SRA"}, // arg0 >> aux1, signed
|
||||||
|
{name: "SRL", argLength: 2, reg: gp21, asm: "SRL"}, // arg0 >> aux1, unsigned
|
||||||
|
{name: "SLLI", argLength: 1, reg: gp11, asm: "SLLI", aux: "Int64"}, // arg0 << auxint
|
||||||
|
{name: "SRAI", argLength: 1, reg: gp11, asm: "SRAI", aux: "Int64"}, // arg0 >> auxint, signed
|
||||||
|
{name: "SRLI", argLength: 1, reg: gp11, asm: "SRLI", aux: "Int64"}, // arg0 >> auxint, unsigned
|
||||||
|
|
||||||
|
// Bitwise ops
|
||||||
|
{name: "XOR", argLength: 2, reg: gp21, asm: "XOR", commutative: true}, // arg0 ^ arg1
|
||||||
|
{name: "XORI", argLength: 1, reg: gp11, asm: "XORI", aux: "Int64"}, // arg0 ^ auxint
|
||||||
|
{name: "OR", argLength: 2, reg: gp21, asm: "OR", commutative: true}, // arg0 | arg1
|
||||||
|
{name: "ORI", argLength: 1, reg: gp11, asm: "ORI", aux: "Int64"}, // arg0 | auxint
|
||||||
|
{name: "AND", argLength: 2, reg: gp21, asm: "AND", commutative: true}, // arg0 & arg1
|
||||||
|
{name: "ANDI", argLength: 1, reg: gp11, asm: "ANDI", aux: "Int64"}, // arg0 & auxint
|
||||||
|
|
||||||
|
// Generate boolean values
|
||||||
|
{name: "SEQZ", argLength: 1, reg: gp11, asm: "SEQZ"}, // arg0 == 0, result is 0 or 1
|
||||||
|
{name: "SNEZ", argLength: 1, reg: gp11, asm: "SNEZ"}, // arg0 != 0, result is 0 or 1
|
||||||
|
{name: "SLT", argLength: 2, reg: gp21, asm: "SLT"}, // arg0 < arg1, result is 0 or 1
|
||||||
|
{name: "SLTI", argLength: 1, reg: gp11, asm: "SLTI", aux: "Int64"}, // arg0 < auxint, result is 0 or 1
|
||||||
|
{name: "SLTU", argLength: 2, reg: gp21, asm: "SLTU"}, // arg0 < arg1, unsigned, result is 0 or 1
|
||||||
|
{name: "SLTIU", argLength: 1, reg: gp11, asm: "SLTIU", aux: "Int64"}, // arg0 < auxint, unsigned, result is 0 or 1
|
||||||
|
|
||||||
|
// MOVconvert converts between pointers and integers.
|
||||||
|
// We have a special op for this so as to not confuse GC
|
||||||
|
// (particularly stack maps). It takes a memory arg so it
|
||||||
|
// gets correctly ordered with respect to GC safepoints.
|
||||||
|
{name: "MOVconvert", argLength: 2, reg: gp11, asm: "MOV"}, // arg0, but converted to int/ptr as appropriate; arg1=mem
|
||||||
|
|
||||||
|
// Calls
|
||||||
|
{name: "CALLstatic", argLength: 1, reg: call, aux: "SymOff", call: true, symEffect: "None"}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem
|
||||||
|
{name: "CALLclosure", argLength: 3, reg: callClosure, aux: "Int64", call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
|
||||||
|
{name: "CALLinter", argLength: 2, reg: callInter, aux: "Int64", call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
|
||||||
|
|
||||||
|
// Generic moves and zeros
|
||||||
|
|
||||||
|
// general unaligned zeroing
|
||||||
|
// arg0 = address of memory to zero (in X5, changed as side effect)
|
||||||
|
// arg1 = address of the last element to zero (inclusive)
|
||||||
|
// arg2 = mem
|
||||||
|
// auxint = element size
|
||||||
|
// returns mem
|
||||||
|
// mov ZERO, (X5)
|
||||||
|
// ADD $sz, X5
|
||||||
|
// BGEU Rarg1, X5, -2(PC)
|
||||||
|
{
|
||||||
|
name: "LoweredZero",
|
||||||
|
aux: "Int64",
|
||||||
|
argLength: 3,
|
||||||
|
reg: regInfo{
|
||||||
|
inputs: []regMask{regNamed["X5"], gpMask},
|
||||||
|
clobbers: regNamed["X5"],
|
||||||
|
},
|
||||||
|
typ: "Mem",
|
||||||
|
faultOnNilArg0: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
// general unaligned move
|
||||||
|
// arg0 = address of dst memory (in X5, changed as side effect)
|
||||||
|
// arg1 = address of src memory (in X6, changed as side effect)
|
||||||
|
// arg2 = address of the last element of src (can't be X7 as we clobber it before using arg2)
|
||||||
|
// arg3 = mem
|
||||||
|
// auxint = alignment
|
||||||
|
// clobbers X7 as a tmp register.
|
||||||
|
// returns mem
|
||||||
|
// mov (X6), X7
|
||||||
|
// mov X7, (X5)
|
||||||
|
// ADD $sz, X5
|
||||||
|
// ADD $sz, X6
|
||||||
|
// BGEU Rarg2, X5, -4(PC)
|
||||||
|
{
|
||||||
|
name: "LoweredMove",
|
||||||
|
aux: "Int64",
|
||||||
|
argLength: 4,
|
||||||
|
reg: regInfo{
|
||||||
|
inputs: []regMask{regNamed["X5"], regNamed["X6"], gpMask &^ regNamed["X7"]},
|
||||||
|
clobbers: regNamed["X5"] | regNamed["X6"] | regNamed["X7"],
|
||||||
|
},
|
||||||
|
typ: "Mem",
|
||||||
|
faultOnNilArg0: true,
|
||||||
|
faultOnNilArg1: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
// Lowering pass-throughs
|
||||||
|
{name: "LoweredNilCheck", argLength: 2, faultOnNilArg0: true, nilCheck: true, reg: regInfo{inputs: []regMask{gpspMask}}}, // arg0=ptr,arg1=mem, returns void. Faults if ptr is nil.
|
||||||
|
{name: "LoweredGetClosurePtr", reg: regInfo{outputs: []regMask{regCtxt}}}, // scheduler ensures only at beginning of entry block
|
||||||
|
|
||||||
|
// LoweredGetCallerSP returns the SP of the caller of the current function.
|
||||||
|
{name: "LoweredGetCallerSP", reg: gp01, rematerializeable: true},
|
||||||
|
|
||||||
|
// LoweredGetCallerPC evaluates to the PC to which its "caller" will return.
|
||||||
|
// I.e., if f calls g "calls" getcallerpc,
|
||||||
|
// the result should be the PC within f that g will return to.
|
||||||
|
// See runtime/stubs.go for a more detailed discussion.
|
||||||
|
{name: "LoweredGetCallerPC", reg: gp01, rematerializeable: true},
|
||||||
|
|
||||||
|
// LoweredWB invokes runtime.gcWriteBarrier. arg0=destptr, arg1=srcptr, arg2=mem, aux=runtime.gcWriteBarrier
|
||||||
|
// It saves all GP registers if necessary,
|
||||||
|
// but clobbers RA (LR) because it's a call
|
||||||
|
// and T6 (REG_TMP).
|
||||||
|
{name: "LoweredWB", argLength: 3, reg: regInfo{inputs: []regMask{regNamed["X5"], regNamed["X6"]}, clobbers: (callerSave &^ (gpMask | regNamed["g"])) | regNamed["X1"]}, clobberFlags: true, aux: "Sym", symEffect: "None"},
|
||||||
|
|
||||||
|
// There are three of these functions so that they can have three different register inputs.
|
||||||
|
// When we check 0 <= c <= cap (A), then 0 <= b <= c (B), then 0 <= a <= b (C), we want the
|
||||||
|
// default registers to match so we don't need to copy registers around unnecessarily.
|
||||||
|
{name: "LoweredPanicBoundsA", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{regNamed["X7"], regNamed["X28"]}}, typ: "Mem"}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go).
|
||||||
|
{name: "LoweredPanicBoundsB", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{regNamed["X6"], regNamed["X7"]}}, typ: "Mem"}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go).
|
||||||
|
{name: "LoweredPanicBoundsC", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{regNamed["X5"], regNamed["X6"]}}, typ: "Mem"}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go).
|
||||||
|
|
||||||
|
// F extension.
|
||||||
|
{name: "FADDS", argLength: 2, reg: fp21, asm: "FADDS", commutative: true, typ: "Float32"}, // arg0 + arg1
|
||||||
|
{name: "FSUBS", argLength: 2, reg: fp21, asm: "FSUBS", commutative: false, typ: "Float32"}, // arg0 - arg1
|
||||||
|
{name: "FMULS", argLength: 2, reg: fp21, asm: "FMULS", commutative: true, typ: "Float32"}, // arg0 * arg1
|
||||||
|
{name: "FDIVS", argLength: 2, reg: fp21, asm: "FDIVS", commutative: false, typ: "Float32"}, // arg0 / arg1
|
||||||
|
{name: "FSQRTS", argLength: 1, reg: fp11, asm: "FSQRTS", typ: "Float32"}, // sqrt(arg0)
|
||||||
|
{name: "FNEGS", argLength: 1, reg: fp11, asm: "FNEGS", typ: "Float32"}, // -arg0
|
||||||
|
{name: "FMVSX", argLength: 1, reg: gpfp, asm: "FMVSX", typ: "Float32"}, // reinterpret arg0 as float
|
||||||
|
{name: "FCVTSW", argLength: 1, reg: gpfp, asm: "FCVTSW", typ: "Float32"}, // float32(low 32 bits of arg0)
|
||||||
|
{name: "FCVTSL", argLength: 1, reg: gpfp, asm: "FCVTSL", typ: "Float32"}, // float32(arg0)
|
||||||
|
{name: "FCVTWS", argLength: 1, reg: fpgp, asm: "FCVTWS", typ: "Int32"}, // int32(arg0)
|
||||||
|
{name: "FCVTLS", argLength: 1, reg: fpgp, asm: "FCVTLS", typ: "Int64"}, // int64(arg0)
|
||||||
|
{name: "FMOVWload", argLength: 2, reg: fpload, asm: "MOVF", aux: "SymOff", typ: "Float32", faultOnNilArg0: true, symEffect: "Read"}, // load float32 from arg0+auxint+aux
|
||||||
|
{name: "FMOVWstore", argLength: 3, reg: fpstore, asm: "MOVF", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store float32 to arg0+auxint+aux
|
||||||
|
{name: "FEQS", argLength: 2, reg: fp2gp, asm: "FEQS", commutative: true}, // arg0 == arg1
|
||||||
|
{name: "FNES", argLength: 2, reg: fp2gp, asm: "FNES", commutative: true}, // arg0 != arg1
|
||||||
|
{name: "FLTS", argLength: 2, reg: fp2gp, asm: "FLTS"}, // arg0 < arg1
|
||||||
|
{name: "FLES", argLength: 2, reg: fp2gp, asm: "FLES"}, // arg0 <= arg1
|
||||||
|
|
||||||
|
// D extension.
|
||||||
|
{name: "FADDD", argLength: 2, reg: fp21, asm: "FADDD", commutative: true, typ: "Float64"}, // arg0 + arg1
|
||||||
|
{name: "FSUBD", argLength: 2, reg: fp21, asm: "FSUBD", commutative: false, typ: "Float64"}, // arg0 - arg1
|
||||||
|
{name: "FMULD", argLength: 2, reg: fp21, asm: "FMULD", commutative: true, typ: "Float64"}, // arg0 * arg1
|
||||||
|
{name: "FDIVD", argLength: 2, reg: fp21, asm: "FDIVD", commutative: false, typ: "Float64"}, // arg0 / arg1
|
||||||
|
{name: "FSQRTD", argLength: 1, reg: fp11, asm: "FSQRTD", typ: "Float64"}, // sqrt(arg0)
|
||||||
|
{name: "FNEGD", argLength: 1, reg: fp11, asm: "FNEGD", typ: "Float64"}, // -arg0
|
||||||
|
{name: "FMVDX", argLength: 1, reg: gpfp, asm: "FMVDX", typ: "Float64"}, // reinterpret arg0 as float
|
||||||
|
{name: "FCVTDW", argLength: 1, reg: gpfp, asm: "FCVTDW", typ: "Float64"}, // float64(low 32 bits of arg0)
|
||||||
|
{name: "FCVTDL", argLength: 1, reg: gpfp, asm: "FCVTDL", typ: "Float64"}, // float64(arg0)
|
||||||
|
{name: "FCVTWD", argLength: 1, reg: fpgp, asm: "FCVTWD", typ: "Int32"}, // int32(arg0)
|
||||||
|
{name: "FCVTLD", argLength: 1, reg: fpgp, asm: "FCVTLD", typ: "Int64"}, // int64(arg0)
|
||||||
|
{name: "FCVTDS", argLength: 1, reg: fp11, asm: "FCVTDS", typ: "Float64"}, // float64(arg0)
|
||||||
|
{name: "FCVTSD", argLength: 1, reg: fp11, asm: "FCVTSD", typ: "Float32"}, // float32(arg0)
|
||||||
|
{name: "FMOVDload", argLength: 2, reg: fpload, asm: "MOVD", aux: "SymOff", typ: "Float64", faultOnNilArg0: true, symEffect: "Read"}, // load float64 from arg0+auxint+aux
|
||||||
|
{name: "FMOVDstore", argLength: 3, reg: fpstore, asm: "MOVD", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store float6 to arg0+auxint+aux
|
||||||
|
{name: "FEQD", argLength: 2, reg: fp2gp, asm: "FEQD", commutative: true}, // arg0 == arg1
|
||||||
|
{name: "FNED", argLength: 2, reg: fp2gp, asm: "FNED", commutative: true}, // arg0 != arg1
|
||||||
|
{name: "FLTD", argLength: 2, reg: fp2gp, asm: "FLTD"}, // arg0 < arg1
|
||||||
|
{name: "FLED", argLength: 2, reg: fp2gp, asm: "FLED"}, // arg0 <= arg1
|
||||||
|
}
|
||||||
|
|
||||||
|
RISCV64blocks := []blockData{
|
||||||
|
{name: "BNE", controls: 1}, // Control != 0 (take a register)
|
||||||
|
}
|
||||||
|
|
||||||
|
archs = append(archs, arch{
|
||||||
|
name: "RISCV64",
|
||||||
|
pkg: "cmd/internal/obj/riscv",
|
||||||
|
genfile: "../../riscv64/ssa.go",
|
||||||
|
ops: RISCV64ops,
|
||||||
|
blocks: RISCV64blocks,
|
||||||
|
regnames: regNamesRISCV64,
|
||||||
|
gpregmask: gpMask,
|
||||||
|
fpregmask: fpMask,
|
||||||
|
framepointerreg: -1, // not used
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -340,7 +340,7 @@ var genericOps = []opData{
|
||||||
// Note: ConstX are sign-extended even when the type of the value is unsigned.
|
// Note: ConstX are sign-extended even when the type of the value is unsigned.
|
||||||
// For instance, uint8(0xaa) is stored as auxint=0xffffffffffffffaa.
|
// For instance, uint8(0xaa) is stored as auxint=0xffffffffffffffaa.
|
||||||
{name: "Const64", aux: "Int64"}, // value is auxint
|
{name: "Const64", aux: "Int64"}, // value is auxint
|
||||||
{name: "Const32F", aux: "Float32"}, // value is math.Float64frombits(uint64(auxint)) and is exactly prepresentable as float 32
|
{name: "Const32F", aux: "Float32"}, // value is math.Float64frombits(uint64(auxint)) and is exactly representable as float 32
|
||||||
{name: "Const64F", aux: "Float64"}, // value is math.Float64frombits(uint64(auxint))
|
{name: "Const64F", aux: "Float64"}, // value is math.Float64frombits(uint64(auxint))
|
||||||
{name: "ConstInterface"}, // nil interface
|
{name: "ConstInterface"}, // nil interface
|
||||||
{name: "ConstSlice"}, // nil slice
|
{name: "ConstSlice"}, // nil slice
|
||||||
|
|
|
||||||
|
|
@ -405,6 +405,7 @@ func genOp() {
|
||||||
|
|
||||||
fmt.Fprintln(w, "func (o Op) SymEffect() SymEffect { return opcodeTable[o].symEffect }")
|
fmt.Fprintln(w, "func (o Op) SymEffect() SymEffect { return opcodeTable[o].symEffect }")
|
||||||
fmt.Fprintln(w, "func (o Op) IsCall() bool { return opcodeTable[o].call }")
|
fmt.Fprintln(w, "func (o Op) IsCall() bool { return opcodeTable[o].call }")
|
||||||
|
fmt.Fprintln(w, "func (o Op) HasSideEffects() bool { return opcodeTable[o].hasSideEffects }")
|
||||||
fmt.Fprintln(w, "func (o Op) UnsafePoint() bool { return opcodeTable[o].unsafePoint }")
|
fmt.Fprintln(w, "func (o Op) UnsafePoint() bool { return opcodeTable[o].unsafePoint }")
|
||||||
|
|
||||||
// generate registers
|
// generate registers
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -9480,7 +9480,7 @@ func rewriteValuePPC64_OpPPC64MOVDload_0(v *Value) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (MOVDload [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) mem)
|
// match: (MOVDload [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) mem)
|
||||||
// cond: canMergeSym(sym1,sym2) && (ptr.Op != OpSB || p.Uses == 1)
|
// cond: canMergeSym(sym1,sym2) && (ptr.Op != OpSB || p.Uses == 1) && (off1+off2)%4 == 0
|
||||||
// result: (MOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
// result: (MOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||||
for {
|
for {
|
||||||
off1 := v.AuxInt
|
off1 := v.AuxInt
|
||||||
|
|
@ -9493,7 +9493,7 @@ func rewriteValuePPC64_OpPPC64MOVDload_0(v *Value) bool {
|
||||||
off2 := p.AuxInt
|
off2 := p.AuxInt
|
||||||
sym2 := p.Aux
|
sym2 := p.Aux
|
||||||
ptr := p.Args[0]
|
ptr := p.Args[0]
|
||||||
if !(canMergeSym(sym1, sym2) && (ptr.Op != OpSB || p.Uses == 1)) {
|
if !(canMergeSym(sym1, sym2) && (ptr.Op != OpSB || p.Uses == 1) && (off1+off2)%4 == 0) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpPPC64MOVDload)
|
v.reset(OpPPC64MOVDload)
|
||||||
|
|
@ -9504,7 +9504,7 @@ func rewriteValuePPC64_OpPPC64MOVDload_0(v *Value) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (MOVDload [off1] {sym} (ADDconst [off2] x) mem)
|
// match: (MOVDload [off1] {sym} (ADDconst [off2] x) mem)
|
||||||
// cond: is16Bit(off1+off2)
|
// cond: is16Bit(off1+off2) && (off1+off2)%4 == 0
|
||||||
// result: (MOVDload [off1+off2] {sym} x mem)
|
// result: (MOVDload [off1+off2] {sym} x mem)
|
||||||
for {
|
for {
|
||||||
off1 := v.AuxInt
|
off1 := v.AuxInt
|
||||||
|
|
@ -9516,7 +9516,7 @@ func rewriteValuePPC64_OpPPC64MOVDload_0(v *Value) bool {
|
||||||
}
|
}
|
||||||
off2 := v_0.AuxInt
|
off2 := v_0.AuxInt
|
||||||
x := v_0.Args[0]
|
x := v_0.Args[0]
|
||||||
if !(is16Bit(off1 + off2)) {
|
if !(is16Bit(off1+off2) && (off1+off2)%4 == 0) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpPPC64MOVDload)
|
v.reset(OpPPC64MOVDload)
|
||||||
|
|
@ -9554,7 +9554,7 @@ func rewriteValuePPC64_OpPPC64MOVDload_0(v *Value) bool {
|
||||||
}
|
}
|
||||||
func rewriteValuePPC64_OpPPC64MOVDloadidx_0(v *Value) bool {
|
func rewriteValuePPC64_OpPPC64MOVDloadidx_0(v *Value) bool {
|
||||||
// match: (MOVDloadidx ptr (MOVDconst [c]) mem)
|
// match: (MOVDloadidx ptr (MOVDconst [c]) mem)
|
||||||
// cond: is16Bit(c)
|
// cond: is16Bit(c) && c%4 == 0
|
||||||
// result: (MOVDload [c] ptr mem)
|
// result: (MOVDload [c] ptr mem)
|
||||||
for {
|
for {
|
||||||
mem := v.Args[2]
|
mem := v.Args[2]
|
||||||
|
|
@ -9564,7 +9564,7 @@ func rewriteValuePPC64_OpPPC64MOVDloadidx_0(v *Value) bool {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
c := v_1.AuxInt
|
c := v_1.AuxInt
|
||||||
if !(is16Bit(c)) {
|
if !(is16Bit(c) && c%4 == 0) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpPPC64MOVDload)
|
v.reset(OpPPC64MOVDload)
|
||||||
|
|
@ -9574,7 +9574,7 @@ func rewriteValuePPC64_OpPPC64MOVDloadidx_0(v *Value) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (MOVDloadidx (MOVDconst [c]) ptr mem)
|
// match: (MOVDloadidx (MOVDconst [c]) ptr mem)
|
||||||
// cond: is16Bit(c)
|
// cond: is16Bit(c) && c%4 == 0
|
||||||
// result: (MOVDload [c] ptr mem)
|
// result: (MOVDload [c] ptr mem)
|
||||||
for {
|
for {
|
||||||
mem := v.Args[2]
|
mem := v.Args[2]
|
||||||
|
|
@ -9584,7 +9584,7 @@ func rewriteValuePPC64_OpPPC64MOVDloadidx_0(v *Value) bool {
|
||||||
}
|
}
|
||||||
c := v_0.AuxInt
|
c := v_0.AuxInt
|
||||||
ptr := v.Args[1]
|
ptr := v.Args[1]
|
||||||
if !(is16Bit(c)) {
|
if !(is16Bit(c) && c%4 == 0) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpPPC64MOVDload)
|
v.reset(OpPPC64MOVDload)
|
||||||
|
|
@ -9617,7 +9617,7 @@ func rewriteValuePPC64_OpPPC64MOVDstore_0(v *Value) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (MOVDstore [off1] {sym} (ADDconst [off2] x) val mem)
|
// match: (MOVDstore [off1] {sym} (ADDconst [off2] x) val mem)
|
||||||
// cond: is16Bit(off1+off2)
|
// cond: is16Bit(off1+off2) && (off1+off2)%4 == 0
|
||||||
// result: (MOVDstore [off1+off2] {sym} x val mem)
|
// result: (MOVDstore [off1+off2] {sym} x val mem)
|
||||||
for {
|
for {
|
||||||
off1 := v.AuxInt
|
off1 := v.AuxInt
|
||||||
|
|
@ -9630,7 +9630,7 @@ func rewriteValuePPC64_OpPPC64MOVDstore_0(v *Value) bool {
|
||||||
off2 := v_0.AuxInt
|
off2 := v_0.AuxInt
|
||||||
x := v_0.Args[0]
|
x := v_0.Args[0]
|
||||||
val := v.Args[1]
|
val := v.Args[1]
|
||||||
if !(is16Bit(off1 + off2)) {
|
if !(is16Bit(off1+off2) && (off1+off2)%4 == 0) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpPPC64MOVDstore)
|
v.reset(OpPPC64MOVDstore)
|
||||||
|
|
@ -9642,7 +9642,7 @@ func rewriteValuePPC64_OpPPC64MOVDstore_0(v *Value) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (MOVDstore [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) val mem)
|
// match: (MOVDstore [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) val mem)
|
||||||
// cond: canMergeSym(sym1,sym2) && (ptr.Op != OpSB || p.Uses == 1)
|
// cond: canMergeSym(sym1,sym2) && (ptr.Op != OpSB || p.Uses == 1) && (off1+off2)%4 == 0
|
||||||
// result: (MOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
|
// result: (MOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
|
||||||
for {
|
for {
|
||||||
off1 := v.AuxInt
|
off1 := v.AuxInt
|
||||||
|
|
@ -9656,7 +9656,7 @@ func rewriteValuePPC64_OpPPC64MOVDstore_0(v *Value) bool {
|
||||||
sym2 := p.Aux
|
sym2 := p.Aux
|
||||||
ptr := p.Args[0]
|
ptr := p.Args[0]
|
||||||
val := v.Args[1]
|
val := v.Args[1]
|
||||||
if !(canMergeSym(sym1, sym2) && (ptr.Op != OpSB || p.Uses == 1)) {
|
if !(canMergeSym(sym1, sym2) && (ptr.Op != OpSB || p.Uses == 1) && (off1+off2)%4 == 0) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpPPC64MOVDstore)
|
v.reset(OpPPC64MOVDstore)
|
||||||
|
|
@ -9713,7 +9713,7 @@ func rewriteValuePPC64_OpPPC64MOVDstore_0(v *Value) bool {
|
||||||
}
|
}
|
||||||
func rewriteValuePPC64_OpPPC64MOVDstoreidx_0(v *Value) bool {
|
func rewriteValuePPC64_OpPPC64MOVDstoreidx_0(v *Value) bool {
|
||||||
// match: (MOVDstoreidx ptr (MOVDconst [c]) val mem)
|
// match: (MOVDstoreidx ptr (MOVDconst [c]) val mem)
|
||||||
// cond: is16Bit(c)
|
// cond: is16Bit(c) && c%4 == 0
|
||||||
// result: (MOVDstore [c] ptr val mem)
|
// result: (MOVDstore [c] ptr val mem)
|
||||||
for {
|
for {
|
||||||
mem := v.Args[3]
|
mem := v.Args[3]
|
||||||
|
|
@ -9724,7 +9724,7 @@ func rewriteValuePPC64_OpPPC64MOVDstoreidx_0(v *Value) bool {
|
||||||
}
|
}
|
||||||
c := v_1.AuxInt
|
c := v_1.AuxInt
|
||||||
val := v.Args[2]
|
val := v.Args[2]
|
||||||
if !(is16Bit(c)) {
|
if !(is16Bit(c) && c%4 == 0) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpPPC64MOVDstore)
|
v.reset(OpPPC64MOVDstore)
|
||||||
|
|
@ -9735,7 +9735,7 @@ func rewriteValuePPC64_OpPPC64MOVDstoreidx_0(v *Value) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (MOVDstoreidx (MOVDconst [c]) ptr val mem)
|
// match: (MOVDstoreidx (MOVDconst [c]) ptr val mem)
|
||||||
// cond: is16Bit(c)
|
// cond: is16Bit(c) && c%4 == 0
|
||||||
// result: (MOVDstore [c] ptr val mem)
|
// result: (MOVDstore [c] ptr val mem)
|
||||||
for {
|
for {
|
||||||
mem := v.Args[3]
|
mem := v.Args[3]
|
||||||
|
|
@ -9746,7 +9746,7 @@ func rewriteValuePPC64_OpPPC64MOVDstoreidx_0(v *Value) bool {
|
||||||
c := v_0.AuxInt
|
c := v_0.AuxInt
|
||||||
ptr := v.Args[1]
|
ptr := v.Args[1]
|
||||||
val := v.Args[2]
|
val := v.Args[2]
|
||||||
if !(is16Bit(c)) {
|
if !(is16Bit(c) && c%4 == 0) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpPPC64MOVDstore)
|
v.reset(OpPPC64MOVDstore)
|
||||||
|
|
@ -9760,7 +9760,7 @@ func rewriteValuePPC64_OpPPC64MOVDstoreidx_0(v *Value) bool {
|
||||||
}
|
}
|
||||||
func rewriteValuePPC64_OpPPC64MOVDstorezero_0(v *Value) bool {
|
func rewriteValuePPC64_OpPPC64MOVDstorezero_0(v *Value) bool {
|
||||||
// match: (MOVDstorezero [off1] {sym} (ADDconst [off2] x) mem)
|
// match: (MOVDstorezero [off1] {sym} (ADDconst [off2] x) mem)
|
||||||
// cond: is16Bit(off1+off2)
|
// cond: is16Bit(off1+off2) && (off1+off2)%4 == 0
|
||||||
// result: (MOVDstorezero [off1+off2] {sym} x mem)
|
// result: (MOVDstorezero [off1+off2] {sym} x mem)
|
||||||
for {
|
for {
|
||||||
off1 := v.AuxInt
|
off1 := v.AuxInt
|
||||||
|
|
@ -9772,7 +9772,7 @@ func rewriteValuePPC64_OpPPC64MOVDstorezero_0(v *Value) bool {
|
||||||
}
|
}
|
||||||
off2 := v_0.AuxInt
|
off2 := v_0.AuxInt
|
||||||
x := v_0.Args[0]
|
x := v_0.Args[0]
|
||||||
if !(is16Bit(off1 + off2)) {
|
if !(is16Bit(off1+off2) && (off1+off2)%4 == 0) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpPPC64MOVDstorezero)
|
v.reset(OpPPC64MOVDstorezero)
|
||||||
|
|
@ -9783,7 +9783,7 @@ func rewriteValuePPC64_OpPPC64MOVDstorezero_0(v *Value) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (MOVDstorezero [off1] {sym1} p:(MOVDaddr [off2] {sym2} x) mem)
|
// match: (MOVDstorezero [off1] {sym1} p:(MOVDaddr [off2] {sym2} x) mem)
|
||||||
// cond: canMergeSym(sym1,sym2) && (x.Op != OpSB || p.Uses == 1)
|
// cond: canMergeSym(sym1,sym2) && (x.Op != OpSB || p.Uses == 1) && (off1+off2)%4 == 0
|
||||||
// result: (MOVDstorezero [off1+off2] {mergeSym(sym1,sym2)} x mem)
|
// result: (MOVDstorezero [off1+off2] {mergeSym(sym1,sym2)} x mem)
|
||||||
for {
|
for {
|
||||||
off1 := v.AuxInt
|
off1 := v.AuxInt
|
||||||
|
|
@ -9796,7 +9796,7 @@ func rewriteValuePPC64_OpPPC64MOVDstorezero_0(v *Value) bool {
|
||||||
off2 := p.AuxInt
|
off2 := p.AuxInt
|
||||||
sym2 := p.Aux
|
sym2 := p.Aux
|
||||||
x := p.Args[0]
|
x := p.Args[0]
|
||||||
if !(canMergeSym(sym1, sym2) && (x.Op != OpSB || p.Uses == 1)) {
|
if !(canMergeSym(sym1, sym2) && (x.Op != OpSB || p.Uses == 1) && (off1+off2)%4 == 0) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpPPC64MOVDstorezero)
|
v.reset(OpPPC64MOVDstorezero)
|
||||||
|
|
@ -11548,7 +11548,7 @@ func rewriteValuePPC64_OpPPC64MOVWZreg_20(v *Value) bool {
|
||||||
}
|
}
|
||||||
func rewriteValuePPC64_OpPPC64MOVWload_0(v *Value) bool {
|
func rewriteValuePPC64_OpPPC64MOVWload_0(v *Value) bool {
|
||||||
// match: (MOVWload [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) mem)
|
// match: (MOVWload [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) mem)
|
||||||
// cond: canMergeSym(sym1,sym2) && (ptr.Op != OpSB || p.Uses == 1)
|
// cond: canMergeSym(sym1,sym2) && (ptr.Op != OpSB || p.Uses == 1) && (off1+off2)%4 == 0
|
||||||
// result: (MOVWload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
// result: (MOVWload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||||
for {
|
for {
|
||||||
off1 := v.AuxInt
|
off1 := v.AuxInt
|
||||||
|
|
@ -11561,7 +11561,7 @@ func rewriteValuePPC64_OpPPC64MOVWload_0(v *Value) bool {
|
||||||
off2 := p.AuxInt
|
off2 := p.AuxInt
|
||||||
sym2 := p.Aux
|
sym2 := p.Aux
|
||||||
ptr := p.Args[0]
|
ptr := p.Args[0]
|
||||||
if !(canMergeSym(sym1, sym2) && (ptr.Op != OpSB || p.Uses == 1)) {
|
if !(canMergeSym(sym1, sym2) && (ptr.Op != OpSB || p.Uses == 1) && (off1+off2)%4 == 0) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpPPC64MOVWload)
|
v.reset(OpPPC64MOVWload)
|
||||||
|
|
@ -11572,7 +11572,7 @@ func rewriteValuePPC64_OpPPC64MOVWload_0(v *Value) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (MOVWload [off1] {sym} (ADDconst [off2] x) mem)
|
// match: (MOVWload [off1] {sym} (ADDconst [off2] x) mem)
|
||||||
// cond: is16Bit(off1+off2)
|
// cond: is16Bit(off1+off2) && (off1+off2)%4 == 0
|
||||||
// result: (MOVWload [off1+off2] {sym} x mem)
|
// result: (MOVWload [off1+off2] {sym} x mem)
|
||||||
for {
|
for {
|
||||||
off1 := v.AuxInt
|
off1 := v.AuxInt
|
||||||
|
|
@ -11584,7 +11584,7 @@ func rewriteValuePPC64_OpPPC64MOVWload_0(v *Value) bool {
|
||||||
}
|
}
|
||||||
off2 := v_0.AuxInt
|
off2 := v_0.AuxInt
|
||||||
x := v_0.Args[0]
|
x := v_0.Args[0]
|
||||||
if !(is16Bit(off1 + off2)) {
|
if !(is16Bit(off1+off2) && (off1+off2)%4 == 0) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpPPC64MOVWload)
|
v.reset(OpPPC64MOVWload)
|
||||||
|
|
@ -11622,7 +11622,7 @@ func rewriteValuePPC64_OpPPC64MOVWload_0(v *Value) bool {
|
||||||
}
|
}
|
||||||
func rewriteValuePPC64_OpPPC64MOVWloadidx_0(v *Value) bool {
|
func rewriteValuePPC64_OpPPC64MOVWloadidx_0(v *Value) bool {
|
||||||
// match: (MOVWloadidx ptr (MOVDconst [c]) mem)
|
// match: (MOVWloadidx ptr (MOVDconst [c]) mem)
|
||||||
// cond: is16Bit(c)
|
// cond: is16Bit(c) && c%4 == 0
|
||||||
// result: (MOVWload [c] ptr mem)
|
// result: (MOVWload [c] ptr mem)
|
||||||
for {
|
for {
|
||||||
mem := v.Args[2]
|
mem := v.Args[2]
|
||||||
|
|
@ -11632,7 +11632,7 @@ func rewriteValuePPC64_OpPPC64MOVWloadidx_0(v *Value) bool {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
c := v_1.AuxInt
|
c := v_1.AuxInt
|
||||||
if !(is16Bit(c)) {
|
if !(is16Bit(c) && c%4 == 0) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpPPC64MOVWload)
|
v.reset(OpPPC64MOVWload)
|
||||||
|
|
@ -11642,7 +11642,7 @@ func rewriteValuePPC64_OpPPC64MOVWloadidx_0(v *Value) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (MOVWloadidx (MOVDconst [c]) ptr mem)
|
// match: (MOVWloadidx (MOVDconst [c]) ptr mem)
|
||||||
// cond: is16Bit(c)
|
// cond: is16Bit(c) && c%4 == 0
|
||||||
// result: (MOVWload [c] ptr mem)
|
// result: (MOVWload [c] ptr mem)
|
||||||
for {
|
for {
|
||||||
mem := v.Args[2]
|
mem := v.Args[2]
|
||||||
|
|
@ -11652,7 +11652,7 @@ func rewriteValuePPC64_OpPPC64MOVWloadidx_0(v *Value) bool {
|
||||||
}
|
}
|
||||||
c := v_0.AuxInt
|
c := v_0.AuxInt
|
||||||
ptr := v.Args[1]
|
ptr := v.Args[1]
|
||||||
if !(is16Bit(c)) {
|
if !(is16Bit(c) && c%4 == 0) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpPPC64MOVWload)
|
v.reset(OpPPC64MOVWload)
|
||||||
|
|
|
||||||
5561
src/cmd/compile/internal/ssa/rewriteRISCV64.go
Normal file
5561
src/cmd/compile/internal/ssa/rewriteRISCV64.go
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -66,7 +66,7 @@ func (op Op) isLoweredGetClosurePtr() bool {
|
||||||
switch op {
|
switch op {
|
||||||
case OpAMD64LoweredGetClosurePtr, OpPPC64LoweredGetClosurePtr, OpARMLoweredGetClosurePtr, OpARM64LoweredGetClosurePtr,
|
case OpAMD64LoweredGetClosurePtr, OpPPC64LoweredGetClosurePtr, OpARMLoweredGetClosurePtr, OpARM64LoweredGetClosurePtr,
|
||||||
Op386LoweredGetClosurePtr, OpMIPS64LoweredGetClosurePtr, OpS390XLoweredGetClosurePtr, OpMIPSLoweredGetClosurePtr,
|
Op386LoweredGetClosurePtr, OpMIPS64LoweredGetClosurePtr, OpS390XLoweredGetClosurePtr, OpMIPSLoweredGetClosurePtr,
|
||||||
OpWasmLoweredGetClosurePtr:
|
OpRISCV64LoweredGetClosurePtr, OpWasmLoweredGetClosurePtr:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|
@ -115,7 +115,7 @@ func schedule(f *Func) {
|
||||||
v.Op == OpARMLoweredNilCheck || v.Op == OpARM64LoweredNilCheck ||
|
v.Op == OpARMLoweredNilCheck || v.Op == OpARM64LoweredNilCheck ||
|
||||||
v.Op == Op386LoweredNilCheck || v.Op == OpMIPS64LoweredNilCheck ||
|
v.Op == Op386LoweredNilCheck || v.Op == OpMIPS64LoweredNilCheck ||
|
||||||
v.Op == OpS390XLoweredNilCheck || v.Op == OpMIPSLoweredNilCheck ||
|
v.Op == OpS390XLoweredNilCheck || v.Op == OpMIPSLoweredNilCheck ||
|
||||||
v.Op == OpWasmLoweredNilCheck:
|
v.Op == OpRISCV64LoweredNilCheck || v.Op == OpWasmLoweredNilCheck:
|
||||||
// Nil checks must come before loads from the same address.
|
// Nil checks must come before loads from the same address.
|
||||||
score[v.ID] = ScoreNilCheck
|
score[v.ID] = ScoreNilCheck
|
||||||
case v.Op == OpPhi:
|
case v.Op == OpPhi:
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,11 @@
|
||||||
6: func test() {
|
6: func test() {
|
||||||
8: go func() {}()
|
8: go func() {}()
|
||||||
10: for {
|
10: for {
|
||||||
1048575:
|
1: package main
|
||||||
10: for {
|
10: for {
|
||||||
1048575:
|
1: package main
|
||||||
10: for {
|
10: for {
|
||||||
1048575:
|
1: package main
|
||||||
10: for {
|
10: for {
|
||||||
1048575:
|
1: package main
|
||||||
10: for {
|
10: for {
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ var (
|
||||||
Dowidth func(*Type)
|
Dowidth func(*Type)
|
||||||
Fatalf func(string, ...interface{})
|
Fatalf func(string, ...interface{})
|
||||||
Sconv func(*Sym, int, int) string // orig: func sconv(s *Sym, flag FmtFlag, mode fmtMode) string
|
Sconv func(*Sym, int, int) string // orig: func sconv(s *Sym, flag FmtFlag, mode fmtMode) string
|
||||||
Tconv func(*Type, int, int, int) string // orig: func tconv(t *Type, flag FmtFlag, mode fmtMode, depth int) string
|
Tconv func(*Type, int, int) string // orig: func tconv(t *Type, flag FmtFlag, mode fmtMode) string
|
||||||
FormatSym func(*Sym, fmt.State, rune, int) // orig: func symFormat(sym *Sym, s fmt.State, verb rune, mode fmtMode)
|
FormatSym func(*Sym, fmt.State, rune, int) // orig: func symFormat(sym *Sym, s fmt.State, verb rune, mode fmtMode)
|
||||||
FormatType func(*Type, fmt.State, rune, int) // orig: func typeFormat(t *Type, s fmt.State, verb rune, mode fmtMode)
|
FormatType func(*Type, fmt.State, rune, int) // orig: func typeFormat(t *Type, s fmt.State, verb rune, mode fmtMode)
|
||||||
TypeLinkSym func(*Type) *obj.LSym
|
TypeLinkSym func(*Type) *obj.LSym
|
||||||
|
|
@ -39,25 +39,23 @@ func (sym *Sym) Format(s fmt.State, verb rune) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Type) String() string {
|
func (t *Type) String() string {
|
||||||
// This is an external entry point, so we pass depth 0 to tconv.
|
|
||||||
// The implementation of tconv (including typefmt and fldconv)
|
// The implementation of tconv (including typefmt and fldconv)
|
||||||
// must take care not to use a type in a formatting string
|
// must handle recursive types correctly.
|
||||||
// to avoid resetting the recursion counter.
|
return Tconv(t, 0, FErr)
|
||||||
return Tconv(t, 0, FErr, 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ShortString generates a short description of t.
|
// ShortString generates a short description of t.
|
||||||
// It is used in autogenerated method names, reflection,
|
// It is used in autogenerated method names, reflection,
|
||||||
// and itab names.
|
// and itab names.
|
||||||
func (t *Type) ShortString() string {
|
func (t *Type) ShortString() string {
|
||||||
return Tconv(t, FmtLeft, FErr, 0)
|
return Tconv(t, FmtLeft, FErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LongString generates a complete description of t.
|
// LongString generates a complete description of t.
|
||||||
// It is useful for reflection,
|
// It is useful for reflection,
|
||||||
// or when a unique fingerprint or hash of a type is required.
|
// or when a unique fingerprint or hash of a type is required.
|
||||||
func (t *Type) LongString() string {
|
func (t *Type) LongString() string {
|
||||||
return Tconv(t, FmtLeft|FmtUnsigned, FErr, 0)
|
return Tconv(t, FmtLeft|FmtUnsigned, FErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Type) Format(s fmt.State, verb rune) {
|
func (t *Type) Format(s fmt.State, verb rune) {
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"cmd/compile/internal/mips"
|
"cmd/compile/internal/mips"
|
||||||
"cmd/compile/internal/mips64"
|
"cmd/compile/internal/mips64"
|
||||||
"cmd/compile/internal/ppc64"
|
"cmd/compile/internal/ppc64"
|
||||||
|
"cmd/compile/internal/riscv64"
|
||||||
"cmd/compile/internal/s390x"
|
"cmd/compile/internal/s390x"
|
||||||
"cmd/compile/internal/wasm"
|
"cmd/compile/internal/wasm"
|
||||||
"cmd/compile/internal/x86"
|
"cmd/compile/internal/x86"
|
||||||
|
|
@ -32,6 +33,7 @@ var archInits = map[string]func(*gc.Arch){
|
||||||
"mips64le": mips64.Init,
|
"mips64le": mips64.Init,
|
||||||
"ppc64": ppc64.Init,
|
"ppc64": ppc64.Init,
|
||||||
"ppc64le": ppc64.Init,
|
"ppc64le": ppc64.Init,
|
||||||
|
"riscv64": riscv64.Init,
|
||||||
"s390x": s390x.Init,
|
"s390x": s390x.Init,
|
||||||
"wasm": wasm.Init,
|
"wasm": wasm.Init,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
20
src/cmd/dist/build.go
vendored
20
src/cmd/dist/build.go
vendored
|
|
@ -110,6 +110,9 @@ func xinit() {
|
||||||
fatalf("$GOROOT must be set")
|
fatalf("$GOROOT must be set")
|
||||||
}
|
}
|
||||||
goroot = filepath.Clean(b)
|
goroot = filepath.Clean(b)
|
||||||
|
if modRoot := findModuleRoot(goroot); modRoot != "" {
|
||||||
|
fatalf("found go.mod file in %s: $GOROOT must not be inside a module", modRoot)
|
||||||
|
}
|
||||||
|
|
||||||
b = os.Getenv("GOROOT_FINAL")
|
b = os.Getenv("GOROOT_FINAL")
|
||||||
if b == "" {
|
if b == "" {
|
||||||
|
|
@ -1532,7 +1535,7 @@ var cgoEnabled = map[string]bool{
|
||||||
"linux/mipsle": true,
|
"linux/mipsle": true,
|
||||||
"linux/mips64": true,
|
"linux/mips64": true,
|
||||||
"linux/mips64le": true,
|
"linux/mips64le": true,
|
||||||
"linux/riscv64": true,
|
"linux/riscv64": false, // Issue 36641
|
||||||
"linux/s390x": true,
|
"linux/s390x": true,
|
||||||
"linux/sparc64": true,
|
"linux/sparc64": true,
|
||||||
"android/386": true,
|
"android/386": true,
|
||||||
|
|
@ -1560,7 +1563,6 @@ var cgoEnabled = map[string]bool{
|
||||||
// List of platforms which are supported but not complete yet. These get
|
// List of platforms which are supported but not complete yet. These get
|
||||||
// filtered out of cgoEnabled for 'dist list'. See golang.org/issue/28944
|
// filtered out of cgoEnabled for 'dist list'. See golang.org/issue/28944
|
||||||
var incomplete = map[string]bool{
|
var incomplete = map[string]bool{
|
||||||
"linux/riscv64": true,
|
|
||||||
"linux/sparc64": true,
|
"linux/sparc64": true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1590,6 +1592,20 @@ func checkCC() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func findModuleRoot(dir string) (root string) {
|
||||||
|
for {
|
||||||
|
if fi, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil && !fi.IsDir() {
|
||||||
|
return dir
|
||||||
|
}
|
||||||
|
d := filepath.Dir(dir)
|
||||||
|
if d == dir {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
dir = d
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func defaulttarg() string {
|
func defaulttarg() string {
|
||||||
// xgetwd might return a path with symlinks fully resolved, and if
|
// xgetwd might return a path with symlinks fully resolved, and if
|
||||||
// there happens to be symlinks in goroot, then the hasprefix test
|
// there happens to be symlinks in goroot, then the hasprefix test
|
||||||
|
|
|
||||||
3
src/cmd/dist/buildtool.go
vendored
3
src/cmd/dist/buildtool.go
vendored
|
|
@ -45,10 +45,11 @@ var bootstrapDirs = []string{
|
||||||
"cmd/compile/internal/mips",
|
"cmd/compile/internal/mips",
|
||||||
"cmd/compile/internal/mips64",
|
"cmd/compile/internal/mips64",
|
||||||
"cmd/compile/internal/ppc64",
|
"cmd/compile/internal/ppc64",
|
||||||
"cmd/compile/internal/types",
|
"cmd/compile/internal/riscv64",
|
||||||
"cmd/compile/internal/s390x",
|
"cmd/compile/internal/s390x",
|
||||||
"cmd/compile/internal/ssa",
|
"cmd/compile/internal/ssa",
|
||||||
"cmd/compile/internal/syntax",
|
"cmd/compile/internal/syntax",
|
||||||
|
"cmd/compile/internal/types",
|
||||||
"cmd/compile/internal/x86",
|
"cmd/compile/internal/x86",
|
||||||
"cmd/compile/internal/wasm",
|
"cmd/compile/internal/wasm",
|
||||||
"cmd/internal/bio",
|
"cmd/internal/bio",
|
||||||
|
|
|
||||||
2
src/cmd/dist/main.go
vendored
2
src/cmd/dist/main.go
vendored
|
|
@ -122,6 +122,8 @@ func main() {
|
||||||
if elfIsLittleEndian(os.Args[0]) {
|
if elfIsLittleEndian(os.Args[0]) {
|
||||||
gohostarch = "mipsle"
|
gohostarch = "mipsle"
|
||||||
}
|
}
|
||||||
|
case strings.Contains(out, "riscv64"):
|
||||||
|
gohostarch = "riscv64"
|
||||||
case strings.Contains(out, "s390x"):
|
case strings.Contains(out, "s390x"):
|
||||||
gohostarch = "s390x"
|
gohostarch = "s390x"
|
||||||
case gohostos == "darwin":
|
case gohostos == "darwin":
|
||||||
|
|
|
||||||
|
|
@ -65,9 +65,10 @@ func usage() {
|
||||||
fmt.Fprintf(os.Stderr, "Usage of [go] doc:\n")
|
fmt.Fprintf(os.Stderr, "Usage of [go] doc:\n")
|
||||||
fmt.Fprintf(os.Stderr, "\tgo doc\n")
|
fmt.Fprintf(os.Stderr, "\tgo doc\n")
|
||||||
fmt.Fprintf(os.Stderr, "\tgo doc <pkg>\n")
|
fmt.Fprintf(os.Stderr, "\tgo doc <pkg>\n")
|
||||||
fmt.Fprintf(os.Stderr, "\tgo doc <sym>[.<method>]\n")
|
fmt.Fprintf(os.Stderr, "\tgo doc <sym>[.<methodOrField>]\n")
|
||||||
fmt.Fprintf(os.Stderr, "\tgo doc [<pkg>].<sym>[.<method>]\n")
|
fmt.Fprintf(os.Stderr, "\tgo doc [<pkg>.]<sym>[.<methodOrField>]\n")
|
||||||
fmt.Fprintf(os.Stderr, "\tgo doc <pkg> <sym>[.<method>]\n")
|
fmt.Fprintf(os.Stderr, "\tgo doc [<pkg>.][<sym>.]<methodOrField>\n")
|
||||||
|
fmt.Fprintf(os.Stderr, "\tgo doc <pkg> <sym>[.<methodOrField>]\n")
|
||||||
fmt.Fprintf(os.Stderr, "For more information run\n")
|
fmt.Fprintf(os.Stderr, "For more information run\n")
|
||||||
fmt.Fprintf(os.Stderr, "\tgo help doc\n\n")
|
fmt.Fprintf(os.Stderr, "\tgo help doc\n\n")
|
||||||
fmt.Fprintf(os.Stderr, "Flags:\n")
|
fmt.Fprintf(os.Stderr, "Flags:\n")
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@ require (
|
||||||
github.com/google/pprof v0.0.0-20191105193234-27840fff0d09
|
github.com/google/pprof v0.0.0-20191105193234-27840fff0d09
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20180524225900-fc6590592b44 // indirect
|
github.com/ianlancetaylor/demangle v0.0.0-20180524225900-fc6590592b44 // indirect
|
||||||
golang.org/x/arch v0.0.0-20190815191158-8a70ba74b3a1
|
golang.org/x/arch v0.0.0-20190815191158-8a70ba74b3a1
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550
|
golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d
|
||||||
golang.org/x/mod v0.1.1-0.20191126161957-788aebd06792
|
golang.org/x/mod v0.2.0
|
||||||
golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82 // indirect
|
golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82 // indirect
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,10 @@ golang.org/x/arch v0.0.0-20190815191158-8a70ba74b3a1/go.mod h1:flIaEI6LNU6xOCD5P
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/mod v0.1.1-0.20191126161957-788aebd06792 h1:04Uqz7R2BD7irAGgQtrKNW5tLa50RgSW71y4ofoaivk=
|
golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d h1:9FCpayM9Egr1baVnV1SX0H87m+XB0B8S0hAMi99X/3U=
|
||||||
golang.org/x/mod v0.1.1-0.20191126161957-788aebd06792/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
|
||||||
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
|
|
||||||
|
|
@ -907,7 +907,7 @@
|
||||||
// Main bool // is this the main module?
|
// Main bool // is this the main module?
|
||||||
// Indirect bool // is this module only an indirect dependency of main module?
|
// Indirect bool // is this module only an indirect dependency of main module?
|
||||||
// Dir string // directory holding files for this module, if any
|
// Dir string // directory holding files for this module, if any
|
||||||
// GoMod string // path to go.mod file for this module, if any
|
// GoMod string // path to go.mod file used when loading this module, if any
|
||||||
// GoVersion string // go version used in module
|
// GoVersion string // go version used in module
|
||||||
// Error *ModuleError // error loading module
|
// Error *ModuleError // error loading module
|
||||||
// }
|
// }
|
||||||
|
|
@ -916,6 +916,9 @@
|
||||||
// Err string // the error itself
|
// Err string // the error itself
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
|
// The file GoMod refers to may be outside the module directory if the
|
||||||
|
// module is in the module cache or if the -modfile flag is used.
|
||||||
|
//
|
||||||
// The default output is to print the module path and then
|
// The default output is to print the module path and then
|
||||||
// information about the version and replacement if any.
|
// information about the version and replacement if any.
|
||||||
// For example, 'go list -m all' might print:
|
// For example, 'go list -m all' might print:
|
||||||
|
|
@ -1020,7 +1023,9 @@
|
||||||
// execution. The "go mod download" command is useful mainly for pre-filling
|
// execution. The "go mod download" command is useful mainly for pre-filling
|
||||||
// the local cache or to compute the answers for a Go module proxy.
|
// the local cache or to compute the answers for a Go module proxy.
|
||||||
//
|
//
|
||||||
// By default, download reports errors to standard error but is otherwise silent.
|
// By default, download writes nothing to standard output. It may print progress
|
||||||
|
// messages and errors to standard error.
|
||||||
|
//
|
||||||
// The -json flag causes download to print a sequence of JSON objects
|
// The -json flag causes download to print a sequence of JSON objects
|
||||||
// to standard output, describing each downloaded module (or failure),
|
// to standard output, describing each downloaded module (or failure),
|
||||||
// corresponding to this Go struct:
|
// corresponding to this Go struct:
|
||||||
|
|
@ -1075,12 +1080,17 @@
|
||||||
// add and drop an exclusion for the given module path and version.
|
// add and drop an exclusion for the given module path and version.
|
||||||
// Note that -exclude=path@version is a no-op if that exclusion already exists.
|
// Note that -exclude=path@version is a no-op if that exclusion already exists.
|
||||||
//
|
//
|
||||||
// The -replace=old[@v]=new[@v] and -dropreplace=old[@v] flags
|
// The -replace=old[@v]=new[@v] flag adds a replacement of the given
|
||||||
// add and drop a replacement of the given module path and version pair.
|
// module path and version pair. If the @v in old@v is omitted, a
|
||||||
// If the @v in old@v is omitted, the replacement applies to all versions
|
// replacement without a version on the left side is added, which applies
|
||||||
// with the old module path. If the @v in new@v is omitted, the new path
|
// to all versions of the old module path. If the @v in new@v is omitted,
|
||||||
// should be a local module root directory, not a module path.
|
// the new path should be a local module root directory, not a module
|
||||||
// Note that -replace overrides any existing replacements for old[@v].
|
// path. Note that -replace overrides any redundant replacements for old[@v],
|
||||||
|
// so omitting @v will drop existing replacements for specific versions.
|
||||||
|
//
|
||||||
|
// The -dropreplace=old[@v] flag drops a replacement of the given
|
||||||
|
// module path and version pair. If the @v is omitted, a replacement without
|
||||||
|
// a version on the left side is dropped.
|
||||||
//
|
//
|
||||||
// The -require, -droprequire, -exclude, -dropexclude, -replace,
|
// The -require, -droprequire, -exclude, -dropexclude, -replace,
|
||||||
// and -dropreplace editing flags may be repeated, and the changes
|
// and -dropreplace editing flags may be repeated, and the changes
|
||||||
|
|
@ -1721,8 +1731,10 @@
|
||||||
// GOHOSTOS
|
// GOHOSTOS
|
||||||
// The operating system (GOOS) of the Go toolchain binaries.
|
// The operating system (GOOS) of the Go toolchain binaries.
|
||||||
// GOMOD
|
// GOMOD
|
||||||
// The absolute path to the go.mod of the main module,
|
// The absolute path to the go.mod of the main module.
|
||||||
// or the empty string if not using modules.
|
// If module-aware mode is enabled, but there is no go.mod, GOMOD will be
|
||||||
|
// os.DevNull ("/dev/null" on Unix-like systems, "NUL" on Windows).
|
||||||
|
// If module-aware mode is disabled, GOMOD will be the empty string.
|
||||||
// GOTOOLDIR
|
// GOTOOLDIR
|
||||||
// The directory where the go tools (compile, cover, doc, etc...) are installed.
|
// The directory where the go tools (compile, cover, doc, etc...) are installed.
|
||||||
//
|
//
|
||||||
|
|
@ -2339,14 +2351,15 @@
|
||||||
//
|
//
|
||||||
// Module support
|
// Module support
|
||||||
//
|
//
|
||||||
// Go 1.13 includes support for Go modules. Module-aware mode is active by default
|
// The go command includes support for Go modules. Module-aware mode is active
|
||||||
// whenever a go.mod file is found in, or in a parent of, the current directory.
|
// by default whenever a go.mod file is found in the current directory or in
|
||||||
|
// any parent directory.
|
||||||
//
|
//
|
||||||
// The quickest way to take advantage of module support is to check out your
|
// The quickest way to take advantage of module support is to check out your
|
||||||
// repository, create a go.mod file (described in the next section) there, and run
|
// repository, create a go.mod file (described in the next section) there, and run
|
||||||
// go commands from within that file tree.
|
// go commands from within that file tree.
|
||||||
//
|
//
|
||||||
// For more fine-grained control, Go 1.13 continues to respect
|
// For more fine-grained control, the go command continues to respect
|
||||||
// a temporary environment variable, GO111MODULE, which can be set to one
|
// a temporary environment variable, GO111MODULE, which can be set to one
|
||||||
// of three string values: off, on, or auto (the default).
|
// of three string values: off, on, or auto (the default).
|
||||||
// If GO111MODULE=on, then the go command requires the use of modules,
|
// If GO111MODULE=on, then the go command requires the use of modules,
|
||||||
|
|
|
||||||
|
|
@ -638,7 +638,7 @@ func (tg *testgoData) grepStderrNot(match, msg string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// grepBothNot looks for a regular expression in the test run's
|
// grepBothNot looks for a regular expression in the test run's
|
||||||
// standard output or stand error and fails, logging msg, if it is
|
// standard output or standard error and fails, logging msg, if it is
|
||||||
// found.
|
// found.
|
||||||
func (tg *testgoData) grepBothNot(match, msg string) {
|
func (tg *testgoData) grepBothNot(match, msg string) {
|
||||||
tg.t.Helper()
|
tg.t.Helper()
|
||||||
|
|
@ -913,6 +913,7 @@ func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) {
|
||||||
|
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
|
tg.parallel()
|
||||||
|
|
||||||
// Copy the runtime packages into a temporary GOROOT
|
// Copy the runtime packages into a temporary GOROOT
|
||||||
// so that we can change files.
|
// so that we can change files.
|
||||||
|
|
@ -1026,28 +1027,6 @@ func TestInternalPackagesOutsideGOROOTAreRespected(t *testing.T) {
|
||||||
tg.grepBoth(`testinternal2(\/|\\)p\.go\:3\:8\: use of internal package .*internal/w not allowed`, "wrote error message for testdata/testinternal2")
|
tg.grepBoth(`testinternal2(\/|\\)p\.go\:3\:8\: use of internal package .*internal/w not allowed`, "wrote error message for testdata/testinternal2")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRunInternal(t *testing.T) {
|
|
||||||
tg := testgo(t)
|
|
||||||
defer tg.cleanup()
|
|
||||||
dir := filepath.Join(tg.pwd(), "testdata")
|
|
||||||
tg.setenv("GOPATH", dir)
|
|
||||||
tg.run("run", filepath.Join(dir, "src/run/good.go"))
|
|
||||||
tg.runFail("run", filepath.Join(dir, "src/run/bad.go"))
|
|
||||||
tg.grepStderr(`testdata(\/|\\)src(\/|\\)run(\/|\\)bad\.go\:3\:8\: use of internal package run/subdir/internal/private not allowed`, "unexpected error for run/bad.go")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRunPkg(t *testing.T) {
|
|
||||||
tg := testgo(t)
|
|
||||||
defer tg.cleanup()
|
|
||||||
dir := filepath.Join(tg.pwd(), "testdata")
|
|
||||||
tg.setenv("GOPATH", dir)
|
|
||||||
tg.run("run", "hello")
|
|
||||||
tg.grepStderr("hello, world", "did not find hello, world")
|
|
||||||
tg.cd(filepath.Join(dir, "src/hello"))
|
|
||||||
tg.run("run", ".")
|
|
||||||
tg.grepStderr("hello, world", "did not find hello, world")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestInternalPackageErrorsAreHandled(t *testing.T) {
|
func TestInternalPackageErrorsAreHandled(t *testing.T) {
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
|
|
@ -1062,56 +1041,6 @@ func TestInternalCache(t *testing.T) {
|
||||||
tg.grepStderr("internal", "did not fail to build p")
|
tg.grepStderr("internal", "did not fail to build p")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestImportCommandMatch(t *testing.T) {
|
|
||||||
tg := testgo(t)
|
|
||||||
defer tg.cleanup()
|
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/importcom"))
|
|
||||||
tg.run("build", "./testdata/importcom/works.go")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestImportCommentMismatch(t *testing.T) {
|
|
||||||
tg := testgo(t)
|
|
||||||
defer tg.cleanup()
|
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/importcom"))
|
|
||||||
tg.runFail("build", "./testdata/importcom/wrongplace.go")
|
|
||||||
tg.grepStderr(`wrongplace expects import "my/x"`, "go build did not mention incorrect import")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestImportCommentSyntaxError(t *testing.T) {
|
|
||||||
tg := testgo(t)
|
|
||||||
defer tg.cleanup()
|
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/importcom"))
|
|
||||||
tg.runFail("build", "./testdata/importcom/bad.go")
|
|
||||||
tg.grepStderr("cannot parse import comment", "go build did not mention syntax error")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestImportCommentConflict(t *testing.T) {
|
|
||||||
tg := testgo(t)
|
|
||||||
defer tg.cleanup()
|
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/importcom"))
|
|
||||||
tg.runFail("build", "./testdata/importcom/conflict.go")
|
|
||||||
tg.grepStderr("found import comments", "go build did not mention comment conflict")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestImportCycle(t *testing.T) {
|
|
||||||
tg := testgo(t)
|
|
||||||
defer tg.cleanup()
|
|
||||||
tg.parallel()
|
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/importcycle"))
|
|
||||||
tg.runFail("build", "selfimport")
|
|
||||||
|
|
||||||
count := tg.grepCountBoth("import cycle not allowed")
|
|
||||||
if count == 0 {
|
|
||||||
t.Fatal("go build did not mention cyclical import")
|
|
||||||
}
|
|
||||||
if count > 1 {
|
|
||||||
t.Fatal("go build mentioned import cycle more than once")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't hang forever.
|
|
||||||
tg.run("list", "-e", "-json", "selfimport")
|
|
||||||
}
|
|
||||||
|
|
||||||
// cmd/go: custom import path checking should not apply to Go packages without import comment.
|
// cmd/go: custom import path checking should not apply to Go packages without import comment.
|
||||||
func TestIssue10952(t *testing.T) {
|
func TestIssue10952(t *testing.T) {
|
||||||
testenv.MustHaveExternalNetwork(t)
|
testenv.MustHaveExternalNetwork(t)
|
||||||
|
|
@ -1217,24 +1146,6 @@ func TestAccidentalGitCheckout(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestErrorMessageForSyntaxErrorInTestGoFileSaysFAIL(t *testing.T) {
|
|
||||||
tg := testgo(t)
|
|
||||||
defer tg.cleanup()
|
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
|
||||||
tg.runFail("test", "syntaxerror")
|
|
||||||
tg.grepStderr("x_test.go:", "did not diagnose error")
|
|
||||||
tg.grepStdout("FAIL", "go test did not say FAIL")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWildcardsDoNotLookInUselessDirectories(t *testing.T) {
|
|
||||||
tg := testgo(t)
|
|
||||||
defer tg.cleanup()
|
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
|
||||||
tg.runFail("list", "...")
|
|
||||||
tg.grepBoth("badpkg", "go list ... failure does not mention badpkg")
|
|
||||||
tg.run("list", "m...")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRelativeImportsGoTest(t *testing.T) {
|
func TestRelativeImportsGoTest(t *testing.T) {
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
|
|
@ -1672,6 +1583,7 @@ func TestDefaultGOPATHGet(t *testing.T) {
|
||||||
|
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
|
tg.parallel()
|
||||||
tg.setenv("GOPATH", "")
|
tg.setenv("GOPATH", "")
|
||||||
tg.tempDir("home")
|
tg.tempDir("home")
|
||||||
tg.setenv(homeEnvName(), tg.path("home"))
|
tg.setenv(homeEnvName(), tg.path("home"))
|
||||||
|
|
@ -1696,6 +1608,7 @@ func TestDefaultGOPATHGet(t *testing.T) {
|
||||||
func TestDefaultGOPATHPrintedSearchList(t *testing.T) {
|
func TestDefaultGOPATHPrintedSearchList(t *testing.T) {
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
|
tg.parallel()
|
||||||
tg.setenv("GOPATH", "")
|
tg.setenv("GOPATH", "")
|
||||||
tg.tempDir("home")
|
tg.tempDir("home")
|
||||||
tg.setenv(homeEnvName(), tg.path("home"))
|
tg.setenv(homeEnvName(), tg.path("home"))
|
||||||
|
|
@ -1818,16 +1731,6 @@ func TestGoTestMutexprofileDashOControlsBinaryLocation(t *testing.T) {
|
||||||
tg.wantExecutable("myerrors.test"+exeSuffix, "go test -mutexprofile -o myerrors.test did not create myerrors.test")
|
tg.wantExecutable("myerrors.test"+exeSuffix, "go test -mutexprofile -o myerrors.test did not create myerrors.test")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGoBuildNonMain(t *testing.T) {
|
|
||||||
tg := testgo(t)
|
|
||||||
defer tg.cleanup()
|
|
||||||
// TODO: tg.parallel()
|
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
|
||||||
tg.runFail("build", "-buildmode=exe", "-o", "not_main"+exeSuffix, "not_main")
|
|
||||||
tg.grepStderr("-buildmode=exe requires exactly one main package", "go build with -o and -buildmode=exe should on a non-main package should throw an error")
|
|
||||||
tg.mustNotExist("not_main" + exeSuffix)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGoTestDashCDashOControlsBinaryLocation(t *testing.T) {
|
func TestGoTestDashCDashOControlsBinaryLocation(t *testing.T) {
|
||||||
skipIfGccgo(t, "gccgo has no standard packages")
|
skipIfGccgo(t, "gccgo has no standard packages")
|
||||||
tooSlow(t)
|
tooSlow(t)
|
||||||
|
|
@ -2191,33 +2094,6 @@ func TestCoverageNoStatements(t *testing.T) {
|
||||||
tg.grepStdout("[no statements]", "expected [no statements] for pkg4")
|
tg.grepStdout("[no statements]", "expected [no statements] for pkg4")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCoverageImportMainLoop(t *testing.T) {
|
|
||||||
skipIfGccgo(t, "gccgo has no cover tool")
|
|
||||||
tg := testgo(t)
|
|
||||||
defer tg.cleanup()
|
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
|
||||||
tg.runFail("test", "importmain/test")
|
|
||||||
tg.grepStderr("not an importable package", "did not detect import main")
|
|
||||||
tg.runFail("test", "-cover", "importmain/test")
|
|
||||||
tg.grepStderr("not an importable package", "did not detect import main")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCoveragePattern(t *testing.T) {
|
|
||||||
skipIfGccgo(t, "gccgo has no cover tool")
|
|
||||||
tooSlow(t)
|
|
||||||
tg := testgo(t)
|
|
||||||
defer tg.cleanup()
|
|
||||||
tg.parallel()
|
|
||||||
tg.makeTempdir()
|
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
|
||||||
|
|
||||||
// If coverpkg=sleepy... expands by package loading
|
|
||||||
// (as opposed to pattern matching on deps)
|
|
||||||
// then it will try to load sleepybad, which does not compile,
|
|
||||||
// and the test command will fail.
|
|
||||||
tg.run("test", "-coverprofile="+tg.path("cover.out"), "-coverpkg=sleepy...", "-run=^$", "sleepy1")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCoverageErrorLine(t *testing.T) {
|
func TestCoverageErrorLine(t *testing.T) {
|
||||||
skipIfGccgo(t, "gccgo has no cover tool")
|
skipIfGccgo(t, "gccgo has no cover tool")
|
||||||
tooSlow(t)
|
tooSlow(t)
|
||||||
|
|
@ -2290,20 +2166,6 @@ func TestCoverageDashC(t *testing.T) {
|
||||||
tg.wantExecutable(tg.path("coverdep"), "go -test -c -coverprofile did not create executable")
|
tg.wantExecutable(tg.path("coverdep"), "go -test -c -coverprofile did not create executable")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPluginNonMain(t *testing.T) {
|
|
||||||
wd, err := os.Getwd()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
pkg := filepath.Join(wd, "testdata", "testdep", "p2")
|
|
||||||
|
|
||||||
tg := testgo(t)
|
|
||||||
defer tg.cleanup()
|
|
||||||
|
|
||||||
tg.runFail("build", "-buildmode=plugin", pkg)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTestEmpty(t *testing.T) {
|
func TestTestEmpty(t *testing.T) {
|
||||||
if !canRace {
|
if !canRace {
|
||||||
t.Skip("no race detector")
|
t.Skip("no race detector")
|
||||||
|
|
@ -2388,39 +2250,6 @@ func main() {
|
||||||
tg.grepStderrNot(`os.Stat .* no such file or directory`, "unexpected stat of archive file")
|
tg.grepStderrNot(`os.Stat .* no such file or directory`, "unexpected stat of archive file")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCoverageWithCgo(t *testing.T) {
|
|
||||||
skipIfGccgo(t, "gccgo has no cover tool")
|
|
||||||
tooSlow(t)
|
|
||||||
if !canCgo {
|
|
||||||
t.Skip("skipping because cgo not enabled")
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, dir := range []string{"cgocover", "cgocover2", "cgocover3", "cgocover4"} {
|
|
||||||
t.Run(dir, func(t *testing.T) {
|
|
||||||
tg := testgo(t)
|
|
||||||
tg.parallel()
|
|
||||||
defer tg.cleanup()
|
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
|
||||||
tg.run("test", "-short", "-cover", dir)
|
|
||||||
data := tg.getStdout() + tg.getStderr()
|
|
||||||
checkCoverage(tg, data)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCgoAsmError(t *testing.T) {
|
|
||||||
if !canCgo {
|
|
||||||
t.Skip("skipping because cgo not enabled")
|
|
||||||
}
|
|
||||||
|
|
||||||
tg := testgo(t)
|
|
||||||
tg.parallel()
|
|
||||||
defer tg.cleanup()
|
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
|
||||||
tg.runFail("build", "cgoasm")
|
|
||||||
tg.grepBoth("package using cgo has Go assembly file", "did not detect Go assembly file")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCgoDependsOnSyscall(t *testing.T) {
|
func TestCgoDependsOnSyscall(t *testing.T) {
|
||||||
if testing.Short() {
|
if testing.Short() {
|
||||||
t.Skip("skipping test that removes $GOROOT/pkg/*_race in short mode")
|
t.Skip("skipping test that removes $GOROOT/pkg/*_race in short mode")
|
||||||
|
|
@ -2434,6 +2263,8 @@ func TestCgoDependsOnSyscall(t *testing.T) {
|
||||||
|
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
|
tg.parallel()
|
||||||
|
|
||||||
files, err := filepath.Glob(filepath.Join(runtime.GOROOT(), "pkg", "*_race"))
|
files, err := filepath.Glob(filepath.Join(runtime.GOROOT(), "pkg", "*_race"))
|
||||||
tg.must(err)
|
tg.must(err)
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
|
|
@ -2647,14 +2478,6 @@ func TestListTemplateContextFunction(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// cmd/go: "go test" should fail if package does not build
|
|
||||||
func TestIssue7108(t *testing.T) {
|
|
||||||
tg := testgo(t)
|
|
||||||
defer tg.cleanup()
|
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
|
||||||
tg.runFail("test", "notest")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGoBuildTestOnly(t *testing.T) {
|
func TestGoBuildTestOnly(t *testing.T) {
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
|
|
@ -2676,17 +2499,6 @@ func TestGoBuildTestOnly(t *testing.T) {
|
||||||
tg.run("install", "./testonly...")
|
tg.run("install", "./testonly...")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGoTestDetectsTestOnlyImportCycles(t *testing.T) {
|
|
||||||
tg := testgo(t)
|
|
||||||
defer tg.cleanup()
|
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
|
||||||
tg.runFail("test", "-c", "testcycle/p3")
|
|
||||||
tg.grepStderr("import cycle not allowed in test", "go test testcycle/p3 produced unexpected error")
|
|
||||||
|
|
||||||
tg.runFail("test", "-c", "testcycle/q1")
|
|
||||||
tg.grepStderr("import cycle not allowed in test", "go test testcycle/q1 produced unexpected error")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGoTestFooTestWorks(t *testing.T) {
|
func TestGoTestFooTestWorks(t *testing.T) {
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
|
|
@ -2714,29 +2526,6 @@ func TestGoTestMainAsNormalTest(t *testing.T) {
|
||||||
tg.grepBoth(okPattern, "go test did not say ok")
|
tg.grepBoth(okPattern, "go test did not say ok")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGoTestMainTwice(t *testing.T) {
|
|
||||||
if testing.Short() {
|
|
||||||
t.Skip("Skipping in short mode")
|
|
||||||
}
|
|
||||||
tg := testgo(t)
|
|
||||||
defer tg.cleanup()
|
|
||||||
tg.makeTempdir()
|
|
||||||
tg.setenv("GOCACHE", tg.tempdir)
|
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
|
||||||
tg.run("test", "-v", "multimain")
|
|
||||||
if strings.Count(tg.getStdout(), "notwithstanding") != 2 {
|
|
||||||
t.Fatal("tests did not run twice")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGoTestFlagsAfterPackage(t *testing.T) {
|
|
||||||
tooSlow(t)
|
|
||||||
tg := testgo(t)
|
|
||||||
defer tg.cleanup()
|
|
||||||
tg.run("test", "testdata/flag_test.go", "-v", "-args", "-v=7") // Two distinct -v flags.
|
|
||||||
tg.run("test", "-v", "testdata/flag_test.go", "-args", "-v=7") // Two distinct -v flags.
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGoTestXtestonlyWorks(t *testing.T) {
|
func TestGoTestXtestonlyWorks(t *testing.T) {
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
|
|
@ -2828,20 +2617,6 @@ func TestGoGenerateXTestPkgName(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGoGenerateBadImports(t *testing.T) {
|
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
t.Skip("skipping because windows has no echo command")
|
|
||||||
}
|
|
||||||
|
|
||||||
// This package has an invalid import causing an import cycle,
|
|
||||||
// but go generate is supposed to still run.
|
|
||||||
tg := testgo(t)
|
|
||||||
defer tg.cleanup()
|
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
|
||||||
tg.run("generate", "gencycle")
|
|
||||||
tg.grepStdout("hello world", "go generate gencycle did not run generator")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGoGetCustomDomainWildcard(t *testing.T) {
|
func TestGoGetCustomDomainWildcard(t *testing.T) {
|
||||||
testenv.MustHaveExternalNetwork(t)
|
testenv.MustHaveExternalNetwork(t)
|
||||||
testenv.MustHaveExecPath(t, "git")
|
testenv.MustHaveExecPath(t, "git")
|
||||||
|
|
@ -3267,43 +3042,6 @@ func TestGoTestRaceInstallCgo(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGoTestRaceFailures(t *testing.T) {
|
|
||||||
tooSlow(t)
|
|
||||||
|
|
||||||
if !canRace {
|
|
||||||
t.Skip("skipping because race detector not supported")
|
|
||||||
}
|
|
||||||
|
|
||||||
tg := testgo(t)
|
|
||||||
tg.parallel()
|
|
||||||
defer tg.cleanup()
|
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
|
||||||
|
|
||||||
tg.run("test", "testrace")
|
|
||||||
|
|
||||||
tg.runFail("test", "-race", "testrace")
|
|
||||||
tg.grepStdout("FAIL: TestRace", "TestRace did not fail")
|
|
||||||
tg.grepBothNot("PASS", "something passed")
|
|
||||||
|
|
||||||
tg.runFail("test", "-race", "testrace", "-run", "XXX", "-bench", ".")
|
|
||||||
tg.grepStdout("FAIL: BenchmarkRace", "BenchmarkRace did not fail")
|
|
||||||
tg.grepBothNot("PASS", "something passed")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGoTestImportErrorStack(t *testing.T) {
|
|
||||||
const out = `package testdep/p1 (test)
|
|
||||||
imports testdep/p2
|
|
||||||
imports testdep/p3: build constraints exclude all Go files `
|
|
||||||
|
|
||||||
tg := testgo(t)
|
|
||||||
defer tg.cleanup()
|
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
|
||||||
tg.runFail("test", "testdep/p1")
|
|
||||||
if !strings.Contains(tg.stderr.String(), out) {
|
|
||||||
t.Fatalf("did not give full import stack:\n\n%s", tg.stderr.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGoGetUpdate(t *testing.T) {
|
func TestGoGetUpdate(t *testing.T) {
|
||||||
// golang.org/issue/9224.
|
// golang.org/issue/9224.
|
||||||
// The recursive updating was trying to walk to
|
// The recursive updating was trying to walk to
|
||||||
|
|
@ -3626,27 +3364,6 @@ func TestGoGetUpdateAllDoesNotTryToLoadDuplicates(t *testing.T) {
|
||||||
tg.grepStderrNot("duplicate loads of", "did not remove old packages from cache")
|
tg.grepStderrNot("duplicate loads of", "did not remove old packages from cache")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Issue 17119 more duplicate load errors
|
|
||||||
func TestIssue17119(t *testing.T) {
|
|
||||||
testenv.MustHaveExternalNetwork(t)
|
|
||||||
|
|
||||||
tg := testgo(t)
|
|
||||||
defer tg.cleanup()
|
|
||||||
tg.parallel()
|
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
|
||||||
tg.runFail("build", "dupload")
|
|
||||||
tg.grepBothNot("duplicate load|internal error", "internal error")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFatalInBenchmarkCauseNonZeroExitStatus(t *testing.T) {
|
|
||||||
tg := testgo(t)
|
|
||||||
defer tg.cleanup()
|
|
||||||
// TODO: tg.parallel()
|
|
||||||
tg.runFail("test", "-run", "^$", "-bench", ".", "./testdata/src/benchfatal")
|
|
||||||
tg.grepBothNot("^ok", "test passed unexpectedly")
|
|
||||||
tg.grepBoth("FAIL.*benchfatal", "test did not run everything")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBinaryOnlyPackages(t *testing.T) {
|
func TestBinaryOnlyPackages(t *testing.T) {
|
||||||
tooSlow(t)
|
tooSlow(t)
|
||||||
|
|
||||||
|
|
@ -3812,16 +3529,6 @@ func TestMatchesNoTests(t *testing.T) {
|
||||||
tg.grepBoth(noMatchesPattern, "go test did not say [no tests to run]")
|
tg.grepBoth(noMatchesPattern, "go test did not say [no tests to run]")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMatchesNoTestsDoesNotOverrideBuildFailure(t *testing.T) {
|
|
||||||
tg := testgo(t)
|
|
||||||
defer tg.cleanup()
|
|
||||||
tg.parallel()
|
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
|
||||||
tg.runFail("test", "-run", "ThisWillNotMatch", "syntaxerror")
|
|
||||||
tg.grepBothNot(noMatchesPattern, "go test did say [no tests to run]")
|
|
||||||
tg.grepBoth("FAIL", "go test did not say FAIL")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMatchesNoBenchmarksIsOK(t *testing.T) {
|
func TestMatchesNoBenchmarksIsOK(t *testing.T) {
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
|
|
@ -3849,18 +3556,6 @@ func TestMatchesOnlyBenchmarkIsOK(t *testing.T) {
|
||||||
tg.grepBoth(okPattern, "go test did not say ok")
|
tg.grepBoth(okPattern, "go test did not say ok")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBenchmarkLabels(t *testing.T) {
|
|
||||||
tg := testgo(t)
|
|
||||||
defer tg.cleanup()
|
|
||||||
// TODO: tg.parallel()
|
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
|
||||||
tg.run("test", "-run", "^$", "-bench", ".", "bench")
|
|
||||||
tg.grepStdout(`(?m)^goos: `+runtime.GOOS, "go test did not print goos")
|
|
||||||
tg.grepStdout(`(?m)^goarch: `+runtime.GOARCH, "go test did not print goarch")
|
|
||||||
tg.grepStdout(`(?m)^pkg: bench`, "go test did not say pkg: bench")
|
|
||||||
tg.grepBothNot(`(?s)pkg:.*pkg:`, "go test said pkg multiple times")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBenchmarkLabelsOutsideGOPATH(t *testing.T) {
|
func TestBenchmarkLabelsOutsideGOPATH(t *testing.T) {
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
|
|
@ -4260,25 +3955,6 @@ func TestCgoFlagContainsSpace(t *testing.T) {
|
||||||
tg.grepStderrNot(`"-L[^"]+c flags".*"-L[^"]+c flags"`, "found too many quoted ld flags")
|
tg.grepStderrNot(`"-L[^"]+c flags".*"-L[^"]+c flags"`, "found too many quoted ld flags")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Issue #20435.
|
|
||||||
func TestGoTestRaceCoverModeFailures(t *testing.T) {
|
|
||||||
tooSlow(t)
|
|
||||||
if !canRace {
|
|
||||||
t.Skip("skipping because race detector not supported")
|
|
||||||
}
|
|
||||||
|
|
||||||
tg := testgo(t)
|
|
||||||
tg.parallel()
|
|
||||||
defer tg.cleanup()
|
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
|
||||||
|
|
||||||
tg.run("test", "testrace")
|
|
||||||
|
|
||||||
tg.runFail("test", "-race", "-covermode=set", "testrace")
|
|
||||||
tg.grepStderr(`-covermode must be "atomic", not "set", when -race is enabled`, "-race -covermode=set was allowed")
|
|
||||||
tg.grepBothNot("PASS", "something passed")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Issue 9737: verify that GOARM and GO386 affect the computed build ID.
|
// Issue 9737: verify that GOARM and GO386 affect the computed build ID.
|
||||||
func TestBuildIDContainsArchModeEnv(t *testing.T) {
|
func TestBuildIDContainsArchModeEnv(t *testing.T) {
|
||||||
if testing.Short() {
|
if testing.Short() {
|
||||||
|
|
@ -4318,60 +3994,6 @@ func main() {}`)
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTestRegexps(t *testing.T) {
|
|
||||||
tg := testgo(t)
|
|
||||||
defer tg.cleanup()
|
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
|
||||||
tg.run("test", "-cpu=1", "-run=X/Y", "-bench=X/Y", "-count=2", "-v", "testregexp")
|
|
||||||
var lines []string
|
|
||||||
for _, line := range strings.SplitAfter(tg.getStdout(), "\n") {
|
|
||||||
if strings.Contains(line, "=== RUN") || strings.Contains(line, "--- BENCH") || strings.Contains(line, "LOG") {
|
|
||||||
lines = append(lines, line)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Important parts:
|
|
||||||
// TestX is run, twice
|
|
||||||
// TestX/Y is run, twice
|
|
||||||
// TestXX is run, twice
|
|
||||||
// TestZ is not run
|
|
||||||
// BenchmarkX is run but only with N=1, once
|
|
||||||
// BenchmarkXX is run but only with N=1, once
|
|
||||||
// BenchmarkX/Y is run in full, twice
|
|
||||||
want := `=== RUN TestX
|
|
||||||
TestX: x_test.go:6: LOG: X running
|
|
||||||
=== RUN TestX/Y
|
|
||||||
TestX/Y: x_test.go:8: LOG: Y running
|
|
||||||
=== RUN TestXX
|
|
||||||
TestXX: z_test.go:10: LOG: XX running
|
|
||||||
=== RUN TestX
|
|
||||||
TestX: x_test.go:6: LOG: X running
|
|
||||||
=== RUN TestX/Y
|
|
||||||
TestX/Y: x_test.go:8: LOG: Y running
|
|
||||||
=== RUN TestXX
|
|
||||||
TestXX: z_test.go:10: LOG: XX running
|
|
||||||
BenchmarkX: x_test.go:13: LOG: X running N=1
|
|
||||||
BenchmarkX/Y: x_test.go:15: LOG: Y running N=1
|
|
||||||
BenchmarkX/Y: x_test.go:15: LOG: Y running N=100
|
|
||||||
BenchmarkX/Y: x_test.go:15: LOG: Y running N=10000
|
|
||||||
BenchmarkX/Y: x_test.go:15: LOG: Y running N=1000000
|
|
||||||
BenchmarkX/Y: x_test.go:15: LOG: Y running N=100000000
|
|
||||||
BenchmarkX/Y: x_test.go:15: LOG: Y running N=1000000000
|
|
||||||
BenchmarkX/Y: x_test.go:15: LOG: Y running N=1
|
|
||||||
BenchmarkX/Y: x_test.go:15: LOG: Y running N=100
|
|
||||||
BenchmarkX/Y: x_test.go:15: LOG: Y running N=10000
|
|
||||||
BenchmarkX/Y: x_test.go:15: LOG: Y running N=1000000
|
|
||||||
BenchmarkX/Y: x_test.go:15: LOG: Y running N=100000000
|
|
||||||
BenchmarkX/Y: x_test.go:15: LOG: Y running N=1000000000
|
|
||||||
BenchmarkXX: z_test.go:18: LOG: XX running N=1
|
|
||||||
`
|
|
||||||
|
|
||||||
have := strings.Join(lines, "")
|
|
||||||
if have != want {
|
|
||||||
t.Errorf("reduced output:<<<\n%s>>> want:<<<\n%s>>>", have, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestListTests(t *testing.T) {
|
func TestListTests(t *testing.T) {
|
||||||
tooSlow(t)
|
tooSlow(t)
|
||||||
var tg *testgoData
|
var tg *testgoData
|
||||||
|
|
@ -4407,6 +4029,7 @@ func TestBuildmodePIE(t *testing.T) {
|
||||||
|
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
|
tg.parallel()
|
||||||
|
|
||||||
tg.tempFile("main.go", `package main; func main() { print("hello") }`)
|
tg.tempFile("main.go", `package main; func main() { print("hello") }`)
|
||||||
src := tg.path("main.go")
|
src := tg.path("main.go")
|
||||||
|
|
@ -4570,6 +4193,7 @@ func TestUpxCompression(t *testing.T) {
|
||||||
|
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
|
tg.parallel()
|
||||||
|
|
||||||
tg.tempFile("main.go", `package main; import "fmt"; func main() { fmt.Print("hello upx") }`)
|
tg.tempFile("main.go", `package main; import "fmt"; func main() { fmt.Print("hello upx") }`)
|
||||||
src := tg.path("main.go")
|
src := tg.path("main.go")
|
||||||
|
|
@ -4963,14 +4587,6 @@ func TestInstallDeps(t *testing.T) {
|
||||||
tg.mustExist(p1)
|
tg.mustExist(p1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGoTestMinusN(t *testing.T) {
|
|
||||||
// Intent here is to verify that 'go test -n' works without crashing.
|
|
||||||
// This reuses flag_test.go, but really any test would do.
|
|
||||||
tg := testgo(t)
|
|
||||||
defer tg.cleanup()
|
|
||||||
tg.run("test", "testdata/flag_test.go", "-n", "-args", "-v=7")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGoTestJSON(t *testing.T) {
|
func TestGoTestJSON(t *testing.T) {
|
||||||
skipIfGccgo(t, "gccgo does not have standard packages")
|
skipIfGccgo(t, "gccgo does not have standard packages")
|
||||||
tooSlow(t)
|
tooSlow(t)
|
||||||
|
|
@ -5108,6 +4724,7 @@ func init() {}
|
||||||
func TestBadCommandLines(t *testing.T) {
|
func TestBadCommandLines(t *testing.T) {
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
|
tg.parallel()
|
||||||
|
|
||||||
tg.tempFile("src/x/x.go", "package x\n")
|
tg.tempFile("src/x/x.go", "package x\n")
|
||||||
tg.setenv("GOPATH", tg.path("."))
|
tg.setenv("GOPATH", tg.path("."))
|
||||||
|
|
@ -5328,6 +4945,7 @@ func TestCgoCache(t *testing.T) {
|
||||||
func TestFilepathUnderCwdFormat(t *testing.T) {
|
func TestFilepathUnderCwdFormat(t *testing.T) {
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
|
tg.parallel()
|
||||||
tg.run("test", "-x", "-cover", "log")
|
tg.run("test", "-x", "-cover", "log")
|
||||||
tg.grepStderrNot(`\.log\.cover\.go`, "-x output should contain correctly formatted filepath under cwd")
|
tg.grepStderrNot(`\.log\.cover\.go`, "-x output should contain correctly formatted filepath under cwd")
|
||||||
}
|
}
|
||||||
|
|
@ -5432,16 +5050,6 @@ func TestCDAndGOPATHAreDifferent(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Issue 26242.
|
|
||||||
func TestGoTestWithoutTests(t *testing.T) {
|
|
||||||
tg := testgo(t)
|
|
||||||
defer tg.cleanup()
|
|
||||||
tg.parallel()
|
|
||||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
|
||||||
tg.run("test", "testnorun")
|
|
||||||
tg.grepStdout(`testnorun\t\[no test files\]`, "do not want test to run")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Issue 25579.
|
// Issue 25579.
|
||||||
func TestGoBuildDashODevNull(t *testing.T) {
|
func TestGoBuildDashODevNull(t *testing.T) {
|
||||||
tooSlow(t)
|
tooSlow(t)
|
||||||
|
|
|
||||||
|
|
@ -178,10 +178,12 @@ func runClean(cmd *base.Command, args []string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if _, statErr := os.Stat(dir); !os.IsNotExist(statErr) {
|
||||||
base.Errorf("go clean -testcache: %v", err)
|
base.Errorf("go clean -testcache: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if cleanModcache {
|
if cleanModcache {
|
||||||
if modfetch.PkgMod == "" {
|
if modfetch.PkgMod == "" {
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import (
|
||||||
|
|
||||||
"cmd/go/internal/base"
|
"cmd/go/internal/base"
|
||||||
"cmd/go/internal/cfg"
|
"cmd/go/internal/cfg"
|
||||||
|
"cmd/go/internal/load"
|
||||||
"cmd/go/internal/web"
|
"cmd/go/internal/web"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -661,7 +662,7 @@ func RepoRootForImportPath(importPath string, mod ModuleMode, security web.Secur
|
||||||
if err == errUnknownSite {
|
if err == errUnknownSite {
|
||||||
rr, err = repoRootForImportDynamic(importPath, mod, security)
|
rr, err = repoRootForImportDynamic(importPath, mod, security)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("unrecognized import path %q: %v", importPath, err)
|
err = load.ImportErrorf(importPath, "unrecognized import path %q: %v", importPath, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -676,7 +677,7 @@ func RepoRootForImportPath(importPath string, mod ModuleMode, security web.Secur
|
||||||
if err == nil && strings.Contains(importPath, "...") && strings.Contains(rr.Root, "...") {
|
if err == nil && strings.Contains(importPath, "...") && strings.Contains(rr.Root, "...") {
|
||||||
// Do not allow wildcards in the repo root.
|
// Do not allow wildcards in the repo root.
|
||||||
rr = nil
|
rr = nil
|
||||||
err = fmt.Errorf("cannot expand ... in %q", importPath)
|
err = load.ImportErrorf(importPath, "cannot expand ... in %q", importPath)
|
||||||
}
|
}
|
||||||
return rr, err
|
return rr, err
|
||||||
}
|
}
|
||||||
|
|
@ -700,7 +701,7 @@ func repoRootFromVCSPaths(importPath string, security web.SecurityMode, vcsPaths
|
||||||
m := srv.regexp.FindStringSubmatch(importPath)
|
m := srv.regexp.FindStringSubmatch(importPath)
|
||||||
if m == nil {
|
if m == nil {
|
||||||
if srv.prefix != "" {
|
if srv.prefix != "" {
|
||||||
return nil, fmt.Errorf("invalid %s import path %q", srv.prefix, importPath)
|
return nil, load.ImportErrorf(importPath, "invalid %s import path %q", srv.prefix, importPath)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -621,8 +621,10 @@ Additional information available from 'go env' but not read from the environment
|
||||||
GOHOSTOS
|
GOHOSTOS
|
||||||
The operating system (GOOS) of the Go toolchain binaries.
|
The operating system (GOOS) of the Go toolchain binaries.
|
||||||
GOMOD
|
GOMOD
|
||||||
The absolute path to the go.mod of the main module,
|
The absolute path to the go.mod of the main module.
|
||||||
or the empty string if not using modules.
|
If module-aware mode is enabled, but there is no go.mod, GOMOD will be
|
||||||
|
os.DevNull ("/dev/null" on Unix-like systems, "NUL" on Windows).
|
||||||
|
If module-aware mode is disabled, GOMOD will be the empty string.
|
||||||
GOTOOLDIR
|
GOTOOLDIR
|
||||||
The directory where the go tools (compile, cover, doc, etc...) are installed.
|
The directory where the go tools (compile, cover, doc, etc...) are installed.
|
||||||
`,
|
`,
|
||||||
|
|
|
||||||
|
|
@ -211,7 +211,7 @@ applied to a Go struct, but now a Module struct:
|
||||||
Main bool // is this the main module?
|
Main bool // is this the main module?
|
||||||
Indirect bool // is this module only an indirect dependency of main module?
|
Indirect bool // is this module only an indirect dependency of main module?
|
||||||
Dir string // directory holding files for this module, if any
|
Dir string // directory holding files for this module, if any
|
||||||
GoMod string // path to go.mod file for this module, if any
|
GoMod string // path to go.mod file used when loading this module, if any
|
||||||
GoVersion string // go version used in module
|
GoVersion string // go version used in module
|
||||||
Error *ModuleError // error loading module
|
Error *ModuleError // error loading module
|
||||||
}
|
}
|
||||||
|
|
@ -220,6 +220,9 @@ applied to a Go struct, but now a Module struct:
|
||||||
Err string // the error itself
|
Err string // the error itself
|
||||||
}
|
}
|
||||||
|
|
||||||
|
The file GoMod refers to may be outside the module directory if the
|
||||||
|
module is in the module cache or if the -modfile flag is used.
|
||||||
|
|
||||||
The default output is to print the module path and then
|
The default output is to print the module path and then
|
||||||
information about the version and replacement if any.
|
information about the version and replacement if any.
|
||||||
For example, 'go list -m all' might print:
|
For example, 'go list -m all' might print:
|
||||||
|
|
@ -387,15 +390,24 @@ func runList(cmd *base.Command, args []string) {
|
||||||
|
|
||||||
modload.InitMod() // Parses go.mod and sets cfg.BuildMod.
|
modload.InitMod() // Parses go.mod and sets cfg.BuildMod.
|
||||||
if cfg.BuildMod == "vendor" {
|
if cfg.BuildMod == "vendor" {
|
||||||
|
const actionDisabledFormat = "go list -m: can't %s using the vendor directory\n\t(Use -mod=mod or -mod=readonly to bypass.)"
|
||||||
|
|
||||||
|
if *listVersions {
|
||||||
|
base.Fatalf(actionDisabledFormat, "determine available versions")
|
||||||
|
}
|
||||||
|
if *listU {
|
||||||
|
base.Fatalf(actionDisabledFormat, "determine available upgrades")
|
||||||
|
}
|
||||||
|
|
||||||
for _, arg := range args {
|
for _, arg := range args {
|
||||||
// In vendor mode, the module graph is incomplete: it contains only the
|
// In vendor mode, the module graph is incomplete: it contains only the
|
||||||
// explicit module dependencies and the modules that supply packages in
|
// explicit module dependencies and the modules that supply packages in
|
||||||
// the import graph. Reject queries that imply more information than that.
|
// the import graph. Reject queries that imply more information than that.
|
||||||
if arg == "all" {
|
if arg == "all" {
|
||||||
base.Fatalf("go list -m: can't compute 'all' using the vendor directory\n\t(Use -mod=mod or -mod=readonly to bypass.)")
|
base.Fatalf(actionDisabledFormat, "compute 'all'")
|
||||||
}
|
}
|
||||||
if strings.Contains(arg, "...") {
|
if strings.Contains(arg, "...") {
|
||||||
base.Fatalf("go list -m: can't match module patterns using the vendor directory\n\t(Use -mod=mod or -mod=readonly to bypass.)")
|
base.Fatalf(actionDisabledFormat, "match module patterns")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/build"
|
"go/build"
|
||||||
|
"go/scanner"
|
||||||
"go/token"
|
"go/token"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
|
@ -1519,18 +1520,31 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
|
||||||
p.Internal.LocalPrefix = dirToImportPath(p.Dir)
|
p.Internal.LocalPrefix = dirToImportPath(p.Dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setError sets p.Error if it hasn't already been set. We may proceed
|
||||||
|
// after encountering some errors so that 'go list -e' has more complete
|
||||||
|
// output. If there's more than one error, we should report the first.
|
||||||
|
setError := func(err error) {
|
||||||
|
if p.Error == nil {
|
||||||
|
p.Error = &PackageError{
|
||||||
|
ImportStack: stk.Copy(),
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if _, ok := err.(*build.NoGoError); ok {
|
if _, ok := err.(*build.NoGoError); ok {
|
||||||
err = &NoGoError{Package: p}
|
err = &NoGoError{Package: p}
|
||||||
}
|
}
|
||||||
p.Incomplete = true
|
p.Incomplete = true
|
||||||
err = base.ExpandScanner(err)
|
|
||||||
p.Error = &PackageError{
|
setError(base.ExpandScanner(err))
|
||||||
ImportStack: stk.Copy(),
|
if _, isScanErr := err.(scanner.ErrorList); !isScanErr {
|
||||||
Err: err,
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// Fall through if there was an error parsing a file. 'go list -e' should
|
||||||
|
// still report imports and other metadata.
|
||||||
|
}
|
||||||
|
|
||||||
useBindir := p.Name == "main"
|
useBindir := p.Name == "main"
|
||||||
if !p.Standard {
|
if !p.Standard {
|
||||||
|
|
@ -1545,7 +1559,7 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
|
||||||
if InstallTargetDir(p) == StalePath {
|
if InstallTargetDir(p) == StalePath {
|
||||||
newPath := strings.Replace(p.ImportPath, "code.google.com/p/go.", "golang.org/x/", 1)
|
newPath := strings.Replace(p.ImportPath, "code.google.com/p/go.", "golang.org/x/", 1)
|
||||||
e := ImportErrorf(p.ImportPath, "the %v command has moved; use %v instead.", p.ImportPath, newPath)
|
e := ImportErrorf(p.ImportPath, "the %v command has moved; use %v instead.", p.ImportPath, newPath)
|
||||||
p.Error = &PackageError{Err: e}
|
setError(e)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
elem := p.DefaultExecName()
|
elem := p.DefaultExecName()
|
||||||
|
|
@ -1658,10 +1672,7 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
|
||||||
inputs := p.AllFiles()
|
inputs := p.AllFiles()
|
||||||
f1, f2 := str.FoldDup(inputs)
|
f1, f2 := str.FoldDup(inputs)
|
||||||
if f1 != "" {
|
if f1 != "" {
|
||||||
p.Error = &PackageError{
|
setError(fmt.Errorf("case-insensitive file name collision: %q and %q", f1, f2))
|
||||||
ImportStack: stk.Copy(),
|
|
||||||
Err: fmt.Errorf("case-insensitive file name collision: %q and %q", f1, f2),
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1674,25 +1685,16 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
|
||||||
// so we shouldn't see any _cgo_ files anyway, but just be safe.
|
// so we shouldn't see any _cgo_ files anyway, but just be safe.
|
||||||
for _, file := range inputs {
|
for _, file := range inputs {
|
||||||
if !SafeArg(file) || strings.HasPrefix(file, "_cgo_") {
|
if !SafeArg(file) || strings.HasPrefix(file, "_cgo_") {
|
||||||
p.Error = &PackageError{
|
setError(fmt.Errorf("invalid input file name %q", file))
|
||||||
ImportStack: stk.Copy(),
|
|
||||||
Err: fmt.Errorf("invalid input file name %q", file),
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if name := pathpkg.Base(p.ImportPath); !SafeArg(name) {
|
if name := pathpkg.Base(p.ImportPath); !SafeArg(name) {
|
||||||
p.Error = &PackageError{
|
setError(fmt.Errorf("invalid input directory name %q", name))
|
||||||
ImportStack: stk.Copy(),
|
|
||||||
Err: fmt.Errorf("invalid input directory name %q", name),
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !SafeArg(p.ImportPath) {
|
if !SafeArg(p.ImportPath) {
|
||||||
p.Error = &PackageError{
|
setError(ImportErrorf(p.ImportPath, "invalid import path %q", p.ImportPath))
|
||||||
ImportStack: stk.Copy(),
|
|
||||||
Err: ImportErrorf(p.ImportPath, "invalid import path %q", p.ImportPath),
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1737,13 +1739,6 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
|
||||||
// code; see issue #16050).
|
// code; see issue #16050).
|
||||||
}
|
}
|
||||||
|
|
||||||
setError := func(err error) {
|
|
||||||
p.Error = &PackageError{
|
|
||||||
ImportStack: stk.Copy(),
|
|
||||||
Err: err,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The gc toolchain only permits C source files with cgo or SWIG.
|
// The gc toolchain only permits C source files with cgo or SWIG.
|
||||||
if len(p.CFiles) > 0 && !p.UsesCgo() && !p.UsesSwig() && cfg.BuildContext.Compiler == "gc" {
|
if len(p.CFiles) > 0 && !p.UsesCgo() && !p.UsesSwig() && cfg.BuildContext.Compiler == "gc" {
|
||||||
setError(fmt.Errorf("C source files not allowed when not using cgo or SWIG: %s", strings.Join(p.CFiles, " ")))
|
setError(fmt.Errorf("C source files not allowed when not using cgo or SWIG: %s", strings.Join(p.CFiles, " ")))
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,9 @@ The go command will automatically download modules as needed during ordinary
|
||||||
execution. The "go mod download" command is useful mainly for pre-filling
|
execution. The "go mod download" command is useful mainly for pre-filling
|
||||||
the local cache or to compute the answers for a Go module proxy.
|
the local cache or to compute the answers for a Go module proxy.
|
||||||
|
|
||||||
By default, download reports errors to standard error but is otherwise silent.
|
By default, download writes nothing to standard output. It may print progress
|
||||||
|
messages and errors to standard error.
|
||||||
|
|
||||||
The -json flag causes download to print a sequence of JSON objects
|
The -json flag causes download to print a sequence of JSON objects
|
||||||
to standard output, describing each downloaded module (or failure),
|
to standard output, describing each downloaded module (or failure),
|
||||||
corresponding to this Go struct:
|
corresponding to this Go struct:
|
||||||
|
|
|
||||||
|
|
@ -55,12 +55,17 @@ The -exclude=path@version and -dropexclude=path@version flags
|
||||||
add and drop an exclusion for the given module path and version.
|
add and drop an exclusion for the given module path and version.
|
||||||
Note that -exclude=path@version is a no-op if that exclusion already exists.
|
Note that -exclude=path@version is a no-op if that exclusion already exists.
|
||||||
|
|
||||||
The -replace=old[@v]=new[@v] and -dropreplace=old[@v] flags
|
The -replace=old[@v]=new[@v] flag adds a replacement of the given
|
||||||
add and drop a replacement of the given module path and version pair.
|
module path and version pair. If the @v in old@v is omitted, a
|
||||||
If the @v in old@v is omitted, the replacement applies to all versions
|
replacement without a version on the left side is added, which applies
|
||||||
with the old module path. If the @v in new@v is omitted, the new path
|
to all versions of the old module path. If the @v in new@v is omitted,
|
||||||
should be a local module root directory, not a module path.
|
the new path should be a local module root directory, not a module
|
||||||
Note that -replace overrides any existing replacements for old[@v].
|
path. Note that -replace overrides any redundant replacements for old[@v],
|
||||||
|
so omitting @v will drop existing replacements for specific versions.
|
||||||
|
|
||||||
|
The -dropreplace=old[@v] flag drops a replacement of the given
|
||||||
|
module path and version pair. If the @v is omitted, a replacement without
|
||||||
|
a version on the left side is dropped.
|
||||||
|
|
||||||
The -require, -droprequire, -exclude, -dropexclude, -replace,
|
The -require, -droprequire, -exclude, -dropexclude, -replace,
|
||||||
and -dropreplace editing flags may be repeated, and the changes
|
and -dropreplace editing flags may be repeated, and the changes
|
||||||
|
|
@ -164,7 +169,7 @@ func runEdit(cmd *base.Command, args []string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if *editModule != "" {
|
if *editModule != "" {
|
||||||
if err := module.CheckPath(*editModule); err != nil {
|
if err := module.CheckImportPath(*editModule); err != nil {
|
||||||
base.Fatalf("go mod: invalid -module: %v", err)
|
base.Fatalf("go mod: invalid -module: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -242,7 +247,7 @@ func parsePathVersion(flag, arg string) (path, version string) {
|
||||||
base.Fatalf("go mod: -%s=%s: need path@version", flag, arg)
|
base.Fatalf("go mod: -%s=%s: need path@version", flag, arg)
|
||||||
}
|
}
|
||||||
path, version = strings.TrimSpace(arg[:i]), strings.TrimSpace(arg[i+1:])
|
path, version = strings.TrimSpace(arg[:i]), strings.TrimSpace(arg[i+1:])
|
||||||
if err := module.CheckPath(path); err != nil {
|
if err := module.CheckImportPath(path); err != nil {
|
||||||
base.Fatalf("go mod: -%s=%s: invalid path: %v", flag, arg, err)
|
base.Fatalf("go mod: -%s=%s: invalid path: %v", flag, arg, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -264,7 +269,7 @@ func parsePath(flag, arg string) (path string) {
|
||||||
base.Fatalf("go mod: -%s=%s: need just path, not path@version", flag, arg)
|
base.Fatalf("go mod: -%s=%s: need just path, not path@version", flag, arg)
|
||||||
}
|
}
|
||||||
path = arg
|
path = arg
|
||||||
if err := module.CheckPath(path); err != nil {
|
if err := module.CheckImportPath(path); err != nil {
|
||||||
base.Fatalf("go mod: -%s=%s: invalid path: %v", flag, arg, err)
|
base.Fatalf("go mod: -%s=%s: invalid path: %v", flag, arg, err)
|
||||||
}
|
}
|
||||||
return path
|
return path
|
||||||
|
|
@ -278,7 +283,7 @@ func parsePathVersionOptional(adj, arg string, allowDirPath bool) (path, version
|
||||||
} else {
|
} else {
|
||||||
path, version = strings.TrimSpace(arg[:i]), strings.TrimSpace(arg[i+1:])
|
path, version = strings.TrimSpace(arg[:i]), strings.TrimSpace(arg[i+1:])
|
||||||
}
|
}
|
||||||
if err := module.CheckPath(path); err != nil {
|
if err := module.CheckImportPath(path); err != nil {
|
||||||
if !allowDirPath || !modfile.IsDirectoryPath(path) {
|
if !allowDirPath || !modfile.IsDirectoryPath(path) {
|
||||||
return path, version, fmt.Errorf("invalid %s path: %v", adj, err)
|
return path, version, fmt.Errorf("invalid %s path: %v", adj, err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"cmd/go/internal/base"
|
"cmd/go/internal/base"
|
||||||
"cmd/go/internal/cfg"
|
"cmd/go/internal/cfg"
|
||||||
|
|
@ -28,8 +27,6 @@ import (
|
||||||
|
|
||||||
var PkgMod string // $GOPATH/pkg/mod; set by package modload
|
var PkgMod string // $GOPATH/pkg/mod; set by package modload
|
||||||
|
|
||||||
const logFindingDelay = 1 * time.Second
|
|
||||||
|
|
||||||
func cacheDir(path string) (string, error) {
|
func cacheDir(path string) (string, error) {
|
||||||
if PkgMod == "" {
|
if PkgMod == "" {
|
||||||
return "", fmt.Errorf("internal error: modfetch.PkgMod not set")
|
return "", fmt.Errorf("internal error: modfetch.PkgMod not set")
|
||||||
|
|
@ -140,11 +137,6 @@ func (r *cachingRepo) Versions(prefix string) ([]string, error) {
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
c := r.cache.Do("versions:"+prefix, func() interface{} {
|
c := r.cache.Do("versions:"+prefix, func() interface{} {
|
||||||
logTimer := time.AfterFunc(logFindingDelay, func() {
|
|
||||||
fmt.Fprintf(os.Stderr, "go: finding versions for %s\n", r.path)
|
|
||||||
})
|
|
||||||
defer logTimer.Stop()
|
|
||||||
|
|
||||||
list, err := r.r.Versions(prefix)
|
list, err := r.r.Versions(prefix)
|
||||||
return cached{list, err}
|
return cached{list, err}
|
||||||
}).(cached)
|
}).(cached)
|
||||||
|
|
@ -167,11 +159,6 @@ func (r *cachingRepo) Stat(rev string) (*RevInfo, error) {
|
||||||
return cachedInfo{info, nil}
|
return cachedInfo{info, nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
logTimer := time.AfterFunc(logFindingDelay, func() {
|
|
||||||
fmt.Fprintf(os.Stderr, "go: finding %s %s\n", r.path, rev)
|
|
||||||
})
|
|
||||||
defer logTimer.Stop()
|
|
||||||
|
|
||||||
info, err = r.r.Stat(rev)
|
info, err = r.r.Stat(rev)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// If we resolved, say, 1234abcde to v0.0.0-20180604122334-1234abcdef78,
|
// If we resolved, say, 1234abcde to v0.0.0-20180604122334-1234abcdef78,
|
||||||
|
|
@ -199,11 +186,6 @@ func (r *cachingRepo) Stat(rev string) (*RevInfo, error) {
|
||||||
|
|
||||||
func (r *cachingRepo) Latest() (*RevInfo, error) {
|
func (r *cachingRepo) Latest() (*RevInfo, error) {
|
||||||
c := r.cache.Do("latest:", func() interface{} {
|
c := r.cache.Do("latest:", func() interface{} {
|
||||||
logTimer := time.AfterFunc(logFindingDelay, func() {
|
|
||||||
fmt.Fprintf(os.Stderr, "go: finding %s latest\n", r.path)
|
|
||||||
})
|
|
||||||
defer logTimer.Stop()
|
|
||||||
|
|
||||||
info, err := r.r.Latest()
|
info, err := r.r.Latest()
|
||||||
|
|
||||||
// Save info for likely future Stat call.
|
// Save info for likely future Stat call.
|
||||||
|
|
|
||||||
|
|
@ -682,8 +682,11 @@ func (r *gitRepo) RecentTag(rev, prefix, major string) (tag string, err error) {
|
||||||
|
|
||||||
semtag := line[len(prefix):]
|
semtag := line[len(prefix):]
|
||||||
// Consider only tags that are valid and complete (not just major.minor prefixes).
|
// Consider only tags that are valid and complete (not just major.minor prefixes).
|
||||||
if c := semver.Canonical(semtag); c != "" && strings.HasPrefix(semtag, c) && (major == "" || semver.Major(c) == major) {
|
// NOTE: Do not replace the call to semver.Compare with semver.Max.
|
||||||
highest = semver.Max(highest, semtag)
|
// We want to return the actual tag, not a canonicalized version of it,
|
||||||
|
// and semver.Max currently canonicalizes (see golang.org/issue/32700).
|
||||||
|
if c := semver.Canonical(semtag); c != "" && strings.HasPrefix(semtag, c) && (major == "" || semver.Major(c) == major) && semver.Compare(semtag, highest) > 0 {
|
||||||
|
highest = semtag
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -191,22 +191,6 @@ func (r *codeRepo) appendIncompatibleVersions(list, incompatible []string) ([]st
|
||||||
return list, nil
|
return list, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// We assume that if the latest release of any major version has a go.mod
|
|
||||||
// file, all subsequent major versions will also have go.mod files (and thus
|
|
||||||
// be ineligible for use as +incompatible versions).
|
|
||||||
// If we're wrong about a major version, users will still be able to 'go get'
|
|
||||||
// specific higher versions explicitly — they just won't affect 'latest' or
|
|
||||||
// appear in 'go list'.
|
|
||||||
//
|
|
||||||
// Conversely, we assume that if the latest release of any major version lacks
|
|
||||||
// a go.mod file, all versions also lack go.mod files. If we're wrong, we may
|
|
||||||
// include a +incompatible version that isn't really valid, but most
|
|
||||||
// operations won't try to use that version anyway.
|
|
||||||
//
|
|
||||||
// These optimizations bring
|
|
||||||
// 'go list -versions -m github.com/openshift/origin' down from 1m58s to 0m37s.
|
|
||||||
// That's still not great, but a substantial improvement.
|
|
||||||
|
|
||||||
versionHasGoMod := func(v string) (bool, error) {
|
versionHasGoMod := func(v string) (bool, error) {
|
||||||
_, err := r.code.ReadFile(v, "go.mod", codehost.MaxGoMod)
|
_, err := r.code.ReadFile(v, "go.mod", codehost.MaxGoMod)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
|
@ -241,32 +225,41 @@ func (r *codeRepo) appendIncompatibleVersions(list, incompatible []string) ([]st
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var lastMajor string
|
var (
|
||||||
|
lastMajor string
|
||||||
|
lastMajorHasGoMod bool
|
||||||
|
)
|
||||||
for i, v := range incompatible {
|
for i, v := range incompatible {
|
||||||
major := semver.Major(v)
|
major := semver.Major(v)
|
||||||
if major == lastMajor {
|
|
||||||
list = append(list, v+"+incompatible")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if major != lastMajor {
|
||||||
rem := incompatible[i:]
|
rem := incompatible[i:]
|
||||||
j := sort.Search(len(rem), func(j int) bool {
|
j := sort.Search(len(rem), func(j int) bool {
|
||||||
return semver.Major(rem[j]) != major
|
return semver.Major(rem[j]) != major
|
||||||
})
|
})
|
||||||
latestAtMajor := rem[j-1]
|
latestAtMajor := rem[j-1]
|
||||||
|
|
||||||
ok, err := versionHasGoMod(latestAtMajor)
|
var err error
|
||||||
|
lastMajor = major
|
||||||
|
lastMajorHasGoMod, err = versionHasGoMod(latestAtMajor)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if ok {
|
|
||||||
// This major version has a go.mod file, so it is not allowed as
|
|
||||||
// +incompatible. Subsequent major versions are likely to also have
|
|
||||||
// go.mod files, so stop here.
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lastMajor = major
|
if lastMajorHasGoMod {
|
||||||
|
// The latest release of this major version has a go.mod file, so it is
|
||||||
|
// not allowed as +incompatible. It would be confusing to include some
|
||||||
|
// minor versions of this major version as +incompatible but require
|
||||||
|
// semantic import versioning for others, so drop all +incompatible
|
||||||
|
// versions for this major version.
|
||||||
|
//
|
||||||
|
// If we're wrong about a minor version in the middle, users will still be
|
||||||
|
// able to 'go get' specific tags for that version explicitly — they just
|
||||||
|
// won't appear in 'go list' or as the results for queries with inequality
|
||||||
|
// bounds.
|
||||||
|
continue
|
||||||
|
}
|
||||||
list = append(list, v+"+incompatible")
|
list = append(list, v+"+incompatible")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -359,7 +352,7 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e
|
||||||
Path: r.modPath,
|
Path: r.modPath,
|
||||||
Err: &module.InvalidVersionError{
|
Err: &module.InvalidVersionError{
|
||||||
Version: info2.Version,
|
Version: info2.Version,
|
||||||
Err: notExistError(err.Error()),
|
Err: notExistError{err: err},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -708,7 +701,7 @@ func (r *codeRepo) findDir(version string) (rev, dir string, gomod []byte, err e
|
||||||
return "", "", nil, fmt.Errorf("reading %s/%s at revision %s: %v", r.pathPrefix, file1, rev, err1)
|
return "", "", nil, fmt.Errorf("reading %s/%s at revision %s: %v", r.pathPrefix, file1, rev, err1)
|
||||||
}
|
}
|
||||||
mpath1 := modfile.ModulePath(gomod1)
|
mpath1 := modfile.ModulePath(gomod1)
|
||||||
found1 := err1 == nil && isMajor(mpath1, r.pathMajor)
|
found1 := err1 == nil && (isMajor(mpath1, r.pathMajor) || r.canReplaceMismatchedVersionDueToBug(mpath1))
|
||||||
|
|
||||||
var file2 string
|
var file2 string
|
||||||
if r.pathMajor != "" && r.codeRoot != r.modPath && !strings.HasPrefix(r.pathMajor, ".") {
|
if r.pathMajor != "" && r.codeRoot != r.modPath && !strings.HasPrefix(r.pathMajor, ".") {
|
||||||
|
|
@ -817,6 +810,17 @@ func isMajor(mpath, pathMajor string) bool {
|
||||||
return pathMajor[1:] == mpathMajor[1:]
|
return pathMajor[1:] == mpathMajor[1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// canReplaceMismatchedVersionDueToBug reports whether versions of r
|
||||||
|
// could replace versions of mpath with otherwise-mismatched major versions
|
||||||
|
// due to a historical bug in the Go command (golang.org/issue/34254).
|
||||||
|
func (r *codeRepo) canReplaceMismatchedVersionDueToBug(mpath string) bool {
|
||||||
|
// The bug caused us to erroneously accept unversioned paths as replacements
|
||||||
|
// for versioned gopkg.in paths.
|
||||||
|
unversioned := r.pathMajor == ""
|
||||||
|
replacingGopkgIn := strings.HasPrefix(mpath, "gopkg.in/")
|
||||||
|
return unversioned && replacingGopkgIn
|
||||||
|
}
|
||||||
|
|
||||||
func (r *codeRepo) GoMod(version string) (data []byte, err error) {
|
func (r *codeRepo) GoMod(version string) (data []byte, err error) {
|
||||||
if version != module.CanonicalVersion(version) {
|
if version != module.CanonicalVersion(version) {
|
||||||
return nil, fmt.Errorf("version %s is not canonical", version)
|
return nil, fmt.Errorf("version %s is not canonical", version)
|
||||||
|
|
|
||||||
|
|
@ -250,9 +250,9 @@ func (lookupDisabledError) Error() string {
|
||||||
var errLookupDisabled error = lookupDisabledError{}
|
var errLookupDisabled error = lookupDisabledError{}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
errProxyOff = notExistError("module lookup disabled by GOPROXY=off")
|
errProxyOff = notExistErrorf("module lookup disabled by GOPROXY=off")
|
||||||
errNoproxy error = notExistError("disabled by GOPRIVATE/GONOPROXY")
|
errNoproxy error = notExistErrorf("disabled by GOPRIVATE/GONOPROXY")
|
||||||
errUseProxy error = notExistError("path does not match GOPRIVATE/GONOPROXY")
|
errUseProxy error = notExistErrorf("path does not match GOPRIVATE/GONOPROXY")
|
||||||
)
|
)
|
||||||
|
|
||||||
func lookupDirect(path string) (Repo, error) {
|
func lookupDirect(path string) (Repo, error) {
|
||||||
|
|
@ -264,7 +264,7 @@ func lookupDirect(path string) (Repo, error) {
|
||||||
rr, err := get.RepoRootForImportPath(path, get.PreferMod, security)
|
rr, err := get.RepoRootForImportPath(path, get.PreferMod, security)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// We don't know where to find code for a module with this path.
|
// We don't know where to find code for a module with this path.
|
||||||
return nil, notExistError(err.Error())
|
return nil, notExistError{err: err}
|
||||||
}
|
}
|
||||||
|
|
||||||
if rr.VCS == "mod" {
|
if rr.VCS == "mod" {
|
||||||
|
|
@ -408,11 +408,22 @@ func (l *loggingRepo) Zip(dst io.Writer, version string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// A notExistError is like os.ErrNotExist, but with a custom message
|
// A notExistError is like os.ErrNotExist, but with a custom message
|
||||||
type notExistError string
|
type notExistError struct {
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func notExistErrorf(format string, args ...interface{}) error {
|
||||||
|
return notExistError{fmt.Errorf(format, args...)}
|
||||||
|
}
|
||||||
|
|
||||||
func (e notExistError) Error() string {
|
func (e notExistError) Error() string {
|
||||||
return string(e)
|
return e.err.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (notExistError) Is(target error) bool {
|
func (notExistError) Is(target error) bool {
|
||||||
return target == os.ErrNotExist
|
return target == os.ErrNotExist
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e notExistError) Unwrap() error {
|
||||||
|
return e.err
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,7 @@ func moduleInfo(m module.Version, fromBuildList bool) *modinfo.ModulePublic {
|
||||||
}
|
}
|
||||||
if HasModRoot() {
|
if HasModRoot() {
|
||||||
info.Dir = ModRoot()
|
info.Dir = ModRoot()
|
||||||
info.GoMod = filepath.Join(info.Dir, "go.mod")
|
info.GoMod = ModFilePath()
|
||||||
if modFile.Go != nil {
|
if modFile.Go != nil {
|
||||||
info.GoVersion = modFile.Go.Version
|
info.GoVersion = modFile.Go.Version
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,14 +21,15 @@ which source files are used in a given build.
|
||||||
|
|
||||||
Module support
|
Module support
|
||||||
|
|
||||||
Go 1.13 includes support for Go modules. Module-aware mode is active by default
|
The go command includes support for Go modules. Module-aware mode is active
|
||||||
whenever a go.mod file is found in, or in a parent of, the current directory.
|
by default whenever a go.mod file is found in the current directory or in
|
||||||
|
any parent directory.
|
||||||
|
|
||||||
The quickest way to take advantage of module support is to check out your
|
The quickest way to take advantage of module support is to check out your
|
||||||
repository, create a go.mod file (described in the next section) there, and run
|
repository, create a go.mod file (described in the next section) there, and run
|
||||||
go commands from within that file tree.
|
go commands from within that file tree.
|
||||||
|
|
||||||
For more fine-grained control, Go 1.13 continues to respect
|
For more fine-grained control, the go command continues to respect
|
||||||
a temporary environment variable, GO111MODULE, which can be set to one
|
a temporary environment variable, GO111MODULE, which can be set to one
|
||||||
of three string values: off, on, or auto (the default).
|
of three string values: off, on, or auto (the default).
|
||||||
If GO111MODULE=on, then the go command requires the use of modules,
|
If GO111MODULE=on, then the go command requires the use of modules,
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ import (
|
||||||
"cmd/go/internal/modfetch"
|
"cmd/go/internal/modfetch"
|
||||||
"cmd/go/internal/par"
|
"cmd/go/internal/par"
|
||||||
"cmd/go/internal/search"
|
"cmd/go/internal/search"
|
||||||
"cmd/go/internal/str"
|
|
||||||
|
|
||||||
"golang.org/x/mod/module"
|
"golang.org/x/mod/module"
|
||||||
"golang.org/x/mod/semver"
|
"golang.org/x/mod/semver"
|
||||||
|
|
@ -40,7 +39,7 @@ var _ load.ImportPathError = (*ImportMissingError)(nil)
|
||||||
|
|
||||||
func (e *ImportMissingError) Error() string {
|
func (e *ImportMissingError) Error() string {
|
||||||
if e.Module.Path == "" {
|
if e.Module.Path == "" {
|
||||||
if str.HasPathPrefix(e.Path, "cmd") {
|
if search.IsStandardImportPath(e.Path) {
|
||||||
return fmt.Sprintf("package %s is not in GOROOT (%s)", e.Path, filepath.Join(cfg.GOROOT, "src", e.Path))
|
return fmt.Sprintf("package %s is not in GOROOT (%s)", e.Path, filepath.Join(cfg.GOROOT, "src", e.Path))
|
||||||
}
|
}
|
||||||
if e.QueryErr != nil {
|
if e.QueryErr != nil {
|
||||||
|
|
@ -118,8 +117,8 @@ func Import(path string) (m module.Version, dir string, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is the package in the standard library?
|
// Is the package in the standard library?
|
||||||
if search.IsStandardImportPath(path) &&
|
pathIsStd := search.IsStandardImportPath(path)
|
||||||
goroot.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, path) {
|
if pathIsStd && goroot.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, path) {
|
||||||
if targetInGorootSrc {
|
if targetInGorootSrc {
|
||||||
if dir, ok := dirInModule(path, targetPrefix, ModRoot(), true); ok {
|
if dir, ok := dirInModule(path, targetPrefix, ModRoot(), true); ok {
|
||||||
return Target, dir, nil
|
return Target, dir, nil
|
||||||
|
|
@ -128,9 +127,6 @@ func Import(path string) (m module.Version, dir string, err error) {
|
||||||
dir := filepath.Join(cfg.GOROOT, "src", path)
|
dir := filepath.Join(cfg.GOROOT, "src", path)
|
||||||
return module.Version{}, dir, nil
|
return module.Version{}, dir, nil
|
||||||
}
|
}
|
||||||
if str.HasPathPrefix(path, "cmd") {
|
|
||||||
return module.Version{}, "", &ImportMissingError{Path: path}
|
|
||||||
}
|
|
||||||
|
|
||||||
// -mod=vendor is special.
|
// -mod=vendor is special.
|
||||||
// Everything must be in the main module or the main module's vendor directory.
|
// Everything must be in the main module or the main module's vendor directory.
|
||||||
|
|
@ -184,7 +180,14 @@ func Import(path string) (m module.Version, dir string, err error) {
|
||||||
// Look up module containing the package, for addition to the build list.
|
// Look up module containing the package, for addition to the build list.
|
||||||
// Goal is to determine the module, download it to dir, and return m, dir, ErrMissing.
|
// Goal is to determine the module, download it to dir, and return m, dir, ErrMissing.
|
||||||
if cfg.BuildMod == "readonly" {
|
if cfg.BuildMod == "readonly" {
|
||||||
return module.Version{}, "", fmt.Errorf("import lookup disabled by -mod=%s", cfg.BuildMod)
|
var queryErr error
|
||||||
|
if !pathIsStd {
|
||||||
|
if cfg.BuildModReason == "" {
|
||||||
|
queryErr = fmt.Errorf("import lookup disabled by -mod=%s", cfg.BuildMod)
|
||||||
|
}
|
||||||
|
queryErr = fmt.Errorf("import lookup disabled by -mod=%s\n\t(%s)", cfg.BuildMod, cfg.BuildModReason)
|
||||||
|
}
|
||||||
|
return module.Version{}, "", &ImportMissingError{Path: path, QueryErr: queryErr}
|
||||||
}
|
}
|
||||||
if modRoot == "" && !allowMissingModuleImports {
|
if modRoot == "" && !allowMissingModuleImports {
|
||||||
return module.Version{}, "", &ImportMissingError{
|
return module.Version{}, "", &ImportMissingError{
|
||||||
|
|
@ -200,7 +203,12 @@ func Import(path string) (m module.Version, dir string, err error) {
|
||||||
latest := map[string]string{} // path -> version
|
latest := map[string]string{} // path -> version
|
||||||
for _, r := range modFile.Replace {
|
for _, r := range modFile.Replace {
|
||||||
if maybeInModule(path, r.Old.Path) {
|
if maybeInModule(path, r.Old.Path) {
|
||||||
latest[r.Old.Path] = semver.Max(r.Old.Version, latest[r.Old.Path])
|
// Don't use semver.Max here; need to preserve +incompatible suffix.
|
||||||
|
v := latest[r.Old.Path]
|
||||||
|
if semver.Compare(r.Old.Version, v) > 0 {
|
||||||
|
v = r.Old.Version
|
||||||
|
}
|
||||||
|
latest[r.Old.Path] = v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -250,6 +258,19 @@ func Import(path string) (m module.Version, dir string, err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if pathIsStd {
|
||||||
|
// This package isn't in the standard library, isn't in any module already
|
||||||
|
// in the build list, and isn't in any other module that the user has
|
||||||
|
// shimmed in via a "replace" directive.
|
||||||
|
// Moreover, the import path is reserved for the standard library, so
|
||||||
|
// QueryPackage cannot possibly find a module containing this package.
|
||||||
|
//
|
||||||
|
// Instead of trying QueryPackage, report an ImportMissingError immediately.
|
||||||
|
return module.Version{}, "", &ImportMissingError{Path: path}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(os.Stderr, "go: finding module for package %s\n", path)
|
||||||
|
|
||||||
candidates, err := QueryPackage(path, "latest", Allowed)
|
candidates, err := QueryPackage(path, "latest", Allowed)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, os.ErrNotExist) {
|
if errors.Is(err, os.ErrNotExist) {
|
||||||
|
|
|
||||||
|
|
@ -1320,6 +1320,21 @@ func fetch(mod module.Version) (dir string, isLocal bool, err error) {
|
||||||
if !filepath.IsAbs(dir) {
|
if !filepath.IsAbs(dir) {
|
||||||
dir = filepath.Join(ModRoot(), dir)
|
dir = filepath.Join(ModRoot(), dir)
|
||||||
}
|
}
|
||||||
|
// Ensure that the replacement directory actually exists:
|
||||||
|
// dirInModule does not report errors for missing modules,
|
||||||
|
// so if we don't report the error now, later failures will be
|
||||||
|
// very mysterious.
|
||||||
|
if _, err := os.Stat(dir); err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
// Semantically the module version itself “exists” — we just don't
|
||||||
|
// have its source code. Remove the equivalence to os.ErrNotExist,
|
||||||
|
// and make the message more concise while we're at it.
|
||||||
|
err = fmt.Errorf("replacement directory %s does not exist", r.Path)
|
||||||
|
} else {
|
||||||
|
err = fmt.Errorf("replacement directory %s: %w", r.Path, err)
|
||||||
|
}
|
||||||
|
return dir, true, module.VersionError(mod, err)
|
||||||
|
}
|
||||||
return dir, true, nil
|
return dir, true, nil
|
||||||
}
|
}
|
||||||
mod = r
|
mod = r
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ func queryProxy(proxy, path, query, current string, allowed func(module.Version)
|
||||||
if current != "" && !semver.IsValid(current) {
|
if current != "" && !semver.IsValid(current) {
|
||||||
return nil, fmt.Errorf("invalid previous version %q", current)
|
return nil, fmt.Errorf("invalid previous version %q", current)
|
||||||
}
|
}
|
||||||
if cfg.BuildMod != "" && cfg.BuildMod != "mod" {
|
if cfg.BuildMod == "vendor" {
|
||||||
return nil, errQueryDisabled
|
return nil, errQueryDisabled
|
||||||
}
|
}
|
||||||
if allowed == nil {
|
if allowed == nil {
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ var queryTests = []struct {
|
||||||
git add go.mod
|
git add go.mod
|
||||||
git commit -m v1 go.mod
|
git commit -m v1 go.mod
|
||||||
git tag start
|
git tag start
|
||||||
for i in v0.0.0-pre1 v0.0.0 v0.0.1 v0.0.2 v0.0.3 v0.1.0 v0.1.1 v0.1.2 v0.3.0 v1.0.0 v1.1.0 v1.9.0 v1.9.9 v1.9.10-pre1 v1.9.10-pre2+metadata; do
|
for i in v0.0.0-pre1 v0.0.0 v0.0.1 v0.0.2 v0.0.3 v0.1.0 v0.1.1 v0.1.2 v0.3.0 v1.0.0 v1.1.0 v1.9.0 v1.9.9 v1.9.10-pre1 v1.9.10-pre2+metadata unversioned; do
|
||||||
echo before $i >status
|
echo before $i >status
|
||||||
git add status
|
git add status
|
||||||
git commit -m "before $i" status
|
git commit -m "before $i" status
|
||||||
|
|
@ -107,6 +107,7 @@ var queryTests = []struct {
|
||||||
{path: queryRepo, query: "v0.2", err: `no matching versions for query "v0.2"`},
|
{path: queryRepo, query: "v0.2", err: `no matching versions for query "v0.2"`},
|
||||||
{path: queryRepo, query: "v0.0", vers: "v0.0.3"},
|
{path: queryRepo, query: "v0.0", vers: "v0.0.3"},
|
||||||
{path: queryRepo, query: "v1.9.10-pre2+metadata", vers: "v1.9.10-pre2.0.20190513201126-42abcb6df8ee"},
|
{path: queryRepo, query: "v1.9.10-pre2+metadata", vers: "v1.9.10-pre2.0.20190513201126-42abcb6df8ee"},
|
||||||
|
{path: queryRepo, query: "ed5ffdaa", vers: "v1.9.10-pre2.0.20191220134614-ed5ffdaa1f5e"},
|
||||||
|
|
||||||
// golang.org/issue/29262: The major version for for a module without a suffix
|
// golang.org/issue/29262: The major version for for a module without a suffix
|
||||||
// should be based on the most recent tag (v1 as appropriate, not v0
|
// should be based on the most recent tag (v1 as appropriate, not v0
|
||||||
|
|
@ -162,10 +163,14 @@ var queryTests = []struct {
|
||||||
{path: queryRepoV2, query: "v2.6.0-pre1", vers: "v2.6.0-pre1"},
|
{path: queryRepoV2, query: "v2.6.0-pre1", vers: "v2.6.0-pre1"},
|
||||||
{path: queryRepoV2, query: "latest", vers: "v2.5.5"},
|
{path: queryRepoV2, query: "latest", vers: "v2.5.5"},
|
||||||
|
|
||||||
// e0cf3de987e6 is the latest commit on the master branch, and it's actually
|
// Commit e0cf3de987e6 is actually v1.19.10-pre1, not anything resembling v3,
|
||||||
// v1.19.10-pre1, not anything resembling v3: attempting to query it as such
|
// and it has a go.mod file with a non-v3 module path. Attempting to query it
|
||||||
// should fail.
|
// as the v3 module should fail.
|
||||||
{path: queryRepoV3, query: "e0cf3de987e6", err: `vcs-test.golang.org/git/querytest.git/v3@v3.0.0-20180704024501-e0cf3de987e6: invalid version: go.mod has non-.../v3 module path "vcs-test.golang.org/git/querytest.git" (and .../v3/go.mod does not exist) at revision e0cf3de987e6`},
|
{path: queryRepoV3, query: "e0cf3de987e6", err: `vcs-test.golang.org/git/querytest.git/v3@v3.0.0-20180704024501-e0cf3de987e6: invalid version: go.mod has non-.../v3 module path "vcs-test.golang.org/git/querytest.git" (and .../v3/go.mod does not exist) at revision e0cf3de987e6`},
|
||||||
|
|
||||||
|
// The querytest repo does not have any commits tagged with major version 3,
|
||||||
|
// and the latest commit in the repo has a go.mod file specifying a non-v3 path.
|
||||||
|
// That should prevent us from resolving any version for the /v3 path.
|
||||||
{path: queryRepoV3, query: "latest", err: `no matching versions for query "latest"`},
|
{path: queryRepoV3, query: "latest", err: `no matching versions for query "latest"`},
|
||||||
|
|
||||||
{path: emptyRepo, query: "latest", vers: "v0.0.0-20180704023549-7bb914627242"},
|
{path: emptyRepo, query: "latest", vers: "v0.0.0-20180704023549-7bb914627242"},
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,8 @@ func init() {
|
||||||
// go test fmt -custom-flag-for-fmt-test
|
// go test fmt -custom-flag-for-fmt-test
|
||||||
// go test -x math
|
// go test -x math
|
||||||
func testFlags(usage func(), args []string) (packageNames, passToTest []string) {
|
func testFlags(usage func(), args []string) (packageNames, passToTest []string) {
|
||||||
args = str.StringList(cmdflag.FindGOFLAGS(testFlagDefn), args)
|
goflags := cmdflag.FindGOFLAGS(testFlagDefn)
|
||||||
|
args = str.StringList(goflags, args)
|
||||||
inPkg := false
|
inPkg := false
|
||||||
var explicitArgs []string
|
var explicitArgs []string
|
||||||
for i := 0; i < len(args); i++ {
|
for i := 0; i < len(args); i++ {
|
||||||
|
|
@ -127,6 +128,9 @@ func testFlags(usage func(), args []string) (packageNames, passToTest []string)
|
||||||
passToTest = append(passToTest, args[i])
|
passToTest = append(passToTest, args[i])
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if i < len(goflags) {
|
||||||
|
f.Present = false // Not actually present on the command line.
|
||||||
|
}
|
||||||
if f.Value != nil {
|
if f.Value != nil {
|
||||||
if err := f.Value.Set(value); err != nil {
|
if err := f.Value.Set(value); err != nil {
|
||||||
base.Fatalf("invalid flag argument for -%s: %v", f.Name, err)
|
base.Fatalf("invalid flag argument for -%s: %v", f.Name, err)
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ func runVet(cmd *base.Command, args []string) {
|
||||||
|
|
||||||
work.BuildInit()
|
work.BuildInit()
|
||||||
work.VetFlags = vetFlags
|
work.VetFlags = vetFlags
|
||||||
|
work.VetExplicit = true
|
||||||
if vetTool != "" {
|
if vetTool != "" {
|
||||||
var err error
|
var err error
|
||||||
work.VetTool, err = filepath.Abs(vetTool)
|
work.VetTool, err = filepath.Abs(vetTool)
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,8 @@ func vetFlags(usage func(), args []string) (passToVet, packageNames []string) {
|
||||||
})
|
})
|
||||||
|
|
||||||
// Process args.
|
// Process args.
|
||||||
args = str.StringList(cmdflag.FindGOFLAGS(vetFlagDefn), args)
|
goflags := cmdflag.FindGOFLAGS(vetFlagDefn)
|
||||||
|
args = str.StringList(goflags, args)
|
||||||
for i := 0; i < len(args); i++ {
|
for i := 0; i < len(args); i++ {
|
||||||
if !strings.HasPrefix(args[i], "-") {
|
if !strings.HasPrefix(args[i], "-") {
|
||||||
return args[:i], args[i:]
|
return args[:i], args[i:]
|
||||||
|
|
@ -139,6 +140,9 @@ func vetFlags(usage func(), args []string) (passToVet, packageNames []string) {
|
||||||
base.SetExitStatus(2)
|
base.SetExitStatus(2)
|
||||||
base.Exit()
|
base.Exit()
|
||||||
}
|
}
|
||||||
|
if i < len(goflags) {
|
||||||
|
f.Present = false // Not actually present on the command line.
|
||||||
|
}
|
||||||
if f.Value != nil {
|
if f.Value != nil {
|
||||||
if err := f.Value.Set(value); err != nil {
|
if err := f.Value.Set(value); err != nil {
|
||||||
base.Fatalf("invalid flag argument for -%s: %v", f.Name, err)
|
base.Fatalf("invalid flag argument for -%s: %v", f.Name, err)
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@ func TestGetFileURL(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
defer os.Remove(f.Name())
|
||||||
|
|
||||||
if _, err := f.WriteString(content); err != nil {
|
if _, err := f.WriteString(content); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -291,7 +291,7 @@ func (b *Builder) Init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := CheckGOOSARCHPair(cfg.Goos, cfg.Goarch); err != nil {
|
if err := CheckGOOSARCHPair(cfg.Goos, cfg.Goarch); err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "cmd/go: %v", err)
|
fmt.Fprintf(os.Stderr, "cmd/go: %v\n", err)
|
||||||
base.SetExitStatus(2)
|
base.SetExitStatus(2)
|
||||||
base.Exit()
|
base.Exit()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1036,7 +1036,7 @@ func (b *Builder) vet(a *Action) error {
|
||||||
// There's too much unsafe.Pointer code
|
// There's too much unsafe.Pointer code
|
||||||
// that vet doesn't like in low-level packages
|
// that vet doesn't like in low-level packages
|
||||||
// like runtime, sync, and reflect.
|
// like runtime, sync, and reflect.
|
||||||
vetFlags = append(vetFlags, string("-unsafeptr=false"))
|
vetFlags = []string{"-unsafeptr=false"}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: We could decide that vet should compute export data for
|
// Note: We could decide that vet should compute export data for
|
||||||
|
|
@ -1774,6 +1774,11 @@ func (b *Builder) fmtcmd(dir string, format string, args ...interface{}) string
|
||||||
}
|
}
|
||||||
if b.WorkDir != "" {
|
if b.WorkDir != "" {
|
||||||
cmd = strings.ReplaceAll(cmd, b.WorkDir, "$WORK")
|
cmd = strings.ReplaceAll(cmd, b.WorkDir, "$WORK")
|
||||||
|
escaped := strconv.Quote(b.WorkDir)
|
||||||
|
escaped = escaped[1 : len(escaped)-1] // strip quote characters
|
||||||
|
if escaped != b.WorkDir {
|
||||||
|
cmd = strings.ReplaceAll(cmd, escaped, "$WORK")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -227,8 +227,8 @@ func (a *Action) trimpath() string {
|
||||||
// For "go build -trimpath", rewrite package source directory
|
// For "go build -trimpath", rewrite package source directory
|
||||||
// to a file system-independent path (just the import path).
|
// to a file system-independent path (just the import path).
|
||||||
if cfg.BuildTrimpath {
|
if cfg.BuildTrimpath {
|
||||||
if m := a.Package.Module; m != nil {
|
if m := a.Package.Module; m != nil && m.Version != "" {
|
||||||
rewrite += ";" + m.Dir + "=>" + m.Path + "@" + m.Version
|
rewrite += ";" + a.Package.Dir + "=>" + m.Path + "@" + m.Version + strings.TrimPrefix(a.Package.ImportPath, m.Path)
|
||||||
} else {
|
} else {
|
||||||
rewrite += ";" + a.Package.Dir + "=>" + a.Package.ImportPath
|
rewrite += ";" + a.Package.Dir + "=>" + a.Package.ImportPath
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,8 @@ var goodCompilerFlags = [][]string{
|
||||||
{"-Osmall"},
|
{"-Osmall"},
|
||||||
{"-W"},
|
{"-W"},
|
||||||
{"-Wall"},
|
{"-Wall"},
|
||||||
|
{"-Wp,-Dfoo=bar"},
|
||||||
|
{"-Wp,-Ufoo"},
|
||||||
{"-fobjc-arc"},
|
{"-fobjc-arc"},
|
||||||
{"-fno-objc-arc"},
|
{"-fno-objc-arc"},
|
||||||
{"-fomit-frame-pointer"},
|
{"-fomit-frame-pointer"},
|
||||||
|
|
|
||||||
1
src/cmd/go/testdata/badmod/go.mod
vendored
1
src/cmd/go/testdata/badmod/go.mod
vendored
|
|
@ -1 +0,0 @@
|
||||||
module m
|
|
||||||
4
src/cmd/go/testdata/badmod/x.go
vendored
4
src/cmd/go/testdata/badmod/x.go
vendored
|
|
@ -1,4 +0,0 @@
|
||||||
package x
|
|
||||||
|
|
||||||
import _ "appengine"
|
|
||||||
import _ "nonexistent.rsc.io" // domain does not exist
|
|
||||||
3
src/cmd/go/testdata/importcom/bad.go
vendored
3
src/cmd/go/testdata/importcom/bad.go
vendored
|
|
@ -1,3 +0,0 @@
|
||||||
package p
|
|
||||||
|
|
||||||
import "bad"
|
|
||||||
3
src/cmd/go/testdata/importcom/conflict.go
vendored
3
src/cmd/go/testdata/importcom/conflict.go
vendored
|
|
@ -1,3 +0,0 @@
|
||||||
package p
|
|
||||||
|
|
||||||
import "conflict"
|
|
||||||
1
src/cmd/go/testdata/importcom/src/bad/bad.go
vendored
1
src/cmd/go/testdata/importcom/src/bad/bad.go
vendored
|
|
@ -1 +0,0 @@
|
||||||
package bad // import
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
package conflict // import "a"
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
package conflict /* import "b" */
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
package x // import "works/x"
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
package x // important! not an import comment
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
package x // import "my/x"
|
|
||||||
3
src/cmd/go/testdata/importcom/works.go
vendored
3
src/cmd/go/testdata/importcom/works.go
vendored
|
|
@ -1,3 +0,0 @@
|
||||||
package p
|
|
||||||
|
|
||||||
import _ "works/x"
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue