[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:
Cherry Zhang 2020-01-31 14:45:52 -05:00
commit ee04d45b8f
452 changed files with 18116 additions and 11162 deletions

View file

@ -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?

View file

@ -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
View 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

View file

@ -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

View file

@ -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

View file

@ -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>

View file

@ -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&rsquo; 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&rsquo;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 projects 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 Stewards 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&rsquo;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>Dont be destructive or inflammatory.
<li>If you encounter an issue, please mail <a href="mailto:conduct@golang.org">conduct@golang.org</a>.
</ul>

View file

@ -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>

View file

@ -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 cant
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 := &lt;-ch
if closed(ch) {
// channel is closed
}
</pre>
<p>should now be written as:</p>
<pre>
v, ok := &lt;-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 &ldquo;short&rdquo; 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>

View file

@ -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

View file

@ -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>//&nbsp;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&#39;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>

View file

@ -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 ";" } ")" ) .
@ -2413,7 +2413,7 @@ operand only on the left-hand side of an <a href="#Assignments">assignment</a>.
Operand = Literal | OperandName | "(" Expression ")" . Operand = Literal | OperandName | "(" Expression ")" .
Literal = BasicLit | CompositeLit | FunctionLit . Literal = BasicLit | CompositeLit | FunctionLit .
BasicLit = int_lit | float_lit | imaginary_lit | rune_lit | string_lit . BasicLit = int_lit | float_lit | imaginary_lit | rune_lit | string_lit .
OperandName = identifier | QualifiedIdent. OperandName = identifier | QualifiedIdent .
</pre> </pre>
<h3 id="Qualified_identifiers">Qualified identifiers</h3> <h3 id="Qualified_identifiers">Qualified identifiers</h3>
@ -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 := &amp;[]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; &amp;s1[2] == &amp;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; &amp;s2[1] == &amp;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>
@ -5279,7 +5279,7 @@ for i, s := range a {
} }
var key string var key string
var val interface {} // element type of m is assignable to val var val interface{} // element type of m is assignable to val
m := map[string]int{"mon":0, "tue":1, "wed":2, "thu":3, "fri":4, "sat":5, "sun":6} m := map[string]int{"mon":0, "tue":1, "wed":2, "thu":3, "fri":4, "sat":5, "sun":6}
for key, val = range m { for key, val = range m {
h(key, val) h(key, val)

View file

@ -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>&lt;tag&gt;</code>), because you must keep your (to checkout the latest <code>&lt;tag&gt;</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>

View file

@ -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 hasnt been tampered with)
before adding new `go.sum` lines to the main modules `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.

View file

@ -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>

View file

@ -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>

View file

@ -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

View file

@ -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

View file

@ -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
}

View file

@ -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 {

View file

@ -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 (

View file

@ -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()

View file

@ -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()

View file

@ -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()

View file

@ -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,

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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{
New: func() interface{} {
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 { if t == nil {
return "<T>" 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 {
b.WriteByte('(')
tconv2(b, t.Elem(), 0, mode, visited)
b.WriteByte(')')
} else {
tconv2(b, t.Elem(), 0, mode, visited)
}
} }
if t.Elem() != nil && t.Elem().IsChan() && t.Elem().Sym == nil && t.Elem().ChanDir() == types.Crecv {
return "chan (" + tmodeString(t.Elem(), mode, depth) + ")"
}
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.
b.WriteString(mode.Sprintf("%v <%v>", t.Etype, t.Sym))
} }
// Don't know how to handle - fall back to detailed prints.
return 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) }

View file

@ -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

View file

@ -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))

View file

@ -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],

View file

@ -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

View file

@ -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
} }

View file

@ -321,12 +321,14 @@ func Enabled() bool {
// byPos sorts diagnostics by source position. // byPos sorts diagnostics by source position.
type byPos struct { type byPos struct {
ctxt *obj.Link ctxt *obj.Link
a []LoggedOpt a []LoggedOpt
} }
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 {
func (x byPos) Swap(i, j int) { x.a[i], x.a[j] = x.a[j], x.a[i] } 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 writerForLSP(subdirpath, file string) io.WriteCloser { func writerForLSP(subdirpath, file string) io.WriteCloser {
basename := file basename := file
@ -367,7 +369,7 @@ func uriIfy(f string) DocumentURI {
// Return filename, replacing a first occurrence of $GOROOT with the // Return filename, replacing a first occurrence of $GOROOT with the
// actual value of the GOROOT (because LSP does not speak "$GOROOT"). // actual value of the GOROOT (because LSP does not speak "$GOROOT").
func uprootedPath(filename string) string { func uprootedPath(filename string) string {
if ! strings.HasPrefix(filename, "$GOROOT/") { if !strings.HasPrefix(filename, "$GOROOT/") {
return filename return filename
} }
return objabi.GOROOT + filename[len("$GOROOT"):] return objabi.GOROOT + filename[len("$GOROOT"):]
@ -379,7 +381,7 @@ func FlushLoggedOpts(ctxt *obj.Link, slashPkgPath string) {
return return
} }
sort.Stable(byPos{ctxt,loggedOpts}) // Stable is necessary to preserve the per-function order, which is repeatable. sort.Stable(byPos{ctxt, loggedOpts}) // Stable is necessary to preserve the per-function order, which is repeatable.
switch Format { switch Format {
case Json0: // LSP 3.15 case Json0: // LSP 3.15

View 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
}

View 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
}

View 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
}

View 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())
}
}

View file

@ -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

View file

@ -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 {

View file

@ -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
} }
} }

View file

@ -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) {

View file

@ -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) ->

View 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

View 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
})
}

View file

@ -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

View file

@ -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

View file

@ -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)

File diff suppressed because it is too large Load diff

View file

@ -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:

View file

@ -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 {

View file

@ -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) {

View file

@ -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
View file

@ -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

View file

@ -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",

View file

@ -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":

View file

@ -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")

View file

@ -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
) )

View file

@ -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=

View file

@ -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,

View file

@ -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)

View file

@ -178,7 +178,9 @@ func runClean(cmd *base.Command, args []string) {
} }
} }
if err != nil { if err != nil {
base.Errorf("go clean -testcache: %v", err) if _, statErr := os.Stat(dir); !os.IsNotExist(statErr) {
base.Errorf("go clean -testcache: %v", err)
}
} }
} }
} }

View file

@ -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
} }

View file

@ -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.
`, `,

View file

@ -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")
} }
} }
} }

View file

@ -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,17 +1520,30 @@ 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"
@ -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, " ")))

View file

@ -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:

View file

@ -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)
} }

View file

@ -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.

View file

@ -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
} }
} }

View file

@ -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") if major != lastMajor {
rem := incompatible[i:]
j := sort.Search(len(rem), func(j int) bool {
return semver.Major(rem[j]) != major
})
latestAtMajor := rem[j-1]
var err error
lastMajor = major
lastMajorHasGoMod, err = versionHasGoMod(latestAtMajor)
if err != nil {
return nil, err
}
}
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 continue
} }
rem := incompatible[i:]
j := sort.Search(len(rem), func(j int) bool {
return semver.Major(rem[j]) != major
})
latestAtMajor := rem[j-1]
ok, err := versionHasGoMod(latestAtMajor)
if err != nil {
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
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)

View file

@ -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
}

View file

@ -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
} }

View file

@ -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,

View file

@ -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) {

View file

@ -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

View file

@ -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 {

View file

@ -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"},

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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)
} }

View file

@ -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()
} }

View file

@ -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
} }

View file

@ -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
} }

View file

@ -52,7 +52,7 @@ var validCompilerFlags = []*lazyregexp.Regexp{
re(`-W([^@,]+)`), // -Wall but not -Wa,-foo. re(`-W([^@,]+)`), // -Wall but not -Wa,-foo.
re(`-Wa,-mbig-obj`), re(`-Wa,-mbig-obj`),
re(`-Wp,-D([A-Za-z_].*)`), re(`-Wp,-D([A-Za-z_].*)`),
re(`-Wp, -U([A-Za-z_]*)`), re(`-Wp,-U([A-Za-z_]*)`),
re(`-ansi`), re(`-ansi`),
re(`-f(no-)?asynchronous-unwind-tables`), re(`-f(no-)?asynchronous-unwind-tables`),
re(`-f(no-)?blocks`), re(`-f(no-)?blocks`),

View file

@ -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"},

View file

@ -1 +0,0 @@
module m

View file

@ -1,4 +0,0 @@
package x
import _ "appengine"
import _ "nonexistent.rsc.io" // domain does not exist

View file

@ -1,3 +0,0 @@
package p
import "bad"

View file

@ -1,3 +0,0 @@
package p
import "conflict"

View file

@ -1 +0,0 @@
package bad // import

View file

@ -1 +0,0 @@
package conflict // import "a"

View file

@ -1 +0,0 @@
package conflict /* import "b" */

View file

@ -1 +0,0 @@
package x // import "works/x"

View file

@ -1 +0,0 @@
package x // important! not an import comment

View file

@ -1 +0,0 @@
package x // import "my/x"

Some files were not shown because too many files have changed in this diff Show more