mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.link] all: merge branch 'master' into dev.link
It has been a while we have not done this.
Merge conflict resolution:
- deleted/rewritten code modified on master
- CL 214286, ported in CL 217317
(cmd/internal/obj/objfile.go)
- CL 210678, it already includes a fix to new code
(cmd/link/internal/ld/deadcode.go)
- CL 209317, applied in this CL
(cmd/link/internal/loadelf/ldelf.go)
Change-Id: Ie927ea6a1d69ce49e8d03e56148cb2725e377876
This commit is contained in:
commit
ee04d45b8f
452 changed files with 18116 additions and 11162 deletions
6
.github/ISSUE_TEMPLATE
vendored
6
.github/ISSUE_TEMPLATE
vendored
|
|
@ -1,4 +1,7 @@
|
|||
<!-- Please answer these questions before submitting your issue. Thanks! -->
|
||||
<!--
|
||||
Please answer these questions before submitting your issue. Thanks!
|
||||
For questions please use one of our forums: https://github.com/golang/go/wiki/Questions
|
||||
-->
|
||||
|
||||
### What version of Go are you using (`go version`)?
|
||||
|
||||
|
|
@ -33,4 +36,3 @@ A link on play.golang.org is best.
|
|||
|
||||
|
||||
### What did you see instead?
|
||||
|
||||
|
|
|
|||
126
CONTRIBUTORS
126
CONTRIBUTORS
|
|
@ -25,6 +25,7 @@
|
|||
# Please keep the list sorted.
|
||||
|
||||
Aamir Khan <syst3m.w0rm@gmail.com>
|
||||
Aaron Beitch <aaronb@arista.com>
|
||||
Aaron Cannon <cannona@fireantproductions.com>
|
||||
Aaron France <aaron.l.france@gmail.com>
|
||||
Aaron Jacobs <jacobsa@google.com>
|
||||
|
|
@ -44,10 +45,12 @@ Adam Kisala <adam.kisala@gmail.com>
|
|||
Adam Langley <agl@golang.org>
|
||||
Adam Medzinski <adam.medzinski@gmail.com>
|
||||
Adam Shannon <adamkshannon@gmail.com>
|
||||
Adam Shelton <aashelt90@gmail.com>
|
||||
Adam Sindelar <adamsh@google.com>
|
||||
Adam Thomason <athomason@gmail.com>
|
||||
Adam Woodbeck <adam@woodbeck.net>
|
||||
Adarsh Ravichandran <adarshravichandran91@gmail.com>
|
||||
Aditya Harindar <aditya.harindar@gmail.com>
|
||||
Aditya Mukerjee <dev@chimeracoder.net>
|
||||
Adrian Hesketh <adrianhesketh@hushmail.com>
|
||||
Adrian Nos <nos.adrian@gmail.com>
|
||||
|
|
@ -81,6 +84,7 @@ Albert Yu <yukinying@gmail.com>
|
|||
Alberto Bertogli <albertito@blitiri.com.ar>
|
||||
Alberto Donizetti <alb.donizetti@gmail.com>
|
||||
Alberto García Hierro <alberto@garciahierro.com> <alberto.garcia.hierro@gmail.com>
|
||||
Alec Benzer <alec.benzer@gmail.com>
|
||||
Aleksa Sarai <cyphar@cyphar.com>
|
||||
Aleksandar Dezelin <dezelin@gmail.com>
|
||||
Aleksandr Lukinykh <a.lukinykh@xsolla.com>
|
||||
|
|
@ -92,7 +96,10 @@ Alex A Skinner <alex@lx.lc>
|
|||
Alex Brainman <alex.brainman@gmail.com>
|
||||
Alex Bramley <abramley@google.com>
|
||||
Alex Browne <stephenalexbrowne@gmail.com>
|
||||
Alex Buchanan <buchanae@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 Kohler <alexjohnkohler@gmail.com>
|
||||
Alex Myasoedov <msoedov@gmail.com>
|
||||
|
|
@ -101,6 +108,7 @@ Alex Schroeder <alex@gnu.org>
|
|||
Alex Sergeyev <abc@alexsergeyev.com>
|
||||
Alex Tokarev <aleksator@gmail.com>
|
||||
Alex Vaghin <crhyme@google.com>
|
||||
Alex Zhirov <azhirov@google.com>
|
||||
Alexander Demakin <alexander.demakin@gmail.com>
|
||||
Alexander Döring <email@alexd.ch>
|
||||
Alexander F Rødseth <alexander.rodseth@appeartv.com>
|
||||
|
|
@ -121,6 +129,7 @@ Alexander Surma <surma@surmair.de>
|
|||
Alexander Zhavnerchik <alex.vizor@gmail.com>
|
||||
Alexander Zillion <alex@alexzillion.com>
|
||||
Alexander Zolotov <goldifit@gmail.com>
|
||||
Alexandr Mayorskiy <a.mayorskiy@corp.mail.ru>
|
||||
Alexandre Cesaro <alexandre.cesaro@gmail.com>
|
||||
Alexandre Fiori <fiorix@gmail.com>
|
||||
Alexandre Maari <draeron@gmail.com>
|
||||
|
|
@ -147,6 +156,7 @@ Aman Gupta <aman@tmm1.net>
|
|||
Amir Mohammad Saied <amir@gluegadget.com>
|
||||
Amr Mohammed <merodiro@gmail.com>
|
||||
Amrut Joshi <amrut.joshi@gmail.com>
|
||||
An Xiao <hac@zju.edu.cn>
|
||||
Anand K. Mistry <anand@mistry.ninja>
|
||||
Anders Pearson <anders@columbia.edu>
|
||||
Anderson Queiroz <contato@andersonq.eti.br>
|
||||
|
|
@ -157,6 +167,7 @@ Andrea Spadaccini <spadaccio@google.com>
|
|||
Andreas Auernhammer <aead@mail.de>
|
||||
Andreas Jellinghaus <andreas@ionisiert.de> <anj@google.com>
|
||||
Andreas Litt <andreas.litt@gmail.com>
|
||||
Andrei Enshin <b1os@bk.ru>
|
||||
Andrei Gherzan <andrei@resin.io>
|
||||
Andrei Korzhevskii <a.korzhevskiy@gmail.com>
|
||||
Andrei Matei <andrei@cockroachlabs.com>
|
||||
|
|
@ -177,12 +188,14 @@ Andrew Gerrand <adg@golang.org>
|
|||
Andrew Harding <andrew@spacemonkey.com>
|
||||
Andrew Jackura <ajackura@google.com>
|
||||
Andrew Lutomirski <andy@luto.us>
|
||||
Andrew Medvedev <andrew.y.medvedev@gmail.com>
|
||||
Andrew Pilloud <andrewpilloud@igneoussystems.com>
|
||||
Andrew Pogrebnoy <absourd.noise@gmail.com>
|
||||
Andrew Poydence <apoydence@pivotal.io>
|
||||
Andrew Pritchard <awpritchard@gmail.com>
|
||||
Andrew Radev <andrey.radev@gmail.com>
|
||||
Andrew Skiba <skibaa@gmail.com>
|
||||
Andrew Stormont <astormont@racktopsystems.com>
|
||||
Andrew Stribblehill <ads@wompom.org>
|
||||
Andrew Szeto <andrew@jabagawee.com>
|
||||
Andrew Todd <andrew.todd@wework.com>
|
||||
|
|
@ -225,12 +238,14 @@ Anton Gyllenberg <anton@iki.fi>
|
|||
Antonin Amand <antonin.amand@gmail.com>
|
||||
Antonio Antelo <aantelov87@gmail.com>
|
||||
Antonio Bibiano <antbbn@gmail.com>
|
||||
Antonio Huete Jimenez <tuxillo@quantumachine.net>
|
||||
Antonio Murdaca <runcom@redhat.com>
|
||||
Antonio Troina <thoeni@gmail.com>
|
||||
Aofei Sheng <aofei@aofeisheng.com>
|
||||
Apisak Darakananda <pongad@gmail.com>
|
||||
Aram Hăvărneanu <aram@mgk.ro>
|
||||
Arash Bina <arash@arash.io>
|
||||
Arda Güçlü <ardaguclu@gmail.com>
|
||||
Areski Belaid <areski@gmail.com>
|
||||
Ariel Mashraki <ariel@mashraki.co.il>
|
||||
Arkadi Pyuro <arkadi@google.com>
|
||||
|
|
@ -239,6 +254,7 @@ Arnaud Ysmal <arnaud.ysmal@gmail.com>
|
|||
Arne Hormann <arnehormann@gmail.com>
|
||||
Arnout Engelen <arnout@bzzt.net>
|
||||
Aron Nopanen <aron.nopanen@gmail.com>
|
||||
Artem Alekseev <artem.alekseev@intel.com>
|
||||
Artem Kolin <artemkaxboy@gmail.com>
|
||||
Arthur Fabre <arthur@arthurfabre.com>
|
||||
Arthur Khashaev <arthur@khashaev.ru>
|
||||
|
|
@ -258,6 +274,7 @@ Avi Flax <avi@timehop.com>
|
|||
awaw fumin <awawfumin@gmail.com>
|
||||
Awn Umar <awn@cryptolosophy.io>
|
||||
Axel Wagner <axel.wagner.hh@googlemail.com>
|
||||
Ayan George <ayan@ayan.net>
|
||||
Ayanamist Yang <ayanamist@gmail.com>
|
||||
Aymerick Jéhanne <aymerick@jehanne.org>
|
||||
Azat Kaumov <kaumov.a.r@gmail.com>
|
||||
|
|
@ -265,6 +282,7 @@ Baiju Muthukadan <baiju.m.mail@gmail.com>
|
|||
Balaram Makam <bmakam.qdt@qualcommdatacenter.com>
|
||||
Balazs Lecz <leczb@google.com>
|
||||
Baokun Lee <nototon@gmail.com>
|
||||
Barnaby Keene <accounts@southcla.ws>
|
||||
Bartosz Grzybowski <melkorm@gmail.com>
|
||||
Bartosz Oler <brtsz@google.com>
|
||||
Bastian Ike <bastian.ike@gmail.com>
|
||||
|
|
@ -279,12 +297,14 @@ Ben Lynn <benlynn@gmail.com>
|
|||
Ben Olive <sionide21@gmail.com>
|
||||
Ben Schwartz <bemasc@google.com>
|
||||
Ben Shi <powerman1st@163.com>
|
||||
Ben Toews <mastahyeti@gmail.com>
|
||||
Benjamin Black <b@b3k.us>
|
||||
Benjamin Cable <cable.benjamin@gmail.com>
|
||||
Benjamin Hsieh <tanookiben@users.noreply.github.com>
|
||||
Benjamin Peterson <benjamin@python.org>
|
||||
Benjamin Prosnitz <bprosnitz@google.com>
|
||||
Benjamin Wester <bwester@squareup.com>
|
||||
Benjamin Wuethrich <benjamin.wuethrich@gmail.com>
|
||||
Benny Siegert <bsiegert@gmail.com>
|
||||
Benoit Sigoure <tsunanet@gmail.com>
|
||||
Berengar Lehr <Berengar.Lehr@gmx.de>
|
||||
|
|
@ -323,6 +343,7 @@ Brady Catherman <brady@gmail.com>
|
|||
Brady Sullivan <brady@bsull.com>
|
||||
Brandon Bennett <bbennett@fb.com>
|
||||
Brandon Gilmore <varz@google.com>
|
||||
Brandon Philips <brandon@ifup.org>
|
||||
Brandon Ryan <bjryan19@gmail.com>
|
||||
Brendan Daniel Tracey <tracey.brendan@gmail.com>
|
||||
Brendan O'Dea <bod@golang.org>
|
||||
|
|
@ -357,6 +378,7 @@ Carl Mastrangelo <notcarl@google.com>
|
|||
Carl Shapiro <cshapiro@google.com> <cshapiro@golang.org>
|
||||
Carlisia Campos <carlisia@grokkingtech.io>
|
||||
Carlo Alberto Ferraris <cafxx@strayorange.com>
|
||||
Carlos Amedee <carlos@golang.org>
|
||||
Carlos Castillo <cookieo9@gmail.com>
|
||||
Carlos Cirello <uldericofilho@gmail.com>
|
||||
Carlos Eduardo <me@carlosedp.com>
|
||||
|
|
@ -374,12 +396,14 @@ Cedric Staub <cs@squareup.com>
|
|||
Cezar Sá Espinola <cezarsa@gmail.com>
|
||||
Chad Rosier <mrosier.qdt@qualcommdatacenter.com>
|
||||
ChaiShushan <chaishushan@gmail.com>
|
||||
Changkun Ou <hi@changkun.us>
|
||||
Channing Kimble-Brown <channing@golang.org>
|
||||
Charles Fenwick Elliott <Charles@FenwickElliott.io>
|
||||
Charles Kenney <charlesc.kenney@gmail.com>
|
||||
Charles L. Dorian <cldorian@gmail.com>
|
||||
Charles Lee <zombie.fml@gmail.com>
|
||||
Charles Weill <weill@google.com>
|
||||
Chauncy Cullitan <chauncyc@google.com>
|
||||
Cherry Zhang <cherryyz@google.com>
|
||||
Chew Choon Keat <choonkeat@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ément Chigot <clement.chigot@atos.net>
|
||||
Clement Skau <clementskau@gmail.com>
|
||||
Clint J. Edwards <clint.j.edwards@gmail.com>
|
||||
Cody Oss <the.cody.oss@gmail.com>
|
||||
Colby Ranger <cranger@google.com>
|
||||
Colin Arnott <colin@urandom.co.uk>
|
||||
|
|
@ -448,6 +473,7 @@ Cristian Staretu <unclejacksons@gmail.com>
|
|||
Cuihtlauac ALVARADO <cuihtlauac.alvarado@orange.com>
|
||||
Cyrill Schumacher <cyrill@schumacher.fm>
|
||||
Daisuke Fujita <dtanshi45@gmail.com>
|
||||
Daisuke Suzuki <daisuzu@gmail.com>
|
||||
Daker Fernandes Pinheiro <daker.fernandes.pinheiro@intel.com>
|
||||
Damian Gryski <dgryski@gmail.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 Peterson <dpiddy@gmail.com>
|
||||
Dan Pupius <dan@medium.com>
|
||||
Dan Scales <danscales@google.com>
|
||||
Dan Sinclair <dan.sinclair@gmail.com>
|
||||
Daniel Cormier <danielc@knowbe4.com>
|
||||
Daniël de Kok <me@danieldk.eu>
|
||||
|
|
@ -501,6 +528,7 @@ Dave Russell <forfuncsake@gmail.com>
|
|||
David Anderson <danderson@google.com>
|
||||
David Barnett <dbarnett@google.com>
|
||||
David Benjamin <davidben@google.com>
|
||||
David Bond <davidsbond93@gmail.com>
|
||||
David Brophy <dave@brophy.uk>
|
||||
David Bürgin <676c7473@gmail.com>
|
||||
David Calavera <david.calavera@gmail.com>
|
||||
|
|
@ -541,6 +569,7 @@ Dean Prichard <dean.prichard@gmail.com>
|
|||
Deepak Jois <deepak.jois@gmail.com>
|
||||
Denis Bernard <db047h@gmail.com>
|
||||
Denis Brandolini <denis.brandolini@gmail.com>
|
||||
Denis Isaev <idenx@yandex.com>
|
||||
Denis Nagorny <denis.nagorny@intel.com>
|
||||
Dennis Kuhnert <mail.kuhnert@gmail.com>
|
||||
Denys Honsiorovskyi <honsiorovskyi@gmail.com>
|
||||
|
|
@ -581,6 +610,7 @@ Dmitry Mottl <dmitry.mottl@gmail.com>
|
|||
Dmitry Neverov <dmitry.neverov@gmail.com>
|
||||
Dmitry Savintsev <dsavints@gmail.com>
|
||||
Dmitry Yakunin <nonamezeil@gmail.com>
|
||||
Domas Tamašauskas <puerdomus@gmail.com>
|
||||
Domen Ipavec <domen@ipavec.net>
|
||||
Dominic Green <dominicgreen1@gmail.com>
|
||||
Dominik Honnef <dominik.honnef@gmail.com>
|
||||
|
|
@ -594,6 +624,7 @@ Doug Fawley <dfawley@google.com>
|
|||
Douglas Danger Manley <doug.manley@gmail.com>
|
||||
Drew Flower <drewvanstone@gmail.com>
|
||||
Drew Hintz <adhintz@google.com>
|
||||
Duco van Amstel <duco.vanamstel@gmail.com>
|
||||
Duncan Holm <mail@frou.org>
|
||||
Dustin Carlino <dcarlino@google.com>
|
||||
Dustin Herbison <djherbis@gmail.com>
|
||||
|
|
@ -607,6 +638,7 @@ Eddie Scholtz <escholtz@google.com>
|
|||
Eden Li <eden.li@gmail.com>
|
||||
Eduard Urbach <e.urbach@gmail.com>
|
||||
Eduardo Ramalho <eduardo.ramalho@gmail.com>
|
||||
Eduardo Villaseñor <evillasrmx@gmail.com>
|
||||
Edward Muller <edwardam@interlix.com>
|
||||
Egon Elbre <egonelbre@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>
|
||||
Eno Compton <enocom@google.com>
|
||||
Eoghan Sherry <ejsherry@gmail.com>
|
||||
Eric Biggers <ebiggers@google.com>
|
||||
Eric Brown <browne@vmware.com>
|
||||
Eric Chiang <eric.chiang.m@gmail.com>
|
||||
Eric Clark <zerohp@gmail.com>
|
||||
Eric Daniels <eric@erdaniels.com>
|
||||
|
|
@ -637,6 +671,7 @@ Eric Pauley <eric@pauley.me>
|
|||
Eric Ponce <tricokun@gmail.com>
|
||||
Eric Rescorla <ekr@rtfm.com>
|
||||
Eric Roshan-Eisner <eric.d.eisner@gmail.com>
|
||||
Eric Rutherford <erutherford@gmail.com>
|
||||
Eric Rykwalder <e.rykwalder@gmail.com>
|
||||
Erik Aigner <aigner.erik@gmail.com>
|
||||
Erik Dubbelboer <erik@dubbelboer.com>
|
||||
|
|
@ -718,6 +753,7 @@ Gabriel Aszalos <gabriel.aszalos@gmail.com>
|
|||
Gabriel Guzman <gabe.guzman@gmail.com>
|
||||
Gabriel Nelle <tehsphinx@web.de>
|
||||
Gabriel Nicolas Avellaneda <avellaneda.gabriel@gmail.com>
|
||||
Gabriel Rosenhouse <rosenhouse@gmail.com>
|
||||
Gabriel Russell <gabriel.russell@gmail.com>
|
||||
Gareth Paul Jones <gpj@foursquare.com>
|
||||
Garret Kelly <gdk@google.com>
|
||||
|
|
@ -735,18 +771,23 @@ Geoffroy Lorieux <lorieux.g@gmail.com>
|
|||
Geon Kim <geon0250@gmail.com>
|
||||
Georg Reinke <guelfey@gmail.com>
|
||||
George Gkirtsou <ggirtsou@gmail.com>
|
||||
George Hartzell <hartzell@alerce.com>
|
||||
George Shammas <george@shamm.as> <georgyo@gmail.com>
|
||||
Gerasimos (Makis) Maropoulos <kataras2006@hotmail.com>
|
||||
Gerasimos Dimitriadis <gedimitr@gmail.com>
|
||||
Gergely Brautigam <skarlso777@gmail.com>
|
||||
Gernot Vormayr <gvormayr@gmail.com>
|
||||
Gert Cuykens <gert.cuykens@gmail.com>
|
||||
Getulio Sánchez <valentin2507@gmail.com>
|
||||
Ghazni Nattarshah <ghazni.nattarshah@gmail.com>
|
||||
Gianguido Sora` <g.sora4@gmail.com>
|
||||
Gideon Jan-Wessel Redelinghuys <gjredelinghuys@gmail.com>
|
||||
Giles Lean <giles.lean@pobox.com>
|
||||
Giovanni Bajo <rasky@develer.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 @andig (184815) <cpuidle@gmx.de>
|
||||
GitHub User @andrius4669 (4699695) <andrius4669@gmail.com>
|
||||
GitHub User @as (8127015) <as.utf8@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 @cch123 (384546) <buaa.cch@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 @erifan (31343225) <eric.fang@arm.com>
|
||||
GitHub User @esell (9735165) <eujon.sellers@gmail.com>
|
||||
GitHub User @frennkie (6499251) <mail@rhab.de>
|
||||
GitHub User @hengwu0 (41297446) <41297446+hengwu0@users.noreply.github.com>
|
||||
GitHub User @itchyny (375258) <itchyny@hatena.ne.jp>
|
||||
GitHub User @jinmiaoluo (39730824) <jinmiaoluo@icloud.com>
|
||||
GitHub User @kazyshr (30496953) <kazyshr0301@gmail.com>
|
||||
GitHub User @kc1212 (1093806) <kc1212@users.noreply.github.com>
|
||||
GitHub User @Kropekk (13366453) <kamilkropiewnicki@gmail.com>
|
||||
GitHub User @linguohua (3434367) <lghchinaidea@gmail.com>
|
||||
GitHub User @LotusFenn (13775899) <fenn.lotus@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 @mkishere (224617) <224617+mkishere@users.noreply.github.com>
|
||||
GitHub User @OlgaVlPetrova (44112727) <OVPpetrova@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 @ramenjuniti (32011829) <ramenjuniti@gmail.com>
|
||||
GitHub User @saitarunreddy (21041941) <saitarunreddypalla@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 @tell-k (26263) <ffk2005@gmail.com>
|
||||
GitHub User @uhei (2116845) <uhei@users.noreply.github.com>
|
||||
GitHub User @uropek (39370426) <uropek@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 @zikaeroh (48577114) <zikaeroh@gmail.com>
|
||||
GitHub User @ZZMarquis (7624583) <zhonglingjian3821@163.com>
|
||||
Giulio Iotti <dullgiulio@gmail.com>
|
||||
Giulio Micheloni <giulio.micheloni@gmail.com>
|
||||
|
|
@ -802,6 +853,7 @@ Guilherme Garnier <guilherme.garnier@gmail.com>
|
|||
Guilherme Goncalves <guilhermeaugustosg@gmail.com>
|
||||
Guilherme Rezende <guilhermebr@gmail.com>
|
||||
Guillaume J. Charmes <guillaume@charmes.net>
|
||||
Günther Noack <gnoack@google.com>
|
||||
Guobiao Mei <meiguobiao@gmail.com>
|
||||
Guoliang Wang <iamwgliang@gmail.com>
|
||||
Gustav Paul <gustav.paul@gmail.com>
|
||||
|
|
@ -825,6 +877,7 @@ Harley Laue <losinggeneration@gmail.com>
|
|||
Harry Moreno <morenoh149@gmail.com>
|
||||
Harshavardhana <hrshvardhana@gmail.com>
|
||||
Hasan Ozgan <hasan@ozgan.net>
|
||||
Hasit Bhatt <hasit.p.bhatt@gmail.com>
|
||||
Hauke Löffler <hloeffler@users.noreply.github.com>
|
||||
Håvard Haugen <havard.haugen@gmail.com>
|
||||
He Liu <liulonnie@gmail.com>
|
||||
|
|
@ -852,9 +905,11 @@ Hong Ruiqi <hongruiqi@gmail.com>
|
|||
Hongfei Tan <feilengcui008@gmail.com>
|
||||
Horst Rutter <hhrutter@gmail.com>
|
||||
Hossein Sheikh Attar <hattar@google.com>
|
||||
Howard Zhang <howard.zhang@arm.com>
|
||||
Hsin Tsao <tsao@google.com>
|
||||
Hsin-Ho Yeh <yhh92u@gmail.com>
|
||||
Hu Keping <hukeping@huawei.com>
|
||||
Huan Du <i@huandu.me>
|
||||
Hugues Bruant <hugues.bruant@gmail.com>
|
||||
Huy Le <huy.dinh.le.89@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>
|
||||
Iccha Sethi <icchasethi@gmail.com>
|
||||
Idora Shinatose <idora.shinatose@gmail.com>
|
||||
Ignacio Hagopian <jsign.uy@gmail.com>
|
||||
Igor Bernstein <igorbernstein@google.com>
|
||||
Igor Dolzhikov <bluesriverz@gmail.com>
|
||||
Igor Vashyst <ivashyst@gmail.com>
|
||||
Igor Zhilianin <igor.zhilianin@gmail.com>
|
||||
Illya Yalovyy <yalovoy@gmail.com>
|
||||
Ilya Sinelnikov <sidhmangh@gmail.com>
|
||||
Ilya Tocar <ilya.tocar@intel.com>
|
||||
INADA Naoki <songofacandy@gmail.com>
|
||||
Inanc Gumus <m@inanc.io>
|
||||
|
|
@ -882,10 +939,12 @@ Ingo Gottwald <in.gottwald@gmail.com>
|
|||
Ingo Krabbe <ikrabbe.ask@gmail.com>
|
||||
Ingo Oeser <nightlyone@googlemail.com> <nightlyone@gmail.com>
|
||||
Ioannis Georgoulas <geototti21@hotmail.com>
|
||||
Irbe Krumina <irbekrm@gmail.com>
|
||||
Irfan Sharif <irfanmahmoudsharif@gmail.com>
|
||||
Irieda Noboru <irieda@gmail.com>
|
||||
Isaac Ardis <isaac.ardis@gmail.com>
|
||||
Isaac Wagner <ibw@isaacwagner.me>
|
||||
Isfan Azhabil <isfan.azhabil@tokopedia.com>
|
||||
Iskander Sharipov <iskander.sharipov@intel.com> <quasilyte@gmail.com>
|
||||
Issac Trotts <issactrotts@google.com>
|
||||
Ivan Babrou <ivan@cloudflare.com>
|
||||
|
|
@ -896,9 +955,11 @@ Ivan Markin <sw@nogoegst.net>
|
|||
Ivan Moscoso <moscoso@gmail.com>
|
||||
Ivan Osadchiy <ivan.osadchii@gmail.com>
|
||||
Ivan Sharavuev <shpiwan@gmail.com>
|
||||
Ivan Trubach <mr.trubach@icloud.com>
|
||||
Ivan Ukhov <ivan.ukhov@gmail.com>
|
||||
Ivy Evans <ivy@ivyevans.net>
|
||||
Jaana Burcu Dogan <jbd@google.com> <jbd@golang.org> <burcujdogan@gmail.com>
|
||||
Jaap Aarts <jaap.aarts1@gmail.com>
|
||||
Jack Britton <jackxbritton@gmail.com>
|
||||
Jack Lindamood <jlindamo@justin.tv>
|
||||
Jacob Baskin <jbaskin@google.com>
|
||||
|
|
@ -982,6 +1043,7 @@ Jean-Francois Cantin <jfcantin@gmail.com>
|
|||
Jean-Marc Eurin <jmeurin@google.com>
|
||||
Jean-Nicolas Moal <jn.moal@gmail.com>
|
||||
Jed Denlea <jed@fastly.com>
|
||||
Jędrzej Szczepaniak <jbszczepaniak@gmail.com>
|
||||
Jeet Parekh <jeetparekh96@gmail.com>
|
||||
Jeevanandam M <jeeva@myjeeva.com>
|
||||
Jeff (Zhefu) Jiang <jeffjiang@google.com>
|
||||
|
|
@ -998,6 +1060,7 @@ Jens Frederich <jfrederich@gmail.com>
|
|||
Jeremiah Harmsen <jeremiah@google.com>
|
||||
Jeremy Banks <_@jeremy.ca>
|
||||
Jeremy Canady <jcanady@gmail.com>
|
||||
Jeremy Faller <jeremy@golang.org>
|
||||
Jeremy Jackins <jeremyjackins@gmail.com>
|
||||
Jeremy Jay <jeremy@pbnjay.com>
|
||||
Jeremy Schlatter <jeremy.schlatter@gmail.com>
|
||||
|
|
@ -1042,6 +1105,7 @@ Joel Stemmer <stemmertech@gmail.com>
|
|||
Joey Geiger <jgeiger@users.noreply.github.com>
|
||||
Johan Brandhorst <johan.brandhorst@gmail.com>
|
||||
Johan Euphrosine <proppy@google.com>
|
||||
Johan Jansson <johan.jansson@iki.fi>
|
||||
Johan Sageryd <j@1616.se>
|
||||
John Asmuth <jasmuth@gmail.com>
|
||||
John Beisley <huin@google.com>
|
||||
|
|
@ -1057,6 +1121,7 @@ John Jenkins <twodopeshaggy@gmail.com>
|
|||
John Leidegren <john.leidegren@gmail.com>
|
||||
John Moore <johnkenneth.moore@gmail.com>
|
||||
John Newlin <jnewlin@google.com>
|
||||
John Papandriopoulos <jpap.code@gmail.com>
|
||||
John Potocny <johnp@vividcortex.com>
|
||||
John R. Lenton <jlenton@gmail.com>
|
||||
John Schnake <schnake.john@gmail.com>
|
||||
|
|
@ -1090,7 +1155,9 @@ Jordan Liggitt <liggitt@google.com>
|
|||
Jordan Rhee <jordanrh@microsoft.com>
|
||||
Jordi Martin <jordimartin@gmail.com>
|
||||
Jorge Araya <jorgejavieran@yahoo.com.mx>
|
||||
Jorge L. Fatta <jorge.fatta@auth0.com>
|
||||
Jos Visser <josv@google.com>
|
||||
Josa Gesell <josa@gesell.me>
|
||||
Jose Luis Vázquez González <josvazg@gmail.com>
|
||||
Joseph Bonneau <jcb@google.com>
|
||||
Joseph Holsten <joseph@josephholsten.com>
|
||||
|
|
@ -1119,11 +1186,13 @@ Julia Hansbrough <flowerhack@google.com>
|
|||
Julian Kornberger <jk+github@digineo.de>
|
||||
Julian Pastarmov <pastarmovj@google.com>
|
||||
Julian Phillips <julian@quantumfyre.co.uk>
|
||||
Julian Tibble <julian.tibble@gmail.com>
|
||||
Julie Qiu <julie@golang.org>
|
||||
Julien Kauffmann <julien.kauffmann@freelan.org>
|
||||
Julien Salleyron <julien.salleyron@gmail.com>
|
||||
Julien Schmidt <google@julienschmidt.com>
|
||||
Julio Montes <julio.montes@intel.com>
|
||||
Jun Zhang <jim.zoumo@gmail.com>
|
||||
Junda Liu <junda@celer.network>
|
||||
Jungho Ahn <jhahn@google.com>
|
||||
Junya Hayashi <ledmonster@gmail.com>
|
||||
|
|
@ -1133,12 +1202,12 @@ Justin Gracenin <jgracenin@gmail.com>
|
|||
Justin Li <git@justinli.net>
|
||||
Justin Nuß <nuss.justin@gmail.com>
|
||||
Justyn Temme <justyntemme@gmail.com>
|
||||
Kelly Heller <pestophagous@gmail.com>
|
||||
Kai Backman <kaib@golang.org>
|
||||
Kai Dong <dokia2357@gmail.com>
|
||||
Kai Trukenmüller <ktye78@gmail.com>
|
||||
Kale Blankenship <kale@lemnisys.com>
|
||||
Kaleb Elwert <kelwert@atlassian.com>
|
||||
Kalman Bekesi <kalmanb@google.com>
|
||||
Kamal Aboul-Hosn <aboulhosn@google.com>
|
||||
Kamil Chmielewski <kamil.chm@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>
|
||||
Kashav Madan <kshvmdn@gmail.com>
|
||||
Kate Manson <kate.manson@izettle.com>
|
||||
Katharine Berry <ktbry@google.com>
|
||||
Katie Hockman <katie@golang.org>
|
||||
Kato Kazuyoshi <kato.kazuyoshi@gmail.com>
|
||||
Katrina Owen <katrina.owen@gmail.com>
|
||||
|
|
@ -1161,9 +1231,11 @@ KB Sriram <kbsriram@google.com>
|
|||
Keegan Carruthers-Smith <keegan.csmith@gmail.com>
|
||||
Kei Son <hey.calmdown@gmail.com>
|
||||
Keiji Yoshida <keijiyoshida.mail@gmail.com>
|
||||
Keisuke Kishimoto <keisuke.kishimoto@gmail.com>
|
||||
Keith Ball <inflatablewoman@gmail.com>
|
||||
Keith Randall <khr@golang.org>
|
||||
Keith Rarick <kr@xph.us>
|
||||
Kelly Heller <pestophagous@gmail.com>
|
||||
Kelsey Hightower <kelsey.hightower@gmail.com>
|
||||
Kelvin Foo Chuan Lyi <vmirage@gmail.com>
|
||||
Ken Friedenbach <kenliz@cruzio.com>
|
||||
|
|
@ -1177,6 +1249,7 @@ Kenneth Shaw <kenshaw@gmail.com>
|
|||
Kenny Grant <kennygrant@gmail.com>
|
||||
Kenta Mori <zoncoen@gmail.com>
|
||||
Ketan Parmar <ketanbparmar@gmail.com>
|
||||
Kevan Swanberg <kevswanberg@gmail.com>
|
||||
Kevin Ballard <kevin@sb.org>
|
||||
Kevin Burke <kev@inburke.com>
|
||||
Kevin Gillette <extemporalgenome@gmail.com>
|
||||
|
|
@ -1198,9 +1271,11 @@ Klaus Post <klauspost@gmail.com>
|
|||
Kodie Goodwin <kodiegoodwin@gmail.com>
|
||||
Koichi Shiraishi <zchee.io@gmail.com>
|
||||
Koki Ide <niconegoto@yahoo.co.jp>
|
||||
Koki Tomoshige <tomocy.dev@gmail.com>
|
||||
Komu Wairagu <komuw05@gmail.com>
|
||||
Konstantin <konstantin8105@gmail.com>
|
||||
Konstantin Shaposhnikov <k.shaposhnikov@gmail.com>
|
||||
Koya IWAMURA <kiwamura0314@gmail.com>
|
||||
Kris Kwiatkowski <kris@cloudflare.com>
|
||||
Kris Nova <kris@nivenly.com>
|
||||
Kris Rousey <krousey@google.com>
|
||||
|
|
@ -1245,8 +1320,10 @@ Leonel Quinteros <leonel.quinteros@gmail.com>
|
|||
Lev Shamardin <shamardin@gmail.com>
|
||||
Lewin Bormann <lewin.bormann@gmail.com>
|
||||
Lion Yang <lion@aosc.xyz>
|
||||
Liz Rice <liz@lizrice.com>
|
||||
Lloyd Dewolf <foolswisdom@gmail.com>
|
||||
Lorenz Bauer <lmb@cloudflare.com>
|
||||
Lorenz Brun <lorenz@brun.one>
|
||||
Lorenz Nickel <mail@lorenznickel.de>
|
||||
Lorenzo Masini <rugginoso@develer.com>
|
||||
Lorenzo Stoakes <lstoakes@gmail.com>
|
||||
|
|
@ -1268,6 +1345,7 @@ Lukasz Milewski <lmmilewski@gmail.com>
|
|||
Luke Champine <luke.champine@gmail.com>
|
||||
Luke Curley <qpingu@gmail.com>
|
||||
Luke Granger-Brown <git@lukegb.com>
|
||||
Luke Young <bored-engineer@users.noreply.github.com>
|
||||
Luna Duclos <luna.duclos@palmstonegames.com>
|
||||
Luuk van Dijk <lvd@golang.org> <lvd@google.com>
|
||||
Lyle Franklin <lylejfranklin@gmail.com>
|
||||
|
|
@ -1290,6 +1368,7 @@ Manu Garg <manugarg@google.com>
|
|||
Manu S Ajith <neo@codingarena.in>
|
||||
Manuel Mendez <mmendez534@gmail.com>
|
||||
Marat Khabibullin <marat.khabibullin@jetbrains.com>
|
||||
Marc Sanmiquel <marcsanmiquel@gmail.com>
|
||||
Marc Weistroff <marc@weistroff.net>
|
||||
Marc-Antoine Ruel <maruel@chromium.org>
|
||||
Marcel Edmund Franke <marcel.edmund.franke@gmail.com>
|
||||
|
|
@ -1318,6 +1397,7 @@ Mark Wolfe <mark@wolfe.id.au>
|
|||
Mark Zavislak <zavislak@google.com>
|
||||
Marko Juhani Silokunnas <marko.silokunnas@gmail.com>
|
||||
Marko Kevac <marko@kevac.org>
|
||||
Marko Kungla <marko.kungla@gmail.com>
|
||||
Marko Mikulicic <mkm@google.com>
|
||||
Marko Mudrinic <mudrinic.mare@gmail.com>
|
||||
Marko Tiikkaja <marko@joh.to>
|
||||
|
|
@ -1473,6 +1553,7 @@ Mike Solomon <msolo@gmail.com>
|
|||
Mike Strosaker <strosake@us.ibm.com>
|
||||
Mike Tsao <mike@sowbug.com>
|
||||
Mike Wiacek <mjwiacek@google.com>
|
||||
Mikhail Fesenko <proggga@gmail.com>
|
||||
Mikhail Gusarov <dottedmag@dottedmag.net>
|
||||
Mikhail Panchenko <m@mihasya.com>
|
||||
Miki Tebeka <miki.tebeka@gmail.com>
|
||||
|
|
@ -1488,9 +1569,11 @@ Miroslav Genov <mgenov@gmail.com>
|
|||
Misty De Meo <mistydemeo@gmail.com>
|
||||
Mohit Agarwal <mohit@sdf.org>
|
||||
Mohit kumar Bajoria <mohitbajo36@gmail.com>
|
||||
Mohit Verma <vmohit.93@gmail.com>
|
||||
Momchil Velikov <momchil.velikov@gmail.com>
|
||||
Monis Khan <mkhan@redhat.com>
|
||||
Monty Taylor <mordred@inaugust.com>
|
||||
Moritz Fain <moritz@fain.io>
|
||||
Moriyoshi Koizumi <mozo@mozo.jp>
|
||||
Morten Siebuhr <sbhr@sbhr.dk>
|
||||
Môshe van der Sterre <moshevds@gmail.com>
|
||||
|
|
@ -1507,6 +1590,7 @@ Naoki Kanatani <k12naoki@gmail.com>
|
|||
Nate Wilkinson <nathanwilk7@gmail.com>
|
||||
Nathan Cantelmo <n.cantelmo@gmail.com>
|
||||
Nathan Caza <mastercactapus@gmail.com>
|
||||
Nathan Dias <nathan.dias@orijtech.com>
|
||||
Nathan Humphreys <nkhumphreys@gmail.com>
|
||||
Nathan John Youngman <nj@nathany.com>
|
||||
Nathan Otterness <otternes@cs.unc.edu>
|
||||
|
|
@ -1551,6 +1635,7 @@ Nigel Tao <nigeltao@golang.org>
|
|||
Nik Nyby <nnyby@columbia.edu>
|
||||
Nikhil Benesch <nikhil.benesch@gmail.com>
|
||||
Nikita Kryuchkov <nkryuchkov10@gmail.com>
|
||||
Nikita Vanyasin <nikita.vanyasin@gmail.com>
|
||||
Niklas Schnelle <niklas.schnelle@gmail.com>
|
||||
Niko Dziemba <niko@dziemba.com>
|
||||
Nikolay Turpitko <nikolay@turpitko.com>
|
||||
|
|
@ -1564,12 +1649,14 @@ Nodir Turakulov <nodir@google.com>
|
|||
Noel Georgi <git@frezbo.com>
|
||||
Norberto Lopes <nlopes.ml@gmail.com>
|
||||
Norman B. Lancaster <qbradq@gmail.com>
|
||||
Nuno Cruces <ncruces@users.noreply.github.com>
|
||||
Odin Ugedal <odin@ugedal.com>
|
||||
Oleg Bulatov <dmage@yandex-team.ru>
|
||||
Oleg Vakheta <helginet@gmail.com>
|
||||
Oleku Konko <oleku.konko@gmail.com>
|
||||
Oling Cat <olingcat@gmail.com>
|
||||
Oliver Hookins <ohookins@gmail.com>
|
||||
Oliver Powell <oliverpowell84@gmail.com>
|
||||
Oliver Stenbom <ostenbom@pivotal.io>
|
||||
Oliver Tonnhofer <olt@bogosoft.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>
|
||||
Padraig Kitterick <padraigkitterick@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 Martini <mrtnpaolo@gmail.com>
|
||||
Parker Moore <parkrmoore@gmail.com>
|
||||
|
|
@ -1626,6 +1715,7 @@ Paul van Brouwershaven <paul@vanbrouwershaven.com>
|
|||
Paul Wankadia <junyer@google.com>
|
||||
Paulo Casaretto <pcasaretto@gmail.com>
|
||||
Paulo Flabiano Smorigo <pfsmorigo@linux.vnet.ibm.com>
|
||||
Paulo Gomes <paulo.gomes.uk@gmail.com>
|
||||
Pavel Paulau <pavel.paulau@gmail.com>
|
||||
Pavel Zinovkin <pavel.zinovkin@gmail.com>
|
||||
Pavlo Sumkin <ymkins@gmail.com>
|
||||
|
|
@ -1679,6 +1769,7 @@ Piyush Mishra <piyush@codeitout.com>
|
|||
Plekhanov Maxim <kishtatix@gmail.com>
|
||||
Pontus Leitzler <leitzler@gmail.com>
|
||||
Prasanna Swaminathan <prasanna@mediamath.com>
|
||||
Prashant Agrawal <prashant.a.vjti@gmail.com>
|
||||
Prashant Varanasi <prashant@prashantv.com>
|
||||
Pravendra Singh <hackpravj@gmail.com>
|
||||
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>
|
||||
Rhys Hiltner <rhys@justin.tv>
|
||||
Ricardo Padilha <ricardospadilha@gmail.com>
|
||||
Ricardo Seriani <ricardo.seriani@gmail.com>
|
||||
Richard Barnes <rlb@ipv.sx>
|
||||
Richard Crowley <r@rcrowley.org>
|
||||
Richard Dingwall <rdingwall@gmail.com>
|
||||
|
|
@ -1734,6 +1826,7 @@ Rijnard van Tonder <rvantonder@gmail.com>
|
|||
Riku Voipio <riku.voipio@linaro.org>
|
||||
Risto Jaakko Saarelma <rsaarelm@gmail.com>
|
||||
Rob Earhart <earhart@google.com>
|
||||
Rob Findley <rfindley@google.com>
|
||||
Rob Norman <rob.norman@infinitycloud.com>
|
||||
Rob Phoenix <rob@robphoenix.com>
|
||||
Rob Pike <r@golang.org>
|
||||
|
|
@ -1753,17 +1846,20 @@ Robert-André Mauchin <zebob.m@gmail.com>
|
|||
Roberto Clapis <robclap8@gmail.com>
|
||||
Roberto Selbach <roberto@selbach.ca>
|
||||
Robin Eklind <r.eklind.87@gmail.com>
|
||||
Robin Zhong <robin@robinzhong.co>
|
||||
Rodolfo Carvalho <rhcarvalho@gmail.com>
|
||||
Rodolfo Rodriguez <rodolfobgibson@gmail.com>
|
||||
Rodrigo Moraes de Oliveira <rodrigo.moraes@gmail.com>
|
||||
Rodrigo Rafael Monti Kochenburger <divoxx@gmail.com>
|
||||
Roger Pau Monné <royger@gmail.com>
|
||||
Roger Peppe <rogpeppe@gmail.com>
|
||||
Rohan Challa <rohan@golang.org>
|
||||
Rohan Verma <rohanverma2004@gmail.com>
|
||||
Roland Illig <roland.illig@gmx.de>
|
||||
Roland Shoemaker <rolandshoemaker@gmail.com>
|
||||
Romain Baugue <romain.baugue@elwinar.com>
|
||||
Roman Budnikov <romanyx90@yandex.ru>
|
||||
Roman Kollár <roman.kollar.0@gmail.com>
|
||||
Roman Shchekin <mrqtros@gmail.com>
|
||||
Ron Hashimoto <mail@h2so5.net>
|
||||
Ron Minnich <rminnich@gmail.com>
|
||||
|
|
@ -1774,6 +1870,7 @@ Rowan Marshall <rowanajmarshall@gmail.com>
|
|||
Rowan Worth <sqweek@gmail.com>
|
||||
Rudi Kramer <rudi.kramer@gmail.com>
|
||||
Rui Ueyama <ruiu@google.com>
|
||||
Ruixin Bao <ruixin.bao@ibm.com>
|
||||
Ruslan Nigmatullin <elessar@dropbox.com>
|
||||
Russ Cox <rsc@golang.org>
|
||||
Russell Haering <russellhaering@gmail.com>
|
||||
|
|
@ -1815,6 +1912,7 @@ Sander van Harmelen <sander@vanharmelen.nl>
|
|||
Sanjay Menakuru <balasanjay@gmail.com>
|
||||
Santhosh Kumar Tekuri <santhosh.tekuri@gmail.com>
|
||||
Sarah Adams <shadams@google.com>
|
||||
Sardorbek Pulatov <sardorbek.pulatov@outlook.com>
|
||||
Sascha Brawer <sascha@brawer.ch>
|
||||
Sasha Lionheart <lionhearts@google.com>
|
||||
Sasha Sobol <sasha@scaledinference.com>
|
||||
|
|
@ -1824,6 +1922,7 @@ Scott Crunkleton <crunk1@gmail.com>
|
|||
Scott Ferguson <scottwferg@gmail.com>
|
||||
Scott Lawrence <bytbox@gmail.com>
|
||||
Scott Mansfield <smansfield@netflix.com>
|
||||
Scott Ragan <ragansa@fb.com>
|
||||
Scott Schwartz <scotts@golang.org>
|
||||
Scott Van Woudenberg <scottvw@google.com>
|
||||
Sean Burford <sburford@google.com>
|
||||
|
|
@ -1832,14 +1931,18 @@ Sean Chittenden <seanc@joyent.com>
|
|||
Sean Christopherson <sean.j.christopherson@intel.com>
|
||||
Sean Dolphin <Sean.Dolphin@kpcompass.com>
|
||||
Sean Harger <sharger@google.com>
|
||||
Sean Liao <seankhliao@gmail.com>
|
||||
Sean Rees <sean@erifax.org>
|
||||
Sebastiaan van Stijn <github@gone.nl>
|
||||
Sebastian Chlopecki <sebsebmc@gmail.com>
|
||||
Sebastian Kinne <skinne@google.com>
|
||||
Sebastian Schmidt <yath@google.com>
|
||||
Sebastien Binet <seb.binet@gmail.com>
|
||||
Sébastien Paolacci <sebastien.paolacci@gmail.com>
|
||||
Sebastien Williams-Wynn <sebastien@cytora.com>
|
||||
Segev Finer <segev208@gmail.com>
|
||||
Seiji Takahashi <timaki.st@gmail.com>
|
||||
Sergei Lemeshkin <sergeilem@gmail.com>
|
||||
Sergei Skorobogatov <skorobo@rambler.ru>
|
||||
Sergei Zagurskii <gvozdoder@gmail.com>
|
||||
Sergey 'SnakE' Gromov <snake.scaly@gmail.com>
|
||||
|
|
@ -1853,6 +1956,7 @@ Sergey Semin <gray12511@gmail.com>
|
|||
Sergey Yanykin <syanykin@ozon.ru>
|
||||
Sergio Luis O. B. Correia <sergio@correia.cc>
|
||||
Sergiusz Bazanski <bazanski@gmail.com>
|
||||
Serhat Giydiren <serhatgiydiren@gmail.com>
|
||||
Serhii Aheienko <serhii.aheienko@gmail.com>
|
||||
Seth Hoenig <seth.a.hoenig@gmail.com>
|
||||
Seth Vargo <sethvargo@gmail.com>
|
||||
|
|
@ -1875,21 +1979,28 @@ Shintaro Kaneko <kaneshin0120@gmail.com>
|
|||
Shivakumar GN <shivakumar.gn@gmail.com>
|
||||
Shivani Singhal <shivani.singhal2804@gmail.com>
|
||||
Shivansh Rai <shivansh@freebsd.org>
|
||||
Shivashis Padhi <shivashispadhi@gmail.com>
|
||||
Shubham Sharma <shubham.sha12@gmail.com>
|
||||
Shun Fan <sfan@google.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 Rawet <simon@rawet.se>
|
||||
Simon Rozman <simon@rozman.si>
|
||||
Simon Thulbourn <simon+github@thulbourn.com>
|
||||
Simon Whitehead <chemnova@gmail.com>
|
||||
Sina Siadat <siadat@gmail.com>
|
||||
Sjoerd Siebinga <sjoerd.siebinga@gmail.com>
|
||||
Sokolov Yura <funny.falcon@gmail.com>
|
||||
Song Gao <song@gao.io>
|
||||
Spencer Kocot <spencerkocot@gmail.com>
|
||||
Spencer Nelson <s@spenczar.com>
|
||||
Spencer Tung <spencertung@google.com>
|
||||
Spring Mc <heresy.mc@gmail.com>
|
||||
Srdjan Petrovic <spetrovic@google.com>
|
||||
Sridhar Venkatakrishnan <sridhar@laddoo.net>
|
||||
Srinidhi Kaushik <shrinidhi.kaushik@gmail.com>
|
||||
StalkR <stalkr@stalkr.net>
|
||||
Stan Schwertly <stan@schwertly.com>
|
||||
Stanislav Afanasev <php.progger@gmail.com>
|
||||
|
|
@ -1931,6 +2042,7 @@ Suyash <dextrous93@gmail.com>
|
|||
Suzy Mueller <suzmue@golang.org>
|
||||
Sven Almgren <sven@tras.se>
|
||||
Sven Blumenstein <svbl@google.com>
|
||||
Sven Taute <sven.taute@gmail.com>
|
||||
Sylvain Zimmer <sylvain@sylvainzimmer.com>
|
||||
Syohei YOSHIDA <syohex@gmail.com>
|
||||
Szabolcs Nagy <nsz@port70.net>
|
||||
|
|
@ -1948,6 +2060,7 @@ Takuto Ikuta <tikuta@google.com>
|
|||
Takuya Ueda <uedatakuya@gmail.com>
|
||||
Tal Shprecher <tshprecher@gmail.com>
|
||||
Tamir Duberstein <tamird@gmail.com>
|
||||
Tao Qingyun <qingyunha@gmail.com>
|
||||
Tao Shen <shentaoskyking@gmail.com>
|
||||
Tao Wang <twang2218@gmail.com>
|
||||
Tarmigan Casebolt <tarmigan@gmail.com>
|
||||
|
|
@ -1981,6 +2094,7 @@ Thomas Wanielista <tomwans@gmail.com>
|
|||
Thorben Krueger <thorben.krueger@gmail.com>
|
||||
Thordur Bjornsson <thorduri@secnorth.net>
|
||||
Tiago Queiroz <contato@tiago.eti.br>
|
||||
Tianji Wu <the729@gmail.com>
|
||||
Tianon Gravi <admwiggin@gmail.com>
|
||||
Tilman Dilo <tilman.dilo@gmail.com>
|
||||
Tim Cooijmans <timcooijmans@gmail.com>
|
||||
|
|
@ -2014,6 +2128,7 @@ Tom Payne <twpayne@gmail.com>
|
|||
Tom Szymanski <tgs@google.com>
|
||||
Tom Thorogood <me+google@tomthorogood.co.uk>
|
||||
Tom Wilkie <tom@weave.works>
|
||||
Tomas Dabasinskas <tomas@dabasinskas.net>
|
||||
Tommy Schaefer <tommy.schaefer@teecom.com>
|
||||
Tomoya Ishizaki <zaq1tomo@gmail.com>
|
||||
Tonis Tiigi <tonistiigi@gmail.com>
|
||||
|
|
@ -2064,6 +2179,7 @@ Victor Chudnovsky <vchudnov@google.com>
|
|||
Victor Vrantchan <vrancean+github@gmail.com>
|
||||
Vignesh Ramachandra <vickyramachandra@gmail.com>
|
||||
Vikas Kedia <vikask@google.com>
|
||||
Ville Skyttä <ville.skytta@iki.fi>
|
||||
Vincent Ambo <tazjin@googlemail.com>
|
||||
Vincent Batts <vbatts@hashbangbash.com> <vbatts@gmail.com>
|
||||
Vincent Vanackere <vincent.vanackere@gmail.com>
|
||||
|
|
@ -2071,15 +2187,18 @@ Vinu Rajashekhar <vinutheraj@gmail.com>
|
|||
Vish Subramanian <vish@google.com>
|
||||
Vishvananda Ishaya <vishvananda@gmail.com>
|
||||
Visweswara R <r.visweswara@gmail.com>
|
||||
Vitaly Zdanevich <zdanevich.vitaly@ya.ru>
|
||||
Vitor De Mario <vitordemario@gmail.com>
|
||||
Vivek Sekhar <vsekhar@google.com>
|
||||
Vlad Krasnov <vlad@cloudflare.com>
|
||||
Vladimir Evgrafov <evgrafov.vladimir@gmail.com>
|
||||
Vladimir Kovpak <cn007b@gmail.com>
|
||||
Vladimir Kuzmin <vkuzmin@uber.com>
|
||||
Vladimir Mihailenco <vladimir.webdev@gmail.com>
|
||||
Vladimir Nikishenko <vova616@gmail.com>
|
||||
Vladimir Stefanovic <vladimir.stefanovic@imgtec.com>
|
||||
Vladimir Varankin <nek.narqo@gmail.com>
|
||||
Vojtech Bocek <vbocek@gmail.com>
|
||||
Volker Dobler <dr.volker.dobler@gmail.com>
|
||||
Volodymyr Paprotski <vpaprots@ca.ibm.com>
|
||||
W. Trevor King <wking@tremily.us>
|
||||
|
|
@ -2087,6 +2206,7 @@ Wade Simmons <wade@wades.im>
|
|||
Wagner Riffel <wgrriffel@gmail.com>
|
||||
Walter Poupore <wpoupore@google.com>
|
||||
Wander Lairson Costa <wcosta@mozilla.com>
|
||||
Wang Xuerui <git@xen0n.name>
|
||||
Warren Fernandes <warren.f.fernandes@gmail.com>
|
||||
Wayne Ashley Berry <wayneashleyberry@gmail.com>
|
||||
Wedson Almeida Filho <wedsonaf@google.com>
|
||||
|
|
@ -2113,10 +2233,12 @@ William Chan <willchan@chromium.org>
|
|||
William Chang <mr.williamchang@gmail.com>
|
||||
William Josephson <wjosephson@gmail.com>
|
||||
William Orr <will@worrbase.com> <ay1244@gmail.com>
|
||||
William Poussier <william.poussier@gmail.com>
|
||||
Wisdom Omuya <deafgoat@gmail.com>
|
||||
Wu Yunzhou <yunzhouwu@gmail.com>
|
||||
Xi Ruoyao <xry23333@gmail.com>
|
||||
Xia Bin <snyh@snyh.org>
|
||||
Xiangdong Ji <xiangdong.ji@arm.com>
|
||||
Xing Xing <mikespook@gmail.com>
|
||||
Xu Fei <badgangkiller@gmail.com>
|
||||
Xudong Zhang <felixmelon@gmail.com>
|
||||
|
|
@ -2148,6 +2270,7 @@ Yoshiyuki Mineo <yoshiyuki.mineo@gmail.com>
|
|||
Yosuke Akatsuka <yosuke.akatsuka@gmail.com>
|
||||
Yu Heng Zhang <annita.zhang@cn.ibm.com>
|
||||
Yu Xuan Zhang <zyxsh@cn.ibm.com>
|
||||
Yuichi Nishiwaki <yuichi.nishiwaki@gmail.com>
|
||||
Yuji Yaginuma <yuuji.yaginuma@gmail.com>
|
||||
Yuki OKUSHI <huyuumi.dev@gmail.com>
|
||||
Yuki Yugui Sonoda <yugui@google.com>
|
||||
|
|
@ -2175,6 +2298,7 @@ Zhongtao Chen <chenzhongtao@126.com>
|
|||
Zhongwei Yao <zhongwei.yao@arm.com>
|
||||
Zhou Peng <p@ctriple.cn>
|
||||
Ziad Hatahet <hatahet@gmail.com>
|
||||
Ziheng Liu <lzhfromustc@gmail.com>
|
||||
Zorion Arrizabalaga <zorionk@gmail.com>
|
||||
Максадбек Ахмедов <a.maksadbek@gmail.com>
|
||||
Максим Федосеев <max.faceless.frei@gmail.com>
|
||||
|
|
|
|||
197
api/go1.14.txt
Normal file
197
api/go1.14.txt
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
pkg crypto/tls, const TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 52393
|
||||
pkg crypto/tls, const TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 uint16
|
||||
pkg crypto/tls, const TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 52392
|
||||
pkg crypto/tls, const TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 uint16
|
||||
pkg crypto/tls, func CipherSuiteName(uint16) string
|
||||
pkg crypto/tls, func CipherSuites() []*CipherSuite
|
||||
pkg crypto/tls, func InsecureCipherSuites() []*CipherSuite
|
||||
pkg crypto/tls, method (*CertificateRequestInfo) SupportsCertificate(*Certificate) error
|
||||
pkg crypto/tls, method (*ClientHelloInfo) SupportsCertificate(*Certificate) error
|
||||
pkg crypto/tls, type Certificate struct, SupportedSignatureAlgorithms []SignatureScheme
|
||||
pkg crypto/tls, type CertificateRequestInfo struct, Version uint16
|
||||
pkg crypto/tls, type CipherSuite struct
|
||||
pkg crypto/tls, type CipherSuite struct, ID uint16
|
||||
pkg crypto/tls, type CipherSuite struct, Insecure bool
|
||||
pkg crypto/tls, type CipherSuite struct, Name string
|
||||
pkg crypto/tls, type CipherSuite struct, SupportedVersions []uint16
|
||||
pkg debug/dwarf, const AttrAddrBase = 115
|
||||
pkg debug/dwarf, const AttrAddrBase Attr
|
||||
pkg debug/dwarf, const AttrAlignment = 136
|
||||
pkg debug/dwarf, const AttrAlignment Attr
|
||||
pkg debug/dwarf, const AttrBinaryScale = 91
|
||||
pkg debug/dwarf, const AttrBinaryScale Attr
|
||||
pkg debug/dwarf, const AttrCallAllCalls = 122
|
||||
pkg debug/dwarf, const AttrCallAllCalls Attr
|
||||
pkg debug/dwarf, const AttrCallAllSourceCalls = 123
|
||||
pkg debug/dwarf, const AttrCallAllSourceCalls Attr
|
||||
pkg debug/dwarf, const AttrCallAllTailCalls = 124
|
||||
pkg debug/dwarf, const AttrCallAllTailCalls Attr
|
||||
pkg debug/dwarf, const AttrCallDataLocation = 133
|
||||
pkg debug/dwarf, const AttrCallDataLocation Attr
|
||||
pkg debug/dwarf, const AttrCallDataValue = 134
|
||||
pkg debug/dwarf, const AttrCallDataValue Attr
|
||||
pkg debug/dwarf, const AttrCallOrigin = 127
|
||||
pkg debug/dwarf, const AttrCallOrigin Attr
|
||||
pkg debug/dwarf, const AttrCallPC = 129
|
||||
pkg debug/dwarf, const AttrCallPC Attr
|
||||
pkg debug/dwarf, const AttrCallParameter = 128
|
||||
pkg debug/dwarf, const AttrCallParameter Attr
|
||||
pkg debug/dwarf, const AttrCallReturnPC = 125
|
||||
pkg debug/dwarf, const AttrCallReturnPC Attr
|
||||
pkg debug/dwarf, const AttrCallTailCall = 130
|
||||
pkg debug/dwarf, const AttrCallTailCall Attr
|
||||
pkg debug/dwarf, const AttrCallTarget = 131
|
||||
pkg debug/dwarf, const AttrCallTarget Attr
|
||||
pkg debug/dwarf, const AttrCallTargetClobbered = 132
|
||||
pkg debug/dwarf, const AttrCallTargetClobbered Attr
|
||||
pkg debug/dwarf, const AttrCallValue = 126
|
||||
pkg debug/dwarf, const AttrCallValue Attr
|
||||
pkg debug/dwarf, const AttrConstExpr = 108
|
||||
pkg debug/dwarf, const AttrConstExpr Attr
|
||||
pkg debug/dwarf, const AttrDataBitOffset = 107
|
||||
pkg debug/dwarf, const AttrDataBitOffset Attr
|
||||
pkg debug/dwarf, const AttrDecimalScale = 92
|
||||
pkg debug/dwarf, const AttrDecimalScale Attr
|
||||
pkg debug/dwarf, const AttrDecimalSign = 94
|
||||
pkg debug/dwarf, const AttrDecimalSign Attr
|
||||
pkg debug/dwarf, const AttrDefaulted = 139
|
||||
pkg debug/dwarf, const AttrDefaulted Attr
|
||||
pkg debug/dwarf, const AttrDeleted = 138
|
||||
pkg debug/dwarf, const AttrDeleted Attr
|
||||
pkg debug/dwarf, const AttrDigitCount = 95
|
||||
pkg debug/dwarf, const AttrDigitCount Attr
|
||||
pkg debug/dwarf, const AttrDwoName = 118
|
||||
pkg debug/dwarf, const AttrDwoName Attr
|
||||
pkg debug/dwarf, const AttrElemental = 102
|
||||
pkg debug/dwarf, const AttrElemental Attr
|
||||
pkg debug/dwarf, const AttrEndianity = 101
|
||||
pkg debug/dwarf, const AttrEndianity Attr
|
||||
pkg debug/dwarf, const AttrEnumClass = 109
|
||||
pkg debug/dwarf, const AttrEnumClass Attr
|
||||
pkg debug/dwarf, const AttrExplicit = 99
|
||||
pkg debug/dwarf, const AttrExplicit Attr
|
||||
pkg debug/dwarf, const AttrExportSymbols = 137
|
||||
pkg debug/dwarf, const AttrExportSymbols Attr
|
||||
pkg debug/dwarf, const AttrLinkageName = 110
|
||||
pkg debug/dwarf, const AttrLinkageName Attr
|
||||
pkg debug/dwarf, const AttrLoclistsBase = 140
|
||||
pkg debug/dwarf, const AttrLoclistsBase Attr
|
||||
pkg debug/dwarf, const AttrMacros = 121
|
||||
pkg debug/dwarf, const AttrMacros Attr
|
||||
pkg debug/dwarf, const AttrMainSubprogram = 106
|
||||
pkg debug/dwarf, const AttrMainSubprogram Attr
|
||||
pkg debug/dwarf, const AttrMutable = 97
|
||||
pkg debug/dwarf, const AttrMutable Attr
|
||||
pkg debug/dwarf, const AttrNoreturn = 135
|
||||
pkg debug/dwarf, const AttrNoreturn Attr
|
||||
pkg debug/dwarf, const AttrObjectPointer = 100
|
||||
pkg debug/dwarf, const AttrObjectPointer Attr
|
||||
pkg debug/dwarf, const AttrPictureString = 96
|
||||
pkg debug/dwarf, const AttrPictureString Attr
|
||||
pkg debug/dwarf, const AttrPure = 103
|
||||
pkg debug/dwarf, const AttrPure Attr
|
||||
pkg debug/dwarf, const AttrRank = 113
|
||||
pkg debug/dwarf, const AttrRank Attr
|
||||
pkg debug/dwarf, const AttrRecursive = 104
|
||||
pkg debug/dwarf, const AttrRecursive Attr
|
||||
pkg debug/dwarf, const AttrReference = 119
|
||||
pkg debug/dwarf, const AttrReference Attr
|
||||
pkg debug/dwarf, const AttrRnglistsBase = 116
|
||||
pkg debug/dwarf, const AttrRnglistsBase Attr
|
||||
pkg debug/dwarf, const AttrRvalueReference = 120
|
||||
pkg debug/dwarf, const AttrRvalueReference Attr
|
||||
pkg debug/dwarf, const AttrSignature = 105
|
||||
pkg debug/dwarf, const AttrSignature Attr
|
||||
pkg debug/dwarf, const AttrSmall = 93
|
||||
pkg debug/dwarf, const AttrSmall Attr
|
||||
pkg debug/dwarf, const AttrStrOffsetsBase = 114
|
||||
pkg debug/dwarf, const AttrStrOffsetsBase Attr
|
||||
pkg debug/dwarf, const AttrStringLengthBitSize = 111
|
||||
pkg debug/dwarf, const AttrStringLengthBitSize Attr
|
||||
pkg debug/dwarf, const AttrStringLengthByteSize = 112
|
||||
pkg debug/dwarf, const AttrStringLengthByteSize Attr
|
||||
pkg debug/dwarf, const AttrThreadsScaled = 98
|
||||
pkg debug/dwarf, const AttrThreadsScaled Attr
|
||||
pkg debug/dwarf, const ClassAddrPtr = 15
|
||||
pkg debug/dwarf, const ClassAddrPtr Class
|
||||
pkg debug/dwarf, const ClassLocList = 16
|
||||
pkg debug/dwarf, const ClassLocList Class
|
||||
pkg debug/dwarf, const ClassRngList = 17
|
||||
pkg debug/dwarf, const ClassRngList Class
|
||||
pkg debug/dwarf, const ClassRngListsPtr = 18
|
||||
pkg debug/dwarf, const ClassRngListsPtr Class
|
||||
pkg debug/dwarf, const ClassStrOffsetsPtr = 19
|
||||
pkg debug/dwarf, const ClassStrOffsetsPtr Class
|
||||
pkg debug/dwarf, const TagAtomicType = 71
|
||||
pkg debug/dwarf, const TagAtomicType Tag
|
||||
pkg debug/dwarf, const TagCallSite = 72
|
||||
pkg debug/dwarf, const TagCallSite Tag
|
||||
pkg debug/dwarf, const TagCallSiteParameter = 73
|
||||
pkg debug/dwarf, const TagCallSiteParameter Tag
|
||||
pkg debug/dwarf, const TagCoarrayType = 68
|
||||
pkg debug/dwarf, const TagCoarrayType Tag
|
||||
pkg debug/dwarf, const TagDynamicType = 70
|
||||
pkg debug/dwarf, const TagDynamicType Tag
|
||||
pkg debug/dwarf, const TagGenericSubrange = 69
|
||||
pkg debug/dwarf, const TagGenericSubrange Tag
|
||||
pkg debug/dwarf, const TagImmutableType = 75
|
||||
pkg debug/dwarf, const TagImmutableType Tag
|
||||
pkg debug/dwarf, const TagSkeletonUnit = 74
|
||||
pkg debug/dwarf, const TagSkeletonUnit Tag
|
||||
pkg debug/dwarf, method (*Data) AddSection(string, []uint8) error
|
||||
pkg debug/dwarf, method (*LineReader) Files() []*LineFile
|
||||
pkg debug/dwarf, method (*Reader) ByteOrder() binary.ByteOrder
|
||||
pkg encoding/asn1, const TagBMPString = 30
|
||||
pkg encoding/asn1, const TagBMPString ideal-int
|
||||
pkg encoding/json, method (*Decoder) InputOffset() int64
|
||||
pkg go/build, type Context struct, Dir string
|
||||
pkg go/doc, func NewFromFiles(*token.FileSet, []*ast.File, string, ...interface{}) (*Package, error)
|
||||
pkg go/doc, type Example struct, Suffix string
|
||||
pkg go/doc, type Func struct, Examples []*Example
|
||||
pkg go/doc, type Package struct, Examples []*Example
|
||||
pkg go/doc, type Type struct, Examples []*Example
|
||||
pkg hash/maphash, func MakeSeed() Seed
|
||||
pkg hash/maphash, method (*Hash) BlockSize() int
|
||||
pkg hash/maphash, method (*Hash) Reset()
|
||||
pkg hash/maphash, method (*Hash) Seed() Seed
|
||||
pkg hash/maphash, method (*Hash) SetSeed(Seed)
|
||||
pkg hash/maphash, method (*Hash) Size() int
|
||||
pkg hash/maphash, method (*Hash) Sum([]uint8) []uint8
|
||||
pkg hash/maphash, method (*Hash) Sum64() uint64
|
||||
pkg hash/maphash, method (*Hash) Write([]uint8) (int, error)
|
||||
pkg hash/maphash, method (*Hash) WriteByte(uint8) error
|
||||
pkg hash/maphash, method (*Hash) WriteString(string) (int, error)
|
||||
pkg hash/maphash, type Hash struct
|
||||
pkg hash/maphash, type Seed struct
|
||||
pkg log, const Lmsgprefix = 64
|
||||
pkg log, const Lmsgprefix ideal-int
|
||||
pkg math, func FMA(float64, float64, float64) float64
|
||||
pkg math/bits, func Rem(uint, uint, uint) uint
|
||||
pkg math/bits, func Rem32(uint32, uint32, uint32) uint32
|
||||
pkg math/bits, func Rem64(uint64, uint64, uint64) uint64
|
||||
pkg mime/multipart, method (*Reader) NextRawPart() (*Part, error)
|
||||
pkg net/http, method (Header) Values(string) []string
|
||||
pkg net/http, type Transport struct, DialTLSContext func(context.Context, string, string) (net.Conn, error)
|
||||
pkg net/http/httptest, type Server struct, EnableHTTP2 bool
|
||||
pkg net/textproto, method (MIMEHeader) Values(string) []string
|
||||
pkg strconv, method (*NumError) Unwrap() error
|
||||
pkg syscall (windows-386), const CTRL_CLOSE_EVENT = 2
|
||||
pkg syscall (windows-386), const CTRL_CLOSE_EVENT ideal-int
|
||||
pkg syscall (windows-386), const CTRL_LOGOFF_EVENT = 5
|
||||
pkg syscall (windows-386), const CTRL_LOGOFF_EVENT ideal-int
|
||||
pkg syscall (windows-386), const CTRL_SHUTDOWN_EVENT = 6
|
||||
pkg syscall (windows-386), const CTRL_SHUTDOWN_EVENT ideal-int
|
||||
pkg syscall (windows-amd64), const CTRL_CLOSE_EVENT = 2
|
||||
pkg syscall (windows-amd64), const CTRL_CLOSE_EVENT ideal-int
|
||||
pkg syscall (windows-amd64), const CTRL_LOGOFF_EVENT = 5
|
||||
pkg syscall (windows-amd64), const CTRL_LOGOFF_EVENT ideal-int
|
||||
pkg syscall (windows-amd64), const CTRL_SHUTDOWN_EVENT = 6
|
||||
pkg syscall (windows-amd64), const CTRL_SHUTDOWN_EVENT ideal-int
|
||||
pkg testing, method (*B) Cleanup(func())
|
||||
pkg testing, method (*T) Cleanup(func())
|
||||
pkg testing, type TB interface, Cleanup(func())
|
||||
pkg unicode, const Version = "12.0.0"
|
||||
pkg unicode, var Elymaic *RangeTable
|
||||
pkg unicode, var Nandinagari *RangeTable
|
||||
pkg unicode, var Nyiakeng_Puachue_Hmong *RangeTable
|
||||
pkg unicode, var Wancho *RangeTable
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
pkg unicode, const Version = "12.0.0"
|
||||
pkg unicode, var Elymaic *RangeTable
|
||||
pkg unicode, var Nandinagari *RangeTable
|
||||
pkg unicode, var Nyiakeng_Puachue_Hmong *RangeTable
|
||||
pkg unicode, var Wancho *RangeTable
|
||||
|
|
@ -74,7 +74,7 @@ important, the use of the tool itself.</p>
|
|||
<p>The <code>go</code> command requires that code adheres to a few key,
|
||||
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
|
||||
root directory of the repository is identified by the repository's
|
||||
main URL, without the <code>http://</code> prefix. Subdirectories are named by
|
||||
|
|
|
|||
|
|
@ -133,6 +133,11 @@ cost of increased memory usage.
|
|||
<code>halt_on_error</code> (default <code>0</code>): Controls whether the program
|
||||
exits after reporting first data race.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<code>atexit_sleep_ms</code> (default <code>1000</code>): Amount of milliseconds
|
||||
to sleep in the main goroutine before exiting.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
|
|
|
|||
211
doc/conduct.html
211
doc/conduct.html
|
|
@ -1,211 +0,0 @@
|
|||
<!--{
|
||||
"Title": "Go Community Code of Conduct",
|
||||
"Path": "/conduct",
|
||||
"Template": true
|
||||
}-->
|
||||
|
||||
<style>
|
||||
ul {
|
||||
max-width: 800px;
|
||||
}
|
||||
ul ul {
|
||||
margin: 0 0 5px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<h2 id="about">About</h2>
|
||||
|
||||
<p>
|
||||
Online communities include people from many different backgrounds.
|
||||
The Go contributors are committed to providing a friendly, safe and welcoming
|
||||
environment for all, regardless of gender identity and expression, sexual orientation,
|
||||
disabilities, neurodiversity, physical appearance, body size, ethnicity, nationality,
|
||||
race, age, religion, or similar personal characteristics.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The first goal of the Code of Conduct is to specify a baseline standard
|
||||
of behavior so that people with different social values and communication
|
||||
styles can talk about Go effectively, productively, and respectfully.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The second goal is to provide a mechanism for resolving conflicts in the
|
||||
community when they arise.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The third goal of the Code of Conduct is to make our community welcoming to
|
||||
people from different backgrounds.
|
||||
Diversity is critical to the project; for Go to be successful, it needs
|
||||
contributors and users from all backgrounds.
|
||||
(See <a href="https://blog.golang.org/open-source">Go, Open Source, Community</a>.)
|
||||
</p>
|
||||
|
||||
<p>
|
||||
We believe that healthy debate and disagreement are essential to a healthy project and community.
|
||||
However, it is never ok to be disrespectful.
|
||||
We value diverse opinions, but we value respectful behavior more.
|
||||
</p>
|
||||
|
||||
<h2 id="values">Gopher values</h2>
|
||||
|
||||
<p>
|
||||
These are the values to which people in the Go community (“Gophers”) should aspire.
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>Be friendly and welcoming
|
||||
<li>Be patient
|
||||
<ul>
|
||||
<li>Remember that people have varying communication styles and that not
|
||||
everyone is using their native language.
|
||||
(Meaning and tone can be lost in translation.)
|
||||
</ul>
|
||||
<li>Be thoughtful
|
||||
<ul>
|
||||
<li>Productive communication requires effort.
|
||||
Think about how your words will be interpreted.
|
||||
<li>Remember that sometimes it is best to refrain entirely from commenting.
|
||||
</ul>
|
||||
<li>Be respectful
|
||||
<ul>
|
||||
<li>In particular, respect differences of opinion.
|
||||
</ul>
|
||||
<li>Be charitable
|
||||
<ul>
|
||||
<li>Interpret the arguments of others in good faith, do not seek to disagree.
|
||||
<li>When we do disagree, try to understand why.
|
||||
</ul>
|
||||
<li>Avoid destructive behavior:
|
||||
<ul>
|
||||
<li>Derailing: stay on topic; if you want to talk about something else,
|
||||
start a new conversation.
|
||||
<li>Unconstructive criticism: don't merely decry the current state of affairs;
|
||||
offer—or at least solicit—suggestions as to how things may be improved.
|
||||
<li>Snarking (pithy, unproductive, sniping comments)
|
||||
<li>Discussing potentially offensive or sensitive issues;
|
||||
this all too often leads to unnecessary conflict.
|
||||
<li>Microaggressions: brief and commonplace verbal, behavioral and
|
||||
environmental indignities that communicate hostile, derogatory or negative
|
||||
slights and insults to a person or group.
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
People are complicated.
|
||||
You should expect to be misunderstood and to misunderstand others;
|
||||
when this inevitably occurs, resist the urge to be defensive or assign blame.
|
||||
Try not to take offense where no offense was intended.
|
||||
Give people the benefit of the doubt.
|
||||
Even if the intent was to provoke, do not rise to it.
|
||||
It is the responsibility of <i>all parties</i> to de-escalate conflict when it arises.
|
||||
</p>
|
||||
|
||||
<h2 id="code">Code of Conduct</h2>
|
||||
|
||||
<h3 id="our-pledge">Our Pledge</h3>
|
||||
|
||||
<p>In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, gender identity and expression, level of
|
||||
experience, education, socio-economic status, nationality, personal appearance,
|
||||
race, religion, or sexual identity and orientation.</p>
|
||||
|
||||
<h3 id="our-standards">Our Standards</h3>
|
||||
|
||||
<p>Examples of behavior that contributes to creating a positive environment
|
||||
include:</p>
|
||||
|
||||
<ul>
|
||||
<li>Using welcoming and inclusive language</li>
|
||||
<li>Being respectful of differing viewpoints and experiences</li>
|
||||
<li>Gracefully accepting constructive criticism</li>
|
||||
<li>Focusing on what is best for the community</li>
|
||||
<li>Showing empathy towards other community members</li>
|
||||
</ul>
|
||||
|
||||
<p>Examples of unacceptable behavior by participants include:</p>
|
||||
|
||||
<ul>
|
||||
<li>The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances</li>
|
||||
<li>Trolling, insulting/derogatory comments, and personal or political attacks</li>
|
||||
<li>Public or private harassment</li>
|
||||
<li>Publishing others’ private information, such as a physical or electronic
|
||||
address, without explicit permission</li>
|
||||
<li>Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="our-responsibilities">Our Responsibilities</h3>
|
||||
|
||||
<p>Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.</p>
|
||||
|
||||
<p>Project maintainers have the right and responsibility to remove, edit, or reject
|
||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||
not aligned to this Code of Conduct, or to ban temporarily or permanently any
|
||||
contributor for other behaviors that they deem inappropriate, threatening,
|
||||
offensive, or harmful.</p>
|
||||
|
||||
<h3 id="scope">Scope</h3>
|
||||
|
||||
<p>This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.</p>
|
||||
|
||||
<p>This Code of Conduct also applies outside the project spaces when the Project
|
||||
Steward has a reasonable belief that an individual’s behavior may have a
|
||||
negative impact on the project or its community.</p>
|
||||
|
||||
<h3 id="conflict-resolution"></a>Conflict Resolution</h3>
|
||||
|
||||
<p>We do not believe that all conflict is bad; healthy debate and disagreement
|
||||
often yield positive results. However, it is never okay to be disrespectful or
|
||||
to engage in behavior that violates the project’s code of conduct.</p>
|
||||
|
||||
<p>If you see someone violating the code of conduct, you are encouraged to address
|
||||
the behavior directly with those involved. Many issues can be resolved quickly
|
||||
and easily, and this gives people more control over the outcome of their
|
||||
dispute. If you are unable to resolve the matter for any reason, or if the
|
||||
behavior is threatening or harassing, report it. We are dedicated to providing
|
||||
an environment where participants feel welcome and safe.</p>
|
||||
|
||||
<p id="reporting">Reports should be directed to Cassandra Salisbury, the
|
||||
Go Project Steward, at <i>conduct@golang.org</i>.
|
||||
It is the Project Steward’s duty to
|
||||
receive and address reported violations of the code of conduct. They will then
|
||||
work with a committee consisting of representatives from the Open Source
|
||||
Programs Office and the Google Open Source Strategy team. If for any reason you
|
||||
are uncomfortable reaching out the Project Steward, please email
|
||||
the Google Open Source Programs Office at <i>opensource@google.com</i>.</p>
|
||||
|
||||
<p>We will investigate every complaint, but you may not receive a direct response.
|
||||
We will use our discretion in determining when and how to follow up on reported
|
||||
incidents, which may range from not taking action to permanent expulsion from
|
||||
the project and project-sponsored spaces. We will notify the accused of the
|
||||
report and provide them an opportunity to discuss it before any action is taken.
|
||||
The identity of the reporter will be omitted from the details of the report
|
||||
supplied to the accused. In potentially harmful situations, such as ongoing
|
||||
harassment or threats to anyone’s safety, we may take action without notice.</p>
|
||||
|
||||
<h3 id="attribution">Attribution</h3>
|
||||
|
||||
<p>This Code of Conduct is adapted from the Contributor Covenant, version 1.4,
|
||||
available at
|
||||
<a href="https://www.contributor-covenant.org/version/1/4/code-of-conduct.html">https://www.contributor-covenant.org/version/1/4/code-of-conduct.html</a></p>
|
||||
|
||||
<h2 id="summary">Summary</h2>
|
||||
|
||||
<ul>
|
||||
<li>Treat everyone with respect and kindness.
|
||||
<li>Be thoughtful in how you communicate.
|
||||
<li>Don’t be destructive or inflammatory.
|
||||
<li>If you encounter an issue, please mail <a href="mailto:conduct@golang.org">conduct@golang.org</a>.
|
||||
</ul>
|
||||
|
|
@ -925,13 +925,13 @@ New files that you contribute should use the standard copyright header:
|
|||
</p>
|
||||
|
||||
<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
|
||||
// license that can be found in the LICENSE file.
|
||||
</pre>
|
||||
|
||||
<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.
|
||||
Do not update the copyright year on files that you change.
|
||||
</p>
|
||||
|
|
|
|||
|
|
@ -1,455 +0,0 @@
|
|||
<!--{
|
||||
"Title": "Pre-Go 1 Release History"
|
||||
}-->
|
||||
|
||||
<p>
|
||||
This page summarizes the changes between stable releases of Go prior to Go 1.
|
||||
See the <a href="release.html">Release History</a> page for notes on recent releases.
|
||||
</p>
|
||||
|
||||
<h2 id="r60">r60 (released 2011/09/07)</h2>
|
||||
|
||||
<p>
|
||||
The r60 release corresponds to
|
||||
<code><a href="weekly.html#2011-08-17">weekly.2011-08-17</a></code>.
|
||||
This section highlights the most significant changes in this release.
|
||||
For a more detailed summary, see the
|
||||
<a href="weekly.html#2011-08-17">weekly release notes</a>.
|
||||
For complete information, see the
|
||||
<a href="//code.google.com/p/go/source/list?r=release-branch.r60">Mercurial change list</a>.
|
||||
</p>
|
||||
|
||||
<h3 id="r60.lang">Language</h3>
|
||||
|
||||
<p>
|
||||
An "else" block is now required to have braces except if the body of the "else"
|
||||
is another "if". Since gofmt always puts those braces in anyway,
|
||||
gofmt-formatted programs will not be affected.
|
||||
To fix other programs, run gofmt.
|
||||
</p>
|
||||
|
||||
<h3 id="r60.pkg">Packages</h3>
|
||||
|
||||
<p>
|
||||
<a href="/pkg/http/">Package http</a>'s URL parsing and query escaping code
|
||||
(such as <code>ParseURL</code> and <code>URLEscape</code>) has been moved to
|
||||
the new <a href="/pkg/url/">url package</a>, with several simplifications to
|
||||
the names. Client code can be updated automatically with gofix.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="/pkg/image/">Package image</a> has had significant changes made to the
|
||||
<code>Pix</code> field of struct types such as
|
||||
<a href="/pkg/image/#RGBA">image.RGBA</a> and
|
||||
<a href="/pkg/image/#NRGBA">image.NRGBA</a>.
|
||||
The <a href="/pkg/image/#Image">image.Image</a> interface type has not changed,
|
||||
though, and you should not need to change your code if you don't explicitly
|
||||
refer to <code>Pix</code> fields. For example, if you decode a number of images
|
||||
using the <a href="/pkg/image/jpeg/">image/jpeg</a> package, compose them using
|
||||
<a href="/pkg/image/draw/">image/draw</a>, and then encode the result using
|
||||
<a href="/pkg/img/png">image/png</a>, then your code should still work as
|
||||
before.
|
||||
If your code <i>does</i> refer to <code>Pix</code> fields see the
|
||||
<a href="/doc/devel/weekly.html#2011-07-19">weekly.2011-07-19</a>
|
||||
snapshot notes for how to update your code.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="/pkg/template/">Package template</a> has been replaced with a new
|
||||
templating package (formerly <code>exp/template</code>). The original template
|
||||
package is still available as <a href="/pkg/old/template/">old/template</a>.
|
||||
The <code>old/template</code> package is deprecated and will be removed.
|
||||
The Go tree has been updated to use the new template package. We encourage
|
||||
users of the old template package to switch to the new one. Code that uses
|
||||
<code>template</code> or <code>exp/template</code> will need to change its
|
||||
import lines to <code>"old/template"</code> or <code>"template"</code>,
|
||||
respectively.
|
||||
</p>
|
||||
|
||||
<h3 id="r60.cmd">Tools</h3>
|
||||
|
||||
<p>
|
||||
<a href="/cmd/goinstall/">Goinstall</a> now uses a new tag selection scheme.
|
||||
When downloading or updating, goinstall looks for a tag or branch with the
|
||||
<code>"go."</code> prefix that corresponds to the local Go version. For Go
|
||||
<code>release.r58</code> it looks for <code>go.r58</code>. For
|
||||
<code>weekly.2011-06-03</code> it looks for <code>go.weekly.2011-06-03</code>.
|
||||
If the specific <code>go.X</code> tag or branch is not found, it chooses the
|
||||
closest earlier version. If an appropriate tag or branch is found, goinstall
|
||||
uses that version of the code. Otherwise it uses the default version selected
|
||||
by the version control system. Library authors are encouraged to use the
|
||||
appropriate tag or branch names in their repositories to make their libraries
|
||||
more accessible.
|
||||
</p>
|
||||
|
||||
<h3 id="r60.minor">Minor revisions</h3>
|
||||
|
||||
<p>
|
||||
r60.1 includes a
|
||||
<a href="//golang.org/change/1824581bf62d">linker
|
||||
fix</a>, a pair of
|
||||
<a href="//golang.org/change/9ef4429c2c64">goplay</a>
|
||||
<a href="//golang.org/change/d42ed8c3098e">fixes</a>,
|
||||
and a <code>json</code> package
|
||||
<a href="//golang.org/change/d5e97874fe84">fix</a> and
|
||||
a new
|
||||
<a href="//golang.org/change/4f0e6269213f">struct tag
|
||||
option</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
r60.2
|
||||
<a href="//golang.org/change/ff19536042ac">fixes</a>
|
||||
a memory leak involving maps.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
r60.3 fixes a
|
||||
<a href="//golang.org/change/01fa62f5e4e5">reflect bug</a>.
|
||||
</p>
|
||||
|
||||
<h2 id="r59">r59 (released 2011/08/01)</h2>
|
||||
|
||||
<p>
|
||||
The r59 release corresponds to
|
||||
<code><a href="weekly.html#2011-07-07">weekly.2011-07-07</a></code>.
|
||||
This section highlights the most significant changes in this release.
|
||||
For a more detailed summary, see the
|
||||
<a href="weekly.html#2011-07-07">weekly release notes</a>.
|
||||
For complete information, see the
|
||||
<a href="//code.google.com/p/go/source/list?r=release-branch.r59">Mercurial change list</a>.
|
||||
</p>
|
||||
|
||||
<h3 id="r59.lang">Language</h3>
|
||||
|
||||
<p>
|
||||
This release includes a language change that restricts the use of
|
||||
<code>goto</code>. In essence, a <code>goto</code> statement outside a block
|
||||
cannot jump to a label inside that block. Your code may require changes if it
|
||||
uses <code>goto</code>.
|
||||
See <a href="//golang.org/change/dc6d3cf9279d">this
|
||||
changeset</a> for how the new rule affected the Go tree.
|
||||
</p>
|
||||
|
||||
<h3 id="r59.pkg">Packages</h3>
|
||||
|
||||
<p>
|
||||
As usual, <a href="/cmd/gofix/">gofix</a> will handle the bulk of the rewrites
|
||||
necessary for these changes to package APIs.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="/pkg/http">Package http</a> has a new
|
||||
<a href="/pkg/http/#FileSystem">FileSystem</a> interface that provides access
|
||||
to files. The <a href="/pkg/http/#FileServer">FileServer</a> helper now takes a
|
||||
<code>FileSystem</code> argument instead of an explicit file system root. By
|
||||
implementing your own <code>FileSystem</code> you can use the
|
||||
<code>FileServer</code> to serve arbitrary data.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="/pkg/os/">Package os</a>'s <code>ErrorString</code> type has been
|
||||
hidden. Most uses of <code>os.ErrorString</code> can be replaced with
|
||||
<a href="/pkg/os/#NewError">os.NewError</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="/pkg/reflect/">Package reflect</a> supports a new struct tag scheme
|
||||
that enables sharing of struct tags between multiple packages.
|
||||
In this scheme, the tags must be of the form:
|
||||
</p>
|
||||
<pre>
|
||||
`key:"value" key2:"value2"`
|
||||
</pre>
|
||||
<p>
|
||||
The <a href="/pkg/reflect/#StructField">StructField</a> type's Tag field now
|
||||
has type <a href="/pkg/reflect/#StructTag">StructTag</a>, which has a
|
||||
<code>Get</code> method. Clients of <a href="/pkg/json">json</a> and
|
||||
<a href="/pkg/xml">xml</a> will need to be updated. Code that says
|
||||
</p>
|
||||
<pre>
|
||||
type T struct {
|
||||
X int "name"
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
should become
|
||||
</p>
|
||||
<pre>
|
||||
type T struct {
|
||||
X int `json:"name"` // or `xml:"name"`
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
Use <a href="/cmd/govet/">govet</a> to identify struct tags that need to be
|
||||
changed to use the new syntax.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="/pkg/sort/">Package sort</a>'s <code>IntArray</code> type has been
|
||||
renamed to <a href="/pkg/sort/#IntSlice">IntSlice</a>, and similarly for
|
||||
<a href="/pkg/sort/#Float64Slice">Float64Slice</a> and
|
||||
<a href="/pkg/sort/#StringSlice">StringSlice</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="/pkg/strings/">Package strings</a>'s <code>Split</code> function has
|
||||
itself been split into <a href="/pkg/strings/#Split">Split</a> and
|
||||
<a href="/pkg/strings/#SplitN">SplitN</a>.
|
||||
<code>SplitN</code> is the same as the old <code>Split</code>.
|
||||
The new <code>Split</code> is equivalent to <code>SplitN</code> with a final
|
||||
argument of -1.
|
||||
</p>
|
||||
|
||||
<a href="/pkg/image/draw/">Package image/draw</a>'s
|
||||
<a href="/pkg/image/draw/#Draw">Draw</a> function now takes an additional
|
||||
argument, a compositing operator.
|
||||
If in doubt, use <a href="/pkg/image/draw/#Op">draw.Over</a>.
|
||||
</p>
|
||||
|
||||
<h3 id="r59.cmd">Tools</h3>
|
||||
|
||||
<p>
|
||||
<a href="/cmd/goinstall/">Goinstall</a> now installs packages and commands from
|
||||
arbitrary remote repositories (not just Google Code, Github, and so on).
|
||||
See the <a href="/cmd/goinstall/">goinstall documentation</a> for details.
|
||||
</p>
|
||||
|
||||
<h2 id="r58">r58 (released 2011/06/29)</h2>
|
||||
|
||||
<p>
|
||||
The r58 release corresponds to
|
||||
<code><a href="weekly.html#2011-06-09">weekly.2011-06-09</a></code>
|
||||
with additional bug fixes.
|
||||
This section highlights the most significant changes in this release.
|
||||
For a more detailed summary, see the
|
||||
<a href="weekly.html#2011-06-09">weekly release notes</a>.
|
||||
For complete information, see the
|
||||
<a href="//code.google.com/p/go/source/list?r=release-branch.r58">Mercurial change list</a>.
|
||||
</p>
|
||||
|
||||
<h3 id="r58.lang">Language</h3>
|
||||
|
||||
<p>
|
||||
This release fixes a <a href="//golang.org/change/b720749486e1">use of uninitialized memory in programs that misuse <code>goto</code></a>.
|
||||
</p>
|
||||
|
||||
<h3 id="r58.pkg">Packages</h3>
|
||||
|
||||
<p>
|
||||
As usual, <a href="/cmd/gofix/">gofix</a> will handle the bulk of the rewrites
|
||||
necessary for these changes to package APIs.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="/pkg/http/">Package http</a> drops the <code>finalURL</code> return
|
||||
value from the <a href="/pkg/http/#Client.Get">Client.Get</a> method. The value
|
||||
is now available via the new <code>Request</code> field on <a
|
||||
href="/pkg/http/#Response">http.Response</a>.
|
||||
Most instances of the type map[string][]string in have been
|
||||
replaced with the new <a href="/pkg/http/#Values">Values</a> type.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="/pkg/exec/">Package exec</a> has been redesigned with a more
|
||||
convenient and succinct API.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="/pkg/strconv/">Package strconv</a>'s <a href="/pkg/strconv/#Quote">Quote</a>
|
||||
function now escapes only those Unicode code points not classified as printable
|
||||
by <a href="/pkg/unicode/#IsPrint">unicode.IsPrint</a>.
|
||||
Previously Quote would escape all non-ASCII characters.
|
||||
This also affects the <a href="/pkg/fmt/">fmt</a> package's <code>"%q"</code>
|
||||
formatting directive. The previous quoting behavior is still available via
|
||||
strconv's new <a href="/pkg/strconv/#QuoteToASCII">QuoteToASCII</a> function.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="/pkg/os/signal/">Package os/signal</a>'s
|
||||
<a href="/pkg/os/#Signal">Signal</a> and
|
||||
<a href="/pkg/os/#UnixSignal">UnixSignal</a> types have been moved to the
|
||||
<a href="/pkg/os/">os</a> package.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="/pkg/image/draw/">Package image/draw</a> is the new name for
|
||||
<code>exp/draw</code>. The GUI-related code from <code>exp/draw</code> is now
|
||||
located in the <a href="/pkg/exp/gui/">exp/gui</a> package.
|
||||
</p>
|
||||
|
||||
<h3 id="r58.cmd">Tools</h3>
|
||||
|
||||
<p>
|
||||
<a href="/cmd/goinstall/">Goinstall</a> now observes the GOPATH environment
|
||||
variable to build and install your own code and external libraries outside of
|
||||
the Go tree (and avoid writing Makefiles).
|
||||
</p>
|
||||
|
||||
|
||||
<h3 id="r58.minor">Minor revisions</h3>
|
||||
|
||||
<p>r58.1 adds
|
||||
<a href="//golang.org/change/293c25943586">build</a> and
|
||||
<a href="//golang.org/change/bf17e96b6582">runtime</a>
|
||||
changes to make Go run on OS X 10.7 Lion.
|
||||
</p>
|
||||
|
||||
<h2 id="r57">r57 (released 2011/05/03)</h2>
|
||||
|
||||
<p>
|
||||
The r57 release corresponds to
|
||||
<code><a href="weekly.html#2011-04-27">weekly.2011-04-27</a></code>
|
||||
with additional bug fixes.
|
||||
This section highlights the most significant changes in this release.
|
||||
For a more detailed summary, see the
|
||||
<a href="weekly.html#2011-04-27">weekly release notes</a>.
|
||||
For complete information, see the
|
||||
<a href="//code.google.com/p/go/source/list?r=release-branch.r57">Mercurial change list</a>.
|
||||
</p>
|
||||
|
||||
<p>The new <a href="/cmd/gofix">gofix</a> tool finds Go programs that use old APIs and rewrites them to use
|
||||
newer ones. After you update to a new Go release, gofix helps make the
|
||||
necessary changes to your programs. Gofix will handle the http, os, and syscall
|
||||
package changes described below, and we will update the program to keep up with
|
||||
future changes to the libraries.
|
||||
Gofix can’t
|
||||
handle all situations perfectly, so read and test the changes it makes before
|
||||
committing them.
|
||||
See <a href="//blog.golang.org/2011/04/introducing-gofix.html">the gofix blog post</a> for more
|
||||
information.</p>
|
||||
|
||||
<h3 id="r57.lang">Language</h3>
|
||||
|
||||
<p>
|
||||
<a href="/doc/go_spec.html#Receive_operator">Multiple assignment syntax</a> replaces the <code>closed</code> function.
|
||||
The syntax for channel
|
||||
receives allows an optional second assigned value, a boolean value
|
||||
indicating whether the channel is closed. This code:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
v := <-ch
|
||||
if closed(ch) {
|
||||
// channel is closed
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>should now be written as:</p>
|
||||
|
||||
<pre>
|
||||
v, ok := <-ch
|
||||
if !ok {
|
||||
// channel is closed
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p><a href="/doc/go_spec.html#Label_scopes">Unused labels are now illegal</a>, just as unused local variables are.</p>
|
||||
|
||||
<h3 id="r57.pkg">Packages</h3>
|
||||
|
||||
<p>
|
||||
<a href="/pkg/gob/">Package gob</a> will now encode and decode values of types that implement the
|
||||
<a href="/pkg/gob/#GobEncoder">GobEncoder</a> and
|
||||
<a href="/pkg/gob/#GobDecoder">GobDecoder</a> interfaces. This allows types with unexported
|
||||
fields to transmit self-consistent descriptions; examples include
|
||||
<a href="/pkg/big/#Int.GobDecode">big.Int</a> and <a href="/pkg/big/#Rat.GobDecode">big.Rat</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="/pkg/http/">Package http</a> has been redesigned.
|
||||
For clients, there are new
|
||||
<a href="/pkg/http/#Client">Client</a> and <a href="/pkg/http/#Transport">Transport</a>
|
||||
abstractions that give more control over HTTP details such as headers sent
|
||||
and redirections followed. These abstractions make it easy to implement
|
||||
custom clients that add functionality such as <a href="//code.google.com/p/goauth2/source/browse/oauth/oauth.go">OAuth2</a>.
|
||||
For servers, <a href="/pkg/http/#ResponseWriter">ResponseWriter</a>
|
||||
has dropped its non-essential methods.
|
||||
The Hijack and Flush methods are no longer required;
|
||||
code can test for them by checking whether a specific value implements
|
||||
<a href="/pkg/http/#Hijacker">Hijacker</a> or <a href="/pkg/http/#Flusher">Flusher</a>.
|
||||
The RemoteAddr and UsingTLS methods are replaced by <a href="/pkg/http/#Request">Request</a>'s
|
||||
RemoteAddr and TLS fields.
|
||||
The SetHeader method is replaced by a Header method;
|
||||
its result, of type <a href="/pkg/http/#Header">Header</a>,
|
||||
implements Set and other methods.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="/pkg/net/">Package net</a>
|
||||
drops the <code>laddr</code> argument from <a href="/pkg/net/#Conn.Dial">Dial</a>
|
||||
and drops the <code>cname</code> return value
|
||||
from <a href="/pkg/net/#LookupHost">LookupHost</a>.
|
||||
The implementation now uses <a href="/cmd/cgo/">cgo</a> to implement
|
||||
network name lookups using the C library getaddrinfo(3)
|
||||
function when possible. This ensures that Go and C programs
|
||||
resolve names the same way and also avoids the OS X
|
||||
application-level firewall.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="/pkg/os/">Package os</a>
|
||||
introduces simplified <a href="/pkg/os/#File.Open">Open</a>
|
||||
and <a href="/pkg/os/#File.Create">Create</a> functions.
|
||||
The original Open is now available as <a href="/pkg/os/#File.OpenFile">OpenFile</a>.
|
||||
The final three arguments to <a href="/pkg/os/#Process.StartProcess">StartProcess</a>
|
||||
have been replaced by a pointer to a <a href="/pkg/os/#ProcAttr">ProcAttr</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="/pkg/reflect/">Package reflect</a> has been redesigned.
|
||||
<a href="/pkg/reflect/#Type">Type</a> is now an interface that implements
|
||||
all the possible type methods.
|
||||
Instead of a type switch on a Type <code>t</code>, switch on <code>t.Kind()</code>.
|
||||
<a href="/pkg/reflect/#Value">Value</a> is now a struct value that
|
||||
implements all the possible value methods.
|
||||
Instead of a type switch on a Value <code>v</code>, switch on <code>v.Kind()</code>.
|
||||
Typeof and NewValue are now called <a href="/pkg/reflect/#Type.TypeOf">TypeOf</a> and <a href="/pkg/reflect/#Value.ValueOf">ValueOf</a>
|
||||
To create a writable Value, use <code>New(t).Elem()</code> instead of <code>Zero(t)</code>.
|
||||
See <a href="//golang.org/change/843855f3c026">the change description</a>
|
||||
for the full details.
|
||||
The new API allows a more efficient implementation of Value
|
||||
that avoids many of the allocations required by the previous API.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Remember that gofix will handle the bulk of the rewrites
|
||||
necessary for these changes to package APIs.
|
||||
</p>
|
||||
|
||||
<h3 id="r57.cmd">Tools</h3>
|
||||
|
||||
<p><a href="/cmd/gofix/">Gofix</a>, a new command, is described above.</p>
|
||||
|
||||
<p>
|
||||
<a href="/cmd/gotest/">Gotest</a> is now a Go program instead of a shell script.
|
||||
The new <code>-test.short</code> flag in combination with package testing's Short function
|
||||
allows you to write tests that can be run in normal or “short” mode;
|
||||
all.bash runs tests in short mode to reduce installation time.
|
||||
The Makefiles know about the flag: use <code>make testshort</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The run-time support now implements CPU and memory profiling.
|
||||
Gotest's new
|
||||
<a href="/cmd/gotest/"><code>-test.cpuprofile</code> and
|
||||
<code>-test.memprofile</code> flags</a> make it easy to
|
||||
profile tests.
|
||||
To add profiling to your web server, see the <a href="/pkg/http/pprof/">http/pprof</a>
|
||||
documentation.
|
||||
For other uses, see the <a href="/pkg/runtime/pprof/">runtime/pprof</a> documentation.
|
||||
</p>
|
||||
|
||||
<h3 id="r57.minor">Minor revisions</h3>
|
||||
|
||||
<p>r57.1 fixes a <a href="//golang.org/change/ff2bc62726e7145eb2ecc1e0f076998e4a8f86f0">nil pointer dereference in http.FormFile</a>.</p>
|
||||
<p>r57.2 fixes a <a href="//golang.org/change/063b0ff67d8277df03c956208abc068076818dae">use of uninitialized memory in programs that misuse <code>goto</code></a>.</p>
|
||||
|
||||
<h2 id="r56">r56 (released 2011/03/16)</h2>
|
||||
|
||||
<p>
|
||||
The r56 release was the first stable release and corresponds to
|
||||
<code><a href="weekly.html#2011-03-07">weekly.2011-03-07.1</a></code>.
|
||||
The numbering starts at 56 because before this release,
|
||||
what we now consider weekly snapshots were called releases.
|
||||
</p>
|
||||
|
|
@ -1,745 +0,0 @@
|
|||
<!--{
|
||||
"Title": "Release History"
|
||||
}-->
|
||||
|
||||
<p>This page summarizes the changes between official stable releases of Go.
|
||||
The <a href="//golang.org/change">change log</a> has the full details.</p>
|
||||
|
||||
<p>To update to a specific release, use:</p>
|
||||
|
||||
<pre>
|
||||
git pull
|
||||
git checkout <i>release-branch</i>
|
||||
</pre>
|
||||
|
||||
<h2 id="policy">Release Policy</h2>
|
||||
|
||||
<p>
|
||||
Each major Go release is supported until there are two newer major releases.
|
||||
For example, Go 1.5 was supported until the Go 1.7 release, and Go 1.6 was
|
||||
supported until the Go 1.8 release.
|
||||
We fix critical problems, including <a href="/security">critical security problems</a>,
|
||||
in supported releases as needed by issuing minor revisions
|
||||
(for example, Go 1.6.1, Go 1.6.2, and so on).
|
||||
</p>
|
||||
|
||||
<h2 id="go1.13">go1.13 (released 2019/09/03)</h2>
|
||||
|
||||
<p>
|
||||
Go 1.13 is a major release of Go.
|
||||
Read the <a href="/doc/go1.13">Go 1.13 Release Notes</a> for more information.
|
||||
</p>
|
||||
|
||||
<h3 id="go1.13.minor">Minor revisions</h3>
|
||||
|
||||
<p>
|
||||
go1.13.1 (released 2019/09/25) includes security fixes to the
|
||||
<code>net/http</code> and <code>net/textproto</code> packages.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.13.1">Go
|
||||
1.13.1 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.13.2 (released 2019/10/17) includes security fixes to the
|
||||
<code>crypto/dsa</code> package and the compiler.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.13.2">Go
|
||||
1.13.2 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.13.3 (released 2019/10/17) includes fixes to the go command,
|
||||
the toolchain, the runtime, <code>syscall</code>, <code>net</code>,
|
||||
<code>net/http</code>, and <code>crypto/ecdsa</code> packages.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.13.3">Go
|
||||
1.13.3 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.13.4 (released 2019/10/31) includes fixes to the <code>net/http</code> and
|
||||
<code>syscall</code> packages. It also fixes an issue on macOS 10.15 Catalina
|
||||
where the non-notarized installer and binaries were being
|
||||
<a href="https://golang.org/issue/34986">rejected by Gatekeeper</a>.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.13.4">Go
|
||||
1.13.4 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<h2 id="go1.12">go1.12 (released 2019/02/25)</h2>
|
||||
|
||||
<p>
|
||||
Go 1.12 is a major release of Go.
|
||||
Read the <a href="/doc/go1.12">Go 1.12 Release Notes</a> for more information.
|
||||
</p>
|
||||
|
||||
<h3 id="go1.12.minor">Minor revisions</h3>
|
||||
|
||||
<p>
|
||||
go1.12.1 (released 2019/03/14) includes fixes to cgo, the compiler, the go
|
||||
command, and the <code>fmt</code>, <code>net/smtp</code>, <code>os</code>,
|
||||
<code>path/filepath</code>, <code>sync</code>, and <code>text/template</code>
|
||||
packages. See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.12.1">Go
|
||||
1.12.1 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.12.2 (released 2019/04/05) includes fixes to the compiler, the go
|
||||
command, the runtime, and the <code>doc</code>, <code>net</code>,
|
||||
<code>net/http/httputil</code>, and <code>os</code> packages. See the
|
||||
<a href="https://github.com/golang/go/issues?q=milestone%3AGo1.12.2">Go
|
||||
1.12.2 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.12.3 (released 2019/04/08) was accidentally released without its
|
||||
intended fix. It is identical to go1.12.2, except for its version
|
||||
number. The intended fix is in go1.12.4.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.12.4 (released 2019/04/11) fixes an issue where using the prebuilt binary
|
||||
releases on older versions of GNU/Linux
|
||||
<a href="https://golang.org/issues/31293">led to failures</a>
|
||||
when linking programs that used cgo.
|
||||
Only Linux users who hit this issue need to update.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.12.5 (released 2019/05/06) includes fixes to the compiler, the linker,
|
||||
the go command, the runtime, and the <code>os</code> package. See the
|
||||
<a href="https://github.com/golang/go/issues?q=milestone%3AGo1.12.5">Go
|
||||
1.12.5 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.12.6 (released 2019/06/11) includes fixes to the compiler, the linker,
|
||||
the go command, and the <code>crypto/x509</code>, <code>net/http</code>, and
|
||||
<code>os</code> packages. See the
|
||||
<a href="https://github.com/golang/go/issues?q=milestone%3AGo1.12.6">Go
|
||||
1.12.6 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.12.7 (released 2019/07/08) includes fixes to cgo, the compiler,
|
||||
and the linker.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.12.7">Go
|
||||
1.12.7 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.12.8 (released 2019/08/13) includes security fixes to the
|
||||
<code>net/http</code> and <code>net/url</code> packages.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.12.8">Go
|
||||
1.12.8 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.12.9 (released 2019/08/15) includes fixes to the linker,
|
||||
and the <code>os</code> and <code>math/big</code> packages.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.12.9+label%3ACherryPickApproved">Go
|
||||
1.12.9 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.12.10 (released 2019/09/25) includes security fixes to the
|
||||
<code>net/http</code> and <code>net/textproto</code> packages.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.12.10">Go
|
||||
1.12.10 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.12.11 (released 2019/10/17) includes security fixes to the
|
||||
<code>crypto/dsa</code> package.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.12.11">Go
|
||||
1.12.11 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.12.12 (released 2019/10/17) includes fixes to the go command,
|
||||
runtime, <code>syscall</code> and <code>net</code> packages.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.12.12">Go
|
||||
1.12.12 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.12.13 (released 2019/10/31) fixes an issue on macOS 10.15 Catalina
|
||||
where the non-notarized installer and binaries were being
|
||||
<a href="https://golang.org/issue/34986">rejected by Gatekeeper</a>.
|
||||
Only macOS users who hit this issue need to update.
|
||||
</p>
|
||||
|
||||
<h2 id="go1.11">go1.11 (released 2018/08/24)</h2>
|
||||
|
||||
<p>
|
||||
Go 1.11 is a major release of Go.
|
||||
Read the <a href="/doc/go1.11">Go 1.11 Release Notes</a> for more information.
|
||||
</p>
|
||||
|
||||
<h3 id="go1.11.minor">Minor revisions</h3>
|
||||
|
||||
<p>
|
||||
go1.11.1 (released 2018/10/01) includes fixes to the compiler, documentation, go
|
||||
command, runtime, and the <code>crypto/x509</code>, <code>encoding/json</code>,
|
||||
<code>go/types</code>, <code>net</code>, <code>net/http</code>, and
|
||||
<code>reflect</code> packages.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.1">Go
|
||||
1.11.1 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.11.2 (released 2018/11/02) includes fixes to the compiler, linker,
|
||||
documentation, go command, and the <code>database/sql</code> and
|
||||
<code>go/types</code> packages.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.2">Go
|
||||
1.11.2 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.11.3 (released 2018/12/12) includes three security fixes to "go get" and
|
||||
the <code>crypto/x509</code> package.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.3">Go
|
||||
1.11.3 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.11.4 (released 2018/12/14) includes fixes to cgo, the compiler, linker,
|
||||
runtime, documentation, go command, and the <code>net/http</code> and
|
||||
<code>go/types</code> packages.
|
||||
It includes a fix to a bug introduced in Go 1.11.3 that broke <code>go</code>
|
||||
<code>get</code> for import path patterns containing "<code>...</code>".
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.4+label%3ACherryPickApproved">Go
|
||||
1.11.4 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.11.5 (released 2019/01/23) includes a security fix to the
|
||||
<code>crypto/elliptic</code> package. See
|
||||
the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.5">Go
|
||||
1.11.5 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.11.6 (released 2019/03/14) includes fixes to cgo, the compiler, linker,
|
||||
runtime, go command, and the <code>crypto/x509</code>, <code>encoding/json</code>,
|
||||
<code>net</code>, and <code>net/url</code> packages. See the
|
||||
<a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.6">Go
|
||||
1.11.6 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.11.7 (released 2019/04/05) includes fixes to the runtime and the
|
||||
<code>net</code> packages. See the
|
||||
<a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.7">Go
|
||||
1.11.7 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.11.8 (released 2019/04/08) was accidentally released without its
|
||||
intended fix. It is identical to go1.11.7, except for its version
|
||||
number. The intended fix is in go1.11.9.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.11.9 (released 2019/04/11) fixes an issue where using the prebuilt binary
|
||||
releases on older versions of GNU/Linux
|
||||
<a href="https://golang.org/issues/31293">led to failures</a>
|
||||
when linking programs that used cgo.
|
||||
Only Linux users who hit this issue need to update.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.11.10 (released 2019/05/06) includes fixes to the runtime and the linker.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.10">Go
|
||||
1.11.10 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.11.11 (released 2019/06/11) includes a fix to the <code>crypto/x509</code> package.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.11">Go
|
||||
1.11.11 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.11.12 (released 2019/07/08) includes fixes to the compiler and the linker.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.12">Go
|
||||
1.11.12 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.11.13 (released 2019/08/13) includes security fixes to the
|
||||
<code>net/http</code> and <code>net/url</code> packages.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.13">Go
|
||||
1.11.13 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<h2 id="go1.10">go1.10 (released 2018/02/16)</h2>
|
||||
|
||||
<p>
|
||||
Go 1.10 is a major release of Go.
|
||||
Read the <a href="/doc/go1.10">Go 1.10 Release Notes</a> for more information.
|
||||
</p>
|
||||
|
||||
<h3 id="go1.10.minor">Minor revisions</h3>
|
||||
|
||||
<p>
|
||||
go1.10.1 (released 2018/03/28) includes fixes to the compiler, runtime, and the
|
||||
<code>archive/zip</code>, <code>crypto/tls</code>, <code>crypto/x509</code>,
|
||||
<code>encoding/json</code>, <code>net</code>, <code>net/http</code>, and
|
||||
<code>net/http/pprof</code> packages.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.10.1">Go
|
||||
1.10.1 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.10.2 (released 2018/05/01) includes fixes to the compiler, linker, and go
|
||||
command.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.10.2">Go
|
||||
1.10.2 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.10.3 (released 2018/06/05) includes fixes to the go command, and the
|
||||
<code>crypto/tls</code>, <code>crypto/x509</code>, and <code>strings</code> packages.
|
||||
In particular, it adds <a href="https://go.googlesource.com/go/+/d4e21288e444d3ffd30d1a0737f15ea3fc3b8ad9">
|
||||
minimal support to the go command for the vgo transition</a>.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.10.3">Go
|
||||
1.10.3 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.10.4 (released 2018/08/24) includes fixes to the go command, linker, and the
|
||||
<code>net/http</code>, <code>mime/multipart</code>, <code>ld/macho</code>,
|
||||
<code>bytes</code>, and <code>strings</code> packages.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.10.4">Go
|
||||
1.10.4 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.10.5 (released 2018/11/02) includes fixes to the go command, linker, runtime
|
||||
and the <code>database/sql</code> package.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.10.5">Go
|
||||
1.10.5 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.10.6 (released 2018/12/12) includes three security fixes to "go get" and
|
||||
the <code>crypto/x509</code> package.
|
||||
It contains the same fixes as Go 1.11.3 and was released at the same time.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.10.6">Go
|
||||
1.10.6 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.10.7 (released 2018/12/14) includes a fix to a bug introduced in Go 1.10.6
|
||||
that broke <code>go</code> <code>get</code> for import path patterns containing
|
||||
"<code>...</code>".
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.10.7+label%3ACherryPickApproved">
|
||||
Go 1.10.7 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.10.8 (released 2019/01/23) includes a security fix to the
|
||||
<code>crypto/elliptic</code> package. See
|
||||
the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.10.8">Go
|
||||
1.10.8 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<h2 id="go1.9">go1.9 (released 2017/08/24)</h2>
|
||||
|
||||
<p>
|
||||
Go 1.9 is a major release of Go.
|
||||
Read the <a href="/doc/go1.9">Go 1.9 Release Notes</a> for more information.
|
||||
</p>
|
||||
|
||||
<h3 id="go1.9.minor">Minor revisions</h3>
|
||||
|
||||
<p>
|
||||
go1.9.1 (released 2017/10/04) includes two security fixes.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.9.1">Go
|
||||
1.9.1 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.9.2 (released 2017/10/25) includes fixes to the compiler, linker, runtime,
|
||||
documentation, <code>go</code> command,
|
||||
and the <code>crypto/x509</code>, <code>database/sql</code>, <code>log</code>,
|
||||
and <code>net/smtp</code> packages.
|
||||
It includes a fix to a bug introduced in Go 1.9.1 that broke <code>go</code> <code>get</code>
|
||||
of non-Git repositories under certain conditions.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.9.2">Go
|
||||
1.9.2 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.9.3 (released 2018/01/22) includes fixes to the compiler, runtime,
|
||||
and the <code>database/sql</code>, <code>math/big</code>, <code>net/http</code>,
|
||||
and <code>net/url</code> packages.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.9.3">Go
|
||||
1.9.3 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.9.4 (released 2018/02/07) includes a security fix to “go get”.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.9.4">Go
|
||||
1.9.4</a> milestone on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.9.5 (released 2018/03/28) includes fixes to the compiler, go command, and
|
||||
<code>net/http/pprof</code> package.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.9.5">Go
|
||||
1.9.5 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.9.6 (released 2018/05/01) includes fixes to the compiler and go command.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.9.6">Go
|
||||
1.9.6 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.9.7 (released 2018/06/05) includes fixes to the go command, and the
|
||||
<code>crypto/x509</code>, and <code>strings</code> packages.
|
||||
In particular, it adds <a href="https://go.googlesource.com/go/+/d4e21288e444d3ffd30d1a0737f15ea3fc3b8ad9">
|
||||
minimal support to the go command for the vgo transition</a>.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.9.7">Go
|
||||
1.9.7 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
|
||||
<h2 id="go1.8">go1.8 (released 2017/02/16)</h2>
|
||||
|
||||
<p>
|
||||
Go 1.8 is a major release of Go.
|
||||
Read the <a href="/doc/go1.8">Go 1.8 Release Notes</a> for more information.
|
||||
</p>
|
||||
|
||||
<h3 id="go1.8.minor">Minor revisions</h3>
|
||||
|
||||
<p>
|
||||
go1.8.1 (released 2017/04/07) includes fixes to the compiler, linker, runtime,
|
||||
documentation, <code>go</code> command and the <code>crypto/tls</code>,
|
||||
<code>encoding/xml</code>, <code>image/png</code>, <code>net</code>,
|
||||
<code>net/http</code>, <code>reflect</code>, <code>text/template</code>,
|
||||
and <code>time</code> packages.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.8.1">Go
|
||||
1.8.1 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.8.2 (released 2017/05/23) includes a security fix to the
|
||||
<code>crypto/elliptic</code> package.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.8.2">Go
|
||||
1.8.2 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.8.3 (released 2017/05/24) includes fixes to the compiler, runtime,
|
||||
documentation, and the <code>database/sql</code> package.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.8.3">Go
|
||||
1.8.3 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.8.4 (released 2017/10/04) includes two security fixes.
|
||||
It contains the same fixes as Go 1.9.1 and was released at the same time.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.8.4">Go
|
||||
1.8.4 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.8.5 (released 2017/10/25) includes fixes to the compiler, linker, runtime,
|
||||
documentation, <code>go</code> command,
|
||||
and the <code>crypto/x509</code> and <code>net/smtp</code> packages.
|
||||
It includes a fix to a bug introduced in Go 1.8.4 that broke <code>go</code> <code>get</code>
|
||||
of non-Git repositories under certain conditions.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.8.5">Go
|
||||
1.8.5 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.8.6 (released 2018/01/22) includes the same fix in <code>math/big</code>
|
||||
as Go 1.9.3 and was released at the same time.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.8.6">Go
|
||||
1.8.6 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.8.7 (released 2018/02/07) includes a security fix to “go get”.
|
||||
It contains the same fix as Go 1.9.4 and was released at the same time.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.8.7">Go
|
||||
1.8.7</a> milestone on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<h2 id="go1.7">go1.7 (released 2016/08/15)</h2>
|
||||
|
||||
<p>
|
||||
Go 1.7 is a major release of Go.
|
||||
Read the <a href="/doc/go1.7">Go 1.7 Release Notes</a> for more information.
|
||||
</p>
|
||||
|
||||
<h3 id="go1.7.minor">Minor revisions</h3>
|
||||
|
||||
<p>
|
||||
go1.7.1 (released 2016/09/07) includes fixes to the compiler, runtime,
|
||||
documentation, and the <code>compress/flate</code>, <code>hash/crc32</code>,
|
||||
<code>io</code>, <code>net</code>, <code>net/http</code>,
|
||||
<code>path/filepath</code>, <code>reflect</code>, and <code>syscall</code>
|
||||
packages.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.7.1">Go
|
||||
1.7.1 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.7.2 should not be used. It was tagged but not fully released.
|
||||
The release was deferred due to a last minute bug report.
|
||||
Use go1.7.3 instead, and refer to the summary of changes below.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.7.3 (released 2016/10/19) includes fixes to the compiler, runtime,
|
||||
and the <code>crypto/cipher</code>, <code>crypto/tls</code>,
|
||||
<code>net/http</code>, and <code>strings</code> packages.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.7.3">Go
|
||||
1.7.3 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.7.4 (released 2016/12/01) includes two security fixes.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.7.4">Go
|
||||
1.7.4 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.7.5 (released 2017/01/26) includes fixes to the compiler, runtime,
|
||||
and the <code>crypto/x509</code> and <code>time</code> packages.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.7.5">Go
|
||||
1.7.5 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.7.6 (released 2017/05/23) includes the same security fix as Go 1.8.2 and
|
||||
was released at the same time.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.8.2">Go
|
||||
1.8.2 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<h2 id="go1.6">go1.6 (released 2016/02/17)</h2>
|
||||
|
||||
<p>
|
||||
Go 1.6 is a major release of Go.
|
||||
Read the <a href="/doc/go1.6">Go 1.6 Release Notes</a> for more information.
|
||||
</p>
|
||||
|
||||
<h3 id="go1.6.minor">Minor revisions</h3>
|
||||
|
||||
<p>
|
||||
go1.6.1 (released 2016/04/12) includes two security fixes.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.6.1">Go
|
||||
1.6.1 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.6.2 (released 2016/04/20) includes fixes to the compiler, runtime, tools,
|
||||
documentation, and the <code>mime/multipart</code>, <code>net/http</code>, and
|
||||
<code>sort</code> packages.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.6.2">Go
|
||||
1.6.2 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.6.3 (released 2016/07/17) includes security fixes to the
|
||||
<code>net/http/cgi</code> package and <code>net/http</code> package when used in
|
||||
a CGI environment.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.6.3">Go
|
||||
1.6.3 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.6.4 (released 2016/12/01) includes two security fixes.
|
||||
It contains the same fixes as Go 1.7.4 and was released at the same time.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.7.4">Go
|
||||
1.7.4 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<h2 id="go1.5">go1.5 (released 2015/08/19)</h2>
|
||||
|
||||
<p>
|
||||
Go 1.5 is a major release of Go.
|
||||
Read the <a href="/doc/go1.5">Go 1.5 Release Notes</a> for more information.
|
||||
</p>
|
||||
|
||||
<h3 id="go1.5.minor">Minor revisions</h3>
|
||||
|
||||
<p>
|
||||
go1.5.1 (released 2015/09/08) includes bug fixes to the compiler, assembler, and
|
||||
the <code>fmt</code>, <code>net/textproto</code>, <code>net/http</code>, and
|
||||
<code>runtime</code> packages.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.5.1">Go
|
||||
1.5.1 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.5.2 (released 2015/12/02) includes bug fixes to the compiler, linker, and
|
||||
the <code>mime/multipart</code>, <code>net</code>, and <code>runtime</code>
|
||||
packages.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.5.2">Go
|
||||
1.5.2 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.5.3 (released 2016/01/13) includes a security fix to the <code>math/big</code> package
|
||||
affecting the <code>crypto/tls</code> package.
|
||||
See the <a href="https://golang.org/s/go153announce">release announcement</a> for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.5.4 (released 2016/04/12) includes two security fixes.
|
||||
It contains the same fixes as Go 1.6.1 and was released at the same time.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.6.1">Go
|
||||
1.6.1 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<h2 id="go1.4">go1.4 (released 2014/12/10)</h2>
|
||||
|
||||
<p>
|
||||
Go 1.4 is a major release of Go.
|
||||
Read the <a href="/doc/go1.4">Go 1.4 Release Notes</a> for more information.
|
||||
</p>
|
||||
|
||||
<h3 id="go1.4.minor">Minor revisions</h3>
|
||||
|
||||
<p>
|
||||
go1.4.1 (released 2015/01/15) includes bug fixes to the linker and the <code>log</code>, <code>syscall</code>, and <code>runtime</code> packages.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.4.1">Go 1.4.1 milestone on our issue tracker</a> for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.4.2 (released 2015/02/17) includes bug fixes to the <code>go</code> command, the compiler and linker, and the <code>runtime</code>, <code>syscall</code>, <code>reflect</code>, and <code>math/big</code> packages.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.4.2">Go 1.4.2 milestone on our issue tracker</a> for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.4.3 (released 2015/09/22) includes security fixes to the <code>net/http</code> package and bug fixes to the <code>runtime</code> package.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.4.3">Go 1.4.3 milestone on our issue tracker</a> for details.
|
||||
</p>
|
||||
|
||||
<h2 id="go1.3">go1.3 (released 2014/06/18)</h2>
|
||||
|
||||
<p>
|
||||
Go 1.3 is a major release of Go.
|
||||
Read the <a href="/doc/go1.3">Go 1.3 Release Notes</a> for more information.
|
||||
</p>
|
||||
|
||||
<h3 id="go1.3.minor">Minor revisions</h3>
|
||||
|
||||
<p>
|
||||
go1.3.1 (released 2014/08/13) includes bug fixes to the compiler and the <code>runtime</code>, <code>net</code>, and <code>crypto/rsa</code> packages.
|
||||
See the <a href="https://github.com/golang/go/commits/go1.3.1">change history</a> for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.3.2 (released 2014/09/25) includes bug fixes to cgo and the crypto/tls packages.
|
||||
See the <a href="https://github.com/golang/go/commits/go1.3.2">change history</a> for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.3.3 (released 2014/09/30) includes further bug fixes to cgo, the runtime package, and the nacl port.
|
||||
See the <a href="https://github.com/golang/go/commits/go1.3.3">change history</a> for details.
|
||||
</p>
|
||||
|
||||
<h2 id="go1.2">go1.2 (released 2013/12/01)</h2>
|
||||
|
||||
<p>
|
||||
Go 1.2 is a major release of Go.
|
||||
Read the <a href="/doc/go1.2">Go 1.2 Release Notes</a> for more information.
|
||||
</p>
|
||||
|
||||
<h3 id="go1.2.minor">Minor revisions</h3>
|
||||
|
||||
<p>
|
||||
go1.2.1 (released 2014/03/02) includes bug fixes to the <code>runtime</code>, <code>net</code>, and <code>database/sql</code> packages.
|
||||
See the <a href="https://github.com/golang/go/commits/go1.2.1">change history</a> for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.2.2 (released 2014/05/05) includes a
|
||||
<a href="https://github.com/golang/go/commits/go1.2.2">security fix</a>
|
||||
that affects the tour binary included in the binary distributions (thanks to Guillaume T).
|
||||
</p>
|
||||
|
||||
<h2 id="go1.1">go1.1 (released 2013/05/13)</h2>
|
||||
|
||||
<p>
|
||||
Go 1.1 is a major release of Go.
|
||||
Read the <a href="/doc/go1.1">Go 1.1 Release Notes</a> for more information.
|
||||
</p>
|
||||
|
||||
<h3 id="go1.1.minor">Minor revisions</h3>
|
||||
|
||||
<p>
|
||||
go1.1.1 (released 2013/06/13) includes several compiler and runtime bug fixes.
|
||||
See the <a href="https://github.com/golang/go/commits/go1.1.1">change history</a> for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.1.2 (released 2013/08/13) includes fixes to the <code>gc</code> compiler
|
||||
and <code>cgo</code>, and the <code>bufio</code>, <code>runtime</code>,
|
||||
<code>syscall</code>, and <code>time</code> packages.
|
||||
See the <a href="https://github.com/golang/go/commits/go1.1.2">change history</a> for details.
|
||||
If you use package syscall's <code>Getrlimit</code> and <code>Setrlimit</code>
|
||||
functions under Linux on the ARM or 386 architectures, please note change
|
||||
<a href="//golang.org/cl/11803043">11803043</a>
|
||||
that fixes <a href="//golang.org/issue/5949">issue 5949</a>.
|
||||
</p>
|
||||
|
||||
<h2 id="go1">go1 (released 2012/03/28)</h2>
|
||||
|
||||
<p>
|
||||
Go 1 is a major release of Go that will be stable in the long term.
|
||||
Read the <a href="/doc/go1.html">Go 1 Release Notes</a> for more information.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
It is intended that programs written for Go 1 will continue to compile and run
|
||||
correctly, unchanged, under future versions of Go 1.
|
||||
Read the <a href="/doc/go1compat.html">Go 1 compatibility document</a> for more
|
||||
about the future of Go 1.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The go1 release corresponds to
|
||||
<code><a href="weekly.html#2012-03-27">weekly.2012-03-27</a></code>.
|
||||
</p>
|
||||
|
||||
<h3 id="go1.minor">Minor revisions</h3>
|
||||
|
||||
<p>
|
||||
go1.0.1 (released 2012/04/25) was issued to
|
||||
<a href="//golang.org/cl/6061043">fix</a> an
|
||||
<a href="//golang.org/issue/3545">escape analysis bug</a>
|
||||
that can lead to memory corruption.
|
||||
It also includes several minor code and documentation fixes.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.0.2 (released 2012/06/13) was issued to fix two bugs in the implementation
|
||||
of maps using struct or array keys:
|
||||
<a href="//golang.org/issue/3695">issue 3695</a> and
|
||||
<a href="//golang.org/issue/3573">issue 3573</a>.
|
||||
It also includes many minor code and documentation fixes.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.0.3 (released 2012/09/21) includes minor code and documentation fixes.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
See the <a href="https://github.com/golang/go/commits/release-branch.go1">go1 release branch history</a> for the complete list of changes.
|
||||
</p>
|
||||
|
||||
<h2 id="pre.go1">Older releases</h2>
|
||||
|
||||
<p>
|
||||
See the <a href="pre_go1.html">Pre-Go 1 Release History</a> page for notes
|
||||
on earlier releases.
|
||||
</p>
|
||||
|
||||
File diff suppressed because it is too large
Load diff
504
doc/go1.14.html
504
doc/go1.14.html
|
|
@ -24,10 +24,30 @@ Do not send CLs removing the interior tags from such phrases.
|
|||
</strong>
|
||||
</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>
|
||||
|
||||
<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>
|
||||
|
||||
<h2 id="ports">Ports</h2>
|
||||
|
|
@ -52,6 +72,11 @@ TODO
|
|||
|
||||
<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 -->
|
||||
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
|
||||
|
|
@ -66,6 +91,49 @@ TODO
|
|||
64-bit <code>darwin/arm64</code> port.
|
||||
</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>
|
||||
|
||||
<p><!-- golang.org/issue/30439 -->
|
||||
|
|
@ -73,12 +141,17 @@ TODO
|
|||
Go 1.14 drops support for the Native Client platform (<code>GOOS=nacl</code>).
|
||||
</p>
|
||||
|
||||
<h2 id="tools">Tools</h2>
|
||||
<h3 id="illumos">Illumos</h3>
|
||||
|
||||
<p>
|
||||
TODO
|
||||
<p><!-- CL 203758 -->
|
||||
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>
|
||||
|
||||
<h2 id="tools">Tools</h2>
|
||||
|
||||
<h3 id="go-command">Go command</h3>
|
||||
|
||||
<h4 id="vendor">Vendoring</h4>
|
||||
|
|
@ -105,7 +178,8 @@ TODO
|
|||
<code>go</code> <code>list</code> <code>-m</code> no longer silently omits
|
||||
transitive dependencies that do not provide packages in
|
||||
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>
|
||||
|
||||
<h4 id="go-flags">Flags</h4>
|
||||
|
|
@ -117,6 +191,11 @@ TODO
|
|||
<a href="https://golang.org/issue/32502">caused the build to fail</a>.
|
||||
</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 -->
|
||||
<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
|
||||
|
|
@ -130,12 +209,48 @@ TODO
|
|||
|
||||
<p><!-- golang.org/issue/34506 -->
|
||||
<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
|
||||
one in the module root directory. A file named "go.mod" must still be present
|
||||
in order to determine the module root directory, but it is not
|
||||
accessed. When <code>-modfile</code> is specified, an alternate go.sum file
|
||||
is also used: its path is derived from the <code>-modfile</code> flag by
|
||||
trimming the ".mod" extension and appending ".sum".
|
||||
command to read (and possibly write) an alternate <code>go.mod</code> file
|
||||
instead of the one in the module root directory. A file
|
||||
named <code>go.mod</code> must still be present in order to determine the
|
||||
module root directory, but it is not accessed. When <code>-modfile</code> is
|
||||
specified, an alternate <code>go.sum</code> file is also used: its path is
|
||||
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>
|
||||
|
||||
<h4 id="incompatible-versions"><code>+incompatible</code> versions</h4>
|
||||
|
|
@ -152,6 +267,30 @@ TODO
|
|||
include them if reported by a proxy.
|
||||
</p>
|
||||
|
||||
|
||||
<h4 id="go.mod"><code>go.mod</code> file maintenance</h4>
|
||||
<!-- golang.org/issue/34822 -->
|
||||
|
||||
<p>
|
||||
<code>go</code> commands other than
|
||||
<code>go</code> <code>mod</code> <code>tidy</code> no longer
|
||||
remove a <code>require</code> directive that specifies a version of an indirect dependency
|
||||
that is already implied by other (transitive) dependencies of the main
|
||||
module.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<code>go</code> commands other than
|
||||
<code>go</code> <code>mod</code> <code>tidy</code> no longer
|
||||
edit the <code>go.mod</code> file if the changes are only cosmetic.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
When <code>-mod=readonly</code> is set, <code>go</code> commands will no
|
||||
longer fail due to a missing <code>go</code> directive or an erroneous
|
||||
<code>// indirect</code> comment.
|
||||
</p>
|
||||
|
||||
<h4 id="module-downloading">Module downloading</h4>
|
||||
|
||||
<p><!-- golang.org/issue/26092 -->
|
||||
|
|
@ -165,10 +304,54 @@ TODO
|
|||
graphic characters and spaces.
|
||||
</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>
|
||||
|
||||
<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>
|
||||
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><!-- CL 171844 and many others -->
|
||||
|
|
@ -182,19 +365,82 @@ TODO
|
|||
visible changes.
|
||||
</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>
|
||||
|
||||
<p>
|
||||
TODO
|
||||
</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>
|
||||
<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>
|
||||
|
||||
</dl><!-- bytes/hash -->
|
||||
</dl><!-- hash/maphash -->
|
||||
|
||||
<dl id="crypto/tls"><dt><a href="/pkg/crypto/tls/">crypto/tls</a></dt>
|
||||
<dd>
|
||||
|
|
@ -224,13 +470,60 @@ TODO
|
|||
|
||||
</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>
|
||||
<p><!-- CL 186927 -->
|
||||
TODO: <a href="https://golang.org/cl/186927">https://golang.org/cl/186927</a>: update type of .js and .mjs files to text/javascript
|
||||
<p><!-- CL 200217 -->
|
||||
<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>
|
||||
|
||||
</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>
|
||||
<dd>
|
||||
|
|
@ -244,10 +537,105 @@ TODO
|
|||
|
||||
</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>
|
||||
<dd>
|
||||
<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>
|
||||
|
||||
</dl><!-- plugin -->
|
||||
|
|
@ -267,16 +655,73 @@ TODO
|
|||
|
||||
<dl id="runtime"><dt><a href="/pkg/runtime/">runtime</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 187739 -->
|
||||
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
|
||||
<p><!-- CL 200081 -->
|
||||
<code>runtime.Goexit</code> can no longer be aborted by a
|
||||
recursive <code>panic</code>/<code>recover</code>.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 188297 -->
|
||||
TODO: <a href="https://golang.org/cl/188297">https://golang.org/cl/188297</a>: don't forward SIGPIPE on macOS
|
||||
<p><!-- CL 188297, CL 191785 -->
|
||||
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>
|
||||
|
||||
</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>
|
||||
<dd>
|
||||
<p><!-- CL 201359 -->
|
||||
|
|
@ -287,6 +732,17 @@ TODO
|
|||
</p>
|
||||
</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>
|
||||
|
||||
<p>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!--{
|
||||
"Title": "The Go Programming Language Specification",
|
||||
"Subtitle": "Version of Sep 4, 2019",
|
||||
"Subtitle": "Version of Jan 14, 2020",
|
||||
"Path": "/ref/spec"
|
||||
}-->
|
||||
|
||||
|
|
@ -20,8 +20,8 @@ dependencies.
|
|||
</p>
|
||||
|
||||
<p>
|
||||
The grammar is compact and regular, allowing for easy analysis by
|
||||
automatic tools such as integrated development environments.
|
||||
The grammar is compact and simple to parse, allowing for easy analysis
|
||||
by automatic tools such as integrated development environments.
|
||||
</p>
|
||||
|
||||
<h2 id="Notation">Notation</h2>
|
||||
|
|
@ -2042,7 +2042,7 @@ of the last non-empty expression list.
|
|||
<p>
|
||||
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.
|
||||
<p>
|
||||
</p>
|
||||
|
||||
<pre class="ebnf">
|
||||
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 ")" .
|
||||
Literal = BasicLit | CompositeLit | FunctionLit .
|
||||
BasicLit = int_lit | float_lit | imaginary_lit | rune_lit | string_lit .
|
||||
OperandName = identifier | QualifiedIdent.
|
||||
OperandName = identifier | QualifiedIdent .
|
||||
</pre>
|
||||
|
||||
<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>
|
||||
|
||||
<pre>
|
||||
p1 := &[]int{} // p1 points to an initialized, empty slice with value []int{} and length 0
|
||||
p1 := &[]int{} // p1 points to an initialized, empty slice with value []int{} and length 0
|
||||
p2 := new([]int) // p2 points to an uninitialized slice with value nil and length 0
|
||||
</pre>
|
||||
|
||||
|
|
@ -3290,8 +3290,8 @@ array with the operand.
|
|||
|
||||
<pre>
|
||||
var a [10]int
|
||||
s1 := a[3:7] // underlying array of s1 is array a; &s1[2] == &a[5]
|
||||
s2 := s1[1:4] // underlying array of s2 is underlying array of s1 which is array a; &s2[1] == &a[5]
|
||||
s1 := a[3:7] // underlying array of s1 is array a; &s1[2] == &a[5]
|
||||
s2 := s1[1:4] // underlying array of s2 is underlying array of s1 which is array a; &s2[1] == &a[5]
|
||||
s2[1] = 42 // s2[1] == s1[2] == a[5] == 42; they all refer to the same underlying array element
|
||||
</pre>
|
||||
|
||||
|
|
@ -5279,7 +5279,7 @@ for i, s := range a {
|
|||
}
|
||||
|
||||
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}
|
||||
for key, val = range m {
|
||||
h(key, val)
|
||||
|
|
|
|||
|
|
@ -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>.
|
||||
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
|
||||
earlier section), you still need to <code>git clone</code> again at this point
|
||||
(to checkout the latest <code><tag></code>), because you must keep your
|
||||
go1.4 repository distinct.
|
||||
</p>
|
||||
|
||||
<h2 id="head">(Optional) Switch to the master branch</h2>
|
||||
|
||||
|
|
|
|||
164
doc/modules.md
164
doc/modules.md
|
|
@ -276,6 +276,10 @@ list. The `go` command does not fall back to later proxies in response to other
|
|||
4xx and 5xx errors. This allows a proxy to act as a gatekeeper, for example, by
|
||||
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
|
||||
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
|
||||
|
|
@ -425,12 +429,170 @@ setting `GOPROXY` to `https://example.com/proxy`.
|
|||
<a id="authenticating"></a>
|
||||
## 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>
|
||||
### go.sum file format
|
||||
|
||||
<a id="checksum-database"></a>
|
||||
### Checksum database
|
||||
|
||||
The checksum database is a global source of `go.sum` lines. The `go` command can
|
||||
use this in many situations to detect misbehavior by proxies or origin servers.
|
||||
|
||||
The checksum database allows for global consistency and reliability for all
|
||||
publicly available module versions. It makes untrusted proxies possible since
|
||||
they can't serve the wrong code without it going unnoticed. It also ensures
|
||||
that the bits associated with a specific version do not change from one day to
|
||||
the next, even if the module's author subsequently alters the tags in their
|
||||
repository.
|
||||
|
||||
The checksum database is served by [sum.golang.org](https://sum.golang.org),
|
||||
which is run by Google. It is a [Transparent
|
||||
Log](https://research.swtch.com/tlog) (or “Merkle Tree”) of `go.sum` line
|
||||
hashes, which is backed by [Trillian](https://github.com/google/trillian). The
|
||||
main advantage of a Merkle tree is that independent auditors can verify that it
|
||||
hasn't been tampered with, so it is more trustworthy than a simple database.
|
||||
|
||||
The `go` command interacts with the checksum database using the protocol
|
||||
originally outlined in [Proposal: Secure the Public Go Module
|
||||
Ecosystem](https://go.googlesource.com/proposal/+/master/design/25530-sumdb.md#checksum-database).
|
||||
|
||||
The table below specifies queries that the checksum database must respond to.
|
||||
For each path, `$base` is the path portion of the checksum database URL,
|
||||
`$module` is a module path, and `$version` is a version. For example, if the
|
||||
checksum database URL is `https://sum.golang.org`, and the client is requesting
|
||||
the record for the module `golang.org/x/text` at version `v0.3.2`, the client
|
||||
would send a `GET` request for
|
||||
`https://sum.golang.org/lookup/golang.org/x/text@v0.3.2`.
|
||||
|
||||
To avoid ambiguity when serving from case-insensitive file systems,
|
||||
the `$module` and `$version` elements are
|
||||
[case-encoded](https://pkg.go.dev/golang.org/x/mod/module#EscapePath)
|
||||
by replacing every uppercase letter with an exclamation mark followed by the
|
||||
corresponding lower-case letter. This allows modules `example.com/M` and
|
||||
`example.com/m` to both be stored on disk, since the former is encoded as
|
||||
`example.com/!m`.
|
||||
|
||||
Parts of the path surrounded by square brakets, like `[.p/$W]` denote optional
|
||||
values.
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Path</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>$base/latest</code></td>
|
||||
<td>
|
||||
Returns a signed, encoded tree description for the latest log. This
|
||||
signed description is in the form of a
|
||||
<a href="https://pkg.go.dev/golang.org/x/mod/sumdb/note">note</a>,
|
||||
which is text that has been signed by one or more server keys and can
|
||||
be verified using the server's public key. The tree description
|
||||
provides the size of the tree and the hash of the tree head at that
|
||||
size. This encoding is described in
|
||||
<code><a href="https://pkg.go.dev/golang.org/x/mod/sumdb/tlog#FormatTree">
|
||||
golang.org/x/mod/sumdb/tlog#FormatTree</a></code>.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr>
|
||||
<td><code>$base/lookup/$module@$version</code></td>
|
||||
<td>
|
||||
Returns the log record number for the entry about <code>$module</code>
|
||||
at <code>$version</code>, followed by the data for the record (that is,
|
||||
the <code>go.sum</code> lines for <code>$module</code> at
|
||||
<code>$version</code>) and a signed, encoded tree description that
|
||||
contains the record.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr>
|
||||
<td><code>$base/tile/$H/$L/$K[.p/$W]</code></td>
|
||||
<td>
|
||||
Returns a [log tile](https://research.swtch.com/tlog#serving_tiles),
|
||||
which is a set of hashes that make up a section of the log. Each tile
|
||||
is defined in a two-dimensional coordinate at tile level
|
||||
<code>$L</code>, <code>$K</code>th from the left, with a tile height of
|
||||
<code>$H</code>. The optional <code>.p/$W</code> suffix indicates a
|
||||
partial log tile with only <code>$W</code> hashes. Clients must fall
|
||||
back to fetching the full tile if a partial tile is not found.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr>
|
||||
<td><code>$base/tile/$H/data/$K[.p/$W]</code></td>
|
||||
<td>
|
||||
Returns the record data for the leaf hashes in
|
||||
<code>/tile/$H/0/$K[.p/$W]</code> (with a literal <code>data</code> path
|
||||
element).
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
If the `go` command consults the checksum database, then the first
|
||||
step is to retrieve the record data through the `/lookup` endpoint. If the
|
||||
module version is not yet recorded in the log, the checksum database will try
|
||||
to fetch it from the origin server before replying. This `/lookup` data
|
||||
provides the sum for this module version as well as its position in the log,
|
||||
which informs the client of which tiles should be fetched to perform proofs.
|
||||
The `go` command performs “inclusion” proofs (that a specific record exists in
|
||||
the log) and “consistency” proofs (that the tree hasn’t been tampered with)
|
||||
before adding new `go.sum` lines to the main module’s `go.sum` file. It's
|
||||
important that the data from `/lookup` should never be used without first
|
||||
authenticating it against the signed tree hash and authenticating the signed
|
||||
tree hash against the client's timeline of signed tree hashes.
|
||||
|
||||
Signed tree hashes and new tiles served by the checksum database are stored
|
||||
in the module cache, so the `go` command only needs to fetch tiles that are
|
||||
missing.
|
||||
|
||||
The `go` command doesn't need to directly connect to the checksum database. It
|
||||
can request module sums via a module proxy that
|
||||
[mirrors the checksum database](https://go.googlesource.com/proposal/+/master/design/25530-sumdb.md#proxying-a-checksum-database)
|
||||
and supports the protocol above. This can be particularly helpful for private,
|
||||
corporate proxies which block requests outside the organization.
|
||||
|
||||
The `GOSUMDB` environment variable identifies the name of checksum database to use
|
||||
and optionally its public key and URL, as in:
|
||||
|
||||
```
|
||||
GOSUMDB="sum.golang.org"
|
||||
GOSUMDB="sum.golang.org+<publickey>"
|
||||
GOSUMDB="sum.golang.org+<publickey> https://sum.golang.org"
|
||||
```
|
||||
|
||||
The `go` command knows the public key of `sum.golang.org`, and also that the
|
||||
name `sum.golang.google.cn` (available inside mainland China) connects to the
|
||||
`sum.golang.org` checksum database; use of any other database requires giving
|
||||
the public key explicitly. The URL defaults to `https://` followed by the
|
||||
database name.
|
||||
|
||||
`GOSUMDB` defaults to `sum.golang.org`, the Go checksum database run by Google.
|
||||
See https://sum.golang.org/privacy for the service's privacy policy.
|
||||
|
||||
If `GOSUMDB` is set to `off`, or if `go get` is invoked with the `-insecure`
|
||||
flag, the checksum database is not consulted, and all unrecognized modules are
|
||||
accepted, at the cost of giving up the security guarantee of verified
|
||||
repeatable downloads for all modules. A better way to bypass the checksum
|
||||
database for specific modules is to use the `GOPRIVATE` or `GONOSUMDB`
|
||||
environment variables. See [Private Modules](#private-modules) for details.
|
||||
|
||||
The `go env -w` command can be used to
|
||||
[set these variables](/pkg/cmd/go/#hdr-Print_Go_environment_information)
|
||||
for future `go` command invocations.
|
||||
|
||||
<a id="privacy"></a>
|
||||
## Privacy
|
||||
|
||||
|
|
@ -449,7 +611,7 @@ using [minimal version selection](#glos-minimal-version-selection). The build
|
|||
list contains versions for all modules in the [module
|
||||
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
|
||||
a build metadata suffix other than `+incompatible`. For example, `v1.2.3`
|
||||
is a canonical version, but `v1.2.3+meta` is not.
|
||||
|
|
|
|||
164
doc/root.html
164
doc/root.html
|
|
@ -1,164 +0,0 @@
|
|||
<!--{
|
||||
"Path": "/",
|
||||
"Template": true
|
||||
}-->
|
||||
|
||||
<div class="left">
|
||||
|
||||
<div id="learn">
|
||||
{{if not $.GoogleCN}}
|
||||
<a class="popout share">Pop-out</a>
|
||||
{{end}}
|
||||
<div class="rootHeading">Try Go</div>
|
||||
<div class="input">
|
||||
<textarea spellcheck="false" class="code">// You can edit this code!
|
||||
// Click here and start typing.
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
fmt.Println("Hello, 世界")
|
||||
}</textarea>
|
||||
</div>
|
||||
<div class="output">
|
||||
<pre>
|
||||
Hello, 世界
|
||||
</pre>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<a class="run" href="#" title="Run this code [shift-enter]">Run</a>
|
||||
{{if not $.GoogleCN}}
|
||||
<a class="share" href="#" title="Share this code">Share</a>
|
||||
<a class="tour" href="//tour.golang.org/" title="Learn Go from your browser">Tour</a>
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="toys">
|
||||
<select>
|
||||
<option value="hello.go">Hello, World!</option>
|
||||
<option value="life.go">Conway's Game of Life</option>
|
||||
<option value="fib.go">Fibonacci Closure</option>
|
||||
<option value="peano.go">Peano Integers</option>
|
||||
<option value="pi.go">Concurrent pi</option>
|
||||
<option value="sieve.go">Concurrent Prime Sieve</option>
|
||||
<option value="solitaire.go">Peg Solitaire Solver</option>
|
||||
<option value="tree.go">Tree Comparison</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="right">
|
||||
|
||||
<div id="about">
|
||||
Go is an open source programming language that makes it easy to build
|
||||
simple, reliable, and efficient software.
|
||||
</div>
|
||||
|
||||
<div id="gopher"></div>
|
||||
|
||||
<a href="/dl/" id="start">
|
||||
<span class="big">Download Go</span>
|
||||
<span class="desc">
|
||||
Binary distributions available for<br>
|
||||
Linux, macOS, Windows, and more.
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
<div style="clear: both"></div>
|
||||
|
||||
{{if not $.GoogleCN}}
|
||||
<div class="left">
|
||||
<div id="video">
|
||||
<div class="rootHeading">Featured video</div>
|
||||
<div class="js-frontpage-video" style="--aspect-ratio-padding: 58.07%;"><iframe width="415" height="241" src="//www.youtube.com/embed/ytEkHepK08c" frameborder="0" allowfullscreen></iframe></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="right">
|
||||
<div id="blog">
|
||||
<div class="rootHeading">Featured articles</div>
|
||||
<div class="read"><a href="//blog.golang.org/">Read more</a></div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<div style="clear: both;"></div>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
window.initFuncs.push(function() {
|
||||
// Set up playground if enabled.
|
||||
if (window.playground) {
|
||||
window.playground({
|
||||
"codeEl": "#learn .code",
|
||||
"outputEl": "#learn .output",
|
||||
"runEl": "#learn .run",
|
||||
"shareEl": "#learn .share",
|
||||
"shareRedirect": "//play.golang.org/p/",
|
||||
"toysEl": "#learn .toys select"
|
||||
});
|
||||
} else {
|
||||
$('#learn').hide()
|
||||
}
|
||||
});
|
||||
|
||||
{{if not $.GoogleCN}}
|
||||
|
||||
function readableTime(t) {
|
||||
var m = ["January", "February", "March", "April", "May", "June", "July",
|
||||
"August", "September", "October", "November", "December"];
|
||||
var p = t.substring(0, t.indexOf("T")).split("-");
|
||||
var d = new Date(p[0], p[1]-1, p[2]);
|
||||
return d.getDate() + " " + m[d.getMonth()] + " " + d.getFullYear();
|
||||
}
|
||||
|
||||
window.feedLoaded = function(result) {
|
||||
var blog = document.getElementById("blog");
|
||||
var read = blog.getElementsByClassName("read")[0];
|
||||
for (var i = 0; i < result.length && i < 2; i++) {
|
||||
var entry = result[i];
|
||||
var title = document.createElement("a");
|
||||
title.className = "title";
|
||||
title.href = entry.Link;
|
||||
title.innerHTML = entry.Title;
|
||||
blog.insertBefore(title, read);
|
||||
var extract = document.createElement("div");
|
||||
extract.className = "extract";
|
||||
extract.innerHTML = entry.Summary;
|
||||
blog.insertBefore(extract, read);
|
||||
var when = document.createElement("div");
|
||||
when.className = "when";
|
||||
when.innerHTML = "Published " + readableTime(entry.Time);
|
||||
blog.insertBefore(when, read);
|
||||
}
|
||||
}
|
||||
|
||||
window.initFuncs.push(function() {
|
||||
// Load blog feed.
|
||||
$('<script/>').attr('text', 'text/javascript')
|
||||
.attr('src', '//blog.golang.org/.json?jsonp=feedLoaded')
|
||||
.appendTo('body');
|
||||
|
||||
// Set the video at random.
|
||||
var videos = [
|
||||
{h: 241, s: "//www.youtube.com/embed/ytEkHepK08c"}, // Tour of Go
|
||||
{h: 241, s: "//www.youtube.com/embed/f6kdp27TYZs"}, // Concurrency Patterns
|
||||
{h: 233, s: "//player.vimeo.com/video/69237265"} // Simple environment
|
||||
];
|
||||
var v = videos[Math.floor(Math.random()*videos.length)];
|
||||
$('#video iframe').attr('height', v.h).attr('src', v.s);
|
||||
// Compute the aspect ratio (as a percentage) of the video
|
||||
// using the fixed width 415 and the height of the current video, v.h.
|
||||
var ar = 100*v.h/415;
|
||||
$('.js-frontpage-video').attr('style', '--aspect-ratio-padding: ' + ar + '%;');
|
||||
});
|
||||
|
||||
{{end}}
|
||||
})();
|
||||
</script>
|
||||
|
|
@ -1,184 +0,0 @@
|
|||
<!--{
|
||||
"Title": "Go Security Policy",
|
||||
"Path": "/security",
|
||||
"Template": true
|
||||
}-->
|
||||
|
||||
<h2>Implementation</h2>
|
||||
|
||||
<h3>Reporting a Security Bug</h3>
|
||||
|
||||
<p>
|
||||
Please report to us any issues you find.
|
||||
This document explains how to do that and what to expect in return.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
All security bugs in the Go distribution should be reported by email to
|
||||
<a href="mailto:security@golang.org">security@golang.org</a>.
|
||||
This mail is delivered to a small security team.
|
||||
Your email will be acknowledged within 24 hours, and you'll receive a more
|
||||
detailed response to your email within 72 hours indicating the next steps in
|
||||
handling your report.
|
||||
For critical problems, you can encrypt your report using our PGP key (listed below).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To ensure your report is not marked as spam, please include the word "vulnerability"
|
||||
anywhere in your email. Please use a descriptive subject line for your report email.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
After the initial reply to your report, the security team will endeavor to keep
|
||||
you informed of the progress being made towards a fix and full announcement.
|
||||
These updates will be sent at least every five days.
|
||||
In reality, this is more likely to be every 24-48 hours.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If you have not received a reply to your email within 48 hours or you have not
|
||||
heard from the security team for the past five days please contact the Go
|
||||
security team directly:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>Primary security coordinator: <a href="mailto:filippo@golang.org">Filippo Valsorda</a> (<a href="https://keybase.io/filippo/pgp_keys.asc">public key</a>).</li>
|
||||
<li>Secondary coordinator: <a href="mailto:agl@golang.org">Adam Langley</a> (<a href="https://www.imperialviolet.org/key.asc">public key</a>).</li>
|
||||
<li>If you receive no response, mail <a href="mailto:golang-dev@googlegroups.com">golang-dev@googlegroups.com</a> or use the <a href="https://groups.google.com/forum/#!forum/golang-dev">golang-dev web interface</a>.</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Please note that golang-dev is a public discussion forum.
|
||||
When escalating on this list, please do not disclose the details of the issue.
|
||||
Simply state that you're trying to reach a member of the security team.
|
||||
</p>
|
||||
|
||||
<h3>Flagging Existing Issues as Security-related</h3>
|
||||
|
||||
<p>
|
||||
If you believe that an <a href="https://golang.org/issue">existing issue</a>
|
||||
is security-related, we ask that you send an email to
|
||||
<a href="mailto:security@golang.org">security@golang.org</a>.
|
||||
The email should include the issue ID and a short description of why it should
|
||||
be handled according to this security policy.
|
||||
</p>
|
||||
|
||||
<h3>Disclosure Process</h3>
|
||||
|
||||
<p>The Go project uses the following disclosure process:</p>
|
||||
|
||||
<ol>
|
||||
<li>Once the security report is received it is assigned a primary handler.
|
||||
This person coordinates the fix and release process.</li>
|
||||
<li>The issue is confirmed and a list of affected software is determined.</li>
|
||||
<li>Code is audited to find any potential similar problems.</li>
|
||||
<li>If it is determined, in consultation with the submitter, that a CVE-ID is
|
||||
required, the primary handler obtains one via email to
|
||||
<a href="https://oss-security.openwall.org/wiki/mailing-lists/distros">oss-distros</a>.</li>
|
||||
<li>Fixes are prepared for the two most recent major releases and the head/master
|
||||
revision. These fixes are not yet committed to the public repository.</li>
|
||||
<li>A notification is sent to the
|
||||
<a href="https://groups.google.com/group/golang-announce">golang-announce</a>
|
||||
mailing list to give users time to prepare their systems for the update.</li>
|
||||
<li>Three working days following this notification, the fixes are applied to
|
||||
the <a href="https://go.googlesource.com/go">public repository</a> and a new
|
||||
Go release is issued.</li>
|
||||
<li>On the date that the fixes are applied, announcements are sent to
|
||||
<a href="https://groups.google.com/group/golang-announce">golang-announce</a>,
|
||||
<a href="https://groups.google.com/group/golang-dev">golang-dev</a>, and
|
||||
<a href="https://groups.google.com/group/golang-nuts">golang-nuts</a>.
|
||||
</ol>
|
||||
|
||||
<p>
|
||||
This process can take some time, especially when coordination is required with
|
||||
maintainers of other projects. Every effort will be made to handle the bug in
|
||||
as timely a manner as possible, however it's important that we follow the
|
||||
process described above to ensure that disclosures are handled consistently.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For security issues that include the assignment of a CVE-ID,
|
||||
the issue is listed publicly under the
|
||||
<a href="https://www.cvedetails.com/vulnerability-list/vendor_id-14185/Golang.html">"Golang" product on the CVEDetails website</a>
|
||||
as well as the
|
||||
<a href="https://web.nvd.nist.gov/view/vuln/search">National Vulnerability Disclosure site</a>.
|
||||
</p>
|
||||
|
||||
<h3>Receiving Security Updates</h3>
|
||||
|
||||
<p>
|
||||
The best way to receive security announcements is to subscribe to the
|
||||
<a href="https://groups.google.com/forum/#!forum/golang-announce">golang-announce</a>
|
||||
mailing list. Any messages pertaining to a security issue will be prefixed
|
||||
with <code>[security]</code>.
|
||||
</p>
|
||||
|
||||
<h3>Comments on This Policy</h3>
|
||||
|
||||
<p>
|
||||
If you have any suggestions to improve this policy, please send an email to
|
||||
<a href="mailto:golang-dev@golang.org">golang-dev@golang.org</a> for discussion.
|
||||
</p>
|
||||
|
||||
<h3>PGP Key for <a href="mailto:security@golang.org">security@golang.org</a></h3>
|
||||
|
||||
<p>
|
||||
We accept PGP-encrypted email, but the majority of the security team
|
||||
are not regular PGP users so it's somewhat inconvenient. Please only
|
||||
use PGP for critical security reports.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Comment: GPGTools - https://gpgtools.org
|
||||
|
||||
mQINBFXI1h0BEADZdm05GDFWvjmQKutUVb0cJKS+VR+6XU3g/YQZGC8tnIL6i7te
|
||||
+fPJHfQc2uIw0xeBgZX4Ni/S8yIqsbIjqYeaToX7QFUufJDQwrmlQRDVAvvT5HBT
|
||||
J80JEs7yHRreFoLzB6dnWehWXzWle4gFKeIy+hvLrYquZVvbeEYTnX7fNzZg0+5L
|
||||
ksvj7lnQlJIy1l3sL/7uPr9qsm45/hzd0WjTQS85Ry6Na3tMwRpqGENDh25Blz75
|
||||
8JgK9JmtTJa00my1zzeCXU04CKKEMRbkMLozzudOH4ZLiLWcFiKRpeCn860wC8l3
|
||||
oJcyyObuTSbr9o05ra3On+epjCEFkknGX1WxPv+TV34i0a23AtuVyTCloKb7RYXc
|
||||
7mUaskZpU2rFBqIkzZ4MQJ7RDtGlm5oBy36j2QL63jAZ1cKoT/yvjJNp2ObmWaVF
|
||||
X3tk/nYw2H0YDjTkTCgGtyAOj3Cfqrtsa5L0jG5K2p4RY8mtVgQ5EOh7QxuS+rmN
|
||||
JiA39SWh7O6uFCwkz/OCXzqeh6/nP10HAb9S9IC34QQxm7Fhd0ZXzEv9IlBTIRzk
|
||||
xddSdACPnLE1gJcFHxBd2LTqS/lmAFShCsf8S252kagKJfHRebQJZHCIs6kT9PfE
|
||||
0muq6KRKeDXv01afAUvoB4QW/3chUrtgL2HryyO8ugMu7leVGmoZhFkIrQARAQAB
|
||||
tCZHbyBTZWN1cml0eSBUZWFtIDxzZWN1cml0eUBnb2xhbmcub3JnPokCPQQTAQoA
|
||||
JwUCVcjWHQIbAwUJB4YfgAULCQgHAwUVCgkICwUWAgMBAAIeAQIXgAAKCRA6RtGR
|
||||
eVpYOLnDD/9YVTd6DTwdJq6irVfM/ICPlPTXB0JLERqCI1Veptcp56eQoJ0XWGQp
|
||||
tkGlgbvmCzFo0B+65Te7YA4R3oyBCXd6JgyWQQPy5p60FHyuuCPVAReclSWyt9f2
|
||||
Yj/u4DjghKhELOvPiI96egcU3g9jrEEcPjm7JYkc9M2gVSNOnnJvcD7wpQJNCzon
|
||||
51eMZ1ZyfA5UCBTa0SaT9eXg5zwNlYQnB6ZF6TjXezkhLqlTsBuHxoNVf+9vCC0o
|
||||
ZKIM2ovptMx9eEguTDKWaQ7tero7Zs/q5fwk/MDzM/LGJ9aXy2RCtqBxv46vDS7G
|
||||
fCNq+aPD/wyFd6hxQkvkua6hgZwYT+cJWHYA2Yv0LO3BYOJdjfc+j2hjv+mC9lF0
|
||||
UpWhCVJv3hHoFaxnz62GdROzf2wXz6aR9Saj1rYSvqT9jC20VInxqMufXNN2sbpo
|
||||
Kyk6MTbAeepphQpfAWQv+ltWgBiEjuFxYdwv/vmw20996JV7O8nqkeCUW84B6su+
|
||||
Y3bbdP9o3DBtOT0j9LTB/FucmdNCNHoO+EnNBKJd6FoYTGLWi3Rq9DLx2V9tdJHo
|
||||
Bn67dymcl+iyp337HJNY+qS+KCgoqAWlxkzXRiXKb/yluhXdIkqhg4kL8JPAJvfS
|
||||
cs7Zn67Mx04ixJnRMYCDmxtD4xPsFMzM7g8m3PQp+nE7WhujM/ImM7kCDQRVyNYd
|
||||
ARAAlw9H/1ybQs4K3XKA1joII16rta9KS7ew76+agXo0jeSRwMEQfItOxYvfhmo8
|
||||
+ydn5TWsTbifGU8L3+EBTMRRyzWhbaGO0Wizw7BTVJ7n5JW+ndPrcUpp/ilUk6AU
|
||||
VxaO/8/R+9+VJZpoeoLHXYloFGNuX58GLIy1jSBvLsLl/Ki5IOrHvD1GK6TftOl5
|
||||
j8IPC1LSBrwGJO803x7wUdQP/tsKN/QPR8pnBntrEgrQFSI+Q3qrCvVMmXnBlYum
|
||||
jfOBt8pKMgB9/ix+HWN8piQNQiJxD+XjEM6XwUmQqIR7y5GINKWgundCmtYIzVgY
|
||||
9p2Br6UPrTJi12LfKv5s2R6NnxFHv/ad29CpPTeLJRsSqFfqBL969BCpj/isXmQE
|
||||
m4FtziZidARXo12KiGAnPF9otirNHp4+8hwNB3scf7cI53y8nZivO9cwI7BoClY6
|
||||
ZIabjDcJxjK+24emoz3mJ5SHpZpQLSb9o8GbLLfXOq+4uzEX2A30fhrtsQb/x0GM
|
||||
4v3EU1aP2mjuksyYbgldtY64tD35wqAA9mVl5Ux+g1HoUBvLw0h+lzwh370NJw//
|
||||
ITvBQVUtDMB96rfIP4fL5pYl5pmRz+vsuJ0iXzm05qBgKfSqO7To9SWxQPdX89R4
|
||||
u0/XVAlw0Ak9Zceq3W96vseEUTR3aoZCMIPiwfcDaq60rWUAEQEAAYkCJQQYAQoA
|
||||
DwUCVcjWHQIbDAUJB4YfgAAKCRA6RtGReVpYOEg/EADZcIYw4q1jAbDkDy3LQG07
|
||||
AR8QmLp/RDp72RKbCSIYyvyXEnmrhUg98lUG676qTH+Y7dlEX107dLhFuKEYyV8D
|
||||
ZalrFQO/3WpLWdIAmWrj/wq14qii1rgmy96Nh3EqG3CS50HEMGkW1llRx2rgBvGl
|
||||
pgoTcwOfT+h8s0HlZdIS/cv2wXqwPgMWr1PIk3as1fu1OH8n/BjeGQQnNJEaoBV7
|
||||
El2C/hz3oqf2uYQ1QvpU23F1NrstekxukO8o2Y/fqsgMJqAiNJApUCl/dNhK+W57
|
||||
iicjvPirUQk8MUVEHXKhWIzYxon6aEUTx+xyNMBpRJIZlJ61FxtnZhoPiAFtXVPb
|
||||
+95BRJA9npidlVFjqz9QDK/4NSnJ3KaERR9tTDcvq4zqT22Z1Ai5gWQKqogTz5Mk
|
||||
F+nZwVizW0yi33id9qDpAuApp8o6AiyH5Ql1Bo23bvqS2lMrXPIS/QmPPsA76CBs
|
||||
lYjQwwz8abUD1pPdzyYtMKZUMwhicSFOHFDM4oQN16k2KJuntuih8BKVDCzIOq+E
|
||||
KHyeh1BqWplUtFh1ckxZlXW9p9F7TsWjtfcKaY8hkX0Cr4uVjwAFIjLcAxk67ROe
|
||||
huEb3Gt+lwJz6aNnZUU87ukMAxRVR2LL0btdxgc6z8spl66GXro/LUkXmAdyOEMV
|
||||
UDrmjf9pr7o00hC7lCHFzw==
|
||||
=WE0r
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
</pre>
|
||||
|
|
@ -2,16 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// We skip this test in race mode because, for unknown reasons,
|
||||
// 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
|
||||
// +build darwin,cgo,!internal
|
||||
|
||||
package cgotest
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !darwin !cgo internal race
|
||||
// +build !darwin !cgo internal
|
||||
|
||||
package cgotest
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build gccgo
|
||||
|
||||
package cgotest
|
||||
|
||||
//typedef void (*PFunc)();
|
||||
//PFunc success_cb;
|
||||
import "C"
|
||||
|
||||
//export Test
|
||||
func Test() {
|
||||
_ = C.success_cb
|
||||
}
|
||||
|
|
@ -562,6 +562,11 @@ void issue8811Execute() {
|
|||
issue8811Init();
|
||||
}
|
||||
|
||||
// issue 8945
|
||||
|
||||
typedef void (*PFunc8945)();
|
||||
PFunc8945 func8945;
|
||||
|
||||
// issue 9557
|
||||
|
||||
struct issue9557_t {
|
||||
|
|
|
|||
|
|
@ -2,14 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// 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
|
||||
|
||||
import (
|
||||
|
|
|
|||
2
misc/cgo/test/testdata/issue24161e0/main.go
vendored
2
misc/cgo/test/testdata/issue24161e0/main.go
vendored
|
|
@ -12,7 +12,7 @@ package issue24161e0
|
|||
#include <TargetConditionals.h>
|
||||
#include <CoreFoundation/CoreFoundation.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;
|
||||
static CFDataRef SecKeyCreateSignature(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef dataToSign, CFErrorRef *error){return NULL;}
|
||||
#define kSecKeyAlgorithmECDSASignatureDigestX962SHA1 foo()
|
||||
|
|
|
|||
2
misc/cgo/test/testdata/issue24161e1/main.go
vendored
2
misc/cgo/test/testdata/issue24161e1/main.go
vendored
|
|
@ -12,7 +12,7 @@ package issue24161e1
|
|||
#include <TargetConditionals.h>
|
||||
#include <CoreFoundation/CoreFoundation.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;
|
||||
static CFDataRef SecKeyCreateSignature(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef dataToSign, CFErrorRef *error){return NULL;}
|
||||
#define kSecKeyAlgorithmECDSASignatureDigestX962SHA1 foo()
|
||||
|
|
|
|||
2
misc/cgo/test/testdata/issue24161e2/main.go
vendored
2
misc/cgo/test/testdata/issue24161e2/main.go
vendored
|
|
@ -12,7 +12,7 @@ package issue24161e2
|
|||
#include <TargetConditionals.h>
|
||||
#include <CoreFoundation/CoreFoundation.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;
|
||||
static CFDataRef SecKeyCreateSignature(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef dataToSign, CFErrorRef *error){return NULL;}
|
||||
#define kSecKeyAlgorithmECDSASignatureDigestX962SHA1 foo()
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ package issue9026
|
|||
// 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(
|
||||
git_merge_file_input *in,
|
||||
|
|
|
|||
|
|
@ -102,6 +102,11 @@ static void issue7978c(uint32_t *sync) {
|
|||
// #include'd twice. No runtime test; just make sure it compiles.
|
||||
#include "issue8331.h"
|
||||
|
||||
// issue 8945
|
||||
|
||||
typedef void (*PFunc8945)();
|
||||
extern PFunc8945 func8945; // definition is in test.go
|
||||
|
||||
// issue 20910
|
||||
void callMulti(void);
|
||||
|
||||
|
|
@ -514,6 +519,13 @@ func test7978(t *testing.T) {
|
|||
|
||||
var issue8331Var C.issue8331
|
||||
|
||||
// issue 8945
|
||||
|
||||
//export Test8945
|
||||
func Test8945() {
|
||||
_ = C.func8945
|
||||
}
|
||||
|
||||
// issue 20910
|
||||
|
||||
//export multi
|
||||
|
|
|
|||
|
|
@ -433,7 +433,7 @@ func (tr *Reader) readHeader() (*Header, *block, error) {
|
|||
// files generated by a pre-Go1.8 toolchain. If the generated file
|
||||
// happened to have a prefix field that parses as valid
|
||||
// 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.
|
||||
//
|
||||
// See https://golang.org/issues/12594
|
||||
|
|
|
|||
57
src/cmd/asm/internal/asm/testdata/riscvenc.s
vendored
57
src/cmd/asm/internal/asm/testdata/riscvenc.s
vendored
|
|
@ -60,11 +60,13 @@ start:
|
|||
AUIPC $0, X10 // 17050000
|
||||
AUIPC $0, X11 // 97050000
|
||||
AUIPC $1, X10 // 17150000
|
||||
AUIPC $1048575, X10 // 17f5ffff
|
||||
AUIPC $-524288, X15 // 97070080
|
||||
AUIPC $524287, X10 // 17f5ff7f
|
||||
|
||||
LUI $0, X15 // b7070000
|
||||
LUI $167, X15 // b7770a00
|
||||
LUI $1048575, X15 // b7f7ffff
|
||||
LUI $-524288, X15 // b7070080
|
||||
LUI $524287, X15 // b7f7ff7f
|
||||
|
||||
SLL X6, X5, X7 // b3936200
|
||||
SLL X5, X6 // 33135300
|
||||
|
|
@ -89,15 +91,15 @@ start:
|
|||
// to 2 because they transfer control to the second instruction
|
||||
// in the function (the first instruction being an invisible
|
||||
// stack pointer adjustment).
|
||||
JAL X5, start // JAL X5, 2 // eff2dff0
|
||||
JAL X5, start // JAL X5, 2 // eff25ff0
|
||||
JALR X6, (X5) // 67830200
|
||||
JALR X6, 4(X5) // 67834200
|
||||
BEQ X5, X6, start // BEQ X5, X6, 2 // e38062f0
|
||||
BNE X5, X6, start // BNE X5, X6, 2 // e39e62ee
|
||||
BLT X5, X6, start // BLT X5, X6, 2 // e3cc62ee
|
||||
BLTU X5, X6, start // BLTU X5, X6, 2 // e3ea62ee
|
||||
BGE X5, X6, start // BGE X5, X6, 2 // e3d862ee
|
||||
BGEU X5, X6, start // BGEU X5, X6, 2 // e3f662ee
|
||||
BEQ X5, X6, start // BEQ X5, X6, 2 // e38c62ee
|
||||
BNE X5, X6, start // BNE X5, X6, 2 // e39a62ee
|
||||
BLT X5, X6, start // BLT X5, X6, 2 // e3c862ee
|
||||
BLTU X5, X6, start // BLTU X5, X6, 2 // e3e662ee
|
||||
BGE X5, X6, start // BGE X5, X6, 2 // e3d462ee
|
||||
BGEU X5, X6, start // BGEU X5, X6, 2 // e3f262ee
|
||||
|
||||
// 2.6: Load and Store Instructions
|
||||
LW (X5), X6 // 03a30200
|
||||
|
|
@ -267,3 +269,40 @@ start:
|
|||
MOVD 4(X5), F0 // 07b04200
|
||||
MOVD F0, 4(X5) // 27b20200
|
||||
MOVD F0, F1 // d3000022
|
||||
|
||||
// These jumps can get printed as jumps to 2 because they go to the
|
||||
// second instruction in the function (the first instruction is an
|
||||
// invisible stack pointer adjustment).
|
||||
JMP start // JMP 2 // 6ff0dfcc
|
||||
JMP (X5) // 67800200
|
||||
JMP 4(X5) // 67804200
|
||||
|
||||
// JMP and CALL to symbol are encoded as:
|
||||
// AUIPC $0, TMP
|
||||
// JALR $0, TMP
|
||||
// with a R_RISCV_PCREL_ITYPE relocation - the linker resolves the
|
||||
// real address and updates the immediates for both instructions.
|
||||
CALL asmtest(SB) // 970f0000
|
||||
JMP asmtest(SB) // 970f0000
|
||||
|
||||
SEQZ X15, X15 // 93b71700
|
||||
SNEZ X15, X15 // b337f000
|
||||
|
||||
// F extension
|
||||
FNEGS F0, F1 // d3100020
|
||||
|
||||
// TODO(jsing): FNES gets encoded as FEQS+XORI - this should
|
||||
// be handled as a single *obj.Prog so that the full two
|
||||
// instruction encoding is tested here.
|
||||
FNES F0, F1, X7 // d3a300a0
|
||||
|
||||
// D extension
|
||||
FNEGD F0, F1 // d3100022
|
||||
FEQD F0, F1, X5 // d3a200a2
|
||||
FLTD F0, F1, X5 // d39200a2
|
||||
FLED F0, F1, X5 // d38200a2
|
||||
|
||||
// TODO(jsing): FNED gets encoded as FEQD+XORI - this should
|
||||
// be handled as a single *obj.Prog so that the full two
|
||||
// instruction encoding is tested here.
|
||||
FNED F0, F1, X5 // d3a200a2
|
||||
|
|
|
|||
|
|
@ -5,12 +5,14 @@
|
|||
package gc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"cmd/compile/internal/types"
|
||||
"cmd/internal/src"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
|
|
@ -650,23 +652,64 @@ var basicnames = []string{
|
|||
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 {
|
||||
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 {
|
||||
// in %-T mode collapse rune and byte with their originals.
|
||||
switch mode {
|
||||
case FTypeIdName, FTypeId:
|
||||
t = types.Types[t.Etype]
|
||||
default:
|
||||
return sconv(t.Sym, FmtShort, mode)
|
||||
b.WriteString(sconv(t.Sym, FmtShort, mode))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
|
|
@ -675,161 +718,197 @@ func typefmt(t *types.Type, flag FmtFlag, mode fmtMode, depth int) string {
|
|||
case FTypeId, FTypeIdName:
|
||||
if flag&FmtShort != 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 {
|
||||
return sconv(t.Sym, FmtUnsigned, mode)
|
||||
b.WriteString(sconv(t.Sym, FmtUnsigned, mode))
|
||||
return
|
||||
}
|
||||
|
||||
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] != "" {
|
||||
var name string
|
||||
switch t {
|
||||
case types.Idealbool:
|
||||
return "untyped bool"
|
||||
name = "untyped bool"
|
||||
case types.Idealstring:
|
||||
return "untyped string"
|
||||
name = "untyped string"
|
||||
case types.Idealint:
|
||||
return "untyped int"
|
||||
name = "untyped int"
|
||||
case types.Idealrune:
|
||||
return "untyped rune"
|
||||
name = "untyped rune"
|
||||
case types.Idealfloat:
|
||||
return "untyped float"
|
||||
name = "untyped float"
|
||||
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 {
|
||||
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 {
|
||||
case TPTR:
|
||||
b.WriteByte('*')
|
||||
switch mode {
|
||||
case FTypeId, FTypeIdName:
|
||||
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:
|
||||
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:
|
||||
return "[]" + tmodeString(t.Elem(), mode, depth)
|
||||
b.WriteString("[]")
|
||||
tconv2(b, t.Elem(), 0, mode, visited)
|
||||
|
||||
case TCHAN:
|
||||
switch t.ChanDir() {
|
||||
case types.Crecv:
|
||||
return "<-chan " + tmodeString(t.Elem(), mode, depth)
|
||||
|
||||
b.WriteString("<-chan ")
|
||||
tconv2(b, t.Elem(), 0, mode, visited)
|
||||
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:
|
||||
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:
|
||||
if t.IsEmptyInterface() {
|
||||
return "interface {}"
|
||||
b.WriteString("interface {}")
|
||||
break
|
||||
}
|
||||
buf := make([]byte, 0, 64)
|
||||
buf = append(buf, "interface {"...)
|
||||
b.WriteString("interface {")
|
||||
for i, f := range t.Fields().Slice() {
|
||||
if i != 0 {
|
||||
buf = append(buf, ';')
|
||||
b.WriteByte(';')
|
||||
}
|
||||
buf = append(buf, ' ')
|
||||
b.WriteByte(' ')
|
||||
switch {
|
||||
case f.Sym == nil:
|
||||
// Check first that a symbol is defined for this type.
|
||||
// Wrong interface definitions may have types lacking a symbol.
|
||||
break
|
||||
case types.IsExported(f.Sym.Name):
|
||||
buf = append(buf, sconv(f.Sym, FmtShort, mode)...)
|
||||
b.WriteString(sconv(f.Sym, FmtShort, mode))
|
||||
default:
|
||||
flag1 := FmtLeft
|
||||
if flag&FmtUnsigned != 0 {
|
||||
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 {
|
||||
buf = append(buf, ' ')
|
||||
b.WriteByte(' ')
|
||||
}
|
||||
buf = append(buf, '}')
|
||||
return string(buf)
|
||||
b.WriteByte('}')
|
||||
|
||||
case TFUNC:
|
||||
buf := make([]byte, 0, 64)
|
||||
if flag&FmtShort != 0 {
|
||||
// no leading func
|
||||
} else {
|
||||
if t.Recv() != nil {
|
||||
buf = append(buf, "method"...)
|
||||
buf = append(buf, tmodeString(t.Recvs(), mode, depth)...)
|
||||
buf = append(buf, ' ')
|
||||
b.WriteString("method")
|
||||
tconv2(b, t.Recvs(), 0, mode, visited)
|
||||
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() {
|
||||
case 0:
|
||||
// nothing to do
|
||||
|
||||
case 1:
|
||||
buf = append(buf, ' ')
|
||||
buf = append(buf, tmodeString(t.Results().Field(0).Type, mode, depth)...) // struct->field->field's type
|
||||
b.WriteByte(' ')
|
||||
tconv2(b, t.Results().Field(0).Type, 0, mode, visited) // struct->field->field's type
|
||||
|
||||
default:
|
||||
buf = append(buf, ' ')
|
||||
buf = append(buf, tmodeString(t.Results(), mode, depth)...)
|
||||
b.WriteByte(' ')
|
||||
tconv2(b, t.Results(), 0, mode, visited)
|
||||
}
|
||||
return string(buf)
|
||||
|
||||
case TSTRUCT:
|
||||
if m := t.StructType().Map; m != nil {
|
||||
mt := m.MapType()
|
||||
// Format the bucket struct for map[x]y as map.bucket[x]y.
|
||||
// This avoids a recursive print that generates very long names.
|
||||
var subtype string
|
||||
switch t {
|
||||
case mt.Bucket:
|
||||
subtype = "bucket"
|
||||
b.WriteString("map.bucket[")
|
||||
case mt.Hmap:
|
||||
subtype = "hdr"
|
||||
b.WriteString("map.hdr[")
|
||||
case mt.Hiter:
|
||||
subtype = "iter"
|
||||
b.WriteString("map.iter[")
|
||||
default:
|
||||
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 {
|
||||
buf = append(buf, '(')
|
||||
b.WriteByte('(')
|
||||
var flag1 FmtFlag
|
||||
switch mode {
|
||||
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() {
|
||||
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 {
|
||||
buf = append(buf, "struct {"...)
|
||||
b.WriteString("struct {")
|
||||
for i, f := range t.Fields().Slice() {
|
||||
if i != 0 {
|
||||
buf = append(buf, ';')
|
||||
b.WriteByte(';')
|
||||
}
|
||||
buf = append(buf, ' ')
|
||||
buf = append(buf, fldconv(f, FmtLong, mode, depth, funarg)...)
|
||||
b.WriteByte(' ')
|
||||
fldconv(b, f, FmtLong, mode, visited, funarg)
|
||||
}
|
||||
if t.NumFields() != 0 {
|
||||
buf = append(buf, ' ')
|
||||
b.WriteByte(' ')
|
||||
}
|
||||
buf = append(buf, '}')
|
||||
b.WriteByte('}')
|
||||
}
|
||||
return string(buf)
|
||||
|
||||
case TFORW:
|
||||
b.WriteString("undefined")
|
||||
if t.Sym != nil {
|
||||
return "undefined " + smodeString(t.Sym, mode)
|
||||
b.WriteByte(' ')
|
||||
b.WriteString(smodeString(t.Sym, mode))
|
||||
}
|
||||
return "undefined"
|
||||
|
||||
case TUNSAFEPTR:
|
||||
return "unsafe.Pointer"
|
||||
b.WriteString("unsafe.Pointer")
|
||||
|
||||
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.
|
||||
|
|
@ -1657,15 +1736,11 @@ func sconv(s *types.Sym, flag FmtFlag, mode fmtMode) string {
|
|||
return symfmt(s, flag, mode)
|
||||
}
|
||||
|
||||
func tmodeString(t *types.Type, mode fmtMode, depth int) string {
|
||||
return tconv(t, 0, mode, depth)
|
||||
}
|
||||
|
||||
func fldconv(f *types.Field, flag FmtFlag, mode fmtMode, depth int, funarg types.Funarg) string {
|
||||
func fldconv(b *bytes.Buffer, f *types.Field, flag FmtFlag, mode fmtMode, visited map[*types.Type]int, funarg types.Funarg) {
|
||||
if f == nil {
|
||||
return "<T>"
|
||||
b.WriteString("<T>")
|
||||
return
|
||||
}
|
||||
|
||||
flag, mode = flag.update(mode)
|
||||
if mode == FTypeIdName {
|
||||
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() {
|
||||
var et *types.Type
|
||||
if f.Type != nil {
|
||||
et = f.Type.Elem()
|
||||
}
|
||||
typ = "..." + tmodeString(et, mode, depth)
|
||||
b.WriteString("...")
|
||||
tconv2(b, et, 0, mode, visited)
|
||||
} else {
|
||||
typ = tmodeString(f.Type, mode, depth)
|
||||
}
|
||||
|
||||
str := typ
|
||||
if name != "" {
|
||||
str = name + " " + typ
|
||||
tconv2(b, f.Type, 0, mode, visited)
|
||||
}
|
||||
|
||||
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
|
||||
|
|
@ -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) {
|
||||
switch verb {
|
||||
case 'v', 'S', 'L':
|
||||
// This is an external entry point, so we pass depth 0 to tconv.
|
||||
// See comments in Type.String.
|
||||
fmt.Fprint(s, tconv(t, fmtFlag(s, verb), mode, 0))
|
||||
|
||||
fmt.Fprint(s, tconv(t, fmtFlag(s, verb), mode))
|
||||
default:
|
||||
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) modeString(mode fmtMode) string { return mode.Sprint(n) }
|
||||
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ func TestIntendedInlining(t *testing.T) {
|
|||
}
|
||||
|
||||
switch runtime.GOARCH {
|
||||
case "386", "wasm", "arm":
|
||||
case "386", "wasm", "arm", "riscv64":
|
||||
default:
|
||||
// TODO(mvdan): As explained in /test/inline_sync.go, some
|
||||
// architectures don't have atomic intrinsics, so these go over
|
||||
|
|
|
|||
|
|
@ -511,8 +511,8 @@ func Main(archInit func(*Arch)) {
|
|||
types.Sconv = func(s *types.Sym, flag, mode int) string {
|
||||
return sconv(s, FmtFlag(flag), fmtMode(mode))
|
||||
}
|
||||
types.Tconv = func(t *types.Type, flag, mode, depth int) string {
|
||||
return tconv(t, FmtFlag(flag), fmtMode(mode), depth)
|
||||
types.Tconv = func(t *types.Type, flag, mode int) string {
|
||||
return tconv(t, FmtFlag(flag), fmtMode(mode))
|
||||
}
|
||||
types.FormatSym = func(sym *types.Sym, s fmt.State, verb rune, mode int) {
|
||||
symFormat(sym, s, verb, fmtMode(mode))
|
||||
|
|
|
|||
|
|
@ -705,6 +705,12 @@ func (lv *Liveness) markUnsafePoints() {
|
|||
v = v.Args[0]
|
||||
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:
|
||||
// Args[0] is the address of the write
|
||||
// barrier control. Ignore Args[1],
|
||||
|
|
|
|||
|
|
@ -340,7 +340,8 @@ func buildssa(fn *Node, worker int) *ssa.Func {
|
|||
s.startmem = s.entryNewValue0(ssa.OpInitMem, types.TypeMem)
|
||||
|
||||
s.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
|
||||
// libraries, because there is extra code (added by rewriteToUseGot())
|
||||
// preceding the deferreturn/ret code that is generated by gencallret()
|
||||
|
|
@ -5968,23 +5969,22 @@ func genssa(f *ssa.Func, pp *Progs) {
|
|||
// Emit basic blocks
|
||||
for i, b := range f.Blocks {
|
||||
s.bstart[b.ID] = s.pp.next
|
||||
s.pp.nextLive = LivenessInvalid
|
||||
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
|
||||
thearch.SSAMarkMoves(&s, b)
|
||||
for _, v := range b.Values {
|
||||
x := s.pp.next
|
||||
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 {
|
||||
case ssa.OpInitMem:
|
||||
// memory arg needs no code
|
||||
|
|
@ -6018,12 +6018,22 @@ func genssa(f *ssa.Func, pp *Progs) {
|
|||
inlMarksByPos[pos] = append(inlMarksByPos[pos], p)
|
||||
|
||||
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.
|
||||
if firstPos != src.NoXPos {
|
||||
s.SetPos(firstPos)
|
||||
firstPos = src.NoXPos
|
||||
}
|
||||
// let the backend handle it
|
||||
thearch.SSAGenValue(&s, v)
|
||||
}
|
||||
|
||||
|
|
@ -6524,7 +6534,7 @@ func (s *SSAGenState) Call(v *ssa.Value) *obj.Prog {
|
|||
} else {
|
||||
// TODO(mdempsky): Can these differences be eliminated?
|
||||
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
|
||||
case sys.ARM, sys.ARM64, sys.MIPS, sys.MIPS64:
|
||||
p.To.Type = obj.TYPE_MEM
|
||||
|
|
|
|||
|
|
@ -1705,7 +1705,6 @@ func mkdotargslice(typ *types.Type, args []*Node, init *Nodes, ddd *Node) *Node
|
|||
if ddd != nil {
|
||||
esc = ddd.Esc
|
||||
}
|
||||
|
||||
if len(args) == 0 {
|
||||
n := nodnil()
|
||||
n.Type = typ
|
||||
|
|
@ -1740,6 +1739,9 @@ func walkCall(n *Node, init *Nodes) {
|
|||
// then assign the remaining arguments as a slice.
|
||||
if nf := params.NumFields(); nf > 0 {
|
||||
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:]
|
||||
slice := mkdotargslice(last.Type, tail, init, n.Right)
|
||||
// Allow immediate GC.
|
||||
|
|
@ -4067,11 +4069,15 @@ func walkCheckPtrArithmetic(n *Node, init *Nodes) *Node {
|
|||
|
||||
n = cheapexpr(n, init)
|
||||
|
||||
slice := mkdotargslice(types.NewSlice(types.Types[TUNSAFEPTR]), originals, init, nil)
|
||||
slice.Esc = EscNone
|
||||
slice.SetTransient(true)
|
||||
ddd := nodl(n.Pos, ODDDARG, nil, nil)
|
||||
ddd.Type = types.NewPtr(types.NewArray(types.Types[TUNSAFEPTR], int64(len(originals))))
|
||||
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))
|
||||
// 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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -321,12 +321,14 @@ func Enabled() bool {
|
|||
// byPos sorts diagnostics by source position.
|
||||
type byPos struct {
|
||||
ctxt *obj.Link
|
||||
a []LoggedOpt
|
||||
a []LoggedOpt
|
||||
}
|
||||
|
||||
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) Swap(i, j int) { x.a[i], x.a[j] = x.a[j], x.a[i] }
|
||||
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) Swap(i, j int) { x.a[i], x.a[j] = x.a[j], x.a[i] }
|
||||
|
||||
func writerForLSP(subdirpath, file string) io.WriteCloser {
|
||||
basename := file
|
||||
|
|
@ -367,7 +369,7 @@ func uriIfy(f string) DocumentURI {
|
|||
// Return filename, replacing a first occurrence of $GOROOT with the
|
||||
// actual value of the GOROOT (because LSP does not speak "$GOROOT").
|
||||
func uprootedPath(filename string) string {
|
||||
if ! strings.HasPrefix(filename, "$GOROOT/") {
|
||||
if !strings.HasPrefix(filename, "$GOROOT/") {
|
||||
return filename
|
||||
}
|
||||
return objabi.GOROOT + filename[len("$GOROOT"):]
|
||||
|
|
@ -379,7 +381,7 @@ func FlushLoggedOpts(ctxt *obj.Link, slashPkgPath string) {
|
|||
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 {
|
||||
|
||||
case Json0: // LSP 3.15
|
||||
|
|
|
|||
25
src/cmd/compile/internal/riscv64/galign.go
Normal file
25
src/cmd/compile/internal/riscv64/galign.go
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package riscv64
|
||||
|
||||
import (
|
||||
"cmd/compile/internal/gc"
|
||||
"cmd/internal/obj/riscv"
|
||||
)
|
||||
|
||||
func Init(arch *gc.Arch) {
|
||||
arch.LinkArch = &riscv.LinkRISCV64
|
||||
|
||||
arch.REGSP = riscv.REG_SP
|
||||
arch.MAXWIDTH = 1 << 50
|
||||
|
||||
arch.Ginsnop = ginsnop
|
||||
arch.Ginsnopdefer = ginsnop
|
||||
arch.ZeroRange = zeroRange
|
||||
|
||||
arch.SSAMarkMoves = ssaMarkMoves
|
||||
arch.SSAGenValue = ssaGenValue
|
||||
arch.SSAGenBlock = ssaGenBlock
|
||||
}
|
||||
48
src/cmd/compile/internal/riscv64/ggen.go
Normal file
48
src/cmd/compile/internal/riscv64/ggen.go
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package riscv64
|
||||
|
||||
import (
|
||||
"cmd/compile/internal/gc"
|
||||
"cmd/internal/obj"
|
||||
"cmd/internal/obj/riscv"
|
||||
)
|
||||
|
||||
func zeroRange(pp *gc.Progs, p *obj.Prog, off, cnt int64, _ *uint32) *obj.Prog {
|
||||
if cnt == 0 {
|
||||
return p
|
||||
}
|
||||
|
||||
// Adjust the frame to account for LR.
|
||||
off += gc.Ctxt.FixedFrameSize()
|
||||
|
||||
if cnt < int64(4*gc.Widthptr) {
|
||||
for i := int64(0); i < cnt; i += int64(gc.Widthptr) {
|
||||
p = pp.Appendpp(p, riscv.AMOV, obj.TYPE_REG, riscv.REG_ZERO, 0, obj.TYPE_MEM, riscv.REG_SP, off+i)
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// TODO(jsing): Add a duff zero implementation for medium sized ranges.
|
||||
|
||||
// Loop, zeroing pointer width bytes at a time.
|
||||
// ADD $(off), SP, T0
|
||||
// ADD $(cnt), T0, T1
|
||||
// loop:
|
||||
// MOV ZERO, (T0)
|
||||
// ADD $Widthptr, T0
|
||||
// BNE T0, T1, loop
|
||||
p = pp.Appendpp(p, riscv.AADD, obj.TYPE_CONST, 0, off, obj.TYPE_REG, riscv.REG_T0, 0)
|
||||
p.Reg = riscv.REG_SP
|
||||
p = pp.Appendpp(p, riscv.AADD, obj.TYPE_CONST, 0, cnt, obj.TYPE_REG, riscv.REG_T1, 0)
|
||||
p.Reg = riscv.REG_T0
|
||||
p = pp.Appendpp(p, riscv.AMOV, obj.TYPE_REG, riscv.REG_ZERO, 0, obj.TYPE_MEM, riscv.REG_T0, 0)
|
||||
loop := p
|
||||
p = pp.Appendpp(p, riscv.AADD, obj.TYPE_CONST, 0, int64(gc.Widthptr), obj.TYPE_REG, riscv.REG_T0, 0)
|
||||
p = pp.Appendpp(p, riscv.ABNE, obj.TYPE_REG, riscv.REG_T0, 0, obj.TYPE_BRANCH, 0, 0)
|
||||
p.Reg = riscv.REG_T1
|
||||
gc.Patch(p, loop)
|
||||
return p
|
||||
}
|
||||
20
src/cmd/compile/internal/riscv64/gsubr.go
Normal file
20
src/cmd/compile/internal/riscv64/gsubr.go
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package riscv64
|
||||
|
||||
import (
|
||||
"cmd/compile/internal/gc"
|
||||
"cmd/internal/obj"
|
||||
"cmd/internal/obj/riscv"
|
||||
)
|
||||
|
||||
func ginsnop(pp *gc.Progs) *obj.Prog {
|
||||
// Hardware nop is ADD $0, ZERO
|
||||
p := pp.Prog(riscv.AADD)
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.Reg = riscv.REG_ZERO
|
||||
p.To = obj.Addr{Type: obj.TYPE_REG, Reg: riscv.REG_ZERO}
|
||||
return p
|
||||
}
|
||||
496
src/cmd/compile/internal/riscv64/ssa.go
Normal file
496
src/cmd/compile/internal/riscv64/ssa.go
Normal file
|
|
@ -0,0 +1,496 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package riscv64
|
||||
|
||||
import (
|
||||
"cmd/compile/internal/gc"
|
||||
"cmd/compile/internal/ssa"
|
||||
"cmd/compile/internal/types"
|
||||
"cmd/internal/obj"
|
||||
"cmd/internal/obj/riscv"
|
||||
)
|
||||
|
||||
// ssaRegToReg maps ssa register numbers to obj register numbers.
|
||||
var ssaRegToReg = []int16{
|
||||
riscv.REG_X0,
|
||||
// X1 (LR): unused
|
||||
riscv.REG_X2,
|
||||
riscv.REG_X3,
|
||||
riscv.REG_X4,
|
||||
riscv.REG_X5,
|
||||
riscv.REG_X6,
|
||||
riscv.REG_X7,
|
||||
riscv.REG_X8,
|
||||
riscv.REG_X9,
|
||||
riscv.REG_X10,
|
||||
riscv.REG_X11,
|
||||
riscv.REG_X12,
|
||||
riscv.REG_X13,
|
||||
riscv.REG_X14,
|
||||
riscv.REG_X15,
|
||||
riscv.REG_X16,
|
||||
riscv.REG_X17,
|
||||
riscv.REG_X18,
|
||||
riscv.REG_X19,
|
||||
riscv.REG_X20,
|
||||
riscv.REG_X21,
|
||||
riscv.REG_X22,
|
||||
riscv.REG_X23,
|
||||
riscv.REG_X24,
|
||||
riscv.REG_X25,
|
||||
riscv.REG_X26,
|
||||
riscv.REG_X27,
|
||||
riscv.REG_X28,
|
||||
riscv.REG_X29,
|
||||
riscv.REG_X30,
|
||||
riscv.REG_X31,
|
||||
riscv.REG_F0,
|
||||
riscv.REG_F1,
|
||||
riscv.REG_F2,
|
||||
riscv.REG_F3,
|
||||
riscv.REG_F4,
|
||||
riscv.REG_F5,
|
||||
riscv.REG_F6,
|
||||
riscv.REG_F7,
|
||||
riscv.REG_F8,
|
||||
riscv.REG_F9,
|
||||
riscv.REG_F10,
|
||||
riscv.REG_F11,
|
||||
riscv.REG_F12,
|
||||
riscv.REG_F13,
|
||||
riscv.REG_F14,
|
||||
riscv.REG_F15,
|
||||
riscv.REG_F16,
|
||||
riscv.REG_F17,
|
||||
riscv.REG_F18,
|
||||
riscv.REG_F19,
|
||||
riscv.REG_F20,
|
||||
riscv.REG_F21,
|
||||
riscv.REG_F22,
|
||||
riscv.REG_F23,
|
||||
riscv.REG_F24,
|
||||
riscv.REG_F25,
|
||||
riscv.REG_F26,
|
||||
riscv.REG_F27,
|
||||
riscv.REG_F28,
|
||||
riscv.REG_F29,
|
||||
riscv.REG_F30,
|
||||
riscv.REG_F31,
|
||||
0, // SB isn't a real register. We fill an Addr.Reg field with 0 in this case.
|
||||
}
|
||||
|
||||
func loadByType(t *types.Type) obj.As {
|
||||
width := t.Size()
|
||||
|
||||
if t.IsFloat() {
|
||||
switch width {
|
||||
case 4:
|
||||
return riscv.AMOVF
|
||||
case 8:
|
||||
return riscv.AMOVD
|
||||
default:
|
||||
gc.Fatalf("unknown float width for load %d in type %v", width, t)
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
switch width {
|
||||
case 1:
|
||||
if t.IsSigned() {
|
||||
return riscv.AMOVB
|
||||
} else {
|
||||
return riscv.AMOVBU
|
||||
}
|
||||
case 2:
|
||||
if t.IsSigned() {
|
||||
return riscv.AMOVH
|
||||
} else {
|
||||
return riscv.AMOVHU
|
||||
}
|
||||
case 4:
|
||||
if t.IsSigned() {
|
||||
return riscv.AMOVW
|
||||
} else {
|
||||
return riscv.AMOVWU
|
||||
}
|
||||
case 8:
|
||||
return riscv.AMOV
|
||||
default:
|
||||
gc.Fatalf("unknown width for load %d in type %v", width, t)
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
// storeByType returns the store instruction of the given type.
|
||||
func storeByType(t *types.Type) obj.As {
|
||||
width := t.Size()
|
||||
|
||||
if t.IsFloat() {
|
||||
switch width {
|
||||
case 4:
|
||||
return riscv.AMOVF
|
||||
case 8:
|
||||
return riscv.AMOVD
|
||||
default:
|
||||
gc.Fatalf("unknown float width for store %d in type %v", width, t)
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
switch width {
|
||||
case 1:
|
||||
return riscv.AMOVB
|
||||
case 2:
|
||||
return riscv.AMOVH
|
||||
case 4:
|
||||
return riscv.AMOVW
|
||||
case 8:
|
||||
return riscv.AMOV
|
||||
default:
|
||||
gc.Fatalf("unknown width for store %d in type %v", width, t)
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
// largestMove returns the largest move instruction possible and its size,
|
||||
// given the alignment of the total size of the move.
|
||||
//
|
||||
// e.g., a 16-byte move may use MOV, but an 11-byte move must use MOVB.
|
||||
//
|
||||
// Note that the moves may not be on naturally aligned addresses depending on
|
||||
// the source and destination.
|
||||
//
|
||||
// This matches the calculation in ssa.moveSize.
|
||||
func largestMove(alignment int64) (obj.As, int64) {
|
||||
switch {
|
||||
case alignment%8 == 0:
|
||||
return riscv.AMOV, 8
|
||||
case alignment%4 == 0:
|
||||
return riscv.AMOVW, 4
|
||||
case alignment%2 == 0:
|
||||
return riscv.AMOVH, 2
|
||||
default:
|
||||
return riscv.AMOVB, 1
|
||||
}
|
||||
}
|
||||
|
||||
// markMoves marks any MOVXconst ops that need to avoid clobbering flags.
|
||||
// RISC-V has no flags, so this is a no-op.
|
||||
func ssaMarkMoves(s *gc.SSAGenState, b *ssa.Block) {}
|
||||
|
||||
func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||
s.SetPos(v.Pos)
|
||||
|
||||
switch v.Op {
|
||||
case ssa.OpInitMem:
|
||||
// memory arg needs no code
|
||||
case ssa.OpArg:
|
||||
// input args need no code
|
||||
case ssa.OpPhi:
|
||||
gc.CheckLoweredPhi(v)
|
||||
case ssa.OpCopy, ssa.OpRISCV64MOVconvert:
|
||||
if v.Type.IsMemory() {
|
||||
return
|
||||
}
|
||||
rs := v.Args[0].Reg()
|
||||
rd := v.Reg()
|
||||
if rs == rd {
|
||||
return
|
||||
}
|
||||
as := riscv.AMOV
|
||||
if v.Type.IsFloat() {
|
||||
as = riscv.AMOVD
|
||||
}
|
||||
p := s.Prog(as)
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = rs
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = rd
|
||||
case ssa.OpLoadReg:
|
||||
if v.Type.IsFlags() {
|
||||
v.Fatalf("load flags not implemented: %v", v.LongString())
|
||||
return
|
||||
}
|
||||
p := s.Prog(loadByType(v.Type))
|
||||
gc.AddrAuto(&p.From, v.Args[0])
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = v.Reg()
|
||||
case ssa.OpStoreReg:
|
||||
if v.Type.IsFlags() {
|
||||
v.Fatalf("store flags not implemented: %v", v.LongString())
|
||||
return
|
||||
}
|
||||
p := s.Prog(storeByType(v.Type))
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = v.Args[0].Reg()
|
||||
gc.AddrAuto(&p.To, v)
|
||||
case ssa.OpSP, ssa.OpSB, ssa.OpGetG:
|
||||
// nothing to do
|
||||
case ssa.OpRISCV64ADD, ssa.OpRISCV64SUB, ssa.OpRISCV64XOR, ssa.OpRISCV64OR, ssa.OpRISCV64AND,
|
||||
ssa.OpRISCV64SLL, ssa.OpRISCV64SRA, ssa.OpRISCV64SRL,
|
||||
ssa.OpRISCV64SLT, ssa.OpRISCV64SLTU, ssa.OpRISCV64MUL, ssa.OpRISCV64MULW, ssa.OpRISCV64MULH,
|
||||
ssa.OpRISCV64MULHU, ssa.OpRISCV64DIV, ssa.OpRISCV64DIVU, ssa.OpRISCV64DIVW,
|
||||
ssa.OpRISCV64DIVUW, ssa.OpRISCV64REM, ssa.OpRISCV64REMU, ssa.OpRISCV64REMW,
|
||||
ssa.OpRISCV64REMUW,
|
||||
ssa.OpRISCV64FADDS, ssa.OpRISCV64FSUBS, ssa.OpRISCV64FMULS, ssa.OpRISCV64FDIVS,
|
||||
ssa.OpRISCV64FEQS, ssa.OpRISCV64FNES, ssa.OpRISCV64FLTS, ssa.OpRISCV64FLES,
|
||||
ssa.OpRISCV64FADDD, ssa.OpRISCV64FSUBD, ssa.OpRISCV64FMULD, ssa.OpRISCV64FDIVD,
|
||||
ssa.OpRISCV64FEQD, ssa.OpRISCV64FNED, ssa.OpRISCV64FLTD, ssa.OpRISCV64FLED:
|
||||
r := v.Reg()
|
||||
r1 := v.Args[0].Reg()
|
||||
r2 := v.Args[1].Reg()
|
||||
p := s.Prog(v.Op.Asm())
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = r2
|
||||
p.Reg = r1
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = r
|
||||
case ssa.OpRISCV64FSQRTS, ssa.OpRISCV64FNEGS, ssa.OpRISCV64FSQRTD, ssa.OpRISCV64FNEGD,
|
||||
ssa.OpRISCV64FMVSX, ssa.OpRISCV64FMVDX,
|
||||
ssa.OpRISCV64FCVTSW, ssa.OpRISCV64FCVTSL, ssa.OpRISCV64FCVTWS, ssa.OpRISCV64FCVTLS,
|
||||
ssa.OpRISCV64FCVTDW, ssa.OpRISCV64FCVTDL, ssa.OpRISCV64FCVTWD, ssa.OpRISCV64FCVTLD, ssa.OpRISCV64FCVTDS, ssa.OpRISCV64FCVTSD:
|
||||
p := s.Prog(v.Op.Asm())
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = v.Args[0].Reg()
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = v.Reg()
|
||||
case ssa.OpRISCV64ADDI, ssa.OpRISCV64XORI, ssa.OpRISCV64ORI, ssa.OpRISCV64ANDI,
|
||||
ssa.OpRISCV64SLLI, ssa.OpRISCV64SRAI, ssa.OpRISCV64SRLI, ssa.OpRISCV64SLTI,
|
||||
ssa.OpRISCV64SLTIU:
|
||||
p := s.Prog(v.Op.Asm())
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = v.AuxInt
|
||||
p.Reg = v.Args[0].Reg()
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = v.Reg()
|
||||
case ssa.OpRISCV64MOVBconst, ssa.OpRISCV64MOVHconst, ssa.OpRISCV64MOVWconst, ssa.OpRISCV64MOVDconst:
|
||||
p := s.Prog(v.Op.Asm())
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = v.AuxInt
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = v.Reg()
|
||||
case ssa.OpRISCV64MOVaddr:
|
||||
p := s.Prog(v.Op.Asm())
|
||||
p.From.Type = obj.TYPE_ADDR
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = v.Reg()
|
||||
|
||||
var wantreg string
|
||||
// MOVW $sym+off(base), R
|
||||
switch v.Aux.(type) {
|
||||
default:
|
||||
v.Fatalf("aux is of unknown type %T", v.Aux)
|
||||
case *obj.LSym:
|
||||
wantreg = "SB"
|
||||
gc.AddAux(&p.From, v)
|
||||
case *gc.Node:
|
||||
wantreg = "SP"
|
||||
gc.AddAux(&p.From, v)
|
||||
case nil:
|
||||
// No sym, just MOVW $off(SP), R
|
||||
wantreg = "SP"
|
||||
p.From.Reg = riscv.REG_SP
|
||||
p.From.Offset = v.AuxInt
|
||||
}
|
||||
if reg := v.Args[0].RegName(); reg != wantreg {
|
||||
v.Fatalf("bad reg %s for symbol type %T, want %s", reg, v.Aux, wantreg)
|
||||
}
|
||||
case ssa.OpRISCV64MOVBload, ssa.OpRISCV64MOVHload, ssa.OpRISCV64MOVWload, ssa.OpRISCV64MOVDload,
|
||||
ssa.OpRISCV64MOVBUload, ssa.OpRISCV64MOVHUload, ssa.OpRISCV64MOVWUload,
|
||||
ssa.OpRISCV64FMOVWload, ssa.OpRISCV64FMOVDload:
|
||||
p := s.Prog(v.Op.Asm())
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Reg = v.Args[0].Reg()
|
||||
gc.AddAux(&p.From, v)
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = v.Reg()
|
||||
case ssa.OpRISCV64MOVBstore, ssa.OpRISCV64MOVHstore, ssa.OpRISCV64MOVWstore, ssa.OpRISCV64MOVDstore,
|
||||
ssa.OpRISCV64FMOVWstore, ssa.OpRISCV64FMOVDstore:
|
||||
p := s.Prog(v.Op.Asm())
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = v.Args[1].Reg()
|
||||
p.To.Type = obj.TYPE_MEM
|
||||
p.To.Reg = v.Args[0].Reg()
|
||||
gc.AddAux(&p.To, v)
|
||||
case ssa.OpRISCV64SEQZ, ssa.OpRISCV64SNEZ:
|
||||
p := s.Prog(v.Op.Asm())
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = v.Args[0].Reg()
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = v.Reg()
|
||||
case ssa.OpRISCV64CALLstatic, ssa.OpRISCV64CALLclosure, ssa.OpRISCV64CALLinter:
|
||||
s.Call(v)
|
||||
case ssa.OpRISCV64LoweredWB:
|
||||
p := s.Prog(obj.ACALL)
|
||||
p.To.Type = obj.TYPE_MEM
|
||||
p.To.Name = obj.NAME_EXTERN
|
||||
p.To.Sym = v.Aux.(*obj.LSym)
|
||||
case ssa.OpRISCV64LoweredPanicBoundsA, ssa.OpRISCV64LoweredPanicBoundsB, ssa.OpRISCV64LoweredPanicBoundsC:
|
||||
p := s.Prog(obj.ACALL)
|
||||
p.To.Type = obj.TYPE_MEM
|
||||
p.To.Name = obj.NAME_EXTERN
|
||||
p.To.Sym = gc.BoundsCheckFunc[v.AuxInt]
|
||||
s.UseArgs(16) // space used in callee args area by assembly stubs
|
||||
case ssa.OpRISCV64LoweredZero:
|
||||
mov, sz := largestMove(v.AuxInt)
|
||||
|
||||
// mov ZERO, (Rarg0)
|
||||
// ADD $sz, Rarg0
|
||||
// BGEU Rarg1, Rarg0, -2(PC)
|
||||
|
||||
p := s.Prog(mov)
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = riscv.REG_ZERO
|
||||
p.To.Type = obj.TYPE_MEM
|
||||
p.To.Reg = v.Args[0].Reg()
|
||||
|
||||
p2 := s.Prog(riscv.AADD)
|
||||
p2.From.Type = obj.TYPE_CONST
|
||||
p2.From.Offset = sz
|
||||
p2.To.Type = obj.TYPE_REG
|
||||
p2.To.Reg = v.Args[0].Reg()
|
||||
|
||||
p3 := s.Prog(riscv.ABGEU)
|
||||
p3.To.Type = obj.TYPE_BRANCH
|
||||
p3.Reg = v.Args[0].Reg()
|
||||
p3.From.Type = obj.TYPE_REG
|
||||
p3.From.Reg = v.Args[1].Reg()
|
||||
gc.Patch(p3, p)
|
||||
|
||||
case ssa.OpRISCV64LoweredMove:
|
||||
mov, sz := largestMove(v.AuxInt)
|
||||
|
||||
// mov (Rarg1), T2
|
||||
// mov T2, (Rarg0)
|
||||
// ADD $sz, Rarg0
|
||||
// ADD $sz, Rarg1
|
||||
// BGEU Rarg2, Rarg0, -4(PC)
|
||||
|
||||
p := s.Prog(mov)
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Reg = v.Args[1].Reg()
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = riscv.REG_T2
|
||||
|
||||
p2 := s.Prog(mov)
|
||||
p2.From.Type = obj.TYPE_REG
|
||||
p2.From.Reg = riscv.REG_T2
|
||||
p2.To.Type = obj.TYPE_MEM
|
||||
p2.To.Reg = v.Args[0].Reg()
|
||||
|
||||
p3 := s.Prog(riscv.AADD)
|
||||
p3.From.Type = obj.TYPE_CONST
|
||||
p3.From.Offset = sz
|
||||
p3.To.Type = obj.TYPE_REG
|
||||
p3.To.Reg = v.Args[0].Reg()
|
||||
|
||||
p4 := s.Prog(riscv.AADD)
|
||||
p4.From.Type = obj.TYPE_CONST
|
||||
p4.From.Offset = sz
|
||||
p4.To.Type = obj.TYPE_REG
|
||||
p4.To.Reg = v.Args[1].Reg()
|
||||
|
||||
p5 := s.Prog(riscv.ABGEU)
|
||||
p5.To.Type = obj.TYPE_BRANCH
|
||||
p5.Reg = v.Args[1].Reg()
|
||||
p5.From.Type = obj.TYPE_REG
|
||||
p5.From.Reg = v.Args[2].Reg()
|
||||
gc.Patch(p5, p)
|
||||
|
||||
case ssa.OpRISCV64LoweredNilCheck:
|
||||
// Issue a load which will fault if arg is nil.
|
||||
// TODO: optimizations. See arm and amd64 LoweredNilCheck.
|
||||
p := s.Prog(riscv.AMOVB)
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Reg = v.Args[0].Reg()
|
||||
gc.AddAux(&p.From, v)
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = riscv.REG_ZERO
|
||||
if gc.Debug_checknil != 0 && v.Pos.Line() > 1 { // v.Pos == 1 in generated wrappers
|
||||
gc.Warnl(v.Pos, "generated nil check")
|
||||
}
|
||||
|
||||
case ssa.OpRISCV64LoweredGetClosurePtr:
|
||||
// Closure pointer is S4 (riscv.REG_CTXT).
|
||||
gc.CheckLoweredGetClosurePtr(v)
|
||||
|
||||
case ssa.OpRISCV64LoweredGetCallerSP:
|
||||
// caller's SP is FixedFrameSize below the address of the first arg
|
||||
p := s.Prog(riscv.AMOV)
|
||||
p.From.Type = obj.TYPE_ADDR
|
||||
p.From.Offset = -gc.Ctxt.FixedFrameSize()
|
||||
p.From.Name = obj.NAME_PARAM
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = v.Reg()
|
||||
|
||||
case ssa.OpRISCV64LoweredGetCallerPC:
|
||||
p := s.Prog(obj.AGETCALLERPC)
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = v.Reg()
|
||||
|
||||
default:
|
||||
v.Fatalf("Unhandled op %v", v.Op)
|
||||
}
|
||||
}
|
||||
|
||||
func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
|
||||
s.SetPos(b.Pos)
|
||||
|
||||
switch b.Kind {
|
||||
case ssa.BlockDefer:
|
||||
// defer returns in A0:
|
||||
// 0 if we should continue executing
|
||||
// 1 if we should jump to deferreturn call
|
||||
p := s.Prog(riscv.ABNE)
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = riscv.REG_ZERO
|
||||
p.Reg = riscv.REG_A0
|
||||
s.Branches = append(s.Branches, gc.Branch{P: p, B: b.Succs[1].Block()})
|
||||
if b.Succs[0].Block() != next {
|
||||
p := s.Prog(obj.AJMP)
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
s.Branches = append(s.Branches, gc.Branch{P: p, B: b.Succs[0].Block()})
|
||||
}
|
||||
case ssa.BlockPlain:
|
||||
if b.Succs[0].Block() != next {
|
||||
p := s.Prog(obj.AJMP)
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
s.Branches = append(s.Branches, gc.Branch{P: p, B: b.Succs[0].Block()})
|
||||
}
|
||||
case ssa.BlockExit:
|
||||
case ssa.BlockRet:
|
||||
s.Prog(obj.ARET)
|
||||
case ssa.BlockRetJmp:
|
||||
p := s.Prog(obj.AJMP)
|
||||
p.To.Type = obj.TYPE_MEM
|
||||
p.To.Name = obj.NAME_EXTERN
|
||||
p.To.Sym = b.Aux.(*obj.LSym)
|
||||
case ssa.BlockRISCV64BNE:
|
||||
var p *obj.Prog
|
||||
switch next {
|
||||
case b.Succs[0].Block():
|
||||
p = s.Br(riscv.ABNE, b.Succs[1].Block())
|
||||
p.As = riscv.InvertBranch(p.As)
|
||||
case b.Succs[1].Block():
|
||||
p = s.Br(riscv.ABNE, b.Succs[0].Block())
|
||||
default:
|
||||
if b.Likely != ssa.BranchUnlikely {
|
||||
p = s.Br(riscv.ABNE, b.Succs[0].Block())
|
||||
s.Br(obj.AJMP, b.Succs[1].Block())
|
||||
} else {
|
||||
p = s.Br(riscv.ABNE, b.Succs[1].Block())
|
||||
p.As = riscv.InvertBranch(p.As)
|
||||
s.Br(obj.AJMP, b.Succs[0].Block())
|
||||
}
|
||||
}
|
||||
p.Reg = b.Controls[0].Reg()
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = riscv.REG_ZERO
|
||||
|
||||
default:
|
||||
b.Fatalf("Unhandled block: %s", b.LongString())
|
||||
}
|
||||
}
|
||||
|
|
@ -305,6 +305,16 @@ func NewConfig(arch string, types Types, ctxt *obj.Link, optimize bool) *Config
|
|||
c.LinkReg = linkRegMIPS
|
||||
c.hasGReg = 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":
|
||||
c.PtrSize = 8
|
||||
c.RegSize = 8
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ func init() {
|
|||
// TODO(josharian): move universe initialization to the types package,
|
||||
// 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()
|
||||
}
|
||||
types.Sconv = func(s *types.Sym, flag, mode int) string {
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ func fuseBlockIf(b *Block) bool {
|
|||
// There may be false positives.
|
||||
func isEmpty(b *Block) bool {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ func TestFuseEliminatesBothBranches(t *testing.T) {
|
|||
t.Errorf("then was not eliminated, but should have")
|
||||
}
|
||||
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")
|
||||
}
|
||||
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) {
|
||||
for _, n := range [...]int{1, 10, 100, 1000, 10000} {
|
||||
b.Run(strconv.Itoa(n), func(b *testing.B) {
|
||||
|
|
|
|||
|
|
@ -813,7 +813,7 @@
|
|||
(MFVSRD x:(FMOVDload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVDload [off] {sym} ptr mem)
|
||||
|
||||
// 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)
|
||||
(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)
|
||||
|
|
@ -836,7 +836,7 @@
|
|||
&& (ptr.Op != OpSB || p.Uses == 1) ->
|
||||
(MOVWstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
|
||||
(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)
|
||||
|
||||
(FMOVSstore [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2)
|
||||
|
|
@ -856,13 +856,13 @@
|
|||
&& (ptr.Op != OpSB || p.Uses == 1) ->
|
||||
(MOVHZload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||
(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)
|
||||
(MOVWZload [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
|
||||
&& (ptr.Op != OpSB || p.Uses == 1) ->
|
||||
(MOVWZload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||
(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)
|
||||
(FMOVSload [off1] {sym1} p:(MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
|
||||
&& (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)
|
||||
(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)
|
||||
(MOVWload [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(off1+off2) -> (MOVWload [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) && (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)
|
||||
(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)
|
||||
|
|
@ -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)
|
||||
|
||||
// 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|WZ|H|HZ|BZ)loadidx (MOVDconst [c]) ptr 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(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
|
||||
(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)
|
||||
|
||||
// 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)
|
||||
(MOVWstorezero [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(off1+off2) ->
|
||||
(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)
|
||||
|
||||
// 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)
|
||||
(MOV(D|W|H|B)storeidx (MOVDconst [c]) ptr 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(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
|
||||
(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)
|
||||
(MOVWstorezero [off1] {sym1} p:(MOVDaddr [off2] {sym2} x) mem) && canMergeSym(sym1,sym2)
|
||||
&& (x.Op != OpSB || p.Uses == 1) ->
|
||||
|
|
|
|||
478
src/cmd/compile/internal/ssa/gen/RISCV64.rules
Normal file
478
src/cmd/compile/internal/ssa/gen/RISCV64.rules
Normal file
|
|
@ -0,0 +1,478 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Optimizations TODO:
|
||||
// * Somehow track when values are already zero/signed-extended, avoid re-extending.
|
||||
// * Use SLTI and SLTIU for comparisons to constants, instead of SLT/SLTU with constants in registers
|
||||
// * Find a more efficient way to do zero/sign extension than left+right shift.
|
||||
// There are many other options (store then load-extend, LUI+ANDI for zero extend, special case 32->64, ...),
|
||||
// but left+right shift is simple and uniform, and we don't have real hardware to do perf testing on anyway.
|
||||
// * Use the zero register instead of moving 0 into a register.
|
||||
// * Add rules to avoid generating a temp bool value for (If (SLT[U] ...) ...).
|
||||
// * Optimize left and right shift by simplifying SLTIU, Neg, and ADD for constants.
|
||||
// * Arrange for non-trivial Zero and Move lowerings to use aligned loads and stores.
|
||||
// * Eliminate zero immediate shifts, adds, etc.
|
||||
// * Use a Duff's device for some moves and zeros.
|
||||
// * Avoid using Neq32 for writeBarrier.enabled checks.
|
||||
|
||||
// Lowering arithmetic
|
||||
(Add64 x y) -> (ADD x y)
|
||||
(AddPtr x y) -> (ADD x y)
|
||||
(Add32 x y) -> (ADD x y)
|
||||
(Add16 x y) -> (ADD x y)
|
||||
(Add8 x y) -> (ADD x y)
|
||||
(Add32F x y) -> (FADDS x y)
|
||||
(Add64F x y) -> (FADDD x y)
|
||||
|
||||
(Sub64 x y) -> (SUB x y)
|
||||
(SubPtr x y) -> (SUB x y)
|
||||
(Sub32 x y) -> (SUB x y)
|
||||
(Sub16 x y) -> (SUB x y)
|
||||
(Sub8 x y) -> (SUB x y)
|
||||
(Sub32F x y) -> (FSUBS x y)
|
||||
(Sub64F x y) -> (FSUBD x y)
|
||||
|
||||
(Mul64 x y) -> (MUL x y)
|
||||
(Mul32 x y) -> (MULW x y)
|
||||
(Mul16 x y) -> (MULW (SignExt16to32 x) (SignExt16to32 y))
|
||||
(Mul8 x y) -> (MULW (SignExt8to32 x) (SignExt8to32 y))
|
||||
(Mul32F x y) -> (FMULS x y)
|
||||
(Mul64F x y) -> (FMULD x y)
|
||||
|
||||
(Div32F x y) -> (FDIVS x y)
|
||||
(Div64F x y) -> (FDIVD x y)
|
||||
|
||||
(Div64 x y) -> (DIV x y)
|
||||
(Div64u x y) -> (DIVU x y)
|
||||
(Div32 x y) -> (DIVW x y)
|
||||
(Div32u x y) -> (DIVUW x y)
|
||||
(Div16 x y) -> (DIVW (SignExt16to32 x) (SignExt16to32 y))
|
||||
(Div16u x y) -> (DIVUW (ZeroExt16to32 x) (ZeroExt16to32 y))
|
||||
(Div8 x y) -> (DIVW (SignExt8to32 x) (SignExt8to32 y))
|
||||
(Div8u x y) -> (DIVUW (ZeroExt8to32 x) (ZeroExt8to32 y))
|
||||
|
||||
(Hmul64 x y) -> (MULH x y)
|
||||
(Hmul64u x y) -> (MULHU x y)
|
||||
(Hmul32 x y) -> (SRAI [32] (MUL (SignExt32to64 x) (SignExt32to64 y)))
|
||||
(Hmul32u x y) -> (SRLI [32] (MUL (ZeroExt32to64 x) (ZeroExt32to64 y)))
|
||||
|
||||
// (x + y) / 2 -> (x / 2) + (y / 2) + (x & y & 1)
|
||||
(Avg64u <t> x y) -> (ADD (ADD <t> (SRLI <t> [1] x) (SRLI <t> [1] y)) (ANDI <t> [1] (AND <t> x y)))
|
||||
|
||||
(Mod64 x y) -> (REM x y)
|
||||
(Mod64u x y) -> (REMU x y)
|
||||
(Mod32 x y) -> (REMW x y)
|
||||
(Mod32u x y) -> (REMUW x y)
|
||||
(Mod16 x y) -> (REMW (SignExt16to32 x) (SignExt16to32 y))
|
||||
(Mod16u x y) -> (REMUW (ZeroExt16to32 x) (ZeroExt16to32 y))
|
||||
(Mod8 x y) -> (REMW (SignExt8to32 x) (SignExt8to32 y))
|
||||
(Mod8u x y) -> (REMUW (ZeroExt8to32 x) (ZeroExt8to32 y))
|
||||
|
||||
(And64 x y) -> (AND x y)
|
||||
(And32 x y) -> (AND x y)
|
||||
(And16 x y) -> (AND x y)
|
||||
(And8 x y) -> (AND x y)
|
||||
|
||||
(Or64 x y) -> (OR x y)
|
||||
(Or32 x y) -> (OR x y)
|
||||
(Or16 x y) -> (OR x y)
|
||||
(Or8 x y) -> (OR x y)
|
||||
|
||||
(Xor64 x y) -> (XOR x y)
|
||||
(Xor32 x y) -> (XOR x y)
|
||||
(Xor16 x y) -> (XOR x y)
|
||||
(Xor8 x y) -> (XOR x y)
|
||||
|
||||
(Neg64 x) -> (SUB (MOVDconst) x)
|
||||
(Neg32 x) -> (SUB (MOVWconst) x)
|
||||
(Neg16 x) -> (SUB (MOVHconst) x)
|
||||
(Neg8 x) -> (SUB (MOVBconst) x)
|
||||
(Neg32F x) -> (FNEGS x)
|
||||
(Neg64F x) -> (FNEGD x)
|
||||
|
||||
(Com64 x) -> (XORI [int64(-1)] x)
|
||||
(Com32 x) -> (XORI [int64(-1)] x)
|
||||
(Com16 x) -> (XORI [int64(-1)] x)
|
||||
(Com8 x) -> (XORI [int64(-1)] x)
|
||||
|
||||
(Sqrt x) -> (FSQRTD x)
|
||||
|
||||
// Zero and sign extension
|
||||
// Shift left until the bits we want are at the top of the register.
|
||||
// Then logical/arithmetic shift right for zero/sign extend.
|
||||
// We always extend to 64 bits; there's no reason not to,
|
||||
// and optimization rules can then collapse some extensions.
|
||||
|
||||
(SignExt8to16 <t> x) -> (SRAI [56] (SLLI <t> [56] x))
|
||||
(SignExt8to32 <t> x) -> (SRAI [56] (SLLI <t> [56] x))
|
||||
(SignExt8to64 <t> x) -> (SRAI [56] (SLLI <t> [56] x))
|
||||
(SignExt16to32 <t> x) -> (SRAI [48] (SLLI <t> [48] x))
|
||||
(SignExt16to64 <t> x) -> (SRAI [48] (SLLI <t> [48] x))
|
||||
(SignExt32to64 <t> x) -> (SRAI [32] (SLLI <t> [32] x))
|
||||
|
||||
(ZeroExt8to16 <t> x) -> (SRLI [56] (SLLI <t> [56] x))
|
||||
(ZeroExt8to32 <t> x) -> (SRLI [56] (SLLI <t> [56] x))
|
||||
(ZeroExt8to64 <t> x) -> (SRLI [56] (SLLI <t> [56] x))
|
||||
(ZeroExt16to32 <t> x) -> (SRLI [48] (SLLI <t> [48] x))
|
||||
(ZeroExt16to64 <t> x) -> (SRLI [48] (SLLI <t> [48] x))
|
||||
(ZeroExt32to64 <t> x) -> (SRLI [32] (SLLI <t> [32] x))
|
||||
|
||||
(Cvt32to32F x) -> (FCVTSW x)
|
||||
(Cvt32to64F x) -> (FCVTDW x)
|
||||
(Cvt64to32F x) -> (FCVTSL x)
|
||||
(Cvt64to64F x) -> (FCVTDL x)
|
||||
|
||||
(Cvt32Fto32 x) -> (FCVTWS x)
|
||||
(Cvt32Fto64 x) -> (FCVTLS x)
|
||||
(Cvt64Fto32 x) -> (FCVTWD x)
|
||||
(Cvt64Fto64 x) -> (FCVTLD x)
|
||||
|
||||
(Cvt32Fto64F x) -> (FCVTDS x)
|
||||
(Cvt64Fto32F x) -> (FCVTSD x)
|
||||
|
||||
(Round32F x) -> x
|
||||
(Round64F x) -> x
|
||||
|
||||
// From genericOps.go:
|
||||
// "0 if arg0 == 0, -1 if arg0 > 0, undef if arg0<0"
|
||||
//
|
||||
// Like other arches, we compute ~((x-1) >> 63), with arithmetic right shift.
|
||||
// For positive x, bit 63 of x-1 is always 0, so the result is -1.
|
||||
// For zero x, bit 63 of x-1 is 1, so the result is 0.
|
||||
//
|
||||
// TODO(prattmic): Use XORconst etc instead of XOR (MOVDconst).
|
||||
(Slicemask <t> x) -> (XOR (MOVDconst [-1]) (SRA <t> (SUB <t> x (MOVDconst [1])) (MOVDconst [63])))
|
||||
|
||||
// Truncations
|
||||
// We ignore the unused high parts of registers, so truncates are just copies.
|
||||
(Trunc16to8 x) -> x
|
||||
(Trunc32to8 x) -> x
|
||||
(Trunc32to16 x) -> x
|
||||
(Trunc64to8 x) -> x
|
||||
(Trunc64to16 x) -> x
|
||||
(Trunc64to32 x) -> x
|
||||
|
||||
// Shifts
|
||||
|
||||
// SLL only considers the bottom 6 bits of y. If y > 64, the result should
|
||||
// always be 0.
|
||||
//
|
||||
// Breaking down the operation:
|
||||
//
|
||||
// (SLL x y) generates x << (y & 63).
|
||||
//
|
||||
// If y < 64, this is the value we want. Otherwise, we want zero.
|
||||
//
|
||||
// So, we AND with -1 * uint64(y < 64), which is 0xfffff... if y < 64 and 0 otherwise.
|
||||
(Lsh8x8 <t> x y) -> (AND (SLL <t> x y) (Neg8 <t> (SLTIU <t> [64] (ZeroExt8to64 y))))
|
||||
(Lsh8x16 <t> x y) -> (AND (SLL <t> x y) (Neg8 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
|
||||
(Lsh8x32 <t> x y) -> (AND (SLL <t> x y) (Neg8 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
|
||||
(Lsh8x64 <t> x y) -> (AND (SLL <t> x y) (Neg8 <t> (SLTIU <t> [64] y)))
|
||||
(Lsh16x8 <t> x y) -> (AND (SLL <t> x y) (Neg16 <t> (SLTIU <t> [64] (ZeroExt8to64 y))))
|
||||
(Lsh16x16 <t> x y) -> (AND (SLL <t> x y) (Neg16 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
|
||||
(Lsh16x32 <t> x y) -> (AND (SLL <t> x y) (Neg16 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
|
||||
(Lsh16x64 <t> x y) -> (AND (SLL <t> x y) (Neg16 <t> (SLTIU <t> [64] y)))
|
||||
(Lsh32x8 <t> x y) -> (AND (SLL <t> x y) (Neg32 <t> (SLTIU <t> [64] (ZeroExt8to64 y))))
|
||||
(Lsh32x16 <t> x y) -> (AND (SLL <t> x y) (Neg32 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
|
||||
(Lsh32x32 <t> x y) -> (AND (SLL <t> x y) (Neg32 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
|
||||
(Lsh32x64 <t> x y) -> (AND (SLL <t> x y) (Neg32 <t> (SLTIU <t> [64] y)))
|
||||
(Lsh64x8 <t> x y) -> (AND (SLL <t> x y) (Neg64 <t> (SLTIU <t> [64] (ZeroExt8to64 y))))
|
||||
(Lsh64x16 <t> x y) -> (AND (SLL <t> x y) (Neg64 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
|
||||
(Lsh64x32 <t> x y) -> (AND (SLL <t> x y) (Neg64 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
|
||||
(Lsh64x64 <t> x y) -> (AND (SLL <t> x y) (Neg64 <t> (SLTIU <t> [64] y)))
|
||||
|
||||
// SRL only considers the bottom 6 bits of y. If y > 64, the result should
|
||||
// always be 0. See Lsh above for a detailed description.
|
||||
(Rsh8Ux8 <t> x y) -> (AND (SRL <t> (ZeroExt8to64 x) y) (Neg8 <t> (SLTIU <t> [64] (ZeroExt8to64 y))))
|
||||
(Rsh8Ux16 <t> x y) -> (AND (SRL <t> (ZeroExt8to64 x) y) (Neg8 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
|
||||
(Rsh8Ux32 <t> x y) -> (AND (SRL <t> (ZeroExt8to64 x) y) (Neg8 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
|
||||
(Rsh8Ux64 <t> x y) -> (AND (SRL <t> (ZeroExt8to64 x) y) (Neg8 <t> (SLTIU <t> [64] y)))
|
||||
(Rsh16Ux8 <t> x y) -> (AND (SRL <t> (ZeroExt16to64 x) y) (Neg16 <t> (SLTIU <t> [64] (ZeroExt8to64 y))))
|
||||
(Rsh16Ux16 <t> x y) -> (AND (SRL <t> (ZeroExt16to64 x) y) (Neg16 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
|
||||
(Rsh16Ux32 <t> x y) -> (AND (SRL <t> (ZeroExt16to64 x) y) (Neg16 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
|
||||
(Rsh16Ux64 <t> x y) -> (AND (SRL <t> (ZeroExt16to64 x) y) (Neg16 <t> (SLTIU <t> [64] y)))
|
||||
(Rsh32Ux8 <t> x y) -> (AND (SRL <t> (ZeroExt32to64 x) y) (Neg32 <t> (SLTIU <t> [64] (ZeroExt8to64 y))))
|
||||
(Rsh32Ux16 <t> x y) -> (AND (SRL <t> (ZeroExt32to64 x) y) (Neg32 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
|
||||
(Rsh32Ux32 <t> x y) -> (AND (SRL <t> (ZeroExt32to64 x) y) (Neg32 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
|
||||
(Rsh32Ux64 <t> x y) -> (AND (SRL <t> (ZeroExt32to64 x) y) (Neg32 <t> (SLTIU <t> [64] y)))
|
||||
(Rsh64Ux8 <t> x y) -> (AND (SRL <t> x y) (Neg64 <t> (SLTIU <t> [64] (ZeroExt8to64 y))))
|
||||
(Rsh64Ux16 <t> x y) -> (AND (SRL <t> x y) (Neg64 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
|
||||
(Rsh64Ux32 <t> x y) -> (AND (SRL <t> x y) (Neg64 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
|
||||
(Rsh64Ux64 <t> x y) -> (AND (SRL <t> x y) (Neg64 <t> (SLTIU <t> [64] y)))
|
||||
|
||||
// SRA only considers the bottom 6 bits of y. If y > 64, the result should
|
||||
// be either 0 or -1 based on the sign bit.
|
||||
//
|
||||
// We implement this by performing the max shift (-1) if y >= 64.
|
||||
//
|
||||
// We OR (uint64(y < 64) - 1) into y before passing it to SRA. This leaves
|
||||
// us with -1 (0xffff...) if y >= 64.
|
||||
//
|
||||
// We don't need to sign-extend the OR result, as it will be at minimum 8 bits,
|
||||
// more than the 6 bits SRA cares about.
|
||||
(Rsh8x8 <t> x y) -> (SRA <t> (SignExt8to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt8to64 y)))))
|
||||
(Rsh8x16 <t> x y) -> (SRA <t> (SignExt8to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt16to64 y)))))
|
||||
(Rsh8x32 <t> x y) -> (SRA <t> (SignExt8to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt32to64 y)))))
|
||||
(Rsh8x64 <t> x y) -> (SRA <t> (SignExt8to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] y))))
|
||||
(Rsh16x8 <t> x y) -> (SRA <t> (SignExt16to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt8to64 y)))))
|
||||
(Rsh16x16 <t> x y) -> (SRA <t> (SignExt16to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt16to64 y)))))
|
||||
(Rsh16x32 <t> x y) -> (SRA <t> (SignExt16to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt32to64 y)))))
|
||||
(Rsh16x64 <t> x y) -> (SRA <t> (SignExt16to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] y))))
|
||||
(Rsh32x8 <t> x y) -> (SRA <t> (SignExt32to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt8to64 y)))))
|
||||
(Rsh32x16 <t> x y) -> (SRA <t> (SignExt32to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt16to64 y)))))
|
||||
(Rsh32x32 <t> x y) -> (SRA <t> (SignExt32to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt32to64 y)))))
|
||||
(Rsh32x64 <t> x y) -> (SRA <t> (SignExt32to64 x) (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] y))))
|
||||
(Rsh64x8 <t> x y) -> (SRA <t> x (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt8to64 y)))))
|
||||
(Rsh64x16 <t> x y) -> (SRA <t> x (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt16to64 y)))))
|
||||
(Rsh64x32 <t> x y) -> (SRA <t> x (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] (ZeroExt32to64 y)))))
|
||||
(Rsh64x64 <t> x y) -> (SRA <t> x (OR <y.Type> y (ADDI <y.Type> [-1] (SLTIU <y.Type> [64] y))))
|
||||
|
||||
// rotates
|
||||
(RotateLeft8 <t> x (MOVBconst [c])) -> (Or8 (Lsh8x64 <t> x (MOVBconst [c&7])) (Rsh8Ux64 <t> x (MOVBconst [-c&7])))
|
||||
(RotateLeft16 <t> x (MOVHconst [c])) -> (Or16 (Lsh16x64 <t> x (MOVHconst [c&15])) (Rsh16Ux64 <t> x (MOVHconst [-c&15])))
|
||||
(RotateLeft32 <t> x (MOVWconst [c])) -> (Or32 (Lsh32x64 <t> x (MOVWconst [c&31])) (Rsh32Ux64 <t> x (MOVWconst [-c&31])))
|
||||
(RotateLeft64 <t> x (MOVDconst [c])) -> (Or64 (Lsh64x64 <t> x (MOVDconst [c&63])) (Rsh64Ux64 <t> x (MOVDconst [-c&63])))
|
||||
|
||||
(Less64 x y) -> (SLT x y)
|
||||
(Less32 x y) -> (SLT (SignExt32to64 x) (SignExt32to64 y))
|
||||
(Less16 x y) -> (SLT (SignExt16to64 x) (SignExt16to64 y))
|
||||
(Less8 x y) -> (SLT (SignExt8to64 x) (SignExt8to64 y))
|
||||
(Less64U x y) -> (SLTU x y)
|
||||
(Less32U x y) -> (SLTU (ZeroExt32to64 x) (ZeroExt32to64 y))
|
||||
(Less16U x y) -> (SLTU (ZeroExt16to64 x) (ZeroExt16to64 y))
|
||||
(Less8U x y) -> (SLTU (ZeroExt8to64 x) (ZeroExt8to64 y))
|
||||
(Less64F x y) -> (FLTD x y)
|
||||
(Less32F x y) -> (FLTS x y)
|
||||
|
||||
// Convert x <= y to !(y > x).
|
||||
(Leq64 x y) -> (Not (Less64 y x))
|
||||
(Leq32 x y) -> (Not (Less32 y x))
|
||||
(Leq16 x y) -> (Not (Less16 y x))
|
||||
(Leq8 x y) -> (Not (Less8 y x))
|
||||
(Leq64U x y) -> (Not (Less64U y x))
|
||||
(Leq32U x y) -> (Not (Less32U y x))
|
||||
(Leq16U x y) -> (Not (Less16U y x))
|
||||
(Leq8U x y) -> (Not (Less8U y x))
|
||||
(Leq64F x y) -> (FLED x y)
|
||||
(Leq32F x y) -> (FLES x y)
|
||||
|
||||
// Convert x > y to y < x.
|
||||
(Greater64 x y) -> (Less64 y x)
|
||||
(Greater32 x y) -> (Less32 y x)
|
||||
(Greater16 x y) -> (Less16 y x)
|
||||
(Greater8 x y) -> (Less8 y x)
|
||||
(Greater64U x y) -> (Less64U y x)
|
||||
(Greater32U x y) -> (Less32U y x)
|
||||
(Greater16U x y) -> (Less16U y x)
|
||||
(Greater8U x y) -> (Less8U y x)
|
||||
(Greater64F x y) -> (FLTD y x)
|
||||
(Greater32F x y) -> (FLTS y x)
|
||||
|
||||
// Convert x >= y to !(x < y)
|
||||
(Geq64 x y) -> (Not (Less64 x y))
|
||||
(Geq32 x y) -> (Not (Less32 x y))
|
||||
(Geq16 x y) -> (Not (Less16 x y))
|
||||
(Geq8 x y) -> (Not (Less8 x y))
|
||||
(Geq64U x y) -> (Not (Less64U x y))
|
||||
(Geq32U x y) -> (Not (Less32U x y))
|
||||
(Geq16U x y) -> (Not (Less16U x y))
|
||||
(Geq8U x y) -> (Not (Less8U x y))
|
||||
(Geq64F x y) -> (FLED y x)
|
||||
(Geq32F x y) -> (FLES y x)
|
||||
|
||||
(EqPtr x y) -> (SEQZ (SUB <x.Type> x y))
|
||||
(Eq64 x y) -> (SEQZ (SUB <x.Type> x y))
|
||||
(Eq32 x y) -> (SEQZ (ZeroExt32to64 (SUB <x.Type> x y)))
|
||||
(Eq16 x y) -> (SEQZ (ZeroExt16to64 (SUB <x.Type> x y)))
|
||||
(Eq8 x y) -> (SEQZ (ZeroExt8to64 (SUB <x.Type> x y)))
|
||||
(Eq64F x y) -> (FEQD x y)
|
||||
(Eq32F x y) -> (FEQS x y)
|
||||
|
||||
(NeqPtr x y) -> (SNEZ (SUB <x.Type> x y))
|
||||
(Neq64 x y) -> (SNEZ (SUB <x.Type> x y))
|
||||
(Neq32 x y) -> (SNEZ (ZeroExt32to64 (SUB <x.Type> x y)))
|
||||
(Neq16 x y) -> (SNEZ (ZeroExt16to64 (SUB <x.Type> x y)))
|
||||
(Neq8 x y) -> (SNEZ (ZeroExt8to64 (SUB <x.Type> x y)))
|
||||
(Neq64F x y) -> (FNED x y)
|
||||
(Neq32F x y) -> (FNES x y)
|
||||
|
||||
// Loads
|
||||
(Load <t> ptr mem) && t.IsBoolean() -> (MOVBUload ptr mem)
|
||||
(Load <t> ptr mem) && ( is8BitInt(t) && isSigned(t)) -> (MOVBload ptr mem)
|
||||
(Load <t> ptr mem) && ( is8BitInt(t) && !isSigned(t)) -> (MOVBUload ptr mem)
|
||||
(Load <t> ptr mem) && (is16BitInt(t) && isSigned(t)) -> (MOVHload ptr mem)
|
||||
(Load <t> ptr mem) && (is16BitInt(t) && !isSigned(t)) -> (MOVHUload ptr mem)
|
||||
(Load <t> ptr mem) && (is32BitInt(t) && isSigned(t)) -> (MOVWload ptr mem)
|
||||
(Load <t> ptr mem) && (is32BitInt(t) && !isSigned(t)) -> (MOVWUload ptr mem)
|
||||
(Load <t> ptr mem) && (is64BitInt(t) || isPtr(t)) -> (MOVDload ptr mem)
|
||||
(Load <t> ptr mem) && is32BitFloat(t) -> (FMOVWload ptr mem)
|
||||
(Load <t> ptr mem) && is64BitFloat(t) -> (FMOVDload ptr mem)
|
||||
|
||||
// Stores
|
||||
(Store {t} ptr val mem) && t.(*types.Type).Size() == 1 -> (MOVBstore ptr val mem)
|
||||
(Store {t} ptr val mem) && t.(*types.Type).Size() == 2 -> (MOVHstore ptr val mem)
|
||||
(Store {t} ptr val mem) && t.(*types.Type).Size() == 4 && !is32BitFloat(val.Type) -> (MOVWstore ptr val mem)
|
||||
(Store {t} ptr val mem) && t.(*types.Type).Size() == 8 && !is64BitFloat(val.Type) -> (MOVDstore ptr val mem)
|
||||
(Store {t} ptr val mem) && t.(*types.Type).Size() == 4 && is32BitFloat(val.Type) -> (FMOVWstore ptr val mem)
|
||||
(Store {t} ptr val mem) && t.(*types.Type).Size() == 8 && is64BitFloat(val.Type) -> (FMOVDstore ptr val mem)
|
||||
|
||||
// We need to fold MOVaddr into the LD/MOVDstore ops so that the live variable analysis
|
||||
// knows what variables are being read/written by the ops.
|
||||
(MOVBUload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) ->
|
||||
(MOVBUload [off1+off2] {mergeSym(sym1,sym2)} base mem)
|
||||
(MOVBload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) ->
|
||||
(MOVBload [off1+off2] {mergeSym(sym1,sym2)} base mem)
|
||||
(MOVHUload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) ->
|
||||
(MOVHUload [off1+off2] {mergeSym(sym1,sym2)} base mem)
|
||||
(MOVHload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) ->
|
||||
(MOVHload [off1+off2] {mergeSym(sym1,sym2)} base mem)
|
||||
(MOVWUload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) ->
|
||||
(MOVWUload [off1+off2] {mergeSym(sym1,sym2)} base mem)
|
||||
(MOVWload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) ->
|
||||
(MOVWload [off1+off2] {mergeSym(sym1,sym2)} base mem)
|
||||
(MOVDload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) ->
|
||||
(MOVDload [off1+off2] {mergeSym(sym1,sym2)} base mem)
|
||||
|
||||
(MOVBstore [off1] {sym1} (MOVaddr [off2] {sym2} base) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) ->
|
||||
(MOVBstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
|
||||
(MOVHstore [off1] {sym1} (MOVaddr [off2] {sym2} base) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) ->
|
||||
(MOVHstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
|
||||
(MOVWstore [off1] {sym1} (MOVaddr [off2] {sym2} base) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) ->
|
||||
(MOVWstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
|
||||
(MOVDstore [off1] {sym1} (MOVaddr [off2] {sym2} base) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) ->
|
||||
(MOVDstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
|
||||
|
||||
(MOVBUload [off1] {sym} (ADDI [off2] base) mem) && is32Bit(off1+off2) ->
|
||||
(MOVBUload [off1+off2] {sym} base mem)
|
||||
(MOVBload [off1] {sym} (ADDI [off2] base) mem) && is32Bit(off1+off2) ->
|
||||
(MOVBload [off1+off2] {sym} base mem)
|
||||
(MOVHUload [off1] {sym} (ADDI [off2] base) mem) && is32Bit(off1+off2) ->
|
||||
(MOVHUload [off1+off2] {sym} base mem)
|
||||
(MOVHload [off1] {sym} (ADDI [off2] base) mem) && is32Bit(off1+off2) ->
|
||||
(MOVHload [off1+off2] {sym} base mem)
|
||||
(MOVWUload [off1] {sym} (ADDI [off2] base) mem) && is32Bit(off1+off2) ->
|
||||
(MOVWUload [off1+off2] {sym} base mem)
|
||||
(MOVWload [off1] {sym} (ADDI [off2] base) mem) && is32Bit(off1+off2) ->
|
||||
(MOVWload [off1+off2] {sym} base mem)
|
||||
(MOVDload [off1] {sym} (ADDI [off2] base) mem) && is32Bit(off1+off2) ->
|
||||
(MOVDload [off1+off2] {sym} base mem)
|
||||
|
||||
(MOVBstore [off1] {sym} (ADDI [off2] base) val mem) && is32Bit(off1+off2) ->
|
||||
(MOVBstore [off1+off2] {sym} base val mem)
|
||||
(MOVHstore [off1] {sym} (ADDI [off2] base) val mem) && is32Bit(off1+off2) ->
|
||||
(MOVHstore [off1+off2] {sym} base val mem)
|
||||
(MOVWstore [off1] {sym} (ADDI [off2] base) val mem) && is32Bit(off1+off2) ->
|
||||
(MOVWstore [off1+off2] {sym} base val mem)
|
||||
(MOVDstore [off1] {sym} (ADDI [off2] base) val mem) && is32Bit(off1+off2) ->
|
||||
(MOVDstore [off1+off2] {sym} base val mem)
|
||||
|
||||
// Similarly, fold ADDI into MOVaddr to avoid confusing live variable analysis
|
||||
// with OffPtr -> ADDI.
|
||||
(ADDI [c] (MOVaddr [d] {s} x)) && is32Bit(c+d) -> (MOVaddr [c+d] {s} x)
|
||||
|
||||
// Zeroing
|
||||
// TODO: more optimized zeroing, including attempting to use aligned accesses.
|
||||
(Zero [0] _ mem) -> mem
|
||||
(Zero [1] ptr mem) -> (MOVBstore ptr (MOVBconst) mem)
|
||||
(Zero [2] ptr mem) -> (MOVHstore ptr (MOVHconst) mem)
|
||||
(Zero [4] ptr mem) -> (MOVWstore ptr (MOVWconst) mem)
|
||||
(Zero [8] ptr mem) -> (MOVDstore ptr (MOVDconst) mem)
|
||||
|
||||
// Generic zeroing uses a loop
|
||||
(Zero [s] {t} ptr mem) ->
|
||||
(LoweredZero [t.(*types.Type).Alignment()]
|
||||
ptr
|
||||
(ADD <ptr.Type> ptr (MOVDconst [s-moveSize(t.(*types.Type).Alignment(), config)]))
|
||||
mem)
|
||||
|
||||
(Convert x mem) -> (MOVconvert x mem)
|
||||
|
||||
// Checks
|
||||
(IsNonNil p) -> (NeqPtr (MOVDconst) p)
|
||||
(IsInBounds idx len) -> (Less64U idx len)
|
||||
(IsSliceInBounds idx len) -> (Leq64U idx len)
|
||||
|
||||
// Trivial lowering
|
||||
(NilCheck ptr mem) -> (LoweredNilCheck ptr mem)
|
||||
(GetClosurePtr) -> (LoweredGetClosurePtr)
|
||||
(GetCallerSP) -> (LoweredGetCallerSP)
|
||||
(GetCallerPC) -> (LoweredGetCallerPC)
|
||||
|
||||
// Write barrier.
|
||||
(WB {fn} destptr srcptr mem) -> (LoweredWB {fn} destptr srcptr mem)
|
||||
|
||||
(PanicBounds [kind] x y mem) && boundsABI(kind) == 0 -> (LoweredPanicBoundsA [kind] x y mem)
|
||||
(PanicBounds [kind] x y mem) && boundsABI(kind) == 1 -> (LoweredPanicBoundsB [kind] x y mem)
|
||||
(PanicBounds [kind] x y mem) && boundsABI(kind) == 2 -> (LoweredPanicBoundsC [kind] x y mem)
|
||||
|
||||
// Moves
|
||||
// TODO: more optimized moves, including attempting to use aligned accesses.
|
||||
(Move [0] _ _ mem) -> mem
|
||||
(Move [1] dst src mem) -> (MOVBstore dst (MOVBload src mem) mem)
|
||||
(Move [2] dst src mem) -> (MOVHstore dst (MOVHload src mem) mem)
|
||||
(Move [4] dst src mem) -> (MOVWstore dst (MOVWload src mem) mem)
|
||||
(Move [8] dst src mem) -> (MOVDstore dst (MOVDload src mem) mem)
|
||||
|
||||
// Generic move uses a loop
|
||||
(Move [s] {t} dst src mem) ->
|
||||
(LoweredMove [t.(*types.Type).Alignment()]
|
||||
dst
|
||||
src
|
||||
(ADDI <src.Type> [s-moveSize(t.(*types.Type).Alignment(), config)] src)
|
||||
mem)
|
||||
|
||||
// Boolean ops; 0=false, 1=true
|
||||
(AndB x y) -> (AND x y)
|
||||
(OrB x y) -> (OR x y)
|
||||
(EqB x y) -> (XORI [1] (XOR <typ.Bool> x y))
|
||||
(NeqB x y) -> (XOR x y)
|
||||
(Not x) -> (XORI [1] x)
|
||||
|
||||
// Lowering pointer arithmetic
|
||||
// TODO: Special handling for SP offsets, like ARM
|
||||
(OffPtr [off] ptr:(SP)) -> (MOVaddr [off] ptr)
|
||||
(OffPtr [off] ptr) && is32Bit(off) -> (ADDI [off] ptr)
|
||||
(OffPtr [off] ptr) -> (ADD (MOVDconst [off]) ptr)
|
||||
|
||||
(Const8 [val]) -> (MOVBconst [val])
|
||||
(Const16 [val]) -> (MOVHconst [val])
|
||||
(Const32 [val]) -> (MOVWconst [val])
|
||||
(Const64 [val]) -> (MOVDconst [val])
|
||||
(Const32F [val]) -> (FMVSX (MOVWconst [int64(int32(math.Float32bits(float32(math.Float64frombits(uint64(val))))))]))
|
||||
(Const64F [val]) -> (FMVDX (MOVDconst [val]))
|
||||
(ConstNil) -> (MOVDconst [0])
|
||||
(ConstBool [b]) -> (MOVBconst [b])
|
||||
|
||||
// Convert 64 bit immediate to two 32 bit immediates, combine with add and shift.
|
||||
// The lower 32 bit immediate will be treated as signed,
|
||||
// so if it is negative, adjust for the borrow by incrementing the top half.
|
||||
// We don't have to worry about overflow from the increment,
|
||||
// because if the top half is all 1s, and int32(c) is negative,
|
||||
// then the overall constant fits in an int32.
|
||||
(MOVDconst <t> [c]) && !is32Bit(c) && int32(c) < 0 -> (ADD (SLLI <t> [32] (MOVDconst [c>>32+1])) (MOVDconst [int64(int32(c))]))
|
||||
(MOVDconst <t> [c]) && !is32Bit(c) && int32(c) >= 0 -> (ADD (SLLI <t> [32] (MOVDconst [c>>32+0])) (MOVDconst [int64(int32(c))]))
|
||||
|
||||
// Fold ADD+MOVDconst into ADDI where possible.
|
||||
(ADD (MOVDconst [off]) ptr) && is32Bit(off) -> (ADDI [off] ptr)
|
||||
|
||||
(Addr {sym} base) -> (MOVaddr {sym} base)
|
||||
(LocalAddr {sym} base _) -> (MOVaddr {sym} base)
|
||||
|
||||
// Conditional branches
|
||||
//
|
||||
// cond is 1 if true. BNE compares against 0.
|
||||
//
|
||||
// TODO(prattmic): RISCV branch instructions take two operands to compare,
|
||||
// so we could generate more efficient code by computing the condition in the
|
||||
// branch itself. This should be revisited now that the compiler has support
|
||||
// for two control values (https://golang.org/cl/196557).
|
||||
(If cond yes no) -> (BNE cond yes no)
|
||||
|
||||
// Calls
|
||||
(StaticCall [argwid] {target} mem) -> (CALLstatic [argwid] {target} mem)
|
||||
(ClosureCall [argwid] entry closure mem) -> (CALLclosure [argwid] entry closure mem)
|
||||
(InterCall [argwid] entry mem) -> (CALLinter [argwid] entry mem)
|
||||
|
||||
// remove redundant *const ops
|
||||
(ADDI [0] x) -> x
|
||||
338
src/cmd/compile/internal/ssa/gen/RISCV64Ops.go
Normal file
338
src/cmd/compile/internal/ssa/gen/RISCV64Ops.go
Normal file
|
|
@ -0,0 +1,338 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Suffixes encode the bit width of various instructions:
|
||||
//
|
||||
// D (double word) = 64 bit int
|
||||
// W (word) = 32 bit int
|
||||
// H (half word) = 16 bit int
|
||||
// B (byte) = 8 bit int
|
||||
// S (single) = 32 bit float
|
||||
// D (double) = 64 bit float
|
||||
// L = 64 bit int, used when the opcode starts with F
|
||||
|
||||
const (
|
||||
riscv64REG_G = 4
|
||||
riscv64REG_CTXT = 20
|
||||
riscv64REG_LR = 1
|
||||
riscv64REG_SP = 2
|
||||
riscv64REG_TMP = 31
|
||||
riscv64REG_ZERO = 0
|
||||
)
|
||||
|
||||
func riscv64RegName(r int) string {
|
||||
switch {
|
||||
case r == riscv64REG_G:
|
||||
return "g"
|
||||
case r == riscv64REG_SP:
|
||||
return "SP"
|
||||
case 0 <= r && r <= 31:
|
||||
return fmt.Sprintf("X%d", r)
|
||||
case 32 <= r && r <= 63:
|
||||
return fmt.Sprintf("F%d", r-32)
|
||||
default:
|
||||
panic(fmt.Sprintf("unknown register %d", r))
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
var regNamesRISCV64 []string
|
||||
var gpMask, fpMask, gpspMask, gpspsbMask regMask
|
||||
regNamed := make(map[string]regMask)
|
||||
|
||||
// Build the list of register names, creating an appropriately indexed
|
||||
// regMask for the gp and fp registers as we go.
|
||||
//
|
||||
// If name is specified, use it rather than the riscv reg number.
|
||||
addreg := func(r int, name string) regMask {
|
||||
mask := regMask(1) << uint(len(regNamesRISCV64))
|
||||
if name == "" {
|
||||
name = riscv64RegName(r)
|
||||
}
|
||||
regNamesRISCV64 = append(regNamesRISCV64, name)
|
||||
regNamed[name] = mask
|
||||
return mask
|
||||
}
|
||||
|
||||
// General purpose registers.
|
||||
for r := 0; r <= 31; r++ {
|
||||
if r == riscv64REG_LR {
|
||||
// LR is not used by regalloc, so we skip it to leave
|
||||
// room for pseudo-register SB.
|
||||
continue
|
||||
}
|
||||
|
||||
mask := addreg(r, "")
|
||||
|
||||
// Add general purpose registers to gpMask.
|
||||
switch r {
|
||||
// ZERO, g, and TMP are not in any gp mask.
|
||||
case riscv64REG_ZERO, riscv64REG_G, riscv64REG_TMP:
|
||||
case riscv64REG_SP:
|
||||
gpspMask |= mask
|
||||
gpspsbMask |= mask
|
||||
default:
|
||||
gpMask |= mask
|
||||
gpspMask |= mask
|
||||
gpspsbMask |= mask
|
||||
}
|
||||
}
|
||||
|
||||
// Floating pointer registers.
|
||||
for r := 32; r <= 63; r++ {
|
||||
mask := addreg(r, "")
|
||||
fpMask |= mask
|
||||
}
|
||||
|
||||
// Pseudo-register: SB
|
||||
mask := addreg(-1, "SB")
|
||||
gpspsbMask |= mask
|
||||
|
||||
if len(regNamesRISCV64) > 64 {
|
||||
// regMask is only 64 bits.
|
||||
panic("Too many RISCV64 registers")
|
||||
}
|
||||
|
||||
regCtxt := regNamed["X20"]
|
||||
callerSave := gpMask | fpMask | regNamed["g"]
|
||||
|
||||
var (
|
||||
gpstore = regInfo{inputs: []regMask{gpspsbMask, gpspMask, 0}} // SB in first input so we can load from a global, but not in second to avoid using SB as a temporary register
|
||||
gp01 = regInfo{outputs: []regMask{gpMask}}
|
||||
gp11 = regInfo{inputs: []regMask{gpMask}, outputs: []regMask{gpMask}}
|
||||
gp21 = regInfo{inputs: []regMask{gpMask, gpMask}, outputs: []regMask{gpMask}}
|
||||
gpload = regInfo{inputs: []regMask{gpspsbMask, 0}, outputs: []regMask{gpMask}}
|
||||
gp11sb = regInfo{inputs: []regMask{gpspsbMask}, outputs: []regMask{gpMask}}
|
||||
|
||||
fp11 = regInfo{inputs: []regMask{fpMask}, outputs: []regMask{fpMask}}
|
||||
fp21 = regInfo{inputs: []regMask{fpMask, fpMask}, outputs: []regMask{fpMask}}
|
||||
gpfp = regInfo{inputs: []regMask{gpMask}, outputs: []regMask{fpMask}}
|
||||
fpgp = regInfo{inputs: []regMask{fpMask}, outputs: []regMask{gpMask}}
|
||||
fpstore = regInfo{inputs: []regMask{gpspsbMask, fpMask, 0}}
|
||||
fpload = regInfo{inputs: []regMask{gpspsbMask, 0}, outputs: []regMask{fpMask}}
|
||||
fp2gp = regInfo{inputs: []regMask{fpMask, fpMask}, outputs: []regMask{gpMask}}
|
||||
|
||||
call = regInfo{clobbers: callerSave}
|
||||
callClosure = regInfo{inputs: []regMask{gpspMask, regCtxt, 0}, clobbers: callerSave}
|
||||
callInter = regInfo{inputs: []regMask{gpMask}, clobbers: callerSave}
|
||||
)
|
||||
|
||||
RISCV64ops := []opData{
|
||||
{name: "ADD", argLength: 2, reg: gp21, asm: "ADD", commutative: true}, // arg0 + arg1
|
||||
{name: "ADDI", argLength: 1, reg: gp11sb, asm: "ADDI", aux: "Int64"}, // arg0 + auxint
|
||||
{name: "SUB", argLength: 2, reg: gp21, asm: "SUB"}, // arg0 - arg1
|
||||
|
||||
// M extension. H means high (i.e., it returns the top bits of
|
||||
// the result). U means unsigned. W means word (i.e., 32-bit).
|
||||
{name: "MUL", argLength: 2, reg: gp21, asm: "MUL", commutative: true, typ: "Int64"}, // arg0 * arg1
|
||||
{name: "MULW", argLength: 2, reg: gp21, asm: "MULW", commutative: true, typ: "Int32"},
|
||||
{name: "MULH", argLength: 2, reg: gp21, asm: "MULH", commutative: true, typ: "Int64"},
|
||||
{name: "MULHU", argLength: 2, reg: gp21, asm: "MULHU", commutative: true, typ: "UInt64"},
|
||||
{name: "DIV", argLength: 2, reg: gp21, asm: "DIV", typ: "Int64"}, // arg0 / arg1
|
||||
{name: "DIVU", argLength: 2, reg: gp21, asm: "DIVU", typ: "UInt64"},
|
||||
{name: "DIVW", argLength: 2, reg: gp21, asm: "DIVW", typ: "Int32"},
|
||||
{name: "DIVUW", argLength: 2, reg: gp21, asm: "DIVUW", typ: "UInt32"},
|
||||
{name: "REM", argLength: 2, reg: gp21, asm: "REM", typ: "Int64"}, // arg0 % arg1
|
||||
{name: "REMU", argLength: 2, reg: gp21, asm: "REMU", typ: "UInt64"},
|
||||
{name: "REMW", argLength: 2, reg: gp21, asm: "REMW", typ: "Int32"},
|
||||
{name: "REMUW", argLength: 2, reg: gp21, asm: "REMUW", typ: "UInt32"},
|
||||
|
||||
{name: "MOVaddr", argLength: 1, reg: gp11sb, asm: "MOV", aux: "SymOff", rematerializeable: true, symEffect: "RdWr"}, // arg0 + auxint + offset encoded in aux
|
||||
// auxint+aux == add auxint and the offset of the symbol in aux (if any) to the effective address
|
||||
|
||||
{name: "MOVBconst", reg: gp01, asm: "MOV", typ: "UInt8", aux: "Int8", rematerializeable: true}, // 8 low bits of auxint
|
||||
{name: "MOVHconst", reg: gp01, asm: "MOV", typ: "UInt16", aux: "Int16", rematerializeable: true}, // 16 low bits of auxint
|
||||
{name: "MOVWconst", reg: gp01, asm: "MOV", typ: "UInt32", aux: "Int32", rematerializeable: true}, // 32 low bits of auxint
|
||||
{name: "MOVDconst", reg: gp01, asm: "MOV", typ: "UInt64", aux: "Int64", rematerializeable: true}, // auxint
|
||||
|
||||
// Loads: load <size> bits from arg0+auxint+aux and extend to 64 bits; arg1=mem
|
||||
{name: "MOVBload", argLength: 2, reg: gpload, asm: "MOVB", aux: "SymOff", typ: "Int8", faultOnNilArg0: true, symEffect: "Read"}, // 8 bits, sign extend
|
||||
{name: "MOVHload", argLength: 2, reg: gpload, asm: "MOVH", aux: "SymOff", typ: "Int16", faultOnNilArg0: true, symEffect: "Read"}, // 16 bits, sign extend
|
||||
{name: "MOVWload", argLength: 2, reg: gpload, asm: "MOVW", aux: "SymOff", typ: "Int32", faultOnNilArg0: true, symEffect: "Read"}, // 32 bits, sign extend
|
||||
{name: "MOVDload", argLength: 2, reg: gpload, asm: "MOV", aux: "SymOff", typ: "Int64", faultOnNilArg0: true, symEffect: "Read"}, // 64 bits
|
||||
{name: "MOVBUload", argLength: 2, reg: gpload, asm: "MOVBU", aux: "SymOff", typ: "UInt8", faultOnNilArg0: true, symEffect: "Read"}, // 8 bits, zero extend
|
||||
{name: "MOVHUload", argLength: 2, reg: gpload, asm: "MOVHU", aux: "SymOff", typ: "UInt16", faultOnNilArg0: true, symEffect: "Read"}, // 16 bits, zero extend
|
||||
{name: "MOVWUload", argLength: 2, reg: gpload, asm: "MOVWU", aux: "SymOff", typ: "UInt32", faultOnNilArg0: true, symEffect: "Read"}, // 32 bits, zero extend
|
||||
|
||||
// Stores: store <size> lowest bits in arg1 to arg0+auxint+aux; arg2=mem
|
||||
{name: "MOVBstore", argLength: 3, reg: gpstore, asm: "MOVB", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 8 bits
|
||||
{name: "MOVHstore", argLength: 3, reg: gpstore, asm: "MOVH", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 16 bits
|
||||
{name: "MOVWstore", argLength: 3, reg: gpstore, asm: "MOVW", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 32 bits
|
||||
{name: "MOVDstore", argLength: 3, reg: gpstore, asm: "MOV", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 64 bits
|
||||
|
||||
// Shift ops
|
||||
{name: "SLL", argLength: 2, reg: gp21, asm: "SLL"}, // arg0 << aux1
|
||||
{name: "SRA", argLength: 2, reg: gp21, asm: "SRA"}, // arg0 >> aux1, signed
|
||||
{name: "SRL", argLength: 2, reg: gp21, asm: "SRL"}, // arg0 >> aux1, unsigned
|
||||
{name: "SLLI", argLength: 1, reg: gp11, asm: "SLLI", aux: "Int64"}, // arg0 << auxint
|
||||
{name: "SRAI", argLength: 1, reg: gp11, asm: "SRAI", aux: "Int64"}, // arg0 >> auxint, signed
|
||||
{name: "SRLI", argLength: 1, reg: gp11, asm: "SRLI", aux: "Int64"}, // arg0 >> auxint, unsigned
|
||||
|
||||
// Bitwise ops
|
||||
{name: "XOR", argLength: 2, reg: gp21, asm: "XOR", commutative: true}, // arg0 ^ arg1
|
||||
{name: "XORI", argLength: 1, reg: gp11, asm: "XORI", aux: "Int64"}, // arg0 ^ auxint
|
||||
{name: "OR", argLength: 2, reg: gp21, asm: "OR", commutative: true}, // arg0 | arg1
|
||||
{name: "ORI", argLength: 1, reg: gp11, asm: "ORI", aux: "Int64"}, // arg0 | auxint
|
||||
{name: "AND", argLength: 2, reg: gp21, asm: "AND", commutative: true}, // arg0 & arg1
|
||||
{name: "ANDI", argLength: 1, reg: gp11, asm: "ANDI", aux: "Int64"}, // arg0 & auxint
|
||||
|
||||
// Generate boolean values
|
||||
{name: "SEQZ", argLength: 1, reg: gp11, asm: "SEQZ"}, // arg0 == 0, result is 0 or 1
|
||||
{name: "SNEZ", argLength: 1, reg: gp11, asm: "SNEZ"}, // arg0 != 0, result is 0 or 1
|
||||
{name: "SLT", argLength: 2, reg: gp21, asm: "SLT"}, // arg0 < arg1, result is 0 or 1
|
||||
{name: "SLTI", argLength: 1, reg: gp11, asm: "SLTI", aux: "Int64"}, // arg0 < auxint, result is 0 or 1
|
||||
{name: "SLTU", argLength: 2, reg: gp21, asm: "SLTU"}, // arg0 < arg1, unsigned, result is 0 or 1
|
||||
{name: "SLTIU", argLength: 1, reg: gp11, asm: "SLTIU", aux: "Int64"}, // arg0 < auxint, unsigned, result is 0 or 1
|
||||
|
||||
// MOVconvert converts between pointers and integers.
|
||||
// We have a special op for this so as to not confuse GC
|
||||
// (particularly stack maps). It takes a memory arg so it
|
||||
// gets correctly ordered with respect to GC safepoints.
|
||||
{name: "MOVconvert", argLength: 2, reg: gp11, asm: "MOV"}, // arg0, but converted to int/ptr as appropriate; arg1=mem
|
||||
|
||||
// Calls
|
||||
{name: "CALLstatic", argLength: 1, reg: call, aux: "SymOff", call: true, symEffect: "None"}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLclosure", argLength: 3, reg: callClosure, aux: "Int64", call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
|
||||
{name: "CALLinter", argLength: 2, reg: callInter, aux: "Int64", call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
|
||||
|
||||
// Generic moves and zeros
|
||||
|
||||
// general unaligned zeroing
|
||||
// arg0 = address of memory to zero (in X5, changed as side effect)
|
||||
// arg1 = address of the last element to zero (inclusive)
|
||||
// arg2 = mem
|
||||
// auxint = element size
|
||||
// returns mem
|
||||
// mov ZERO, (X5)
|
||||
// ADD $sz, X5
|
||||
// BGEU Rarg1, X5, -2(PC)
|
||||
{
|
||||
name: "LoweredZero",
|
||||
aux: "Int64",
|
||||
argLength: 3,
|
||||
reg: regInfo{
|
||||
inputs: []regMask{regNamed["X5"], gpMask},
|
||||
clobbers: regNamed["X5"],
|
||||
},
|
||||
typ: "Mem",
|
||||
faultOnNilArg0: true,
|
||||
},
|
||||
|
||||
// general unaligned move
|
||||
// arg0 = address of dst memory (in X5, changed as side effect)
|
||||
// arg1 = address of src memory (in X6, changed as side effect)
|
||||
// arg2 = address of the last element of src (can't be X7 as we clobber it before using arg2)
|
||||
// arg3 = mem
|
||||
// auxint = alignment
|
||||
// clobbers X7 as a tmp register.
|
||||
// returns mem
|
||||
// mov (X6), X7
|
||||
// mov X7, (X5)
|
||||
// ADD $sz, X5
|
||||
// ADD $sz, X6
|
||||
// BGEU Rarg2, X5, -4(PC)
|
||||
{
|
||||
name: "LoweredMove",
|
||||
aux: "Int64",
|
||||
argLength: 4,
|
||||
reg: regInfo{
|
||||
inputs: []regMask{regNamed["X5"], regNamed["X6"], gpMask &^ regNamed["X7"]},
|
||||
clobbers: regNamed["X5"] | regNamed["X6"] | regNamed["X7"],
|
||||
},
|
||||
typ: "Mem",
|
||||
faultOnNilArg0: true,
|
||||
faultOnNilArg1: true,
|
||||
},
|
||||
|
||||
// Lowering pass-throughs
|
||||
{name: "LoweredNilCheck", argLength: 2, faultOnNilArg0: true, nilCheck: true, reg: regInfo{inputs: []regMask{gpspMask}}}, // arg0=ptr,arg1=mem, returns void. Faults if ptr is nil.
|
||||
{name: "LoweredGetClosurePtr", reg: regInfo{outputs: []regMask{regCtxt}}}, // scheduler ensures only at beginning of entry block
|
||||
|
||||
// LoweredGetCallerSP returns the SP of the caller of the current function.
|
||||
{name: "LoweredGetCallerSP", reg: gp01, rematerializeable: true},
|
||||
|
||||
// LoweredGetCallerPC evaluates to the PC to which its "caller" will return.
|
||||
// I.e., if f calls g "calls" getcallerpc,
|
||||
// the result should be the PC within f that g will return to.
|
||||
// See runtime/stubs.go for a more detailed discussion.
|
||||
{name: "LoweredGetCallerPC", reg: gp01, rematerializeable: true},
|
||||
|
||||
// LoweredWB invokes runtime.gcWriteBarrier. arg0=destptr, arg1=srcptr, arg2=mem, aux=runtime.gcWriteBarrier
|
||||
// It saves all GP registers if necessary,
|
||||
// but clobbers RA (LR) because it's a call
|
||||
// and T6 (REG_TMP).
|
||||
{name: "LoweredWB", argLength: 3, reg: regInfo{inputs: []regMask{regNamed["X5"], regNamed["X6"]}, clobbers: (callerSave &^ (gpMask | regNamed["g"])) | regNamed["X1"]}, clobberFlags: true, aux: "Sym", symEffect: "None"},
|
||||
|
||||
// There are three of these functions so that they can have three different register inputs.
|
||||
// When we check 0 <= c <= cap (A), then 0 <= b <= c (B), then 0 <= a <= b (C), we want the
|
||||
// default registers to match so we don't need to copy registers around unnecessarily.
|
||||
{name: "LoweredPanicBoundsA", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{regNamed["X7"], regNamed["X28"]}}, typ: "Mem"}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go).
|
||||
{name: "LoweredPanicBoundsB", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{regNamed["X6"], regNamed["X7"]}}, typ: "Mem"}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go).
|
||||
{name: "LoweredPanicBoundsC", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{regNamed["X5"], regNamed["X6"]}}, typ: "Mem"}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go).
|
||||
|
||||
// F extension.
|
||||
{name: "FADDS", argLength: 2, reg: fp21, asm: "FADDS", commutative: true, typ: "Float32"}, // arg0 + arg1
|
||||
{name: "FSUBS", argLength: 2, reg: fp21, asm: "FSUBS", commutative: false, typ: "Float32"}, // arg0 - arg1
|
||||
{name: "FMULS", argLength: 2, reg: fp21, asm: "FMULS", commutative: true, typ: "Float32"}, // arg0 * arg1
|
||||
{name: "FDIVS", argLength: 2, reg: fp21, asm: "FDIVS", commutative: false, typ: "Float32"}, // arg0 / arg1
|
||||
{name: "FSQRTS", argLength: 1, reg: fp11, asm: "FSQRTS", typ: "Float32"}, // sqrt(arg0)
|
||||
{name: "FNEGS", argLength: 1, reg: fp11, asm: "FNEGS", typ: "Float32"}, // -arg0
|
||||
{name: "FMVSX", argLength: 1, reg: gpfp, asm: "FMVSX", typ: "Float32"}, // reinterpret arg0 as float
|
||||
{name: "FCVTSW", argLength: 1, reg: gpfp, asm: "FCVTSW", typ: "Float32"}, // float32(low 32 bits of arg0)
|
||||
{name: "FCVTSL", argLength: 1, reg: gpfp, asm: "FCVTSL", typ: "Float32"}, // float32(arg0)
|
||||
{name: "FCVTWS", argLength: 1, reg: fpgp, asm: "FCVTWS", typ: "Int32"}, // int32(arg0)
|
||||
{name: "FCVTLS", argLength: 1, reg: fpgp, asm: "FCVTLS", typ: "Int64"}, // int64(arg0)
|
||||
{name: "FMOVWload", argLength: 2, reg: fpload, asm: "MOVF", aux: "SymOff", typ: "Float32", faultOnNilArg0: true, symEffect: "Read"}, // load float32 from arg0+auxint+aux
|
||||
{name: "FMOVWstore", argLength: 3, reg: fpstore, asm: "MOVF", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store float32 to arg0+auxint+aux
|
||||
{name: "FEQS", argLength: 2, reg: fp2gp, asm: "FEQS", commutative: true}, // arg0 == arg1
|
||||
{name: "FNES", argLength: 2, reg: fp2gp, asm: "FNES", commutative: true}, // arg0 != arg1
|
||||
{name: "FLTS", argLength: 2, reg: fp2gp, asm: "FLTS"}, // arg0 < arg1
|
||||
{name: "FLES", argLength: 2, reg: fp2gp, asm: "FLES"}, // arg0 <= arg1
|
||||
|
||||
// D extension.
|
||||
{name: "FADDD", argLength: 2, reg: fp21, asm: "FADDD", commutative: true, typ: "Float64"}, // arg0 + arg1
|
||||
{name: "FSUBD", argLength: 2, reg: fp21, asm: "FSUBD", commutative: false, typ: "Float64"}, // arg0 - arg1
|
||||
{name: "FMULD", argLength: 2, reg: fp21, asm: "FMULD", commutative: true, typ: "Float64"}, // arg0 * arg1
|
||||
{name: "FDIVD", argLength: 2, reg: fp21, asm: "FDIVD", commutative: false, typ: "Float64"}, // arg0 / arg1
|
||||
{name: "FSQRTD", argLength: 1, reg: fp11, asm: "FSQRTD", typ: "Float64"}, // sqrt(arg0)
|
||||
{name: "FNEGD", argLength: 1, reg: fp11, asm: "FNEGD", typ: "Float64"}, // -arg0
|
||||
{name: "FMVDX", argLength: 1, reg: gpfp, asm: "FMVDX", typ: "Float64"}, // reinterpret arg0 as float
|
||||
{name: "FCVTDW", argLength: 1, reg: gpfp, asm: "FCVTDW", typ: "Float64"}, // float64(low 32 bits of arg0)
|
||||
{name: "FCVTDL", argLength: 1, reg: gpfp, asm: "FCVTDL", typ: "Float64"}, // float64(arg0)
|
||||
{name: "FCVTWD", argLength: 1, reg: fpgp, asm: "FCVTWD", typ: "Int32"}, // int32(arg0)
|
||||
{name: "FCVTLD", argLength: 1, reg: fpgp, asm: "FCVTLD", typ: "Int64"}, // int64(arg0)
|
||||
{name: "FCVTDS", argLength: 1, reg: fp11, asm: "FCVTDS", typ: "Float64"}, // float64(arg0)
|
||||
{name: "FCVTSD", argLength: 1, reg: fp11, asm: "FCVTSD", typ: "Float32"}, // float32(arg0)
|
||||
{name: "FMOVDload", argLength: 2, reg: fpload, asm: "MOVD", aux: "SymOff", typ: "Float64", faultOnNilArg0: true, symEffect: "Read"}, // load float64 from arg0+auxint+aux
|
||||
{name: "FMOVDstore", argLength: 3, reg: fpstore, asm: "MOVD", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store float6 to arg0+auxint+aux
|
||||
{name: "FEQD", argLength: 2, reg: fp2gp, asm: "FEQD", commutative: true}, // arg0 == arg1
|
||||
{name: "FNED", argLength: 2, reg: fp2gp, asm: "FNED", commutative: true}, // arg0 != arg1
|
||||
{name: "FLTD", argLength: 2, reg: fp2gp, asm: "FLTD"}, // arg0 < arg1
|
||||
{name: "FLED", argLength: 2, reg: fp2gp, asm: "FLED"}, // arg0 <= arg1
|
||||
}
|
||||
|
||||
RISCV64blocks := []blockData{
|
||||
{name: "BNE", controls: 1}, // Control != 0 (take a register)
|
||||
}
|
||||
|
||||
archs = append(archs, arch{
|
||||
name: "RISCV64",
|
||||
pkg: "cmd/internal/obj/riscv",
|
||||
genfile: "../../riscv64/ssa.go",
|
||||
ops: RISCV64ops,
|
||||
blocks: RISCV64blocks,
|
||||
regnames: regNamesRISCV64,
|
||||
gpregmask: gpMask,
|
||||
fpregmask: fpMask,
|
||||
framepointerreg: -1, // not used
|
||||
})
|
||||
}
|
||||
|
|
@ -340,7 +340,7 @@ var genericOps = []opData{
|
|||
// Note: ConstX are sign-extended even when the type of the value is unsigned.
|
||||
// For instance, uint8(0xaa) is stored as auxint=0xffffffffffffffaa.
|
||||
{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: "ConstInterface"}, // nil interface
|
||||
{name: "ConstSlice"}, // nil slice
|
||||
|
|
|
|||
|
|
@ -405,6 +405,7 @@ func genOp() {
|
|||
|
||||
fmt.Fprintln(w, "func (o Op) SymEffect() SymEffect { return opcodeTable[o].symEffect }")
|
||||
fmt.Fprintln(w, "func (o Op) 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 }")
|
||||
|
||||
// generate registers
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -9480,7 +9480,7 @@ func rewriteValuePPC64_OpPPC64MOVDload_0(v *Value) bool {
|
|||
return true
|
||||
}
|
||||
// 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)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
|
|
@ -9493,7 +9493,7 @@ func rewriteValuePPC64_OpPPC64MOVDload_0(v *Value) bool {
|
|||
off2 := p.AuxInt
|
||||
sym2 := p.Aux
|
||||
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
|
||||
}
|
||||
v.reset(OpPPC64MOVDload)
|
||||
|
|
@ -9504,7 +9504,7 @@ func rewriteValuePPC64_OpPPC64MOVDload_0(v *Value) bool {
|
|||
return true
|
||||
}
|
||||
// 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)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
|
|
@ -9516,7 +9516,7 @@ func rewriteValuePPC64_OpPPC64MOVDload_0(v *Value) bool {
|
|||
}
|
||||
off2 := v_0.AuxInt
|
||||
x := v_0.Args[0]
|
||||
if !(is16Bit(off1 + off2)) {
|
||||
if !(is16Bit(off1+off2) && (off1+off2)%4 == 0) {
|
||||
break
|
||||
}
|
||||
v.reset(OpPPC64MOVDload)
|
||||
|
|
@ -9554,7 +9554,7 @@ func rewriteValuePPC64_OpPPC64MOVDload_0(v *Value) bool {
|
|||
}
|
||||
func rewriteValuePPC64_OpPPC64MOVDloadidx_0(v *Value) bool {
|
||||
// match: (MOVDloadidx ptr (MOVDconst [c]) mem)
|
||||
// cond: is16Bit(c)
|
||||
// cond: is16Bit(c) && c%4 == 0
|
||||
// result: (MOVDload [c] ptr mem)
|
||||
for {
|
||||
mem := v.Args[2]
|
||||
|
|
@ -9564,7 +9564,7 @@ func rewriteValuePPC64_OpPPC64MOVDloadidx_0(v *Value) bool {
|
|||
break
|
||||
}
|
||||
c := v_1.AuxInt
|
||||
if !(is16Bit(c)) {
|
||||
if !(is16Bit(c) && c%4 == 0) {
|
||||
break
|
||||
}
|
||||
v.reset(OpPPC64MOVDload)
|
||||
|
|
@ -9574,7 +9574,7 @@ func rewriteValuePPC64_OpPPC64MOVDloadidx_0(v *Value) bool {
|
|||
return true
|
||||
}
|
||||
// match: (MOVDloadidx (MOVDconst [c]) ptr mem)
|
||||
// cond: is16Bit(c)
|
||||
// cond: is16Bit(c) && c%4 == 0
|
||||
// result: (MOVDload [c] ptr mem)
|
||||
for {
|
||||
mem := v.Args[2]
|
||||
|
|
@ -9584,7 +9584,7 @@ func rewriteValuePPC64_OpPPC64MOVDloadidx_0(v *Value) bool {
|
|||
}
|
||||
c := v_0.AuxInt
|
||||
ptr := v.Args[1]
|
||||
if !(is16Bit(c)) {
|
||||
if !(is16Bit(c) && c%4 == 0) {
|
||||
break
|
||||
}
|
||||
v.reset(OpPPC64MOVDload)
|
||||
|
|
@ -9617,7 +9617,7 @@ func rewriteValuePPC64_OpPPC64MOVDstore_0(v *Value) bool {
|
|||
return true
|
||||
}
|
||||
// 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)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
|
|
@ -9630,7 +9630,7 @@ func rewriteValuePPC64_OpPPC64MOVDstore_0(v *Value) bool {
|
|||
off2 := v_0.AuxInt
|
||||
x := v_0.Args[0]
|
||||
val := v.Args[1]
|
||||
if !(is16Bit(off1 + off2)) {
|
||||
if !(is16Bit(off1+off2) && (off1+off2)%4 == 0) {
|
||||
break
|
||||
}
|
||||
v.reset(OpPPC64MOVDstore)
|
||||
|
|
@ -9642,7 +9642,7 @@ func rewriteValuePPC64_OpPPC64MOVDstore_0(v *Value) bool {
|
|||
return true
|
||||
}
|
||||
// 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)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
|
|
@ -9656,7 +9656,7 @@ func rewriteValuePPC64_OpPPC64MOVDstore_0(v *Value) bool {
|
|||
sym2 := p.Aux
|
||||
ptr := p.Args[0]
|
||||
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
|
||||
}
|
||||
v.reset(OpPPC64MOVDstore)
|
||||
|
|
@ -9713,7 +9713,7 @@ func rewriteValuePPC64_OpPPC64MOVDstore_0(v *Value) bool {
|
|||
}
|
||||
func rewriteValuePPC64_OpPPC64MOVDstoreidx_0(v *Value) bool {
|
||||
// match: (MOVDstoreidx ptr (MOVDconst [c]) val mem)
|
||||
// cond: is16Bit(c)
|
||||
// cond: is16Bit(c) && c%4 == 0
|
||||
// result: (MOVDstore [c] ptr val mem)
|
||||
for {
|
||||
mem := v.Args[3]
|
||||
|
|
@ -9724,7 +9724,7 @@ func rewriteValuePPC64_OpPPC64MOVDstoreidx_0(v *Value) bool {
|
|||
}
|
||||
c := v_1.AuxInt
|
||||
val := v.Args[2]
|
||||
if !(is16Bit(c)) {
|
||||
if !(is16Bit(c) && c%4 == 0) {
|
||||
break
|
||||
}
|
||||
v.reset(OpPPC64MOVDstore)
|
||||
|
|
@ -9735,7 +9735,7 @@ func rewriteValuePPC64_OpPPC64MOVDstoreidx_0(v *Value) bool {
|
|||
return true
|
||||
}
|
||||
// match: (MOVDstoreidx (MOVDconst [c]) ptr val mem)
|
||||
// cond: is16Bit(c)
|
||||
// cond: is16Bit(c) && c%4 == 0
|
||||
// result: (MOVDstore [c] ptr val mem)
|
||||
for {
|
||||
mem := v.Args[3]
|
||||
|
|
@ -9746,7 +9746,7 @@ func rewriteValuePPC64_OpPPC64MOVDstoreidx_0(v *Value) bool {
|
|||
c := v_0.AuxInt
|
||||
ptr := v.Args[1]
|
||||
val := v.Args[2]
|
||||
if !(is16Bit(c)) {
|
||||
if !(is16Bit(c) && c%4 == 0) {
|
||||
break
|
||||
}
|
||||
v.reset(OpPPC64MOVDstore)
|
||||
|
|
@ -9760,7 +9760,7 @@ func rewriteValuePPC64_OpPPC64MOVDstoreidx_0(v *Value) bool {
|
|||
}
|
||||
func rewriteValuePPC64_OpPPC64MOVDstorezero_0(v *Value) bool {
|
||||
// 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)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
|
|
@ -9772,7 +9772,7 @@ func rewriteValuePPC64_OpPPC64MOVDstorezero_0(v *Value) bool {
|
|||
}
|
||||
off2 := v_0.AuxInt
|
||||
x := v_0.Args[0]
|
||||
if !(is16Bit(off1 + off2)) {
|
||||
if !(is16Bit(off1+off2) && (off1+off2)%4 == 0) {
|
||||
break
|
||||
}
|
||||
v.reset(OpPPC64MOVDstorezero)
|
||||
|
|
@ -9783,7 +9783,7 @@ func rewriteValuePPC64_OpPPC64MOVDstorezero_0(v *Value) bool {
|
|||
return true
|
||||
}
|
||||
// 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)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
|
|
@ -9796,7 +9796,7 @@ func rewriteValuePPC64_OpPPC64MOVDstorezero_0(v *Value) bool {
|
|||
off2 := p.AuxInt
|
||||
sym2 := p.Aux
|
||||
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
|
||||
}
|
||||
v.reset(OpPPC64MOVDstorezero)
|
||||
|
|
@ -11548,7 +11548,7 @@ func rewriteValuePPC64_OpPPC64MOVWZreg_20(v *Value) bool {
|
|||
}
|
||||
func rewriteValuePPC64_OpPPC64MOVWload_0(v *Value) bool {
|
||||
// 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)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
|
|
@ -11561,7 +11561,7 @@ func rewriteValuePPC64_OpPPC64MOVWload_0(v *Value) bool {
|
|||
off2 := p.AuxInt
|
||||
sym2 := p.Aux
|
||||
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
|
||||
}
|
||||
v.reset(OpPPC64MOVWload)
|
||||
|
|
@ -11572,7 +11572,7 @@ func rewriteValuePPC64_OpPPC64MOVWload_0(v *Value) bool {
|
|||
return true
|
||||
}
|
||||
// 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)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
|
|
@ -11584,7 +11584,7 @@ func rewriteValuePPC64_OpPPC64MOVWload_0(v *Value) bool {
|
|||
}
|
||||
off2 := v_0.AuxInt
|
||||
x := v_0.Args[0]
|
||||
if !(is16Bit(off1 + off2)) {
|
||||
if !(is16Bit(off1+off2) && (off1+off2)%4 == 0) {
|
||||
break
|
||||
}
|
||||
v.reset(OpPPC64MOVWload)
|
||||
|
|
@ -11622,7 +11622,7 @@ func rewriteValuePPC64_OpPPC64MOVWload_0(v *Value) bool {
|
|||
}
|
||||
func rewriteValuePPC64_OpPPC64MOVWloadidx_0(v *Value) bool {
|
||||
// match: (MOVWloadidx ptr (MOVDconst [c]) mem)
|
||||
// cond: is16Bit(c)
|
||||
// cond: is16Bit(c) && c%4 == 0
|
||||
// result: (MOVWload [c] ptr mem)
|
||||
for {
|
||||
mem := v.Args[2]
|
||||
|
|
@ -11632,7 +11632,7 @@ func rewriteValuePPC64_OpPPC64MOVWloadidx_0(v *Value) bool {
|
|||
break
|
||||
}
|
||||
c := v_1.AuxInt
|
||||
if !(is16Bit(c)) {
|
||||
if !(is16Bit(c) && c%4 == 0) {
|
||||
break
|
||||
}
|
||||
v.reset(OpPPC64MOVWload)
|
||||
|
|
@ -11642,7 +11642,7 @@ func rewriteValuePPC64_OpPPC64MOVWloadidx_0(v *Value) bool {
|
|||
return true
|
||||
}
|
||||
// match: (MOVWloadidx (MOVDconst [c]) ptr mem)
|
||||
// cond: is16Bit(c)
|
||||
// cond: is16Bit(c) && c%4 == 0
|
||||
// result: (MOVWload [c] ptr mem)
|
||||
for {
|
||||
mem := v.Args[2]
|
||||
|
|
@ -11652,7 +11652,7 @@ func rewriteValuePPC64_OpPPC64MOVWloadidx_0(v *Value) bool {
|
|||
}
|
||||
c := v_0.AuxInt
|
||||
ptr := v.Args[1]
|
||||
if !(is16Bit(c)) {
|
||||
if !(is16Bit(c) && c%4 == 0) {
|
||||
break
|
||||
}
|
||||
v.reset(OpPPC64MOVWload)
|
||||
|
|
|
|||
5561
src/cmd/compile/internal/ssa/rewriteRISCV64.go
Normal file
5561
src/cmd/compile/internal/ssa/rewriteRISCV64.go
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -66,7 +66,7 @@ func (op Op) isLoweredGetClosurePtr() bool {
|
|||
switch op {
|
||||
case OpAMD64LoweredGetClosurePtr, OpPPC64LoweredGetClosurePtr, OpARMLoweredGetClosurePtr, OpARM64LoweredGetClosurePtr,
|
||||
Op386LoweredGetClosurePtr, OpMIPS64LoweredGetClosurePtr, OpS390XLoweredGetClosurePtr, OpMIPSLoweredGetClosurePtr,
|
||||
OpWasmLoweredGetClosurePtr:
|
||||
OpRISCV64LoweredGetClosurePtr, OpWasmLoweredGetClosurePtr:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
|
@ -115,7 +115,7 @@ func schedule(f *Func) {
|
|||
v.Op == OpARMLoweredNilCheck || v.Op == OpARM64LoweredNilCheck ||
|
||||
v.Op == Op386LoweredNilCheck || v.Op == OpMIPS64LoweredNilCheck ||
|
||||
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.
|
||||
score[v.ID] = ScoreNilCheck
|
||||
case v.Op == OpPhi:
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@
|
|||
6: func test() {
|
||||
8: go func() {}()
|
||||
10: for {
|
||||
1048575:
|
||||
1: package main
|
||||
10: for {
|
||||
1048575:
|
||||
1: package main
|
||||
10: for {
|
||||
1048575:
|
||||
1: package main
|
||||
10: for {
|
||||
1048575:
|
||||
1: package main
|
||||
10: for {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ var (
|
|||
Dowidth func(*Type)
|
||||
Fatalf func(string, ...interface{})
|
||||
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)
|
||||
FormatType func(*Type, fmt.State, rune, int) // orig: func typeFormat(t *Type, s fmt.State, verb rune, mode fmtMode)
|
||||
TypeLinkSym func(*Type) *obj.LSym
|
||||
|
|
@ -39,25 +39,23 @@ func (sym *Sym) Format(s fmt.State, verb rune) {
|
|||
}
|
||||
|
||||
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)
|
||||
// must take care not to use a type in a formatting string
|
||||
// to avoid resetting the recursion counter.
|
||||
return Tconv(t, 0, FErr, 0)
|
||||
// must handle recursive types correctly.
|
||||
return Tconv(t, 0, FErr)
|
||||
}
|
||||
|
||||
// ShortString generates a short description of t.
|
||||
// It is used in autogenerated method names, reflection,
|
||||
// and itab names.
|
||||
func (t *Type) ShortString() string {
|
||||
return Tconv(t, FmtLeft, FErr, 0)
|
||||
return Tconv(t, FmtLeft, FErr)
|
||||
}
|
||||
|
||||
// LongString generates a complete description of t.
|
||||
// It is useful for reflection,
|
||||
// or when a unique fingerprint or hash of a type is required.
|
||||
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) {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import (
|
|||
"cmd/compile/internal/mips"
|
||||
"cmd/compile/internal/mips64"
|
||||
"cmd/compile/internal/ppc64"
|
||||
"cmd/compile/internal/riscv64"
|
||||
"cmd/compile/internal/s390x"
|
||||
"cmd/compile/internal/wasm"
|
||||
"cmd/compile/internal/x86"
|
||||
|
|
@ -32,6 +33,7 @@ var archInits = map[string]func(*gc.Arch){
|
|||
"mips64le": mips64.Init,
|
||||
"ppc64": ppc64.Init,
|
||||
"ppc64le": ppc64.Init,
|
||||
"riscv64": riscv64.Init,
|
||||
"s390x": s390x.Init,
|
||||
"wasm": wasm.Init,
|
||||
}
|
||||
|
|
|
|||
20
src/cmd/dist/build.go
vendored
20
src/cmd/dist/build.go
vendored
|
|
@ -110,6 +110,9 @@ func xinit() {
|
|||
fatalf("$GOROOT must be set")
|
||||
}
|
||||
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")
|
||||
if b == "" {
|
||||
|
|
@ -1532,7 +1535,7 @@ var cgoEnabled = map[string]bool{
|
|||
"linux/mipsle": true,
|
||||
"linux/mips64": true,
|
||||
"linux/mips64le": true,
|
||||
"linux/riscv64": true,
|
||||
"linux/riscv64": false, // Issue 36641
|
||||
"linux/s390x": true,
|
||||
"linux/sparc64": 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
|
||||
// filtered out of cgoEnabled for 'dist list'. See golang.org/issue/28944
|
||||
var incomplete = map[string]bool{
|
||||
"linux/riscv64": 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 {
|
||||
// xgetwd might return a path with symlinks fully resolved, and if
|
||||
// there happens to be symlinks in goroot, then the hasprefix test
|
||||
|
|
|
|||
3
src/cmd/dist/buildtool.go
vendored
3
src/cmd/dist/buildtool.go
vendored
|
|
@ -45,10 +45,11 @@ var bootstrapDirs = []string{
|
|||
"cmd/compile/internal/mips",
|
||||
"cmd/compile/internal/mips64",
|
||||
"cmd/compile/internal/ppc64",
|
||||
"cmd/compile/internal/types",
|
||||
"cmd/compile/internal/riscv64",
|
||||
"cmd/compile/internal/s390x",
|
||||
"cmd/compile/internal/ssa",
|
||||
"cmd/compile/internal/syntax",
|
||||
"cmd/compile/internal/types",
|
||||
"cmd/compile/internal/x86",
|
||||
"cmd/compile/internal/wasm",
|
||||
"cmd/internal/bio",
|
||||
|
|
|
|||
2
src/cmd/dist/main.go
vendored
2
src/cmd/dist/main.go
vendored
|
|
@ -122,6 +122,8 @@ func main() {
|
|||
if elfIsLittleEndian(os.Args[0]) {
|
||||
gohostarch = "mipsle"
|
||||
}
|
||||
case strings.Contains(out, "riscv64"):
|
||||
gohostarch = "riscv64"
|
||||
case strings.Contains(out, "s390x"):
|
||||
gohostarch = "s390x"
|
||||
case gohostos == "darwin":
|
||||
|
|
|
|||
|
|
@ -65,9 +65,10 @@ func usage() {
|
|||
fmt.Fprintf(os.Stderr, "Usage of [go] doc:\n")
|
||||
fmt.Fprintf(os.Stderr, "\tgo doc\n")
|
||||
fmt.Fprintf(os.Stderr, "\tgo doc <pkg>\n")
|
||||
fmt.Fprintf(os.Stderr, "\tgo doc <sym>[.<method>]\n")
|
||||
fmt.Fprintf(os.Stderr, "\tgo doc [<pkg>].<sym>[.<method>]\n")
|
||||
fmt.Fprintf(os.Stderr, "\tgo doc <pkg> <sym>[.<method>]\n")
|
||||
fmt.Fprintf(os.Stderr, "\tgo doc <sym>[.<methodOrField>]\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, "\tgo doc <pkg> <sym>[.<methodOrField>]\n")
|
||||
fmt.Fprintf(os.Stderr, "For more information run\n")
|
||||
fmt.Fprintf(os.Stderr, "\tgo help doc\n\n")
|
||||
fmt.Fprintf(os.Stderr, "Flags:\n")
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ require (
|
|||
github.com/google/pprof v0.0.0-20191105193234-27840fff0d09
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20180524225900-fc6590592b44 // indirect
|
||||
golang.org/x/arch v0.0.0-20190815191158-8a70ba74b3a1
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550
|
||||
golang.org/x/mod v0.1.1-0.20191126161957-788aebd06792
|
||||
golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d
|
||||
golang.org/x/mod v0.2.0
|
||||
golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82 // indirect
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e
|
||||
)
|
||||
|
|
|
|||
|
|
@ -7,8 +7,10 @@ golang.org/x/arch v0.0.0-20190815191158-8a70ba74b3a1/go.mod h1:flIaEI6LNU6xOCD5P
|
|||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
|
||||
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/mod v0.1.1-0.20191126161957-788aebd06792/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d h1:9FCpayM9Egr1baVnV1SX0H87m+XB0B8S0hAMi99X/3U=
|
||||
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-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
|
|
|||
|
|
@ -907,7 +907,7 @@
|
|||
// Main bool // is this the main module?
|
||||
// Indirect bool // is this module only an indirect dependency of main module?
|
||||
// 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
|
||||
// Error *ModuleError // error loading module
|
||||
// }
|
||||
|
|
@ -916,6 +916,9 @@
|
|||
// 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
|
||||
// information about the version and replacement if any.
|
||||
// For example, 'go list -m all' might print:
|
||||
|
|
@ -1020,7 +1023,9 @@
|
|||
// 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.
|
||||
//
|
||||
// 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
|
||||
// to standard output, describing each downloaded module (or failure),
|
||||
// corresponding to this Go struct:
|
||||
|
|
@ -1075,12 +1080,17 @@
|
|||
// 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.
|
||||
//
|
||||
// The -replace=old[@v]=new[@v] and -dropreplace=old[@v] flags
|
||||
// add and drop a replacement of the given module path and version pair.
|
||||
// If the @v in old@v is omitted, the replacement applies to all versions
|
||||
// with the old module path. If the @v in new@v is omitted, the new path
|
||||
// should be a local module root directory, not a module path.
|
||||
// Note that -replace overrides any existing replacements for old[@v].
|
||||
// The -replace=old[@v]=new[@v] flag adds a replacement of the given
|
||||
// module path and version pair. If the @v in old@v is omitted, a
|
||||
// replacement without a version on the left side is added, which applies
|
||||
// to all versions of the old module path. If the @v in new@v is omitted,
|
||||
// the new path should be a local module root directory, not a module
|
||||
// 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,
|
||||
// and -dropreplace editing flags may be repeated, and the changes
|
||||
|
|
@ -1721,8 +1731,10 @@
|
|||
// GOHOSTOS
|
||||
// The operating system (GOOS) of the Go toolchain binaries.
|
||||
// GOMOD
|
||||
// The absolute path to the go.mod of the main module,
|
||||
// or the empty string if not using modules.
|
||||
// The absolute path to the go.mod of the main module.
|
||||
// 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
|
||||
// The directory where the go tools (compile, cover, doc, etc...) are installed.
|
||||
//
|
||||
|
|
@ -2339,14 +2351,15 @@
|
|||
//
|
||||
// Module support
|
||||
//
|
||||
// Go 1.13 includes support for Go modules. Module-aware mode is active by default
|
||||
// whenever a go.mod file is found in, or in a parent of, the current directory.
|
||||
// The go command includes support for Go modules. Module-aware mode is active
|
||||
// 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
|
||||
// repository, create a go.mod file (described in the next section) there, and run
|
||||
// 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
|
||||
// of three string values: off, on, or auto (the default).
|
||||
// If GO111MODULE=on, then the go command requires the use of modules,
|
||||
|
|
|
|||
|
|
@ -638,7 +638,7 @@ func (tg *testgoData) grepStderrNot(match, msg string) {
|
|||
}
|
||||
|
||||
// grepBothNot looks for a regular expression in the test run's
|
||||
// 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.
|
||||
func (tg *testgoData) grepBothNot(match, msg string) {
|
||||
tg.t.Helper()
|
||||
|
|
@ -913,6 +913,7 @@ func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) {
|
|||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
|
||||
// Copy the runtime packages into a temporary GOROOT
|
||||
// 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")
|
||||
}
|
||||
|
||||
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) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
|
|
@ -1062,56 +1041,6 @@ func TestInternalCache(t *testing.T) {
|
|||
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.
|
||||
func TestIssue10952(t *testing.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) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
|
|
@ -1672,6 +1583,7 @@ func TestDefaultGOPATHGet(t *testing.T) {
|
|||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
tg.setenv("GOPATH", "")
|
||||
tg.tempDir("home")
|
||||
tg.setenv(homeEnvName(), tg.path("home"))
|
||||
|
|
@ -1696,6 +1608,7 @@ func TestDefaultGOPATHGet(t *testing.T) {
|
|||
func TestDefaultGOPATHPrintedSearchList(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
tg.setenv("GOPATH", "")
|
||||
tg.tempDir("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")
|
||||
}
|
||||
|
||||
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) {
|
||||
skipIfGccgo(t, "gccgo has no standard packages")
|
||||
tooSlow(t)
|
||||
|
|
@ -2191,33 +2094,6 @@ func TestCoverageNoStatements(t *testing.T) {
|
|||
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) {
|
||||
skipIfGccgo(t, "gccgo has no cover tool")
|
||||
tooSlow(t)
|
||||
|
|
@ -2290,20 +2166,6 @@ func TestCoverageDashC(t *testing.T) {
|
|||
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) {
|
||||
if !canRace {
|
||||
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")
|
||||
}
|
||||
|
||||
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) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping test that removes $GOROOT/pkg/*_race in short mode")
|
||||
|
|
@ -2434,6 +2263,8 @@ func TestCgoDependsOnSyscall(t *testing.T) {
|
|||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
|
||||
files, err := filepath.Glob(filepath.Join(runtime.GOROOT(), "pkg", "*_race"))
|
||||
tg.must(err)
|
||||
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) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
|
|
@ -2676,17 +2499,6 @@ func TestGoBuildTestOnly(t *testing.T) {
|
|||
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) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
|
|
@ -2714,29 +2526,6 @@ func TestGoTestMainAsNormalTest(t *testing.T) {
|
|||
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) {
|
||||
tg := testgo(t)
|
||||
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) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
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) {
|
||||
// golang.org/issue/9224.
|
||||
// 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")
|
||||
}
|
||||
|
||||
// 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) {
|
||||
tooSlow(t)
|
||||
|
||||
|
|
@ -3812,16 +3529,6 @@ func TestMatchesNoTests(t *testing.T) {
|
|||
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) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
|
|
@ -3849,18 +3556,6 @@ func TestMatchesOnlyBenchmarkIsOK(t *testing.T) {
|
|||
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) {
|
||||
tg := testgo(t)
|
||||
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")
|
||||
}
|
||||
|
||||
// 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.
|
||||
func TestBuildIDContainsArchModeEnv(t *testing.T) {
|
||||
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) {
|
||||
tooSlow(t)
|
||||
var tg *testgoData
|
||||
|
|
@ -4407,6 +4029,7 @@ func TestBuildmodePIE(t *testing.T) {
|
|||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
|
||||
tg.tempFile("main.go", `package main; func main() { print("hello") }`)
|
||||
src := tg.path("main.go")
|
||||
|
|
@ -4570,6 +4193,7 @@ func TestUpxCompression(t *testing.T) {
|
|||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
|
||||
tg.tempFile("main.go", `package main; import "fmt"; func main() { fmt.Print("hello upx") }`)
|
||||
src := tg.path("main.go")
|
||||
|
|
@ -4963,14 +4587,6 @@ func TestInstallDeps(t *testing.T) {
|
|||
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) {
|
||||
skipIfGccgo(t, "gccgo does not have standard packages")
|
||||
tooSlow(t)
|
||||
|
|
@ -5108,6 +4724,7 @@ func init() {}
|
|||
func TestBadCommandLines(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
|
||||
tg.tempFile("src/x/x.go", "package x\n")
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
|
|
@ -5328,6 +4945,7 @@ func TestCgoCache(t *testing.T) {
|
|||
func TestFilepathUnderCwdFormat(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
tg.run("test", "-x", "-cover", "log")
|
||||
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.
|
||||
func TestGoBuildDashODevNull(t *testing.T) {
|
||||
tooSlow(t)
|
||||
|
|
|
|||
|
|
@ -178,7 +178,9 @@ func runClean(cmd *base.Command, args []string) {
|
|||
}
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import (
|
|||
|
||||
"cmd/go/internal/base"
|
||||
"cmd/go/internal/cfg"
|
||||
"cmd/go/internal/load"
|
||||
"cmd/go/internal/web"
|
||||
)
|
||||
|
||||
|
|
@ -661,7 +662,7 @@ func RepoRootForImportPath(importPath string, mod ModuleMode, security web.Secur
|
|||
if err == errUnknownSite {
|
||||
rr, err = repoRootForImportDynamic(importPath, mod, security)
|
||||
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 {
|
||||
|
|
@ -676,7 +677,7 @@ func RepoRootForImportPath(importPath string, mod ModuleMode, security web.Secur
|
|||
if err == nil && strings.Contains(importPath, "...") && strings.Contains(rr.Root, "...") {
|
||||
// Do not allow wildcards in the repo root.
|
||||
rr = nil
|
||||
err = fmt.Errorf("cannot expand ... in %q", importPath)
|
||||
err = load.ImportErrorf(importPath, "cannot expand ... in %q", importPath)
|
||||
}
|
||||
return rr, err
|
||||
}
|
||||
|
|
@ -700,7 +701,7 @@ func repoRootFromVCSPaths(importPath string, security web.SecurityMode, vcsPaths
|
|||
m := srv.regexp.FindStringSubmatch(importPath)
|
||||
if m == nil {
|
||||
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -621,8 +621,10 @@ Additional information available from 'go env' but not read from the environment
|
|||
GOHOSTOS
|
||||
The operating system (GOOS) of the Go toolchain binaries.
|
||||
GOMOD
|
||||
The absolute path to the go.mod of the main module,
|
||||
or the empty string if not using modules.
|
||||
The absolute path to the go.mod of the main module.
|
||||
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
|
||||
The directory where the go tools (compile, cover, doc, etc...) are installed.
|
||||
`,
|
||||
|
|
|
|||
|
|
@ -211,7 +211,7 @@ applied to a Go struct, but now a Module struct:
|
|||
Main bool // is this the main module?
|
||||
Indirect bool // is this module only an indirect dependency of main module?
|
||||
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
|
||||
Error *ModuleError // error loading module
|
||||
}
|
||||
|
|
@ -220,6 +220,9 @@ applied to a Go struct, but now a Module struct:
|
|||
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
|
||||
information about the version and replacement if any.
|
||||
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.
|
||||
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 {
|
||||
// In vendor mode, the module graph is incomplete: it contains only the
|
||||
// explicit module dependencies and the modules that supply packages in
|
||||
// the import graph. Reject queries that imply more information than that.
|
||||
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, "...") {
|
||||
base.Fatalf("go list -m: can't match module patterns using the vendor directory\n\t(Use -mod=mod or -mod=readonly to bypass.)")
|
||||
base.Fatalf(actionDisabledFormat, "match module patterns")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"go/scanner"
|
||||
"go/token"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
|
@ -1519,17 +1520,30 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
|
|||
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 _, ok := err.(*build.NoGoError); ok {
|
||||
err = &NoGoError{Package: p}
|
||||
}
|
||||
p.Incomplete = true
|
||||
err = base.ExpandScanner(err)
|
||||
p.Error = &PackageError{
|
||||
ImportStack: stk.Copy(),
|
||||
Err: err,
|
||||
|
||||
setError(base.ExpandScanner(err))
|
||||
if _, isScanErr := err.(scanner.ErrorList); !isScanErr {
|
||||
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"
|
||||
|
|
@ -1545,7 +1559,7 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
|
|||
if InstallTargetDir(p) == StalePath {
|
||||
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)
|
||||
p.Error = &PackageError{Err: e}
|
||||
setError(e)
|
||||
return
|
||||
}
|
||||
elem := p.DefaultExecName()
|
||||
|
|
@ -1658,10 +1672,7 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
|
|||
inputs := p.AllFiles()
|
||||
f1, f2 := str.FoldDup(inputs)
|
||||
if f1 != "" {
|
||||
p.Error = &PackageError{
|
||||
ImportStack: stk.Copy(),
|
||||
Err: fmt.Errorf("case-insensitive file name collision: %q and %q", f1, f2),
|
||||
}
|
||||
setError(fmt.Errorf("case-insensitive file name collision: %q and %q", f1, f2))
|
||||
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.
|
||||
for _, file := range inputs {
|
||||
if !SafeArg(file) || strings.HasPrefix(file, "_cgo_") {
|
||||
p.Error = &PackageError{
|
||||
ImportStack: stk.Copy(),
|
||||
Err: fmt.Errorf("invalid input file name %q", file),
|
||||
}
|
||||
setError(fmt.Errorf("invalid input file name %q", file))
|
||||
return
|
||||
}
|
||||
}
|
||||
if name := pathpkg.Base(p.ImportPath); !SafeArg(name) {
|
||||
p.Error = &PackageError{
|
||||
ImportStack: stk.Copy(),
|
||||
Err: fmt.Errorf("invalid input directory name %q", name),
|
||||
}
|
||||
setError(fmt.Errorf("invalid input directory name %q", name))
|
||||
return
|
||||
}
|
||||
if !SafeArg(p.ImportPath) {
|
||||
p.Error = &PackageError{
|
||||
ImportStack: stk.Copy(),
|
||||
Err: ImportErrorf(p.ImportPath, "invalid import path %q", p.ImportPath),
|
||||
}
|
||||
setError(ImportErrorf(p.ImportPath, "invalid import path %q", p.ImportPath))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -1737,13 +1739,6 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
|
|||
// 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.
|
||||
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, " ")))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
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
|
||||
to standard output, describing each downloaded module (or failure),
|
||||
corresponding to this Go struct:
|
||||
|
|
|
|||
|
|
@ -55,12 +55,17 @@ The -exclude=path@version and -dropexclude=path@version flags
|
|||
add and drop an exclusion for the given module path and version.
|
||||
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
|
||||
add and drop a replacement of the given module path and version pair.
|
||||
If the @v in old@v is omitted, the replacement applies to all versions
|
||||
with the old module path. If the @v in new@v is omitted, the new path
|
||||
should be a local module root directory, not a module path.
|
||||
Note that -replace overrides any existing replacements for old[@v].
|
||||
The -replace=old[@v]=new[@v] flag adds a replacement of the given
|
||||
module path and version pair. If the @v in old@v is omitted, a
|
||||
replacement without a version on the left side is added, which applies
|
||||
to all versions of the old module path. If the @v in new@v is omitted,
|
||||
the new path should be a local module root directory, not a module
|
||||
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,
|
||||
and -dropreplace editing flags may be repeated, and the changes
|
||||
|
|
@ -164,7 +169,7 @@ func runEdit(cmd *base.Command, args []string) {
|
|||
}
|
||||
|
||||
if *editModule != "" {
|
||||
if err := module.CheckPath(*editModule); err != nil {
|
||||
if err := module.CheckImportPath(*editModule); err != nil {
|
||||
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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
|
|
@ -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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
return path
|
||||
|
|
@ -278,7 +283,7 @@ func parsePathVersionOptional(adj, arg string, allowDirPath bool) (path, version
|
|||
} else {
|
||||
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) {
|
||||
return path, version, fmt.Errorf("invalid %s path: %v", adj, err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"cmd/go/internal/base"
|
||||
"cmd/go/internal/cfg"
|
||||
|
|
@ -28,8 +27,6 @@ import (
|
|||
|
||||
var PkgMod string // $GOPATH/pkg/mod; set by package modload
|
||||
|
||||
const logFindingDelay = 1 * time.Second
|
||||
|
||||
func cacheDir(path string) (string, error) {
|
||||
if PkgMod == "" {
|
||||
return "", fmt.Errorf("internal error: modfetch.PkgMod not set")
|
||||
|
|
@ -140,11 +137,6 @@ func (r *cachingRepo) Versions(prefix string) ([]string, error) {
|
|||
err error
|
||||
}
|
||||
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)
|
||||
return cached{list, err}
|
||||
}).(cached)
|
||||
|
|
@ -167,11 +159,6 @@ func (r *cachingRepo) Stat(rev string) (*RevInfo, error) {
|
|||
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)
|
||||
if err == nil {
|
||||
// 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) {
|
||||
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()
|
||||
|
||||
// Save info for likely future Stat call.
|
||||
|
|
|
|||
|
|
@ -682,8 +682,11 @@ func (r *gitRepo) RecentTag(rev, prefix, major string) (tag string, err error) {
|
|||
|
||||
semtag := line[len(prefix):]
|
||||
// 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) {
|
||||
highest = semver.Max(highest, semtag)
|
||||
// NOTE: Do not replace the call to semver.Compare with semver.Max.
|
||||
// We want to return the actual tag, not a canonicalized version of it,
|
||||
// and semver.Max currently canonicalizes (see golang.org/issue/32700).
|
||||
if c := semver.Canonical(semtag); c != "" && strings.HasPrefix(semtag, c) && (major == "" || semver.Major(c) == major) && semver.Compare(semtag, highest) > 0 {
|
||||
highest = semtag
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -191,22 +191,6 @@ func (r *codeRepo) appendIncompatibleVersions(list, incompatible []string) ([]st
|
|||
return list, nil
|
||||
}
|
||||
|
||||
// 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) {
|
||||
_, err := r.code.ReadFile(v, "go.mod", codehost.MaxGoMod)
|
||||
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 {
|
||||
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
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
|
|
@ -359,7 +352,7 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e
|
|||
Path: r.modPath,
|
||||
Err: &module.InvalidVersionError{
|
||||
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)
|
||||
}
|
||||
mpath1 := modfile.ModulePath(gomod1)
|
||||
found1 := err1 == nil && isMajor(mpath1, r.pathMajor)
|
||||
found1 := err1 == nil && (isMajor(mpath1, r.pathMajor) || r.canReplaceMismatchedVersionDueToBug(mpath1))
|
||||
|
||||
var file2 string
|
||||
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:]
|
||||
}
|
||||
|
||||
// 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) {
|
||||
if version != module.CanonicalVersion(version) {
|
||||
return nil, fmt.Errorf("version %s is not canonical", version)
|
||||
|
|
|
|||
|
|
@ -250,9 +250,9 @@ func (lookupDisabledError) Error() string {
|
|||
var errLookupDisabled error = lookupDisabledError{}
|
||||
|
||||
var (
|
||||
errProxyOff = notExistError("module lookup disabled by GOPROXY=off")
|
||||
errNoproxy error = notExistError("disabled by GOPRIVATE/GONOPROXY")
|
||||
errUseProxy error = notExistError("path does not match GOPRIVATE/GONOPROXY")
|
||||
errProxyOff = notExistErrorf("module lookup disabled by GOPROXY=off")
|
||||
errNoproxy error = notExistErrorf("disabled by GOPRIVATE/GONOPROXY")
|
||||
errUseProxy error = notExistErrorf("path does not match GOPRIVATE/GONOPROXY")
|
||||
)
|
||||
|
||||
func lookupDirect(path string) (Repo, error) {
|
||||
|
|
@ -264,7 +264,7 @@ func lookupDirect(path string) (Repo, error) {
|
|||
rr, err := get.RepoRootForImportPath(path, get.PreferMod, security)
|
||||
if err != nil {
|
||||
// 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" {
|
||||
|
|
@ -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
|
||||
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 {
|
||||
return string(e)
|
||||
return e.err.Error()
|
||||
}
|
||||
|
||||
func (notExistError) Is(target error) bool {
|
||||
return target == os.ErrNotExist
|
||||
}
|
||||
|
||||
func (e notExistError) Unwrap() error {
|
||||
return e.err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ func moduleInfo(m module.Version, fromBuildList bool) *modinfo.ModulePublic {
|
|||
}
|
||||
if HasModRoot() {
|
||||
info.Dir = ModRoot()
|
||||
info.GoMod = filepath.Join(info.Dir, "go.mod")
|
||||
info.GoMod = ModFilePath()
|
||||
if modFile.Go != nil {
|
||||
info.GoVersion = modFile.Go.Version
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,14 +21,15 @@ which source files are used in a given build.
|
|||
|
||||
Module support
|
||||
|
||||
Go 1.13 includes support for Go modules. Module-aware mode is active by default
|
||||
whenever a go.mod file is found in, or in a parent of, the current directory.
|
||||
The go command includes support for Go modules. Module-aware mode is active
|
||||
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
|
||||
repository, create a go.mod file (described in the next section) there, and run
|
||||
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
|
||||
of three string values: off, on, or auto (the default).
|
||||
If GO111MODULE=on, then the go command requires the use of modules,
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ import (
|
|||
"cmd/go/internal/modfetch"
|
||||
"cmd/go/internal/par"
|
||||
"cmd/go/internal/search"
|
||||
"cmd/go/internal/str"
|
||||
|
||||
"golang.org/x/mod/module"
|
||||
"golang.org/x/mod/semver"
|
||||
|
|
@ -40,7 +39,7 @@ var _ load.ImportPathError = (*ImportMissingError)(nil)
|
|||
|
||||
func (e *ImportMissingError) Error() string {
|
||||
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))
|
||||
}
|
||||
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?
|
||||
if search.IsStandardImportPath(path) &&
|
||||
goroot.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, path) {
|
||||
pathIsStd := search.IsStandardImportPath(path)
|
||||
if pathIsStd && goroot.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, path) {
|
||||
if targetInGorootSrc {
|
||||
if dir, ok := dirInModule(path, targetPrefix, ModRoot(), true); ok {
|
||||
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)
|
||||
return module.Version{}, dir, nil
|
||||
}
|
||||
if str.HasPathPrefix(path, "cmd") {
|
||||
return module.Version{}, "", &ImportMissingError{Path: path}
|
||||
}
|
||||
|
||||
// -mod=vendor is special.
|
||||
// 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.
|
||||
// Goal is to determine the module, download it to dir, and return m, dir, ErrMissing.
|
||||
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 {
|
||||
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
|
||||
for _, r := range modFile.Replace {
|
||||
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)
|
||||
if err != nil {
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
|
|
|
|||
|
|
@ -1320,6 +1320,21 @@ func fetch(mod module.Version) (dir string, isLocal bool, err error) {
|
|||
if !filepath.IsAbs(dir) {
|
||||
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
|
||||
}
|
||||
mod = r
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ func queryProxy(proxy, path, query, current string, allowed func(module.Version)
|
|||
if current != "" && !semver.IsValid(current) {
|
||||
return nil, fmt.Errorf("invalid previous version %q", current)
|
||||
}
|
||||
if cfg.BuildMod != "" && cfg.BuildMod != "mod" {
|
||||
if cfg.BuildMod == "vendor" {
|
||||
return nil, errQueryDisabled
|
||||
}
|
||||
if allowed == nil {
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ var queryTests = []struct {
|
|||
git add go.mod
|
||||
git commit -m v1 go.mod
|
||||
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
|
||||
git add 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.0", vers: "v0.0.3"},
|
||||
{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
|
||||
// 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: "latest", vers: "v2.5.5"},
|
||||
|
||||
// e0cf3de987e6 is the latest commit on the master branch, and it's actually
|
||||
// v1.19.10-pre1, not anything resembling v3: attempting to query it as such
|
||||
// should fail.
|
||||
// Commit e0cf3de987e6 is actually v1.19.10-pre1, not anything resembling v3,
|
||||
// and it has a go.mod file with a non-v3 module path. Attempting to query it
|
||||
// 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`},
|
||||
|
||||
// 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: emptyRepo, query: "latest", vers: "v0.0.0-20180704023549-7bb914627242"},
|
||||
|
|
|
|||
|
|
@ -88,7 +88,8 @@ func init() {
|
|||
// go test fmt -custom-flag-for-fmt-test
|
||||
// go test -x math
|
||||
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
|
||||
var explicitArgs []string
|
||||
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])
|
||||
continue
|
||||
}
|
||||
if i < len(goflags) {
|
||||
f.Present = false // Not actually present on the command line.
|
||||
}
|
||||
if f.Value != nil {
|
||||
if err := f.Value.Set(value); err != nil {
|
||||
base.Fatalf("invalid flag argument for -%s: %v", f.Name, err)
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ func runVet(cmd *base.Command, args []string) {
|
|||
|
||||
work.BuildInit()
|
||||
work.VetFlags = vetFlags
|
||||
work.VetExplicit = true
|
||||
if vetTool != "" {
|
||||
var err error
|
||||
work.VetTool, err = filepath.Abs(vetTool)
|
||||
|
|
|
|||
|
|
@ -126,7 +126,8 @@ func vetFlags(usage func(), args []string) (passToVet, packageNames []string) {
|
|||
})
|
||||
|
||||
// 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++ {
|
||||
if !strings.HasPrefix(args[i], "-") {
|
||||
return args[:i], args[i:]
|
||||
|
|
@ -139,6 +140,9 @@ func vetFlags(usage func(), args []string) (passToVet, packageNames []string) {
|
|||
base.SetExitStatus(2)
|
||||
base.Exit()
|
||||
}
|
||||
if i < len(goflags) {
|
||||
f.Present = false // Not actually present on the command line.
|
||||
}
|
||||
if f.Value != nil {
|
||||
if err := f.Value.Set(value); err != nil {
|
||||
base.Fatalf("invalid flag argument for -%s: %v", f.Name, err)
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ func TestGetFileURL(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(f.Name())
|
||||
|
||||
if _, err := f.WriteString(content); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -291,7 +291,7 @@ func (b *Builder) Init() {
|
|||
}
|
||||
|
||||
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.Exit()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1036,7 +1036,7 @@ func (b *Builder) vet(a *Action) error {
|
|||
// There's too much unsafe.Pointer code
|
||||
// that vet doesn't like in low-level packages
|
||||
// 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
|
||||
|
|
@ -1774,6 +1774,11 @@ func (b *Builder) fmtcmd(dir string, format string, args ...interface{}) string
|
|||
}
|
||||
if b.WorkDir != "" {
|
||||
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -227,8 +227,8 @@ func (a *Action) trimpath() string {
|
|||
// For "go build -trimpath", rewrite package source directory
|
||||
// to a file system-independent path (just the import path).
|
||||
if cfg.BuildTrimpath {
|
||||
if m := a.Package.Module; m != nil {
|
||||
rewrite += ";" + m.Dir + "=>" + m.Path + "@" + m.Version
|
||||
if m := a.Package.Module; m != nil && m.Version != "" {
|
||||
rewrite += ";" + a.Package.Dir + "=>" + m.Path + "@" + m.Version + strings.TrimPrefix(a.Package.ImportPath, m.Path)
|
||||
} else {
|
||||
rewrite += ";" + a.Package.Dir + "=>" + a.Package.ImportPath
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ var validCompilerFlags = []*lazyregexp.Regexp{
|
|||
re(`-W([^@,]+)`), // -Wall but not -Wa,-foo.
|
||||
re(`-Wa,-mbig-obj`),
|
||||
re(`-Wp,-D([A-Za-z_].*)`),
|
||||
re(`-Wp, -U([A-Za-z_]*)`),
|
||||
re(`-Wp,-U([A-Za-z_]*)`),
|
||||
re(`-ansi`),
|
||||
re(`-f(no-)?asynchronous-unwind-tables`),
|
||||
re(`-f(no-)?blocks`),
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ var goodCompilerFlags = [][]string{
|
|||
{"-Osmall"},
|
||||
{"-W"},
|
||||
{"-Wall"},
|
||||
{"-Wp,-Dfoo=bar"},
|
||||
{"-Wp,-Ufoo"},
|
||||
{"-fobjc-arc"},
|
||||
{"-fno-objc-arc"},
|
||||
{"-fomit-frame-pointer"},
|
||||
|
|
|
|||
1
src/cmd/go/testdata/badmod/go.mod
vendored
1
src/cmd/go/testdata/badmod/go.mod
vendored
|
|
@ -1 +0,0 @@
|
|||
module m
|
||||
4
src/cmd/go/testdata/badmod/x.go
vendored
4
src/cmd/go/testdata/badmod/x.go
vendored
|
|
@ -1,4 +0,0 @@
|
|||
package x
|
||||
|
||||
import _ "appengine"
|
||||
import _ "nonexistent.rsc.io" // domain does not exist
|
||||
3
src/cmd/go/testdata/importcom/bad.go
vendored
3
src/cmd/go/testdata/importcom/bad.go
vendored
|
|
@ -1,3 +0,0 @@
|
|||
package p
|
||||
|
||||
import "bad"
|
||||
3
src/cmd/go/testdata/importcom/conflict.go
vendored
3
src/cmd/go/testdata/importcom/conflict.go
vendored
|
|
@ -1,3 +0,0 @@
|
|||
package p
|
||||
|
||||
import "conflict"
|
||||
1
src/cmd/go/testdata/importcom/src/bad/bad.go
vendored
1
src/cmd/go/testdata/importcom/src/bad/bad.go
vendored
|
|
@ -1 +0,0 @@
|
|||
package bad // import
|
||||
|
|
@ -1 +0,0 @@
|
|||
package conflict // import "a"
|
||||
|
|
@ -1 +0,0 @@
|
|||
package conflict /* import "b" */
|
||||
|
|
@ -1 +0,0 @@
|
|||
package x // import "works/x"
|
||||
|
|
@ -1 +0,0 @@
|
|||
package x // important! not an import comment
|
||||
|
|
@ -1 +0,0 @@
|
|||
package x // import "my/x"
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue