src/cmd/go/zdefaultcc.go
src/cmd/internal/obj/zbootstrap.go
src/go/doc/headscan
-src/runtime/zversion.go
+src/runtime/internal/sys/zversion.go
src/unicode/maketables
src/*.*/
test/pass.out
# This file is distinct from the CONTRIBUTORS files.
# See the latter for an explanation.
-# Names should be added to this file as
-# Name or Organization <email address>
-# The email address is not required for organizations.
+# Names should be added to this file as one of
+# Organization's name
+# Individual's name <submission email address>
+# Individual's name <submission email address> <email2> <emailN>
+# See CONTRIBUTORS for the meaning of multiple email addresses.
# Please keep the list sorted.
Akshat Kumar <seed@mail.nanosouffle.net>
Alan Shreve <alan@inconshreveable.com>
Albert Strasheim <fullung@gmail.com>
+Alberto Bertogli <albertito@blitiri.com.ar>
Alberto Donizetti <alb.donizetti@gmail.com>
Alberto GarcÃa Hierro <alberto@garciahierro.com> <alberto.garcia.hierro@gmail.com>
Aleksandar Dezelin <dezelin@gmail.com>
Alex Plugaru <alex@plugaru.org> <alexandru.plugaru@gmail.com>
Alex Schroeder <alex@gnu.org>
Alex Sergeyev <abc@alexsergeyev.com>
+Alexander Demakin <alexander.demakin@gmail.com>
Alexander Larsson <alexander.larsson@gmail.com>
Alexander Morozov <lk4d4math@gmail.com>
Alexander Neumann <alexander@bumpern.de>
Andy Davis <andy@bigandian.com>
Andy Maloney <asmaloney@gmail.com>
Anfernee Yongkun Gui <anfernee.gui@gmail.com>
+Angelo Bulfone <mbulfone@gmail.com>
Anh Hai Trinh <anh.hai.trinh@gmail.com>
Anmol Sethi <anmol@aubble.com>
Anschel Schaffer-Cohen <anschelsc@gmail.com>
+Anthony Canino <anthony.canino1@gmail.com>
Anthony Eufemio <anthony.eufemio@gmail.com>
Anthony Martin <ality@pbrane.org>
Anthony Starks <ajstarks@gmail.com>
Areski Belaid <areski@gmail.com>
Arnaud Ysmal <arnaud.ysmal@gmail.com>
Arne Hormann <arnehormann@gmail.com>
+Arnout Engelen <arnout@bzzt.net>
Aron Nopanen <aron.nopanen@gmail.com>
Artyom Pervukhin <artyom.pervukhin@gmail.com>
Arvindh Rajesh Tamilmani <art@a-30.net>
Corey Thomasson <cthom.lists@gmail.com>
Cristian Staretu <unclejacksons@gmail.com>
Damian Gryski <dgryski@gmail.com>
+Dan Caddigan <goldcaddy77@gmail.com>
Dan Callahan <dan.callahan@gmail.com>
Dan Peterson <dpiddy@gmail.com>
Dan Sinclair <dan.sinclair@gmail.com>
Daniel Lidén <daniel.liden.87@gmail.com>
Daniel Morsing <daniel.morsing@gmail.com>
Daniel Ortiz Pereira da Silva <daniel.particular@gmail.com>
+Daniel Skinner <daniel@dasa.cc>
Daniel Theophanes <kardianos@gmail.com>
Darren Elwood <darren@textnode.com>
Dave Cheney <dave@cheney.net>
David du Colombier <0intro@gmail.com>
David Forsythe <dforsythe@gmail.com>
David G. Andersen <dave.andersen@gmail.com>
+David Howden <dhowden@gmail.com>
David Jakob Fritz <david.jakob.fritz@gmail.com>
David Leon Gil <coruus@gmail.com>
David R. Jenni <david.r.jenni@gmail.com>
Dmitriy Shelenin <deemok@googlemail.com> <deemok@gmail.com>
Dmitry Chestnykh <dchest@gmail.com>
Dmitry Savintsev <dsavints@gmail.com>
+Dmitry Yakunin <nonamezeil@gmail.com>
Dominik Honnef <dominik.honnef@gmail.com>
Donald Huang <don.hcd@gmail.com>
Donovan Hide <donovanhide@gmail.com>
Eivind Uggedal <eivind@uggedal.com>
Elias Naur <elias.naur@gmail.com>
Emil Hessman <c.emil.hessman@gmail.com> <emil@hessman.se>
+Emmanuel Odeke <emm.odeke@gmail.com> <odeke@ualberta.ca>
Eoghan Sherry <ejsherry@gmail.com>
Eric Clark <zerohp@gmail.com>
Eric Lagergren <ericscottlagergren@gmail.com>
Eric Milliken <emilliken@gmail.com>
Eric Roshan-Eisner <eric.d.eisner@gmail.com>
Erik Aigner <aigner.erik@gmail.com>
+Erik Dubbelboer <erik@dubbelboer.com>
Erik St. Martin <alakriti@gmail.com>
Erik Westrup <erik.westrup@gmail.com>
Esko Luontola <esko.luontola@gmail.com>
Florian Uekermann <florian@uekermann-online.de>
Florian Weimer <fw@deneb.enyo.de>
Florin Patan <florinpatan@gmail.com>
+Ford Hurley <ford.hurley@gmail.com>
+Francisco Claude <fclaude@recoded.cl>
Francisco Souza <franciscossouza@gmail.com>
Frederick Kelly Mayle III <frederickmayle@gmail.com>
Fredrik Enestad <fredrik.enestad@soundtrackyourbrand.com>
Frithjof Schulze <schulze@math.uni-hannover.de> <sfrithjof@gmail.com>
Gabriel Aszalos <gabriel.aszalos@gmail.com>
Gary Burd <gary@beagledreams.com>
+Gaurish Sharma <contact@gaurishsharma.com>
Gautham Thambidorai <gautham.dorai@gmail.com>
Geert-Johan Riemer <gjr19912@gmail.com>
Georg Reinke <guelfey@gmail.com>
Henrik Edwards <henrik.edwards@gmail.com>
Herbert Georg Fischer <herbert.fischer@gmail.com>
Hong Ruiqi <hongruiqi@gmail.com>
+Hsin-Ho Yeh <yhh92u@gmail.com>
Hu Keping <hukeping@huawei.com>
+Ian Gudger <ian@loosescre.ws>
IBM
Icarus Sparry <golang@icarus.freeuk.com>
Igneous Systems, Inc.
John C Barstow <jbowtie@amathaine.com>
John Graham-Cumming <jgc@jgc.org> <jgrahamc@gmail.com>
John Howard Palevich <jack.palevich@gmail.com>
+John Jenkins <twodopeshaggy@gmail.com>
John Potocny <johnp@vividcortex.com>
John Shahid <jvshahid@gmail.com>
John Tuley <john@tuley.org>
Ken Friedenbach <kenliz@cruzio.com>
Ken Rockot <ken@oz.gs>
Ken Sedgwick <ken@bonsai.com>
+Kenny Grant <kennygrant@gmail.com>
Kevin Ballard <kevin@sb.org>
+Klaus Post <klauspost@gmail.com>
Konstantin Shaposhnikov <k.shaposhnikov@gmail.com>
KPCompass, Inc.
Kristopher Watts <traetox@gmail.com>
Lai Jiangshan <eag0628@gmail.com>
Larz Conwell <larzconwell@gmail.com>
Lee Packham <lpackham@gmail.com>
+Lewin Bormann <lewin.bormann@gmail.com>
Liberty Fund Inc
Linaro Limited
Lloyd Dewolf <foolswisdom@gmail.com>
Luka Zakrajšek <tr00.g33k@gmail.com>
Luke Curley <qpingu@gmail.com>
Mal Curtis <mal@mal.co.nz>
+Manu S Ajith <neo@codingarena.in>
Manuel Mendez <mmendez534@gmail.com>
Marc Weistroff <marc@weistroff.net>
Marco Hennings <marco.hennings@freiheit.com>
Mats Lidell <mats.lidell@cag.se>
Matt Aimonetti <mattaimonetti@gmail.com>
Matt Bostock <matt@mattbostock.com>
+Matt Drollette <matt@drollette.com>
Matt Jibson <matt.jibson@gmail.com>
Matt Joiner <anacrolix@gmail.com>
Matt Layher <mdlayher@gmail.com>
Matthew Horsnell <matthew.horsnell@gmail.com>
Maxim Khitrov <max@mxcrypt.com>
Meir Fischer <meirfischer@gmail.com>
+Meng Zhuo <mengzhuo1203@gmail.com>
Meteor Development Group
+Mhd Sulhan <m.shulhan@gmail.com>
Micah Stetson <micah.stetson@gmail.com>
Michael Chaten <mchaten@gmail.com>
Michael Elkins <michael.elkins@gmail.com>
Mikio Hara <mikioh.mikioh@gmail.com>
Mikkel Krautz <mikkel@krautz.dk>
Miquel Sabaté Solà <mikisabate@gmail.com>
+Mohit Agarwal <mohit@sdf.org>
Moov Corporation
Moriyoshi Koizumi <mozo@mozo.jp>
Môshe van der Sterre <moshevds@gmail.com>
Nan Deng <monnand@gmail.com>
Nathan John Youngman <nj@nathany.com>
+Nathan Otterness <otternes@cs.unc.edu>
Nathan P Finch <nate.finch@gmail.com>
+Nathan VanBenschoten <nvanbenschoten@gmail.com>
Nathan Youngman <git@nathany.com>
Neelesh Chandola <neelesh.c98@gmail.com>
Nevins Bartolomeo <nevins.bartolomeo@gmail.com>
Paul A Querna <paul.querna@gmail.com>
Paul Hammond <paul@paulhammond.org>
Paul Lalonde <paul.a.lalonde@gmail.com>
+Paul Meyer <paul.meyer@microsoft.com>
Paul Rosania <paul.rosania@gmail.com>
Paul Sbarra <Sbarra.Paul@gmail.com>
Paul Smith <paulsmith@pobox.com> <paulsmith@gmail.com>
Paul van Brouwershaven <paul@vanbrouwershaven.com>
+Pavel Paulau <pavel.paulau@gmail.com>
Pavel Zinovkin <pavel.zinovkin@gmail.com>
Pawel Knap <pawelknap88@gmail.com>
Percy Wegmann <ox.to.a.cart@gmail.com>
Preetam Jinka <pj@preet.am>
Quan Yong Zhai <qyzhai@gmail.com>
Quoc-Viet Nguyen <afelion@gmail.com>
+RackTop Systems Inc.
Raif S. Naffah <go@naffah-raif.name>
Rajat Goel <rajat.goel2010@gmail.com>
+Ralph Corderoy <ralph@inputplus.co.uk>
Red Hat, Inc.
Reinaldo de Souza Jr <juniorz@gmail.com>
Rémy Oudompheng <oudomphe@phare.normalesup.org>
Richard Musiol <mail@richard-musiol.de>
Rick Arnold <rickarnoldjr@gmail.com>
Risto Jaakko Saarelma <rsaarelm@gmail.com>
+Rob Norman <rob.norman@infinitycloud.com>
Robert Daniel Kortschak <dan.kortschak@adelaide.edu.au>
Robert Dinu <r@varp.se>
Robert Figueiredo <robfig@gmail.com>
Scott Barron <scott.barron@github.com>
Scott Ferguson <scottwferg@gmail.com>
Scott Lawrence <bytbox@gmail.com>
-Sebastien Binet <seb.binet@gmail.com>
+Sebastien Binet <seb.binet@gmail.com>
Sébastien Paolacci <sebastien.paolacci@gmail.com>
Sergei Skorobogatov <skorobo@rambler.ru>
Sergey 'SnakE' Gromov <snake.scaly@gmail.com>
Sergio Luis O. B. Correia <sergio@correia.cc>
+Seth Hoenig <seth.a.hoenig@gmail.com>
Shane Hansen <shanemhansen@gmail.com>
Shaozhen Ding <dsz0111@gmail.com>
Shawn Smith <shawn.p.smith@gmail.com>
Silvan Jegen <s.jegen@gmail.com>
Simon Whitehead <chemnova@gmail.com>
Sokolov Yura <funny.falcon@gmail.com>
+Spencer Nelson <s@spenczar.com>
Spring Mc <heresy.mc@gmail.com>
Square, Inc.
StalkR <stalkr@stalkr.net>
Stephen McQuay <stephen@mcquay.me>
Stephen Weinberg <stephen@q5comm.com>
Steve McCoy <mccoyst@gmail.com>
+Steve Phillips <elimisteve@gmail.com>
Steve Streeting <steve@stevestreeting.com>
Steven Elliot Harris <seharris@gmail.com>
Steven Hartland <steven.hartland@multiplay.co.uk>
Thomas Alan Copeland <talan.copeland@gmail.com>
Thomas Desrosiers <thomasdesr@gmail.com>
Thomas Kappler <tkappler@gmail.com>
+Thorben Krueger <thorben.krueger@gmail.com>
Tim Cooijmans <timcooijmans@gmail.com>
Timo Savola <timo.savola@gmail.com>
Timo Truyts <alkaloid.btx@gmail.com>
Tom Linford <tomlinford@gmail.com>
Tommy Schaefer <tommy.schaefer@teecom.com>
Tor Andersson <tor.andersson@gmail.com>
+Tormod Erevik Lea <tormodlea@gmail.com>
Totoro W <tw19881113@gmail.com>
Travis Cline <travis.cline@gmail.com>
Trey Tacon <ttacon@gmail.com>
Xia Bin <snyh@snyh.org>
Xing Xing <mikespook@gmail.com>
Yann Kerhervé <yann.kerherve@gmail.com>
+Yao Zhang <lunaria21@gmail.com>
+Yasuharu Goto <matope.ono@gmail.com>
Yasuhiro Matsumoto <mattn.jp@gmail.com>
Yesudeep Mangalapilly <yesudeep@google.com>
Yissakhar Z. Beck <yissakhar.beck@gmail.com>
# individual or corporate CLA was used.
# Names should be added to this file like so:
-# Name <email address>
+# Individual's name <submission email address>
+# Individual's name <submission email address> <email2> <emailN>
#
-# An entry with two email addresses specifies that the
+# An entry with multiple email addresses specifies that the
# first address should be used in the submit logs and
-# that the second address should be recognized as the
-# same person when interacting with Rietveld.
+# that the other addresses should be recognized as the
+# same person when interacting with Gerrit.
# Please keep the list sorted.
Alan Donovan <adonovan@google.com>
Alan Shreve <alan@inconshreveable.com>
Albert Strasheim <fullung@gmail.com>
+Alberto Bertogli <albertito@blitiri.com.ar>
Alberto Donizetti <alb.donizetti@gmail.com>
Alberto GarcÃa Hierro <alberto@garciahierro.com> <alberto.garcia.hierro@gmail.com>
Aleksandar Dezelin <dezelin@gmail.com>
Alex Plugaru <alex@plugaru.org> <alexandru.plugaru@gmail.com>
Alex Schroeder <alex@gnu.org>
Alex Sergeyev <abc@alexsergeyev.com>
+Alexander Demakin <alexander.demakin@gmail.com>
Alexander Larsson <alexander.larsson@gmail.com>
Alexander Morozov <lk4d4math@gmail.com>
Alexander Neumann <alexander@bumpern.de>
Andy Davis <andy@bigandian.com>
Andy Maloney <asmaloney@gmail.com>
Anfernee Yongkun Gui <anfernee.gui@gmail.com>
+Angelo Bulfone <mbulfone@gmail.com>
Anh Hai Trinh <anh.hai.trinh@gmail.com>
Anmol Sethi <anmol@aubble.com>
Anschel Schaffer-Cohen <anschelsc@gmail.com>
+Anthony Canino <anthony.canino1@gmail.com>
Anthony Eufemio <anthony.eufemio@gmail.com>
Anthony Martin <ality@pbrane.org>
Anthony Starks <ajstarks@gmail.com>
Areski Belaid <areski@gmail.com>
Arnaud Ysmal <arnaud.ysmal@gmail.com>
Arne Hormann <arnehormann@gmail.com>
+Arnout Engelen <arnout@bzzt.net>
Aron Nopanen <aron.nopanen@gmail.com>
Artyom Pervukhin <artyom.pervukhin@gmail.com>
Arvindh Rajesh Tamilmani <art@a-30.net>
Case Nelson <case.nelson@gmail.com>
Casey Marshall <casey.marshall@gmail.com>
Catalin Patulea <catalinp@google.com>
+Cedric Staub <cs@squareup.com>
Cezar Sá Espinola <cezarsa@gmail.com>
ChaiShushan <chaishushan@gmail.com>
Charles L. Dorian <cldorian@gmail.com>
Cristian Staretu <unclejacksons@gmail.com>
Damian Gryski <dgryski@gmail.com>
Damien Neil <dneil@google.com>
+Dan Caddigan <goldcaddy77@gmail.com>
Dan Callahan <dan.callahan@gmail.com>
+Dan Jacques <dnj@google.com>
Dan Peterson <dpiddy@gmail.com>
Dan Pupius <dan@medium.com>
Dan Sinclair <dan.sinclair@gmail.com>
Daniel Morsing <daniel.morsing@gmail.com>
Daniel Nadasi <dnadasi@google.com>
Daniel Ortiz Pereira da Silva <daniel.particular@gmail.com>
+Daniel Skinner <daniel@dasa.cc>
Daniel Theophanes <kardianos@gmail.com>
Darren Elwood <darren@textnode.com>
Dave Borowitz <dborowitz@google.com>
David Forsythe <dforsythe@gmail.com>
David G. Andersen <dave.andersen@gmail.com>
David Glasser <glasser@meteor.com>
+David Howden <dhowden@gmail.com>
David Jakob Fritz <david.jakob.fritz@gmail.com>
David Leon Gil <coruus@gmail.com>
David McLeish <davemc@google.com>
Dmitriy Vyukov <dvyukov@google.com>
Dmitry Chestnykh <dchest@gmail.com>
Dmitry Savintsev <dsavints@gmail.com>
+Dmitry Yakunin <nonamezeil@gmail.com>
Dominik Honnef <dominik.honnef@gmail.com>
Dominik Vogt <vogt@linux.vnet.ibm.com>
Donald Huang <don.hcd@gmail.com>
Eivind Uggedal <eivind@uggedal.com>
Elias Naur <elias.naur@gmail.com>
Emil Hessman <c.emil.hessman@gmail.com> <emil@hessman.se>
+Emmanuel Odeke <emm.odeke@gmail.com> <odeke@ualberta.ca>
Eoghan Sherry <ejsherry@gmail.com>
Eric Clark <zerohp@gmail.com>
Eric Garrido <ekg@google.com>
+Eric Koleda <ekoleda+devrel@google.com>
Eric Lagergren <ericscottlagergren@gmail.com>
Eric Milliken <emilliken@gmail.com>
Eric Roshan-Eisner <eric.d.eisner@gmail.com>
Erik Aigner <aigner.erik@gmail.com>
+Erik Dubbelboer <erik@dubbelboer.com>
Erik St. Martin <alakriti@gmail.com>
Erik Westrup <erik.westrup@gmail.com>
Esko Luontola <esko.luontola@gmail.com>
+Evan Broder <evan@stripe.com>
Evan Brown <evanbrown@google.com>
Evan Kroske <evankroske@google.com>
Evan Martin <evan.martin@gmail.com>
Florian Weimer <fw@deneb.enyo.de>
Florin Patan <florinpatan@gmail.com>
Folke Behrens <folke@google.com>
+Ford Hurley <ford.hurley@gmail.com>
Francesc Campoy <campoy@golang.org>
+Francisco Claude <fclaude@recoded.cl>
Francisco Souza <franciscossouza@gmail.com>
Frederick Kelly Mayle III <frederickmayle@gmail.com>
Fredrik Enestad <fredrik.enestad@soundtrackyourbrand.com>
Gabriel Aszalos <gabriel.aszalos@gmail.com>
Garrick Evans <garrick@google.com>
Gary Burd <gary@beagledreams.com> <gary.burd@gmail.com>
+Gaurish Sharma <contact@gaurishsharma.com>
Gautham Thambidorai <gautham.dorai@gmail.com>
Geert-Johan Riemer <gjr19912@gmail.com>
Georg Reinke <guelfey@gmail.com>
Herbert Georg Fischer <herbert.fischer@gmail.com>
Hong Ruiqi <hongruiqi@gmail.com>
Hossein Sheikh Attar <hattar@google.com>
+Hsin-Ho Yeh <yhh92u@gmail.com>
Hu Keping <hukeping@huawei.com>
Hyang-Ah Hana Kim <hakim@google.com> <hyangah@gmail.com>
+Ian Gudger <ian@loosescre.ws>
Ian Lance Taylor <iant@golang.org>
Icarus Sparry <golang@icarus.freeuk.com>
Igor Dolzhikov <bluesriverz@gmail.com>
+Ilya Tocar <ilya.tocar@intel.com>
INADA Naoki <songofacandy@gmail.com>
Ingo Krabbe <ikrabbe.ask@gmail.com>
Ingo Oeser <nightlyone@googlemail.com> <nightlyone@gmail.com>
John Dethridge <jcd@golang.org>
John Graham-Cumming <jgc@jgc.org> <jgrahamc@gmail.com>
John Howard Palevich <jack.palevich@gmail.com>
+John Jenkins <twodopeshaggy@gmail.com>
John Newlin <jnewlin@google.com>
John Potocny <johnp@vividcortex.com>
John Shahid <jvshahid@gmail.com>
Ken Rockot <ken@oz.gs> <ken.rockot@gmail.com>
Ken Sedgwick <ken@bonsai.com>
Ken Thompson <ken@golang.org>
+Kenny Grant <kennygrant@gmail.com>
Kevin Ballard <kevin@sb.org>
Kevin Klues <klueska@gmail.com> <klueska@google.com>
+Kevin Malachowski <chowski@google.com>
+Kim Shrier <kshrier@racktopsystems.com>
Kirklin McDonald <kirklin.mcdonald@gmail.com>
+Klaus Post <klauspost@gmail.com>
Konstantin Shaposhnikov <k.shaposhnikov@gmail.com>
Kristopher Watts <traetox@gmail.com>
Kun Li <likunarmstrong@gmail.com>
Larry Hosken <lahosken@golang.org>
Larz Conwell <larzconwell@gmail.com>
Lee Packham <lpackham@gmail.com>
+Lewin Bormann <lewin.bormann@gmail.com>
Lloyd Dewolf <foolswisdom@gmail.com>
Lorenzo Stoakes <lstoakes@gmail.com>
Louis Kruger <louisk@google.com>
Mal Curtis <mal@mal.co.nz>
Manoj Dayaram <platform-dev@moovweb.com> <manoj.dayaram@moovweb.com>
Manu Garg <manugarg@google.com>
+Manu S Ajith <neo@codingarena.in>
Manuel Mendez <mmendez534@gmail.com>
Marc Weistroff <marc@weistroff.net>
Marcel van Lohuizen <mpvl@golang.org>
Matt Aimonetti <mattaimonetti@gmail.com>
Matt Bostock <matt@mattbostock.com>
Matt Brown <mdbrown@google.com>
+Matt Drollette <matt@drollette.com>
Matt Jibson <matt.jibson@gmail.com>
Matt Joiner <anacrolix@gmail.com>
Matt Jones <mrjones@google.com>
Maxim Pimenov <mpimenov@google.com>
Maxim Ushakov <ushakov@google.com>
Meir Fischer <meirfischer@gmail.com>
+Meng Zhuo <mengzhuo1203@gmail.com>
+Mhd Sulhan <m.shulhan@gmail.com>
Micah Stetson <micah.stetson@gmail.com>
Michael Chaten <mchaten@gmail.com>
Michael Elkins <michael.elkins@gmail.com>
Mikio Hara <mikioh.mikioh@gmail.com>
Mikkel Krautz <mikkel@krautz.dk> <krautz@gmail.com>
Miquel Sabaté Solà <mikisabate@gmail.com>
+Mohit Agarwal <mohit@sdf.org>
Moriyoshi Koizumi <mozo@mozo.jp>
Môshe van der Sterre <moshevds@gmail.com>
Mrunal Patel <mrunalp@gmail.com>
Nan Deng <monnand@gmail.com>
Nathan John Youngman <nj@nathany.com>
+Nathan Otterness <otternes@cs.unc.edu>
Nathan P Finch <nate.finch@gmail.com>
+Nathan VanBenschoten <nvanbenschoten@gmail.com>
Nathan Youngman <git@nathany.com>
Nathan(yinian) Hu <nathanhu@google.com>
Neelesh Chandola <neelesh.c98@gmail.com>
Paul Borman <borman@google.com>
Paul Chang <paulchang@google.com>
Paul Hammond <paul@paulhammond.org>
+Paul Hankin <paulhankin@google.com>
Paul Lalonde <paul.a.lalonde@gmail.com>
Paul Marks <pmarks@google.com>
+Paul Meyer <paul.meyer@microsoft.com>
Paul Nasrat <pnasrat@google.com>
Paul Rosania <paul.rosania@gmail.com>
Paul Sbarra <Sbarra.Paul@gmail.com>
Paul Smith <paulsmith@pobox.com> <paulsmith@gmail.com>
Paul van Brouwershaven <paul@vanbrouwershaven.com>
+Pavel Paulau <pavel.paulau@gmail.com>
Pavel Zinovkin <pavel.zinovkin@gmail.com>
Pawel Knap <pawelknap88@gmail.com>
Pawel Szczur <filemon@google.com>
Rahul Chaudhry <rahulchaudhry@chromium.org>
Raif S. Naffah <go@naffah-raif.name>
Rajat Goel <rajat.goel2010@gmail.com>
+Ralph Corderoy <ralph@inputplus.co.uk>
Raph Levien <raph@google.com>
Raul Silvera <rsilvera@google.com>
Reinaldo de Souza Jr <juniorz@gmail.com>
Rick Hudson <rlh@golang.org>
Risto Jaakko Saarelma <rsaarelm@gmail.com>
Rob Earhart <earhart@google.com>
+Rob Norman <rob.norman@infinitycloud.com>
Rob Pike <r@golang.org>
Robert Daniel Kortschak <dan.kortschak@adelaide.edu.au>
Robert Dinu <r@varp.se>
Sergei Skorobogatov <skorobo@rambler.ru>
Sergey 'SnakE' Gromov <snake.scaly@gmail.com>
Sergio Luis O. B. Correia <sergio@correia.cc>
+Seth Hoenig <seth.a.hoenig@gmail.com>
Shane Hansen <shanemhansen@gmail.com>
Shaozhen Ding <dsz0111@gmail.com>
Shawn Ledbetter <sledbetter@google.com>
Silvan Jegen <s.jegen@gmail.com>
Simon Whitehead <chemnova@gmail.com>
Sokolov Yura <funny.falcon@gmail.com>
+Spencer Nelson <s@spenczar.com>
Spring Mc <heresy.mc@gmail.com>
Srdjan Petrovic <spetrovic@google.com>
StalkR <stalkr@stalkr.net>
Stephen McQuay <stephen@mcquay.me>
Stephen Weinberg <stephen@q5comm.com>
Steve McCoy <mccoyst@gmail.com>
+Steve Newman <snewman@google.com>
+Steve Phillips <elimisteve@gmail.com>
Steve Streeting <steve@stevestreeting.com>
Steven Elliot Harris <seharris@gmail.com>
Steven Hartland <steven.hartland@multiplay.co.uk>
Thomas Desrosiers <thomasdesr@gmail.com>
Thomas Habets <habets@google.com>
Thomas Kappler <tkappler@gmail.com>
+Thorben Krueger <thorben.krueger@gmail.com>
Tim Cooijmans <timcooijmans@gmail.com>
Tim Hockin <thockin@google.com>
Timo Savola <timo.savola@gmail.com>
Tom Szymanski <tgs@google.com>
Tommy Schaefer <tommy.schaefer@teecom.com>
Tor Andersson <tor.andersson@gmail.com>
+Tormod Erevik Lea <tormodlea@gmail.com>
Totoro W <tw19881113@gmail.com>
Travis Cline <travis.cline@gmail.com>
Trevor Strohman <trevor.strohman@gmail.com>
Vladimir Nikishenko <vova616@gmail.com>
Volker Dobler <dr.volker.dobler@gmail.com>
Wei Guangjing <vcc.163@gmail.com>
+Will Chan <willchan@google.com>
Will Norris <willnorris@google.com>
Willem van der Schyff <willemvds@gmail.com>
William Chan <willchan@chromium.org>
Xing Xing <mikespook@gmail.com>
Yan Zou <yzou@google.com>
Yann Kerhervé <yann.kerherve@gmail.com>
+Yao Zhang <lunaria21@gmail.com>
+Yasuharu Goto <matope.ono@gmail.com>
Yasuhiro Matsumoto <mattn.jp@gmail.com>
Yesudeep Mangalapilly <yesudeep@google.com>
Yissakhar Z. Beck <yissakhar.beck@gmail.com>
Yo-An Lin <yoanlin93@gmail.com>
Yongjian Xu <i3dmaster@gmail.com>
Yoshiyuki Kanno <nekotaroh@gmail.com> <yoshiyuki.kanno@stoic.co.jp>
+Yuki Yugui Sonoda <yugui@google.com>
Yusuke Kagiwada <block.rxckin.beats@gmail.com>
Yuusei Kuwana <kuwana@kumama.org>
Yuval Pavel Zholkover <paulzhol@gmail.com>
pkg bufio, var ErrFinalToken error
pkg debug/dwarf, const ClassUnknown = 0
pkg debug/dwarf, const ClassUnknown Class
+pkg debug/elf, const R_MIPS_16 = 1
+pkg debug/elf, const R_MIPS_16 R_MIPS
+pkg debug/elf, const R_MIPS_26 = 4
+pkg debug/elf, const R_MIPS_26 R_MIPS
+pkg debug/elf, const R_MIPS_32 = 2
+pkg debug/elf, const R_MIPS_32 R_MIPS
+pkg debug/elf, const R_MIPS_64 = 18
+pkg debug/elf, const R_MIPS_64 R_MIPS
+pkg debug/elf, const R_MIPS_ADD_IMMEDIATE = 34
+pkg debug/elf, const R_MIPS_ADD_IMMEDIATE R_MIPS
+pkg debug/elf, const R_MIPS_CALL16 = 11
+pkg debug/elf, const R_MIPS_CALL16 R_MIPS
+pkg debug/elf, const R_MIPS_CALL_HI16 = 30
+pkg debug/elf, const R_MIPS_CALL_HI16 R_MIPS
+pkg debug/elf, const R_MIPS_CALL_LO16 = 31
+pkg debug/elf, const R_MIPS_CALL_LO16 R_MIPS
+pkg debug/elf, const R_MIPS_DELETE = 27
+pkg debug/elf, const R_MIPS_DELETE R_MIPS
+pkg debug/elf, const R_MIPS_GOT16 = 9
+pkg debug/elf, const R_MIPS_GOT16 R_MIPS
+pkg debug/elf, const R_MIPS_GOT_DISP = 19
+pkg debug/elf, const R_MIPS_GOT_DISP R_MIPS
+pkg debug/elf, const R_MIPS_GOT_HI16 = 22
+pkg debug/elf, const R_MIPS_GOT_HI16 R_MIPS
+pkg debug/elf, const R_MIPS_GOT_LO16 = 23
+pkg debug/elf, const R_MIPS_GOT_LO16 R_MIPS
+pkg debug/elf, const R_MIPS_GOT_OFST = 21
+pkg debug/elf, const R_MIPS_GOT_OFST R_MIPS
+pkg debug/elf, const R_MIPS_GOT_PAGE = 20
+pkg debug/elf, const R_MIPS_GOT_PAGE R_MIPS
+pkg debug/elf, const R_MIPS_GPREL16 = 7
+pkg debug/elf, const R_MIPS_GPREL16 R_MIPS
+pkg debug/elf, const R_MIPS_GPREL32 = 12
+pkg debug/elf, const R_MIPS_GPREL32 R_MIPS
+pkg debug/elf, const R_MIPS_HI16 = 5
+pkg debug/elf, const R_MIPS_HI16 R_MIPS
+pkg debug/elf, const R_MIPS_HIGHER = 28
+pkg debug/elf, const R_MIPS_HIGHER R_MIPS
+pkg debug/elf, const R_MIPS_HIGHEST = 29
+pkg debug/elf, const R_MIPS_HIGHEST R_MIPS
+pkg debug/elf, const R_MIPS_INSERT_A = 25
+pkg debug/elf, const R_MIPS_INSERT_A R_MIPS
+pkg debug/elf, const R_MIPS_INSERT_B = 26
+pkg debug/elf, const R_MIPS_INSERT_B R_MIPS
+pkg debug/elf, const R_MIPS_JALR = 37
+pkg debug/elf, const R_MIPS_JALR R_MIPS
+pkg debug/elf, const R_MIPS_LITERAL = 8
+pkg debug/elf, const R_MIPS_LITERAL R_MIPS
+pkg debug/elf, const R_MIPS_LO16 = 6
+pkg debug/elf, const R_MIPS_LO16 R_MIPS
+pkg debug/elf, const R_MIPS_NONE = 0
+pkg debug/elf, const R_MIPS_NONE R_MIPS
+pkg debug/elf, const R_MIPS_PC16 = 10
+pkg debug/elf, const R_MIPS_PC16 R_MIPS
+pkg debug/elf, const R_MIPS_PJUMP = 35
+pkg debug/elf, const R_MIPS_PJUMP R_MIPS
+pkg debug/elf, const R_MIPS_REL16 = 33
+pkg debug/elf, const R_MIPS_REL16 R_MIPS
+pkg debug/elf, const R_MIPS_REL32 = 3
+pkg debug/elf, const R_MIPS_REL32 R_MIPS
+pkg debug/elf, const R_MIPS_RELGOT = 36
+pkg debug/elf, const R_MIPS_RELGOT R_MIPS
+pkg debug/elf, const R_MIPS_SCN_DISP = 32
+pkg debug/elf, const R_MIPS_SCN_DISP R_MIPS
+pkg debug/elf, const R_MIPS_SHIFT5 = 16
+pkg debug/elf, const R_MIPS_SHIFT5 R_MIPS
+pkg debug/elf, const R_MIPS_SHIFT6 = 17
+pkg debug/elf, const R_MIPS_SHIFT6 R_MIPS
+pkg debug/elf, const R_MIPS_SUB = 24
+pkg debug/elf, const R_MIPS_SUB R_MIPS
+pkg debug/elf, const R_MIPS_TLS_DTPMOD32 = 38
+pkg debug/elf, const R_MIPS_TLS_DTPMOD32 R_MIPS
+pkg debug/elf, const R_MIPS_TLS_DTPMOD64 = 40
+pkg debug/elf, const R_MIPS_TLS_DTPMOD64 R_MIPS
+pkg debug/elf, const R_MIPS_TLS_DTPREL32 = 39
+pkg debug/elf, const R_MIPS_TLS_DTPREL32 R_MIPS
+pkg debug/elf, const R_MIPS_TLS_DTPREL64 = 41
+pkg debug/elf, const R_MIPS_TLS_DTPREL64 R_MIPS
+pkg debug/elf, const R_MIPS_TLS_DTPREL_HI16 = 44
+pkg debug/elf, const R_MIPS_TLS_DTPREL_HI16 R_MIPS
+pkg debug/elf, const R_MIPS_TLS_DTPREL_LO16 = 45
+pkg debug/elf, const R_MIPS_TLS_DTPREL_LO16 R_MIPS
+pkg debug/elf, const R_MIPS_TLS_GD = 42
+pkg debug/elf, const R_MIPS_TLS_GD R_MIPS
+pkg debug/elf, const R_MIPS_TLS_GOTTPREL = 46
+pkg debug/elf, const R_MIPS_TLS_GOTTPREL R_MIPS
+pkg debug/elf, const R_MIPS_TLS_LDM = 43
+pkg debug/elf, const R_MIPS_TLS_LDM R_MIPS
+pkg debug/elf, const R_MIPS_TLS_TPREL32 = 47
+pkg debug/elf, const R_MIPS_TLS_TPREL32 R_MIPS
+pkg debug/elf, const R_MIPS_TLS_TPREL64 = 48
+pkg debug/elf, const R_MIPS_TLS_TPREL64 R_MIPS
+pkg debug/elf, const R_MIPS_TLS_TPREL_HI16 = 49
+pkg debug/elf, const R_MIPS_TLS_TPREL_HI16 R_MIPS
+pkg debug/elf, const R_MIPS_TLS_TPREL_LO16 = 50
+pkg debug/elf, const R_MIPS_TLS_TPREL_LO16 R_MIPS
+pkg debug/elf, method (R_MIPS) GoString() string
+pkg debug/elf, method (R_MIPS) String() string
+pkg debug/elf, type R_MIPS int
pkg html/template, func IsTrue(interface{}) (bool, bool)
pkg image, func NewNYCbCrA(Rectangle, YCbCrSubsampleRatio) *NYCbCrA
pkg image, method (*NYCbCrA) AOffset(int, int) int
pkg net/http, const StatusRequestHeaderFieldsTooLarge ideal-int
pkg net/http, const StatusTooManyRequests = 429
pkg net/http, const StatusTooManyRequests ideal-int
+pkg net/http, type Transport struct, ExpectContinueTimeout time.Duration
+pkg net/http, type Transport struct, TLSNextProto map[string]func(string, *tls.Conn) RoundTripper
+pkg net/http, var ErrSkipAltProtocol error
pkg net/http/httptest, method (*ResponseRecorder) WriteString(string) (int, error)
+pkg net/http/httputil, type BufferPool interface { Get, Put }
+pkg net/http/httputil, type BufferPool interface, Get() []uint8
+pkg net/http/httputil, type BufferPool interface, Put([]uint8)
+pkg net/http/httputil, type ReverseProxy struct, BufferPool BufferPool
pkg net/url, method (*Error) Temporary() bool
pkg net/url, method (*Error) Timeout() bool
+pkg os/exec, type ExitError struct, Stderr []uint8
pkg strconv, func AppendQuoteRuneToGraphic([]uint8, int32) []uint8
pkg strconv, func AppendQuoteToGraphic([]uint8, string) []uint8
pkg strconv, func IsGraphic(int32) bool
Tools:
+cmd/dist: use clang on FreeBSD (https://golang.org/cl/16635)
cmd/go: vendoring enabled by default (https://golang.org/cl/13967/)
cmd/go: flags for tests must precede package name if present; also makes it easier to pass flags to test binaries (https://golang.org/cl/14826)
+cmd/go: add -msan option (https://golang.org/cl/16169)
+cmd/go: use shallow clones for new git checkouts (https://golang.org/cl/16360)
+cmd/compile: add -msan option (https://golang.org/cl/16160)
+cmd/link: add -msan option (https://golang.org/cl/16161)
Ports:
+Add new experimental ports for linux/mips64 and linux/mips64le: no cgo, external linking or disasm yet (https://golang.org/cl/14460 and others)
NaCl is no longer restricted to pepper_41 (https://golang.org/cl/13958/)
+Reflect change:
+cmd/compile/internal/gc: make embedded unexported structs RO (https://golang.org/cl/14085)
+encoding/json: check for exported fields in embedded structs (https://golang.org/cl/14011)
+encoding/xml: check for exported fields in embedded structs (https://golang.org/cl/14012)
+reflect: adjust access to unexported embedded structs (https://golang.org/cl/14010)
+
API additions and behavior changes:
bufio: add Scanner.Buffer (https://golang.org/cl/14599/)
bufio: add ErrFinalToken as a sentinel value for Scan's split functions (https://golang.org/cl/14924)
+crypto/aes: dedicated asm version of AES-GCM (https://golang.org/cl/10484)
fmt: allow any integer type as an argument to the * operator (https://golang.org/cl/14491/)
+image: add NYCbCrA types (https://golang.org/cl/15671)
math/rand: add Read (https://golang.org/cl/14522)
+net/http: HTTP/2.0 support (many CLs)
net/url: make *url.Error implement net.Error (https://golang.org/cl/15672)
+runtime: only one goroutine in traceback (https://golang.org/cl/16512) maybe
strconv: QuoteToGraphic (https://golang.org/cl/14184/)
text/template: ExecError (https://golang.org/cl/13957/)
text/template: trimming spaces (https://golang.org/cl/14391/)
<!--{
"Title": "The Go Programming Language Specification",
- "Subtitle": "Version of September 24, 2015",
+ "Subtitle": "Version of October 20, 2015",
"Path": "/ref/spec"
}-->
</p>
<p>
-Numeric constants represent values of arbitrary precision and do not overflow.
+Numeric constants represent exact values of arbitrary precision and do not overflow.
+Consequently, there are no constants denoting the IEEE-754 negative zero, infinity,
+and not-a-number values.
</p>
<p>
complex, or string constant.
</p>
-<p>
-There are no constants denoting the IEEE-754 infinity and not-a-number values,
-but the <a href="/pkg/math/"><code>math</code> package</a>'s
-<a href="/pkg/math/#Inf">Inf</a>,
-<a href="/pkg/math/#NaN">NaN</a>,
-<a href="/pkg/math/#IsInf">IsInf</a>, and
-<a href="/pkg/math/#IsNaN">IsNaN</a>
-functions return and test for those values at run time.
-</p>
-
<p>
Implementation restriction: Although numeric constants have arbitrary
precision in the language, a compiler may implement them using an
</p>
<pre>
-const c = 3 < 4 // c is the untyped bool constant true
+const c = 3 < 4 // c is the untyped boolean constant true
type MyBool bool
var x, y int
var (
- // The result of a comparison is an untyped bool.
+ // The result of a comparison is an untyped boolean.
// The usual assignment rules apply.
b3 = x == y // b3 has type bool
b4 bool = x == y // b4 has type bool
<code>T</code> is a floating-point type,
and <code>x</code> is representable by a value
of type <code>T</code> after rounding using
- IEEE 754 round-to-even rules.
+ IEEE 754 round-to-even rules, but with an IEEE <code>-0.0</code>
+ further rounded to an unsigned <code>0.0</code>.
The constant <code>T(x)</code> is the rounded value.
</li>
<li>
float32(2.718281828) // 2.718281828 of type float32
complex128(1) // 1.0 + 0.0i of type complex128
float32(0.49999999) // 0.5 of type float32
+float64(-1e-1000) // 0.0 of type float64
string('x') // "x" of type string
string(0x266c) // "♬" of type string
MyString("foo" + "bar") // "foobar" of type MyString
<dd>
Supports Linux binaries. New in 1.5 and not as well excercised as other ports.
</dd>
+<dt>
+ <code>mips64, mips64le</code> (64-bit MIPS big- and little-endian)
+</dt>
+<dd>
+ Supports Linux binaries. New in 1.6 and not as well excercised as other ports.
+</dd>
</dl>
<p>
<p>
If you want to install Go 1.5 on a system that is not supported by Go 1.4 (such
-as <code>linux/ppc64</code>) you can either use
+as <code>linux/ppc64</code> and <code>linux/mips64le</code>) you can either use
<a href="/src/bootstrap.bash">bootstrap.bash</a> on a system that can bootstrap Go
1.5 normally, or bootstrap with gccgo 5.
</p>
Choices for <code>$GOARCH</code> are
<code>amd64</code> (64-bit x86, the most mature port),
<code>386</code> (32-bit x86), <code>arm</code> (32-bit ARM), <code>arm64</code> (64-bit ARM),
-<code>ppc64le</code> (PowerPC 64-bit, little-endian), and <code>ppc64</code> (PowerPC 64-bit, big-endian).
+<code>ppc64le</code> (PowerPC 64-bit, little-endian), <code>ppc64</code> (PowerPC 64-bit, big-endian),
+<code>mips64le</code> (MIPS 64-bit, little-endian), and <code>mips64</code> (MIPS 64-bit, big-endian).
The valid combinations of <code>$GOOS</code> and <code>$GOARCH</code> are:
<table cellpadding="0">
<tr>
<td></td><td><code>linux</code></td> <td><code>ppc64le</code></td>
</tr>
<tr>
+<td></td><td><code>linux</code></td> <td><code>mips64</code></td>
+</tr>
+<tr>
+<td></td><td><code>linux</code></td> <td><code>mips64le</code></td>
+</tr>
+<tr>
<td></td><td><code>netbsd</code></td> <td><code>386</code></td>
</tr>
<tr>
--- /dev/null
+// Copyright 2015 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.
+
+// Tests that cgo detects invalid pointer passing at runtime.
+
+package main
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "runtime"
+ "strings"
+ "sync"
+)
+
+// ptrTest is the tests without the boilerplate.
+type ptrTest struct {
+ name string // for reporting
+ c string // the cgo comment
+ imports []string // a list of imports
+ support string // supporting functions
+ body string // the body of the main function
+ fail bool // whether the test should fail
+ expensive bool // whether the test requires the expensive check
+}
+
+var ptrTests = []ptrTest{
+ {
+ // Passing a pointer to a struct that contains a Go pointer.
+ name: "ptr1",
+ c: `typedef struct s { int *p; } s; void f(s *ps) {}`,
+ body: `C.f(&C.s{new(C.int)})`,
+ fail: true,
+ },
+ {
+ // Passing a pointer to a struct that contains a Go pointer.
+ name: "ptr2",
+ c: `typedef struct s { int *p; } s; void f(s *ps) {}`,
+ body: `p := &C.s{new(C.int)}; C.f(p)`,
+ fail: true,
+ },
+ {
+ // Passing a pointer to an int field of a Go struct
+ // that (irrelevantly) contains a Go pointer.
+ name: "ok1",
+ c: `struct s { int i; int *p; }; void f(int *p) {}`,
+ body: `p := &C.struct_s{i: 0, p: new(C.int)}; C.f(&p.i)`,
+ fail: false,
+ },
+ {
+ // Passing a pointer to a pointer field of a Go struct.
+ name: "ptr-field",
+ c: `struct s { int i; int *p; }; void f(int **p) {}`,
+ body: `p := &C.struct_s{i: 0, p: new(C.int)}; C.f(&p.p)`,
+ fail: true,
+ },
+ {
+ // Passing a pointer to a pointer field of a Go
+ // struct, where the field does not contain a Go
+ // pointer, but another field (irrelevantly) does.
+ name: "ptr-field-ok",
+ c: `struct s { int *p1; int *p2; }; void f(int **p) {}`,
+ body: `p := &C.struct_s{p1: nil, p2: new(C.int)}; C.f(&p.p1)`,
+ fail: false,
+ },
+ {
+ // Passing the address of a slice with no Go pointers.
+ name: "slice-ok-1",
+ c: `void f(void **p) {}`,
+ imports: []string{"unsafe"},
+ body: `s := []unsafe.Pointer{nil}; C.f(&s[0])`,
+ fail: false,
+ },
+ {
+ // Passing the address of a slice with a Go pointer.
+ name: "slice-ptr-1",
+ c: `void f(void **p) {}`,
+ imports: []string{"unsafe"},
+ body: `i := 0; s := []unsafe.Pointer{unsafe.Pointer(&i)}; C.f(&s[0])`,
+ fail: true,
+ },
+ {
+ // Passing the address of a slice with a Go pointer,
+ // where we are passing the address of an element that
+ // is not a Go pointer.
+ name: "slice-ptr-2",
+ c: `void f(void **p) {}`,
+ imports: []string{"unsafe"},
+ body: `i := 0; s := []unsafe.Pointer{nil, unsafe.Pointer(&i)}; C.f(&s[0])`,
+ fail: true,
+ },
+ {
+ // Passing the address of a slice that is an element
+ // in a struct only looks at the slice.
+ name: "slice-ok-2",
+ c: `void f(void **p) {}`,
+ imports: []string{"unsafe"},
+ support: `type S struct { p *int; s []unsafe.Pointer }`,
+ body: `i := 0; p := &S{p:&i, s:[]unsafe.Pointer{nil}}; C.f(&p.s[0])`,
+ fail: false,
+ },
+ {
+ // Passing the address of a static variable with no
+ // pointers doesn't matter.
+ name: "varok",
+ c: `void f(char** parg) {}`,
+ support: `var hello = [...]C.char{'h', 'e', 'l', 'l', 'o'}`,
+ body: `parg := [1]*C.char{&hello[0]}; C.f(&parg[0])`,
+ fail: false,
+ },
+ {
+ // Passing the address of a static variable with
+ // pointers does matter.
+ name: "var",
+ c: `void f(char*** parg) {}`,
+ support: `var hello = [...]*C.char{new(C.char)}`,
+ body: `parg := [1]**C.char{&hello[0]}; C.f(&parg[0])`,
+ fail: true,
+ },
+ /*
+ TODO(khr): reenable when write barriers are fixed.
+ {
+ // Storing a Go pointer into C memory should fail.
+ name: "barrier",
+ c: `#include <stdlib.h>
+ char **f1() { return malloc(sizeof(char*)); }
+ void f2(char **p) {}`,
+ body: `p := C.f1(); *p = new(C.char); C.f2(p)`,
+ fail: true,
+ expensive: true,
+ },
+ {
+ // Storing a Go pointer into C memory by assigning a
+ // large value should fail.
+ name: "barrier-struct",
+ c: `#include <stdlib.h>
+ struct s { char *a[10]; };
+ struct s *f1() { return malloc(sizeof(struct s)); }
+ void f2(struct s *p) {}`,
+ body: `p := C.f1(); p.a = [10]*C.char{new(C.char)}; C.f2(p)`,
+ fail: true,
+ expensive: true,
+ },
+ {
+ // Storing a Go pointer into C memory using a slice
+ // copy should fail.
+ name: "barrier-slice",
+ c: `#include <stdlib.h>
+ struct s { char *a[10]; };
+ struct s *f1() { return malloc(sizeof(struct s)); }
+ void f2(struct s *p) {}`,
+ body: `p := C.f1(); copy(p.a[:], []*C.char{new(C.char)}); C.f2(p)`,
+ fail: true,
+ expensive: true,
+ },
+ {
+ // A very large value uses a GC program, which is a
+ // different code path.
+ name: "barrier-gcprog-array",
+ c: `#include <stdlib.h>
+ struct s { char *a[32769]; };
+ struct s *f1() { return malloc(sizeof(struct s)); }
+ void f2(struct s *p) {}`,
+ body: `p := C.f1(); p.a = [32769]*C.char{new(C.char)}; C.f2(p)`,
+ fail: true,
+ expensive: true,
+ },
+ {
+ // Similar case, with a source on the heap.
+ name: "barrier-gcprog-array-heap",
+ c: `#include <stdlib.h>
+ struct s { char *a[32769]; };
+ struct s *f1() { return malloc(sizeof(struct s)); }
+ void f2(struct s *p) {}
+ void f3(void *p) {}`,
+ imports: []string{"unsafe"},
+ body: `p := C.f1(); n := &[32769]*C.char{new(C.char)}; p.a = *n; C.f2(p); n[0] = nil; C.f3(unsafe.Pointer(n))`,
+ fail: true,
+ expensive: true,
+ },
+ {
+ // A GC program with a struct.
+ name: "barrier-gcprog-struct",
+ c: `#include <stdlib.h>
+ struct s { char *a[32769]; };
+ struct s2 { struct s f; };
+ struct s2 *f1() { return malloc(sizeof(struct s2)); }
+ void f2(struct s2 *p) {}`,
+ body: `p := C.f1(); p.f = C.struct_s{[32769]*C.char{new(C.char)}}; C.f2(p)`,
+ fail: true,
+ expensive: true,
+ },
+ {
+ // Similar case, with a source on the heap.
+ name: "barrier-gcprog-struct-heap",
+ c: `#include <stdlib.h>
+ struct s { char *a[32769]; };
+ struct s2 { struct s f; };
+ struct s2 *f1() { return malloc(sizeof(struct s2)); }
+ void f2(struct s2 *p) {}
+ void f3(void *p) {}`,
+ imports: []string{"unsafe"},
+ body: `p := C.f1(); n := &C.struct_s{[32769]*C.char{new(C.char)}}; p.f = *n; C.f2(p); n.a[0] = nil; C.f3(unsafe.Pointer(n))`,
+ fail: true,
+ expensive: true,
+ },
+ */
+}
+
+func main() {
+ os.Exit(doTests())
+}
+
+func doTests() int {
+ dir, err := ioutil.TempDir("", "cgoerrors")
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ return 2
+ }
+ defer os.RemoveAll(dir)
+
+ workers := runtime.NumCPU() + 1
+
+ var wg sync.WaitGroup
+ c := make(chan int)
+ errs := make(chan int)
+ for i := 0; i < workers; i++ {
+ wg.Add(1)
+ go func() {
+ worker(dir, c, errs)
+ wg.Done()
+ }()
+ }
+
+ for i := range ptrTests {
+ c <- i
+ }
+ close(c)
+
+ go func() {
+ wg.Wait()
+ close(errs)
+ }()
+
+ tot := 0
+ for e := range errs {
+ tot += e
+ }
+ return tot
+}
+
+func worker(dir string, c, errs chan int) {
+ e := 0
+ for i := range c {
+ if !doOne(dir, i) {
+ e++
+ }
+ }
+ if e > 0 {
+ errs <- e
+ }
+}
+
+func doOne(dir string, i int) bool {
+ t := &ptrTests[i]
+
+ name := filepath.Join(dir, fmt.Sprintf("t%d.go", i))
+ f, err := os.Create(name)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ return false
+ }
+
+ b := bufio.NewWriter(f)
+ fmt.Fprintln(b, `package main`)
+ fmt.Fprintln(b)
+ fmt.Fprintln(b, `/*`)
+ fmt.Fprintln(b, t.c)
+ fmt.Fprintln(b, `*/`)
+ fmt.Fprintln(b, `import "C"`)
+ fmt.Fprintln(b)
+ for _, imp := range t.imports {
+ fmt.Fprintln(b, `import "`+imp+`"`)
+ }
+ if len(t.imports) > 0 {
+ fmt.Fprintln(b)
+ }
+ if len(t.support) > 0 {
+ fmt.Fprintln(b, t.support)
+ fmt.Fprintln(b)
+ }
+ fmt.Fprintln(b, `func main() {`)
+ fmt.Fprintln(b, t.body)
+ fmt.Fprintln(b, `}`)
+
+ if err := b.Flush(); err != nil {
+ fmt.Fprintf(os.Stderr, "flushing %s: %v\n", name, err)
+ return false
+ }
+ if err := f.Close(); err != nil {
+ fmt.Fprintln(os.Stderr, "closing %s: %v\n", name, err)
+ return false
+ }
+
+ ok := true
+
+ cmd := exec.Command("go", "run", name)
+ cmd.Dir = dir
+
+ if t.expensive {
+ cmd.Env = cgocheckEnv("1")
+ buf, err := cmd.CombinedOutput()
+ if err != nil {
+ var errbuf bytes.Buffer
+ if t.fail {
+ fmt.Fprintf(&errbuf, "test %s marked expensive but failed when not expensive: %v\n", t.name, err)
+ } else {
+ fmt.Fprintf(&errbuf, "test %s failed unexpectedly with GODEBUG=cgocheck=1: %v\n", t.name, err)
+ }
+ reportTestOutput(&errbuf, t.name, buf)
+ os.Stderr.Write(errbuf.Bytes())
+ ok = false
+ }
+
+ cmd = exec.Command("go", "run", name)
+ cmd.Dir = dir
+ }
+
+ if t.expensive {
+ cmd.Env = cgocheckEnv("2")
+ }
+
+ buf, err := cmd.CombinedOutput()
+
+ if t.fail {
+ if err == nil {
+ var errbuf bytes.Buffer
+ fmt.Fprintf(&errbuf, "test %s did not fail as expected\n", t.name)
+ reportTestOutput(&errbuf, t.name, buf)
+ os.Stderr.Write(errbuf.Bytes())
+ ok = false
+ } else if !bytes.Contains(buf, []byte("Go pointer")) {
+ var errbuf bytes.Buffer
+ fmt.Fprintf(&errbuf, "test %s output does not contain expected error (failed with %v)\n", t.name, err)
+ reportTestOutput(&errbuf, t.name, buf)
+ os.Stderr.Write(errbuf.Bytes())
+ ok = false
+ }
+ } else {
+ if err != nil {
+ var errbuf bytes.Buffer
+ fmt.Fprintf(&errbuf, "test %s failed unexpectedly: %v\n", t.name, err)
+ reportTestOutput(&errbuf, t.name, buf)
+ os.Stderr.Write(errbuf.Bytes())
+ ok = false
+ }
+
+ if !t.expensive && ok {
+ // Make sure it passes with the expensive checks.
+ cmd := exec.Command("go", "run", name)
+ cmd.Dir = dir
+ cmd.Env = cgocheckEnv("2")
+ buf, err := cmd.CombinedOutput()
+ if err != nil {
+ var errbuf bytes.Buffer
+ fmt.Fprintf(&errbuf, "test %s failed unexpectedly with expensive checks: %v\n", t.name, err)
+ reportTestOutput(&errbuf, t.name, buf)
+ os.Stderr.Write(errbuf.Bytes())
+ ok = false
+ }
+ }
+ }
+
+ if t.fail && ok {
+ cmd = exec.Command("go", "run", name)
+ cmd.Dir = dir
+ cmd.Env = cgocheckEnv("0")
+ buf, err := cmd.CombinedOutput()
+ if err != nil {
+ var errbuf bytes.Buffer
+ fmt.Fprintf(&errbuf, "test %s failed unexpectedly with GODEBUG=cgocheck=0: %v\n", t.name, err)
+ reportTestOutput(&errbuf, t.name, buf)
+ os.Stderr.Write(errbuf.Bytes())
+ ok = false
+ }
+ }
+
+ return ok
+}
+
+func reportTestOutput(w io.Writer, name string, buf []byte) {
+ fmt.Fprintf(w, "=== test %s output ===\n", name)
+ fmt.Fprintf(w, "%s", buf)
+ fmt.Fprintf(w, "=== end of test %s output ===\n", name)
+}
+
+func cgocheckEnv(val string) []string {
+ env := []string{"GODEBUG=cgocheck=" + val}
+ for _, e := range os.Environ() {
+ if !strings.HasPrefix(e, "GODEBUG=") {
+ env = append(env, e)
+ }
+ }
+ return env
+}
check issue11097a.go
check issue11097b.go
+if ! go run ptr.go; then
+ exit 1
+fi
+
rm -rf errs _obj
exit 0
"path"
"runtime"
"strings"
+ "sync"
"testing"
"unsafe"
)
+// Pass a func value from nestedCall to goCallback using an integer token.
+var callbackMutex sync.Mutex
+var callbackToken int
+var callbackFuncs = make(map[int]func())
+
// nestedCall calls into C, back into Go, and finally to f.
func nestedCall(f func()) {
- // NOTE: Depends on representation of f.
// callback(x) calls goCallback(x)
- C.callback(*(*unsafe.Pointer)(unsafe.Pointer(&f)))
+ callbackMutex.Lock()
+ callbackToken++
+ i := callbackToken
+ callbackFuncs[i] = f
+ callbackMutex.Unlock()
+
+ // Pass the address of i because the C function was written to
+ // take a pointer. We could pass an int if we felt like
+ // rewriting the C code.
+ C.callback(unsafe.Pointer(&i))
+
+ callbackMutex.Lock()
+ delete(callbackFuncs, i)
+ callbackMutex.Unlock()
}
//export goCallback
func goCallback(p unsafe.Pointer) {
- (*(*func())(unsafe.Pointer(&p)))()
+ i := *(*int)(p)
+
+ callbackMutex.Lock()
+ f := callbackFuncs[i]
+ callbackMutex.Unlock()
+
+ if f == nil {
+ panic("missing callback function")
+ }
+ f()
}
func testCallback(t *testing.T) {
func TestReturnAfterGrow(t *testing.T) { testReturnAfterGrow(t) }
func TestReturnAfterGrowFromGo(t *testing.T) { testReturnAfterGrowFromGo(t) }
func Test9026(t *testing.T) { test9026(t) }
+func Test9510(t *testing.T) { test9510(t) }
func Test9557(t *testing.T) { test9557(t) }
func Test10303(t *testing.T) { test10303(t, 10) }
func Test11925(t *testing.T) { test11925(t) }
func Test12030(t *testing.T) { test12030(t) }
+func TestGCC68255(t *testing.T) { testGCC68255(t) }
func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
--- /dev/null
+// Copyright 2015 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 cgotest
+
+import (
+ "testing"
+
+ "./gcc68255"
+)
+
+func testGCC68255(t *testing.T) {
+ if !gcc68255.F() {
+ t.Error("C global variable was not initialized")
+ }
+}
--- /dev/null
+// Copyright 2015 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.
+
+// Test that it's OK to have C code that does nothing other than
+// initialize a global variable. This used to fail with gccgo.
+
+package gcc68255
+
+/*
+#include "c.h"
+*/
+import "C"
+
+func F() bool {
+ return C.v != nil
+}
--- /dev/null
+// Copyright 2015 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.
+
+static void f(void) {
+}
+
+void (*v)(void) = f;
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "abs_amd64.s"
+extern void (*v)(void);
package cgotest
+import "runtime"
+
/*
typedef int *intptr;
)
func test10303(t *testing.T, n int) {
+ if runtime.Compiler == "gccgo" {
+ t.Skip("gccgo permits C pointers on the stack")
+ }
+
// Run at a few different stack depths just to avoid an unlucky pass
// due to variables ending up on different pages.
if n > 0 {
--- /dev/null
+// Copyright 2015 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.
+
+// Test that we can link together two different cgo packages that both
+// use the same libgcc function.
+
+package cgotest
+
+import (
+ "runtime"
+ "testing"
+
+ "./issue9510a"
+ "./issue9510b"
+)
+
+func test9510(t *testing.T) {
+ if runtime.GOARCH == "arm" {
+ t.Skip("skipping because libgcc may be a Thumb library")
+ }
+ issue9510a.F(1, 1)
+ issue9510b.F(1, 1)
+}
--- /dev/null
+package issue9510a
+
+/*
+static double csquare(double a, double b) {
+ __complex__ double d;
+ __real__ d = a;
+ __imag__ d = b;
+ return __real__ (d * d);
+}
+*/
+import "C"
+
+func F(a, b float64) float64 {
+ return float64(C.csquare(C.double(a), C.double(b)))
+}
--- /dev/null
+package issue9510b
+
+/*
+static double csquare(double a, double b) {
+ __complex__ double d;
+ __real__ d = a;
+ __imag__ d = b;
+ return __real__ (d * d);
+}
+*/
+import "C"
+
+func F(a, b float64) float64 {
+ return float64(C.csquare(C.double(a), C.double(b)))
+}
--- /dev/null
+// Copyright 2015 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 darwin dragonfly freebsd linux,!arm64 netbsd openbsd
+
+package main
+
+import "syscall"
+
+func dup2(oldfd, newfd int) error {
+ return syscall.Dup2(oldfd, newfd)
+}
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux,arm64
+
+package main
+
+import "syscall"
+
+func dup2(oldfd, newfd int) error {
+ return syscall.Dup3(oldfd, newfd, 0)
+}
os.Exit(2)
}
- if e := syscall.Dup2(p[0], fd); e != nil {
+ if e := dup2(p[0], fd); e != nil {
fmt.Fprintf(os.Stderr, "dup2: %v\n", e)
os.Exit(2)
}
GOPATH=$(pwd) go build -buildmode=c-shared $suffix -o libgo.$libext src/libgo/libgo.go
binpush libgo.$libext
-if [ "$goos" == "linux" ]; then
+if [ "$goos" == "linux" ] || [ "$goos" == "android" ] ; then
if readelf -d libgo.$libext | grep TEXTREL >/dev/null; then
echo "libgo.$libext has TEXTREL set"
exit 1
fi
# test2: tests libgo2 which does not export any functions.
-GOPATH=$(pwd) go build -buildmode=c-shared $suffix -o libgo2.$libext src/libgo2/libgo2.go
+GOPATH=$(pwd) go build -buildmode=c-shared $suffix -o libgo2.$libext libgo2
binpush libgo2.$libext
linkflags="-Wl,--no-as-needed"
if [ "$goos" == "darwin" ]; then
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
package main
/*
-#cgo CFLAGS: -fsanitize=memory
-#cgo LDFLAGS: -fsanitize=memory
-
#include <stdint.h>
void f(int32_t *p, int n) {
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+/*
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+void f(int32_t *p, int n) {
+ int32_t * volatile q = (int32_t *)malloc(sizeof(int32_t) * n);
+ memcpy(p, q, n * sizeof(*p));
+ free(q);
+}
+
+void g(int32_t *p, int n) {
+ if (p[4] != 1) {
+ abort();
+ }
+}
+*/
+import "C"
+
+import (
+ "unsafe"
+)
+
+func main() {
+ a := make([]int32, 10)
+ C.f((*C.int32_t)(unsafe.Pointer(&a[0])), C.int(len(a)))
+ a[4] = 1
+ C.g((*C.int32_t)(unsafe.Pointer(&a[0])), C.int(len(a)))
+}
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+/*
+extern int *GoFn(void);
+
+// Yes, you can have definitions if you use //export, as long as they are weak.
+int f(void) __attribute__ ((weak));
+
+int f() {
+ int *p = GoFn();
+ if (*p != 12345)
+ return 0;
+ return 1;
+}
+*/
+import "C"
+
+//export GoFn
+func GoFn() *C.int {
+ i := C.int(12345)
+ return &i
+}
+
+func main() {
+ if r := C.f(); r != 1 {
+ panic(r)
+ }
+}
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+// The memory profiler can call copy from a slice on the system stack,
+// which msan used to think meant a reference to uninitialized memory.
+
+/*
+#include <time.h>
+#include <unistd.h>
+
+extern void Nop(char*);
+
+// Use weak as a hack to permit defining a function even though we use export.
+void poison() __attribute__ ((weak));
+
+// Poison the stack.
+void poison() {
+ char a[1024];
+ Nop(&a[0]);
+}
+
+*/
+import "C"
+
+import (
+ "runtime"
+)
+
+func main() {
+ runtime.MemProfileRate = 1
+ start(100)
+}
+
+func start(i int) {
+ if i == 0 {
+ return
+ }
+ C.poison()
+ // Tie up a thread.
+ // We won't actually wait for this sleep to complete.
+ go func() { C.sleep(1) }()
+ start(i - 1)
+}
+
+//export Nop
+func Nop(*C.char) {
+}
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+/*
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+void f(int32_t *p, int n) {
+ int32_t * volatile q = (int32_t *)malloc(sizeof(int32_t) * n);
+ memcpy(p, q, n * sizeof(*p));
+ free(q);
+}
+
+void g(int32_t *p, int n) {
+ if (p[4] != 1) {
+ // We shouldn't get here; msan should stop us first.
+ exit(0);
+ }
+}
+*/
+import "C"
+
+import (
+ "unsafe"
+)
+
+func main() {
+ a := make([]int32, 10)
+ C.f((*C.int32_t)(unsafe.Pointer(&a[0])), C.int(len(a)))
+ a[3] = 1
+ C.g((*C.int32_t)(unsafe.Pointer(&a[0])), C.int(len(a)))
+}
# The sanitizers were originally developed with clang, so prefer it.
CC=cc
-if test "$(type -p clang)" != ""; then
+if test -x "$(type -p clang)"; then
CC=clang
fi
export CC
-if $CC -fsanitize=memory 2>&1 | grep "unrecognized" >& /dev/null; then
+TMPDIR=${TMPDIR:-/tmp}
+echo > ${TMPDIR}/testsanitizers$$.c
+if $CC -fsanitize=memory -c ${TMPDIR}/testsanitizers$$.c -o ${TMPDIR}/testsanitizers$$.o 2>&1 | grep "unrecognized" >& /dev/null; then
echo "skipping msan test: -fsanitize=memory not supported"
+ rm -f ${TMPDIR}/testsanitizers$$.*
exit 0
fi
+rm -f ${TMPDIR}/testsanitizers$$.*
# The memory sanitizer in versions of clang before 3.6 don't work with Go.
if $CC --version | grep clang >& /dev/null; then
fi
fi
-go run msan.go
+status=0
+
+if ! go build -msan std; then
+ echo "FAIL: build -msan std"
+ status=1
+fi
+
+if ! go run -msan msan.go; then
+ echo "FAIL: msan"
+ status=1
+fi
+
+if ! go run -msan msan2.go; then
+ echo "FAIL: msan2"
+ status=1
+fi
+
+if ! go run -msan msan3.go; then
+ echo "FAIL: msan3"
+ status=1
+fi
+
+if ! go run -msan msan4.go; then
+ echo "FAIL: msan4"
+ status=1
+fi
+
+if go run -msan msan_fail.go 2>/dev/null; then
+ echo "FAIL: msan_fail"
+ status=1
+fi
+
+exit $status
"os/exec"
"path/filepath"
"regexp"
+ "runtime"
"strings"
"testing"
"time"
}
// The install command should have created a "shlibname" file for the
-// listed packages (and runtime/cgo) indicating the name of the shared
-// library containing it.
+// listed packages (and runtime/cgo, and math on arm) indicating the
+// name of the shared library containing it.
func TestShlibnameFiles(t *testing.T) {
pkgs := append([]string{}, minpkgs...)
pkgs = append(pkgs, "runtime/cgo")
+ if runtime.GOARCH == "arm" {
+ pkgs = append(pkgs, "math")
+ }
for _, pkg := range pkgs {
shlibnamefile := filepath.Join(gorootInstallDir, pkg+".shlibname")
contentsb, err := ioutil.ReadFile(shlibnamefile)
run(t, "cgo executable", "./bin/execgo")
}
+func checkPIE(t *testing.T, name string) {
+ f, err := elf.Open(name)
+ if err != nil {
+ t.Fatal("elf.Open failed: ", err)
+ }
+ defer f.Close()
+ if f.Type != elf.ET_DYN {
+ t.Errorf("%s has type %v, want ET_DYN", name, f.Type)
+ }
+ if hasDynTag(f, elf.DT_TEXTREL) {
+ t.Errorf("%s has DT_TEXTREL set", name)
+ }
+}
+
+func TestTrivialPIE(t *testing.T) {
+ name := "trivial_pie"
+ goCmd(t, "build", "-buildmode=pie", "-o="+name, "trivial")
+ defer os.Remove(name)
+ run(t, name, "./"+name)
+ checkPIE(t, name)
+}
+
+func TestCgoPIE(t *testing.T) {
+ name := "cgo_pie"
+ goCmd(t, "build", "-buildmode=pie", "-o="+name, "execgo")
+ defer os.Remove(name)
+ run(t, name, "./"+name)
+ checkPIE(t, name)
+}
+
// Build a GOPATH package into a shared library that links against the goroot runtime
// and an executable that links against both.
func TestGopathShlib(t *testing.T) {
func getenv(envvar string) string {
s := os.Getenv(envvar)
if s == "" {
- log.Fatalf("%s not set\nrun $GOROOT/misc/ios/detect.go to attempt to autodetect", s)
+ log.Fatalf("%s not set\nrun $GOROOT/misc/ios/detect.go to attempt to autodetect", envvar)
}
return s
}
}
defer os.Chdir(oldwd)
- type waitPanic struct {
- err error
- }
defer func() {
if r := recover(); r != nil {
if w, ok := r.(waitPanic); ok {
}()
defer exec.Command("killall", "ios-deploy").Run() // cleanup
-
exec.Command("killall", "ios-deploy").Run()
var opts options
opts, args = parseArgs(args)
// ios-deploy invokes lldb to give us a shell session with the app.
- cmd = exec.Command(
+ s, err := newSession(appdir, args, opts)
+ if err != nil {
+ return err
+ }
+ defer func() {
+ b := s.out.Bytes()
+ if err == nil && !debug {
+ i := bytes.Index(b, []byte("(lldb) process continue"))
+ if i > 0 {
+ b = b[i:]
+ }
+ }
+ os.Stdout.Write(b)
+ }()
+
+ // Script LLDB. Oh dear.
+ s.do(`process handle SIGHUP --stop false --pass true --notify false`)
+ s.do(`process handle SIGPIPE --stop false --pass true --notify false`)
+ s.do(`process handle SIGUSR1 --stop false --pass true --notify false`)
+ s.do(`process handle SIGSEGV --stop false --pass true --notify false`) // does not work
+ s.do(`process handle SIGBUS --stop false --pass true --notify false`) // does not work
+
+ if opts.lldb {
+ _, err := io.Copy(s.in, os.Stdin)
+ if err != io.EOF {
+ return err
+ }
+ return nil
+ }
+
+ s.do(`breakpoint set -n getwd`) // in runtime/cgo/gcc_darwin_arm.go
+
+ s.doCmd("run", "stop reason = breakpoint", 20*time.Second)
+
+ // Move the current working directory into the faux gopath.
+ if pkgpath != "src" {
+ s.do(`breakpoint delete 1`)
+ s.do(`expr char* $mem = (char*)malloc(512)`)
+ s.do(`expr $mem = (char*)getwd($mem, 512)`)
+ s.do(`expr $mem = (char*)strcat($mem, "/` + pkgpath + `")`)
+ s.do(`call (void)chdir($mem)`)
+ }
+
+ startTestsLen := s.out.Len()
+ fmt.Fprintln(s.in, `process continue`)
+
+ passed := func(out *buf) bool {
+ // Just to make things fun, lldb sometimes translates \n into \r\n.
+ return s.out.LastIndex([]byte("\nPASS\n")) > startTestsLen ||
+ s.out.LastIndex([]byte("\nPASS\r")) > startTestsLen ||
+ s.out.LastIndex([]byte("\n(lldb) PASS\n")) > startTestsLen ||
+ s.out.LastIndex([]byte("\n(lldb) PASS\r")) > startTestsLen
+ }
+ err = s.wait("test completion", passed, opts.timeout)
+ if passed(s.out) {
+ // The returned lldb error code is usually non-zero.
+ // We check for test success by scanning for the final
+ // PASS returned by the test harness, assuming the worst
+ // in its absence.
+ return nil
+ }
+ return err
+}
+
+type lldbSession struct {
+ cmd *exec.Cmd
+ in *os.File
+ out *buf
+ timedout chan struct{}
+ exited chan error
+}
+
+func newSession(appdir string, args []string, opts options) (*lldbSession, error) {
+ lldbr, in, err := os.Pipe()
+ if err != nil {
+ return nil, err
+ }
+ s := &lldbSession{
+ in: in,
+ out: new(buf),
+ exited: make(chan error),
+ }
+
+ s.cmd = exec.Command(
// lldb tries to be clever with terminals.
// So we wrap it in script(1) and be clever
// right back at it.
"--bundle", appdir,
)
if debug {
- log.Println(strings.Join(cmd.Args, " "))
+ log.Println(strings.Join(s.cmd.Args, " "))
}
- lldbr, lldb, err := os.Pipe()
- if err != nil {
- return err
- }
- w := new(bufWriter)
+ var out io.Writer = s.out
if opts.lldb {
- mw := io.MultiWriter(w, os.Stderr)
- cmd.Stdout = mw
- cmd.Stderr = mw
- } else {
- cmd.Stdout = w
- cmd.Stderr = w // everything of interest is on stderr
+ out = io.MultiWriter(out, os.Stderr)
}
- cmd.Stdin = lldbr
+ s.cmd.Stdout = out
+ s.cmd.Stderr = out // everything of interest is on stderr
+ s.cmd.Stdin = lldbr
- if err := cmd.Start(); err != nil {
- return fmt.Errorf("ios-deploy failed to start: %v", err)
+ if err := s.cmd.Start(); err != nil {
+ return nil, fmt.Errorf("ios-deploy failed to start: %v", err)
}
// Manage the -test.timeout here, outside of the test. There is a lot
// of moving parts in an iOS test harness (notably lldb) that can
// swallow useful stdio or cause its own ruckus.
- var timedout chan struct{}
if opts.timeout > 1*time.Second {
- timedout = make(chan struct{})
+ s.timedout = make(chan struct{})
time.AfterFunc(opts.timeout-1*time.Second, func() {
- close(timedout)
+ close(s.timedout)
})
}
- exited := make(chan error)
go func() {
- exited <- cmd.Wait()
+ s.exited <- s.cmd.Wait()
}()
- waitFor := func(stage, str string, timeout time.Duration) error {
- select {
- case <-timedout:
- w.printBuf()
- if p := cmd.Process; p != nil {
- p.Kill()
- }
- return fmt.Errorf("timeout (stage %s)", stage)
- case err := <-exited:
- w.printBuf()
- return fmt.Errorf("failed (stage %s): %v", stage, err)
- case i := <-w.find(str, timeout):
- if i < 0 {
- log.Printf("timed out on stage %q, retrying", stage)
- return errRetry
- }
- w.clearTo(i + len(str))
- return nil
- }
+ cond := func(out *buf) bool {
+ i0 := s.out.LastIndex([]byte("(lldb)"))
+ i1 := s.out.LastIndex([]byte("fruitstrap"))
+ i2 := s.out.LastIndex([]byte(" connect"))
+ return i0 > 0 && i1 > 0 && i2 > 0
}
- do := func(cmd string) {
- fmt.Fprintln(lldb, cmd)
- if err := waitFor(fmt.Sprintf("prompt after %q", cmd), "(lldb)", 0); err != nil {
- panic(waitPanic{err})
- }
+ if err := s.wait("lldb start", cond, 5*time.Second); err != nil {
+ fmt.Printf("lldb start error: %v\n", err)
+ return nil, errRetry
}
+ return s, nil
+}
- // Wait for installation and connection.
- if err := waitFor("ios-deploy before run", "(lldb)", 0); err != nil {
- // Retry if we see a rare and longstanding ios-deploy bug.
- // https://github.com/phonegap/ios-deploy/issues/11
- // Assertion failed: (AMDeviceStartService(device, CFSTR("com.apple.debugserver"), &gdbfd, NULL) == 0)
- log.Printf("%v, retrying", err)
- return errRetry
- }
+func (s *lldbSession) do(cmd string) { s.doCmd(cmd, "(lldb)", 0) }
- // Script LLDB. Oh dear.
- do(`process handle SIGHUP --stop false --pass true --notify false`)
- do(`process handle SIGPIPE --stop false --pass true --notify false`)
- do(`process handle SIGUSR1 --stop false --pass true --notify false`)
- do(`process handle SIGSEGV --stop false --pass true --notify false`) // does not work
- do(`process handle SIGBUS --stop false --pass true --notify false`) // does not work
-
- if opts.lldb {
- _, err := io.Copy(lldb, os.Stdin)
- if err != io.EOF {
- return err
- }
- return nil
+func (s *lldbSession) doCmd(cmd string, waitFor string, extraTimeout time.Duration) {
+ startLen := s.out.Len()
+ fmt.Fprintln(s.in, cmd)
+ cond := func(out *buf) bool {
+ i := s.out.LastIndex([]byte(waitFor))
+ return i > startLen
}
-
- do(`breakpoint set -n getwd`) // in runtime/cgo/gcc_darwin_arm.go
-
- fmt.Fprintln(lldb, `run`)
- if err := waitFor("br getwd", "stop reason = breakpoint", 20*time.Second); err != nil {
- // At this point we see several flaky errors from the iOS
- // build infrastructure. The most common is never reaching
- // the breakpoint, which we catch with a timeout. Very
- // occasionally lldb can produce errors like:
- //
- // Breakpoint 1: no locations (pending).
- // WARNING: Unable to resolve breakpoint to any actual locations.
- //
- // As no actual test code has been executed by this point,
- // we treat all errors as recoverable.
- if err != errRetry {
- log.Printf("%v, retrying", err)
- err = errRetry
- }
- return err
- }
- if err := waitFor("br getwd prompt", "(lldb)", 0); err != nil {
- return err
+ if err := s.wait(fmt.Sprintf("running cmd %q", cmd), cond, extraTimeout); err != nil {
+ panic(waitPanic{err})
}
+}
- // Move the current working directory into the faux gopath.
- if pkgpath != "src" {
- do(`breakpoint delete 1`)
- do(`expr char* $mem = (char*)malloc(512)`)
- do(`expr $mem = (char*)getwd($mem, 512)`)
- do(`expr $mem = (char*)strcat($mem, "/` + pkgpath + `")`)
- do(`call (void)chdir($mem)`)
- }
-
- // Run the tests.
- w.trimSuffix("(lldb) ")
- fmt.Fprintln(lldb, `process continue`)
-
- // Wait for the test to complete.
- select {
- case <-timedout:
- w.printBuf()
- if p := cmd.Process; p != nil {
- p.Kill()
- }
- return errors.New("timeout running tests")
- case <-w.find("\nPASS", 0):
- passed := w.isPass()
- w.printBuf()
- if passed {
- return nil
- }
- return errors.New("test failure")
- case err := <-exited:
- // The returned lldb error code is usually non-zero.
- // We check for test success by scanning for the final
- // PASS returned by the test harness, assuming the worst
- // in its absence.
- if w.isPass() {
- err = nil
- } else if err == nil {
- err = errors.New("test failure")
+func (s *lldbSession) wait(reason string, cond func(out *buf) bool, extraTimeout time.Duration) error {
+ doTimeout := 1*time.Second + extraTimeout
+ doTimedout := time.After(doTimeout)
+ for {
+ select {
+ case <-s.timedout:
+ if p := s.cmd.Process; p != nil {
+ p.Kill()
+ }
+ return fmt.Errorf("test timeout (%s)", reason)
+ case <-doTimedout:
+ return fmt.Errorf("command timeout (%s for %v)", reason, doTimeout)
+ case err := <-s.exited:
+ return fmt.Errorf("exited (%s: %v)", reason, err)
+ default:
+ if cond(s.out) {
+ return nil
+ }
+ time.Sleep(20 * time.Millisecond)
}
- w.printBuf()
- return err
}
}
-type bufWriter struct {
- mu sync.Mutex
- buf []byte
- suffix []byte // remove from each Write
-
- findTxt []byte // search buffer on each Write
- findCh chan int // report find position
- findAfter *time.Timer
+type buf struct {
+ mu sync.Mutex
+ buf []byte
}
-func (w *bufWriter) Write(in []byte) (n int, err error) {
+func (w *buf) Write(in []byte) (n int, err error) {
w.mu.Lock()
defer w.mu.Unlock()
-
- n = len(in)
- in = bytes.TrimSuffix(in, w.suffix)
-
- if debug {
- inTxt := strings.Replace(string(in), "\n", "\\n", -1)
- findTxt := strings.Replace(string(w.findTxt), "\n", "\\n", -1)
- fmt.Printf("debug --> %s <-- debug (findTxt='%s')\n", inTxt, findTxt)
- }
-
w.buf = append(w.buf, in...)
-
- if len(w.findTxt) > 0 {
- if i := bytes.Index(w.buf, w.findTxt); i >= 0 {
- w.findCh <- i
- close(w.findCh)
- w.findTxt = nil
- w.findCh = nil
- if w.findAfter != nil {
- w.findAfter.Stop()
- w.findAfter = nil
- }
- }
- }
- return n, nil
+ return len(in), nil
}
-func (w *bufWriter) trimSuffix(p string) {
+func (w *buf) LastIndex(sep []byte) int {
w.mu.Lock()
defer w.mu.Unlock()
- w.suffix = []byte(p)
+ return bytes.LastIndex(w.buf, sep)
}
-func (w *bufWriter) printBuf() {
+func (w *buf) Bytes() []byte {
w.mu.Lock()
defer w.mu.Unlock()
- fmt.Fprintf(os.Stderr, "%s", w.buf)
- w.buf = nil
-}
-func (w *bufWriter) clearTo(i int) {
- w.mu.Lock()
- defer w.mu.Unlock()
- w.buf = w.buf[i:]
+ b := make([]byte, len(w.buf))
+ copy(b, w.buf)
+ return b
}
-// find returns a channel that will have exactly one byte index sent
-// to it when the text str appears in the buffer. If the text does not
-// appear before timeout, -1 is sent.
-//
-// A timeout of zero means no timeout.
-func (w *bufWriter) find(str string, timeout time.Duration) <-chan int {
+func (w *buf) Len() int {
w.mu.Lock()
defer w.mu.Unlock()
- if len(w.findTxt) > 0 {
- panic(fmt.Sprintf("find(%s): already trying to find %s", str, w.findTxt))
- }
- txt := []byte(str)
- ch := make(chan int, 1)
- if i := bytes.Index(w.buf, txt); i >= 0 {
- ch <- i
- close(ch)
- } else {
- w.findTxt = txt
- w.findCh = ch
- if timeout > 0 {
- w.findAfter = time.AfterFunc(timeout, func() {
- w.mu.Lock()
- defer w.mu.Unlock()
- if w.findCh == ch {
- w.findTxt = nil
- w.findCh = nil
- w.findAfter = nil
- ch <- -1
- close(ch)
- }
- })
- }
- }
- return ch
+ return len(w.buf)
}
-func (w *bufWriter) isPass() bool {
- w.mu.Lock()
- defer w.mu.Unlock()
-
- // The final stdio of lldb is non-deterministic, so we
- // scan the whole buffer.
- //
- // Just to make things fun, lldb sometimes translates \n
- // into \r\n.
- return bytes.Contains(w.buf, []byte("\nPASS\n")) || bytes.Contains(w.buf, []byte("\nPASS\r"))
+type waitPanic struct {
+ err error
}
type options struct {
--- /dev/null
+// Copyright 2015 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.
+
+// Sortac sorts the AUTHORS and CONTRIBUTORS files.
+//
+// Usage:
+//
+// sortac [file...]
+//
+// Sortac sorts the named files in place.
+// If given no arguments, it sorts standard input to standard output.
+package main
+
+import (
+ "bufio"
+ "bytes"
+ "flag"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "os"
+
+ "golang.org/x/text/collate"
+ "golang.org/x/text/language"
+)
+
+func main() {
+ log.SetFlags(0)
+ log.SetPrefix("sortac: ")
+ flag.Parse()
+
+ args := flag.Args()
+ if len(args) == 0 {
+ os.Stdout.Write(sortAC(os.Stdin))
+ } else {
+ for _, arg := range args {
+ f, err := os.Open(arg)
+ if err != nil {
+ log.Fatal(err)
+ }
+ sorted := sortAC(f)
+ f.Close()
+ if err := ioutil.WriteFile(arg, sorted, 0644); err != nil {
+ log.Fatal(err)
+ }
+ }
+ }
+}
+
+func sortAC(r io.Reader) []byte {
+ bs := bufio.NewScanner(r)
+ var header []string
+ var lines []string
+ for bs.Scan() {
+ t := bs.Text()
+ lines = append(lines, t)
+ if t == "# Please keep the list sorted." {
+ header = lines
+ lines = nil
+ continue
+ }
+ }
+ if err := bs.Err(); err != nil {
+ log.Fatal(err)
+ }
+
+ var out bytes.Buffer
+ c := collate.New(language.Und, collate.Loose)
+ c.SortStrings(lines)
+ for _, l := range header {
+ fmt.Fprintln(&out, l)
+ }
+ for _, l := range lines {
+ fmt.Fprintln(&out, l)
+ }
+ return out.Bytes()
+}
exit 1
fi
+if [ -z $GOARM ]; then
+ export GOARM=7
+fi
+if [ "$GOARM" != "7" ]; then
+ echo "android only supports GOARM=7, got GOARM=$GOARM" 1>&2
+ exit 1
+fi
+
export CGO_ENABLED=1
unset GOBIN
cp -a "${GOROOT}/src" "${FAKE_GOROOT}/"
cp -a "${GOROOT}/test" "${FAKE_GOROOT}/"
cp -a "${GOROOT}/lib" "${FAKE_GOROOT}/"
-cp -a "${GOROOT}/pkg/android_$GOARCH" "${FAKE_GOROOT}/pkg/"
+
+# For android, the go tool will install the compiled package in
+# pkg/android_${GOARCH}_shared directory by default, not in
+# the usual pkg/${GOOS}_${GOARCH}. Some tests in src/go/* assume
+# the compiled packages were installed in the usual places.
+# Instead of reflecting this exception into the go/* packages,
+# we copy the compiled packages into the usual places.
+cp -a "${GOROOT}/pkg/android_${GOARCH}_shared" "${FAKE_GOROOT}/pkg/"
+mv "${FAKE_GOROOT}/pkg/android_${GOARCH}_shared" "${FAKE_GOROOT}/pkg/android_${GOARCH}"
+
echo '# Syncing test files to android device'
adb shell mkdir -p /data/local/tmp/goroot
time adb sync data &> /dev/null
return int64(x)
}
-// skipUnread skips any unread bytes in the existing file entry, as well as any alignment padding.
-func (tr *Reader) skipUnread() {
- nr := tr.numBytes() + tr.pad // number of bytes to skip
+// skipUnread skips any unread bytes in the existing file entry, as well as any
+// alignment padding. It returns io.ErrUnexpectedEOF if any io.EOF is
+// encountered in the data portion; it is okay to hit io.EOF in the padding.
+//
+// Note that this function still works properly even when sparse files are being
+// used since numBytes returns the bytes remaining in the underlying io.Reader.
+func (tr *Reader) skipUnread() error {
+ dataSkip := tr.numBytes() // Number of data bytes to skip
+ totalSkip := dataSkip + tr.pad // Total number of bytes to skip
tr.curr, tr.pad = nil, 0
- if sr, ok := tr.r.(io.Seeker); ok {
- if _, err := sr.Seek(nr, os.SEEK_CUR); err == nil {
- return
+
+ // If possible, Seek to the last byte before the end of the data section.
+ // Do this because Seek is often lazy about reporting errors; this will mask
+ // the fact that the tar stream may be truncated. We can rely on the
+ // io.CopyN done shortly afterwards to trigger any IO errors.
+ var seekSkipped int64 // Number of bytes skipped via Seek
+ if sr, ok := tr.r.(io.Seeker); ok && dataSkip > 1 {
+ // Not all io.Seeker can actually Seek. For example, os.Stdin implements
+ // io.Seeker, but calling Seek always returns an error and performs
+ // no action. Thus, we try an innocent seek to the current position
+ // to see if Seek is really supported.
+ pos1, err := sr.Seek(0, os.SEEK_CUR)
+ if err == nil {
+ // Seek seems supported, so perform the real Seek.
+ pos2, err := sr.Seek(dataSkip-1, os.SEEK_CUR)
+ if err != nil {
+ tr.err = err
+ return tr.err
+ }
+ seekSkipped = pos2 - pos1
}
}
- _, tr.err = io.CopyN(ioutil.Discard, tr.r, nr)
+
+ var copySkipped int64 // Number of bytes skipped via CopyN
+ copySkipped, tr.err = io.CopyN(ioutil.Discard, tr.r, totalSkip-seekSkipped)
+ if tr.err == io.EOF && seekSkipped+copySkipped < dataSkip {
+ tr.err = io.ErrUnexpectedEOF
+ }
+ return tr.err
}
func (tr *Reader) verifyChecksum(header []byte) bool {
return given == unsigned || given == signed
}
+// readHeader reads the next block header and assumes that the underlying reader
+// is already aligned to a block boundary.
+//
+// The err will be set to io.EOF only when one of the following occurs:
+// * Exactly 0 bytes are read and EOF is hit.
+// * Exactly 1 block of zeros is read and EOF is hit.
+// * At least 2 blocks of zeros are read.
func (tr *Reader) readHeader() *Header {
header := tr.hdrBuff[:]
copy(header, zeroBlock)
if _, tr.err = io.ReadFull(tr.r, header); tr.err != nil {
- return nil
+ return nil // io.EOF is okay here
}
// Two blocks of zero bytes marks the end of the archive.
if bytes.Equal(header, zeroBlock[0:blockSize]) {
if _, tr.err = io.ReadFull(tr.r, header); tr.err != nil {
- return nil
+ return nil // io.EOF is okay here
}
if bytes.Equal(header, zeroBlock[0:blockSize]) {
tr.err = io.EOF
}
}
-func TestNonSeekable(t *testing.T) {
- test := gnuTarTest
- f, err := os.Open(test.file)
- if err != nil {
- t.Fatalf("Unexpected error: %v", err)
- }
- defer f.Close()
-
- type readerOnly struct {
- io.Reader
- }
- tr := NewReader(readerOnly{f})
- nread := 0
-
- for ; ; nread++ {
- _, err := tr.Next()
- if err == io.EOF {
- break
- }
- if err != nil {
- t.Fatalf("Unexpected error: %v", err)
- }
- }
-
- if nread != len(test.headers) {
- t.Errorf("Didn't process all files\nexpected: %d\nprocessed %d\n", len(test.headers), nread)
- }
-}
-
func TestParsePAXHeader(t *testing.T) {
paxTests := [][3]string{
{"a", "a=name", "10 a=name\n"}, // Test case involving multiple acceptable lengths
}
}
+
+type reader struct{ io.Reader }
+type readSeeker struct{ io.ReadSeeker }
+type readBadSeeker struct{ io.ReadSeeker }
+
+func (rbs *readBadSeeker) Seek(int64, int) (int64, error) { return 0, fmt.Errorf("illegal seek") }
+
+// TestReadTruncation test the ending condition on various truncated files and
+// that truncated files are still detected even if the underlying io.Reader
+// satisfies io.Seeker.
+func TestReadTruncation(t *testing.T) {
+ var ss []string
+ for _, p := range []string{
+ "testdata/gnu.tar",
+ "testdata/ustar-file-reg.tar",
+ "testdata/pax-path-hdr.tar",
+ "testdata/sparse-formats.tar",
+ } {
+ buf, err := ioutil.ReadFile(p)
+ if err != nil {
+ t.Fatalf("unexpected error: %v", err)
+ }
+ ss = append(ss, string(buf))
+ }
+
+ data1, data2, pax, sparse := ss[0], ss[1], ss[2], ss[3]
+ data2 += strings.Repeat("\x00", 10*512)
+ trash := strings.Repeat("garbage ", 64) // Exactly 512 bytes
+
+ var vectors = []struct {
+ input string // Input stream
+ cnt int // Expected number of headers read
+ err error // Expected error outcome
+ }{
+ {"", 0, io.EOF}, // Empty file is a "valid" tar file
+ {data1[:511], 0, io.ErrUnexpectedEOF},
+ {data1[:512], 1, io.ErrUnexpectedEOF},
+ {data1[:1024], 1, io.EOF},
+ {data1[:1536], 2, io.ErrUnexpectedEOF},
+ {data1[:2048], 2, io.EOF},
+ {data1, 2, io.EOF},
+ {data1[:2048] + data2[:1536], 3, io.EOF},
+ {data2[:511], 0, io.ErrUnexpectedEOF},
+ {data2[:512], 1, io.ErrUnexpectedEOF},
+ {data2[:1195], 1, io.ErrUnexpectedEOF},
+ {data2[:1196], 1, io.EOF}, // Exact end of data and start of padding
+ {data2[:1200], 1, io.EOF},
+ {data2[:1535], 1, io.EOF},
+ {data2[:1536], 1, io.EOF}, // Exact end of padding
+ {data2[:1536] + trash[:1], 1, io.ErrUnexpectedEOF},
+ {data2[:1536] + trash[:511], 1, io.ErrUnexpectedEOF},
+ {data2[:1536] + trash, 1, ErrHeader},
+ {data2[:2048], 1, io.EOF}, // Exactly 1 empty block
+ {data2[:2048] + trash[:1], 1, io.ErrUnexpectedEOF},
+ {data2[:2048] + trash[:511], 1, io.ErrUnexpectedEOF},
+ {data2[:2048] + trash, 1, ErrHeader},
+ {data2[:2560], 1, io.EOF}, // Exactly 2 empty blocks (normal end-of-stream)
+ {data2[:2560] + trash[:1], 1, io.EOF},
+ {data2[:2560] + trash[:511], 1, io.EOF},
+ {data2[:2560] + trash, 1, io.EOF},
+ {data2[:3072], 1, io.EOF},
+ {pax, 0, io.EOF}, // PAX header without data is a "valid" tar file
+ {pax + trash[:1], 0, io.ErrUnexpectedEOF},
+ {pax + trash[:511], 0, io.ErrUnexpectedEOF},
+ {sparse[:511], 0, io.ErrUnexpectedEOF},
+ // TODO(dsnet): This should pass, but currently fails.
+ // {sparse[:512], 0, io.ErrUnexpectedEOF},
+ {sparse[:3584], 1, io.EOF},
+ {sparse[:9200], 1, io.EOF}, // Terminate in padding of sparse header
+ {sparse[:9216], 1, io.EOF},
+ {sparse[:9728], 2, io.ErrUnexpectedEOF},
+ {sparse[:10240], 2, io.EOF},
+ {sparse[:11264], 2, io.ErrUnexpectedEOF},
+ {sparse, 5, io.EOF},
+ {sparse + trash, 5, io.EOF},
+ }
+
+ for i, v := range vectors {
+ for j := 0; j < 6; j++ {
+ var tr *Reader
+ var s1, s2 string
+
+ switch j {
+ case 0:
+ tr = NewReader(&reader{strings.NewReader(v.input)})
+ s1, s2 = "io.Reader", "auto"
+ case 1:
+ tr = NewReader(&reader{strings.NewReader(v.input)})
+ s1, s2 = "io.Reader", "manual"
+ case 2:
+ tr = NewReader(&readSeeker{strings.NewReader(v.input)})
+ s1, s2 = "io.ReadSeeker", "auto"
+ case 3:
+ tr = NewReader(&readSeeker{strings.NewReader(v.input)})
+ s1, s2 = "io.ReadSeeker", "manual"
+ case 4:
+ tr = NewReader(&readBadSeeker{strings.NewReader(v.input)})
+ s1, s2 = "ReadBadSeeker", "auto"
+ case 5:
+ tr = NewReader(&readBadSeeker{strings.NewReader(v.input)})
+ s1, s2 = "ReadBadSeeker", "manual"
+ }
+
+ var cnt int
+ var err error
+ for {
+ if _, err = tr.Next(); err != nil {
+ break
+ }
+ cnt++
+ if s2 == "manual" {
+ if _, err = io.Copy(ioutil.Discard, tr); err != nil {
+ break
+ }
+ }
+ }
+ if err != v.err {
+ t.Errorf("test %d, NewReader(%s(...)) with %s discard: got %v, want %v",
+ i, s1, s2, err, v.err)
+ }
+ if cnt != v.cnt {
+ t.Errorf("test %d, NewReader(%s(...)) with %s discard: got %d headers, want %d headers",
+ i, s1, s2, cnt, v.cnt)
+ }
+ }
+ }
+}
"errors"
"fmt"
"io"
- "os"
"path"
+ "sort"
"strconv"
"strings"
"time"
// succeed, and seems harmless enough.
ext.ModTime = hdr.ModTime
// The spec asks that we namespace our pseudo files
- // with the current pid.
- pid := os.Getpid()
+ // with the current pid. However, this results in differing outputs
+ // for identical inputs. As such, the constant 0 is now used instead.
+ // golang.org/issue/12358
dir, file := path.Split(hdr.Name)
- fullName := path.Join(dir,
- fmt.Sprintf("PaxHeaders.%d", pid), file)
+ fullName := path.Join(dir, "PaxHeaders.0", file)
ascii := toASCII(fullName)
if len(ascii) > 100 {
// Construct the body
var buf bytes.Buffer
- for k, v := range paxHeaders {
- fmt.Fprint(&buf, paxHeader(k+"="+v))
+ // Keys are sorted before writing to body to allow deterministic output.
+ var keys []string
+ for k := range paxHeaders {
+ keys = append(keys, k)
+ }
+ sort.Strings(keys)
+
+ for _, k := range keys {
+ fmt.Fprint(&buf, paxHeader(k+"="+paxHeaders[k]))
}
ext.Size = int64(len(buf.Bytes()))
"io/ioutil"
"os"
"reflect"
+ "sort"
"strings"
"testing"
"testing/iotest"
t.Fatal(err)
}
// Simple test to make sure PAX extensions are in effect
- if !bytes.Contains(buf.Bytes(), []byte("PaxHeaders.")) {
+ if !bytes.Contains(buf.Bytes(), []byte("PaxHeaders.0")) {
t.Fatal("Expected at least one PAX header to be written.")
}
// Test that we can get a long name back out of the archive.
t.Fatal(err)
}
// Simple test to make sure PAX extensions are in effect
- if !bytes.Contains(buf.Bytes(), []byte("PaxHeaders.")) {
+ if !bytes.Contains(buf.Bytes(), []byte("PaxHeaders.0")) {
t.Fatal("Expected at least one PAX header to be written.")
}
// Test that we can get a long name back out of the archive.
t.Fatal(err)
}
// Simple test to make sure PAX extensions are in effect
- if !bytes.Contains(buf.Bytes(), []byte("PaxHeaders.")) {
+ if !bytes.Contains(buf.Bytes(), []byte("PaxHeaders.0")) {
t.Fatal("Expected at least one PAX header to be written.")
}
// Test that we can get a long name back out of the archive.
}
}
+func TestPaxHeadersSorted(t *testing.T) {
+ fileinfo, err := os.Stat("testdata/small.txt")
+ if err != nil {
+ t.Fatal(err)
+ }
+ hdr, err := FileInfoHeader(fileinfo, "")
+ if err != nil {
+ t.Fatalf("os.Stat: %v", err)
+ }
+ contents := strings.Repeat(" ", int(hdr.Size))
+
+ hdr.Xattrs = map[string]string{
+ "foo": "foo",
+ "bar": "bar",
+ "baz": "baz",
+ "qux": "qux",
+ }
+
+ var buf bytes.Buffer
+ writer := NewWriter(&buf)
+ if err := writer.WriteHeader(hdr); err != nil {
+ t.Fatal(err)
+ }
+ if _, err = writer.Write([]byte(contents)); err != nil {
+ t.Fatal(err)
+ }
+ if err := writer.Close(); err != nil {
+ t.Fatal(err)
+ }
+ // Simple test to make sure PAX extensions are in effect
+ if !bytes.Contains(buf.Bytes(), []byte("PaxHeaders.0")) {
+ t.Fatal("Expected at least one PAX header to be written.")
+ }
+
+ // xattr bar should always appear before others
+ indices := []int{
+ bytes.Index(buf.Bytes(), []byte("bar=bar")),
+ bytes.Index(buf.Bytes(), []byte("baz=baz")),
+ bytes.Index(buf.Bytes(), []byte("foo=foo")),
+ bytes.Index(buf.Bytes(), []byte("qux=qux")),
+ }
+ if !sort.IntsAreSorted(indices) {
+ t.Fatal("PAX headers are not sorted")
+ }
+}
+
func TestPAXHeader(t *testing.T) {
medName := strings.Repeat("CD", 50)
longName := strings.Repeat("AB", 100)
"cmd/internal/obj"
"cmd/internal/obj/arm"
"cmd/internal/obj/arm64"
+ "cmd/internal/obj/mips"
"cmd/internal/obj/ppc64"
"cmd/internal/obj/x86"
"fmt"
return archArm()
case "arm64":
return archArm64()
+ case "mips64":
+ a := archMips64()
+ a.LinkArch = &mips.Linkmips64
+ return a
+ case "mips64le":
+ a := archMips64()
+ a.LinkArch = &mips.Linkmips64le
+ return a
case "ppc64":
a := archPPC64()
a.LinkArch = &ppc64.Linkppc64
IsJump: jumpPPC64,
}
}
+
+func archMips64() *Arch {
+ register := make(map[string]int16)
+ // Create maps for easy lookup of instruction names etc.
+ // Note that there is no list of names as there is for x86.
+ for i := mips.REG_R0; i <= mips.REG_R31; i++ {
+ register[obj.Rconv(i)] = int16(i)
+ }
+ for i := mips.REG_F0; i <= mips.REG_F31; i++ {
+ register[obj.Rconv(i)] = int16(i)
+ }
+ for i := mips.REG_M0; i <= mips.REG_M31; i++ {
+ register[obj.Rconv(i)] = int16(i)
+ }
+ for i := mips.REG_FCR0; i <= mips.REG_FCR31; i++ {
+ register[obj.Rconv(i)] = int16(i)
+ }
+ register["HI"] = mips.REG_HI
+ register["LO"] = mips.REG_LO
+ // Pseudo-registers.
+ register["SB"] = RSB
+ register["FP"] = RFP
+ register["PC"] = RPC
+ // Avoid unintentionally clobbering g using R30.
+ delete(register, "R30")
+ register["g"] = mips.REG_R30
+ registerPrefix := map[string]bool{
+ "F": true,
+ "FCR": true,
+ "M": true,
+ "R": true,
+ }
+
+ instructions := make(map[string]int)
+ for i, s := range obj.Anames {
+ instructions[s] = i
+ }
+ for i, s := range mips.Anames {
+ if i >= obj.A_ARCHSPECIFIC {
+ instructions[s] = i + obj.ABaseMIPS64
+ }
+ }
+ // Annoying alias.
+ instructions["JAL"] = mips.AJAL
+
+ return &Arch{
+ LinkArch: &mips.Linkmips64,
+ Instructions: instructions,
+ Register: register,
+ RegisterPrefix: registerPrefix,
+ RegisterNumber: mipsRegisterNumber,
+ IsJump: jumpMIPS64,
+ }
+}
--- /dev/null
+// Copyright 2015 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.
+
+// This file encapsulates some of the odd characteristics of the
+// 64-bit MIPS (MIPS64) instruction set, to minimize its interaction
+// with the core of the assembler.
+
+package arch
+
+import "cmd/internal/obj/mips"
+
+func jumpMIPS64(word string) bool {
+ switch word {
+ case "BEQ", "BFPF", "BFPT", "BGEZ", "BGEZAL", "BGTZ", "BLEZ", "BLTZ", "BLTZAL", "BNE", "JMP", "JAL", "CALL":
+ return true
+ }
+ return false
+}
+
+// IsMIPS64CMP reports whether the op (as defined by an mips.A* constant) is
+// one of the CMP instructions that require special handling.
+func IsMIPS64CMP(op int) bool {
+ switch op {
+ case mips.ACMPEQF, mips.ACMPEQD, mips.ACMPGEF, mips.ACMPGED,
+ mips.ACMPGTF, mips.ACMPGTD:
+ return true
+ }
+ return false
+}
+
+// IsMIPS64MUL reports whether the op (as defined by an mips.A* constant) is
+// one of the MUL/DIV/REM instructions that require special handling.
+func IsMIPS64MUL(op int) bool {
+ switch op {
+ case mips.AMUL, mips.AMULU, mips.AMULV, mips.AMULVU,
+ mips.ADIV, mips.ADIVU, mips.ADIVV, mips.ADIVVU,
+ mips.AREM, mips.AREMU, mips.AREMV, mips.AREMVU:
+ return true
+ }
+ return false
+}
+
+func mipsRegisterNumber(name string, n int16) (int16, bool) {
+ switch name {
+ case "F":
+ if 0 <= n && n <= 31 {
+ return mips.REG_F0 + n, true
+ }
+ case "FCR":
+ if 0 <= n && n <= 31 {
+ return mips.REG_FCR0 + n, true
+ }
+ case "M":
+ if 0 <= n && n <= 31 {
+ return mips.REG_M0 + n, true
+ }
+ case "R":
+ if 0 <= n && n <= 31 {
+ return mips.REG_R0 + n, true
+ }
+ }
+ return 0, false
+}
prog.Reg = reg
break
}
+ if p.arch.Thechar == '0' {
+ // 3-operand jumps.
+ // First two must be registers
+ target = &a[2]
+ prog.From = a[0]
+ prog.Reg = p.getRegister(prog, op, &a[1])
+ break
+ }
fallthrough
default:
p.errorf("wrong number of arguments to %s instruction", obj.Aconv(op))
prog.From = a[0]
prog.Reg = p.getRegister(prog, op, &a[1])
break
+ } else if p.arch.Thechar == '0' {
+ if arch.IsMIPS64CMP(op) || arch.IsMIPS64MUL(op) {
+ prog.From = a[0]
+ prog.Reg = p.getRegister(prog, op, &a[1])
+ break
+ }
}
prog.From = a[0]
prog.To = a[1]
case 3:
switch p.arch.Thechar {
+ case '0':
+ prog.From = a[0]
+ prog.Reg = p.getRegister(prog, op, &a[1])
+ prog.To = a[2]
case '5':
// Special cases.
if arch.IsARMSTREX(op) {
func Test386EndToEnd(t *testing.T) {
testEndToEnd(t, "386")
}
+
+func TestMIPS64EndToEnd(t *testing.T) {
+ testEndToEnd(t, "mips64")
+}
testOperandParser(t, parser, ppc64OperandTests)
}
+func TestMIPS64OperandParser(t *testing.T) {
+ parser := newParser("mips64")
+ testOperandParser(t, parser, mips64OperandTests)
+}
+
type operandTest struct {
input, output string
}
{"(R29, RSP)", "(R29, RSP)"},
{"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.
}
+
+var mips64OperandTests = []operandTest{
+ {"$((1<<63)-1)", "$9223372036854775807"},
+ {"$(-64*1024)", "$-65536"},
+ {"$(1024 * 8)", "$8192"},
+ {"$-1", "$-1"},
+ {"$-24(R4)", "$-24(R4)"},
+ {"$0", "$0"},
+ {"$0(R1)", "$(R1)"},
+ {"$0.5", "$(0.5)"},
+ {"$0x7000", "$28672"},
+ {"$0x88888eef", "$2290650863"},
+ {"$1", "$1"},
+ {"$_main<>(SB)", "$_main<>(SB)"},
+ {"$argframe(FP)", "$argframe(FP)"},
+ {"$~3", "$-4"},
+ {"(-288-3*8)(R1)", "-312(R1)"},
+ {"(16)(R7)", "16(R7)"},
+ {"(8)(g)", "8(g)"},
+ {"(R0)", "(R0)"},
+ {"(R3)", "(R3)"},
+ {"(R4)", "(R4)"},
+ {"(R5)", "(R5)"},
+ {"-1(R4)", "-1(R4)"},
+ {"-1(R5)", "-1(R5)"},
+ {"6(PC)", "6(PC)"},
+ {"F14", "F14"},
+ {"F15", "F15"},
+ {"F16", "F16"},
+ {"F17", "F17"},
+ {"F18", "F18"},
+ {"F19", "F19"},
+ {"F20", "F20"},
+ {"F21", "F21"},
+ {"F22", "F22"},
+ {"F23", "F23"},
+ {"F24", "F24"},
+ {"F25", "F25"},
+ {"F26", "F26"},
+ {"F27", "F27"},
+ {"F28", "F28"},
+ {"F29", "F29"},
+ {"F30", "F30"},
+ {"F31", "F31"},
+ {"R0", "R0"},
+ {"R1", "R1"},
+ {"R11", "R11"},
+ {"R12", "R12"},
+ {"R13", "R13"},
+ {"R14", "R14"},
+ {"R15", "R15"},
+ {"R16", "R16"},
+ {"R17", "R17"},
+ {"R18", "R18"},
+ {"R19", "R19"},
+ {"R2", "R2"},
+ {"R20", "R20"},
+ {"R21", "R21"},
+ {"R22", "R22"},
+ {"R23", "R23"},
+ {"R24", "R24"},
+ {"R25", "R25"},
+ {"R26", "R26"},
+ {"R27", "R27"},
+ {"R28", "R28"},
+ {"R29", "R29"},
+ {"R3", "R3"},
+ {"R31", "R31"},
+ {"R4", "R4"},
+ {"R5", "R5"},
+ {"R6", "R6"},
+ {"R7", "R7"},
+ {"R8", "R8"},
+ {"R9", "R9"},
+ {"LO", "LO"},
+ {"a(FP)", "a(FP)"},
+ {"g", "g"},
+ {"ret+8(FP)", "ret+8(FP)"},
+ {"runtime·abort(SB)", "runtime.abort(SB)"},
+ {"·AddUint32(SB)", "\"\".AddUint32(SB)"},
+ {"·trunc(SB)", "\"\".trunc(SB)"},
+ {"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.
+}
--- /dev/null
+8 00001 (testdata/mips64.s:8) TEXT foo(SB), 0, $0
+18 00002 (testdata/mips64.s:18) MOVW R1, R2
+19 00003 (testdata/mips64.s:19) MOVW LO, R1
+20 00004 (testdata/mips64.s:20) MOVW HI, R1
+21 00005 (testdata/mips64.s:21) MOVW R1, LO
+22 00006 (testdata/mips64.s:22) MOVW R1, HI
+23 00007 (testdata/mips64.s:23) MOVV R1, R2
+24 00008 (testdata/mips64.s:24) MOVV LO, R1
+25 00009 (testdata/mips64.s:25) MOVV HI, R1
+26 00010 (testdata/mips64.s:26) MOVV R1, LO
+27 00011 (testdata/mips64.s:27) MOVV R1, HI
+33 00012 (testdata/mips64.s:33) MOVW foo<>+3(SB), R2
+34 00013 (testdata/mips64.s:34) MOVW 16(R1), R2
+35 00014 (testdata/mips64.s:35) MOVW (R1), R2
+36 00015 (testdata/mips64.s:36) MOVV foo<>+3(SB), R2
+37 00016 (testdata/mips64.s:37) MOVV 16(R1), R2
+38 00017 (testdata/mips64.s:38) MOVV (R1), R2
+44 00018 (testdata/mips64.s:44) MOVB R1, R2
+50 00019 (testdata/mips64.s:50) MOVB foo<>+3(SB), R2
+51 00020 (testdata/mips64.s:51) MOVB 16(R1), R2
+52 00021 (testdata/mips64.s:52) MOVB (R1), R2
+61 00022 (testdata/mips64.s:61) MOVD foo<>+3(SB), F2
+62 00023 (testdata/mips64.s:62) MOVD 16(R1), F2
+63 00024 (testdata/mips64.s:63) MOVD (R1), F2
+69 00025 (testdata/mips64.s:69) MOVD $(0.10000000000000001), F2
+75 00026 (testdata/mips64.s:75) MOVD F1, F2
+81 00027 (testdata/mips64.s:81) MOVD F2, foo<>+3(SB)
+82 00028 (testdata/mips64.s:82) MOVD F2, 16(R1)
+83 00029 (testdata/mips64.s:83) MOVD F2, (R1)
+92 00030 (testdata/mips64.s:92) MOVW R1, foo<>+3(SB)
+93 00031 (testdata/mips64.s:93) MOVW R1, 16(R2)
+94 00032 (testdata/mips64.s:94) MOVW R1, (R2)
+95 00033 (testdata/mips64.s:95) MOVV R1, foo<>+3(SB)
+96 00034 (testdata/mips64.s:96) MOVV R1, 16(R2)
+97 00035 (testdata/mips64.s:97) MOVV R1, (R2)
+103 00036 (testdata/mips64.s:103) MOVB R1, foo<>+3(SB)
+104 00037 (testdata/mips64.s:104) MOVB R1, 16(R2)
+105 00038 (testdata/mips64.s:105) MOVB R1, (R2)
+114 00039 (testdata/mips64.s:114) MOVD F1, foo<>+3(SB)
+115 00040 (testdata/mips64.s:115) MOVD F1, 16(R2)
+116 00041 (testdata/mips64.s:116) MOVD F1, (R2)
+125 00042 (testdata/mips64.s:125) MOVW FCR0, R1
+131 00043 (testdata/mips64.s:131) MOVW R1, FCR0
+137 00044 (testdata/mips64.s:137) MOVW R1, M1
+138 00045 (testdata/mips64.s:138) MOVV R1, M1
+144 00046 (testdata/mips64.s:144) MOVW M1, R1
+145 00047 (testdata/mips64.s:145) MOVV M1, R1
+158 00048 (testdata/mips64.s:158) ADD R1, R2, R3
+164 00049 (testdata/mips64.s:164) ADD $1, R2, R3
+170 00050 (testdata/mips64.s:170) ADD R1, R2
+176 00051 (testdata/mips64.s:176) ADD $4, R1
+182 00052 (testdata/mips64.s:182) MUL R1, R2
+188 00053 (testdata/mips64.s:188) SLL R1, R2, R3
+194 00054 (testdata/mips64.s:194) SLL R1, R2
+200 00055 (testdata/mips64.s:200) SLL $4, R1, R2
+206 00056 (testdata/mips64.s:206) SLL $4, R1
+215 00057 (testdata/mips64.s:215) MOVW $1, R1
+216 00058 (testdata/mips64.s:216) MOVV $1, R1
+222 00059 (testdata/mips64.s:222) MOVW $1, R1
+223 00060 (testdata/mips64.s:223) MOVW $foo(SB), R1
+224 00061 (testdata/mips64.s:224) MOVV $1, R1
+225 00062 (testdata/mips64.s:225) MOVV $foo(SB), R1
+236 00063 (testdata/mips64.s:236) JMP 64(PC)
+237 00064 (testdata/mips64.s:237) JMP 63
+238 00065 (testdata/mips64.s:238) CALL 66(PC)
+239 00066 (testdata/mips64.s:239) CALL 63
+245 00067 (testdata/mips64.s:245) JMP 4(R1)
+246 00068 (testdata/mips64.s:246) JMP foo(SB)
+247 00069 (testdata/mips64.s:247) CALL 4(R1)
+248 00070 (testdata/mips64.s:248) CALL foo(SB)
+258 00071 (testdata/mips64.s:258) BEQ R1, 72(PC)
+259 00072 (testdata/mips64.s:259) BEQ R1, 71
+266 00073 (testdata/mips64.s:266) BEQ R1, R2, 74(PC)
+267 00074 (testdata/mips64.s:267) BEQ R1, R2, 73
+277 00075 (testdata/mips64.s:277) BLTZ R1, 76(PC)
+278 00076 (testdata/mips64.s:278) BLTZ R1, 75
+285 00077 (testdata/mips64.s:285) BFPT 78(PC)
+286 00078 (testdata/mips64.s:286) BFPT 77
+296 00079 (testdata/mips64.s:296) ABSD F1, F2
+302 00080 (testdata/mips64.s:302) ADDD F1, F2
+308 00081 (testdata/mips64.s:308) ADDD F1, F2, F3
+314 00082 (testdata/mips64.s:314) CMPEQD F1, F2
+320 00083 (testdata/mips64.s:320) WORD $1
+321 00084 (testdata/mips64.s:321) WORD $foo(SB)
+330 00085 (testdata/mips64.s:330) NOP
+336 00086 (testdata/mips64.s:336) NOP R2
+342 00087 (testdata/mips64.s:342) NOP F2
+348 00088 (testdata/mips64.s:348) NOP R2
+354 00089 (testdata/mips64.s:354) NOP F2
+360 00090 (testdata/mips64.s:360) NOP $4
+365 00091 (testdata/mips64.s:365) SYSCALL
+366 00092 (testdata/mips64.s:366) BREAK
+367 00093 (testdata/mips64.s:367) BREAK $1, (R1)
+376 00094 (testdata/mips64.s:376) SYSCALL
+377 00095 (testdata/mips64.s:377) RET
+382 00096 (testdata/mips64.s:382) CALL foo(SB)
+383 00097 (testdata/mips64.s:383) JMP foo(SB)
+384 00098 (testdata/mips64.s:384) CALL foo(SB)
+392 00099 (testdata/mips64.s:392) END
--- /dev/null
+// Copyright 2015 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.
+
+// This input was created by taking the ppc64 testcase and modified
+// by hand.
+
+TEXT foo(SB),0,$0
+
+//inst:
+//
+// load ints and bytes
+//
+// LMOVW rreg ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVW R1, R2
+ MOVW LO, R1
+ MOVW HI, R1
+ MOVW R1, LO
+ MOVW R1, HI
+ MOVV R1, R2
+ MOVV LO, R1
+ MOVV HI, R1
+ MOVV R1, LO
+ MOVV R1, HI
+
+// LMOVW addr ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVW foo<>+3(SB), R2
+ MOVW 16(R1), R2
+ MOVW (R1), R2
+ MOVV foo<>+3(SB), R2
+ MOVV 16(R1), R2
+ MOVV (R1), R2
+
+// LMOVB rreg ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVB R1, R2
+
+// LMOVB addr ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVB foo<>+3(SB), R2
+ MOVB 16(R1), R2
+ MOVB (R1), R2
+
+//
+// load floats
+//
+// LFMOV addr ',' freg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVD foo<>+3(SB), F2
+ MOVD 16(R1), F2
+ MOVD (R1), F2
+
+// LFMOV fimm ',' freg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVD $0.1, F2
+
+// LFMOV freg ',' freg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVD F1, F2
+
+// LFMOV freg ',' addr
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVD F2, foo<>+3(SB)
+ MOVD F2, 16(R1)
+ MOVD F2, (R1)
+
+//
+// store ints and bytes
+//
+// LMOVW rreg ',' addr
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVW R1, foo<>+3(SB)
+ MOVW R1, 16(R2)
+ MOVW R1, (R2)
+ MOVV R1, foo<>+3(SB)
+ MOVV R1, 16(R2)
+ MOVV R1, (R2)
+
+// LMOVB rreg ',' addr
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVB R1, foo<>+3(SB)
+ MOVB R1, 16(R2)
+ MOVB R1, (R2)
+
+//
+// store floats
+//
+// LMOVW freg ',' addr
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVD F1, foo<>+3(SB)
+ MOVD F1, 16(R2)
+ MOVD F1, (R2)
+
+//
+// floating point status
+//
+// LMOVW fpscr ',' freg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVW FCR0, R1
+
+// LMOVW freg ',' fpscr
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVW R1, FCR0
+
+// LMOVW rreg ',' mreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVW R1, M1
+ MOVV R1, M1
+
+// LMOVW mreg ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVW M1, R1
+ MOVV M1, R1
+
+
+//
+// integer operations
+// logical instructions
+// shift instructions
+// unary instructions
+//
+// LADDW rreg ',' sreg ',' rreg
+// {
+// outcode(int($1), &$2, int($4), &$6);
+// }
+ ADD R1, R2, R3
+
+// LADDW imm ',' sreg ',' rreg
+// {
+// outcode(int($1), &$2, int($4), &$6);
+// }
+ ADD $1, R2, R3
+
+// LADDW rreg ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ ADD R1, R2
+
+// LADDW imm ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ ADD $4, R1
+
+// LMUL rreg ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MUL R1, R2
+
+// LSHW rreg ',' sreg ',' rreg
+// {
+// outcode(int($1), &$2, int($4), &$6);
+// }
+ SLL R1, R2, R3
+
+// LSHW rreg ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ SLL R1, R2
+
+// LSHW imm ',' sreg ',' rreg
+// {
+// outcode(int($1), &$2, int($4), &$6);
+// }
+ SLL $4, R1, R2
+
+// LSHW imm ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ SLL $4, R1
+
+//
+// move immediate: macro for lui+or, addi, addis, and other combinations
+//
+// LMOVW imm ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVW $1, R1
+ MOVV $1, R1
+
+// LMOVW ximm ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVW $1, R1
+ MOVW $foo(SB), R1
+ MOVV $1, R1
+ MOVV $foo(SB), R1
+
+
+//
+// branch
+//
+// LBRA rel
+// {
+// outcode(int($1), &nullgen, 0, &$2);
+// }
+label0:
+ JMP 1(PC)
+ JMP label0+0
+ JAL 1(PC)
+ JAL label0+0
+
+// LBRA addr
+// {
+// outcode(int($1), &nullgen, 0, &$2);
+// }
+ JMP 4(R1)
+ JMP foo+0(SB)
+ JAL 4(R1)
+ JAL foo+0(SB)
+
+//
+// BEQ/BNE
+//
+// LBRA rreg ',' rel
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+label1:
+ BEQ R1, 1(PC)
+ BEQ R1, label1
+
+// LBRA rreg ',' sreg ',' rel
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+label2:
+ BEQ R1, R2, 1(PC)
+ BEQ R1, R2, label2
+
+//
+// other integer conditional branch
+//
+// LBRA rreg ',' rel
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+label3:
+ BLTZ R1, 1(PC)
+ BLTZ R1, label3
+
+//
+// floating point conditional branch
+//
+// LBRA rel
+label4:
+ BFPT 1(PC)
+ BFPT label4
+
+
+//
+// floating point operate
+//
+// LFCONV freg ',' freg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ ABSD F1, F2
+
+// LFADD freg ',' freg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ ADDD F1, F2
+
+// LFADD freg ',' freg ',' freg
+// {
+// outcode(int($1), &$2, int($4.Reg), &$6);
+// }
+ ADDD F1, F2, F3
+
+// LFCMP freg ',' freg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ CMPEQD F1, F2
+
+
+//
+// WORD
+//
+ WORD $1
+ WORD $foo(SB)
+
+//
+// NOP
+//
+// LNOP comma // asm doesn't support the trailing comma.
+// {
+// outcode(int($1), &nullgen, 0, &nullgen);
+// }
+ NOP
+
+// LNOP rreg comma // asm doesn't support the trailing comma.
+// {
+// outcode(int($1), &$2, 0, &nullgen);
+// }
+ NOP R2
+
+// LNOP freg comma // asm doesn't support the trailing comma.
+// {
+// outcode(int($1), &$2, 0, &nullgen);
+// }
+ NOP F2
+
+// LNOP ',' rreg // asm doesn't support the leading comma.
+// {
+// outcode(int($1), &nullgen, 0, &$3);
+// }
+ NOP R2
+
+// LNOP ',' freg // asm doesn't support the leading comma.
+// {
+// outcode(int($1), &nullgen, 0, &$3);
+// }
+ NOP F2
+
+// LNOP imm
+// {
+// outcode(int($1), &$2, 0, &nullgen);
+// }
+ NOP $4
+
+//
+// special
+//
+ SYSCALL
+ BREAK
+ BREAK $1, (R1) // overloaded CACHE opcode
+
+//
+// RET
+//
+// LRETRN comma // asm doesn't support the trailing comma.
+// {
+// outcode(int($1), &nullgen, 0, &nullgen);
+// }
+ SYSCALL
+ RET
+
+
+// More JMP/JAL cases, and canonical names JMP, CALL.
+
+ JAL foo(SB)
+ JMP foo(SB)
+ CALL foo(SB)
+
+// END
+//
+// LEND comma // asm doesn't support the trailing comma.
+// {
+// outcode(int($1), &nullgen, 0, &nullgen);
+// }
+ END
// Scan to newline. Backslashes escape newlines.
for tok != '\n' {
if tok == scanner.EOF {
- in.Error("missing newline in macro definition for %q\n", name)
+ in.Error("missing newline in definition for macro:", name)
}
if tok == '\\' {
tok = in.Stack.Next()
if f.Ref == nil {
f.Ref = make([]*Ref, 0, 8)
}
- f.walk(ast2, "prog", (*File).saveRef)
+ f.walk(ast2, "prog", (*File).saveExprs)
// Accumulate exported functions.
// The comments are only on ast1 but we need to
return strings.Join(pieces, "")
}
+// Save various references we are going to need later.
+func (f *File) saveExprs(x interface{}, context string) {
+ switch x := x.(type) {
+ case *ast.Expr:
+ switch (*x).(type) {
+ case *ast.SelectorExpr:
+ f.saveRef(x, context)
+ }
+ case *ast.CallExpr:
+ f.saveCall(x)
+ }
+}
+
// Save references to C.xxx for later processing.
-func (f *File) saveRef(x interface{}, context string) {
- n, ok := x.(*ast.Expr)
- if !ok {
+func (f *File) saveRef(n *ast.Expr, context string) {
+ sel := (*n).(*ast.SelectorExpr)
+ // For now, assume that the only instance of capital C is when
+ // used as the imported package identifier.
+ // The parser should take care of scoping in the future, so
+ // that we will be able to distinguish a "top-level C" from a
+ // local C.
+ if l, ok := sel.X.(*ast.Ident); !ok || l.Name != "C" {
return
}
- if sel, ok := (*n).(*ast.SelectorExpr); ok {
- // For now, assume that the only instance of capital C is
- // when used as the imported package identifier.
- // The parser should take care of scoping in the future,
- // so that we will be able to distinguish a "top-level C"
- // from a local C.
- if l, ok := sel.X.(*ast.Ident); ok && l.Name == "C" {
- if context == "as2" {
- context = "expr"
- }
- if context == "embed-type" {
- error_(sel.Pos(), "cannot embed C type")
- }
- goname := sel.Sel.Name
- if goname == "errno" {
- error_(sel.Pos(), "cannot refer to errno directly; see documentation")
- return
- }
- if goname == "_CMalloc" {
- error_(sel.Pos(), "cannot refer to C._CMalloc; use C.malloc")
- return
- }
- if goname == "malloc" {
- goname = "_CMalloc"
- }
- name := f.Name[goname]
- if name == nil {
- name = &Name{
- Go: goname,
- }
- f.Name[goname] = name
- }
- f.Ref = append(f.Ref, &Ref{
- Name: name,
- Expr: n,
- Context: context,
- })
- return
+ if context == "as2" {
+ context = "expr"
+ }
+ if context == "embed-type" {
+ error_(sel.Pos(), "cannot embed C type")
+ }
+ goname := sel.Sel.Name
+ if goname == "errno" {
+ error_(sel.Pos(), "cannot refer to errno directly; see documentation")
+ return
+ }
+ if goname == "_CMalloc" {
+ error_(sel.Pos(), "cannot refer to C._CMalloc; use C.malloc")
+ return
+ }
+ if goname == "malloc" {
+ goname = "_CMalloc"
+ }
+ name := f.Name[goname]
+ if name == nil {
+ name = &Name{
+ Go: goname,
}
+ f.Name[goname] = name
+ }
+ f.Ref = append(f.Ref, &Ref{
+ Name: name,
+ Expr: n,
+ Context: context,
+ })
+}
+
+// Save calls to C.xxx for later processing.
+func (f *File) saveCall(call *ast.CallExpr) {
+ sel, ok := call.Fun.(*ast.SelectorExpr)
+ if !ok {
+ return
+ }
+ if l, ok := sel.X.(*ast.Ident); !ok || l.Name != "C" {
+ return
}
+ f.Calls = append(f.Calls, call)
}
// If a function should be exported add it to ExpFunc.
C.long, C.ulong (unsigned long), C.longlong (long long),
C.ulonglong (unsigned long long), C.float, C.double.
The C type void* is represented by Go's unsafe.Pointer.
+The C types __int128_t and __uint128_t are represented by [16]byte.
To access a struct, union, or enum type directly, prefix it with
struct_, union_, or enum_, as in C.struct_stat.
// C string to Go string
func C.GoString(*C.char) string
- // C string, length to Go string
+ // C data with explicit length to Go string
func C.GoStringN(*C.char, C.int) string
- // C pointer, length to Go []byte
+ // C data with explicit length to Go []byte
func C.GoBytes(unsafe.Pointer, C.int) []byte
C references to Go
duplicate symbols and the linker will fail. To avoid this, definitions
must be placed in preambles in other files, or in C source files.
+Passing pointers
+
+Go is a garbage collected language, and the garbage collector needs to
+know the location of every pointer to Go memory. Because of this,
+there are restrictions on passing pointers between Go and C.
+
+In this section the term Go pointer means a pointer to memory
+allocated by Go (such as by using the & operator or calling the
+predefined new function) and the term C pointer means a pointer to
+memory allocated by C (such as by a call to C.malloc). Whether a
+pointer is a Go pointer or a C pointer is a dynamic property
+determined by how the memory was allocated; it has nothing to do with
+the type of the pointer.
+
+Go code may pass a Go pointer to C provided the Go memory to which it
+points does not contain any Go pointers. The C code must preserve
+this property: it must not store any Go pointers into Go memory, even
+temporarily. When passing a pointer to a field in a struct, the Go
+memory in question is the memory occupied by the field, not the entire
+struct. When passing a pointer to an element in an array or slice,
+the Go memory in question is the entire array or the entire backing
+array of the slice.
+
+C code may not keep a copy of a Go pointer after the call returns.
+
+If Go code passes a Go pointer to a C function, the C function must
+return. There is no specific time limit, but a C function that simply
+blocks holding a Go pointer while other goroutines are running may
+eventually cause the program to run out of memory and fail (because
+the garbage collector may not be able to make progress).
+
+A Go function called by C code may not return a Go pointer. A Go
+function called by C code may take C pointers as arguments, and it may
+store non-pointer or C pointer data through those pointers, but it may
+not store a Go pointer into memory pointed to by a C pointer. A Go
+function called by C code may take a Go pointer as an argument, but it
+must preserve the property that the Go memory to which it points does
+not contain any Go pointers.
+
+These rules are partially enforced by cgo by default. It is possible
+to defeat this enforcement by using the unsafe package, and of course
+there is nothing stopping the C code from doing anything it likes.
+However, programs that break these rules are likely to fail in
+unexpected and unpredictable ways.
+
Using cgo directly
Usage:
if len(needType) > 0 {
p.loadDWARF(f, needType)
}
+ p.rewriteCalls(f)
p.rewriteRef(f)
}
n.Mangle = prefix + n.Kind + "_" + n.Go
}
+// rewriteCalls rewrites all calls that pass pointers to check that
+// they follow the rules for passing pointers between Go and C.
+func (p *Package) rewriteCalls(f *File) {
+ for _, call := range f.Calls {
+ // This is a call to C.xxx; set goname to "xxx".
+ goname := call.Fun.(*ast.SelectorExpr).Sel.Name
+ if goname == "malloc" {
+ continue
+ }
+ name := f.Name[goname]
+ if name.Kind != "func" {
+ // Probably a type conversion.
+ continue
+ }
+ p.rewriteCall(f, call, name)
+ }
+}
+
+// rewriteCall rewrites one call to add pointer checks. We replace
+// each pointer argument x with _cgoCheckPointer(x).(T).
+func (p *Package) rewriteCall(f *File, call *ast.CallExpr, name *Name) {
+ for i, param := range name.FuncType.Params {
+ // An untyped nil does not need a pointer check, and
+ // when _cgoCheckPointer returns the untyped nil the
+ // type assertion we are going to insert will fail.
+ // Easier to just skip nil arguments.
+ // TODO: Note that this fails if nil is shadowed.
+ if id, ok := call.Args[i].(*ast.Ident); ok && id.Name == "nil" {
+ continue
+ }
+
+ if !p.needsPointerCheck(f, param.Go) {
+ continue
+ }
+
+ if len(call.Args) <= i {
+ // Avoid a crash; this will be caught when the
+ // generated file is compiled.
+ return
+ }
+
+ c := &ast.CallExpr{
+ Fun: ast.NewIdent("_cgoCheckPointer"),
+ Args: []ast.Expr{
+ call.Args[i],
+ },
+ }
+
+ // Add optional additional arguments for an address
+ // expression.
+ if u, ok := call.Args[i].(*ast.UnaryExpr); ok && u.Op == token.AND {
+ c.Args = p.checkAddrArgs(f, c.Args, u.X)
+ }
+
+ // _cgoCheckPointer returns interface{}.
+ // We need to type assert that to the type we want.
+ // If the Go version of this C type uses
+ // unsafe.Pointer, we can't use a type assertion,
+ // because the Go file might not import unsafe.
+ // Instead we use a local variant of _cgoCheckPointer.
+
+ var arg ast.Expr
+ if n := p.unsafeCheckPointerName(param.Go); n != "" {
+ c.Fun = ast.NewIdent(n)
+ arg = c
+ } else {
+ // In order for the type assertion to succeed,
+ // we need it to match the actual type of the
+ // argument. The only type we have is the
+ // type of the function parameter. We know
+ // that the argument type must be assignable
+ // to the function parameter type, or the code
+ // would not compile, but there is nothing
+ // requiring that the types be exactly the
+ // same. Add a type conversion to the
+ // argument so that the type assertion will
+ // succeed.
+ c.Args[0] = &ast.CallExpr{
+ Fun: param.Go,
+ Args: []ast.Expr{
+ c.Args[0],
+ },
+ }
+
+ arg = &ast.TypeAssertExpr{
+ X: c,
+ Type: param.Go,
+ }
+ }
+
+ call.Args[i] = arg
+ }
+}
+
+// needsPointerCheck returns whether the type t needs a pointer check.
+// This is true if t is a pointer and if the value to which it points
+// might contain a pointer.
+func (p *Package) needsPointerCheck(f *File, t ast.Expr) bool {
+ return p.hasPointer(f, t, true)
+}
+
+// hasPointer is used by needsPointerCheck. If top is true it returns
+// whether t is or contains a pointer that might point to a pointer.
+// If top is false it returns whether t is or contains a pointer.
+func (p *Package) hasPointer(f *File, t ast.Expr, top bool) bool {
+ switch t := t.(type) {
+ case *ast.ArrayType:
+ if t.Len == nil {
+ if !top {
+ return true
+ }
+ return p.hasPointer(f, t.Elt, false)
+ }
+ return p.hasPointer(f, t.Elt, top)
+ case *ast.StructType:
+ for _, field := range t.Fields.List {
+ if p.hasPointer(f, field.Type, top) {
+ return true
+ }
+ }
+ return false
+ case *ast.StarExpr: // Pointer type.
+ if !top {
+ return true
+ }
+ return p.hasPointer(f, t.X, false)
+ case *ast.FuncType, *ast.InterfaceType, *ast.MapType, *ast.ChanType:
+ return true
+ case *ast.Ident:
+ // TODO: Handle types defined within function.
+ for _, d := range p.Decl {
+ gd, ok := d.(*ast.GenDecl)
+ if !ok || gd.Tok != token.TYPE {
+ continue
+ }
+ for _, spec := range gd.Specs {
+ ts, ok := spec.(*ast.TypeSpec)
+ if !ok {
+ continue
+ }
+ if ts.Name.Name == t.Name {
+ return p.hasPointer(f, ts.Type, top)
+ }
+ }
+ }
+ if def := typedef[t.Name]; def != nil {
+ return p.hasPointer(f, def.Go, top)
+ }
+ if t.Name == "string" {
+ return !top
+ }
+ if t.Name == "error" {
+ return true
+ }
+ if goTypes[t.Name] != nil {
+ return false
+ }
+ // We can't figure out the type. Conservative
+ // approach is to assume it has a pointer.
+ return true
+ case *ast.SelectorExpr:
+ if l, ok := t.X.(*ast.Ident); !ok || l.Name != "C" {
+ // Type defined in a different package.
+ // Conservative approach is to assume it has a
+ // pointer.
+ return true
+ }
+ name := f.Name[t.Sel.Name]
+ if name != nil && name.Kind == "type" && name.Type != nil && name.Type.Go != nil {
+ return p.hasPointer(f, name.Type.Go, top)
+ }
+ // We can't figure out the type. Conservative
+ // approach is to assume it has a pointer.
+ return true
+ default:
+ error_(t.Pos(), "could not understand type %s", gofmt(t))
+ return true
+ }
+}
+
+// checkAddrArgs tries to add arguments to the call of
+// _cgoCheckPointer when the argument is an address expression. We
+// pass true to mean that the argument is an address operation of
+// something other than a slice index, which means that it's only
+// necessary to check the specific element pointed to, not the entire
+// object. This is for &s.f, where f is a field in a struct. We can
+// pass a slice or array, meaning that we should check the entire
+// slice or array but need not check any other part of the object.
+// This is for &s.a[i], where we need to check all of a. However, we
+// only pass the slice or array if we can refer to it without side
+// effects.
+func (p *Package) checkAddrArgs(f *File, args []ast.Expr, x ast.Expr) []ast.Expr {
+ index, ok := x.(*ast.IndexExpr)
+ if !ok {
+ // This is the address of something that is not an
+ // index expression. We only need to examine the
+ // single value to which it points.
+ // TODO: what is true is shadowed?
+ return append(args, ast.NewIdent("true"))
+ }
+ if !p.hasSideEffects(f, index.X) {
+ // Examine the entire slice.
+ return append(args, index.X)
+ }
+ // Treat the pointer as unknown.
+ return args
+}
+
+// hasSideEffects returns whether the expression x has any side
+// effects. x is an expression, not a statement, so the only side
+// effect is a function call.
+func (p *Package) hasSideEffects(f *File, x ast.Expr) bool {
+ found := false
+ f.walk(x, "expr",
+ func(f *File, x interface{}, context string) {
+ switch x.(type) {
+ case *ast.CallExpr:
+ found = true
+ }
+ })
+ return found
+}
+
+// unsafeCheckPointerName is given the Go version of a C type. If the
+// type uses unsafe.Pointer, we arrange to build a version of
+// _cgoCheckPointer that returns that type. This avoids using a type
+// assertion to unsafe.Pointer in our copy of user code. We return
+// the name of the _cgoCheckPointer function we are going to build, or
+// the empty string if the type does not use unsafe.Pointer.
+func (p *Package) unsafeCheckPointerName(t ast.Expr) string {
+ if !p.hasUnsafePointer(t) {
+ return ""
+ }
+ var buf bytes.Buffer
+ conf.Fprint(&buf, fset, t)
+ s := buf.String()
+ for i, t := range p.CgoChecks {
+ if s == t {
+ return p.unsafeCheckPointerNameIndex(i)
+ }
+ }
+ p.CgoChecks = append(p.CgoChecks, s)
+ return p.unsafeCheckPointerNameIndex(len(p.CgoChecks) - 1)
+}
+
+// hasUnsafePointer returns whether the Go type t uses unsafe.Pointer.
+// t is the Go version of a C type, so we don't need to handle every case.
+// We only care about direct references, not references via typedefs.
+func (p *Package) hasUnsafePointer(t ast.Expr) bool {
+ switch t := t.(type) {
+ case *ast.Ident:
+ return t.Name == "unsafe.Pointer"
+ case *ast.ArrayType:
+ return p.hasUnsafePointer(t.Elt)
+ case *ast.StructType:
+ for _, f := range t.Fields.List {
+ if p.hasUnsafePointer(f.Type) {
+ return true
+ }
+ }
+ case *ast.StarExpr: // Pointer type.
+ return p.hasUnsafePointer(t.X)
+ }
+ return false
+}
+
+// unsafeCheckPointerNameIndex returns the name to use for a
+// _cgoCheckPointer variant based on the index in the CgoChecks slice.
+func (p *Package) unsafeCheckPointerNameIndex(i int) string {
+ return fmt.Sprintf("_cgoCheckPointer%d", i)
+}
+
// rewriteRef rewrites all the C.xxx references in f.AST to refer to the
// Go equivalents, now that we have figured out the meaning of all
// the xxx. In *godefs mode, rewriteRef replaces the names
t.Go = c.int32
case 8:
t.Go = c.int64
+ case 16:
+ t.Go = &ast.ArrayType{
+ Len: c.intExpr(t.Size),
+ Elt: c.uint8,
+ }
}
if t.Align = t.Size; t.Align >= c.ptrSize {
t.Align = c.ptrSize
t.Go = c.uint32
case 8:
t.Go = c.uint64
+ case 16:
+ t.Go = &ast.ArrayType{
+ Len: c.intExpr(t.Size),
+ Elt: c.uint8,
+ }
}
if t.Align = t.Size; t.Align >= c.ptrSize {
t.Align = c.ptrSize
GoFiles []string // list of Go files
GccFiles []string // list of gcc output files
Preamble string // collected preamble for _cgo_export.h
+ CgoChecks []string // see unsafeCheckPointerName
}
// A File collects information about a single Go input file.
Package string // Package name
Preamble string // C preamble (doc comment on import "C")
Ref []*Ref // all references to C.xxx in AST
+ Calls []*ast.CallExpr // all calls to C.xxx in AST
ExpFunc []*ExpFunc // exported functions for this file
Name map[string]*Name // map from Go name to Name
}
}
var ptrSizeMap = map[string]int64{
- "386": 4,
- "amd64": 8,
- "arm": 4,
- "arm64": 8,
- "ppc64": 8,
- "ppc64le": 8,
- "s390": 4,
- "s390x": 8,
+ "386": 4,
+ "amd64": 8,
+ "arm": 4,
+ "arm64": 8,
+ "mips64": 8,
+ "mips64le": 8,
+ "ppc64": 8,
+ "ppc64le": 8,
+ "s390": 4,
+ "s390x": 8,
}
var intSizeMap = map[string]int64{
- "386": 4,
- "amd64": 8,
- "arm": 4,
- "arm64": 8,
- "ppc64": 8,
- "ppc64le": 8,
- "s390": 4,
- "s390x": 4,
+ "386": 4,
+ "amd64": 8,
+ "arm": 4,
+ "arm64": 8,
+ "mips64": 8,
+ "mips64le": 8,
+ "ppc64": 8,
+ "ppc64le": 8,
+ "s390": 4,
+ "s390x": 4,
}
var cPrefix string
fmt.Fprint(fgo2, goProlog)
}
+ for i, t := range p.CgoChecks {
+ n := p.unsafeCheckPointerNameIndex(i)
+ fmt.Fprintf(fgo2, "\nfunc %s(p interface{}, args ...interface{}) %s {\n", n, t)
+ fmt.Fprintf(fgo2, "\treturn _cgoCheckPointer(p, args...).(%s)\n", t)
+ fmt.Fprintf(fgo2, "}\n")
+ }
+
gccgoSymbolPrefix := p.gccgoSymbolPrefix()
cVars := make(map[string]bool)
fmt.Fprintf(fgo2, "//go:cgo_export_static _cgoexp%s_%s\n", cPrefix, exp.ExpName)
fmt.Fprintf(fgo2, "//go:nosplit\n") // no split stack, so no use of m or g
fmt.Fprintf(fgo2, "//go:norace\n") // must not have race detector calls inserted
- fmt.Fprintf(fgo2, "func _cgoexp%s_%s(a unsafe.Pointer, n int32) {", cPrefix, exp.ExpName)
+ fmt.Fprintf(fgo2, "func _cgoexp%s_%s(a unsafe.Pointer, n int32) {\n", cPrefix, exp.ExpName)
fmt.Fprintf(fgo2, "\tfn := %s\n", goname)
// The indirect here is converting from a Go function pointer to a C function pointer.
fmt.Fprintf(fgo2, "\t_cgo_runtime_cgocallback(**(**unsafe.Pointer)(unsafe.Pointer(&fn)), a, uintptr(n));\n")
//go:linkname _cgo_runtime_cgocallback runtime.cgocallback
func _cgo_runtime_cgocallback(unsafe.Pointer, unsafe.Pointer, uintptr)
+
+//go:linkname _cgoCheckPointer runtime.cgoCheckPointer
+func _cgoCheckPointer(interface{}, ...interface{}) interface{}
`
const goStringDef = `
Write memory profile for the compilation to file.
-memprofilerate rate
Set runtime.MemProfileRate for the compilation to rate.
+ -msan
+ Insert calls to C/C++ memory sanitizer.
-nolocalimports
Disallow local (relative) imports.
-o file
Write a package (archive) file rather than an object file
-race
Compile with race detector enabled.
+ -trimpath prefix
+ Remove prefix from recorded source file paths.
-u
Disallow importing packages not marked as safe; implies -nolocalimports.
The //go:noescape directive specifies that the next declaration in the file, which
must be a func without a body (meaning that it has an implementation not written
in Go) does not allow any of the pointers passed as arguments to escape into the
-heap or into the values returned from the function. This information can be used as
+heap or into the values returned from the function. This information can be used
during the compiler's escape analysis of Go code calling the function.
//go:nosplit
* res = nl % nr
* according to op.
*/
-func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
+func dodiv(op gc.Op, nl *gc.Node, nr *gc.Node, res *gc.Node) {
// Have to be careful about handling
// most negative int divided by -1 correctly.
// The hardware will trap.
x.Type = gc.Types[gc.TINT64]
gmove(x, oldx)
x.Type = t
- oldx.Etype = r // squirrel away old r value
+ // TODO(marvin): Fix Node.EType type union.
+ oldx.Etype = gc.EType(r) // squirrel away old r value
gc.SetReg(dr, 1)
}
}
* res = nl << nr
* res = nl >> nr
*/
-func cgen_shift(op int, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
+func cgen_shift(op gc.Op, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
a := optoas(op, nl.Type)
if nr.Op == gc.OLITERAL {
* there is no 2-operand byte multiply instruction so
* we do a full-width multiplication and truncate afterwards.
*/
-func cgen_bmul(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) bool {
+func cgen_bmul(op gc.Op, nl *gc.Node, nr *gc.Node, res *gc.Node) bool {
if optoas(op, nl.Type) != x86.AIMULB {
return false
}
gins(as, &n1, n2)
}
-func ginscmp(op int, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
+func ginscmp(op gc.Op, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
if gc.Isint[t.Etype] && n1.Op == gc.OLITERAL && gc.Smallintconst(n1) && n2.Op != gc.OLITERAL {
// Reverse comparison to place constant last.
op = gc.Brrev(op)
}
// General case.
var r1, r2, g1, g2 gc.Node
- if n1.Op == gc.ONAME && n1.Class&gc.PHEAP == 0 || n1.Op == gc.OINDREG {
+
+ // A special case to make write barriers more efficient.
+ // Comparing the first field of a named struct can be done directly.
+ base := n1
+ if n1.Op == gc.ODOT && n1.Left.Type.Etype == gc.TSTRUCT && n1.Left.Type.Type.Sym == n1.Right.Sym {
+ base = n1.Left
+ }
+
+ if base.Op == gc.ONAME && base.Class&gc.PHEAP == 0 || n1.Op == gc.OINDREG {
r1 = *n1
} else {
gc.Regalloc(&r1, t, n1)
/*
* return Axxx for Oxxx on type t.
*/
-func optoas(op int, t *gc.Type) int {
+func optoas(op gc.Op, t *gc.Type) int {
if t == nil {
gc.Fatalf("optoas: t is nil")
}
+ // avoid constant conversions in switches below
+ const (
+ OMINUS_ = uint32(gc.OMINUS) << 16
+ OLSH_ = uint32(gc.OLSH) << 16
+ ORSH_ = uint32(gc.ORSH) << 16
+ OADD_ = uint32(gc.OADD) << 16
+ OSUB_ = uint32(gc.OSUB) << 16
+ OMUL_ = uint32(gc.OMUL) << 16
+ ODIV_ = uint32(gc.ODIV) << 16
+ OMOD_ = uint32(gc.OMOD) << 16
+ OOR_ = uint32(gc.OOR) << 16
+ OAND_ = uint32(gc.OAND) << 16
+ OXOR_ = uint32(gc.OXOR) << 16
+ OEQ_ = uint32(gc.OEQ) << 16
+ ONE_ = uint32(gc.ONE) << 16
+ OLT_ = uint32(gc.OLT) << 16
+ OLE_ = uint32(gc.OLE) << 16
+ OGE_ = uint32(gc.OGE) << 16
+ OGT_ = uint32(gc.OGT) << 16
+ OCMP_ = uint32(gc.OCMP) << 16
+ OPS_ = uint32(gc.OPS) << 16
+ OPC_ = uint32(gc.OPC) << 16
+ OAS_ = uint32(gc.OAS) << 16
+ OHMUL_ = uint32(gc.OHMUL) << 16
+ OSQRT_ = uint32(gc.OSQRT) << 16
+ OADDR_ = uint32(gc.OADDR) << 16
+ OINC_ = uint32(gc.OINC) << 16
+ ODEC_ = uint32(gc.ODEC) << 16
+ OLROT_ = uint32(gc.OLROT) << 16
+ ORROTC_ = uint32(gc.ORROTC) << 16
+ OEXTEND_ = uint32(gc.OEXTEND) << 16
+ )
+
a := obj.AXXX
switch uint32(op)<<16 | uint32(gc.Simtype[t.Etype]) {
default:
gc.Fatalf("optoas: no entry %v-%v", gc.Oconv(int(op), 0), t)
- case gc.OADDR<<16 | gc.TPTR32:
+ case OADDR_ | gc.TPTR32:
a = x86.ALEAL
- case gc.OADDR<<16 | gc.TPTR64:
+ case OADDR_ | gc.TPTR64:
a = x86.ALEAQ
- case gc.OEQ<<16 | gc.TBOOL,
- gc.OEQ<<16 | gc.TINT8,
- gc.OEQ<<16 | gc.TUINT8,
- gc.OEQ<<16 | gc.TINT16,
- gc.OEQ<<16 | gc.TUINT16,
- gc.OEQ<<16 | gc.TINT32,
- gc.OEQ<<16 | gc.TUINT32,
- gc.OEQ<<16 | gc.TINT64,
- gc.OEQ<<16 | gc.TUINT64,
- gc.OEQ<<16 | gc.TPTR32,
- gc.OEQ<<16 | gc.TPTR64,
- gc.OEQ<<16 | gc.TFLOAT32,
- gc.OEQ<<16 | gc.TFLOAT64:
+ case OEQ_ | gc.TBOOL,
+ OEQ_ | gc.TINT8,
+ OEQ_ | gc.TUINT8,
+ OEQ_ | gc.TINT16,
+ OEQ_ | gc.TUINT16,
+ OEQ_ | gc.TINT32,
+ OEQ_ | gc.TUINT32,
+ OEQ_ | gc.TINT64,
+ OEQ_ | gc.TUINT64,
+ OEQ_ | gc.TPTR32,
+ OEQ_ | gc.TPTR64,
+ OEQ_ | gc.TFLOAT32,
+ OEQ_ | gc.TFLOAT64:
a = x86.AJEQ
- case gc.ONE<<16 | gc.TBOOL,
- gc.ONE<<16 | gc.TINT8,
- gc.ONE<<16 | gc.TUINT8,
- gc.ONE<<16 | gc.TINT16,
- gc.ONE<<16 | gc.TUINT16,
- gc.ONE<<16 | gc.TINT32,
- gc.ONE<<16 | gc.TUINT32,
- gc.ONE<<16 | gc.TINT64,
- gc.ONE<<16 | gc.TUINT64,
- gc.ONE<<16 | gc.TPTR32,
- gc.ONE<<16 | gc.TPTR64,
- gc.ONE<<16 | gc.TFLOAT32,
- gc.ONE<<16 | gc.TFLOAT64:
+ case ONE_ | gc.TBOOL,
+ ONE_ | gc.TINT8,
+ ONE_ | gc.TUINT8,
+ ONE_ | gc.TINT16,
+ ONE_ | gc.TUINT16,
+ ONE_ | gc.TINT32,
+ ONE_ | gc.TUINT32,
+ ONE_ | gc.TINT64,
+ ONE_ | gc.TUINT64,
+ ONE_ | gc.TPTR32,
+ ONE_ | gc.TPTR64,
+ ONE_ | gc.TFLOAT32,
+ ONE_ | gc.TFLOAT64:
a = x86.AJNE
- case gc.OPS<<16 | gc.TBOOL,
- gc.OPS<<16 | gc.TINT8,
- gc.OPS<<16 | gc.TUINT8,
- gc.OPS<<16 | gc.TINT16,
- gc.OPS<<16 | gc.TUINT16,
- gc.OPS<<16 | gc.TINT32,
- gc.OPS<<16 | gc.TUINT32,
- gc.OPS<<16 | gc.TINT64,
- gc.OPS<<16 | gc.TUINT64,
- gc.OPS<<16 | gc.TPTR32,
- gc.OPS<<16 | gc.TPTR64,
- gc.OPS<<16 | gc.TFLOAT32,
- gc.OPS<<16 | gc.TFLOAT64:
+ case OPS_ | gc.TBOOL,
+ OPS_ | gc.TINT8,
+ OPS_ | gc.TUINT8,
+ OPS_ | gc.TINT16,
+ OPS_ | gc.TUINT16,
+ OPS_ | gc.TINT32,
+ OPS_ | gc.TUINT32,
+ OPS_ | gc.TINT64,
+ OPS_ | gc.TUINT64,
+ OPS_ | gc.TPTR32,
+ OPS_ | gc.TPTR64,
+ OPS_ | gc.TFLOAT32,
+ OPS_ | gc.TFLOAT64:
a = x86.AJPS
- case gc.OPC<<16 | gc.TBOOL,
- gc.OPC<<16 | gc.TINT8,
- gc.OPC<<16 | gc.TUINT8,
- gc.OPC<<16 | gc.TINT16,
- gc.OPC<<16 | gc.TUINT16,
- gc.OPC<<16 | gc.TINT32,
- gc.OPC<<16 | gc.TUINT32,
- gc.OPC<<16 | gc.TINT64,
- gc.OPC<<16 | gc.TUINT64,
- gc.OPC<<16 | gc.TPTR32,
- gc.OPC<<16 | gc.TPTR64,
- gc.OPC<<16 | gc.TFLOAT32,
- gc.OPC<<16 | gc.TFLOAT64:
+ case OPC_ | gc.TBOOL,
+ OPC_ | gc.TINT8,
+ OPC_ | gc.TUINT8,
+ OPC_ | gc.TINT16,
+ OPC_ | gc.TUINT16,
+ OPC_ | gc.TINT32,
+ OPC_ | gc.TUINT32,
+ OPC_ | gc.TINT64,
+ OPC_ | gc.TUINT64,
+ OPC_ | gc.TPTR32,
+ OPC_ | gc.TPTR64,
+ OPC_ | gc.TFLOAT32,
+ OPC_ | gc.TFLOAT64:
a = x86.AJPC
- case gc.OLT<<16 | gc.TINT8,
- gc.OLT<<16 | gc.TINT16,
- gc.OLT<<16 | gc.TINT32,
- gc.OLT<<16 | gc.TINT64:
+ case OLT_ | gc.TINT8,
+ OLT_ | gc.TINT16,
+ OLT_ | gc.TINT32,
+ OLT_ | gc.TINT64:
a = x86.AJLT
- case gc.OLT<<16 | gc.TUINT8,
- gc.OLT<<16 | gc.TUINT16,
- gc.OLT<<16 | gc.TUINT32,
- gc.OLT<<16 | gc.TUINT64:
+ case OLT_ | gc.TUINT8,
+ OLT_ | gc.TUINT16,
+ OLT_ | gc.TUINT32,
+ OLT_ | gc.TUINT64:
a = x86.AJCS
- case gc.OLE<<16 | gc.TINT8,
- gc.OLE<<16 | gc.TINT16,
- gc.OLE<<16 | gc.TINT32,
- gc.OLE<<16 | gc.TINT64:
+ case OLE_ | gc.TINT8,
+ OLE_ | gc.TINT16,
+ OLE_ | gc.TINT32,
+ OLE_ | gc.TINT64:
a = x86.AJLE
- case gc.OLE<<16 | gc.TUINT8,
- gc.OLE<<16 | gc.TUINT16,
- gc.OLE<<16 | gc.TUINT32,
- gc.OLE<<16 | gc.TUINT64:
+ case OLE_ | gc.TUINT8,
+ OLE_ | gc.TUINT16,
+ OLE_ | gc.TUINT32,
+ OLE_ | gc.TUINT64:
a = x86.AJLS
- case gc.OGT<<16 | gc.TINT8,
- gc.OGT<<16 | gc.TINT16,
- gc.OGT<<16 | gc.TINT32,
- gc.OGT<<16 | gc.TINT64:
+ case OGT_ | gc.TINT8,
+ OGT_ | gc.TINT16,
+ OGT_ | gc.TINT32,
+ OGT_ | gc.TINT64:
a = x86.AJGT
- case gc.OGT<<16 | gc.TUINT8,
- gc.OGT<<16 | gc.TUINT16,
- gc.OGT<<16 | gc.TUINT32,
- gc.OGT<<16 | gc.TUINT64,
- gc.OLT<<16 | gc.TFLOAT32,
- gc.OLT<<16 | gc.TFLOAT64:
+ case OGT_ | gc.TUINT8,
+ OGT_ | gc.TUINT16,
+ OGT_ | gc.TUINT32,
+ OGT_ | gc.TUINT64,
+ OLT_ | gc.TFLOAT32,
+ OLT_ | gc.TFLOAT64:
a = x86.AJHI
- case gc.OGE<<16 | gc.TINT8,
- gc.OGE<<16 | gc.TINT16,
- gc.OGE<<16 | gc.TINT32,
- gc.OGE<<16 | gc.TINT64:
+ case OGE_ | gc.TINT8,
+ OGE_ | gc.TINT16,
+ OGE_ | gc.TINT32,
+ OGE_ | gc.TINT64:
a = x86.AJGE
- case gc.OGE<<16 | gc.TUINT8,
- gc.OGE<<16 | gc.TUINT16,
- gc.OGE<<16 | gc.TUINT32,
- gc.OGE<<16 | gc.TUINT64,
- gc.OLE<<16 | gc.TFLOAT32,
- gc.OLE<<16 | gc.TFLOAT64:
+ case OGE_ | gc.TUINT8,
+ OGE_ | gc.TUINT16,
+ OGE_ | gc.TUINT32,
+ OGE_ | gc.TUINT64,
+ OLE_ | gc.TFLOAT32,
+ OLE_ | gc.TFLOAT64:
a = x86.AJCC
- case gc.OCMP<<16 | gc.TBOOL,
- gc.OCMP<<16 | gc.TINT8,
- gc.OCMP<<16 | gc.TUINT8:
+ case OCMP_ | gc.TBOOL,
+ OCMP_ | gc.TINT8,
+ OCMP_ | gc.TUINT8:
a = x86.ACMPB
- case gc.OCMP<<16 | gc.TINT16,
- gc.OCMP<<16 | gc.TUINT16:
+ case OCMP_ | gc.TINT16,
+ OCMP_ | gc.TUINT16:
a = x86.ACMPW
- case gc.OCMP<<16 | gc.TINT32,
- gc.OCMP<<16 | gc.TUINT32,
- gc.OCMP<<16 | gc.TPTR32:
+ case OCMP_ | gc.TINT32,
+ OCMP_ | gc.TUINT32,
+ OCMP_ | gc.TPTR32:
a = x86.ACMPL
- case gc.OCMP<<16 | gc.TINT64,
- gc.OCMP<<16 | gc.TUINT64,
- gc.OCMP<<16 | gc.TPTR64:
+ case OCMP_ | gc.TINT64,
+ OCMP_ | gc.TUINT64,
+ OCMP_ | gc.TPTR64:
a = x86.ACMPQ
- case gc.OCMP<<16 | gc.TFLOAT32:
+ case OCMP_ | gc.TFLOAT32:
a = x86.AUCOMISS
- case gc.OCMP<<16 | gc.TFLOAT64:
+ case OCMP_ | gc.TFLOAT64:
a = x86.AUCOMISD
- case gc.OAS<<16 | gc.TBOOL,
- gc.OAS<<16 | gc.TINT8,
- gc.OAS<<16 | gc.TUINT8:
+ case OAS_ | gc.TBOOL,
+ OAS_ | gc.TINT8,
+ OAS_ | gc.TUINT8:
a = x86.AMOVB
- case gc.OAS<<16 | gc.TINT16,
- gc.OAS<<16 | gc.TUINT16:
+ case OAS_ | gc.TINT16,
+ OAS_ | gc.TUINT16:
a = x86.AMOVW
- case gc.OAS<<16 | gc.TINT32,
- gc.OAS<<16 | gc.TUINT32,
- gc.OAS<<16 | gc.TPTR32:
+ case OAS_ | gc.TINT32,
+ OAS_ | gc.TUINT32,
+ OAS_ | gc.TPTR32:
a = x86.AMOVL
- case gc.OAS<<16 | gc.TINT64,
- gc.OAS<<16 | gc.TUINT64,
- gc.OAS<<16 | gc.TPTR64:
+ case OAS_ | gc.TINT64,
+ OAS_ | gc.TUINT64,
+ OAS_ | gc.TPTR64:
a = x86.AMOVQ
- case gc.OAS<<16 | gc.TFLOAT32:
+ case OAS_ | gc.TFLOAT32:
a = x86.AMOVSS
- case gc.OAS<<16 | gc.TFLOAT64:
+ case OAS_ | gc.TFLOAT64:
a = x86.AMOVSD
- case gc.OADD<<16 | gc.TINT8,
- gc.OADD<<16 | gc.TUINT8:
+ case OADD_ | gc.TINT8,
+ OADD_ | gc.TUINT8:
a = x86.AADDB
- case gc.OADD<<16 | gc.TINT16,
- gc.OADD<<16 | gc.TUINT16:
+ case OADD_ | gc.TINT16,
+ OADD_ | gc.TUINT16:
a = x86.AADDW
- case gc.OADD<<16 | gc.TINT32,
- gc.OADD<<16 | gc.TUINT32,
- gc.OADD<<16 | gc.TPTR32:
+ case OADD_ | gc.TINT32,
+ OADD_ | gc.TUINT32,
+ OADD_ | gc.TPTR32:
a = x86.AADDL
- case gc.OADD<<16 | gc.TINT64,
- gc.OADD<<16 | gc.TUINT64,
- gc.OADD<<16 | gc.TPTR64:
+ case OADD_ | gc.TINT64,
+ OADD_ | gc.TUINT64,
+ OADD_ | gc.TPTR64:
a = x86.AADDQ
- case gc.OADD<<16 | gc.TFLOAT32:
+ case OADD_ | gc.TFLOAT32:
a = x86.AADDSS
- case gc.OADD<<16 | gc.TFLOAT64:
+ case OADD_ | gc.TFLOAT64:
a = x86.AADDSD
- case gc.OSUB<<16 | gc.TINT8,
- gc.OSUB<<16 | gc.TUINT8:
+ case OSUB_ | gc.TINT8,
+ OSUB_ | gc.TUINT8:
a = x86.ASUBB
- case gc.OSUB<<16 | gc.TINT16,
- gc.OSUB<<16 | gc.TUINT16:
+ case OSUB_ | gc.TINT16,
+ OSUB_ | gc.TUINT16:
a = x86.ASUBW
- case gc.OSUB<<16 | gc.TINT32,
- gc.OSUB<<16 | gc.TUINT32,
- gc.OSUB<<16 | gc.TPTR32:
+ case OSUB_ | gc.TINT32,
+ OSUB_ | gc.TUINT32,
+ OSUB_ | gc.TPTR32:
a = x86.ASUBL
- case gc.OSUB<<16 | gc.TINT64,
- gc.OSUB<<16 | gc.TUINT64,
- gc.OSUB<<16 | gc.TPTR64:
+ case OSUB_ | gc.TINT64,
+ OSUB_ | gc.TUINT64,
+ OSUB_ | gc.TPTR64:
a = x86.ASUBQ
- case gc.OSUB<<16 | gc.TFLOAT32:
+ case OSUB_ | gc.TFLOAT32:
a = x86.ASUBSS
- case gc.OSUB<<16 | gc.TFLOAT64:
+ case OSUB_ | gc.TFLOAT64:
a = x86.ASUBSD
- case gc.OINC<<16 | gc.TINT8,
- gc.OINC<<16 | gc.TUINT8:
+ case OINC_ | gc.TINT8,
+ OINC_ | gc.TUINT8:
a = x86.AINCB
- case gc.OINC<<16 | gc.TINT16,
- gc.OINC<<16 | gc.TUINT16:
+ case OINC_ | gc.TINT16,
+ OINC_ | gc.TUINT16:
a = x86.AINCW
- case gc.OINC<<16 | gc.TINT32,
- gc.OINC<<16 | gc.TUINT32,
- gc.OINC<<16 | gc.TPTR32:
+ case OINC_ | gc.TINT32,
+ OINC_ | gc.TUINT32,
+ OINC_ | gc.TPTR32:
a = x86.AINCL
- case gc.OINC<<16 | gc.TINT64,
- gc.OINC<<16 | gc.TUINT64,
- gc.OINC<<16 | gc.TPTR64:
+ case OINC_ | gc.TINT64,
+ OINC_ | gc.TUINT64,
+ OINC_ | gc.TPTR64:
a = x86.AINCQ
- case gc.ODEC<<16 | gc.TINT8,
- gc.ODEC<<16 | gc.TUINT8:
+ case ODEC_ | gc.TINT8,
+ ODEC_ | gc.TUINT8:
a = x86.ADECB
- case gc.ODEC<<16 | gc.TINT16,
- gc.ODEC<<16 | gc.TUINT16:
+ case ODEC_ | gc.TINT16,
+ ODEC_ | gc.TUINT16:
a = x86.ADECW
- case gc.ODEC<<16 | gc.TINT32,
- gc.ODEC<<16 | gc.TUINT32,
- gc.ODEC<<16 | gc.TPTR32:
+ case ODEC_ | gc.TINT32,
+ ODEC_ | gc.TUINT32,
+ ODEC_ | gc.TPTR32:
a = x86.ADECL
- case gc.ODEC<<16 | gc.TINT64,
- gc.ODEC<<16 | gc.TUINT64,
- gc.ODEC<<16 | gc.TPTR64:
+ case ODEC_ | gc.TINT64,
+ ODEC_ | gc.TUINT64,
+ ODEC_ | gc.TPTR64:
a = x86.ADECQ
- case gc.OMINUS<<16 | gc.TINT8,
- gc.OMINUS<<16 | gc.TUINT8:
+ case OMINUS_ | gc.TINT8,
+ OMINUS_ | gc.TUINT8:
a = x86.ANEGB
- case gc.OMINUS<<16 | gc.TINT16,
- gc.OMINUS<<16 | gc.TUINT16:
+ case OMINUS_ | gc.TINT16,
+ OMINUS_ | gc.TUINT16:
a = x86.ANEGW
- case gc.OMINUS<<16 | gc.TINT32,
- gc.OMINUS<<16 | gc.TUINT32,
- gc.OMINUS<<16 | gc.TPTR32:
+ case OMINUS_ | gc.TINT32,
+ OMINUS_ | gc.TUINT32,
+ OMINUS_ | gc.TPTR32:
a = x86.ANEGL
- case gc.OMINUS<<16 | gc.TINT64,
- gc.OMINUS<<16 | gc.TUINT64,
- gc.OMINUS<<16 | gc.TPTR64:
+ case OMINUS_ | gc.TINT64,
+ OMINUS_ | gc.TUINT64,
+ OMINUS_ | gc.TPTR64:
a = x86.ANEGQ
- case gc.OAND<<16 | gc.TBOOL,
- gc.OAND<<16 | gc.TINT8,
- gc.OAND<<16 | gc.TUINT8:
+ case OAND_ | gc.TBOOL,
+ OAND_ | gc.TINT8,
+ OAND_ | gc.TUINT8:
a = x86.AANDB
- case gc.OAND<<16 | gc.TINT16,
- gc.OAND<<16 | gc.TUINT16:
+ case OAND_ | gc.TINT16,
+ OAND_ | gc.TUINT16:
a = x86.AANDW
- case gc.OAND<<16 | gc.TINT32,
- gc.OAND<<16 | gc.TUINT32,
- gc.OAND<<16 | gc.TPTR32:
+ case OAND_ | gc.TINT32,
+ OAND_ | gc.TUINT32,
+ OAND_ | gc.TPTR32:
a = x86.AANDL
- case gc.OAND<<16 | gc.TINT64,
- gc.OAND<<16 | gc.TUINT64,
- gc.OAND<<16 | gc.TPTR64:
+ case OAND_ | gc.TINT64,
+ OAND_ | gc.TUINT64,
+ OAND_ | gc.TPTR64:
a = x86.AANDQ
- case gc.OOR<<16 | gc.TBOOL,
- gc.OOR<<16 | gc.TINT8,
- gc.OOR<<16 | gc.TUINT8:
+ case OOR_ | gc.TBOOL,
+ OOR_ | gc.TINT8,
+ OOR_ | gc.TUINT8:
a = x86.AORB
- case gc.OOR<<16 | gc.TINT16,
- gc.OOR<<16 | gc.TUINT16:
+ case OOR_ | gc.TINT16,
+ OOR_ | gc.TUINT16:
a = x86.AORW
- case gc.OOR<<16 | gc.TINT32,
- gc.OOR<<16 | gc.TUINT32,
- gc.OOR<<16 | gc.TPTR32:
+ case OOR_ | gc.TINT32,
+ OOR_ | gc.TUINT32,
+ OOR_ | gc.TPTR32:
a = x86.AORL
- case gc.OOR<<16 | gc.TINT64,
- gc.OOR<<16 | gc.TUINT64,
- gc.OOR<<16 | gc.TPTR64:
+ case OOR_ | gc.TINT64,
+ OOR_ | gc.TUINT64,
+ OOR_ | gc.TPTR64:
a = x86.AORQ
- case gc.OXOR<<16 | gc.TINT8,
- gc.OXOR<<16 | gc.TUINT8:
+ case OXOR_ | gc.TINT8,
+ OXOR_ | gc.TUINT8:
a = x86.AXORB
- case gc.OXOR<<16 | gc.TINT16,
- gc.OXOR<<16 | gc.TUINT16:
+ case OXOR_ | gc.TINT16,
+ OXOR_ | gc.TUINT16:
a = x86.AXORW
- case gc.OXOR<<16 | gc.TINT32,
- gc.OXOR<<16 | gc.TUINT32,
- gc.OXOR<<16 | gc.TPTR32:
+ case OXOR_ | gc.TINT32,
+ OXOR_ | gc.TUINT32,
+ OXOR_ | gc.TPTR32:
a = x86.AXORL
- case gc.OXOR<<16 | gc.TINT64,
- gc.OXOR<<16 | gc.TUINT64,
- gc.OXOR<<16 | gc.TPTR64:
+ case OXOR_ | gc.TINT64,
+ OXOR_ | gc.TUINT64,
+ OXOR_ | gc.TPTR64:
a = x86.AXORQ
- case gc.OLROT<<16 | gc.TINT8,
- gc.OLROT<<16 | gc.TUINT8:
+ case OLROT_ | gc.TINT8,
+ OLROT_ | gc.TUINT8:
a = x86.AROLB
- case gc.OLROT<<16 | gc.TINT16,
- gc.OLROT<<16 | gc.TUINT16:
+ case OLROT_ | gc.TINT16,
+ OLROT_ | gc.TUINT16:
a = x86.AROLW
- case gc.OLROT<<16 | gc.TINT32,
- gc.OLROT<<16 | gc.TUINT32,
- gc.OLROT<<16 | gc.TPTR32:
+ case OLROT_ | gc.TINT32,
+ OLROT_ | gc.TUINT32,
+ OLROT_ | gc.TPTR32:
a = x86.AROLL
- case gc.OLROT<<16 | gc.TINT64,
- gc.OLROT<<16 | gc.TUINT64,
- gc.OLROT<<16 | gc.TPTR64:
+ case OLROT_ | gc.TINT64,
+ OLROT_ | gc.TUINT64,
+ OLROT_ | gc.TPTR64:
a = x86.AROLQ
- case gc.OLSH<<16 | gc.TINT8,
- gc.OLSH<<16 | gc.TUINT8:
+ case OLSH_ | gc.TINT8,
+ OLSH_ | gc.TUINT8:
a = x86.ASHLB
- case gc.OLSH<<16 | gc.TINT16,
- gc.OLSH<<16 | gc.TUINT16:
+ case OLSH_ | gc.TINT16,
+ OLSH_ | gc.TUINT16:
a = x86.ASHLW
- case gc.OLSH<<16 | gc.TINT32,
- gc.OLSH<<16 | gc.TUINT32,
- gc.OLSH<<16 | gc.TPTR32:
+ case OLSH_ | gc.TINT32,
+ OLSH_ | gc.TUINT32,
+ OLSH_ | gc.TPTR32:
a = x86.ASHLL
- case gc.OLSH<<16 | gc.TINT64,
- gc.OLSH<<16 | gc.TUINT64,
- gc.OLSH<<16 | gc.TPTR64:
+ case OLSH_ | gc.TINT64,
+ OLSH_ | gc.TUINT64,
+ OLSH_ | gc.TPTR64:
a = x86.ASHLQ
- case gc.ORSH<<16 | gc.TUINT8:
+ case ORSH_ | gc.TUINT8:
a = x86.ASHRB
- case gc.ORSH<<16 | gc.TUINT16:
+ case ORSH_ | gc.TUINT16:
a = x86.ASHRW
- case gc.ORSH<<16 | gc.TUINT32,
- gc.ORSH<<16 | gc.TPTR32:
+ case ORSH_ | gc.TUINT32,
+ ORSH_ | gc.TPTR32:
a = x86.ASHRL
- case gc.ORSH<<16 | gc.TUINT64,
- gc.ORSH<<16 | gc.TPTR64:
+ case ORSH_ | gc.TUINT64,
+ ORSH_ | gc.TPTR64:
a = x86.ASHRQ
- case gc.ORSH<<16 | gc.TINT8:
+ case ORSH_ | gc.TINT8:
a = x86.ASARB
- case gc.ORSH<<16 | gc.TINT16:
+ case ORSH_ | gc.TINT16:
a = x86.ASARW
- case gc.ORSH<<16 | gc.TINT32:
+ case ORSH_ | gc.TINT32:
a = x86.ASARL
- case gc.ORSH<<16 | gc.TINT64:
+ case ORSH_ | gc.TINT64:
a = x86.ASARQ
- case gc.ORROTC<<16 | gc.TINT8,
- gc.ORROTC<<16 | gc.TUINT8:
+ case ORROTC_ | gc.TINT8,
+ ORROTC_ | gc.TUINT8:
a = x86.ARCRB
- case gc.ORROTC<<16 | gc.TINT16,
- gc.ORROTC<<16 | gc.TUINT16:
+ case ORROTC_ | gc.TINT16,
+ ORROTC_ | gc.TUINT16:
a = x86.ARCRW
- case gc.ORROTC<<16 | gc.TINT32,
- gc.ORROTC<<16 | gc.TUINT32:
+ case ORROTC_ | gc.TINT32,
+ ORROTC_ | gc.TUINT32:
a = x86.ARCRL
- case gc.ORROTC<<16 | gc.TINT64,
- gc.ORROTC<<16 | gc.TUINT64:
+ case ORROTC_ | gc.TINT64,
+ ORROTC_ | gc.TUINT64:
a = x86.ARCRQ
- case gc.OHMUL<<16 | gc.TINT8,
- gc.OMUL<<16 | gc.TINT8,
- gc.OMUL<<16 | gc.TUINT8:
+ case OHMUL_ | gc.TINT8,
+ OMUL_ | gc.TINT8,
+ OMUL_ | gc.TUINT8:
a = x86.AIMULB
- case gc.OHMUL<<16 | gc.TINT16,
- gc.OMUL<<16 | gc.TINT16,
- gc.OMUL<<16 | gc.TUINT16:
+ case OHMUL_ | gc.TINT16,
+ OMUL_ | gc.TINT16,
+ OMUL_ | gc.TUINT16:
a = x86.AIMULW
- case gc.OHMUL<<16 | gc.TINT32,
- gc.OMUL<<16 | gc.TINT32,
- gc.OMUL<<16 | gc.TUINT32,
- gc.OMUL<<16 | gc.TPTR32:
+ case OHMUL_ | gc.TINT32,
+ OMUL_ | gc.TINT32,
+ OMUL_ | gc.TUINT32,
+ OMUL_ | gc.TPTR32:
a = x86.AIMULL
- case gc.OHMUL<<16 | gc.TINT64,
- gc.OMUL<<16 | gc.TINT64,
- gc.OMUL<<16 | gc.TUINT64,
- gc.OMUL<<16 | gc.TPTR64:
+ case OHMUL_ | gc.TINT64,
+ OMUL_ | gc.TINT64,
+ OMUL_ | gc.TUINT64,
+ OMUL_ | gc.TPTR64:
a = x86.AIMULQ
- case gc.OHMUL<<16 | gc.TUINT8:
+ case OHMUL_ | gc.TUINT8:
a = x86.AMULB
- case gc.OHMUL<<16 | gc.TUINT16:
+ case OHMUL_ | gc.TUINT16:
a = x86.AMULW
- case gc.OHMUL<<16 | gc.TUINT32,
- gc.OHMUL<<16 | gc.TPTR32:
+ case OHMUL_ | gc.TUINT32,
+ OHMUL_ | gc.TPTR32:
a = x86.AMULL
- case gc.OHMUL<<16 | gc.TUINT64,
- gc.OHMUL<<16 | gc.TPTR64:
+ case OHMUL_ | gc.TUINT64,
+ OHMUL_ | gc.TPTR64:
a = x86.AMULQ
- case gc.OMUL<<16 | gc.TFLOAT32:
+ case OMUL_ | gc.TFLOAT32:
a = x86.AMULSS
- case gc.OMUL<<16 | gc.TFLOAT64:
+ case OMUL_ | gc.TFLOAT64:
a = x86.AMULSD
- case gc.ODIV<<16 | gc.TINT8,
- gc.OMOD<<16 | gc.TINT8:
+ case ODIV_ | gc.TINT8,
+ OMOD_ | gc.TINT8:
a = x86.AIDIVB
- case gc.ODIV<<16 | gc.TUINT8,
- gc.OMOD<<16 | gc.TUINT8:
+ case ODIV_ | gc.TUINT8,
+ OMOD_ | gc.TUINT8:
a = x86.ADIVB
- case gc.ODIV<<16 | gc.TINT16,
- gc.OMOD<<16 | gc.TINT16:
+ case ODIV_ | gc.TINT16,
+ OMOD_ | gc.TINT16:
a = x86.AIDIVW
- case gc.ODIV<<16 | gc.TUINT16,
- gc.OMOD<<16 | gc.TUINT16:
+ case ODIV_ | gc.TUINT16,
+ OMOD_ | gc.TUINT16:
a = x86.ADIVW
- case gc.ODIV<<16 | gc.TINT32,
- gc.OMOD<<16 | gc.TINT32:
+ case ODIV_ | gc.TINT32,
+ OMOD_ | gc.TINT32:
a = x86.AIDIVL
- case gc.ODIV<<16 | gc.TUINT32,
- gc.ODIV<<16 | gc.TPTR32,
- gc.OMOD<<16 | gc.TUINT32,
- gc.OMOD<<16 | gc.TPTR32:
+ case ODIV_ | gc.TUINT32,
+ ODIV_ | gc.TPTR32,
+ OMOD_ | gc.TUINT32,
+ OMOD_ | gc.TPTR32:
a = x86.ADIVL
- case gc.ODIV<<16 | gc.TINT64,
- gc.OMOD<<16 | gc.TINT64:
+ case ODIV_ | gc.TINT64,
+ OMOD_ | gc.TINT64:
a = x86.AIDIVQ
- case gc.ODIV<<16 | gc.TUINT64,
- gc.ODIV<<16 | gc.TPTR64,
- gc.OMOD<<16 | gc.TUINT64,
- gc.OMOD<<16 | gc.TPTR64:
+ case ODIV_ | gc.TUINT64,
+ ODIV_ | gc.TPTR64,
+ OMOD_ | gc.TUINT64,
+ OMOD_ | gc.TPTR64:
a = x86.ADIVQ
- case gc.OEXTEND<<16 | gc.TINT16:
+ case OEXTEND_ | gc.TINT16:
a = x86.ACWD
- case gc.OEXTEND<<16 | gc.TINT32:
+ case OEXTEND_ | gc.TINT32:
a = x86.ACDQ
- case gc.OEXTEND<<16 | gc.TINT64:
+ case OEXTEND_ | gc.TINT64:
a = x86.ACQO
- case gc.ODIV<<16 | gc.TFLOAT32:
+ case ODIV_ | gc.TFLOAT32:
a = x86.ADIVSS
- case gc.ODIV<<16 | gc.TFLOAT64:
+ case ODIV_ | gc.TFLOAT64:
a = x86.ADIVSD
- case gc.OSQRT<<16 | gc.TFLOAT64:
+ case OSQRT_ | gc.TFLOAT64:
a = x86.ASQRTSD
}
return 2
}
+ if (p.Info.Reguse|p.Info.Regset)&FtoB(int(v.Reg)) != 0 {
+ return 2
+ }
+
if p.Info.Flags&gc.LeftAddr != 0 {
if copyas(&p.From, v) {
return 2
x86.AMOVSL: {Flags: gc.OK, Reguse: DI | SI, Regset: DI | SI},
x86.AMOVSQ: {Flags: gc.OK, Reguse: DI | SI, Regset: DI | SI},
x86.AMOVSW: {Flags: gc.OK, Reguse: DI | SI, Regset: DI | SI},
- obj.ADUFFCOPY: {Flags: gc.OK, Reguse: DI | SI, Regset: DI | SI | CX},
+ obj.ADUFFCOPY: {Flags: gc.OK, Reguse: DI | SI, Regset: DI | SI | X0},
x86.AMOVSD: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Move},
x86.AMOVSS: {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Move},
x86.ASTOSL: {Flags: gc.OK, Reguse: AX | DI, Regset: DI},
x86.ASTOSQ: {Flags: gc.OK, Reguse: AX | DI, Regset: DI},
x86.ASTOSW: {Flags: gc.OK, Reguse: AX | DI, Regset: DI},
- obj.ADUFFZERO: {Flags: gc.OK, Reguse: AX | DI, Regset: DI},
+ obj.ADUFFZERO: {Flags: gc.OK, Reguse: X0 | DI, Regset: DI},
x86.ASUBB: {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.SetCarry},
x86.ASUBL: {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry},
x86.ASUBQ: {Flags: gc.SizeQ | gc.LeftRead | RightRdwr | gc.SetCarry},
DI = 1 << (x86.REG_DI - x86.REG_AX)
SI = 1 << (x86.REG_SI - x86.REG_AX)
R15 = 1 << (x86.REG_R15 - x86.REG_AX)
+ X0 = 1 << 16
)
func RtoB(r int) uint64 {
gins(arm.AMOVW, &lo1, &al)
gins(arm.AMOVW, &hi1, &ah)
gins(arm.AMOVW, &lo2, &n1)
- gins(optoas(int(n.Op), lo1.Type), &n1, &al)
+ gins(optoas(n.Op, lo1.Type), &n1, &al)
gins(arm.AMOVW, &hi2, &n1)
- gins(optoas(int(n.Op), lo1.Type), &n1, &ah)
+ gins(optoas(n.Op, lo1.Type), &n1, &ah)
gc.Regfree(&n1)
}
* generate comparison of nl, nr, both 64-bit.
* nl is memory; nr is constant or memory.
*/
-func cmp64(nl *gc.Node, nr *gc.Node, op int, likely int, to *obj.Prog) {
+func cmp64(nl *gc.Node, nr *gc.Node, op gc.Op, likely int, to *obj.Prog) {
var lo1 gc.Node
var hi1 gc.Node
var lo2 gc.Node
* res = nl << nr
* res = nl >> nr
*/
-func cgen_shift(op int, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
+func cgen_shift(op gc.Op, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
if nl.Type.Width > 4 {
gc.Fatalf("cgen_shift %v", nl.Type)
}
gc.Regfree(&n2)
}
-func ginscmp(op int, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
+func ginscmp(op gc.Op, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
if gc.Isint[t.Etype] && n1.Op == gc.OLITERAL && n1.Int() == 0 && n2.Op != gc.OLITERAL {
op = gc.Brrev(op)
n1, n2 = n2, n1
/*
* return Axxx for Oxxx on type t.
*/
-func optoas(op int, t *gc.Type) int {
+func optoas(op gc.Op, t *gc.Type) int {
if t == nil {
gc.Fatalf("optoas: t is nil")
}
+ // avoid constant conversions in switches below
+ const (
+ OMINUS_ = uint32(gc.OMINUS) << 16
+ OLSH_ = uint32(gc.OLSH) << 16
+ ORSH_ = uint32(gc.ORSH) << 16
+ OADD_ = uint32(gc.OADD) << 16
+ OSUB_ = uint32(gc.OSUB) << 16
+ OMUL_ = uint32(gc.OMUL) << 16
+ ODIV_ = uint32(gc.ODIV) << 16
+ OMOD_ = uint32(gc.OMOD) << 16
+ OOR_ = uint32(gc.OOR) << 16
+ OAND_ = uint32(gc.OAND) << 16
+ OXOR_ = uint32(gc.OXOR) << 16
+ OEQ_ = uint32(gc.OEQ) << 16
+ ONE_ = uint32(gc.ONE) << 16
+ OLT_ = uint32(gc.OLT) << 16
+ OLE_ = uint32(gc.OLE) << 16
+ OGE_ = uint32(gc.OGE) << 16
+ OGT_ = uint32(gc.OGT) << 16
+ OCMP_ = uint32(gc.OCMP) << 16
+ OPS_ = uint32(gc.OPS) << 16
+ OAS_ = uint32(gc.OAS) << 16
+ OSQRT_ = uint32(gc.OSQRT) << 16
+ )
+
a := obj.AXXX
switch uint32(op)<<16 | uint32(gc.Simtype[t.Etype]) {
default:
break;
*/
// TODO(kaib): make sure the conditional branches work on all edge cases
- case gc.OEQ<<16 | gc.TBOOL,
- gc.OEQ<<16 | gc.TINT8,
- gc.OEQ<<16 | gc.TUINT8,
- gc.OEQ<<16 | gc.TINT16,
- gc.OEQ<<16 | gc.TUINT16,
- gc.OEQ<<16 | gc.TINT32,
- gc.OEQ<<16 | gc.TUINT32,
- gc.OEQ<<16 | gc.TINT64,
- gc.OEQ<<16 | gc.TUINT64,
- gc.OEQ<<16 | gc.TPTR32,
- gc.OEQ<<16 | gc.TPTR64,
- gc.OEQ<<16 | gc.TFLOAT32,
- gc.OEQ<<16 | gc.TFLOAT64:
+ case OEQ_ | gc.TBOOL,
+ OEQ_ | gc.TINT8,
+ OEQ_ | gc.TUINT8,
+ OEQ_ | gc.TINT16,
+ OEQ_ | gc.TUINT16,
+ OEQ_ | gc.TINT32,
+ OEQ_ | gc.TUINT32,
+ OEQ_ | gc.TINT64,
+ OEQ_ | gc.TUINT64,
+ OEQ_ | gc.TPTR32,
+ OEQ_ | gc.TPTR64,
+ OEQ_ | gc.TFLOAT32,
+ OEQ_ | gc.TFLOAT64:
a = arm.ABEQ
- case gc.ONE<<16 | gc.TBOOL,
- gc.ONE<<16 | gc.TINT8,
- gc.ONE<<16 | gc.TUINT8,
- gc.ONE<<16 | gc.TINT16,
- gc.ONE<<16 | gc.TUINT16,
- gc.ONE<<16 | gc.TINT32,
- gc.ONE<<16 | gc.TUINT32,
- gc.ONE<<16 | gc.TINT64,
- gc.ONE<<16 | gc.TUINT64,
- gc.ONE<<16 | gc.TPTR32,
- gc.ONE<<16 | gc.TPTR64,
- gc.ONE<<16 | gc.TFLOAT32,
- gc.ONE<<16 | gc.TFLOAT64:
+ case ONE_ | gc.TBOOL,
+ ONE_ | gc.TINT8,
+ ONE_ | gc.TUINT8,
+ ONE_ | gc.TINT16,
+ ONE_ | gc.TUINT16,
+ ONE_ | gc.TINT32,
+ ONE_ | gc.TUINT32,
+ ONE_ | gc.TINT64,
+ ONE_ | gc.TUINT64,
+ ONE_ | gc.TPTR32,
+ ONE_ | gc.TPTR64,
+ ONE_ | gc.TFLOAT32,
+ ONE_ | gc.TFLOAT64:
a = arm.ABNE
- case gc.OLT<<16 | gc.TINT8,
- gc.OLT<<16 | gc.TINT16,
- gc.OLT<<16 | gc.TINT32,
- gc.OLT<<16 | gc.TINT64,
- gc.OLT<<16 | gc.TFLOAT32,
- gc.OLT<<16 | gc.TFLOAT64:
+ case OLT_ | gc.TINT8,
+ OLT_ | gc.TINT16,
+ OLT_ | gc.TINT32,
+ OLT_ | gc.TINT64,
+ OLT_ | gc.TFLOAT32,
+ OLT_ | gc.TFLOAT64:
a = arm.ABLT
- case gc.OLT<<16 | gc.TUINT8,
- gc.OLT<<16 | gc.TUINT16,
- gc.OLT<<16 | gc.TUINT32,
- gc.OLT<<16 | gc.TUINT64:
+ case OLT_ | gc.TUINT8,
+ OLT_ | gc.TUINT16,
+ OLT_ | gc.TUINT32,
+ OLT_ | gc.TUINT64:
a = arm.ABLO
- case gc.OLE<<16 | gc.TINT8,
- gc.OLE<<16 | gc.TINT16,
- gc.OLE<<16 | gc.TINT32,
- gc.OLE<<16 | gc.TINT64,
- gc.OLE<<16 | gc.TFLOAT32,
- gc.OLE<<16 | gc.TFLOAT64:
+ case OLE_ | gc.TINT8,
+ OLE_ | gc.TINT16,
+ OLE_ | gc.TINT32,
+ OLE_ | gc.TINT64,
+ OLE_ | gc.TFLOAT32,
+ OLE_ | gc.TFLOAT64:
a = arm.ABLE
- case gc.OLE<<16 | gc.TUINT8,
- gc.OLE<<16 | gc.TUINT16,
- gc.OLE<<16 | gc.TUINT32,
- gc.OLE<<16 | gc.TUINT64:
+ case OLE_ | gc.TUINT8,
+ OLE_ | gc.TUINT16,
+ OLE_ | gc.TUINT32,
+ OLE_ | gc.TUINT64:
a = arm.ABLS
- case gc.OGT<<16 | gc.TINT8,
- gc.OGT<<16 | gc.TINT16,
- gc.OGT<<16 | gc.TINT32,
- gc.OGT<<16 | gc.TINT64,
- gc.OGT<<16 | gc.TFLOAT32,
- gc.OGT<<16 | gc.TFLOAT64:
+ case OGT_ | gc.TINT8,
+ OGT_ | gc.TINT16,
+ OGT_ | gc.TINT32,
+ OGT_ | gc.TINT64,
+ OGT_ | gc.TFLOAT32,
+ OGT_ | gc.TFLOAT64:
a = arm.ABGT
- case gc.OGT<<16 | gc.TUINT8,
- gc.OGT<<16 | gc.TUINT16,
- gc.OGT<<16 | gc.TUINT32,
- gc.OGT<<16 | gc.TUINT64:
+ case OGT_ | gc.TUINT8,
+ OGT_ | gc.TUINT16,
+ OGT_ | gc.TUINT32,
+ OGT_ | gc.TUINT64:
a = arm.ABHI
- case gc.OGE<<16 | gc.TINT8,
- gc.OGE<<16 | gc.TINT16,
- gc.OGE<<16 | gc.TINT32,
- gc.OGE<<16 | gc.TINT64,
- gc.OGE<<16 | gc.TFLOAT32,
- gc.OGE<<16 | gc.TFLOAT64:
+ case OGE_ | gc.TINT8,
+ OGE_ | gc.TINT16,
+ OGE_ | gc.TINT32,
+ OGE_ | gc.TINT64,
+ OGE_ | gc.TFLOAT32,
+ OGE_ | gc.TFLOAT64:
a = arm.ABGE
- case gc.OGE<<16 | gc.TUINT8,
- gc.OGE<<16 | gc.TUINT16,
- gc.OGE<<16 | gc.TUINT32,
- gc.OGE<<16 | gc.TUINT64:
+ case OGE_ | gc.TUINT8,
+ OGE_ | gc.TUINT16,
+ OGE_ | gc.TUINT32,
+ OGE_ | gc.TUINT64:
a = arm.ABHS
- case gc.OCMP<<16 | gc.TBOOL,
- gc.OCMP<<16 | gc.TINT8,
- gc.OCMP<<16 | gc.TUINT8,
- gc.OCMP<<16 | gc.TINT16,
- gc.OCMP<<16 | gc.TUINT16,
- gc.OCMP<<16 | gc.TINT32,
- gc.OCMP<<16 | gc.TUINT32,
- gc.OCMP<<16 | gc.TPTR32:
+ case OCMP_ | gc.TBOOL,
+ OCMP_ | gc.TINT8,
+ OCMP_ | gc.TUINT8,
+ OCMP_ | gc.TINT16,
+ OCMP_ | gc.TUINT16,
+ OCMP_ | gc.TINT32,
+ OCMP_ | gc.TUINT32,
+ OCMP_ | gc.TPTR32:
a = arm.ACMP
- case gc.OCMP<<16 | gc.TFLOAT32:
+ case OCMP_ | gc.TFLOAT32:
a = arm.ACMPF
- case gc.OCMP<<16 | gc.TFLOAT64:
+ case OCMP_ | gc.TFLOAT64:
a = arm.ACMPD
- case gc.OPS<<16 | gc.TFLOAT32,
- gc.OPS<<16 | gc.TFLOAT64:
+ case OPS_ | gc.TFLOAT32,
+ OPS_ | gc.TFLOAT64:
a = arm.ABVS
- case gc.OAS<<16 | gc.TBOOL:
+ case OAS_ | gc.TBOOL:
a = arm.AMOVB
- case gc.OAS<<16 | gc.TINT8:
+ case OAS_ | gc.TINT8:
a = arm.AMOVBS
- case gc.OAS<<16 | gc.TUINT8:
+ case OAS_ | gc.TUINT8:
a = arm.AMOVBU
- case gc.OAS<<16 | gc.TINT16:
+ case OAS_ | gc.TINT16:
a = arm.AMOVHS
- case gc.OAS<<16 | gc.TUINT16:
+ case OAS_ | gc.TUINT16:
a = arm.AMOVHU
- case gc.OAS<<16 | gc.TINT32,
- gc.OAS<<16 | gc.TUINT32,
- gc.OAS<<16 | gc.TPTR32:
+ case OAS_ | gc.TINT32,
+ OAS_ | gc.TUINT32,
+ OAS_ | gc.TPTR32:
a = arm.AMOVW
- case gc.OAS<<16 | gc.TFLOAT32:
+ case OAS_ | gc.TFLOAT32:
a = arm.AMOVF
- case gc.OAS<<16 | gc.TFLOAT64:
+ case OAS_ | gc.TFLOAT64:
a = arm.AMOVD
- case gc.OADD<<16 | gc.TINT8,
- gc.OADD<<16 | gc.TUINT8,
- gc.OADD<<16 | gc.TINT16,
- gc.OADD<<16 | gc.TUINT16,
- gc.OADD<<16 | gc.TINT32,
- gc.OADD<<16 | gc.TUINT32,
- gc.OADD<<16 | gc.TPTR32:
+ case OADD_ | gc.TINT8,
+ OADD_ | gc.TUINT8,
+ OADD_ | gc.TINT16,
+ OADD_ | gc.TUINT16,
+ OADD_ | gc.TINT32,
+ OADD_ | gc.TUINT32,
+ OADD_ | gc.TPTR32:
a = arm.AADD
- case gc.OADD<<16 | gc.TFLOAT32:
+ case OADD_ | gc.TFLOAT32:
a = arm.AADDF
- case gc.OADD<<16 | gc.TFLOAT64:
+ case OADD_ | gc.TFLOAT64:
a = arm.AADDD
- case gc.OSUB<<16 | gc.TINT8,
- gc.OSUB<<16 | gc.TUINT8,
- gc.OSUB<<16 | gc.TINT16,
- gc.OSUB<<16 | gc.TUINT16,
- gc.OSUB<<16 | gc.TINT32,
- gc.OSUB<<16 | gc.TUINT32,
- gc.OSUB<<16 | gc.TPTR32:
+ case OSUB_ | gc.TINT8,
+ OSUB_ | gc.TUINT8,
+ OSUB_ | gc.TINT16,
+ OSUB_ | gc.TUINT16,
+ OSUB_ | gc.TINT32,
+ OSUB_ | gc.TUINT32,
+ OSUB_ | gc.TPTR32:
a = arm.ASUB
- case gc.OSUB<<16 | gc.TFLOAT32:
+ case OSUB_ | gc.TFLOAT32:
a = arm.ASUBF
- case gc.OSUB<<16 | gc.TFLOAT64:
+ case OSUB_ | gc.TFLOAT64:
a = arm.ASUBD
- case gc.OMINUS<<16 | gc.TINT8,
- gc.OMINUS<<16 | gc.TUINT8,
- gc.OMINUS<<16 | gc.TINT16,
- gc.OMINUS<<16 | gc.TUINT16,
- gc.OMINUS<<16 | gc.TINT32,
- gc.OMINUS<<16 | gc.TUINT32,
- gc.OMINUS<<16 | gc.TPTR32:
+ case OMINUS_ | gc.TINT8,
+ OMINUS_ | gc.TUINT8,
+ OMINUS_ | gc.TINT16,
+ OMINUS_ | gc.TUINT16,
+ OMINUS_ | gc.TINT32,
+ OMINUS_ | gc.TUINT32,
+ OMINUS_ | gc.TPTR32:
a = arm.ARSB
- case gc.OAND<<16 | gc.TINT8,
- gc.OAND<<16 | gc.TUINT8,
- gc.OAND<<16 | gc.TINT16,
- gc.OAND<<16 | gc.TUINT16,
- gc.OAND<<16 | gc.TINT32,
- gc.OAND<<16 | gc.TUINT32,
- gc.OAND<<16 | gc.TPTR32:
+ case OAND_ | gc.TINT8,
+ OAND_ | gc.TUINT8,
+ OAND_ | gc.TINT16,
+ OAND_ | gc.TUINT16,
+ OAND_ | gc.TINT32,
+ OAND_ | gc.TUINT32,
+ OAND_ | gc.TPTR32:
a = arm.AAND
- case gc.OOR<<16 | gc.TINT8,
- gc.OOR<<16 | gc.TUINT8,
- gc.OOR<<16 | gc.TINT16,
- gc.OOR<<16 | gc.TUINT16,
- gc.OOR<<16 | gc.TINT32,
- gc.OOR<<16 | gc.TUINT32,
- gc.OOR<<16 | gc.TPTR32:
+ case OOR_ | gc.TINT8,
+ OOR_ | gc.TUINT8,
+ OOR_ | gc.TINT16,
+ OOR_ | gc.TUINT16,
+ OOR_ | gc.TINT32,
+ OOR_ | gc.TUINT32,
+ OOR_ | gc.TPTR32:
a = arm.AORR
- case gc.OXOR<<16 | gc.TINT8,
- gc.OXOR<<16 | gc.TUINT8,
- gc.OXOR<<16 | gc.TINT16,
- gc.OXOR<<16 | gc.TUINT16,
- gc.OXOR<<16 | gc.TINT32,
- gc.OXOR<<16 | gc.TUINT32,
- gc.OXOR<<16 | gc.TPTR32:
+ case OXOR_ | gc.TINT8,
+ OXOR_ | gc.TUINT8,
+ OXOR_ | gc.TINT16,
+ OXOR_ | gc.TUINT16,
+ OXOR_ | gc.TINT32,
+ OXOR_ | gc.TUINT32,
+ OXOR_ | gc.TPTR32:
a = arm.AEOR
- case gc.OLSH<<16 | gc.TINT8,
- gc.OLSH<<16 | gc.TUINT8,
- gc.OLSH<<16 | gc.TINT16,
- gc.OLSH<<16 | gc.TUINT16,
- gc.OLSH<<16 | gc.TINT32,
- gc.OLSH<<16 | gc.TUINT32,
- gc.OLSH<<16 | gc.TPTR32:
+ case OLSH_ | gc.TINT8,
+ OLSH_ | gc.TUINT8,
+ OLSH_ | gc.TINT16,
+ OLSH_ | gc.TUINT16,
+ OLSH_ | gc.TINT32,
+ OLSH_ | gc.TUINT32,
+ OLSH_ | gc.TPTR32:
a = arm.ASLL
- case gc.ORSH<<16 | gc.TUINT8,
- gc.ORSH<<16 | gc.TUINT16,
- gc.ORSH<<16 | gc.TUINT32,
- gc.ORSH<<16 | gc.TPTR32:
+ case ORSH_ | gc.TUINT8,
+ ORSH_ | gc.TUINT16,
+ ORSH_ | gc.TUINT32,
+ ORSH_ | gc.TPTR32:
a = arm.ASRL
- case gc.ORSH<<16 | gc.TINT8,
- gc.ORSH<<16 | gc.TINT16,
- gc.ORSH<<16 | gc.TINT32:
+ case ORSH_ | gc.TINT8,
+ ORSH_ | gc.TINT16,
+ ORSH_ | gc.TINT32:
a = arm.ASRA
- case gc.OMUL<<16 | gc.TUINT8,
- gc.OMUL<<16 | gc.TUINT16,
- gc.OMUL<<16 | gc.TUINT32,
- gc.OMUL<<16 | gc.TPTR32:
+ case OMUL_ | gc.TUINT8,
+ OMUL_ | gc.TUINT16,
+ OMUL_ | gc.TUINT32,
+ OMUL_ | gc.TPTR32:
a = arm.AMULU
- case gc.OMUL<<16 | gc.TINT8,
- gc.OMUL<<16 | gc.TINT16,
- gc.OMUL<<16 | gc.TINT32:
+ case OMUL_ | gc.TINT8,
+ OMUL_ | gc.TINT16,
+ OMUL_ | gc.TINT32:
a = arm.AMUL
- case gc.OMUL<<16 | gc.TFLOAT32:
+ case OMUL_ | gc.TFLOAT32:
a = arm.AMULF
- case gc.OMUL<<16 | gc.TFLOAT64:
+ case OMUL_ | gc.TFLOAT64:
a = arm.AMULD
- case gc.ODIV<<16 | gc.TUINT8,
- gc.ODIV<<16 | gc.TUINT16,
- gc.ODIV<<16 | gc.TUINT32,
- gc.ODIV<<16 | gc.TPTR32:
+ case ODIV_ | gc.TUINT8,
+ ODIV_ | gc.TUINT16,
+ ODIV_ | gc.TUINT32,
+ ODIV_ | gc.TPTR32:
a = arm.ADIVU
- case gc.ODIV<<16 | gc.TINT8,
- gc.ODIV<<16 | gc.TINT16,
- gc.ODIV<<16 | gc.TINT32:
+ case ODIV_ | gc.TINT8,
+ ODIV_ | gc.TINT16,
+ ODIV_ | gc.TINT32:
a = arm.ADIV
- case gc.OMOD<<16 | gc.TUINT8,
- gc.OMOD<<16 | gc.TUINT16,
- gc.OMOD<<16 | gc.TUINT32,
- gc.OMOD<<16 | gc.TPTR32:
+ case OMOD_ | gc.TUINT8,
+ OMOD_ | gc.TUINT16,
+ OMOD_ | gc.TUINT32,
+ OMOD_ | gc.TPTR32:
a = arm.AMODU
- case gc.OMOD<<16 | gc.TINT8,
- gc.OMOD<<16 | gc.TINT16,
- gc.OMOD<<16 | gc.TINT32:
+ case OMOD_ | gc.TINT8,
+ OMOD_ | gc.TINT16,
+ OMOD_ | gc.TINT32:
a = arm.AMOD
// case CASE(OEXTEND, TINT16):
// a = ACQO;
// break;
- case gc.ODIV<<16 | gc.TFLOAT32:
+ case ODIV_ | gc.TFLOAT32:
a = arm.ADIVF
- case gc.ODIV<<16 | gc.TFLOAT64:
+ case ODIV_ | gc.TFLOAT64:
a = arm.ADIVD
- case gc.OSQRT<<16 | gc.TFLOAT64:
+ case OSQRT_ | gc.TFLOAT64:
a = arm.ASQRTD
}
* res = nl % nr
* according to op.
*/
-func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
+func dodiv(op gc.Op, nl *gc.Node, nr *gc.Node, res *gc.Node) {
// Have to be careful about handling
// most negative int divided by -1 correctly.
// The hardware will generate undefined result.
* res = nl << nr
* res = nl >> nr
*/
-func cgen_shift(op int, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
+func cgen_shift(op gc.Op, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
a := int(optoas(op, nl.Type))
if nr.Op == gc.OLITERAL {
gc.Regfree(&ntmp)
}
-func ginscmp(op int, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
+func ginscmp(op gc.Op, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
if gc.Isint[t.Etype] && n1.Op == gc.OLITERAL && n2.Op != gc.OLITERAL {
// Reverse comparison to place constant last.
op = gc.Brrev(op)
/*
* return Axxx for Oxxx on type t.
*/
-func optoas(op int, t *gc.Type) int {
+func optoas(op gc.Op, t *gc.Type) int {
if t == nil {
gc.Fatalf("optoas: t is nil")
}
+ // avoid constant conversions in switches below
+ const (
+ OMINUS_ = uint32(gc.OMINUS) << 16
+ OLSH_ = uint32(gc.OLSH) << 16
+ ORSH_ = uint32(gc.ORSH) << 16
+ OADD_ = uint32(gc.OADD) << 16
+ OSUB_ = uint32(gc.OSUB) << 16
+ OMUL_ = uint32(gc.OMUL) << 16
+ ODIV_ = uint32(gc.ODIV) << 16
+ OOR_ = uint32(gc.OOR) << 16
+ OAND_ = uint32(gc.OAND) << 16
+ OXOR_ = uint32(gc.OXOR) << 16
+ OEQ_ = uint32(gc.OEQ) << 16
+ ONE_ = uint32(gc.ONE) << 16
+ OLT_ = uint32(gc.OLT) << 16
+ OLE_ = uint32(gc.OLE) << 16
+ OGE_ = uint32(gc.OGE) << 16
+ OGT_ = uint32(gc.OGT) << 16
+ OCMP_ = uint32(gc.OCMP) << 16
+ OAS_ = uint32(gc.OAS) << 16
+ OHMUL_ = uint32(gc.OHMUL) << 16
+ OSQRT_ = uint32(gc.OSQRT) << 16
+ )
+
a := int(obj.AXXX)
switch uint32(op)<<16 | uint32(gc.Simtype[t.Etype]) {
default:
gc.Fatalf("optoas: no entry for op=%v type=%v", gc.Oconv(int(op), 0), t)
- case gc.OEQ<<16 | gc.TBOOL,
- gc.OEQ<<16 | gc.TINT8,
- gc.OEQ<<16 | gc.TUINT8,
- gc.OEQ<<16 | gc.TINT16,
- gc.OEQ<<16 | gc.TUINT16,
- gc.OEQ<<16 | gc.TINT32,
- gc.OEQ<<16 | gc.TUINT32,
- gc.OEQ<<16 | gc.TINT64,
- gc.OEQ<<16 | gc.TUINT64,
- gc.OEQ<<16 | gc.TPTR32,
- gc.OEQ<<16 | gc.TPTR64,
- gc.OEQ<<16 | gc.TFLOAT32,
- gc.OEQ<<16 | gc.TFLOAT64:
+ case OEQ_ | gc.TBOOL,
+ OEQ_ | gc.TINT8,
+ OEQ_ | gc.TUINT8,
+ OEQ_ | gc.TINT16,
+ OEQ_ | gc.TUINT16,
+ OEQ_ | gc.TINT32,
+ OEQ_ | gc.TUINT32,
+ OEQ_ | gc.TINT64,
+ OEQ_ | gc.TUINT64,
+ OEQ_ | gc.TPTR32,
+ OEQ_ | gc.TPTR64,
+ OEQ_ | gc.TFLOAT32,
+ OEQ_ | gc.TFLOAT64:
a = arm64.ABEQ
- case gc.ONE<<16 | gc.TBOOL,
- gc.ONE<<16 | gc.TINT8,
- gc.ONE<<16 | gc.TUINT8,
- gc.ONE<<16 | gc.TINT16,
- gc.ONE<<16 | gc.TUINT16,
- gc.ONE<<16 | gc.TINT32,
- gc.ONE<<16 | gc.TUINT32,
- gc.ONE<<16 | gc.TINT64,
- gc.ONE<<16 | gc.TUINT64,
- gc.ONE<<16 | gc.TPTR32,
- gc.ONE<<16 | gc.TPTR64,
- gc.ONE<<16 | gc.TFLOAT32,
- gc.ONE<<16 | gc.TFLOAT64:
+ case ONE_ | gc.TBOOL,
+ ONE_ | gc.TINT8,
+ ONE_ | gc.TUINT8,
+ ONE_ | gc.TINT16,
+ ONE_ | gc.TUINT16,
+ ONE_ | gc.TINT32,
+ ONE_ | gc.TUINT32,
+ ONE_ | gc.TINT64,
+ ONE_ | gc.TUINT64,
+ ONE_ | gc.TPTR32,
+ ONE_ | gc.TPTR64,
+ ONE_ | gc.TFLOAT32,
+ ONE_ | gc.TFLOAT64:
a = arm64.ABNE
- case gc.OLT<<16 | gc.TINT8,
- gc.OLT<<16 | gc.TINT16,
- gc.OLT<<16 | gc.TINT32,
- gc.OLT<<16 | gc.TINT64:
+ case OLT_ | gc.TINT8,
+ OLT_ | gc.TINT16,
+ OLT_ | gc.TINT32,
+ OLT_ | gc.TINT64:
a = arm64.ABLT
- case gc.OLT<<16 | gc.TUINT8,
- gc.OLT<<16 | gc.TUINT16,
- gc.OLT<<16 | gc.TUINT32,
- gc.OLT<<16 | gc.TUINT64,
- gc.OLT<<16 | gc.TFLOAT32,
- gc.OLT<<16 | gc.TFLOAT64:
+ case OLT_ | gc.TUINT8,
+ OLT_ | gc.TUINT16,
+ OLT_ | gc.TUINT32,
+ OLT_ | gc.TUINT64,
+ OLT_ | gc.TFLOAT32,
+ OLT_ | gc.TFLOAT64:
a = arm64.ABLO
- case gc.OLE<<16 | gc.TINT8,
- gc.OLE<<16 | gc.TINT16,
- gc.OLE<<16 | gc.TINT32,
- gc.OLE<<16 | gc.TINT64:
+ case OLE_ | gc.TINT8,
+ OLE_ | gc.TINT16,
+ OLE_ | gc.TINT32,
+ OLE_ | gc.TINT64:
a = arm64.ABLE
- case gc.OLE<<16 | gc.TUINT8,
- gc.OLE<<16 | gc.TUINT16,
- gc.OLE<<16 | gc.TUINT32,
- gc.OLE<<16 | gc.TUINT64,
- gc.OLE<<16 | gc.TFLOAT32,
- gc.OLE<<16 | gc.TFLOAT64:
+ case OLE_ | gc.TUINT8,
+ OLE_ | gc.TUINT16,
+ OLE_ | gc.TUINT32,
+ OLE_ | gc.TUINT64,
+ OLE_ | gc.TFLOAT32,
+ OLE_ | gc.TFLOAT64:
a = arm64.ABLS
- case gc.OGT<<16 | gc.TINT8,
- gc.OGT<<16 | gc.TINT16,
- gc.OGT<<16 | gc.TINT32,
- gc.OGT<<16 | gc.TINT64,
- gc.OGT<<16 | gc.TFLOAT32,
- gc.OGT<<16 | gc.TFLOAT64:
+ case OGT_ | gc.TINT8,
+ OGT_ | gc.TINT16,
+ OGT_ | gc.TINT32,
+ OGT_ | gc.TINT64,
+ OGT_ | gc.TFLOAT32,
+ OGT_ | gc.TFLOAT64:
a = arm64.ABGT
- case gc.OGT<<16 | gc.TUINT8,
- gc.OGT<<16 | gc.TUINT16,
- gc.OGT<<16 | gc.TUINT32,
- gc.OGT<<16 | gc.TUINT64:
+ case OGT_ | gc.TUINT8,
+ OGT_ | gc.TUINT16,
+ OGT_ | gc.TUINT32,
+ OGT_ | gc.TUINT64:
a = arm64.ABHI
- case gc.OGE<<16 | gc.TINT8,
- gc.OGE<<16 | gc.TINT16,
- gc.OGE<<16 | gc.TINT32,
- gc.OGE<<16 | gc.TINT64,
- gc.OGE<<16 | gc.TFLOAT32,
- gc.OGE<<16 | gc.TFLOAT64:
+ case OGE_ | gc.TINT8,
+ OGE_ | gc.TINT16,
+ OGE_ | gc.TINT32,
+ OGE_ | gc.TINT64,
+ OGE_ | gc.TFLOAT32,
+ OGE_ | gc.TFLOAT64:
a = arm64.ABGE
- case gc.OGE<<16 | gc.TUINT8,
- gc.OGE<<16 | gc.TUINT16,
- gc.OGE<<16 | gc.TUINT32,
- gc.OGE<<16 | gc.TUINT64:
+ case OGE_ | gc.TUINT8,
+ OGE_ | gc.TUINT16,
+ OGE_ | gc.TUINT32,
+ OGE_ | gc.TUINT64:
a = arm64.ABHS
- case gc.OCMP<<16 | gc.TBOOL,
- gc.OCMP<<16 | gc.TINT8,
- gc.OCMP<<16 | gc.TINT16,
- gc.OCMP<<16 | gc.TINT32,
- gc.OCMP<<16 | gc.TPTR32,
- gc.OCMP<<16 | gc.TINT64,
- gc.OCMP<<16 | gc.TUINT8,
- gc.OCMP<<16 | gc.TUINT16,
- gc.OCMP<<16 | gc.TUINT32,
- gc.OCMP<<16 | gc.TUINT64,
- gc.OCMP<<16 | gc.TPTR64:
+ case OCMP_ | gc.TBOOL,
+ OCMP_ | gc.TINT8,
+ OCMP_ | gc.TINT16,
+ OCMP_ | gc.TINT32,
+ OCMP_ | gc.TPTR32,
+ OCMP_ | gc.TINT64,
+ OCMP_ | gc.TUINT8,
+ OCMP_ | gc.TUINT16,
+ OCMP_ | gc.TUINT32,
+ OCMP_ | gc.TUINT64,
+ OCMP_ | gc.TPTR64:
a = arm64.ACMP
- case gc.OCMP<<16 | gc.TFLOAT32:
+ case OCMP_ | gc.TFLOAT32:
a = arm64.AFCMPS
- case gc.OCMP<<16 | gc.TFLOAT64:
+ case OCMP_ | gc.TFLOAT64:
a = arm64.AFCMPD
- case gc.OAS<<16 | gc.TBOOL,
- gc.OAS<<16 | gc.TINT8:
+ case OAS_ | gc.TBOOL,
+ OAS_ | gc.TINT8:
a = arm64.AMOVB
- case gc.OAS<<16 | gc.TUINT8:
+ case OAS_ | gc.TUINT8:
a = arm64.AMOVBU
- case gc.OAS<<16 | gc.TINT16:
+ case OAS_ | gc.TINT16:
a = arm64.AMOVH
- case gc.OAS<<16 | gc.TUINT16:
+ case OAS_ | gc.TUINT16:
a = arm64.AMOVHU
- case gc.OAS<<16 | gc.TINT32:
+ case OAS_ | gc.TINT32:
a = arm64.AMOVW
- case gc.OAS<<16 | gc.TUINT32,
- gc.OAS<<16 | gc.TPTR32:
+ case OAS_ | gc.TUINT32,
+ OAS_ | gc.TPTR32:
a = arm64.AMOVWU
- case gc.OAS<<16 | gc.TINT64,
- gc.OAS<<16 | gc.TUINT64,
- gc.OAS<<16 | gc.TPTR64:
+ case OAS_ | gc.TINT64,
+ OAS_ | gc.TUINT64,
+ OAS_ | gc.TPTR64:
a = arm64.AMOVD
- case gc.OAS<<16 | gc.TFLOAT32:
+ case OAS_ | gc.TFLOAT32:
a = arm64.AFMOVS
- case gc.OAS<<16 | gc.TFLOAT64:
+ case OAS_ | gc.TFLOAT64:
a = arm64.AFMOVD
- case gc.OADD<<16 | gc.TINT8,
- gc.OADD<<16 | gc.TUINT8,
- gc.OADD<<16 | gc.TINT16,
- gc.OADD<<16 | gc.TUINT16,
- gc.OADD<<16 | gc.TINT32,
- gc.OADD<<16 | gc.TUINT32,
- gc.OADD<<16 | gc.TPTR32,
- gc.OADD<<16 | gc.TINT64,
- gc.OADD<<16 | gc.TUINT64,
- gc.OADD<<16 | gc.TPTR64:
+ case OADD_ | gc.TINT8,
+ OADD_ | gc.TUINT8,
+ OADD_ | gc.TINT16,
+ OADD_ | gc.TUINT16,
+ OADD_ | gc.TINT32,
+ OADD_ | gc.TUINT32,
+ OADD_ | gc.TPTR32,
+ OADD_ | gc.TINT64,
+ OADD_ | gc.TUINT64,
+ OADD_ | gc.TPTR64:
a = arm64.AADD
- case gc.OADD<<16 | gc.TFLOAT32:
+ case OADD_ | gc.TFLOAT32:
a = arm64.AFADDS
- case gc.OADD<<16 | gc.TFLOAT64:
+ case OADD_ | gc.TFLOAT64:
a = arm64.AFADDD
- case gc.OSUB<<16 | gc.TINT8,
- gc.OSUB<<16 | gc.TUINT8,
- gc.OSUB<<16 | gc.TINT16,
- gc.OSUB<<16 | gc.TUINT16,
- gc.OSUB<<16 | gc.TINT32,
- gc.OSUB<<16 | gc.TUINT32,
- gc.OSUB<<16 | gc.TPTR32,
- gc.OSUB<<16 | gc.TINT64,
- gc.OSUB<<16 | gc.TUINT64,
- gc.OSUB<<16 | gc.TPTR64:
+ case OSUB_ | gc.TINT8,
+ OSUB_ | gc.TUINT8,
+ OSUB_ | gc.TINT16,
+ OSUB_ | gc.TUINT16,
+ OSUB_ | gc.TINT32,
+ OSUB_ | gc.TUINT32,
+ OSUB_ | gc.TPTR32,
+ OSUB_ | gc.TINT64,
+ OSUB_ | gc.TUINT64,
+ OSUB_ | gc.TPTR64:
a = arm64.ASUB
- case gc.OSUB<<16 | gc.TFLOAT32:
+ case OSUB_ | gc.TFLOAT32:
a = arm64.AFSUBS
- case gc.OSUB<<16 | gc.TFLOAT64:
+ case OSUB_ | gc.TFLOAT64:
a = arm64.AFSUBD
- case gc.OMINUS<<16 | gc.TINT8,
- gc.OMINUS<<16 | gc.TUINT8,
- gc.OMINUS<<16 | gc.TINT16,
- gc.OMINUS<<16 | gc.TUINT16,
- gc.OMINUS<<16 | gc.TINT32,
- gc.OMINUS<<16 | gc.TUINT32,
- gc.OMINUS<<16 | gc.TPTR32,
- gc.OMINUS<<16 | gc.TINT64,
- gc.OMINUS<<16 | gc.TUINT64,
- gc.OMINUS<<16 | gc.TPTR64:
+ case OMINUS_ | gc.TINT8,
+ OMINUS_ | gc.TUINT8,
+ OMINUS_ | gc.TINT16,
+ OMINUS_ | gc.TUINT16,
+ OMINUS_ | gc.TINT32,
+ OMINUS_ | gc.TUINT32,
+ OMINUS_ | gc.TPTR32,
+ OMINUS_ | gc.TINT64,
+ OMINUS_ | gc.TUINT64,
+ OMINUS_ | gc.TPTR64:
a = arm64.ANEG
- case gc.OMINUS<<16 | gc.TFLOAT32:
+ case OMINUS_ | gc.TFLOAT32:
a = arm64.AFNEGS
- case gc.OMINUS<<16 | gc.TFLOAT64:
+ case OMINUS_ | gc.TFLOAT64:
a = arm64.AFNEGD
- case gc.OAND<<16 | gc.TINT8,
- gc.OAND<<16 | gc.TUINT8,
- gc.OAND<<16 | gc.TINT16,
- gc.OAND<<16 | gc.TUINT16,
- gc.OAND<<16 | gc.TINT32,
- gc.OAND<<16 | gc.TUINT32,
- gc.OAND<<16 | gc.TPTR32,
- gc.OAND<<16 | gc.TINT64,
- gc.OAND<<16 | gc.TUINT64,
- gc.OAND<<16 | gc.TPTR64:
+ case OAND_ | gc.TINT8,
+ OAND_ | gc.TUINT8,
+ OAND_ | gc.TINT16,
+ OAND_ | gc.TUINT16,
+ OAND_ | gc.TINT32,
+ OAND_ | gc.TUINT32,
+ OAND_ | gc.TPTR32,
+ OAND_ | gc.TINT64,
+ OAND_ | gc.TUINT64,
+ OAND_ | gc.TPTR64:
a = arm64.AAND
- case gc.OOR<<16 | gc.TINT8,
- gc.OOR<<16 | gc.TUINT8,
- gc.OOR<<16 | gc.TINT16,
- gc.OOR<<16 | gc.TUINT16,
- gc.OOR<<16 | gc.TINT32,
- gc.OOR<<16 | gc.TUINT32,
- gc.OOR<<16 | gc.TPTR32,
- gc.OOR<<16 | gc.TINT64,
- gc.OOR<<16 | gc.TUINT64,
- gc.OOR<<16 | gc.TPTR64:
+ case OOR_ | gc.TINT8,
+ OOR_ | gc.TUINT8,
+ OOR_ | gc.TINT16,
+ OOR_ | gc.TUINT16,
+ OOR_ | gc.TINT32,
+ OOR_ | gc.TUINT32,
+ OOR_ | gc.TPTR32,
+ OOR_ | gc.TINT64,
+ OOR_ | gc.TUINT64,
+ OOR_ | gc.TPTR64:
a = arm64.AORR
- case gc.OXOR<<16 | gc.TINT8,
- gc.OXOR<<16 | gc.TUINT8,
- gc.OXOR<<16 | gc.TINT16,
- gc.OXOR<<16 | gc.TUINT16,
- gc.OXOR<<16 | gc.TINT32,
- gc.OXOR<<16 | gc.TUINT32,
- gc.OXOR<<16 | gc.TPTR32,
- gc.OXOR<<16 | gc.TINT64,
- gc.OXOR<<16 | gc.TUINT64,
- gc.OXOR<<16 | gc.TPTR64:
+ case OXOR_ | gc.TINT8,
+ OXOR_ | gc.TUINT8,
+ OXOR_ | gc.TINT16,
+ OXOR_ | gc.TUINT16,
+ OXOR_ | gc.TINT32,
+ OXOR_ | gc.TUINT32,
+ OXOR_ | gc.TPTR32,
+ OXOR_ | gc.TINT64,
+ OXOR_ | gc.TUINT64,
+ OXOR_ | gc.TPTR64:
a = arm64.AEOR
// TODO(minux): handle rotates
// a = 0//???; RLDC?
// break;
- case gc.OLSH<<16 | gc.TINT8,
- gc.OLSH<<16 | gc.TUINT8,
- gc.OLSH<<16 | gc.TINT16,
- gc.OLSH<<16 | gc.TUINT16,
- gc.OLSH<<16 | gc.TINT32,
- gc.OLSH<<16 | gc.TUINT32,
- gc.OLSH<<16 | gc.TPTR32,
- gc.OLSH<<16 | gc.TINT64,
- gc.OLSH<<16 | gc.TUINT64,
- gc.OLSH<<16 | gc.TPTR64:
+ case OLSH_ | gc.TINT8,
+ OLSH_ | gc.TUINT8,
+ OLSH_ | gc.TINT16,
+ OLSH_ | gc.TUINT16,
+ OLSH_ | gc.TINT32,
+ OLSH_ | gc.TUINT32,
+ OLSH_ | gc.TPTR32,
+ OLSH_ | gc.TINT64,
+ OLSH_ | gc.TUINT64,
+ OLSH_ | gc.TPTR64:
a = arm64.ALSL
- case gc.ORSH<<16 | gc.TUINT8,
- gc.ORSH<<16 | gc.TUINT16,
- gc.ORSH<<16 | gc.TUINT32,
- gc.ORSH<<16 | gc.TPTR32,
- gc.ORSH<<16 | gc.TUINT64,
- gc.ORSH<<16 | gc.TPTR64:
+ case ORSH_ | gc.TUINT8,
+ ORSH_ | gc.TUINT16,
+ ORSH_ | gc.TUINT32,
+ ORSH_ | gc.TPTR32,
+ ORSH_ | gc.TUINT64,
+ ORSH_ | gc.TPTR64:
a = arm64.ALSR
- case gc.ORSH<<16 | gc.TINT8,
- gc.ORSH<<16 | gc.TINT16,
- gc.ORSH<<16 | gc.TINT32,
- gc.ORSH<<16 | gc.TINT64:
+ case ORSH_ | gc.TINT8,
+ ORSH_ | gc.TINT16,
+ ORSH_ | gc.TINT32,
+ ORSH_ | gc.TINT64:
a = arm64.AASR
// TODO(minux): handle rotates
// a = 0//??? RLDC??
// break;
- case gc.OHMUL<<16 | gc.TINT64:
+ case OHMUL_ | gc.TINT64:
a = arm64.ASMULH
- case gc.OHMUL<<16 | gc.TUINT64,
- gc.OHMUL<<16 | gc.TPTR64:
+ case OHMUL_ | gc.TUINT64,
+ OHMUL_ | gc.TPTR64:
a = arm64.AUMULH
- case gc.OMUL<<16 | gc.TINT8,
- gc.OMUL<<16 | gc.TINT16,
- gc.OMUL<<16 | gc.TINT32:
+ case OMUL_ | gc.TINT8,
+ OMUL_ | gc.TINT16,
+ OMUL_ | gc.TINT32:
a = arm64.ASMULL
- case gc.OMUL<<16 | gc.TINT64:
+ case OMUL_ | gc.TINT64:
a = arm64.AMUL
- case gc.OMUL<<16 | gc.TUINT8,
- gc.OMUL<<16 | gc.TUINT16,
- gc.OMUL<<16 | gc.TUINT32,
- gc.OMUL<<16 | gc.TPTR32:
+ case OMUL_ | gc.TUINT8,
+ OMUL_ | gc.TUINT16,
+ OMUL_ | gc.TUINT32,
+ OMUL_ | gc.TPTR32:
// don't use word multiply, the high 32-bit are undefined.
a = arm64.AUMULL
- case gc.OMUL<<16 | gc.TUINT64,
- gc.OMUL<<16 | gc.TPTR64:
+ case OMUL_ | gc.TUINT64,
+ OMUL_ | gc.TPTR64:
a = arm64.AMUL // for 64-bit multiplies, signedness doesn't matter.
- case gc.OMUL<<16 | gc.TFLOAT32:
+ case OMUL_ | gc.TFLOAT32:
a = arm64.AFMULS
- case gc.OMUL<<16 | gc.TFLOAT64:
+ case OMUL_ | gc.TFLOAT64:
a = arm64.AFMULD
- case gc.ODIV<<16 | gc.TINT8,
- gc.ODIV<<16 | gc.TINT16,
- gc.ODIV<<16 | gc.TINT32,
- gc.ODIV<<16 | gc.TINT64:
+ case ODIV_ | gc.TINT8,
+ ODIV_ | gc.TINT16,
+ ODIV_ | gc.TINT32,
+ ODIV_ | gc.TINT64:
a = arm64.ASDIV
- case gc.ODIV<<16 | gc.TUINT8,
- gc.ODIV<<16 | gc.TUINT16,
- gc.ODIV<<16 | gc.TUINT32,
- gc.ODIV<<16 | gc.TPTR32,
- gc.ODIV<<16 | gc.TUINT64,
- gc.ODIV<<16 | gc.TPTR64:
+ case ODIV_ | gc.TUINT8,
+ ODIV_ | gc.TUINT16,
+ ODIV_ | gc.TUINT32,
+ ODIV_ | gc.TPTR32,
+ ODIV_ | gc.TUINT64,
+ ODIV_ | gc.TPTR64:
a = arm64.AUDIV
- case gc.ODIV<<16 | gc.TFLOAT32:
+ case ODIV_ | gc.TFLOAT32:
a = arm64.AFDIVS
- case gc.ODIV<<16 | gc.TFLOAT64:
+ case ODIV_ | gc.TFLOAT64:
a = arm64.AFDIVD
- case gc.OSQRT<<16 | gc.TFLOAT64:
+ case OSQRT_ | gc.TFLOAT64:
a = arm64.AFSQRTD
}
import "cmd/internal/obj"
-/*
- * machine size and rounding
- * alignment is dictated around
- * the size of a pointer, set in betypeinit
- * (see ../6g/galign.c).
- */
+// machine size and rounding alignment is dictated around
+// the size of a pointer, set in betypeinit (see ../amd64/galign.go).
var defercalc int
func Rnd(o int64, r int64) int64 {
f.Width = o // really offset for TFIELD
if f.Nname != nil {
// this same stackparam logic is in addrescapes
- // in typecheck.c. usually addrescapes runs after
+ // in typecheck.go. usually addrescapes runs after
// widstruct, in which case we could drop this,
// but function closure functions are the exception.
if f.Nname.Name.Param.Stackparam != nil {
t.Width = -2
t.Align = 0
- et := int32(t.Etype)
+ et := t.Etype
switch et {
case TFUNC, TCHAN, TMAP, TSTRING:
break
- /* simtype == 0 during bootstrap */
+ // simtype == 0 during bootstrap
default:
if Simtype[t.Etype] != 0 {
- et = int32(Simtype[t.Etype])
+ et = Simtype[t.Etype]
}
}
default:
Fatalf("dowidth: unknown type: %v", t)
- /* compiler-specific stuff */
+ // compiler-specific stuff
case TINT8, TUINT8, TBOOL:
// bool is int8
w = 1
}
w = 1 // anything will do
- // dummy type; should be replaced before use.
+ // dummy type; should be replaced before use.
case TANY:
if Debug['A'] == 0 {
Fatalf("dowidth any")
}
w = widstruct(t, t, 0, 1)
- // make fake type to check later to
+ // make fake type to check later to
// trigger function argument computation.
case TFUNC:
t1 := typ(TFUNCARGS)
// width of func type is pointer
w = int64(Widthptr)
- // function is 3 cated structures;
+ // function is 3 cated structures;
// compute their widths as side-effect.
case TFUNCARGS:
t1 := t.Type
}
}
-/*
- * when a type's width should be known, we call checkwidth
- * to compute it. during a declaration like
- *
- * type T *struct { next T }
- *
- * it is necessary to defer the calculation of the struct width
- * until after T has been initialized to be a pointer to that struct.
- * similarly, during import processing structs may be used
- * before their definition. in those situations, calling
- * defercheckwidth() stops width calculations until
- * resumecheckwidth() is called, at which point all the
- * checkwidths that were deferred are executed.
- * dowidth should only be called when the type's size
- * is needed immediately. checkwidth makes sure the
- * size is evaluated eventually.
- */
+// when a type's width should be known, we call checkwidth
+// to compute it. during a declaration like
+//
+// type T *struct { next T }
+//
+// it is necessary to defer the calculation of the struct width
+// until after T has been initialized to be a pointer to that struct.
+// similarly, during import processing structs may be used
+// before their definition. in those situations, calling
+// defercheckwidth() stops width calculations until
+// resumecheckwidth() is called, at which point all the
+// checkwidths that were deferred are executed.
+// dowidth should only be called when the type's size
+// is needed immediately. checkwidth makes sure the
+// size is evaluated eventually.
type TypeList struct {
t *Type
next *TypeList
Fatalf("typeinit before betypeinit")
}
- for i := 0; i < NTYPE; i++ {
- Simtype[i] = uint8(i)
+ for et := EType(0); et < NTYPE; et++ {
+ Simtype[et] = et
}
Types[TPTR32] = typ(TPTR32)
Tptr = TPTR64
}
- for i := TINT8; i <= TUINT64; i++ {
- Isint[i] = true
+ for et := TINT8; et <= TUINT64; et++ {
+ Isint[et] = true
}
Isint[TINT] = true
Isint[TUINT] = true
Issigned[TINT32] = true
Issigned[TINT64] = true
- /*
- * initialize okfor
- */
- for i := 0; i < NTYPE; i++ {
- if Isint[i] || i == TIDEAL {
- okforeq[i] = true
- okforcmp[i] = true
- okforarith[i] = true
- okforadd[i] = true
- okforand[i] = true
- okforconst[i] = true
- issimple[i] = true
- Minintval[i] = new(Mpint)
- Maxintval[i] = new(Mpint)
+ // initialize okfor
+ for et := EType(0); et < NTYPE; et++ {
+ if Isint[et] || et == TIDEAL {
+ okforeq[et] = true
+ okforcmp[et] = true
+ okforarith[et] = true
+ okforadd[et] = true
+ okforand[et] = true
+ okforconst[et] = true
+ issimple[et] = true
+ Minintval[et] = new(Mpint)
+ Maxintval[et] = new(Mpint)
}
- if Isfloat[i] {
- okforeq[i] = true
- okforcmp[i] = true
- okforadd[i] = true
- okforarith[i] = true
- okforconst[i] = true
- issimple[i] = true
- minfltval[i] = newMpflt()
- maxfltval[i] = newMpflt()
+ if Isfloat[et] {
+ okforeq[et] = true
+ okforcmp[et] = true
+ okforadd[et] = true
+ okforarith[et] = true
+ okforconst[et] = true
+ issimple[et] = true
+ minfltval[et] = newMpflt()
+ maxfltval[et] = newMpflt()
}
- if Iscomplex[i] {
- okforeq[i] = true
- okforadd[i] = true
- okforarith[i] = true
- okforconst[i] = true
- issimple[i] = true
+ if Iscomplex[et] {
+ okforeq[et] = true
+ okforadd[et] = true
+ okforarith[et] = true
+ okforconst[et] = true
+ issimple[et] = true
}
}
mpatofix(Maxintval[TUINT32], "0xffffffff")
mpatofix(Maxintval[TUINT64], "0xffffffffffffffff")
- /* f is valid float if min < f < max. (min and max are not themselves valid.) */
- mpatoflt(maxfltval[TFLOAT32], "33554431p103") /* 2^24-1 p (127-23) + 1/2 ulp*/
+ // f is valid float if min < f < max. (min and max are not themselves valid.)
+ mpatoflt(maxfltval[TFLOAT32], "33554431p103") // 2^24-1 p (127-23) + 1/2 ulp
mpatoflt(minfltval[TFLOAT32], "-33554431p103")
- mpatoflt(maxfltval[TFLOAT64], "18014398509481983p970") /* 2^53-1 p (1023-52) + 1/2 ulp */
+ mpatoflt(maxfltval[TFLOAT64], "18014398509481983p970") // 2^53-1 p (1023-52) + 1/2 ulp
mpatoflt(minfltval[TFLOAT64], "-18014398509481983p970")
maxfltval[TCOMPLEX64] = maxfltval[TFLOAT32]
maxfltval[TCOMPLEX128] = maxfltval[TFLOAT64]
minfltval[TCOMPLEX128] = minfltval[TFLOAT64]
- /* for walk to use in error messages */
+ // for walk to use in error messages
Types[TFUNC] = functype(nil, nil, nil)
- /* types used in front end */
+ // types used in front end
// types[TNIL] got set early in lexinit
Types[TIDEAL] = typ(TIDEAL)
Types[TINTER] = typ(TINTER)
- /* simple aliases */
- Simtype[TMAP] = uint8(Tptr)
+ // simple aliases
+ Simtype[TMAP] = Tptr
- Simtype[TCHAN] = uint8(Tptr)
- Simtype[TFUNC] = uint8(Tptr)
- Simtype[TUNSAFEPTR] = uint8(Tptr)
+ Simtype[TCHAN] = Tptr
+ Simtype[TFUNC] = Tptr
+ Simtype[TUNSAFEPTR] = Tptr
- /* pick up the backend thearch.typedefs */
- var s1 *Sym
- var etype int
- var sameas int
- var s *Sym
+ // pick up the backend thearch.typedefs
for i = range Thearch.Typedefs {
- s = Lookup(Thearch.Typedefs[i].Name)
- s1 = Pkglookup(Thearch.Typedefs[i].Name, builtinpkg)
+ s := Lookup(Thearch.Typedefs[i].Name)
+ s1 := Pkglookup(Thearch.Typedefs[i].Name, builtinpkg)
- etype = Thearch.Typedefs[i].Etype
- if etype < 0 || etype >= len(Types) {
+ etype := Thearch.Typedefs[i].Etype
+ if int(etype) >= len(Types) {
Fatalf("typeinit: %s bad etype", s.Name)
}
- sameas = Thearch.Typedefs[i].Sameas
- if sameas < 0 || sameas >= len(Types) {
+ sameas := Thearch.Typedefs[i].Sameas
+ if int(sameas) >= len(Types) {
Fatalf("typeinit: %s bad sameas", s.Name)
}
- Simtype[etype] = uint8(sameas)
+ Simtype[etype] = sameas
minfltval[etype] = minfltval[sameas]
maxfltval[etype] = maxfltval[sameas]
Minintval[etype] = Minintval[sameas]
itable.Type = Types[TUINT8]
}
-/*
- * compute total size of f's in/out arguments.
- */
+// compute total size of f's in/out arguments.
func Argsize(t *Type) int {
var save Iter
var x int64
--- /dev/null
+// Copyright 2015 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.
+
+// Binary package export.
+// Based loosely on x/tools/go/importer.
+// (see fmt.go, go.y as "documentation" for how to use/setup data structures)
+//
+// Use "-newexport" flag to enable.
+
+// TODO(gri):
+// - inlined functions
+
+/*
+Export data encoding:
+
+The export data is a serialized description of the graph of exported
+objects: constants, types, variables, and functions. Only types can
+be re-exported and so we need to know which package they are coming
+from. Therefore, packages are also part of the export graph.
+
+The roots of the graph are the list of constants, variables, functions,
+and eventually types. Types are written last because most of them will
+be written as part of other objects which will reduce the number of
+types that need to be written separately.
+
+The graph is serialized in in-order fashion, starting with the roots.
+Each object in the graph is serialized by writing its fields sequentially.
+If the field is a pointer to another object, that object is serialized,
+recursively. Otherwise the field is written. Non-pointer fields are all
+encoded as either an integer or string value.
+
+Only packages and types may be referred to more than once. When getting
+to a package or type that was not serialized before, a number (index) is
+assigned to it, starting at 0. In this case, the encoding starts with an
+integer tag with a value < 0. The tag value indicates the kind of object
+(package or type) that follows and that this is the first time that we
+see this object. If the package or tag was already serialized, the encoding
+starts with the respective package or type index >= 0. An importer can
+trivially determine if a package or type needs to be read in for the first
+time (tag < 0) and entered into the respective package or type table, or
+if the package or type was seen already (index >= 0), in which case the
+index is the table index where the respective object can be found.
+
+Before exporting or importing, the type tables are populated with the
+predeclared types (int, string, error, unsafe.Pointer, etc.). This way
+they are automatically encoded with a known and fixed type index.
+
+Encoding format:
+
+The export data starts with a single byte indicating the encoding format
+(compact, or with debugging information), followed by a version string
+(so we can evolve the encoding if need be), the name of the imported
+package, and a string containing platform-specific information for that
+package.
+
+After this header, the lists of objects follow. After the objects, platform-
+specific data may be found which is not used strictly for type checking.
+
+The encoding of objects is straight-forward: Constants, variables, and
+functions start with their name, type, and possibly a value. Named types
+record their name and package so that they can be canonicalized: If the
+same type was imported before via another import, the importer must use
+the previously imported type pointer so that we have exactly one version
+(i.e., one pointer) for each named type (and read but discard the current
+type encoding). Unnamed types simply encode their respective fields.
+
+In the encoding, all lists (of objects, struct fields, methods, parameter
+names, but also the bytes of a string, etc.) start with an integer which
+is the length of the list. This permits an importer to allocate the right
+amount of space to hold the list without the need to grow it later.
+
+All integer values use a variable-length encoding for compact representation.
+
+If debugFormat is set, each integer and string value is preceeded by a marker
+and position information in the encoding. This mechanism permits an importer
+to recognize immediately when it is out of sync. The importer recognizes this
+mode automatically (i.e., it can import export data produced with debugging
+support even if debugFormat is not set at the time of import). Using this mode
+will massively increase the size of the export data (by a factor of 2 to 3)
+and is only recommended for debugging.
+
+The exporter and importer are completely symmetric in implementation: For
+each encoding routine there is the matching and symmetric decoding routine.
+This symmetry makes it very easy to change or extend the format: If a new
+field needs to be encoded, a symmetric change can be made to exporter and
+importer.
+*/
+
+package gc
+
+import (
+ "bytes"
+ "cmd/compile/internal/big"
+ "cmd/internal/obj"
+ "encoding/binary"
+ "fmt"
+ "sort"
+ "strings"
+)
+
+// debugging support
+const (
+ debugFormat = false // use debugging format for export data (emits a lot of additional data)
+)
+
+const exportVersion = "v0"
+
+// Set forceNewExport to force the use of the new export format - for testing on the build dashboard.
+// TODO(gri) remove eventually
+const forceNewExport = false
+
+// Export writes the export data for localpkg to out and returns the number of bytes written.
+func Export(out *obj.Biobuf, trace bool) int {
+ p := exporter{
+ out: out,
+ pkgIndex: make(map[*Pkg]int),
+ typIndex: make(map[*Type]int),
+ trace: trace,
+ }
+
+ // write low-level encoding format
+ var format byte = 'c' // compact
+ if debugFormat {
+ format = 'd'
+ }
+ p.byte(format)
+
+ // --- generic export data ---
+
+ if p.trace {
+ p.tracef("\n--- generic export data ---\n")
+ if p.indent != 0 {
+ Fatalf("incorrect indentation %d", p.indent)
+ }
+ }
+
+ p.string(exportVersion)
+ if p.trace {
+ p.tracef("\n")
+ }
+
+ // populate type map with predeclared "known" types
+ predecl := predeclared()
+ for index, typ := range predecl {
+ p.typIndex[typ] = index
+ }
+ if len(p.typIndex) != len(predecl) {
+ Fatalf("duplicate entries in type map?")
+ }
+
+ // write package data
+ if localpkg.Path != "" {
+ Fatalf("local package path not empty: %q", localpkg.Path)
+ }
+ p.pkg(localpkg)
+
+ // write compiler-specific flags
+ // go.y:import_safety
+ {
+ var flags string
+ if safemode != 0 {
+ flags = "safe"
+ }
+ p.string(flags)
+ }
+
+ if p.trace {
+ p.tracef("\n")
+ }
+
+ // collect objects to export
+ var consts, vars, funcs []*Sym
+ var types []*Type
+ for _, n := range exportlist {
+ sym := n.Sym
+ // TODO(gri) Closures appear marked as exported.
+ // Investigate and determine if we need this.
+ if sym.Flags&SymExported != 0 {
+ continue
+ }
+ sym.Flags |= SymExported
+
+ // TODO(gri) Closures have dots in their names;
+ // e.g., TestFloatZeroValue.func1 in math/big tests.
+ // We may not need this eventually. See also comment
+ // on sym.Flags&SymExported test above.
+ if strings.Contains(sym.Name, ".") {
+ Fatalf("unexpected export symbol: %v", sym)
+ }
+
+ if sym.Flags&SymExport != 0 {
+ if sym.Def == nil {
+ Fatalf("unknown export symbol: %v", sym)
+ }
+ switch n := sym.Def; n.Op {
+ case OLITERAL:
+ // constant
+ typecheck(&n, Erv)
+ if n == nil || n.Op != OLITERAL {
+ Fatalf("dumpexportconst: oconst nil: %v", sym)
+ }
+ consts = append(consts, sym)
+
+ case ONAME:
+ // variable or function
+ typecheck(&n, Erv|Ecall)
+ if n == nil || n.Type == nil {
+ Fatalf("variable/function exported but not defined: %v", sym)
+ }
+ if n.Type.Etype == TFUNC && n.Class == PFUNC {
+ funcs = append(funcs, sym)
+ } else {
+ vars = append(vars, sym)
+ }
+
+ case OTYPE:
+ // named type
+ t := n.Type
+ if t.Etype == TFORW {
+ Fatalf("export of incomplete type %v", sym)
+ }
+ types = append(types, t)
+
+ default:
+ Fatalf("unexpected export symbol: %v %v", Oconv(int(n.Op), 0), sym)
+ }
+ }
+ }
+ exportlist = nil // match export.go use of exportlist
+
+ // for reproducible output
+ sort.Sort(symByName(consts))
+ sort.Sort(symByName(vars))
+ sort.Sort(symByName(funcs))
+ // sort types later when we have fewer types left
+
+ // write consts
+ p.int(len(consts))
+ for _, sym := range consts {
+ n := sym.Def
+ typ := n.Type // may or may not be specified
+ // Untyped (ideal) constants get their own type. This decouples
+ // the constant type from the encoding of the constant value.
+ if typ == nil || isideal(typ) {
+ typ = untype(n.Val().Ctype())
+ }
+
+ p.string(sym.Name)
+ p.typ(typ)
+ p.value(n.Val())
+ }
+
+ // write vars
+ p.int(len(vars))
+ for _, sym := range vars {
+ p.string(sym.Name)
+ p.typ(sym.Def.Type)
+ }
+
+ // write funcs
+ p.int(len(funcs))
+ for _, sym := range funcs {
+ p.string(sym.Name)
+ // The type can only be a signature for functions. However, by always
+ // writing the complete type specification (rather than just a signature)
+ // we keep the option open of sharing common signatures across multiple
+ // functions as a means to further compress the export data.
+ p.typ(sym.Def.Type)
+ p.int(p.collectInlined(sym.Def))
+ }
+
+ // determine which types are still left to write and sort them
+ i := 0
+ for _, t := range types {
+ if _, ok := p.typIndex[t]; !ok {
+ types[i] = t
+ i++
+ }
+ }
+ types = types[:i]
+ sort.Sort(typByName(types))
+
+ // write types
+ p.int(len(types))
+ for _, t := range types {
+ // Writing a type may further reduce the number of types
+ // that are left to be written, but at this point we don't
+ // care.
+ p.typ(t)
+ }
+
+ if p.trace {
+ p.tracef("\n")
+ }
+
+ // --- compiler-specific export data ---
+
+ if p.trace {
+ p.tracef("\n--- compiler specific export data ---\n")
+ if p.indent != 0 {
+ Fatalf("incorrect indentation")
+ }
+ }
+
+ // write inlined function bodies
+ p.int(len(p.inlined))
+ for i, f := range p.inlined {
+ p.body(i, f)
+ }
+
+ if p.trace {
+ p.tracef("\n")
+ }
+
+ // --- end of export data ---
+
+ return p.written
+}
+
+type symByName []*Sym
+
+func (a symByName) Len() int { return len(a) }
+func (a symByName) Less(i, j int) bool { return a[i].Name < a[j].Name }
+func (a symByName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+
+type typByName []*Type
+
+func (a typByName) Len() int { return len(a) }
+func (a typByName) Less(i, j int) bool { return a[i].Sym.Name < a[j].Sym.Name }
+func (a typByName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+
+type exporter struct {
+ out *obj.Biobuf
+ pkgIndex map[*Pkg]int
+ typIndex map[*Type]int
+ inlined []*Func
+
+ written int // bytes written
+ indent int // for p.trace
+ trace bool
+}
+
+func (p *exporter) pkg(pkg *Pkg) {
+ if pkg == nil {
+ Fatalf("unexpected nil pkg")
+ }
+
+ // if we saw the package before, write its index (>= 0)
+ if i, ok := p.pkgIndex[pkg]; ok {
+ p.index('P', i)
+ return
+ }
+
+ // otherwise, remember the package, write the package tag (< 0) and package data
+ if p.trace {
+ p.tracef("P%d = { ", len(p.pkgIndex))
+ defer p.tracef("} ")
+ }
+ p.pkgIndex[pkg] = len(p.pkgIndex)
+
+ p.tag(packageTag)
+ p.string(pkg.Name)
+ p.string(pkg.Path)
+}
+
+func (p *exporter) typ(t *Type) {
+ if t == nil {
+ Fatalf("nil type")
+ }
+
+ // Possible optimization: Anonymous pointer types *T where
+ // T is a named type are common. We could canonicalize all
+ // such types *T to a single type PT = *T. This would lead
+ // to at most one *T entry in typIndex, and all future *T's
+ // would be encoded as the respective index directly. Would
+ // save 1 byte (pointerTag) per *T and reduce the typIndex
+ // size (at the cost of a canonicalization map). We can do
+ // this later, without encoding format change.
+
+ // if we saw the type before, write its index (>= 0)
+ if i, ok := p.typIndex[t]; ok {
+ p.index('T', i)
+ return
+ }
+
+ // otherwise, remember the type, write the type tag (< 0) and type data
+ if p.trace {
+ p.tracef("T%d = {>\n", len(p.typIndex))
+ defer p.tracef("<\n} ")
+ }
+ p.typIndex[t] = len(p.typIndex)
+
+ // pick off named types
+ if sym := t.Sym; sym != nil {
+ // Fields should be exported by p.field().
+ if t.Etype == TFIELD {
+ Fatalf("printing a field/parameter with wrong function")
+ }
+ // Predeclared types should have been found in the type map.
+ if t.Orig == t {
+ Fatalf("predeclared type missing from type map?")
+ }
+ // TODO(gri) The assertion below seems incorrect (crashes during all.bash).
+ // Investigate.
+ /*
+ // we expect the respective definition to point to us
+ if sym.Def.Type != t {
+ Fatalf("type definition doesn't point to us?")
+ }
+ */
+
+ p.tag(namedTag)
+ p.qualifiedName(sym)
+
+ // write underlying type
+ p.typ(t.Orig)
+
+ // interfaces don't have associated methods
+ if t.Orig.Etype == TINTER {
+ return
+ }
+
+ // sort methods for reproducible export format
+ // TODO(gri) Determine if they are already sorted
+ // in which case we can drop this step.
+ var methods []*Type
+ for m := t.Method; m != nil; m = m.Down {
+ methods = append(methods, m)
+ }
+ sort.Sort(methodbyname(methods))
+ p.int(len(methods))
+
+ if p.trace && t.Method != nil {
+ p.tracef("associated methods {>\n")
+ }
+
+ for _, m := range methods {
+ p.string(m.Sym.Name)
+ p.paramList(getthisx(m.Type))
+ p.paramList(getinargx(m.Type))
+ p.paramList(getoutargx(m.Type))
+ p.int(p.collectInlined(m.Type.Nname))
+
+ if p.trace && m.Down != nil {
+ p.tracef("\n")
+ }
+ }
+
+ if p.trace && t.Method != nil {
+ p.tracef("<\n} ")
+ }
+
+ return
+ }
+
+ // otherwise we have a type literal
+ switch t.Etype {
+ case TARRAY:
+ // TODO(gri) define named constant for the -100
+ if t.Bound >= 0 || t.Bound == -100 {
+ p.tag(arrayTag)
+ p.int64(t.Bound)
+ } else {
+ p.tag(sliceTag)
+ }
+ p.typ(t.Type)
+
+ case T_old_DARRAY:
+ // see p.param use of T_old_DARRAY
+ p.tag(dddTag)
+ p.typ(t.Type)
+
+ case TSTRUCT:
+ p.tag(structTag)
+ p.fieldList(t)
+
+ case TPTR32, TPTR64: // could use Tptr but these are constants
+ p.tag(pointerTag)
+ p.typ(t.Type)
+
+ case TFUNC:
+ p.tag(signatureTag)
+ p.paramList(getinargx(t))
+ p.paramList(getoutargx(t))
+
+ case TINTER:
+ p.tag(interfaceTag)
+
+ // gc doesn't separate between embedded interfaces
+ // and methods declared explicitly with an interface
+ p.int(0) // no embedded interfaces
+ p.methodList(t)
+
+ case TMAP:
+ p.tag(mapTag)
+ p.typ(t.Down) // key
+ p.typ(t.Type) // val
+
+ case TCHAN:
+ p.tag(chanTag)
+ p.int(int(t.Chan))
+ p.typ(t.Type)
+
+ default:
+ Fatalf("unexpected type: %s (Etype = %d)", Tconv(t, 0), t.Etype)
+ }
+}
+
+func (p *exporter) qualifiedName(sym *Sym) {
+ p.string(sym.Name)
+ p.pkg(sym.Pkg)
+}
+
+func (p *exporter) fieldList(t *Type) {
+ if p.trace && t.Type != nil {
+ p.tracef("fields {>\n")
+ defer p.tracef("<\n} ")
+ }
+
+ p.int(countfield(t))
+ for f := t.Type; f != nil; f = f.Down {
+ p.field(f)
+ if p.trace && f.Down != nil {
+ p.tracef("\n")
+ }
+ }
+}
+
+func (p *exporter) field(f *Type) {
+ if f.Etype != TFIELD {
+ Fatalf("field expected")
+ }
+
+ p.fieldName(f)
+ p.typ(f.Type)
+ p.note(f.Note)
+}
+
+func (p *exporter) note(n *string) {
+ var s string
+ if n != nil {
+ s = *n
+ }
+ p.string(s)
+}
+
+func (p *exporter) methodList(t *Type) {
+ if p.trace && t.Type != nil {
+ p.tracef("methods {>\n")
+ defer p.tracef("<\n} ")
+ }
+
+ p.int(countfield(t))
+ for m := t.Type; m != nil; m = m.Down {
+ p.method(m)
+ if p.trace && m.Down != nil {
+ p.tracef("\n")
+ }
+ }
+}
+
+func (p *exporter) method(m *Type) {
+ if m.Etype != TFIELD {
+ Fatalf("method expected")
+ }
+
+ p.fieldName(m)
+ // TODO(gri) For functions signatures, we use p.typ() to export
+ // so we could share the same type with multiple functions. Do
+ // the same here, or never try to do this for functions.
+ p.paramList(getinargx(m.Type))
+ p.paramList(getoutargx(m.Type))
+}
+
+// fieldName is like qualifiedName but it doesn't record the package
+// for blank (_) or exported names.
+func (p *exporter) fieldName(t *Type) {
+ sym := t.Sym
+
+ var name string
+ if t.Embedded == 0 {
+ name = sym.Name
+ } else if bname := basetypeName(t); bname != "" && !exportname(bname) {
+ // anonymous field with unexported base type name: use "?" as field name
+ // (bname != "" per spec, but we are conservative in case of errors)
+ name = "?"
+ }
+
+ p.string(name)
+ if name == "?" || name != "_" && name != "" && !exportname(name) {
+ p.pkg(sym.Pkg)
+ }
+}
+
+func basetypeName(t *Type) string {
+ s := t.Sym
+ if s == nil && Isptr[t.Etype] {
+ s = t.Type.Sym // deref
+ }
+ if s != nil {
+ return s.Name
+ }
+ return ""
+}
+
+func (p *exporter) paramList(params *Type) {
+ if params.Etype != TSTRUCT || !params.Funarg {
+ Fatalf("parameter list expected")
+ }
+
+ // use negative length to indicate unnamed parameters
+ // (look at the first parameter only since either all
+ // names are present or all are absent)
+ n := countfield(params)
+ if n > 0 && parName(params.Type) == "" {
+ n = -n
+ }
+ p.int(n)
+ for q := params.Type; q != nil; q = q.Down {
+ p.param(q, n)
+ }
+}
+
+func (p *exporter) param(q *Type, n int) {
+ if q.Etype != TFIELD {
+ Fatalf("parameter expected")
+ }
+ t := q.Type
+ if q.Isddd {
+ // create a fake type to encode ... just for the p.typ call
+ // (T_old_DARRAY is not used anywhere else in the compiler,
+ // we use it here to communicate between p.param and p.typ.)
+ t = &Type{Etype: T_old_DARRAY, Type: t.Type}
+ }
+ p.typ(t)
+ if n > 0 {
+ p.string(parName(q))
+ }
+ // TODO(gri) This is compiler-specific (escape info).
+ // Move into compiler-specific section eventually?
+ // (Not having escape info causes tests to fail, e.g. runtime GCInfoTest)
+ p.note(q.Note)
+}
+
+func parName(q *Type) string {
+ if q.Sym == nil {
+ return ""
+ }
+ name := q.Sym.Name
+ // undo gc-internal name mangling - we just need the source name
+ if len(name) > 0 && name[0] == '~' {
+ // name is ~b%d or ~r%d
+ switch name[1] {
+ case 'b':
+ return "_"
+ case 'r':
+ return ""
+ default:
+ Fatalf("unexpected parameter name: %s", name)
+ }
+ }
+ // undo gc-internal name specialization
+ if i := strings.Index(name, "·"); i > 0 {
+ name = name[:i] // cut off numbering
+ }
+ return name
+}
+
+func (p *exporter) value(x Val) {
+ if p.trace {
+ p.tracef("= ")
+ }
+
+ switch x := x.U.(type) {
+ case bool:
+ tag := falseTag
+ if x {
+ tag = trueTag
+ }
+ p.tag(tag)
+
+ case *Mpint:
+ if Mpcmpfixfix(Minintval[TINT64], x) <= 0 && Mpcmpfixfix(x, Maxintval[TINT64]) <= 0 {
+ // common case: x fits into an int64 - use compact encoding
+ p.tag(int64Tag)
+ p.int64(Mpgetfix(x))
+ return
+ }
+ // uncommon case: large x - use float encoding
+ // (powers of 2 will be encoded efficiently with exponent)
+ p.tag(floatTag)
+ f := newMpflt()
+ Mpmovefixflt(f, x)
+ p.float(f)
+
+ case *Mpflt:
+ p.tag(floatTag)
+ p.float(x)
+
+ case *Mpcplx:
+ p.tag(complexTag)
+ p.float(&x.Real)
+ p.float(&x.Imag)
+
+ case string:
+ p.tag(stringTag)
+ p.string(x)
+
+ default:
+ Fatalf("unexpected value %v (%T)", x, x)
+ }
+}
+
+func (p *exporter) float(x *Mpflt) {
+ // extract sign (there is no -0)
+ f := &x.Val
+ sign := f.Sign()
+ if sign == 0 {
+ // x == 0
+ p.int(0)
+ return
+ }
+ // x != 0
+
+ // extract exponent such that 0.5 <= m < 1.0
+ var m big.Float
+ exp := f.MantExp(&m)
+
+ // extract mantissa as *big.Int
+ // - set exponent large enough so mant satisfies mant.IsInt()
+ // - get *big.Int from mant
+ m.SetMantExp(&m, int(m.MinPrec()))
+ mant, acc := m.Int(nil)
+ if acc != big.Exact {
+ Fatalf("internal error")
+ }
+
+ p.int(sign)
+ p.int(exp)
+ p.string(string(mant.Bytes()))
+}
+
+// ----------------------------------------------------------------------------
+// Inlined function bodies
+
+// TODO(gri) This section is incomplete. At the moment nothing meaningful
+// is written out for exported functions with inlined function bodies.
+
+func (p *exporter) collectInlined(n *Node) int {
+ if n != nil && n.Func != nil && n.Func.Inl != nil {
+ // when lazily typechecking inlined bodies, some re-exported ones may not have been typechecked yet.
+ // currently that can leave unresolved ONONAMEs in import-dot-ed packages in the wrong package
+ if Debug['l'] < 2 {
+ typecheckinl(n)
+ }
+ p.inlined = append(p.inlined, n.Func)
+ return len(p.inlined) - 1 // index >= 0 => inlined
+ }
+ return -1 // index < 0 => not inlined
+}
+
+func (p *exporter) body(i int, f *Func) {
+ p.int(i)
+ p.block(f.Inl)
+}
+
+func (p *exporter) block(list *NodeList) {
+ p.int(count(list))
+ for q := list; q != nil; q = q.Next {
+ p.stmt(q.N)
+ }
+}
+
+func (p *exporter) stmt(n *Node) {
+ // TODO(gri) do something sensible here
+ p.string("body")
+}
+
+// ----------------------------------------------------------------------------
+// Low-level encoders
+
+func (p *exporter) index(marker byte, index int) {
+ if index < 0 {
+ Fatalf("invalid index < 0")
+ }
+ if debugFormat {
+ p.marker('t')
+ }
+ if p.trace {
+ p.tracef("%c%d ", marker, index)
+ }
+ p.rawInt64(int64(index))
+}
+
+func (p *exporter) tag(tag int) {
+ if tag >= 0 {
+ Fatalf("invalid tag >= 0")
+ }
+ if debugFormat {
+ p.marker('t')
+ }
+ if p.trace {
+ p.tracef("%s ", tagString[-tag])
+ }
+ p.rawInt64(int64(tag))
+}
+
+func (p *exporter) int(x int) {
+ p.int64(int64(x))
+}
+
+func (p *exporter) int64(x int64) {
+ if debugFormat {
+ p.marker('i')
+ }
+ if p.trace {
+ p.tracef("%d ", x)
+ }
+ p.rawInt64(x)
+}
+
+func (p *exporter) string(s string) {
+ if debugFormat {
+ p.marker('s')
+ }
+ if p.trace {
+ p.tracef("%q ", s)
+ }
+ p.rawInt64(int64(len(s)))
+ for i := 0; i < len(s); i++ {
+ p.byte(s[i])
+ }
+}
+
+// marker emits a marker byte and position information which makes
+// it easy for a reader to detect if it is "out of sync". Used for
+// debugFormat format only.
+func (p *exporter) marker(m byte) {
+ p.byte(m)
+ p.rawInt64(int64(p.written))
+}
+
+// rawInt64 should only be used by low-level encoders
+func (p *exporter) rawInt64(x int64) {
+ var tmp [binary.MaxVarintLen64]byte
+ n := binary.PutVarint(tmp[:], x)
+ for i := 0; i < n; i++ {
+ p.byte(tmp[i])
+ }
+}
+
+// byte is the bottleneck interface to write to p.out.
+// byte escapes b as follows (any encoding does that
+// hides '$'):
+//
+// '$' => '|' 'S'
+// '|' => '|' '|'
+//
+// Necessary so other tools can find the end of the
+// export data by searching for "$$".
+func (p *exporter) byte(b byte) {
+ switch b {
+ case '$':
+ // write '$' as '|' 'S'
+ b = 'S'
+ fallthrough
+ case '|':
+ // write '|' as '|' '|'
+ obj.Bputc(p.out, '|')
+ p.written++
+ }
+ obj.Bputc(p.out, b)
+ p.written++
+}
+
+// tracef is like fmt.Printf but it rewrites the format string
+// to take care of indentation.
+func (p *exporter) tracef(format string, args ...interface{}) {
+ if strings.IndexAny(format, "<>\n") >= 0 {
+ var buf bytes.Buffer
+ for i := 0; i < len(format); i++ {
+ // no need to deal with runes
+ ch := format[i]
+ switch ch {
+ case '>':
+ p.indent++
+ continue
+ case '<':
+ p.indent--
+ continue
+ }
+ buf.WriteByte(ch)
+ if ch == '\n' {
+ for j := p.indent; j > 0; j-- {
+ buf.WriteString(". ")
+ }
+ }
+ }
+ format = buf.String()
+ }
+ fmt.Printf(format, args...)
+}
+
+// ----------------------------------------------------------------------------
+// Export format
+
+// Tags. Must be < 0.
+const (
+ // Packages
+ packageTag = -(iota + 1)
+
+ // Types
+ namedTag
+ arrayTag
+ sliceTag
+ dddTag
+ structTag
+ pointerTag
+ signatureTag
+ interfaceTag
+ mapTag
+ chanTag
+
+ // Values
+ falseTag
+ trueTag
+ int64Tag
+ floatTag
+ fractionTag // not used by gc
+ complexTag
+ stringTag
+)
+
+// Debugging support.
+// (tagString is only used when tracing is enabled)
+var tagString = [...]string{
+ // Packages:
+ -packageTag: "package",
+
+ // Types:
+ -namedTag: "named type",
+ -arrayTag: "array",
+ -sliceTag: "slice",
+ -dddTag: "ddd",
+ -structTag: "struct",
+ -pointerTag: "pointer",
+ -signatureTag: "signature",
+ -interfaceTag: "interface",
+ -mapTag: "map",
+ -chanTag: "chan",
+
+ // Values:
+ -falseTag: "false",
+ -trueTag: "true",
+ -int64Tag: "int64",
+ -floatTag: "float",
+ -fractionTag: "fraction",
+ -complexTag: "complex",
+ -stringTag: "string",
+}
+
+// untype returns the "pseudo" untyped type for a Ctype (import/export use only).
+// (we can't use an pre-initialized array because we must be sure all types are
+// set up)
+func untype(ctype Ctype) *Type {
+ switch ctype {
+ case CTINT:
+ return idealint
+ case CTRUNE:
+ return idealrune
+ case CTFLT:
+ return idealfloat
+ case CTCPLX:
+ return idealcomplex
+ case CTSTR:
+ return idealstring
+ case CTBOOL:
+ return idealbool
+ case CTNIL:
+ return Types[TNIL]
+ }
+ Fatalf("unknown Ctype")
+ return nil
+}
+
+var (
+ idealint = typ(TIDEAL)
+ idealrune = typ(TIDEAL)
+ idealfloat = typ(TIDEAL)
+ idealcomplex = typ(TIDEAL)
+)
+
+var predecl []*Type // initialized lazily
+
+func predeclared() []*Type {
+ if predecl == nil {
+ // initialize lazily to be sure that all
+ // elements have been initialized before
+ predecl = []*Type{
+ // basic types
+ Types[TBOOL],
+ Types[TINT],
+ Types[TINT8],
+ Types[TINT16],
+ Types[TINT32],
+ Types[TINT64],
+ Types[TUINT],
+ Types[TUINT8],
+ Types[TUINT16],
+ Types[TUINT32],
+ Types[TUINT64],
+ Types[TUINTPTR],
+ Types[TFLOAT32],
+ Types[TFLOAT64],
+ Types[TCOMPLEX64],
+ Types[TCOMPLEX128],
+ Types[TSTRING],
+
+ // aliases
+ bytetype,
+ runetype,
+
+ // error
+ errortype,
+
+ // untyped types
+ untype(CTBOOL),
+ untype(CTINT),
+ untype(CTRUNE),
+ untype(CTFLT),
+ untype(CTCPLX),
+ untype(CTSTR),
+ untype(CTNIL),
+
+ // package unsafe
+ Types[TUNSAFEPTR],
+ }
+ }
+ return predecl
+}
--- /dev/null
+// Copyright 2015 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.
+
+// Binary package import.
+// Based loosely on x/tools/go/importer.
+
+package gc
+
+import (
+ "cmd/compile/internal/big"
+ "cmd/internal/obj"
+ "encoding/binary"
+)
+
+// The overall structure of Import is symmetric to Export: For each
+// export method in bexport.go there is a matching and symmetric method
+// in bimport.go. Changing the export format requires making symmetric
+// changes to bimport.go and bexport.go.
+
+// Import populates importpkg from the serialized package data.
+func Import(in *obj.Biobuf) {
+ p := importer{in: in}
+ p.buf = p.bufarray[:]
+
+ // read low-level encoding format
+ switch format := p.byte(); format {
+ case 'c':
+ // compact format - nothing to do
+ case 'd':
+ p.debugFormat = true
+ default:
+ Fatalf("invalid encoding format in export data: got %q; want 'c' or 'd'", format)
+ }
+
+ // --- generic export data ---
+
+ if v := p.string(); v != exportVersion {
+ Fatalf("unknown export data version: %s", v)
+ }
+
+ // populate typList with predeclared "known" types
+ p.typList = append(p.typList, predeclared()...)
+
+ // read package data
+ p.pkg()
+ if p.pkgList[0] != importpkg {
+ Fatalf("imported package not found in pkgList[0]")
+ }
+
+ // read compiler-specific flags
+ importpkg.Safe = p.string() == "safe"
+
+ // defer some type-checking until all types are read in completely
+ // (go.y:import_there)
+ tcok := typecheckok
+ typecheckok = true
+ defercheckwidth()
+
+ // read consts
+ for i := p.int(); i > 0; i-- {
+ sym := p.localname()
+ typ := p.typ()
+ val := p.value(typ)
+ if isideal(typ) {
+ // canonicalize ideal types
+ typ = Types[TIDEAL]
+ }
+ importconst(sym, typ, nodlit(val))
+ }
+
+ // read vars
+ for i := p.int(); i > 0; i-- {
+ sym := p.localname()
+ typ := p.typ()
+ importvar(sym, typ)
+ }
+
+ // read funcs
+ for i := p.int(); i > 0; i-- {
+ // go.y:hidden_fndcl
+ sym := p.localname()
+ typ := p.typ()
+ // TODO(gri) fix this
+ p.int() // read and discard index of inlined function body for now
+
+ importsym(sym, ONAME)
+ if sym.Def != nil && sym.Def.Op == ONAME && !Eqtype(typ, sym.Def.Type) {
+ Fatalf("inconsistent definition for func %v during import\n\t%v\n\t%v", sym, sym.Def.Type, typ)
+ }
+
+ n := newfuncname(sym)
+ n.Type = typ
+ declare(n, PFUNC)
+ funchdr(n)
+
+ // go.y:hidden_import
+ n.Func.Inl = nil
+ funcbody(n)
+ importlist = append(importlist, n) // TODO(gri) do this only if body is inlineable?
+ }
+
+ // read types
+ for i := p.int(); i > 0; i-- {
+ // name is parsed as part of named type
+ p.typ()
+ }
+
+ // --- compiler-specific export data ---
+
+ for i := p.int(); i > 0; i-- {
+ p.body()
+ }
+
+ // --- end of export data ---
+
+ typecheckok = tcok
+ resumecheckwidth()
+
+ testdclstack() // debugging only
+}
+
+type importer struct {
+ in *obj.Biobuf
+ buf []byte // for reading strings
+ bufarray [64]byte // initial underlying array for buf, large enough to avoid allocation when compiling std lib
+ pkgList []*Pkg
+ typList []*Type
+
+ debugFormat bool
+ read int // bytes read
+}
+
+func (p *importer) pkg() *Pkg {
+ // if the package was seen before, i is its index (>= 0)
+ i := p.tagOrIndex()
+ if i >= 0 {
+ return p.pkgList[i]
+ }
+
+ // otherwise, i is the package tag (< 0)
+ if i != packageTag {
+ Fatalf("expected package tag, found tag = %d", i)
+ }
+
+ // read package data
+ name := p.string()
+ path := p.string()
+
+ // we should never see an empty package name
+ if name == "" {
+ Fatalf("empty package name in import")
+ }
+
+ // we should never see a bad import path
+ if isbadimport(path) {
+ Fatalf("bad path in import: %q", path)
+ }
+
+ // an empty path denotes the package we are currently importing
+ pkg := importpkg
+ if path != "" {
+ pkg = mkpkg(path)
+ }
+ if pkg.Name == "" {
+ pkg.Name = name
+ } else if pkg.Name != name {
+ Fatalf("inconsistent package names: got %s; want %s (path = %s)", pkg.Name, name, path)
+ }
+ p.pkgList = append(p.pkgList, pkg)
+
+ return pkg
+}
+
+func (p *importer) localname() *Sym {
+ // go.y:hidden_importsym
+ name := p.string()
+ if name == "" {
+ Fatalf("unexpected anonymous name")
+ }
+ structpkg = importpkg // go.y:hidden_pkg_importsym
+ return importpkg.Lookup(name)
+}
+
+func (p *importer) newtyp(etype EType) *Type {
+ t := typ(etype)
+ p.typList = append(p.typList, t)
+ return t
+}
+
+func (p *importer) typ() *Type {
+ // if the type was seen before, i is its index (>= 0)
+ i := p.tagOrIndex()
+ if i >= 0 {
+ return p.typList[i]
+ }
+
+ // otherwise, i is the type tag (< 0)
+ var t *Type
+ switch i {
+ case namedTag:
+ // go.y:hidden_importsym
+ tsym := p.qualifiedName()
+
+ // go.y:hidden_pkgtype
+ t = pkgtype(tsym)
+ importsym(tsym, OTYPE)
+ p.typList = append(p.typList, t)
+
+ // read underlying type
+ // go.y:hidden_type
+ t0 := p.typ()
+ importtype(t, t0) // go.y:hidden_import
+
+ // interfaces don't have associated methods
+ if t0.Etype == TINTER {
+ break
+ }
+
+ // read associated methods
+ for i := p.int(); i > 0; i-- {
+ // go.y:hidden_fndcl
+ name := p.string()
+ recv := p.paramList() // TODO(gri) do we need a full param list for the receiver?
+ params := p.paramList()
+ result := p.paramList()
+ // TODO(gri) fix this
+ p.int() // read and discard index of inlined function body for now
+
+ pkg := localpkg
+ if !exportname(name) {
+ pkg = tsym.Pkg
+ }
+ sym := pkg.Lookup(name)
+
+ n := methodname1(newname(sym), recv.N.Right)
+ n.Type = functype(recv.N, params, result)
+ checkwidth(n.Type)
+ // addmethod uses the global variable structpkg to verify consistency
+ {
+ saved := structpkg
+ structpkg = tsym.Pkg
+ addmethod(sym, n.Type, false, nointerface)
+ structpkg = saved
+ }
+ nointerface = false
+ funchdr(n)
+
+ // (comment from go.y)
+ // inl.C's inlnode in on a dotmeth node expects to find the inlineable body as
+ // (dotmeth's type).Nname.Inl, and dotmeth's type has been pulled
+ // out by typecheck's lookdot as this $$.ttype. So by providing
+ // this back link here we avoid special casing there.
+ n.Type.Nname = n
+
+ // go.y:hidden_import
+ n.Func.Inl = nil
+ funcbody(n)
+ importlist = append(importlist, n) // TODO(gri) do this only if body is inlineable?
+ }
+
+ case arrayTag, sliceTag:
+ t = p.newtyp(TARRAY)
+ t.Bound = -1
+ if i == arrayTag {
+ t.Bound = p.int64()
+ }
+ t.Type = p.typ()
+
+ case dddTag:
+ t = p.newtyp(T_old_DARRAY)
+ t.Bound = -1
+ t.Type = p.typ()
+
+ case structTag:
+ t = p.newtyp(TSTRUCT)
+ tostruct0(t, p.fieldList())
+
+ case pointerTag:
+ t = p.newtyp(Tptr)
+ t.Type = p.typ()
+
+ case signatureTag:
+ t = p.newtyp(TFUNC)
+ params := p.paramList()
+ result := p.paramList()
+ functype0(t, nil, params, result)
+
+ case interfaceTag:
+ t = p.newtyp(TINTER)
+ if p.int() != 0 {
+ Fatalf("unexpected embedded interface")
+ }
+ tointerface0(t, p.methodList())
+
+ case mapTag:
+ t = p.newtyp(TMAP)
+ t.Down = p.typ() // key
+ t.Type = p.typ() // val
+
+ case chanTag:
+ t = p.newtyp(TCHAN)
+ t.Chan = uint8(p.int())
+ t.Type = p.typ()
+
+ default:
+ Fatalf("unexpected type (tag = %d)", i)
+ }
+
+ if t == nil {
+ Fatalf("nil type (type tag = %d)", i)
+ }
+
+ return t
+}
+
+func (p *importer) qualifiedName() *Sym {
+ name := p.string()
+ pkg := p.pkg()
+ return pkg.Lookup(name)
+}
+
+// go.y:hidden_structdcl_list
+func (p *importer) fieldList() *NodeList {
+ i := p.int()
+ if i == 0 {
+ return nil
+ }
+ n := list1(p.field())
+ for i--; i > 0; i-- {
+ n = list(n, p.field())
+ }
+ return n
+}
+
+// go.y:hidden_structdcl
+func (p *importer) field() *Node {
+ sym := p.fieldName()
+ typ := p.typ()
+ note := p.note()
+
+ var n *Node
+ if sym.Name != "" {
+ n = Nod(ODCLFIELD, newname(sym), typenod(typ))
+ } else {
+ // anonymous field - typ must be T or *T and T must be a type name
+ s := typ.Sym
+ if s == nil && Isptr[typ.Etype] {
+ s = typ.Type.Sym // deref
+ }
+ pkg := importpkg
+ if sym != nil {
+ pkg = sym.Pkg
+ }
+ n = embedded(s, pkg)
+ n.Right = typenod(typ)
+ }
+ n.SetVal(note)
+
+ return n
+}
+
+func (p *importer) note() (v Val) {
+ if s := p.string(); s != "" {
+ v.U = s
+ }
+ return
+}
+
+// go.y:hidden_interfacedcl_list
+func (p *importer) methodList() *NodeList {
+ i := p.int()
+ if i == 0 {
+ return nil
+ }
+ n := list1(p.method())
+ for i--; i > 0; i-- {
+ n = list(n, p.method())
+ }
+ return n
+}
+
+// go.y:hidden_interfacedcl
+func (p *importer) method() *Node {
+ sym := p.fieldName()
+ params := p.paramList()
+ result := p.paramList()
+ return Nod(ODCLFIELD, newname(sym), typenod(functype(fakethis(), params, result)))
+}
+
+// go.y:sym,hidden_importsym
+func (p *importer) fieldName() *Sym {
+ name := p.string()
+ pkg := localpkg
+ if name == "_" {
+ // During imports, unqualified non-exported identifiers are from builtinpkg
+ // (see go.y:sym). The binary exporter only exports blank as a non-exported
+ // identifier without qualification.
+ pkg = builtinpkg
+ } else if name == "?" || name != "" && !exportname(name) {
+ if name == "?" {
+ name = ""
+ }
+ pkg = p.pkg()
+ }
+ return pkg.Lookup(name)
+}
+
+// go.y:ohidden_funarg_list
+func (p *importer) paramList() *NodeList {
+ i := p.int()
+ if i == 0 {
+ return nil
+ }
+ // negative length indicates unnamed parameters
+ named := true
+ if i < 0 {
+ i = -i
+ named = false
+ }
+ // i > 0
+ n := list1(p.param(named))
+ i--
+ for ; i > 0; i-- {
+ n = list(n, p.param(named))
+ }
+ return n
+}
+
+// go.y:hidden_funarg
+func (p *importer) param(named bool) *Node {
+ typ := p.typ()
+
+ isddd := false
+ if typ.Etype == T_old_DARRAY {
+ // T_old_DARRAY indicates ... type
+ typ.Etype = TARRAY
+ isddd = true
+ }
+
+ n := Nod(ODCLFIELD, nil, typenod(typ))
+ n.Isddd = isddd
+
+ if named {
+ name := p.string()
+ if name == "" {
+ Fatalf("expected named parameter")
+ }
+ // The parameter package doesn't matter; it's never consulted.
+ // We use the builtinpkg per go.y:sym (line 1181).
+ n.Left = newname(builtinpkg.Lookup(name))
+ }
+
+ // TODO(gri) This is compiler-specific (escape info).
+ // Move into compiler-specific section eventually?
+ n.SetVal(p.note())
+
+ return n
+}
+
+func (p *importer) value(typ *Type) (x Val) {
+ switch tag := p.tagOrIndex(); tag {
+ case falseTag:
+ x.U = false
+ case trueTag:
+ x.U = true
+ case int64Tag:
+ u := new(Mpint)
+ Mpmovecfix(u, p.int64())
+ u.Rune = typ == idealrune
+ x.U = u
+ case floatTag:
+ f := newMpflt()
+ p.float(f)
+ if typ == idealint || Isint[typ.Etype] {
+ // uncommon case: large int encoded as float
+ u := new(Mpint)
+ mpmovefltfix(u, f)
+ x.U = u
+ break
+ }
+ x.U = f
+ case complexTag:
+ u := new(Mpcplx)
+ p.float(&u.Real)
+ p.float(&u.Imag)
+ x.U = u
+ case stringTag:
+ x.U = p.string()
+ default:
+ Fatalf("unexpected value tag %d", tag)
+ }
+
+ // verify ideal type
+ if isideal(typ) && untype(x.Ctype()) != typ {
+ Fatalf("value %v and type %v don't match", x, typ)
+ }
+
+ return
+}
+
+func (p *importer) float(x *Mpflt) {
+ sign := p.int()
+ if sign == 0 {
+ Mpmovecflt(x, 0)
+ return
+ }
+
+ exp := p.int()
+ mant := new(big.Int).SetBytes([]byte(p.string()))
+
+ m := x.Val.SetInt(mant)
+ m.SetMantExp(m, exp-mant.BitLen())
+ if sign < 0 {
+ m.Neg(m)
+ }
+}
+
+// ----------------------------------------------------------------------------
+// Inlined function bodies
+
+func (p *importer) body() {
+ p.int()
+ p.block()
+}
+
+func (p *importer) block() {
+ for i := p.int(); i > 0; i-- {
+ p.stmt()
+ }
+}
+
+func (p *importer) stmt() {
+ // TODO(gri) do something sensible here
+ p.string()
+}
+
+// ----------------------------------------------------------------------------
+// Low-level decoders
+
+func (p *importer) tagOrIndex() int {
+ if p.debugFormat {
+ p.marker('t')
+ }
+
+ return int(p.rawInt64())
+}
+
+func (p *importer) int() int {
+ x := p.int64()
+ if int64(int(x)) != x {
+ Fatalf("exported integer too large")
+ }
+ return int(x)
+}
+
+func (p *importer) int64() int64 {
+ if p.debugFormat {
+ p.marker('i')
+ }
+
+ return p.rawInt64()
+}
+
+func (p *importer) string() string {
+ if p.debugFormat {
+ p.marker('s')
+ }
+
+ if n := int(p.rawInt64()); n > 0 {
+ if cap(p.buf) < n {
+ p.buf = make([]byte, n)
+ } else {
+ p.buf = p.buf[:n]
+ }
+ for i := 0; i < n; i++ {
+ p.buf[i] = p.byte()
+ }
+ return string(p.buf)
+ }
+
+ return ""
+}
+
+func (p *importer) marker(want byte) {
+ if got := p.byte(); got != want {
+ Fatalf("incorrect marker: got %c; want %c (pos = %d)", got, want, p.read)
+ }
+
+ pos := p.read
+ if n := int(p.rawInt64()); n != pos {
+ Fatalf("incorrect position: got %d; want %d", n, pos)
+ }
+}
+
+// rawInt64 should only be used by low-level decoders
+func (p *importer) rawInt64() int64 {
+ i, err := binary.ReadVarint(p)
+ if err != nil {
+ Fatalf("read error: %v", err)
+ }
+ return i
+}
+
+// needed for binary.ReadVarint in rawInt64
+func (p *importer) ReadByte() (byte, error) {
+ return p.byte(), nil
+}
+
+// byte is the bottleneck interface for reading from p.in.
+// It unescapes '|' 'S' to '$' and '|' '|' to '|'.
+func (p *importer) byte() byte {
+ c := obj.Bgetc(p.in)
+ p.read++
+ if c < 0 {
+ Fatalf("read error")
+ }
+ if c == '|' {
+ c = obj.Bgetc(p.in)
+ p.read++
+ if c < 0 {
+ Fatalf("read error")
+ }
+ switch c {
+ case 'S':
+ c = '$'
+ case '|':
+ // nothing to do
+ default:
+ Fatalf("unexpected escape sequence in export data")
+ }
+ }
+ return byte(c)
+}
const runtimeimport = "" +
"package runtime\n" +
- "import runtime \"runtime\"\n" +
"func @\"\".newobject (@\"\".typ·2 *byte) (? *any)\n" +
"func @\"\".panicindex ()\n" +
"func @\"\".panicslice ()\n" +
"func @\"\".chanrecv2 (@\"\".chanType·2 *byte, @\"\".hchan·3 <-chan any, @\"\".elem·4 *any) (? bool)\n" +
"func @\"\".chansend1 (@\"\".chanType·1 *byte, @\"\".hchan·2 chan<- any, @\"\".elem·3 *any)\n" +
"func @\"\".closechan (@\"\".hchan·1 any)\n" +
- "var @\"\".writeBarrierEnabled bool\n" +
+ "var @\"\".writeBarrier struct { @\"\".enabled bool; @\"\".needed bool; @\"\".cgo bool }\n" +
"func @\"\".writebarrierptr (@\"\".dst·1 *any, @\"\".src·2 any)\n" +
"func @\"\".writebarrierstring (@\"\".dst·1 *any, @\"\".src·2 any)\n" +
"func @\"\".writebarrierslice (@\"\".dst·1 *any, @\"\".src·2 any)\n" +
"func @\"\".racewrite (? uintptr)\n" +
"func @\"\".racereadrange (@\"\".addr·1 uintptr, @\"\".size·2 uintptr)\n" +
"func @\"\".racewriterange (@\"\".addr·1 uintptr, @\"\".size·2 uintptr)\n" +
+ "func @\"\".msanread (@\"\".addr·1 uintptr, @\"\".size·2 uintptr)\n" +
+ "func @\"\".msanwrite (@\"\".addr·1 uintptr, @\"\".size·2 uintptr)\n" +
"\n" +
"$$\n"
const unsafeimport = "" +
"package unsafe\n" +
- "import runtime \"runtime\"\n" +
"type @\"\".Pointer uintptr\n" +
"func @\"\".Offsetof (? any) (? uintptr)\n" +
"func @\"\".Sizeof (? any) (? uintptr)\n" +
func chansend1(chanType *byte, hchan chan<- any, elem *any)
func closechan(hchan any)
-var writeBarrierEnabled bool
+var writeBarrier struct {
+ enabled bool
+ needed bool
+ cgo bool
+}
func writebarrierptr(dst *any, src any)
func writebarrierstring(dst *any, src any)
func racewrite(uintptr)
func racereadrange(addr, size uintptr)
func racewriterange(addr, size uintptr)
+
+// memory sanitizer
+func msanread(addr, size uintptr)
+func msanwrite(addr, size uintptr)
return out
}
-/* difference */
+// difference
func bvandnot(dst Bvec, src1 Bvec, src2 Bvec) {
for i, x := range src1.b {
dst.b[i] = x &^ src2.b[i]
}
}
-/* union */
+// union
func bvor(dst Bvec, src1 Bvec, src2 Bvec) {
for i, x := range src1.b {
dst.b[i] = x | src2.b[i]
}
}
-/* intersection */
+// intersection
func bvand(dst Bvec, src1 Bvec, src2 Bvec) {
for i, x := range src1.b {
dst.b[i] = x & src2.b[i]
import (
"cmd/internal/obj"
+ "cmd/internal/obj/ppc64"
"fmt"
)
-/*
- * generate:
- * res = n;
- * simplifies and calls Thearch.Gmove.
- * if wb is true, need to emit write barriers.
- */
+// generate:
+// res = n;
+// simplifies and calls Thearch.Gmove.
+// if wb is true, need to emit write barriers.
func Cgen(n, res *Node) {
cgen_wb(n, res, false)
}
}
if wb {
- if int(Simtype[res.Type.Etype]) != Tptr {
+ if Simtype[res.Type.Etype] != Tptr {
Fatalf("cgen_wb of type %v", res.Type)
}
if n.Ullman >= UINF {
return
}
- if Ctxt.Arch.Thechar == '7' || Ctxt.Arch.Thechar == '9' {
+ if Ctxt.Arch.Thechar == '0' || Ctxt.Arch.Thechar == '7' || Ctxt.Arch.Thechar == '9' {
// if both are addressable, move
if n.Addable {
if n.Op == OREGISTER || res.Op == OREGISTER {
goto sbop
}
- a := Thearch.Optoas(int(n.Op), nl.Type)
+ a := Thearch.Optoas(n.Op, nl.Type)
// unary
var n1 Node
Regalloc(&n1, nl.Type, res)
OXOR,
OADD,
OMUL:
- if n.Op == OMUL && Thearch.Cgen_bmul != nil && Thearch.Cgen_bmul(int(n.Op), nl, nr, res) {
+ if n.Op == OMUL && Thearch.Cgen_bmul != nil && Thearch.Cgen_bmul(n.Op, nl, nr, res) {
break
}
- a = Thearch.Optoas(int(n.Op), nl.Type)
+ a = Thearch.Optoas(n.Op, nl.Type)
goto sbop
// asymmetric binary
case OSUB:
- a = Thearch.Optoas(int(n.Op), nl.Type)
+ a = Thearch.Optoas(n.Op, nl.Type)
goto abop
case OHMUL:
case OMOD, ODIV:
if Isfloat[n.Type.Etype] || Thearch.Dodiv == nil {
- a = Thearch.Optoas(int(n.Op), nl.Type)
+ a = Thearch.Optoas(n.Op, nl.Type)
goto abop
}
var n1 Node
Regalloc(&n1, nl.Type, res)
Cgen(nl, &n1)
- cgen_div(int(n.Op), &n1, nr, res)
+ cgen_div(n.Op, &n1, nr, res)
Regfree(&n1)
} else {
var n2 Node
n2 = *nr
}
- cgen_div(int(n.Op), nl, &n2, res)
+ cgen_div(n.Op, nl, &n2, res)
if n2.Op != OLITERAL {
Regfree(&n2)
}
}
case OLSH, ORSH, OLROT:
- Thearch.Cgen_shift(int(n.Op), n.Bounded, nl, nr, res)
+ Thearch.Cgen_shift(n.Op, n.Bounded, nl, nr, res)
}
return
- /*
- * put simplest on right - we'll generate into left
- * and then adjust it using the computation of right.
- * constants and variables have the same ullman
- * count, so look for constants specially.
- *
- * an integer constant we can use as an immediate
- * is simpler than a variable - we can use the immediate
- * in the adjustment instruction directly - so it goes
- * on the right.
- *
- * other constants, like big integers or floating point
- * constants, require a mov into a register, so those
- * might as well go on the left, so we can reuse that
- * register for the computation.
- */
+ // put simplest on right - we'll generate into left
+ // and then adjust it using the computation of right.
+ // constants and variables have the same ullman
+ // count, so look for constants specially.
+ //
+ // an integer constant we can use as an immediate
+ // is simpler than a variable - we can use the immediate
+ // in the adjustment instruction directly - so it goes
+ // on the right.
+ //
+ // other constants, like big integers or floating point
+ // constants, require a mov into a register, so those
+ // might as well go on the left, so we can reuse that
+ // register for the computation.
sbop: // symmetric binary
if nl.Ullman < nr.Ullman || (nl.Ullman == nr.Ullman && (Smallintconst(nl) || (nr.Op == OLITERAL && !Smallintconst(nr)))) {
nl, nr = nr, nl
Regalloc(&n1, nl.Type, res)
Cgen(nl, &n1)
- if Smallintconst(nr) && Ctxt.Arch.Thechar != '5' && Ctxt.Arch.Thechar != '7' && Ctxt.Arch.Thechar != '9' { // TODO(rsc): Check opcode for arm
+ if Smallintconst(nr) && Ctxt.Arch.Thechar != '0' && Ctxt.Arch.Thechar != '5' && Ctxt.Arch.Thechar != '7' && Ctxt.Arch.Thechar != '9' { // TODO(rsc): Check opcode for arm
n2 = *nr
} else {
Regalloc(&n2, nr.Type, nil)
Cgen(nr, &n2)
}
} else {
- if Smallintconst(nr) && Ctxt.Arch.Thechar != '5' && Ctxt.Arch.Thechar != '7' && Ctxt.Arch.Thechar != '9' { // TODO(rsc): Check opcode for arm
+ if Smallintconst(nr) && Ctxt.Arch.Thechar != '0' && Ctxt.Arch.Thechar != '5' && Ctxt.Arch.Thechar != '7' && Ctxt.Arch.Thechar != '9' { // TODO(rsc): Check opcode for arm
n2 = *nr
} else {
Regalloc(&n2, nr.Type, res)
var sys_wbptr *Node
func cgen_wbptr(n, res *Node) {
- if Curfn != nil && Curfn.Func.Nowritebarrier {
- Yyerror("write barrier prohibited")
+ if Curfn != nil {
+ if Curfn.Func.Nowritebarrier {
+ Yyerror("write barrier prohibited")
+ }
+ if Curfn.Func.WBLineno == 0 {
+ Curfn.Func.WBLineno = lineno
+ }
}
if Debug_wb > 0 {
Warn("write barrier")
Cgenr(n, &src, nil)
}
- wbEnabled := syslook("writeBarrierEnabled", 0)
+ wbVar := syslook("writeBarrier", 0)
+ wbEnabled := Nod(ODOT, wbVar, newname(wbVar.Type.Type.Sym))
+ wbEnabled = typecheck(&wbEnabled, Erv)
pbr := Thearch.Ginscmp(ONE, Types[TUINT8], wbEnabled, Nodintconst(0), -1)
Thearch.Gins(Thearch.Optoas(OAS, Types[Tptr]), &src, &dst)
pjmp := Gbranch(obj.AJMP, nil, 0)
}
func cgen_wbfat(n, res *Node) {
- if Curfn != nil && Curfn.Func.Nowritebarrier {
- Yyerror("write barrier prohibited")
+ if Curfn != nil {
+ if Curfn.Func.Nowritebarrier {
+ Yyerror("write barrier prohibited")
+ }
+ if Curfn.Func.WBLineno == 0 {
+ Curfn.Func.WBLineno = lineno
+ }
}
if Debug_wb > 0 {
Warn("write barrier")
}
}
-/*
- * allocate a register (reusing res if possible) and generate
- * a = n
- * The caller must call Regfree(a).
- */
+// allocate a register (reusing res if possible) and generate
+// a = n
+// The caller must call Regfree(a).
func Cgenr(n *Node, a *Node, res *Node) {
if Debug['g'] != 0 {
Dump("cgenr-n", n)
}
}
-/*
- * allocate a register (reusing res if possible) and generate
- * a = &n
- * The caller must call Regfree(a).
- * The generated code checks that the result is not nil.
- */
+// allocate a register (reusing res if possible) and generate
+// a = &n
+// The caller must call Regfree(a).
+// The generated code checks that the result is not nil.
func Agenr(n *Node, a *Node, res *Node) {
if Debug['g'] != 0 {
Dump("\nagenr-n", n)
return x
}
-/*
- * generate:
- * res = &n;
- * The generated code checks that the result is not nil.
- */
+// generate:
+// res = &n;
+// The generated code checks that the result is not nil.
func Agen(n *Node, res *Node) {
if Debug['g'] != 0 {
Dump("\nagen-res", res)
// but they don't support direct generation of a bool value yet.
// We can fix that as we go.
switch Ctxt.Arch.Thechar {
- case '5', '7', '9':
- Fatalf("genval 5g, 7g, 9g ONAMES not fully implemented")
+ case '0', '5', '7', '9':
+ Fatalf("genval 0g, 5g, 7g, 9g ONAMES not fully implemented")
}
Cgen(n, res)
if !wantTrue {
return
}
- if n.Addable && Ctxt.Arch.Thechar != '5' && Ctxt.Arch.Thechar != '7' && Ctxt.Arch.Thechar != '9' {
+ if n.Addable && Ctxt.Arch.Thechar != '0' && Ctxt.Arch.Thechar != '5' && Ctxt.Arch.Thechar != '7' && Ctxt.Arch.Thechar != '9' {
// no need for a temporary
bgenNonZero(n, nil, wantTrue, likely, to)
return
// n.Op is one of OEQ, ONE, OLT, OGT, OLE, OGE
nl := n.Left
nr := n.Right
- a := int(n.Op)
+ op := n.Op
if !wantTrue {
if Isfloat[nr.Type.Etype] {
return
}
- a = Brcom(a)
+ op = Brcom(op)
}
wantTrue = true
// make simplest on right
if nl.Op == OLITERAL || (nl.Ullman < nr.Ullman && nl.Ullman < UINF) {
- a = Brrev(a)
+ op = Brrev(op)
nl, nr = nr, nl
}
if Isslice(nl.Type) || Isinter(nl.Type) {
// front end should only leave cmp to literal nil
- if (a != OEQ && a != ONE) || nr.Op != OLITERAL {
+ if (op != OEQ && op != ONE) || nr.Op != OLITERAL {
if Isslice(nl.Type) {
Yyerror("illegal slice comparison")
} else {
Regalloc(&tmp, ptr.Type, &ptr)
Cgen(&ptr, &tmp)
Regfree(&ptr)
- bgenNonZero(&tmp, res, a == OEQ != wantTrue, likely, to)
+ bgenNonZero(&tmp, res, op == OEQ != wantTrue, likely, to)
Regfree(&tmp)
return
}
if Iscomplex[nl.Type.Etype] {
- complexbool(a, nl, nr, res, wantTrue, likely, to)
+ complexbool(op, nl, nr, res, wantTrue, likely, to)
return
}
if !nr.Addable {
nr = CgenTemp(nr)
}
- Thearch.Cmp64(nl, nr, a, likely, to)
+ Thearch.Cmp64(nl, nr, op, likely, to)
return
}
Cgen(nl, &n1)
nl = &n1
- if Smallintconst(nr) && Ctxt.Arch.Thechar != '9' {
+ if Smallintconst(nr) && Ctxt.Arch.Thechar != '0' && Ctxt.Arch.Thechar != '9' {
Thearch.Gins(Thearch.Optoas(OCMP, nr.Type), nl, nr)
- bins(nr.Type, res, a, likely, to)
+ bins(nr.Type, res, op, likely, to)
return
}
l, r := nl, nr
// On x86, only < and <= work right with NaN; reverse if needed
- if Ctxt.Arch.Thechar == '6' && Isfloat[nl.Type.Etype] && (a == OGT || a == OGE) {
+ if Ctxt.Arch.Thechar == '6' && Isfloat[nl.Type.Etype] && (op == OGT || op == OGE) {
l, r = r, l
- a = Brrev(a)
+ op = Brrev(op)
+ }
+
+ // MIPS does not have CMP instruction
+ if Ctxt.Arch.Thechar == '0' {
+ p := Thearch.Ginscmp(op, nr.Type, l, r, likely)
+ Patch(p, to)
+ return
}
// Do the comparison.
switch n.Op {
case ONE:
Patch(Gbranch(Thearch.Optoas(OPS, nr.Type), nr.Type, likely), to)
- Patch(Gbranch(Thearch.Optoas(a, nr.Type), nr.Type, likely), to)
+ Patch(Gbranch(Thearch.Optoas(op, nr.Type), nr.Type, likely), to)
default:
p := Gbranch(Thearch.Optoas(OPS, nr.Type), nr.Type, -likely)
- Patch(Gbranch(Thearch.Optoas(a, nr.Type), nr.Type, likely), to)
+ Patch(Gbranch(Thearch.Optoas(op, nr.Type), nr.Type, likely), to)
Patch(p, Pc)
}
return
// On arm64 and ppc64, <= and >= mishandle NaN. Must decompose into < or > and =.
// TODO(josh): Convert a <= b to b > a instead?
case OLE, OGE:
- if a == OLE {
- a = OLT
+ if op == OLE {
+ op = OLT
} else {
- a = OGT
+ op = OGT
}
- Patch(Gbranch(Thearch.Optoas(a, nr.Type), nr.Type, likely), to)
+ Patch(Gbranch(Thearch.Optoas(op, nr.Type), nr.Type, likely), to)
Patch(Gbranch(Thearch.Optoas(OEQ, nr.Type), nr.Type, likely), to)
return
}
}
// Not a special case. Insert the conditional jump or value gen.
- bins(nr.Type, res, a, likely, to)
+ bins(nr.Type, res, op, likely, to)
}
func bgenNonZero(n, res *Node, wantTrue bool, likely int, to *obj.Prog) {
// TODO: Optimize on systems that can compare to zero easily.
- a := ONE
+ var op Op = ONE
if !wantTrue {
- a = OEQ
+ op = OEQ
}
+
+ // MIPS does not have CMP instruction
+ if Thearch.Thechar == '0' {
+ p := Gbranch(Thearch.Optoas(op, n.Type), n.Type, likely)
+ Naddr(&p.From, n)
+ Patch(p, to)
+ return
+ }
+
var zero Node
Nodconst(&zero, n.Type, 0)
Thearch.Gins(Thearch.Optoas(OCMP, n.Type), n, &zero)
- bins(n.Type, res, a, likely, to)
+ bins(n.Type, res, op, likely, to)
}
// bins inserts an instruction to handle the result of a compare.
// If res is non-nil, it inserts appropriate value generation instructions.
// If res is nil, it inserts a branch to to.
-func bins(typ *Type, res *Node, a, likely int, to *obj.Prog) {
- a = Thearch.Optoas(a, typ)
+func bins(typ *Type, res *Node, op Op, likely int, to *obj.Prog) {
+ a := Thearch.Optoas(op, typ)
if res != nil {
// value gen
Thearch.Ginsboolval(a, res)
return -1000 // not on stack
}
-/*
- * block copy:
- * memmove(&ns, &n, w);
- * if wb is true, needs write barrier.
- */
+// block copy:
+// memmove(&ns, &n, w);
+// if wb is true, needs write barrier.
func sgen_wb(n *Node, ns *Node, w int64, wb bool) {
if Debug['g'] != 0 {
op := "sgen"
Thearch.Blockcopy(n, ns, osrc, odst, w)
}
-/*
- * generate:
- * call f
- * proc=-1 normal call but no return
- * proc=0 normal call
- * proc=1 goroutine run in new proc
- * proc=2 defer call save away stack
- * proc=3 normal call to C pointer (not Go func value)
-*/
+// generate:
+// call f
+// proc=-1 normal call but no return
+// proc=0 normal call
+// proc=1 goroutine run in new proc
+// proc=2 defer call save away stack
+// proc=3 normal call to C pointer (not Go func value)
func Ginscall(f *Node, proc int) {
if f.Type != nil {
extra := int32(0)
-1: // normal call but no return
if f.Op == ONAME && f.Class == PFUNC {
if f == Deferreturn {
- // Deferred calls will appear to be returning to
- // the CALL deferreturn(SB) that we are about to emit.
- // However, the stack trace code will show the line
- // of the instruction byte before the return PC.
- // To avoid that being an unrelated instruction,
- // insert an actual hardware NOP that will have the right line number.
- // This is different from obj.ANOP, which is a virtual no-op
- // that doesn't make it into the instruction stream.
+ // Deferred calls will appear to be returning to the CALL
+ // deferreturn(SB) that we are about to emit. However, the
+ // stack scanning code will think that the instruction
+ // before the CALL is executing. To avoid the scanning
+ // code making bad assumptions (both cosmetic such as
+ // showing the wrong line number and fatal, such as being
+ // confused over whether a stack slot contains a pointer
+ // or a scalar) insert an actual hardware NOP that will
+ // have the right line number. This is different from
+ // obj.ANOP, which is a virtual no-op that doesn't make it
+ // into the instruction stream.
Thearch.Ginsnop()
+
+ if Thearch.Thechar == '9' {
+ // On ppc64, when compiling Go into position
+ // independent code on ppc64le we insert an
+ // instruction to reload the TOC pointer from the
+ // stack as well. See the long comment near
+ // jmpdefer in runtime/asm_ppc64.s for why.
+ // If the MOVD is not needed, insert a hardware NOP
+ // so that the same number of instructions are used
+ // on ppc64 in both shared and non-shared modes.
+ if Ctxt.Flag_shared != 0 {
+ p := Thearch.Gins(ppc64.AMOVD, nil, nil)
+ p.From.Type = obj.TYPE_MEM
+ p.From.Offset = 24
+ p.From.Reg = ppc64.REGSP
+ p.To.Type = obj.TYPE_REG
+ p.To.Reg = ppc64.REG_R2
+ } else {
+ Thearch.Ginsnop()
+ }
+ }
}
p := Thearch.Gins(obj.ACALL, nil, f)
}
}
-/*
- * n is call to interface method.
- * generate res = n.
- */
+// n is call to interface method.
+// generate res = n.
func cgen_callinter(n *Node, res *Node, proc int) {
i := n.Left
if i.Op != ODOTINTER {
Regfree(&nodo)
}
-/*
- * generate function call;
- * proc=0 normal call
- * proc=1 goroutine run in new proc
- * proc=2 defer call save away stack
- */
+// generate function call;
+// proc=0 normal call
+// proc=1 goroutine run in new proc
+// proc=2 defer call save away stack
func cgen_call(n *Node, proc int) {
if n == nil {
return
Ginscall(n.Left, proc)
}
-/*
- * call to n has already been generated.
- * generate:
- * res = return value from call.
- */
+// call to n has already been generated.
+// generate:
+// res = return value from call.
func cgen_callret(n *Node, res *Node) {
t := n.Left.Type
if t.Etype == TPTR32 || t.Etype == TPTR64 {
Cgen_as(res, &nod)
}
-/*
- * call to n has already been generated.
- * generate:
- * res = &return value from call.
- */
+// call to n has already been generated.
+// generate:
+// res = &return value from call.
func cgen_aret(n *Node, res *Node) {
t := n.Left.Type
if Isptr[t.Etype] {
}
}
-/*
- * generate return.
- * n->left is assignments to return values.
- */
+// generate return.
+// n->left is assignments to return values.
func cgen_ret(n *Node) {
if n != nil {
Genlist(n.List) // copy out args
}
}
-/*
- * generate division according to op, one of:
- * res = nl / nr
- * res = nl % nr
- */
-func cgen_div(op int, nl *Node, nr *Node, res *Node) {
+// generate division according to op, one of:
+// res = nl / nr
+// res = nl % nr
+func cgen_div(op Op, nl *Node, nr *Node, res *Node) {
var w int
// TODO(rsc): arm64 needs to support the relevant instructions
// in peep and optoas in order to enable this.
// TODO(rsc): ppc64 needs to support the relevant instructions
// in peep and optoas in order to enable this.
- if nr.Op != OLITERAL || Ctxt.Arch.Thechar == '7' || Ctxt.Arch.Thechar == '9' {
+ if nr.Op != OLITERAL || Ctxt.Arch.Thechar == '0' || Ctxt.Arch.Thechar == '7' || Ctxt.Arch.Thechar == '9' {
goto longdiv
}
w = int(nl.Type.Width * 8)
"fmt"
)
-/*
- * function literals aka closures
- */
+// function literals aka closures
func closurehdr(ntype *Node) {
var name *Node
var a *Node
}
func makeclosure(func_ *Node) *Node {
- /*
- * wrap body in external function
- * that begins by reading closure parameters.
- */
+ // wrap body in external function
+ // that begins by reading closure parameters.
xtype := Nod(OTFUNC, nil, nil)
xtype.List = func_.List
return n.Val().U.(bool)
}
-/*
- * truncate float literal fv to 32-bit or 64-bit precision
- * according to type; return truncated value.
- */
+// truncate float literal fv to 32-bit or 64-bit precision
+// according to type; return truncated value.
func truncfltlit(oldv *Mpflt, t *Type) *Mpflt {
if t == nil {
return oldv
return fv
}
-/*
- * convert n, if literal, to type t.
- * implicit conversion.
- */
+// convert n, if literal, to type t.
+// implicit conversion.
func Convlit(np **Node, t *Type) {
convlit1(np, t, false)
}
-/*
- * convert n, if literal, to type t.
- * return a new node if necessary
- * (if n is a named constant, can't edit n->type directly).
- */
+// convert n, if literal, to type t.
+// return a new node if necessary
+//(if n is a named constant, can't edit n->type directly).
func convlit1(np **Node, t *Type, explicit bool) {
n := *np
if n == nil || t == nil || n.Type == nil || isideal(t) || n.Type == t {
if n.Type.Etype == TUNSAFEPTR && t.Etype != TUINTPTR {
goto bad
}
- ct := int(n.Val().Ctype())
+ ct := n.Val().Ctype()
if Isint[et] {
switch ct {
default:
n.SetVal(toint(n.Val()))
fallthrough
- // flowthrough
case CTINT:
overflow(n.Val(), t)
}
n.SetVal(toflt(n.Val()))
fallthrough
- // flowthrough
case CTFLT:
n.SetVal(Val{truncfltlit(n.Val().U.(*Mpflt), t)})
}
case CTFLT, CTINT, CTRUNE:
n.SetVal(tocplx(n.Val()))
+ fallthrough
case CTCPLX:
overflow(n.Val(), t)
return v
}
-func consttype(n *Node) int {
+func consttype(n *Node) Ctype {
if n == nil || n.Op != OLITERAL {
return -1
}
- return int(n.Val().Ctype())
+ return n.Val().Ctype()
}
-func Isconst(n *Node, ct int) bool {
+func Isconst(n *Node, ct Ctype) bool {
t := consttype(n)
// If the caller is asking for CTINT, allow CTRUNE too.
return n.Orig
}
-/*
- * if n is constant, rewrite as OLITERAL node.
- */
+// if n is constant, rewrite as OLITERAL node.
func evconst(n *Node) {
// pick off just the opcodes that can be
// constant evaluated.
wl = TIDEAL
}
+ // avoid constant conversions in switches below
+ const (
+ CTINT_ = uint32(CTINT)
+ CTRUNE_ = uint32(CTRUNE)
+ CTFLT_ = uint32(CTFLT)
+ CTCPLX_ = uint32(CTCPLX)
+ CTSTR_ = uint32(CTSTR)
+ CTBOOL_ = uint32(CTBOOL)
+ CTNIL_ = uint32(CTNIL)
+ OCONV_ = uint32(OCONV) << 16
+ OARRAYBYTESTR_ = uint32(OARRAYBYTESTR) << 16
+ OPLUS_ = uint32(OPLUS) << 16
+ OMINUS_ = uint32(OMINUS) << 16
+ OCOM_ = uint32(OCOM) << 16
+ ONOT_ = uint32(ONOT) << 16
+ OLSH_ = uint32(OLSH) << 16
+ ORSH_ = uint32(ORSH) << 16
+ OADD_ = uint32(OADD) << 16
+ OSUB_ = uint32(OSUB) << 16
+ OMUL_ = uint32(OMUL) << 16
+ ODIV_ = uint32(ODIV) << 16
+ OMOD_ = uint32(OMOD) << 16
+ OOR_ = uint32(OOR) << 16
+ OAND_ = uint32(OAND) << 16
+ OANDNOT_ = uint32(OANDNOT) << 16
+ OXOR_ = uint32(OXOR) << 16
+ OEQ_ = uint32(OEQ) << 16
+ ONE_ = uint32(ONE) << 16
+ OLT_ = uint32(OLT) << 16
+ OLE_ = uint32(OLE) << 16
+ OGE_ = uint32(OGE) << 16
+ OGT_ = uint32(OGT) << 16
+ OOROR_ = uint32(OOROR) << 16
+ OANDAND_ = uint32(OANDAND) << 16
+ )
+
nr := n.Right
var rv Val
var lno int
Yyerror("illegal constant expression %v %v", Oconv(int(n.Op), 0), nl.Type)
n.Diag = 1
}
-
return
- case OCONV<<16 | CTNIL,
- OARRAYBYTESTR<<16 | CTNIL:
+ case OCONV_ | CTNIL_,
+ OARRAYBYTESTR_ | CTNIL_:
if n.Type.Etype == TSTRING {
v = tostr(v)
nl.Type = n.Type
fallthrough
// fall through
- case OCONV<<16 | CTINT,
- OCONV<<16 | CTRUNE,
- OCONV<<16 | CTFLT,
- OCONV<<16 | CTSTR:
+ case OCONV_ | CTINT_,
+ OCONV_ | CTRUNE_,
+ OCONV_ | CTFLT_,
+ OCONV_ | CTSTR_:
convlit1(&nl, n.Type, true)
v = nl.Val()
- case OPLUS<<16 | CTINT,
- OPLUS<<16 | CTRUNE:
+ case OPLUS_ | CTINT_,
+ OPLUS_ | CTRUNE_:
break
- case OMINUS<<16 | CTINT,
- OMINUS<<16 | CTRUNE:
+ case OMINUS_ | CTINT_,
+ OMINUS_ | CTRUNE_:
mpnegfix(v.U.(*Mpint))
- case OCOM<<16 | CTINT,
- OCOM<<16 | CTRUNE:
+ case OCOM_ | CTINT_,
+ OCOM_ | CTRUNE_:
et := Txxx
if nl.Type != nil {
et = int(nl.Type.Etype)
mpxorfixfix(v.U.(*Mpint), &b)
- case OPLUS<<16 | CTFLT:
+ case OPLUS_ | CTFLT_:
break
- case OMINUS<<16 | CTFLT:
+ case OMINUS_ | CTFLT_:
mpnegflt(v.U.(*Mpflt))
- case OPLUS<<16 | CTCPLX:
+ case OPLUS_ | CTCPLX_:
break
- case OMINUS<<16 | CTCPLX:
+ case OMINUS_ | CTCPLX_:
mpnegflt(&v.U.(*Mpcplx).Real)
mpnegflt(&v.U.(*Mpcplx).Imag)
- case ONOT<<16 | CTBOOL:
+ case ONOT_ | CTBOOL_:
if !v.U.(bool) {
goto settrue
}
default:
goto illegal
- case OADD<<16 | CTINT,
- OADD<<16 | CTRUNE:
+ case OADD_ | CTINT_,
+ OADD_ | CTRUNE_:
mpaddfixfix(v.U.(*Mpint), rv.U.(*Mpint), 0)
- case OSUB<<16 | CTINT,
- OSUB<<16 | CTRUNE:
+ case OSUB_ | CTINT_,
+ OSUB_ | CTRUNE_:
mpsubfixfix(v.U.(*Mpint), rv.U.(*Mpint))
- case OMUL<<16 | CTINT,
- OMUL<<16 | CTRUNE:
+ case OMUL_ | CTINT_,
+ OMUL_ | CTRUNE_:
mpmulfixfix(v.U.(*Mpint), rv.U.(*Mpint))
- case ODIV<<16 | CTINT,
- ODIV<<16 | CTRUNE:
+ case ODIV_ | CTINT_,
+ ODIV_ | CTRUNE_:
if mpcmpfixc(rv.U.(*Mpint), 0) == 0 {
Yyerror("division by zero")
mpsetovf(v.U.(*Mpint))
mpdivfixfix(v.U.(*Mpint), rv.U.(*Mpint))
- case OMOD<<16 | CTINT,
- OMOD<<16 | CTRUNE:
+ case OMOD_ | CTINT_,
+ OMOD_ | CTRUNE_:
if mpcmpfixc(rv.U.(*Mpint), 0) == 0 {
Yyerror("division by zero")
mpsetovf(v.U.(*Mpint))
mpmodfixfix(v.U.(*Mpint), rv.U.(*Mpint))
- case OLSH<<16 | CTINT,
- OLSH<<16 | CTRUNE:
+ case OLSH_ | CTINT_,
+ OLSH_ | CTRUNE_:
mplshfixfix(v.U.(*Mpint), rv.U.(*Mpint))
- case ORSH<<16 | CTINT,
- ORSH<<16 | CTRUNE:
+ case ORSH_ | CTINT_,
+ ORSH_ | CTRUNE_:
mprshfixfix(v.U.(*Mpint), rv.U.(*Mpint))
- case OOR<<16 | CTINT,
- OOR<<16 | CTRUNE:
+ case OOR_ | CTINT_,
+ OOR_ | CTRUNE_:
mporfixfix(v.U.(*Mpint), rv.U.(*Mpint))
- case OAND<<16 | CTINT,
- OAND<<16 | CTRUNE:
+ case OAND_ | CTINT_,
+ OAND_ | CTRUNE_:
mpandfixfix(v.U.(*Mpint), rv.U.(*Mpint))
- case OANDNOT<<16 | CTINT,
- OANDNOT<<16 | CTRUNE:
+ case OANDNOT_ | CTINT_,
+ OANDNOT_ | CTRUNE_:
mpandnotfixfix(v.U.(*Mpint), rv.U.(*Mpint))
- case OXOR<<16 | CTINT,
- OXOR<<16 | CTRUNE:
+ case OXOR_ | CTINT_,
+ OXOR_ | CTRUNE_:
mpxorfixfix(v.U.(*Mpint), rv.U.(*Mpint))
- case OADD<<16 | CTFLT:
+ case OADD_ | CTFLT_:
mpaddfltflt(v.U.(*Mpflt), rv.U.(*Mpflt))
- case OSUB<<16 | CTFLT:
+ case OSUB_ | CTFLT_:
mpsubfltflt(v.U.(*Mpflt), rv.U.(*Mpflt))
- case OMUL<<16 | CTFLT:
+ case OMUL_ | CTFLT_:
mpmulfltflt(v.U.(*Mpflt), rv.U.(*Mpflt))
- case ODIV<<16 | CTFLT:
+ case ODIV_ | CTFLT_:
if mpcmpfltc(rv.U.(*Mpflt), 0) == 0 {
Yyerror("division by zero")
Mpmovecflt(v.U.(*Mpflt), 1.0)
// The default case above would print 'ideal % ideal',
// which is not quite an ideal error.
- case OMOD<<16 | CTFLT:
+ case OMOD_ | CTFLT_:
if n.Diag == 0 {
Yyerror("illegal constant expression: floating-point %% operation")
n.Diag = 1
return
- case OADD<<16 | CTCPLX:
+ case OADD_ | CTCPLX_:
mpaddfltflt(&v.U.(*Mpcplx).Real, &rv.U.(*Mpcplx).Real)
mpaddfltflt(&v.U.(*Mpcplx).Imag, &rv.U.(*Mpcplx).Imag)
- case OSUB<<16 | CTCPLX:
+ case OSUB_ | CTCPLX_:
mpsubfltflt(&v.U.(*Mpcplx).Real, &rv.U.(*Mpcplx).Real)
mpsubfltflt(&v.U.(*Mpcplx).Imag, &rv.U.(*Mpcplx).Imag)
- case OMUL<<16 | CTCPLX:
+ case OMUL_ | CTCPLX_:
cmplxmpy(v.U.(*Mpcplx), rv.U.(*Mpcplx))
- case ODIV<<16 | CTCPLX:
+ case ODIV_ | CTCPLX_:
if mpcmpfltc(&rv.U.(*Mpcplx).Real, 0) == 0 && mpcmpfltc(&rv.U.(*Mpcplx).Imag, 0) == 0 {
Yyerror("complex division by zero")
Mpmovecflt(&rv.U.(*Mpcplx).Real, 1.0)
cmplxdiv(v.U.(*Mpcplx), rv.U.(*Mpcplx))
- case OEQ<<16 | CTNIL:
+ case OEQ_ | CTNIL_:
goto settrue
- case ONE<<16 | CTNIL:
+ case ONE_ | CTNIL_:
goto setfalse
- case OEQ<<16 | CTINT,
- OEQ<<16 | CTRUNE:
+ case OEQ_ | CTINT_,
+ OEQ_ | CTRUNE_:
if Mpcmpfixfix(v.U.(*Mpint), rv.U.(*Mpint)) == 0 {
goto settrue
}
goto setfalse
- case ONE<<16 | CTINT,
- ONE<<16 | CTRUNE:
+ case ONE_ | CTINT_,
+ ONE_ | CTRUNE_:
if Mpcmpfixfix(v.U.(*Mpint), rv.U.(*Mpint)) != 0 {
goto settrue
}
goto setfalse
- case OLT<<16 | CTINT,
- OLT<<16 | CTRUNE:
+ case OLT_ | CTINT_,
+ OLT_ | CTRUNE_:
if Mpcmpfixfix(v.U.(*Mpint), rv.U.(*Mpint)) < 0 {
goto settrue
}
goto setfalse
- case OLE<<16 | CTINT,
- OLE<<16 | CTRUNE:
+ case OLE_ | CTINT_,
+ OLE_ | CTRUNE_:
if Mpcmpfixfix(v.U.(*Mpint), rv.U.(*Mpint)) <= 0 {
goto settrue
}
goto setfalse
- case OGE<<16 | CTINT,
- OGE<<16 | CTRUNE:
+ case OGE_ | CTINT_,
+ OGE_ | CTRUNE_:
if Mpcmpfixfix(v.U.(*Mpint), rv.U.(*Mpint)) >= 0 {
goto settrue
}
goto setfalse
- case OGT<<16 | CTINT,
- OGT<<16 | CTRUNE:
+ case OGT_ | CTINT_,
+ OGT_ | CTRUNE_:
if Mpcmpfixfix(v.U.(*Mpint), rv.U.(*Mpint)) > 0 {
goto settrue
}
goto setfalse
- case OEQ<<16 | CTFLT:
+ case OEQ_ | CTFLT_:
if mpcmpfltflt(v.U.(*Mpflt), rv.U.(*Mpflt)) == 0 {
goto settrue
}
goto setfalse
- case ONE<<16 | CTFLT:
+ case ONE_ | CTFLT_:
if mpcmpfltflt(v.U.(*Mpflt), rv.U.(*Mpflt)) != 0 {
goto settrue
}
goto setfalse
- case OLT<<16 | CTFLT:
+ case OLT_ | CTFLT_:
if mpcmpfltflt(v.U.(*Mpflt), rv.U.(*Mpflt)) < 0 {
goto settrue
}
goto setfalse
- case OLE<<16 | CTFLT:
+ case OLE_ | CTFLT_:
if mpcmpfltflt(v.U.(*Mpflt), rv.U.(*Mpflt)) <= 0 {
goto settrue
}
goto setfalse
- case OGE<<16 | CTFLT:
+ case OGE_ | CTFLT_:
if mpcmpfltflt(v.U.(*Mpflt), rv.U.(*Mpflt)) >= 0 {
goto settrue
}
goto setfalse
- case OGT<<16 | CTFLT:
+ case OGT_ | CTFLT_:
if mpcmpfltflt(v.U.(*Mpflt), rv.U.(*Mpflt)) > 0 {
goto settrue
}
goto setfalse
- case OEQ<<16 | CTCPLX:
+ case OEQ_ | CTCPLX_:
if mpcmpfltflt(&v.U.(*Mpcplx).Real, &rv.U.(*Mpcplx).Real) == 0 && mpcmpfltflt(&v.U.(*Mpcplx).Imag, &rv.U.(*Mpcplx).Imag) == 0 {
goto settrue
}
goto setfalse
- case ONE<<16 | CTCPLX:
+ case ONE_ | CTCPLX_:
if mpcmpfltflt(&v.U.(*Mpcplx).Real, &rv.U.(*Mpcplx).Real) != 0 || mpcmpfltflt(&v.U.(*Mpcplx).Imag, &rv.U.(*Mpcplx).Imag) != 0 {
goto settrue
}
goto setfalse
- case OEQ<<16 | CTSTR:
+ case OEQ_ | CTSTR_:
if strlit(nl) == strlit(nr) {
goto settrue
}
goto setfalse
- case ONE<<16 | CTSTR:
+ case ONE_ | CTSTR_:
if strlit(nl) != strlit(nr) {
goto settrue
}
goto setfalse
- case OLT<<16 | CTSTR:
+ case OLT_ | CTSTR_:
if strlit(nl) < strlit(nr) {
goto settrue
}
goto setfalse
- case OLE<<16 | CTSTR:
+ case OLE_ | CTSTR_:
if strlit(nl) <= strlit(nr) {
goto settrue
}
goto setfalse
- case OGE<<16 | CTSTR:
+ case OGE_ | CTSTR_:
if strlit(nl) >= strlit(nr) {
goto settrue
}
goto setfalse
- case OGT<<16 | CTSTR:
+ case OGT_ | CTSTR_:
if strlit(nl) > strlit(nr) {
goto settrue
}
goto setfalse
- case OOROR<<16 | CTBOOL:
+ case OOROR_ | CTBOOL_:
if v.U.(bool) || rv.U.(bool) {
goto settrue
}
goto setfalse
- case OANDAND<<16 | CTBOOL:
+ case OANDAND_ | CTBOOL_:
if v.U.(bool) && rv.U.(bool) {
goto settrue
}
goto setfalse
- case OEQ<<16 | CTBOOL:
+ case OEQ_ | CTBOOL_:
if v.U.(bool) == rv.U.(bool) {
goto settrue
}
goto setfalse
- case ONE<<16 | CTBOOL:
+ case ONE_ | CTBOOL_:
if v.U.(bool) != rv.U.(bool) {
goto settrue
}
Yyerror("illegal constant expression: %v %v %v", nl.Type, Oconv(int(n.Op), 0), nr.Type)
n.Diag = 1
}
-
- return
}
func nodlit(v Val) *Node {
// idealkind returns a constant kind like consttype
// but for an arbitrary "ideal" (untyped constant) expression.
-func idealkind(n *Node) int {
+func idealkind(n *Node) Ctype {
if n == nil || !isideal(n.Type) {
return CTxxx
}
return CTxxx
case OLITERAL:
- return int(n.Val().Ctype())
+ return n.Val().Ctype()
// numeric kinds.
case OADD,
return
}
-/*
- * defaultlit on both nodes simultaneously;
- * if they're both ideal going in they better
- * get the same type going out.
- * force means must assign concrete (non-ideal) type.
- */
+// defaultlit on both nodes simultaneously;
+// if they're both ideal going in they better
+// get the same type going out.
+// force means must assign concrete (non-ideal) type.
func defaultlit2(lp **Node, rp **Node, force int) {
l := *lp
r := *rp
return -1
}
-/*
- * convert x to type et and back to int64
- * for sign extension and truncation.
- */
-func iconv(x int64, et int) int64 {
+// convert x to type et and back to int64
+// for sign extension and truncation.
+func iconv(x int64, et EType) int64 {
switch et {
case TINT8:
x = int64(int8(x))
return f.Op == OINDREG && t.Op == OINDREG && f.Xoffset+f.Type.Width >= t.Xoffset && t.Xoffset+t.Type.Width >= f.Xoffset
}
-func complexbool(op int, nl, nr, res *Node, wantTrue bool, likely int, to *obj.Prog) {
+func complexbool(op Op, nl, nr, res *Node, wantTrue bool, likely int, to *obj.Prog) {
// make both sides addable in ullman order
if nr != nil {
if nl.Ullman > nr.Ullman && !nl.Addable {
// build and execute tree
// real(res) = real(nl) op real(nr)
// imag(res) = imag(nl) op imag(nr)
-func complexadd(op int, nl *Node, nr *Node, res *Node) {
+func complexadd(op Op, nl *Node, nr *Node, res *Node) {
var n1 Node
var n2 Node
var n3 Node
subnode(&n5, &n6, res)
var ra Node
- ra.Op = uint8(op)
+ ra.Op = op
ra.Left = &n1
ra.Right = &n3
ra.Type = n1.Type
Cgen(&ra, &n5)
ra = Node{}
- ra.Op = uint8(op)
+ ra.Op = op
ra.Left = &n2
ra.Right = &n4
ra.Type = n2.Type
ft := Simsimtype(f.Type)
tt := Simsimtype(t.Type)
- switch uint32(ft)<<16 | uint32(tt) {
- default:
- Fatalf("complexmove: unknown conversion: %v -> %v\n", f.Type, t.Type)
-
- // complex to complex move/convert.
+ // complex to complex move/convert.
// make f addable.
// also use temporary if possible stack overlap.
- case TCOMPLEX64<<16 | TCOMPLEX64,
- TCOMPLEX64<<16 | TCOMPLEX128,
- TCOMPLEX128<<16 | TCOMPLEX64,
- TCOMPLEX128<<16 | TCOMPLEX128:
+ if (ft == TCOMPLEX64 || ft == TCOMPLEX128) && (tt == TCOMPLEX64 || tt == TCOMPLEX128) {
if !f.Addable || overlap_cplx(f, t) {
var tmp Node
Tempname(&tmp, f.Type)
Cgen(&n1, &n3)
Cgen(&n2, &n4)
+ } else {
+ Fatalf("complexmove: unknown conversion: %v -> %v\n", f.Type, t.Type)
}
}
complexminus(nl, res)
case OADD, OSUB:
- complexadd(int(n.Op), nl, nr, res)
+ complexadd(n.Op, nl, nr, res)
case OMUL:
complexmul(nl, nr, res)
return true
}
-/*
- * declaration stack & operations
- */
+// declaration stack & operations
func dcopy(a *Sym, b *Sym) {
a.Pkg = b.Pkg
a.Name = b.Name
var vargen int
-/*
- * declare individual names - var, typ, const
- */
+// declare individual names - var, typ, const
var declare_typegen int
-func declare(n *Node, ctxt uint8) {
+func declare(n *Node, ctxt Class) {
if ctxt == PDISCARD {
return
}
s.Def = n
n.Name.Vargen = int32(gen)
n.Name.Funcdepth = Funcdepth
- n.Class = uint8(ctxt)
+ n.Class = ctxt
autoexport(n, ctxt)
}
-func addvar(n *Node, t *Type, ctxt uint8) {
+func addvar(n *Node, t *Type, ctxt Class) {
if n == nil || n.Sym == nil || (n.Op != ONAME && n.Op != ONONAME) || t == nil {
Fatalf("addvar: n=%v t=%v nil", n, t)
}
n.Type = t
}
-/*
- * declare variables from grammar
- * new_name_list (type | [type] = expr_list)
- */
+// declare variables from grammar
+// new_name_list (type | [type] = expr_list)
func variter(vl *NodeList, t *Node, el *NodeList) *NodeList {
var init *NodeList
doexpr := el != nil
return init
}
-/*
- * declare constants from grammar
- * new_name_list [[type] = expr_list]
- */
+// declare constants from grammar
+// new_name_list [[type] = expr_list]
func constiter(vl *NodeList, t *Node, cl *NodeList) *NodeList {
lno := int32(0) // default is to leave line number alone in listtreecopy
if cl == nil {
return vv
}
-/*
- * this generates a new name node,
- * typically for labels or other one-off names.
- */
+// this generates a new name node,
+// typically for labels or other one-off names.
func newname(s *Sym) *Node {
if s == nil {
Fatalf("newname nil")
return n
}
-/*
- * this generates a new name node for a name
- * being declared.
- */
+// this generates a new name node for a name
+// being declared.
func dclname(s *Sym) *Node {
n := newname(s)
n.Op = ONONAME // caller will correct it
return t.Nod
}
-/*
- * this will return an old name
- * that has already been pushed on the
- * declaration list. a diagnostic is
- * generated if no name has been defined.
- */
+// this will return an old name
+// that has already been pushed on the
+// declaration list. a diagnostic is
+// generated if no name has been defined.
func oldname(s *Sym) *Node {
n := s.Def
if n == nil {
return n
}
-/*
- * := declarations
- */
+// := declarations
func colasname(n *Node) bool {
switch n.Op {
case ONAME,
return as
}
-/*
- * declare the arguments in an
- * interface field declaration.
- */
+// declare the arguments in an
+// interface field declaration.
func ifacedcl(n *Node) {
if n.Op != ODCLFIELD || n.Right == nil {
Fatalf("ifacedcl")
funcbody(n)
}
-/*
- * declare the function proper
- * and declare the arguments.
- * called in extern-declaration context
- * returns in auto-declaration context.
- */
+// declare the function proper
+// and declare the arguments.
+// called in extern-declaration context
+// returns in auto-declaration context.
func funchdr(n *Node) {
// change the declaration context from extern to auto
if Funcdepth == 0 && dclcontext != PEXTERN {
}
}
-/*
- * Same as funcargs, except run over an already constructed TFUNC.
- * This happens during import, where the hidden_fndcl rule has
- * used functype directly to parse the function's type.
- */
+// Same as funcargs, except run over an already constructed TFUNC.
+// This happens during import, where the hidden_fndcl rule has
+// used functype directly to parse the function's type.
func funcargs2(t *Type) {
if t.Etype != TFUNC {
Fatalf("funcargs2 %v", t)
}
}
-/*
- * finish the body.
- * called in auto-declaration context.
- * returns in extern-declaration context.
- */
+// finish the body.
+// called in auto-declaration context.
+// returns in extern-declaration context.
func funcbody(n *Node) {
// change the declaration context from auto to extern
if dclcontext != PAUTO {
}
}
-/*
- * new type being defined with name s.
- */
+// new type being defined with name s.
func typedcl0(s *Sym) *Node {
n := newname(s)
n.Op = OTYPE
return n
}
-/*
- * node n, which was returned by typedcl0
- * is being declared to have uncompiled type t.
- * return the ODCLTYPE node to use.
- */
+// node n, which was returned by typedcl0
+// is being declared to have uncompiled type t.
+// return the ODCLTYPE node to use.
func typedcl1(n *Node, t *Node, local bool) *Node {
n.Name.Param.Ntype = t
n.Local = local
return Nod(ODCLTYPE, n, nil)
}
-/*
- * structs, functions, and methods.
- * they don't belong here, but where do they belong?
- */
+// structs, functions, and methods.
+// they don't belong here, but where do they belong?
func checkembeddedtype(t *Type) {
if t == nil {
return
lineno = int32(lno)
}
-/*
- * convert a parsed id/type list into
- * a type for struct/interface/arglist
- */
+// convert a parsed id/type list into
+// a type for struct/interface/arglist
func tostruct(l *NodeList) *Type {
- var f *Type
t := typ(TSTRUCT)
+ tostruct0(t, l)
+ return t
+}
+
+func tostruct0(t *Type, l *NodeList) {
+ if t == nil || t.Etype != TSTRUCT {
+ Fatalf("struct expected")
+ }
for tp := &t.Type; l != nil; l = l.Next {
- f = structfield(l.N)
+ f := structfield(l.N)
*tp = f
tp = &f.Down
if !t.Broke {
checkwidth(t)
}
-
- return t
}
func tofunargs(l *NodeList) *Type {
f = structfield(l.N)
f.Funarg = true
- // esc.c needs to find f given a PPARAM to add the tag.
+ // esc.go needs to find f given a PPARAM to add the tag.
if l.N.Left != nil && l.N.Left.Class == PPARAM {
l.N.Left.Name.Param.Field = f
}
}
func tointerface(l *NodeList) *Type {
- var f *Type
- var t1 *Type
-
t := typ(TINTER)
+ tointerface0(t, l)
+ return t
+}
+
+func tointerface0(t *Type, l *NodeList) *Type {
+ if t == nil || t.Etype != TINTER {
+ Fatalf("interface expected")
+ }
tp := &t.Type
for ; l != nil; l = l.Next {
- f = interfacefield(l.N)
+ f := interfacefield(l.N)
if l.N.Left == nil && f.Type.Etype == TINTER {
// embedded interface, inline methods
- for t1 = f.Type.Type; t1 != nil; t1 = t1.Down {
+ for t1 := f.Type.Type; t1 != nil; t1 = t1.Down {
f = typ(TFIELD)
f.Type = t1.Type
f.Broke = t1.Broke
return n
}
-/*
- * check that the list of declarations is either all anonymous or all named
- */
+// check that the list of declarations is either all anonymous or all named
func findtype(l *NodeList) *Node {
for ; l != nil; l = l.Next {
if l.N.Op == OKEY {
// declarations, which are parsed by rules that don't
// use checkargs, but can happen for func literals in
// the inline bodies.
- // TODO(rsc) this can go when typefmt case TFIELD in exportmode fmt.c prints _ instead of ?
+ // TODO(rsc) this can go when typefmt case TFIELD in exportmode fmt.go prints _ instead of ?
if importpkg != nil && n.Sym == nil {
n = nil
}
return n
}
-/*
- * Is this field a method on an interface?
- * Those methods have an anonymous
- * *struct{} as the receiver.
- * (See fakethis above.)
- */
+// Is this field a method on an interface?
+// Those methods have an anonymous *struct{} as the receiver.
+// (See fakethis above.)
func isifacemethod(f *Type) bool {
rcvr := getthisx(f).Type
if rcvr.Sym != nil {
return true
}
-/*
- * turn a parsed function declaration
- * into a type
- */
+// turn a parsed function declaration into a type
func functype(this *Node, in *NodeList, out *NodeList) *Type {
t := typ(TFUNC)
+ functype0(t, this, in, out)
+ return t
+}
+
+func functype0(t *Type, this *Node, in *NodeList, out *NodeList) {
+ if t == nil || t.Etype != TFUNC {
+ Fatalf("function type expected")
+ }
var rcvr *NodeList
if this != nil {
t.Outnamed = true
}
}
-
- return t
}
var methodsym_toppkg *Pkg
return n
}
-/*
- * add a method, declared as a function,
- * n is fieldname, pa is base type, t is function type
- */
+// add a method, declared as a function,
+// n is fieldname, pa is base type, t is function type
func addmethod(sf *Sym, t *Type, local bool, nointerface bool) {
// get field sym
if sf == nil {
s1.Def.Func.Shortname = newname(s)
funcsyms = append(funcsyms, s1.Def)
}
+
+type nowritebarrierrecChecker struct {
+ curfn *Node
+ stable bool
+
+ // best maps from the ODCLFUNC of each visited function that
+ // recursively invokes a write barrier to the called function
+ // on the shortest path to a write barrier.
+ best map[*Node]nowritebarrierrecCall
+}
+
+type nowritebarrierrecCall struct {
+ target *Node
+ depth int
+ lineno int32
+}
+
+func checknowritebarrierrec() {
+ c := nowritebarrierrecChecker{
+ best: make(map[*Node]nowritebarrierrecCall),
+ }
+ visitBottomUp(xtop, func(list []*Node, recursive bool) {
+ // Functions with write barriers have depth 0.
+ for _, n := range list {
+ if n.Func.WBLineno != 0 {
+ c.best[n] = nowritebarrierrecCall{target: nil, depth: 0, lineno: n.Func.WBLineno}
+ }
+ }
+
+ // Propagate write barrier depth up from callees. In
+ // the recursive case, we have to update this at most
+ // len(list) times and can stop when we an iteration
+ // that doesn't change anything.
+ for _ = range list {
+ c.stable = false
+ for _, n := range list {
+ if n.Func.WBLineno == 0 {
+ c.curfn = n
+ c.visitcodelist(n.Nbody)
+ }
+ }
+ if c.stable {
+ break
+ }
+ }
+
+ // Check nowritebarrierrec functions.
+ for _, n := range list {
+ if !n.Func.Nowritebarrierrec {
+ continue
+ }
+ call, hasWB := c.best[n]
+ if !hasWB {
+ continue
+ }
+
+ // Build the error message in reverse.
+ err := ""
+ for call.target != nil {
+ err = fmt.Sprintf("\n\t%v: called by %v%s", Ctxt.Line(int(call.lineno)), n.Func.Nname, err)
+ n = call.target
+ call = c.best[n]
+ }
+ err = fmt.Sprintf("write barrier prohibited by caller; %v%s", n.Func.Nname, err)
+ yyerrorl(int(n.Func.WBLineno), err)
+ }
+ })
+}
+
+func (c *nowritebarrierrecChecker) visitcodelist(l *NodeList) {
+ for ; l != nil; l = l.Next {
+ c.visitcode(l.N)
+ }
+}
+
+func (c *nowritebarrierrecChecker) visitcode(n *Node) {
+ if n == nil {
+ return
+ }
+
+ if n.Op == OCALLFUNC || n.Op == OCALLMETH {
+ c.visitcall(n)
+ }
+
+ c.visitcodelist(n.Ninit)
+ c.visitcode(n.Left)
+ c.visitcode(n.Right)
+ c.visitcodelist(n.List)
+ c.visitcodelist(n.Nbody)
+ c.visitcodelist(n.Rlist)
+}
+
+func (c *nowritebarrierrecChecker) visitcall(n *Node) {
+ fn := n.Left
+ if n.Op == OCALLMETH {
+ fn = n.Left.Right.Sym.Def
+ }
+ if fn == nil || fn.Op != ONAME || fn.Class != PFUNC || fn.Name.Defn == nil {
+ return
+ }
+ defn := fn.Name.Defn
+
+ fnbest, ok := c.best[defn]
+ if !ok {
+ return
+ }
+ best, ok := c.best[c.curfn]
+ if ok && fnbest.depth+1 >= best.depth {
+ return
+ }
+ c.best[c.curfn] = nowritebarrierrecCall{target: defn, depth: fnbest.depth + 1, lineno: n.Lineno}
+ c.stable = false
+}
import (
"cmd/internal/obj"
"fmt"
+ "strconv"
"strings"
)
var v *Node
for ll := n.Func.Cvars; ll != nil; ll = ll.Next {
v = ll.N
- if v.Op == OXXX { // unnamed out argument; see dcl.c:/^funcargs
+ if v.Op == OXXX { // unnamed out argument; see dcl.go:/^funcargs
continue
}
a = v.Name.Param.Closure
if note == nil || !strings.HasPrefix(*note, "esc:") {
return EscUnknown
}
- em := uint16(atoi((*note)[4:]))
+ n, _ := strconv.ParseInt((*note)[4:], 0, 0)
+ em := uint16(n)
if em == 0 {
return EscNone
}
package gc
import (
+ "bytes"
"cmd/internal/obj"
"fmt"
"sort"
"unicode/utf8"
)
+var (
+ newexport int // if set, use new export format
+ Debug_export int // if set, print debugging information about export data
+ exportsize int
+)
+
+func exportf(format string, args ...interface{}) {
+ n, _ := fmt.Fprintf(bout, format, args...)
+ exportsize += n
+ if Debug_export != 0 {
+ fmt.Printf(format, args...)
+ }
+}
+
var asmlist *NodeList
// Mark n's symbol as exported
}
func exportname(s string) bool {
- if s[0] < utf8.RuneSelf {
- return 'A' <= s[0] && s[0] <= 'Z'
+ if r := s[0]; r < utf8.RuneSelf {
+ return 'A' <= r && r <= 'Z'
}
r, _ := utf8.DecodeRuneInString(s)
return unicode.IsUpper(r)
return sym.Pkg == localpkg && exportname(sym.Name)
}
-func autoexport(n *Node, ctxt uint8) {
+func autoexport(n *Node, ctxt Class) {
if n == nil || n.Sym == nil {
return
}
if !p.Direct {
suffix = " // indirect"
}
- fmt.Fprintf(bout, "\timport %s %q%s\n", p.Name, p.Path, suffix)
+ exportf("\timport %s %q%s\n", p.Name, p.Path, suffix)
}
// Look for anything we need for the inline body
}
}
- // Local variables in the bodies need their type.
+ // Local variables in the bodies need their type.
case ODCL:
t := n.Left.Type
exportlist = append(exportlist, n)
}
- // for operations that need a type when rendered, put the type on the export list.
+ // for operations that need a type when rendered, put the type on the export list.
case OCONV,
OCONVIFACE,
OCONVNOP,
dumpexporttype(t)
if t != nil && !isideal(t) {
- fmt.Fprintf(bout, "\tconst %v %v = %v\n", Sconv(s, obj.FmtSharp), Tconv(t, obj.FmtSharp), Vconv(n.Val(), obj.FmtSharp))
+ exportf("\tconst %v %v = %v\n", Sconv(s, obj.FmtSharp), Tconv(t, obj.FmtSharp), Vconv(n.Val(), obj.FmtSharp))
} else {
- fmt.Fprintf(bout, "\tconst %v = %v\n", Sconv(s, obj.FmtSharp), Vconv(n.Val(), obj.FmtSharp))
+ exportf("\tconst %v = %v\n", Sconv(s, obj.FmtSharp), Vconv(n.Val(), obj.FmtSharp))
}
}
}
// NOTE: The space after %#S here is necessary for ld's export data parser.
- fmt.Fprintf(bout, "\tfunc %v %v { %v }\n", Sconv(s, obj.FmtSharp), Tconv(t, obj.FmtShort|obj.FmtSharp), Hconv(n.Func.Inl, obj.FmtSharp))
+ exportf("\tfunc %v %v { %v }\n", Sconv(s, obj.FmtSharp), Tconv(t, obj.FmtShort|obj.FmtSharp), Hconv(n.Func.Inl, obj.FmtSharp))
reexportdeplist(n.Func.Inl)
} else {
- fmt.Fprintf(bout, "\tfunc %v %v\n", Sconv(s, obj.FmtSharp), Tconv(t, obj.FmtShort|obj.FmtSharp))
+ exportf("\tfunc %v %v\n", Sconv(s, obj.FmtSharp), Tconv(t, obj.FmtShort|obj.FmtSharp))
}
} else {
- fmt.Fprintf(bout, "\tvar %v %v\n", Sconv(s, obj.FmtSharp), Tconv(t, obj.FmtSharp))
+ exportf("\tvar %v %v\n", Sconv(s, obj.FmtSharp), Tconv(t, obj.FmtSharp))
}
}
}
sort.Sort(methodbyname(m))
- fmt.Fprintf(bout, "\ttype %v %v\n", Sconv(t.Sym, obj.FmtSharp), Tconv(t, obj.FmtSharp|obj.FmtLong))
+ exportf("\ttype %v %v\n", Sconv(t.Sym, obj.FmtSharp), Tconv(t, obj.FmtSharp|obj.FmtLong))
for _, f := range m {
if f.Nointerface {
- fmt.Fprintf(bout, "\t//go:nointerface\n")
+ exportf("\t//go:nointerface\n")
}
if f.Type.Nname != nil && f.Type.Nname.Func.Inl != nil { // nname was set by caninl
if Debug['l'] < 2 {
typecheckinl(f.Type.Nname)
}
- fmt.Fprintf(bout, "\tfunc (%v) %v %v { %v }\n", Tconv(getthisx(f.Type).Type, obj.FmtSharp), Sconv(f.Sym, obj.FmtShort|obj.FmtByte|obj.FmtSharp), Tconv(f.Type, obj.FmtShort|obj.FmtSharp), Hconv(f.Type.Nname.Func.Inl, obj.FmtSharp))
+ exportf("\tfunc (%v) %v %v { %v }\n", Tconv(getthisx(f.Type).Type, obj.FmtSharp), Sconv(f.Sym, obj.FmtShort|obj.FmtByte|obj.FmtSharp), Tconv(f.Type, obj.FmtShort|obj.FmtSharp), Hconv(f.Type.Nname.Func.Inl, obj.FmtSharp))
reexportdeplist(f.Type.Nname.Func.Inl)
} else {
- fmt.Fprintf(bout, "\tfunc (%v) %v %v\n", Tconv(getthisx(f.Type).Type, obj.FmtSharp), Sconv(f.Sym, obj.FmtShort|obj.FmtByte|obj.FmtSharp), Tconv(f.Type, obj.FmtShort|obj.FmtSharp))
+ exportf("\tfunc (%v) %v %v\n", Tconv(getthisx(f.Type).Type, obj.FmtSharp), Sconv(f.Sym, obj.FmtShort|obj.FmtByte|obj.FmtSharp), Tconv(f.Type, obj.FmtShort|obj.FmtSharp))
}
}
}
}
func dumpexport() {
- lno := lineno
-
if buildid != "" {
- fmt.Fprintf(bout, "build id %q\n", buildid)
- }
- fmt.Fprintf(bout, "\n$$\npackage %s", localpkg.Name)
- if safemode != 0 {
- fmt.Fprintf(bout, " safe")
- }
- fmt.Fprintf(bout, "\n")
+ exportf("build id %q\n", buildid)
+ }
+
+ size := 0 // size of export section without enclosing markers
+ if forceNewExport || newexport != 0 {
+ // binary export
+ // The linker also looks for the $$ marker - use char after $$ to distinguish format.
+ exportf("\n$$B\n") // indicate binary format
+ const verifyExport = true // enable to check format changes
+ if verifyExport {
+ // save a copy of the export data
+ var copy bytes.Buffer
+ bcopy := obj.Binitw(©)
+ size = Export(bcopy, Debug_export != 0)
+ bcopy.Flush() // flushing to bytes.Buffer cannot fail
+ if n, err := bout.Write(copy.Bytes()); n != size || err != nil {
+ Fatalf("error writing export data: got %d bytes, want %d bytes, err = %v", n, size, err)
+ }
+ // export data must contain no '$' so that we can find the end by searching for "$$"
+ if bytes.IndexByte(copy.Bytes(), '$') >= 0 {
+ Fatalf("export data contains $")
+ }
- for _, p := range pkgs {
- if p.Direct {
- dumppkg(p)
+ // verify that we can read the copied export data back in
+ // (use empty package map to avoid collisions)
+ savedPkgMap := pkgMap
+ savedPkgs := pkgs
+ pkgMap = make(map[string]*Pkg)
+ pkgs = nil
+ importpkg = mkpkg("")
+ Import(obj.Binitr(©)) // must not die
+ importpkg = nil
+ pkgs = savedPkgs
+ pkgMap = savedPkgMap
+ } else {
+ size = Export(bout, Debug_export != 0)
+ }
+ exportf("\n$$\n")
+ } else {
+ // textual export
+ lno := lineno
+
+ exportf("\n$$\n") // indicate textual format
+ exportsize = 0
+ exportf("package %s", localpkg.Name)
+ if safemode != 0 {
+ exportf(" safe")
+ }
+ exportf("\n")
+
+ for _, p := range pkgs {
+ if p.Direct {
+ dumppkg(p)
+ }
}
- }
- // exportlist grows during iteration - cannot use range
- for len(exportlist) > 0 {
- n := exportlist[0]
- exportlist = exportlist[1:]
- lineno = n.Lineno
- dumpsym(n.Sym)
+ // exportlist grows during iteration - cannot use range
+ for len(exportlist) > 0 {
+ n := exportlist[0]
+ exportlist = exportlist[1:]
+ lineno = n.Lineno
+ dumpsym(n.Sym)
+ }
+
+ size = exportsize
+ exportf("\n$$\n")
+ lineno = lno
}
- fmt.Fprintf(bout, "\n$$\n")
- lineno = lno
+ if Debug_export != 0 {
+ fmt.Printf("export data size = %d bytes\n", size)
+ }
}
-/*
- * import
- */
+// import
-/*
- * return the sym for ss, which should match lexical
- */
-func importsym(s *Sym, op int) *Sym {
- if s.Def != nil && int(s.Def.Op) != op {
+// return the sym for ss, which should match lexical
+func importsym(s *Sym, op Op) *Sym {
+ if s.Def != nil && s.Def.Op != op {
pkgstr := fmt.Sprintf("during import %q", importpkg.Path)
redeclare(s, pkgstr)
}
return s
}
-/*
- * return the type pkg.name, forward declaring if needed
- */
+// return the type pkg.name, forward declaring if needed
func pkgtype(s *Sym) *Type {
importsym(s, OTYPE)
if s.Def == nil || s.Def.Op != OTYPE {
// Flags: those of %N
// ',' separate items with ',' instead of ';'
//
-// In mparith1.c:
-// %B Mpint* Big integers
-// %F Mpflt* Big floats
+// In mparith2.go and mparith3.go:
+// %B Mpint* Big integers
+// %F Mpflt* Big floats
//
// %S, %T and %N obey use the following flags to set the format mode:
const (
}
// Fmt "%E": etype
-func Econv(et int, flag int) string {
- if et >= 0 && et < len(etnames) && etnames[et] != "" {
+func Econv(et EType) string {
+ if int(et) < len(etnames) && etnames[et] != "" {
return etnames[et]
}
return fmt.Sprintf("E-%d", et)
if fmtmode == FDbg {
fmtmode = 0
- str := Econv(int(t.Etype), 0) + "-" + typefmt(t, flag)
+ str := Econv(t.Etype) + "-" + typefmt(t, flag)
fmtmode = FDbg
return str
}
}
} else if fmtmode == FExp {
// TODO(rsc) this breaks on the eliding of unused arguments in the backend
- // when this is fixed, the special case in dcl.c checkarglist can go.
+ // when this is fixed, the special case in dcl.go checkarglist can go.
//if(t->funarg)
// fmtstrcpy(fp, "_ ");
//else
}
if fmtmode == FExp {
- Fatalf("missing %v case during export", Econv(int(t.Etype), 0))
+ Fatalf("missing %v case during export", Econv(t.Etype))
}
// Don't know how to handle - fall back to detailed prints.
- return fmt.Sprintf("%v <%v> %v", Econv(int(t.Etype), 0), t.Sym, t.Type)
+ return fmt.Sprintf("%v <%v> %v", Econv(t.Etype), t.Sym, t.Type)
}
// Statements which may be rendered with a simplestmt as init.
-func stmtwithinit(op int) bool {
+func stmtwithinit(op Op) bool {
switch op {
case OIF, OFOR, OSWITCH:
return true
// block starting with the init statements.
// if we can just say "for" n->ninit; ... then do so
- simpleinit := n.Ninit != nil && n.Ninit.Next == nil && n.Ninit.N.Ninit == nil && stmtwithinit(int(n.Op))
+ simpleinit := n.Ninit != nil && n.Ninit.Next == nil && n.Ninit.N.Ninit == nil && stmtwithinit(n.Op)
// otherwise, print the inits as separate statements
complexinit := n.Ninit != nil && !simpleinit && (fmtmode != FErr)
// but if it was for if/for/switch, put in an extra surrounding block to limit the scope
- extrablock := complexinit && stmtwithinit(int(n.Op))
+ extrablock := complexinit && stmtwithinit(n.Op)
if extrablock {
f += "{"
f += Nconv(n.Right, 0)
}
- // Don't export "v = <N>" initializing statements, hope they're always
+ // Don't export "v = <N>" initializing statements, hope they're always
// preceded by the DCL which will be re-parsed and typecheck to reproduce
// the "v = <N>" again.
case OAS, OASWB:
case OASOP:
if n.Implicit {
- if n.Etype == OADD {
+ if Op(n.Etype) == OADD {
f += fmt.Sprintf("%v++", n.Left)
} else {
f += fmt.Sprintf("%v--", n.Left)
return Vconv(n.Val(), 0)
- // Special case: name used as local variable in export.
+ // Special case: name used as local variable in export.
// _ becomes ~b%d internally; print as _ for export
case ONAME:
if (fmtmode == FExp || fmtmode == FErr) && n.Sym != nil && n.Sym.Name[0] == '~' && n.Sym.Name[1] == 'b' {
}
fallthrough
- //fallthrough
case OPACK, ONONAME:
return Sconv(n.Sym, 0)
case OCMPSTR, OCMPIFACE:
var f string
f += exprfmt(n.Left, nprec)
+ // TODO(marvin): Fix Node.EType type union.
f += fmt.Sprintf(" %v ", Oconv(int(n.Etype), obj.FmtSharp))
f += exprfmt(n.Right, nprec+1)
return f
"fmt"
)
-/*
- * portable half of code generator.
- * mainly statements and control flow.
- */
+// portable half of code generator.
+// mainly statements and control flow.
var labellist *Label
var lastlabel *Label
return nil
}
-/*
- * compile statements
- */
+// compile statements
func Genlist(l *NodeList) {
for ; l != nil; l = l.Next {
gen(l.N)
}
}
-/*
- * generate code to start new proc running call n.
- */
+// generate code to start new proc running call n.
func cgen_proc(n *Node, proc int) {
switch n.Left.Op {
default:
}
}
-/*
- * generate declaration.
- * have to allocate heap copy
- * for escaped variables.
- */
+// generate declaration.
+// have to allocate heap copy
+// for escaped variables.
func cgen_dcl(n *Node) {
if Debug['g'] != 0 {
Dump("\ncgen-dcl", n)
Cgen_as(n.Name.Heapaddr, prealloc[n])
}
-/*
- * generate discard of value
- */
+// generate discard of value
func cgen_discard(nr *Node) {
if nr == nil {
return
}
}
-/*
- * clearslim generates code to zero a slim node.
- */
+// clearslim generates code to zero a slim node.
func Clearslim(n *Node) {
var z Node
z.Op = OLITERAL
Cgen(&z, n)
}
-/*
- * generate:
- * res = iface{typ, data}
- * n->left is typ
- * n->right is data
- */
+// generate:
+// res = iface{typ, data}
+// n->left is typ
+// n->right is data
func Cgen_eface(n *Node, res *Node) {
- /*
- * the right node of an eface may contain function calls that uses res as an argument,
- * so it's important that it is done first
- */
+ // the right node of an eface may contain function calls that uses res as an argument,
+ // so it's important that it is done first
tmp := temp(Types[Tptr])
Cgen(n.Right, tmp)
Cgen(n.Left, &dst)
}
-/*
- * generate one of:
- * res, resok = x.(T)
- * res = x.(T) (when resok == nil)
- * n.Left is x
- * n.Type is T
- */
+// generate one of:
+// res, resok = x.(T)
+// res = x.(T) (when resok == nil)
+// n.Left is x
+// n.Type is T
func cgen_dottype(n *Node, res, resok *Node, wb bool) {
if Debug_typeassert > 0 {
Warn("type assertion inlined")
}
}
-/*
- * generate:
- * res, resok = x.(T)
- * n.Left is x
- * n.Type is T
- */
+// generate:
+// res, resok = x.(T)
+// n.Left is x
+// n.Type is T
func Cgen_As2dottype(n, res, resok *Node) {
if Debug_typeassert > 0 {
Warn("type assertion inlined")
Patch(q, Pc)
}
-/*
- * gather series of offsets
- * >=0 is direct addressed field
- * <0 is pointer to next field (+1)
- */
+// gather series of offsets
+// >=0 is direct addressed field
+// <0 is pointer to next field (+1)
func Dotoffset(n *Node, oary []int64, nn **Node) int {
var i int
return i
}
-/*
- * make a new off the books
- */
+// make a new off the books
func Tempname(nn *Node, t *Type) {
if Curfn == nil {
Fatalf("no curfn for tempname")
numPtr := 0
visitComponents(nl.Type, 0, func(t *Type, offset int64) bool {
n++
- if int(Simtype[t.Etype]) == Tptr && t != itable {
+ if Simtype[t.Etype] == Tptr && t != itable {
numPtr++
}
return n <= maxMoves && (!wb || numPtr <= 1)
ptrOffset int64
)
visitComponents(nl.Type, 0, func(t *Type, offset int64) bool {
- if wb && int(Simtype[t.Etype]) == Tptr && t != itable {
+ if wb && Simtype[t.Etype] == Tptr && t != itable {
if ptrType != nil {
Fatalf("componentgen_wb %v", Tconv(nl.Type, 0))
}
"cmd/internal/obj"
)
-// avoid <ctype.h>
-
// The parser's maximum stack size.
// We have to use a #define macro here since yacc
// or bison will check for its definition and use
type NilVal struct{}
-func (v Val) Ctype() int {
+func (v Val) Ctype() Ctype {
switch x := v.U.(type) {
default:
Fatalf("unexpected Ctype for %T", v.U)
}
type Type struct {
- Etype uint8
+ Etype EType
Nointerface bool
Noalg bool
Chan uint8
T *Type
}
+type EType uint8
+
const (
Txxx = iota
TFUNC
TARRAY
- T_old_DARRAY
+ T_old_DARRAY // Doesn't seem to be used in existing code. Used now for Isddd export (see bexport.go). TODO(gri) rename.
TSTRUCT
TCHAN
TMAP
NTYPE
)
+// Ctype describes the constant kind of an "ideal" (untyped) constant.
+type Ctype int8
+
const (
- CTxxx = iota
+ CTxxx Ctype = iota
CTINT
CTRUNE
)
const (
- /* types of channel */
- /* must match ../../pkg/nreflect/type.go:/Chandir */
+ // types of channel
+ // must match ../../pkg/nreflect/type.go:/Chandir
Cxxx = 0
Crecv = 1 << 0
Csend = 1 << 1
Cboth = Crecv | Csend
)
-// declaration context
+// The Class of a variable/function describes the "storage class"
+// of a variable or function. During parsing, storage classes are
+// called declaration contexts.
+type Class uint8
+
const (
- Pxxx = uint8(iota)
- PEXTERN // global variable
- PAUTO // local variables
- PPARAM // input arguments
- PPARAMOUT // output results
- PPARAMREF // closure variable reference
- PFUNC // global function
+ Pxxx Class = iota
+ PEXTERN // global variable
+ PAUTO // local variables
+ PPARAM // input arguments
+ PPARAMOUT // output results
+ PPARAMREF // closure variable reference
+ PFUNC // global function
PDISCARD // discard during parse of duplicate import
- PHEAP = uint8(1 << 7) // an extra bit to identify an escaped variable
+ PHEAP = 1 << 7 // an extra bit to identify an escaped variable
)
const (
type Typedef struct {
Name string
- Etype int
- Sameas int
+ Etype EType
+ Sameas EType
}
type Sig struct {
dir string
}
-/*
- * argument passing to/from
- * smagic and umagic
- */
+// argument passing to/from
+// smagic and umagic
type Magic struct {
W int // input for both - width
S int // output for both - shift
Ua int // output - adder
}
-/*
- * note this is the runtime representation
- * of the compilers arrays.
- *
- * typedef struct
- * { // must not move anything
- * uchar array[8]; // pointer to data
- * uchar nel[4]; // number of elements
- * uchar cap[4]; // allocated number of elements
- * } Array;
- */
+// note this is the runtime representation
+// of the compilers arrays.
+//
+// typedef struct
+// { // must not move anything
+// uchar array[8]; // pointer to data
+// uchar nel[4]; // number of elements
+// uchar cap[4]; // allocated number of elements
+// } Array;
var Array_array int // runtime offsetof(Array,array) - same for String
var Array_nel int // runtime offsetof(Array,nel) - same for String
var sizeof_Array int // runtime sizeof(Array)
-/*
- * note this is the runtime representation
- * of the compilers strings.
- *
- * typedef struct
- * { // must not move anything
- * uchar array[8]; // pointer to data
- * uchar nel[4]; // number of elements
- * } String;
- */
+// note this is the runtime representation
+// of the compilers strings.
+//
+// typedef struct
+// { // must not move anything
+// uchar array[8]; // pointer to data
+// uchar nel[4]; // number of elements
+// } String;
var sizeof_String int // runtime sizeof(String)
var dotlist [10]Dlist // size is max depth of embeddeds
var lexbuf bytes.Buffer
var strbuf bytes.Buffer
-
-var litbuf string
+var litbuf string // LLITERAL value for use in syntax error messages
var Debug [256]int
var racepkg *Pkg // package runtime/race
+var msanpkg *Pkg // package runtime/msan
+
var typepkg *Pkg // fake package for runtime type info (headers)
var typelinkpkg *Pkg // fake package for runtime type info (data)
var trackpkg *Pkg // fake package for field tracking
-var Tptr int // either TPTR32 or TPTR64
+var Tptr EType // either TPTR32 or TPTR64
var myimportpath string
var errortype *Type
-var Simtype [NTYPE]uint8
+var Simtype [NTYPE]EType
var (
Isptr [NTYPE]bool
var funcsyms []*Node
-var dclcontext uint8 // PEXTERN/PAUTO
+var dclcontext Class // PEXTERN/PAUTO
var incannedimport int
var Widthreg int
-var typesw *Node
+var typesw *Node // TODO(gri) remove when yacc-based parser is gone
var nblank *Node
var flag_race int
+var flag_msan int
+
var flag_largemodel int
+// Whether we are adding any sort of code instrumentation, such as
+// when the race detector is enabled.
+var instrumenting bool
+
// Pending annotations for next func declaration.
var (
- noescape bool
- nosplit bool
- nowritebarrier bool
- systemstack bool
- norace bool
+ noescape bool
+ noinline bool
+ norace bool
+ nosplit bool
+ nowritebarrier bool
+ nowritebarrierrec bool
+ systemstack bool
)
var debuglive int
Rpo []*Flow
}
-/*
- * interface to back end
- */
+// interface to back end
const (
// Pseudo-op, like TEXT, GLOBL, TYPE, PCDATA, FUNCDATA.
Bgen_float func(*Node, bool, int, *obj.Prog) // optional
Cgen64 func(*Node, *Node) // only on 32-bit systems
Cgenindex func(*Node, *Node, bool) *obj.Prog
- Cgen_bmul func(int, *Node, *Node, *Node) bool
+ Cgen_bmul func(Op, *Node, *Node, *Node) bool
Cgen_float func(*Node, *Node) // optional
Cgen_hmul func(*Node, *Node, *Node)
- Cgen_shift func(int, bool, *Node, *Node, *Node)
+ Cgen_shift func(Op, bool, *Node, *Node, *Node)
Clearfat func(*Node)
- Cmp64 func(*Node, *Node, int, int, *obj.Prog) // only on 32-bit systems
+ Cmp64 func(*Node, *Node, Op, int, *obj.Prog) // only on 32-bit systems
Defframe func(*obj.Prog)
- Dodiv func(int, *Node, *Node, *Node)
+ Dodiv func(Op, *Node, *Node, *Node)
Excise func(*Flow)
Expandchecks func(*obj.Prog)
Getg func(*Node)
// function calls needed during the evaluation, and on 32-bit systems
// the values are guaranteed not to be 64-bit values, so no in-memory
// temporaries are necessary.
- Ginscmp func(op int, t *Type, n1, n2 *Node, likely int) *obj.Prog
+ Ginscmp func(op Op, t *Type, n1, n2 *Node, likely int) *obj.Prog
// Ginsboolval inserts instructions to convert the result
// of a just-completed comparison to a boolean value.
FtoB func(int) uint64
BtoR func(uint64) int
BtoF func(uint64) int
- Optoas func(int, *Type) int
+ Optoas func(Op, *Type) int
Doregbits func(int) uint64
Regnames func(*int) []string
Use387 bool // should 8g use 387 FP instructions instead of sse2.
break;
}
if my.Name == "init" {
+ lineno = int32($1)
Yyerror("cannot import package as init - init must be a func");
break;
}
} else if importpkg.Name != $2.Name {
Yyerror("conflicting names %s and %s for package %q", importpkg.Name, $2.Name, importpkg.Path);
}
- importpkg.Direct = true;
+ if incannedimport == 0 {
+ importpkg.Direct = true;
+ }
importpkg.Safe = curio.importsafe
if safemode != 0 && !curio.importsafe {
| expr LASOP expr
{
$$ = Nod(OASOP, $1, $3);
- $$.Etype = uint8($2); // rathole to pass opcode
+ $$.Etype = EType($2); // rathole to pass opcode
}
| expr_list '=' expr_list
{
}
if $1.Next != nil {
Yyerror("argument count mismatch: %d = %d", count($1), 1);
- } else if ($1.N.Op != ONAME && $1.N.Op != OTYPE && $1.N.Op != ONONAME) || isblank($1.N) {
+ } else if ($1.N.Op != ONAME && $1.N.Op != OTYPE && $1.N.Op != ONONAME && ($1.N.Op != OLITERAL || $1.N.Name == nil)) || isblank($1.N) {
Yyerror("invalid variable name %s in type switch", $1.N);
} else {
$$.Left = dclname($1.N.Sym);
{
$$ = Nod(OASOP, $1, Nodintconst(1));
$$.Implicit = true;
- $$.Etype = OADD;
+ // TODO(marvin): Fix Node.EType type union.
+ $$.Etype = EType(OADD);
}
| expr LDEC
{
$$ = Nod(OASOP, $1, Nodintconst(1));
$$.Implicit = true;
- $$.Etype = OSUB;
+ // TODO(marvin): Fix Node.EType type union.
+ $$.Etype = EType(OSUB);
}
case:
$$.Noescape = noescape;
$$.Func.Norace = norace;
$$.Func.Nosplit = nosplit;
+ $$.Func.Noinline = noinline;
$$.Func.Nowritebarrier = nowritebarrier;
+ $$.Func.Nowritebarrierrec = nowritebarrierrec;
$$.Func.Systemstack = systemstack;
funcbody($$);
}
if nsyntaxerrors == 0 {
testdclstack();
}
- nointerface = false
noescape = false
+ noinline = false
+ nointerface = false
norace = false
nosplit = false
nowritebarrier = false
+ nowritebarrierrec = false
systemstack = false
}
var dpc *obj.Prog
-/*
- * Is this node a memory operand?
- */
+// Is this node a memory operand?
func Ismem(n *Node) bool {
switch n.Op {
case OITAB,
p := Prog(as)
p.To.Type = obj.TYPE_BRANCH
p.To.Val = nil
- if as != obj.AJMP && likely != 0 && Thearch.Thechar != '9' && Thearch.Thechar != '7' {
+ if as != obj.AJMP && likely != 0 && Thearch.Thechar != '9' && Thearch.Thechar != '7' && Thearch.Thechar != '0' {
p.From.Type = obj.TYPE_CONST
if likely > 0 {
p.From.Offset = 1
// n->left is PHEAP ONAME for stack parameter.
// compute address of actual parameter on stack.
case OPARAM:
- a.Etype = Simtype[n.Left.Type.Etype]
+ a.Etype = uint8(Simtype[n.Left.Type.Etype])
a.Width = n.Left.Type.Width
a.Offset = n.Xoffset
case ONAME:
a.Etype = 0
if n.Type != nil {
- a.Etype = Simtype[n.Type.Etype]
+ a.Etype = uint8(Simtype[n.Type.Etype])
}
a.Offset = n.Xoffset
s := n.Sym
a.Sym = Linksym(s)
+ case ODOT:
+ // A special case to make write barriers more efficient.
+ // Taking the address of the first field of a named struct
+ // is the same as taking the address of the struct.
+ if n.Left.Type.Etype != TSTRUCT || n.Left.Type.Type.Sym != n.Right.Sym {
+ Debug['h'] = 1
+ Dump("naddr", n)
+ Fatalf("naddr: bad %v %v", Oconv(int(n.Op), 0), Ctxt.Dconv(a))
+ }
+ Naddr(a, n.Left)
+
case OLITERAL:
if Thearch.Thechar == '8' {
a.Width = 0
case OADDR:
Naddr(a, n.Left)
a.Etype = uint8(Tptr)
- if Thearch.Thechar != '5' && Thearch.Thechar != '7' && Thearch.Thechar != '9' { // TODO(rsc): Do this even for arm, ppc64.
+ if Thearch.Thechar != '0' && Thearch.Thechar != '5' && Thearch.Thechar != '7' && Thearch.Thechar != '9' { // TODO(rsc): Do this even for arm, ppc64.
a.Width = int64(Widthptr)
}
if a.Type != obj.TYPE_MEM {
if a.Type == obj.TYPE_CONST && a.Offset == 0 {
break // ptr(nil)
}
- a.Etype = Simtype[Tptr]
+ a.Etype = uint8(Simtype[Tptr])
a.Offset += int64(Array_array)
a.Width = int64(Widthptr)
if a.Type == obj.TYPE_CONST && a.Offset == 0 {
break // len(nil)
}
- a.Etype = Simtype[TUINT]
+ a.Etype = uint8(Simtype[TUINT])
a.Offset += int64(Array_nel)
if Thearch.Thechar != '5' { // TODO(rsc): Do this even on arm.
a.Width = int64(Widthint)
if a.Type == obj.TYPE_CONST && a.Offset == 0 {
break // cap(nil)
}
- a.Etype = Simtype[TUINT]
+ a.Etype = uint8(Simtype[TUINT])
a.Offset += int64(Array_cap)
if Thearch.Thechar != '5' { // TODO(rsc): Do this even on arm.
a.Width = int64(Widthint)
return n > len(Thearch.ReservedRegs)
}
-/*
- * allocate register of type t, leave in n.
- * if o != N, o may be reusable register.
- * caller must Regfree(n).
- */
+// allocate register of type t, leave in n.
+// if o != N, o may be reusable register.
+// caller must Regfree(n).
func Regalloc(n *Node, t *Type, o *Node) {
if t == nil {
Fatalf("regalloc: t nil")
}
- et := int(Simtype[t.Etype])
+ et := Simtype[t.Etype]
if Ctxt.Arch.Regsize == 4 && (et == TINT64 || et == TUINT64) {
Fatalf("regalloc 64bit")
}
// a->offset += v;
// break;
-/*
- * a function named init is a special case.
- * it is called by the initialization before
- * main is run. to make it unique within a
- * package and also uncallable, the name,
- * normally "pkg.init", is altered to "pkg.init.1".
- */
+// a function named init is a special case.
+// it is called by the initialization before
+// main is run. to make it unique within a
+// package and also uncallable, the name,
+// normally "pkg.init", is altered to "pkg.init.1".
var renameinit_initgen int
return Lookupf("init.%d", renameinit_initgen)
}
-/*
- * hand-craft the following initialization code
- * var initdone· uint8 (1)
- * func init() (2)
- * if initdone· != 0 { (3)
- * if initdone· == 2 (4)
- * return
- * throw(); (5)
- * }
- * initdone· = 1; (6)
- * // over all matching imported symbols
- * <pkg>.init() (7)
- * { <init stmts> } (8)
- * init.<n>() // if any (9)
- * initdone· = 2; (10)
- * return (11)
- * }
- */
+// hand-craft the following initialization code
+// var initdone· uint8 (1)
+// func init() (2)
+// if initdone· != 0 { (3)
+// if initdone· == 2 (4)
+// return
+// throw(); (5)
+// }
+// initdone· = 1; (6)
+// // over all matching imported symbols
+// <pkg>.init() (7)
+// { <init stmts> } (8)
+// init.<n>() // if any (9)
+// initdone· = 2; (10)
+// return (11)
+// }
func anyinit(n *NodeList) bool {
// are there any interesting init statements
for l := n; l != nil; l = l.Next {
Fatalf("caninl no nname %v", Nconv(fn, obj.FmtSign))
}
+ // If marked "go:noinline", don't inline
+ if fn.Func.Noinline {
+ return
+ }
+
// If fn has no body (is defined outside of Go), cannot inline it.
if fn.Nbody == nil {
return
}
}
- // Runtime package must not be race instrumented.
- // Racewalk skips runtime package. However, some runtime code can be
+ // Runtime package must not be instrumented.
+ // Instrument skips runtime package. However, some runtime code can be
// inlined into other packages and instrumented there. To avoid this,
- // we disable inlining of runtime functions in race mode.
+ // we disable inlining of runtime functions when instrumenting.
// The example that we observed is inlining of LockOSThread,
// which lead to false race reports on m contents.
- if flag_race != 0 && myimportpath == "runtime" {
+ if instrumenting && myimportpath == "runtime" {
return
}
case ODEFER, OPROC:
switch n.Left.Op {
case OCALLFUNC, OCALLMETH:
- n.Left.Etype = n.Op
+ // TODO(marvin): Fix Node.EType type union.
+ n.Left.Etype = EType(n.Op)
}
fallthrough
// switch at the top of this function.
switch n.Op {
case OCALLFUNC, OCALLMETH:
- if n.Etype == OPROC || n.Etype == ODEFER {
+ // TODO(marvin): Fix Node.EType type union.
+ if n.Etype == EType(OPROC) || n.Etype == EType(ODEFER) {
return
}
}
{"slice", &Debug_slice}, // print information about slice compilation
{"typeassert", &Debug_typeassert}, // print information about type assertion inlining
{"wb", &Debug_wb}, // print information about write barriers
+ {"export", &Debug_export}, // print export data
}
const (
obj.Flagcount("l", "disable inlining", &Debug['l'])
obj.Flagcount("live", "debug liveness analysis", &debuglive)
obj.Flagcount("m", "print optimization decisions", &Debug['m'])
+ obj.Flagcount("msan", "build code compatible with C/C++ memory sanitizer", &flag_msan)
+ obj.Flagcount("newexport", "use new export format", &newexport) // TODO(gri) remove eventually (issue 13241)
+ obj.Flagcount("oldparser", "use old parser", &oldparser) // TODO(gri) remove eventually (issue 13240)
obj.Flagcount("nolocalimports", "reject local (relative) imports", &nolocalimports)
obj.Flagstr("o", "write output to `file`", &outfile)
obj.Flagstr("p", "set expected package import `path`", &myimportpath)
obj.Flagcount("y", "debug declarations in canned imports (with -d)", &Debug['y'])
var flag_shared int
var flag_dynlink bool
- if Thearch.Thechar == '6' || Thearch.Thechar == '5' {
+ switch Thearch.Thechar {
+ case '5', '6', '7', '9':
obj.Flagcount("shared", "generate code that can be linked into a shared library", &flag_shared)
}
if Thearch.Thechar == '6' {
obj.Flagcount("largemodel", "generate code that assumes a large memory model", &flag_largemodel)
+ }
+ switch Thearch.Thechar {
+ case '5', '6', '7', '8', '9':
flag.BoolVar(&flag_dynlink, "dynlink", false, "support references to Go symbols defined in other shared libraries")
}
obj.Flagstr("cpuprofile", "write cpu profile to `file`", &cpuprofile)
racepkg = mkpkg("runtime/race")
racepkg.Name = "race"
}
+ if flag_msan != 0 {
+ msanpkg = mkpkg("runtime/msan")
+ msanpkg.Name = "msan"
+ }
+ if flag_race != 0 && flag_msan != 0 {
+ log.Fatal("can not use both -race and -msan")
+ } else if flag_race != 0 || flag_msan != 0 {
+ instrumenting = true
+ }
// parse -d argument
if debugstr != "" {
lexlineno = 1
const BOM = 0xFEFF
+ // Uncomment the line below to temporarily switch the compiler back
+ // to the yacc-based parser. Short-term work-around for issues with
+ // the new recursive-descent parser for which setting -oldparser is
+ // not sufficient.
+ // TODO(gri) remove this eventually (issue 13240)
+ //
+ // oldparser = 1
+
for _, infile = range flag.Args() {
+ if trace && Debug['x'] != 0 && oldparser == 0 {
+ fmt.Printf("--- %s ---\n", infile)
+ }
+
linehistpush(infile)
curio.infile = infile
fninit(xtop)
}
+ if compiling_runtime != 0 {
+ checknowritebarrierrec()
+ }
+
// Phase 9: Check external declarations.
for i, n := range externdcl {
if n.Op == ONAME {
}
func skiptopkgdef(b *obj.Biobuf) bool {
- /* archive header */
+ // archive header
p := obj.Brdline(b, '\n')
if p == "" {
return false
return false
}
- /* symbol table may be first; skip it */
+ // symbol table may be first; skip it
sz := arsize(b, "__.GOSYMDEF")
if sz >= 0 {
obj.Bseek(b, 8, 0)
}
- /* package export block is next */
+ // package export block is next
sz = arsize(b, "__.PKGDEF")
if sz <= 0 {
} else if flag_race != 0 {
suffixsep = "_"
suffix = "race"
+ } else if flag_msan != 0 {
+ suffixsep = "_"
+ suffix = "msan"
}
file = fmt.Sprintf("%s/pkg/%s_%s%s%s/%s.a", goroot, goos, goarch, suffixsep, suffix, name)
cannedimports("fake.o", "$$\n")
}
+// TODO(gri) line argument doesn't appear to be used
func importfile(f *Val, line int) {
if _, ok := f.U.(string); !ok {
Yyerror("import statement not a string")
// so don't record the full path.
linehistpragma(file[len(file)-len(path_)-2:]) // acts as #pragma lib
- /*
- * position the input right
- * after $$ and return
- */
- pushedio = curio
-
- curio.bin = imp
- curio.peekc = 0
- curio.peekc1 = 0
- curio.infile = file
- curio.nlsemi = false
- typecheckok = true
+ // In the importfile, if we find:
+ // $$\n (old format): position the input right after $$\n and return
+ // $$B\n (new format): import directly, then feed the lexer a dummy statement
+ // look for $$
+ var c int
for {
- c := getc()
- if c == EOF {
+ c = obj.Bgetc(imp)
+ if c < 0 {
break
}
- if c != '$' {
- continue
+ if c == '$' {
+ c = obj.Bgetc(imp)
+ if c == '$' || c < 0 {
+ break
+ }
}
- c = getc()
- if c == EOF {
- break
+ }
+
+ // get character after $$
+ if c >= 0 {
+ c = obj.Bgetc(imp)
+ }
+
+ switch c {
+ case '\n':
+ // old export format
+ pushedio = curio
+
+ curio.bin = imp
+ curio.peekc = 0
+ curio.peekc1 = 0
+ curio.infile = file
+ curio.nlsemi = false
+ typecheckok = true
+
+ if oldparser == 0 {
+ push_parser()
}
- if c != '$' {
- continue
+
+ case 'B':
+ // new export format
+ obj.Bgetc(imp) // skip \n after $$B
+ Import(imp)
+
+ // continue as if the package was imported before (see above)
+ tag := ""
+ if importpkg.Safe {
+ tag = "safe"
}
- return
- }
+ p := fmt.Sprintf("package %s %s\n$$\n", importpkg.Name, tag)
+ cannedimports(file, p)
- Yyerror("no import in %q", f.U.(string))
- unimportfile()
+ default:
+ Yyerror("no import in %q", f.U.(string))
+ }
}
func unimportfile() {
+ if oldparser == 0 {
+ pop_parser()
+ }
+
if curio.bin != nil {
obj.Bterm(curio.bin)
curio.bin = nil
typecheckok = true
incannedimport = 1
+
+ if oldparser == 0 {
+ push_parser()
+ }
}
func isSpace(c int) bool {
goto l0
}
- lineno = lexlineno /* start of token */
+ lineno = lexlineno // start of token
if c >= utf8.RuneSelf {
- /* all multibyte runes are alpha */
+ // all multibyte runes are alpha
cp = &lexbuf
cp.Reset()
c1 = '.'
}
- /* "..." */
+ // "..."
case '"':
lexbuf.Reset()
lexbuf.WriteString(`"<string>"`)
goto strlit
- /* `...` */
+ // `...`
case '`':
lexbuf.Reset()
lexbuf.WriteString("`<string>`")
goto strlit
- /* '.' */
+ // '.'
case '\'':
if escchar('\'', &escflag, &v) {
Yyerror("empty character literal or unescaped ' in character literal")
}
if c1 == '=' {
- c = ODIV
+ c = int(ODIV)
goto asop
}
case ':':
c1 = getc()
if c1 == '=' {
- c = LCOLAS
+ c = int(LCOLAS)
yylval.i = int(lexlineno)
goto lx
}
case '*':
c1 = getc()
if c1 == '=' {
- c = OMUL
+ c = int(OMUL)
goto asop
}
case '%':
c1 = getc()
if c1 == '=' {
- c = OMOD
+ c = int(OMOD)
goto asop
}
case '+':
c1 = getc()
if c1 == '+' {
- c = LINC
+ c = int(LINC)
goto lx
}
if c1 == '=' {
- c = OADD
+ c = int(OADD)
goto asop
}
case '-':
c1 = getc()
if c1 == '-' {
- c = LDEC
+ c = int(LDEC)
goto lx
}
if c1 == '=' {
- c = OSUB
+ c = int(OSUB)
goto asop
}
case '>':
c1 = getc()
if c1 == '>' {
- c = LRSH
+ c = int(LRSH)
c1 = getc()
if c1 == '=' {
- c = ORSH
+ c = int(ORSH)
goto asop
}
}
if c1 == '=' {
- c = LGE
+ c = int(LGE)
goto lx
}
- c = LGT
+ c = int(LGT)
case '<':
c1 = getc()
if c1 == '<' {
- c = LLSH
+ c = int(LLSH)
c1 = getc()
if c1 == '=' {
- c = OLSH
+ c = int(OLSH)
goto asop
}
}
if c1 == '=' {
- c = LLE
+ c = int(LLE)
goto lx
}
if c1 == '-' {
- c = LCOMM
+ c = int(LCOMM)
goto lx
}
- c = LLT
+ c = int(LLT)
case '=':
c1 = getc()
if c1 == '=' {
- c = LEQ
+ c = int(LEQ)
goto lx
}
case '!':
c1 = getc()
if c1 == '=' {
- c = LNE
+ c = int(LNE)
goto lx
}
case '&':
c1 = getc()
if c1 == '&' {
- c = LANDAND
+ c = int(LANDAND)
goto lx
}
if c1 == '^' {
- c = LANDNOT
+ c = int(LANDNOT)
c1 = getc()
if c1 == '=' {
- c = OANDNOT
+ c = int(OANDNOT)
goto asop
}
}
if c1 == '=' {
- c = OAND
+ c = int(OAND)
goto asop
}
case '|':
c1 = getc()
if c1 == '|' {
- c = LOROR
+ c = int(LOROR)
goto lx
}
if c1 == '=' {
- c = OOR
+ c = int(OOR)
goto asop
}
case '^':
c1 = getc()
if c1 == '=' {
- c = OXOR
+ c = int(OXOR)
goto asop
}
- /*
- * clumsy dance:
- * to implement rule that disallows
- * if T{1}[0] { ... }
- * but allows
- * if (T{1}[0]) { ... }
- * the block bodies for if/for/switch/select
- * begin with an LBODY token, not '{'.
- *
- * when we see the keyword, the next
- * non-parenthesized '{' becomes an LBODY.
- * loophack is normally false.
- * a keyword sets it to true.
- * parens push loophack onto a stack and go back to false.
- * a '{' with loophack == true becomes LBODY and disables loophack.
- *
- * i said it was clumsy.
- */
+ // clumsy dance:
+ // to implement rule that disallows
+ // if T{1}[0] { ... }
+ // but allows
+ // if (T{1}[0]) { ... }
+ // the block bodies for if/for/switch/select
+ // begin with an LBODY token, not '{'.
+ //
+ // when we see the keyword, the next
+ // non-parenthesized '{' becomes an LBODY.
+ // loophack is normally false.
+ // a keyword sets it to true.
+ // parens push loophack onto a stack and go back to false.
+ // a '{' with loophack == true becomes LBODY and disables loophack.
+ //
+ // I said it was clumsy.
+ //
+ // We only need the loophack when running with -oldparser.
case '(', '[':
- if loophack || _yylex_lstk != nil {
+ if oldparser != 0 && (loophack || _yylex_lstk != nil) {
h = new(Loophack)
if h == nil {
Flusherrors()
goto lx
case ')', ']':
- if _yylex_lstk != nil {
+ if oldparser != 0 && _yylex_lstk != nil {
h = _yylex_lstk
loophack = h.v
_yylex_lstk = h.next
goto lx
case '{':
- if loophack {
+ if oldparser != 0 && loophack {
if Debug['x'] != 0 {
fmt.Printf("%v lex: LBODY\n", Ctxt.Line(int(lexlineno)))
}
}
return LASOP
- /*
- * cp is set to lexbuf and some
- * prefix has been stored
- */
+ // cp is set to lexbuf and some
+ // prefix has been stored
talph:
for {
if c >= utf8.RuneSelf {
if !unicode.IsLetter(r) && !unicode.IsDigit(r) && (importpkg == nil || r != 0xb7) {
Yyerror("invalid identifier character U+%04x", r)
}
+ if cp.Len() == 0 && unicode.IsDigit(r) {
+ Yyerror("identifier cannot begin with digit U+%04x", r)
+ }
cp.WriteRune(r)
} else if !isAlnum(c) && c != '_' {
break
goto l0
case LFOR, LIF, LSWITCH, LSELECT:
- loophack = true // see comment about loophack above
+ if oldparser != 0 {
+ loophack = true // see comment about loophack above
+ }
}
if Debug['x'] != 0 {
mpatoflt(&yylval.val.U.(*Mpcplx).Imag, str)
if yylval.val.U.(*Mpcplx).Imag.Val.IsInf() {
Yyerror("overflow in imaginary constant")
- Mpmovecflt(&yylval.val.U.(*Mpcplx).Real, 0.0)
+ Mpmovecflt(&yylval.val.U.(*Mpcplx).Imag, 0.0)
}
if Debug['x'] != 0 {
return p != ""
}
-/*
- * read and interpret syntax that looks like
- * //line parse.y:15
- * as a discontinuity in sequential line numbers.
- * the next line of input comes from parse.y:15
- */
+// read and interpret syntax that looks like
+// //line parse.y:15
+// as a discontinuity in sequential line numbers.
+// the next line of input comes from parse.y:15
func getlinepragma() int {
var cmd, verb, name string
return c
}
+ if verb == "go:noinline" {
+ noinline = true
+ return c
+ }
+
if verb == "go:systemstack" {
if compiling_runtime == 0 {
Yyerror("//go:systemstack only allowed in runtime")
nowritebarrier = true
return c
}
+
+ if verb == "go:nowritebarrierrec" {
+ if compiling_runtime == 0 {
+ Yyerror("//go:nowritebarrierrec only allowed in runtime")
+ }
+ nowritebarrierrec = true
+ nowritebarrier = true // Implies nowritebarrier
+ return c
+ }
return c
}
if c != 'l' {
Yyerror("%s", msg)
}
+var oldparser int // if set, theparser is used (otherwise we use the recursive-descent parser)
var theparser yyParser
var parsing bool
func yyparse() {
- theparser = yyNewParser()
parsing = true
- theparser.Parse(yy{})
+ if oldparser != 0 {
+ theparser = yyNewParser()
+ theparser.Parse(yy{})
+ } else {
+ parse_file()
+ }
parsing = false
}
var syms = []struct {
name string
lexical int
- etype int
- op int
+ etype EType
+ op Op
}{
- /* basic types */
+ // basic types
{"int8", LNAME, TINT8, OXXX},
{"int16", LNAME, TINT16, OXXX},
{"int32", LNAME, TINT32, OXXX},
s1.Lexical = uint16(lex)
if etype := s.etype; etype != Txxx {
- if etype < 0 || etype >= len(Types) {
+ if int(etype) >= len(Types) {
Fatalf("lexinit: %s bad etype", s.name)
}
s2 := Pkglookup(s.name, builtinpkg)
continue
}
+ // TODO(marvin): Fix Node.EType type union.
if etype := s.op; etype != OXXX {
s2 := Pkglookup(s.name, builtinpkg)
s2.Lexical = LNAME
s2.Def = Nod(ONAME, nil, nil)
s2.Def.Sym = s2
- s2.Def.Etype = uint8(etype)
+ s2.Def.Etype = EType(etype)
}
}
}
func lexfini() {
- var s *Sym
- var lex int
- var etype int
- var i int
-
- for i = 0; i < len(syms); i++ {
- lex = syms[i].lexical
+ for i := range syms {
+ lex := syms[i].lexical
if lex != LNAME {
continue
}
- s = Lookup(syms[i].name)
+ s := Lookup(syms[i].name)
s.Lexical = uint16(lex)
- etype = syms[i].etype
+ etype := syms[i].etype
if etype != Txxx && (etype != TANY || Debug['A'] != 0) && s.Def == nil {
s.Def = typenod(Types[etype])
s.Def.Name = new(Name)
s.Origpkg = builtinpkg
}
- etype = syms[i].op
- if etype != OXXX && s.Def == nil {
+ // TODO(marvin): Fix Node.EType type union.
+ etype = EType(syms[i].op)
+ if etype != EType(OXXX) && s.Def == nil {
s.Def = Nod(ONAME, nil, nil)
s.Def.Sym = s
- s.Def.Etype = uint8(etype)
+ s.Def.Etype = etype
s.Origpkg = builtinpkg
}
}
// backend-specific builtin types (e.g. int).
- for i = range Thearch.Typedefs {
- s = Lookup(Thearch.Typedefs[i].Name)
+ for i := range Thearch.Typedefs {
+ s := Lookup(Thearch.Typedefs[i].Name)
if s.Def == nil {
s.Def = typenod(Types[Thearch.Typedefs[i].Etype])
s.Def.Name = new(Name)
// there's only so much table-driven we can handle.
// these are special cases.
- s = Lookup("byte")
-
- if s.Def == nil {
+ if s := Lookup("byte"); s.Def == nil {
s.Def = typenod(bytetype)
s.Def.Name = new(Name)
s.Origpkg = builtinpkg
}
- s = Lookup("error")
- if s.Def == nil {
+ if s := Lookup("error"); s.Def == nil {
s.Def = typenod(errortype)
s.Def.Name = new(Name)
s.Origpkg = builtinpkg
}
- s = Lookup("rune")
- if s.Def == nil {
+ if s := Lookup("rune"); s.Def == nil {
s.Def = typenod(runetype)
s.Def.Name = new(Name)
s.Origpkg = builtinpkg
}
- s = Lookup("nil")
- if s.Def == nil {
+ if s := Lookup("nil"); s.Def == nil {
var v Val
v.U = new(NilVal)
s.Def = nodlit(v)
s.Origpkg = builtinpkg
}
- s = Lookup("iota")
- if s.Def == nil {
+ if s := Lookup("iota"); s.Def == nil {
s.Def = Nod(OIOTA, nil, nil)
s.Def.Sym = s
s.Origpkg = builtinpkg
}
- s = Lookup("true")
- if s.Def == nil {
+ if s := Lookup("true"); s.Def == nil {
s.Def = Nodbool(true)
s.Def.Sym = s
s.Def.Name = new(Name)
s.Origpkg = builtinpkg
}
- s = Lookup("false")
- if s.Def == nil {
+ if s := Lookup("false"); s.Def == nil {
s.Def = Nodbool(false)
s.Def.Sym = s
s.Def.Name = new(Name)
// +build ignore
-// Generate builtin.go from $* (runtime.go and unsafe.go).
-// Run this after changing runtime.go and unsafe.go
+// Generate builtin.go from builtin/runtime.go and builtin/unsafe.go
+// (passed as arguments on the command line by a go:generate comment).
+// Run this after changing builtin/runtime.go and builtin/unsafe.go
// or after changing the export metadata format in the compiler.
// Either way, you need to have a working compiler binary first.
package main
Yyerror("mpgetflt ovf")
}
- return x
+ return x + 0 // avoid -0 (should not be needed, but be conservative)
}
func mpgetflt32(a *Mpflt) float64 {
Yyerror("mpgetflt32 ovf")
}
- return x
+ return x + 0 // avoid -0 (should not be needed, but be conservative)
}
func Mpmovecflt(a *Mpflt, c float64) {
fmt.Printf("\nconst %g", c)
}
+ // convert -0 to 0
+ if c == 0 {
+ c = 0
+ }
a.Val.SetFloat64(c)
if Mpdebug {
}
func mpnegflt(a *Mpflt) {
- a.Val.Neg(&a.Val)
+ // avoid -0
+ if a.Val.Sign() != 0 {
+ a.Val.Neg(&a.Val)
+ }
}
//
// - decimal point and binary point in constant
// TODO(gri) use different conversion function or check separately
Yyerror("malformed constant: %s", as)
- a.Val.SetUint64(0)
+ a.Val.SetFloat64(0)
return
}
if f.IsInf() {
Yyerror("constant too large: %s", as)
- a.Val.SetUint64(0)
+ a.Val.SetFloat64(0)
return
}
+
+ // -0 becomes 0
+ if f.Sign() == 0 && f.Signbit() {
+ a.Val.SetFloat64(0)
+ }
}
func (f *Mpflt) String() string {
// determine sign
f := &fvp.Val
var sign string
- if fvp.Val.Signbit() {
+ if f.Sign() < 0 {
sign = "-"
f = new(big.Float).Abs(f)
} else if flag&obj.FmtSign != 0 {
sign = "+"
}
+ // Don't try to convert infinities (will not terminate).
+ if f.IsInf() {
+ return sign + "Inf"
+ }
+
// Use fmt formatting if in float64 range (common case).
if x, _ := f.Float64(); !math.IsInf(x, 0) {
return fmt.Sprintf("%s%.6g", sign, x)
"strconv"
)
-/*
- * architecture-independent object file output
- */
+// architecture-independent object file output
const (
ArhdrSize = 60
)
a.Sym = Linksym(symdata)
a.Node = symdata.Def
a.Offset = 0
- a.Etype = Simtype[TINT]
+ a.Etype = uint8(Simtype[TINT])
}
func datagostring(sval string, a *obj.Addr) {
a.Sym = Linksym(symhdr)
a.Node = symhdr.Def
a.Offset = 0
- a.Etype = TSTRING
+ a.Etype = uint8(TSTRING)
}
func dgostringptr(s *Sym, off int, str string) int {
p.From3.Offset = int64(Widthptr)
datagostring(*lit, &p.To)
p.To.Type = obj.TYPE_ADDR
- p.To.Etype = Simtype[TINT]
+ p.To.Etype = uint8(Simtype[TINT])
off += Widthptr
return off
}
func gdatacomplex(nam *Node, cval *Mpcplx) {
- w := cplxsubtype(int(nam.Type.Etype))
- w = int(Types[w].Width)
+ cst := cplxsubtype(nam.Type.Etype)
+ w := int(Types[cst].Width)
p := Thearch.Gins(obj.ADATA, nam, nil)
p.From3 = new(obj.Addr)
// contain m or k. They are usually unnecessary, but in the unnecessary
// cases they are also typically registerizable, so not much harm done.
// And this only applies to the multiple-assignment form.
-// We could do a more precise analysis if needed, like in walk.c.
+// We could do a more precise analysis if needed, like in walk.go.
//
// Ordermapassign also inserts these temporaries if needed for
// calling writebarrierfat with a pointer to n->right.
case OAS:
order.out = list(order.out, n)
- // We call writebarrierfat only for values > 4 pointers long. See walk.c.
+ // We call writebarrierfat only for values > 4 pointers long. See walk.go.
if (n.Left.Op == OINDEXMAP || (needwritebarrier(n.Left, n.Right) && n.Left.Type.Width > int64(4*Widthptr))) && !isaddrokay(n.Right) {
m := n.Left
n.Left = ordertemp(m.Type, order, false)
a = Nod(OAS, m, l.N)
typecheck(&a, Etop)
post = list(post, a)
- } else if flag_race != 0 && n.Op == OAS2FUNC && !isblank(l.N) {
+ } else if instrumenting && n.Op == OAS2FUNC && !isblank(l.N) {
m = l.N
l.N = ordertemp(m.Type, order, false)
a = Nod(OAS, m, l.N)
tmp1.Etype = 0 // now an rvalue not an lvalue
}
tmp1 = ordercopyexpr(tmp1, n.Left.Type, order, 0)
- n.Right = Nod(int(n.Etype), tmp1, n.Right)
+ // TODO(marvin): Fix Node.EType type union.
+ n.Right = Nod(Op(n.Etype), tmp1, n.Right)
typecheck(&n.Right, Erv)
orderexpr(&n.Right, order, nil)
n.Etype = 0
ordercallargs(&n.List, order)
order.out = list(order.out, n)
- // Special: clean case temporaries in each block entry.
+ // Special: clean case temporaries in each block entry.
// Select must enter one of its blocks, so there is no
// need for a cleaning at the end.
// Doubly special: evaluation order for select is stricter
OREAL,
ORECOVER:
ordercall(n, order)
- if lhs == nil || lhs.Op != ONAME || flag_race != 0 {
+ if lhs == nil || lhs.Op != ONAME || instrumenting {
n = ordercopyexpr(n, n.Type, order, 0)
}
// TODO(rsc): The Isfat is for consistency with componentgen and walkexpr.
// It needs to be removed in all three places.
// That would allow inlining x.(struct{*int}) the same as x.(*int).
- if !isdirectiface(n.Type) || Isfat(n.Type) || flag_race != 0 {
+ if !isdirectiface(n.Type) || Isfat(n.Type) || instrumenting {
n = ordercopyexpr(n, n.Type, order, 1)
}
--- /dev/null
+// Copyright 2015 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 gc
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+)
+
+const trace = false // if set, parse tracing can be enabled with -x
+
+// TODO(gri) Once we handle imports w/o redirecting the underlying
+// source of the lexer we can get rid of these. They are here for
+// compatibility with the existing yacc-based parser setup (issue 13242).
+var thenewparser parser // the parser in use
+var savedstate []parser // saved parser state, used during import
+
+func push_parser() {
+ savedstate = append(savedstate, thenewparser)
+ thenewparser = parser{}
+ thenewparser.next()
+}
+
+func pop_parser() {
+ n := len(savedstate) - 1
+ thenewparser = savedstate[n]
+ savedstate = savedstate[:n]
+}
+
+func parse_file() {
+ thenewparser = parser{}
+ thenewparser.loadsys()
+ thenewparser.next()
+ thenewparser.file()
+}
+
+// This loads the definitions for the low-level runtime functions,
+// so that the compiler can generate calls to them,
+// but does not make the name "runtime" visible as a package.
+//
+// go.y:loadsys
+func (p *parser) loadsys() {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("loadsys")()
+ }
+
+ importpkg = Runtimepkg
+
+ if Debug['A'] != 0 {
+ cannedimports("runtime.Builtin", "package runtime\n\n$$\n\n")
+ } else {
+ cannedimports("runtime.Builtin", runtimeimport)
+ }
+ curio.importsafe = true
+
+ p.import_package()
+ p.import_there()
+
+ importpkg = nil
+}
+
+type parser struct {
+ tok int32 // next token (one-token look-ahead)
+ op Op // valid if tok == LASOP
+ val Val // valid if tok == LLITERAL
+ sym_ *Sym // valid if tok == LNAME
+ nest int // expression nesting level (for complit ambiguity resolution)
+ yy yySymType // for temporary use by next
+ indent int // tracing support
+}
+
+func (p *parser) next() {
+ p.tok = yylex(&p.yy)
+ p.op = Op(p.yy.i)
+ p.val = p.yy.val
+ p.sym_ = p.yy.sym
+}
+
+func (p *parser) got(tok int32) bool {
+ if p.tok == tok {
+ p.next()
+ return true
+ }
+ return false
+}
+
+func (p *parser) want(tok int32) {
+ if p.tok != EOF && !p.got(tok) {
+ p.syntax_error("")
+ p.advance()
+ }
+}
+
+// ----------------------------------------------------------------------------
+// Syntax error handling
+
+func (p *parser) syntax_error(msg string) {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("syntax_error (" + msg + ")")()
+ }
+
+ if p.tok == EOF && nerrors > 0 {
+ return // avoid meaningless follow-up errors
+ }
+
+ // add punctuation etc. as needed to msg
+ switch {
+ case msg == "":
+ // nothing to do
+ case strings.HasPrefix(msg, "in"), strings.HasPrefix(msg, "at"), strings.HasPrefix(msg, "after"):
+ msg = " " + msg
+ case strings.HasPrefix(msg, "expecting"):
+ msg = ", " + msg
+ default:
+ // plain error - we don't care about current token
+ Yyerror("syntax error: " + msg)
+ return
+ }
+
+ // determine token string
+ var tok string
+ switch p.tok {
+ case LLITERAL:
+ // this is also done in Yyerror but it's cleaner to do it here
+ tok = litbuf
+ case LNAME:
+ if p.sym_ != nil && p.sym_.Name != "" {
+ tok = p.sym_.Name
+ } else {
+ tok = "name"
+ }
+ case LASOP:
+ tok = goopnames[p.op] + "="
+ default:
+ tok = tokstring(p.tok)
+ }
+
+ Yyerror("syntax error: unexpected " + tok + msg)
+}
+
+// Advance consumes tokens until it finds a token of the stoplist.
+// If the stoplist is empty or no advance was necessary, the next
+// token is consumed.
+func (p *parser) advance(stoplist ...int32) {
+ if len(stoplist) == 0 {
+ p.next()
+ return
+ }
+
+ for n := 0; p.tok != EOF; n++ {
+ for _, stop := range stoplist {
+ if p.tok == stop {
+ if n == 0 {
+ p.next() // consume at least one token
+ }
+ return
+ }
+ }
+ p.next()
+ }
+}
+
+func tokstring(tok int32) string {
+ switch tok {
+ case EOF:
+ return "EOF"
+ case ',':
+ return "comma"
+ case ';':
+ return "semicolon or newline"
+ }
+ if 0 <= tok && tok < 128 {
+ // get invisibles properly backslashed
+ s := strconv.QuoteRune(tok)
+ if n := len(s); n > 0 && s[0] == '\'' && s[n-1] == '\'' {
+ s = s[1 : n-1]
+ }
+ return s
+ }
+ if s := tokstrings[tok]; s != "" {
+ return s
+ }
+ // catchall
+ return yyTokname(int(tok))
+}
+
+// TODO(gri) figure out why yyTokname doesn't work for us as expected
+// (issue 13243)
+var tokstrings = map[int32]string{
+ LLITERAL: "LLITERAL",
+ LASOP: "op=",
+ LCOLAS: ":=",
+ LBREAK: "break",
+ LCASE: "case",
+ LCHAN: "chan",
+ LCONST: "const",
+ LCONTINUE: "continue",
+ LDDD: "...",
+ LDEFAULT: "default",
+ LDEFER: "defer",
+ LELSE: "else",
+ LFALL: "fallthrough",
+ LFOR: "for",
+ LFUNC: "func",
+ LGO: "go",
+ LGOTO: "goto",
+ LIF: "if",
+ LIMPORT: "import",
+ LINTERFACE: "interface",
+ LMAP: "map",
+ LNAME: "LNAME",
+ LPACKAGE: "package",
+ LRANGE: "range",
+ LRETURN: "return",
+ LSELECT: "select",
+ LSTRUCT: "struct",
+ LSWITCH: "switch",
+ LTYPE: "type",
+ LVAR: "var",
+ LANDAND: "&&",
+ LANDNOT: "&^",
+ LBODY: "LBODY", // we should never see this one
+ LCOMM: "<-",
+ LDEC: "--",
+ LEQ: "==",
+ LGE: ">=",
+ LGT: ">",
+ LIGNORE: "LIGNORE", // we should never see this one
+ LINC: "++",
+ LLE: "<=",
+ LLSH: "<<",
+ LLT: "<",
+ LNE: "!=",
+ LOROR: "||",
+ LRSH: ">>",
+ NotPackage: "NotPackage", // we should never see this one
+ NotParen: "NotParen", // we should never see this one
+ PreferToRightParen: "PreferToRightParen", // we should never see this one
+}
+
+func (p *parser) print_trace(msg ...interface{}) {
+ const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "
+ const n = len(dots)
+ fmt.Printf("%5d: ", lineno)
+
+ // TODO(gri) imports screw up p.indent - fix this
+ // (issue 13243)
+ if p.indent < 0 {
+ p.indent = 0
+ }
+
+ i := 2 * p.indent
+ for i > n {
+ fmt.Print(dots)
+ i -= n
+ }
+ // i <= n
+ fmt.Print(dots[0:i])
+ fmt.Println(msg...)
+}
+
+// usage: defer p.trace(msg)()
+func (p *parser) trace(msg string) func() {
+ p.print_trace(msg, "(")
+ p.indent++
+ return func() {
+ p.indent--
+ if x := recover(); x != nil {
+ panic(x) // skip print_trace
+ }
+ p.print_trace(")")
+ }
+}
+
+// ----------------------------------------------------------------------------
+// Parsing package files
+
+// go.y:file
+func (p *parser) file() {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("file")()
+ }
+
+ p.package_()
+
+ //go.y:imports
+ for p.tok == LIMPORT {
+ p.import_()
+ p.want(';')
+ }
+
+ xtop = concat(xtop, p.xdcl_list())
+}
+
+// go.y:package
+func (p *parser) package_() {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("package_")()
+ }
+
+ if p.got(LPACKAGE) {
+ mkpackage(p.sym().Name)
+ p.want(';')
+ } else {
+ p.syntax_error("package statement must be first")
+ errorexit()
+ }
+}
+
+// go.y:import
+func (p *parser) import_() {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("import_")()
+ }
+
+ p.want(LIMPORT)
+ if p.got('(') {
+ for p.tok != EOF && p.tok != ')' {
+ p.import_stmt()
+ p.osemi()
+ }
+ p.want(')')
+ } else {
+ p.import_stmt()
+ }
+}
+
+// go.y:import_stmt
+func (p *parser) import_stmt() {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("import_stmt")()
+ }
+
+ line := int32(p.import_here())
+ if p.tok == LPACKAGE {
+ p.import_package()
+ p.import_there()
+
+ ipkg := importpkg
+ my := importmyname
+ importpkg = nil
+ importmyname = nil
+
+ if my == nil {
+ my = Lookup(ipkg.Name)
+ }
+
+ pack := Nod(OPACK, nil, nil)
+ pack.Sym = my
+ pack.Name.Pkg = ipkg
+ pack.Lineno = line
+
+ if strings.HasPrefix(my.Name, ".") {
+ importdot(ipkg, pack)
+ return
+ }
+ if my.Name == "init" {
+ lineno = line
+ Yyerror("cannot import package as init - init must be a func")
+ return
+ }
+ if my.Name == "_" {
+ return
+ }
+ if my.Def != nil {
+ lineno = line
+ redeclare(my, "as imported package name")
+ }
+ my.Def = pack
+ my.Lastlineno = line
+ my.Block = 1 // at top level
+
+ return
+ }
+
+ p.import_there()
+ // When an invalid import path is passed to importfile,
+ // it calls Yyerror and then sets up a fake import with
+ // no package statement. This allows us to test more
+ // than one invalid import statement in a single file.
+ if nerrors == 0 {
+ Fatalf("phase error in import")
+ }
+}
+
+// go.y:import_here
+func (p *parser) import_here() int {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("import_here")()
+ }
+
+ importmyname = nil
+ switch p.tok {
+ case LNAME, '@', '?':
+ // import with given name
+ importmyname = p.sym()
+
+ case '.':
+ // import into my name space
+ importmyname = Lookup(".")
+ p.next()
+ }
+
+ var path Val
+ if p.tok == LLITERAL {
+ path = p.val
+ p.next()
+ } else {
+ p.syntax_error("missing import path; require quoted string")
+ p.advance(';', ')')
+ }
+
+ line := parserline() // TODO(gri) check correct placement of this (issue 13243)
+ importfile(&path, line)
+ return line
+}
+
+// go.y:import_package
+func (p *parser) import_package() {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("import_package")()
+ }
+
+ p.want(LPACKAGE)
+ var name string
+ if p.tok == LNAME {
+ name = p.sym_.Name
+ p.next()
+ } else {
+ p.import_error()
+ }
+
+ // go.y:import_safety
+ if p.tok == LNAME {
+ if p.sym_.Name == "safe" {
+ curio.importsafe = true
+ }
+ p.next()
+ }
+ p.want(';')
+
+ if importpkg.Name == "" {
+ importpkg.Name = name
+ numImport[name]++
+ } else if importpkg.Name != name {
+ Yyerror("conflicting names %s and %s for package %q", importpkg.Name, name, importpkg.Path)
+ }
+ if incannedimport == 0 {
+ importpkg.Direct = true
+ }
+ importpkg.Safe = curio.importsafe
+
+ if safemode != 0 && !curio.importsafe {
+ Yyerror("cannot import unsafe package %q", importpkg.Path)
+ }
+}
+
+// go.y:import_there
+func (p *parser) import_there() {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("import_there")()
+ }
+
+ defercheckwidth()
+
+ p.hidden_import_list()
+ p.want('$')
+ // don't read past 2nd '$'
+ if p.tok != '$' {
+ p.import_error()
+ }
+
+ resumecheckwidth()
+ unimportfile()
+}
+
+// go.y:common_dcl
+func (p *parser) common_dcl() *NodeList {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("common_dcl")()
+ }
+
+ var dcl func() *NodeList
+ switch p.tok {
+ case LVAR:
+ dcl = p.vardcl
+
+ case LCONST:
+ iota_ = 0
+ dcl = p.constdcl
+
+ case LTYPE:
+ dcl = p.typedcl
+
+ default:
+ panic("unreachable")
+ }
+
+ p.next()
+ var l *NodeList
+ if p.got('(') {
+ for p.tok != EOF && p.tok != ')' {
+ l = concat(l, dcl())
+ p.osemi()
+ }
+ p.want(')')
+ } else {
+ l = dcl()
+ }
+
+ iota_ = -100000
+ lastconst = nil
+
+ return l
+}
+
+// go.y:vardcl
+func (p *parser) vardcl() *NodeList {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("vardcl")()
+ }
+
+ names := p.dcl_name_list()
+ var typ *Node
+ var exprs *NodeList
+ if p.got('=') {
+ exprs = p.expr_list()
+ } else {
+ typ = p.ntype()
+ if p.got('=') {
+ exprs = p.expr_list()
+ }
+ }
+
+ return variter(names, typ, exprs)
+}
+
+// go.y:constdcl
+func (p *parser) constdcl() *NodeList {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("constdcl")()
+ }
+
+ names := p.dcl_name_list()
+ var typ *Node
+ var exprs *NodeList
+ if p.tok != EOF && p.tok != ';' && p.tok != ')' {
+ if p.tok != '=' {
+ typ = p.ntype()
+ }
+ if p.got('=') {
+ exprs = p.expr_list()
+ }
+ }
+
+ return constiter(names, typ, exprs)
+}
+
+// go.y:typedcl
+func (p *parser) typedcl() *NodeList {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("typedcl")()
+ }
+
+ name := typedcl0(p.sym())
+
+ // handle case where type is missing
+ var typ *Node
+ if p.tok != ';' {
+ typ = p.ntype()
+ } else {
+ p.syntax_error("in type declaration")
+ p.advance(';', ')')
+ }
+
+ return list1(typedcl1(name, typ, true))
+}
+
+// go.y:simple_stmt
+// may return missing_stmt if labelOk is set
+func (p *parser) simple_stmt(labelOk, rangeOk bool) *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("simple_stmt")()
+ }
+
+ if rangeOk && p.got(LRANGE) {
+ // LRANGE expr
+ r := Nod(ORANGE, nil, p.expr())
+ r.Etype = 0 // := flag
+ return r
+ }
+
+ lhs := p.expr_list()
+
+ if count(lhs) == 1 && p.tok != '=' && p.tok != LCOLAS && p.tok != LRANGE {
+ // expr
+ lhs := lhs.N
+ switch p.tok {
+ case LASOP:
+ // expr LASOP expr
+ op := p.op
+ p.next()
+ rhs := p.expr()
+
+ stmt := Nod(OASOP, lhs, rhs)
+ stmt.Etype = EType(op) // rathole to pass opcode
+ return stmt
+
+ case LINC:
+ // expr LINC
+ p.next()
+
+ stmt := Nod(OASOP, lhs, Nodintconst(1))
+ stmt.Implicit = true
+ stmt.Etype = EType(OADD)
+ return stmt
+
+ case LDEC:
+ // expr LDEC
+ p.next()
+
+ stmt := Nod(OASOP, lhs, Nodintconst(1))
+ stmt.Implicit = true
+ stmt.Etype = EType(OSUB)
+ return stmt
+
+ case ':':
+ // labelname ':' stmt
+ if labelOk {
+ // If we have a labelname, it was parsed by operand
+ // (calling p.name()) and given an ONAME, ONONAME, or OTYPE node.
+ if lhs.Op == ONAME || lhs.Op == ONONAME || lhs.Op == OTYPE {
+ lhs = newname(lhs.Sym)
+ } else {
+ p.syntax_error("expecting semicolon or newline or }")
+ // we already progressed, no need to advance
+ }
+ lhs := Nod(OLABEL, lhs, nil)
+ lhs.Sym = dclstack // context, for goto restrictions
+ p.next() // consume ':' after making label node for correct lineno
+ return p.labeled_stmt(lhs)
+ }
+ fallthrough
+
+ default:
+ // expr
+ // These nodes do not carry line numbers.
+ // Since a bare name used as an expression is an error,
+ // introduce a wrapper node to give the correct line.
+ switch lhs.Op {
+ case ONAME, ONONAME, OTYPE, OPACK, OLITERAL:
+ lhs = Nod(OPAREN, lhs, nil)
+ lhs.Implicit = true
+ }
+ return lhs
+ }
+ }
+
+ // expr_list
+ switch p.tok {
+ case '=':
+ p.next()
+ if rangeOk && p.got(LRANGE) {
+ // expr_list '=' LRANGE expr
+ r := Nod(ORANGE, nil, p.expr())
+ r.List = lhs
+ r.Etype = 0 // := flag
+ return r
+ }
+
+ // expr_list '=' expr_list
+ rhs := p.expr_list()
+
+ if lhs.Next == nil && rhs.Next == nil {
+ // simple
+ return Nod(OAS, lhs.N, rhs.N)
+ }
+ // multiple
+ stmt := Nod(OAS2, nil, nil)
+ stmt.List = lhs
+ stmt.Rlist = rhs
+ return stmt
+
+ case LCOLAS:
+ line := lineno
+ p.next()
+
+ if rangeOk && p.got(LRANGE) {
+ // expr_list LCOLAS LRANGE expr
+ r := Nod(ORANGE, nil, p.expr())
+ r.List = lhs
+ r.Colas = true
+ colasdefn(lhs, r)
+ return r
+ }
+
+ // expr_list LCOLAS expr_list
+ rhs := p.expr_list()
+
+ if rhs.N.Op == OTYPESW {
+ ts := Nod(OTYPESW, nil, rhs.N.Right)
+ if rhs.Next != nil {
+ Yyerror("expr.(type) must be alone in list")
+ }
+ if lhs.Next != nil {
+ Yyerror("argument count mismatch: %d = %d", count(lhs), 1)
+ } else if (lhs.N.Op != ONAME && lhs.N.Op != OTYPE && lhs.N.Op != ONONAME && (lhs.N.Op != OLITERAL || lhs.N.Name == nil)) || isblank(lhs.N) {
+ Yyerror("invalid variable name %s in type switch", lhs.N)
+ } else {
+ ts.Left = dclname(lhs.N.Sym)
+ } // it's a colas, so must not re-use an oldname
+ return ts
+ }
+ return colas(lhs, rhs, int32(line))
+
+ default:
+ p.syntax_error("expecting := or = or comma")
+ p.advance(';', '}')
+ return nil
+ }
+}
+
+// may return missing_stmt
+func (p *parser) labeled_stmt(label *Node) *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("labeled_stmt")()
+ }
+
+ var ls *Node // labeled statement
+ if p.tok != '}' && p.tok != EOF {
+ ls = p.stmt()
+ if ls == missing_stmt {
+ // report error at line of ':' token
+ saved := lexlineno
+ lexlineno = prevlineno
+ p.syntax_error("missing statement after label")
+ // we are already at the end of the labeled statement - no need to advance
+ lexlineno = saved
+ return missing_stmt
+ }
+ }
+
+ label.Name.Defn = ls
+ l := list1(label)
+ if ls != nil {
+ l = list(l, ls)
+ }
+ return liststmt(l)
+}
+
+// go.y:case
+func (p *parser) case_(tswitch *Node) *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("case_")()
+ }
+
+ switch p.tok {
+ case LCASE:
+ p.next()
+ cases := p.expr_list() // expr_or_type_list
+ switch p.tok {
+ case ':':
+ // LCASE expr_or_type_list ':'
+
+ // will be converted to OCASE
+ // right will point to next case
+ // done in casebody()
+ markdcl()
+ stmt := Nod(OXCASE, nil, nil)
+ stmt.List = cases
+ if tswitch != nil {
+ if n := tswitch.Left; n != nil {
+ // type switch - declare variable
+ nn := newname(n.Sym)
+ declare(nn, dclcontext)
+ stmt.Rlist = list1(nn)
+
+ // keep track of the instances for reporting unused
+ nn.Name.Defn = tswitch
+ }
+ }
+
+ p.next() // consume ':' after declaring type switch var for correct lineno
+ return stmt
+
+ case '=':
+ // LCASE expr_or_type_list '=' expr ':'
+ p.next()
+ rhs := p.expr()
+
+ // will be converted to OCASE
+ // right will point to next case
+ // done in casebody()
+ markdcl()
+ stmt := Nod(OXCASE, nil, nil)
+ var n *Node
+ if cases.Next == nil {
+ n = Nod(OAS, cases.N, rhs)
+ } else {
+ n = Nod(OAS2, nil, nil)
+ n.List = cases
+ n.Rlist = list1(rhs)
+ }
+ stmt.List = list1(n)
+
+ p.want(':') // consume ':' after declaring select cases for correct lineno
+ return stmt
+
+ case LCOLAS:
+ // LCASE expr_or_type_list LCOLAS expr ':'
+ p.next()
+ rhs := p.expr()
+
+ // will be converted to OCASE
+ // right will point to next case
+ // done in casebody()
+ markdcl()
+ stmt := Nod(OXCASE, nil, nil)
+ stmt.List = list1(colas(cases, list1(rhs), int32(p.op)))
+
+ p.want(':') // consume ':' after declaring select cases for correct lineno
+ return stmt
+
+ default:
+ p.syntax_error("expecting := or = or : or comma")
+ p.advance(LCASE, LDEFAULT, '}')
+ return nil
+ }
+
+ case LDEFAULT:
+ // LDEFAULT ':'
+ p.next()
+
+ markdcl()
+ stmt := Nod(OXCASE, nil, nil)
+ if tswitch != nil {
+ if n := tswitch.Left; n != nil {
+ // type switch - declare variable
+ nn := newname(n.Sym)
+ declare(nn, dclcontext)
+ stmt.Rlist = list1(nn)
+
+ // keep track of the instances for reporting unused
+ nn.Name.Defn = tswitch
+ }
+ }
+
+ p.want(':') // consume ':' after declaring type switch var for correct lineno
+ return stmt
+
+ default:
+ p.syntax_error("expecting case or default or }")
+ p.advance(LCASE, LDEFAULT, '}')
+ return nil
+ }
+}
+
+// go.y:compound_stmt
+func (p *parser) compound_stmt(else_clause bool) *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("compound_stmt")()
+ }
+
+ if p.tok == '{' {
+ markdcl()
+ p.next() // consume ';' after markdcl() for correct lineno
+ } else if else_clause {
+ p.syntax_error("else must be followed by if or statement block")
+ p.advance('}')
+ return nil
+ } else {
+ panic("unreachable")
+ }
+
+ l := p.stmt_list()
+
+ var stmt *Node
+ if l == nil {
+ stmt = Nod(OEMPTY, nil, nil)
+ } else {
+ stmt = liststmt(l)
+ }
+ popdcl()
+
+ p.want('}') // TODO(gri) is this correct location w/ respect to popdcl()? (issue 13243)
+
+ return stmt
+}
+
+// go.y:caseblock
+func (p *parser) caseblock(tswitch *Node) *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("caseblock")()
+ }
+
+ stmt := p.case_(tswitch)
+
+ // If the last token read by the lexer was consumed
+ // as part of the case, clear it (parser has cleared yychar).
+ // If the last token read by the lexer was the lookahead
+ // leave it alone (parser has it cached in yychar).
+ // This is so that the stmt_list action doesn't look at
+ // the case tokens if the stmt_list is empty.
+ //yylast = yychar;
+ stmt.Xoffset = int64(block)
+
+ stmt.Nbody = p.stmt_list()
+
+ // TODO(gri) what do we need to do here? (issue 13243)
+ // // This is the only place in the language where a statement
+ // // list is not allowed to drop the final semicolon, because
+ // // it's the only place where a statement list is not followed
+ // // by a closing brace. Handle the error for pedantry.
+
+ // // Find the final token of the statement list.
+ // // yylast is lookahead; yyprev is last of stmt_list
+ // last := yyprev;
+
+ // if last > 0 && last != ';' && yychar != '}' {
+ // Yyerror("missing statement after label");
+ // }
+
+ popdcl()
+
+ return stmt
+}
+
+// go.y:caseblock_list
+func (p *parser) caseblock_list(tswitch *Node) (l *NodeList) {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("caseblock_list")()
+ }
+
+ if !p.got('{') {
+ p.syntax_error("missing { after switch clause")
+ p.advance('}')
+ return nil
+ }
+
+ for p.tok != '}' {
+ l = list(l, p.caseblock(tswitch))
+ }
+ p.want('}')
+ return
+}
+
+// go.y:loop_body
+func (p *parser) loop_body(context string) *NodeList {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("loop_body")()
+ }
+
+ if p.tok == '{' {
+ markdcl()
+ p.next() // consume ';' after markdcl() for correct lineno
+ } else {
+ p.syntax_error("missing { after " + context)
+ p.advance('}')
+ return nil
+ }
+
+ body := p.stmt_list()
+ popdcl()
+ p.want('}')
+
+ return body
+}
+
+// go.y:for_header
+func (p *parser) for_header() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("for_header")()
+ }
+
+ init, cond, post := p.header(true)
+
+ if init != nil || post != nil {
+ // init ; test ; incr
+ if post != nil && post.Colas {
+ Yyerror("cannot declare in the for-increment")
+ }
+ h := Nod(OFOR, nil, nil)
+ if init != nil {
+ h.Ninit = list1(init)
+ }
+ h.Left = cond
+ h.Right = post
+ return h
+ }
+
+ if cond != nil && cond.Op == ORANGE {
+ // range_stmt - handled by pexpr
+ return cond
+ }
+
+ // normal test
+ h := Nod(OFOR, nil, nil)
+ h.Left = cond
+ return h
+}
+
+// go.y:for_body
+func (p *parser) for_body() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("for_body")()
+ }
+
+ stmt := p.for_header()
+ body := p.loop_body("for clause")
+
+ stmt.Nbody = concat(stmt.Nbody, body)
+ return stmt
+}
+
+// go.y:for_stmt
+func (p *parser) for_stmt() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("for_stmt")()
+ }
+
+ p.want(LFOR)
+ markdcl()
+ body := p.for_body()
+ popdcl()
+
+ return body
+}
+
+func (p *parser) header(for_stmt bool) (init, cond, post *Node) {
+ if p.tok == '{' {
+ return
+ }
+
+ nest := p.nest
+ p.nest = -1
+
+ if p.tok != ';' {
+ // accept potential vardcl but complain
+ // (for test/syntax/forvar.go)
+ if for_stmt && p.tok == LVAR {
+ Yyerror("var declaration not allowed in for initializer")
+ p.next()
+ }
+ init = p.simple_stmt(false, for_stmt)
+ // If we have a range clause, we are done.
+ if for_stmt && init.Op == ORANGE {
+ cond = init
+ init = nil
+
+ p.nest = nest
+ return
+ }
+ }
+ if p.got(';') {
+ if for_stmt {
+ if p.tok != ';' {
+ cond = p.simple_stmt(false, false)
+ }
+ p.want(';')
+ if p.tok != '{' {
+ post = p.simple_stmt(false, false)
+ }
+ } else if p.tok != '{' {
+ cond = p.simple_stmt(false, false)
+ }
+ } else {
+ cond = init
+ init = nil
+ }
+
+ p.nest = nest
+
+ return
+}
+
+// go.y:if_header
+func (p *parser) if_header() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("if_header")()
+ }
+
+ init, cond, _ := p.header(false)
+ h := Nod(OIF, nil, nil)
+ h.Ninit = list1(init)
+ h.Left = cond
+ return h
+}
+
+// go.y:if_stmt
+func (p *parser) if_stmt() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("if_stmt")()
+ }
+
+ p.want(LIF)
+
+ markdcl()
+
+ stmt := p.if_header()
+ if stmt.Left == nil {
+ Yyerror("missing condition in if statement")
+ }
+
+ stmt.Nbody = p.loop_body("if clause")
+
+ l := p.elseif_list_else()
+
+ n := stmt
+ popdcl()
+ for nn := l; nn != nil; nn = nn.Next {
+ if nn.N.Op == OIF {
+ popdcl()
+ }
+ n.Rlist = list1(nn.N)
+ n = nn.N
+ }
+
+ return stmt
+}
+
+// go.y:elsif
+func (p *parser) elseif() *NodeList {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("elseif")()
+ }
+
+ // LELSE LIF already consumed
+ markdcl()
+
+ stmt := p.if_header()
+ if stmt.Left == nil {
+ Yyerror("missing condition in if statement")
+ }
+
+ stmt.Nbody = p.loop_body("if clause")
+
+ return list1(stmt)
+}
+
+// go.y:elsif_list
+// go.y:else
+func (p *parser) elseif_list_else() (l *NodeList) {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("elseif_list_else")()
+ }
+
+ for p.got(LELSE) {
+ if p.got(LIF) {
+ l = concat(l, p.elseif())
+ } else {
+ l = concat(l, p.else_())
+ break
+ }
+ }
+
+ return l
+}
+
+// go.y:else
+func (p *parser) else_() *NodeList {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("else")()
+ }
+
+ l := &NodeList{N: p.compound_stmt(true)}
+ l.End = l
+ return l
+
+}
+
+// go.y:switch_stmt
+func (p *parser) switch_stmt() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("switch_stmt")()
+ }
+
+ p.want(LSWITCH)
+ markdcl()
+
+ hdr := p.if_header()
+ hdr.Op = OSWITCH
+
+ tswitch := hdr.Left
+ if tswitch != nil && tswitch.Op != OTYPESW {
+ tswitch = nil
+ }
+
+ hdr.List = p.caseblock_list(tswitch)
+ popdcl()
+
+ return hdr
+}
+
+// go.y:select_stmt
+func (p *parser) select_stmt() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("select_stmt")()
+ }
+
+ p.want(LSELECT)
+ hdr := Nod(OSELECT, nil, nil)
+ hdr.List = p.caseblock_list(nil)
+ return hdr
+}
+
+// TODO(gri) should have lexer return this info - no need for separate lookup
+// (issue 13244)
+var prectab = map[int32]struct {
+ prec int // > 0 (0 indicates not found)
+ op Op
+}{
+ // not an expression anymore, but left in so we can give a good error
+ // message when used in expression context
+ LCOMM: {1, OSEND},
+
+ LOROR: {2, OOROR},
+
+ LANDAND: {3, OANDAND},
+
+ LEQ: {4, OEQ},
+ LNE: {4, ONE},
+ LLE: {4, OLE},
+ LGE: {4, OGE},
+ LLT: {4, OLT},
+ LGT: {4, OGT},
+
+ '+': {5, OADD},
+ '-': {5, OSUB},
+ '|': {5, OOR},
+ '^': {5, OXOR},
+
+ '*': {6, OMUL},
+ '/': {6, ODIV},
+ '%': {6, OMOD},
+ '&': {6, OAND},
+ LLSH: {6, OLSH},
+ LRSH: {6, ORSH},
+ LANDNOT: {6, OANDNOT},
+}
+
+func (p *parser) bexpr(prec int) *Node {
+ // don't trace bexpr - only leads to overly nested trace output
+
+ x := p.uexpr()
+ t := prectab[p.tok]
+ for tprec := t.prec; tprec >= prec; tprec-- {
+ for tprec == prec {
+ p.next()
+ y := p.bexpr(t.prec + 1)
+ x = Nod(t.op, x, y)
+ t = prectab[p.tok]
+ tprec = t.prec
+ }
+ }
+ return x
+}
+
+// go.y:expr
+func (p *parser) expr() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("expr")()
+ }
+
+ return p.bexpr(1)
+}
+
+// go.y:uexpr
+func (p *parser) uexpr() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("uexpr")()
+ }
+
+ var op Op
+ switch p.tok {
+ case '*':
+ op = OIND
+
+ case '&':
+ p.next()
+ x := p.uexpr()
+ if x.Op == OCOMPLIT {
+ // Special case for &T{...}: turn into (*T){...}.
+ x.Right = Nod(OIND, x.Right, nil)
+ x.Right.Implicit = true
+ } else {
+ x = Nod(OADDR, x, nil)
+ }
+ return x
+
+ case '+':
+ op = OPLUS
+
+ case '-':
+ op = OMINUS
+
+ case '!':
+ op = ONOT
+
+ case '~':
+ // TODO(gri) do this in the lexer instead (issue 13244)
+ p.next()
+ x := p.uexpr()
+ Yyerror("the bitwise complement operator is ^")
+ return Nod(OCOM, x, nil)
+
+ case '^':
+ op = OCOM
+
+ case LCOMM:
+ // receive operation (<-s2) or receive-only channel type (<-chan s3)
+ p.next()
+ if p.got(LCHAN) {
+ // <-chan T
+ t := Nod(OTCHAN, p.chan_elem(), nil)
+ t.Etype = Crecv
+ return t
+ }
+ return Nod(ORECV, p.uexpr(), nil)
+
+ default:
+ return p.pexpr(false)
+ }
+
+ // simple uexpr
+ p.next()
+ return Nod(op, p.uexpr(), nil)
+}
+
+// call-like statements that can be preceded by 'defer' and 'go'
+//
+// go.y:pseudocall
+func (p *parser) pseudocall() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("pseudocall")()
+ }
+
+ x := p.pexpr(true)
+ if x.Op != OCALL {
+ Yyerror("argument to go/defer must be function call")
+ }
+ return x
+}
+
+// go.y:pexpr (partial)
+func (p *parser) operand(keep_parens bool) *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("operand")()
+ }
+
+ switch p.tok {
+ case LLITERAL:
+ x := nodlit(p.val)
+ p.next()
+ return x
+
+ case LNAME, '@', '?':
+ return p.name()
+
+ case '(':
+ p.next()
+ p.nest++
+ x := p.expr() // expr_or_type
+ p.nest--
+ p.want(')')
+
+ // Need to know on lhs of := whether there are ( ).
+ // Don't bother with the OPAREN in other cases:
+ // it's just a waste of memory and time.
+ //
+ // But if the next token is a { , introduce OPAREN since
+ // we may have a composite literal and we need to know
+ // if there were ()'s'.
+ //
+ // TODO(gri) could simplify this if we parse complits
+ // in operand (see respective comment in pexpr).
+ //
+ // (We can probably not do this because of qualified types
+ // as in pkg.Type{}) (issue 13243).
+ if keep_parens || p.tok == '{' {
+ return Nod(OPAREN, x, nil)
+ }
+ switch x.Op {
+ case ONAME, ONONAME, OPACK, OTYPE, OLITERAL, OTYPESW:
+ return Nod(OPAREN, x, nil)
+ }
+ return x
+
+ case LFUNC:
+ t := p.ntype() // fntype
+ if p.tok == '{' {
+ // fnlitdcl
+ closurehdr(t)
+ // fnliteral
+ p.next() // consume '{'
+ p.nest++
+ body := p.stmt_list()
+ p.nest--
+ p.want('}')
+ return closurebody(body)
+ }
+ return t
+
+ case '[', LCHAN, LMAP, LSTRUCT, LINTERFACE:
+ return p.ntype() // othertype
+
+ case '{':
+ // common case: p.header is missing simple_stmt before { in if, for, switch
+ p.syntax_error("missing operand")
+ // '{' will be consumed in pexpr - no need to consume it here
+ return nil
+
+ default:
+ p.syntax_error("expecting expression")
+ p.advance()
+ return nil
+ }
+}
+
+// go.y:pexpr, pexpr_no_paren
+func (p *parser) pexpr(keep_parens bool) *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("pexpr")()
+ }
+
+ x := p.operand(keep_parens)
+
+loop:
+ for {
+ switch p.tok {
+ case '.':
+ p.next()
+ switch p.tok {
+ case LNAME, '@', '?':
+ // pexpr '.' sym
+ x = p.new_dotname(x)
+
+ case '(':
+ p.next()
+ switch p.tok {
+ default:
+ // pexpr '.' '(' expr_or_type ')'
+ t := p.expr() // expr_or_type
+ p.want(')')
+ x = Nod(ODOTTYPE, x, t)
+
+ case LTYPE:
+ // pexpr '.' '(' LTYPE ')'
+ p.next()
+ p.want(')')
+ x = Nod(OTYPESW, nil, x)
+ }
+
+ default:
+ p.syntax_error("expecting name or (")
+ p.advance(';', '}')
+ }
+
+ case '[':
+ p.next()
+ p.nest++
+ var index [3]*Node
+ if p.tok != ':' {
+ index[0] = p.expr()
+ }
+ ncol := 0
+ for ncol < len(index)-1 && p.got(':') {
+ ncol++
+ if p.tok != EOF && p.tok != ':' && p.tok != ']' {
+ index[ncol] = p.expr()
+ }
+ }
+ p.nest--
+ p.want(']')
+
+ switch ncol {
+ case 0:
+ i := index[0]
+ if i == nil {
+ Yyerror("missing index in index expression")
+ }
+ x = Nod(OINDEX, x, i)
+ case 1:
+ i := index[0]
+ j := index[1]
+ x = Nod(OSLICE, x, Nod(OKEY, i, j))
+ case 2:
+ i := index[0]
+ j := index[1]
+ k := index[2]
+ if j == nil {
+ Yyerror("middle index required in 3-index slice")
+ }
+ if k == nil {
+ Yyerror("final index required in 3-index slice")
+ }
+ x = Nod(OSLICE3, x, Nod(OKEY, i, Nod(OKEY, j, k)))
+
+ default:
+ panic("unreachable")
+ }
+
+ case '(':
+ // convtype '(' expr ocomma ')'
+ p.next()
+ p.nest++
+ args, ddd := p.arg_list()
+ p.nest--
+ p.want(')')
+
+ // call or conversion
+ x = Nod(OCALL, x, nil)
+ x.List = args
+ x.Isddd = ddd
+
+ case '{':
+ // TODO(gri) should this (complit acceptance) be in operand?
+ // accept ()'s around the complit type but complain if we have a complit
+ // (issue 13243)
+ t := x
+ for t.Op == OPAREN {
+ t = t.Left
+ }
+ // determine if '{' belongs to a complit or a compound_stmt
+ complit_ok := false
+ switch t.Op {
+ case ONAME, ONONAME, OTYPE, OPACK, OXDOT, ODOT:
+ if p.nest >= 0 {
+ // x is considered a comptype
+ complit_ok = true
+ }
+ case OTARRAY, OTSTRUCT, OTMAP:
+ // x is a comptype
+ complit_ok = true
+ }
+ if !complit_ok {
+ break loop
+ }
+ if t != x {
+ p.syntax_error("cannot parenthesize type in composite literal")
+ // already progressed, no need to advance
+ }
+ n := p.complitexpr()
+ n.Right = x
+ x = n
+
+ default:
+ break loop
+ }
+ }
+
+ return x
+}
+
+// go.y:keyval
+func (p *parser) keyval() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("keyval")()
+ }
+
+ x := p.bare_complitexpr()
+ if p.got(':') {
+ x = Nod(OKEY, x, p.bare_complitexpr())
+ }
+ return x
+}
+
+// go.y:bare_complitexpr
+func (p *parser) bare_complitexpr() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("bare_complitexpr")()
+ }
+
+ if p.tok == '{' {
+ // '{' start_complit braced_keyval_list '}'
+ return p.complitexpr()
+ }
+
+ x := p.expr()
+
+ // These nodes do not carry line numbers.
+ // Since a composite literal commonly spans several lines,
+ // the line number on errors may be misleading.
+ // Introduce a wrapper node to give the correct line.
+
+ // TODO(gri) This is causing trouble when used for keys. Need to fix complit parsing.
+ // switch x.Op {
+ // case ONAME, ONONAME, OTYPE, OPACK, OLITERAL:
+ // x = Nod(OPAREN, x, nil)
+ // x.Implicit = true
+ // }
+ // (issue 13243)
+ return x
+}
+
+// go.y:complitexpr
+func (p *parser) complitexpr() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("complitexpr")()
+ }
+
+ // make node early so we get the right line number
+ n := Nod(OCOMPLIT, nil, nil)
+
+ p.want('{')
+ p.nest++
+
+ var l *NodeList
+ for p.tok != EOF && p.tok != '}' {
+ l = list(l, p.keyval())
+ p.ocomma("composite literal")
+ }
+
+ p.nest--
+ p.want('}')
+
+ n.List = l
+ return n
+}
+
+// names and types
+// newname is used before declared
+// oldname is used after declared
+//
+// go.y:new_name:
+func (p *parser) new_name(sym *Sym) *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("new_name")()
+ }
+
+ if sym != nil {
+ return newname(sym)
+ }
+ return nil
+}
+
+// go.y:onew_name:
+func (p *parser) onew_name() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("onew_name")()
+ }
+
+ switch p.tok {
+ case LNAME, '@', '?':
+ return p.new_name(p.sym())
+ }
+ return nil
+}
+
+// go.y:sym
+func (p *parser) sym() *Sym {
+ switch p.tok {
+ case LNAME:
+ s := p.sym_
+ p.next()
+ // during imports, unqualified non-exported identifiers are from builtinpkg
+ if importpkg != nil && !exportname(s.Name) {
+ s = Pkglookup(s.Name, builtinpkg)
+ }
+ return s
+
+ case '@':
+ return p.hidden_importsym()
+
+ case '?':
+ p.next()
+ return nil
+
+ default:
+ p.syntax_error("")
+ p.advance()
+ return new(Sym)
+ }
+}
+
+func mkname(sym *Sym) *Node {
+ n := oldname(sym)
+ if n.Name != nil && n.Name.Pack != nil {
+ n.Name.Pack.Used = true
+ }
+ return n
+}
+
+// go.y:name
+func (p *parser) name() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("name")()
+ }
+
+ return mkname(p.sym())
+}
+
+// go.y:dotdotdot
+func (p *parser) dotdotdot() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("dotdotdot")()
+ }
+
+ p.want(LDDD)
+ switch p.tok {
+ case LCOMM, LFUNC, '[', LCHAN, LMAP, LSTRUCT, LINTERFACE, '*', LNAME, '@', '?', '(':
+ return Nod(ODDD, p.ntype(), nil)
+ }
+
+ Yyerror("final argument in variadic function missing type")
+ return Nod(ODDD, typenod(typ(TINTER)), nil)
+}
+
+// go.y:ntype
+func (p *parser) ntype() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("ntype")()
+ }
+
+ switch p.tok {
+ case LCOMM:
+ // recvchantype
+ p.next()
+ p.want(LCHAN)
+ t := Nod(OTCHAN, p.chan_elem(), nil)
+ t.Etype = Crecv
+ return t
+
+ case LFUNC:
+ // fntype
+ p.next()
+ params := p.param_list()
+ result := p.fnres()
+ params = checkarglist(params, 1)
+ t := Nod(OTFUNC, nil, nil)
+ t.List = params
+ t.Rlist = result
+ return t
+
+ case '[':
+ // '[' oexpr ']' ntype
+ // '[' LDDD ']' ntype
+ p.next()
+ p.nest++
+ var len *Node
+ if p.tok != ']' {
+ if p.got(LDDD) {
+ len = Nod(ODDD, nil, nil)
+ } else {
+ len = p.expr()
+ }
+ }
+ p.nest--
+ p.want(']')
+ return Nod(OTARRAY, len, p.ntype())
+
+ case LCHAN:
+ // LCHAN non_recvchantype
+ // LCHAN LCOMM ntype
+ p.next()
+ var dir EType = Cboth
+ if p.got(LCOMM) {
+ dir = Csend
+ }
+ t := Nod(OTCHAN, p.chan_elem(), nil)
+ t.Etype = dir
+ return t
+
+ case LMAP:
+ // LMAP '[' ntype ']' ntype
+ p.next()
+ p.want('[')
+ key := p.ntype()
+ p.want(']')
+ val := p.ntype()
+ return Nod(OTMAP, key, val)
+
+ case LSTRUCT:
+ return p.structtype()
+
+ case LINTERFACE:
+ return p.interfacetype()
+
+ case '*':
+ // ptrtype
+ p.next()
+ return Nod(OIND, p.ntype(), nil)
+
+ case LNAME, '@', '?':
+ return p.dotname()
+
+ case '(':
+ p.next()
+ t := p.ntype()
+ p.want(')')
+ return t
+
+ case LDDD:
+ // permit ...T but complain
+ // TODO(gri) introduced for test/fixedbugs/bug228.go - maybe adjust bug or find better solution
+ // (issue 13243)
+ p.syntax_error("")
+ p.advance()
+ return p.ntype()
+
+ default:
+ p.syntax_error("")
+ p.advance()
+ return nil
+ }
+}
+
+func (p *parser) chan_elem() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("chan_elem")()
+ }
+
+ switch p.tok {
+ case LCOMM, LFUNC,
+ '[', LCHAN, LMAP, LSTRUCT, LINTERFACE,
+ '*',
+ LNAME, '@', '?',
+ '(',
+ LDDD:
+ return p.ntype()
+
+ default:
+ p.syntax_error("missing channel element type")
+ // assume element type is simply absent - don't advance
+ return nil
+ }
+}
+
+// go.y:fnret_type
+// TODO(gri) only called from fnres - inline and remove this one
+// (issue 13243)
+func (p *parser) fnret_type() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("fnret_type")()
+ }
+
+ switch p.tok {
+ case LFUNC, // fntype
+ LCOMM, // recvchantype
+ '[', LCHAN, LMAP, LSTRUCT, LINTERFACE, // othertype
+ '*': // ptrtype
+ return p.ntype()
+
+ default:
+ return p.dotname()
+ }
+}
+
+// go.y:dotname (partial)
+func (p *parser) new_dotname(pkg *Node) *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("new_dotname")()
+ }
+
+ sel := p.sym()
+ if pkg.Op == OPACK {
+ s := restrictlookup(sel.Name, pkg.Name.Pkg)
+ pkg.Used = true
+ return oldname(s)
+ }
+ return Nod(OXDOT, pkg, newname(sel))
+
+}
+
+// go.y:dotname
+func (p *parser) dotname() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("dotname")()
+ }
+
+ name := p.name()
+ if p.got('.') {
+ return p.new_dotname(name)
+ }
+ return name
+}
+
+// go.y:structtype
+func (p *parser) structtype() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("structtype")()
+ }
+
+ p.want(LSTRUCT)
+ p.want('{')
+ var l *NodeList
+ for p.tok != EOF && p.tok != '}' {
+ l = concat(l, p.structdcl())
+ p.osemi()
+ }
+ p.want('}')
+
+ t := Nod(OTSTRUCT, nil, nil)
+ t.List = l
+ return t
+}
+
+// go.y:interfacetype
+func (p *parser) interfacetype() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("interfacetype")()
+ }
+
+ p.want(LINTERFACE)
+ p.want('{')
+ var l *NodeList
+ for p.tok != EOF && p.tok != '}' {
+ l = list(l, p.interfacedcl())
+ p.osemi()
+ }
+ p.want('}')
+
+ t := Nod(OTINTER, nil, nil)
+ t.List = l
+ return t
+}
+
+// Function stuff.
+// All in one place to show how crappy it all is.
+//
+// go.y:xfndcl
+func (p *parser) xfndcl() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("xfndcl")()
+ }
+
+ p.want(LFUNC)
+ f := p.fndcl()
+ body := p.fnbody()
+
+ if f == nil {
+ return nil
+ }
+ if noescape && body != nil {
+ Yyerror("can only use //go:noescape with external func implementations")
+ }
+
+ f.Nbody = body
+ f.Func.Endlineno = lineno
+ f.Noescape = noescape
+ f.Func.Norace = norace
+ f.Func.Nosplit = nosplit
+ f.Func.Noinline = noinline
+ f.Func.Nowritebarrier = nowritebarrier
+ f.Func.Nowritebarrierrec = nowritebarrierrec
+ f.Func.Systemstack = systemstack
+ funcbody(f)
+
+ return f
+}
+
+// go.y:fndcl
+func (p *parser) fndcl() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("fndcl")()
+ }
+
+ switch p.tok {
+ case LNAME, '@', '?':
+ // sym '(' oarg_type_list_ocomma ')' fnres
+ name := p.sym()
+ params := p.param_list()
+ result := p.fnres()
+
+ params = checkarglist(params, 1)
+
+ if name.Name == "init" {
+ name = renameinit()
+ if params != nil || result != nil {
+ Yyerror("func init must have no arguments and no return values")
+ }
+ }
+
+ if localpkg.Name == "main" && name.Name == "main" {
+ if params != nil || result != nil {
+ Yyerror("func main must have no arguments and no return values")
+ }
+ }
+
+ t := Nod(OTFUNC, nil, nil)
+ t.List = params
+ t.Rlist = result
+
+ f := Nod(ODCLFUNC, nil, nil)
+ f.Func.Nname = newfuncname(name)
+ f.Func.Nname.Name.Defn = f
+ f.Func.Nname.Name.Param.Ntype = t // TODO: check if nname already has an ntype
+ declare(f.Func.Nname, PFUNC)
+
+ funchdr(f)
+ return f
+
+ case '(':
+ // '(' oarg_type_list_ocomma ')' sym '(' oarg_type_list_ocomma ')' fnres
+ rparam := p.param_list()
+ name := p.sym()
+ params := p.param_list()
+ result := p.fnres()
+
+ rparam = checkarglist(rparam, 0)
+ params = checkarglist(params, 1)
+
+ if rparam == nil {
+ Yyerror("method has no receiver")
+ return nil
+ }
+
+ if rparam.Next != nil {
+ Yyerror("method has multiple receivers")
+ return nil
+ }
+
+ rcvr := rparam.N
+ if rcvr.Op != ODCLFIELD {
+ Yyerror("bad receiver in method")
+ return nil
+ }
+
+ t := Nod(OTFUNC, rcvr, nil)
+ t.List = params
+ t.Rlist = result
+
+ f := Nod(ODCLFUNC, nil, nil)
+ f.Func.Shortname = newfuncname(name)
+ f.Func.Nname = methodname1(f.Func.Shortname, rcvr.Right)
+ f.Func.Nname.Name.Defn = f
+ f.Func.Nname.Name.Param.Ntype = t
+ f.Func.Nname.Nointerface = nointerface
+ declare(f.Func.Nname, PFUNC)
+
+ funchdr(f)
+ return f
+
+ default:
+ p.syntax_error("expecting name or (")
+ p.advance('{', ';')
+ return nil
+ }
+}
+
+// go.y:hidden_fndcl
+func (p *parser) hidden_fndcl() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("hidden_fndcl")()
+ }
+
+ switch p.tok {
+ default:
+ // hidden_pkg_importsym '(' ohidden_funarg_list ')' ohidden_funres
+ s1 := p.hidden_pkg_importsym()
+ p.want('(')
+ s3 := p.ohidden_funarg_list()
+ p.want(')')
+ s5 := p.ohidden_funres()
+
+ s := s1
+ t := functype(nil, s3, s5)
+
+ importsym(s, ONAME)
+ if s.Def != nil && s.Def.Op == ONAME {
+ if Eqtype(t, s.Def.Type) {
+ dclcontext = PDISCARD // since we skip funchdr below
+ return nil
+ }
+ Yyerror("inconsistent definition for func %v during import\n\t%v\n\t%v", s, s.Def.Type, t)
+ }
+
+ ss := newfuncname(s)
+ ss.Type = t
+ declare(ss, PFUNC)
+
+ funchdr(ss)
+ return ss
+
+ case '(':
+ // '(' hidden_funarg_list ')' sym '(' ohidden_funarg_list ')' ohidden_funres
+ p.next()
+ s2 := p.hidden_funarg_list()
+ p.want(')')
+ s4 := p.sym()
+ p.want('(')
+ s6 := p.ohidden_funarg_list()
+ p.want(')')
+ s8 := p.ohidden_funres()
+
+ ss := methodname1(newname(s4), s2.N.Right)
+ ss.Type = functype(s2.N, s6, s8)
+
+ checkwidth(ss.Type)
+ addmethod(s4, ss.Type, false, nointerface)
+ nointerface = false
+ funchdr(ss)
+
+ // inl.C's inlnode in on a dotmeth node expects to find the inlineable body as
+ // (dotmeth's type).Nname.Inl, and dotmeth's type has been pulled
+ // out by typecheck's lookdot as this $$.ttype. So by providing
+ // this back link here we avoid special casing there.
+ ss.Type.Nname = ss
+ return ss
+ }
+}
+
+// go.y:fnbody
+func (p *parser) fnbody() *NodeList {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("fnbody")()
+ }
+
+ if p.got('{') {
+ body := p.stmt_list()
+ p.want('}')
+ if body == nil {
+ body = list1(Nod(OEMPTY, nil, nil))
+ }
+ return body
+ }
+
+ return nil
+}
+
+// go.y:fnres
+func (p *parser) fnres() *NodeList {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("fnres")()
+ }
+
+ switch p.tok {
+ default:
+ return nil
+
+ case LCOMM, LFUNC, '[', LCHAN, LMAP, LSTRUCT, LINTERFACE, '*', LNAME, '@', '?':
+ result := p.fnret_type()
+ return list1(Nod(ODCLFIELD, nil, result))
+
+ case '(':
+ result := p.param_list()
+ return checkarglist(result, 0)
+ }
+}
+
+// go.y:xdcl_list
+func (p *parser) xdcl_list() (l *NodeList) {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("xdcl_list")()
+ }
+
+loop:
+ for p.tok != EOF {
+ switch p.tok {
+ case LVAR, LCONST, LTYPE:
+ l = concat(l, p.common_dcl())
+
+ case LFUNC:
+ l = list(l, p.xfndcl())
+
+ default:
+ if p.tok == '{' && l != nil && l.End.N.Op == ODCLFUNC && l.End.N.Nbody == nil {
+ // opening { of function declaration on next line
+ p.syntax_error("unexpected semicolon or newline before {")
+ } else {
+ p.syntax_error("non-declaration statement outside function body")
+ }
+ p.advance(LVAR, LCONST, LTYPE, LFUNC)
+ goto loop
+ }
+
+ if nsyntaxerrors == 0 {
+ testdclstack()
+ }
+
+ noescape = false
+ noinline = false
+ nointerface = false
+ norace = false
+ nosplit = false
+ nowritebarrier = false
+ nowritebarrierrec = false
+ systemstack = false
+
+ // Consume ';' AFTER resetting the above flags since
+ // it may read the subsequent comment line which may
+ // set the flags for the next function declaration.
+ if p.tok != EOF && !p.got(';') {
+ p.syntax_error("after top level declaration")
+ p.advance(LVAR, LCONST, LTYPE, LFUNC)
+ goto loop
+ }
+ }
+ return
+}
+
+// go.y:structdcl
+func (p *parser) structdcl() *NodeList {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("structdcl")()
+ }
+
+ var sym *Sym
+ switch p.tok {
+ case LNAME:
+ sym = p.sym_
+ p.next()
+ if sym == nil {
+ panic("unreachable") // we must have a sym for LNAME
+ }
+ if p.tok == '.' || p.tok == LLITERAL || p.tok == ';' || p.tok == '}' {
+ // embed oliteral
+ field := p.embed(sym)
+ tag := p.oliteral()
+
+ field.SetVal(tag)
+ return list1(field)
+ }
+
+ // LNAME belongs to first *Sym of new_name_list
+ //
+ // during imports, unqualified non-exported identifiers are from builtinpkg
+ if importpkg != nil && !exportname(sym.Name) {
+ sym = Pkglookup(sym.Name, builtinpkg)
+ if sym == nil {
+ p.import_error()
+ }
+ }
+ fallthrough
+
+ case '@', '?':
+ // new_name_list ntype oliteral
+ fields := p.new_name_list(sym)
+ typ := p.ntype()
+ tag := p.oliteral()
+
+ if l := fields; l == nil || l.N.Sym.Name == "?" {
+ // ? symbol, during import (list1(nil) == nil)
+ n := typ
+ if n.Op == OIND {
+ n = n.Left
+ }
+ n = embedded(n.Sym, importpkg)
+ n.Right = typ
+ n.SetVal(tag)
+ return list1(n)
+ }
+
+ for l := fields; l != nil; l = l.Next {
+ l.N = Nod(ODCLFIELD, l.N, typ)
+ l.N.SetVal(tag)
+ }
+ return fields
+
+ case '(':
+ p.next()
+ if p.got('*') {
+ // '(' '*' embed ')' oliteral
+ field := p.embed(nil)
+ p.want(')')
+ tag := p.oliteral()
+
+ field.Right = Nod(OIND, field.Right, nil)
+ field.SetVal(tag)
+ Yyerror("cannot parenthesize embedded type")
+ return list1(field)
+
+ } else {
+ // '(' embed ')' oliteral
+ field := p.embed(nil)
+ p.want(')')
+ tag := p.oliteral()
+
+ field.SetVal(tag)
+ Yyerror("cannot parenthesize embedded type")
+ return list1(field)
+ }
+
+ case '*':
+ p.next()
+ if p.got('(') {
+ // '*' '(' embed ')' oliteral
+ field := p.embed(nil)
+ p.want(')')
+ tag := p.oliteral()
+
+ field.Right = Nod(OIND, field.Right, nil)
+ field.SetVal(tag)
+ Yyerror("cannot parenthesize embedded type")
+ return list1(field)
+
+ } else {
+ // '*' embed oliteral
+ field := p.embed(nil)
+ tag := p.oliteral()
+
+ field.Right = Nod(OIND, field.Right, nil)
+ field.SetVal(tag)
+ return list1(field)
+ }
+
+ default:
+ p.syntax_error("expecting field name or embedded type")
+ p.advance(';', '}')
+ return nil
+ }
+}
+
+// go.y:oliteral
+func (p *parser) oliteral() (v Val) {
+ if p.tok == LLITERAL {
+ v = p.val
+ p.next()
+ }
+ return
+}
+
+// go.y:packname
+func (p *parser) packname(name *Sym) *Sym {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("embed")()
+ }
+
+ if name != nil {
+ // LNAME was already consumed and is coming in as name
+ } else if p.tok == LNAME {
+ name = p.sym_
+ p.next()
+ } else {
+ p.syntax_error("expecting name")
+ p.advance('.', ';', '}')
+ name = new(Sym)
+ }
+
+ if p.got('.') {
+ // LNAME '.' sym
+ s := p.sym()
+
+ var pkg *Pkg
+ if name.Def == nil || name.Def.Op != OPACK {
+ Yyerror("%v is not a package", name)
+ pkg = localpkg
+ } else {
+ name.Def.Used = true
+ pkg = name.Def.Name.Pkg
+ }
+ return restrictlookup(s.Name, pkg)
+ }
+
+ // LNAME
+ if n := oldname(name); n.Name != nil && n.Name.Pack != nil {
+ n.Name.Pack.Used = true
+ }
+ return name
+}
+
+// go.y:embed
+func (p *parser) embed(sym *Sym) *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("embed")()
+ }
+
+ pkgname := p.packname(sym)
+ return embedded(pkgname, localpkg)
+}
+
+// go.y: interfacedcl
+func (p *parser) interfacedcl() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("interfacedcl")()
+ }
+
+ switch p.tok {
+ case LNAME:
+ sym := p.sym_
+ p.next()
+
+ // accept potential name list but complain
+ hasNameList := false
+ for p.got(',') {
+ p.sym()
+ hasNameList = true
+ }
+ if hasNameList {
+ p.syntax_error("name list not allowed in interface type")
+ // already progressed, no need to advance
+ }
+
+ if p.tok != '(' {
+ // packname
+ pname := p.packname(sym)
+ return Nod(ODCLFIELD, nil, oldname(pname))
+ }
+
+ // newname indcl
+ mname := newname(sym)
+ sig := p.indcl()
+
+ meth := Nod(ODCLFIELD, mname, sig)
+ ifacedcl(meth)
+ return meth
+
+ case '(':
+ p.next()
+ pname := p.packname(nil)
+ p.want(')')
+ n := Nod(ODCLFIELD, nil, oldname(pname))
+ Yyerror("cannot parenthesize embedded type")
+ return n
+
+ default:
+ p.syntax_error("")
+ p.advance(';', '}')
+ return nil
+ }
+}
+
+// go.y:indcl
+func (p *parser) indcl() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("indcl")()
+ }
+
+ params := p.param_list()
+ result := p.fnres()
+
+ // without func keyword
+ params = checkarglist(params, 1)
+ t := Nod(OTFUNC, fakethis(), nil)
+ t.List = params
+ t.Rlist = result
+
+ return t
+}
+
+// go.y:arg_type
+func (p *parser) arg_type() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("arg_type")()
+ }
+
+ switch p.tok {
+ case LNAME, '@', '?':
+ name := p.sym()
+ switch p.tok {
+ case LCOMM, LFUNC, '[', LCHAN, LMAP, LSTRUCT, LINTERFACE, '*', LNAME, '@', '?', '(':
+ // sym name_or_type
+ typ := p.ntype()
+ nn := Nod(ONONAME, nil, nil)
+ nn.Sym = name
+ return Nod(OKEY, nn, typ)
+
+ case LDDD:
+ // sym dotdotdot
+ typ := p.dotdotdot()
+ nn := Nod(ONONAME, nil, nil)
+ nn.Sym = name
+ return Nod(OKEY, nn, typ)
+
+ default:
+ // name_or_type
+ name := mkname(name)
+ // from dotname
+ if p.got('.') {
+ return p.new_dotname(name)
+ }
+ return name
+ }
+
+ case LDDD:
+ // dotdotdot
+ return p.dotdotdot()
+
+ case LCOMM, LFUNC, '[', LCHAN, LMAP, LSTRUCT, LINTERFACE, '*', '(':
+ // name_or_type
+ return p.ntype()
+
+ default:
+ p.syntax_error("expecting )")
+ p.advance(',', ')')
+ return nil
+ }
+}
+
+// go.y:oarg_type_list_ocomma + surrounding ()'s
+func (p *parser) param_list() (l *NodeList) {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("param_list")()
+ }
+
+ p.want('(')
+ for p.tok != EOF && p.tok != ')' {
+ l = list(l, p.arg_type())
+ p.ocomma("parameter list")
+ }
+ p.want(')')
+ return
+}
+
+var missing_stmt = Nod(OXXX, nil, nil)
+
+// go.y:stmt
+// maty return missing_stmt
+func (p *parser) stmt() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("stmt")()
+ }
+
+ switch p.tok {
+ case '{':
+ return p.compound_stmt(false)
+
+ case LVAR, LCONST, LTYPE:
+ return liststmt(p.common_dcl())
+
+ case LNAME, '@', '?', LLITERAL, LFUNC, '(', // operands
+ '[', LSTRUCT, LMAP, LCHAN, LINTERFACE, // composite types
+ '+', '-', '*', '&', '^', '~', LCOMM, '!': // unary operators
+ return p.simple_stmt(true, false)
+
+ case LFOR:
+ return p.for_stmt()
+
+ case LSWITCH:
+ return p.switch_stmt()
+
+ case LSELECT:
+ return p.select_stmt()
+
+ case LIF:
+ return p.if_stmt()
+
+ case LFALL:
+ p.next()
+ // will be converted to OFALL
+ stmt := Nod(OXFALL, nil, nil)
+ stmt.Xoffset = int64(block)
+ return stmt
+
+ case LBREAK:
+ p.next()
+ return Nod(OBREAK, p.onew_name(), nil)
+
+ case LCONTINUE:
+ p.next()
+ return Nod(OCONTINUE, p.onew_name(), nil)
+
+ case LGO:
+ p.next()
+ return Nod(OPROC, p.pseudocall(), nil)
+
+ case LDEFER:
+ p.next()
+ return Nod(ODEFER, p.pseudocall(), nil)
+
+ case LGOTO:
+ p.next()
+ stmt := Nod(OGOTO, p.new_name(p.sym()), nil)
+ stmt.Sym = dclstack // context, for goto restrictions
+ return stmt
+
+ case LRETURN:
+ p.next()
+ var results *NodeList
+ if p.tok != ';' && p.tok != '}' {
+ results = p.expr_list()
+ }
+
+ stmt := Nod(ORETURN, nil, nil)
+ stmt.List = results
+ if stmt.List == nil && Curfn != nil {
+ for l := Curfn.Func.Dcl; l != nil; l = l.Next {
+ if l.N.Class == PPARAM {
+ continue
+ }
+ if l.N.Class != PPARAMOUT {
+ break
+ }
+ if l.N.Sym.Def != l.N {
+ Yyerror("%s is shadowed during return", l.N.Sym.Name)
+ }
+ }
+ }
+
+ return stmt
+
+ case ';':
+ return nil
+
+ default:
+ return missing_stmt
+ }
+}
+
+// go.y:stmt_list
+func (p *parser) stmt_list() (l *NodeList) {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("stmt_list")()
+ }
+
+ for p.tok != EOF && p.tok != '}' && p.tok != LCASE && p.tok != LDEFAULT {
+ s := p.stmt()
+ if s == missing_stmt {
+ break
+ }
+ l = list(l, s)
+ // customized version of osemi:
+ // ';' is optional before a closing ')' or '}'
+ if p.tok == ')' || p.tok == '}' {
+ continue
+ }
+ if !p.got(';') {
+ p.syntax_error("at end of statement")
+ p.advance(';', '}')
+ }
+ }
+ return
+}
+
+// go.y:new_name_list
+// if first != nil we have the first symbol already
+func (p *parser) new_name_list(first *Sym) *NodeList {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("new_name_list")()
+ }
+
+ if first == nil {
+ first = p.sym() // may still be nil
+ }
+ l := list1(p.new_name(first))
+ for p.got(',') {
+ l = list(l, p.new_name(p.sym()))
+ }
+ return l
+}
+
+// go.y:dcl_name_list
+func (p *parser) dcl_name_list() *NodeList {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("dcl_name_list")()
+ }
+
+ l := list1(dclname(p.sym()))
+ for p.got(',') {
+ l = list(l, dclname(p.sym()))
+ }
+ return l
+}
+
+// go.y:expr_list
+func (p *parser) expr_list() *NodeList {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("expr_list")()
+ }
+
+ l := list1(p.expr())
+ for p.got(',') {
+ l = list(l, p.expr())
+ }
+ return l
+}
+
+// go.y:expr_or_type_list
+func (p *parser) arg_list() (l *NodeList, ddd bool) {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("arg_list")()
+ }
+
+ // TODO(gri) make this more tolerant in the presence of LDDD
+ // that is not at the end (issue 13243).
+
+ for p.tok != EOF && p.tok != ')' && !ddd {
+ l = list(l, p.expr()) // expr_or_type
+ ddd = p.got(LDDD)
+ p.ocomma("argument list")
+ }
+
+ return
+}
+
+// go.y:osemi
+func (p *parser) osemi() {
+ // ';' is optional before a closing ')' or '}'
+ if p.tok == ')' || p.tok == '}' {
+ return
+ }
+ p.want(';')
+}
+
+// go.y:ocomma
+func (p *parser) ocomma(context string) {
+ switch p.tok {
+ case ')', '}':
+ // ',' is optional before a closing ')' or '}'
+ return
+ case ';':
+ p.syntax_error("need trailing comma before newline in " + context)
+ p.next() // interpret ';' as comma
+ return
+ }
+ p.want(',')
+}
+
+// ----------------------------------------------------------------------------
+// Importing packages
+
+func (p *parser) import_error() {
+ p.syntax_error("in export data of imported package")
+ p.next()
+}
+
+// The methods below reflect a 1:1 translation of the corresponding go.y yacc
+// productions They could be simplified significantly and also use better
+// variable names. However, we will be able to delete them once we enable the
+// new export format by default, so it's not worth the effort.
+
+// go.y:hidden_importsym:
+func (p *parser) hidden_importsym() *Sym {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("hidden_importsym")()
+ }
+
+ p.want('@')
+ var s2 Val
+ if p.tok == LLITERAL {
+ s2 = p.val
+ p.next()
+ } else {
+ p.import_error()
+ }
+ p.want('.')
+
+ switch p.tok {
+ case LNAME:
+ s4 := p.sym_
+ p.next()
+
+ var p *Pkg
+
+ if s2.U.(string) == "" {
+ p = importpkg
+ } else {
+ if isbadimport(s2.U.(string)) {
+ errorexit()
+ }
+ p = mkpkg(s2.U.(string))
+ }
+ return Pkglookup(s4.Name, p)
+
+ case '?':
+ p.next()
+
+ var p *Pkg
+
+ if s2.U.(string) == "" {
+ p = importpkg
+ } else {
+ if isbadimport(s2.U.(string)) {
+ errorexit()
+ }
+ p = mkpkg(s2.U.(string))
+ }
+ return Pkglookup("?", p)
+
+ default:
+ p.import_error()
+ return nil
+ }
+}
+
+// go.y:ohidden_funarg_list
+func (p *parser) ohidden_funarg_list() *NodeList {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("ohidden_funarg_list")()
+ }
+
+ var ss *NodeList
+ if p.tok != ')' {
+ ss = p.hidden_funarg_list()
+ }
+ return ss
+}
+
+// go.y:ohidden_structdcl_list
+func (p *parser) ohidden_structdcl_list() *NodeList {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("ohidden_structdcl_list")()
+ }
+
+ var ss *NodeList
+ if p.tok != '}' {
+ ss = p.hidden_structdcl_list()
+ }
+ return ss
+}
+
+// go.y:ohidden_interfacedcl_list
+func (p *parser) ohidden_interfacedcl_list() *NodeList {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("ohidden_interfacedcl_list")()
+ }
+
+ var ss *NodeList
+ if p.tok != '}' {
+ ss = p.hidden_interfacedcl_list()
+ }
+ return ss
+}
+
+// import syntax from package header
+//
+// go.y:hidden_import
+func (p *parser) hidden_import() {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("hidden_import")()
+ }
+
+ switch p.tok {
+ case LIMPORT:
+ // LIMPORT LNAME LLITERAL ';'
+ p.next()
+ var s2 *Sym
+ if p.tok == LNAME {
+ s2 = p.sym_
+ p.next()
+ } else {
+ p.import_error()
+ }
+ var s3 Val
+ if p.tok == LLITERAL {
+ s3 = p.val
+ p.next()
+ } else {
+ p.import_error()
+ }
+ p.want(';')
+
+ importimport(s2, s3.U.(string))
+
+ case LVAR:
+ // LVAR hidden_pkg_importsym hidden_type ';'
+ p.next()
+ s2 := p.hidden_pkg_importsym()
+ s3 := p.hidden_type()
+ p.want(';')
+
+ importvar(s2, s3)
+
+ case LCONST:
+ // LCONST hidden_pkg_importsym '=' hidden_constant ';'
+ // LCONST hidden_pkg_importsym hidden_type '=' hidden_constant ';'
+ p.next()
+ s2 := p.hidden_pkg_importsym()
+ var s3 *Type = Types[TIDEAL]
+ if p.tok != '=' {
+ s3 = p.hidden_type()
+ }
+ p.want('=')
+ s4 := p.hidden_constant()
+ p.want(';')
+
+ importconst(s2, s3, s4)
+
+ case LTYPE:
+ // LTYPE hidden_pkgtype hidden_type ';'
+ p.next()
+ s2 := p.hidden_pkgtype()
+ s3 := p.hidden_type()
+ p.want(';')
+
+ importtype(s2, s3)
+
+ case LFUNC:
+ // LFUNC hidden_fndcl fnbody ';'
+ p.next()
+ s2 := p.hidden_fndcl()
+ s3 := p.fnbody()
+ p.want(';')
+
+ if s2 == nil {
+ dclcontext = PEXTERN // since we skip the funcbody below
+ return
+ }
+
+ s2.Func.Inl = s3
+
+ funcbody(s2)
+ importlist = append(importlist, s2)
+
+ if Debug['E'] > 0 {
+ fmt.Printf("import [%q] func %v \n", importpkg.Path, s2)
+ if Debug['m'] > 2 && s2.Func.Inl != nil {
+ fmt.Printf("inl body:%v\n", s2.Func.Inl)
+ }
+ }
+
+ default:
+ p.import_error()
+ }
+}
+
+// go.y:hidden_pkg_importsym
+func (p *parser) hidden_pkg_importsym() *Sym {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("hidden_pkg_importsym")()
+ }
+
+ s1 := p.hidden_importsym()
+
+ ss := s1
+ structpkg = ss.Pkg
+
+ return ss
+}
+
+// go.y:hidden_pkgtype
+func (p *parser) hidden_pkgtype() *Type {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("hidden_pkgtype")()
+ }
+
+ s1 := p.hidden_pkg_importsym()
+
+ ss := pkgtype(s1)
+ importsym(s1, OTYPE)
+
+ return ss
+}
+
+// ----------------------------------------------------------------------------
+// Importing types
+
+// go.y:hidden_type
+func (p *parser) hidden_type() *Type {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("hidden_type")()
+ }
+
+ switch p.tok {
+ default:
+ return p.hidden_type_misc()
+ case LCOMM:
+ return p.hidden_type_recv_chan()
+ case LFUNC:
+ return p.hidden_type_func()
+ }
+}
+
+// go.y:hidden_type_non_recv_chan
+func (p *parser) hidden_type_non_recv_chan() *Type {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("hidden_type_non_recv_chan")()
+ }
+
+ switch p.tok {
+ default:
+ return p.hidden_type_misc()
+ case LFUNC:
+ return p.hidden_type_func()
+ }
+}
+
+// go.y:hidden_type_misc
+func (p *parser) hidden_type_misc() *Type {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("hidden_type_misc")()
+ }
+
+ switch p.tok {
+ case '@':
+ // hidden_importsym
+ s1 := p.hidden_importsym()
+ return pkgtype(s1)
+
+ case LNAME:
+ // LNAME
+ s1 := p.sym_
+ p.next()
+
+ // predefined name like uint8
+ s1 = Pkglookup(s1.Name, builtinpkg)
+ if s1.Def == nil || s1.Def.Op != OTYPE {
+ Yyerror("%s is not a type", s1.Name)
+ return nil
+ } else {
+ return s1.Def.Type
+ }
+
+ case '[':
+ // '[' ']' hidden_type
+ // '[' LLITERAL ']' hidden_type
+ p.next()
+ var s2 *Node
+ if p.tok == LLITERAL {
+ s2 = nodlit(p.val)
+ p.next()
+ }
+ p.want(']')
+ s4 := p.hidden_type()
+
+ return aindex(s2, s4)
+
+ case LMAP:
+ // LMAP '[' hidden_type ']' hidden_type
+ p.next()
+ p.want('[')
+ s3 := p.hidden_type()
+ p.want(']')
+ s5 := p.hidden_type()
+
+ return maptype(s3, s5)
+
+ case LSTRUCT:
+ // LSTRUCT '{' ohidden_structdcl_list '}'
+ p.next()
+ p.want('{')
+ s3 := p.ohidden_structdcl_list()
+ p.want('}')
+
+ return tostruct(s3)
+
+ case LINTERFACE:
+ // LINTERFACE '{' ohidden_interfacedcl_list '}'
+ p.next()
+ p.want('{')
+ s3 := p.ohidden_interfacedcl_list()
+ p.want('}')
+
+ return tointerface(s3)
+
+ case '*':
+ // '*' hidden_type
+ p.next()
+ s2 := p.hidden_type()
+ return Ptrto(s2)
+
+ case LCHAN:
+ p.next()
+ switch p.tok {
+ default:
+ // LCHAN hidden_type_non_recv_chan
+ s2 := p.hidden_type_non_recv_chan()
+ ss := typ(TCHAN)
+ ss.Type = s2
+ ss.Chan = Cboth
+ return ss
+
+ case '(':
+ // LCHAN '(' hidden_type_recv_chan ')'
+ p.next()
+ s3 := p.hidden_type_recv_chan()
+ p.want(')')
+ ss := typ(TCHAN)
+ ss.Type = s3
+ ss.Chan = Cboth
+ return ss
+
+ case LCOMM:
+ // LCHAN hidden_type
+ p.next()
+ s3 := p.hidden_type()
+ ss := typ(TCHAN)
+ ss.Type = s3
+ ss.Chan = Csend
+ return ss
+ }
+
+ default:
+ p.import_error()
+ return nil
+ }
+}
+
+// go.y:hidden_type_recv_chan
+func (p *parser) hidden_type_recv_chan() *Type {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("hidden_type_recv_chan")()
+ }
+
+ p.want(LCOMM)
+ p.want(LCHAN)
+ s3 := p.hidden_type()
+
+ ss := typ(TCHAN)
+ ss.Type = s3
+ ss.Chan = Crecv
+ return ss
+}
+
+// go.y:hidden_type_func
+func (p *parser) hidden_type_func() *Type {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("hidden_type_func")()
+ }
+
+ p.want(LFUNC)
+ p.want('(')
+ s3 := p.ohidden_funarg_list()
+ p.want(')')
+ s5 := p.ohidden_funres()
+
+ return functype(nil, s3, s5)
+}
+
+// go.y:hidden_funarg
+func (p *parser) hidden_funarg() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("hidden_funarg")()
+ }
+
+ s1 := p.sym()
+ switch p.tok {
+ default:
+ s2 := p.hidden_type()
+ s3 := p.oliteral()
+
+ ss := Nod(ODCLFIELD, nil, typenod(s2))
+ if s1 != nil {
+ ss.Left = newname(s1)
+ }
+ ss.SetVal(s3)
+ return ss
+
+ case LDDD:
+ p.next()
+ s3 := p.hidden_type()
+ s4 := p.oliteral()
+
+ var t *Type
+
+ t = typ(TARRAY)
+ t.Bound = -1
+ t.Type = s3
+
+ ss := Nod(ODCLFIELD, nil, typenod(t))
+ if s1 != nil {
+ ss.Left = newname(s1)
+ }
+ ss.Isddd = true
+ ss.SetVal(s4)
+
+ return ss
+ }
+}
+
+// go.y:hidden_structdcl
+func (p *parser) hidden_structdcl() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("hidden_structdcl")()
+ }
+
+ s1 := p.sym()
+ s2 := p.hidden_type()
+ s3 := p.oliteral()
+
+ var s *Sym
+ var pkg *Pkg
+
+ var ss *Node
+ if s1 != nil && s1.Name != "?" {
+ ss = Nod(ODCLFIELD, newname(s1), typenod(s2))
+ ss.SetVal(s3)
+ } else {
+ s = s2.Sym
+ if s == nil && Isptr[s2.Etype] {
+ s = s2.Type.Sym
+ }
+ pkg = importpkg
+ if s1 != nil {
+ pkg = s1.Pkg
+ }
+ ss = embedded(s, pkg)
+ ss.Right = typenod(s2)
+ ss.SetVal(s3)
+ }
+
+ return ss
+}
+
+// go.y:hidden_interfacedcl
+func (p *parser) hidden_interfacedcl() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("hidden_interfacedcl")()
+ }
+
+ // TODO(gri) possible conflict here: both cases may start with '@' per grammar
+ // (issue 13245).
+
+ switch p.tok {
+ case LNAME, '@', '?':
+ s1 := p.sym()
+ p.want('(')
+ s3 := p.ohidden_funarg_list()
+ p.want(')')
+ s5 := p.ohidden_funres()
+
+ return Nod(ODCLFIELD, newname(s1), typenod(functype(fakethis(), s3, s5)))
+
+ default:
+ s1 := p.hidden_type()
+
+ return Nod(ODCLFIELD, nil, typenod(s1))
+ }
+}
+
+// go.y:ohidden_funres
+func (p *parser) ohidden_funres() *NodeList {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("ohidden_funres")()
+ }
+
+ switch p.tok {
+ default:
+ return nil
+
+ case '(', '@', LNAME, '[', LMAP, LSTRUCT, LINTERFACE, '*', LCHAN, LCOMM, LFUNC:
+ return p.hidden_funres()
+ }
+}
+
+// go.y:hidden_funres
+func (p *parser) hidden_funres() *NodeList {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("hidden_funres")()
+ }
+
+ switch p.tok {
+ case '(':
+ p.next()
+ s2 := p.ohidden_funarg_list()
+ p.want(')')
+ return s2
+
+ default:
+ s1 := p.hidden_type()
+ return list1(Nod(ODCLFIELD, nil, typenod(s1)))
+ }
+}
+
+// ----------------------------------------------------------------------------
+// Importing constants
+
+// go.y:hidden_literal
+func (p *parser) hidden_literal() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("hidden_literal")()
+ }
+
+ switch p.tok {
+ case LLITERAL:
+ ss := nodlit(p.val)
+ p.next()
+ return ss
+
+ case '-':
+ p.next()
+ if p.tok == LLITERAL {
+ ss := nodlit(p.val)
+ p.next()
+ switch ss.Val().Ctype() {
+ case CTINT, CTRUNE:
+ mpnegfix(ss.Val().U.(*Mpint))
+ break
+ case CTFLT:
+ mpnegflt(ss.Val().U.(*Mpflt))
+ break
+ case CTCPLX:
+ mpnegflt(&ss.Val().U.(*Mpcplx).Real)
+ mpnegflt(&ss.Val().U.(*Mpcplx).Imag)
+ break
+ default:
+ Yyerror("bad negated constant")
+ }
+ return ss
+ } else {
+ p.import_error()
+ return nil
+ }
+
+ case LNAME, '@', '?':
+ s1 := p.sym()
+ ss := oldname(Pkglookup(s1.Name, builtinpkg))
+ if ss.Op != OLITERAL {
+ Yyerror("bad constant %v", ss.Sym)
+ }
+ return ss
+
+ default:
+ p.import_error()
+ return nil
+ }
+}
+
+// go.y:hidden_constant
+func (p *parser) hidden_constant() *Node {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("hidden_constant")()
+ }
+
+ switch p.tok {
+ default:
+ return p.hidden_literal()
+ case '(':
+ p.next()
+ s2 := p.hidden_literal()
+ p.want('+')
+ s4 := p.hidden_literal()
+ p.want(')')
+
+ if s2.Val().Ctype() == CTRUNE && s4.Val().Ctype() == CTINT {
+ ss := s2
+ mpaddfixfix(s2.Val().U.(*Mpint), s4.Val().U.(*Mpint), 0)
+ return ss
+ }
+ s4.Val().U.(*Mpcplx).Real = s4.Val().U.(*Mpcplx).Imag
+ Mpmovecflt(&s4.Val().U.(*Mpcplx).Imag, 0.0)
+ return nodcplxlit(s2.Val(), s4.Val())
+ }
+}
+
+// go.y:hidden_import_list
+func (p *parser) hidden_import_list() {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("hidden_import_list")()
+ }
+
+ for p.tok != '$' {
+ p.hidden_import()
+ }
+}
+
+// go.y:hidden_funarg_list
+func (p *parser) hidden_funarg_list() *NodeList {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("hidden_funarg_list")()
+ }
+
+ s1 := p.hidden_funarg()
+ ss := list1(s1)
+ for p.got(',') {
+ s3 := p.hidden_funarg()
+ ss = list(ss, s3)
+ }
+ return ss
+}
+
+// go.y:hidden_structdcl_list
+func (p *parser) hidden_structdcl_list() *NodeList {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("hidden_structdcl_list")()
+ }
+
+ s1 := p.hidden_structdcl()
+ ss := list1(s1)
+ for p.got(';') {
+ s3 := p.hidden_structdcl()
+ ss = list(ss, s3)
+ }
+ return ss
+}
+
+// go.y:hidden_interfacedcl_list
+func (p *parser) hidden_interfacedcl_list() *NodeList {
+ if trace && Debug['x'] != 0 {
+ defer p.trace("hidden_interfacedcl_list")()
+ }
+
+ s1 := p.hidden_interfacedcl()
+ ss := list1(s1)
+ for p.got(';') {
+ s3 := p.hidden_interfacedcl()
+ ss = list(ss, s3)
+ }
+ return ss
+}
}
func emitptrargsmap() {
+ if Curfn.Func.Nname.Sym.Name == "_" {
+ return
+ }
sym := Lookup(fmt.Sprintf("%s.args_stackmap", Curfn.Func.Nname.Sym.Name))
nptr := int(Curfn.Type.Argwid / int64(Widthptr))
if haspointers(n.Type) {
stkptrsize = Stksize
}
- if Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9' {
+ if Thearch.Thechar == '0' || Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9' {
Stksize = Rnd(Stksize, int64(Widthptr))
}
if Stksize >= 1<<31 {
Fatalf("bad checknil")
}
- if ((Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9') && n.Op != OREGISTER) || !n.Addable || n.Op == OLITERAL {
+ if ((Thearch.Thechar == '0' || Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9') && n.Op != OREGISTER) || !n.Addable || n.Op == OLITERAL {
var reg Node
Regalloc(®, Types[Tptr], n)
Cgen(n, ®)
if nerrors != 0 {
goto ret
}
- if flag_race != 0 {
- racewalk(Curfn)
+ if instrumenting {
+ instrument(Curfn)
}
if nerrors != 0 {
goto ret
return
}
var a *Node
- var class uint8
+ var class Class
for l := fn.Func.Dcl; l != nil; l = l.Next {
a = l.N
class = a.Class &^ PHEAP
// the PCDATA must begin one instruction early too.
// The instruction before a call to deferreturn is always a
// no-op, to keep PC-specific data unambiguous.
- splicebefore(lv, bb, newpcdataprog(p.Opt.(*obj.Prog), pos), p.Opt.(*obj.Prog))
+ prev := p.Opt.(*obj.Prog)
+ if Ctxt.Arch.Thechar == '9' {
+ // On ppc64 there is an additional instruction
+ // (another no-op or reload of toc pointer) before
+ // the call.
+ prev = prev.Opt.(*obj.Prog)
+ }
+ splicebefore(lv, bb, newpcdataprog(prev, pos), prev)
} else {
splicebefore(lv, bb, newpcdataprog(p, pos), p)
}
// longer and more difficult to follow during debugging.
// Remove them.
-/* what instruction does a JMP to p eventually land on? */
+// what instruction does a JMP to p eventually land on?
func chasejmp(p *obj.Prog, jmploop *int) *obj.Prog {
n := 0
for p != nil && p.As == obj.AJMP && p.To.Type == obj.TYPE_BRANCH {
return p
}
-/*
- * reuse reg pointer for mark/sweep state.
- * leave reg==nil at end because alive==nil.
- */
+// reuse reg pointer for mark/sweep state.
+// leave reg==nil at end because alive==nil.
var alive interface{} = nil
var dead interface{} = 1
-/* mark all code reachable from firstp as alive */
+// mark all code reachable from firstp as alive
func mark(firstp *obj.Prog) {
for p := firstp; p != nil; p = p.Link {
if p.Opt != dead {
}
}
-/*
- * find looping structure
- *
- * 1) find reverse postordering
- * 2) find approximate dominators,
- * the actual dominators if the flow graph is reducible
- * otherwise, dominators plus some other non-dominators.
- * See Matthew S. Hecht and Jeffrey D. Ullman,
- * "Analysis of a Simple Algorithm for Global Data Flow Problems",
- * Conf. Record of ACM Symp. on Principles of Prog. Langs, Boston, Massachusetts,
- * Oct. 1-3, 1973, pp. 207-217.
- * 3) find all nodes with a predecessor dominated by the current node.
- * such a node is a loop head.
- * recursively, all preds with a greater rpo number are in the loop
- */
+// find looping structure
+//
+// 1) find reverse postordering
+// 2) find approximate dominators,
+// the actual dominators if the flow graph is reducible
+// otherwise, dominators plus some other non-dominators.
+// See Matthew S. Hecht and Jeffrey D. Ullman,
+// "Analysis of a Simple Algorithm for Global Data Flow Problems",
+// Conf. Record of ACM Symp. on Principles of Prog. Langs, Boston, Massachusetts,
+// Oct. 1-3, 1973, pp. 207-217.
+// 3) find all nodes with a predecessor dominated by the current node.
+// such a node is a loop head.
+// recursively, all preds with a greater rpo number are in the loop
func postorder(r *Flow, rpo2r []*Flow, n int32) int32 {
r.Rpo = 1
r1 := r.S1
return
}
- if Debug_checknil > 1 { /* || strcmp(curfn->nname->sym->name, "f1") == 0 */
+ if Debug_checknil > 1 { // || strcmp(curfn->nname->sym->name, "f1") == 0
Dumpit("nilopt", g.Start, 0)
}
"strings"
)
-// The racewalk pass modifies the code tree for the function as follows:
+// The instrument pass modifies the code tree for instrumentation.
+//
+// For flag_race it modifies the function as follows:
//
// 1. It inserts a call to racefuncenterfp at the beginning of each function.
// 2. It inserts a call to racefuncexit at the end of each function.
// 3. It inserts a call to raceread before each memory read.
// 4. It inserts a call to racewrite before each memory write.
//
+// For flag_msan:
+//
+// 1. It inserts a call to msanread before each memory read.
+// 2. It inserts a call to msanwrite before each memory write.
+//
// The rewriting is not yet complete. Certain nodes are not rewritten
// but should be.
// Do not instrument the following packages at all,
// at best instrumentation would cause infinite recursion.
-var omit_pkgs = []string{"runtime", "runtime/race"}
+var omit_pkgs = []string{"runtime/internal/atomic", "runtime/internal/sys", "runtime", "runtime/race", "runtime/msan"}
// Only insert racefuncenterfp/racefuncexit into the following packages.
// Memory accesses in the packages are either uninteresting or will cause false positives.
-var noinst_pkgs = []string{"sync", "sync/atomic"}
+var norace_inst_pkgs = []string{"sync", "sync/atomic"}
func ispkgin(pkgs []string) bool {
if myimportpath != "" {
return false
}
-// TODO(rsc): Remove. Put //go:norace on forkAndExecInChild instead.
-func isforkfunc(fn *Node) bool {
- // Special case for syscall.forkAndExecInChild.
- // In the child, this function must not acquire any locks, because
- // they might have been locked at the time of the fork. This means
- // no rescheduling, no malloc calls, and no new stack segments.
- // Race instrumentation does all of the above.
- return myimportpath != "" && myimportpath == "syscall" && fn.Func.Nname.Sym.Name == "forkAndExecInChild"
-}
-
-func racewalk(fn *Node) {
- if ispkgin(omit_pkgs) || isforkfunc(fn) || fn.Func.Norace {
+func instrument(fn *Node) {
+ if ispkgin(omit_pkgs) || fn.Func.Norace {
return
}
- if !ispkgin(noinst_pkgs) {
- racewalklist(fn.Nbody, nil)
+ if flag_race == 0 || !ispkgin(norace_inst_pkgs) {
+ instrumentlist(fn.Nbody, nil)
// nothing interesting for race detector in fn->enter
- racewalklist(fn.Func.Exit, nil)
+ instrumentlist(fn.Func.Exit, nil)
}
- nd := mkcall("racefuncenterfp", nil, nil, Nod(OADDR, nodfp, nil))
- fn.Func.Enter = concat(list1(nd), fn.Func.Enter)
- nd = mkcall("racefuncexit", nil, nil)
- fn.Func.Exit = list(fn.Func.Exit, nd)
+ if flag_race != 0 {
+ // nodpc is the PC of the caller as extracted by
+ // getcallerpc. We use -widthptr(FP) for x86.
+ // BUG: this will not work on arm.
+ nodpc := Nod(OXXX, nil, nil)
+
+ *nodpc = *nodfp
+ nodpc.Type = Types[TUINTPTR]
+ nodpc.Xoffset = int64(-Widthptr)
+ nd := mkcall("racefuncenter", nil, nil, nodpc)
+ fn.Func.Enter = concat(list1(nd), fn.Func.Enter)
+ nd = mkcall("racefuncexit", nil, nil)
+ fn.Func.Exit = list(fn.Func.Exit, nd)
+ }
if Debug['W'] != 0 {
- s := fmt.Sprintf("after racewalk %v", fn.Func.Nname.Sym)
+ s := fmt.Sprintf("after instrument %v", fn.Func.Nname.Sym)
dumplist(s, fn.Nbody)
s = fmt.Sprintf("enter %v", fn.Func.Nname.Sym)
dumplist(s, fn.Func.Enter)
}
}
-func racewalklist(l *NodeList, init **NodeList) {
+func instrumentlist(l *NodeList, init **NodeList) {
var instr *NodeList
for ; l != nil; l = l.Next {
instr = nil
- racewalknode(&l.N, &instr, 0, 0)
+ instrumentnode(&l.N, &instr, 0, 0)
if init == nil {
l.N.Ninit = concat(l.N.Ninit, instr)
} else {
// walkexpr and walkstmt combined
// walks the tree and adds calls to the
// instrumentation code to top-level (statement) nodes' init
-func racewalknode(np **Node, init **NodeList, wr int, skip int) {
+func instrumentnode(np **Node, init **NodeList, wr int, skip int) {
n := *np
if n == nil {
}
if Debug['w'] > 1 {
- Dump("racewalk-before", n)
+ Dump("instrument-before", n)
}
setlineno(n)
if init == nil {
- Fatalf("racewalk: bad init list")
+ Fatalf("instrument: bad init list")
}
if init == &n.Ninit {
// If init == &n->ninit and n->ninit is non-nil,
- // racewalknode might append it to itself.
+ // instrumentnode might append it to itself.
// nil it out and handle it separately before putting it back.
l := n.Ninit
n.Ninit = nil
- racewalklist(l, nil)
- racewalknode(&n, &l, wr, skip) // recurse with nil n->ninit
+ instrumentlist(l, nil)
+ instrumentnode(&n, &l, wr, skip) // recurse with nil n->ninit
appendinit(&n, l)
*np = n
return
}
- racewalklist(n.Ninit, nil)
+ instrumentlist(n.Ninit, nil)
switch n.Op {
default:
- Fatalf("racewalk: unknown node type %v", Oconv(int(n.Op), 0))
+ Fatalf("instrument: unknown node type %v", Oconv(int(n.Op), 0))
case OAS, OASWB, OAS2FUNC:
- racewalknode(&n.Left, init, 1, 0)
- racewalknode(&n.Right, init, 0, 0)
+ instrumentnode(&n.Left, init, 1, 0)
+ instrumentnode(&n.Right, init, 0, 0)
goto ret
// can't matter
for l := n.List; l != nil; l = l.Next {
switch l.N.Op {
case OCALLFUNC, OCALLMETH, OCALLINTER:
- racewalknode(&l.N, &out, 0, 0)
+ instrumentnode(&l.N, &out, 0, 0)
out = list(out, l.N)
// Scan past OAS nodes copying results off stack.
// Those must not be instrumented, because the
out = list(out, l.N)
}
default:
- racewalknode(&l.N, &out, 0, 0)
+ instrumentnode(&l.N, &out, 0, 0)
out = list(out, l.N)
}
}
goto ret
case ODEFER:
- racewalknode(&n.Left, init, 0, 0)
+ instrumentnode(&n.Left, init, 0, 0)
goto ret
case OPROC:
- racewalknode(&n.Left, init, 0, 0)
+ instrumentnode(&n.Left, init, 0, 0)
goto ret
case OCALLINTER:
- racewalknode(&n.Left, init, 0, 0)
+ instrumentnode(&n.Left, init, 0, 0)
goto ret
// Instrument dst argument of runtime.writebarrier* calls
// as we do not instrument runtime code.
// typedslicecopy is instrumented in runtime.
case OCALLFUNC:
- racewalknode(&n.Left, init, 0, 0)
+ instrumentnode(&n.Left, init, 0, 0)
goto ret
case ONOT,
OIMAG,
OCOM,
OSQRT:
- racewalknode(&n.Left, init, wr, 0)
+ instrumentnode(&n.Left, init, wr, 0)
goto ret
case ODOTINTER:
- racewalknode(&n.Left, init, 0, 0)
+ instrumentnode(&n.Left, init, 0, 0)
goto ret
case ODOT:
- racewalknode(&n.Left, init, 0, 1)
+ instrumentnode(&n.Left, init, 0, 1)
callinstr(&n, init, wr, skip)
goto ret
case ODOTPTR: // dst = (*x).f with implicit *; otherwise it's ODOT+OIND
- racewalknode(&n.Left, init, 0, 0)
+ instrumentnode(&n.Left, init, 0, 0)
callinstr(&n, init, wr, skip)
goto ret
case OIND: // *p
- racewalknode(&n.Left, init, 0, 0)
+ instrumentnode(&n.Left, init, 0, 0)
callinstr(&n, init, wr, skip)
goto ret
case OSPTR, OLEN, OCAP:
- racewalknode(&n.Left, init, 0, 0)
+ instrumentnode(&n.Left, init, 0, 0)
if Istype(n.Left.Type, TMAP) {
n1 := Nod(OCONVNOP, n.Left, nil)
n1.Type = Ptrto(Types[TUINT8])
OGT,
OADD,
OCOMPLEX:
- racewalknode(&n.Left, init, wr, 0)
- racewalknode(&n.Right, init, wr, 0)
+ instrumentnode(&n.Left, init, wr, 0)
+ instrumentnode(&n.Right, init, wr, 0)
goto ret
case OANDAND, OOROR:
- racewalknode(&n.Left, init, wr, 0)
+ instrumentnode(&n.Left, init, wr, 0)
// walk has ensured the node has moved to a location where
// side effects are safe.
// n->right may not be executed,
// so instrumentation goes to n->right->ninit, not init.
- racewalknode(&n.Right, &n.Right.Ninit, wr, 0)
+ instrumentnode(&n.Right, &n.Right.Ninit, wr, 0)
goto ret
goto ret
case OCONV:
- racewalknode(&n.Left, init, wr, 0)
+ instrumentnode(&n.Left, init, wr, 0)
goto ret
case OCONVNOP:
- racewalknode(&n.Left, init, wr, 0)
+ instrumentnode(&n.Left, init, wr, 0)
goto ret
case ODIV, OMOD:
- racewalknode(&n.Left, init, wr, 0)
- racewalknode(&n.Right, init, wr, 0)
+ instrumentnode(&n.Left, init, wr, 0)
+ instrumentnode(&n.Right, init, wr, 0)
goto ret
case OINDEX:
if !Isfixedarray(n.Left.Type) {
- racewalknode(&n.Left, init, 0, 0)
+ instrumentnode(&n.Left, init, 0, 0)
} else if !islvalue(n.Left) {
// index of unaddressable array, like Map[k][i].
- racewalknode(&n.Left, init, wr, 0)
+ instrumentnode(&n.Left, init, wr, 0)
- racewalknode(&n.Right, init, 0, 0)
+ instrumentnode(&n.Right, init, 0, 0)
goto ret
}
- racewalknode(&n.Right, init, 0, 0)
+ instrumentnode(&n.Right, init, 0, 0)
if n.Left.Type.Etype != TSTRING {
callinstr(&n, init, wr, skip)
}
goto ret
case OSLICE, OSLICEARR, OSLICE3, OSLICE3ARR, OSLICESTR:
- racewalknode(&n.Left, init, 0, 0)
- racewalknode(&n.Right, init, 0, 0)
+ instrumentnode(&n.Left, init, 0, 0)
+ instrumentnode(&n.Right, init, 0, 0)
goto ret
case OKEY:
- racewalknode(&n.Left, init, 0, 0)
- racewalknode(&n.Right, init, 0, 0)
+ instrumentnode(&n.Left, init, 0, 0)
+ instrumentnode(&n.Right, init, 0, 0)
goto ret
case OADDR:
- racewalknode(&n.Left, init, 0, 1)
+ instrumentnode(&n.Left, init, 0, 1)
goto ret
// n->left is Type* which is not interesting.
case OEFACE:
- racewalknode(&n.Right, init, 0, 0)
+ instrumentnode(&n.Right, init, 0, 0)
goto ret
case OITAB:
- racewalknode(&n.Left, init, 0, 0)
+ instrumentnode(&n.Left, init, 0, 0)
goto ret
// should not appear in AST by now
OAS2RECV,
OAS2MAPR,
OASOP:
- Yyerror("racewalk: %v must be lowered by now", Oconv(int(n.Op), 0))
+ Yyerror("instrument: %v must be lowered by now", Oconv(int(n.Op), 0))
goto ret
// impossible nodes: only appear in backend.
case ORROTC, OEXTEND:
- Yyerror("racewalk: %v cannot exist now", Oconv(int(n.Op), 0))
+ Yyerror("instrument: %v cannot exist now", Oconv(int(n.Op), 0))
goto ret
case OGETG:
- Yyerror("racewalk: OGETG can happen only in runtime which we don't instrument")
+ Yyerror("instrument: OGETG can happen only in runtime which we don't instrument")
goto ret
case OFOR:
if n.Left != nil {
- racewalknode(&n.Left, &n.Left.Ninit, 0, 0)
+ instrumentnode(&n.Left, &n.Left.Ninit, 0, 0)
}
if n.Right != nil {
- racewalknode(&n.Right, &n.Right.Ninit, 0, 0)
+ instrumentnode(&n.Right, &n.Right.Ninit, 0, 0)
}
goto ret
case OIF, OSWITCH:
if n.Left != nil {
- racewalknode(&n.Left, &n.Left.Ninit, 0, 0)
+ instrumentnode(&n.Left, &n.Left.Ninit, 0, 0)
}
goto ret
ret:
if n.Op != OBLOCK { // OBLOCK is handled above in a special way.
- racewalklist(n.List, init)
+ instrumentlist(n.List, init)
}
- racewalklist(n.Nbody, nil)
- racewalklist(n.Rlist, nil)
+ instrumentlist(n.Nbody, nil)
+ instrumentlist(n.Rlist, nil)
*np = n
}
func isartificial(n *Node) bool {
// compiler-emitted artificial things that we do not want to instrument,
- // cant' possibly participate in a data race.
+ // can't possibly participate in a data race.
+ // can't be seen by C/C++ and therefore irrelevant for msan.
if n.Op == ONAME && n.Sym != nil && n.Sym.Name != "" {
if n.Sym.Name == "_" {
return true
n = treecopy(n, 0)
makeaddable(n)
var f *Node
- if t.Etype == TSTRUCT || Isfixedarray(t) {
+ if flag_msan != 0 {
+ name := "msanread"
+ if wr != 0 {
+ name = "msanwrite"
+ }
+ // dowidth may not have been called for PEXTERN.
+ dowidth(t)
+ w := t.Width
+ if w == BADWIDTH {
+ Fatalf("instrument: %v badwidth", t)
+ }
+ f = mkcall(name, nil, init, uintptraddr(n), Nodintconst(w))
+ } else if flag_race != 0 && (t.Etype == TSTRUCT || Isfixedarray(t)) {
name := "racereadrange"
if wr != 0 {
name = "racewriterange"
}
- f = mkcall(name, nil, init, uintptraddr(n), Nodintconst(t.Width))
- } else {
+ // dowidth may not have been called for PEXTERN.
+ dowidth(t)
+ w := t.Width
+ if w == BADWIDTH {
+ Fatalf("instrument: %v badwidth", t)
+ }
+ f = mkcall(name, nil, init, uintptraddr(n), Nodintconst(w))
+ } else if flag_race != 0 {
name := "raceread"
if wr != 0 {
name = "racewrite"
import "cmd/internal/obj"
-/*
- * range
- */
+// range
func typecheckrange(n *Node) {
var toomany int
var why string
//
// Parameters are as in walkrange: "for v1, v2 = range a".
func memclrrange(n, v1, v2, a *Node) bool {
- if Debug['N'] != 0 || flag_race != 0 {
+ if Debug['N'] != 0 || instrumenting {
return false
}
if v1 == nil || v2 != nil {
"sort"
)
-/*
- * runtime interface and reflection data structures
- */
+// runtime interface and reflection data structures
var signatlist *NodeList
// byMethodNameAndPackagePath sorts method signatures by name, then package path.
return i
}
-/*
- * f is method type, with receiver.
- * return function type, receiver as first argument (or not).
- */
+// f is method type, with receiver.
+// return function type, receiver as first argument (or not).
func methodfunc(f *Type, receiver *Type) *Type {
var in *NodeList
if receiver != nil {
return dsymptr(s, ot, pkg.Pathsym, 0)
}
-/*
- * uncommonType
- * ../../runtime/type.go:/uncommonType
- */
+// uncommonType
+// ../../runtime/type.go:/uncommonType
func dextratype(sym *Sym, off int, t *Type, ptroff int) int {
m := methods(t)
if t.Sym == nil && len(m) == 0 {
}
}
-/*
- * commonType
- * ../../runtime/type.go:/commonType
- */
+// commonType
+// ../../runtime/type.go:/commonType
var dcommontype_algarray *Sym
dupok = obj.DUPOK
}
- if compiling_runtime != 0 && (tbase == Types[tbase.Etype] || tbase == bytetype || tbase == runetype || tbase == errortype) { // int, float, etc
+ if localpkg.Name == "runtime" && (tbase == Types[tbase.Etype] || tbase == bytetype || tbase == runetype || tbase == errortype) { // int, float, etc
goto ok
}
ot = dsymptr(s, ot, s1, 0)
}
- // ../../runtime/type.go:/ChanType
+ // ../../runtime/type.go:/ChanType
case TCHAN:
s1 := dtypesym(t.Type)
ot = dsymptr(s, ot, dtypesym(a.type_), 0)
}
- // ../../../runtime/type.go:/MapType
+ // ../../../runtime/type.go:/MapType
case TMAP:
s1 := dtypesym(t.Down)
xt = ot - 2*Widthptr
ot = dsymptr(s, ot, s1, 0)
- // ../../runtime/type.go:/StructType
+ // ../../runtime/type.go:/StructType
// for security, only the exported fields.
case TSTRUCT:
n := 0
}
} else {
ot = dgostringptr(s, ot, "")
- if t1.Type.Sym != nil && t1.Type.Sym.Pkg == builtinpkg {
+ if t1.Type.Sym != nil &&
+ (t1.Type.Sym.Pkg == builtinpkg || !exportname(t1.Type.Sym.Name)) {
ot = dgopkgpath(s, ot, localpkg)
} else {
ot = dgostringptr(s, ot, "")
// so this is as good as any.
// another possible choice would be package main,
// but using runtime means fewer copies in .6 files.
- if compiling_runtime != 0 {
- for i := 1; i <= TBOOL; i++ {
+ if localpkg.Name == "runtime" {
+ for i := EType(1); i <= TBOOL; i++ {
dtypesym(Ptrto(Types[i]))
}
dtypesym(Ptrto(Types[TSTRING]))
if flag_race != 0 {
dimportpath(racepkg)
}
+ if flag_msan != 0 {
+ dimportpath(msanpkg)
+ }
dimportpath(mkpkg("main"))
}
}
width int
id int // index in vars
name int8
- etype int8
+ etype EType
addr int8
}
}
}
-/*
- * add mov b,rn
- * just after r
- */
+// add mov b,rn
+// just after r
func addmove(r *Flow, bn int, rn int, f int) {
p1 := Ctxt.NewProg()
Clearp(p1)
p1.As = int16(Thearch.Optoas(OAS, Types[uint8(v.etype)]))
// TODO(rsc): Remove special case here.
- if (Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9') && v.etype == TBOOL {
+ if (Thearch.Thechar == '0' || Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9') && v.etype == TBOOL {
p1.As = int16(Thearch.Optoas(OAS, Types[TUINT8]))
}
p1.From.Type = obj.TYPE_REG
}
func mkvar(f *Flow, a *obj.Addr) Bits {
- /*
- * mark registers used
- */
+ // mark registers used
if a.Type == obj.TYPE_NONE {
return zbits
}
// TODO(rsc): Remove special case here.
case obj.TYPE_ADDR:
var bit Bits
- if Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9' {
+ if Thearch.Thechar == '0' || Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9' {
goto memcase
}
a.Type = obj.TYPE_MEM
if node.Sym == nil || node.Sym.Name[0] == '.' {
return zbits
}
- et := int(a.Etype)
+ et := EType(a.Etype)
o := a.Offset
w := a.Width
if w < 0 {
v = &vars[i]
if v.node == node && int(v.name) == n {
if v.offset == o {
- if int(v.etype) == et {
+ if v.etype == et {
if int64(v.width) == w {
// TODO(rsc): Remove special case for arm here.
if flag == 0 || Thearch.Thechar != '5' {
v.id = i
v.offset = o
v.name = int8(n)
- v.etype = int8(et)
+ v.etype = et
v.width = int(w)
v.addr = int8(flag) // funny punning
v.node = node
}
// Treat values with their address taken as live at calls,
- // because the garbage collector's liveness analysis in ../gc/plive.c does.
+ // because the garbage collector's liveness analysis in plive.go does.
// These must be consistent or else we will elide stores and the garbage
// collector will see uninitialized data.
// The typical case where our own analysis is out of sync is when the
// sets addrtaken, even though it ends up not being actually shared.
// If we were better about _ elision, _ = &x would suffice too.
// The broader := in a closure problem is mentioned in a comment in
- // closure.c:/^typecheckclosure and dcl.c:/^oldname.
+ // closure.go:/^typecheckclosure and dcl.go:/^oldname.
if node.Addrtaken {
v.addr = 1
}
}
if Debug['R'] != 0 {
- fmt.Printf("bit=%2d et=%v w=%d+%d %v %v flag=%d\n", i, Econv(int(et), 0), o, w, Nconv(node, obj.FmtSharp), Ctxt.Dconv(a), v.addr)
+ fmt.Printf("bit=%2d et=%v w=%d+%d %v %v flag=%d\n", i, Econv(et), o, w, Nconv(node, obj.FmtSharp), Ctxt.Dconv(a), v.addr)
}
Ostats.Nvar++
r.regno = 0
switch v.etype {
default:
- Fatalf("unknown etype %d/%v", Bitno(b), Econv(int(v.etype), 0))
+ Fatalf("unknown etype %d/%v", Bitno(b), Econv(v.etype))
case TINT8,
TUINT8,
func regopt(firstp *obj.Prog) {
mergetemp(firstp)
- /*
- * control flow is more complicated in generated go code
- * than in generated c code. define pseudo-variables for
- * registers, so we have complete register usage information.
- */
+ // control flow is more complicated in generated go code
+ // than in generated c code. define pseudo-variables for
+ // registers, so we have complete register usage information.
var nreg int
regnames := Thearch.Regnames(&nreg)
ivar = zbits
ovar = zbits
- /*
- * pass 1
- * build aux data structure
- * allocate pcs
- * find use and set of variables
- */
+ // pass 1
+ // build aux data structure
+ // allocate pcs
+ // find use and set of variables
g := Flowstart(firstp, func() interface{} { return new(Reg) })
if g == nil {
for i := 0; i < nvar; i++ {
}
if Debug['R'] != 0 && Debug['v'] != 0 {
- fmt.Printf("bit=%2d addr=%d et=%v w=%-2d s=%v + %d\n", i, v.addr, Econv(int(v.etype), 0), v.width, v.node, v.offset)
+ fmt.Printf("bit=%2d addr=%d et=%v w=%-2d s=%v + %d\n", i, v.addr, Econv(v.etype), v.width, v.node, v.offset)
}
}
Dumpit("pass1", firstf, 1)
}
- /*
- * pass 2
- * find looping structure
- */
+ // pass 2
+ // find looping structure
flowrpo(g)
if Debug['R'] != 0 && Debug['v'] != 0 {
Dumpit("pass2", firstf, 1)
}
- /*
- * pass 2.5
- * iterate propagating fat vardef covering forward
- * r->act records vars with a VARDEF since the last CALL.
- * (r->act will be reused in pass 5 for something else,
- * but we'll be done with it by then.)
- */
+ // pass 2.5
+ // iterate propagating fat vardef covering forward
+ // r->act records vars with a VARDEF since the last CALL.
+ // (r->act will be reused in pass 5 for something else,
+ // but we'll be done with it by then.)
active := 0
for f := firstf; f != nil; f = f.Link {
}
}
- /*
- * pass 3
- * iterate propagating usage
- * back until flow graph is complete
- */
+ // pass 3
+ // iterate propagating usage
+ // back until flow graph is complete
var f1 *Flow
var i int
var f *Flow
}
}
- /* pick up unreachable code */
+ // pick up unreachable code
loop11:
i = 0
Dumpit("pass3", firstf, 1)
}
- /*
- * pass 4
- * iterate propagating register/variable synchrony
- * forward until graph is complete
- */
+ // pass 4
+ // iterate propagating register/variable synchrony
+ // forward until graph is complete
loop2:
change = 0
Dumpit("pass4", firstf, 1)
}
- /*
- * pass 4.5
- * move register pseudo-variables into regu.
- */
+ // pass 4.5
+ // move register pseudo-variables into regu.
mask := uint64((1 << uint(nreg)) - 1)
for f := firstf; f != nil; f = f.Link {
r := f.Data.(*Reg)
Dumpit("pass4.5", firstf, 1)
}
- /*
- * pass 5
- * isolate regions
- * calculate costs (paint1)
- */
+ // pass 5
+ // isolate regions
+ // calculate costs (paint1)
var bit Bits
if f := firstf; f != nil {
r := f.Data.(*Reg)
Dumpit("pass5", firstf, 1)
}
- /*
- * pass 6
- * determine used registers (paint2)
- * replace code (paint3)
- */
+ // pass 6
+ // determine used registers (paint2)
+ // replace code (paint3)
if Debug['R'] != 0 && Debug['v'] != 0 {
fmt.Printf("\nregisterizing\n")
}
if rgp.regno != 0 {
if Debug['R'] != 0 && Debug['v'] != 0 {
v := &vars[rgp.varno]
- fmt.Printf("registerize %v+%d (bit=%2d et=%v) in %v usedreg=%#x vreg=%#x\n", v.node, v.offset, rgp.varno, Econv(int(v.etype), 0), obj.Rconv(int(rgp.regno)), usedreg, vreg)
+ fmt.Printf("registerize %v+%d (bit=%2d et=%v) in %v usedreg=%#x vreg=%#x\n", v.node, v.offset, rgp.varno, Econv(v.etype), obj.Rconv(int(rgp.regno)), usedreg, vreg)
}
paint3(rgp.enter, int(rgp.varno), vreg, int(rgp.regno))
}
}
- /*
- * free aux structures. peep allocates new ones.
- */
+ // free aux structures. peep allocates new ones.
for i := 0; i < nvar; i++ {
vars[i].node.SetOpt(nil)
}
firstf = nil
}
- /*
- * pass 7
- * peep-hole on basic block
- */
+ // pass 7
+ // peep-hole on basic block
if Debug['R'] == 0 || Debug['P'] != 0 {
Thearch.Peep(firstp)
}
- /*
- * eliminate nops
- */
+ // eliminate nops
for p := firstp; p != nil; p = p.Link {
for p.Link != nil && p.Link.As == obj.ANOP {
p.Link = p.Link.Link
package gc
-/*
- * select
- */
+// select
func typecheckselect(sel *Node) {
var ncase *Node
var n *Node
}
// optimization: one-case select: single op.
- // TODO(rsc): Reenable optimization once order.c can handle it.
+ // TODO(rsc): Reenable optimization once order.go can handle it.
// golang.org/issue/7672.
if i == 1 {
cas := sel.List.N
"fmt"
)
-/*
- * static initialization
- */
+// static initialization
const (
InitNotStarted = 0
InitDone = 1
return lout
}
-/*
- * compilation of top-level (static) assignments
- * into DATA statements if at all possible.
- */
+// compilation of top-level (static) assignments
+// into DATA statements if at all possible.
func staticinit(n *Node, out **NodeList) bool {
if n.Op != ONAME || n.Class != PEXTERN || n.Name.Defn == nil || n.Name.Defn.Op != OAS {
Fatalf("staticinit")
return false
}
-/*
- * from here down is the walk analysis
- * of composite literals.
- * most of the work is to generate
- * data statements for the constant
- * part of the composite literal.
- */
+// from here down is the walk analysis
+// of composite literals.
+// most of the work is to generate
+// data statements for the constant
+// part of the composite literal.
func staticname(t *Type, ctxt int) *Node {
n := newname(Lookupf("statictmp_%.4d", statuniqgen))
statuniqgen++
// set auto to point at new temp or heap (3 assign)
var a *Node
if x := prealloc[n]; x != nil {
- // temp allocated during order.c for dddarg
+ // temp allocated during order.go for dddarg
x.Type = t
if vstat == nil {
s.Unimplementedf("local variable with class %s%s unimplemented", classnames[n.Class&^PHEAP], str)
}
}
- // nodfp is a special argument which is the function's FP.
- aux := &ssa.ArgSymbol{Typ: Types[TUINTPTR], Node: nodfp}
- s.decladdrs[nodfp] = s.entryNewValue1A(ssa.OpAddr, Types[TUINTPTR], aux, s.sp)
// Convert the AST-based IR to the SSA-based IR
s.stmtList(fn.Func.Enter)
}
type opAndType struct {
- op uint8
- etype uint8
+ op Op
+ etype EType
}
var opToSSA = map[opAndType]ssa.Op{
opAndType{OSQRT, TFLOAT64}: ssa.OpSqrt,
}
-func (s *state) concreteEtype(t *Type) uint8 {
+func (s *state) concreteEtype(t *Type) EType {
e := t.Etype
switch e {
default:
}
}
-func (s *state) ssaOp(op uint8, t *Type) ssa.Op {
+func (s *state) ssaOp(op Op, t *Type) ssa.Op {
etype := s.concreteEtype(t)
x, ok := opToSSA[opAndType{op, etype}]
if !ok {
- s.Unimplementedf("unhandled binary op %s %s", opnames[op], Econv(int(etype), 0))
+ s.Unimplementedf("unhandled binary op %s %s", opnames[op], Econv(etype))
}
return x
}
}
type opAndTwoTypes struct {
- op uint8
- etype1 uint8
- etype2 uint8
+ op Op
+ etype1 EType
+ etype2 EType
}
type twoTypes struct {
- etype1 uint8
- etype2 uint8
+ etype1 EType
+ etype2 EType
}
type twoOpsAndType struct {
op1 ssa.Op
op2 ssa.Op
- intermediateType uint8
+ intermediateType EType
}
var fpConvOpToSSA = map[twoTypes]twoOpsAndType{
opAndTwoTypes{ORSH, TUINT64, TUINT64}: ssa.OpRsh64Ux64,
}
-func (s *state) ssaShiftOp(op uint8, t *Type, u *Type) ssa.Op {
+func (s *state) ssaShiftOp(op Op, t *Type, u *Type) ssa.Op {
etype1 := s.concreteEtype(t)
etype2 := s.concreteEtype(u)
x, ok := shiftOpToSSA[opAndTwoTypes{op, etype1, etype2}]
if !ok {
- s.Unimplementedf("unhandled shift op %s etype=%s/%s", opnames[op], Econv(int(etype1), 0), Econv(int(etype2), 0))
+ s.Unimplementedf("unhandled shift op %s etype=%s/%s", opnames[op], Econv(etype1), Econv(etype2))
}
return x
}
-func (s *state) ssaRotateOp(op uint8, t *Type) ssa.Op {
+func (s *state) ssaRotateOp(op Op, t *Type) ssa.Op {
etype1 := s.concreteEtype(t)
x, ok := opToSSA[opAndType{op, etype1}]
if !ok {
- s.Unimplementedf("unhandled rotate op %s etype=%s", opnames[op], Econv(int(etype1), 0))
+ s.Unimplementedf("unhandled rotate op %s etype=%s", opnames[op], Econv(etype1))
}
return x
}
return nil
}
if etypesign(from.Etype) != etypesign(to.Etype) {
- s.Fatalf("CONVNOP sign mismatch %v (%s) -> %v (%s)\n", from, Econv(int(from.Etype), 0), to, Econv(int(to.Etype), 0))
+ s.Fatalf("CONVNOP sign mismatch %v (%s) -> %v (%s)\n", from, Econv(from.Etype), to, Econv(to.Etype))
return nil
}
s.newValue1(op, ttp, s.newValue1(ssa.OpComplexImag, ftp, x)))
}
- s.Unimplementedf("unhandled OCONV %s -> %s", Econv(int(n.Left.Type.Etype), 0), Econv(int(n.Type.Etype), 0))
+ s.Unimplementedf("unhandled OCONV %s -> %s", Econv(n.Left.Type.Etype), Econv(n.Type.Etype))
return nil
case ODOTTYPE:
}
if haspointers(et) {
// TODO: just one write barrier call for all of these writes?
- // TODO: maybe just one writeBarrierEnabled check?
+ // TODO: maybe just one writeBarrier.enabled check?
s.insertWB(et, addr, n.Lineno)
}
}
// etypesign returns the signed-ness of e, for integer/pointer etypes.
// -1 means signed, +1 means unsigned, 0 means non-integer/non-pointer.
-func etypesign(e uint8) int8 {
+func etypesign(e EType) int8 {
switch e {
case TINT8, TINT16, TINT32, TINT64, TINT:
return -1
case PPARAM:
// parameter slot
v := s.decladdrs[n]
- if v == nil {
- if flag_race != 0 && n.String() == ".fp" {
- s.Unimplementedf("race detector mishandles nodfp")
- }
- s.Fatalf("addr of undeclared ONAME %v. declared: %v", n, s.decladdrs)
+ if v != nil {
+ return v
}
- return v
+ if n.String() == ".fp" {
+ // Special arg that points to the frame pointer.
+ // (Used by the race detector, others?)
+ aux := s.lookupSymbol(n, &ssa.ArgSymbol{Typ: n.Type, Node: n})
+ return s.entryNewValue1A(ssa.OpAddr, t, aux, s.sp)
+ }
+ s.Fatalf("addr of undeclared ONAME %v. declared: %v", n, s.decladdrs)
+ return nil
case PAUTO:
// We need to regenerate the address of autos
// at every use. This prevents LEA instructions
// Note: there must be no GC suspension points between the write and
// the call that this function inserts.
func (s *state) insertWB(t *Type, p *ssa.Value, line int32) {
- // if writeBarrierEnabled {
+ // if writeBarrier.enabled {
// typedmemmove_nostore(&t, p)
// }
bThen := s.f.NewBlock(ssa.BlockPlain)
- aux := &ssa.ExternSymbol{Types[TBOOL], syslook("writeBarrierEnabled", 0).Sym}
+ aux := &ssa.ExternSymbol{Types[TBOOL], syslook("writeBarrier", 0).Sym}
flagaddr := s.newValue1A(ssa.OpAddr, Ptrto(Types[TBOOL]), aux, s.sb)
+ // TODO: select the .enabled field. It is currently first, so not needed for now.
flag := s.newValue2(ssa.OpLoad, Types[TBOOL], flagaddr, s.mem())
b := s.endBlock()
b.Kind = ssa.BlockIf
}
func parserline() int {
- if parsing && theparser.Lookahead() > 0 {
+ if oldparser != 0 && parsing && theparser.Lookahead() > 0 {
// parser has one symbol lookahead
return int(prevlineno)
}
}
}
-func Nod(op int, nleft *Node, nright *Node) *Node {
+func Nod(op Op, nleft *Node, nright *Node) *Node {
n := new(Node)
- n.Op = uint8(op)
+ n.Op = op
n.Left = nleft
n.Right = nright
n.Lineno = int32(parserline())
if n.Orig != nil {
return
}
- norig := Nod(int(n.Op), nil, nil)
+ norig := Nod(n.Op, nil, nil)
*norig = *n
n.Orig = norig
}
if key != nil {
var bad *Type
atype := algtype1(key, &bad)
- var mtype int
+ var mtype EType
if bad == nil {
- mtype = int(key.Etype)
+ mtype = key.Etype
} else {
- mtype = int(bad.Etype)
+ mtype = bad.Etype
}
switch mtype {
default:
return t
}
-func typ(et int) *Type {
+func typ(et EType) *Type {
t := new(Type)
- t.Etype = uint8(et)
+ t.Etype = et
t.Width = BADWIDTH
t.Lineno = int(lineno)
t.Orig = t
return true
}
-func isptrto(t *Type, et int) bool {
+func isptrto(t *Type, et EType) bool {
if t == nil {
return false
}
if t == nil {
return false
}
- if int(t.Etype) != et {
+ if t.Etype != et {
return false
}
return true
}
-func Istype(t *Type, et int) bool {
- return t != nil && int(t.Etype) == et
+func Istype(t *Type, et EType) bool {
+ return t != nil && t.Etype == et
}
func Isfixedarray(t *Type) bool {
return false
}
-/*
- * given receiver of type t (t == r or t == *r)
- * return type to hang methods off (r).
- */
+// given receiver of type t (t == r or t == *r)
+// return type to hang methods off (r).
func methtype(t *Type, mustname int) *Type {
if t == nil {
return nil
return t
}
-func cplxsubtype(et int) int {
+func cplxsubtype(et EType) EType {
switch et {
case TCOMPLEX64:
return TFLOAT32
return TFLOAT64
}
- Fatalf("cplxsubtype: %v\n", Econv(int(et), 0))
+ Fatalf("cplxsubtype: %v\n", Econv(et))
return 0
}
// Is type src assignment compatible to type dst?
// If so, return op code to use in conversion.
// If not, return 0.
-func assignop(src *Type, dst *Type, why *string) int {
+func assignop(src *Type, dst *Type, why *string) Op {
if why != nil {
*why = ""
}
// Can we convert a value of type src to a value of type dst?
// If so, return op code to use in conversion (maybe OCONVNOP).
// If not, return 0.
-func convertop(src *Type, dst *Type, why *string) int {
+func convertop(src *Type, dst *Type, why *string) Op {
if why != nil {
*why = ""
}
}
}
-/*
- * Is this a 64-bit type?
- */
+// Is this a 64-bit type?
func Is64(t *Type) bool {
if t == nil {
return false
return false
}
-/*
- * Is a conversion between t1 and t2 a no-op?
- */
+// Is a conversion between t1 and t2 a no-op?
func Noconv(t1 *Type, t2 *Type) bool {
- e1 := int(Simtype[t1.Etype])
- e2 := int(Simtype[t2.Etype])
+ e1 := Simtype[t1.Etype]
+ e2 := Simtype[t2.Etype]
switch e1 {
case TINT8, TUINT8:
return n
}
-/*
- * compute a hash value for type t.
- * if t is a method type, ignore the receiver
- * so that the hash can be used in interface checks.
- * %T already contains
- * all the necessary logic to generate a representation
- * of the type that completely describes it.
- * using smprint here avoids duplicating that code.
- * using md5 here is overkill, but i got tired of
- * accidental collisions making the runtime think
- * two types are equal when they really aren't.
- */
+// compute a hash value for type t.
+// if t is a method type, ignore the receiver
+// so that the hash can be used in interface checks.
+// %T already contains
+// all the necessary logic to generate a representation
+// of the type that completely describes it.
+// using smprint here avoids duplicating that code.
+// using md5 here is overkill, but i got tired of
+// accidental collisions making the runtime think
+// two types are equal when they really aren't.
func typehash(t *Type) uint32 {
var p string
}
}
-/*
- * calculate sethi/ullman number
- * roughly how many registers needed to
- * compile a node. used to compile the
- * hardest side first to minimize registers.
- */
+// calculate sethi/ullman number
+// roughly how many registers needed to
+// compile a node. used to compile the
+// hardest side first to minimize registers.
func ullmancalc(n *Node) {
if n == nil {
return
ul = UINF
goto out
- // hard with race detector
+ // hard with instrumented code
case OANDAND, OOROR:
- if flag_race != 0 {
+ if instrumenting {
ul = UINF
goto out
}
n.Ullman = uint8(ul)
}
-func badtype(o int, tl *Type, tr *Type) {
+func badtype(op Op, tl *Type, tr *Type) {
fmt_ := ""
if tl != nil {
fmt_ += fmt.Sprintf("\n\t%v", tl)
}
s := fmt_
- Yyerror("illegal types for operand: %v%s", Oconv(int(o), 0), s)
+ Yyerror("illegal types for operand: %v%s", Oconv(int(op), 0), s)
}
-/*
- * iterator to walk a structure declaration
- */
+// iterator to walk a structure declaration
func Structfirst(s *Iter, nn **Type) *Type {
var t *Type
return t
}
-/*
- * iterator to this and inargs in a function
- */
+// iterator to this and inargs in a function
func funcfirst(s *Iter, t *Type) *Type {
var fp *Type
// Brcom returns !(op).
// For example, Brcom(==) is !=.
-func Brcom(a int) int {
- switch a {
+func Brcom(op Op) Op {
+ switch op {
case OEQ:
return ONE
case ONE:
case OGE:
return OLT
}
- Fatalf("brcom: no com for %v\n", Oconv(a, 0))
- return a
+ Fatalf("brcom: no com for %v\n", Oconv(int(op), 0))
+ return op
}
// Brrev returns reverse(op).
// For example, Brrev(<) is >.
-func Brrev(a int) int {
- switch a {
+func Brrev(op Op) Op {
+ switch op {
case OEQ:
return OEQ
case ONE:
case OGE:
return OLE
}
- Fatalf("brrev: no rev for %v\n", Oconv(a, 0))
- return a
+ Fatalf("brrev: no rev for %v\n", Oconv(int(op), 0))
+ return op
}
-/*
- * return side effect-free n, appending side effects to init.
- * result is assignable if n is.
- */
+// return side effect-free n, appending side effects to init.
+// result is assignable if n is.
func safeexpr(n *Node, init **NodeList) *Node {
if n == nil {
return nil
return l
}
-/*
- * return side-effect free and cheap n, appending side effects to init.
- * result may not be assignable.
- */
+// return side-effect free and cheap n, appending side effects to init.
+// result may not be assignable.
func cheapexpr(n *Node, init **NodeList) *Node {
switch n.Op {
case ONAME, OLITERAL:
}
}
-/*
- * unicode-aware case-insensitive strcmp
- */
+// unicode-aware case-insensitive strcmp
-/*
- * code to resolve elided DOTs
- * in embedded types
- */
+// code to resolve elided DOTs
+// in embedded types
// search depth 0 --
// return count of fields+methods
return n
}
-/*
- * code to help generate trampoline
- * functions for methods on embedded
- * subtypes.
- * these are approx the same as
- * the corresponding adddot routines
- * except that they expect to be called
- * with unique tasks and they return
- * the actual methods.
- */
+// code to help generate trampoline
+// functions for methods on embedded
+// subtypes.
+// these are approx the same as
+// the corresponding adddot routines
+// except that they expect to be called
+// with unique tasks and they return
+// the actual methods.
type Symlink struct {
field *Type
link *Symlink
}
}
-/*
- * Given funarg struct list, return list of ODCLFIELD Node fn args.
- */
+// Given funarg struct list, return list of ODCLFIELD Node fn args.
func structargs(tl **Type, mustname int) *NodeList {
var savet Iter
var a *Node
return args
}
-/*
- * Generate a wrapper function to convert from
- * a receiver of type T to a receiver of type U.
- * That is,
- *
- * func (t T) M() {
- * ...
- * }
- *
- * already exists; this function generates
- *
- * func (u U) M() {
- * u.M()
- * }
- *
- * where the types T and U are such that u.M() is valid
- * and calls the T.M method.
- * The resulting function is for use in method tables.
- *
- * rcvr - U
- * method - M func (t T)(), a TFIELD type struct
- * newnam - the eventual mangled name of this function
- */
+// Generate a wrapper function to convert from
+// a receiver of type T to a receiver of type U.
+// That is,
+//
+// func (t T) M() {
+// ...
+// }
+//
+// already exists; this function generates
+//
+// func (u U) M() {
+// u.M()
+// }
+//
+// where the types T and U are such that u.M() is valid
+// and calls the T.M method.
+// The resulting function is for use in method tables.
+//
+// rcvr - U
+// method - M func (t T)(), a TFIELD type struct
+// newnam - the eventual mangled name of this function
var genwrapper_linehistdone int = 0
dot := adddot(Nod(OXDOT, this.Left, newname(method.Sym)))
// generate call
- if flag_race == 0 && Isptr[rcvr.Etype] && Isptr[methodrcvr.Etype] && method.Embedded != 0 && !isifacemethod(method.Type) {
+ if !instrumenting && Isptr[rcvr.Etype] && Isptr[methodrcvr.Etype] && method.Embedded != 0 && !isifacemethod(method.Type) {
// generate tail call: adjust pointer receiver and jump to embedded method.
dot = dot.Left // skip final .M
if !Isptr[dotlist[0].field.Type.Etype] {
return n
}
-/*
- * Generate a helper function to compute the hash of a value of type t.
- */
+// Generate a helper function to compute the hash of a value of type t.
func genhash(sym *Sym, t *Type) {
if Debug['r'] != 0 {
fmt.Printf("genhash %v %v\n", sym, t)
return nif
}
-/*
- * Generate a helper function to check equality of two values of type t.
- */
+// Generate a helper function to check equality of two values of type t.
func geneq(sym *Sym, t *Type) {
if Debug['r'] != 0 {
fmt.Printf("geneq %v %v\n", sym, t)
return true
}
-/*
- * even simpler simtype; get rid of ptr, bool.
- * assuming that the front end has rejected
- * all the invalid conversions (like ptr -> bool)
- */
-func Simsimtype(t *Type) int {
+// even simpler simtype; get rid of ptr, bool.
+// assuming that the front end has rejected
+// all the invalid conversions (like ptr -> bool)
+func Simsimtype(t *Type) EType {
if t == nil {
return 0
}
- et := int(Simtype[t.Etype])
+ et := Simtype[t.Etype]
switch et {
case TPTR32:
et = TUINT32
return n
}
-/*
- * return nelem of list
- */
+// return nelem of list
func structcount(t *Type) int {
var s Iter
return v
}
-/*
- * return power of 2 of the constant
- * operand. -1 if it is not a power of 2.
- * 1000+ if it is a -(power of 2)
- */
+// return power of 2 of the constant
+// operand. -1 if it is not a power of 2.
+// 1000+ if it is a -(power of 2)
func powtwo(n *Node) int {
if n == nil || n.Op != OLITERAL || n.Type == nil {
return -1
return -1
}
-/*
- * return the unsigned type for
- * a signed integer type.
- * returns T if input is not a
- * signed integer type.
- */
+// return the unsigned type for
+// a signed integer type.
+// returns T if input is not a
+// signed integer type.
func tounsigned(t *Type) *Type {
// this is types[et+1], but not sure
// that this relation is immutable
return t
}
-/*
- * magic number for signed division
- * see hacker's delight chapter 10
- */
+// magic number for signed division
+// see hacker's delight chapter 10
func Smagic(m *Magic) {
var mask uint64
m.S = p - m.W
}
-/*
- * magic number for unsigned division
- * see hacker's delight chapter 10
- */
+// magic number for unsigned division
+// see hacker's delight chapter 10
func Umagic(m *Magic) {
var mask uint64
return nil
}
-/*
- * Convert raw string to the prefix that will be used in the symbol
- * table. All control characters, space, '%' and '"', as well as
- * non-7-bit clean bytes turn into %xx. The period needs escaping
- * only in the last segment of the path, and it makes for happier
- * users if we escape that as little as possible.
- *
- * If you edit this, edit ../../debug/goobj/read.go:/importPathToPrefix too.
- */
+// Convert raw string to the prefix that will be used in the symbol
+// table. All control characters, space, '%' and '"', as well as
+// non-7-bit clean bytes turn into %xx. The period needs escaping
+// only in the last segment of the path, and it makes for happier
+// users if we escape that as little as possible.
+//
+// If you edit this, edit ../../debug/goobj/read.go:/importPathToPrefix too.
func pathtoprefix(s string) string {
slash := strings.LastIndex(s, "/")
for i := 0; i < len(s); i++ {
*init = list(*init, n)
}
-/*
- * Can this type be stored directly in an interface word?
- * Yes, if the representation is a single pointer.
- */
+// Can this type be stored directly in an interface word?
+// Yes, if the representation is a single pointer.
func isdirectiface(t *Type) bool {
switch t.Etype {
case TPTR32,
n2 := c2.node.Left
// sort by type (for switches on interface)
- ct := int(n1.Val().Ctype())
- if ct > int(n2.Val().Ctype()) {
+ ct := n1.Val().Ctype()
+ if ct > n2.Val().Ctype() {
return +1
}
- if ct < int(n2.Val().Ctype()) {
+ if ct < n2.Val().Ctype() {
return -1
}
if !Eqtype(n1.Type, n2.Type) {
Esc uint16 // EscXXX
- Op uint8
+ Op Op
Nointerface bool
Ullman uint8 // sethi/ullman number
Addable bool // addressable
- Etype uint8 // op for OASOP, etype for OTYPE, exclam for export, 6g saved reg
+ Etype EType // op for OASOP, etype for OTYPE, exclam for export, 6g saved reg
Bounded bool // bounds check unnecessary
- Class uint8 // PPARAM, PAUTO, PEXTERN, etc
+ Class Class // PPARAM, PAUTO, PEXTERN, etc
Embedded uint8 // ODCLFIELD embedded type
Colas bool // OAS resulting from :=
Diag uint8 // already printed error about this
Endlineno int32
- Norace bool // func must not have race detector annotations
- Nosplit bool // func should not execute on separate stack
- Nowritebarrier bool // emit compiler error instead of write barrier
- Dupok bool // duplicate definitions ok
- Wrapper bool // is method wrapper
- Needctxt bool // function uses context register (has closure variables)
- Systemstack bool // must run on system stack
+ Norace bool // func must not have race detector annotations
+ Nosplit bool // func should not execute on separate stack
+ Noinline bool // func should not be inlined
+ Nowritebarrier bool // emit compiler error instead of write barrier
+ Nowritebarrierrec bool // error on write barrier in this or recursive callees
+ Dupok bool // duplicate definitions ok
+ Wrapper bool // is method wrapper
+ Needctxt bool // function uses context register (has closure variables)
+ Systemstack bool // must run on system stack
+
+ WBLineno int32 // line number of first write barrier
}
+type Op uint8
+
// Node ops.
const (
- OXXX = iota
+ OXXX = Op(iota)
// names
ONAME // var, const or func name
}
func (t *Type) SimpleString() string {
- return Econv(int(t.Etype), 0)
+ return Econv(t.Etype)
}
func (t *Type) Equal(u ssa.Type) bool {
"strings"
)
-/*
- * type check the whole tree of an expression.
- * calculates expression types.
- * evaluates compile time constants.
- * marks variables that escape the local frame.
- * rewrites n->op to be more specific in some cases.
- */
+// type check the whole tree of an expression.
+// calculates expression types.
+// evaluates compile time constants.
+// marks variables that escape the local frame.
+// rewrites n->op to be more specific in some cases.
var typecheckdefstack []*Node
-/*
- * resolve ONONAME to definition, if any.
- */
+// resolve ONONAME to definition, if any.
func resolve(n *Node) *Node {
if n != nil && n.Op == ONONAME && n.Sym != nil {
r := n.Sym.Def
if Isslice(t) {
return "slice"
}
- et := int(t.Etype)
- if 0 <= et && et < len(_typekind) {
+ et := t.Etype
+ if int(et) < len(_typekind) {
s := _typekind[et]
if s != "" {
return s
return n
}
-/*
- * does n contain a call or receive operation?
- */
+// does n contain a call or receive operation?
func callrecv(n *Node) bool {
if n == nil {
return false
Fatalf("typecheck %v", Oconv(int(n.Op), 0))
- /*
- * names
- */
+ // names
case OLITERAL:
ok |= Erv
case ODDD:
break
- /*
- * types (OIND is with exprs)
- */
+ // types (OIND is with exprs)
case OTYPE:
ok |= Etype
}
t := typ(TCHAN)
t.Type = l.Type
- t.Chan = n.Etype
+ // TODO(marvin): Fix Node.EType type union.
+ t.Chan = uint8(n.Etype)
n.Op = OTYPE
n.Type = t
n.Left = nil
return
}
- /*
- * type or expr
- */
+ // type or expr
case OIND:
ntop := Erv | Etype
n.Type = t.Type
break OpSwitch
- /*
- * arithmetic exprs
- */
+ // arithmetic exprs
case OASOP,
OADD,
OAND,
OSUB,
OXOR:
var l *Node
- var op int
+ var op Op
var r *Node
if n.Op == OASOP {
ok |= Etop
n.Type = nil
return
}
- op = int(n.Etype)
+ // TODO(marvin): Fix Node.EType type union.
+ op = Op(n.Etype)
} else {
ok |= Erv
l = typecheck(&n.Left, Erv|top&Eiota)
n.Type = nil
return
}
- op = int(n.Op)
+ op = n.Op
}
if op == OLSH || op == ORSH {
defaultlit(&r, Types[TUINT])
if t.Etype == TIDEAL {
t = r.Type
}
- et := int(t.Etype)
+ et := t.Etype
if et == TIDEAL {
et = TINT
}
- aop := 0
+ var aop Op = OXXX
if iscmp[n.Op] && t.Etype != TIDEAL && !Eqtype(l.Type, r.Type) {
// comparison is okay as long as one side is
// assignable to the other. convert so they have
}
converted:
- et = int(t.Etype)
+ et = t.Etype
}
if t.Etype != TIDEAL && !Eqtype(l.Type, r.Type) {
if et == TSTRING {
if iscmp[n.Op] {
- n.Etype = n.Op
+ // TODO(marvin): Fix Node.EType type union.
+ n.Etype = EType(n.Op)
n.Op = OCMPSTR
} else if n.Op == OADD {
// create OADDSTR node with list of strings in x + y + z + (w + v) + ...
} else if r.Op == OLITERAL && r.Val().Ctype() == CTNIL {
} else // leave alone for back end
if Isinter(r.Type) == Isinter(l.Type) {
- n.Etype = n.Op
+ // TODO(marvin): Fix Node.EType type union.
+ n.Etype = EType(n.Op)
n.Op = OCMPIFACE
}
}
n.Type = t
break OpSwitch
- /*
- * exprs
- */
+ // exprs
case OADDR:
ok |= Erv
}
break OpSwitch
- /*
- * call and call like
- */
+ // call and call like
case OCALL:
l := n.Left
n.Diag |= n.Left.Diag
l = n.Left
if l.Op == ONAME && l.Etype != 0 {
- if n.Isddd && l.Etype != OAPPEND {
+ // TODO(marvin): Fix Node.EType type union.
+ if n.Isddd && Op(l.Etype) != OAPPEND {
Yyerror("invalid use of ... with builtin %v", l)
}
// builtin: OLEN, OCAP, etc.
- n.Op = l.Etype
+ // TODO(marvin): Fix Node.EType type union.
+ n.Op = Op(l.Etype)
n.Left = n.Right
n.Right = nil
n.Orig = r
}
- n.Type = Types[cplxsubtype(int(t.Etype))]
+ n.Type = Types[cplxsubtype(t.Etype)]
break OpSwitch
}
return
}
var why string
- n.Op = uint8(convertop(t, n.Type, &why))
- if (n.Op) == 0 {
+ n.Op = convertop(t, n.Type, &why)
+ if n.Op == 0 {
if n.Diag == 0 && !n.Type.Broke {
Yyerror("cannot convert %v to type %v%s", Nconv(n.Left, obj.FmtLong), n.Type, why)
n.Diag = 1
typecheck(&n.Left, Erv)
break OpSwitch
- /*
- * statements
- */
+ // statements
case OAS:
ok |= Etop
}
func derefall(t *Type) *Type {
- for t != nil && int(t.Etype) == Tptr {
+ for t != nil && t.Etype == Tptr {
t = t.Type
}
return t
dowidth(tt)
rcvr := getthisx(f2.Type).Type.Type
if !Eqtype(rcvr, tt) {
- if int(rcvr.Etype) == Tptr && Eqtype(rcvr.Type, tt) {
+ if rcvr.Etype == Tptr && Eqtype(rcvr.Type, tt) {
checklvalue(n.Left, "call pointer method on")
n.Left = Nod(OADDR, n.Left, nil)
n.Left.Implicit = true
typecheck(&n.Left, Etype|Erv)
- } else if int(tt.Etype) == Tptr && int(rcvr.Etype) != Tptr && Eqtype(tt.Type, rcvr) {
+ } else if tt.Etype == Tptr && rcvr.Etype != Tptr && Eqtype(tt.Type, rcvr) {
n.Left = Nod(OIND, n.Left, nil)
n.Left.Implicit = true
typecheck(&n.Left, Etype|Erv)
- } else if int(tt.Etype) == Tptr && int(tt.Type.Etype) == Tptr && Eqtype(derefall(tt), derefall(rcvr)) {
+ } else if tt.Etype == Tptr && tt.Type.Etype == Tptr && Eqtype(derefall(tt), derefall(rcvr)) {
Yyerror("calling method %v with receiver %v requires explicit dereference", n.Right, Nconv(n.Left, obj.FmtLong))
- for int(tt.Etype) == Tptr {
+ for tt.Etype == Tptr {
// Stop one level early for method with pointer receiver.
- if int(rcvr.Etype) == Tptr && int(tt.Type.Etype) != Tptr {
+ if rcvr.Etype == Tptr && tt.Type.Etype != Tptr {
break
}
n.Left = Nod(OIND, n.Left, nil)
return false
}
+// downcount is the same as countfield
+// TODO decide if we want both (for semantic reasons)
func downcount(t *Type) int {
n := 0
for tl := t.Type; tl != nil; tl = tl.Down {
return n
}
-/*
- * typecheck assignment: type list = expression list
- */
-func typecheckaste(op int, call *Node, isddd bool, tstruct *Type, nl *NodeList, desc func() string) {
+// typecheck assignment: type list = expression list
+func typecheckaste(op Op, call *Node, isddd bool, tstruct *Type, nl *NodeList, desc func() string) {
var t *Type
var n *Node
var n1 int
goto out
}
-/*
- * type check composite
- */
+// type check composite
func fielddup(n *Node, hash map[string]bool) {
if n.Op != ONAME {
Fatalf("fielddup: not ONAME")
}
// Save original node (including n->right)
- norig := Nod(int(n.Op), nil, nil)
+ norig := Nod(n.Op, nil, nil)
*norig = *n
setlineno(n.Right)
- l := typecheck(&n.Right, Etype|Ecomplit) /* sic */
+ l := typecheck(&n.Right, Etype|Ecomplit) // sic
t := l.Type
if t == nil {
n.Type = nil
return
}
-/*
- * lvalue etc
- */
+// lvalue etc
func islvalue(n *Node) bool {
switch n.Op {
case OINDEX:
return false
}
-/*
- * type check assignment.
- * if this assignment is the definition of a var on the left side,
- * fill in the var's type.
- */
+// type check assignment.
+// if this assignment is the definition of a var on the left side,
+// fill in the var's type.
func typecheckas(n *Node) {
// delicate little dance.
// the definition of n may refer to this assignment
}
}
-/*
- * type check function definition
- */
+// type check function definition
func typecheckfunc(n *Node) {
typecheck(&n.Func.Nname, Erv|Easgn)
t := n.Func.Nname.Type
import "cmd/internal/obj"
-/*
- * look for
- * unsafe.Sizeof
- * unsafe.Offsetof
- * unsafe.Alignof
- * rewrite with a constant
- */
+// look for
+// unsafe.Sizeof
+// unsafe.Offsetof
+// unsafe.Alignof
+// rewrite with a constant
func unsafenmagic(nn *Node) *Node {
fn := nn.Left
args := nn.List
"os"
"runtime"
"runtime/pprof"
- "strconv"
)
func (n *Node) Line() string {
return Ctxt.LineHist.LineString(int(n.Lineno))
}
-func atoi(s string) int {
- // NOTE: Not strconv.Atoi, accepts hex and octal prefixes.
- n, _ := strconv.ParseInt(s, 0, 0)
- return int(n)
-}
-
var atExitFuncs []func()
func AtExit(f func()) {
walkprintfunc(&n.Left, &n.Ninit)
case OCOPY:
- n.Left = copyany(n.Left, &n.Ninit, 1)
+ n.Left = copyany(n.Left, &n.Ninit, true)
default:
walkexpr(&n.Left, &n.Ninit)
walkprintfunc(&n.Left, &n.Ninit)
case OCOPY:
- n.Left = copyany(n.Left, &n.Ninit, 1)
+ n.Left = copyany(n.Left, &n.Ninit, true)
default:
walkexpr(&n.Left, &n.Ninit)
// so that reorder3 can fix up conflicts
var rl *NodeList
- var cl uint8
+ var cl Class
for ll := Curfn.Func.Dcl; ll != nil; ll = ll.Next {
cl = ll.N.Class &^ PHEAP
if cl == PAUTO {
if f.Op != OCALLFUNC && f.Op != OCALLMETH && f.Op != OCALLINTER {
Fatalf("expected return of call, have %v", f)
}
- n.List = concat(list1(f), ascompatet(int(n.Op), rl, &f.Type, 0, &n.Ninit))
+ n.List = concat(list1(f), ascompatet(n.Op, rl, &f.Type, 0, &n.Ninit))
break
}
// move function calls out, to make reorder3's job easier.
walkexprlistsafe(n.List, &n.Ninit)
- ll := ascompatee(int(n.Op), rl, n.List, &n.Ninit)
+ ll := ascompatee(n.Op, rl, n.List, &n.Ninit)
n.List = reorder3(ll)
break
}
- ll := ascompatte(int(n.Op), nil, false, Getoutarg(Curfn.Type), n.List, 1, &n.Ninit)
+ ll := ascompatte(n.Op, nil, false, Getoutarg(Curfn.Type), n.List, 1, &n.Ninit)
n.List = ll
case ORETJMP:
return Smallintconst(l) && Smallintconst(r) && (t.Type.Width == 0 || Mpgetfix(r.Val().U.(*Mpint)) < (1<<16)/t.Type.Width)
}
-/*
- * walk the whole tree of the body of an
- * expression or simple statement.
- * the types expressions are calculated.
- * compile-time constants are evaluated.
- * complex side effects like statements are appended to init
- */
+// walk the whole tree of the body of an
+// expression or simple statement.
+// the types expressions are calculated.
+// compile-time constants are evaluated.
+// complex side effects like statements are appended to init
func walkexprlist(l *NodeList, init **NodeList) {
for ; l != nil; l = l.Next {
walkexpr(&l.N, init)
Fatalf("missed typecheck: %v\n", Nconv(n, obj.FmtSign))
}
+opswitch:
switch n.Op {
default:
Dump("walk", n)
OEMPTY,
OPARAM,
OGETG:
- goto ret
case ONOT,
OMINUS,
ODOTMETH,
ODOTINTER:
walkexpr(&n.Left, init)
- goto ret
case OIND:
walkexpr(&n.Left, init)
- goto ret
case ODOT:
usefield(n)
walkexpr(&n.Left, init)
- goto ret
case ODOTPTR:
usefield(n)
}
walkexpr(&n.Left, init)
- goto ret
case OEFACE:
walkexpr(&n.Left, init)
walkexpr(&n.Right, init)
- goto ret
case OSPTR, OITAB:
walkexpr(&n.Left, init)
- goto ret
case OLEN, OCAP:
walkexpr(&n.Left, init)
n.Typecheck = 1
}
- goto ret
-
case OLSH, ORSH:
walkexpr(&n.Left, init)
walkexpr(&n.Right, init)
if Debug['m'] != 0 && n.Etype != 0 && !Isconst(n.Right, CTINT) {
Warn("shift bounds check elided")
}
- goto ret
// Use results from call expression as arguments for complex.
case OAND,
walkexpr(&n.Left, init)
walkexpr(&n.Right, init)
- goto ret
case OOR, OXOR:
walkexpr(&n.Left, init)
walkexpr(&n.Right, init)
walkrotate(&n)
- goto ret
case OEQ, ONE:
walkexpr(&n.Left, init)
safemode = 0
walkcompare(&n, init)
safemode = old_safemode
- goto ret
case OANDAND, OOROR:
walkexpr(&n.Left, init)
walkexpr(&n.Right, &ll)
addinit(&n.Right, ll)
- goto ret
case OPRINT, OPRINTN:
walkexprlist(n.List, init)
n = walkprint(n, init)
- goto ret
case OPANIC:
n = mkcall("gopanic", nil, init, n.Left)
- goto ret
case ORECOVER:
n = mkcall("gorecover", n.Type, init, Nod(OADDR, nodfp, nil))
- goto ret
case OLITERAL:
n.Addable = true
- goto ret
case OCLOSUREVAR, OCFUNC:
n.Addable = true
- goto ret
case ONAME:
if n.Class&PHEAP == 0 && n.Class != PPARAMREF {
n.Addable = true
}
- goto ret
case OCALLINTER:
t := n.Left.Type
if n.List != nil && n.List.N.Op == OAS {
- goto ret
+ break
}
walkexpr(&n.Left, init)
walkexprlist(n.List, init)
- ll := ascompatte(int(n.Op), n, n.Isddd, getinarg(t), n.List, 0, init)
+ ll := ascompatte(n.Op, n, n.Isddd, getinarg(t), n.List, 0, init)
n.List = reorder1(ll)
- goto ret
case OCALLFUNC:
if n.Left.Op == OCLOSURE {
t := n.Left.Type
if n.List != nil && n.List.N.Op == OAS {
- goto ret
+ break
}
walkexpr(&n.Left, init)
n.Op = OSQRT
n.Left = n.List.N
n.List = nil
- goto ret
+ break opswitch
}
}
- ll := ascompatte(int(n.Op), n, n.Isddd, getinarg(t), n.List, 0, init)
+ ll := ascompatte(n.Op, n, n.Isddd, getinarg(t), n.List, 0, init)
n.List = reorder1(ll)
- goto ret
case OCALLMETH:
t := n.Left.Type
if n.List != nil && n.List.N.Op == OAS {
- goto ret
+ break
}
walkexpr(&n.Left, init)
walkexprlist(n.List, init)
- ll := ascompatte(int(n.Op), n, false, getthis(t), list1(n.Left.Left), 0, init)
- lr := ascompatte(int(n.Op), n, n.Isddd, getinarg(t), n.List, 0, init)
+ ll := ascompatte(n.Op, n, false, getthis(t), list1(n.Left.Left), 0, init)
+ lr := ascompatte(n.Op, n, n.Isddd, getinarg(t), n.List, 0, init)
ll = concat(ll, lr)
n.Left.Left = nil
ullmancalc(n.Left)
n.List = reorder1(ll)
- goto ret
case OAS:
*init = concat(*init, n.Ninit)
n.Left = safeexpr(n.Left, init)
if oaslit(n, init) {
- goto ret
+ break
}
- if n.Right == nil || iszero(n.Right) && flag_race == 0 {
- goto ret
+ if n.Right == nil || iszero(n.Right) && !instrumenting {
+ break
}
switch n.Right.Op {
// TODO(rsc): The Isfat is for consistency with componentgen and orderexpr.
// It needs to be removed in all three places.
// That would allow inlining x.(struct{*int}) the same as x.(*int).
- if isdirectiface(n.Right.Type) && !Isfat(n.Right.Type) && flag_race == 0 {
+ if isdirectiface(n.Right.Type) && !Isfat(n.Right.Type) && !instrumenting {
// handled directly during cgen
walkexpr(&n.Right, init)
break
n = mkcall1(fn, nil, init, typename(r.Type), r.Left, n1)
walkexpr(&n, init)
- goto ret
+ break opswitch
case ORECV:
// x = <-c; n.Left is x, n.Right.Left is c.
r := n.Right.Left // the channel
n = mkcall1(chanfn("chanrecv1", 2, r.Type), nil, init, typename(r.Type), r, n1)
walkexpr(&n, init)
- goto ret
+ break opswitch
case OAPPEND:
// x = append(...)
if r.Op == OAPPEND {
// Left in place for back end.
// Do not add a new write barrier.
- goto ret
+ break opswitch
}
// Otherwise, lowered for race detector.
// Treat as ordinary assignment.
n = applywritebarrier(n, init)
}
- goto ret
-
case OAS2:
*init = concat(*init, n.Ninit)
n.Ninit = nil
lr.N = applywritebarrier(lr.N, init)
}
n = liststmt(ll)
- goto ret
// a,b,... = fn()
case OAS2FUNC:
walkexprlistsafe(n.List, init)
walkexpr(&r, init)
- ll := ascompatet(int(n.Op), n.List, &r.Type, 0, init)
+ ll := ascompatet(n.Op, n.List, &r.Type, 0, init)
for lr := ll; lr != nil; lr = lr.Next {
lr.N = applywritebarrier(lr.N, init)
}
n = liststmt(concat(list1(r), ll))
- goto ret
// x, y = <-c
// orderstmt made sure x is addressable.
r = mkcall1(fn, n.List.Next.N.Type, init, typename(r.Left.Type), r.Left, n1)
n = Nod(OAS, n.List.Next.N, r)
typecheck(&n, Etop)
- goto ret
// a,b = m[i];
case OAS2MAPR:
walkexpr(&n, init)
// TODO: ptr is always non-nil, so disable nil check for this OIND op.
- goto ret
case ODELETE:
*init = concat(*init, n.Ninit)
t := map_.Type
n = mkcall1(mapfndel("mapdelete", t), nil, init, typename(t), map_, key)
- goto ret
case OAS2DOTTYPE:
e := n.Rlist.N // i.(T)
// TODO(rsc): The Isfat is for consistency with componentgen and orderexpr.
// It needs to be removed in all three places.
// That would allow inlining x.(struct{*int}) the same as x.(*int).
- if isdirectiface(e.Type) && !Isfat(e.Type) && flag_race == 0 {
+ if isdirectiface(e.Type) && !Isfat(e.Type) && !instrumenting {
// handled directly during gen.
walkexprlistsafe(n.List, init)
walkexpr(&e.Left, init)
- goto ret
+ break
}
// res, ok = i.(T)
}
n = Nod(OAS, ok, fast)
typecheck(&n, Etop)
- goto ret
+ break
}
}
call := mkcall1(fn, oktype, init, typename(t), from, resptr)
n = Nod(OAS, ok, call)
typecheck(&n, Etop)
- goto ret
case ODOTTYPE, ODOTTYPE2:
if !isdirectiface(n.Type) || Isfat(n.Type) {
Fatalf("walkexpr ODOTTYPE") // should see inside OAS only
}
walkexpr(&n.Left, init)
- goto ret
case OCONVIFACE:
walkexpr(&n.Left, init)
l.Type = n.Type
l.Typecheck = n.Typecheck
n = l
- goto ret
+ break
}
// Build name of function: convI2E etc.
ll = list(ll, l)
if isdirectiface(n.Left.Type) {
- /* For pointer types, we can make a special form of optimization
- *
- * These statements are put onto the expression init list:
- * Itab *tab = atomicloadtype(&cache);
- * if(tab == nil)
- * tab = typ2Itab(type, itype, &cache);
- *
- * The CONVIFACE expression is replaced with this:
- * OEFACE{tab, ptr};
- */
+ // For pointer types, we can make a special form of optimization
+ //
+ // These statements are put onto the expression init list:
+ // Itab *tab = atomicloadtype(&cache);
+ // if(tab == nil)
+ // tab = typ2Itab(type, itype, &cache);
+ //
+ // The CONVIFACE expression is replaced with this:
+ // OEFACE{tab, ptr};
l := temp(Ptrto(Types[TUINT8]))
n1 := Nod(OAS, l, sym.Def)
l.Typecheck = n.Typecheck
l.Type = n.Type
n = l
- goto ret
+ break
}
}
n.List = ll
typecheck(&n, Erv)
walkexpr(&n, init)
- goto ret
case OCONV, OCONVNOP:
if Thearch.Thechar == '5' {
if Isfloat[n.Left.Type.Etype] {
if n.Type.Etype == TINT64 {
n = mkcall("float64toint64", n.Type, init, conv(n.Left, Types[TFLOAT64]))
- goto ret
+ break
}
if n.Type.Etype == TUINT64 {
n = mkcall("float64touint64", n.Type, init, conv(n.Left, Types[TFLOAT64]))
- goto ret
+ break
}
}
if Isfloat[n.Type.Etype] {
if n.Left.Type.Etype == TINT64 {
n = mkcall("int64tofloat64", n.Type, init, conv(n.Left, Types[TINT64]))
- goto ret
+ break
}
if n.Left.Type.Etype == TUINT64 {
n = mkcall("uint64tofloat64", n.Type, init, conv(n.Left, Types[TUINT64]))
- goto ret
+ break
}
}
}
walkexpr(&n.Left, init)
- goto ret
case OANDNOT:
walkexpr(&n.Left, init)
n.Right = Nod(OCOM, n.Right, nil)
typecheck(&n.Right, Erv)
walkexpr(&n.Right, init)
- goto ret
case OMUL:
walkexpr(&n.Left, init)
walkexpr(&n.Right, init)
walkmul(&n, init)
- goto ret
case ODIV, OMOD:
walkexpr(&n.Left, init)
walkexpr(&n.Right, init)
- /*
- * rewrite complex div into function call.
- */
- et := int(n.Left.Type.Etype)
+ // rewrite complex div into function call.
+ et := n.Left.Type.Etype
if Iscomplex[et] && n.Op == ODIV {
t := n.Type
n = mkcall("complex128div", Types[TCOMPLEX128], init, conv(n.Left, Types[TCOMPLEX128]), conv(n.Right, Types[TCOMPLEX128]))
n = conv(n, t)
- goto ret
+ break
}
// Nothing to do for float divisions.
if Isfloat[et] {
- goto ret
+ break
}
// Try rewriting as shifts or magic multiplies.
walkdiv(&n, init)
- /*
- * rewrite 64-bit div and mod into function calls
- * on 32-bit architectures.
- */
+ // rewrite 64-bit div and mod into function calls
+ // on 32-bit architectures.
switch n.Op {
case OMOD, ODIV:
if Widthreg >= 8 || (et != TUINT64 && et != TINT64) {
- goto ret
+ break opswitch
}
var fn string
if et == TINT64 {
fn += "mod"
}
n = mkcall(fn, n.Type, init, conv(n.Left, Types[et]), conv(n.Right, Types[et]))
-
- default:
- break
}
- goto ret
-
case OINDEX:
walkexpr(&n.Left, init)
// if range of type cannot exceed static array bound,
// disable bounds check.
if n.Bounded {
- goto ret
+ break
}
t := n.Left.Type
if t != nil && Isptr[t.Etype] {
Yyerror("index out of bounds")
}
}
- goto ret
case OINDEXMAP:
if n.Etype == 1 {
- goto ret
+ break
}
walkexpr(&n.Left, init)
walkexpr(&n.Right, init)
n.Type = t.Type
n.Typecheck = 1
- goto ret
-
case ORECV:
Fatalf("walkexpr ORECV") // should see inside OAS only
}
walkexpr(&n.Right.Right, init)
n = reduceSlice(n)
- goto ret
case OSLICE3, OSLICE3ARR:
walkexpr(&n.Left, init)
n.Op = OSLICEARR
}
n = reduceSlice(n)
- goto ret
}
- goto ret
case OADDR:
walkexpr(&n.Left, init)
- goto ret
case ONEW:
if n.Esc == EscNone {
n = callnew(n.Type.Type)
}
- goto ret
-
// If one argument to the comparison is an empty string,
// comparing the lengths instead will yield the same result
// without the function call.
case OCMPSTR:
if (Isconst(n.Left, CTSTR) && len(n.Left.Val().U.(string)) == 0) || (Isconst(n.Right, CTSTR) && len(n.Right.Val().U.(string)) == 0) {
- r := Nod(int(n.Etype), Nod(OLEN, n.Left, nil), Nod(OLEN, n.Right, nil))
+ // TODO(marvin): Fix Node.EType type union.
+ r := Nod(Op(n.Etype), Nod(OLEN, n.Left, nil), Nod(OLEN, n.Right, nil))
typecheck(&r, Erv)
walkexpr(&r, init)
r.Type = n.Type
n = r
- goto ret
+ break
}
// s + "badgerbadgerbadger" == "badgerbadgerbadger"
- if (n.Etype == OEQ || n.Etype == ONE) && Isconst(n.Right, CTSTR) && n.Left.Op == OADDSTR && count(n.Left.List) == 2 && Isconst(n.Left.List.Next.N, CTSTR) && strlit(n.Right) == strlit(n.Left.List.Next.N) {
- r := Nod(int(n.Etype), Nod(OLEN, n.Left.List.N, nil), Nodintconst(0))
+ if (Op(n.Etype) == OEQ || Op(n.Etype) == ONE) && Isconst(n.Right, CTSTR) && n.Left.Op == OADDSTR && count(n.Left.List) == 2 && Isconst(n.Left.List.Next.N, CTSTR) && strlit(n.Right) == strlit(n.Left.List.Next.N) {
+ // TODO(marvin): Fix Node.EType type union.
+ r := Nod(Op(n.Etype), Nod(OLEN, n.Left.List.N, nil), Nodintconst(0))
typecheck(&r, Erv)
walkexpr(&r, init)
r.Type = n.Type
n = r
- goto ret
+ break
}
var r *Node
- if n.Etype == OEQ || n.Etype == ONE {
+ // TODO(marvin): Fix Node.EType type union.
+ if Op(n.Etype) == OEQ || Op(n.Etype) == ONE {
// prepare for rewrite below
n.Left = cheapexpr(n.Left, init)
// quick check of len before full compare for == or !=
// eqstring assumes that the lengths are equal
- if n.Etype == OEQ {
+ // TODO(marvin): Fix Node.EType type union.
+ if Op(n.Etype) == OEQ {
// len(left) == len(right) && eqstring(left, right)
r = Nod(OANDAND, Nod(OEQ, Nod(OLEN, n.Left, nil), Nod(OLEN, n.Right, nil)), r)
} else {
// sys_cmpstring(s1, s2) :: 0
r = mkcall("cmpstring", Types[TINT], init, conv(n.Left, Types[TSTRING]), conv(n.Right, Types[TSTRING]))
- r = Nod(int(n.Etype), r, Nodintconst(0))
+ // TODO(marvin): Fix Node.EType type union.
+ r = Nod(Op(n.Etype), r, Nodintconst(0))
}
typecheck(&r, Erv)
}
r.Type = n.Type
n = r
- goto ret
case OADDSTR:
n = addstr(n, init)
- goto ret
case OAPPEND:
// order should make sure we only see OAS(node, OAPPEND), which we handle above.
Fatalf("append outside assignment")
case OCOPY:
- n = copyany(n, init, flag_race)
- goto ret
+ n = copyany(n, init, instrumenting)
// cannot use chanfn - closechan takes any, not chan any
case OCLOSE:
substArgTypes(fn, n.Left.Type)
n = mkcall1(fn, nil, init, n.Left)
- goto ret
case OMAKECHAN:
n = mkcall1(chanfn("makechan", 1, n.Type), n.Type, init, typename(n.Type), conv(n.Left, Types[TINT64]))
- goto ret
case OMAKEMAP:
t := n.Type
substArgTypes(fn, hmap(t), mapbucket(t), t.Down, t.Type)
n = mkcall1(fn, n.Type, init, typename(n.Type), conv(n.Left, Types[TINT64]), a, r)
- goto ret
case OMAKESLICE:
l := n.Left
n = mkcall1(fn, n.Type, init, typename(n.Type), conv(l, Types[TINT64]), conv(r, Types[TINT64]))
}
- goto ret
-
case ORUNESTR:
a := nodnil()
if n.Esc == EscNone {
// intstring(*[4]byte, rune)
n = mkcall("intstring", n.Type, init, a, conv(n.Left, Types[TINT64]))
- goto ret
-
case OARRAYBYTESTR:
a := nodnil()
if n.Esc == EscNone {
// slicebytetostring(*[32]byte, []byte) string;
n = mkcall("slicebytetostring", n.Type, init, a, n.Left)
- goto ret
-
// slicebytetostringtmp([]byte) string;
case OARRAYBYTESTRTMP:
n = mkcall("slicebytetostringtmp", n.Type, init, n.Left)
- goto ret
-
// slicerunetostring(*[32]byte, []rune) string;
case OARRAYRUNESTR:
a := nodnil()
}
n = mkcall("slicerunetostring", n.Type, init, a, n.Left)
- goto ret
// stringtoslicebyte(*32[byte], string) []byte;
case OSTRARRAYBYTE:
}
n = mkcall("stringtoslicebyte", n.Type, init, a, conv(n.Left, Types[TSTRING]))
- goto ret
// stringtoslicebytetmp(string) []byte;
case OSTRARRAYBYTETMP:
n = mkcall("stringtoslicebytetmp", n.Type, init, conv(n.Left, Types[TSTRING]))
- goto ret
-
// stringtoslicerune(*[32]rune, string) []rune
case OSTRARRAYRUNE:
a := nodnil()
}
n = mkcall("stringtoslicerune", n.Type, init, a, n.Left)
- goto ret
// ifaceeq(i1 any-1, i2 any-2) (ret bool);
case OCMPIFACE:
n.Left = cheapexpr(n.Left, init)
substArgTypes(fn, n.Right.Type, n.Left.Type)
r := mkcall1(fn, n.Type, init, n.Left, n.Right)
- if n.Etype == ONE {
+ // TODO(marvin): Fix Node.EType type union.
+ if Op(n.Etype) == ONE {
r = Nod(ONOT, r, nil)
}
// check itable/type before full compare.
- if n.Etype == OEQ {
+ // TODO(marvin): Fix Node.EType type union.
+ if Op(n.Etype) == OEQ {
r = Nod(OANDAND, Nod(OEQ, Nod(OITAB, n.Left, nil), Nod(OITAB, n.Right, nil)), r)
} else {
r = Nod(OOROR, Nod(ONE, Nod(OITAB, n.Left, nil), Nod(OITAB, n.Right, nil)), r)
walkexpr(&r, init)
r.Type = n.Type
n = r
- goto ret
case OARRAYLIT, OMAPLIT, OSTRUCTLIT, OPTRLIT:
var_ := temp(n.Type)
anylit(0, n, var_, init)
n = var_
- goto ret
case OSEND:
n1 := n.Right
walkexpr(&n1, init)
n1 = Nod(OADDR, n1, nil)
n = mkcall1(chanfn("chansend1", 2, n.Left.Type), nil, init, typename(n.Left.Type), n.Left, n1)
- goto ret
case OCLOSURE:
n = walkclosure(n, init)
- goto ret
case OCALLPART:
n = walkpartialcall(n, init)
- goto ret
}
- Fatalf("missing switch %v", Oconv(int(n.Op), 0))
-
// Expressions that are constant at run time but not
// considered const by the language spec are not turned into
// constants until walk. For example, if n is y%1 == 0, the
// walk of y%1 may have replaced it by 0.
// Check whether n with its updated args is itself now a constant.
-ret:
t := n.Type
evconst(n)
return n
}
-func ascompatee1(op int, l *Node, r *Node, init **NodeList) *Node {
+func ascompatee1(op Op, l *Node, r *Node, init **NodeList) *Node {
// convas will turn map assigns into function calls,
// making it impossible for reorder3 to work.
n := Nod(OAS, l, r)
return convas(n, init)
}
-func ascompatee(op int, nl *NodeList, nr *NodeList, init **NodeList) *NodeList {
- /*
- * check assign expression list to
- * a expression list. called in
- * expr-list = expr-list
- */
+func ascompatee(op Op, nl *NodeList, nr *NodeList, init **NodeList) *NodeList {
+ // check assign expression list to
+ // a expression list. called in
+ // expr-list = expr-list
// ensure order of evaluation for function calls
for ll := nl; ll != nil; ll = ll.Next {
return nn
}
-/*
- * l is an lv and rt is the type of an rv
- * return 1 if this implies a function call
- * evaluating the lv or a function call
- * in the conversion of the types
- */
+// l is an lv and rt is the type of an rv
+// return 1 if this implies a function call
+// evaluating the lv or a function call
+// in the conversion of the types
func fncall(l *Node, rt *Type) bool {
if l.Ullman >= UINF || l.Op == OINDEXMAP {
return true
return true
}
-func ascompatet(op int, nl *NodeList, nr **Type, fp int, init **NodeList) *NodeList {
+func ascompatet(op Op, nl *NodeList, nr **Type, fp int, init **NodeList) *NodeList {
var l *Node
var tmp *Node
var a *Node
var ll *NodeList
var saver Iter
- /*
- * check assign type list to
- * a expression list. called in
- * expr-list = func()
- */
+ // check assign type list to
+ // a expression list. called in
+ // expr-list = func()
r := Structfirst(&saver, nr)
var nn *NodeList
return concat(nn, mm)
}
-/*
-* package all the arguments that match a ... T parameter into a []T.
- */
+// package all the arguments that match a ... T parameter into a []T.
func mkdotargslice(lr0 *NodeList, nn *NodeList, l *Type, fp int, init **NodeList, ddd *Node) *NodeList {
esc := uint16(EscUnknown)
if ddd != nil {
return nn
}
-/*
- * helpers for shape errors
- */
+// helpers for shape errors
func dumptypes(nl **Type, what string) string {
var savel Iter
return fmt_
}
-/*
- * check assign expression list to
- * a type list. called in
- * return expr-list
- * func(expr-list)
- */
-func ascompatte(op int, call *Node, isddd bool, nl **Type, lr *NodeList, fp int, init **NodeList) *NodeList {
+// check assign expression list to
+// a type list. called in
+// return expr-list
+// func(expr-list)
+func ascompatte(op Op, call *Node, isddd bool, nl **Type, lr *NodeList, fp int, init **NodeList) *NodeList {
var savel Iter
lr0 := lr
var n *Node
var on *Node
var t *Type
- var et int
+ var et EType
- op := int(nn.Op)
+ op := nn.Op
all := nn.List
var calls *NodeList
notfirst := false
}
t = n.Type
- et = int(n.Type.Etype)
+ et = n.Type.Etype
if Isinter(n.Type) {
if isnilinter(n.Type) {
on = syslook("printeface", 1)
return n
}
-/*
- * from ascompat[te]
- * evaluating actual function arguments.
- * f(a,b)
- * if there is exactly one function expr,
- * then it is done first. otherwise must
- * make temp variables
- */
+// from ascompat[te]
+// evaluating actual function arguments.
+// f(a,b)
+// if there is exactly one function expr,
+// then it is done first. otherwise must
+// make temp variables
func reorder1(all *NodeList) *NodeList {
var n *Node
return concat(g, r)
}
-/*
- * from ascompat[ee]
- * a,b = c,d
- * simultaneous assignment. there cannot
- * be later use of an earlier lvalue.
- *
- * function calls have been removed.
- */
+// from ascompat[ee]
+// a,b = c,d
+// simultaneous assignment. there cannot
+// be later use of an earlier lvalue.
+//
+// function calls have been removed.
func reorder3(all *NodeList) *NodeList {
var l *Node
return concat(early, all)
}
-/*
- * if the evaluation of *np would be affected by the
- * assignments in all up to but not including stop,
- * copy into a temporary during *early and
- * replace *np with that temp.
- */
+// if the evaluation of *np would be affected by the
+// assignments in all up to but not including stop,
+// copy into a temporary during *early and
+// replace *np with that temp.
func reorder3save(np **Node, all *NodeList, stop *NodeList, early **NodeList) {
n := *np
if !aliased(n, all, stop) {
*np = q.Left
}
-/*
- * what's the outer value that a write to n affects?
- * outer value means containing struct or array.
- */
+// what's the outer value that a write to n affects?
+// outer value means containing struct or array.
func outervalue(n *Node) *Node {
for {
if n.Op == OXDOT {
return n
}
-/*
- * Is it possible that the computation of n might be
- * affected by writes in as up to but not including stop?
- */
+// Is it possible that the computation of n might be
+// affected by writes in as up to but not including stop?
func aliased(n *Node, all *NodeList, stop *NodeList) bool {
if n == nil {
return false
return true
}
-/*
- * does the evaluation of n only refer to variables
- * whose addresses have not been taken?
- * (and no other memory)
- */
+// does the evaluation of n only refer to variables
+// whose addresses have not been taken?
+// (and no other memory)
func varexpr(n *Node) bool {
if n == nil {
return true
return false
}
-/*
- * is the name l mentioned in r?
- */
+// is the name l mentioned in r?
func vmatch2(l *Node, r *Node) bool {
if r == nil {
return false
return false
}
-/*
- * is any name mentioned in l also mentioned in r?
- * called by sinit.go
- */
+// is any name mentioned in l also mentioned in r?
+// called by sinit.go
func vmatch1(l *Node, r *Node) bool {
- /*
- * isolate all left sides
- */
+ // isolate all left sides
if l == nil || r == nil {
return false
}
return false
}
-/*
- * walk through argin parameters.
- * generate and return code to allocate
- * copies of escaped parameters to the heap.
- */
+// walk through argin parameters.
+// generate and return code to allocate
+// copies of escaped parameters to the heap.
func paramstoheap(argin **Type, out int) *NodeList {
var savet Iter
var v *Node
return nn
}
-/*
- * walk through argout parameters copying back to stack
- */
+// walk through argout parameters copying back to stack
func returnsfromheap(argin **Type) *NodeList {
var savet Iter
var v *Node
return nn
}
-/*
- * take care of migrating any function in/out args
- * between the stack and the heap. adds code to
- * curfn's before and after lists.
- */
+// take care of migrating any function in/out args
+// between the stack and the heap. adds code to
+// curfn's before and after lists.
func heapmoves() {
lno := lineno
lineno = Curfn.Lineno
substArgTypes(fn, l1.Type, l2.Type)
nt := mkcall1(fn, Types[TINT], &l, typename(l1.Type.Type), nptr1, nptr2)
l = list(l, nt)
- } else if flag_race != 0 {
+ } else if instrumenting {
// rely on runtime to instrument copy.
// copy(s[len(l1):len(l1)+len(l2)], l2)
nptr1 := Nod(OSLICE, s, Nod(OKEY, Nod(OLEN, l1, nil), Nod(OADD, Nod(OLEN, l1, nil), Nod(OLEN, l2, nil))))
}
// General case, with no function calls left as arguments.
- // Leave for gen, except that race detector requires old form
- if flag_race == 0 {
+ // Leave for gen, except that instrumentation requires old form.
+ if !instrumenting {
return n
}
//
// Also works if b is a string.
//
-func copyany(n *Node, init **NodeList, runtimecall int) *Node {
+func copyany(n *Node, init **NodeList, runtimecall bool) *Node {
if haspointers(n.Left.Type.Type) {
fn := writebarrierfn("typedslicecopy", n.Left.Type, n.Right.Type)
return mkcall1(fn, n.Type, init, typename(n.Left.Type.Type), n.Left, n.Right)
}
- if runtimecall != 0 {
+ if runtimecall {
var fn *Node
if n.Right.Type.Etype == TSTRING {
fn = syslook("slicestringcopy", 1)
typecheck(&a, Etop)
*init = list(*init, a)
- andor := OANDAND
+ var andor Op = OANDAND
if n.Op == ONE {
andor = OOROR
}
for i := 0; int64(i) < t.Bound; i++ {
li = Nod(OINDEX, l, Nodintconst(int64(i)))
ri = Nod(OINDEX, r, Nodintconst(int64(i)))
- a = Nod(int(n.Op), li, ri)
+ a = Nod(n.Op, li, ri)
if expr == nil {
expr = a
} else {
}
li = Nod(OXDOT, l, newname(t1.Sym))
ri = Nod(OXDOT, r, newname(t1.Sym))
- a = Nod(int(n.Op), li, ri)
+ a = Nod(n.Op, li, ri)
if expr == nil {
expr = a
} else {
}
func walkrotate(np **Node) {
- if Thearch.Thechar == '7' || Thearch.Thechar == '9' {
+ if Thearch.Thechar == '0' || Thearch.Thechar == '7' || Thearch.Thechar == '9' {
return
}
return
}
-/*
- * walkmul rewrites integer multiplication by powers of two as shifts.
- */
+// walkmul rewrites integer multiplication by powers of two as shifts.
func walkmul(np **Node, init **NodeList) {
n := *np
if !Isint[n.Type.Etype] {
*np = n
}
-/*
- * walkdiv rewrites division by a constant as less expensive
- * operations.
- */
+// walkdiv rewrites division by a constant as less expensive
+// operations.
func walkdiv(np **Node, init **NodeList) {
// if >= 0, nr is 1<<pow // 1 if nr is negative.
// TODO(minux)
- if Thearch.Thechar == '7' || Thearch.Thechar == '9' {
+ if Thearch.Thechar == '0' || Thearch.Thechar == '7' || Thearch.Thechar == '9' {
return
}
Curfn = nil
funchdr(fn)
- a = Nod(int(n.Op), nil, nil)
+ a = Nod(n.Op, nil, nil)
a.List = printargs
typecheck(&a, Etop)
walkstmt(&a)
const yyErrCode = 2
const yyMaxDepth = 200
-//line go.y:2308
+//line go.y:2317
func fixlbrace(lbr int) {
// If the opening brace was an LBODY,
// set up for another one now that we're done.
break
}
if my.Name == "init" {
+ lineno = int32(yyDollar[1].i)
Yyerror("cannot import package as init - init must be a func")
break
}
}
case 12:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:272
+ //line go.y:273
{
// When an invalid import path is passed to importfile,
// it calls Yyerror and then sets up a fake import with
}
case 15:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:288
+ //line go.y:289
{
// import with original name
yyVAL.i = parserline()
}
case 16:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:295
+ //line go.y:296
{
// import with given name
yyVAL.i = parserline()
}
case 17:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:302
+ //line go.y:303
{
// import into my name space
yyVAL.i = parserline()
}
case 18:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:311
+ //line go.y:312
{
if importpkg.Name == "" {
importpkg.Name = yyDollar[2].sym.Name
} else if importpkg.Name != yyDollar[2].sym.Name {
Yyerror("conflicting names %s and %s for package %q", importpkg.Name, yyDollar[2].sym.Name, importpkg.Path)
}
- importpkg.Direct = true
+ if incannedimport == 0 {
+ importpkg.Direct = true
+ }
importpkg.Safe = curio.importsafe
if safemode != 0 && !curio.importsafe {
}
case 20:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:328
+ //line go.y:331
{
if yyDollar[1].sym.Name == "safe" {
curio.importsafe = true
}
case 21:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:335
+ //line go.y:338
{
defercheckwidth()
}
case 22:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:339
+ //line go.y:342
{
resumecheckwidth()
unimportfile()
}
case 23:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:348
+ //line go.y:351
{
Yyerror("empty top-level declaration")
yyVAL.list = nil
}
case 25:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:354
+ //line go.y:357
{
yyVAL.list = list1(yyDollar[1].node)
}
case 26:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:358
+ //line go.y:361
{
Yyerror("non-declaration statement outside function body")
yyVAL.list = nil
}
case 27:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:363
+ //line go.y:366
{
yyVAL.list = nil
}
case 28:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:369
+ //line go.y:372
{
yyVAL.list = yyDollar[2].list
}
case 29:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:373
+ //line go.y:376
{
yyVAL.list = yyDollar[3].list
}
case 30:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:377
+ //line go.y:380
{
yyVAL.list = nil
}
case 31:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:381
+ //line go.y:384
{
yyVAL.list = yyDollar[2].list
iota_ = -100000
}
case 32:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:387
+ //line go.y:390
{
yyVAL.list = yyDollar[3].list
iota_ = -100000
}
case 33:
yyDollar = yyS[yypt-7 : yypt+1]
- //line go.y:393
+ //line go.y:396
{
yyVAL.list = concat(yyDollar[3].list, yyDollar[5].list)
iota_ = -100000
}
case 34:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:399
+ //line go.y:402
{
yyVAL.list = nil
iota_ = -100000
}
case 35:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:404
+ //line go.y:407
{
yyVAL.list = list1(yyDollar[2].node)
}
case 36:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:408
+ //line go.y:411
{
yyVAL.list = yyDollar[3].list
}
case 37:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:412
+ //line go.y:415
{
yyVAL.list = nil
}
case 38:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:418
+ //line go.y:421
{
iota_ = 0
}
case 39:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:424
+ //line go.y:427
{
yyVAL.list = variter(yyDollar[1].list, yyDollar[2].node, nil)
}
case 40:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:428
+ //line go.y:431
{
yyVAL.list = variter(yyDollar[1].list, yyDollar[2].node, yyDollar[4].list)
}
case 41:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:432
+ //line go.y:435
{
yyVAL.list = variter(yyDollar[1].list, nil, yyDollar[3].list)
}
case 42:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:438
+ //line go.y:441
{
yyVAL.list = constiter(yyDollar[1].list, yyDollar[2].node, yyDollar[4].list)
}
case 43:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:442
+ //line go.y:445
{
yyVAL.list = constiter(yyDollar[1].list, nil, yyDollar[3].list)
}
case 45:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:449
+ //line go.y:452
{
yyVAL.list = constiter(yyDollar[1].list, yyDollar[2].node, nil)
}
case 46:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:453
+ //line go.y:456
{
yyVAL.list = constiter(yyDollar[1].list, nil, nil)
}
case 47:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:459
+ //line go.y:462
{
// different from dclname because the name
// becomes visible right here, not at the end
}
case 48:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:468
+ //line go.y:471
{
yyVAL.node = typedcl1(yyDollar[1].node, yyDollar[2].node, true)
}
case 49:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:474
+ //line go.y:477
{
yyVAL.node = yyDollar[1].node
}
case 50:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:488
+ //line go.y:491
{
yyVAL.node = Nod(OASOP, yyDollar[1].node, yyDollar[3].node)
- yyVAL.node.Etype = uint8(yyDollar[2].i) // rathole to pass opcode
+ yyVAL.node.Etype = EType(yyDollar[2].i) // rathole to pass opcode
}
case 51:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:493
+ //line go.y:496
{
if yyDollar[1].list.Next == nil && yyDollar[3].list.Next == nil {
// simple
}
case 52:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:505
+ //line go.y:508
{
if yyDollar[3].list.N.Op == OTYPESW {
yyVAL.node = Nod(OTYPESW, nil, yyDollar[3].list.N.Right)
}
if yyDollar[1].list.Next != nil {
Yyerror("argument count mismatch: %d = %d", count(yyDollar[1].list), 1)
- } else if (yyDollar[1].list.N.Op != ONAME && yyDollar[1].list.N.Op != OTYPE && yyDollar[1].list.N.Op != ONONAME) || isblank(yyDollar[1].list.N) {
+ } else if (yyDollar[1].list.N.Op != ONAME && yyDollar[1].list.N.Op != OTYPE && yyDollar[1].list.N.Op != ONONAME && (yyDollar[1].list.N.Op != OLITERAL || yyDollar[1].list.N.Name == nil)) || isblank(yyDollar[1].list.N) {
Yyerror("invalid variable name %s in type switch", yyDollar[1].list.N)
} else {
yyVAL.node.Left = dclname(yyDollar[1].list.N.Sym)
}
case 53:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:523
+ //line go.y:526
{
yyVAL.node = Nod(OASOP, yyDollar[1].node, Nodintconst(1))
yyVAL.node.Implicit = true
- yyVAL.node.Etype = OADD
+ // TODO(marvin): Fix Node.EType type union.
+ yyVAL.node.Etype = EType(OADD)
}
case 54:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:529
+ //line go.y:533
{
yyVAL.node = Nod(OASOP, yyDollar[1].node, Nodintconst(1))
yyVAL.node.Implicit = true
- yyVAL.node.Etype = OSUB
+ // TODO(marvin): Fix Node.EType type union.
+ yyVAL.node.Etype = EType(OSUB)
}
case 55:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:537
+ //line go.y:542
{
var n, nn *Node
}
case 56:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:560
+ //line go.y:565
{
var n *Node
}
case 57:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:578
+ //line go.y:583
{
// will be converted to OCASE
// right will point to next case
}
case 58:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:587
+ //line go.y:592
{
var n, nn *Node
}
case 59:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:608
+ //line go.y:613
{
markdcl()
}
case 60:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:612
+ //line go.y:617
{
if yyDollar[3].list == nil {
yyVAL.node = Nod(OEMPTY, nil, nil)
}
case 61:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:623
+ //line go.y:628
{
// If the last token read by the lexer was consumed
// as part of the case, clear it (parser has cleared yychar).
}
case 62:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:634
+ //line go.y:639
{
// This is the only place in the language where a statement
// list is not allowed to drop the final semicolon, because
}
case 63:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:653
+ //line go.y:658
{
yyVAL.list = nil
}
case 64:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:657
+ //line go.y:662
{
yyVAL.list = list(yyDollar[1].list, yyDollar[2].node)
}
case 65:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:663
+ //line go.y:668
{
markdcl()
}
case 66:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:667
+ //line go.y:672
{
yyVAL.list = yyDollar[3].list
popdcl()
}
case 67:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:674
+ //line go.y:679
{
yyVAL.node = Nod(ORANGE, nil, yyDollar[4].node)
yyVAL.node.List = yyDollar[1].list
}
case 68:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:680
+ //line go.y:685
{
yyVAL.node = Nod(ORANGE, nil, yyDollar[4].node)
yyVAL.node.List = yyDollar[1].list
}
case 69:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:687
+ //line go.y:692
{
yyVAL.node = Nod(ORANGE, nil, yyDollar[2].node)
yyVAL.node.Etype = 0 // := flag
}
case 70:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:694
+ //line go.y:699
{
// init ; test ; incr
if yyDollar[5].node != nil && yyDollar[5].node.Colas {
}
case 71:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:707
+ //line go.y:712
{
// normal test
yyVAL.node = Nod(OFOR, nil, nil)
}
case 73:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:716
+ //line go.y:721
{
yyVAL.node = yyDollar[1].node
yyVAL.node.Nbody = concat(yyVAL.node.Nbody, yyDollar[2].list)
}
case 74:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:723
+ //line go.y:728
{
markdcl()
}
case 75:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:727
+ //line go.y:732
{
yyVAL.node = yyDollar[3].node
popdcl()
}
case 76:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:734
+ //line go.y:739
{
// test
yyVAL.node = Nod(OIF, nil, nil)
}
case 77:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:740
+ //line go.y:745
{
// init ; test
yyVAL.node = Nod(OIF, nil, nil)
}
case 78:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:752
+ //line go.y:757
{
markdcl()
}
case 79:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:756
+ //line go.y:761
{
if yyDollar[3].node.Left == nil {
Yyerror("missing condition in if statement")
}
case 80:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:762
+ //line go.y:767
{
yyDollar[3].node.Nbody = yyDollar[5].list
}
case 81:
yyDollar = yyS[yypt-8 : yypt+1]
- //line go.y:766
+ //line go.y:771
{
var n *Node
var nn *NodeList
}
case 82:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:784
+ //line go.y:789
{
markdcl()
}
case 83:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:788
+ //line go.y:793
{
if yyDollar[4].node.Left == nil {
Yyerror("missing condition in if statement")
}
case 84:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:797
+ //line go.y:802
{
yyVAL.list = nil
}
case 85:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:801
+ //line go.y:806
{
yyVAL.list = concat(yyDollar[1].list, yyDollar[2].list)
}
case 86:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:806
+ //line go.y:811
{
yyVAL.list = nil
}
case 87:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:810
+ //line go.y:815
{
l := &NodeList{N: yyDollar[2].node}
l.End = l
}
case 88:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:818
+ //line go.y:823
{
markdcl()
}
case 89:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:822
+ //line go.y:827
{
var n *Node
n = yyDollar[3].node.Left
}
case 90:
yyDollar = yyS[yypt-7 : yypt+1]
- //line go.y:831
+ //line go.y:836
{
yyVAL.node = yyDollar[3].node
yyVAL.node.Op = OSWITCH
}
case 91:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:841
+ //line go.y:846
{
typesw = Nod(OXXX, typesw, nil)
}
case 92:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:845
+ //line go.y:850
{
yyVAL.node = Nod(OSELECT, nil, nil)
yyVAL.node.Lineno = typesw.Lineno
}
case 94:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:858
+ //line go.y:863
{
yyVAL.node = Nod(OOROR, yyDollar[1].node, yyDollar[3].node)
}
case 95:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:862
+ //line go.y:867
{
yyVAL.node = Nod(OANDAND, yyDollar[1].node, yyDollar[3].node)
}
case 96:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:866
+ //line go.y:871
{
yyVAL.node = Nod(OEQ, yyDollar[1].node, yyDollar[3].node)
}
case 97:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:870
+ //line go.y:875
{
yyVAL.node = Nod(ONE, yyDollar[1].node, yyDollar[3].node)
}
case 98:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:874
+ //line go.y:879
{
yyVAL.node = Nod(OLT, yyDollar[1].node, yyDollar[3].node)
}
case 99:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:878
+ //line go.y:883
{
yyVAL.node = Nod(OLE, yyDollar[1].node, yyDollar[3].node)
}
case 100:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:882
+ //line go.y:887
{
yyVAL.node = Nod(OGE, yyDollar[1].node, yyDollar[3].node)
}
case 101:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:886
+ //line go.y:891
{
yyVAL.node = Nod(OGT, yyDollar[1].node, yyDollar[3].node)
}
case 102:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:890
+ //line go.y:895
{
yyVAL.node = Nod(OADD, yyDollar[1].node, yyDollar[3].node)
}
case 103:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:894
+ //line go.y:899
{
yyVAL.node = Nod(OSUB, yyDollar[1].node, yyDollar[3].node)
}
case 104:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:898
+ //line go.y:903
{
yyVAL.node = Nod(OOR, yyDollar[1].node, yyDollar[3].node)
}
case 105:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:902
+ //line go.y:907
{
yyVAL.node = Nod(OXOR, yyDollar[1].node, yyDollar[3].node)
}
case 106:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:906
+ //line go.y:911
{
yyVAL.node = Nod(OMUL, yyDollar[1].node, yyDollar[3].node)
}
case 107:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:910
+ //line go.y:915
{
yyVAL.node = Nod(ODIV, yyDollar[1].node, yyDollar[3].node)
}
case 108:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:914
+ //line go.y:919
{
yyVAL.node = Nod(OMOD, yyDollar[1].node, yyDollar[3].node)
}
case 109:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:918
+ //line go.y:923
{
yyVAL.node = Nod(OAND, yyDollar[1].node, yyDollar[3].node)
}
case 110:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:922
+ //line go.y:927
{
yyVAL.node = Nod(OANDNOT, yyDollar[1].node, yyDollar[3].node)
}
case 111:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:926
+ //line go.y:931
{
yyVAL.node = Nod(OLSH, yyDollar[1].node, yyDollar[3].node)
}
case 112:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:930
+ //line go.y:935
{
yyVAL.node = Nod(ORSH, yyDollar[1].node, yyDollar[3].node)
}
case 113:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:935
+ //line go.y:940
{
yyVAL.node = Nod(OSEND, yyDollar[1].node, yyDollar[3].node)
}
case 115:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:942
+ //line go.y:947
{
yyVAL.node = Nod(OIND, yyDollar[2].node, nil)
}
case 116:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:946
+ //line go.y:951
{
if yyDollar[2].node.Op == OCOMPLIT {
// Special case for &T{...}: turn into (*T){...}.
}
case 117:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:957
+ //line go.y:962
{
yyVAL.node = Nod(OPLUS, yyDollar[2].node, nil)
}
case 118:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:961
+ //line go.y:966
{
yyVAL.node = Nod(OMINUS, yyDollar[2].node, nil)
}
case 119:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:965
+ //line go.y:970
{
yyVAL.node = Nod(ONOT, yyDollar[2].node, nil)
}
case 120:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:969
+ //line go.y:974
{
Yyerror("the bitwise complement operator is ^")
yyVAL.node = Nod(OCOM, yyDollar[2].node, nil)
}
case 121:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:974
+ //line go.y:979
{
yyVAL.node = Nod(OCOM, yyDollar[2].node, nil)
}
case 122:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:978
+ //line go.y:983
{
yyVAL.node = Nod(ORECV, yyDollar[2].node, nil)
}
case 123:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:988
+ //line go.y:993
{
yyVAL.node = Nod(OCALL, yyDollar[1].node, nil)
}
case 124:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:992
+ //line go.y:997
{
yyVAL.node = Nod(OCALL, yyDollar[1].node, nil)
yyVAL.node.List = yyDollar[3].list
}
case 125:
yyDollar = yyS[yypt-6 : yypt+1]
- //line go.y:997
+ //line go.y:1002
{
yyVAL.node = Nod(OCALL, yyDollar[1].node, nil)
yyVAL.node.List = yyDollar[3].list
}
case 126:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1005
+ //line go.y:1010
{
yyVAL.node = nodlit(yyDollar[1].val)
}
case 128:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1010
+ //line go.y:1015
{
if yyDollar[1].node.Op == OPACK {
var s *Sym
}
case 129:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:1021
+ //line go.y:1026
{
yyVAL.node = Nod(ODOTTYPE, yyDollar[1].node, yyDollar[4].node)
}
case 130:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:1025
+ //line go.y:1030
{
yyVAL.node = Nod(OTYPESW, nil, yyDollar[1].node)
}
case 131:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:1029
+ //line go.y:1034
{
yyVAL.node = Nod(OINDEX, yyDollar[1].node, yyDollar[3].node)
}
case 132:
yyDollar = yyS[yypt-6 : yypt+1]
- //line go.y:1033
+ //line go.y:1038
{
yyVAL.node = Nod(OSLICE, yyDollar[1].node, Nod(OKEY, yyDollar[3].node, yyDollar[5].node))
}
case 133:
yyDollar = yyS[yypt-8 : yypt+1]
- //line go.y:1037
+ //line go.y:1042
{
if yyDollar[5].node == nil {
Yyerror("middle index required in 3-index slice")
}
case 135:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:1048
+ //line go.y:1053
{
// conversion
yyVAL.node = Nod(OCALL, yyDollar[1].node, nil)
}
case 136:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:1054
+ //line go.y:1059
{
yyVAL.node = yyDollar[3].node
yyVAL.node.Right = yyDollar[1].node
}
case 137:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:1061
+ //line go.y:1066
{
yyVAL.node = yyDollar[3].node
yyVAL.node.Right = yyDollar[1].node
}
case 138:
yyDollar = yyS[yypt-7 : yypt+1]
- //line go.y:1067
+ //line go.y:1072
{
Yyerror("cannot parenthesize type in composite literal")
yyVAL.node = yyDollar[5].node
}
case 140:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:1076
+ //line go.y:1081
{
// composite expression.
// make node early so we get the right line number.
}
case 141:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1084
+ //line go.y:1089
{
yyVAL.node = Nod(OKEY, yyDollar[1].node, yyDollar[3].node)
}
case 142:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1090
+ //line go.y:1095
{
// These nodes do not carry line numbers.
// Since a composite literal commonly spans several lines,
}
case 143:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:1103
+ //line go.y:1108
{
yyVAL.node = yyDollar[2].node
yyVAL.node.List = yyDollar[3].list
}
case 145:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:1111
+ //line go.y:1116
{
yyVAL.node = yyDollar[2].node
yyVAL.node.List = yyDollar[3].list
}
case 147:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1119
+ //line go.y:1124
{
yyVAL.node = yyDollar[2].node
}
case 151:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1140
+ //line go.y:1145
{
yyVAL.i = LBODY
}
case 152:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1144
+ //line go.y:1149
{
yyVAL.i = '{'
}
case 153:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1155
+ //line go.y:1160
{
if yyDollar[1].sym == nil {
yyVAL.node = nil
}
case 154:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1165
+ //line go.y:1170
{
yyVAL.node = dclname(yyDollar[1].sym)
}
case 155:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:1170
+ //line go.y:1175
{
yyVAL.node = nil
}
case 157:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1177
+ //line go.y:1182
{
yyVAL.sym = yyDollar[1].sym
// during imports, unqualified non-exported identifiers are from builtinpkg
}
case 159:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1186
+ //line go.y:1191
{
yyVAL.sym = nil
}
case 160:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:1192
+ //line go.y:1197
{
var p *Pkg
}
case 161:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:1206
+ //line go.y:1211
{
var p *Pkg
}
case 162:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1222
+ //line go.y:1227
{
yyVAL.node = oldname(yyDollar[1].sym)
if yyVAL.node.Name != nil && yyVAL.node.Name.Pack != nil {
}
case 164:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1243
+ //line go.y:1248
{
Yyerror("final argument in variadic function missing type")
yyVAL.node = Nod(ODDD, typenod(typ(TINTER)), nil)
}
case 165:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1248
+ //line go.y:1253
{
yyVAL.node = Nod(ODDD, yyDollar[2].node, nil)
}
case 171:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1259
+ //line go.y:1264
{
yyVAL.node = yyDollar[2].node
}
case 175:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1268
+ //line go.y:1273
{
yyVAL.node = Nod(OIND, yyDollar[2].node, nil)
}
case 180:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1278
+ //line go.y:1283
{
yyVAL.node = yyDollar[2].node
}
case 190:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1299
+ //line go.y:1304
{
if yyDollar[1].node.Op == OPACK {
var s *Sym
}
case 191:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:1312
+ //line go.y:1317
{
yyVAL.node = Nod(OTARRAY, yyDollar[2].node, yyDollar[4].node)
}
case 192:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:1316
+ //line go.y:1321
{
// array literal of nelem
yyVAL.node = Nod(OTARRAY, Nod(ODDD, nil, nil), yyDollar[4].node)
}
case 193:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1321
+ //line go.y:1326
{
yyVAL.node = Nod(OTCHAN, yyDollar[2].node, nil)
yyVAL.node.Etype = Cboth
}
case 194:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1326
+ //line go.y:1331
{
yyVAL.node = Nod(OTCHAN, yyDollar[3].node, nil)
yyVAL.node.Etype = Csend
}
case 195:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:1331
+ //line go.y:1336
{
yyVAL.node = Nod(OTMAP, yyDollar[3].node, yyDollar[5].node)
}
case 198:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1339
+ //line go.y:1344
{
yyVAL.node = Nod(OIND, yyDollar[2].node, nil)
}
case 199:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1345
+ //line go.y:1350
{
yyVAL.node = Nod(OTCHAN, yyDollar[3].node, nil)
yyVAL.node.Etype = Crecv
}
case 200:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:1352
+ //line go.y:1357
{
yyVAL.node = Nod(OTSTRUCT, nil, nil)
yyVAL.node.List = yyDollar[3].list
}
case 201:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1358
+ //line go.y:1363
{
yyVAL.node = Nod(OTSTRUCT, nil, nil)
fixlbrace(yyDollar[2].i)
}
case 202:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:1365
+ //line go.y:1370
{
yyVAL.node = Nod(OTINTER, nil, nil)
yyVAL.node.List = yyDollar[3].list
}
case 203:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1371
+ //line go.y:1376
{
yyVAL.node = Nod(OTINTER, nil, nil)
fixlbrace(yyDollar[2].i)
}
case 204:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1382
+ //line go.y:1387
{
yyVAL.node = yyDollar[2].node
if yyVAL.node == nil {
yyVAL.node.Noescape = noescape
yyVAL.node.Func.Norace = norace
yyVAL.node.Func.Nosplit = nosplit
+ yyVAL.node.Func.Noinline = noinline
yyVAL.node.Func.Nowritebarrier = nowritebarrier
+ yyVAL.node.Func.Nowritebarrierrec = nowritebarrierrec
yyVAL.node.Func.Systemstack = systemstack
funcbody(yyVAL.node)
}
case 205:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:1402
+ //line go.y:1409
{
var t *Node
}
case 206:
yyDollar = yyS[yypt-8 : yypt+1]
- //line go.y:1433
+ //line go.y:1440
{
var rcvr, t *Node
}
case 207:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:1471
+ //line go.y:1478
{
var s *Sym
var t *Type
}
case 208:
yyDollar = yyS[yypt-8 : yypt+1]
- //line go.y:1496
+ //line go.y:1503
{
yyVAL.node = methodname1(newname(yyDollar[4].sym), yyDollar[2].list.N.Right)
yyVAL.node.Type = functype(yyDollar[2].list.N, yyDollar[6].list, yyDollar[8].list)
}
case 209:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:1514
+ //line go.y:1521
{
yyDollar[3].list = checkarglist(yyDollar[3].list, 1)
yyVAL.node = Nod(OTFUNC, nil, nil)
}
case 210:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:1522
+ //line go.y:1529
{
yyVAL.list = nil
}
case 211:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1526
+ //line go.y:1533
{
yyVAL.list = yyDollar[2].list
if yyVAL.list == nil {
}
case 212:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:1535
+ //line go.y:1542
{
yyVAL.list = nil
}
case 213:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1539
+ //line go.y:1546
{
yyVAL.list = list1(Nod(ODCLFIELD, nil, yyDollar[1].node))
}
case 214:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1543
+ //line go.y:1550
{
yyDollar[2].list = checkarglist(yyDollar[2].list, 0)
yyVAL.list = yyDollar[2].list
}
case 215:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1550
+ //line go.y:1557
{
closurehdr(yyDollar[1].node)
}
case 216:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:1556
+ //line go.y:1563
{
yyVAL.node = closurebody(yyDollar[3].list)
fixlbrace(yyDollar[2].i)
}
case 217:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1561
+ //line go.y:1568
{
yyVAL.node = closurebody(nil)
}
case 218:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:1572
+ //line go.y:1579
{
yyVAL.list = nil
}
case 219:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1576
+ //line go.y:1583
{
yyVAL.list = concat(yyDollar[1].list, yyDollar[2].list)
if nsyntaxerrors == 0 {
testdclstack()
}
- nointerface = false
noescape = false
+ noinline = false
+ nointerface = false
norace = false
nosplit = false
nowritebarrier = false
+ nowritebarrierrec = false
systemstack = false
}
case 221:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1592
+ //line go.y:1601
{
yyVAL.list = concat(yyDollar[1].list, yyDollar[3].list)
}
case 223:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1599
+ //line go.y:1608
{
yyVAL.list = concat(yyDollar[1].list, yyDollar[3].list)
}
case 224:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1605
+ //line go.y:1614
{
yyVAL.list = list1(yyDollar[1].node)
}
case 225:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1609
+ //line go.y:1618
{
yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
}
case 227:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1616
+ //line go.y:1625
{
yyVAL.list = concat(yyDollar[1].list, yyDollar[3].list)
}
case 228:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1622
+ //line go.y:1631
{
yyVAL.list = list1(yyDollar[1].node)
}
case 229:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1626
+ //line go.y:1635
{
yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
}
case 230:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1632
+ //line go.y:1641
{
var l *NodeList
}
case 231:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1656
+ //line go.y:1665
{
yyDollar[1].node.SetVal(yyDollar[2].val)
yyVAL.list = list1(yyDollar[1].node)
}
case 232:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:1661
+ //line go.y:1670
{
yyDollar[2].node.SetVal(yyDollar[4].val)
yyVAL.list = list1(yyDollar[2].node)
}
case 233:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1667
+ //line go.y:1676
{
yyDollar[2].node.Right = Nod(OIND, yyDollar[2].node.Right, nil)
yyDollar[2].node.SetVal(yyDollar[3].val)
}
case 234:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:1673
+ //line go.y:1682
{
yyDollar[3].node.Right = Nod(OIND, yyDollar[3].node.Right, nil)
yyDollar[3].node.SetVal(yyDollar[5].val)
}
case 235:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:1680
+ //line go.y:1689
{
yyDollar[3].node.Right = Nod(OIND, yyDollar[3].node.Right, nil)
yyDollar[3].node.SetVal(yyDollar[5].val)
}
case 236:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1689
+ //line go.y:1698
{
var n *Node
}
case 237:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1699
+ //line go.y:1708
{
var pkg *Pkg
}
case 238:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1714
+ //line go.y:1723
{
yyVAL.node = embedded(yyDollar[1].sym, localpkg)
}
case 239:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1720
+ //line go.y:1729
{
yyVAL.node = Nod(ODCLFIELD, yyDollar[1].node, yyDollar[2].node)
ifacedcl(yyVAL.node)
}
case 240:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1725
+ //line go.y:1734
{
yyVAL.node = Nod(ODCLFIELD, nil, oldname(yyDollar[1].sym))
}
case 241:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1729
+ //line go.y:1738
{
yyVAL.node = Nod(ODCLFIELD, nil, oldname(yyDollar[2].sym))
Yyerror("cannot parenthesize embedded type")
}
case 242:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:1736
+ //line go.y:1745
{
// without func keyword
yyDollar[2].list = checkarglist(yyDollar[2].list, 1)
}
case 244:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1750
+ //line go.y:1759
{
yyVAL.node = Nod(ONONAME, nil, nil)
yyVAL.node.Sym = yyDollar[1].sym
}
case 245:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1756
+ //line go.y:1765
{
yyVAL.node = Nod(ONONAME, nil, nil)
yyVAL.node.Sym = yyDollar[1].sym
}
case 247:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1765
+ //line go.y:1774
{
yyVAL.list = list1(yyDollar[1].node)
}
case 248:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1769
+ //line go.y:1778
{
yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
}
case 249:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:1774
+ //line go.y:1783
{
yyVAL.list = nil
}
case 250:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1778
+ //line go.y:1787
{
yyVAL.list = yyDollar[1].list
}
case 251:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:1786
+ //line go.y:1795
{
yyVAL.node = nil
}
case 253:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1791
+ //line go.y:1800
{
yyVAL.node = liststmt(yyDollar[1].list)
}
case 255:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1796
+ //line go.y:1805
{
yyVAL.node = nil
}
case 261:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1807
+ //line go.y:1816
{
yyDollar[1].node = Nod(OLABEL, yyDollar[1].node, nil)
yyDollar[1].node.Sym = dclstack // context, for goto restrictions
}
case 262:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:1812
+ //line go.y:1821
{
var l *NodeList
}
case 263:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1823
+ //line go.y:1832
{
// will be converted to OFALL
yyVAL.node = Nod(OXFALL, nil, nil)
}
case 264:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1829
+ //line go.y:1838
{
yyVAL.node = Nod(OBREAK, yyDollar[2].node, nil)
}
case 265:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1833
+ //line go.y:1842
{
yyVAL.node = Nod(OCONTINUE, yyDollar[2].node, nil)
}
case 266:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1837
+ //line go.y:1846
{
yyVAL.node = Nod(OPROC, yyDollar[2].node, nil)
}
case 267:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1841
+ //line go.y:1850
{
yyVAL.node = Nod(ODEFER, yyDollar[2].node, nil)
}
case 268:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1845
+ //line go.y:1854
{
yyVAL.node = Nod(OGOTO, yyDollar[2].node, nil)
yyVAL.node.Sym = dclstack // context, for goto restrictions
}
case 269:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1850
+ //line go.y:1859
{
yyVAL.node = Nod(ORETURN, nil, nil)
yyVAL.node.List = yyDollar[2].list
}
case 270:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1872
+ //line go.y:1881
{
yyVAL.list = nil
if yyDollar[1].node != nil {
}
case 271:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1879
+ //line go.y:1888
{
yyVAL.list = yyDollar[1].list
if yyDollar[3].node != nil {
}
case 272:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1888
+ //line go.y:1897
{
yyVAL.list = list1(yyDollar[1].node)
}
case 273:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1892
+ //line go.y:1901
{
yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
}
case 274:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1898
+ //line go.y:1907
{
yyVAL.list = list1(yyDollar[1].node)
}
case 275:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1902
+ //line go.y:1911
{
yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
}
case 276:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1908
+ //line go.y:1917
{
yyVAL.list = list1(yyDollar[1].node)
}
case 277:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1912
+ //line go.y:1921
{
yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
}
case 278:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1918
+ //line go.y:1927
{
yyVAL.list = list1(yyDollar[1].node)
}
case 279:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1922
+ //line go.y:1931
{
yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
}
case 280:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1931
+ //line go.y:1940
{
yyVAL.list = list1(yyDollar[1].node)
}
case 281:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1935
+ //line go.y:1944
{
yyVAL.list = list1(yyDollar[1].node)
}
case 282:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1939
+ //line go.y:1948
{
yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
}
case 283:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1943
+ //line go.y:1952
{
yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
}
case 284:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:1948
+ //line go.y:1957
{
yyVAL.list = nil
}
case 285:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1952
+ //line go.y:1961
{
yyVAL.list = yyDollar[1].list
}
case 290:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:1966
+ //line go.y:1975
{
yyVAL.node = nil
}
case 292:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:1972
+ //line go.y:1981
{
yyVAL.list = nil
}
case 294:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:1978
+ //line go.y:1987
{
yyVAL.node = nil
}
case 296:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:1984
+ //line go.y:1993
{
yyVAL.list = nil
}
case 298:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:1990
+ //line go.y:1999
{
yyVAL.list = nil
}
case 300:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:1996
+ //line go.y:2005
{
yyVAL.list = nil
}
case 302:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:2002
+ //line go.y:2011
{
yyVAL.val.U = nil
}
case 304:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:2012
+ //line go.y:2021
{
importimport(yyDollar[2].sym, yyDollar[3].val.U.(string))
}
case 305:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:2016
+ //line go.y:2025
{
importvar(yyDollar[2].sym, yyDollar[3].typ)
}
case 306:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:2020
+ //line go.y:2029
{
importconst(yyDollar[2].sym, Types[TIDEAL], yyDollar[4].node)
}
case 307:
yyDollar = yyS[yypt-6 : yypt+1]
- //line go.y:2024
+ //line go.y:2033
{
importconst(yyDollar[2].sym, yyDollar[3].typ, yyDollar[5].node)
}
case 308:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:2028
+ //line go.y:2037
{
importtype(yyDollar[2].typ, yyDollar[3].typ)
}
case 309:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:2032
+ //line go.y:2041
{
if yyDollar[2].node == nil {
dclcontext = PEXTERN // since we skip the funcbody below
}
case 310:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:2053
+ //line go.y:2062
{
yyVAL.sym = yyDollar[1].sym
structpkg = yyVAL.sym.Pkg
}
case 311:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:2060
+ //line go.y:2069
{
yyVAL.typ = pkgtype(yyDollar[1].sym)
importsym(yyDollar[1].sym, OTYPE)
}
case 317:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:2080
+ //line go.y:2089
{
yyVAL.typ = pkgtype(yyDollar[1].sym)
}
case 318:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:2084
+ //line go.y:2093
{
// predefined name like uint8
yyDollar[1].sym = Pkglookup(yyDollar[1].sym.Name, builtinpkg)
}
case 319:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:2095
+ //line go.y:2104
{
yyVAL.typ = aindex(nil, yyDollar[3].typ)
}
case 320:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:2099
+ //line go.y:2108
{
yyVAL.typ = aindex(nodlit(yyDollar[2].val), yyDollar[4].typ)
}
case 321:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:2103
+ //line go.y:2112
{
yyVAL.typ = maptype(yyDollar[3].typ, yyDollar[5].typ)
}
case 322:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:2107
+ //line go.y:2116
{
yyVAL.typ = tostruct(yyDollar[3].list)
}
case 323:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:2111
+ //line go.y:2120
{
yyVAL.typ = tointerface(yyDollar[3].list)
}
case 324:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:2115
+ //line go.y:2124
{
yyVAL.typ = Ptrto(yyDollar[2].typ)
}
case 325:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:2119
+ //line go.y:2128
{
yyVAL.typ = typ(TCHAN)
yyVAL.typ.Type = yyDollar[2].typ
}
case 326:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:2125
+ //line go.y:2134
{
yyVAL.typ = typ(TCHAN)
yyVAL.typ.Type = yyDollar[3].typ
}
case 327:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:2131
+ //line go.y:2140
{
yyVAL.typ = typ(TCHAN)
yyVAL.typ.Type = yyDollar[3].typ
}
case 328:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:2139
+ //line go.y:2148
{
yyVAL.typ = typ(TCHAN)
yyVAL.typ.Type = yyDollar[3].typ
}
case 329:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:2147
+ //line go.y:2156
{
yyVAL.typ = functype(nil, yyDollar[3].list, yyDollar[5].list)
}
case 330:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:2153
+ //line go.y:2162
{
yyVAL.node = Nod(ODCLFIELD, nil, typenod(yyDollar[2].typ))
if yyDollar[1].sym != nil {
}
case 331:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:2161
+ //line go.y:2170
{
var t *Type
}
case 332:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:2178
+ //line go.y:2187
{
var s *Sym
var p *Pkg
}
case 333:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:2202
+ //line go.y:2211
{
yyVAL.node = Nod(ODCLFIELD, newname(yyDollar[1].sym), typenod(functype(fakethis(), yyDollar[3].list, yyDollar[5].list)))
}
case 334:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:2206
+ //line go.y:2215
{
yyVAL.node = Nod(ODCLFIELD, nil, typenod(yyDollar[1].typ))
}
case 335:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:2211
+ //line go.y:2220
{
yyVAL.list = nil
}
case 337:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:2218
+ //line go.y:2227
{
yyVAL.list = yyDollar[2].list
}
case 338:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:2222
+ //line go.y:2231
{
yyVAL.list = list1(Nod(ODCLFIELD, nil, typenod(yyDollar[1].typ)))
}
case 339:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:2232
+ //line go.y:2241
{
yyVAL.node = nodlit(yyDollar[1].val)
}
case 340:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:2236
+ //line go.y:2245
{
yyVAL.node = nodlit(yyDollar[2].val)
switch yyVAL.node.Val().Ctype() {
}
case 341:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:2254
+ //line go.y:2263
{
yyVAL.node = oldname(Pkglookup(yyDollar[1].sym.Name, builtinpkg))
if yyVAL.node.Op != OLITERAL {
}
case 343:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:2264
+ //line go.y:2273
{
if yyDollar[2].node.Val().Ctype() == CTRUNE && yyDollar[4].node.Val().Ctype() == CTINT {
yyVAL.node = yyDollar[2].node
}
case 346:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:2280
+ //line go.y:2289
{
yyVAL.list = list1(yyDollar[1].node)
}
case 347:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:2284
+ //line go.y:2293
{
yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
}
case 348:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:2290
+ //line go.y:2299
{
yyVAL.list = list1(yyDollar[1].node)
}
case 349:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:2294
+ //line go.y:2303
{
yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
}
case 350:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:2300
+ //line go.y:2309
{
yyVAL.list = list1(yyDollar[1].node)
}
case 351:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:2304
+ //line go.y:2313
{
yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
}
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package ppc64
+package mips64
import (
"cmd/compile/internal/gc"
"cmd/internal/obj"
- "cmd/internal/obj/ppc64"
+ "cmd/internal/obj/mips"
)
func blockcopy(n, res *gc.Node, osrc, odst, w int64) {
gc.Fatalf("sgen: invalid alignment %d for %v", align, n.Type)
case 1:
- op = ppc64.AMOVBU
+ op = mips.AMOVB
case 2:
- op = ppc64.AMOVHU
+ op = mips.AMOVH
case 4:
- op = ppc64.AMOVWZU // there is no lwau, only lwaux
+ op = mips.AMOVW
case 8:
- op = ppc64.AMOVDU
+ op = mips.AMOVV
}
if w%int64(align) != 0 {
if n.Ullman >= res.Ullman {
gc.Agenr(n, &dst, res) // temporarily use dst
gc.Regalloc(&src, gc.Types[gc.Tptr], nil)
- gins(ppc64.AMOVD, &dst, &src)
+ gins(mips.AMOVV, &dst, &src)
if res.Op == gc.ONAME {
gc.Gvardef(res)
}
if dir < 0 {
if c >= 4 {
gc.Regalloc(&nend, gc.Types[gc.Tptr], nil)
- gins(ppc64.AMOVD, &src, &nend)
+ gins(mips.AMOVV, &src, &nend)
}
- p := gins(ppc64.AADD, nil, &src)
+ p := gins(mips.AADDV, nil, &src)
p.From.Type = obj.TYPE_CONST
p.From.Offset = w
- p = gins(ppc64.AADD, nil, &dst)
+ p = gins(mips.AADDV, nil, &dst)
p.From.Type = obj.TYPE_CONST
p.From.Offset = w
} else {
- p := gins(ppc64.AADD, nil, &src)
+ p := gins(mips.AADDV, nil, &src)
p.From.Type = obj.TYPE_CONST
p.From.Offset = int64(-dir)
- p = gins(ppc64.AADD, nil, &dst)
+ p = gins(mips.AADDV, nil, &dst)
p.From.Type = obj.TYPE_CONST
p.From.Offset = int64(-dir)
if c >= 4 {
gc.Regalloc(&nend, gc.Types[gc.Tptr], nil)
- p := gins(ppc64.AMOVD, &src, &nend)
+ p := gins(mips.AMOVV, &src, &nend)
p.From.Type = obj.TYPE_ADDR
p.From.Offset = w
}
p.From.Offset = int64(dir)
ploop := p
+ p = gins(mips.AADDV, nil, &src)
+ p.From.Type = obj.TYPE_CONST
+ p.From.Offset = int64(dir)
+
p = gins(op, &tmp, &dst)
p.To.Type = obj.TYPE_MEM
p.To.Offset = int64(dir)
- p = gins(ppc64.ACMP, &src, &nend)
+ p = gins(mips.AADDV, nil, &dst)
+ p.From.Type = obj.TYPE_CONST
+ p.From.Offset = int64(dir)
- gc.Patch(gc.Gbranch(ppc64.ABNE, nil, 0), ploop)
+ gc.Patch(ginsbranch(mips.ABNE, nil, &src, &nend, 0), ploop)
gc.Regfree(&nend)
} else {
- // TODO(austin): Instead of generating ADD $-8,R8; ADD
- // $-8,R7; n*(MOVDU 8(R8),R9; MOVDU R9,8(R7);) just
- // generate the offsets directly and eliminate the
- // ADDs. That will produce shorter, more
+ // TODO: Instead of generating ADDV $-8,R8; ADDV
+ // $-8,R7; n*(MOVV 8(R8),R9; ADDV $8,R8; MOVV R9,8(R7);
+ // ADDV $8,R7;) just generate the offsets directly and
+ // eliminate the ADDs. That will produce shorter, more
// pipeline-able code.
var p *obj.Prog
- for {
- tmp14 := c
- c--
- if tmp14 <= 0 {
- break
- }
-
+ for ; c > 0; c-- {
p = gins(op, &src, &tmp)
p.From.Type = obj.TYPE_MEM
p.From.Offset = int64(dir)
+ p = gins(mips.AADDV, nil, &src)
+ p.From.Type = obj.TYPE_CONST
+ p.From.Offset = int64(dir)
+
p = gins(op, &tmp, &dst)
p.To.Type = obj.TYPE_MEM
p.To.Offset = int64(dir)
+
+ p = gins(mips.AADDV, nil, &dst)
+ p.From.Type = obj.TYPE_CONST
+ p.From.Offset = int64(dir)
}
}
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package ppc64
+package mips64
import (
"cmd/compile/internal/gc"
"cmd/internal/obj"
- "cmd/internal/obj/ppc64"
+ "cmd/internal/obj/mips"
)
-var thechar int = '9'
+var thechar int = '0'
-var thestring string = "ppc64"
+var thestring string = "mips64"
var thelinkarch *obj.LinkArch
func linkarchinit() {
thestring = obj.Getgoarch()
gc.Thearch.Thestring = thestring
- if thestring == "ppc64le" {
- thelinkarch = &ppc64.Linkppc64le
+ if thestring == "mips64le" {
+ thelinkarch = &mips.Linkmips64le
} else {
- thelinkarch = &ppc64.Linkppc64
+ thelinkarch = &mips.Linkmips64
}
gc.Thearch.Thelinkarch = thelinkarch
}
gc.Thearch.Thestring = thestring
gc.Thearch.Thelinkarch = thelinkarch
gc.Thearch.Typedefs = typedefs
- gc.Thearch.REGSP = ppc64.REGSP
- gc.Thearch.REGCTXT = ppc64.REGCTXT
- gc.Thearch.REGCALLX = ppc64.REG_R3
- gc.Thearch.REGCALLX2 = ppc64.REG_R4
- gc.Thearch.REGRETURN = ppc64.REG_R3
- gc.Thearch.REGMIN = ppc64.REG_R0
- gc.Thearch.REGMAX = ppc64.REG_R31
- gc.Thearch.FREGMIN = ppc64.REG_F0
- gc.Thearch.FREGMAX = ppc64.REG_F31
+ gc.Thearch.REGSP = mips.REGSP
+ gc.Thearch.REGCTXT = mips.REGCTXT
+ gc.Thearch.REGCALLX = mips.REG_R1
+ gc.Thearch.REGCALLX2 = mips.REG_R2
+ gc.Thearch.REGRETURN = mips.REGRET
+ gc.Thearch.REGMIN = mips.REG_R0
+ gc.Thearch.REGMAX = mips.REG_R31
+ gc.Thearch.FREGMIN = mips.REG_F0
+ gc.Thearch.FREGMAX = mips.REG_F31
gc.Thearch.MAXWIDTH = MAXWIDTH
gc.Thearch.ReservedRegs = resvd
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package ppc64
+package mips64
import (
"cmd/compile/internal/gc"
"cmd/internal/obj"
- "cmd/internal/obj/ppc64"
+ "cmd/internal/obj/mips"
"fmt"
)
}
if cnt < int64(4*gc.Widthptr) {
for i := int64(0); i < cnt; i += int64(gc.Widthptr) {
- p = appendpp(p, ppc64.AMOVD, obj.TYPE_REG, ppc64.REGZERO, 0, obj.TYPE_MEM, ppc64.REGSP, 8+frame+lo+i)
+ p = appendpp(p, mips.AMOVV, obj.TYPE_REG, mips.REGZERO, 0, obj.TYPE_MEM, mips.REGSP, 8+frame+lo+i)
}
// TODO(dfc): https://golang.org/issue/12108
// If DUFFZERO is used inside a tail call (see genwrapper) it will
// overwrite the link register.
} else if false && cnt <= int64(128*gc.Widthptr) {
- p = appendpp(p, ppc64.AADD, obj.TYPE_CONST, 0, 8+frame+lo-8, obj.TYPE_REG, ppc64.REGRT1, 0)
- p.Reg = ppc64.REGSP
+ p = appendpp(p, mips.AADDV, obj.TYPE_CONST, 0, 8+frame+lo-8, obj.TYPE_REG, mips.REGRT1, 0)
+ p.Reg = mips.REGSP
p = appendpp(p, obj.ADUFFZERO, obj.TYPE_NONE, 0, 0, obj.TYPE_MEM, 0, 0)
f := gc.Sysfunc("duffzero")
gc.Naddr(&p.To, f)
gc.Afunclit(&p.To, f)
- p.To.Offset = 4 * (128 - cnt/int64(gc.Widthptr))
+ p.To.Offset = 8 * (128 - cnt/int64(gc.Widthptr))
} else {
- p = appendpp(p, ppc64.AMOVD, obj.TYPE_CONST, 0, 8+frame+lo-8, obj.TYPE_REG, ppc64.REGTMP, 0)
- p = appendpp(p, ppc64.AADD, obj.TYPE_REG, ppc64.REGTMP, 0, obj.TYPE_REG, ppc64.REGRT1, 0)
- p.Reg = ppc64.REGSP
- p = appendpp(p, ppc64.AMOVD, obj.TYPE_CONST, 0, cnt, obj.TYPE_REG, ppc64.REGTMP, 0)
- p = appendpp(p, ppc64.AADD, obj.TYPE_REG, ppc64.REGTMP, 0, obj.TYPE_REG, ppc64.REGRT2, 0)
- p.Reg = ppc64.REGRT1
- p = appendpp(p, ppc64.AMOVDU, obj.TYPE_REG, ppc64.REGZERO, 0, obj.TYPE_MEM, ppc64.REGRT1, int64(gc.Widthptr))
+ // ADDV $(8+frame+lo-8), SP, r1
+ // ADDV $cnt, r1, r2
+ // loop:
+ // MOVV R0, (Widthptr)r1
+ // ADDV $Widthptr, r1
+ // BNE r1, r2, loop
+ p = appendpp(p, mips.AADDV, obj.TYPE_CONST, 0, 8+frame+lo-8, obj.TYPE_REG, mips.REGRT1, 0)
+ p.Reg = mips.REGSP
+ p = appendpp(p, mips.AADDV, obj.TYPE_CONST, 0, cnt, obj.TYPE_REG, mips.REGRT2, 0)
+ p.Reg = mips.REGRT1
+ p = appendpp(p, mips.AMOVV, obj.TYPE_REG, mips.REGZERO, 0, obj.TYPE_MEM, mips.REGRT1, int64(gc.Widthptr))
p1 := p
- p = appendpp(p, ppc64.ACMP, obj.TYPE_REG, ppc64.REGRT1, 0, obj.TYPE_REG, ppc64.REGRT2, 0)
- p = appendpp(p, ppc64.ABNE, obj.TYPE_NONE, 0, 0, obj.TYPE_BRANCH, 0, 0)
+ p = appendpp(p, mips.AADDV, obj.TYPE_CONST, 0, int64(gc.Widthptr), obj.TYPE_REG, mips.REGRT1, 0)
+ p = appendpp(p, mips.ABNE, obj.TYPE_REG, mips.REGRT1, 0, obj.TYPE_BRANCH, 0, 0)
+ p.Reg = mips.REGRT2
gc.Patch(p, p1)
}
func ginsnop() {
var reg gc.Node
- gc.Nodreg(®, gc.Types[gc.TINT], ppc64.REG_R0)
- gins(ppc64.AOR, ®, ®)
+ gc.Nodreg(®, gc.Types[gc.TINT], mips.REG_R0)
+ gins(mips.ANOR, ®, ®)
}
var panicdiv *gc.Node
* res = nl % nr
* according to op.
*/
-func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
- // Have to be careful about handling
- // most negative int divided by -1 correctly.
- // The hardware will generate undefined result.
- // Also need to explicitly trap on division on zero,
- // the hardware will silently generate undefined result.
- // DIVW will leave unpredicable result in higher 32-bit,
- // so always use DIVD/DIVDU.
+func dodiv(op gc.Op, nl *gc.Node, nr *gc.Node, res *gc.Node) {
t := nl.Type
t0 := t
- check := 0
- if gc.Issigned[t.Etype] {
- check = 1
- if gc.Isconst(nl, gc.CTINT) && nl.Int() != -(1<<uint64(t.Width*8-1)) {
- check = 0
- } else if gc.Isconst(nr, gc.CTINT) && nr.Int() != -1 {
- check = 0
- }
- }
if t.Width < 8 {
if gc.Issigned[t.Etype] {
} else {
t = gc.Types[gc.TUINT64]
}
- check = 0
}
a := optoas(gc.ODIV, t)
}
// Handle divide-by-zero panic.
- p1 := gins(optoas(gc.OCMP, t), &tr, nil)
-
- p1.To.Type = obj.TYPE_REG
- p1.To.Reg = ppc64.REGZERO
- p1 = gc.Gbranch(optoas(gc.ONE, t), nil, +1)
+ p1 := ginsbranch(mips.ABNE, nil, &tr, nil, 0)
if panicdiv == nil {
panicdiv = gc.Sysfunc("panicdivide")
}
gc.Ginscall(panicdiv, -1)
gc.Patch(p1, gc.Pc)
- var p2 *obj.Prog
- if check != 0 {
- var nm1 gc.Node
- gc.Nodconst(&nm1, t, -1)
- gins(optoas(gc.OCMP, t), &tr, &nm1)
- p1 := gc.Gbranch(optoas(gc.ONE, t), nil, +1)
- if op == gc.ODIV {
- // a / (-1) is -a.
- gins(optoas(gc.OMINUS, t), nil, &tl)
-
- gmove(&tl, res)
- } else {
- // a % (-1) is 0.
- var nz gc.Node
- gc.Nodconst(&nz, t, 0)
-
- gmove(&nz, res)
- }
-
- p2 = gc.Gbranch(obj.AJMP, nil, 0)
- gc.Patch(p1, gc.Pc)
- }
-
- p1 = gins(a, &tr, &tl)
+ gins3(a, &tr, &tl, nil)
+ gc.Regfree(&tr)
if op == gc.ODIV {
- gc.Regfree(&tr)
- gmove(&tl, res)
- } else {
- // A%B = A-(A/B*B)
- var tm gc.Node
- gc.Regalloc(&tm, t, nil)
-
- // patch div to use the 3 register form
- // TODO(minux): add gins3?
- p1.Reg = p1.To.Reg
-
- p1.To.Reg = tm.Reg
- gins(optoas(gc.OMUL, t), &tr, &tm)
- gc.Regfree(&tr)
- gins(optoas(gc.OSUB, t), &tm, &tl)
- gc.Regfree(&tm)
- gmove(&tl, res)
+ var lo gc.Node
+ gc.Nodreg(&lo, gc.Types[gc.TUINT64], mips.REG_LO)
+ gins(mips.AMOVV, &lo, &tl)
+ } else { // remainder in REG_HI
+ var hi gc.Node
+ gc.Nodreg(&hi, gc.Types[gc.TUINT64], mips.REG_HI)
+ gins(mips.AMOVV, &hi, &tl)
}
-
+ gmove(&tl, res)
gc.Regfree(&tl)
- if check != 0 {
- gc.Patch(p2, gc.Pc)
- }
}
/*
func cgen_hmul(nl *gc.Node, nr *gc.Node, res *gc.Node) {
// largest ullman on left.
if nl.Ullman < nr.Ullman {
- tmp := (*gc.Node)(nl)
- nl = nr
- nr = tmp
+ nl, nr = nr, nl
}
t := (*gc.Type)(nl.Type)
case gc.TINT8,
gc.TINT16,
gc.TINT32:
- gins(optoas(gc.OMUL, t), &n2, &n1)
- p := (*obj.Prog)(gins(ppc64.ASRAD, nil, &n1))
+ gins3(optoas(gc.OMUL, t), &n2, &n1, nil)
+ var lo gc.Node
+ gc.Nodreg(&lo, gc.Types[gc.TUINT64], mips.REG_LO)
+ gins(mips.AMOVV, &lo, &n1)
+ p := (*obj.Prog)(gins(mips.ASRAV, nil, &n1))
p.From.Type = obj.TYPE_CONST
p.From.Offset = int64(w)
case gc.TUINT8,
gc.TUINT16,
gc.TUINT32:
- gins(optoas(gc.OMUL, t), &n2, &n1)
- p := (*obj.Prog)(gins(ppc64.ASRD, nil, &n1))
+ gins3(optoas(gc.OMUL, t), &n2, &n1, nil)
+ var lo gc.Node
+ gc.Nodreg(&lo, gc.Types[gc.TUINT64], mips.REG_LO)
+ gins(mips.AMOVV, &lo, &n1)
+ p := (*obj.Prog)(gins(mips.ASRLV, nil, &n1))
p.From.Type = obj.TYPE_CONST
p.From.Offset = int64(w)
case gc.TINT64,
gc.TUINT64:
if gc.Issigned[t.Etype] {
- gins(ppc64.AMULHD, &n2, &n1)
+ gins3(mips.AMULV, &n2, &n1, nil)
} else {
- gins(ppc64.AMULHDU, &n2, &n1)
+ gins3(mips.AMULVU, &n2, &n1, nil)
}
+ var hi gc.Node
+ gc.Nodreg(&hi, gc.Types[gc.TUINT64], mips.REG_HI)
+ gins(mips.AMOVV, &hi, &n1)
default:
gc.Fatalf("cgen_hmul %v", t)
* res = nl << nr
* res = nl >> nr
*/
-func cgen_shift(op int, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
+func cgen_shift(op gc.Op, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
a := int(optoas(op, nl.Type))
if nr.Op == gc.OLITERAL {
// test and fix up large shifts
if !bounded {
+ var rtmp gc.Node
+ gc.Nodreg(&rtmp, tcount, mips.REGTMP)
gc.Nodconst(&n3, tcount, nl.Type.Width*8)
- gins(optoas(gc.OCMP, tcount), &n1, &n3)
- p1 := (*obj.Prog)(gc.Gbranch(optoas(gc.OLT, tcount), nil, +1))
+ gins3(mips.ASGTU, &n3, &n1, &rtmp)
+ p1 := ginsbranch(mips.ABNE, nil, &rtmp, nil, 0)
if op == gc.ORSH && gc.Issigned[nl.Type.Etype] {
gc.Nodconst(&n3, gc.Types[gc.TUINT32], nl.Type.Width*8-1)
gins(a, &n3, &n2)
c := uint64(w % 8) // bytes
q := uint64(w / 8) // dwords
- if gc.Reginuse(ppc64.REGRT1) {
- gc.Fatalf("%v in use during clearfat", obj.Rconv(ppc64.REGRT1))
+ if gc.Reginuse(mips.REGRT1) {
+ gc.Fatalf("%v in use during clearfat", obj.Rconv(mips.REGRT1))
}
var r0 gc.Node
- gc.Nodreg(&r0, gc.Types[gc.TUINT64], ppc64.REGZERO)
+ gc.Nodreg(&r0, gc.Types[gc.TUINT64], mips.REGZERO)
var dst gc.Node
- gc.Nodreg(&dst, gc.Types[gc.Tptr], ppc64.REGRT1)
+ gc.Nodreg(&dst, gc.Types[gc.Tptr], mips.REGRT1)
gc.Regrealloc(&dst)
gc.Agen(nl, &dst)
var boff uint64
if q > 128 {
- p := gins(ppc64.ASUB, nil, &dst)
+ p := gins(mips.ASUBV, nil, &dst)
p.From.Type = obj.TYPE_CONST
p.From.Offset = 8
var end gc.Node
gc.Regalloc(&end, gc.Types[gc.Tptr], nil)
- p = gins(ppc64.AMOVD, &dst, &end)
+ p = gins(mips.AMOVV, &dst, &end)
p.From.Type = obj.TYPE_ADDR
p.From.Offset = int64(q * 8)
- p = gins(ppc64.AMOVDU, &r0, &dst)
+ p = gins(mips.AMOVV, &r0, &dst)
p.To.Type = obj.TYPE_MEM
p.To.Offset = 8
pl := (*obj.Prog)(p)
- p = gins(ppc64.ACMP, &dst, &end)
- gc.Patch(gc.Gbranch(ppc64.ABNE, nil, 0), pl)
+ p = gins(mips.AADDV, nil, &dst)
+ p.From.Type = obj.TYPE_CONST
+ p.From.Offset = 8
+
+ gc.Patch(ginsbranch(mips.ABNE, nil, &dst, &end, 0), pl)
gc.Regfree(&end)
- // The loop leaves R3 on the last zeroed dword
+ // The loop leaves R1 on the last zeroed dword
boff = 8
// TODO(dfc): https://golang.org/issue/12108
// If DUFFZERO is used inside a tail call (see genwrapper) it will
// overwrite the link register.
} else if false && q >= 4 {
- p := gins(ppc64.ASUB, nil, &dst)
+ p := gins(mips.ASUBV, nil, &dst)
p.From.Type = obj.TYPE_CONST
p.From.Offset = 8
f := (*gc.Node)(gc.Sysfunc("duffzero"))
p = gins(obj.ADUFFZERO, nil, f)
gc.Afunclit(&p.To, f)
- // 4 and 128 = magic constants: see ../../runtime/asm_ppc64x.s
- p.To.Offset = int64(4 * (128 - q))
+ // 8 and 128 = magic constants: see ../../runtime/asm_mips64x.s
+ p.To.Offset = int64(8 * (128 - q))
- // duffzero leaves R3 on the last zeroed dword
+ // duffzero leaves R1 on the last zeroed dword
boff = 8
} else {
var p *obj.Prog
for t := uint64(0); t < q; t++ {
- p = gins(ppc64.AMOVD, &r0, &dst)
+ p = gins(mips.AMOVV, &r0, &dst)
p.To.Type = obj.TYPE_MEM
p.To.Offset = int64(8 * t)
}
var p *obj.Prog
for t := uint64(0); t < c; t++ {
- p = gins(ppc64.AMOVB, &r0, &dst)
+ p = gins(mips.AMOVB, &r0, &dst)
p.To.Type = obj.TYPE_MEM
p.To.Offset = int64(t + boff)
}
// Expand CHECKNIL pseudo-op into actual nil pointer check.
func expandchecks(firstp *obj.Prog) {
var p1 *obj.Prog
- var p2 *obj.Prog
for p := (*obj.Prog)(firstp); p != nil; p = p.Link {
if gc.Debug_checknil != 0 && gc.Ctxt.Debugvlog != 0 {
gc.Fatalf("invalid nil check %v\n", p)
}
- /*
- // check is
- // TD $4, R0, arg (R0 is always zero)
- // eqv. to:
- // tdeq r0, arg
- // NOTE: this needs special runtime support to make SIGTRAP recoverable.
- reg = p->from.reg;
- p->as = ATD;
- p->from = p->to = p->from3 = zprog.from;
- p->from.type = TYPE_CONST;
- p->from.offset = 4;
- p->from.reg = 0;
- p->reg = REGZERO;
- p->to.type = TYPE_REG;
- p->to.reg = reg;
- */
// check is
- // CMP arg, R0
- // BNE 2(PC) [likely]
- // MOVD R0, 0(R0)
+ // BNE arg, 2(PC)
+ // MOVV R0, 0(R0)
p1 = gc.Ctxt.NewProg()
-
- p2 = gc.Ctxt.NewProg()
gc.Clearp(p1)
- gc.Clearp(p2)
- p1.Link = p2
- p2.Link = p.Link
+ p1.Link = p.Link
p.Link = p1
p1.Lineno = p.Lineno
- p2.Lineno = p.Lineno
p1.Pc = 9999
- p2.Pc = 9999
- p.As = ppc64.ACMP
- p.To.Type = obj.TYPE_REG
- p.To.Reg = ppc64.REGZERO
- p1.As = ppc64.ABNE
- //p1->from.type = TYPE_CONST;
- //p1->from.offset = 1; // likely
- p1.To.Type = obj.TYPE_BRANCH
-
- p1.To.Val = p2.Link
+ p.As = mips.ABNE
+ p.To.Type = obj.TYPE_BRANCH
+ p.To.Val = p1.Link
// crash by write to memory address 0.
- p2.As = ppc64.AMOVD
-
- p2.From.Type = obj.TYPE_REG
- p2.From.Reg = ppc64.REGZERO
- p2.To.Type = obj.TYPE_MEM
- p2.To.Reg = ppc64.REGZERO
- p2.To.Offset = 0
+ p1.As = mips.AMOVV
+ p1.From.Type = obj.TYPE_REG
+ p1.From.Reg = mips.REGZERO
+ p1.To.Type = obj.TYPE_MEM
+ p1.To.Reg = mips.REGZERO
+ p1.To.Offset = 0
}
}
// res = runtime.getg()
func getg(res *gc.Node) {
var n1 gc.Node
- gc.Nodreg(&n1, res.Type, ppc64.REGG)
+ gc.Nodreg(&n1, res.Type, mips.REGG)
gmove(&n1, res)
}
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package ppc64
+package mips64
import (
"cmd/compile/internal/big"
"cmd/compile/internal/gc"
"cmd/internal/obj"
- "cmd/internal/obj/ppc64"
+ "cmd/internal/obj/mips"
"fmt"
)
var resvd = []int{
- ppc64.REGZERO,
- ppc64.REGSP, // reserved for SP
- // We need to preserve the C ABI TLS pointer because sigtramp
- // may happen during C code and needs to access the g. C
- // clobbers REGG, so if Go were to clobber REGTLS, sigtramp
- // won't know which convention to use. By preserving REGTLS,
- // we can just retrieve g from TLS when we aren't sure.
- ppc64.REGTLS,
-
- // TODO(austin): Consolidate REGTLS and REGG?
- ppc64.REGG,
- ppc64.REGTMP, // REGTMP
- ppc64.FREGCVI,
- ppc64.FREGZERO,
- ppc64.FREGHALF,
- ppc64.FREGONE,
- ppc64.FREGTWO,
+ mips.REGZERO,
+ mips.REGSP, // reserved for SP
+ mips.REGLINK, // reserved for link
+ mips.REGG,
+ mips.REGTMP,
+ mips.REG_R26, // kernel
+ mips.REG_R27, // kernel
+ mips.FREGZERO,
+ mips.FREGHALF,
+ mips.FREGONE,
+ mips.FREGTWO,
}
/*
gc.Nodconst(&n1, gc.Types[gc.TINT64], c)
- if as != ppc64.AMOVD && (c < -ppc64.BIG || c > ppc64.BIG) || n2.Op != gc.OREGISTER || as == ppc64.AMULLD {
+ if as != mips.AMOVV && (c < -mips.BIG || c > mips.BIG) || n2.Op != gc.OREGISTER || as == mips.AMUL || as == mips.AMULU || as == mips.AMULV || as == mips.AMULVU {
// cannot have more than 16-bit of immediate in ADD, etc.
// instead, MOV into register first.
var ntmp gc.Node
gc.Regalloc(&ntmp, gc.Types[gc.TINT64], nil)
- rawgins(ppc64.AMOVD, &n1, &ntmp)
+ rawgins(mips.AMOVV, &n1, &ntmp)
rawgins(as, &ntmp, n2)
gc.Regfree(&ntmp)
return
rawgins(as, &n1, n2)
}
-/*
- * generate
- * as n, $c (CMP/CMPU)
- */
-func ginscon2(as int, n2 *gc.Node, c int64) {
- var n1 gc.Node
-
- gc.Nodconst(&n1, gc.Types[gc.TINT64], c)
-
- switch as {
- default:
- gc.Fatalf("ginscon2")
-
- case ppc64.ACMP:
- if -ppc64.BIG <= c && c <= ppc64.BIG {
- rawgins(as, n2, &n1)
- return
- }
-
- case ppc64.ACMPU:
- if 0 <= c && c <= 2*ppc64.BIG {
- rawgins(as, n2, &n1)
- return
- }
+// generate branch
+// n1, n2 are registers
+func ginsbranch(as int, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
+ p := gc.Gbranch(as, t, likely)
+ gc.Naddr(&p.From, n1)
+ if n2 != nil {
+ p.Reg = n2.Reg
}
-
- // MOV n1 into register first
- var ntmp gc.Node
- gc.Regalloc(&ntmp, gc.Types[gc.TINT64], nil)
-
- rawgins(ppc64.AMOVD, &n1, &ntmp)
- rawgins(as, n2, &ntmp)
- gc.Regfree(&ntmp)
+ return p
}
-func ginscmp(op int, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
- if gc.Isint[t.Etype] && n1.Op == gc.OLITERAL && n2.Op != gc.OLITERAL {
- // Reverse comparison to place constant last.
- op = gc.Brrev(op)
+func ginscmp(op gc.Op, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
+ if !gc.Isfloat[t.Etype] && (op == gc.OLT || op == gc.OGE) {
+ // swap nodes to fit SGT instruction
n1, n2 = n2, n1
}
+ if gc.Isfloat[t.Etype] && (op == gc.OLT || op == gc.OLE) {
+ // swap nodes to fit CMPGT, CMPGE instructions and reverse relation
+ n1, n2 = n2, n1
+ if op == gc.OLT {
+ op = gc.OGT
+ } else {
+ op = gc.OGE
+ }
+ }
var r1, r2, g1, g2 gc.Node
gc.Regalloc(&r1, t, n1)
gc.Regalloc(&g1, n1.Type, &r1)
gc.Cgen(n1, &g1)
gmove(&g1, &r1)
- if gc.Isint[t.Etype] && gc.Isconst(n2, gc.CTINT) {
- ginscon2(optoas(gc.OCMP, t), &r1, n2.Int())
- } else {
- gc.Regalloc(&r2, t, n2)
- gc.Regalloc(&g2, n1.Type, &r2)
- gc.Cgen(n2, &g2)
- gmove(&g2, &r2)
- rawgins(optoas(gc.OCMP, t), &r1, &r2)
- gc.Regfree(&g2)
- gc.Regfree(&r2)
+
+ gc.Regalloc(&r2, t, n2)
+ gc.Regalloc(&g2, n1.Type, &r2)
+ gc.Cgen(n2, &g2)
+ gmove(&g2, &r2)
+
+ var p *obj.Prog
+ var ntmp gc.Node
+ gc.Nodreg(&ntmp, gc.Types[gc.TINT], mips.REGTMP)
+
+ switch gc.Simtype[t.Etype] {
+ case gc.TINT8,
+ gc.TINT16,
+ gc.TINT32,
+ gc.TINT64:
+ if op == gc.OEQ || op == gc.ONE {
+ p = ginsbranch(optoas(op, t), nil, &r1, &r2, likely)
+ } else {
+ gins3(mips.ASGT, &r1, &r2, &ntmp)
+
+ p = ginsbranch(optoas(op, t), nil, &ntmp, nil, likely)
+ }
+
+ case gc.TBOOL,
+ gc.TUINT8,
+ gc.TUINT16,
+ gc.TUINT32,
+ gc.TUINT64,
+ gc.TPTR32,
+ gc.TPTR64:
+ if op == gc.OEQ || op == gc.ONE {
+ p = ginsbranch(optoas(op, t), nil, &r1, &r2, likely)
+ } else {
+ gins3(mips.ASGTU, &r1, &r2, &ntmp)
+
+ p = ginsbranch(optoas(op, t), nil, &ntmp, nil, likely)
+ }
+
+ case gc.TFLOAT32:
+ switch op {
+ default:
+ gc.Fatalf("ginscmp: no entry for op=%v type=%v", gc.Oconv(int(op), 0), t)
+
+ case gc.OEQ,
+ gc.ONE:
+ gins3(mips.ACMPEQF, &r1, &r2, nil)
+
+ case gc.OGE:
+ gins3(mips.ACMPGEF, &r1, &r2, nil)
+
+ case gc.OGT:
+ gins3(mips.ACMPGTF, &r1, &r2, nil)
+ }
+ p = gc.Gbranch(optoas(op, t), nil, likely)
+
+ case gc.TFLOAT64:
+ switch op {
+ default:
+ gc.Fatalf("ginscmp: no entry for op=%v type=%v", gc.Oconv(int(op), 0), t)
+
+ case gc.OEQ,
+ gc.ONE:
+ gins3(mips.ACMPEQD, &r1, &r2, nil)
+
+ case gc.OGE:
+ gins3(mips.ACMPGED, &r1, &r2, nil)
+
+ case gc.OGT:
+ gins3(mips.ACMPGTD, &r1, &r2, nil)
+ }
+ p = gc.Gbranch(optoas(op, t), nil, likely)
}
+
+ gc.Regfree(&g2)
+ gc.Regfree(&r2)
gc.Regfree(&g1)
gc.Regfree(&r1)
- return gc.Gbranch(optoas(op, t), nil, likely)
+
+ return p
}
// set up nodes representing 2^63
f.Convconst(&con, gc.Types[gc.TINT64])
var r1 gc.Node
gc.Regalloc(&r1, con.Type, t)
- gins(ppc64.AMOVD, &con, &r1)
+ gins(mips.AMOVV, &con, &r1)
gmove(&r1, t)
gc.Regfree(&r1)
return
f.Convconst(&con, gc.Types[gc.TUINT64])
var r1 gc.Node
gc.Regalloc(&r1, con.Type, t)
- gins(ppc64.AMOVD, &con, &r1)
+ gins(mips.AMOVV, &con, &r1)
gmove(&r1, t)
gc.Regfree(&r1)
return
}
}
- // float constants come from memory.
- //if(isfloat[tt])
- // goto hard;
-
- // 64-bit immediates are also from memory.
- //if(isint[tt])
- // goto hard;
- //// 64-bit immediates are really 32-bit sign-extended
- //// unless moving into a register.
- //if(isint[tt]) {
- // if(mpcmpfixfix(con.val.u.xval, minintval[TINT32]) < 0)
- // goto hard;
- // if(mpcmpfixfix(con.val.u.xval, maxintval[TINT32]) > 0)
- // goto hard;
- //}
+ // value -> value copy, first operand in memory.
+ // any floating point operand requires register
+ // src, so goto hard to copy to register first.
+ if gc.Ismem(f) && ft != tt && (gc.Isfloat[ft] || gc.Isfloat[tt]) {
+ cvt = gc.Types[ft]
+ goto hard
+ }
// value -> value copy, only one memory operand.
// figure out the instruction to use.
*/
case gc.TINT8<<16 | gc.TINT8, // same size
gc.TUINT8<<16 | gc.TINT8,
- gc.TINT16<<16 | gc.TINT8,
- // truncate
+ gc.TINT16<<16 | gc.TINT8, // truncate
gc.TUINT16<<16 | gc.TINT8,
gc.TINT32<<16 | gc.TINT8,
gc.TUINT32<<16 | gc.TINT8,
gc.TINT64<<16 | gc.TINT8,
gc.TUINT64<<16 | gc.TINT8:
- a = ppc64.AMOVB
+ a = mips.AMOVB
case gc.TINT8<<16 | gc.TUINT8, // same size
gc.TUINT8<<16 | gc.TUINT8,
- gc.TINT16<<16 | gc.TUINT8,
- // truncate
+ gc.TINT16<<16 | gc.TUINT8, // truncate
gc.TUINT16<<16 | gc.TUINT8,
gc.TINT32<<16 | gc.TUINT8,
gc.TUINT32<<16 | gc.TUINT8,
gc.TINT64<<16 | gc.TUINT8,
gc.TUINT64<<16 | gc.TUINT8:
- a = ppc64.AMOVBZ
+ a = mips.AMOVBU
case gc.TINT16<<16 | gc.TINT16, // same size
gc.TUINT16<<16 | gc.TINT16,
- gc.TINT32<<16 | gc.TINT16,
- // truncate
+ gc.TINT32<<16 | gc.TINT16, // truncate
gc.TUINT32<<16 | gc.TINT16,
gc.TINT64<<16 | gc.TINT16,
gc.TUINT64<<16 | gc.TINT16:
- a = ppc64.AMOVH
+ a = mips.AMOVH
case gc.TINT16<<16 | gc.TUINT16, // same size
gc.TUINT16<<16 | gc.TUINT16,
- gc.TINT32<<16 | gc.TUINT16,
- // truncate
+ gc.TINT32<<16 | gc.TUINT16, // truncate
gc.TUINT32<<16 | gc.TUINT16,
gc.TINT64<<16 | gc.TUINT16,
gc.TUINT64<<16 | gc.TUINT16:
- a = ppc64.AMOVHZ
+ a = mips.AMOVHU
case gc.TINT32<<16 | gc.TINT32, // same size
gc.TUINT32<<16 | gc.TINT32,
- gc.TINT64<<16 | gc.TINT32,
- // truncate
+ gc.TINT64<<16 | gc.TINT32, // truncate
gc.TUINT64<<16 | gc.TINT32:
- a = ppc64.AMOVW
+ a = mips.AMOVW
case gc.TINT32<<16 | gc.TUINT32, // same size
gc.TUINT32<<16 | gc.TUINT32,
- gc.TINT64<<16 | gc.TUINT32,
+ gc.TINT64<<16 | gc.TUINT32, // truncate
gc.TUINT64<<16 | gc.TUINT32:
- a = ppc64.AMOVWZ
+ a = mips.AMOVWU
case gc.TINT64<<16 | gc.TINT64, // same size
gc.TINT64<<16 | gc.TUINT64,
gc.TUINT64<<16 | gc.TINT64,
gc.TUINT64<<16 | gc.TUINT64:
- a = ppc64.AMOVD
+ a = mips.AMOVV
/*
* integer up-conversions
gc.TINT8<<16 | gc.TUINT32,
gc.TINT8<<16 | gc.TINT64,
gc.TINT8<<16 | gc.TUINT64:
- a = ppc64.AMOVB
+ a = mips.AMOVB
goto rdst
gc.TUINT8<<16 | gc.TUINT32,
gc.TUINT8<<16 | gc.TINT64,
gc.TUINT8<<16 | gc.TUINT64:
- a = ppc64.AMOVBZ
+ a = mips.AMOVBU
goto rdst
gc.TINT16<<16 | gc.TUINT32,
gc.TINT16<<16 | gc.TINT64,
gc.TINT16<<16 | gc.TUINT64:
- a = ppc64.AMOVH
+ a = mips.AMOVH
goto rdst
gc.TUINT16<<16 | gc.TUINT32,
gc.TUINT16<<16 | gc.TINT64,
gc.TUINT16<<16 | gc.TUINT64:
- a = ppc64.AMOVHZ
+ a = mips.AMOVHU
goto rdst
case gc.TINT32<<16 | gc.TINT64, // sign extend int32
gc.TINT32<<16 | gc.TUINT64:
- a = ppc64.AMOVW
+ a = mips.AMOVW
goto rdst
case gc.TUINT32<<16 | gc.TINT64, // zero extend uint32
gc.TUINT32<<16 | gc.TUINT64:
- a = ppc64.AMOVWZ
+ a = mips.AMOVWU
goto rdst
gc.TFLOAT64<<16 | gc.TUINT64:
bignodes()
- var r1 gc.Node
- gc.Regalloc(&r1, gc.Types[ft], f)
+ gc.Regalloc(&r1, gc.Types[gc.TFLOAT64], nil)
gmove(f, &r1)
if tt == gc.TUINT64 {
gc.Regalloc(&r2, gc.Types[gc.TFLOAT64], nil)
gmove(&bigf, &r2)
- gins(ppc64.AFCMPU, &r1, &r2)
- p1 := (*obj.Prog)(gc.Gbranch(optoas(gc.OLT, gc.Types[gc.TFLOAT64]), nil, +1))
- gins(ppc64.AFSUB, &r2, &r1)
+ gins3(mips.ACMPGED, &r1, &r2, nil)
+ p1 := gc.Gbranch(mips.ABFPF, nil, 0)
+ gins(mips.ASUBD, &r2, &r1)
gc.Patch(p1, gc.Pc)
gc.Regfree(&r2)
}
- gc.Regalloc(&r2, gc.Types[gc.TFLOAT64], nil)
- var r3 gc.Node
- gc.Regalloc(&r3, gc.Types[gc.TINT64], t)
- gins(ppc64.AFCTIDZ, &r1, &r2)
- p1 := (*obj.Prog)(gins(ppc64.AFMOVD, &r2, nil))
- p1.To.Type = obj.TYPE_MEM
- p1.To.Reg = ppc64.REGSP
- p1.To.Offset = -8
- p1 = gins(ppc64.AMOVD, nil, &r3)
- p1.From.Type = obj.TYPE_MEM
- p1.From.Reg = ppc64.REGSP
- p1.From.Offset = -8
- gc.Regfree(&r2)
+ gc.Regalloc(&r2, gc.Types[gc.TINT64], t)
+ gins(mips.ATRUNCDV, &r1, &r1)
+ gins(mips.AMOVV, &r1, &r2)
gc.Regfree(&r1)
+
if tt == gc.TUINT64 {
- p1 := (*obj.Prog)(gc.Gbranch(optoas(gc.OLT, gc.Types[gc.TFLOAT64]), nil, +1)) // use CR0 here again
- gc.Nodreg(&r1, gc.Types[gc.TINT64], ppc64.REGTMP)
- gins(ppc64.AMOVD, &bigi, &r1)
- gins(ppc64.AADD, &r1, &r3)
+ p1 := gc.Gbranch(mips.ABFPF, nil, 0) // use FCR0 here again
+ gc.Nodreg(&r1, gc.Types[gc.TINT64], mips.REGTMP)
+ gmove(&bigi, &r1)
+ gins(mips.AADDVU, &r1, &r2)
gc.Patch(p1, gc.Pc)
}
- gmove(&r3, t)
- gc.Regfree(&r3)
+ gmove(&r2, t)
+ gc.Regfree(&r2)
return
//warn("gmove: convert int to float not implemented: %N -> %N\n", f, t);
//return;
// algorithm is:
- // if small enough, use native int64 -> uint64 conversion.
+ // if small enough, use native int64 -> float64 conversion.
// otherwise, halve (rounding to odd?), convert, and double.
/*
* integer to float
gc.TUINT64<<16 | gc.TFLOAT64:
bignodes()
- var r1 gc.Node
+ var rtmp gc.Node
gc.Regalloc(&r1, gc.Types[gc.TINT64], nil)
gmove(f, &r1)
if ft == gc.TUINT64 {
- gc.Nodreg(&r2, gc.Types[gc.TUINT64], ppc64.REGTMP)
- gmove(&bigi, &r2)
- gins(ppc64.ACMPU, &r1, &r2)
- p1 := (*obj.Prog)(gc.Gbranch(optoas(gc.OLT, gc.Types[gc.TUINT64]), nil, +1))
- p2 := (*obj.Prog)(gins(ppc64.ASRD, nil, &r1))
+ gc.Nodreg(&rtmp, gc.Types[gc.TUINT64], mips.REGTMP)
+ gmove(&bigi, &rtmp)
+ gins(mips.AAND, &r1, &rtmp)
+ p1 := ginsbranch(mips.ABEQ, nil, &rtmp, nil, 0)
+ p2 := gins(mips.ASRLV, nil, &r1)
p2.From.Type = obj.TYPE_CONST
p2.From.Offset = 1
gc.Patch(p1, gc.Pc)
}
gc.Regalloc(&r2, gc.Types[gc.TFLOAT64], t)
- p1 := (*obj.Prog)(gins(ppc64.AMOVD, &r1, nil))
- p1.To.Type = obj.TYPE_MEM
- p1.To.Reg = ppc64.REGSP
- p1.To.Offset = -8
- p1 = gins(ppc64.AFMOVD, nil, &r2)
- p1.From.Type = obj.TYPE_MEM
- p1.From.Reg = ppc64.REGSP
- p1.From.Offset = -8
- gins(ppc64.AFCFID, &r2, &r2)
+ gins(mips.AMOVV, &r1, &r2)
+ gins(mips.AMOVVD, &r2, &r2)
gc.Regfree(&r1)
+
if ft == gc.TUINT64 {
- p1 := (*obj.Prog)(gc.Gbranch(optoas(gc.OLT, gc.Types[gc.TUINT64]), nil, +1)) // use CR0 here again
- gc.Nodreg(&r1, gc.Types[gc.TFLOAT64], ppc64.FREGTWO)
- gins(ppc64.AFMUL, &r1, &r2)
+ p1 := ginsbranch(mips.ABEQ, nil, &rtmp, nil, 0)
+ gc.Nodreg(&r1, gc.Types[gc.TFLOAT64], mips.FREGTWO)
+ gins(mips.AMULD, &r1, &r2)
gc.Patch(p1, gc.Pc)
}
* float to float
*/
case gc.TFLOAT32<<16 | gc.TFLOAT32:
- a = ppc64.AFMOVS
+ a = mips.AMOVF
case gc.TFLOAT64<<16 | gc.TFLOAT64:
- a = ppc64.AFMOVD
+ a = mips.AMOVD
case gc.TFLOAT32<<16 | gc.TFLOAT64:
- a = ppc64.AFMOVS
+ a = mips.AMOVFD
goto rdst
case gc.TFLOAT64<<16 | gc.TFLOAT32:
- a = ppc64.AFRSP
+ a = mips.AMOVDF
goto rdst
}
return nil // caller must not use
}
}
- if as == ppc64.ACMP || as == ppc64.ACMPU {
- if x, ok := t.IntLiteral(); ok {
- ginscon2(as, f, x)
- return nil // caller must not use
- }
- }
return rawgins(as, f, t)
}
+/*
+ * generate one instruction:
+ * as f, r, t
+ * r must be register, if not nil
+ */
+func gins3(as int, f, r, t *gc.Node) *obj.Prog {
+ p := rawgins(as, f, t)
+ if r != nil {
+ p.Reg = r.Reg
+ }
+ return p
+}
+
/*
* generate one instruction:
* as f, t
switch as {
case obj.ACALL:
- if p.To.Type == obj.TYPE_REG && p.To.Reg != ppc64.REG_CTR {
- // Allow front end to emit CALL REG, and rewrite into MOV REG, CTR; CALL CTR.
- pp := gc.Prog(as)
- pp.From = p.From
- pp.To.Type = obj.TYPE_REG
- pp.To.Reg = ppc64.REG_CTR
-
- p.As = ppc64.AMOVD
- p.From = p.To
- p.To.Type = obj.TYPE_REG
- p.To.Reg = ppc64.REG_CTR
+ if p.To.Type == obj.TYPE_REG {
+ // Allow front end to emit CALL REG, and rewrite into CALL (REG).
+ p.From = obj.Addr{}
+ p.To.Type = obj.TYPE_MEM
+ p.To.Offset = 0
if gc.Debug['g'] != 0 {
fmt.Printf("%v\n", p)
- fmt.Printf("%v\n", pp)
}
- return pp
+ return p
}
// Bad things the front end has done to us. Crash to find call stack.
- case ppc64.AAND, ppc64.AMULLD:
+ case mips.AAND:
if p.From.Type == obj.TYPE_CONST {
gc.Debug['h'] = 1
gc.Fatalf("bad inst: %v", p)
}
- case ppc64.ACMP, ppc64.ACMPU:
+ case mips.ASGT, mips.ASGTU:
if p.From.Type == obj.TYPE_MEM || p.To.Type == obj.TYPE_MEM {
gc.Debug['h'] = 1
gc.Fatalf("bad inst: %v", p)
}
+
+ // Special cases
+ case mips.AMUL, mips.AMULU, mips.AMULV, mips.AMULVU:
+ if p.From.Type == obj.TYPE_CONST {
+ gc.Debug['h'] = 1
+ gc.Fatalf("bad inst: %v", p)
+ }
+
+ pp := gc.Prog(mips.AMOVV)
+ pp.From.Type = obj.TYPE_REG
+ pp.From.Reg = mips.REG_LO
+ pp.To = p.To
+
+ p.Reg = p.To.Reg
+ p.To = obj.Addr{}
+
+ case mips.ASUBVU:
+ // unary
+ if f == nil {
+ p.From = p.To
+ p.Reg = mips.REGZERO
+ }
}
if gc.Debug['g'] != 0 {
w := int32(0)
switch as {
- case ppc64.AMOVB,
- ppc64.AMOVBU,
- ppc64.AMOVBZ,
- ppc64.AMOVBZU:
+ case mips.AMOVB,
+ mips.AMOVBU:
w = 1
- case ppc64.AMOVH,
- ppc64.AMOVHU,
- ppc64.AMOVHZ,
- ppc64.AMOVHZU:
+ case mips.AMOVH,
+ mips.AMOVHU:
w = 2
- case ppc64.AMOVW,
- ppc64.AMOVWU,
- ppc64.AMOVWZ,
- ppc64.AMOVWZU:
+ case mips.AMOVW,
+ mips.AMOVWU:
w = 4
- case ppc64.AMOVD,
- ppc64.AMOVDU:
+ case mips.AMOVV:
if p.From.Type == obj.TYPE_CONST || p.From.Type == obj.TYPE_ADDR {
break
}
/*
* return Axxx for Oxxx on type t.
*/
-func optoas(op int, t *gc.Type) int {
+func optoas(op gc.Op, t *gc.Type) int {
if t == nil {
gc.Fatalf("optoas: t is nil")
}
+ // avoid constant conversions in switches below
+ const (
+ OMINUS_ = uint32(gc.OMINUS) << 16
+ OLSH_ = uint32(gc.OLSH) << 16
+ ORSH_ = uint32(gc.ORSH) << 16
+ OADD_ = uint32(gc.OADD) << 16
+ OSUB_ = uint32(gc.OSUB) << 16
+ OMUL_ = uint32(gc.OMUL) << 16
+ ODIV_ = uint32(gc.ODIV) << 16
+ OOR_ = uint32(gc.OOR) << 16
+ OAND_ = uint32(gc.OAND) << 16
+ OXOR_ = uint32(gc.OXOR) << 16
+ OEQ_ = uint32(gc.OEQ) << 16
+ ONE_ = uint32(gc.ONE) << 16
+ OLT_ = uint32(gc.OLT) << 16
+ OLE_ = uint32(gc.OLE) << 16
+ OGE_ = uint32(gc.OGE) << 16
+ OGT_ = uint32(gc.OGT) << 16
+ OCMP_ = uint32(gc.OCMP) << 16
+ OAS_ = uint32(gc.OAS) << 16
+ OHMUL_ = uint32(gc.OHMUL) << 16
+ )
+
a := int(obj.AXXX)
switch uint32(op)<<16 | uint32(gc.Simtype[t.Etype]) {
default:
gc.Fatalf("optoas: no entry for op=%v type=%v", gc.Oconv(int(op), 0), t)
- case gc.OEQ<<16 | gc.TBOOL,
- gc.OEQ<<16 | gc.TINT8,
- gc.OEQ<<16 | gc.TUINT8,
- gc.OEQ<<16 | gc.TINT16,
- gc.OEQ<<16 | gc.TUINT16,
- gc.OEQ<<16 | gc.TINT32,
- gc.OEQ<<16 | gc.TUINT32,
- gc.OEQ<<16 | gc.TINT64,
- gc.OEQ<<16 | gc.TUINT64,
- gc.OEQ<<16 | gc.TPTR32,
- gc.OEQ<<16 | gc.TPTR64,
- gc.OEQ<<16 | gc.TFLOAT32,
- gc.OEQ<<16 | gc.TFLOAT64:
- a = ppc64.ABEQ
-
- case gc.ONE<<16 | gc.TBOOL,
- gc.ONE<<16 | gc.TINT8,
- gc.ONE<<16 | gc.TUINT8,
- gc.ONE<<16 | gc.TINT16,
- gc.ONE<<16 | gc.TUINT16,
- gc.ONE<<16 | gc.TINT32,
- gc.ONE<<16 | gc.TUINT32,
- gc.ONE<<16 | gc.TINT64,
- gc.ONE<<16 | gc.TUINT64,
- gc.ONE<<16 | gc.TPTR32,
- gc.ONE<<16 | gc.TPTR64,
- gc.ONE<<16 | gc.TFLOAT32,
- gc.ONE<<16 | gc.TFLOAT64:
- a = ppc64.ABNE
-
- case gc.OLT<<16 | gc.TINT8, // ACMP
- gc.OLT<<16 | gc.TINT16,
- gc.OLT<<16 | gc.TINT32,
- gc.OLT<<16 | gc.TINT64,
- gc.OLT<<16 | gc.TUINT8,
- // ACMPU
- gc.OLT<<16 | gc.TUINT16,
- gc.OLT<<16 | gc.TUINT32,
- gc.OLT<<16 | gc.TUINT64,
- gc.OLT<<16 | gc.TFLOAT32,
- // AFCMPU
- gc.OLT<<16 | gc.TFLOAT64:
- a = ppc64.ABLT
-
- case gc.OLE<<16 | gc.TINT8, // ACMP
- gc.OLE<<16 | gc.TINT16,
- gc.OLE<<16 | gc.TINT32,
- gc.OLE<<16 | gc.TINT64,
- gc.OLE<<16 | gc.TUINT8,
- // ACMPU
- gc.OLE<<16 | gc.TUINT16,
- gc.OLE<<16 | gc.TUINT32,
- gc.OLE<<16 | gc.TUINT64:
- // No OLE for floats, because it mishandles NaN.
- // Front end must reverse comparison or use OLT and OEQ together.
- a = ppc64.ABLE
-
- case gc.OGT<<16 | gc.TINT8,
- gc.OGT<<16 | gc.TINT16,
- gc.OGT<<16 | gc.TINT32,
- gc.OGT<<16 | gc.TINT64,
- gc.OGT<<16 | gc.TUINT8,
- gc.OGT<<16 | gc.TUINT16,
- gc.OGT<<16 | gc.TUINT32,
- gc.OGT<<16 | gc.TUINT64,
- gc.OGT<<16 | gc.TFLOAT32,
- gc.OGT<<16 | gc.TFLOAT64:
- a = ppc64.ABGT
-
- case gc.OGE<<16 | gc.TINT8,
- gc.OGE<<16 | gc.TINT16,
- gc.OGE<<16 | gc.TINT32,
- gc.OGE<<16 | gc.TINT64,
- gc.OGE<<16 | gc.TUINT8,
- gc.OGE<<16 | gc.TUINT16,
- gc.OGE<<16 | gc.TUINT32,
- gc.OGE<<16 | gc.TUINT64:
- // No OGE for floats, because it mishandles NaN.
- // Front end must reverse comparison or use OLT and OEQ together.
- a = ppc64.ABGE
-
- case gc.OCMP<<16 | gc.TBOOL,
- gc.OCMP<<16 | gc.TINT8,
- gc.OCMP<<16 | gc.TINT16,
- gc.OCMP<<16 | gc.TINT32,
- gc.OCMP<<16 | gc.TPTR32,
- gc.OCMP<<16 | gc.TINT64:
- a = ppc64.ACMP
-
- case gc.OCMP<<16 | gc.TUINT8,
- gc.OCMP<<16 | gc.TUINT16,
- gc.OCMP<<16 | gc.TUINT32,
- gc.OCMP<<16 | gc.TUINT64,
- gc.OCMP<<16 | gc.TPTR64:
- a = ppc64.ACMPU
-
- case gc.OCMP<<16 | gc.TFLOAT32,
- gc.OCMP<<16 | gc.TFLOAT64:
- a = ppc64.AFCMPU
-
- case gc.OAS<<16 | gc.TBOOL,
- gc.OAS<<16 | gc.TINT8:
- a = ppc64.AMOVB
-
- case gc.OAS<<16 | gc.TUINT8:
- a = ppc64.AMOVBZ
-
- case gc.OAS<<16 | gc.TINT16:
- a = ppc64.AMOVH
-
- case gc.OAS<<16 | gc.TUINT16:
- a = ppc64.AMOVHZ
-
- case gc.OAS<<16 | gc.TINT32:
- a = ppc64.AMOVW
-
- case gc.OAS<<16 | gc.TUINT32,
- gc.OAS<<16 | gc.TPTR32:
- a = ppc64.AMOVWZ
-
- case gc.OAS<<16 | gc.TINT64,
- gc.OAS<<16 | gc.TUINT64,
- gc.OAS<<16 | gc.TPTR64:
- a = ppc64.AMOVD
-
- case gc.OAS<<16 | gc.TFLOAT32:
- a = ppc64.AFMOVS
-
- case gc.OAS<<16 | gc.TFLOAT64:
- a = ppc64.AFMOVD
-
- case gc.OADD<<16 | gc.TINT8,
- gc.OADD<<16 | gc.TUINT8,
- gc.OADD<<16 | gc.TINT16,
- gc.OADD<<16 | gc.TUINT16,
- gc.OADD<<16 | gc.TINT32,
- gc.OADD<<16 | gc.TUINT32,
- gc.OADD<<16 | gc.TPTR32,
- gc.OADD<<16 | gc.TINT64,
- gc.OADD<<16 | gc.TUINT64,
- gc.OADD<<16 | gc.TPTR64:
- a = ppc64.AADD
-
- case gc.OADD<<16 | gc.TFLOAT32:
- a = ppc64.AFADDS
-
- case gc.OADD<<16 | gc.TFLOAT64:
- a = ppc64.AFADD
-
- case gc.OSUB<<16 | gc.TINT8,
- gc.OSUB<<16 | gc.TUINT8,
- gc.OSUB<<16 | gc.TINT16,
- gc.OSUB<<16 | gc.TUINT16,
- gc.OSUB<<16 | gc.TINT32,
- gc.OSUB<<16 | gc.TUINT32,
- gc.OSUB<<16 | gc.TPTR32,
- gc.OSUB<<16 | gc.TINT64,
- gc.OSUB<<16 | gc.TUINT64,
- gc.OSUB<<16 | gc.TPTR64:
- a = ppc64.ASUB
-
- case gc.OSUB<<16 | gc.TFLOAT32:
- a = ppc64.AFSUBS
-
- case gc.OSUB<<16 | gc.TFLOAT64:
- a = ppc64.AFSUB
-
- case gc.OMINUS<<16 | gc.TINT8,
- gc.OMINUS<<16 | gc.TUINT8,
- gc.OMINUS<<16 | gc.TINT16,
- gc.OMINUS<<16 | gc.TUINT16,
- gc.OMINUS<<16 | gc.TINT32,
- gc.OMINUS<<16 | gc.TUINT32,
- gc.OMINUS<<16 | gc.TPTR32,
- gc.OMINUS<<16 | gc.TINT64,
- gc.OMINUS<<16 | gc.TUINT64,
- gc.OMINUS<<16 | gc.TPTR64:
- a = ppc64.ANEG
-
- case gc.OAND<<16 | gc.TINT8,
- gc.OAND<<16 | gc.TUINT8,
- gc.OAND<<16 | gc.TINT16,
- gc.OAND<<16 | gc.TUINT16,
- gc.OAND<<16 | gc.TINT32,
- gc.OAND<<16 | gc.TUINT32,
- gc.OAND<<16 | gc.TPTR32,
- gc.OAND<<16 | gc.TINT64,
- gc.OAND<<16 | gc.TUINT64,
- gc.OAND<<16 | gc.TPTR64:
- a = ppc64.AAND
-
- case gc.OOR<<16 | gc.TINT8,
- gc.OOR<<16 | gc.TUINT8,
- gc.OOR<<16 | gc.TINT16,
- gc.OOR<<16 | gc.TUINT16,
- gc.OOR<<16 | gc.TINT32,
- gc.OOR<<16 | gc.TUINT32,
- gc.OOR<<16 | gc.TPTR32,
- gc.OOR<<16 | gc.TINT64,
- gc.OOR<<16 | gc.TUINT64,
- gc.OOR<<16 | gc.TPTR64:
- a = ppc64.AOR
-
- case gc.OXOR<<16 | gc.TINT8,
- gc.OXOR<<16 | gc.TUINT8,
- gc.OXOR<<16 | gc.TINT16,
- gc.OXOR<<16 | gc.TUINT16,
- gc.OXOR<<16 | gc.TINT32,
- gc.OXOR<<16 | gc.TUINT32,
- gc.OXOR<<16 | gc.TPTR32,
- gc.OXOR<<16 | gc.TINT64,
- gc.OXOR<<16 | gc.TUINT64,
- gc.OXOR<<16 | gc.TPTR64:
- a = ppc64.AXOR
+ case OEQ_ | gc.TBOOL,
+ OEQ_ | gc.TINT8,
+ OEQ_ | gc.TUINT8,
+ OEQ_ | gc.TINT16,
+ OEQ_ | gc.TUINT16,
+ OEQ_ | gc.TINT32,
+ OEQ_ | gc.TUINT32,
+ OEQ_ | gc.TINT64,
+ OEQ_ | gc.TUINT64,
+ OEQ_ | gc.TPTR32,
+ OEQ_ | gc.TPTR64:
+ a = mips.ABEQ
+
+ case OEQ_ | gc.TFLOAT32, // ACMPEQF
+ OEQ_ | gc.TFLOAT64: // ACMPEQD
+ a = mips.ABFPT
+
+ case ONE_ | gc.TBOOL,
+ ONE_ | gc.TINT8,
+ ONE_ | gc.TUINT8,
+ ONE_ | gc.TINT16,
+ ONE_ | gc.TUINT16,
+ ONE_ | gc.TINT32,
+ ONE_ | gc.TUINT32,
+ ONE_ | gc.TINT64,
+ ONE_ | gc.TUINT64,
+ ONE_ | gc.TPTR32,
+ ONE_ | gc.TPTR64:
+ a = mips.ABNE
+
+ case ONE_ | gc.TFLOAT32, // ACMPEQF
+ ONE_ | gc.TFLOAT64: // ACMPEQD
+ a = mips.ABFPF
+
+ case OLT_ | gc.TINT8, // ASGT
+ OLT_ | gc.TINT16,
+ OLT_ | gc.TINT32,
+ OLT_ | gc.TINT64,
+ OLT_ | gc.TUINT8, // ASGTU
+ OLT_ | gc.TUINT16,
+ OLT_ | gc.TUINT32,
+ OLT_ | gc.TUINT64:
+ a = mips.ABNE
+
+ case OLT_ | gc.TFLOAT32, // ACMPGEF
+ OLT_ | gc.TFLOAT64: // ACMPGED
+ a = mips.ABFPT
+
+ case OLE_ | gc.TINT8, // ASGT
+ OLE_ | gc.TINT16,
+ OLE_ | gc.TINT32,
+ OLE_ | gc.TINT64,
+ OLE_ | gc.TUINT8, // ASGTU
+ OLE_ | gc.TUINT16,
+ OLE_ | gc.TUINT32,
+ OLE_ | gc.TUINT64:
+ a = mips.ABEQ
+
+ case OLE_ | gc.TFLOAT32, // ACMPGTF
+ OLE_ | gc.TFLOAT64: // ACMPGTD
+ a = mips.ABFPT
+
+ case OGT_ | gc.TINT8, // ASGT
+ OGT_ | gc.TINT16,
+ OGT_ | gc.TINT32,
+ OGT_ | gc.TINT64,
+ OGT_ | gc.TUINT8, // ASGTU
+ OGT_ | gc.TUINT16,
+ OGT_ | gc.TUINT32,
+ OGT_ | gc.TUINT64:
+ a = mips.ABNE
+
+ case OGT_ | gc.TFLOAT32, // ACMPGTF
+ OGT_ | gc.TFLOAT64: // ACMPGTD
+ a = mips.ABFPT
+
+ case OGE_ | gc.TINT8, // ASGT
+ OGE_ | gc.TINT16,
+ OGE_ | gc.TINT32,
+ OGE_ | gc.TINT64,
+ OGE_ | gc.TUINT8, // ASGTU
+ OGE_ | gc.TUINT16,
+ OGE_ | gc.TUINT32,
+ OGE_ | gc.TUINT64:
+ a = mips.ABEQ
+
+ case OGE_ | gc.TFLOAT32, // ACMPGEF
+ OGE_ | gc.TFLOAT64: // ACMPGED
+ a = mips.ABFPT
+
+ case OAS_ | gc.TBOOL,
+ OAS_ | gc.TINT8:
+ a = mips.AMOVB
+
+ case OAS_ | gc.TUINT8:
+ a = mips.AMOVBU
+
+ case OAS_ | gc.TINT16:
+ a = mips.AMOVH
+
+ case OAS_ | gc.TUINT16:
+ a = mips.AMOVHU
+
+ case OAS_ | gc.TINT32:
+ a = mips.AMOVW
+
+ case OAS_ | gc.TUINT32,
+ OAS_ | gc.TPTR32:
+ a = mips.AMOVWU
+
+ case OAS_ | gc.TINT64,
+ OAS_ | gc.TUINT64,
+ OAS_ | gc.TPTR64:
+ a = mips.AMOVV
+
+ case OAS_ | gc.TFLOAT32:
+ a = mips.AMOVF
+
+ case OAS_ | gc.TFLOAT64:
+ a = mips.AMOVD
+
+ case OADD_ | gc.TINT8,
+ OADD_ | gc.TUINT8,
+ OADD_ | gc.TINT16,
+ OADD_ | gc.TUINT16,
+ OADD_ | gc.TINT32,
+ OADD_ | gc.TUINT32,
+ OADD_ | gc.TPTR32:
+ a = mips.AADDU
+
+ case OADD_ | gc.TINT64,
+ OADD_ | gc.TUINT64,
+ OADD_ | gc.TPTR64:
+ a = mips.AADDVU
+
+ case OADD_ | gc.TFLOAT32:
+ a = mips.AADDF
+
+ case OADD_ | gc.TFLOAT64:
+ a = mips.AADDD
+
+ case OSUB_ | gc.TINT8,
+ OSUB_ | gc.TUINT8,
+ OSUB_ | gc.TINT16,
+ OSUB_ | gc.TUINT16,
+ OSUB_ | gc.TINT32,
+ OSUB_ | gc.TUINT32,
+ OSUB_ | gc.TPTR32:
+ a = mips.ASUBU
+
+ case OSUB_ | gc.TINT64,
+ OSUB_ | gc.TUINT64,
+ OSUB_ | gc.TPTR64:
+ a = mips.ASUBVU
+
+ case OSUB_ | gc.TFLOAT32:
+ a = mips.ASUBF
+
+ case OSUB_ | gc.TFLOAT64:
+ a = mips.ASUBD
+
+ case OMINUS_ | gc.TINT8,
+ OMINUS_ | gc.TUINT8,
+ OMINUS_ | gc.TINT16,
+ OMINUS_ | gc.TUINT16,
+ OMINUS_ | gc.TINT32,
+ OMINUS_ | gc.TUINT32,
+ OMINUS_ | gc.TPTR32,
+ OMINUS_ | gc.TINT64,
+ OMINUS_ | gc.TUINT64,
+ OMINUS_ | gc.TPTR64:
+ a = mips.ASUBVU
+
+ case OAND_ | gc.TINT8,
+ OAND_ | gc.TUINT8,
+ OAND_ | gc.TINT16,
+ OAND_ | gc.TUINT16,
+ OAND_ | gc.TINT32,
+ OAND_ | gc.TUINT32,
+ OAND_ | gc.TPTR32,
+ OAND_ | gc.TINT64,
+ OAND_ | gc.TUINT64,
+ OAND_ | gc.TPTR64:
+ a = mips.AAND
+
+ case OOR_ | gc.TINT8,
+ OOR_ | gc.TUINT8,
+ OOR_ | gc.TINT16,
+ OOR_ | gc.TUINT16,
+ OOR_ | gc.TINT32,
+ OOR_ | gc.TUINT32,
+ OOR_ | gc.TPTR32,
+ OOR_ | gc.TINT64,
+ OOR_ | gc.TUINT64,
+ OOR_ | gc.TPTR64:
+ a = mips.AOR
+
+ case OXOR_ | gc.TINT8,
+ OXOR_ | gc.TUINT8,
+ OXOR_ | gc.TINT16,
+ OXOR_ | gc.TUINT16,
+ OXOR_ | gc.TINT32,
+ OXOR_ | gc.TUINT32,
+ OXOR_ | gc.TPTR32,
+ OXOR_ | gc.TINT64,
+ OXOR_ | gc.TUINT64,
+ OXOR_ | gc.TPTR64:
+ a = mips.AXOR
// TODO(minux): handle rotates
//case CASE(OLROT, TINT8):
// a = 0//???; RLDC?
// break;
- case gc.OLSH<<16 | gc.TINT8,
- gc.OLSH<<16 | gc.TUINT8,
- gc.OLSH<<16 | gc.TINT16,
- gc.OLSH<<16 | gc.TUINT16,
- gc.OLSH<<16 | gc.TINT32,
- gc.OLSH<<16 | gc.TUINT32,
- gc.OLSH<<16 | gc.TPTR32,
- gc.OLSH<<16 | gc.TINT64,
- gc.OLSH<<16 | gc.TUINT64,
- gc.OLSH<<16 | gc.TPTR64:
- a = ppc64.ASLD
-
- case gc.ORSH<<16 | gc.TUINT8,
- gc.ORSH<<16 | gc.TUINT16,
- gc.ORSH<<16 | gc.TUINT32,
- gc.ORSH<<16 | gc.TPTR32,
- gc.ORSH<<16 | gc.TUINT64,
- gc.ORSH<<16 | gc.TPTR64:
- a = ppc64.ASRD
-
- case gc.ORSH<<16 | gc.TINT8,
- gc.ORSH<<16 | gc.TINT16,
- gc.ORSH<<16 | gc.TINT32,
- gc.ORSH<<16 | gc.TINT64:
- a = ppc64.ASRAD
+ case OLSH_ | gc.TINT8,
+ OLSH_ | gc.TUINT8,
+ OLSH_ | gc.TINT16,
+ OLSH_ | gc.TUINT16,
+ OLSH_ | gc.TINT32,
+ OLSH_ | gc.TUINT32,
+ OLSH_ | gc.TPTR32,
+ OLSH_ | gc.TINT64,
+ OLSH_ | gc.TUINT64,
+ OLSH_ | gc.TPTR64:
+ a = mips.ASLLV
+
+ case ORSH_ | gc.TUINT8,
+ ORSH_ | gc.TUINT16,
+ ORSH_ | gc.TUINT32,
+ ORSH_ | gc.TPTR32,
+ ORSH_ | gc.TUINT64,
+ ORSH_ | gc.TPTR64:
+ a = mips.ASRLV
+
+ case ORSH_ | gc.TINT8,
+ ORSH_ | gc.TINT16,
+ ORSH_ | gc.TINT32,
+ ORSH_ | gc.TINT64:
+ a = mips.ASRAV
// TODO(minux): handle rotates
//case CASE(ORROTC, TINT8):
// a = 0//??? RLDC??
// break;
- case gc.OHMUL<<16 | gc.TINT64:
- a = ppc64.AMULHD
-
- case gc.OHMUL<<16 | gc.TUINT64,
- gc.OHMUL<<16 | gc.TPTR64:
- a = ppc64.AMULHDU
-
- case gc.OMUL<<16 | gc.TINT8,
- gc.OMUL<<16 | gc.TINT16,
- gc.OMUL<<16 | gc.TINT32,
- gc.OMUL<<16 | gc.TINT64:
- a = ppc64.AMULLD
-
- case gc.OMUL<<16 | gc.TUINT8,
- gc.OMUL<<16 | gc.TUINT16,
- gc.OMUL<<16 | gc.TUINT32,
- gc.OMUL<<16 | gc.TPTR32,
- // don't use word multiply, the high 32-bit are undefined.
- gc.OMUL<<16 | gc.TUINT64,
- gc.OMUL<<16 | gc.TPTR64:
- // for 64-bit multiplies, signedness doesn't matter.
- a = ppc64.AMULLD
-
- case gc.OMUL<<16 | gc.TFLOAT32:
- a = ppc64.AFMULS
-
- case gc.OMUL<<16 | gc.TFLOAT64:
- a = ppc64.AFMUL
-
- case gc.ODIV<<16 | gc.TINT8,
- gc.ODIV<<16 | gc.TINT16,
- gc.ODIV<<16 | gc.TINT32,
- gc.ODIV<<16 | gc.TINT64:
- a = ppc64.ADIVD
-
- case gc.ODIV<<16 | gc.TUINT8,
- gc.ODIV<<16 | gc.TUINT16,
- gc.ODIV<<16 | gc.TUINT32,
- gc.ODIV<<16 | gc.TPTR32,
- gc.ODIV<<16 | gc.TUINT64,
- gc.ODIV<<16 | gc.TPTR64:
- a = ppc64.ADIVDU
-
- case gc.ODIV<<16 | gc.TFLOAT32:
- a = ppc64.AFDIVS
-
- case gc.ODIV<<16 | gc.TFLOAT64:
- a = ppc64.AFDIV
+ case OHMUL_ | gc.TINT64:
+ a = mips.AMULV
+
+ case OHMUL_ | gc.TUINT64,
+ OHMUL_ | gc.TPTR64:
+ a = mips.AMULVU
+
+ case OMUL_ | gc.TINT8,
+ OMUL_ | gc.TINT16,
+ OMUL_ | gc.TINT32,
+ OMUL_ | gc.TINT64:
+ a = mips.AMULV
+
+ case OMUL_ | gc.TUINT8,
+ OMUL_ | gc.TUINT16,
+ OMUL_ | gc.TUINT32,
+ OMUL_ | gc.TPTR32,
+ OMUL_ | gc.TUINT64,
+ OMUL_ | gc.TPTR64:
+ a = mips.AMULVU
+
+ case OMUL_ | gc.TFLOAT32:
+ a = mips.AMULF
+
+ case OMUL_ | gc.TFLOAT64:
+ a = mips.AMULD
+
+ case ODIV_ | gc.TINT8,
+ ODIV_ | gc.TINT16,
+ ODIV_ | gc.TINT32,
+ ODIV_ | gc.TINT64:
+ a = mips.ADIVV
+
+ case ODIV_ | gc.TUINT8,
+ ODIV_ | gc.TUINT16,
+ ODIV_ | gc.TUINT32,
+ ODIV_ | gc.TPTR32,
+ ODIV_ | gc.TUINT64,
+ ODIV_ | gc.TPTR64:
+ a = mips.ADIVVU
+
+ case ODIV_ | gc.TFLOAT32:
+ a = mips.ADIVF
+
+ case ODIV_ | gc.TFLOAT64:
+ a = mips.ADIVD
}
return a
+++ /dev/null
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ppc64
-
-// Many Power ISA arithmetic and logical instructions come in four
-// standard variants. These bits let us map between variants.
-const (
- V_CC = 1 << 0 // xCC (affect CR field 0 flags)
- V_V = 1 << 1 // xV (affect SO and OV flags)
-)
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package ppc64
+package mips64
import (
"cmd/compile/internal/gc"
"cmd/internal/obj"
- "cmd/internal/obj/ppc64"
+ "cmd/internal/obj/mips"
"fmt"
)
// can eliminate moves that don't care without
// breaking moves that do care. This might let us
// simplify or remove the next peep loop, too.
- if p.As == ppc64.AMOVD || p.As == ppc64.AFMOVD {
+ if p.As == mips.AMOVV || p.As == mips.AMOVF || p.As == mips.AMOVD {
if regtyp(&p.To) {
// Try to eliminate reg->reg moves
if regtyp(&p.From) {
- if p.From.Type == p.To.Type {
+ if isfreg(&p.From) == isfreg(&p.To) {
if copyprop(r) {
excise(r)
t++
// Convert uses to $0 to uses of R0 and
// propagate R0
if regzer(&p.From) != 0 {
- if p.To.Type == obj.TYPE_REG {
+ if p.To.Type == obj.TYPE_REG && !isfreg(&p.To) {
p.From.Type = obj.TYPE_REG
- p.From.Reg = ppc64.REGZERO
+ p.From.Reg = mips.REGZERO
if copyprop(r) {
excise(r)
t++
default:
continue
- case ppc64.AMOVH,
- ppc64.AMOVHZ,
- ppc64.AMOVB,
- ppc64.AMOVBZ,
- ppc64.AMOVW,
- ppc64.AMOVWZ:
+ case mips.AMOVH,
+ mips.AMOVHU,
+ mips.AMOVB,
+ mips.AMOVBU,
+ mips.AMOVW,
+ mips.AMOVWU:
if p.To.Type != obj.TYPE_REG {
continue
}
excise(r1)
}
- if gc.Debug['D'] > 1 {
- goto ret /* allow following code improvement to be suppressed */
- }
-
- /*
- * look for OP x,y,R; CMP R, $0 -> OPCC x,y,R
- * when OP can set condition codes correctly
- */
- for r := (*gc.Flow)(g.Start); r != nil; r = r.Link {
- p = r.Prog
- switch p.As {
- case ppc64.ACMP,
- ppc64.ACMPW: /* always safe? */
- if regzer(&p.To) == 0 {
- continue
- }
- r1 = r.S1
- if r1 == nil {
- continue
- }
- switch r1.Prog.As {
- default:
- continue
-
- /* the conditions can be complex and these are currently little used */
- case ppc64.ABCL,
- ppc64.ABC:
- continue
-
- case ppc64.ABEQ,
- ppc64.ABGE,
- ppc64.ABGT,
- ppc64.ABLE,
- ppc64.ABLT,
- ppc64.ABNE,
- ppc64.ABVC,
- ppc64.ABVS:
- break
- }
-
- r1 = r
- for {
- r1 = gc.Uniqp(r1)
- if r1 == nil || r1.Prog.As != obj.ANOP {
- break
- }
- }
-
- if r1 == nil {
- continue
- }
- p1 = r1.Prog
- if p1.To.Type != obj.TYPE_REG || p1.To.Reg != p.From.Reg {
- continue
- }
- switch p1.As {
- /* irregular instructions */
- case ppc64.ASUB,
- ppc64.AADD,
- ppc64.AXOR,
- ppc64.AOR:
- if p1.From.Type == obj.TYPE_CONST || p1.From.Type == obj.TYPE_ADDR {
- continue
- }
- }
-
- switch p1.As {
- default:
- continue
-
- case ppc64.AMOVW,
- ppc64.AMOVD:
- if p1.From.Type != obj.TYPE_REG {
- continue
- }
- continue
-
- case ppc64.AANDCC,
- ppc64.AANDNCC,
- ppc64.AORCC,
- ppc64.AORNCC,
- ppc64.AXORCC,
- ppc64.ASUBCC,
- ppc64.ASUBECC,
- ppc64.ASUBMECC,
- ppc64.ASUBZECC,
- ppc64.AADDCC,
- ppc64.AADDCCC,
- ppc64.AADDECC,
- ppc64.AADDMECC,
- ppc64.AADDZECC,
- ppc64.ARLWMICC,
- ppc64.ARLWNMCC,
- /* don't deal with floating point instructions for now */
- /*
- case AFABS:
- case AFADD:
- case AFADDS:
- case AFCTIW:
- case AFCTIWZ:
- case AFDIV:
- case AFDIVS:
- case AFMADD:
- case AFMADDS:
- case AFMOVD:
- case AFMSUB:
- case AFMSUBS:
- case AFMUL:
- case AFMULS:
- case AFNABS:
- case AFNEG:
- case AFNMADD:
- case AFNMADDS:
- case AFNMSUB:
- case AFNMSUBS:
- case AFRSP:
- case AFSUB:
- case AFSUBS:
- case ACNTLZW:
- case AMTFSB0:
- case AMTFSB1:
- */
- ppc64.AADD,
- ppc64.AADDV,
- ppc64.AADDC,
- ppc64.AADDCV,
- ppc64.AADDME,
- ppc64.AADDMEV,
- ppc64.AADDE,
- ppc64.AADDEV,
- ppc64.AADDZE,
- ppc64.AADDZEV,
- ppc64.AAND,
- ppc64.AANDN,
- ppc64.ADIVW,
- ppc64.ADIVWV,
- ppc64.ADIVWU,
- ppc64.ADIVWUV,
- ppc64.ADIVD,
- ppc64.ADIVDV,
- ppc64.ADIVDU,
- ppc64.ADIVDUV,
- ppc64.AEQV,
- ppc64.AEXTSB,
- ppc64.AEXTSH,
- ppc64.AEXTSW,
- ppc64.AMULHW,
- ppc64.AMULHWU,
- ppc64.AMULLW,
- ppc64.AMULLWV,
- ppc64.AMULHD,
- ppc64.AMULHDU,
- ppc64.AMULLD,
- ppc64.AMULLDV,
- ppc64.ANAND,
- ppc64.ANEG,
- ppc64.ANEGV,
- ppc64.ANOR,
- ppc64.AOR,
- ppc64.AORN,
- ppc64.AREM,
- ppc64.AREMV,
- ppc64.AREMU,
- ppc64.AREMUV,
- ppc64.AREMD,
- ppc64.AREMDV,
- ppc64.AREMDU,
- ppc64.AREMDUV,
- ppc64.ARLWMI,
- ppc64.ARLWNM,
- ppc64.ASLW,
- ppc64.ASRAW,
- ppc64.ASRW,
- ppc64.ASLD,
- ppc64.ASRAD,
- ppc64.ASRD,
- ppc64.ASUB,
- ppc64.ASUBV,
- ppc64.ASUBC,
- ppc64.ASUBCV,
- ppc64.ASUBME,
- ppc64.ASUBMEV,
- ppc64.ASUBE,
- ppc64.ASUBEV,
- ppc64.ASUBZE,
- ppc64.ASUBZEV,
- ppc64.AXOR:
- t = variant2as(int(p1.As), as2variant(int(p1.As))|V_CC)
- }
-
- if gc.Debug['D'] != 0 {
- fmt.Printf("cmp %v; %v -> ", p1, p)
- }
- p1.As = int16(t)
- if gc.Debug['D'] != 0 {
- fmt.Printf("%v\n", p1)
- }
- excise(r)
- continue
- }
- }
-
-ret:
gc.Flowend(g)
}
}
}
if a.Type == obj.TYPE_REG {
- if a.Reg == ppc64.REGZERO {
+ if a.Reg == mips.REGZERO {
return 1
}
}
func regtyp(a *obj.Addr) bool {
// TODO(rsc): Floating point register exclusions?
- return a.Type == obj.TYPE_REG && ppc64.REG_R0 <= a.Reg && a.Reg <= ppc64.REG_F31 && a.Reg != ppc64.REGZERO
+ return a.Type == obj.TYPE_REG && mips.REG_R0 <= a.Reg && a.Reg <= mips.REG_F31 && a.Reg != mips.REGZERO
+}
+
+func isfreg(a *obj.Addr) bool {
+ return mips.REG_F0 <= a.Reg && a.Reg <= mips.REG_F31
}
/*
// 0 otherwise (not touched)
func copyu(p *obj.Prog, v *obj.Addr, s *obj.Addr) int {
if p.From3Type() != obj.TYPE_NONE {
- // 9g never generates a from3
+ // never generates a from3
fmt.Printf("copyu: from3 (%v) not implemented\n", gc.Ctxt.Dconv(p.From3))
}
return 2
case obj.ANOP, /* read p->from, write p->to */
- ppc64.AMOVH,
- ppc64.AMOVHZ,
- ppc64.AMOVB,
- ppc64.AMOVBZ,
- ppc64.AMOVW,
- ppc64.AMOVWZ,
- ppc64.AMOVD,
- ppc64.ANEG,
- ppc64.ANEGCC,
- ppc64.AADDME,
- ppc64.AADDMECC,
- ppc64.AADDZE,
- ppc64.AADDZECC,
- ppc64.ASUBME,
- ppc64.ASUBMECC,
- ppc64.ASUBZE,
- ppc64.ASUBZECC,
- ppc64.AFCTIW,
- ppc64.AFCTIWZ,
- ppc64.AFCTID,
- ppc64.AFCTIDZ,
- ppc64.AFCFID,
- ppc64.AFCFIDCC,
- ppc64.AFMOVS,
- ppc64.AFMOVD,
- ppc64.AFRSP,
- ppc64.AFNEG,
- ppc64.AFNEGCC:
+ mips.AMOVV,
+ mips.AMOVF,
+ mips.AMOVD,
+ mips.AMOVH,
+ mips.AMOVHU,
+ mips.AMOVB,
+ mips.AMOVBU,
+ mips.AMOVW,
+ mips.AMOVWU,
+ mips.AMOVFD,
+ mips.AMOVDF,
+ mips.AMOVDW,
+ mips.AMOVWD,
+ mips.AMOVFW,
+ mips.AMOVWF,
+ mips.AMOVDV,
+ mips.AMOVVD,
+ mips.AMOVFV,
+ mips.AMOVVF,
+ mips.ATRUNCFV,
+ mips.ATRUNCDV,
+ mips.ATRUNCFW,
+ mips.ATRUNCDW:
if s != nil {
if copysub(&p.From, v, s, 1) != 0 {
return 1
return 0
- case ppc64.AMOVBU, /* rar p->from, write p->to or read p->from, rar p->to */
- ppc64.AMOVBZU,
- ppc64.AMOVHU,
- ppc64.AMOVHZU,
- ppc64.AMOVWZU,
- ppc64.AMOVDU:
- if p.From.Type == obj.TYPE_MEM {
- if copyas(&p.From, v) {
- // No s!=nil check; need to fail
- // anyway in that case
- return 2
- }
-
- if s != nil {
- if copysub(&p.To, v, s, 1) != 0 {
- return 1
- }
- return 0
- }
-
- if copyas(&p.To, v) {
- return 3
- }
- } else if p.To.Type == obj.TYPE_MEM {
- if copyas(&p.To, v) {
- return 2
- }
- if s != nil {
- if copysub(&p.From, v, s, 1) != 0 {
- return 1
- }
- return 0
- }
-
- if copyau(&p.From, v) {
- return 1
- }
- } else {
- fmt.Printf("copyu: bad %v\n", p)
- }
-
- return 0
-
- case ppc64.ARLWMI, /* read p->from, read p->reg, rar p->to */
- ppc64.ARLWMICC:
- if copyas(&p.To, v) {
- return 2
- }
- fallthrough
-
- /* fall through */
- case ppc64.AADD,
- /* read p->from, read p->reg, write p->to */
- ppc64.AADDC,
- ppc64.AADDE,
- ppc64.ASUB,
- ppc64.ASLW,
- ppc64.ASRW,
- ppc64.ASRAW,
- ppc64.ASLD,
- ppc64.ASRD,
- ppc64.ASRAD,
- ppc64.AOR,
- ppc64.AORCC,
- ppc64.AORN,
- ppc64.AORNCC,
- ppc64.AAND,
- ppc64.AANDCC,
- ppc64.AANDN,
- ppc64.AANDNCC,
- ppc64.ANAND,
- ppc64.ANANDCC,
- ppc64.ANOR,
- ppc64.ANORCC,
- ppc64.AXOR,
- ppc64.AMULHW,
- ppc64.AMULHWU,
- ppc64.AMULLW,
- ppc64.AMULLD,
- ppc64.ADIVW,
- ppc64.ADIVD,
- ppc64.ADIVWU,
- ppc64.ADIVDU,
- ppc64.AREM,
- ppc64.AREMU,
- ppc64.AREMD,
- ppc64.AREMDU,
- ppc64.ARLWNM,
- ppc64.ARLWNMCC,
- ppc64.AFADDS,
- ppc64.AFADD,
- ppc64.AFSUBS,
- ppc64.AFSUB,
- ppc64.AFMULS,
- ppc64.AFMUL,
- ppc64.AFDIVS,
- ppc64.AFDIV:
+ case mips.ASGT, /* read p->from, read p->reg, write p->to */
+ mips.ASGTU,
+
+ mips.AADD,
+ mips.AADDU,
+ mips.ASUB,
+ mips.ASUBU,
+ mips.ASLL,
+ mips.ASRL,
+ mips.ASRA,
+ mips.AOR,
+ mips.ANOR,
+ mips.AAND,
+ mips.AXOR,
+
+ mips.AADDV,
+ mips.AADDVU,
+ mips.ASUBV,
+ mips.ASUBVU,
+ mips.ASLLV,
+ mips.ASRLV,
+ mips.ASRAV,
+
+ mips.AADDF,
+ mips.AADDD,
+ mips.ASUBF,
+ mips.ASUBD,
+ mips.AMULF,
+ mips.AMULD,
+ mips.ADIVF,
+ mips.ADIVD:
if s != nil {
if copysub(&p.From, v, s, 1) != 0 {
return 1
}
return 0
- case ppc64.ABEQ,
- ppc64.ABGT,
- ppc64.ABGE,
- ppc64.ABLT,
- ppc64.ABLE,
- ppc64.ABNE,
- ppc64.ABVC,
- ppc64.ABVS:
- return 0
-
case obj.ACHECKNIL, /* read p->from */
- ppc64.ACMP, /* read p->from, read p->to */
- ppc64.ACMPU,
- ppc64.ACMPW,
- ppc64.ACMPWU,
- ppc64.AFCMPO,
- ppc64.AFCMPU:
+ mips.ABEQ, /* read p->from, read p->reg */
+ mips.ABNE,
+ mips.ABGTZ,
+ mips.ABGEZ,
+ mips.ABLTZ,
+ mips.ABLEZ,
+
+ mips.ACMPEQD,
+ mips.ACMPEQF,
+ mips.ACMPGED,
+ mips.ACMPGEF,
+ mips.ACMPGTD,
+ mips.ACMPGTF,
+ mips.ABFPF,
+ mips.ABFPT,
+
+ mips.AMUL,
+ mips.AMULU,
+ mips.ADIV,
+ mips.ADIVU,
+ mips.AMULV,
+ mips.AMULVU,
+ mips.ADIVV,
+ mips.ADIVVU:
if s != nil {
if copysub(&p.From, v, s, 1) != 0 {
return 1
}
- return copysub(&p.To, v, s, 1)
+ return copysub1(p, v, s, 1)
}
if copyau(&p.From, v) {
return 1
}
- if copyau(&p.To, v) {
+ if copyau1(p, v) {
return 1
}
return 0
- // 9g never generates a branch to a GPR (this isn't
- // even a normal instruction; liblink turns it in to a
- // mov and a branch).
- case ppc64.ABR: /* read p->to */
+ case mips.AJMP: /* read p->to */
if s != nil {
if copysub(&p.To, v, s, 1) != 0 {
return 1
}
return 0
- case obj.ARET: /* funny */
+ case mips.ARET: /* funny */
if s != nil {
return 0
}
// everything is set (and not used).
return 3
- case ppc64.ABL: /* funny */
+ case mips.AJAL: /* funny */
if v.Type == obj.TYPE_REG {
// TODO(rsc): REG_R0 and REG_F0 used to be
// (when register numbers started at 0) exregoffset and exfregoffset,
// which are unset entirely.
// It's strange that this handles R0 and F0 differently from the other
// registers. Possible failure to optimize?
- if ppc64.REG_R0 < v.Reg && v.Reg <= ppc64.REGEXT {
+ if mips.REG_R0 < v.Reg && v.Reg <= mips.REG_R31 {
return 2
}
- if v.Reg == ppc64.REGARG {
+ if v.Reg == mips.REGARG {
return 2
}
- if ppc64.REG_F0 < v.Reg && v.Reg <= ppc64.FREGEXT {
+ if mips.REG_F0 < v.Reg && v.Reg <= mips.REG_F31 {
return 2
}
}
}
return 3
- // R0 is zero, used by DUFFZERO, cannot be substituted.
- // R3 is ptr to memory, used and set, cannot be substituted.
+ // R0 is zero, used by DUFFZERO, cannot be substituted.
+ // R1 is ptr to memory, used and set, cannot be substituted.
case obj.ADUFFZERO:
if v.Type == obj.TYPE_REG {
if v.Reg == 0 {
return 1
}
- if v.Reg == 3 {
+ if v.Reg == 1 {
return 2
}
}
return 0
- // R3, R4 are ptr to src, dst, used and set, cannot be substituted.
- // R5 is scratch, set by DUFFCOPY, cannot be substituted.
+ // R1, R2 are ptr to src, dst, used and set, cannot be substituted.
+ // R3 is scratch, set by DUFFCOPY, cannot be substituted.
case obj.ADUFFCOPY:
if v.Type == obj.TYPE_REG {
- if v.Reg == 3 || v.Reg == 4 {
+ if v.Reg == 1 || v.Reg == 2 {
return 2
}
- if v.Reg == 5 {
+ if v.Reg == 3 {
return 3
}
}
case obj.ATEXT: /* funny */
if v.Type == obj.TYPE_REG {
- if v.Reg == ppc64.REGARG {
+ if v.Reg == mips.REGARG {
return 3
}
}
}
// copysub replaces v with s in a if f!=0 or indicates it if could if f==0.
-// Returns 1 on failure to substitute (it always succeeds on ppc64).
+// Returns 1 on failure to substitute (it always succeeds on mips).
func copysub(a *obj.Addr, v *obj.Addr, s *obj.Addr, f int) int {
if f != 0 {
if copyau(a, v) {
}
// copysub1 replaces v with s in p1->reg if f!=0 or indicates if it could if f==0.
-// Returns 1 on failure to substitute (it always succeeds on ppc64).
+// Returns 1 on failure to substitute (it always succeeds on mips).
func copysub1(p1 *obj.Prog, v *obj.Addr, s *obj.Addr, f int) int {
if f != 0 {
if copyau1(p1, v) {
}
func stackaddr(a *obj.Addr) bool {
- return a.Type == obj.TYPE_REG && a.Reg == ppc64.REGSP
+ return a.Type == obj.TYPE_REG && a.Reg == mips.REGSP
}
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package ppc64
+package mips64
import (
"cmd/compile/internal/gc"
"cmd/internal/obj"
- "cmd/internal/obj/ppc64"
+ "cmd/internal/obj/mips"
)
const (
// size variants of an operation even if we just use a subset.
//
// The table is formatted for 8-space tabs.
-var progtable = [ppc64.ALAST]obj.ProgInfo{
+var progtable = [mips.ALAST]obj.ProgInfo{
obj.ATYPE: {Flags: gc.Pseudo | gc.Skip},
obj.ATEXT: {Flags: gc.Pseudo},
obj.AFUNCDATA: {Flags: gc.Pseudo},
obj.AVARKILL: {Flags: gc.Pseudo | gc.RightWrite},
// NOP is an internal no-op that also stands
- // for USED and SET annotations, not the Power opcode.
+ // for USED and SET annotations, not the MIPS opcode.
obj.ANOP: {Flags: gc.LeftRead | gc.RightWrite},
// Integer
- ppc64.AADD: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
- ppc64.ASUB: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
- ppc64.ANEG: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
- ppc64.AAND: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
- ppc64.AOR: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
- ppc64.AXOR: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
- ppc64.AMULLD: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
- ppc64.AMULLW: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
- ppc64.AMULHD: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
- ppc64.AMULHDU: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
- ppc64.ADIVD: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
- ppc64.ADIVDU: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
- ppc64.ASLD: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
- ppc64.ASRD: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
- ppc64.ASRAD: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
- ppc64.ACMP: {Flags: gc.SizeQ | gc.LeftRead | gc.RightRead},
- ppc64.ACMPU: {Flags: gc.SizeQ | gc.LeftRead | gc.RightRead},
- ppc64.ATD: {Flags: gc.SizeQ | gc.RightRead},
+ mips.AADD: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+ mips.AADDU: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+ mips.AADDV: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+ mips.AADDVU: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+ mips.ASUB: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+ mips.ASUBU: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+ mips.ASUBV: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+ mips.ASUBVU: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+ mips.AAND: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+ mips.AOR: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+ mips.AXOR: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+ mips.ANOR: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+ mips.AMUL: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead},
+ mips.AMULU: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead},
+ mips.AMULV: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead},
+ mips.AMULVU: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead},
+ mips.ADIV: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead},
+ mips.ADIVU: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead},
+ mips.ADIVV: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead},
+ mips.ADIVVU: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead},
+ mips.AREM: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead},
+ mips.AREMU: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead},
+ mips.AREMV: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead},
+ mips.AREMVU: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead},
+ mips.ASLL: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+ mips.ASLLV: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+ mips.ASRA: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+ mips.ASRAV: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+ mips.ASRL: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+ mips.ASRLV: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+ mips.ASGT: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+ mips.ASGTU: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
// Floating point.
- ppc64.AFADD: {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
- ppc64.AFADDS: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
- ppc64.AFSUB: {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
- ppc64.AFSUBS: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
- ppc64.AFMUL: {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
- ppc64.AFMULS: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
- ppc64.AFDIV: {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
- ppc64.AFDIVS: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
- ppc64.AFCTIDZ: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
- ppc64.AFCFID: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
- ppc64.AFCMPU: {Flags: gc.SizeD | gc.LeftRead | gc.RightRead},
- ppc64.AFRSP: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
+ mips.AADDF: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
+ mips.AADDD: {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
+ mips.ASUBF: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
+ mips.ASUBD: {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
+ mips.AMULF: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
+ mips.AMULD: {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
+ mips.ADIVF: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
+ mips.ADIVD: {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
+ mips.AABSF: {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite},
+ mips.AABSD: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite},
+ mips.ANEGF: {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite},
+ mips.ANEGD: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite},
+ mips.ACMPEQF: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead},
+ mips.ACMPEQD: {Flags: gc.SizeD | gc.LeftRead | gc.RegRead},
+ mips.ACMPGTF: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead},
+ mips.ACMPGTD: {Flags: gc.SizeD | gc.LeftRead | gc.RegRead},
+ mips.ACMPGEF: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead},
+ mips.ACMPGED: {Flags: gc.SizeD | gc.LeftRead | gc.RegRead},
+ mips.AMOVFD: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
+ mips.AMOVDF: {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv},
+ mips.AMOVFW: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
+ mips.AMOVWF: {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv},
+ mips.AMOVDW: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
+ mips.AMOVWD: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
+ mips.AMOVFV: {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
+ mips.AMOVVF: {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv},
+ mips.AMOVDV: {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
+ mips.AMOVVD: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
+ mips.ATRUNCFW: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
+ mips.ATRUNCDW: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
+ mips.ATRUNCFV: {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
+ mips.ATRUNCDV: {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
// Moves
- ppc64.AMOVB: {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
- ppc64.AMOVBU: {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv | gc.PostInc},
- ppc64.AMOVBZ: {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
- ppc64.AMOVH: {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
- ppc64.AMOVHU: {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv | gc.PostInc},
- ppc64.AMOVHZ: {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
- ppc64.AMOVW: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
-
- // there is no AMOVWU.
- ppc64.AMOVWZU: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv | gc.PostInc},
- ppc64.AMOVWZ: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
- ppc64.AMOVD: {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Move},
- ppc64.AMOVDU: {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Move | gc.PostInc},
- ppc64.AFMOVS: {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
- ppc64.AFMOVD: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Move},
+ mips.AMOVB: {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+ mips.AMOVBU: {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+ mips.AMOVH: {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+ mips.AMOVHU: {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+ mips.AMOVW: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+ mips.AMOVWU: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+ mips.AMOVV: {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Move},
+ mips.AMOVF: {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+ mips.AMOVD: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Move},
// Jumps
- ppc64.ABR: {Flags: gc.Jump | gc.Break},
- ppc64.ABL: {Flags: gc.Call},
- ppc64.ABEQ: {Flags: gc.Cjmp},
- ppc64.ABNE: {Flags: gc.Cjmp},
- ppc64.ABGE: {Flags: gc.Cjmp},
- ppc64.ABLT: {Flags: gc.Cjmp},
- ppc64.ABGT: {Flags: gc.Cjmp},
- ppc64.ABLE: {Flags: gc.Cjmp},
- obj.ARET: {Flags: gc.Break},
+ mips.AJMP: {Flags: gc.Jump | gc.Break},
+ mips.AJAL: {Flags: gc.Call},
+ mips.ABEQ: {Flags: gc.Cjmp},
+ mips.ABNE: {Flags: gc.Cjmp},
+ mips.ABGEZ: {Flags: gc.Cjmp},
+ mips.ABLTZ: {Flags: gc.Cjmp},
+ mips.ABGTZ: {Flags: gc.Cjmp},
+ mips.ABLEZ: {Flags: gc.Cjmp},
+ mips.ABFPF: {Flags: gc.Cjmp},
+ mips.ABFPT: {Flags: gc.Cjmp},
+ mips.ARET: {Flags: gc.Break},
obj.ADUFFZERO: {Flags: gc.Call},
obj.ADUFFCOPY: {Flags: gc.Call},
}
-var initproginfo_initialized int
-
-func initproginfo() {
- var addvariant = []int{V_CC, V_V, V_CC | V_V}
-
- if initproginfo_initialized != 0 {
- return
- }
- initproginfo_initialized = 1
-
- // Perform one-time expansion of instructions in progtable to
- // their CC, V, and VCC variants
- var as2 int
- var i int
- var variant int
- for as := int(0); as < len(progtable); as++ {
- if progtable[as].Flags == 0 {
- continue
- }
- variant = as2variant(as)
- for i = 0; i < len(addvariant); i++ {
- as2 = variant2as(as, variant|addvariant[i])
- if as2 != 0 && progtable[as2].Flags == 0 {
- progtable[as2] = progtable[as]
- }
- }
- }
-}
-
func proginfo(p *obj.Prog) {
- initproginfo()
-
info := &p.Info
*info = progtable[p.As]
if info.Flags == 0 {
if (p.From.Type == obj.TYPE_MEM || p.From.Type == obj.TYPE_ADDR) && p.From.Reg != 0 {
info.Regindex |= RtoB(int(p.From.Reg))
- if info.Flags&gc.PostInc != 0 {
- info.Regset |= RtoB(int(p.From.Reg))
- }
}
if (p.To.Type == obj.TYPE_MEM || p.To.Type == obj.TYPE_ADDR) && p.To.Reg != 0 {
info.Regindex |= RtoB(int(p.To.Reg))
- if info.Flags&gc.PostInc != 0 {
- info.Regset |= RtoB(int(p.To.Reg))
- }
}
if p.From.Type == obj.TYPE_ADDR && p.From.Sym != nil && (info.Flags&gc.LeftRead != 0) {
}
if p.As == obj.ADUFFZERO {
- info.Reguse |= 1<<0 | RtoB(ppc64.REG_R3)
- info.Regset |= RtoB(ppc64.REG_R3)
+ info.Reguse |= 1<<0 | RtoB(mips.REGRT1)
+ info.Regset |= RtoB(mips.REGRT1)
}
if p.As == obj.ADUFFCOPY {
// TODO(austin) Revisit when duffcopy is implemented
- info.Reguse |= RtoB(ppc64.REG_R3) | RtoB(ppc64.REG_R4) | RtoB(ppc64.REG_R5)
-
- info.Regset |= RtoB(ppc64.REG_R3) | RtoB(ppc64.REG_R4)
- }
-}
+ info.Reguse |= RtoB(mips.REGRT1) | RtoB(mips.REGRT2) | RtoB(mips.REG_R3)
-// Instruction variants table. Initially this contains entries only
-// for the "base" form of each instruction. On the first call to
-// as2variant or variant2as, we'll add the variants to the table.
-var varianttable = [ppc64.ALAST][4]int{
- ppc64.AADD: [4]int{ppc64.AADD, ppc64.AADDCC, ppc64.AADDV, ppc64.AADDVCC},
- ppc64.AADDC: [4]int{ppc64.AADDC, ppc64.AADDCCC, ppc64.AADDCV, ppc64.AADDCVCC},
- ppc64.AADDE: [4]int{ppc64.AADDE, ppc64.AADDECC, ppc64.AADDEV, ppc64.AADDEVCC},
- ppc64.AADDME: [4]int{ppc64.AADDME, ppc64.AADDMECC, ppc64.AADDMEV, ppc64.AADDMEVCC},
- ppc64.AADDZE: [4]int{ppc64.AADDZE, ppc64.AADDZECC, ppc64.AADDZEV, ppc64.AADDZEVCC},
- ppc64.AAND: [4]int{ppc64.AAND, ppc64.AANDCC, 0, 0},
- ppc64.AANDN: [4]int{ppc64.AANDN, ppc64.AANDNCC, 0, 0},
- ppc64.ACNTLZD: [4]int{ppc64.ACNTLZD, ppc64.ACNTLZDCC, 0, 0},
- ppc64.ACNTLZW: [4]int{ppc64.ACNTLZW, ppc64.ACNTLZWCC, 0, 0},
- ppc64.ADIVD: [4]int{ppc64.ADIVD, ppc64.ADIVDCC, ppc64.ADIVDV, ppc64.ADIVDVCC},
- ppc64.ADIVDU: [4]int{ppc64.ADIVDU, ppc64.ADIVDUCC, ppc64.ADIVDUV, ppc64.ADIVDUVCC},
- ppc64.ADIVW: [4]int{ppc64.ADIVW, ppc64.ADIVWCC, ppc64.ADIVWV, ppc64.ADIVWVCC},
- ppc64.ADIVWU: [4]int{ppc64.ADIVWU, ppc64.ADIVWUCC, ppc64.ADIVWUV, ppc64.ADIVWUVCC},
- ppc64.AEQV: [4]int{ppc64.AEQV, ppc64.AEQVCC, 0, 0},
- ppc64.AEXTSB: [4]int{ppc64.AEXTSB, ppc64.AEXTSBCC, 0, 0},
- ppc64.AEXTSH: [4]int{ppc64.AEXTSH, ppc64.AEXTSHCC, 0, 0},
- ppc64.AEXTSW: [4]int{ppc64.AEXTSW, ppc64.AEXTSWCC, 0, 0},
- ppc64.AFABS: [4]int{ppc64.AFABS, ppc64.AFABSCC, 0, 0},
- ppc64.AFADD: [4]int{ppc64.AFADD, ppc64.AFADDCC, 0, 0},
- ppc64.AFADDS: [4]int{ppc64.AFADDS, ppc64.AFADDSCC, 0, 0},
- ppc64.AFCFID: [4]int{ppc64.AFCFID, ppc64.AFCFIDCC, 0, 0},
- ppc64.AFCTID: [4]int{ppc64.AFCTID, ppc64.AFCTIDCC, 0, 0},
- ppc64.AFCTIDZ: [4]int{ppc64.AFCTIDZ, ppc64.AFCTIDZCC, 0, 0},
- ppc64.AFCTIW: [4]int{ppc64.AFCTIW, ppc64.AFCTIWCC, 0, 0},
- ppc64.AFCTIWZ: [4]int{ppc64.AFCTIWZ, ppc64.AFCTIWZCC, 0, 0},
- ppc64.AFDIV: [4]int{ppc64.AFDIV, ppc64.AFDIVCC, 0, 0},
- ppc64.AFDIVS: [4]int{ppc64.AFDIVS, ppc64.AFDIVSCC, 0, 0},
- ppc64.AFMADD: [4]int{ppc64.AFMADD, ppc64.AFMADDCC, 0, 0},
- ppc64.AFMADDS: [4]int{ppc64.AFMADDS, ppc64.AFMADDSCC, 0, 0},
- ppc64.AFMOVD: [4]int{ppc64.AFMOVD, ppc64.AFMOVDCC, 0, 0},
- ppc64.AFMSUB: [4]int{ppc64.AFMSUB, ppc64.AFMSUBCC, 0, 0},
- ppc64.AFMSUBS: [4]int{ppc64.AFMSUBS, ppc64.AFMSUBSCC, 0, 0},
- ppc64.AFMUL: [4]int{ppc64.AFMUL, ppc64.AFMULCC, 0, 0},
- ppc64.AFMULS: [4]int{ppc64.AFMULS, ppc64.AFMULSCC, 0, 0},
- ppc64.AFNABS: [4]int{ppc64.AFNABS, ppc64.AFNABSCC, 0, 0},
- ppc64.AFNEG: [4]int{ppc64.AFNEG, ppc64.AFNEGCC, 0, 0},
- ppc64.AFNMADD: [4]int{ppc64.AFNMADD, ppc64.AFNMADDCC, 0, 0},
- ppc64.AFNMADDS: [4]int{ppc64.AFNMADDS, ppc64.AFNMADDSCC, 0, 0},
- ppc64.AFNMSUB: [4]int{ppc64.AFNMSUB, ppc64.AFNMSUBCC, 0, 0},
- ppc64.AFNMSUBS: [4]int{ppc64.AFNMSUBS, ppc64.AFNMSUBSCC, 0, 0},
- ppc64.AFRES: [4]int{ppc64.AFRES, ppc64.AFRESCC, 0, 0},
- ppc64.AFRSP: [4]int{ppc64.AFRSP, ppc64.AFRSPCC, 0, 0},
- ppc64.AFRSQRTE: [4]int{ppc64.AFRSQRTE, ppc64.AFRSQRTECC, 0, 0},
- ppc64.AFSEL: [4]int{ppc64.AFSEL, ppc64.AFSELCC, 0, 0},
- ppc64.AFSQRT: [4]int{ppc64.AFSQRT, ppc64.AFSQRTCC, 0, 0},
- ppc64.AFSQRTS: [4]int{ppc64.AFSQRTS, ppc64.AFSQRTSCC, 0, 0},
- ppc64.AFSUB: [4]int{ppc64.AFSUB, ppc64.AFSUBCC, 0, 0},
- ppc64.AFSUBS: [4]int{ppc64.AFSUBS, ppc64.AFSUBSCC, 0, 0},
- ppc64.AMTFSB0: [4]int{ppc64.AMTFSB0, ppc64.AMTFSB0CC, 0, 0},
- ppc64.AMTFSB1: [4]int{ppc64.AMTFSB1, ppc64.AMTFSB1CC, 0, 0},
- ppc64.AMULHD: [4]int{ppc64.AMULHD, ppc64.AMULHDCC, 0, 0},
- ppc64.AMULHDU: [4]int{ppc64.AMULHDU, ppc64.AMULHDUCC, 0, 0},
- ppc64.AMULHW: [4]int{ppc64.AMULHW, ppc64.AMULHWCC, 0, 0},
- ppc64.AMULHWU: [4]int{ppc64.AMULHWU, ppc64.AMULHWUCC, 0, 0},
- ppc64.AMULLD: [4]int{ppc64.AMULLD, ppc64.AMULLDCC, ppc64.AMULLDV, ppc64.AMULLDVCC},
- ppc64.AMULLW: [4]int{ppc64.AMULLW, ppc64.AMULLWCC, ppc64.AMULLWV, ppc64.AMULLWVCC},
- ppc64.ANAND: [4]int{ppc64.ANAND, ppc64.ANANDCC, 0, 0},
- ppc64.ANEG: [4]int{ppc64.ANEG, ppc64.ANEGCC, ppc64.ANEGV, ppc64.ANEGVCC},
- ppc64.ANOR: [4]int{ppc64.ANOR, ppc64.ANORCC, 0, 0},
- ppc64.AOR: [4]int{ppc64.AOR, ppc64.AORCC, 0, 0},
- ppc64.AORN: [4]int{ppc64.AORN, ppc64.AORNCC, 0, 0},
- ppc64.AREM: [4]int{ppc64.AREM, ppc64.AREMCC, ppc64.AREMV, ppc64.AREMVCC},
- ppc64.AREMD: [4]int{ppc64.AREMD, ppc64.AREMDCC, ppc64.AREMDV, ppc64.AREMDVCC},
- ppc64.AREMDU: [4]int{ppc64.AREMDU, ppc64.AREMDUCC, ppc64.AREMDUV, ppc64.AREMDUVCC},
- ppc64.AREMU: [4]int{ppc64.AREMU, ppc64.AREMUCC, ppc64.AREMUV, ppc64.AREMUVCC},
- ppc64.ARLDC: [4]int{ppc64.ARLDC, ppc64.ARLDCCC, 0, 0},
- ppc64.ARLDCL: [4]int{ppc64.ARLDCL, ppc64.ARLDCLCC, 0, 0},
- ppc64.ARLDCR: [4]int{ppc64.ARLDCR, ppc64.ARLDCRCC, 0, 0},
- ppc64.ARLDMI: [4]int{ppc64.ARLDMI, ppc64.ARLDMICC, 0, 0},
- ppc64.ARLWMI: [4]int{ppc64.ARLWMI, ppc64.ARLWMICC, 0, 0},
- ppc64.ARLWNM: [4]int{ppc64.ARLWNM, ppc64.ARLWNMCC, 0, 0},
- ppc64.ASLD: [4]int{ppc64.ASLD, ppc64.ASLDCC, 0, 0},
- ppc64.ASLW: [4]int{ppc64.ASLW, ppc64.ASLWCC, 0, 0},
- ppc64.ASRAD: [4]int{ppc64.ASRAD, ppc64.ASRADCC, 0, 0},
- ppc64.ASRAW: [4]int{ppc64.ASRAW, ppc64.ASRAWCC, 0, 0},
- ppc64.ASRD: [4]int{ppc64.ASRD, ppc64.ASRDCC, 0, 0},
- ppc64.ASRW: [4]int{ppc64.ASRW, ppc64.ASRWCC, 0, 0},
- ppc64.ASUB: [4]int{ppc64.ASUB, ppc64.ASUBCC, ppc64.ASUBV, ppc64.ASUBVCC},
- ppc64.ASUBC: [4]int{ppc64.ASUBC, ppc64.ASUBCCC, ppc64.ASUBCV, ppc64.ASUBCVCC},
- ppc64.ASUBE: [4]int{ppc64.ASUBE, ppc64.ASUBECC, ppc64.ASUBEV, ppc64.ASUBEVCC},
- ppc64.ASUBME: [4]int{ppc64.ASUBME, ppc64.ASUBMECC, ppc64.ASUBMEV, ppc64.ASUBMEVCC},
- ppc64.ASUBZE: [4]int{ppc64.ASUBZE, ppc64.ASUBZECC, ppc64.ASUBZEV, ppc64.ASUBZEVCC},
- ppc64.AXOR: [4]int{ppc64.AXOR, ppc64.AXORCC, 0, 0},
-}
-
-var initvariants_initialized int
-
-func initvariants() {
- if initvariants_initialized != 0 {
- return
- }
- initvariants_initialized = 1
-
- var j int
- for i := int(0); i < len(varianttable); i++ {
- if varianttable[i][0] == 0 {
- // Instruction has no variants
- varianttable[i][0] = i
-
- continue
- }
-
- // Copy base form to other variants
- if varianttable[i][0] == i {
- for j = 0; j < len(varianttable[i]); j++ {
- varianttable[varianttable[i][j]] = varianttable[i]
- }
- }
- }
-}
-
-// as2variant returns the variant (V_*) flags of instruction as.
-func as2variant(as int) int {
- initvariants()
- for i := int(0); i < len(varianttable[as]); i++ {
- if varianttable[as][i] == as {
- return i
- }
+ info.Regset |= RtoB(mips.REGRT1) | RtoB(mips.REGRT2)
}
- gc.Fatalf("as2variant: instruction %v is not a variant of itself", obj.Aconv(as))
- return 0
-}
-
-// variant2as returns the instruction as with the given variant (V_*) flags.
-// If no such variant exists, this returns 0.
-func variant2as(as int, flags int) int {
- initvariants()
- return varianttable[as][flags]
}
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package ppc64
+package mips64
-import "cmd/internal/obj/ppc64"
+import "cmd/internal/obj/mips"
import "cmd/compile/internal/gc"
const (
func excludedregs() uint64 {
// Exclude registers with fixed functions
- regbits := uint64(1<<0 | RtoB(ppc64.REGSP) | RtoB(ppc64.REGG) | RtoB(ppc64.REGTLS))
+ regbits := uint64(1<<0 | RtoB(mips.REGSP) | RtoB(mips.REGG) | RtoB(mips.REGTMP) | RtoB(mips.REGLINK) | RtoB(mips.REG_R26) | RtoB(mips.REG_R27))
// Also exclude floating point registers with fixed constants
- regbits |= RtoB(ppc64.REG_F27) | RtoB(ppc64.REG_F28) | RtoB(ppc64.REG_F29) | RtoB(ppc64.REG_F30) | RtoB(ppc64.REG_F31)
+ regbits |= RtoB(mips.FREGZERO) | RtoB(mips.FREGHALF) | RtoB(mips.FREGONE) | RtoB(mips.FREGTWO)
return regbits
}
* 32+31 F31
*/
func RtoB(r int) uint64 {
- if r > ppc64.REG_R0 && r <= ppc64.REG_R31 {
- return 1 << uint(r-ppc64.REG_R0)
+ if r > mips.REG_R0 && r <= mips.REG_R31 {
+ return 1 << uint(r-mips.REG_R0)
}
- if r >= ppc64.REG_F0 && r <= ppc64.REG_F31 {
- return 1 << uint(32+r-ppc64.REG_F0)
+ if r >= mips.REG_F0 && r <= mips.REG_F31 {
+ return 1 << uint(32+r-mips.REG_F0)
}
return 0
}
if b == 0 {
return 0
}
- return gc.Bitno(b) + ppc64.REG_R0
+ return gc.Bitno(b) + mips.REG_R0
}
func BtoF(b uint64) int {
if b == 0 {
return 0
}
- return gc.Bitno(b) + ppc64.REG_F0
+ return gc.Bitno(b) + mips.REG_F0
}
gc.Widthptr = 8
gc.Widthint = 8
gc.Widthreg = 8
+
+ if gc.Ctxt.Flag_shared != 0 {
+ gc.Thearch.ReservedRegs = append(gc.Thearch.ReservedRegs, ppc64.REG_R2)
+ gc.Thearch.ReservedRegs = append(gc.Thearch.ReservedRegs, ppc64.REG_R12)
+ }
}
func Main() {
* res = nl % nr
* according to op.
*/
-func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
+func dodiv(op gc.Op, nl *gc.Node, nr *gc.Node, res *gc.Node) {
// Have to be careful about handling
// most negative int divided by -1 correctly.
// The hardware will generate undefined result.
* res = nl << nr
* res = nl >> nr
*/
-func cgen_shift(op int, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
+func cgen_shift(op gc.Op, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
a := int(optoas(op, nl.Type))
if nr.Op == gc.OLITERAL {
gc.Regfree(&ntmp)
}
-func ginscmp(op int, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
+func ginscmp(op gc.Op, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
if gc.Isint[t.Etype] && n1.Op == gc.OLITERAL && n2.Op != gc.OLITERAL {
// Reverse comparison to place constant last.
op = gc.Brrev(op)
case obj.ACALL:
if p.To.Type == obj.TYPE_REG && p.To.Reg != ppc64.REG_CTR {
// Allow front end to emit CALL REG, and rewrite into MOV REG, CTR; CALL CTR.
+ if gc.Ctxt.Flag_shared != 0 {
+ // Make sure function pointer is in R12 as well when
+ // compiling Go into PIC.
+ // TODO(mwhudson): it would obviously be better to
+ // change the register allocation to put the value in
+ // R12 already, but I don't know how to do that.
+ q := gc.Prog(as)
+ q.As = ppc64.AMOVD
+ q.From = p.To
+ q.To.Type = obj.TYPE_REG
+ q.To.Reg = ppc64.REG_R12
+ }
pp := gc.Prog(as)
pp.From = p.From
pp.To.Type = obj.TYPE_REG
p.To.Type = obj.TYPE_REG
p.To.Reg = ppc64.REG_CTR
+ if gc.Ctxt.Flag_shared != 0 {
+ // When compiling Go into PIC, the function we just
+ // called via pointer might have been implemented in
+ // a separate module and so overwritten the TOC
+ // pointer in R2; reload it.
+ q := gc.Prog(ppc64.AMOVD)
+ q.From.Type = obj.TYPE_MEM
+ q.From.Offset = 24
+ q.From.Reg = ppc64.REGSP
+ q.To.Type = obj.TYPE_REG
+ q.To.Reg = ppc64.REG_R2
+ }
+
if gc.Debug['g'] != 0 {
fmt.Printf("%v\n", p)
fmt.Printf("%v\n", pp)
/*
* return Axxx for Oxxx on type t.
*/
-func optoas(op int, t *gc.Type) int {
+func optoas(op gc.Op, t *gc.Type) int {
if t == nil {
gc.Fatalf("optoas: t is nil")
}
+ // avoid constant conversions in switches below
+ const (
+ OMINUS_ = uint32(gc.OMINUS) << 16
+ OLSH_ = uint32(gc.OLSH) << 16
+ ORSH_ = uint32(gc.ORSH) << 16
+ OADD_ = uint32(gc.OADD) << 16
+ OSUB_ = uint32(gc.OSUB) << 16
+ OMUL_ = uint32(gc.OMUL) << 16
+ ODIV_ = uint32(gc.ODIV) << 16
+ OOR_ = uint32(gc.OOR) << 16
+ OAND_ = uint32(gc.OAND) << 16
+ OXOR_ = uint32(gc.OXOR) << 16
+ OEQ_ = uint32(gc.OEQ) << 16
+ ONE_ = uint32(gc.ONE) << 16
+ OLT_ = uint32(gc.OLT) << 16
+ OLE_ = uint32(gc.OLE) << 16
+ OGE_ = uint32(gc.OGE) << 16
+ OGT_ = uint32(gc.OGT) << 16
+ OCMP_ = uint32(gc.OCMP) << 16
+ OAS_ = uint32(gc.OAS) << 16
+ OHMUL_ = uint32(gc.OHMUL) << 16
+ )
+
a := int(obj.AXXX)
switch uint32(op)<<16 | uint32(gc.Simtype[t.Etype]) {
default:
gc.Fatalf("optoas: no entry for op=%v type=%v", gc.Oconv(int(op), 0), t)
- case gc.OEQ<<16 | gc.TBOOL,
- gc.OEQ<<16 | gc.TINT8,
- gc.OEQ<<16 | gc.TUINT8,
- gc.OEQ<<16 | gc.TINT16,
- gc.OEQ<<16 | gc.TUINT16,
- gc.OEQ<<16 | gc.TINT32,
- gc.OEQ<<16 | gc.TUINT32,
- gc.OEQ<<16 | gc.TINT64,
- gc.OEQ<<16 | gc.TUINT64,
- gc.OEQ<<16 | gc.TPTR32,
- gc.OEQ<<16 | gc.TPTR64,
- gc.OEQ<<16 | gc.TFLOAT32,
- gc.OEQ<<16 | gc.TFLOAT64:
+ case OEQ_ | gc.TBOOL,
+ OEQ_ | gc.TINT8,
+ OEQ_ | gc.TUINT8,
+ OEQ_ | gc.TINT16,
+ OEQ_ | gc.TUINT16,
+ OEQ_ | gc.TINT32,
+ OEQ_ | gc.TUINT32,
+ OEQ_ | gc.TINT64,
+ OEQ_ | gc.TUINT64,
+ OEQ_ | gc.TPTR32,
+ OEQ_ | gc.TPTR64,
+ OEQ_ | gc.TFLOAT32,
+ OEQ_ | gc.TFLOAT64:
a = ppc64.ABEQ
- case gc.ONE<<16 | gc.TBOOL,
- gc.ONE<<16 | gc.TINT8,
- gc.ONE<<16 | gc.TUINT8,
- gc.ONE<<16 | gc.TINT16,
- gc.ONE<<16 | gc.TUINT16,
- gc.ONE<<16 | gc.TINT32,
- gc.ONE<<16 | gc.TUINT32,
- gc.ONE<<16 | gc.TINT64,
- gc.ONE<<16 | gc.TUINT64,
- gc.ONE<<16 | gc.TPTR32,
- gc.ONE<<16 | gc.TPTR64,
- gc.ONE<<16 | gc.TFLOAT32,
- gc.ONE<<16 | gc.TFLOAT64:
+ case ONE_ | gc.TBOOL,
+ ONE_ | gc.TINT8,
+ ONE_ | gc.TUINT8,
+ ONE_ | gc.TINT16,
+ ONE_ | gc.TUINT16,
+ ONE_ | gc.TINT32,
+ ONE_ | gc.TUINT32,
+ ONE_ | gc.TINT64,
+ ONE_ | gc.TUINT64,
+ ONE_ | gc.TPTR32,
+ ONE_ | gc.TPTR64,
+ ONE_ | gc.TFLOAT32,
+ ONE_ | gc.TFLOAT64:
a = ppc64.ABNE
- case gc.OLT<<16 | gc.TINT8, // ACMP
- gc.OLT<<16 | gc.TINT16,
- gc.OLT<<16 | gc.TINT32,
- gc.OLT<<16 | gc.TINT64,
- gc.OLT<<16 | gc.TUINT8,
+ case OLT_ | gc.TINT8, // ACMP
+ OLT_ | gc.TINT16,
+ OLT_ | gc.TINT32,
+ OLT_ | gc.TINT64,
+ OLT_ | gc.TUINT8,
// ACMPU
- gc.OLT<<16 | gc.TUINT16,
- gc.OLT<<16 | gc.TUINT32,
- gc.OLT<<16 | gc.TUINT64,
- gc.OLT<<16 | gc.TFLOAT32,
+ OLT_ | gc.TUINT16,
+ OLT_ | gc.TUINT32,
+ OLT_ | gc.TUINT64,
+ OLT_ | gc.TFLOAT32,
// AFCMPU
- gc.OLT<<16 | gc.TFLOAT64:
+ OLT_ | gc.TFLOAT64:
a = ppc64.ABLT
- case gc.OLE<<16 | gc.TINT8, // ACMP
- gc.OLE<<16 | gc.TINT16,
- gc.OLE<<16 | gc.TINT32,
- gc.OLE<<16 | gc.TINT64,
- gc.OLE<<16 | gc.TUINT8,
+ case OLE_ | gc.TINT8, // ACMP
+ OLE_ | gc.TINT16,
+ OLE_ | gc.TINT32,
+ OLE_ | gc.TINT64,
+ OLE_ | gc.TUINT8,
// ACMPU
- gc.OLE<<16 | gc.TUINT16,
- gc.OLE<<16 | gc.TUINT32,
- gc.OLE<<16 | gc.TUINT64:
+ OLE_ | gc.TUINT16,
+ OLE_ | gc.TUINT32,
+ OLE_ | gc.TUINT64:
// No OLE for floats, because it mishandles NaN.
// Front end must reverse comparison or use OLT and OEQ together.
a = ppc64.ABLE
- case gc.OGT<<16 | gc.TINT8,
- gc.OGT<<16 | gc.TINT16,
- gc.OGT<<16 | gc.TINT32,
- gc.OGT<<16 | gc.TINT64,
- gc.OGT<<16 | gc.TUINT8,
- gc.OGT<<16 | gc.TUINT16,
- gc.OGT<<16 | gc.TUINT32,
- gc.OGT<<16 | gc.TUINT64,
- gc.OGT<<16 | gc.TFLOAT32,
- gc.OGT<<16 | gc.TFLOAT64:
+ case OGT_ | gc.TINT8,
+ OGT_ | gc.TINT16,
+ OGT_ | gc.TINT32,
+ OGT_ | gc.TINT64,
+ OGT_ | gc.TUINT8,
+ OGT_ | gc.TUINT16,
+ OGT_ | gc.TUINT32,
+ OGT_ | gc.TUINT64,
+ OGT_ | gc.TFLOAT32,
+ OGT_ | gc.TFLOAT64:
a = ppc64.ABGT
- case gc.OGE<<16 | gc.TINT8,
- gc.OGE<<16 | gc.TINT16,
- gc.OGE<<16 | gc.TINT32,
- gc.OGE<<16 | gc.TINT64,
- gc.OGE<<16 | gc.TUINT8,
- gc.OGE<<16 | gc.TUINT16,
- gc.OGE<<16 | gc.TUINT32,
- gc.OGE<<16 | gc.TUINT64:
+ case OGE_ | gc.TINT8,
+ OGE_ | gc.TINT16,
+ OGE_ | gc.TINT32,
+ OGE_ | gc.TINT64,
+ OGE_ | gc.TUINT8,
+ OGE_ | gc.TUINT16,
+ OGE_ | gc.TUINT32,
+ OGE_ | gc.TUINT64:
// No OGE for floats, because it mishandles NaN.
// Front end must reverse comparison or use OLT and OEQ together.
a = ppc64.ABGE
- case gc.OCMP<<16 | gc.TBOOL,
- gc.OCMP<<16 | gc.TINT8,
- gc.OCMP<<16 | gc.TINT16,
- gc.OCMP<<16 | gc.TINT32,
- gc.OCMP<<16 | gc.TPTR32,
- gc.OCMP<<16 | gc.TINT64:
+ case OCMP_ | gc.TBOOL,
+ OCMP_ | gc.TINT8,
+ OCMP_ | gc.TINT16,
+ OCMP_ | gc.TINT32,
+ OCMP_ | gc.TPTR32,
+ OCMP_ | gc.TINT64:
a = ppc64.ACMP
- case gc.OCMP<<16 | gc.TUINT8,
- gc.OCMP<<16 | gc.TUINT16,
- gc.OCMP<<16 | gc.TUINT32,
- gc.OCMP<<16 | gc.TUINT64,
- gc.OCMP<<16 | gc.TPTR64:
+ case OCMP_ | gc.TUINT8,
+ OCMP_ | gc.TUINT16,
+ OCMP_ | gc.TUINT32,
+ OCMP_ | gc.TUINT64,
+ OCMP_ | gc.TPTR64:
a = ppc64.ACMPU
- case gc.OCMP<<16 | gc.TFLOAT32,
- gc.OCMP<<16 | gc.TFLOAT64:
+ case OCMP_ | gc.TFLOAT32,
+ OCMP_ | gc.TFLOAT64:
a = ppc64.AFCMPU
- case gc.OAS<<16 | gc.TBOOL,
- gc.OAS<<16 | gc.TINT8:
+ case OAS_ | gc.TBOOL,
+ OAS_ | gc.TINT8:
a = ppc64.AMOVB
- case gc.OAS<<16 | gc.TUINT8:
+ case OAS_ | gc.TUINT8:
a = ppc64.AMOVBZ
- case gc.OAS<<16 | gc.TINT16:
+ case OAS_ | gc.TINT16:
a = ppc64.AMOVH
- case gc.OAS<<16 | gc.TUINT16:
+ case OAS_ | gc.TUINT16:
a = ppc64.AMOVHZ
- case gc.OAS<<16 | gc.TINT32:
+ case OAS_ | gc.TINT32:
a = ppc64.AMOVW
- case gc.OAS<<16 | gc.TUINT32,
- gc.OAS<<16 | gc.TPTR32:
+ case OAS_ | gc.TUINT32,
+ OAS_ | gc.TPTR32:
a = ppc64.AMOVWZ
- case gc.OAS<<16 | gc.TINT64,
- gc.OAS<<16 | gc.TUINT64,
- gc.OAS<<16 | gc.TPTR64:
+ case OAS_ | gc.TINT64,
+ OAS_ | gc.TUINT64,
+ OAS_ | gc.TPTR64:
a = ppc64.AMOVD
- case gc.OAS<<16 | gc.TFLOAT32:
+ case OAS_ | gc.TFLOAT32:
a = ppc64.AFMOVS
- case gc.OAS<<16 | gc.TFLOAT64:
+ case OAS_ | gc.TFLOAT64:
a = ppc64.AFMOVD
- case gc.OADD<<16 | gc.TINT8,
- gc.OADD<<16 | gc.TUINT8,
- gc.OADD<<16 | gc.TINT16,
- gc.OADD<<16 | gc.TUINT16,
- gc.OADD<<16 | gc.TINT32,
- gc.OADD<<16 | gc.TUINT32,
- gc.OADD<<16 | gc.TPTR32,
- gc.OADD<<16 | gc.TINT64,
- gc.OADD<<16 | gc.TUINT64,
- gc.OADD<<16 | gc.TPTR64:
+ case OADD_ | gc.TINT8,
+ OADD_ | gc.TUINT8,
+ OADD_ | gc.TINT16,
+ OADD_ | gc.TUINT16,
+ OADD_ | gc.TINT32,
+ OADD_ | gc.TUINT32,
+ OADD_ | gc.TPTR32,
+ OADD_ | gc.TINT64,
+ OADD_ | gc.TUINT64,
+ OADD_ | gc.TPTR64:
a = ppc64.AADD
- case gc.OADD<<16 | gc.TFLOAT32:
+ case OADD_ | gc.TFLOAT32:
a = ppc64.AFADDS
- case gc.OADD<<16 | gc.TFLOAT64:
+ case OADD_ | gc.TFLOAT64:
a = ppc64.AFADD
- case gc.OSUB<<16 | gc.TINT8,
- gc.OSUB<<16 | gc.TUINT8,
- gc.OSUB<<16 | gc.TINT16,
- gc.OSUB<<16 | gc.TUINT16,
- gc.OSUB<<16 | gc.TINT32,
- gc.OSUB<<16 | gc.TUINT32,
- gc.OSUB<<16 | gc.TPTR32,
- gc.OSUB<<16 | gc.TINT64,
- gc.OSUB<<16 | gc.TUINT64,
- gc.OSUB<<16 | gc.TPTR64:
+ case OSUB_ | gc.TINT8,
+ OSUB_ | gc.TUINT8,
+ OSUB_ | gc.TINT16,
+ OSUB_ | gc.TUINT16,
+ OSUB_ | gc.TINT32,
+ OSUB_ | gc.TUINT32,
+ OSUB_ | gc.TPTR32,
+ OSUB_ | gc.TINT64,
+ OSUB_ | gc.TUINT64,
+ OSUB_ | gc.TPTR64:
a = ppc64.ASUB
- case gc.OSUB<<16 | gc.TFLOAT32:
+ case OSUB_ | gc.TFLOAT32:
a = ppc64.AFSUBS
- case gc.OSUB<<16 | gc.TFLOAT64:
+ case OSUB_ | gc.TFLOAT64:
a = ppc64.AFSUB
- case gc.OMINUS<<16 | gc.TINT8,
- gc.OMINUS<<16 | gc.TUINT8,
- gc.OMINUS<<16 | gc.TINT16,
- gc.OMINUS<<16 | gc.TUINT16,
- gc.OMINUS<<16 | gc.TINT32,
- gc.OMINUS<<16 | gc.TUINT32,
- gc.OMINUS<<16 | gc.TPTR32,
- gc.OMINUS<<16 | gc.TINT64,
- gc.OMINUS<<16 | gc.TUINT64,
- gc.OMINUS<<16 | gc.TPTR64:
+ case OMINUS_ | gc.TINT8,
+ OMINUS_ | gc.TUINT8,
+ OMINUS_ | gc.TINT16,
+ OMINUS_ | gc.TUINT16,
+ OMINUS_ | gc.TINT32,
+ OMINUS_ | gc.TUINT32,
+ OMINUS_ | gc.TPTR32,
+ OMINUS_ | gc.TINT64,
+ OMINUS_ | gc.TUINT64,
+ OMINUS_ | gc.TPTR64:
a = ppc64.ANEG
- case gc.OAND<<16 | gc.TINT8,
- gc.OAND<<16 | gc.TUINT8,
- gc.OAND<<16 | gc.TINT16,
- gc.OAND<<16 | gc.TUINT16,
- gc.OAND<<16 | gc.TINT32,
- gc.OAND<<16 | gc.TUINT32,
- gc.OAND<<16 | gc.TPTR32,
- gc.OAND<<16 | gc.TINT64,
- gc.OAND<<16 | gc.TUINT64,
- gc.OAND<<16 | gc.TPTR64:
+ case OAND_ | gc.TINT8,
+ OAND_ | gc.TUINT8,
+ OAND_ | gc.TINT16,
+ OAND_ | gc.TUINT16,
+ OAND_ | gc.TINT32,
+ OAND_ | gc.TUINT32,
+ OAND_ | gc.TPTR32,
+ OAND_ | gc.TINT64,
+ OAND_ | gc.TUINT64,
+ OAND_ | gc.TPTR64:
a = ppc64.AAND
- case gc.OOR<<16 | gc.TINT8,
- gc.OOR<<16 | gc.TUINT8,
- gc.OOR<<16 | gc.TINT16,
- gc.OOR<<16 | gc.TUINT16,
- gc.OOR<<16 | gc.TINT32,
- gc.OOR<<16 | gc.TUINT32,
- gc.OOR<<16 | gc.TPTR32,
- gc.OOR<<16 | gc.TINT64,
- gc.OOR<<16 | gc.TUINT64,
- gc.OOR<<16 | gc.TPTR64:
+ case OOR_ | gc.TINT8,
+ OOR_ | gc.TUINT8,
+ OOR_ | gc.TINT16,
+ OOR_ | gc.TUINT16,
+ OOR_ | gc.TINT32,
+ OOR_ | gc.TUINT32,
+ OOR_ | gc.TPTR32,
+ OOR_ | gc.TINT64,
+ OOR_ | gc.TUINT64,
+ OOR_ | gc.TPTR64:
a = ppc64.AOR
- case gc.OXOR<<16 | gc.TINT8,
- gc.OXOR<<16 | gc.TUINT8,
- gc.OXOR<<16 | gc.TINT16,
- gc.OXOR<<16 | gc.TUINT16,
- gc.OXOR<<16 | gc.TINT32,
- gc.OXOR<<16 | gc.TUINT32,
- gc.OXOR<<16 | gc.TPTR32,
- gc.OXOR<<16 | gc.TINT64,
- gc.OXOR<<16 | gc.TUINT64,
- gc.OXOR<<16 | gc.TPTR64:
+ case OXOR_ | gc.TINT8,
+ OXOR_ | gc.TUINT8,
+ OXOR_ | gc.TINT16,
+ OXOR_ | gc.TUINT16,
+ OXOR_ | gc.TINT32,
+ OXOR_ | gc.TUINT32,
+ OXOR_ | gc.TPTR32,
+ OXOR_ | gc.TINT64,
+ OXOR_ | gc.TUINT64,
+ OXOR_ | gc.TPTR64:
a = ppc64.AXOR
// TODO(minux): handle rotates
// a = 0//???; RLDC?
// break;
- case gc.OLSH<<16 | gc.TINT8,
- gc.OLSH<<16 | gc.TUINT8,
- gc.OLSH<<16 | gc.TINT16,
- gc.OLSH<<16 | gc.TUINT16,
- gc.OLSH<<16 | gc.TINT32,
- gc.OLSH<<16 | gc.TUINT32,
- gc.OLSH<<16 | gc.TPTR32,
- gc.OLSH<<16 | gc.TINT64,
- gc.OLSH<<16 | gc.TUINT64,
- gc.OLSH<<16 | gc.TPTR64:
+ case OLSH_ | gc.TINT8,
+ OLSH_ | gc.TUINT8,
+ OLSH_ | gc.TINT16,
+ OLSH_ | gc.TUINT16,
+ OLSH_ | gc.TINT32,
+ OLSH_ | gc.TUINT32,
+ OLSH_ | gc.TPTR32,
+ OLSH_ | gc.TINT64,
+ OLSH_ | gc.TUINT64,
+ OLSH_ | gc.TPTR64:
a = ppc64.ASLD
- case gc.ORSH<<16 | gc.TUINT8,
- gc.ORSH<<16 | gc.TUINT16,
- gc.ORSH<<16 | gc.TUINT32,
- gc.ORSH<<16 | gc.TPTR32,
- gc.ORSH<<16 | gc.TUINT64,
- gc.ORSH<<16 | gc.TPTR64:
+ case ORSH_ | gc.TUINT8,
+ ORSH_ | gc.TUINT16,
+ ORSH_ | gc.TUINT32,
+ ORSH_ | gc.TPTR32,
+ ORSH_ | gc.TUINT64,
+ ORSH_ | gc.TPTR64:
a = ppc64.ASRD
- case gc.ORSH<<16 | gc.TINT8,
- gc.ORSH<<16 | gc.TINT16,
- gc.ORSH<<16 | gc.TINT32,
- gc.ORSH<<16 | gc.TINT64:
+ case ORSH_ | gc.TINT8,
+ ORSH_ | gc.TINT16,
+ ORSH_ | gc.TINT32,
+ ORSH_ | gc.TINT64:
a = ppc64.ASRAD
// TODO(minux): handle rotates
// a = 0//??? RLDC??
// break;
- case gc.OHMUL<<16 | gc.TINT64:
+ case OHMUL_ | gc.TINT64:
a = ppc64.AMULHD
- case gc.OHMUL<<16 | gc.TUINT64,
- gc.OHMUL<<16 | gc.TPTR64:
+ case OHMUL_ | gc.TUINT64,
+ OHMUL_ | gc.TPTR64:
a = ppc64.AMULHDU
- case gc.OMUL<<16 | gc.TINT8,
- gc.OMUL<<16 | gc.TINT16,
- gc.OMUL<<16 | gc.TINT32,
- gc.OMUL<<16 | gc.TINT64:
+ case OMUL_ | gc.TINT8,
+ OMUL_ | gc.TINT16,
+ OMUL_ | gc.TINT32,
+ OMUL_ | gc.TINT64:
a = ppc64.AMULLD
- case gc.OMUL<<16 | gc.TUINT8,
- gc.OMUL<<16 | gc.TUINT16,
- gc.OMUL<<16 | gc.TUINT32,
- gc.OMUL<<16 | gc.TPTR32,
+ case OMUL_ | gc.TUINT8,
+ OMUL_ | gc.TUINT16,
+ OMUL_ | gc.TUINT32,
+ OMUL_ | gc.TPTR32,
// don't use word multiply, the high 32-bit are undefined.
- gc.OMUL<<16 | gc.TUINT64,
- gc.OMUL<<16 | gc.TPTR64:
+ OMUL_ | gc.TUINT64,
+ OMUL_ | gc.TPTR64:
// for 64-bit multiplies, signedness doesn't matter.
a = ppc64.AMULLD
- case gc.OMUL<<16 | gc.TFLOAT32:
+ case OMUL_ | gc.TFLOAT32:
a = ppc64.AFMULS
- case gc.OMUL<<16 | gc.TFLOAT64:
+ case OMUL_ | gc.TFLOAT64:
a = ppc64.AFMUL
- case gc.ODIV<<16 | gc.TINT8,
- gc.ODIV<<16 | gc.TINT16,
- gc.ODIV<<16 | gc.TINT32,
- gc.ODIV<<16 | gc.TINT64:
+ case ODIV_ | gc.TINT8,
+ ODIV_ | gc.TINT16,
+ ODIV_ | gc.TINT32,
+ ODIV_ | gc.TINT64:
a = ppc64.ADIVD
- case gc.ODIV<<16 | gc.TUINT8,
- gc.ODIV<<16 | gc.TUINT16,
- gc.ODIV<<16 | gc.TUINT32,
- gc.ODIV<<16 | gc.TPTR32,
- gc.ODIV<<16 | gc.TUINT64,
- gc.ODIV<<16 | gc.TPTR64:
+ case ODIV_ | gc.TUINT8,
+ ODIV_ | gc.TUINT16,
+ ODIV_ | gc.TUINT32,
+ ODIV_ | gc.TPTR32,
+ ODIV_ | gc.TUINT64,
+ ODIV_ | gc.TPTR64:
a = ppc64.ADIVDU
- case gc.ODIV<<16 | gc.TFLOAT32:
+ case ODIV_ | gc.TFLOAT32:
a = ppc64.AFDIVS
- case gc.ODIV<<16 | gc.TFLOAT64:
+ case ODIV_ | gc.TFLOAT64:
a = ppc64.AFDIV
}
// Exclude registers with fixed functions
regbits := uint64(1<<0 | RtoB(ppc64.REGSP) | RtoB(ppc64.REGG) | RtoB(ppc64.REGTLS) | RtoB(ppc64.REGTMP))
+ if gc.Ctxt.Flag_shared != 0 {
+ // When compiling Go into PIC, R2 is reserved to be the TOC pointer
+ // and R12 so that calls via function pointer can stomp on it.
+ regbits |= RtoB(ppc64.REG_R2)
+ regbits |= RtoB(ppc64.REG_R12)
+ }
// Also exclude floating point registers with fixed constants
regbits |= RtoB(ppc64.REG_F27) | RtoB(ppc64.REG_F28) | RtoB(ppc64.REG_F29) | RtoB(ppc64.REG_F30) | RtoB(ppc64.REG_F31)
gins(x86.ASUBL, &lo2, &ax)
gins(x86.ASBBL, &hi2, &dx)
- // let's call the next two EX and FX.
case gc.OMUL:
- var ex gc.Node
+ // let's call the next three EX, FX and GX
+ var ex, fx, gx gc.Node
gc.Regalloc(&ex, gc.Types[gc.TPTR32], nil)
-
- var fx gc.Node
gc.Regalloc(&fx, gc.Types[gc.TPTR32], nil)
+ gc.Regalloc(&gx, gc.Types[gc.TPTR32], nil)
- // load args into DX:AX and EX:CX.
+ // load args into DX:AX and EX:GX.
gins(x86.AMOVL, &lo1, &ax)
gins(x86.AMOVL, &hi1, &dx)
- gins(x86.AMOVL, &lo2, &cx)
+ gins(x86.AMOVL, &lo2, &gx)
gins(x86.AMOVL, &hi2, &ex)
// if DX and EX are zero, use 32 x 32 -> 64 unsigned multiply.
gins(x86.AORL, &ex, &fx)
p1 := gc.Gbranch(x86.AJNE, nil, 0)
- gins(x86.AMULL, &cx, nil) // implicit &ax
+ gins(x86.AMULL, &gx, nil) // implicit &ax
p2 := gc.Gbranch(obj.AJMP, nil, 0)
gc.Patch(p1, gc.Pc)
// full 64x64 -> 64, from 32x32 -> 64.
- gins(x86.AIMULL, &cx, &dx)
+ gins(x86.AIMULL, &gx, &dx)
gins(x86.AMOVL, &ax, &fx)
gins(x86.AIMULL, &ex, &fx)
gins(x86.AADDL, &dx, &fx)
- gins(x86.AMOVL, &cx, &dx)
+ gins(x86.AMOVL, &gx, &dx)
gins(x86.AMULL, &dx, nil) // implicit &ax
gins(x86.AADDL, &fx, &dx)
gc.Patch(p2, gc.Pc)
gc.Regfree(&ex)
gc.Regfree(&fx)
+ gc.Regfree(&gx)
- // We only rotate by a constant c in [0,64).
+ // We only rotate by a constant c in [0,64).
// if c >= 32:
// lo, hi = hi, lo
// c -= 32
gins(x86.AMOVL, &lo1, &ax)
gins(x86.AMOVL, &hi1, &dx)
- gins(optoas(int(n.Op), lo1.Type), &lo2, &ax)
- gins(optoas(int(n.Op), lo1.Type), &hi2, &dx)
+ gins(optoas(n.Op, lo1.Type), &lo2, &ax)
+ gins(optoas(n.Op, lo1.Type), &hi2, &dx)
}
if gc.Is64(r.Type) {
* generate comparison of nl, nr, both 64-bit.
* nl is memory; nr is constant or memory.
*/
-func cmp64(nl *gc.Node, nr *gc.Node, op int, likely int, to *obj.Prog) {
+func cmp64(nl *gc.Node, nr *gc.Node, op gc.Op, likely int, to *obj.Prog) {
var lo1 gc.Node
var hi1 gc.Node
var lo2 gc.Node
* res = nl % nr
* according to op.
*/
-func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node, ax *gc.Node, dx *gc.Node) {
+func dodiv(op gc.Op, nl *gc.Node, nr *gc.Node, res *gc.Node, ax *gc.Node, dx *gc.Node) {
// Have to be careful about handling
// most negative int divided by -1 correctly.
// The hardware will trap.
* res = nl / nr
* res = nl % nr
*/
-func cgen_div(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
+func cgen_div(op gc.Op, nl *gc.Node, nr *gc.Node, res *gc.Node) {
if gc.Is64(nl.Type) {
gc.Fatalf("cgen_div %v", nl.Type)
}
* res = nl << nr
* res = nl >> nr
*/
-func cgen_shift(op int, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
+func cgen_shift(op gc.Op, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
if nl.Type.Width > 4 {
gc.Fatalf("cgen_shift %v", nl.Type)
}
* there is no 2-operand byte multiply instruction so
* we do a full-width multiplication and truncate afterwards.
*/
-func cgen_bmul(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) bool {
+func cgen_bmul(op gc.Op, nl *gc.Node, nr *gc.Node, res *gc.Node) bool {
if optoas(op, nl.Type) != x86.AIMULB {
return false
}
if nl.Ullman >= nr.Ullman {
gc.Cgen(nl, &f0)
if nr.Addable {
- gins(foptoas(int(n.Op), n.Type, 0), nr, &f0)
+ gins(foptoas(n.Op, n.Type, 0), nr, &f0)
} else {
gc.Cgen(nr, &f0)
- gins(foptoas(int(n.Op), n.Type, Fpop), &f0, &f1)
+ gins(foptoas(n.Op, n.Type, Fpop), &f0, &f1)
}
} else {
gc.Cgen(nr, &f0)
if nl.Addable {
- gins(foptoas(int(n.Op), n.Type, Frev), nl, &f0)
+ gins(foptoas(n.Op, n.Type, Frev), nl, &f0)
} else {
gc.Cgen(nl, &f0)
- gins(foptoas(int(n.Op), n.Type, Frev|Fpop), &f0, &f1)
+ gins(foptoas(n.Op, n.Type, Frev|Fpop), &f0, &f1)
}
}
gc.Cgen(nl, &f0)
if n.Op != gc.OCONV && n.Op != gc.OPLUS {
- gins(foptoas(int(n.Op), n.Type, 0), nil, nil)
+ gins(foptoas(n.Op, n.Type, 0), nil, nil)
}
gmove(&f0, res)
return
// symmetric binary
case gc.OADD,
gc.OMUL:
- a = foptoas(int(n.Op), nl.Type, 0)
+ a = foptoas(n.Op, nl.Type, 0)
goto sbop
case gc.OSUB,
gc.OMOD,
gc.ODIV:
- a = foptoas(int(n.Op), nl.Type, 0)
+ a = foptoas(n.Op, nl.Type, 0)
goto abop
}
func bgen_float(n *gc.Node, wantTrue bool, likely int, to *obj.Prog) {
nl := n.Left
nr := n.Right
- a := int(n.Op)
+ op := n.Op
if !wantTrue {
// brcom is not valid on floats when NaN is involved.
p1 := gc.Gbranch(obj.AJMP, nil, 0)
}
if gc.Thearch.Use387 {
- a = gc.Brrev(a) // because the args are stacked
- if a == gc.OGE || a == gc.OGT {
+ op = gc.Brrev(op) // because the args are stacked
+ if op == gc.OGE || op == gc.OGT {
// only < and <= work right with NaN; reverse if needed
nl, nr = nr, nl
- a = gc.Brrev(a)
+ op = gc.Brrev(op)
}
var ax, n2, tmp gc.Node
nl = &n3
}
- if a == gc.OGE || a == gc.OGT {
- // only < and <= work right with NaN; reverse if needed
+ if op == gc.OGE || op == gc.OGT {
+ // only < and <= work right with NopN; reverse if needed
nl, nr = nr, nl
- a = gc.Brrev(a)
+ op = gc.Brrev(op)
}
gins(foptoas(gc.OCMP, nr.Type, 0), nl, nr)
gc.Regfree(nr)
}
- switch a {
+ switch op {
case gc.OEQ:
// neither NE nor P
p1 := gc.Gbranch(x86.AJNE, nil, -likely)
gc.Patch(gc.Gbranch(x86.AJNE, nil, likely), to)
gc.Patch(gc.Gbranch(x86.AJPS, nil, likely), to)
default:
- gc.Patch(gc.Gbranch(optoas(a, nr.Type), nil, likely), to)
+ gc.Patch(gc.Gbranch(optoas(op, nr.Type), nil, likely), to)
}
}
/*
* return Axxx for Oxxx on type t.
*/
-func optoas(op int, t *gc.Type) int {
+func optoas(op gc.Op, t *gc.Type) int {
if t == nil {
gc.Fatalf("optoas: t is nil")
}
+ // avoid constant conversions in switches below
+ const (
+ OMINUS_ = uint32(gc.OMINUS) << 16
+ OLSH_ = uint32(gc.OLSH) << 16
+ ORSH_ = uint32(gc.ORSH) << 16
+ OADD_ = uint32(gc.OADD) << 16
+ OSUB_ = uint32(gc.OSUB) << 16
+ OMUL_ = uint32(gc.OMUL) << 16
+ ODIV_ = uint32(gc.ODIV) << 16
+ OMOD_ = uint32(gc.OMOD) << 16
+ OOR_ = uint32(gc.OOR) << 16
+ OAND_ = uint32(gc.OAND) << 16
+ OXOR_ = uint32(gc.OXOR) << 16
+ OEQ_ = uint32(gc.OEQ) << 16
+ ONE_ = uint32(gc.ONE) << 16
+ OLT_ = uint32(gc.OLT) << 16
+ OLE_ = uint32(gc.OLE) << 16
+ OGE_ = uint32(gc.OGE) << 16
+ OGT_ = uint32(gc.OGT) << 16
+ OCMP_ = uint32(gc.OCMP) << 16
+ OAS_ = uint32(gc.OAS) << 16
+ OHMUL_ = uint32(gc.OHMUL) << 16
+ OADDR_ = uint32(gc.OADDR) << 16
+ OINC_ = uint32(gc.OINC) << 16
+ ODEC_ = uint32(gc.ODEC) << 16
+ OLROT_ = uint32(gc.OLROT) << 16
+ OEXTEND_ = uint32(gc.OEXTEND) << 16
+ OCOM_ = uint32(gc.OCOM) << 16
+ )
+
a := obj.AXXX
switch uint32(op)<<16 | uint32(gc.Simtype[t.Etype]) {
default:
gc.Fatalf("optoas: no entry %v-%v", gc.Oconv(int(op), 0), t)
- case gc.OADDR<<16 | gc.TPTR32:
+ case OADDR_ | gc.TPTR32:
a = x86.ALEAL
- case gc.OEQ<<16 | gc.TBOOL,
- gc.OEQ<<16 | gc.TINT8,
- gc.OEQ<<16 | gc.TUINT8,
- gc.OEQ<<16 | gc.TINT16,
- gc.OEQ<<16 | gc.TUINT16,
- gc.OEQ<<16 | gc.TINT32,
- gc.OEQ<<16 | gc.TUINT32,
- gc.OEQ<<16 | gc.TINT64,
- gc.OEQ<<16 | gc.TUINT64,
- gc.OEQ<<16 | gc.TPTR32,
- gc.OEQ<<16 | gc.TPTR64,
- gc.OEQ<<16 | gc.TFLOAT32,
- gc.OEQ<<16 | gc.TFLOAT64:
+ case OEQ_ | gc.TBOOL,
+ OEQ_ | gc.TINT8,
+ OEQ_ | gc.TUINT8,
+ OEQ_ | gc.TINT16,
+ OEQ_ | gc.TUINT16,
+ OEQ_ | gc.TINT32,
+ OEQ_ | gc.TUINT32,
+ OEQ_ | gc.TINT64,
+ OEQ_ | gc.TUINT64,
+ OEQ_ | gc.TPTR32,
+ OEQ_ | gc.TPTR64,
+ OEQ_ | gc.TFLOAT32,
+ OEQ_ | gc.TFLOAT64:
a = x86.AJEQ
- case gc.ONE<<16 | gc.TBOOL,
- gc.ONE<<16 | gc.TINT8,
- gc.ONE<<16 | gc.TUINT8,
- gc.ONE<<16 | gc.TINT16,
- gc.ONE<<16 | gc.TUINT16,
- gc.ONE<<16 | gc.TINT32,
- gc.ONE<<16 | gc.TUINT32,
- gc.ONE<<16 | gc.TINT64,
- gc.ONE<<16 | gc.TUINT64,
- gc.ONE<<16 | gc.TPTR32,
- gc.ONE<<16 | gc.TPTR64,
- gc.ONE<<16 | gc.TFLOAT32,
- gc.ONE<<16 | gc.TFLOAT64:
+ case ONE_ | gc.TBOOL,
+ ONE_ | gc.TINT8,
+ ONE_ | gc.TUINT8,
+ ONE_ | gc.TINT16,
+ ONE_ | gc.TUINT16,
+ ONE_ | gc.TINT32,
+ ONE_ | gc.TUINT32,
+ ONE_ | gc.TINT64,
+ ONE_ | gc.TUINT64,
+ ONE_ | gc.TPTR32,
+ ONE_ | gc.TPTR64,
+ ONE_ | gc.TFLOAT32,
+ ONE_ | gc.TFLOAT64:
a = x86.AJNE
- case gc.OLT<<16 | gc.TINT8,
- gc.OLT<<16 | gc.TINT16,
- gc.OLT<<16 | gc.TINT32,
- gc.OLT<<16 | gc.TINT64:
+ case OLT_ | gc.TINT8,
+ OLT_ | gc.TINT16,
+ OLT_ | gc.TINT32,
+ OLT_ | gc.TINT64:
a = x86.AJLT
- case gc.OLT<<16 | gc.TUINT8,
- gc.OLT<<16 | gc.TUINT16,
- gc.OLT<<16 | gc.TUINT32,
- gc.OLT<<16 | gc.TUINT64:
+ case OLT_ | gc.TUINT8,
+ OLT_ | gc.TUINT16,
+ OLT_ | gc.TUINT32,
+ OLT_ | gc.TUINT64:
a = x86.AJCS
- case gc.OLE<<16 | gc.TINT8,
- gc.OLE<<16 | gc.TINT16,
- gc.OLE<<16 | gc.TINT32,
- gc.OLE<<16 | gc.TINT64:
+ case OLE_ | gc.TINT8,
+ OLE_ | gc.TINT16,
+ OLE_ | gc.TINT32,
+ OLE_ | gc.TINT64:
a = x86.AJLE
- case gc.OLE<<16 | gc.TUINT8,
- gc.OLE<<16 | gc.TUINT16,
- gc.OLE<<16 | gc.TUINT32,
- gc.OLE<<16 | gc.TUINT64:
+ case OLE_ | gc.TUINT8,
+ OLE_ | gc.TUINT16,
+ OLE_ | gc.TUINT32,
+ OLE_ | gc.TUINT64:
a = x86.AJLS
- case gc.OGT<<16 | gc.TINT8,
- gc.OGT<<16 | gc.TINT16,
- gc.OGT<<16 | gc.TINT32,
- gc.OGT<<16 | gc.TINT64:
+ case OGT_ | gc.TINT8,
+ OGT_ | gc.TINT16,
+ OGT_ | gc.TINT32,
+ OGT_ | gc.TINT64:
a = x86.AJGT
- case gc.OGT<<16 | gc.TUINT8,
- gc.OGT<<16 | gc.TUINT16,
- gc.OGT<<16 | gc.TUINT32,
- gc.OGT<<16 | gc.TUINT64,
- gc.OLT<<16 | gc.TFLOAT32,
- gc.OLT<<16 | gc.TFLOAT64:
+ case OGT_ | gc.TUINT8,
+ OGT_ | gc.TUINT16,
+ OGT_ | gc.TUINT32,
+ OGT_ | gc.TUINT64,
+ OLT_ | gc.TFLOAT32,
+ OLT_ | gc.TFLOAT64:
a = x86.AJHI
- case gc.OGE<<16 | gc.TINT8,
- gc.OGE<<16 | gc.TINT16,
- gc.OGE<<16 | gc.TINT32,
- gc.OGE<<16 | gc.TINT64:
+ case OGE_ | gc.TINT8,
+ OGE_ | gc.TINT16,
+ OGE_ | gc.TINT32,
+ OGE_ | gc.TINT64:
a = x86.AJGE
- case gc.OGE<<16 | gc.TUINT8,
- gc.OGE<<16 | gc.TUINT16,
- gc.OGE<<16 | gc.TUINT32,
- gc.OGE<<16 | gc.TUINT64,
- gc.OLE<<16 | gc.TFLOAT32,
- gc.OLE<<16 | gc.TFLOAT64:
+ case OGE_ | gc.TUINT8,
+ OGE_ | gc.TUINT16,
+ OGE_ | gc.TUINT32,
+ OGE_ | gc.TUINT64,
+ OLE_ | gc.TFLOAT32,
+ OLE_ | gc.TFLOAT64:
a = x86.AJCC
- case gc.OCMP<<16 | gc.TBOOL,
- gc.OCMP<<16 | gc.TINT8,
- gc.OCMP<<16 | gc.TUINT8:
+ case OCMP_ | gc.TBOOL,
+ OCMP_ | gc.TINT8,
+ OCMP_ | gc.TUINT8:
a = x86.ACMPB
- case gc.OCMP<<16 | gc.TINT16,
- gc.OCMP<<16 | gc.TUINT16:
+ case OCMP_ | gc.TINT16,
+ OCMP_ | gc.TUINT16:
a = x86.ACMPW
- case gc.OCMP<<16 | gc.TINT32,
- gc.OCMP<<16 | gc.TUINT32,
- gc.OCMP<<16 | gc.TPTR32:
+ case OCMP_ | gc.TINT32,
+ OCMP_ | gc.TUINT32,
+ OCMP_ | gc.TPTR32:
a = x86.ACMPL
- case gc.OAS<<16 | gc.TBOOL,
- gc.OAS<<16 | gc.TINT8,
- gc.OAS<<16 | gc.TUINT8:
+ case OAS_ | gc.TBOOL,
+ OAS_ | gc.TINT8,
+ OAS_ | gc.TUINT8:
a = x86.AMOVB
- case gc.OAS<<16 | gc.TINT16,
- gc.OAS<<16 | gc.TUINT16:
+ case OAS_ | gc.TINT16,
+ OAS_ | gc.TUINT16:
a = x86.AMOVW
- case gc.OAS<<16 | gc.TINT32,
- gc.OAS<<16 | gc.TUINT32,
- gc.OAS<<16 | gc.TPTR32:
+ case OAS_ | gc.TINT32,
+ OAS_ | gc.TUINT32,
+ OAS_ | gc.TPTR32:
a = x86.AMOVL
- case gc.OAS<<16 | gc.TFLOAT32:
+ case OAS_ | gc.TFLOAT32:
a = x86.AMOVSS
- case gc.OAS<<16 | gc.TFLOAT64:
+ case OAS_ | gc.TFLOAT64:
a = x86.AMOVSD
- case gc.OADD<<16 | gc.TINT8,
- gc.OADD<<16 | gc.TUINT8:
+ case OADD_ | gc.TINT8,
+ OADD_ | gc.TUINT8:
a = x86.AADDB
- case gc.OADD<<16 | gc.TINT16,
- gc.OADD<<16 | gc.TUINT16:
+ case OADD_ | gc.TINT16,
+ OADD_ | gc.TUINT16:
a = x86.AADDW
- case gc.OADD<<16 | gc.TINT32,
- gc.OADD<<16 | gc.TUINT32,
- gc.OADD<<16 | gc.TPTR32:
+ case OADD_ | gc.TINT32,
+ OADD_ | gc.TUINT32,
+ OADD_ | gc.TPTR32:
a = x86.AADDL
- case gc.OSUB<<16 | gc.TINT8,
- gc.OSUB<<16 | gc.TUINT8:
+ case OSUB_ | gc.TINT8,
+ OSUB_ | gc.TUINT8:
a = x86.ASUBB
- case gc.OSUB<<16 | gc.TINT16,
- gc.OSUB<<16 | gc.TUINT16:
+ case OSUB_ | gc.TINT16,
+ OSUB_ | gc.TUINT16:
a = x86.ASUBW
- case gc.OSUB<<16 | gc.TINT32,
- gc.OSUB<<16 | gc.TUINT32,
- gc.OSUB<<16 | gc.TPTR32:
+ case OSUB_ | gc.TINT32,
+ OSUB_ | gc.TUINT32,
+ OSUB_ | gc.TPTR32:
a = x86.ASUBL
- case gc.OINC<<16 | gc.TINT8,
- gc.OINC<<16 | gc.TUINT8:
+ case OINC_ | gc.TINT8,
+ OINC_ | gc.TUINT8:
a = x86.AINCB
- case gc.OINC<<16 | gc.TINT16,
- gc.OINC<<16 | gc.TUINT16:
+ case OINC_ | gc.TINT16,
+ OINC_ | gc.TUINT16:
a = x86.AINCW
- case gc.OINC<<16 | gc.TINT32,
- gc.OINC<<16 | gc.TUINT32,
- gc.OINC<<16 | gc.TPTR32:
+ case OINC_ | gc.TINT32,
+ OINC_ | gc.TUINT32,
+ OINC_ | gc.TPTR32:
a = x86.AINCL
- case gc.ODEC<<16 | gc.TINT8,
- gc.ODEC<<16 | gc.TUINT8:
+ case ODEC_ | gc.TINT8,
+ ODEC_ | gc.TUINT8:
a = x86.ADECB
- case gc.ODEC<<16 | gc.TINT16,
- gc.ODEC<<16 | gc.TUINT16:
+ case ODEC_ | gc.TINT16,
+ ODEC_ | gc.TUINT16:
a = x86.ADECW
- case gc.ODEC<<16 | gc.TINT32,
- gc.ODEC<<16 | gc.TUINT32,
- gc.ODEC<<16 | gc.TPTR32:
+ case ODEC_ | gc.TINT32,
+ ODEC_ | gc.TUINT32,
+ ODEC_ | gc.TPTR32:
a = x86.ADECL
- case gc.OCOM<<16 | gc.TINT8,
- gc.OCOM<<16 | gc.TUINT8:
+ case OCOM_ | gc.TINT8,
+ OCOM_ | gc.TUINT8:
a = x86.ANOTB
- case gc.OCOM<<16 | gc.TINT16,
- gc.OCOM<<16 | gc.TUINT16:
+ case OCOM_ | gc.TINT16,
+ OCOM_ | gc.TUINT16:
a = x86.ANOTW
- case gc.OCOM<<16 | gc.TINT32,
- gc.OCOM<<16 | gc.TUINT32,
- gc.OCOM<<16 | gc.TPTR32:
+ case OCOM_ | gc.TINT32,
+ OCOM_ | gc.TUINT32,
+ OCOM_ | gc.TPTR32:
a = x86.ANOTL
- case gc.OMINUS<<16 | gc.TINT8,
- gc.OMINUS<<16 | gc.TUINT8:
+ case OMINUS_ | gc.TINT8,
+ OMINUS_ | gc.TUINT8:
a = x86.ANEGB
- case gc.OMINUS<<16 | gc.TINT16,
- gc.OMINUS<<16 | gc.TUINT16:
+ case OMINUS_ | gc.TINT16,
+ OMINUS_ | gc.TUINT16:
a = x86.ANEGW
- case gc.OMINUS<<16 | gc.TINT32,
- gc.OMINUS<<16 | gc.TUINT32,
- gc.OMINUS<<16 | gc.TPTR32:
+ case OMINUS_ | gc.TINT32,
+ OMINUS_ | gc.TUINT32,
+ OMINUS_ | gc.TPTR32:
a = x86.ANEGL
- case gc.OAND<<16 | gc.TINT8,
- gc.OAND<<16 | gc.TUINT8:
+ case OAND_ | gc.TINT8,
+ OAND_ | gc.TUINT8:
a = x86.AANDB
- case gc.OAND<<16 | gc.TINT16,
- gc.OAND<<16 | gc.TUINT16:
+ case OAND_ | gc.TINT16,
+ OAND_ | gc.TUINT16:
a = x86.AANDW
- case gc.OAND<<16 | gc.TINT32,
- gc.OAND<<16 | gc.TUINT32,
- gc.OAND<<16 | gc.TPTR32:
+ case OAND_ | gc.TINT32,
+ OAND_ | gc.TUINT32,
+ OAND_ | gc.TPTR32:
a = x86.AANDL
- case gc.OOR<<16 | gc.TINT8,
- gc.OOR<<16 | gc.TUINT8:
+ case OOR_ | gc.TINT8,
+ OOR_ | gc.TUINT8:
a = x86.AORB
- case gc.OOR<<16 | gc.TINT16,
- gc.OOR<<16 | gc.TUINT16:
+ case OOR_ | gc.TINT16,
+ OOR_ | gc.TUINT16:
a = x86.AORW
- case gc.OOR<<16 | gc.TINT32,
- gc.OOR<<16 | gc.TUINT32,
- gc.OOR<<16 | gc.TPTR32:
+ case OOR_ | gc.TINT32,
+ OOR_ | gc.TUINT32,
+ OOR_ | gc.TPTR32:
a = x86.AORL
- case gc.OXOR<<16 | gc.TINT8,
- gc.OXOR<<16 | gc.TUINT8:
+ case OXOR_ | gc.TINT8,
+ OXOR_ | gc.TUINT8:
a = x86.AXORB
- case gc.OXOR<<16 | gc.TINT16,
- gc.OXOR<<16 | gc.TUINT16:
+ case OXOR_ | gc.TINT16,
+ OXOR_ | gc.TUINT16:
a = x86.AXORW
- case gc.OXOR<<16 | gc.TINT32,
- gc.OXOR<<16 | gc.TUINT32,
- gc.OXOR<<16 | gc.TPTR32:
+ case OXOR_ | gc.TINT32,
+ OXOR_ | gc.TUINT32,
+ OXOR_ | gc.TPTR32:
a = x86.AXORL
- case gc.OLROT<<16 | gc.TINT8,
- gc.OLROT<<16 | gc.TUINT8:
+ case OLROT_ | gc.TINT8,
+ OLROT_ | gc.TUINT8:
a = x86.AROLB
- case gc.OLROT<<16 | gc.TINT16,
- gc.OLROT<<16 | gc.TUINT16:
+ case OLROT_ | gc.TINT16,
+ OLROT_ | gc.TUINT16:
a = x86.AROLW
- case gc.OLROT<<16 | gc.TINT32,
- gc.OLROT<<16 | gc.TUINT32,
- gc.OLROT<<16 | gc.TPTR32:
+ case OLROT_ | gc.TINT32,
+ OLROT_ | gc.TUINT32,
+ OLROT_ | gc.TPTR32:
a = x86.AROLL
- case gc.OLSH<<16 | gc.TINT8,
- gc.OLSH<<16 | gc.TUINT8:
+ case OLSH_ | gc.TINT8,
+ OLSH_ | gc.TUINT8:
a = x86.ASHLB
- case gc.OLSH<<16 | gc.TINT16,
- gc.OLSH<<16 | gc.TUINT16:
+ case OLSH_ | gc.TINT16,
+ OLSH_ | gc.TUINT16:
a = x86.ASHLW
- case gc.OLSH<<16 | gc.TINT32,
- gc.OLSH<<16 | gc.TUINT32,
- gc.OLSH<<16 | gc.TPTR32:
+ case OLSH_ | gc.TINT32,
+ OLSH_ | gc.TUINT32,
+ OLSH_ | gc.TPTR32:
a = x86.ASHLL
- case gc.ORSH<<16 | gc.TUINT8:
+ case ORSH_ | gc.TUINT8:
a = x86.ASHRB
- case gc.ORSH<<16 | gc.TUINT16:
+ case ORSH_ | gc.TUINT16:
a = x86.ASHRW
- case gc.ORSH<<16 | gc.TUINT32,
- gc.ORSH<<16 | gc.TPTR32:
+ case ORSH_ | gc.TUINT32,
+ ORSH_ | gc.TPTR32:
a = x86.ASHRL
- case gc.ORSH<<16 | gc.TINT8:
+ case ORSH_ | gc.TINT8:
a = x86.ASARB
- case gc.ORSH<<16 | gc.TINT16:
+ case ORSH_ | gc.TINT16:
a = x86.ASARW
- case gc.ORSH<<16 | gc.TINT32:
+ case ORSH_ | gc.TINT32:
a = x86.ASARL
- case gc.OHMUL<<16 | gc.TINT8,
- gc.OMUL<<16 | gc.TINT8,
- gc.OMUL<<16 | gc.TUINT8:
+ case OHMUL_ | gc.TINT8,
+ OMUL_ | gc.TINT8,
+ OMUL_ | gc.TUINT8:
a = x86.AIMULB
- case gc.OHMUL<<16 | gc.TINT16,
- gc.OMUL<<16 | gc.TINT16,
- gc.OMUL<<16 | gc.TUINT16:
+ case OHMUL_ | gc.TINT16,
+ OMUL_ | gc.TINT16,
+ OMUL_ | gc.TUINT16:
a = x86.AIMULW
- case gc.OHMUL<<16 | gc.TINT32,
- gc.OMUL<<16 | gc.TINT32,
- gc.OMUL<<16 | gc.TUINT32,
- gc.OMUL<<16 | gc.TPTR32:
+ case OHMUL_ | gc.TINT32,
+ OMUL_ | gc.TINT32,
+ OMUL_ | gc.TUINT32,
+ OMUL_ | gc.TPTR32:
a = x86.AIMULL
- case gc.OHMUL<<16 | gc.TUINT8:
+ case OHMUL_ | gc.TUINT8:
a = x86.AMULB
- case gc.OHMUL<<16 | gc.TUINT16:
+ case OHMUL_ | gc.TUINT16:
a = x86.AMULW
- case gc.OHMUL<<16 | gc.TUINT32,
- gc.OHMUL<<16 | gc.TPTR32:
+ case OHMUL_ | gc.TUINT32,
+ OHMUL_ | gc.TPTR32:
a = x86.AMULL
- case gc.ODIV<<16 | gc.TINT8,
- gc.OMOD<<16 | gc.TINT8:
+ case ODIV_ | gc.TINT8,
+ OMOD_ | gc.TINT8:
a = x86.AIDIVB
- case gc.ODIV<<16 | gc.TUINT8,
- gc.OMOD<<16 | gc.TUINT8:
+ case ODIV_ | gc.TUINT8,
+ OMOD_ | gc.TUINT8:
a = x86.ADIVB
- case gc.ODIV<<16 | gc.TINT16,
- gc.OMOD<<16 | gc.TINT16:
+ case ODIV_ | gc.TINT16,
+ OMOD_ | gc.TINT16:
a = x86.AIDIVW
- case gc.ODIV<<16 | gc.TUINT16,
- gc.OMOD<<16 | gc.TUINT16:
+ case ODIV_ | gc.TUINT16,
+ OMOD_ | gc.TUINT16:
a = x86.ADIVW
- case gc.ODIV<<16 | gc.TINT32,
- gc.OMOD<<16 | gc.TINT32:
+ case ODIV_ | gc.TINT32,
+ OMOD_ | gc.TINT32:
a = x86.AIDIVL
- case gc.ODIV<<16 | gc.TUINT32,
- gc.ODIV<<16 | gc.TPTR32,
- gc.OMOD<<16 | gc.TUINT32,
- gc.OMOD<<16 | gc.TPTR32:
+ case ODIV_ | gc.TUINT32,
+ ODIV_ | gc.TPTR32,
+ OMOD_ | gc.TUINT32,
+ OMOD_ | gc.TPTR32:
a = x86.ADIVL
- case gc.OEXTEND<<16 | gc.TINT16:
+ case OEXTEND_ | gc.TINT16:
a = x86.ACWD
- case gc.OEXTEND<<16 | gc.TINT32:
+ case OEXTEND_ | gc.TINT32:
a = x86.ACDQ
}
return a
}
-func foptoas(op int, t *gc.Type, flg int) int {
+func foptoas(op gc.Op, t *gc.Type, flg int) int {
a := obj.AXXX
- et := int(gc.Simtype[t.Etype])
+ et := gc.Simtype[t.Etype]
+
+ // avoid constant conversions in switches below
+ const (
+ OCMP_ = uint32(gc.OCMP) << 16
+ OAS_ = uint32(gc.OAS) << 16
+ OADD_ = uint32(gc.OADD) << 16
+ OSUB_ = uint32(gc.OSUB) << 16
+ OMUL_ = uint32(gc.OMUL) << 16
+ ODIV_ = uint32(gc.ODIV) << 16
+ OMINUS_ = uint32(gc.OMINUS) << 16
+ )
if !gc.Thearch.Use387 {
switch uint32(op)<<16 | uint32(et) {
default:
gc.Fatalf("foptoas-sse: no entry %v-%v", gc.Oconv(int(op), 0), t)
- case gc.OCMP<<16 | gc.TFLOAT32:
+ case OCMP_ | gc.TFLOAT32:
a = x86.AUCOMISS
- case gc.OCMP<<16 | gc.TFLOAT64:
+ case OCMP_ | gc.TFLOAT64:
a = x86.AUCOMISD
- case gc.OAS<<16 | gc.TFLOAT32:
+ case OAS_ | gc.TFLOAT32:
a = x86.AMOVSS
- case gc.OAS<<16 | gc.TFLOAT64:
+ case OAS_ | gc.TFLOAT64:
a = x86.AMOVSD
- case gc.OADD<<16 | gc.TFLOAT32:
+ case OADD_ | gc.TFLOAT32:
a = x86.AADDSS
- case gc.OADD<<16 | gc.TFLOAT64:
+ case OADD_ | gc.TFLOAT64:
a = x86.AADDSD
- case gc.OSUB<<16 | gc.TFLOAT32:
+ case OSUB_ | gc.TFLOAT32:
a = x86.ASUBSS
- case gc.OSUB<<16 | gc.TFLOAT64:
+ case OSUB_ | gc.TFLOAT64:
a = x86.ASUBSD
- case gc.OMUL<<16 | gc.TFLOAT32:
+ case OMUL_ | gc.TFLOAT32:
a = x86.AMULSS
- case gc.OMUL<<16 | gc.TFLOAT64:
+ case OMUL_ | gc.TFLOAT64:
a = x86.AMULSD
- case gc.ODIV<<16 | gc.TFLOAT32:
+ case ODIV_ | gc.TFLOAT32:
a = x86.ADIVSS
- case gc.ODIV<<16 | gc.TFLOAT64:
+ case ODIV_ | gc.TFLOAT64:
a = x86.ADIVSD
}
}
switch uint32(op)<<16 | (uint32(et)<<8 | uint32(flg)) {
- case gc.OADD<<16 | (gc.TFLOAT32<<8 | 0):
+ case OADD_ | (gc.TFLOAT32<<8 | 0):
return x86.AFADDF
- case gc.OADD<<16 | (gc.TFLOAT64<<8 | 0):
+ case OADD_ | (gc.TFLOAT64<<8 | 0):
return x86.AFADDD
- case gc.OADD<<16 | (gc.TFLOAT64<<8 | Fpop):
+ case OADD_ | (gc.TFLOAT64<<8 | Fpop):
return x86.AFADDDP
- case gc.OSUB<<16 | (gc.TFLOAT32<<8 | 0):
+ case OSUB_ | (gc.TFLOAT32<<8 | 0):
return x86.AFSUBF
- case gc.OSUB<<16 | (gc.TFLOAT32<<8 | Frev):
+ case OSUB_ | (gc.TFLOAT32<<8 | Frev):
return x86.AFSUBRF
- case gc.OSUB<<16 | (gc.TFLOAT64<<8 | 0):
+ case OSUB_ | (gc.TFLOAT64<<8 | 0):
return x86.AFSUBD
- case gc.OSUB<<16 | (gc.TFLOAT64<<8 | Frev):
+ case OSUB_ | (gc.TFLOAT64<<8 | Frev):
return x86.AFSUBRD
- case gc.OSUB<<16 | (gc.TFLOAT64<<8 | Fpop):
+ case OSUB_ | (gc.TFLOAT64<<8 | Fpop):
return x86.AFSUBDP
- case gc.OSUB<<16 | (gc.TFLOAT64<<8 | (Fpop | Frev)):
+ case OSUB_ | (gc.TFLOAT64<<8 | (Fpop | Frev)):
return x86.AFSUBRDP
- case gc.OMUL<<16 | (gc.TFLOAT32<<8 | 0):
+ case OMUL_ | (gc.TFLOAT32<<8 | 0):
return x86.AFMULF
- case gc.OMUL<<16 | (gc.TFLOAT64<<8 | 0):
+ case OMUL_ | (gc.TFLOAT64<<8 | 0):
return x86.AFMULD
- case gc.OMUL<<16 | (gc.TFLOAT64<<8 | Fpop):
+ case OMUL_ | (gc.TFLOAT64<<8 | Fpop):
return x86.AFMULDP
- case gc.ODIV<<16 | (gc.TFLOAT32<<8 | 0):
+ case ODIV_ | (gc.TFLOAT32<<8 | 0):
return x86.AFDIVF
- case gc.ODIV<<16 | (gc.TFLOAT32<<8 | Frev):
+ case ODIV_ | (gc.TFLOAT32<<8 | Frev):
return x86.AFDIVRF
- case gc.ODIV<<16 | (gc.TFLOAT64<<8 | 0):
+ case ODIV_ | (gc.TFLOAT64<<8 | 0):
return x86.AFDIVD
- case gc.ODIV<<16 | (gc.TFLOAT64<<8 | Frev):
+ case ODIV_ | (gc.TFLOAT64<<8 | Frev):
return x86.AFDIVRD
- case gc.ODIV<<16 | (gc.TFLOAT64<<8 | Fpop):
+ case ODIV_ | (gc.TFLOAT64<<8 | Fpop):
return x86.AFDIVDP
- case gc.ODIV<<16 | (gc.TFLOAT64<<8 | (Fpop | Frev)):
+ case ODIV_ | (gc.TFLOAT64<<8 | (Fpop | Frev)):
return x86.AFDIVRDP
- case gc.OCMP<<16 | (gc.TFLOAT32<<8 | 0):
+ case OCMP_ | (gc.TFLOAT32<<8 | 0):
return x86.AFCOMF
- case gc.OCMP<<16 | (gc.TFLOAT32<<8 | Fpop):
+ case OCMP_ | (gc.TFLOAT32<<8 | Fpop):
return x86.AFCOMFP
- case gc.OCMP<<16 | (gc.TFLOAT64<<8 | 0):
+ case OCMP_ | (gc.TFLOAT64<<8 | 0):
return x86.AFCOMD
- case gc.OCMP<<16 | (gc.TFLOAT64<<8 | Fpop):
+ case OCMP_ | (gc.TFLOAT64<<8 | Fpop):
return x86.AFCOMDP
- case gc.OCMP<<16 | (gc.TFLOAT64<<8 | Fpop2):
+ case OCMP_ | (gc.TFLOAT64<<8 | Fpop2):
return x86.AFCOMDPP
- case gc.OMINUS<<16 | (gc.TFLOAT32<<8 | 0):
+ case OMINUS_ | (gc.TFLOAT32<<8 | 0):
return x86.AFCHS
- case gc.OMINUS<<16 | (gc.TFLOAT64<<8 | 0):
+ case OMINUS_ | (gc.TFLOAT64<<8 | 0):
return x86.AFCHS
}
gins(as, &n1, n2)
}
-func ginscmp(op int, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
- if gc.Isint[t.Etype] || int(t.Etype) == gc.Tptr {
+func ginscmp(op gc.Op, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
+ if gc.Isint[t.Etype] || t.Etype == gc.Tptr {
if (n1.Op == gc.OLITERAL || n1.Op == gc.OADDR && n1.Left.Op == gc.ONAME) && n2.Op != gc.OLITERAL {
// Reverse comparison to place constant (including address constant) last.
op = gc.Brrev(op)
} else {
// Implementation of conversion-free x = y for int64 or uint64 x.
// This is generated by the code that copies small values out of closures,
- // and that code has DX live, so avoid DX and use CX instead.
+ // and that code has DX live, so avoid DX and just use AX twice.
var r1 gc.Node
gc.Nodreg(&r1, gc.Types[gc.TUINT32], x86.REG_AX)
- var r2 gc.Node
- gc.Nodreg(&r2, gc.Types[gc.TUINT32], x86.REG_CX)
gins(x86.AMOVL, &flo, &r1)
- gins(x86.AMOVL, &fhi, &r2)
gins(x86.AMOVL, &r1, &tlo)
- gins(x86.AMOVL, &r2, &thi)
+ gins(x86.AMOVL, &fhi, &r1)
+ gins(x86.AMOVL, &r1, &thi)
}
splitclean()
"cmd/compile/internal/amd64"
"cmd/compile/internal/arm"
"cmd/compile/internal/arm64"
+ "cmd/compile/internal/mips64"
"cmd/compile/internal/ppc64"
"cmd/compile/internal/x86"
"cmd/internal/obj"
arm.Main()
case "arm64":
arm64.Main()
+ case "mips64", "mips64le":
+ mips64.Main()
case "ppc64", "ppc64le":
ppc64.Main()
}
"bytes"
"flag"
"fmt"
+ "io"
"os"
"os/exec"
"path/filepath"
rebuildall bool
defaultclang bool
- sflag bool // build static binaries
- vflag int // verbosity
+ vflag int // verbosity
)
// The known architectures.
"amd64p32",
"arm",
"arm64",
+ "mips64",
+ "mips64le",
"ppc64",
"ppc64le",
}
{"cmd/go", []string{
"zdefaultcc.go",
}},
- {"runtime", []string{
+ {"runtime/internal/sys", []string{
"zversion.go",
}},
}
}
// For package runtime, copy some files into the work space.
- if dir == "runtime" {
+ if dir == "runtime" || strings.HasPrefix(dir, "runtime/internal/") {
xmkdirall(pathf("%s/pkg/include", goroot))
// For use by assembly and C files.
copyfile(pathf("%s/pkg/include/textflag.h", goroot),
// Remove installed packages and tools.
xremoveall(pathf("%s/pkg/%s_%s", goroot, gohostos, gohostarch))
xremoveall(pathf("%s/pkg/%s_%s", goroot, goos, goarch))
+ xremoveall(pathf("%s/pkg/%s_%s_race", goroot, gohostos, gohostarch))
+ xremoveall(pathf("%s/pkg/%s_%s_race", goroot, goos, goarch))
xremoveall(tooldir)
// Remove cached version info.
// stopping at having installed the go_bootstrap command.
func cmdbootstrap() {
flag.BoolVar(&rebuildall, "a", rebuildall, "rebuild all")
- flag.BoolVar(&sflag, "s", sflag, "build static binaries")
xflagparse(0)
if isdir(pathf("%s/src/pkg", goroot)) {
setup()
checkCC()
+ copyLibgcc()
bootstrapBuildTools()
// For the main bootstrap, building for host os/arch.
}
}
+// copyLibgcc copies the C compiler's libgcc into the pkg directory.
+func copyLibgcc() {
+ if !needCC() {
+ return
+ }
+ var args []string
+ switch goarch {
+ case "386":
+ args = []string{"-m32"}
+ case "amd64", "amd64p32":
+ args = []string{"-m64"}
+ case "arm":
+ args = []string{"-marm"}
+ }
+ args = append(args, "--print-libgcc-file-name")
+ output, err := exec.Command(defaultcctarget, args...).Output()
+ if err != nil {
+ fatal("cannot find libgcc file name: %v", err)
+ }
+ libgcc := strings.TrimSpace(string(output))
+ if len(libgcc) == 0 {
+ return
+ }
+ in, err := os.Open(libgcc)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return
+ }
+ fatal("cannot open libgcc for copying: %v", err)
+ }
+ defer in.Close()
+ outdir := filepath.Join(goroot, "pkg", "libgcc", goos+"_"+goarch)
+ if err := os.MkdirAll(outdir, 0777); err != nil {
+ fatal("cannot create libgcc.a directory: %v", err)
+ }
+ out, err := os.Create(filepath.Join(outdir, "libgcc"))
+ if err != nil {
+ fatal("cannot create libgcc.a for copying: %v", err)
+ }
+ if _, err := io.Copy(out, in); err != nil {
+ fatal("error copying libgcc: %v", err)
+ }
+ if err := out.Close(); err != nil {
+ fatal("error closing new libgcc: %v", err)
+ }
+}
+
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
// Install installs the list of packages named on the command line.
func cmdinstall() {
- flag.BoolVar(&sflag, "s", sflag, "build static binaries")
xflagparse(-1)
if flag.NArg() == 0 {
// mkzversion writes zversion.go:
//
// package runtime
-// const defaultGoroot = <goroot>
-// const theVersion = <version>
-// const goexperiment = <goexperiment>
-// const stackGuardMultiplier = <multiplier value>
-// const buildVersion = <build version>
+// const DefaultGoroot = <goroot>
+// const TheVersion = <version>
+// const Goexperiment = <goexperiment>
+// const StackGuardMultiplier = <multiplier value>
+// const BuildVersion = <build version>
//
func mkzversion(dir, file string) {
out := fmt.Sprintf(
"// auto generated by go tool dist\n"+
"\n"+
- "package runtime\n"+
+ "package sys\n"+
"\n"+
- "const defaultGoroot = `%s`\n"+
- "const theVersion = `%s`\n"+
- "const goexperiment = `%s`\n"+
- "const stackGuardMultiplier = %d\n\n"+
- "var buildVersion = theVersion\n", goroot_final, findgoversion(), os.Getenv("GOEXPERIMENT"), stackGuardMultiplier())
+ "const DefaultGoroot = `%s`\n"+
+ "const TheVersion = `%s`\n"+
+ "const Goexperiment = `%s`\n"+
+ "const StackGuardMultiplier = %d\n\n"+
+ "var BuildVersion = TheVersion\n", goroot_final, findgoversion(), os.Getenv("GOEXPERIMENT"), stackGuardMultiplier())
writefile(out, file, writeSkipSame)
}
"compile/internal/arm64",
"compile/internal/big",
"compile/internal/gc",
+ "compile/internal/mips64",
"compile/internal/ppc64",
"compile/internal/ssa",
"compile/internal/x86",
"internal/obj",
"internal/obj/arm",
"internal/obj/arm64",
+ "internal/obj/mips",
"internal/obj/ppc64",
"internal/obj/x86",
"link",
"link/internal/arm",
"link/internal/arm64",
"link/internal/ld",
+ "link/internal/mips64",
"link/internal/ppc64",
"link/internal/x86",
}
package main
var builddeps = map[string][]string{
- "bufio": {"bytes", "errors", "io", "runtime", "sync", "sync/atomic", "unicode", "unicode/utf8"},
- "bytes": {"errors", "io", "runtime", "sync", "sync/atomic", "unicode", "unicode/utf8"},
- "container/heap": {"runtime", "sort"},
- "crypto": {"errors", "hash", "io", "math", "runtime", "strconv", "sync", "sync/atomic", "unicode/utf8"},
- "crypto/sha1": {"crypto", "errors", "hash", "io", "math", "runtime", "strconv", "sync", "sync/atomic", "unicode/utf8"},
- "debug/dwarf": {"encoding/binary", "errors", "fmt", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "path", "reflect", "runtime", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
- "debug/elf": {"bytes", "debug/dwarf", "encoding/binary", "errors", "fmt", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "path", "reflect", "runtime", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
- "encoding": {"runtime"},
- "encoding/base64": {"errors", "io", "math", "runtime", "strconv", "sync", "sync/atomic", "unicode/utf8"},
- "encoding/binary": {"errors", "io", "math", "reflect", "runtime", "strconv", "sync", "sync/atomic", "unicode/utf8"},
- "encoding/json": {"bytes", "encoding", "encoding/base64", "errors", "fmt", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "reflect", "runtime", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
- "errors": {"runtime"},
- "flag": {"errors", "fmt", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "reflect", "runtime", "sort", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
- "fmt": {"errors", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "reflect", "runtime", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
- "go/ast": {"bytes", "errors", "fmt", "go/scanner", "go/token", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "path/filepath", "reflect", "runtime", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
- "go/build": {"bufio", "bytes", "errors", "fmt", "go/ast", "go/doc", "go/parser", "go/scanner", "go/token", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "io/ioutil", "log", "math", "net/url", "os", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
- "go/doc": {"bytes", "errors", "fmt", "go/ast", "go/scanner", "go/token", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "io/ioutil", "math", "net/url", "os", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
- "go/parser": {"bytes", "errors", "fmt", "go/ast", "go/scanner", "go/token", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "io/ioutil", "math", "os", "path/filepath", "reflect", "runtime", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
- "go/scanner": {"bytes", "errors", "fmt", "go/token", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "path/filepath", "reflect", "runtime", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
- "go/token": {"errors", "fmt", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "reflect", "runtime", "sort", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
- "hash": {"errors", "io", "runtime", "sync", "sync/atomic"},
- "internal/singleflight": {"runtime", "sync", "sync/atomic"},
- "internal/syscall/windows": {"errors", "runtime", "sync", "sync/atomic", "syscall", "unicode/utf16"},
- "internal/syscall/windows/registry": {"errors", "io", "runtime", "sync", "sync/atomic", "syscall", "unicode/utf16"},
- "io": {"errors", "runtime", "sync", "sync/atomic"},
- "io/ioutil": {"bytes", "errors", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "path/filepath", "runtime", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
- "log": {"errors", "fmt", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "reflect", "runtime", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
- "math": {"runtime"},
- "net/url": {"bytes", "errors", "fmt", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "reflect", "runtime", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
- "os": {"errors", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "runtime", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
- "os/exec": {"bytes", "errors", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "path/filepath", "runtime", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
- "os/signal": {"errors", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "os", "runtime", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
- "path": {"errors", "io", "runtime", "strings", "sync", "sync/atomic", "unicode", "unicode/utf8"},
- "path/filepath": {"bytes", "errors", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "os", "runtime", "sort", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
- "reflect": {"errors", "math", "runtime", "strconv", "sync", "sync/atomic", "unicode/utf8"},
- "regexp": {"bytes", "errors", "io", "math", "regexp/syntax", "runtime", "sort", "strconv", "strings", "sync", "sync/atomic", "unicode", "unicode/utf8"},
- "regexp/syntax": {"bytes", "errors", "io", "math", "runtime", "sort", "strconv", "strings", "sync", "sync/atomic", "unicode", "unicode/utf8"},
- "runtime": {},
- "sort": {"runtime"},
- "strconv": {"errors", "math", "runtime", "unicode/utf8"},
- "strings": {"errors", "io", "runtime", "sync", "sync/atomic", "unicode", "unicode/utf8"},
- "sync": {"runtime", "sync/atomic"},
- "sync/atomic": {"runtime"},
- "syscall": {"errors", "runtime", "sync", "sync/atomic", "unicode/utf16"},
- "text/template": {"bytes", "errors", "fmt", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "io/ioutil", "math", "net/url", "os", "path/filepath", "reflect", "runtime", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
- "text/template/parse": {"bytes", "errors", "fmt", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "reflect", "runtime", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
- "time": {"errors", "internal/syscall/windows/registry", "io", "runtime", "sync", "sync/atomic", "syscall", "unicode/utf16"},
- "unicode": {"runtime"},
- "unicode/utf16": {"runtime"},
- "unicode/utf8": {"runtime"},
- "cmd/go": {"bufio", "bytes", "container/heap", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "encoding", "encoding/base64", "encoding/binary", "encoding/json", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "internal/singleflight", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+ "bufio": {"bytes", "errors", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "unicode", "unicode/utf8"},
+ "bytes": {"errors", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "unicode", "unicode/utf8"},
+ "container/heap": {"runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort"},
+ "crypto": {"errors", "hash", "io", "math", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "sync", "sync/atomic", "unicode/utf8"},
+ "crypto/sha1": {"crypto", "errors", "hash", "io", "math", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "sync", "sync/atomic", "unicode/utf8"},
+ "debug/dwarf": {"encoding/binary", "errors", "fmt", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "path", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+ "debug/elf": {"bytes", "debug/dwarf", "encoding/binary", "errors", "fmt", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "path", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+ "encoding": {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
+ "encoding/base64": {"errors", "io", "math", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "sync", "sync/atomic", "unicode/utf8"},
+ "encoding/binary": {"errors", "io", "math", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "sync", "sync/atomic", "unicode/utf8"},
+ "encoding/json": {"bytes", "encoding", "encoding/base64", "errors", "fmt", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+ "errors": {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
+ "flag": {"errors", "fmt", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
+ "fmt": {"errors", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
+ "go/ast": {"bytes", "errors", "fmt", "go/scanner", "go/token", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "path/filepath", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+ "go/build": {"bufio", "bytes", "errors", "fmt", "go/ast", "go/doc", "go/parser", "go/scanner", "go/token", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "io/ioutil", "log", "math", "net/url", "os", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+ "go/doc": {"bytes", "errors", "fmt", "go/ast", "go/scanner", "go/token", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "io/ioutil", "math", "net/url", "os", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+ "go/parser": {"bytes", "errors", "fmt", "go/ast", "go/scanner", "go/token", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "io/ioutil", "math", "os", "path/filepath", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+ "go/scanner": {"bytes", "errors", "fmt", "go/token", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "path/filepath", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+ "go/token": {"errors", "fmt", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
+ "hash": {"errors", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic"},
+ "internal/singleflight": {"runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic"},
+ "internal/syscall/windows": {"errors", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "syscall", "unicode/utf16"},
+ "internal/syscall/windows/registry": {"errors", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "syscall", "unicode/utf16"},
+ "io": {"errors", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic"},
+ "io/ioutil": {"bytes", "errors", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "path/filepath", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+ "log": {"errors", "fmt", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
+ "math": {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
+ "net/url": {"bytes", "errors", "fmt", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+ "os": {"errors", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
+ "os/exec": {"bytes", "errors", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "path/filepath", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+ "os/signal": {"errors", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "os", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
+ "path": {"errors", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strings", "sync", "sync/atomic", "unicode", "unicode/utf8"},
+ "path/filepath": {"errors", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "os", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+ "reflect": {"errors", "math", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "sync", "sync/atomic", "unicode/utf8"},
+ "regexp": {"bytes", "errors", "io", "math", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "unicode", "unicode/utf8"},
+ "regexp/syntax": {"bytes", "errors", "io", "math", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "unicode", "unicode/utf8"},
+ "runtime": {"runtime/internal/atomic", "runtime/internal/sys"},
+ "runtime/internal/atomic": {"runtime/internal/sys"},
+ "runtime/internal/sys": {},
+ "sort": {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
+ "strconv": {"errors", "math", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "unicode/utf8"},
+ "strings": {"errors", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "unicode", "unicode/utf8"},
+ "sync": {"runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync/atomic"},
+ "sync/atomic": {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
+ "syscall": {"errors", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "unicode/utf16"},
+ "text/template": {"bytes", "errors", "fmt", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "io/ioutil", "math", "net/url", "os", "path/filepath", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+ "text/template/parse": {"bytes", "errors", "fmt", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+ "time": {"errors", "internal/syscall/windows/registry", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "syscall", "unicode/utf16"},
+ "unicode": {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
+ "unicode/utf16": {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
+ "unicode/utf8": {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
+ "cmd/go": {"bufio", "bytes", "container/heap", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "encoding", "encoding/base64", "encoding/binary", "encoding/json", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "internal/singleflight", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
}
#!/bin/bash
+# Copyright 2015 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.
set -e
-# Windows has the most dependencies.
+declare -A alldeps
+
+# We need to test enough GOOS/GOARCH combinations to pick up all the
+# package dependencies.
+gooslist="windows linux darwin solaris"
+goarchlist="386 amd64 arm arm64 ppc64"
+
+for goos in $gooslist; do
+ for goarch in $goarchlist; do
+ deps=$(GOOS=$goos GOARCH=$goarch go list -tags cmd_go_bootstrap -f '{{join .Deps "\n"}}' cmd/go | grep -v '^unsafe$')
+ for dep in $deps cmd/go; do
+ alldeps[$dep]="${alldeps[$dep]} $(GOOS=$goos GOARCH=$goarch go list -tags cmd_go_bootstrap -f '{{range .Deps}}{{if not (eq . "unsafe")}}{{print .}} {{end}}{{end}}' $dep)"
+ done
+ done
+done
+
export GOOS=windows
(
echo
echo 'var builddeps = map[string][]string{'
- deps=$(GOOS=windows go list -tags cmd_go_bootstrap -f '{{join .Deps "\n"}}' cmd/go | grep -v '^unsafe$')
- GOOS=windows go list -tags cmd_go_bootstrap -f '{{printf "%q" .ImportPath}}: { {{range .Deps}}{{if not (eq . "unsafe")}}{{printf "%q" .}}, {{end}}{{end}} },' $deps cmd/go
+ for dep in $(for dep in ${!alldeps[@]}; do echo $dep; done | grep -v '^cmd/go$' | sort) cmd/go; do
+ echo -n '"'$dep'"': {
+ for subdep in ${alldeps[$dep]}; do
+ echo $subdep
+ done | sort -u | while read subdep; do
+ echo -n '"'$subdep'"',
+ done
+ echo },
+ done
echo '}'
) |gofmt >deps.go
t.registerTest("wiki", "../doc/articles/wiki", "./test.bash")
t.registerTest("codewalk", "../doc/codewalk", "time", "./run")
for _, name := range t.shootoutTests() {
- if name == "spectralnorm" && os.Getenv("GO_BUILDER_NAME") == "linux-arm-arm5" {
- // Heavy on floating point and takes over 20 minutes with softfloat.
- // Disabled per Issue 12688.
- continue
+ if name == "spectralnorm" {
+ switch os.Getenv("GO_BUILDER_NAME") {
+ case "linux-arm-arm5", "linux-mips64-minux":
+ // Heavy on floating point and takes over 20 minutes with
+ // softfloat on arm5 builder and over 33 minutes on MIPS64
+ // builder with kernel FPU emulator.
+ // Disabled per Issue 12688.
+ continue
+ }
}
t.registerTest("shootout:"+name, "../test/bench/shootout", "time", "./timing.sh", "-test", name)
}
}
if t.goos != "android" && !t.iOS() {
- t.registerTest("bench_go1", "../test/bench/go1", "go", "test")
+ t.registerTest("bench_go1", "../test/bench/go1", "go", "test", t.timeout(600))
}
if t.goos != "android" && !t.iOS() {
const nShards = 5
"darwin-arm", "darwin-arm64",
"dragonfly-386", "dragonfly-amd64",
"freebsd-386", "freebsd-amd64", "freebsd-arm",
- "linux-386", "linux-amd64", "linux-arm", "linux-arm64",
+ "linux-386", "linux-amd64", "linux-arm", "linux-arm64", "linux-ppc64le",
"netbsd-386", "netbsd-amd64",
"openbsd-386", "openbsd-amd64",
"windows-386", "windows-amd64":
case "c-shared":
// TODO(hyangah): add linux-386.
switch pair {
- case "linux-amd64", "darwin-amd64", "android-arm", "linux-arm":
+ case "linux-amd64", "darwin-amd64", "android-arm", "linux-arm", "linux-arm64":
return true
}
return false
case "shared":
switch pair {
- case "linux-amd64":
+ case "linux-amd64", "linux-arm", "linux-arm64", "linux-ppc64le":
return true
}
return false
// No exec facility on Android or iOS.
return false
}
- if t.goarch == "ppc64le" || t.goarch == "ppc64" {
+ if t.goarch == "ppc64" {
// External linking not implemented on ppc64 (issue #8912).
return false
}
+ if t.goarch == "mips64le" || t.goarch == "mips64" {
+ // External linking not implemented on mips64.
+ return false
+ }
return true
}
import (
"bytes"
+ "debug/elf"
+ "encoding/binary"
"fmt"
"io/ioutil"
"os"
if strings.Contains(run("", CheckExit, "sysctl", "machdep.cpu.extfeatures"), "EM64T") {
gohostarch = "amd64"
}
+ case "freebsd":
+ // Since FreeBSD 10 gcc is no longer part of the base system.
+ defaultclang = true
case "solaris":
// Even on 64-bit platform, solaris uname -m prints i86pc.
out := run("", CheckExit, "isainfo", "-n")
gohostarch = "ppc64le"
case strings.Contains(out, "ppc64"):
gohostarch = "ppc64"
+ case strings.Contains(out, "mips64"):
+ file, err := elf.Open(os.Args[0])
+ if err != nil {
+ fatal("failed to open %s to determine endianness: %v", os.Args[0], err)
+ }
+ if file.FileHeader.ByteOrder == binary.BigEndian {
+ gohostarch = "mips64"
+ } else {
+ gohostarch = "mips64le"
+ }
case gohostos == "darwin":
if strings.Contains(run("", CheckExit, "uname", "-v"), "RELEASE_ARM_") {
gohostarch = "arm"
-race
enable data race detection.
Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64.
+ -msan
+ enable interoperation with memory sanitizer.
+ Supported only on linux/amd64.
-v
print the names of packages as they are compiled.
-work
a suffix to use in the name of the package installation directory,
in order to keep output separate from default builds.
If using the -race flag, the install suffix is automatically set to race
- or, if set explicitly, has _race appended to it. Using a -buildmode
- option that requires non-default compile flags has a similar effect.
+ or, if set explicitly, has _race appended to it. Likewise for the -msan
+ flag. Using a -buildmode option that requires non-default compile flags
+ has a similar effect.
-ldflags 'flag list'
arguments to pass on each go tool link invocation.
-linkshared
link against shared libraries previously created with
- -buildmode=shared
+ -buildmode=shared.
-pkgdir dir
install and load all packages from dir instead of the usual locations.
For example, when building with a non-standard configuration,
Build the listed main packages and everything they import into
executables. Packages not named main are ignored.
+ -buildmode=pie
+ Build the listed main packages and everything they import into
+ position independent executables (PIE). Packages not named
+ main are ignored.
+
File types
-race
enable data race detection.
Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64.
+ -msan
+ enable interoperation with memory sanitizer.
+ Supported only on linux/amd64.
-v
print the names of packages as they are compiled.
-work
a suffix to use in the name of the package installation directory,
in order to keep output separate from default builds.
If using the -race flag, the install suffix is automatically set to race
- or, if set explicitly, has _race appended to it. Using a -buildmode
- option that requires non-default compile flags has a similar effect.
+ or, if set explicitly, has _race appended to it. Likewise for the -msan
+ flag. Using a -buildmode option that requires non-default compile flags
+ has a similar effect.
-ldflags 'flag list'
arguments to pass on each go tool link invocation.
-linkshared
link against shared libraries previously created with
- -buildmode=shared
+ -buildmode=shared.
-pkgdir dir
install and load all packages from dir instead of the usual locations.
For example, when building with a non-standard configuration,
var buildLdflags []string // -ldflags flag
var buildGccgoflags []string // -gccgoflags flag
var buildRace bool // -race flag
+var buildMSan bool // -msan flag
var buildToolExec []string // -toolexec flag
var buildBuildmode string // -buildmode flag
var buildLinkshared bool // -linkshared flag
cmd.Flag.BoolVar(&buildLinkshared, "linkshared", false, "")
cmd.Flag.StringVar(&buildPkgdir, "pkgdir", "", "")
cmd.Flag.BoolVar(&buildRace, "race", false, "")
+ cmd.Flag.BoolVar(&buildMSan, "msan", false, "")
cmd.Flag.Var((*stringsFlag)(&buildContext.BuildTags), "tags", "")
cmd.Flag.Var((*stringsFlag)(&buildToolExec), "toolexec", "")
cmd.Flag.BoolVar(&buildWork, "work", false, "")
codegenArg = "-fPIC"
} else {
switch platform {
- case "linux/amd64", "linux/arm", "android/arm":
+ case "linux/amd64", "linux/arm", "linux/arm64",
+ "android/amd64", "android/arm":
codegenArg = "-shared"
case "darwin/amd64":
default:
ldBuildmode = "c-shared"
case "default":
switch platform {
- case "android/arm":
+ case "android/arm", "android/arm64", "android/amd64":
codegenArg = "-shared"
ldBuildmode = "pie"
default:
fatalf("-buildmode=pie not supported by gccgo")
} else {
switch platform {
- case "android/arm":
+ case "linux/arm", "android/arm", "linux/amd64", "android/amd64", "linux/arm64", "android/arm64", "linux/ppc64le":
codegenArg = "-shared"
default:
fatalf("-buildmode=pie not supported on %s\n", platform)
codegenArg = "-fPIC"
} else {
switch platform {
- case "linux/amd64":
+ case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le":
default:
fatalf("-buildmode=shared not supported on %s\n", platform)
}
if gccgo {
codegenArg = "-fPIC"
} else {
- if platform != "linux/amd64" {
- fmt.Fprintf(os.Stderr, "go %s: -linkshared is only supported on linux/amd64\n", flag.Args()[0])
- os.Exit(2)
+ switch platform {
+ case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le":
+ buildAsmflags = append(buildAsmflags, "-D=GOBUILDMODE_shared=1")
+ default:
+ fatalf("-linkshared not supported on %s\n", platform)
}
codegenArg = "-dynlink"
// TODO(mwhudson): remove -w when that gets fixed in linker.
}
func runBuild(cmd *Command, args []string) {
- raceInit()
+ instrumentInit()
buildModeInit()
var b builder
b.init()
fatalf("cannot install, GOBIN must be an absolute path")
}
- raceInit()
+ instrumentInit()
buildModeInit()
pkgs := pkgsFilter(packagesForBuild(args))
// action returns the action for applying the given operation (mode) to the package.
// depMode is the action to use when building dependencies.
-// action never looks for p in a shared library.
+// action never looks for p in a shared library, but may find p's dependencies in a
+// shared library if buildLinkshared is true.
func (b *builder) action(mode buildMode, depMode buildMode, p *Package) *action {
- return b.action1(mode, depMode, p, false)
+ return b.action1(mode, depMode, p, false, "")
}
// action1 returns the action for applying the given operation (mode) to the package.
// depMode is the action to use when building dependencies.
// action1 will look for p in a shared library if lookshared is true.
-func (b *builder) action1(mode buildMode, depMode buildMode, p *Package, lookshared bool) *action {
+// forShlib is the shared library that p will become part of, if any.
+func (b *builder) action1(mode buildMode, depMode buildMode, p *Package, lookshared bool, forShlib string) *action {
shlib := ""
if lookshared {
shlib = p.Shlib
b.actionCache[key] = a
for _, p1 := range p.imports {
- ls := buildLinkshared
- // If p1 is part of the same shared library as p, we need the action
- // that builds p here, not the shared libary or we get action loops.
- if p1.Shlib == p.Shlib {
- ls = false
+ if forShlib != "" {
+ // p is part of a shared library.
+ if p1.Shlib != "" && p1.Shlib != forShlib {
+ // p1 is explicitly part of a different shared library.
+ // Put the action for that shared library into a.deps.
+ a.deps = append(a.deps, b.action1(depMode, depMode, p1, true, p1.Shlib))
+ } else {
+ // p1 is (implicitly or not) part of this shared library.
+ // Put the action for p1 into a.deps.
+ a.deps = append(a.deps, b.action1(depMode, depMode, p1, false, forShlib))
+ }
+ } else {
+ // p is not part of a shared library.
+ // If p1 is in a shared library, put the action for that into
+ // a.deps, otherwise put the action for p1 into a.deps.
+ a.deps = append(a.deps, b.action1(depMode, depMode, p1, buildLinkshared, p1.Shlib))
}
- a.deps = append(a.deps, b.action1(depMode, depMode, p1, ls))
}
// If we are not doing a cross-build, then record the binary we'll
// using cgo, to make sure we do not overwrite the binary while
// a package is using it. If this is a cross-build, then the cgo we
// are writing is not the cgo we need to use.
- if goos == runtime.GOOS && goarch == runtime.GOARCH && !buildRace {
+ if goos == runtime.GOOS && goarch == runtime.GOARCH && !buildRace && !buildMSan {
if (len(p.CgoFiles) > 0 || p.Standard && p.ImportPath == "runtime/cgo") && !buildLinkshared && buildBuildmode != "shared" {
var stk importStack
p1 := loadPackage("cmd/cgo", &stk)
switch mode {
case modeInstall:
a.f = (*builder).install
- a.deps = []*action{b.action1(modeBuild, depMode, p, lookshared)}
+ a.deps = []*action{b.action1(modeBuild, depMode, p, lookshared, forShlib)}
a.target = a.p.target
// Install header for cgo in c-archive and c-shared modes.
func (b *builder) libaction(libname string, pkgs []*Package, mode, depMode buildMode) *action {
a := &action{}
- if mode == modeBuild {
+ switch mode {
+ default:
+ fatalf("unrecognized mode %v", mode)
+
+ case modeBuild:
a.f = (*builder).linkShared
a.target = filepath.Join(b.work, libname)
for _, p := range pkgs {
}
a.deps = append(a.deps, b.action(depMode, depMode, p))
}
- } else if mode == modeInstall {
+
+ case modeInstall:
// Currently build mode shared forces external linking mode, and
- // external linking mode forces an import of runtime/cgo. So if it
- // was not passed on the command line and it is not present in
- // another shared library, add it here.
- seencgo := false
+ // external linking mode forces an import of runtime/cgo (and
+ // math on arm). So if it was not passed on the command line and
+ // it is not present in another shared library, add it here.
_, gccgo := buildToolchain.(gccgoToolchain)
if !gccgo {
+ seencgo := false
for _, p := range pkgs {
seencgo = seencgo || (p.Standard && p.ImportPath == "runtime/cgo")
}
pkgs = append(pkgs, p)
}
}
+ if goarch == "arm" {
+ seenmath := false
+ for _, p := range pkgs {
+ seenmath = seenmath || (p.Standard && p.ImportPath == "math")
+ }
+ if !seenmath {
+ var stk importStack
+ p := loadPackage("math", &stk)
+ if p.Error != nil {
+ fatalf("load math: %v", p.Error)
+ }
+ computeStale(p)
+ // If math is in another shared library, then that's
+ // also the shared library that contains runtime, so
+ // something will depend on it and so math's staleness
+ // will be checked when processing that library.
+ if p.Shlib == "" || p.Shlib == libname {
+ pkgs = append([]*Package{}, pkgs...)
+ pkgs = append(pkgs, p)
+ }
+ }
+ }
}
// Figure out where the library will go.
if err != nil || lstat.ModTime().After(built) {
stale = true
}
- a.deps = append(a.deps, b.action(depMode, depMode, p))
+ a.deps = append(a.deps, b.action1(depMode, depMode, p, false, a.target))
}
if stale {
shlibnameaction.deps = append(shlibnameaction.deps, buildAction)
}
}
- } else {
- fatalf("unregonized mode %v", mode)
}
return a
}
// different sections of the bootstrap script have to
// be merged, the banners give patch something
// to use to find its context.
- fmt.Printf("\n#\n# %s\n#\n\n", a.p.ImportPath)
+ b.print("\n#\n# " + a.p.ImportPath + "\n#\n\n")
}
if buildV {
- fmt.Fprintf(os.Stderr, "%s\n", a.p.ImportPath)
+ b.print(a.p.ImportPath + "\n")
}
// Make build directory.
if fi.IsDir() {
return fmt.Errorf("build output %q already exists and is a directory", dst)
}
- if !force && !isObject(dst) {
+ if !force && fi.Mode().IsRegular() && !isObject(dst) {
return fmt.Errorf("build output %q already exists and is not an object file", dst)
}
}
}
}
- os.Remove(dst)
+ mayberemovefile(dst)
df, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
if err != nil && toolIsWindows {
// Windows does not allow deletion of a binary file
_, err = io.Copy(df, sf)
df.Close()
if err != nil {
- os.Remove(dst)
+ mayberemovefile(dst)
return fmt.Errorf("copying %s to %s: %v", src, dst, err)
}
return nil
return false
}
+// mayberemovefile removes a file only if it is a regular file
+// When running as a user with sufficient privileges, we may delete
+// even device files, for example, which is not intended.
+func mayberemovefile(s string) {
+ if fi, err := os.Lstat(s); err == nil && !fi.Mode().IsRegular() {
+ return
+ }
+ os.Remove(s)
+}
+
// fmtcmd formats a command in the manner of fmt.Sprintf but also:
//
// If dir is non-empty and the script is not in dir right now,
if p.Name == "main" {
gcargs[1] = "main"
}
- if p.Standard && p.ImportPath == "runtime" {
+ if p.Standard && (p.ImportPath == "runtime" || strings.HasPrefix(p.ImportPath, "runtime/internal")) {
// runtime compiles with a special gc flag to emit
// additional reflect type data.
gcargs = append(gcargs, "-+")
for _, f := range ofiles {
absOfiles = append(absOfiles, mkAbs(objDir, f))
}
- cmd := "c"
absAfile := mkAbs(objDir, afile)
- appending := false
- if _, err := os.Stat(absAfile); err == nil {
- appending = true
- cmd = "r"
- }
- cmdline := stringList("pack", cmd, absAfile, absOfiles)
+ // The archive file should have been created by the compiler.
+ // Since it used to not work that way, verify.
+ if _, err := os.Stat(absAfile); err != nil {
+ fatalf("os.Stat of archive file failed: %v", err)
+ }
- if appending {
- if buildN || buildX {
- b.showcmd(p.Dir, "%s # internal", joinUnambiguously(cmdline))
- }
- if buildN {
- return nil
- }
- if err := packInternal(b, absAfile, absOfiles); err != nil {
- b.showOutput(p.Dir, p.ImportPath, err.Error()+"\n")
- return errPrintedOutput
- }
+ if buildN || buildX {
+ cmdline := stringList("pack", "r", absAfile, absOfiles)
+ b.showcmd(p.Dir, "%s # internal", joinUnambiguously(cmdline))
+ }
+ if buildN {
return nil
}
-
- // Need actual pack.
- cmdline[0] = tool("pack")
- return b.run(p.Dir, p.ImportPath, nil, buildToolExec, cmdline)
+ if err := packInternal(b, absAfile, absOfiles); err != nil {
+ b.showOutput(p.Dir, p.ImportPath, err.Error()+"\n")
+ return errPrintedOutput
+ }
+ return nil
}
func packInternal(b *builder, afile string, ofiles []string) error {
for _, f := range ofiles {
absOfiles = append(absOfiles, mkAbs(objDir, f))
}
- return b.run(p.Dir, p.ImportPath, nil, "ar", "cru", mkAbs(objDir, afile), absOfiles)
+ return b.run(p.Dir, p.ImportPath, nil, "ar", "rc", mkAbs(objDir, afile), absOfiles)
}
func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions []*action, mainpkg string, ofiles []string) error {
}
}
- switch ldBuildmode {
- case "c-archive", "c-shared":
- ldflags = append(ldflags, "-Wl,--whole-archive")
- }
-
+ ldflags = append(ldflags, "-Wl,--whole-archive")
ldflags = append(ldflags, afiles...)
-
- switch ldBuildmode {
- case "c-archive", "c-shared":
- ldflags = append(ldflags, "-Wl,--no-whole-archive")
- }
+ ldflags = append(ldflags, "-Wl,--no-whole-archive")
ldflags = append(ldflags, cgoldflags...)
ldflags = append(ldflags, envList("CGO_LDFLAGS", "")...)
return strings.Map(clean, gccgoPkgpath(p))
}
-// libgcc returns the filename for libgcc, as determined by invoking gcc with
-// the -print-libgcc-file-name option.
-func (b *builder) libgcc(p *Package) (string, error) {
- var buf bytes.Buffer
-
- gccCmd := b.gccCmd(p.Dir)
-
- prev := b.print
- if buildN {
- // In -n mode we temporarily swap out the builder's
- // print function to capture the command-line. This
- // let's us assign it to $LIBGCC and produce a valid
- // buildscript for cgo packages.
- b.print = func(a ...interface{}) (int, error) {
- return fmt.Fprint(&buf, a...)
- }
- }
- f, err := b.runOut(p.Dir, p.ImportPath, nil, gccCmd, "-print-libgcc-file-name")
- if err != nil {
- return "", fmt.Errorf("gcc -print-libgcc-file-name: %v (%s)", err, f)
- }
- if buildN {
- s := fmt.Sprintf("LIBGCC=$(%s)\n", buf.Next(buf.Len()-1))
- b.print = prev
- b.print(s)
- return "$LIBGCC", nil
- }
-
- // The compiler might not be able to find libgcc, and in that case,
- // it will simply return "libgcc.a", which is of no use to us.
- if !filepath.IsAbs(string(f)) {
- return "", nil
- }
-
- return strings.Trim(string(f), "\r\n"), nil
-}
-
// gcc runs the gcc C compiler to create an object from a single C file.
func (b *builder) gcc(p *Package, out string, flags []string, cfile string) error {
return b.ccompile(p, out, flags, cfile, b.gccCmd(p.Dir))
var cgoRe = regexp.MustCompile(`[/\\:]`)
-var (
- cgoLibGccFile string
- cgoLibGccErr error
- cgoLibGccFileOnce sync.Once
-)
-
func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofiles, gccfiles, gxxfiles, mfiles []string) (outGo, outObj []string, err error) {
cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, cgoLDFLAGS := b.cflags(p, true)
_, cgoexeCFLAGS, _, _ := b.cflags(p, false)
cgoLDFLAGS = append(cgoLDFLAGS, "-lobjc")
}
+ if buildMSan && p.ImportPath != "runtime/cgo" {
+ cgoCFLAGS = append([]string{"-fsanitize=memory"}, cgoCFLAGS...)
+ cgoLDFLAGS = append([]string{"-fsanitize=memory"}, cgoLDFLAGS...)
+ }
+
// Allows including _cgo_export.h from .[ch] files in the package.
cgoCPPFLAGS = append(cgoCPPFLAGS, "-I", obj)
if p.Standard && p.ImportPath == "runtime/cgo" {
cgoflags = append(cgoflags, "-import_runtime_cgo=false")
}
- if p.Standard && (p.ImportPath == "runtime/race" || p.ImportPath == "runtime/cgo") {
+ if p.Standard && (p.ImportPath == "runtime/race" || p.ImportPath == "runtime/msan" || p.ImportPath == "runtime/cgo") {
cgoflags = append(cgoflags, "-import_syscall=false")
}
}
}
- cgoLibGccFileOnce.Do(func() {
- cgoLibGccFile, cgoLibGccErr = b.libgcc(p)
- })
- if cgoLibGccFile == "" && cgoLibGccErr != nil {
- return nil, nil, err
- }
-
var staticLibs []string
if goos == "windows" {
- // libmingw32 and libmingwex might also use libgcc, so libgcc must come last,
- // and they also have some inter-dependencies, so must use linker groups.
+ // libmingw32 and libmingwex have some inter-dependencies,
+ // so must use linker groups.
staticLibs = []string{"-Wl,--start-group", "-lmingwex", "-lmingw32", "-Wl,--end-group"}
}
- if cgoLibGccFile != "" {
- staticLibs = append(staticLibs, cgoLibGccFile)
- }
cflags := stringList(cgoCPPFLAGS, cgoCFLAGS)
for _, cfile := range cfiles {
linkobj = append(linkobj, p.SysoFiles...)
dynobj := obj + "_cgo_.o"
- pie := goarch == "arm" && (goos == "linux" || goos == "android")
+ pie := (goarch == "arm" && goos == "linux") || goos == "android"
if pie { // we need to use -pie for Linux/ARM to get accurate imported sym
cgoLDFLAGS = append(cgoLDFLAGS, "-pie")
}
return heap.Pop(q).(*action)
}
-func raceInit() {
- if !buildRace {
+func instrumentInit() {
+ if !buildRace && !buildMSan {
return
}
+ if buildRace && buildMSan {
+ fmt.Fprintf(os.Stderr, "go %s: may not use -race and -msan simultaneously", flag.Args()[0])
+ os.Exit(2)
+ }
if goarch != "amd64" || goos != "linux" && goos != "freebsd" && goos != "darwin" && goos != "windows" {
- fmt.Fprintf(os.Stderr, "go %s: -race is only supported on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0])
+ fmt.Fprintf(os.Stderr, "go %s: -race and -msan are only supported on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0])
os.Exit(2)
}
if !buildContext.CgoEnabled {
fmt.Fprintf(os.Stderr, "go %s: -race requires cgo; enable cgo by setting CGO_ENABLED=1\n", flag.Args()[0])
os.Exit(2)
}
- buildGcflags = append(buildGcflags, "-race")
- buildLdflags = append(buildLdflags, "-race")
+ if buildRace {
+ buildGcflags = append(buildGcflags, "-race")
+ buildLdflags = append(buildLdflags, "-race")
+ } else {
+ buildGcflags = append(buildGcflags, "-msan")
+ buildLdflags = append(buildLdflags, "-msan")
+ }
if buildContext.InstallSuffix != "" {
buildContext.InstallSuffix += "_"
}
- buildContext.InstallSuffix += "race"
- buildContext.BuildTags = append(buildContext.BuildTags, "race")
+
+ if buildRace {
+ buildContext.InstallSuffix += "race"
+ buildContext.BuildTags = append(buildContext.BuildTags, "race")
+ } else {
+ buildContext.InstallSuffix += "msan"
+ buildContext.BuildTags = append(buildContext.BuildTags, "msan")
+ }
}
pkg string
commands map[string][]string
lineNum int // current line number.
+ env []string
}
// run runs the generators in the current file.
}
}
+ g.setEnv()
words := g.split(string(buf))
if len(words) == 0 {
g.errorf("no arguments to directive")
return bytes.HasPrefix(buf, []byte("//go:generate ")) || bytes.HasPrefix(buf, []byte("//go:generate\t"))
}
+// setEnv sets the extra environment variables used when executing a
+// single go:generate command.
+func (g *Generator) setEnv() {
+ g.env = []string{
+ "GOARCH=" + runtime.GOARCH,
+ "GOOS=" + runtime.GOOS,
+ "GOFILE=" + g.file,
+ "GOLINE=" + strconv.Itoa(g.lineNum),
+ "GOPACKAGE=" + g.pkg,
+ "DOLLAR=" + "$",
+ }
+}
+
// split breaks the line into words, evaluating quoted
// strings and evaluating environment variables.
// The initial //go:generate element is present in line.
// expandVar expands the $XXX invocation in word. It is called
// by os.Expand.
func (g *Generator) expandVar(word string) string {
- switch word {
- case "GOARCH":
- return buildContext.GOARCH
- case "GOOS":
- return buildContext.GOOS
- case "GOFILE":
- return g.file
- case "GOLINE":
- return fmt.Sprint(g.lineNum)
- case "GOPACKAGE":
- return g.pkg
- case "DOLLAR":
- return "$"
- default:
- return os.Getenv(word)
+ w := word + "="
+ for _, e := range g.env {
+ if strings.HasPrefix(e, w) {
+ return e[len(w):]
+ }
}
+ return os.Getenv(word)
}
// identLength returns the length of the identifier beginning the string.
cmd.Stderr = os.Stderr
// Run the command in the package directory.
cmd.Dir = g.dir
- env := []string{
- "GOARCH=" + runtime.GOARCH,
- "GOOS=" + runtime.GOOS,
- "GOFILE=" + g.file,
- "GOPACKAGE=" + g.pkg,
- }
- cmd.Env = mergeEnvLists(env, origEnv)
+ cmd.Env = mergeEnvLists(g.env, origEnv)
err := cmd.Run()
if err != nil {
g.errorf("running %q: %s", words[0], err)
pkg: "sys",
commands: make(map[string][]string),
}
+ g.setEnv()
g.setShorthand([]string{"-command", "yacc", "go", "tool", "yacc"})
for _, test := range splitTests {
// First with newlines.
// Disable any prompting for passwords by Git.
// Only has an effect for 2.3.0 or later, but avoiding
// the prompt in earlier versions is just too hard.
- // See golang.org/issue/9341.
- os.Setenv("GIT_TERMINAL_PROMPT", "0")
+ // If user has explicitly set GIT_TERMINAL_PROMPT=1, keep
+ // prompting.
+ // See golang.org/issue/9341 and golang.org/issue/12706.
+ if v := os.Getenv("GIT_TERMINAL_PROMPT"); v == "" {
+ os.Setenv("GIT_TERMINAL_PROMPT", "0")
+ }
// Phase 1. Download/update.
var stk importStack
// removed if it exists.
func (tg *testgoData) creatingTemp(path string) {
if filepath.IsAbs(path) && !strings.HasPrefix(path, tg.tempdir) {
- tg.t.Fatal("internal testsuite error: creatingTemp(%q) with absolute path not in temporary directory", path)
+ tg.t.Fatalf("internal testsuite error: creatingTemp(%q) with absolute path not in temporary directory", path)
}
// If we have changed the working directory, make sure we have
// an absolute path, because we are going to change directory
tg.wantExecutable("testdata/bin/go-cmd-test"+exeSuffix, "go install go-cmd-test did not write to testdata/bin/go-cmd-test")
}
+// Issue 12407
+func TestBuildOutputToDevNull(t *testing.T) {
+ if runtime.GOOS == "plan9" {
+ t.Skip("skipping because /dev/null is a regular file on plan9")
+ }
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
+ tg.run("build", "-o", os.DevNull, "go-cmd-test")
+}
+
func TestPackageMainTestImportsArchiveNotBinary(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
tg.run("test", "main_test")
}
+// Issue 12690
+func TestPackageNotStaleWithTrailingSlash(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ goroot := runtime.GOROOT()
+ tg.setenv("GOROOT", goroot+"/")
+ tg.wantNotStale("runtime", "with trailing slash in GOROOT, runtime listed as stale")
+ tg.wantNotStale("os", "with trailing slash in GOROOT, os listed as stale")
+ tg.wantNotStale("io", "with trailing slash in GOROOT, io listed as stale")
+}
+
// With $GOBIN set, binaries get installed to $GOBIN.
func TestInstallIntoGOBIN(t *testing.T) {
tg := testgo(t)
}
}
+func TestGoListDedupsPackages(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
+ tg.run("list", "xtestonly", "./testdata/src/xtestonly/...")
+ got := strings.TrimSpace(tg.getStdout())
+ const want = "xtestonly"
+ if got != want {
+ t.Errorf("got %q; want %q", got, want)
+ }
+}
+
// Issue 4096. Validate the output of unsuccessful go install foo/quxx.
func TestUnsuccessfulGoInstallShouldMentionMissingPackage(t *testing.T) {
tg := testgo(t)
tg.grepStdoutNot("no", "go generate -run yes ./testdata/generate/test4.go selected no")
}
+func TestGoGenerateEnv(t *testing.T) {
+ switch runtime.GOOS {
+ case "plan9", "windows":
+ t.Skipf("skipping because %s does not have the env command", runtime.GOOS)
+ }
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.parallel()
+ tg.tempFile("env.go", "package main\n\n//go:generate env")
+ tg.run("generate", tg.path("env.go"))
+ for _, v := range []string{"GOARCH", "GOOS", "GOFILE", "GOLINE", "GOPACKAGE", "DOLLAR"} {
+ tg.grepStdout("^"+v+"=", "go generate environment missing "+v)
+ }
+}
+
func TestGoGetCustomDomainWildcard(t *testing.T) {
testenv.MustHaveExternalNetwork(t)
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
tg.runFail("test", "testdep/p1")
if !strings.Contains(tg.stderr.String(), out) {
- t.Fatal("did not give full import stack:\n\n%s", tg.stderr.String())
+ t.Fatalf("did not give full import stack:\n\n%s", tg.stderr.String())
}
}
-buildmode=exe
Build the listed main packages and everything they import into
executables. Packages not named main are ignored.
+
+ -buildmode=pie
+ Build the listed main packages and everything they import into
+ position independent executables (PIE). Packages not named
+ main are ignored.
`,
}
var raceExclude = map[string]bool{
"runtime/race": true,
+ "runtime/msan": true,
"runtime/cgo": true,
"cmd/cgo": true,
"syscall": true,
var cgoSyscallExclude = map[string]bool{
"runtime/cgo": true,
"runtime/race": true,
+ "runtime/msan": true,
}
// load populates p using information from bp, err, which should
importPaths = append(importPaths, "syscall")
}
- // Currently build mode c-shared, or -linkshared, forces
+ // Currently build modes c-shared, pie, and -linkshared force
// external linking mode, and external linking mode forces an
// import of runtime/cgo.
- if p.Name == "main" && !p.Goroot && (buildBuildmode == "c-shared" || buildLinkshared) {
+ if p.Name == "main" && !p.Goroot && (buildBuildmode == "c-shared" || buildBuildmode == "pie" || buildLinkshared) {
importPaths = append(importPaths, "runtime/cgo")
}
- // Everything depends on runtime, except runtime and unsafe.
- if !p.Standard || (p.ImportPath != "runtime" && p.ImportPath != "unsafe") {
+ // Everything depends on runtime, except runtime, its internal
+ // subpackages, and unsafe.
+ if !p.Standard || (p.ImportPath != "runtime" && !strings.HasPrefix(p.ImportPath, "runtime/internal/") && p.ImportPath != "unsafe") {
importPaths = append(importPaths, "runtime")
// When race detection enabled everything depends on runtime/race.
// Exclude certain packages to avoid circular dependencies.
if buildRace && (!p.Standard || !raceExclude[p.ImportPath]) {
importPaths = append(importPaths, "runtime/race")
}
+ // MSan uses runtime/msan.
+ if buildMSan && (!p.Standard || !raceExclude[p.ImportPath]) {
+ importPaths = append(importPaths, "runtime/msan")
+ }
// On ARM with GOARM=5, everything depends on math for the link.
if p.Name == "main" && goarch == "arm" {
importPaths = append(importPaths, "math")
}
args = importPaths(args)
- var pkgs []*Package
- var stk importStack
- var set = make(map[string]bool)
+ var (
+ pkgs []*Package
+ stk importStack
+ seenArg = make(map[string]bool)
+ seenPkg = make(map[*Package]bool)
+ )
for _, arg := range args {
- if !set[arg] {
- pkgs = append(pkgs, loadPackage(arg, &stk))
- set[arg] = true
+ if seenArg[arg] {
+ continue
}
+ seenArg[arg] = true
+ pkg := loadPackage(arg, &stk)
+ if seenPkg[pkg] {
+ continue
+ }
+ seenPkg[pkg] = true
+ pkgs = append(pkgs, pkg)
}
computeStale(pkgs...)
}
func runRun(cmd *Command, args []string) {
- raceInit()
+ instrumentInit()
buildModeInit()
var b builder
b.init()
findExecCmd() // initialize cached result
- raceInit()
+ instrumentInit()
buildModeInit()
pkgs := packagesForBuild(pkgArgs)
if len(pkgs) == 0 {
if deps["C"] {
delete(deps, "C")
deps["runtime/cgo"] = true
- if goos == runtime.GOOS && goarch == runtime.GOARCH && !buildRace {
+ if goos == runtime.GOOS && goarch == runtime.GOARCH && !buildRace && !buildMSan {
deps["cmd/cgo"] = true
}
}
if buildRace {
extraOpts = "-race "
}
+ if buildMSan {
+ extraOpts = "-msan "
+ }
fmt.Fprintf(os.Stderr, "installing these packages with 'go test %s-i%s' will speed future tests.\n\n", extraOpts, args)
}
var c1, c2, c3 byte
for {
c1, c2, c3 = c2, c3, r.readByte()
- if c3 == 0 { // NUL or EOF, either is bad
+ // The new export format can contain 0 bytes.
+ // Don't consider them errors, only look for r.err != nil.
+ if r.err != nil {
return errCorruptObject
}
if c1 == '\n' && c2 == '!' && c3 == '\n' {
return C_NONE
case obj.TYPE_REG:
+ ctxt.Instoffset = 0
if REG_R0 <= a.Reg && a.Reg <= REG_R15 {
return C_REG
}
case obj.TYPE_MEM:
switch a.Name {
case obj.NAME_EXTERN,
+ obj.NAME_GOTREF,
obj.NAME_STATIC:
if a.Sym == nil || a.Sym.Name == "" {
fmt.Printf("null sym external\n")
return C_LCON
case obj.NAME_EXTERN,
+ obj.NAME_GOTREF,
obj.NAME_STATIC:
s := a.Sym
if s == nil {
aclass(ctxt, &p.To)
if ctxt.Instoffset != 0 {
- ctxt.Diag("%v: doesn't support BL offset(REG) where offset != 0", p)
+ ctxt.Diag("%v: doesn't support BL offset(REG) with non-zero offset %d", p, ctxt.Instoffset)
}
o1 = oprrr(ctxt, ABL, int(p.Scond))
o1 |= (uint32(p.To.Reg) & 15) << 0
rel.Add = p.To.Offset
if ctxt.Flag_shared != 0 {
- rel.Type = obj.R_PCREL
+ if p.To.Name == obj.NAME_GOTREF {
+ rel.Type = obj.R_GOTPCREL
+ } else {
+ rel.Type = obj.R_PCREL
+ }
rel.Add += ctxt.Pc - p.Rel.Pc - 8
} else {
rel.Type = obj.R_ADDR
p.From.Offset = 0
}
}
+
+ if ctxt.Flag_dynlink {
+ rewriteToUseGot(ctxt, p)
+ }
+}
+
+// Rewrite p, if necessary, to access global data via the global offset table.
+func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog) {
+ if p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO {
+ // ADUFFxxx $offset
+ // becomes
+ // MOVW runtime.duffxxx@GOT, R9
+ // ADD $offset, R9
+ // CALL (R9)
+ var sym *obj.LSym
+ if p.As == obj.ADUFFZERO {
+ sym = obj.Linklookup(ctxt, "runtime.duffzero", 0)
+ } else {
+ sym = obj.Linklookup(ctxt, "runtime.duffcopy", 0)
+ }
+ offset := p.To.Offset
+ p.As = AMOVW
+ p.From.Type = obj.TYPE_MEM
+ p.From.Name = obj.NAME_GOTREF
+ p.From.Sym = sym
+ p.To.Type = obj.TYPE_REG
+ p.To.Reg = REG_R9
+ p.To.Name = obj.NAME_NONE
+ p.To.Offset = 0
+ p.To.Sym = nil
+ p1 := obj.Appendp(ctxt, p)
+ p1.As = AADD
+ p1.From.Type = obj.TYPE_CONST
+ p1.From.Offset = offset
+ p1.To.Type = obj.TYPE_REG
+ p1.To.Reg = REG_R9
+ p2 := obj.Appendp(ctxt, p1)
+ p2.As = obj.ACALL
+ p2.To.Type = obj.TYPE_MEM
+ p2.To.Reg = REG_R9
+ return
+ }
+
+ // We only care about global data: NAME_EXTERN means a global
+ // symbol in the Go sense, and p.Sym.Local is true for a few
+ // internally defined symbols.
+ if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local {
+ // MOVW $sym, Rx becomes MOVW sym@GOT, Rx
+ // MOVW $sym+<off>, Rx becomes MOVW sym@GOT, Rx; ADD <off>, Rx
+ if p.As != AMOVW {
+ ctxt.Diag("do not know how to handle TYPE_ADDR in %v with -dynlink", p)
+ }
+ if p.To.Type != obj.TYPE_REG {
+ ctxt.Diag("do not know how to handle LEAQ-type insn to non-register in %v with -dynlink", p)
+ }
+ p.From.Type = obj.TYPE_MEM
+ p.From.Name = obj.NAME_GOTREF
+ if p.From.Offset != 0 {
+ q := obj.Appendp(ctxt, p)
+ q.As = AADD
+ q.From.Type = obj.TYPE_CONST
+ q.From.Offset = p.From.Offset
+ q.To = p.To
+ p.From.Offset = 0
+ }
+ }
+ if p.From3 != nil && p.From3.Name == obj.NAME_EXTERN {
+ ctxt.Diag("don't know how to handle %v with -dynlink", p)
+ }
+ var source *obj.Addr
+ // MOVx sym, Ry becomes MOVW sym@GOT, R9; MOVx (R9), Ry
+ // MOVx Ry, sym becomes MOVW sym@GOT, R9; MOVx Ry, (R9)
+ // An addition may be inserted between the two MOVs if there is an offset.
+ if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local {
+ if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local {
+ ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p)
+ }
+ source = &p.From
+ } else if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local {
+ source = &p.To
+ } else {
+ return
+ }
+ if p.As == obj.ATEXT || p.As == obj.AFUNCDATA || p.As == obj.ACALL || p.As == obj.ARET || p.As == obj.AJMP {
+ return
+ }
+ if source.Sym.Type == obj.STLSBSS {
+ return
+ }
+ if source.Type != obj.TYPE_MEM {
+ ctxt.Diag("don't know how to handle %v with -dynlink", p)
+ }
+ p1 := obj.Appendp(ctxt, p)
+ p2 := obj.Appendp(ctxt, p1)
+
+ p1.As = AMOVW
+ p1.From.Type = obj.TYPE_MEM
+ p1.From.Sym = source.Sym
+ p1.From.Name = obj.NAME_GOTREF
+ p1.To.Type = obj.TYPE_REG
+ p1.To.Reg = REG_R9
+
+ p2.As = p.As
+ p2.From = p.From
+ p2.To = p.To
+ if p.From.Name == obj.NAME_EXTERN {
+ p2.From.Reg = REG_R9
+ p2.From.Name = obj.NAME_NONE
+ p2.From.Sym = nil
+ } else if p.To.Name == obj.NAME_EXTERN {
+ p2.To.Reg = REG_R9
+ p2.To.Name = obj.NAME_NONE
+ p2.To.Sym = nil
+ } else {
+ return
+ }
+ obj.Nopout(p)
}
// Prog.mark
C_LOREG
C_ADDR // TODO(aram): explain difference from C_VCONADDR
+
+ // The GOT slot for a symbol in -dynlink mode.
+ C_GOTADDR
+
+ // TLS "var" in local exec mode: will become a constant offset from
+ // thread local base that is ultimately chosen by the program linker.
+ C_TLS_LE
+
+ // TLS "var" in initial exec mode: will become a memory address (chosen
+ // by the program linker) that the dynamic linker will fill with the
+ // offset from the thread local base.
+ C_TLS_IE
+
C_ROFF // register offset (including register extended)
C_GOK
"UOREG64K",
"LOREG",
"ADDR",
+ "GOTADDR",
+ "TLS_LE",
+ "TLS_IE",
"ROFF",
"GOK",
"TEXTSIZE",
{AMOVH, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0},
{AMOVW, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0},
{AMOVD, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0},
+ {AMOVD, C_GOTADDR, C_NONE, C_REG, 71, 8, 0, 0, 0},
+ {AMOVD, C_TLS_LE, C_NONE, C_REG, 69, 4, 0, 0, 0},
+ {AMOVD, C_TLS_IE, C_NONE, C_REG, 70, 8, 0, 0, 0},
{AMUL, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0},
{AMUL, C_REG, C_NONE, C_REG, 15, 4, 0, 0, 0},
{AMADD, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0},
buildop(ctxt)
}
- bflag := 0
- c := int32(0)
- p.Pc = int64(c)
+ bflag := 1
+ c := int64(0)
+ p.Pc = c
var m int
var o *Optab
for p = p.Link; p != nil; p = p.Link {
if p.As == ADWORD && (c&7) != 0 {
c += 4
}
- p.Pc = int64(c)
+ p.Pc = c
o = oplook(ctxt, p)
m = int(o.size)
if m == 0 {
if p.As == AB || p.As == obj.ARET || p.As == AERET { /* TODO: other unconditional operations */
checkpool(ctxt, p, 0)
}
- c += int32(m)
+ c += int64(m)
if ctxt.Blitrl != nil {
checkpool(ctxt, p, 1)
}
}
- cursym.Size = int64(c)
+ cursym.Size = c
/*
* if any procedure is large enough to
* around jmps to fix. this is rare.
*/
for bflag != 0 {
+ if ctxt.Debugvlog != 0 {
+ fmt.Fprintf(ctxt.Bso, "%5.2f span1\n", obj.Cputime())
+ }
bflag = 0
c = 0
- for p = cursym.Text; p != nil; p = p.Link {
+ for p = cursym.Text.Link; p != nil; p = p.Link {
if p.As == ADWORD && (c&7) != 0 {
c += 4
}
- p.Pc = int64(c)
+ p.Pc = c
o = oplook(ctxt, p)
- /* very large branches
- if(o->type == 6 && p->cond) {
- otxt = p->cond->pc - c;
- if(otxt < 0)
- otxt = -otxt;
- if(otxt >= (1L<<17) - 10) {
- q = ctxt->arch->prg();
- q->link = p->link;
- p->link = q;
- q->as = AB;
- q->to.type = obj.TYPE_BRANCH;
- q->cond = p->cond;
- p->cond = q;
- q = ctxt->arch->prg();
- q->link = p->link;
- p->link = q;
- q->as = AB;
- q->to.type = obj.TYPE_BRANCH;
- q->cond = q->link->link;
- bflag = 1;
+ /* very large branches */
+ if o.type_ == 7 && p.Pcond != nil {
+ otxt := p.Pcond.Pc - c
+ if otxt <= -(1<<18)+10 || otxt >= (1<<18)-10 {
+ q := ctxt.NewProg()
+ q.Link = p.Link
+ p.Link = q
+ q.As = AB
+ q.To.Type = obj.TYPE_BRANCH
+ q.Pcond = p.Pcond
+ p.Pcond = q
+ q = ctxt.NewProg()
+ q.Link = p.Link
+ p.Link = q
+ q.As = AB
+ q.To.Type = obj.TYPE_BRANCH
+ q.Pcond = q.Link.Link
+ bflag = 1
}
}
- */
m = int(o.size)
if m == 0 {
continue
}
- c += int32(m)
+ c += int64(m)
}
}
c += -c & (FuncAlign - 1)
- cursym.Size = int64(c)
+ cursym.Size = c
/*
* lay out the code, emitting code and data relocations.
}
ctxt.Instoffset = a.Offset
if a.Sym != nil { // use relocation
+ if a.Sym.Type == obj.STLSBSS {
+ if ctxt.Flag_shared != 0 {
+ return C_TLS_IE
+ } else {
+ return C_TLS_LE
+ }
+ }
return C_ADDR
}
return C_LEXT
+ case obj.NAME_GOTREF:
+ return C_GOTADDR
+
case obj.NAME_AUTO:
ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset
return autoclass(ctxt.Instoffset)
case obj.NAME_EXTERN,
obj.NAME_STATIC:
- s := a.Sym
- if s == nil {
+ if a.Sym == nil {
break
}
+ if a.Sym.Type == obj.STLSBSS {
+ ctxt.Diag("taking address of TLS variable is not supported")
+ }
ctxt.Instoffset = a.Offset
return C_VCONADDR
rel.Add = p.From.Offset
rel.Type = obj.R_ADDRARM64
+ case 69: /* LE model movd $tlsvar, reg -> movz reg, 0 + reloc */
+ o1 = opirr(ctxt, AMOVZ)
+ o1 |= uint32(p.To.Reg & 31)
+ rel := obj.Addrel(ctxt.Cursym)
+ rel.Off = int32(ctxt.Pc)
+ rel.Siz = 4
+ rel.Sym = p.From.Sym
+ rel.Type = obj.R_ARM64_TLS_LE
+ if p.From.Offset != 0 {
+ ctxt.Diag("invalid offset on MOVW $tlsvar")
+ }
+
+ case 70: /* IE model movd $tlsvar, reg -> adrp REGTMP, 0; ldr reg, [REGTMP, #0] + relocs */
+ o1 = ADR(1, 0, REGTMP)
+ o2 = olsr12u(ctxt, int32(opldr12(ctxt, AMOVD)), 0, REGTMP, int(p.To.Reg))
+ rel := obj.Addrel(ctxt.Cursym)
+ rel.Off = int32(ctxt.Pc)
+ rel.Siz = 8
+ rel.Sym = p.From.Sym
+ rel.Add = 0
+ rel.Type = obj.R_ARM64_TLS_IE
+ if p.From.Offset != 0 {
+ ctxt.Diag("invalid offset on MOVW $tlsvar")
+ }
+
+ case 71: /* movd sym@GOT, reg -> adrp REGTMP, #0; ldr reg, [REGTMP, #0] + relocs */
+ o1 = ADR(1, 0, REGTMP)
+ o2 = olsr12u(ctxt, int32(opldr12(ctxt, AMOVD)), 0, REGTMP, int(p.To.Reg))
+ rel := obj.Addrel(ctxt.Cursym)
+ rel.Off = int32(ctxt.Pc)
+ rel.Siz = 8
+ rel.Sym = p.From.Sym
+ rel.Add = 0
+ rel.Type = obj.R_ARM64_GOTPCREL
+
// This is supposed to be something that stops execution.
// It's not supposed to be reached, ever, but if it is, we'd
// like to be able to tell how we got there. Assemble as
s.Size = 4
p.From.Type = obj.TYPE_MEM
p.From.Sym = s
+ p.From.Sym.Local = true
p.From.Name = obj.NAME_EXTERN
p.From.Offset = 0
}
s.Size = 8
p.From.Type = obj.TYPE_MEM
p.From.Sym = s
+ p.From.Sym.Local = true
p.From.Name = obj.NAME_EXTERN
p.From.Offset = 0
}
break
}
+
+ if ctxt.Flag_dynlink {
+ rewriteToUseGot(ctxt, p)
+ }
+}
+
+// Rewrite p, if necessary, to access global data via the global offset table.
+func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog) {
+ if p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO {
+ // ADUFFxxx $offset
+ // becomes
+ // MOVD runtime.duffxxx@GOT, REGTMP
+ // ADD $offset, REGTMP
+ // CALL REGTMP
+ var sym *obj.LSym
+ if p.As == obj.ADUFFZERO {
+ sym = obj.Linklookup(ctxt, "runtime.duffzero", 0)
+ } else {
+ sym = obj.Linklookup(ctxt, "runtime.duffcopy", 0)
+ }
+ offset := p.To.Offset
+ p.As = AMOVD
+ p.From.Type = obj.TYPE_MEM
+ p.From.Name = obj.NAME_GOTREF
+ p.From.Sym = sym
+ p.To.Type = obj.TYPE_REG
+ p.To.Reg = REGTMP
+ p.To.Name = obj.NAME_NONE
+ p.To.Offset = 0
+ p.To.Sym = nil
+ p1 := obj.Appendp(ctxt, p)
+ p1.As = AADD
+ p1.From.Type = obj.TYPE_CONST
+ p1.From.Offset = offset
+ p1.To.Type = obj.TYPE_REG
+ p1.To.Reg = REGTMP
+ p2 := obj.Appendp(ctxt, p1)
+ p2.As = obj.ACALL
+ p2.To.Type = obj.TYPE_REG
+ p2.To.Reg = REGTMP
+ }
+
+ // We only care about global data: NAME_EXTERN means a global
+ // symbol in the Go sense, and p.Sym.Local is true for a few
+ // internally defined symbols.
+ if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local {
+ // MOVD $sym, Rx becomes MOVD sym@GOT, Rx
+ // MOVD $sym+<off>, Rx becomes MOVD sym@GOT, Rx; ADD <off>, Rx
+ if p.As != AMOVD {
+ ctxt.Diag("do not know how to handle TYPE_ADDR in %v with -dynlink", p)
+ }
+ if p.To.Type != obj.TYPE_REG {
+ ctxt.Diag("do not know how to handle LEAQ-type insn to non-register in %v with -dynlink", p)
+ }
+ p.From.Type = obj.TYPE_MEM
+ p.From.Name = obj.NAME_GOTREF
+ if p.From.Offset != 0 {
+ q := obj.Appendp(ctxt, p)
+ q.As = AADD
+ q.From.Type = obj.TYPE_CONST
+ q.From.Offset = p.From.Offset
+ q.To = p.To
+ p.From.Offset = 0
+ }
+ }
+ if p.From3 != nil && p.From3.Name == obj.NAME_EXTERN {
+ ctxt.Diag("don't know how to handle %v with -dynlink", p)
+ }
+ var source *obj.Addr
+ // MOVx sym, Ry becomes MOVD sym@GOT, REGTMP; MOVx (REGTMP), Ry
+ // MOVx Ry, sym becomes MOVD sym@GOT, REGTMP; MOVD Ry, (REGTMP)
+ // An addition may be inserted between the two MOVs if there is an offset.
+ if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local {
+ if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local {
+ ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p)
+ }
+ source = &p.From
+ } else if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local {
+ source = &p.To
+ } else {
+ return
+ }
+ if p.As == obj.ATEXT || p.As == obj.AFUNCDATA || p.As == obj.ACALL || p.As == obj.ARET || p.As == obj.AJMP {
+ return
+ }
+ if source.Sym.Type == obj.STLSBSS {
+ return
+ }
+ if source.Type != obj.TYPE_MEM {
+ ctxt.Diag("don't know how to handle %v with -dynlink", p)
+ }
+ p1 := obj.Appendp(ctxt, p)
+ p2 := obj.Appendp(ctxt, p1)
+ p1.As = AMOVD
+ p1.From.Type = obj.TYPE_MEM
+ p1.From.Sym = source.Sym
+ p1.From.Name = obj.NAME_GOTREF
+ p1.To.Type = obj.TYPE_REG
+ p1.To.Reg = REGTMP
+
+ p2.As = p.As
+ p2.From = p.From
+ p2.To = p.To
+ if p.From.Name == obj.NAME_EXTERN {
+ p2.From.Reg = REGTMP
+ p2.From.Name = obj.NAME_NONE
+ p2.From.Sym = nil
+ } else if p.To.Name == obj.NAME_EXTERN {
+ p2.To.Reg = REGTMP
+ p2.To.Name = obj.NAME_NONE
+ p2.To.Sym = nil
+ } else {
+ return
+ }
+ obj.Nopout(p)
}
func follow(ctxt *obj.Link, s *obj.LSym) {
// Reloc.type
const (
R_ADDR = 1 + iota
+ // R_ADDRPOWER relocates a pair of "D-form" instructions (instructions with 16-bit
+ // immediates in the low half of the instruction word), usually addis followed by
+ // another add or a load, inserting the "high adjusted" 16 bits of the address of
+ // the referenced symbol into the immediate field of the first instruction and the
+ // low 16 bits into that of the second instruction.
R_ADDRPOWER
+ // R_ADDRARM64 relocates an adrp, add pair to compute the address of the
+ // referenced symbol.
R_ADDRARM64
+ // R_ADDRMIPS (only used on mips64) resolves to a 32-bit external address,
+ // by loading the address into a register with two instructions (lui, ori).
+ R_ADDRMIPS
R_SIZE
R_CALL
R_CALLARM
R_CALLARM64
R_CALLIND
R_CALLPOWER
+ // R_CALLMIPS (only used on mips64) resolves to non-PC-relative target address
+ // of a CALL (JAL) instruction, by encoding the address into the instruction.
+ R_CALLMIPS
R_CONST
R_PCREL
// R_TLS_LE, used on 386, amd64, and ARM, resolves to the offset of the
R_USEFIELD
R_POWER_TOC
R_GOTPCREL
+ // R_JMPMIPS (only used on mips64) resolves to non-PC-relative target address
+ // of a JMP instruction, by encoding the address into the instruction.
+ // The stack nosplit check ignores this since it is not a function call.
+ R_JMPMIPS
+
+ // Platform dependent relocations. Architectures with fixed width instructions
+ // have the inherent issue that a 32-bit (or 64-bit!) displacement cannot be
+ // stuffed into a 32-bit instruction, so an address needs to be spread across
+ // several instructions, and in turn this requires a sequence of relocations, each
+ // updating a part of an instruction. This leads to relocation codes that are
+ // inherently processor specific.
+
+ // Arm64.
+
+ // Set a MOV[NZ] immediate field to bits [15:0] of the offset from the thread
+ // local base to the thread local variable defined by the referenced (thread
+ // local) symbol. Error if the offset does not fit into 16 bits.
+ R_ARM64_TLS_LE
+
+ // Relocates an ADRP; LD64 instruction sequence to load the offset between
+ // the thread local base and the thread local variable defined by the
+ // referenced (thread local) symbol from the GOT.
+ R_ARM64_TLS_IE
+
+ // R_ARM64_GOTPCREL relocates an adrp, ld64 pair to compute the address of the GOT
+ // slot of the referenced symbol.
+ R_ARM64_GOTPCREL
+
+ // PPC64.
+
+ // R_POWER_TLS_LE is used to implement the "local exec" model for tls
+ // access. It resolves to the offset of the thread-local symbol from the
+ // thread pointer (R13) and inserts this value into the low 16 bits of an
+ // instruction word.
+ R_POWER_TLS_LE
+
+ // R_POWER_TLS_IE is used to implement the "initial exec" model for tls access. It
+ // relocates a D-form, DS-form instruction sequence like R_ADDRPOWER_DS. It
+ // inserts to the offset of GOT slot for the thread-local symbol from the TOC (the
+ // GOT slot is filled by the dynamic linker with the offset of the thread-local
+ // symbol from the thread pointer (R13)).
+ R_POWER_TLS_IE
+
+ // R_POWER_TLS marks an X-form instruction such as "MOVD 0(R13)(R31*1), g" as
+ // accessing a particular thread-local symbol. It does not affect code generation
+ // but is used by the system linker when relaxing "initial exec" model code to
+ // "local exec" model code.
+ R_POWER_TLS
+
+ // R_ADDRPOWER_DS is similar to R_ADDRPOWER above, but assumes the second
+ // instruction is a "DS-form" instruction, which has an immediate field occupying
+ // bits [15:2] of the instruction word. Bits [15:2] of the address of the
+ // relocated symbol are inserted into this field; it is an error if the last two
+ // bits of the address are not 0.
+ R_ADDRPOWER_DS
+
+ // R_ADDRPOWER_PCREL relocates a D-form, DS-form instruction sequence like
+ // R_ADDRPOWER_DS but inserts the offset of the GOT slot for the referenced symbol
+ // from the TOC rather than the symbol's address.
+ R_ADDRPOWER_GOT
+
+ // R_ADDRPOWER_PCREL relocates two D-form instructions like R_ADDRPOWER, but
+ // inserts the displacement from the place being relocated to the address of the
+ // the relocated symbol instead of just its address.
+ R_ADDRPOWER_PCREL
+
+ // R_ADDRPOWER_TOCREL relocates two D-form instructions like R_ADDRPOWER, but
+ // inserts the offset from the TOC to the address of the the relocated symbol
+ // rather than the symbol's address.
+ R_ADDRPOWER_TOCREL
+
+ // R_ADDRPOWER_TOCREL relocates a D-form, DS-form instruction sequence like
+ // R_ADDRPOWER_DS but inserts the offset from the TOC to the address of the the
+ // relocated symbol rather than the symbol's address.
+ R_ADDRPOWER_TOCREL_DS
)
type Auto struct {
switch ctxt.Arch.Thechar {
case '6', '8':
return 0
+ case '9':
+ // PIC code on ppc64le requires 32 bytes of stack, and it's easier to
+ // just use that much stack always on ppc64x.
+ return int64(4 * ctxt.Arch.Ptrsize)
default:
return int64(ctxt.Arch.Ptrsize)
}
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package ppc64
+package mips
import "cmd/internal/obj"
-//go:generate go run ../stringer.go -i $GOFILE -o anames.go -p ppc64
+//go:generate go run ../stringer.go -i $GOFILE -o anames.go -p mips
/*
- * powerpc 64
+ * mips 64
*/
const (
NSNAME = 8
)
const (
- REG_R0 = obj.RBasePPC64 + iota
+ REG_R0 = obj.RBaseMIPS64 + iota
REG_R1
REG_R2
REG_R3
REG_F30
REG_F31
- REG_CR0
- REG_CR1
- REG_CR2
- REG_CR3
- REG_CR4
- REG_CR5
- REG_CR6
- REG_CR7
+ REG_HI
+ REG_LO
- REG_MSR
- REG_FPSCR
- REG_CR
+ // co-processor 0 control registers
+ REG_M0 = obj.RBaseMIPS64 + 1024 + iota
+ REG_M1
+ REG_M2
+ REG_M3
+ REG_M4
+ REG_M5
+ REG_M6
+ REG_M7
+ REG_M8
+ REG_M9
+ REG_M10
+ REG_M11
+ REG_M12
+ REG_M13
+ REG_M14
+ REG_M15
+ REG_M16
+ REG_M17
+ REG_M18
+ REG_M19
+ REG_M20
+ REG_M21
+ REG_M22
+ REG_M23
+ REG_M24
+ REG_M25
+ REG_M26
+ REG_M27
+ REG_M28
+ REG_M29
+ REG_M30
+ REG_M31
- REG_SPECIAL = REG_CR0
+ // FPU control registers
+ REG_FCR0 = obj.RBaseMIPS64 + 2048 + iota
+ REG_FCR1
+ REG_FCR2
+ REG_FCR3
+ REG_FCR4
+ REG_FCR5
+ REG_FCR6
+ REG_FCR7
+ REG_FCR8
+ REG_FCR9
+ REG_FCR10
+ REG_FCR11
+ REG_FCR12
+ REG_FCR13
+ REG_FCR14
+ REG_FCR15
+ REG_FCR16
+ REG_FCR17
+ REG_FCR18
+ REG_FCR19
+ REG_FCR20
+ REG_FCR21
+ REG_FCR22
+ REG_FCR23
+ REG_FCR24
+ REG_FCR25
+ REG_FCR26
+ REG_FCR27
+ REG_FCR28
+ REG_FCR29
+ REG_FCR30
+ REG_FCR31
- REG_SPR0 = obj.RBasePPC64 + 1024 // first of 1024 registers
- REG_DCR0 = obj.RBasePPC64 + 2048 // first of 1024 registers
-
- REG_XER = REG_SPR0 + 1
- REG_LR = REG_SPR0 + 8
- REG_CTR = REG_SPR0 + 9
+ REG_SPECIAL = REG_M0
REGZERO = REG_R0 /* set to zero */
- REGSP = REG_R1
- REGSB = REG_R2
- REGRET = REG_R3
+ REGSP = REG_R29
+ REGSB = REG_R30
+ REGLINK = REG_R31
+ REGRET = REG_R1
REGARG = -1 /* -1 disables passing the first argument in register */
- REGRT1 = REG_R3 /* reserved for runtime, duffzero and duffcopy */
- REGRT2 = REG_R4 /* reserved for runtime, duffcopy */
- REGMIN = REG_R7 /* register variables allocated from here to REGMAX */
- REGCTXT = REG_R11 /* context for closures */
- REGTLS = REG_R13 /* C ABI TLS base pointer */
- REGMAX = REG_R27
- REGEXT = REG_R30 /* external registers allocated from here down */
+ REGRT1 = REG_R1 /* reserved for runtime, duffzero and duffcopy */
+ REGRT2 = REG_R2 /* reserved for runtime, duffcopy */
+ REGCTXT = REG_R22 /* context for closures */
REGG = REG_R30 /* G */
- REGTMP = REG_R31 /* used by the linker */
+ REGTMP = REG_R28 /* used by the linker */
FREGRET = REG_F0
- FREGMIN = REG_F17 /* first register variable */
- FREGMAX = REG_F26 /* last register variable for 9g only */
- FREGEXT = REG_F26 /* first external register */
- FREGCVI = REG_F27 /* floating conversion constant */
- FREGZERO = REG_F28 /* both float and double */
- FREGHALF = REG_F29 /* double */
- FREGONE = REG_F30 /* double */
- FREGTWO = REG_F31 /* double */
+ FREGZERO = REG_F24 /* both float and double */
+ FREGHALF = REG_F26 /* double */
+ FREGONE = REG_F28 /* double */
+ FREGTWO = REG_F30 /* double */
)
-/*
- * GENERAL:
- *
- * compiler allocates R3 up as temps
- * compiler allocates register variables R7-R27
- * compiler allocates external registers R30 down
- *
- * compiler allocates register variables F17-F26
- * compiler allocates external registers F26 down
- */
const (
- BIG = 32768 - 8
+ BIG = 32766
)
const (
/* mark flags */
- LABEL = 1 << 0
- LEAF = 1 << 1
- FLOAT = 1 << 2
- BRANCH = 1 << 3
- LOAD = 1 << 4
- FCMP = 1 << 5
- SYNC = 1 << 6
- LIST = 1 << 7
- FOLL = 1 << 8
- NOSCHED = 1 << 9
+ FOLL = 1 << 0
+ LABEL = 1 << 1
+ LEAF = 1 << 2
+ SYNC = 1 << 3
+ BRANCH = 1 << 4
+ LOAD = 1 << 5
+ FCMP = 1 << 6
+ NOSCHED = 1 << 7
+
+ NSCHED = 20
)
const (
C_NONE = iota
C_REG
C_FREG
- C_CREG
- C_SPR /* special processor register */
+ C_FCREG
+ C_MREG /* special processor register */
+ C_HI
+ C_LO
C_ZCON
- C_SCON /* 16 bit signed */
- C_UCON /* 32 bit signed, low 16 bits 0 */
+ C_SCON /* 16 bit signed */
+ C_UCON /* 32 bit signed, low 16 bits 0 */
+ C_ADD0CON
+ C_AND0CON
C_ADDCON /* -0x8000 <= v < 0 */
C_ANDCON /* 0 < v <= 0xFFFF */
C_LCON /* other 32 */
C_ZOREG
C_SOREG
C_LOREG
- C_FPSCR
- C_MSR
- C_XER
- C_LR
- C_CTR
- C_ANY
C_GOK
C_ADDR
C_TEXTSIZE
)
const (
- AADD = obj.ABasePPC64 + obj.A_ARCHSPECIFIC + iota
- AADDCC
- AADDV
- AADDVCC
- AADDC
- AADDCCC
- AADDCV
- AADDCVCC
- AADDME
- AADDMECC
- AADDMEVCC
- AADDMEV
- AADDE
- AADDECC
- AADDEVCC
- AADDEV
- AADDZE
- AADDZECC
- AADDZEVCC
- AADDZEV
+ AABSD = obj.ABaseMIPS64 + obj.A_ARCHSPECIFIC + iota
+ AABSF
+ AABSW
+ AADD
+ AADDD
+ AADDF
+ AADDU
+ AADDW
AAND
- AANDCC
- AANDN
- AANDNCC
- ABC
- ABCL
ABEQ
- ABGE
- ABGT
- ABLE
- ABLT
+ ABFPF
+ ABFPT
+ ABGEZ
+ ABGEZAL
+ ABGTZ
+ ABLEZ
+ ABLTZ
+ ABLTZAL
ABNE
- ABVC
- ABVS
- ACMP
- ACMPU
- ACNTLZW
- ACNTLZWCC
- ACRAND
- ACRANDN
- ACREQV
- ACRNAND
- ACRNOR
- ACROR
- ACRORN
- ACRXOR
+ ABREAK
+ ACMPEQD
+ ACMPEQF
+ ACMPGED
+ ACMPGEF
+ ACMPGTD
+ ACMPGTF
+ ADIV
+ ADIVD
+ ADIVF
+ ADIVU
ADIVW
- ADIVWCC
- ADIVWVCC
- ADIVWV
- ADIVWU
- ADIVWUCC
- ADIVWUVCC
- ADIVWUV
- AEQV
- AEQVCC
- AEXTSB
- AEXTSBCC
- AEXTSH
- AEXTSHCC
- AFABS
- AFABSCC
- AFADD
- AFADDCC
- AFADDS
- AFADDSCC
- AFCMPO
- AFCMPU
- AFCTIW
- AFCTIWCC
- AFCTIWZ
- AFCTIWZCC
- AFDIV
- AFDIVCC
- AFDIVS
- AFDIVSCC
- AFMADD
- AFMADDCC
- AFMADDS
- AFMADDSCC
- AFMOVD
- AFMOVDCC
- AFMOVDU
- AFMOVS
- AFMOVSU
- AFMSUB
- AFMSUBCC
- AFMSUBS
- AFMSUBSCC
- AFMUL
- AFMULCC
- AFMULS
- AFMULSCC
- AFNABS
- AFNABSCC
- AFNEG
- AFNEGCC
- AFNMADD
- AFNMADDCC
- AFNMADDS
- AFNMADDSCC
- AFNMSUB
- AFNMSUBCC
- AFNMSUBS
- AFNMSUBSCC
- AFRSP
- AFRSPCC
- AFSUB
- AFSUBCC
- AFSUBS
- AFSUBSCC
- AMOVMW
- ALSW
- ALWAR
- AMOVWBR
+ AGOK
AMOVB
AMOVBU
- AMOVBZ
- AMOVBZU
+ AMOVD
+ AMOVDF
+ AMOVDW
+ AMOVF
+ AMOVFD
+ AMOVFW
AMOVH
- AMOVHBR
AMOVHU
- AMOVHZ
- AMOVHZU
AMOVW
- AMOVWU
- AMOVFL
- AMOVCRFS
- AMTFSB0
- AMTFSB0CC
- AMTFSB1
- AMTFSB1CC
- AMULHW
- AMULHWCC
- AMULHWU
- AMULHWUCC
- AMULLW
- AMULLWCC
- AMULLWVCC
- AMULLWV
- ANAND
- ANANDCC
- ANEG
- ANEGCC
- ANEGVCC
- ANEGV
+ AMOVWD
+ AMOVWF
+ AMOVWL
+ AMOVWR
+ AMUL
+ AMULD
+ AMULF
+ AMULU
+ AMULW
+ ANEGD
+ ANEGF
+ ANEGW
ANOR
- ANORCC
AOR
- AORCC
- AORN
- AORNCC
AREM
- AREMCC
- AREMV
- AREMVCC
AREMU
- AREMUCC
- AREMUV
- AREMUVCC
- ARFI
- ARLWMI
- ARLWMICC
- ARLWNM
- ARLWNMCC
- ASLW
- ASLWCC
- ASRW
- ASRAW
- ASRAWCC
- ASRWCC
- ASTSW
- ASTWCCC
+ ARFE
+ ASGT
+ ASGTU
+ ASLL
+ ASRA
+ ASRL
ASUB
- ASUBCC
- ASUBVCC
- ASUBC
- ASUBCCC
- ASUBCV
- ASUBCVCC
- ASUBME
- ASUBMECC
- ASUBMEVCC
- ASUBMEV
- ASUBV
- ASUBE
- ASUBECC
- ASUBEV
- ASUBEVCC
- ASUBZE
- ASUBZECC
- ASUBZEVCC
- ASUBZEV
- ASYNC
- AXOR
- AXORCC
-
- ADCBF
- ADCBI
- ADCBST
- ADCBT
- ADCBTST
- ADCBZ
- AECIWX
- AECOWX
- AEIEIO
- AICBI
- AISYNC
- APTESYNC
- ATLBIE
- ATLBIEL
- ATLBSYNC
- ATW
-
+ ASUBD
+ ASUBF
+ ASUBU
+ ASUBW
ASYSCALL
+ ATLBP
+ ATLBR
+ ATLBWI
+ ATLBWR
AWORD
-
- ARFCI
-
- /* optional on 32-bit */
- AFRES
- AFRESCC
- AFRSQRTE
- AFRSQRTECC
- AFSEL
- AFSELCC
- AFSQRT
- AFSQRTCC
- AFSQRTS
- AFSQRTSCC
+ AXOR
/* 64-bit */
+ AMOVV
+ AMOVVL
+ AMOVVR
+ ASLLV
+ ASRAV
+ ASRLV
+ ADIVV
+ ADIVVU
+ AREMV
+ AREMVU
+ AMULV
+ AMULVU
+ AADDV
+ AADDVU
+ ASUBV
+ ASUBVU
- ACNTLZD
- ACNTLZDCC
- ACMPW /* CMP with L=0 */
- ACMPWU
- ADIVD
- ADIVDCC
- ADIVDVCC
- ADIVDV
- ADIVDU
- ADIVDUCC
- ADIVDUVCC
- ADIVDUV
- AEXTSW
- AEXTSWCC
- /* AFCFIW; AFCFIWCC */
- AFCFID
- AFCFIDCC
- AFCTID
- AFCTIDCC
- AFCTIDZ
- AFCTIDZCC
- ALDAR
- AMOVD
- AMOVDU
- AMOVWZ
- AMOVWZU
- AMULHD
- AMULHDCC
- AMULHDU
- AMULHDUCC
- AMULLD
- AMULLDCC
- AMULLDVCC
- AMULLDV
- ARFID
- ARLDMI
- ARLDMICC
- ARLDC
- ARLDCCC
- ARLDCR
- ARLDCRCC
- ARLDCL
- ARLDCLCC
- ASLBIA
- ASLBIE
- ASLBMFEE
- ASLBMFEV
- ASLBMTE
- ASLD
- ASLDCC
- ASRD
- ASRAD
- ASRADCC
- ASRDCC
- ASTDCCC
- ATD
-
- /* 64-bit pseudo operation */
- ADWORD
- AREMD
- AREMDCC
- AREMDV
- AREMDVCC
- AREMDU
- AREMDUCC
- AREMDUV
- AREMDUVCC
-
- /* more 64-bit operations */
- AHRFID
+ /* 64-bit FP */
+ ATRUNCFV
+ ATRUNCDV
+ ATRUNCFW
+ ATRUNCDW
+ AMOVWU
+ AMOVFV
+ AMOVDV
+ AMOVVF
+ AMOVVD
ALAST
// aliases
- ABR = obj.AJMP
- ABL = obj.ACALL
+ AJMP = obj.AJMP
+ AJAL = obj.ACALL
+ ARET = obj.ARET
)
-// Generated by stringer -i a.out.go -o anames.go -p ppc64
+// Generated by stringer -i a.out.go -o anames.go -p mips
// Do not edit.
-package ppc64
+package mips
import "cmd/internal/obj"
var Anames = []string{
- obj.A_ARCHSPECIFIC: "ADD",
- "ADDCC",
- "ADDV",
- "ADDVCC",
- "ADDC",
- "ADDCCC",
- "ADDCV",
- "ADDCVCC",
- "ADDME",
- "ADDMECC",
- "ADDMEVCC",
- "ADDMEV",
- "ADDE",
- "ADDECC",
- "ADDEVCC",
- "ADDEV",
- "ADDZE",
- "ADDZECC",
- "ADDZEVCC",
- "ADDZEV",
+ obj.A_ARCHSPECIFIC: "ABSD",
+ "ABSF",
+ "ABSW",
+ "ADD",
+ "ADDD",
+ "ADDF",
+ "ADDU",
+ "ADDW",
"AND",
- "ANDCC",
- "ANDN",
- "ANDNCC",
- "BC",
- "BCL",
"BEQ",
- "BGE",
- "BGT",
- "BLE",
- "BLT",
+ "BFPF",
+ "BFPT",
+ "BGEZ",
+ "BGEZAL",
+ "BGTZ",
+ "BLEZ",
+ "BLTZ",
+ "BLTZAL",
"BNE",
- "BVC",
- "BVS",
- "CMP",
- "CMPU",
- "CNTLZW",
- "CNTLZWCC",
- "CRAND",
- "CRANDN",
- "CREQV",
- "CRNAND",
- "CRNOR",
- "CROR",
- "CRORN",
- "CRXOR",
+ "BREAK",
+ "CMPEQD",
+ "CMPEQF",
+ "CMPGED",
+ "CMPGEF",
+ "CMPGTD",
+ "CMPGTF",
+ "DIV",
+ "DIVD",
+ "DIVF",
+ "DIVU",
"DIVW",
- "DIVWCC",
- "DIVWVCC",
- "DIVWV",
- "DIVWU",
- "DIVWUCC",
- "DIVWUVCC",
- "DIVWUV",
- "EQV",
- "EQVCC",
- "EXTSB",
- "EXTSBCC",
- "EXTSH",
- "EXTSHCC",
- "FABS",
- "FABSCC",
- "FADD",
- "FADDCC",
- "FADDS",
- "FADDSCC",
- "FCMPO",
- "FCMPU",
- "FCTIW",
- "FCTIWCC",
- "FCTIWZ",
- "FCTIWZCC",
- "FDIV",
- "FDIVCC",
- "FDIVS",
- "FDIVSCC",
- "FMADD",
- "FMADDCC",
- "FMADDS",
- "FMADDSCC",
- "FMOVD",
- "FMOVDCC",
- "FMOVDU",
- "FMOVS",
- "FMOVSU",
- "FMSUB",
- "FMSUBCC",
- "FMSUBS",
- "FMSUBSCC",
- "FMUL",
- "FMULCC",
- "FMULS",
- "FMULSCC",
- "FNABS",
- "FNABSCC",
- "FNEG",
- "FNEGCC",
- "FNMADD",
- "FNMADDCC",
- "FNMADDS",
- "FNMADDSCC",
- "FNMSUB",
- "FNMSUBCC",
- "FNMSUBS",
- "FNMSUBSCC",
- "FRSP",
- "FRSPCC",
- "FSUB",
- "FSUBCC",
- "FSUBS",
- "FSUBSCC",
- "MOVMW",
- "LSW",
- "LWAR",
- "MOVWBR",
+ "GOK",
"MOVB",
"MOVBU",
- "MOVBZ",
- "MOVBZU",
+ "MOVD",
+ "MOVDF",
+ "MOVDW",
+ "MOVF",
+ "MOVFD",
+ "MOVFW",
"MOVH",
- "MOVHBR",
"MOVHU",
- "MOVHZ",
- "MOVHZU",
"MOVW",
- "MOVWU",
- "MOVFL",
- "MOVCRFS",
- "MTFSB0",
- "MTFSB0CC",
- "MTFSB1",
- "MTFSB1CC",
- "MULHW",
- "MULHWCC",
- "MULHWU",
- "MULHWUCC",
- "MULLW",
- "MULLWCC",
- "MULLWVCC",
- "MULLWV",
- "NAND",
- "NANDCC",
- "NEG",
- "NEGCC",
- "NEGVCC",
- "NEGV",
+ "MOVWD",
+ "MOVWF",
+ "MOVWL",
+ "MOVWR",
+ "MUL",
+ "MULD",
+ "MULF",
+ "MULU",
+ "MULW",
+ "NEGD",
+ "NEGF",
+ "NEGW",
"NOR",
- "NORCC",
"OR",
- "ORCC",
- "ORN",
- "ORNCC",
"REM",
- "REMCC",
- "REMV",
- "REMVCC",
"REMU",
- "REMUCC",
- "REMUV",
- "REMUVCC",
- "RFI",
- "RLWMI",
- "RLWMICC",
- "RLWNM",
- "RLWNMCC",
- "SLW",
- "SLWCC",
- "SRW",
- "SRAW",
- "SRAWCC",
- "SRWCC",
- "STSW",
- "STWCCC",
+ "RFE",
+ "SGT",
+ "SGTU",
+ "SLL",
+ "SRA",
+ "SRL",
"SUB",
- "SUBCC",
- "SUBVCC",
- "SUBC",
- "SUBCCC",
- "SUBCV",
- "SUBCVCC",
- "SUBME",
- "SUBMECC",
- "SUBMEVCC",
- "SUBMEV",
- "SUBV",
- "SUBE",
- "SUBECC",
- "SUBEV",
- "SUBEVCC",
- "SUBZE",
- "SUBZECC",
- "SUBZEVCC",
- "SUBZEV",
- "SYNC",
- "XOR",
- "XORCC",
- "DCBF",
- "DCBI",
- "DCBST",
- "DCBT",
- "DCBTST",
- "DCBZ",
- "ECIWX",
- "ECOWX",
- "EIEIO",
- "ICBI",
- "ISYNC",
- "PTESYNC",
- "TLBIE",
- "TLBIEL",
- "TLBSYNC",
- "TW",
+ "SUBD",
+ "SUBF",
+ "SUBU",
+ "SUBW",
"SYSCALL",
+ "TLBP",
+ "TLBR",
+ "TLBWI",
+ "TLBWR",
"WORD",
- "RFCI",
- "FRES",
- "FRESCC",
- "FRSQRTE",
- "FRSQRTECC",
- "FSEL",
- "FSELCC",
- "FSQRT",
- "FSQRTCC",
- "FSQRTS",
- "FSQRTSCC",
- "CNTLZD",
- "CNTLZDCC",
- "CMPW",
- "CMPWU",
- "DIVD",
- "DIVDCC",
- "DIVDVCC",
- "DIVDV",
- "DIVDU",
- "DIVDUCC",
- "DIVDUVCC",
- "DIVDUV",
- "EXTSW",
- "EXTSWCC",
- "FCFID",
- "FCFIDCC",
- "FCTID",
- "FCTIDCC",
- "FCTIDZ",
- "FCTIDZCC",
- "LDAR",
- "MOVD",
- "MOVDU",
- "MOVWZ",
- "MOVWZU",
- "MULHD",
- "MULHDCC",
- "MULHDU",
- "MULHDUCC",
- "MULLD",
- "MULLDCC",
- "MULLDVCC",
- "MULLDV",
- "RFID",
- "RLDMI",
- "RLDMICC",
- "RLDC",
- "RLDCCC",
- "RLDCR",
- "RLDCRCC",
- "RLDCL",
- "RLDCLCC",
- "SLBIA",
- "SLBIE",
- "SLBMFEE",
- "SLBMFEV",
- "SLBMTE",
- "SLD",
- "SLDCC",
- "SRD",
- "SRAD",
- "SRADCC",
- "SRDCC",
- "STDCCC",
- "TD",
- "DWORD",
- "REMD",
- "REMDCC",
- "REMDV",
- "REMDVCC",
- "REMDU",
- "REMDUCC",
- "REMDUV",
- "REMDUVCC",
- "HRFID",
+ "XOR",
+ "MOVV",
+ "MOVVL",
+ "MOVVR",
+ "SLLV",
+ "SRAV",
+ "SRLV",
+ "DIVV",
+ "DIVVU",
+ "REMV",
+ "REMVU",
+ "MULV",
+ "MULVU",
+ "ADDV",
+ "ADDVU",
+ "SUBV",
+ "SUBVU",
+ "TRUNCFV",
+ "TRUNCDV",
+ "TRUNCFW",
+ "TRUNCDW",
+ "MOVWU",
+ "MOVFV",
+ "MOVDV",
+ "MOVVF",
+ "MOVVD",
"LAST",
}
-package ppc64
+package mips
-var cnames9 = []string{
+var cnames0 = []string{
"NONE",
"REG",
"FREG",
- "CREG",
- "SPR",
+ "FCREG",
+ "MREG",
+ "HI",
+ "LO",
"ZCON",
"SCON",
"UCON",
+ "ADD0CON",
+ "AND0CON",
"ADDCON",
"ANDCON",
"LCON",
"ZOREG",
"SOREG",
"LOREG",
- "FPSCR",
- "MSR",
- "XER",
- "LR",
- "CTR",
- "ANY",
"GOK",
"ADDR",
"TEXTSIZE",
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package ppc64
+package mips
import (
"cmd/internal/obj"
- "encoding/binary"
"fmt"
"log"
"sort"
a1 uint8
a2 uint8
a3 uint8
- a4 uint8
type_ int8
size int8
param int16
}
var optab = []Optab{
- Optab{obj.ATEXT, C_LEXT, C_NONE, C_NONE, C_TEXTSIZE, 0, 0, 0},
- Optab{obj.ATEXT, C_LEXT, C_NONE, C_LCON, C_TEXTSIZE, 0, 0, 0},
- Optab{obj.ATEXT, C_ADDR, C_NONE, C_NONE, C_TEXTSIZE, 0, 0, 0},
- Optab{obj.ATEXT, C_ADDR, C_NONE, C_LCON, C_TEXTSIZE, 0, 0, 0},
- /* move register */
- Optab{AMOVD, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0},
- Optab{AMOVB, C_REG, C_NONE, C_NONE, C_REG, 12, 4, 0},
- Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_REG, 13, 4, 0},
- Optab{AMOVW, C_REG, C_NONE, C_NONE, C_REG, 12, 4, 0},
- Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_REG, 13, 4, 0},
- Optab{AADD, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0},
- Optab{AADD, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0},
- Optab{AADD, C_ADDCON, C_REG, C_NONE, C_REG, 4, 4, 0},
- Optab{AADD, C_ADDCON, C_NONE, C_NONE, C_REG, 4, 4, 0},
- Optab{AADD, C_UCON, C_REG, C_NONE, C_REG, 20, 4, 0},
- Optab{AADD, C_UCON, C_NONE, C_NONE, C_REG, 20, 4, 0},
- Optab{AADD, C_LCON, C_REG, C_NONE, C_REG, 22, 12, 0},
- Optab{AADD, C_LCON, C_NONE, C_NONE, C_REG, 22, 12, 0},
- Optab{AADDC, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0},
- Optab{AADDC, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0},
- Optab{AADDC, C_ADDCON, C_REG, C_NONE, C_REG, 4, 4, 0},
- Optab{AADDC, C_ADDCON, C_NONE, C_NONE, C_REG, 4, 4, 0},
- Optab{AADDC, C_LCON, C_REG, C_NONE, C_REG, 22, 12, 0},
- Optab{AADDC, C_LCON, C_NONE, C_NONE, C_REG, 22, 12, 0},
- Optab{AAND, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0}, /* logical, no literal */
- Optab{AAND, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
- Optab{AANDCC, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
- Optab{AANDCC, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
- Optab{AANDCC, C_ANDCON, C_NONE, C_NONE, C_REG, 58, 4, 0},
- Optab{AANDCC, C_ANDCON, C_REG, C_NONE, C_REG, 58, 4, 0},
- Optab{AANDCC, C_UCON, C_NONE, C_NONE, C_REG, 59, 4, 0},
- Optab{AANDCC, C_UCON, C_REG, C_NONE, C_REG, 59, 4, 0},
- Optab{AANDCC, C_LCON, C_NONE, C_NONE, C_REG, 23, 12, 0},
- Optab{AANDCC, C_LCON, C_REG, C_NONE, C_REG, 23, 12, 0},
- Optab{AMULLW, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0},
- Optab{AMULLW, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0},
- Optab{AMULLW, C_ADDCON, C_REG, C_NONE, C_REG, 4, 4, 0},
- Optab{AMULLW, C_ADDCON, C_NONE, C_NONE, C_REG, 4, 4, 0},
- Optab{AMULLW, C_ANDCON, C_REG, C_NONE, C_REG, 4, 4, 0},
- Optab{AMULLW, C_ANDCON, C_NONE, C_NONE, C_REG, 4, 4, 0},
- Optab{AMULLW, C_LCON, C_REG, C_NONE, C_REG, 22, 12, 0},
- Optab{AMULLW, C_LCON, C_NONE, C_NONE, C_REG, 22, 12, 0},
- Optab{ASUBC, C_REG, C_REG, C_NONE, C_REG, 10, 4, 0},
- Optab{ASUBC, C_REG, C_NONE, C_NONE, C_REG, 10, 4, 0},
- Optab{ASUBC, C_REG, C_NONE, C_ADDCON, C_REG, 27, 4, 0},
- Optab{ASUBC, C_REG, C_NONE, C_LCON, C_REG, 28, 12, 0},
- Optab{AOR, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0}, /* logical, literal not cc (or/xor) */
- Optab{AOR, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
- Optab{AOR, C_ANDCON, C_NONE, C_NONE, C_REG, 58, 4, 0},
- Optab{AOR, C_ANDCON, C_REG, C_NONE, C_REG, 58, 4, 0},
- Optab{AOR, C_UCON, C_NONE, C_NONE, C_REG, 59, 4, 0},
- Optab{AOR, C_UCON, C_REG, C_NONE, C_REG, 59, 4, 0},
- Optab{AOR, C_LCON, C_NONE, C_NONE, C_REG, 23, 12, 0},
- Optab{AOR, C_LCON, C_REG, C_NONE, C_REG, 23, 12, 0},
- Optab{ADIVW, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0}, /* op r1[,r2],r3 */
- Optab{ADIVW, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0},
- Optab{ASUB, C_REG, C_REG, C_NONE, C_REG, 10, 4, 0}, /* op r2[,r1],r3 */
- Optab{ASUB, C_REG, C_NONE, C_NONE, C_REG, 10, 4, 0},
- Optab{ASLW, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
- Optab{ASLW, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
- Optab{ASLD, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
- Optab{ASLD, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
- Optab{ASLD, C_SCON, C_REG, C_NONE, C_REG, 25, 4, 0},
- Optab{ASLD, C_SCON, C_NONE, C_NONE, C_REG, 25, 4, 0},
- Optab{ASLW, C_SCON, C_REG, C_NONE, C_REG, 57, 4, 0},
- Optab{ASLW, C_SCON, C_NONE, C_NONE, C_REG, 57, 4, 0},
- Optab{ASRAW, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
- Optab{ASRAW, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
- Optab{ASRAW, C_SCON, C_REG, C_NONE, C_REG, 56, 4, 0},
- Optab{ASRAW, C_SCON, C_NONE, C_NONE, C_REG, 56, 4, 0},
- Optab{ASRAD, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
- Optab{ASRAD, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
- Optab{ASRAD, C_SCON, C_REG, C_NONE, C_REG, 56, 4, 0},
- Optab{ASRAD, C_SCON, C_NONE, C_NONE, C_REG, 56, 4, 0},
- Optab{ARLWMI, C_SCON, C_REG, C_LCON, C_REG, 62, 4, 0},
- Optab{ARLWMI, C_REG, C_REG, C_LCON, C_REG, 63, 4, 0},
- Optab{ARLDMI, C_SCON, C_REG, C_LCON, C_REG, 30, 4, 0},
- Optab{ARLDC, C_SCON, C_REG, C_LCON, C_REG, 29, 4, 0},
- Optab{ARLDCL, C_SCON, C_REG, C_LCON, C_REG, 29, 4, 0},
- Optab{ARLDCL, C_REG, C_REG, C_LCON, C_REG, 14, 4, 0},
- Optab{ARLDCL, C_REG, C_NONE, C_LCON, C_REG, 14, 4, 0},
- Optab{AFADD, C_FREG, C_NONE, C_NONE, C_FREG, 2, 4, 0},
- Optab{AFADD, C_FREG, C_REG, C_NONE, C_FREG, 2, 4, 0},
- Optab{AFABS, C_FREG, C_NONE, C_NONE, C_FREG, 33, 4, 0},
- Optab{AFABS, C_NONE, C_NONE, C_NONE, C_FREG, 33, 4, 0},
- Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_FREG, 33, 4, 0},
- Optab{AFMADD, C_FREG, C_REG, C_FREG, C_FREG, 34, 4, 0},
- Optab{AFMUL, C_FREG, C_NONE, C_NONE, C_FREG, 32, 4, 0},
- Optab{AFMUL, C_FREG, C_REG, C_NONE, C_FREG, 32, 4, 0},
-
- /* store, short offset */
- Optab{AMOVD, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
- Optab{AMOVW, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
- Optab{AMOVWZ, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
- Optab{AMOVBZ, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
- Optab{AMOVBZU, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
- Optab{AMOVB, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
- Optab{AMOVBU, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
- Optab{AMOVD, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
- Optab{AMOVW, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
- Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
- Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
- Optab{AMOVB, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
- Optab{AMOVD, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
- Optab{AMOVW, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
- Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
- Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
- Optab{AMOVB, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
- Optab{AMOVD, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
- Optab{AMOVW, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
- Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
- Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
- Optab{AMOVBZU, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
- Optab{AMOVB, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
- Optab{AMOVBU, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
-
- /* load, short offset */
- Optab{AMOVD, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
- Optab{AMOVW, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
- Optab{AMOVWZ, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
- Optab{AMOVBZ, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
- Optab{AMOVBZU, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
- Optab{AMOVB, C_ZOREG, C_REG, C_NONE, C_REG, 9, 8, REGZERO},
- Optab{AMOVBU, C_ZOREG, C_REG, C_NONE, C_REG, 9, 8, REGZERO},
- Optab{AMOVD, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB},
- Optab{AMOVW, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB},
- Optab{AMOVWZ, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB},
- Optab{AMOVBZ, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB},
- Optab{AMOVB, C_SEXT, C_NONE, C_NONE, C_REG, 9, 8, REGSB},
- Optab{AMOVD, C_SAUTO, C_NONE, C_NONE, C_REG, 8, 4, REGSP},
- Optab{AMOVW, C_SAUTO, C_NONE, C_NONE, C_REG, 8, 4, REGSP},
- Optab{AMOVWZ, C_SAUTO, C_NONE, C_NONE, C_REG, 8, 4, REGSP},
- Optab{AMOVBZ, C_SAUTO, C_NONE, C_NONE, C_REG, 8, 4, REGSP},
- Optab{AMOVB, C_SAUTO, C_NONE, C_NONE, C_REG, 9, 8, REGSP},
- Optab{AMOVD, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
- Optab{AMOVW, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
- Optab{AMOVWZ, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
- Optab{AMOVBZ, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
- Optab{AMOVBZU, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
- Optab{AMOVB, C_SOREG, C_NONE, C_NONE, C_REG, 9, 8, REGZERO},
- Optab{AMOVBU, C_SOREG, C_NONE, C_NONE, C_REG, 9, 8, REGZERO},
-
- /* store, long offset */
- Optab{AMOVD, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
- Optab{AMOVW, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
- Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
- Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
- Optab{AMOVB, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
- Optab{AMOVD, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
- Optab{AMOVW, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
- Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
- Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
- Optab{AMOVB, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
- Optab{AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
- Optab{AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
- Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
- Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
- Optab{AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
- Optab{AMOVD, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
- Optab{AMOVW, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
- Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
- Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
- Optab{AMOVB, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
-
- /* load, long offset */
- Optab{AMOVD, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB},
- Optab{AMOVW, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB},
- Optab{AMOVWZ, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB},
- Optab{AMOVBZ, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB},
- Optab{AMOVB, C_LEXT, C_NONE, C_NONE, C_REG, 37, 12, REGSB},
- Optab{AMOVD, C_LAUTO, C_NONE, C_NONE, C_REG, 36, 8, REGSP},
- Optab{AMOVW, C_LAUTO, C_NONE, C_NONE, C_REG, 36, 8, REGSP},
- Optab{AMOVWZ, C_LAUTO, C_NONE, C_NONE, C_REG, 36, 8, REGSP},
- Optab{AMOVBZ, C_LAUTO, C_NONE, C_NONE, C_REG, 36, 8, REGSP},
- Optab{AMOVB, C_LAUTO, C_NONE, C_NONE, C_REG, 37, 12, REGSP},
- Optab{AMOVD, C_LOREG, C_NONE, C_NONE, C_REG, 36, 8, REGZERO},
- Optab{AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, 36, 8, REGZERO},
- Optab{AMOVWZ, C_LOREG, C_NONE, C_NONE, C_REG, 36, 8, REGZERO},
- Optab{AMOVBZ, C_LOREG, C_NONE, C_NONE, C_REG, 36, 8, REGZERO},
- Optab{AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, 37, 12, REGZERO},
- Optab{AMOVD, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0},
- Optab{AMOVW, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0},
- Optab{AMOVWZ, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0},
- Optab{AMOVBZ, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0},
- Optab{AMOVB, C_ADDR, C_NONE, C_NONE, C_REG, 76, 12, 0},
-
- /* load constant */
- Optab{AMOVD, C_SECON, C_NONE, C_NONE, C_REG, 3, 4, REGSB},
- Optab{AMOVD, C_SACON, C_NONE, C_NONE, C_REG, 3, 4, REGSP},
- Optab{AMOVD, C_LECON, C_NONE, C_NONE, C_REG, 26, 8, REGSB},
- Optab{AMOVD, C_LACON, C_NONE, C_NONE, C_REG, 26, 8, REGSP},
- Optab{AMOVD, C_ADDCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
- Optab{AMOVW, C_SECON, C_NONE, C_NONE, C_REG, 3, 4, REGSB}, /* TO DO: check */
- Optab{AMOVW, C_SACON, C_NONE, C_NONE, C_REG, 3, 4, REGSP},
- Optab{AMOVW, C_LECON, C_NONE, C_NONE, C_REG, 26, 8, REGSB},
- Optab{AMOVW, C_LACON, C_NONE, C_NONE, C_REG, 26, 8, REGSP},
- Optab{AMOVW, C_ADDCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
- Optab{AMOVWZ, C_SECON, C_NONE, C_NONE, C_REG, 3, 4, REGSB}, /* TO DO: check */
- Optab{AMOVWZ, C_SACON, C_NONE, C_NONE, C_REG, 3, 4, REGSP},
- Optab{AMOVWZ, C_LECON, C_NONE, C_NONE, C_REG, 26, 8, REGSB},
- Optab{AMOVWZ, C_LACON, C_NONE, C_NONE, C_REG, 26, 8, REGSP},
- Optab{AMOVWZ, C_ADDCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
-
- /* load unsigned/long constants (TO DO: check) */
- Optab{AMOVD, C_UCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
- Optab{AMOVD, C_LCON, C_NONE, C_NONE, C_REG, 19, 8, 0},
- Optab{AMOVW, C_UCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
- Optab{AMOVW, C_LCON, C_NONE, C_NONE, C_REG, 19, 8, 0},
- Optab{AMOVWZ, C_UCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
- Optab{AMOVWZ, C_LCON, C_NONE, C_NONE, C_REG, 19, 8, 0},
- Optab{AMOVHBR, C_ZOREG, C_REG, C_NONE, C_REG, 45, 4, 0},
- Optab{AMOVHBR, C_ZOREG, C_NONE, C_NONE, C_REG, 45, 4, 0},
- Optab{AMOVHBR, C_REG, C_REG, C_NONE, C_ZOREG, 44, 4, 0},
- Optab{AMOVHBR, C_REG, C_NONE, C_NONE, C_ZOREG, 44, 4, 0},
- Optab{ASYSCALL, C_NONE, C_NONE, C_NONE, C_NONE, 5, 4, 0},
- Optab{ASYSCALL, C_REG, C_NONE, C_NONE, C_NONE, 77, 12, 0},
- Optab{ASYSCALL, C_SCON, C_NONE, C_NONE, C_NONE, 77, 12, 0},
- Optab{ABEQ, C_NONE, C_NONE, C_NONE, C_SBRA, 16, 4, 0},
- Optab{ABEQ, C_CREG, C_NONE, C_NONE, C_SBRA, 16, 4, 0},
- Optab{ABR, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0},
- Optab{ABC, C_SCON, C_REG, C_NONE, C_SBRA, 16, 4, 0},
- Optab{ABC, C_SCON, C_REG, C_NONE, C_LBRA, 17, 4, 0},
- Optab{ABR, C_NONE, C_NONE, C_NONE, C_LR, 18, 4, 0},
- Optab{ABR, C_NONE, C_NONE, C_NONE, C_CTR, 18, 4, 0},
- Optab{ABR, C_REG, C_NONE, C_NONE, C_CTR, 18, 4, 0},
- Optab{ABR, C_NONE, C_NONE, C_NONE, C_ZOREG, 15, 8, 0},
- Optab{ABC, C_NONE, C_REG, C_NONE, C_LR, 18, 4, 0},
- Optab{ABC, C_NONE, C_REG, C_NONE, C_CTR, 18, 4, 0},
- Optab{ABC, C_SCON, C_REG, C_NONE, C_LR, 18, 4, 0},
- Optab{ABC, C_SCON, C_REG, C_NONE, C_CTR, 18, 4, 0},
- Optab{ABC, C_NONE, C_NONE, C_NONE, C_ZOREG, 15, 8, 0},
- Optab{AFMOVD, C_SEXT, C_NONE, C_NONE, C_FREG, 8, 4, REGSB},
- Optab{AFMOVD, C_SAUTO, C_NONE, C_NONE, C_FREG, 8, 4, REGSP},
- Optab{AFMOVD, C_SOREG, C_NONE, C_NONE, C_FREG, 8, 4, REGZERO},
- Optab{AFMOVD, C_LEXT, C_NONE, C_NONE, C_FREG, 36, 8, REGSB},
- Optab{AFMOVD, C_LAUTO, C_NONE, C_NONE, C_FREG, 36, 8, REGSP},
- Optab{AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 36, 8, REGZERO},
- Optab{AFMOVD, C_ADDR, C_NONE, C_NONE, C_FREG, 75, 8, 0},
- Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
- Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
- Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
- Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
- Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
- Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
- Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
- Optab{ASYNC, C_NONE, C_NONE, C_NONE, C_NONE, 46, 4, 0},
- Optab{AWORD, C_LCON, C_NONE, C_NONE, C_NONE, 40, 4, 0},
- Optab{ADWORD, C_LCON, C_NONE, C_NONE, C_NONE, 31, 8, 0},
- Optab{ADWORD, C_DCON, C_NONE, C_NONE, C_NONE, 31, 8, 0},
- Optab{AADDME, C_REG, C_NONE, C_NONE, C_REG, 47, 4, 0},
- Optab{AEXTSB, C_REG, C_NONE, C_NONE, C_REG, 48, 4, 0},
- Optab{AEXTSB, C_NONE, C_NONE, C_NONE, C_REG, 48, 4, 0},
- Optab{ANEG, C_REG, C_NONE, C_NONE, C_REG, 47, 4, 0},
- Optab{ANEG, C_NONE, C_NONE, C_NONE, C_REG, 47, 4, 0},
- Optab{AREM, C_REG, C_NONE, C_NONE, C_REG, 50, 12, 0},
- Optab{AREM, C_REG, C_REG, C_NONE, C_REG, 50, 12, 0},
- Optab{AREMU, C_REG, C_NONE, C_NONE, C_REG, 50, 16, 0},
- Optab{AREMU, C_REG, C_REG, C_NONE, C_REG, 50, 16, 0},
- Optab{AREMD, C_REG, C_NONE, C_NONE, C_REG, 51, 12, 0},
- Optab{AREMD, C_REG, C_REG, C_NONE, C_REG, 51, 12, 0},
- Optab{AREMDU, C_REG, C_NONE, C_NONE, C_REG, 51, 12, 0},
- Optab{AREMDU, C_REG, C_REG, C_NONE, C_REG, 51, 12, 0},
- Optab{AMTFSB0, C_SCON, C_NONE, C_NONE, C_NONE, 52, 4, 0},
- Optab{AMOVFL, C_FPSCR, C_NONE, C_NONE, C_FREG, 53, 4, 0},
- Optab{AMOVFL, C_FREG, C_NONE, C_NONE, C_FPSCR, 64, 4, 0},
- Optab{AMOVFL, C_FREG, C_NONE, C_LCON, C_FPSCR, 64, 4, 0},
- Optab{AMOVFL, C_LCON, C_NONE, C_NONE, C_FPSCR, 65, 4, 0},
- Optab{AMOVD, C_MSR, C_NONE, C_NONE, C_REG, 54, 4, 0}, /* mfmsr */
- Optab{AMOVD, C_REG, C_NONE, C_NONE, C_MSR, 54, 4, 0}, /* mtmsrd */
- Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_MSR, 54, 4, 0}, /* mtmsr */
-
- /* 64-bit special registers */
- Optab{AMOVD, C_REG, C_NONE, C_NONE, C_SPR, 66, 4, 0},
- Optab{AMOVD, C_REG, C_NONE, C_NONE, C_LR, 66, 4, 0},
- Optab{AMOVD, C_REG, C_NONE, C_NONE, C_CTR, 66, 4, 0},
- Optab{AMOVD, C_REG, C_NONE, C_NONE, C_XER, 66, 4, 0},
- Optab{AMOVD, C_SPR, C_NONE, C_NONE, C_REG, 66, 4, 0},
- Optab{AMOVD, C_LR, C_NONE, C_NONE, C_REG, 66, 4, 0},
- Optab{AMOVD, C_CTR, C_NONE, C_NONE, C_REG, 66, 4, 0},
- Optab{AMOVD, C_XER, C_NONE, C_NONE, C_REG, 66, 4, 0},
-
- /* 32-bit special registers (gloss over sign-extension or not?) */
- Optab{AMOVW, C_REG, C_NONE, C_NONE, C_SPR, 66, 4, 0},
- Optab{AMOVW, C_REG, C_NONE, C_NONE, C_CTR, 66, 4, 0},
- Optab{AMOVW, C_REG, C_NONE, C_NONE, C_XER, 66, 4, 0},
- Optab{AMOVW, C_SPR, C_NONE, C_NONE, C_REG, 66, 4, 0},
- Optab{AMOVW, C_XER, C_NONE, C_NONE, C_REG, 66, 4, 0},
- Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_SPR, 66, 4, 0},
- Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_CTR, 66, 4, 0},
- Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_XER, 66, 4, 0},
- Optab{AMOVWZ, C_SPR, C_NONE, C_NONE, C_REG, 66, 4, 0},
- Optab{AMOVWZ, C_XER, C_NONE, C_NONE, C_REG, 66, 4, 0},
- Optab{AMOVFL, C_FPSCR, C_NONE, C_NONE, C_CREG, 73, 4, 0},
- Optab{AMOVFL, C_CREG, C_NONE, C_NONE, C_CREG, 67, 4, 0},
- Optab{AMOVW, C_CREG, C_NONE, C_NONE, C_REG, 68, 4, 0},
- Optab{AMOVWZ, C_CREG, C_NONE, C_NONE, C_REG, 68, 4, 0},
- Optab{AMOVFL, C_REG, C_NONE, C_LCON, C_CREG, 69, 4, 0},
- Optab{AMOVFL, C_REG, C_NONE, C_NONE, C_CREG, 69, 4, 0},
- Optab{AMOVW, C_REG, C_NONE, C_NONE, C_CREG, 69, 4, 0},
- Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_CREG, 69, 4, 0},
- Optab{ACMP, C_REG, C_NONE, C_NONE, C_REG, 70, 4, 0},
- Optab{ACMP, C_REG, C_REG, C_NONE, C_REG, 70, 4, 0},
- Optab{ACMP, C_REG, C_NONE, C_NONE, C_ADDCON, 71, 4, 0},
- Optab{ACMP, C_REG, C_REG, C_NONE, C_ADDCON, 71, 4, 0},
- Optab{ACMPU, C_REG, C_NONE, C_NONE, C_REG, 70, 4, 0},
- Optab{ACMPU, C_REG, C_REG, C_NONE, C_REG, 70, 4, 0},
- Optab{ACMPU, C_REG, C_NONE, C_NONE, C_ANDCON, 71, 4, 0},
- Optab{ACMPU, C_REG, C_REG, C_NONE, C_ANDCON, 71, 4, 0},
- Optab{AFCMPO, C_FREG, C_NONE, C_NONE, C_FREG, 70, 4, 0},
- Optab{AFCMPO, C_FREG, C_REG, C_NONE, C_FREG, 70, 4, 0},
- Optab{ATW, C_LCON, C_REG, C_NONE, C_REG, 60, 4, 0},
- Optab{ATW, C_LCON, C_REG, C_NONE, C_ADDCON, 61, 4, 0},
- Optab{ADCBF, C_ZOREG, C_NONE, C_NONE, C_NONE, 43, 4, 0},
- Optab{ADCBF, C_ZOREG, C_REG, C_NONE, C_NONE, 43, 4, 0},
- Optab{AECOWX, C_REG, C_REG, C_NONE, C_ZOREG, 44, 4, 0},
- Optab{AECIWX, C_ZOREG, C_REG, C_NONE, C_REG, 45, 4, 0},
- Optab{AECOWX, C_REG, C_NONE, C_NONE, C_ZOREG, 44, 4, 0},
- Optab{AECIWX, C_ZOREG, C_NONE, C_NONE, C_REG, 45, 4, 0},
- Optab{AEIEIO, C_NONE, C_NONE, C_NONE, C_NONE, 46, 4, 0},
- Optab{ATLBIE, C_REG, C_NONE, C_NONE, C_NONE, 49, 4, 0},
- Optab{ATLBIE, C_SCON, C_NONE, C_NONE, C_REG, 49, 4, 0},
- Optab{ASLBMFEE, C_REG, C_NONE, C_NONE, C_REG, 55, 4, 0},
- Optab{ASLBMTE, C_REG, C_NONE, C_NONE, C_REG, 55, 4, 0},
- Optab{ASTSW, C_REG, C_NONE, C_NONE, C_ZOREG, 44, 4, 0},
- Optab{ASTSW, C_REG, C_NONE, C_LCON, C_ZOREG, 41, 4, 0},
- Optab{ALSW, C_ZOREG, C_NONE, C_NONE, C_REG, 45, 4, 0},
- Optab{ALSW, C_ZOREG, C_NONE, C_LCON, C_REG, 42, 4, 0},
- Optab{obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, 78, 4, 0},
- Optab{obj.AUSEFIELD, C_ADDR, C_NONE, C_NONE, C_NONE, 0, 0, 0},
- Optab{obj.APCDATA, C_LCON, C_NONE, C_NONE, C_LCON, 0, 0, 0},
- Optab{obj.AFUNCDATA, C_SCON, C_NONE, C_NONE, C_ADDR, 0, 0, 0},
- Optab{obj.ANOP, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0},
- Optab{obj.ADUFFZERO, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, // same as ABR/ABL
- Optab{obj.ADUFFCOPY, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, // same as ABR/ABL
-
- Optab{obj.AXXX, C_NONE, C_NONE, C_NONE, C_NONE, 0, 4, 0},
+ {obj.ATEXT, C_LEXT, C_NONE, C_TEXTSIZE, 0, 0, 0},
+ {obj.ATEXT, C_ADDR, C_NONE, C_TEXTSIZE, 0, 0, 0},
+
+ {AMOVW, C_REG, C_NONE, C_REG, 14, 8, 0},
+ {AMOVV, C_REG, C_NONE, C_REG, 1, 4, 0},
+ {AMOVB, C_REG, C_NONE, C_REG, 12, 8, 0},
+ {AMOVBU, C_REG, C_NONE, C_REG, 13, 4, 0},
+ {AMOVWU, C_REG, C_NONE, C_REG, 14, 8, 0},
+
+ {ASUB, C_REG, C_REG, C_REG, 2, 4, 0},
+ {AADD, C_REG, C_REG, C_REG, 2, 4, 0},
+ {AAND, C_REG, C_REG, C_REG, 2, 4, 0},
+ {ASUB, C_REG, C_NONE, C_REG, 2, 4, 0},
+ {AADD, C_REG, C_NONE, C_REG, 2, 4, 0},
+ {AAND, C_REG, C_NONE, C_REG, 2, 4, 0},
+
+ {ASLL, C_REG, C_NONE, C_REG, 9, 4, 0},
+ {ASLL, C_REG, C_REG, C_REG, 9, 4, 0},
+
+ {AADDF, C_FREG, C_NONE, C_FREG, 32, 4, 0},
+ {AADDF, C_FREG, C_REG, C_FREG, 32, 4, 0},
+ {ACMPEQF, C_FREG, C_REG, C_NONE, 32, 4, 0},
+ {AABSF, C_FREG, C_NONE, C_FREG, 33, 4, 0},
+ {AMOVF, C_FREG, C_NONE, C_FREG, 33, 4, 0},
+ {AMOVD, C_FREG, C_NONE, C_FREG, 33, 4, 0},
+
+ {AMOVW, C_REG, C_NONE, C_SEXT, 7, 4, REGSB},
+ {AMOVWU, C_REG, C_NONE, C_SEXT, 7, 4, REGSB},
+ {AMOVV, C_REG, C_NONE, C_SEXT, 7, 4, REGSB},
+ {AMOVB, C_REG, C_NONE, C_SEXT, 7, 4, REGSB},
+ {AMOVBU, C_REG, C_NONE, C_SEXT, 7, 4, REGSB},
+ {AMOVWL, C_REG, C_NONE, C_SEXT, 7, 4, REGSB},
+ {AMOVW, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP},
+ {AMOVWU, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP},
+ {AMOVV, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP},
+ {AMOVB, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP},
+ {AMOVBU, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP},
+ {AMOVWL, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP},
+ {AMOVW, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO},
+ {AMOVWU, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO},
+ {AMOVV, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO},
+ {AMOVB, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO},
+ {AMOVBU, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO},
+ {AMOVWL, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO},
+
+ {AMOVW, C_SEXT, C_NONE, C_REG, 8, 4, REGSB},
+ {AMOVWU, C_SEXT, C_NONE, C_REG, 8, 4, REGSB},
+ {AMOVV, C_SEXT, C_NONE, C_REG, 8, 4, REGSB},
+ {AMOVB, C_SEXT, C_NONE, C_REG, 8, 4, REGSB},
+ {AMOVBU, C_SEXT, C_NONE, C_REG, 8, 4, REGSB},
+ {AMOVWL, C_SEXT, C_NONE, C_REG, 8, 4, REGSB},
+ {AMOVW, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP},
+ {AMOVWU, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP},
+ {AMOVV, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP},
+ {AMOVB, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP},
+ {AMOVBU, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP},
+ {AMOVWL, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP},
+ {AMOVW, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO},
+ {AMOVWU, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO},
+ {AMOVV, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO},
+ {AMOVB, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO},
+ {AMOVBU, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO},
+ {AMOVWL, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO},
+
+ {AMOVW, C_REG, C_NONE, C_LEXT, 35, 16, REGSB},
+ {AMOVWU, C_REG, C_NONE, C_LEXT, 35, 16, REGSB},
+ {AMOVV, C_REG, C_NONE, C_LEXT, 35, 16, REGSB},
+ {AMOVB, C_REG, C_NONE, C_LEXT, 35, 16, REGSB},
+ {AMOVBU, C_REG, C_NONE, C_LEXT, 35, 16, REGSB},
+ {AMOVW, C_REG, C_NONE, C_LAUTO, 35, 16, REGSP},
+ {AMOVWU, C_REG, C_NONE, C_LAUTO, 35, 16, REGSP},
+ {AMOVV, C_REG, C_NONE, C_LAUTO, 35, 16, REGSP},
+ {AMOVB, C_REG, C_NONE, C_LAUTO, 35, 16, REGSP},
+ {AMOVBU, C_REG, C_NONE, C_LAUTO, 35, 16, REGSP},
+ {AMOVW, C_REG, C_NONE, C_LOREG, 35, 16, REGZERO},
+ {AMOVWU, C_REG, C_NONE, C_LOREG, 35, 16, REGZERO},
+ {AMOVV, C_REG, C_NONE, C_LOREG, 35, 16, REGZERO},
+ {AMOVB, C_REG, C_NONE, C_LOREG, 35, 16, REGZERO},
+ {AMOVBU, C_REG, C_NONE, C_LOREG, 35, 16, REGZERO},
+ {AMOVW, C_REG, C_NONE, C_ADDR, 50, 12, 0},
+ {AMOVWU, C_REG, C_NONE, C_ADDR, 50, 12, 0},
+ {AMOVV, C_REG, C_NONE, C_ADDR, 50, 12, 0},
+ {AMOVB, C_REG, C_NONE, C_ADDR, 50, 12, 0},
+ {AMOVBU, C_REG, C_NONE, C_ADDR, 50, 12, 0},
+
+ {AMOVW, C_LEXT, C_NONE, C_REG, 36, 16, REGSB},
+ {AMOVWU, C_LEXT, C_NONE, C_REG, 36, 16, REGSB},
+ {AMOVV, C_LEXT, C_NONE, C_REG, 36, 16, REGSB},
+ {AMOVB, C_LEXT, C_NONE, C_REG, 36, 16, REGSB},
+ {AMOVBU, C_LEXT, C_NONE, C_REG, 36, 16, REGSB},
+ {AMOVW, C_LAUTO, C_NONE, C_REG, 36, 16, REGSP},
+ {AMOVWU, C_LAUTO, C_NONE, C_REG, 36, 16, REGSP},
+ {AMOVV, C_LAUTO, C_NONE, C_REG, 36, 16, REGSP},
+ {AMOVB, C_LAUTO, C_NONE, C_REG, 36, 16, REGSP},
+ {AMOVBU, C_LAUTO, C_NONE, C_REG, 36, 16, REGSP},
+ {AMOVW, C_LOREG, C_NONE, C_REG, 36, 16, REGZERO},
+ {AMOVWU, C_LOREG, C_NONE, C_REG, 36, 16, REGZERO},
+ {AMOVV, C_LOREG, C_NONE, C_REG, 36, 16, REGZERO},
+ {AMOVB, C_LOREG, C_NONE, C_REG, 36, 16, REGZERO},
+ {AMOVBU, C_LOREG, C_NONE, C_REG, 36, 16, REGZERO},
+ {AMOVW, C_ADDR, C_NONE, C_REG, 51, 12, 0},
+ {AMOVWU, C_ADDR, C_NONE, C_REG, 51, 12, 0},
+ {AMOVV, C_ADDR, C_NONE, C_REG, 51, 12, 0},
+ {AMOVB, C_ADDR, C_NONE, C_REG, 51, 12, 0},
+ {AMOVBU, C_ADDR, C_NONE, C_REG, 51, 12, 0},
+
+ {AMOVW, C_SECON, C_NONE, C_REG, 3, 4, REGSB},
+ {AMOVV, C_SECON, C_NONE, C_REG, 3, 4, REGSB},
+ {AMOVW, C_SACON, C_NONE, C_REG, 3, 4, REGSP},
+ {AMOVV, C_SACON, C_NONE, C_REG, 3, 4, REGSP},
+ {AMOVW, C_LECON, C_NONE, C_REG, 26, 12, REGSB},
+ {AMOVV, C_LECON, C_NONE, C_REG, 26, 12, REGSB},
+ {AMOVW, C_LACON, C_NONE, C_REG, 26, 12, REGSP},
+ {AMOVV, C_LACON, C_NONE, C_REG, 26, 12, REGSP},
+ {AMOVW, C_ADDCON, C_NONE, C_REG, 3, 4, REGZERO},
+ {AMOVV, C_ADDCON, C_NONE, C_REG, 3, 4, REGZERO},
+ {AMOVW, C_ANDCON, C_NONE, C_REG, 3, 4, REGZERO},
+ {AMOVV, C_ANDCON, C_NONE, C_REG, 3, 4, REGZERO},
+
+ {AMOVW, C_UCON, C_NONE, C_REG, 24, 4, 0},
+ {AMOVV, C_UCON, C_NONE, C_REG, 24, 4, 0},
+ {AMOVW, C_LCON, C_NONE, C_REG, 19, 8, 0},
+ {AMOVV, C_LCON, C_NONE, C_REG, 19, 8, 0},
+
+ {AMOVW, C_HI, C_NONE, C_REG, 20, 4, 0},
+ {AMOVV, C_HI, C_NONE, C_REG, 20, 4, 0},
+ {AMOVW, C_LO, C_NONE, C_REG, 20, 4, 0},
+ {AMOVV, C_LO, C_NONE, C_REG, 20, 4, 0},
+ {AMOVW, C_REG, C_NONE, C_HI, 21, 4, 0},
+ {AMOVV, C_REG, C_NONE, C_HI, 21, 4, 0},
+ {AMOVW, C_REG, C_NONE, C_LO, 21, 4, 0},
+ {AMOVV, C_REG, C_NONE, C_LO, 21, 4, 0},
+
+ {AMUL, C_REG, C_REG, C_NONE, 22, 4, 0},
+
+ {AADD, C_ADD0CON, C_REG, C_REG, 4, 4, 0},
+ {AADD, C_ADD0CON, C_NONE, C_REG, 4, 4, 0},
+ {AADD, C_ANDCON, C_REG, C_REG, 10, 8, 0},
+ {AADD, C_ANDCON, C_NONE, C_REG, 10, 8, 0},
+
+ {AAND, C_AND0CON, C_REG, C_REG, 4, 4, 0},
+ {AAND, C_AND0CON, C_NONE, C_REG, 4, 4, 0},
+ {AAND, C_ADDCON, C_REG, C_REG, 10, 8, 0},
+ {AAND, C_ADDCON, C_NONE, C_REG, 10, 8, 0},
+
+ {AADD, C_UCON, C_REG, C_REG, 25, 8, 0},
+ {AADD, C_UCON, C_NONE, C_REG, 25, 8, 0},
+ {AAND, C_UCON, C_REG, C_REG, 25, 8, 0},
+ {AAND, C_UCON, C_NONE, C_REG, 25, 8, 0},
+
+ {AADD, C_LCON, C_NONE, C_REG, 23, 12, 0},
+ {AAND, C_LCON, C_NONE, C_REG, 23, 12, 0},
+ {AADD, C_LCON, C_REG, C_REG, 23, 12, 0},
+ {AAND, C_LCON, C_REG, C_REG, 23, 12, 0},
+
+ {ASLL, C_SCON, C_REG, C_REG, 16, 4, 0},
+ {ASLL, C_SCON, C_NONE, C_REG, 16, 4, 0},
+
+ {ASYSCALL, C_NONE, C_NONE, C_NONE, 5, 4, 0},
+
+ {ABEQ, C_REG, C_REG, C_SBRA, 6, 4, 0},
+ {ABEQ, C_REG, C_NONE, C_SBRA, 6, 4, 0},
+ {ABLEZ, C_REG, C_NONE, C_SBRA, 6, 4, 0},
+ {ABFPT, C_NONE, C_NONE, C_SBRA, 6, 8, 0},
+
+ {AJMP, C_NONE, C_NONE, C_LBRA, 11, 4, 0},
+ {AJAL, C_NONE, C_NONE, C_LBRA, 11, 4, 0},
+
+ {AJMP, C_NONE, C_NONE, C_ZOREG, 18, 4, REGZERO},
+ {AJAL, C_NONE, C_NONE, C_ZOREG, 18, 4, REGLINK},
+
+ {AMOVW, C_SEXT, C_NONE, C_FREG, 27, 4, REGSB},
+ {AMOVF, C_SEXT, C_NONE, C_FREG, 27, 4, REGSB},
+ {AMOVD, C_SEXT, C_NONE, C_FREG, 27, 4, REGSB},
+ {AMOVW, C_SAUTO, C_NONE, C_FREG, 27, 4, REGSP},
+ {AMOVF, C_SAUTO, C_NONE, C_FREG, 27, 4, REGSP},
+ {AMOVD, C_SAUTO, C_NONE, C_FREG, 27, 4, REGSP},
+ {AMOVW, C_SOREG, C_NONE, C_FREG, 27, 4, REGZERO},
+ {AMOVF, C_SOREG, C_NONE, C_FREG, 27, 4, REGZERO},
+ {AMOVD, C_SOREG, C_NONE, C_FREG, 27, 4, REGZERO},
+
+ {AMOVW, C_LEXT, C_NONE, C_FREG, 27, 16, REGSB},
+ {AMOVF, C_LEXT, C_NONE, C_FREG, 27, 16, REGSB},
+ {AMOVD, C_LEXT, C_NONE, C_FREG, 27, 16, REGSB},
+ {AMOVW, C_LAUTO, C_NONE, C_FREG, 27, 16, REGSP},
+ {AMOVF, C_LAUTO, C_NONE, C_FREG, 27, 16, REGSP},
+ {AMOVD, C_LAUTO, C_NONE, C_FREG, 27, 16, REGSP},
+ {AMOVW, C_LOREG, C_NONE, C_FREG, 27, 16, REGZERO},
+ {AMOVF, C_LOREG, C_NONE, C_FREG, 27, 16, REGZERO},
+ {AMOVD, C_LOREG, C_NONE, C_FREG, 27, 16, REGZERO},
+ {AMOVF, C_ADDR, C_NONE, C_FREG, 51, 12, 0},
+ {AMOVD, C_ADDR, C_NONE, C_FREG, 51, 12, 0},
+
+ {AMOVW, C_FREG, C_NONE, C_SEXT, 28, 4, REGSB},
+ {AMOVF, C_FREG, C_NONE, C_SEXT, 28, 4, REGSB},
+ {AMOVD, C_FREG, C_NONE, C_SEXT, 28, 4, REGSB},
+ {AMOVW, C_FREG, C_NONE, C_SAUTO, 28, 4, REGSP},
+ {AMOVF, C_FREG, C_NONE, C_SAUTO, 28, 4, REGSP},
+ {AMOVD, C_FREG, C_NONE, C_SAUTO, 28, 4, REGSP},
+ {AMOVW, C_FREG, C_NONE, C_SOREG, 28, 4, REGZERO},
+ {AMOVF, C_FREG, C_NONE, C_SOREG, 28, 4, REGZERO},
+ {AMOVD, C_FREG, C_NONE, C_SOREG, 28, 4, REGZERO},
+
+ {AMOVW, C_FREG, C_NONE, C_LEXT, 28, 16, REGSB},
+ {AMOVF, C_FREG, C_NONE, C_LEXT, 28, 16, REGSB},
+ {AMOVD, C_FREG, C_NONE, C_LEXT, 28, 16, REGSB},
+ {AMOVW, C_FREG, C_NONE, C_LAUTO, 28, 16, REGSP},
+ {AMOVF, C_FREG, C_NONE, C_LAUTO, 28, 16, REGSP},
+ {AMOVD, C_FREG, C_NONE, C_LAUTO, 28, 16, REGSP},
+ {AMOVW, C_FREG, C_NONE, C_LOREG, 28, 16, REGZERO},
+ {AMOVF, C_FREG, C_NONE, C_LOREG, 28, 16, REGZERO},
+ {AMOVD, C_FREG, C_NONE, C_LOREG, 28, 16, REGZERO},
+ {AMOVF, C_FREG, C_NONE, C_ADDR, 50, 12, 0},
+ {AMOVD, C_FREG, C_NONE, C_ADDR, 50, 12, 0},
+
+ {AMOVW, C_REG, C_NONE, C_FREG, 30, 4, 0},
+ {AMOVW, C_FREG, C_NONE, C_REG, 31, 4, 0},
+ {AMOVV, C_REG, C_NONE, C_FREG, 47, 4, 0},
+ {AMOVV, C_FREG, C_NONE, C_REG, 48, 4, 0},
+
+ {AMOVW, C_ADDCON, C_NONE, C_FREG, 34, 8, 0},
+ {AMOVW, C_ANDCON, C_NONE, C_FREG, 34, 8, 0},
+ {AMOVW, C_UCON, C_NONE, C_FREG, 35, 8, 0},
+ {AMOVW, C_LCON, C_NONE, C_FREG, 36, 12, 0},
+
+ {AMOVW, C_REG, C_NONE, C_MREG, 37, 4, 0},
+ {AMOVV, C_REG, C_NONE, C_MREG, 37, 4, 0},
+ {AMOVW, C_MREG, C_NONE, C_REG, 38, 4, 0},
+ {AMOVV, C_MREG, C_NONE, C_REG, 38, 4, 0},
+
+ {AWORD, C_LCON, C_NONE, C_NONE, 40, 4, 0},
+
+ {AMOVW, C_REG, C_NONE, C_FCREG, 41, 8, 0},
+ {AMOVV, C_REG, C_NONE, C_FCREG, 41, 8, 0},
+ {AMOVW, C_FCREG, C_NONE, C_REG, 42, 4, 0},
+ {AMOVV, C_FCREG, C_NONE, C_REG, 42, 4, 0},
+
+ {ABREAK, C_REG, C_NONE, C_SEXT, 7, 4, REGSB}, /* really CACHE instruction */
+ {ABREAK, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP},
+ {ABREAK, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO},
+ {ABREAK, C_NONE, C_NONE, C_NONE, 5, 4, 0},
+
+ {obj.AUNDEF, C_NONE, C_NONE, C_NONE, 49, 4, 0},
+ {obj.AUSEFIELD, C_ADDR, C_NONE, C_NONE, 0, 0, 0},
+ {obj.APCDATA, C_LCON, C_NONE, C_LCON, 0, 0, 0},
+ {obj.AFUNCDATA, C_SCON, C_NONE, C_ADDR, 0, 0, 0},
+ {obj.ANOP, C_NONE, C_NONE, C_NONE, 0, 0, 0},
+ {obj.ADUFFZERO, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, // same as AJMP
+ {obj.ADUFFCOPY, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, // same as AJMP
+
+ {obj.AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0},
}
type Oprang struct {
var xcmp [C_NCLASS][C_NCLASS]uint8
-func span9(ctxt *obj.Link, cursym *obj.LSym) {
+func span0(ctxt *obj.Link, cursym *obj.LSym) {
p := cursym.Text
if p == nil || p.Link == nil { // handle external functions and ELF section symbols
return
ctxt.Cursym = cursym
ctxt.Autosize = int32(p.To.Offset + 8)
- if oprange[AANDN&obj.AMask].start == nil {
+ if oprange[AOR&obj.AMask].start == nil {
buildop(ctxt)
}
o = oplook(ctxt, p)
// very large conditional branches
- if (o.type_ == 16 || o.type_ == 17) && p.Pcond != nil {
+ if o.type_ == 6 && p.Pcond != nil {
otxt = p.Pcond.Pc - c
- if otxt < -(1<<15)+10 || otxt >= (1<<15)-10 {
+ if otxt < -(1<<17)+10 || otxt >= (1<<17)-10 {
q = ctxt.NewProg()
q.Link = p.Link
p.Link = q
- q.As = ABR
+ q.As = AJMP
+ q.Lineno = p.Lineno
q.To.Type = obj.TYPE_BRANCH
q.Pcond = p.Pcond
p.Pcond = q
q = ctxt.NewProg()
q.Link = p.Link
p.Link = q
- q.As = ABR
+ q.As = AJMP
+ q.Lineno = p.Lineno
q.To.Type = obj.TYPE_BRANCH
q.Pcond = q.Link.Link
- //addnop(p->link);
- //addnop(p);
+ addnop(ctxt, p.Link)
+ addnop(ctxt, p)
bflag = 1
}
}
bp := cursym.P
var i int32
- var out [6]uint32
+ var out [4]uint32
for p := cursym.Text.Link; p != nil; p = p.Link {
ctxt.Pc = p.Pc
ctxt.Curp = p
o = oplook(ctxt, p)
if int(o.size) > 4*len(out) {
- log.Fatalf("out array in span9 is too small, need at least %d for %v", o.size/4, p)
+ log.Fatalf("out array in span0 is too small, need at least %d for %v", o.size/4, p)
}
asmout(ctxt, p, o, out[:])
for i = 0; i < int32(o.size/4); i++ {
if REG_F0 <= a.Reg && a.Reg <= REG_F31 {
return C_FREG
}
- if REG_CR0 <= a.Reg && a.Reg <= REG_CR7 || a.Reg == REG_CR {
- return C_CREG
+ if REG_M0 <= a.Reg && a.Reg <= REG_M31 {
+ return C_MREG
}
- if REG_SPR0 <= a.Reg && a.Reg <= REG_SPR0+1023 {
- switch a.Reg {
- case REG_LR:
- return C_LR
-
- case REG_XER:
- return C_XER
-
- case REG_CTR:
- return C_CTR
- }
-
- return C_SPR
+ if REG_FCR0 <= a.Reg && a.Reg <= REG_FCR31 {
+ return C_FCREG
}
-
- if REG_DCR0 <= a.Reg && a.Reg <= REG_DCR0+1023 {
- return C_SPR
- }
- if a.Reg == REG_FPSCR {
- return C_FPSCR
+ if a.Reg == REG_LO {
+ return C_LO
}
- if a.Reg == REG_MSR {
- return C_MSR
+ if a.Reg == REG_HI {
+ return C_HI
}
return C_GOK
case obj.TYPE_CONST,
obj.TYPE_ADDR:
switch a.Name {
- case obj.TYPE_NONE:
+ case obj.NAME_NONE:
ctxt.Instoffset = a.Offset
if a.Reg != 0 {
if -BIG <= ctxt.Instoffset && ctxt.Instoffset <= BIG {
if isint32(ctxt.Instoffset) || isuint32(uint64(ctxt.Instoffset)) {
return C_LCON
}
- return C_DCON
+ return C_LCON // C_DCON
}
if ctxt.Instoffset >= -0x8000 {
if isint32(ctxt.Instoffset) {
return C_LCON
}
- return C_DCON
+ return C_LCON // C_DCON
case obj.TYPE_BRANCH:
return C_SBRA
}
func oplook(ctxt *obj.Link, p *obj.Prog) *Optab {
+ if oprange[AOR&obj.AMask].start == nil {
+ buildop(ctxt)
+ }
+
a1 := int(p.Optab)
if a1 != 0 {
return &optab[a1-1:][0]
}
a1--
- a3 := C_NONE + 1
- if p.From3 != nil {
- a3 = int(p.From3.Class)
- if a3 == 0 {
- a3 = aclass(ctxt, p.From3) + 1
- p.From3.Class = int8(a3)
- }
+ a3 := int(p.To.Class)
+ if a3 == 0 {
+ a3 = aclass(ctxt, &p.To) + 1
+ p.To.Class = int8(a3)
}
a3--
- a4 := int(p.To.Class)
- if a4 == 0 {
- a4 = aclass(ctxt, &p.To) + 1
- p.To.Class = int8(a4)
- }
-
- a4--
a2 := C_NONE
if p.Reg != 0 {
a2 = C_REG
}
- //print("oplook %v %d %d %d %d\n", p, a1, a2, a3, a4);
+ //print("oplook %P %d %d %d\n", p, a1, a2, a3);
r0 := p.As & obj.AMask
o := oprange[r0].start
e := oprange[r0].stop
c1 := xcmp[a1][:]
c3 := xcmp[a3][:]
- c4 := xcmp[a4][:]
for ; -cap(o) < -cap(e); o = o[1:] {
if int(o[0].a2) == a2 {
if c1[o[0].a1] != 0 {
if c3[o[0].a3] != 0 {
- if c4[o[0].a4] != 0 {
- p.Optab = uint16((-cap(o) + cap(optab)) + 1)
- return &o[0]
- }
+ p.Optab = uint16((-cap(o) + cap(optab)) + 1)
+ return &o[0]
}
}
}
}
- ctxt.Diag("illegal combination %v %v %v %v %v", obj.Aconv(int(p.As)), DRconv(a1), DRconv(a2), DRconv(a3), DRconv(a4))
+ ctxt.Diag("illegal combination %v %v %v %v", obj.Aconv(int(p.As)), DRconv(a1), DRconv(a2), DRconv(a3))
prasm(p)
if o == nil {
o = optab
return true
}
+ case C_ADD0CON:
+ if b == C_ADDCON {
+ return true
+ }
+ fallthrough
+
case C_ADDCON:
if b == C_ZCON || b == C_SCON {
return true
}
- case C_ANDCON:
- if b == C_ZCON || b == C_SCON {
+ case C_AND0CON:
+ if b == C_ANDCON {
return true
}
+ fallthrough
- case C_SPR:
- if b == C_LR || b == C_XER || b == C_CTR {
+ case C_ANDCON:
+ if b == C_ZCON || b == C_SCON {
return true
}
if b == C_ZOREG {
return true
}
-
- case C_ANY:
- return true
}
return false
if n != 0 {
return n < 0
}
- n = int(p1.a4) - int(p2.a4)
- if n != 0 {
- return n < 0
- }
return false
}
func opset(a, b0 int16) {
ctxt.Diag("unknown op in build: %v", obj.Aconv(int(r)))
log.Fatalf("bad code")
- case ADCBF: /* unary indexed: op (b+a); op (b) */
- opset(ADCBI, r0)
-
- opset(ADCBST, r0)
- opset(ADCBT, r0)
- opset(ADCBTST, r0)
- opset(ADCBZ, r0)
- opset(AICBI, r0)
-
- case AECOWX: /* indexed store: op s,(b+a); op s,(b) */
- opset(ASTWCCC, r0)
-
- opset(ASTDCCC, r0)
-
- case AREM: /* macro */
- opset(AREMCC, r0)
-
- opset(AREMV, r0)
- opset(AREMVCC, r0)
-
- case AREMU:
- opset(AREMU, r0)
- opset(AREMUCC, r0)
- opset(AREMUV, r0)
- opset(AREMUVCC, r0)
-
- case AREMD:
- opset(AREMDCC, r0)
- opset(AREMDV, r0)
- opset(AREMDVCC, r0)
-
- case AREMDU:
- opset(AREMDU, r0)
- opset(AREMDUCC, r0)
- opset(AREMDUV, r0)
- opset(AREMDUVCC, r0)
-
- case ADIVW: /* op Rb[,Ra],Rd */
- opset(AMULHW, r0)
-
- opset(AMULHWCC, r0)
- opset(AMULHWU, r0)
- opset(AMULHWUCC, r0)
- opset(AMULLWCC, r0)
- opset(AMULLWVCC, r0)
- opset(AMULLWV, r0)
- opset(ADIVWCC, r0)
- opset(ADIVWV, r0)
- opset(ADIVWVCC, r0)
- opset(ADIVWU, r0)
- opset(ADIVWUCC, r0)
- opset(ADIVWUV, r0)
- opset(ADIVWUVCC, r0)
- opset(AADDCC, r0)
- opset(AADDCV, r0)
- opset(AADDCVCC, r0)
+ case AABSF:
+ opset(AMOVFD, r0)
+ opset(AMOVDF, r0)
+ opset(AMOVWF, r0)
+ opset(AMOVFW, r0)
+ opset(AMOVWD, r0)
+ opset(AMOVDW, r0)
+ opset(ANEGF, r0)
+ opset(ANEGD, r0)
+ opset(AABSD, r0)
+ opset(ATRUNCDW, r0)
+ opset(ATRUNCFW, r0)
+ opset(ATRUNCDV, r0)
+ opset(ATRUNCFV, r0)
+ opset(AMOVVF, r0)
+ opset(AMOVFV, r0)
+ opset(AMOVVD, r0)
+ opset(AMOVDV, r0)
+
+ case AADD:
+ opset(ASGT, r0)
+ opset(ASGTU, r0)
+ opset(AADDU, r0)
opset(AADDV, r0)
- opset(AADDVCC, r0)
- opset(AADDE, r0)
- opset(AADDECC, r0)
- opset(AADDEV, r0)
- opset(AADDEVCC, r0)
- opset(ACRAND, r0)
- opset(ACRANDN, r0)
- opset(ACREQV, r0)
- opset(ACRNAND, r0)
- opset(ACRNOR, r0)
- opset(ACROR, r0)
- opset(ACRORN, r0)
- opset(ACRXOR, r0)
- opset(AMULHD, r0)
- opset(AMULHDCC, r0)
- opset(AMULHDU, r0)
- opset(AMULHDUCC, r0)
- opset(AMULLD, r0)
- opset(AMULLDCC, r0)
- opset(AMULLDVCC, r0)
- opset(AMULLDV, r0)
- opset(ADIVD, r0)
- opset(ADIVDCC, r0)
- opset(ADIVDVCC, r0)
- opset(ADIVDV, r0)
- opset(ADIVDU, r0)
- opset(ADIVDUCC, r0)
- opset(ADIVDUVCC, r0)
- opset(ADIVDUCC, r0)
-
- case AMOVBZ: /* lbz, stz, rlwm(r/r), lhz, lha, stz, and x variants */
- opset(AMOVH, r0)
-
- opset(AMOVHZ, r0)
+ opset(AADDVU, r0)
- case AMOVBZU: /* lbz[x]u, stb[x]u, lhz[x]u, lha[x]u, sth[u]x, ld[x]u, std[u]x */
- opset(AMOVHU, r0)
-
- opset(AMOVHZU, r0)
- opset(AMOVWU, r0)
- opset(AMOVWZU, r0)
- opset(AMOVDU, r0)
- opset(AMOVMW, r0)
-
- case AAND: /* logical op Rb,Rs,Ra; no literal */
- opset(AANDN, r0)
-
- opset(AANDNCC, r0)
- opset(AEQV, r0)
- opset(AEQVCC, r0)
- opset(ANAND, r0)
- opset(ANANDCC, r0)
- opset(ANOR, r0)
- opset(ANORCC, r0)
- opset(AORCC, r0)
- opset(AORN, r0)
- opset(AORNCC, r0)
- opset(AXORCC, r0)
-
- case AADDME: /* op Ra, Rd */
- opset(AADDMECC, r0)
-
- opset(AADDMEV, r0)
- opset(AADDMEVCC, r0)
- opset(AADDZE, r0)
- opset(AADDZECC, r0)
- opset(AADDZEV, r0)
- opset(AADDZEVCC, r0)
- opset(ASUBME, r0)
- opset(ASUBMECC, r0)
- opset(ASUBMEV, r0)
- opset(ASUBMEVCC, r0)
- opset(ASUBZE, r0)
- opset(ASUBZECC, r0)
- opset(ASUBZEV, r0)
- opset(ASUBZEVCC, r0)
-
- case AADDC:
- opset(AADDCCC, r0)
+ case AADDF:
+ opset(ADIVF, r0)
+ opset(ADIVD, r0)
+ opset(AMULF, r0)
+ opset(AMULD, r0)
+ opset(ASUBF, r0)
+ opset(ASUBD, r0)
+ opset(AADDD, r0)
+
+ case AAND:
+ opset(AOR, r0)
+ opset(AXOR, r0)
case ABEQ:
- opset(ABGE, r0)
- opset(ABGT, r0)
- opset(ABLE, r0)
- opset(ABLT, r0)
opset(ABNE, r0)
- opset(ABVC, r0)
- opset(ABVS, r0)
-
- case ABR:
- opset(ABL, r0)
-
- case ABC:
- opset(ABCL, r0)
-
- case AEXTSB: /* op Rs, Ra */
- opset(AEXTSBCC, r0)
-
- opset(AEXTSH, r0)
- opset(AEXTSHCC, r0)
- opset(ACNTLZW, r0)
- opset(ACNTLZWCC, r0)
- opset(ACNTLZD, r0)
- opset(AEXTSW, r0)
- opset(AEXTSWCC, r0)
- opset(ACNTLZDCC, r0)
-
- case AFABS: /* fop [s,]d */
- opset(AFABSCC, r0)
-
- opset(AFNABS, r0)
- opset(AFNABSCC, r0)
- opset(AFNEG, r0)
- opset(AFNEGCC, r0)
- opset(AFRSP, r0)
- opset(AFRSPCC, r0)
- opset(AFCTIW, r0)
- opset(AFCTIWCC, r0)
- opset(AFCTIWZ, r0)
- opset(AFCTIWZCC, r0)
- opset(AFCTID, r0)
- opset(AFCTIDCC, r0)
- opset(AFCTIDZ, r0)
- opset(AFCTIDZCC, r0)
- opset(AFCFID, r0)
- opset(AFCFIDCC, r0)
- opset(AFRES, r0)
- opset(AFRESCC, r0)
- opset(AFRSQRTE, r0)
- opset(AFRSQRTECC, r0)
- opset(AFSQRT, r0)
- opset(AFSQRTCC, r0)
- opset(AFSQRTS, r0)
- opset(AFSQRTSCC, r0)
-
- case AFADD:
- opset(AFADDS, r0)
- opset(AFADDCC, r0)
- opset(AFADDSCC, r0)
- opset(AFDIV, r0)
- opset(AFDIVS, r0)
- opset(AFDIVCC, r0)
- opset(AFDIVSCC, r0)
- opset(AFSUB, r0)
- opset(AFSUBS, r0)
- opset(AFSUBCC, r0)
- opset(AFSUBSCC, r0)
-
- case AFMADD:
- opset(AFMADDCC, r0)
- opset(AFMADDS, r0)
- opset(AFMADDSCC, r0)
- opset(AFMSUB, r0)
- opset(AFMSUBCC, r0)
- opset(AFMSUBS, r0)
- opset(AFMSUBSCC, r0)
- opset(AFNMADD, r0)
- opset(AFNMADDCC, r0)
- opset(AFNMADDS, r0)
- opset(AFNMADDSCC, r0)
- opset(AFNMSUB, r0)
- opset(AFNMSUBCC, r0)
- opset(AFNMSUBS, r0)
- opset(AFNMSUBSCC, r0)
- opset(AFSEL, r0)
- opset(AFSELCC, r0)
-
- case AFMUL:
- opset(AFMULS, r0)
- opset(AFMULCC, r0)
- opset(AFMULSCC, r0)
-
- case AFCMPO:
- opset(AFCMPU, r0)
-
- case AMTFSB0:
- opset(AMTFSB0CC, r0)
- opset(AMTFSB1, r0)
- opset(AMTFSB1CC, r0)
-
- case ANEG: /* op [Ra,] Rd */
- opset(ANEGCC, r0)
-
- opset(ANEGV, r0)
- opset(ANEGVCC, r0)
-
- case AOR: /* or/xor Rb,Rs,Ra; ori/xori $uimm,Rs,Ra; oris/xoris $uimm,Rs,Ra */
- opset(AXOR, r0)
- case ASLW:
- opset(ASLWCC, r0)
- opset(ASRW, r0)
- opset(ASRWCC, r0)
+ case ABLEZ:
+ opset(ABGEZ, r0)
+ opset(ABGEZAL, r0)
+ opset(ABLTZ, r0)
+ opset(ABLTZAL, r0)
+ opset(ABGTZ, r0)
- case ASLD:
- opset(ASLDCC, r0)
- opset(ASRD, r0)
- opset(ASRDCC, r0)
+ case AMOVB:
+ opset(AMOVH, r0)
- case ASRAW: /* sraw Rb,Rs,Ra; srawi sh,Rs,Ra */
- opset(ASRAWCC, r0)
+ case AMOVBU:
+ opset(AMOVHU, r0)
- case ASRAD: /* sraw Rb,Rs,Ra; srawi sh,Rs,Ra */
- opset(ASRADCC, r0)
+ case AMUL:
+ opset(AREM, r0)
+ opset(AREMU, r0)
+ opset(ADIVU, r0)
+ opset(AMULU, r0)
+ opset(ADIV, r0)
+ opset(ADIVV, r0)
+ opset(ADIVVU, r0)
+ opset(AMULV, r0)
+ opset(AMULVU, r0)
+ opset(AREMV, r0)
+ opset(AREMVU, r0)
- case ASUB: /* SUB Ra,Rb,Rd => subf Rd,ra,rb */
- opset(ASUB, r0)
+ case ASLL:
+ opset(ASRL, r0)
+ opset(ASRA, r0)
+ opset(ASLLV, r0)
+ opset(ASRAV, r0)
+ opset(ASRLV, r0)
- opset(ASUBCC, r0)
+ case ASUB:
+ opset(ASUBU, r0)
opset(ASUBV, r0)
- opset(ASUBVCC, r0)
- opset(ASUBCCC, r0)
- opset(ASUBCV, r0)
- opset(ASUBCVCC, r0)
- opset(ASUBE, r0)
- opset(ASUBECC, r0)
- opset(ASUBEV, r0)
- opset(ASUBEVCC, r0)
-
- case ASYNC:
- opset(AISYNC, r0)
- opset(APTESYNC, r0)
- opset(ATLBSYNC, r0)
-
- case ARLWMI:
- opset(ARLWMICC, r0)
- opset(ARLWNM, r0)
- opset(ARLWNMCC, r0)
-
- case ARLDMI:
- opset(ARLDMICC, r0)
-
- case ARLDC:
- opset(ARLDCCC, r0)
-
- case ARLDCL:
- opset(ARLDCR, r0)
- opset(ARLDCLCC, r0)
- opset(ARLDCRCC, r0)
-
- case AFMOVD:
- opset(AFMOVDCC, r0)
- opset(AFMOVDU, r0)
- opset(AFMOVS, r0)
- opset(AFMOVSU, r0)
-
- case AECIWX:
- opset(ALWAR, r0)
- opset(ALDAR, r0)
-
- case ASYSCALL: /* just the op; flow of control */
- opset(ARFI, r0)
-
- opset(ARFCI, r0)
- opset(ARFID, r0)
- opset(AHRFID, r0)
-
- case AMOVHBR:
- opset(AMOVWBR, r0)
-
- case ASLBMFEE:
- opset(ASLBMFEV, r0)
-
- case ATW:
- opset(ATD, r0)
-
- case ATLBIE:
- opset(ASLBIE, r0)
- opset(ATLBIEL, r0)
-
- case AEIEIO:
- opset(ASLBIA, r0)
-
- case ACMP:
- opset(ACMPW, r0)
-
- case ACMPU:
- opset(ACMPWU, r0)
-
- case AADD,
- AANDCC, /* and. Rb,Rs,Ra; andi. $uimm,Rs,Ra; andis. $uimm,Rs,Ra */
- ALSW,
- AMOVW,
- /* load/store/move word with sign extension; special 32-bit move; move 32-bit literals */
- AMOVWZ, /* load/store/move word with zero extension; move 32-bit literals */
- AMOVD, /* load/store/move 64-bit values, including 32-bit literals with/without sign-extension */
- AMOVB, /* macro: move byte with sign extension */
- AMOVBU, /* macro: move byte with sign extension & update */
- AMOVFL,
- AMULLW,
- /* op $s[,r2],r3; op r1[,r2],r3; no cc/v */
- ASUBC, /* op r1,$s,r3; op r1[,r2],r3 */
- ASTSW,
- ASLBMTE,
+ opset(ASUBVU, r0)
+ opset(ANOR, r0)
+
+ case ASYSCALL:
+ opset(ATLBP, r0)
+ opset(ATLBR, r0)
+ opset(ATLBWI, r0)
+ opset(ATLBWR, r0)
+
+ case ACMPEQF:
+ opset(ACMPGTF, r0)
+ opset(ACMPGTD, r0)
+ opset(ACMPGEF, r0)
+ opset(ACMPGED, r0)
+ opset(ACMPEQD, r0)
+
+ case ABFPT:
+ opset(ABFPF, r0)
+
+ case AMOVWL:
+ opset(AMOVWR, r0)
+ opset(AMOVVR, r0)
+ opset(AMOVVL, r0)
+
+ case AMOVW,
+ AMOVD,
+ AMOVF,
+ AMOVV,
+ ABREAK,
+ ARFE,
+ AJAL,
+ AJMP,
+ AMOVWU,
AWORD,
- ADWORD,
obj.ANOP,
obj.ATEXT,
obj.AUNDEF,
}
}
-func OPVCC(o uint32, xo uint32, oe uint32, rc uint32) uint32 {
- return o<<26 | xo<<1 | oe<<10 | rc&1
+func OP(x uint32, y uint32) uint32 {
+ return x<<3 | y<<0
}
-func OPCC(o uint32, xo uint32, rc uint32) uint32 {
- return OPVCC(o, xo, 0, rc)
+func SP(x uint32, y uint32) uint32 {
+ return x<<29 | y<<26
}
-func OP(o uint32, xo uint32) uint32 {
- return OPVCC(o, xo, 0, 0)
+func BCOND(x uint32, y uint32) uint32 {
+ return x<<19 | y<<16
}
-/* the order is dest, a/s, b/imm for both arithmetic and logical operations */
-func AOP_RRR(op uint32, d uint32, a uint32, b uint32) uint32 {
- return op | (d&31)<<21 | (a&31)<<16 | (b&31)<<11
+func MMU(x uint32, y uint32) uint32 {
+ return SP(2, 0) | 16<<21 | x<<3 | y<<0
}
-func AOP_IRR(op uint32, d uint32, a uint32, simm uint32) uint32 {
- return op | (d&31)<<21 | (a&31)<<16 | simm&0xFFFF
+func FPF(x uint32, y uint32) uint32 {
+ return SP(2, 1) | 16<<21 | x<<3 | y<<0
}
-func LOP_RRR(op uint32, a uint32, s uint32, b uint32) uint32 {
- return op | (s&31)<<21 | (a&31)<<16 | (b&31)<<11
+func FPD(x uint32, y uint32) uint32 {
+ return SP(2, 1) | 17<<21 | x<<3 | y<<0
}
-func LOP_IRR(op uint32, a uint32, s uint32, uimm uint32) uint32 {
- return op | (s&31)<<21 | (a&31)<<16 | uimm&0xFFFF
+func FPW(x uint32, y uint32) uint32 {
+ return SP(2, 1) | 20<<21 | x<<3 | y<<0
}
-func OP_BR(op uint32, li uint32, aa uint32) uint32 {
- return op | li&0x03FFFFFC | aa<<1
+func FPV(x uint32, y uint32) uint32 {
+ return SP(2, 1) | 21<<21 | x<<3 | y<<0
}
-func OP_BC(op uint32, bo uint32, bi uint32, bd uint32, aa uint32) uint32 {
- return op | (bo&0x1F)<<21 | (bi&0x1F)<<16 | bd&0xFFFC | aa<<1
+func OP_RRR(op uint32, r1 uint32, r2 uint32, r3 uint32) uint32 {
+ return op | (r1&31)<<16 | (r2&31)<<21 | (r3&31)<<11
}
-func OP_BCR(op uint32, bo uint32, bi uint32) uint32 {
- return op | (bo&0x1F)<<21 | (bi&0x1F)<<16
+func OP_IRR(op uint32, i uint32, r2 uint32, r3 uint32) uint32 {
+ return op | i&0xFFFF | (r2&31)<<21 | (r3&31)<<16
}
-func OP_RLW(op uint32, a uint32, s uint32, sh uint32, mb uint32, me uint32) uint32 {
- return op | (s&31)<<21 | (a&31)<<16 | (sh&31)<<11 | (mb&31)<<6 | (me&31)<<1
+func OP_SRR(op uint32, s uint32, r2 uint32, r3 uint32) uint32 {
+ return op | (s&31)<<6 | (r2&31)<<16 | (r3&31)<<11
}
-const (
- /* each rhs is OPVCC(_, _, _, _) */
- OP_ADD = 31<<26 | 266<<1 | 0<<10 | 0
- OP_ADDI = 14<<26 | 0<<1 | 0<<10 | 0
- OP_ADDIS = 15<<26 | 0<<1 | 0<<10 | 0
- OP_ANDI = 28<<26 | 0<<1 | 0<<10 | 0
- OP_EXTSB = 31<<26 | 954<<1 | 0<<10 | 0
- OP_EXTSH = 31<<26 | 922<<1 | 0<<10 | 0
- OP_EXTSW = 31<<26 | 986<<1 | 0<<10 | 0
- OP_MCRF = 19<<26 | 0<<1 | 0<<10 | 0
- OP_MCRFS = 63<<26 | 64<<1 | 0<<10 | 0
- OP_MCRXR = 31<<26 | 512<<1 | 0<<10 | 0
- OP_MFCR = 31<<26 | 19<<1 | 0<<10 | 0
- OP_MFFS = 63<<26 | 583<<1 | 0<<10 | 0
- OP_MFMSR = 31<<26 | 83<<1 | 0<<10 | 0
- OP_MFSPR = 31<<26 | 339<<1 | 0<<10 | 0
- OP_MFSR = 31<<26 | 595<<1 | 0<<10 | 0
- OP_MFSRIN = 31<<26 | 659<<1 | 0<<10 | 0
- OP_MTCRF = 31<<26 | 144<<1 | 0<<10 | 0
- OP_MTFSF = 63<<26 | 711<<1 | 0<<10 | 0
- OP_MTFSFI = 63<<26 | 134<<1 | 0<<10 | 0
- OP_MTMSR = 31<<26 | 146<<1 | 0<<10 | 0
- OP_MTMSRD = 31<<26 | 178<<1 | 0<<10 | 0
- OP_MTSPR = 31<<26 | 467<<1 | 0<<10 | 0
- OP_MTSR = 31<<26 | 210<<1 | 0<<10 | 0
- OP_MTSRIN = 31<<26 | 242<<1 | 0<<10 | 0
- OP_MULLW = 31<<26 | 235<<1 | 0<<10 | 0
- OP_MULLD = 31<<26 | 233<<1 | 0<<10 | 0
- OP_OR = 31<<26 | 444<<1 | 0<<10 | 0
- OP_ORI = 24<<26 | 0<<1 | 0<<10 | 0
- OP_ORIS = 25<<26 | 0<<1 | 0<<10 | 0
- OP_RLWINM = 21<<26 | 0<<1 | 0<<10 | 0
- OP_SUBF = 31<<26 | 40<<1 | 0<<10 | 0
- OP_RLDIC = 30<<26 | 4<<1 | 0<<10 | 0
- OP_RLDICR = 30<<26 | 2<<1 | 0<<10 | 0
- OP_RLDICL = 30<<26 | 0<<1 | 0<<10 | 0
-)
-
-func oclass(a *obj.Addr) int {
- return int(a.Class) - 1
+func OP_FRRR(op uint32, r1 uint32, r2 uint32, r3 uint32) uint32 {
+ return op | (r1&31)<<16 | (r2&31)<<11 | (r3&31)<<6
}
-// add R_ADDRPOWER relocation to symbol s for the two instructions o1 and o2.
-func addaddrreloc(ctxt *obj.Link, s *obj.LSym, o1 *uint32, o2 *uint32) {
- rel := obj.Addrel(ctxt.Cursym)
- rel.Off = int32(ctxt.Pc)
- rel.Siz = 8
- rel.Sym = s
- rel.Add = int64(uint64(*o1)<<32 | uint64(uint32(*o2)))
- rel.Type = obj.R_ADDRPOWER
+func OP_JMP(op uint32, i uint32) uint32 {
+ return op | i&0x3FFFFFF
}
-/*
- * 32-bit masks
- */
-func getmask(m []byte, v uint32) bool {
- m[1] = 0
- m[0] = m[1]
- if v != ^uint32(0) && v&(1<<31) != 0 && v&1 != 0 { /* MB > ME */
- if getmask(m, ^v) {
- i := int(m[0])
- m[0] = m[1] + 1
- m[1] = byte(i - 1)
- return true
- }
-
- return false
- }
-
- for i := 0; i < 32; i++ {
- if v&(1<<uint(31-i)) != 0 {
- m[0] = byte(i)
- for {
- m[1] = byte(i)
- i++
- if i >= 32 || v&(1<<uint(31-i)) == 0 {
- break
- }
- }
-
- for ; i < 32; i++ {
- if v&(1<<uint(31-i)) != 0 {
- return false
- }
- }
- return true
- }
- }
-
- return false
-}
-
-func maskgen(ctxt *obj.Link, p *obj.Prog, m []byte, v uint32) {
- if !getmask(m, v) {
- ctxt.Diag("cannot generate mask #%x\n%v", v, p)
- }
-}
-
-/*
- * 64-bit masks (rldic etc)
- */
-func getmask64(m []byte, v uint64) bool {
- m[1] = 0
- m[0] = m[1]
- for i := 0; i < 64; i++ {
- if v&(uint64(1)<<uint(63-i)) != 0 {
- m[0] = byte(i)
- for {
- m[1] = byte(i)
- i++
- if i >= 64 || v&(uint64(1)<<uint(63-i)) == 0 {
- break
- }
- }
-
- for ; i < 64; i++ {
- if v&(uint64(1)<<uint(63-i)) != 0 {
- return false
- }
- }
- return true
- }
- }
-
- return false
-}
-
-func maskgen64(ctxt *obj.Link, p *obj.Prog, m []byte, v uint64) {
- if !getmask64(m, v) {
- ctxt.Diag("cannot generate mask #%x\n%v", v, p)
- }
-}
-
-func loadu32(r int, d int64) uint32 {
- v := int32(d >> 16)
- if isuint32(uint64(d)) {
- return LOP_IRR(OP_ORIS, uint32(r), REGZERO, uint32(v))
- }
- return AOP_IRR(OP_ADDIS, uint32(r), REGZERO, uint32(v))
-}
-
-func high16adjusted(d int32) uint16 {
- if d&0x8000 != 0 {
- return uint16((d >> 16) + 1)
- }
- return uint16(d >> 16)
+func oclass(a *obj.Addr) int {
+ return int(a.Class) - 1
}
func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
o2 := uint32(0)
o3 := uint32(0)
o4 := uint32(0)
- o5 := uint32(0)
- //print("%v => case %d\n", p, o->type);
switch o.type_ {
default:
- ctxt.Diag("unknown type %d", o.type_)
+ ctxt.Diag("unknown type %d %v", o.type_)
prasm(p)
case 0: /* pseudo ops */
break
- case 1: /* mov r1,r2 ==> OR Rs,Rs,Ra */
- if p.To.Reg == REGZERO && p.From.Type == obj.TYPE_CONST {
- v := regoff(ctxt, &p.From)
- if r0iszero != 0 /*TypeKind(100016)*/ && v != 0 {
- //nerrors--;
- ctxt.Diag("literal operation on R0\n%v", p)
- }
-
- o1 = LOP_IRR(OP_ADDI, REGZERO, REGZERO, uint32(v))
- break
- }
-
- o1 = LOP_RRR(OP_OR, uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.From.Reg))
+ case 1: /* mov r1,r2 ==> OR r1,r0,r2 */
+ o1 = OP_RRR(oprrr(ctxt, AOR), uint32(p.From.Reg), uint32(REGZERO), uint32(p.To.Reg))
- case 2: /* int/cr/fp op Rb,[Ra],Rd */
+ case 2: /* add/sub r1,[r2],r3 */
r := int(p.Reg)
if r == 0 {
r = int(p.To.Reg)
}
- o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(p.From.Reg))
+ o1 = OP_RRR(oprrr(ctxt, int(p.As)), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
- case 3: /* mov $soreg/addcon/ucon, r ==> addis/addi $i,reg',r */
- d := vregoff(ctxt, &p.From)
+ case 3: /* mov $soreg, r ==> or/add $i,o,r */
+ v := regoff(ctxt, &p.From)
- v := int32(d)
r := int(p.From.Reg)
if r == 0 {
r = int(o.param)
}
- if r0iszero != 0 /*TypeKind(100016)*/ && p.To.Reg == 0 && (r != 0 || v != 0) {
- ctxt.Diag("literal operation on R0\n%v", p)
- }
- a := OP_ADDI
- if o.a1 == C_UCON {
- if d&0xffff != 0 {
- log.Fatalf("invalid handling of %v", p)
- }
- v >>= 16
- if r == REGZERO && isuint32(uint64(d)) {
- o1 = LOP_IRR(OP_ORIS, uint32(p.To.Reg), REGZERO, uint32(v))
- break
- }
-
- a = OP_ADDIS
- } else {
- if int64(int16(d)) != d {
- log.Fatalf("invalid handling of %v", p)
- }
+ a := AADDVU
+ if o.a1 == C_ANDCON {
+ a = AOR
}
- o1 = AOP_IRR(uint32(a), uint32(p.To.Reg), uint32(r), uint32(v))
+ o1 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(r), uint32(p.To.Reg))
- case 4: /* add/mul $scon,[r1],r2 */
+ case 4: /* add $scon,[r1],r2 */
v := regoff(ctxt, &p.From)
r := int(p.Reg)
if r == 0 {
r = int(p.To.Reg)
}
- if r0iszero != 0 /*TypeKind(100016)*/ && p.To.Reg == 0 {
- ctxt.Diag("literal operation on R0\n%v", p)
- }
- if int32(int16(v)) != v {
- log.Fatalf("mishandled instruction %v", p)
- }
- o1 = AOP_IRR(uint32(opirr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(v))
+
+ o1 = OP_IRR(opirr(ctxt, int(p.As)), uint32(v), uint32(r), uint32(p.To.Reg))
case 5: /* syscall */
o1 = uint32(oprrr(ctxt, int(p.As)))
- case 6: /* logical op Rb,[Rs,]Ra; no literal */
- r := int(p.Reg)
-
- if r == 0 {
- r = int(p.To.Reg)
+ case 6: /* beq r1,[r2],sbra */
+ v := int32(0)
+ if p.Pcond == nil {
+ v = int32(-4) >> 2
+ } else {
+ v = int32(p.Pcond.Pc-p.Pc-4) >> 2
+ }
+ if (v<<16)>>16 != v {
+ ctxt.Diag("short branch too far\n%v", p)
}
- o1 = LOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(p.From.Reg))
+ o1 = OP_IRR(opirr(ctxt, int(p.As)), uint32(v), uint32(p.From.Reg), uint32(p.Reg))
+ // for ABFPT and ABFPF only: always fill delay slot with 0
+ // see comments in func preprocess for details.
+ o2 = 0
- case 7: /* mov r, soreg ==> stw o(r) */
+ case 7: /* mov r, soreg ==> sw o(r) */
r := int(p.To.Reg)
-
if r == 0 {
r = int(o.param)
}
v := regoff(ctxt, &p.To)
- if p.To.Type == obj.TYPE_MEM && p.To.Index != 0 {
- if v != 0 {
- ctxt.Diag("illegal indexed instruction\n%v", p)
- }
- o1 = AOP_RRR(uint32(opstorex(ctxt, int(p.As))), uint32(p.From.Reg), uint32(p.To.Index), uint32(r))
- } else {
- if int32(int16(v)) != v {
- log.Fatalf("mishandled instruction %v", p)
- }
- o1 = AOP_IRR(uint32(opstore(ctxt, int(p.As))), uint32(p.From.Reg), uint32(r), uint32(v))
- }
+ o1 = OP_IRR(opirr(ctxt, int(p.As)), uint32(v), uint32(r), uint32(p.From.Reg))
- case 8: /* mov soreg, r ==> lbz/lhz/lwz o(r) */
+ case 8: /* mov soreg, r ==> lw o(r) */
r := int(p.From.Reg)
-
if r == 0 {
r = int(o.param)
}
v := regoff(ctxt, &p.From)
- if p.From.Type == obj.TYPE_MEM && p.From.Index != 0 {
- if v != 0 {
- ctxt.Diag("illegal indexed instruction\n%v", p)
- }
- o1 = AOP_RRR(uint32(oploadx(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.From.Index), uint32(r))
- } else {
- if int32(int16(v)) != v {
- log.Fatalf("mishandled instruction %v", p)
- }
- o1 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(v))
- }
+ o1 = OP_IRR(opirr(ctxt, int(p.As)+ALAST), uint32(v), uint32(r), uint32(p.To.Reg))
- case 9: /* movb soreg, r ==> lbz o(r),r2; extsb r2,r2 */
- r := int(p.From.Reg)
+ case 9: /* sll r1,[r2],r3 */
+ r := int(p.Reg)
if r == 0 {
- r = int(o.param)
+ r = int(p.To.Reg)
}
+ o1 = OP_RRR(oprrr(ctxt, int(p.As)), uint32(r), uint32(p.From.Reg), uint32(p.To.Reg))
+
+ case 10: /* add $con,[r1],r2 ==> mov $con, t; add t,[r1],r2 */
v := regoff(ctxt, &p.From)
- if p.From.Type == obj.TYPE_MEM && p.From.Index != 0 {
- if v != 0 {
- ctxt.Diag("illegal indexed instruction\n%v", p)
- }
- o1 = AOP_RRR(uint32(oploadx(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.From.Index), uint32(r))
- } else {
- o1 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(v))
+ a := AOR
+ if v < 0 {
+ a = AADDU
}
- o2 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.To.Reg), 0)
-
- case 10: /* sub Ra,[Rb],Rd => subf Rd,Ra,Rb */
+ o1 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(0), uint32(REGTMP))
r := int(p.Reg)
-
if r == 0 {
r = int(p.To.Reg)
}
- o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.From.Reg), uint32(r))
+ o2 = OP_RRR(oprrr(ctxt, int(p.As)), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
- case 11: /* br/bl lbra */
+ case 11: /* jmp lbra */
v := int32(0)
-
- if p.Pcond != nil {
- v = int32(p.Pcond.Pc - p.Pc)
- if v&03 != 0 {
- ctxt.Diag("odd branch target address\n%v", p)
- v &^= 03
- }
-
- if v < -(1<<25) || v >= 1<<24 {
- ctxt.Diag("branch too far\n%v", p)
- }
- }
-
- o1 = OP_BR(uint32(opirr(ctxt, int(p.As))), uint32(v), 0)
- if p.To.Sym != nil {
- rel := obj.Addrel(ctxt.Cursym)
- rel.Off = int32(ctxt.Pc)
- rel.Siz = 4
- rel.Sym = p.To.Sym
- v += int32(p.To.Offset)
- if v&03 != 0 {
- ctxt.Diag("odd branch target address\n%v", p)
- v &^= 03
+ if aclass(ctxt, &p.To) == C_SBRA && p.To.Sym == nil && p.As == AJMP {
+ // use PC-relative branch for short branches
+ // BEQ R0, R0, sbra
+ if p.Pcond == nil {
+ v = int32(-4) >> 2
+ } else {
+ v = int32(p.Pcond.Pc-p.Pc-4) >> 2
}
-
- rel.Add = int64(v)
- rel.Type = obj.R_CALLPOWER
- }
-
- case 12: /* movb r,r (extsb); movw r,r (extsw) */
- if p.To.Reg == REGZERO && p.From.Type == obj.TYPE_CONST {
- v := regoff(ctxt, &p.From)
- if r0iszero != 0 /*TypeKind(100016)*/ && v != 0 {
- ctxt.Diag("literal operation on R0\n%v", p)
+ if (v<<16)>>16 == v {
+ o1 = OP_IRR(opirr(ctxt, ABEQ), uint32(v), uint32(REGZERO), uint32(REGZERO))
+ break
}
-
- o1 = LOP_IRR(OP_ADDI, REGZERO, REGZERO, uint32(v))
- break
}
-
- if p.As == AMOVW {
- o1 = LOP_RRR(OP_EXTSW, uint32(p.To.Reg), uint32(p.From.Reg), 0)
+ if p.Pcond == nil {
+ v = int32(p.Pc) >> 2
} else {
- o1 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.From.Reg), 0)
- }
-
- case 13: /* mov[bhw]z r,r; uses rlwinm not andi. to avoid changing CC */
- if p.As == AMOVBZ {
- o1 = OP_RLW(OP_RLWINM, uint32(p.To.Reg), uint32(p.From.Reg), 0, 24, 31)
- } else if p.As == AMOVH {
- o1 = LOP_RRR(OP_EXTSH, uint32(p.To.Reg), uint32(p.From.Reg), 0)
- } else if p.As == AMOVHZ {
- o1 = OP_RLW(OP_RLWINM, uint32(p.To.Reg), uint32(p.From.Reg), 0, 16, 31)
- } else if p.As == AMOVWZ {
- o1 = OP_RLW(OP_RLDIC, uint32(p.To.Reg), uint32(p.From.Reg), 0, 0, 0) | 1<<5 /* MB=32 */
+ v = int32(p.Pcond.Pc) >> 2
+ }
+ o1 = OP_JMP(opirr(ctxt, int(p.As)), uint32(v))
+ if p.To.Sym == nil {
+ p.To.Sym = ctxt.Cursym.Text.From.Sym
+ p.To.Offset = p.Pcond.Pc
+ }
+ rel := obj.Addrel(ctxt.Cursym)
+ rel.Off = int32(ctxt.Pc)
+ rel.Siz = 4
+ rel.Sym = p.To.Sym
+ rel.Add = p.To.Offset
+ if p.As == AJAL {
+ rel.Type = obj.R_CALLMIPS
} else {
- ctxt.Diag("internal: bad mov[bhw]z\n%v", p)
- }
-
- case 14: /* rldc[lr] Rb,Rs,$mask,Ra -- left, right give different masks */
- r := int(p.Reg)
-
- if r == 0 {
- r = int(p.To.Reg)
- }
- d := vregoff(ctxt, p.From3)
- var mask [2]uint8
- maskgen64(ctxt, p, mask[:], uint64(d))
- var a int
- switch p.As {
- case ARLDCL, ARLDCLCC:
- a = int(mask[0]) /* MB */
- if mask[1] != 63 {
- ctxt.Diag("invalid mask for rotate: %x (end != bit 63)\n%v", uint64(d), p)
- }
-
- case ARLDCR, ARLDCRCC:
- a = int(mask[1]) /* ME */
- if mask[0] != 0 {
- ctxt.Diag("invalid mask for rotate: %x (start != 0)\n%v", uint64(d), p)
- }
-
- default:
- ctxt.Diag("unexpected op in rldc case\n%v", p)
- a = 0
+ rel.Type = obj.R_JMPMIPS
}
- o1 = LOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(p.From.Reg))
- o1 |= (uint32(a) & 31) << 6
- if a&0x20 != 0 {
- o1 |= 1 << 5 /* mb[5] is top bit */
+ case 12: /* movbs r,r */
+ v := 16
+ if p.As == AMOVB {
+ v = 24
}
+ o1 = OP_SRR(opirr(ctxt, ASLL), uint32(v), uint32(p.From.Reg), uint32(p.To.Reg))
+ o2 = OP_SRR(opirr(ctxt, ASRA), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg))
- case 17, /* bc bo,bi,lbra (same for now) */
- 16: /* bc bo,bi,sbra */
- a := 0
-
- if p.From.Type == obj.TYPE_CONST {
- a = int(regoff(ctxt, &p.From))
- }
- r := int(p.Reg)
- if r == 0 {
- r = 0
- }
- v := int32(0)
- if p.Pcond != nil {
- v = int32(p.Pcond.Pc - p.Pc)
- }
- if v&03 != 0 {
- ctxt.Diag("odd branch target address\n%v", p)
- v &^= 03
- }
-
- if v < -(1<<16) || v >= 1<<15 {
- ctxt.Diag("branch too far\n%v", p)
- }
- o1 = OP_BC(uint32(opirr(ctxt, int(p.As))), uint32(a), uint32(r), uint32(v), 0)
-
- case 15: /* br/bl (r) => mov r,lr; br/bl (lr) */
- var v int32
- if p.As == ABC || p.As == ABCL {
- v = regoff(ctxt, &p.To) & 31
+ case 13: /* movbu r,r */
+ if p.As == AMOVBU {
+ o1 = OP_IRR(opirr(ctxt, AAND), uint32(0xff), uint32(p.From.Reg), uint32(p.To.Reg))
} else {
- v = 20 /* unconditional */
- }
- o1 = AOP_RRR(OP_MTSPR, uint32(p.To.Reg), 0, 0) | (REG_LR&0x1f)<<16 | ((REG_LR>>5)&0x1f)<<11
- o2 = OPVCC(19, 16, 0, 0)
- if p.As == ABL || p.As == ABCL {
- o2 |= 1
- }
- o2 = OP_BCR(o2, uint32(v), uint32(p.To.Index))
-
- case 18: /* br/bl (lr/ctr); bc/bcl bo,bi,(lr/ctr) */
- var v int32
- if p.As == ABC || p.As == ABCL {
- v = regoff(ctxt, &p.From) & 31
- } else {
- v = 20 /* unconditional */
- }
- r := int(p.Reg)
- if r == 0 {
- r = 0
- }
- switch oclass(&p.To) {
- case C_CTR:
- o1 = OPVCC(19, 528, 0, 0)
-
- case C_LR:
- o1 = OPVCC(19, 16, 0, 0)
-
- default:
- ctxt.Diag("bad optab entry (18): %d\n%v", p.To.Class, p)
- v = 0
- }
-
- if p.As == ABL || p.As == ABCL {
- o1 |= 1
+ o1 = OP_IRR(opirr(ctxt, AAND), uint32(0xffff), uint32(p.From.Reg), uint32(p.To.Reg))
}
- o1 = OP_BCR(o1, uint32(v), uint32(r))
- case 19: /* mov $lcon,r ==> cau+or */
- d := vregoff(ctxt, &p.From)
-
- if p.From.Sym == nil {
- o1 = loadu32(int(p.To.Reg), d)
- o2 = LOP_IRR(OP_ORI, uint32(p.To.Reg), uint32(p.To.Reg), uint32(int32(d)))
+ case 14: /* movwu r,r */
+ o1 = OP_SRR(opirr(ctxt, ASLLV+ALAST), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg))
+ if p.As == AMOVWU {
+ o2 = OP_SRR(opirr(ctxt, ASRLV+ALAST), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg))
} else {
- o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(high16adjusted(int32(d))))
- o2 = AOP_IRR(OP_ADDI, uint32(p.To.Reg), REGTMP, uint32(d))
- addaddrreloc(ctxt, p.From.Sym, &o1, &o2)
+ o2 = OP_SRR(opirr(ctxt, ASRAV+ALAST), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg))
}
- //if(dlm) reloc(&p->from, p->pc, 0);
-
- case 20: /* add $ucon,,r */
+ case 16: /* sll $c,[r1],r2 */
v := regoff(ctxt, &p.From)
-
- r := int(p.Reg)
- if r == 0 {
- r = int(p.To.Reg)
- }
- if p.As == AADD && (r0iszero == 0 /*TypeKind(100016)*/ && p.Reg == 0 || r0iszero != 0 /*TypeKind(100016)*/ && p.To.Reg == 0) {
- ctxt.Diag("literal operation on R0\n%v", p)
- }
- o1 = AOP_IRR(uint32(opirr(ctxt, int(p.As)+ALAST)), uint32(p.To.Reg), uint32(r), uint32(v)>>16)
-
- case 22: /* add $lcon,r1,r2 ==> cau+or+add */ /* could do add/sub more efficiently */
- if p.To.Reg == REGTMP || p.Reg == REGTMP {
- ctxt.Diag("cant synthesize large constant\n%v", p)
- }
- d := vregoff(ctxt, &p.From)
- o1 = loadu32(REGTMP, d)
- o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, uint32(int32(d)))
r := int(p.Reg)
if r == 0 {
r = int(p.To.Reg)
}
- o3 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(r))
- if p.From.Sym != nil {
- ctxt.Diag("%v is not supported", p)
- }
-
- //if(dlm) reloc(&p->from, p->pc, 0);
- case 23: /* and $lcon,r1,r2 ==> cau+or+and */ /* masks could be done using rlnm etc. */
- if p.To.Reg == REGTMP || p.Reg == REGTMP {
- ctxt.Diag("cant synthesize large constant\n%v", p)
- }
- d := vregoff(ctxt, &p.From)
- o1 = loadu32(REGTMP, d)
- o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, uint32(int32(d)))
- r := int(p.Reg)
- if r == 0 {
- r = int(p.To.Reg)
- }
- o3 = LOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(r))
- if p.From.Sym != nil {
- ctxt.Diag("%v is not supported", p)
+ /* OP_SRR will use only the low 5 bits of the shift value */
+ if v >= 32 && vshift(p.As) {
+ o1 = OP_SRR(opirr(ctxt, int(p.As)+ALAST), uint32(v-32), uint32(r), uint32(p.To.Reg))
+ } else {
+ o1 = OP_SRR(opirr(ctxt, int(p.As)), uint32(v), uint32(r), uint32(p.To.Reg))
}
- //if(dlm) reloc(&p->from, p->pc, 0);
-
- /*24*/
- case 25:
- /* sld[.] $sh,rS,rA -> rldicr[.] $sh,rS,mask(0,63-sh),rA; srd[.] -> rldicl */
- v := regoff(ctxt, &p.From)
-
- if v < 0 {
- v = 0
- } else if v > 63 {
- v = 63
- }
+ case 18: /* jmp [r1],0(r2) */
r := int(p.Reg)
- if r == 0 {
- r = int(p.To.Reg)
- }
- var a int
- switch p.As {
- case ASLD, ASLDCC:
- a = int(63 - v)
- o1 = OP_RLDICR
-
- case ASRD, ASRDCC:
- a = int(v)
- v = 64 - v
- o1 = OP_RLDICL
-
- default:
- ctxt.Diag("unexpected op in sldi case\n%v", p)
- a = 0
- o1 = 0
- }
-
- o1 = AOP_RRR(o1, uint32(r), uint32(p.To.Reg), (uint32(v) & 0x1F))
- o1 |= (uint32(a) & 31) << 6
- if v&0x20 != 0 {
- o1 |= 1 << 1
- }
- if a&0x20 != 0 {
- o1 |= 1 << 5 /* mb[5] is top bit */
- }
- if p.As == ASLDCC || p.As == ASRDCC {
- o1 |= 1 /* Rc */
- }
-
- case 26: /* mov $lsext/auto/oreg,,r2 ==> addis+addi */
- if p.To.Reg == REGTMP {
- ctxt.Diag("can't synthesize large constant\n%v", p)
- }
- v := regoff(ctxt, &p.From)
- r := int(p.From.Reg)
if r == 0 {
r = int(o.param)
}
- o1 = AOP_IRR(OP_ADDIS, REGTMP, uint32(r), uint32(high16adjusted(v)))
- o2 = AOP_IRR(OP_ADDI, uint32(p.To.Reg), REGTMP, uint32(v))
-
- case 27: /* subc ra,$simm,rd => subfic rd,ra,$simm */
- v := regoff(ctxt, p.From3)
-
- r := int(p.From.Reg)
- o1 = AOP_IRR(uint32(opirr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(v))
+ o1 = OP_RRR(oprrr(ctxt, int(p.As)), uint32(0), uint32(p.To.Reg), uint32(r))
+ rel := obj.Addrel(ctxt.Cursym)
+ rel.Off = int32(ctxt.Pc)
+ rel.Siz = 0
+ rel.Type = obj.R_CALLIND
- case 28: /* subc r1,$lcon,r2 ==> cau+or+subfc */
- if p.To.Reg == REGTMP || p.From.Reg == REGTMP {
- ctxt.Diag("can't synthesize large constant\n%v", p)
- }
- v := regoff(ctxt, p.From3)
- o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(v)>>16)
- o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, uint32(v))
- o3 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.From.Reg), REGTMP)
- if p.From.Sym != nil {
- ctxt.Diag("%v is not supported", p)
- }
-
- //if(dlm) reloc(&p->from3, p->pc, 0);
-
- case 29: /* rldic[lr]? $sh,s,$mask,a -- left, right, plain give different masks */
+ case 19: /* mov $lcon,r ==> lu+or */
v := regoff(ctxt, &p.From)
-
- d := vregoff(ctxt, p.From3)
- var mask [2]uint8
- maskgen64(ctxt, p, mask[:], uint64(d))
- var a int
- switch p.As {
- case ARLDC, ARLDCCC:
- a = int(mask[0]) /* MB */
- if int32(mask[1]) != (63 - v) {
- ctxt.Diag("invalid mask for shift: %x (shift %d)\n%v", uint64(d), v, p)
- }
-
- case ARLDCL, ARLDCLCC:
- a = int(mask[0]) /* MB */
- if mask[1] != 63 {
- ctxt.Diag("invalid mask for shift: %x (shift %d)\n%v", uint64(d), v, p)
- }
-
- case ARLDCR, ARLDCRCC:
- a = int(mask[1]) /* ME */
- if mask[0] != 0 {
- ctxt.Diag("invalid mask for shift: %x (shift %d)\n%v", uint64(d), v, p)
- }
-
- default:
- ctxt.Diag("unexpected op in rldic case\n%v", p)
- a = 0
- }
-
- o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(p.Reg), uint32(p.To.Reg), (uint32(v) & 0x1F))
- o1 |= (uint32(a) & 31) << 6
- if v&0x20 != 0 {
- o1 |= 1 << 1
- }
- if a&0x20 != 0 {
- o1 |= 1 << 5 /* mb[5] is top bit */
- }
-
- case 30: /* rldimi $sh,s,$mask,a */
- v := regoff(ctxt, &p.From)
-
- d := vregoff(ctxt, p.From3)
- var mask [2]uint8
- maskgen64(ctxt, p, mask[:], uint64(d))
- if int32(mask[1]) != (63 - v) {
- ctxt.Diag("invalid mask for shift: %x (shift %d)\n%v", uint64(d), v, p)
- }
- o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(p.Reg), uint32(p.To.Reg), (uint32(v) & 0x1F))
- o1 |= (uint32(mask[0]) & 31) << 6
- if v&0x20 != 0 {
- o1 |= 1 << 1
- }
- if mask[0]&0x20 != 0 {
- o1 |= 1 << 5 /* mb[5] is top bit */
- }
-
- case 31: /* dword */
- d := vregoff(ctxt, &p.From)
-
- if ctxt.Arch.ByteOrder == binary.BigEndian {
- o1 = uint32(d >> 32)
- o2 = uint32(d)
- } else {
- o1 = uint32(d)
- o2 = uint32(d >> 32)
- }
-
+ o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(p.To.Reg))
+ o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg))
if p.From.Sym != nil {
rel := obj.Addrel(ctxt.Cursym)
rel.Off = int32(ctxt.Pc)
rel.Siz = 8
rel.Sym = p.From.Sym
rel.Add = p.From.Offset
- rel.Type = obj.R_ADDR
- o2 = 0
- o1 = o2
+ rel.Type = obj.R_ADDRMIPS
}
- case 32: /* fmul frc,fra,frd */
- r := int(p.Reg)
-
- if r == 0 {
- r = int(p.To.Reg)
+ case 20: /* mov lo/hi,r */
+ a := OP(2, 0) /* mfhi */
+ if p.From.Reg == REG_LO {
+ a = OP(2, 2) /* mflo */
}
- o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), 0) | (uint32(p.From.Reg)&31)<<6
+ o1 = OP_RRR(a, uint32(REGZERO), uint32(REGZERO), uint32(p.To.Reg))
- case 33: /* fabs [frb,]frd; fmr. frb,frd */
- r := int(p.From.Reg)
-
- if oclass(&p.From) == C_NONE {
- r = int(p.To.Reg)
+ case 21: /* mov r,lo/hi */
+ a := OP(2, 1) /* mthi */
+ if p.To.Reg == REG_LO {
+ a = OP(2, 3) /* mtlo */
}
- o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), 0, uint32(r))
+ o1 = OP_RRR(a, uint32(REGZERO), uint32(p.From.Reg), uint32(REGZERO))
- case 34: /* FMADDx fra,frb,frc,frd (d=a*b+c); FSELx a<0? (d=b): (d=c) */
- o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg)) | (uint32(p.From3.Reg)&31)<<6
+ case 22: /* mul r1,r2 */
+ o1 = OP_RRR(oprrr(ctxt, int(p.As)), uint32(p.From.Reg), uint32(p.Reg), uint32(REGZERO))
- case 35: /* mov r,lext/lauto/loreg ==> cau $(v>>16),sb,r'; store o(r') */
- v := regoff(ctxt, &p.To)
-
- r := int(p.To.Reg)
+ case 23: /* add $lcon,r1,r2 ==> lu+or+add */
+ v := regoff(ctxt, &p.From)
+ o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
+ o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
+ r := int(p.Reg)
if r == 0 {
- r = int(o.param)
+ r = int(p.To.Reg)
}
- o1 = AOP_IRR(OP_ADDIS, REGTMP, uint32(r), uint32(high16adjusted(v)))
- o2 = AOP_IRR(uint32(opstore(ctxt, int(p.As))), uint32(p.From.Reg), REGTMP, uint32(v))
+ o3 = OP_RRR(oprrr(ctxt, int(p.As)), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
- case 36: /* mov bz/h/hz lext/lauto/lreg,r ==> lbz/lha/lhz etc */
+ case 24: /* mov $ucon,r ==> lu r */
v := regoff(ctxt, &p.From)
+ o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(p.To.Reg))
- r := int(p.From.Reg)
+ case 25: /* add/and $ucon,[r1],r2 ==> lu $con,t; add t,[r1],r2 */
+ v := regoff(ctxt, &p.From)
+ o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
+ r := int(p.Reg)
if r == 0 {
- r = int(o.param)
+ r = int(p.To.Reg)
}
- o1 = AOP_IRR(OP_ADDIS, REGTMP, uint32(r), uint32(high16adjusted(v)))
- o2 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(v))
+ o2 = OP_RRR(oprrr(ctxt, int(p.As)), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
- case 37: /* movb lext/lauto/lreg,r ==> lbz o(reg),r; extsb r */
+ case 26: /* mov $lsext/auto/oreg,r ==> lu+or+add */
v := regoff(ctxt, &p.From)
-
+ o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
+ o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
r := int(p.From.Reg)
if r == 0 {
r = int(o.param)
}
- o1 = AOP_IRR(OP_ADDIS, REGTMP, uint32(r), uint32(high16adjusted(v)))
- o2 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(v))
- o3 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.To.Reg), 0)
+ o3 = OP_RRR(oprrr(ctxt, AADDVU), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
- case 40: /* word */
- o1 = uint32(regoff(ctxt, &p.From))
-
- case 41: /* stswi */
- o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(p.From.Reg), uint32(p.To.Reg), 0) | (uint32(regoff(ctxt, p.From3))&0x7F)<<11
-
- case 42: /* lswi */
- o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.From.Reg), 0) | (uint32(regoff(ctxt, p.From3))&0x7F)<<11
-
- case 43: /* unary indexed source: dcbf (b); dcbf (a+b) */
- o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), 0, uint32(p.From.Index), uint32(p.From.Reg))
-
- case 44: /* indexed store */
- o1 = AOP_RRR(uint32(opstorex(ctxt, int(p.As))), uint32(p.From.Reg), uint32(p.To.Index), uint32(p.To.Reg))
-
- case 45: /* indexed load */
- o1 = AOP_RRR(uint32(oploadx(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.From.Index), uint32(p.From.Reg))
-
- case 46: /* plain op */
- o1 = uint32(oprrr(ctxt, int(p.As)))
-
- case 47: /* op Ra, Rd; also op [Ra,] Rd */
+ case 27: /* mov [sl]ext/auto/oreg,fr ==> lwc1 o(r) */
+ v := regoff(ctxt, &p.From)
r := int(p.From.Reg)
-
if r == 0 {
- r = int(p.To.Reg)
+ r = int(o.param)
}
- o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), 0)
-
- case 48: /* op Rs, Ra */
- r := int(p.From.Reg)
-
- if r == 0 {
- r = int(p.To.Reg)
+ a := AMOVF + ALAST
+ if p.As == AMOVD {
+ a = AMOVD + ALAST
}
- o1 = LOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), 0)
+ switch o.size {
+ case 16:
+ o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
+ o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
+ o3 = OP_RRR(opirr(ctxt, AADDVU), uint32(r), uint32(REGTMP), uint32(REGTMP))
+ o4 = OP_IRR(opirr(ctxt, a), uint32(0), uint32(r), uint32(p.To.Reg))
- case 49: /* op Rb; op $n, Rb */
- if p.From.Type != obj.TYPE_REG { /* tlbie $L, rB */
- v := regoff(ctxt, &p.From) & 1
- o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), 0, 0, uint32(p.To.Reg)) | uint32(v)<<21
- } else {
- o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), 0, 0, uint32(p.From.Reg))
+ case 4:
+ o1 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(r), uint32(p.To.Reg))
}
- case 50: /* rem[u] r1[,r2],r3 */
- r := int(p.Reg)
-
+ case 28: /* mov fr,[sl]ext/auto/oreg ==> swc1 o(r) */
+ v := regoff(ctxt, &p.To)
+ r := int(p.To.Reg)
if r == 0 {
- r = int(p.To.Reg)
- }
- v := oprrr(ctxt, int(p.As))
- t := v & (1<<10 | 1) /* OE|Rc */
- o1 = AOP_RRR(uint32(v)&^uint32(t), REGTMP, uint32(r), uint32(p.From.Reg))
- o2 = AOP_RRR(OP_MULLW, REGTMP, REGTMP, uint32(p.From.Reg))
- o3 = AOP_RRR(OP_SUBF|uint32(t), uint32(p.To.Reg), REGTMP, uint32(r))
- if p.As == AREMU {
- o4 = o3
-
- /* Clear top 32 bits */
- o3 = OP_RLW(OP_RLDIC, REGTMP, REGTMP, 0, 0, 0) | 1<<5
+ r = int(o.param)
}
-
- case 51: /* remd[u] r1[,r2],r3 */
- r := int(p.Reg)
-
- if r == 0 {
- r = int(p.To.Reg)
+ a := AMOVF
+ if p.As == AMOVD {
+ a = AMOVD
}
- v := oprrr(ctxt, int(p.As))
- t := v & (1<<10 | 1) /* OE|Rc */
- o1 = AOP_RRR(uint32(v)&^uint32(t), REGTMP, uint32(r), uint32(p.From.Reg))
- o2 = AOP_RRR(OP_MULLD, REGTMP, REGTMP, uint32(p.From.Reg))
- o3 = AOP_RRR(OP_SUBF|uint32(t), uint32(p.To.Reg), REGTMP, uint32(r))
-
- case 52: /* mtfsbNx cr(n) */
- v := regoff(ctxt, &p.From) & 31
-
- o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(v), 0, 0)
-
- case 53: /* mffsX ,fr1 */
- o1 = AOP_RRR(OP_MFFS, uint32(p.To.Reg), 0, 0)
+ switch o.size {
+ case 16:
+ o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
+ o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
+ o3 = OP_RRR(opirr(ctxt, AADDVU), uint32(r), uint32(REGTMP), uint32(REGTMP))
+ o4 = OP_IRR(opirr(ctxt, a), uint32(0), uint32(REGTMP), uint32(p.From.Reg))
- case 54: /* mov msr,r1; mov r1, msr*/
- if oclass(&p.From) == C_REG {
- if p.As == AMOVD {
- o1 = AOP_RRR(OP_MTMSRD, uint32(p.From.Reg), 0, 0)
- } else {
- o1 = AOP_RRR(OP_MTMSR, uint32(p.From.Reg), 0, 0)
- }
- } else {
- o1 = AOP_RRR(OP_MFMSR, uint32(p.To.Reg), 0, 0)
+ case 4:
+ o1 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(r), uint32(p.From.Reg))
}
- case 55: /* op Rb, Rd */
- o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), 0, uint32(p.From.Reg))
-
- case 56: /* sra $sh,[s,]a; srd $sh,[s,]a */
- v := regoff(ctxt, &p.From)
-
- r := int(p.Reg)
- if r == 0 {
- r = int(p.To.Reg)
- }
- o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(r), uint32(p.To.Reg), uint32(v)&31)
- if p.As == ASRAD && (v&0x20 != 0) {
- o1 |= 1 << 1 /* mb[5] */
- }
+ case 30: /* movw r,fr */
+ a := SP(2, 1) | (4 << 21) /* mtc1 */
+ o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg))
- case 57: /* slw $sh,[s,]a -> rlwinm ... */
- v := regoff(ctxt, &p.From)
+ case 31: /* movw fr,r */
+ a := SP(2, 1) | (0 << 21) /* mtc1 */
+ o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
+ case 32: /* fadd fr1,[fr2],fr3 */
r := int(p.Reg)
if r == 0 {
r = int(p.To.Reg)
}
+ o1 = OP_FRRR(oprrr(ctxt, int(p.As)), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
- /*
- * Let user (gs) shoot himself in the foot.
- * qc has already complained.
- *
- if(v < 0 || v > 31)
- ctxt->diag("illegal shift %ld\n%v", v, p);
- */
- if v < 0 {
- v = 0
- } else if v > 32 {
- v = 32
- }
- var mask [2]uint8
- if p.As == ASRW || p.As == ASRWCC { /* shift right */
- mask[0] = uint8(v)
- mask[1] = 31
- v = 32 - v
- } else {
- mask[0] = 0
- mask[1] = uint8(31 - v)
- }
-
- o1 = OP_RLW(OP_RLWINM, uint32(p.To.Reg), uint32(r), uint32(v), uint32(mask[0]), uint32(mask[1]))
- if p.As == ASLWCC || p.As == ASRWCC {
- o1 |= 1 /* Rc */
- }
+ case 33: /* fabs fr1, fr3 */
+ o1 = OP_FRRR(oprrr(ctxt, int(p.As)), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg))
- case 58: /* logical $andcon,[s],a */
+ case 34: /* mov $con,fr ==> or/add $i,t; mov t,fr */
v := regoff(ctxt, &p.From)
-
- r := int(p.Reg)
- if r == 0 {
- r = int(p.To.Reg)
+ a := AADDU
+ if o.a1 == C_ANDCON {
+ a = AOR
}
- o1 = LOP_IRR(uint32(opirr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(v))
+ o1 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(0), uint32(REGTMP))
+ o2 = OP_RRR(SP(2, 1)|(4<<21), uint32(REGTMP), uint32(0), uint32(p.To.Reg)) /* mtc1 */
- case 59: /* or/and $ucon,,r */
- v := regoff(ctxt, &p.From)
-
- r := int(p.Reg)
+ case 35: /* mov r,lext/auto/oreg ==> sw o(r) */
+ v := regoff(ctxt, &p.To)
+ r := int(p.To.Reg)
if r == 0 {
- r = int(p.To.Reg)
+ r = int(o.param)
}
- o1 = LOP_IRR(uint32(opirr(ctxt, int(p.As)+ALAST)), uint32(p.To.Reg), uint32(r), uint32(v)>>16) /* oris, xoris, andis */
-
- case 60: /* tw to,a,b */
- r := int(regoff(ctxt, &p.From) & 31)
+ o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
+ o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
+ o3 = OP_RRR(oprrr(ctxt, AADDVU), uint32(r), uint32(REGTMP), uint32(REGTMP))
+ o4 = OP_IRR(opirr(ctxt, int(p.As)), uint32(0), uint32(REGTMP), uint32(p.From.Reg))
- o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(r), uint32(p.Reg), uint32(p.To.Reg))
-
- case 61: /* tw to,a,$simm */
- r := int(regoff(ctxt, &p.From) & 31)
-
- v := regoff(ctxt, &p.To)
- o1 = AOP_IRR(uint32(opirr(ctxt, int(p.As))), uint32(r), uint32(p.Reg), uint32(v))
-
- case 62: /* rlwmi $sh,s,$mask,a */
+ case 36: /* mov lext/auto/oreg,r ==> lw o(r30) */
v := regoff(ctxt, &p.From)
-
- var mask [2]uint8
- maskgen(ctxt, p, mask[:], uint32(regoff(ctxt, p.From3)))
- o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(p.Reg), uint32(p.To.Reg), uint32(v))
- o1 |= (uint32(mask[0])&31)<<6 | (uint32(mask[1])&31)<<1
-
- case 63: /* rlwmi b,s,$mask,a */
- var mask [2]uint8
- maskgen(ctxt, p, mask[:], uint32(regoff(ctxt, p.From3)))
-
- o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(p.Reg), uint32(p.To.Reg), uint32(p.From.Reg))
- o1 |= (uint32(mask[0])&31)<<6 | (uint32(mask[1])&31)<<1
-
- case 64: /* mtfsf fr[, $m] {,fpcsr} */
- var v int32
- if p.From3Type() != obj.TYPE_NONE {
- v = regoff(ctxt, p.From3) & 255
- } else {
- v = 255
- }
- o1 = OP_MTFSF | uint32(v)<<17 | uint32(p.From.Reg)<<11
-
- case 65: /* MOVFL $imm,FPSCR(n) => mtfsfi crfd,imm */
- if p.To.Reg == 0 {
- ctxt.Diag("must specify FPSCR(n)\n%v", p)
- }
- o1 = OP_MTFSFI | (uint32(p.To.Reg)&15)<<23 | (uint32(regoff(ctxt, &p.From))&31)<<12
-
- case 66: /* mov spr,r1; mov r1,spr, also dcr */
- var r int
- var v int32
- if REG_R0 <= p.From.Reg && p.From.Reg <= REG_R31 {
- r = int(p.From.Reg)
- v = int32(p.To.Reg)
- if REG_DCR0 <= v && v <= REG_DCR0+1023 {
- o1 = OPVCC(31, 451, 0, 0) /* mtdcr */
- } else {
- o1 = OPVCC(31, 467, 0, 0) /* mtspr */
- }
- } else {
- r = int(p.To.Reg)
- v = int32(p.From.Reg)
- if REG_DCR0 <= v && v <= REG_DCR0+1023 {
- o1 = OPVCC(31, 323, 0, 0) /* mfdcr */
- } else {
- o1 = OPVCC(31, 339, 0, 0) /* mfspr */
- }
- }
-
- o1 = AOP_RRR(o1, uint32(r), 0, 0) | (uint32(v)&0x1f)<<16 | ((uint32(v)>>5)&0x1f)<<11
-
- case 67: /* mcrf crfD,crfS */
- if p.From.Type != obj.TYPE_REG || p.From.Reg < REG_CR0 || REG_CR7 < p.From.Reg || p.To.Type != obj.TYPE_REG || p.To.Reg < REG_CR0 || REG_CR7 < p.To.Reg {
- ctxt.Diag("illegal CR field number\n%v", p)
- }
- o1 = AOP_RRR(OP_MCRF, ((uint32(p.To.Reg) & 7) << 2), ((uint32(p.From.Reg) & 7) << 2), 0)
-
- case 68: /* mfcr rD; mfocrf CRM,rD */
- if p.From.Type == obj.TYPE_REG && REG_CR0 <= p.From.Reg && p.From.Reg <= REG_CR7 {
- v := int32(1 << uint(7-(p.To.Reg&7))) /* CR(n) */
- o1 = AOP_RRR(OP_MFCR, uint32(p.To.Reg), 0, 0) | 1<<20 | uint32(v)<<12 /* new form, mfocrf */
- } else {
- o1 = AOP_RRR(OP_MFCR, uint32(p.To.Reg), 0, 0) /* old form, whole register */
- }
-
- case 69: /* mtcrf CRM,rS */
- var v int32
- if p.From3Type() != obj.TYPE_NONE {
- if p.To.Reg != 0 {
- ctxt.Diag("can't use both mask and CR(n)\n%v", p)
- }
- v = regoff(ctxt, p.From3) & 0xff
- } else {
- if p.To.Reg == 0 {
- v = 0xff /* CR */
- } else {
- v = 1 << uint(7-(p.To.Reg&7)) /* CR(n) */
- }
- }
-
- o1 = AOP_RRR(OP_MTCRF, uint32(p.From.Reg), 0, 0) | uint32(v)<<12
-
- case 70: /* [f]cmp r,r,cr*/
- var r int
- if p.Reg == 0 {
- r = 0
- } else {
- r = (int(p.Reg) & 7) << 2
- }
- o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(r), uint32(p.From.Reg), uint32(p.To.Reg))
-
- case 71: /* cmp[l] r,i,cr*/
- var r int
- if p.Reg == 0 {
- r = 0
- } else {
- r = (int(p.Reg) & 7) << 2
+ r := int(p.From.Reg)
+ if r == 0 {
+ r = int(o.param)
}
- o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(r), uint32(p.From.Reg), 0) | uint32(regoff(ctxt, &p.To))&0xffff
-
- case 72: /* slbmte (Rb+Rs -> slb[Rb]) -> Rs, Rb */
- o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.From.Reg), 0, uint32(p.To.Reg))
+ o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
+ o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
+ o3 = OP_RRR(oprrr(ctxt, AADDVU), uint32(r), uint32(REGTMP), uint32(REGTMP))
+ o4 = OP_IRR(opirr(ctxt, int(p.As)+ALAST), uint32(0), uint32(REGTMP), uint32(p.To.Reg))
- case 73: /* mcrfs crfD,crfS */
- if p.From.Type != obj.TYPE_REG || p.From.Reg != REG_FPSCR || p.To.Type != obj.TYPE_REG || p.To.Reg < REG_CR0 || REG_CR7 < p.To.Reg {
- ctxt.Diag("illegal FPSCR/CR field number\n%v", p)
+ case 37: /* movw r,mr */
+ a := SP(2, 0) | (4 << 21) /* mtc0 */
+ if p.As == AMOVV {
+ a = SP(2, 0) | (5 << 21) /* dmtc0 */
}
- o1 = AOP_RRR(OP_MCRFS, ((uint32(p.To.Reg) & 7) << 2), ((0 & 7) << 2), 0)
+ o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg))
- case 77: /* syscall $scon, syscall Rx */
- if p.From.Type == obj.TYPE_CONST {
- if p.From.Offset > BIG || p.From.Offset < -BIG {
- ctxt.Diag("illegal syscall, sysnum too large: %v", p)
- }
- o1 = AOP_IRR(OP_ADDI, REGZERO, REGZERO, uint32(p.From.Offset))
- } else if p.From.Type == obj.TYPE_REG {
- o1 = LOP_RRR(OP_OR, REGZERO, uint32(p.From.Reg), uint32(p.From.Reg))
- } else {
- ctxt.Diag("illegal syscall: %v", p)
- o1 = 0x7fe00008 // trap always
+ case 38: /* movw mr,r */
+ a := SP(2, 0) | (0 << 21) /* mfc0 */
+ if p.As == AMOVV {
+ a = SP(2, 0) | (1 << 21) /* dmfc0 */
}
+ o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
- o2 = uint32(oprrr(ctxt, int(p.As)))
- o3 = AOP_RRR(uint32(oprrr(ctxt, AXOR)), REGZERO, REGZERO, REGZERO) // XOR R0, R0
-
- case 78: /* undef */
- o1 = 0 /* "An instruction consisting entirely of binary 0s is guaranteed
- always to be an illegal instruction." */
-
- /* relocation operations */
- case 74:
- v := regoff(ctxt, &p.To)
-
- o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(high16adjusted(v)))
- o2 = AOP_IRR(uint32(opstore(ctxt, int(p.As))), uint32(p.From.Reg), REGTMP, uint32(v))
- addaddrreloc(ctxt, p.To.Sym, &o1, &o2)
-
- //if(dlm) reloc(&p->to, p->pc, 1);
-
- case 75:
- v := regoff(ctxt, &p.From)
- o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(high16adjusted(v)))
- o2 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(v))
- addaddrreloc(ctxt, p.From.Sym, &o1, &o2)
-
- //if(dlm) reloc(&p->from, p->pc, 1);
-
- case 76:
- v := regoff(ctxt, &p.From)
- o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(high16adjusted(v)))
- o2 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(v))
- addaddrreloc(ctxt, p.From.Sym, &o1, &o2)
- o3 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.To.Reg), 0)
-
- //if(dlm) reloc(&p->from, p->pc, 1);
+ case 40: /* word */
+ o1 = uint32(regoff(ctxt, &p.From))
+ case 41: /* movw f,fcr */
+ o1 = OP_RRR(SP(2, 1)|(2<<21), uint32(REGZERO), uint32(0), uint32(p.To.Reg)) /* mfcc1 */
+ o2 = OP_RRR(SP(2, 1)|(6<<21), uint32(p.From.Reg), uint32(0), uint32(p.To.Reg)) /* mtcc1 */
+
+ case 42: /* movw fcr,r */
+ o1 = OP_RRR(SP(2, 1)|(2<<21), uint32(p.To.Reg), uint32(0), uint32(p.From.Reg)) /* mfcc1 */
+
+ case 47: /* movv r,fr */
+ a := SP(2, 1) | (5 << 21) /* dmtc1 */
+ o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg))
+
+ case 48: /* movv fr,r */
+ a := SP(2, 1) | (1 << 21) /* dmtc1 */
+ o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
+
+ case 49: /* undef */
+ o1 = 8 /* JMP (R0) */
+
+ /* relocation operations */
+ case 50: /* mov r,addr ==> lu + or + sw (REGTMP) */
+ o1 = OP_IRR(opirr(ctxt, ALAST), uint32(0), uint32(REGZERO), uint32(REGTMP))
+ o2 = OP_IRR(opirr(ctxt, AOR), uint32(0), uint32(REGTMP), uint32(REGTMP))
+ rel := obj.Addrel(ctxt.Cursym)
+ rel.Off = int32(ctxt.Pc)
+ rel.Siz = 8
+ rel.Sym = p.To.Sym
+ rel.Add = p.To.Offset
+ rel.Type = obj.R_ADDRMIPS
+ o3 = OP_IRR(opirr(ctxt, int(p.As)), uint32(0), uint32(REGTMP), uint32(p.From.Reg))
+
+ case 51: /* mov addr,r ==> lu + or + lw (REGTMP) */
+ o1 = OP_IRR(opirr(ctxt, ALAST), uint32(0), uint32(REGZERO), uint32(REGTMP))
+ o2 = OP_IRR(opirr(ctxt, AOR), uint32(0), uint32(REGTMP), uint32(REGTMP))
+ rel := obj.Addrel(ctxt.Cursym)
+ rel.Off = int32(ctxt.Pc)
+ rel.Siz = 8
+ rel.Sym = p.From.Sym
+ rel.Add = p.From.Offset
+ rel.Type = obj.R_ADDRMIPS
+ o3 = OP_IRR(opirr(ctxt, int(p.As)+ALAST), uint32(0), uint32(REGTMP), uint32(p.To.Reg))
}
out[0] = o1
out[1] = o2
out[2] = o3
out[3] = o4
- out[4] = o5
return
}
func vregoff(ctxt *obj.Link, a *obj.Addr) int64 {
ctxt.Instoffset = 0
- if a != nil {
- aclass(ctxt, a)
- }
+ aclass(ctxt, a)
return ctxt.Instoffset
}
return int32(vregoff(ctxt, a))
}
-func oprrr(ctxt *obj.Link, a int) int32 {
+func oprrr(ctxt *obj.Link, a int) uint32 {
switch a {
case AADD:
- return int32(OPVCC(31, 266, 0, 0))
- case AADDCC:
- return int32(OPVCC(31, 266, 0, 1))
- case AADDV:
- return int32(OPVCC(31, 266, 1, 0))
- case AADDVCC:
- return int32(OPVCC(31, 266, 1, 1))
- case AADDC:
- return int32(OPVCC(31, 10, 0, 0))
- case AADDCCC:
- return int32(OPVCC(31, 10, 0, 1))
- case AADDCV:
- return int32(OPVCC(31, 10, 1, 0))
- case AADDCVCC:
- return int32(OPVCC(31, 10, 1, 1))
- case AADDE:
- return int32(OPVCC(31, 138, 0, 0))
- case AADDECC:
- return int32(OPVCC(31, 138, 0, 1))
- case AADDEV:
- return int32(OPVCC(31, 138, 1, 0))
- case AADDEVCC:
- return int32(OPVCC(31, 138, 1, 1))
- case AADDME:
- return int32(OPVCC(31, 234, 0, 0))
- case AADDMECC:
- return int32(OPVCC(31, 234, 0, 1))
- case AADDMEV:
- return int32(OPVCC(31, 234, 1, 0))
- case AADDMEVCC:
- return int32(OPVCC(31, 234, 1, 1))
- case AADDZE:
- return int32(OPVCC(31, 202, 0, 0))
- case AADDZECC:
- return int32(OPVCC(31, 202, 0, 1))
- case AADDZEV:
- return int32(OPVCC(31, 202, 1, 0))
- case AADDZEVCC:
- return int32(OPVCC(31, 202, 1, 1))
-
+ return OP(4, 0)
+ case AADDU:
+ return OP(4, 1)
+ case ASGT:
+ return OP(5, 2)
+ case ASGTU:
+ return OP(5, 3)
case AAND:
- return int32(OPVCC(31, 28, 0, 0))
- case AANDCC:
- return int32(OPVCC(31, 28, 0, 1))
- case AANDN:
- return int32(OPVCC(31, 60, 0, 0))
- case AANDNCC:
- return int32(OPVCC(31, 60, 0, 1))
-
- case ACMP:
- return int32(OPVCC(31, 0, 0, 0) | 1<<21) /* L=1 */
- case ACMPU:
- return int32(OPVCC(31, 32, 0, 0) | 1<<21)
- case ACMPW:
- return int32(OPVCC(31, 0, 0, 0)) /* L=0 */
- case ACMPWU:
- return int32(OPVCC(31, 32, 0, 0))
-
- case ACNTLZW:
- return int32(OPVCC(31, 26, 0, 0))
- case ACNTLZWCC:
- return int32(OPVCC(31, 26, 0, 1))
- case ACNTLZD:
- return int32(OPVCC(31, 58, 0, 0))
- case ACNTLZDCC:
- return int32(OPVCC(31, 58, 0, 1))
-
- case ACRAND:
- return int32(OPVCC(19, 257, 0, 0))
- case ACRANDN:
- return int32(OPVCC(19, 129, 0, 0))
- case ACREQV:
- return int32(OPVCC(19, 289, 0, 0))
- case ACRNAND:
- return int32(OPVCC(19, 225, 0, 0))
- case ACRNOR:
- return int32(OPVCC(19, 33, 0, 0))
- case ACROR:
- return int32(OPVCC(19, 449, 0, 0))
- case ACRORN:
- return int32(OPVCC(19, 417, 0, 0))
- case ACRXOR:
- return int32(OPVCC(19, 193, 0, 0))
-
- case ADCBF:
- return int32(OPVCC(31, 86, 0, 0))
- case ADCBI:
- return int32(OPVCC(31, 470, 0, 0))
- case ADCBST:
- return int32(OPVCC(31, 54, 0, 0))
- case ADCBT:
- return int32(OPVCC(31, 278, 0, 0))
- case ADCBTST:
- return int32(OPVCC(31, 246, 0, 0))
- case ADCBZ:
- return int32(OPVCC(31, 1014, 0, 0))
-
- case AREM, ADIVW:
- return int32(OPVCC(31, 491, 0, 0))
-
- case AREMCC, ADIVWCC:
- return int32(OPVCC(31, 491, 0, 1))
-
- case AREMV, ADIVWV:
- return int32(OPVCC(31, 491, 1, 0))
-
- case AREMVCC, ADIVWVCC:
- return int32(OPVCC(31, 491, 1, 1))
-
- case AREMU, ADIVWU:
- return int32(OPVCC(31, 459, 0, 0))
-
- case AREMUCC, ADIVWUCC:
- return int32(OPVCC(31, 459, 0, 1))
-
- case AREMUV, ADIVWUV:
- return int32(OPVCC(31, 459, 1, 0))
-
- case AREMUVCC, ADIVWUVCC:
- return int32(OPVCC(31, 459, 1, 1))
-
- case AREMD, ADIVD:
- return int32(OPVCC(31, 489, 0, 0))
-
- case AREMDCC, ADIVDCC:
- return int32(OPVCC(31, 489, 0, 1))
-
- case AREMDV, ADIVDV:
- return int32(OPVCC(31, 489, 1, 0))
-
- case AREMDVCC, ADIVDVCC:
- return int32(OPVCC(31, 489, 1, 1))
-
- case AREMDU, ADIVDU:
- return int32(OPVCC(31, 457, 0, 0))
-
- case AREMDUCC, ADIVDUCC:
- return int32(OPVCC(31, 457, 0, 1))
-
- case AREMDUV, ADIVDUV:
- return int32(OPVCC(31, 457, 1, 0))
-
- case AREMDUVCC, ADIVDUVCC:
- return int32(OPVCC(31, 457, 1, 1))
-
- case AEIEIO:
- return int32(OPVCC(31, 854, 0, 0))
-
- case AEQV:
- return int32(OPVCC(31, 284, 0, 0))
- case AEQVCC:
- return int32(OPVCC(31, 284, 0, 1))
-
- case AEXTSB:
- return int32(OPVCC(31, 954, 0, 0))
- case AEXTSBCC:
- return int32(OPVCC(31, 954, 0, 1))
- case AEXTSH:
- return int32(OPVCC(31, 922, 0, 0))
- case AEXTSHCC:
- return int32(OPVCC(31, 922, 0, 1))
- case AEXTSW:
- return int32(OPVCC(31, 986, 0, 0))
- case AEXTSWCC:
- return int32(OPVCC(31, 986, 0, 1))
-
- case AFABS:
- return int32(OPVCC(63, 264, 0, 0))
- case AFABSCC:
- return int32(OPVCC(63, 264, 0, 1))
- case AFADD:
- return int32(OPVCC(63, 21, 0, 0))
- case AFADDCC:
- return int32(OPVCC(63, 21, 0, 1))
- case AFADDS:
- return int32(OPVCC(59, 21, 0, 0))
- case AFADDSCC:
- return int32(OPVCC(59, 21, 0, 1))
- case AFCMPO:
- return int32(OPVCC(63, 32, 0, 0))
- case AFCMPU:
- return int32(OPVCC(63, 0, 0, 0))
- case AFCFID:
- return int32(OPVCC(63, 846, 0, 0))
- case AFCFIDCC:
- return int32(OPVCC(63, 846, 0, 1))
- case AFCTIW:
- return int32(OPVCC(63, 14, 0, 0))
- case AFCTIWCC:
- return int32(OPVCC(63, 14, 0, 1))
- case AFCTIWZ:
- return int32(OPVCC(63, 15, 0, 0))
- case AFCTIWZCC:
- return int32(OPVCC(63, 15, 0, 1))
- case AFCTID:
- return int32(OPVCC(63, 814, 0, 0))
- case AFCTIDCC:
- return int32(OPVCC(63, 814, 0, 1))
- case AFCTIDZ:
- return int32(OPVCC(63, 815, 0, 0))
- case AFCTIDZCC:
- return int32(OPVCC(63, 815, 0, 1))
- case AFDIV:
- return int32(OPVCC(63, 18, 0, 0))
- case AFDIVCC:
- return int32(OPVCC(63, 18, 0, 1))
- case AFDIVS:
- return int32(OPVCC(59, 18, 0, 0))
- case AFDIVSCC:
- return int32(OPVCC(59, 18, 0, 1))
- case AFMADD:
- return int32(OPVCC(63, 29, 0, 0))
- case AFMADDCC:
- return int32(OPVCC(63, 29, 0, 1))
- case AFMADDS:
- return int32(OPVCC(59, 29, 0, 0))
- case AFMADDSCC:
- return int32(OPVCC(59, 29, 0, 1))
-
- case AFMOVS, AFMOVD:
- return int32(OPVCC(63, 72, 0, 0)) /* load */
- case AFMOVDCC:
- return int32(OPVCC(63, 72, 0, 1))
- case AFMSUB:
- return int32(OPVCC(63, 28, 0, 0))
- case AFMSUBCC:
- return int32(OPVCC(63, 28, 0, 1))
- case AFMSUBS:
- return int32(OPVCC(59, 28, 0, 0))
- case AFMSUBSCC:
- return int32(OPVCC(59, 28, 0, 1))
- case AFMUL:
- return int32(OPVCC(63, 25, 0, 0))
- case AFMULCC:
- return int32(OPVCC(63, 25, 0, 1))
- case AFMULS:
- return int32(OPVCC(59, 25, 0, 0))
- case AFMULSCC:
- return int32(OPVCC(59, 25, 0, 1))
- case AFNABS:
- return int32(OPVCC(63, 136, 0, 0))
- case AFNABSCC:
- return int32(OPVCC(63, 136, 0, 1))
- case AFNEG:
- return int32(OPVCC(63, 40, 0, 0))
- case AFNEGCC:
- return int32(OPVCC(63, 40, 0, 1))
- case AFNMADD:
- return int32(OPVCC(63, 31, 0, 0))
- case AFNMADDCC:
- return int32(OPVCC(63, 31, 0, 1))
- case AFNMADDS:
- return int32(OPVCC(59, 31, 0, 0))
- case AFNMADDSCC:
- return int32(OPVCC(59, 31, 0, 1))
- case AFNMSUB:
- return int32(OPVCC(63, 30, 0, 0))
- case AFNMSUBCC:
- return int32(OPVCC(63, 30, 0, 1))
- case AFNMSUBS:
- return int32(OPVCC(59, 30, 0, 0))
- case AFNMSUBSCC:
- return int32(OPVCC(59, 30, 0, 1))
- case AFRES:
- return int32(OPVCC(59, 24, 0, 0))
- case AFRESCC:
- return int32(OPVCC(59, 24, 0, 1))
- case AFRSP:
- return int32(OPVCC(63, 12, 0, 0))
- case AFRSPCC:
- return int32(OPVCC(63, 12, 0, 1))
- case AFRSQRTE:
- return int32(OPVCC(63, 26, 0, 0))
- case AFRSQRTECC:
- return int32(OPVCC(63, 26, 0, 1))
- case AFSEL:
- return int32(OPVCC(63, 23, 0, 0))
- case AFSELCC:
- return int32(OPVCC(63, 23, 0, 1))
- case AFSQRT:
- return int32(OPVCC(63, 22, 0, 0))
- case AFSQRTCC:
- return int32(OPVCC(63, 22, 0, 1))
- case AFSQRTS:
- return int32(OPVCC(59, 22, 0, 0))
- case AFSQRTSCC:
- return int32(OPVCC(59, 22, 0, 1))
- case AFSUB:
- return int32(OPVCC(63, 20, 0, 0))
- case AFSUBCC:
- return int32(OPVCC(63, 20, 0, 1))
- case AFSUBS:
- return int32(OPVCC(59, 20, 0, 0))
- case AFSUBSCC:
- return int32(OPVCC(59, 20, 0, 1))
-
- case AICBI:
- return int32(OPVCC(31, 982, 0, 0))
- case AISYNC:
- return int32(OPVCC(19, 150, 0, 0))
-
- case AMTFSB0:
- return int32(OPVCC(63, 70, 0, 0))
- case AMTFSB0CC:
- return int32(OPVCC(63, 70, 0, 1))
- case AMTFSB1:
- return int32(OPVCC(63, 38, 0, 0))
- case AMTFSB1CC:
- return int32(OPVCC(63, 38, 0, 1))
-
- case AMULHW:
- return int32(OPVCC(31, 75, 0, 0))
- case AMULHWCC:
- return int32(OPVCC(31, 75, 0, 1))
- case AMULHWU:
- return int32(OPVCC(31, 11, 0, 0))
- case AMULHWUCC:
- return int32(OPVCC(31, 11, 0, 1))
- case AMULLW:
- return int32(OPVCC(31, 235, 0, 0))
- case AMULLWCC:
- return int32(OPVCC(31, 235, 0, 1))
- case AMULLWV:
- return int32(OPVCC(31, 235, 1, 0))
- case AMULLWVCC:
- return int32(OPVCC(31, 235, 1, 1))
-
- case AMULHD:
- return int32(OPVCC(31, 73, 0, 0))
- case AMULHDCC:
- return int32(OPVCC(31, 73, 0, 1))
- case AMULHDU:
- return int32(OPVCC(31, 9, 0, 0))
- case AMULHDUCC:
- return int32(OPVCC(31, 9, 0, 1))
- case AMULLD:
- return int32(OPVCC(31, 233, 0, 0))
- case AMULLDCC:
- return int32(OPVCC(31, 233, 0, 1))
- case AMULLDV:
- return int32(OPVCC(31, 233, 1, 0))
- case AMULLDVCC:
- return int32(OPVCC(31, 233, 1, 1))
-
- case ANAND:
- return int32(OPVCC(31, 476, 0, 0))
- case ANANDCC:
- return int32(OPVCC(31, 476, 0, 1))
- case ANEG:
- return int32(OPVCC(31, 104, 0, 0))
- case ANEGCC:
- return int32(OPVCC(31, 104, 0, 1))
- case ANEGV:
- return int32(OPVCC(31, 104, 1, 0))
- case ANEGVCC:
- return int32(OPVCC(31, 104, 1, 1))
- case ANOR:
- return int32(OPVCC(31, 124, 0, 0))
- case ANORCC:
- return int32(OPVCC(31, 124, 0, 1))
+ return OP(4, 4)
case AOR:
- return int32(OPVCC(31, 444, 0, 0))
- case AORCC:
- return int32(OPVCC(31, 444, 0, 1))
- case AORN:
- return int32(OPVCC(31, 412, 0, 0))
- case AORNCC:
- return int32(OPVCC(31, 412, 0, 1))
-
- case ARFI:
- return int32(OPVCC(19, 50, 0, 0))
- case ARFCI:
- return int32(OPVCC(19, 51, 0, 0))
- case ARFID:
- return int32(OPVCC(19, 18, 0, 0))
- case AHRFID:
- return int32(OPVCC(19, 274, 0, 0))
-
- case ARLWMI:
- return int32(OPVCC(20, 0, 0, 0))
- case ARLWMICC:
- return int32(OPVCC(20, 0, 0, 1))
- case ARLWNM:
- return int32(OPVCC(23, 0, 0, 0))
- case ARLWNMCC:
- return int32(OPVCC(23, 0, 0, 1))
-
- case ARLDCL:
- return int32(OPVCC(30, 8, 0, 0))
- case ARLDCR:
- return int32(OPVCC(30, 9, 0, 0))
-
- case ASYSCALL:
- return int32(OPVCC(17, 1, 0, 0))
-
- case ASLW:
- return int32(OPVCC(31, 24, 0, 0))
- case ASLWCC:
- return int32(OPVCC(31, 24, 0, 1))
- case ASLD:
- return int32(OPVCC(31, 27, 0, 0))
- case ASLDCC:
- return int32(OPVCC(31, 27, 0, 1))
-
- case ASRAW:
- return int32(OPVCC(31, 792, 0, 0))
- case ASRAWCC:
- return int32(OPVCC(31, 792, 0, 1))
- case ASRAD:
- return int32(OPVCC(31, 794, 0, 0))
- case ASRADCC:
- return int32(OPVCC(31, 794, 0, 1))
-
- case ASRW:
- return int32(OPVCC(31, 536, 0, 0))
- case ASRWCC:
- return int32(OPVCC(31, 536, 0, 1))
- case ASRD:
- return int32(OPVCC(31, 539, 0, 0))
- case ASRDCC:
- return int32(OPVCC(31, 539, 0, 1))
-
+ return OP(4, 5)
+ case AXOR:
+ return OP(4, 6)
case ASUB:
- return int32(OPVCC(31, 40, 0, 0))
- case ASUBCC:
- return int32(OPVCC(31, 40, 0, 1))
+ return OP(4, 2)
+ case ASUBU:
+ return OP(4, 3)
+ case ANOR:
+ return OP(4, 7)
+ case ASLL:
+ return OP(0, 4)
+ case ASRL:
+ return OP(0, 6)
+ case ASRA:
+ return OP(0, 7)
+ case ASLLV:
+ return OP(2, 4)
+ case ASRLV:
+ return OP(2, 6)
+ case ASRAV:
+ return OP(2, 7)
+ case AADDV:
+ return OP(5, 4)
+ case AADDVU:
+ return OP(5, 5)
case ASUBV:
- return int32(OPVCC(31, 40, 1, 0))
- case ASUBVCC:
- return int32(OPVCC(31, 40, 1, 1))
- case ASUBC:
- return int32(OPVCC(31, 8, 0, 0))
- case ASUBCCC:
- return int32(OPVCC(31, 8, 0, 1))
- case ASUBCV:
- return int32(OPVCC(31, 8, 1, 0))
- case ASUBCVCC:
- return int32(OPVCC(31, 8, 1, 1))
- case ASUBE:
- return int32(OPVCC(31, 136, 0, 0))
- case ASUBECC:
- return int32(OPVCC(31, 136, 0, 1))
- case ASUBEV:
- return int32(OPVCC(31, 136, 1, 0))
- case ASUBEVCC:
- return int32(OPVCC(31, 136, 1, 1))
- case ASUBME:
- return int32(OPVCC(31, 232, 0, 0))
- case ASUBMECC:
- return int32(OPVCC(31, 232, 0, 1))
- case ASUBMEV:
- return int32(OPVCC(31, 232, 1, 0))
- case ASUBMEVCC:
- return int32(OPVCC(31, 232, 1, 1))
- case ASUBZE:
- return int32(OPVCC(31, 200, 0, 0))
- case ASUBZECC:
- return int32(OPVCC(31, 200, 0, 1))
- case ASUBZEV:
- return int32(OPVCC(31, 200, 1, 0))
- case ASUBZEVCC:
- return int32(OPVCC(31, 200, 1, 1))
-
- case ASYNC:
- return int32(OPVCC(31, 598, 0, 0))
- case APTESYNC:
- return int32(OPVCC(31, 598, 0, 0) | 2<<21)
-
- case ATLBIE:
- return int32(OPVCC(31, 306, 0, 0))
- case ATLBIEL:
- return int32(OPVCC(31, 274, 0, 0))
- case ATLBSYNC:
- return int32(OPVCC(31, 566, 0, 0))
- case ASLBIA:
- return int32(OPVCC(31, 498, 0, 0))
- case ASLBIE:
- return int32(OPVCC(31, 434, 0, 0))
- case ASLBMFEE:
- return int32(OPVCC(31, 915, 0, 0))
- case ASLBMFEV:
- return int32(OPVCC(31, 851, 0, 0))
- case ASLBMTE:
- return int32(OPVCC(31, 402, 0, 0))
-
- case ATW:
- return int32(OPVCC(31, 4, 0, 0))
- case ATD:
- return int32(OPVCC(31, 68, 0, 0))
-
- case AXOR:
- return int32(OPVCC(31, 316, 0, 0))
- case AXORCC:
- return int32(OPVCC(31, 316, 0, 1))
+ return OP(5, 6)
+ case ASUBVU:
+ return OP(5, 7)
+ case AREM,
+ ADIV:
+ return OP(3, 2)
+ case AREMU,
+ ADIVU:
+ return OP(3, 3)
+ case AMUL:
+ return OP(3, 0)
+ case AMULU:
+ return OP(3, 1)
+ case AREMV,
+ ADIVV:
+ return OP(3, 6)
+ case AREMVU,
+ ADIVVU:
+ return OP(3, 7)
+ case AMULV:
+ return OP(3, 4)
+ case AMULVU:
+ return OP(3, 5)
+
+ case AJMP:
+ return OP(1, 0)
+ case AJAL:
+ return OP(1, 1)
+
+ case ABREAK:
+ return OP(1, 5)
+ case ASYSCALL:
+ return OP(1, 4)
+ case ATLBP:
+ return MMU(1, 0)
+ case ATLBR:
+ return MMU(0, 1)
+ case ATLBWI:
+ return MMU(0, 2)
+ case ATLBWR:
+ return MMU(0, 6)
+ case ARFE:
+ return MMU(2, 0)
+
+ case ADIVF:
+ return FPF(0, 3)
+ case ADIVD:
+ return FPD(0, 3)
+ case AMULF:
+ return FPF(0, 2)
+ case AMULD:
+ return FPD(0, 2)
+ case ASUBF:
+ return FPF(0, 1)
+ case ASUBD:
+ return FPD(0, 1)
+ case AADDF:
+ return FPF(0, 0)
+ case AADDD:
+ return FPD(0, 0)
+ case ATRUNCFV:
+ return FPF(1, 1)
+ case ATRUNCDV:
+ return FPD(1, 1)
+ case ATRUNCFW:
+ return FPF(1, 5)
+ case ATRUNCDW:
+ return FPD(1, 5)
+ case AMOVFV:
+ return FPF(4, 5)
+ case AMOVDV:
+ return FPD(4, 5)
+ case AMOVVF:
+ return FPV(4, 0)
+ case AMOVVD:
+ return FPV(4, 1)
+ case AMOVFW:
+ return FPF(4, 4)
+ case AMOVDW:
+ return FPD(4, 4)
+ case AMOVWF:
+ return FPW(4, 0)
+ case AMOVDF:
+ return FPD(4, 0)
+ case AMOVWD:
+ return FPW(4, 1)
+ case AMOVFD:
+ return FPF(4, 1)
+ case AABSF:
+ return FPF(0, 5)
+ case AABSD:
+ return FPD(0, 5)
+ case AMOVF:
+ return FPF(0, 6)
+ case AMOVD:
+ return FPD(0, 6)
+ case ANEGF:
+ return FPF(0, 7)
+ case ANEGD:
+ return FPD(0, 7)
+ case ACMPEQF:
+ return FPF(6, 2)
+ case ACMPEQD:
+ return FPD(6, 2)
+ case ACMPGTF:
+ return FPF(7, 4)
+ case ACMPGTD:
+ return FPD(7, 4)
+ case ACMPGEF:
+ return FPF(7, 6)
+ case ACMPGED:
+ return FPD(7, 6)
}
- ctxt.Diag("bad r/r opcode %v", obj.Aconv(a))
+ if a >= ALAST {
+ ctxt.Diag("bad rrr opcode %v+ALAST", obj.Aconv(a-ALAST))
+ } else {
+ ctxt.Diag("bad rrr opcode %v", obj.Aconv(a))
+ }
return 0
}
-func opirr(ctxt *obj.Link, a int) int32 {
+func opirr(ctxt *obj.Link, a int) uint32 {
switch a {
case AADD:
- return int32(OPVCC(14, 0, 0, 0))
- case AADDC:
- return int32(OPVCC(12, 0, 0, 0))
- case AADDCCC:
- return int32(OPVCC(13, 0, 0, 0))
- case AADD + ALAST:
- return int32(OPVCC(15, 0, 0, 0)) /* ADDIS/CAU */
-
- case AANDCC:
- return int32(OPVCC(28, 0, 0, 0))
- case AANDCC + ALAST:
- return int32(OPVCC(29, 0, 0, 0)) /* ANDIS./ANDIU. */
-
- case ABR:
- return int32(OPVCC(18, 0, 0, 0))
- case ABL:
- return int32(OPVCC(18, 0, 0, 0) | 1)
- case obj.ADUFFZERO:
- return int32(OPVCC(18, 0, 0, 0) | 1)
- case obj.ADUFFCOPY:
- return int32(OPVCC(18, 0, 0, 0) | 1)
- case ABC:
- return int32(OPVCC(16, 0, 0, 0))
- case ABCL:
- return int32(OPVCC(16, 0, 0, 0) | 1)
-
- case ABEQ:
- return int32(AOP_RRR(16<<26, 12, 2, 0))
- case ABGE:
- return int32(AOP_RRR(16<<26, 4, 0, 0))
- case ABGT:
- return int32(AOP_RRR(16<<26, 12, 1, 0))
- case ABLE:
- return int32(AOP_RRR(16<<26, 4, 1, 0))
- case ABLT:
- return int32(AOP_RRR(16<<26, 12, 0, 0))
- case ABNE:
- return int32(AOP_RRR(16<<26, 4, 2, 0))
- case ABVC:
- return int32(AOP_RRR(16<<26, 4, 3, 0))
- case ABVS:
- return int32(AOP_RRR(16<<26, 12, 3, 0))
-
- case ACMP:
- return int32(OPVCC(11, 0, 0, 0) | 1<<21) /* L=1 */
- case ACMPU:
- return int32(OPVCC(10, 0, 0, 0) | 1<<21)
- case ACMPW:
- return int32(OPVCC(11, 0, 0, 0)) /* L=0 */
- case ACMPWU:
- return int32(OPVCC(10, 0, 0, 0))
- case ALSW:
- return int32(OPVCC(31, 597, 0, 0))
-
- case AMULLW:
- return int32(OPVCC(7, 0, 0, 0))
-
+ return SP(1, 0)
+ case AADDU:
+ return SP(1, 1)
+ case ASGT:
+ return SP(1, 2)
+ case ASGTU:
+ return SP(1, 3)
+ case AAND:
+ return SP(1, 4)
case AOR:
- return int32(OPVCC(24, 0, 0, 0))
- case AOR + ALAST:
- return int32(OPVCC(25, 0, 0, 0)) /* ORIS/ORIU */
-
- case ARLWMI:
- return int32(OPVCC(20, 0, 0, 0)) /* rlwimi */
- case ARLWMICC:
- return int32(OPVCC(20, 0, 0, 1))
- case ARLDMI:
- return int32(OPVCC(30, 0, 0, 0) | 3<<2) /* rldimi */
- case ARLDMICC:
- return int32(OPVCC(30, 0, 0, 1) | 3<<2)
-
- case ARLWNM:
- return int32(OPVCC(21, 0, 0, 0)) /* rlwinm */
- case ARLWNMCC:
- return int32(OPVCC(21, 0, 0, 1))
-
- case ARLDCL:
- return int32(OPVCC(30, 0, 0, 0)) /* rldicl */
- case ARLDCLCC:
- return int32(OPVCC(30, 0, 0, 1))
- case ARLDCR:
- return int32(OPVCC(30, 1, 0, 0)) /* rldicr */
- case ARLDCRCC:
- return int32(OPVCC(30, 1, 0, 1))
- case ARLDC:
- return int32(OPVCC(30, 0, 0, 0) | 2<<2)
- case ARLDCCC:
- return int32(OPVCC(30, 0, 0, 1) | 2<<2)
-
- case ASRAW:
- return int32(OPVCC(31, 824, 0, 0))
- case ASRAWCC:
- return int32(OPVCC(31, 824, 0, 1))
- case ASRAD:
- return int32(OPVCC(31, (413 << 1), 0, 0))
- case ASRADCC:
- return int32(OPVCC(31, (413 << 1), 0, 1))
-
- case ASTSW:
- return int32(OPVCC(31, 725, 0, 0))
-
- case ASUBC:
- return int32(OPVCC(8, 0, 0, 0))
-
- case ATW:
- return int32(OPVCC(3, 0, 0, 0))
- case ATD:
- return int32(OPVCC(2, 0, 0, 0))
-
+ return SP(1, 5)
case AXOR:
- return int32(OPVCC(26, 0, 0, 0)) /* XORIL */
- case AXOR + ALAST:
- return int32(OPVCC(27, 0, 0, 0)) /* XORIU */
- }
-
- ctxt.Diag("bad opcode i/r %v", obj.Aconv(a))
- return 0
-}
-
-/*
- * load o(a),d
- */
-func opload(ctxt *obj.Link, a int) int32 {
- switch a {
- case AMOVD:
- return int32(OPVCC(58, 0, 0, 0)) /* ld */
- case AMOVDU:
- return int32(OPVCC(58, 0, 0, 1)) /* ldu */
- case AMOVWZ:
- return int32(OPVCC(32, 0, 0, 0)) /* lwz */
- case AMOVWZU:
- return int32(OPVCC(33, 0, 0, 0)) /* lwzu */
- case AMOVW:
- return int32(OPVCC(58, 0, 0, 0) | 1<<1) /* lwa */
-
- /* no AMOVWU */
- case AMOVB, AMOVBZ:
- return int32(OPVCC(34, 0, 0, 0))
- /* load */
-
- case AMOVBU, AMOVBZU:
- return int32(OPVCC(35, 0, 0, 0))
- case AFMOVD:
- return int32(OPVCC(50, 0, 0, 0))
- case AFMOVDU:
- return int32(OPVCC(51, 0, 0, 0))
- case AFMOVS:
- return int32(OPVCC(48, 0, 0, 0))
- case AFMOVSU:
- return int32(OPVCC(49, 0, 0, 0))
- case AMOVH:
- return int32(OPVCC(42, 0, 0, 0))
- case AMOVHU:
- return int32(OPVCC(43, 0, 0, 0))
- case AMOVHZ:
- return int32(OPVCC(40, 0, 0, 0))
- case AMOVHZU:
- return int32(OPVCC(41, 0, 0, 0))
- case AMOVMW:
- return int32(OPVCC(46, 0, 0, 0)) /* lmw */
- }
-
- ctxt.Diag("bad load opcode %v", obj.Aconv(a))
- return 0
-}
-
-/*
- * indexed load a(b),d
- */
-func oploadx(ctxt *obj.Link, a int) int32 {
- switch a {
- case AMOVWZ:
- return int32(OPVCC(31, 23, 0, 0)) /* lwzx */
- case AMOVWZU:
- return int32(OPVCC(31, 55, 0, 0)) /* lwzux */
- case AMOVW:
- return int32(OPVCC(31, 341, 0, 0)) /* lwax */
- case AMOVWU:
- return int32(OPVCC(31, 373, 0, 0)) /* lwaux */
-
- case AMOVB, AMOVBZ:
- return int32(OPVCC(31, 87, 0, 0)) /* lbzx */
-
- case AMOVBU, AMOVBZU:
- return int32(OPVCC(31, 119, 0, 0)) /* lbzux */
- case AFMOVD:
- return int32(OPVCC(31, 599, 0, 0)) /* lfdx */
- case AFMOVDU:
- return int32(OPVCC(31, 631, 0, 0)) /* lfdux */
- case AFMOVS:
- return int32(OPVCC(31, 535, 0, 0)) /* lfsx */
- case AFMOVSU:
- return int32(OPVCC(31, 567, 0, 0)) /* lfsux */
- case AMOVH:
- return int32(OPVCC(31, 343, 0, 0)) /* lhax */
- case AMOVHU:
- return int32(OPVCC(31, 375, 0, 0)) /* lhaux */
- case AMOVHBR:
- return int32(OPVCC(31, 790, 0, 0)) /* lhbrx */
- case AMOVWBR:
- return int32(OPVCC(31, 534, 0, 0)) /* lwbrx */
- case AMOVHZ:
- return int32(OPVCC(31, 279, 0, 0)) /* lhzx */
- case AMOVHZU:
- return int32(OPVCC(31, 311, 0, 0)) /* lhzux */
- case AECIWX:
- return int32(OPVCC(31, 310, 0, 0)) /* eciwx */
- case ALWAR:
- return int32(OPVCC(31, 20, 0, 0)) /* lwarx */
- case ALDAR:
- return int32(OPVCC(31, 84, 0, 0))
- case ALSW:
- return int32(OPVCC(31, 533, 0, 0)) /* lswx */
+ return SP(1, 6)
+ case ALAST:
+ return SP(1, 7) /* lui */
+ case ASLL:
+ return OP(0, 0)
+ case ASRL:
+ return OP(0, 2)
+ case ASRA:
+ return OP(0, 3)
+ case AADDV:
+ return SP(3, 0)
+ case AADDVU:
+ return SP(3, 1)
+
+ case AJMP:
+ return SP(0, 2)
+ case AJAL,
+ obj.ADUFFZERO,
+ obj.ADUFFCOPY:
+ return SP(0, 3)
+ case ABEQ:
+ return SP(0, 4)
+ case ABEQ + ALAST:
+ return SP(2, 4) /* likely */
+ case ABNE:
+ return SP(0, 5)
+ case ABNE + ALAST:
+ return SP(2, 5) /* likely */
+ case ABGEZ:
+ return SP(0, 1) | BCOND(0, 1)
+ case ABGEZ + ALAST:
+ return SP(0, 1) | BCOND(0, 3) /* likely */
+ case ABGEZAL:
+ return SP(0, 1) | BCOND(2, 1)
+ case ABGEZAL + ALAST:
+ return SP(0, 1) | BCOND(2, 3) /* likely */
+ case ABGTZ:
+ return SP(0, 7)
+ case ABGTZ + ALAST:
+ return SP(2, 7) /* likely */
+ case ABLEZ:
+ return SP(0, 6)
+ case ABLEZ + ALAST:
+ return SP(2, 6) /* likely */
+ case ABLTZ:
+ return SP(0, 1) | BCOND(0, 0)
+ case ABLTZ + ALAST:
+ return SP(0, 1) | BCOND(0, 2) /* likely */
+ case ABLTZAL:
+ return SP(0, 1) | BCOND(2, 0)
+ case ABLTZAL + ALAST:
+ return SP(0, 1) | BCOND(2, 2) /* likely */
+ case ABFPT:
+ return SP(2, 1) | (257 << 16)
+ case ABFPT + ALAST:
+ return SP(2, 1) | (259 << 16) /* likely */
+ case ABFPF:
+ return SP(2, 1) | (256 << 16)
+ case ABFPF + ALAST:
+ return SP(2, 1) | (258 << 16) /* likely */
+
+ case AMOVB,
+ AMOVBU:
+ return SP(5, 0)
+ case AMOVH,
+ AMOVHU:
+ return SP(5, 1)
+ case AMOVW,
+ AMOVWU:
+ return SP(5, 3)
+ case AMOVV:
+ return SP(7, 7)
+ case AMOVF:
+ return SP(7, 1)
case AMOVD:
- return int32(OPVCC(31, 21, 0, 0)) /* ldx */
- case AMOVDU:
- return int32(OPVCC(31, 53, 0, 0)) /* ldux */
+ return SP(7, 5)
+ case AMOVWL:
+ return SP(5, 2)
+ case AMOVWR:
+ return SP(5, 6)
+ case AMOVVL:
+ return SP(5, 4)
+ case AMOVVR:
+ return SP(5, 5)
+
+ case ABREAK:
+ return SP(5, 7)
+
+ case AMOVWL + ALAST:
+ return SP(4, 2)
+ case AMOVWR + ALAST:
+ return SP(4, 6)
+ case AMOVVL + ALAST:
+ return SP(3, 2)
+ case AMOVVR + ALAST:
+ return SP(3, 3)
+ case AMOVB + ALAST:
+ return SP(4, 0)
+ case AMOVBU + ALAST:
+ return SP(4, 4)
+ case AMOVH + ALAST:
+ return SP(4, 1)
+ case AMOVHU + ALAST:
+ return SP(4, 5)
+ case AMOVW + ALAST:
+ return SP(4, 3)
+ case AMOVWU + ALAST:
+ return SP(4, 7)
+ case AMOVV + ALAST:
+ return SP(6, 7)
+ case AMOVF + ALAST:
+ return SP(6, 1)
+ case AMOVD + ALAST:
+ return SP(6, 5)
+
+ case ASLLV:
+ return OP(7, 0)
+ case ASRLV:
+ return OP(7, 2)
+ case ASRAV:
+ return OP(7, 3)
+ case ASLLV + ALAST:
+ return OP(7, 4)
+ case ASRLV + ALAST:
+ return OP(7, 6)
+ case ASRAV + ALAST:
+ return OP(7, 7)
}
- ctxt.Diag("bad loadx opcode %v", obj.Aconv(a))
- return 0
-}
-
-/*
- * store s,o(d)
- */
-func opstore(ctxt *obj.Link, a int) int32 {
- switch a {
- case AMOVB, AMOVBZ:
- return int32(OPVCC(38, 0, 0, 0)) /* stb */
-
- case AMOVBU, AMOVBZU:
- return int32(OPVCC(39, 0, 0, 0)) /* stbu */
- case AFMOVD:
- return int32(OPVCC(54, 0, 0, 0)) /* stfd */
- case AFMOVDU:
- return int32(OPVCC(55, 0, 0, 0)) /* stfdu */
- case AFMOVS:
- return int32(OPVCC(52, 0, 0, 0)) /* stfs */
- case AFMOVSU:
- return int32(OPVCC(53, 0, 0, 0)) /* stfsu */
-
- case AMOVHZ, AMOVH:
- return int32(OPVCC(44, 0, 0, 0)) /* sth */
-
- case AMOVHZU, AMOVHU:
- return int32(OPVCC(45, 0, 0, 0)) /* sthu */
- case AMOVMW:
- return int32(OPVCC(47, 0, 0, 0)) /* stmw */
- case ASTSW:
- return int32(OPVCC(31, 725, 0, 0)) /* stswi */
-
- case AMOVWZ, AMOVW:
- return int32(OPVCC(36, 0, 0, 0)) /* stw */
-
- case AMOVWZU, AMOVWU:
- return int32(OPVCC(37, 0, 0, 0)) /* stwu */
- case AMOVD:
- return int32(OPVCC(62, 0, 0, 0)) /* std */
- case AMOVDU:
- return int32(OPVCC(62, 0, 0, 1)) /* stdu */
+ if a >= ALAST {
+ ctxt.Diag("bad irr opcode %v+ALAST", obj.Aconv(a-ALAST))
+ } else {
+ ctxt.Diag("bad irr opcode %v", obj.Aconv(a))
}
-
- ctxt.Diag("unknown store opcode %v", obj.Aconv(a))
return 0
}
-/*
- * indexed store s,a(b)
- */
-func opstorex(ctxt *obj.Link, a int) int32 {
+func vshift(a int16) bool {
switch a {
- case AMOVB, AMOVBZ:
- return int32(OPVCC(31, 215, 0, 0)) /* stbx */
-
- case AMOVBU, AMOVBZU:
- return int32(OPVCC(31, 247, 0, 0)) /* stbux */
- case AFMOVD:
- return int32(OPVCC(31, 727, 0, 0)) /* stfdx */
- case AFMOVDU:
- return int32(OPVCC(31, 759, 0, 0)) /* stfdux */
- case AFMOVS:
- return int32(OPVCC(31, 663, 0, 0)) /* stfsx */
- case AFMOVSU:
- return int32(OPVCC(31, 695, 0, 0)) /* stfsux */
-
- case AMOVHZ, AMOVH:
- return int32(OPVCC(31, 407, 0, 0)) /* sthx */
- case AMOVHBR:
- return int32(OPVCC(31, 918, 0, 0)) /* sthbrx */
-
- case AMOVHZU, AMOVHU:
- return int32(OPVCC(31, 439, 0, 0)) /* sthux */
-
- case AMOVWZ, AMOVW:
- return int32(OPVCC(31, 151, 0, 0)) /* stwx */
-
- case AMOVWZU, AMOVWU:
- return int32(OPVCC(31, 183, 0, 0)) /* stwux */
- case ASTSW:
- return int32(OPVCC(31, 661, 0, 0)) /* stswx */
- case AMOVWBR:
- return int32(OPVCC(31, 662, 0, 0)) /* stwbrx */
- case ASTWCCC:
- return int32(OPVCC(31, 150, 0, 1)) /* stwcx. */
- case ASTDCCC:
- return int32(OPVCC(31, 214, 0, 1)) /* stwdx. */
- case AECOWX:
- return int32(OPVCC(31, 438, 0, 0)) /* ecowx */
- case AMOVD:
- return int32(OPVCC(31, 149, 0, 0)) /* stdx */
- case AMOVDU:
- return int32(OPVCC(31, 181, 0, 0)) /* stdux */
+ case ASLLV,
+ ASRLV,
+ ASRAV:
+ return true
}
-
- ctxt.Diag("unknown storex opcode %v", obj.Aconv(a))
- return 0
+ return false
}
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package ppc64
+package mips
import (
"cmd/internal/obj"
)
func init() {
- obj.RegisterRegister(obj.RBasePPC64, REG_DCR0+1024, Rconv)
- obj.RegisterOpcode(obj.ABasePPC64, Anames)
+ obj.RegisterRegister(obj.RBaseMIPS64, REG_FCR0+1024, Rconv)
+ obj.RegisterOpcode(obj.ABaseMIPS64, Anames)
}
func Rconv(r int) string {
if REG_F0 <= r && r <= REG_F31 {
return fmt.Sprintf("F%d", r-REG_F0)
}
- if REG_CR0 <= r && r <= REG_CR7 {
- return fmt.Sprintf("CR%d", r-REG_CR0)
+ if REG_M0 <= r && r <= REG_M31 {
+ return fmt.Sprintf("M%d", r-REG_M0)
}
- if r == REG_CR {
- return "CR"
+ if REG_FCR0 <= r && r <= REG_FCR31 {
+ return fmt.Sprintf("FCR%d", r-REG_FCR0)
}
- if REG_SPR0 <= r && r <= REG_SPR0+1023 {
- switch r {
- case REG_XER:
- return "XER"
-
- case REG_LR:
- return "LR"
-
- case REG_CTR:
- return "CTR"
- }
-
- return fmt.Sprintf("SPR(%d)", r-REG_SPR0)
- }
-
- if REG_DCR0 <= r && r <= REG_DCR0+1023 {
- return fmt.Sprintf("DCR(%d)", r-REG_DCR0)
- }
- if r == REG_FPSCR {
- return "FPSCR"
+ if r == REG_HI {
+ return "HI"
}
- if r == REG_MSR {
- return "MSR"
+ if r == REG_LO {
+ return "LO"
}
- return fmt.Sprintf("Rgok(%d)", r-obj.RBasePPC64)
+ return fmt.Sprintf("Rgok(%d)", r-obj.RBaseMIPS64)
}
func DRconv(a int) string {
s := "C_??"
if a >= C_NONE && a <= C_NCLASS {
- s = cnames9[a]
+ s = cnames0[a]
}
var fp string
fp += s
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package ppc64
+package mips
import (
"cmd/internal/obj"
p.From.Class = 0
p.To.Class = 0
- // Rewrite BR/BL to symbol as TYPE_BRANCH.
+ // Rewrite JMP/JAL to symbol as TYPE_BRANCH.
switch p.As {
- case ABR,
- ABL,
- obj.ARET,
+ case AJMP,
+ AJAL,
+ ARET,
obj.ADUFFZERO,
obj.ADUFFCOPY:
if p.To.Sym != nil {
// Rewrite float constants to values stored in memory.
switch p.As {
- case AFMOVS:
+ case AMOVF:
if p.From.Type == obj.TYPE_FCONST {
f32 := float32(p.From.Val.(float64))
i32 := math.Float32bits(f32)
p.From.Offset = 0
}
- case AFMOVD:
+ case AMOVD:
if p.From.Type == obj.TYPE_FCONST {
i64 := math.Float64bits(p.From.Val.(float64))
literal := fmt.Sprintf("$f64.%016x", i64)
}
// Put >32-bit constants in memory and load them
- case AMOVD:
+ case AMOVV:
if p.From.Type == obj.TYPE_CONST && p.From.Name == obj.NAME_NONE && p.From.Reg == 0 && int64(int32(p.From.Offset)) != p.From.Offset {
literal := fmt.Sprintf("$i64.%016x", uint64(p.From.Offset))
s := obj.Linklookup(ctxt, literal, 0)
// Rewrite SUB constants into ADD.
switch p.As {
- case ASUBC:
+ case ASUB:
if p.From.Type == obj.TYPE_CONST {
p.From.Offset = -p.From.Offset
- p.As = AADDC
+ p.As = AADD
}
- case ASUBCCC:
+ case ASUBU:
if p.From.Type == obj.TYPE_CONST {
p.From.Offset = -p.From.Offset
- p.As = AADDCCC
+ p.As = AADDU
}
- case ASUB:
+ case ASUBV:
if p.From.Type == obj.TYPE_CONST {
p.From.Offset = -p.From.Offset
- p.As = AADD
+ p.As = AADDV
+ }
+
+ case ASUBVU:
+ if p.From.Type == obj.TYPE_CONST {
+ p.From.Offset = -p.From.Offset
+ p.As = AADDVU
}
}
}
// TODO(minux): add morestack short-cuts with small fixed frame-size.
ctxt.Cursym = cursym
+ // a switch for enabling/disabling instruction scheduling
+ nosched := true
+
if cursym.Text == nil || cursym.Text.Link == nil {
return
}
p.Link.Mark |= LABEL
}
- case ANOR:
+ /* too hard, just leave alone */
+ case AMOVW,
+ AMOVV:
q = p
- if p.To.Type == obj.TYPE_REG {
- if p.To.Reg == REGZERO {
- p.Mark |= LABEL | SYNC
- }
+ if p.To.Type == obj.TYPE_REG && p.To.Reg >= REG_SPECIAL {
+ p.Mark |= LABEL | SYNC
+ break
+ }
+ if p.From.Type == obj.TYPE_REG && p.From.Reg >= REG_SPECIAL {
+ p.Mark |= LABEL | SYNC
}
- case ALWAR,
- ASTWCCC,
- AECIWX,
- AECOWX,
- AEIEIO,
- AICBI,
- AISYNC,
- ATLBIE,
- ATLBIEL,
- ASLBIA,
- ASLBIE,
- ASLBMFEE,
- ASLBMFEV,
- ASLBMTE,
- ADCBF,
- ADCBI,
- ADCBST,
- ADCBT,
- ADCBTST,
- ADCBZ,
- ASYNC,
- ATLBSYNC,
- APTESYNC,
- ATW,
+ /* too hard, just leave alone */
+ case ASYSCALL,
AWORD,
- ARFI,
- ARFCI,
- ARFID,
- AHRFID:
+ ATLBWR,
+ ATLBWI,
+ ATLBP,
+ ATLBR:
q = p
p.Mark |= LABEL | SYNC
- continue
- case AMOVW, AMOVWZ, AMOVD:
+ case ANOR:
q = p
- if p.From.Reg >= REG_SPECIAL || p.To.Reg >= REG_SPECIAL {
- p.Mark |= LABEL | SYNC
+ if p.To.Type == obj.TYPE_REG {
+ if p.To.Reg == REGZERO {
+ p.Mark |= LABEL | SYNC
+ }
}
- continue
-
- case AFABS,
- AFABSCC,
- AFADD,
- AFADDCC,
- AFCTIW,
- AFCTIWCC,
- AFCTIWZ,
- AFCTIWZCC,
- AFDIV,
- AFDIVCC,
- AFMADD,
- AFMADDCC,
- AFMOVD,
- AFMOVDU,
- /* case AFMOVDS: */
- AFMOVS,
- AFMOVSU,
-
- /* case AFMOVSD: */
- AFMSUB,
- AFMSUBCC,
- AFMUL,
- AFMULCC,
- AFNABS,
- AFNABSCC,
- AFNEG,
- AFNEGCC,
- AFNMADD,
- AFNMADDCC,
- AFNMSUB,
- AFNMSUBCC,
- AFRSP,
- AFRSPCC,
- AFSUB,
- AFSUBCC:
- q = p
- p.Mark |= FLOAT
- continue
-
- case ABL,
- ABCL,
+ case ABGEZAL,
+ ABLTZAL,
+ AJAL,
obj.ADUFFZERO,
obj.ADUFFCOPY:
cursym.Text.Mark &^= LEAF
fallthrough
- case ABC,
+ case AJMP,
ABEQ,
- ABGE,
- ABGT,
- ABLE,
- ABLT,
+ ABGEZ,
+ ABGTZ,
+ ABLEZ,
+ ABLTZ,
ABNE,
- ABR,
- ABVC,
- ABVS:
- p.Mark |= BRANCH
+ ABFPT, ABFPF:
+ if p.As == ABFPT || p.As == ABFPF {
+ // We don't treat ABFPT and ABFPF as branches here,
+ // so that we will always fill nop (0x0) in their
+ // delay slot during assembly.
+ // This is to workaround a kernel FPU emulator bug
+ // where it uses the user stack to simulate the
+ // instruction in the delay slot if it's not 0x0,
+ // and somehow that leads to SIGSEGV when the kernel
+ // jump to the stack.
+ p.Mark |= SYNC
+ } else {
+ p.Mark |= BRANCH
+ }
q = p
q1 = p.Pcond
if q1 != nil {
if q1.Mark&LEAF == 0 {
q1.Mark |= LABEL
}
- } else {
- p.Mark |= LABEL
}
+ //else {
+ // p.Mark |= LABEL
+ //}
q1 = p.Link
if q1 != nil {
q1.Mark |= LABEL
}
continue
- case AFCMPO, AFCMPU:
- q = p
- p.Mark |= FCMP | FLOAT
- continue
-
- case obj.ARET:
+ case ARET:
q = p
if p.Link != nil {
p.Link.Mark |= LABEL
}
autosize := int32(0)
- var aoffset int
- var mov int
var o int
var p1 *obj.Prog
var p2 *obj.Prog
o = int(p.As)
switch o {
case obj.ATEXT:
- mov = AMOVD
- aoffset = 0
autosize = int32(textstksiz + 8)
if (p.Mark&LEAF != 0) && autosize <= 8 {
autosize = 0
q = p
if autosize != 0 {
- /* use MOVDU to adjust R1 when saving R31, if autosize is small */
- if cursym.Text.Mark&LEAF == 0 && autosize >= -BIG && autosize <= BIG {
- mov = AMOVDU
- aoffset = int(-autosize)
- } else {
- q = obj.Appendp(ctxt, p)
- q.As = AADD
- q.Lineno = p.Lineno
- q.From.Type = obj.TYPE_CONST
- q.From.Offset = int64(-autosize)
- q.To.Type = obj.TYPE_REG
- q.To.Reg = REGSP
- q.Spadj = +autosize
- }
+ q = obj.Appendp(ctxt, p)
+ q.As = AADDV
+ q.Lineno = p.Lineno
+ q.From.Type = obj.TYPE_CONST
+ q.From.Offset = int64(-autosize)
+ q.To.Type = obj.TYPE_REG
+ q.To.Reg = REGSP
+ q.Spadj = +autosize
} else if cursym.Text.Mark&LEAF == 0 {
- if ctxt.Debugvlog != 0 {
- fmt.Fprintf(ctxt.Bso, "save suppressed in: %s\n", cursym.Name)
- ctxt.Bso.Flush()
- }
+ if cursym.Text.From3.Offset&obj.NOSPLIT != 0 {
+ if ctxt.Debugvlog != 0 {
+ fmt.Fprintf(ctxt.Bso, "save suppressed in: %s\n", cursym.Name)
+ ctxt.Bso.Flush()
+ }
- cursym.Text.Mark |= LEAF
+ cursym.Text.Mark |= LEAF
+ }
}
if cursym.Text.Mark&LEAF != 0 {
}
q = obj.Appendp(ctxt, q)
- q.As = AMOVD
- q.Lineno = p.Lineno
- q.From.Type = obj.TYPE_REG
- q.From.Reg = REG_LR
- q.To.Type = obj.TYPE_REG
- q.To.Reg = REGTMP
-
- q = obj.Appendp(ctxt, q)
- q.As = int16(mov)
+ q.As = AMOVV
q.Lineno = p.Lineno
q.From.Type = obj.TYPE_REG
- q.From.Reg = REGTMP
+ q.From.Reg = REGLINK
q.To.Type = obj.TYPE_MEM
- q.To.Offset = int64(aoffset)
+ q.To.Offset = int64(0)
q.To.Reg = REGSP
- if q.As == AMOVDU {
- q.Spadj = int32(-aoffset)
- }
if cursym.Text.From3.Offset&obj.WRAPPER != 0 {
// if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
//
- // MOVD g_panic(g), R3
- // CMP R0, R3
- // BEQ end
- // MOVD panic_argp(R3), R4
- // ADD $(autosize+8), R1, R5
- // CMP R4, R5
- // BNE end
- // ADD $8, R1, R6
- // MOVD R6, panic_argp(R3)
+ // MOVV g_panic(g), R1
+ // BEQ R1, end
+ // MOVV panic_argp(R1), R2
+ // ADDV $(autosize+8), R29, R3
+ // BNE R2, R3, end
+ // ADDV $8, R29, R2
+ // MOVV R2, panic_argp(R1)
// end:
// NOP
//
// The NOP is needed to give the jumps somewhere to land.
- // It is a liblink NOP, not a ppc64 NOP: it encodes to 0 instruction bytes.
+ // It is a liblink NOP, not an mips NOP: it encodes to 0 instruction bytes.
q = obj.Appendp(ctxt, q)
- q.As = AMOVD
+ q.As = AMOVV
q.From.Type = obj.TYPE_MEM
q.From.Reg = REGG
q.From.Offset = 4 * int64(ctxt.Arch.Ptrsize) // G.panic
q.To.Type = obj.TYPE_REG
- q.To.Reg = REG_R3
-
- q = obj.Appendp(ctxt, q)
- q.As = ACMP
- q.From.Type = obj.TYPE_REG
- q.From.Reg = REG_R0
- q.To.Type = obj.TYPE_REG
- q.To.Reg = REG_R3
+ q.To.Reg = REG_R1
q = obj.Appendp(ctxt, q)
q.As = ABEQ
+ q.From.Type = obj.TYPE_REG
+ q.From.Reg = REG_R1
q.To.Type = obj.TYPE_BRANCH
+ q.Mark |= BRANCH
p1 = q
q = obj.Appendp(ctxt, q)
- q.As = AMOVD
+ q.As = AMOVV
q.From.Type = obj.TYPE_MEM
- q.From.Reg = REG_R3
+ q.From.Reg = REG_R1
q.From.Offset = 0 // Panic.argp
q.To.Type = obj.TYPE_REG
- q.To.Reg = REG_R4
+ q.To.Reg = REG_R2
q = obj.Appendp(ctxt, q)
- q.As = AADD
+ q.As = AADDV
q.From.Type = obj.TYPE_CONST
q.From.Offset = int64(autosize) + 8
q.Reg = REGSP
q.To.Type = obj.TYPE_REG
- q.To.Reg = REG_R5
-
- q = obj.Appendp(ctxt, q)
- q.As = ACMP
- q.From.Type = obj.TYPE_REG
- q.From.Reg = REG_R4
- q.To.Type = obj.TYPE_REG
- q.To.Reg = REG_R5
+ q.To.Reg = REG_R3
q = obj.Appendp(ctxt, q)
q.As = ABNE
+ q.From.Type = obj.TYPE_REG
+ q.From.Reg = REG_R2
+ q.Reg = REG_R3
q.To.Type = obj.TYPE_BRANCH
+ q.Mark |= BRANCH
p2 = q
q = obj.Appendp(ctxt, q)
- q.As = AADD
+ q.As = AADDV
q.From.Type = obj.TYPE_CONST
q.From.Offset = 8
q.Reg = REGSP
q.To.Type = obj.TYPE_REG
- q.To.Reg = REG_R6
+ q.To.Reg = REG_R2
q = obj.Appendp(ctxt, q)
- q.As = AMOVD
+ q.As = AMOVV
q.From.Type = obj.TYPE_REG
- q.From.Reg = REG_R6
+ q.From.Reg = REG_R2
q.To.Type = obj.TYPE_MEM
- q.To.Reg = REG_R3
+ q.To.Reg = REG_R1
q.To.Offset = 0 // Panic.argp
q = obj.Appendp(ctxt, q)
p2.Pcond = q
}
- case obj.ARET:
+ case ARET:
if p.From.Type == obj.TYPE_CONST {
ctxt.Diag("using BECOME (%v) is not supported!", p)
break
}
if p.To.Sym != nil { // retjmp
- p.As = ABR
+ p.As = AJMP
p.To.Type = obj.TYPE_BRANCH
break
}
if cursym.Text.Mark&LEAF != 0 {
if autosize == 0 {
- p.As = ABR
+ p.As = AJMP
p.From = obj.Addr{}
- p.To.Type = obj.TYPE_REG
- p.To.Reg = REG_LR
+ p.To.Type = obj.TYPE_MEM
+ p.To.Offset = 0
+ p.To.Reg = REGLINK
p.Mark |= BRANCH
break
}
- p.As = AADD
+ p.As = AADDV
p.From.Type = obj.TYPE_CONST
p.From.Offset = int64(autosize)
p.To.Type = obj.TYPE_REG
p.Spadj = -autosize
q = ctxt.NewProg()
- q.As = ABR
+ q.As = AJMP
q.Lineno = p.Lineno
- q.To.Type = obj.TYPE_REG
- q.To.Reg = REG_LR
+ q.To.Type = obj.TYPE_MEM
+ q.To.Offset = 0
+ q.To.Reg = REGLINK
q.Mark |= BRANCH
q.Spadj = +autosize
break
}
- p.As = AMOVD
+ p.As = AMOVV
p.From.Type = obj.TYPE_MEM
p.From.Offset = 0
p.From.Reg = REGSP
p.To.Type = obj.TYPE_REG
- p.To.Reg = REGTMP
-
- q = ctxt.NewProg()
- q.As = AMOVD
- q.Lineno = p.Lineno
- q.From.Type = obj.TYPE_REG
- q.From.Reg = REGTMP
- q.To.Type = obj.TYPE_REG
- q.To.Reg = REG_LR
-
- q.Link = p.Link
- p.Link = q
- p = q
+ p.To.Reg = REG_R4
if false {
// Debug bad returns
q = ctxt.NewProg()
- q.As = AMOVD
+ q.As = AMOVV
q.Lineno = p.Lineno
q.From.Type = obj.TYPE_MEM
q.From.Offset = 0
- q.From.Reg = REGTMP
+ q.From.Reg = REG_R4
q.To.Type = obj.TYPE_REG
q.To.Reg = REGTMP
if autosize != 0 {
q = ctxt.NewProg()
- q.As = AADD
+ q.As = AADDV
q.Lineno = p.Lineno
q.From.Type = obj.TYPE_CONST
q.From.Offset = int64(autosize)
}
q1 = ctxt.NewProg()
- q1.As = ABR
+ q1.As = AJMP
q1.Lineno = p.Lineno
- q1.To.Type = obj.TYPE_REG
- q1.To.Reg = REG_LR
+ q1.To.Type = obj.TYPE_MEM
+ q1.To.Offset = 0
+ q1.To.Reg = REG_R4
q1.Mark |= BRANCH
q1.Spadj = +autosize
q1.Link = q.Link
q.Link = q1
- case AADD:
+ case AADDV,
+ AADDVU:
if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.From.Type == obj.TYPE_CONST {
p.Spadj = int32(-p.From.Offset)
}
}
}
+
+ if nosched {
+ // if we don't do instruction scheduling, simply add
+ // NOP after each branch instruction.
+ for p = cursym.Text; p != nil; p = p.Link {
+ if p.Mark&BRANCH != 0 {
+ addnop(ctxt, p)
+ }
+ }
+ return
+ }
+
+ // instruction scheduling
+ q = nil // p - 1
+ q1 = cursym.Text // top of block
+ o = 0 // count of instructions
+ for p = cursym.Text; p != nil; p = p1 {
+ p1 = p.Link
+ o++
+ if p.Mark&NOSCHED != 0 {
+ if q1 != p {
+ sched(ctxt, q1, q)
+ }
+ for ; p != nil; p = p.Link {
+ if p.Mark&NOSCHED == 0 {
+ break
+ }
+ q = p
+ }
+ p1 = p
+ q1 = p
+ o = 0
+ continue
+ }
+ if p.Mark&(LABEL|SYNC) != 0 {
+ if q1 != p {
+ sched(ctxt, q1, q)
+ }
+ q1 = p
+ o = 1
+ }
+ if p.Mark&(BRANCH|SYNC) != 0 {
+ sched(ctxt, q1, p)
+ q1 = p1
+ o = 0
+ }
+ if o >= NSCHED {
+ sched(ctxt, q1, p)
+ q1 = p1
+ o = 0
+ }
+ q = p
+ }
}
-/*
-// instruction scheduling
- if(debug['Q'] == 0)
- return;
-
- curtext = nil;
- q = nil; // p - 1
- q1 = firstp; // top of block
- o = 0; // count of instructions
- for(p = firstp; p != nil; p = p1) {
- p1 = p->link;
- o++;
- if(p->mark & NOSCHED){
- if(q1 != p){
- sched(q1, q);
- }
- for(; p != nil; p = p->link){
- if(!(p->mark & NOSCHED))
- break;
- q = p;
- }
- p1 = p;
- q1 = p;
- o = 0;
- continue;
- }
- if(p->mark & (LABEL|SYNC)) {
- if(q1 != p)
- sched(q1, q);
- q1 = p;
- o = 1;
- }
- if(p->mark & (BRANCH|SYNC)) {
- sched(q1, p);
- q1 = p1;
- o = 0;
- }
- if(o >= NSCHED) {
- sched(q1, p);
- q1 = p1;
- o = 0;
- }
- q = p;
- }
-*/
func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32) *obj.Prog {
- // MOVD g_stackguard(g), R3
+ // MOVV g_stackguard(g), R1
p = obj.Appendp(ctxt, p)
- p.As = AMOVD
+ p.As = AMOVV
p.From.Type = obj.TYPE_MEM
p.From.Reg = REGG
p.From.Offset = 2 * int64(ctxt.Arch.Ptrsize) // G.stackguard0
p.From.Offset = 3 * int64(ctxt.Arch.Ptrsize) // G.stackguard1
}
p.To.Type = obj.TYPE_REG
- p.To.Reg = REG_R3
+ p.To.Reg = REG_R1
var q *obj.Prog
if framesize <= obj.StackSmall {
// small stack: SP < stackguard
- // CMP stackguard, SP
+ // AGTU SP, stackguard, R1
p = obj.Appendp(ctxt, p)
- p.As = ACMPU
+ p.As = ASGTU
p.From.Type = obj.TYPE_REG
- p.From.Reg = REG_R3
+ p.From.Reg = REGSP
+ p.Reg = REG_R1
p.To.Type = obj.TYPE_REG
- p.To.Reg = REGSP
+ p.To.Reg = REG_R1
} else if framesize <= obj.StackBig {
// large stack: SP-framesize < stackguard-StackSmall
- // ADD $-framesize, SP, R4
- // CMP stackguard, R4
+ // ADDV $-framesize, SP, R2
+ // SGTU R2, stackguard, R1
p = obj.Appendp(ctxt, p)
- p.As = AADD
+ p.As = AADDV
p.From.Type = obj.TYPE_CONST
p.From.Offset = int64(-framesize)
p.Reg = REGSP
p.To.Type = obj.TYPE_REG
- p.To.Reg = REG_R4
+ p.To.Reg = REG_R2
p = obj.Appendp(ctxt, p)
- p.As = ACMPU
+ p.As = ASGTU
p.From.Type = obj.TYPE_REG
- p.From.Reg = REG_R3
+ p.From.Reg = REG_R2
+ p.Reg = REG_R1
p.To.Type = obj.TYPE_REG
- p.To.Reg = REG_R4
+ p.To.Reg = REG_R1
} else {
// Such a large stack we need to protect against wraparound.
// If SP is close to zero:
//
// Preemption sets stackguard to StackPreempt, a very large value.
// That breaks the math above, so we have to check for that explicitly.
- // // stackguard is R3
- // CMP R3, $StackPreempt
- // BEQ label-of-call-to-morestack
- // ADD $StackGuard, SP, R4
- // SUB R3, R4
- // MOVD $(framesize+(StackGuard-StackSmall)), R31
- // CMPU R31, R4
+ // // stackguard is R1
+ // MOVV $StackPreempt, R2
+ // BEQ R1, R2, label-of-call-to-morestack
+ // ADDV $StackGuard, SP, R2
+ // SUBVU R1, R2
+ // MOVV $(framesize+(StackGuard-StackSmall)), R1
+ // SGTU R2, R1, R1
p = obj.Appendp(ctxt, p)
- p.As = ACMP
- p.From.Type = obj.TYPE_REG
- p.From.Reg = REG_R3
- p.To.Type = obj.TYPE_CONST
- p.To.Offset = obj.StackPreempt
+ p.As = AMOVV
+ p.From.Type = obj.TYPE_CONST
+ p.From.Offset = obj.StackPreempt
+ p.To.Type = obj.TYPE_REG
+ p.To.Reg = REG_R2
p = obj.Appendp(ctxt, p)
q = p
p.As = ABEQ
+ p.From.Type = obj.TYPE_REG
+ p.From.Reg = REG_R1
+ p.Reg = REG_R2
p.To.Type = obj.TYPE_BRANCH
+ p.Mark |= BRANCH
p = obj.Appendp(ctxt, p)
- p.As = AADD
+ p.As = AADDV
p.From.Type = obj.TYPE_CONST
p.From.Offset = obj.StackGuard
p.Reg = REGSP
p.To.Type = obj.TYPE_REG
- p.To.Reg = REG_R4
+ p.To.Reg = REG_R2
p = obj.Appendp(ctxt, p)
- p.As = ASUB
+ p.As = ASUBVU
p.From.Type = obj.TYPE_REG
- p.From.Reg = REG_R3
+ p.From.Reg = REG_R1
p.To.Type = obj.TYPE_REG
- p.To.Reg = REG_R4
+ p.To.Reg = REG_R2
p = obj.Appendp(ctxt, p)
- p.As = AMOVD
+ p.As = AMOVV
p.From.Type = obj.TYPE_CONST
p.From.Offset = int64(framesize) + obj.StackGuard - obj.StackSmall
p.To.Type = obj.TYPE_REG
- p.To.Reg = REGTMP
+ p.To.Reg = REG_R1
p = obj.Appendp(ctxt, p)
- p.As = ACMPU
+ p.As = ASGTU
p.From.Type = obj.TYPE_REG
- p.From.Reg = REGTMP
+ p.From.Reg = REG_R2
+ p.Reg = REG_R1
p.To.Type = obj.TYPE_REG
- p.To.Reg = REG_R4
+ p.To.Reg = REG_R1
}
- // q1: BLT done
+ // q1: BNE R1, done
p = obj.Appendp(ctxt, p)
q1 := p
- p.As = ABLT
+ p.As = ABNE
+ p.From.Type = obj.TYPE_REG
+ p.From.Reg = REG_R1
p.To.Type = obj.TYPE_BRANCH
+ p.Mark |= BRANCH
- // MOVD LR, R5
+ // MOVV LINK, R3
p = obj.Appendp(ctxt, p)
- p.As = AMOVD
+ p.As = AMOVV
p.From.Type = obj.TYPE_REG
- p.From.Reg = REG_LR
+ p.From.Reg = REGLINK
p.To.Type = obj.TYPE_REG
- p.To.Reg = REG_R5
+ p.To.Reg = REG_R3
if q != nil {
q.Pcond = p
+ p.Mark |= LABEL
}
- // BL runtime.morestack(SB)
+ // JAL runtime.morestack(SB)
p = obj.Appendp(ctxt, p)
- p.As = ABL
+ p.As = AJAL
p.To.Type = obj.TYPE_BRANCH
if ctxt.Cursym.Cfunc != 0 {
p.To.Sym = obj.Linklookup(ctxt, "runtime.morestackc", 0)
} else {
p.To.Sym = obj.Linklookup(ctxt, "runtime.morestack", 0)
}
+ p.Mark |= BRANCH
- // BR start
+ // JMP start
p = obj.Appendp(ctxt, p)
- p.As = ABR
+ p.As = AJMP
p.To.Type = obj.TYPE_BRANCH
p.Pcond = ctxt.Cursym.Text.Link
+ p.Mark |= BRANCH
// placeholder for q1's jump target
p = obj.Appendp(ctxt, p)
return p
}
-func follow(ctxt *obj.Link, s *obj.LSym) {
- ctxt.Cursym = s
+func addnop(ctxt *obj.Link, p *obj.Prog) {
+ q := ctxt.NewProg()
+ // we want to use the canonical NOP (SLL $0,R0,R0) here,
+ // however, as the assembler will always replace $0
+ // as R0, we have to resort to manually encode the SLL
+ // instruction as WORD $0.
+ q.As = AWORD
+ q.Lineno = p.Lineno
+ q.From.Type = obj.TYPE_CONST
+ q.From.Name = obj.NAME_NONE
+ q.From.Offset = 0
+
+ q.Link = p.Link
+ p.Link = q
+}
- firstp := ctxt.NewProg()
- lastp := firstp
- xfol(ctxt, s.Text, &lastp)
- lastp.Link = nil
- s.Text = firstp.Link
+const (
+ E_HILO = 1 << 0
+ E_FCR = 1 << 1
+ E_MCR = 1 << 2
+ E_MEM = 1 << 3
+ E_MEMSP = 1 << 4 /* uses offset and size */
+ E_MEMSB = 1 << 5 /* uses offset and size */
+ ANYMEM = E_MEM | E_MEMSP | E_MEMSB
+ //DELAY = LOAD|BRANCH|FCMP
+ DELAY = BRANCH /* only schedule branch */
+)
+
+type Dep struct {
+ ireg uint32
+ freg uint32
+ cc uint32
+}
+
+type Sch struct {
+ p obj.Prog
+ set Dep
+ used Dep
+ soffset int32
+ size uint8
+ nop uint8
+ comp bool
}
-func relinv(a int) int {
- switch a {
- case ABEQ:
- return ABNE
- case ABNE:
- return ABEQ
+func sched(ctxt *obj.Link, p0, pe *obj.Prog) {
+ var sch [NSCHED]Sch
- case ABGE:
- return ABLT
- case ABLT:
- return ABGE
+ /*
+ * build side structure
+ */
+ s := sch[:]
+ for p := p0; ; p = p.Link {
+ s[0].p = *p
+ markregused(ctxt, &s[0])
+ if p == pe {
+ break
+ }
+ s = s[1:]
+ }
+ se := s
- case ABGT:
- return ABLE
- case ABLE:
- return ABGT
+ for i := cap(sch) - cap(se); i >= 0; i-- {
+ s = sch[i:]
+ if s[0].p.Mark&DELAY == 0 {
+ continue
+ }
+ if -cap(s) < -cap(se) {
+ if !conflict(&s[0], &s[1]) {
+ continue
+ }
+ }
- case ABVC:
- return ABVS
- case ABVS:
- return ABVC
+ var t []Sch
+ var j int
+ for j = cap(sch) - cap(s) - 1; j >= 0; j-- {
+ t = sch[j:]
+ if t[0].comp {
+ if s[0].p.Mark&BRANCH != 0 {
+ goto no2
+ }
+ }
+ if t[0].p.Mark&DELAY != 0 {
+ if -cap(s) >= -cap(se) || conflict(&t[0], &s[1]) {
+ goto no2
+ }
+ }
+ for u := t[1:]; -cap(u) <= -cap(s); u = u[1:] {
+ if depend(ctxt, &u[0], &t[0]) {
+ goto no2
+ }
+ }
+ goto out2
+ no2:
+ }
+
+ if s[0].p.Mark&BRANCH != 0 {
+ s[0].nop = 1
+ }
+ continue
+
+ out2:
+ // t[0] is the instruction being moved to fill the delay
+ stmp := t[0]
+ copy(t[:i-j], t[1:i-j+1])
+ s[0] = stmp
+
+ if t[i-j-1].p.Mark&BRANCH != 0 {
+ // t[i-j] is being put into a branch delay slot
+ // combine its Spadj with the branch instruction
+ t[i-j-1].p.Spadj += t[i-j].p.Spadj
+ t[i-j].p.Spadj = 0
+ }
+
+ i--
+ }
+
+ /*
+ * put it all back
+ */
+ var p *obj.Prog
+ var q *obj.Prog
+ for s, p = sch[:], p0; -cap(s) <= -cap(se); s, p = s[1:], q {
+ q = p.Link
+ if q != s[0].p.Link {
+ *p = s[0].p
+ p.Link = q
+ }
+ for s[0].nop != 0 {
+ s[0].nop--
+ addnop(ctxt, p)
+ }
+ }
+}
+
+func markregused(ctxt *obj.Link, s *Sch) {
+ p := &s.p
+ s.comp = compound(ctxt, p)
+ s.nop = 0
+ if s.comp {
+ s.set.ireg |= 1 << (REGTMP - REG_R0)
+ s.used.ireg |= 1 << (REGTMP - REG_R0)
+ }
+
+ ar := 0 /* dest is really reference */
+ ad := 0 /* source/dest is really address */
+ ld := 0 /* opcode is load instruction */
+ sz := 20 /* size of load/store for overlap computation */
+
+ /*
+ * flags based on opcode
+ */
+ switch p.As {
+ case obj.ATEXT:
+ ctxt.Autosize = int32(p.To.Offset + 8)
+ ad = 1
+
+ case AJAL:
+ c := p.Reg
+ if c == 0 {
+ c = REGLINK
+ }
+ s.set.ireg |= 1 << uint(c-REG_R0)
+ ar = 1
+ ad = 1
+
+ case ABGEZAL,
+ ABLTZAL:
+ s.set.ireg |= 1 << (REGLINK - REG_R0)
+ fallthrough
+ case ABEQ,
+ ABGEZ,
+ ABGTZ,
+ ABLEZ,
+ ABLTZ,
+ ABNE:
+ ar = 1
+ ad = 1
+
+ case ABFPT,
+ ABFPF:
+ ad = 1
+ s.used.cc |= E_FCR
+
+ case ACMPEQD,
+ ACMPEQF,
+ ACMPGED,
+ ACMPGEF,
+ ACMPGTD,
+ ACMPGTF:
+ ar = 1
+ s.set.cc |= E_FCR
+ p.Mark |= FCMP
+
+ case AJMP:
+ ar = 1
+ ad = 1
+
+ case AMOVB,
+ AMOVBU:
+ sz = 1
+ ld = 1
+
+ case AMOVH,
+ AMOVHU:
+ sz = 2
+ ld = 1
+
+ case AMOVF,
+ AMOVW,
+ AMOVWL,
+ AMOVWR:
+ sz = 4
+ ld = 1
+
+ case AMOVD,
+ AMOVV,
+ AMOVVL,
+ AMOVVR:
+ sz = 8
+ ld = 1
+
+ case ADIV,
+ ADIVU,
+ AMUL,
+ AMULU,
+ AREM,
+ AREMU,
+ ADIVV,
+ ADIVVU,
+ AMULV,
+ AMULVU,
+ AREMV,
+ AREMVU:
+ s.set.cc = E_HILO
+ fallthrough
+ case AADD,
+ AADDU,
+ AADDV,
+ AADDVU,
+ AAND,
+ ANOR,
+ AOR,
+ ASGT,
+ ASGTU,
+ ASLL,
+ ASRA,
+ ASRL,
+ ASLLV,
+ ASRAV,
+ ASRLV,
+ ASUB,
+ ASUBU,
+ ASUBV,
+ ASUBVU,
+ AXOR,
+
+ AADDD,
+ AADDF,
+ AADDW,
+ ASUBD,
+ ASUBF,
+ ASUBW,
+ AMULF,
+ AMULD,
+ AMULW,
+ ADIVF,
+ ADIVD,
+ ADIVW:
+ if p.Reg == 0 {
+ if p.To.Type == obj.TYPE_REG {
+ p.Reg = p.To.Reg
+ }
+ //if(p->reg == NREG)
+ // print("botch %P\n", p);
+ }
+ }
+
+ /*
+ * flags based on 'to' field
+ */
+ c := int(p.To.Class)
+ if c == 0 {
+ c = aclass(ctxt, &p.To) + 1
+ p.To.Class = int8(c)
+ }
+ c--
+ switch c {
+ default:
+ fmt.Printf("unknown class %d %v\n", c, p)
+
+ case C_ZCON,
+ C_SCON,
+ C_ADD0CON,
+ C_AND0CON,
+ C_ADDCON,
+ C_ANDCON,
+ C_UCON,
+ C_LCON,
+ C_NONE,
+ C_SBRA,
+ C_LBRA,
+ C_ADDR,
+ C_TEXTSIZE:
+ break
+
+ case C_HI,
+ C_LO:
+ s.set.cc |= E_HILO
+
+ case C_FCREG:
+ s.set.cc |= E_FCR
+
+ case C_MREG:
+ s.set.cc |= E_MCR
+
+ case C_ZOREG,
+ C_SOREG,
+ C_LOREG:
+ c = int(p.To.Reg)
+ s.used.ireg |= 1 << uint(c-REG_R0)
+ if ad != 0 {
+ break
+ }
+ s.size = uint8(sz)
+ s.soffset = regoff(ctxt, &p.To)
+
+ m := uint32(ANYMEM)
+ if c == REGSB {
+ m = E_MEMSB
+ }
+ if c == REGSP {
+ m = E_MEMSP
+ }
+
+ if ar != 0 {
+ s.used.cc |= m
+ } else {
+ s.set.cc |= m
+ }
+
+ case C_SACON,
+ C_LACON:
+ s.used.ireg |= 1 << (REGSP - REG_R0)
+
+ case C_SECON,
+ C_LECON:
+ s.used.ireg |= 1 << (REGSB - REG_R0)
+
+ case C_REG:
+ if ar != 0 {
+ s.used.ireg |= 1 << uint(p.To.Reg-REG_R0)
+ } else {
+ s.set.ireg |= 1 << uint(p.To.Reg-REG_R0)
+ }
+
+ case C_FREG:
+ if ar != 0 {
+ s.used.freg |= 1 << uint(p.To.Reg-REG_F0)
+ } else {
+ s.set.freg |= 1 << uint(p.To.Reg-REG_F0)
+ }
+ if ld != 0 && p.From.Type == obj.TYPE_REG {
+ p.Mark |= LOAD
+ }
+
+ case C_SAUTO,
+ C_LAUTO:
+ s.used.ireg |= 1 << (REGSP - REG_R0)
+ if ad != 0 {
+ break
+ }
+ s.size = uint8(sz)
+ s.soffset = regoff(ctxt, &p.To)
+
+ if ar != 0 {
+ s.used.cc |= E_MEMSP
+ } else {
+ s.set.cc |= E_MEMSP
+ }
+
+ case C_SEXT,
+ C_LEXT:
+ s.used.ireg |= 1 << (REGSB - REG_R0)
+ if ad != 0 {
+ break
+ }
+ s.size = uint8(sz)
+ s.soffset = regoff(ctxt, &p.To)
+
+ if ar != 0 {
+ s.used.cc |= E_MEMSB
+ } else {
+ s.set.cc |= E_MEMSB
+ }
+ }
+
+ /*
+ * flags based on 'from' field
+ */
+ c = int(p.From.Class)
+ if c == 0 {
+ c = aclass(ctxt, &p.From) + 1
+ p.From.Class = int8(c)
+ }
+ c--
+ switch c {
+ default:
+ fmt.Printf("unknown class %d %v\n", c, p)
+
+ case C_ZCON,
+ C_SCON,
+ C_ADD0CON,
+ C_AND0CON,
+ C_ADDCON,
+ C_ANDCON,
+ C_UCON,
+ C_LCON,
+ C_NONE,
+ C_SBRA,
+ C_LBRA,
+ C_ADDR,
+ C_TEXTSIZE:
+ break
+
+ case C_HI,
+ C_LO:
+ s.used.cc |= E_HILO
+
+ case C_FCREG:
+ s.used.cc |= E_FCR
+
+ case C_MREG:
+ s.used.cc |= E_MCR
+
+ case C_ZOREG,
+ C_SOREG,
+ C_LOREG:
+ c = int(p.From.Reg)
+ s.used.ireg |= 1 << uint(c-REG_R0)
+ if ld != 0 {
+ p.Mark |= LOAD
+ }
+ s.size = uint8(sz)
+ s.soffset = regoff(ctxt, &p.From)
+
+ m := uint32(ANYMEM)
+ if c == REGSB {
+ m = E_MEMSB
+ }
+ if c == REGSP {
+ m = E_MEMSP
+ }
+
+ s.used.cc |= m
+
+ case C_SACON,
+ C_LACON:
+ c = int(p.From.Reg)
+ if c == 0 {
+ c = REGSP
+ }
+ s.used.ireg |= 1 << uint(c-REG_R0)
+
+ case C_SECON,
+ C_LECON:
+ s.used.ireg |= 1 << (REGSB - REG_R0)
+
+ case C_REG:
+ s.used.ireg |= 1 << uint(p.From.Reg-REG_R0)
+
+ case C_FREG:
+ s.used.freg |= 1 << uint(p.From.Reg-REG_F0)
+ if ld != 0 && p.To.Type == obj.TYPE_REG {
+ p.Mark |= LOAD
+ }
+
+ case C_SAUTO,
+ C_LAUTO:
+ s.used.ireg |= 1 << (REGSP - REG_R0)
+ if ld != 0 {
+ p.Mark |= LOAD
+ }
+ if ad != 0 {
+ break
+ }
+ s.size = uint8(sz)
+ s.soffset = regoff(ctxt, &p.From)
+
+ s.used.cc |= E_MEMSP
+
+ case C_SEXT:
+ case C_LEXT:
+ s.used.ireg |= 1 << (REGSB - REG_R0)
+ if ld != 0 {
+ p.Mark |= LOAD
+ }
+ if ad != 0 {
+ break
+ }
+ s.size = uint8(sz)
+ s.soffset = regoff(ctxt, &p.From)
+
+ s.used.cc |= E_MEMSB
+ }
+
+ c = int(p.Reg)
+ if c != 0 {
+ if REG_F0 <= c && c <= REG_F31 {
+ s.used.freg |= 1 << uint(c-REG_F0)
+ } else {
+ s.used.ireg |= 1 << uint(c-REG_R0)
+ }
+ }
+ s.set.ireg &^= (1 << (REGZERO - REG_R0)) /* R0 cant be set */
+}
+
+/*
+ * test to see if 2 instrictions can be
+ * interchanged without changing semantics
+ */
+func depend(ctxt *obj.Link, sa, sb *Sch) bool {
+ if sa.set.ireg&(sb.set.ireg|sb.used.ireg) != 0 {
+ return true
+ }
+ if sb.set.ireg&sa.used.ireg != 0 {
+ return true
+ }
+
+ if sa.set.freg&(sb.set.freg|sb.used.freg) != 0 {
+ return true
+ }
+ if sb.set.freg&sa.used.freg != 0 {
+ return true
+ }
+
+ /*
+ * special case.
+ * loads from same address cannot pass.
+ * this is for hardware fifo's and the like
+ */
+ if sa.used.cc&sb.used.cc&E_MEM != 0 {
+ if sa.p.Reg == sb.p.Reg {
+ if regoff(ctxt, &sa.p.From) == regoff(ctxt, &sb.p.From) {
+ return true
+ }
+ }
+ }
+
+ x := (sa.set.cc & (sb.set.cc | sb.used.cc)) | (sb.set.cc & sa.used.cc)
+ if x != 0 {
+ /*
+ * allow SB and SP to pass each other.
+ * allow SB to pass SB iff doffsets are ok
+ * anything else conflicts
+ */
+ if x != E_MEMSP && x != E_MEMSB {
+ return true
+ }
+ x = sa.set.cc | sb.set.cc | sa.used.cc | sb.used.cc
+ if x&E_MEM != 0 {
+ return true
+ }
+ if offoverlap(sa, sb) {
+ return true
+ }
+ }
+
+ return false
+}
+
+func offoverlap(sa, sb *Sch) bool {
+ if sa.soffset < sb.soffset {
+ if sa.soffset+int32(sa.size) > sb.soffset {
+ return true
+ }
+ return false
+ }
+ if sb.soffset+int32(sb.size) > sa.soffset {
+ return true
+ }
+ return false
+}
+
+/*
+ * test 2 adjacent instructions
+ * and find out if inserted instructions
+ * are desired to prevent stalls.
+ */
+func conflict(sa, sb *Sch) bool {
+ if sa.set.ireg&sb.used.ireg != 0 {
+ return true
}
+ if sa.set.freg&sb.used.freg != 0 {
+ return true
+ }
+ if sa.set.cc&sb.used.cc != 0 {
+ return true
+ }
+ return false
+}
+
+func compound(ctxt *obj.Link, p *obj.Prog) bool {
+ o := oplook(ctxt, p)
+ if o.size != 4 {
+ return true
+ }
+ if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSB {
+ return true
+ }
+ return false
+}
+
+func follow(ctxt *obj.Link, s *obj.LSym) {
+ ctxt.Cursym = s
- return 0
+ firstp := ctxt.NewProg()
+ lastp := firstp
+ xfol(ctxt, s.Text, &lastp)
+ lastp.Link = nil
+ s.Text = firstp.Link
}
func xfol(ctxt *obj.Link, p *obj.Prog, last **obj.Prog) {
var q *obj.Prog
var r *obj.Prog
var a int
- var b int
var i int
loop:
return
}
a = int(p.As)
- if a == ABR {
+ if a == AJMP {
q = p.Pcond
if (p.Mark&NOSCHED != 0) || q != nil && (q.Mark&NOSCHED != 0) {
p.Mark |= FOLL
if q == *last || (q.Mark&NOSCHED != 0) {
break
}
- b = 0 /* set */
a = int(q.As)
if a == obj.ANOP {
i--
continue
}
- if a == ABR || a == obj.ARET || a == ARFI || a == ARFCI || a == ARFID || a == AHRFID {
+ if a == AJMP || a == ARET || a == ARFE {
goto copy
}
if q.Pcond == nil || (q.Pcond.Mark&FOLL != 0) {
continue
}
- b = relinv(a)
- if b == 0 {
+ if a != ABEQ && a != ABNE {
continue
}
(*last).Link = r
*last = r
- if a == ABR || a == obj.ARET || a == ARFI || a == ARFCI || a == ARFID || a == AHRFID {
+ if a == AJMP || a == ARET || a == ARFE {
return
}
- r.As = int16(b)
+ r.As = ABNE
+ if a == ABNE {
+ r.As = ABEQ
+ }
r.Pcond = p.Link
r.Link = p.Pcond
if r.Link.Mark&FOLL == 0 {
}
}
- a = ABR
+ a = AJMP
q = ctxt.NewProg()
q.As = int16(a)
q.Lineno = p.Lineno
p.Mark |= FOLL
(*last).Link = p
*last = p
- if a == ABR || a == obj.ARET || a == ARFI || a == ARFCI || a == ARFID || a == AHRFID {
+ if a == AJMP || a == ARET || a == ARFE {
if p.Mark&NOSCHED != 0 {
p = p.Link
goto loop
}
if p.Pcond != nil {
- if a != ABL && p.Link != nil {
+ if a != AJAL && p.Link != nil {
xfol(ctxt, p.Link, last)
p = p.Pcond
if p == nil || (p.Mark&FOLL != 0) {
goto loop
}
-var Linkppc64 = obj.LinkArch{
+var Linkmips64 = obj.LinkArch{
ByteOrder: binary.BigEndian,
- Name: "ppc64",
- Thechar: '9',
+ Name: "mips64",
+ Thechar: '0',
Preprocess: preprocess,
- Assemble: span9,
+ Assemble: span0,
Follow: follow,
Progedit: progedit,
Minlc: 4,
Regsize: 8,
}
-var Linkppc64le = obj.LinkArch{
+var Linkmips64le = obj.LinkArch{
ByteOrder: binary.LittleEndian,
- Name: "ppc64le",
- Thechar: '9',
+ Name: "mips64le",
+ Thechar: '0',
Preprocess: preprocess,
- Assemble: span9,
+ Assemble: span0,
Follow: follow,
Progedit: progedit,
Minlc: 4,
C_DACON /* $n(REG) where int32 < n */
C_SBRA
C_LBRA
+ C_LBRAPIC
C_SAUTO
C_LAUTO
C_SEXT
C_ANY
C_GOK
C_ADDR
+ C_GOTADDR
+ C_TLS_LE
+ C_TLS_IE
C_TEXTSIZE
C_NCLASS /* must be the last */
"ANY",
"GOK",
"ADDR",
+ "GOTADDR",
+ "TLS_LE",
+ "TLS_IE",
"TEXTSIZE",
"NCLASS",
}
{AMOVBZ, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0},
{AMOVB, C_ADDR, C_NONE, C_NONE, C_REG, 76, 12, 0},
+ {AMOVD, C_TLS_LE, C_NONE, C_NONE, C_REG, 79, 4, 0},
+ {AMOVD, C_TLS_IE, C_NONE, C_NONE, C_REG, 80, 8, 0},
+
+ {AMOVD, C_GOTADDR, C_NONE, C_NONE, C_REG, 81, 8, 0},
+
/* load constant */
{AMOVD, C_SECON, C_NONE, C_NONE, C_REG, 3, 4, REGSB},
{AMOVD, C_SACON, C_NONE, C_NONE, C_REG, 3, 4, REGSP},
{ABEQ, C_NONE, C_NONE, C_NONE, C_SBRA, 16, 4, 0},
{ABEQ, C_CREG, C_NONE, C_NONE, C_SBRA, 16, 4, 0},
{ABR, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0},
+ {ABR, C_NONE, C_NONE, C_NONE, C_LBRAPIC, 11, 8, 0},
{ABC, C_SCON, C_REG, C_NONE, C_SBRA, 16, 4, 0},
{ABC, C_SCON, C_REG, C_NONE, C_LBRA, 17, 4, 0},
{ABR, C_NONE, C_NONE, C_NONE, C_LR, 18, 4, 0},
}
ctxt.Instoffset = a.Offset
if a.Sym != nil { // use relocation
+ if a.Sym.Type == obj.STLSBSS {
+ if ctxt.Flag_shared != 0 {
+ return C_TLS_IE
+ } else {
+ return C_TLS_LE
+ }
+ }
return C_ADDR
}
return C_LEXT
+ case obj.NAME_GOTREF:
+ return C_GOTADDR
+
case obj.NAME_AUTO:
ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset
if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
return C_DCON
case obj.TYPE_BRANCH:
+ if a.Sym != nil && ctxt.Flag_dynlink {
+ return C_LBRAPIC
+ }
return C_SBRA
}
return int(a.Class) - 1
}
-// add R_ADDRPOWER relocation to symbol s for the two instructions o1 and o2.
-func addaddrreloc(ctxt *obj.Link, s *obj.LSym, o1 *uint32, o2 *uint32) {
+const (
+ D_FORM = iota
+ DS_FORM
+)
+
+// opform returns the form (D_FORM or DS_FORM) of an instruction. Used to decide on
+// which relocation to use with a load or store and only supports the needed
+// instructions.
+func opform(ctxt *obj.Link, insn int32) int {
+ switch uint32(insn) {
+ default:
+ ctxt.Diag("bad insn in loadform: %x", insn)
+ case OPVCC(58, 0, 0, 0), // ld
+ OPVCC(58, 0, 0, 0) | 1<<1, // lwa
+ OPVCC(62, 0, 0, 0): // std
+ return DS_FORM
+ case OP_ADDI, // add
+ OPVCC(32, 0, 0, 0), // lwz
+ OPVCC(42, 0, 0, 0), // lha
+ OPVCC(40, 0, 0, 0), // lhz
+ OPVCC(34, 0, 0, 0), // lbz
+ OPVCC(50, 0, 0, 0), // lfd
+ OPVCC(48, 0, 0, 0), // lfs
+ OPVCC(36, 0, 0, 0), // stw
+ OPVCC(44, 0, 0, 0), // sth
+ OPVCC(38, 0, 0, 0), // stb
+ OPVCC(54, 0, 0, 0), // stfd
+ OPVCC(52, 0, 0, 0): // stfs
+ return D_FORM
+ }
+ return 0
+}
+
+// Encode instructions and create relocation for accessing s+d according to the
+// instruction op with source or destination (as appropriate) register reg.
+func symbolAccess(ctxt *obj.Link, s *obj.LSym, d int64, reg int16, op int32) (o1, o2 uint32) {
+ var base uint32
+ form := opform(ctxt, op)
+ if ctxt.Flag_shared != 0 {
+ base = REG_R2
+ } else {
+ base = REG_R0
+ }
+ o1 = AOP_IRR(OP_ADDIS, REGTMP, base, 0)
+ o2 = AOP_IRR(uint32(op), uint32(reg), REGTMP, 0)
rel := obj.Addrel(ctxt.Cursym)
rel.Off = int32(ctxt.Pc)
rel.Siz = 8
rel.Sym = s
- rel.Add = int64(uint64(*o1)<<32 | uint64(uint32(*o2)))
- rel.Type = obj.R_ADDRPOWER
+ rel.Add = d
+ if ctxt.Flag_shared != 0 {
+ switch form {
+ case D_FORM:
+ rel.Type = obj.R_ADDRPOWER_TOCREL
+ case DS_FORM:
+ rel.Type = obj.R_ADDRPOWER_TOCREL_DS
+ }
+
+ } else {
+ switch form {
+ case D_FORM:
+ rel.Type = obj.R_ADDRPOWER
+ case DS_FORM:
+ rel.Type = obj.R_ADDRPOWER_DS
+ }
+ }
+ return
}
/*
if v != 0 {
ctxt.Diag("illegal indexed instruction\n%v", p)
}
+ if ctxt.Flag_shared != 0 && r == REG_R13 {
+ rel := obj.Addrel(ctxt.Cursym)
+ rel.Off = int32(ctxt.Pc)
+ rel.Siz = 4
+ // This (and the matching part in the load case
+ // below) are the only places in the ppc64 toolchain
+ // that knows the name of the tls variable. Possibly
+ // we could add some assembly syntax so that the name
+ // of the variable does not have to be assumed.
+ rel.Sym = obj.Linklookup(ctxt, "runtime.tls_g", 0)
+ rel.Type = obj.R_POWER_TLS
+ }
o1 = AOP_RRR(uint32(opstorex(ctxt, int(p.As))), uint32(p.From.Reg), uint32(p.To.Index), uint32(r))
} else {
if int32(int16(v)) != v {
if v != 0 {
ctxt.Diag("illegal indexed instruction\n%v", p)
}
+ if ctxt.Flag_shared != 0 && r == REG_R13 {
+ rel := obj.Addrel(ctxt.Cursym)
+ rel.Off = int32(ctxt.Pc)
+ rel.Siz = 4
+ rel.Sym = obj.Linklookup(ctxt, "runtime.tls_g", 0)
+ rel.Type = obj.R_POWER_TLS
+ }
o1 = AOP_RRR(uint32(oploadx(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.From.Index), uint32(r))
} else {
if int32(int16(v)) != v {
rel.Add = int64(v)
rel.Type = obj.R_CALLPOWER
}
+ o2 = 0x60000000 // nop, sometimes overwritten by ld r2, 24(r1) when dynamic linking
case 12: /* movb r,r (extsb); movw r,r (extsw) */
if p.To.Reg == REGZERO && p.From.Type == obj.TYPE_CONST {
o1 = loadu32(int(p.To.Reg), d)
o2 = LOP_IRR(OP_ORI, uint32(p.To.Reg), uint32(p.To.Reg), uint32(int32(d)))
} else {
- o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(high16adjusted(int32(d))))
- o2 = AOP_IRR(OP_ADDI, uint32(p.To.Reg), REGTMP, uint32(d))
- addaddrreloc(ctxt, p.From.Sym, &o1, &o2)
+ o1, o2 = symbolAccess(ctxt, p.From.Sym, d, p.To.Reg, OP_ADDI)
}
//if(dlm) reloc(&p->from, p->pc, 0);
r = int(p.To.Reg)
}
o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(r), uint32(p.To.Reg), uint32(v)&31)
- if p.As == ASRAD && (v&0x20 != 0) {
+ if (p.As == ASRAD || p.As == ASRADCC) && (v&0x20 != 0) {
o1 |= 1 << 1 /* mb[5] */
}
o1 = 0 /* "An instruction consisting entirely of binary 0s is guaranteed
always to be an illegal instruction." */
- /* relocation operations */
+ /* relocation operations */
case 74:
- v := regoff(ctxt, &p.To)
-
- o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(high16adjusted(v)))
- o2 = AOP_IRR(uint32(opstore(ctxt, int(p.As))), uint32(p.From.Reg), REGTMP, uint32(v))
- addaddrreloc(ctxt, p.To.Sym, &o1, &o2)
+ v := vregoff(ctxt, &p.To)
+ o1, o2 = symbolAccess(ctxt, p.To.Sym, v, p.From.Reg, opstore(ctxt, int(p.As)))
//if(dlm) reloc(&p->to, p->pc, 1);
case 75:
- v := regoff(ctxt, &p.From)
- o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(high16adjusted(v)))
- o2 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(v))
- addaddrreloc(ctxt, p.From.Sym, &o1, &o2)
+ v := vregoff(ctxt, &p.From)
+ o1, o2 = symbolAccess(ctxt, p.From.Sym, v, p.To.Reg, opload(ctxt, int(p.As)))
//if(dlm) reloc(&p->from, p->pc, 1);
case 76:
- v := regoff(ctxt, &p.From)
- o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(high16adjusted(v)))
- o2 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(v))
- addaddrreloc(ctxt, p.From.Sym, &o1, &o2)
+ v := vregoff(ctxt, &p.From)
+ o1, o2 = symbolAccess(ctxt, p.From.Sym, v, p.To.Reg, opload(ctxt, int(p.As)))
o3 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.To.Reg), 0)
//if(dlm) reloc(&p->from, p->pc, 1);
+ case 79:
+ if p.From.Offset != 0 {
+ ctxt.Diag("invalid offset against tls var %v", p)
+ }
+ o1 = AOP_IRR(OP_ADDI, uint32(p.To.Reg), REGZERO, 0)
+ rel := obj.Addrel(ctxt.Cursym)
+ rel.Off = int32(ctxt.Pc)
+ rel.Siz = 4
+ rel.Sym = p.From.Sym
+ rel.Type = obj.R_POWER_TLS_LE
+
+ case 80:
+ if p.From.Offset != 0 {
+ ctxt.Diag("invalid offset against tls var %v", p)
+ }
+ o1 = AOP_IRR(OP_ADDIS, uint32(p.To.Reg), REG_R2, 0)
+ o2 = AOP_IRR(uint32(opload(ctxt, AMOVD)), uint32(p.To.Reg), uint32(p.To.Reg), 0)
+ rel := obj.Addrel(ctxt.Cursym)
+ rel.Off = int32(ctxt.Pc)
+ rel.Siz = 8
+ rel.Sym = p.From.Sym
+ rel.Type = obj.R_POWER_TLS_IE
+
+ case 81:
+ v := vregoff(ctxt, &p.To)
+ if v != 0 {
+ ctxt.Diag("invalid offset against GOT slot %v", p)
+ }
+
+ o1 = AOP_IRR(OP_ADDIS, uint32(p.To.Reg), REG_R2, 0)
+ o2 = AOP_IRR(uint32(opload(ctxt, AMOVD)), uint32(p.To.Reg), uint32(p.To.Reg), 0)
+ rel := obj.Addrel(ctxt.Cursym)
+ rel.Off = int32(ctxt.Pc)
+ rel.Siz = 8
+ rel.Sym = p.From.Sym
+ rel.Type = obj.R_ADDRPOWER_GOT
}
out[0] = o1
s.Size = 4
p.From.Type = obj.TYPE_MEM
p.From.Sym = s
+ p.From.Sym.Local = true
p.From.Name = obj.NAME_EXTERN
p.From.Offset = 0
}
s.Size = 8
p.From.Type = obj.TYPE_MEM
p.From.Sym = s
+ p.From.Sym.Local = true
p.From.Name = obj.NAME_EXTERN
p.From.Offset = 0
}
s.Size = 8
p.From.Type = obj.TYPE_MEM
p.From.Sym = s
+ p.From.Sym.Local = true
p.From.Name = obj.NAME_EXTERN
p.From.Offset = 0
}
p.As = AADD
}
}
+ if ctxt.Flag_dynlink {
+ rewriteToUseGot(ctxt, p)
+ }
+}
+
+// Rewrite p, if necessary, to access global data via the global offset table.
+func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog) {
+ if p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO {
+ // ADUFFxxx $offset
+ // becomes
+ // MOVD runtime.duffxxx@GOT, R12
+ // ADD $offset, R12
+ // MOVD R12, CTR
+ // BL (CTR)
+ var sym *obj.LSym
+ if p.As == obj.ADUFFZERO {
+ sym = obj.Linklookup(ctxt, "runtime.duffzero", 0)
+ } else {
+ sym = obj.Linklookup(ctxt, "runtime.duffcopy", 0)
+ }
+ offset := p.To.Offset
+ p.As = AMOVD
+ p.From.Type = obj.TYPE_MEM
+ p.From.Name = obj.NAME_GOTREF
+ p.From.Sym = sym
+ p.To.Type = obj.TYPE_REG
+ p.To.Reg = REG_R12
+ p.To.Name = obj.NAME_NONE
+ p.To.Offset = 0
+ p.To.Sym = nil
+ p1 := obj.Appendp(ctxt, p)
+ p1.As = AADD
+ p1.From.Type = obj.TYPE_CONST
+ p1.From.Offset = offset
+ p1.To.Type = obj.TYPE_REG
+ p1.To.Reg = REG_R12
+ p2 := obj.Appendp(ctxt, p1)
+ p2.As = AMOVD
+ p2.From.Type = obj.TYPE_REG
+ p2.From.Reg = REG_R12
+ p2.To.Type = obj.TYPE_REG
+ p2.To.Reg = REG_CTR
+ p3 := obj.Appendp(ctxt, p2)
+ p3.As = obj.ACALL
+ p3.From.Type = obj.TYPE_REG
+ p3.From.Reg = REG_R12
+ p3.To.Type = obj.TYPE_REG
+ p3.To.Reg = REG_CTR
+ }
+
+ // We only care about global data: NAME_EXTERN means a global
+ // symbol in the Go sense, and p.Sym.Local is true for a few
+ // internally defined symbols.
+ if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local {
+ // MOVD $sym, Rx becomes MOVD sym@GOT, Rx
+ // MOVD $sym+<off>, Rx becomes MOVD sym@GOT, Rx; ADD <off>, Rx
+ if p.As != AMOVD {
+ ctxt.Diag("do not know how to handle TYPE_ADDR in %v with -dynlink", p)
+ }
+ if p.To.Type != obj.TYPE_REG {
+ ctxt.Diag("do not know how to handle LEAQ-type insn to non-register in %v with -dynlink", p)
+ }
+ p.From.Type = obj.TYPE_MEM
+ p.From.Name = obj.NAME_GOTREF
+ if p.From.Offset != 0 {
+ q := obj.Appendp(ctxt, p)
+ q.As = AADD
+ q.From.Type = obj.TYPE_CONST
+ q.From.Offset = p.From.Offset
+ q.To = p.To
+ p.From.Offset = 0
+ }
+ }
+ if p.From3 != nil && p.From3.Name == obj.NAME_EXTERN {
+ ctxt.Diag("don't know how to handle %v with -dynlink", p)
+ }
+ var source *obj.Addr
+ // MOVx sym, Ry becomes MOVD sym@GOT, REGTMP; MOVx (REGTMP), Ry
+ // MOVx Ry, sym becomes MOVD sym@GOT, REGTMP; MOVx Ry, (REGTMP)
+ // An addition may be inserted between the two MOVs if there is an offset.
+ if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local {
+ if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local {
+ ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p)
+ }
+ source = &p.From
+ } else if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local {
+ source = &p.To
+ } else {
+ return
+ }
+ if p.As == obj.ATEXT || p.As == obj.AFUNCDATA || p.As == obj.ACALL || p.As == obj.ARET || p.As == obj.AJMP {
+ return
+ }
+ if source.Sym.Type == obj.STLSBSS {
+ return
+ }
+ if source.Type != obj.TYPE_MEM {
+ ctxt.Diag("don't know how to handle %v with -dynlink", p)
+ }
+ p1 := obj.Appendp(ctxt, p)
+ p2 := obj.Appendp(ctxt, p1)
+
+ p1.As = AMOVD
+ p1.From.Type = obj.TYPE_MEM
+ p1.From.Sym = source.Sym
+ p1.From.Name = obj.NAME_GOTREF
+ p1.To.Type = obj.TYPE_REG
+ p1.To.Reg = REGTMP
+
+ p2.As = p.As
+ p2.From = p.From
+ p2.To = p.To
+ if p.From.Name == obj.NAME_EXTERN {
+ p2.From.Reg = REGTMP
+ p2.From.Name = obj.NAME_NONE
+ p2.From.Sym = nil
+ } else if p.To.Name == obj.NAME_EXTERN {
+ p2.To.Reg = REGTMP
+ p2.To.Name = obj.NAME_NONE
+ p2.To.Sym = nil
+ } else {
+ return
+ }
+ obj.Nopout(p)
}
func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
p.To.Offset = int64(autosize)
- if p.From3.Offset&obj.NOSPLIT == 0 {
- p = stacksplit(ctxt, p, autosize) // emit split check
+ q = p
+
+ if ctxt.Flag_shared != 0 && cursym.Name != "runtime.duffzero" && cursym.Name != "runtime.duffcopy" {
+ // When compiling Go into PIC, all functions must start
+ // with instructions to load the TOC pointer into r2:
+ //
+ // addis r2, r12, .TOC.-func@ha
+ // addi r2, r2, .TOC.-func@l+4
+ //
+ // We could probably skip this prologue in some situations
+ // but it's a bit subtle. However, it is both safe and
+ // necessary to leave the prologue off duffzero and
+ // duffcopy as we rely on being able to jump to a specific
+ // instruction offset for them.
+ //
+ // These are AWORDS because there is no (afaict) way to
+ // generate the addis instruction except as part of the
+ // load of a large constant, and in that case there is no
+ // way to use r12 as the source.
+ q = obj.Appendp(ctxt, q)
+ q.As = AWORD
+ q.Lineno = p.Lineno
+ q.From.Type = obj.TYPE_CONST
+ q.From.Offset = 0x3c4c0000
+ q = obj.Appendp(ctxt, q)
+ q.As = AWORD
+ q.Lineno = p.Lineno
+ q.From.Type = obj.TYPE_CONST
+ q.From.Offset = 0x38420000
+ rel := obj.Addrel(ctxt.Cursym)
+ rel.Off = 0
+ rel.Siz = 8
+ rel.Sym = obj.Linklookup(ctxt, ".TOC.", 0)
+ rel.Type = obj.R_ADDRPOWER_PCREL
}
- q = p
+ if cursym.Text.From3.Offset&obj.NOSPLIT == 0 {
+ q = stacksplit(ctxt, q, autosize) // emit split check
+ }
if autosize != 0 {
/* use MOVDU to adjust R1 when saving R31, if autosize is small */
mov = AMOVDU
aoffset = int(-autosize)
} else {
- q = obj.Appendp(ctxt, p)
+ q = obj.Appendp(ctxt, q)
q.As = AADD
q.Lineno = p.Lineno
q.From.Type = obj.TYPE_CONST
q.Spadj = int32(-aoffset)
}
+ if ctxt.Flag_shared != 0 {
+ q = obj.Appendp(ctxt, q)
+ q.As = AMOVD
+ q.Lineno = p.Lineno
+ q.From.Type = obj.TYPE_REG
+ q.From.Reg = REG_R2
+ q.To.Type = obj.TYPE_MEM
+ q.To.Reg = REGSP
+ q.To.Offset = 24
+ }
+
if cursym.Text.From3.Offset&obj.WRAPPER != 0 {
// if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
//
q.Pcond = p
}
- // BL runtime.morestack(SB)
- p = obj.Appendp(ctxt, p)
-
- p.As = ABL
- p.To.Type = obj.TYPE_BRANCH
+ var morestacksym *obj.LSym
if ctxt.Cursym.Cfunc != 0 {
- p.To.Sym = obj.Linklookup(ctxt, "runtime.morestackc", 0)
+ morestacksym = obj.Linklookup(ctxt, "runtime.morestackc", 0)
} else if ctxt.Cursym.Text.From3.Offset&obj.NEEDCTXT == 0 {
- p.To.Sym = obj.Linklookup(ctxt, "runtime.morestack_noctxt", 0)
+ morestacksym = obj.Linklookup(ctxt, "runtime.morestack_noctxt", 0)
} else {
- p.To.Sym = obj.Linklookup(ctxt, "runtime.morestack", 0)
+ morestacksym = obj.Linklookup(ctxt, "runtime.morestack", 0)
}
+ if ctxt.Flag_dynlink {
+ // Avoid calling morestack via a PLT when dynamically linking. The
+ // PLT stubs generated by the system linker on ppc64le when "std r2,
+ // 24(r1)" to save the TOC pointer in their callers stack
+ // frame. Unfortunately (and necessarily) morestack is called before
+ // the function that calls it sets up its frame and so the PLT ends
+ // up smashing the saved TOC pointer for its caller's caller.
+ //
+ // According to the ABI documentation there is a mechanism to avoid
+ // the TOC save that the PLT stub does (put a R_PPC64_TOCSAVE
+ // relocation on the nop after the call to morestack) but at the time
+ // of writing it is not supported at all by gold and my attempt to
+ // use it with ld.bfd caused an internal linker error. So this hack
+ // seems preferable.
+
+ // MOVD $runtime.morestack(SB), R12
+ p = obj.Appendp(ctxt, p)
+ p.As = AMOVD
+ p.From.Type = obj.TYPE_MEM
+ p.From.Sym = morestacksym
+ p.From.Name = obj.NAME_GOTREF
+ p.To.Type = obj.TYPE_REG
+ p.To.Reg = REG_R12
+
+ // MOVD R12, CTR
+ p = obj.Appendp(ctxt, p)
+ p.As = AMOVD
+ p.From.Type = obj.TYPE_REG
+ p.From.Reg = REG_R12
+ p.To.Type = obj.TYPE_REG
+ p.To.Reg = REG_CTR
+
+ // BL CTR
+ p = obj.Appendp(ctxt, p)
+ p.As = obj.ACALL
+ p.From.Type = obj.TYPE_REG
+ p.From.Reg = REG_R12
+ p.To.Type = obj.TYPE_REG
+ p.To.Reg = REG_CTR
+ } else {
+ // BL runtime.morestack(SB)
+ p = obj.Appendp(ctxt, p)
+
+ p.As = ABL
+ p.To.Type = obj.TYPE_BRANCH
+ p.To.Sym = morestacksym
+ }
// BR start
p = obj.Appendp(ctxt, p)
return &Biobuf{w: bufio.NewWriter(w)}
}
+func Binitr(r io.Reader) *Biobuf {
+ return &Biobuf{r: bufio.NewReader(r)}
+}
+
func (b *Biobuf) Write(p []byte) (int, error) {
return b.w.Write(p)
}
const (
// Because of masking operations in the encodings, each register
// space should start at 0 modulo some power of 2.
- RBase386 = 1 * 1024
- RBaseAMD64 = 2 * 1024
- RBaseARM = 3 * 1024
- RBasePPC64 = 4 * 1024 // range [4k, 8k)
- RBaseARM64 = 8 * 1024 // range [8k, 12k)
+ RBase386 = 1 * 1024
+ RBaseAMD64 = 2 * 1024
+ RBaseARM = 3 * 1024
+ RBasePPC64 = 4 * 1024 // range [4k, 8k)
+ RBaseARM64 = 8 * 1024 // range [8k, 13k)
+ RBaseMIPS64 = 13 * 1024 // range [13k, 16k)
)
// RegisterRegister binds a pretty-printer (Rconv) for register
ABaseAMD64
ABasePPC64
ABaseARM64
+ ABaseMIPS64
AMask = 1<<12 - 1 // AND with this to use the opcode as an array index.
)
AMOVHDU
AMOVNTHD
AMOVHDA
+ AVPCMPEQB
+ AVPMOVMSKB
+ AVPAND
+ AVPTEST
+ AVPBROADCASTB
// from 386
AJCXZW
REGRET = REG_AX
FREGRET = REG_X0
REGSP = REG_SP
- REGTMP = REG_DI
REGCTXT = REG_DX
REGEXT = REG_R15 /* compiler allocates external registers R15 down */
FREGMIN = REG_X0 + 5 /* first register variable */
"MOVHDU",
"MOVNTHD",
"MOVHDA",
+ "VPCMPEQB",
+ "VPMOVMSKB",
+ "VPAND",
+ "VPTEST",
+ "VPBROADCASTB",
"JCXZW",
"FCMOVCC",
"FCMOVCS",
Zr_m
Zr_m_xm
Zr_m_xm_vex
+ Zr_r_r_vex
Zrp_
Z_ib
Z_il
Pf2 = 0xf2 /* xmm escape 1: f2 0f */
Pf3 = 0xf3 /* xmm escape 2: f3 0f */
Pq3 = 0x67 /* xmm escape 3: 66 48 0f */
- Pvex1 = 0xc5 /* 66 escape, vex encoding */
- Pvex2 = 0xc6 /* f3 escape, vex encoding */
+ Pvex1 = 0xc5 /* 66.0f escape, vex encoding */
+ Pvex2 = 0xc6 /* f3.0f escape, vex encoding */
+ Pvex3 = 0xc7 /* 66.0f38 escape, vex encoding */
Pw = 0x48 /* Rex.w */
Pw8 = 0x90 // symbolic; exact value doesn't matter
Py = 0x80 /* defaults to 64-bit mode */
{Yxr, Ynone, Yml, Zr_m_xm_vex, 1},
}
+var yml_xr_vex = []ytab{
+ {Yml, Ynone, Yxr, Zm_r_xm_vex, 1},
+ {Yxr, Ynone, Yxr, Zm_r_xm_vex, 1},
+}
+
+var yxm_xm_xm = []ytab{
+ {Yxr, Yxr, Yxr, Zr_r_r_vex, 1},
+ {Yxm, Yxr, Yxr, Zr_r_r_vex, 1},
+}
+
var ymr = []ytab{
{Ymr, Ynone, Ymr, Zm_r, 1},
}
{Ymr, Ynone, Yrl, Zm_r_xm, 1},
}
+var ymskb_vex = []ytab{
+ {Yxr, Ynone, Yrl, Zm_r_xm_vex, 2},
+}
+
var ycrc32l = []ytab{
{Yml, Ynone, Yrl, Zlitm_r, 0},
}
{APSRLO, ypsdq, Pq, [23]uint8{0x73, 03}},
{APSRLL, yps, Py3, [23]uint8{0xd2, 0x72, 02, Pe, 0xd2, Pe, 0x72, 02}},
{APSRLQ, yps, Py3, [23]uint8{0xd3, 0x73, 02, Pe, 0xd3, Pe, 0x73, 02}},
- {APSRLW, yps, Py3, [23]uint8{0xd1, 0x71, 02, Pe, 0xe1, Pe, 0x71, 02}},
+ {APSRLW, yps, Py3, [23]uint8{0xd1, 0x71, 02, Pe, 0xd1, Pe, 0x71, 02}},
{APSUBB, yxm, Pe, [23]uint8{0xf8}},
{APSUBL, yxm, Pe, [23]uint8{0xfa}},
{APSUBQ, yxm, Pe, [23]uint8{0xfb}},
{AMOVHDU, yxmov_vex, Pvex2, [23]uint8{0x6f, 0x7f}},
{AMOVNTHD, yxr_ml_vex, Pvex1, [23]uint8{0xe7}},
{AMOVHDA, yxmov_vex, Pvex1, [23]uint8{0x6f, 0x7f}},
+ {AVPCMPEQB, yxm_xm_xm, Pvex1, [23]uint8{0x74, 0x74}},
+ {AVPMOVMSKB, ymskb_vex, Pvex1, [23]uint8{0xd7}},
+ {AVPAND, yxm_xm_xm, Pvex1, [23]uint8{0xdb, 0xdb}},
+ {AVPBROADCASTB, yml_xr_vex, Pvex3, [23]uint8{0x78, 0x78}},
+ {AVPTEST, yml_xr_vex, Pvex3, [23]uint8{0x17, 0x17}},
{obj.AUSEFIELD, ynop, Px, [23]uint8{0, 0}},
{obj.ATYPE, nil, 0, [23]uint8{}},
{obj.AFUNCDATA, yfuncdata, Px, [23]uint8{0, 0}},
c = naclpad(ctxt, s, c, -c&31)
}
- c += -c & (FuncAlign - 1)
+ // Pad functions with trap instruction, to catch invalid jumps
+ if c&(FuncAlign-1) != 0 {
+ v = -c & (FuncAlign - 1)
+ obj.Symgrow(ctxt, s, int64(c)+int64(v))
+ for i := c; i < c+v; i++ {
+ // 0xCC is INT $3 - breakpoint instruction
+ s.P[i] = uint8(0xCC)
+ }
+ c += v
+ }
s.Size = int64(c)
if false { /* debug['a'] > 1 */
}
}
+var isAndroid = (obj.Getgoos() == "android")
+
func prefixof(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) int {
if a.Reg < REG_CS && a.Index < REG_CS { // fast path
return 0
if p.Mode == 32 {
switch ctxt.Headtype {
default:
+ if isAndroid {
+ return 0x65 // GS
+ }
log.Fatalf("unknown TLS base register for %s", obj.Headstr(ctxt.Headtype))
case obj.Hdarwin,
log.Fatalf("unknown TLS base register for %s", obj.Headstr(ctxt.Headtype))
case obj.Hlinux:
+ if isAndroid {
+ return 0x64 // FS
+ }
+
if ctxt.Flag_shared != 0 {
log.Fatalf("unknown TLS base register for linux with -shared")
} else {
0x48, 0x8b, 0x6d, 0x00, // MOVQ 0(BP), BP
}
-func vexprefix(ctxt *obj.Link, to *obj.Addr, from *obj.Addr, pref uint8) {
+// Assemble vex prefix, from 3 operands and prefix.
+// For details about vex prefix see:
+// https://en.wikipedia.org/wiki/VEX_prefix#Technical_description
+func vexprefix(ctxt *obj.Link, to *obj.Addr, from *obj.Addr, from3 *obj.Addr, pref uint8) {
rexR := regrex[to.Reg]
rexB := regrex[from.Reg]
rexX := regrex[from.Index]
var prefBit uint8
- if pref == Pvex1 {
+ // This will go into VEX.PP field.
+ if pref == Pvex1 || pref == Pvex3 {
prefBit = 1
} else if pref == Pvex2 {
prefBit = 2
- } // TODO add Pvex0,Pvex3
+ } // TODO add Pvex0
- if rexX == 0 && rexB == 0 { // 2-byte vex prefix
+ if rexX == 0 && rexB == 0 && pref != Pvex3 { // 2-byte vex prefix
+ // In 2-byte case, first byte is always C5
ctxt.Andptr[0] = 0xc5
ctxt.Andptr = ctxt.Andptr[1:]
- if rexR != 0 {
+ if from3 == nil {
+ // If this is a 2-operand instruction fill VEX.VVVV with 1111
+ // We are also interested only in 256-bit version, so VEX.L=1
ctxt.Andptr[0] = 0x7c
} else {
- ctxt.Andptr[0] = 0xfc
+ // VEX.L=1
+ ctxt.Andptr[0] = 0x4
+ // VEX.VVVV (bits 3:6) is a inversed register number
+ ctxt.Andptr[0] |= byte((^(from3.Reg - REG_X0))<<3) & 0x78
+ }
+
+ // VEX encodes REX.R as inversed upper bit
+ if rexR == 0 {
+ ctxt.Andptr[0] |= 0x80
}
ctxt.Andptr[0] |= prefBit
ctxt.Andptr = ctxt.Andptr[1:]
- } else {
+ } else { // 3-byte case
+ // First byte is always C$
ctxt.Andptr[0] = 0xc4
ctxt.Andptr = ctxt.Andptr[1:]
- ctxt.Andptr[0] = 0x1 // TODO handle different prefix
+ // Encode VEX.mmmmm with prefix value, assume 0F,
+ // which encodes as 1, unless 0F38 was specified with pvex3.
+ ctxt.Andptr[0] = 0x1 // TODO handle 0F3A
+ if pref == Pvex3 {
+ ctxt.Andptr[0] = 0x2
+ }
+
+ // REX.[RXB] are inverted and encoded in 3 upper bits
if rexR == 0 {
ctxt.Andptr[0] |= 0x80
}
}
ctxt.Andptr = ctxt.Andptr[1:]
- ctxt.Andptr[0] = 0x7c
+ // Fill VEX.VVVV, same as 2-operand VEX instruction.
+ if from3 == nil {
+ ctxt.Andptr[0] = 0x7c
+ } else {
+ ctxt.Andptr[0] = 0x4
+ ctxt.Andptr[0] |= byte((^(from3.Reg - REG_X0))<<3) & 0x78
+ }
ctxt.Andptr[0] |= prefBit
ctxt.Andptr = ctxt.Andptr[1:]
}
case Zm_r_xm_vex:
ctxt.Vexflag = 1
- vexprefix(ctxt, &p.To, &p.From, o.prefix)
+ vexprefix(ctxt, &p.To, &p.From, nil, o.prefix)
ctxt.Andptr[0] = byte(op)
ctxt.Andptr = ctxt.Andptr[1:]
asmand(ctxt, p, &p.From, &p.To)
case Zr_m_xm_vex:
ctxt.Vexflag = 1
- vexprefix(ctxt, &p.From, &p.To, o.prefix)
+ vexprefix(ctxt, &p.From, &p.To, nil, o.prefix)
ctxt.Andptr[0] = byte(op)
ctxt.Andptr = ctxt.Andptr[1:]
asmand(ctxt, p, &p.To, &p.From)
+ case Zr_r_r_vex:
+ ctxt.Vexflag = 1
+ vexprefix(ctxt, &p.To, &p.From, p.From3, o.prefix)
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmand(ctxt, p, &p.From, &p.To)
+
case Zr_m_xm:
mediaop(ctxt, o, op, int(yt.zoffset), z)
asmand(ctxt, p, &p.To, &p.From)
)
func CanUse1InsnTLS(ctxt *obj.Link) bool {
+ if isAndroid {
+ // For android, we use a disgusting hack that assumes
+ // the thread-local storage slot for g is allocated
+ // using pthread_key_create with a fixed offset
+ // (see src/runtime/cgo/gcc_android_amd64.c).
+ // This makes access to the TLS storage (for g) doable
+ // with 1 instruction.
+ return true
+ }
+
if ctxt.Arch.Regsize == 4 {
switch ctxt.Headtype {
case obj.Hlinux,
Write memory profile to file.
-memprofilerate rate
Set runtime.MemProfileRate to rate.
+ -msan
+ Link with C/C++ memory sanitizer support.
-o file
Write output to file (default a.out, or a.out.exe on Windows).
-r dir1:dir2:...
return
- case 256 + ld.R_X86_64_GOTPCREL:
+ case 256 + ld.R_X86_64_GOTPCREL, 256 + ld.R_X86_64_GOTPCRELX, 256 + ld.R_X86_64_REX_GOTPCRELX:
if targ.Type != obj.SDYNIMPORT {
// have symbol
if r.Off >= 2 && s.P[r.Off-2] == 0x8b {
func elfreloc1(r *ld.Reloc, sectoff int64) int {
ld.Thearch.Vput(uint64(sectoff))
- elfsym := r.Xsym.Elfsym
+ elfsym := r.Xsym.ElfsymForReloc()
switch r.Type {
default:
return -1
"log"
)
+// This assembler:
+//
+// .align 2
+// local.dso_init:
+// ldr r0, .Lmoduledata
+// .Lloadfrom:
+// ldr r0, [r0]
+// b runtime.addmoduledata@plt
+// .align 2
+// .Lmoduledata:
+// .word local.moduledata(GOT_PREL) + (. - (.Lloadfrom + 4))
+// assembles to:
+//
+// 00000000 <local.dso_init>:
+// 0: e59f0004 ldr r0, [pc, #4] ; c <local.dso_init+0xc>
+// 4: e5900000 ldr r0, [r0]
+// 8: eafffffe b 0 <runtime.addmoduledata>
+// 8: R_ARM_JUMP24 runtime.addmoduledata
+// c: 00000004 .word 0x00000004
+// c: R_ARM_GOT_PREL local.moduledata
+
func gentext() {
+ if !ld.DynlinkingGo() {
+ return
+ }
+ addmoduledata := ld.Linklookup(ld.Ctxt, "runtime.addmoduledata", 0)
+ if addmoduledata.Type == obj.STEXT {
+ // we're linking a module containing the runtime -> no need for
+ // an init function
+ return
+ }
+ addmoduledata.Reachable = true
+ initfunc := ld.Linklookup(ld.Ctxt, "go.link.addmoduledata", 0)
+ initfunc.Type = obj.STEXT
+ initfunc.Local = true
+ initfunc.Reachable = true
+ o := func(op uint32) {
+ ld.Adduint32(ld.Ctxt, initfunc, op)
+ }
+ o(0xe59f0004)
+ o(0xe08f0000)
+
+ o(0xeafffffe)
+ rel := ld.Addrel(initfunc)
+ rel.Off = 8
+ rel.Siz = 4
+ rel.Sym = ld.Linklookup(ld.Ctxt, "runtime.addmoduledata", 0)
+ rel.Type = obj.R_CALLARM
+ rel.Add = 0xeafffffe // vomit
+
+ o(0x00000000)
+ rel = ld.Addrel(initfunc)
+ rel.Off = 12
+ rel.Siz = 4
+ rel.Sym = ld.Ctxt.Moduledata
+ rel.Type = obj.R_PCREL
+ rel.Add = 4
+
+ if ld.Ctxt.Etextp != nil {
+ ld.Ctxt.Etextp.Next = initfunc
+ } else {
+ ld.Ctxt.Textp = initfunc
+ }
+ ld.Ctxt.Etextp = initfunc
+ initarray_entry := ld.Linklookup(ld.Ctxt, "go.link.addmoduledatainit", 0)
+ initarray_entry.Reachable = true
+ initarray_entry.Local = true
+ initarray_entry.Type = obj.SINITARR
+ ld.Addaddr(ld.Ctxt, initarray_entry, initfunc)
}
// Preserve highest 8 bits of a, and do addition to lower 24-bit
func elfreloc1(r *ld.Reloc, sectoff int64) int {
ld.Thearch.Lput(uint32(sectoff))
- elfsym := r.Xsym.Elfsym
+ elfsym := r.Xsym.ElfsymForReloc()
switch r.Type {
default:
return -1
case obj.R_TLS_IE:
ld.Thearch.Lput(ld.R_ARM_TLS_IE32 | uint32(elfsym)<<8)
+
+ case obj.R_GOTPCREL:
+ if r.Siz == 4 {
+ ld.Thearch.Lput(ld.R_ARM_GOT_PREL | uint32(elfsym)<<8)
+ } else {
+ return -1
+ }
}
return 0
"log"
)
-func gentext() {}
+func gentext() {
+ if !ld.DynlinkingGo() {
+ return
+ }
+ addmoduledata := ld.Linklookup(ld.Ctxt, "runtime.addmoduledata", 0)
+ if addmoduledata.Type == obj.STEXT {
+ // we're linking a module containing the runtime -> no need for
+ // an init function
+ return
+ }
+ addmoduledata.Reachable = true
+ initfunc := ld.Linklookup(ld.Ctxt, "go.link.addmoduledata", 0)
+ initfunc.Type = obj.STEXT
+ initfunc.Local = true
+ initfunc.Reachable = true
+ o := func(op uint32) {
+ ld.Adduint32(ld.Ctxt, initfunc, op)
+ }
+ // 0000000000000000 <local.dso_init>:
+ // 0: 90000000 adrp x0, 0 <runtime.firstmoduledata>
+ // 0: R_AARCH64_ADR_PREL_PG_HI21 local.moduledata
+ // 4: 91000000 add x0, x0, #0x0
+ // 4: R_AARCH64_ADD_ABS_LO12_NC local.moduledata
+ o(0x90000000)
+ o(0x91000000)
+ rel := ld.Addrel(initfunc)
+ rel.Off = 0
+ rel.Siz = 8
+ rel.Sym = ld.Ctxt.Moduledata
+ rel.Type = obj.R_ADDRARM64
+
+ // 8: 14000000 bl 0 <runtime.addmoduledata>
+ // 8: R_AARCH64_CALL26 runtime.addmoduledata
+ o(0x14000000)
+ rel = ld.Addrel(initfunc)
+ rel.Off = 8
+ rel.Siz = 4
+ rel.Sym = ld.Linklookup(ld.Ctxt, "runtime.addmoduledata", 0)
+ rel.Type = obj.R_CALLARM64 // Really should be R_AARCH64_JUMP26 but doesn't seem to make any difference
+
+ if ld.Ctxt.Etextp != nil {
+ ld.Ctxt.Etextp.Next = initfunc
+ } else {
+ ld.Ctxt.Textp = initfunc
+ }
+ ld.Ctxt.Etextp = initfunc
+ initarray_entry := ld.Linklookup(ld.Ctxt, "go.link.addmoduledatainit", 0)
+ initarray_entry.Reachable = true
+ initarray_entry.Local = true
+ initarray_entry.Type = obj.SINITARR
+ ld.Addaddr(ld.Ctxt, initarray_entry, initfunc)
+}
func adddynrela(rel *ld.LSym, s *ld.LSym, r *ld.Reloc) {
log.Fatalf("adddynrela not implemented")
func elfreloc1(r *ld.Reloc, sectoff int64) int {
ld.Thearch.Vput(uint64(sectoff))
- elfsym := r.Xsym.Elfsym
+ elfsym := r.Xsym.ElfsymForReloc()
switch r.Type {
default:
return -1
ld.Thearch.Vput(uint64(sectoff + 4))
ld.Thearch.Vput(ld.R_AARCH64_ADD_ABS_LO12_NC | uint64(elfsym)<<32)
+ case obj.R_ARM64_TLS_LE:
+ ld.Thearch.Vput(ld.R_AARCH64_TLSLE_MOVW_TPREL_G0 | uint64(elfsym)<<32)
+
+ case obj.R_ARM64_TLS_IE:
+ ld.Thearch.Vput(ld.R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 | uint64(elfsym)<<32)
+ ld.Thearch.Vput(uint64(r.Xadd))
+ ld.Thearch.Vput(uint64(sectoff + 4))
+ ld.Thearch.Vput(ld.R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC | uint64(elfsym)<<32)
+
+ case obj.R_ARM64_GOTPCREL:
+ ld.Thearch.Vput(ld.R_AARCH64_ADR_GOT_PAGE | uint64(elfsym)<<32)
+ ld.Thearch.Vput(uint64(r.Xadd))
+ ld.Thearch.Vput(uint64(sectoff + 4))
+ ld.Thearch.Vput(ld.R_AARCH64_LD64_GOT_LO12_NC | uint64(elfsym)<<32)
+
case obj.R_CALLARM64:
if r.Siz != 4 {
return -1
default:
return -1
+ case obj.R_ARM64_GOTPCREL:
+ var o1, o2 uint32
+ if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
+ o1 = uint32(*val >> 32)
+ o2 = uint32(*val)
+ } else {
+ o1 = uint32(*val)
+ o2 = uint32(*val >> 32)
+ }
+ // Any relocation against a function symbol is redirected to
+ // be against a local symbol instead (see putelfsym in
+ // symtab.go) but unfortunately the system linker was buggy
+ // when confronted with a R_AARCH64_ADR_GOT_PAGE relocation
+ // against a local symbol until May 2015
+ // (https://sourceware.org/bugzilla/show_bug.cgi?id=18270). So
+ // we convert the adrp; ld64 + R_ARM64_GOTPCREL into adrp;
+ // add + R_ADDRARM64.
+ if !(r.Sym.Version != 0 || (r.Sym.Type&obj.SHIDDEN != 0) || r.Sym.Local) && r.Sym.Type == obj.STEXT && ld.DynlinkingGo() {
+ if o2&0xffc00000 != 0xf9400000 {
+ ld.Ctxt.Diag("R_ARM64_GOTPCREL against unexpected instruction %x", o2)
+ }
+ o2 = 0x91000000 | (o2 & 0x000003ff)
+ r.Type = obj.R_ADDRARM64
+ }
+ if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
+ *val = int64(o1)<<32 | int64(o2)
+ } else {
+ *val = int64(o2)<<32 | int64(o1)
+ }
+ fallthrough
+
case obj.R_ADDRARM64:
r.Done = 0
rs = rs.Outer
}
- if rs.Type != obj.SHOSTOBJ && rs.Sect == nil {
+ if rs.Type != obj.SHOSTOBJ && rs.Type != obj.SDYNIMPORT && rs.Sect == nil {
ld.Diag("missing section for %s", rs.Name)
}
r.Xsym = rs
return 0
- case obj.R_CALLARM64:
+ case obj.R_CALLARM64,
+ obj.R_ARM64_TLS_LE,
+ obj.R_ARM64_TLS_IE:
r.Done = 0
r.Xsym = r.Sym
r.Xadd = r.Add
}
return 0
+ case obj.R_ARM64_TLS_LE:
+ r.Done = 0
+ if ld.HEADTYPE != obj.Hlinux {
+ ld.Diag("TLS reloc on unsupported OS %s", ld.Headstr(int(ld.HEADTYPE)))
+ }
+ // The TCB is two pointers. This is not documented anywhere, but is
+ // de facto part of the ABI.
+ v := r.Sym.Value + int64(2*ld.Thearch.Ptrsize)
+ if v < 0 || v >= 32678 {
+ ld.Diag("TLS offset out of range %d", v)
+ }
+ *val |= v << 5
+ return 0
+
case obj.R_CALLARM64:
t := (ld.Symaddr(r.Sym) + r.Add) - (s.Value + int64(r.Off))
if t >= 1<<27 || t < -1<<27 {
break
}
+ if ld.Buildmode == ld.BuildmodeCShared || ld.DynlinkingGo() {
+ ld.Linkmode = ld.LinkExternal
+ }
+
switch ld.HEADTYPE {
default:
ld.Exitf("unknown -H option: %v", ld.HEADTYPE)
package ld
+import (
+ "cmd/internal/obj"
+ "encoding/binary"
+ "fmt"
+ "os"
+)
+
const (
SARMAG = 8
SAR_HDR = 16 + 44
size string
fmag string
}
+
+// hostArchive reads an archive file holding host objects and links in
+// required objects. The general format is the same as a Go archive
+// file, but it has an armap listing symbols and the objects that
+// define them. This is used for the compiler support library
+// libgcc.a.
+func hostArchive(name string) {
+ f, err := obj.Bopenr(name)
+ if err != nil {
+ if os.IsNotExist(err) {
+ // It's OK if we don't have a libgcc file at all.
+ return
+ }
+ Exitf("cannot open file %s: %v", name, err)
+ }
+ defer obj.Bterm(f)
+
+ magbuf := make([]byte, len(ARMAG))
+ if obj.Bread(f, magbuf) != len(magbuf) {
+ Exitf("file %s too short", name)
+ }
+
+ var arhdr ArHdr
+ l := nextar(f, obj.Boffset(f), &arhdr)
+ if l <= 0 {
+ Exitf("%s missing armap", name)
+ }
+
+ var armap archiveMap
+ if arhdr.name == "/" || arhdr.name == "/SYM64/" {
+ armap = readArmap(name, f, arhdr)
+ } else {
+ Exitf("%s missing armap", name)
+ }
+
+ loaded := make(map[uint64]bool)
+ any := true
+ for any {
+ var load []uint64
+ for s := Ctxt.Allsym; s != nil; s = s.Allsym {
+ for _, r := range s.R {
+ if r.Sym != nil && r.Sym.Type&obj.SMASK == obj.SXREF {
+ if off := armap[r.Sym.Name]; off != 0 && !loaded[off] {
+ load = append(load, off)
+ loaded[off] = true
+ }
+ }
+ }
+ }
+
+ for _, off := range load {
+ l := nextar(f, int64(off), &arhdr)
+ if l <= 0 {
+ Exitf("%s missing archive entry at offset %d", name, off)
+ }
+ pname := fmt.Sprintf("%s(%s)", name, arhdr.name)
+ l = atolwhex(arhdr.size)
+
+ h := ldobj(f, "libgcc", l, pname, name, ArchiveObj)
+ obj.Bseek(f, h.off, 0)
+ h.ld(f, h.pkg, h.length, h.pn)
+ }
+
+ any = len(load) > 0
+ }
+}
+
+// archiveMap is an archive symbol map: a mapping from symbol name to
+// offset within the archive file.
+type archiveMap map[string]uint64
+
+// readArmap reads the archive symbol map.
+func readArmap(filename string, f *obj.Biobuf, arhdr ArHdr) archiveMap {
+ is64 := arhdr.name == "/SYM64/"
+ wordSize := 4
+ if is64 {
+ wordSize = 8
+ }
+
+ l := atolwhex(arhdr.size)
+ contents := make([]byte, l)
+ if obj.Bread(f, contents) != int(l) {
+ Exitf("short read from %s", filename)
+ }
+
+ var c uint64
+ if is64 {
+ c = binary.BigEndian.Uint64(contents)
+ } else {
+ c = uint64(binary.BigEndian.Uint32(contents))
+ }
+ contents = contents[wordSize:]
+
+ ret := make(archiveMap)
+
+ names := contents[c*uint64(wordSize):]
+ for i := uint64(0); i < c; i++ {
+ n := 0
+ for names[n] != 0 {
+ n++
+ }
+ name := string(names[:n])
+ names = names[n+1:]
+
+ // For Mach-O and PE/386 files we strip a leading
+ // underscore from the symbol name.
+ if goos == "darwin" || (goos == "windows" && goarch == "386") {
+ if name[0] == '_' && len(name) > 1 {
+ name = name[1:]
+ }
+ }
+
+ var off uint64
+ if is64 {
+ off = binary.BigEndian.Uint64(contents)
+ } else {
+ off = uint64(binary.BigEndian.Uint32(contents))
+ }
+ contents = contents[wordSize:]
+
+ ret[name] = off
+ }
+
+ return ret
+}
Ptrsize: 8,
Regsize: 8,
}
+
+var Linkmips64 = LinkArch{
+ ByteOrder: binary.BigEndian,
+ Name: "mips64",
+ Thechar: '0',
+ Minlc: 4,
+ Ptrsize: 8,
+ Regsize: 8,
+}
+
+var Linkmips64le = LinkArch{
+ ByteOrder: binary.LittleEndian,
+ Name: "mips64le",
+ Thechar: '0',
+ Minlc: 4,
+ Ptrsize: 8,
+ Regsize: 8,
+}
// We need to be able to reference dynimport symbols when linking against
// shared libraries, and Solaris needs it always
if HEADTYPE != obj.Hsolaris && r.Sym != nil && r.Sym.Type == obj.SDYNIMPORT && !DynlinkingGo() {
- Diag("unhandled relocation for %s (type %d rtype %d)", r.Sym.Name, r.Sym.Type, r.Type)
+ if !(Thearch.Thechar == '9' && Linkmode == LinkExternal && r.Sym.Name == ".TOC.") {
+ Diag("unhandled relocation for %s (type %d rtype %d)", r.Sym.Name, r.Sym.Type, r.Type)
+ }
}
if r.Sym != nil && r.Sym.Type != obj.STLSBSS && !r.Sym.Reachable {
Diag("unreachable sym in relocation: %s %s", s.Name, r.Sym.Name)
}
case obj.R_TLS_LE:
- if Linkmode == LinkExternal && Iself && HEADTYPE != obj.Hopenbsd {
+ isAndroidX86 := goos == "android" && (Thearch.Thechar == '6' || Thearch.Thechar == '8')
+
+ if Linkmode == LinkExternal && Iself && HEADTYPE != obj.Hopenbsd && !isAndroidX86 {
r.Done = 0
if r.Sym == nil {
r.Sym = Ctxt.Tlsg
// related to the fact that our own TLS storage happens
// to take up 8 bytes.
o = 8 + r.Sym.Value
- } else if Iself || Ctxt.Headtype == obj.Hplan9 || Ctxt.Headtype == obj.Hdarwin {
+ } else if Iself || Ctxt.Headtype == obj.Hplan9 || Ctxt.Headtype == obj.Hdarwin || isAndroidX86 {
o = int64(Ctxt.Tlsoffset) + r.Add
} else if Ctxt.Headtype == obj.Hwindows {
o = r.Add
}
case obj.R_TLS_IE:
- if Linkmode == LinkExternal && Iself && HEADTYPE != obj.Hopenbsd {
+ isAndroidX86 := goos == "android" && (Thearch.Thechar == '6' || Thearch.Thechar == '8')
+
+ if Linkmode == LinkExternal && Iself && HEADTYPE != obj.Hopenbsd && !isAndroidX86 {
r.Done = 0
if r.Sym == nil {
r.Sym = Ctxt.Tlsg
}
func decodetype_gcprog_shlib(s *LSym) uint64 {
+ if Thearch.Thechar == '7' {
+ for _, shlib := range Ctxt.Shlibs {
+ if shlib.Path == s.File {
+ return shlib.gcdata_addresses[s]
+ }
+ }
+ return 0
+ }
return decode_inuxi(s.P[2*int32(Thearch.Ptrsize)+8+1*int32(Thearch.Ptrsize):], Thearch.Ptrsize)
}
}
func synthesizestringtypes(die *DWDie) {
- prototype := walktypedef(defgotype(lookup_or_diag("type.runtime._string")))
+ prototype := walktypedef(defgotype(lookup_or_diag("type.runtime.stringStructDWARF")))
if prototype == nil {
return
}
case obj.A_PARAM:
dt = DW_ABRV_PARAM
- offs = int64(a.Aoffset)
- if haslinkregister() {
- offs += int64(Thearch.Ptrsize)
- }
+ offs = int64(a.Aoffset) + Ctxt.FixedFrameSize()
default:
continue
elfstrdbg[ElfStrGDBScripts] = Addstring(shstrtab, ".debug_gdb_scripts")
if Linkmode == LinkExternal {
switch Thearch.Thechar {
- case '6', '7', '9':
+ case '0', '6', '7', '9':
elfstrdbg[ElfStrRelDebugInfo] = Addstring(shstrtab, ".rela.debug_info")
elfstrdbg[ElfStrRelDebugAranges] = Addstring(shstrtab, ".rela.debug_aranges")
elfstrdbg[ElfStrRelDebugLine] = Addstring(shstrtab, ".rela.debug_line")
func dwarfaddelfrelocheader(elfstr int, shdata *ElfShdr, off int64, size int64) {
sh := newElfShdr(elfstrdbg[elfstr])
switch Thearch.Thechar {
- case '6', '7', '9':
+ case '0', '6', '7', '9':
sh.type_ = SHT_RELA
default:
sh.type_ = SHT_REL
* Relocation types.
*/
const (
- R_X86_64_NONE = 0
- R_X86_64_64 = 1
- R_X86_64_PC32 = 2
- R_X86_64_GOT32 = 3
- R_X86_64_PLT32 = 4
- R_X86_64_COPY = 5
- R_X86_64_GLOB_DAT = 6
- R_X86_64_JMP_SLOT = 7
- R_X86_64_RELATIVE = 8
- R_X86_64_GOTPCREL = 9
- R_X86_64_32 = 10
- R_X86_64_32S = 11
- R_X86_64_16 = 12
- R_X86_64_PC16 = 13
- R_X86_64_8 = 14
- R_X86_64_PC8 = 15
- R_X86_64_DTPMOD64 = 16
- R_X86_64_DTPOFF64 = 17
- R_X86_64_TPOFF64 = 18
- R_X86_64_TLSGD = 19
- R_X86_64_TLSLD = 20
- R_X86_64_DTPOFF32 = 21
- R_X86_64_GOTTPOFF = 22
- R_X86_64_TPOFF32 = 23
- R_X86_64_COUNT = 24
- R_AARCH64_ABS64 = 257
- R_AARCH64_ABS32 = 258
- R_AARCH64_CALL26 = 283
- R_AARCH64_ADR_PREL_PG_HI21 = 275
- R_AARCH64_ADD_ABS_LO12_NC = 277
- R_ALPHA_NONE = 0
- R_ALPHA_REFLONG = 1
- R_ALPHA_REFQUAD = 2
- R_ALPHA_GPREL32 = 3
- R_ALPHA_LITERAL = 4
- R_ALPHA_LITUSE = 5
- R_ALPHA_GPDISP = 6
- R_ALPHA_BRADDR = 7
- R_ALPHA_HINT = 8
- R_ALPHA_SREL16 = 9
- R_ALPHA_SREL32 = 10
- R_ALPHA_SREL64 = 11
- R_ALPHA_OP_PUSH = 12
- R_ALPHA_OP_STORE = 13
- R_ALPHA_OP_PSUB = 14
- R_ALPHA_OP_PRSHIFT = 15
- R_ALPHA_GPVALUE = 16
- R_ALPHA_GPRELHIGH = 17
- R_ALPHA_GPRELLOW = 18
- R_ALPHA_IMMED_GP_16 = 19
- R_ALPHA_IMMED_GP_HI32 = 20
- R_ALPHA_IMMED_SCN_HI32 = 21
- R_ALPHA_IMMED_BR_HI32 = 22
- R_ALPHA_IMMED_LO32 = 23
- R_ALPHA_COPY = 24
- R_ALPHA_GLOB_DAT = 25
- R_ALPHA_JMP_SLOT = 26
- R_ALPHA_RELATIVE = 27
- R_ALPHA_COUNT = 28
- R_ARM_NONE = 0
- R_ARM_PC24 = 1
- R_ARM_ABS32 = 2
- R_ARM_REL32 = 3
- R_ARM_PC13 = 4
- R_ARM_ABS16 = 5
- R_ARM_ABS12 = 6
- R_ARM_THM_ABS5 = 7
- R_ARM_ABS8 = 8
- R_ARM_SBREL32 = 9
- R_ARM_THM_PC22 = 10
- R_ARM_THM_PC8 = 11
- R_ARM_AMP_VCALL9 = 12
- R_ARM_SWI24 = 13
- R_ARM_THM_SWI8 = 14
- R_ARM_XPC25 = 15
- R_ARM_THM_XPC22 = 16
- R_ARM_COPY = 20
- R_ARM_GLOB_DAT = 21
- R_ARM_JUMP_SLOT = 22
- R_ARM_RELATIVE = 23
- R_ARM_GOTOFF = 24
- R_ARM_GOTPC = 25
- R_ARM_GOT32 = 26
- R_ARM_PLT32 = 27
- R_ARM_CALL = 28
- R_ARM_JUMP24 = 29
- R_ARM_V4BX = 40
- R_ARM_GOT_PREL = 96
- R_ARM_GNU_VTENTRY = 100
- R_ARM_GNU_VTINHERIT = 101
- R_ARM_TLS_IE32 = 107
- R_ARM_TLS_LE32 = 108
- R_ARM_RSBREL32 = 250
- R_ARM_THM_RPC22 = 251
- R_ARM_RREL32 = 252
- R_ARM_RABS32 = 253
- R_ARM_RPC24 = 254
- R_ARM_RBASE = 255
- R_ARM_COUNT = 38
- R_386_NONE = 0
- R_386_32 = 1
- R_386_PC32 = 2
- R_386_GOT32 = 3
- R_386_PLT32 = 4
- R_386_COPY = 5
- R_386_GLOB_DAT = 6
- R_386_JMP_SLOT = 7
- R_386_RELATIVE = 8
- R_386_GOTOFF = 9
- R_386_GOTPC = 10
- R_386_TLS_TPOFF = 14
- R_386_TLS_IE = 15
- R_386_TLS_GOTIE = 16
- R_386_TLS_LE = 17
- R_386_TLS_GD = 18
- R_386_TLS_LDM = 19
- R_386_TLS_GD_32 = 24
- R_386_TLS_GD_PUSH = 25
- R_386_TLS_GD_CALL = 26
- R_386_TLS_GD_POP = 27
- R_386_TLS_LDM_32 = 28
- R_386_TLS_LDM_PUSH = 29
- R_386_TLS_LDM_CALL = 30
- R_386_TLS_LDM_POP = 31
- R_386_TLS_LDO_32 = 32
- R_386_TLS_IE_32 = 33
- R_386_TLS_LE_32 = 34
- R_386_TLS_DTPMOD32 = 35
- R_386_TLS_DTPOFF32 = 36
- R_386_TLS_TPOFF32 = 37
- R_386_COUNT = 38
- R_PPC_NONE = 0
- R_PPC_ADDR32 = 1
- R_PPC_ADDR24 = 2
- R_PPC_ADDR16 = 3
- R_PPC_ADDR16_LO = 4
- R_PPC_ADDR16_HI = 5
- R_PPC_ADDR16_HA = 6
- R_PPC_ADDR14 = 7
- R_PPC_ADDR14_BRTAKEN = 8
- R_PPC_ADDR14_BRNTAKEN = 9
- R_PPC_REL24 = 10
- R_PPC_REL14 = 11
- R_PPC_REL14_BRTAKEN = 12
- R_PPC_REL14_BRNTAKEN = 13
- R_PPC_GOT16 = 14
- R_PPC_GOT16_LO = 15
- R_PPC_GOT16_HI = 16
- R_PPC_GOT16_HA = 17
- R_PPC_PLTREL24 = 18
- R_PPC_COPY = 19
- R_PPC_GLOB_DAT = 20
- R_PPC_JMP_SLOT = 21
- R_PPC_RELATIVE = 22
- R_PPC_LOCAL24PC = 23
- R_PPC_UADDR32 = 24
- R_PPC_UADDR16 = 25
- R_PPC_REL32 = 26
- R_PPC_PLT32 = 27
- R_PPC_PLTREL32 = 28
- R_PPC_PLT16_LO = 29
- R_PPC_PLT16_HI = 30
- R_PPC_PLT16_HA = 31
- R_PPC_SDAREL16 = 32
- R_PPC_SECTOFF = 33
- R_PPC_SECTOFF_LO = 34
- R_PPC_SECTOFF_HI = 35
- R_PPC_SECTOFF_HA = 36
- R_PPC_COUNT = 37
- R_PPC_TLS = 67
- R_PPC_DTPMOD32 = 68
- R_PPC_TPREL16 = 69
- R_PPC_TPREL16_LO = 70
- R_PPC_TPREL16_HI = 71
- R_PPC_TPREL16_HA = 72
- R_PPC_TPREL32 = 73
- R_PPC_DTPREL16 = 74
- R_PPC_DTPREL16_LO = 75
- R_PPC_DTPREL16_HI = 76
- R_PPC_DTPREL16_HA = 77
- R_PPC_DTPREL32 = 78
- R_PPC_GOT_TLSGD16 = 79
- R_PPC_GOT_TLSGD16_LO = 80
- R_PPC_GOT_TLSGD16_HI = 81
- R_PPC_GOT_TLSGD16_HA = 82
- R_PPC_GOT_TLSLD16 = 83
- R_PPC_GOT_TLSLD16_LO = 84
- R_PPC_GOT_TLSLD16_HI = 85
- R_PPC_GOT_TLSLD16_HA = 86
- R_PPC_GOT_TPREL16 = 87
- R_PPC_GOT_TPREL16_LO = 88
- R_PPC_GOT_TPREL16_HI = 89
- R_PPC_GOT_TPREL16_HA = 90
- R_PPC_EMB_NADDR32 = 101
- R_PPC_EMB_NADDR16 = 102
- R_PPC_EMB_NADDR16_LO = 103
- R_PPC_EMB_NADDR16_HI = 104
- R_PPC_EMB_NADDR16_HA = 105
- R_PPC_EMB_SDAI16 = 106
- R_PPC_EMB_SDA2I16 = 107
- R_PPC_EMB_SDA2REL = 108
- R_PPC_EMB_SDA21 = 109
- R_PPC_EMB_MRKREF = 110
- R_PPC_EMB_RELSEC16 = 111
- R_PPC_EMB_RELST_LO = 112
- R_PPC_EMB_RELST_HI = 113
- R_PPC_EMB_RELST_HA = 114
- R_PPC_EMB_BIT_FLD = 115
- R_PPC_EMB_RELSDA = 116
- R_PPC_EMB_COUNT = R_PPC_EMB_RELSDA - R_PPC_EMB_NADDR32 + 1
- R_PPC64_REL24 = R_PPC_REL24
- R_PPC64_JMP_SLOT = R_PPC_JMP_SLOT
- R_PPC64_ADDR64 = 38
- R_PPC64_TOC16 = 47
- R_PPC64_TOC16_LO = 48
- R_PPC64_TOC16_HI = 49
- R_PPC64_TOC16_HA = 50
- R_PPC64_TOC16_DS = 63
- R_PPC64_TOC16_LO_DS = 64
- R_PPC64_REL16_LO = 250
- R_PPC64_REL16_HI = 251
- R_PPC64_REL16_HA = 252
- R_SPARC_NONE = 0
- R_SPARC_8 = 1
- R_SPARC_16 = 2
- R_SPARC_32 = 3
- R_SPARC_DISP8 = 4
- R_SPARC_DISP16 = 5
- R_SPARC_DISP32 = 6
- R_SPARC_WDISP30 = 7
- R_SPARC_WDISP22 = 8
- R_SPARC_HI22 = 9
- R_SPARC_22 = 10
- R_SPARC_13 = 11
- R_SPARC_LO10 = 12
- R_SPARC_GOT10 = 13
- R_SPARC_GOT13 = 14
- R_SPARC_GOT22 = 15
- R_SPARC_PC10 = 16
- R_SPARC_PC22 = 17
- R_SPARC_WPLT30 = 18
- R_SPARC_COPY = 19
- R_SPARC_GLOB_DAT = 20
- R_SPARC_JMP_SLOT = 21
- R_SPARC_RELATIVE = 22
- R_SPARC_UA32 = 23
- R_SPARC_PLT32 = 24
- R_SPARC_HIPLT22 = 25
- R_SPARC_LOPLT10 = 26
- R_SPARC_PCPLT32 = 27
- R_SPARC_PCPLT22 = 28
- R_SPARC_PCPLT10 = 29
- R_SPARC_10 = 30
- R_SPARC_11 = 31
- R_SPARC_64 = 32
- R_SPARC_OLO10 = 33
- R_SPARC_HH22 = 34
- R_SPARC_HM10 = 35
- R_SPARC_LM22 = 36
- R_SPARC_PC_HH22 = 37
- R_SPARC_PC_HM10 = 38
- R_SPARC_PC_LM22 = 39
- R_SPARC_WDISP16 = 40
- R_SPARC_WDISP19 = 41
- R_SPARC_GLOB_JMP = 42
- R_SPARC_7 = 43
- R_SPARC_5 = 44
- R_SPARC_6 = 45
- R_SPARC_DISP64 = 46
- R_SPARC_PLT64 = 47
- R_SPARC_HIX22 = 48
- R_SPARC_LOX10 = 49
- R_SPARC_H44 = 50
- R_SPARC_M44 = 51
- R_SPARC_L44 = 52
- R_SPARC_REGISTER = 53
- R_SPARC_UA64 = 54
- R_SPARC_UA16 = 55
- ARM_MAGIC_TRAMP_NUMBER = 0x5c000003
+ R_X86_64_NONE = 0
+ R_X86_64_64 = 1
+ R_X86_64_PC32 = 2
+ R_X86_64_GOT32 = 3
+ R_X86_64_PLT32 = 4
+ R_X86_64_COPY = 5
+ R_X86_64_GLOB_DAT = 6
+ R_X86_64_JMP_SLOT = 7
+ R_X86_64_RELATIVE = 8
+ R_X86_64_GOTPCREL = 9
+ R_X86_64_32 = 10
+ R_X86_64_32S = 11
+ R_X86_64_16 = 12
+ R_X86_64_PC16 = 13
+ R_X86_64_8 = 14
+ R_X86_64_PC8 = 15
+ R_X86_64_DTPMOD64 = 16
+ R_X86_64_DTPOFF64 = 17
+ R_X86_64_TPOFF64 = 18
+ R_X86_64_TLSGD = 19
+ R_X86_64_TLSLD = 20
+ R_X86_64_DTPOFF32 = 21
+ R_X86_64_GOTTPOFF = 22
+ R_X86_64_TPOFF32 = 23
+ R_X86_64_PC64 = 24
+ R_X86_64_GOTOFF64 = 25
+ R_X86_64_GOTPC32 = 26
+ R_X86_64_GOT64 = 27
+ R_X86_64_GOTPCREL64 = 28
+ R_X86_64_GOTPC64 = 29
+ R_X86_64_GOTPLT64 = 30
+ R_X86_64_PLTOFF64 = 31
+ R_X86_64_SIZE32 = 32
+ R_X86_64_SIZE64 = 33
+ R_X86_64_GOTPC32_TLSDEC = 34
+ R_X86_64_TLSDESC_CALL = 35
+ R_X86_64_TLSDESC = 36
+ R_X86_64_IRELATIVE = 37
+ R_X86_64_PC32_BND = 40
+ R_X86_64_GOTPCRELX = 41
+ R_X86_64_REX_GOTPCRELX = 42
+
+ R_AARCH64_ABS64 = 257
+ R_AARCH64_ABS32 = 258
+ R_AARCH64_CALL26 = 283
+ R_AARCH64_ADR_PREL_PG_HI21 = 275
+ R_AARCH64_ADD_ABS_LO12_NC = 277
+ R_AARCH64_LDST8_ABS_LO12_NC = 278
+ R_AARCH64_LDST16_ABS_LO12_NC = 284
+ R_AARCH64_LDST32_ABS_LO12_NC = 285
+ R_AARCH64_LDST64_ABS_LO12_NC = 286
+ R_AARCH64_ADR_GOT_PAGE = 311
+ R_AARCH64_LD64_GOT_LO12_NC = 312
+ R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 = 541
+ R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC = 542
+ R_AARCH64_TLSLE_MOVW_TPREL_G0 = 547
+
+ R_ALPHA_NONE = 0
+ R_ALPHA_REFLONG = 1
+ R_ALPHA_REFQUAD = 2
+ R_ALPHA_GPREL32 = 3
+ R_ALPHA_LITERAL = 4
+ R_ALPHA_LITUSE = 5
+ R_ALPHA_GPDISP = 6
+ R_ALPHA_BRADDR = 7
+ R_ALPHA_HINT = 8
+ R_ALPHA_SREL16 = 9
+ R_ALPHA_SREL32 = 10
+ R_ALPHA_SREL64 = 11
+ R_ALPHA_OP_PUSH = 12
+ R_ALPHA_OP_STORE = 13
+ R_ALPHA_OP_PSUB = 14
+ R_ALPHA_OP_PRSHIFT = 15
+ R_ALPHA_GPVALUE = 16
+ R_ALPHA_GPRELHIGH = 17
+ R_ALPHA_GPRELLOW = 18
+ R_ALPHA_IMMED_GP_16 = 19
+ R_ALPHA_IMMED_GP_HI32 = 20
+ R_ALPHA_IMMED_SCN_HI32 = 21
+ R_ALPHA_IMMED_BR_HI32 = 22
+ R_ALPHA_IMMED_LO32 = 23
+ R_ALPHA_COPY = 24
+ R_ALPHA_GLOB_DAT = 25
+ R_ALPHA_JMP_SLOT = 26
+ R_ALPHA_RELATIVE = 27
+
+ R_ARM_NONE = 0
+ R_ARM_PC24 = 1
+ R_ARM_ABS32 = 2
+ R_ARM_REL32 = 3
+ R_ARM_PC13 = 4
+ R_ARM_ABS16 = 5
+ R_ARM_ABS12 = 6
+ R_ARM_THM_ABS5 = 7
+ R_ARM_ABS8 = 8
+ R_ARM_SBREL32 = 9
+ R_ARM_THM_PC22 = 10
+ R_ARM_THM_PC8 = 11
+ R_ARM_AMP_VCALL9 = 12
+ R_ARM_SWI24 = 13
+ R_ARM_THM_SWI8 = 14
+ R_ARM_XPC25 = 15
+ R_ARM_THM_XPC22 = 16
+ R_ARM_COPY = 20
+ R_ARM_GLOB_DAT = 21
+ R_ARM_JUMP_SLOT = 22
+ R_ARM_RELATIVE = 23
+ R_ARM_GOTOFF = 24
+ R_ARM_GOTPC = 25
+ R_ARM_GOT32 = 26
+ R_ARM_PLT32 = 27
+ R_ARM_CALL = 28
+ R_ARM_JUMP24 = 29
+ R_ARM_V4BX = 40
+ R_ARM_GOT_PREL = 96
+ R_ARM_GNU_VTENTRY = 100
+ R_ARM_GNU_VTINHERIT = 101
+ R_ARM_TLS_IE32 = 107
+ R_ARM_TLS_LE32 = 108
+ R_ARM_RSBREL32 = 250
+ R_ARM_THM_RPC22 = 251
+ R_ARM_RREL32 = 252
+ R_ARM_RABS32 = 253
+ R_ARM_RPC24 = 254
+ R_ARM_RBASE = 255
+
+ R_386_NONE = 0
+ R_386_32 = 1
+ R_386_PC32 = 2
+ R_386_GOT32 = 3
+ R_386_PLT32 = 4
+ R_386_COPY = 5
+ R_386_GLOB_DAT = 6
+ R_386_JMP_SLOT = 7
+ R_386_RELATIVE = 8
+ R_386_GOTOFF = 9
+ R_386_GOTPC = 10
+ R_386_TLS_TPOFF = 14
+ R_386_TLS_IE = 15
+ R_386_TLS_GOTIE = 16
+ R_386_TLS_LE = 17
+ R_386_TLS_GD = 18
+ R_386_TLS_LDM = 19
+ R_386_TLS_GD_32 = 24
+ R_386_TLS_GD_PUSH = 25
+ R_386_TLS_GD_CALL = 26
+ R_386_TLS_GD_POP = 27
+ R_386_TLS_LDM_32 = 28
+ R_386_TLS_LDM_PUSH = 29
+ R_386_TLS_LDM_CALL = 30
+ R_386_TLS_LDM_POP = 31
+ R_386_TLS_LDO_32 = 32
+ R_386_TLS_IE_32 = 33
+ R_386_TLS_LE_32 = 34
+ R_386_TLS_DTPMOD32 = 35
+ R_386_TLS_DTPOFF32 = 36
+ R_386_TLS_TPOFF32 = 37
+ R_386_TLS_GOTDESC = 39
+ R_386_TLS_DESC_CALL = 40
+ R_386_TLS_DESC = 41
+ R_386_IRELATIVE = 42
+ R_386_GOT32X = 43
+
+ R_PPC_NONE = 0
+ R_PPC_ADDR32 = 1
+ R_PPC_ADDR24 = 2
+ R_PPC_ADDR16 = 3
+ R_PPC_ADDR16_LO = 4
+ R_PPC_ADDR16_HI = 5
+ R_PPC_ADDR16_HA = 6
+ R_PPC_ADDR14 = 7
+ R_PPC_ADDR14_BRTAKEN = 8
+ R_PPC_ADDR14_BRNTAKEN = 9
+ R_PPC_REL24 = 10
+ R_PPC_REL14 = 11
+ R_PPC_REL14_BRTAKEN = 12
+ R_PPC_REL14_BRNTAKEN = 13
+ R_PPC_GOT16 = 14
+ R_PPC_GOT16_LO = 15
+ R_PPC_GOT16_HI = 16
+ R_PPC_GOT16_HA = 17
+ R_PPC_PLTREL24 = 18
+ R_PPC_COPY = 19
+ R_PPC_GLOB_DAT = 20
+ R_PPC_JMP_SLOT = 21
+ R_PPC_RELATIVE = 22
+ R_PPC_LOCAL24PC = 23
+ R_PPC_UADDR32 = 24
+ R_PPC_UADDR16 = 25
+ R_PPC_REL32 = 26
+ R_PPC_PLT32 = 27
+ R_PPC_PLTREL32 = 28
+ R_PPC_PLT16_LO = 29
+ R_PPC_PLT16_HI = 30
+ R_PPC_PLT16_HA = 31
+ R_PPC_SDAREL16 = 32
+ R_PPC_SECTOFF = 33
+ R_PPC_SECTOFF_LO = 34
+ R_PPC_SECTOFF_HI = 35
+ R_PPC_SECTOFF_HA = 36
+ R_PPC_TLS = 67
+ R_PPC_DTPMOD32 = 68
+ R_PPC_TPREL16 = 69
+ R_PPC_TPREL16_LO = 70
+ R_PPC_TPREL16_HI = 71
+ R_PPC_TPREL16_HA = 72
+ R_PPC_TPREL32 = 73
+ R_PPC_DTPREL16 = 74
+ R_PPC_DTPREL16_LO = 75
+ R_PPC_DTPREL16_HI = 76
+ R_PPC_DTPREL16_HA = 77
+ R_PPC_DTPREL32 = 78
+ R_PPC_GOT_TLSGD16 = 79
+ R_PPC_GOT_TLSGD16_LO = 80
+ R_PPC_GOT_TLSGD16_HI = 81
+ R_PPC_GOT_TLSGD16_HA = 82
+ R_PPC_GOT_TLSLD16 = 83
+ R_PPC_GOT_TLSLD16_LO = 84
+ R_PPC_GOT_TLSLD16_HI = 85
+ R_PPC_GOT_TLSLD16_HA = 86
+ R_PPC_GOT_TPREL16 = 87
+ R_PPC_GOT_TPREL16_LO = 88
+ R_PPC_GOT_TPREL16_HI = 89
+ R_PPC_GOT_TPREL16_HA = 90
+ R_PPC_EMB_NADDR32 = 101
+ R_PPC_EMB_NADDR16 = 102
+ R_PPC_EMB_NADDR16_LO = 103
+ R_PPC_EMB_NADDR16_HI = 104
+ R_PPC_EMB_NADDR16_HA = 105
+ R_PPC_EMB_SDAI16 = 106
+ R_PPC_EMB_SDA2I16 = 107
+ R_PPC_EMB_SDA2REL = 108
+ R_PPC_EMB_SDA21 = 109
+ R_PPC_EMB_MRKREF = 110
+ R_PPC_EMB_RELSEC16 = 111
+ R_PPC_EMB_RELST_LO = 112
+ R_PPC_EMB_RELST_HI = 113
+ R_PPC_EMB_RELST_HA = 114
+ R_PPC_EMB_BIT_FLD = 115
+ R_PPC_EMB_RELSDA = 116
+
+ R_PPC64_ADDR32 = R_PPC_ADDR32
+ R_PPC64_ADDR16_LO = R_PPC_ADDR16_LO
+ R_PPC64_ADDR16_HA = R_PPC_ADDR16_HA
+ R_PPC64_REL24 = R_PPC_REL24
+ R_PPC64_GOT16_HA = R_PPC_GOT16_HA
+ R_PPC64_JMP_SLOT = R_PPC_JMP_SLOT
+ R_PPC64_TPREL16 = R_PPC_TPREL16
+ R_PPC64_ADDR64 = 38
+ R_PPC64_TOC16 = 47
+ R_PPC64_TOC16_LO = 48
+ R_PPC64_TOC16_HI = 49
+ R_PPC64_TOC16_HA = 50
+ R_PPC64_ADDR16_LO_DS = 57
+ R_PPC64_GOT16_LO_DS = 59
+ R_PPC64_TOC16_DS = 63
+ R_PPC64_TOC16_LO_DS = 64
+ R_PPC64_TLS = 67
+ R_PPC64_GOT_TPREL16_LO_DS = 88
+ R_PPC64_GOT_TPREL16_HA = 90
+ R_PPC64_REL16_LO = 250
+ R_PPC64_REL16_HI = 251
+ R_PPC64_REL16_HA = 252
+
+ R_SPARC_NONE = 0
+ R_SPARC_8 = 1
+ R_SPARC_16 = 2
+ R_SPARC_32 = 3
+ R_SPARC_DISP8 = 4
+ R_SPARC_DISP16 = 5
+ R_SPARC_DISP32 = 6
+ R_SPARC_WDISP30 = 7
+ R_SPARC_WDISP22 = 8
+ R_SPARC_HI22 = 9
+ R_SPARC_22 = 10
+ R_SPARC_13 = 11
+ R_SPARC_LO10 = 12
+ R_SPARC_GOT10 = 13
+ R_SPARC_GOT13 = 14
+ R_SPARC_GOT22 = 15
+ R_SPARC_PC10 = 16
+ R_SPARC_PC22 = 17
+ R_SPARC_WPLT30 = 18
+ R_SPARC_COPY = 19
+ R_SPARC_GLOB_DAT = 20
+ R_SPARC_JMP_SLOT = 21
+ R_SPARC_RELATIVE = 22
+ R_SPARC_UA32 = 23
+ R_SPARC_PLT32 = 24
+ R_SPARC_HIPLT22 = 25
+ R_SPARC_LOPLT10 = 26
+ R_SPARC_PCPLT32 = 27
+ R_SPARC_PCPLT22 = 28
+ R_SPARC_PCPLT10 = 29
+ R_SPARC_10 = 30
+ R_SPARC_11 = 31
+ R_SPARC_64 = 32
+ R_SPARC_OLO10 = 33
+ R_SPARC_HH22 = 34
+ R_SPARC_HM10 = 35
+ R_SPARC_LM22 = 36
+ R_SPARC_PC_HH22 = 37
+ R_SPARC_PC_HM10 = 38
+ R_SPARC_PC_LM22 = 39
+ R_SPARC_WDISP16 = 40
+ R_SPARC_WDISP19 = 41
+ R_SPARC_GLOB_JMP = 42
+ R_SPARC_7 = 43
+ R_SPARC_5 = 44
+ R_SPARC_6 = 45
+ R_SPARC_DISP64 = 46
+ R_SPARC_PLT64 = 47
+ R_SPARC_HIX22 = 48
+ R_SPARC_LOX10 = 49
+ R_SPARC_H44 = 50
+ R_SPARC_M44 = 51
+ R_SPARC_L44 = 52
+ R_SPARC_REGISTER = 53
+ R_SPARC_UA64 = 54
+ R_SPARC_UA16 = 55
+
+ ARM_MAGIC_TRAMP_NUMBER = 0x5c000003
)
/*
}
fallthrough
- case '6', '7':
+ case '0', '6', '7':
+ if Thearch.Thechar == '0' {
+ ehdr.flags = 0x20000000 /* MIPS 3 */
+ }
elf64 = true
ehdr.phoff = ELF64HDRSIZE /* Must be be ELF64HDRSIZE: first PHdr must follow ELF header */
}
switch Thearch.Thechar {
- case '6', '7', '9':
+ case '0', '6', '7', '9':
sy := Linklookup(Ctxt, ".rela.plt", 0)
if sy.Size > 0 {
Elfwritedynent(s, DT_PLTREL, DT_RELA)
var prefix string
var typ int
switch Thearch.Thechar {
- case '6', '7', '9':
+ case '0', '6', '7', '9':
prefix = ".rela"
typ = SHT_RELA
default:
continue
}
- if r.Xsym.Elfsym == 0 {
+ if r.Xsym.ElfsymForReloc() == 0 {
Diag("reloc %d to non-elf symbol %s (outer=%s) %d", r.Type, r.Sym.Name, r.Xsym.Name, r.Sym.Type)
}
if Thearch.Elfreloc1(r, int64(uint64(sym.Value+int64(r.Off))-sect.Vaddr)) < 0 {
Debug['d'] = 1
switch Thearch.Thechar {
- case '6', '7', '9':
+ case '0', '6', '7', '9':
Addstring(shstrtab, ".rela.text")
Addstring(shstrtab, ".rela.rodata")
Addstring(shstrtab, ".rela"+relro_prefix+".typelink")
if hasinitarr {
Addstring(shstrtab, ".init_array")
switch Thearch.Thechar {
- case '6', '7', '9':
+ case '0', '6', '7', '9':
Addstring(shstrtab, ".rela.init_array")
default:
Addstring(shstrtab, ".rel.init_array")
Addstring(shstrtab, ".dynsym")
Addstring(shstrtab, ".dynstr")
switch Thearch.Thechar {
- case '6', '7', '9':
+ case '0', '6', '7', '9':
Addstring(shstrtab, ".rela")
Addstring(shstrtab, ".rela.plt")
default:
s.Type = obj.SELFROSECT
s.Reachable = true
switch Thearch.Thechar {
- case '6', '7', '9':
+ case '0', '6', '7', '9':
s.Size += ELF64SYMSIZE
default:
s.Size += ELF32SYMSIZE
/* relocation table */
switch Thearch.Thechar {
- case '6', '7', '9':
+ case '0', '6', '7', '9':
s = Linklookup(Ctxt, ".rela", 0)
default:
s = Linklookup(Ctxt, ".rel", 0)
Thearch.Elfsetupplt()
switch Thearch.Thechar {
- case '6', '7', '9':
+ case '0', '6', '7', '9':
s = Linklookup(Ctxt, ".rela.plt", 0)
default:
s = Linklookup(Ctxt, ".rel.plt", 0)
elfwritedynentsym(s, DT_SYMTAB, Linklookup(Ctxt, ".dynsym", 0))
switch Thearch.Thechar {
- case '6', '7', '9':
+ case '0', '6', '7', '9':
Elfwritedynent(s, DT_SYMENT, ELF64SYMSIZE)
default:
Elfwritedynent(s, DT_SYMENT, ELF32SYMSIZE)
elfwritedynentsym(s, DT_STRTAB, Linklookup(Ctxt, ".dynstr", 0))
elfwritedynentsymsize(s, DT_STRSZ, Linklookup(Ctxt, ".dynstr", 0))
switch Thearch.Thechar {
- case '6', '7', '9':
+ case '0', '6', '7', '9':
elfwritedynentsym(s, DT_RELA, Linklookup(Ctxt, ".rela", 0))
elfwritedynentsymsize(s, DT_RELASZ, Linklookup(Ctxt, ".rela", 0))
Elfwritedynent(s, DT_RELAENT, ELF64RELASIZE)
switch Thearch.Thechar {
default:
Exitf("unknown architecture in asmbelf: %v", Thearch.Thechar)
+ case '0':
+ eh.machine = EM_MIPS
case '5':
eh.machine = EM_ARM
case '6':
return
}
+ // \n$$B marks the beginning of binary export data - don't skip over the B
p0 += 3
- for p0 < len(data) && data[p0] != '\n' {
+ for p0 < len(data) && data[p0] != '\n' && data[p0] != 'B' {
p0++
}
// second marks end of exports / beginning of local data
- p1 = strings.Index(data[p0:], "\n$$")
+ p1 = strings.Index(data[p0:], "\n$$\n")
if p1 < 0 {
fmt.Fprintf(os.Stderr, "%s: cannot find end of exports in %s\n", os.Args[0], filename)
if Debug['u'] != 0 {
}
p1 += p0
- for p0 < p1 && (data[p0] == ' ' || data[p0] == '\t' || data[p0] == '\n') {
+ for p0 < p1 && data[p0] != 'B' && (data[p0] == ' ' || data[p0] == '\t' || data[p0] == '\n') {
p0++
}
- if p0 < p1 {
+ // don't check this section if we have binary (B) export data
+ // TODO fix this eventually
+ if p0 < p1 && data[p0] != 'B' {
if !strings.HasPrefix(data[p0:], "package ") {
fmt.Fprintf(os.Stderr, "%s: bad package section in %s - %.20s\n", os.Args[0], filename, data[p0:])
if Debug['u'] != 0 {
Diag("%s: elf %s unimplemented", pn, Thestring)
return
+ case '0':
+ if elfobj.machine != ElfMachMips || hdr.Ident[4] != ElfClass64 {
+ Diag("%s: elf object but not mips64", pn)
+ return
+ }
+
case '5':
if e != binary.LittleEndian || elfobj.machine != ElfMachArm || hdr.Ident[4] != ElfClass32 {
Diag("%s: elf object but not arm", pn)
if strings.HasPrefix(sym.name, ".Linfo_string") { // clang does this
continue
}
+
+ if sym.name == "" && sym.type_ == 0 && sect.name == ".debug_str" {
+ // This reportedly happens with clang 3.7 on ARM.
+ // See issue 13139.
+ continue
+ }
+
Diag("%s: sym#%d: ignoring %s in section %d (type %d)", pn, i, sym.name, sym.shndx, sym.type_)
continue
}
case ElfSymBindWeak:
if needSym != 0 {
- s = linknewsym(Ctxt, sym.name, 0)
+ s = Linklookup(Ctxt, sym.name, 0)
if sym.other == 2 {
s.Type |= obj.SHIDDEN
}
'6' | R_X86_64_PC32<<24,
'6' | R_X86_64_PLT32<<24,
'6' | R_X86_64_GOTPCREL<<24,
+ '6' | R_X86_64_GOTPCRELX<<24,
+ '6' | R_X86_64_REX_GOTPCRELX<<24,
'8' | R_386_32<<24,
'8' | R_386_PC32<<24,
'8' | R_386_GOT32<<24,
'8' | R_386_PLT32<<24,
'8' | R_386_GOTOFF<<24,
'8' | R_386_GOTPC<<24,
+ '8' | R_386_GOT32X<<24,
'9' | R_PPC64_REL24<<24:
*siz = 4
"path/filepath"
"runtime"
"strings"
+ "sync"
)
// Data layout and relocation.
elfglobalsymndx int
flag_installsuffix string
flag_race int
+ flag_msan int
Buildmode BuildMode
Linkshared bool
tracksym string
*mode = BuildmodeExe
case "pie":
switch goos {
- case "android":
+ case "android", "linux":
default:
return badmode()
}
}
*mode = BuildmodeCArchive
case "c-shared":
- if goarch != "amd64" && goarch != "arm" {
+ if goarch != "amd64" && goarch != "arm" && goarch != "arm64" {
return badmode()
}
*mode = BuildmodeCShared
case "shared":
- if goos != "linux" || (goarch != "amd64" && goarch != "arm") {
+ if goos != "linux" || (goarch != "386" && goarch != "amd64" && goarch != "arm" && goarch != "arm64" && goarch != "ppc64le") {
return badmode()
}
*mode = BuildmodeShared
} else if flag_race != 0 {
suffixsep = "_"
suffix = "race"
+ } else if flag_msan != 0 {
+ suffixsep = "_"
+ suffix = "msan"
}
Lflag(fmt.Sprintf("%s/pkg/%s_%s%s%s", goroot, goos, goarch, suffixsep, suffix))
if flag_race != 0 {
loadinternal("runtime/race")
}
+ if flag_msan != 0 {
+ loadinternal("runtime/msan")
+ }
var i int
for i = 0; i < len(Ctxt.Library); i++ {
Linkmode = LinkExternal
}
+ // Force external linking for PIE executables, as
+ // internal linking does not support TLS_IE.
+ if Buildmode == BuildmodePIE {
+ Linkmode = LinkExternal
+ }
+
// cgo on Darwin must use external linking
// we can always use external linking, but then there will be circular
// dependency problems when compiling natively (external linking requires
if (Thearch.Thechar == '5' || Thearch.Thechar == '7') && HEADTYPE == obj.Hdarwin && iscgo {
Linkmode = LinkExternal
}
+
+ // Force external linking for msan.
+ if flag_msan != 0 {
+ Linkmode = LinkExternal
+ }
}
// cmd/7l doesn't support cgo internal linking
// In internal link mode, read the host object files.
if Linkmode == LinkInternal {
hostobjs()
+
+ // If we have any undefined symbols in external
+ // objects, try to read them from our copy of the C
+ // compiler support library, libgcc.a.
+ any := false
+ for s := Ctxt.Allsym; s != nil; s = s.Allsym {
+ for _, r := range s.R {
+ if r.Sym != nil && r.Sym.Type&obj.SMASK == obj.SXREF {
+ any = true
+ break
+ }
+ }
+ }
+ if any {
+ hostArchive(fmt.Sprintf("%s/pkg/libgcc/%s_%s/libgcc", goroot, goos, goarch))
+ }
} else {
hostlinksetup()
}
"os/user",
"runtime/cgo",
"runtime/race",
+ "runtime/msan",
}
-func ldhostobj(ld func(*obj.Biobuf, string, int64, string), f *obj.Biobuf, pkg string, length int64, pn string, file string) {
+func ldhostobj(ld func(*obj.Biobuf, string, int64, string), f *obj.Biobuf, pkg string, length int64, pn string, file string) *Hostobj {
isinternal := false
for i := 0; i < len(internalpkg); i++ {
if pkg == internalpkg[i] {
h.file = file
h.off = obj.Boffset(f)
h.length = length
+ return h
}
func hostobjs() {
// hostobjCopy creates a copy of the object files in hostobj in a
// temporary directory.
func hostobjCopy() (paths []string) {
+ var wg sync.WaitGroup
+ sema := make(chan struct{}, runtime.NumCPU()) // limit open file descriptors
for i, h := range hostobj {
- f, err := os.Open(h.file)
- if err != nil {
- Exitf("cannot reopen %s: %v", h.pn, err)
- }
- if _, err := f.Seek(h.off, 0); err != nil {
- Exitf("cannot seek %s: %v", h.pn, err)
- }
+ h := h
+ dst := fmt.Sprintf("%s/%06d.o", tmpdir, i)
+ paths = append(paths, dst)
+
+ wg.Add(1)
+ go func() {
+ sema <- struct{}{}
+ defer func() {
+ <-sema
+ wg.Done()
+ }()
+ f, err := os.Open(h.file)
+ if err != nil {
+ Exitf("cannot reopen %s: %v", h.pn, err)
+ }
+ if _, err := f.Seek(h.off, 0); err != nil {
+ Exitf("cannot seek %s: %v", h.pn, err)
+ }
- p := fmt.Sprintf("%s/%06d.o", tmpdir, i)
- paths = append(paths, p)
- w, err := os.Create(p)
- if err != nil {
- Exitf("cannot create %s: %v", p, err)
- }
- if _, err := io.CopyN(w, f, h.length); err != nil {
- Exitf("cannot write %s: %v", p, err)
- }
- if err := w.Close(); err != nil {
- Exitf("cannot close %s: %v", p, err)
- }
+ w, err := os.Create(dst)
+ if err != nil {
+ Exitf("cannot create %s: %v", dst, err)
+ }
+ if _, err := io.CopyN(w, f, h.length); err != nil {
+ Exitf("cannot write %s: %v", dst, err)
+ }
+ if err := w.Close(); err != nil {
+ Exitf("cannot close %s: %v", dst, err)
+ }
+ }()
}
+ wg.Wait()
return paths
}
argv = append(argv, "-shared", "-Wl,-z,nodelete")
}
case BuildmodeShared:
- // TODO(mwhudson): unless you do this, dynamic relocations fill
- // out the findfunctab table and for some reason shared libraries
- // and the executable both define a main function and putting the
- // address of executable's main into the shared libraries
- // findfunctab violates the assumptions of the runtime. TBH, I
- // think we may well end up wanting to use -Bsymbolic here
- // anyway.
- argv = append(argv, "-Wl,-Bsymbolic-functions")
if UseRelro() {
argv = append(argv, "-Wl,-z,relro")
}
Ctxt.Cursym = nil
Exitf("%s: running dsymutil failed: %v\n%s", os.Args[0], err, out)
}
+ // Skip combining if `dsymutil` didn't generate a file. See #11994.
+ if _, err := os.Stat(dsym); os.IsNotExist(err) {
+ return
+ }
// For os.Rename to work reliably, must be in same directory as outfile.
combinedOutput := outfile + "~"
if err := machoCombineDwarf(outfile, dsym, combinedOutput); err != nil {
}
}
-func ldobj(f *obj.Biobuf, pkg string, length int64, pn string, file string, whence int) {
+// ldobj loads an input object. If it is a host object (an object
+// compiled by a non-Go compiler) it returns the Hostobj pointer. If
+// it is a Go object, it returns nil.
+func ldobj(f *obj.Biobuf, pkg string, length int64, pn string, file string, whence int) *Hostobj {
eof := obj.Boffset(f) + length
start := obj.Boffset(f)
magic := uint32(c1)<<24 | uint32(c2)<<16 | uint32(c3)<<8 | uint32(c4)
if magic == 0x7f454c46 { // \x7F E L F
- ldhostobj(ldelf, f, pkg, length, pn, file)
- return
+ return ldhostobj(ldelf, f, pkg, length, pn, file)
}
if magic&^1 == 0xfeedface || magic&^0x01000000 == 0xcefaedfe {
- ldhostobj(ldmacho, f, pkg, length, pn, file)
- return
+ return ldhostobj(ldmacho, f, pkg, length, pn, file)
}
if c1 == 0x4c && c2 == 0x01 || c1 == 0x64 && c2 == 0x86 {
- ldhostobj(ldpe, f, pkg, length, pn, file)
- return
+ return ldhostobj(ldpe, f, pkg, length, pn, file)
}
/* check the header */
if line == "" {
if obj.Blinelen(f) > 0 {
Diag("%s: not an object file", pn)
- return
+ return nil
}
Diag("truncated object file: %s", pn)
- return
+ return nil
}
if !strings.HasPrefix(line, "go object ") {
if line == Thestring {
// old header format: just $GOOS
Diag("%s: stale object file", pn)
- return
+ return nil
}
Diag("%s: not an object file", pn)
- return
+ return nil
}
// First, check that the basic goos, goarch, and version match.
line = strings.TrimRight(line, "\n")
if !strings.HasPrefix(line[10:]+" ", t) && Debug['f'] == 0 {
Diag("%s: object is [%s] expected [%s]", pn, line[10:], t)
- return
+ return nil
}
// Second, check that longer lines match each other exactly,
theline = line[10:]
} else if theline != line[10:] {
Diag("%s: object is [%s] expected [%s]", pn, line[10:], theline)
- return
+ return nil
}
}
c3 = obj.Bgetc(f)
if c3 == obj.Beof {
Diag("truncated object file: %s", pn)
- return
+ return nil
}
}
obj.Bseek(f, import1, 0)
ldobjfile(Ctxt, f, pkg, eof-obj.Boffset(f), pn)
+ return nil
}
func readelfsymboldata(f *elf.File, sym *elf.Symbol) []byte {
if err == io.EOF {
break
}
- return nil, fmt.Errorf("read namesize failed:", err)
+ return nil, fmt.Errorf("read namesize failed: %v", err)
}
err = binary.Read(r, f.ByteOrder, &descsize)
if err != nil {
- return nil, fmt.Errorf("read descsize failed:", err)
+ return nil, fmt.Errorf("read descsize failed: %v", err)
}
err = binary.Read(r, f.ByteOrder, ¬eType)
if err != nil {
- return nil, fmt.Errorf("read type failed:", err)
+ return nil, fmt.Errorf("read type failed: %v", err)
}
noteName, err := readwithpad(r, namesize)
if err != nil {
- return nil, fmt.Errorf("read name failed:", err)
+ return nil, fmt.Errorf("read name failed: %v", err)
}
desc, err := readwithpad(r, descsize)
if err != nil {
- return nil, fmt.Errorf("read desc failed:", err)
+ return nil, fmt.Errorf("read desc failed: %v", err)
}
if string(name) == string(noteName) && typ == noteType {
return desc, nil
Diag("cannot read symbols from shared library: %s", libpath)
return
}
+ gcdata_locations := make(map[uint64]*LSym)
for _, elfsym := range syms {
if elf.ST_TYPE(elfsym.Info) == elf.STT_NOTYPE || elf.ST_TYPE(elfsym.Info) == elf.STT_SECTION {
continue
// the type data.
if strings.HasPrefix(lsym.Name, "type.") && !strings.HasPrefix(lsym.Name, "type..") {
lsym.P = readelfsymboldata(f, &elfsym)
+ gcdata_locations[elfsym.Value+2*uint64(Thearch.Ptrsize)+8+1*uint64(Thearch.Ptrsize)] = lsym
+ }
+ }
+ }
+ gcdata_addresses := make(map[*LSym]uint64)
+ if Thearch.Thechar == '7' {
+ for _, sect := range f.Sections {
+ if sect.Type == elf.SHT_RELA {
+ var rela elf.Rela64
+ rdr := sect.Open()
+ for {
+ err := binary.Read(rdr, f.ByteOrder, &rela)
+ if err == io.EOF {
+ break
+ } else if err != nil {
+ Diag("reading relocation failed %v", err)
+ return
+ }
+ t := elf.R_AARCH64(rela.Info & 0xffff)
+ if t != elf.R_AARCH64_RELATIVE {
+ continue
+ }
+ if lsym, ok := gcdata_locations[rela.Off]; ok {
+ gcdata_addresses[lsym] = uint64(rela.Addend)
+ }
+ }
}
}
}
Ctxt.Etextp = last
}
- Ctxt.Shlibs = append(Ctxt.Shlibs, Shlib{Path: libpath, Hash: hash, Deps: deps, File: f})
+ Ctxt.Shlibs = append(Ctxt.Shlibs, Shlib{Path: libpath, Hash: hash, Deps: deps, File: f, gcdata_addresses: gcdata_addresses})
}
func mywhatsys() {
// allow stack checks here.
func haslinkregister() bool {
- return Thearch.Thechar == '5' || Thearch.Thechar == '9' || Thearch.Thechar == '7'
+ return Ctxt.FixedFrameSize() != 0
}
func callsize() int {
return 0
}
// Raise limit to allow frame.
- limit = int(obj.StackLimit + s.Locals)
- if haslinkregister() {
- limit += Thearch.Regsize
- }
+ limit = int(obj.StackLimit+s.Locals) + int(Ctxt.FixedFrameSize())
}
// Walk through sp adjustments in function, consuming relocs.
r = &s.R[ri]
switch r.Type {
// Direct call.
- case obj.R_CALL, obj.R_CALLARM, obj.R_CALLARM64, obj.R_CALLPOWER:
+ case obj.R_CALL, obj.R_CALLARM, obj.R_CALLARM64, obj.R_CALLPOWER, obj.R_CALLMIPS:
ch.limit = int(int32(limit) - pcsp.value - int32(callsize()))
ch.sym = r.Sym
if stkcheck(&ch, depth+1) < 0 {
}
for s := Ctxt.Allsym; s != nil; s = s.Allsym {
- if s.Hide != 0 || (s.Name[0] == '.' && s.Version == 0 && s.Name != ".rathole") {
+ if s.Hide != 0 || ((s.Name == "" || s.Name[0] == '.') && s.Version == 0 && s.Name != ".rathole" && s.Name != ".TOC.") {
continue
}
switch s.Type & obj.SMASK {
if r.Sym == nil {
continue
}
- if (r.Type == obj.R_CALL || r.Type == obj.R_CALLARM || r.Type == obj.R_CALLPOWER) && r.Sym.Type == obj.STEXT {
+ if (r.Type == obj.R_CALL || r.Type == obj.R_CALLARM || r.Type == obj.R_CALLPOWER || r.Type == obj.R_CALLMIPS) && r.Sym.Type == obj.STEXT {
fmt.Fprintf(&Bso, "%s calls %s\n", s.Name, r.Sym.Name)
}
}
Got int32
Align int32
Elfsym int32
+ LocalElfsym int32
Args int32
Locals int32
Value int64
Size int64
- Hash *LSym
Allsym *LSym
Next *LSym
Sub *LSym
return fmt.Sprintf("%s<%d>", s.Name, s.Version)
}
+func (s *LSym) ElfsymForReloc() int32 {
+ // If putelfsym created a local version of this symbol, use that in all
+ // relocations.
+ if s.LocalElfsym != 0 {
+ return s.LocalElfsym
+ } else {
+ return s.Elfsym
+ }
+}
+
type Reloc struct {
Off int32
Siz uint8
}
type Shlib struct {
- Path string
- Hash []byte
- Deps []string
- File *elf.File
+ Path string
+ Hash []byte
+ Deps []string
+ File *elf.File
+ gcdata_addresses map[*LSym]uint64
}
type Link struct {
Moduledata *LSym
}
+// The smallest possible offset from the hardware stack pointer to a local
+// variable on the stack. Architectures that use a link register save its value
+// on the stack in the function prologue and so always have a pointer between
+// the hardware stack pointer and the local variable area.
+func (ctxt *Link) FixedFrameSize() int64 {
+ switch ctxt.Arch.Thechar {
+ case '6', '8':
+ return 0
+ case '9':
+ // PIC code on ppc64le requires 32 bytes of stack, and it's easier to
+ // just use that much stack always on ppc64x.
+ return int64(4 * ctxt.Arch.Ptrsize)
+ default:
+ return int64(ctxt.Arch.Ptrsize)
+ }
+}
+
type LinkArch struct {
ByteOrder binary.ByteOrder
Name string
obj.Flagstr("k", "set field tracking `symbol`", &tracksym)
obj.Flagfn1("linkmode", "set link `mode` (internal, external, auto)", setlinkmode)
flag.BoolVar(&Linkshared, "linkshared", false, "link against installed Go shared libraries")
+ obj.Flagcount("msan", "enable MSan interface", &flag_msan)
obj.Flagcount("n", "dump symbol table", &Debug['n'])
obj.Flagstr("o", "write output to `file`", &outfile)
flag.Var(&rpath, "r", "set the ELF dynamic linker search `path` to dir1:dir2:...")
obj.Hopenbsd,
obj.Hdragonfly,
obj.Hsolaris:
- ctxt.Tlsoffset = -1 * ctxt.Arch.Ptrsize
+ if obj.Getgoos() == "android" {
+ switch ctxt.Arch.Thechar {
+ case '6':
+ // Android/amd64 constant - offset from 0(FS) to our TLS slot.
+ // Explained in src/runtime/cgo/gcc_android_*.c
+ ctxt.Tlsoffset = 0x1d0
+ case '8':
+ // Android/386 constant - offset from 0(GS) to our TLS slot.
+ ctxt.Tlsoffset = 0xf8
+ default:
+ ctxt.Tlsoffset = -1 * ctxt.Arch.Ptrsize
+ }
+ } else {
+ ctxt.Tlsoffset = -1 * ctxt.Arch.Ptrsize
+ }
case obj.Hnacl:
switch ctxt.Arch.Thechar {
/*
* OS X system constants - offset from 0(GS) to our TLS.
- * Explained in ../../runtime/cgo/gcc_darwin_*.c.
+ * Explained in src/runtime/cgo/gcc_darwin_*.c.
*/
case obj.Hdarwin:
switch ctxt.Arch.Thechar {
func putelfsyment(off int, addr int64, size int64, info int, shndx int, other int) {
switch Thearch.Thechar {
- case '6', '7', '9':
+ case '0', '6', '7', '9':
Thearch.Lput(uint32(off))
Cput(uint8(info))
Cput(uint8(other))
bind = STB_LOCAL
}
- if bind != elfbind {
- return
- }
-
- off := putelfstr(s)
if Linkmode == LinkExternal && elfshnum != SHN_UNDEF {
addr -= int64(xo.Sect.Vaddr)
}
if x.Type&obj.SHIDDEN != 0 {
other = STV_HIDDEN
}
- putelfsyment(off, addr, size, bind<<4|type_&0xf, elfshnum, other)
+ if (Buildmode == BuildmodePIE || DynlinkingGo()) && Thearch.Thechar == '9' && type_ == STT_FUNC && x.Name != "runtime.duffzero" && x.Name != "runtime.duffcopy" {
+ // On ppc64 the top three bits of the st_other field indicate how
+ // many instructions separate the global and local entry points. In
+ // our case it is two instructions, indicated by the value 3.
+ other |= 3 << 5
+ }
+
+ if DynlinkingGo() && bind == STB_GLOBAL && elfbind == STB_LOCAL && x.Type == obj.STEXT {
+ // When dynamically linking, we want references to functions defined
+ // in this module to always be to the function object, not to the
+ // PLT. We force this by writing an additional local symbol for every
+ // global function symbol and making all relocations against the
+ // global symbol refer to this local symbol instead (see
+ // (*LSym).ElfsymForReloc). This is approximately equivalent to the
+ // ELF linker -Bsymbolic-functions option, but that is buggy on
+ // several platforms.
+ putelfsyment(putelfstr("local."+s), addr, size, STB_LOCAL<<4|type_&0xf, elfshnum, other)
+ x.LocalElfsym = int32(numelfsym)
+ numelfsym++
+ return
+ } else if bind != elfbind {
+ return
+ }
+
+ putelfsyment(putelfstr(s), addr, size, bind<<4|type_&0xf, elfshnum, other)
x.Elfsym = int32(numelfsym)
numelfsym++
}
adduint(Ctxt, moduledata, uint64(pclntabNfunc+1))
// The filetab slice
Addaddrplus(Ctxt, moduledata, Linklookup(Ctxt, "runtime.pclntab", 0), int64(pclntabFiletabOffset))
- adduint(Ctxt, moduledata, uint64(Ctxt.Nhistfile))
- adduint(Ctxt, moduledata, uint64(Ctxt.Nhistfile))
+ adduint(Ctxt, moduledata, uint64(Ctxt.Nhistfile)+1)
+ adduint(Ctxt, moduledata, uint64(Ctxt.Nhistfile)+1)
// findfunctab
Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.findfunctab", 0))
// minpc, maxpc
--- /dev/null
+// Inferno utils/5l/asm.c
+// http://code.google.com/p/inferno-os/source/browse/utils/5l/asm.c
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package mips64
+
+import (
+ "cmd/internal/obj"
+ "cmd/link/internal/ld"
+ "encoding/binary"
+ "fmt"
+ "log"
+)
+
+func gentext() {}
+
+func adddynrela(rel *ld.LSym, s *ld.LSym, r *ld.Reloc) {
+ log.Fatalf("adddynrela not implemented")
+}
+
+func adddynrel(s *ld.LSym, r *ld.Reloc) {
+ log.Fatalf("adddynrel not implemented")
+}
+
+func elfreloc1(r *ld.Reloc, sectoff int64) int {
+ return -1
+}
+
+func elfsetupplt() {
+ return
+}
+
+func machoreloc1(r *ld.Reloc, sectoff int64) int {
+ return -1
+}
+
+func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
+ if ld.Linkmode == ld.LinkExternal {
+ return -1
+ }
+
+ switch r.Type {
+ case obj.R_CONST:
+ *val = r.Add
+ return 0
+
+ case obj.R_GOTOFF:
+ *val = ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ld.Linklookup(ld.Ctxt, ".got", 0))
+ return 0
+
+ case obj.R_ADDRMIPS:
+ t := ld.Symaddr(r.Sym) + r.Add
+ if t >= 1<<32 || t < -1<<32 {
+ ld.Diag("program too large, address relocation = %v", t)
+ }
+
+ // the first instruction is always at the lower address, this is endian neutral;
+ // but note that o1 and o2 should still use the target endian.
+ o1 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off:])
+ o2 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off+4:])
+ o1 = o1&0xffff0000 | uint32(t>>16)&0xffff
+ o2 = o2&0xffff0000 | uint32(t)&0xffff
+
+ // when laid out, the instruction order must always be o1, o2.
+ if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
+ *val = int64(o1)<<32 | int64(o2)
+ } else {
+ *val = int64(o2)<<32 | int64(o1)
+ }
+ return 0
+
+ case obj.R_CALLMIPS,
+ obj.R_JMPMIPS:
+ // Low 26 bits = (S + A) >> 2
+ t := ld.Symaddr(r.Sym) + r.Add
+ o1 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off:])
+ *val = int64(o1&0xfc000000 | uint32(t>>2)&^0xfc000000)
+ return 0
+ }
+
+ return -1
+}
+
+func archrelocvariant(r *ld.Reloc, s *ld.LSym, t int64) int64 {
+ return -1
+}
+
+func asmb() {
+ if ld.Debug['v'] != 0 {
+ fmt.Fprintf(&ld.Bso, "%5.2f asmb\n", obj.Cputime())
+ }
+ ld.Bso.Flush()
+
+ if ld.Iself {
+ ld.Asmbelfsetup()
+ }
+
+ sect := ld.Segtext.Sect
+ ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
+ ld.Codeblk(int64(sect.Vaddr), int64(sect.Length))
+ for sect = sect.Next; sect != nil; sect = sect.Next {
+ ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
+ ld.Datblk(int64(sect.Vaddr), int64(sect.Length))
+ }
+
+ if ld.Segrodata.Filelen > 0 {
+ if ld.Debug['v'] != 0 {
+ fmt.Fprintf(&ld.Bso, "%5.2f rodatblk\n", obj.Cputime())
+ }
+ ld.Bso.Flush()
+
+ ld.Cseek(int64(ld.Segrodata.Fileoff))
+ ld.Datblk(int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
+ }
+
+ if ld.Debug['v'] != 0 {
+ fmt.Fprintf(&ld.Bso, "%5.2f datblk\n", obj.Cputime())
+ }
+ ld.Bso.Flush()
+
+ ld.Cseek(int64(ld.Segdata.Fileoff))
+ ld.Datblk(int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
+
+ /* output symbol table */
+ ld.Symsize = 0
+
+ ld.Lcsize = 0
+ symo := uint32(0)
+ if ld.Debug['s'] == 0 {
+ // TODO: rationalize
+ if ld.Debug['v'] != 0 {
+ fmt.Fprintf(&ld.Bso, "%5.2f sym\n", obj.Cputime())
+ }
+ ld.Bso.Flush()
+ switch ld.HEADTYPE {
+ default:
+ if ld.Iself {
+ symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
+ symo = uint32(ld.Rnd(int64(symo), int64(ld.INITRND)))
+ }
+
+ case obj.Hplan9:
+ symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
+ }
+
+ ld.Cseek(int64(symo))
+ switch ld.HEADTYPE {
+ default:
+ if ld.Iself {
+ if ld.Debug['v'] != 0 {
+ fmt.Fprintf(&ld.Bso, "%5.2f elfsym\n", obj.Cputime())
+ }
+ ld.Asmelfsym()
+ ld.Cflush()
+ ld.Cwrite(ld.Elfstrdat)
+
+ if ld.Debug['v'] != 0 {
+ fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime())
+ }
+ ld.Dwarfemitdebugsections()
+
+ if ld.Linkmode == ld.LinkExternal {
+ ld.Elfemitreloc()
+ }
+ }
+
+ case obj.Hplan9:
+ ld.Asmplan9sym()
+ ld.Cflush()
+
+ sym := ld.Linklookup(ld.Ctxt, "pclntab", 0)
+ if sym != nil {
+ ld.Lcsize = int32(len(sym.P))
+ for i := 0; int32(i) < ld.Lcsize; i++ {
+ ld.Cput(uint8(sym.P[i]))
+ }
+
+ ld.Cflush()
+ }
+ }
+ }
+
+ ld.Ctxt.Cursym = nil
+ if ld.Debug['v'] != 0 {
+ fmt.Fprintf(&ld.Bso, "%5.2f header\n", obj.Cputime())
+ }
+ ld.Bso.Flush()
+ ld.Cseek(0)
+ switch ld.HEADTYPE {
+ default:
+ case obj.Hplan9: /* plan 9 */
+ magic := uint32(4*18*18 + 7)
+ if ld.Thestring == "mips64le" {
+ magic = uint32(4*26*26 + 7)
+ }
+ ld.Thearch.Lput(uint32(magic)) /* magic */
+ ld.Thearch.Lput(uint32(ld.Segtext.Filelen)) /* sizes */
+ ld.Thearch.Lput(uint32(ld.Segdata.Filelen))
+ ld.Thearch.Lput(uint32(ld.Segdata.Length - ld.Segdata.Filelen))
+ ld.Thearch.Lput(uint32(ld.Symsize)) /* nsyms */
+ ld.Thearch.Lput(uint32(ld.Entryvalue())) /* va of entry */
+ ld.Thearch.Lput(0)
+ ld.Thearch.Lput(uint32(ld.Lcsize))
+
+ case obj.Hlinux,
+ obj.Hfreebsd,
+ obj.Hnetbsd,
+ obj.Hopenbsd,
+ obj.Hnacl:
+ ld.Asmbelf(int64(symo))
+ }
+
+ ld.Cflush()
+ if ld.Debug['c'] != 0 {
+ fmt.Printf("textsize=%d\n", ld.Segtext.Filelen)
+ fmt.Printf("datsize=%d\n", ld.Segdata.Filelen)
+ fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen)
+ fmt.Printf("symsize=%d\n", ld.Symsize)
+ fmt.Printf("lcsize=%d\n", ld.Lcsize)
+ fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize))
+ }
+}
--- /dev/null
+// Inferno utils/5l/asm.c
+// http://code.google.com/p/inferno-os/source/browse/utils/5l/asm.c
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package mips64
+
+// Writing object files.
+
+// cmd/9l/l.h from Vita Nuova.
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+const (
+ thechar = '0'
+ MaxAlign = 32 // max data alignment
+ FuncAlign = 8
+ MINLC = 4
+)
+
+/* Used by ../internal/ld/dwarf.go */
+const (
+ DWARFREGSP = 29
+ DWARFREGLR = 31
+)
--- /dev/null
+// Inferno utils/5l/obj.c
+// http://code.google.com/p/inferno-os/source/browse/utils/5l/obj.c
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package mips64
+
+import (
+ "cmd/internal/obj"
+ "cmd/link/internal/ld"
+ "fmt"
+ "log"
+)
+
+// Reading object files.
+
+func Main() {
+ linkarchinit()
+ ld.Ldmain()
+}
+
+func linkarchinit() {
+ ld.Thestring = obj.Getgoarch()
+ if ld.Thestring == "mips64le" {
+ ld.Thelinkarch = &ld.Linkmips64le
+ } else {
+ ld.Thelinkarch = &ld.Linkmips64
+ }
+
+ ld.Thearch.Thechar = thechar
+ ld.Thearch.Ptrsize = ld.Thelinkarch.Ptrsize
+ ld.Thearch.Intsize = ld.Thelinkarch.Ptrsize
+ ld.Thearch.Regsize = ld.Thelinkarch.Regsize
+ ld.Thearch.Funcalign = FuncAlign
+ ld.Thearch.Maxalign = MaxAlign
+ ld.Thearch.Minlc = MINLC
+ ld.Thearch.Dwarfregsp = DWARFREGSP
+ ld.Thearch.Dwarfreglr = DWARFREGLR
+
+ ld.Thearch.Adddynrel = adddynrel
+ ld.Thearch.Archinit = archinit
+ ld.Thearch.Archreloc = archreloc
+ ld.Thearch.Archrelocvariant = archrelocvariant
+ ld.Thearch.Asmb = asmb
+ ld.Thearch.Elfreloc1 = elfreloc1
+ ld.Thearch.Elfsetupplt = elfsetupplt
+ ld.Thearch.Gentext = gentext
+ ld.Thearch.Machoreloc1 = machoreloc1
+ if ld.Thelinkarch == &ld.Linkmips64le {
+ ld.Thearch.Lput = ld.Lputl
+ ld.Thearch.Wput = ld.Wputl
+ ld.Thearch.Vput = ld.Vputl
+ } else {
+ ld.Thearch.Lput = ld.Lputb
+ ld.Thearch.Wput = ld.Wputb
+ ld.Thearch.Vput = ld.Vputb
+ }
+
+ ld.Thearch.Linuxdynld = "/lib64/ld64.so.1"
+
+ ld.Thearch.Freebsddynld = "XXX"
+ ld.Thearch.Openbsddynld = "XXX"
+ ld.Thearch.Netbsddynld = "XXX"
+ ld.Thearch.Dragonflydynld = "XXX"
+ ld.Thearch.Solarisdynld = "XXX"
+}
+
+func archinit() {
+ // getgoextlinkenabled is based on GO_EXTLINK_ENABLED when
+ // Go was built; see ../../make.bash.
+ if ld.Linkmode == ld.LinkAuto && obj.Getgoextlinkenabled() == "0" {
+ ld.Linkmode = ld.LinkInternal
+ }
+
+ switch ld.HEADTYPE {
+ default:
+ if ld.Linkmode == ld.LinkAuto {
+ ld.Linkmode = ld.LinkInternal
+ }
+ if ld.Linkmode == ld.LinkExternal && obj.Getgoextlinkenabled() != "1" {
+ log.Fatalf("cannot use -linkmode=external with -H %s", ld.Headstr(int(ld.HEADTYPE)))
+ }
+ }
+
+ switch ld.HEADTYPE {
+ default:
+ ld.Exitf("unknown -H option: %v", ld.HEADTYPE)
+
+ case obj.Hplan9: /* plan 9 */
+ ld.HEADR = 32
+
+ if ld.INITTEXT == -1 {
+ ld.INITTEXT = 16*1024 + int64(ld.HEADR)
+ }
+ if ld.INITDAT == -1 {
+ ld.INITDAT = 0
+ }
+ if ld.INITRND == -1 {
+ ld.INITRND = 16 * 1024
+ }
+
+ case obj.Hlinux: /* mips64 elf */
+ ld.Elfinit()
+ ld.HEADR = ld.ELFRESERVE
+ if ld.INITTEXT == -1 {
+ ld.INITTEXT = 0x10000 + int64(ld.HEADR)
+ }
+ if ld.INITDAT == -1 {
+ ld.INITDAT = 0
+ }
+ if ld.INITRND == -1 {
+ ld.INITRND = 0x10000
+ }
+
+ case obj.Hnacl:
+ ld.Elfinit()
+ ld.HEADR = 0x10000
+ ld.Funcalign = 16
+ if ld.INITTEXT == -1 {
+ ld.INITTEXT = 0x20000
+ }
+ if ld.INITDAT == -1 {
+ ld.INITDAT = 0
+ }
+ if ld.INITRND == -1 {
+ ld.INITRND = 0x10000
+ }
+ }
+
+ if ld.INITDAT != 0 && ld.INITRND != 0 {
+ fmt.Printf("warning: -D0x%x is ignored because of -R0x%x\n", uint64(ld.INITDAT), uint32(ld.INITRND))
+ }
+}
"log"
)
-func gentext() {
+func genplt() {
var s *ld.LSym
var stub *ld.LSym
var pprevtextp **ld.LSym
ld.Ctxt.Arch.ByteOrder.PutUint32(s.P[r.Off+4:], o1)
}
}
+
+}
+
+func genaddmoduledata() {
+ addmoduledata := ld.Linkrlookup(ld.Ctxt, "runtime.addmoduledata", 0)
+ if addmoduledata.Type == obj.STEXT {
+ return
+ }
+ addmoduledata.Reachable = true
+ initfunc := ld.Linklookup(ld.Ctxt, "go.link.addmoduledata", 0)
+ initfunc.Type = obj.STEXT
+ initfunc.Local = true
+ initfunc.Reachable = true
+ o := func(op uint32) {
+ ld.Adduint32(ld.Ctxt, initfunc, op)
+ }
+ // addis r2, r12, .TOC.-func@ha
+ rel := ld.Addrel(initfunc)
+ rel.Off = int32(initfunc.Size)
+ rel.Siz = 8
+ rel.Sym = ld.Linklookup(ld.Ctxt, ".TOC.", 0)
+ rel.Type = obj.R_ADDRPOWER_PCREL
+ o(0x3c4c0000)
+ // addi r2, r2, .TOC.-func@l
+ o(0x38420000)
+ // mflr r31
+ o(0x7c0802a6)
+ // stdu r31, -32(r1)
+ o(0xf801ffe1)
+ // addis r3, r2, local.moduledata@got@ha
+ rel = ld.Addrel(initfunc)
+ rel.Off = int32(initfunc.Size)
+ rel.Siz = 8
+ rel.Sym = ld.Linklookup(ld.Ctxt, "local.moduledata", 0)
+ rel.Type = obj.R_ADDRPOWER_GOT
+ o(0x3c620000)
+ // ld r3, local.moduledata@got@l(r3)
+ o(0xe8630000)
+ // bl runtime.addmoduledata
+ rel = ld.Addrel(initfunc)
+ rel.Off = int32(initfunc.Size)
+ rel.Siz = 4
+ rel.Sym = addmoduledata
+ rel.Type = obj.R_CALLPOWER
+ o(0x48000001)
+ // nop
+ o(0x60000000)
+ // ld r31, 0(r1)
+ o(0xe8010000)
+ // mtlr r31
+ o(0x7c0803a6)
+ // addi r1,r1,32
+ o(0x38210020)
+ // blr
+ o(0x4e800020)
+
+ if ld.Ctxt.Etextp != nil {
+ ld.Ctxt.Etextp.Next = initfunc
+ } else {
+ ld.Ctxt.Textp = initfunc
+ }
+ ld.Ctxt.Etextp = initfunc
+
+ initarray_entry := ld.Linklookup(ld.Ctxt, "go.link.addmoduledatainit", 0)
+ initarray_entry.Reachable = true
+ initarray_entry.Local = true
+ initarray_entry.Type = obj.SINITARR
+ ld.Addaddr(ld.Ctxt, initarray_entry, initfunc)
+}
+
+func gentext() {
+ if ld.DynlinkingGo() {
+ genaddmoduledata()
+ }
+
+ if ld.Linkmode == ld.LinkInternal {
+ genplt()
+ }
}
// Construct a call stub in stub that calls symbol targ via its PLT
}
func elfreloc1(r *ld.Reloc, sectoff int64) int {
- // TODO(minux)
- return -1
+ ld.Thearch.Vput(uint64(sectoff))
+
+ elfsym := r.Xsym.ElfsymForReloc()
+ switch r.Type {
+ default:
+ return -1
+
+ case obj.R_ADDR:
+ switch r.Siz {
+ case 4:
+ ld.Thearch.Vput(ld.R_PPC64_ADDR32 | uint64(elfsym)<<32)
+ case 8:
+ ld.Thearch.Vput(ld.R_PPC64_ADDR64 | uint64(elfsym)<<32)
+ default:
+ return -1
+ }
+
+ case obj.R_POWER_TLS:
+ ld.Thearch.Vput(ld.R_PPC64_TLS | uint64(elfsym)<<32)
+
+ case obj.R_POWER_TLS_LE:
+ ld.Thearch.Vput(ld.R_PPC64_TPREL16 | uint64(elfsym)<<32)
+
+ case obj.R_POWER_TLS_IE:
+ ld.Thearch.Vput(ld.R_PPC64_GOT_TPREL16_HA | uint64(elfsym)<<32)
+ ld.Thearch.Vput(uint64(r.Xadd))
+ ld.Thearch.Vput(uint64(sectoff + 4))
+ ld.Thearch.Vput(ld.R_PPC64_GOT_TPREL16_LO_DS | uint64(elfsym)<<32)
+
+ case obj.R_ADDRPOWER:
+ ld.Thearch.Vput(ld.R_PPC64_ADDR16_HA | uint64(elfsym)<<32)
+ ld.Thearch.Vput(uint64(r.Xadd))
+ ld.Thearch.Vput(uint64(sectoff + 4))
+ ld.Thearch.Vput(ld.R_PPC64_ADDR16_LO | uint64(elfsym)<<32)
+
+ case obj.R_ADDRPOWER_DS:
+ ld.Thearch.Vput(ld.R_PPC64_ADDR16_HA | uint64(elfsym)<<32)
+ ld.Thearch.Vput(uint64(r.Xadd))
+ ld.Thearch.Vput(uint64(sectoff + 4))
+ ld.Thearch.Vput(ld.R_PPC64_ADDR16_LO_DS | uint64(elfsym)<<32)
+
+ case obj.R_ADDRPOWER_GOT:
+ ld.Thearch.Vput(ld.R_PPC64_GOT16_HA | uint64(elfsym)<<32)
+ ld.Thearch.Vput(uint64(r.Xadd))
+ ld.Thearch.Vput(uint64(sectoff + 4))
+ ld.Thearch.Vput(ld.R_PPC64_GOT16_LO_DS | uint64(elfsym)<<32)
+
+ case obj.R_ADDRPOWER_PCREL:
+ ld.Thearch.Vput(ld.R_PPC64_REL16_HA | uint64(elfsym)<<32)
+ ld.Thearch.Vput(uint64(r.Xadd))
+ ld.Thearch.Vput(uint64(sectoff + 4))
+ ld.Thearch.Vput(ld.R_PPC64_REL16_LO | uint64(elfsym)<<32)
+ r.Xadd += 4
+
+ case obj.R_ADDRPOWER_TOCREL:
+ ld.Thearch.Vput(ld.R_PPC64_TOC16_HA | uint64(elfsym)<<32)
+ ld.Thearch.Vput(uint64(r.Xadd))
+ ld.Thearch.Vput(uint64(sectoff + 4))
+ ld.Thearch.Vput(ld.R_PPC64_TOC16_LO | uint64(elfsym)<<32)
+
+ case obj.R_ADDRPOWER_TOCREL_DS:
+ ld.Thearch.Vput(ld.R_PPC64_TOC16_HA | uint64(elfsym)<<32)
+ ld.Thearch.Vput(uint64(r.Xadd))
+ ld.Thearch.Vput(uint64(sectoff + 4))
+ ld.Thearch.Vput(ld.R_PPC64_TOC16_LO_DS | uint64(elfsym)<<32)
+
+ case obj.R_CALLPOWER:
+ if r.Siz != 4 {
+ return -1
+ }
+ ld.Thearch.Vput(ld.R_PPC64_REL24 | uint64(elfsym)<<32)
+
+ }
+ ld.Thearch.Vput(uint64(r.Xadd))
+
+ return 0
}
func elfsetupplt() {
return toc.Value
}
+func archrelocaddr(r *ld.Reloc, s *ld.LSym, val *int64) int {
+ var o1, o2 uint32
+ if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
+ o1 = uint32(*val >> 32)
+ o2 = uint32(*val)
+ } else {
+ o1 = uint32(*val)
+ o2 = uint32(*val >> 32)
+ }
+
+ // We are spreading a 31-bit address across two instructions, putting the
+ // high (adjusted) part in the low 16 bits of the first instruction and the
+ // low part in the low 16 bits of the second instruction, or, in the DS case,
+ // bits 15-2 (inclusive) of the address into bits 15-2 of the second
+ // instruction (it is an error in this case if the low 2 bits of the address
+ // are non-zero).
+
+ t := ld.Symaddr(r.Sym) + r.Add
+ if t < 0 || t >= 1<<31 {
+ ld.Ctxt.Diag("relocation for %s is too big (>=2G): %d", s.Name, ld.Symaddr(r.Sym))
+ }
+ if t&0x8000 != 0 {
+ t += 0x10000
+ }
+
+ switch r.Type {
+ case obj.R_ADDRPOWER:
+ o1 |= (uint32(t) >> 16) & 0xffff
+ o2 |= uint32(t) & 0xffff
+
+ case obj.R_ADDRPOWER_DS:
+ o1 |= (uint32(t) >> 16) & 0xffff
+ if t&3 != 0 {
+ ld.Ctxt.Diag("bad DS reloc for %s: %d", s.Name, ld.Symaddr(r.Sym))
+ }
+ o2 |= uint32(t) & 0xfffc
+
+ default:
+ return -1
+ }
+
+ if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
+ *val = int64(o1)<<32 | int64(o2)
+ } else {
+ *val = int64(o2)<<32 | int64(o1)
+ }
+ return 0
+}
+
func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
if ld.Linkmode == ld.LinkExternal {
- // TODO(minux): translate R_ADDRPOWER and R_CALLPOWER into standard ELF relocations.
- // R_ADDRPOWER corresponds to R_PPC_ADDR16_HA and R_PPC_ADDR16_LO.
- // R_CALLPOWER corresponds to R_PPC_REL24.
- return -1
+ switch r.Type {
+ default:
+ return -1
+
+ case obj.R_POWER_TLS, obj.R_POWER_TLS_LE, obj.R_POWER_TLS_IE:
+ r.Done = 0
+ // check Outer is nil, Type is TLSBSS?
+ r.Xadd = r.Add
+ r.Xsym = r.Sym
+ return 0
+
+ case obj.R_ADDRPOWER,
+ obj.R_ADDRPOWER_DS,
+ obj.R_ADDRPOWER_TOCREL,
+ obj.R_ADDRPOWER_TOCREL_DS,
+ obj.R_ADDRPOWER_GOT,
+ obj.R_ADDRPOWER_PCREL:
+ r.Done = 0
+
+ // set up addend for eventual relocation via outer symbol.
+ rs := r.Sym
+ r.Xadd = r.Add
+ for rs.Outer != nil {
+ r.Xadd += ld.Symaddr(rs) - ld.Symaddr(rs.Outer)
+ rs = rs.Outer
+ }
+
+ if rs.Type != obj.SHOSTOBJ && rs.Type != obj.SDYNIMPORT && rs.Sect == nil {
+ ld.Diag("missing section for %s", rs.Name)
+ }
+ r.Xsym = rs
+
+ return 0
+
+ case obj.R_CALLPOWER:
+ r.Done = 0
+ r.Xsym = r.Sym
+ r.Xadd = r.Add
+ return 0
+ }
}
switch r.Type {
*val = ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ld.Linklookup(ld.Ctxt, ".got", 0))
return 0
- case obj.R_ADDRPOWER:
- // r->add is two ppc64 instructions holding an immediate 32-bit constant.
- // We want to add r->sym's address to that constant.
- // The encoding of the immediate x<<16 + y,
- // where x is the low 16 bits of the first instruction and y is the low 16
- // bits of the second. Both x and y are signed (int16, not uint16).
- o1 := uint32(r.Add >> 32)
- o2 := uint32(r.Add)
- t := ld.Symaddr(r.Sym)
- if t < 0 {
- ld.Ctxt.Diag("relocation for %s is too big (>=2G): %d", s.Name, ld.Symaddr(r.Sym))
- }
-
- t += int64((o1&0xffff)<<16 + uint32(int32(o2)<<16>>16))
- if t&0x8000 != 0 {
- t += 0x10000
- }
- o1 = o1&0xffff0000 | (uint32(t)>>16)&0xffff
- o2 = o2&0xffff0000 | uint32(t)&0xffff
-
- // when laid out, the instruction order must always be o1, o2.
- if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
- *val = int64(o1)<<32 | int64(o2)
- } else {
- *val = int64(o2)<<32 | int64(o1)
- }
- return 0
+ case obj.R_ADDRPOWER, obj.R_ADDRPOWER_DS:
+ return archrelocaddr(r, s, val)
case obj.R_CALLPOWER:
// Bits 6 through 29 = (S + A - P) >> 2
- var o1 uint32
- if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
- o1 = ld.Be32(s.P[r.Off:])
- } else {
- o1 = ld.Le32(s.P[r.Off:])
- }
t := ld.Symaddr(r.Sym) + r.Add - (s.Value + int64(r.Off))
if t&3 != 0 {
ld.Ctxt.Diag("relocation for %s+%d is too big: %d", r.Sym.Name, r.Off, t)
}
- *val = int64(o1&0xfc000003 | uint32(t)&^0xfc000003)
+ *val |= int64(uint32(t) &^ 0xfc000003)
return 0
case obj.R_POWER_TOC: // S + A - .TOC.
*val = ld.Symaddr(r.Sym) + r.Add - symtoc(s)
return 0
+
+ case obj.R_POWER_TLS_LE:
+ // The thread pointer points 0x7000 bytes after the start of the the
+ // thread local storage area as documented in section "3.7.2 TLS
+ // Runtime Handling" of "Power Architecture 64-Bit ELF V2 ABI
+ // Specification".
+ v := r.Sym.Value - 0x7000
+ if int64(int16(v)) != v {
+ ld.Diag("TLS offset out of range %d", v)
+ }
+ *val = (*val &^ 0xffff) | (v & 0xffff)
+ return 0
}
return -1
r.Siz = 8
r.Type = obj.R_ADDRPOWER
- // addis r11,0,.plt@ha; addi r11,r11,.plt@l
- r.Add = 0x3d600000<<32 | 0x396b0000
-
- glink.Size += 8
+ ld.Adduint32(ld.Ctxt, glink, 0x3d600000) // addis r11,0,.plt@ha
+ ld.Adduint32(ld.Ctxt, glink, 0x396b0000) // addi r11,r11,.plt@l
// Load r12 = dynamic resolver address and r11 = DSO
// identifier from the first two doublewords of the PLT.
ld.Linkmode = ld.LinkInternal
}
+ switch ld.Buildmode {
+ case ld.BuildmodePIE, ld.BuildmodeShared:
+ ld.Linkmode = ld.LinkExternal
+ }
+
+ if ld.Linkshared {
+ ld.Linkmode = ld.LinkExternal
+ }
+
+ if ld.Linkmode == ld.LinkExternal {
+ toc := ld.Linklookup(ld.Ctxt, ".TOC.", 0)
+ toc.Type = obj.SDYNIMPORT
+ }
+
switch ld.HEADTYPE {
default:
if ld.Linkmode == ld.LinkAuto {
if ld.Linkmode == ld.LinkExternal && obj.Getgoextlinkenabled() != "1" {
log.Fatalf("cannot use -linkmode=external with -H %s", ld.Headstr(int(ld.HEADTYPE)))
}
+
+ case obj.Hlinux:
+ break
}
switch ld.HEADTYPE {
return
- case 256 + ld.R_386_GOT32:
+ case 256 + ld.R_386_GOT32, 256 + ld.R_386_GOT32X:
if targ.Type != obj.SDYNIMPORT {
// have symbol
if r.Off >= 2 && s.P[r.Off-2] == 0x8b {
func elfreloc1(r *ld.Reloc, sectoff int64) int {
ld.Thearch.Lput(uint32(sectoff))
- elfsym := r.Xsym.Elfsym
+ elfsym := r.Xsym.ElfsymForReloc()
switch r.Type {
default:
return -1
"cmd/link/internal/amd64"
"cmd/link/internal/arm"
"cmd/link/internal/arm64"
+ "cmd/link/internal/mips64"
"cmd/link/internal/ppc64"
"cmd/link/internal/x86"
"fmt"
arm.Main()
case "arm64":
arm64.Main()
+ case "mips64", "mips64le":
+ mips64.Main()
case "ppc64", "ppc64le":
ppc64.Main()
}
return false
}
}
+ default:
+ return false
}
}
return true
_ = i
}
if f != nil {
+ x := one() // ERROR "declaration of x shadows declaration at testdata/shadow.go:14"
var _, err = f.Read(buf) // ERROR "declaration of err shadows declaration at testdata/shadow.go:13"
- if err != nil {
+ if x == 1 && err != nil {
return err
}
}
_, _ = err, x
return
}
+
+func one() int {
+ return 1
+}
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// No testdata on Android.
-
-// +build !android
-
package main_test
import (
"bytes"
"flag"
"fmt"
+ "internal/testenv"
"os"
"os/exec"
"path/filepath"
os.Exit(result)
}
-func CanRun() bool {
+func MustHavePerl(t *testing.T) {
switch runtime.GOOS {
case "plan9", "windows":
- // No Perl installed, can't run errcheck.
- return false
- case "nacl":
- // Minimal and problematic file system.
- return false
+ t.Skipf("skipping test: perl not available on %s", runtime.GOOS)
}
- return true
}
var (
if built {
return
}
- if !CanRun() || failed {
+ testenv.MustHaveGoBuild(t)
+ MustHavePerl(t)
+ if failed {
t.Skip("cannot run on this environment")
- return
}
cmd := exec.Command("go", "build", "-o", binary)
output, err := cmd.CombinedOutput()
// returned by Read as tentative until they receive the io.EOF
// marking the end of the data.
type Reader struct {
- Header
+ Header // valid after NewReader or Reader.Reset
r flate.Reader
decompressor io.ReadCloser
digest hash.Hash32
// NewReader creates a new Reader reading the given reader.
// If r does not also implement io.ByteReader,
// the decompressor may read more data than necessary from r.
+//
// It is the caller's responsibility to call Close on the Reader when done.
+//
+// The Reader.Header fields will be valid in the Reader returned.
func NewReader(r io.Reader) (*Reader, error) {
z := new(Reader)
z.r = makeReader(r)
// A Writer is an io.WriteCloser.
// Writes to a Writer are compressed and written to w.
type Writer struct {
- Header
+ Header // written at first call to Write, Flush, or Close
w io.Writer
level int
wroteHeader bool
// The following functions are defined in gcm_amd64.s.
func hasGCMAsm() bool
+
+//go:noescape
func aesEncBlock(dst, src *[16]byte, ks []uint32)
+
+//go:noescape
func gcmAesInit(productTable *[256]byte, ks []uint32)
+
+//go:noescape
func gcmAesData(productTable *[256]byte, data []byte, T *[16]byte)
+
+//go:noescape
func gcmAesEnc(productTable *[256]byte, dst, src []byte, ctr, T *[16]byte, ks []uint32)
+
+//go:noescape
func gcmAesDec(productTable *[256]byte, dst, src []byte, ctr, T *[16]byte, ks []uint32)
+
+//go:noescape
func gcmAesFinish(productTable *[256]byte, tagMask, T *[16]byte, pLen, dLen uint64)
const (
func (x *ctr) refill() {
remain := len(x.out) - x.outUsed
- if remain > x.outUsed {
- return
- }
copy(x.out, x.out[x.outUsed:])
x.out = x.out[:cap(x.out)]
bs := x.b.BlockSize()
- for remain < len(x.out)-bs {
+ for remain <= len(x.out)-bs {
x.b.Encrypt(x.out[remain:], x.ctr)
remain += bs
--- /dev/null
+// Copyright 2015 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 cipher_test
+
+import (
+ "bytes"
+ "crypto/cipher"
+ "testing"
+)
+
+type noopBlock int
+
+func (b noopBlock) BlockSize() int { return int(b) }
+func (noopBlock) Encrypt(dst, src []byte) { copy(dst, src) }
+func (noopBlock) Decrypt(dst, src []byte) { copy(dst, src) }
+
+func inc(b []byte) {
+ for i := len(b) - 1; i >= 0; i++ {
+ b[i]++
+ if b[i] != 0 {
+ break
+ }
+ }
+}
+
+func xor(a, b []byte) {
+ for i := range a {
+ a[i] ^= b[i]
+ }
+}
+
+func TestCTR(t *testing.T) {
+ for size := 64; size <= 1024; size *= 2 {
+ iv := make([]byte, size)
+ ctr := cipher.NewCTR(noopBlock(size), iv)
+ src := make([]byte, 1024)
+ for i := range src {
+ src[i] = 0xff
+ }
+ want := make([]byte, 1024)
+ copy(want, src)
+ counter := make([]byte, size)
+ for i := 1; i < len(want)/size; i++ {
+ inc(counter)
+ xor(want[i*size:(i+1)*size], counter)
+ }
+ dst := make([]byte, 1024)
+ ctr.XORKeyStream(dst, src)
+ if !bytes.Equal(dst, want) {
+ t.Errorf("for size %d\nhave %x\nwant %x", size, dst, want)
+ }
+ }
+}
"math/big"
)
+// A invertible implements fast inverse mod Curve.Params().N
+type invertible interface {
+ // Inverse returns the inverse of k in GF(P)
+ Inverse(k *big.Int) *big.Int
+}
+
+// combinedMult implements fast multiplication S1*g + S2*p (g - generator, p - arbitrary point)
+type combinedMult interface {
+ CombinedMult(bigX, bigY *big.Int, baseScalar, scalar []byte) (x, y *big.Int)
+}
+
const (
aesIV = "IV for ECDSA CTR"
)
return
}
- kInv = fermatInverse(k, N)
+ if in, ok := priv.Curve.(invertible); ok {
+ kInv = in.Inverse(k)
+ } else {
+ kInv = fermatInverse(k, N)
+ }
+
r, _ = priv.Curve.ScalarBaseMult(k.Bytes())
r.Mod(r, N)
if r.Sign() != 0 {
return false
}
e := hashToInt(hash, c)
- w := new(big.Int).ModInverse(s, N)
+
+ var w *big.Int
+ if in, ok := c.(invertible); ok {
+ w = in.Inverse(s)
+ } else {
+ w = new(big.Int).ModInverse(s, N)
+ }
u1 := e.Mul(e, w)
u1.Mod(u1, N)
u2 := w.Mul(r, w)
u2.Mod(u2, N)
- x1, y1 := c.ScalarBaseMult(u1.Bytes())
- x2, y2 := c.ScalarMult(pub.X, pub.Y, u2.Bytes())
- x, y := c.Add(x1, y1, x2, y2)
+ // Check if implements S1*g + S2*p
+ var x, y *big.Int
+ if opt, ok := c.(combinedMult); ok {
+ x, y = opt.CombinedMult(pub.X, pub.Y, u1.Bytes(), u2.Bytes())
+ } else {
+ x1, y1 := c.ScalarBaseMult(u1.Bytes())
+ x2, y2 := c.ScalarMult(pub.X, pub.Y, u2.Bytes())
+ x, y = c.Add(x1, y1, x2, y2)
+ }
+
if x.Sign() == 0 && y.Sign() == 0 {
return false
}
testKeyGeneration(t, elliptic.P521(), "p521")
}
+func BenchmarkSignP256(b *testing.B) {
+ b.ResetTimer()
+ p256 := elliptic.P256()
+ hashed := []byte("testing")
+ priv, _ := GenerateKey(p256, rand.Reader)
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, _, _ = Sign(rand.Reader, priv, hashed)
+ }
+}
+
+func BenchmarkVerifyP256(b *testing.B) {
+ b.ResetTimer()
+ p256 := elliptic.P256()
+ hashed := []byte("testing")
+ priv, _ := GenerateKey(p256, rand.Reader)
+ r, s, _ := Sign(rand.Reader, priv, hashed)
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ Verify(&priv.PublicKey, hashed, r, s)
+ }
+}
+
+func BenchmarkKeyGeneration(b *testing.B) {
+ b.ResetTimer()
+ p256 := elliptic.P256()
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ GenerateKey(p256, rand.Reader)
+ }
+}
+
func testSignAndVerify(t *testing.T, c elliptic.Curve, tag string) {
priv, _ := GenerateKey(c, rand.Reader)
}
}
+func BenchmarkScalarMultP256(b *testing.B) {
+ b.ResetTimer()
+ p256 := P256()
+ _, x, y, _ := GenerateKey(p256, rand.Reader)
+ priv, _, _, _ := GenerateKey(p256, rand.Reader)
+
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ p256.ScalarMult(x, y, priv)
+ }
+}
+
func TestMarshal(t *testing.T) {
p224 := P224()
_, x, y, err := GenerateKey(p224, rand.Reader)
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build !amd64
+
package elliptic
// This file contains a constant-time, 32-bit implementation of P256.
--- /dev/null
+// Copyright 2015 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.
+
+// This file contains the Go wrapper for the constant-time, 64-bit assembly
+// implementation of P256. The optimizations performed here are described in
+// detail in:
+// S.Gueron and V.Krasnov, "Fast prime field elliptic-curve cryptography with
+// 256-bit primes"
+// http://link.springer.com/article/10.1007%2Fs13389-014-0090-x
+// https://eprint.iacr.org/2013/816.pdf
+
+// +build amd64
+
+package elliptic
+
+import (
+ "math/big"
+ "sync"
+)
+
+type (
+ p256Curve struct {
+ *CurveParams
+ }
+
+ p256Point struct {
+ xyz [12]uint64
+ }
+)
+
+var (
+ p256 p256Curve
+ p256Precomputed *[37][64 * 8]uint64
+ precomputeOnce sync.Once
+)
+
+func initP256() {
+ // See FIPS 186-3, section D.2.3
+ p256.CurveParams = &CurveParams{Name: "P-256"}
+ p256.P, _ = new(big.Int).SetString("115792089210356248762697446949407573530086143415290314195533631308867097853951", 10)
+ p256.N, _ = new(big.Int).SetString("115792089210356248762697446949407573529996955224135760342422259061068512044369", 10)
+ p256.B, _ = new(big.Int).SetString("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16)
+ p256.Gx, _ = new(big.Int).SetString("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 16)
+ p256.Gy, _ = new(big.Int).SetString("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", 16)
+ p256.BitSize = 256
+}
+
+func (curve p256Curve) Params() *CurveParams {
+ return curve.CurveParams
+}
+
+// Functions implemented in p256_asm_amd64.s
+// Montgomery multiplication modulo P256
+func p256Mul(res, in1, in2 []uint64)
+
+// Montgomery square modulo P256
+func p256Sqr(res, in []uint64)
+
+// Montgomery multiplication by 1
+func p256FromMont(res, in []uint64)
+
+// iff cond == 1 val <- -val
+func p256NegCond(val []uint64, cond int)
+
+// if cond == 0 res <- b; else res <- a
+func p256MovCond(res, a, b []uint64, cond int)
+
+// Endianess swap
+func p256BigToLittle(res []uint64, in []byte)
+func p256LittleToBig(res []byte, in []uint64)
+
+// Constant time table access
+func p256Select(point, table []uint64, idx int)
+func p256SelectBase(point, table []uint64, idx int)
+
+// Montgomery multiplication modulo Ord(G)
+func p256OrdMul(res, in1, in2 []uint64)
+
+// Montgomery square modulo Ord(G), repeated n times
+func p256OrdSqr(res, in []uint64, n int)
+
+// Point add with in2 being affine point
+// If sign == 1 -> in2 = -in2
+// If sel == 0 -> res = in1
+// if zero == 0 -> res = in2
+func p256PointAddAffineAsm(res, in1, in2 []uint64, sign, sel, zero int)
+
+// Point add
+func p256PointAddAsm(res, in1, in2 []uint64)
+
+// Point double
+func p256PointDoubleAsm(res, in []uint64)
+
+func (curve p256Curve) Inverse(k *big.Int) *big.Int {
+ if k.Cmp(p256.N) >= 0 {
+ // This should never happen.
+ reducedK := new(big.Int).Mod(k, p256.N)
+ k = reducedK
+ }
+
+ // table will store precomputed powers of x. The four words at index
+ // 4×i store x^(i+1).
+ var table [4 * 15]uint64
+
+ x := make([]uint64, 4)
+ fromBig(x[:], k)
+ // This code operates in the Montgomery domain where R = 2^256 mod n
+ // and n is the order of the scalar field. (See initP256 for the
+ // value.) Elements in the Montgomery domain take the form a×R and
+ // multiplication of x and y in the calculates (x × y × R^-1) mod n. RR
+ // is R×R mod n thus the Montgomery multiplication x and RR gives x×R,
+ // i.e. converts x into the Montgomery domain.
+ RR := []uint64{0x83244c95be79eea2, 0x4699799c49bd6fa6, 0x2845b2392b6bec59, 0x66e12d94f3d95620}
+ p256OrdMul(table[:4], x, RR)
+
+ // Prepare the table, no need in constant time access, because the
+ // power is not a secret. (Entry 0 is never used.)
+ for i := 2; i < 16; i += 2 {
+ p256OrdSqr(table[4*(i-1):], table[4*((i/2)-1):], 1)
+ p256OrdMul(table[4*i:], table[4*(i-1):], table[:4])
+ }
+
+ x[0] = table[4*14+0] // f
+ x[1] = table[4*14+1]
+ x[2] = table[4*14+2]
+ x[3] = table[4*14+3]
+
+ p256OrdSqr(x, x, 4)
+ p256OrdMul(x, x, table[4*14:4*14+4]) // ff
+ t := make([]uint64, 4, 4)
+ t[0] = x[0]
+ t[1] = x[1]
+ t[2] = x[2]
+ t[3] = x[3]
+
+ p256OrdSqr(x, x, 8)
+ p256OrdMul(x, x, t) // ffff
+ t[0] = x[0]
+ t[1] = x[1]
+ t[2] = x[2]
+ t[3] = x[3]
+
+ p256OrdSqr(x, x, 16)
+ p256OrdMul(x, x, t) // ffffffff
+ t[0] = x[0]
+ t[1] = x[1]
+ t[2] = x[2]
+ t[3] = x[3]
+
+ p256OrdSqr(x, x, 64) // ffffffff0000000000000000
+ p256OrdMul(x, x, t) // ffffffff00000000ffffffff
+ p256OrdSqr(x, x, 32) // ffffffff00000000ffffffff00000000
+ p256OrdMul(x, x, t) // ffffffff00000000ffffffffffffffff
+
+ // Remaining 32 windows
+ expLo := [32]byte{0xb, 0xc, 0xe, 0x6, 0xf, 0xa, 0xa, 0xd, 0xa, 0x7, 0x1, 0x7, 0x9, 0xe, 0x8, 0x4, 0xf, 0x3, 0xb, 0x9, 0xc, 0xa, 0xc, 0x2, 0xf, 0xc, 0x6, 0x3, 0x2, 0x5, 0x4, 0xf}
+ for i := 0; i < 32; i++ {
+ p256OrdSqr(x, x, 4)
+ p256OrdMul(x, x, table[4*(expLo[i]-1):])
+ }
+
+ // Multiplying by one in the Montgomery domain converts a Montgomery
+ // value out of the domain.
+ one := []uint64{1, 0, 0, 0}
+ p256OrdMul(x, x, one)
+
+ xOut := make([]byte, 32)
+ p256LittleToBig(xOut, x)
+ return new(big.Int).SetBytes(xOut)
+}
+
+// fromBig converts a *big.Int into a format used by this code.
+func fromBig(out []uint64, big *big.Int) {
+ for i := range out {
+ out[i] = 0
+ }
+
+ for i, v := range big.Bits() {
+ out[i] = uint64(v)
+ }
+}
+
+// p256GetScalar endian-swaps the big-endian scalar value from in and writes it
+// to out. If the scalar is equal or greater than the order of the group, it's
+// reduced modulo that order.
+func p256GetScalar(out []uint64, in []byte) {
+ n := new(big.Int).SetBytes(in)
+
+ if n.Cmp(p256.N) >= 0 {
+ n.Mod(n, p256.N)
+ }
+ fromBig(out, n)
+}
+
+// p256Mul operates in a Montgomery domain with R = 2^256 mod p, where p is the
+// underlying field of the curve. (See initP256 for the value.) Thus rr here is
+// R×R mod p. See comment in Inverse about how this is used.
+var rr = []uint64{0x0000000000000003, 0xfffffffbffffffff, 0xfffffffffffffffe, 0x00000004fffffffd}
+
+func maybeReduceModP(in *big.Int) *big.Int {
+ if in.Cmp(p256.P) < 0 {
+ return in
+ }
+ return new(big.Int).Mod(in, p256.P)
+}
+
+func (curve p256Curve) CombinedMult(bigX, bigY *big.Int, baseScalar, scalar []byte) (x, y *big.Int) {
+ scalarReversed := make([]uint64, 4)
+ var r1, r2 p256Point
+ p256GetScalar(scalarReversed, baseScalar)
+ r1.p256BaseMult(scalarReversed)
+
+ p256GetScalar(scalarReversed, scalar)
+ fromBig(r2.xyz[0:4], maybeReduceModP(bigX))
+ fromBig(r2.xyz[4:8], maybeReduceModP(bigY))
+ p256Mul(r2.xyz[0:4], r2.xyz[0:4], rr[:])
+ p256Mul(r2.xyz[4:8], r2.xyz[4:8], rr[:])
+
+ // This sets r2's Z value to 1, in the Montgomery domain.
+ r2.xyz[8] = 0x0000000000000001
+ r2.xyz[9] = 0xffffffff00000000
+ r2.xyz[10] = 0xffffffffffffffff
+ r2.xyz[11] = 0x00000000fffffffe
+
+ r2.p256ScalarMult(scalarReversed)
+ p256PointAddAsm(r1.xyz[:], r1.xyz[:], r2.xyz[:])
+ return r1.p256PointToAffine()
+}
+
+func (curve p256Curve) ScalarBaseMult(scalar []byte) (x, y *big.Int) {
+ scalarReversed := make([]uint64, 4)
+ p256GetScalar(scalarReversed, scalar)
+
+ var r p256Point
+ r.p256BaseMult(scalarReversed)
+ return r.p256PointToAffine()
+}
+
+func (curve p256Curve) ScalarMult(bigX, bigY *big.Int, scalar []byte) (x, y *big.Int) {
+ scalarReversed := make([]uint64, 4)
+ p256GetScalar(scalarReversed, scalar)
+
+ var r p256Point
+ fromBig(r.xyz[0:4], maybeReduceModP(bigX))
+ fromBig(r.xyz[4:8], maybeReduceModP(bigY))
+ p256Mul(r.xyz[0:4], r.xyz[0:4], rr[:])
+ p256Mul(r.xyz[4:8], r.xyz[4:8], rr[:])
+ // This sets r2's Z value to 1, in the Montgomery domain.
+ r.xyz[8] = 0x0000000000000001
+ r.xyz[9] = 0xffffffff00000000
+ r.xyz[10] = 0xffffffffffffffff
+ r.xyz[11] = 0x00000000fffffffe
+
+ r.p256ScalarMult(scalarReversed)
+ return r.p256PointToAffine()
+}
+
+func (p *p256Point) p256PointToAffine() (x, y *big.Int) {
+ zInv := make([]uint64, 4)
+ zInvSq := make([]uint64, 4)
+ p256Inverse(zInv, p.xyz[8:12])
+ p256Sqr(zInvSq, zInv)
+ p256Mul(zInv, zInv, zInvSq)
+
+ p256Mul(zInvSq, p.xyz[0:4], zInvSq)
+ p256Mul(zInv, p.xyz[4:8], zInv)
+
+ p256FromMont(zInvSq, zInvSq)
+ p256FromMont(zInv, zInv)
+
+ xOut := make([]byte, 32)
+ yOut := make([]byte, 32)
+ p256LittleToBig(xOut, zInvSq)
+ p256LittleToBig(yOut, zInv)
+
+ return new(big.Int).SetBytes(xOut), new(big.Int).SetBytes(yOut)
+}
+
+// p256Inverse sets out to in^-1 mod p.
+func p256Inverse(out, in []uint64) {
+ var stack [6 * 4]uint64
+ p2 := stack[4*0 : 4*0+4]
+ p4 := stack[4*1 : 4*1+4]
+ p8 := stack[4*2 : 4*2+4]
+ p16 := stack[4*3 : 4*3+4]
+ p32 := stack[4*4 : 4*4+4]
+
+ p256Sqr(out, in)
+ p256Mul(p2, out, in) // 3*p
+
+ p256Sqr(out, p2)
+ p256Sqr(out, out)
+ p256Mul(p4, out, p2) // f*p
+
+ p256Sqr(out, p4)
+ p256Sqr(out, out)
+ p256Sqr(out, out)
+ p256Sqr(out, out)
+ p256Mul(p8, out, p4) // ff*p
+
+ p256Sqr(out, p8)
+
+ for i := 0; i < 7; i++ {
+ p256Sqr(out, out)
+ }
+ p256Mul(p16, out, p8) // ffff*p
+
+ p256Sqr(out, p16)
+ for i := 0; i < 15; i++ {
+ p256Sqr(out, out)
+ }
+ p256Mul(p32, out, p16) // ffffffff*p
+
+ p256Sqr(out, p32)
+
+ for i := 0; i < 31; i++ {
+ p256Sqr(out, out)
+ }
+ p256Mul(out, out, in)
+
+ for i := 0; i < 32*4; i++ {
+ p256Sqr(out, out)
+ }
+ p256Mul(out, out, p32)
+
+ for i := 0; i < 32; i++ {
+ p256Sqr(out, out)
+ }
+ p256Mul(out, out, p32)
+
+ for i := 0; i < 16; i++ {
+ p256Sqr(out, out)
+ }
+ p256Mul(out, out, p16)
+
+ for i := 0; i < 8; i++ {
+ p256Sqr(out, out)
+ }
+ p256Mul(out, out, p8)
+
+ p256Sqr(out, out)
+ p256Sqr(out, out)
+ p256Sqr(out, out)
+ p256Sqr(out, out)
+ p256Mul(out, out, p4)
+
+ p256Sqr(out, out)
+ p256Sqr(out, out)
+ p256Mul(out, out, p2)
+
+ p256Sqr(out, out)
+ p256Sqr(out, out)
+ p256Mul(out, out, in)
+}
+
+func (p *p256Point) p256StorePoint(r *[16 * 4 * 3]uint64, index int) {
+ copy(r[index*12:], p.xyz[:])
+}
+
+func boothW5(in uint) (int, int) {
+ var s uint = ^((in >> 5) - 1)
+ var d uint = (1 << 6) - in - 1
+ d = (d & s) | (in & (^s))
+ d = (d >> 1) + (d & 1)
+ return int(d), int(s & 1)
+}
+
+func boothW7(in uint) (int, int) {
+ var s uint = ^((in >> 7) - 1)
+ var d uint = (1 << 8) - in - 1
+ d = (d & s) | (in & (^s))
+ d = (d >> 1) + (d & 1)
+ return int(d), int(s & 1)
+}
+
+func initTable() {
+ p256Precomputed = new([37][64 * 8]uint64)
+
+ basePoint := []uint64{
+ 0x79e730d418a9143c, 0x75ba95fc5fedb601, 0x79fb732b77622510, 0x18905f76a53755c6,
+ 0xddf25357ce95560a, 0x8b4ab8e4ba19e45c, 0xd2e88688dd21f325, 0x8571ff1825885d85,
+ 0x0000000000000001, 0xffffffff00000000, 0xffffffffffffffff, 0x00000000fffffffe,
+ }
+ t1 := make([]uint64, 12)
+ t2 := make([]uint64, 12)
+ copy(t2, basePoint)
+
+ zInv := make([]uint64, 4)
+ zInvSq := make([]uint64, 4)
+ for j := 0; j < 64; j++ {
+ copy(t1, t2)
+ for i := 0; i < 37; i++ {
+ // The window size is 7 so we need to double 7 times.
+ if i != 0 {
+ for k := 0; k < 7; k++ {
+ p256PointDoubleAsm(t1, t1)
+ }
+ }
+ // Convert the point to affine form. (Its values are
+ // still in Montgomery form however.)
+ p256Inverse(zInv, t1[8:12])
+ p256Sqr(zInvSq, zInv)
+ p256Mul(zInv, zInv, zInvSq)
+
+ p256Mul(t1[:4], t1[:4], zInvSq)
+ p256Mul(t1[4:8], t1[4:8], zInv)
+
+ copy(t1[8:12], basePoint[8:12])
+ // Update the table entry
+ copy(p256Precomputed[i][j*8:], t1[:8])
+ }
+ if j == 0 {
+ p256PointDoubleAsm(t2, basePoint)
+ } else {
+ p256PointAddAsm(t2, t2, basePoint)
+ }
+ }
+}
+
+func (p *p256Point) p256BaseMult(scalar []uint64) {
+ precomputeOnce.Do(initTable)
+
+ wvalue := (scalar[0] << 1) & 0xff
+ sel, sign := boothW7(uint(wvalue))
+ p256SelectBase(p.xyz[0:8], p256Precomputed[0][0:], sel)
+ p256NegCond(p.xyz[4:8], sign)
+
+ // (This is one, in the Montgomery domain.)
+ p.xyz[8] = 0x0000000000000001
+ p.xyz[9] = 0xffffffff00000000
+ p.xyz[10] = 0xffffffffffffffff
+ p.xyz[11] = 0x00000000fffffffe
+
+ var t0 p256Point
+ // (This is one, in the Montgomery domain.)
+ t0.xyz[8] = 0x0000000000000001
+ t0.xyz[9] = 0xffffffff00000000
+ t0.xyz[10] = 0xffffffffffffffff
+ t0.xyz[11] = 0x00000000fffffffe
+
+ index := uint(6)
+ zero := sel
+
+ for i := 1; i < 37; i++ {
+ if index < 192 {
+ wvalue = ((scalar[index/64] >> (index % 64)) + (scalar[index/64+1] << (64 - (index % 64)))) & 0xff
+ } else {
+ wvalue = (scalar[index/64] >> (index % 64)) & 0xff
+ }
+ index += 7
+ sel, sign = boothW7(uint(wvalue))
+ p256SelectBase(t0.xyz[0:8], p256Precomputed[i][0:], sel)
+ p256PointAddAffineAsm(p.xyz[0:12], p.xyz[0:12], t0.xyz[0:8], sign, sel, zero)
+ zero |= sel
+ }
+}
+
+func (p *p256Point) p256ScalarMult(scalar []uint64) {
+ // precomp is a table of precomputed points that stores powers of p
+ // from p^1 to p^16.
+ var precomp [16 * 4 * 3]uint64
+ var t0, t1, t2, t3 p256Point
+
+ // Prepare the table
+ p.p256StorePoint(&precomp, 0) // 1
+
+ p256PointDoubleAsm(t0.xyz[:], p.xyz[:])
+ p256PointDoubleAsm(t1.xyz[:], t0.xyz[:])
+ p256PointDoubleAsm(t2.xyz[:], t1.xyz[:])
+ p256PointDoubleAsm(t3.xyz[:], t2.xyz[:])
+ t0.p256StorePoint(&precomp, 1) // 2
+ t1.p256StorePoint(&precomp, 3) // 4
+ t2.p256StorePoint(&precomp, 7) // 8
+ t3.p256StorePoint(&precomp, 15) // 16
+
+ p256PointAddAsm(t0.xyz[:], t0.xyz[:], p.xyz[:])
+ p256PointAddAsm(t1.xyz[:], t1.xyz[:], p.xyz[:])
+ p256PointAddAsm(t2.xyz[:], t2.xyz[:], p.xyz[:])
+ t0.p256StorePoint(&precomp, 2) // 3
+ t1.p256StorePoint(&precomp, 4) // 5
+ t2.p256StorePoint(&precomp, 8) // 9
+
+ p256PointDoubleAsm(t0.xyz[:], t0.xyz[:])
+ p256PointDoubleAsm(t1.xyz[:], t1.xyz[:])
+ t0.p256StorePoint(&precomp, 5) // 6
+ t1.p256StorePoint(&precomp, 9) // 10
+
+ p256PointAddAsm(t2.xyz[:], t0.xyz[:], p.xyz[:])
+ p256PointAddAsm(t1.xyz[:], t1.xyz[:], p.xyz[:])
+ t2.p256StorePoint(&precomp, 6) // 7
+ t1.p256StorePoint(&precomp, 10) // 11
+
+ p256PointDoubleAsm(t0.xyz[:], t0.xyz[:])
+ p256PointDoubleAsm(t2.xyz[:], t2.xyz[:])
+ t0.p256StorePoint(&precomp, 11) // 12
+ t2.p256StorePoint(&precomp, 13) // 14
+
+ p256PointAddAsm(t0.xyz[:], t0.xyz[:], p.xyz[:])
+ p256PointAddAsm(t2.xyz[:], t2.xyz[:], p.xyz[:])
+ t0.p256StorePoint(&precomp, 12) // 13
+ t2.p256StorePoint(&precomp, 14) // 15
+
+ // Start scanning the window from top bit
+ index := uint(254)
+ var sel, sign int
+
+ wvalue := (scalar[index/64] >> (index % 64)) & 0x3f
+ sel, _ = boothW5(uint(wvalue))
+
+ p256Select(p.xyz[0:12], precomp[0:], sel)
+ zero := sel
+
+ for index > 4 {
+ index -= 5
+ p256PointDoubleAsm(p.xyz[:], p.xyz[:])
+ p256PointDoubleAsm(p.xyz[:], p.xyz[:])
+ p256PointDoubleAsm(p.xyz[:], p.xyz[:])
+ p256PointDoubleAsm(p.xyz[:], p.xyz[:])
+ p256PointDoubleAsm(p.xyz[:], p.xyz[:])
+
+ if index < 192 {
+ wvalue = ((scalar[index/64] >> (index % 64)) + (scalar[index/64+1] << (64 - (index % 64)))) & 0x3f
+ } else {
+ wvalue = (scalar[index/64] >> (index % 64)) & 0x3f
+ }
+
+ sel, sign = boothW5(uint(wvalue))
+
+ p256Select(t0.xyz[0:], precomp[0:], sel)
+ p256NegCond(t0.xyz[4:8], sign)
+ p256PointAddAsm(t1.xyz[:], p.xyz[:], t0.xyz[:])
+ p256MovCond(t1.xyz[0:12], t1.xyz[0:12], p.xyz[0:12], sel)
+ p256MovCond(p.xyz[0:12], t1.xyz[0:12], t0.xyz[0:12], zero)
+ zero |= sel
+ }
+
+ p256PointDoubleAsm(p.xyz[:], p.xyz[:])
+ p256PointDoubleAsm(p.xyz[:], p.xyz[:])
+ p256PointDoubleAsm(p.xyz[:], p.xyz[:])
+ p256PointDoubleAsm(p.xyz[:], p.xyz[:])
+ p256PointDoubleAsm(p.xyz[:], p.xyz[:])
+
+ wvalue = (scalar[0] << 1) & 0x3f
+ sel, sign = boothW5(uint(wvalue))
+
+ p256Select(t0.xyz[0:], precomp[0:], sel)
+ p256NegCond(t0.xyz[4:8], sign)
+ p256PointAddAsm(t1.xyz[:], p.xyz[:], t0.xyz[:])
+ p256MovCond(t1.xyz[0:12], t1.xyz[0:12], p.xyz[0:12], sel)
+ p256MovCond(p.xyz[0:12], t1.xyz[0:12], t0.xyz[0:12], zero)
+}
--- /dev/null
+// Copyright 2015 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.
+
+// This file contains constant-time, 64-bit assembly implementation of
+// P256. The optimizations performed here are described in detail in:
+// S.Gueron and V.Krasnov, "Fast prime field elliptic-curve cryptography with
+// 256-bit primes"
+// http://link.springer.com/article/10.1007%2Fs13389-014-0090-x
+// https://eprint.iacr.org/2013/816.pdf
+
+#include "textflag.h"
+
+#define res_ptr DI
+#define x_ptr SI
+#define y_ptr CX
+
+#define acc0 R8
+#define acc1 R9
+#define acc2 R10
+#define acc3 R11
+#define acc4 R12
+#define acc5 R13
+#define t0 R14
+#define t1 R15
+
+DATA p256const0<>+0x00(SB)/8, $0x00000000ffffffff
+DATA p256const1<>+0x00(SB)/8, $0xffffffff00000001
+DATA p256ordK0<>+0x00(SB)/8, $0xccd1c8aaee00bc4f
+DATA p256ord<>+0x00(SB)/8, $0xf3b9cac2fc632551
+DATA p256ord<>+0x08(SB)/8, $0xbce6faada7179e84
+DATA p256ord<>+0x10(SB)/8, $0xffffffffffffffff
+DATA p256ord<>+0x18(SB)/8, $0xffffffff00000000
+DATA p256one<>+0x00(SB)/8, $0x0000000000000001
+DATA p256one<>+0x08(SB)/8, $0xffffffff00000000
+DATA p256one<>+0x10(SB)/8, $0xffffffffffffffff
+DATA p256one<>+0x18(SB)/8, $0x00000000fffffffe
+GLOBL p256const0<>(SB), 8, $8
+GLOBL p256const1<>(SB), 8, $8
+GLOBL p256ordK0<>(SB), 8, $8
+GLOBL p256ord<>(SB), 8, $32
+GLOBL p256one<>(SB), 8, $32
+
+/* ---------------------------------------*/
+// func p256LittleToBig(res []byte, in []uint64)
+TEXT ·p256LittleToBig(SB),NOSPLIT,$0
+ JMP ·p256BigToLittle(SB)
+/* ---------------------------------------*/
+// func p256BigToLittle(res []uint64, in []byte)
+TEXT ·p256BigToLittle(SB),NOSPLIT,$0
+ MOVQ res+0(FP), res_ptr
+ MOVQ in+24(FP), x_ptr
+
+ MOVQ (8*0)(x_ptr), acc0
+ MOVQ (8*1)(x_ptr), acc1
+ MOVQ (8*2)(x_ptr), acc2
+ MOVQ (8*3)(x_ptr), acc3
+
+ BSWAPQ acc0
+ BSWAPQ acc1
+ BSWAPQ acc2
+ BSWAPQ acc3
+
+ MOVQ acc3, (8*0)(res_ptr)
+ MOVQ acc2, (8*1)(res_ptr)
+ MOVQ acc1, (8*2)(res_ptr)
+ MOVQ acc0, (8*3)(res_ptr)
+
+ RET
+/* ---------------------------------------*/
+// func p256MovCond(res, a, b []uint64, cond int)
+// If cond == 0 res=b, else res=a
+TEXT ·p256MovCond(SB),NOSPLIT,$0
+ MOVQ res+0(FP), res_ptr
+ MOVQ a+24(FP), x_ptr
+ MOVQ b+48(FP), y_ptr
+ MOVQ cond+72(FP), X12
+
+ PXOR X13, X13
+ PSHUFD $0, X12, X12
+ PCMPEQL X13, X12
+
+ MOVOU X12, X0
+ PANDN (16*0)(x_ptr), X0
+ MOVOU X12, X1
+ PANDN (16*1)(x_ptr), X1
+ MOVOU X12, X2
+ PANDN (16*2)(x_ptr), X2
+ MOVOU X12, X3
+ PANDN (16*3)(x_ptr), X3
+ MOVOU X12, X4
+ PANDN (16*4)(x_ptr), X4
+ MOVOU X12, X5
+ PANDN (16*5)(x_ptr), X5
+
+ MOVOU (16*0)(y_ptr), X6
+ MOVOU (16*1)(y_ptr), X7
+ MOVOU (16*2)(y_ptr), X8
+ MOVOU (16*3)(y_ptr), X9
+ MOVOU (16*4)(y_ptr), X10
+ MOVOU (16*5)(y_ptr), X11
+
+ PAND X12, X6
+ PAND X12, X7
+ PAND X12, X8
+ PAND X12, X9
+ PAND X12, X10
+ PAND X12, X11
+
+ PXOR X6, X0
+ PXOR X7, X1
+ PXOR X8, X2
+ PXOR X9, X3
+ PXOR X10, X4
+ PXOR X11, X5
+
+ MOVOU X0, (16*0)(res_ptr)
+ MOVOU X1, (16*1)(res_ptr)
+ MOVOU X2, (16*2)(res_ptr)
+ MOVOU X3, (16*3)(res_ptr)
+ MOVOU X4, (16*4)(res_ptr)
+ MOVOU X5, (16*5)(res_ptr)
+
+ RET
+/* ---------------------------------------*/
+// func p256NegCond(val []uint64, cond int)
+TEXT ·p256NegCond(SB),NOSPLIT,$0
+ MOVQ val+0(FP), res_ptr
+ MOVQ cond+24(FP), t0
+ // acc = poly
+ MOVQ $-1, acc0
+ MOVQ p256const0<>(SB), acc1
+ MOVQ $0, acc2
+ MOVQ p256const1<>(SB), acc3
+ // Load the original value
+ MOVQ (8*0)(res_ptr), acc5
+ MOVQ (8*1)(res_ptr), x_ptr
+ MOVQ (8*2)(res_ptr), y_ptr
+ MOVQ (8*3)(res_ptr), t1
+ // Speculatively subtract
+ SUBQ acc5, acc0
+ SBBQ x_ptr, acc1
+ SBBQ y_ptr, acc2
+ SBBQ t1, acc3
+ // If condition is 0, keep original value
+ TESTQ t0, t0
+ CMOVQEQ acc5, acc0
+ CMOVQEQ x_ptr, acc1
+ CMOVQEQ y_ptr, acc2
+ CMOVQEQ t1, acc3
+ // Store result
+ MOVQ acc0, (8*0)(res_ptr)
+ MOVQ acc1, (8*1)(res_ptr)
+ MOVQ acc2, (8*2)(res_ptr)
+ MOVQ acc3, (8*3)(res_ptr)
+
+ RET
+/* ---------------------------------------*/
+// func p256Sqr(res, in []uint64)
+TEXT ·p256Sqr(SB),NOSPLIT,$0
+ MOVQ res+0(FP), res_ptr
+ MOVQ in+24(FP), x_ptr
+ // y[1:] * y[0]
+ MOVQ (8*0)(x_ptr), t0
+
+ MOVQ (8*1)(x_ptr), AX
+ MULQ t0
+ MOVQ AX, acc1
+ MOVQ DX, acc2
+
+ MOVQ (8*2)(x_ptr), AX
+ MULQ t0
+ ADDQ AX, acc2
+ ADCQ $0, DX
+ MOVQ DX, acc3
+
+ MOVQ (8*3)(x_ptr), AX
+ MULQ t0
+ ADDQ AX, acc3
+ ADCQ $0, DX
+ MOVQ DX, acc4
+ // y[2:] * y[1]
+ MOVQ (8*1)(x_ptr), t0
+
+ MOVQ (8*2)(x_ptr), AX
+ MULQ t0
+ ADDQ AX, acc3
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ (8*3)(x_ptr), AX
+ MULQ t0
+ ADDQ t1, acc4
+ ADCQ $0, DX
+ ADDQ AX, acc4
+ ADCQ $0, DX
+ MOVQ DX, acc5
+ // y[3] * y[2]
+ MOVQ (8*2)(x_ptr), t0
+
+ MOVQ (8*3)(x_ptr), AX
+ MULQ t0
+ ADDQ AX, acc5
+ ADCQ $0, DX
+ MOVQ DX, y_ptr
+ XORQ t1, t1
+ // *2
+ ADDQ acc1, acc1
+ ADCQ acc2, acc2
+ ADCQ acc3, acc3
+ ADCQ acc4, acc4
+ ADCQ acc5, acc5
+ ADCQ y_ptr, y_ptr
+ ADCQ $0, t1
+ // Missing products
+ MOVQ (8*0)(x_ptr), AX
+ MULQ AX
+ MOVQ AX, acc0
+ MOVQ DX, t0
+
+ MOVQ (8*1)(x_ptr), AX
+ MULQ AX
+ ADDQ t0, acc1
+ ADCQ AX, acc2
+ ADCQ $0, DX
+ MOVQ DX, t0
+
+ MOVQ (8*2)(x_ptr), AX
+ MULQ AX
+ ADDQ t0, acc3
+ ADCQ AX, acc4
+ ADCQ $0, DX
+ MOVQ DX, t0
+
+ MOVQ (8*3)(x_ptr), AX
+ MULQ AX
+ ADDQ t0, acc5
+ ADCQ AX, y_ptr
+ ADCQ DX, t1
+ MOVQ t1, x_ptr
+ // First reduction step
+ MOVQ acc0, AX
+ MOVQ acc0, t1
+ SHLQ $32, acc0
+ MULQ p256const1<>(SB)
+ SHRQ $32, t1
+ ADDQ acc0, acc1
+ ADCQ t1, acc2
+ ADCQ AX, acc3
+ ADCQ $0, DX
+ MOVQ DX, acc0
+ // Second reduction step
+ MOVQ acc1, AX
+ MOVQ acc1, t1
+ SHLQ $32, acc1
+ MULQ p256const1<>(SB)
+ SHRQ $32, t1
+ ADDQ acc1, acc2
+ ADCQ t1, acc3
+ ADCQ AX, acc0
+ ADCQ $0, DX
+ MOVQ DX, acc1
+ // Third reduction step
+ MOVQ acc2, AX
+ MOVQ acc2, t1
+ SHLQ $32, acc2
+ MULQ p256const1<>(SB)
+ SHRQ $32, t1
+ ADDQ acc2, acc3
+ ADCQ t1, acc0
+ ADCQ AX, acc1
+ ADCQ $0, DX
+ MOVQ DX, acc2
+ // Last reduction step
+ XORQ t0, t0
+ MOVQ acc3, AX
+ MOVQ acc3, t1
+ SHLQ $32, acc3
+ MULQ p256const1<>(SB)
+ SHRQ $32, t1
+ ADDQ acc3, acc0
+ ADCQ t1, acc1
+ ADCQ AX, acc2
+ ADCQ $0, DX
+ MOVQ DX, acc3
+ // Add bits [511:256] of the sqr result
+ ADCQ acc4, acc0
+ ADCQ acc5, acc1
+ ADCQ y_ptr, acc2
+ ADCQ x_ptr, acc3
+ ADCQ $0, t0
+
+ MOVQ acc0, acc4
+ MOVQ acc1, acc5
+ MOVQ acc2, y_ptr
+ MOVQ acc3, t1
+ // Subtract p256
+ SUBQ $-1, acc0
+ SBBQ p256const0<>(SB) ,acc1
+ SBBQ $0, acc2
+ SBBQ p256const1<>(SB), acc3
+ SBBQ $0, t0
+
+ CMOVQCS acc4, acc0
+ CMOVQCS acc5, acc1
+ CMOVQCS y_ptr, acc2
+ CMOVQCS t1, acc3
+
+ MOVQ acc0, (8*0)(res_ptr)
+ MOVQ acc1, (8*1)(res_ptr)
+ MOVQ acc2, (8*2)(res_ptr)
+ MOVQ acc3, (8*3)(res_ptr)
+
+ RET
+/* ---------------------------------------*/
+// func p256Mul(res, in1, in2 []uint64)
+TEXT ·p256Mul(SB),NOSPLIT,$0
+ MOVQ res+0(FP), res_ptr
+ MOVQ in1+24(FP), x_ptr
+ MOVQ in2+48(FP), y_ptr
+ // x * y[0]
+ MOVQ (8*0)(y_ptr), t0
+
+ MOVQ (8*0)(x_ptr), AX
+ MULQ t0
+ MOVQ AX, acc0
+ MOVQ DX, acc1
+
+ MOVQ (8*1)(x_ptr), AX
+ MULQ t0
+ ADDQ AX, acc1
+ ADCQ $0, DX
+ MOVQ DX, acc2
+
+ MOVQ (8*2)(x_ptr), AX
+ MULQ t0
+ ADDQ AX, acc2
+ ADCQ $0, DX
+ MOVQ DX, acc3
+
+ MOVQ (8*3)(x_ptr), AX
+ MULQ t0
+ ADDQ AX, acc3
+ ADCQ $0, DX
+ MOVQ DX, acc4
+ XORQ acc5, acc5
+ // First reduction step
+ MOVQ acc0, AX
+ MOVQ acc0, t1
+ SHLQ $32, acc0
+ MULQ p256const1<>(SB)
+ SHRQ $32, t1
+ ADDQ acc0, acc1
+ ADCQ t1, acc2
+ ADCQ AX, acc3
+ ADCQ DX, acc4
+ ADCQ $0, acc5
+ XORQ acc0, acc0
+ // x * y[1]
+ MOVQ (8*1)(y_ptr), t0
+
+ MOVQ (8*0)(x_ptr), AX
+ MULQ t0
+ ADDQ AX, acc1
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ (8*1)(x_ptr), AX
+ MULQ t0
+ ADDQ t1, acc2
+ ADCQ $0, DX
+ ADDQ AX, acc2
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ (8*2)(x_ptr), AX
+ MULQ t0
+ ADDQ t1, acc3
+ ADCQ $0, DX
+ ADDQ AX, acc3
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ (8*3)(x_ptr), AX
+ MULQ t0
+ ADDQ t1, acc4
+ ADCQ $0, DX
+ ADDQ AX, acc4
+ ADCQ DX, acc5
+ ADCQ $0, acc0
+ // Second reduction step
+ MOVQ acc1, AX
+ MOVQ acc1, t1
+ SHLQ $32, acc1
+ MULQ p256const1<>(SB)
+ SHRQ $32, t1
+ ADDQ acc1, acc2
+ ADCQ t1, acc3
+ ADCQ AX, acc4
+ ADCQ DX, acc5
+ ADCQ $0, acc0
+ XORQ acc1, acc1
+ // x * y[2]
+ MOVQ (8*2)(y_ptr), t0
+
+ MOVQ (8*0)(x_ptr), AX
+ MULQ t0
+ ADDQ AX, acc2
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ (8*1)(x_ptr), AX
+ MULQ t0
+ ADDQ t1, acc3
+ ADCQ $0, DX
+ ADDQ AX, acc3
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ (8*2)(x_ptr), AX
+ MULQ t0
+ ADDQ t1, acc4
+ ADCQ $0, DX
+ ADDQ AX, acc4
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ (8*3)(x_ptr), AX
+ MULQ t0
+ ADDQ t1, acc5
+ ADCQ $0, DX
+ ADDQ AX, acc5
+ ADCQ DX, acc0
+ ADCQ $0, acc1
+ // Third reduction step
+ MOVQ acc2, AX
+ MOVQ acc2, t1
+ SHLQ $32, acc2
+ MULQ p256const1<>(SB)
+ SHRQ $32, t1
+ ADDQ acc2, acc3
+ ADCQ t1, acc4
+ ADCQ AX, acc5
+ ADCQ DX, acc0
+ ADCQ $0, acc1
+ XORQ acc2, acc2
+ // x * y[3]
+ MOVQ (8*3)(y_ptr), t0
+
+ MOVQ (8*0)(x_ptr), AX
+ MULQ t0
+ ADDQ AX, acc3
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ (8*1)(x_ptr), AX
+ MULQ t0
+ ADDQ t1, acc4
+ ADCQ $0, DX
+ ADDQ AX, acc4
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ (8*2)(x_ptr), AX
+ MULQ t0
+ ADDQ t1, acc5
+ ADCQ $0, DX
+ ADDQ AX, acc5
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ (8*3)(x_ptr), AX
+ MULQ t0
+ ADDQ t1, acc0
+ ADCQ $0, DX
+ ADDQ AX, acc0
+ ADCQ DX, acc1
+ ADCQ $0, acc2
+ // Last reduction step
+ MOVQ acc3, AX
+ MOVQ acc3, t1
+ SHLQ $32, acc3
+ MULQ p256const1<>(SB)
+ SHRQ $32, t1
+ ADDQ acc3, acc4
+ ADCQ t1, acc5
+ ADCQ AX, acc0
+ ADCQ DX, acc1
+ ADCQ $0, acc2
+ // Copy result [255:0]
+ MOVQ acc4, x_ptr
+ MOVQ acc5, acc3
+ MOVQ acc0, t0
+ MOVQ acc1, t1
+ // Subtract p256
+ SUBQ $-1, acc4
+ SBBQ p256const0<>(SB) ,acc5
+ SBBQ $0, acc0
+ SBBQ p256const1<>(SB), acc1
+ SBBQ $0, acc2
+
+ CMOVQCS x_ptr, acc4
+ CMOVQCS acc3, acc5
+ CMOVQCS t0, acc0
+ CMOVQCS t1, acc1
+
+ MOVQ acc4, (8*0)(res_ptr)
+ MOVQ acc5, (8*1)(res_ptr)
+ MOVQ acc0, (8*2)(res_ptr)
+ MOVQ acc1, (8*3)(res_ptr)
+
+ RET
+/* ---------------------------------------*/
+// func p256FromMont(res, in []uint64)
+TEXT ·p256FromMont(SB),NOSPLIT,$0
+ MOVQ res+0(FP), res_ptr
+ MOVQ in+24(FP), x_ptr
+
+ MOVQ (8*0)(x_ptr), acc0
+ MOVQ (8*1)(x_ptr), acc1
+ MOVQ (8*2)(x_ptr), acc2
+ MOVQ (8*3)(x_ptr), acc3
+ XORQ acc4, acc4
+
+ // Only reduce, no multiplications are needed
+ // First stage
+ MOVQ acc0, AX
+ MOVQ acc0, t1
+ SHLQ $32, acc0
+ MULQ p256const1<>(SB)
+ SHRQ $32, t1
+ ADDQ acc0, acc1
+ ADCQ t1, acc2
+ ADCQ AX, acc3
+ ADCQ DX, acc4
+ XORQ acc5, acc5
+ // Second stage
+ MOVQ acc1, AX
+ MOVQ acc1, t1
+ SHLQ $32, acc1
+ MULQ p256const1<>(SB)
+ SHRQ $32, t1
+ ADDQ acc1, acc2
+ ADCQ t1, acc3
+ ADCQ AX, acc4
+ ADCQ DX, acc5
+ XORQ acc0, acc0
+ // Third stage
+ MOVQ acc2, AX
+ MOVQ acc2, t1
+ SHLQ $32, acc2
+ MULQ p256const1<>(SB)
+ SHRQ $32, t1
+ ADDQ acc2, acc3
+ ADCQ t1, acc4
+ ADCQ AX, acc5
+ ADCQ DX, acc0
+ XORQ acc1, acc1
+ // Last stage
+ MOVQ acc3, AX
+ MOVQ acc3, t1
+ SHLQ $32, acc3
+ MULQ p256const1<>(SB)
+ SHRQ $32, t1
+ ADDQ acc3, acc4
+ ADCQ t1, acc5
+ ADCQ AX, acc0
+ ADCQ DX, acc1
+
+ MOVQ acc4, x_ptr
+ MOVQ acc5, acc3
+ MOVQ acc0, t0
+ MOVQ acc1, t1
+
+ SUBQ $-1, acc4
+ SBBQ p256const0<>(SB), acc5
+ SBBQ $0, acc0
+ SBBQ p256const1<>(SB), acc1
+
+ CMOVQCS x_ptr, acc4
+ CMOVQCS acc3, acc5
+ CMOVQCS t0, acc0
+ CMOVQCS t1, acc1
+
+ MOVQ acc4, (8*0)(res_ptr)
+ MOVQ acc5, (8*1)(res_ptr)
+ MOVQ acc0, (8*2)(res_ptr)
+ MOVQ acc1, (8*3)(res_ptr)
+
+ RET
+/* ---------------------------------------*/
+// Constant time point access to arbitrary point table.
+// Indexed from 1 to 15, with -1 offset
+// (index 0 is implicitly point at infinity)
+// func p256Select(point, table []uint64, idx int)
+TEXT ·p256Select(SB),NOSPLIT,$0
+ MOVQ idx+48(FP),AX
+ MOVQ table+24(FP),DI
+ MOVQ point+0(FP),DX
+
+ PXOR X15, X15 // X15 = 0
+ PCMPEQL X14, X14 // X14 = -1
+ PSUBL X14, X15 // X15 = 1
+ MOVL AX, X14
+ PSHUFD $0, X14, X14
+
+ PXOR X0, X0
+ PXOR X1, X1
+ PXOR X2, X2
+ PXOR X3, X3
+ PXOR X4, X4
+ PXOR X5, X5
+ MOVQ $16, AX
+
+ MOVOU X15, X13
+
+loop_select:
+
+ MOVOU X13, X12
+ PADDL X15, X13
+ PCMPEQL X14, X12
+
+ MOVOU (16*0)(DI), X6
+ MOVOU (16*1)(DI), X7
+ MOVOU (16*2)(DI), X8
+ MOVOU (16*3)(DI), X9
+ MOVOU (16*4)(DI), X10
+ MOVOU (16*5)(DI), X11
+ ADDQ $(16*6), DI
+
+ PAND X12, X6
+ PAND X12, X7
+ PAND X12, X8
+ PAND X12, X9
+ PAND X12, X10
+ PAND X12, X11
+
+ PXOR X6, X0
+ PXOR X7, X1
+ PXOR X8, X2
+ PXOR X9, X3
+ PXOR X10, X4
+ PXOR X11, X5
+
+ DECQ AX
+ JNE loop_select
+
+ MOVOU X0, (16*0)(DX)
+ MOVOU X1, (16*1)(DX)
+ MOVOU X2, (16*2)(DX)
+ MOVOU X3, (16*3)(DX)
+ MOVOU X4, (16*4)(DX)
+ MOVOU X5, (16*5)(DX)
+
+ RET
+/* ---------------------------------------*/
+// Constant time point access to base point table.
+// func p256SelectBase(point, table []uint64, idx int)
+TEXT ·p256SelectBase(SB),NOSPLIT,$0
+ MOVQ idx+48(FP),AX
+ MOVQ table+24(FP),DI
+ MOVQ point+0(FP),DX
+
+ PXOR X15, X15 // X15 = 0
+ PCMPEQL X14, X14 // X14 = -1
+ PSUBL X14, X15 // X15 = 1
+ MOVL AX, X14
+ PSHUFD $0, X14, X14
+
+ PXOR X0, X0
+ PXOR X1, X1
+ PXOR X2, X2
+ PXOR X3, X3
+ MOVQ $32, AX
+
+ MOVOU X15, X13
+
+loop_select_base:
+
+ MOVOU X13, X12
+ PADDL X15, X13
+ PCMPEQL X14, X12
+
+ MOVOU (16*0)(DI), X4
+ MOVOU (16*1)(DI), X5
+ MOVOU (16*2)(DI), X6
+ MOVOU (16*3)(DI), X7
+
+ MOVOU (16*4)(DI), X8
+ MOVOU (16*5)(DI), X9
+ MOVOU (16*6)(DI), X10
+ MOVOU (16*7)(DI), X11
+
+ ADDQ $(16*8), DI
+
+ PAND X12, X4
+ PAND X12, X5
+ PAND X12, X6
+ PAND X12, X7
+
+ MOVOU X13, X12
+ PADDL X15, X13
+ PCMPEQL X14, X12
+
+ PAND X12, X8
+ PAND X12, X9
+ PAND X12, X10
+ PAND X12, X11
+
+ PXOR X4, X0
+ PXOR X5, X1
+ PXOR X6, X2
+ PXOR X7, X3
+
+ PXOR X8, X0
+ PXOR X9, X1
+ PXOR X10, X2
+ PXOR X11, X3
+
+ DECQ AX
+ JNE loop_select_base
+
+ MOVOU X0, (16*0)(DX)
+ MOVOU X1, (16*1)(DX)
+ MOVOU X2, (16*2)(DX)
+ MOVOU X3, (16*3)(DX)
+
+ RET
+/* ---------------------------------------*/
+// func p256OrdMul(res, in1, in2 []uint64)
+TEXT ·p256OrdMul(SB),NOSPLIT,$0
+ MOVQ res+0(FP), res_ptr
+ MOVQ in1+24(FP), x_ptr
+ MOVQ in2+48(FP), y_ptr
+ // x * y[0]
+ MOVQ (8*0)(y_ptr), t0
+
+ MOVQ (8*0)(x_ptr), AX
+ MULQ t0
+ MOVQ AX, acc0
+ MOVQ DX, acc1
+
+ MOVQ (8*1)(x_ptr), AX
+ MULQ t0
+ ADDQ AX, acc1
+ ADCQ $0, DX
+ MOVQ DX, acc2
+
+ MOVQ (8*2)(x_ptr), AX
+ MULQ t0
+ ADDQ AX, acc2
+ ADCQ $0, DX
+ MOVQ DX, acc3
+
+ MOVQ (8*3)(x_ptr), AX
+ MULQ t0
+ ADDQ AX, acc3
+ ADCQ $0, DX
+ MOVQ DX, acc4
+ XORQ acc5, acc5
+ // First reduction step
+ MOVQ acc0, AX
+ MULQ p256ordK0<>(SB)
+ MOVQ AX, t0
+
+ MOVQ p256ord<>+0x00(SB), AX
+ MULQ t0
+ ADDQ AX, acc0
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ p256ord<>+0x08(SB), AX
+ MULQ t0
+ ADDQ t1, acc1
+ ADCQ $0, DX
+ ADDQ AX, acc1
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ p256ord<>+0x10(SB), AX
+ MULQ t0
+ ADDQ t1, acc2
+ ADCQ $0, DX
+ ADDQ AX, acc2
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ p256ord<>+0x18(SB), AX
+ MULQ t0
+ ADDQ t1, acc3
+ ADCQ $0, DX
+ ADDQ AX, acc3
+ ADCQ DX, acc4
+ ADCQ $0, acc5
+ // x * y[1]
+ MOVQ (8*1)(y_ptr), t0
+
+ MOVQ (8*0)(x_ptr), AX
+ MULQ t0
+ ADDQ AX, acc1
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ (8*1)(x_ptr), AX
+ MULQ t0
+ ADDQ t1, acc2
+ ADCQ $0, DX
+ ADDQ AX, acc2
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ (8*2)(x_ptr), AX
+ MULQ t0
+ ADDQ t1, acc3
+ ADCQ $0, DX
+ ADDQ AX, acc3
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ (8*3)(x_ptr), AX
+ MULQ t0
+ ADDQ t1, acc4
+ ADCQ $0, DX
+ ADDQ AX, acc4
+ ADCQ DX, acc5
+ ADCQ $0, acc0
+ // Second reduction step
+ MOVQ acc1, AX
+ MULQ p256ordK0<>(SB)
+ MOVQ AX, t0
+
+ MOVQ p256ord<>+0x00(SB), AX
+ MULQ t0
+ ADDQ AX, acc1
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ p256ord<>+0x08(SB), AX
+ MULQ t0
+ ADDQ t1, acc2
+ ADCQ $0, DX
+ ADDQ AX, acc2
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ p256ord<>+0x10(SB), AX
+ MULQ t0
+ ADDQ t1, acc3
+ ADCQ $0, DX
+ ADDQ AX, acc3
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ p256ord<>+0x18(SB), AX
+ MULQ t0
+ ADDQ t1, acc4
+ ADCQ $0, DX
+ ADDQ AX, acc4
+ ADCQ DX, acc5
+ ADCQ $0, acc0
+ // x * y[2]
+ MOVQ (8*2)(y_ptr), t0
+
+ MOVQ (8*0)(x_ptr), AX
+ MULQ t0
+ ADDQ AX, acc2
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ (8*1)(x_ptr), AX
+ MULQ t0
+ ADDQ t1, acc3
+ ADCQ $0, DX
+ ADDQ AX, acc3
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ (8*2)(x_ptr), AX
+ MULQ t0
+ ADDQ t1, acc4
+ ADCQ $0, DX
+ ADDQ AX, acc4
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ (8*3)(x_ptr), AX
+ MULQ t0
+ ADDQ t1, acc5
+ ADCQ $0, DX
+ ADDQ AX, acc5
+ ADCQ DX, acc0
+ ADCQ $0, acc1
+ // Third reduction step
+ MOVQ acc2, AX
+ MULQ p256ordK0<>(SB)
+ MOVQ AX, t0
+
+ MOVQ p256ord<>+0x00(SB), AX
+ MULQ t0
+ ADDQ AX, acc2
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ p256ord<>+0x08(SB), AX
+ MULQ t0
+ ADDQ t1, acc3
+ ADCQ $0, DX
+ ADDQ AX, acc3
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ p256ord<>+0x10(SB), AX
+ MULQ t0
+ ADDQ t1, acc4
+ ADCQ $0, DX
+ ADDQ AX, acc4
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ p256ord<>+0x18(SB), AX
+ MULQ t0
+ ADDQ t1, acc5
+ ADCQ $0, DX
+ ADDQ AX, acc5
+ ADCQ DX, acc0
+ ADCQ $0, acc1
+ // x * y[3]
+ MOVQ (8*3)(y_ptr), t0
+
+ MOVQ (8*0)(x_ptr), AX
+ MULQ t0
+ ADDQ AX, acc3
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ (8*1)(x_ptr), AX
+ MULQ t0
+ ADDQ t1, acc4
+ ADCQ $0, DX
+ ADDQ AX, acc4
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ (8*2)(x_ptr), AX
+ MULQ t0
+ ADDQ t1, acc5
+ ADCQ $0, DX
+ ADDQ AX, acc5
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ (8*3)(x_ptr), AX
+ MULQ t0
+ ADDQ t1, acc0
+ ADCQ $0, DX
+ ADDQ AX, acc0
+ ADCQ DX, acc1
+ ADCQ $0, acc2
+ // Last reduction step
+ MOVQ acc3, AX
+ MULQ p256ordK0<>(SB)
+ MOVQ AX, t0
+
+ MOVQ p256ord<>+0x00(SB), AX
+ MULQ t0
+ ADDQ AX, acc3
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ p256ord<>+0x08(SB), AX
+ MULQ t0
+ ADDQ t1, acc4
+ ADCQ $0, DX
+ ADDQ AX, acc4
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ p256ord<>+0x10(SB), AX
+ MULQ t0
+ ADDQ t1, acc5
+ ADCQ $0, DX
+ ADDQ AX, acc5
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ p256ord<>+0x18(SB), AX
+ MULQ t0
+ ADDQ t1, acc0
+ ADCQ $0, DX
+ ADDQ AX, acc0
+ ADCQ DX, acc1
+ ADCQ $0, acc2
+ // Copy result [255:0]
+ MOVQ acc4, x_ptr
+ MOVQ acc5, acc3
+ MOVQ acc0, t0
+ MOVQ acc1, t1
+ // Subtract p256
+ SUBQ p256ord<>+0x00(SB), acc4
+ SBBQ p256ord<>+0x08(SB) ,acc5
+ SBBQ p256ord<>+0x10(SB), acc0
+ SBBQ p256ord<>+0x18(SB), acc1
+ SBBQ $0, acc2
+
+ CMOVQCS x_ptr, acc4
+ CMOVQCS acc3, acc5
+ CMOVQCS t0, acc0
+ CMOVQCS t1, acc1
+
+ MOVQ acc4, (8*0)(res_ptr)
+ MOVQ acc5, (8*1)(res_ptr)
+ MOVQ acc0, (8*2)(res_ptr)
+ MOVQ acc1, (8*3)(res_ptr)
+
+ RET
+/* ---------------------------------------*/
+// func p256OrdSqr(res, in []uint64, n int)
+TEXT ·p256OrdSqr(SB),NOSPLIT,$0
+ MOVQ res+0(FP), res_ptr
+ MOVQ in+24(FP), x_ptr
+ MOVQ n+48(FP), BX
+
+ordSqrLoop:
+
+ // y[1:] * y[0]
+ MOVQ (8*0)(x_ptr), t0
+
+ MOVQ (8*1)(x_ptr), AX
+ MULQ t0
+ MOVQ AX, acc1
+ MOVQ DX, acc2
+
+ MOVQ (8*2)(x_ptr), AX
+ MULQ t0
+ ADDQ AX, acc2
+ ADCQ $0, DX
+ MOVQ DX, acc3
+
+ MOVQ (8*3)(x_ptr), AX
+ MULQ t0
+ ADDQ AX, acc3
+ ADCQ $0, DX
+ MOVQ DX, acc4
+ // y[2:] * y[1]
+ MOVQ (8*1)(x_ptr), t0
+
+ MOVQ (8*2)(x_ptr), AX
+ MULQ t0
+ ADDQ AX, acc3
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ (8*3)(x_ptr), AX
+ MULQ t0
+ ADDQ t1, acc4
+ ADCQ $0, DX
+ ADDQ AX, acc4
+ ADCQ $0, DX
+ MOVQ DX, acc5
+ // y[3] * y[2]
+ MOVQ (8*2)(x_ptr), t0
+
+ MOVQ (8*3)(x_ptr), AX
+ MULQ t0
+ ADDQ AX, acc5
+ ADCQ $0, DX
+ MOVQ DX, y_ptr
+ XORQ t1, t1
+ // *2
+ ADDQ acc1, acc1
+ ADCQ acc2, acc2
+ ADCQ acc3, acc3
+ ADCQ acc4, acc4
+ ADCQ acc5, acc5
+ ADCQ y_ptr, y_ptr
+ ADCQ $0, t1
+ // Missing products
+ MOVQ (8*0)(x_ptr), AX
+ MULQ AX
+ MOVQ AX, acc0
+ MOVQ DX, t0
+
+ MOVQ (8*1)(x_ptr), AX
+ MULQ AX
+ ADDQ t0, acc1
+ ADCQ AX, acc2
+ ADCQ $0, DX
+ MOVQ DX, t0
+
+ MOVQ (8*2)(x_ptr), AX
+ MULQ AX
+ ADDQ t0, acc3
+ ADCQ AX, acc4
+ ADCQ $0, DX
+ MOVQ DX, t0
+
+ MOVQ (8*3)(x_ptr), AX
+ MULQ AX
+ ADDQ t0, acc5
+ ADCQ AX, y_ptr
+ ADCQ DX, t1
+ MOVQ t1, x_ptr
+ // First reduction step
+ MOVQ acc0, AX
+ MULQ p256ordK0<>(SB)
+ MOVQ AX, t0
+
+ MOVQ p256ord<>+0x00(SB), AX
+ MULQ t0
+ ADDQ AX, acc0
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ p256ord<>+0x08(SB), AX
+ MULQ t0
+ ADDQ t1, acc1
+ ADCQ $0, DX
+ ADDQ AX, acc1
+
+ MOVQ t0, t1
+ ADCQ DX, acc2
+ ADCQ $0, t1
+ SUBQ t0, acc2
+ SBBQ $0, t1
+
+ MOVQ t0, AX
+ MOVQ t0, DX
+ MOVQ t0, acc0
+ SHLQ $32, AX
+ SHRQ $32, DX
+
+ ADDQ t1, acc3
+ ADCQ $0, acc0
+ SUBQ AX, acc3
+ SBBQ DX, acc0
+ // Second reduction step
+ MOVQ acc1, AX
+ MULQ p256ordK0<>(SB)
+ MOVQ AX, t0
+
+ MOVQ p256ord<>+0x00(SB), AX
+ MULQ t0
+ ADDQ AX, acc1
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ p256ord<>+0x08(SB), AX
+ MULQ t0
+ ADDQ t1, acc2
+ ADCQ $0, DX
+ ADDQ AX, acc2
+
+ MOVQ t0, t1
+ ADCQ DX, acc3
+ ADCQ $0, t1
+ SUBQ t0, acc3
+ SBBQ $0, t1
+
+ MOVQ t0, AX
+ MOVQ t0, DX
+ MOVQ t0, acc1
+ SHLQ $32, AX
+ SHRQ $32, DX
+
+ ADDQ t1, acc0
+ ADCQ $0, acc1
+ SUBQ AX, acc0
+ SBBQ DX, acc1
+ // Third reduction step
+ MOVQ acc2, AX
+ MULQ p256ordK0<>(SB)
+ MOVQ AX, t0
+
+ MOVQ p256ord<>+0x00(SB), AX
+ MULQ t0
+ ADDQ AX, acc2
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ p256ord<>+0x08(SB), AX
+ MULQ t0
+ ADDQ t1, acc3
+ ADCQ $0, DX
+ ADDQ AX, acc3
+
+ MOVQ t0, t1
+ ADCQ DX, acc0
+ ADCQ $0, t1
+ SUBQ t0, acc0
+ SBBQ $0, t1
+
+ MOVQ t0, AX
+ MOVQ t0, DX
+ MOVQ t0, acc2
+ SHLQ $32, AX
+ SHRQ $32, DX
+
+ ADDQ t1, acc1
+ ADCQ $0, acc2
+ SUBQ AX, acc1
+ SBBQ DX, acc2
+ // Last reduction step
+ MOVQ acc3, AX
+ MULQ p256ordK0<>(SB)
+ MOVQ AX, t0
+
+ MOVQ p256ord<>+0x00(SB), AX
+ MULQ t0
+ ADDQ AX, acc3
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ p256ord<>+0x08(SB), AX
+ MULQ t0
+ ADDQ t1, acc0
+ ADCQ $0, DX
+ ADDQ AX, acc0
+ ADCQ $0, DX
+ MOVQ DX, t1
+
+ MOVQ t0, t1
+ ADCQ DX, acc1
+ ADCQ $0, t1
+ SUBQ t0, acc1
+ SBBQ $0, t1
+
+ MOVQ t0, AX
+ MOVQ t0, DX
+ MOVQ t0, acc3
+ SHLQ $32, AX
+ SHRQ $32, DX
+
+ ADDQ t1, acc2
+ ADCQ $0, acc3
+ SUBQ AX, acc2
+ SBBQ DX, acc3
+ XORQ t0, t0
+ // Add bits [511:256] of the sqr result
+ ADCQ acc4, acc0
+ ADCQ acc5, acc1
+ ADCQ y_ptr, acc2
+ ADCQ x_ptr, acc3
+ ADCQ $0, t0
+
+ MOVQ acc0, acc4
+ MOVQ acc1, acc5
+ MOVQ acc2, y_ptr
+ MOVQ acc3, t1
+ // Subtract p256
+ SUBQ p256ord<>+0x00(SB), acc0
+ SBBQ p256ord<>+0x08(SB) ,acc1
+ SBBQ p256ord<>+0x10(SB), acc2
+ SBBQ p256ord<>+0x18(SB), acc3
+ SBBQ $0, t0
+
+ CMOVQCS acc4, acc0
+ CMOVQCS acc5, acc1
+ CMOVQCS y_ptr, acc2
+ CMOVQCS t1, acc3
+
+ MOVQ acc0, (8*0)(res_ptr)
+ MOVQ acc1, (8*1)(res_ptr)
+ MOVQ acc2, (8*2)(res_ptr)
+ MOVQ acc3, (8*3)(res_ptr)
+ MOVQ res_ptr, x_ptr
+ DECQ BX
+ JNE ordSqrLoop
+
+ RET
+/* ---------------------------------------*/
+#undef res_ptr
+#undef x_ptr
+#undef y_ptr
+
+#undef acc0
+#undef acc1
+#undef acc2
+#undef acc3
+#undef acc4
+#undef acc5
+#undef t0
+#undef t1
+/* ---------------------------------------*/
+#define mul0 AX
+#define mul1 DX
+#define acc0 BX
+#define acc1 CX
+#define acc2 R8
+#define acc3 R9
+#define acc4 R10
+#define acc5 R11
+#define acc6 R12
+#define acc7 R13
+#define t0 R14
+#define t1 R15
+#define t2 DI
+#define t3 SI
+#define hlp BP
+/* ---------------------------------------*/
+TEXT p256SubInternal(SB),NOSPLIT,$0
+ XORQ mul0, mul0
+ SUBQ t0, acc4
+ SBBQ t1, acc5
+ SBBQ t2, acc6
+ SBBQ t3, acc7
+ SBBQ $0, mul0
+
+ MOVQ acc4, acc0
+ MOVQ acc5, acc1
+ MOVQ acc6, acc2
+ MOVQ acc7, acc3
+
+ ADDQ $-1, acc4
+ ADCQ p256const0<>(SB), acc5
+ ADCQ $0, acc6
+ ADCQ p256const1<>(SB), acc7
+ ADCQ $0, mul0
+
+ CMOVQNE acc0, acc4
+ CMOVQNE acc1, acc5
+ CMOVQNE acc2, acc6
+ CMOVQNE acc3, acc7
+
+ RET
+/* ---------------------------------------*/
+TEXT p256MulInternal(SB),NOSPLIT,$0
+ MOVQ acc4, mul0
+ MULQ t0
+ MOVQ mul0, acc0
+ MOVQ mul1, acc1
+
+ MOVQ acc4, mul0
+ MULQ t1
+ ADDQ mul0, acc1
+ ADCQ $0, mul1
+ MOVQ mul1, acc2
+
+ MOVQ acc4, mul0
+ MULQ t2
+ ADDQ mul0, acc2
+ ADCQ $0, mul1
+ MOVQ mul1, acc3
+
+ MOVQ acc4, mul0
+ MULQ t3
+ ADDQ mul0, acc3
+ ADCQ $0, mul1
+ MOVQ mul1, acc4
+
+ MOVQ acc5, mul0
+ MULQ t0
+ ADDQ mul0, acc1
+ ADCQ $0, mul1
+ MOVQ mul1, hlp
+
+ MOVQ acc5, mul0
+ MULQ t1
+ ADDQ hlp, acc2
+ ADCQ $0, mul1
+ ADDQ mul0, acc2
+ ADCQ $0, mul1
+ MOVQ mul1, hlp
+
+ MOVQ acc5, mul0
+ MULQ t2
+ ADDQ hlp, acc3
+ ADCQ $0, mul1
+ ADDQ mul0, acc3
+ ADCQ $0, mul1
+ MOVQ mul1, hlp
+
+ MOVQ acc5, mul0
+ MULQ t3
+ ADDQ hlp, acc4
+ ADCQ $0, mul1
+ ADDQ mul0, acc4
+ ADCQ $0, mul1
+ MOVQ mul1, acc5
+
+ MOVQ acc6, mul0
+ MULQ t0
+ ADDQ mul0, acc2
+ ADCQ $0, mul1
+ MOVQ mul1, hlp
+
+ MOVQ acc6, mul0
+ MULQ t1
+ ADDQ hlp, acc3
+ ADCQ $0, mul1
+ ADDQ mul0, acc3
+ ADCQ $0, mul1
+ MOVQ mul1, hlp
+
+ MOVQ acc6, mul0
+ MULQ t2
+ ADDQ hlp, acc4
+ ADCQ $0, mul1
+ ADDQ mul0, acc4
+ ADCQ $0, mul1
+ MOVQ mul1, hlp
+
+ MOVQ acc6, mul0
+ MULQ t3
+ ADDQ hlp, acc5
+ ADCQ $0, mul1
+ ADDQ mul0, acc5
+ ADCQ $0, mul1
+ MOVQ mul1, acc6
+
+ MOVQ acc7, mul0
+ MULQ t0
+ ADDQ mul0, acc3
+ ADCQ $0, mul1
+ MOVQ mul1, hlp
+
+ MOVQ acc7, mul0
+ MULQ t1
+ ADDQ hlp, acc4
+ ADCQ $0, mul1
+ ADDQ mul0, acc4
+ ADCQ $0, mul1
+ MOVQ mul1, hlp
+
+ MOVQ acc7, mul0
+ MULQ t2
+ ADDQ hlp, acc5
+ ADCQ $0, mul1
+ ADDQ mul0, acc5
+ ADCQ $0, mul1
+ MOVQ mul1, hlp
+
+ MOVQ acc7, mul0
+ MULQ t3
+ ADDQ hlp, acc6
+ ADCQ $0, mul1
+ ADDQ mul0, acc6
+ ADCQ $0, mul1
+ MOVQ mul1, acc7
+ // First reduction step
+ MOVQ acc0, mul0
+ MOVQ acc0, hlp
+ SHLQ $32, acc0
+ MULQ p256const1<>(SB)
+ SHRQ $32, hlp
+ ADDQ acc0, acc1
+ ADCQ hlp, acc2
+ ADCQ mul0, acc3
+ ADCQ $0, mul1
+ MOVQ mul1, acc0
+ // Second reduction step
+ MOVQ acc1, mul0
+ MOVQ acc1, hlp
+ SHLQ $32, acc1
+ MULQ p256const1<>(SB)
+ SHRQ $32, hlp
+ ADDQ acc1, acc2
+ ADCQ hlp, acc3
+ ADCQ mul0, acc0
+ ADCQ $0, mul1
+ MOVQ mul1, acc1
+ // Third reduction step
+ MOVQ acc2, mul0
+ MOVQ acc2, hlp
+ SHLQ $32, acc2
+ MULQ p256const1<>(SB)
+ SHRQ $32, hlp
+ ADDQ acc2, acc3
+ ADCQ hlp, acc0
+ ADCQ mul0, acc1
+ ADCQ $0, mul1
+ MOVQ mul1, acc2
+ // Last reduction step
+ MOVQ acc3, mul0
+ MOVQ acc3, hlp
+ SHLQ $32, acc3
+ MULQ p256const1<>(SB)
+ SHRQ $32, hlp
+ ADDQ acc3, acc0
+ ADCQ hlp, acc1
+ ADCQ mul0, acc2
+ ADCQ $0, mul1
+ MOVQ mul1, acc3
+ BYTE $0x48; BYTE $0xc7; BYTE $0xc5; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00 // MOVQ $0, BP
+ // Add bits [511:256] of the result
+ ADCQ acc0, acc4
+ ADCQ acc1, acc5
+ ADCQ acc2, acc6
+ ADCQ acc3, acc7
+ ADCQ $0, hlp
+ // Copy result
+ MOVQ acc4, acc0
+ MOVQ acc5, acc1
+ MOVQ acc6, acc2
+ MOVQ acc7, acc3
+ // Subtract p256
+ SUBQ $-1, acc4
+ SBBQ p256const0<>(SB) ,acc5
+ SBBQ $0, acc6
+ SBBQ p256const1<>(SB), acc7
+ SBBQ $0, hlp
+ // If the result of the subtraction is negative, restore the previous result
+ CMOVQCS acc0, acc4
+ CMOVQCS acc1, acc5
+ CMOVQCS acc2, acc6
+ CMOVQCS acc3, acc7
+
+ RET
+/* ---------------------------------------*/
+TEXT p256SqrInternal(SB),NOSPLIT,$0
+
+ MOVQ acc4, mul0
+ MULQ acc5
+ MOVQ mul0, acc1
+ MOVQ mul1, acc2
+
+ MOVQ acc4, mul0
+ MULQ acc6
+ ADDQ mul0, acc2
+ ADCQ $0, mul1
+ MOVQ mul1, acc3
+
+ MOVQ acc4, mul0
+ MULQ acc7
+ ADDQ mul0, acc3
+ ADCQ $0, mul1
+ MOVQ mul1, t0
+
+ MOVQ acc5, mul0
+ MULQ acc6
+ ADDQ mul0, acc3
+ ADCQ $0, mul1
+ MOVQ mul1, hlp
+
+ MOVQ acc5, mul0
+ MULQ acc7
+ ADDQ hlp, t0
+ ADCQ $0, mul1
+ ADDQ mul0, t0
+ ADCQ $0, mul1
+ MOVQ mul1, t1
+
+ MOVQ acc6, mul0
+ MULQ acc7
+ ADDQ mul0, t1
+ ADCQ $0, mul1
+ MOVQ mul1, t2
+ XORQ t3, t3
+ // *2
+ ADDQ acc1, acc1
+ ADCQ acc2, acc2
+ ADCQ acc3, acc3
+ ADCQ t0, t0
+ ADCQ t1, t1
+ ADCQ t2, t2
+ ADCQ $0, t3
+ // Missing products
+ MOVQ acc4, mul0
+ MULQ mul0
+ MOVQ mul0, acc0
+ MOVQ DX, acc4
+
+ MOVQ acc5, mul0
+ MULQ mul0
+ ADDQ acc4, acc1
+ ADCQ mul0, acc2
+ ADCQ $0, DX
+ MOVQ DX, acc4
+
+ MOVQ acc6, mul0
+ MULQ mul0
+ ADDQ acc4, acc3
+ ADCQ mul0, t0
+ ADCQ $0, DX
+ MOVQ DX, acc4
+
+ MOVQ acc7, mul0
+ MULQ mul0
+ ADDQ acc4, t1
+ ADCQ mul0, t2
+ ADCQ DX, t3
+ // First reduction step
+ MOVQ acc0, mul0
+ MOVQ acc0, hlp
+ SHLQ $32, acc0
+ MULQ p256const1<>(SB)
+ SHRQ $32, hlp
+ ADDQ acc0, acc1
+ ADCQ hlp, acc2
+ ADCQ mul0, acc3
+ ADCQ $0, mul1
+ MOVQ mul1, acc0
+ // Second reduction step
+ MOVQ acc1, mul0
+ MOVQ acc1, hlp
+ SHLQ $32, acc1
+ MULQ p256const1<>(SB)
+ SHRQ $32, hlp
+ ADDQ acc1, acc2
+ ADCQ hlp, acc3
+ ADCQ mul0, acc0
+ ADCQ $0, mul1
+ MOVQ mul1, acc1
+ // Third reduction step
+ MOVQ acc2, mul0
+ MOVQ acc2, hlp
+ SHLQ $32, acc2
+ MULQ p256const1<>(SB)
+ SHRQ $32, hlp
+ ADDQ acc2, acc3
+ ADCQ hlp, acc0
+ ADCQ mul0, acc1
+ ADCQ $0, mul1
+ MOVQ mul1, acc2
+ // Last reduction step
+ MOVQ acc3, mul0
+ MOVQ acc3, hlp
+ SHLQ $32, acc3
+ MULQ p256const1<>(SB)
+ SHRQ $32, hlp
+ ADDQ acc3, acc0
+ ADCQ hlp, acc1
+ ADCQ mul0, acc2
+ ADCQ $0, mul1
+ MOVQ mul1, acc3
+ BYTE $0x48; BYTE $0xc7; BYTE $0xc5; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00 // MOVQ $0, BP
+ // Add bits [511:256] of the result
+ ADCQ acc0, t0
+ ADCQ acc1, t1
+ ADCQ acc2, t2
+ ADCQ acc3, t3
+ ADCQ $0, hlp
+ // Copy result
+ MOVQ t0, acc4
+ MOVQ t1, acc5
+ MOVQ t2, acc6
+ MOVQ t3, acc7
+ // Subtract p256
+ SUBQ $-1, acc4
+ SBBQ p256const0<>(SB) ,acc5
+ SBBQ $0, acc6
+ SBBQ p256const1<>(SB), acc7
+ SBBQ $0, hlp
+ // If the result of the subtraction is negative, restore the previous result
+ CMOVQCS t0, acc4
+ CMOVQCS t1, acc5
+ CMOVQCS t2, acc6
+ CMOVQCS t3, acc7
+
+ RET
+/* ---------------------------------------*/
+#define p256MulBy2Inline\
+ XORQ mul0, mul0;\
+ ADDQ acc4, acc4;\
+ ADCQ acc5, acc5;\
+ ADCQ acc6, acc6;\
+ ADCQ acc7, acc7;\
+ ADCQ $0, mul0;\
+ MOVQ acc4, t0;\
+ MOVQ acc5, t1;\
+ MOVQ acc6, t2;\
+ MOVQ acc7, t3;\
+ SUBQ $-1, t0;\
+ SBBQ p256const0<>(SB), t1;\
+ SBBQ $0, t2;\
+ SBBQ p256const1<>(SB), t3;\
+ SBBQ $0, mul0;\
+ CMOVQCS acc4, t0;\
+ CMOVQCS acc5, t1;\
+ CMOVQCS acc6, t2;\
+ CMOVQCS acc7, t3;
+/* ---------------------------------------*/
+#define p256AddInline \
+ XORQ mul0, mul0;\
+ ADDQ t0, acc4;\
+ ADCQ t1, acc5;\
+ ADCQ t2, acc6;\
+ ADCQ t3, acc7;\
+ ADCQ $0, mul0;\
+ MOVQ acc4, t0;\
+ MOVQ acc5, t1;\
+ MOVQ acc6, t2;\
+ MOVQ acc7, t3;\
+ SUBQ $-1, t0;\
+ SBBQ p256const0<>(SB), t1;\
+ SBBQ $0, t2;\
+ SBBQ p256const1<>(SB), t3;\
+ SBBQ $0, mul0;\
+ CMOVQCS acc4, t0;\
+ CMOVQCS acc5, t1;\
+ CMOVQCS acc6, t2;\
+ CMOVQCS acc7, t3;
+/* ---------------------------------------*/
+#define LDacc(src) MOVQ src(8*0), acc4; MOVQ src(8*1), acc5; MOVQ src(8*2), acc6; MOVQ src(8*3), acc7
+#define LDt(src) MOVQ src(8*0), t0; MOVQ src(8*1), t1; MOVQ src(8*2), t2; MOVQ src(8*3), t3
+#define ST(dst) MOVQ acc4, dst(8*0); MOVQ acc5, dst(8*1); MOVQ acc6, dst(8*2); MOVQ acc7, dst(8*3)
+#define STt(dst) MOVQ t0, dst(8*0); MOVQ t1, dst(8*1); MOVQ t2, dst(8*2); MOVQ t3, dst(8*3)
+#define acc2t MOVQ acc4, t0; MOVQ acc5, t1; MOVQ acc6, t2; MOVQ acc7, t3
+#define t2acc MOVQ t0, acc4; MOVQ t1, acc5; MOVQ t2, acc6; MOVQ t3, acc7
+/* ---------------------------------------*/
+#define x1in(off) (32*0 + off)(SP)
+#define y1in(off) (32*1 + off)(SP)
+#define z1in(off) (32*2 + off)(SP)
+#define x2in(off) (32*3 + off)(SP)
+#define y2in(off) (32*4 + off)(SP)
+#define xout(off) (32*5 + off)(SP)
+#define yout(off) (32*6 + off)(SP)
+#define zout(off) (32*7 + off)(SP)
+#define s2(off) (32*8 + off)(SP)
+#define z1sqr(off) (32*9 + off)(SP)
+#define h(off) (32*10 + off)(SP)
+#define r(off) (32*11 + off)(SP)
+#define hsqr(off) (32*12 + off)(SP)
+#define rsqr(off) (32*13 + off)(SP)
+#define hcub(off) (32*14 + off)(SP)
+#define rptr (32*15)(SP)
+#define sel_save (32*15 + 8)(SP)
+#define zero_save (32*15 + 8 + 4)(SP)
+
+// func p256PointAddAffineAsm(res, in1, in2 []uint64, sign, sel, zero int)
+TEXT ·p256PointAddAffineAsm(SB),0,$512-96
+ // Move input to stack in order to free registers
+ MOVQ res+0(FP), AX
+ MOVQ in1+24(FP), BX
+ MOVQ in2+48(FP), CX
+ MOVQ sign+72(FP), DX
+ MOVQ sel+80(FP), t1
+ MOVQ zero+88(FP), t2
+
+ MOVOU (16*0)(BX), X0
+ MOVOU (16*1)(BX), X1
+ MOVOU (16*2)(BX), X2
+ MOVOU (16*3)(BX), X3
+ MOVOU (16*4)(BX), X4
+ MOVOU (16*5)(BX), X5
+
+ MOVOU X0, x1in(16*0)
+ MOVOU X1, x1in(16*1)
+ MOVOU X2, y1in(16*0)
+ MOVOU X3, y1in(16*1)
+ MOVOU X4, z1in(16*0)
+ MOVOU X5, z1in(16*1)
+
+ MOVOU (16*0)(CX), X0
+ MOVOU (16*1)(CX), X1
+
+ MOVOU X0, x2in(16*0)
+ MOVOU X1, x2in(16*1)
+ // Store pointer to result
+ MOVQ mul0, rptr
+ MOVL t1, sel_save
+ MOVL t2, zero_save
+ // Negate y2in based on sign
+ MOVQ (16*2 + 8*0)(CX), acc4
+ MOVQ (16*2 + 8*1)(CX), acc5
+ MOVQ (16*2 + 8*2)(CX), acc6
+ MOVQ (16*2 + 8*3)(CX), acc7
+ MOVQ $-1, acc0
+ MOVQ p256const0<>(SB), acc1
+ MOVQ $0, acc2
+ MOVQ p256const1<>(SB), acc3
+ XORQ mul0, mul0
+ // Speculatively subtract
+ SUBQ acc4, acc0
+ SBBQ acc5, acc1
+ SBBQ acc6, acc2
+ SBBQ acc7, acc3
+ SBBQ $0, mul0
+ MOVQ acc0, t0
+ MOVQ acc1, t1
+ MOVQ acc2, t2
+ MOVQ acc3, t3
+ // Add in case the operand was > p256
+ ADDQ $-1, acc0
+ ADCQ p256const0<>(SB), acc1
+ ADCQ $0, acc2
+ ADCQ p256const1<>(SB), acc3
+ ADCQ $0, mul0
+ CMOVQNE t0, acc0
+ CMOVQNE t1, acc1
+ CMOVQNE t2, acc2
+ CMOVQNE t3, acc3
+ // If condition is 0, keep original value
+ TESTQ DX, DX
+ CMOVQEQ acc4, acc0
+ CMOVQEQ acc5, acc1
+ CMOVQEQ acc6, acc2
+ CMOVQEQ acc7, acc3
+ // Store result
+ MOVQ acc0, y2in(8*0)
+ MOVQ acc1, y2in(8*1)
+ MOVQ acc2, y2in(8*2)
+ MOVQ acc3, y2in(8*3)
+ // Begin point add
+ LDacc (z1in)
+ CALL p256SqrInternal(SB) // z1ˆ2
+ ST (z1sqr)
+
+ LDt (x2in)
+ CALL p256MulInternal(SB) // x2 * z1ˆ2
+
+ LDt (x1in)
+ CALL p256SubInternal(SB) // h = u2 - u1
+ ST (h)
+
+ LDt (z1in)
+ CALL p256MulInternal(SB) // z3 = h * z1
+ ST (zout)
+
+ LDacc (z1sqr)
+ CALL p256MulInternal(SB) // z1ˆ3
+
+ LDt (y2in)
+ CALL p256MulInternal(SB) // s2 = y2 * z1ˆ3
+ ST (s2)
+
+ LDt (y1in)
+ CALL p256SubInternal(SB) // r = s2 - s1
+ ST (r)
+
+ CALL p256SqrInternal(SB) // rsqr = rˆ2
+ ST (rsqr)
+
+ LDacc (h)
+ CALL p256SqrInternal(SB) // hsqr = hˆ2
+ ST (hsqr)
+
+ LDt (h)
+ CALL p256MulInternal(SB) // hcub = hˆ3
+ ST (hcub)
+
+ LDt (y1in)
+ CALL p256MulInternal(SB) // y1 * hˆ3
+ ST (s2)
+
+ LDacc (x1in)
+ LDt (hsqr)
+ CALL p256MulInternal(SB) // u1 * hˆ2
+ ST (h)
+
+ p256MulBy2Inline // u1 * hˆ2 * 2, inline
+ LDacc (rsqr)
+ CALL p256SubInternal(SB) // rˆ2 - u1 * hˆ2 * 2
+
+ LDt (hcub)
+ CALL p256SubInternal(SB)
+ ST (xout)
+
+ MOVQ acc4, t0
+ MOVQ acc5, t1
+ MOVQ acc6, t2
+ MOVQ acc7, t3
+ LDacc (h)
+ CALL p256SubInternal(SB)
+
+ LDt (r)
+ CALL p256MulInternal(SB)
+
+ LDt (s2)
+ CALL p256SubInternal(SB)
+ ST (yout)
+ // Load stored values from stack
+ MOVQ rptr, AX
+ MOVL sel_save, BX
+ MOVL zero_save, CX
+ // The result is not valid if (sel == 0), conditional choose
+ MOVOU xout(16*0), X0
+ MOVOU xout(16*1), X1
+ MOVOU yout(16*0), X2
+ MOVOU yout(16*1), X3
+ MOVOU zout(16*0), X4
+ MOVOU zout(16*1), X5
+
+ MOVL BX, X6
+ MOVL CX, X7
+
+ PXOR X8, X8
+ PCMPEQL X9, X9
+
+ PSHUFD $0, X6, X6
+ PSHUFD $0, X7, X7
+
+ PCMPEQL X8, X6
+ PCMPEQL X8, X7
+
+ MOVOU X6, X15
+ PANDN X9, X15
+
+ MOVOU x1in(16*0), X9
+ MOVOU x1in(16*1), X10
+ MOVOU y1in(16*0), X11
+ MOVOU y1in(16*1), X12
+ MOVOU z1in(16*0), X13
+ MOVOU z1in(16*1), X14
+
+ PAND X15, X0
+ PAND X15, X1
+ PAND X15, X2
+ PAND X15, X3
+ PAND X15, X4
+ PAND X15, X5
+
+ PAND X6, X9
+ PAND X6, X10
+ PAND X6, X11
+ PAND X6, X12
+ PAND X6, X13
+ PAND X6, X14
+
+ PXOR X9, X0
+ PXOR X10, X1
+ PXOR X11, X2
+ PXOR X12, X3
+ PXOR X13, X4
+ PXOR X14, X5
+ // Similarly if zero == 0
+ PCMPEQL X9, X9
+ MOVOU X7, X15
+ PANDN X9, X15
+
+ MOVOU x2in(16*0), X9
+ MOVOU x2in(16*1), X10
+ MOVOU y2in(16*0), X11
+ MOVOU y2in(16*1), X12
+ MOVOU p256one<>+0x00(SB), X13
+ MOVOU p256one<>+0x10(SB), X14
+
+ PAND X15, X0
+ PAND X15, X1
+ PAND X15, X2
+ PAND X15, X3
+ PAND X15, X4
+ PAND X15, X5
+
+ PAND X7, X9
+ PAND X7, X10
+ PAND X7, X11
+ PAND X7, X12
+ PAND X7, X13
+ PAND X7, X14
+
+ PXOR X9, X0
+ PXOR X10, X1
+ PXOR X11, X2
+ PXOR X12, X3
+ PXOR X13, X4
+ PXOR X14, X5
+ // Finally output the result
+ MOVOU X0, (16*0)(AX)
+ MOVOU X1, (16*1)(AX)
+ MOVOU X2, (16*2)(AX)
+ MOVOU X3, (16*3)(AX)
+ MOVOU X4, (16*4)(AX)
+ MOVOU X5, (16*5)(AX)
+ MOVQ $0, rptr
+
+ RET
+#undef x1in
+#undef y1in
+#undef z1in
+#undef x2in
+#undef y2in
+#undef xout
+#undef yout
+#undef zout
+#undef s2
+#undef z1sqr
+#undef h
+#undef r
+#undef hsqr
+#undef rsqr
+#undef hcub
+#undef rptr
+#undef sel_save
+#undef zero_save
+/* ---------------------------------------*/
+#define x1in(off) (32*0 + off)(SP)
+#define y1in(off) (32*1 + off)(SP)
+#define z1in(off) (32*2 + off)(SP)
+#define x2in(off) (32*3 + off)(SP)
+#define y2in(off) (32*4 + off)(SP)
+#define z2in(off) (32*5 + off)(SP)
+
+#define xout(off) (32*6 + off)(SP)
+#define yout(off) (32*7 + off)(SP)
+#define zout(off) (32*8 + off)(SP)
+
+#define u1(off) (32*9 + off)(SP)
+#define u2(off) (32*10 + off)(SP)
+#define s1(off) (32*11 + off)(SP)
+#define s2(off) (32*12 + off)(SP)
+#define z1sqr(off) (32*13 + off)(SP)
+#define z2sqr(off) (32*14 + off)(SP)
+#define h(off) (32*15 + off)(SP)
+#define r(off) (32*16 + off)(SP)
+#define hsqr(off) (32*17 + off)(SP)
+#define rsqr(off) (32*18 + off)(SP)
+#define hcub(off) (32*19 + off)(SP)
+#define rptr (32*20)(SP)
+
+//func p256PointAddAsm(res, in1, in2 []uint64)
+TEXT ·p256PointAddAsm(SB),0,$672-72
+ // Move input to stack in order to free registers
+ MOVQ res+0(FP), AX
+ MOVQ in1+24(FP), BX
+ MOVQ in2+48(FP), CX
+
+ MOVOU (16*0)(BX), X0
+ MOVOU (16*1)(BX), X1
+ MOVOU (16*2)(BX), X2
+ MOVOU (16*3)(BX), X3
+ MOVOU (16*4)(BX), X4
+ MOVOU (16*5)(BX), X5
+
+ MOVOU X0, x1in(16*0)
+ MOVOU X1, x1in(16*1)
+ MOVOU X2, y1in(16*0)
+ MOVOU X3, y1in(16*1)
+ MOVOU X4, z1in(16*0)
+ MOVOU X5, z1in(16*1)
+
+ MOVOU (16*0)(CX), X0
+ MOVOU (16*1)(CX), X1
+ MOVOU (16*2)(CX), X2
+ MOVOU (16*3)(CX), X3
+ MOVOU (16*4)(CX), X4
+ MOVOU (16*5)(CX), X5
+
+ MOVOU X0, x2in(16*0)
+ MOVOU X1, x2in(16*1)
+ MOVOU X2, y2in(16*0)
+ MOVOU X3, y2in(16*1)
+ MOVOU X4, z2in(16*0)
+ MOVOU X5, z2in(16*1)
+ // Store pointer to result
+ MOVQ AX, rptr
+ // Begin point add
+ LDacc (z2in)
+ CALL p256SqrInternal(SB) // z2ˆ2
+ ST (z2sqr)
+ LDt (z2in)
+ CALL p256MulInternal(SB) // z2ˆ3
+ LDt (y1in)
+ CALL p256MulInternal(SB) // s1 = z2ˆ3*y1
+ ST (s1)
+
+ LDacc (z1in)
+ CALL p256SqrInternal(SB) // z1ˆ2
+ ST (z1sqr)
+ LDt (z1in)
+ CALL p256MulInternal(SB) // z1ˆ3
+ LDt (y2in)
+ CALL p256MulInternal(SB) // s2 = z1ˆ3*y2
+ ST (s2)
+
+ LDt (s1)
+ CALL p256SubInternal(SB) // r = s2 - s1
+ ST (r)
+
+ LDacc (z2sqr)
+ LDt (x1in)
+ CALL p256MulInternal(SB) // u1 = x1 * z2ˆ2
+ ST (u1)
+ LDacc (z1sqr)
+ LDt (x2in)
+ CALL p256MulInternal(SB) // u2 = x2 * z1ˆ2
+ ST (u2)
+
+ LDt (u1)
+ CALL p256SubInternal(SB) // h = u2 - u1
+ ST (h)
+
+ LDacc (r)
+ CALL p256SqrInternal(SB) // rsqr = rˆ2
+ ST (rsqr)
+
+ LDacc (h)
+ CALL p256SqrInternal(SB) // hsqr = hˆ2
+ ST (hsqr)
+
+ LDt (h)
+ CALL p256MulInternal(SB) // hcub = hˆ3
+ ST (hcub)
+
+ LDt (s1)
+ CALL p256MulInternal(SB)
+ ST (s2)
+
+ LDacc (z1in)
+ LDt (z2in)
+ CALL p256MulInternal(SB) // z1 * z2
+ LDt (h)
+ CALL p256MulInternal(SB) // z1 * z2 * h
+ ST (zout)
+
+ LDacc (hsqr)
+ LDt (u1)
+ CALL p256MulInternal(SB) // hˆ2 * u1
+ ST (u2)
+
+ p256MulBy2Inline // u1 * hˆ2 * 2, inline
+ LDacc (rsqr)
+ CALL p256SubInternal(SB) // rˆ2 - u1 * hˆ2 * 2
+
+ LDt (hcub)
+ CALL p256SubInternal(SB)
+ ST (xout)
+
+ MOVQ acc4, t0
+ MOVQ acc5, t1
+ MOVQ acc6, t2
+ MOVQ acc7, t3
+ LDacc (u2)
+ CALL p256SubInternal(SB)
+
+ LDt (r)
+ CALL p256MulInternal(SB)
+
+ LDt (s2)
+ CALL p256SubInternal(SB)
+ ST (yout)
+
+ MOVOU xout(16*0), X0
+ MOVOU xout(16*1), X1
+ MOVOU yout(16*0), X2
+ MOVOU yout(16*1), X3
+ MOVOU zout(16*0), X4
+ MOVOU zout(16*1), X5
+ // Finally output the result
+ MOVQ rptr, AX
+ MOVQ $0, rptr
+ MOVOU X0, (16*0)(AX)
+ MOVOU X1, (16*1)(AX)
+ MOVOU X2, (16*2)(AX)
+ MOVOU X3, (16*3)(AX)
+ MOVOU X4, (16*4)(AX)
+ MOVOU X5, (16*5)(AX)
+
+ RET
+#undef x1in
+#undef y1in
+#undef z1in
+#undef x2in
+#undef y2in
+#undef z2in
+#undef xout
+#undef yout
+#undef zout
+#undef s1
+#undef s2
+#undef u1
+#undef u2
+#undef z1sqr
+#undef z2sqr
+#undef h
+#undef r
+#undef hsqr
+#undef rsqr
+#undef hcub
+#undef rptr
+/* ---------------------------------------*/
+#define x(off) (32*0 + off)(SP)
+#define y(off) (32*1 + off)(SP)
+#define z(off) (32*2 + off)(SP)
+
+#define s(off) (32*3 + off)(SP)
+#define m(off) (32*4 + off)(SP)
+#define zsqr(off) (32*5 + off)(SP)
+#define tmp(off) (32*6 + off)(SP)
+#define rptr (32*7)(SP)
+
+//func p256PointDoubleAsm(res, in []uint64)
+TEXT ·p256PointDoubleAsm(SB),NOSPLIT,$256-48
+ // Move input to stack in order to free registers
+ MOVQ res+0(FP), AX
+ MOVQ in+24(FP), BX
+
+ MOVOU (16*0)(BX), X0
+ MOVOU (16*1)(BX), X1
+ MOVOU (16*2)(BX), X2
+ MOVOU (16*3)(BX), X3
+ MOVOU (16*4)(BX), X4
+ MOVOU (16*5)(BX), X5
+
+ MOVOU X0, x(16*0)
+ MOVOU X1, x(16*1)
+ MOVOU X2, y(16*0)
+ MOVOU X3, y(16*1)
+ MOVOU X4, z(16*0)
+ MOVOU X5, z(16*1)
+ // Store pointer to result
+ MOVQ AX, rptr
+ // Begin point double
+ LDacc (z)
+ CALL p256SqrInternal(SB)
+ ST (zsqr)
+
+ LDt (x)
+ p256AddInline
+ STt (m)
+
+ LDacc (z)
+ LDt (y)
+ CALL p256MulInternal(SB)
+ p256MulBy2Inline
+ MOVQ rptr, AX
+ // Store z
+ MOVQ t0, (16*4 + 8*0)(AX)
+ MOVQ t1, (16*4 + 8*1)(AX)
+ MOVQ t2, (16*4 + 8*2)(AX)
+ MOVQ t3, (16*4 + 8*3)(AX)
+
+ LDacc (x)
+ LDt (zsqr)
+ CALL p256SubInternal(SB)
+ LDt (m)
+ CALL p256MulInternal(SB)
+ ST (m)
+ // Multiply by 3
+ p256MulBy2Inline
+ LDacc (m)
+ p256AddInline
+ STt (m)
+ ////////////////////////
+ LDacc (y)
+ p256MulBy2Inline
+ t2acc
+ CALL p256SqrInternal(SB)
+ ST (s)
+ CALL p256SqrInternal(SB)
+ // Divide by 2
+ XORQ mul0, mul0
+ MOVQ acc4, t0
+ MOVQ acc5, t1
+ MOVQ acc6, t2
+ MOVQ acc7, t3
+
+ ADDQ $-1, acc4
+ ADCQ p256const0<>(SB), acc5
+ ADCQ $0, acc6
+ ADCQ p256const1<>(SB), acc7
+ ADCQ $0, mul0
+ TESTQ $1, t0
+
+ CMOVQEQ t0, acc4
+ CMOVQEQ t1, acc5
+ CMOVQEQ t2, acc6
+ CMOVQEQ t3, acc7
+ ANDQ t0, mul0
+
+ SHRQ $1, acc4:acc5
+ SHRQ $1, acc5:acc6
+ SHRQ $1, acc6:acc7
+ SHRQ $1, acc7:mul0
+ ST (y)
+ /////////////////////////
+ LDacc (x)
+ LDt (s)
+ CALL p256MulInternal(SB)
+ ST (s)
+ p256MulBy2Inline
+ STt (tmp)
+
+ LDacc (m)
+ CALL p256SqrInternal(SB)
+ LDt (tmp)
+ CALL p256SubInternal(SB)
+
+ MOVQ rptr, AX
+ // Store x
+ MOVQ acc4, (16*0 + 8*0)(AX)
+ MOVQ acc5, (16*0 + 8*1)(AX)
+ MOVQ acc6, (16*0 + 8*2)(AX)
+ MOVQ acc7, (16*0 + 8*3)(AX)
+
+ acc2t
+ LDacc (s)
+ CALL p256SubInternal(SB)
+
+ LDt (m)
+ CALL p256MulInternal(SB)
+
+ LDt (y)
+ CALL p256SubInternal(SB)
+ MOVQ rptr, AX
+ // Store y
+ MOVQ acc4, (16*2 + 8*0)(AX)
+ MOVQ acc5, (16*2 + 8*1)(AX)
+ MOVQ acc6, (16*2 + 8*2)(AX)
+ MOVQ acc7, (16*2 + 8*3)(AX)
+ ///////////////////////
+ MOVQ $0, rptr
+
+ RET
+/* ---------------------------------------*/
+
nn = len(p)
d.len += uint64(nn)
if d.nx > 0 {
- n := len(p)
- if n > chunk-d.nx {
- n = chunk - d.nx
- }
- for i := 0; i < n; i++ {
- d.x[d.nx+i] = p[i]
- }
+ n := copy(d.x[d.nx:], p)
d.nx += n
if d.nx == chunk {
- block(d, d.x[0:chunk])
+ block(d, d.x[:])
d.nx = 0
}
p = p[n:]
{TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil},
{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil},
+ {TLS_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, rsaKA, suiteTLS12, nil, nil, aeadAESGCM},
+ {TLS_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, rsaKA, suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
{TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, suiteDefaultOff, cipherRC4, macSHA1, nil},
{TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil},
{TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil},
TLS_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x000a
TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002f
TLS_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0035
+ TLS_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009c
+ TLS_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009d
TLS_ECDHE_ECDSA_WITH_RC4_128_SHA uint16 = 0xc007
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA uint16 = 0xc009
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA uint16 = 0xc00a
// ServerName is used to verify the hostname on the returned
// certificates unless InsecureSkipVerify is given. It is also included
- // in the client's handshake to support virtual hosting.
+ // in the client's handshake to support virtual hosting unless it is
+ // an IP address.
ServerName string
// ClientAuth determines the server's policy for
type halfConn struct {
sync.Mutex
- err error // first permanent error
- version uint16 // protocol version
- cipher interface{} // cipher algorithm
- mac macFunction
- seq [8]byte // 64-bit sequence number
- bfree *block // list of free blocks
+ err error // first permanent error
+ version uint16 // protocol version
+ cipher interface{} // cipher algorithm
+ mac macFunction
+ seq [8]byte // 64-bit sequence number
+ bfree *block // list of free blocks
+ additionalData [13]byte // to avoid allocs; interface method args escape
nextCipher interface{} // next encryption state
nextMac macFunction // next MAC algorithm
nonce := payload[:8]
payload = payload[8:]
- var additionalData [13]byte
- copy(additionalData[:], hc.seq[:])
- copy(additionalData[8:], b.data[:3])
+ copy(hc.additionalData[:], hc.seq[:])
+ copy(hc.additionalData[8:], b.data[:3])
n := len(payload) - c.Overhead()
- additionalData[11] = byte(n >> 8)
- additionalData[12] = byte(n)
+ hc.additionalData[11] = byte(n >> 8)
+ hc.additionalData[12] = byte(n)
var err error
- payload, err = c.Open(payload[:0], nonce, payload, additionalData[:])
+ payload, err = c.Open(payload[:0], nonce, payload, hc.additionalData[:])
if err != nil {
return false, 0, alertBadRecordMAC
}
payload := b.data[recordHeaderLen+explicitIVLen:]
payload = payload[:payloadLen]
- var additionalData [13]byte
- copy(additionalData[:], hc.seq[:])
- copy(additionalData[8:], b.data[:3])
- additionalData[11] = byte(payloadLen >> 8)
- additionalData[12] = byte(payloadLen)
+ copy(hc.additionalData[:], hc.seq[:])
+ copy(hc.additionalData[8:], b.data[:3])
+ hc.additionalData[11] = byte(payloadLen >> 8)
+ hc.additionalData[12] = byte(payloadLen)
- c.Seal(payload[:0], nonce, payload, additionalData[:])
+ c.Seal(payload[:0], nonce, payload, hc.additionalData[:])
case cbcMode:
blockSize := c.BlockSize()
if explicitIVLen > 0 {
return errors.New("tls: NextProtos values too large")
}
+ sni := c.config.ServerName
+ // IP address literals are not permitted as SNI values. See
+ // https://tools.ietf.org/html/rfc6066#section-3.
+ if net.ParseIP(sni) != nil {
+ sni = ""
+ }
+
hello := &clientHelloMsg{
vers: c.config.maxVersion(),
compressionMethods: []uint8{compressionNone},
random: make([]byte, 32),
ocspStapling: true,
scts: true,
- serverName: c.config.ServerName,
+ serverName: sni,
supportedCurves: c.config.curvePreferences(),
supportedPoints: []uint8{pointFormatUncompressed},
nextProtoNeg: len(c.config.NextProtos) > 0,
runClientTestTLS12(t, test)
}
+func TestHandshakeClientRSAAES128GCM(t *testing.T) {
+ test := &clientTest{
+ name: "AES128-GCM-SHA256",
+ command: []string{"openssl", "s_server", "-cipher", "AES128-GCM-SHA256"},
+ }
+ runClientTestTLS12(t, test)
+}
+
+func TestHandshakeClientRSAAES256GCM(t *testing.T) {
+ test := &clientTest{
+ name: "AES256-GCM-SHA384",
+ command: []string{"openssl", "s_server", "-cipher", "AES256-GCM-SHA384"},
+ }
+ runClientTestTLS12(t, test)
+}
+
func TestHandshakeClientECDHERSAAES(t *testing.T) {
test := &clientTest{
name: "ECDHE-RSA-AES",
}
runClientTestTLS12(t, test)
}
+
+func TestNoIPAddressesInSNI(t *testing.T) {
+ for _, ipLiteral := range []string{"1.2.3.4", "::1"} {
+ c, s := net.Pipe()
+
+ go func() {
+ client := Client(c, &Config{ServerName: ipLiteral})
+ client.Handshake()
+ }()
+
+ var header [5]byte
+ if _, err := io.ReadFull(s, header[:]); err != nil {
+ t.Fatal(err)
+ }
+ recordLen := int(header[3])<<8 | int(header[4])
+
+ record := make([]byte, recordLen)
+ if _, err := io.ReadFull(s, record[:]); err != nil {
+ t.Fatal(err)
+ }
+ s.Close()
+
+ if bytes.Index(record, []byte(ipLiteral)) != -1 {
+ t.Errorf("IP literal %q found in ClientHello: %x", ipLiteral, record)
+ }
+ }
+}
// masterFromPreMasterSecret generates the master secret from the pre-master
// secret. See http://tools.ietf.org/html/rfc5246#section-8.1
func masterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, clientRandom, serverRandom []byte) []byte {
- var seed [tlsRandomLength * 2]byte
- copy(seed[0:len(clientRandom)], clientRandom)
- copy(seed[len(clientRandom):], serverRandom)
+ seed := make([]byte, 0, len(clientRandom)+len(serverRandom))
+ seed = append(seed, clientRandom...)
+ seed = append(seed, serverRandom...)
+
masterSecret := make([]byte, masterSecretLength)
- prfForVersion(version, suite)(masterSecret, preMasterSecret, masterSecretLabel, seed[0:])
+ prfForVersion(version, suite)(masterSecret, preMasterSecret, masterSecretLabel, seed)
return masterSecret
}
// secret, given the lengths of the MAC key, cipher key and IV, as defined in
// RFC 2246, section 6.3.
func keysFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) {
- var seed [tlsRandomLength * 2]byte
- copy(seed[0:len(clientRandom)], serverRandom)
- copy(seed[len(serverRandom):], clientRandom)
+ seed := make([]byte, 0, len(serverRandom)+len(clientRandom))
+ seed = append(seed, serverRandom...)
+ seed = append(seed, clientRandom...)
n := 2*macLen + 2*keyLen + 2*ivLen
keyMaterial := make([]byte, n)
- prfForVersion(version, suite)(keyMaterial, masterSecret, keyExpansionLabel, seed[0:])
+ prfForVersion(version, suite)(keyMaterial, masterSecret, keyExpansionLabel, seed)
clientMAC = keyMaterial[:macLen]
keyMaterial = keyMaterial[macLen:]
serverMAC = keyMaterial[:macLen]
>>> Flow 1 (client to server)
-00000000 16 03 01 00 81 01 00 00 7d 03 03 00 00 00 00 00 |........}.......|
+00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 22 c0 2f |............."./|
00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 36 |...../.5.......6|
-00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
-00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
-00000070 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
-00000080 01 00 00 12 00 00 |......|
+00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
+00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
+00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
+00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
+00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
>>> Flow 2 (server to client)
-00000000 16 03 01 00 59 02 00 00 55 03 01 c0 e1 5c 5b 45 |....Y...U....\[E|
-00000010 70 fc a1 73 44 e7 69 b6 83 a1 71 bc 03 21 2e cc |p..sD.i...q..!..|
-00000020 21 7a 28 20 82 6b 2f 77 7d 40 c7 20 0d e4 19 db |!z( .k/w}@. ....|
-00000030 35 cd 75 a4 e7 e5 6c 3e c9 d5 fe 9d c5 88 78 7b |5.u...l>......x{|
-00000040 c4 fc 04 9a c1 10 7a 15 d9 e9 4a 95 c0 09 00 00 |......z...J.....|
+00000000 16 03 01 00 59 02 00 00 55 03 01 38 1a 94 8d 84 |....Y...U..8....|
+00000010 d7 a4 29 89 50 ad 07 97 5b c0 2c 7b 8c a6 75 0e |..).P...[.,{..u.|
+00000020 97 51 62 10 07 87 c5 6f 0a 5f 86 20 1d ac 1d 05 |.Qb....o._. ....|
+00000030 ea 85 48 84 73 d9 07 8d d0 81 56 99 81 10 7b 18 |..H.s.....V...{.|
+00000040 e8 5e da a9 fe cd f9 91 88 31 9b 6e c0 09 00 00 |.^.......1.n....|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
00000060 01 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..|
00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....|
00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....|
00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.|
00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....|
-00000270 2a 16 03 01 00 d6 0c 00 00 d2 03 00 17 41 04 01 |*............A..|
-00000280 74 83 af 3a 65 7a ad 1a 63 1f 13 82 9d f4 de 06 |t..:ez..c.......|
-00000290 4e 3a 03 81 61 72 ff f8 58 da 7b f5 81 6d 81 57 |N:..ar..X.{..m.W|
-000002a0 d9 d1 b1 6d e3 97 db 86 72 17 15 18 16 d4 ec 04 |...m....r.......|
-000002b0 32 7c 38 90 6b a4 3c e9 35 79 2d 4c 39 5e 2d 00 |2|8.k.<.5y-L9^-.|
-000002c0 8b 30 81 88 02 42 01 44 78 e1 2a bb 95 f7 45 58 |.0...B.Dx.*...EX|
-000002d0 d4 0d b6 e4 4e ff 48 b3 11 14 ee d5 6c bb 5f 0c |....N.H.....l._.|
-000002e0 90 b6 ef bc 05 77 f6 05 42 b4 d8 a6 70 e6 8c 90 |.....w..B...p...|
-000002f0 f0 4b 3b c9 d3 4e 0c 85 65 b4 e0 fe b5 10 09 9b |.K;..N..e.......|
-00000300 e1 08 84 ea 93 96 8e a4 02 42 01 c7 15 ee 9d 98 |.........B......|
-00000310 b7 25 eb 07 ff f6 94 7e e7 9d a5 17 9e 37 93 40 |.%.....~.....7.@|
-00000320 4c 9f eb 6b a3 7a 57 d8 81 c6 d9 09 34 aa 96 8c |L..k.zW.....4...|
-00000330 4d 28 2e 9f f7 0b 1c 09 e1 d1 d8 48 6e 8a 8e 9c |M(.........Hn...|
-00000340 01 4c e7 2d 53 8f 8e 71 61 82 ff ff 16 03 01 00 |.L.-S..qa.......|
-00000350 0e 0d 00 00 06 03 01 02 40 00 00 0e 00 00 00 |........@......|
+00000270 2a 16 03 01 00 d5 0c 00 00 d1 03 00 17 41 04 68 |*............A.h|
+00000280 37 18 3d 57 d2 5a 39 75 1e 7f 0a 3a 47 65 36 2e |7.=W.Z9u...:Ge6.|
+00000290 6d cb 8f aa 0f 0d 45 5e 3f 14 82 f5 8c b1 11 0a |m.....E^?.......|
+000002a0 8f e0 bc e4 07 d3 d5 bf 2d f4 82 ba cf c9 1c 88 |........-.......|
+000002b0 33 72 a8 49 39 48 40 74 c6 96 c3 30 72 31 34 00 |3r.I9H@t...0r14.|
+000002c0 8a 30 81 87 02 41 0e 43 2d 29 81 e9 c3 07 fc 5c |.0...A.C-).....\|
+000002d0 ad c0 51 9e 0f cf c5 77 e4 bf 00 b6 66 f9 0e c6 |..Q....w....f...|
+000002e0 40 c6 b5 49 a4 04 05 31 2c 7c 1f 24 38 80 1b 3f |@..I...1,|.$8..?|
+000002f0 16 5f c7 4d a8 7d 98 50 7f 7d 6d ed e9 19 1d 19 |._.M.}.P.}m.....|
+00000300 7b fd ec c5 4d 18 ab 02 42 01 00 db 37 b7 fa 39 |{...M...B...7..9|
+00000310 4b 3f 16 06 eb b8 4a 22 c6 de 00 d8 a7 eb a2 9e |K?....J"........|
+00000320 e1 6f f4 a4 32 e2 ca d0 72 3a e5 f3 14 27 a0 dd |.o..2...r:...'..|
+00000330 c4 26 34 b3 6c a3 d0 03 90 7a 2e 0e bf 0b 63 63 |.&4.l....z....cc|
+00000340 77 66 37 dd 1a 0f 7a 90 3f c8 a9 16 03 01 00 0e |wf7...z.?.......|
+00000350 0d 00 00 06 03 01 02 40 00 00 0e 00 00 00 |.......@......|
>>> Flow 3 (client to server)
00000000 16 03 01 02 0a 0b 00 02 06 00 02 03 00 02 00 30 |...............0|
00000010 82 01 fc 30 82 01 5e 02 09 00 9a 30 84 6c 26 35 |...0..^....0.l&5|
00000220 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd a7 |Q.5uq..T[....g..|
00000230 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e f1 |$ >.V...(^.+-O..|
00000240 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 |..lK[.V.2B.X..I.|
-00000250 b5 68 1a 41 03 56 6b dc 5a 89 16 03 01 00 91 0f |.h.A.Vk.Z.......|
-00000260 00 00 8d 00 8b 30 81 88 02 42 01 91 2d e9 99 a4 |.....0...B..-...|
-00000270 88 5c 03 9c ea 8b 64 07 f2 c9 e7 ad 5b a3 fb 27 |.\....d.....[..'|
-00000280 fd 19 9b 78 bd 7b 9d 0a cc 8a 61 c5 83 33 02 29 |...x.{....a..3.)|
-00000290 c3 66 24 9d 5f bc 03 d9 2a 49 aa 59 51 83 49 72 |.f$._...*I.YQ.Ir|
-000002a0 13 be ea 82 5a 5c 09 2f da 23 bc 18 02 42 01 0d |....Z\./.#...B..|
-000002b0 a1 15 4d fe 18 ec 90 d5 4e 9a 75 60 05 67 10 5e |..M.....N.u`.g.^|
-000002c0 3c 34 00 e8 18 33 8f 90 26 2e d3 a9 81 6c 43 17 |<4...3..&....lC.|
-000002d0 80 9e c5 bd 23 c9 24 96 a1 29 23 a4 13 3f ad d2 |....#.$..)#..?..|
-000002e0 45 19 0b 56 56 4b c1 f1 cc 70 c8 af 44 ff 34 96 |E..VVK...p..D.4.|
-000002f0 14 03 01 00 01 01 16 03 01 00 30 c4 0c 67 53 06 |..........0..gS.|
-00000300 49 b3 c9 5c 2e 72 f6 54 ba ad ac a8 80 55 17 01 |I..\.r.T.....U..|
-00000310 5c 44 71 7d ad 15 34 95 9a 7f 7b 95 0e 08 70 ce |\Dq}..4...{...p.|
-00000320 5a 33 f4 3b 4e 80 06 43 70 93 17 |Z3.;N..Cp..|
+00000250 b5 68 1a 41 03 56 6b dc 5a 89 16 03 01 00 90 0f |.h.A.Vk.Z.......|
+00000260 00 00 8c 00 8a 30 81 87 02 41 51 c5 53 a8 0f cb |.....0...AQ.S...|
+00000270 18 79 4a 59 53 62 17 bb 29 39 fa cd 56 6c 5c 29 |.yJYSb..)9..Vl\)|
+00000280 1f e3 bc df fb 9a 29 fa 38 1a 73 aa 4c 79 6b 1c |......).8.s.Lyk.|
+00000290 9f 1c 8e 95 c7 11 cc df 5d e9 c7 93 ce a3 9b e6 |........].......|
+000002a0 94 17 24 3a 8e f8 9a a9 46 01 f9 02 42 01 a1 df |..$:....F...B...|
+000002b0 c5 cc fe 8d 5b 34 fb 89 2f f5 b3 3f 75 d7 19 1b |....[4../..?u...|
+000002c0 5e 0f 1a 2e 8f 2d 62 61 73 85 2c 03 3b 22 07 2f |^....-bas.,.;"./|
+000002d0 6b f3 5c fb ba b2 87 54 1c ef d2 f8 82 f3 9e f8 |k.\....T........|
+000002e0 ce 1b fa ce b0 6d d0 85 f8 62 6e d6 ba 93 cc 14 |.....m...bn.....|
+000002f0 03 01 00 01 01 16 03 01 00 30 76 90 a8 a2 8d 25 |.........0v....%|
+00000300 c5 c2 ff ef 2b 76 83 2c 7a 0d 44 37 99 67 02 d3 |....+v.,z.D7.g..|
+00000310 6e 3b 28 83 21 cf f5 6a 71 61 2d 5b 24 57 b2 19 |n;(.!..jqa-[$W..|
+00000320 63 d4 e5 96 0c 0c e1 f3 3a 99 |c.......:.|
>>> Flow 4 (server to client)
-00000000 14 03 01 00 01 01 16 03 01 00 30 3b ba 6c 73 ec |..........0;.ls.|
-00000010 11 5b 44 46 1d bb 31 1b 1b e8 d8 51 4f 95 b0 40 |.[DF..1....QO..@|
-00000020 87 49 33 73 40 98 61 1c 94 02 48 9b 80 d3 6c af |.I3s@.a...H...l.|
-00000030 e2 31 63 11 a7 c8 db ed 7a a4 4d |.1c.....z.M|
+00000000 14 03 01 00 01 01 16 03 01 00 30 37 f0 ad 4c 11 |..........07..L.|
+00000010 6d fb 54 90 13 d2 10 93 43 d8 be 3b d0 2b 14 a5 |m.T.....C..;.+..|
+00000020 9d fb a6 5d 38 e0 f5 e9 a6 0a 8e 3d 99 a2 ec 96 |...]8......=....|
+00000030 d8 ff 90 13 03 99 33 d7 15 29 5f |......3..)_|
>>> Flow 5 (client to server)
-00000000 17 03 01 00 20 2e f7 66 f0 ce 50 d7 38 7a d4 fd |.... ..f..P.8z..|
-00000010 e3 66 b1 76 76 59 ad bc b0 0a 75 1d f0 92 6e e3 |.f.vvY....u...n.|
-00000020 21 1d 13 dc ad 17 03 01 00 20 f1 b2 0f 3b 26 91 |!........ ...;&.|
-00000030 ed ff 9f fc 41 04 7e 47 17 02 af 0c 2b e8 b7 31 |....A.~G....+..1|
-00000040 ae 29 71 f9 a8 89 84 f3 e8 da 15 03 01 00 20 1f |.)q........... .|
-00000050 26 64 cf 34 c1 48 6b 79 61 e2 77 57 9d 27 14 45 |&d.4.Hkya.wW.'.E|
-00000060 46 24 ad 2d 35 57 db 2b 32 03 e2 68 b0 1a 5a |F$.-5W.+2..h..Z|
+00000000 17 03 01 00 20 f9 59 b0 e2 8b f9 2c dd 30 1b 8f |.... .Y....,.0..|
+00000010 df 85 0f 17 88 23 5e ca c9 d3 ca 5f 52 d4 33 e0 |.....#^...._R.3.|
+00000020 d2 62 54 17 f2 17 03 01 00 20 62 2d 28 d2 55 68 |.bT...... b-(.Uh|
+00000030 77 ab 6e c0 ac d9 cd 31 1c 38 aa 07 b3 e8 0d 89 |w.n....1.8......|
+00000040 7e e4 f3 a0 65 84 f6 b8 c8 91 15 03 01 00 20 b5 |~...e......... .|
+00000050 95 69 90 d7 32 d1 5a a5 e0 e2 6c 0a dc 00 1c 5e |.i..2.Z...l....^|
+00000060 d2 10 2b a2 3e ae a5 b2 63 9f c4 4e 62 56 db |..+.>...c..NbV.|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 81 01 00 00 7d 03 03 00 00 00 00 00 |........}.......|
+00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 22 c0 2f |............."./|
00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 36 |...../.5.......6|
-00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
-00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
-00000070 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
-00000080 01 00 00 12 00 00 |......|
+00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
+00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
+00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
+00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
+00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
>>> Flow 2 (server to client)
-00000000 16 03 01 00 51 02 00 00 4d 03 01 b7 de 52 5a 07 |....Q...M....RZ.|
-00000010 43 b8 72 1d d9 6f 5c a5 70 da ee 27 b7 a9 50 9d |C.r..o\.p..'..P.|
-00000020 e7 75 ad 61 a5 2f 69 47 2a d8 2e 20 a8 b0 64 6b |.u.a./iG*.. ..dk|
-00000030 4d 25 ec 50 2b 8e a7 9b 0c f9 f5 3c 62 96 a3 53 |M%.P+......<b..S|
-00000040 a7 4b af 33 1e e7 f8 43 b9 be 6e e7 00 05 00 00 |.K.3...C..n.....|
-00000050 05 ff 01 00 01 00 16 03 01 02 be 0b 00 02 ba 00 |................|
-00000060 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......|
-00000070 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..|
-00000080 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 45 31 0b |.*.H........0E1.|
-00000090 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..|
-000000a0 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State|
-000000b0 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter|
-000000c0 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty |
-000000d0 4c 74 64 30 1e 17 0d 31 30 30 34 32 34 30 39 30 |Ltd0...100424090|
-000000e0 39 33 38 5a 17 0d 31 31 30 34 32 34 30 39 30 39 |938Z..1104240909|
-000000f0 33 38 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 |38Z0E1.0...U....|
-00000100 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som|
-00000110 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..|
-00000120 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi|
-00000130 74 73 20 50 74 79 20 4c 74 64 30 81 9f 30 0d 06 |ts Pty Ltd0..0..|
-00000140 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 |.*.H............|
-00000150 30 81 89 02 81 81 00 bb 79 d6 f5 17 b5 e5 bf 46 |0.......y......F|
-00000160 10 d0 dc 69 be e6 2b 07 43 5a d0 03 2d 8a 7a 43 |...i..+.CZ..-.zC|
-00000170 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 8c b5 b4 82 |...R..eL,x.#....|
-00000180 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 fe 12 5c 7a |....;~b.,.3...\z|
-00000190 56 fc f5 06 bf fa 58 7b 26 3f b5 cd 04 d3 d0 c9 |V.....X{&?......|
-000001a0 21 96 4a c7 f4 54 9f 5a bf ef 42 71 00 fe 18 99 |!.J..T.Z..Bq....|
-000001b0 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e db 51 c9 7c |..~.}}..9....Q.||
-000001c0 e3 c0 4c 3b 32 66 01 cf af b1 1d b8 71 9a 1d db |..L;2f......q...|
-000001d0 db 89 6b ae da 2d 79 02 03 01 00 01 a3 81 a7 30 |..k..-y........0|
-000001e0 81 a4 30 1d 06 03 55 1d 0e 04 16 04 14 b1 ad e2 |..0...U.........|
-000001f0 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 88 |.Z..(.i.#i..&...|
-00000200 39 30 75 06 03 55 1d 23 04 6e 30 6c 80 14 b1 ad |90u..U.#.n0l....|
-00000210 e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 |..Z..(.i.#i..&..|
-00000220 88 39 a1 49 a4 47 30 45 31 0b 30 09 06 03 55 04 |.9.I.G0E1.0...U.|
-00000230 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 0a |...AU1.0...U....|
-00000240 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 |Some-State1!0...|
-00000250 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 |U....Internet Wi|
-00000260 64 67 69 74 73 20 50 74 79 20 4c 74 64 82 09 00 |dgits Pty Ltd...|
-00000270 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 55 1d 13 04 |........0...U...|
-00000280 05 30 03 01 01 ff 30 0d 06 09 2a 86 48 86 f7 0d |.0....0...*.H...|
-00000290 01 01 05 05 00 03 81 81 00 08 6c 45 24 c7 6b b1 |..........lE$.k.|
-000002a0 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a 64 75 b5 5a |Y..R.......zdu.Z|
-000002b0 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f 38 b3 6e 60 |.f..+...f..O8.n`|
-000002c0 d3 92 fd f7 41 08 b5 25 13 b1 18 7a 24 fb 30 1d |....A..%...z$.0.|
-000002d0 ba ed 98 b9 17 ec e7 d7 31 59 db 95 d3 1d 78 ea |........1Y....x.|
-000002e0 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 90 |PV\..Z-Z_3....u.|
-000002f0 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c a3 |...R...... _....|
-00000300 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b 26 |......W.p.&mq..&|
-00000310 6e 38 50 29 6c 90 a7 bd d9 16 03 01 00 0e 0d 00 |n8P)l...........|
-00000320 00 06 03 01 02 40 00 00 0e 00 00 00 |.....@......|
+00000000 16 03 01 00 51 02 00 00 4d 03 01 4e 15 d3 06 f6 |....Q...M..N....|
+00000010 ec 13 16 c5 fa 59 cf 5e 2f ad 85 b9 38 e7 7f fb |.....Y.^/...8...|
+00000020 85 cb da eb f2 2e 17 51 a2 b0 be 20 61 e4 32 c9 |.......Q... a.2.|
+00000030 66 92 36 89 0c 0c f4 00 15 47 86 d9 e9 90 ab 2d |f.6......G.....-|
+00000040 8f a3 e2 5e f6 44 2c 6a 1d 98 88 5c 00 05 00 00 |...^.D,j...\....|
+00000050 05 ff 01 00 01 00 16 03 01 02 71 0b 00 02 6d 00 |..........q...m.|
+00000060 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
+00000070 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
+00000080 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
+00000090 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
+000000a0 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
+000000b0 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
+000000c0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
+000000d0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
+000000e0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
+000000f0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
+00000100 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
+00000110 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
+00000120 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
+00000130 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
+00000140 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
+00000150 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
+00000160 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
+00000170 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
+00000180 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
+00000190 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
+000001a0 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
+000001b0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
+000001c0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
+000001d0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
+000001e0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
+000001f0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
+00000200 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
+00000210 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
+00000220 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
+00000230 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
+00000240 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
+00000250 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
+00000260 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
+00000270 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
+00000280 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
+00000290 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
+000002a0 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
+000002b0 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
+000002c0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 01 00 |..A4......9.....|
+000002d0 0e 0d 00 00 06 03 01 02 40 00 00 0e 00 00 00 |........@......|
>>> Flow 3 (client to server)
00000000 16 03 01 02 0a 0b 00 02 06 00 02 03 00 02 00 30 |...............0|
00000010 82 01 fc 30 82 01 5e 02 09 00 9a 30 84 6c 26 35 |...0..^....0.l&5|
000001e0 be e8 91 b3 da 1a f5 5d a3 23 f5 26 8b 45 70 8d |.......].#.&.Ep.|
000001f0 65 62 9b 7e 01 99 3d 18 f6 10 9a 38 61 9b 2e 57 |eb.~..=....8a..W|
00000200 e4 fa cc b1 8a ce e2 23 a0 87 f0 e1 67 51 eb 16 |.......#....gQ..|
-00000210 03 01 00 86 10 00 00 82 00 80 6d 51 f3 7f f9 3e |..........mQ...>|
-00000220 fb 75 82 41 36 83 e8 6a ee 2a 2e 25 90 67 4c 8e |.u.A6..j.*.%.gL.|
-00000230 62 2f 30 81 17 e0 85 09 0c 2b b7 23 d7 b0 e2 1d |b/0......+.#....|
-00000240 f7 3b d7 f5 a1 27 b6 ee 24 b6 1b cc 5b ea 66 0d |.;...'..$...[.f.|
-00000250 6a f4 e5 85 f9 da 43 b4 0e 86 85 e1 f5 aa be c8 |j.....C.........|
-00000260 ce 39 4c 9c 86 00 08 c2 4b e2 c6 ec 2f f7 ce e6 |.9L.....K.../...|
-00000270 bd 77 82 6f 23 b6 e0 bd a2 92 b7 3a ac e8 56 f1 |.w.o#......:..V.|
-00000280 af 54 5e 46 87 e9 3b 33 e7 b8 28 b7 d6 c8 90 35 |.T^F..;3..(....5|
-00000290 d4 1c 43 d1 30 6f 55 4e 0a 70 16 03 01 00 91 0f |..C.0oUN.p......|
-000002a0 00 00 8d 00 8b 30 81 88 02 42 00 b5 1a 9d 48 90 |.....0...B....H.|
-000002b0 2f d9 1a 04 66 f7 3b 4d d7 ae d9 1e dd 3c fa 24 |/...f.;M.....<.$|
-000002c0 0f 24 97 b2 61 46 16 d9 a0 35 f9 f7 54 45 92 fd |.$..aF...5..TE..|
-000002d0 10 56 ab 26 d7 b5 10 80 8b 88 95 ef c6 73 1c d2 |.V.&.........s..|
-000002e0 ff e9 20 cd 18 a8 40 c4 4d 83 c2 e2 02 42 01 8c |.. ...@.M....B..|
-000002f0 d2 13 4c cc e5 38 37 17 6c 83 d6 ad c1 dc af ec |..L..87.l.......|
-00000300 8d 06 75 b8 08 ad 56 4a 8f b9 03 59 80 f8 81 d4 |..u...VJ...Y....|
-00000310 f3 91 89 eb 9c 27 5d e1 dc 6d ef d6 20 da e7 9c |.....']..m.. ...|
-00000320 71 75 cb 2a f9 e4 05 46 c8 85 ca 7b 9c 97 e8 6d |qu.*...F...{...m|
-00000330 14 03 01 00 01 01 16 03 01 00 24 9f 67 4e 22 04 |..........$.gN".|
-00000340 10 f4 28 55 3e 50 88 90 61 07 42 29 f5 9b f5 32 |..(U>P..a.B)...2|
-00000350 16 3d ea c1 8f aa a1 4c b5 72 26 d8 32 cd 50 |.=.....L.r&.2.P|
+00000210 03 01 00 86 10 00 00 82 00 80 73 bd 73 65 92 86 |..........s.se..|
+00000220 23 41 14 79 7f d5 c1 10 ce 94 4d ad 9c c3 a9 87 |#A.y......M.....|
+00000230 b5 32 52 f8 6b 11 93 2d 9b 98 0b 8b 1d c0 f6 53 |.2R.k..-.......S|
+00000240 17 6d c7 9c 2e ae c9 6f cc 99 23 38 37 1a 10 fe |.m.....o..#87...|
+00000250 05 0b b5 55 0a 14 e9 60 7d 70 26 98 e2 54 d9 65 |...U...`}p&..T.e|
+00000260 cf 2e f4 53 5f 1d aa 3a f6 33 7b eb 4c 0e b3 ff |...S_..:.3{.L...|
+00000270 5a db 36 2a 47 f3 df f9 fc f5 31 78 83 aa 6b 52 |Z.6*G.....1x..kR|
+00000280 b7 ba 1a 96 bc fa c1 a1 a9 bb 2b f5 38 89 00 4d |..........+.8..M|
+00000290 e5 78 13 4e a4 38 46 42 dc 16 16 03 01 00 91 0f |.x.N.8FB........|
+000002a0 00 00 8d 00 8b 30 81 88 02 42 01 45 b9 8f b1 1f |.....0...B.E....|
+000002b0 72 80 2c 4f 2c 65 58 db 40 7e f1 d5 14 0b cc 4c |r.,O,eX.@~.....L|
+000002c0 8b 50 5c ee 93 45 95 3d fe 00 5e 5e ca 13 56 8d |.P\..E.=..^^..V.|
+000002d0 2b b3 1a 22 70 3f d2 41 cf 74 8f c3 0f 37 ba 97 |+.."p?.A.t...7..|
+000002e0 cb 29 16 77 92 df 19 35 f9 8a a0 8e 02 42 01 00 |.).w...5.....B..|
+000002f0 3f 8b ce b1 2a 01 43 e8 2c b5 27 d1 19 bc 04 b3 |?...*.C.,.'.....|
+00000300 c3 ad bf e8 12 37 57 6f c9 01 7c 8e f4 4d 88 39 |.....7Wo..|..M.9|
+00000310 4b 00 f6 ff fd 38 39 f8 3e 7f 49 d4 6a 82 94 6a |K....89.>.I.j..j|
+00000320 d3 f4 17 f2 a9 e0 ef 85 1e 01 85 b6 ca 89 91 ee |................|
+00000330 14 03 01 00 01 01 16 03 01 00 24 8d 82 24 82 55 |..........$..$.U|
+00000340 c4 0e 45 8c f0 f3 e3 29 4e ff 6c ee 43 4b ca 68 |..E....)N.l.CK.h|
+00000350 2e 12 98 cf ce b6 7e fa 73 07 e1 0f aa 7f 80 |......~.s......|
>>> Flow 4 (server to client)
-00000000 14 03 01 00 01 01 16 03 01 00 24 df 8d f1 07 6d |..........$....m|
-00000010 63 39 fc ba b1 67 3b 68 85 b9 37 7d d3 67 19 76 |c9...g;h..7}.g.v|
-00000020 34 a4 1b 86 31 bd fe 06 72 00 d8 2b f2 65 3d |4...1...r..+.e=|
+00000000 14 03 01 00 01 01 16 03 01 00 24 21 a3 eb a6 f5 |..........$!....|
+00000010 d0 17 38 9b 89 ec f3 39 23 33 f6 49 51 41 97 92 |..8....9#3.IQA..|
+00000020 a6 64 bd 60 68 9d 0e 45 06 2f dd ff 79 b6 50 |.d.`h..E./..y.P|
>>> Flow 5 (client to server)
-00000000 17 03 01 00 1a 60 cc 81 4f 8b 73 b3 7f 34 bf f1 |.....`..O.s..4..|
-00000010 7c d8 32 0a ef 2a 26 f9 b8 69 84 83 48 21 ee 15 ||.2..*&..i..H!..|
-00000020 03 01 00 16 23 7a 0c 65 3a 66 1a 75 03 e4 85 3f |....#z.e:f.u...?|
-00000030 83 cd 55 70 99 f4 44 dc 67 ba |..Up..D.g.|
+00000000 17 03 01 00 1a d2 72 d5 91 9d fc 6c 22 02 cc 32 |......r....l"..2|
+00000010 58 5c 8a f6 75 11 48 e1 3f e4 e5 81 29 63 62 15 |X\..u.H.?...)cb.|
+00000020 03 01 00 16 b6 9a 1f 43 d4 ae b7 16 25 ce ae b7 |.......C....%...|
+00000030 6c 37 f7 35 0a 26 7d ea 1f 80 |l7.5.&}...|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 81 01 00 00 7d 03 03 00 00 00 00 00 |........}.......|
+00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 22 c0 2f |............."./|
00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 36 |...../.5.......6|
-00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
-00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
-00000070 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
-00000080 01 00 00 12 00 00 |......|
+00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
+00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
+00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
+00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
+00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
>>> Flow 2 (server to client)
-00000000 16 03 01 00 59 02 00 00 55 03 01 dc a9 22 c2 a2 |....Y...U...."..|
-00000010 05 ba c4 66 9a 71 aa 0f 92 6a fc df b0 29 4d 36 |...f.q...j...)M6|
-00000020 39 2e f8 39 ed 8e f6 7f 8f 17 13 20 f8 9c f3 3d |9..9....... ...=|
-00000030 0a 41 8f 30 c7 5d cd 17 c5 ad 1c 52 45 a3 47 8c |.A.0.].....RE.G.|
-00000040 07 4c 48 e1 00 2b 32 38 01 c8 79 b7 c0 09 00 00 |.LH..+28..y.....|
+00000000 16 03 01 00 59 02 00 00 55 03 01 eb ed 76 6a 07 |....Y...U....vj.|
+00000010 65 02 ec 6f 93 a0 38 21 09 0d d7 bf 11 20 51 eb |e..o..8!..... Q.|
+00000020 cc 00 08 9b 7a 98 c4 c5 02 ff c1 20 f9 1b c7 66 |....z...... ...f|
+00000030 35 40 8c 67 8d 7f d5 c8 28 f0 cb d2 f9 da af 7a |5@.g....(......z|
+00000040 ea 4e 42 f2 5d 44 1c cc 92 36 b1 10 c0 09 00 00 |.NB.]D...6......|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
00000060 01 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..|
00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....|
00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....|
00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.|
00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....|
-00000270 2a 16 03 01 00 d5 0c 00 00 d1 03 00 17 41 04 89 |*............A..|
-00000280 95 9a 90 82 59 ab 29 bf 10 06 8c 6c 0d 67 cf b1 |....Y.)....l.g..|
-00000290 66 8b 5e 43 b8 46 56 3a 8d 30 92 35 28 82 f2 38 |f.^C.FV:.0.5(..8|
-000002a0 6e 19 5d 37 f0 ab fc 78 15 6a 6a 73 ca dc a6 f2 |n.]7...x.jjs....|
-000002b0 68 5d b3 ab 6d 68 44 3b 80 d2 d9 cd 78 0a ed 00 |h]..mhD;....x...|
-000002c0 8a 30 81 87 02 42 01 80 63 4a 22 4c 8e 66 4e 25 |.0...B..cJ"L.fN%|
-000002d0 e1 86 27 81 de eb b3 a0 c4 dc dc e2 a0 94 2a b6 |..'...........*.|
-000002e0 b3 e9 e7 42 e1 1d 1a c0 43 8d a1 d6 8d 77 84 06 |...B....C....w..|
-000002f0 ba 95 99 e3 54 80 59 4e 3c fb 0c f3 b7 d3 a8 d2 |....T.YN<.......|
-00000300 ce 49 97 fb e2 79 91 93 02 41 2b 2c b7 9f 81 ea |.I...y...A+,....|
-00000310 de 17 12 af 4d 20 bc a1 43 1d 60 a0 37 52 a2 7b |....M ..C.`.7R.{|
-00000320 a8 4c de fd 1d fe 37 3b 00 23 61 ce d2 80 47 43 |.L....7;.#a...GC|
-00000330 b0 3a f3 1f aa c7 07 b1 68 5b d8 f3 03 a9 56 5c |.:......h[....V\|
-00000340 63 ef 83 1d 9c 9c 8d 29 81 e9 3b 16 03 01 00 0e |c......)..;.....|
+00000270 2a 16 03 01 00 d5 0c 00 00 d1 03 00 17 41 04 34 |*............A.4|
+00000280 47 57 64 b3 20 6d eb 17 9c 36 d4 aa 78 8b 20 26 |GWd. m...6..x. &|
+00000290 6f 22 10 79 5f 96 69 62 1d ae 9f c7 40 17 1e 30 |o".y_.ib....@..0|
+000002a0 10 db d1 13 51 d8 63 61 ef 8e fb 34 d6 02 95 ac |....Q.ca...4....|
+000002b0 fb 33 72 a9 46 ff 27 b1 15 ca dd 81 8f 5a 58 00 |.3r.F.'......ZX.|
+000002c0 8a 30 81 87 02 41 5c 09 1a 87 40 f3 1a 87 84 31 |.0...A\...@....1|
+000002d0 62 6c e5 a5 c0 3c cc ba 5d 4a 5e 65 ea e0 60 83 |bl...<..]J^e..`.|
+000002e0 fe fe 99 1d 66 4a bb 6c 0d 5e 25 64 e3 92 ce eb |....fJ.l.^%d....|
+000002f0 15 39 42 a6 b0 98 a1 d3 79 65 c7 fc e7 c7 64 c7 |.9B.....ye....d.|
+00000300 69 9c 2f 7e 00 c1 a3 02 42 01 f2 61 91 ae 8e f6 |i./~....B..a....|
+00000310 88 99 70 55 32 4a fe 08 31 f0 8d d6 e6 1d fa a1 |..pU2J..1.......|
+00000320 76 b6 16 98 58 8e 46 30 b1 00 b6 dd 5d 70 bb e1 |v...X.F0....]p..|
+00000330 81 89 bd aa ac b5 7f 9b d3 c0 8b 4b c3 36 00 87 |...........K.6..|
+00000340 47 0c 34 92 27 c3 aa bd 0d 7c 36 16 03 01 00 0e |G.4.'....|6.....|
00000350 0d 00 00 06 03 01 02 40 00 00 0e 00 00 00 |.......@......|
>>> Flow 3 (client to server)
00000000 16 03 01 01 fb 0b 00 01 f7 00 01 f4 00 01 f1 30 |...............0|
00000220 a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e |.$ >.V...(^.+-O.|
00000230 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I|
00000240 a6 b5 68 1a 41 03 56 6b dc 5a 89 16 03 01 00 86 |..h.A.Vk.Z......|
-00000250 0f 00 00 82 00 80 0e 80 9c 3a 6e 40 51 09 39 d4 |.........:n@Q.9.|
-00000260 40 58 10 da 7f 32 12 08 9e f0 4d 9a d7 20 a2 9c |@X...2....M.. ..|
-00000270 b0 95 3a 33 4e f8 b1 a3 74 62 ab 51 7d 23 d4 32 |..:3N...tb.Q}#.2|
-00000280 a2 af b8 5a 3b b0 23 e4 7a f1 eb 4d b7 bb 23 d5 |...Z;.#.z..M..#.|
-00000290 a9 0d b4 81 d2 b4 45 bd 15 52 ad 58 da 92 a2 c4 |......E..R.X....|
-000002a0 30 66 87 f2 ae c5 e4 8c fa ba a0 40 76 b8 3f 72 |0f.........@v.?r|
-000002b0 2a d9 95 2a 2d c6 05 3c 1e 2f 11 ef c5 3c 11 e4 |*..*-..<./...<..|
-000002c0 be 5a de 37 43 7f 74 52 6e ee 3c 39 cc f1 14 05 |.Z.7C.tRn.<9....|
-000002d0 2d 91 c2 3d c4 7c 14 03 01 00 01 01 16 03 01 00 |-..=.|..........|
-000002e0 30 cd 3c 92 f8 b9 36 7a e7 8a fb 0f 2f b8 2c 7b |0.<...6z..../.,{|
-000002f0 10 59 45 14 0a b0 6a 8c 31 b2 89 5b ac 19 dc 12 |.YE...j.1..[....|
-00000300 73 8c 8c 10 49 5a bf 9f bc 58 82 32 11 ba c5 38 |s...IZ...X.2...8|
-00000310 ff |.|
+00000250 0f 00 00 82 00 80 1e 4d 89 4e e2 82 ca 5d 31 8a |.......M.N...]1.|
+00000260 66 c7 c2 d6 00 4d 2e 1e 94 34 61 6b 86 3d 78 60 |f....M...4ak.=x`|
+00000270 70 e1 71 93 22 df 5d 81 d3 d7 33 10 f5 01 f9 1d |p.q.".]...3.....|
+00000280 e2 4a 91 22 67 ae 5b 2f 4c d9 43 31 35 c6 01 ad |.J."g.[/L.C15...|
+00000290 59 86 03 a1 9b c5 ea a5 2d aa ef 46 5a a8 70 57 |Y.......-..FZ.pW|
+000002a0 50 59 ea 7a 07 32 bb a6 a1 11 33 05 d8 88 2e 42 |PY.z.2....3....B|
+000002b0 d8 7b f7 34 be 5e 5f 42 9f 6a 90 ed d7 4b c4 7e |.{.4.^_B.j...K.~|
+000002c0 f9 5c a5 ff 28 f8 a1 f1 8f 1c e0 7a 37 a0 49 e5 |.\..(......z7.I.|
+000002d0 ce 11 46 ef 5f 06 14 03 01 00 01 01 16 03 01 00 |..F._...........|
+000002e0 30 cb 08 f0 3c d4 21 f2 3a 7d db 59 75 80 48 24 |0...<.!.:}.Yu.H$|
+000002f0 27 6f 2c 26 50 a4 7d 6c 91 d5 5d f7 c9 b4 bd 15 |'o,&P.}l..].....|
+00000300 a8 8a 12 d5 40 8c 9a 0f 56 67 66 89 dd 12 36 d8 |....@...Vgf...6.|
+00000310 d3 |.|
>>> Flow 4 (server to client)
-00000000 14 03 01 00 01 01 16 03 01 00 30 da 45 99 fe 52 |..........0.E..R|
-00000010 4f cd d0 e6 30 19 f4 bd 80 6d 5c 8a 72 03 d3 88 |O...0....m\.r...|
-00000020 38 63 e9 c9 39 ee ab 3f 52 26 84 b0 4d cb 5c a4 |8c..9..?R&..M.\.|
-00000030 0d 51 c7 47 48 43 3a bf 89 c7 13 |.Q.GHC:....|
+00000000 14 03 01 00 01 01 16 03 01 00 30 02 e3 be 9d 2d |..........0....-|
+00000010 6f 2c 9a b7 b4 f1 a5 30 ec 3e ae 05 e6 02 19 2f |o,.....0.>...../|
+00000020 a4 ac d1 6e ac de 75 4e cc 14 e6 78 5a ea 27 7f |...n..uN...xZ.'.|
+00000030 4e 45 c4 9d b2 da a6 ea b7 d2 7e |NE........~|
>>> Flow 5 (client to server)
-00000000 17 03 01 00 20 4d d9 1d 0d 3d 8b 73 91 b9 4e 5e |.... M...=.s..N^|
-00000010 35 71 4f 67 79 d2 f7 39 35 ea 23 d0 6d 64 de a5 |5qOgy..95.#.md..|
-00000020 59 fb 75 1f c9 17 03 01 00 20 ba bd 3c b4 d7 be |Y.u...... ..<...|
-00000030 24 64 68 1e 8c b2 bf 6f 78 9f ad 7f fa dd 89 a6 |$dh....ox.......|
-00000040 f9 e7 5e 70 db e9 db 3a 62 b2 15 03 01 00 20 2a |..^p...:b..... *|
-00000050 82 f4 8b 45 fc 76 35 6c 54 48 62 2f 52 55 f2 d9 |...E.v5lTHb/RU..|
-00000060 99 b2 b5 2d 5f a0 05 ab f1 93 58 75 4a 87 35 |...-_.....XuJ.5|
+00000000 17 03 01 00 20 e0 71 e9 54 11 6e 48 4b be a2 2a |.... .q.T.nHK..*|
+00000010 b1 70 d2 2c 74 c0 f4 74 05 f1 d3 d6 84 29 58 f7 |.p.,t..t.....)X.|
+00000020 87 90 84 2b c8 17 03 01 00 20 b6 a2 e9 e0 f0 0d |...+..... ......|
+00000030 d5 ef d7 32 6d cb 99 5d a6 37 c2 6e f9 c3 8e 6f |...2m..].7.n...o|
+00000040 76 71 d8 a6 c5 ae 4e 04 77 06 15 03 01 00 20 f2 |vq....N.w..... .|
+00000050 09 ab dc 37 90 78 3a 2a 41 ab 9b a9 c1 78 2a 64 |...7.x:*A....x*d|
+00000060 a8 3f 21 c4 bb af 76 b3 c6 2f e1 20 a3 b1 1e |.?!...v../. ...|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 81 01 00 00 7d 03 03 00 00 00 00 00 |........}.......|
+00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 22 c0 2f |............."./|
00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 36 |...../.5.......6|
-00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
-00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
-00000070 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
-00000080 01 00 00 12 00 00 |......|
+00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
+00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
+00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
+00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
+00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
>>> Flow 2 (server to client)
-00000000 16 03 01 00 51 02 00 00 4d 03 01 90 e6 e1 c6 bd |....Q...M.......|
-00000010 86 08 db 33 94 f3 bd 0b 2d fc e0 ba 89 a7 c5 66 |...3....-......f|
-00000020 a5 19 78 33 2b b9 c4 22 d8 e0 63 20 2e 85 53 25 |..x3+.."..c ..S%|
-00000030 f2 22 e3 ca 79 94 9e 50 00 13 da 9d 21 33 49 27 |."..y..P....!3I'|
-00000040 9b 44 c5 10 bc e8 44 01 04 31 02 81 00 05 00 00 |.D....D..1......|
-00000050 05 ff 01 00 01 00 16 03 01 02 be 0b 00 02 ba 00 |................|
-00000060 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......|
-00000070 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..|
-00000080 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 45 31 0b |.*.H........0E1.|
-00000090 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..|
-000000a0 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State|
-000000b0 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter|
-000000c0 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty |
-000000d0 4c 74 64 30 1e 17 0d 31 30 30 34 32 34 30 39 30 |Ltd0...100424090|
-000000e0 39 33 38 5a 17 0d 31 31 30 34 32 34 30 39 30 39 |938Z..1104240909|
-000000f0 33 38 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 |38Z0E1.0...U....|
-00000100 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som|
-00000110 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..|
-00000120 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi|
-00000130 74 73 20 50 74 79 20 4c 74 64 30 81 9f 30 0d 06 |ts Pty Ltd0..0..|
-00000140 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 |.*.H............|
-00000150 30 81 89 02 81 81 00 bb 79 d6 f5 17 b5 e5 bf 46 |0.......y......F|
-00000160 10 d0 dc 69 be e6 2b 07 43 5a d0 03 2d 8a 7a 43 |...i..+.CZ..-.zC|
-00000170 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 8c b5 b4 82 |...R..eL,x.#....|
-00000180 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 fe 12 5c 7a |....;~b.,.3...\z|
-00000190 56 fc f5 06 bf fa 58 7b 26 3f b5 cd 04 d3 d0 c9 |V.....X{&?......|
-000001a0 21 96 4a c7 f4 54 9f 5a bf ef 42 71 00 fe 18 99 |!.J..T.Z..Bq....|
-000001b0 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e db 51 c9 7c |..~.}}..9....Q.||
-000001c0 e3 c0 4c 3b 32 66 01 cf af b1 1d b8 71 9a 1d db |..L;2f......q...|
-000001d0 db 89 6b ae da 2d 79 02 03 01 00 01 a3 81 a7 30 |..k..-y........0|
-000001e0 81 a4 30 1d 06 03 55 1d 0e 04 16 04 14 b1 ad e2 |..0...U.........|
-000001f0 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 88 |.Z..(.i.#i..&...|
-00000200 39 30 75 06 03 55 1d 23 04 6e 30 6c 80 14 b1 ad |90u..U.#.n0l....|
-00000210 e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 |..Z..(.i.#i..&..|
-00000220 88 39 a1 49 a4 47 30 45 31 0b 30 09 06 03 55 04 |.9.I.G0E1.0...U.|
-00000230 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 0a |...AU1.0...U....|
-00000240 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 |Some-State1!0...|
-00000250 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 |U....Internet Wi|
-00000260 64 67 69 74 73 20 50 74 79 20 4c 74 64 82 09 00 |dgits Pty Ltd...|
-00000270 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 55 1d 13 04 |........0...U...|
-00000280 05 30 03 01 01 ff 30 0d 06 09 2a 86 48 86 f7 0d |.0....0...*.H...|
-00000290 01 01 05 05 00 03 81 81 00 08 6c 45 24 c7 6b b1 |..........lE$.k.|
-000002a0 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a 64 75 b5 5a |Y..R.......zdu.Z|
-000002b0 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f 38 b3 6e 60 |.f..+...f..O8.n`|
-000002c0 d3 92 fd f7 41 08 b5 25 13 b1 18 7a 24 fb 30 1d |....A..%...z$.0.|
-000002d0 ba ed 98 b9 17 ec e7 d7 31 59 db 95 d3 1d 78 ea |........1Y....x.|
-000002e0 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 90 |PV\..Z-Z_3....u.|
-000002f0 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c a3 |...R...... _....|
-00000300 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b 26 |......W.p.&mq..&|
-00000310 6e 38 50 29 6c 90 a7 bd d9 16 03 01 00 0e 0d 00 |n8P)l...........|
-00000320 00 06 03 01 02 40 00 00 0e 00 00 00 |.....@......|
+00000000 16 03 01 00 51 02 00 00 4d 03 01 e5 d7 4b 56 7b |....Q...M....KV{|
+00000010 a8 2c 07 33 fc 66 d7 79 e9 26 91 56 7d 9d 99 1d |.,.3.f.y.&.V}...|
+00000020 b2 24 36 2c f6 78 3a e7 63 15 f6 20 9f e1 d4 07 |.$6,.x:.c.. ....|
+00000030 a9 75 3d b9 3b 8c 46 cb a7 37 36 56 af 4e 99 cf |.u=.;.F..76V.N..|
+00000040 90 49 e1 e9 69 25 81 0f fd 22 48 e6 00 05 00 00 |.I..i%..."H.....|
+00000050 05 ff 01 00 01 00 16 03 01 02 71 0b 00 02 6d 00 |..........q...m.|
+00000060 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
+00000070 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
+00000080 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
+00000090 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
+000000a0 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
+000000b0 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
+000000c0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
+000000d0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
+000000e0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
+000000f0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
+00000100 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
+00000110 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
+00000120 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
+00000130 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
+00000140 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
+00000150 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
+00000160 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
+00000170 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
+00000180 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
+00000190 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
+000001a0 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
+000001b0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
+000001c0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
+000001d0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
+000001e0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
+000001f0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
+00000200 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
+00000210 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
+00000220 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
+00000230 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
+00000240 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
+00000250 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
+00000260 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
+00000270 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
+00000280 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
+00000290 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
+000002a0 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
+000002b0 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
+000002c0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 01 00 |..A4......9.....|
+000002d0 0e 0d 00 00 06 03 01 02 40 00 00 0e 00 00 00 |........@......|
>>> Flow 3 (client to server)
00000000 16 03 01 01 fb 0b 00 01 f7 00 01 f4 00 01 f1 30 |...............0|
00000010 82 01 ed 30 82 01 58 a0 03 02 01 02 02 01 00 30 |...0..X........0|
000001d0 8b ec ab 67 be c8 64 b0 11 50 46 58 17 6b 99 1c |...g..d..PFX.k..|
000001e0 d3 1d fc 06 f1 0e e5 96 a8 0c f9 78 20 b7 44 18 |...........x .D.|
000001f0 51 8d 10 7e 4f 94 67 df a3 4e 70 73 8e 90 91 85 |Q..~O.g..Nps....|
-00000200 16 03 01 00 86 10 00 00 82 00 80 6d 51 f3 7f f9 |...........mQ...|
-00000210 3e fb 75 82 41 36 83 e8 6a ee 2a 2e 25 90 67 4c |>.u.A6..j.*.%.gL|
-00000220 8e 62 2f 30 81 17 e0 85 09 0c 2b b7 23 d7 b0 e2 |.b/0......+.#...|
-00000230 1d f7 3b d7 f5 a1 27 b6 ee 24 b6 1b cc 5b ea 66 |..;...'..$...[.f|
-00000240 0d 6a f4 e5 85 f9 da 43 b4 0e 86 85 e1 f5 aa be |.j.....C........|
-00000250 c8 ce 39 4c 9c 86 00 08 c2 4b e2 c6 ec 2f f7 ce |..9L.....K.../..|
-00000260 e6 bd 77 82 6f 23 b6 e0 bd a2 92 b7 3a ac e8 56 |..w.o#......:..V|
-00000270 f1 af 54 5e 46 87 e9 3b 33 e7 b8 28 b7 d6 c8 90 |..T^F..;3..(....|
-00000280 35 d4 1c 43 d1 30 6f 55 4e 0a 70 16 03 01 00 86 |5..C.0oUN.p.....|
-00000290 0f 00 00 82 00 80 10 19 57 14 c3 ee 2d da cb de |........W...-...|
-000002a0 f3 70 c5 62 91 2f ad 62 dd 10 f1 65 20 a2 cf d5 |.p.b./.b...e ...|
-000002b0 cd 6d 5f e4 b3 3e 38 e8 d0 1a f7 f0 e7 7e b6 5d |.m_..>8......~.]|
-000002c0 c3 6c ad f6 0d 05 1e 41 35 2d 04 15 3c 36 96 00 |.l.....A5-..<6..|
-000002d0 e8 02 b2 01 b8 9f 21 4b 34 85 ef 5e 4c 87 ef 49 |......!K4..^L..I|
-000002e0 df d1 9a b6 b2 bd b8 90 fd 3f 31 93 0c dc c7 18 |.........?1.....|
-000002f0 ff f6 76 bd 5b 74 76 b3 62 87 6a df ff 63 15 d5 |..v.[tv.b.j..c..|
-00000300 94 d5 fe fd 4c 12 df f1 35 07 f1 8a f1 77 7a 35 |....L...5....wz5|
-00000310 cd 99 1d 2a d7 9a 14 03 01 00 01 01 16 03 01 00 |...*............|
-00000320 24 8d db 0c 87 b5 df fd 68 de fe 46 3e e4 41 b5 |$.......h..F>.A.|
-00000330 19 64 68 3c c4 e2 2b 43 50 e4 ee 52 75 34 d3 c1 |.dh<..+CP..Ru4..|
-00000340 51 18 c0 b2 5f |Q..._|
+00000200 16 03 01 00 86 10 00 00 82 00 80 73 bd 73 65 92 |...........s.se.|
+00000210 86 23 41 14 79 7f d5 c1 10 ce 94 4d ad 9c c3 a9 |.#A.y......M....|
+00000220 87 b5 32 52 f8 6b 11 93 2d 9b 98 0b 8b 1d c0 f6 |..2R.k..-.......|
+00000230 53 17 6d c7 9c 2e ae c9 6f cc 99 23 38 37 1a 10 |S.m.....o..#87..|
+00000240 fe 05 0b b5 55 0a 14 e9 60 7d 70 26 98 e2 54 d9 |....U...`}p&..T.|
+00000250 65 cf 2e f4 53 5f 1d aa 3a f6 33 7b eb 4c 0e b3 |e...S_..:.3{.L..|
+00000260 ff 5a db 36 2a 47 f3 df f9 fc f5 31 78 83 aa 6b |.Z.6*G.....1x..k|
+00000270 52 b7 ba 1a 96 bc fa c1 a1 a9 bb 2b f5 38 89 00 |R..........+.8..|
+00000280 4d e5 78 13 4e a4 38 46 42 dc 16 16 03 01 00 86 |M.x.N.8FB.......|
+00000290 0f 00 00 82 00 80 3d f7 ff c1 72 82 b8 90 42 a3 |......=...r...B.|
+000002a0 10 24 b5 01 44 60 98 39 e4 36 86 56 09 55 e5 73 |.$..D`.9.6.V.U.s|
+000002b0 3a d9 9d 00 ae 05 23 6f 78 4e 49 28 c1 cc 7a ff |:.....#oxNI(..z.|
+000002c0 8f 67 92 cd 94 c0 d2 68 7f 48 ec 10 83 48 9e 02 |.g.....h.H...H..|
+000002d0 b8 10 b2 1b f0 ba 8f 5a c8 85 d9 19 53 c2 8d 37 |.......Z....S..7|
+000002e0 8e 86 4c ca ee 0f c4 97 20 f9 a5 4e 94 b8 c5 c5 |..L..... ..N....|
+000002f0 53 0c c1 b6 e5 a1 4e d6 15 b3 6b 08 c2 25 c3 de |S.....N...k..%..|
+00000300 e7 69 85 85 56 31 16 ad 68 7e 00 8f 1b fc f8 9f |.i..V1..h~......|
+00000310 d7 50 87 08 0d c5 14 03 01 00 01 01 16 03 01 00 |.P..............|
+00000320 24 eb 0c f3 4f 56 04 e3 54 b0 a8 e4 bb af 3a 44 |$...OV..T.....:D|
+00000330 c7 d6 f0 24 2f fc e6 79 93 f4 4e ec c5 1f 5b 99 |...$/..y..N...[.|
+00000340 32 37 c2 f1 ad |27...|
>>> Flow 4 (server to client)
-00000000 14 03 01 00 01 01 16 03 01 00 24 0b a4 04 46 60 |..........$...F`|
-00000010 15 fb 9a 9f 47 51 6d b4 4b c6 e7 2a 1b 98 b4 8a |....GQm.K..*....|
-00000020 8a 1a 03 cf f4 16 7d 80 70 27 e5 e8 d5 9f ad |......}.p'.....|
+00000000 14 03 01 00 01 01 16 03 01 00 24 75 ac 09 a6 28 |..........$u...(|
+00000010 60 ce 7f 81 a2 75 86 af 84 95 dc 3f e1 07 1c 02 |`....u.....?....|
+00000020 bc 3c 90 db 1e 1a 35 06 93 60 22 69 b9 05 bb |.<....5..`"i...|
>>> Flow 5 (client to server)
-00000000 17 03 01 00 1a 6f 84 50 27 c7 f1 aa b0 04 7d 80 |.....o.P'.....}.|
-00000010 6d a7 20 8a 73 cf d9 de 9a d6 f5 e9 36 13 7c 15 |m. .s.......6.|.|
-00000020 03 01 00 16 e8 0b e0 a6 3b 1e 21 24 65 4e 49 b2 |........;.!$eNI.|
-00000030 2d a3 41 2b 98 23 4e d5 4b fd |-.A+.#N.K.|
+00000000 17 03 01 00 1a f4 67 a7 d8 0a 67 8d 3a 11 53 7e |......g...g.:.S~|
+00000010 49 91 bf 92 85 e0 35 24 25 72 92 26 63 9b 09 15 |I.....5$%r.&c...|
+00000020 03 01 00 16 98 bb a0 ca 40 70 26 6f 2d 73 35 3d |........@p&o-s5=|
+00000030 90 8c ff 01 e0 b1 50 52 e3 57 |......PR.W|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 81 01 00 00 7d 03 03 00 00 00 00 00 |........}.......|
+00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 22 c0 2f |............."./|
00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 36 |...../.5.......6|
-00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
-00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
-00000070 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
-00000080 01 00 00 12 00 00 |......|
+00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
+00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
+00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
+00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
+00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
>>> Flow 2 (server to client)
-00000000 16 03 01 00 59 02 00 00 55 03 01 f5 8f 8d 8e ca |....Y...U.......|
-00000010 30 6b fe 63 c9 84 57 c0 f1 c8 a5 d8 10 56 14 62 |0k.c..W......V.b|
-00000020 c8 02 b2 89 21 5c 09 67 86 d8 9b 20 dc 3f 55 54 |....!\.g... .?UT|
-00000030 33 29 47 45 d3 e0 87 1a 4b 1b 75 30 89 e0 4d 01 |3)GE....K.u0..M.|
-00000040 a1 6a 46 f7 8f 23 d6 74 fd 90 2f 53 c0 09 00 00 |.jF..#.t../S....|
+00000000 16 03 01 00 59 02 00 00 55 03 01 78 09 57 86 09 |....Y...U..x.W..|
+00000010 64 7e 35 c7 c7 b9 44 9c 09 ae f0 49 cb 1c 1f 58 |d~5...D....I...X|
+00000020 89 ef 65 16 9e 32 73 cd 4d 1b 8f 20 10 4d 5b cf |..e..2s.M.. .M[.|
+00000030 d0 24 59 dd e8 47 c9 a2 ad 9c 98 b5 eb 16 46 6b |.$Y..G........Fk|
+00000040 7d 33 6e 53 0a 3d 81 71 a1 bc 43 7a c0 09 00 00 |}3nS.=.q..Cz....|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
00000060 01 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..|
00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....|
00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....|
00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.|
00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....|
-00000270 2a 16 03 01 00 d5 0c 00 00 d1 03 00 17 41 04 22 |*............A."|
-00000280 8a 47 c6 d3 7a c4 30 a4 8e 41 11 ac b3 2d 2f 45 |.G..z.0..A...-/E|
-00000290 61 54 9b 1f 2e 03 5d 50 eb fc 5b 44 a0 a7 48 78 |aT....]P..[D..Hx|
-000002a0 ce 14 d5 39 a7 c4 ed f5 4d 8f da 9d 71 52 69 70 |...9....M...qRip|
-000002b0 7e 52 29 ad 80 8a 19 ad 4c 5d 1c f1 22 7e 1a 00 |~R).....L].."~..|
-000002c0 8a 30 81 87 02 42 00 97 8b 6d f7 87 c1 a9 a6 55 |.0...B...m.....U|
-000002d0 0f 61 c2 f2 e1 05 26 a8 83 16 1c 0b 69 3b 95 57 |.a....&.....i;.W|
-000002e0 76 5b eb 45 7a bd 6a f1 3e a0 93 49 fa 74 32 fd |v[.Ez.j.>..I.t2.|
-000002f0 dc 20 3a bb e3 ee 6d b8 56 aa e9 d2 7d 6a ec b7 |. :...m.V...}j..|
-00000300 0a bd aa dc d7 b0 69 65 02 41 4d 19 61 16 d8 5f |......ie.AM.a.._|
-00000310 1d c1 32 25 15 26 eb 88 5b c1 dd 9a 12 40 fa f1 |..2%.&..[....@..|
-00000320 81 5e 7d b8 2b 6e 60 63 1a 9e 86 cb d5 64 96 d4 |.^}.+n`c.....d..|
-00000330 75 fc 02 33 e0 66 60 b2 40 47 cf e6 6d 25 9c 83 |u..3.f`.@G..m%..|
-00000340 23 d3 4b e2 eb ac f1 56 44 f8 3f 16 03 01 00 04 |#.K....VD.?.....|
-00000350 0e 00 00 00 |....|
+00000270 2a 16 03 01 00 d6 0c 00 00 d2 03 00 17 41 04 51 |*............A.Q|
+00000280 39 70 43 9c 01 de 29 df 3c d0 f8 31 54 70 34 53 |9pC...).<..1Tp4S|
+00000290 0e ab e8 e0 b0 8b 21 66 63 ac a9 68 7c 92 6f f8 |......!fc..h|.o.|
+000002a0 cf a3 ba cb 6d 39 f4 5c f5 2e ff 1d d7 1b b9 e7 |....m9.\........|
+000002b0 08 13 59 f8 64 7e 23 e0 1d 04 cf 37 47 d6 b7 00 |..Y.d~#....7G...|
+000002c0 8b 30 81 88 02 42 01 cd 1d 01 46 68 da 4c b6 0d |.0...B....Fh.L..|
+000002d0 67 05 39 0d aa 6c c5 40 e4 5d bf 4f 2a 92 78 8d |g.9..l.@.].O*.x.|
+000002e0 08 0e c0 07 8c 68 cc 55 4e 54 a9 9d 22 f9 a6 4a |.....h.UNT.."..J|
+000002f0 e4 38 9f 53 4a 60 e8 eb 81 02 50 75 7e 13 31 2a |.8.SJ`....Pu~.1*|
+00000300 ff 3e 17 cd b4 d1 d4 75 02 42 01 95 ba b6 a0 12 |.>.....u.B......|
+00000310 23 59 9f ae 1c c0 60 d2 8f 59 6b 35 ee b3 3f ac |#Y....`..Yk5..?.|
+00000320 e4 42 9a 23 d0 f4 fd a1 3c 36 1b 31 33 76 8d f0 |.B.#....<6.13v..|
+00000330 b6 66 fd 92 9a 2a 27 8b 06 11 72 41 09 bd 27 55 |.f...*'...rA..'U|
+00000340 c7 1b a9 d1 49 5e 8f 85 dc aa 9d be 16 03 01 00 |....I^..........|
+00000350 04 0e 00 00 00 |.....|
>>> Flow 3 (client to server)
00000000 16 03 01 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..|
00000010 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.|
00000020 a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e |.$ >.V...(^.+-O.|
00000030 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I|
00000040 a6 b5 68 1a 41 03 56 6b dc 5a 89 14 03 01 00 01 |..h.A.Vk.Z......|
-00000050 01 16 03 01 00 30 cc 86 f1 7e 6e a8 c9 b5 02 5f |.....0...~n...._|
-00000060 fb b2 3b ea 74 bf a8 da e4 6a 69 50 a2 5a 78 4f |..;.t....jiP.ZxO|
-00000070 35 e1 cc 87 c3 fb 1f 5e f6 a4 5c 63 cc 59 12 3e |5......^..\c.Y.>|
-00000080 07 c3 a8 d7 87 ba |......|
+00000050 01 16 03 01 00 30 64 61 7f ea 98 8e e7 c9 0f ea |.....0da........|
+00000060 0a b3 52 ba 3d 01 36 a4 47 24 7b 2d 19 b5 7e 92 |..R.=.6.G${-..~.|
+00000070 04 b7 8c 4f fc 02 5d 79 15 3e 50 72 05 3c df d2 |...O..]y.>Pr.<..|
+00000080 c6 a3 b3 c8 7c 48 |....|H|
>>> Flow 4 (server to client)
-00000000 14 03 01 00 01 01 16 03 01 00 30 e8 b6 20 b9 c1 |..........0.. ..|
-00000010 07 38 38 bb 42 b2 b2 a1 c5 8d 92 62 db 67 ab fc |.88.B......b.g..|
-00000020 f6 64 3f 71 83 1d a0 86 bb 2d e3 4f 65 d5 44 52 |.d?q.....-.Oe.DR|
-00000030 4d f5 62 80 3c af 95 87 19 7c 20 |M.b.<....| |
+00000000 14 03 01 00 01 01 16 03 01 00 30 7d 49 8d e9 da |..........0}I...|
+00000010 87 77 18 4d 10 63 17 ed 1f 34 7a d4 be e3 dd b6 |.w.M.c...4z.....|
+00000020 8b f3 a7 06 bc de 76 8e 04 be 8a 95 5b 24 19 ec |......v.....[$..|
+00000030 66 55 8a 1b e0 df 0b a1 57 cb 67 |fU......W.g|
>>> Flow 5 (client to server)
-00000000 17 03 01 00 20 bd 65 61 28 e5 ea 1b 81 db 75 92 |.... .ea(.....u.|
-00000010 ad a7 3b 01 a3 23 0e 3b 60 10 8a 1e 04 91 fb 9e |..;..#.;`.......|
-00000020 7a cf 1f cf 9c 17 03 01 00 20 87 9c dc ed 0d 08 |z........ ......|
-00000030 56 40 23 8b c5 2c d8 7e 42 82 3c 0a c9 f3 77 6d |V@#..,.~B.<...wm|
-00000040 8d 9a 30 d1 9c c4 ae 04 fb b7 15 03 01 00 20 f7 |..0........... .|
-00000050 f0 12 0d e5 03 c1 80 4e 7e 21 d7 75 55 1c 91 89 |.......N~!.uU...|
-00000060 e7 e1 45 fc 7d d8 fc b1 d0 e7 dc e2 4c ba f4 |..E.}.......L..|
+00000000 17 03 01 00 20 2d a3 e5 55 13 3f 73 8e ba 41 79 |.... -..U.?s..Ay|
+00000010 65 e0 83 d5 3a ea cd e9 a8 b4 4b 3c d0 0c bf 06 |e...:.....K<....|
+00000020 75 2a 67 f2 f7 17 03 01 00 20 a0 8d 3c a2 ca b3 |u*g...... ..<...|
+00000030 f3 e5 36 dc 44 a4 3b ad cd 03 be a9 70 a8 75 51 |..6.D.;.....p.uQ|
+00000040 0f 8e 9f 7c a7 3c 03 84 38 88 15 03 01 00 20 75 |...|.<..8..... u|
+00000050 0f db fe 48 b4 7e 04 3b f5 5b 47 5b 0a ab 69 18 |...H.~.;.[G[..i.|
+00000060 37 bb 89 d3 a8 40 ba 53 3b 5f 6d 8b 06 ff ae |7....@.S;_m....|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 81 01 00 00 7d 03 03 00 00 00 00 00 |........}.......|
+00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 22 c0 2f |............."./|
00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 36 |...../.5.......6|
-00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
-00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
-00000070 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
-00000080 01 00 00 12 00 00 |......|
+00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
+00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
+00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
+00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
+00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
>>> Flow 2 (server to client)
-00000000 16 03 01 00 59 02 00 00 55 03 01 5c 69 d0 60 d6 |....Y...U..\i.`.|
-00000010 b3 f4 23 19 5e 3e 26 d8 29 ea c3 94 e4 ed 51 f6 |..#.^>&.).....Q.|
-00000020 58 a2 e3 9c 79 a1 0b 6d 29 90 32 20 23 5b 47 b1 |X...y..m).2 #[G.|
-00000030 8f 22 bc 06 aa ee f7 c3 97 ca 93 df b1 90 7d b4 |."............}.|
-00000040 8c c0 d9 54 35 ca 5b 11 98 37 84 ea c0 13 00 00 |...T5.[..7......|
+00000000 16 03 01 00 59 02 00 00 55 03 01 90 3d f6 98 16 |....Y...U...=...|
+00000010 55 0f 73 94 05 96 4c ab ad f4 98 7a db c5 ca 26 |U.s...L....z...&|
+00000020 1b c8 d9 15 a8 79 8e 2b 10 67 54 20 b2 8e 45 24 |.....y.+.gT ..E$|
+00000030 6d 82 ec f5 30 41 2e 32 10 fa c0 76 3f 84 81 39 |m...0A.2...v?..9|
+00000040 1e 5d 98 c1 33 d9 0d 4f 21 e1 0d 47 c0 13 00 00 |.]..3..O!..G....|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
-00000060 01 02 be 0b 00 02 ba 00 02 b7 00 02 b4 30 82 02 |.............0..|
-00000070 b0 30 82 02 19 a0 03 02 01 02 02 09 00 85 b0 bb |.0..............|
-00000080 a4 8a 7f b8 ca 30 0d 06 09 2a 86 48 86 f7 0d 01 |.....0...*.H....|
-00000090 01 05 05 00 30 45 31 0b 30 09 06 03 55 04 06 13 |....0E1.0...U...|
-000000a0 02 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f |.AU1.0...U....So|
-000000b0 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 |me-State1!0...U.|
-000000c0 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 |...Internet Widg|
-000000d0 69 74 73 20 50 74 79 20 4c 74 64 30 1e 17 0d 31 |its Pty Ltd0...1|
-000000e0 30 30 34 32 34 30 39 30 39 33 38 5a 17 0d 31 31 |00424090938Z..11|
-000000f0 30 34 32 34 30 39 30 39 33 38 5a 30 45 31 0b 30 |0424090938Z0E1.0|
-00000100 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 |...U....AU1.0...|
-00000110 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 |U....Some-State1|
-00000120 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e |!0...U....Intern|
-00000130 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c |et Widgits Pty L|
-00000140 74 64 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 |td0..0...*.H....|
-00000150 01 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 bb |........0.......|
-00000160 79 d6 f5 17 b5 e5 bf 46 10 d0 dc 69 be e6 2b 07 |y......F...i..+.|
-00000170 43 5a d0 03 2d 8a 7a 43 85 b7 14 52 e7 a5 65 4c |CZ..-.zC...R..eL|
-00000180 2c 78 b8 23 8c b5 b4 82 e5 de 1f 95 3b 7e 62 a5 |,x.#........;~b.|
-00000190 2c a5 33 d6 fe 12 5c 7a 56 fc f5 06 bf fa 58 7b |,.3...\zV.....X{|
-000001a0 26 3f b5 cd 04 d3 d0 c9 21 96 4a c7 f4 54 9f 5a |&?......!.J..T.Z|
-000001b0 bf ef 42 71 00 fe 18 99 07 7f 7e 88 7d 7d f1 04 |..Bq......~.}}..|
-000001c0 39 c4 a2 2e db 51 c9 7c e3 c0 4c 3b 32 66 01 cf |9....Q.|..L;2f..|
-000001d0 af b1 1d b8 71 9a 1d db db 89 6b ae da 2d 79 02 |....q.....k..-y.|
-000001e0 03 01 00 01 a3 81 a7 30 81 a4 30 1d 06 03 55 1d |.......0..0...U.|
-000001f0 0e 04 16 04 14 b1 ad e2 85 5a cf cb 28 db 69 ce |.........Z..(.i.|
-00000200 23 69 de d3 26 8e 18 88 39 30 75 06 03 55 1d 23 |#i..&...90u..U.#|
-00000210 04 6e 30 6c 80 14 b1 ad e2 85 5a cf cb 28 db 69 |.n0l......Z..(.i|
-00000220 ce 23 69 de d3 26 8e 18 88 39 a1 49 a4 47 30 45 |.#i..&...9.I.G0E|
-00000230 31 0b 30 09 06 03 55 04 06 13 02 41 55 31 13 30 |1.0...U....AU1.0|
-00000240 11 06 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 |...U....Some-Sta|
-00000250 74 65 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 |te1!0...U....Int|
-00000260 65 72 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 |ernet Widgits Pt|
-00000270 79 20 4c 74 64 82 09 00 85 b0 bb a4 8a 7f b8 ca |y Ltd...........|
-00000280 30 0c 06 03 55 1d 13 04 05 30 03 01 01 ff 30 0d |0...U....0....0.|
-00000290 06 09 2a 86 48 86 f7 0d 01 01 05 05 00 03 81 81 |..*.H...........|
-000002a0 00 08 6c 45 24 c7 6b b1 59 ab 0c 52 cc f2 b0 14 |..lE$.k.Y..R....|
-000002b0 d7 87 9d 7a 64 75 b5 5a 95 66 e4 c5 2b 8e ae 12 |...zdu.Z.f..+...|
-000002c0 66 1f eb 4f 38 b3 6e 60 d3 92 fd f7 41 08 b5 25 |f..O8.n`....A..%|
-000002d0 13 b1 18 7a 24 fb 30 1d ba ed 98 b9 17 ec e7 d7 |...z$.0.........|
-000002e0 31 59 db 95 d3 1d 78 ea 50 56 5c d5 82 5a 2d 5a |1Y....x.PV\..Z-Z|
-000002f0 5f 33 c4 b6 d8 c9 75 90 96 8c 0f 52 98 b5 cd 98 |_3....u....R....|
-00000300 1f 89 20 5f f2 a0 1c a3 1b 96 94 dd a9 fd 57 e9 |.. _..........W.|
-00000310 70 e8 26 6d 71 99 9b 26 6e 38 50 29 6c 90 a7 bd |p.&mq..&n8P)l...|
-00000320 d9 16 03 01 00 cb 0c 00 00 c7 03 00 17 41 04 a6 |.............A..|
-00000330 57 60 8d 63 4e 4d 3f 48 e0 5d ad 9a 9c f7 e6 8c |W`.cNM?H.]......|
-00000340 00 18 9c eb 34 ea f0 5c d5 77 3f af 81 a9 50 d9 |....4..\.w?...P.|
-00000350 05 cf b9 bf 88 5c 70 29 24 61 6f d8 77 11 21 57 |.....\p)$ao.w.!W|
-00000360 a0 4d e1 4b 8e 55 06 50 7f a2 30 c1 c2 b9 c6 00 |.M.K.U.P..0.....|
-00000370 80 68 7c e4 1a bc a4 1e 16 b9 3e 4a 59 39 a9 54 |.h|.......>JY9.T|
-00000380 6f c7 17 b2 f5 af b5 73 5b db cc 71 f2 1b aa dc |o......s[..q....|
-00000390 9d 64 3c 0f 82 e6 da 1a 6b 96 19 e2 f0 15 b0 df |.d<.....k.......|
-000003a0 8a 2d 96 09 63 52 f6 53 ef 12 d4 3b 35 b7 0b 43 |.-..cR.S...;5..C|
-000003b0 2c 6e 58 4c c8 2f b8 55 84 89 c9 39 81 7a 7a 7d |,nXL./.U...9.zz}|
-000003c0 88 68 db eb d7 81 aa 2e b2 25 ba 98 6c 46 b7 85 |.h.......%..lF..|
-000003d0 8a 21 17 b9 36 23 c0 84 94 af 3b 9b 04 5d ec 31 |.!..6#....;..].1|
-000003e0 f5 75 84 d8 77 d7 80 37 ae c3 5c 26 41 f6 72 af |.u..w..7..\&A.r.|
-000003f0 88 16 03 01 00 04 0e 00 00 00 |..........|
+00000060 01 02 71 0b 00 02 6d 00 02 6a 00 02 67 30 82 02 |..q...m..j..g0..|
+00000070 63 30 82 01 cc a0 03 02 01 02 02 09 00 a2 73 00 |c0............s.|
+00000080 0c 81 00 cb f3 30 0d 06 09 2a 86 48 86 f7 0d 01 |.....0...*.H....|
+00000090 01 0b 05 00 30 2b 31 17 30 15 06 03 55 04 0a 13 |....0+1.0...U...|
+000000a0 0e 47 6f 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 |.Google TESTING1|
+000000b0 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f 6f |.0...U....Go Roo|
+000000c0 74 30 1e 17 0d 31 35 30 31 30 31 30 30 30 30 30 |t0...15010100000|
+000000d0 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 30 |0Z..250101000000|
+000000e0 5a 30 26 31 17 30 15 06 03 55 04 0a 13 0e 47 6f |Z0&1.0...U....Go|
+000000f0 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 0b 30 09 |ogle TESTING1.0.|
+00000100 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
+00000110 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
+00000120 81 89 02 81 81 00 af 87 88 f6 20 1b 95 65 6c 14 |.......... ..el.|
+00000130 ab 44 05 af 3b 45 14 e3 b7 6d fd 00 63 4d 95 7f |.D..;E...m..cM..|
+00000140 fe 6a 62 35 86 c0 4a f9 18 7c f6 aa 25 5e 7a 64 |.jb5..J..|..%^zd|
+00000150 31 66 00 ba f4 8e 92 af c7 6b d8 76 d4 f3 5f 41 |1f.......k.v.._A|
+00000160 cb 6e 56 15 97 1b 97 c1 3c 12 39 21 66 3d 2b 16 |.nV.....<.9!f=+.|
+00000170 d1 bc db 1c c0 a7 da b7 ca ad ba da cb d5 21 50 |..............!P|
+00000180 ec de 8d ab d1 6b 81 4b 89 02 f3 c4 be c1 6c 89 |.....k.K......l.|
+00000190 b1 44 84 bd 21 d1 04 7d 9d 16 4d f9 82 15 f6 ef |.D..!..}..M.....|
+000001a0 fa d6 09 47 f2 fb 02 03 01 00 01 a3 81 93 30 81 |...G..........0.|
+000001b0 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
+000001c0 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
+000001d0 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
+000001e0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
+000001f0 06 03 55 1d 0e 04 12 04 10 12 50 8d 89 6f 1b d1 |..U.......P..o..|
+00000200 dc 54 4d 6e cb 69 5e 06 f4 30 1b 06 03 55 1d 23 |.TMn.i^..0...U.#|
+00000210 04 14 30 12 80 10 bf 3d b6 a9 66 f2 b8 40 cf ea |..0....=..f..@..|
+00000220 b4 03 78 48 1a 41 30 19 06 03 55 1d 11 04 12 30 |..xH.A0...U....0|
+00000230 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
+00000240 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
+00000250 03 81 81 00 92 7c af 91 55 12 18 96 59 31 a6 48 |.....|..U...Y1.H|
+00000260 40 d5 2d d5 ee bb 02 a0 f5 c2 1e 7c 9b b3 30 7d |@.-........|..0}|
+00000270 3c dc 76 da 4f 3d c0 fa ae 2d 33 24 6b 03 7b 1b |<.v.O=...-3$k.{.|
+00000280 67 59 11 21 b5 11 bc 77 b9 d9 e0 6e a8 2d 2e 35 |gY.!...w...n.-.5|
+00000290 fa 64 5f 22 3e 63 10 6b be ff 14 86 6d 0d f0 15 |.d_">c.k....m...|
+000002a0 31 a8 14 38 1e 3b 84 87 2c cb 98 ed 51 76 b9 b1 |1..8.;..,...Qv..|
+000002b0 4f dd db 9b 84 04 86 40 fa 51 dd ba b4 8d eb e3 |O......@.Q......|
+000002c0 46 de 46 b9 4f 86 c7 f9 a4 c2 41 34 ac cc f6 ea |F.F.O.....A4....|
+000002d0 b0 ab 39 18 16 03 01 00 cb 0c 00 00 c7 03 00 17 |..9.............|
+000002e0 41 04 d9 ae 3f 05 64 d3 77 d9 1d b8 37 8a d4 ac |A...?.d.w...7...|
+000002f0 51 f4 af 65 70 da c0 64 76 00 53 50 a2 d4 6c bc |Q..ep..dv.SP..l.|
+00000300 9c 62 ab 2f 7b 02 48 fe b2 0d 0b bb be 8f 34 55 |.b./{.H.......4U|
+00000310 fb ce ee 93 43 76 d5 ce 3b b5 79 ab 3d 74 6e 19 |....Cv..;.y.=tn.|
+00000320 a9 7d 00 80 05 cf 57 f2 f7 e0 ad 71 f1 75 d0 8b |.}....W....q.u..|
+00000330 f5 9d 83 1a 7e 0a 71 10 d7 9e fe bd 9d 47 62 45 |....~.q......GbE|
+00000340 8d 1b 9c 33 fa 2c 5c aa ce 9e 62 dc ad 56 ac 87 |...3.,\...b..V..|
+00000350 84 54 f5 32 87 d1 bb 8b d9 d7 6d 3c 6c 6d b7 79 |.T.2......m<lm.y|
+00000360 05 4d 55 f1 7c ef b1 fc e7 35 5d 41 66 60 44 4f |.MU.|....5]Af`DO|
+00000370 f3 dd de 25 f4 73 12 c2 b6 cc 61 d5 14 5a ff 88 |...%.s....a..Z..|
+00000380 ae f5 04 62 ac 2d 10 a0 95 c1 8e fa e6 db fe 41 |...b.-.........A|
+00000390 46 98 f1 3d 2e e3 2a 5a ea 87 26 6e 7a 4f 38 6c |F..=..*Z..&nzO8l|
+000003a0 4b 1f 1b 56 16 03 01 00 04 0e 00 00 00 |K..V.........|
>>> Flow 3 (client to server)
00000000 16 03 01 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..|
00000010 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.|
00000020 a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e |.$ >.V...(^.+-O.|
00000030 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I|
00000040 a6 b5 68 1a 41 03 56 6b dc 5a 89 14 03 01 00 01 |..h.A.Vk.Z......|
-00000050 01 16 03 01 00 30 d2 5b 27 5a f5 64 49 31 d5 aa |.....0.['Z.dI1..|
-00000060 a3 72 ae c9 af 0b aa 75 af ac f3 45 f4 e3 03 fa |.r.....u...E....|
-00000070 e8 97 88 7b 51 a9 ae 61 40 c8 11 74 3e d8 9a b6 |...{Q..a@..t>...|
-00000080 e7 6a 5e 71 84 7e |.j^q.~|
+00000050 01 16 03 01 00 30 73 96 2d 54 e3 9a bc 54 f5 9e |.....0s.-T...T..|
+00000060 e5 c7 46 35 b8 e1 d6 f6 14 95 92 f1 95 81 5a 9d |..F5..........Z.|
+00000070 4b df cc 96 77 f2 39 60 5d 5d da 94 b0 bf a0 80 |K...w.9`]]......|
+00000080 bd 28 55 b1 6a c3 |.(U.j.|
>>> Flow 4 (server to client)
-00000000 14 03 01 00 01 01 16 03 01 00 30 8d 63 fc 58 2e |..........0.c.X.|
-00000010 50 f7 60 2c 9f 5a 8e 58 29 6c a6 3a 8d 2b a7 2b |P.`,.Z.X)l.:.+.+|
-00000020 1c 12 8a 53 3f d5 60 79 12 c3 78 e3 aa 50 15 45 |...S?.`y..x..P.E|
-00000030 07 da 2d c7 a9 c3 45 07 48 00 78 |..-...E.H.x|
+00000000 14 03 01 00 01 01 16 03 01 00 30 c9 46 7a 8b be |..........0.Fz..|
+00000010 cd eb 5c 83 13 9c 9b 9f 70 84 38 3b 48 8c f4 11 |..\.....p.8;H...|
+00000020 b3 ca 10 09 38 d0 8e c8 9f 66 db b9 8a 95 15 6b |....8....f.....k|
+00000030 5e f8 1d 39 25 75 3d f1 b9 32 a3 |^..9%u=..2.|
>>> Flow 5 (client to server)
-00000000 17 03 01 00 20 40 91 8d e6 95 2f 97 c8 0c 94 5c |.... @..../....\|
-00000010 46 a7 d3 31 82 3d dc 7e 86 5b dd df 3f 3b 5b 9c |F..1.=.~.[..?;[.|
-00000020 d5 0d 52 5a 53 17 03 01 00 20 1d 18 da 6b e8 66 |..RZS.... ...k.f|
-00000030 ce 58 18 81 4b 69 8c f6 db 1a ee d0 78 fb f5 68 |.X..Ki......x..h|
-00000040 2c 99 48 47 65 15 2a ae ff 4e 15 03 01 00 20 68 |,.HGe.*..N.... h|
-00000050 aa 7f 75 33 45 7a 1a 33 18 35 5a 5b 14 b0 f6 83 |..u3Ez.3.5Z[....|
-00000060 97 85 3f b2 dc 78 68 eb 43 ef 92 7f 38 bd f8 |..?..xh.C...8..|
+00000000 17 03 01 00 20 04 69 a9 01 42 f4 1a fd 5a 4e 12 |.... .i..B...ZN.|
+00000010 2b 6d cd 68 6b 94 70 b2 80 07 cf 79 a4 43 69 bf |+m.hk.p....y.Ci.|
+00000020 27 25 b5 ae e7 17 03 01 00 20 bf 1e cd 83 64 af |'%....... ....d.|
+00000030 6f cc 89 21 bf 16 e7 e8 86 29 f3 0a 36 ab a4 e3 |o..!.....)..6...|
+00000040 fa c0 7e 7a 78 ca 29 17 11 9c 15 03 01 00 20 94 |..~zx.)....... .|
+00000050 7a dd 17 eb fd 67 b1 cc 58 c9 c3 ae db b6 b0 a4 |z....g..X.......|
+00000060 68 15 36 ca 33 22 ec 03 fb cf 2f f5 70 d6 9d |h.6.3"..../.p..|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 81 01 00 00 7d 03 03 00 00 00 00 00 |........}.......|
+00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 22 c0 2f |............."./|
00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 36 |...../.5.......6|
-00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
-00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
-00000070 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
-00000080 01 00 00 12 00 00 |......|
+00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
+00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
+00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
+00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
+00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
>>> Flow 2 (server to client)
-00000000 16 03 01 00 51 02 00 00 4d 03 01 a9 b0 bf 24 3f |....Q...M.....$?|
-00000010 98 c6 0f 83 23 2b b6 e4 3f d5 5b 10 9a 6f b8 63 |....#+..?.[..o.c|
-00000020 4c 3c d6 4d 05 c0 08 85 f7 72 72 20 ab 85 8c ff |L<.M.....rr ....|
-00000030 f7 bb 95 ab 69 37 3d b6 79 cb 46 ad 4e 22 e7 c6 |....i7=.y.F.N"..|
-00000040 a5 9b 72 92 32 ff a5 f7 ed dc 30 41 00 05 00 00 |..r.2.....0A....|
-00000050 05 ff 01 00 01 00 16 03 01 02 be 0b 00 02 ba 00 |................|
-00000060 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......|
-00000070 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..|
-00000080 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 45 31 0b |.*.H........0E1.|
-00000090 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..|
-000000a0 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State|
-000000b0 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter|
-000000c0 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty |
-000000d0 4c 74 64 30 1e 17 0d 31 30 30 34 32 34 30 39 30 |Ltd0...100424090|
-000000e0 39 33 38 5a 17 0d 31 31 30 34 32 34 30 39 30 39 |938Z..1104240909|
-000000f0 33 38 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 |38Z0E1.0...U....|
-00000100 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som|
-00000110 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..|
-00000120 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi|
-00000130 74 73 20 50 74 79 20 4c 74 64 30 81 9f 30 0d 06 |ts Pty Ltd0..0..|
-00000140 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 |.*.H............|
-00000150 30 81 89 02 81 81 00 bb 79 d6 f5 17 b5 e5 bf 46 |0.......y......F|
-00000160 10 d0 dc 69 be e6 2b 07 43 5a d0 03 2d 8a 7a 43 |...i..+.CZ..-.zC|
-00000170 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 8c b5 b4 82 |...R..eL,x.#....|
-00000180 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 fe 12 5c 7a |....;~b.,.3...\z|
-00000190 56 fc f5 06 bf fa 58 7b 26 3f b5 cd 04 d3 d0 c9 |V.....X{&?......|
-000001a0 21 96 4a c7 f4 54 9f 5a bf ef 42 71 00 fe 18 99 |!.J..T.Z..Bq....|
-000001b0 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e db 51 c9 7c |..~.}}..9....Q.||
-000001c0 e3 c0 4c 3b 32 66 01 cf af b1 1d b8 71 9a 1d db |..L;2f......q...|
-000001d0 db 89 6b ae da 2d 79 02 03 01 00 01 a3 81 a7 30 |..k..-y........0|
-000001e0 81 a4 30 1d 06 03 55 1d 0e 04 16 04 14 b1 ad e2 |..0...U.........|
-000001f0 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 88 |.Z..(.i.#i..&...|
-00000200 39 30 75 06 03 55 1d 23 04 6e 30 6c 80 14 b1 ad |90u..U.#.n0l....|
-00000210 e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 |..Z..(.i.#i..&..|
-00000220 88 39 a1 49 a4 47 30 45 31 0b 30 09 06 03 55 04 |.9.I.G0E1.0...U.|
-00000230 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 0a |...AU1.0...U....|
-00000240 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 |Some-State1!0...|
-00000250 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 |U....Internet Wi|
-00000260 64 67 69 74 73 20 50 74 79 20 4c 74 64 82 09 00 |dgits Pty Ltd...|
-00000270 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 55 1d 13 04 |........0...U...|
-00000280 05 30 03 01 01 ff 30 0d 06 09 2a 86 48 86 f7 0d |.0....0...*.H...|
-00000290 01 01 05 05 00 03 81 81 00 08 6c 45 24 c7 6b b1 |..........lE$.k.|
-000002a0 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a 64 75 b5 5a |Y..R.......zdu.Z|
-000002b0 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f 38 b3 6e 60 |.f..+...f..O8.n`|
-000002c0 d3 92 fd f7 41 08 b5 25 13 b1 18 7a 24 fb 30 1d |....A..%...z$.0.|
-000002d0 ba ed 98 b9 17 ec e7 d7 31 59 db 95 d3 1d 78 ea |........1Y....x.|
-000002e0 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 90 |PV\..Z-Z_3....u.|
-000002f0 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c a3 |...R...... _....|
-00000300 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b 26 |......W.p.&mq..&|
-00000310 6e 38 50 29 6c 90 a7 bd d9 16 03 01 00 04 0e 00 |n8P)l...........|
-00000320 00 00 |..|
+00000000 16 03 01 00 51 02 00 00 4d 03 01 1c 0e e9 7a c6 |....Q...M.....z.|
+00000010 91 fe 7e 8c 6f 0b 8e cf 23 f5 07 29 10 de 05 a6 |..~.o...#..)....|
+00000020 20 72 11 65 4f 2b 45 95 96 02 62 20 43 a8 93 34 | r.eO+E...b C..4|
+00000030 e7 c0 29 d5 fb 26 f9 c2 59 37 94 dc e6 b5 c4 ed |..)..&..Y7......|
+00000040 ae 7a d7 94 d1 f4 d8 0b 02 ad 20 1b 00 05 00 00 |.z........ .....|
+00000050 05 ff 01 00 01 00 16 03 01 02 71 0b 00 02 6d 00 |..........q...m.|
+00000060 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
+00000070 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
+00000080 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
+00000090 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
+000000a0 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
+000000b0 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
+000000c0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
+000000d0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
+000000e0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
+000000f0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
+00000100 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
+00000110 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
+00000120 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
+00000130 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
+00000140 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
+00000150 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
+00000160 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
+00000170 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
+00000180 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
+00000190 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
+000001a0 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
+000001b0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
+000001c0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
+000001d0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
+000001e0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
+000001f0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
+00000200 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
+00000210 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
+00000220 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
+00000230 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
+00000240 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
+00000250 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
+00000260 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
+00000270 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
+00000280 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
+00000290 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
+000002a0 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
+000002b0 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
+000002c0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 01 00 |..A4......9.....|
+000002d0 04 0e 00 00 00 |.....|
>>> Flow 3 (client to server)
-00000000 16 03 01 00 86 10 00 00 82 00 80 6d 51 f3 7f f9 |...........mQ...|
-00000010 3e fb 75 82 41 36 83 e8 6a ee 2a 2e 25 90 67 4c |>.u.A6..j.*.%.gL|
-00000020 8e 62 2f 30 81 17 e0 85 09 0c 2b b7 23 d7 b0 e2 |.b/0......+.#...|
-00000030 1d f7 3b d7 f5 a1 27 b6 ee 24 b6 1b cc 5b ea 66 |..;...'..$...[.f|
-00000040 0d 6a f4 e5 85 f9 da 43 b4 0e 86 85 e1 f5 aa be |.j.....C........|
-00000050 c8 ce 39 4c 9c 86 00 08 c2 4b e2 c6 ec 2f f7 ce |..9L.....K.../..|
-00000060 e6 bd 77 82 6f 23 b6 e0 bd a2 92 b7 3a ac e8 56 |..w.o#......:..V|
-00000070 f1 af 54 5e 46 87 e9 3b 33 e7 b8 28 b7 d6 c8 90 |..T^F..;3..(....|
-00000080 35 d4 1c 43 d1 30 6f 55 4e 0a 70 14 03 01 00 01 |5..C.0oUN.p.....|
-00000090 01 16 03 01 00 24 4d 1d d7 8c d6 c7 65 a6 ce af |.....$M.....e...|
-000000a0 e7 59 0d 7e dc d9 96 1c ed 9c 57 94 84 b8 3f b5 |.Y.~......W...?.|
-000000b0 34 e1 61 a5 61 f3 5d 09 bc ff |4.a.a.]...|
+00000000 16 03 01 00 86 10 00 00 82 00 80 73 bd 73 65 92 |...........s.se.|
+00000010 86 23 41 14 79 7f d5 c1 10 ce 94 4d ad 9c c3 a9 |.#A.y......M....|
+00000020 87 b5 32 52 f8 6b 11 93 2d 9b 98 0b 8b 1d c0 f6 |..2R.k..-.......|
+00000030 53 17 6d c7 9c 2e ae c9 6f cc 99 23 38 37 1a 10 |S.m.....o..#87..|
+00000040 fe 05 0b b5 55 0a 14 e9 60 7d 70 26 98 e2 54 d9 |....U...`}p&..T.|
+00000050 65 cf 2e f4 53 5f 1d aa 3a f6 33 7b eb 4c 0e b3 |e...S_..:.3{.L..|
+00000060 ff 5a db 36 2a 47 f3 df f9 fc f5 31 78 83 aa 6b |.Z.6*G.....1x..k|
+00000070 52 b7 ba 1a 96 bc fa c1 a1 a9 bb 2b f5 38 89 00 |R..........+.8..|
+00000080 4d e5 78 13 4e a4 38 46 42 dc 16 14 03 01 00 01 |M.x.N.8FB.......|
+00000090 01 16 03 01 00 24 ae a9 da 45 6b 5e 76 57 02 62 |.....$...Ek^vW.b|
+000000a0 63 d4 1f 40 bf c9 47 27 a9 7a 24 c0 f0 e9 c2 c4 |c..@..G'.z$.....|
+000000b0 9c 07 84 df ae c7 66 40 d2 b0 |......f@..|
>>> Flow 4 (server to client)
-00000000 14 03 01 00 01 01 16 03 01 00 24 13 81 89 61 5c |..........$...a\|
-00000010 fb 0a 9c a1 4b db 94 6b 8b 41 6e 63 d6 aa db 88 |....K..k.Anc....|
-00000020 03 b7 b5 19 b8 12 cf 5e 17 54 79 2f 03 91 7e |.......^.Ty/..~|
+00000000 14 03 01 00 01 01 16 03 01 00 24 e9 84 92 41 c5 |..........$...A.|
+00000010 31 e1 3c a9 78 18 d1 7b e1 b1 0b 0a ef 18 54 19 |1.<.x..{......T.|
+00000020 7c ba c7 59 ca c8 7b 4d c9 f4 ad d6 7b 77 fb ||..Y..{M....{w.|
>>> Flow 5 (client to server)
-00000000 17 03 01 00 1a b3 2b da ce 45 ec b2 9d 3b 18 d9 |......+..E...;..|
-00000010 7a cb 99 ea ff 4d 91 b5 48 df 6f 8b 2f 85 c7 15 |z....M..H.o./...|
-00000020 03 01 00 16 19 1c 72 74 36 cf 22 0f a0 a7 18 96 |......rt6.".....|
-00000030 3a 67 cb 22 16 f1 a8 7b 57 37 |:g."...{W7|
+00000000 17 03 01 00 1a 1a dc 95 e2 4f ec f1 f6 68 9d 15 |.........O...h..|
+00000010 56 d5 7b 06 1a f5 be bb b1 ca b2 a6 d3 9e 28 15 |V.{...........(.|
+00000020 03 01 00 16 64 fe 4a 37 d3 32 a8 55 38 9e 0f 76 |....d.J7.2.U8..v|
+00000030 50 de e2 2e aa 77 15 2b e5 21 |P....w.+.!|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 81 01 00 00 7d 03 03 00 00 00 00 00 |........}.......|
+00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 22 c0 2f |............."./|
00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 36 |...../.5.......6|
-00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
-00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
-00000070 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
-00000080 01 00 00 12 00 00 |......|
+00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
+00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
+00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
+00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
+00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
>>> Flow 2 (server to client)
-00000000 16 03 02 00 59 02 00 00 55 03 02 5a 52 92 23 05 |....Y...U..ZR.#.|
-00000010 58 68 b2 1e 77 a2 a8 16 e9 88 85 ea 38 b3 63 c2 |Xh..w.......8.c.|
-00000020 40 f8 de 37 3c d4 b9 51 11 2d d1 20 12 fd 95 b3 |@..7<..Q.-. ....|
-00000030 2a 54 40 c0 23 3a 4e 4e f6 7b f8 77 04 6e e7 d7 |*T@.#:NN.{.w.n..|
-00000040 3b 9a 45 32 e0 af df aa ff bf 78 8b c0 09 00 00 |;.E2......x.....|
+00000000 16 03 02 00 59 02 00 00 55 03 02 07 ae a6 e4 1a |....Y...U.......|
+00000010 f7 7a 0c bc ea 21 0e 86 e3 d0 b4 2c fc d9 97 a3 |.z...!.....,....|
+00000020 8b 29 5f 59 3e a9 06 fb ca d9 57 20 cd 45 e7 cd |.)_Y>.....W .E..|
+00000030 6c 4c 56 cd 7c 4c 51 2c 8f 8c 67 a2 05 51 26 f5 |lLV.|LQ,..g..Q&.|
+00000040 17 cc 18 c2 a1 29 94 4b e2 02 cc 1c c0 09 00 00 |.....).K........|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
00000060 02 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..|
00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....|
00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....|
00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.|
00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....|
-00000270 2a 16 03 02 00 d5 0c 00 00 d1 03 00 17 41 04 c3 |*............A..|
-00000280 55 86 65 95 83 02 4b 69 6e 95 f4 52 46 83 21 86 |U.e...Kin..RF.!.|
-00000290 9e 99 cf 81 d9 b8 20 7a 87 b3 07 48 14 04 20 d9 |...... z...H.. .|
-000002a0 6c 2e 22 5a b5 b4 ef de 15 b3 08 ef 1e 18 ea 67 |l."Z...........g|
-000002b0 eb 45 fd e1 27 43 ed 41 ea 05 7e f3 f9 ee 23 00 |.E..'C.A..~...#.|
-000002c0 8a 30 81 87 02 42 00 b0 9c 06 85 83 b2 bf 42 22 |.0...B........B"|
-000002d0 6e 57 7a 31 fe a9 d9 28 be 0a a9 80 49 a2 14 c1 |nWz1...(....I...|
-000002e0 a9 99 76 b7 f9 76 d0 3c d3 0c c7 42 34 d7 94 a9 |..v..v.<...B4...|
-000002f0 15 66 7e 6b 83 6e b2 b4 5b 22 c9 4e a0 96 db 2b |.f~k.n..[".N...+|
-00000300 ad 77 33 1e 4a 5c 2f 2e 02 41 26 0c 1a 5a b4 07 |.w3.J\/..A&..Z..|
-00000310 95 99 ec 0b 5b 2e bb db 0e d5 26 c4 b3 eb c2 30 |....[.....&....0|
-00000320 b0 7b c1 07 97 a0 99 3f db 4e b0 c4 b8 bb 5e be |.{.....?.N....^.|
-00000330 2a e4 b3 a4 5c ad d1 d7 7a 2d fb ae 73 ee 0c 1e |*...\...z-..s...|
-00000340 3b 64 e1 74 14 bc c0 1e 8b f3 26 16 03 02 00 04 |;d.t......&.....|
-00000350 0e 00 00 00 |....|
+00000270 2a 16 03 02 00 d6 0c 00 00 d2 03 00 17 41 04 cd |*............A..|
+00000280 9d 30 75 8d 98 17 b5 1b 2f 4e af ea 69 52 a1 c1 |.0u...../N..iR..|
+00000290 86 73 6a 56 54 f8 ed b6 35 e5 4e 34 a0 6f b1 85 |.sjVT...5.N4.o..|
+000002a0 95 8e be 77 c5 1a 56 9a 59 d1 69 79 ea d6 2b c7 |...w..V.Y.iy..+.|
+000002b0 c1 4a fb bc f8 98 c3 49 1c f3 ce 33 ef 98 20 00 |.J.....I...3.. .|
+000002c0 8b 30 81 88 02 42 00 8b 15 7e 3b 4f 73 b0 8e ca |.0...B...~;Os...|
+000002d0 67 e0 7c d8 89 70 f1 b2 6b 9c 19 84 fa aa 6e 15 |g.|..p..k.....n.|
+000002e0 8b 46 95 57 d5 ac 79 f3 e8 2a e5 7a a8 1e c3 d7 |.F.W..y..*.z....|
+000002f0 0a b2 02 cd d6 32 34 2f 37 65 41 c8 61 c6 ed e5 |.....24/7eA.a...|
+00000300 d2 6f 0f e8 1a 49 b6 c7 02 42 00 d1 00 f4 05 65 |.o...I...B.....e|
+00000310 dd 43 42 db 8b 0b 95 9d f5 62 51 e6 58 60 20 9b |.CB......bQ.X` .|
+00000320 46 84 e6 1f 76 4a 92 42 e4 4d 77 5b 76 a5 78 a0 |F...vJ.B.Mw[v.x.|
+00000330 b0 f0 50 7d f9 4f ca 43 9d c2 50 cb 20 1c 40 52 |..P}.O.C..P. .@R|
+00000340 0f a8 c4 43 7a 9d d5 61 de 26 30 b5 16 03 02 00 |...Cz..a.&0.....|
+00000350 04 0e 00 00 00 |.....|
>>> Flow 3 (client to server)
00000000 16 03 02 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..|
00000010 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.|
00000030 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I|
00000040 a6 b5 68 1a 41 03 56 6b dc 5a 89 14 03 02 00 01 |..h.A.Vk.Z......|
00000050 01 16 03 02 00 40 00 00 00 00 00 00 00 00 00 00 |.....@..........|
-00000060 00 00 00 00 00 00 33 07 8a af e1 94 ef f9 08 3a |......3........:|
-00000070 33 5f b3 e6 42 07 85 af 40 e2 8b 34 53 62 1a 10 |3_..B...@..4Sb..|
-00000080 bb 08 7e 75 d4 21 12 2d 54 87 33 1c 4e 13 27 72 |..~u.!.-T.3.N.'r|
-00000090 3f 9e 9f cc de 47 |?....G|
+00000060 00 00 00 00 00 00 c0 81 e7 e8 40 f3 24 45 ed 74 |..........@.$E.t|
+00000070 86 31 7b 39 d1 3c a2 67 99 28 06 b1 34 b6 3c a6 |.1{9.<.g.(..4.<.|
+00000080 1d ce 39 aa 56 c9 72 0d f1 e0 c1 5a 51 a0 5d f2 |..9.V.r....ZQ.].|
+00000090 44 4d e6 d7 0e 84 |DM....|
>>> Flow 4 (server to client)
-00000000 14 03 02 00 01 01 16 03 02 00 40 4f 47 0d 43 54 |..........@OG.CT|
-00000010 50 69 3a c8 21 a6 6e 28 78 cc 01 b4 5d eb f7 2b |Pi:.!.n(x...]..+|
-00000020 8b 7e 26 6e cf 56 98 65 ad bf 0f a0 b4 67 13 70 |.~&n.V.e.....g.p|
-00000030 de b5 b5 91 df d6 df 8c 53 c6 54 3d 5d 98 e4 25 |........S.T=]..%|
-00000040 47 a0 0f 91 c7 08 96 17 48 bd 0f |G.......H..|
+00000000 14 03 02 00 01 01 16 03 02 00 40 82 8d c7 e3 7b |..........@....{|
+00000010 f8 9d 33 a1 c2 08 8c 24 d9 af 66 64 6e e8 61 8e |..3....$..fdn.a.|
+00000020 3c 03 65 2d c3 64 a2 26 23 a5 25 3f a2 a4 f9 40 |<.e-.d.&#.%?...@|
+00000030 ec 9f 0e b8 57 b1 5f 84 ea 94 72 1a 3e 60 f1 dd |....W._...r.>`..|
+00000040 af 2e 81 f7 16 de 43 85 21 51 49 |......C.!QI|
>>> Flow 5 (client to server)
00000000 17 03 02 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........|
-00000010 00 00 00 00 00 4e fe 12 d7 4b d7 3f 86 5a 2c f6 |.....N...K.?.Z,.|
-00000020 86 03 2a bd 1a 98 d7 bb 9f 59 6c 6d 4d 57 b0 50 |..*......YlmMW.P|
-00000030 d6 97 7e d4 b6 15 03 02 00 30 00 00 00 00 00 00 |..~......0......|
-00000040 00 00 00 00 00 00 00 00 00 00 65 8b b5 ae 86 90 |..........e.....|
-00000050 00 4e 1e 3f bc ac ed 49 f4 5e 73 49 e6 d8 37 83 |.N.?...I.^sI..7.|
-00000060 cf 4f e5 7b 5e c9 1d c8 c9 dc |.O.{^.....|
+00000010 00 00 00 00 00 43 8f 88 82 c8 e1 55 37 76 d7 a5 |.....C.....U7v..|
+00000020 83 c6 d2 94 26 fe 30 1f e2 24 ca d7 27 22 33 47 |....&.0..$..'"3G|
+00000030 5f a9 74 9d ad 15 03 02 00 30 00 00 00 00 00 00 |_.t......0......|
+00000040 00 00 00 00 00 00 00 00 00 00 49 8e ee 5c ec 86 |..........I..\..|
+00000050 e7 64 a7 ac 0d 5c c4 43 a6 45 a4 22 b7 3d 21 06 |.d...\.C.E.".=!.|
+00000060 11 67 08 99 9a 08 a1 7c e0 1e |.g.....|..|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 81 01 00 00 7d 03 03 00 00 00 00 00 |........}.......|
+00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 22 c0 2f |............."./|
00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 36 |...../.5.......6|
-00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
-00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
-00000070 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
-00000080 01 00 00 12 00 00 |......|
+00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
+00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
+00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
+00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
+00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
>>> Flow 2 (server to client)
-00000000 16 03 02 00 59 02 00 00 55 03 02 e3 ed 49 27 a3 |....Y...U....I'.|
-00000010 28 c5 8c 30 27 c2 ed 57 9b f7 37 a1 6d 2b 88 c2 |(..0'..W..7.m+..|
-00000020 df a7 2d 01 01 00 9a 09 da c2 1f 20 ee 33 87 03 |..-........ .3..|
-00000030 28 93 1c 16 99 5b b1 e0 bf 87 e8 77 4a 72 c9 92 |(....[.....wJr..|
-00000040 8a bc b2 3e 24 e1 f6 e8 f4 3f a2 24 c0 13 00 00 |...>$....?.$....|
+00000000 16 03 02 00 59 02 00 00 55 03 02 0c 74 28 d1 02 |....Y...U...t(..|
+00000010 15 8f 15 9c ec 8c 4e 34 97 d8 14 ab 0c ed 1b 38 |......N4.......8|
+00000020 af 7f e6 d3 41 db fd ad a0 8d 4f 20 03 71 4a d6 |....A.....O .qJ.|
+00000030 32 23 57 6c e1 55 34 1d 48 6f 9d e0 9a db 15 9d |2#Wl.U4.Ho......|
+00000040 5b 45 a7 3e 4e 98 31 7d f5 d4 b6 36 c0 13 00 00 |[E.>N.1}...6....|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
-00000060 02 02 be 0b 00 02 ba 00 02 b7 00 02 b4 30 82 02 |.............0..|
-00000070 b0 30 82 02 19 a0 03 02 01 02 02 09 00 85 b0 bb |.0..............|
-00000080 a4 8a 7f b8 ca 30 0d 06 09 2a 86 48 86 f7 0d 01 |.....0...*.H....|
-00000090 01 05 05 00 30 45 31 0b 30 09 06 03 55 04 06 13 |....0E1.0...U...|
-000000a0 02 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f |.AU1.0...U....So|
-000000b0 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 |me-State1!0...U.|
-000000c0 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 |...Internet Widg|
-000000d0 69 74 73 20 50 74 79 20 4c 74 64 30 1e 17 0d 31 |its Pty Ltd0...1|
-000000e0 30 30 34 32 34 30 39 30 39 33 38 5a 17 0d 31 31 |00424090938Z..11|
-000000f0 30 34 32 34 30 39 30 39 33 38 5a 30 45 31 0b 30 |0424090938Z0E1.0|
-00000100 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 |...U....AU1.0...|
-00000110 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 |U....Some-State1|
-00000120 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e |!0...U....Intern|
-00000130 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c |et Widgits Pty L|
-00000140 74 64 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 |td0..0...*.H....|
-00000150 01 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 bb |........0.......|
-00000160 79 d6 f5 17 b5 e5 bf 46 10 d0 dc 69 be e6 2b 07 |y......F...i..+.|
-00000170 43 5a d0 03 2d 8a 7a 43 85 b7 14 52 e7 a5 65 4c |CZ..-.zC...R..eL|
-00000180 2c 78 b8 23 8c b5 b4 82 e5 de 1f 95 3b 7e 62 a5 |,x.#........;~b.|
-00000190 2c a5 33 d6 fe 12 5c 7a 56 fc f5 06 bf fa 58 7b |,.3...\zV.....X{|
-000001a0 26 3f b5 cd 04 d3 d0 c9 21 96 4a c7 f4 54 9f 5a |&?......!.J..T.Z|
-000001b0 bf ef 42 71 00 fe 18 99 07 7f 7e 88 7d 7d f1 04 |..Bq......~.}}..|
-000001c0 39 c4 a2 2e db 51 c9 7c e3 c0 4c 3b 32 66 01 cf |9....Q.|..L;2f..|
-000001d0 af b1 1d b8 71 9a 1d db db 89 6b ae da 2d 79 02 |....q.....k..-y.|
-000001e0 03 01 00 01 a3 81 a7 30 81 a4 30 1d 06 03 55 1d |.......0..0...U.|
-000001f0 0e 04 16 04 14 b1 ad e2 85 5a cf cb 28 db 69 ce |.........Z..(.i.|
-00000200 23 69 de d3 26 8e 18 88 39 30 75 06 03 55 1d 23 |#i..&...90u..U.#|
-00000210 04 6e 30 6c 80 14 b1 ad e2 85 5a cf cb 28 db 69 |.n0l......Z..(.i|
-00000220 ce 23 69 de d3 26 8e 18 88 39 a1 49 a4 47 30 45 |.#i..&...9.I.G0E|
-00000230 31 0b 30 09 06 03 55 04 06 13 02 41 55 31 13 30 |1.0...U....AU1.0|
-00000240 11 06 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 |...U....Some-Sta|
-00000250 74 65 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 |te1!0...U....Int|
-00000260 65 72 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 |ernet Widgits Pt|
-00000270 79 20 4c 74 64 82 09 00 85 b0 bb a4 8a 7f b8 ca |y Ltd...........|
-00000280 30 0c 06 03 55 1d 13 04 05 30 03 01 01 ff 30 0d |0...U....0....0.|
-00000290 06 09 2a 86 48 86 f7 0d 01 01 05 05 00 03 81 81 |..*.H...........|
-000002a0 00 08 6c 45 24 c7 6b b1 59 ab 0c 52 cc f2 b0 14 |..lE$.k.Y..R....|
-000002b0 d7 87 9d 7a 64 75 b5 5a 95 66 e4 c5 2b 8e ae 12 |...zdu.Z.f..+...|
-000002c0 66 1f eb 4f 38 b3 6e 60 d3 92 fd f7 41 08 b5 25 |f..O8.n`....A..%|
-000002d0 13 b1 18 7a 24 fb 30 1d ba ed 98 b9 17 ec e7 d7 |...z$.0.........|
-000002e0 31 59 db 95 d3 1d 78 ea 50 56 5c d5 82 5a 2d 5a |1Y....x.PV\..Z-Z|
-000002f0 5f 33 c4 b6 d8 c9 75 90 96 8c 0f 52 98 b5 cd 98 |_3....u....R....|
-00000300 1f 89 20 5f f2 a0 1c a3 1b 96 94 dd a9 fd 57 e9 |.. _..........W.|
-00000310 70 e8 26 6d 71 99 9b 26 6e 38 50 29 6c 90 a7 bd |p.&mq..&n8P)l...|
-00000320 d9 16 03 02 00 cb 0c 00 00 c7 03 00 17 41 04 f7 |.............A..|
-00000330 75 c1 b9 58 a0 7d 50 48 e9 85 79 db 89 76 4c d7 |u..X.}PH..y..vL.|
-00000340 84 5b 94 9a 15 d8 92 32 74 d2 3e ce 76 5a bd 0e |.[.....2t.>.vZ..|
-00000350 24 e7 a6 d0 77 5d 8e 3d 9f 94 7a ea 15 46 3c 5c |$...w].=..z..F<\|
-00000360 61 28 76 4a ff 81 97 2b 3a 0c b7 aa b4 0e cb 00 |a(vJ...+:.......|
-00000370 80 19 00 a8 fe 0a ea 35 30 51 a3 77 37 08 68 10 |.......50Q.w7.h.|
-00000380 5a e9 07 2d 83 67 77 4c 3a 25 14 1c 5b c1 2e 80 |Z..-.gwL:%..[...|
-00000390 30 6d ba 26 c1 f9 c6 3e fc 55 34 8c d2 9f 2b a6 |0m.&...>.U4...+.|
-000003a0 46 0c 9d 58 2c 9c 2b ce 6f 03 d7 49 4e df 21 ce |F..X,.+.o..IN.!.|
-000003b0 3f 8b 19 fe 3e 71 23 51 c3 ec 30 c8 3e 3c 3c 50 |?...>q#Q..0.><<P|
-000003c0 da 08 52 c0 10 9f e3 4a be e0 97 aa de 5e 13 22 |..R....J.....^."|
-000003d0 b2 77 ee 5d 2d d4 ff fb 7f c3 1e e7 51 fe fc 4b |.w.]-.......Q..K|
-000003e0 56 5b 8f 50 ad cc 34 7a a9 dd 24 0a d0 c7 b9 bf |V[.P..4z..$.....|
-000003f0 1a 16 03 02 00 04 0e 00 00 00 |..........|
+00000060 02 02 71 0b 00 02 6d 00 02 6a 00 02 67 30 82 02 |..q...m..j..g0..|
+00000070 63 30 82 01 cc a0 03 02 01 02 02 09 00 a2 73 00 |c0............s.|
+00000080 0c 81 00 cb f3 30 0d 06 09 2a 86 48 86 f7 0d 01 |.....0...*.H....|
+00000090 01 0b 05 00 30 2b 31 17 30 15 06 03 55 04 0a 13 |....0+1.0...U...|
+000000a0 0e 47 6f 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 |.Google TESTING1|
+000000b0 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f 6f |.0...U....Go Roo|
+000000c0 74 30 1e 17 0d 31 35 30 31 30 31 30 30 30 30 30 |t0...15010100000|
+000000d0 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 30 |0Z..250101000000|
+000000e0 5a 30 26 31 17 30 15 06 03 55 04 0a 13 0e 47 6f |Z0&1.0...U....Go|
+000000f0 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 0b 30 09 |ogle TESTING1.0.|
+00000100 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
+00000110 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
+00000120 81 89 02 81 81 00 af 87 88 f6 20 1b 95 65 6c 14 |.......... ..el.|
+00000130 ab 44 05 af 3b 45 14 e3 b7 6d fd 00 63 4d 95 7f |.D..;E...m..cM..|
+00000140 fe 6a 62 35 86 c0 4a f9 18 7c f6 aa 25 5e 7a 64 |.jb5..J..|..%^zd|
+00000150 31 66 00 ba f4 8e 92 af c7 6b d8 76 d4 f3 5f 41 |1f.......k.v.._A|
+00000160 cb 6e 56 15 97 1b 97 c1 3c 12 39 21 66 3d 2b 16 |.nV.....<.9!f=+.|
+00000170 d1 bc db 1c c0 a7 da b7 ca ad ba da cb d5 21 50 |..............!P|
+00000180 ec de 8d ab d1 6b 81 4b 89 02 f3 c4 be c1 6c 89 |.....k.K......l.|
+00000190 b1 44 84 bd 21 d1 04 7d 9d 16 4d f9 82 15 f6 ef |.D..!..}..M.....|
+000001a0 fa d6 09 47 f2 fb 02 03 01 00 01 a3 81 93 30 81 |...G..........0.|
+000001b0 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
+000001c0 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
+000001d0 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
+000001e0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
+000001f0 06 03 55 1d 0e 04 12 04 10 12 50 8d 89 6f 1b d1 |..U.......P..o..|
+00000200 dc 54 4d 6e cb 69 5e 06 f4 30 1b 06 03 55 1d 23 |.TMn.i^..0...U.#|
+00000210 04 14 30 12 80 10 bf 3d b6 a9 66 f2 b8 40 cf ea |..0....=..f..@..|
+00000220 b4 03 78 48 1a 41 30 19 06 03 55 1d 11 04 12 30 |..xH.A0...U....0|
+00000230 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
+00000240 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
+00000250 03 81 81 00 92 7c af 91 55 12 18 96 59 31 a6 48 |.....|..U...Y1.H|
+00000260 40 d5 2d d5 ee bb 02 a0 f5 c2 1e 7c 9b b3 30 7d |@.-........|..0}|
+00000270 3c dc 76 da 4f 3d c0 fa ae 2d 33 24 6b 03 7b 1b |<.v.O=...-3$k.{.|
+00000280 67 59 11 21 b5 11 bc 77 b9 d9 e0 6e a8 2d 2e 35 |gY.!...w...n.-.5|
+00000290 fa 64 5f 22 3e 63 10 6b be ff 14 86 6d 0d f0 15 |.d_">c.k....m...|
+000002a0 31 a8 14 38 1e 3b 84 87 2c cb 98 ed 51 76 b9 b1 |1..8.;..,...Qv..|
+000002b0 4f dd db 9b 84 04 86 40 fa 51 dd ba b4 8d eb e3 |O......@.Q......|
+000002c0 46 de 46 b9 4f 86 c7 f9 a4 c2 41 34 ac cc f6 ea |F.F.O.....A4....|
+000002d0 b0 ab 39 18 16 03 02 00 cb 0c 00 00 c7 03 00 17 |..9.............|
+000002e0 41 04 2c e8 55 b8 19 d6 cd e5 c7 96 a4 aa 61 af |A.,.U.........a.|
+000002f0 aa b2 f1 fc b3 ac 9a 90 02 d0 0a 86 61 9a c1 2e |............a...|
+00000300 3e fd 42 0b ba 07 95 77 2b 92 a2 5b 1f 44 ad 6b |>.B....w+..[.D.k|
+00000310 78 7a f4 b3 4b 04 d3 d5 2d eb 20 2d 73 02 4c db |xz..K...-. -s.L.|
+00000320 7e ac 00 80 79 b0 c6 b9 a8 50 e4 bf de 97 c6 1f |~...y....P......|
+00000330 ae 5f 89 77 6e e4 23 8c 8d 1a 49 f8 d4 92 cf 0d |._.wn.#...I.....|
+00000340 f0 08 bd 3a 88 9c 55 46 fc be 9e 7c 70 ff 6f 70 |...:..UF...|p.op|
+00000350 7b 94 b3 7b 82 c3 58 53 f7 20 13 3c 83 6e 10 55 |{..{..XS. .<.n.U|
+00000360 9d 51 cb 53 8c 93 dc 0e 02 06 40 d4 df ce 57 e4 |.Q.S......@...W.|
+00000370 e0 9a ba e2 b3 9b 01 98 0e 12 ca e9 96 5b 7a f2 |.............[z.|
+00000380 b1 ac 9c 44 e7 6e 2e c6 51 63 99 68 26 93 ca e2 |...D.n..Qc.h&...|
+00000390 40 31 e5 9a 80 ce 83 8f ca 80 90 c4 e8 ab 89 b2 |@1..............|
+000003a0 ca d6 30 a5 16 03 02 00 04 0e 00 00 00 |..0..........|
>>> Flow 3 (client to server)
00000000 16 03 02 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..|
00000010 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.|
00000030 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I|
00000040 a6 b5 68 1a 41 03 56 6b dc 5a 89 14 03 02 00 01 |..h.A.Vk.Z......|
00000050 01 16 03 02 00 40 00 00 00 00 00 00 00 00 00 00 |.....@..........|
-00000060 00 00 00 00 00 00 1e 0b cd 40 fa 0f ed fa 55 74 |.........@....Ut|
-00000070 4e ad 10 d1 b5 e1 41 8c c0 93 81 38 f3 83 f1 37 |N.....A....8...7|
-00000080 6a d4 6c ea ba 5b 9e 38 d3 c1 bb 41 45 fb f0 48 |j.l..[.8...AE..H|
-00000090 c1 06 31 64 e0 65 |..1d.e|
+00000060 00 00 00 00 00 00 7d 87 6f 44 8f b9 92 51 5a b7 |......}.oD...QZ.|
+00000070 d2 6c 22 7f 62 a1 4e 30 61 f8 42 cd b0 05 c0 24 |.l".b.N0a.B....$|
+00000080 1f e0 49 a8 36 ce 8a 68 94 b7 37 c7 e8 d9 d8 05 |..I.6..h..7.....|
+00000090 be fb 5e 48 ba d1 |..^H..|
>>> Flow 4 (server to client)
-00000000 14 03 02 00 01 01 16 03 02 00 40 17 d1 79 f8 e0 |..........@..y..|
-00000010 d4 40 15 85 df 4d a6 d5 60 90 1f d6 52 58 e7 ae |.@...M..`...RX..|
-00000020 05 eb a2 ea ed c9 be ae b5 54 39 de 05 66 27 67 |.........T9..f'g|
-00000030 59 07 03 e7 10 f9 3f da d8 85 8b 2f 7b 33 9f f5 |Y.....?..../{3..|
-00000040 43 50 b9 9c 6e dd 01 ae d8 c9 1d |CP..n......|
+00000000 14 03 02 00 01 01 16 03 02 00 40 7d ed 01 b9 5a |..........@}...Z|
+00000010 34 f4 e1 63 70 84 13 86 e6 4d 90 92 da 3c 9b 35 |4..cp....M...<.5|
+00000020 77 92 7f 0a fd 69 09 75 30 5b c3 2c 6e 8e d0 59 |w....i.u0[.,n..Y|
+00000030 08 08 5c c9 eb 53 45 f3 a6 12 16 f2 95 06 27 82 |..\..SE.......'.|
+00000040 6d 9b 9e 6a bb 52 79 65 ca 94 9b |m..j.Rye...|
>>> Flow 5 (client to server)
00000000 17 03 02 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........|
-00000010 00 00 00 00 00 65 81 63 71 55 1c 46 8a 60 46 d9 |.....e.cqU.F.`F.|
-00000020 7d 71 a2 62 b8 a8 3b 06 3d a2 f4 53 a4 46 a8 9e |}q.b..;.=..S.F..|
-00000030 b7 89 8a 42 ce 15 03 02 00 30 00 00 00 00 00 00 |...B.....0......|
-00000040 00 00 00 00 00 00 00 00 00 00 7a 78 a4 e7 2f 40 |..........zx../@|
-00000050 df 42 9b 76 7a 45 0a 86 40 af 3c 40 c6 69 ba e1 |.B.vzE..@.<@.i..|
-00000060 23 82 fa 44 fd 73 fc 5b f7 b9 |#..D.s.[..|
+00000010 00 00 00 00 00 bb 2d 28 50 1f a4 8f be 94 b9 99 |......-(P.......|
+00000020 e6 0b dd cf 50 fc 72 92 ec 1d 72 9b 27 9a 36 18 |....P.r...r.'.6.|
+00000030 3e e3 d7 cc 69 15 03 02 00 30 00 00 00 00 00 00 |>...i....0......|
+00000040 00 00 00 00 00 00 00 00 00 00 61 ca 39 3c 7e 9f |..........a.9<~.|
+00000050 1c c8 c2 2a 42 4a d0 c4 f3 80 41 04 b4 35 d0 41 |...*BJ....A..5.A|
+00000060 3d 47 1b 16 2c 71 27 04 7c 81 |=G..,q'.|.|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 81 01 00 00 7d 03 03 00 00 00 00 00 |........}.......|
+00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 22 c0 2f |............."./|
00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 36 |...../.5.......6|
-00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
-00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
-00000070 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
-00000080 01 00 00 12 00 00 |......|
+00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
+00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
+00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
+00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
+00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
>>> Flow 2 (server to client)
-00000000 16 03 02 00 51 02 00 00 4d 03 02 7e 38 ae 3c 50 |....Q...M..~8.<P|
-00000010 03 96 3d 54 2f cd 86 21 98 7f 87 43 d8 58 aa a3 |..=T/..!...C.X..|
-00000020 d5 9f e7 25 a6 ab 34 7f 10 5f 99 20 56 c5 a8 dd |...%..4.._. V...|
-00000030 37 17 0d 51 f1 0d c4 4e 76 0f 01 26 56 c9 0c 20 |7..Q...Nv..&V.. |
-00000040 28 ef cd ac 38 ea d3 7f 6f aa 7c b8 00 05 00 00 |(...8...o.|.....|
-00000050 05 ff 01 00 01 00 16 03 02 02 be 0b 00 02 ba 00 |................|
-00000060 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......|
-00000070 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..|
-00000080 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 45 31 0b |.*.H........0E1.|
-00000090 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..|
-000000a0 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State|
-000000b0 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter|
-000000c0 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty |
-000000d0 4c 74 64 30 1e 17 0d 31 30 30 34 32 34 30 39 30 |Ltd0...100424090|
-000000e0 39 33 38 5a 17 0d 31 31 30 34 32 34 30 39 30 39 |938Z..1104240909|
-000000f0 33 38 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 |38Z0E1.0...U....|
-00000100 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som|
-00000110 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..|
-00000120 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi|
-00000130 74 73 20 50 74 79 20 4c 74 64 30 81 9f 30 0d 06 |ts Pty Ltd0..0..|
-00000140 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 |.*.H............|
-00000150 30 81 89 02 81 81 00 bb 79 d6 f5 17 b5 e5 bf 46 |0.......y......F|
-00000160 10 d0 dc 69 be e6 2b 07 43 5a d0 03 2d 8a 7a 43 |...i..+.CZ..-.zC|
-00000170 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 8c b5 b4 82 |...R..eL,x.#....|
-00000180 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 fe 12 5c 7a |....;~b.,.3...\z|
-00000190 56 fc f5 06 bf fa 58 7b 26 3f b5 cd 04 d3 d0 c9 |V.....X{&?......|
-000001a0 21 96 4a c7 f4 54 9f 5a bf ef 42 71 00 fe 18 99 |!.J..T.Z..Bq....|
-000001b0 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e db 51 c9 7c |..~.}}..9....Q.||
-000001c0 e3 c0 4c 3b 32 66 01 cf af b1 1d b8 71 9a 1d db |..L;2f......q...|
-000001d0 db 89 6b ae da 2d 79 02 03 01 00 01 a3 81 a7 30 |..k..-y........0|
-000001e0 81 a4 30 1d 06 03 55 1d 0e 04 16 04 14 b1 ad e2 |..0...U.........|
-000001f0 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 88 |.Z..(.i.#i..&...|
-00000200 39 30 75 06 03 55 1d 23 04 6e 30 6c 80 14 b1 ad |90u..U.#.n0l....|
-00000210 e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 |..Z..(.i.#i..&..|
-00000220 88 39 a1 49 a4 47 30 45 31 0b 30 09 06 03 55 04 |.9.I.G0E1.0...U.|
-00000230 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 0a |...AU1.0...U....|
-00000240 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 |Some-State1!0...|
-00000250 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 |U....Internet Wi|
-00000260 64 67 69 74 73 20 50 74 79 20 4c 74 64 82 09 00 |dgits Pty Ltd...|
-00000270 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 55 1d 13 04 |........0...U...|
-00000280 05 30 03 01 01 ff 30 0d 06 09 2a 86 48 86 f7 0d |.0....0...*.H...|
-00000290 01 01 05 05 00 03 81 81 00 08 6c 45 24 c7 6b b1 |..........lE$.k.|
-000002a0 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a 64 75 b5 5a |Y..R.......zdu.Z|
-000002b0 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f 38 b3 6e 60 |.f..+...f..O8.n`|
-000002c0 d3 92 fd f7 41 08 b5 25 13 b1 18 7a 24 fb 30 1d |....A..%...z$.0.|
-000002d0 ba ed 98 b9 17 ec e7 d7 31 59 db 95 d3 1d 78 ea |........1Y....x.|
-000002e0 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 90 |PV\..Z-Z_3....u.|
-000002f0 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c a3 |...R...... _....|
-00000300 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b 26 |......W.p.&mq..&|
-00000310 6e 38 50 29 6c 90 a7 bd d9 16 03 02 00 04 0e 00 |n8P)l...........|
-00000320 00 00 |..|
+00000000 16 03 02 00 51 02 00 00 4d 03 02 59 22 be 64 85 |....Q...M..Y".d.|
+00000010 71 af 54 70 5f a8 50 ff 68 52 a0 9e a7 79 4d 90 |q.Tp_.P.hR...yM.|
+00000020 cd bc c7 9c 4f 62 bc 4d a6 b9 0c 20 e1 94 8f 01 |....Ob.M... ....|
+00000030 fa 7f 9e 6f 01 72 82 ef cc 41 ed 4d 7e 76 ee e1 |...o.r...A.M~v..|
+00000040 21 34 f3 5c e0 b4 4b e2 73 37 a8 40 00 05 00 00 |!4.\..K.s7.@....|
+00000050 05 ff 01 00 01 00 16 03 02 02 71 0b 00 02 6d 00 |..........q...m.|
+00000060 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
+00000070 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
+00000080 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
+00000090 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
+000000a0 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
+000000b0 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
+000000c0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
+000000d0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
+000000e0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
+000000f0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
+00000100 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
+00000110 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
+00000120 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
+00000130 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
+00000140 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
+00000150 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
+00000160 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
+00000170 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
+00000180 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
+00000190 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
+000001a0 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
+000001b0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
+000001c0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
+000001d0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
+000001e0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
+000001f0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
+00000200 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
+00000210 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
+00000220 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
+00000230 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
+00000240 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
+00000250 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
+00000260 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
+00000270 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
+00000280 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
+00000290 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
+000002a0 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
+000002b0 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
+000002c0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 02 00 |..A4......9.....|
+000002d0 04 0e 00 00 00 |.....|
>>> Flow 3 (client to server)
-00000000 16 03 02 00 86 10 00 00 82 00 80 6d 51 f3 7f f9 |...........mQ...|
-00000010 3e fb 75 82 41 36 83 e8 6a ee 2a 2e 25 90 67 4c |>.u.A6..j.*.%.gL|
-00000020 8e 62 2f 30 81 17 e0 85 09 0c 2b b7 23 d7 b0 e2 |.b/0......+.#...|
-00000030 1d f7 3b d7 f5 a1 27 b6 ee 24 b6 1b cc 5b ea 66 |..;...'..$...[.f|
-00000040 0d 6a f4 e5 85 f9 da 43 b4 0e 86 85 e1 f5 aa be |.j.....C........|
-00000050 c8 ce 39 4c 9c 86 00 08 c2 4b e2 c6 ec 2f f7 ce |..9L.....K.../..|
-00000060 e6 bd 77 82 6f 23 b6 e0 bd a2 92 b7 3a ac e8 56 |..w.o#......:..V|
-00000070 f1 af 54 5e 46 87 e9 3b 33 e7 b8 28 b7 d6 c8 90 |..T^F..;3..(....|
-00000080 35 d4 1c 43 d1 30 6f 55 4e 0a 70 14 03 02 00 01 |5..C.0oUN.p.....|
-00000090 01 16 03 02 00 24 b9 df 85 a1 6d a7 14 b5 bc f5 |.....$....m.....|
-000000a0 c2 1d 40 fc 1e 19 f2 36 2d ec 6b 59 c5 6d ae c7 |..@....6-.kY.m..|
-000000b0 1c ad 7e a3 5b 4d 12 e5 58 5a |..~.[M..XZ|
+00000000 16 03 02 00 86 10 00 00 82 00 80 73 bd 73 65 92 |...........s.se.|
+00000010 86 23 41 14 79 7f d5 c1 10 ce 94 4d ad 9c c3 a9 |.#A.y......M....|
+00000020 87 b5 32 52 f8 6b 11 93 2d 9b 98 0b 8b 1d c0 f6 |..2R.k..-.......|
+00000030 53 17 6d c7 9c 2e ae c9 6f cc 99 23 38 37 1a 10 |S.m.....o..#87..|
+00000040 fe 05 0b b5 55 0a 14 e9 60 7d 70 26 98 e2 54 d9 |....U...`}p&..T.|
+00000050 65 cf 2e f4 53 5f 1d aa 3a f6 33 7b eb 4c 0e b3 |e...S_..:.3{.L..|
+00000060 ff 5a db 36 2a 47 f3 df f9 fc f5 31 78 83 aa 6b |.Z.6*G.....1x..k|
+00000070 52 b7 ba 1a 96 bc fa c1 a1 a9 bb 2b f5 38 89 00 |R..........+.8..|
+00000080 4d e5 78 13 4e a4 38 46 42 dc 16 14 03 02 00 01 |M.x.N.8FB.......|
+00000090 01 16 03 02 00 24 0b 7b 3e 32 fb 94 95 66 26 a9 |.....$.{>2...f&.|
+000000a0 4c 21 5e 18 59 cb 80 57 1b 9a 89 c8 91 c5 30 1f |L!^.Y..W......0.|
+000000b0 1a e2 80 9a 0f 03 8e 7b 4c 7d |.......{L}|
>>> Flow 4 (server to client)
-00000000 14 03 02 00 01 01 16 03 02 00 24 a3 f3 22 a8 32 |..........$..".2|
-00000010 63 c3 88 5c 0f fb 2d 47 21 0d 62 e2 db aa ed ae |c..\..-G!.b.....|
-00000020 b6 5f e3 c8 98 fc 91 5e 04 83 cf c3 21 17 ce |._.....^....!..|
+00000000 14 03 02 00 01 01 16 03 02 00 24 06 7f be 82 45 |..........$....E|
+00000010 79 c6 67 fb d3 1e 3f ca d9 0f 8f 81 36 cc 80 77 |y.g...?.....6..w|
+00000020 b8 48 f3 88 29 fa f1 3a b2 d4 fd 10 e5 8c 43 |.H..)..:......C|
>>> Flow 5 (client to server)
-00000000 17 03 02 00 1a f1 e4 46 c7 14 91 4b c6 25 fd aa |.......F...K.%..|
-00000010 5d dd 3f 61 ac 9c 79 68 bc e6 0f a1 e4 f3 73 15 |].?a..yh......s.|
-00000020 03 02 00 16 6b 8d 23 3c 99 b4 c2 23 3c 27 fd 41 |....k.#<...#<'.A|
-00000030 cc 04 e5 fc e7 f9 d9 81 0a b8 |..........|
+00000000 17 03 02 00 1a 29 4d a2 80 38 2c 9e 96 bb 29 8b |.....)M..8,...).|
+00000010 22 69 ea 85 3e d8 a9 66 39 b8 58 12 ae 67 db 15 |"i..>..f9.X..g..|
+00000020 03 02 00 16 8c b2 f4 c1 35 5d 28 dc 5c bc 30 95 |........5](.\.0.|
+00000030 99 3e f6 c6 ff 4f 5c f4 85 1a |.>...O\...|
--- /dev/null
+>>> Flow 1 (client to server)
+00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 22 c0 2f |............."./|
+00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
+00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
+00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
+00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
+00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
+00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
+>>> Flow 2 (server to client)
+00000000 16 03 03 00 51 02 00 00 4d 03 03 e7 18 39 61 14 |....Q...M....9a.|
+00000010 47 69 40 34 ae 4e 58 4b 32 2d ed 2a 52 09 c5 2f |Gi@4.NXK2-.*R../|
+00000020 07 f6 44 0b 2b 9c 43 4b bb 79 b6 20 48 f4 ff f1 |..D.+.CK.y. H...|
+00000030 c6 72 77 e5 3a e0 8d 08 b9 cd 8b bf e3 9b ec 41 |.rw.:..........A|
+00000040 1d d9 86 1b 35 7b 8c 04 e0 83 0d d3 00 9c 00 00 |....5{..........|
+00000050 05 ff 01 00 01 00 16 03 03 02 71 0b 00 02 6d 00 |..........q...m.|
+00000060 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
+00000070 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
+00000080 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
+00000090 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
+000000a0 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
+000000b0 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
+000000c0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
+000000d0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
+000000e0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
+000000f0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
+00000100 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
+00000110 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
+00000120 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
+00000130 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
+00000140 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
+00000150 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
+00000160 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
+00000170 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
+00000180 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
+00000190 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
+000001a0 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
+000001b0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
+000001c0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
+000001d0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
+000001e0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
+000001f0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
+00000200 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
+00000210 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
+00000220 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
+00000230 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
+00000240 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
+00000250 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
+00000260 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
+00000270 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
+00000280 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
+00000290 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
+000002a0 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
+000002b0 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
+000002c0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 03 00 |..A4......9.....|
+000002d0 04 0e 00 00 00 |.....|
+>>> Flow 3 (client to server)
+00000000 16 03 03 00 86 10 00 00 82 00 80 73 bd 73 65 92 |...........s.se.|
+00000010 86 23 41 14 79 7f d5 c1 10 ce 94 4d ad 9c c3 a9 |.#A.y......M....|
+00000020 87 b5 32 52 f8 6b 11 93 2d 9b 98 0b 8b 1d c0 f6 |..2R.k..-.......|
+00000030 53 17 6d c7 9c 2e ae c9 6f cc 99 23 38 37 1a 10 |S.m.....o..#87..|
+00000040 fe 05 0b b5 55 0a 14 e9 60 7d 70 26 98 e2 54 d9 |....U...`}p&..T.|
+00000050 65 cf 2e f4 53 5f 1d aa 3a f6 33 7b eb 4c 0e b3 |e...S_..:.3{.L..|
+00000060 ff 5a db 36 2a 47 f3 df f9 fc f5 31 78 83 aa 6b |.Z.6*G.....1x..k|
+00000070 52 b7 ba 1a 96 bc fa c1 a1 a9 bb 2b f5 38 89 00 |R..........+.8..|
+00000080 4d e5 78 13 4e a4 38 46 42 dc 16 14 03 03 00 01 |M.x.N.8FB.......|
+00000090 01 16 03 03 00 28 00 00 00 00 00 00 00 00 8a 9b |.....(..........|
+000000a0 29 1d 64 2e ee 0d 39 d9 c5 86 b9 02 9d c3 bd 74 |).d...9........t|
+000000b0 39 9d 53 9f 1a ee 84 64 82 82 41 81 f8 2f |9.S....d..A../|
+>>> Flow 4 (server to client)
+00000000 14 03 03 00 01 01 16 03 03 00 28 60 71 25 f9 f9 |..........(`q%..|
+00000010 89 cd f8 6f 00 a6 0e 92 f8 3e 84 08 79 6f 91 cd |...o.....>..yo..|
+00000020 e2 62 d5 da 96 79 c3 0d f4 34 26 bd 47 9c 30 aa |.b...y...4&.G.0.|
+00000030 1b 5f 24 |._$|
+>>> Flow 5 (client to server)
+00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 44 05 c9 |.............D..|
+00000010 2b 82 55 26 ab 4b 65 b1 94 e5 8a 81 bf 44 a5 cb |+.U&.Ke......D..|
+00000020 22 f0 0a 15 03 03 00 1a 00 00 00 00 00 00 00 02 |"...............|
+00000030 59 8d 6f 5d 30 47 4d 3e ed aa 87 5f ca 39 44 a4 |Y.o]0GM>..._.9D.|
+00000040 9b fc |..|
--- /dev/null
+>>> Flow 1 (client to server)
+00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 22 c0 2f |............."./|
+00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
+00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
+00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
+00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
+00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
+00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
+>>> Flow 2 (server to client)
+00000000 16 03 03 00 51 02 00 00 4d 03 03 08 e2 40 1b 1a |....Q...M....@..|
+00000010 54 dc 66 60 e1 e0 8d 94 c6 dd 2c eb 95 e0 e9 2f |T.f`......,..../|
+00000020 fb 49 17 d8 34 d7 a2 7a 1b e1 60 20 26 a3 4b 7c |.I..4..z..` &.K||
+00000030 40 cc df 4b 9c 72 a9 e6 61 89 1e 20 b2 e5 e3 1e |@..K.r..a.. ....|
+00000040 4e a3 b6 32 ce fc 94 0d ab 13 74 f8 00 9d 00 00 |N..2......t.....|
+00000050 05 ff 01 00 01 00 16 03 03 02 71 0b 00 02 6d 00 |..........q...m.|
+00000060 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
+00000070 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
+00000080 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
+00000090 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
+000000a0 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
+000000b0 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
+000000c0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
+000000d0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
+000000e0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
+000000f0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
+00000100 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
+00000110 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
+00000120 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
+00000130 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
+00000140 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
+00000150 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
+00000160 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
+00000170 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
+00000180 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
+00000190 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
+000001a0 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
+000001b0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
+000001c0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
+000001d0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
+000001e0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
+000001f0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
+00000200 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
+00000210 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
+00000220 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
+00000230 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
+00000240 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
+00000250 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
+00000260 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
+00000270 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
+00000280 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
+00000290 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
+000002a0 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
+000002b0 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
+000002c0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 03 00 |..A4......9.....|
+000002d0 04 0e 00 00 00 |.....|
+>>> Flow 3 (client to server)
+00000000 16 03 03 00 86 10 00 00 82 00 80 73 bd 73 65 92 |...........s.se.|
+00000010 86 23 41 14 79 7f d5 c1 10 ce 94 4d ad 9c c3 a9 |.#A.y......M....|
+00000020 87 b5 32 52 f8 6b 11 93 2d 9b 98 0b 8b 1d c0 f6 |..2R.k..-.......|
+00000030 53 17 6d c7 9c 2e ae c9 6f cc 99 23 38 37 1a 10 |S.m.....o..#87..|
+00000040 fe 05 0b b5 55 0a 14 e9 60 7d 70 26 98 e2 54 d9 |....U...`}p&..T.|
+00000050 65 cf 2e f4 53 5f 1d aa 3a f6 33 7b eb 4c 0e b3 |e...S_..:.3{.L..|
+00000060 ff 5a db 36 2a 47 f3 df f9 fc f5 31 78 83 aa 6b |.Z.6*G.....1x..k|
+00000070 52 b7 ba 1a 96 bc fa c1 a1 a9 bb 2b f5 38 89 00 |R..........+.8..|
+00000080 4d e5 78 13 4e a4 38 46 42 dc 16 14 03 03 00 01 |M.x.N.8FB.......|
+00000090 01 16 03 03 00 28 00 00 00 00 00 00 00 00 28 9a |.....(........(.|
+000000a0 46 23 21 fa a9 ec 6d 57 d1 27 2f 53 58 a9 00 48 |F#!...mW.'/SX..H|
+000000b0 7e 82 82 b8 23 f3 c4 a8 d3 2c a3 99 76 2e |~...#....,..v.|
+>>> Flow 4 (server to client)
+00000000 14 03 03 00 01 01 16 03 03 00 28 0c c8 0a e1 b8 |..........(.....|
+00000010 95 b9 84 bc 0f 48 eb d4 4a a5 63 c2 92 58 8a 91 |.....H..J.c..X..|
+00000020 27 30 36 28 23 f5 50 bd d6 a9 e9 61 54 10 f9 72 |'06(#.P....aT..r|
+00000030 98 d1 0e |...|
+>>> Flow 5 (client to server)
+00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 b9 55 ce |..............U.|
+00000010 5a ab 7e 7e 58 4f c9 5a bc 0e 93 98 4f 87 86 98 |Z.~~XO.Z....O...|
+00000020 a6 40 7e 15 03 03 00 1a 00 00 00 00 00 00 00 02 |.@~.............|
+00000030 57 0c 6f d9 28 87 d4 a6 de 14 91 a7 79 cc 19 e5 |W.o.(.......y...|
+00000040 28 66 |(f|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 99 01 00 00 95 03 03 00 00 00 00 00 |................|
+00000000 16 03 01 00 9d 01 00 00 99 03 03 00 00 00 00 00 |................|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 22 c0 2f |............."./|
00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 4e |...../.5.......N|
-00000050 33 74 00 00 00 05 00 05 01 00 00 00 00 00 0a 00 |3t..............|
-00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
-00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
-00000080 03 ff 01 00 01 00 00 10 00 10 00 0e 06 70 72 6f |.............pro|
-00000090 74 6f 32 06 70 72 6f 74 6f 31 00 12 00 00 |to2.proto1....|
+00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
+00000050 01 00 00 4e 33 74 00 00 00 05 00 05 01 00 00 00 |...N3t..........|
+00000060 00 00 0a 00 08 00 06 00 17 00 18 00 19 00 0b 00 |................|
+00000070 02 01 00 00 0d 00 0e 00 0c 04 01 04 03 05 01 05 |................|
+00000080 03 02 01 02 03 ff 01 00 01 00 00 10 00 10 00 0e |................|
+00000090 06 70 72 6f 74 6f 32 06 70 72 6f 74 6f 31 00 12 |.proto2.proto1..|
+000000a0 00 00 |..|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 66 02 00 00 62 03 03 56 83 34 0f 9e |....f...b..V.4..|
-00000010 dd 02 1c 4f 4f 09 d0 2c df e6 c1 d2 4a c0 6a e7 |...OO..,....J.j.|
-00000020 1e 65 51 c2 42 01 05 70 4a 6c 97 20 0f a8 fb d8 |.eQ.B..pJl. ....|
-00000030 2f 0f 75 21 17 f8 dd 63 28 4a 18 f6 b1 e5 6f 7c |/.u!...c(J....o||
-00000040 1d 09 d4 13 bf 66 3a bd c5 48 14 fc c0 2f 00 00 |.....f:..H.../..|
+00000000 16 03 03 00 66 02 00 00 62 03 03 a2 7d b9 7c f9 |....f...b...}.|.|
+00000010 bf fb cb b2 d5 11 c0 99 19 73 3d b4 eb 6b 39 f8 |.........s=..k9.|
+00000020 1b 7c 1d 6b 17 4d 66 a3 ed 20 5b 20 ee 87 d7 1f |.|.k.Mf.. [ ....|
+00000030 cf 60 6c 75 12 8b de 56 f6 ca da 4a 92 76 49 43 |.`lu...V...J.vIC|
+00000040 70 18 0a e7 7b 2a 0c f3 44 a6 d8 dd c0 2f 00 00 |p...{*..D..../..|
00000050 1a ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 10 |................|
-00000060 00 09 00 07 06 70 72 6f 74 6f 31 16 03 03 02 be |.....proto1.....|
-00000070 0b 00 02 ba 00 02 b7 00 02 b4 30 82 02 b0 30 82 |..........0...0.|
-00000080 02 19 a0 03 02 01 02 02 09 00 85 b0 bb a4 8a 7f |................|
-00000090 b8 ca 30 0d 06 09 2a 86 48 86 f7 0d 01 01 05 05 |..0...*.H.......|
-000000a0 00 30 45 31 0b 30 09 06 03 55 04 06 13 02 41 55 |.0E1.0...U....AU|
-000000b0 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d 65 2d |1.0...U....Some-|
-000000c0 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a 13 18 |State1!0...U....|
-000000d0 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 74 73 |Internet Widgits|
-000000e0 20 50 74 79 20 4c 74 64 30 1e 17 0d 31 30 30 34 | Pty Ltd0...1004|
-000000f0 32 34 30 39 30 39 33 38 5a 17 0d 31 31 30 34 32 |24090938Z..11042|
-00000100 34 30 39 30 39 33 38 5a 30 45 31 0b 30 09 06 03 |4090938Z0E1.0...|
-00000110 55 04 06 13 02 41 55 31 13 30 11 06 03 55 04 08 |U....AU1.0...U..|
-00000120 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f |..Some-State1!0.|
-00000130 06 03 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 |..U....Internet |
-00000140 57 69 64 67 69 74 73 20 50 74 79 20 4c 74 64 30 |Widgits Pty Ltd0|
-00000150 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 |..0...*.H.......|
-00000160 00 03 81 8d 00 30 81 89 02 81 81 00 bb 79 d6 f5 |.....0.......y..|
-00000170 17 b5 e5 bf 46 10 d0 dc 69 be e6 2b 07 43 5a d0 |....F...i..+.CZ.|
-00000180 03 2d 8a 7a 43 85 b7 14 52 e7 a5 65 4c 2c 78 b8 |.-.zC...R..eL,x.|
-00000190 23 8c b5 b4 82 e5 de 1f 95 3b 7e 62 a5 2c a5 33 |#........;~b.,.3|
-000001a0 d6 fe 12 5c 7a 56 fc f5 06 bf fa 58 7b 26 3f b5 |...\zV.....X{&?.|
-000001b0 cd 04 d3 d0 c9 21 96 4a c7 f4 54 9f 5a bf ef 42 |.....!.J..T.Z..B|
-000001c0 71 00 fe 18 99 07 7f 7e 88 7d 7d f1 04 39 c4 a2 |q......~.}}..9..|
-000001d0 2e db 51 c9 7c e3 c0 4c 3b 32 66 01 cf af b1 1d |..Q.|..L;2f.....|
-000001e0 b8 71 9a 1d db db 89 6b ae da 2d 79 02 03 01 00 |.q.....k..-y....|
-000001f0 01 a3 81 a7 30 81 a4 30 1d 06 03 55 1d 0e 04 16 |....0..0...U....|
-00000200 04 14 b1 ad e2 85 5a cf cb 28 db 69 ce 23 69 de |......Z..(.i.#i.|
-00000210 d3 26 8e 18 88 39 30 75 06 03 55 1d 23 04 6e 30 |.&...90u..U.#.n0|
-00000220 6c 80 14 b1 ad e2 85 5a cf cb 28 db 69 ce 23 69 |l......Z..(.i.#i|
-00000230 de d3 26 8e 18 88 39 a1 49 a4 47 30 45 31 0b 30 |..&...9.I.G0E1.0|
-00000240 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 |...U....AU1.0...|
-00000250 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 |U....Some-State1|
-00000260 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e |!0...U....Intern|
-00000270 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c |et Widgits Pty L|
-00000280 74 64 82 09 00 85 b0 bb a4 8a 7f b8 ca 30 0c 06 |td...........0..|
-00000290 03 55 1d 13 04 05 30 03 01 01 ff 30 0d 06 09 2a |.U....0....0...*|
-000002a0 86 48 86 f7 0d 01 01 05 05 00 03 81 81 00 08 6c |.H.............l|
-000002b0 45 24 c7 6b b1 59 ab 0c 52 cc f2 b0 14 d7 87 9d |E$.k.Y..R.......|
-000002c0 7a 64 75 b5 5a 95 66 e4 c5 2b 8e ae 12 66 1f eb |zdu.Z.f..+...f..|
-000002d0 4f 38 b3 6e 60 d3 92 fd f7 41 08 b5 25 13 b1 18 |O8.n`....A..%...|
-000002e0 7a 24 fb 30 1d ba ed 98 b9 17 ec e7 d7 31 59 db |z$.0.........1Y.|
-000002f0 95 d3 1d 78 ea 50 56 5c d5 82 5a 2d 5a 5f 33 c4 |...x.PV\..Z-Z_3.|
-00000300 b6 d8 c9 75 90 96 8c 0f 52 98 b5 cd 98 1f 89 20 |...u....R...... |
-00000310 5f f2 a0 1c a3 1b 96 94 dd a9 fd 57 e9 70 e8 26 |_..........W.p.&|
-00000320 6d 71 99 9b 26 6e 38 50 29 6c 90 a7 bd d9 16 03 |mq..&n8P)l......|
-00000330 03 00 cd 0c 00 00 c9 03 00 17 41 04 85 b7 f7 7c |..........A....||
-00000340 49 4e 97 14 07 51 bc 56 2d 3f cf 1d 29 08 ac 6a |IN...Q.V-?..)..j|
-00000350 b4 e7 0d 62 d8 fd 4d 03 29 0d f8 6c 36 6f 4d 5f |...b..M.)..l6oM_|
-00000360 b7 5a 8e 37 3e c2 d9 dc f4 15 52 e9 87 71 0f e5 |.Z.7>.....R..q..|
-00000370 4e a6 88 0e 54 35 e0 8b 50 91 e1 c4 04 01 00 80 |N...T5..P.......|
-00000380 51 eb f8 d6 52 ba f5 b5 0a 22 5f 91 fe f7 ee 43 |Q...R...."_....C|
-00000390 f8 af 52 b6 27 2c fc 14 e2 fb 41 61 ff 7c b9 be |..R.',....Aa.|..|
-000003a0 f9 78 be dc 18 32 8c 4d ef 46 c0 5a a7 91 6a 1b |.x...2.M.F.Z..j.|
-000003b0 47 78 46 39 47 81 8a 2d b4 cb fd bb 44 3e a7 b7 |GxF9G..-....D>..|
-000003c0 cc 4e df 17 7b 2b 38 49 fa 9d 9f 4e cd ed f2 16 |.N..{+8I...N....|
-000003d0 03 d9 68 cf c9 5a 08 32 f8 ed 02 30 54 61 f6 c0 |..h..Z.2...0Ta..|
-000003e0 f6 78 bc ad 04 9c 8e 90 7d 3d f5 35 86 aa 6e e9 |.x......}=.5..n.|
-000003f0 a2 9a d3 86 27 9f 2d 6e ea 6e ad 82 0e aa ef 97 |....'.-n.n......|
-00000400 16 03 03 00 04 0e 00 00 00 |.........|
+00000060 00 09 00 07 06 70 72 6f 74 6f 31 16 03 03 02 71 |.....proto1....q|
+00000070 0b 00 02 6d 00 02 6a 00 02 67 30 82 02 63 30 82 |...m..j..g0..c0.|
+00000080 01 cc a0 03 02 01 02 02 09 00 a2 73 00 0c 81 00 |...........s....|
+00000090 cb f3 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 |..0...*.H.......|
+000000a0 00 30 2b 31 17 30 15 06 03 55 04 0a 13 0e 47 6f |.0+1.0...U....Go|
+000000b0 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 10 30 0e |ogle TESTING1.0.|
+000000c0 06 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e |..U....Go Root0.|
+000000d0 17 0d 31 35 30 31 30 31 30 30 30 30 30 30 5a 17 |..150101000000Z.|
+000000e0 0d 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 26 |.250101000000Z0&|
+000000f0 31 17 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c |1.0...U....Googl|
+00000100 65 20 54 45 53 54 49 4e 47 31 0b 30 09 06 03 55 |e TESTING1.0...U|
+00000110 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 2a 86 48 |....Go0..0...*.H|
+00000120 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 81 89 02 |............0...|
+00000130 81 81 00 af 87 88 f6 20 1b 95 65 6c 14 ab 44 05 |....... ..el..D.|
+00000140 af 3b 45 14 e3 b7 6d fd 00 63 4d 95 7f fe 6a 62 |.;E...m..cM...jb|
+00000150 35 86 c0 4a f9 18 7c f6 aa 25 5e 7a 64 31 66 00 |5..J..|..%^zd1f.|
+00000160 ba f4 8e 92 af c7 6b d8 76 d4 f3 5f 41 cb 6e 56 |......k.v.._A.nV|
+00000170 15 97 1b 97 c1 3c 12 39 21 66 3d 2b 16 d1 bc db |.....<.9!f=+....|
+00000180 1c c0 a7 da b7 ca ad ba da cb d5 21 50 ec de 8d |...........!P...|
+00000190 ab d1 6b 81 4b 89 02 f3 c4 be c1 6c 89 b1 44 84 |..k.K......l..D.|
+000001a0 bd 21 d1 04 7d 9d 16 4d f9 82 15 f6 ef fa d6 09 |.!..}..M........|
+000001b0 47 f2 fb 02 03 01 00 01 a3 81 93 30 81 90 30 0e |G..........0..0.|
+000001c0 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 a0 30 1d |..U...........0.|
+000001d0 06 03 55 1d 25 04 16 30 14 06 08 2b 06 01 05 05 |..U.%..0...+....|
+000001e0 07 03 01 06 08 2b 06 01 05 05 07 03 02 30 0c 06 |.....+.......0..|
+000001f0 03 55 1d 13 01 01 ff 04 02 30 00 30 19 06 03 55 |.U.......0.0...U|
+00000200 1d 0e 04 12 04 10 12 50 8d 89 6f 1b d1 dc 54 4d |.......P..o...TM|
+00000210 6e cb 69 5e 06 f4 30 1b 06 03 55 1d 23 04 14 30 |n.i^..0...U.#..0|
+00000220 12 80 10 bf 3d b6 a9 66 f2 b8 40 cf ea b4 03 78 |....=..f..@....x|
+00000230 48 1a 41 30 19 06 03 55 1d 11 04 12 30 10 82 0e |H.A0...U....0...|
+00000240 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e 67 30 0d |example.golang0.|
+00000250 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 03 81 81 |..*.H...........|
+00000260 00 92 7c af 91 55 12 18 96 59 31 a6 48 40 d5 2d |..|..U...Y1.H@.-|
+00000270 d5 ee bb 02 a0 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 |........|..0}<.v|
+00000280 da 4f 3d c0 fa ae 2d 33 24 6b 03 7b 1b 67 59 11 |.O=...-3$k.{.gY.|
+00000290 21 b5 11 bc 77 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f |!...w...n.-.5.d_|
+000002a0 22 3e 63 10 6b be ff 14 86 6d 0d f0 15 31 a8 14 |">c.k....m...1..|
+000002b0 38 1e 3b 84 87 2c cb 98 ed 51 76 b9 b1 4f dd db |8.;..,...Qv..O..|
+000002c0 9b 84 04 86 40 fa 51 dd ba b4 8d eb e3 46 de 46 |....@.Q......F.F|
+000002d0 b9 4f 86 c7 f9 a4 c2 41 34 ac cc f6 ea b0 ab 39 |.O.....A4......9|
+000002e0 18 16 03 03 00 cd 0c 00 00 c9 03 00 17 41 04 41 |.............A.A|
+000002f0 a4 1f 6f ea 6d 59 68 72 1a 6d 47 c7 b4 a0 08 01 |..o.mYhr.mG.....|
+00000300 b9 b3 d8 7a 95 75 c0 58 2a d9 29 91 e7 d9 78 b2 |...z.u.X*.)...x.|
+00000310 97 1d 52 72 2d 18 cb ce 83 8a 07 f4 bd dd 7e a1 |..Rr-.........~.|
+00000320 d2 45 51 9d bf f1 bf 01 33 3a 10 94 6c 2b 99 04 |.EQ.....3:..l+..|
+00000330 01 00 80 63 8f 03 6d b4 4d f7 27 d0 1f f2 0f ff |...c..m.M.'.....|
+00000340 af 27 c2 97 21 68 8c 32 8b 14 67 0e b5 75 3a 5b |.'..!h.2..g..u:[|
+00000350 73 08 9a c7 fd ad 8d 50 2a de e7 d6 c5 87 7a b2 |s......P*.....z.|
+00000360 06 29 0a 09 dd d4 81 d5 a7 2b 4d 20 50 72 6f be |.).......+M Pro.|
+00000370 35 9b c6 2d b0 1e 8f a2 cf 10 33 d4 53 0b 33 95 |5..-......3.S.3.|
+00000380 b8 a5 34 38 1b db 1e 45 07 36 3a 86 c7 f1 b1 3a |..48...E.6:....:|
+00000390 2e 5d 82 b2 1d 3e e1 27 8f f2 f4 2c 8c c3 27 e9 |.]...>.'...,..'.|
+000003a0 f0 9a 8f 6d 20 b1 19 8e 23 d5 04 69 e4 eb 0d eb |...m ...#..i....|
+000003b0 97 fb 71 16 03 03 00 04 0e 00 00 00 |..q.........|
>>> Flow 3 (client to server)
00000000 16 03 03 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..|
00000010 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.|
00000020 a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e |.$ >.V...(^.+-O.|
00000030 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I|
00000040 a6 b5 68 1a 41 03 56 6b dc 5a 89 14 03 03 00 01 |..h.A.Vk.Z......|
-00000050 01 16 03 03 00 28 00 00 00 00 00 00 00 00 47 18 |.....(........G.|
-00000060 39 03 93 d9 5b 27 29 70 52 68 15 79 f2 60 e6 58 |9...[')pRh.y.`.X|
-00000070 d9 98 cd ce a1 8f 4d ee 2c f0 34 9f fa 73 |......M.,.4..s|
+00000050 01 16 03 03 00 28 00 00 00 00 00 00 00 00 15 94 |.....(..........|
+00000060 6f 5b 35 9d eb 14 c8 be 23 a7 05 8c 14 86 35 a7 |o[5.....#.....5.|
+00000070 5c 91 76 4f 85 b1 09 f8 0f 58 9f ec d2 a9 |\.vO.....X....|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 28 39 76 15 70 f1 |..........(9v.p.|
-00000010 73 c9 9a 1e 76 40 bc de de 49 be 3e 10 4d 6a 42 |s...v@...I.>.MjB|
-00000020 1b 9b bd 07 6b 19 ff f9 2c 19 3c c8 e7 06 fa c8 |....k...,.<.....|
-00000030 3d 52 b4 |=R.|
+00000000 14 03 03 00 01 01 16 03 03 00 28 e7 7f 99 c9 fa |..........(.....|
+00000010 e0 a3 e3 77 68 74 37 62 26 90 d6 be ec a1 ae 5a |...wht7b&......Z|
+00000020 de af 10 f1 2e a0 42 f0 88 ed 89 54 04 b2 b9 eb |......B....T....|
+00000030 b0 91 b8 |...|
>>> Flow 5 (client to server)
-00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 14 96 ec |................|
-00000010 f4 bb ae 45 81 0c 39 10 e2 3a 91 51 04 2c 01 a8 |...E..9..:.Q.,..|
-00000020 8b a3 25 15 03 03 00 1a 00 00 00 00 00 00 00 02 |..%.............|
-00000030 fe 1a 53 01 17 ad a1 30 0a 73 17 9f 39 b4 30 ac |..S....0.s..9.0.|
-00000040 91 ee |..|
+00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 be e7 77 |...............w|
+00000010 f9 92 ac 51 d0 34 25 34 e6 35 9e ea f0 d3 89 45 |...Q.4%4.5.....E|
+00000020 84 1b 93 15 03 03 00 1a 00 00 00 00 00 00 00 02 |................|
+00000030 1a 27 54 01 c9 7c 86 4b 61 c8 98 1b d3 15 1f 93 |.'T..|.Ka.......|
+00000040 f9 42 |.B|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 92 01 00 00 8e 03 03 00 00 00 00 00 |................|
+00000000 16 03 01 00 96 01 00 00 92 03 03 00 00 00 00 00 |................|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 22 c0 2f |............."./|
00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 47 |...../.5.......G|
-00000050 33 74 00 00 00 05 00 05 01 00 00 00 00 00 0a 00 |3t..............|
-00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
-00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
-00000080 03 ff 01 00 01 00 00 10 00 09 00 07 06 70 72 6f |.............pro|
-00000090 74 6f 33 00 12 00 00 |to3....|
+00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
+00000050 01 00 00 47 33 74 00 00 00 05 00 05 01 00 00 00 |...G3t..........|
+00000060 00 00 0a 00 08 00 06 00 17 00 18 00 19 00 0b 00 |................|
+00000070 02 01 00 00 0d 00 0e 00 0c 04 01 04 03 05 01 05 |................|
+00000080 03 02 01 02 03 ff 01 00 01 00 00 10 00 09 00 07 |................|
+00000090 06 70 72 6f 74 6f 33 00 12 00 00 |.proto3....|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 59 02 00 00 55 03 03 94 d7 79 73 82 |....Y...U....ys.|
-00000010 87 7c 85 6e 8a 1b 7d bf 69 c9 98 0c 44 bd f6 78 |.|.n..}.i...D..x|
-00000020 d2 80 dc d8 7d 80 bb 91 4b d4 ed 20 fe 9f 2f 7b |....}...K.. ../{|
-00000030 f2 1a 44 36 cd ce af f1 b5 01 8a ac 18 e4 2b 23 |..D6..........+#|
-00000040 a8 ab 1a 32 23 8b 0b e2 81 a8 0a 40 c0 2f 00 00 |...2#......@./..|
+00000000 16 03 03 00 59 02 00 00 55 03 03 18 3d 15 59 fb |....Y...U...=.Y.|
+00000010 0a a4 93 d7 43 50 59 7f 6c f9 64 db b5 47 cc 17 |....CPY.l.d..G..|
+00000020 8c cd 91 b5 04 02 3f c0 5d 60 b7 20 75 ed d2 e9 |......?.]`. u...|
+00000030 b6 72 2d f7 66 34 2e 2f d2 b9 80 66 eb c3 36 f6 |.r-.f4./...f..6.|
+00000040 b2 61 77 79 a9 c2 db cd 57 5a b2 6b c0 2f 00 00 |.awy....WZ.k./..|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
-00000060 03 02 be 0b 00 02 ba 00 02 b7 00 02 b4 30 82 02 |.............0..|
-00000070 b0 30 82 02 19 a0 03 02 01 02 02 09 00 85 b0 bb |.0..............|
-00000080 a4 8a 7f b8 ca 30 0d 06 09 2a 86 48 86 f7 0d 01 |.....0...*.H....|
-00000090 01 05 05 00 30 45 31 0b 30 09 06 03 55 04 06 13 |....0E1.0...U...|
-000000a0 02 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f |.AU1.0...U....So|
-000000b0 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 |me-State1!0...U.|
-000000c0 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 |...Internet Widg|
-000000d0 69 74 73 20 50 74 79 20 4c 74 64 30 1e 17 0d 31 |its Pty Ltd0...1|
-000000e0 30 30 34 32 34 30 39 30 39 33 38 5a 17 0d 31 31 |00424090938Z..11|
-000000f0 30 34 32 34 30 39 30 39 33 38 5a 30 45 31 0b 30 |0424090938Z0E1.0|
-00000100 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 |...U....AU1.0...|
-00000110 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 |U....Some-State1|
-00000120 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e |!0...U....Intern|
-00000130 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c |et Widgits Pty L|
-00000140 74 64 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 |td0..0...*.H....|
-00000150 01 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 bb |........0.......|
-00000160 79 d6 f5 17 b5 e5 bf 46 10 d0 dc 69 be e6 2b 07 |y......F...i..+.|
-00000170 43 5a d0 03 2d 8a 7a 43 85 b7 14 52 e7 a5 65 4c |CZ..-.zC...R..eL|
-00000180 2c 78 b8 23 8c b5 b4 82 e5 de 1f 95 3b 7e 62 a5 |,x.#........;~b.|
-00000190 2c a5 33 d6 fe 12 5c 7a 56 fc f5 06 bf fa 58 7b |,.3...\zV.....X{|
-000001a0 26 3f b5 cd 04 d3 d0 c9 21 96 4a c7 f4 54 9f 5a |&?......!.J..T.Z|
-000001b0 bf ef 42 71 00 fe 18 99 07 7f 7e 88 7d 7d f1 04 |..Bq......~.}}..|
-000001c0 39 c4 a2 2e db 51 c9 7c e3 c0 4c 3b 32 66 01 cf |9....Q.|..L;2f..|
-000001d0 af b1 1d b8 71 9a 1d db db 89 6b ae da 2d 79 02 |....q.....k..-y.|
-000001e0 03 01 00 01 a3 81 a7 30 81 a4 30 1d 06 03 55 1d |.......0..0...U.|
-000001f0 0e 04 16 04 14 b1 ad e2 85 5a cf cb 28 db 69 ce |.........Z..(.i.|
-00000200 23 69 de d3 26 8e 18 88 39 30 75 06 03 55 1d 23 |#i..&...90u..U.#|
-00000210 04 6e 30 6c 80 14 b1 ad e2 85 5a cf cb 28 db 69 |.n0l......Z..(.i|
-00000220 ce 23 69 de d3 26 8e 18 88 39 a1 49 a4 47 30 45 |.#i..&...9.I.G0E|
-00000230 31 0b 30 09 06 03 55 04 06 13 02 41 55 31 13 30 |1.0...U....AU1.0|
-00000240 11 06 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 |...U....Some-Sta|
-00000250 74 65 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 |te1!0...U....Int|
-00000260 65 72 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 |ernet Widgits Pt|
-00000270 79 20 4c 74 64 82 09 00 85 b0 bb a4 8a 7f b8 ca |y Ltd...........|
-00000280 30 0c 06 03 55 1d 13 04 05 30 03 01 01 ff 30 0d |0...U....0....0.|
-00000290 06 09 2a 86 48 86 f7 0d 01 01 05 05 00 03 81 81 |..*.H...........|
-000002a0 00 08 6c 45 24 c7 6b b1 59 ab 0c 52 cc f2 b0 14 |..lE$.k.Y..R....|
-000002b0 d7 87 9d 7a 64 75 b5 5a 95 66 e4 c5 2b 8e ae 12 |...zdu.Z.f..+...|
-000002c0 66 1f eb 4f 38 b3 6e 60 d3 92 fd f7 41 08 b5 25 |f..O8.n`....A..%|
-000002d0 13 b1 18 7a 24 fb 30 1d ba ed 98 b9 17 ec e7 d7 |...z$.0.........|
-000002e0 31 59 db 95 d3 1d 78 ea 50 56 5c d5 82 5a 2d 5a |1Y....x.PV\..Z-Z|
-000002f0 5f 33 c4 b6 d8 c9 75 90 96 8c 0f 52 98 b5 cd 98 |_3....u....R....|
-00000300 1f 89 20 5f f2 a0 1c a3 1b 96 94 dd a9 fd 57 e9 |.. _..........W.|
-00000310 70 e8 26 6d 71 99 9b 26 6e 38 50 29 6c 90 a7 bd |p.&mq..&n8P)l...|
-00000320 d9 16 03 03 00 cd 0c 00 00 c9 03 00 17 41 04 7d |.............A.}|
-00000330 75 a5 53 0b a5 4d a6 81 e0 df c4 11 c9 b5 31 ba |u.S..M........1.|
-00000340 9f 7b 51 04 57 c6 e0 b9 b0 bc 4f bc 71 74 8a 2e |.{Q.W.....O.qt..|
-00000350 d1 f6 39 36 94 4e c7 d3 a7 1b 2c b5 55 04 71 01 |..96.N....,.U.q.|
-00000360 9e 2b 42 1e 8b a4 40 b2 13 4f 03 1f 51 9e 5c 04 |.+B...@..O..Q.\.|
-00000370 01 00 80 68 05 c7 4a ca df 00 85 2b 53 f7 4f c3 |...h..J....+S.O.|
-00000380 b4 0f e8 f7 b8 30 b7 36 56 65 7b 03 6a 72 f1 aa |.....0.6Ve{.jr..|
-00000390 54 30 90 9e c7 dc fc 03 96 15 70 67 13 12 a4 f4 |T0........pg....|
-000003a0 42 f0 f9 a1 48 c0 44 44 77 0e ea fd cb b5 6e 19 |B...H.DDw.....n.|
-000003b0 89 94 a7 12 67 87 47 19 c3 00 2d c4 9b d4 dc 66 |....g.G...-....f|
-000003c0 fa ca d7 97 79 9b 28 7f 74 d4 37 c0 06 63 d4 9e |....y.(.t.7..c..|
-000003d0 a1 53 16 5a 8e d7 a5 cc 90 4d 63 f9 0c 18 85 7f |.S.Z.....Mc.....|
-000003e0 0e 35 3a 49 73 88 82 51 41 e5 2d 58 aa 38 3e bd |.5:Is..QA.-X.8>.|
-000003f0 3d d8 da 16 03 03 00 04 0e 00 00 00 |=...........|
+00000060 03 02 71 0b 00 02 6d 00 02 6a 00 02 67 30 82 02 |..q...m..j..g0..|
+00000070 63 30 82 01 cc a0 03 02 01 02 02 09 00 a2 73 00 |c0............s.|
+00000080 0c 81 00 cb f3 30 0d 06 09 2a 86 48 86 f7 0d 01 |.....0...*.H....|
+00000090 01 0b 05 00 30 2b 31 17 30 15 06 03 55 04 0a 13 |....0+1.0...U...|
+000000a0 0e 47 6f 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 |.Google TESTING1|
+000000b0 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f 6f |.0...U....Go Roo|
+000000c0 74 30 1e 17 0d 31 35 30 31 30 31 30 30 30 30 30 |t0...15010100000|
+000000d0 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 30 |0Z..250101000000|
+000000e0 5a 30 26 31 17 30 15 06 03 55 04 0a 13 0e 47 6f |Z0&1.0...U....Go|
+000000f0 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 0b 30 09 |ogle TESTING1.0.|
+00000100 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
+00000110 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
+00000120 81 89 02 81 81 00 af 87 88 f6 20 1b 95 65 6c 14 |.......... ..el.|
+00000130 ab 44 05 af 3b 45 14 e3 b7 6d fd 00 63 4d 95 7f |.D..;E...m..cM..|
+00000140 fe 6a 62 35 86 c0 4a f9 18 7c f6 aa 25 5e 7a 64 |.jb5..J..|..%^zd|
+00000150 31 66 00 ba f4 8e 92 af c7 6b d8 76 d4 f3 5f 41 |1f.......k.v.._A|
+00000160 cb 6e 56 15 97 1b 97 c1 3c 12 39 21 66 3d 2b 16 |.nV.....<.9!f=+.|
+00000170 d1 bc db 1c c0 a7 da b7 ca ad ba da cb d5 21 50 |..............!P|
+00000180 ec de 8d ab d1 6b 81 4b 89 02 f3 c4 be c1 6c 89 |.....k.K......l.|
+00000190 b1 44 84 bd 21 d1 04 7d 9d 16 4d f9 82 15 f6 ef |.D..!..}..M.....|
+000001a0 fa d6 09 47 f2 fb 02 03 01 00 01 a3 81 93 30 81 |...G..........0.|
+000001b0 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
+000001c0 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
+000001d0 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
+000001e0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
+000001f0 06 03 55 1d 0e 04 12 04 10 12 50 8d 89 6f 1b d1 |..U.......P..o..|
+00000200 dc 54 4d 6e cb 69 5e 06 f4 30 1b 06 03 55 1d 23 |.TMn.i^..0...U.#|
+00000210 04 14 30 12 80 10 bf 3d b6 a9 66 f2 b8 40 cf ea |..0....=..f..@..|
+00000220 b4 03 78 48 1a 41 30 19 06 03 55 1d 11 04 12 30 |..xH.A0...U....0|
+00000230 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
+00000240 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
+00000250 03 81 81 00 92 7c af 91 55 12 18 96 59 31 a6 48 |.....|..U...Y1.H|
+00000260 40 d5 2d d5 ee bb 02 a0 f5 c2 1e 7c 9b b3 30 7d |@.-........|..0}|
+00000270 3c dc 76 da 4f 3d c0 fa ae 2d 33 24 6b 03 7b 1b |<.v.O=...-3$k.{.|
+00000280 67 59 11 21 b5 11 bc 77 b9 d9 e0 6e a8 2d 2e 35 |gY.!...w...n.-.5|
+00000290 fa 64 5f 22 3e 63 10 6b be ff 14 86 6d 0d f0 15 |.d_">c.k....m...|
+000002a0 31 a8 14 38 1e 3b 84 87 2c cb 98 ed 51 76 b9 b1 |1..8.;..,...Qv..|
+000002b0 4f dd db 9b 84 04 86 40 fa 51 dd ba b4 8d eb e3 |O......@.Q......|
+000002c0 46 de 46 b9 4f 86 c7 f9 a4 c2 41 34 ac cc f6 ea |F.F.O.....A4....|
+000002d0 b0 ab 39 18 16 03 03 00 cd 0c 00 00 c9 03 00 17 |..9.............|
+000002e0 41 04 62 52 78 76 89 36 e7 b9 a6 cc df 8e f8 c3 |A.bRxv.6........|
+000002f0 52 54 b6 42 9b 68 65 65 27 91 bf 1b 0f 21 ab a9 |RT.B.hee'....!..|
+00000300 f4 00 62 dd 70 25 b8 ec d0 3d 9b 0c 53 16 6e eb |..b.p%...=..S.n.|
+00000310 a8 c3 1a ad a9 de ec 27 64 07 e8 9b b8 bf 5a 6c |.......'d.....Zl|
+00000320 87 f4 04 01 00 80 05 ec 2b f7 2e a4 5e 79 85 6f |........+...^y.o|
+00000330 64 7a b5 fb 9a e9 f1 12 ae 28 93 4b 6d 8e a0 2f |dz.......(.Km../|
+00000340 94 bc 38 26 01 64 ab fb 03 c8 3d 17 bc b4 43 09 |..8&.d....=...C.|
+00000350 19 c8 e9 ac 60 40 67 57 71 e3 72 22 cf b1 a7 38 |....`@gWq.r"...8|
+00000360 ac 86 88 9d 47 6f 70 c9 43 82 75 b6 bf 42 4e 72 |....Gop.C.u..BNr|
+00000370 12 48 d1 2b ce 74 02 5d 30 56 66 6f 71 8f 9b 82 |.H.+.t.]0Vfoq...|
+00000380 70 3b 92 5d fb 37 d3 cf d3 23 27 d2 d5 8d 72 22 |p;.].7...#'...r"|
+00000390 d4 b4 92 6d 64 06 d9 0b e0 bb 34 eb bf 42 ec 6a |...md.....4..B.j|
+000003a0 ea e3 56 68 85 a0 16 03 03 00 04 0e 00 00 00 |..Vh...........|
>>> Flow 3 (client to server)
00000000 16 03 03 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..|
00000010 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.|
00000020 a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e |.$ >.V...(^.+-O.|
00000030 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I|
00000040 a6 b5 68 1a 41 03 56 6b dc 5a 89 14 03 03 00 01 |..h.A.Vk.Z......|
-00000050 01 16 03 03 00 28 00 00 00 00 00 00 00 00 a8 da |.....(..........|
-00000060 74 a6 d0 a5 26 86 f3 5f 89 a4 af ac 9c 1a 01 1f |t...&.._........|
-00000070 89 8a 1c fc cf 68 3e a5 a3 20 1a b3 78 af |.....h>.. ..x.|
+00000050 01 16 03 03 00 28 00 00 00 00 00 00 00 00 97 34 |.....(.........4|
+00000060 d5 c2 64 97 f6 a9 f5 60 bc 17 f3 d3 02 3f 42 a8 |..d....`.....?B.|
+00000070 2f ba eb c6 50 3c ec 9b 8d 3b 22 ed ec 35 |/...P<...;"..5|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 28 1a f2 a9 e8 71 |..........(....q|
-00000010 b2 a6 ca 36 4a ea 55 f6 20 03 fd f7 90 c3 af 30 |...6J.U. ......0|
-00000020 d3 29 c3 d7 1b d6 4d 3e 61 55 94 0d 4e 3e 83 1a |.)....M>aU..N>..|
-00000030 97 dd 19 |...|
+00000000 14 03 03 00 01 01 16 03 03 00 28 9a e5 f5 51 5c |..........(...Q\|
+00000010 cb be 5d a1 67 cc 55 aa ba db e7 0a ab 96 3b 33 |..].g.U.......;3|
+00000020 5f 2c 8c 61 20 f1 0d 6e ce 90 d8 39 27 d7 fb 68 |_,.a ..n...9'..h|
+00000030 d9 dd da |...|
>>> Flow 5 (client to server)
-00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 94 5b 5e |..............[^|
-00000010 51 a1 52 ee 19 78 78 ef 12 0d 9c 66 bf e2 48 cb |Q.R..xx....f..H.|
-00000020 f6 00 1e 15 03 03 00 1a 00 00 00 00 00 00 00 02 |................|
-00000030 cd 5d 31 58 d9 5a 12 65 5b c6 7e 4e e2 04 e7 1d |.]1X.Z.e[.~N....|
-00000040 b1 4c |.L|
+00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 a8 be 7c |...............||
+00000010 05 48 ea df 62 4a 7a 45 68 e4 dc e6 42 ff 06 f2 |.H..bJzEh...B...|
+00000020 02 33 1a 15 03 03 00 1a 00 00 00 00 00 00 00 02 |.3..............|
+00000030 66 68 f4 de da 69 b4 f9 80 9c 80 c6 46 e5 2b ae |fh...i......F.+.|
+00000040 0e d1 |..|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 81 01 00 00 7d 03 03 00 00 00 00 00 |........}.......|
+00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 22 c0 2f |............."./|
00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 36 |...../.5.......6|
-00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
-00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
-00000070 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
-00000080 01 00 00 12 00 00 |......|
+00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
+00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
+00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
+00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
+00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 59 02 00 00 55 03 03 a5 28 60 99 bf |....Y...U...(`..|
-00000010 c7 54 04 87 60 ad c5 32 f6 bf ed 11 47 de 4d ff |.T..`..2....G.M.|
-00000020 99 e1 8f 88 f6 af 10 6e 29 74 0a 20 1d 39 cb e0 |.......n)t. .9..|
-00000030 a5 11 fe 8e 23 11 83 c7 a6 53 fc 97 03 9d ff 7c |....#....S.....||
-00000040 cf 51 ba 41 64 61 38 22 5c c6 4a 04 c0 09 00 00 |.Q.Ada8"\.J.....|
+00000000 16 03 03 00 59 02 00 00 55 03 03 f0 5c 85 c8 ff |....Y...U...\...|
+00000010 c5 57 76 99 3d 75 e6 2e db 31 26 c0 0c 81 c5 6b |.Wv.=u...1&....k|
+00000020 30 79 e6 72 86 77 48 01 ec 43 1a 20 f8 fd ad b5 |0y.r.wH..C. ....|
+00000030 a0 7b f3 35 27 df ad 95 f9 56 f9 79 6c a2 6c 23 |.{.5'....V.yl.l#|
+00000040 51 4c ef fc 92 fb fa 59 97 e9 63 27 c0 09 00 00 |QL.....Y..c'....|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
00000060 03 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..|
00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....|
00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....|
00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.|
00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....|
-00000270 2a 16 03 03 00 d7 0c 00 00 d3 03 00 17 41 04 c4 |*............A..|
-00000280 0a 40 05 84 eb 90 3c 13 d0 90 af 69 fa 5c 20 75 |.@....<....i.\ u|
-00000290 e1 9b f2 30 f7 df cc 75 2c 35 7e 38 16 99 7d 57 |...0...u,5~8..}W|
-000002a0 6d d7 f0 93 2d 1d c8 03 89 6e 52 3b 20 e5 8a 5f |m...-....nR; .._|
-000002b0 6d ca 6e 6a ca 51 f8 a4 dc 1d ec 3e 73 c9 72 04 |m.nj.Q.....>s.r.|
-000002c0 03 00 8a 30 81 87 02 41 37 bf 0d 1d c1 9a 37 39 |...0...A7.....79|
-000002d0 4d 4a f8 17 50 5d 4c 78 d4 25 99 9d 81 48 98 a8 |MJ..P]Lx.%...H..|
-000002e0 ff 2d 3f 98 4b 9f d8 96 2b fa 37 cc e8 66 25 0e |.-?.K...+.7..f%.|
-000002f0 d3 5e 53 c5 3b ad 17 3f 21 ce d2 45 d8 93 95 6c |.^S.;..?!..E...l|
-00000300 25 f9 5a 10 9f 37 c8 14 a6 02 42 00 e6 bd 9a 89 |%.Z..7....B.....|
-00000310 8e 73 40 f4 90 e6 d8 e2 98 51 10 23 fb 98 e5 47 |.s@......Q.#...G|
-00000320 0c 2a 7a 2f 02 66 a8 20 e4 cb 4f ba 14 1d 9e 3a |.*z/.f. ..O....:|
-00000330 2f 09 47 44 02 e0 9f 30 21 71 f0 99 09 de 23 d2 |/.GD...0!q....#.|
-00000340 f5 f0 b2 93 70 a3 8f 79 b9 4f 88 0b 35 16 03 03 |....p..y.O..5...|
-00000350 00 2e 0d 00 00 26 03 01 02 40 00 1e 06 01 06 02 |.....&...@......|
-00000360 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 |................|
-00000370 03 02 03 03 02 01 02 02 02 03 00 00 0e 00 00 00 |................|
+00000270 2a 16 03 03 00 d8 0c 00 00 d4 03 00 17 41 04 51 |*............A.Q|
+00000280 1e 2e 40 c5 a1 13 15 f0 bc 8a 04 e1 9a 57 74 10 |..@..........Wt.|
+00000290 7e b3 17 bf 0c c9 85 9b 5f bd 6b 39 c7 a6 c0 50 |~......._.k9...P|
+000002a0 0e 5e 9b b1 8c cc 57 39 e8 0f 94 02 be 28 19 16 |.^....W9.....(..|
+000002b0 94 73 2b c1 3c a7 0f c9 e7 b0 89 ac 13 53 f9 04 |.s+.<........S..|
+000002c0 03 00 8b 30 81 88 02 42 01 1b e0 ab 94 02 aa 27 |...0...B.......'|
+000002d0 fa 7b 99 9c 68 36 d8 2d 2e e0 92 84 c7 7b 37 74 |.{..h6.-.....{7t|
+000002e0 6a ad a8 f5 50 3f 74 d5 e8 8e 5a db 31 43 c8 98 |j...P?t...Z.1C..|
+000002f0 d3 ee 61 43 80 9a 72 eb 2d 2b 21 b8 33 aa 61 0a |..aC..r.-+!.3.a.|
+00000300 cd dc 85 88 29 26 83 ee 3c b2 02 42 00 b6 ea 34 |....)&..<..B...4|
+00000310 30 71 5c 0a 9a 6d a2 25 62 1c 3e 13 90 9c a3 b8 |0q\..m.%b.>.....|
+00000320 0d 97 a8 06 26 9e 31 50 88 9a b9 ff 12 63 a8 14 |....&.1P.....c..|
+00000330 18 f3 c2 b0 af d1 27 25 a9 ec ef 69 85 7a 72 c6 |......'%...i.zr.|
+00000340 b0 88 d2 c1 41 43 f4 69 62 25 13 eb f9 f8 16 03 |....AC.ib%......|
+00000350 03 00 2e 0d 00 00 26 03 01 02 40 00 1e 06 01 06 |......&...@.....|
+00000360 02 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 |................|
+00000370 01 03 02 03 03 02 01 02 02 02 03 00 00 0e 00 00 |................|
+00000380 00 |.|
>>> Flow 3 (client to server)
00000000 16 03 03 02 0a 0b 00 02 06 00 02 03 00 02 00 30 |...............0|
00000010 82 01 fc 30 82 01 5e 02 09 00 9a 30 84 6c 26 35 |...0..^....0.l&5|
00000220 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd a7 |Q.5uq..T[....g..|
00000230 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e f1 |$ >.V...(^.+-O..|
00000240 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 |..lK[.V.2B.X..I.|
-00000250 b5 68 1a 41 03 56 6b dc 5a 89 16 03 03 00 92 0f |.h.A.Vk.Z.......|
-00000260 00 00 8e 05 03 00 8a 30 81 87 02 42 00 cc a4 ad |.......0...B....|
-00000270 0b ff 09 40 8f 2c a6 37 72 1d f7 d2 19 74 85 ad |...@.,.7r....t..|
-00000280 ac 33 b0 b8 5b 56 39 cf b0 ef 46 68 94 39 4c d0 |.3..[V9...Fh.9L.|
-00000290 f4 97 32 10 99 36 c5 95 c8 14 23 37 78 46 5c a9 |..2..6....#7xF\.|
-000002a0 20 95 65 47 ff 54 02 f1 aa 1d d7 bc 39 2d 02 41 | .eG.T......9-.A|
-000002b0 2e f9 d6 8c e8 c5 a9 6f 10 4f d6 5f 4e 88 e9 71 |.......o.O._N..q|
-000002c0 23 5b 6f b8 ab 19 d3 dd ec f3 32 e3 3b fa 41 a2 |#[o.......2.;.A.|
-000002d0 e8 ae dc 27 8d 4e 79 f4 47 ef c9 8f bf 0b 41 3b |...'.Ny.G.....A;|
-000002e0 94 16 cb 8f 1e b5 f3 4e 6e 42 46 35 1a 0c ca 79 |.......NnBF5...y|
-000002f0 4b 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 |K..........@....|
-00000300 00 00 00 00 00 00 00 00 00 00 00 00 64 1c d9 9f |............d...|
-00000310 34 ec c2 74 76 7a 9f cf 95 19 be 8d 6a 2f 25 96 |4..tvz......j/%.|
-00000320 df de 18 ca 0e c9 d4 2f e4 b0 34 10 5b 72 7a 18 |......./..4.[rz.|
-00000330 5c 64 d7 fc 2e 1b 28 10 ae a6 31 e9 |\d....(...1.|
+00000250 b5 68 1a 41 03 56 6b dc 5a 89 16 03 03 00 93 0f |.h.A.Vk.Z.......|
+00000260 00 00 8f 05 03 00 8b 30 81 88 02 42 00 8a 82 c2 |.......0...B....|
+00000270 c0 30 8c a1 12 c4 4a ed d1 00 3f 2d ee bd 8e 9c |.0....J...?-....|
+00000280 a5 a0 d9 6f 44 27 49 60 e9 75 01 ee b4 0d 87 25 |...oD'I`.u.....%|
+00000290 2a 8d 67 f1 e3 d9 49 6f a0 34 90 76 93 52 f9 17 |*.g...Io.4.v.R..|
+000002a0 fb 1b cc d0 5a f4 50 37 9c 4c 44 b6 61 5f 02 42 |....Z.P7.LD.a_.B|
+000002b0 01 ad 85 38 e9 3a 69 35 ea 74 76 2c 09 6b ab d4 |...8.:i5.tv,.k..|
+000002c0 e0 dc d1 d5 03 41 22 8e 8b 53 98 b7 f1 b6 e9 29 |.....A"..S.....)|
+000002d0 d2 57 34 dc e0 b6 71 77 79 bd 57 61 7c 30 77 00 |.W4...qwy.Wa|0w.|
+000002e0 7a 42 2d 1f ed e8 14 da 16 33 c6 31 e4 3d 53 3a |zB-......3.1.=S:|
+000002f0 9a 37 14 03 03 00 01 01 16 03 03 00 40 00 00 00 |.7..........@...|
+00000300 00 00 00 00 00 00 00 00 00 00 00 00 00 d4 fe c1 |................|
+00000310 a6 fb 21 78 21 80 af 0d da a1 80 68 e2 9c ec 0b |..!x!......h....|
+00000320 57 8c 2a 7e f1 11 3b 52 ea 17 00 d1 d4 14 78 c5 |W.*~..;R......x.|
+00000330 81 39 12 ad 30 98 93 1b 29 77 45 7d 00 |.9..0...)wE}.|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 40 27 6f 24 a3 0c |..........@'o$..|
-00000010 6d d7 68 4a fb 43 b0 97 02 6c 22 7e 2f a1 f1 7a |m.hJ.C...l"~/..z|
-00000020 37 bf 38 82 dc a0 83 24 01 4b c0 4f 15 e1 7c 4c |7.8....$.K.O..|L|
-00000030 d4 cd b8 e2 71 af f5 20 7d f9 4a 48 4b f0 a1 f3 |....q.. }.JHK...|
-00000040 7b 02 29 18 c0 87 a5 dd c4 73 8e |{.)......s.|
+00000000 14 03 03 00 01 01 16 03 03 00 40 f7 0a 50 d0 87 |..........@..P..|
+00000010 fb f9 be b0 6b 8d 9b a5 8b d2 56 27 67 7d 3c 51 |....k.....V'g}<Q|
+00000020 af 53 8c 7d 61 9f 12 a5 54 5d ec 56 36 31 01 73 |.S.}a...T].V61.s|
+00000030 37 cb 5f ff 36 3c 1c 4a e3 db ec 99 bc 86 15 e4 |7._.6<.J........|
+00000040 cd 5d 87 bd d7 80 c7 b1 fe 42 9f |.].......B.|
>>> Flow 5 (client to server)
00000000 17 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........|
-00000010 00 00 00 00 00 bf 7a e1 23 0d d0 13 6e 96 81 6d |......z.#...n..m|
-00000020 32 56 0f 75 7e 01 88 5f 6d e6 d6 ca ec 3c 17 e9 |2V.u~.._m....<..|
-00000030 44 a9 c0 1c a4 15 03 03 00 30 00 00 00 00 00 00 |D........0......|
-00000040 00 00 00 00 00 00 00 00 00 00 76 be 7a 77 29 01 |..........v.zw).|
-00000050 8e 13 02 66 81 43 a0 55 03 35 22 09 de ea 52 bb |...f.C.U.5"...R.|
-00000060 51 cc c1 09 0e 9b 4d bd 94 85 |Q.....M...|
+00000010 00 00 00 00 00 ef 81 cf 63 f1 b5 6b b2 30 6f 00 |........c..k.0o.|
+00000020 0e c0 0c 5d d4 85 76 d2 30 db 6b 14 06 e4 75 0b |...]..v.0.k...u.|
+00000030 cf fc 72 aa 64 15 03 03 00 30 00 00 00 00 00 00 |..r.d....0......|
+00000040 00 00 00 00 00 00 00 00 00 00 ef 28 8a e7 15 51 |...........(...Q|
+00000050 0d 0d 27 4f 36 35 f6 43 28 d2 16 dc a3 35 33 3e |..'O65.C(....53>|
+00000060 be 80 db 31 a9 89 3d 17 c2 58 |...1..=..X|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 81 01 00 00 7d 03 03 00 00 00 00 00 |........}.......|
+00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 22 c0 2f |............."./|
00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 36 |...../.5.......6|
-00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
-00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
-00000070 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
-00000080 01 00 00 12 00 00 |......|
+00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
+00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
+00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
+00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
+00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 51 02 00 00 4d 03 03 79 e8 35 e3 d2 |....Q...M..y.5..|
-00000010 c0 5e 39 d1 46 da 9c 94 56 20 e2 06 d6 9b f6 dd |.^9.F...V ......|
-00000020 4f 7a c1 e8 34 a1 9f 8b c2 e1 fb 20 66 9c 5a 9a |Oz..4...... f.Z.|
-00000030 3d 22 ab 8e d8 81 03 94 68 a0 6c 72 d8 23 0b 4b |="......h.lr.#.K|
-00000040 fe 9d c7 49 a7 7c bd fa b5 7a 5e 5b 00 05 00 00 |...I.|...z^[....|
-00000050 05 ff 01 00 01 00 16 03 03 02 be 0b 00 02 ba 00 |................|
-00000060 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......|
-00000070 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..|
-00000080 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 45 31 0b |.*.H........0E1.|
-00000090 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..|
-000000a0 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State|
-000000b0 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter|
-000000c0 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty |
-000000d0 4c 74 64 30 1e 17 0d 31 30 30 34 32 34 30 39 30 |Ltd0...100424090|
-000000e0 39 33 38 5a 17 0d 31 31 30 34 32 34 30 39 30 39 |938Z..1104240909|
-000000f0 33 38 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 |38Z0E1.0...U....|
-00000100 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som|
-00000110 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..|
-00000120 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi|
-00000130 74 73 20 50 74 79 20 4c 74 64 30 81 9f 30 0d 06 |ts Pty Ltd0..0..|
-00000140 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 |.*.H............|
-00000150 30 81 89 02 81 81 00 bb 79 d6 f5 17 b5 e5 bf 46 |0.......y......F|
-00000160 10 d0 dc 69 be e6 2b 07 43 5a d0 03 2d 8a 7a 43 |...i..+.CZ..-.zC|
-00000170 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 8c b5 b4 82 |...R..eL,x.#....|
-00000180 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 fe 12 5c 7a |....;~b.,.3...\z|
-00000190 56 fc f5 06 bf fa 58 7b 26 3f b5 cd 04 d3 d0 c9 |V.....X{&?......|
-000001a0 21 96 4a c7 f4 54 9f 5a bf ef 42 71 00 fe 18 99 |!.J..T.Z..Bq....|
-000001b0 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e db 51 c9 7c |..~.}}..9....Q.||
-000001c0 e3 c0 4c 3b 32 66 01 cf af b1 1d b8 71 9a 1d db |..L;2f......q...|
-000001d0 db 89 6b ae da 2d 79 02 03 01 00 01 a3 81 a7 30 |..k..-y........0|
-000001e0 81 a4 30 1d 06 03 55 1d 0e 04 16 04 14 b1 ad e2 |..0...U.........|
-000001f0 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 88 |.Z..(.i.#i..&...|
-00000200 39 30 75 06 03 55 1d 23 04 6e 30 6c 80 14 b1 ad |90u..U.#.n0l....|
-00000210 e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 |..Z..(.i.#i..&..|
-00000220 88 39 a1 49 a4 47 30 45 31 0b 30 09 06 03 55 04 |.9.I.G0E1.0...U.|
-00000230 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 0a |...AU1.0...U....|
-00000240 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 |Some-State1!0...|
-00000250 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 |U....Internet Wi|
-00000260 64 67 69 74 73 20 50 74 79 20 4c 74 64 82 09 00 |dgits Pty Ltd...|
-00000270 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 55 1d 13 04 |........0...U...|
-00000280 05 30 03 01 01 ff 30 0d 06 09 2a 86 48 86 f7 0d |.0....0...*.H...|
-00000290 01 01 05 05 00 03 81 81 00 08 6c 45 24 c7 6b b1 |..........lE$.k.|
-000002a0 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a 64 75 b5 5a |Y..R.......zdu.Z|
-000002b0 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f 38 b3 6e 60 |.f..+...f..O8.n`|
-000002c0 d3 92 fd f7 41 08 b5 25 13 b1 18 7a 24 fb 30 1d |....A..%...z$.0.|
-000002d0 ba ed 98 b9 17 ec e7 d7 31 59 db 95 d3 1d 78 ea |........1Y....x.|
-000002e0 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 90 |PV\..Z-Z_3....u.|
-000002f0 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c a3 |...R...... _....|
-00000300 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b 26 |......W.p.&mq..&|
-00000310 6e 38 50 29 6c 90 a7 bd d9 16 03 03 00 2e 0d 00 |n8P)l...........|
-00000320 00 26 03 01 02 40 00 1e 06 01 06 02 06 03 05 01 |.&...@..........|
-00000330 05 02 05 03 04 01 04 02 04 03 03 01 03 02 03 03 |................|
-00000340 02 01 02 02 02 03 00 00 0e 00 00 00 |............|
+00000000 16 03 03 00 51 02 00 00 4d 03 03 e8 b5 19 bd df |....Q...M.......|
+00000010 e5 18 78 4b 01 f1 3f 7f ab 91 05 78 98 77 50 bf |..xK..?....x.wP.|
+00000020 60 f5 a4 76 7b 3c 40 9f 54 56 68 20 a1 99 57 a7 |`..v{<@.TVh ..W.|
+00000030 a8 46 ca 26 22 d8 bb 8d 93 12 48 ff be 8e d3 d4 |.F.&".....H.....|
+00000040 e0 fd cd ce f5 d9 a9 2e fe d4 cd 85 00 05 00 00 |................|
+00000050 05 ff 01 00 01 00 16 03 03 02 71 0b 00 02 6d 00 |..........q...m.|
+00000060 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
+00000070 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
+00000080 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
+00000090 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
+000000a0 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
+000000b0 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
+000000c0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
+000000d0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
+000000e0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
+000000f0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
+00000100 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
+00000110 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
+00000120 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
+00000130 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
+00000140 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
+00000150 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
+00000160 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
+00000170 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
+00000180 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
+00000190 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
+000001a0 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
+000001b0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
+000001c0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
+000001d0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
+000001e0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
+000001f0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
+00000200 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
+00000210 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
+00000220 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
+00000230 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
+00000240 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
+00000250 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
+00000260 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
+00000270 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
+00000280 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
+00000290 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
+000002a0 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
+000002b0 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
+000002c0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 03 00 |..A4......9.....|
+000002d0 2e 0d 00 00 26 03 01 02 40 00 1e 06 01 06 02 06 |....&...@.......|
+000002e0 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 03 |................|
+000002f0 02 03 03 02 01 02 02 02 03 00 00 0e 00 00 00 |...............|
>>> Flow 3 (client to server)
00000000 16 03 03 02 0a 0b 00 02 06 00 02 03 00 02 00 30 |...............0|
00000010 82 01 fc 30 82 01 5e 02 09 00 9a 30 84 6c 26 35 |...0..^....0.l&5|
000001e0 be e8 91 b3 da 1a f5 5d a3 23 f5 26 8b 45 70 8d |.......].#.&.Ep.|
000001f0 65 62 9b 7e 01 99 3d 18 f6 10 9a 38 61 9b 2e 57 |eb.~..=....8a..W|
00000200 e4 fa cc b1 8a ce e2 23 a0 87 f0 e1 67 51 eb 16 |.......#....gQ..|
-00000210 03 03 00 86 10 00 00 82 00 80 6d 51 f3 7f f9 3e |..........mQ...>|
-00000220 fb 75 82 41 36 83 e8 6a ee 2a 2e 25 90 67 4c 8e |.u.A6..j.*.%.gL.|
-00000230 62 2f 30 81 17 e0 85 09 0c 2b b7 23 d7 b0 e2 1d |b/0......+.#....|
-00000240 f7 3b d7 f5 a1 27 b6 ee 24 b6 1b cc 5b ea 66 0d |.;...'..$...[.f.|
-00000250 6a f4 e5 85 f9 da 43 b4 0e 86 85 e1 f5 aa be c8 |j.....C.........|
-00000260 ce 39 4c 9c 86 00 08 c2 4b e2 c6 ec 2f f7 ce e6 |.9L.....K.../...|
-00000270 bd 77 82 6f 23 b6 e0 bd a2 92 b7 3a ac e8 56 f1 |.w.o#......:..V.|
-00000280 af 54 5e 46 87 e9 3b 33 e7 b8 28 b7 d6 c8 90 35 |.T^F..;3..(....5|
-00000290 d4 1c 43 d1 30 6f 55 4e 0a 70 16 03 03 00 92 0f |..C.0oUN.p......|
-000002a0 00 00 8e 05 03 00 8a 30 81 87 02 41 19 c7 50 06 |.......0...A..P.|
-000002b0 42 82 f9 e5 ec 0b f7 65 7e b1 19 53 5f 23 ab 19 |B......e~..S_#..|
-000002c0 54 08 ec d2 a7 22 dd 83 7c 97 76 59 a5 6b f4 1d |T...."..|.vY.k..|
-000002d0 92 86 34 2d ce 71 bb 01 d2 8a 67 0e a8 fb 51 e4 |..4-.q....g...Q.|
-000002e0 69 9c 27 23 74 b9 fd 6f b6 5e 48 a0 cc 02 42 01 |i.'#t..o.^H...B.|
-000002f0 50 97 b7 95 14 f4 a6 f2 95 63 17 38 59 a1 51 95 |P........c.8Y.Q.|
-00000300 1e bc 99 fb fd 82 8b ab cb 4d 8e 17 a9 f8 e9 c2 |.........M......|
-00000310 9b 93 15 02 50 e6 c2 05 54 e7 8a ec 6f 93 1f 79 |....P...T...o..y|
-00000320 8d 67 e7 2d d6 65 ab 97 fd be 20 97 bd 6b c4 fc |.g.-.e.... ..k..|
-00000330 02 14 03 03 00 01 01 16 03 03 00 24 24 df 52 6e |...........$$.Rn|
-00000340 c1 35 48 fe 60 77 28 69 36 fe 96 a1 72 db a2 f5 |.5H.`w(i6...r...|
-00000350 d0 b7 c3 d9 67 e5 ee f2 d9 18 bf f0 35 80 06 c2 |....g.......5...|
+00000210 03 03 00 86 10 00 00 82 00 80 73 bd 73 65 92 86 |..........s.se..|
+00000220 23 41 14 79 7f d5 c1 10 ce 94 4d ad 9c c3 a9 87 |#A.y......M.....|
+00000230 b5 32 52 f8 6b 11 93 2d 9b 98 0b 8b 1d c0 f6 53 |.2R.k..-.......S|
+00000240 17 6d c7 9c 2e ae c9 6f cc 99 23 38 37 1a 10 fe |.m.....o..#87...|
+00000250 05 0b b5 55 0a 14 e9 60 7d 70 26 98 e2 54 d9 65 |...U...`}p&..T.e|
+00000260 cf 2e f4 53 5f 1d aa 3a f6 33 7b eb 4c 0e b3 ff |...S_..:.3{.L...|
+00000270 5a db 36 2a 47 f3 df f9 fc f5 31 78 83 aa 6b 52 |Z.6*G.....1x..kR|
+00000280 b7 ba 1a 96 bc fa c1 a1 a9 bb 2b f5 38 89 00 4d |..........+.8..M|
+00000290 e5 78 13 4e a4 38 46 42 dc 16 16 03 03 00 92 0f |.x.N.8FB........|
+000002a0 00 00 8e 05 03 00 8a 30 81 87 02 42 01 4c f6 31 |.......0...B.L.1|
+000002b0 4f ec 64 bb ce d0 96 4d 66 f3 8d 64 78 c9 2d 47 |O.d....Mf..dx.-G|
+000002c0 39 02 88 31 49 84 7f cc a8 af c1 17 35 fb 46 b1 |9..1I.......5.F.|
+000002d0 dc 07 58 71 13 6b 8e 71 2b 94 fd 41 7c 26 45 39 |..Xq.k.q+..A|&E9|
+000002e0 28 b1 aa f7 5b 89 04 de 84 d1 b5 d9 9f f3 02 41 |(...[..........A|
+000002f0 4e f6 2a ed 39 ee 63 68 da f5 ae 1b 4d f5 01 0f |N.*.9.ch....M...|
+00000300 bc f7 05 d2 96 42 67 e3 8f ff 27 d5 bf c4 53 bf |.....Bg...'...S.|
+00000310 8a d7 46 58 05 54 94 d8 73 a9 d9 38 40 5f cb 8c |..FX.T..s..8@_..|
+00000320 c7 d1 94 56 2a e1 61 32 29 f7 c9 c1 e8 95 30 e3 |...V*.a2).....0.|
+00000330 33 14 03 03 00 01 01 16 03 03 00 24 b1 86 d2 50 |3..........$...P|
+00000340 fc ea 68 b1 d9 3d b7 2c fd 2c 87 f0 d4 44 2b 22 |..h..=.,.,...D+"|
+00000350 b8 47 74 77 46 14 6d 18 b3 08 9c 3a d4 a1 ba cb |.GtwF.m....:....|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 24 40 5b dc 01 59 |..........$@[..Y|
-00000010 33 6e 61 5a 6d fc c8 a5 f5 00 9b 55 77 c5 e6 f2 |3naZm......Uw...|
-00000020 c6 5c b6 2f 94 3c 72 5b b5 0c 3e 78 88 e6 44 |.\./.<r[..>x..D|
+00000000 14 03 03 00 01 01 16 03 03 00 24 70 c7 ee d4 d3 |..........$p....|
+00000010 d3 ad dc 5a d1 a3 01 89 4d ae 0f b9 7b 97 91 4a |...Z....M...{..J|
+00000020 c0 5b e2 94 ef 5f 2f e0 90 1a 18 8a e8 50 9d |.[..._/......P.|
>>> Flow 5 (client to server)
-00000000 17 03 03 00 1a cd 2f 11 b1 3a e4 1c 31 95 9b c4 |....../..:..1...|
-00000010 37 20 9f 03 d3 45 a4 15 e1 09 1e 0c f6 5d d3 15 |7 ...E.......]..|
-00000020 03 03 00 16 d7 f6 a1 d0 ad 41 69 73 c0 40 22 f2 |.........Ais.@".|
-00000030 5f e8 c3 50 f9 35 fc 59 e0 3a |_..P.5.Y.:|
+00000000 17 03 03 00 1a e8 e8 00 30 71 09 61 65 55 90 c8 |........0q.aeU..|
+00000010 d6 fd 8d 5d a9 fb e6 2b d4 45 a9 8c ea 2f 0b 15 |...]...+.E.../..|
+00000020 03 03 00 16 f2 d3 36 ce 26 42 59 1b d7 15 c5 c4 |......6.&BY.....|
+00000030 8b 0b 06 0a d0 fd 78 62 3d 39 |......xb=9|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 81 01 00 00 7d 03 03 00 00 00 00 00 |........}.......|
+00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 22 c0 2f |............."./|
00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 36 |...../.5.......6|
-00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
-00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
-00000070 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
-00000080 01 00 00 12 00 00 |......|
+00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
+00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
+00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
+00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
+00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 59 02 00 00 55 03 03 74 fe 19 af 4b |....Y...U..t...K|
-00000010 f3 d8 92 62 5a df 90 2c cc 09 fd 79 45 26 cd 52 |...bZ..,...yE&.R|
-00000020 9a e6 da 16 99 fe 1d 91 79 a7 a0 20 b3 13 e9 03 |........y.. ....|
-00000030 52 23 5f f0 55 59 f1 9e 00 a7 77 97 90 ed 2b fb |R#_.UY....w...+.|
-00000040 9c ab fe b1 db ea 16 95 95 68 b0 e9 c0 30 00 00 |.........h...0..|
+00000000 16 03 03 00 59 02 00 00 55 03 03 f5 6d a6 9a 3d |....Y...U...m..=|
+00000010 b4 32 c7 59 b9 f7 09 bb 56 7e 06 26 02 ac eb dd |.2.Y....V~.&....|
+00000020 78 91 e4 cd f9 f4 e7 98 7f 13 f0 20 6d d5 42 4a |x.......... m.BJ|
+00000030 85 ac 86 9a a6 78 6d 5c d7 ef 9d 16 dc ff 5a 41 |.....xm\......ZA|
+00000040 91 5a 54 ff ba f6 90 f4 2a 4f fd 37 c0 30 00 00 |.ZT.....*O.7.0..|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
-00000060 03 02 be 0b 00 02 ba 00 02 b7 00 02 b4 30 82 02 |.............0..|
-00000070 b0 30 82 02 19 a0 03 02 01 02 02 09 00 85 b0 bb |.0..............|
-00000080 a4 8a 7f b8 ca 30 0d 06 09 2a 86 48 86 f7 0d 01 |.....0...*.H....|
-00000090 01 05 05 00 30 45 31 0b 30 09 06 03 55 04 06 13 |....0E1.0...U...|
-000000a0 02 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f |.AU1.0...U....So|
-000000b0 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 |me-State1!0...U.|
-000000c0 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 |...Internet Widg|
-000000d0 69 74 73 20 50 74 79 20 4c 74 64 30 1e 17 0d 31 |its Pty Ltd0...1|
-000000e0 30 30 34 32 34 30 39 30 39 33 38 5a 17 0d 31 31 |00424090938Z..11|
-000000f0 30 34 32 34 30 39 30 39 33 38 5a 30 45 31 0b 30 |0424090938Z0E1.0|
-00000100 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 |...U....AU1.0...|
-00000110 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 |U....Some-State1|
-00000120 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e |!0...U....Intern|
-00000130 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c |et Widgits Pty L|
-00000140 74 64 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 |td0..0...*.H....|
-00000150 01 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 bb |........0.......|
-00000160 79 d6 f5 17 b5 e5 bf 46 10 d0 dc 69 be e6 2b 07 |y......F...i..+.|
-00000170 43 5a d0 03 2d 8a 7a 43 85 b7 14 52 e7 a5 65 4c |CZ..-.zC...R..eL|
-00000180 2c 78 b8 23 8c b5 b4 82 e5 de 1f 95 3b 7e 62 a5 |,x.#........;~b.|
-00000190 2c a5 33 d6 fe 12 5c 7a 56 fc f5 06 bf fa 58 7b |,.3...\zV.....X{|
-000001a0 26 3f b5 cd 04 d3 d0 c9 21 96 4a c7 f4 54 9f 5a |&?......!.J..T.Z|
-000001b0 bf ef 42 71 00 fe 18 99 07 7f 7e 88 7d 7d f1 04 |..Bq......~.}}..|
-000001c0 39 c4 a2 2e db 51 c9 7c e3 c0 4c 3b 32 66 01 cf |9....Q.|..L;2f..|
-000001d0 af b1 1d b8 71 9a 1d db db 89 6b ae da 2d 79 02 |....q.....k..-y.|
-000001e0 03 01 00 01 a3 81 a7 30 81 a4 30 1d 06 03 55 1d |.......0..0...U.|
-000001f0 0e 04 16 04 14 b1 ad e2 85 5a cf cb 28 db 69 ce |.........Z..(.i.|
-00000200 23 69 de d3 26 8e 18 88 39 30 75 06 03 55 1d 23 |#i..&...90u..U.#|
-00000210 04 6e 30 6c 80 14 b1 ad e2 85 5a cf cb 28 db 69 |.n0l......Z..(.i|
-00000220 ce 23 69 de d3 26 8e 18 88 39 a1 49 a4 47 30 45 |.#i..&...9.I.G0E|
-00000230 31 0b 30 09 06 03 55 04 06 13 02 41 55 31 13 30 |1.0...U....AU1.0|
-00000240 11 06 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 |...U....Some-Sta|
-00000250 74 65 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 |te1!0...U....Int|
-00000260 65 72 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 |ernet Widgits Pt|
-00000270 79 20 4c 74 64 82 09 00 85 b0 bb a4 8a 7f b8 ca |y Ltd...........|
-00000280 30 0c 06 03 55 1d 13 04 05 30 03 01 01 ff 30 0d |0...U....0....0.|
-00000290 06 09 2a 86 48 86 f7 0d 01 01 05 05 00 03 81 81 |..*.H...........|
-000002a0 00 08 6c 45 24 c7 6b b1 59 ab 0c 52 cc f2 b0 14 |..lE$.k.Y..R....|
-000002b0 d7 87 9d 7a 64 75 b5 5a 95 66 e4 c5 2b 8e ae 12 |...zdu.Z.f..+...|
-000002c0 66 1f eb 4f 38 b3 6e 60 d3 92 fd f7 41 08 b5 25 |f..O8.n`....A..%|
-000002d0 13 b1 18 7a 24 fb 30 1d ba ed 98 b9 17 ec e7 d7 |...z$.0.........|
-000002e0 31 59 db 95 d3 1d 78 ea 50 56 5c d5 82 5a 2d 5a |1Y....x.PV\..Z-Z|
-000002f0 5f 33 c4 b6 d8 c9 75 90 96 8c 0f 52 98 b5 cd 98 |_3....u....R....|
-00000300 1f 89 20 5f f2 a0 1c a3 1b 96 94 dd a9 fd 57 e9 |.. _..........W.|
-00000310 70 e8 26 6d 71 99 9b 26 6e 38 50 29 6c 90 a7 bd |p.&mq..&n8P)l...|
-00000320 d9 16 03 03 00 cd 0c 00 00 c9 03 00 17 41 04 22 |.............A."|
-00000330 84 e9 5e 6e 35 92 a3 83 73 0a d6 0d 1a c1 4d ab |..^n5...s.....M.|
-00000340 1f ab c2 dc 3f 53 a5 7d 38 c0 92 a4 82 e1 3c c5 |....?S.}8.....<.|
-00000350 24 60 20 a5 3b c5 65 ba 9c f1 b9 a5 b9 c2 70 73 |$` .;.e.......ps|
-00000360 19 74 a6 d1 0f 75 b4 75 e0 e8 60 20 e9 23 fe 04 |.t...u.u..` .#..|
-00000370 01 00 80 92 e0 56 3f 48 0d 10 23 48 b5 95 b6 91 |.....V?H..#H....|
-00000380 3e 8a 2e c7 02 e2 85 0e 59 c8 03 24 d9 1a 1a 25 |>.......Y..$...%|
-00000390 8e 12 bb 0b 83 ac 51 36 81 3f bc 0e be b9 3b 1d |......Q6.?....;.|
-000003a0 67 56 21 4d 24 36 84 05 61 e7 70 60 d5 8e ae 97 |gV!M$6..a.p`....|
-000003b0 b8 3a d3 b1 94 72 52 cd b0 0d dd 46 b1 15 3b 58 |.:...rR....F..;X|
-000003c0 c1 a4 63 2c 4c 31 f9 c7 4f 27 c1 0f f0 24 36 72 |..c,L1..O'...$6r|
-000003d0 e0 f8 51 12 86 c2 13 ed 6b 84 a8 15 c3 d0 39 55 |..Q.....k.....9U|
-000003e0 a4 60 50 88 c9 1e 60 60 aa 8d a5 31 3e 35 c3 f8 |.`P...``...1>5..|
-000003f0 2c 90 1c 16 03 03 00 2e 0d 00 00 26 03 01 02 40 |,..........&...@|
-00000400 00 1e 06 01 06 02 06 03 05 01 05 02 05 03 04 01 |................|
-00000410 04 02 04 03 03 01 03 02 03 03 02 01 02 02 02 03 |................|
-00000420 00 00 0e 00 00 00 |......|
+00000060 03 02 71 0b 00 02 6d 00 02 6a 00 02 67 30 82 02 |..q...m..j..g0..|
+00000070 63 30 82 01 cc a0 03 02 01 02 02 09 00 a2 73 00 |c0............s.|
+00000080 0c 81 00 cb f3 30 0d 06 09 2a 86 48 86 f7 0d 01 |.....0...*.H....|
+00000090 01 0b 05 00 30 2b 31 17 30 15 06 03 55 04 0a 13 |....0+1.0...U...|
+000000a0 0e 47 6f 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 |.Google TESTING1|
+000000b0 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f 6f |.0...U....Go Roo|
+000000c0 74 30 1e 17 0d 31 35 30 31 30 31 30 30 30 30 30 |t0...15010100000|
+000000d0 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 30 |0Z..250101000000|
+000000e0 5a 30 26 31 17 30 15 06 03 55 04 0a 13 0e 47 6f |Z0&1.0...U....Go|
+000000f0 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 0b 30 09 |ogle TESTING1.0.|
+00000100 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
+00000110 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
+00000120 81 89 02 81 81 00 af 87 88 f6 20 1b 95 65 6c 14 |.......... ..el.|
+00000130 ab 44 05 af 3b 45 14 e3 b7 6d fd 00 63 4d 95 7f |.D..;E...m..cM..|
+00000140 fe 6a 62 35 86 c0 4a f9 18 7c f6 aa 25 5e 7a 64 |.jb5..J..|..%^zd|
+00000150 31 66 00 ba f4 8e 92 af c7 6b d8 76 d4 f3 5f 41 |1f.......k.v.._A|
+00000160 cb 6e 56 15 97 1b 97 c1 3c 12 39 21 66 3d 2b 16 |.nV.....<.9!f=+.|
+00000170 d1 bc db 1c c0 a7 da b7 ca ad ba da cb d5 21 50 |..............!P|
+00000180 ec de 8d ab d1 6b 81 4b 89 02 f3 c4 be c1 6c 89 |.....k.K......l.|
+00000190 b1 44 84 bd 21 d1 04 7d 9d 16 4d f9 82 15 f6 ef |.D..!..}..M.....|
+000001a0 fa d6 09 47 f2 fb 02 03 01 00 01 a3 81 93 30 81 |...G..........0.|
+000001b0 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
+000001c0 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
+000001d0 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
+000001e0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
+000001f0 06 03 55 1d 0e 04 12 04 10 12 50 8d 89 6f 1b d1 |..U.......P..o..|
+00000200 dc 54 4d 6e cb 69 5e 06 f4 30 1b 06 03 55 1d 23 |.TMn.i^..0...U.#|
+00000210 04 14 30 12 80 10 bf 3d b6 a9 66 f2 b8 40 cf ea |..0....=..f..@..|
+00000220 b4 03 78 48 1a 41 30 19 06 03 55 1d 11 04 12 30 |..xH.A0...U....0|
+00000230 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
+00000240 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
+00000250 03 81 81 00 92 7c af 91 55 12 18 96 59 31 a6 48 |.....|..U...Y1.H|
+00000260 40 d5 2d d5 ee bb 02 a0 f5 c2 1e 7c 9b b3 30 7d |@.-........|..0}|
+00000270 3c dc 76 da 4f 3d c0 fa ae 2d 33 24 6b 03 7b 1b |<.v.O=...-3$k.{.|
+00000280 67 59 11 21 b5 11 bc 77 b9 d9 e0 6e a8 2d 2e 35 |gY.!...w...n.-.5|
+00000290 fa 64 5f 22 3e 63 10 6b be ff 14 86 6d 0d f0 15 |.d_">c.k....m...|
+000002a0 31 a8 14 38 1e 3b 84 87 2c cb 98 ed 51 76 b9 b1 |1..8.;..,...Qv..|
+000002b0 4f dd db 9b 84 04 86 40 fa 51 dd ba b4 8d eb e3 |O......@.Q......|
+000002c0 46 de 46 b9 4f 86 c7 f9 a4 c2 41 34 ac cc f6 ea |F.F.O.....A4....|
+000002d0 b0 ab 39 18 16 03 03 00 cd 0c 00 00 c9 03 00 17 |..9.............|
+000002e0 41 04 2a 2a b7 63 a8 8e 34 67 32 18 57 6e fe 2a |A.**.c..4g2.Wn.*|
+000002f0 51 41 41 5f 65 a3 a7 e9 d6 0b 42 7f 77 fb 40 09 |QAA_e.....B.w.@.|
+00000300 c8 7a a2 9b fd 5f 6e 2b ce 85 f6 24 c2 8d e8 bb |.z..._n+...$....|
+00000310 69 3e dc 51 15 6f a8 db a4 fb 11 10 70 04 82 6a |i>.Q.o......p..j|
+00000320 7b 81 04 01 00 80 7a a3 c9 1b e6 02 33 39 55 36 |{.....z.....39U6|
+00000330 dc f9 2d f7 00 5b 8d f4 de 7a f7 3b 1b 4c 9a 27 |..-..[...z.;.L.'|
+00000340 f6 db 3c d1 6b f8 d6 7a 20 53 33 5f 88 9f f6 73 |..<.k..z S3_...s|
+00000350 90 2f 35 9e f6 05 b5 80 96 4f c8 85 e6 72 95 ba |./5......O...r..|
+00000360 3b 42 43 94 c3 0b db 91 ff 6b 24 c6 b1 78 de 18 |;BC......k$..x..|
+00000370 9f d5 3b 33 53 22 45 bf cb b2 d2 77 ce 03 56 7b |..;3S"E....w..V{|
+00000380 b7 56 b6 ec 04 64 62 04 f7 f8 52 1a 47 49 01 71 |.V...db...R.GI.q|
+00000390 29 9e ee 68 1f e9 c6 36 fb 77 4c 9a 14 90 e1 70 |)..h...6.wL....p|
+000003a0 7d 7e 77 92 a6 18 16 03 03 00 2e 0d 00 00 26 03 |}~w...........&.|
+000003b0 01 02 40 00 1e 06 01 06 02 06 03 05 01 05 02 05 |..@.............|
+000003c0 03 04 01 04 02 04 03 03 01 03 02 03 03 02 01 02 |................|
+000003d0 02 02 03 00 00 0e 00 00 00 |.........|
>>> Flow 3 (client to server)
00000000 16 03 03 01 fb 0b 00 01 f7 00 01 f4 00 01 f1 30 |...............0|
00000010 82 01 ed 30 82 01 58 a0 03 02 01 02 02 01 00 30 |...0..X........0|
00000220 a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e |.$ >.V...(^.+-O.|
00000230 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I|
00000240 a6 b5 68 1a 41 03 56 6b dc 5a 89 16 03 03 00 88 |..h.A.Vk.Z......|
-00000250 0f 00 00 84 05 01 00 80 33 bb 8e 67 64 03 e7 7e |........3..gd..~|
-00000260 be a5 b1 bc cf 7a 07 24 01 17 c3 3d 4b 72 dd c3 |.....z.$...=Kr..|
-00000270 64 a7 36 e8 49 ab b6 87 ce d6 af 9e 07 22 76 e8 |d.6.I........"v.|
-00000280 0d 44 a3 36 c9 eb a4 49 85 cf 72 67 e8 2a a7 5b |.D.6...I..rg.*.[|
-00000290 d3 f2 46 af 53 48 c6 13 f7 0b 5b 9c c7 4d 3e 05 |..F.SH....[..M>.|
-000002a0 3c 0f 69 a7 40 3a e8 70 04 01 1c 29 b2 42 0f 5f |<.i.@:.p...).B._|
-000002b0 1c d5 b7 5c c2 17 07 7f bd a2 b3 9a 95 81 51 24 |...\..........Q$|
-000002c0 54 5c 42 d6 a4 76 c0 d7 54 d2 11 54 bf fd dc a0 |T\B..v..T..T....|
-000002d0 ee 95 26 64 59 a0 fc 51 14 03 03 00 01 01 16 03 |..&dY..Q........|
-000002e0 03 00 28 00 00 00 00 00 00 00 00 af f4 8a be d9 |..(.............|
-000002f0 ff f1 44 e4 41 ab 9b b3 d8 b0 3d 3f 6b c5 1d b6 |..D.A.....=?k...|
-00000300 1d 9e 35 f5 20 f4 2a af e8 35 77 |..5. .*..5w|
+00000250 0f 00 00 84 05 01 00 80 45 11 dc 3c 2a fc 5f aa |........E..<*._.|
+00000260 60 09 59 47 45 cc a7 74 e3 9d 0c c3 a4 08 b0 2a |`.YGE..t.......*|
+00000270 44 47 cd 66 ed 94 54 8f d7 74 fd 47 a3 90 56 69 |DG.f..T..t.G..Vi|
+00000280 5a b6 c5 b0 bd c2 16 a2 1e af 58 37 88 cb d1 4b |Z.........X7...K|
+00000290 5c ee e6 0f 16 9b e0 d7 43 b3 e6 0a b2 90 fa 21 |\.......C......!|
+000002a0 78 95 3e 7f fc c1 b3 df a1 bf fc eb bc e8 37 63 |x.>...........7c|
+000002b0 87 33 3e c3 9a e4 6c 0f 3d 0d 9f e8 db 2d 82 ad |.3>...l.=....-..|
+000002c0 3c 6d f7 4a 5e 81 21 4f 19 0e 60 2d ef c1 40 8d |<m.J^.!O..`-..@.|
+000002d0 cb 97 4f 08 1c c0 66 e7 14 03 03 00 01 01 16 03 |..O...f.........|
+000002e0 03 00 28 00 00 00 00 00 00 00 00 8c ce 5e 94 90 |..(..........^..|
+000002f0 22 2c 8d 64 be 29 99 62 1f 95 6e 3b 51 22 9c eb |",.d.).b..n;Q"..|
+00000300 f3 0f 24 b8 a5 84 58 70 82 71 a1 |..$...Xp.q.|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 28 ff 0d 47 63 2b |..........(..Gc+|
-00000010 bd 00 3a ad 82 e3 a7 b3 b0 84 4a 26 f4 30 78 20 |..:.......J&.0x |
-00000020 80 f2 2b 15 98 61 1c cb 8b 17 67 8a 11 96 aa 93 |..+..a....g.....|
-00000030 68 f7 fb |h..|
+00000000 14 03 03 00 01 01 16 03 03 00 28 b1 23 11 48 69 |..........(.#.Hi|
+00000010 52 44 34 f1 9a 69 2b 79 fb 68 b4 53 d5 d7 08 08 |RD4..i+y.h.S....|
+00000020 34 95 5f 56 b2 57 eb 91 31 6c 32 25 b5 68 8a 8e |4._V.W..1l2%.h..|
+00000030 f1 68 6e |.hn|
>>> Flow 5 (client to server)
-00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 a6 8d 7b |...............{|
-00000010 99 5e a2 e1 95 bb 5f e4 01 f4 0e 20 52 b4 64 4e |.^...._.... R.dN|
-00000020 86 b1 3f 15 03 03 00 1a 00 00 00 00 00 00 00 02 |..?.............|
-00000030 61 98 eb d0 7c ac bd 00 ac 7a e1 32 20 3e 81 b6 |a...|....z.2 >..|
-00000040 9d d5 |..|
+00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 03 ab 9e |................|
+00000010 f0 a6 6c f1 ea 23 20 63 42 a3 9d c6 5d 41 96 c1 |..l..# cB...]A..|
+00000020 44 b2 8b 15 03 03 00 1a 00 00 00 00 00 00 00 02 |D...............|
+00000030 e9 73 41 50 28 b0 d3 00 46 81 d6 c9 1a ca ab cd |.sAP(...F.......|
+00000040 44 9b |D.|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 81 01 00 00 7d 03 03 00 00 00 00 00 |........}.......|
+00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 22 c0 2f |............."./|
00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 36 |...../.5.......6|
-00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
-00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
-00000070 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
-00000080 01 00 00 12 00 00 |......|
+00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
+00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
+00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
+00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
+00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 59 02 00 00 55 03 03 b3 7f 4e e7 11 |....Y...U....N..|
-00000010 6d bc 56 ec 9c a8 61 08 d6 5a 2a 42 7b f1 94 0a |m.V...a..Z*B{...|
-00000020 29 35 8b 7e 23 a0 6c 59 23 cf 39 20 84 09 b6 5b |)5.~#.lY#.9 ...[|
-00000030 2f 46 80 3b 26 92 fd 81 e9 24 8c e2 b8 64 a2 03 |/F.;&....$...d..|
-00000040 3a 68 c3 7b 44 f8 28 41 e2 d3 6c 7c c0 09 00 00 |:h.{D.(A..l|....|
+00000000 16 03 03 00 59 02 00 00 55 03 03 2a 01 f8 3e d1 |....Y...U..*..>.|
+00000010 52 41 2e 9a 8d 56 ff 52 3d 6a fe 65 ab 91 bb b7 |RA...V.R=j.e....|
+00000020 82 be f1 60 40 3b 80 a1 f8 dc 95 20 48 87 41 46 |...`@;..... H.AF|
+00000030 6a d2 f3 b8 d8 68 20 40 45 b7 fe 19 21 bc 84 00 |j....h @E...!...|
+00000040 5d 40 40 21 58 3e 7d fb a7 e3 30 37 c0 09 00 00 |]@@!X>}...07....|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
00000060 03 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..|
00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....|
00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....|
00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.|
00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....|
-00000270 2a 16 03 03 00 d7 0c 00 00 d3 03 00 17 41 04 0f |*............A..|
-00000280 4d b0 41 d4 dc 6b 8a 85 52 eb eb 18 4a 8f a7 e6 |M.A..k..R...J...|
-00000290 24 52 e5 86 be 57 d7 0a e7 23 84 a8 a9 6c 96 08 |$R...W...#...l..|
-000002a0 4b f7 47 32 79 d9 df 81 f6 05 40 63 3b 14 67 3b |K.G2y.....@c;.g;|
-000002b0 ea 01 a0 0d 43 1a 36 29 b3 51 7a e4 af 1b 67 04 |....C.6).Qz...g.|
-000002c0 03 00 8a 30 81 87 02 42 01 8e 57 8a b8 b7 5b 2f |...0...B..W...[/|
-000002d0 9c 31 74 d8 7d 68 d7 6e 83 73 5f fb d0 cd de 66 |.1t.}h.n.s_....f|
-000002e0 60 fa 0a 0a 15 0b 30 3b 08 b6 f1 3e 4f 20 13 62 |`.....0;...>O .b|
-000002f0 b5 ff 86 81 dc 42 a1 4c af c8 ff b3 24 81 d8 e1 |.....B.L....$...|
-00000300 d1 09 0c 32 11 92 5e dd 3f 87 02 41 76 a7 29 48 |...2..^.?..Av.)H|
-00000310 52 68 1c 72 4d d5 39 bf fa 61 ec b2 27 ce 10 4e |Rh.rM.9..a..'..N|
-00000320 86 12 3d 1e 04 9c 11 b7 b4 0c cf 98 9d 01 c3 93 |..=.............|
-00000330 cf 83 9e 92 9a ca fd 8f b1 9f 1b 20 c4 fb a4 46 |........... ...F|
-00000340 60 fc fd d5 33 b0 8f b5 b5 c8 a4 70 c5 16 03 03 |`...3......p....|
-00000350 00 2e 0d 00 00 26 03 01 02 40 00 1e 06 01 06 02 |.....&...@......|
-00000360 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 |................|
-00000370 03 02 03 03 02 01 02 02 02 03 00 00 0e 00 00 00 |................|
+00000270 2a 16 03 03 00 d8 0c 00 00 d4 03 00 17 41 04 00 |*............A..|
+00000280 9e 90 3a 3d 00 37 0a c0 43 92 6e bf b4 23 d9 64 |..:=.7..C.n..#.d|
+00000290 99 d2 90 9e eb 88 b6 d6 6f 15 4a 22 72 f0 bf 5e |........o.J"r..^|
+000002a0 72 80 93 90 aa f1 d1 9c 45 c6 6e 3a f8 a9 6f fe |r.......E.n:..o.|
+000002b0 fb 24 dc b1 4d 52 39 91 f5 48 36 06 f6 15 0e 04 |.$..MR9..H6.....|
+000002c0 03 00 8b 30 81 88 02 42 00 a9 54 74 a7 a8 d0 04 |...0...B..Tt....|
+000002d0 ae ef e4 64 38 74 21 e6 18 f0 79 b2 d7 7e 7b 0e |...d8t!...y..~{.|
+000002e0 f6 74 75 52 f0 b8 15 3c 3d 15 52 75 9f 60 03 63 |.tuR...<=.Ru.`.c|
+000002f0 15 b8 1e b8 0e 5c 58 c7 e7 2f 6d 76 c7 c8 42 7a |.....\X../mv..Bz|
+00000300 df 15 26 4b dc 9c 3b 4d b3 b6 02 42 00 a5 fd bf |..&K..;M...B....|
+00000310 a9 5d fc 87 42 24 f9 0b 7a 17 97 7c ee 45 1c 29 |.]..B$..z..|.E.)|
+00000320 3a 07 5f df 4d f2 d3 cb fc a6 fd 84 34 2c 40 84 |:._.M.......4,@.|
+00000330 06 76 bf 43 35 d2 f6 9a 7c d6 1b 5e d8 fd 08 35 |.v.C5...|..^...5|
+00000340 1b 90 0e 24 a7 48 9d 71 ab 4a 11 92 d3 6e 16 03 |...$.H.q.J...n..|
+00000350 03 00 2e 0d 00 00 26 03 01 02 40 00 1e 06 01 06 |......&...@.....|
+00000360 02 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 |................|
+00000370 01 03 02 03 03 02 01 02 02 02 03 00 00 0e 00 00 |................|
+00000380 00 |.|
>>> Flow 3 (client to server)
00000000 16 03 03 01 fb 0b 00 01 f7 00 01 f4 00 01 f1 30 |...............0|
00000010 82 01 ed 30 82 01 58 a0 03 02 01 02 02 01 00 30 |...0..X........0|
00000220 a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e |.$ >.V...(^.+-O.|
00000230 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I|
00000240 a6 b5 68 1a 41 03 56 6b dc 5a 89 16 03 03 00 88 |..h.A.Vk.Z......|
-00000250 0f 00 00 84 05 01 00 80 02 19 16 cc 97 ad 70 20 |..............p |
-00000260 bd 64 63 dd b6 81 a0 16 b3 46 4b 42 ff 21 58 2c |.dc......FKB.!X,|
-00000270 bb 2b 4c e1 4e d7 49 4d 5c 7c 63 32 3e ef e6 ad |.+L.N.IM\|c2>...|
-00000280 85 3f ab b4 5c 2a 37 76 8b 28 56 08 4f 08 b9 51 |.?..\*7v.(V.O..Q|
-00000290 71 14 07 27 47 45 11 a0 03 cf 72 7d 67 ef 31 8d |q..'GE....r}g.1.|
-000002a0 e7 db 36 76 b1 b3 f4 bf aa 6c c4 56 94 35 71 e1 |..6v.....l.V.5q.|
-000002b0 dd 88 6d 15 90 c8 70 ad d8 95 55 42 9b c1 45 19 |..m...p...UB..E.|
-000002c0 36 ce 87 c6 fd 94 8a d4 98 6e ec 18 d5 da 59 54 |6........n....YT|
-000002d0 80 a7 8c 90 ae 55 20 1c 14 03 03 00 01 01 16 03 |.....U .........|
+00000250 0f 00 00 84 05 01 00 80 20 ef 4b 1c d7 67 37 6e |........ .K..g7n|
+00000260 24 12 9e e9 59 b1 6d da e5 3e 6b 11 03 f4 96 e4 |$...Y.m..>k.....|
+00000270 2e fb 03 e1 13 af 73 4d 15 11 c1 80 e2 ed 11 c6 |......sM........|
+00000280 73 6a 96 ce d1 26 e4 bc fe 71 c9 48 32 fd d8 70 |sj...&...q.H2..p|
+00000290 01 9d 18 7b ed a3 bd 6a 68 df 45 a0 d5 77 79 d2 |...{...jh.E..wy.|
+000002a0 5b e2 8c 96 68 95 46 8d 7d e6 b6 26 fa e1 c4 05 |[...h.F.}..&....|
+000002b0 4c d1 39 4e 35 e3 0c 1b 26 37 2e 0b 9b 0b cf f7 |L.9N5...&7......|
+000002c0 25 c3 da 27 18 70 83 18 49 ff ee ba e3 f8 70 75 |%..'.p..I.....pu|
+000002d0 e8 9b 2d 89 d7 b2 00 a5 14 03 03 00 01 01 16 03 |..-.............|
000002e0 03 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............|
-000002f0 00 00 00 58 fe bc 5c ba b2 a9 96 77 2f 95 c9 10 |...X..\....w/...|
-00000300 fd 6d fc 6a 88 8c df 82 c3 a4 3d cc 28 f4 bf 7d |.m.j......=.(..}|
-00000310 4a f8 3d 97 36 e5 a0 76 92 94 da dd cc f5 e4 0e |J.=.6..v........|
-00000320 7a c4 2c |z.,|
+000002f0 00 00 00 d3 33 79 85 64 14 07 a6 93 74 f8 f8 55 |....3y.d....t..U|
+00000300 0f fb fc 8e 1b 4c 38 21 b6 61 c5 4b b2 d4 17 b2 |.....L8!.a.K....|
+00000310 c4 be a6 4b d6 3f a3 5f 3c ff 5f 1d 93 a2 c4 82 |...K.?._<._.....|
+00000320 96 90 eb |...|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 40 81 ab 5a 66 a8 |..........@..Zf.|
-00000010 0f a5 d3 07 00 66 45 1f 31 a9 ef f7 a0 d9 23 46 |.....fE.1.....#F|
-00000020 f0 3e 50 18 99 e3 5a bd eb b7 1d 81 d5 95 d5 ee |.>P...Z.........|
-00000030 21 31 41 4b 19 92 b5 95 36 da 21 c0 4a 2a a0 1c |!1AK....6.!.J*..|
-00000040 a3 9f 8e a0 6f 9d 37 5e 12 11 03 |....o.7^...|
+00000000 14 03 03 00 01 01 16 03 03 00 40 80 b0 df ff b3 |..........@.....|
+00000010 34 11 03 f5 2d fb c7 c2 38 15 df 41 97 55 0e 1d |4...-...8..A.U..|
+00000020 36 f7 a5 35 5b 63 d7 c5 a6 fd fc a1 91 32 9d cd |6..5[c.......2..|
+00000030 34 66 75 4c 5d 27 ee 89 ed d4 4a ec 67 b0 da e7 |4fuL]'....J.g...|
+00000040 f0 e7 36 eb db b9 22 97 74 30 cd |..6...".t0.|
>>> Flow 5 (client to server)
00000000 17 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........|
-00000010 00 00 00 00 00 a9 51 94 19 72 ab 9f 3e 97 5e 99 |......Q..r..>.^.|
-00000020 2c ec 13 48 3e 10 54 5f 8a 85 88 4d 1a a8 f5 ed |,..H>.T_...M....|
-00000030 c3 4f a9 59 a3 15 03 03 00 30 00 00 00 00 00 00 |.O.Y.....0......|
-00000040 00 00 00 00 00 00 00 00 00 00 25 00 6d 2f a0 f6 |..........%.m/..|
-00000050 ce 8a 30 ba 53 da 97 c6 11 f3 d2 f3 9e 66 d6 dd |..0.S........f..|
-00000060 19 f3 ee 07 03 d3 e6 f1 30 32 |........02|
+00000010 00 00 00 00 00 62 24 32 e9 40 38 c8 c3 dd 07 42 |.....b$2.@8....B|
+00000020 05 c8 7c 3d d1 27 68 00 e4 91 6c 2d 08 c1 a1 b6 |..|=.'h...l-....|
+00000030 8a 89 3d 1d c1 15 03 03 00 30 00 00 00 00 00 00 |..=......0......|
+00000040 00 00 00 00 00 00 00 00 00 00 d1 c8 bc cb cb a5 |................|
+00000050 24 1e ad c5 bf 23 92 4b 81 a6 c0 77 19 e0 46 30 |$....#.K...w..F0|
+00000060 48 51 0c cc 39 cd 4b 8d e5 a7 |HQ..9.K...|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 81 01 00 00 7d 03 03 00 00 00 00 00 |........}.......|
+00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 22 c0 2f |............."./|
00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 36 |...../.5.......6|
-00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
-00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
-00000070 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
-00000080 01 00 00 12 00 00 |......|
+00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
+00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
+00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
+00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
+00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 51 02 00 00 4d 03 03 b3 b2 22 69 e4 |....Q...M...."i.|
-00000010 1a a1 56 94 26 0c 43 b7 89 0c 34 ce dc 5a c8 ca |..V.&.C...4..Z..|
-00000020 e2 42 92 5c 75 9a b3 22 22 64 38 20 6d 2c 26 0b |.B.\u..""d8 m,&.|
-00000030 34 b6 b8 20 36 e2 58 e5 ee 1f e2 9f a0 75 f6 d9 |4.. 6.X......u..|
-00000040 0c e4 39 ce 3c 8e 2e f8 e8 d1 a2 16 00 05 00 00 |..9.<...........|
-00000050 05 ff 01 00 01 00 16 03 03 02 be 0b 00 02 ba 00 |................|
-00000060 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......|
-00000070 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..|
-00000080 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 45 31 0b |.*.H........0E1.|
-00000090 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..|
-000000a0 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State|
-000000b0 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter|
-000000c0 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty |
-000000d0 4c 74 64 30 1e 17 0d 31 30 30 34 32 34 30 39 30 |Ltd0...100424090|
-000000e0 39 33 38 5a 17 0d 31 31 30 34 32 34 30 39 30 39 |938Z..1104240909|
-000000f0 33 38 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 |38Z0E1.0...U....|
-00000100 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som|
-00000110 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..|
-00000120 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi|
-00000130 74 73 20 50 74 79 20 4c 74 64 30 81 9f 30 0d 06 |ts Pty Ltd0..0..|
-00000140 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 |.*.H............|
-00000150 30 81 89 02 81 81 00 bb 79 d6 f5 17 b5 e5 bf 46 |0.......y......F|
-00000160 10 d0 dc 69 be e6 2b 07 43 5a d0 03 2d 8a 7a 43 |...i..+.CZ..-.zC|
-00000170 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 8c b5 b4 82 |...R..eL,x.#....|
-00000180 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 fe 12 5c 7a |....;~b.,.3...\z|
-00000190 56 fc f5 06 bf fa 58 7b 26 3f b5 cd 04 d3 d0 c9 |V.....X{&?......|
-000001a0 21 96 4a c7 f4 54 9f 5a bf ef 42 71 00 fe 18 99 |!.J..T.Z..Bq....|
-000001b0 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e db 51 c9 7c |..~.}}..9....Q.||
-000001c0 e3 c0 4c 3b 32 66 01 cf af b1 1d b8 71 9a 1d db |..L;2f......q...|
-000001d0 db 89 6b ae da 2d 79 02 03 01 00 01 a3 81 a7 30 |..k..-y........0|
-000001e0 81 a4 30 1d 06 03 55 1d 0e 04 16 04 14 b1 ad e2 |..0...U.........|
-000001f0 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 88 |.Z..(.i.#i..&...|
-00000200 39 30 75 06 03 55 1d 23 04 6e 30 6c 80 14 b1 ad |90u..U.#.n0l....|
-00000210 e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 |..Z..(.i.#i..&..|
-00000220 88 39 a1 49 a4 47 30 45 31 0b 30 09 06 03 55 04 |.9.I.G0E1.0...U.|
-00000230 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 0a |...AU1.0...U....|
-00000240 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 |Some-State1!0...|
-00000250 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 |U....Internet Wi|
-00000260 64 67 69 74 73 20 50 74 79 20 4c 74 64 82 09 00 |dgits Pty Ltd...|
-00000270 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 55 1d 13 04 |........0...U...|
-00000280 05 30 03 01 01 ff 30 0d 06 09 2a 86 48 86 f7 0d |.0....0...*.H...|
-00000290 01 01 05 05 00 03 81 81 00 08 6c 45 24 c7 6b b1 |..........lE$.k.|
-000002a0 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a 64 75 b5 5a |Y..R.......zdu.Z|
-000002b0 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f 38 b3 6e 60 |.f..+...f..O8.n`|
-000002c0 d3 92 fd f7 41 08 b5 25 13 b1 18 7a 24 fb 30 1d |....A..%...z$.0.|
-000002d0 ba ed 98 b9 17 ec e7 d7 31 59 db 95 d3 1d 78 ea |........1Y....x.|
-000002e0 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 90 |PV\..Z-Z_3....u.|
-000002f0 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c a3 |...R...... _....|
-00000300 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b 26 |......W.p.&mq..&|
-00000310 6e 38 50 29 6c 90 a7 bd d9 16 03 03 00 2e 0d 00 |n8P)l...........|
-00000320 00 26 03 01 02 40 00 1e 06 01 06 02 06 03 05 01 |.&...@..........|
-00000330 05 02 05 03 04 01 04 02 04 03 03 01 03 02 03 03 |................|
-00000340 02 01 02 02 02 03 00 00 0e 00 00 00 |............|
+00000000 16 03 03 00 51 02 00 00 4d 03 03 60 8e 1c c9 6d |....Q...M..`...m|
+00000010 de 9d 2a dc 6a a6 82 71 9a 3f 8f 5b 18 52 44 4e |..*.j..q.?.[.RDN|
+00000020 4d 72 0d e7 c8 a1 b0 81 64 8c 1f 20 06 a8 17 35 |Mr......d.. ...5|
+00000030 b8 0b 96 52 30 f7 b3 d4 2a 25 94 c0 ba a8 a2 f7 |...R0...*%......|
+00000040 86 5c 18 18 3c 68 3a 71 0f bc 3f 12 00 05 00 00 |.\..<h:q..?.....|
+00000050 05 ff 01 00 01 00 16 03 03 02 71 0b 00 02 6d 00 |..........q...m.|
+00000060 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
+00000070 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
+00000080 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
+00000090 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
+000000a0 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
+000000b0 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
+000000c0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
+000000d0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
+000000e0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
+000000f0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
+00000100 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
+00000110 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
+00000120 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
+00000130 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
+00000140 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
+00000150 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
+00000160 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
+00000170 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
+00000180 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
+00000190 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
+000001a0 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
+000001b0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
+000001c0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
+000001d0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
+000001e0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
+000001f0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
+00000200 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
+00000210 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
+00000220 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
+00000230 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
+00000240 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
+00000250 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
+00000260 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
+00000270 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
+00000280 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
+00000290 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
+000002a0 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
+000002b0 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
+000002c0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 03 00 |..A4......9.....|
+000002d0 2e 0d 00 00 26 03 01 02 40 00 1e 06 01 06 02 06 |....&...@.......|
+000002e0 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 03 |................|
+000002f0 02 03 03 02 01 02 02 02 03 00 00 0e 00 00 00 |...............|
>>> Flow 3 (client to server)
00000000 16 03 03 01 fb 0b 00 01 f7 00 01 f4 00 01 f1 30 |...............0|
00000010 82 01 ed 30 82 01 58 a0 03 02 01 02 02 01 00 30 |...0..X........0|
000001d0 8b ec ab 67 be c8 64 b0 11 50 46 58 17 6b 99 1c |...g..d..PFX.k..|
000001e0 d3 1d fc 06 f1 0e e5 96 a8 0c f9 78 20 b7 44 18 |...........x .D.|
000001f0 51 8d 10 7e 4f 94 67 df a3 4e 70 73 8e 90 91 85 |Q..~O.g..Nps....|
-00000200 16 03 03 00 86 10 00 00 82 00 80 6d 51 f3 7f f9 |...........mQ...|
-00000210 3e fb 75 82 41 36 83 e8 6a ee 2a 2e 25 90 67 4c |>.u.A6..j.*.%.gL|
-00000220 8e 62 2f 30 81 17 e0 85 09 0c 2b b7 23 d7 b0 e2 |.b/0......+.#...|
-00000230 1d f7 3b d7 f5 a1 27 b6 ee 24 b6 1b cc 5b ea 66 |..;...'..$...[.f|
-00000240 0d 6a f4 e5 85 f9 da 43 b4 0e 86 85 e1 f5 aa be |.j.....C........|
-00000250 c8 ce 39 4c 9c 86 00 08 c2 4b e2 c6 ec 2f f7 ce |..9L.....K.../..|
-00000260 e6 bd 77 82 6f 23 b6 e0 bd a2 92 b7 3a ac e8 56 |..w.o#......:..V|
-00000270 f1 af 54 5e 46 87 e9 3b 33 e7 b8 28 b7 d6 c8 90 |..T^F..;3..(....|
-00000280 35 d4 1c 43 d1 30 6f 55 4e 0a 70 16 03 03 00 88 |5..C.0oUN.p.....|
-00000290 0f 00 00 84 05 01 00 80 01 24 8d bb 05 61 2d 29 |.........$...a-)|
-000002a0 12 11 90 f5 57 21 be b7 29 76 55 63 94 8e 7b 4d |....W!..)vUc..{M|
-000002b0 3b 3d 89 5b 1f b9 e1 8c 36 68 6f 31 21 50 af e4 |;=.[....6ho1!P..|
-000002c0 9f ca a5 68 55 b9 eb 36 75 3a 0c be 11 30 28 c8 |...hU..6u:...0(.|
-000002d0 8b 82 93 9a 71 37 4d 4e 4f d2 0c 2f 13 36 ad c3 |....q7MNO../.6..|
-000002e0 df 8a 1b 59 b2 f9 8b a7 74 63 75 4a f4 9d e0 6b |...Y....tcuJ...k|
-000002f0 42 02 5a a9 6e a4 a8 24 d3 23 f7 09 ee b0 dc c4 |B.Z.n..$.#......|
-00000300 6f 87 58 72 e7 e3 87 b3 6b 15 ba 7f dd 9b 93 91 |o.Xr....k.......|
-00000310 5b 21 a0 31 31 bd 15 b5 14 03 03 00 01 01 16 03 |[!.11...........|
-00000320 03 00 24 fc 0e 7c e8 3e 8b b5 dc c9 3d 38 61 a1 |..$..|.>....=8a.|
-00000330 24 d6 77 1f 06 1f 30 32 ba dd 05 68 45 f1 4f 0d |$.w...02...hE.O.|
-00000340 2e 24 09 ad c1 e5 b7 |.$.....|
+00000200 16 03 03 00 86 10 00 00 82 00 80 73 bd 73 65 92 |...........s.se.|
+00000210 86 23 41 14 79 7f d5 c1 10 ce 94 4d ad 9c c3 a9 |.#A.y......M....|
+00000220 87 b5 32 52 f8 6b 11 93 2d 9b 98 0b 8b 1d c0 f6 |..2R.k..-.......|
+00000230 53 17 6d c7 9c 2e ae c9 6f cc 99 23 38 37 1a 10 |S.m.....o..#87..|
+00000240 fe 05 0b b5 55 0a 14 e9 60 7d 70 26 98 e2 54 d9 |....U...`}p&..T.|
+00000250 65 cf 2e f4 53 5f 1d aa 3a f6 33 7b eb 4c 0e b3 |e...S_..:.3{.L..|
+00000260 ff 5a db 36 2a 47 f3 df f9 fc f5 31 78 83 aa 6b |.Z.6*G.....1x..k|
+00000270 52 b7 ba 1a 96 bc fa c1 a1 a9 bb 2b f5 38 89 00 |R..........+.8..|
+00000280 4d e5 78 13 4e a4 38 46 42 dc 16 16 03 03 00 88 |M.x.N.8FB.......|
+00000290 0f 00 00 84 05 01 00 80 21 58 47 70 c2 2e 1c 4a |........!XGp...J|
+000002a0 fa 97 b2 cf 8d f8 93 f4 b0 8c b3 e0 e7 33 a6 ea |.............3..|
+000002b0 d7 fe 8e 25 e7 f3 f5 a1 8d 09 b7 0b 01 ec a1 15 |...%............|
+000002c0 5b 67 06 53 2a 7d 31 e5 a8 16 bc e3 1d ed 5a 77 |[g.S*}1.......Zw|
+000002d0 0b 78 78 c5 fc c5 62 8e 41 49 d3 ea cd 69 10 3f |.xx...b.AI...i.?|
+000002e0 34 9e 86 df f9 9f f6 02 0c 29 c4 66 a0 45 cf 7b |4........).f.E.{|
+000002f0 ce 51 ec 0a 26 b4 9d 3d 9e 63 5d 40 1a e8 84 4e |.Q..&..=.c]@...N|
+00000300 24 f5 42 48 b5 3e f8 92 c4 f2 e6 5d f4 ad 67 01 |$.BH.>.....]..g.|
+00000310 f8 a7 a7 2b b5 fc be e8 14 03 03 00 01 01 16 03 |...+............|
+00000320 03 00 24 f0 ec 1d f5 39 1c d2 d2 c7 f4 1f 3b 0c |..$....9......;.|
+00000330 cd 25 e4 8e ed c4 bb 02 9d 38 e5 a7 91 e0 ea 00 |.%.......8......|
+00000340 73 a8 9a 63 c9 e7 7d |s..c..}|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 24 d7 b6 b3 0a e6 |..........$.....|
-00000010 86 9a 25 e4 38 de d0 57 ff 93 0b f4 de 76 3d 00 |..%.8..W.....v=.|
-00000020 64 35 cf 70 f6 ea 74 2d b0 71 2d 92 e2 df eb |d5.p..t-.q-....|
+00000000 14 03 03 00 01 01 16 03 03 00 24 0b c5 7d ca a6 |..........$..}..|
+00000010 87 7f 50 7b 88 9c d9 8e ea 78 a0 40 6b 8e 92 0b |..P{.....x.@k...|
+00000020 78 88 97 46 ec 7c 20 5b 1f fc da 49 d8 6a be |x..F.| [...I.j.|
>>> Flow 5 (client to server)
-00000000 17 03 03 00 1a db bd 43 12 7c b5 83 b5 18 9d 6a |.......C.|.....j|
-00000010 70 3f 5a eb cb d0 ba d4 03 3e a0 7b 25 f0 41 15 |p?Z......>.{%.A.|
-00000020 03 03 00 16 f8 f2 a3 27 a5 c7 25 d9 6c 08 b1 96 |.......'..%.l...|
-00000030 38 22 38 df 16 fb e2 9f 61 a3 |8"8.....a.|
+00000000 17 03 03 00 1a 16 25 97 df 98 e4 d6 8e d1 2c 0c |......%.......,.|
+00000010 27 74 67 e5 b7 f1 c7 58 41 5f 04 f5 e4 74 dc 15 |'tg....XA_...t..|
+00000020 03 03 00 16 df 55 01 0d 53 5b b4 36 c7 88 8d b0 |.....U..S[.6....|
+00000030 22 53 ec 87 1b 07 c7 9d af 89 |"S........|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 81 01 00 00 7d 03 03 00 00 00 00 00 |........}.......|
+00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 22 c0 2f |............."./|
00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 36 |...../.5.......6|
-00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
-00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
-00000070 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
-00000080 01 00 00 12 00 00 |......|
+00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
+00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
+00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
+00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
+00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 59 02 00 00 55 03 03 21 9b eb 15 24 |....Y...U..!...$|
-00000010 46 b6 c1 85 f5 be c5 0d e2 6b 60 bc ee 73 b1 fb |F........k`..s..|
-00000020 34 6f f0 b8 f0 9e 1c 26 a4 4b 0f 20 cb 2b 84 a2 |4o.....&.K. .+..|
-00000030 cb a5 48 70 fe 84 25 b0 16 20 14 a1 83 21 fc f9 |..Hp..%.. ...!..|
-00000040 82 fc 9e 1a d1 3b 56 69 ab c5 0e 2c c0 09 00 00 |.....;Vi...,....|
+00000000 16 03 03 00 59 02 00 00 55 03 03 8a ae 27 5b 39 |....Y...U....'[9|
+00000010 8b c4 a6 d5 fa 9e 67 9e 6c fe 53 ed ab ec e0 04 |......g.l.S.....|
+00000020 8d 7c f8 1f d0 db 2e cb 22 4d a1 20 ee 80 5f fc |.|......"M. .._.|
+00000030 f8 77 8a 23 23 c5 95 81 7f a6 12 f5 e0 19 91 50 |.w.##..........P|
+00000040 da 75 42 c2 eb 45 bf e2 a5 54 ed 6e c0 09 00 00 |.uB..E...T.n....|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
00000060 03 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..|
00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....|
00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....|
00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.|
00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....|
-00000270 2a 16 03 03 00 d8 0c 00 00 d4 03 00 17 41 04 b6 |*............A..|
-00000280 3f 37 33 68 cb 79 c0 86 f4 9d 12 ac c4 9d 8c 9b |?73h.y..........|
-00000290 59 1c d4 a9 01 9f 2d cb 80 24 02 ec e0 ff d1 8c |Y.....-..$......|
-000002a0 bd 82 67 3f 47 58 1a 2e 6b 61 f6 8e 4e 27 7f 49 |..g?GX..ka..N'.I|
-000002b0 b5 45 f1 0b 9a 33 ff 53 ac 65 e2 82 7a 18 5c 04 |.E...3.S.e..z.\.|
-000002c0 03 00 8b 30 81 88 02 42 00 e1 2d ff 5d e7 77 f1 |...0...B..-.].w.|
-000002d0 12 d9 e4 c2 4d cd 9c b5 ee e4 fd 21 b2 d8 53 a9 |....M......!..S.|
-000002e0 42 e7 c5 9b 51 c3 59 37 a5 08 d4 e6 29 12 c5 56 |B...Q.Y7....)..V|
-000002f0 b8 fe f0 bb 77 87 a3 ee 09 b0 8c cd 1c 39 9e b5 |....w........9..|
-00000300 d9 15 63 53 cb d7 f1 55 5b 48 02 42 01 19 10 8a |..cS...U[H.B....|
-00000310 7a ee 95 b1 77 44 d4 a3 bf d1 f3 f1 b0 d8 c7 7e |z...wD.........~|
-00000320 42 c0 83 04 f5 f7 9c c0 ce 6a 98 47 9d 21 29 84 |B........j.G.!).|
-00000330 c8 be 6b 67 4e fc c6 26 ec 63 df 00 33 e6 d2 f7 |..kgN..&.c..3...|
-00000340 34 93 85 9b 1b 0f e0 89 42 b6 0b 94 1b 80 16 03 |4.......B.......|
-00000350 03 00 04 0e 00 00 00 |.......|
+00000270 2a 16 03 03 00 d7 0c 00 00 d3 03 00 17 41 04 3e |*............A.>|
+00000280 e3 d6 d6 7b d7 ec 6f 4b 88 50 53 26 5a 2b a6 69 |...{..oK.PS&Z+.i|
+00000290 25 6f 30 a7 c3 a5 39 5c e2 ca b6 35 a5 30 35 9a |%o0...9\...5.05.|
+000002a0 35 8f e3 65 bd 4c 47 30 72 9a 4b 32 c4 6d 01 c9 |5..e.LG0r.K2.m..|
+000002b0 a5 91 d1 cd 0b 79 e2 04 0f a9 9c c2 72 cd 58 04 |.....y......r.X.|
+000002c0 03 00 8a 30 81 87 02 41 70 01 8c dd 0a 32 db e3 |...0...Ap....2..|
+000002d0 0b 04 9c d0 64 a1 08 06 b1 cf e3 66 79 1f c0 c1 |....d......fy...|
+000002e0 14 34 87 a6 e5 52 11 20 12 24 a5 b6 c2 50 63 86 |.4...R. .$...Pc.|
+000002f0 31 6a e3 85 7d 19 2d 3b 68 bf b7 64 20 37 c7 f9 |1j..}.-;h..d 7..|
+00000300 76 38 b5 32 84 0b f9 b6 71 02 42 01 89 e3 93 85 |v8.2....q.B.....|
+00000310 d6 16 8e 44 66 72 d6 9f b3 b1 e9 22 ad 2e f8 49 |...Dfr....."...I|
+00000320 41 8f 80 f9 0e d4 fd de 35 67 cf 09 ba 65 f7 a1 |A.......5g...e..|
+00000330 17 a8 c0 b5 a3 cc c0 17 83 af 68 92 5b 5c a9 ce |..........h.[\..|
+00000340 ce 11 92 93 fe 39 b9 80 19 20 f2 b6 3b 16 03 03 |.....9... ..;...|
+00000350 00 04 0e 00 00 00 |......|
>>> Flow 3 (client to server)
00000000 16 03 03 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..|
00000010 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.|
00000030 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I|
00000040 a6 b5 68 1a 41 03 56 6b dc 5a 89 14 03 03 00 01 |..h.A.Vk.Z......|
00000050 01 16 03 03 00 40 00 00 00 00 00 00 00 00 00 00 |.....@..........|
-00000060 00 00 00 00 00 00 50 73 9c 9f a8 d7 78 ac 06 14 |......Ps....x...|
-00000070 8f ae fc fb ef 7d 99 db b7 c9 91 dd f2 fe da 1b |.....}..........|
-00000080 aa 9e 7d e4 5c 2f 5f dd 74 aa fe 03 51 e7 cd 98 |..}.\/_.t...Q...|
-00000090 e9 21 19 c9 6f 59 |.!..oY|
+00000060 00 00 00 00 00 00 39 19 e6 fb c7 28 b4 c9 f5 ba |......9....(....|
+00000070 a2 44 0a 74 70 18 86 1f 5f c2 3d 99 f5 d7 17 04 |.D.tp..._.=.....|
+00000080 88 07 a5 06 01 6a 2c 13 55 0b fc 82 75 b5 24 54 |.....j,.U...u.$T|
+00000090 a0 63 9e f0 ce 92 |.c....|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 40 47 18 b5 1b 75 |..........@G...u|
-00000010 b8 a3 63 ab 77 d3 47 cb 14 26 b4 88 fe 15 db 22 |..c.w.G..&....."|
-00000020 76 3b 25 d3 68 8e f2 a7 d5 03 2b 82 7b b1 0f 10 |v;%.h.....+.{...|
-00000030 49 6a 3d 95 d0 4b 55 0e 14 eb bb a7 34 bb 57 b3 |Ij=..KU.....4.W.|
-00000040 5d fb 7e 15 80 5a fa f3 3a df 90 |].~..Z..:..|
+00000000 14 03 03 00 01 01 16 03 03 00 40 15 37 89 e6 1f |..........@.7...|
+00000010 20 f6 91 b9 1f fb 29 e9 3e 07 ab c2 09 96 06 89 | .....).>.......|
+00000020 69 c2 dd 63 e1 24 5d cd af 08 e2 ed df 46 45 6b |i..c.$]......FEk|
+00000030 1e 9f 62 b6 89 27 04 3f fc f2 77 71 23 04 24 37 |..b..'.?..wq#.$7|
+00000040 74 8a 0a 64 a8 10 e3 1c dc 53 64 |t..d.....Sd|
>>> Flow 5 (client to server)
00000000 17 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........|
-00000010 00 00 00 00 00 70 74 e2 60 fc 3a 7a b7 5e 16 07 |.....pt.`.:z.^..|
-00000020 22 92 07 fe 92 53 c4 43 1b 8f 94 07 84 48 2b 50 |"....S.C.....H+P|
-00000030 ab 1d 6d 49 ed 15 03 03 00 30 00 00 00 00 00 00 |..mI.....0......|
-00000040 00 00 00 00 00 00 00 00 00 00 ce a8 ba 91 0b e4 |................|
-00000050 8c 38 23 9b 8b 2c 0a 0c 63 79 61 f4 b6 25 f7 41 |.8#..,..cya..%.A|
-00000060 04 9f b0 8f e0 e5 24 44 2f e9 |......$D/.|
+00000010 00 00 00 00 00 ae 4e e7 3a 25 9d 8f fa 06 99 49 |......N.:%.....I|
+00000020 2e b8 0f 49 d0 54 2d 06 b4 d7 4c 60 51 f1 13 11 |...I.T-...L`Q...|
+00000030 c1 b3 f5 d0 bc 15 03 03 00 30 00 00 00 00 00 00 |.........0......|
+00000040 00 00 00 00 00 00 00 00 00 00 80 de bf db 10 74 |...............t|
+00000050 da 3f d8 77 ca 37 cc f3 96 bd d3 e1 34 9c f2 0a |.?.w.7......4...|
+00000060 70 60 5e 7c a4 7e c9 bd 89 5f |p`^|.~..._|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 81 01 00 00 7d 03 03 00 00 00 00 00 |........}.......|
+00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 22 c0 2f |............."./|
00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 36 |...../.5.......6|
-00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
-00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
-00000070 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
-00000080 01 00 00 12 00 00 |......|
+00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
+00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
+00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
+00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
+00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 59 02 00 00 55 03 03 91 8a 4f 94 29 |....Y...U....O.)|
-00000010 32 fa 66 7a 7f b8 a7 04 5c 34 b9 7e 12 83 35 1f |2.fz....\4.~..5.|
-00000020 93 b0 af e0 9f 71 07 5e 2f d7 ca 20 52 dc 0d e7 |.....q.^/.. R...|
-00000030 f8 16 db 90 9a 78 2f 03 0b f0 ae a7 2f c6 b4 4c |.....x/...../..L|
-00000040 62 e7 de 32 d5 68 61 f3 07 e4 60 d2 c0 2b 00 00 |b..2.ha...`..+..|
+00000000 16 03 03 00 59 02 00 00 55 03 03 42 ab c5 81 f5 |....Y...U..B....|
+00000010 c0 5b 73 64 f6 1b e0 59 30 b0 fd c5 e6 b3 57 f2 |.[sd...Y0.....W.|
+00000020 28 3f 5c d2 e8 05 7d a8 29 84 2e 20 8e 18 6b 52 |(?\...}.).. ..kR|
+00000030 1b ee 03 02 64 52 fb 24 44 4f 39 f2 d3 0f e6 9d |....dR.$DO9.....|
+00000040 50 31 31 b3 39 9e c1 3a b3 67 41 a0 c0 2b 00 00 |P11.9..:.gA..+..|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
00000060 03 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..|
00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....|
00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....|
00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.|
00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....|
-00000270 2a 16 03 03 00 d8 0c 00 00 d4 03 00 17 41 04 26 |*............A.&|
-00000280 c1 67 14 4b 9e b0 45 8c 27 bf a3 a2 78 5b 56 ad |.g.K..E.'...x[V.|
-00000290 d1 21 56 53 df 86 e9 91 de e3 f9 5d e6 f6 5d 79 |.!VS.......]..]y|
-000002a0 11 8b 60 f9 c2 9a c6 3f 6b 72 cd 7c d7 0e 13 64 |..`....?kr.|...d|
-000002b0 af e8 9f 40 35 e6 fb 04 0c 60 aa 19 61 dd 24 04 |...@5....`..a.$.|
-000002c0 03 00 8b 30 81 88 02 42 00 9d e1 02 5d 8b b1 45 |...0...B....]..E|
-000002d0 e5 c7 b6 94 27 df 36 31 fd 5e 47 fe c8 0f 5f 17 |....'.61.^G..._.|
-000002e0 b1 92 56 76 29 45 3d 90 be 91 6e 2c a7 b2 e1 33 |..Vv)E=...n,...3|
-000002f0 3b f9 3c bb 80 58 c2 d8 a8 59 82 16 dc 9e dd 60 |;.<..X...Y.....`|
-00000300 ff 82 b9 0c 5a ca ff f3 02 2c 02 42 00 a4 c0 d3 |....Z....,.B....|
-00000310 aa 1d 69 52 c0 06 fa 93 e8 50 da a4 2f 72 c9 4a |..iR.....P../r.J|
-00000320 2c 43 7f 95 05 f7 7a f3 4a 2e 2d ce 13 be 80 40 |,C....z.J.-....@|
-00000330 a4 3b b2 f0 73 8d f1 d4 7b a3 ff 01 e1 58 71 31 |.;..s...{....Xq1|
-00000340 fc d8 2f b3 ef 62 2e b7 ac f5 c4 bc b8 68 16 03 |../..b.......h..|
+00000270 2a 16 03 03 00 d8 0c 00 00 d4 03 00 17 41 04 7a |*............A.z|
+00000280 01 b4 2c 50 85 34 6e 2c 2c 52 bc fa cf 71 82 e5 |..,P.4n,,R...q..|
+00000290 98 8d b0 f1 65 5f 7d bc c8 1b 7c 84 3e 46 45 c5 |....e_}...|.>FE.|
+000002a0 43 0e 72 e1 90 63 40 26 1c 22 dc 9a 3b b8 12 26 |C.r..c@&."..;..&|
+000002b0 a9 d6 1c e1 44 cf c7 38 db 9e 1b d0 b9 bb 06 04 |....D..8........|
+000002c0 03 00 8b 30 81 88 02 42 01 6b af f8 34 ae 89 50 |...0...B.k..4..P|
+000002d0 df 44 20 16 0b f9 ef a9 99 63 39 48 39 08 69 2d |.D ......c9H9.i-|
+000002e0 2d 9d 8b 3a e8 8a 9c 2f e9 d2 85 f2 d3 54 53 ec |-..:.../.....TS.|
+000002f0 b7 18 5b b0 76 3c 38 02 85 cc 00 20 45 9d e7 ba |..[.v<8.... E...|
+00000300 c0 3f c0 b5 1f df 64 42 fd 34 02 42 00 fa e5 dd |.?....dB.4.B....|
+00000310 04 c4 60 60 ff 9b 95 a2 a4 b4 80 87 9f 59 b4 8e |..``.........Y..|
+00000320 72 bf 53 8e 61 b6 df 99 9d 81 05 c5 71 a2 00 cb |r.S.a.......q...|
+00000330 80 bd e5 2a c3 51 d0 45 2f a3 8b 6d 21 6e 6c 80 |...*.Q.E/..m!nl.|
+00000340 4e f1 28 23 6d 76 df 55 77 69 a1 be 39 05 16 03 |N.(#mv.Uwi..9...|
00000350 03 00 04 0e 00 00 00 |.......|
>>> Flow 3 (client to server)
00000000 16 03 03 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..|
00000020 a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e |.$ >.V...(^.+-O.|
00000030 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I|
00000040 a6 b5 68 1a 41 03 56 6b dc 5a 89 14 03 03 00 01 |..h.A.Vk.Z......|
-00000050 01 16 03 03 00 28 00 00 00 00 00 00 00 00 83 cf |.....(..........|
-00000060 ef 50 c2 e7 da b9 74 7f 1c e0 b8 fb dc 39 c9 98 |.P....t......9..|
-00000070 0c a3 7d 8c c6 fa 6f f2 ee 44 a0 a0 03 18 |..}...o..D....|
+00000050 01 16 03 03 00 28 00 00 00 00 00 00 00 00 94 ba |.....(..........|
+00000060 0a c6 38 6b 65 60 95 5e df fc 42 7e ac 9f 5a 25 |..8ke`.^..B~..Z%|
+00000070 39 0e a9 7a 61 b3 17 80 77 82 e5 80 0a af |9..za...w.....|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 28 73 c4 48 24 3d |..........(s.H$=|
-00000010 8f 5f f3 8c fc fd 63 be 64 39 d5 56 67 bd d7 c4 |._....c.d9.Vg...|
-00000020 0d 57 88 1a 45 a6 f3 ad 11 b2 5a 41 58 33 f3 d3 |.W..E.....ZAX3..|
-00000030 58 fa 21 |X.!|
+00000000 14 03 03 00 01 01 16 03 03 00 28 ef 8d ac 17 6f |..........(....o|
+00000010 88 03 88 8f f3 d5 a0 60 28 a9 4d e8 20 ae 0c 21 |.......`(.M. ..!|
+00000020 fd d1 50 9b c3 d1 e9 cd 27 ed d7 8b 92 60 49 47 |..P.....'....`IG|
+00000030 ed 9a 74 |..t|
>>> Flow 5 (client to server)
-00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 65 5e 55 |.............e^U|
-00000010 32 be 00 77 6e 1d 8e 8f 95 33 24 3d 7a c2 b0 3f |2..wn....3$=z..?|
-00000020 ca aa 97 15 03 03 00 1a 00 00 00 00 00 00 00 02 |................|
-00000030 b2 71 6e 42 6a 0d cf c9 ac 14 a4 b5 9c c9 71 60 |.qnBj.........q`|
-00000040 d7 c2 |..|
+00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 1d 4f 3c |..............O<|
+00000010 c5 d1 39 01 46 ab 7d d1 75 59 e7 f5 cd fa 02 0b |..9.F.}.uY......|
+00000020 dd 02 17 15 03 03 00 1a 00 00 00 00 00 00 00 02 |................|
+00000030 e9 a5 d5 0c 05 2a 82 fe a5 6c 03 6e d0 c4 7d cb |.....*...l.n..}.|
+00000040 32 f3 |2.|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 81 01 00 00 7d 03 03 00 00 00 00 00 |........}.......|
+00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 22 c0 2f |............."./|
00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 36 |...../.5.......6|
-00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
-00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
-00000070 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
-00000080 01 00 00 12 00 00 |......|
+00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
+00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
+00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
+00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
+00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 59 02 00 00 55 03 03 11 50 81 a7 ef |....Y...U...P...|
-00000010 3f bd a5 a9 41 11 e6 86 b2 a3 d8 bf 29 c3 d4 f4 |?...A.......)...|
-00000020 b6 20 2d cb 94 1b 0e dd 99 d1 0b 20 78 92 23 31 |. -........ x.#1|
-00000030 e3 fc 99 67 1f fd f3 2a fc 9c 4c 74 6e 32 e4 f8 |...g...*..Ltn2..|
-00000040 ed 6d 2e 6d ad a9 a9 bf 63 27 7e 44 c0 2c 00 00 |.m.m....c'~D.,..|
+00000000 16 03 03 00 59 02 00 00 55 03 03 ed 6d 5a 1c 89 |....Y...U...mZ..|
+00000010 a4 f3 35 0b e4 74 7e e2 05 a5 36 4d 4a 55 b3 7c |..5..t~...6MJU.||
+00000020 a1 a6 42 a3 fc 35 8c e0 97 5b 4b 20 a1 4a 06 28 |..B..5...[K .J.(|
+00000030 4d 40 0b fc 47 d5 4d 9b d5 43 b0 0d 0d c6 ae 30 |M@..G.M..C.....0|
+00000040 79 59 00 d4 90 96 98 92 d2 3a 57 07 c0 2c 00 00 |yY.......:W..,..|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
00000060 03 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..|
00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....|
00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....|
00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.|
00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....|
-00000270 2a 16 03 03 00 d7 0c 00 00 d3 03 00 17 41 04 fc |*............A..|
-00000280 e6 25 27 3c 76 10 a8 9e d3 a4 a8 68 31 06 85 fc |.%'<v......h1...|
-00000290 35 2a 76 b3 ad 08 c5 70 ed 3d 61 e0 29 cc 47 52 |5*v....p.=a.).GR|
-000002a0 68 21 ab 48 19 f9 28 ba 54 8c 56 8e b0 7d 55 7f |h!.H..(.T.V..}U.|
-000002b0 75 f5 42 38 61 ff e2 06 98 1a ae fc bc a0 3a 04 |u.B8a.........:.|
-000002c0 03 00 8a 30 81 87 02 42 01 0c b2 7f c9 d3 1b 83 |...0...B........|
-000002d0 1e 24 a3 d7 1c 81 f0 02 ae ed 42 6f e9 d9 91 4d |.$........Bo...M|
-000002e0 16 5f aa 8e 5a de 3b 00 0e e6 2d fb 05 30 f3 cf |._..Z.;...-..0..|
-000002f0 31 a2 ec 99 87 ea 42 03 0a 57 82 e5 12 27 98 8a |1.....B..W...'..|
-00000300 c6 56 4b 9a 0b d7 37 5f 46 50 02 41 57 61 13 3c |.VK...7_FP.AWa.<|
-00000310 48 d0 b3 b0 d5 21 72 49 80 7b d7 ef 8f 0d a0 c5 |H....!rI.{......|
-00000320 88 a1 5d ca 61 6d fb 8b 51 15 5d e5 a2 61 c4 78 |..].am..Q.]..a.x|
-00000330 8f d9 e3 78 df 7d a0 8f 0c c0 cc 18 36 41 e6 bb |...x.}......6A..|
-00000340 6d e3 9d 04 c2 c4 d0 66 35 45 9a 08 b2 16 03 03 |m......f5E......|
+00000270 2a 16 03 03 00 d7 0c 00 00 d3 03 00 17 41 04 89 |*............A..|
+00000280 e6 6d 6a 56 3e e5 4e 72 df 2b 41 11 de a0 c0 3e |.mjV>.Nr.+A....>|
+00000290 22 04 9a b5 a8 d6 22 30 2a e5 bd 83 1c 7a 8e 6c |"....."0*....z.l|
+000002a0 93 ab 8f d7 64 9e fe 89 c0 da 9a 45 7d 76 91 69 |....d......E}v.i|
+000002b0 0a 11 c5 59 26 49 ec 69 99 b3 91 a5 4b 2b 89 04 |...Y&I.i....K+..|
+000002c0 03 00 8a 30 81 87 02 42 01 17 1d ff 9a 99 76 20 |...0...B......v |
+000002d0 13 8a e1 5a a8 04 8a 1e 84 57 fd b0 95 c1 6c af |...Z.....W....l.|
+000002e0 b2 66 13 b5 75 36 ce 86 69 67 3d dc 82 2f 06 57 |.f..u6..ig=../.W|
+000002f0 19 14 56 54 0e 8e 04 74 0b 73 49 61 92 8e d1 9a |..VT...t.sIa....|
+00000300 b5 60 7f 65 a8 f8 99 eb ac 56 02 41 57 a3 78 57 |.`.e.....V.AW.xW|
+00000310 8a dd fa 9c 3d 24 a0 f2 0a 74 1a 8a 8f 6c 82 55 |....=$...t...l.U|
+00000320 4c cd d8 5d 79 99 87 93 41 e7 78 f4 28 0d ef 63 |L..]y...A.x.(..c|
+00000330 fb da 8e 93 86 31 6e 3e ca 6f 6b 1b fd 7a a3 86 |.....1n>.ok..z..|
+00000340 6e bb 17 35 90 d9 a4 df 12 d0 54 5e 25 16 03 03 |n..5......T^%...|
00000350 00 04 0e 00 00 00 |......|
>>> Flow 3 (client to server)
00000000 16 03 03 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..|
00000020 a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e |.$ >.V...(^.+-O.|
00000030 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I|
00000040 a6 b5 68 1a 41 03 56 6b dc 5a 89 14 03 03 00 01 |..h.A.Vk.Z......|
-00000050 01 16 03 03 00 28 00 00 00 00 00 00 00 00 a3 3f |.....(.........?|
-00000060 be 65 91 cd fe 37 43 e0 ea 6f 15 9d c2 aa 6a 02 |.e...7C..o....j.|
-00000070 20 b8 bc b5 c8 9a 1c d4 c4 e5 9b 2e 39 e7 | ...........9.|
+00000050 01 16 03 03 00 28 00 00 00 00 00 00 00 00 9d e7 |.....(..........|
+00000060 31 2a 0a 46 84 fd d9 18 c2 b0 b1 31 eb 63 4d 2d |1*.F.......1.cM-|
+00000070 ee 17 59 e6 b4 0f c6 d8 3d 8c e9 57 83 a8 |..Y.....=..W..|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 28 7c b7 1f 13 9e |..........(|....|
-00000010 21 d2 eb db 32 fc 36 d0 53 e1 11 04 ce d0 61 33 |!...2.6.S.....a3|
-00000020 1e 30 3d 91 c3 6a 0d 98 55 f5 e0 5c ca 77 fa 72 |.0=..j..U..\.w.r|
-00000030 63 6a be |cj.|
+00000000 14 03 03 00 01 01 16 03 03 00 28 e0 85 25 02 b4 |..........(..%..|
+00000010 86 32 57 70 3c 7e 6b e5 75 e0 3a 43 c8 c2 fe f8 |.2Wp<~k.u.:C....|
+00000020 2e 04 fe 73 e4 7b 2c 9a e0 65 2e d6 53 ae f1 19 |...s.{,..e..S...|
+00000030 dd 6f 1a |.o.|
>>> Flow 5 (client to server)
-00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 d9 db db |................|
-00000010 4b 3a ae 5c a4 dc 96 33 ed b5 a0 70 64 1f 96 2f |K:.\...3...pd../|
-00000020 b6 cd 1e 15 03 03 00 1a 00 00 00 00 00 00 00 02 |................|
-00000030 18 a0 d1 98 a6 71 c9 56 36 bd 1a 46 4b 5b 45 29 |.....q.V6..FK[E)|
-00000040 1f dd |..|
+00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 29 b2 e6 |.............)..|
+00000010 c3 2e 72 ba cc ac d9 3b c7 0c 1d 53 b2 30 39 71 |..r....;...S.09q|
+00000020 6e dd 79 15 03 03 00 1a 00 00 00 00 00 00 00 02 |n.y.............|
+00000030 88 c9 92 fe 6c 1f 6c fd bd 7b fb 0a 8a b5 cc c9 |....l.l..{......|
+00000040 94 90 |..|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 81 01 00 00 7d 03 03 00 00 00 00 00 |........}.......|
+00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 22 c0 2f |............."./|
00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 36 |...../.5.......6|
-00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
-00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
-00000070 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
-00000080 01 00 00 12 00 00 |......|
+00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
+00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
+00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
+00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
+00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 59 02 00 00 55 03 03 e6 ae 89 0d 22 |....Y...U......"|
-00000010 e5 e0 cd 57 a3 ca 71 4f 17 2f 64 77 f8 30 89 ef |...W..qO./dw.0..|
-00000020 e8 19 70 ac dd 2c c5 9f 84 7d 1d 20 1c 59 3c fe |..p..,...}. .Y<.|
-00000030 a9 ec 10 dd 38 3b 43 fe 6b 09 e5 e4 83 d9 7a 78 |....8;C.k.....zx|
-00000040 86 08 33 da 9b e1 09 d8 c9 07 34 19 c0 13 00 00 |..3.......4.....|
+00000000 16 03 03 00 59 02 00 00 55 03 03 2a 6a a8 b3 97 |....Y...U..*j...|
+00000010 d5 c8 5e b4 22 7e d0 a5 c7 46 af 89 60 44 77 5e |..^."~...F..`Dw^|
+00000020 1a f8 3a 30 08 6d 5f 4c 61 36 c5 20 57 79 91 3e |..:0.m_La6. Wy.>|
+00000030 1f 40 d1 f1 33 d7 a9 fb 93 eb 16 0d e1 39 e3 a3 |.@..3........9..|
+00000040 80 e3 4f 58 a6 f8 a4 be 19 dd ef ee c0 13 00 00 |..OX............|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
-00000060 03 02 be 0b 00 02 ba 00 02 b7 00 02 b4 30 82 02 |.............0..|
-00000070 b0 30 82 02 19 a0 03 02 01 02 02 09 00 85 b0 bb |.0..............|
-00000080 a4 8a 7f b8 ca 30 0d 06 09 2a 86 48 86 f7 0d 01 |.....0...*.H....|
-00000090 01 05 05 00 30 45 31 0b 30 09 06 03 55 04 06 13 |....0E1.0...U...|
-000000a0 02 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f |.AU1.0...U....So|
-000000b0 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 |me-State1!0...U.|
-000000c0 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 |...Internet Widg|
-000000d0 69 74 73 20 50 74 79 20 4c 74 64 30 1e 17 0d 31 |its Pty Ltd0...1|
-000000e0 30 30 34 32 34 30 39 30 39 33 38 5a 17 0d 31 31 |00424090938Z..11|
-000000f0 30 34 32 34 30 39 30 39 33 38 5a 30 45 31 0b 30 |0424090938Z0E1.0|
-00000100 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 |...U....AU1.0...|
-00000110 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 |U....Some-State1|
-00000120 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e |!0...U....Intern|
-00000130 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c |et Widgits Pty L|
-00000140 74 64 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 |td0..0...*.H....|
-00000150 01 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 bb |........0.......|
-00000160 79 d6 f5 17 b5 e5 bf 46 10 d0 dc 69 be e6 2b 07 |y......F...i..+.|
-00000170 43 5a d0 03 2d 8a 7a 43 85 b7 14 52 e7 a5 65 4c |CZ..-.zC...R..eL|
-00000180 2c 78 b8 23 8c b5 b4 82 e5 de 1f 95 3b 7e 62 a5 |,x.#........;~b.|
-00000190 2c a5 33 d6 fe 12 5c 7a 56 fc f5 06 bf fa 58 7b |,.3...\zV.....X{|
-000001a0 26 3f b5 cd 04 d3 d0 c9 21 96 4a c7 f4 54 9f 5a |&?......!.J..T.Z|
-000001b0 bf ef 42 71 00 fe 18 99 07 7f 7e 88 7d 7d f1 04 |..Bq......~.}}..|
-000001c0 39 c4 a2 2e db 51 c9 7c e3 c0 4c 3b 32 66 01 cf |9....Q.|..L;2f..|
-000001d0 af b1 1d b8 71 9a 1d db db 89 6b ae da 2d 79 02 |....q.....k..-y.|
-000001e0 03 01 00 01 a3 81 a7 30 81 a4 30 1d 06 03 55 1d |.......0..0...U.|
-000001f0 0e 04 16 04 14 b1 ad e2 85 5a cf cb 28 db 69 ce |.........Z..(.i.|
-00000200 23 69 de d3 26 8e 18 88 39 30 75 06 03 55 1d 23 |#i..&...90u..U.#|
-00000210 04 6e 30 6c 80 14 b1 ad e2 85 5a cf cb 28 db 69 |.n0l......Z..(.i|
-00000220 ce 23 69 de d3 26 8e 18 88 39 a1 49 a4 47 30 45 |.#i..&...9.I.G0E|
-00000230 31 0b 30 09 06 03 55 04 06 13 02 41 55 31 13 30 |1.0...U....AU1.0|
-00000240 11 06 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 |...U....Some-Sta|
-00000250 74 65 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 |te1!0...U....Int|
-00000260 65 72 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 |ernet Widgits Pt|
-00000270 79 20 4c 74 64 82 09 00 85 b0 bb a4 8a 7f b8 ca |y Ltd...........|
-00000280 30 0c 06 03 55 1d 13 04 05 30 03 01 01 ff 30 0d |0...U....0....0.|
-00000290 06 09 2a 86 48 86 f7 0d 01 01 05 05 00 03 81 81 |..*.H...........|
-000002a0 00 08 6c 45 24 c7 6b b1 59 ab 0c 52 cc f2 b0 14 |..lE$.k.Y..R....|
-000002b0 d7 87 9d 7a 64 75 b5 5a 95 66 e4 c5 2b 8e ae 12 |...zdu.Z.f..+...|
-000002c0 66 1f eb 4f 38 b3 6e 60 d3 92 fd f7 41 08 b5 25 |f..O8.n`....A..%|
-000002d0 13 b1 18 7a 24 fb 30 1d ba ed 98 b9 17 ec e7 d7 |...z$.0.........|
-000002e0 31 59 db 95 d3 1d 78 ea 50 56 5c d5 82 5a 2d 5a |1Y....x.PV\..Z-Z|
-000002f0 5f 33 c4 b6 d8 c9 75 90 96 8c 0f 52 98 b5 cd 98 |_3....u....R....|
-00000300 1f 89 20 5f f2 a0 1c a3 1b 96 94 dd a9 fd 57 e9 |.. _..........W.|
-00000310 70 e8 26 6d 71 99 9b 26 6e 38 50 29 6c 90 a7 bd |p.&mq..&n8P)l...|
-00000320 d9 16 03 03 00 cd 0c 00 00 c9 03 00 17 41 04 77 |.............A.w|
-00000330 87 a7 ad f6 f8 34 82 05 ef bb 14 6d c7 8b 7b 2a |.....4.....m..{*|
-00000340 4d ca 41 65 58 3c 83 fa 4d ce 0c 74 46 85 fe 38 |M.AeX<..M..tF..8|
-00000350 95 80 ee 7c c2 bf f2 be a3 c6 bf f3 aa 07 23 40 |...|..........#@|
-00000360 7e cc 74 4a 4e 2e 69 af 6b e0 42 8a fc 41 be 04 |~.tJN.i.k.B..A..|
-00000370 01 00 80 99 ed a8 3a ef 93 1b 4c 17 80 9e cc eb |......:...L.....|
-00000380 da 39 fb c8 9a 73 e1 96 20 3e 41 fa 8b 1a b1 68 |.9...s.. >A....h|
-00000390 cd 47 bc 4b 7b 0c 14 da 87 d3 36 09 5e 37 33 88 |.G.K{.....6.^73.|
-000003a0 7f 88 07 87 46 ec e5 72 a8 59 92 07 fa 4d 02 dc |....F..r.Y...M..|
-000003b0 bf 3a f5 e4 77 0b a6 85 ce 43 ee 1b 90 30 7f ec |.:..w....C...0..|
-000003c0 88 79 f8 88 59 af 6b 7f 2d 88 de 92 cd c8 36 cf |.y..Y.k.-.....6.|
-000003d0 ba b9 08 6a c4 3d d7 9a 48 50 e1 67 d0 62 a5 b3 |...j.=..HP.g.b..|
-000003e0 b0 5f 2e 16 ee 4d 7d a2 cf d9 93 19 89 b7 64 0f |._...M}.......d.|
-000003f0 0f 8e 3d 16 03 03 00 04 0e 00 00 00 |..=.........|
+00000060 03 02 71 0b 00 02 6d 00 02 6a 00 02 67 30 82 02 |..q...m..j..g0..|
+00000070 63 30 82 01 cc a0 03 02 01 02 02 09 00 a2 73 00 |c0............s.|
+00000080 0c 81 00 cb f3 30 0d 06 09 2a 86 48 86 f7 0d 01 |.....0...*.H....|
+00000090 01 0b 05 00 30 2b 31 17 30 15 06 03 55 04 0a 13 |....0+1.0...U...|
+000000a0 0e 47 6f 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 |.Google TESTING1|
+000000b0 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f 6f |.0...U....Go Roo|
+000000c0 74 30 1e 17 0d 31 35 30 31 30 31 30 30 30 30 30 |t0...15010100000|
+000000d0 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 30 |0Z..250101000000|
+000000e0 5a 30 26 31 17 30 15 06 03 55 04 0a 13 0e 47 6f |Z0&1.0...U....Go|
+000000f0 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 0b 30 09 |ogle TESTING1.0.|
+00000100 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
+00000110 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
+00000120 81 89 02 81 81 00 af 87 88 f6 20 1b 95 65 6c 14 |.......... ..el.|
+00000130 ab 44 05 af 3b 45 14 e3 b7 6d fd 00 63 4d 95 7f |.D..;E...m..cM..|
+00000140 fe 6a 62 35 86 c0 4a f9 18 7c f6 aa 25 5e 7a 64 |.jb5..J..|..%^zd|
+00000150 31 66 00 ba f4 8e 92 af c7 6b d8 76 d4 f3 5f 41 |1f.......k.v.._A|
+00000160 cb 6e 56 15 97 1b 97 c1 3c 12 39 21 66 3d 2b 16 |.nV.....<.9!f=+.|
+00000170 d1 bc db 1c c0 a7 da b7 ca ad ba da cb d5 21 50 |..............!P|
+00000180 ec de 8d ab d1 6b 81 4b 89 02 f3 c4 be c1 6c 89 |.....k.K......l.|
+00000190 b1 44 84 bd 21 d1 04 7d 9d 16 4d f9 82 15 f6 ef |.D..!..}..M.....|
+000001a0 fa d6 09 47 f2 fb 02 03 01 00 01 a3 81 93 30 81 |...G..........0.|
+000001b0 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
+000001c0 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
+000001d0 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
+000001e0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
+000001f0 06 03 55 1d 0e 04 12 04 10 12 50 8d 89 6f 1b d1 |..U.......P..o..|
+00000200 dc 54 4d 6e cb 69 5e 06 f4 30 1b 06 03 55 1d 23 |.TMn.i^..0...U.#|
+00000210 04 14 30 12 80 10 bf 3d b6 a9 66 f2 b8 40 cf ea |..0....=..f..@..|
+00000220 b4 03 78 48 1a 41 30 19 06 03 55 1d 11 04 12 30 |..xH.A0...U....0|
+00000230 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
+00000240 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
+00000250 03 81 81 00 92 7c af 91 55 12 18 96 59 31 a6 48 |.....|..U...Y1.H|
+00000260 40 d5 2d d5 ee bb 02 a0 f5 c2 1e 7c 9b b3 30 7d |@.-........|..0}|
+00000270 3c dc 76 da 4f 3d c0 fa ae 2d 33 24 6b 03 7b 1b |<.v.O=...-3$k.{.|
+00000280 67 59 11 21 b5 11 bc 77 b9 d9 e0 6e a8 2d 2e 35 |gY.!...w...n.-.5|
+00000290 fa 64 5f 22 3e 63 10 6b be ff 14 86 6d 0d f0 15 |.d_">c.k....m...|
+000002a0 31 a8 14 38 1e 3b 84 87 2c cb 98 ed 51 76 b9 b1 |1..8.;..,...Qv..|
+000002b0 4f dd db 9b 84 04 86 40 fa 51 dd ba b4 8d eb e3 |O......@.Q......|
+000002c0 46 de 46 b9 4f 86 c7 f9 a4 c2 41 34 ac cc f6 ea |F.F.O.....A4....|
+000002d0 b0 ab 39 18 16 03 03 00 cd 0c 00 00 c9 03 00 17 |..9.............|
+000002e0 41 04 8e c8 e8 42 7c 8a 01 c2 ff 01 cb 0b e1 20 |A....B|........ |
+000002f0 50 42 d4 3a 1b 34 ff 74 59 81 2f a2 0e 29 b2 f9 |PB.:.4.tY./..)..|
+00000300 47 cf 0d 08 97 cf aa 9f fe f0 7f e8 f4 fd 3a fa |G.............:.|
+00000310 a6 b6 47 32 d3 25 78 87 bf 77 cc 12 37 02 6a ad |..G2.%x..w..7.j.|
+00000320 cf 2c 04 01 00 80 13 a1 95 17 7b 21 86 7f f2 02 |.,........{!....|
+00000330 9f ed 88 2d 1f 2c 38 96 bc fa 5a 39 85 4b 9f ff |...-.,8...Z9.K..|
+00000340 5c 7a 02 1e 5f c9 4a 69 51 d3 83 34 9f dc 8c 39 |\z.._.JiQ..4...9|
+00000350 fe 81 76 fc c3 59 ff e2 a8 81 ca 6f f6 52 c9 44 |..v..Y.....o.R.D|
+00000360 a0 3f 5e 5e 92 20 db d9 2e 0b e3 ab 75 e7 79 f6 |.?^^. ......u.y.|
+00000370 b2 73 17 e1 94 1e 12 62 e9 b0 0f 04 e7 5d 83 ac |.s.....b.....]..|
+00000380 71 ca a5 62 40 dd 69 b1 3f cf bb 3d c7 3e 51 6c |q..b@.i.?..=.>Ql|
+00000390 11 f2 cf 39 f1 b5 72 bd 52 d4 3d 3c c0 90 34 c8 |...9..r.R.=<..4.|
+000003a0 4b 22 55 39 1c 2b 16 03 03 00 04 0e 00 00 00 |K"U9.+.........|
>>> Flow 3 (client to server)
00000000 16 03 03 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..|
00000010 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.|
00000030 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I|
00000040 a6 b5 68 1a 41 03 56 6b dc 5a 89 14 03 03 00 01 |..h.A.Vk.Z......|
00000050 01 16 03 03 00 40 00 00 00 00 00 00 00 00 00 00 |.....@..........|
-00000060 00 00 00 00 00 00 f2 20 58 ec f1 88 a6 26 79 9d |....... X....&y.|
-00000070 2e 9b 02 b5 5e da e2 c1 c5 8d c8 93 6f 6d 07 4e |....^.......om.N|
-00000080 fa dd ee cb b1 ae c7 3b 09 b2 cc 64 7a cd 98 91 |.......;...dz...|
-00000090 cb f8 3c 34 3b ed |..<4;.|
+00000060 00 00 00 00 00 00 a2 6e de ea 78 0c 4d 20 ad 1f |.......n..x.M ..|
+00000070 1a f5 6b 15 09 f1 50 bb cd 40 0e c7 d9 ed 7f e1 |..k...P..@......|
+00000080 4b bc d3 26 5d 89 b7 26 c5 6c 0e 59 6f 84 51 5d |K..&]..&.l.Yo.Q]|
+00000090 2f 75 d8 0f 2e e8 |/u....|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 40 4c a1 8d bd 49 |..........@L...I|
-00000010 33 d3 72 fb 2f 23 7e 11 29 fc d2 ff 9b 67 30 c8 |3.r./#~.)....g0.|
-00000020 be c1 bc 51 6e 92 a5 f4 9d e3 b3 f9 d2 d4 c4 a5 |...Qn...........|
-00000030 83 23 90 b3 17 00 35 18 c5 ef 8b 18 a3 cf ed 9d |.#....5.........|
-00000040 a9 52 c9 11 0a c9 55 c2 76 df 78 |.R....U.v.x|
+00000000 14 03 03 00 01 01 16 03 03 00 40 dd d8 e7 63 89 |..........@...c.|
+00000010 8e cc 3e e0 df 6d 5a 42 b3 49 1b 66 e8 79 e9 f0 |..>..mZB.I.f.y..|
+00000020 8a c3 0e 5e d7 01 ac 04 81 6a e1 60 14 60 b9 a6 |...^.....j.`.`..|
+00000030 4c a5 46 43 74 df 30 1e f8 74 77 4c b5 42 e5 25 |L.FCt.0..twL.B.%|
+00000040 81 9d b1 04 bc 02 46 bd b1 55 d0 |......F..U.|
>>> Flow 5 (client to server)
00000000 17 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........|
-00000010 00 00 00 00 00 60 40 d0 bf 8f ef 05 2b 89 d7 bb |.....`@.....+...|
-00000020 27 d0 1f b2 cf c3 ff 8e be 69 16 a9 b3 03 e8 3c |'........i.....<|
-00000030 30 1d 58 39 4a 15 03 03 00 30 00 00 00 00 00 00 |0.X9J....0......|
-00000040 00 00 00 00 00 00 00 00 00 00 de 61 51 a1 3c fc |...........aQ.<.|
-00000050 1c 7b e6 f2 7d e0 aa 80 2d 9c e9 22 09 5c dd 8a |.{..}...-..".\..|
-00000060 55 cc c4 77 34 97 05 88 98 d3 |U..w4.....|
+00000010 00 00 00 00 00 35 49 6d a7 3f a1 39 5d 37 8d 2e |.....5Im.?.9]7..|
+00000020 c5 1e 90 3b f9 60 58 d3 47 e3 db 73 8b aa 6c 9e |...;.`X.G..s..l.|
+00000030 b5 82 55 09 62 15 03 03 00 30 00 00 00 00 00 00 |..U.b....0......|
+00000040 00 00 00 00 00 00 00 00 00 00 71 b3 7b c7 d4 27 |..........q.{..'|
+00000050 f9 77 7f d0 80 25 1b 43 d0 0e 92 38 8c f3 2f 50 |.w...%.C...8../P|
+00000060 eb 96 22 fb e6 09 45 ec 7f 16 |.."...E...|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 81 01 00 00 7d 03 03 00 00 00 00 00 |........}.......|
+00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 22 c0 2f |............."./|
00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 36 |...../.5.......6|
-00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
-00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
-00000070 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
-00000080 01 00 00 12 00 00 |......|
+00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
+00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
+00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
+00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
+00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 51 02 00 00 4d 03 03 e8 ae 4c 97 41 |....Q...M....L.A|
-00000010 78 0f 08 84 d4 4a 80 6d a2 e1 d0 67 40 8f 01 8b |x....J.m...g@...|
-00000020 20 54 cb 28 16 52 04 fd 3c c2 84 20 30 96 f0 51 | T.(.R..<.. 0..Q|
-00000030 72 86 6a d8 47 b9 47 e3 a4 ad 97 77 a9 77 1a f9 |r.j.G.G....w.w..|
-00000040 ba 63 33 32 4f 43 09 1c e1 bd 1b 3b 00 05 00 00 |.c32OC.....;....|
-00000050 05 ff 01 00 01 00 16 03 03 02 be 0b 00 02 ba 00 |................|
-00000060 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......|
-00000070 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..|
-00000080 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 45 31 0b |.*.H........0E1.|
-00000090 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..|
-000000a0 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State|
-000000b0 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter|
-000000c0 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty |
-000000d0 4c 74 64 30 1e 17 0d 31 30 30 34 32 34 30 39 30 |Ltd0...100424090|
-000000e0 39 33 38 5a 17 0d 31 31 30 34 32 34 30 39 30 39 |938Z..1104240909|
-000000f0 33 38 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 |38Z0E1.0...U....|
-00000100 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som|
-00000110 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..|
-00000120 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi|
-00000130 74 73 20 50 74 79 20 4c 74 64 30 81 9f 30 0d 06 |ts Pty Ltd0..0..|
-00000140 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 |.*.H............|
-00000150 30 81 89 02 81 81 00 bb 79 d6 f5 17 b5 e5 bf 46 |0.......y......F|
-00000160 10 d0 dc 69 be e6 2b 07 43 5a d0 03 2d 8a 7a 43 |...i..+.CZ..-.zC|
-00000170 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 8c b5 b4 82 |...R..eL,x.#....|
-00000180 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 fe 12 5c 7a |....;~b.,.3...\z|
-00000190 56 fc f5 06 bf fa 58 7b 26 3f b5 cd 04 d3 d0 c9 |V.....X{&?......|
-000001a0 21 96 4a c7 f4 54 9f 5a bf ef 42 71 00 fe 18 99 |!.J..T.Z..Bq....|
-000001b0 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e db 51 c9 7c |..~.}}..9....Q.||
-000001c0 e3 c0 4c 3b 32 66 01 cf af b1 1d b8 71 9a 1d db |..L;2f......q...|
-000001d0 db 89 6b ae da 2d 79 02 03 01 00 01 a3 81 a7 30 |..k..-y........0|
-000001e0 81 a4 30 1d 06 03 55 1d 0e 04 16 04 14 b1 ad e2 |..0...U.........|
-000001f0 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 88 |.Z..(.i.#i..&...|
-00000200 39 30 75 06 03 55 1d 23 04 6e 30 6c 80 14 b1 ad |90u..U.#.n0l....|
-00000210 e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 |..Z..(.i.#i..&..|
-00000220 88 39 a1 49 a4 47 30 45 31 0b 30 09 06 03 55 04 |.9.I.G0E1.0...U.|
-00000230 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 0a |...AU1.0...U....|
-00000240 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 |Some-State1!0...|
-00000250 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 |U....Internet Wi|
-00000260 64 67 69 74 73 20 50 74 79 20 4c 74 64 82 09 00 |dgits Pty Ltd...|
-00000270 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 55 1d 13 04 |........0...U...|
-00000280 05 30 03 01 01 ff 30 0d 06 09 2a 86 48 86 f7 0d |.0....0...*.H...|
-00000290 01 01 05 05 00 03 81 81 00 08 6c 45 24 c7 6b b1 |..........lE$.k.|
-000002a0 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a 64 75 b5 5a |Y..R.......zdu.Z|
-000002b0 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f 38 b3 6e 60 |.f..+...f..O8.n`|
-000002c0 d3 92 fd f7 41 08 b5 25 13 b1 18 7a 24 fb 30 1d |....A..%...z$.0.|
-000002d0 ba ed 98 b9 17 ec e7 d7 31 59 db 95 d3 1d 78 ea |........1Y....x.|
-000002e0 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 90 |PV\..Z-Z_3....u.|
-000002f0 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c a3 |...R...... _....|
-00000300 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b 26 |......W.p.&mq..&|
-00000310 6e 38 50 29 6c 90 a7 bd d9 16 03 03 00 04 0e 00 |n8P)l...........|
-00000320 00 00 |..|
+00000000 16 03 03 00 51 02 00 00 4d 03 03 79 8f 56 ac 75 |....Q...M..y.V.u|
+00000010 4f a9 fc 2c b9 53 82 a6 b4 c8 0d 4e 50 9a 9e aa |O..,.S.....NP...|
+00000020 8d ed 21 21 91 5d a2 cc 99 1b 68 20 0c e7 35 50 |..!!.]....h ..5P|
+00000030 67 02 70 2a 45 0d 6c 4c 46 df 75 dc 5f 6e 2f 79 |g.p*E.lLF.u._n/y|
+00000040 03 26 da 45 53 25 50 23 c0 85 3b 8c 00 05 00 00 |.&.ES%P#..;.....|
+00000050 05 ff 01 00 01 00 16 03 03 02 71 0b 00 02 6d 00 |..........q...m.|
+00000060 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
+00000070 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
+00000080 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
+00000090 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
+000000a0 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
+000000b0 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
+000000c0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
+000000d0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
+000000e0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
+000000f0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
+00000100 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
+00000110 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
+00000120 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
+00000130 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
+00000140 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
+00000150 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
+00000160 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
+00000170 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
+00000180 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
+00000190 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
+000001a0 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
+000001b0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
+000001c0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
+000001d0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
+000001e0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
+000001f0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
+00000200 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
+00000210 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
+00000220 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
+00000230 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
+00000240 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
+00000250 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
+00000260 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
+00000270 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
+00000280 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
+00000290 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
+000002a0 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
+000002b0 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
+000002c0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 03 00 |..A4......9.....|
+000002d0 04 0e 00 00 00 |.....|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 86 10 00 00 82 00 80 6d 51 f3 7f f9 |...........mQ...|
-00000010 3e fb 75 82 41 36 83 e8 6a ee 2a 2e 25 90 67 4c |>.u.A6..j.*.%.gL|
-00000020 8e 62 2f 30 81 17 e0 85 09 0c 2b b7 23 d7 b0 e2 |.b/0......+.#...|
-00000030 1d f7 3b d7 f5 a1 27 b6 ee 24 b6 1b cc 5b ea 66 |..;...'..$...[.f|
-00000040 0d 6a f4 e5 85 f9 da 43 b4 0e 86 85 e1 f5 aa be |.j.....C........|
-00000050 c8 ce 39 4c 9c 86 00 08 c2 4b e2 c6 ec 2f f7 ce |..9L.....K.../..|
-00000060 e6 bd 77 82 6f 23 b6 e0 bd a2 92 b7 3a ac e8 56 |..w.o#......:..V|
-00000070 f1 af 54 5e 46 87 e9 3b 33 e7 b8 28 b7 d6 c8 90 |..T^F..;3..(....|
-00000080 35 d4 1c 43 d1 30 6f 55 4e 0a 70 14 03 03 00 01 |5..C.0oUN.p.....|
-00000090 01 16 03 03 00 24 54 8c 7f 71 03 7c 98 e5 97 65 |.....$T..q.|...e|
-000000a0 51 13 b2 9d 4a b8 c9 c1 e6 11 1b 50 c8 1b c0 46 |Q...J......P...F|
-000000b0 a7 cb 13 97 92 a0 51 d4 a9 e5 |......Q...|
+00000000 16 03 03 00 86 10 00 00 82 00 80 73 bd 73 65 92 |...........s.se.|
+00000010 86 23 41 14 79 7f d5 c1 10 ce 94 4d ad 9c c3 a9 |.#A.y......M....|
+00000020 87 b5 32 52 f8 6b 11 93 2d 9b 98 0b 8b 1d c0 f6 |..2R.k..-.......|
+00000030 53 17 6d c7 9c 2e ae c9 6f cc 99 23 38 37 1a 10 |S.m.....o..#87..|
+00000040 fe 05 0b b5 55 0a 14 e9 60 7d 70 26 98 e2 54 d9 |....U...`}p&..T.|
+00000050 65 cf 2e f4 53 5f 1d aa 3a f6 33 7b eb 4c 0e b3 |e...S_..:.3{.L..|
+00000060 ff 5a db 36 2a 47 f3 df f9 fc f5 31 78 83 aa 6b |.Z.6*G.....1x..k|
+00000070 52 b7 ba 1a 96 bc fa c1 a1 a9 bb 2b f5 38 89 00 |R..........+.8..|
+00000080 4d e5 78 13 4e a4 38 46 42 dc 16 14 03 03 00 01 |M.x.N.8FB.......|
+00000090 01 16 03 03 00 24 72 bd b1 13 05 73 26 c0 0b ec |.....$r....s&...|
+000000a0 e6 39 08 6a 2d 87 00 51 58 9d e3 8d da be 60 98 |.9.j-..QX.....`.|
+000000b0 0a ee 0c 96 13 f4 e5 30 90 85 |.......0..|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 24 37 ca ae 55 79 |..........$7..Uy|
-00000010 e7 0a 70 55 1e d1 76 61 57 46 d2 c0 d0 ed 3d 70 |..pU..vaWF....=p|
-00000020 1f 02 f2 06 5b 3e 50 ec 13 4b 67 e2 7c bd 45 |....[>P..Kg.|.E|
+00000000 14 03 03 00 01 01 16 03 03 00 24 d4 ad ab a0 01 |..........$.....|
+00000010 1b 87 9c aa c4 27 08 b5 8c 4a 7f fc 03 df a6 d6 |.....'...J......|
+00000020 f8 6c d1 61 7c d3 1f 6d 18 c3 8d 88 5c 7b cf |.l.a|..m....\{.|
>>> Flow 5 (client to server)
-00000000 17 03 03 00 1a c4 13 68 ec e0 38 a1 07 35 da d7 |.......h..8..5..|
-00000010 c4 6b f9 5c ed a7 8a cb 96 7a 22 7c ca a5 30 15 |.k.\.....z"|..0.|
-00000020 03 03 00 16 f7 a7 8d 41 b0 c1 4b 61 60 b0 b2 ed |.......A..Ka`...|
-00000030 4a ab c3 54 d5 20 eb 67 b7 8f |J..T. .g..|
+00000000 17 03 03 00 1a 33 a8 7a 61 46 09 7b 64 e6 aa f8 |.....3.zaF.{d...|
+00000010 8a 43 d3 a9 0c e9 2e c0 89 7c 72 fb 75 50 50 15 |.C.......|r.uPP.|
+00000020 03 03 00 16 2b b9 b5 eb f8 bd 53 20 ea 67 bc 47 |....+.....S .g.G|
+00000030 83 cf c5 6e f9 4f 9e 12 f5 1a |...n.O....|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 81 01 00 00 7d 03 03 00 00 00 00 00 |........}.......|
+00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 22 c0 2f |............."./|
00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 36 |...../.5.......6|
-00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
-00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
-00000070 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
-00000080 01 00 00 12 00 00 |......|
+00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
+00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
+00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
+00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
+00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
>>> Flow 2 (server to client)
-00000000 16 03 03 01 c6 02 00 01 c2 03 03 1b f6 69 c1 c2 |.............i..|
-00000010 36 77 72 32 69 95 c9 e7 db 9b 5d bd 59 ba 08 02 |6wr2i.....].Y...|
-00000020 1e 76 11 c4 8e 49 08 22 8e 8a 5a 20 44 ec d9 13 |.v...I."..Z D...|
-00000030 23 ad 05 45 48 29 00 c6 11 3d 5a 5c a1 ee 34 2b |#..EH)...=Z\..4+|
-00000040 58 ef 34 5b 7e 42 08 84 23 66 56 ee c0 2f 00 01 |X.4[~B..#fV../..|
+00000000 16 03 03 01 c6 02 00 01 c2 03 03 5d d8 84 38 51 |...........]..8Q|
+00000010 c6 51 9e 6c d3 e0 b2 d7 81 2a 9b 1c 06 0b 11 c8 |.Q.l.....*......|
+00000020 54 90 f3 d1 66 83 7a 68 2f 65 8b 20 ac 8b 35 9a |T...f.zh/e. ..5.|
+00000030 31 25 04 c9 89 31 27 80 8f 10 74 8e 3c 4f 20 bc |1%...1'...t.<O .|
+00000040 3b 46 9d d0 91 f3 ca 7e 0e 59 b7 72 c0 2f 00 01 |;F.....~.Y.r./..|
00000050 7a ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 12 |z...............|
00000060 01 69 01 67 00 75 00 a4 b9 09 90 b4 18 58 14 87 |.i.g.u.......X..|
00000070 bb 13 a2 cc 67 70 0a 3c 35 98 04 f9 1b df b8 e3 |....gp.<5.......|
00000190 91 bc f1 b5 40 be 1e 2e e7 5c b4 74 27 ed 8f 9b |....@....\.t'...|
000001a0 02 e9 fa c2 4c ba a2 be 02 21 00 af 43 64 52 71 |....L....!..CdRq|
000001b0 15 29 58 40 91 c7 08 16 96 03 a8 73 a5 65 a0 6c |.)X@.......s.e.l|
-000001c0 b8 48 56 5a b6 29 83 64 6d 2a 9d 16 03 03 02 be |.HVZ.).dm*......|
-000001d0 0b 00 02 ba 00 02 b7 00 02 b4 30 82 02 b0 30 82 |..........0...0.|
-000001e0 02 19 a0 03 02 01 02 02 09 00 85 b0 bb a4 8a 7f |................|
-000001f0 b8 ca 30 0d 06 09 2a 86 48 86 f7 0d 01 01 05 05 |..0...*.H.......|
-00000200 00 30 45 31 0b 30 09 06 03 55 04 06 13 02 41 55 |.0E1.0...U....AU|
-00000210 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d 65 2d |1.0...U....Some-|
-00000220 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a 13 18 |State1!0...U....|
-00000230 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 74 73 |Internet Widgits|
-00000240 20 50 74 79 20 4c 74 64 30 1e 17 0d 31 30 30 34 | Pty Ltd0...1004|
-00000250 32 34 30 39 30 39 33 38 5a 17 0d 31 31 30 34 32 |24090938Z..11042|
-00000260 34 30 39 30 39 33 38 5a 30 45 31 0b 30 09 06 03 |4090938Z0E1.0...|
-00000270 55 04 06 13 02 41 55 31 13 30 11 06 03 55 04 08 |U....AU1.0...U..|
-00000280 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f |..Some-State1!0.|
-00000290 06 03 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 |..U....Internet |
-000002a0 57 69 64 67 69 74 73 20 50 74 79 20 4c 74 64 30 |Widgits Pty Ltd0|
-000002b0 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 |..0...*.H.......|
-000002c0 00 03 81 8d 00 30 81 89 02 81 81 00 bb 79 d6 f5 |.....0.......y..|
-000002d0 17 b5 e5 bf 46 10 d0 dc 69 be e6 2b 07 43 5a d0 |....F...i..+.CZ.|
-000002e0 03 2d 8a 7a 43 85 b7 14 52 e7 a5 65 4c 2c 78 b8 |.-.zC...R..eL,x.|
-000002f0 23 8c b5 b4 82 e5 de 1f 95 3b 7e 62 a5 2c a5 33 |#........;~b.,.3|
-00000300 d6 fe 12 5c 7a 56 fc f5 06 bf fa 58 7b 26 3f b5 |...\zV.....X{&?.|
-00000310 cd 04 d3 d0 c9 21 96 4a c7 f4 54 9f 5a bf ef 42 |.....!.J..T.Z..B|
-00000320 71 00 fe 18 99 07 7f 7e 88 7d 7d f1 04 39 c4 a2 |q......~.}}..9..|
-00000330 2e db 51 c9 7c e3 c0 4c 3b 32 66 01 cf af b1 1d |..Q.|..L;2f.....|
-00000340 b8 71 9a 1d db db 89 6b ae da 2d 79 02 03 01 00 |.q.....k..-y....|
-00000350 01 a3 81 a7 30 81 a4 30 1d 06 03 55 1d 0e 04 16 |....0..0...U....|
-00000360 04 14 b1 ad e2 85 5a cf cb 28 db 69 ce 23 69 de |......Z..(.i.#i.|
-00000370 d3 26 8e 18 88 39 30 75 06 03 55 1d 23 04 6e 30 |.&...90u..U.#.n0|
-00000380 6c 80 14 b1 ad e2 85 5a cf cb 28 db 69 ce 23 69 |l......Z..(.i.#i|
-00000390 de d3 26 8e 18 88 39 a1 49 a4 47 30 45 31 0b 30 |..&...9.I.G0E1.0|
-000003a0 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 |...U....AU1.0...|
-000003b0 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 |U....Some-State1|
-000003c0 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e |!0...U....Intern|
-000003d0 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c |et Widgits Pty L|
-000003e0 74 64 82 09 00 85 b0 bb a4 8a 7f b8 ca 30 0c 06 |td...........0..|
-000003f0 03 55 1d 13 04 05 30 03 01 01 ff 30 0d 06 09 2a |.U....0....0...*|
-00000400 86 48 86 f7 0d 01 01 05 05 00 03 81 81 00 08 6c |.H.............l|
-00000410 45 24 c7 6b b1 59 ab 0c 52 cc f2 b0 14 d7 87 9d |E$.k.Y..R.......|
-00000420 7a 64 75 b5 5a 95 66 e4 c5 2b 8e ae 12 66 1f eb |zdu.Z.f..+...f..|
-00000430 4f 38 b3 6e 60 d3 92 fd f7 41 08 b5 25 13 b1 18 |O8.n`....A..%...|
-00000440 7a 24 fb 30 1d ba ed 98 b9 17 ec e7 d7 31 59 db |z$.0.........1Y.|
-00000450 95 d3 1d 78 ea 50 56 5c d5 82 5a 2d 5a 5f 33 c4 |...x.PV\..Z-Z_3.|
-00000460 b6 d8 c9 75 90 96 8c 0f 52 98 b5 cd 98 1f 89 20 |...u....R...... |
-00000470 5f f2 a0 1c a3 1b 96 94 dd a9 fd 57 e9 70 e8 26 |_..........W.p.&|
-00000480 6d 71 99 9b 26 6e 38 50 29 6c 90 a7 bd d9 16 03 |mq..&n8P)l......|
-00000490 03 00 cd 0c 00 00 c9 03 00 17 41 04 d7 61 5b 05 |..........A..a[.|
-000004a0 de 22 d3 3d 00 72 a5 be 0a c1 76 94 a1 34 41 6e |.".=.r....v..4An|
-000004b0 55 f2 74 91 d2 6f 5c 47 87 c8 4b eb ab ab 10 b9 |U.t..o\G..K.....|
-000004c0 f9 0a bc 63 03 5f 90 5b e3 6f e1 44 97 cc bf d2 |...c._.[.o.D....|
-000004d0 e8 0d f5 9c 2e 9d 07 2c b2 00 90 0b 04 01 00 80 |.......,........|
-000004e0 67 3d c7 73 42 b9 b2 fd 4b dd 02 57 87 95 20 75 |g=.sB...K..W.. u|
-000004f0 da c1 e7 d3 33 09 01 5d e9 32 d7 20 7f 92 a9 dd |....3..].2. ....|
-00000500 bb 17 c5 ee f2 07 b2 04 1d 5e 1f c2 41 66 3f 14 |.........^..Af?.|
-00000510 90 cd 84 ac 49 46 04 3e ce 89 7d 79 42 2a 8c 56 |....IF.>..}yB*.V|
-00000520 93 d3 9c 3b 57 38 9e 91 af 62 ad 86 40 29 3d 46 |...;W8...b..@)=F|
-00000530 c7 cc f4 3f a1 7d ee 53 3d 94 1c 85 b9 1d a9 5f |...?.}.S=......_|
-00000540 10 8e ee 38 5e 98 5d 39 31 79 83 cd f9 02 a8 a9 |...8^.]91y......|
-00000550 b8 82 21 33 40 ed 27 54 a3 6e 64 cb e9 ce dd e1 |..!3@.'T.nd.....|
-00000560 16 03 03 00 04 0e 00 00 00 |.........|
+000001c0 b8 48 56 5a b6 29 83 64 6d 2a 9d 16 03 03 02 71 |.HVZ.).dm*.....q|
+000001d0 0b 00 02 6d 00 02 6a 00 02 67 30 82 02 63 30 82 |...m..j..g0..c0.|
+000001e0 01 cc a0 03 02 01 02 02 09 00 a2 73 00 0c 81 00 |...........s....|
+000001f0 cb f3 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 |..0...*.H.......|
+00000200 00 30 2b 31 17 30 15 06 03 55 04 0a 13 0e 47 6f |.0+1.0...U....Go|
+00000210 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 10 30 0e |ogle TESTING1.0.|
+00000220 06 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e |..U....Go Root0.|
+00000230 17 0d 31 35 30 31 30 31 30 30 30 30 30 30 5a 17 |..150101000000Z.|
+00000240 0d 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 26 |.250101000000Z0&|
+00000250 31 17 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c |1.0...U....Googl|
+00000260 65 20 54 45 53 54 49 4e 47 31 0b 30 09 06 03 55 |e TESTING1.0...U|
+00000270 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 2a 86 48 |....Go0..0...*.H|
+00000280 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 81 89 02 |............0...|
+00000290 81 81 00 af 87 88 f6 20 1b 95 65 6c 14 ab 44 05 |....... ..el..D.|
+000002a0 af 3b 45 14 e3 b7 6d fd 00 63 4d 95 7f fe 6a 62 |.;E...m..cM...jb|
+000002b0 35 86 c0 4a f9 18 7c f6 aa 25 5e 7a 64 31 66 00 |5..J..|..%^zd1f.|
+000002c0 ba f4 8e 92 af c7 6b d8 76 d4 f3 5f 41 cb 6e 56 |......k.v.._A.nV|
+000002d0 15 97 1b 97 c1 3c 12 39 21 66 3d 2b 16 d1 bc db |.....<.9!f=+....|
+000002e0 1c c0 a7 da b7 ca ad ba da cb d5 21 50 ec de 8d |...........!P...|
+000002f0 ab d1 6b 81 4b 89 02 f3 c4 be c1 6c 89 b1 44 84 |..k.K......l..D.|
+00000300 bd 21 d1 04 7d 9d 16 4d f9 82 15 f6 ef fa d6 09 |.!..}..M........|
+00000310 47 f2 fb 02 03 01 00 01 a3 81 93 30 81 90 30 0e |G..........0..0.|
+00000320 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 a0 30 1d |..U...........0.|
+00000330 06 03 55 1d 25 04 16 30 14 06 08 2b 06 01 05 05 |..U.%..0...+....|
+00000340 07 03 01 06 08 2b 06 01 05 05 07 03 02 30 0c 06 |.....+.......0..|
+00000350 03 55 1d 13 01 01 ff 04 02 30 00 30 19 06 03 55 |.U.......0.0...U|
+00000360 1d 0e 04 12 04 10 12 50 8d 89 6f 1b d1 dc 54 4d |.......P..o...TM|
+00000370 6e cb 69 5e 06 f4 30 1b 06 03 55 1d 23 04 14 30 |n.i^..0...U.#..0|
+00000380 12 80 10 bf 3d b6 a9 66 f2 b8 40 cf ea b4 03 78 |....=..f..@....x|
+00000390 48 1a 41 30 19 06 03 55 1d 11 04 12 30 10 82 0e |H.A0...U....0...|
+000003a0 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e 67 30 0d |example.golang0.|
+000003b0 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 03 81 81 |..*.H...........|
+000003c0 00 92 7c af 91 55 12 18 96 59 31 a6 48 40 d5 2d |..|..U...Y1.H@.-|
+000003d0 d5 ee bb 02 a0 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 |........|..0}<.v|
+000003e0 da 4f 3d c0 fa ae 2d 33 24 6b 03 7b 1b 67 59 11 |.O=...-3$k.{.gY.|
+000003f0 21 b5 11 bc 77 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f |!...w...n.-.5.d_|
+00000400 22 3e 63 10 6b be ff 14 86 6d 0d f0 15 31 a8 14 |">c.k....m...1..|
+00000410 38 1e 3b 84 87 2c cb 98 ed 51 76 b9 b1 4f dd db |8.;..,...Qv..O..|
+00000420 9b 84 04 86 40 fa 51 dd ba b4 8d eb e3 46 de 46 |....@.Q......F.F|
+00000430 b9 4f 86 c7 f9 a4 c2 41 34 ac cc f6 ea b0 ab 39 |.O.....A4......9|
+00000440 18 16 03 03 00 cd 0c 00 00 c9 03 00 17 41 04 1e |.............A..|
+00000450 d1 1c 5c d3 00 41 84 cd f7 e2 78 ad b5 7d 5b f2 |..\..A....x..}[.|
+00000460 23 5b 1a 18 44 3f 86 8e 3e 52 f2 4b b6 7d 84 b4 |#[..D?..>R.K.}..|
+00000470 1d 98 83 8f 2f 58 07 92 1f 58 2a 8d 8c e3 fa b7 |..../X...X*.....|
+00000480 aa 78 7e 33 9a 64 b9 b6 cb 78 94 be 2b c3 ac 04 |.x~3.d...x..+...|
+00000490 01 00 80 65 9f 42 e3 24 5c cd 18 aa 08 8e 6b bf |...e.B.$\.....k.|
+000004a0 39 15 2a a3 e6 42 1c 9d 6b 34 39 a2 2c 58 f5 5f |9.*..B..k49.,X._|
+000004b0 3e fb 2a 4c 01 2b e5 20 4e f5 69 77 c1 62 8f 68 |>.*L.+. N.iw.b.h|
+000004c0 be b4 c4 77 27 c9 4a 97 6d 18 7f 45 fd c9 9e 24 |...w'.J.m..E...$|
+000004d0 19 6b d9 00 c5 52 1a 34 a3 c9 cb eb 92 fc f6 48 |.k...R.4.......H|
+000004e0 3d 89 8a ff 82 be 55 c9 92 e2 24 86 b0 99 c6 e8 |=.....U...$.....|
+000004f0 a5 4c b7 bc 5a e5 f3 81 94 ee 15 47 e7 5e 8c 66 |.L..Z......G.^.f|
+00000500 32 72 7d 81 78 61 fe 25 98 dd 07 a2 92 4c eb ed |2r}.xa.%.....L..|
+00000510 f1 a7 17 16 03 03 00 04 0e 00 00 00 |............|
>>> Flow 3 (client to server)
00000000 16 03 03 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..|
00000010 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.|
00000020 a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e |.$ >.V...(^.+-O.|
00000030 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I|
00000040 a6 b5 68 1a 41 03 56 6b dc 5a 89 14 03 03 00 01 |..h.A.Vk.Z......|
-00000050 01 16 03 03 00 28 00 00 00 00 00 00 00 00 60 0e |.....(........`.|
-00000060 49 99 7a 9f 28 6e 46 03 a8 fd 0e b7 ed bb 9c ba |I.z.(nF.........|
-00000070 07 9c 4d cc 26 2b c2 70 a0 26 38 a0 f2 a0 |..M.&+.p.&8...|
+00000050 01 16 03 03 00 28 00 00 00 00 00 00 00 00 f0 4f |.....(.........O|
+00000060 fe 22 53 9e e1 61 f4 45 4e 41 ff 5e e4 63 25 f7 |."S..a.ENA.^.c%.|
+00000070 b2 f6 0a ea 89 75 7f d4 e7 3a cc e8 c2 2c |.....u...:...,|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 28 d2 ef 8f f4 7b |..........(....{|
-00000010 7a 9b c8 98 a4 36 f2 be 61 46 0e af f4 6f 63 71 |z....6..aF...ocq|
-00000020 6e bd 87 ea 1b f2 95 ad 36 7d a3 52 7f b2 b6 45 |n.......6}.R...E|
-00000030 3f 0b 62 |?.b|
+00000000 14 03 03 00 01 01 16 03 03 00 28 ad 49 0a 66 16 |..........(.I.f.|
+00000010 6d 64 42 c2 ab 38 bf 81 3d d9 14 13 d6 69 27 81 |mdB..8..=....i'.|
+00000020 ea 5c 53 fd 6c bf 81 6c 06 81 a5 67 f2 cd ed a3 |.\S.l..l...g....|
+00000030 d4 c2 08 |...|
>>> Flow 5 (client to server)
-00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 53 a1 85 |.............S..|
-00000010 ce 3c c1 64 39 80 fb db 67 ec 48 20 7f e9 82 f4 |.<.d9...g.H ....|
-00000020 2d 69 0a 15 03 03 00 1a 00 00 00 00 00 00 00 02 |-i..............|
-00000030 ab 78 11 1b 80 55 23 db 07 c5 7f c3 5e 19 d8 b3 |.x...U#.....^...|
-00000040 f8 c6 |..|
+00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 5c ab e3 |.............\..|
+00000010 f9 61 72 9e 44 46 1a 05 e9 00 eb 5b e0 73 22 03 |.ar.DF.....[.s".|
+00000020 9f 90 f9 15 03 03 00 1a 00 00 00 00 00 00 00 02 |................|
+00000030 04 28 a4 9d 07 79 95 40 0f f0 eb b9 5d 97 bf 87 |.(...y.@....]...|
+00000040 4a b6 |J.|
>>> Flow 1 (client to server)
-00000000 16 03 00 00 2f 01 00 00 2b 03 00 10 71 68 59 99 |..../...+...qhY.|
-00000010 9c a6 e7 36 8b 0d 03 be f5 42 ab 7c d0 3b 76 3e |...6.....B.|.;v>|
-00000020 46 7c 6c a3 94 09 b7 1b 0e 42 27 00 00 04 00 0a |F|l......B'.....|
-00000030 00 ff 01 00 |....|
+00000000 16 03 00 00 30 01 00 00 2c 03 00 50 32 2f f9 d5 |....0...,..P2/..|
+00000010 8f 83 ac 79 0e 0b e5 65 2c 87 79 01 7d 15 73 00 |...y...e,.y.}.s.|
+00000020 46 7c dc c6 6d 70 0b f3 d2 dc de 00 00 04 00 0a |F|..mp..........|
+00000030 00 ff 02 01 00 |.....|
>>> Flow 2 (server to client)
00000000 16 03 00 00 31 02 00 00 2d 03 00 00 00 00 00 00 |....1...-.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000002a0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 00 00 |..A4......9.....|
000002b0 04 0e 00 00 00 |.....|
>>> Flow 3 (client to server)
-00000000 16 03 00 00 84 10 00 00 80 1b 62 18 c8 60 0b f7 |..........b..`..|
-00000010 4a b8 ec 98 56 eb aa 4b d9 05 c0 f1 be b9 a5 28 |J...V..K.......(|
-00000020 62 e8 3e 25 08 9f 28 dd 08 1f 04 80 5f 10 81 cf |b.>%..(....._...|
-00000030 aa 2f 55 cd f1 0f ec 5b 90 0a 1f 49 bc a3 96 38 |./U....[...I...8|
-00000040 c7 32 b6 0a da b3 a5 7a 76 28 82 19 30 f4 6b ae |.2.....zv(..0.k.|
-00000050 fb 81 cc b4 ad 92 f8 c6 20 da 27 89 45 f4 43 c2 |........ .'.E.C.|
-00000060 16 7e de 29 03 dc 90 dd 3a 23 58 4c 35 be 11 a5 |.~.)....:#XL5...|
-00000070 52 18 79 13 e6 b3 2d e6 8e f5 76 60 0c c1 92 bb |R.y...-...v`....|
-00000080 07 67 c5 24 12 1b aa d6 53 14 03 00 00 01 01 16 |.g.$....S.......|
-00000090 03 00 00 40 5f 64 da b6 24 19 07 44 32 85 f3 c0 |...@_d..$..D2...|
-000000a0 9b c6 2c ad b1 d1 0f 4b 52 20 2f ea 6f 15 80 44 |..,....KR /.o..D|
-000000b0 78 34 44 02 67 e0 2e b4 b8 df 7b 3f 21 dd 66 9b |x4D.g.....{?!.f.|
-000000c0 e7 5f 71 ff 5f 30 fb 5b 5a 19 f0 24 f8 21 bc 7c |._q._0.[Z..$.!.||
-000000d0 00 e1 1f e8 |....|
+00000000 16 03 00 00 84 10 00 00 80 48 96 89 e9 d2 e6 c6 |.........H......|
+00000010 eb 9d f8 46 dd c7 d8 01 95 57 76 1a 59 1c 79 21 |...F.....Wv.Y.y!|
+00000020 94 0b 83 b2 c9 5e c1 5f 4f 12 00 10 63 12 d3 f9 |.....^._O...c...|
+00000030 ae ae 31 18 fa b4 33 37 eb b9 23 15 55 7e cf 62 |..1...37..#.U~.b|
+00000040 20 a7 cb eb 69 35 e0 35 32 e4 0a 4c c0 33 e9 7d | ...i5.52..L.3.}|
+00000050 f2 a8 4b e2 fe 90 62 7a 09 df c5 46 03 0c 52 7a |..K...bz...F..Rz|
+00000060 fb 96 dd fd 55 aa e5 be 3c 35 65 03 be e1 51 0f |....U...<5e...Q.|
+00000070 7b b3 05 6b e9 af 9b 0e e4 ea d9 34 69 a5 c2 9a |{..k.......4i...|
+00000080 71 a8 cc 0a 94 ef 91 14 88 14 03 00 00 01 01 16 |q...............|
+00000090 03 00 00 40 0c 34 26 4c cf f0 d4 a0 08 b9 b7 6b |...@.4&L.......k|
+000000a0 0a 69 55 48 91 2c 92 4c 9b e7 66 d0 b8 da 2d e7 |.iUH.,.L..f...-.|
+000000b0 89 ca f5 a4 3d 11 ff 87 22 07 c0 ed 72 9c ad 19 |....=..."...r...|
+000000c0 7d 63 2b 67 43 e3 33 76 a1 ac 69 77 55 bb 60 ba |}c+gC.3v..iwU.`.|
+000000d0 57 00 4e 2a |W.N*|
>>> Flow 4 (server to client)
-00000000 14 03 00 00 01 01 16 03 00 00 40 48 01 fc 08 a0 |..........@H....|
-00000010 fa 0e 63 58 25 18 06 3c 54 5c 60 ce 35 f6 ec b8 |..cX%..<T\`.5...|
-00000020 ed f8 97 c7 b0 5f 96 6b d1 10 53 e9 23 20 44 56 |....._.k..S.# DV|
-00000030 d7 ee 11 e1 6f b7 1e fb 33 94 7f f0 78 f5 2e 02 |....o...3...x...|
-00000040 37 7a 43 cf e7 c7 52 b3 c6 8d 8e 17 03 00 00 18 |7zC...R.........|
-00000050 f7 3c 05 79 4b 55 8c d7 2c 50 82 f0 61 34 f6 c7 |.<.yKU..,P..a4..|
-00000060 f3 71 e1 76 1d f0 65 b6 17 03 00 00 28 50 ce 6c |.q.v..e.....(P.l|
-00000070 96 97 70 88 b7 3c 74 a9 cb a3 0e ae 3a 7f 85 99 |..p..<t.....:...|
-00000080 58 36 10 7f 1a e8 f8 7d 83 75 24 7e b1 6a 8e b0 |X6.....}.u$~.j..|
-00000090 f1 cc 06 19 f7 15 03 00 00 18 2c 1d 87 1d ce 08 |..........,.....|
-000000a0 8f 10 09 6e bd fc ad e0 1d a7 47 d5 b9 8f 3e b8 |...n......G...>.|
-000000b0 b3 fa |..|
+00000000 14 03 00 00 01 01 16 03 00 00 40 dd e1 34 c5 4a |..........@..4.J|
+00000010 96 76 81 49 df 1b 3d 48 cc 6c b0 3b ee 77 a9 62 |.v.I..=H.l.;.w.b|
+00000020 91 b3 16 b0 e1 79 4b 2a 95 d8 54 98 7b 5e ac 0f |.....yK*..T.{^..|
+00000030 07 3b 06 36 e1 38 dc 75 6a af f7 ce a4 b2 3f 9e |.;.6.8.uj.....?.|
+00000040 36 b1 44 ce e9 6c 34 ba ce 97 02 17 03 00 00 18 |6.D..l4.........|
+00000050 5b be 71 2f a1 15 2f e9 9b 83 8e f1 9b e7 5b 4a |[.q/../.......[J|
+00000060 a1 85 13 03 c0 f2 30 0c 17 03 00 00 28 2c d9 9e |......0.....(,..|
+00000070 f4 d2 70 2a 37 76 66 e7 f4 5c c7 55 be d8 82 49 |..p*7vf..\.U...I|
+00000080 77 e0 4f 0f 87 4b c0 b1 f3 d2 a3 63 df 62 bc ee |w.O..K.....c.b..|
+00000090 5c c2 50 2a 96 15 03 00 00 18 8b 0a 68 8a d8 64 |\.P*........h..d|
+000000a0 4e 3f f9 ee c6 b2 21 51 03 10 6b 73 3b 8c a4 bb |N?....!Q..ks;...|
+000000b0 6d f2 |m.|
>>> Flow 1 (client to server)
-00000000 16 03 00 00 2f 01 00 00 2b 03 00 37 cd 49 a6 9f |..../...+..7.I..|
-00000010 e9 19 6a 39 cd 75 ce 6c f1 1b 96 d3 d4 f0 33 0c |..j9.u.l......3.|
-00000020 8f 53 b2 06 c4 0e 39 86 e3 98 7e 00 00 04 00 2f |.S....9...~..../|
-00000030 00 ff 01 00 |....|
+00000000 16 03 00 00 30 01 00 00 2c 03 00 36 b0 f3 52 13 |....0...,..6..R.|
+00000010 00 17 16 8f 6e 44 24 06 84 05 5b 03 e6 8a 55 ee |....nD$...[...U.|
+00000020 75 9c a8 77 9e e0 7b 15 f9 60 6e 00 00 04 00 2f |u..w..{..`n..../|
+00000030 00 ff 02 01 00 |.....|
>>> Flow 2 (server to client)
00000000 16 03 00 00 31 02 00 00 2d 03 00 00 00 00 00 00 |....1...-.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000002a0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 00 00 |..A4......9.....|
000002b0 04 0e 00 00 00 |.....|
>>> Flow 3 (client to server)
-00000000 16 03 00 00 84 10 00 00 80 4d 3f 93 aa 84 d8 ad |.........M?.....|
-00000010 93 2c 63 02 66 2f 96 88 b8 5c 09 1e 63 e2 e5 96 |.,c.f/...\..c...|
-00000020 26 d8 07 14 86 26 62 f4 0c 04 68 1c bf bb b1 53 |&....&b...h....S|
-00000030 97 96 43 59 4a 57 65 12 88 45 34 2b 86 2b 05 aa |..CYJWe..E4+.+..|
-00000040 9b 2b b9 aa 13 30 5c 91 c0 9f 03 8a 96 61 dd 87 |.+...0\......a..|
-00000050 ae e3 ad 6a 7b 8a 18 23 67 c9 df ad f2 47 eb 8b |...j{..#g....G..|
-00000060 7d 24 95 47 f1 4e b5 c6 15 b4 12 2a 42 df b3 99 |}$.G.N.....*B...|
-00000070 d1 b8 60 ce 6a cf 98 c1 13 a1 68 e6 92 ee 92 a2 |..`.j.....h.....|
-00000080 1d 2f 63 66 f3 b9 1b fc 33 14 03 00 00 01 01 16 |./cf....3.......|
-00000090 03 00 00 40 75 48 68 7d 8f f5 5a c0 cb 90 a5 9e |...@uHh}..Z.....|
-000000a0 94 bb eb 61 b5 36 aa ce 09 7a 11 ba 22 56 2a d7 |...a.6...z.."V*.|
-000000b0 91 a3 99 73 5b c5 b2 b7 b9 92 56 c6 cb fe 13 73 |...s[.....V....s|
-000000c0 28 30 03 26 62 63 7e 8a d2 58 c8 e7 52 03 26 67 |(0.&bc~..X..R.&g|
-000000d0 48 21 4f 21 |H!O!|
+00000000 16 03 00 00 84 10 00 00 80 2d 0b b1 1c 96 72 65 |.........-....re|
+00000010 e5 3b 5b 48 35 91 b8 2e 18 b5 6c 36 a4 91 10 0e |.;[H5.....l6....|
+00000020 15 63 de fb 7e ea 44 cd 2e 2f 37 2c 88 96 30 d4 |.c..~.D../7,..0.|
+00000030 07 ff 02 9b af 84 2c 43 6c 3a 1f 75 17 4c 5e 8b |......,Cl:.u.L^.|
+00000040 4a d9 df 68 fe ad 72 c9 0c f7 a5 0c a1 70 8b 9f |J..h..r......p..|
+00000050 e7 8e 1d 32 61 8e 80 e5 3a 3a 61 ea 22 1a 67 e5 |...2a...::a.".g.|
+00000060 06 6a 5e 0c 65 bd c7 32 9c 13 c1 53 ad 8e f1 be |.j^.e..2...S....|
+00000070 4d 6c 53 89 8f 9c 49 d2 85 58 04 b5 e8 53 b4 82 |MlS...I..X...S..|
+00000080 84 46 9d 70 fa 0a 34 15 1d 14 03 00 00 01 01 16 |.F.p..4.........|
+00000090 03 00 00 40 71 c7 4b ef 6b 7a f4 a2 29 dd c0 4b |...@q.K.kz..)..K|
+000000a0 ef 04 7d ea 1c 31 16 38 ae 85 f9 89 db 2f a8 04 |..}..1.8...../..|
+000000b0 ad 61 b7 33 73 8c 31 9b 72 5a f6 8b 10 71 0c af |.a.3s.1.rZ...q..|
+000000c0 99 89 14 63 b8 19 f8 0e 2c 0f 14 c6 d6 0a bd 4f |...c....,......O|
+000000d0 96 59 0d 60 |.Y.`|
>>> Flow 4 (server to client)
-00000000 14 03 00 00 01 01 16 03 00 00 40 84 8f 6e 80 35 |..........@..n.5|
-00000010 57 73 64 ef 29 bb 25 ff 5d 9d c7 55 38 b7 18 b3 |Wsd.).%.]..U8...|
-00000020 13 d1 ac 20 e0 1e f8 48 47 7a 40 2d bc a7 f2 af |... ...HGz@-....|
-00000030 ed a6 26 48 f4 51 b4 b6 56 60 9b c3 d9 43 00 95 |..&H.Q..V`...C..|
-00000040 86 be 6c 4e 49 6b f9 10 99 51 22 17 03 00 00 20 |..lNIk...Q".... |
-00000050 d4 7e dc 50 7b c2 26 ee 79 09 84 9f d7 e0 52 b1 |.~.P{.&.y.....R.|
-00000060 e8 9c 92 30 b7 34 06 c6 e5 86 57 a1 fb 8d 06 d6 |...0.4....W.....|
-00000070 17 03 00 00 30 93 0a 3d 64 26 3d a2 74 bc 8f d1 |....0..=d&=.t...|
-00000080 16 38 d0 6b 62 eb 82 b0 9a 50 68 aa 7e f7 45 32 |.8.kb....Ph.~.E2|
-00000090 43 cb 84 2d 95 39 6c bc c8 a0 2d aa ea fe f5 84 |C..-.9l...-.....|
-000000a0 c8 e4 8b 93 a1 15 03 00 00 20 03 7b 3e 43 1d 0a |......... .{>C..|
-000000b0 9b 9b e3 17 0f de be 75 e5 6e 2f 5b e8 8d a8 68 |.......u.n/[...h|
-000000c0 4e f0 82 49 00 dd b6 95 b4 22 |N..I....."|
+00000000 14 03 00 00 01 01 16 03 00 00 40 28 76 de 29 3b |..........@(v.);|
+00000010 48 77 56 f1 e5 97 21 20 88 9c 7d 5e 02 3d bb c9 |HwV...! ..}^.=..|
+00000020 2f b1 ce 2e 65 ac 53 ea a2 06 0e fb cf 53 28 1d |/...e.S......S(.|
+00000030 df b3 24 48 52 7a 28 d6 9e 50 83 64 da 34 c1 f4 |..$HRz(..P.d.4..|
+00000040 c9 bf ec 42 33 c4 8a 6f 89 aa 1c 17 03 00 00 20 |...B3..o....... |
+00000050 f2 af bb 38 4f 37 58 0e c4 2b 28 45 01 45 89 e9 |...8O7X..+(E.E..|
+00000060 31 5a 6d 8d 4d 1b 49 bd 7d 87 8a 62 e6 c8 03 43 |1Zm.M.I.}..b...C|
+00000070 17 03 00 00 30 60 ec e4 6f ec 88 33 d8 89 49 73 |....0`..o..3..Is|
+00000080 3a aa 67 ab 45 9f de c7 3f 0e 39 3d 9a 30 99 9c |:.g.E...?.9=.0..|
+00000090 2d 10 5f f0 7d 70 10 d5 8e ca 18 91 25 e8 9d d1 |-._.}p......%...|
+000000a0 36 b0 a7 90 9b 15 03 00 00 20 63 e9 92 98 7d b1 |6........ c...}.|
+000000b0 9a 88 07 37 b2 27 99 95 b9 16 17 74 c2 42 9c dc |...7.'.....t.B..|
+000000c0 80 32 de f4 f6 87 cb f1 87 d8 |.2........|
>>> Flow 1 (client to server)
-00000000 16 03 00 00 2f 01 00 00 2b 03 00 a7 1d 3d ed 0f |..../...+....=..|
-00000010 2c 7b 1f f1 c8 1c a9 17 ce 69 e2 73 a2 07 d2 91 |,{.......i.s....|
-00000020 e9 27 fa 70 11 6f 18 6d 2a 25 f1 00 00 04 00 05 |.'.p.o.m*%......|
-00000030 00 ff 01 00 |....|
+00000000 16 03 00 00 30 01 00 00 2c 03 00 3c 64 40 96 81 |....0...,..<d@..|
+00000010 b4 90 3d a5 bb 90 8a ba 39 73 4c cd 2d f9 4c 12 |..=.....9sL.-.L.|
+00000020 4c 6e d6 09 43 e3 eb 07 2e 52 1a 00 00 04 00 05 |Ln..C....R......|
+00000030 00 ff 02 01 00 |.....|
>>> Flow 2 (server to client)
00000000 16 03 00 00 31 02 00 00 2d 03 00 00 00 00 00 00 |....1...-.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000002a0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 00 00 |..A4......9.....|
000002b0 04 0e 00 00 00 |.....|
>>> Flow 3 (client to server)
-00000000 16 03 00 00 84 10 00 00 80 25 85 a3 22 29 e4 fb |.........%..")..|
-00000010 53 b9 a3 6b ed 70 2b 35 7f db 08 35 b8 4c 95 cd |S..k.p+5...5.L..|
-00000020 00 ec 5e a1 2e ba e9 ac a6 d4 ef ca 74 a0 12 1b |..^.........t...|
-00000030 a7 ec 76 22 2c 63 71 1a 3a 50 94 ce 96 c4 d7 76 |..v",cq.:P.....v|
-00000040 1f 47 58 c7 57 98 af ea 7e 57 05 68 d3 f9 87 02 |.GX.W...~W.h....|
-00000050 35 72 35 66 08 b4 cf 48 24 15 92 d5 ba 46 8d 60 |5r5f...H$....F.`|
-00000060 5a 53 0b e4 9b 53 44 55 dc 77 d1 e4 e0 25 51 f6 |ZS...SDU.w...%Q.|
-00000070 f1 7c 96 0b 32 d4 8c 04 d3 3d e6 70 c7 d6 60 a7 |.|..2....=.p..`.|
-00000080 ae 69 22 69 41 1a 8d 12 67 14 03 00 00 01 01 16 |.i"iA...g.......|
-00000090 03 00 00 3c 32 dd 86 fd 5b 53 74 ea 01 45 5b 9e |...<2...[St..E[.|
-000000a0 32 d0 9d 27 e8 ce 4c d5 a1 c2 d3 2e 0a e9 e5 d2 |2..'..L.........|
-000000b0 04 8c 77 a3 ff e9 8b 02 14 16 af 54 db ec c4 98 |..w........T....|
-000000c0 72 50 f7 65 fa eb ac 11 07 81 d7 fa 4e 18 34 bc |rP.e........N.4.|
+00000000 16 03 00 00 84 10 00 00 80 00 e0 40 dd e4 0f 54 |...........@...T|
+00000010 40 66 62 06 72 2a 7a 06 2d a9 0f 16 3b 5c 63 9b |@fb.r*z.-...;\c.|
+00000020 95 82 9c d4 95 57 c0 37 d1 30 6a 33 e1 5a ec 93 |.....W.7.0j3.Z..|
+00000030 12 ec 2a 94 c6 9c b3 6c a3 4f ef cd f1 80 25 a7 |..*....l.O....%.|
+00000040 54 ca 6a 6e b9 80 0b fc f1 e9 60 a0 f5 33 24 3b |T.jn......`..3$;|
+00000050 13 04 9a f1 8a 37 cd 11 cf 95 ae 71 ba 73 8e 00 |.....7.....q.s..|
+00000060 86 17 6a 3b d5 9e a9 04 87 fd 62 ed 4c b5 01 55 |..j;......b.L..U|
+00000070 65 a2 fb e8 1d 86 a5 58 2a ad e7 fd d3 44 2f 7d |e......X*....D/}|
+00000080 25 b7 3b c7 75 39 5c 45 f6 14 03 00 00 01 01 16 |%.;.u9\E........|
+00000090 03 00 00 3c e6 58 15 b2 fb 0d 44 ed 43 d5 ff a8 |...<.X....D.C...|
+000000a0 41 25 83 41 46 da f6 8e 70 34 39 c6 6c 2c ea 1b |A%.AF...p49.l,..|
+000000b0 2a 02 5c 4b e4 87 58 33 6c d0 22 2e ce 85 df 31 |*.\K..X3l."....1|
+000000c0 0d 71 4c 1a f9 9c 64 d7 87 53 eb c9 1a 0a 16 dc |.qL...d..S......|
>>> Flow 4 (server to client)
-00000000 14 03 00 00 01 01 16 03 00 00 3c 29 af 2c 96 3a |..........<).,.:|
-00000010 be a0 91 a8 e4 66 6b 30 ba e2 80 fc a2 8a 09 b4 |.....fk0........|
-00000020 28 14 3b 36 c2 3b 3e 88 e2 10 da 93 af 71 9a 06 |(.;6.;>......q..|
-00000030 1c 8d 97 04 05 ec e2 69 cf 28 20 0f ec 4c a7 f3 |.......i.( ..L..|
-00000040 18 4e 6b 5b 88 9c a9 17 03 00 00 21 5e 0b b4 2d |.Nk[.......!^..-|
-00000050 a6 b5 0b 3a 86 de 8a e7 87 f3 4c f6 74 7e 0d 16 |...:......L.t~..|
-00000060 9b fc 0c 42 6b f4 9e 15 8b 6a c5 97 88 15 03 00 |...Bk....j......|
-00000070 00 16 f0 a4 e2 16 bf 81 05 ad 1d f5 1c 89 d9 ab |................|
-00000080 48 23 ab 96 ea 92 aa cd |H#......|
+00000000 14 03 00 00 01 01 16 03 00 00 3c 17 a2 5b 4a 06 |..........<..[J.|
+00000010 63 6a 4b f9 ef 66 ed 31 f6 87 75 20 8b 08 8d 5d |cjK..f.1..u ...]|
+00000020 0f 72 87 dd 8d db 99 d5 06 42 2b a3 84 77 35 f2 |.r.......B+..w5.|
+00000030 1d 11 ae 0b 0c df ed 10 6e 23 27 93 29 65 25 f6 |........n#'.)e%.|
+00000040 60 b9 76 c8 95 2b 0c 17 03 00 00 21 df 08 e8 1f |`.v..+.....!....|
+00000050 2f ea 5a 61 d6 d4 4a c0 c1 b5 59 bc e1 89 6e 88 |/.Za..J...Y...n.|
+00000060 bb 8d 16 db 64 87 31 6c 2d d6 c7 d2 ed 15 03 00 |....d.1l-.......|
+00000070 00 16 a9 53 32 af 7a a4 88 02 93 6b aa 95 84 4f |...S2.z....k...O|
+00000080 17 5a 97 93 67 87 3b 07 |.Z..g.;.|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 7d 01 00 00 79 03 01 65 14 3f 40 e4 |....}...y..e.?@.|
-00000010 2f 74 65 7e d0 c8 87 03 59 61 9d c3 84 5e c9 62 |/te~....Ya...^.b|
-00000020 e6 46 b8 0c 4a 5e 3f 33 43 a5 dd 00 00 04 c0 0a |.F..J^?3C.......|
-00000030 00 ff 02 01 00 00 4b 00 0b 00 04 03 00 01 02 00 |......K.........|
-00000040 0a 00 3a 00 38 00 0e 00 0d 00 19 00 1c 00 0b 00 |..:.8...........|
-00000050 0c 00 1b 00 18 00 09 00 0a 00 1a 00 16 00 17 00 |................|
-00000060 08 00 06 00 07 00 14 00 15 00 04 00 05 00 12 00 |................|
-00000070 13 00 01 00 02 00 03 00 0f 00 10 00 11 00 0f 00 |................|
-00000080 01 01 |..|
+00000000 16 03 01 00 5f 01 00 00 5b 03 01 ad 87 94 6b 8a |...._...[.....k.|
+00000010 38 9e 70 d6 94 8a 73 a9 39 d8 d7 25 ab 47 92 4c |8.p...s.9..%.G.L|
+00000020 b1 20 8e 4d f3 7b cd 84 5e 13 c1 00 00 04 c0 0a |. .M.{..^.......|
+00000030 00 ff 02 01 00 00 2d 00 0b 00 04 03 00 01 02 00 |......-.........|
+00000040 0a 00 1c 00 1a 00 17 00 19 00 1c 00 1b 00 18 00 |................|
+00000050 1a 00 16 00 0e 00 0d 00 0b 00 0c 00 09 00 0a 00 |................|
+00000060 0f 00 01 01 |....|
>>> Flow 2 (server to client)
00000000 16 03 01 00 31 02 00 00 2d 03 01 00 00 00 00 00 |....1...-.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000260 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd a7 24 20 3e |uq..T[....g..$ >|
00000270 b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e f1 07 9f 6c |.V...(^.+-O....l|
00000280 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 b5 68 1a |K[.V.2B.X..I..h.|
-00000290 41 03 56 6b dc 5a 89 00 8b 30 81 88 02 42 01 3e |A.Vk.Z...0...B.>|
-000002a0 79 81 6e 89 cd 3e 3f ec e4 b5 75 17 28 ee fb 09 |y.n..>?...u.(...|
-000002b0 21 19 6f 3c e6 ca 1e f2 18 b6 47 f8 37 05 1c 85 |!.o<......G.7...|
-000002c0 0f a4 b8 6b 40 04 50 77 e3 05 9b 24 b8 93 e8 4d |...k@.Pw...$...M|
-000002d0 ef 30 cd 51 90 58 a2 49 71 b3 3f b9 46 ab a9 72 |.0.Q.X.Iq.?.F..r|
-000002e0 02 42 01 58 ef 20 c1 0a 33 f8 fd 50 9e 65 f5 ef |.B.X. ..3..P.e..|
-000002f0 f4 91 49 2d d2 de 66 2b 97 69 7d b1 d0 ef d6 91 |..I-..f+.i}.....|
-00000300 0f fc 57 2b 73 b9 49 01 33 d2 1b 5b 9a 2c 51 35 |..W+s.I.3..[.,Q5|
-00000310 0e eb 38 53 fa 20 07 84 52 b3 43 24 09 5a 32 c0 |..8S. ..R.C$.Z2.|
-00000320 32 17 34 6c 16 03 01 00 04 0e 00 00 00 |2.4l.........|
+00000290 41 03 56 6b dc 5a 89 00 8b 30 81 88 02 42 00 8b |A.Vk.Z...0...B..|
+000002a0 48 d5 a3 a0 35 5c 31 f5 0b e8 72 7c 87 31 79 af |H...5\1...r|.1y.|
+000002b0 7f 12 93 9a f9 df d5 44 bf 08 5a 6b 1c 68 dd 73 |.......D..Zk.h.s|
+000002c0 67 0f 32 41 45 53 bf 74 cf 91 54 e7 7a 88 41 7a |g.2AES.t..T.z.Az|
+000002d0 15 ea 3d e3 b8 93 c0 3f 24 4c fb ee 25 f1 20 80 |..=....?$L..%. .|
+000002e0 02 42 01 ab 97 5f 8b 8d 22 71 f9 f5 a3 59 69 42 |.B..._.."q...YiB|
+000002f0 06 bd 12 f5 61 53 cb c8 a1 b4 90 87 12 94 9b f8 |....aS..........|
+00000300 b3 1d 34 d9 cd 64 20 9c 92 ec b5 72 35 01 44 3a |..4..d ....r5.D:|
+00000310 86 e4 54 46 0d 74 1d 4e d8 41 16 eb ac c3 8a 2f |..TF.t.N.A...../|
+00000320 20 11 ad bc 16 03 01 00 04 0e 00 00 00 | ............|
>>> Flow 3 (client to server)
-00000000 16 03 01 00 46 10 00 00 42 41 04 31 74 f8 f6 18 |....F...BA.1t...|
-00000010 55 6a 9b 3b 78 0a 0e f0 c9 91 aa 8e 77 39 0a 88 |Uj.;x.......w9..|
-00000020 a4 d4 f6 04 9d de 89 18 b6 50 12 72 26 9c 8f e1 |.........P.r&...|
-00000030 f0 b2 e6 df ce 3b 46 be e9 2a 9a e3 7f d1 d5 92 |.....;F..*......|
-00000040 ff e3 ae 0a 2d a1 3b 07 f6 04 59 14 03 01 00 01 |....-.;...Y.....|
-00000050 01 16 03 01 00 30 02 4f df 41 30 97 6f f7 18 ca |.....0.O.A0.o...|
-00000060 05 35 17 a1 a2 a5 71 61 b1 d8 dd 9a c6 f3 54 53 |.5....qa......TS|
-00000070 84 f6 fb 93 1e 0e 9d e7 fe 35 85 9e 73 d0 2e a1 |.........5..s...|
-00000080 a7 63 d9 40 c6 ac |.c.@..|
+00000000 16 03 01 00 46 10 00 00 42 41 04 38 ca 59 61 cd |....F...BA.8.Ya.|
+00000010 17 4a cf a8 0b 81 c6 b7 7f 52 dd 95 d7 57 9d 24 |.J.......R...W.$|
+00000020 bb b1 02 af 57 ee b9 f9 c5 a0 c3 20 44 e1 9a e4 |....W...... D...|
+00000030 83 64 7d a1 fa 9d 2e 3b 5e be 0f af ed 96 f3 09 |.d}....;^.......|
+00000040 62 a2 22 21 72 f8 84 89 8a fd 10 14 03 01 00 01 |b."!r...........|
+00000050 01 16 03 01 00 30 bd e6 23 e0 32 b8 4c ef ce 9e |.....0..#.2.L...|
+00000060 22 a5 77 2c f1 7e 2f 8d 8b 9e a5 92 42 f9 0f 02 |".w,.~/.....B...|
+00000070 eb 2e 94 f1 6d a3 24 3f c0 ae bb c0 c4 99 08 51 |....m.$?.......Q|
+00000080 47 28 8b 4e f9 02 |G(.N..|
>>> Flow 4 (server to client)
-00000000 14 03 01 00 01 01 16 03 01 00 30 07 7e 4e 9c 19 |..........0.~N..|
-00000010 f0 35 cd 02 b7 a6 0a 1a b1 a8 11 a3 f9 b1 35 7b |.5............5{|
-00000020 96 7f e6 e1 00 c6 6d 9e e6 8a bb a2 b8 bd a3 9d |......m.........|
-00000030 05 22 1b f1 f5 28 4a 00 6e f1 71 17 03 01 00 20 |."...(J.n.q.... |
-00000040 ad c7 4c dc f4 81 1a 39 3d 86 5e 8e f5 0d a3 33 |..L....9=.^....3|
-00000050 88 32 e7 be 8b 6a 8d 44 29 7b 47 fd e5 33 01 1e |.2...j.D){G..3..|
-00000060 17 03 01 00 30 61 47 ee ae 89 25 ac 85 3b 8a 84 |....0aG...%..;..|
-00000070 47 61 ea 3e 4c 70 57 07 d6 f1 1c 21 cb 44 7e de |Ga.>LpW....!.D~.|
-00000080 b5 01 9e fb fe ad bc be 74 c0 65 a0 6b c1 0c 8c |........t.e.k...|
-00000090 2b 00 24 c6 b7 15 03 01 00 20 b7 8b 6b e5 77 ab |+.$...... ..k.w.|
-000000a0 f6 50 9e 88 4d 56 a8 25 8d 02 db cb 68 8b 3f 62 |.P..MV.%....h.?b|
-000000b0 be aa 02 24 75 b1 e5 4b 18 c9 |...$u..K..|
+00000000 14 03 01 00 01 01 16 03 01 00 30 11 a9 f0 95 27 |..........0....'|
+00000010 ac 0a b7 8e 0d 42 0a 2a f8 f8 e2 4f 4f 4a 79 d1 |.....B.*...OOJy.|
+00000020 73 e6 4d 42 90 3c 06 f8 7b da 26 cc 58 be 97 f6 |s.MB.<..{.&.X...|
+00000030 41 32 fb 39 2f fa e1 bc 59 2b 45 17 03 01 00 20 |A2.9/...Y+E.... |
+00000040 93 6a a1 a6 a2 e6 be bb be 2f 8f 0c 52 39 1c 6a |.j......./..R9.j|
+00000050 6d 4c af 38 f7 60 8b ad 0e c7 62 0c 8b a4 42 14 |mL.8.`....b...B.|
+00000060 17 03 01 00 30 da b0 1b ef cf 45 86 09 e9 be aa |....0.....E.....|
+00000070 0f 71 af a3 86 d0 0f 2d e8 76 39 9a c4 1f f5 c2 |.q.....-.v9.....|
+00000080 82 0a ee 34 0e a6 3b 19 b8 2c 10 ad fc 03 33 31 |...4..;..,....31|
+00000090 10 42 9b 6e 7b 15 03 01 00 20 ac 73 4d 4b 92 30 |.B.n{.... .sMK.0|
+000000a0 bf 4c bc 77 c1 87 d7 20 ad 82 bd 75 31 82 0d 34 |.L.w... ...u1..4|
+000000b0 cb b2 86 fd 4f 9c 84 a3 80 af |....O.....|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 36 01 00 00 32 03 01 35 4a e8 32 84 |....6...2..5J.2.|
-00000010 51 68 04 7e d0 0f 43 94 c7 5d 44 d2 95 a3 12 63 |Qh.~..C..]D....c|
-00000020 77 c5 ce 78 5a 25 a3 81 df c4 6b 00 00 04 00 0a |w..xZ%....k.....|
-00000030 00 ff 01 00 00 05 00 0f 00 01 01 |...........|
+00000000 16 03 01 00 37 01 00 00 33 03 01 8d f4 8c 3d bd |....7...3.....=.|
+00000010 d8 81 53 bb f5 bc 18 69 07 09 0d 05 93 4f 6f eb |..S....i.....Oo.|
+00000020 fa fb 03 65 d4 49 a3 df 9f c3 a5 00 00 04 00 0a |...e.I..........|
+00000030 00 ff 02 01 00 00 05 00 0f 00 01 01 |............|
>>> Flow 2 (server to client)
00000000 16 03 01 00 31 02 00 00 2d 03 01 00 00 00 00 00 |....1...-.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000002a0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 01 00 |..A4......9.....|
000002b0 04 0e 00 00 00 |.....|
>>> Flow 3 (client to server)
-00000000 16 03 01 00 86 10 00 00 82 00 80 1f 4d 12 64 f2 |............M.d.|
-00000010 72 22 86 4a 16 05 3f d2 1b e5 ed a7 f1 19 c4 6d |r".J..?........m|
-00000020 1d 3a 5c f6 46 8f b9 4d 9e c4 d4 19 95 0a 63 9f |.:\.F..M......c.|
-00000030 8a 41 1f fc d5 98 45 ca 69 33 37 64 d5 c8 0e 5a |.A....E.i37d...Z|
-00000040 12 9f 06 54 8a 61 8b 13 f0 d8 fb b9 97 fb cd 1d |...T.a..........|
-00000050 bd 6c 88 cc 98 57 c3 66 3a 86 04 c9 b9 21 c6 f2 |.l...W.f:....!..|
-00000060 f3 43 7d 4e bf 28 d5 a2 d7 39 e0 78 cb eb b4 af |.C}N.(...9.x....|
-00000070 21 0e ae 4c 16 9b b3 49 5f 81 02 55 59 97 d9 d2 |!..L...I_..UY...|
-00000080 c4 e2 4c be 0a a6 41 62 48 1d 66 14 03 01 00 01 |..L...AbH.f.....|
-00000090 01 16 03 01 00 28 9d e0 c3 31 82 c2 48 5d fb 47 |.....(...1..H].G|
-000000a0 85 60 d4 17 d2 4f 4d 3c 64 db e4 49 1f a9 66 93 |.`...OM<d..I..f.|
-000000b0 72 6c 32 06 a5 0c 1f db 64 6d 54 71 fd 30 |rl2.....dmTq.0|
+00000000 16 03 01 00 86 10 00 00 82 00 80 6b 00 e3 47 e3 |...........k..G.|
+00000010 0d 22 44 53 7a b9 d1 14 4e e4 47 17 a1 e2 f5 d2 |."DSz...N.G.....|
+00000020 f7 82 2f 1b e2 3a 60 aa 79 36 fa 74 05 72 66 88 |../..:`.y6.t.rf.|
+00000030 3f 6a 57 8d 10 8a a1 80 3c 74 5b 29 c3 a1 b8 57 |?jW.....<t[)...W|
+00000040 20 cc 75 fc 0e 3c 09 06 46 52 b2 ca b2 cd bf 4c | .u..<..FR.....L|
+00000050 b3 12 2b 59 f1 41 a2 c7 4c 62 c7 61 26 2b 89 fe |..+Y.A..Lb.a&+..|
+00000060 01 9a b6 2b b4 15 75 05 4b f8 5b 04 9a 64 cc 06 |...+..u.K.[..d..|
+00000070 6b 8c 98 6d 51 37 50 b4 69 03 5c 9a ed e3 9a 23 |k..mQ7P.i.\....#|
+00000080 a9 68 e0 56 58 f7 f4 a0 d6 b4 55 14 03 01 00 01 |.h.VX.....U.....|
+00000090 01 16 03 01 00 28 9f ac be d9 6f ab cb 0e 45 8a |.....(....o...E.|
+000000a0 96 71 fd 23 39 b0 02 cc a6 5a 7a 64 e2 29 9f 18 |.q.#9....Zzd.)..|
+000000b0 dc 25 84 ee 76 56 3c cc d9 15 34 16 67 7e |.%..vV<...4.g~|
>>> Flow 4 (server to client)
-00000000 14 03 01 00 01 01 16 03 01 00 28 94 66 8f ad 8f |..........(.f...|
-00000010 9f 00 72 f6 af 51 47 67 63 df 3f dd 17 09 0a c5 |..r..QGgc.?.....|
-00000020 bf f8 4d 66 39 f9 b5 47 01 f8 e8 6d ed b4 17 39 |..Mf9..G...m...9|
-00000030 ff 0a ca 17 03 01 00 18 68 93 94 51 12 b9 17 0b |........h..Q....|
-00000040 d1 a0 22 fc cc c4 76 1a 1e 02 c6 20 5e 74 83 4c |.."...v.... ^t.L|
-00000050 17 03 01 00 28 08 bd 86 07 84 90 78 bd 1d 90 ce |....(......x....|
-00000060 09 80 bb d8 de fd 39 82 4b c4 0d 06 f3 65 f5 5b |......9.K....e.[|
-00000070 3d c3 fd 69 80 1f 51 ce 1d 98 f1 05 fa 15 03 01 |=..i..Q.........|
-00000080 00 18 ed 48 04 21 85 77 d7 b6 29 e3 25 af ea ec |...H.!.w..).%...|
-00000090 3e 41 82 a0 ca 7d 44 79 8a 0b |>A...}Dy..|
+00000000 14 03 01 00 01 01 16 03 01 00 28 f4 cf 23 f8 86 |..........(..#..|
+00000010 83 df 44 af 1c 25 b1 51 84 5b 6a f3 0e 6b 47 5c |..D..%.Q.[j..kG\|
+00000020 2a 59 67 db 42 11 f9 53 58 4e db 6f 00 b2 20 5b |*Yg.B..SXN.o.. [|
+00000030 ae a3 43 17 03 01 00 18 df e0 22 d6 05 ab 79 c7 |..C......."...y.|
+00000040 87 8a 82 83 01 bc 06 45 36 74 4d 1c 40 96 97 5f |.......E6tM.@.._|
+00000050 17 03 01 00 28 49 bd b7 e9 41 6b eb b1 aa 89 60 |....(I...Ak....`|
+00000060 21 91 df bf f4 7a 49 9d 54 04 4a 16 1a d1 44 9a |!....zI.T.J...D.|
+00000070 09 6c 4f 01 3d c0 2f d5 a3 72 a3 b2 fe 15 03 01 |.lO.=./..r......|
+00000080 00 18 5c 7a de a0 ef ed 56 99 99 01 5f b4 32 b3 |..\z....V..._.2.|
+00000090 00 be c6 cc 7e bb 6f 82 7d f7 |....~.o.}.|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 36 01 00 00 32 03 01 8c 5a 87 31 6a |....6...2...Z.1j|
-00000010 8c 7a d5 26 4b 94 17 27 fc a2 c0 5f b5 bc 3f 10 |.z.&K..'..._..?.|
-00000020 80 0e e0 1e 36 80 4b 91 61 77 d4 00 00 04 00 2f |....6.K.aw...../|
-00000030 00 ff 01 00 00 05 00 0f 00 01 01 |...........|
+00000000 16 03 01 00 37 01 00 00 33 03 01 39 72 8e 06 ed |....7...3..9r...|
+00000010 d2 74 5c 02 74 0e 2b 7a bd 54 ce be 17 a0 4f 1a |.t\.t.+z.T....O.|
+00000020 c5 72 b1 e8 3e 2e 90 68 ff fc 6e 00 00 04 00 2f |.r..>..h..n..../|
+00000030 00 ff 02 01 00 00 05 00 0f 00 01 01 |............|
>>> Flow 2 (server to client)
00000000 16 03 01 00 31 02 00 00 2d 03 01 00 00 00 00 00 |....1...-.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000002a0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 01 00 |..A4......9.....|
000002b0 04 0e 00 00 00 |.....|
>>> Flow 3 (client to server)
-00000000 16 03 01 00 86 10 00 00 82 00 80 31 f5 2e e4 c7 |...........1....|
-00000010 f5 76 d6 f7 2d 1b 8d 4d a9 2a 43 84 b2 0b 08 d6 |.v..-..M.*C.....|
-00000020 4d d9 9a eb 4b 01 49 6e 11 45 43 0d 31 a7 c3 66 |M...K.In.EC.1..f|
-00000030 da 1c 92 68 fb 3d 36 27 94 2f 67 ae 3d 31 a3 8f |...h.=6'./g.=1..|
-00000040 01 5a d9 17 92 bc 20 7c cb ae b4 ca 4c ce d4 a9 |.Z.... |....L...|
-00000050 2c 1d fe fc 3c a9 14 31 1d 65 08 d8 6e 8d ac 9d |,...<..1.e..n...|
-00000060 21 ee 63 4a e2 da 3c 0e b1 34 8f 6e 20 dd d4 d4 |!.cJ..<..4.n ...|
-00000070 d8 16 27 5d 02 54 e6 ec 5f 43 84 5b 21 24 ef 5d |..'].T.._C.[!$.]|
-00000080 45 c4 2b 2c 98 7d 50 dc 0b fc 76 14 03 01 00 01 |E.+,.}P...v.....|
-00000090 01 16 03 01 00 30 ef 50 ea 3c e3 b7 a8 5b 9a d2 |.....0.P.<...[..|
-000000a0 11 69 0f d0 5e 79 c8 cb 68 4a ac 16 ef b4 de 1f |.i..^y..hJ......|
-000000b0 21 0b 8e 91 cb 70 3f 02 bd 45 c1 34 02 e0 66 8a |!....p?..E.4..f.|
-000000c0 00 ea 6c 5a 96 41 |..lZ.A|
+00000000 16 03 01 00 86 10 00 00 82 00 80 0e a2 23 fe 89 |.............#..|
+00000010 46 08 20 98 da 4d 91 a4 48 40 ab 03 df 1f 00 67 |F. ..M..H@.....g|
+00000020 f3 fb fb 22 f7 8e d6 65 2c 43 a7 f4 9c 0e 25 cc |..."...e,C....%.|
+00000030 d9 3b b5 58 df bd 93 27 1c df 69 37 27 01 cb 0d |.;.X...'..i7'...|
+00000040 b4 f4 a6 8d 91 fe ef dc 9a e2 09 7c 53 1a 73 6d |...........|S.sm|
+00000050 b9 f6 89 0a 1f 94 f0 26 25 ef 73 54 20 d5 8d 77 |.......&%.sT ..w|
+00000060 36 2e e7 4c 9a f1 4a be ae 6e b6 be 16 10 31 42 |6..L..J..n....1B|
+00000070 9e d2 49 41 2c 32 52 11 bc 85 2d fa 39 80 9b f9 |..IA,2R...-.9...|
+00000080 95 fe e8 88 2a a2 57 65 7e 38 b2 14 03 01 00 01 |....*.We~8......|
+00000090 01 16 03 01 00 30 1c 6f 91 45 16 ed 25 82 ee 5f |.....0.o.E..%.._|
+000000a0 f9 f0 09 0c a4 ad 56 61 e5 b7 a2 05 50 02 b8 80 |......Va....P...|
+000000b0 ef 73 d1 11 3c 25 50 44 0d ba b5 7c fd 5d 7a df |.s..<%PD...|.]z.|
+000000c0 14 62 1b 29 be 29 |.b.).)|
>>> Flow 4 (server to client)
-00000000 14 03 01 00 01 01 16 03 01 00 30 99 2c 65 32 5f |..........0.,e2_|
-00000010 53 37 d8 c2 98 87 f4 68 b6 d7 52 6a 14 c7 df 6e |S7.....h..Rj...n|
-00000020 bb ce ae 31 d4 04 24 4d e9 c2 39 7b 68 a7 fa 90 |...1..$M..9{h...|
-00000030 c1 30 14 a2 20 c0 8d e1 2a dc 22 17 03 01 00 20 |.0.. ...*.".... |
-00000040 41 c5 03 05 20 53 e9 fa 0a 26 38 ab 84 6a 5e 36 |A... S...&8..j^6|
-00000050 1b 03 80 2f c3 5c 0b 2c bd 7f 79 68 bb ab 4d 70 |.../.\.,..yh..Mp|
-00000060 17 03 01 00 30 a1 04 3e f4 a2 54 7a e7 09 0f 20 |....0..>..Tz... |
-00000070 38 f8 9e bb 1b 61 28 bf 46 e8 75 56 b4 c3 93 b9 |8....a(.F.uV....|
-00000080 8c 18 3e 8e af 9f 59 1a 96 be db 61 80 56 c6 09 |..>...Y....a.V..|
-00000090 3c 21 02 37 d2 15 03 01 00 20 13 d1 81 7d ca 04 |<!.7..... ...}..|
-000000a0 2b c3 fc fa 06 5b b4 98 59 27 0d 07 2a 39 3c 6f |+....[..Y'..*9<o|
-000000b0 8d 64 83 17 0f ba ec 22 21 36 |.d....."!6|
+00000000 14 03 01 00 01 01 16 03 01 00 30 5e 8c b1 dc 1f |..........0^....|
+00000010 b3 18 85 4a 46 02 fb 34 e4 05 56 78 4c e3 34 63 |...JF..4..VxL.4c|
+00000020 06 08 b4 ee 36 e2 28 ab c9 98 ee 26 4e 5b 5d 42 |....6.(....&N[]B|
+00000030 5f f8 e1 d1 2f 8b c8 ef 5a 65 40 17 03 01 00 20 |_.../...Ze@.... |
+00000040 e7 92 6e b1 60 b9 f8 cd 53 d3 37 5b 44 74 1c af |..n.`...S.7[Dt..|
+00000050 90 93 13 8e 55 25 cc 9f 57 8c f3 06 f7 ba e0 f9 |....U%..W.......|
+00000060 17 03 01 00 30 fc 83 e6 4e 8c 65 8f d1 7c c7 f4 |....0...N.e..|..|
+00000070 8b 68 0d 5d da 8e 49 45 68 ea 4c e3 7f 7d 84 87 |.h.]..IEh.L..}..|
+00000080 2f 63 e0 fb 43 24 04 cd e2 38 32 50 0a 4c 43 ce |/c..C$...82P.LC.|
+00000090 3b 12 a5 6b 99 15 03 01 00 20 2a 42 d8 57 26 79 |;..k..... *B.W&y|
+000000a0 51 ee 79 9d b2 83 b8 49 a4 e9 a2 08 34 73 c4 f5 |Q.y....I....4s..|
+000000b0 53 21 4b 78 ec 5b ce b4 4e a0 |S!Kx.[..N.|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 36 01 00 00 32 03 01 c5 fc 32 c0 09 |....6...2....2..|
-00000010 47 0b a9 f3 72 c9 6c 3a e0 94 33 48 35 ac b9 3b |G...r.l:..3H5..;|
-00000020 da 5f 8b 6e 0c 54 c3 16 f0 39 bd 00 00 04 00 05 |._.n.T...9......|
-00000030 00 ff 01 00 00 05 00 0f 00 01 01 |...........|
+00000000 16 03 01 00 37 01 00 00 33 03 01 b3 82 99 50 b0 |....7...3.....P.|
+00000010 1e 7a 46 48 9d 8e 93 32 3b 01 bc 50 e9 5c eb 91 |.zFH...2;..P.\..|
+00000020 25 4b c1 ea 0a 91 c9 b3 2b 54 90 00 00 04 00 05 |%K......+T......|
+00000030 00 ff 02 01 00 00 05 00 0f 00 01 01 |............|
>>> Flow 2 (server to client)
00000000 16 03 01 00 31 02 00 00 2d 03 01 00 00 00 00 00 |....1...-.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000002a0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 01 00 |..A4......9.....|
000002b0 04 0e 00 00 00 |.....|
>>> Flow 3 (client to server)
-00000000 16 03 01 00 86 10 00 00 82 00 80 6a ad 7f e3 26 |...........j...&|
-00000010 71 da 48 af 11 63 de 2e e8 50 f9 6a be 04 3d 17 |q.H..c...P.j..=.|
-00000020 d1 29 fe 2c 7f b6 26 c1 7e 0b 18 1c 41 62 5c 91 |.).,..&.~...Ab\.|
-00000030 ee 26 9c 92 f5 d1 e9 29 e1 ca a7 01 6a 41 b9 00 |.&.....)....jA..|
-00000040 34 1d 5b c6 28 0e 1a 8f 32 c5 03 e7 a1 8f 89 1b |4.[.(...2.......|
-00000050 af 13 22 2b 5b e8 76 2d 00 ac da 27 75 95 75 e7 |.."+[.v-...'u.u.|
-00000060 00 00 39 2c bf f2 01 57 e6 29 e3 26 b1 6b ae c5 |..9,...W.).&.k..|
-00000070 8d ce d2 36 b2 94 1f 9c 30 5e b2 16 3d 20 cf 4d |...6....0^..= .M|
-00000080 88 f5 ac 4c 27 e3 f5 86 ef 9e dc 14 03 01 00 01 |...L'...........|
-00000090 01 16 03 01 00 24 48 d8 80 c4 37 22 31 99 53 30 |.....$H...7"1.S0|
-000000a0 5b 00 07 7e 87 2e 59 9a d9 0c 42 9e dd ed da 89 |[..~..Y...B.....|
-000000b0 1a 1f cb ab 55 0c ba d9 a9 c0 |....U.....|
+00000000 16 03 01 00 86 10 00 00 82 00 80 05 1c 93 2a 69 |..............*i|
+00000010 f7 0b 1d 59 ea ca c2 4a b1 7c ef 22 4c 7b 31 5f |...Y...J.|."L{1_|
+00000020 18 8d 32 b6 db 75 8c f8 45 07 27 e1 9f 3f 9d 0b |..2..u..E.'..?..|
+00000030 02 ac 2c 3f aa bf 79 fb d4 af 98 0c b2 c0 03 4b |..,?..y........K|
+00000040 86 26 c3 30 f3 ea 2b 1a ab 70 90 8d 01 2b 0e ff |.&.0..+..p...+..|
+00000050 4c 10 9a 29 75 cb 14 bb 85 80 98 35 fb 82 e8 b5 |L..)u......5....|
+00000060 80 6f 9d e6 3b b6 14 36 bb 61 8e 18 f2 6b da 09 |.o..;..6.a...k..|
+00000070 71 9c 6d 1e c3 60 a9 c5 8b 4e 77 41 db ec 12 49 |q.m..`...NwA...I|
+00000080 a4 c2 e2 10 ce 7f 18 05 b9 74 aa 14 03 01 00 01 |.........t......|
+00000090 01 16 03 01 00 24 3d 90 d0 f6 6f 15 94 05 a0 fb |.....$=...o.....|
+000000a0 43 83 55 b5 b1 ef e5 fd fc 00 d3 d5 25 b4 7c 9f |C.U.........%.|.|
+000000b0 e0 82 99 2a 6d 5a 26 7c 05 21 |...*mZ&|.!|
>>> Flow 4 (server to client)
-00000000 14 03 01 00 01 01 16 03 01 00 24 ae 00 c8 14 67 |..........$....g|
-00000010 4b b5 21 96 98 91 d6 27 40 9b 5e a5 86 53 56 f3 |K.!....'@.^..SV.|
-00000020 f6 dc 7e b2 49 78 4b 4d 57 7c 62 a5 f2 16 8f 17 |..~.IxKMW|b.....|
-00000030 03 01 00 21 34 e3 48 58 1c 67 fb 3a 46 28 5d a1 |...!4.HX.g.:F(].|
-00000040 19 66 58 b1 bb fb e7 17 71 07 3f 0a d0 7c c9 24 |.fX.....q.?..|.$|
-00000050 c7 ef 41 af 62 15 03 01 00 16 dd dc 16 dc 16 cc |..A.b...........|
-00000060 0d f3 2c 29 00 c0 4f 01 68 05 92 a0 f7 ad e2 63 |..,)..O.h......c|
+00000000 14 03 01 00 01 01 16 03 01 00 24 28 d0 1f ec 1d |..........$(....|
+00000010 9e 1d e3 80 6b 6d 3e 8b c5 f7 9c 14 a9 0b c3 53 |....km>........S|
+00000020 fd 48 d0 b3 eb d1 49 97 97 71 e9 36 b9 e6 3a 17 |.H....I..q.6..:.|
+00000030 03 01 00 21 c3 b6 2e 02 05 86 0f 57 04 dd 88 33 |...!.......W...3|
+00000040 0a ed 1d d5 a8 0f 55 54 c5 8c 87 5b 11 b7 80 7f |......UT...[....|
+00000050 30 79 e0 64 ee 15 03 01 00 16 b1 50 de 3d 18 05 |0y.d.......P.=..|
+00000060 2f db 37 4c db 62 f1 c8 d5 19 ca c2 fb a5 8a 37 |/.7L.b.........7|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 d4 01 00 00 d0 03 02 74 2d da 6d 98 |...........t-.m.|
-00000010 ad 3e a5 ec 90 ea d1 5b f0 e0 a7 45 33 d9 5e 8d |.>.....[...E3.^.|
-00000020 0f 1d 01 16 6d 00 31 65 ed 50 88 00 00 5e c0 14 |....m.1e.P...^..|
-00000030 c0 0a 00 39 00 38 00 88 00 87 c0 0f c0 05 00 35 |...9.8.........5|
-00000040 00 84 c0 13 c0 09 00 33 00 32 00 9a 00 99 00 45 |.......3.2.....E|
-00000050 00 44 c0 0e c0 04 00 2f 00 96 00 41 00 07 c0 11 |.D...../...A....|
-00000060 c0 07 c0 0c c0 02 00 05 00 04 c0 12 c0 08 00 16 |................|
-00000070 00 13 c0 0d c0 03 00 0a 00 15 00 12 00 09 00 14 |................|
-00000080 00 11 00 08 00 06 00 03 00 ff 56 00 01 00 00 49 |..........V....I|
-00000090 00 0b 00 04 03 00 01 02 00 0a 00 34 00 32 00 0e |...........4.2..|
-000000a0 00 0d 00 19 00 0b 00 0c 00 18 00 09 00 0a 00 16 |................|
-000000b0 00 17 00 08 00 06 00 07 00 14 00 15 00 04 00 05 |................|
-000000c0 00 12 00 13 00 01 00 02 00 03 00 0f 00 10 00 11 |................|
-000000d0 00 23 00 00 00 0f 00 01 01 |.#.......|
+00000000 16 03 01 00 cf 01 00 00 cb 03 02 ee 33 c1 3f a6 |............3.?.|
+00000010 62 ba a6 4f c7 32 25 0f 15 66 f7 35 a2 cf c0 cd |b..O.2%..f.5....|
+00000020 48 93 77 1c 04 1f fb 65 41 37 ca 00 00 70 c0 14 |H.w....eA7...p..|
+00000030 c0 0a 00 39 00 38 00 37 00 36 00 88 00 87 00 86 |...9.8.7.6......|
+00000040 00 85 c0 0f c0 05 00 35 00 84 c0 13 c0 09 00 33 |.......5.......3|
+00000050 00 32 00 31 00 30 00 9a 00 99 00 98 00 97 00 45 |.2.1.0.........E|
+00000060 00 44 00 43 00 42 c0 0e c0 04 00 2f 00 96 00 41 |.D.C.B...../...A|
+00000070 00 07 c0 11 c0 07 c0 0c c0 02 00 05 00 04 c0 12 |................|
+00000080 c0 08 00 16 00 13 00 10 00 0d c0 0d c0 03 00 0a |................|
+00000090 00 15 00 12 00 0f 00 0c 00 09 00 ff 56 00 02 01 |............V...|
+000000a0 00 00 31 00 0b 00 04 03 00 01 02 00 0a 00 1c 00 |..1.............|
+000000b0 1a 00 17 00 19 00 1c 00 1b 00 18 00 1a 00 16 00 |................|
+000000c0 0e 00 0d 00 0b 00 0c 00 09 00 0a 00 23 00 00 00 |............#...|
+000000d0 0f 00 01 01 |....|
>>> Flow 2 (server to client)
00000000 15 03 02 00 02 02 56 |......V|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 36 01 00 00 32 03 02 ff e1 a1 04 0b |....6...2.......|
-00000010 c2 dc fb 7d 07 61 44 9b 00 67 fe 38 73 f5 fc 4e |...}.aD..g.8s..N|
-00000020 35 94 0a d5 c1 d0 e7 54 dc 44 1f 00 00 04 00 05 |5......T.D......|
-00000030 00 ff 01 00 00 05 00 0f 00 01 01 |...........|
+00000000 16 03 01 00 37 01 00 00 33 03 02 95 4a cf f5 14 |....7...3...J...|
+00000010 56 9b d6 be 0c ba 0d b2 ad 65 47 d2 c6 ce 84 c9 |V........eG.....|
+00000020 f4 80 2a 4e 75 df ff 48 cf 48 9b 00 00 04 00 05 |..*Nu..H.H......|
+00000030 00 ff 02 01 00 00 05 00 0f 00 01 01 |............|
>>> Flow 2 (server to client)
00000000 16 03 02 00 31 02 00 00 2d 03 02 00 00 00 00 00 |....1...-.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000002a0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 02 00 |..A4......9.....|
000002b0 04 0e 00 00 00 |.....|
>>> Flow 3 (client to server)
-00000000 16 03 02 00 86 10 00 00 82 00 80 4c e0 4d 6a 19 |...........L.Mj.|
-00000010 a2 72 2a 3d 41 14 a7 b3 0a 25 11 bf c9 9f cf 8c |.r*=A....%......|
-00000020 3c 0b 01 49 aa f1 59 4b 60 ac e5 72 9b ec 20 41 |<..I..YK`..r.. A|
-00000030 2f 7e ef bf e0 fe 13 c0 1d fd 51 c5 08 c6 9a 9e |/~........Q.....|
-00000040 74 88 c7 e3 36 99 73 fd 00 2d a2 6a bd 25 f2 d7 |t...6.s..-.j.%..|
-00000050 24 fd fd ab 0c e0 18 38 ba 7b f0 c9 c0 58 a6 d0 |$......8.{...X..|
-00000060 4e e2 59 70 aa f4 52 34 12 a0 ec a4 53 1e 8b ee |N.Yp..R4....S...|
-00000070 3e bf a4 87 da 02 4c 95 bd 10 af e8 88 c9 ce 87 |>.....L.........|
-00000080 3c 9e 91 70 91 a0 85 18 84 e4 e0 14 03 02 00 01 |<..p............|
-00000090 01 16 03 02 00 24 c5 c0 27 71 49 ad ed 37 e6 5d |.....$..'qI..7.]|
-000000a0 1b 78 3e 74 15 b7 61 e5 f3 af 1e d0 a2 85 b3 13 |.x>t..a.........|
-000000b0 6e 5e 9a c7 3d 47 32 4d 1b 8d |n^..=G2M..|
+00000000 16 03 02 00 86 10 00 00 82 00 80 19 c3 d4 f2 e4 |................|
+00000010 bf 4a 52 90 a4 65 f6 e7 29 1a 7f ef 0e a4 1e b4 |.JR..e..).......|
+00000020 c2 df b2 83 43 4a 1a f4 b6 cd 51 a5 24 62 3f e1 |....CJ....Q.$b?.|
+00000030 fb 5f 7e b1 10 08 3b 8a ab eb 3a a3 72 ba 31 1c |._~...;...:.r.1.|
+00000040 23 bd ef 2e 3d 13 dc 61 88 a6 af ca 80 82 5d e4 |#...=..a......].|
+00000050 d6 a2 d3 13 80 87 c6 ad a5 13 4e f1 b6 a0 5d fa |..........N...].|
+00000060 ed a7 0d 37 58 f1 54 38 18 f5 be db 90 9f 07 4a |...7X.T8.......J|
+00000070 67 25 c9 8d 9d 5e 07 62 ca db 72 74 b5 bd a0 ed |g%...^.b..rt....|
+00000080 d0 95 9f 3e cd 37 b8 96 df df 3b 14 03 02 00 01 |...>.7....;.....|
+00000090 01 16 03 02 00 24 80 53 7a 8f 23 06 a7 6b e6 be |.....$.Sz.#..k..|
+000000a0 61 c2 1a c8 35 30 6b e2 2f 82 f3 46 ff e3 1d bd |a...50k./..F....|
+000000b0 68 e9 a2 78 49 33 05 ca d9 41 |h..xI3...A|
>>> Flow 4 (server to client)
-00000000 14 03 02 00 01 01 16 03 02 00 24 31 22 76 4d 43 |..........$1"vMC|
-00000010 7a 8a 58 2c 7d 1c 41 39 bf 08 7e 82 17 55 52 b3 |z.X,}.A9..~..UR.|
-00000020 81 bd 7a f8 3c bf 9c 2b f0 9b 3f 65 f5 42 15 17 |..z.<..+..?e.B..|
-00000030 03 02 00 21 b1 cc e5 56 16 70 58 0b 91 3c 8c 46 |...!...V.pX..<.F|
-00000040 0e 3b b6 fe 32 5d 2e b0 8c 6a 1c a0 82 c9 43 81 |.;..2]...j....C.|
-00000050 cf 07 25 47 c9 15 03 02 00 16 53 91 04 70 ba 03 |..%G......S..p..|
-00000060 53 69 57 86 3b 2f 8b 97 37 7c b8 85 46 b6 72 42 |SiW.;/..7|..F.rB|
+00000000 14 03 02 00 01 01 16 03 02 00 24 8f 06 3e 7b 8c |..........$..>{.|
+00000010 fb f2 3d 9e 5c a9 46 56 79 2a 3a ba ad 25 30 57 |..=.\.FVy*:..%0W|
+00000020 f9 f1 16 70 51 5d 73 7e 47 74 8d c0 84 b0 31 17 |...pQ]s~Gt....1.|
+00000030 03 02 00 21 76 09 88 df 7e f7 2f c9 3d 86 b9 30 |...!v...~./.=..0|
+00000040 b0 5c ac ea db c6 d0 d5 69 55 91 7b a1 72 0b 4d |.\......iU.{.r.M|
+00000050 7d ae 6f aa 50 15 03 02 00 16 8c 31 73 86 1a c7 |}.o.P......1s...|
+00000060 ef 08 52 8a 7d 30 b8 00 3b 62 4d 21 7b 81 2c 76 |..R.}0..;bM!{.,v|
>>> Flow 1 (client to server)
-00000000 16 03 01 01 4c 01 00 01 48 03 03 44 3b 24 ee 2f |....L...H..D;$./|
-00000010 63 3d ca bd 3e c5 bf a2 24 f1 59 c3 54 dc f0 43 |c=..>...$.Y.T..C|
-00000020 15 c4 51 f2 29 ea 1b ce 2c fe af 00 00 b6 c0 30 |..Q.)...,......0|
+00000000 16 03 01 01 4d 01 00 01 49 03 03 ac 76 61 d8 20 |....M...I...va. |
+00000010 b3 c3 1d c2 3d c2 a4 b9 e2 46 a2 a1 0a 5e 08 56 |....=....F...^.V|
+00000020 4a aa 59 43 42 d6 21 9c 46 0c 21 00 00 b6 c0 30 |J.YCB.!.F.!....0|
00000030 c0 2c c0 28 c0 24 c0 14 c0 0a 00 a5 00 a3 00 a1 |.,.(.$..........|
00000040 00 9f 00 6b 00 6a 00 69 00 68 00 39 00 38 00 37 |...k.j.i.h.9.8.7|
00000050 00 36 00 88 00 87 00 86 00 85 c0 32 c0 2e c0 2a |.6.........2...*|
000000b0 00 3c 00 2f 00 96 00 41 00 07 c0 11 c0 07 c0 0c |.<./...A........|
000000c0 c0 02 00 05 00 04 c0 12 c0 08 00 16 00 13 00 10 |................|
000000d0 00 0d c0 0d c0 03 00 0a 00 15 00 12 00 0f 00 0c |................|
-000000e0 00 09 00 ff 01 00 00 69 00 0b 00 04 03 00 01 02 |.......i........|
-000000f0 00 0a 00 1c 00 1a 00 17 00 19 00 1c 00 1b 00 18 |................|
-00000100 00 1a 00 16 00 0e 00 0d 00 0b 00 0c 00 09 00 0a |................|
-00000110 00 23 00 00 00 0d 00 20 00 1e 06 01 06 02 06 03 |.#..... ........|
-00000120 05 01 05 02 05 03 04 01 04 02 04 03 03 01 03 02 |................|
-00000130 03 03 02 01 02 02 02 03 00 0f 00 01 01 00 10 00 |................|
-00000140 10 00 0e 06 70 72 6f 74 6f 32 06 70 72 6f 74 6f |....proto2.proto|
-00000150 31 |1|
+000000e0 00 09 00 ff 02 01 00 00 69 00 0b 00 04 03 00 01 |........i.......|
+000000f0 02 00 0a 00 1c 00 1a 00 17 00 19 00 1c 00 1b 00 |................|
+00000100 18 00 1a 00 16 00 0e 00 0d 00 0b 00 0c 00 09 00 |................|
+00000110 0a 00 23 00 00 00 0d 00 20 00 1e 06 01 06 02 06 |..#..... .......|
+00000120 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 03 |................|
+00000130 02 03 03 02 01 02 02 02 03 00 0f 00 01 01 00 10 |................|
+00000140 00 10 00 0e 06 70 72 6f 74 6f 32 06 70 72 6f 74 |.....proto2.prot|
+00000150 6f 31 |o1|
>>> Flow 2 (server to client)
00000000 16 03 03 00 42 02 00 00 3e 03 03 00 00 00 00 00 |....B...>.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000002d0 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.|
000002e0 a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e |.$ >.V...(^.+-O.|
000002f0 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I|
-00000300 a6 b5 68 1a 41 03 56 6b dc 5a 89 05 01 00 80 40 |..h.A.Vk.Z.....@|
-00000310 93 b2 1f 79 3d 56 c0 ae 94 87 c0 a7 28 ef 1d 15 |...y=V......(...|
-00000320 be 4b fb 66 e0 60 2c a3 57 ee 56 7d d6 89 b8 8e |.K.f.`,.W.V}....|
-00000330 8f 0f 3f 1b c6 9f a4 1d 34 60 b6 9c e9 9b a9 27 |..?.....4`.....'|
-00000340 d0 45 7b 04 71 2d db 9c 67 1b d5 d4 fe 19 69 59 |.E{.q-..g.....iY|
-00000350 71 8a 35 75 33 a8 c9 f2 4d c4 8f 40 17 a7 25 53 |q.5u3...M..@..%S|
-00000360 57 c5 cd ee df a9 3b a3 61 ab e2 a2 ca de 5c 08 |W.....;.a.....\.|
-00000370 3d 5b a2 ef cd c8 bc 16 1f 1d 0f 83 9e b7 20 f5 |=[............ .|
-00000380 89 3f 09 ba 2e da 12 34 81 e5 2f 8d 3c 90 89 16 |.?.....4../.<...|
+00000300 a6 b5 68 1a 41 03 56 6b dc 5a 89 05 01 00 80 aa |..h.A.Vk.Z......|
+00000310 8c a6 e1 51 65 fc 99 37 cf 63 d8 fd 04 52 d5 50 |...Qe..7.c...R.P|
+00000320 1f 0a f5 90 58 48 19 8d d8 0b 64 23 e4 24 56 b4 |....XH....d#.$V.|
+00000330 e5 87 0f 88 a1 7a 29 fa 88 79 99 75 6d 53 a9 50 |.....z)..y.umS.P|
+00000340 a4 9c b9 47 c2 51 87 10 b9 a5 e3 6f a9 38 b8 83 |...G.Q.....o.8..|
+00000350 0d 39 b5 28 27 5f ec 9d a3 2d 1c 53 6b da 93 0d |.9.('_...-.Sk...|
+00000360 cc cf 0c 27 7e d2 f0 05 d5 c0 04 dc 6d d4 2e 03 |...'~.......m...|
+00000370 a7 16 98 58 e4 8d fd 14 6b bb 0c 09 b0 16 35 9e |...X....k.....5.|
+00000380 78 3a 29 21 b5 2f 13 37 94 ae f7 fe 54 89 c0 16 |x:)!./.7....T...|
00000390 03 03 00 04 0e 00 00 00 |........|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 46 10 00 00 42 41 04 8b a2 de a6 1e |....F...BA......|
-00000010 d9 22 3c 03 4a be 49 2f 40 e3 1e e0 b4 76 7f 78 |."<.J.I/@....v.x|
-00000020 96 22 8d 8d c9 45 3b d8 7a ce e3 16 3d 37 ec 80 |."...E;.z...=7..|
-00000030 aa 3f d5 19 de c1 2c 7b 7f eb 3c fc 5d c3 52 3b |.?....,{..<.].R;|
-00000040 d4 22 25 1c c7 1f 39 c5 23 bd 73 14 03 03 00 01 |."%...9.#.s.....|
-00000050 01 16 03 03 00 28 c8 53 0a ad c2 f6 7e 18 08 a3 |.....(.S....~...|
-00000060 29 27 20 1c 6c 1d 6c d8 8f 05 31 de e6 ab 7f 22 |)' .l.l...1...."|
-00000070 93 6a fb ef b0 f8 43 a9 d3 4f 9d 04 b5 9a |.j....C..O....|
+00000000 16 03 03 00 46 10 00 00 42 41 04 35 ca 56 91 15 |....F...BA.5.V..|
+00000010 4f dd af 97 f2 2d fb df 54 2b 80 98 18 bb 33 54 |O....-..T+....3T|
+00000020 3f 7e 66 21 d3 81 38 f9 a4 b5 b9 a6 46 9a 52 8b |?~f!..8.....F.R.|
+00000030 98 f7 81 1f 77 81 78 38 01 c5 3b fb 7a b7 53 e7 |....w.x8..;.z.S.|
+00000040 ae c3 4c 2e 73 f4 8e 3a 36 0d 43 14 03 03 00 01 |..L.s..:6.C.....|
+00000050 01 16 03 03 00 28 38 26 8e 03 ad 81 9b a0 41 d9 |.....(8&......A.|
+00000060 c0 11 3f 36 dc 6b ab 6c 29 dc df 02 a3 fe b0 0f |..?6.k.l).......|
+00000070 2e b1 c6 44 39 42 d5 ef 29 30 d8 e0 f1 f9 |...D9B..)0....|
>>> Flow 4 (server to client)
00000000 16 03 03 00 82 04 00 00 7e 00 00 00 00 00 78 50 |........~.....xP|
00000010 46 ad c1 db a8 38 86 7b 2b bb fd d0 c3 42 3e 00 |F....8.{+....B>.|
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 94 |................|
-00000030 6f ec 80 83 61 8e d9 64 ac a2 ee 3b 69 31 79 e1 |o...a..d...;i1y.|
-00000040 53 0a 92 1d aa 23 09 c2 49 02 2d 0d 1d c1 63 d6 |S....#..I.-...c.|
-00000050 21 56 c7 24 02 28 d5 f1 11 b0 e7 1b 4a 7c 55 af |!V.$.(......J|U.|
-00000060 1b c8 32 4c 5b 33 94 b0 ed b0 2f 52 c4 52 81 ee |..2L[3..../R.R..|
-00000070 60 6f 66 fb f5 db dd f9 1e 30 11 d4 ca 75 0e 2b |`of......0...u.+|
-00000080 ff d0 e5 f2 68 a4 e7 14 03 03 00 01 01 16 03 03 |....h...........|
-00000090 00 28 00 00 00 00 00 00 00 00 67 3b 4a ba f3 27 |.(........g;J..'|
-000000a0 c8 45 94 68 36 5a 40 e1 dc 67 9b d4 45 58 e9 24 |.E.h6Z@..g..EX.$|
-000000b0 31 85 3a f8 5d cb 84 8e 64 05 17 03 03 00 25 00 |1.:.]...d.....%.|
-000000c0 00 00 00 00 00 00 01 35 d9 ba 0a e2 3e fd a2 80 |.......5....>...|
-000000d0 10 0e 38 7b ad 85 85 48 6a 2a ab 2a 46 c3 59 96 |..8{...Hj*.*F.Y.|
-000000e0 fd 75 11 5d 15 03 03 00 1a 00 00 00 00 00 00 00 |.u.]............|
-000000f0 02 0b 4d a5 89 4d 86 47 14 60 27 f8 09 bc c9 4d |..M..M.G.`'....M|
-00000100 00 31 cb |.1.|
+00000030 6f ec 80 83 61 fb fb 41 b1 31 e9 71 75 43 c3 74 |o...a..A.1.quC.t|
+00000040 a1 a0 ac fb 97 b7 69 ee a6 2f e3 a3 dd 9f de e4 |......i../......|
+00000050 80 9d d7 69 1a 2c 0b b4 02 bd ef e2 6a c1 ca 30 |...i.,......j..0|
+00000060 8b 9d 60 f9 fe 33 94 53 3a 14 a3 1a aa 5a ba ff |..`..3.S:....Z..|
+00000070 1e 94 fd 4f e7 90 0b 09 ee 80 f3 d6 d5 c0 48 83 |...O..........H.|
+00000080 98 20 d7 a4 07 99 e0 14 03 03 00 01 01 16 03 03 |. ..............|
+00000090 00 28 00 00 00 00 00 00 00 00 0d 66 de 91 4a 97 |.(.........f..J.|
+000000a0 21 c6 d2 d7 df 68 9b 7e f6 43 73 02 66 b3 5a d6 |!....h.~.Cs.f.Z.|
+000000b0 92 48 c2 c1 11 fc cd 1e 2e 4b 17 03 03 00 25 00 |.H.......K....%.|
+000000c0 00 00 00 00 00 00 01 72 0c 48 75 fa b2 8b 23 09 |.......r.Hu...#.|
+000000d0 be 76 36 a4 bc e0 62 ef bd 79 8e de 6b 39 4b 55 |.v6...b..y..k9KU|
+000000e0 8d 3c ca 14 15 03 03 00 1a 00 00 00 00 00 00 00 |.<..............|
+000000f0 02 74 5f 79 31 41 4f f5 4d 02 96 bc c3 9a 85 92 |.t_y1AO.M.......|
+00000100 44 e1 76 |D.v|
>>> Flow 1 (client to server)
-00000000 16 03 01 01 4c 01 00 01 48 03 03 1d 1a f7 e5 ad |....L...H.......|
-00000010 a4 5c fd 61 b4 c2 25 33 c7 b9 fc fb 2b a5 4b fe |.\.a..%3....+.K.|
-00000020 16 84 55 4b 9f 68 73 61 b8 92 4d 00 00 b6 c0 30 |..UK.hsa..M....0|
+00000000 16 03 01 01 4d 01 00 01 49 03 03 73 f2 f2 44 4f |....M...I..s..DO|
+00000010 87 05 77 e2 e7 07 ca c7 d4 36 37 4e d9 17 ba ff |..w......67N....|
+00000020 b0 e1 47 65 f8 7f fd 7a b4 85 39 00 00 b6 c0 30 |..Ge...z..9....0|
00000030 c0 2c c0 28 c0 24 c0 14 c0 0a 00 a5 00 a3 00 a1 |.,.(.$..........|
00000040 00 9f 00 6b 00 6a 00 69 00 68 00 39 00 38 00 37 |...k.j.i.h.9.8.7|
00000050 00 36 00 88 00 87 00 86 00 85 c0 32 c0 2e c0 2a |.6.........2...*|
000000b0 00 3c 00 2f 00 96 00 41 00 07 c0 11 c0 07 c0 0c |.<./...A........|
000000c0 c0 02 00 05 00 04 c0 12 c0 08 00 16 00 13 00 10 |................|
000000d0 00 0d c0 0d c0 03 00 0a 00 15 00 12 00 0f 00 0c |................|
-000000e0 00 09 00 ff 01 00 00 69 00 0b 00 04 03 00 01 02 |.......i........|
-000000f0 00 0a 00 1c 00 1a 00 17 00 19 00 1c 00 1b 00 18 |................|
-00000100 00 1a 00 16 00 0e 00 0d 00 0b 00 0c 00 09 00 0a |................|
-00000110 00 23 00 00 00 0d 00 20 00 1e 06 01 06 02 06 03 |.#..... ........|
-00000120 05 01 05 02 05 03 04 01 04 02 04 03 03 01 03 02 |................|
-00000130 03 03 02 01 02 02 02 03 00 0f 00 01 01 00 10 00 |................|
-00000140 10 00 0e 06 70 72 6f 74 6f 32 06 70 72 6f 74 6f |....proto2.proto|
-00000150 31 |1|
+000000e0 00 09 00 ff 02 01 00 00 69 00 0b 00 04 03 00 01 |........i.......|
+000000f0 02 00 0a 00 1c 00 1a 00 17 00 19 00 1c 00 1b 00 |................|
+00000100 18 00 1a 00 16 00 0e 00 0d 00 0b 00 0c 00 09 00 |................|
+00000110 0a 00 23 00 00 00 0d 00 20 00 1e 06 01 06 02 06 |..#..... .......|
+00000120 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 03 |................|
+00000130 02 03 03 02 01 02 02 02 03 00 0f 00 01 01 00 10 |................|
+00000140 00 10 00 0e 06 70 72 6f 74 6f 32 06 70 72 6f 74 |.....proto2.prot|
+00000150 6f 31 |o1|
>>> Flow 2 (server to client)
00000000 16 03 03 00 35 02 00 00 31 03 03 00 00 00 00 00 |....5...1.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000002d0 09 67 fd a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b |.g..$ >.V...(^.+|
000002e0 2d 4f 9e f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 |-O....lK[.V.2B.X|
000002f0 b6 d7 49 a6 b5 68 1a 41 03 56 6b dc 5a 89 05 01 |..I..h.A.Vk.Z...|
-00000300 00 80 36 d2 96 c8 27 66 d8 bd 6c 28 29 30 b3 be |..6...'f..l()0..|
-00000310 0a bb b2 fe 9d c3 59 47 34 cf de fe f4 ab 5d 79 |......YG4.....]y|
-00000320 24 a9 9d c9 b5 e9 50 6a 3b 96 e3 29 cb d7 37 06 |$.....Pj;..)..7.|
-00000330 19 08 88 15 29 c2 55 03 62 75 1d 35 c2 8e 25 a2 |....).U.bu.5..%.|
-00000340 86 20 bf 18 46 15 81 f2 74 4b bb dd 3d e3 a5 f6 |. ..F...tK..=...|
-00000350 28 18 41 89 c8 39 13 f9 c0 88 fd cc f0 6e 9e 3d |(.A..9.......n.=|
-00000360 cb 29 ad 26 5b d1 e6 11 5c 64 7d b6 df d7 39 87 |.).&[...\d}...9.|
-00000370 24 df 9f 62 17 ef f2 b3 3a b3 88 a4 f0 91 ea f2 |$..b....:.......|
-00000380 5d c9 16 03 03 00 04 0e 00 00 00 |]..........|
+00000300 00 80 97 89 a3 7f 30 d1 7b 70 26 3d a4 d5 66 2e |......0.{p&=..f.|
+00000310 cd fc 02 f5 37 a5 cd 09 69 7a c6 2f b2 62 e8 a6 |....7...iz./.b..|
+00000320 88 e2 3a c4 0a 8c 77 ad d3 c9 29 49 84 81 9c cd |..:...w...)I....|
+00000330 33 44 59 2d b5 2e e7 ce 12 c5 3b 46 13 6d 4a c8 |3DY-......;F.mJ.|
+00000340 6d f6 1f e7 f1 99 13 01 ca 43 79 fa b5 78 c7 1a |m........Cy..x..|
+00000350 7d 8f 85 dd 3b ca 56 22 c3 d0 41 11 1b 13 8c 07 |}...;.V"..A.....|
+00000360 02 75 87 7a ea 68 43 30 0b 2a 38 52 b2 8f cc ea |.u.z.hC0.*8R....|
+00000370 a3 a3 cb 71 fb 97 cd 3e 74 d0 5b 9b bd 17 13 f0 |...q...>t.[.....|
+00000380 d9 fe 16 03 03 00 04 0e 00 00 00 |...........|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 46 10 00 00 42 41 04 b0 22 15 73 fc |....F...BA..".s.|
-00000010 1c fd 24 4a 36 69 8a be ac bd 72 30 bb 6b e1 9b |..$J6i....r0.k..|
-00000020 42 e8 56 7a 86 b1 8d cb 9c 3e 2d 63 13 57 a8 13 |B.Vz.....>-c.W..|
-00000030 71 3b a2 01 86 af f8 76 40 0b 44 4f 0a 0f 5a da |q;.....v@.DO..Z.|
-00000040 31 36 3b 13 c0 10 6c 96 64 a7 24 14 03 03 00 01 |16;...l.d.$.....|
-00000050 01 16 03 03 00 28 10 2d 45 93 5c 37 34 d9 2a a0 |.....(.-E.\74.*.|
-00000060 b6 37 13 bc a6 1f 0c ce 2e 55 c1 ad 36 b8 60 72 |.7.......U..6.`r|
-00000070 81 cb 1a 7a 5b 26 49 ad 77 ef 62 e8 fc 00 |...z[&I.w.b...|
+00000000 16 03 03 00 46 10 00 00 42 41 04 ba 5b 0f e7 ec |....F...BA..[...|
+00000010 8e c8 ad 51 8c c0 50 f1 8a 2a 68 32 74 d0 95 03 |...Q..P..*h2t...|
+00000020 0c 61 f1 1c 89 ed 95 5d 9a 4a 14 ee cc 14 9a 73 |.a.....].J.....s|
+00000030 f6 db 46 dd b7 47 8a 82 3d 7a b8 9f 45 d1 a2 3f |..F..G..=z..E..?|
+00000040 f4 34 9b b6 6d 7d 41 87 c9 d5 cd 14 03 03 00 01 |.4..m}A.........|
+00000050 01 16 03 03 00 28 1e ae f6 90 a9 91 eb 4b ca 23 |.....(.......K.#|
+00000060 6e bf 9e 67 5b 38 ab f6 d6 ee 12 aa b9 b6 d0 6e |n..g[8.........n|
+00000070 a7 dd 45 91 34 45 78 a0 04 9e d8 85 48 48 |..E.4Ex.....HH|
>>> Flow 4 (server to client)
00000000 16 03 03 00 82 04 00 00 7e 00 00 00 00 00 78 50 |........~.....xP|
00000010 46 ad c1 db a8 38 86 7b 2b bb fd d0 c3 42 3e 00 |F....8.{+....B>.|
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 94 |................|
-00000030 6f ec 80 83 61 05 33 d2 9d 95 89 7b 28 54 50 50 |o...a.3....{(TPP|
-00000040 b3 3c 99 5c 82 ab cf 88 24 e8 48 81 db 4a 22 79 |.<.\....$.H..J"y|
-00000050 0b fa 33 50 ed 82 a1 7c 33 0e f2 ff 6d a7 d6 88 |..3P...|3...m...|
-00000060 29 65 74 e3 27 33 94 97 66 0c 86 ce fc ca 0e 2a |)et.'3..f......*|
-00000070 96 fa fe 19 a3 01 64 d9 4d 8e 58 95 5b 74 a6 aa |......d.M.X.[t..|
-00000080 f4 9f c1 34 97 2d e5 14 03 03 00 01 01 16 03 03 |...4.-..........|
-00000090 00 28 00 00 00 00 00 00 00 00 4d 56 6d d5 6f cc |.(........MVm.o.|
-000000a0 3d d4 85 32 3c 07 ea 3c 52 61 88 8e dd d5 d3 d0 |=..2<..<Ra......|
-000000b0 f9 4e 1b b1 c1 d1 67 cb 1a e8 17 03 03 00 25 00 |.N....g.......%.|
-000000c0 00 00 00 00 00 00 01 c3 43 ab 0c ab 59 30 e9 d4 |........C...Y0..|
-000000d0 eb 65 c2 7f 9a 5a 1e 09 06 a4 9d 69 bb 3f 0b 06 |.e...Z.....i.?..|
-000000e0 87 b8 09 39 15 03 03 00 1a 00 00 00 00 00 00 00 |...9............|
-000000f0 02 c2 6f f4 88 f0 7a 59 a6 49 3e 44 a3 7b 6e 36 |..o...zY.I>D.{n6|
-00000100 ae 66 87 |.f.|
+00000030 6f ec 80 83 61 4f 7f 09 64 32 96 26 b5 71 46 6a |o...aO..d2.&.qFj|
+00000040 29 7d fd 0b bb 49 13 0e c8 c5 de 06 ed 47 e8 cb |)}...I.......G..|
+00000050 d8 9f 18 82 69 af ab 24 d2 78 90 ba 9a c8 24 95 |....i..$.x....$.|
+00000060 46 53 19 2e e8 33 94 3c 22 73 26 d6 86 4e 01 a4 |FS...3.<"s&..N..|
+00000070 34 ea a8 bf f2 ca b5 0d fc f6 08 b9 31 b3 42 e7 |4...........1.B.|
+00000080 c1 92 96 f9 bf 9a 00 14 03 03 00 01 01 16 03 03 |................|
+00000090 00 28 00 00 00 00 00 00 00 00 bd 51 1d 0e bd 51 |.(.........Q...Q|
+000000a0 a3 b1 03 f2 df f4 ba 9b 1e a5 a8 22 e7 ce 7c 19 |..........."..|.|
+000000b0 1a bf 37 3d 42 f4 4d 6f 63 75 17 03 03 00 25 00 |..7=B.Mocu....%.|
+000000c0 00 00 00 00 00 00 01 52 8a d2 34 52 70 f1 cf 87 |.......R..4Rp...|
+000000d0 54 4e fd e6 11 a7 76 1a f4 7b 70 e8 34 ef 01 c8 |TN....v..{p.4...|
+000000e0 6c 4a f8 6d 15 03 03 00 1a 00 00 00 00 00 00 00 |lJ.m............|
+000000f0 02 8a 4c f9 7c d1 61 a6 cd 2a e6 3a 5b b0 cb aa |..L.|.a..*.:[...|
+00000100 91 2e 8b |...|
>>> Flow 1 (client to server)
-00000000 16 03 01 01 34 01 00 01 30 03 03 78 08 b2 d4 18 |....4...0..x....|
-00000010 8e b1 6b a2 d2 e0 c6 41 02 c5 93 f1 b9 60 94 e8 |..k....A.....`..|
-00000020 f2 64 6c 97 50 2d 24 a3 cd c0 36 00 00 b6 c0 30 |.dl.P-$...6....0|
+00000000 16 03 01 01 35 01 00 01 31 03 03 00 02 67 8e 1d |....5...1....g..|
+00000010 3b d2 26 20 63 c5 6a b6 68 25 02 72 ce 86 6b c7 |;.& c.j.h%.r..k.|
+00000020 97 1a 9f 4d be 02 98 ac 24 5e 82 00 00 b6 c0 30 |...M....$^.....0|
00000030 c0 2c c0 28 c0 24 c0 14 c0 0a 00 a5 00 a3 00 a1 |.,.(.$..........|
00000040 00 9f 00 6b 00 6a 00 69 00 68 00 39 00 38 00 37 |...k.j.i.h.9.8.7|
00000050 00 36 00 88 00 87 00 86 00 85 c0 32 c0 2e c0 2a |.6.........2...*|
000000b0 00 3c 00 2f 00 96 00 41 00 07 c0 11 c0 07 c0 0c |.<./...A........|
000000c0 c0 02 00 05 00 04 c0 12 c0 08 00 16 00 13 00 10 |................|
000000d0 00 0d c0 0d c0 03 00 0a 00 15 00 12 00 0f 00 0c |................|
-000000e0 00 09 00 ff 01 00 00 51 00 0b 00 04 03 00 01 02 |.......Q........|
-000000f0 00 0a 00 1c 00 1a 00 17 00 19 00 1c 00 1b 00 18 |................|
-00000100 00 1a 00 16 00 0e 00 0d 00 0b 00 0c 00 09 00 0a |................|
-00000110 00 0d 00 20 00 1e 06 01 06 02 06 03 05 01 05 02 |... ............|
-00000120 05 03 04 01 04 02 04 03 03 01 03 02 03 03 02 01 |................|
-00000130 02 02 02 03 00 0f 00 01 01 |.........|
+000000e0 00 09 00 ff 02 01 00 00 51 00 0b 00 04 03 00 01 |........Q.......|
+000000f0 02 00 0a 00 1c 00 1a 00 17 00 19 00 1c 00 1b 00 |................|
+00000100 18 00 1a 00 16 00 0e 00 0d 00 0b 00 0c 00 09 00 |................|
+00000110 0a 00 0d 00 20 00 1e 06 01 06 02 06 03 05 01 05 |.... ...........|
+00000120 02 05 03 04 01 04 02 04 03 03 01 03 02 03 03 02 |................|
+00000130 01 02 02 02 03 00 0f 00 01 01 |..........|
>>> Flow 2 (server to client)
00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000270 b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e f1 07 9f 6c |.V...(^.+-O....l|
00000280 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 b5 68 1a |K[.V.2B.X..I..h.|
00000290 41 03 56 6b dc 5a 89 05 03 00 8b 30 81 88 02 42 |A.Vk.Z.....0...B|
-000002a0 00 91 b4 4a f2 9d 13 a1 6d 3b ee 46 2f 3b 97 50 |...J....m;.F/;.P|
-000002b0 b9 3e 28 7a 51 7a 8b 3b a6 16 03 d6 1f 92 0a ec |.>(zQz.;........|
-000002c0 5b 9b b5 48 98 ce d8 22 bd 7d eb cb 14 7b 14 73 |[..H...".}...{.s|
-000002d0 2d 5f 01 8c dc 5a 63 34 92 4e 59 4a 90 f9 b1 c9 |-_...Zc4.NYJ....|
-000002e0 d8 18 02 42 01 89 e4 e4 39 d0 52 d1 70 19 fe d7 |...B....9.R.p...|
-000002f0 c6 70 10 36 94 1e 45 fd b4 03 37 79 c7 db cf 6d |.p.6..E...7y...m|
-00000300 33 5d 80 fe 04 de d1 78 bf c4 dd cf 91 82 57 14 |3].....x......W.|
-00000310 14 09 e3 2d dd d2 78 9c 53 cc 1f f7 40 6c 4a 59 |...-..x.S...@lJY|
-00000320 49 a8 a1 06 24 18 16 03 03 00 04 0e 00 00 00 |I...$..........|
+000002a0 01 bc 56 16 22 ad fd e7 ac ba c8 f5 3f c0 d7 f8 |..V.".......?...|
+000002b0 8c 64 e0 ba 09 30 c3 66 49 90 7e d2 68 86 07 72 |.d...0.fI.~.h..r|
+000002c0 20 87 a1 e1 36 92 a7 68 e2 c3 6e 34 93 a9 ca e8 | ...6..h..n4....|
+000002d0 68 3d 9e 42 c4 1e 8e 2d 95 05 ee a6 a4 2c 8d be |h=.B...-.....,..|
+000002e0 e3 88 02 42 01 16 18 77 b9 99 0e f8 46 90 46 07 |...B...w....F.F.|
+000002f0 f9 67 a9 26 68 d7 da c8 a1 d9 67 55 ec 37 11 2d |.g.&h.....gU.7.-|
+00000300 4b f3 52 f4 96 6a 0e 8a 6a 14 21 94 63 ea f9 70 |K.R..j..j.!.c..p|
+00000310 2d 57 05 8a 72 29 6e d2 60 a1 97 af 08 5b c3 cf |-W..r)n.`....[..|
+00000320 3a 82 a3 81 11 cf 16 03 03 00 04 0e 00 00 00 |:..............|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 46 10 00 00 42 41 04 66 37 3a ce 68 |....F...BA.f7:.h|
-00000010 23 0f b2 d0 cb 20 24 26 37 d5 84 46 4a 2e 59 80 |#.... $&7..FJ.Y.|
-00000020 87 b3 10 7e 36 fd af 7c 99 07 99 dd 18 af 6d 7c |...~6..|......m||
-00000030 b5 b2 b7 93 45 95 d9 98 1a 13 5b a2 12 e8 b7 95 |....E.....[.....|
-00000040 ed a1 3a 6d aa 8f fc b6 b5 b4 41 14 03 03 00 01 |..:m......A.....|
-00000050 01 16 03 03 00 40 b0 12 69 00 a4 3a 6d bd 56 40 |.....@..i..:m.V@|
-00000060 6e 9d 5e a8 1b 0f 59 c5 09 48 b2 07 d8 bc 7b 02 |n.^...Y..H....{.|
-00000070 70 61 f6 1b a9 27 55 8c 16 4d 69 4c ca 31 30 9f |pa...'U..MiL.10.|
-00000080 d3 62 ba d4 1b 11 ee 0a a0 f3 61 be c6 64 c3 dc |.b........a..d..|
-00000090 97 50 47 27 ed 09 |.PG'..|
+00000000 16 03 03 00 46 10 00 00 42 41 04 8c 80 0c da 24 |....F...BA.....$|
+00000010 d6 66 ff cc 1b 26 d5 3f 37 37 16 8f 16 ee 0d 5f |.f...&.?77....._|
+00000020 c3 0e 62 7c e4 52 2d 43 29 e9 6b da 49 bc 99 16 |..b|.R-C).k.I...|
+00000030 28 46 8e 43 20 7f 12 66 1c 94 1c 03 55 6f 05 53 |(F.C ..f....Uo.S|
+00000040 6f b7 dc 8b 70 9d 9d c5 1f da 5b 14 03 03 00 01 |o...p.....[.....|
+00000050 01 16 03 03 00 40 17 60 dd e5 b2 58 fd 74 10 38 |.....@.`...X.t.8|
+00000060 95 b1 73 7e 8f 7a 2b d0 f5 65 80 0c dc b1 ca 29 |..s~.z+..e.....)|
+00000070 06 25 e1 f9 c3 c0 7c 88 e4 ad d3 16 0a 8a dd 1f |.%....|.........|
+00000080 a7 86 86 0f ac c7 ea f5 0f 1f 2b 97 85 b3 81 f7 |..........+.....|
+00000090 5d 42 2f 3b 72 80 |]B/;r.|
>>> Flow 4 (server to client)
00000000 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 00 |..........@.....|
-00000010 00 00 00 00 00 00 00 00 00 00 00 09 34 9a eb 7c |............4..||
-00000020 6a 6d 6a 02 7b 50 14 b8 f7 b0 93 30 ea 0b 61 4a |jmj.{P.....0..aJ|
-00000030 0b 75 10 39 41 78 46 9d ba 8e d3 e9 e4 ab dc 1f |.u.9AxF.........|
-00000040 c9 43 95 e8 f9 d6 3a d3 5d 7d 09 17 03 03 00 40 |.C....:.]}.....@|
+00000010 00 00 00 00 00 00 00 00 00 00 00 82 01 fd 38 ae |..............8.|
+00000020 a4 07 8f bd 72 0a a2 b5 c5 78 09 89 65 1b 6d 1e |....r....x..e.m.|
+00000030 56 52 9d 4f de 02 15 2d 93 d8 8f d7 1f bb 07 3b |VR.O...-.......;|
+00000040 e9 62 3c 19 3e 19 65 ac 10 aa e5 17 03 03 00 40 |.b<.>.e........@|
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000060 b4 64 88 d5 53 f9 1e 47 d4 d8 c4 fa 0e c2 76 a6 |.d..S..G......v.|
-00000070 ed 5c 17 ba ea 76 72 cb c5 73 a3 c5 44 21 3c 40 |.\...vr..s..D!<@|
-00000080 33 27 09 37 73 3b 0e a3 7b 95 72 10 8d 74 85 19 |3'.7s;..{.r..t..|
+00000060 18 61 1d 26 f3 b9 34 20 00 6c 27 75 fc 35 f5 c2 |.a.&..4 .l'u.5..|
+00000070 6f 71 ca 9b 0d 70 30 46 57 7c 07 86 7d 52 a9 d6 |oq...p0FW|..}R..|
+00000080 ab fc 89 a5 48 79 ae 60 03 05 4b 17 b2 d9 6b 39 |....Hy.`..K...k9|
00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........|
-000000a0 00 00 00 00 00 b3 c0 05 e9 ec 05 06 52 ef 09 b7 |............R...|
-000000b0 52 29 04 88 ed 11 bb bd 36 a3 0f ce 2c 55 a2 87 |R)......6...,U..|
-000000c0 7e 2b 0c aa 83 |~+...|
+000000a0 00 00 00 00 00 8f 8d 88 88 c5 1e f5 bf 06 f2 45 |...............E|
+000000b0 e7 fe f0 24 c7 4c 92 5a 80 a7 89 c8 2b ac 49 d9 |...$.L.Z....+.I.|
+000000c0 39 00 ca 57 ec |9..W.|
>>> Flow 1 (client to server)
-00000000 16 03 01 01 34 01 00 01 30 03 03 10 5e c8 3f c6 |....4...0...^.?.|
-00000010 fe 44 c4 f0 13 c5 bd ad 06 21 65 e5 a8 40 b5 1d |.D.......!e..@..|
-00000020 21 07 99 34 5b ef 70 85 29 92 7d 00 00 b6 c0 30 |!..4[.p.).}....0|
+00000000 16 03 01 01 35 01 00 01 31 03 03 ed 84 e2 1a c1 |....5...1.......|
+00000010 d9 3f a5 ba 70 0b 5f 3f 3b 87 79 18 27 03 92 ee |.?..p._?;.y.'...|
+00000020 b1 9f c7 36 26 e3 0b 6d fc d5 ed 00 00 b6 c0 30 |...6&..m.......0|
00000030 c0 2c c0 28 c0 24 c0 14 c0 0a 00 a5 00 a3 00 a1 |.,.(.$..........|
00000040 00 9f 00 6b 00 6a 00 69 00 68 00 39 00 38 00 37 |...k.j.i.h.9.8.7|
00000050 00 36 00 88 00 87 00 86 00 85 c0 32 c0 2e c0 2a |.6.........2...*|
000000b0 00 3c 00 2f 00 96 00 41 00 07 c0 11 c0 07 c0 0c |.<./...A........|
000000c0 c0 02 00 05 00 04 c0 12 c0 08 00 16 00 13 00 10 |................|
000000d0 00 0d c0 0d c0 03 00 0a 00 15 00 12 00 0f 00 0c |................|
-000000e0 00 09 00 ff 01 00 00 51 00 0b 00 04 03 00 01 02 |.......Q........|
-000000f0 00 0a 00 1c 00 1a 00 17 00 19 00 1c 00 1b 00 18 |................|
-00000100 00 1a 00 16 00 0e 00 0d 00 0b 00 0c 00 09 00 0a |................|
-00000110 00 0d 00 20 00 1e 06 01 06 02 06 03 05 01 05 02 |... ............|
-00000120 05 03 04 01 04 02 04 03 03 01 03 02 03 03 02 01 |................|
-00000130 02 02 02 03 00 0f 00 01 01 |.........|
+000000e0 00 09 00 ff 02 01 00 00 51 00 0b 00 04 03 00 01 |........Q.......|
+000000f0 02 00 0a 00 1c 00 1a 00 17 00 19 00 1c 00 1b 00 |................|
+00000100 18 00 1a 00 16 00 0e 00 0d 00 0b 00 0c 00 09 00 |................|
+00000110 0a 00 0d 00 20 00 1e 06 01 06 02 06 03 05 01 05 |.... ...........|
+00000120 02 05 03 04 01 04 02 04 03 03 01 03 02 03 03 02 |................|
+00000130 01 02 02 02 03 00 0f 00 01 01 |..........|
>>> Flow 2 (server to client)
00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000002c0 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd a7 |Q.5uq..T[....g..|
000002d0 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e f1 |$ >.V...(^.+-O..|
000002e0 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 |..lK[.V.2B.X..I.|
-000002f0 b5 68 1a 41 03 56 6b dc 5a 89 05 01 00 80 6a 4b |.h.A.Vk.Z.....jK|
-00000300 b1 7d 23 cd 0e cb 26 02 d4 ee 90 f2 e0 4a 47 3d |.}#...&......JG=|
-00000310 b3 36 90 8d 01 42 98 92 ad 75 87 71 02 70 02 a8 |.6...B...u.q.p..|
-00000320 0c b0 06 ee bd 6a 1f 3f 6c 4b 4b 6b 75 41 23 b4 |.....j.?lKKkuA#.|
-00000330 f9 c2 a6 60 e2 de 55 b6 d4 85 62 e9 8f 20 70 ed |...`..U...b.. p.|
-00000340 9a b8 bb dd 1f 19 87 e9 ad b3 30 3f 7c 63 51 f1 |..........0?|cQ.|
-00000350 59 ab d1 a0 a1 80 22 56 ca 68 52 f8 0f 80 c6 a6 |Y....."V.hR.....|
-00000360 9e 12 51 ed 29 d0 6d c2 1a e5 37 dc 76 e3 f3 53 |..Q.).m...7.v..S|
-00000370 1b 07 0b ea a6 11 af dc 54 d3 ee 25 cc 27 16 03 |........T..%.'..|
+000002f0 b5 68 1a 41 03 56 6b dc 5a 89 05 01 00 80 7c 5c |.h.A.Vk.Z.....|\|
+00000300 f6 68 cc 07 f0 bd ec 30 07 d0 70 1b c6 95 a4 14 |.h.....0..p.....|
+00000310 67 3a 83 a1 43 ff 0a c3 f0 b7 ee 59 f8 c7 09 65 |g:..C......Y...e|
+00000320 08 ac 18 34 d4 8f 46 c4 2c 91 7b 57 95 e0 54 03 |...4..F.,.{W..T.|
+00000330 d8 8e b6 53 61 74 77 8b a3 5f 23 f0 06 dc 3a 56 |...Satw.._#...:V|
+00000340 61 80 5e 31 d5 75 c3 05 9f d0 06 1f c5 32 ba 79 |a.^1.u.......2.y|
+00000350 fd 14 a9 54 5a 18 b4 2b 09 0e 19 ab 76 0b 12 5d |...TZ..+....v..]|
+00000360 52 27 ce b8 dd 4c f8 f2 d2 70 56 43 19 53 b3 13 |R'...L...pVC.S..|
+00000370 b9 b7 65 ce cd 50 ed 4a 9f 42 96 c7 3c b9 16 03 |..e..P.J.B..<...|
00000380 03 00 04 0e 00 00 00 |.......|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 46 10 00 00 42 41 04 2d 4b 0c 6b 65 |....F...BA.-K.ke|
-00000010 82 32 95 8b 77 ec f0 f2 b2 ba d1 38 74 ed 82 49 |.2..w......8t..I|
-00000020 fb ce 8f 66 97 9d b6 97 d8 ae f5 19 af ad 47 b9 |...f..........G.|
-00000030 db 7b d2 c9 4e 10 68 14 ed 23 a5 98 94 f9 2a 00 |.{..N.h..#....*.|
-00000040 b6 44 b3 44 01 29 6c 56 da bb a8 14 03 03 00 01 |.D.D.)lV........|
-00000050 01 16 03 03 00 40 f4 fd de d6 20 2e 18 80 4e 73 |.....@.... ...Ns|
-00000060 af dd 97 42 08 3b 51 80 e9 26 00 48 6b 8b 21 99 |...B.;Q..&.Hk.!.|
-00000070 a8 60 1f 64 51 d0 5a 90 8b b0 69 b8 6b 29 59 21 |.`.dQ.Z...i.k)Y!|
-00000080 b1 13 19 13 07 01 e1 2c c3 6b 17 2d 01 a5 be d6 |.......,.k.-....|
-00000090 b0 0d 3d 6a 8c fe |..=j..|
+00000000 16 03 03 00 46 10 00 00 42 41 04 36 1c 6c f5 0a |....F...BA.6.l..|
+00000010 7f 52 84 ac 5a 27 45 76 79 a6 89 f1 1d d9 30 30 |.R..Z'Evy.....00|
+00000020 b6 64 af c7 34 11 12 b3 b9 72 83 e6 78 bc 06 74 |.d..4....r..x..t|
+00000030 a7 a4 10 01 34 77 5c 05 88 82 0f a9 cf 8d e8 68 |....4w\........h|
+00000040 09 80 c7 79 b6 e9 5a 2a 5f 80 5e 14 03 03 00 01 |...y..Z*_.^.....|
+00000050 01 16 03 03 00 40 ef f9 3c 34 cd 26 70 c9 7b 60 |.....@..<4.&p.{`|
+00000060 a7 27 0a 2b 86 18 2f 10 ad 48 3f 2e 9e 88 13 d6 |.'.+../..H?.....|
+00000070 d8 c6 fd 35 99 be 09 e6 dd ae 02 06 ea df 60 62 |...5..........`b|
+00000080 e0 f8 67 ea 9d c8 8c 11 d8 5a e7 6a a6 b2 eb 62 |..g......Z.j...b|
+00000090 23 b2 d2 be 75 58 |#...uX|
>>> Flow 4 (server to client)
00000000 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 00 |..........@.....|
-00000010 00 00 00 00 00 00 00 00 00 00 00 84 e2 7f e3 b4 |................|
-00000020 53 d7 d0 30 c4 e5 ea 09 df ba 33 b0 02 34 eb 2e |S..0......3..4..|
-00000030 b2 ec 47 0d e7 20 76 12 fa 53 3b 44 86 e1 e1 63 |..G.. v..S;D...c|
-00000040 06 29 57 98 ce 87 18 ad 02 17 01 17 03 03 00 40 |.)W............@|
+00000010 00 00 00 00 00 00 00 00 00 00 00 a6 52 02 4f 20 |............R.O |
+00000020 f6 d7 2d 2d 7c 65 4e 7b 43 33 32 50 9b c6 68 2c |..--|eN{C32P..h,|
+00000030 c0 6a 02 6f c6 bc 38 d8 06 c0 42 ba c1 41 ce 5c |.j.o..8...B..A.\|
+00000040 d0 a0 5f fc 8a 31 33 26 a2 79 9a 17 03 03 00 40 |.._..13&.y.....@|
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000060 b0 3a f5 90 90 30 9c b3 39 5b b4 56 f6 b9 30 7e |.:...0..9[.V..0~|
-00000070 8e a8 2d 60 47 b6 57 8a 20 61 02 f2 8e 43 c2 01 |..-`G.W. a...C..|
-00000080 ee f0 be 5a 93 52 2f ea 03 2a 4f 01 ea 9e 1c a2 |...Z.R/..*O.....|
+00000060 f2 42 8f e8 79 0d f3 c0 a0 b7 8a 5e de b8 52 c4 |.B..y......^..R.|
+00000070 b6 9d b2 10 00 e8 a3 19 27 12 ac 38 e7 d8 ec 89 |........'..8....|
+00000080 af 7d 68 15 03 e8 c4 c8 08 34 ad ad 15 7b 69 bb |.}h......4...{i.|
00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........|
-000000a0 00 00 00 00 00 c0 7e 61 51 a1 76 15 8a 7e 20 5f |......~aQ.v..~ _|
-000000b0 d4 a4 c6 3e 6c 50 18 c6 63 88 d0 ac 4c fa 31 b3 |...>lP..c...L.1.|
-000000c0 e7 c9 77 11 7a |..w.z|
+000000a0 00 00 00 00 00 a0 a5 02 ff b1 77 9a 8f e0 fc ca |..........w.....|
+000000b0 86 ee ca 9c 7c 3b ca 61 33 7f f9 12 54 79 41 97 |....|;.a3...TyA.|
+000000c0 b0 7d bd 9b 93 |.}...|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 5a 01 00 00 56 03 03 80 13 c8 83 43 |....Z...V......C|
-00000010 94 79 15 01 6e 0a 9f c5 0f e7 f6 d8 b1 94 de b4 |.y..n...........|
-00000020 57 8c 4f a8 08 48 ee 9b b4 d2 43 00 00 04 00 05 |W.O..H....C.....|
-00000030 00 ff 01 00 00 29 00 0d 00 20 00 1e 06 01 06 02 |.....)... ......|
-00000040 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 |................|
-00000050 03 02 03 03 02 01 02 02 02 03 00 0f 00 01 01 |...............|
+00000000 16 03 01 00 5b 01 00 00 57 03 03 55 46 9e 3b 51 |....[...W..UF.;Q|
+00000010 e7 cd bf df bc fe 0d 5a 5a de a6 09 6c 72 cb ea |.......ZZ...lr..|
+00000020 ab f8 a6 fd 9a 5b be 77 7d 25 20 00 00 04 00 05 |.....[.w}% .....|
+00000030 00 ff 02 01 00 00 29 00 0d 00 20 00 1e 06 01 06 |......)... .....|
+00000040 02 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 |................|
+00000050 01 03 02 03 03 02 01 02 02 02 03 00 0f 00 01 01 |................|
>>> Flow 2 (server to client)
00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000001e0 be e8 91 b3 da 1a f5 5d a3 23 f5 26 8b 45 70 8d |.......].#.&.Ep.|
000001f0 65 62 9b 7e 01 99 3d 18 f6 10 9a 38 61 9b 2e 57 |eb.~..=....8a..W|
00000200 e4 fa cc b1 8a ce e2 23 a0 87 f0 e1 67 51 eb 16 |.......#....gQ..|
-00000210 03 03 00 86 10 00 00 82 00 80 88 00 24 23 a5 c7 |............$#..|
-00000220 03 2d 86 37 91 f1 71 a9 5f fb 97 49 88 04 9b 0e |.-.7..q._..I....|
-00000230 89 da 65 d0 56 71 e7 76 22 ef 8e 11 0e 6b 50 3d |..e.Vq.v"....kP=|
-00000240 64 3f f7 9b e4 45 01 d9 12 cb da fe 10 da 4e b5 |d?...E........N.|
-00000250 b8 6a b5 bc 74 19 d3 4f a9 bb ee 54 37 e4 70 d0 |.j..t..O...T7.p.|
-00000260 b6 e7 35 96 70 fe a5 2b 14 ac fb c6 1a fa 7d 12 |..5.p..+......}.|
-00000270 87 1b 63 9d 72 30 4d 2c 1a c9 29 32 72 b6 13 53 |..c.r0M,..)2r..S|
-00000280 96 05 de 78 bc f0 1a 74 e2 31 b9 ea db 62 62 6e |...x...t.1...bbn|
-00000290 a0 a6 b2 c0 3e 2a 94 0d 6a f7 16 03 03 00 92 0f |....>*..j.......|
-000002a0 00 00 8e 04 03 00 8a 30 81 87 02 42 01 71 5b 3b |.......0...B.q[;|
-000002b0 a3 35 58 c0 b6 08 09 4f ac af 89 e0 b3 d5 3d 45 |.5X....O......=E|
-000002c0 1f 49 7f 4a c9 bc 9d 0e 50 3a f5 79 bc 54 5d a9 |.I.J....P:.y.T].|
-000002d0 62 ed 85 c5 f3 47 36 03 cc f1 cd 33 c3 70 2a a6 |b....G6....3.p*.|
-000002e0 7c d9 6e 0c db 0d 1b 4f 6a 39 ba 77 bd ea 02 41 ||.n....Oj9.w...A|
-000002f0 00 f2 b7 06 df 2f 81 7e 98 24 46 06 59 4e 86 6a |...../.~.$F.YN.j|
-00000300 b7 4f b6 4b 95 40 88 f0 8f f8 bd 16 f5 d5 82 7e |.O.K.@.........~|
-00000310 82 51 6f 05 49 43 59 cd 1d 40 69 67 ff 65 a8 68 |.Qo.ICY..@ig.e.h|
-00000320 39 2f a1 ad a7 6a ef 5c d5 69 5e 16 50 bb 2a b2 |9/...j.\.i^.P.*.|
-00000330 2f 14 03 03 00 01 01 16 03 03 00 24 55 f6 74 21 |/..........$U.t!|
-00000340 b4 08 a0 7f a2 dc 86 44 e3 f8 e3 0d e1 d6 5c 1c |.......D......\.|
-00000350 22 1e 41 2b 30 cc 34 0f a4 a1 7c a0 27 21 01 e0 |".A+0.4...|.'!..|
+00000210 03 03 00 86 10 00 00 82 00 80 03 64 6f 74 1b 0e |...........dot..|
+00000220 df 6b a4 8e f8 ec b5 02 c2 d6 7a 9a f3 bf 3e 32 |.k........z...>2|
+00000230 ba 41 dd 61 33 8a 63 fb 71 e6 87 68 32 9c 41 d5 |.A.a3.c.q..h2.A.|
+00000240 59 ee 93 55 16 e9 0a 01 72 14 93 23 82 73 91 3a |Y..U....r..#.s.:|
+00000250 6d 3c e6 e0 a8 33 34 84 80 59 65 6b c1 6d 01 19 |m<...34..Yek.m..|
+00000260 cc d5 4f 1d f6 88 4f cc b5 c6 3c 9c 68 4a be 47 |..O...O...<.hJ.G|
+00000270 c2 67 61 a4 e3 c3 00 c0 9c d4 83 ed b5 65 25 a4 |.ga..........e%.|
+00000280 2e 1c 8d 47 3f 80 b8 1d 5b 74 a2 bf fa b9 b7 e2 |...G?...[t......|
+00000290 58 94 ba ec a9 cf 1c 56 ef 0a 16 03 03 00 92 0f |X......V........|
+000002a0 00 00 8e 04 03 00 8a 30 81 87 02 41 75 cf 19 3a |.......0...Au..:|
+000002b0 a1 9e e9 69 c7 f3 63 0b 46 c2 60 35 e1 cc 95 0d |...i..c.F.`5....|
+000002c0 ee 0f ad 28 17 b4 b2 09 ea 38 18 c7 08 84 b6 ac |...(.....8......|
+000002d0 65 03 b9 49 c3 ea ff e4 45 d3 15 14 3a 94 14 0c |e..I....E...:...|
+000002e0 cb 48 ce 75 c2 a4 4a 0e 7d d8 f0 c5 5f 02 42 01 |.H.u..J.}..._.B.|
+000002f0 99 dd c7 54 ce ee 38 bb 18 16 eb 92 0a 53 0b 92 |...T..8......S..|
+00000300 d8 73 73 48 b3 0a 3b ea 12 ea 62 d3 88 99 00 54 |.ssH..;...b....T|
+00000310 bc 92 28 7d 66 b3 17 7f e7 5f 69 50 d1 a1 4c 6a |..(}f...._iP..Lj|
+00000320 99 60 00 59 0a 4d 6c 97 05 54 ee 82 5a e1 c5 88 |.`.Y.Ml..T..Z...|
+00000330 1b 14 03 03 00 01 01 16 03 03 00 24 80 64 11 aa |...........$.d..|
+00000340 cc 9d 1c 83 b6 2f 56 dc 48 cb 33 e5 0f 25 a2 42 |...../V.H.3..%.B|
+00000350 df b8 a6 cc 64 93 10 63 ad 76 91 27 3f c7 8f d4 |....d..c.v.'?...|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 24 6f 6b e7 fb f7 |..........$ok...|
-00000010 52 83 b3 6f ba 1b d7 e8 cb 0a 05 ee 90 04 2b c7 |R..o..........+.|
-00000020 c2 bd 0d 8e ee 42 88 40 ae 01 4a d0 07 4b f4 17 |.....B.@..J..K..|
-00000030 03 03 00 21 e0 8b bd 80 04 18 9c be 12 07 d4 4d |...!...........M|
-00000040 58 d9 ec c3 f0 67 b5 b3 d1 78 25 e7 2e dd a0 0a |X....g...x%.....|
-00000050 ac 0f a1 90 59 15 03 03 00 16 76 30 22 0b 00 83 |....Y.....v0"...|
-00000060 c4 31 29 1c ca 44 cb 9f 0e 48 17 21 43 f6 af 47 |.1)..D...H.!C..G|
+00000000 14 03 03 00 01 01 16 03 03 00 24 24 8d e5 5f d9 |..........$$.._.|
+00000010 99 7d d4 f2 5f f4 4b e3 b4 8e 33 84 7a c3 cb bf |.}.._.K...3.z...|
+00000020 21 00 94 db 7b 7f 6c fa a0 f2 9f 0e e9 3b 27 17 |!...{.l......;'.|
+00000030 03 03 00 21 67 f8 3a ff c1 3b cb de 04 bf 49 a6 |...!g.:..;....I.|
+00000040 9a 45 56 ab 64 99 06 7e 40 cc a7 f6 4e 1e ca cb |.EV.d..~@...N...|
+00000050 11 87 da 58 b7 15 03 03 00 16 10 1b 62 97 25 bf |...X........b.%.|
+00000060 84 c1 23 d6 76 4a a1 da 07 c7 25 68 f6 6e 63 55 |..#.vJ....%h.ncU|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 5a 01 00 00 56 03 03 b0 80 f6 7c 13 |....Z...V.....|.|
-00000010 30 5d 57 f0 11 3b 30 4b 0e 01 50 9a 44 0b 89 6f |0]W..;0K..P.D..o|
-00000020 b6 f1 a3 34 b4 f1 b9 bf fe 66 a5 00 00 04 00 05 |...4.....f......|
-00000030 00 ff 01 00 00 29 00 0d 00 20 00 1e 06 01 06 02 |.....)... ......|
-00000040 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 |................|
-00000050 03 02 03 03 02 01 02 02 02 03 00 0f 00 01 01 |...............|
+00000000 16 03 01 00 5b 01 00 00 57 03 03 87 41 6f c5 67 |....[...W...Ao.g|
+00000010 07 3b 12 46 ad aa d2 be 0d 08 98 e3 c7 4b ac 48 |.;.F.........K.H|
+00000020 67 02 6b 3b dc 84 79 c5 57 e9 89 00 00 04 00 05 |g.k;..y.W.......|
+00000030 00 ff 02 01 00 00 29 00 0d 00 20 00 1e 06 01 06 |......)... .....|
+00000040 02 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 |................|
+00000050 01 03 02 03 03 02 01 02 02 02 03 00 0f 00 01 01 |................|
>>> Flow 2 (server to client)
00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000001d0 8b ec ab 67 be c8 64 b0 11 50 46 58 17 6b 99 1c |...g..d..PFX.k..|
000001e0 d3 1d fc 06 f1 0e e5 96 a8 0c f9 78 20 b7 44 18 |...........x .D.|
000001f0 51 8d 10 7e 4f 94 67 df a3 4e 70 73 8e 90 91 85 |Q..~O.g..Nps....|
-00000200 16 03 03 00 86 10 00 00 82 00 80 98 61 16 34 c4 |............a.4.|
-00000210 c6 0a 47 c1 de 87 b1 b7 70 1b 24 8d 7e 35 90 35 |..G.....p.$.~5.5|
-00000220 f7 a5 6f c7 c9 91 ad 46 4c 50 e5 7e 61 7c 49 66 |..o....FLP.~a|If|
-00000230 e9 fe 1e 2c 30 fa 22 03 36 8f 44 27 a7 d2 14 84 |...,0.".6.D'....|
-00000240 d0 1f 21 ca 40 35 d1 7d 31 3f e1 73 de 69 bc da |..!.@5.}1?.s.i..|
-00000250 a5 96 8a b5 50 2b 4b 87 5a b3 fb e1 11 0a 29 59 |....P+K.Z.....)Y|
-00000260 13 2e e3 c2 05 d3 23 e8 09 0c 42 f6 8e 26 67 89 |......#...B..&g.|
-00000270 24 0f 08 2f 3d 24 2b 0c a2 98 38 02 5c 95 9f ce |$../=$+...8.\...|
-00000280 e3 75 ba 05 b5 f8 f0 07 e9 a1 44 16 03 03 00 88 |.u........D.....|
-00000290 0f 00 00 84 04 01 00 80 04 c0 bc 4b 23 59 ed 26 |...........K#Y.&|
-000002a0 8d 90 35 da 5b 55 88 e7 12 10 7b d7 1c 27 d1 c4 |..5.[U....{..'..|
-000002b0 d8 1b e2 e7 54 ad a4 be 00 6b 5b 61 2d ec 97 0c |....T....k[a-...|
-000002c0 a5 9b ae ab 13 fa 94 53 1c 65 28 21 7d b5 c5 be |.......S.e(!}...|
-000002d0 22 62 91 78 fc e3 de 84 5c 4e 0d f5 73 5e 20 49 |"b.x....\N..s^ I|
-000002e0 5a e2 f9 d3 2f 36 23 91 31 5b ee c7 0b 6f b3 35 |Z.../6#.1[...o.5|
-000002f0 2f 8a 51 84 3c fe 78 34 1f 8c 68 d3 fc 4f c6 5e |/.Q.<.x4..h..O.^|
-00000300 7b fe b2 81 79 91 37 ee 7f f1 9b a4 88 5f 1b 44 |{...y.7......_.D|
-00000310 dc e9 36 bb d1 45 bb 1f 14 03 03 00 01 01 16 03 |..6..E..........|
-00000320 03 00 24 12 e7 8a 31 36 26 9f fe 45 95 cf 41 56 |..$...16&..E..AV|
-00000330 b4 69 ef e4 22 14 5a 4d c8 79 a7 18 7b 68 a8 02 |.i..".ZM.y..{h..|
-00000340 75 ea 42 fe c4 a1 32 |u.B...2|
+00000200 16 03 03 00 86 10 00 00 82 00 80 79 a7 23 10 fc |...........y.#..|
+00000210 64 a7 ab 17 ce d6 8b ab ff c2 44 40 3b ba b4 c6 |d.........D@;...|
+00000220 86 b7 66 7d be 9b fa 66 f9 f6 bb e4 f7 02 16 ea |..f}...f........|
+00000230 0f 13 9c 8a 98 3a 34 e6 58 82 dc dc 27 3a 3d 5c |.....:4.X...':=\|
+00000240 99 09 db 48 54 a5 5a a2 16 7f ba 99 d9 0d ca fb |...HT.Z.........|
+00000250 4a 9e b7 f6 3a ab 26 ef f9 df a2 0c 4c 45 19 3b |J...:.&.....LE.;|
+00000260 b2 9f 21 cd ff fc cc c7 fb 91 fa 54 93 a9 42 a9 |..!........T..B.|
+00000270 4c 48 4a 8c 7b 9a d7 90 97 f6 21 89 03 f6 a5 86 |LHJ.{.....!.....|
+00000280 83 6f 21 19 2f 5b f8 ec a6 36 e9 16 03 03 00 88 |.o!./[...6......|
+00000290 0f 00 00 84 04 01 00 80 0f 9d 15 cc c0 0b 71 8a |..............q.|
+000002a0 b9 95 ca 9a 86 ff bf 93 8d da 64 ce 99 28 e2 6e |..........d..(.n|
+000002b0 6d 6f 34 c9 03 fa 87 96 b0 1d 4f b2 3c 9e 4d 2c |mo4.......O.<.M,|
+000002c0 df be 7d fb 53 fe 90 6f 45 f3 f0 d9 ab 70 d4 df |..}.S..oE....p..|
+000002d0 5a 95 a4 53 12 02 c1 45 15 c2 2b 69 7e 5f 6f cd |Z..S...E..+i~_o.|
+000002e0 b3 eb 5d ff 48 36 94 ad 28 29 fe 47 40 ab 9c eb |..].H6..().G@...|
+000002f0 02 f9 ca 7d e0 48 9f 6e a4 9f 1e c2 d7 fd 16 18 |...}.H.n........|
+00000300 db ad d9 35 27 89 96 c8 c4 70 10 be a4 5d 6b b4 |...5'....p...]k.|
+00000310 d8 61 70 93 08 00 0f c9 14 03 03 00 01 01 16 03 |.ap.............|
+00000320 03 00 24 7b ee b7 23 12 63 f0 80 ca b3 6f d3 b8 |..${..#.c....o..|
+00000330 ca cc 4a 54 06 ea e5 3e 73 f2 de 1d d6 16 7e 61 |..JT...>s.....~a|
+00000340 32 76 eb f8 8a 66 74 |2v...ft|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 24 ae 6d 7b ac b6 |..........$.m{..|
-00000010 62 5c 40 65 6b 0e 5c 12 68 61 14 90 54 3e 24 78 |b\@ek.\.ha..T>$x|
-00000020 be 85 17 a0 9b de a0 00 e9 80 1b a9 0f e4 d7 17 |................|
-00000030 03 03 00 21 86 06 17 6b 62 02 a7 a0 71 fe c0 e4 |...!...kb...q...|
-00000040 44 00 54 dd cc a9 70 cf bc 92 0d 40 07 62 f5 39 |D.T...p....@.b.9|
-00000050 2a 30 ab 7f cd 15 03 03 00 16 6f 8d c9 d4 62 02 |*0........o...b.|
-00000060 da 64 4c 89 32 86 9f 29 24 05 ed cc 77 9d e5 55 |.dL.2..)$...w..U|
+00000000 14 03 03 00 01 01 16 03 03 00 24 64 d5 a4 78 e9 |..........$d..x.|
+00000010 f1 1d d1 34 f7 b3 95 87 18 f6 cf 65 c6 f0 02 08 |...4.......e....|
+00000020 69 f5 6d aa f2 da fc 2c ac fc aa f8 25 aa 50 17 |i.m....,....%.P.|
+00000030 03 03 00 21 9f 94 f8 78 46 58 2c 21 0d 30 04 89 |...!...xFX,!.0..|
+00000040 bd 35 03 dc 04 b6 0f 6f 22 65 db 3d 8d 96 00 0c |.5.....o"e.=....|
+00000050 db bf e5 b3 59 15 03 03 00 16 a6 35 f2 07 5e 32 |....Y......5..^2|
+00000060 4e 09 e4 31 3a f6 4a 83 c2 03 db b9 bf b0 eb 6d |N..1:.J........m|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 5a 01 00 00 56 03 03 52 b6 c5 b4 e3 |....Z...V..R....|
-00000010 35 ce 4e b2 9c e0 38 09 e7 fe 00 a2 1a 0a 43 eb |5.N...8.......C.|
-00000020 df 98 6a 34 71 f9 d0 f8 5d e7 5e 00 00 04 00 05 |..j4q...].^.....|
-00000030 00 ff 01 00 00 29 00 0d 00 20 00 1e 06 01 06 02 |.....)... ......|
-00000040 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 |................|
-00000050 03 02 03 03 02 01 02 02 02 03 00 0f 00 01 01 |...............|
+00000000 16 03 01 00 5b 01 00 00 57 03 03 9a 56 e0 d9 b8 |....[...W...V...|
+00000010 ac d5 88 c7 2f d1 87 1b 44 c6 ff 7b 4f 6f f0 2a |..../...D..{Oo.*|
+00000020 56 a1 9e 46 86 4b 6f 91 29 29 3b 00 00 04 00 05 |V..F.Ko.));.....|
+00000030 00 ff 02 01 00 00 29 00 0d 00 20 00 1e 06 01 06 |......)... .....|
+00000040 02 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 |................|
+00000050 01 03 02 03 03 02 01 02 02 02 03 00 0f 00 01 01 |................|
>>> Flow 2 (server to client)
00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000002d0 00 |.|
>>> Flow 3 (client to server)
00000000 16 03 03 00 07 0b 00 00 03 00 00 00 16 03 03 00 |................|
-00000010 86 10 00 00 82 00 80 2e 8e cb 6c f5 db 45 5b f0 |..........l..E[.|
-00000020 67 7d b1 ac 87 c2 d6 e9 ea 37 40 15 2a ea a1 af |g}.......7@.*...|
-00000030 ed 71 68 18 9c 6c 84 20 52 3e 38 94 8e d9 cd b3 |.qh..l. R>8.....|
-00000040 15 73 8b db d7 ff 1d 8a ed a6 f4 00 7d d0 0a 1e |.s..........}...|
-00000050 9a 1b 5c 59 f6 a0 29 62 03 a1 c6 bf 8a 57 14 06 |..\Y..)b.....W..|
-00000060 9a e8 03 72 bc cd cd 6f 6d e2 ce a8 41 7a f0 65 |...r...om...Az.e|
-00000070 42 0c 7b dd 93 d7 ab 37 f8 2a b3 c4 72 95 61 e1 |B.{....7.*..r.a.|
-00000080 75 98 f5 99 69 ef 0a d0 00 41 0f 05 87 13 d3 7d |u...i....A.....}|
-00000090 ba 74 34 43 9a 6c d0 14 03 03 00 01 01 16 03 03 |.t4C.l..........|
-000000a0 00 24 87 7e 7d 48 ca 17 9c ad 30 b8 6a 05 2f d3 |.$.~}H....0.j./.|
-000000b0 fc 18 2e df fd f5 0e 38 c3 06 57 4c 27 66 02 af |.......8..WL'f..|
-000000c0 6d 78 4d 2e b6 dc |mxM...|
+00000010 86 10 00 00 82 00 80 3a 72 91 a2 c3 ba 83 75 1b |.......:r.....u.|
+00000020 d3 f6 1c 07 7f 92 a8 b0 1f 47 42 cc 8d 4e 7e 1e |.........GB..N~.|
+00000030 23 49 44 29 53 19 9f 3b 5c bb 5d ed 6c d9 49 5d |#ID)S..;\.].l.I]|
+00000040 6e f9 d1 59 9d 40 67 b3 0c ee 41 85 6c 4a 4d 3b |n..Y.@g...A.lJM;|
+00000050 c1 e6 c8 7f 93 15 cb 2a 17 64 da 70 f3 2a c3 7c |.......*.d.p.*.||
+00000060 a2 02 48 19 fb 74 5a dc 52 0d 80 6b ed c0 8c 15 |..H..tZ.R..k....|
+00000070 3e 3b 34 7c 55 6e 95 e0 d1 4a 7f b0 bc 33 67 a7 |>;4|Un...J...3g.|
+00000080 3b 40 bb eb 83 58 4a fb fb 01 9b 0d fa ef 83 c4 |;@...XJ.........|
+00000090 87 10 75 0c a7 ad 91 14 03 03 00 01 01 16 03 03 |..u.............|
+000000a0 00 24 18 ce de 8d ab c1 6e 3b 0b 51 fe 94 ae 0a |.$......n;.Q....|
+000000b0 39 9c 4d a2 90 53 d4 1e 5f f6 96 5a 51 f2 39 c1 |9.M..S.._..ZQ.9.|
+000000c0 d6 06 c0 4e 58 99 |...NX.|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 24 cf ee f6 28 ea |..........$...(.|
-00000010 df e2 7e 9a 75 e0 f9 b4 c4 c2 57 3a 54 26 db 7f |..~.u.....W:T&..|
-00000020 c4 19 6d b6 d6 c7 b1 05 7f 92 21 9e 51 1a 0a 17 |..m.......!.Q...|
-00000030 03 03 00 21 87 48 77 c4 eb 7c 5d 13 3b f4 8d 08 |...!.Hw..|].;...|
-00000040 f9 35 c3 d2 e5 c0 8c ea 15 c9 2d c5 e0 70 fd 7c |.5........-..p.||
-00000050 de 93 4f 8c 8d 15 03 03 00 16 d4 8a d5 6a fc db |..O..........j..|
-00000060 c7 1d 1f 76 64 b9 31 68 72 cc 58 de 9f 2a a6 45 |...vd.1hr.X..*.E|
+00000000 14 03 03 00 01 01 16 03 03 00 24 8b 7e 57 f3 7d |..........$.~W.}|
+00000010 ab 44 f0 c7 53 2d 39 08 14 32 12 4e 4b 45 9a e3 |.D..S-9..2.NKE..|
+00000020 1c 43 36 16 59 a0 4b e4 78 43 d2 a5 dc 96 b1 17 |.C6.Y.K.xC......|
+00000030 03 03 00 21 54 89 75 23 de 7d c7 c6 80 a6 a6 69 |...!T.u#.}.....i|
+00000040 d0 a8 95 77 71 a0 89 34 f4 c3 31 73 bb b0 ac d7 |...wq..4..1s....|
+00000050 e5 e4 83 4b 10 15 03 03 00 16 0d 44 43 67 21 cc |...K.......DCg!.|
+00000060 6c c1 7e 72 99 aa 7f a1 de 10 0b 36 ae 05 d9 9e |l.~r.......6....|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 a1 01 00 00 9d 03 03 0f b7 07 5f c7 |.............._.|
-00000010 18 b8 39 6d 92 b3 90 ed bf 5c 48 7c 6a 56 ee e9 |..9m.....\H|jV..|
-00000020 7a 5b 5f 71 a4 f0 7f 47 57 73 78 00 00 04 c0 0a |z[_q...GWsx.....|
-00000030 00 ff 02 01 00 00 6f 00 0b 00 04 03 00 01 02 00 |......o.........|
-00000040 0a 00 3a 00 38 00 0e 00 0d 00 19 00 1c 00 0b 00 |..:.8...........|
-00000050 0c 00 1b 00 18 00 09 00 0a 00 1a 00 16 00 17 00 |................|
-00000060 08 00 06 00 07 00 14 00 15 00 04 00 05 00 12 00 |................|
-00000070 13 00 01 00 02 00 03 00 0f 00 10 00 11 00 0d 00 |................|
-00000080 20 00 1e 06 01 06 02 06 03 05 01 05 02 05 03 04 | ...............|
-00000090 01 04 02 04 03 03 01 03 02 03 03 02 01 02 02 02 |................|
-000000a0 03 00 0f 00 01 01 |......|
+00000000 16 03 01 00 83 01 00 00 7f 03 03 ec 8e d0 43 01 |..............C.|
+00000010 8e 81 3f d8 1f 7e 96 f1 de 4c 94 18 09 1d c5 8c |..?..~...L......|
+00000020 3a 58 68 5b 3e 7d 46 66 fe 04 74 00 00 04 c0 0a |:Xh[>}Ff..t.....|
+00000030 00 ff 02 01 00 00 51 00 0b 00 04 03 00 01 02 00 |......Q.........|
+00000040 0a 00 1c 00 1a 00 17 00 19 00 1c 00 1b 00 18 00 |................|
+00000050 1a 00 16 00 0e 00 0d 00 0b 00 0c 00 09 00 0a 00 |................|
+00000060 0d 00 20 00 1e 06 01 06 02 06 03 05 01 05 02 05 |.. .............|
+00000070 03 04 01 04 02 04 03 03 01 03 02 03 03 02 01 02 |................|
+00000080 02 02 03 00 0f 00 01 01 |........|
>>> Flow 2 (server to client)
00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000270 b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e f1 07 9f 6c |.V...(^.+-O....l|
00000280 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 b5 68 1a |K[.V.2B.X..I..h.|
00000290 41 03 56 6b dc 5a 89 05 03 00 8b 30 81 88 02 42 |A.Vk.Z.....0...B|
-000002a0 00 d3 cf 21 cd 3c 2e 11 f5 f8 1d c8 c1 57 4b f8 |...!.<.......WK.|
-000002b0 1a c0 2b 1d 47 0f 2d a5 ac a1 c8 83 5d 76 87 05 |..+.G.-.....]v..|
-000002c0 2b 0d 36 d5 57 9f b9 8a a0 a2 94 67 6a cd 29 db |+.6.W......gj.).|
-000002d0 04 b0 6b 06 d9 f7 17 9f 1c 60 92 e7 4e 50 48 7f |..k......`..NPH.|
-000002e0 dc d0 02 42 01 56 fd 38 bd 05 a5 16 6d 91 d1 ce |...B.V.8....m...|
-000002f0 bb 8c 45 b2 76 2f 92 9c 8b 94 57 7d de 53 8b 7b |..E.v/....W}.S.{|
-00000300 80 26 6c 4a 43 4b a6 c9 46 49 08 ab c7 57 f3 d9 |.&lJCK..FI...W..|
-00000310 fa 1d 55 fe 91 de 8a 0d 8b d1 44 96 87 85 cb 02 |..U.......D.....|
-00000320 76 9c 00 ad 5f b8 16 03 03 00 04 0e 00 00 00 |v..._..........|
+000002a0 01 08 89 99 1c 91 97 fb e8 5b 69 5f f5 36 66 d6 |.........[i_.6f.|
+000002b0 dd 53 04 09 c8 7f c1 25 28 8c 28 57 55 3a 95 3f |.S.....%(.(WU:.?|
+000002c0 ab 09 47 9a 27 74 83 84 44 cf 86 b7 5e 7f fe db |..G.'t..D...^...|
+000002d0 05 33 3c 1a b7 f6 bc ff 0d 33 e4 ec 3c e2 1d e2 |.3<......3..<...|
+000002e0 6e ab 02 42 00 92 4e 45 a7 86 e4 bd 40 82 b7 04 |n..B..NE....@...|
+000002f0 12 fe 34 ab e3 c9 4a 05 1f 4e 58 79 67 58 94 53 |..4...J..NXygX.S|
+00000300 e8 1b ba 60 76 92 00 99 a7 5f 0a 98 cb e3 1e de |...`v...._......|
+00000310 0c df 18 76 58 d5 e1 f1 ef a5 da 9a a3 62 77 50 |...vX........bwP|
+00000320 37 d0 22 d0 31 90 16 03 03 00 04 0e 00 00 00 |7.".1..........|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 46 10 00 00 42 41 04 0b dc ea 22 05 |....F...BA....".|
-00000010 44 c2 09 47 65 31 3b 0b e1 05 1a 87 8c 2d 3b 56 |D..Ge1;......-;V|
-00000020 49 34 27 3e d6 3b 93 e2 12 7f 5d 7b dc 85 c8 96 |I4'>.;....]{....|
-00000030 4c 8c f9 18 6f 15 cf db 6e 2c 14 6a c9 dd 1c 70 |L...o...n,.j...p|
-00000040 7e 05 c4 17 71 76 df 10 ee 8c b1 14 03 03 00 01 |~...qv..........|
-00000050 01 16 03 03 00 40 ff 12 88 36 3c 00 17 d1 b9 41 |.....@...6<....A|
-00000060 7a 12 25 94 4c 90 65 62 d8 09 ab f9 b4 ee c3 de |z.%.L.eb........|
-00000070 46 2f cb ee 18 76 4f 76 8e dd 89 fc 7a 21 3b 5f |F/...vOv....z!;_|
-00000080 ff ac 1c 03 aa be 96 82 82 ea 2e 22 2a 80 b3 86 |..........."*...|
-00000090 38 e4 4d 90 91 46 |8.M..F|
+00000000 16 03 03 00 46 10 00 00 42 41 04 9e 94 25 4f 70 |....F...BA...%Op|
+00000010 a8 e0 87 3a 09 6c 58 4f 5e 76 d9 63 dc c3 d5 63 |...:.lXO^v.c...c|
+00000020 be f2 75 ff 23 23 79 6b 82 fe 56 f5 b9 7a 55 55 |..u.##yk..V..zUU|
+00000030 32 3b ee c5 f0 1f 7b e9 82 01 21 8d 06 03 48 95 |2;....{...!...H.|
+00000040 21 b8 fa 9d 18 2a 08 9c 71 a8 4d 14 03 03 00 01 |!....*..q.M.....|
+00000050 01 16 03 03 00 40 31 f0 7b 5f e8 94 a3 7f b0 12 |.....@1.{_......|
+00000060 a9 80 87 26 eb cf b6 87 61 e7 5b 9b 36 3d 11 bb |...&....a.[.6=..|
+00000070 21 55 5c f7 e8 f3 b7 1e f2 06 0d c5 a9 8d f8 48 |!U\............H|
+00000080 c2 2b 8f 83 be 17 4f ec ff 8e 24 44 74 25 09 40 |.+....O...$Dt%.@|
+00000090 90 fd 70 4d fb bb |..pM..|
>>> Flow 4 (server to client)
00000000 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 00 |..........@.....|
-00000010 00 00 00 00 00 00 00 00 00 00 00 e5 c1 f0 6a db |..............j.|
-00000020 05 98 ed 33 94 73 7f 13 7f 78 17 7f d1 9e c5 a7 |...3.s...x......|
-00000030 62 7f 85 14 2c 7d b2 8e ef 75 a9 df 92 cc 22 20 |b...,}...u...." |
-00000040 66 08 85 22 d3 ea 5c 4c 4c c8 d7 17 03 03 00 40 |f.."..\LL......@|
+00000010 00 00 00 00 00 00 00 00 00 00 00 13 eb 4e 56 3d |.............NV=|
+00000020 1b 10 2e e8 08 65 b9 53 9e 56 49 b7 e9 25 35 94 |.....e.S.VI..%5.|
+00000030 c7 df 7d f7 78 2e f3 8b 9c 2b 9d 42 90 91 5c 97 |..}.x....+.B..\.|
+00000040 22 20 ca 6d a2 83 b3 d8 b3 71 64 17 03 03 00 40 |" .m.....qd....@|
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000060 f2 20 07 d2 13 ca ed 01 c9 7b 91 14 01 2c 08 f5 |. .......{...,..|
-00000070 8a 69 94 bc 19 9a d9 65 6b 15 04 b4 45 17 ec 6f |.i.....ek...E..o|
-00000080 85 de 31 dc a2 de 8b 4d 53 57 66 4a 29 21 5a 20 |..1....MSWfJ)!Z |
+00000060 97 f1 c4 2e bf 6d 85 d5 3d 4b 4a 8b ee 53 08 5a |.....m..=KJ..S.Z|
+00000070 db 8b 75 49 d9 cb db e3 86 90 ac 93 ce e7 9a 70 |..uI...........p|
+00000080 4c dc 4a f4 c9 f6 b5 fd f0 3f 9f e9 f9 c3 b3 c6 |L.J......?......|
00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........|
-000000a0 00 00 00 00 00 55 15 f7 89 8d 75 57 7e 92 db ec |.....U....uW~...|
-000000b0 32 ec 07 5c 83 32 36 59 61 f1 9d a6 7a eb 76 c1 |2..\.26Ya...z.v.|
-000000c0 c7 96 3f 4d 0a |..?M.|
+000000a0 00 00 00 00 00 5e b1 b7 21 7d 89 65 66 17 d8 79 |.....^..!}.ef..y|
+000000b0 26 db ad 08 28 2c e7 7a c4 ec 93 19 4f c8 bb 5c |&...(,.z....O..\|
+000000c0 c2 9e 09 56 07 |...V.|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 5e 01 00 00 5a 03 03 f0 0a 06 d0 65 |....^...Z......e|
-00000010 1c c3 90 ac dc 61 42 e5 b8 a9 17 fb e7 c3 1e bd |.....aB.........|
-00000020 d9 09 5a 63 71 e2 f9 58 db 26 6e 00 00 04 00 05 |..Zcq..X.&n.....|
-00000030 00 ff 01 00 00 2d 00 23 00 00 00 0d 00 20 00 1e |.....-.#..... ..|
-00000040 06 01 06 02 06 03 05 01 05 02 05 03 04 01 04 02 |................|
-00000050 04 03 03 01 03 02 03 03 02 01 02 02 02 03 00 0f |................|
-00000060 00 01 01 |...|
+00000000 16 03 01 00 5f 01 00 00 5b 03 03 6e cc 37 81 0a |...._...[..n.7..|
+00000010 b9 fe 58 30 8e 32 61 3c b1 38 1e 2b f6 ab 44 ee |..X0.2a<.8.+..D.|
+00000020 f2 cc fe 6e fe 40 65 49 d9 ba aa 00 00 04 00 05 |...n.@eI........|
+00000030 00 ff 02 01 00 00 2d 00 23 00 00 00 0d 00 20 00 |......-.#..... .|
+00000040 1e 06 01 06 02 06 03 05 01 05 02 05 03 04 01 04 |................|
+00000050 02 04 03 03 01 03 02 03 03 02 01 02 02 02 03 00 |................|
+00000060 0f 00 01 01 |....|
>>> Flow 2 (server to client)
00000000 16 03 03 00 35 02 00 00 31 03 03 00 00 00 00 00 |....5...1.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000002a0 4f 86 c7 f9 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 |O.....A4......9.|
000002b0 16 03 03 00 04 0e 00 00 00 |.........|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 86 10 00 00 82 00 80 87 06 ba d7 1f |................|
-00000010 68 0c f2 a6 51 b4 ae af 8c c5 5d d4 bd f1 82 6d |h...Q.....]....m|
-00000020 1d dd ce 69 be 07 62 13 af 06 71 3a 47 a9 bd f7 |...i..b...q:G...|
-00000030 bb 27 f0 38 df 88 01 40 29 c9 bb 7b 5d 6d 28 bd |.'.8...@)..{]m(.|
-00000040 c8 28 e6 6d ff 5c c9 d3 c6 f5 06 17 e5 e5 1c 5b |.(.m.\.........[|
-00000050 a1 18 7a 34 92 0a 39 20 5a 22 44 6c cc 5c 8c 83 |..z4..9 Z"Dl.\..|
-00000060 d0 19 4c bb 4e dc e2 64 ec b2 b8 3f 18 3f 9d 65 |..L.N..d...?.?.e|
-00000070 5b 89 26 ae f6 fd 54 71 c4 45 e9 56 6a 28 42 a9 |[.&...Tq.E.Vj(B.|
-00000080 5b 9f 12 69 a4 08 83 53 95 04 18 14 03 03 00 01 |[..i...S........|
-00000090 01 16 03 03 00 24 55 80 0f 43 c3 08 45 99 c9 1b |.....$U..C..E...|
-000000a0 fd fe dd e8 48 f2 89 99 86 ef f7 fd 5f 2a 4b 0b |....H......._*K.|
-000000b0 33 0e 5f 17 bb b7 a2 3c 9d 30 |3._....<.0|
+00000000 16 03 03 00 86 10 00 00 82 00 80 5d f3 3b c6 24 |...........].;.$|
+00000010 34 17 eb e1 6c de fa cd ed 6f 42 74 01 5f 4b 22 |4...l....oBt._K"|
+00000020 9e 79 da 68 9f e9 f8 af 84 6b b7 38 52 f3 5e a1 |.y.h.....k.8R.^.|
+00000030 e2 aa d1 48 15 1e 39 6e 18 59 3e dc 57 4a fb b1 |...H..9n.Y>.WJ..|
+00000040 18 18 40 ae 84 da d8 76 50 65 3b a5 d9 7a 72 b1 |..@....vPe;..zr.|
+00000050 51 07 65 08 0e 1d 05 f5 47 a8 7d 79 89 1e fe 00 |Q.e.....G.}y....|
+00000060 89 af 01 7f 4d 0c 11 d7 02 cf 88 7b be 03 c5 65 |....M......{...e|
+00000070 44 77 32 56 5c da 01 53 d1 dd d9 b4 5f 42 85 da |Dw2V\..S...._B..|
+00000080 82 0b 95 59 45 a3 7a 48 d4 00 22 14 03 03 00 01 |...YE.zH..".....|
+00000090 01 16 03 03 00 24 dd 06 a2 4b a0 8e 8b 31 f2 26 |.....$...K...1.&|
+000000a0 b2 6f d4 5d ff 34 eb 31 42 16 e7 c2 26 3d f7 16 |.o.].4.1B...&=..|
+000000b0 ed bd 41 4b 6f d4 03 fb b7 83 |..AKo.....|
>>> Flow 4 (server to client)
00000000 16 03 03 00 82 04 00 00 7e 00 00 00 00 00 78 50 |........~.....xP|
00000010 46 ad c1 db a8 38 86 7b 2b bb fd d0 c3 42 3e 00 |F....8.{+....B>.|
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 94 |................|
-00000030 6f 2c b5 83 61 c4 74 90 94 e5 6c fd 70 64 57 3a |o,..a.t...l.pdW:|
-00000040 25 78 bf 9f a0 7c 51 bc 2a 69 1e b3 fd 71 34 b7 |%x...|Q.*i...q4.|
-00000050 9a ef cb 49 37 f8 5d 5e 7c cf 6d fc 13 c1 52 79 |...I7.]^|.m...Ry|
-00000060 8e ed c3 84 01 33 94 10 65 34 64 5e b4 9c 07 46 |.....3..e4d^...F|
-00000070 5b 9e d7 5e 55 df fd c0 e9 d2 e8 d3 c6 42 18 ef |[..^U........B..|
-00000080 a5 6c be e8 d2 49 c6 14 03 03 00 01 01 16 03 03 |.l...I..........|
-00000090 00 24 66 94 4b b5 3f 5d 59 db 36 c1 dd 55 8c ee |.$f.K.?]Y.6..U..|
-000000a0 de a4 bc d0 12 44 31 3e e4 e7 4a 51 e3 62 69 ab |.....D1>..JQ.bi.|
-000000b0 14 78 85 49 a3 97 17 03 03 00 21 dd 96 5d 21 e0 |.x.I......!..]!.|
-000000c0 2e 3d 33 dd 6c df bb 41 d7 bd 50 c7 1c 6f 97 34 |.=3.l..A..P..o.4|
-000000d0 6a 6e d6 1d 27 81 2d f7 fb 32 85 02 15 03 03 00 |jn..'.-..2......|
-000000e0 16 5e 4e 62 15 97 a7 a3 9b 1b 50 44 85 fb 28 66 |.^Nb......PD..(f|
-000000f0 aa 66 54 45 c9 dc 61 |.fTE..a|
+00000030 6f 2c b5 83 61 4d 51 5f 33 46 48 fe 9e e9 83 f4 |o,..aMQ_3FH.....|
+00000040 b1 aa c9 b1 61 2a b2 9d 0f 17 c4 09 f6 26 7a 75 |....a*.......&zu|
+00000050 f1 19 99 db 36 d8 32 f0 94 61 4f 8f ed 80 33 51 |....6.2..aO...3Q|
+00000060 f3 c6 15 84 6b 33 94 c8 4f 84 b7 7c 27 6d 8f fe |....k3..O..|'m..|
+00000070 41 8e b2 92 ca 80 e8 6c ba 75 77 f5 3a 87 17 ae |A......l.uw.:...|
+00000080 f8 b9 6b 10 f9 85 da 14 03 03 00 01 01 16 03 03 |..k.............|
+00000090 00 24 70 bd b9 24 02 ce 69 8a 07 c7 c8 7e cf b7 |.$p..$..i....~..|
+000000a0 4e 2b e2 dc 47 fc f7 3a c8 2d ab a0 9a ed 27 d9 |N+..G..:.-....'.|
+000000b0 71 ea 45 29 d6 25 17 03 03 00 21 d9 28 ee 99 04 |q.E).%....!.(...|
+000000c0 35 ff ca 3d 30 3f 76 fb 08 1a 56 73 f5 72 c3 fa |5..=0?v...Vs.r..|
+000000d0 cd 9e 3c 1b 3f 43 4d 56 92 38 9e a6 15 03 03 00 |..<.?CMV.8......|
+000000e0 16 6f 55 57 7b 81 6f 7d fa 90 76 0b 5b 6d 95 35 |.oUW{.o}..v.[m.5|
+000000f0 39 9f a8 c9 dc b7 80 |9......|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 5e 01 00 00 5a 03 03 62 f6 20 66 23 |....^...Z..b. f#|
-00000010 d5 71 0a c0 57 92 2e 80 b6 06 0c 54 5b 1c 77 a0 |.q..W......T[.w.|
-00000020 ce 0b b2 52 4a b9 f2 c6 97 33 42 00 00 04 00 05 |...RJ....3B.....|
-00000030 00 ff 01 00 00 2d 00 23 00 00 00 0d 00 20 00 1e |.....-.#..... ..|
-00000040 06 01 06 02 06 03 05 01 05 02 05 03 04 01 04 02 |................|
-00000050 04 03 03 01 03 02 03 03 02 01 02 02 02 03 00 0f |................|
-00000060 00 01 01 |...|
+00000000 16 03 01 00 5f 01 00 00 5b 03 03 54 25 f9 0f b8 |...._...[..T%...|
+00000010 2d 52 a0 17 b6 62 1c 60 38 31 30 67 f1 55 9c c8 |-R...b.`810g.U..|
+00000020 d3 74 65 bf cd 34 fb 6f f2 60 7c 00 00 04 00 05 |.te..4.o.`|.....|
+00000030 00 ff 02 01 00 00 2d 00 23 00 00 00 0d 00 20 00 |......-.#..... .|
+00000040 1e 06 01 06 02 06 03 05 01 05 02 05 03 04 01 04 |................|
+00000050 02 04 03 03 01 03 02 03 03 02 01 02 02 02 03 00 |................|
+00000060 0f 00 01 01 |....|
>>> Flow 2 (server to client)
00000000 16 03 03 00 35 02 00 00 31 03 03 00 00 00 00 00 |....5...1.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000002a0 4f 86 c7 f9 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 |O.....A4......9.|
000002b0 16 03 03 00 04 0e 00 00 00 |.........|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 86 10 00 00 82 00 80 5b 43 6f db 52 |...........[Co.R|
-00000010 56 e3 d9 4b 1e c8 95 8b 78 a6 19 00 44 9c 44 b4 |V..K....x...D.D.|
-00000020 f7 fe d4 3f 69 ea 9c 67 d3 48 b8 c5 93 bc 22 f1 |...?i..g.H....".|
-00000030 a9 0e 81 82 d0 cf dc 0b ea f0 02 67 92 8d 72 40 |...........g..r@|
-00000040 25 bb f3 88 53 c0 2f ba 38 ef da d1 7c 73 84 ec |%...S./.8...|s..|
-00000050 61 96 b9 d4 93 06 4a 06 7b 6d 40 e7 bb 15 59 6e |a.....J.{m@...Yn|
-00000060 ad 31 71 eb cf 84 57 3b 0c ad aa 70 02 63 24 a9 |.1q...W;...p.c$.|
-00000070 7c a1 9a 6d b7 e0 4c d5 67 4c ce 53 9d b6 31 de ||..m..L.gL.S..1.|
-00000080 69 b9 f5 ca a8 e3 ea d6 f5 a3 f3 14 03 03 00 01 |i...............|
-00000090 01 16 03 03 00 24 66 ae 13 67 70 20 f5 f5 76 03 |.....$f..gp ..v.|
-000000a0 11 6e 32 a6 73 a2 70 42 ab 4f 16 93 d2 fa a1 ac |.n2.s.pB.O......|
-000000b0 4e b2 08 4a a9 b5 20 aa 80 b6 |N..J.. ...|
+00000000 16 03 03 00 86 10 00 00 82 00 80 19 db c8 25 14 |..............%.|
+00000010 e0 7b 6e 87 7b 59 2d 85 8b 47 ce 31 d7 3a 53 06 |.{n.{Y-..G.1.:S.|
+00000020 ff cf 89 ae 45 fd 59 d2 50 c2 31 33 48 81 a8 d7 |....E.Y.P.13H...|
+00000030 47 36 b9 bd 8d f3 f9 f8 c2 6d 6a 8a 6b c4 e5 53 |G6.......mj.k..S|
+00000040 24 52 40 66 49 a9 56 74 4c 94 bc 85 5b 79 5a e1 |$R@fI.VtL...[yZ.|
+00000050 66 3c 42 d8 ca e1 3f c5 36 b8 b5 8c b2 ea 87 68 |f<B...?.6......h|
+00000060 70 eb e3 da 27 fe ed f5 d0 4a c7 fe 46 0b 0f 29 |p...'....J..F..)|
+00000070 19 41 ef dd a9 85 8a 67 02 41 04 30 20 07 09 55 |.A.....g.A.0 ..U|
+00000080 ff 92 44 f1 59 49 39 dd fa d7 a0 14 03 03 00 01 |..D.YI9.........|
+00000090 01 16 03 03 00 24 82 b5 7b d1 7c 03 93 88 fd 97 |.....$..{.|.....|
+000000a0 54 b7 ff 39 a7 11 c3 cd 53 f3 1c 6c ed ab b6 a0 |T..9....S..l....|
+000000b0 1c b9 89 f0 1a f8 5f 15 7f 85 |......_...|
>>> Flow 4 (server to client)
00000000 16 03 03 00 82 04 00 00 7e 00 00 00 00 00 78 50 |........~.....xP|
00000010 46 ad c1 db a8 38 86 7b 2b bb fd d0 c3 42 3e 00 |F....8.{+....B>.|
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 94 |................|
-00000030 6f 2c b5 83 61 bd 50 da 49 7f 8b 8f 58 57 00 a1 |o,..a.P.I...XW..|
-00000040 11 0d 4a 9d 8a 39 dd 85 23 c0 eb 9d 1a 45 93 92 |..J..9..#....E..|
-00000050 e7 af 15 a3 a4 48 da f9 a4 d8 8e cb 6c 3d 44 77 |.....H......l=Dw|
-00000060 f9 c4 83 89 85 33 94 c1 c6 20 9a 73 44 83 89 5e |.....3... .sD..^|
-00000070 59 ee 05 c6 7e 8d e9 7d 7b f8 84 46 b6 7d 43 ec |Y...~..}{..F.}C.|
-00000080 f1 af 1f 0f 35 b4 1c 14 03 03 00 01 01 16 03 03 |....5...........|
-00000090 00 24 8c 0d bd bc 34 93 ed ad 80 21 6d 08 e4 0e |.$....4....!m...|
-000000a0 67 4f 99 8d df 2a 2d 4f 13 39 82 be a1 d2 1f 75 |gO...*-O.9.....u|
-000000b0 73 c8 b2 ce 41 0c 17 03 03 00 21 d8 c2 50 d6 11 |s...A.....!..P..|
-000000c0 bc 86 58 68 0e 60 4a 47 a5 d0 12 7e a3 b5 be 64 |..Xh.`JG...~...d|
-000000d0 e6 b1 bc 62 70 85 d4 7c cd fe 67 cf 15 03 03 00 |...bp..|..g.....|
-000000e0 16 e4 1c d5 f4 f7 d0 f5 b2 b3 2b 3d b0 7d c0 23 |..........+=.}.#|
-000000f0 e2 5c a5 c7 a4 23 fa |.\...#.|
+00000030 6f 2c b5 83 61 01 55 65 2a 95 38 d4 d5 5f 41 c1 |o,..a.Ue*.8.._A.|
+00000040 45 e4 f8 4b 3b 08 44 df 0b 72 11 93 cd d4 ff 36 |E..K;.D..r.....6|
+00000050 0f 4f 3a a9 4c 9f ab c7 ae 88 97 bc 1e ff 2d 27 |.O:.L.........-'|
+00000060 39 a8 82 84 ae 33 94 48 8b 1c 58 9d 60 65 3c 3f |9....3.H..X.`e<?|
+00000070 17 9d 6a eb 50 cd 65 04 bb c7 28 c8 0d 57 44 52 |..j.P.e...(..WDR|
+00000080 e0 17 de df f3 13 b1 14 03 03 00 01 01 16 03 03 |................|
+00000090 00 24 5a 41 90 0a eb d9 6b 02 68 3d 98 12 1d fa |.$ZA....k.h=....|
+000000a0 46 7d 73 ea 8e 49 72 a5 2f 04 40 5c 7d 03 c7 3a |F}s..Ir./.@\}..:|
+000000b0 6e 50 7c 87 bb 13 17 03 03 00 21 46 da ec ad 52 |nP|.......!F...R|
+000000c0 ea 5a 01 89 15 77 79 af 86 02 b5 89 c8 97 dc f7 |.Z...wy.........|
+000000d0 ac 73 09 87 7a 61 57 d6 9b 17 10 af 15 03 03 00 |.s..zaW.........|
+000000e0 16 bb 20 22 ad 6e 65 66 8c d6 07 e3 82 5f ac 1e |.. ".nef....._..|
+000000f0 ec 54 72 eb 2d c5 af |.Tr.-..|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 5a 01 00 00 56 03 03 ac 1d 0b 6e f3 |....Z...V.....n.|
-00000010 25 04 00 97 a0 79 39 c5 ef 95 8b e3 c1 87 0d 1c |%....y9.........|
-00000020 0b c3 39 3e ff 23 0e 3c 28 8f 75 00 00 04 00 0a |..9>.#.<(.u.....|
-00000030 00 ff 01 00 00 29 00 0d 00 20 00 1e 06 01 06 02 |.....)... ......|
-00000040 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 |................|
-00000050 03 02 03 03 02 01 02 02 02 03 00 0f 00 01 01 |...............|
+00000000 16 03 01 00 5b 01 00 00 57 03 03 1e c8 d0 4c b2 |....[...W.....L.|
+00000010 8d 37 e1 88 c7 0f e0 6a 21 3c 5e 8a bf fa 97 1f |.7.....j!<^.....|
+00000020 5b 28 bc 6d 47 32 0a 6b f7 11 f5 00 00 04 00 0a |[(.mG2.k........|
+00000030 00 ff 02 01 00 00 29 00 0d 00 20 00 1e 06 01 06 |......)... .....|
+00000040 02 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 |................|
+00000050 01 03 02 03 03 02 01 02 02 02 03 00 0f 00 01 01 |................|
>>> Flow 2 (server to client)
00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000002a0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 03 00 |..A4......9.....|
000002b0 04 0e 00 00 00 |.....|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 86 10 00 00 82 00 80 15 75 c5 63 e0 |............u.c.|
-00000010 c3 a5 89 dd b3 bf 03 1d bd 62 86 2e 10 98 79 cb |.........b....y.|
-00000020 40 3d 9b 36 7e 55 65 d7 80 0a c5 24 ff ad 98 d5 |@=.6~Ue....$....|
-00000030 d4 d9 4e 1b ed 50 0a fa 8a 3e f3 01 c4 e3 47 f7 |..N..P...>....G.|
-00000040 bd 81 fc 33 0b 61 6b b5 3f 38 9b 24 cd 7d 46 66 |...3.ak.?8.$.}Ff|
-00000050 18 87 ea 67 04 b7 ad 23 ac 64 4e 21 cd 29 9f 60 |...g...#.dN!.).`|
-00000060 0e c1 ca 3d 25 d6 d5 2b e2 60 dc b5 57 be c0 b8 |...=%..+.`..W...|
-00000070 b6 35 25 96 5b 36 55 53 86 b7 90 ef 6c bf 45 2a |.5%.[6US....l.E*|
-00000080 3d a0 af 08 f0 8a 9c d0 d8 6b 88 14 03 03 00 01 |=........k......|
-00000090 01 16 03 03 00 30 c5 0f b8 12 c6 5a 42 6a d8 3f |.....0.....ZBj.?|
-000000a0 f5 49 e4 9a 5d b7 93 90 e7 09 1f 68 40 9d 33 a9 |.I..]......h@.3.|
-000000b0 21 fa 9c 12 c7 7c d4 bf 91 c2 f8 ac 27 b9 8b b6 |!....|......'...|
-000000c0 34 6e f3 c0 fb 83 |4n....|
+00000000 16 03 03 00 86 10 00 00 82 00 80 4d c2 e0 9b 40 |...........M...@|
+00000010 44 52 aa 55 06 71 0b bc 17 89 3a 94 d8 d0 1d ed |DR.U.q....:.....|
+00000020 70 d3 21 30 1b be 97 e0 72 30 60 05 de 9a a9 dd |p.!0....r0`.....|
+00000030 8c 0c 81 78 3a 15 9c 1c c6 22 81 0a 10 57 d1 9a |...x:...."...W..|
+00000040 17 5c 74 9e 58 79 4b f1 70 d9 d9 21 d8 79 64 fa |.\t.XyK.p..!.yd.|
+00000050 aa a5 e6 93 2a 16 57 23 a7 17 fb 71 b6 c2 d3 5b |....*.W#...q...[|
+00000060 3d 22 50 16 47 17 5f 15 e8 f1 30 da 10 69 84 25 |="P.G._...0..i.%|
+00000070 05 d0 b5 f0 e8 69 72 4e 93 d3 7c 1a 01 6d 37 fb |.....irN..|..m7.|
+00000080 cf e1 af f9 da dd 71 56 9b 08 24 14 03 03 00 01 |......qV..$.....|
+00000090 01 16 03 03 00 30 53 ab b5 09 5a 36 36 df b1 ed |.....0S...Z66...|
+000000a0 d2 69 5c 45 0b a9 02 8f 6d 25 d4 01 da 5f 27 ab |.i\E....m%..._'.|
+000000b0 ba 89 6e ee d8 91 24 f8 5e ca 6e 4d 51 41 88 3c |..n...$.^.nMQA.<|
+000000c0 f8 67 b4 fb d3 cb |.g....|
>>> Flow 4 (server to client)
00000000 14 03 03 00 01 01 16 03 03 00 30 00 00 00 00 00 |..........0.....|
-00000010 00 00 00 c1 a2 65 c1 36 63 85 cd ca 5a eb 50 ab |.....e.6c...Z.P.|
-00000020 bb ec 43 30 37 8f 71 b9 b7 2d 1b bb a2 88 fa d5 |..C07.q..-......|
-00000030 b4 a5 c5 4b 19 71 53 46 7d bb d0 17 03 03 00 30 |...K.qSF}......0|
-00000040 00 00 00 00 00 00 00 00 6a a1 3d c6 35 a0 58 c4 |........j.=.5.X.|
-00000050 ef 12 f2 59 1e 02 42 33 42 5f fe 87 a2 1a ce b7 |...Y..B3B_......|
-00000060 0d d2 36 7c 7f 1a 4c 79 1f 38 34 58 b3 05 fb 96 |..6|..Ly.84X....|
-00000070 15 03 03 00 20 00 00 00 00 00 00 00 00 a1 89 42 |.... ..........B|
-00000080 bc 58 1f 2f 9b c4 d7 e2 d1 ce 1c c9 e0 a5 47 be |.X./..........G.|
-00000090 63 0c a4 bf 26 |c...&|
+00000010 00 00 00 50 83 52 65 2d 6e 76 aa 8d 2d 46 06 12 |...P.Re-nv..-F..|
+00000020 1a e7 25 79 28 61 9e 2d 07 0b fb 3c 77 38 d8 b0 |..%y(a.-...<w8..|
+00000030 af ca 86 8a 51 07 4d 83 39 81 9b 17 03 03 00 30 |....Q.M.9......0|
+00000040 00 00 00 00 00 00 00 00 a1 ea 74 b2 7b fc 3f 9d |..........t.{.?.|
+00000050 bc eb 9d 09 a2 56 4a ff d4 fd 00 23 0b e6 69 62 |.....VJ....#..ib|
+00000060 0e 4c 82 43 3f 21 8f b8 fd 5c ce 37 6c 57 d2 98 |.L.C?!...\.7lW..|
+00000070 15 03 03 00 20 00 00 00 00 00 00 00 00 dc 47 cc |.... .........G.|
+00000080 34 eb 9e 7f d0 8f 5a 32 e6 6d 76 15 18 cc 8d 21 |4.....Z2.mv....!|
+00000090 43 91 81 31 81 |C..1.|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 5a 01 00 00 56 03 03 be 9a 2f 46 66 |....Z...V..../Ff|
-00000010 a3 b3 10 62 63 b6 32 cb de 1e eb 76 13 50 60 d0 |...bc.2....v.P`.|
-00000020 ee 40 a9 cd 50 ae d8 86 10 37 8b 00 00 04 00 2f |.@..P....7...../|
-00000030 00 ff 01 00 00 29 00 0d 00 20 00 1e 06 01 06 02 |.....)... ......|
-00000040 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 |................|
-00000050 03 02 03 03 02 01 02 02 02 03 00 0f 00 01 01 |...............|
+00000000 16 03 01 00 5b 01 00 00 57 03 03 5a ba 29 44 35 |....[...W..Z.)D5|
+00000010 c4 48 64 61 06 84 70 5c b5 65 ad 01 9b b2 29 0d |.Hda..p\.e....).|
+00000020 d1 46 17 3a 27 fb 92 d8 aa 21 aa 00 00 04 00 2f |.F.:'....!...../|
+00000030 00 ff 02 01 00 00 29 00 0d 00 20 00 1e 06 01 06 |......)... .....|
+00000040 02 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 |................|
+00000050 01 03 02 03 03 02 01 02 02 02 03 00 0f 00 01 01 |................|
>>> Flow 2 (server to client)
00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000002a0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 03 00 |..A4......9.....|
000002b0 04 0e 00 00 00 |.....|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 86 10 00 00 82 00 80 61 b4 31 93 2b |...........a.1.+|
-00000010 d5 e8 06 74 b1 f6 d6 5f a3 92 78 b6 cf bf 7f ea |...t..._..x.....|
-00000020 a2 07 1e 90 94 68 5b 19 ae d4 e3 11 78 96 58 fd |.....h[.....x.X.|
-00000030 96 18 f2 09 58 dc 39 a1 d9 9e 83 f0 24 45 6e 6b |....X.9.....$Enk|
-00000040 e6 5e e7 cb 94 42 00 10 64 d5 d2 bc 80 23 bd fe |.^...B..d....#..|
-00000050 5c 3e 3a 80 ff 38 b8 dc ff 25 ba b0 0a cc ef 94 |\>:..8...%......|
-00000060 a1 31 bd 04 93 91 86 6e 8b fd a1 9d 01 ee 91 a6 |.1.....n........|
-00000070 44 8b 21 55 52 67 3e b1 e4 6e bd 1f 07 85 e1 97 |D.!URg>..n......|
-00000080 7f 55 70 00 5f f4 4b e6 50 45 f7 14 03 03 00 01 |.Up._.K.PE......|
-00000090 01 16 03 03 00 40 71 ff ab 6d 79 3c da dc 5b 34 |.....@q..my<..[4|
-000000a0 48 39 48 08 e3 29 cb 53 21 fd 67 93 0b f8 81 47 |H9H..).S!.g....G|
-000000b0 40 7f 23 50 5f 94 db 2b 7b 7e 9f 0b bf 38 59 d9 |@.#P_..+{~...8Y.|
-000000c0 6b 57 8f 1e 83 eb 93 2c 62 12 31 c6 f5 21 f2 22 |kW.....,b.1..!."|
-000000d0 7a 82 e9 e6 ec 38 |z....8|
+00000000 16 03 03 00 86 10 00 00 82 00 80 ad e8 09 aa 07 |................|
+00000010 c0 3c 8b 39 d2 a8 bd ca 59 eb cf 0a de 33 3e d2 |.<.9....Y....3>.|
+00000020 4f 76 1f 7a 96 50 b3 52 6b 04 9e 6f f1 06 2b 4a |Ov.z.P.Rk..o..+J|
+00000030 7f 01 f2 51 a3 a7 1e f6 20 a7 27 4e 97 68 61 98 |...Q.... .'N.ha.|
+00000040 9f fd bd aa e8 e6 80 4d 9a 65 51 35 11 44 e4 2c |.......M.eQ5.D.,|
+00000050 a2 47 33 d1 b6 b7 d5 40 c0 17 34 ff e2 12 8e 00 |.G3....@..4.....|
+00000060 41 e6 4f 3e 56 2f d9 30 6b d9 99 e3 9f ce 10 ba |A.O>V/.0k.......|
+00000070 7c 95 3b 49 c9 5f 1e 97 37 90 e4 da 9a e0 01 5f ||.;I._..7......_|
+00000080 b8 6f 95 19 40 0f ca 63 76 6b 2a 14 03 03 00 01 |.o..@..cvk*.....|
+00000090 01 16 03 03 00 40 86 cb f5 69 1b ee 67 6e 3b be |.....@...i..gn;.|
+000000a0 e0 de 22 06 8c d4 f4 98 a6 45 1c 2f e5 f0 b4 25 |.."......E./...%|
+000000b0 f4 c0 87 7f e8 1c 2c 1d 20 52 50 fe dc a3 0c 22 |......,. RP...."|
+000000c0 b7 7f d3 9c 42 b8 23 d0 3e fd 93 be a2 50 28 dd |....B.#.>....P(.|
+000000d0 79 f3 c6 90 c7 bb |y.....|
>>> Flow 4 (server to client)
00000000 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 00 |..........@.....|
-00000010 00 00 00 00 00 00 00 00 00 00 00 45 87 33 41 c1 |...........E.3A.|
-00000020 b8 e7 4c 11 1c 1b 7b 55 51 85 06 01 c1 b6 87 6b |..L...{UQ......k|
-00000030 01 b3 56 c4 5a 37 ea b6 3a c4 b0 da 1b 5c 15 d4 |..V.Z7..:....\..|
-00000040 03 5a 57 e9 9a 56 16 a5 fa 77 1c 17 03 03 00 40 |.ZW..V...w.....@|
+00000010 00 00 00 00 00 00 00 00 00 00 00 70 e5 19 ef 25 |...........p...%|
+00000020 05 0b 02 79 2b 79 49 e6 2c ad c0 e7 03 b3 40 68 |...y+yI.,.....@h|
+00000030 67 98 31 7c 7e 85 86 a8 5c de 72 3f d1 59 12 20 |g.1|~...\.r?.Y. |
+00000040 87 95 44 57 64 35 03 f5 68 61 20 17 03 03 00 40 |..DWd5..ha ....@|
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000060 6f 2e 7c ba 3d 85 4c 7b 1f 13 a5 d6 97 e6 67 f4 |o.|.=.L{......g.|
-00000070 24 d5 a8 d4 26 41 64 0a fd b3 2e a0 a2 7a 2b 54 |$...&Ad......z+T|
-00000080 a4 1d 6e fe 4c c4 73 e3 76 d0 3a 60 52 df b0 53 |..n.L.s.v.:`R..S|
+00000060 1b 17 7c bb 04 4f 31 7b da 40 5e 93 64 97 4a 8d |..|..O1{.@^.d.J.|
+00000070 98 cf 77 2d 01 53 37 53 2c 59 8f ca ac 65 ae f3 |..w-.S7S,Y...e..|
+00000080 f8 d4 ae 67 74 c8 72 21 67 51 9a 1b 71 f2 0e 04 |...gt.r!gQ..q...|
00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........|
-000000a0 00 00 00 00 00 8b 0a 6d 14 3b 84 bc 7d c6 8d 9d |.......m.;..}...|
-000000b0 d5 27 32 84 4b 14 75 42 0f aa 5e 88 ba fa a2 c7 |.'2.K.uB..^.....|
-000000c0 16 93 8a c4 fd |.....|
+000000a0 00 00 00 00 00 fd 36 99 3d c7 44 1b 30 39 4a a7 |......6.=.D.09J.|
+000000b0 40 43 e3 01 2b 22 3d c6 8c a1 0d 73 d5 16 d2 25 |@C..+"=....s...%|
+000000c0 19 c8 d7 76 ee |...v.|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 9a 01 00 00 96 03 03 16 dc f8 f5 3a |...............:|
-00000010 13 32 e6 1f bd f6 3c 66 b7 4c 67 17 ee b2 2a ba |.2....<f.Lg...*.|
-00000020 68 5b 8e b1 7c 8f 71 d6 6c 30 e1 00 00 04 c0 2f |h[..|.q.l0...../|
-00000030 00 ff 01 00 00 69 00 0b 00 04 03 00 01 02 00 0a |.....i..........|
-00000040 00 34 00 32 00 0e 00 0d 00 19 00 0b 00 0c 00 18 |.4.2............|
-00000050 00 09 00 0a 00 16 00 17 00 08 00 06 00 07 00 14 |................|
-00000060 00 15 00 04 00 05 00 12 00 13 00 01 00 02 00 03 |................|
-00000070 00 0f 00 10 00 11 00 0d 00 20 00 1e 06 01 06 02 |......... ......|
-00000080 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 |................|
-00000090 03 02 03 03 02 01 02 02 02 03 00 0f 00 01 01 |...............|
+00000000 16 03 01 00 83 01 00 00 7f 03 03 19 c7 02 a0 bf |................|
+00000010 5a fb c2 d4 f5 68 0a 19 0f 5e 3a 6b c5 88 17 0b |Z....h...^:k....|
+00000020 35 ff df ee 06 32 ad 32 99 0e c9 00 00 04 c0 2f |5....2.2......./|
+00000030 00 ff 02 01 00 00 51 00 0b 00 04 03 00 01 02 00 |......Q.........|
+00000040 0a 00 1c 00 1a 00 17 00 19 00 1c 00 1b 00 18 00 |................|
+00000050 1a 00 16 00 0e 00 0d 00 0b 00 0c 00 09 00 0a 00 |................|
+00000060 0d 00 20 00 1e 06 01 06 02 06 03 05 01 05 02 05 |.. .............|
+00000070 03 04 01 04 02 04 03 03 01 03 02 03 03 02 01 02 |................|
+00000080 02 02 03 00 0f 00 01 01 |........|
>>> Flow 2 (server to client)
00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000002c0 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd a7 |Q.5uq..T[....g..|
000002d0 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e f1 |$ >.V...(^.+-O..|
000002e0 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 |..lK[.V.2B.X..I.|
-000002f0 b5 68 1a 41 03 56 6b dc 5a 89 05 01 00 80 40 b3 |.h.A.Vk.Z.....@.|
-00000300 66 ee 53 3c 80 f4 da d1 de e6 fe 50 c8 89 60 d5 |f.S<.......P..`.|
-00000310 e4 80 73 39 91 79 6c cf 89 bb a5 da e4 c7 e5 0d |..s9.yl.........|
-00000320 13 a6 76 24 65 1a a2 b8 cb 95 c2 c6 9d 66 74 57 |..v$e........ftW|
-00000330 9e 90 4f 48 77 88 3a b4 f3 fa 88 ab 61 22 d3 40 |..OHw.:.....a".@|
-00000340 08 c4 0a 69 19 ed c3 ea d8 15 79 12 d5 ac 8d af |...i......y.....|
-00000350 41 7d 87 4b a9 ff f8 cb 24 55 88 38 34 11 a5 bd |A}.K....$U.84...|
-00000360 c1 d6 e5 86 d5 64 b5 f2 df c8 03 f2 a2 6b ff f4 |.....d.......k..|
-00000370 a8 38 e0 18 04 d4 cd bd e0 cc 63 fc 3f 8b 16 03 |.8........c.?...|
+000002f0 b5 68 1a 41 03 56 6b dc 5a 89 05 01 00 80 97 53 |.h.A.Vk.Z......S|
+00000300 cc 1f a2 55 e2 52 69 a6 b3 78 4f 7e 34 3e 37 e4 |...U.Ri..xO~4>7.|
+00000310 e0 bb 15 ff 96 f8 1d 9c 11 03 2c 68 ca 6d 2b 3c |..........,h.m+<|
+00000320 b3 96 64 21 d6 3f 81 42 07 c0 1b 85 7e a9 65 54 |..d!.?.B....~.eT|
+00000330 23 89 33 c1 71 b9 29 72 47 8a 0e 71 75 20 d7 b6 |#.3.q.)rG..qu ..|
+00000340 9d c2 ac c1 a8 dc 6c 0e 7e 29 93 fc b2 68 83 2e |......l.~)...h..|
+00000350 e1 fe e5 eb 54 d7 c3 30 f2 8f 9d 91 49 48 4f 84 |....T..0....IHO.|
+00000360 1a d5 47 75 27 bf c8 09 65 4a a8 7c 65 a0 d0 23 |..Gu'...eJ.|e..#|
+00000370 9f 26 d6 57 62 cb e1 06 64 90 16 73 1b d4 16 03 |.&.Wb...d..s....|
00000380 03 00 04 0e 00 00 00 |.......|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 46 10 00 00 42 41 04 de de ff 8c df |....F...BA......|
-00000010 d8 4c 72 af 29 3c 4d e0 ed 0f 34 cc fd 2d 52 63 |.Lr.)<M...4..-Rc|
-00000020 94 e8 74 f1 0b 18 69 28 ed 1e f7 62 4e 4f 2c 14 |..t...i(...bNO,.|
-00000030 61 4b 9f 55 d8 70 59 8f 4b a8 ab c6 d2 cd aa 59 |aK.U.pY.K......Y|
-00000040 8a ef 9b b3 f6 ba 52 e5 51 bb a1 14 03 03 00 01 |......R.Q.......|
-00000050 01 16 03 03 00 28 44 1c eb 89 59 bb ad fb 9f 3f |.....(D...Y....?|
-00000060 56 06 54 ae 27 6d e4 47 3c 0c 60 30 db 0e d6 0e |V.T.'m.G<.`0....|
-00000070 9d 0d a9 a0 e7 25 26 6e 99 d0 8f e0 1b 9d |.....%&n......|
+00000000 16 03 03 00 46 10 00 00 42 41 04 1a 94 a7 1a 36 |....F...BA.....6|
+00000010 d1 ca ad d7 e8 64 03 84 b4 a6 9f dc 30 a2 a3 60 |.....d......0..`|
+00000020 a0 5a 1f a0 3d 8e d1 b8 96 75 37 ee a6 3f d6 ad |.Z..=....u7..?..|
+00000030 93 b6 7d 58 99 53 04 4b 6e c6 7f 04 bf 60 f9 ba |..}X.S.Kn....`..|
+00000040 e7 b8 04 73 10 77 ff 22 93 b2 7b 14 03 03 00 01 |...s.w."..{.....|
+00000050 01 16 03 03 00 28 29 6b 2b 14 21 a7 e4 84 c0 9d |.....()k+.!.....|
+00000060 92 07 cd dd 0b eb c1 b0 76 06 71 48 46 93 b8 05 |........v.qHF...|
+00000070 1a 2b 53 14 da 34 ac 05 4c cc 4d 47 12 28 |.+S..4..L.MG.(|
>>> Flow 4 (server to client)
00000000 14 03 03 00 01 01 16 03 03 00 28 00 00 00 00 00 |..........(.....|
-00000010 00 00 00 92 90 01 f0 70 fa 57 2e 40 d3 4c ef 6a |.......p.W.@.L.j|
-00000020 03 0c 56 65 f7 c0 3b d0 8a db 48 c9 ae 58 3e 7c |..Ve..;...H..X>||
-00000030 d1 48 67 17 03 03 00 25 00 00 00 00 00 00 00 01 |.Hg....%........|
-00000040 9e 35 a0 13 73 da 3f 26 ff 1d 90 08 e9 cc 40 7e |.5..s.?&......@~|
-00000050 82 f3 5e 6e b4 8e 5a 39 7f a4 09 60 b2 15 03 03 |..^n..Z9...`....|
-00000060 00 1a 00 00 00 00 00 00 00 02 04 95 9b 2d 17 1c |.............-..|
-00000070 6a bc 26 f7 6c 8e f1 c0 0e 82 4a 44 |j.&.l.....JD|
+00000010 00 00 00 b9 c9 6f cb 58 df 1c a1 0a 79 4e fa 8f |.....o.X....yN..|
+00000020 41 55 8a 0a f8 d1 83 88 28 fb 44 00 8a a5 11 39 |AU......(.D....9|
+00000030 5b d4 83 17 03 03 00 25 00 00 00 00 00 00 00 01 |[......%........|
+00000040 85 4f 2a 54 aa c0 ce 7b 1e 4e e4 64 56 57 68 5e |.O*T...{.N.dVWh^|
+00000050 fa 41 67 8a da 9d f4 78 a6 c6 13 76 7c 15 03 03 |.Ag....x...v|...|
+00000060 00 1a 00 00 00 00 00 00 00 02 38 71 21 c6 82 bc |..........8q!...|
+00000070 2e 37 14 1d 15 2f 74 9d 7c 99 d8 66 |.7.../t.|..f|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 9a 01 00 00 96 03 03 5d 6b 2a ff 74 |...........]k*.t|
-00000010 88 f1 68 8d 1b eb c3 84 34 b5 19 0a 7d f1 9a 0f |..h.....4...}...|
-00000020 4d c3 0a d7 98 b8 72 e0 73 e4 38 00 00 04 c0 30 |M.....r.s.8....0|
-00000030 00 ff 01 00 00 69 00 0b 00 04 03 00 01 02 00 0a |.....i..........|
-00000040 00 34 00 32 00 0e 00 0d 00 19 00 0b 00 0c 00 18 |.4.2............|
-00000050 00 09 00 0a 00 16 00 17 00 08 00 06 00 07 00 14 |................|
-00000060 00 15 00 04 00 05 00 12 00 13 00 01 00 02 00 03 |................|
-00000070 00 0f 00 10 00 11 00 0d 00 20 00 1e 06 01 06 02 |......... ......|
-00000080 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 |................|
-00000090 03 02 03 03 02 01 02 02 02 03 00 0f 00 01 01 |...............|
+00000000 16 03 01 00 83 01 00 00 7f 03 03 55 9b 71 e2 46 |...........U.q.F|
+00000010 88 58 c4 16 6a 6e 14 3d 3a 5a f9 fe ec 68 71 24 |.X..jn.=:Z...hq$|
+00000020 d0 06 6f a1 56 8f d6 15 42 6b ba 00 00 04 c0 30 |..o.V...Bk.....0|
+00000030 00 ff 02 01 00 00 51 00 0b 00 04 03 00 01 02 00 |......Q.........|
+00000040 0a 00 1c 00 1a 00 17 00 19 00 1c 00 1b 00 18 00 |................|
+00000050 1a 00 16 00 0e 00 0d 00 0b 00 0c 00 09 00 0a 00 |................|
+00000060 0d 00 20 00 1e 06 01 06 02 06 03 05 01 05 02 05 |.. .............|
+00000070 03 04 01 04 02 04 03 03 01 03 02 03 03 02 01 02 |................|
+00000080 02 02 03 00 0f 00 01 01 |........|
>>> Flow 2 (server to client)
00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000002c0 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd a7 |Q.5uq..T[....g..|
000002d0 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e f1 |$ >.V...(^.+-O..|
000002e0 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 |..lK[.V.2B.X..I.|
-000002f0 b5 68 1a 41 03 56 6b dc 5a 89 05 01 00 80 22 6b |.h.A.Vk.Z....."k|
-00000300 87 4b f8 ba f2 09 91 ee ce 81 67 d4 fd d8 b5 07 |.K........g.....|
-00000310 fe c3 88 96 ca e3 3a f0 87 cc ae 44 94 8e 8f 70 |......:....D...p|
-00000320 79 cd de a2 26 4e 17 45 d7 ea 0f 95 a6 c9 7b 17 |y...&N.E......{.|
-00000330 68 7c f5 e8 6c d5 87 6d 5a 7e 53 af 95 0c 42 91 |h|..l..mZ~S...B.|
-00000340 c0 07 18 75 fd 74 1c ad ef df f8 41 b1 ad fc 36 |...u.t.....A...6|
-00000350 19 31 cf c8 3f 36 55 dd 54 ac 44 a9 3a d1 ae 23 |.1..?6U.T.D.:..#|
-00000360 0a 18 bf b7 6f c7 bc a6 70 50 5e 50 dd da ff 5b |....o...pP^P...[|
-00000370 67 7d 0a f5 70 a0 8c 88 d9 38 d4 bf a9 c3 16 03 |g}..p....8......|
+000002f0 b5 68 1a 41 03 56 6b dc 5a 89 05 01 00 80 7f 44 |.h.A.Vk.Z......D|
+00000300 af 7b 21 01 6b f0 1c 75 d3 6b 28 99 68 e1 0e d3 |.{!.k..u.k(.h...|
+00000310 a8 cb 5a 2e 23 ad d7 92 73 46 5b 66 88 bd f1 d6 |..Z.#...sF[f....|
+00000320 5d 52 d1 07 53 88 9c 64 e3 ce 80 b3 39 7f 9e 2b |]R..S..d....9..+|
+00000330 0a 02 a7 e1 3e 00 70 51 3b b4 52 d1 3c 4a e9 f7 |....>.pQ;.R.<J..|
+00000340 0f 85 fa ff d7 ba 96 fc 77 8e 66 8d c6 4c b8 c2 |........w.f..L..|
+00000350 a5 d3 ad 72 f0 8c ba d2 bf 1c 81 7b 4e d5 9e 80 |...r.......{N...|
+00000360 7e b2 90 a0 2f d6 ad c2 33 43 da 46 b0 22 40 ff |~.../...3C.F."@.|
+00000370 df 95 b3 1e f1 97 b9 7b 61 3c 78 d9 ae cb 16 03 |.......{a<x.....|
00000380 03 00 04 0e 00 00 00 |.......|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 46 10 00 00 42 41 04 d0 f7 11 ae 9f |....F...BA......|
-00000010 ec 2e ac 8e 97 6c 58 0e 57 32 8e ac fa 3e af 36 |.....lX.W2...>.6|
-00000020 22 e1 41 2b d3 d1 9c c2 1d 51 c0 e4 20 b3 4c 85 |".A+.....Q.. .L.|
-00000030 b8 bd f2 d1 c6 2f 7d 83 c7 43 d9 31 36 1a 83 ca |...../}..C.16...|
-00000040 c6 89 f8 ba 8c d1 7e 99 04 6e 92 14 03 03 00 01 |......~..n......|
-00000050 01 16 03 03 00 28 32 67 c1 6e 5e 1e 4b 51 1b 70 |.....(2g.n^.KQ.p|
-00000060 54 b9 1d 69 79 38 bd fa 7c 6b 58 71 af 72 08 2d |T..iy8..|kXq.r.-|
-00000070 55 df 24 be 5b 41 0a ef 0e 90 cf d9 62 81 |U.$.[A......b.|
+00000000 16 03 03 00 46 10 00 00 42 41 04 d8 85 85 d2 78 |....F...BA.....x|
+00000010 27 a5 0a bb 10 67 ec a9 d8 11 f0 ba b9 d7 21 39 |'....g........!9|
+00000020 ed c7 0a a0 a2 69 ab fb 9b 15 e0 d7 ec ca 97 c8 |.....i..........|
+00000030 c0 b2 66 0b 2c 68 37 ac f0 34 fa 3a 07 dd f2 ae |..f.,h7..4.:....|
+00000040 8e f6 e3 eb de 08 1f 56 e5 66 eb 14 03 03 00 01 |.......V.f......|
+00000050 01 16 03 03 00 28 f5 2d 89 00 0c 9d d9 0e 54 1b |.....(.-......T.|
+00000060 71 84 4d c7 bb 98 36 8c 29 b6 06 d8 7b df d9 92 |q.M...6.)...{...|
+00000070 01 00 16 44 5e e3 db f3 8f b7 fa 43 0c f7 |...D^......C..|
>>> Flow 4 (server to client)
00000000 14 03 03 00 01 01 16 03 03 00 28 00 00 00 00 00 |..........(.....|
-00000010 00 00 00 87 2a 3e 09 54 54 c3 58 c0 5b 7b 91 00 |....*>.TT.X.[{..|
-00000020 c4 07 98 9e de 1f f8 04 bb d7 42 04 55 7d 18 a4 |..........B.U}..|
-00000030 41 7c a6 17 03 03 00 25 00 00 00 00 00 00 00 01 |A|.....%........|
-00000040 ab 23 05 51 b4 60 a2 77 01 58 be a6 9f 89 2b b5 |.#.Q.`.w.X....+.|
-00000050 77 6b 19 23 67 f7 89 f1 ef d6 1b f5 e7 15 03 03 |wk.#g...........|
-00000060 00 1a 00 00 00 00 00 00 00 02 8a bf f0 fb 9f 56 |...............V|
-00000070 36 f1 92 49 a9 e5 40 87 f9 87 9e 4d |6..I..@....M|
+00000010 00 00 00 a4 82 dc d1 67 ed 17 ae 22 13 0d ac d2 |.......g..."....|
+00000020 f4 58 44 5b b4 c6 25 29 80 b6 bc 63 0e 67 22 6e |.XD[..%)...c.g"n|
+00000030 18 92 48 17 03 03 00 25 00 00 00 00 00 00 00 01 |..H....%........|
+00000040 a0 fe 37 25 fb 4d 29 96 f9 01 67 19 d8 83 26 68 |..7%.M)...g...&h|
+00000050 d0 e8 58 2c ef 90 a3 b5 26 51 26 a9 28 15 03 03 |..X,....&Q&.(...|
+00000060 00 1a 00 00 00 00 00 00 00 02 91 4b d5 54 4a ef |...........K.TJ.|
+00000070 22 88 ab b7 a2 bb 20 5a b2 3e 7b 36 |"..... Z.>{6|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 5a 01 00 00 56 03 03 8a fe f5 09 70 |....Z...V......p|
-00000010 8e 6b e3 2b 12 ff d1 b2 ae 15 bf 47 0e ca 5c b5 |.k.+.......G..\.|
-00000020 bb 0e ad af e5 a6 7e 36 c5 a4 c3 00 00 04 00 05 |......~6........|
-00000030 00 ff 01 00 00 29 00 0d 00 20 00 1e 06 01 06 02 |.....)... ......|
-00000040 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 |................|
-00000050 03 02 03 03 02 01 02 02 02 03 00 0f 00 01 01 |...............|
+00000000 16 03 01 00 5b 01 00 00 57 03 03 ec 96 78 51 74 |....[...W....xQt|
+00000010 1b f2 21 ad f2 4f 50 aa 67 f1 20 e2 4f d3 4d 0e |..!..OP.g. .O.M.|
+00000020 54 91 df 91 d8 81 e3 75 bb 20 c2 00 00 04 00 05 |T......u. ......|
+00000030 00 ff 02 01 00 00 29 00 0d 00 20 00 1e 06 01 06 |......)... .....|
+00000040 02 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 |................|
+00000050 01 03 02 03 03 02 01 02 02 02 03 00 0f 00 01 01 |................|
>>> Flow 2 (server to client)
00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000002a0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 03 00 |..A4......9.....|
000002b0 04 0e 00 00 00 |.....|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 86 10 00 00 82 00 80 1c f7 2c 18 38 |.............,.8|
-00000010 d9 41 b5 ab b7 35 2b 75 2d 66 ba c8 70 c2 19 1c |.A...5+u-f..p...|
-00000020 f2 6d d9 a9 a8 40 8e b5 2c 75 99 06 a5 25 be 0d |.m...@..,u...%..|
-00000030 b4 b0 9b aa fc 6b 12 a5 b3 e7 02 60 aa 25 e9 7f |.....k.....`.%..|
-00000040 6b f5 c4 7a 1d 16 a5 d1 76 cc d5 a1 18 68 91 c3 |k..z....v....h..|
-00000050 57 b8 10 f2 b8 81 f3 1b 74 ef 6c 37 3e 81 41 09 |W.......t.l7>.A.|
-00000060 2a c5 15 e6 cc bb 74 4c 01 7a b9 82 5c e2 7f b7 |*.....tL.z..\...|
-00000070 ac 2d 76 30 18 30 c2 19 8c 5f f2 80 41 89 bb 47 |.-v0.0..._..A..G|
-00000080 28 3d 61 cc 3c 06 a8 76 93 57 71 14 03 03 00 01 |(=a.<..v.Wq.....|
-00000090 01 16 03 03 00 24 46 34 1f cc eb 53 c7 d2 04 28 |.....$F4...S...(|
-000000a0 b6 3d 3f 39 06 70 56 b7 db eb 53 9c 66 c3 45 9f |.=?9.pV...S.f.E.|
-000000b0 69 ca 58 8f e7 ba a7 e6 5a 97 |i.X.....Z.|
+00000000 16 03 03 00 86 10 00 00 82 00 80 05 4b 04 74 76 |............K.tv|
+00000010 73 3a 92 04 4d 8b 3b 59 c2 43 c5 f4 07 e8 bc a3 |s:..M.;Y.C......|
+00000020 62 44 b7 80 9f 8f bc 43 8a 67 09 64 a7 93 9f f9 |bD.....C.g.d....|
+00000030 2c 55 03 4b e5 87 9d 18 a2 c3 48 4f 02 6e e0 23 |,U.K......HO.n.#|
+00000040 0b 2f 57 81 e4 38 50 11 d6 b1 71 4f c2 e5 a4 03 |./W..8P...qO....|
+00000050 34 a4 eb a1 42 47 79 05 bc 7b b8 26 5b c1 f9 82 |4...BGy..{.&[...|
+00000060 fc 58 49 eb 04 52 fe 57 3c ed 5c 2b d8 fe 49 d7 |.XI..R.W<.\+..I.|
+00000070 d2 2e 6c e8 74 74 0d 87 b3 f6 2d f0 ff 03 f0 2d |..l.tt....-....-|
+00000080 c8 a2 20 89 3f 3f 11 e1 fb 93 85 14 03 03 00 01 |.. .??..........|
+00000090 01 16 03 03 00 24 9a 81 c0 9e 76 b6 3d 78 37 8e |.....$....v.=x7.|
+000000a0 ab 33 48 93 bb 0d f4 86 3c ff 72 28 10 35 c2 10 |.3H.....<.r(.5..|
+000000b0 f0 a0 ff 0c 20 f3 c4 29 83 a6 |.... ..)..|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 24 78 c3 02 89 60 |..........$x...`|
-00000010 e7 72 9f 51 87 14 ca 2e 0d 79 98 eb 1e 39 62 f9 |.r.Q.....y...9b.|
-00000020 fc a5 c9 2c f8 0c 04 16 60 70 90 b7 31 f8 30 17 |...,....`p..1.0.|
-00000030 03 03 00 21 6a b7 24 73 a7 0d 17 04 d7 54 a8 ea |...!j.$s.....T..|
-00000040 28 4e f2 0a ef 87 d5 a9 b8 84 81 46 8e 97 d1 ae |(N.........F....|
-00000050 3c cc b1 6b 72 15 03 03 00 16 1a bb 2f df ae 3e |<..kr......./..>|
-00000060 a7 89 69 3e 35 f2 f6 cd 35 60 29 3a 6f be 32 0d |..i>5...5`):o.2.|
+00000000 14 03 03 00 01 01 16 03 03 00 24 93 15 62 c5 2b |..........$..b.+|
+00000010 4f 8a d7 0f 70 1f 9d 11 fc 8f 9a a9 b7 d7 44 50 |O...p.........DP|
+00000020 6e 0e 5b d7 3b de 15 7d 17 35 31 42 1f a4 40 17 |n.[.;..}.51B..@.|
+00000030 03 03 00 21 a9 ca 73 e9 ce 2d 21 ef 7d bc 40 91 |...!..s..-!.}.@.|
+00000040 41 c9 53 62 af 09 8e b4 37 0f fa ab b7 76 8f 5b |A.Sb....7....v.[|
+00000050 7d 0f 04 48 49 15 03 03 00 16 76 b1 d7 91 88 6f |}..HI.....v....o|
+00000060 b4 e7 a4 f1 d2 c2 ac 50 db 31 ae 5c f7 53 a1 68 |.......P.1.\.S.h|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 f6 01 00 00 f2 03 03 53 1e 13 2e bd |...........S....|
-00000010 ad 66 fd 77 1a ad 5f 4d cb bd 2e ca b5 c2 45 1d |.f.w.._M......E.|
-00000020 7c 83 9d 62 3e 39 9c ce 78 99 e7 20 b4 06 b0 ec ||..b>9..x.. ....|
-00000030 cf b7 52 6e 38 10 31 37 b2 e6 58 0f fa e3 b0 cb |..Rn8.17..X.....|
-00000040 20 a4 d2 4b f3 7d 92 e6 7e 13 37 08 00 04 00 05 | ..K.}..~.7.....|
-00000050 00 ff 01 00 00 a5 00 23 00 78 50 46 ad c1 db a8 |.......#.xPF....|
-00000060 38 86 7b 2b bb fd d0 c3 42 3e 00 00 00 00 00 00 |8.{+....B>......|
-00000070 00 00 00 00 00 00 00 00 00 00 94 6f 2c b5 83 61 |...........o,..a|
-00000080 c4 74 90 94 e5 6c fd 70 64 57 3a 25 78 bf 9f a0 |.t...l.pdW:%x...|
-00000090 7c 51 bc 2a 69 1e b3 fd 71 34 b7 9a ef cb 49 37 ||Q.*i...q4....I7|
-000000a0 f8 5d 5e 7c cf 6d fc 13 c1 52 79 8e ed c3 84 01 |.]^|.m...Ry.....|
-000000b0 33 94 10 65 34 64 5e b4 9c 07 46 5b 9e d7 5e 55 |3..e4d^...F[..^U|
-000000c0 df fd c0 e9 d2 e8 d3 c6 42 18 ef a5 6c be e8 d2 |........B...l...|
-000000d0 49 c6 00 0d 00 20 00 1e 06 01 06 02 06 03 05 01 |I.... ..........|
-000000e0 05 02 05 03 04 01 04 02 04 03 03 01 03 02 03 03 |................|
-000000f0 02 01 02 02 02 03 00 0f 00 01 01 |...........|
+00000000 16 03 01 00 f7 01 00 00 f3 03 03 35 70 0b ed 1c |...........5p...|
+00000010 83 57 b1 7b 0a 47 ce d4 07 3a 49 96 93 4c a1 83 |.W.{.G...:I..L..|
+00000020 4b ab b7 ab 7d b0 14 be dd 91 92 20 09 34 b7 de |K...}...... .4..|
+00000030 bd 43 e8 cd 8e f3 43 aa 04 64 8f 0a 55 a6 58 ed |.C....C..d..U.X.|
+00000040 31 8b 3d 4c 84 4f 2c 6d b0 b1 75 6f 00 04 00 05 |1.=L.O,m..uo....|
+00000050 00 ff 02 01 00 00 a5 00 23 00 78 50 46 ad c1 db |........#.xPF...|
+00000060 a8 38 86 7b 2b bb fd d0 c3 42 3e 00 00 00 00 00 |.8.{+....B>.....|
+00000070 00 00 00 00 00 00 00 00 00 00 00 94 6f 2c b5 83 |............o,..|
+00000080 61 4d 51 5f 33 46 48 fe 9e e9 83 f4 b1 aa c9 b1 |aMQ_3FH.........|
+00000090 61 2a b2 9d 0f 17 c4 09 f6 26 7a 75 f1 19 99 db |a*.......&zu....|
+000000a0 36 d8 32 f0 94 61 4f 8f ed 80 33 51 f3 c6 15 84 |6.2..aO...3Q....|
+000000b0 6b 33 94 c8 4f 84 b7 7c 27 6d 8f fe 41 8e b2 92 |k3..O..|'m..A...|
+000000c0 ca 80 e8 6c ba 75 77 f5 3a 87 17 ae f8 b9 6b 10 |...l.uw.:.....k.|
+000000d0 f9 85 da 00 0d 00 20 00 1e 06 01 06 02 06 03 05 |...... .........|
+000000e0 01 05 02 05 03 04 01 04 02 04 03 03 01 03 02 03 |................|
+000000f0 03 02 01 02 02 02 03 00 0f 00 01 01 |............|
>>> Flow 2 (server to client)
00000000 16 03 03 00 51 02 00 00 4d 03 03 00 00 00 00 00 |....Q...M.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 20 b4 06 b0 ec |........... ....|
-00000030 cf b7 52 6e 38 10 31 37 b2 e6 58 0f fa e3 b0 cb |..Rn8.17..X.....|
-00000040 20 a4 d2 4b f3 7d 92 e6 7e 13 37 08 00 05 00 00 | ..K.}..~.7.....|
+00000020 00 00 00 00 00 00 00 00 00 00 00 20 09 34 b7 de |........... .4..|
+00000030 bd 43 e8 cd 8e f3 43 aa 04 64 8f 0a 55 a6 58 ed |.C....C..d..U.X.|
+00000040 31 8b 3d 4c 84 4f 2c 6d b0 b1 75 6f 00 05 00 00 |1.=L.O,m..uo....|
00000050 05 ff 01 00 01 00 14 03 03 00 01 01 16 03 03 00 |................|
-00000060 24 24 31 13 8c 45 4f 8a fc 71 50 94 b0 6f 02 5e |$$1..EO..qP..o.^|
-00000070 da d3 a3 13 8b c8 53 fb 54 8d ef 90 f7 55 b1 be |......S.T....U..|
-00000080 37 30 05 e5 5d |70..]|
+00000060 24 18 67 37 5a c6 ea 3f 5f 06 2d c3 f1 2a ff d3 |$.g7Z..?_.-..*..|
+00000070 45 ce fe 38 1a e6 39 25 e7 e5 01 4d 6e fd 23 af |E..8..9%...Mn.#.|
+00000080 dc 67 1b 1d e2 |.g...|
>>> Flow 3 (client to server)
-00000000 14 03 03 00 01 01 16 03 03 00 24 ed dd e4 a5 09 |..........$.....|
-00000010 0d 7c cb e4 90 9c a1 1c 21 f4 13 bd 45 8f f4 d8 |.|......!...E...|
-00000020 7e e2 89 7a 0d f4 75 99 66 8c 05 a3 1a e2 2b |~..z..u.f.....+|
+00000000 14 03 03 00 01 01 16 03 03 00 24 b5 75 e6 1d 1d |..........$.u...|
+00000010 cb 2c 5d 9f d1 07 de 23 11 84 c2 59 50 55 72 27 |.,]....#...YPUr'|
+00000020 f2 5e 34 e2 c1 53 bf 21 5f f4 c4 2c f1 e1 7a |.^4..S.!_..,..z|
>>> Flow 4 (server to client)
-00000000 17 03 03 00 21 69 fa 9e 98 fb 7a 95 b1 8e e5 74 |....!i....z....t|
-00000010 03 02 d7 3d 69 c4 b8 c9 5b 49 e3 30 32 e3 c5 6a |...=i...[I.02..j|
-00000020 fa 20 98 bd 01 ed 15 03 03 00 16 c9 b1 20 1f 30 |. ........... .0|
-00000030 c1 2f 15 75 cd 82 45 de 1a 81 cd dc 10 05 1c 45 |./.u..E........E|
-00000040 dc |.|
+00000000 17 03 03 00 21 93 92 dd 07 a3 8f 3d 34 6d b8 94 |....!......=4m..|
+00000010 a7 6f 18 27 e7 cd 30 0a 08 4f b6 9b cb 43 93 27 |.o.'..0..O...C.'|
+00000020 b6 8b 83 ae d6 8a 15 03 03 00 16 68 a1 a4 f8 66 |...........h...f|
+00000030 8a c0 e7 d3 97 83 cb 35 94 84 7a e6 47 3c 97 8c |.......5..z.G<..|
+00000040 69 |i|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 f6 01 00 00 f2 03 03 aa 0c c2 75 42 |..............uB|
-00000010 62 2a 1d 14 a0 cc a1 e4 a7 19 77 50 80 2b f8 05 |b*........wP.+..|
-00000020 0b fa 60 3a a7 a7 84 d3 e1 68 26 20 68 97 0c ae |..`:.....h& h...|
-00000030 7b 1d bc 13 14 a8 f6 c1 e1 96 1f 54 18 2c cb 99 |{..........T.,..|
-00000040 17 7d be 45 6a 39 53 c6 50 c7 8c 75 00 04 00 05 |.}.Ej9S.P..u....|
-00000050 00 ff 01 00 00 a5 00 23 00 78 50 46 ad c1 db a8 |.......#.xPF....|
-00000060 38 86 7b 2b bb fd d0 c3 42 3e 00 00 00 00 00 00 |8.{+....B>......|
-00000070 00 00 00 00 00 00 00 00 00 00 94 6f 2c b5 83 61 |...........o,..a|
-00000080 bd 50 da 49 7f 8b 8f 58 57 00 a1 11 0d 4a 9d 8a |.P.I...XW....J..|
-00000090 39 dd 85 23 c0 eb 9d 1a 45 93 92 e7 af 15 a3 a4 |9..#....E.......|
-000000a0 48 da f9 a4 d8 8e cb 6c 3d 44 77 f9 c4 83 89 85 |H......l=Dw.....|
-000000b0 33 94 c1 c6 20 9a 73 44 83 89 5e 59 ee 05 c6 7e |3... .sD..^Y...~|
-000000c0 8d e9 7d 7b f8 84 46 b6 7d 43 ec f1 af 1f 0f 35 |..}{..F.}C.....5|
-000000d0 b4 1c 00 0d 00 20 00 1e 06 01 06 02 06 03 05 01 |..... ..........|
-000000e0 05 02 05 03 04 01 04 02 04 03 03 01 03 02 03 03 |................|
-000000f0 02 01 02 02 02 03 00 0f 00 01 01 |...........|
+00000000 16 03 01 00 f7 01 00 00 f3 03 03 2b 89 3f 02 47 |...........+.?.G|
+00000010 f6 14 64 3b 64 08 84 6e 9c e1 c9 4d 4f 30 92 06 |..d;d..n...MO0..|
+00000020 d1 19 58 5d 93 30 41 4d a6 2c f6 20 53 3c e7 f4 |..X].0AM.,. S<..|
+00000030 23 7e 59 b1 32 c4 2d db 0b 6f ab 64 4a 72 c9 31 |#~Y.2.-..o.dJr.1|
+00000040 d9 b9 38 a8 b4 4e 0c 39 f8 f4 61 7a 00 04 00 05 |..8..N.9..az....|
+00000050 00 ff 02 01 00 00 a5 00 23 00 78 50 46 ad c1 db |........#.xPF...|
+00000060 a8 38 86 7b 2b bb fd d0 c3 42 3e 00 00 00 00 00 |.8.{+....B>.....|
+00000070 00 00 00 00 00 00 00 00 00 00 00 94 6f 2c b5 83 |............o,..|
+00000080 61 01 55 65 2a 95 38 d4 d5 5f 41 c1 45 e4 f8 4b |a.Ue*.8.._A.E..K|
+00000090 3b 08 44 df 0b 72 11 93 cd d4 ff 36 0f 4f 3a a9 |;.D..r.....6.O:.|
+000000a0 4c 9f ab c7 ae 88 97 bc 1e ff 2d 27 39 a8 82 84 |L.........-'9...|
+000000b0 ae 33 94 48 8b 1c 58 9d 60 65 3c 3f 17 9d 6a eb |.3.H..X.`e<?..j.|
+000000c0 50 cd 65 04 bb c7 28 c8 0d 57 44 52 e0 17 de df |P.e...(..WDR....|
+000000d0 f3 13 b1 00 0d 00 20 00 1e 06 01 06 02 06 03 05 |...... .........|
+000000e0 01 05 02 05 03 04 01 04 02 04 03 03 01 03 02 03 |................|
+000000f0 03 02 01 02 02 02 03 00 0f 00 01 01 |............|
>>> Flow 2 (server to client)
00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000002a0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 03 00 |..A4......9.....|
000002b0 04 0e 00 00 00 |.....|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 86 10 00 00 82 00 80 ac 10 32 61 b0 |.............2a.|
-00000010 03 e3 1e 2f 89 91 5f d6 4c e0 82 a7 82 41 67 d3 |.../.._.L....Ag.|
-00000020 5f b3 68 2d c0 d1 6f 03 7b 79 94 cc bb 35 6c 8a |_.h-..o.{y...5l.|
-00000030 bf 1c 83 ff 88 91 5c 04 64 cc a0 df 0b 08 8c 0f |......\.d.......|
-00000040 72 13 17 9f 27 14 8d 9a af 17 70 41 44 9f 89 8c |r...'.....pAD...|
-00000050 fa e4 66 33 4d bd 2f 93 2a 1e 85 a1 af 9e 27 12 |..f3M./.*.....'.|
-00000060 59 a4 13 67 56 85 c2 86 47 f8 c5 49 8f a4 c2 6e |Y..gV...G..I...n|
-00000070 04 78 0f 11 2b fb 7e 34 b8 eb 25 93 71 ab 9f f5 |.x..+.~4..%.q...|
-00000080 93 df 2b c3 1e 9e 6a 9e e3 57 aa 14 03 03 00 01 |..+...j..W......|
-00000090 01 16 03 03 00 24 e0 13 15 10 4c db f3 b6 de d2 |.....$....L.....|
-000000a0 68 02 f5 ea 1f 8e 58 70 4a 5a 78 d9 66 c5 74 77 |h.....XpJZx.f.tw|
-000000b0 a0 3a ec d8 b7 42 e3 a5 d4 62 |.:...B...b|
+00000000 16 03 03 00 86 10 00 00 82 00 80 ab d9 61 5e d3 |.............a^.|
+00000010 87 d7 eb 21 12 6f f9 61 dd 8b de 76 d7 14 70 2f |...!.o.a...v..p/|
+00000020 9c 0f 3c d4 4c 77 41 e2 ac 73 18 c3 0f 66 f2 b1 |..<.LwA..s...f..|
+00000030 fd 4b 1e d9 cb 5c 94 16 4d c2 98 f9 0d 55 f7 79 |.K...\..M....U.y|
+00000040 e2 8d 2c 87 96 e7 10 fb 78 fb ce 27 5d 9f ac 97 |..,.....x..']...|
+00000050 d6 54 6f 0c 78 dc 7b 2e 49 4c e2 42 24 b9 3d de |.To.x.{.IL.B$.=.|
+00000060 89 5f 1a 40 54 33 11 96 89 6f 59 25 5e 89 60 40 |._.@T3...oY%^.`@|
+00000070 83 8c 0e 92 0e 7d 68 9d 17 74 ba 39 e8 6f e3 43 |.....}h..t.9.o.C|
+00000080 44 80 e6 62 4b 35 43 21 5b eb 32 14 03 03 00 01 |D..bK5C![.2.....|
+00000090 01 16 03 03 00 24 77 1a b5 2c 88 d7 a6 83 f5 30 |.....$w..,.....0|
+000000a0 a0 c3 b4 45 a6 af 9b c2 ac 55 cf 73 4f a0 ba e5 |...E.....U.sO...|
+000000b0 2a be 9c 97 d2 d2 0b e9 95 0e |*.........|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 24 e9 c1 1f 5b e6 |..........$...[.|
-00000010 c1 d5 8a 14 eb c6 41 c1 77 6d 59 83 b6 95 34 f9 |......A.wmY...4.|
-00000020 7b a1 c9 9d 58 a5 b2 1b 33 6e 04 ab e0 03 61 17 |{...X...3n....a.|
-00000030 03 03 00 21 67 8b 55 43 d7 a7 05 c9 1f a0 d3 65 |...!g.UC.......e|
-00000040 30 36 07 8f d8 52 7e 40 79 31 2e 1c 1a c2 a6 fe |06...R~@y1......|
-00000050 e0 39 4d a0 5d 15 03 03 00 16 b8 94 fb 17 e5 1d |.9M.]...........|
-00000060 2e 28 95 cf 02 85 8e 11 2e 16 b1 53 72 aa a4 94 |.(.........Sr...|
+00000000 14 03 03 00 01 01 16 03 03 00 24 a9 ae 0c a5 ed |..........$.....|
+00000010 51 10 d9 14 71 41 40 bd be f5 44 98 11 2f d8 0f |Q...qA@...D../..|
+00000020 4d 42 bf 28 53 bf 02 7e d6 16 92 7f dd 03 ec 17 |MB.(S..~........|
+00000030 03 03 00 21 46 c2 68 a1 6a 35 67 e7 7d 62 71 43 |...!F.h.j5g.}bqC|
+00000040 6b ea d6 fc 22 fc 2d ad 45 d6 6d 98 9e e5 88 a0 |k...".-.E.m.....|
+00000050 ac 80 f7 6f 05 15 03 03 00 16 0c ae f4 fc 0e 09 |...o............|
+00000060 0b 09 73 69 83 0d 00 89 39 ff f6 20 4e 2b 88 3d |..si....9.. N+.=|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 6e 01 00 00 6a 03 03 be 99 22 5c d2 |....n...j...."\.|
-00000010 02 c7 a6 be f3 33 7a d4 76 1f cf 1e 39 0b 25 7c |.....3z.v...9.%||
-00000020 32 70 e4 8c 49 a6 87 b9 c1 2f 6d 00 00 04 00 2f |2p..I..../m..../|
-00000030 00 ff 01 00 00 3d 00 00 00 10 00 0e 00 00 0b 73 |.....=.........s|
-00000040 6e 69 74 65 73 74 2e 63 6f 6d 00 0d 00 20 00 1e |nitest.com... ..|
-00000050 06 01 06 02 06 03 05 01 05 02 05 03 04 01 04 02 |................|
-00000060 04 03 03 01 03 02 03 03 02 01 02 02 02 03 00 0f |................|
-00000070 00 01 01 |...|
+00000000 16 03 01 00 6f 01 00 00 6b 03 03 07 0f b6 b9 cc |....o...k.......|
+00000010 db 23 57 92 d0 9b 37 72 9d ad 9a 0d 17 6b dd b8 |.#W...7r.....k..|
+00000020 81 b7 7c 54 dd 68 fe 4e 28 00 39 00 00 04 00 2f |..|T.h.N(.9..../|
+00000030 00 ff 02 01 00 00 3d 00 00 00 10 00 0e 00 00 0b |......=.........|
+00000040 73 6e 69 74 65 73 74 2e 63 6f 6d 00 0d 00 20 00 |snitest.com... .|
+00000050 1e 06 01 06 02 06 03 05 01 05 02 05 03 04 01 04 |................|
+00000060 02 04 03 03 01 03 02 03 03 02 01 02 02 02 03 00 |................|
+00000070 0f 00 01 01 |....|
>>> Flow 2 (server to client)
00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000230 2c 65 25 d6 52 b6 e3 18 45 bd cc 16 03 03 00 04 |,e%.R...E.......|
00000240 0e 00 00 00 |....|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 86 10 00 00 82 00 80 6b 03 31 ca a0 |...........k.1..|
-00000010 62 a2 53 11 ce 13 d9 f6 e7 d4 ec 2e c3 0a 38 56 |b.S...........8V|
-00000020 23 22 67 23 c8 8d 16 b4 3c 0b 26 9f 1c 2d 65 13 |#"g#....<.&..-e.|
-00000030 c3 cb 65 69 b0 47 ff 87 e8 02 56 c4 77 8a 40 29 |..ei.G....V.w.@)|
-00000040 82 62 8b 06 61 0a 1c b3 c7 29 b6 aa c9 96 37 18 |.b..a....)....7.|
-00000050 d0 60 66 63 9b 62 4b 30 cc 03 9c 37 05 c6 32 98 |.`fc.bK0...7..2.|
-00000060 cb a0 e2 e4 38 60 d4 93 99 9a fc 03 66 fb b6 ef |....8`......f...|
-00000070 8a 1e bb ca 13 c5 d9 7a 7c 3b 50 dc d0 ad 00 b5 |.......z|;P.....|
-00000080 2c dc 1a ef c4 5c af d3 4e cd e6 14 03 03 00 01 |,....\..N.......|
-00000090 01 16 03 03 00 40 42 31 83 8a 2c 86 22 c5 df e5 |.....@B1..,."...|
-000000a0 f2 0b f8 0c 2f 1e 82 f4 69 fe 1d bd 4c db f1 80 |..../...i...L...|
-000000b0 68 30 b7 e3 60 76 b3 f1 52 ae d6 e7 b3 cb 4a e0 |h0..`v..R.....J.|
-000000c0 27 0a c1 1a 72 ed 71 ab 0a fc 10 d9 5e 4d fd 10 |'...r.q.....^M..|
-000000d0 04 92 39 78 be 23 |..9x.#|
+00000000 16 03 03 00 86 10 00 00 82 00 80 72 6a 6f a8 c9 |...........rjo..|
+00000010 3e 4c 33 da 92 23 97 68 fc 4e ca 74 77 98 f3 88 |>L3..#.h.N.tw...|
+00000020 ba a0 55 b6 a0 6f ff c8 db 2b 90 17 1f 45 bc 26 |..U..o...+...E.&|
+00000030 62 6e b9 91 96 b9 03 5d eb f2 a2 59 87 7b 81 4a |bn.....]...Y.{.J|
+00000040 0c f9 e2 23 60 e3 c7 4d 53 4f 3a 1f c5 5f dd 15 |...#`..MSO:.._..|
+00000050 cc 78 c5 21 fd 33 02 68 77 7c 8d 5f e8 80 a7 84 |.x.!.3.hw|._....|
+00000060 a7 2c b3 1f 64 df 8a 63 e9 b3 24 02 c1 6a 94 bd |.,..d..c..$..j..|
+00000070 a1 62 e5 32 e5 d9 83 25 0d 0f 1a 02 90 8a cd 79 |.b.2...%.......y|
+00000080 1c bd 4a c2 f4 5d a0 24 c6 c1 ae 14 03 03 00 01 |..J..].$........|
+00000090 01 16 03 03 00 40 1f 1a 17 47 15 25 5b 3d 5f e5 |.....@...G.%[=_.|
+000000a0 f4 d9 64 47 5f 80 09 f7 dd 5a ff 58 19 08 b5 db |..dG_....Z.X....|
+000000b0 38 88 a4 44 07 01 fb 80 1d 89 b2 d4 af 95 80 b3 |8..D............|
+000000c0 75 13 82 0e 24 12 1d 5c 29 72 1d 21 d4 69 16 e0 |u...$..\)r.!.i..|
+000000d0 b5 4b 46 62 fe f7 |.KFb..|
>>> Flow 4 (server to client)
00000000 15 03 03 00 02 02 14 |.......|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 6e 01 00 00 6a 03 03 23 de 75 da 8e |....n...j..#.u..|
-00000010 0a 4b 7b e4 cb 34 14 83 be d1 6a 95 25 86 f8 91 |.K{..4....j.%...|
-00000020 d8 bb ac 82 9e 19 d6 9f 52 26 f6 00 00 04 00 2f |........R&...../|
-00000030 00 ff 01 00 00 3d 00 00 00 10 00 0e 00 00 0b 73 |.....=.........s|
-00000040 6e 69 74 65 73 74 2e 63 6f 6d 00 0d 00 20 00 1e |nitest.com... ..|
-00000050 06 01 06 02 06 03 05 01 05 02 05 03 04 01 04 02 |................|
-00000060 04 03 03 01 03 02 03 03 02 01 02 02 02 03 00 0f |................|
-00000070 00 01 01 |...|
+00000000 16 03 01 00 6f 01 00 00 6b 03 03 fe d6 ce b5 1b |....o...k.......|
+00000010 1c 50 0c db 9c 35 5d 0e f2 ee 57 3f 65 83 9f 28 |.P...5]...W?e..(|
+00000020 96 50 1c e0 7f 95 f9 17 39 4f c3 00 00 04 00 2f |.P......9O...../|
+00000030 00 ff 02 01 00 00 3d 00 00 00 10 00 0e 00 00 0b |......=.........|
+00000040 73 6e 69 74 65 73 74 2e 63 6f 6d 00 0d 00 20 00 |snitest.com... .|
+00000050 1e 06 01 06 02 06 03 05 01 05 02 05 03 04 01 04 |................|
+00000060 02 04 03 03 01 03 02 03 03 02 01 02 02 02 03 00 |................|
+00000070 0f 00 01 01 |....|
>>> Flow 2 (server to client)
00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000230 2c 65 25 d6 52 b6 e3 18 45 bd cc 16 03 03 00 04 |,e%.R...E.......|
00000240 0e 00 00 00 |....|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 86 10 00 00 82 00 80 a2 99 61 c5 90 |.............a..|
-00000010 47 1a e7 47 56 51 59 e4 6e ab 82 01 18 78 ee 95 |G..GVQY.n....x..|
-00000020 b8 e2 c7 c7 f9 64 98 dd 84 8d 96 d9 2d 08 62 1e |.....d......-.b.|
-00000030 4f 29 83 b6 93 68 77 7a 14 1b f0 b3 1a 67 7b 7a |O)...hwz.....g{z|
-00000040 f9 54 f3 7e 6d eb b6 7a c9 37 70 6a 83 68 f2 15 |.T.~m..z.7pj.h..|
-00000050 81 07 30 6e b8 fa 19 0e 46 dc d6 9a 4a 8e 8d f1 |..0n....F...J...|
-00000060 05 78 60 75 d4 00 d9 1e 11 5f 16 f7 bc 9f e8 8a |.x`u....._......|
-00000070 c4 3e bd d9 1a b8 67 50 00 be 5f 43 ee 07 ad be |.>....gP.._C....|
-00000080 f5 85 67 fc 8f c6 87 47 6d 6e b2 14 03 03 00 01 |..g....Gmn......|
-00000090 01 16 03 03 00 40 91 7d 7b 05 99 48 05 70 a9 67 |.....@.}{..H.p.g|
-000000a0 e9 7a 0a c3 6b bf b0 ad 68 65 17 fb 18 bf 8d bd |.z..k...he......|
-000000b0 e1 4b 12 bf ea 82 9d a6 1e 3a c8 77 65 32 bd 5e |.K.......:.we2.^|
-000000c0 c4 46 da e7 e1 ac 09 fe 4a ac bc 57 6a 17 7d dc |.F......J..Wj.}.|
-000000d0 fe 9c d0 d0 6e fc |....n.|
+00000000 16 03 03 00 86 10 00 00 82 00 80 6f bc 33 c8 2d |...........o.3.-|
+00000010 5a 50 65 2f 06 1a 45 16 9e 5b ab 97 43 b1 9e 96 |ZPe/..E..[..C...|
+00000020 b5 4a fe c3 7c e8 e4 07 ea 00 47 d2 51 23 11 ae |.J..|.....G.Q#..|
+00000030 11 a8 79 71 b9 c6 82 17 40 ae c7 fc cd 05 4d 6d |..yq....@.....Mm|
+00000040 cb bc f1 ce 30 d0 10 37 4a e6 aa d3 14 fb bc 62 |....0..7J......b|
+00000050 eb 6c fa ec e1 e1 dd 63 39 95 0b 87 71 a0 83 ba |.l.....c9...q...|
+00000060 bf 25 f8 a9 d3 c4 35 e1 88 23 85 56 c6 f4 0b 10 |.%....5..#.V....|
+00000070 d1 70 f8 0a 3d a1 08 17 ce 27 2d 4c a7 c5 b5 0d |.p..=....'-L....|
+00000080 f2 43 b7 b9 02 21 7a eb 40 d2 66 14 03 03 00 01 |.C...!z.@.f.....|
+00000090 01 16 03 03 00 40 0a 93 47 0b 6e 40 ff cd 09 a5 |.....@..G.n@....|
+000000a0 bc a4 c5 a8 c3 1c 0a fb d4 2e 8a 2f 0c f3 d6 e1 |.........../....|
+000000b0 de 1f 56 2f 09 61 2d 31 d5 b1 29 6b f2 18 8b f2 |..V/.a-1..)k....|
+000000c0 0c 0e 09 5f ec 11 56 af 44 8b e5 2d 09 68 eb c2 |..._..V.D..-.h..|
+000000d0 91 4d 04 b2 10 02 |.M....|
>>> Flow 4 (server to client)
00000000 15 03 03 00 02 02 14 |.......|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 6e 01 00 00 6a 03 03 27 db e3 e8 f4 |....n...j..'....|
-00000010 48 1d 45 d5 20 64 97 b2 20 a6 67 94 7a 1e 87 12 |H.E. d.. .g.z...|
-00000020 25 b1 53 94 27 78 ed ae 58 2f 1b 00 00 04 00 2f |%.S.'x..X/...../|
-00000030 00 ff 01 00 00 3d 00 00 00 10 00 0e 00 00 0b 73 |.....=.........s|
-00000040 6e 69 74 65 73 74 2e 63 6f 6d 00 0d 00 20 00 1e |nitest.com... ..|
-00000050 06 01 06 02 06 03 05 01 05 02 05 03 04 01 04 02 |................|
-00000060 04 03 03 01 03 02 03 03 02 01 02 02 02 03 00 0f |................|
-00000070 00 01 01 |...|
+00000000 16 03 01 00 6f 01 00 00 6b 03 03 64 29 6e 67 3d |....o...k..d)ng=|
+00000010 5a 13 48 8a ae a5 67 6b 2f 5b 76 d2 c1 df 23 c6 |Z.H...gk/[v...#.|
+00000020 f9 52 26 33 ce 0b 03 f6 53 a7 db 00 00 04 00 2f |.R&3....S....../|
+00000030 00 ff 02 01 00 00 3d 00 00 00 10 00 0e 00 00 0b |......=.........|
+00000040 73 6e 69 74 65 73 74 2e 63 6f 6d 00 0d 00 20 00 |snitest.com... .|
+00000050 1e 06 01 06 02 06 03 05 01 05 02 05 03 04 01 04 |................|
+00000060 02 04 03 03 01 03 02 03 03 02 01 02 02 02 03 00 |................|
+00000070 0f 00 01 01 |....|
>>> Flow 2 (server to client)
00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000230 2c 65 25 d6 52 b6 e3 18 45 bd cc 16 03 03 00 04 |,e%.R...E.......|
00000240 0e 00 00 00 |....|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 86 10 00 00 82 00 80 72 23 e9 89 70 |...........r#..p|
-00000010 97 02 08 58 0d 28 96 5b 19 73 dd 4f 6e 4c 11 dd |...X.(.[.s.OnL..|
-00000020 cb 56 14 f4 8f c8 e5 84 03 f5 7e f0 a4 08 44 8c |.V........~...D.|
-00000030 22 74 01 5c e4 9d e0 38 53 90 66 e3 df bb 09 a8 |"t.\...8S.f.....|
-00000040 11 97 0a 44 01 d2 70 85 14 a1 9a 2f 02 34 40 6d |...D..p..../.4@m|
-00000050 66 80 72 9a 97 98 5c 91 0e dc 42 ac c2 90 2f 30 |f.r...\...B.../0|
-00000060 ca 39 25 94 da 6e b6 5f 94 a9 94 66 7f 32 6a bb |.9%..n._...f.2j.|
-00000070 5d 43 20 c3 74 f7 52 29 1f d5 62 6b a4 a1 8c 25 |]C .t.R)..bk...%|
-00000080 46 69 22 a5 68 54 f4 68 30 e2 52 14 03 03 00 01 |Fi".hT.h0.R.....|
-00000090 01 16 03 03 00 40 51 d2 78 64 e3 59 ee b7 5f 95 |.....@Q.xd.Y.._.|
-000000a0 4c 49 7f 0d 49 3f 55 71 8c 3b 24 e3 81 22 4a d1 |LI..I?Uq.;$.."J.|
-000000b0 ab 84 4e df 02 9d 56 ea 2a 14 71 e1 dc 1d 5c 1d |..N...V.*.q...\.|
-000000c0 54 ce cb 58 f6 4d e7 73 44 0d 99 95 a5 2d 7c 2f |T..X.M.sD....-|/|
-000000d0 15 f5 8f fd 97 40 |.....@|
+00000000 16 03 03 00 86 10 00 00 82 00 80 7b 3b b8 73 f0 |...........{;.s.|
+00000010 78 2c 75 91 ee 4a ac 6e 9d 08 8e ef dd 52 fb 38 |x,u..J.n.....R.8|
+00000020 d7 6f b3 39 8a 8c 3c dc 4b e0 a9 2b 0b de 9a d6 |.o.9..<.K..+....|
+00000030 38 72 ae 0f 76 87 4b f6 45 17 f6 fa b2 5a 07 30 |8r..v.K.E....Z.0|
+00000040 5b ef e7 40 e0 95 98 bf 8d 8d 5e 7a 6a ea 2d 2e |[..@......^zj.-.|
+00000050 9c 99 e4 47 6b 4f 16 32 fb 0d a7 01 36 2e 06 f2 |...GkO.2....6...|
+00000060 65 74 b6 ed 07 51 60 7a 98 d6 77 36 f4 c7 f6 b1 |et...Q`z..w6....|
+00000070 f1 6a 3e 38 7c 79 5c c6 b4 53 5c 85 fb 0b 2c f9 |.j>8|y\..S\...,.|
+00000080 2c 60 97 c8 73 f7 22 ef 52 4c 10 14 03 03 00 01 |,`..s.".RL......|
+00000090 01 16 03 03 00 40 4c 73 6e 5e 66 9d 53 2e fa b7 |.....@Lsn^f.S...|
+000000a0 90 2d 52 55 13 d2 67 28 aa 1a 6f 62 42 ef 2f 4d |.-RU..g(..obB./M|
+000000b0 04 1d ef 64 8f 1a 70 c0 d0 bf 06 72 ee db 3e 43 |...d..p....r..>C|
+000000c0 7f ed 37 bb a1 62 0c c5 c8 a9 c0 51 8f 77 95 b3 |..7..b.....Q.w..|
+000000d0 72 7e 01 89 c4 32 |r~...2|
>>> Flow 4 (server to client)
00000000 15 03 03 00 02 02 14 |.......|
// Possible directories with certificate files; stop after successfully
// reading at least one file from a directory.
var certDirectories = []string{
+ "/etc/ssl/certs", // SLES10/SLES11, https://golang.org/issue/12139
"/system/etc/security/cacerts", // Android
}
)
var (
- driversMu sync.Mutex
+ driversMu sync.RWMutex
drivers = make(map[string]driver.Driver)
)
// Drivers returns a sorted list of the names of the registered drivers.
func Drivers() []string {
- driversMu.Lock()
- defer driversMu.Unlock()
+ driversMu.RLock()
+ defer driversMu.RUnlock()
var list []string
for name := range drivers {
list = append(list, name)
// function should be called just once. It is rarely necessary to
// close a DB.
func Open(driverName, dataSourceName string) (*DB, error) {
- driversMu.Lock()
+ driversMu.RLock()
driveri, ok := drivers[driverName]
- driversMu.Unlock()
+ driversMu.RUnlock()
if !ok {
return nil, fmt.Errorf("sql: unknown driver %q (forgotten import?)", driverName)
}
func (i R_386) String() string { return stringName(uint32(i), r386Strings, false) }
func (i R_386) GoString() string { return stringName(uint32(i), r386Strings, true) }
+// Relocation types for MIPS.
+type R_MIPS int
+
+const (
+ R_MIPS_NONE R_MIPS = 0
+ R_MIPS_16 R_MIPS = 1
+ R_MIPS_32 R_MIPS = 2
+ R_MIPS_REL32 R_MIPS = 3
+ R_MIPS_26 R_MIPS = 4
+ R_MIPS_HI16 R_MIPS = 5 /* high 16 bits of symbol value */
+ R_MIPS_LO16 R_MIPS = 6 /* low 16 bits of symbol value */
+ R_MIPS_GPREL16 R_MIPS = 7 /* GP-relative reference */
+ R_MIPS_LITERAL R_MIPS = 8 /* Reference to literal section */
+ R_MIPS_GOT16 R_MIPS = 9 /* Reference to global offset table */
+ R_MIPS_PC16 R_MIPS = 10 /* 16 bit PC relative reference */
+ R_MIPS_CALL16 R_MIPS = 11 /* 16 bit call thru glbl offset tbl */
+ R_MIPS_GPREL32 R_MIPS = 12
+ R_MIPS_SHIFT5 R_MIPS = 16
+ R_MIPS_SHIFT6 R_MIPS = 17
+ R_MIPS_64 R_MIPS = 18
+ R_MIPS_GOT_DISP R_MIPS = 19
+ R_MIPS_GOT_PAGE R_MIPS = 20
+ R_MIPS_GOT_OFST R_MIPS = 21
+ R_MIPS_GOT_HI16 R_MIPS = 22
+ R_MIPS_GOT_LO16 R_MIPS = 23
+ R_MIPS_SUB R_MIPS = 24
+ R_MIPS_INSERT_A R_MIPS = 25
+ R_MIPS_INSERT_B R_MIPS = 26
+ R_MIPS_DELETE R_MIPS = 27
+ R_MIPS_HIGHER R_MIPS = 28
+ R_MIPS_HIGHEST R_MIPS = 29
+ R_MIPS_CALL_HI16 R_MIPS = 30
+ R_MIPS_CALL_LO16 R_MIPS = 31
+ R_MIPS_SCN_DISP R_MIPS = 32
+ R_MIPS_REL16 R_MIPS = 33
+ R_MIPS_ADD_IMMEDIATE R_MIPS = 34
+ R_MIPS_PJUMP R_MIPS = 35
+ R_MIPS_RELGOT R_MIPS = 36
+ R_MIPS_JALR R_MIPS = 37
+
+ R_MIPS_TLS_DTPMOD32 R_MIPS = 38 /* Module number 32 bit */
+ R_MIPS_TLS_DTPREL32 R_MIPS = 39 /* Module-relative offset 32 bit */
+ R_MIPS_TLS_DTPMOD64 R_MIPS = 40 /* Module number 64 bit */
+ R_MIPS_TLS_DTPREL64 R_MIPS = 41 /* Module-relative offset 64 bit */
+ R_MIPS_TLS_GD R_MIPS = 42 /* 16 bit GOT offset for GD */
+ R_MIPS_TLS_LDM R_MIPS = 43 /* 16 bit GOT offset for LDM */
+ R_MIPS_TLS_DTPREL_HI16 R_MIPS = 44 /* Module-relative offset, high 16 bits */
+ R_MIPS_TLS_DTPREL_LO16 R_MIPS = 45 /* Module-relative offset, low 16 bits */
+ R_MIPS_TLS_GOTTPREL R_MIPS = 46 /* 16 bit GOT offset for IE */
+ R_MIPS_TLS_TPREL32 R_MIPS = 47 /* TP-relative offset, 32 bit */
+ R_MIPS_TLS_TPREL64 R_MIPS = 48 /* TP-relative offset, 64 bit */
+ R_MIPS_TLS_TPREL_HI16 R_MIPS = 49 /* TP-relative offset, high 16 bits */
+ R_MIPS_TLS_TPREL_LO16 R_MIPS = 50 /* TP-relative offset, low 16 bits */
+)
+
+var rmipsStrings = []intName{
+ {0, "R_MIPS_NONE"},
+ {1, "R_MIPS_16"},
+ {2, "R_MIPS_32"},
+ {3, "R_MIPS_REL32"},
+ {4, "R_MIPS_26"},
+ {5, "R_MIPS_HI16"},
+ {6, "R_MIPS_LO16"},
+ {7, "R_MIPS_GPREL16"},
+ {8, "R_MIPS_LITERAL"},
+ {9, "R_MIPS_GOT16"},
+ {10, "R_MIPS_PC16"},
+ {11, "R_MIPS_CALL16"},
+ {12, "R_MIPS_GPREL32"},
+ {16, "R_MIPS_SHIFT5"},
+ {17, "R_MIPS_SHIFT6"},
+ {18, "R_MIPS_64"},
+ {19, "R_MIPS_GOT_DISP"},
+ {20, "R_MIPS_GOT_PAGE"},
+ {21, "R_MIPS_GOT_OFST"},
+ {22, "R_MIPS_GOT_HI16"},
+ {23, "R_MIPS_GOT_LO16"},
+ {24, "R_MIPS_SUB"},
+ {25, "R_MIPS_INSERT_A"},
+ {26, "R_MIPS_INSERT_B"},
+ {27, "R_MIPS_DELETE"},
+ {28, "R_MIPS_HIGHER"},
+ {29, "R_MIPS_HIGHEST"},
+ {30, "R_MIPS_CALL_HI16"},
+ {31, "R_MIPS_CALL_LO16"},
+ {32, "R_MIPS_SCN_DISP"},
+ {33, "R_MIPS_REL16"},
+ {34, "R_MIPS_ADD_IMMEDIATE"},
+ {35, "R_MIPS_PJUMP"},
+ {36, "R_MIPS_RELGOT"},
+ {37, "R_MIPS_JALR"},
+ {38, "R_MIPS_TLS_DTPMOD32"},
+ {39, "R_MIPS_TLS_DTPREL32"},
+ {40, "R_MIPS_TLS_DTPMOD64"},
+ {41, "R_MIPS_TLS_DTPREL64"},
+ {42, "R_MIPS_TLS_GD"},
+ {43, "R_MIPS_TLS_LDM"},
+ {44, "R_MIPS_TLS_DTPREL_HI16"},
+ {45, "R_MIPS_TLS_DTPREL_LO16"},
+ {46, "R_MIPS_TLS_GOTTPREL"},
+ {47, "R_MIPS_TLS_TPREL32"},
+ {48, "R_MIPS_TLS_TPREL64"},
+ {49, "R_MIPS_TLS_TPREL_HI16"},
+ {50, "R_MIPS_TLS_TPREL_LO16"},
+}
+
+func (i R_MIPS) String() string { return stringName(uint32(i), rmipsStrings, false) }
+func (i R_MIPS) GoString() string { return stringName(uint32(i), rmipsStrings, true) }
+
// Relocation types for PowerPC.
type R_PPC int
return f.applyRelocationsPPC(dst, rels)
case f.Class == ELFCLASS64 && f.Machine == EM_PPC64:
return f.applyRelocationsPPC64(dst, rels)
+ case f.Class == ELFCLASS64 && f.Machine == EM_MIPS:
+ return f.applyRelocationsMIPS64(dst, rels)
default:
return errors.New("applyRelocations: not implemented")
}
return nil
}
+func (f *File) applyRelocationsMIPS64(dst []byte, rels []byte) error {
+ // 24 is the size of Rela64.
+ if len(rels)%24 != 0 {
+ return errors.New("length of relocation section is not a multiple of 24")
+ }
+
+ symbols, _, err := f.getSymbols(SHT_SYMTAB)
+ if err != nil {
+ return err
+ }
+
+ b := bytes.NewReader(rels)
+ var rela Rela64
+
+ for b.Len() > 0 {
+ binary.Read(b, f.ByteOrder, &rela)
+ var symNo uint64
+ var t R_MIPS
+ if f.ByteOrder == binary.BigEndian {
+ symNo = rela.Info >> 32
+ t = R_MIPS(rela.Info & 0xff)
+ } else {
+ symNo = rela.Info & 0xffffffff
+ t = R_MIPS(rela.Info >> 56)
+ }
+
+ if symNo == 0 || symNo > uint64(len(symbols)) {
+ continue
+ }
+ sym := &symbols[symNo-1]
+ if SymType(sym.Info&0xf) != STT_SECTION {
+ // We don't handle non-section relocations for now.
+ continue
+ }
+
+ switch t {
+ case R_MIPS_64:
+ if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
+ continue
+ }
+ f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend))
+ case R_MIPS_32:
+ if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
+ continue
+ }
+ f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
+ }
+ }
+
+ return nil
+}
+
func (f *File) DWARF() (*dwarf.Data, error) {
// sectionData gets the data for s, checks its size, and
// applies any applicable relations.
}},
},
},
+ {
+ "testdata/go-relocation-test-gcc492-mips64.obj",
+ []relocationTestEntry{
+ {0, &dwarf.Entry{
+ Offset: 0xb,
+ Tag: dwarf.TagCompileUnit,
+ Children: true,
+ Field: []dwarf.Field{
+ {Attr: dwarf.AttrProducer, Val: "GNU C 4.9.2 -meb -mabi=64 -march=mips3 -mtune=mips64 -mllsc -mno-shared -g", Class: dwarf.ClassString},
+ {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
+ {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
+ {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
+ {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
+ {Attr: dwarf.AttrHighpc, Val: int64(100), Class: dwarf.ClassConstant},
+ {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
+ },
+ }},
+ },
+ },
+ {
+ "testdata/go-relocation-test-gcc493-mips64le.obj",
+ []relocationTestEntry{
+ {0, &dwarf.Entry{
+ Offset: 0xb,
+ Tag: dwarf.TagCompileUnit,
+ Children: true,
+ Field: []dwarf.Field{
+ {Attr: dwarf.AttrProducer, Val: "GNU C 4.9.3 -mel -mabi=64 -mllsc -mno-shared -g -fstack-protector-strong", Class: dwarf.ClassString},
+ {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
+ {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
+ {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
+ {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
+ {Attr: dwarf.AttrHighpc, Val: int64(100), Class: dwarf.ClassConstant},
+ {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
+ },
+ }},
+ },
+ },
{
"testdata/go-relocation-test-clang-x86.obj",
[]relocationTestEntry{
}
for i, test := range nilValueTestData {
if _, err := Marshal(test); err == nil {
- t.Fatal("#%d: successfully marshaled nil value", i)
+ t.Fatalf("#%d: successfully marshaled nil value", i)
}
}
}
d.saveError(err)
break
}
- v.Set(reflect.ValueOf(b[0:n]))
+ v.SetBytes(b[:n])
case reflect.String:
v.SetString(string(s))
case reflect.Interface:
Loop
Embed0p // has Point with X, Y, used
Embed0q // has Point with Z, used
+ embed // contains exported field
}
type Embed0 struct {
Point
}
+type embed struct {
+ Q int
+}
+
type Loop struct {
Loop1 int `json:",omitempty"`
Loop2 int `json:",omitempty"`
"Loop2": 14,
"X": 15,
"Y": 16,
- "Z": 17
+ "Z": 17,
+ "Q": 18
}`,
ptr: new(Top),
out: Top{
Embed0q: Embed0q{
Point: Point{Z: 17},
},
+ embed: embed{
+ Q: 18,
+ },
},
},
{
Embed0q: Embed0q{
Point: Point{Z: 17},
},
+ embed: embed{
+ Q: 18,
+ },
}
b, err := Marshal(top)
if err != nil {
t.Fatal(err)
}
- want := "{\"Level0\":1,\"Level1b\":2,\"Level1c\":3,\"Level1a\":5,\"LEVEL1B\":6,\"e\":{\"Level1a\":8,\"Level1b\":9,\"Level1c\":10,\"Level1d\":11,\"x\":12},\"Loop1\":13,\"Loop2\":14,\"X\":15,\"Y\":16,\"Z\":17}"
+ want := "{\"Level0\":1,\"Level1b\":2,\"Level1c\":3,\"Level1a\":5,\"LEVEL1B\":6,\"e\":{\"Level1a\":8,\"Level1b\":9,\"Level1c\":10,\"Level1d\":11,\"x\":12},\"Loop1\":13,\"Loop2\":14,\"X\":15,\"Y\":16,\"Z\":17,\"Q\":18}"
if string(b) != want {
t.Errorf("Wrong marshal result.\n got: %q\nwant: %q", b, want)
}
}
}
+// The fix for issue 8962 introduced a regression.
+// Issue 12921.
+func TestSliceOfCustomByte(t *testing.T) {
+ type Uint8 uint8
+
+ a := []Uint8("hello")
+
+ data, err := Marshal(a)
+ if err != nil {
+ t.Fatal(err)
+ }
+ var b []Uint8
+ err = Unmarshal(data, &b)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !reflect.DeepEqual(a, b) {
+ t.Fatal("expected %v == %v", a, b)
+ }
+}
+
var decodeTypeErrorTests = []struct {
dest interface{}
src string
// Scan f.typ for fields to include.
for i := 0; i < f.typ.NumField(); i++ {
sf := f.typ.Field(i)
- if sf.PkgPath != "" { // unexported
+ if sf.PkgPath != "" && !sf.Anonymous { // unexported
continue
}
tag := sf.Tag.Get("json")
EmbedC
EmbedB EmbedB
FieldA string
+ embedD
}
type EmbedB struct {
FieldC string
}
+type embedD struct {
+ fieldD string
+ FieldE string // Promoted and visible when embedD is embedded.
+}
+
type NameCasing struct {
XMLName struct{} `xml:"casing"`
Xy string
},
},
FieldA: "A.A",
+ embedD: embedD{
+ FieldE: "A.D.E",
+ },
},
ExpectXML: `<EmbedA>` +
`<FieldB>A.C.B</FieldB>` +
`<FieldC>A.B.C.C</FieldC>` +
`</EmbedB>` +
`<FieldA>A.A</FieldA>` +
+ `<FieldE>A.D.E</FieldE>` +
`</EmbedA>`,
},
n := typ.NumField()
for i := 0; i < n; i++ {
f := typ.Field(i)
- if f.PkgPath != "" || f.Tag.Get("xml") == "-" {
+ if (f.PkgPath != "" && !f.Anonymous) || f.Tag.Get("xml") == "-" {
continue // Private field
}
// convertString returns the string represented by the next input characters.
// The format of the input is determined by the verb.
func (s *ss) convertString(verb rune) (str string) {
- if !s.okVerb(verb, "svqx", "string") {
+ if !s.okVerb(verb, "svqxX", "string") {
return ""
}
s.skipSpace(false)
switch verb {
case 'q':
str = s.quotedString()
- case 'x':
+ case 'x', 'X':
str = s.hexString()
default:
str = string(s.token(true, notSpace)) // %s and %v just return the next word
// Strings
{"%s", "using-%s\n", &stringVal, "using-%s"},
{"%x", "7573696e672d2578\n", &stringVal, "using-%x"},
+ {"%X", "7573696E672D2558\n", &stringVal, "using-%X"},
{"%q", `"quoted\twith\\do\u0075bl\x65s"` + "\n", &stringVal, "quoted\twith\\doubles"},
{"%q", "`quoted with backs`\n", &stringVal, "quoted with backs"},
// Byte slices
{"%s", "bytes-%s\n", &bytesVal, []byte("bytes-%s")},
{"%x", "62797465732d2578\n", &bytesVal, []byte("bytes-%x")},
+ {"%X", "62797465732D2558\n", &bytesVal, []byte("bytes-%X")},
{"%q", `"bytes\rwith\vdo\u0075bl\x65s"` + "\n", &bytesVal, []byte("bytes\rwith\vdoubles")},
{"%q", "`bytes with backs`\n", &bytesVal, []byte("bytes with backs")},
c.GOARCH = envOr("GOARCH", runtime.GOARCH)
c.GOOS = envOr("GOOS", runtime.GOOS)
- c.GOROOT = runtime.GOROOT()
+ c.GOROOT = pathpkg.Clean(runtime.GOROOT())
c.GOPATH = envOr("GOPATH", "")
c.Compiler = runtime.Compiler
// in all releases >= Go 1.x. Code that requires Go 1.x or later should
// say "+build go1.x", and code that should only be built before Go 1.x
// (perhaps it is the stub to use in that case) should say "+build !go1.x".
- c.ReleaseTags = []string{"go1.1", "go1.2", "go1.3", "go1.4", "go1.5"}
+ c.ReleaseTags = []string{"go1.1", "go1.2", "go1.3", "go1.4", "go1.5", "go1.6"}
switch os.Getenv("CGO_ENABLED") {
case "1":
//
var pkgDeps = map[string][]string{
// L0 is the lowest level, core, nearly unavoidable packages.
- "errors": {},
- "io": {"errors", "sync"},
- "runtime": {"unsafe"},
+ "errors": {},
+ "io": {"errors", "sync"},
+ "runtime": {"unsafe", "runtime/internal/atomic", "runtime/internal/sys"},
+ "runtime/internal/sys": {},
+ "runtime/internal/atomic": {"unsafe", "runtime/internal/sys"},
"sync": {"runtime", "sync/atomic", "unsafe"},
"sync/atomic": {"unsafe"},
"unsafe": {},
"errors",
"io",
"runtime",
+ "runtime/internal/atomic",
"sync",
"sync/atomic",
"unsafe",
// that shows up in programs that use cgo.
"C": {},
- // Race detector uses cgo.
+ // Race detector/MSan uses cgo.
"runtime/race": {"C"},
+ "runtime/msan": {"C"},
// Plan 9 alone needs io/ioutil and os.
"os/user": {"L4", "CGO", "io/ioutil", "os", "syscall"},
"net/http/cgi": {"L4", "NET", "OS", "crypto/tls", "net/http", "regexp"},
"net/http/cookiejar": {"L4", "NET", "net/http"},
"net/http/fcgi": {"L4", "NET", "OS", "net/http", "net/http/cgi"},
- "net/http/httptest": {"L4", "NET", "OS", "crypto/tls", "flag", "net/http"},
+ "net/http/httptest": {"L4", "NET", "OS", "crypto/tls", "flag", "net/http", "net/http/internal"},
"net/http/httputil": {"L4", "NET", "OS", "net/http", "net/http/internal"},
"net/http/pprof": {"L4", "OS", "html/template", "net/http", "runtime/pprof", "runtime/trace"},
"net/rpc": {"L4", "NET", "encoding/gob", "html/template", "net/http"},
}
sort.Strings(all)
- test := func(mustImport bool) {
- for _, pkg := range all {
- imports, err := findImports(pkg)
- if err != nil {
- t.Error(err)
- continue
- }
- ok := allowed(pkg)
- var bad []string
- for _, imp := range imports {
- if !ok[imp] {
- bad = append(bad, imp)
- }
- }
- if bad != nil {
- t.Errorf("unexpected dependency: %s imports %v", pkg, bad)
+ for _, pkg := range all {
+ imports, err := findImports(pkg)
+ if err != nil {
+ t.Error(err)
+ continue
+ }
+ ok := allowed(pkg)
+ var bad []string
+ for _, imp := range imports {
+ if !ok[imp] {
+ bad = append(bad, imp)
}
}
+ if bad != nil {
+ t.Errorf("unexpected dependency: %s imports %v", pkg, bad)
+ }
}
- test(true)
}
var buildIgnore = []byte("\n// +build ignore")
// - "go1.3", from Go version 1.3 onward
// - "go1.4", from Go version 1.4 onward
// - "go1.5", from Go version 1.5 onward
+// - "go1.6", from Go version 1.6 onward
// - any additional words listed in ctxt.BuildTags
//
// If a file's name, after stripping the extension and a possible _test suffix,
--- /dev/null
+// Copyright 2015 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 gcimporter
+
+import (
+ "encoding/binary"
+ "fmt"
+ "go/constant"
+ "go/token"
+ "go/types"
+ "sort"
+ "unicode"
+ "unicode/utf8"
+)
+
+// BImportData imports a package from the serialized package data
+// and returns the number of bytes consumed and a reference to the package.
+// If data is obviously malformed, an error is returned but in
+// general it is not recommended to call BImportData on untrusted data.
+func BImportData(imports map[string]*types.Package, data []byte, path string) (int, *types.Package, error) {
+ p := importer{
+ imports: imports,
+ data: data,
+ }
+ p.buf = p.bufarray[:]
+
+ // read low-level encoding format
+ switch format := p.byte(); format {
+ case 'c':
+ // compact format - nothing to do
+ case 'd':
+ p.debugFormat = true
+ default:
+ return p.read, nil, fmt.Errorf("invalid encoding format in export data: got %q; want 'c' or 'd'", format)
+ }
+
+ // --- generic export data ---
+
+ if v := p.string(); v != "v0" {
+ return p.read, nil, fmt.Errorf("unknown version: %s", v)
+ }
+
+ // populate typList with predeclared "known" types
+ p.typList = append(p.typList, predeclared...)
+
+ // read package data
+ // TODO(gri) clean this up
+ i := p.tagOrIndex()
+ if i != packageTag {
+ panic(fmt.Sprintf("package tag expected, got %d", i))
+ }
+ name := p.string()
+ if s := p.string(); s != "" {
+ panic(fmt.Sprintf("empty path expected, got %s", s))
+ }
+ pkg := p.imports[path]
+ if pkg == nil {
+ pkg = types.NewPackage(path, name)
+ p.imports[path] = pkg
+ }
+ p.pkgList = append(p.pkgList, pkg)
+
+ if debug && p.pkgList[0] != pkg {
+ panic("imported packaged not found in pkgList[0]")
+ }
+
+ // read compiler-specific flags
+ p.string() // discard
+
+ // read consts
+ for i := p.int(); i > 0; i-- {
+ name := p.string()
+ typ := p.typ()
+ val := p.value()
+ p.declare(types.NewConst(token.NoPos, pkg, name, typ, val))
+ }
+
+ // read vars
+ for i := p.int(); i > 0; i-- {
+ name := p.string()
+ typ := p.typ()
+ p.declare(types.NewVar(token.NoPos, pkg, name, typ))
+ }
+
+ // read funcs
+ for i := p.int(); i > 0; i-- {
+ name := p.string()
+ sig := p.typ().(*types.Signature)
+ p.int() // read and discard index of inlined function body
+ p.declare(types.NewFunc(token.NoPos, pkg, name, sig))
+ }
+
+ // read types
+ for i := p.int(); i > 0; i-- {
+ // name is parsed as part of named type and the
+ // type object is added to scope via respective
+ // named type
+ _ = p.typ().(*types.Named)
+ }
+
+ // ignore compiler-specific import data
+
+ // complete interfaces
+ for _, typ := range p.typList {
+ if it, ok := typ.(*types.Interface); ok {
+ it.Complete()
+ }
+ }
+
+ // record all referenced packages as imports
+ list := append(([]*types.Package)(nil), p.pkgList[1:]...)
+ sort.Sort(byPath(list))
+ pkg.SetImports(list)
+
+ // package was imported completely and without errors
+ pkg.MarkComplete()
+
+ return p.read, pkg, nil
+}
+
+type importer struct {
+ imports map[string]*types.Package
+ data []byte
+ buf []byte // for reading strings
+ bufarray [64]byte // initial underlying array for buf, large enough to avoid allocation when compiling std lib
+ pkgList []*types.Package
+ typList []types.Type
+
+ debugFormat bool
+ read int // bytes read
+}
+
+func (p *importer) declare(obj types.Object) {
+ if alt := p.pkgList[0].Scope().Insert(obj); alt != nil {
+ // This can only happen if we import a package a second time.
+ panic(fmt.Sprintf("%s already declared", alt.Name()))
+ }
+}
+
+func (p *importer) pkg() *types.Package {
+ // if the package was seen before, i is its index (>= 0)
+ i := p.tagOrIndex()
+ if i >= 0 {
+ return p.pkgList[i]
+ }
+
+ // otherwise, i is the package tag (< 0)
+ if i != packageTag {
+ panic(fmt.Sprintf("unexpected package tag %d", i))
+ }
+
+ // read package data
+ name := p.string()
+ path := p.string()
+
+ // we should never see an empty package name
+ if name == "" {
+ panic("empty package name in import")
+ }
+
+ // we should never see an empty import path
+ if path == "" {
+ panic("empty import path")
+ }
+
+ // if the package was imported before, use that one; otherwise create a new one
+ pkg := p.imports[path]
+ if pkg == nil {
+ pkg = types.NewPackage(path, name)
+ p.imports[path] = pkg
+ }
+ p.pkgList = append(p.pkgList, pkg)
+
+ return pkg
+}
+
+func (p *importer) record(t types.Type) {
+ p.typList = append(p.typList, t)
+}
+
+// A dddSlice is a types.Type representing ...T parameters.
+// It only appears for parameter types and does not escape
+// the importer.
+type dddSlice struct {
+ elem types.Type
+}
+
+func (t *dddSlice) Underlying() types.Type { return t }
+func (t *dddSlice) String() string { return "..." + t.elem.String() }
+
+func (p *importer) typ() types.Type {
+ // if the type was seen before, i is its index (>= 0)
+ i := p.tagOrIndex()
+ if i >= 0 {
+ return p.typList[i]
+ }
+
+ // otherwise, i is the type tag (< 0)
+ switch i {
+ case namedTag:
+ // read type object
+ name := p.string()
+ tpkg := p.pkg()
+ scope := tpkg.Scope()
+ obj := scope.Lookup(name)
+
+ // if the object doesn't exist yet, create and insert it
+ if obj == nil {
+ obj = types.NewTypeName(token.NoPos, tpkg, name, nil)
+ scope.Insert(obj)
+ }
+
+ if _, ok := obj.(*types.TypeName); !ok {
+ panic(fmt.Sprintf("pkg = %s, name = %s => %s", tpkg, name, obj))
+ }
+
+ // associate new named type with obj if it doesn't exist yet
+ t0 := types.NewNamed(obj.(*types.TypeName), nil, nil)
+
+ // but record the existing type, if any
+ t := obj.Type().(*types.Named)
+ p.record(t)
+
+ // read underlying type
+ t0.SetUnderlying(p.typ())
+
+ // interfaces don't have associated methods
+ if _, ok := t0.Underlying().(*types.Interface); ok {
+ return t
+ }
+
+ // read associated methods
+ for i := p.int(); i > 0; i-- {
+ name := p.string()
+ recv, _ := p.paramList() // TODO(gri) do we need a full param list for the receiver?
+ params, isddd := p.paramList()
+ result, _ := p.paramList()
+ p.int() // read and discard index of inlined function body
+ sig := types.NewSignature(recv.At(0), params, result, isddd)
+ t0.AddMethod(types.NewFunc(token.NoPos, tpkg, name, sig))
+ }
+
+ return t
+
+ case arrayTag:
+ t := new(types.Array)
+ p.record(t)
+
+ n := p.int64()
+ *t = *types.NewArray(p.typ(), n)
+ return t
+
+ case sliceTag:
+ t := new(types.Slice)
+ p.record(t)
+
+ *t = *types.NewSlice(p.typ())
+ return t
+
+ case dddTag:
+ t := new(dddSlice)
+ p.record(t)
+
+ t.elem = p.typ()
+ return t
+
+ case structTag:
+ t := new(types.Struct)
+ p.record(t)
+
+ n := p.int()
+ fields := make([]*types.Var, n)
+ tags := make([]string, n)
+ for i := range fields {
+ fields[i] = p.field()
+ tags[i] = p.string()
+ }
+ *t = *types.NewStruct(fields, tags)
+ return t
+
+ case pointerTag:
+ t := new(types.Pointer)
+ p.record(t)
+
+ *t = *types.NewPointer(p.typ())
+ return t
+
+ case signatureTag:
+ t := new(types.Signature)
+ p.record(t)
+
+ params, isddd := p.paramList()
+ result, _ := p.paramList()
+ *t = *types.NewSignature(nil, params, result, isddd)
+ return t
+
+ case interfaceTag:
+ // Create a dummy entry in the type list. This is safe because we
+ // cannot expect the interface type to appear in a cycle, as any
+ // such cycle must contain a named type which would have been
+ // first defined earlier.
+ n := len(p.typList)
+ p.record(nil)
+
+ // no embedded interfaces with gc compiler
+ if p.int() != 0 {
+ panic("unexpected embedded interface")
+ }
+
+ // read methods
+ methods := make([]*types.Func, p.int())
+ for i := range methods {
+ pkg, name := p.fieldName()
+ params, isddd := p.paramList()
+ result, _ := p.paramList()
+ sig := types.NewSignature(nil, params, result, isddd)
+ methods[i] = types.NewFunc(token.NoPos, pkg, name, sig)
+ }
+
+ t := types.NewInterface(methods, nil)
+ p.typList[n] = t
+ return t
+
+ case mapTag:
+ t := new(types.Map)
+ p.record(t)
+
+ key := p.typ()
+ val := p.typ()
+ *t = *types.NewMap(key, val)
+ return t
+
+ case chanTag:
+ t := new(types.Chan)
+ p.record(t)
+
+ var dir types.ChanDir
+ // tag values must match the constants in cmd/compile/internal/gc/go.go
+ switch d := p.int(); d {
+ case 1 /* Crecv */ :
+ dir = types.RecvOnly
+ case 2 /* Csend */ :
+ dir = types.SendOnly
+ case 3 /* Cboth */ :
+ dir = types.SendRecv
+ default:
+ panic(fmt.Sprintf("unexpected channel dir %d", d))
+ }
+ val := p.typ()
+ *t = *types.NewChan(dir, val)
+ return t
+
+ default:
+ panic(fmt.Sprintf("unexpected type tag %d", i))
+ }
+}
+
+func (p *importer) field() *types.Var {
+ pkg, name := p.fieldName()
+ typ := p.typ()
+
+ anonymous := false
+ if name == "" {
+ // anonymous field - typ must be T or *T and T must be a type name
+ switch typ := deref(typ).(type) {
+ case *types.Basic: // basic types are named types
+ name = typ.Name()
+ case *types.Named:
+ pkg = p.pkgList[0]
+ name = typ.Obj().Name()
+ default:
+ panic("anonymous field expected")
+ }
+ anonymous = true
+ }
+
+ return types.NewField(token.NoPos, pkg, name, typ, anonymous)
+}
+
+func (p *importer) fieldName() (*types.Package, string) {
+ name := p.string()
+ if name == "" {
+ return nil, "" // anonymous field
+ }
+ pkg := p.pkgList[0]
+ if name == "?" || name != "_" && !exported(name) {
+ if name == "?" {
+ name = ""
+ }
+ pkg = p.pkg()
+ }
+ return pkg, name
+}
+
+func (p *importer) paramList() (*types.Tuple, bool) {
+ n := p.int()
+ if n == 0 {
+ return nil, false
+ }
+ // negative length indicates unnamed parameters
+ named := true
+ if n < 0 {
+ n = -n
+ named = false
+ }
+ // n > 0
+ params := make([]*types.Var, n)
+ isddd := false
+ for i := range params {
+ params[i], isddd = p.param(named)
+ }
+ return types.NewTuple(params...), isddd
+}
+
+func (p *importer) param(named bool) (*types.Var, bool) {
+ t := p.typ()
+ td, isddd := t.(*dddSlice)
+ if isddd {
+ t = types.NewSlice(td.elem)
+ }
+
+ var name string
+ if named {
+ name = p.string()
+ if name == "" {
+ panic("expected named parameter")
+ }
+ }
+
+ // read and discard compiler-specific info
+ p.string()
+
+ return types.NewVar(token.NoPos, nil, name, t), isddd
+}
+
+func exported(name string) bool {
+ ch, _ := utf8.DecodeRuneInString(name)
+ return unicode.IsUpper(ch)
+}
+
+func (p *importer) value() constant.Value {
+ switch tag := p.tagOrIndex(); tag {
+ case falseTag:
+ return constant.MakeBool(false)
+ case trueTag:
+ return constant.MakeBool(true)
+ case int64Tag:
+ return constant.MakeInt64(p.int64())
+ case floatTag:
+ return p.float()
+ case complexTag:
+ re := p.float()
+ im := p.float()
+ return constant.BinaryOp(re, token.ADD, constant.MakeImag(im))
+ case stringTag:
+ return constant.MakeString(p.string())
+ default:
+ panic(fmt.Sprintf("unexpected value tag %d", tag))
+ }
+}
+
+func (p *importer) float() constant.Value {
+ sign := p.int()
+ if sign == 0 {
+ return constant.MakeInt64(0)
+ }
+
+ exp := p.int()
+ mant := []byte(p.string()) // big endian
+
+ // remove leading 0's if any
+ for len(mant) > 0 && mant[0] == 0 {
+ mant = mant[1:]
+ }
+
+ // convert to little endian
+ // TODO(gri) go/constant should have a more direct conversion function
+ // (e.g., once it supports a big.Float based implementation)
+ for i, j := 0, len(mant)-1; i < j; i, j = i+1, j-1 {
+ mant[i], mant[j] = mant[j], mant[i]
+ }
+
+ // adjust exponent (constant.MakeFromBytes creates an integer value,
+ // but mant represents the mantissa bits such that 0.5 <= mant < 1.0)
+ exp -= len(mant) << 3
+ if len(mant) > 0 {
+ for msd := mant[len(mant)-1]; msd&0x80 == 0; msd <<= 1 {
+ exp++
+ }
+ }
+
+ x := constant.MakeFromBytes(mant)
+ switch {
+ case exp < 0:
+ d := constant.Shift(constant.MakeInt64(1), token.SHL, uint(-exp))
+ x = constant.BinaryOp(x, token.QUO, d)
+ case exp > 0:
+ x = constant.Shift(x, token.SHL, uint(exp))
+ }
+
+ if sign < 0 {
+ x = constant.UnaryOp(token.SUB, x, 0)
+ }
+ return x
+}
+
+// ----------------------------------------------------------------------------
+// Low-level decoders
+
+func (p *importer) tagOrIndex() int {
+ if p.debugFormat {
+ p.marker('t')
+ }
+
+ return int(p.rawInt64())
+}
+
+func (p *importer) int() int {
+ x := p.int64()
+ if int64(int(x)) != x {
+ panic("exported integer too large")
+ }
+ return int(x)
+}
+
+func (p *importer) int64() int64 {
+ if p.debugFormat {
+ p.marker('i')
+ }
+
+ return p.rawInt64()
+}
+
+func (p *importer) string() string {
+ if p.debugFormat {
+ p.marker('s')
+ }
+
+ if n := int(p.rawInt64()); n > 0 {
+ if cap(p.buf) < n {
+ p.buf = make([]byte, n)
+ } else {
+ p.buf = p.buf[:n]
+ }
+ for i := 0; i < n; i++ {
+ p.buf[i] = p.byte()
+ }
+ return string(p.buf)
+ }
+
+ return ""
+}
+
+func (p *importer) marker(want byte) {
+ if got := p.byte(); got != want {
+ panic(fmt.Sprintf("incorrect marker: got %c; want %c (pos = %d)", got, want, p.read))
+ }
+
+ pos := p.read
+ if n := int(p.rawInt64()); n != pos {
+ panic(fmt.Sprintf("incorrect position: got %d; want %d", n, pos))
+ }
+}
+
+// rawInt64 should only be used by low-level decoders
+func (p *importer) rawInt64() int64 {
+ i, err := binary.ReadVarint(p)
+ if err != nil {
+ panic(fmt.Sprintf("read error: %v", err))
+ }
+ return i
+}
+
+// needed for binary.ReadVarint in rawInt64
+func (p *importer) ReadByte() (byte, error) {
+ return p.byte(), nil
+}
+
+// byte is the bottleneck interface for reading p.data.
+// It unescapes '|' 'S' to '$' and '|' '|' to '|'.
+func (p *importer) byte() byte {
+ b := p.data[0]
+ r := 1
+ if b == '|' {
+ b = p.data[1]
+ r = 2
+ switch b {
+ case 'S':
+ b = '$'
+ case '|':
+ // nothing to do
+ default:
+ panic("unexpected escape sequence in export data")
+ }
+ }
+ p.data = p.data[r:]
+ p.read += r
+ return b
+
+}
+
+// ----------------------------------------------------------------------------
+// Export format
+
+// Tags. Must be < 0.
+const (
+ // Packages
+ packageTag = -(iota + 1)
+
+ // Types
+ namedTag
+ arrayTag
+ sliceTag
+ dddTag
+ structTag
+ pointerTag
+ signatureTag
+ interfaceTag
+ mapTag
+ chanTag
+
+ // Values
+ falseTag
+ trueTag
+ int64Tag
+ floatTag
+ fractionTag // not used by gc
+ complexTag
+ stringTag
+)
+
+var predeclared = []types.Type{
+ // basic types
+ types.Typ[types.Bool],
+ types.Typ[types.Int],
+ types.Typ[types.Int8],
+ types.Typ[types.Int16],
+ types.Typ[types.Int32],
+ types.Typ[types.Int64],
+ types.Typ[types.Uint],
+ types.Typ[types.Uint8],
+ types.Typ[types.Uint16],
+ types.Typ[types.Uint32],
+ types.Typ[types.Uint64],
+ types.Typ[types.Uintptr],
+ types.Typ[types.Float32],
+ types.Typ[types.Float64],
+ types.Typ[types.Complex64],
+ types.Typ[types.Complex128],
+ types.Typ[types.String],
+
+ // aliases
+ types.Universe.Lookup("byte").Type(),
+ types.Universe.Lookup("rune").Type(),
+
+ // error
+ types.Universe.Lookup("error").Type(),
+
+ // untyped types
+ types.Typ[types.UntypedBool],
+ types.Typ[types.UntypedInt],
+ types.Typ[types.UntypedRune],
+ types.Typ[types.UntypedFloat],
+ types.Typ[types.UntypedComplex],
+ types.Typ[types.UntypedString],
+ types.Typ[types.UntypedNil],
+
+ // package unsafe
+ types.Typ[types.UnsafePointer],
+}
// FindExportData positions the reader r at the beginning of the
// export data section of an underlying GC-created object/archive
// file by reading from it. The reader must be positioned at the
-// start of the file before calling this function.
+// start of the file before calling this function. The hdr result
+// is the string before the export data, either "$$" or "$$B".
//
-func FindExportData(r *bufio.Reader) (err error) {
+func FindExportData(r *bufio.Reader) (hdr string, err error) {
// Read first line to make sure this is an object file.
line, err := r.ReadSlice('\n')
if err != nil {
return
}
+
if string(line) == "!<arch>\n" {
// Archive file. Scan to __.PKGDEF.
var name string
}
// Skip over object header to export data.
- // Begins after first line with $$.
+ // Begins after first line starting with $$.
for line[0] != '$' {
if line, err = r.ReadSlice('\n'); err != nil {
return
}
}
+ hdr = string(line)
return
}
"go/build"
"go/token"
"io"
+ "io/ioutil"
"os"
"path/filepath"
"sort"
}
}()
+ var hdr string
buf := bufio.NewReader(f)
- if err = FindExportData(buf); err != nil {
+ if hdr, err = FindExportData(buf); err != nil {
return
}
- pkg, err = ImportData(packages, filename, id, buf)
+ switch hdr {
+ case "$$\n":
+ return ImportData(packages, filename, id, buf)
+ case "$$B\n":
+ var data []byte
+ data, err = ioutil.ReadAll(buf)
+ if err == nil {
+ _, pkg, err = BImportData(packages, data, path)
+ return
+ }
+ default:
+ err = fmt.Errorf("unknown export data header: %q", hdr)
+ }
return
}
return filepath.Join(dirname, filename[:len(filename)-2]+"o")
}
-// Use the same global imports map for all tests. The effect is
-// as if all tested packages were imported into a single package.
-var imports = make(map[string]*types.Package)
+// TODO(gri) Remove this function once we switched to new export format by default.
+func compileNewExport(t *testing.T, dirname, filename string) string {
+ testenv.MustHaveGoBuild(t)
+ cmd := exec.Command("go", "tool", "compile", "-newexport", filename)
+ cmd.Dir = dirname
+ out, err := cmd.CombinedOutput()
+ if err != nil {
+ t.Logf("%s", out)
+ t.Fatalf("go tool compile %s failed: %s", filename, err)
+ }
+ // filename should end with ".go"
+ return filepath.Join(dirname, filename[:len(filename)-2]+"o")
+}
func testPath(t *testing.T, path string) *types.Package {
t0 := time.Now()
- pkg, err := Import(imports, path)
+ pkg, err := Import(make(map[string]*types.Package), path)
if err != nil {
t.Errorf("testPath(%s): %s", path, err)
return nil
return
}
-func TestImport(t *testing.T) {
+func TestImportTestdata(t *testing.T) {
// This package only handles gc export data.
if runtime.Compiler != "gc" {
t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
defer os.Remove(outFn)
}
- nimports := 0
if pkg := testPath(t, "./testdata/exports"); pkg != nil {
- nimports++
- // The package's Imports should include all the types
- // referenced by the exportdata, which may be more than
- // the import statements in the package's source, but
- // fewer than the transitive closure of dependencies.
- want := `[package ast ("go/ast") package token ("go/token") package runtime ("runtime")]`
+ // The package's Imports list must include all packages
+ // explicitly imported by exports.go, plus all packages
+ // referenced indirectly via exported objects in exports.go.
+ // With the textual export format, the list may also include
+ // additional packages that are not strictly required for
+ // import processing alone (they are exported to err "on
+ // the safe side").
+ got := fmt.Sprint(pkg.Imports())
+ for _, want := range []string{"go/ast", "go/token"} {
+ if !strings.Contains(got, want) {
+ t.Errorf(`Package("exports").Imports() = %s, does not contain %s`, got, want)
+ }
+ }
+ }
+}
+
+// TODO(gri) Remove this function once we switched to new export format by default
+// (and update the comment and want list in TestImportTestdata).
+func TestImportTestdataNewExport(t *testing.T) {
+ // This package only handles gc export data.
+ if runtime.Compiler != "gc" {
+ t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
+ return
+ }
+
+ if outFn := compileNewExport(t, "testdata", "exports.go"); outFn != "" {
+ defer os.Remove(outFn)
+ }
+
+ if pkg := testPath(t, "./testdata/exports"); pkg != nil {
+ // The package's Imports list must include all packages
+ // explicitly imported by exports.go, plus all packages
+ // referenced indirectly via exported objects in exports.go.
+ want := `[package ast ("go/ast") package token ("go/token")]`
got := fmt.Sprint(pkg.Imports())
if got != want {
t.Errorf(`Package("exports").Imports() = %s, want %s`, got, want)
}
}
- nimports += testDir(t, "", time.Now().Add(maxTime)) // installed packages
+}
+
+func TestImportStdLib(t *testing.T) {
+ skipSpecialPlatforms(t)
+
+ // This package only handles gc export data.
+ if runtime.Compiler != "gc" {
+ t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
+ return
+ }
+
+ nimports := testDir(t, "", time.Now().Add(maxTime)) // installed packages
t.Logf("tested %d imports", nimports)
}
importPath := s[0]
objName := s[1]
- pkg, err := Import(imports, importPath)
+ pkg, err := Import(make(map[string]*types.Package), importPath)
if err != nil {
t.Error(err)
continue
// The Qualifier controls the printing of
// package-level objects, and may be nil.
func WriteType(buf *bytes.Buffer, typ Type, qf Qualifier) {
- writeType(buf, typ, qf, make([]Type, 8))
+ writeType(buf, typ, qf, make([]Type, 0, 8))
}
func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) {
// The Qualifier controls the printing of
// package-level objects, and may be nil.
func WriteSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier) {
- writeSignature(buf, sig, qf, make([]Type, 8))
+ writeSignature(buf, sig, qf, make([]Type, 0, 8))
}
func writeSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier, visited []Type) {
this *Package
want string
}{
+ {nil, nil, "<nil>"},
{pT, nil, "p.T"},
{pT, p, "T"},
{pT, q, "p.T"},
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build 386 arm arm64 ppc64 ppc64le
+// +build 386 arm arm64 mips64 mips64le ppc64 ppc64le
package crc32
// Clone t0 as t4. Redefining the "lhs" template should not fail.
t4 := Must(t0.Clone())
if _, err := t4.Parse(`{{define "lhs"}} OK {{end}}`); err != nil {
- t.Error(`redefine "lhs": got err %v want non-nil`, err)
+ t.Errorf(`redefine "lhs": got err %v want nil`, err)
}
// Cloning t1 should fail as it has been executed.
if _, err := t1.Clone(); err == nil {
set: make(map[string]*Template),
},
}
+ ret.set[ret.Name()] = ret
for _, x := range textClone.Templates() {
name := x.Name()
src := t.set[name]
--- /dev/null
+package template
+
+import (
+ "bytes"
+ "testing"
+)
+
+func TestTemplateClone(t *testing.T) {
+ // https://golang.org/issue/12996
+ orig := New("name")
+ clone, err := orig.Clone()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(clone.Templates()) != len(orig.Templates()) {
+ t.Fatalf("Invalid lenth of t.Clone().Templates()")
+ }
+
+ const want = "stuff"
+ parsed := Must(clone.Parse(want))
+ var buf bytes.Buffer
+ err = parsed.Execute(&buf, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if got := buf.String(); got != want {
+ t.Fatalf("got %q; want %q", got, want)
+ }
+}
package unix
import (
- "runtime"
"sync/atomic"
"syscall"
"unsafe"
)
-var randomTrap = map[string]uintptr{
- "386": 355,
- "amd64": 318,
- "arm": 384,
- "ppc64": 359,
- "ppc64le": 359,
-}[runtime.GOARCH]
-
var randomUnsupported int32 // atomic
// GetRandomFlag is a flag supported by the getrandom system call.
--- /dev/null
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package unix
+
+const randomTrap uintptr = 355
--- /dev/null
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package unix
+
+const randomTrap uintptr = 318
--- /dev/null
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package unix
+
+const randomTrap uintptr = 384
--- /dev/null
+// 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 arm64
+
+package unix
+
+const randomTrap uintptr = 278
--- /dev/null
+// Copyright 2015 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 mips64 mips64le
+
+package unix
+
+const randomTrap uintptr = 5313
--- /dev/null
+// 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 ppc64 ppc64le
+
+package unix
+
+const randomTrap uintptr = 359
var crashy = false
+func testableNetwork(network string) bool {
+ switch network {
+ case "unix", "unixgram":
+ switch runtime.GOOS {
+ case "darwin":
+ switch runtime.GOARCH {
+ case "arm", "arm64":
+ return false
+ }
+ case "android":
+ return false
+ }
+ }
+ return true
+}
+
func runStreamSyslog(l net.Listener, done chan<- string, wg *sync.WaitGroup) {
for {
var c net.Conn
func TestWithSimulated(t *testing.T) {
msg := "Test 123"
- transport := []string{"unix", "unixgram", "udp", "tcp"}
-
- if runtime.GOOS == "darwin" {
- switch runtime.GOARCH {
- case "arm", "arm64":
- transport = []string{"udp", "tcp"}
+ var transport []string
+ for _, n := range []string{"unix", "unixgram", "udp", "tcp"} {
+ if testableNetwork(n) {
+ transport = append(transport, n)
}
}
}
func TestFlap(t *testing.T) {
- if runtime.GOOS == "darwin" {
- switch runtime.GOARCH {
- case "arm", "arm64":
- t.Skipf("skipping on %s/%s", runtime.GOOS, runtime.GOARCH)
- }
+ net := "unix"
+ if !testableNetwork(net) {
+ t.Skipf("skipping on %s/%s; 'unix' is not supported", runtime.GOOS, runtime.GOARCH)
}
- net := "unix"
done := make(chan string)
addr, sock, srvWG := startServer(net, "", done)
defer srvWG.Wait()
const N = 10
const M = 100
net := "unix"
- if runtime.GOOS == "darwin" {
- switch runtime.GOARCH {
- case "arm", "arm64":
- net = "tcp"
+ if !testableNetwork(net) {
+ net = "tcp"
+ if !testableNetwork(net) {
+ t.Skipf("skipping on %s/%s; neither 'unix' or 'tcp' is supported", runtime.GOOS, runtime.GOARCH)
}
}
done := make(chan string, N*M)
// Special cases are:
// Abs(±Inf) = +Inf
// Abs(NaN) = NaN
-func Abs(x float64) float64
-
-func abs(x float64) float64 {
- switch {
- case x < 0:
+func Abs(x float64) float64 {
+ // TODO: once golang.org/issue/13095 is fixed, change this to:
+ // return Float64frombits(Float64bits(x) &^ (1 << 63))
+ // But for now, this generates better code and can also be inlined:
+ if x < 0 {
return -x
- case x == 0:
+ }
+ if x == 0 {
return 0 // return correctly abs(-0)
}
return x
+++ /dev/null
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "textflag.h"
-
-// func Abs(x float64) float64
-TEXT ·Abs(SB),NOSPLIT,$0
- FMOVD x+0(FP), F0 // F0=x
- FABS // F0=|x|
- FMOVDP F0, ret+8(FP)
- RET
+++ /dev/null
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "textflag.h"
-
-// func Abs(x float64) float64
-TEXT ·Abs(SB),NOSPLIT,$0
- MOVQ $(1<<63), BX
- MOVQ BX, X0 // movsd $(-0.0), x0
- MOVSD x+0(FP), X1
- ANDNPD X1, X0
- MOVSD X0, ret+8(FP)
- RET
+++ /dev/null
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "textflag.h"
-
-TEXT ·Abs(SB),NOSPLIT,$0
- MOVW x_lo+0(FP), R0
- MOVW x_hi+4(FP), R1
- AND $((1<<31)-1), R1
- MOVW R0, ret_lo+8(FP)
- MOVW R1, ret_hi+12(FP)
- RET
+++ /dev/null
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "textflag.h"
-
-TEXT ·Abs(SB),NOSPLIT,$0-16
- FMOVD x+0(FP), F3
- FABSD F3, F3
- FMOVD F3, ret+8(FP)
- RET
+++ /dev/null
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build ppc64 ppc64le
-
-#include "textflag.h"
-
-TEXT ·Abs(SB),NOSPLIT,$0-16
- MOVD x+0(FP), R3
- MOVD $((1<<63)-1), R4
- AND R4, R3
- MOVD R3, ret+8(FP)
- RET
1.842068661871398836913874273e-02,
-8.3193870863553801814961137573e-02,
}
+var expm1Large = []float64{
+ 4.2031418113550844e+21,
+ 4.0690789717473863e+33,
+ -0.9372627915981363e+00,
+ -1.0,
+ 7.077694784145933e+41,
+ 5.117936223839153e+12,
+ 5.124137759001189e+22,
+ 7.03546003972584e+11,
+ 8.456921800389698e+07,
+ -1.0,
+}
var exp2 = []float64{
3.1537839463286288034313104e+01,
2.1361549283756232296144849e+02,
0,
Inf(1),
NaN(),
+ Float64frombits(2), // subnormal; see https://golang.org/issue/13013
}
var sqrtSC = []float64{
NaN(),
0,
Inf(1),
NaN(),
+ 3.1434555694052576e-162,
}
var vftanhSC = []float64{
t.Errorf("Expm1(%g) = %g, want %g", a, f, expm1[i])
}
}
+ for i := 0; i < len(vf); i++ {
+ a := vf[i] * 10
+ if f := Expm1(a); !close(expm1Large[i], f) {
+ t.Errorf("Expm1(%g) = %g, want %g", a, f, expm1Large[i])
+ }
+ }
for i := 0; i < len(vfexpm1SC); i++ {
if f := Expm1(vfexpm1SC[i]); !alike(expm1SC[i], f) {
t.Errorf("Expm1(%g) = %g, want %g", vfexpm1SC[i], f, expm1SC[i])
--- /dev/null
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !math_big_pure_go,mips64 !math_big_pure_go,mips64le
+
+#include "textflag.h"
+
+// This file provides fast assembly versions for the elementary
+// arithmetic operations on vectors implemented in arith.go.
+
+TEXT ·mulWW(SB),NOSPLIT,$0
+ JMP ·mulWW_g(SB)
+
+TEXT ·divWW(SB),NOSPLIT,$0
+ JMP ·divWW_g(SB)
+
+TEXT ·addVV(SB),NOSPLIT,$0
+ JMP ·addVV_g(SB)
+
+TEXT ·subVV(SB),NOSPLIT,$0
+ JMP ·subVV_g(SB)
+
+TEXT ·addVW(SB),NOSPLIT,$0
+ JMP ·addVW_g(SB)
+
+TEXT ·subVW(SB),NOSPLIT,$0
+ JMP ·subVW_g(SB)
+
+TEXT ·shlVU(SB),NOSPLIT,$0
+ JMP ·shlVU_g(SB)
+
+TEXT ·shrVU(SB),NOSPLIT,$0
+ JMP ·shrVU_g(SB)
+
+TEXT ·mulAddVWW(SB),NOSPLIT,$0
+ JMP ·mulAddVWW_g(SB)
+
+TEXT ·addMulVVW(SB),NOSPLIT,$0
+ JMP ·addMulVVW_g(SB)
+
+TEXT ·divWVW(SB),NOSPLIT,$0
+ JMP ·divWVW_g(SB)
+
+TEXT ·bitLen(SB),NOSPLIT,$0
+ JMP ·bitLen_g(SB)
// not require 0.5 <= |mant| < 1.0. Specifically:
//
// mant := new(Float)
-// new(Float).SetMantExp(mant, x.SetMantExp(mant)).Cmp(x).Eql() is true
+// new(Float).SetMantExp(mant, x.MantExp(mant)).Cmp(x) == 0
//
// Special cases are:
//
y = Float64frombits(Float64bits(y) + uint64(k)<<52) // add k to y's exponent
return y
}
- t := Float64frombits(uint64((0x3ff - k) << 52)) // 2**-k
+ t := Float64frombits(uint64(0x3ff-k) << 52) // 2**-k
y := x - (e + t)
y += 1
y = Float64frombits(Float64bits(y) + uint64(k)<<52) // add k to y's exponent
// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n).
func (r *Rand) Perm(n int) []int {
m := make([]int, n)
+ // In the following loop, the iteration when i=0 always swaps m[0] with m[0].
+ // A change to remove this useless iteration is to assign 1 to i in the init
+ // statement. But Perm also effects r. Making this change will affect
+ // the final state of r. So this change can't be made for compatibility
+ // reasons for Go 1.
for i := 0; i < n; i++ {
j := r.Intn(i + 1)
m[i] = m[j]
// normalize x
exp := int((ix >> shift) & mask)
if exp == 0 { // subnormal x
- for ix&1<<shift == 0 {
+ for ix&(1<<shift) == 0 {
ix <<= 1
exp--
}
--- /dev/null
+// 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 mips64 mips64le
+
+#include "textflag.h"
+
+TEXT ·Asin(SB),NOSPLIT,$0
+ JMP ·asin(SB)
+
+TEXT ·Acos(SB),NOSPLIT,$0
+ JMP ·acos(SB)
+
+TEXT ·Atan2(SB),NOSPLIT,$0
+ JMP ·atan2(SB)
+
+TEXT ·Atan(SB),NOSPLIT,$0
+ JMP ·atan(SB)
+
+TEXT ·Dim(SB),NOSPLIT,$0
+ JMP ·dim(SB)
+
+TEXT ·Min(SB),NOSPLIT,$0
+ JMP ·min(SB)
+
+TEXT ·Max(SB),NOSPLIT,$0
+ JMP ·max(SB)
+
+TEXT ·Exp2(SB),NOSPLIT,$0
+ JMP ·exp2(SB)
+
+TEXT ·Expm1(SB),NOSPLIT,$0
+ JMP ·expm1(SB)
+
+TEXT ·Exp(SB),NOSPLIT,$0
+ JMP ·exp(SB)
+
+TEXT ·Floor(SB),NOSPLIT,$0
+ JMP ·floor(SB)
+
+TEXT ·Ceil(SB),NOSPLIT,$0
+ JMP ·ceil(SB)
+
+TEXT ·Trunc(SB),NOSPLIT,$0
+ JMP ·trunc(SB)
+
+TEXT ·Frexp(SB),NOSPLIT,$0
+ JMP ·frexp(SB)
+
+TEXT ·Hypot(SB),NOSPLIT,$0
+ JMP ·hypot(SB)
+
+TEXT ·Ldexp(SB),NOSPLIT,$0
+ JMP ·ldexp(SB)
+
+TEXT ·Log10(SB),NOSPLIT,$0
+ JMP ·log10(SB)
+
+TEXT ·Log2(SB),NOSPLIT,$0
+ JMP ·log2(SB)
+
+TEXT ·Log1p(SB),NOSPLIT,$0
+ JMP ·log1p(SB)
+
+TEXT ·Log(SB),NOSPLIT,$0
+ JMP ·log(SB)
+
+TEXT ·Modf(SB),NOSPLIT,$0
+ JMP ·modf(SB)
+
+TEXT ·Mod(SB),NOSPLIT,$0
+ JMP ·mod(SB)
+
+TEXT ·Remainder(SB),NOSPLIT,$0
+ JMP ·remainder(SB)
+
+TEXT ·Sincos(SB),NOSPLIT,$0
+ JMP ·sincos(SB)
+
+TEXT ·Sin(SB),NOSPLIT,$0
+ JMP ·sin(SB)
+
+TEXT ·Cos(SB),NOSPLIT,$0
+ JMP ·cos(SB)
+
+TEXT ·Sqrt(SB),NOSPLIT,$0
+ JMP ·sqrt(SB)
+
+TEXT ·Tan(SB),NOSPLIT,$0
+ JMP ·tan(SB)
{"tcp", "no-such-name:80"},
{"tcp", "mh/astro/r70:http"},
- {"tcp", "127.0.0.1:0"},
- {"udp", "127.0.0.1:0"},
+ {"tcp", JoinHostPort("127.0.0.1", "-1")},
+ {"tcp", JoinHostPort("127.0.0.1", "123456789")},
+ {"udp", JoinHostPort("127.0.0.1", "-1")},
+ {"udp", JoinHostPort("127.0.0.1", "123456789")},
{"ip:icmp", "127.0.0.1"},
{"unix", "/path/to/somewhere"},
for i, tt := range dialErrorTests {
c, err := d.Dial(tt.network, tt.address)
if err == nil {
- t.Errorf("#%d: should fail; %s:%s->%s", i, tt.network, c.LocalAddr(), c.RemoteAddr())
+ t.Errorf("#%d: should fail; %s:%s->%s", i, c.LocalAddr().Network(), c.LocalAddr(), c.RemoteAddr())
c.Close()
continue
}
+ if tt.network == "tcp" || tt.network == "udp" {
+ nerr := err
+ if op, ok := nerr.(*OpError); ok {
+ nerr = op.Err
+ }
+ if sys, ok := nerr.(*os.SyscallError); ok {
+ nerr = sys.Err
+ }
+ if nerr == errOpNotSupported {
+ t.Errorf("#%d: should fail without %v; %s:%s->", i, nerr, tt.network, tt.address)
+ continue
+ }
+ }
if c != nil {
t.Errorf("Dial returned non-nil interface %T(%v) with err != nil", c, c)
}
{"tcp", "no-such-name:80"},
{"tcp", "mh/astro/r70:http"},
- {"tcp", "127.0.0.1:0"},
+ {"tcp", JoinHostPort("127.0.0.1", "-1")},
+ {"tcp", JoinHostPort("127.0.0.1", "123456789")},
{"unix", "/path/to/somewhere"},
{"unixpacket", "/path/to/somewhere"},
for i, tt := range listenErrorTests {
ln, err := Listen(tt.network, tt.address)
if err == nil {
- t.Errorf("#%d: should fail; %s:%s->", i, tt.network, ln.Addr())
+ t.Errorf("#%d: should fail; %s:%s->", i, ln.Addr().Network(), ln.Addr())
ln.Close()
continue
}
+ if tt.network == "tcp" {
+ nerr := err
+ if op, ok := nerr.(*OpError); ok {
+ nerr = op.Err
+ }
+ if sys, ok := nerr.(*os.SyscallError); ok {
+ nerr = sys.Err
+ }
+ if nerr == errOpNotSupported {
+ t.Errorf("#%d: should fail without %v; %s:%s->", i, nerr, tt.network, tt.address)
+ continue
+ }
+ }
if ln != nil {
t.Errorf("Listen returned non-nil interface %T(%v) with err != nil", ln, ln)
}
{"udp", "127.0.0.1:☺"},
{"udp", "no-such-name:80"},
{"udp", "mh/astro/r70:http"},
+
+ {"udp", JoinHostPort("127.0.0.1", "-1")},
+ {"udp", JoinHostPort("127.0.0.1", "123456789")},
}
func TestListenPacketError(t *testing.T) {
for i, tt := range listenPacketErrorTests {
c, err := ListenPacket(tt.network, tt.address)
if err == nil {
- t.Errorf("#%d: should fail; %s:%s->", i, tt.network, c.LocalAddr())
+ t.Errorf("#%d: should fail; %s:%s->", i, c.LocalAddr().Network(), c.LocalAddr())
c.Close()
continue
}
func TestClientWithCorrectTLSServerName(t *testing.T) {
defer afterTest(t)
+
+ const serverName = "example.com"
ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
- if r.TLS.ServerName != "127.0.0.1" {
- t.Errorf("expected client to set ServerName 127.0.0.1, got: %q", r.TLS.ServerName)
+ if r.TLS.ServerName != serverName {
+ t.Errorf("expected client to set ServerName %q, got: %q", serverName, r.TLS.ServerName)
}
}))
defer ts.Close()
- c := &Client{Transport: newTLSTransport(t, ts)}
+ trans := newTLSTransport(t, ts)
+ trans.TLSClientConfig.ServerName = serverName
+ c := &Client{Transport: trans}
if _, err := c.Get(ts.URL); err != nil {
t.Fatalf("expected successful TLS connection, got error: %v", err)
}
var ExportErrRequestCanceled = errRequestCanceled
var ExportServeFile = serveFile
+
+func SetTestHookServerServe(fn func(*Server, net.Listener)) { testHookServerServe = fn }
}
defer ln.Close()
+ syscalls := "sendfile,sendfile64"
+ switch runtime.GOARCH {
+ case "mips64", "mips64le":
+ // mips64 strace doesn't support sendfile64 and will error out
+ // if we specify that with `-e trace='.
+ syscalls = "sendfile"
+ }
+
var buf bytes.Buffer
- child := exec.Command("strace", "-f", "-q", "-e", "trace=sendfile,sendfile64", os.Args[0], "-test.run=TestLinuxSendfileChild")
+ child := exec.Command("strace", "-f", "-q", "-e", "trace="+syscalls, os.Args[0], "-test.run=TestLinuxSendfileChild")
child.ExtraFiles = append(child.ExtraFiles, lnf)
child.Env = append([]string{"GO_WANT_HELPER_PROCESS=1"}, os.Environ()...)
child.Stdout = &buf
-// This file is autogenerated using x/tools/cmd/bundle from
-// https://go-review.googlesource.com/#/c/15850/
-// Usage:
-// $ bundle golang.org/x/net/http2 net/http http2 > /tmp/x.go; mv /tmp/x.go $GOROOT/src/net/http/h2_bundle.go
-
-// Copyright 2015 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.
+// Code generated by golang.org/x/tools/cmd/bundle command:
+// $ bundle golang.org/x/net/http2 net/http http2
+// Package http2 implements the HTTP/2 protocol.
+//
+// This is a work in progress. This package is low-level and intended
+// to be used directly by very few people. Most users will use it
+// indirectly through integration with the net/http package. See
+// ConfigureServer. That ConfigureServer call will likely be automatic
+// or available via an empty import in the future.
+//
+// See http://http2.github.io/
+//
package http
import (
"encoding/binary"
"errors"
"fmt"
+ "golang.org/x/net/http2/hpack"
"io"
+ "io/ioutil"
"log"
"net"
"net/url"
"strings"
"sync"
"time"
-
- "golang.org/x/net/http2/hpack"
)
-// buffer is an io.ReadWriteCloser backed by a fixed size buffer.
-// It never allocates, but moves old data as new data is written.
-type http2buffer struct {
- buf []byte
- r, w int
- closed bool
- err error // err to return to reader
+// ClientConnPool manages a pool of HTTP/2 client connections.
+type http2ClientConnPool interface {
+ GetClientConn(req *Request, addr string) (*http2ClientConn, error)
+ MarkDead(*http2ClientConn)
}
-var (
- http2errReadEmpty = errors.New("read from empty buffer")
- http2errWriteClosed = errors.New("write on closed buffer")
- http2errWriteFull = errors.New("write on full buffer")
-)
+type http2clientConnPool struct {
+ t *http2Transport
+ mu sync.Mutex // TODO: switch to RWMutex
+ // TODO: add support for sharing conns based on cert names
+ // (e.g. share conn for googleapis.com and appspot.com)
+ conns map[string][]*http2ClientConn // key is host:port
+ keys map[*http2ClientConn][]string
+}
-// Read copies bytes from the buffer into p.
-// It is an error to read when no data is available.
-func (b *http2buffer) Read(p []byte) (n int, err error) {
- n = copy(p, b.buf[b.r:b.w])
- b.r += n
- if b.closed && b.r == b.w {
- err = b.err
- } else if b.r == b.w && n == 0 {
- err = http2errReadEmpty
+func (p *http2clientConnPool) GetClientConn(req *Request, addr string) (*http2ClientConn, error) {
+ return p.getClientConn(req, addr, true)
+}
+
+func (p *http2clientConnPool) getClientConn(req *Request, addr string, dialOnMiss bool) (*http2ClientConn, error) {
+ p.mu.Lock()
+ for _, cc := range p.conns[addr] {
+ if cc.CanTakeNewRequest() {
+ p.mu.Unlock()
+ return cc, nil
+ }
}
- return n, err
+ p.mu.Unlock()
+ if !dialOnMiss {
+ return nil, http2ErrNoCachedConn
+ }
+
+ cc, err := p.t.dialClientConn(addr)
+ if err != nil {
+ return nil, err
+ }
+ p.addConn(addr, cc)
+ return cc, nil
}
-// Len returns the number of bytes of the unread portion of the buffer.
-func (b *http2buffer) Len() int {
- return b.w - b.r
+func (p *http2clientConnPool) addConn(key string, cc *http2ClientConn) {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ if p.conns == nil {
+ p.conns = make(map[string][]*http2ClientConn)
+ }
+ if p.keys == nil {
+ p.keys = make(map[*http2ClientConn][]string)
+ }
+ p.conns[key] = append(p.conns[key], cc)
+ p.keys[cc] = append(p.keys[cc], key)
}
-// Write copies bytes from p into the buffer.
-// It is an error to write more data than the buffer can hold.
-func (b *http2buffer) Write(p []byte) (n int, err error) {
- if b.closed {
- return 0, http2errWriteClosed
+func (p *http2clientConnPool) MarkDead(cc *http2ClientConn) {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ for _, key := range p.keys[cc] {
+ vv, ok := p.conns[key]
+ if !ok {
+ continue
+ }
+ newList := http2filterOutClientConn(vv, cc)
+ if len(newList) > 0 {
+ p.conns[key] = newList
+ } else {
+ delete(p.conns, key)
+ }
}
+ delete(p.keys, cc)
+}
- if b.r > 0 && len(p) > len(b.buf)-b.w {
- copy(b.buf, b.buf[b.r:b.w])
- b.w -= b.r
- b.r = 0
+func (p *http2clientConnPool) closeIdleConnections() {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+
+ for _, vv := range p.conns {
+ for _, cc := range vv {
+ cc.closeIfIdle()
+ }
}
+}
- n = copy(b.buf[b.w:], p)
- b.w += n
- if n < len(p) {
- err = http2errWriteFull
+func http2filterOutClientConn(in []*http2ClientConn, exclude *http2ClientConn) []*http2ClientConn {
+ out := in[:0]
+ for _, v := range in {
+ if v != exclude {
+ out = append(out, v)
+ }
}
- return n, err
+
+ if len(in) != len(out) {
+ in[len(in)-1] = nil
+ }
+ return out
+}
+
+func http2configureTransport(t1 *Transport) error {
+ connPool := new(http2clientConnPool)
+ t2 := &http2Transport{ConnPool: http2noDialClientConnPool{connPool}}
+ if err := http2registerHTTPSProtocol(t1, http2noDialH2RoundTripper{t2}); err != nil {
+ return err
+ }
+ if t1.TLSClientConfig == nil {
+ t1.TLSClientConfig = new(tls.Config)
+ }
+ if !http2strSliceContains(t1.TLSClientConfig.NextProtos, "h2") {
+ t1.TLSClientConfig.NextProtos = append([]string{"h2"}, t1.TLSClientConfig.NextProtos...)
+ }
+ upgradeFn := func(authority string, c *tls.Conn) RoundTripper {
+ cc, err := t2.NewClientConn(c)
+ if err != nil {
+ c.Close()
+ return http2erringRoundTripper{err}
+ }
+ connPool.addConn(http2authorityAddr(authority), cc)
+ return t2
+ }
+ if m := t1.TLSNextProto; len(m) == 0 {
+ t1.TLSNextProto = map[string]func(string, *tls.Conn) RoundTripper{
+ "h2": upgradeFn,
+ }
+ } else {
+ m["h2"] = upgradeFn
+ }
+ return nil
+}
+
+// registerHTTPSProtocol calls Transport.RegisterProtocol but
+// convering panics into errors.
+func http2registerHTTPSProtocol(t *Transport, rt RoundTripper) (err error) {
+ defer func() {
+ if e := recover(); e != nil {
+ err = fmt.Errorf("%v", e)
+ }
+ }()
+ t.RegisterProtocol("https", rt)
+ return nil
+}
+
+// noDialClientConnPool is an implementation of http2.ClientConnPool
+// which never dials. We let the HTTP/1.1 client dial and use its TLS
+// connection instead.
+type http2noDialClientConnPool struct{ *http2clientConnPool }
+
+func (p http2noDialClientConnPool) GetClientConn(req *Request, addr string) (*http2ClientConn, error) {
+ const doDial = false
+ return p.getClientConn(req, addr, doDial)
}
-// Close marks the buffer as closed. Future calls to Write will
-// return an error. Future calls to Read, once the buffer is
-// empty, will return err.
-func (b *http2buffer) Close(err error) {
- if !b.closed {
- b.closed = true
- b.err = err
+// noDialH2RoundTripper is a RoundTripper which only tries to complete the request
+// if there's already has a cached connection to the host.
+type http2noDialH2RoundTripper struct{ t *http2Transport }
+
+func (rt http2noDialH2RoundTripper) RoundTrip(req *Request) (*Response, error) {
+ res, err := rt.t.RoundTrip(req)
+ if err == http2ErrNoCachedConn {
+ return nil, ErrSkipAltProtocol
}
+ return res, err
}
// An ErrCode is an unsigned 32-bit error code as defined in the HTTP/2 spec.
func (http2goAwayFlowError) Error() string { return "connection exceeded flow control window size" }
+// fixedBuffer is an io.ReadWriter backed by a fixed size buffer.
+// It never allocates, but moves old data as new data is written.
+type http2fixedBuffer struct {
+ buf []byte
+ r, w int
+}
+
+var (
+ http2errReadEmpty = errors.New("read from empty fixedBuffer")
+ http2errWriteFull = errors.New("write on full fixedBuffer")
+)
+
+// Read copies bytes from the buffer into p.
+// It is an error to read when no data is available.
+func (b *http2fixedBuffer) Read(p []byte) (n int, err error) {
+ if b.r == b.w {
+ return 0, http2errReadEmpty
+ }
+ n = copy(p, b.buf[b.r:b.w])
+ b.r += n
+ if b.r == b.w {
+ b.r = 0
+ b.w = 0
+ }
+ return n, nil
+}
+
+// Len returns the number of bytes of the unread portion of the buffer.
+func (b *http2fixedBuffer) Len() int {
+ return b.w - b.r
+}
+
+// Write copies bytes from p into the buffer.
+// It is an error to write more data than the buffer can hold.
+func (b *http2fixedBuffer) Write(p []byte) (n int, err error) {
+
+ if b.r > 0 && len(p) > len(b.buf)-b.w {
+ copy(b.buf, b.buf[b.r:b.w])
+ b.w -= b.r
+ b.r = 0
+ }
+
+ n = copy(b.buf[b.w:], p)
+ b.w += n
+ if n < len(p) {
+ err = http2errWriteFull
+ }
+ return n, err
+}
+
// flow is the flow control window's size.
type http2flow struct {
// n is the number of DATA bytes we're allowed to send.
Data [8]byte
}
+func (f *http2PingFrame) IsAck() bool { return f.Flags.Has(http2FlagPingAck) }
+
func http2parsePingFrame(fh http2FrameHeader, payload []byte) (http2Frame, error) {
if len(payload) != 8 {
return nil, http2ConnectionError(http2ErrCodeFrameSize)
// See http://http2.github.io/http2-spec/#rfc.section.6.9
type http2WindowUpdateFrame struct {
http2FrameHeader
- Increment uint32
+ Increment uint32 // never read with high bit set
}
func http2parseWindowUpdateFrame(fh http2FrameHeader, p []byte) (http2Frame, error) {
return err
}
+func http2mustUint31(v int32) uint32 {
+ if v < 0 || v > 2147483647 {
+ panic("out of range")
+ }
+ return uint32(v)
+}
+
+// pipe is a goroutine-safe io.Reader/io.Writer pair. It's like
+// io.Pipe except there are no PipeReader/PipeWriter halves, and the
+// underlying buffer is an interface. (io.Pipe is always unbuffered)
type http2pipe struct {
- b http2buffer
- c sync.Cond
- m sync.Mutex
+ mu sync.Mutex
+ c sync.Cond // c.L must point to
+ b http2pipeBuffer
+ err error // read error once empty. non-nil means closed.
+}
+
+type http2pipeBuffer interface {
+ Len() int
+ io.Writer
+ io.Reader
}
// Read waits until data is available and copies bytes
// from the buffer into p.
-func (r *http2pipe) Read(p []byte) (n int, err error) {
- r.c.L.Lock()
- defer r.c.L.Unlock()
- for r.b.Len() == 0 && !r.b.closed {
- r.c.Wait()
+func (p *http2pipe) Read(d []byte) (n int, err error) {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ if p.c.L == nil {
+ p.c.L = &p.mu
+ }
+ for {
+ if p.b.Len() > 0 {
+ return p.b.Read(d)
+ }
+ if p.err != nil {
+ return 0, p.err
+ }
+ p.c.Wait()
}
- return r.b.Read(p)
}
+var http2errClosedPipeWrite = errors.New("write on closed buffer")
+
// Write copies bytes from p into the buffer and wakes a reader.
// It is an error to write more data than the buffer can hold.
-func (w *http2pipe) Write(p []byte) (n int, err error) {
- w.c.L.Lock()
- defer w.c.L.Unlock()
- defer w.c.Signal()
- return w.b.Write(p)
+func (p *http2pipe) Write(d []byte) (n int, err error) {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ if p.c.L == nil {
+ p.c.L = &p.mu
+ }
+ defer p.c.Signal()
+ if p.err != nil {
+ return 0, http2errClosedPipeWrite
+ }
+ return p.b.Write(d)
}
-func (c *http2pipe) Close(err error) {
- c.c.L.Lock()
- defer c.c.L.Unlock()
- defer c.c.Signal()
- c.b.Close(err)
+// CloseWithError causes Reads to wake up and return the
+// provided err after all data has been read.
+//
+// The error must be non-nil.
+func (p *http2pipe) CloseWithError(err error) {
+ if err == nil {
+ panic("CloseWithError must be non-nil")
+ }
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ if p.c.L == nil {
+ p.c.L = &p.mu
+ }
+ defer p.c.Signal()
+ if p.err == nil {
+ p.err = err
+ }
+}
+
+// Err returns the error (if any) first set with CloseWithError.
+// This is the error which will be returned after the reader is exhausted.
+func (p *http2pipe) Err() error {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ return p.err
}
const (
var (
http2errClientDisconnected = errors.New("client disconnected")
http2errClosedBody = errors.New("body closed by handler")
- http2errStreamBroken = errors.New("http2: stream broken")
+ http2errHandlerComplete = errors.New("http2: request body closed due to handler exiting")
+ http2errStreamClosed = errors.New("http2: stream closed")
)
var http2responseWriterStatePool = sync.Pool{
// The configuration conf may be nil.
//
// ConfigureServer must be called before s begins serving.
-func http2ConfigureServer(s *Server, conf *http2Server) {
+func http2ConfigureServer(s *Server, conf *http2Server) error {
if conf == nil {
conf = new(http2Server)
}
+
if s.TLSConfig == nil {
s.TLSConfig = new(tls.Config)
- }
-
- if s.TLSConfig.CipherSuites != nil {
+ } else if s.TLSConfig.CipherSuites != nil {
+ // If they already provided a CipherSuite list, return
+ // an error if it has a bad order or is missing
+ // ECDHE_RSA_WITH_AES_128_GCM_SHA256.
const requiredCipher = tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
haveRequired := false
- for _, v := range s.TLSConfig.CipherSuites {
- if v == requiredCipher {
+ sawBad := false
+ for i, cs := range s.TLSConfig.CipherSuites {
+ if cs == requiredCipher {
haveRequired = true
- break
+ }
+ if http2isBadCipher(cs) {
+ sawBad = true
+ } else if sawBad {
+ return fmt.Errorf("http2: TLSConfig.CipherSuites index %d contains an HTTP/2-approved cipher suite (%#04x), but it comes after unapproved cipher suites. With this configuration, clients that don't support previous, approved cipher suites may be given an unapproved one and reject the connection.", i, cs)
}
}
if !haveRequired {
- s.TLSConfig.CipherSuites = append(s.TLSConfig.CipherSuites, requiredCipher)
+ return fmt.Errorf("http2: TLSConfig.CipherSuites is missing HTTP/2-required TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")
}
}
+ s.TLSConfig.PreferServerCipherSuites = true
+
haveNPN := false
for _, p := range s.TLSConfig.NextProtos {
if p == http2NextProtoTLS {
}
s.TLSNextProto[http2NextProtoTLS] = protoHandler
s.TLSNextProto["h2-14"] = protoHandler
+ return nil
}
func (srv *http2Server) handleConn(hs *Server, c net.Conn, h Handler) {
streams: make(map[uint32]*http2stream),
readFrameCh: make(chan http2readFrameResult),
wantWriteFrameCh: make(chan http2frameWriteMsg, 8),
- wroteFrameCh: make(chan struct{}, 1),
+ wroteFrameCh: make(chan http2frameWriteResult, 1),
bodyReadCh: make(chan http2bodyReadMsg),
doneServing: make(chan struct{}),
advMaxStreams: srv.maxConcurrentStreams(),
handler Handler
framer *http2Framer
hpackDecoder *hpack.Decoder
- doneServing chan struct{} // closed when serverConn.serve ends
- readFrameCh chan http2readFrameResult // written by serverConn.readFrames
- wantWriteFrameCh chan http2frameWriteMsg // from handlers -> serve
- wroteFrameCh chan struct{} // from writeFrameAsync -> serve, tickles more frame writes
- bodyReadCh chan http2bodyReadMsg // from handlers -> serve
- testHookCh chan func(int) // code to run on the serve loop
- flow http2flow // conn-wide (not stream-specific) outbound flow control
- inflow http2flow // conn-wide inbound flow control
- tlsState *tls.ConnectionState // shared by all handlers, like net/http
+ doneServing chan struct{} // closed when serverConn.serve ends
+ readFrameCh chan http2readFrameResult // written by serverConn.readFrames
+ wantWriteFrameCh chan http2frameWriteMsg // from handlers -> serve
+ wroteFrameCh chan http2frameWriteResult // from writeFrameAsync -> serve, tickles more frame writes
+ bodyReadCh chan http2bodyReadMsg // from handlers -> serve
+ testHookCh chan func(int) // code to run on the serve loop
+ flow http2flow // conn-wide (not stream-specific) outbound flow control
+ inflow http2flow // conn-wide inbound flow control
+ tlsState *tls.ConnectionState // shared by all handlers, like net/http
remoteAddrStr string
// Everything following is owned by the serve loop; use serveG.check():
return http2stateIdle, nil
}
+// setConnState calls the net/http ConnState hook for this connection, if configured.
+// Note that the net/http package does StateNew and StateClosed for us.
+// There is currently no plan for StateHijacked or hijacking HTTP/2 connections.
+func (sc *http2serverConn) setConnState(state ConnState) {
+ if sc.hs.ConnState != nil {
+ sc.hs.ConnState(sc.conn, state)
+ }
+}
+
func (sc *http2serverConn) vlogf(format string, args ...interface{}) {
if http2VerboseLogs {
sc.logf(format, args...)
}
}
+// frameWriteResult is the message passed from writeFrameAsync to the serve goroutine.
+type http2frameWriteResult struct {
+ wm http2frameWriteMsg // what was written (or attempted)
+ err error // result of the writeFrame call
+}
+
// writeFrameAsync runs in its own goroutine and writes a single frame
// and then reports when it's done.
// At most one goroutine can be running writeFrameAsync at a time per
// serverConn.
func (sc *http2serverConn) writeFrameAsync(wm http2frameWriteMsg) {
err := wm.write.writeFrame(sc)
- if ch := wm.done; ch != nil {
- select {
- case ch <- err:
- default:
- panic(fmt.Sprintf("unbuffered done channel passed in for type %T", wm.write))
- }
- }
- sc.wroteFrameCh <- struct{}{}
+ sc.wroteFrameCh <- http2frameWriteResult{wm, err}
}
func (sc *http2serverConn) closeAllStreamsOnConnClose() {
return
}
+ sc.setConnState(StateActive)
+ sc.setConnState(StateIdle)
+
go sc.readFrames()
settingsTimer := time.NewTimer(http2firstSettingsTimeout)
select {
case wm := <-sc.wantWriteFrameCh:
sc.writeFrame(wm)
- case <-sc.wroteFrameCh:
- if sc.writingFrame != true {
- panic("internal error: expected to be already writing a frame")
- }
- sc.writingFrame = false
- sc.scheduleFrameWrite()
+ case res := <-sc.wroteFrameCh:
+ sc.wroteFrame(res)
case res := <-sc.readFrameCh:
if !sc.processFrameFromReader(res) {
return
New: func() interface{} { return make(chan error, 1) },
}
-// writeDataFromHandler writes the data described in req to stream.id.
-//
-// The flow control currently happens in the Handler where it waits
-// for 1 or more bytes to be available to then write here. So at this
-// point we know that we have flow control. But this might have to
-// change when priority is implemented, so the serve goroutine knows
-// the total amount of bytes waiting to be sent and can can have more
-// scheduling decisions available.
-func (sc *http2serverConn) writeDataFromHandler(stream *http2stream, writeData *http2writeData) error {
+var http2writeDataPool = sync.Pool{
+ New: func() interface{} { return new(http2writeData) },
+}
+
+// writeDataFromHandler writes DATA response frames from a handler on
+// the given stream.
+func (sc *http2serverConn) writeDataFromHandler(stream *http2stream, data []byte, endStream bool) error {
ch := http2errChanPool.Get().(chan error)
- sc.writeFrameFromHandler(http2frameWriteMsg{
- write: writeData,
+ writeArg := http2writeDataPool.Get().(*http2writeData)
+ *writeArg = http2writeData{stream.id, data, endStream}
+ err := sc.writeFrameFromHandler(http2frameWriteMsg{
+ write: writeArg,
stream: stream,
done: ch,
})
- select {
- case err := <-ch:
- http2errChanPool.Put(ch)
+ if err != nil {
return err
+ }
+ var frameWriteDone bool // the frame write is done (successfully or not)
+ select {
+ case err = <-ch:
+ frameWriteDone = true
case <-sc.doneServing:
return http2errClientDisconnected
case <-stream.cw:
- return http2errStreamBroken
+
+ select {
+ case err = <-ch:
+ frameWriteDone = true
+ default:
+ return http2errStreamClosed
+ }
}
+ http2errChanPool.Put(ch)
+ if frameWriteDone {
+ http2writeDataPool.Put(writeArg)
+ }
+ return err
}
// writeFrameFromHandler sends wm to sc.wantWriteFrameCh, but aborts
// deadlock writing to sc.wantWriteFrameCh (which is only mildly
// buffered and is read by serve itself). If you're on the serve
// goroutine, call writeFrame instead.
-func (sc *http2serverConn) writeFrameFromHandler(wm http2frameWriteMsg) {
+func (sc *http2serverConn) writeFrameFromHandler(wm http2frameWriteMsg) error {
sc.serveG.checkNotOn()
- var scheduled bool
select {
case sc.wantWriteFrameCh <- wm:
- scheduled = true
+ return nil
case <-sc.doneServing:
- case <-wm.stream.cw:
-
- }
-
- if !scheduled && wm.done != nil {
- select {
- case wm.done <- http2errStreamBroken:
- default:
- panic("expected buffered channel")
- }
+ return http2errClientDisconnected
}
}
if sc.writingFrame {
panic("internal error: can only be writing one frame at a time")
}
- sc.writingFrame = true
st := wm.stream
if st != nil {
case http2stateClosed:
if st.sentReset || st.gotReset {
- sc.wroteFrameCh <- struct{}{}
+ sc.scheduleFrameWrite()
return
}
panic(fmt.Sprintf("internal error: attempt to send a write %v on a closed stream", wm))
}
}
+ sc.writingFrame = true
sc.needsFrameFlush = true
- if http2endsStream(wm.write) {
+ go sc.writeFrameAsync(wm)
+}
+
+// wroteFrame is called on the serve goroutine with the result of
+// whatever happened on writeFrameAsync.
+func (sc *http2serverConn) wroteFrame(res http2frameWriteResult) {
+ sc.serveG.check()
+ if !sc.writingFrame {
+ panic("internal error: expected to be already writing a frame")
+ }
+ sc.writingFrame = false
+
+ wm := res.wm
+ st := wm.stream
+
+ closeStream := http2endsStream(wm.write)
+
+ if ch := wm.done; ch != nil {
+ select {
+ case ch <- res.err:
+ default:
+ panic(fmt.Sprintf("unbuffered done channel passed in for type %T", wm.write))
+ }
+ }
+ wm.write = nil
+
+ if closeStream {
if st == nil {
panic("internal error: expecting non-nil stream")
}
errCancel := http2StreamError{st.id, http2ErrCodeCancel}
sc.resetStream(errCancel)
case http2stateHalfClosedRemote:
- sc.closeStream(st, nil)
+ sc.closeStream(st, http2errHandlerComplete)
}
}
- go sc.writeFrameAsync(wm)
+
+ sc.scheduleFrameWrite()
}
// scheduleFrameWrite tickles the frame writing scheduler.
func (sc *http2serverConn) processPing(f *http2PingFrame) error {
sc.serveG.check()
- if f.Flags.Has(http2FlagSettingsAck) {
+ if f.IsAck() {
return nil
}
}
st.state = http2stateClosed
sc.curOpenStreams--
+ if sc.curOpenStreams == 0 {
+ sc.setConnState(StateIdle)
+ }
delete(sc.streams, st.id)
if p := st.body; p != nil {
- p.Close(err)
+ p.CloseWithError(err)
}
st.cw.Close()
sc.writeSched.forgetStream(st.id)
data := f.Data()
if st.declBodyBytes != -1 && st.bodyBytes+int64(len(data)) > st.declBodyBytes {
- st.body.Close(fmt.Errorf("sender tried to send more than declared Content-Length of %d bytes", st.declBodyBytes))
+ st.body.CloseWithError(fmt.Errorf("sender tried to send more than declared Content-Length of %d bytes", st.declBodyBytes))
return http2StreamError{id, http2ErrCodeStreamClosed}
}
if len(data) > 0 {
}
if f.StreamEnded() {
if st.declBodyBytes != -1 && st.declBodyBytes != st.bodyBytes {
- st.body.Close(fmt.Errorf("request declared a Content-Length of %d but only wrote %d bytes",
+ st.body.CloseWithError(fmt.Errorf("request declared a Content-Length of %d but only wrote %d bytes",
st.declBodyBytes, st.bodyBytes))
} else {
- st.body.Close(io.EOF)
+ st.body.CloseWithError(io.EOF)
}
st.state = http2stateHalfClosedRemote
}
http2adjustStreamPriority(sc.streams, st.id, f.Priority)
}
sc.curOpenStreams++
+ if sc.curOpenStreams == 1 {
+ sc.setConnState(StateActive)
+ }
sc.req = http2requestParam{
stream: st,
header: make(Header),
}
if bodyOpen {
body.pipe = &http2pipe{
- b: http2buffer{buf: make([]byte, http2initialWindowSize)},
+ b: &http2fixedBuffer{buf: make([]byte, http2initialWindowSize)},
}
- body.pipe.c.L = &body.pipe.m
if vv, ok := rp.header["Content-Length"]; ok {
req.ContentLength, _ = strconv.ParseInt(vv[0], 10, 64)
// called from handler goroutines.
// h may be nil.
-func (sc *http2serverConn) writeHeaders(st *http2stream, headerData *http2writeResHeaders) {
+func (sc *http2serverConn) writeHeaders(st *http2stream, headerData *http2writeResHeaders) error {
sc.serveG.checkNotOn()
var errc chan error
if headerData.h != nil {
errc = http2errChanPool.Get().(chan error)
}
- sc.writeFrameFromHandler(http2frameWriteMsg{
+ if err := sc.writeFrameFromHandler(http2frameWriteMsg{
write: headerData,
stream: st,
done: errc,
- })
+ }); err != nil {
+ return err
+ }
if errc != nil {
select {
- case <-errc:
-
+ case err := <-errc:
http2errChanPool.Put(errc)
+ return err
case <-sc.doneServing:
-
+ return http2errClientDisconnected
case <-st.cw:
-
+ return http2errStreamClosed
}
}
+ return nil
}
// called from handler goroutines.
// and schedules flow control tokens to be sent.
func (sc *http2serverConn) noteBodyReadFromHandler(st *http2stream, n int) {
sc.serveG.checkNotOn()
- sc.bodyReadCh <- http2bodyReadMsg{st, n}
+ select {
+ case sc.bodyReadCh <- http2bodyReadMsg{st, n}:
+ case <-sc.doneServing:
+ }
}
func (sc *http2serverConn) noteBodyRead(st *http2stream, n int) {
func (b *http2requestBody) Close() error {
if b.pipe != nil {
- b.pipe.Close(http2errClosedBody)
+ b.pipe.CloseWithError(http2errClosedBody)
}
b.closed = true
return nil
wroteHeader bool // WriteHeader called (explicitly or implicitly). Not necessarily sent to user yet.
sentHeader bool // have we sent the header frame?
handlerDone bool // handler has finished
- curWrite http2writeData
closeNotifierMu sync.Mutex // guards closeNotifierCh
closeNotifierCh chan bool // nil until first used
ctype = DetectContentType(p)
}
endStream := rws.handlerDone && len(p) == 0
- rws.conn.writeHeaders(rws.stream, &http2writeResHeaders{
+ err = rws.conn.writeHeaders(rws.stream, &http2writeResHeaders{
streamID: rws.stream.id,
httpResCode: rws.status,
h: rws.snapHeader,
contentType: ctype,
contentLength: clen,
})
+ if err != nil {
+ return 0, err
+ }
if endStream {
return 0, nil
}
if len(p) == 0 && !rws.handlerDone {
return 0, nil
}
- curWrite := &rws.curWrite
- curWrite.streamID = rws.stream.id
- curWrite.p = p
- curWrite.endStream = rws.handlerDone
- if err := rws.conn.writeDataFromHandler(rws.stream, curWrite); err != nil {
+
+ if err := rws.conn.writeDataFromHandler(rws.stream, p, rws.handlerDone); err != nil {
return 0, err
}
return len(p), nil
http2responseWriterStatePool.Put(rws)
}
+const (
+ // transportDefaultConnFlow is how many connection-level flow control
+ // tokens we give the server at start-up, past the default 64k.
+ http2transportDefaultConnFlow = 1 << 30
+
+ // transportDefaultStreamFlow is how many stream-level flow
+ // control tokens we announce to the peer, and how many bytes
+ // we buffer per stream.
+ http2transportDefaultStreamFlow = 4 << 20
+
+ // transportDefaultStreamMinRefresh is the minimum number of bytes we'll send
+ // a stream-level WINDOW_UPDATE for at a time.
+ http2transportDefaultStreamMinRefresh = 4 << 10
+)
+
+// Transport is an HTTP/2 Transport.
+//
+// A Transport internally caches connections to servers. It is safe
+// for concurrent use by multiple goroutines.
type http2Transport struct {
- Fallback RoundTripper
+ // DialTLS specifies an optional dial function for creating
+ // TLS connections for requests.
+ //
+ // If DialTLS is nil, tls.Dial is used.
+ //
+ // If the returned net.Conn has a ConnectionState method like tls.Conn,
+ // it will be used to set http.Response.TLS.
+ DialTLS func(network, addr string, cfg *tls.Config) (net.Conn, error)
+
+ // TLSClientConfig specifies the TLS configuration to use with
+ // tls.Client. If nil, the default configuration is used.
+ TLSClientConfig *tls.Config
+
+ // ConnPool optionally specifies an alternate connection pool to use.
+ // If nil, the default is used.
+ ConnPool http2ClientConnPool
+
+ connPoolOnce sync.Once
+ connPoolOrDef http2ClientConnPool // non-nil version of ConnPool
+}
+
+var http2errTransportVersion = errors.New("http2: ConfigureTransport is only supported starting at Go 1.6")
- // TODO: remove this and make more general with a TLS dial hook, like http
- InsecureTLSDial bool
+// ConfigureTransport configures a net/http HTTP/1 Transport to use HTTP/2.
+// It requires Go 1.6 or later and returns an error if the net/http package is too old
+// or if t1 has already been HTTP/2-enabled.
+func http2ConfigureTransport(t1 *Transport) error {
+ return http2configureTransport(t1)
+}
+
+func (t *http2Transport) connPool() http2ClientConnPool {
+ t.connPoolOnce.Do(t.initConnPool)
+ return t.connPoolOrDef
+}
- connMu sync.Mutex
- conns map[string][]*http2clientConn // key is host:port
+func (t *http2Transport) initConnPool() {
+ if t.ConnPool != nil {
+ t.connPoolOrDef = t.ConnPool
+ } else {
+ t.connPoolOrDef = &http2clientConnPool{t: t}
+ }
}
-type http2clientConn struct {
+// ClientConn is the state of a single HTTP/2 client connection to an
+// HTTP/2 server.
+type http2ClientConn struct {
t *http2Transport
- tconn *tls.Conn
- tlsState *tls.ConnectionState
- connKey []string // key(s) this connection is cached in, in t.conns
+ tconn net.Conn // usually *tls.Conn, except specialized impls
+ tlsState *tls.ConnectionState // nil only for specialized impls
+ // readLoop goroutine fields:
readerDone chan struct{} // closed on error
readerErr error // set before readerDone is closed
- hdec *hpack.Decoder
- nextRes *Response
- mu sync.Mutex
+ mu sync.Mutex // guards following
+ cond *sync.Cond // hold mu; broadcast on flow/closed changes
+ flow http2flow // our conn-level flow control quota (cs.flow is per stream)
+ inflow http2flow // peer's conn-level flow control
closed bool
- goAway *http2GoAwayFrame // if non-nil, the GoAwayFrame we received
- streams map[uint32]*http2clientStream
+ goAway *http2GoAwayFrame // if non-nil, the GoAwayFrame we received
+ streams map[uint32]*http2clientStream // client-initiated
nextStreamID uint32
bw *bufio.Writer
- werr error // first write error that has occurred
br *bufio.Reader
fr *http2Framer
// Settings from peer:
initialWindowSize uint32
hbuf bytes.Buffer // HPACK encoder writes into this
henc *hpack.Encoder
+ freeBuf [][]byte
+
+ wmu sync.Mutex // held while writing; acquire AFTER wmu if holding both
+ werr error // first write error that has occurred
}
+// clientStream is the state for a single HTTP/2 stream. One of these
+// is created for each Transport.RoundTrip call.
type http2clientStream struct {
- ID uint32
- resc chan http2resAndError
- pw *io.PipeWriter
- pr *io.PipeReader
+ cc *http2ClientConn
+ ID uint32
+ resc chan http2resAndError
+ bufPipe http2pipe // buffered pipe with the flow-controlled response payload
+
+ flow http2flow // guarded by cc.mu
+ inflow http2flow // guarded by cc.mu
+
+ peerReset chan struct{} // closed on peer reset
+ resetErr error // populated before peerReset is closed
+}
+
+// checkReset reports any error sent in a RST_STREAM frame by the
+// server.
+func (cs *http2clientStream) checkReset() error {
+ select {
+ case <-cs.peerReset:
+ return cs.resetErr
+ default:
+ return nil
+ }
}
type http2stickyErrWriter struct {
return
}
+var http2ErrNoCachedConn = errors.New("http2: no cached connection was available")
+
+// RoundTripOpt are options for the Transport.RoundTripOpt method.
+type http2RoundTripOpt struct {
+ // OnlyCachedConn controls whether RoundTripOpt may
+ // create a new TCP connection. If set true and
+ // no cached connection is available, RoundTripOpt
+ // will return ErrNoCachedConn.
+ OnlyCachedConn bool
+}
+
func (t *http2Transport) RoundTrip(req *Request) (*Response, error) {
- if req.URL.Scheme != "https" {
- if t.Fallback == nil {
- return nil, errors.New("http2: unsupported scheme and no Fallback")
- }
- return t.Fallback.RoundTrip(req)
- }
+ return t.RoundTripOpt(req, http2RoundTripOpt{})
+}
- host, port, err := net.SplitHostPort(req.URL.Host)
- if err != nil {
- host = req.URL.Host
- port = "443"
+// authorityAddr returns a given authority (a host/IP, or host:port / ip:port)
+// and returns a host:port. The port 443 is added if needed.
+func http2authorityAddr(authority string) (addr string) {
+ if _, _, err := net.SplitHostPort(authority); err == nil {
+ return authority
}
+ return net.JoinHostPort(authority, "443")
+}
+// RoundTripOpt is like RoundTrip, but takes options.
+func (t *http2Transport) RoundTripOpt(req *Request, opt http2RoundTripOpt) (*Response, error) {
+ if req.URL.Scheme != "https" {
+ return nil, errors.New("http2: unsupported scheme")
+ }
+
+ addr := http2authorityAddr(req.URL.Host)
for {
- cc, err := t.getClientConn(host, port)
+ cc, err := t.connPool().GetClientConn(req, addr)
if err != nil {
return nil, err
}
- res, err := cc.roundTrip(req)
+ res, err := cc.RoundTrip(req)
if http2shouldRetryRequest(err) {
continue
}
// connected from previous requests but are now sitting idle.
// It does not interrupt any connections currently in use.
func (t *http2Transport) CloseIdleConnections() {
- t.connMu.Lock()
- defer t.connMu.Unlock()
- for _, vv := range t.conns {
- for _, cc := range vv {
- cc.closeIfIdle()
- }
+ if cp, ok := t.connPool().(*http2clientConnPool); ok {
+ cp.closeIdleConnections()
}
}
return err == http2errClientConnClosed
}
-func (t *http2Transport) removeClientConn(cc *http2clientConn) {
- t.connMu.Lock()
- defer t.connMu.Unlock()
- for _, key := range cc.connKey {
- vv, ok := t.conns[key]
- if !ok {
- continue
- }
- newList := http2filterOutClientConn(vv, cc)
- if len(newList) > 0 {
- t.conns[key] = newList
- } else {
- delete(t.conns, key)
- }
+func (t *http2Transport) dialClientConn(addr string) (*http2ClientConn, error) {
+ host, _, err := net.SplitHostPort(addr)
+ if err != nil {
+ return nil, err
}
+ tconn, err := t.dialTLS()("tcp", addr, t.newTLSConfig(host))
+ if err != nil {
+ return nil, err
+ }
+ return t.NewClientConn(tconn)
}
-func http2filterOutClientConn(in []*http2clientConn, exclude *http2clientConn) []*http2clientConn {
- out := in[:0]
- for _, v := range in {
- if v != exclude {
- out = append(out, v)
- }
+func (t *http2Transport) newTLSConfig(host string) *tls.Config {
+ cfg := new(tls.Config)
+ if t.TLSClientConfig != nil {
+ *cfg = *t.TLSClientConfig
}
- return out
+ cfg.NextProtos = []string{http2NextProtoTLS}
+ cfg.ServerName = host
+ return cfg
}
-func (t *http2Transport) getClientConn(host, port string) (*http2clientConn, error) {
- t.connMu.Lock()
- defer t.connMu.Unlock()
-
- key := net.JoinHostPort(host, port)
-
- for _, cc := range t.conns[key] {
- if cc.canTakeNewRequest() {
- return cc, nil
- }
+func (t *http2Transport) dialTLS() func(string, string, *tls.Config) (net.Conn, error) {
+ if t.DialTLS != nil {
+ return t.DialTLS
}
- if t.conns == nil {
- t.conns = make(map[string][]*http2clientConn)
- }
- cc, err := t.newClientConn(host, port, key)
- if err != nil {
- return nil, err
- }
- t.conns[key] = append(t.conns[key], cc)
- return cc, nil
+ return t.dialTLSDefault
}
-func (t *http2Transport) newClientConn(host, port, key string) (*http2clientConn, error) {
- cfg := &tls.Config{
- ServerName: host,
- NextProtos: []string{http2NextProtoTLS},
- InsecureSkipVerify: t.InsecureTLSDial,
- }
- tconn, err := tls.Dial("tcp", net.JoinHostPort(host, port), cfg)
+func (t *http2Transport) dialTLSDefault(network, addr string, cfg *tls.Config) (net.Conn, error) {
+ cn, err := tls.Dial(network, addr, cfg)
if err != nil {
return nil, err
}
- if err := tconn.Handshake(); err != nil {
+ if err := cn.Handshake(); err != nil {
return nil, err
}
- if !t.InsecureTLSDial {
- if err := tconn.VerifyHostname(cfg.ServerName); err != nil {
+ if !cfg.InsecureSkipVerify {
+ if err := cn.VerifyHostname(cfg.ServerName); err != nil {
return nil, err
}
}
- state := tconn.ConnectionState()
+ state := cn.ConnectionState()
if p := state.NegotiatedProtocol; p != http2NextProtoTLS {
-
- return nil, fmt.Errorf("bad protocol: %v", p)
+ return nil, fmt.Errorf("http2: unexpected ALPN protocol %q; want %q", p, http2NextProtoTLS)
}
if !state.NegotiatedProtocolIsMutual {
- return nil, errors.New("could not negotiate protocol mutually")
+ return nil, errors.New("http2: could not negotiate protocol mutually")
}
- if _, err := tconn.Write(http2clientPreface); err != nil {
+ return cn, nil
+}
+
+func (t *http2Transport) NewClientConn(c net.Conn) (*http2ClientConn, error) {
+ if _, err := c.Write(http2clientPreface); err != nil {
return nil, err
}
- cc := &http2clientConn{
+ cc := &http2ClientConn{
t: t,
- tconn: tconn,
- connKey: []string{key},
- tlsState: &state,
+ tconn: c,
readerDone: make(chan struct{}),
nextStreamID: 1,
maxFrameSize: 16 << 10,
maxConcurrentStreams: 1000,
streams: make(map[uint32]*http2clientStream),
}
- cc.bw = bufio.NewWriter(http2stickyErrWriter{tconn, &cc.werr})
- cc.br = bufio.NewReader(tconn)
+ cc.cond = sync.NewCond(&cc.mu)
+ cc.flow.add(int32(http2initialWindowSize))
+
+ cc.bw = bufio.NewWriter(http2stickyErrWriter{c, &cc.werr})
+ cc.br = bufio.NewReader(c)
cc.fr = http2NewFramer(cc.bw, cc.br)
cc.henc = hpack.NewEncoder(&cc.hbuf)
- cc.fr.WriteSettings()
+ type connectionStater interface {
+ ConnectionState() tls.ConnectionState
+ }
+ if cs, ok := c.(connectionStater); ok {
+ state := cs.ConnectionState()
+ cc.tlsState = &state
+ }
- cc.fr.WriteWindowUpdate(0, 1<<30)
+ cc.fr.WriteSettings(
+ http2Setting{ID: http2SettingEnablePush, Val: 0},
+ http2Setting{ID: http2SettingInitialWindowSize, Val: http2transportDefaultStreamFlow},
+ )
+ cc.fr.WriteWindowUpdate(0, http2transportDefaultConnFlow)
+ cc.inflow.add(http2transportDefaultConnFlow + http2initialWindowSize)
cc.bw.Flush()
if cc.werr != nil {
return nil, cc.werr
cc.initialWindowSize = s.Val
default:
- log.Printf("Unhandled Setting: %v", s)
+ t.vlogf("Unhandled Setting: %v", s)
}
return nil
})
- cc.hdec = hpack.NewDecoder(http2initialHeaderTableSize, cc.onNewHeaderField)
-
go cc.readLoop()
return cc, nil
}
-func (cc *http2clientConn) setGoAway(f *http2GoAwayFrame) {
+func (cc *http2ClientConn) setGoAway(f *http2GoAwayFrame) {
cc.mu.Lock()
defer cc.mu.Unlock()
cc.goAway = f
}
-func (cc *http2clientConn) canTakeNewRequest() bool {
+func (cc *http2ClientConn) CanTakeNewRequest() bool {
cc.mu.Lock()
defer cc.mu.Unlock()
return cc.goAway == nil &&
cc.nextStreamID < 2147483647
}
-func (cc *http2clientConn) closeIfIdle() {
+func (cc *http2ClientConn) closeIfIdle() {
cc.mu.Lock()
if len(cc.streams) > 0 {
cc.mu.Unlock()
cc.tconn.Close()
}
-func (cc *http2clientConn) roundTrip(req *Request) (*Response, error) {
+const http2maxAllocFrameSize = 512 << 10
+
+// frameBuffer returns a scratch buffer suitable for writing DATA frames.
+// They're capped at the min of the peer's max frame size or 512KB
+// (kinda arbitrarily), but definitely capped so we don't allocate 4GB
+// bufers.
+func (cc *http2ClientConn) frameScratchBuffer() []byte {
+ cc.mu.Lock()
+ size := cc.maxFrameSize
+ if size > http2maxAllocFrameSize {
+ size = http2maxAllocFrameSize
+ }
+ for i, buf := range cc.freeBuf {
+ if len(buf) >= int(size) {
+ cc.freeBuf[i] = nil
+ cc.mu.Unlock()
+ return buf[:size]
+ }
+ }
+ cc.mu.Unlock()
+ return make([]byte, size)
+}
+
+func (cc *http2ClientConn) putFrameScratchBuffer(buf []byte) {
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
+ const maxBufs = 4 // arbitrary; 4 concurrent requests per conn? investigate.
+ if len(cc.freeBuf) < maxBufs {
+ cc.freeBuf = append(cc.freeBuf, buf)
+ return
+ }
+ for i, old := range cc.freeBuf {
+ if old == nil {
+ cc.freeBuf[i] = buf
+ return
+ }
+ }
+
+}
+
+func (cc *http2ClientConn) RoundTrip(req *Request) (*Response, error) {
cc.mu.Lock()
if cc.closed {
}
cs := cc.newStream()
- hasBody := false
+ hasBody := req.Body != nil
hdrs := cc.encodeHeaders(req)
first := true
- for len(hdrs) > 0 {
+
+ cc.wmu.Lock()
+ frameSize := int(cc.maxFrameSize)
+ for len(hdrs) > 0 && cc.werr == nil {
chunk := hdrs
- if len(chunk) > int(cc.maxFrameSize) {
- chunk = chunk[:cc.maxFrameSize]
+ if len(chunk) > frameSize {
+ chunk = chunk[:frameSize]
}
hdrs = hdrs[len(chunk):]
endHeaders := len(hdrs) == 0
}
cc.bw.Flush()
werr := cc.werr
+ cc.wmu.Unlock()
cc.mu.Unlock()
+ if werr != nil {
+ return nil, werr
+ }
+
+ var bodyCopyErrc chan error
+ var gotResHeaders chan struct{} // closed on resheaders
if hasBody {
+ bodyCopyErrc = make(chan error, 1)
+ gotResHeaders = make(chan struct{})
+ go func() {
+ bodyCopyErrc <- cs.writeRequestBody(req.Body, gotResHeaders)
+ }()
+ }
+ for {
+ select {
+ case re := <-cs.resc:
+ if gotResHeaders != nil {
+ close(gotResHeaders)
+ }
+ if re.err != nil {
+ return nil, re.err
+ }
+ res := re.res
+ res.Request = req
+ res.TLS = cc.tlsState
+ return res, nil
+ case err := <-bodyCopyErrc:
+ if err != nil {
+ return nil, err
+ }
+ }
}
+}
- if werr != nil {
- return nil, werr
+var http2errServerResponseBeforeRequestBody = errors.New("http2: server sent response while still writing request body")
+
+func (cs *http2clientStream) writeRequestBody(body io.Reader, gotResHeaders <-chan struct{}) error {
+ cc := cs.cc
+ sentEnd := false
+ buf := cc.frameScratchBuffer()
+ defer cc.putFrameScratchBuffer(buf)
+
+ for !sentEnd {
+ var sawEOF bool
+ n, err := io.ReadFull(body, buf)
+ if err == io.ErrUnexpectedEOF {
+ sawEOF = true
+ err = nil
+ } else if err == io.EOF {
+ break
+ } else if err != nil {
+ return err
+ }
+
+ toWrite := buf[:n]
+ for len(toWrite) > 0 && err == nil {
+ var allowed int32
+ allowed, err = cs.awaitFlowControl(int32(len(toWrite)))
+ if err != nil {
+ return err
+ }
+
+ cc.wmu.Lock()
+ select {
+ case <-gotResHeaders:
+ err = http2errServerResponseBeforeRequestBody
+ case <-cs.peerReset:
+ err = cs.resetErr
+ default:
+ data := toWrite[:allowed]
+ toWrite = toWrite[allowed:]
+ sentEnd = sawEOF && len(toWrite) == 0
+ err = cc.fr.WriteData(cs.ID, sentEnd, data)
+ }
+ cc.wmu.Unlock()
+ }
+ if err != nil {
+ return err
+ }
}
- re := <-cs.resc
- if re.err != nil {
- return nil, re.err
+ var err error
+
+ cc.wmu.Lock()
+ if !sentEnd {
+ err = cc.fr.WriteData(cs.ID, true, nil)
+ }
+ if ferr := cc.bw.Flush(); ferr != nil && err == nil {
+ err = ferr
+ }
+ cc.wmu.Unlock()
+
+ return err
+}
+
+// awaitFlowControl waits for [1, min(maxBytes, cc.cs.maxFrameSize)] flow
+// control tokens from the server.
+// It returns either the non-zero number of tokens taken or an error
+// if the stream is dead.
+func (cs *http2clientStream) awaitFlowControl(maxBytes int32) (taken int32, err error) {
+ cc := cs.cc
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
+ for {
+ if cc.closed {
+ return 0, http2errClientConnClosed
+ }
+ if err := cs.checkReset(); err != nil {
+ return 0, err
+ }
+ if a := cs.flow.available(); a > 0 {
+ take := a
+ if take > maxBytes {
+ take = maxBytes
+ }
+ if take > int32(cc.maxFrameSize) {
+ take = int32(cc.maxFrameSize)
+ }
+ cs.flow.take(take)
+ return take, nil
+ }
+ cc.cond.Wait()
}
- res := re.res
- res.Request = req
- res.TLS = cc.tlsState
- return res, nil
}
// requires cc.mu be held.
-func (cc *http2clientConn) encodeHeaders(req *Request) []byte {
+func (cc *http2ClientConn) encodeHeaders(req *Request) []byte {
cc.hbuf.Reset()
host := req.Host
host = req.URL.Host
}
- path := req.URL.Path
- if path == "" {
- path = "/"
- }
-
cc.writeHeader(":authority", host)
cc.writeHeader(":method", req.Method)
- cc.writeHeader(":path", path)
+ cc.writeHeader(":path", req.URL.RequestURI())
cc.writeHeader(":scheme", "https")
for k, vv := range req.Header {
return cc.hbuf.Bytes()
}
-func (cc *http2clientConn) writeHeader(name, value string) {
- log.Printf("sending %q = %q", name, value)
+func (cc *http2ClientConn) writeHeader(name, value string) {
cc.henc.WriteField(hpack.HeaderField{Name: name, Value: value})
}
}
// requires cc.mu be held.
-func (cc *http2clientConn) newStream() *http2clientStream {
+func (cc *http2ClientConn) newStream() *http2clientStream {
cs := &http2clientStream{
- ID: cc.nextStreamID,
- resc: make(chan http2resAndError, 1),
- }
+ cc: cc,
+ ID: cc.nextStreamID,
+ resc: make(chan http2resAndError, 1),
+ peerReset: make(chan struct{}),
+ }
+ cs.flow.add(int32(cc.initialWindowSize))
+ cs.flow.setConnFlow(&cc.flow)
+ cs.inflow.add(http2transportDefaultStreamFlow)
+ cs.inflow.setConnFlow(&cc.inflow)
cc.nextStreamID += 2
cc.streams[cs.ID] = cs
return cs
}
-func (cc *http2clientConn) streamByID(id uint32, andRemove bool) *http2clientStream {
+func (cc *http2ClientConn) streamByID(id uint32, andRemove bool) *http2clientStream {
cc.mu.Lock()
defer cc.mu.Unlock()
cs := cc.streams[id]
return cs
}
-// runs in its own goroutine.
-func (cc *http2clientConn) readLoop() {
- defer cc.t.removeClientConn(cc)
- defer close(cc.readerDone)
-
- activeRes := map[uint32]*http2clientStream{}
-
- defer func() {
- err := cc.readerErr
- if err == io.EOF {
- err = io.ErrUnexpectedEOF
- }
- for _, cs := range activeRes {
- cs.pw.CloseWithError(err)
- }
- }()
+// clientConnReadLoop is the state owned by the clientConn's frame-reading readLoop.
+type http2clientConnReadLoop struct {
+ cc *http2ClientConn
+ activeRes map[uint32]*http2clientStream // keyed by streamID
// continueStreamID is the stream ID we're waiting for
// continuation frames for.
- var continueStreamID uint32
+ continueStreamID uint32
+
+ hdec *hpack.Decoder
+
+ // Fields reset on each HEADERS:
+ nextRes *Response
+ sawRegHeader bool // saw non-pseudo header
+ reqMalformed error // non-nil once known to be malformed
+}
+
+// readLoop runs in its own goroutine and reads and dispatches frames.
+func (cc *http2ClientConn) readLoop() {
+ rl := &http2clientConnReadLoop{
+ cc: cc,
+ activeRes: make(map[uint32]*http2clientStream),
+ }
+
+ rl.hdec = hpack.NewDecoder(http2initialHeaderTableSize, rl.onNewHeaderField)
+
+ defer rl.cleanup()
+ cc.readerErr = rl.run()
+ if ce, ok := cc.readerErr.(http2ConnectionError); ok {
+ cc.wmu.Lock()
+ cc.fr.WriteGoAway(0, http2ErrCode(ce), nil)
+ cc.wmu.Unlock()
+ }
+}
+
+func (rl *http2clientConnReadLoop) cleanup() {
+ cc := rl.cc
+ defer cc.tconn.Close()
+ defer cc.t.connPool().MarkDead(cc)
+ defer close(cc.readerDone)
+
+ err := cc.readerErr
+ if err == io.EOF {
+ err = io.ErrUnexpectedEOF
+ }
+ cc.mu.Lock()
+ for _, cs := range rl.activeRes {
+ cs.bufPipe.CloseWithError(err)
+ }
+ for _, cs := range cc.streams {
+ select {
+ case cs.resc <- http2resAndError{err: err}:
+ default:
+ }
+ }
+ cc.closed = true
+ cc.cond.Broadcast()
+ cc.mu.Unlock()
+}
+func (rl *http2clientConnReadLoop) run() error {
+ cc := rl.cc
for {
f, err := cc.fr.ReadFrame()
- if err != nil {
- cc.readerErr = err
- return
+ if se, ok := err.(http2StreamError); ok {
+
+ return se
+ } else if err != nil {
+ return err
}
- log.Printf("Transport received %v: %#v", f.Header(), f)
+ cc.vlogf("Transport received %v: %#v", f.Header(), f)
streamID := f.Header().StreamID
_, isContinue := f.(*http2ContinuationFrame)
if isContinue {
- if streamID != continueStreamID {
- log.Printf("Protocol violation: got CONTINUATION with id %d; want %d", streamID, continueStreamID)
- cc.readerErr = http2ConnectionError(http2ErrCodeProtocol)
- return
+ if streamID != rl.continueStreamID {
+ cc.logf("Protocol violation: got CONTINUATION with id %d; want %d", streamID, rl.continueStreamID)
+ return http2ConnectionError(http2ErrCodeProtocol)
}
- } else if continueStreamID != 0 {
-
- log.Printf("Protocol violation: got %T for stream %d, want CONTINUATION for %d", f, streamID, continueStreamID)
- cc.readerErr = http2ConnectionError(http2ErrCodeProtocol)
- return
- }
-
- if streamID%2 == 0 {
+ } else if rl.continueStreamID != 0 {
- continue
- }
- streamEnded := false
- if ff, ok := f.(http2streamEnder); ok {
- streamEnded = ff.StreamEnded()
- }
-
- cs := cc.streamByID(streamID, streamEnded)
- if cs == nil {
- log.Printf("Received frame for untracked stream ID %d", streamID)
- continue
+ cc.logf("Protocol violation: got %T for stream %d, want CONTINUATION for %d", f, streamID, rl.continueStreamID)
+ return http2ConnectionError(http2ErrCodeProtocol)
}
switch f := f.(type) {
case *http2HeadersFrame:
- cc.nextRes = &Response{
- Proto: "HTTP/2.0",
- ProtoMajor: 2,
- Header: make(Header),
- }
- cs.pr, cs.pw = io.Pipe()
- cc.hdec.Write(f.HeaderBlockFragment())
+ err = rl.processHeaders(f)
case *http2ContinuationFrame:
- cc.hdec.Write(f.HeaderBlockFragment())
+ err = rl.processContinuation(f)
case *http2DataFrame:
- log.Printf("DATA: %q", f.Data())
- cs.pw.Write(f.Data())
+ err = rl.processData(f)
case *http2GoAwayFrame:
- cc.t.removeClientConn(cc)
- if f.ErrCode != 0 {
-
- log.Printf("transport got GOAWAY with error code = %v", f.ErrCode)
- }
- cc.setGoAway(f)
+ err = rl.processGoAway(f)
+ case *http2RSTStreamFrame:
+ err = rl.processResetStream(f)
+ case *http2SettingsFrame:
+ err = rl.processSettings(f)
+ case *http2PushPromiseFrame:
+ err = rl.processPushPromise(f)
+ case *http2WindowUpdateFrame:
+ err = rl.processWindowUpdate(f)
+ case *http2PingFrame:
+ err = rl.processPing(f)
default:
- log.Printf("Transport: unhandled response frame type %T", f)
+ cc.logf("Transport: unhandled response frame type %T", f)
}
- headersEnded := false
- if he, ok := f.(http2headersEnder); ok {
- headersEnded = he.HeadersEnded()
- if headersEnded {
- continueStreamID = 0
- } else {
- continueStreamID = streamID
- }
+ if err != nil {
+ return err
}
+ }
+}
+
+func (rl *http2clientConnReadLoop) processHeaders(f *http2HeadersFrame) error {
+ rl.sawRegHeader = false
+ rl.reqMalformed = nil
+ rl.nextRes = &Response{
+ Proto: "HTTP/2.0",
+ ProtoMajor: 2,
+ Header: make(Header),
+ }
+ return rl.processHeaderBlockFragment(f.HeaderBlockFragment(), f.StreamID, f.HeadersEnded(), f.StreamEnded())
+}
+
+func (rl *http2clientConnReadLoop) processContinuation(f *http2ContinuationFrame) error {
+ return rl.processHeaderBlockFragment(f.HeaderBlockFragment(), f.StreamID, f.HeadersEnded(), f.StreamEnded())
+}
+
+func (rl *http2clientConnReadLoop) processHeaderBlockFragment(frag []byte, streamID uint32, headersEnded, streamEnded bool) error {
+ cc := rl.cc
+ cs := cc.streamByID(streamID, streamEnded)
+ if cs == nil {
+
+ return nil
+ }
+ _, err := rl.hdec.Write(frag)
+ if err != nil {
+ return err
+ }
+ if !headersEnded {
+ rl.continueStreamID = cs.ID
+ return nil
+ }
+
+ rl.continueStreamID = 0
- if streamEnded {
- cs.pw.Close()
- delete(activeRes, streamID)
+ if rl.reqMalformed != nil {
+ cs.resc <- http2resAndError{err: rl.reqMalformed}
+ rl.cc.writeStreamReset(cs.ID, http2ErrCodeProtocol, rl.reqMalformed)
+ return nil
+ }
+
+ res := rl.nextRes
+ if streamEnded {
+ res.Body = http2noBody
+ } else {
+ buf := new(bytes.Buffer)
+ cs.bufPipe = http2pipe{b: buf}
+ res.Body = http2transportResponseBody{cs}
+ }
+ rl.activeRes[cs.ID] = cs
+ cs.resc <- http2resAndError{res: res}
+ rl.nextRes = nil
+ return nil
+}
+
+// transportResponseBody is the concrete type of Transport.RoundTrip's
+// Response.Body. It is an io.ReadCloser. On Read, it reads from cs.body.
+// On Close it sends RST_STREAM if EOF wasn't already seen.
+type http2transportResponseBody struct {
+ cs *http2clientStream
+}
+
+func (b http2transportResponseBody) Read(p []byte) (n int, err error) {
+ n, err = b.cs.bufPipe.Read(p)
+ if n == 0 {
+ return
+ }
+
+ cs := b.cs
+ cc := cs.cc
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
+
+ var connAdd, streamAdd int32
+
+ if v := cc.inflow.available(); v < http2transportDefaultConnFlow/2 {
+ connAdd = http2transportDefaultConnFlow - v
+ cc.inflow.add(connAdd)
+ }
+ if err == nil {
+ if v := cs.inflow.available(); v < http2transportDefaultStreamFlow-http2transportDefaultStreamMinRefresh {
+ streamAdd = http2transportDefaultStreamFlow - v
+ cs.inflow.add(streamAdd)
}
- if headersEnded {
- if cs == nil {
- panic("couldn't find stream")
- }
+ }
+ if connAdd != 0 || streamAdd != 0 {
+ cc.wmu.Lock()
+ defer cc.wmu.Unlock()
+ if connAdd != 0 {
+ cc.fr.WriteWindowUpdate(0, http2mustUint31(connAdd))
+ }
+ if streamAdd != 0 {
+ cc.fr.WriteWindowUpdate(cs.ID, http2mustUint31(streamAdd))
+ }
+ cc.bw.Flush()
+ }
+ return
+}
+
+func (b http2transportResponseBody) Close() error {
+ if b.cs.bufPipe.Err() != io.EOF {
+
+ b.cs.cc.writeStreamReset(b.cs.ID, http2ErrCodeCancel, nil)
+ }
+ return nil
+}
+
+func (rl *http2clientConnReadLoop) processData(f *http2DataFrame) error {
+ cc := rl.cc
+ cs := cc.streamByID(f.StreamID, f.StreamEnded())
+ if cs == nil {
+ return nil
+ }
+ data := f.Data()
+ if http2VerboseLogs {
+ rl.cc.logf("DATA: %q", data)
+ }
- cc.nextRes.Body = cs.pr
- res := cc.nextRes
- activeRes[streamID] = cs
- cs.resc <- http2resAndError{res: res}
+ cc.mu.Lock()
+ if cs.inflow.available() >= int32(len(data)) {
+ cs.inflow.take(int32(len(data)))
+ } else {
+ cc.mu.Unlock()
+ return http2ConnectionError(http2ErrCodeFlowControl)
+ }
+ cc.mu.Unlock()
+
+ if _, err := cs.bufPipe.Write(data); err != nil {
+ return err
+ }
+
+ if f.StreamEnded() {
+ cs.bufPipe.CloseWithError(io.EOF)
+ delete(rl.activeRes, cs.ID)
+ }
+ return nil
+}
+
+func (rl *http2clientConnReadLoop) processGoAway(f *http2GoAwayFrame) error {
+ cc := rl.cc
+ cc.t.connPool().MarkDead(cc)
+ if f.ErrCode != 0 {
+
+ cc.vlogf("transport got GOAWAY with error code = %v", f.ErrCode)
+ }
+ cc.setGoAway(f)
+ return nil
+}
+
+func (rl *http2clientConnReadLoop) processSettings(f *http2SettingsFrame) error {
+ cc := rl.cc
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
+ return f.ForeachSetting(func(s http2Setting) error {
+ switch s.ID {
+ case http2SettingMaxFrameSize:
+ cc.maxFrameSize = s.Val
+ case http2SettingMaxConcurrentStreams:
+ cc.maxConcurrentStreams = s.Val
+ case http2SettingInitialWindowSize:
+
+ cc.initialWindowSize = s.Val
+ default:
+
+ cc.vlogf("Unhandled Setting: %v", s)
}
+ return nil
+ })
+}
+
+func (rl *http2clientConnReadLoop) processWindowUpdate(f *http2WindowUpdateFrame) error {
+ cc := rl.cc
+ cs := cc.streamByID(f.StreamID, false)
+ if f.StreamID != 0 && cs == nil {
+ return nil
}
+
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
+
+ fl := &cc.flow
+ if cs != nil {
+ fl = &cs.flow
+ }
+ if !fl.add(int32(f.Increment)) {
+ return http2ConnectionError(http2ErrCodeFlowControl)
+ }
+ cc.cond.Broadcast()
+ return nil
}
-func (cc *http2clientConn) onNewHeaderField(f hpack.HeaderField) {
+func (rl *http2clientConnReadLoop) processResetStream(f *http2RSTStreamFrame) error {
+ cs := rl.cc.streamByID(f.StreamID, true)
+ if cs == nil {
- log.Printf("Header field: %+v", f)
- if f.Name == ":status" {
- code, err := strconv.Atoi(f.Value)
- if err != nil {
- panic("TODO: be graceful")
+ return nil
+ }
+ select {
+ case <-cs.peerReset:
+
+ default:
+ err := http2StreamError{cs.ID, f.ErrCode}
+ cs.resetErr = err
+ close(cs.peerReset)
+ cs.bufPipe.CloseWithError(err)
+ }
+ delete(rl.activeRes, cs.ID)
+ return nil
+}
+
+func (rl *http2clientConnReadLoop) processPing(f *http2PingFrame) error {
+ if f.IsAck() {
+
+ return nil
+ }
+ cc := rl.cc
+ cc.wmu.Lock()
+ defer cc.wmu.Unlock()
+ if err := cc.fr.WritePing(true, f.Data); err != nil {
+ return err
+ }
+ return cc.bw.Flush()
+}
+
+func (rl *http2clientConnReadLoop) processPushPromise(f *http2PushPromiseFrame) error {
+
+ return http2ConnectionError(http2ErrCodeProtocol)
+}
+
+func (cc *http2ClientConn) writeStreamReset(streamID uint32, code http2ErrCode, err error) {
+
+ cc.wmu.Lock()
+ cc.fr.WriteRSTStream(streamID, code)
+ cc.wmu.Unlock()
+}
+
+// onNewHeaderField runs on the readLoop goroutine whenever a new
+// hpack header field is decoded.
+func (rl *http2clientConnReadLoop) onNewHeaderField(f hpack.HeaderField) {
+ cc := rl.cc
+ if http2VerboseLogs {
+ cc.logf("Header field: %+v", f)
+ }
+ isPseudo := strings.HasPrefix(f.Name, ":")
+ if isPseudo {
+ if rl.sawRegHeader {
+ rl.reqMalformed = errors.New("http2: invalid pseudo header after regular header")
+ return
}
- cc.nextRes.Status = f.Value + " " + StatusText(code)
- cc.nextRes.StatusCode = code
- return
+ switch f.Name {
+ case ":status":
+ code, err := strconv.Atoi(f.Value)
+ if err != nil {
+ rl.reqMalformed = errors.New("http2: invalid :status")
+ return
+ }
+ rl.nextRes.Status = f.Value + " " + StatusText(code)
+ rl.nextRes.StatusCode = code
+ default:
+
+ rl.reqMalformed = fmt.Errorf("http2: unknown response pseudo header %q", f.Name)
+ }
+ } else {
+ rl.sawRegHeader = true
+ rl.nextRes.Header.Add(CanonicalHeaderKey(f.Name), f.Value)
}
- if strings.HasPrefix(f.Name, ":") {
+}
- return
+func (cc *http2ClientConn) logf(format string, args ...interface{}) {
+ cc.t.logf(format, args...)
+}
+
+func (cc *http2ClientConn) vlogf(format string, args ...interface{}) {
+ cc.t.vlogf(format, args...)
+}
+
+func (t *http2Transport) vlogf(format string, args ...interface{}) {
+ if http2VerboseLogs {
+ t.logf(format, args...)
}
- cc.nextRes.Header.Add(CanonicalHeaderKey(f.Name), f.Value)
}
+func (t *http2Transport) logf(format string, args ...interface{}) {
+ log.Printf(format, args...)
+}
+
+var http2noBody io.ReadCloser = ioutil.NopCloser(bytes.NewReader(nil))
+
+func http2strSliceContains(ss []string, s string) bool {
+ for _, v := range ss {
+ if v == s {
+ return true
+ }
+ }
+ return false
+}
+
+type http2erringRoundTripper struct{ err error }
+
+func (rt http2erringRoundTripper) RoundTrip(*Request) (*Response, error) { return nil, rt.err }
+
// writeFramer is implemented by any type that is used to write frames.
type http2writeFramer interface {
writeFrame(http2writeContext) error
return v.endStream
case *http2writeResHeaders:
return v.endStream
+ case nil:
+
+ panic("endsStream called on nil writeFramer")
}
return false
}
return m
}
+// writeHeader writes a header if it was not written yet and
+// detects Content-Type if needed.
+//
+// bytes or str are the beginning of the response body.
+// We pass both to avoid unnecessarily generate garbage
+// in rw.WriteString which was created for performance reasons.
+// Non-nil bytes win.
+func (rw *ResponseRecorder) writeHeader(b []byte, str string) {
+ if rw.wroteHeader {
+ return
+ }
+ if len(str) > 512 {
+ str = str[:512]
+ }
+
+ _, hasType := rw.HeaderMap["Content-Type"]
+ hasTE := rw.HeaderMap.Get("Transfer-Encoding") != ""
+ if !hasType && !hasTE {
+ if b == nil {
+ b = []byte(str)
+ }
+ rw.HeaderMap.Set("Content-Type", http.DetectContentType(b))
+ }
+
+ rw.WriteHeader(200)
+}
+
// Write always succeeds and writes to rw.Body, if not nil.
func (rw *ResponseRecorder) Write(buf []byte) (int, error) {
- if !rw.wroteHeader {
- rw.WriteHeader(200)
- }
+ rw.writeHeader(buf, "")
if rw.Body != nil {
rw.Body.Write(buf)
}
// WriteString always succeeds and writes to rw.Body, if not nil.
func (rw *ResponseRecorder) WriteString(str string) (int, error) {
- if !rw.wroteHeader {
- rw.WriteHeader(200)
- }
+ rw.writeHeader(nil, str)
if rw.Body != nil {
rw.Body.WriteString(str)
}
func (rw *ResponseRecorder) WriteHeader(code int) {
if !rw.wroteHeader {
rw.Code = code
+ rw.wroteHeader = true
}
- rw.wroteHeader = true
}
// Flush sets rw.Flushed to true.
return nil
}
}
+ hasHeader := func(key, want string) checkFunc {
+ return func(rec *ResponseRecorder) error {
+ if got := rec.HeaderMap.Get(key); got != want {
+ return fmt.Errorf("header %s = %q; want %q", key, got, want)
+ }
+ return nil
+ }
+ }
tests := []struct {
name string
func(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "hi first")
},
- check(hasStatus(200), hasContents("hi first"), hasFlush(false)),
+ check(
+ hasStatus(200),
+ hasContents("hi first"),
+ hasFlush(false),
+ hasHeader("Content-Type", "text/plain; charset=utf-8"),
+ ),
},
{
"flush",
},
check(hasStatus(200), hasFlush(true)),
},
+ {
+ "Content-Type detection",
+ func(w http.ResponseWriter, r *http.Request) {
+ io.WriteString(w, "<html>")
+ },
+ check(hasHeader("Content-Type", "text/html; charset=utf-8")),
+ },
+ {
+ "no Content-Type detection with Transfer-Encoding",
+ func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Transfer-Encoding", "some encoding")
+ io.WriteString(w, "<html>")
+ },
+ check(hasHeader("Content-Type", "")), // no header
+ },
+ {
+ "no Content-Type detection if set explicitly",
+ func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "some/type")
+ io.WriteString(w, "<html>")
+ },
+ check(hasHeader("Content-Type", "some/type")),
+ },
}
r, _ := http.NewRequest("GET", "http://foo.com/", nil)
for _, tt := range tests {
package httptest
import (
+ "bytes"
"crypto/tls"
"flag"
"fmt"
+ "log"
"net"
"net/http"
+ "net/http/internal"
"os"
+ "runtime"
"sync"
+ "time"
)
// A Server is an HTTP server listening on a system-chosen port on the
// wg counts the number of outstanding HTTP requests on this server.
// Close blocks until all requests are finished.
wg sync.WaitGroup
-}
-
-// historyListener keeps track of all connections that it's ever
-// accepted.
-type historyListener struct {
- net.Listener
- sync.Mutex // protects history
- history []net.Conn
-}
-func (hs *historyListener) Accept() (c net.Conn, err error) {
- c, err = hs.Listener.Accept()
- if err == nil {
- hs.Lock()
- hs.history = append(hs.history, c)
- hs.Unlock()
- }
- return
+ mu sync.Mutex // guards closed and conns
+ closed bool
+ conns map[net.Conn]http.ConnState // except terminal states
}
func newLocalListener() net.Listener {
if s.URL != "" {
panic("Server already started")
}
- s.Listener = &historyListener{Listener: s.Listener}
s.URL = "http://" + s.Listener.Addr().String()
- s.wrapHandler()
- go s.Config.Serve(s.Listener)
+ s.wrap()
+ s.goServe()
if *serve != "" {
fmt.Fprintln(os.Stderr, "httptest: serving on", s.URL)
select {}
if s.URL != "" {
panic("Server already started")
}
- cert, err := tls.X509KeyPair(localhostCert, localhostKey)
+ cert, err := tls.X509KeyPair(internal.LocalhostCert, internal.LocalhostKey)
if err != nil {
panic(fmt.Sprintf("httptest: NewTLSServer: %v", err))
}
if len(s.TLS.Certificates) == 0 {
s.TLS.Certificates = []tls.Certificate{cert}
}
- tlsListener := tls.NewListener(s.Listener, s.TLS)
-
- s.Listener = &historyListener{Listener: tlsListener}
+ s.Listener = tls.NewListener(s.Listener, s.TLS)
s.URL = "https://" + s.Listener.Addr().String()
- s.wrapHandler()
- go s.Config.Serve(s.Listener)
-}
-
-func (s *Server) wrapHandler() {
- h := s.Config.Handler
- if h == nil {
- h = http.DefaultServeMux
- }
- s.Config.Handler = &waitGroupHandler{
- s: s,
- h: h,
- }
+ s.wrap()
+ s.goServe()
}
// NewTLSServer starts and returns a new Server using TLS.
return ts
}
+type closeIdleTransport interface {
+ CloseIdleConnections()
+}
+
// Close shuts down the server and blocks until all outstanding
// requests on this server have completed.
func (s *Server) Close() {
- s.Listener.Close()
- s.wg.Wait()
- s.CloseClientConnections()
- if t, ok := http.DefaultTransport.(*http.Transport); ok {
+ s.mu.Lock()
+ if !s.closed {
+ s.closed = true
+ s.Listener.Close()
+ s.Config.SetKeepAlivesEnabled(false)
+ for c, st := range s.conns {
+ // Force-close any idle connections (those between
+ // requests) and new connections (those which connected
+ // but never sent a request). StateNew connections are
+ // super rare and have only been seen (in
+ // previously-flaky tests) in the case of
+ // socket-late-binding races from the http Client
+ // dialing this server and then getting an idle
+ // connection before the dial completed. There is thus
+ // a connected connection in StateNew with no
+ // associated Request. We only close StateIdle and
+ // StateNew because they're not doing anything. It's
+ // possible StateNew is about to do something in a few
+ // milliseconds, but a previous CL to check again in a
+ // few milliseconds wasn't liked (early versions of
+ // https://golang.org/cl/15151) so now we just
+ // forcefully close StateNew. The docs for Server.Close say
+ // we wait for "oustanding requests", so we don't close things
+ // in StateActive.
+ if st == http.StateIdle || st == http.StateNew {
+ s.closeConn(c)
+ }
+ }
+ // If this server doesn't shut down in 5 seconds, tell the user why.
+ t := time.AfterFunc(5*time.Second, s.logCloseHangDebugInfo)
+ defer t.Stop()
+ }
+ s.mu.Unlock()
+
+ // Not part of httptest.Server's correctness, but assume most
+ // users of httptest.Server will be using the standard
+ // transport, so help them out and close any idle connections for them.
+ if t, ok := http.DefaultTransport.(closeIdleTransport); ok {
t.CloseIdleConnections()
}
+
+ s.wg.Wait()
}
-// CloseClientConnections closes any currently open HTTP connections
-// to the test Server.
-func (s *Server) CloseClientConnections() {
- hl, ok := s.Listener.(*historyListener)
- if !ok {
- return
+func (s *Server) logCloseHangDebugInfo() {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ var buf bytes.Buffer
+ buf.WriteString("httptest.Server blocked in Close after 5 seconds, waiting for connections:\n")
+ for c, st := range s.conns {
+ fmt.Fprintf(&buf, " %T %p %v in state %v\n", c, c, c.RemoteAddr(), st)
}
- hl.Lock()
- for _, conn := range hl.history {
- conn.Close()
+ log.Print(buf.String())
+}
+
+// CloseClientConnections closes any open HTTP connections to the test Server.
+func (s *Server) CloseClientConnections() {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ for c := range s.conns {
+ s.closeConn(c)
}
- hl.Unlock()
}
-// waitGroupHandler wraps a handler, incrementing and decrementing a
-// sync.WaitGroup on each request, to enable Server.Close to block
-// until outstanding requests are finished.
-type waitGroupHandler struct {
- s *Server
- h http.Handler // non-nil
+func (s *Server) goServe() {
+ s.wg.Add(1)
+ go func() {
+ defer s.wg.Done()
+ s.Config.Serve(s.Listener)
+ }()
+}
+
+// wrap installs the connection state-tracking hook to know which
+// connections are idle.
+func (s *Server) wrap() {
+ oldHook := s.Config.ConnState
+ s.Config.ConnState = func(c net.Conn, cs http.ConnState) {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ switch cs {
+ case http.StateNew:
+ s.wg.Add(1)
+ if _, exists := s.conns[c]; exists {
+ panic("invalid state transition")
+ }
+ if s.conns == nil {
+ s.conns = make(map[net.Conn]http.ConnState)
+ }
+ s.conns[c] = cs
+ if s.closed {
+ // Probably just a socket-late-binding dial from
+ // the default transport that lost the race (and
+ // thus this connection is now idle and will
+ // never be used).
+ s.closeConn(c)
+ }
+ case http.StateActive:
+ if oldState, ok := s.conns[c]; ok {
+ if oldState != http.StateNew && oldState != http.StateIdle {
+ panic("invalid state transition")
+ }
+ s.conns[c] = cs
+ }
+ case http.StateIdle:
+ if oldState, ok := s.conns[c]; ok {
+ if oldState != http.StateActive {
+ panic("invalid state transition")
+ }
+ s.conns[c] = cs
+ }
+ if s.closed {
+ s.closeConn(c)
+ }
+ case http.StateHijacked, http.StateClosed:
+ s.forgetConn(c)
+ }
+ if oldHook != nil {
+ oldHook(c, cs)
+ }
+ }
}
-func (h *waitGroupHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
- h.s.wg.Add(1)
- defer h.s.wg.Done() // a defer, in case ServeHTTP below panics
- h.h.ServeHTTP(w, r)
+// closeConn closes c. Except on plan9, which is special. See comment below.
+// s.mu must be held.
+func (s *Server) closeConn(c net.Conn) {
+ if runtime.GOOS == "plan9" {
+ // Go's Plan 9 net package isn't great at unblocking reads when
+ // their underlying TCP connections are closed. Don't trust
+ // that that the ConnState state machine will get to
+ // StateClosed. Instead, just go there directly. Plan 9 may leak
+ // resources if the syscall doesn't end up returning. Oh well.
+ s.forgetConn(c)
+ }
+ go c.Close()
}
-// localhostCert is a PEM-encoded TLS cert with SAN IPs
-// "127.0.0.1" and "[::1]", expiring at the last second of 2049 (the end
-// of ASN.1 time).
-// generated from src/crypto/tls:
-// go run generate_cert.go --rsa-bits 1024 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
-var localhostCert = []byte(`-----BEGIN CERTIFICATE-----
-MIICEzCCAXygAwIBAgIQMIMChMLGrR+QvmQvpwAU6zANBgkqhkiG9w0BAQsFADAS
-MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw
-MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
-iQKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9SjY1bIw4
-iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZBl2+XsDul
-rKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQABo2gwZjAO
-BgNVHQ8BAf8EBAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUw
-AwEB/zAuBgNVHREEJzAlggtleGFtcGxlLmNvbYcEfwAAAYcQAAAAAAAAAAAAAAAA
-AAAAATANBgkqhkiG9w0BAQsFAAOBgQCEcetwO59EWk7WiJsG4x8SY+UIAA+flUI9
-tyC4lNhbcF2Idq9greZwbYCqTTTr2XiRNSMLCOjKyI7ukPoPjo16ocHj+P3vZGfs
-h1fIw3cSS2OolhloGw/XM6RWPWtPAlGykKLciQrBru5NAPvCMsb/I1DAceTiotQM
-fblo6RBxUQ==
------END CERTIFICATE-----`)
-
-// localhostKey is the private key for localhostCert.
-var localhostKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
-MIICXgIBAAKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9
-SjY1bIw4iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZB
-l2+XsDulrKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQAB
-AoGAGRzwwir7XvBOAy5tM/uV6e+Zf6anZzus1s1Y1ClbjbE6HXbnWWF/wbZGOpet
-3Zm4vD6MXc7jpTLryzTQIvVdfQbRc6+MUVeLKwZatTXtdZrhu+Jk7hx0nTPy8Jcb
-uJqFk541aEw+mMogY/xEcfbWd6IOkp+4xqjlFLBEDytgbIECQQDvH/E6nk+hgN4H
-qzzVtxxr397vWrjrIgPbJpQvBsafG7b0dA4AFjwVbFLmQcj2PprIMmPcQrooz8vp
-jy4SHEg1AkEA/v13/5M47K9vCxmb8QeD/asydfsgS5TeuNi8DoUBEmiSJwma7FXY
-fFUtxuvL7XvjwjN5B30pNEbc6Iuyt7y4MQJBAIt21su4b3sjXNueLKH85Q+phy2U
-fQtuUE9txblTu14q3N7gHRZB4ZMhFYyDy8CKrN2cPg/Fvyt0Xlp/DoCzjA0CQQDU
-y2ptGsuSmgUtWj3NM9xuwYPm+Z/F84K6+ARYiZ6PYj013sovGKUFfYAqVXVlxtIX
-qyUBnu3X9ps8ZfjLZO7BAkEAlT4R5Yl6cGhaJQYZHOde3JEMhNRcVFMO8dJDaFeo
-f9Oeos0UUothgiDktdQHxdNEwLjQf7lJJBzV+5OtwswCWA==
------END RSA PRIVATE KEY-----`)
+// forgetConn removes c from the set of tracked conns and decrements it from the
+// waitgroup, unless it was previously removed.
+// s.mu must be held.
+func (s *Server) forgetConn(c net.Conn) {
+ if _, ok := s.conns[c]; ok {
+ delete(s.conns, c)
+ s.wg.Done()
+ }
+}
package httptest
import (
+ "bufio"
"io/ioutil"
+ "net"
"net/http"
"testing"
)
t.Errorf("got %q, want hello", string(got))
}
}
+
+// Issue 12781
+func TestGetAfterClose(t *testing.T) {
+ ts := NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Write([]byte("hello"))
+ }))
+
+ res, err := http.Get(ts.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ got, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if string(got) != "hello" {
+ t.Fatalf("got %q, want hello", string(got))
+ }
+
+ ts.Close()
+
+ res, err = http.Get(ts.URL)
+ if err == nil {
+ body, _ := ioutil.ReadAll(res.Body)
+ t.Fatalf("Unexected response after close: %v, %v, %s", res.Status, res.Header, body)
+ }
+}
+
+func TestServerCloseBlocking(t *testing.T) {
+ ts := NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Write([]byte("hello"))
+ }))
+ dial := func() net.Conn {
+ c, err := net.Dial("tcp", ts.Listener.Addr().String())
+ if err != nil {
+ t.Fatal(err)
+ }
+ return c
+ }
+
+ // Keep one connection in StateNew (connected, but not sending anything)
+ cnew := dial()
+ defer cnew.Close()
+
+ // Keep one connection in StateIdle (idle after a request)
+ cidle := dial()
+ defer cidle.Close()
+ cidle.Write([]byte("HEAD / HTTP/1.1\r\nHost: foo\r\n\r\n"))
+ _, err := http.ReadResponse(bufio.NewReader(cidle), nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ ts.Close() // test we don't hang here forever.
+}
// If nil, logging goes to os.Stderr via the log package's
// standard logger.
ErrorLog *log.Logger
+
+ // BufferPool optionally specifies a buffer pool to
+ // get byte slices for use by io.CopyBuffer when
+ // copying HTTP response bodies.
+ BufferPool BufferPool
+}
+
+// A BufferPool is an interface for getting and returning temporary
+// byte slices for use by io.CopyBuffer.
+type BufferPool interface {
+ Get() []byte
+ Put([]byte)
}
func singleJoiningSlash(a, b string) string {
}
}
- io.Copy(dst, src)
+ var buf []byte
+ if p.BufferPool != nil {
+ buf = p.BufferPool.Get()
+ }
+ io.CopyBuffer(dst, src, buf)
+ if p.BufferPool != nil {
+ p.BufferPool.Put(buf)
+ }
}
func (p *ReverseProxy) logf(format string, args ...interface{}) {
import (
"bufio"
+ "io"
"io/ioutil"
"log"
"net/http"
"net/http/httptest"
"net/url"
"reflect"
+ "strconv"
"strings"
+ "sync"
"testing"
"time"
)
t.Errorf("Got %q; want %q", slurp, "hi")
}
}
+
+type bufferPool struct {
+ get func() []byte
+ put func([]byte)
+}
+
+func (bp bufferPool) Get() []byte { return bp.get() }
+func (bp bufferPool) Put(v []byte) { bp.put(v) }
+
+func TestReverseProxyGetPutBuffer(t *testing.T) {
+ const msg = "hi"
+ backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ io.WriteString(w, msg)
+ }))
+ defer backend.Close()
+
+ backendURL, err := url.Parse(backend.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ var (
+ mu sync.Mutex
+ log []string
+ )
+ addLog := func(event string) {
+ mu.Lock()
+ defer mu.Unlock()
+ log = append(log, event)
+ }
+ rp := NewSingleHostReverseProxy(backendURL)
+ const size = 1234
+ rp.BufferPool = bufferPool{
+ get: func() []byte {
+ addLog("getBuf")
+ return make([]byte, size)
+ },
+ put: func(p []byte) {
+ addLog("putBuf-" + strconv.Itoa(len(p)))
+ },
+ }
+ frontend := httptest.NewServer(rp)
+ defer frontend.Close()
+
+ req, _ := http.NewRequest("GET", frontend.URL, nil)
+ req.Close = true
+ res, err := http.DefaultClient.Do(req)
+ if err != nil {
+ t.Fatalf("Get: %v", err)
+ }
+ slurp, err := ioutil.ReadAll(res.Body)
+ res.Body.Close()
+ if err != nil {
+ t.Fatalf("reading body: %v", err)
+ }
+ if string(slurp) != msg {
+ t.Errorf("msg = %q; want %q", slurp, msg)
+ }
+ wantLog := []string{"getBuf", "putBuf-" + strconv.Itoa(size)}
+ mu.Lock()
+ defer mu.Unlock()
+ if !reflect.DeepEqual(log, wantLog) {
+ t.Errorf("Log events = %q; want %q", log, wantLog)
+ }
+}
func (cr *chunkedReader) beginChunk() {
// chunk-size CRLF
var line []byte
- line, cr.err = readLine(cr.r)
+ line, cr.err = readChunkLine(cr.r)
if cr.err != nil {
return
}
// Read a line of bytes (up to \n) from b.
// Give up if the line exceeds maxLineLength.
-// The returned bytes are a pointer into storage in
-// the bufio, so they are only valid until the next bufio read.
-func readLine(b *bufio.Reader) (p []byte, err error) {
- if p, err = b.ReadSlice('\n'); err != nil {
+// The returned bytes are owned by the bufio.Reader
+// so they are only valid until the next bufio read.
+func readChunkLine(b *bufio.Reader) ([]byte, error) {
+ p, err := b.ReadSlice('\n')
+ if err != nil {
// We always know when EOF is coming.
// If the caller asked for a line, there should be a line.
if err == io.EOF {
if len(p) >= maxLineLength {
return nil, ErrLineTooLong
}
- return trimTrailingWhitespace(p), nil
+ p = trimTrailingWhitespace(p)
+ p, err = removeChunkExtension(p)
+ if err != nil {
+ return nil, err
+ }
+ return p, nil
}
func trimTrailingWhitespace(b []byte) []byte {
return b == ' ' || b == '\t' || b == '\n' || b == '\r'
}
+// removeChunkExtension removes any chunk-extension from p.
+// For example,
+// "0" => "0"
+// "0;token" => "0"
+// "0;token=val" => "0"
+// `0;token="quoted string"` => "0"
+func removeChunkExtension(p []byte) ([]byte, error) {
+ semi := bytes.IndexByte(p, ';')
+ if semi == -1 {
+ return p, nil
+ }
+ // TODO: care about exact syntax of chunk extensions? We're
+ // ignoring and stripping them anyway. For now just never
+ // return an error.
+ return p[:semi], nil
+}
+
// NewChunkedWriter returns a new chunkedWriter that translates writes into HTTP
// "chunked" format before writing them to w. Closing the returned chunkedWriter
// sends the final 0-length chunk that marks the end of the stream.
t.Error("expected error on bogus input")
}
}
+
+func TestChunkReadingIgnoresExtensions(t *testing.T) {
+ in := "7;ext=\"some quoted string\"\r\n" + // token=quoted string
+ "hello, \r\n" +
+ "17;someext\r\n" + // token without value
+ "world! 0123456789abcdef\r\n" +
+ "0;someextension=sometoken\r\n" // token=token
+ data, err := ioutil.ReadAll(NewChunkedReader(strings.NewReader(in)))
+ if err != nil {
+ t.Fatalf("ReadAll = %q, %v", data, err)
+ }
+ if g, e := string(data), "hello, world! 0123456789abcdef"; g != e {
+ t.Errorf("read %q; want %q", g, e)
+ }
+}
--- /dev/null
+// Copyright 2015 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 internal
+
+// LocalhostCert is a PEM-encoded TLS cert with SAN IPs
+// "127.0.0.1" and "[::1]", expiring at Jan 29 16:00:00 2084 GMT.
+// generated from src/crypto/tls:
+// go run generate_cert.go --rsa-bits 1024 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
+var LocalhostCert = []byte(`-----BEGIN CERTIFICATE-----
+MIICEzCCAXygAwIBAgIQMIMChMLGrR+QvmQvpwAU6zANBgkqhkiG9w0BAQsFADAS
+MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw
+MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
+iQKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9SjY1bIw4
+iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZBl2+XsDul
+rKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQABo2gwZjAO
+BgNVHQ8BAf8EBAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUw
+AwEB/zAuBgNVHREEJzAlggtleGFtcGxlLmNvbYcEfwAAAYcQAAAAAAAAAAAAAAAA
+AAAAATANBgkqhkiG9w0BAQsFAAOBgQCEcetwO59EWk7WiJsG4x8SY+UIAA+flUI9
+tyC4lNhbcF2Idq9greZwbYCqTTTr2XiRNSMLCOjKyI7ukPoPjo16ocHj+P3vZGfs
+h1fIw3cSS2OolhloGw/XM6RWPWtPAlGykKLciQrBru5NAPvCMsb/I1DAceTiotQM
+fblo6RBxUQ==
+-----END CERTIFICATE-----`)
+
+// LocalhostKey is the private key for localhostCert.
+var LocalhostKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
+MIICXgIBAAKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9
+SjY1bIw4iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZB
+l2+XsDulrKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQAB
+AoGAGRzwwir7XvBOAy5tM/uV6e+Zf6anZzus1s1Y1ClbjbE6HXbnWWF/wbZGOpet
+3Zm4vD6MXc7jpTLryzTQIvVdfQbRc6+MUVeLKwZatTXtdZrhu+Jk7hx0nTPy8Jcb
+uJqFk541aEw+mMogY/xEcfbWd6IOkp+4xqjlFLBEDytgbIECQQDvH/E6nk+hgN4H
+qzzVtxxr397vWrjrIgPbJpQvBsafG7b0dA4AFjwVbFLmQcj2PprIMmPcQrooz8vp
+jy4SHEg1AkEA/v13/5M47K9vCxmb8QeD/asydfsgS5TeuNi8DoUBEmiSJwma7FXY
+fFUtxuvL7XvjwjN5B30pNEbc6Iuyt7y4MQJBAIt21su4b3sjXNueLKH85Q+phy2U
+fQtuUE9txblTu14q3N7gHRZB4ZMhFYyDy8CKrN2cPg/Fvyt0Xlp/DoCzjA0CQQDU
+y2ptGsuSmgUtWj3NM9xuwYPm+Z/F84K6+ARYiZ6PYj013sovGKUFfYAqVXVlxtIX
+qyUBnu3X9ps8ZfjLZO7BAkEAlT4R5Yl6cGhaJQYZHOde3JEMhNRcVFMO8dJDaFeo
+f9Oeos0UUothgiDktdQHxdNEwLjQf7lJJBzV+5OtwswCWA==
+-----END RSA PRIVATE KEY-----`)
--- /dev/null
+// Copyright 2015 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 http
+
+// Common HTTP methods.
+//
+// Unless otherwise noted, these are defined in RFC 7231 section 4.3.
+const (
+ MethodGet = "GET"
+ MethodHead = "HEAD"
+ MethodPost = "POST"
+ MethodPut = "PUT"
+ MethodPatch = "PATCH" // RFC 5741
+ MethodDelete = "DELETE"
+ MethodConnect = "CONNECT"
+ MethodOptions = "OPTIONS"
+ MethodTrace = "TRACE"
+)
return major, minor, true
}
+func validMethod(method string) bool {
+ /*
+ Method = "OPTIONS" ; Section 9.2
+ | "GET" ; Section 9.3
+ | "HEAD" ; Section 9.4
+ | "POST" ; Section 9.5
+ | "PUT" ; Section 9.6
+ | "DELETE" ; Section 9.7
+ | "TRACE" ; Section 9.8
+ | "CONNECT" ; Section 9.9
+ | extension-method
+ extension-method = token
+ token = 1*<any CHAR except CTLs or separators>
+ */
+ return len(method) > 0 && strings.IndexFunc(method, isNotToken) == -1
+}
+
// NewRequest returns a new Request given a method, URL, and optional body.
//
// If the provided body is also an io.Closer, the returned
// type's documentation for the difference between inbound and outbound
// request fields.
func NewRequest(method, urlStr string, body io.Reader) (*Request, error) {
+ if !validMethod(method) {
+ return nil, fmt.Errorf("net/http: invalid method %q", method)
+ }
u, err := url.Parse(urlStr)
if err != nil {
return nil, err
}
}
+func TestRequestInvalidMethod(t *testing.T) {
+ _, err := NewRequest("bad method", "http://foo.com/", nil)
+ if err == nil {
+ t.Error("expected error from NewRequest with invalid method")
+ }
+ req, err := NewRequest("GET", "http://foo.example/", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ req.Method = "bad method"
+ _, err = DefaultClient.Do(req)
+ if err == nil || !strings.Contains(err.Error(), "invalid method") {
+ t.Errorf("Transport error = %v; want invalid method", err)
+ }
+}
+
func TestNewRequestContentLength(t *testing.T) {
readByte := func(r io.Reader) io.Reader {
var b [1]byte
})
}
-func TestAutomaticHTTP2(t *testing.T) {
- ln, err := net.Listen("tcp", ":0")
- if err != nil {
- t.Fatal(err)
- }
+func TestAutomaticHTTP2_Serve(t *testing.T) {
+ defer afterTest(t)
+ ln := newLocalListener(t)
ln.Close() // immediately (not a defer!)
var s Server
if err := s.Serve(ln); err == nil {
}
}
+func TestAutomaticHTTP2_ListenAndServe(t *testing.T) {
+ defer afterTest(t)
+ defer SetTestHookServerServe(nil)
+ cert, err := tls.X509KeyPair(internal.LocalhostCert, internal.LocalhostKey)
+ if err != nil {
+ t.Fatal(err)
+ }
+ var ok bool
+ var s *Server
+ const maxTries = 5
+ var ln net.Listener
+Try:
+ for try := 0; try < maxTries; try++ {
+ ln = newLocalListener(t)
+ addr := ln.Addr().String()
+ ln.Close()
+ t.Logf("Got %v", addr)
+ lnc := make(chan net.Listener, 1)
+ SetTestHookServerServe(func(s *Server, ln net.Listener) {
+ lnc <- ln
+ })
+ s = &Server{
+ Addr: addr,
+ TLSConfig: &tls.Config{
+ Certificates: []tls.Certificate{cert},
+ },
+ }
+ errc := make(chan error, 1)
+ go func() { errc <- s.ListenAndServeTLS("", "") }()
+ select {
+ case err := <-errc:
+ t.Logf("On try #%v: %v", try+1, err)
+ continue
+ case ln = <-lnc:
+ ok = true
+ t.Logf("Listening on %v", ln.Addr().String())
+ break Try
+ }
+ }
+ if !ok {
+ t.Fatal("Failed to start up after %d tries", maxTries)
+ }
+ defer ln.Close()
+ c, err := tls.Dial("tcp", ln.Addr().String(), &tls.Config{
+ InsecureSkipVerify: true,
+ NextProtos: []string{"h2", "http/1.1"},
+ })
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+ if got, want := c.ConnectionState().NegotiatedProtocol, "h2"; got != want {
+ t.Errorf("NegotiatedProtocol = %q; want %q", got, want)
+ }
+ if got, want := c.ConnectionState().NegotiatedProtocolIsMutual, true; got != want {
+ t.Errorf("NegotiatedProtocolIsMutual = %v; want %v", got, want)
+ }
+}
+
type serverExpectTest struct {
contentLength int // of request body
chunked bool
return errors.New("no content-length")
}
if !strings.Contains(got, "Content-Type: text/plain") {
- return errors.New("no content-length")
+ return errors.New("no content-type")
}
return nil
},
if !strings.Contains(got, "404") {
return errors.New("wrong status")
}
- if strings.Contains(got, "Some-Header") {
+ if strings.Contains(got, "Too-Late") {
return errors.New("shouldn't have seen Too-Late")
}
return nil
}
}
+func TestHandlerSetsBodyNil(t *testing.T) {
+ defer afterTest(t)
+ ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ r.Body = nil
+ fmt.Fprintf(w, "%v", r.RemoteAddr)
+ }))
+ defer ts.Close()
+ get := func() string {
+ res, err := Get(ts.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer res.Body.Close()
+ slurp, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ t.Fatal(err)
+ }
+ return string(slurp)
+ }
+ a, b := get(), get()
+ if a != b {
+ t.Errorf("Failed to reuse connections between requests: %v vs %v", a, b)
+ }
+}
+
func BenchmarkClientServer(b *testing.B) {
b.ReportAllocs()
b.StopTimer()
type response struct {
conn *conn
req *Request // request for this response
- wroteHeader bool // reply header has been (logically) written
- wroteContinue bool // 100 Continue response was written
+ reqBody io.ReadCloser
+ wroteHeader bool // reply header has been (logically) written
+ wroteContinue bool // 100 Continue response was written
w *bufio.Writer // buffers output in chunks to chunkWriter
cw chunkWriter
w = &response{
conn: c,
req: req,
+ reqBody: req.Body,
handlerHeader: make(Header),
contentLength: -1,
}
// Close the body (regardless of w.closeAfterReply) so we can
// re-use its bufio.Reader later safely.
- w.req.Body.Close()
+ w.reqBody.Close()
if w.req.MultipartForm != nil {
w.req.MultipartForm.RemoveAll()
// Redirect replies to the request with a redirect to url,
// which may be a path relative to the request path.
+//
+// The provided code should be in the 3xx range and is usually
+// StatusMovedPermanently, StatusFound or StatusSeeOther.
func Redirect(w ResponseWriter, r *Request, urlStr string, code int) {
if u, err := url.Parse(urlStr); err == nil {
// If url was relative, make absolute by
// RedirectHandler returns a request handler that redirects
// each request it receives to the given url using the given
// status code.
+//
+// The provided code should be in the 3xx range and is usually
+// StatusMovedPermanently, StatusFound or StatusSeeOther.
func RedirectHandler(url string, code int) Handler {
return &redirectHandler{url, code}
}
disableKeepAlives int32 // accessed atomically.
nextProtoOnce sync.Once // guards initialization of TLSNextProto in Serve
+ nextProtoErr error
}
// A ConnState represents the state of a client connection to a server.
return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})
}
+var testHookServerServe func(*Server, net.Listener) // used if non-nil
+
// Serve accepts incoming connections on the Listener l, creating a
// new service goroutine for each. The service goroutines read requests and
// then call srv.Handler to reply to them.
// Serve always returns a non-nil error.
func (srv *Server) Serve(l net.Listener) error {
defer l.Close()
+ if fn := testHookServerServe; fn != nil {
+ fn(srv, l)
+ }
var tempDelay time.Duration // how long to sleep on accept failure
- srv.nextProtoOnce.Do(srv.setNextProtoDefaults)
+ if err := srv.setupHTTP2(); err != nil {
+ return err
+ }
for {
rw, e := l.Accept()
if e != nil {
if addr == "" {
addr = ":https"
}
+
+ // Setup HTTP/2 before srv.Serve, to initialize srv.TLSConfig
+ // before we clone it and create the TLS Listener.
+ if err := srv.setupHTTP2(); err != nil {
+ return err
+ }
+
config := cloneTLSConfig(srv.TLSConfig)
- if config.NextProtos == nil {
- config.NextProtos = []string{"http/1.1"}
+ if !strSliceContains(config.NextProtos, "http/1.1") {
+ config.NextProtos = append(config.NextProtos, "http/1.1")
}
if len(config.Certificates) == 0 || certFile != "" || keyFile != "" {
return srv.Serve(tlsListener)
}
-func (srv *Server) setNextProtoDefaults() {
+func (srv *Server) setupHTTP2() error {
+ srv.nextProtoOnce.Do(srv.onceSetNextProtoDefaults)
+ return srv.nextProtoErr
+}
+
+// onceSetNextProtoDefaults configures HTTP/2, if the user hasn't
+// configured otherwise. (by setting srv.TLSNextProto non-nil)
+// It must only be called via srv.nextProtoOnce (use srv.setupHTTP2).
+func (srv *Server) onceSetNextProtoDefaults() {
// Enable HTTP/2 by default if the user hasn't otherwise
// configured their TLSNextProto map.
if srv.TLSNextProto == nil {
- http2ConfigureServer(srv, nil)
+ srv.nextProtoErr = http2ConfigureServer(srv, nil)
}
}
return
}
+
+func strSliceContains(ss []string, s string) bool {
+ for _, v := range ss {
+ if v == s {
+ return true
+ }
+ }
+ return false
+}
ExpectContinueTimeout: 1 * time.Second,
}
+func init() {
+ if !strings.Contains(os.Getenv("GODEBUG"), "h2client=0") {
+ err := http2ConfigureTransport(DefaultTransport.(*Transport))
+ if err != nil {
+ panic(err)
+ }
+ }
+}
+
// DefaultMaxIdleConnsPerHost is the default value of Transport's
// MaxIdleConnsPerHost.
const DefaultMaxIdleConnsPerHost = 2
// This time does not include the time to send the request header.
ExpectContinueTimeout time.Duration
+ // TLSNextProto specifies how the Transport switches to an
+ // alternate protocol (such as HTTP/2) after a TLS NPN/ALPN
+ // protocol negotiation. If Transport dials an TLS connection
+ // with a non-empty protocol name and TLSNextProto contains a
+ // map entry for that key (such as "h2"), then the func is
+ // called with the request's authority (such as "example.com"
+ // or "example.com:1234") and the TLS connection. The function
+ // must return a RoundTripper that then handles the request.
+ TLSNextProto map[string]func(authority string, c *tls.Conn) RoundTripper
+
// TODO: tunable on global max cached connections
// TODO: tunable on timeout on cached connections
}
//
// For higher-level HTTP client support (such as handling of cookies
// and redirects), see Get, Post, and the Client type.
-func (t *Transport) RoundTrip(req *Request) (resp *Response, err error) {
+func (t *Transport) RoundTrip(req *Request) (*Response, error) {
if req.URL == nil {
req.closeBody()
return nil, errors.New("http: nil Request.URL")
req.closeBody()
return nil, errors.New("http: nil Request.Header")
}
- if req.URL.Scheme != "http" && req.URL.Scheme != "https" {
- t.altMu.RLock()
- var rt RoundTripper
- if t.altProto != nil {
- rt = t.altProto[req.URL.Scheme]
- }
- t.altMu.RUnlock()
- if rt == nil {
- req.closeBody()
- return nil, &badStringError{"unsupported protocol scheme", req.URL.Scheme}
+ // TODO(bradfitz): switch to atomic.Value for this map instead of RWMutex
+ t.altMu.RLock()
+ altRT := t.altProto[req.URL.Scheme]
+ t.altMu.RUnlock()
+ if altRT != nil {
+ if resp, err := altRT.RoundTrip(req); err != ErrSkipAltProtocol {
+ return resp, err
}
- return rt.RoundTrip(req)
+ }
+ if s := req.URL.Scheme; s != "http" && s != "https" {
+ req.closeBody()
+ return nil, &badStringError{"unsupported protocol scheme", s}
+ }
+ if !validMethod(req.Method) {
+ return nil, fmt.Errorf("net/http: invalid method %q", req.Method)
}
if req.URL.Host == "" {
req.closeBody()
req.closeBody()
return nil, err
}
-
+ if pconn.alt != nil {
+ // HTTP/2 path.
+ return pconn.alt.RoundTrip(req)
+ }
return pconn.roundTrip(treq)
}
+// ErrSkipAltProtocol is a sentinel error value defined by Transport.RegisterProtocol.
+var ErrSkipAltProtocol = errors.New("net/http: skip alternate protocol")
+
// RegisterProtocol registers a new protocol with scheme.
// The Transport will pass requests using the given scheme to rt.
// It is rt's responsibility to simulate HTTP request semantics.
//
// RegisterProtocol can be used by other packages to provide
// implementations of protocol schemes like "ftp" or "file".
+//
+// If rt.RoundTrip returns ErrSkipAltProtocol, the Transport will
+// handle the RoundTrip itself for that one request, as if the
+// protocol were not registered.
func (t *Transport) RegisterProtocol(scheme string, rt RoundTripper) {
- if scheme == "http" || scheme == "https" {
- panic("protocol " + scheme + " already registered")
- }
t.altMu.Lock()
defer t.altMu.Unlock()
if t.altProto == nil {
pconn.conn = tlsConn
}
+ if s := pconn.tlsState; s != nil && s.NegotiatedProtocolIsMutual && s.NegotiatedProtocol != "" {
+ if next, ok := t.TLSNextProto[s.NegotiatedProtocol]; ok {
+ return &persistConn{alt: next(cm.targetAddr, pconn.conn.(*tls.Conn))}, nil
+ }
+ }
+
pconn.br = bufio.NewReader(noteEOFReader{pconn.conn, &pconn.sawEOF})
pconn.bw = bufio.NewWriter(pconn.conn)
go pconn.readLoop()
// persistConn wraps a connection, usually a persistent one
// (but may be used for non-keep-alive requests as well)
type persistConn struct {
+ // alt optionally specifies the TLS NextProto RoundTripper.
+ // This is used for HTTP/2 today and future protocol laters.
+ // If it's non-nil, the rest of the fields are unused.
+ alt RoundTripper
+
t *Transport
cacheKey connectMethodKey
conn net.Conn
if !pc.closed {
pc.closeLocked()
if len(pb) > 0 {
- log.Printf("Unsolicited response received on idle HTTP channel starting with %q; err=%v",
- string(pb), err)
+ buf, _ := pc.br.Peek(pc.br.Buffered())
+ log.Printf("Unsolicited response received on idle HTTP channel starting with %q; err=%v", buf, err)
}
}
pc.lk.Unlock()
defer afterTest(t)
tr := &Transport{}
_, err := tr.RoundTrip(&Request{
+ Method: "GET",
Header: make(Header),
URL: &url.URL{
Scheme: "http",
return nil, os.NewSyscallError("wsaioctl", err)
}
iilen := ret / uint32(unsafe.Sizeof(iia[0]))
- return iia[:iilen-1], nil
+ return iia[:iilen], nil
}
func bytesEqualIP(a []byte, b []int8) bool {
if host, port, err = SplitHostPort(addr); err != nil {
return nil, err
}
- if portnum, err = parsePort(net, port); err != nil {
+ if portnum, err = LookupPort(net, port); err != nil {
return nil, err
}
}
// LookupPort looks up the port for the given network and service.
func LookupPort(network, service string) (port int, err error) {
- if n, i, ok := dtoi(service, 0); ok && i == len(service) {
- return n, nil
+ port, _, ok := dtoi(service, 0)
+ if !ok && port != big && port != -big {
+ port, err = lookupPort(network, service)
+ if err != nil {
+ return 0, err
+ }
}
- return lookupPort(network, service)
+ if 0 > port || port > 65535 {
+ return 0, &AddrError{Err: "invalid port", Addr: service}
+ }
+ return port, nil
}
// LookupCNAME returns the canonical DNS host for the given name.
}
}
}
+
+// nacl was previous failing to reuse an address.
+func TestListenCloseListen(t *testing.T) {
+ const maxTries = 10
+ for tries := 0; tries < maxTries; tries++ {
+ ln, err := newLocalListener("tcp")
+ if err != nil {
+ t.Fatal(err)
+ }
+ addr := ln.Addr().String()
+ if err := ln.Close(); err != nil {
+ t.Fatal(err)
+ }
+ ln, err = Listen("tcp", addr)
+ if err == nil {
+ // Success. nacl couldn't do this before.
+ ln.Close()
+ return
+ }
+ t.Errorf("failed on try %d/%d: %v", tries+1, maxTries, err)
+ }
+ t.Fatal("failed to listen/close/listen on same address after %d tries", maxTries)
+}
import (
"bufio"
+ "bytes"
"fmt"
"io"
+ "io/ioutil"
"os"
"os/exec"
+ "sort"
+ "strings"
"syscall"
"testing"
"time"
t.Fatalf(`"%s" received from recv, but "abc" expected`, s)
}
}
+
+func isWindowsXP(t *testing.T) bool {
+ v, err := syscall.GetVersion()
+ if err != nil {
+ t.Fatalf("GetVersion failed: %v", err)
+ }
+ major := byte(v)
+ return major < 6
+}
+
+func listInterfacesWithNetsh() ([]string, error) {
+ removeUTF8BOM := func(b []byte) []byte {
+ if len(b) >= 3 && b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF {
+ return b[3:]
+ }
+ return b
+ }
+ f, err := ioutil.TempFile("", "netsh")
+ if err != nil {
+ return nil, err
+ }
+ f.Close()
+ defer os.Remove(f.Name())
+ cmd := fmt.Sprintf(`netsh interface ip show config | Out-File "%s" -encoding UTF8`, f.Name())
+ out, err := exec.Command("powershell", "-Command", cmd).CombinedOutput()
+ if err != nil {
+ if len(out) != 0 {
+ return nil, fmt.Errorf("netsh failed: %v: %q", err, string(removeUTF8BOM(out)))
+ }
+ var err2 error
+ out, err2 = ioutil.ReadFile(f.Name())
+ if err2 != nil {
+ return nil, err2
+ }
+ if len(out) != 0 {
+ return nil, fmt.Errorf("netsh failed: %v: %q", err, string(removeUTF8BOM(out)))
+ }
+ return nil, fmt.Errorf("netsh failed: %v", err)
+ }
+ out, err = ioutil.ReadFile(f.Name())
+ if err != nil {
+ return nil, err
+ }
+ out = removeUTF8BOM(out)
+ lines := bytes.Split(out, []byte{'\r', '\n'})
+ names := make([]string, 0)
+ for _, line := range lines {
+ f := bytes.Split(line, []byte{'"'})
+ if len(f) == 3 {
+ names = append(names, string(f[1]))
+ }
+ }
+ return names, nil
+}
+
+func TestInterfaceList(t *testing.T) {
+ if isWindowsXP(t) {
+ t.Skip("Windows XP netsh command does not provide required functionality")
+ }
+ ift, err := Interfaces()
+ if err != nil {
+ t.Fatal(err)
+ }
+ have := make([]string, 0)
+ for _, ifi := range ift {
+ have = append(have, ifi.Name)
+ }
+ sort.Strings(have)
+
+ want, err := listInterfacesWithNetsh()
+ if err != nil {
+ t.Fatal(err)
+ }
+ sort.Strings(want)
+
+ if strings.Join(want, "/") != strings.Join(have, "/") {
+ t.Fatalf("unexpected interface list %q, want %q", have, want)
+ }
+}
// Returns number, new offset, success.
func dtoi(s string, i0 int) (n int, i int, ok bool) {
n = 0
+ neg := false
+ if len(s) > 0 && s[0] == '-' {
+ neg = true
+ s = s[1:]
+ }
for i = i0; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
n = n*10 + int(s[i]-'0')
if n >= big {
- return 0, i, false
+ if neg {
+ return -big, i + 1, false
+ }
+ return big, i, false
}
}
if i == i0 {
return 0, i, false
}
+ if neg {
+ n = -n
+ i++
+ }
return n, i, true
}
}
}
}
+
+func TestDtoi(t *testing.T) {
+ for _, tt := range []struct {
+ in string
+ out int
+ off int
+ ok bool
+ }{
+ {"", 0, 0, false},
+
+ {"-123456789", -big, 9, false},
+ {"-1", -1, 2, true},
+ {"0", 0, 1, true},
+ {"65536", 65536, 5, true},
+ {"123456789", big, 8, false},
+ } {
+ n, i, ok := dtoi(tt.in, 0)
+ if n != tt.out || i != tt.off || ok != tt.ok {
+ t.Errorf("got %d, %d, %v; want %d, %d, %v", n, i, ok, tt.out, tt.off, tt.ok)
+ }
+ }
+}
+++ /dev/null
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Network service port manipulations
-
-package net
-
-// parsePort parses port as a network service port number for both
-// TCP and UDP.
-func parsePort(net, port string) (int, error) {
- p, i, ok := dtoi(port, 0)
- if !ok || i != len(port) {
- var err error
- p, err = LookupPort(net, port)
- if err != nil {
- return 0, err
- }
- }
- if p < 0 || p > 0xFFFF {
- return 0, &AddrError{Err: "invalid port", Addr: port}
- }
- return p, nil
-}
"testing"
)
-var portTests = []struct {
+var lookupPortTests = []struct {
network string
name string
port int
ok bool
}{
+ {"tcp", "0", 0, true},
{"tcp", "echo", 7, true},
{"tcp", "discard", 9, true},
{"tcp", "systat", 11, true},
{"tcp", "finger", 79, true},
{"tcp", "42", 42, true},
+ {"udp", "0", 0, true},
{"udp", "echo", 7, true},
{"udp", "tftp", 69, true},
{"udp", "bootpc", 68, true},
{"--badnet--", "zzz", 0, false},
{"tcp", "--badport--", 0, false},
+ {"tcp", "-1", 0, false},
+ {"tcp", "65536", 0, false},
+ {"udp", "-1", 0, false},
+ {"udp", "65536", 0, false},
}
func TestLookupPort(t *testing.T) {
t.Skipf("not supported on %s", runtime.GOOS)
}
- for _, tt := range portTests {
+ for _, tt := range lookupPortTests {
if port, err := LookupPort(tt.network, tt.name); port != tt.port || (err == nil) != tt.ok {
- t.Errorf("LookupPort(%q, %q) = %v, %v; want %v", tt.network, tt.name, port, err, tt.port)
+ t.Errorf("LookupPort(%q, %q) = %d, %v; want %d", tt.network, tt.name, port, err, tt.port)
}
}
}
panic("ERROR")
}
+type hidden int
+
+func (t *hidden) Exported(args Args, reply *Reply) error {
+ reply.C = args.A + args.B
+ return nil
+}
+
+type Embed struct {
+ hidden
+}
+
func listenTCP() (net.Listener, string) {
l, e := net.Listen("tcp", "127.0.0.1:0") // any available address
if e != nil {
func startServer() {
Register(new(Arith))
+ Register(new(Embed))
RegisterName("net.rpc.Arith", new(Arith))
var l net.Listener
func startNewServer() {
newServer = NewServer()
newServer.Register(new(Arith))
+ newServer.Register(new(Embed))
newServer.RegisterName("net.rpc.Arith", new(Arith))
newServer.RegisterName("newServer.Arith", new(Arith))
t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B)
}
+ // Methods exported from unexported embedded structs
+ args = &Args{7, 0}
+ reply = new(Reply)
+ err = client.Call("Embed.Exported", args, reply)
+ if err != nil {
+ t.Errorf("Add: expected no error but got string %q", err.Error())
+ }
+ if reply.C != args.A+args.B {
+ t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B)
+ }
+
// Nonexistent method
args = &Args{7, 0}
reply = new(Reply)
// Go 1.5 introduced the RawPath field to hold the encoded form of Path.
// The Parse function sets both Path and RawPath in the URL it returns,
// and URL's String method uses RawPath if it is a valid encoding of Path,
-// by calling the EncodedPath method.
+// by calling the EscapedPath method.
//
// In earlier versions of Go, the more indirect workarounds were that an
// HTTP server could consult req.RequestURI and an HTTP client could
goto Error
}
// RawPath is a hint as to the encoding of Path to use
- // in url.EncodedPath. If that method already gets the
+ // in url.EscapedPath. If that method already gets the
// right answer without RawPath, leave it empty.
// This will help make sure that people don't rely on it in general.
if url.EscapedPath() != rest && validEncodedPath(rest) {
//
// If u.Opaque is non-empty, String uses the first form;
// otherwise it uses the second form.
-// To obtain the path, String uses u.EncodedPath().
+// To obtain the path, String uses u.EscapedPath().
//
// In the second form, the following rules apply:
// - if u.Scheme is empty, scheme: is omitted.
// Portable analogs of some common system call errors.
var (
- ErrInvalid = errors.New("invalid argument")
+ ErrInvalid = errors.New("invalid argument") // methods on File will return this error when the receiver is nil
ErrPermission = errors.New("permission denied")
ErrExist = errors.New("file already exists")
ErrNotExist = errors.New("file does not exist")
// An ExitError reports an unsuccessful exit by a command.
type ExitError struct {
*os.ProcessState
+
+ // Stderr holds a subset of the standard error output from the
+ // Cmd.Output method if standard error was not otherwise being
+ // collected.
+ //
+ // If the error output is long, Stderr may contain only a prefix
+ // and suffix of the output, with the middle replaced with
+ // text about the number of omitted bytes.
+ //
+ // Stderr is provided for debugging, for inclusion in error messages.
+ // Users with other needs should redirect Cmd.Stderr as needed.
+ Stderr []byte
}
func (e *ExitError) Error() string {
if err != nil {
return err
} else if !state.Success() {
- return &ExitError{state}
+ return &ExitError{ProcessState: state}
}
return copyError
}
// Output runs the command and returns its standard output.
+// Any returned error will usually be of type *ExitError.
+// If c.Stderr was nil, Output populates ExitError.Stderr.
func (c *Cmd) Output() ([]byte, error) {
if c.Stdout != nil {
return nil, errors.New("exec: Stdout already set")
}
- var b bytes.Buffer
- c.Stdout = &b
+ var stdout bytes.Buffer
+ c.Stdout = &stdout
+
+ captureErr := c.Stderr == nil
+ if captureErr {
+ c.Stderr = &prefixSuffixSaver{N: 32 << 10}
+ }
+
err := c.Run()
- return b.Bytes(), err
+ if err != nil && captureErr {
+ if ee, ok := err.(*ExitError); ok {
+ ee.Stderr = c.Stderr.(*prefixSuffixSaver).Bytes()
+ }
+ }
+ return stdout.Bytes(), err
}
// CombinedOutput runs the command and returns its combined standard
c.closeAfterWait = append(c.closeAfterWait, pr)
return pr, nil
}
+
+// prefixSuffixSaver is an io.Writer which retains the first N bytes
+// and the last N bytes written to it. The Bytes() methods reconstructs
+// it with a pretty error message.
+type prefixSuffixSaver struct {
+ N int // max size of prefix or suffix
+ prefix []byte
+ suffix []byte // ring buffer once len(suffix) == N
+ suffixOff int // offset to write into suffix
+ skipped int64
+
+ // TODO(bradfitz): we could keep one large []byte and use part of it for
+ // the prefix, reserve space for the '... Omitting N bytes ...' message,
+ // then the ring buffer suffix, and just rearrange the ring buffer
+ // suffix when Bytes() is called, but it doesn't seem worth it for
+ // now just for error messages. It's only ~64KB anyway.
+}
+
+func (w *prefixSuffixSaver) Write(p []byte) (n int, err error) {
+ lenp := len(p)
+ p = w.fill(&w.prefix, p)
+
+ // Only keep the last w.N bytes of suffix data.
+ if overage := len(p) - w.N; overage > 0 {
+ p = p[overage:]
+ w.skipped += int64(overage)
+ }
+ p = w.fill(&w.suffix, p)
+
+ // w.suffix is full now if p is non-empty. Overwrite it in a circle.
+ for len(p) > 0 { // 0, 1, or 2 iterations.
+ n := copy(w.suffix[w.suffixOff:], p)
+ p = p[n:]
+ w.skipped += int64(n)
+ w.suffixOff += n
+ if w.suffixOff == w.N {
+ w.suffixOff = 0
+ }
+ }
+ return lenp, nil
+}
+
+// fill appends up to len(p) bytes of p to *dst, such that *dst does not
+// grow larger than w.N. It returns the un-appended suffix of p.
+func (w *prefixSuffixSaver) fill(dst *[]byte, p []byte) (pRemain []byte) {
+ if remain := w.N - len(*dst); remain > 0 {
+ add := minInt(len(p), remain)
+ *dst = append(*dst, p[:add]...)
+ p = p[add:]
+ }
+ return p
+}
+
+func (w *prefixSuffixSaver) Bytes() []byte {
+ if w.suffix == nil {
+ return w.prefix
+ }
+ if w.skipped == 0 {
+ return append(w.prefix, w.suffix...)
+ }
+ var buf bytes.Buffer
+ buf.Grow(len(w.prefix) + len(w.suffix) + 50)
+ buf.Write(w.prefix)
+ buf.WriteString("\n... omitting ")
+ buf.WriteString(strconv.FormatInt(w.skipped, 10))
+ buf.WriteString(" bytes ...\n")
+ buf.Write(w.suffix[w.suffixOff:])
+ buf.Write(w.suffix[:w.suffixOff])
+ return buf.Bytes()
+}
+
+func minInt(a, b int) int {
+ if a < b {
+ return a
+ }
+ return b
+}
}
fmt.Print(p)
os.Exit(0)
+ case "stderrfail":
+ fmt.Fprintf(os.Stderr, "some stderr text\n")
+ os.Exit(1)
default:
fmt.Fprintf(os.Stderr, "Unknown command %q\n", cmd)
os.Exit(2)
t.Fatalf("yes got stuck writing to bad writer")
}
}
+
+func TestOutputStderrCapture(t *testing.T) {
+ testenv.MustHaveExec(t)
+
+ cmd := helperCommand(t, "stderrfail")
+ _, err := cmd.Output()
+ ee, ok := err.(*exec.ExitError)
+ if !ok {
+ t.Fatalf("Output error type = %T; want ExitError", err)
+ }
+ got := string(ee.Stderr)
+ want := "some stderr text\n"
+ if got != want {
+ t.Errorf("ExitError.Stderr = %q; want %q", got, want)
+ }
+}
--- /dev/null
+// Copyright 2015 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 exec
+
+import (
+ "io"
+ "testing"
+)
+
+func TestPrefixSuffixSaver(t *testing.T) {
+ tests := []struct {
+ N int
+ writes []string
+ want string
+ }{
+ {
+ N: 2,
+ writes: nil,
+ want: "",
+ },
+ {
+ N: 2,
+ writes: []string{"a"},
+ want: "a",
+ },
+ {
+ N: 2,
+ writes: []string{"abc", "d"},
+ want: "abcd",
+ },
+ {
+ N: 2,
+ writes: []string{"abc", "d", "e"},
+ want: "ab\n... omitting 1 bytes ...\nde",
+ },
+ {
+ N: 2,
+ writes: []string{"ab______________________yz"},
+ want: "ab\n... omitting 22 bytes ...\nyz",
+ },
+ {
+ N: 2,
+ writes: []string{"ab_______________________y", "z"},
+ want: "ab\n... omitting 23 bytes ...\nyz",
+ },
+ }
+ for i, tt := range tests {
+ w := &prefixSuffixSaver{N: tt.N}
+ for _, s := range tt.writes {
+ n, err := io.WriteString(w, s)
+ if err != nil || n != len(s) {
+ t.Errorf("%d. WriteString(%q) = %v, %v; want %v, %v", i, s, n, err, len(s), nil)
+ }
+ }
+ if got := string(w.Bytes()); got != tt.want {
+ t.Errorf("%d. Bytes = %q; want %q", i, got, tt.want)
+ }
+ }
+}
"syscall"
)
+func sameFile(fs1, fs2 *fileStat) bool {
+ return fs1.sys.Dev == fs2.sys.Dev && fs1.sys.Ino == fs2.sys.Ino
+}
+
func rename(oldname, newname string) error {
e := syscall.Rename(oldname, newname)
if e != nil {
if f == nil {
return nil, ErrInvalid
}
- var stat syscall.Stat_t
- err := syscall.Fstat(f.fd, &stat)
+ var fs fileStat
+ err := syscall.Fstat(f.fd, &fs.sys)
if err != nil {
return nil, &PathError{"stat", f.name, err}
}
- return fileInfoFromStat(&stat, f.name), nil
+ fillFileStatFromSys(&fs, f.name)
+ return &fs, nil
}
// Stat returns a FileInfo describing the named file.
// If there is an error, it will be of type *PathError.
func Stat(name string) (FileInfo, error) {
- var stat syscall.Stat_t
- err := syscall.Stat(name, &stat)
+ var fs fileStat
+ err := syscall.Stat(name, &fs.sys)
if err != nil {
return nil, &PathError{"stat", name, err}
}
- return fileInfoFromStat(&stat, name), nil
+ fillFileStatFromSys(&fs, name)
+ return &fs, nil
}
// Lstat returns a FileInfo describing the named file.
// describes the symbolic link. Lstat makes no attempt to follow the link.
// If there is an error, it will be of type *PathError.
func Lstat(name string) (FileInfo, error) {
- var stat syscall.Stat_t
- err := syscall.Lstat(name, &stat)
+ var fs fileStat
+ err := syscall.Lstat(name, &fs.sys)
if err != nil {
return nil, &PathError{"lstat", name, err}
}
- return fileInfoFromStat(&stat, name), nil
+ fillFileStatFromSys(&fs, name)
+ return &fs, nil
}
func (f *File) readdir(n int) (fi []FileInfo, err error) {
testReaddir(sysdir.name, sysdir.files, t)
}
+func benchmarkReaddirname(path string, b *testing.B) {
+ var nentries int
+ for i := 0; i < b.N; i++ {
+ f, err := Open(path)
+ if err != nil {
+ b.Fatalf("open %q failed: %v", path, err)
+ }
+ ns, err := f.Readdirnames(-1)
+ f.Close()
+ if err != nil {
+ b.Fatalf("readdirnames %q failed: %v", path, err)
+ }
+ nentries = len(ns)
+ }
+ b.Logf("benchmarkReaddirname %q: %d entries", path, nentries)
+}
+
+func benchmarkReaddir(path string, b *testing.B) {
+ var nentries int
+ for i := 0; i < b.N; i++ {
+ f, err := Open(path)
+ if err != nil {
+ b.Fatalf("open %q failed: %v", path, err)
+ }
+ fs, err := f.Readdir(-1)
+ f.Close()
+ if err != nil {
+ b.Fatalf("readdir %q failed: %v", path, err)
+ }
+ nentries = len(fs)
+ }
+ b.Logf("benchmarkReaddir %q: %d entries", path, nentries)
+}
+
+func BenchmarkReaddirname(b *testing.B) {
+ benchmarkReaddirname(".", b)
+}
+
+func BenchmarkReaddir(b *testing.B) {
+ benchmarkReaddir(".", b)
+}
+
// Read the directory one entry at a time.
func smallReaddirnames(file *File, length int, t *testing.T) []string {
names := make([]string, length)
func TestLongSymlink(t *testing.T) {
switch runtime.GOOS {
- case "plan9", "nacl":
+ case "android", "plan9", "nacl":
t.Skipf("skipping on %s", runtime.GOOS)
case "windows":
if !supportsSymlinks {
func TestMkdirAllWithSymlink(t *testing.T) {
switch runtime.GOOS {
- case "nacl", "plan9":
+ case "android", "nacl", "plan9":
t.Skipf("skipping on %s", runtime.GOOS)
case "windows":
if !supportsSymlinks {
// We must use a buffered channel or risk missing the signal
// if we're not ready to receive when the signal is sent.
c := make(chan os.Signal, 1)
- signal.Notify(c, os.Interrupt, os.Kill)
+ signal.Notify(c, os.Interrupt)
// Block until a signal is received.
s := <-c
"time"
)
-func sameFile(fs1, fs2 *fileStat) bool {
- stat1 := fs1.sys.(*syscall.Stat_t)
- stat2 := fs2.sys.(*syscall.Stat_t)
- return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino
-}
-
-func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
- fs := &fileStat{
- name: basename(name),
- size: int64(st.Size),
- modTime: timespecToTime(st.Mtimespec),
- sys: st,
- }
- fs.mode = FileMode(st.Mode & 0777)
- switch st.Mode & syscall.S_IFMT {
+func fillFileStatFromSys(fs *fileStat, name string) {
+ fs.name = basename(name)
+ fs.size = int64(fs.sys.Size)
+ fs.modTime = timespecToTime(fs.sys.Mtimespec)
+ fs.mode = FileMode(fs.sys.Mode & 0777)
+ switch fs.sys.Mode & syscall.S_IFMT {
case syscall.S_IFBLK, syscall.S_IFWHT:
fs.mode |= ModeDevice
case syscall.S_IFCHR:
case syscall.S_IFSOCK:
fs.mode |= ModeSocket
}
- if st.Mode&syscall.S_ISGID != 0 {
+ if fs.sys.Mode&syscall.S_ISGID != 0 {
fs.mode |= ModeSetgid
}
- if st.Mode&syscall.S_ISUID != 0 {
+ if fs.sys.Mode&syscall.S_ISUID != 0 {
fs.mode |= ModeSetuid
}
- if st.Mode&syscall.S_ISVTX != 0 {
+ if fs.sys.Mode&syscall.S_ISVTX != 0 {
fs.mode |= ModeSticky
}
- return fs
}
func timespecToTime(ts syscall.Timespec) time.Time {
"time"
)
-func sameFile(fs1, fs2 *fileStat) bool {
- stat1 := fs1.sys.(*syscall.Stat_t)
- stat2 := fs2.sys.(*syscall.Stat_t)
- return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino
-}
-
-func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
- fs := &fileStat{
- name: basename(name),
- size: int64(st.Size),
- modTime: timespecToTime(st.Mtim),
- sys: st,
- }
- fs.mode = FileMode(st.Mode & 0777)
- switch st.Mode & syscall.S_IFMT {
+func fillFileStatFromSys(fs *fileStat, name string) {
+ fs.name = basename(name)
+ fs.size = int64(fs.sys.Size)
+ fs.modTime = timespecToTime(fs.sys.Mtim)
+ fs.mode = FileMode(fs.sys.Mode & 0777)
+ switch fs.sys.Mode & syscall.S_IFMT {
case syscall.S_IFBLK:
fs.mode |= ModeDevice
case syscall.S_IFCHR:
case syscall.S_IFSOCK:
fs.mode |= ModeSocket
}
- if st.Mode&syscall.S_ISGID != 0 {
+ if fs.sys.Mode&syscall.S_ISGID != 0 {
fs.mode |= ModeSetgid
}
- if st.Mode&syscall.S_ISUID != 0 {
+ if fs.sys.Mode&syscall.S_ISUID != 0 {
fs.mode |= ModeSetuid
}
- if st.Mode&syscall.S_ISVTX != 0 {
+ if fs.sys.Mode&syscall.S_ISVTX != 0 {
fs.mode |= ModeSticky
}
- return fs
}
func timespecToTime(ts syscall.Timespec) time.Time {
"time"
)
-func sameFile(fs1, fs2 *fileStat) bool {
- stat1 := fs1.sys.(*syscall.Stat_t)
- stat2 := fs2.sys.(*syscall.Stat_t)
- return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino
-}
-
-func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
- fs := &fileStat{
- name: basename(name),
- size: int64(st.Size),
- modTime: timespecToTime(st.Mtimespec),
- sys: st,
- }
- fs.mode = FileMode(st.Mode & 0777)
- switch st.Mode & syscall.S_IFMT {
+func fillFileStatFromSys(fs *fileStat, name string) {
+ fs.name = basename(name)
+ fs.size = int64(fs.sys.Size)
+ fs.modTime = timespecToTime(fs.sys.Mtimespec)
+ fs.mode = FileMode(fs.sys.Mode & 0777)
+ switch fs.sys.Mode & syscall.S_IFMT {
case syscall.S_IFBLK:
fs.mode |= ModeDevice
case syscall.S_IFCHR:
case syscall.S_IFSOCK:
fs.mode |= ModeSocket
}
- if st.Mode&syscall.S_ISGID != 0 {
+ if fs.sys.Mode&syscall.S_ISGID != 0 {
fs.mode |= ModeSetgid
}
- if st.Mode&syscall.S_ISUID != 0 {
+ if fs.sys.Mode&syscall.S_ISUID != 0 {
fs.mode |= ModeSetuid
}
- if st.Mode&syscall.S_ISVTX != 0 {
+ if fs.sys.Mode&syscall.S_ISVTX != 0 {
fs.mode |= ModeSticky
}
- return fs
}
func timespecToTime(ts syscall.Timespec) time.Time {
"time"
)
-func sameFile(fs1, fs2 *fileStat) bool {
- stat1 := fs1.sys.(*syscall.Stat_t)
- stat2 := fs2.sys.(*syscall.Stat_t)
- return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino
-}
-
-func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
- fs := &fileStat{
- name: basename(name),
- size: int64(st.Size),
- modTime: timespecToTime(st.Mtim),
- sys: st,
- }
- fs.mode = FileMode(st.Mode & 0777)
- switch st.Mode & syscall.S_IFMT {
+func fillFileStatFromSys(fs *fileStat, name string) {
+ fs.name = basename(name)
+ fs.size = int64(fs.sys.Size)
+ fs.modTime = timespecToTime(fs.sys.Mtim)
+ fs.mode = FileMode(fs.sys.Mode & 0777)
+ switch fs.sys.Mode & syscall.S_IFMT {
case syscall.S_IFBLK:
fs.mode |= ModeDevice
case syscall.S_IFCHR:
case syscall.S_IFSOCK:
fs.mode |= ModeSocket
}
- if st.Mode&syscall.S_ISGID != 0 {
+ if fs.sys.Mode&syscall.S_ISGID != 0 {
fs.mode |= ModeSetgid
}
- if st.Mode&syscall.S_ISUID != 0 {
+ if fs.sys.Mode&syscall.S_ISUID != 0 {
fs.mode |= ModeSetuid
}
- if st.Mode&syscall.S_ISVTX != 0 {
+ if fs.sys.Mode&syscall.S_ISVTX != 0 {
fs.mode |= ModeSticky
}
- return fs
}
func timespecToTime(ts syscall.Timespec) time.Time {
"time"
)
-func sameFile(fs1, fs2 *fileStat) bool {
- stat1 := fs1.sys.(*syscall.Stat_t)
- stat2 := fs2.sys.(*syscall.Stat_t)
- return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino
-}
-
-func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
- fs := &fileStat{
- name: basename(name),
- size: int64(st.Size),
- modTime: timespecToTime(st.Mtime, st.MtimeNsec),
- sys: st,
- }
- fs.mode = FileMode(st.Mode & 0777)
- switch st.Mode & syscall.S_IFMT {
+func fillFileStatFromSys(fs *fileStat, name string) {
+ fs.name = basename(name)
+ fs.size = int64(fs.sys.Size)
+ fs.modTime = timespecToTime(fs.sys.Mtime, fs.sys.MtimeNsec)
+ fs.mode = FileMode(fs.sys.Mode & 0777)
+ switch fs.sys.Mode & syscall.S_IFMT {
case syscall.S_IFBLK:
fs.mode |= ModeDevice
case syscall.S_IFCHR:
case syscall.S_IFSOCK:
fs.mode |= ModeSocket
}
- if st.Mode&syscall.S_ISGID != 0 {
+ if fs.sys.Mode&syscall.S_ISGID != 0 {
fs.mode |= ModeSetgid
}
- if st.Mode&syscall.S_ISUID != 0 {
+ if fs.sys.Mode&syscall.S_ISUID != 0 {
fs.mode |= ModeSetuid
}
- if st.Mode&syscall.S_ISVTX != 0 {
+ if fs.sys.Mode&syscall.S_ISVTX != 0 {
fs.mode |= ModeSticky
}
- return fs
}
func timespecToTime(sec, nsec int64) time.Time {
"time"
)
-func sameFile(fs1, fs2 *fileStat) bool {
- stat1 := fs1.sys.(*syscall.Stat_t)
- stat2 := fs2.sys.(*syscall.Stat_t)
- return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino
-}
-
-func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
- fs := &fileStat{
- name: basename(name),
- size: int64(st.Size),
- modTime: timespecToTime(st.Mtimespec),
- sys: st,
- }
- fs.mode = FileMode(st.Mode & 0777)
- switch st.Mode & syscall.S_IFMT {
+func fillFileStatFromSys(fs *fileStat, name string) {
+ fs.name = basename(name)
+ fs.size = int64(fs.sys.Size)
+ fs.modTime = timespecToTime(fs.sys.Mtimespec)
+ fs.mode = FileMode(fs.sys.Mode & 0777)
+ switch fs.sys.Mode & syscall.S_IFMT {
case syscall.S_IFBLK:
fs.mode |= ModeDevice
case syscall.S_IFCHR:
case syscall.S_IFSOCK:
fs.mode |= ModeSocket
}
- if st.Mode&syscall.S_ISGID != 0 {
+ if fs.sys.Mode&syscall.S_ISGID != 0 {
fs.mode |= ModeSetgid
}
- if st.Mode&syscall.S_ISUID != 0 {
+ if fs.sys.Mode&syscall.S_ISUID != 0 {
fs.mode |= ModeSetuid
}
- if st.Mode&syscall.S_ISVTX != 0 {
+ if fs.sys.Mode&syscall.S_ISVTX != 0 {
fs.mode |= ModeSticky
}
- return fs
}
func timespecToTime(ts syscall.Timespec) time.Time {
"time"
)
-func sameFile(fs1, fs2 *fileStat) bool {
- stat1 := fs1.sys.(*syscall.Stat_t)
- stat2 := fs2.sys.(*syscall.Stat_t)
- return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino
-}
-
-func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
- fs := &fileStat{
- name: basename(name),
- size: int64(st.Size),
- modTime: timespecToTime(st.Mtim),
- sys: st,
- }
- fs.mode = FileMode(st.Mode & 0777)
- switch st.Mode & syscall.S_IFMT {
+func fillFileStatFromSys(fs *fileStat, name string) {
+ fs.name = basename(name)
+ fs.size = int64(fs.sys.Size)
+ fs.modTime = timespecToTime(fs.sys.Mtim)
+ fs.mode = FileMode(fs.sys.Mode & 0777)
+ switch fs.sys.Mode & syscall.S_IFMT {
case syscall.S_IFBLK:
fs.mode |= ModeDevice
case syscall.S_IFCHR:
case syscall.S_IFSOCK:
fs.mode |= ModeSocket
}
- if st.Mode&syscall.S_ISGID != 0 {
+ if fs.sys.Mode&syscall.S_ISGID != 0 {
fs.mode |= ModeSetgid
}
- if st.Mode&syscall.S_ISUID != 0 {
+ if fs.sys.Mode&syscall.S_ISUID != 0 {
fs.mode |= ModeSetuid
}
- if st.Mode&syscall.S_ISVTX != 0 {
+ if fs.sys.Mode&syscall.S_ISVTX != 0 {
fs.mode |= ModeSticky
}
- return fs
}
func timespecToTime(ts syscall.Timespec) time.Time {
"time"
)
-func sameFile(fs1, fs2 *fileStat) bool {
- stat1 := fs1.sys.(*syscall.Stat_t)
- stat2 := fs2.sys.(*syscall.Stat_t)
- return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino
-}
-
-func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
- fs := &fileStat{
- name: basename(name),
- size: int64(st.Size),
- modTime: timespecToTime(st.Mtim),
- sys: st,
- }
- fs.mode = FileMode(st.Mode & 0777)
- switch st.Mode & syscall.S_IFMT {
+func fillFileStatFromSys(fs *fileStat, name string) {
+ fs.name = basename(name)
+ fs.size = int64(fs.sys.Size)
+ fs.modTime = timespecToTime(fs.sys.Mtim)
+ fs.mode = FileMode(fs.sys.Mode & 0777)
+ switch fs.sys.Mode & syscall.S_IFMT {
case syscall.S_IFBLK:
fs.mode |= ModeDevice
case syscall.S_IFCHR:
case syscall.S_IFSOCK:
fs.mode |= ModeSocket
}
- if st.Mode&syscall.S_ISGID != 0 {
+ if fs.sys.Mode&syscall.S_ISGID != 0 {
fs.mode |= ModeSetgid
}
- if st.Mode&syscall.S_ISUID != 0 {
+ if fs.sys.Mode&syscall.S_ISUID != 0 {
fs.mode |= ModeSetuid
}
- if st.Mode&syscall.S_ISVTX != 0 {
+ if fs.sys.Mode&syscall.S_ISVTX != 0 {
fs.mode |= ModeSticky
}
- return fs
}
func timespecToTime(ts syscall.Timespec) time.Time {
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build !windows
-
package os
-import (
- "time"
-)
+import "time"
// A fileStat is the implementation of FileInfo returned by Stat and Lstat.
type fileStat struct {
--- /dev/null
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !windows
+// +build !plan9
+
+package os
+
+import (
+ "syscall"
+ "time"
+)
+
+// A fileStat is the implementation of FileInfo returned by Stat and Lstat.
+type fileStat struct {
+ name string
+ size int64
+ mode FileMode
+ modTime time.Time
+ sys syscall.Stat_t
+}
+
+func (fs *fileStat) Size() int64 { return fs.size }
+func (fs *fileStat) Mode() FileMode { return fs.mode }
+func (fs *fileStat) ModTime() time.Time { return fs.modTime }
+func (fs *fileStat) Sys() interface{} { return &fs.sys }
func TestGlobSymlink(t *testing.T) {
switch runtime.GOOS {
- case "nacl", "plan9":
+ case "android", "nacl", "plan9":
t.Skipf("skipping on %s", runtime.GOOS)
case "windows":
if !supportsSymlinks {
// Can't use IsAbs - `\a` and `a` are both relative in Windows.
baseSlashed := len(base) > 0 && base[0] == Separator
targSlashed := len(targ) > 0 && targ[0] == Separator
- if baseSlashed != targSlashed || baseVol != targVol {
+ if baseSlashed != targSlashed || !sameWord(baseVol, targVol) {
return "", errors.New("Rel: can't make " + targ + " relative to " + base)
}
// Position base[b0:bi] and targ[t0:ti] at the first differing elements.
for ti < tl && targ[ti] != Separator {
ti++
}
- if targ[t0:ti] != base[b0:bi] {
+ if !sameWord(targ[t0:ti], base[b0:bi]) {
break
}
if bi < bl {
}
return ""
}
+
+func sameWord(a, b string) bool {
+ return a == b
+}
{"test/linkabs", "/"},
}
-var EvalSymlinksAbsWindowsTests = []EvalSymlinksTest{
- {`c:\`, `c:\`},
+// findEvalSymlinksTestDirsDest searches testDirs
+// for matching path and returns correspondent dest.
+func findEvalSymlinksTestDirsDest(t *testing.T, testDirs []EvalSymlinksTest, path string) string {
+ for _, d := range testDirs {
+ if d.path == path {
+ return d.dest
+ }
+ }
+ t.Fatalf("did not find %q in testDirs slice", path)
+ return ""
}
// simpleJoin builds a file name from the directory and path.
func TestEvalSymlinks(t *testing.T) {
switch runtime.GOOS {
- case "nacl", "plan9":
+ case "android", "nacl", "plan9":
t.Skipf("skipping on %s", runtime.GOOS)
}
+ if !supportsSymlinks {
+ t.Skip("skipping because symlinks are not supported")
+ }
tmpDir, err := ioutil.TempDir("", "evalsymlink")
if err != nil {
t.Fatal("eval symlink for tmp dir:", err)
}
+ tests := EvalSymlinksTests
+ testdirs := EvalSymlinksTestDirs
+ if runtime.GOOS == "windows" {
+ if len(tmpDir) < 3 {
+ t.Fatalf("tmpDir path %q is too short", tmpDir)
+ }
+ if tmpDir[1] != ':' {
+ t.Fatalf("tmpDir path %q must have drive letter in it", tmpDir)
+ }
+ newtest := EvalSymlinksTest{"test/linkabswin", tmpDir[:3]}
+ tests = append(tests, newtest)
+ testdirs = append(testdirs, newtest)
+ }
+
// Create the symlink farm using relative paths.
- for _, d := range EvalSymlinksTestDirs {
+ for _, d := range testdirs {
var err error
path := simpleJoin(tmpDir, d.path)
if d.dest == "" {
err = os.Mkdir(path, 0755)
} else {
- if supportsSymlinks {
- err = os.Symlink(d.dest, path)
- }
+ err = os.Symlink(d.dest, path)
}
if err != nil {
t.Fatal(err)
}
}
- var tests []EvalSymlinksTest
- if supportsSymlinks {
- tests = EvalSymlinksTests
- } else {
- for _, d := range EvalSymlinksTests {
- if d.path == d.dest {
- // will test only real files and directories
- tests = append(tests, d)
- // test "canonical" names
- d2 := EvalSymlinksTest{
- path: strings.ToUpper(d.path),
- dest: d.dest,
- }
- tests = append(tests, d2)
- }
- }
+ wd, err := os.Getwd()
+ if err != nil {
+ t.Fatal(err)
}
// Evaluate the symlink farm.
} else if filepath.Clean(p) != filepath.Clean(dest) {
t.Errorf("Clean(%q)=%q, want %q", path, p, dest)
}
+
+ // test EvalSymlinks(".")
+ func() {
+ defer func() {
+ err := os.Chdir(wd)
+ if err != nil {
+ t.Fatal(err)
+ }
+ }()
+
+ err := os.Chdir(path)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ p, err := filepath.EvalSymlinks(".")
+ if err != nil {
+ t.Errorf(`EvalSymlinks(".") in %q directory error: %v`, d.path, err)
+ return
+ }
+ if p == "." {
+ return
+ }
+ want := filepath.Clean(findEvalSymlinksTestDirsDest(t, testdirs, d.path))
+ if p == want {
+ return
+ }
+ t.Errorf(`EvalSymlinks(".") in %q directory returns %q, want "." or %q`, d.path, p, want)
+ }()
+
+ // test EvalSymlinks where parameter is relative path
+ func() {
+ defer func() {
+ err := os.Chdir(wd)
+ if err != nil {
+ t.Fatal(err)
+ }
+ }()
+
+ err := os.Chdir(tmpDir)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if p, err := filepath.EvalSymlinks(d.path); err != nil {
+ t.Errorf("EvalSymlinks(%q) error: %v", d.path, err)
+ } else if filepath.Clean(p) != filepath.Clean(d.dest) {
+ t.Errorf("Clean(%q)=%q, want %q", d.path, p, d.dest)
+ }
+ }()
}
}
{`C:a\b\c`, `C:a/b/d`, `..\d`},
{`C:\`, `D:\`, `err`},
{`C:`, `D:`, `err`},
+ {`C:\Projects`, `c:\projects\src`, `src`},
}
func TestRel(t *testing.T) {
}
return ""
}
+
+func sameWord(a, b string) bool {
+ return a == b
+}
func isUNC(path string) bool {
return volumeNameLen(path) > 2
}
+
+func sameWord(a, b string) bool {
+ return strings.EqualFold(a, b)
+}
"os/exec"
"path/filepath"
"reflect"
+ "strings"
"syscall"
"testing"
)
}
}
}
+
+// TestEvalSymlinksCanonicalNames verify that EvalSymlinks
+// returns "canonical" path names on windows.
+func TestEvalSymlinksCanonicalNames(t *testing.T) {
+ tmp, err := ioutil.TempDir("", "evalsymlinkcanonical")
+ if err != nil {
+ t.Fatal("creating temp dir:", err)
+ }
+ defer os.RemoveAll(tmp)
+
+ // ioutil.TempDir might return "non-canonical" name.
+ cTmpName, err := filepath.EvalSymlinks(tmp)
+ if err != nil {
+ t.Errorf("EvalSymlinks(%q) error: %v", tmp, err)
+ }
+
+ dirs := []string{
+ "test",
+ "test/dir",
+ "testing_long_dir",
+ "TEST2",
+ }
+
+ for _, d := range dirs {
+ dir := filepath.Join(cTmpName, d)
+ err := os.Mkdir(dir, 0755)
+ if err != nil {
+ t.Fatal(err)
+ }
+ cname, err := filepath.EvalSymlinks(dir)
+ if err != nil {
+ t.Errorf("EvalSymlinks(%q) error: %v", dir, err)
+ continue
+ }
+ if dir != cname {
+ t.Errorf("EvalSymlinks(%q) returns %q, but should return %q", dir, cname, dir)
+ continue
+ }
+ // test non-canonical names
+ test := strings.ToUpper(dir)
+ p, err := filepath.EvalSymlinks(test)
+ if err != nil {
+ t.Errorf("EvalSymlinks(%q) error: %v", test, err)
+ continue
+ }
+ if p != cname {
+ t.Errorf("EvalSymlinks(%q) returns %q, but should return %q", test, p, cname)
+ continue
+ }
+ // another test
+ test = strings.ToLower(dir)
+ p, err = filepath.EvalSymlinks(test)
+ if err != nil {
+ t.Errorf("EvalSymlinks(%q) error: %v", test, err)
+ continue
+ }
+ if p != cname {
+ t.Errorf("EvalSymlinks(%q) returns %q, but should return %q", test, p, cname)
+ continue
+ }
+ }
+}
package filepath
import (
- "bytes"
"errors"
"os"
+ "runtime"
)
-const utf8RuneSelf = 0x80
+// isRoot returns true if path is root of file system
+// (`/` on unix and `/`, `\`, `c:\` or `c:/` on windows).
+func isRoot(path string) bool {
+ if runtime.GOOS != "windows" {
+ return path == "/"
+ }
+ switch len(path) {
+ case 1:
+ return os.IsPathSeparator(path[0])
+ case 3:
+ return path[1] == ':' && os.IsPathSeparator(path[2])
+ }
+ return false
+}
-func walkSymlinks(path string) (string, error) {
- const maxIter = 255
- originalPath := path
- // consume path by taking each frontmost path element,
- // expanding it if it's a symlink, and appending it to b
- var b bytes.Buffer
- for n := 0; path != ""; n++ {
- if n > maxIter {
- return "", errors.New("EvalSymlinks: too many links in " + originalPath)
- }
+// isDriveLetter returns true if path is Windows drive letter (like "c:").
+func isDriveLetter(path string) bool {
+ if runtime.GOOS != "windows" {
+ return false
+ }
+ return len(path) == 2 && path[1] == ':'
+}
- // find next path component, p
- var i = -1
- for j, c := range path {
- if c < utf8RuneSelf && os.IsPathSeparator(uint8(c)) {
- i = j
- break
- }
- }
- var p string
- if i == -1 {
- p, path = path, ""
- } else {
- p, path = path[:i], path[i+1:]
- }
+func walkLink(path string, linksWalked *int) (newpath string, islink bool, err error) {
+ if *linksWalked > 255 {
+ return "", false, errors.New("EvalSymlinks: too many links")
+ }
+ fi, err := os.Lstat(path)
+ if err != nil {
+ return "", false, err
+ }
+ if fi.Mode()&os.ModeSymlink == 0 {
+ return path, false, nil
+ }
+ newpath, err = os.Readlink(path)
+ if err != nil {
+ return "", false, err
+ }
+ *linksWalked++
+ return newpath, true, nil
+}
- if p == "" {
- if b.Len() == 0 {
- // must be absolute path
- b.WriteRune(Separator)
+func walkLinks(path string, linksWalked *int) (string, error) {
+ switch dir, file := Split(path); {
+ case dir == "":
+ newpath, _, err := walkLink(file, linksWalked)
+ return newpath, err
+ case file == "":
+ if isDriveLetter(dir) {
+ // appending "." to avoid bug in Join (see issue 11551)
+ return dir + ".", nil
+ }
+ if os.IsPathSeparator(dir[len(dir)-1]) {
+ if isRoot(dir) {
+ return dir, nil
}
- continue
+ return walkLinks(dir[:len(dir)-1], linksWalked)
}
-
- fi, err := os.Lstat(b.String() + p)
+ newpath, _, err := walkLink(dir, linksWalked)
+ return newpath, err
+ default:
+ newdir, err := walkLinks(dir, linksWalked)
if err != nil {
return "", err
}
- if fi.Mode()&os.ModeSymlink == 0 {
- b.WriteString(p)
- if path != "" || (b.Len() == 2 && len(p) == 2 && p[1] == ':') {
- b.WriteRune(Separator)
- }
- continue
- }
-
- // it's a symlink, put it at the front of path
- dest, err := os.Readlink(b.String() + p)
+ newpath, islink, err := walkLink(Join(newdir, file), linksWalked)
if err != nil {
return "", err
}
- if IsAbs(dest) || os.IsPathSeparator(dest[0]) {
- b.Reset()
+ if !islink {
+ return newpath, nil
+ }
+ if IsAbs(newpath) || os.IsPathSeparator(newpath[0]) {
+ return newpath, nil
}
- path = dest + string(Separator) + path
+ return Join(newdir, newpath), nil
+
+ }
+}
+
+func walkSymlinks(path string) (string, error) {
+ if path == "" {
+ return path, nil
+ }
+ var linksWalked int // to protect against cycles
+ newpath, err := walkLinks(path, &linksWalked)
+ if err != nil {
+ return "", err
}
- return Clean(b.String()), nil
+ return Clean(newpath), nil
}
}
func evalSymlinks(path string) (string, error) {
- path, err := walkSymlinks(path)
+ newpath, err := walkSymlinks(path)
if err != nil {
return "", err
}
+ // discard the walk if path is "." and link destination is relative path (just like unix does)
+ if path != "." || IsAbs(newpath) {
+ path = newpath
+ }
p, err := toShort(path)
if err != nil {
type Private struct {
x int
y **int
+ Z int
}
func (p *Private) m() {
}
+type private struct {
+ Z int
+ z int
+ S string
+ A [1]Private
+ T []Private
+}
+
+func (p *private) P() {
+}
+
type Public struct {
X int
Y **int
+ private
}
func (p *Public) M() {
func TestUnexported(t *testing.T) {
var pub Public
+ pub.S = "S"
+ pub.T = pub.A[:]
v := ValueOf(&pub)
isValid(v.Elem().Field(0))
isValid(v.Elem().Field(1))
+ isValid(v.Elem().Field(2))
isValid(v.Elem().FieldByName("X"))
isValid(v.Elem().FieldByName("Y"))
+ isValid(v.Elem().FieldByName("Z"))
isValid(v.Type().Method(0).Func)
+ m, _ := v.Type().MethodByName("M")
+ isValid(m.Func)
+ m, _ = v.Type().MethodByName("P")
+ isValid(m.Func)
isNonNil(v.Elem().Field(0).Interface())
isNonNil(v.Elem().Field(1).Interface())
+ isNonNil(v.Elem().Field(2).Field(2).Index(0))
isNonNil(v.Elem().FieldByName("X").Interface())
isNonNil(v.Elem().FieldByName("Y").Interface())
+ isNonNil(v.Elem().FieldByName("Z").Interface())
+ isNonNil(v.Elem().FieldByName("S").Index(0).Interface())
isNonNil(v.Type().Method(0).Func.Interface())
+ m, _ = v.Type().MethodByName("P")
+ isNonNil(m.Func.Interface())
var priv Private
v = ValueOf(&priv)
shouldPanic(func() { v.Type().Method(0).Func.Interface() })
}
+func TestSetPanic(t *testing.T) {
+ ok := func(f func()) { f() }
+ bad := shouldPanic
+ clear := func(v Value) { v.Set(Zero(v.Type())) }
+
+ type t0 struct {
+ W int
+ }
+
+ type t1 struct {
+ Y int
+ t0
+ }
+
+ type T2 struct {
+ Z int
+ namedT0 t0
+ }
+
+ type T struct {
+ X int
+ t1
+ T2
+ NamedT1 t1
+ NamedT2 T2
+ namedT1 t1
+ namedT2 T2
+ }
+
+ // not addressable
+ v := ValueOf(T{})
+ bad(func() { clear(v.Field(0)) }) // .X
+ bad(func() { clear(v.Field(1)) }) // .t1
+ bad(func() { clear(v.Field(1).Field(0)) }) // .t1.Y
+ bad(func() { clear(v.Field(1).Field(1)) }) // .t1.t0
+ bad(func() { clear(v.Field(1).Field(1).Field(0)) }) // .t1.t0.W
+ bad(func() { clear(v.Field(2)) }) // .T2
+ bad(func() { clear(v.Field(2).Field(0)) }) // .T2.Z
+ bad(func() { clear(v.Field(2).Field(1)) }) // .T2.namedT0
+ bad(func() { clear(v.Field(2).Field(1).Field(0)) }) // .T2.namedT0.W
+ bad(func() { clear(v.Field(3)) }) // .NamedT1
+ bad(func() { clear(v.Field(3).Field(0)) }) // .NamedT1.Y
+ bad(func() { clear(v.Field(3).Field(1)) }) // .NamedT1.t0
+ bad(func() { clear(v.Field(3).Field(1).Field(0)) }) // .NamedT1.t0.W
+ bad(func() { clear(v.Field(4)) }) // .NamedT2
+ bad(func() { clear(v.Field(4).Field(0)) }) // .NamedT2.Z
+ bad(func() { clear(v.Field(4).Field(1)) }) // .NamedT2.namedT0
+ bad(func() { clear(v.Field(4).Field(1).Field(0)) }) // .NamedT2.namedT0.W
+ bad(func() { clear(v.Field(5)) }) // .namedT1
+ bad(func() { clear(v.Field(5).Field(0)) }) // .namedT1.Y
+ bad(func() { clear(v.Field(5).Field(1)) }) // .namedT1.t0
+ bad(func() { clear(v.Field(5).Field(1).Field(0)) }) // .namedT1.t0.W
+ bad(func() { clear(v.Field(6)) }) // .namedT2
+ bad(func() { clear(v.Field(6).Field(0)) }) // .namedT2.Z
+ bad(func() { clear(v.Field(6).Field(1)) }) // .namedT2.namedT0
+ bad(func() { clear(v.Field(6).Field(1).Field(0)) }) // .namedT2.namedT0.W
+
+ // addressable
+ v = ValueOf(&T{}).Elem()
+ ok(func() { clear(v.Field(0)) }) // .X
+ bad(func() { clear(v.Field(1)) }) // .t1
+ ok(func() { clear(v.Field(1).Field(0)) }) // .t1.Y
+ bad(func() { clear(v.Field(1).Field(1)) }) // .t1.t0
+ ok(func() { clear(v.Field(1).Field(1).Field(0)) }) // .t1.t0.W
+ ok(func() { clear(v.Field(2)) }) // .T2
+ ok(func() { clear(v.Field(2).Field(0)) }) // .T2.Z
+ bad(func() { clear(v.Field(2).Field(1)) }) // .T2.namedT0
+ bad(func() { clear(v.Field(2).Field(1).Field(0)) }) // .T2.namedT0.W
+ ok(func() { clear(v.Field(3)) }) // .NamedT1
+ ok(func() { clear(v.Field(3).Field(0)) }) // .NamedT1.Y
+ bad(func() { clear(v.Field(3).Field(1)) }) // .NamedT1.t0
+ ok(func() { clear(v.Field(3).Field(1).Field(0)) }) // .NamedT1.t0.W
+ ok(func() { clear(v.Field(4)) }) // .NamedT2
+ ok(func() { clear(v.Field(4).Field(0)) }) // .NamedT2.Z
+ bad(func() { clear(v.Field(4).Field(1)) }) // .NamedT2.namedT0
+ bad(func() { clear(v.Field(4).Field(1).Field(0)) }) // .NamedT2.namedT0.W
+ bad(func() { clear(v.Field(5)) }) // .namedT1
+ bad(func() { clear(v.Field(5).Field(0)) }) // .namedT1.Y
+ bad(func() { clear(v.Field(5).Field(1)) }) // .namedT1.t0
+ bad(func() { clear(v.Field(5).Field(1).Field(0)) }) // .namedT1.t0.W
+ bad(func() { clear(v.Field(6)) }) // .namedT2
+ bad(func() { clear(v.Field(6).Field(0)) }) // .namedT2.Z
+ bad(func() { clear(v.Field(6).Field(1)) }) // .namedT2.namedT0
+ bad(func() { clear(v.Field(6).Field(1).Field(0)) }) // .namedT2.namedT0.W
+}
+
+type timp int
+
+func (t timp) W() {}
+func (t timp) Y() {}
+func (t timp) w() {}
+func (t timp) y() {}
+
+func TestCallPanic(t *testing.T) {
+ type t0 interface {
+ W()
+ w()
+ }
+ type T1 interface {
+ Y()
+ y()
+ }
+ type T2 struct {
+ T1
+ t0
+ }
+ type T struct {
+ t0 // 0
+ T1 // 1
+
+ NamedT0 t0 // 2
+ NamedT1 T1 // 3
+ NamedT2 T2 // 4
+
+ namedT0 t0 // 5
+ namedT1 T1 // 6
+ namedT2 T2 // 7
+ }
+ ok := func(f func()) { f() }
+ bad := shouldPanic
+ call := func(v Value) { v.Call(nil) }
+
+ i := timp(0)
+ v := ValueOf(T{i, i, i, i, T2{i, i}, i, i, T2{i, i}})
+ ok(func() { call(v.Field(0).Method(0)) }) // .t0.W
+ ok(func() { call(v.Field(0).Elem().Method(0)) }) // .t0.W
+ bad(func() { call(v.Field(0).Method(1)) }) // .t0.w
+ bad(func() { call(v.Field(0).Elem().Method(2)) }) // .t0.w
+ ok(func() { call(v.Field(1).Method(0)) }) // .T1.Y
+ ok(func() { call(v.Field(1).Elem().Method(0)) }) // .T1.Y
+ bad(func() { call(v.Field(1).Method(1)) }) // .T1.y
+ bad(func() { call(v.Field(1).Elem().Method(2)) }) // .T1.y
+
+ ok(func() { call(v.Field(2).Method(0)) }) // .NamedT0.W
+ ok(func() { call(v.Field(2).Elem().Method(0)) }) // .NamedT0.W
+ bad(func() { call(v.Field(2).Method(1)) }) // .NamedT0.w
+ bad(func() { call(v.Field(2).Elem().Method(2)) }) // .NamedT0.w
+
+ ok(func() { call(v.Field(3).Method(0)) }) // .NamedT1.Y
+ ok(func() { call(v.Field(3).Elem().Method(0)) }) // .NamedT1.Y
+ bad(func() { call(v.Field(3).Method(1)) }) // .NamedT1.y
+ bad(func() { call(v.Field(3).Elem().Method(3)) }) // .NamedT1.y
+
+ ok(func() { call(v.Field(4).Field(0).Method(0)) }) // .NamedT2.T1.Y
+ ok(func() { call(v.Field(4).Field(0).Elem().Method(0)) }) // .NamedT2.T1.W
+ ok(func() { call(v.Field(4).Field(1).Method(0)) }) // .NamedT2.t0.W
+ ok(func() { call(v.Field(4).Field(1).Elem().Method(0)) }) // .NamedT2.t0.W
+
+ bad(func() { call(v.Field(5).Method(0)) }) // .namedT0.W
+ bad(func() { call(v.Field(5).Elem().Method(0)) }) // .namedT0.W
+ bad(func() { call(v.Field(5).Method(1)) }) // .namedT0.w
+ bad(func() { call(v.Field(5).Elem().Method(2)) }) // .namedT0.w
+
+ bad(func() { call(v.Field(6).Method(0)) }) // .namedT1.Y
+ bad(func() { call(v.Field(6).Elem().Method(0)) }) // .namedT1.Y
+ bad(func() { call(v.Field(6).Method(0)) }) // .namedT1.y
+ bad(func() { call(v.Field(6).Elem().Method(0)) }) // .namedT1.y
+
+ bad(func() { call(v.Field(7).Field(0).Method(0)) }) // .namedT2.T1.Y
+ bad(func() { call(v.Field(7).Field(0).Elem().Method(0)) }) // .namedT2.T1.W
+ bad(func() { call(v.Field(7).Field(1).Method(0)) }) // .namedT2.t0.W
+ bad(func() { call(v.Field(7).Field(1).Elem().Method(0)) }) // .namedT2.t0.W
+}
+
func shouldPanic(f func()) {
defer func() {
if recover() == nil {
--- /dev/null
+// Copyright 2015 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 mips64 mips64le
+
+#include "textflag.h"
+#include "funcdata.h"
+
+#define REGCTXT R22
+
+// makeFuncStub is the code half of the function returned by MakeFunc.
+// See the comment on the declaration of makeFuncStub in makefunc.go
+// for more details.
+// No arg size here, runtime pulls arg map out of the func value.
+TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
+ NO_LOCAL_POINTERS
+ MOVV REGCTXT, 8(R29)
+ MOVV $argframe+0(FP), R1
+ MOVV R1, 16(R29)
+ JAL ·callReflect(SB)
+ RET
+
+// methodValueCall is the code half of the function returned by makeMethodValue.
+// See the comment on the declaration of methodValueCall in makefunc.go
+// for more details.
+// No arg size here; runtime pulls arg map out of the func value.
+TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$16
+ NO_LOCAL_POINTERS
+ MOVV REGCTXT, 8(R29)
+ MOVV $argframe+0(FP), R1
+ MOVV R1, 16(R29)
+ JAL ·callMethod(SB)
+ RET
// MakeRO returns a copy of v with the read-only flag set.
func MakeRO(v Value) Value {
- v.flag |= flagRO
+ v.flag |= flagStickyRO
return v
}
// IsRO reports whether v's read-only flag is set.
func IsRO(v Value) bool {
- return v.flag&flagRO != 0
+ return v.flag&flagStickyRO != 0
}
var CallGC = &callGC
fl := flag(Func)
if p.pkgPath != nil {
m.PkgPath = *p.pkgPath
- fl |= flagRO
+ fl |= flagStickyRO
}
mt := p.typ
m.Type = mt
// A StructField describes a single field in a struct.
type StructField struct {
// Name is the field name.
+ Name string
// PkgPath is the package path that qualifies a lower case (unexported)
// field name. It is empty for upper case (exported) field names.
// See https://golang.org/ref/spec#Uniqueness_of_identifiers
- Name string
PkgPath string
Type Type // field type
// flag holds metadata about the value.
// The lowest bits are flag bits:
- // - flagRO: obtained via unexported field, so read-only
+ // - flagStickyRO: obtained via unexported not embedded field, so read-only
+ // - flagEmbedRO: obtained via unexported embedded field, so read-only
// - flagIndir: val holds a pointer to the data
// - flagAddr: v.CanAddr is true (implies flagIndir)
// - flagMethod: v is a method value.
const (
flagKindWidth = 5 // there are 27 kinds
flagKindMask flag = 1<<flagKindWidth - 1
- flagRO flag = 1 << 5
- flagIndir flag = 1 << 6
- flagAddr flag = 1 << 7
- flagMethod flag = 1 << 8
- flagMethodShift = 9
+ flagStickyRO flag = 1 << 5
+ flagEmbedRO flag = 1 << 6
+ flagIndir flag = 1 << 7
+ flagAddr flag = 1 << 8
+ flagMethod flag = 1 << 9
+ flagMethodShift = 10
+ flagRO flag = flagStickyRO | flagEmbedRO
)
func (f flag) kind() Kind {
field := &tt.fields[i]
typ := field.typ
- // Inherit permission bits from v.
- fl := v.flag&(flagRO|flagIndir|flagAddr) | flag(typ.Kind())
+ // Inherit permission bits from v, but clear flagEmbedRO.
+ fl := v.flag&(flagStickyRO|flagIndir|flagAddr) | flag(typ.Kind())
// Using an unexported field forces flagRO.
if field.pkgPath != nil {
- fl |= flagRO
+ if field.name == nil {
+ fl |= flagEmbedRO
+ } else {
+ fl |= flagStickyRO
+ }
}
// Either flagIndir is set and v.ptr points at struct,
// or flagIndir is not set and v.ptr is the actual struct data.
if v.typ.Kind() == Interface && v.IsNil() {
panic("reflect: Method on nil interface value")
}
- fl := v.flag & (flagRO | flagIndir)
+ fl := v.flag & (flagStickyRO | flagIndir) // Clear flagEmbedRO
fl |= flag(Func)
fl |= flag(i)<<flagMethodShift | flagMethod
return Value{v.typ, v.ptr, fl}
// Substitution when subexpression isn't found
{"(x)?", "$1", "123", "123"},
{"abc", "$1", "123", "123"},
+
+ // Substitutions involving a (x){0}
+ {"(a)(b){0}(c)", ".$1|$3.", "xacxacx", "x.a|c.x.a|c.x"},
+ {"(a)(((b))){0}c", ".$1.", "xacxacx", "x.a.x.a.x"},
+ {"((a(b){0}){3}){5}(h)", "y caramb$2", "say aaaaaaaaaaaaaaaah", "say ay caramba"},
+ {"((a(b){0}){3}){5}h", "y caramb$2", "say aaaaaaaaaaaaaaaah", "say ay caramba"},
}
var replaceLiteralTests = []ReplaceTest{
} else {
endPos = len(src)
}
+ if nmatch > re.prog.NumCap {
+ nmatch = re.prog.NumCap
+ }
+
for searchPos <= endPos {
a := re.doExecute(nil, bsrc, src, searchPos, nmatch)
if len(a) == 0 {
package runtime
-import "unsafe"
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
const (
- c0 = uintptr((8-ptrSize)/4*2860486313 + (ptrSize-4)/4*33054211828000289)
- c1 = uintptr((8-ptrSize)/4*3267000013 + (ptrSize-4)/4*23344194077549503)
+ c0 = uintptr((8-sys.PtrSize)/4*2860486313 + (sys.PtrSize-4)/4*33054211828000289)
+ c1 = uintptr((8-sys.PtrSize)/4*3267000013 + (sys.PtrSize-4)/4*23344194077549503)
)
// type algorithms - known to compiler
return *(*string)(p) == *(*string)(q)
}
func interequal(p, q unsafe.Pointer) bool {
- return ifaceeq(*(*interface {
- f()
- })(p), *(*interface {
- f()
- })(q))
+ return ifaceeq(*(*iface)(p), *(*iface)(q))
}
func nilinterequal(p, q unsafe.Pointer) bool {
- return efaceeq(*(*interface{})(p), *(*interface{})(q))
+ return efaceeq(*(*eface)(p), *(*eface)(q))
}
-func efaceeq(p, q interface{}) bool {
- x := (*eface)(unsafe.Pointer(&p))
- y := (*eface)(unsafe.Pointer(&q))
+func efaceeq(x, y eface) bool {
t := x._type
if t != y._type {
return false
}
return eq(x.data, y.data)
}
-func ifaceeq(p, q interface {
- f()
-}) bool {
- x := (*iface)(unsafe.Pointer(&p))
- y := (*iface)(unsafe.Pointer(&q))
+func ifaceeq(x, y iface) bool {
xtab := x.tab
if xtab != y.tab {
return false
memclr(s.array, uintptr(s.len))
}
-const hashRandomBytes = ptrSize / 4 * 64
+const hashRandomBytes = sys.PtrSize / 4 * 64
// used in asm_{386,amd64}.s to seed the hash function
var aeskeysched [hashRandomBytes]byte
getRandomData(aeskeysched[:])
return
}
- getRandomData((*[len(hashkey) * ptrSize]byte)(unsafe.Pointer(&hashkey))[:])
+ getRandomData((*[len(hashkey) * sys.PtrSize]byte)(unsafe.Pointer(&hashkey))[:])
hashkey[0] |= 1 // make sure these numbers are odd
hashkey[1] |= 1
hashkey[2] |= 1
+++ /dev/null
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package runtime
-
-const (
- thechar = '8'
- _BigEndian = 0
- _CacheLineSize = 64
- _PhysPageSize = goos_nacl*65536 + (1-goos_nacl)*4096 // 4k normally; 64k on NaCl
- _PCQuantum = 1
- _Int64Align = 4
- hugePageSize = 1 << 21
- minFrameSize = 0
-)
-
-type uintreg uint32
-type intptr int32 // TODO(rsc): remove
+++ /dev/null
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package runtime
-
-const (
- thechar = '6'
- _BigEndian = 0
- _CacheLineSize = 64
- _PhysPageSize = 4096
- _PCQuantum = 1
- _Int64Align = 8
- hugePageSize = 1 << 21
- minFrameSize = 0
-)
-
-type uintreg uint64
-type intptr int64 // TODO(rsc): remove
+++ /dev/null
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package runtime
-
-const (
- thechar = '6'
- _BigEndian = 0
- _CacheLineSize = 64
- _PhysPageSize = 65536*goos_nacl + 4096*(1-goos_nacl)
- _PCQuantum = 1
- _Int64Align = 8
- hugePageSize = 1 << 21
- minFrameSize = 0
-)
-
-type uintreg uint64
-type intptr int32 // TODO(rsc): remove
+++ /dev/null
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package runtime
-
-const (
- thechar = '5'
- _BigEndian = 0
- _CacheLineSize = 32
- _PhysPageSize = 65536*goos_nacl + 4096*(1-goos_nacl)
- _PCQuantum = 4
- _Int64Align = 4
- hugePageSize = 0
- minFrameSize = 4
-)
-
-type uintreg uint32
-type intptr int32 // TODO(rsc): remove
+++ /dev/null
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package runtime
-
-const (
- thechar = '7'
- _BigEndian = 0
- _CacheLineSize = 32
- _PhysPageSize = 65536
- _PCQuantum = 4
- _Int64Align = 8
- hugePageSize = 0
- minFrameSize = 8
-)
-
-type uintreg uint64
-type intptr int64 // TODO(rsc): remove
+++ /dev/null
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package runtime
-
-const (
- thechar = '9'
- _BigEndian = 1
- _CacheLineSize = 64
- _PhysPageSize = 65536
- _PCQuantum = 4
- _Int64Align = 8
- hugePageSize = 0
- minFrameSize = 8
-)
-
-type uintreg uint64
-type intptr int64 // TODO(rsc): remove
+++ /dev/null
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package runtime
-
-const (
- thechar = '9'
- _BigEndian = 0
- _CacheLineSize = 64
- _PhysPageSize = 65536
- _PCQuantum = 4
- _Int64Align = 8
- hugePageSize = 0
- minFrameSize = 8
-)
-
-type uintreg uint64
-type intptr int64 // TODO(rsc): remove
MOVL AX, g_stackguard0(CX)
MOVL AX, g_stackguard1(CX)
+#ifndef GOOS_windows
// skip runtime·ldt0setup(SB) and tls test after _cgo_init for non-windows
- CMPL runtime·iswindows(SB), $0
- JEQ ok
+ JMP ok
+#endif
needtls:
+#ifdef GOOS_plan9
// skip runtime·ldt0setup(SB) and tls test on Plan 9 in all cases
- CMPL runtime·isplan9(SB), $1
- JEQ ok
+ JMP ok
+#endif
// set up %gs
CALL runtime·ldt0setup(SB)
// store through it, to make sure it works
get_tls(BX)
MOVL $0x123, g(BX)
- MOVL runtime·tls0(SB), AX
+ MOVL runtime·m0+m_tls(SB), AX
CMPL AX, $0x123
JEQ ok
MOVL AX, 0 // abort
CALLFN(·call536870912, 536870912)
CALLFN(·call1073741824, 1073741824)
-// bool cas(int32 *val, int32 old, int32 new)
-// Atomically:
-// if(*val == old){
-// *val = new;
-// return 1;
-// }else
-// return 0;
-TEXT runtime·cas(SB), NOSPLIT, $0-13
- MOVL ptr+0(FP), BX
- MOVL old+4(FP), AX
- MOVL new+8(FP), CX
- LOCK
- CMPXCHGL CX, 0(BX)
- SETEQ ret+12(FP)
- RET
-
-TEXT runtime·casuintptr(SB), NOSPLIT, $0-13
- JMP runtime·cas(SB)
-
-TEXT runtime·atomicloaduintptr(SB), NOSPLIT, $0-8
- JMP runtime·atomicload(SB)
-
-TEXT runtime·atomicloaduint(SB), NOSPLIT, $0-8
- JMP runtime·atomicload(SB)
-
-TEXT runtime·atomicstoreuintptr(SB), NOSPLIT, $0-8
- JMP runtime·atomicstore(SB)
-
-// bool runtime·cas64(uint64 *val, uint64 old, uint64 new)
-// Atomically:
-// if(*val == *old){
-// *val = new;
-// return 1;
-// } else {
-// return 0;
-// }
-TEXT runtime·cas64(SB), NOSPLIT, $0-21
- MOVL ptr+0(FP), BP
- MOVL old_lo+4(FP), AX
- MOVL old_hi+8(FP), DX
- MOVL new_lo+12(FP), BX
- MOVL new_hi+16(FP), CX
- LOCK
- CMPXCHG8B 0(BP)
- SETEQ ret+20(FP)
- RET
-
-// bool casp(void **p, void *old, void *new)
-// Atomically:
-// if(*p == old){
-// *p = new;
-// return 1;
-// }else
-// return 0;
-TEXT runtime·casp1(SB), NOSPLIT, $0-13
- MOVL ptr+0(FP), BX
- MOVL old+4(FP), AX
- MOVL new+8(FP), CX
- LOCK
- CMPXCHGL CX, 0(BX)
- SETEQ ret+12(FP)
- RET
-
-// uint32 xadd(uint32 volatile *val, int32 delta)
-// Atomically:
-// *val += delta;
-// return *val;
-TEXT runtime·xadd(SB), NOSPLIT, $0-12
- MOVL ptr+0(FP), BX
- MOVL delta+4(FP), AX
- MOVL AX, CX
- LOCK
- XADDL AX, 0(BX)
- ADDL CX, AX
- MOVL AX, ret+8(FP)
- RET
-
-TEXT runtime·xchg(SB), NOSPLIT, $0-12
- MOVL ptr+0(FP), BX
- MOVL new+4(FP), AX
- XCHGL AX, 0(BX)
- MOVL AX, ret+8(FP)
- RET
-
-TEXT runtime·xchguintptr(SB), NOSPLIT, $0-12
- JMP runtime·xchg(SB)
-
TEXT runtime·procyield(SB),NOSPLIT,$0-0
MOVL cycles+0(FP), AX
again:
JNZ again
RET
-TEXT runtime·atomicstorep1(SB), NOSPLIT, $0-8
- MOVL ptr+0(FP), BX
- MOVL val+4(FP), AX
- XCHGL AX, 0(BX)
- RET
-
-TEXT runtime·atomicstore(SB), NOSPLIT, $0-8
- MOVL ptr+0(FP), BX
- MOVL val+4(FP), AX
- XCHGL AX, 0(BX)
- RET
-
-// uint64 atomicload64(uint64 volatile* addr);
-TEXT runtime·atomicload64(SB), NOSPLIT, $0-12
- MOVL ptr+0(FP), AX
- TESTL $7, AX
- JZ 2(PC)
- MOVL 0, AX // crash with nil ptr deref
- LEAL ret_lo+4(FP), BX
- // MOVQ (%EAX), %MM0
- BYTE $0x0f; BYTE $0x6f; BYTE $0x00
- // MOVQ %MM0, 0(%EBX)
- BYTE $0x0f; BYTE $0x7f; BYTE $0x03
- // EMMS
- BYTE $0x0F; BYTE $0x77
- RET
-
-// void runtime·atomicstore64(uint64 volatile* addr, uint64 v);
-TEXT runtime·atomicstore64(SB), NOSPLIT, $0-12
- MOVL ptr+0(FP), AX
- TESTL $7, AX
- JZ 2(PC)
- MOVL 0, AX // crash with nil ptr deref
- // MOVQ and EMMS were introduced on the Pentium MMX.
- // MOVQ 0x8(%ESP), %MM0
- BYTE $0x0f; BYTE $0x6f; BYTE $0x44; BYTE $0x24; BYTE $0x08
- // MOVQ %MM0, (%EAX)
- BYTE $0x0f; BYTE $0x7f; BYTE $0x00
- // EMMS
- BYTE $0x0F; BYTE $0x77
- // This is essentially a no-op, but it provides required memory fencing.
- // It can be replaced with MFENCE, but MFENCE was introduced only on the Pentium4 (SSE2).
- MOVL $0, AX
- LOCK
- XADDL AX, (SP)
- RET
-
-// void runtime·atomicor8(byte volatile*, byte);
-TEXT runtime·atomicor8(SB), NOSPLIT, $0-5
- MOVL ptr+0(FP), AX
- MOVB val+4(FP), BX
- LOCK
- ORB BX, (AX)
- RET
-
-// void runtime·atomicand8(byte volatile*, byte);
-TEXT runtime·atomicand8(SB), NOSPLIT, $0-5
- MOVL ptr+0(FP), AX
- MOVB val+4(FP), BX
- LOCK
- ANDB BX, (AX)
- RET
-
TEXT ·publicationBarrier(SB),NOSPLIT,$0-0
// Stores are already ordered on x86, so this is just a
// compile barrier.
RET
TEXT runtime·ldt0setup(SB),NOSPLIT,$16-0
- // set up ldt 7 to point at tls0
+ // set up ldt 7 to point at m0.tls
// ldt 1 would be fine on Linux, but on OS X, 7 is as low as we can go.
// the entry number is just a hint. setldt will set up GS with what it used.
MOVL $7, 0(SP)
- LEAL runtime·tls0(SB), AX
+ LEAL runtime·m0+m_tls(SB), AX
MOVL AX, 4(SP)
MOVL $32, 8(SP) // sizeof(tls array)
CALL runtime·setldt(SB)
// traceback from goexit1 must hit code range of goexit
BYTE $0x90 // NOP
+// Prefetching doesn't seem to help.
TEXT runtime·prefetcht0(SB),NOSPLIT,$0-4
- MOVL addr+0(FP), AX
- PREFETCHT0 (AX)
RET
TEXT runtime·prefetcht1(SB),NOSPLIT,$0-4
- MOVL addr+0(FP), AX
- PREFETCHT1 (AX)
RET
-
TEXT runtime·prefetcht2(SB),NOSPLIT,$0-4
- MOVL addr+0(FP), AX
- PREFETCHT2 (AX)
RET
TEXT runtime·prefetchnta(SB),NOSPLIT,$0-4
- MOVL addr+0(FP), AX
- PREFETCHNTA (AX)
RET
JNE notintel
MOVB $1, runtime·lfenceBeforeRdtsc(SB)
notintel:
+ // Do nothing.
MOVQ $1, AX
CPUID
MOVL CX, runtime·cpuid_ecx(SB)
MOVL DX, runtime·cpuid_edx(SB)
+ // Detect AVX and AVX2 as per 14.7.1 Detection of AVX2 chapter of [1]
+ // [1] 64-ia-32-architectures-software-developer-manual-325462.pdf
+ // http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-manual-325462.pdf
+ ANDL $0x18000000, CX // check for OSXSAVE and AVX bits
+ CMPL CX, $0x18000000
+ JNE noavx
+ MOVL $0, CX
+ // For XGETBV, OSXSAVE bit is required and sufficient
+ BYTE $0x0F; BYTE $0x01; BYTE $0xD0
+ ANDL $6, AX
+ CMPL AX, $6 // Check for OS support of YMM registers
+ JNE noavx
+ MOVB $1, runtime·support_avx(SB)
+ MOVL $7, AX
+ MOVL $0, CX
+ CPUID
+ ANDL $0x20, BX // check for AVX2 bit
+ CMPL BX, $0x20
+ JNE noavx2
+ MOVB $1, runtime·support_avx2(SB)
+ JMP nocpuinfo
+noavx:
+ MOVB $0, runtime·support_avx(SB)
+noavx2:
+ MOVB $0, runtime·support_avx2(SB)
nocpuinfo:
// if there is an _cgo_init, call it.
MOVQ AX, g_stackguard0(CX)
MOVQ AX, g_stackguard1(CX)
- CMPL runtime·iswindows(SB), $0
- JEQ ok
+#ifndef GOOS_windows
+ JMP ok
+#endif
needtls:
+#ifdef GOOS_plan9
// skip TLS setup on Plan 9
- CMPL runtime·isplan9(SB), $1
- JEQ ok
+ JMP ok
+#endif
+#ifdef GOOS_solaris
// skip TLS setup on Solaris
- CMPL runtime·issolaris(SB), $1
- JEQ ok
+ JMP ok
+#endif
- LEAQ runtime·tls0(SB), DI
+ LEAQ runtime·m0+m_tls(SB), DI
CALL runtime·settls(SB)
// store through it, to make sure it works
get_tls(BX)
MOVQ $0x123, g(BX)
- MOVQ runtime·tls0(SB), AX
+ MOVQ runtime·m0+m_tls(SB), AX
CMPQ AX, $0x123
JEQ 2(PC)
MOVL AX, 0 // abort
CALLFN(·call536870912, 536870912)
CALLFN(·call1073741824, 1073741824)
-// bool cas(int32 *val, int32 old, int32 new)
-// Atomically:
-// if(*val == old){
-// *val = new;
-// return 1;
-// } else
-// return 0;
-TEXT runtime·cas(SB), NOSPLIT, $0-17
- MOVQ ptr+0(FP), BX
- MOVL old+8(FP), AX
- MOVL new+12(FP), CX
- LOCK
- CMPXCHGL CX, 0(BX)
- SETEQ ret+16(FP)
- RET
-
-// bool runtime·cas64(uint64 *val, uint64 old, uint64 new)
-// Atomically:
-// if(*val == *old){
-// *val = new;
-// return 1;
-// } else {
-// return 0;
-// }
-TEXT runtime·cas64(SB), NOSPLIT, $0-25
- MOVQ ptr+0(FP), BX
- MOVQ old+8(FP), AX
- MOVQ new+16(FP), CX
- LOCK
- CMPXCHGQ CX, 0(BX)
- SETEQ ret+24(FP)
- RET
-
-TEXT runtime·casuintptr(SB), NOSPLIT, $0-25
- JMP runtime·cas64(SB)
-
-TEXT runtime·atomicloaduintptr(SB), NOSPLIT, $0-16
- JMP runtime·atomicload64(SB)
-
-TEXT runtime·atomicloaduint(SB), NOSPLIT, $0-16
- JMP runtime·atomicload64(SB)
-
-TEXT runtime·atomicstoreuintptr(SB), NOSPLIT, $0-16
- JMP runtime·atomicstore64(SB)
-
-// bool casp(void **val, void *old, void *new)
-// Atomically:
-// if(*val == old){
-// *val = new;
-// return 1;
-// } else
-// return 0;
-TEXT runtime·casp1(SB), NOSPLIT, $0-25
- MOVQ ptr+0(FP), BX
- MOVQ old+8(FP), AX
- MOVQ new+16(FP), CX
- LOCK
- CMPXCHGQ CX, 0(BX)
- SETEQ ret+24(FP)
- RET
-
-// uint32 xadd(uint32 volatile *val, int32 delta)
-// Atomically:
-// *val += delta;
-// return *val;
-TEXT runtime·xadd(SB), NOSPLIT, $0-20
- MOVQ ptr+0(FP), BX
- MOVL delta+8(FP), AX
- MOVL AX, CX
- LOCK
- XADDL AX, 0(BX)
- ADDL CX, AX
- MOVL AX, ret+16(FP)
- RET
-
-TEXT runtime·xadd64(SB), NOSPLIT, $0-24
- MOVQ ptr+0(FP), BX
- MOVQ delta+8(FP), AX
- MOVQ AX, CX
- LOCK
- XADDQ AX, 0(BX)
- ADDQ CX, AX
- MOVQ AX, ret+16(FP)
- RET
-
-TEXT runtime·xadduintptr(SB), NOSPLIT, $0-24
- JMP runtime·xadd64(SB)
-
-TEXT runtime·xchg(SB), NOSPLIT, $0-20
- MOVQ ptr+0(FP), BX
- MOVL new+8(FP), AX
- XCHGL AX, 0(BX)
- MOVL AX, ret+16(FP)
- RET
-
-TEXT runtime·xchg64(SB), NOSPLIT, $0-24
- MOVQ ptr+0(FP), BX
- MOVQ new+8(FP), AX
- XCHGQ AX, 0(BX)
- MOVQ AX, ret+16(FP)
- RET
-
-TEXT runtime·xchguintptr(SB), NOSPLIT, $0-24
- JMP runtime·xchg64(SB)
-
TEXT runtime·procyield(SB),NOSPLIT,$0-0
MOVL cycles+0(FP), AX
again:
JNZ again
RET
-TEXT runtime·atomicstorep1(SB), NOSPLIT, $0-16
- MOVQ ptr+0(FP), BX
- MOVQ val+8(FP), AX
- XCHGQ AX, 0(BX)
- RET
-
-TEXT runtime·atomicstore(SB), NOSPLIT, $0-12
- MOVQ ptr+0(FP), BX
- MOVL val+8(FP), AX
- XCHGL AX, 0(BX)
- RET
-
-TEXT runtime·atomicstore64(SB), NOSPLIT, $0-16
- MOVQ ptr+0(FP), BX
- MOVQ val+8(FP), AX
- XCHGQ AX, 0(BX)
- RET
-
-// void runtime·atomicor8(byte volatile*, byte);
-TEXT runtime·atomicor8(SB), NOSPLIT, $0-9
- MOVQ ptr+0(FP), AX
- MOVB val+8(FP), BX
- LOCK
- ORB BX, (AX)
- RET
-
-// void runtime·atomicand8(byte volatile*, byte);
-TEXT runtime·atomicand8(SB), NOSPLIT, $0-9
- MOVQ ptr+0(FP), AX
- MOVB val+8(FP), BX
- LOCK
- ANDB BX, (AX)
- RET
TEXT ·publicationBarrier(SB),NOSPLIT,$0-0
// Stores are already ordered on x86, so this is just a
TEXT runtime·memeqbody(SB),NOSPLIT,$0-0
CMPQ BX, $8
JB small
+ CMPQ BX, $64
+ JB bigloop
+ CMPB runtime·support_avx2(SB), $1
+ JE hugeloop_avx2
// 64 bytes at a time using xmm registers
hugeloop:
MOVB $0, (AX)
RET
+ // 64 bytes at a time using ymm registers
+hugeloop_avx2:
+ CMPQ BX, $64
+ JB bigloop_avx2
+ MOVHDU (SI), X0
+ MOVHDU (DI), X1
+ MOVHDU 32(SI), X2
+ MOVHDU 32(DI), X3
+ VPCMPEQB X1, X0, X4
+ VPCMPEQB X2, X3, X5
+ VPAND X4, X5, X6
+ VPMOVMSKB X6, DX
+ ADDQ $64, SI
+ ADDQ $64, DI
+ SUBQ $64, BX
+ CMPL DX, $0xffffffff
+ JEQ hugeloop_avx2
+ VZEROUPPER
+ MOVB $0, (AX)
+ RET
+
+bigloop_avx2:
+ VZEROUPPER
+
// 8 bytes at a time using 64-bit register
bigloop:
CMPQ BX, $8
JB small
CMPQ R8, $63
- JA big_loop
+ JBE loop
+ CMPB runtime·support_avx2(SB), $1
+ JEQ big_loop_avx2
+ JMP big_loop
loop:
CMPQ R8, $16
JBE _0through16
JBE loop
JMP big_loop
+ // Compare 64-bytes per loop iteration.
+ // Loop is unrolled and uses AVX2.
+big_loop_avx2:
+ MOVHDU (SI), X2
+ MOVHDU (DI), X3
+ MOVHDU 32(SI), X4
+ MOVHDU 32(DI), X5
+ VPCMPEQB X2, X3, X0
+ VPMOVMSKB X0, AX
+ XORL $0xffffffff, AX
+ JNE diff32_avx2
+ VPCMPEQB X4, X5, X6
+ VPMOVMSKB X6, AX
+ XORL $0xffffffff, AX
+ JNE diff64_avx2
+
+ ADDQ $64, SI
+ ADDQ $64, DI
+ SUBQ $64, R8
+ CMPQ R8, $64
+ JB big_loop_avx2_exit
+ JMP big_loop_avx2
+
+ // Avoid AVX->SSE transition penalty and search first 32 bytes of 64 byte chunk.
+diff32_avx2:
+ VZEROUPPER
+ JMP diff16
+
+ // Same as diff32_avx2, but for last 32 bytes.
+diff64_avx2:
+ VZEROUPPER
+ JMP diff48
+
+ // For <64 bytes remainder jump to normal loop.
+big_loop_avx2_exit:
+ VZEROUPPER
+ JMP loop
+
+
+// TODO: Also use this in bytes.Index
+TEXT strings·indexShortStr(SB),NOSPLIT,$0-40
+ MOVQ s+0(FP), DI
+ MOVQ s_len+8(FP), CX
+ MOVQ c+16(FP), AX
+ MOVQ c_len+24(FP), BX
+ CMPQ BX, CX
+ JA fail
+ CMPQ BX, $2
+ JA _3_or_more
+ MOVW (AX), AX
+ LEAQ -1(DI)(CX*1), CX
+loop2:
+ MOVW (DI), SI
+ CMPW SI,AX
+ JZ success
+ ADDQ $1,DI
+ CMPQ DI,CX
+ JB loop2
+ JMP fail
+_3_or_more:
+ CMPQ BX, $3
+ JA _4_or_more
+ MOVW 1(AX), DX
+ MOVW (AX), AX
+ LEAQ -2(DI)(CX*1), CX
+loop3:
+ MOVW (DI), SI
+ CMPW SI,AX
+ JZ partial_success3
+ ADDQ $1,DI
+ CMPQ DI,CX
+ JB loop3
+ JMP fail
+partial_success3:
+ MOVW 1(DI), SI
+ CMPW SI,DX
+ JZ success
+ ADDQ $1,DI
+ CMPQ DI,CX
+ JB loop3
+ JMP fail
+_4_or_more:
+ CMPQ BX, $4
+ JA _5_or_more
+ MOVL (AX), AX
+ LEAQ -3(DI)(CX*1), CX
+loop4:
+ MOVL (DI), SI
+ CMPL SI,AX
+ JZ success
+ ADDQ $1,DI
+ CMPQ DI,CX
+ JB loop4
+ JMP fail
+_5_or_more:
+ CMPQ BX, $7
+ JA _8_or_more
+ LEAQ 1(DI)(CX*1), CX
+ SUBQ BX, CX
+ MOVL -4(AX)(BX*1), DX
+ MOVL (AX), AX
+loop5to7:
+ MOVL (DI), SI
+ CMPL SI,AX
+ JZ partial_success5to7
+ ADDQ $1,DI
+ CMPQ DI,CX
+ JB loop5to7
+ JMP fail
+partial_success5to7:
+ MOVL -4(BX)(DI*1), SI
+ CMPL SI,DX
+ JZ success
+ ADDQ $1,DI
+ CMPQ DI,CX
+ JB loop5to7
+ JMP fail
+_8_or_more:
+ CMPQ BX, $8
+ JA _9_or_more
+ MOVQ (AX), AX
+ LEAQ -7(DI)(CX*1), CX
+loop8:
+ MOVQ (DI), SI
+ CMPQ SI,AX
+ JZ success
+ ADDQ $1,DI
+ CMPQ DI,CX
+ JB loop8
+ JMP fail
+_9_or_more:
+ CMPQ BX, $16
+ JA _16_or_more
+ LEAQ 1(DI)(CX*1), CX
+ SUBQ BX, CX
+ MOVQ -8(AX)(BX*1), DX
+ MOVQ (AX), AX
+loop9to15:
+ MOVQ (DI), SI
+ CMPQ SI,AX
+ JZ partial_success9to15
+ ADDQ $1,DI
+ CMPQ DI,CX
+ JB loop9to15
+ JMP fail
+partial_success9to15:
+ MOVQ -8(BX)(DI*1), SI
+ CMPQ SI,DX
+ JZ success
+ ADDQ $1,DI
+ CMPQ DI,CX
+ JB loop9to15
+ JMP fail
+_16_or_more:
+ CMPQ BX, $16
+ JA _17_to_31
+ MOVOU (AX), X1
+ LEAQ -15(DI)(CX*1), CX
+loop16:
+ MOVOU (DI), X2
+ PCMPEQB X1, X2
+ PMOVMSKB X2, SI
+ CMPQ SI, $0xffff
+ JE success
+ ADDQ $1,DI
+ CMPQ DI,CX
+ JB loop16
+ JMP fail
+_17_to_31:
+ LEAQ 1(DI)(CX*1), CX
+ SUBQ BX, CX
+ MOVOU -16(AX)(BX*1), X0
+ MOVOU (AX), X1
+loop17to31:
+ MOVOU (DI), X2
+ PCMPEQB X1,X2
+ PMOVMSKB X2, SI
+ CMPQ SI, $0xffff
+ JE partial_success17to31
+ ADDQ $1,DI
+ CMPQ DI,CX
+ JB loop17to31
+ JMP fail
+partial_success17to31:
+ MOVOU -16(BX)(DI*1), X3
+ PCMPEQB X0, X3
+ PMOVMSKB X3, SI
+ CMPQ SI, $0xffff
+ JE success
+ ADDQ $1,DI
+ CMPQ DI,CX
+ JB loop17to31
+fail:
+ MOVQ $-1, ret+32(FP)
+ RET
+success:
+ SUBQ s+0(FP), DI
+ MOVQ DI, ret+32(FP)
+ RET
+
+
TEXT bytes·IndexByte(SB),NOSPLIT,$0-40
MOVQ s+0(FP), SI
MOVQ s_len+8(FP), BX
CMPQ BX, $16
JLT small
+ CMPQ BX, $32
+ JA avx2
+no_avx2:
// round up to first 16-byte boundary
TESTQ $15, SI
JZ aligned
MOVQ $-1, (R8)
RET
+avx2:
+ CMPB runtime·support_avx2(SB), $1
+ JNE no_avx2
+ MOVD AX, X0
+ LEAQ -32(SI)(BX*1), R11
+ VPBROADCASTB X0, X1
+avx2_loop:
+ MOVHDU (DI), X2
+ VPCMPEQB X1, X2, X3
+ VPTEST X3, X3
+ JNZ avx2success
+ ADDQ $32, DI
+ CMPQ DI, R11
+ JLT avx2_loop
+ MOVQ R11, DI
+ MOVHDU (DI), X2
+ VPCMPEQB X1, X2, X3
+ VPTEST X3, X3
+ JNZ avx2success
+ VZEROUPPER
+ MOVQ $-1, (R8)
+ RET
+
+avx2success:
+ VPMOVMSKB X3, DX
+ BSFL DX, DX
+ SUBQ SI, DI
+ ADDQ DI, DX
+ MOVQ DX, (R8)
+ VZEROUPPER
+ RET
+
// we've found the chunk containing the byte
// now just figure out which specific byte it is
ssesuccess:
nocpuinfo:
needtls:
- LEAL runtime·tls0(SB), DI
+ LEAL runtime·m0+m_tls(SB), DI
CALL runtime·settls(SB)
// store through it, to make sure it works
get_tls(BX)
MOVQ $0x123, g(BX)
- MOVQ runtime·tls0(SB), AX
+ MOVQ runtime·m0+m_tls(SB), AX
CMPQ AX, $0x123
JEQ 2(PC)
MOVL AX, 0 // abort
CALLFN(·call536870912, 536870912)
CALLFN(·call1073741824, 1073741824)
-// bool cas(int32 *val, int32 old, int32 new)
-// Atomically:
-// if(*val == old){
-// *val = new;
-// return 1;
-// } else
-// return 0;
-TEXT runtime·cas(SB), NOSPLIT, $0-17
- MOVL ptr+0(FP), BX
- MOVL old+4(FP), AX
- MOVL new+8(FP), CX
- LOCK
- CMPXCHGL CX, 0(BX)
- SETEQ ret+16(FP)
- RET
-
-TEXT runtime·casuintptr(SB), NOSPLIT, $0-17
- JMP runtime·cas(SB)
-
-TEXT runtime·atomicloaduintptr(SB), NOSPLIT, $0-12
- JMP runtime·atomicload(SB)
-
-TEXT runtime·atomicloaduint(SB), NOSPLIT, $0-12
- JMP runtime·atomicload(SB)
-
-TEXT runtime·atomicstoreuintptr(SB), NOSPLIT, $0-12
- JMP runtime·atomicstore(SB)
-
-// bool runtime·cas64(uint64 *val, uint64 old, uint64 new)
-// Atomically:
-// if(*val == *old){
-// *val = new;
-// return 1;
-// } else {
-// return 0;
-// }
-TEXT runtime·cas64(SB), NOSPLIT, $0-25
- MOVL ptr+0(FP), BX
- MOVQ old+8(FP), AX
- MOVQ new+16(FP), CX
- LOCK
- CMPXCHGQ CX, 0(BX)
- SETEQ ret+24(FP)
- RET
-
-// bool casp(void **val, void *old, void *new)
-// Atomically:
-// if(*val == old){
-// *val = new;
-// return 1;
-// } else
-// return 0;
-TEXT runtime·casp1(SB), NOSPLIT, $0-17
- MOVL ptr+0(FP), BX
- MOVL old+4(FP), AX
- MOVL new+8(FP), CX
- LOCK
- CMPXCHGL CX, 0(BX)
- SETEQ ret+16(FP)
- RET
-
-// uint32 xadd(uint32 volatile *val, int32 delta)
-// Atomically:
-// *val += delta;
-// return *val;
-TEXT runtime·xadd(SB), NOSPLIT, $0-12
- MOVL ptr+0(FP), BX
- MOVL delta+4(FP), AX
- MOVL AX, CX
- LOCK
- XADDL AX, 0(BX)
- ADDL CX, AX
- MOVL AX, ret+8(FP)
- RET
-
-TEXT runtime·xadd64(SB), NOSPLIT, $0-24
- MOVL ptr+0(FP), BX
- MOVQ delta+8(FP), AX
- MOVQ AX, CX
- LOCK
- XADDQ AX, 0(BX)
- ADDQ CX, AX
- MOVQ AX, ret+16(FP)
- RET
-
-TEXT runtime·xadduintptr(SB), NOSPLIT, $0-12
- JMP runtime·xadd(SB)
-
-TEXT runtime·xchg(SB), NOSPLIT, $0-12
- MOVL ptr+0(FP), BX
- MOVL new+4(FP), AX
- XCHGL AX, 0(BX)
- MOVL AX, ret+8(FP)
- RET
-
-TEXT runtime·xchg64(SB), NOSPLIT, $0-24
- MOVL ptr+0(FP), BX
- MOVQ new+8(FP), AX
- XCHGQ AX, 0(BX)
- MOVQ AX, ret+16(FP)
- RET
-
-TEXT runtime·xchguintptr(SB), NOSPLIT, $0-12
- JMP runtime·xchg(SB)
-
TEXT runtime·procyield(SB),NOSPLIT,$0-0
MOVL cycles+0(FP), AX
again:
JNZ again
RET
-TEXT runtime·atomicstorep1(SB), NOSPLIT, $0-8
- MOVL ptr+0(FP), BX
- MOVL val+4(FP), AX
- XCHGL AX, 0(BX)
- RET
-
-TEXT runtime·atomicstore(SB), NOSPLIT, $0-8
- MOVL ptr+0(FP), BX
- MOVL val+4(FP), AX
- XCHGL AX, 0(BX)
- RET
-
-TEXT runtime·atomicstore64(SB), NOSPLIT, $0-16
- MOVL ptr+0(FP), BX
- MOVQ val+8(FP), AX
- XCHGQ AX, 0(BX)
- RET
-
-// void runtime·atomicor8(byte volatile*, byte);
-TEXT runtime·atomicor8(SB), NOSPLIT, $0-5
- MOVL ptr+0(FP), BX
- MOVB val+4(FP), AX
- LOCK
- ORB AX, 0(BX)
- RET
-
-// void runtime·atomicand8(byte volatile*, byte);
-TEXT runtime·atomicand8(SB), NOSPLIT, $0-5
- MOVL ptr+0(FP), BX
- MOVB val+4(FP), AX
- LOCK
- ANDB AX, 0(BX)
- RET
-
TEXT ·publicationBarrier(SB),NOSPLIT,$0-0
// Stores are already ordered on x86, so this is just a
// compile barrier.
MOVQ BX, CX
REP
STOSB
+ // Note: we zero only 4 bytes at a time so that the tail is at most
+ // 3 bytes. That guarantees that we aren't zeroing pointers with STOSB.
+ // See issue 13160.
RET
TEXT runtime·getcallerpc(SB),NOSPLIT,$8-12
MOVW R8, g_m(g)
// create istack out of the OS stack
- MOVW $(-8192+104)(R13), R0
+ // (1MB of system stack is available on iOS and Android)
+ MOVW $(-64*1024+104)(R13), R0
MOVW R0, g_stackguard0(g)
MOVW R0, g_stackguard1(g)
MOVW R0, (g_stack+stack_lo)(g)
MOVW $0, R0
MOVW (R0), R1
-// bool armcas(int32 *val, int32 old, int32 new)
-// Atomically:
-// if(*val == old){
-// *val = new;
-// return 1;
-// }else
-// return 0;
-//
-// To implement runtime·cas in sys_$GOOS_arm.s
-// using the native instructions, use:
-//
-// TEXT runtime·cas(SB),NOSPLIT,$0
-// B runtime·armcas(SB)
-//
-TEXT runtime·armcas(SB),NOSPLIT,$0-13
- MOVW valptr+0(FP), R1
- MOVW old+4(FP), R2
- MOVW new+8(FP), R3
-casl:
- LDREX (R1), R0
- CMP R0, R2
- BNE casfail
-
- MOVB runtime·goarm(SB), R11
- CMP $7, R11
- BLT 2(PC)
- WORD $0xf57ff05a // dmb ishst
-
- STREX R3, (R1), R0
- CMP $0, R0
- BNE casl
- MOVW $1, R0
-
- MOVB runtime·goarm(SB), R11
- CMP $7, R11
- BLT 2(PC)
- WORD $0xf57ff05b // dmb ish
-
- MOVB R0, ret+12(FP)
- RET
-casfail:
- MOVW $0, R0
- MOVB R0, ret+12(FP)
- RET
-
-TEXT runtime·casuintptr(SB),NOSPLIT,$0-13
- B runtime·cas(SB)
-
-TEXT runtime·atomicloaduintptr(SB),NOSPLIT,$0-8
- B runtime·atomicload(SB)
-
-TEXT runtime·atomicloaduint(SB),NOSPLIT,$0-8
- B runtime·atomicload(SB)
-
-TEXT runtime·atomicstoreuintptr(SB),NOSPLIT,$0-8
- B runtime·atomicstore(SB)
-
// armPublicationBarrier is a native store/store barrier for ARMv7+.
// On earlier ARM revisions, armPublicationBarrier is a no-op.
// This will not work on SMP ARMv6 machines, if any are in use.
TEXT runtime·sigreturn(SB),NOSPLIT,$0-4
RET
+
+#ifndef GOOS_nacl
+// This is called from .init_array and follows the platform, not Go, ABI.
+TEXT runtime·addmoduledata(SB),NOSPLIT,$0-4
+ MOVW R9, saver9-4(SP) // The access to global variables below implicitly uses R9, which is callee-save
+ MOVW runtime·lastmoduledatap(SB), R1
+ MOVW R0, moduledata_next(R1)
+ MOVW R0, runtime·lastmoduledatap(SB)
+ MOVW saver9-4(SP), R9
+ RET
+#endif
#ifdef TLSG_IS_VARIABLE
MOVD $runtime·tls_g(SB), R2 // arg 2: &tls_g
#else
- MOVD 0, R2 // arg 2: not used when using platform's TLS
+ MOVD $0, R2 // arg 2: not used when using platform's TLS
#endif
MOVD $setg_gcc<>(SB), R1 // arg 1: setg
MOVD g, R0 // arg 0: G
CALLFN(·call536870912, 536870920 )
CALLFN(·call1073741824, 1073741832 )
-// bool cas(uint32 *ptr, uint32 old, uint32 new)
-// Atomically:
-// if(*val == old){
-// *val = new;
-// return 1;
-// } else
-// return 0;
-TEXT runtime·cas(SB), NOSPLIT, $0-17
- MOVD ptr+0(FP), R0
- MOVW old+8(FP), R1
- MOVW new+12(FP), R2
-again:
- LDAXRW (R0), R3
- CMPW R1, R3
- BNE ok
- STLXRW R2, (R0), R3
- CBNZ R3, again
-ok:
- CSET EQ, R0
- MOVB R0, ret+16(FP)
- RET
-
-TEXT runtime·casuintptr(SB), NOSPLIT, $0-25
- B runtime·cas64(SB)
-
-TEXT runtime·atomicloaduintptr(SB), NOSPLIT, $-8-16
- B runtime·atomicload64(SB)
-
-TEXT runtime·atomicloaduint(SB), NOSPLIT, $-8-16
- B runtime·atomicload64(SB)
-
-TEXT runtime·atomicstoreuintptr(SB), NOSPLIT, $0-16
- B runtime·atomicstore64(SB)
-
// AES hashing not implemented for ARM64, issue #10109.
TEXT runtime·aeshash(SB),NOSPLIT,$-8-0
MOVW $0, R0
TEXT runtime·aeshashstr(SB),NOSPLIT,$-8-0
MOVW $0, R0
MOVW (R0), R1
-
-// bool casp(void **val, void *old, void *new)
-// Atomically:
-// if(*val == old){
-// *val = new;
-// return 1;
-// } else
-// return 0;
-TEXT runtime·casp1(SB), NOSPLIT, $0-25
- B runtime·cas64(SB)
-
+
TEXT runtime·procyield(SB),NOSPLIT,$0-0
MOVWU cycles+0(FP), R0
again:
TEXT runtime·sigreturn(SB),NOSPLIT,$0-8
RET
+
+// This is called from .init_array and follows the platform, not Go, ABI.
+TEXT runtime·addmoduledata(SB),NOSPLIT,$0-0
+ SUB $0x10, RSP
+ MOVD R27, 8(RSP) // The access to global variables below implicitly uses R27, which is callee-save
+ MOVD runtime·lastmoduledatap(SB), R1
+ MOVD R0, moduledata_next(R1)
+ MOVD R0, runtime·lastmoduledatap(SB)
+ MOVD 8(RSP), R27
+ ADD $0x10, RSP
+ RET
--- /dev/null
+// Copyright 2015 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 mips64 mips64le
+
+#include "go_asm.h"
+#include "go_tls.h"
+#include "funcdata.h"
+#include "textflag.h"
+
+#define REGCTXT R22
+
+TEXT runtime·rt0_go(SB),NOSPLIT,$0
+ // R29 = stack; R1 = argc; R2 = argv
+
+ // initialize essential registers
+ JAL runtime·reginit(SB)
+
+ ADDV $-24, R29
+ MOVW R1, 8(R29) // argc
+ MOVV R2, 16(R29) // argv
+
+ // create istack out of the given (operating system) stack.
+ // _cgo_init may update stackguard.
+ MOVV $runtime·g0(SB), g
+ MOVV $(-64*1024), R28
+ ADDV R28, R29, R1
+ MOVV R1, g_stackguard0(g)
+ MOVV R1, g_stackguard1(g)
+ MOVV R1, (g_stack+stack_lo)(g)
+ MOVV R29, (g_stack+stack_hi)(g)
+
+ // no cgo yet
+
+nocgo:
+ // update stackguard after _cgo_init
+ MOVV (g_stack+stack_lo)(g), R1
+ ADDV $const__StackGuard, R1
+ MOVV R1, g_stackguard0(g)
+ MOVV R1, g_stackguard1(g)
+
+ // set the per-goroutine and per-mach "registers"
+ MOVV $runtime·m0(SB), R1
+
+ // save m->g0 = g0
+ MOVV g, m_g0(R1)
+ // save m0 to g0->m
+ MOVV R1, g_m(g)
+
+ JAL runtime·check(SB)
+
+ // args are already prepared
+ JAL runtime·args(SB)
+ JAL runtime·osinit(SB)
+ JAL runtime·schedinit(SB)
+
+ // create a new goroutine to start program
+ MOVV $runtime·mainPC(SB), R1 // entry
+ ADDV $-24, R29
+ MOVV R1, 16(R29)
+ MOVV R0, 8(R29)
+ MOVV R0, 0(R29)
+ JAL runtime·newproc(SB)
+ ADDV $24, R29
+
+ // start this M
+ JAL runtime·mstart(SB)
+
+ MOVV R0, 1(R0)
+ RET
+
+DATA runtime·mainPC+0(SB)/8,$runtime·main(SB)
+GLOBL runtime·mainPC(SB),RODATA,$8
+
+TEXT runtime·breakpoint(SB),NOSPLIT,$-8-0
+ MOVV R0, 2(R0) // TODO: TD
+ RET
+
+TEXT runtime·asminit(SB),NOSPLIT,$-8-0
+ RET
+
+TEXT _cgo_reginit(SB),NOSPLIT,$-8-0
+ // crosscall_ppc64 and crosscall2 need to reginit, but can't
+ // get at the 'runtime.reginit' symbol.
+ JMP runtime·reginit(SB)
+
+TEXT runtime·reginit(SB),NOSPLIT,$-8-0
+ // initialize essential FP registers
+ MOVD $0.5, F26
+ SUBD F26, F26, F24
+ ADDD F26, F26, F28
+ ADDD F28, F28, F30
+ RET
+
+/*
+ * go-routine
+ */
+
+// void gosave(Gobuf*)
+// save state in Gobuf; setjmp
+TEXT runtime·gosave(SB), NOSPLIT, $-8-8
+ MOVV buf+0(FP), R1
+ MOVV R29, gobuf_sp(R1)
+ MOVV R31, gobuf_pc(R1)
+ MOVV g, gobuf_g(R1)
+ MOVV R0, gobuf_lr(R1)
+ MOVV R0, gobuf_ret(R1)
+ MOVV R0, gobuf_ctxt(R1)
+ RET
+
+// void gogo(Gobuf*)
+// restore state from Gobuf; longjmp
+TEXT runtime·gogo(SB), NOSPLIT, $-8-8
+ MOVV buf+0(FP), R3
+ MOVV gobuf_g(R3), g // make sure g is not nil
+ JAL runtime·save_g(SB)
+
+ MOVV 0(g), R2
+ MOVV gobuf_sp(R3), R29
+ MOVV gobuf_lr(R3), R31
+ MOVV gobuf_ret(R3), R1
+ MOVV gobuf_ctxt(R3), REGCTXT
+ MOVV R0, gobuf_sp(R3)
+ MOVV R0, gobuf_ret(R3)
+ MOVV R0, gobuf_lr(R3)
+ MOVV R0, gobuf_ctxt(R3)
+ MOVV gobuf_pc(R3), R4
+ JMP (R4)
+
+// void mcall(fn func(*g))
+// Switch to m->g0's stack, call fn(g).
+// Fn must never return. It should gogo(&g->sched)
+// to keep running g.
+TEXT runtime·mcall(SB), NOSPLIT, $-8-8
+ // Save caller state in g->sched
+ MOVV R29, (g_sched+gobuf_sp)(g)
+ MOVV R31, (g_sched+gobuf_pc)(g)
+ MOVV R0, (g_sched+gobuf_lr)(g)
+ MOVV g, (g_sched+gobuf_g)(g)
+
+ // Switch to m->g0 & its stack, call fn.
+ MOVV g, R1
+ MOVV g_m(g), R3
+ MOVV m_g0(R3), g
+ JAL runtime·save_g(SB)
+ BNE g, R1, 2(PC)
+ JMP runtime·badmcall(SB)
+ MOVV fn+0(FP), REGCTXT // context
+ MOVV 0(REGCTXT), R4 // code pointer
+ MOVV (g_sched+gobuf_sp)(g), R29 // sp = m->g0->sched.sp
+ ADDV $-16, R29
+ MOVV R1, 8(R29)
+ MOVV R0, 0(R29)
+ JAL (R4)
+ JMP runtime·badmcall2(SB)
+
+// systemstack_switch is a dummy routine that systemstack leaves at the bottom
+// of the G stack. We need to distinguish the routine that
+// lives at the bottom of the G stack from the one that lives
+// at the top of the system stack because the one at the top of
+// the system stack terminates the stack walk (see topofstack()).
+TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
+ UNDEF
+ JAL (R31) // make sure this function is not leaf
+ RET
+
+// func systemstack(fn func())
+TEXT runtime·systemstack(SB), NOSPLIT, $0-8
+ MOVV fn+0(FP), R1 // R1 = fn
+ MOVV R1, REGCTXT // context
+ MOVV g_m(g), R2 // R2 = m
+
+ MOVV m_gsignal(R2), R3 // R3 = gsignal
+ BEQ g, R3, noswitch
+
+ MOVV m_g0(R2), R3 // R3 = g0
+ BEQ g, R3, noswitch
+
+ MOVV m_curg(R2), R4
+ BEQ g, R4, switch
+
+ // Bad: g is not gsignal, not g0, not curg. What is it?
+ // Hide call from linker nosplit analysis.
+ MOVV $runtime·badsystemstack(SB), R4
+ JAL (R4)
+
+switch:
+ // save our state in g->sched. Pretend to
+ // be systemstack_switch if the G stack is scanned.
+ MOVV $runtime·systemstack_switch(SB), R4
+ ADDV $8, R4 // get past prologue
+ MOVV R4, (g_sched+gobuf_pc)(g)
+ MOVV R29, (g_sched+gobuf_sp)(g)
+ MOVV R0, (g_sched+gobuf_lr)(g)
+ MOVV g, (g_sched+gobuf_g)(g)
+
+ // switch to g0
+ MOVV R3, g
+ JAL runtime·save_g(SB)
+ MOVV (g_sched+gobuf_sp)(g), R1
+ // make it look like mstart called systemstack on g0, to stop traceback
+ ADDV $-8, R1
+ MOVV $runtime·mstart(SB), R2
+ MOVV R2, 0(R1)
+ MOVV R1, R29
+
+ // call target function
+ MOVV 0(REGCTXT), R4 // code pointer
+ JAL (R4)
+
+ // switch back to g
+ MOVV g_m(g), R1
+ MOVV m_curg(R1), g
+ JAL runtime·save_g(SB)
+ MOVV (g_sched+gobuf_sp)(g), R29
+ MOVV R0, (g_sched+gobuf_sp)(g)
+ RET
+
+noswitch:
+ // already on m stack, just call directly
+ MOVV 0(REGCTXT), R4 // code pointer
+ JAL (R4)
+ RET
+
+/*
+ * support for morestack
+ */
+
+// Called during function prolog when more stack is needed.
+// Caller has already loaded:
+// R1: framesize, R2: argsize, R3: LR
+//
+// The traceback routines see morestack on a g0 as being
+// the top of a stack (for example, morestack calling newstack
+// calling the scheduler calling newm calling gc), so we must
+// record an argument size. For that purpose, it has no arguments.
+TEXT runtime·morestack(SB),NOSPLIT,$-8-0
+ // Cannot grow scheduler stack (m->g0).
+ MOVV g_m(g), R7
+ MOVV m_g0(R7), R8
+ BNE g, R8, 2(PC)
+ JAL runtime·abort(SB)
+
+ // Cannot grow signal stack (m->gsignal).
+ MOVV m_gsignal(R7), R8
+ BNE g, R8, 2(PC)
+ JAL runtime·abort(SB)
+
+ // Called from f.
+ // Set g->sched to context in f.
+ MOVV REGCTXT, (g_sched+gobuf_ctxt)(g)
+ MOVV R29, (g_sched+gobuf_sp)(g)
+ MOVV R31, (g_sched+gobuf_pc)(g)
+ MOVV R3, (g_sched+gobuf_lr)(g)
+
+ // Called from f.
+ // Set m->morebuf to f's caller.
+ MOVV R3, (m_morebuf+gobuf_pc)(R7) // f's caller's PC
+ MOVV R29, (m_morebuf+gobuf_sp)(R7) // f's caller's SP
+ MOVV g, (m_morebuf+gobuf_g)(R7)
+
+ // Call newstack on m->g0's stack.
+ MOVV m_g0(R7), g
+ JAL runtime·save_g(SB)
+ MOVV (g_sched+gobuf_sp)(g), R29
+ JAL runtime·newstack(SB)
+
+ // Not reached, but make sure the return PC from the call to newstack
+ // is still in this function, and not the beginning of the next.
+ UNDEF
+
+TEXT runtime·morestack_noctxt(SB),NOSPLIT,$-8-0
+ MOVV R0, REGCTXT
+ JMP runtime·morestack(SB)
+
+TEXT runtime·stackBarrier(SB),NOSPLIT,$0
+ // We came here via a RET to an overwritten LR.
+ // R1 may be live. Other registers are available.
+
+ // Get the original return PC, g.stkbar[g.stkbarPos].savedLRVal.
+ MOVV (g_stkbar+slice_array)(g), R2
+ MOVV g_stkbarPos(g), R3
+ MOVV $stkbar__size, R4
+ MULVU R3, R4
+ MOVV LO, R4
+ ADDV R2, R4
+ MOVV stkbar_savedLRVal(R4), R4
+ // Record that this stack barrier was hit.
+ ADDV $1, R3
+ MOVV R3, g_stkbarPos(g)
+ // Jump to the original return PC.
+ JMP (R4)
+
+// reflectcall: call a function with the given argument list
+// func call(argtype *_type, f *FuncVal, arg *byte, argsize, retoffset uint32).
+// we don't have variable-sized frames, so we use a small number
+// of constant-sized-frame functions to encode a few bits of size in the pc.
+// Caution: ugly multiline assembly macros in your future!
+
+#define DISPATCH(NAME,MAXSIZE) \
+ MOVV $MAXSIZE, R28; \
+ SGTU R1, R28, R28; \
+ BNE R28, 3(PC); \
+ MOVV $NAME(SB), R4; \
+ JMP (R4)
+// Note: can't just "BR NAME(SB)" - bad inlining results.
+
+TEXT reflect·call(SB), NOSPLIT, $0-0
+ JMP ·reflectcall(SB)
+
+TEXT ·reflectcall(SB), NOSPLIT, $-8-32
+ MOVWU argsize+24(FP), R1
+ // NOTE(rsc): No call16, because CALLFN needs four words
+ // of argument space to invoke callwritebarrier.
+ DISPATCH(runtime·call32, 32)
+ DISPATCH(runtime·call64, 64)
+ DISPATCH(runtime·call128, 128)
+ DISPATCH(runtime·call256, 256)
+ DISPATCH(runtime·call512, 512)
+ DISPATCH(runtime·call1024, 1024)
+ DISPATCH(runtime·call2048, 2048)
+ DISPATCH(runtime·call4096, 4096)
+ DISPATCH(runtime·call8192, 8192)
+ DISPATCH(runtime·call16384, 16384)
+ DISPATCH(runtime·call32768, 32768)
+ DISPATCH(runtime·call65536, 65536)
+ DISPATCH(runtime·call131072, 131072)
+ DISPATCH(runtime·call262144, 262144)
+ DISPATCH(runtime·call524288, 524288)
+ DISPATCH(runtime·call1048576, 1048576)
+ DISPATCH(runtime·call2097152, 2097152)
+ DISPATCH(runtime·call4194304, 4194304)
+ DISPATCH(runtime·call8388608, 8388608)
+ DISPATCH(runtime·call16777216, 16777216)
+ DISPATCH(runtime·call33554432, 33554432)
+ DISPATCH(runtime·call67108864, 67108864)
+ DISPATCH(runtime·call134217728, 134217728)
+ DISPATCH(runtime·call268435456, 268435456)
+ DISPATCH(runtime·call536870912, 536870912)
+ DISPATCH(runtime·call1073741824, 1073741824)
+ MOVV $runtime·badreflectcall(SB), R4
+ JMP (R4)
+
+#define CALLFN(NAME,MAXSIZE) \
+TEXT NAME(SB), WRAPPER, $MAXSIZE-24; \
+ NO_LOCAL_POINTERS; \
+ /* copy arguments to stack */ \
+ MOVV arg+16(FP), R1; \
+ MOVWU argsize+24(FP), R2; \
+ MOVV R29, R3; \
+ ADDV $8, R3; \
+ ADDV R3, R2; \
+ BEQ R3, R2, 6(PC); \
+ MOVBU (R1), R4; \
+ ADDV $1, R1; \
+ MOVBU R4, (R3); \
+ ADDV $1, R3; \
+ JMP -5(PC); \
+ /* call function */ \
+ MOVV f+8(FP), REGCTXT; \
+ MOVV (REGCTXT), R4; \
+ PCDATA $PCDATA_StackMapIndex, $0; \
+ JAL (R4); \
+ /* copy return values back */ \
+ MOVV arg+16(FP), R1; \
+ MOVWU n+24(FP), R2; \
+ MOVWU retoffset+28(FP), R4; \
+ MOVV R29, R3; \
+ ADDV R4, R3; \
+ ADDV R4, R1; \
+ SUBVU R4, R2; \
+ ADDV $8, R3; \
+ ADDV R3, R2; \
+loop: \
+ BEQ R3, R2, end; \
+ MOVBU (R3), R4; \
+ ADDV $1, R3; \
+ MOVBU R4, (R1); \
+ ADDV $1, R1; \
+ JMP loop; \
+end: \
+ /* execute write barrier updates */ \
+ MOVV argtype+0(FP), R5; \
+ MOVV arg+16(FP), R1; \
+ MOVWU n+24(FP), R2; \
+ MOVWU retoffset+28(FP), R4; \
+ MOVV R5, 8(R29); \
+ MOVV R1, 16(R29); \
+ MOVV R2, 24(R29); \
+ MOVV R4, 32(R29); \
+ JAL runtime·callwritebarrier(SB); \
+ RET
+
+CALLFN(·call16, 16)
+CALLFN(·call32, 32)
+CALLFN(·call64, 64)
+CALLFN(·call128, 128)
+CALLFN(·call256, 256)
+CALLFN(·call512, 512)
+CALLFN(·call1024, 1024)
+CALLFN(·call2048, 2048)
+CALLFN(·call4096, 4096)
+CALLFN(·call8192, 8192)
+CALLFN(·call16384, 16384)
+CALLFN(·call32768, 32768)
+CALLFN(·call65536, 65536)
+CALLFN(·call131072, 131072)
+CALLFN(·call262144, 262144)
+CALLFN(·call524288, 524288)
+CALLFN(·call1048576, 1048576)
+CALLFN(·call2097152, 2097152)
+CALLFN(·call4194304, 4194304)
+CALLFN(·call8388608, 8388608)
+CALLFN(·call16777216, 16777216)
+CALLFN(·call33554432, 33554432)
+CALLFN(·call67108864, 67108864)
+CALLFN(·call134217728, 134217728)
+CALLFN(·call268435456, 268435456)
+CALLFN(·call536870912, 536870912)
+CALLFN(·call1073741824, 1073741824)
+
+TEXT runtime·procyield(SB),NOSPLIT,$0-0
+ RET
+
+// void jmpdefer(fv, sp);
+// called from deferreturn.
+// 1. grab stored LR for caller
+// 2. sub 8 bytes to get back to JAL deferreturn
+// 3. JMP to fn
+TEXT runtime·jmpdefer(SB), NOSPLIT, $-8-16
+ MOVV 0(R29), R31
+ ADDV $-8, R31
+
+ MOVV fv+0(FP), REGCTXT
+ MOVV argp+8(FP), R29
+ ADDV $-8, R29
+ NOR R0, R0 // prevent scheduling
+ MOVV 0(REGCTXT), R4
+ JMP (R4)
+
+// Save state of caller into g->sched. Smashes R31.
+TEXT gosave<>(SB),NOSPLIT,$-8
+ MOVV R31, (g_sched+gobuf_pc)(g)
+ MOVV R29, (g_sched+gobuf_sp)(g)
+ MOVV R0, (g_sched+gobuf_lr)(g)
+ MOVV R0, (g_sched+gobuf_ret)(g)
+ MOVV R0, (g_sched+gobuf_ctxt)(g)
+ RET
+
+// func asmcgocall(fn, arg unsafe.Pointer) int32
+// Call fn(arg) on the scheduler stack,
+// aligned appropriately for the gcc ABI.
+// See cgocall.go for more details.
+TEXT ·asmcgocall(SB),NOSPLIT,$0-20
+ UNDEF // no cgo yet
+ RET
+
+// cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
+// Turn the fn into a Go func (by taking its address) and call
+// cgocallback_gofunc.
+TEXT runtime·cgocallback(SB),NOSPLIT,$24-24
+ MOVV $fn+0(FP), R1
+ MOVV R1, 8(R29)
+ MOVV frame+8(FP), R1
+ MOVV R1, 16(R29)
+ MOVV framesize+16(FP), R1
+ MOVV R1, 24(R29)
+ MOVV $runtime·cgocallback_gofunc(SB), R1
+ JAL (R1)
+ RET
+
+// cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize)
+// See cgocall.go for more details.
+TEXT ·cgocallback_gofunc(SB),NOSPLIT,$16-24
+ NO_LOCAL_POINTERS
+
+ // Load m and g from thread-local storage.
+ MOVB runtime·iscgo(SB), R1
+ BEQ R1, nocgo
+ JAL runtime·load_g(SB)
+nocgo:
+
+ // If g is nil, Go did not create the current thread.
+ // Call needm to obtain one for temporary use.
+ // In this case, we're running on the thread stack, so there's
+ // lots of space, but the linker doesn't know. Hide the call from
+ // the linker analysis by using an indirect call.
+ BNE g, havem
+ MOVV g, savedm-8(SP) // g is zero, so is m.
+ MOVV $runtime·needm(SB), R4
+ JAL (R4)
+
+ // Set m->sched.sp = SP, so that if a panic happens
+ // during the function we are about to execute, it will
+ // have a valid SP to run on the g0 stack.
+ // The next few lines (after the havem label)
+ // will save this SP onto the stack and then write
+ // the same SP back to m->sched.sp. That seems redundant,
+ // but if an unrecovered panic happens, unwindm will
+ // restore the g->sched.sp from the stack location
+ // and then systemstack will try to use it. If we don't set it here,
+ // that restored SP will be uninitialized (typically 0) and
+ // will not be usable.
+ MOVV g_m(g), R1
+ MOVV m_g0(R1), R1
+ MOVV R29, (g_sched+gobuf_sp)(R1)
+
+havem:
+ MOVV g_m(g), R3
+ MOVV R3, savedm-8(SP)
+ // Now there's a valid m, and we're running on its m->g0.
+ // Save current m->g0->sched.sp on stack and then set it to SP.
+ // Save current sp in m->g0->sched.sp in preparation for
+ // switch back to m->curg stack.
+ // NOTE: unwindm knows that the saved g->sched.sp is at 8(R29) aka savedsp-16(SP).
+ MOVV m_g0(R3), R1
+ MOVV (g_sched+gobuf_sp)(R1), R2
+ MOVV R2, savedsp-16(SP)
+ MOVV R29, (g_sched+gobuf_sp)(R1)
+
+ // Switch to m->curg stack and call runtime.cgocallbackg.
+ // Because we are taking over the execution of m->curg
+ // but *not* resuming what had been running, we need to
+ // save that information (m->curg->sched) so we can restore it.
+ // We can restore m->curg->sched.sp easily, because calling
+ // runtime.cgocallbackg leaves SP unchanged upon return.
+ // To save m->curg->sched.pc, we push it onto the stack.
+ // This has the added benefit that it looks to the traceback
+ // routine like cgocallbackg is going to return to that
+ // PC (because the frame we allocate below has the same
+ // size as cgocallback_gofunc's frame declared above)
+ // so that the traceback will seamlessly trace back into
+ // the earlier calls.
+ //
+ // In the new goroutine, -16(SP) and -8(SP) are unused.
+ MOVV m_curg(R3), g
+ JAL runtime·save_g(SB)
+ MOVV (g_sched+gobuf_sp)(g), R2 // prepare stack as R2
+ MOVV (g_sched+gobuf_pc)(g), R3
+ MOVV R3, -24(R2)
+ MOVV $-24(R2), R29
+ JAL runtime·cgocallbackg(SB)
+
+ // Restore g->sched (== m->curg->sched) from saved values.
+ MOVV 0(R29), R3
+ MOVV R3, (g_sched+gobuf_pc)(g)
+ MOVV $24(R29), R2
+ MOVV R2, (g_sched+gobuf_sp)(g)
+
+ // Switch back to m->g0's stack and restore m->g0->sched.sp.
+ // (Unlike m->curg, the g0 goroutine never uses sched.pc,
+ // so we do not have to restore it.)
+ MOVV g_m(g), R3
+ MOVV m_g0(R3), g
+ JAL runtime·save_g(SB)
+ MOVV (g_sched+gobuf_sp)(g), R29
+ MOVV savedsp-16(SP), R2
+ MOVV R2, (g_sched+gobuf_sp)(g)
+
+ // If the m on entry was nil, we called needm above to borrow an m
+ // for the duration of the call. Since the call is over, return it with dropm.
+ MOVV savedm-8(SP), R3
+ BNE R3, droppedm
+ MOVV $runtime·dropm(SB), R4
+ JAL (R4)
+droppedm:
+
+ // Done!
+ RET
+
+// void setg(G*); set g. for use by needm.
+TEXT runtime·setg(SB), NOSPLIT, $0-8
+ MOVV gg+0(FP), g
+ // This only happens if iscgo, so jump straight to save_g
+ JAL runtime·save_g(SB)
+ RET
+
+// void setg_gcc(G*); set g in C TLS.
+// Must obey the gcc calling convention.
+TEXT setg_gcc<>(SB),NOSPLIT,$-8-0
+ UNDEF // no cgo yet
+ RET
+
+TEXT runtime·getcallerpc(SB),NOSPLIT,$8-16
+ MOVV 16(R29), R1 // LR saved by caller
+ MOVV runtime·stackBarrierPC(SB), R2
+ BNE R1, R2, nobar
+ // Get original return PC.
+ JAL runtime·nextBarrierPC(SB)
+ MOVV 8(R29), R1
+nobar:
+ MOVV R1, ret+8(FP)
+ RET
+
+TEXT runtime·setcallerpc(SB),NOSPLIT,$8-16
+ MOVV pc+8(FP), R1
+ MOVV 16(R29), R2
+ MOVV runtime·stackBarrierPC(SB), R3
+ BEQ R2, R3, setbar
+ MOVV R1, 16(R29) // set LR in caller
+ RET
+setbar:
+ // Set the stack barrier return PC.
+ MOVV R1, 8(R29)
+ JAL runtime·setNextBarrierPC(SB)
+ RET
+
+TEXT runtime·getcallersp(SB),NOSPLIT,$0-16
+ MOVV argp+0(FP), R1
+ ADDV $-8, R1
+ MOVV R1, ret+8(FP)
+ RET
+
+TEXT runtime·abort(SB),NOSPLIT,$-8-0
+ MOVW (R0), R0
+ UNDEF
+
+// memhash_varlen(p unsafe.Pointer, h seed) uintptr
+// redirects to memhash(p, h, size) using the size
+// stored in the closure.
+TEXT runtime·memhash_varlen(SB),NOSPLIT,$40-24
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVV p+0(FP), R1
+ MOVV h+8(FP), R2
+ MOVV 8(REGCTXT), R3
+ MOVV R1, 8(R29)
+ MOVV R2, 16(R29)
+ MOVV R3, 24(R29)
+ JAL runtime·memhash(SB)
+ MOVV 32(R29), R1
+ MOVV R1, ret+16(FP)
+ RET
+
+// AES hashing not implemented for mips64
+TEXT runtime·aeshash(SB),NOSPLIT,$-8-0
+ MOVW (R0), R1
+TEXT runtime·aeshash32(SB),NOSPLIT,$-8-0
+ MOVW (R0), R1
+TEXT runtime·aeshash64(SB),NOSPLIT,$-8-0
+ MOVW (R0), R1
+TEXT runtime·aeshashstr(SB),NOSPLIT,$-8-0
+ MOVW (R0), R1
+
+TEXT runtime·memeq(SB),NOSPLIT,$-8-25
+ MOVV a+0(FP), R1
+ MOVV b+8(FP), R2
+ MOVV size+16(FP), R3
+ ADDV R1, R3, R4
+loop:
+ BNE R1, R4, test
+ MOVV $1, R1
+ MOVB R1, ret+24(FP)
+ RET
+test:
+ MOVBU (R1), R6
+ ADDV $1, R1
+ MOVBU (R2), R7
+ ADDV $1, R2
+ BEQ R6, R7, loop
+
+ MOVB R0, ret+24(FP)
+ RET
+
+// memequal_varlen(a, b unsafe.Pointer) bool
+TEXT runtime·memequal_varlen(SB),NOSPLIT,$40-17
+ MOVV a+0(FP), R1
+ MOVV b+8(FP), R2
+ BEQ R1, R2, eq
+ MOVV 8(REGCTXT), R3 // compiler stores size at offset 8 in the closure
+ MOVV R1, 8(R29)
+ MOVV R2, 16(R29)
+ MOVV R3, 24(R29)
+ JAL runtime·memeq(SB)
+ MOVBU 32(R29), R1
+ MOVB R1, ret+16(FP)
+ RET
+eq:
+ MOVV $1, R1
+ MOVB R1, ret+16(FP)
+ RET
+
+// eqstring tests whether two strings are equal.
+// The compiler guarantees that strings passed
+// to eqstring have equal length.
+// See runtime_test.go:eqstring_generic for
+// equivalent Go code.
+TEXT runtime·eqstring(SB),NOSPLIT,$0-33
+ MOVV s1str+0(FP), R1
+ MOVV s2str+16(FP), R2
+ MOVV $1, R3
+ MOVB R3, ret+32(FP)
+ BNE R1, R2, 2(PC)
+ RET
+ MOVV s1len+8(FP), R3
+ ADDV R1, R3, R4
+loop:
+ BNE R1, R4, 2(PC)
+ RET
+ MOVBU (R1), R6
+ ADDV $1, R1
+ MOVBU (R2), R7
+ ADDV $1, R2
+ BEQ R6, R7, loop
+ MOVB R0, ret+32(FP)
+ RET
+
+// TODO: share code with memeq?
+TEXT bytes·Equal(SB),NOSPLIT,$0-49
+ MOVV a_len+8(FP), R3
+ MOVV b_len+32(FP), R4
+ BNE R3, R4, noteq // unequal lengths are not equal
+
+ MOVV a+0(FP), R1
+ MOVV b+24(FP), R2
+ ADDV R1, R3 // end
+
+loop:
+ BEQ R1, R3, equal // reached the end
+ MOVBU (R1), R6
+ ADDV $1, R1
+ MOVBU (R2), R7
+ ADDV $1, R2
+ BEQ R6, R7, loop
+
+noteq:
+ MOVB R0, ret+48(FP)
+ RET
+
+equal:
+ MOVV $1, R1
+ MOVB R1, ret+48(FP)
+ RET
+
+TEXT bytes·IndexByte(SB),NOSPLIT,$0-40
+ MOVV s+0(FP), R1
+ MOVV s_len+8(FP), R2
+ MOVBU c+24(FP), R3 // byte to find
+ MOVV R1, R4 // store base for later
+ ADDV R1, R2 // end
+ ADDV $-1, R1
+
+loop:
+ ADDV $1, R1
+ BEQ R1, R2, notfound
+ MOVBU (R1), R5
+ BNE R3, R5, loop
+
+ SUBV R4, R1 // remove base
+ MOVV R1, ret+32(FP)
+ RET
+
+notfound:
+ MOVV $-1, R1
+ MOVV R1, ret+32(FP)
+ RET
+
+TEXT strings·IndexByte(SB),NOSPLIT,$0-32
+ MOVV p+0(FP), R1
+ MOVV b_len+8(FP), R2
+ MOVBU c+16(FP), R3 // byte to find
+ MOVV R1, R4 // store base for later
+ ADDV R1, R2 // end
+ ADDV $-1, R1
+
+loop:
+ ADDV $1, R1
+ BEQ R1, R2, notfound
+ MOVBU (R1), R5
+ BNE R3, R5, loop
+
+ SUBV R4, R1 // remove base
+ MOVV R1, ret+24(FP)
+ RET
+
+notfound:
+ MOVV $-1, R1
+ MOVV R1, ret+24(FP)
+ RET
+
+TEXT runtime·fastrand1(SB), NOSPLIT, $0-4
+ MOVV g_m(g), R2
+ MOVWU m_fastrand(R2), R1
+ ADDU R1, R1
+ BGEZ R1, 2(PC)
+ XOR $0x88888eef, R1
+ MOVW R1, m_fastrand(R2)
+ MOVW R1, ret+0(FP)
+ RET
+
+TEXT runtime·return0(SB), NOSPLIT, $0
+ MOVW $0, R1
+ RET
+
+// Called from cgo wrappers, this function returns g->m->curg.stack.hi.
+// Must obey the gcc calling convention.
+TEXT _cgo_topofstack(SB),NOSPLIT,$-8
+ UNDEF // no cgo yet
+ RET
+
+// The top-most function running on a goroutine
+// returns to goexit+PCQuantum.
+TEXT runtime·goexit(SB),NOSPLIT,$-8-0
+ NOR R0, R0 // NOP
+ JAL runtime·goexit1(SB) // does not return
+ // traceback from goexit1 must hit code range of goexit
+ NOR R0, R0 // NOP
+
+TEXT runtime·prefetcht0(SB),NOSPLIT,$0-8
+ RET
+
+TEXT runtime·prefetcht1(SB),NOSPLIT,$0-8
+ RET
+
+TEXT runtime·prefetcht2(SB),NOSPLIT,$0-8
+ RET
+
+TEXT runtime·prefetchnta(SB),NOSPLIT,$0-8
+ RET
// with arguments (the arguments should be stored at FIXED_FRAME+0(R1),
// FIXED_FRAME+8(R1) etc) and some other low-level places.
//
-// The reason for using a constant is when code is compiled as PIC on ppc64le
-// the fixed part of the stack is 32 bytes large (although PIC is not actually
-// supported yet).
+// The reason for using a constant is to make supporting PIC easier (although
+// we only support PIC on ppc64le which has a minimum 32 bytes of stack frame,
+// and currently always use that much, PIC on ppc64 would need to use 48).
-#ifdef GOARCH_ppc64
-#define FIXED_FRAME 8
-#endif
-
-#ifdef GOARCH_ppc64le
-#define FIXED_FRAME 8
-#endif
+#define FIXED_FRAME 32
BL runtime·reginit(SB)
SUB $(FIXED_FRAME+16), R1
- MOVW R3, FIXED_FRAME+0(R1) // argc
- MOVD R4, FIXED_FRAME+8(R1) // argv
+ MOVD R2, 24(R1) // stash the TOC pointer away again now we've created a new frame
+ MOVW R3, FIXED_FRAME+0(R1) // argc
+ MOVD R4, FIXED_FRAME+8(R1) // argv
// create istack out of the given (operating system) stack.
// _cgo_init may update stackguard.
RLDCR $0, R1, $~15, R1 // 16-byte align
BL (CTR) // may clobber R0, R3-R12
MOVD R14, R1 // restore stack
+ MOVD 24(R1), R2
XOR R0, R0 // fix R0
nocgo:
MOVDU R3, -8(R1)
MOVDU R0, -8(R1)
MOVDU R0, -8(R1)
+ MOVDU R0, -8(R1)
+ MOVDU R0, -8(R1)
+ MOVDU R0, -8(R1)
BL runtime·newproc(SB)
- ADD $24, R1
+ ADD $(16+FIXED_FRAME), R1
// start this M
BL runtime·mstart(SB)
MOVD (g_sched+gobuf_sp)(g), R1 // sp = m->g0->sched.sp
MOVDU R3, -8(R1)
MOVDU R0, -8(R1)
+ MOVDU R0, -8(R1)
+ MOVDU R0, -8(R1)
+ MOVDU R0, -8(R1)
BL (CTR)
+ MOVD 24(R1), R2
BR runtime·badmcall2(SB)
// systemstack_switch is a dummy routine that systemstack leaves at the bottom
// at the top of the system stack because the one at the top of
// the system stack terminates the stack walk (see topofstack()).
TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
+ // We have several undefs here so that 16 bytes past
+ // $runtime·systemstack_switch lies within them whether or not the
+ // instructions that derive r2 from r12 are there.
+ UNDEF
+ UNDEF
UNDEF
BL (LR) // make sure this function is not leaf
RET
// save our state in g->sched. Pretend to
// be systemstack_switch if the G stack is scanned.
MOVD $runtime·systemstack_switch(SB), R6
- ADD $8, R6 // get past prologue
+ ADD $16, R6 // get past prologue (including r2-setting instructions when they're there)
MOVD R6, (g_sched+gobuf_pc)(g)
MOVD R1, (g_sched+gobuf_sp)(g)
MOVD R0, (g_sched+gobuf_lr)(g)
MOVD R12, CTR
BL (CTR)
+ // restore TOC pointer. It seems unlikely that we will use systemstack
+ // to call a function defined in another module, but the results of
+ // doing so would be so confusing that it's worth doing this.
+ MOVD g_m(g), R3
+ MOVD m_curg(R3), g
+ MOVD (g_sched+gobuf_sp)(g), R3
+ MOVD 24(R3), R2
// switch back to g
MOVD g_m(g), R3
MOVD m_curg(R3), g
MOVD 0(R11), R12 // code pointer
MOVD R12, CTR
BL (CTR)
+ MOVD 24(R1), R2
RET
/*
MOVD R12, CTR; \
PCDATA $PCDATA_StackMapIndex, $0; \
BL (CTR); \
+ MOVD 24(R1), R2; \
/* copy return values back */ \
MOVD arg+16(FP), R3; \
MOVWZ n+24(FP), R4; \
BL runtime·callwritebarrier(SB); \
RET
-CALLFN(·call16, 16)
CALLFN(·call32, 32)
CALLFN(·call64, 64)
CALLFN(·call128, 128)
CALLFN(·call536870912, 536870912)
CALLFN(·call1073741824, 1073741824)
-// bool cas(uint32 *ptr, uint32 old, uint32 new)
-// Atomically:
-// if(*val == old){
-// *val = new;
-// return 1;
-// } else
-// return 0;
-TEXT runtime·cas(SB), NOSPLIT, $0-17
- MOVD ptr+0(FP), R3
- MOVWZ old+8(FP), R4
- MOVWZ new+12(FP), R5
-cas_again:
- SYNC
- LWAR (R3), R6
- CMPW R6, R4
- BNE cas_fail
- STWCCC R5, (R3)
- BNE cas_again
- MOVD $1, R3
- SYNC
- ISYNC
- MOVB R3, ret+16(FP)
- RET
-cas_fail:
- MOVD $0, R3
- BR -5(PC)
-
-// bool runtime·cas64(uint64 *ptr, uint64 old, uint64 new)
-// Atomically:
-// if(*val == *old){
-// *val = new;
-// return 1;
-// } else {
-// return 0;
-// }
-TEXT runtime·cas64(SB), NOSPLIT, $0-25
- MOVD ptr+0(FP), R3
- MOVD old+8(FP), R4
- MOVD new+16(FP), R5
-cas64_again:
- SYNC
- LDAR (R3), R6
- CMP R6, R4
- BNE cas64_fail
- STDCCC R5, (R3)
- BNE cas64_again
- MOVD $1, R3
- SYNC
- ISYNC
- MOVB R3, ret+24(FP)
- RET
-cas64_fail:
- MOVD $0, R3
- BR -5(PC)
-
-TEXT runtime·casuintptr(SB), NOSPLIT, $0-25
- BR runtime·cas64(SB)
-
-TEXT runtime·atomicloaduintptr(SB), NOSPLIT|NOFRAME, $0-16
- BR runtime·atomicload64(SB)
-
-TEXT runtime·atomicloaduint(SB), NOSPLIT|NOFRAME, $0-16
- BR runtime·atomicload64(SB)
-
-TEXT runtime·atomicstoreuintptr(SB), NOSPLIT, $0-16
- BR runtime·atomicstore64(SB)
-
-// bool casp(void **val, void *old, void *new)
-// Atomically:
-// if(*val == old){
-// *val = new;
-// return 1;
-// } else
-// return 0;
-TEXT runtime·casp1(SB), NOSPLIT, $0-25
- BR runtime·cas64(SB)
-
-// uint32 xadd(uint32 volatile *ptr, int32 delta)
-// Atomically:
-// *val += delta;
-// return *val;
-TEXT runtime·xadd(SB), NOSPLIT, $0-20
- MOVD ptr+0(FP), R4
- MOVW delta+8(FP), R5
- SYNC
- LWAR (R4), R3
- ADD R5, R3
- STWCCC R3, (R4)
- BNE -4(PC)
- SYNC
- ISYNC
- MOVW R3, ret+16(FP)
- RET
-
-TEXT runtime·xadd64(SB), NOSPLIT, $0-24
- MOVD ptr+0(FP), R4
- MOVD delta+8(FP), R5
- SYNC
- LDAR (R4), R3
- ADD R5, R3
- STDCCC R3, (R4)
- BNE -4(PC)
- SYNC
- ISYNC
- MOVD R3, ret+16(FP)
- RET
-
-TEXT runtime·xchg(SB), NOSPLIT, $0-20
- MOVD ptr+0(FP), R4
- MOVW new+8(FP), R5
- SYNC
- LWAR (R4), R3
- STWCCC R5, (R4)
- BNE -3(PC)
- SYNC
- ISYNC
- MOVW R3, ret+16(FP)
- RET
-
-TEXT runtime·xchg64(SB), NOSPLIT, $0-24
- MOVD ptr+0(FP), R4
- MOVD new+8(FP), R5
- SYNC
- LDAR (R4), R3
- STDCCC R5, (R4)
- BNE -3(PC)
- SYNC
- ISYNC
- MOVD R3, ret+16(FP)
- RET
-
-TEXT runtime·xchguintptr(SB), NOSPLIT, $0-24
- BR runtime·xchg64(SB)
-
TEXT runtime·procyield(SB),NOSPLIT,$0-0
RET
-TEXT runtime·atomicstorep1(SB), NOSPLIT, $0-16
- BR runtime·atomicstore64(SB)
-
-TEXT runtime·atomicstore(SB), NOSPLIT, $0-12
- MOVD ptr+0(FP), R3
- MOVW val+8(FP), R4
- SYNC
- MOVW R4, 0(R3)
- RET
-
-TEXT runtime·atomicstore64(SB), NOSPLIT, $0-16
- MOVD ptr+0(FP), R3
- MOVD val+8(FP), R4
- SYNC
- MOVD R4, 0(R3)
- RET
-
-// void runtime·atomicor8(byte volatile*, byte);
-TEXT runtime·atomicor8(SB), NOSPLIT, $0-9
- MOVD ptr+0(FP), R3
- MOVBZ val+8(FP), R4
- // Align ptr down to 4 bytes so we can use 32-bit load/store.
- // R5 = (R3 << 0) & ~3
- RLDCR $0, R3, $~3, R5
- // Compute val shift.
-#ifdef GOARCH_ppc64
- // Big endian. ptr = ptr ^ 3
- XOR $3, R3
-#endif
- // R6 = ((ptr & 3) * 8) = (ptr << 3) & (3*8)
- RLDC $3, R3, $(3*8), R6
- // Shift val for aligned ptr. R4 = val << R6
- SLD R6, R4, R4
-
-again:
- SYNC
- LWAR (R5), R6
- OR R4, R6
- STWCCC R6, (R5)
- BNE again
- SYNC
- ISYNC
- RET
-
-// void runtime·atomicand8(byte volatile*, byte);
-TEXT runtime·atomicand8(SB), NOSPLIT, $0-9
- MOVD ptr+0(FP), R3
- MOVBZ val+8(FP), R4
- // Align ptr down to 4 bytes so we can use 32-bit load/store.
- // R5 = (R3 << 0) & ~3
- RLDCR $0, R3, $~3, R5
- // Compute val shift.
-#ifdef GOARCH_ppc64
- // Big endian. ptr = ptr ^ 3
- XOR $3, R3
-#endif
- // R6 = ((ptr & 3) * 8) = (ptr << 3) & (3*8)
- RLDC $3, R3, $(3*8), R6
- // Shift val for aligned ptr. R4 = val << R6 | ^(0xFF << R6)
- MOVD $0xFF, R7
- SLD R6, R4
- SLD R6, R7
- XOR $-1, R7
- OR R7, R4
-again:
- SYNC
- LWAR (R5), R6
- AND R4, R6
- STWCCC R6, (R5)
- BNE again
- SYNC
- ISYNC
- RET
-
// void jmpdefer(fv, sp);
// called from deferreturn.
// 1. grab stored LR for caller
-// 2. sub 4 bytes to get back to BL deferreturn
+// 2. sub 8 bytes to get back to either nop or toc reload before deferreturn
// 3. BR to fn
+// When dynamically linking Go, it is not sufficient to rewind to the BL
+// deferreturn -- we might be jumping between modules and so we need to reset
+// the TOC pointer in r2. To do this, codegen inserts MOVD 24(R1), R2 *before*
+// the BL deferreturn and jmpdefer rewinds to that.
TEXT runtime·jmpdefer(SB), NOSPLIT|NOFRAME, $0-16
MOVD 0(R1), R31
- SUB $4, R31
+ SUB $8, R31
MOVD R31, LR
MOVD fv+0(FP), R11
// C code can clobber R0, so set it back to 0. F27-F31 are
// callee save, so we don't need to recover those.
XOR R0, R0
- // Restore g, stack pointer. R3 is errno, so don't touch it
+ // Restore g, stack pointer, toc pointer.
+ // R3 is errno, so don't touch it
MOVD 40(R1), g
+ MOVD (g_stack+stack_hi)(g), R5
+ MOVD 32(R1), R6
+ SUB R6, R5
+ MOVD 24(R5), R2
BL runtime·save_g(SB)
MOVD (g_stack+stack_hi)(g), R5
MOVD 32(R1), R6
// The top-most function running on a goroutine
// returns to goexit+PCQuantum.
+//
+// When dynamically linking Go, it can be returned to from a function
+// implemented in a different module and so needs to reload the TOC pointer
+// from the stack (although this function declares that it does not set up x-a
+// frame, newproc1 does in fact allocate one for goexit and saves the TOC
+// pointer in the correct place).
+// goexit+_PCQuantum is halfway through the usual global entry point prologue
+// that derives r2 from r12 which is a bit silly, but not harmful.
TEXT runtime·goexit(SB),NOSPLIT|NOFRAME,$0-0
- MOVD R0, R0 // NOP
+ MOVD 24(R1), R2
BL runtime·goexit1(SB) // does not return
// traceback from goexit1 must hit code range of goexit
MOVD R0, R0 // NOP
TEXT runtime·prefetchnta(SB),NOSPLIT,$0-8
RET
+
+TEXT runtime·sigreturn(SB),NOSPLIT,$0-8
+ RET
+
+// prepGoExitFrame saves the current TOC pointer (i.e. the TOC pointer for the
+// module containing runtime) to the frame that goexit will execute in when
+// the goroutine exits. It's implemented in assembly mainly because that's the
+// easiest way to get access to R2.
+TEXT runtime·prepGoExitFrame(SB),NOSPLIT,$0-8
+ MOVD sp+0(FP), R3
+ MOVD R2, 24(R3)
+ RET
+
+TEXT runtime·addmoduledata(SB),NOSPLIT|NOFRAME,$0-0
+ ADD $-8, R1
+ MOVD R31, 0(R1)
+ MOVD runtime·lastmoduledatap(SB), R4
+ MOVD R3, moduledata_next(R4)
+ MOVD R3, runtime·lastmoduledatap(SB)
+ MOVD 0(R1), R31
+ ADD $8, R1
+ RET
+++ /dev/null
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package runtime
-
-import "unsafe"
-
-var locktab [57]struct {
- l mutex
- pad [_CacheLineSize - unsafe.Sizeof(mutex{})]byte
-}
-
-func addrLock(addr *uint64) *mutex {
- return &locktab[(uintptr(unsafe.Pointer(addr))>>3)%uintptr(len(locktab))].l
-}
-
-// Atomic add and return new value.
-//go:nosplit
-func xadd(val *uint32, delta int32) uint32 {
- for {
- oval := *val
- nval := oval + uint32(delta)
- if cas(val, oval, nval) {
- return nval
- }
- }
-}
-
-//go:noescape
-//go:linkname xadduintptr runtime.xadd
-func xadduintptr(ptr *uintptr, delta uintptr) uintptr
-
-//go:nosplit
-func xchg(addr *uint32, v uint32) uint32 {
- for {
- old := *addr
- if cas(addr, old, v) {
- return old
- }
- }
-}
-
-//go:nosplit
-func xchguintptr(addr *uintptr, v uintptr) uintptr {
- return uintptr(xchg((*uint32)(unsafe.Pointer(addr)), uint32(v)))
-}
-
-//go:nosplit
-func atomicload(addr *uint32) uint32 {
- return xadd(addr, 0)
-}
-
-//go:nosplit
-func atomicloadp(addr unsafe.Pointer) unsafe.Pointer {
- return unsafe.Pointer(uintptr(xadd((*uint32)(addr), 0)))
-}
-
-//go:nosplit
-func atomicstorep1(addr unsafe.Pointer, v unsafe.Pointer) {
- for {
- old := *(*unsafe.Pointer)(addr)
- if casp1((*unsafe.Pointer)(addr), old, v) {
- return
- }
- }
-}
-
-//go:nosplit
-func atomicstore(addr *uint32, v uint32) {
- for {
- old := *addr
- if cas(addr, old, v) {
- return
- }
- }
-}
-
-//go:nosplit
-func cas64(addr *uint64, old, new uint64) bool {
- var ok bool
- systemstack(func() {
- lock(addrLock(addr))
- if *addr == old {
- *addr = new
- ok = true
- }
- unlock(addrLock(addr))
- })
- return ok
-}
-
-//go:nosplit
-func xadd64(addr *uint64, delta int64) uint64 {
- var r uint64
- systemstack(func() {
- lock(addrLock(addr))
- r = *addr + uint64(delta)
- *addr = r
- unlock(addrLock(addr))
- })
- return r
-}
-
-//go:nosplit
-func xchg64(addr *uint64, v uint64) uint64 {
- var r uint64
- systemstack(func() {
- lock(addrLock(addr))
- r = *addr
- *addr = v
- unlock(addrLock(addr))
- })
- return r
-}
-
-//go:nosplit
-func atomicload64(addr *uint64) uint64 {
- var r uint64
- systemstack(func() {
- lock(addrLock(addr))
- r = *addr
- unlock(addrLock(addr))
- })
- return r
-}
-
-//go:nosplit
-func atomicstore64(addr *uint64, v uint64) {
- systemstack(func() {
- lock(addrLock(addr))
- *addr = v
- unlock(addrLock(addr))
- })
-}
-
-//go:nosplit
-func atomicor8(addr *uint8, v uint8) {
- // Align down to 4 bytes and use 32-bit CAS.
- uaddr := uintptr(unsafe.Pointer(addr))
- addr32 := (*uint32)(unsafe.Pointer(uaddr &^ 3))
- word := uint32(v) << ((uaddr & 3) * 8) // little endian
- for {
- old := *addr32
- if cas(addr32, old, old|word) {
- return
- }
- }
-}
-
-//go:nosplit
-func atomicand8(addr *uint8, v uint8) {
- // Align down to 4 bytes and use 32-bit CAS.
- uaddr := uintptr(unsafe.Pointer(addr))
- addr32 := (*uint32)(unsafe.Pointer(uaddr &^ 3))
- word := uint32(v) << ((uaddr & 3) * 8) // little endian
- mask := uint32(0xFF) << ((uaddr & 3) * 8) // little endian
- word |= ^mask
- for {
- old := *addr32
- if cas(addr32, old, old&word) {
- return
- }
- }
-}
#include "textflag.h"
-// uint32 runtime·atomicload(uint32 volatile* addr)
-TEXT ·atomicload(SB),NOSPLIT,$-8-12
- MOVD ptr+0(FP), R0
- LDARW (R0), R0
- MOVW R0, ret+8(FP)
- RET
-
-// uint64 runtime·atomicload64(uint64 volatile* addr)
-TEXT ·atomicload64(SB),NOSPLIT,$-8-16
- MOVD ptr+0(FP), R0
- LDAR (R0), R0
- MOVD R0, ret+8(FP)
- RET
-
-// void *runtime·atomicloadp(void *volatile *addr)
-TEXT ·atomicloadp(SB),NOSPLIT,$-8-16
- MOVD ptr+0(FP), R0
- LDAR (R0), R0
- MOVD R0, ret+8(FP)
- RET
-
-TEXT runtime·atomicstorep1(SB), NOSPLIT, $0-16
- B runtime·atomicstore64(SB)
-
-TEXT runtime·atomicstore(SB), NOSPLIT, $0-12
- MOVD ptr+0(FP), R0
- MOVW val+8(FP), R1
- STLRW R1, (R0)
- RET
-
-TEXT runtime·atomicstore64(SB), NOSPLIT, $0-16
- MOVD ptr+0(FP), R0
- MOVD val+8(FP), R1
- STLR R1, (R0)
- RET
-
-TEXT runtime·xchg(SB), NOSPLIT, $0-20
-again:
- MOVD ptr+0(FP), R0
- MOVW new+8(FP), R1
- LDAXRW (R0), R2
- STLXRW R1, (R0), R3
- CBNZ R3, again
- MOVW R2, ret+16(FP)
- RET
-
-TEXT runtime·xchg64(SB), NOSPLIT, $0-24
-again:
- MOVD ptr+0(FP), R0
- MOVD new+8(FP), R1
- LDAXR (R0), R2
- STLXR R1, (R0), R3
- CBNZ R3, again
- MOVD R2, ret+16(FP)
- RET
-
-// bool runtime·cas64(uint64 *ptr, uint64 old, uint64 new)
-// Atomically:
-// if(*val == *old){
-// *val = new;
-// return 1;
-// } else {
-// return 0;
-// }
-TEXT runtime·cas64(SB), NOSPLIT, $0-25
- MOVD ptr+0(FP), R0
- MOVD old+8(FP), R1
- MOVD new+16(FP), R2
-again:
- LDAXR (R0), R3
- CMP R1, R3
- BNE ok
- STLXR R2, (R0), R3
- CBNZ R3, again
-ok:
- CSET EQ, R0
- MOVB R0, ret+24(FP)
- RET
-
-// uint32 xadd(uint32 volatile *ptr, int32 delta)
-// Atomically:
-// *val += delta;
-// return *val;
-TEXT runtime·xadd(SB), NOSPLIT, $0-20
-again:
- MOVD ptr+0(FP), R0
- MOVW delta+8(FP), R1
- LDAXRW (R0), R2
- ADDW R2, R1, R2
- STLXRW R2, (R0), R3
- CBNZ R3, again
- MOVW R2, ret+16(FP)
- RET
-
-TEXT runtime·xadd64(SB), NOSPLIT, $0-24
-again:
- MOVD ptr+0(FP), R0
- MOVD delta+8(FP), R1
- LDAXR (R0), R2
- ADD R2, R1, R2
- STLXR R2, (R0), R3
- CBNZ R3, again
- MOVD R2, ret+16(FP)
- RET
-
-TEXT runtime·xchguintptr(SB), NOSPLIT, $0-24
- B runtime·xchg64(SB)
-
TEXT ·publicationBarrier(SB),NOSPLIT,$-8-0
DMB $0xe // DMB ST
RET
--- /dev/null
+// Copyright 2015 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 mips64 mips64le
+
+#include "textflag.h"
+
+#define SYNC WORD $0xf
+
+TEXT ·publicationBarrier(SB),NOSPLIT,$-8-0
+ SYNC
+ RET
package runtime
-import "unsafe"
+import (
+ "runtime/internal/atomic"
+ "unsafe"
+)
// These functions cannot have go:noescape annotations,
// because while ptr does not escape, new does.
//go:nosplit
func atomicstorep(ptr unsafe.Pointer, new unsafe.Pointer) {
- atomicstorep1(noescape(ptr), new)
+ atomic.Storep1(noescape(ptr), new)
writebarrierptr_nostore((*uintptr)(ptr), uintptr(new))
}
//go:nosplit
func casp(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool {
- if !casp1((*unsafe.Pointer)(noescape(unsafe.Pointer(ptr))), noescape(old), new) {
+ if !atomic.Casp1((*unsafe.Pointer)(noescape(unsafe.Pointer(ptr))), noescape(old), new) {
return false
}
writebarrierptr_nostore((*uintptr)(unsafe.Pointer(ptr)), uintptr(new))
//go:nosplit
func sync_atomic_StorePointer(ptr *unsafe.Pointer, new unsafe.Pointer) {
sync_atomic_StoreUintptr((*uintptr)(unsafe.Pointer(ptr)), uintptr(new))
- atomicstorep1(noescape(unsafe.Pointer(ptr)), new)
+ atomic.Storep1(noescape(unsafe.Pointer(ptr)), new)
writebarrierptr_nostore((*uintptr)(unsafe.Pointer(ptr)), uintptr(new))
}
+++ /dev/null
-// 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 ppc64 ppc64le
-
-package runtime
-
-import "unsafe"
-
-//go:noescape
-func xadd(ptr *uint32, delta int32) uint32
-
-//go:noescape
-func xadd64(ptr *uint64, delta int64) uint64
-
-//go:noescape
-//go:linkname xadduintptr runtime.xadd64
-func xadduintptr(ptr *uintptr, delta uintptr) uintptr
-
-//go:noescape
-func xchg(ptr *uint32, new uint32) uint32
-
-//go:noescape
-func xchg64(ptr *uint64, new uint64) uint64
-
-//go:noescape
-func xchguintptr(ptr *uintptr, new uintptr) uintptr
-
-//go:noescape
-func atomicload(ptr *uint32) uint32
-
-//go:noescape
-func atomicload64(ptr *uint64) uint64
-
-//go:noescape
-func atomicloadp(ptr unsafe.Pointer) unsafe.Pointer
-
-//go:noescape
-func atomicand8(ptr *uint8, val uint8)
-
-//go:noescape
-func atomicor8(ptr *uint8, val uint8)
-
-// NOTE: Do not add atomicxor8 (XOR is not idempotent).
-
-//go:noescape
-func cas64(ptr *uint64, old, new uint64) bool
-
-//go:noescape
-func atomicstore(ptr *uint32, val uint32)
-
-//go:noescape
-func atomicstore64(ptr *uint64, val uint64)
-
-// NO go:noescape annotation; see atomic_pointer.go.
-func atomicstorep1(ptr unsafe.Pointer, val unsafe.Pointer)
#include "textflag.h"
-// uint32 runtime·atomicload(uint32 volatile* addr)
-TEXT ·atomicload(SB),NOSPLIT|NOFRAME,$0-12
- MOVD addr+0(FP), R3
- SYNC
- MOVWZ 0(R3), R3
- CMPW R3, R3, CR7
- BC 4, 30, 1(PC) // bne- cr7,0x4
- ISYNC
- MOVW R3, ret+8(FP)
- RET
-
-// uint64 runtime·atomicload64(uint64 volatile* addr)
-TEXT ·atomicload64(SB),NOSPLIT|NOFRAME,$0-16
- MOVD addr+0(FP), R3
- SYNC
- MOVD 0(R3), R3
- CMP R3, R3, CR7
- BC 4, 30, 1(PC) // bne- cr7,0x4
- ISYNC
- MOVD R3, ret+8(FP)
- RET
-
-// void *runtime·atomicloadp(void *volatile *addr)
-TEXT ·atomicloadp(SB),NOSPLIT|NOFRAME,$0-16
- MOVD addr+0(FP), R3
- SYNC
- MOVD 0(R3), R3
- CMP R3, R3, CR7
- BC 4, 30, 1(PC) // bne- cr7,0x4
- ISYNC
- MOVD R3, ret+8(FP)
- RET
-
TEXT ·publicationBarrier(SB),NOSPLIT|NOFRAME,$0-0
// LWSYNC is the "export" barrier recommended by Power ISA
// v2.07 book II, appendix B.2.2.2.
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include <string.h> /* for strerror */
+#include <pthread.h>
+#include <signal.h>
+#include "libcgo.h"
+
+static void* threadentry(void*);
+static pthread_key_t k1;
+
+#define magic1 (0x23581321U)
+
+static void
+inittls(void)
+{
+ uint32 x;
+ pthread_key_t tofree[128], k;
+ int i, ntofree;
+
+ /*
+ * Same logic, code as gcc_android_amd64.c:/inittls.
+ * Note that this is a temporary hack that should be fixed soon.
+ *
+ * TODO: fix this.
+ *
+ * The linker and runtime hard-code this constant offset
+ * from %gs where we expect to find g. Disgusting.
+ *
+ * Known to src/cmd/link/internal/ld/sym.go:/0xf8
+ * and to src/runtime/sys_linux_386.s:/0xf8 or /GOOS_android.
+ * TODO(hyangah): check 0xb0 works with API23+
+ *
+ * As disgusting as on the darwin/386, darwin/amd64.
+ */
+ ntofree = 0;
+ for(;;) {
+ if(pthread_key_create(&k, nil) < 0) {
+ fprintf(stderr, "runtime/cgo: pthread_key_create failed\n");
+ abort();
+ }
+ pthread_setspecific(k, (void*)magic1);
+ asm volatile("movl %%gs:0xf8, %0" : "=r"(x));
+ pthread_setspecific(k, 0);
+ if (x == magic1) {
+ k1 = k;
+ break;
+ }
+ if(ntofree >= nelem(tofree)) {
+ fprintf(stderr, "runtime/cgo: could not obtain pthread_keys\n");
+ fprintf(stderr, "\ttried");
+ for(i=0; i<ntofree; i++)
+ fprintf(stderr, " %#x", (unsigned)tofree[i]);
+ fprintf(stderr, "\n");
+ abort();
+ }
+ tofree[ntofree++] = k;
+ }
+ // TODO: output to stderr is not useful for apps.
+ // Can we fall back to Android's log library?
+
+ /*
+ * We got the key we wanted. Free the others.
+ */
+ for(i=0; i<ntofree; i++) {
+ pthread_key_delete(tofree[i]);
+ }
+}
+
+
+static void*
+threadentry(void *v)
+{
+ ThreadStart ts;
+
+ ts = *(ThreadStart*)v;
+ free(v);
+
+ pthread_setspecific(k1, (void*)ts.g);
+
+ crosscall_386(ts.fn);
+ return nil;
+}
+
+void (*x_cgo_inittls)(void) = inittls;
+void* (*x_cgo_threadentry)(void*) = threadentry;
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include <string.h> /* for strerror */
+#include <pthread.h>
+#include <signal.h>
+#include "libcgo.h"
+
+static void* threadentry(void*);
+static pthread_key_t k1;
+
+#define magic1 (0x23581321345589ULL)
+
+static void
+inittls(void)
+{
+ uint64 x;
+ pthread_key_t tofree[128], k;
+ int i, ntofree;
+
+ /*
+ * Same logic, code as gcc_darwin_386.c:/inittls.
+ * Note that this is a temporary hack that should be fixed soon.
+ * Android-L and M bionic's pthread implementation differ
+ * significantly, and can change any time.
+ * https://android-review.googlesource.com/#/c/134202
+ *
+ * We chose %fs:0x1d0 which seems to work in testing with Android
+ * emulators (API22, API23) but it may break any time.
+ *
+ * TODO: fix this.
+ *
+ * The linker and runtime hard-code this constant offset
+ * from %fs where we expect to find g. Disgusting.
+ *
+ * Known to src/cmd/link/internal/ld/sym.go:/0x1d0
+ * and to src/runtime/sys_linux_amd64.s:/0x1d0 or /GOOS_android.
+ *
+ * As disgusting as on the darwin/386, darwin/amd64.
+ */
+ ntofree = 0;
+ for(;;) {
+ if(pthread_key_create(&k, nil) < 0) {
+ fprintf(stderr, "runtime/cgo: pthread_key_create failed\n");
+ abort();
+ }
+ pthread_setspecific(k, (void*)magic1);
+ asm volatile("movq %%fs:0x1d0, %0" : "=r"(x));
+ pthread_setspecific(k, 0);
+ if(x == magic1) {
+ k1 = k;
+ break;
+ }
+ if(ntofree >= nelem(tofree)) {
+ fprintf(stderr, "runtime/cgo: could not obtain pthread_keys\n");
+ fprintf(stderr, "\ttried");
+ for(i=0; i<ntofree; i++)
+ fprintf(stderr, " %#x", (unsigned)tofree[i]);
+ fprintf(stderr, "\n");
+ abort();
+ }
+ tofree[ntofree++] = k;
+ }
+ // TODO: output to stderr is not useful for apps.
+ // Can we fall back to Android's log library?
+
+ /*
+ * We got the key we wanted. Free the others.
+ */
+ for(i=0; i<ntofree; i++) {
+ pthread_key_delete(tofree[i]);
+ }
+}
+
+
+static void*
+threadentry(void *v)
+{
+ ThreadStart ts;
+
+ ts = *(ThreadStart*)v;
+ free(v);
+
+ pthread_setspecific(k1, (void*)ts.g);
+
+ crosscall_amd64(ts.fn);
+ return nil;
+}
+
+void (*x_cgo_inittls)(void) = inittls;
+void* (*x_cgo_threadentry)(void*) = threadentry;
static void *threadentry(void*);
static void (*setg_gcc)(void*);
+// These will be set in gcc_android_386.c for android-specific customization.
+void (*x_cgo_inittls)(void);
+void* (*x_cgo_threadentry)(void*);
+
void
x_cgo_init(G *g, void (*setg)(void*))
{
pthread_attr_getstacksize(&attr, &size);
g->stacklo = (uintptr)&attr - size + 4096;
pthread_attr_destroy(&attr);
+
+ if (x_cgo_inittls) {
+ x_cgo_inittls();
+ }
}
static void*
threadentry(void *v)
{
+ if (x_cgo_threadentry) {
+ return x_cgo_threadentry(v);
+ }
+
ThreadStart ts;
ts = *(ThreadStart*)v;
static void* threadentry(void*);
static void (*setg_gcc)(void*);
+// These will be set in gcc_android_amd64.c for android-specific customization.
+void (*x_cgo_inittls)(void);
+void* (*x_cgo_threadentry)(void*);
+
void
x_cgo_init(G* g, void (*setg)(void*))
{
g->stacklo = (uintptr)&size - size + 4096;
pthread_attr_destroy(attr);
free(attr);
+
+ if (x_cgo_inittls) {
+ x_cgo_inittls();
+ }
}
static void*
threadentry(void *v)
{
+ if (x_cgo_threadentry) {
+ return x_cgo_threadentry(v);
+ }
+
ThreadStart ts;
ts = *(ThreadStart*)v;
// Set up Go ABI constant registers
bl _cgo_reginit
+ nop
// Restore g pointer (r30 in Go ABI, which may have been clobbered by C)
mr %r30, %r4
--- /dev/null
+// Copyright 2015 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 ppc64 ppc64le
+
+package runtime
+
+// crosscall_ppc64 calls into the runtime to set up the registers the
+// Go runtime expects and so the symbol it calls needs to be exported
+// for external linking to work.
+//go:cgo_export_static _cgo_reginit
package runtime
-import "unsafe"
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
// Call from Go to C.
//go:nosplit
case "arm":
// On arm, stack frame is two words and there's a saved LR between
// SP and the stack frame and between the stack frame and the arguments.
- cb = (*args)(unsafe.Pointer(sp + 4*ptrSize))
+ cb = (*args)(unsafe.Pointer(sp + 4*sys.PtrSize))
case "arm64":
// On arm64, stack frame is four words and there's a saved LR between
// SP and the stack frame and between the stack frame and the arguments.
- cb = (*args)(unsafe.Pointer(sp + 5*ptrSize))
+ cb = (*args)(unsafe.Pointer(sp + 5*sys.PtrSize))
case "amd64":
// On amd64, stack frame is one word, plus caller PC.
if framepointer_enabled {
// In this case, there's also saved BP.
- cb = (*args)(unsafe.Pointer(sp + 3*ptrSize))
+ cb = (*args)(unsafe.Pointer(sp + 3*sys.PtrSize))
break
}
- cb = (*args)(unsafe.Pointer(sp + 2*ptrSize))
+ cb = (*args)(unsafe.Pointer(sp + 2*sys.PtrSize))
case "386":
// On 386, stack frame is three words, plus caller PC.
- cb = (*args)(unsafe.Pointer(sp + 4*ptrSize))
+ cb = (*args)(unsafe.Pointer(sp + 4*sys.PtrSize))
case "ppc64", "ppc64le":
// On ppc64, the callback arguments are in the arguments area of
// cgocallback's stack frame. The stack looks like this:
// | cgocallback_gofunc +------------------------------+ <- sp + minFrameSize
// | | fixed frame area |
// +--------------------+------------------------------+ <- sp
- cb = (*args)(unsafe.Pointer(sp + 2*minFrameSize + 2*ptrSize))
+ cb = (*args)(unsafe.Pointer(sp + 2*sys.MinFrameSize + 2*sys.PtrSize))
}
// Invoke callback.
if raceenabled {
racereleasemerge(unsafe.Pointer(&racecgosync))
}
+ if msanenabled {
+ // Tell msan that we wrote to the entire argument block.
+ // This tells msan that we set the results.
+ // Since we have already called the function it doesn't
+ // matter that we are writing to the non-result parameters.
+ msanwrite(cb.arg, cb.argsize)
+ }
// Do not unwind m->g0->sched.sp.
// Our caller, cgocallback, will do that.
default:
throw("unwindm not implemented")
case "386", "amd64", "arm", "ppc64", "ppc64le":
- sched.sp = *(*uintptr)(unsafe.Pointer(sched.sp + minFrameSize))
+ sched.sp = *(*uintptr)(unsafe.Pointer(sched.sp + sys.MinFrameSize))
case "arm64":
sched.sp = *(*uintptr)(unsafe.Pointer(sched.sp + 16))
}
}
var racecgosync uint64 // represents possible synchronization in C code
+
+// Pointer checking for cgo code.
+
+// We want to detect all cases where a program that does not use
+// unsafe makes a cgo call passing a Go pointer to memory that
+// contains a Go pointer. Here a Go pointer is defined as a pointer
+// to memory allocated by the Go runtime. Programs that use unsafe
+// can evade this restriction easily, so we don't try to catch them.
+// The cgo program will rewrite all possibly bad pointer arguments to
+// call cgoCheckPointer, where we can catch cases of a Go pointer
+// pointing to a Go pointer.
+
+// Complicating matters, taking the address of a slice or array
+// element permits the C program to access all elements of the slice
+// or array. In that case we will see a pointer to a single element,
+// but we need to check the entire data structure.
+
+// The cgoCheckPointer call takes additional arguments indicating that
+// it was called on an address expression. An additional argument of
+// true means that it only needs to check a single element. An
+// additional argument of a slice or array means that it needs to
+// check the entire slice/array, but nothing else. Otherwise, the
+// pointer could be anything, and we check the entire heap object,
+// which is conservative but safe.
+
+// When and if we implement a moving garbage collector,
+// cgoCheckPointer will pin the pointer for the duration of the cgo
+// call. (This is necessary but not sufficient; the cgo program will
+// also have to change to pin Go pointers that can not point to Go
+// pointers.)
+
+// cgoCheckPointer checks if the argument contains a Go pointer that
+// points to a Go pointer, and panics if it does. It returns the pointer.
+func cgoCheckPointer(ptr interface{}, args ...interface{}) interface{} {
+ if debug.cgocheck == 0 {
+ return ptr
+ }
+
+ ep := (*eface)(unsafe.Pointer(&ptr))
+ t := ep._type
+
+ top := true
+ if len(args) > 0 && t.kind&kindMask == kindPtr {
+ p := ep.data
+ if t.kind&kindDirectIface == 0 {
+ p = *(*unsafe.Pointer)(p)
+ }
+ if !cgoIsGoPointer(p) {
+ return ptr
+ }
+ aep := (*eface)(unsafe.Pointer(&args[0]))
+ switch aep._type.kind & kindMask {
+ case kindBool:
+ pt := (*ptrtype)(unsafe.Pointer(t))
+ cgoCheckArg(pt.elem, p, true, false)
+ return ptr
+ case kindSlice:
+ // Check the slice rather than the pointer.
+ ep = aep
+ t = ep._type
+ case kindArray:
+ // Check the array rather than the pointer.
+ // Pass top as false since we have a pointer
+ // to the array.
+ ep = aep
+ t = ep._type
+ top = false
+ default:
+ throw("can't happen")
+ }
+ }
+
+ cgoCheckArg(t, ep.data, t.kind&kindDirectIface == 0, top)
+ return ptr
+}
+
+const cgoCheckPointerFail = "cgo argument has Go pointer to Go pointer"
+
+// cgoCheckArg is the real work of cgoCheckPointer. The argument p
+// is either a pointer to the value (of type t), or the value itself,
+// depending on indir. The top parameter is whether we are at the top
+// level, where Go pointers are allowed.
+func cgoCheckArg(t *_type, p unsafe.Pointer, indir, top bool) {
+ if t.kind&kindNoPointers != 0 {
+ // If the type has no pointers there is nothing to do.
+ return
+ }
+
+ switch t.kind & kindMask {
+ default:
+ throw("can't happen")
+ case kindArray:
+ at := (*arraytype)(unsafe.Pointer(t))
+ if !indir {
+ if at.len != 1 {
+ throw("can't happen")
+ }
+ cgoCheckArg(at.elem, p, at.elem.kind&kindDirectIface == 0, top)
+ return
+ }
+ for i := uintptr(0); i < at.len; i++ {
+ cgoCheckArg(at.elem, p, true, top)
+ p = add(p, at.elem.size)
+ }
+ case kindChan, kindMap:
+ // These types contain internal pointers that will
+ // always be allocated in the Go heap. It's never OK
+ // to pass them to C.
+ panic(errorString(cgoCheckPointerFail))
+ case kindFunc:
+ if indir {
+ p = *(*unsafe.Pointer)(p)
+ }
+ if !cgoIsGoPointer(p) {
+ return
+ }
+ panic(errorString(cgoCheckPointerFail))
+ case kindInterface:
+ it := *(**_type)(p)
+ if it == nil {
+ return
+ }
+ // A type known at compile time is OK since it's
+ // constant. A type not known at compile time will be
+ // in the heap and will not be OK.
+ if inheap(uintptr(unsafe.Pointer(it))) {
+ panic(errorString(cgoCheckPointerFail))
+ }
+ p = *(*unsafe.Pointer)(add(p, sys.PtrSize))
+ if !cgoIsGoPointer(p) {
+ return
+ }
+ if !top {
+ panic(errorString(cgoCheckPointerFail))
+ }
+ cgoCheckArg(it, p, it.kind&kindDirectIface == 0, false)
+ case kindSlice:
+ st := (*slicetype)(unsafe.Pointer(t))
+ s := (*slice)(p)
+ p = s.array
+ if !cgoIsGoPointer(p) {
+ return
+ }
+ if !top {
+ panic(errorString(cgoCheckPointerFail))
+ }
+ for i := 0; i < s.cap; i++ {
+ cgoCheckArg(st.elem, p, true, false)
+ p = add(p, st.elem.size)
+ }
+ case kindStruct:
+ st := (*structtype)(unsafe.Pointer(t))
+ if !indir {
+ if len(st.fields) != 1 {
+ throw("can't happen")
+ }
+ cgoCheckArg(st.fields[0].typ, p, st.fields[0].typ.kind&kindDirectIface == 0, top)
+ return
+ }
+ for _, f := range st.fields {
+ cgoCheckArg(f.typ, add(p, f.offset), true, top)
+ }
+ case kindPtr, kindUnsafePointer:
+ if indir {
+ p = *(*unsafe.Pointer)(p)
+ }
+
+ if !cgoIsGoPointer(p) {
+ return
+ }
+ if !top {
+ panic(errorString(cgoCheckPointerFail))
+ }
+
+ cgoCheckUnknownPointer(p)
+ }
+}
+
+// cgoCheckUnknownPointer is called for an arbitrary pointer into Go
+// memory. It checks whether that Go memory contains any other
+// pointer into Go memory. If it does, we panic.
+func cgoCheckUnknownPointer(p unsafe.Pointer) {
+ if cgoInRange(p, mheap_.arena_start, mheap_.arena_used) {
+ if !inheap(uintptr(p)) {
+ // This pointer is either to a stack or to an
+ // unused span. Escape analysis should
+ // prevent the former and the latter should
+ // not happen.
+ panic(errorString("cgo argument has invalid Go pointer"))
+ }
+
+ base, hbits, span := heapBitsForObject(uintptr(p), 0, 0)
+ if base == 0 {
+ return
+ }
+ n := span.elemsize
+ for i := uintptr(0); i < n; i += sys.PtrSize {
+ bits := hbits.bits()
+ if i >= 2*sys.PtrSize && bits&bitMarked == 0 {
+ // No more possible pointers.
+ break
+ }
+ if bits&bitPointer != 0 {
+ if cgoIsGoPointer(*(*unsafe.Pointer)(unsafe.Pointer(base + i))) {
+ panic(errorString(cgoCheckPointerFail))
+ }
+ }
+ hbits = hbits.next()
+ }
+
+ return
+ }
+
+ for datap := &firstmoduledata; datap != nil; datap = datap.next {
+ if cgoInRange(p, datap.data, datap.edata) || cgoInRange(p, datap.bss, datap.ebss) {
+ // We have no way to know the size of the object.
+ // We have to assume that it might contain a pointer.
+ panic(errorString(cgoCheckPointerFail))
+ }
+ // In the text or noptr sections, we know that the
+ // pointer does not point to a Go pointer.
+ }
+}
+
+// cgoIsGoPointer returns whether the pointer is a Go pointer--a
+// pointer to Go memory. We only care about Go memory that might
+// contain pointers.
+//go:nosplit
+//go:nowritebarrierrec
+func cgoIsGoPointer(p unsafe.Pointer) bool {
+ if p == nil {
+ return false
+ }
+
+ if cgoInRange(p, mheap_.arena_start, mheap_.arena_used) {
+ return true
+ }
+
+ for datap := &firstmoduledata; datap != nil; datap = datap.next {
+ if cgoInRange(p, datap.data, datap.edata) || cgoInRange(p, datap.bss, datap.ebss) {
+ return true
+ }
+ }
+
+ return false
+}
+
+// cgoInRange returns whether p is between start and end.
+//go:nosplit
+//go:nowritebarrierrec
+func cgoInRange(p unsafe.Pointer, start, end uintptr) bool {
+ return start <= uintptr(p) && uintptr(p) < end
+}
--- /dev/null
+// Copyright 2015 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.
+
+// Code to check that pointer writes follow the cgo rules.
+// These functions are invoked via the write barrier when debug.cgocheck > 1.
+
+package runtime
+
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
+
+const cgoWriteBarrierFail = "Go pointer stored into non-Go memory"
+
+// cgoCheckWriteBarrier is called whenever a pointer is stored into memory.
+// It throws if the program is storing a Go pointer into non-Go memory.
+//go:nosplit
+//go:nowritebarrier
+func cgoCheckWriteBarrier(dst *uintptr, src uintptr) {
+ if !cgoIsGoPointer(unsafe.Pointer(src)) {
+ return
+ }
+ if cgoIsGoPointer(unsafe.Pointer(dst)) {
+ return
+ }
+
+ // If we are running on the system stack then dst might be an
+ // address on the stack, which is OK.
+ g := getg()
+ if g == g.m.g0 || g == g.m.gsignal {
+ return
+ }
+
+ // Allocating memory can write to various mfixalloc structs
+ // that look like they are non-Go memory.
+ if g.m.mallocing != 0 {
+ return
+ }
+
+ systemstack(func() {
+ println("write of Go pointer", hex(src), "to non-Go memory", hex(uintptr(unsafe.Pointer(dst))))
+ throw(cgoWriteBarrierFail)
+ })
+}
+
+// cgoCheckMemmove is called when moving a block of memory.
+// dst and src point off bytes into the value to copy.
+// size is the number of bytes to copy.
+// It throws if the program is copying a block that contains a Go pointer
+// into non-Go memory.
+//go:nosplit
+//go:nowritebarrier
+func cgoCheckMemmove(typ *_type, dst, src unsafe.Pointer, off, size uintptr) {
+ if typ.kind&kindNoPointers != 0 {
+ return
+ }
+ if !cgoIsGoPointer(src) {
+ return
+ }
+ if cgoIsGoPointer(dst) {
+ return
+ }
+ cgoCheckTypedBlock(typ, src, off, size)
+}
+
+// cgoCheckSliceCopy is called when copying n elements of a slice from
+// src to dst. typ is the element type of the slice.
+// It throws if the program is copying slice elements that contain Go pointers
+// into non-Go memory.
+//go:nosplit
+//go:nowritebarrier
+func cgoCheckSliceCopy(typ *_type, dst, src slice, n int) {
+ if typ.kind&kindNoPointers != 0 {
+ return
+ }
+ if !cgoIsGoPointer(src.array) {
+ return
+ }
+ if cgoIsGoPointer(dst.array) {
+ return
+ }
+ p := src.array
+ for i := 0; i < n; i++ {
+ cgoCheckTypedBlock(typ, p, 0, typ.size)
+ p = add(p, typ.size)
+ }
+}
+
+// cgoCheckTypedBlock checks the block of memory at src, for up to size bytes,
+// and throws if it finds a Go pointer. The type of the memory is typ,
+// and src is off bytes into that type.
+//go:nosplit
+//go:nowritebarrier
+func cgoCheckTypedBlock(typ *_type, src unsafe.Pointer, off, size uintptr) {
+ if typ.kind&kindGCProg == 0 {
+ cgoCheckBits(src, typ.gcdata, off, size)
+ return
+ }
+
+ // The type has a GC program. Try to find GC bits somewhere else.
+ for datap := &firstmoduledata; datap != nil; datap = datap.next {
+ if cgoInRange(src, datap.data, datap.edata) {
+ doff := uintptr(src) - datap.data
+ cgoCheckBits(add(src, -doff), datap.gcdatamask.bytedata, off+doff, size)
+ return
+ }
+ if cgoInRange(src, datap.bss, datap.ebss) {
+ boff := uintptr(src) - datap.bss
+ cgoCheckBits(add(src, -boff), datap.gcbssmask.bytedata, off+boff, size)
+ return
+ }
+ }
+
+ aoff := uintptr(src) - mheap_.arena_start
+ idx := aoff >> _PageShift
+ s := h_spans[idx]
+ if s.state == _MSpanStack {
+ // There are no heap bits for value stored on the stack.
+ // For a channel receive src might be on the stack of some
+ // other goroutine, so we can't unwind the stack even if
+ // we wanted to.
+ // We can't expand the GC program without extra storage
+ // space we can't easily get.
+ // Fortunately we have the type information.
+ systemstack(func() {
+ cgoCheckUsingType(typ, src, off, size)
+ })
+ return
+ }
+
+ // src must be in the regular heap.
+
+ hbits := heapBitsForAddr(uintptr(src))
+ for i := uintptr(0); i < off+size; i += sys.PtrSize {
+ bits := hbits.bits()
+ if bits != 0 {
+ println(i, bits)
+ }
+ if i >= off && bits&bitPointer != 0 {
+ v := *(*unsafe.Pointer)(add(src, i))
+ if cgoIsGoPointer(v) {
+ systemstack(func() {
+ throw(cgoWriteBarrierFail)
+ })
+ }
+ }
+ hbits = hbits.next()
+ }
+}
+
+// cgoCheckBits checks the block of memory at src, for up to size
+// bytes, and throws if it finds a Go pointer. The gcbits mark each
+// pointer value. The src pointer is off bytes into the gcbits.
+//go:nosplit
+//go:nowritebarrier
+func cgoCheckBits(src unsafe.Pointer, gcbits *byte, off, size uintptr) {
+ skipMask := off / sys.PtrSize / 8
+ skipBytes := skipMask * sys.PtrSize * 8
+ ptrmask := addb(gcbits, skipMask)
+ src = add(src, skipBytes)
+ off -= skipBytes
+ size += off
+ var bits uint32
+ for i := uintptr(0); i < size; i += sys.PtrSize {
+ if i&(sys.PtrSize*8-1) == 0 {
+ bits = uint32(*ptrmask)
+ ptrmask = addb(ptrmask, 1)
+ } else {
+ bits >>= 1
+ }
+ if off > 0 {
+ off -= sys.PtrSize
+ } else {
+ if bits&1 != 0 {
+ v := *(*unsafe.Pointer)(add(src, i))
+ if cgoIsGoPointer(v) {
+ systemstack(func() {
+ throw(cgoWriteBarrierFail)
+ })
+ }
+ }
+ }
+ }
+}
+
+// cgoCheckUsingType is like cgoCheckTypedBlock, but is a last ditch
+// fall back to look for pointers in src using the type information.
+// We only this when looking at a value on the stack when the type
+// uses a GC program, because otherwise it's more efficient to use the
+// GC bits. This is called on the system stack.
+//go:nowritebarrier
+//go:systemstack
+func cgoCheckUsingType(typ *_type, src unsafe.Pointer, off, size uintptr) {
+ if typ.kind&kindNoPointers != 0 {
+ return
+ }
+ if typ.kind&kindGCProg == 0 {
+ cgoCheckBits(src, typ.gcdata, off, size)
+ return
+ }
+ switch typ.kind & kindMask {
+ default:
+ throw("can't happen")
+ case kindArray:
+ at := (*arraytype)(unsafe.Pointer(typ))
+ for i := uintptr(0); i < at.len; i++ {
+ if off < at.elem.size {
+ cgoCheckUsingType(at.elem, src, off, size)
+ }
+ src = add(src, at.elem.size)
+ skipped := off
+ if skipped > at.elem.size {
+ skipped = at.elem.size
+ }
+ checked := at.elem.size - skipped
+ off -= skipped
+ if size <= checked {
+ return
+ }
+ size -= checked
+ }
+ case kindStruct:
+ st := (*structtype)(unsafe.Pointer(typ))
+ for _, f := range st.fields {
+ if off < f.typ.size {
+ cgoCheckUsingType(f.typ, src, off, size)
+ }
+ src = add(src, f.typ.size)
+ skipped := off
+ if skipped > f.typ.size {
+ skipped = f.typ.size
+ }
+ checked := f.typ.size - skipped
+ off -= skipped
+ if size <= checked {
+ return
+ }
+ size -= checked
+ }
+ }
+}
// This file contains the implementation of Go channels.
-import "unsafe"
+// Invariants:
+// At least one of c.sendq and c.recvq is empty.
+// For buffered channels, also:
+// c.qcount > 0 implies that c.recvq is empty.
+// c.qcount < c.dataqsiz implies that c.sendq is empty.
+import (
+ "runtime/internal/atomic"
+ "unsafe"
+)
const (
maxAlign = 8
if raceenabled {
raceReadObjectPC(t.elem, ep, callerpc, funcPC(chansend))
}
+ if msanenabled {
+ msanread(ep, t.elem.size)
+ }
if c == nil {
if !block {
}
lock(&c.lock)
+
if c.closed != 0 {
unlock(&c.lock)
panic("send on closed channel")
}
- if c.dataqsiz == 0 { // synchronous channel
- sg := c.recvq.dequeue()
- if sg != nil { // found a waiting receiver
- if raceenabled {
- racesync(c, sg)
- }
- unlock(&c.lock)
-
- recvg := sg.g
- if sg.elem != nil {
- syncsend(c, sg, ep)
- }
- recvg.param = unsafe.Pointer(sg)
- if sg.releasetime != 0 {
- sg.releasetime = cputicks()
- }
- goready(recvg, 3)
- return true
- }
-
- if !block {
- unlock(&c.lock)
- return false
- }
-
- // no receiver available: block on this channel.
- gp := getg()
- mysg := acquireSudog()
- mysg.releasetime = 0
- if t0 != 0 {
- mysg.releasetime = -1
- }
- mysg.elem = ep
- mysg.waitlink = nil
- gp.waiting = mysg
- mysg.g = gp
- mysg.selectdone = nil
- gp.param = nil
- c.sendq.enqueue(mysg)
- goparkunlock(&c.lock, "chan send", traceEvGoBlockSend, 3)
+ if sg := c.recvq.dequeue(); sg != nil {
+ // Found a waiting receiver. We pass the value we want to send
+ // directly to the receiver, bypassing the channel buffer (if any).
+ send(c, sg, ep, func() { unlock(&c.lock) })
+ return true
+ }
- // someone woke us up.
- if mysg != gp.waiting {
- throw("G waiting list is corrupted!")
- }
- gp.waiting = nil
- if gp.param == nil {
- if c.closed == 0 {
- throw("chansend: spurious wakeup")
- }
- panic("send on closed channel")
+ if c.qcount < c.dataqsiz {
+ // Space is available in the channel buffer. Enqueue the element to send.
+ qp := chanbuf(c, c.sendx)
+ if raceenabled {
+ raceacquire(qp)
+ racerelease(qp)
}
- gp.param = nil
- if mysg.releasetime > 0 {
- blockevent(int64(mysg.releasetime)-t0, 2)
+ typedmemmove(c.elemtype, qp, ep)
+ c.sendx++
+ if c.sendx == c.dataqsiz {
+ c.sendx = 0
}
- releaseSudog(mysg)
+ c.qcount++
+ unlock(&c.lock)
return true
}
- // asynchronous channel
- // wait for some space to write our data
- var t1 int64
- for futile := byte(0); c.qcount >= c.dataqsiz; futile = traceFutileWakeup {
- if !block {
- unlock(&c.lock)
- return false
- }
- gp := getg()
- mysg := acquireSudog()
- mysg.releasetime = 0
- if t0 != 0 {
- mysg.releasetime = -1
- }
- mysg.g = gp
- mysg.elem = nil
- mysg.selectdone = nil
- c.sendq.enqueue(mysg)
- goparkunlock(&c.lock, "chan send", traceEvGoBlockSend|futile, 3)
-
- // someone woke us up - try again
- if mysg.releasetime > 0 {
- t1 = mysg.releasetime
- }
- releaseSudog(mysg)
- lock(&c.lock)
- if c.closed != 0 {
- unlock(&c.lock)
- panic("send on closed channel")
- }
+ if !block {
+ unlock(&c.lock)
+ return false
}
- // write our data into the channel buffer
- if raceenabled {
- raceacquire(chanbuf(c, c.sendx))
- racerelease(chanbuf(c, c.sendx))
+ // Block on the channel. Some receiver will complete our operation for us.
+ gp := getg()
+ mysg := acquireSudog()
+ mysg.releasetime = 0
+ if t0 != 0 {
+ mysg.releasetime = -1
+ }
+ mysg.elem = ep
+ mysg.waitlink = nil
+ mysg.g = gp
+ mysg.selectdone = nil
+ gp.waiting = mysg
+ gp.param = nil
+ c.sendq.enqueue(mysg)
+ goparkunlock(&c.lock, "chan send", traceEvGoBlockSend, 3)
+
+ // someone woke us up.
+ if mysg != gp.waiting {
+ throw("G waiting list is corrupted")
+ }
+ gp.waiting = nil
+ if gp.param == nil {
+ if c.closed == 0 {
+ throw("chansend: spurious wakeup")
+ }
+ panic("send on closed channel")
}
- typedmemmove(c.elemtype, chanbuf(c, c.sendx), ep)
- c.sendx++
- if c.sendx == c.dataqsiz {
- c.sendx = 0
+ gp.param = nil
+ if mysg.releasetime > 0 {
+ blockevent(int64(mysg.releasetime)-t0, 2)
}
- c.qcount++
+ releaseSudog(mysg)
+ return true
+}
- // wake up a waiting receiver
- sg := c.recvq.dequeue()
- if sg != nil {
- recvg := sg.g
- unlock(&c.lock)
- if sg.releasetime != 0 {
- sg.releasetime = cputicks()
+// send processes a send operation on an empty channel c.
+// The value ep sent by the sender is copied to the receiver sg.
+// The receiver is then woken up to go on its merry way.
+// Channel c must be empty and locked. send unlocks c with unlockf.
+// sg must already be dequeued from c.
+// ep must be non-nil and point to the heap or the caller's stack.
+func send(c *hchan, sg *sudog, ep unsafe.Pointer, unlockf func()) {
+ if raceenabled {
+ if c.dataqsiz == 0 {
+ racesync(c, sg)
+ } else {
+ // Pretend we go through the buffer, even though
+ // we copy directly. Note that we need to increment
+ // the head/tail locations only when raceenabled.
+ qp := chanbuf(c, c.recvx)
+ raceacquire(qp)
+ racerelease(qp)
+ raceacquireg(sg.g, qp)
+ racereleaseg(sg.g, qp)
+ c.recvx++
+ if c.recvx == c.dataqsiz {
+ c.recvx = 0
+ }
+ c.sendx = c.recvx // c.sendx = (c.sendx+1) % c.dataqsiz
}
- goready(recvg, 3)
- } else {
- unlock(&c.lock)
}
- if t1 > 0 {
- blockevent(t1-t0, 2)
+ unlockf()
+ if sg.elem != nil {
+ sendDirect(c.elemtype, sg, ep)
+ sg.elem = nil
+ }
+ gp := sg.g
+ gp.param = unsafe.Pointer(sg)
+ if sg.releasetime != 0 {
+ sg.releasetime = cputicks()
}
- return true
+ goready(gp, 4)
}
-func syncsend(c *hchan, sg *sudog, elem unsafe.Pointer) {
- // Send on unbuffered channel is the only operation
+func sendDirect(t *_type, sg *sudog, src unsafe.Pointer) {
+ // Send on an unbuffered or empty-buffered channel is the only operation
// in the entire runtime where one goroutine
// writes to the stack of another goroutine. The GC assumes that
// stack writes only happen when the goroutine is running and are
// typedmemmove will call heapBitsBulkBarrier, but the target bytes
// are not in the heap, so that will not help. We arrange to call
// memmove and typeBitsBulkBarrier instead.
- memmove(sg.elem, elem, c.elemtype.size)
- typeBitsBulkBarrier(c.elemtype, uintptr(sg.elem), c.elemtype.size)
- sg.elem = nil
+
+ // Once we read sg.elem out of sg, it will no longer
+ // be updated if the destination's stack gets copied (shrunk).
+ // So make sure that no preemption points can happen between read & use.
+ dst := sg.elem
+ memmove(dst, src, t.size)
+ typeBitsBulkBarrier(t, uintptr(dst), t.size)
}
func closechan(c *hchan) {
if sg == nil {
break
}
- gp := sg.g
- sg.elem = nil
- gp.param = nil
+ if sg.elem != nil {
+ memclr(sg.elem, uintptr(c.elemsize))
+ sg.elem = nil
+ }
if sg.releasetime != 0 {
sg.releasetime = cputicks()
}
+ gp := sg.g
+ gp.param = nil
+ if raceenabled {
+ raceacquireg(gp, unsafe.Pointer(c))
+ }
goready(gp, 3)
}
- // release all writers
+ // release all writers (they will panic)
for {
sg := c.sendq.dequeue()
if sg == nil {
break
}
- gp := sg.g
sg.elem = nil
- gp.param = nil
if sg.releasetime != 0 {
sg.releasetime = cputicks()
}
+ gp := sg.g
+ gp.param = nil
+ if raceenabled {
+ raceacquireg(gp, unsafe.Pointer(c))
+ }
goready(gp, 3)
}
unlock(&c.lock)
// If block == false and no elements are available, returns (false, false).
// Otherwise, if c is closed, zeros *ep and returns (true, false).
// Otherwise, fills in *ep with an element and returns (true, true).
+// A non-nil ep must point to the heap or the caller's stack.
func chanrecv(t *chantype, c *hchan, ep unsafe.Pointer, block bool) (selected, received bool) {
- // raceenabled: don't need to check ep, as it is always on the stack.
+ // raceenabled: don't need to check ep, as it is always on the stack
+ // or is new memory allocated by reflect.
if debugChan {
print("chanrecv: chan=", c, "\n")
// The order of operations is important here: reversing the operations can lead to
// incorrect behavior when racing with a close.
if !block && (c.dataqsiz == 0 && c.sendq.first == nil ||
- c.dataqsiz > 0 && atomicloaduint(&c.qcount) == 0) &&
- atomicload(&c.closed) == 0 {
+ c.dataqsiz > 0 && atomic.Loaduint(&c.qcount) == 0) &&
+ atomic.Load(&c.closed) == 0 {
return
}
}
lock(&c.lock)
- if c.dataqsiz == 0 { // synchronous channel
- if c.closed != 0 {
- return recvclosed(c, ep)
- }
-
- sg := c.sendq.dequeue()
- if sg != nil {
- if raceenabled {
- racesync(c, sg)
- }
- unlock(&c.lock)
-
- if ep != nil {
- typedmemmove(c.elemtype, ep, sg.elem)
- }
- sg.elem = nil
- gp := sg.g
- gp.param = unsafe.Pointer(sg)
- if sg.releasetime != 0 {
- sg.releasetime = cputicks()
- }
- goready(gp, 3)
- selected = true
- received = true
- return
- }
-
- if !block {
- unlock(&c.lock)
- return
- }
-
- // no sender available: block on this channel.
- gp := getg()
- mysg := acquireSudog()
- mysg.releasetime = 0
- if t0 != 0 {
- mysg.releasetime = -1
- }
- mysg.elem = ep
- mysg.waitlink = nil
- gp.waiting = mysg
- mysg.g = gp
- mysg.selectdone = nil
- gp.param = nil
- c.recvq.enqueue(mysg)
- goparkunlock(&c.lock, "chan receive", traceEvGoBlockRecv, 3)
- // someone woke us up
- if mysg != gp.waiting {
- throw("G waiting list is corrupted!")
+ if c.closed != 0 && c.qcount == 0 {
+ if raceenabled {
+ raceacquire(unsafe.Pointer(c))
}
- gp.waiting = nil
- if mysg.releasetime > 0 {
- blockevent(mysg.releasetime-t0, 2)
- }
- haveData := gp.param != nil
- gp.param = nil
- releaseSudog(mysg)
-
- if haveData {
- // a sender sent us some data. It already wrote to ep.
- selected = true
- received = true
- return
- }
-
- lock(&c.lock)
- if c.closed == 0 {
- throw("chanrecv: spurious wakeup")
+ unlock(&c.lock)
+ if ep != nil {
+ memclr(ep, uintptr(c.elemsize))
}
- return recvclosed(c, ep)
+ return true, false
}
- // asynchronous channel
- // wait for some data to appear
- var t1 int64
- for futile := byte(0); c.qcount <= 0; futile = traceFutileWakeup {
- if c.closed != 0 {
- selected, received = recvclosed(c, ep)
- if t1 > 0 {
- blockevent(t1-t0, 2)
- }
- return
- }
+ if sg := c.sendq.dequeue(); sg != nil {
+ // Found a waiting sender. If buffer is size 0, receive value
+ // directly from sender. Otherwise, recieve from head of queue
+ // and add sender's value to the tail of the queue (both map to
+ // the same buffer slot because the queue is full).
+ recv(c, sg, ep, func() { unlock(&c.lock) })
+ return true, true
+ }
- if !block {
- unlock(&c.lock)
- return
+ if c.qcount > 0 {
+ // Receive directly from queue
+ qp := chanbuf(c, c.recvx)
+ if raceenabled {
+ raceacquire(qp)
+ racerelease(qp)
}
-
- // wait for someone to send an element
- gp := getg()
- mysg := acquireSudog()
- mysg.releasetime = 0
- if t0 != 0 {
- mysg.releasetime = -1
+ if ep != nil {
+ typedmemmove(c.elemtype, ep, qp)
}
- mysg.elem = nil
- mysg.g = gp
- mysg.selectdone = nil
-
- c.recvq.enqueue(mysg)
- goparkunlock(&c.lock, "chan receive", traceEvGoBlockRecv|futile, 3)
-
- // someone woke us up - try again
- if mysg.releasetime > 0 {
- t1 = mysg.releasetime
+ memclr(qp, uintptr(c.elemsize))
+ c.recvx++
+ if c.recvx == c.dataqsiz {
+ c.recvx = 0
}
- releaseSudog(mysg)
- lock(&c.lock)
- }
-
- if raceenabled {
- raceacquire(chanbuf(c, c.recvx))
- racerelease(chanbuf(c, c.recvx))
- }
- if ep != nil {
- typedmemmove(c.elemtype, ep, chanbuf(c, c.recvx))
- }
- memclr(chanbuf(c, c.recvx), uintptr(c.elemsize))
-
- c.recvx++
- if c.recvx == c.dataqsiz {
- c.recvx = 0
- }
- c.qcount--
-
- // ping a sender now that there is space
- sg := c.sendq.dequeue()
- if sg != nil {
- gp := sg.g
- unlock(&c.lock)
- if sg.releasetime != 0 {
- sg.releasetime = cputicks()
- }
- goready(gp, 3)
- } else {
+ c.qcount--
unlock(&c.lock)
+ return true, true
}
- if t1 > 0 {
- blockevent(t1-t0, 2)
- }
- selected = true
- received = true
- return
+ if !block {
+ unlock(&c.lock)
+ return false, false
+ }
+
+ // no sender available: block on this channel.
+ gp := getg()
+ mysg := acquireSudog()
+ mysg.releasetime = 0
+ if t0 != 0 {
+ mysg.releasetime = -1
+ }
+ mysg.elem = ep
+ mysg.waitlink = nil
+ gp.waiting = mysg
+ mysg.g = gp
+ mysg.selectdone = nil
+ gp.param = nil
+ c.recvq.enqueue(mysg)
+ goparkunlock(&c.lock, "chan receive", traceEvGoBlockRecv, 3)
+
+ // someone woke us up
+ if mysg != gp.waiting {
+ throw("G waiting list is corrupted")
+ }
+ gp.waiting = nil
+ if mysg.releasetime > 0 {
+ blockevent(mysg.releasetime-t0, 2)
+ }
+ closed := gp.param == nil
+ gp.param = nil
+ releaseSudog(mysg)
+ return true, !closed
}
-// recvclosed is a helper function for chanrecv. Handles cleanup
-// when the receiver encounters a closed channel.
-// Caller must hold c.lock, recvclosed will release the lock.
-func recvclosed(c *hchan, ep unsafe.Pointer) (selected, recevied bool) {
- if raceenabled {
- raceacquire(unsafe.Pointer(c))
+// recv processes a receive operation on a full channel c.
+// There are 2 parts:
+// 1) The value sent by the sender sg is put into the channel
+// and the sender is woken up to go on its merry way.
+// 2) The value received by the receiver (the current G) is
+// written to ep.
+// For synchronous channels, both values are the same.
+// For asynchronous channels, the receiver gets its data from
+// the channel buffer and the sender's data is put in the
+// channel buffer.
+// Channel c must be full and locked. recv unlocks c with unlockf.
+// sg must already be dequeued from c.
+// A non-nil ep must point to the heap or the caller's stack.
+func recv(c *hchan, sg *sudog, ep unsafe.Pointer, unlockf func()) {
+ if c.dataqsiz == 0 {
+ if raceenabled {
+ racesync(c, sg)
+ }
+ unlockf()
+ if ep != nil {
+ // copy data from sender
+ // ep points to our own stack or heap, so nothing
+ // special (ala sendDirect) needed here.
+ typedmemmove(c.elemtype, ep, sg.elem)
+ }
+ } else {
+ // Queue is full. Take the item at the
+ // head of the queue. Make the sender enqueue
+ // its item at the tail of the queue. Since the
+ // queue is full, those are both the same slot.
+ qp := chanbuf(c, c.recvx)
+ if raceenabled {
+ raceacquire(qp)
+ racerelease(qp)
+ raceacquireg(sg.g, qp)
+ racereleaseg(sg.g, qp)
+ }
+ // copy data from queue to receiver
+ if ep != nil {
+ typedmemmove(c.elemtype, ep, qp)
+ }
+ // copy data from sender to queue
+ typedmemmove(c.elemtype, qp, sg.elem)
+ c.recvx++
+ if c.recvx == c.dataqsiz {
+ c.recvx = 0
+ }
+ c.sendx = c.recvx // c.sendx = (c.sendx+1) % c.dataqsiz
+ unlockf()
}
- unlock(&c.lock)
- if ep != nil {
- memclr(ep, uintptr(c.elemsize))
+ sg.elem = nil
+ gp := sg.g
+ gp.param = unsafe.Pointer(sg)
+ if sg.releasetime != 0 {
+ sg.releasetime = cputicks()
}
- return true, false
+ goready(gp, 4)
}
// compiler implements
// if sgp participates in a select and is already signaled, ignore it
if sgp.selectdone != nil {
// claim the right to signal
- if *sgp.selectdone != 0 || !cas(sgp.selectdone, 0, 1) {
+ if *sgp.selectdone != 0 || !atomic.Cas(sgp.selectdone, 0, 1) {
continue
}
}
package runtime
-import "unsafe"
+import (
+ "runtime/internal/atomic"
+ "unsafe"
+)
const (
numBuckets = 1 << 10
if n&0x80000000 != 0 {
print("runtime: setcpuprofile(off) twice\n")
}
- if cas(&cpuprof.handoff, n, n|0x80000000) {
+ if atomic.Cas(&cpuprof.handoff, n, n|0x80000000) {
if n == 0 {
// we did the transition from 0 -> nonzero so we wake getprofile
notewakeup(&cpuprof.wait)
// so it cannot allocate memory or block. It can try to swap logs with
// the writing goroutine, as explained in the comment at the top of this file.
func (p *cpuProfile) flushlog() bool {
- if !cas(&p.handoff, 0, uint32(p.nlog)) {
+ if !atomic.Cas(&p.handoff, 0, uint32(p.nlog)) {
return false
}
notewakeup(&p.wait)
p.flushing = true
goto Flush
}
- if cas(&p.handoff, n, 0) {
+ if atomic.Cas(&p.handoff, n, 0) {
break
}
}
// Finally done. Clean up and return nil.
p.flushing = false
- if !cas(&p.handoff, p.handoff, 0) {
+ if !atomic.Cas(&p.handoff, p.handoff, 0) {
print("runtime: profile flush racing with something\n")
}
return nil
// +build !arm
// +build !arm64
+// +build !mips64
+// +build !mips64le
package runtime
}
}
}
- if runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" {
+ if runtime.GOARCH == "ppc64" {
// TODO(austin) External linking not implemented on
// ppc64 (issue #8912)
t.Skipf("no external linking on ppc64")
package runtime
-import "unsafe"
+import (
+ "runtime/internal/atomic"
+ "unsafe"
+)
// GOMAXPROCS sets the maximum number of CPUs that can be executing
// simultaneously and returns the previous setting. If n < 1, it does not
// NumCgoCall returns the number of cgo calls made by the current process.
func NumCgoCall() int64 {
var n int64
- for mp := (*m)(atomicloadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink {
+ for mp := (*m)(atomic.Loadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink {
n += int64(mp.ncgocall)
}
return n
var big = make([]byte, 1<<20)
func TestFreeOSMemory(t *testing.T) {
- if runtime.GOARCH == "arm64" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" ||
+ if runtime.GOARCH == "arm64" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "mips64" || runtime.GOARCH == "mips64le" ||
runtime.GOOS == "nacl" {
t.Skip("issue 9993; scavenger temporarily disabled on systems with physical pages larger than logical pages")
}
_EPOLL_CTL_ADD = 0x1
_EPOLL_CTL_DEL = 0x2
_EPOLL_CTL_MOD = 0x3
+
+ _AF_UNIX = 0x1
+ _F_SETFL = 0x4
+ _SOCK_DGRAM = 0x2
)
type timespec struct {
fpstate *fpstate1
__reserved1 [8]uint64
}
+
+type sockaddr_un struct {
+ family uint16
+ path [108]byte
+}
--- /dev/null
+// +build mips64 mips64le
+// +build linux
+
+package runtime
+
+const (
+ _EINTR = 0x4
+ _EAGAIN = 0xb
+ _ENOMEM = 0xc
+
+ _PROT_NONE = 0x0
+ _PROT_READ = 0x1
+ _PROT_WRITE = 0x2
+ _PROT_EXEC = 0x4
+
+ _MAP_ANON = 0x800
+ _MAP_PRIVATE = 0x2
+ _MAP_FIXED = 0x10
+
+ _MADV_DONTNEED = 0x4
+ _MADV_HUGEPAGE = 0xe
+ _MADV_NOHUGEPAGE = 0xf
+
+ _SA_RESTART = 0x10000000
+ _SA_ONSTACK = 0x8000000
+ _SA_SIGINFO = 0x8
+
+ _SIGHUP = 0x1
+ _SIGINT = 0x2
+ _SIGQUIT = 0x3
+ _SIGILL = 0x4
+ _SIGTRAP = 0x5
+ _SIGABRT = 0x6
+ _SIGEMT = 0x7
+ _SIGFPE = 0x8
+ _SIGKILL = 0x9
+ _SIGBUS = 0xa
+ _SIGSEGV = 0xb
+ _SIGSYS = 0xc
+ _SIGPIPE = 0xd
+ _SIGALRM = 0xe
+ _SIGUSR1 = 0x10
+ _SIGUSR2 = 0x11
+ _SIGCHLD = 0x12
+ _SIGPWR = 0x13
+ _SIGWINCH = 0x14
+ _SIGURG = 0x15
+ _SIGIO = 0x16
+ _SIGSTOP = 0x17
+ _SIGTSTP = 0x18
+ _SIGCONT = 0x19
+ _SIGTTIN = 0x1a
+ _SIGTTOU = 0x1b
+ _SIGVTALRM = 0x1c
+ _SIGPROF = 0x1d
+ _SIGXCPU = 0x1e
+ _SIGXFSZ = 0x1f
+
+ _FPE_INTDIV = 0x1
+ _FPE_INTOVF = 0x2
+ _FPE_FLTDIV = 0x3
+ _FPE_FLTOVF = 0x4
+ _FPE_FLTUND = 0x5
+ _FPE_FLTRES = 0x6
+ _FPE_FLTINV = 0x7
+ _FPE_FLTSUB = 0x8
+
+ _BUS_ADRALN = 0x1
+ _BUS_ADRERR = 0x2
+ _BUS_OBJERR = 0x3
+
+ _SEGV_MAPERR = 0x1
+ _SEGV_ACCERR = 0x2
+
+ _ITIMER_REAL = 0x0
+ _ITIMER_VIRTUAL = 0x1
+ _ITIMER_PROF = 0x2
+
+ _EPOLLIN = 0x1
+ _EPOLLOUT = 0x4
+ _EPOLLERR = 0x8
+ _EPOLLHUP = 0x10
+ _EPOLLRDHUP = 0x2000
+ _EPOLLET = 0x80000000
+ _EPOLL_CLOEXEC = 0x80000
+ _EPOLL_CTL_ADD = 0x1
+ _EPOLL_CTL_DEL = 0x2
+ _EPOLL_CTL_MOD = 0x3
+)
+
+//struct Sigset {
+// uint64 sig[1];
+//};
+//typedef uint64 Sigset;
+
+type timespec struct {
+ tv_sec int64
+ tv_nsec int64
+}
+
+func (ts *timespec) set_sec(x int64) {
+ ts.tv_sec = x
+}
+
+func (ts *timespec) set_nsec(x int32) {
+ ts.tv_nsec = int64(x)
+}
+
+type timeval struct {
+ tv_sec int64
+ tv_usec int64
+}
+
+func (tv *timeval) set_usec(x int32) {
+ tv.tv_usec = int64(x)
+}
+
+type sigactiont struct {
+ sa_flags uint32
+ sa_handler uintptr
+ sa_mask [2]uint64
+ // linux header does not have sa_restorer field,
+ // but it is used in setsig(). it is no harm to put it here
+ sa_restorer uintptr
+}
+
+type siginfo struct {
+ si_signo int32
+ si_code int32
+ si_errno int32
+ __pad0 [1]int32
+ // below here is a union; si_addr is the only field we use
+ si_addr uint64
+}
+
+type itimerval struct {
+ it_interval timeval
+ it_value timeval
+}
+
+type epollevent struct {
+ events uint32
+ pad_cgo_0 [4]byte
+ data [8]byte // unaligned uintptr
+}
+
+const (
+ _O_RDONLY = 0x0
+ _O_CLOEXEC = 0x80000
+ _SA_RESTORER = 0
+)
+
+type sigaltstackt struct {
+ ss_sp *byte
+ ss_size uintptr
+ ss_flags int32
+}
+
+type sigcontext struct {
+ sc_regs [32]uint64
+ sc_fpregs [32]uint64
+ sc_mdhi uint64
+ sc_hi1 uint64
+ sc_hi2 uint64
+ sc_hi3 uint64
+ sc_mdlo uint64
+ sc_lo1 uint64
+ sc_lo2 uint64
+ sc_lo3 uint64
+ sc_pc uint64
+ sc_fpc_csr uint32
+ sc_used_math uint32
+ sc_dsp uint32
+ sc_reserved uint32
+}
+
+type ucontext struct {
+ uc_flags uint64
+ uc_link *ucontext
+ uc_stack sigaltstackt
+ uc_mcontext sigcontext
+ uc_sigmask uint64
+}
--- /dev/null
+// AUTO-GENERATED by mkduff.go
+// Run go generate from src/runtime to update.
+// See mkduff.go for comments.
+
+// +build mips64 mips64le
+
+#include "textflag.h"
+
+TEXT runtime·duffzero(SB), NOSPLIT, $-8-0
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ MOVV R0, 8(R1)
+ ADDV $8, R1
+ RET
+
+// TODO: Implement runtime·duffcopy.
}
var s string
- sp := (*_string)(unsafe.Pointer(&s))
- sp.str = &p[0]
+ sp := stringStructOf(&s)
+ sp.str = unsafe.Pointer(&p[0])
sp.len = int(r)
return s
}
func cstring(s string) unsafe.Pointer {
p := make([]byte, len(s)+1)
- sp := (*_string)(unsafe.Pointer(&s))
- memmove(unsafe.Pointer(&p[0]), unsafe.Pointer(sp.str), uintptr(len(s)))
+ copy(p, s)
return unsafe.Pointer(&p[0])
}
package runtime
-import "unsafe"
-
// The Error interface identifies a run time error.
type Error interface {
error
}
func typestring(x interface{}) string {
- e := (*eface)(unsafe.Pointer(&x))
+ e := efaceOf(&x)
return *e._type._string
}
package runtime
-import "unsafe"
+import (
+ "runtime/internal/atomic"
+ "runtime/internal/sys"
+ "unsafe"
+)
var Fadd64 = fadd64
var Fsub64 = fsub64
var Entersyscall = entersyscall
var Exitsyscall = exitsyscall
var LockedOSThread = lockedOSThread
-var Xadduintptr = xadduintptr
+var Xadduintptr = atomic.Xadduintptr
var FuncPC = funcPC
var Gostringnocopy = gostringnocopy
var Maxstring = &maxstring
-type Uintreg uintreg
+type Uintreg sys.Uintreg
var Open = open
var Close = closefd
func Envs() []string { return envs }
func SetEnvs(e []string) { envs = e }
-var BigEndian = _BigEndian
+var BigEndian = sys.BigEndian
// For benchmarking.
func BenchSetType(n int, x interface{}) {
- e := *(*eface)(unsafe.Pointer(&x))
+ e := *efaceOf(&x)
t := e._type
var size uintptr
var p unsafe.Pointer
})
}
-const PtrSize = ptrSize
+const PtrSize = sys.PtrSize
var TestingAssertE2I2GC = &testingAssertE2I2GC
var TestingAssertE2T2GC = &testingAssertE2T2GC
package runtime
+import "unsafe"
+
var (
TestingWER = &testingWER
TimeBeginPeriodRetValue = &timeBeginPeriodRetValue
)
+
+func NumberOfProcessors() int32 {
+ var info systeminfo
+ stdcall1(_GetSystemInfo, uintptr(unsafe.Pointer(&info)))
+ return int32(info.dwnumberofprocessors)
+}
allocfreetrace: setting allocfreetrace=1 causes every allocation to be
profiled and a stack trace printed on each object's allocation and free.
+ cgocheck: setting cgocheck=0 disables all checks for packages
+ using cgo to incorrectly pass Go pointers to non-Go code.
+ Setting cgocheck=1 (the default) enables relatively cheap
+ checks that may miss some errors. Setting cgocheck=2 enables
+ expensive checks that should not miss any errors, but will
+ cause your program to run slower.
+
efence: setting efence=1 causes the allocator to run in a mode
where each object is allocated on a unique page and addresses are
never recycled.
The GOTRACEBACK variable controls the amount of output generated when a Go
program fails due to an unrecovered panic or an unexpected runtime condition.
-By default, a failure prints a stack trace for every extant goroutine, eliding functions
-internal to the run-time system, and then exits with exit code 2.
-If GOTRACEBACK=0, the per-goroutine stack traces are omitted entirely.
-If GOTRACEBACK=1, the default behavior is used.
-If GOTRACEBACK=2, the per-goroutine stack traces include run-time functions.
-If GOTRACEBACK=crash, the per-goroutine stack traces include run-time functions,
-and if possible the program crashes in an operating-specific manner instead of
-exiting. For example, on Unix systems, the program raises SIGABRT to trigger a
-core dump.
+By default, a failure prints a stack trace for the current goroutine,
+eliding functions internal to the run-time system, and then exits with exit code 2.
+The failure prints stack traces for all goroutines if there is no current goroutine
+or the failure is internal to the run-time.
+GOTRACEBACK=none omits the goroutine stack traces entirely.
+GOTRACEBACK=single (the default) behaves as described above.
+GOTRACEBACK=all adds stack traces for all user-created goroutines.
+GOTRACEBACK=system is like ``all'' but adds stack frames for run-time functions
+and shows goroutines created internally by the run-time.
+GOTRACEBACK=crash is like ``system'' but crashes in an operating system-specific
+manner instead of exiting. For example, on Unix systems, the crash raises
+SIGABRT to trigger a core dump.
+For historical reasons, the GOTRACEBACK settings 0, 1, and 2 are synonyms for
+none, all, and system, respectively.
The GOARCH, GOOS, GOPATH, and GOROOT environment variables complete
the set of Go environment variables. They influence the building of Go programs
*/
package runtime
+import "runtime/internal/sys"
+
// Caller reports file and line number information about function invocations on
// the calling goroutine's stack. The argument skip is the number of stack frames
// to ascend, with 0 identifying the caller of Caller. (For historical reasons the
if s != "" {
return s
}
- return defaultGoroot
+ return sys.DefaultGoroot
}
// Version returns the Go tree's version string.
// It is either the commit hash and date at the time of the build or,
// when possible, a release tag like "go1.3".
func Version() string {
- return theVersion
+ return sys.TheVersion
}
// GOOS is the running program's operating system target:
// one of darwin, freebsd, linux, and so on.
-const GOOS string = theGoos
+const GOOS string = sys.TheGoos
// GOARCH is the running program's architecture target:
// 386, amd64, or arm.
-const GOARCH string = theGoarch
+const GOARCH string = sys.TheGoarch
testIfaceEqual(io.EOF)
}
+var a bool
+
+//go:noinline
func testIfaceEqual(x interface{}) {
if x == "abc" {
- // Prevent inlining
- panic("")
+ a = true
}
}
typeScalar, typeScalar, typeScalar, typeScalar, // t int; y uint16; u uint64
typePointer, typeScalar, // i string
}
- case "arm64", "amd64", "ppc64", "ppc64le":
+ case "arm64", "amd64", "mips64", "mips64le", "ppc64", "ppc64le":
return []byte{
typePointer, // q *int
typeScalar, typeScalar, typeScalar, // w byte; e [17]byte
// xxhash: https://code.google.com/p/xxhash/
// cityhash: https://code.google.com/p/cityhash/
-// +build amd64 amd64p32 arm64 ppc64 ppc64le
+// +build amd64 amd64p32 arm64 mips64 mips64le ppc64 ppc64le
package runtime
// before the table grows. Typical tables will be somewhat less loaded.
import (
+ "runtime/internal/atomic"
+ "runtime/internal/sys"
"unsafe"
)
oldIterator = 2 // there may be an iterator using oldbuckets
// sentinel bucket ID for iterator checks
- noCheck = 1<<(8*ptrSize) - 1
+ noCheck = 1<<(8*sys.PtrSize) - 1
)
// A header for a Go map.
}
func (b *bmap) overflow(t *maptype) *bmap {
- return *(**bmap)(add(unsafe.Pointer(b), uintptr(t.bucketsize)-ptrSize))
+ return *(**bmap)(add(unsafe.Pointer(b), uintptr(t.bucketsize)-sys.PtrSize))
}
func (h *hmap) setoverflow(t *maptype, b, ovf *bmap) {
h.createOverflow()
*h.overflow[0] = append(*h.overflow[0], ovf)
}
- *(**bmap)(add(unsafe.Pointer(b), uintptr(t.bucketsize)-ptrSize)) = ovf
+ *(**bmap)(add(unsafe.Pointer(b), uintptr(t.bucketsize)-sys.PtrSize)) = ovf
}
func (h *hmap) createOverflow() {
}
// check compiler's and reflect's math
- if t.key.size > maxKeySize && (!t.indirectkey || t.keysize != uint8(ptrSize)) ||
+ if t.key.size > maxKeySize && (!t.indirectkey || t.keysize != uint8(sys.PtrSize)) ||
t.key.size <= maxKeySize && (t.indirectkey || t.keysize != uint8(t.key.size)) {
throw("key size wrong")
}
- if t.elem.size > maxValueSize && (!t.indirectvalue || t.valuesize != uint8(ptrSize)) ||
+ if t.elem.size > maxValueSize && (!t.indirectvalue || t.valuesize != uint8(sys.PtrSize)) ||
t.elem.size <= maxValueSize && (t.indirectvalue || t.valuesize != uint8(t.elem.size)) {
throw("value size wrong")
}
racereadpc(unsafe.Pointer(h), callerpc, pc)
raceReadObjectPC(t.key, key, callerpc, pc)
}
+ if msanenabled && h != nil {
+ msanread(key, t.key.size)
+ }
if h == nil || h.count == 0 {
- return atomicloadp(unsafe.Pointer(&zeroptr))
+ return atomic.Loadp(unsafe.Pointer(&zeroptr))
}
alg := t.key.alg
hash := alg.hash(key, uintptr(h.hash0))
b = oldb
}
}
- top := uint8(hash >> (ptrSize*8 - 8))
+ top := uint8(hash >> (sys.PtrSize*8 - 8))
if top < minTopHash {
top += minTopHash
}
}
b = b.overflow(t)
if b == nil {
- return atomicloadp(unsafe.Pointer(&zeroptr))
+ return atomic.Loadp(unsafe.Pointer(&zeroptr))
}
}
}
racereadpc(unsafe.Pointer(h), callerpc, pc)
raceReadObjectPC(t.key, key, callerpc, pc)
}
+ if msanenabled && h != nil {
+ msanread(key, t.key.size)
+ }
if h == nil || h.count == 0 {
- return atomicloadp(unsafe.Pointer(&zeroptr)), false
+ return atomic.Loadp(unsafe.Pointer(&zeroptr)), false
}
alg := t.key.alg
hash := alg.hash(key, uintptr(h.hash0))
b = oldb
}
}
- top := uint8(hash >> (ptrSize*8 - 8))
+ top := uint8(hash >> (sys.PtrSize*8 - 8))
if top < minTopHash {
top += minTopHash
}
}
b = b.overflow(t)
if b == nil {
- return atomicloadp(unsafe.Pointer(&zeroptr)), false
+ return atomic.Loadp(unsafe.Pointer(&zeroptr)), false
}
}
}
b = oldb
}
}
- top := uint8(hash >> (ptrSize*8 - 8))
+ top := uint8(hash >> (sys.PtrSize*8 - 8))
if top < minTopHash {
top += minTopHash
}
raceReadObjectPC(t.key, key, callerpc, pc)
raceReadObjectPC(t.elem, val, callerpc, pc)
}
+ if msanenabled {
+ msanread(key, t.key.size)
+ msanread(val, t.elem.size)
+ }
alg := t.key.alg
hash := alg.hash(key, uintptr(h.hash0))
growWork(t, h, bucket)
}
b := (*bmap)(unsafe.Pointer(uintptr(h.buckets) + bucket*uintptr(t.bucketsize)))
- top := uint8(hash >> (ptrSize*8 - 8))
+ top := uint8(hash >> (sys.PtrSize*8 - 8))
if top < minTopHash {
top += minTopHash
}
racewritepc(unsafe.Pointer(h), callerpc, pc)
raceReadObjectPC(t.key, key, callerpc, pc)
}
+ if msanenabled && h != nil {
+ msanread(key, t.key.size)
+ }
if h == nil || h.count == 0 {
return
}
growWork(t, h, bucket)
}
b := (*bmap)(unsafe.Pointer(uintptr(h.buckets) + bucket*uintptr(t.bucketsize)))
- top := uint8(hash >> (ptrSize*8 - 8))
+ top := uint8(hash >> (sys.PtrSize*8 - 8))
if top < minTopHash {
top += minTopHash
}
return
}
- if unsafe.Sizeof(hiter{})/ptrSize != 12 {
+ if unsafe.Sizeof(hiter{})/sys.PtrSize != 12 {
throw("hash_iter size incorrect") // see ../../cmd/internal/gc/reflect.go
}
it.t = t
// Remember we have an iterator.
// Can run concurrently with another hash_iter_init().
if old := h.flags; old&(iterator|oldIterator) != iterator|oldIterator {
- atomicor8(&h.flags, iterator|oldIterator)
+ atomic.Or8(&h.flags, iterator|oldIterator)
}
mapiternext(it)
} else {
hash &^= newbit
}
- top = uint8(hash >> (ptrSize*8 - 8))
+ top = uint8(hash >> (sys.PtrSize*8 - 8))
if top < minTopHash {
top += minTopHash
}
// serve as the zero value for t.
func mapzero(t *_type) {
// Is the type small enough for existing buffer?
- cursize := uintptr(atomicloadp(unsafe.Pointer(&zerosize)))
+ cursize := uintptr(atomic.Loadp(unsafe.Pointer(&zerosize)))
if t.size <= cursize {
return
}
// Allocate a new buffer.
lock(&zerolock)
- cursize = uintptr(atomicloadp(unsafe.Pointer(&zerosize)))
+ cursize = uintptr(atomic.Loadp(unsafe.Pointer(&zerosize)))
if cursize < t.size {
for cursize < t.size {
cursize *= 2
throw("map element too large")
}
}
- atomicstorep1(unsafe.Pointer(&zeroptr), persistentalloc(cursize, 64, &memstats.other_sys))
- atomicstorep1(unsafe.Pointer(&zerosize), unsafe.Pointer(zerosize))
+ atomic.Storep1(unsafe.Pointer(&zeroptr), persistentalloc(cursize, 64, &memstats.other_sys))
+ atomic.Storep1(unsafe.Pointer(&zerosize), unsafe.Pointer(zerosize))
}
unlock(&zerolock)
}
package runtime
import (
+ "runtime/internal/atomic"
+ "runtime/internal/sys"
"unsafe"
)
racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapaccess1_fast32))
}
if h == nil || h.count == 0 {
- return atomicloadp(unsafe.Pointer(&zeroptr))
+ return atomic.Loadp(unsafe.Pointer(&zeroptr))
}
var b *bmap
if h.B == 0 {
}
b = b.overflow(t)
if b == nil {
- return atomicloadp(unsafe.Pointer(&zeroptr))
+ return atomic.Loadp(unsafe.Pointer(&zeroptr))
}
}
}
racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapaccess2_fast32))
}
if h == nil || h.count == 0 {
- return atomicloadp(unsafe.Pointer(&zeroptr)), false
+ return atomic.Loadp(unsafe.Pointer(&zeroptr)), false
}
var b *bmap
if h.B == 0 {
}
b = b.overflow(t)
if b == nil {
- return atomicloadp(unsafe.Pointer(&zeroptr)), false
+ return atomic.Loadp(unsafe.Pointer(&zeroptr)), false
}
}
}
racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapaccess1_fast64))
}
if h == nil || h.count == 0 {
- return atomicloadp(unsafe.Pointer(&zeroptr))
+ return atomic.Loadp(unsafe.Pointer(&zeroptr))
}
var b *bmap
if h.B == 0 {
}
b = b.overflow(t)
if b == nil {
- return atomicloadp(unsafe.Pointer(&zeroptr))
+ return atomic.Loadp(unsafe.Pointer(&zeroptr))
}
}
}
racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapaccess2_fast64))
}
if h == nil || h.count == 0 {
- return atomicloadp(unsafe.Pointer(&zeroptr)), false
+ return atomic.Loadp(unsafe.Pointer(&zeroptr)), false
}
var b *bmap
if h.B == 0 {
}
b = b.overflow(t)
if b == nil {
- return atomicloadp(unsafe.Pointer(&zeroptr)), false
+ return atomic.Loadp(unsafe.Pointer(&zeroptr)), false
}
}
}
racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapaccess1_faststr))
}
if h == nil || h.count == 0 {
- return atomicloadp(unsafe.Pointer(&zeroptr))
+ return atomic.Loadp(unsafe.Pointer(&zeroptr))
}
- key := (*stringStruct)(unsafe.Pointer(&ky))
+ key := stringStructOf(&ky)
if h.B == 0 {
// One-bucket table.
b := (*bmap)(h.buckets)
if x == empty {
continue
}
- k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+i*2*ptrSize))
+ k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+i*2*sys.PtrSize))
if k.len != key.len {
continue
}
if k.str == key.str || memeq(k.str, key.str, uintptr(key.len)) {
- return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*ptrSize+i*uintptr(t.valuesize))
+ return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*sys.PtrSize+i*uintptr(t.valuesize))
}
}
- return atomicloadp(unsafe.Pointer(&zeroptr))
+ return atomic.Loadp(unsafe.Pointer(&zeroptr))
}
// long key, try not to do more comparisons than necessary
keymaybe := uintptr(bucketCnt)
if x == empty {
continue
}
- k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+i*2*ptrSize))
+ k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+i*2*sys.PtrSize))
if k.len != key.len {
continue
}
if k.str == key.str {
- return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*ptrSize+i*uintptr(t.valuesize))
+ return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*sys.PtrSize+i*uintptr(t.valuesize))
}
// check first 4 bytes
// TODO: on amd64/386 at least, make this compile to one 4-byte comparison instead of
keymaybe = i
}
if keymaybe != bucketCnt {
- k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+keymaybe*2*ptrSize))
+ k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+keymaybe*2*sys.PtrSize))
if memeq(k.str, key.str, uintptr(key.len)) {
- return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*ptrSize+keymaybe*uintptr(t.valuesize))
+ return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*sys.PtrSize+keymaybe*uintptr(t.valuesize))
}
}
- return atomicloadp(unsafe.Pointer(&zeroptr))
+ return atomic.Loadp(unsafe.Pointer(&zeroptr))
}
dohash:
hash := t.key.alg.hash(noescape(unsafe.Pointer(&ky)), uintptr(h.hash0))
b = oldb
}
}
- top := uint8(hash >> (ptrSize*8 - 8))
+ top := uint8(hash >> (sys.PtrSize*8 - 8))
if top < minTopHash {
top += minTopHash
}
if x != top {
continue
}
- k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+i*2*ptrSize))
+ k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+i*2*sys.PtrSize))
if k.len != key.len {
continue
}
if k.str == key.str || memeq(k.str, key.str, uintptr(key.len)) {
- return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*ptrSize+i*uintptr(t.valuesize))
+ return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*sys.PtrSize+i*uintptr(t.valuesize))
}
}
b = b.overflow(t)
if b == nil {
- return atomicloadp(unsafe.Pointer(&zeroptr))
+ return atomic.Loadp(unsafe.Pointer(&zeroptr))
}
}
}
racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapaccess2_faststr))
}
if h == nil || h.count == 0 {
- return atomicloadp(unsafe.Pointer(&zeroptr)), false
+ return atomic.Loadp(unsafe.Pointer(&zeroptr)), false
}
- key := (*stringStruct)(unsafe.Pointer(&ky))
+ key := stringStructOf(&ky)
if h.B == 0 {
// One-bucket table.
b := (*bmap)(h.buckets)
if x == empty {
continue
}
- k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+i*2*ptrSize))
+ k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+i*2*sys.PtrSize))
if k.len != key.len {
continue
}
if k.str == key.str || memeq(k.str, key.str, uintptr(key.len)) {
- return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*ptrSize+i*uintptr(t.valuesize)), true
+ return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*sys.PtrSize+i*uintptr(t.valuesize)), true
}
}
- return atomicloadp(unsafe.Pointer(&zeroptr)), false
+ return atomic.Loadp(unsafe.Pointer(&zeroptr)), false
}
// long key, try not to do more comparisons than necessary
keymaybe := uintptr(bucketCnt)
if x == empty {
continue
}
- k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+i*2*ptrSize))
+ k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+i*2*sys.PtrSize))
if k.len != key.len {
continue
}
if k.str == key.str {
- return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*ptrSize+i*uintptr(t.valuesize)), true
+ return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*sys.PtrSize+i*uintptr(t.valuesize)), true
}
// check first 4 bytes
if *((*[4]byte)(key.str)) != *((*[4]byte)(k.str)) {
keymaybe = i
}
if keymaybe != bucketCnt {
- k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+keymaybe*2*ptrSize))
+ k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+keymaybe*2*sys.PtrSize))
if memeq(k.str, key.str, uintptr(key.len)) {
- return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*ptrSize+keymaybe*uintptr(t.valuesize)), true
+ return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*sys.PtrSize+keymaybe*uintptr(t.valuesize)), true
}
}
- return atomicloadp(unsafe.Pointer(&zeroptr)), false
+ return atomic.Loadp(unsafe.Pointer(&zeroptr)), false
}
dohash:
hash := t.key.alg.hash(noescape(unsafe.Pointer(&ky)), uintptr(h.hash0))
b = oldb
}
}
- top := uint8(hash >> (ptrSize*8 - 8))
+ top := uint8(hash >> (sys.PtrSize*8 - 8))
if top < minTopHash {
top += minTopHash
}
if x != top {
continue
}
- k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+i*2*ptrSize))
+ k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+i*2*sys.PtrSize))
if k.len != key.len {
continue
}
if k.str == key.str || memeq(k.str, key.str, uintptr(key.len)) {
- return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*ptrSize+i*uintptr(t.valuesize)), true
+ return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*sys.PtrSize+i*uintptr(t.valuesize)), true
}
}
b = b.overflow(t)
if b == nil {
- return atomicloadp(unsafe.Pointer(&zeroptr)), false
+ return atomic.Loadp(unsafe.Pointer(&zeroptr)), false
}
}
}
package runtime
-import "unsafe"
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
//go:linkname runtime_debug_WriteHeapDump runtime/debug.WriteHeapDump
func runtime_debug_WriteHeapDump(fd uintptr) {
}
func dumpstr(s string) {
- sp := (*stringStruct)(unsafe.Pointer(&s))
+ sp := stringStructOf(&s)
dumpmemrange(sp.str, uintptr(sp.len))
}
if t.x == nil || t.x.pkgpath == nil || t.x.name == nil {
dumpstr(*t._string)
} else {
- pkgpath := (*stringStruct)(unsafe.Pointer(&t.x.pkgpath))
- name := (*stringStruct)(unsafe.Pointer(&t.x.name))
+ pkgpath := stringStructOf(t.x.pkgpath)
+ name := stringStructOf(t.x.name)
dumpint(uint64(uintptr(pkgpath.len) + 1 + uintptr(name.len)))
dwrite(pkgpath.str, uintptr(pkgpath.len))
dwritebyte('.')
for i := uintptr(0); i < uintptr(bv.n); i++ {
if bv.bytedata[i/8]>>(i%8)&1 == 1 {
dumpint(fieldKindPtr)
- dumpint(uint64(offset + i*ptrSize))
+ dumpint(uint64(offset + i*sys.PtrSize))
}
}
}
if pc != f.entry {
pc--
}
- pcdata := pcdatavalue(f, _PCDATA_StackMapIndex, pc)
+ pcdata := pcdatavalue(f, _PCDATA_StackMapIndex, pc, nil)
if pcdata == -1 {
// We do not have a valid pcdata value but there might be a
// stackmap for this function. It is likely that we are looking
var bv bitvector
if stkmap != nil && stkmap.n > 0 {
bv = stackmapdata(stkmap, pcdata)
- dumpbvtypes(&bv, unsafe.Pointer(s.varp-uintptr(bv.n*ptrSize)))
+ dumpbvtypes(&bv, unsafe.Pointer(s.varp-uintptr(bv.n*sys.PtrSize)))
} else {
bv.n = -1
}
dumpbv(&child.args, child.argoff)
} else {
// conservative - everything might be a pointer
- for off := child.argoff; off < child.argoff+child.arglen; off += ptrSize {
+ for off := child.argoff; off < child.argoff+child.arglen; off += sys.PtrSize {
dumpint(fieldKindPtr)
dumpint(uint64(off))
}
// Dump fields in the local vars section
if stkmap == nil {
// No locals information, dump everything.
- for off := child.arglen; off < s.varp-s.sp; off += ptrSize {
+ for off := child.arglen; off < s.varp-s.sp; off += sys.PtrSize {
dumpint(fieldKindPtr)
dumpint(uint64(off))
}
} else if stkmap.n < 0 {
// Locals size information, dump just the locals.
size := uintptr(-stkmap.n)
- for off := s.varp - size - s.sp; off < s.varp-s.sp; off += ptrSize {
+ for off := s.varp - size - s.sp; off < s.varp-s.sp; off += sys.PtrSize {
dumpint(fieldKindPtr)
dumpint(uint64(off))
}
} else if stkmap.n > 0 {
// Locals bitmap information, scan just the pointers in
// locals.
- dumpbv(&bv, s.varp-uintptr(bv.n)*ptrSize-s.sp)
+ dumpbv(&bv, s.varp-uintptr(bv.n)*sys.PtrSize-s.sp)
}
dumpint(fieldKindEol)
dumpint(tagPanic)
dumpint(uint64(uintptr(unsafe.Pointer(p))))
dumpint(uint64(uintptr(unsafe.Pointer(gp))))
- eface := (*eface)(unsafe.Pointer(&p.arg))
+ eface := efaceOf(&p.arg)
dumpint(uint64(uintptr(unsafe.Pointer(eface._type))))
dumpint(uint64(uintptr(unsafe.Pointer(eface.data))))
dumpint(0) // was p->defer, no longer recorded
} else {
dumpbool(true) // big-endian ptrs
}
- dumpint(ptrSize)
+ dumpint(sys.PtrSize)
dumpint(uint64(mheap_.arena_start))
dumpint(uint64(mheap_.arena_used))
- dumpint(thechar)
- dumpstr(goexperiment)
+ dumpint(sys.TheChar)
+ dumpstr(sys.Goexperiment)
dumpint(uint64(ncpu))
}
for i := uintptr(0); i < uintptr(mheap_.nspan); i++ {
s := h_allspans[i]
if s.state == _MSpanInUse {
- mSpan_EnsureSwept(s)
+ s.ensureSwept()
}
}
memclr(unsafe.Pointer(&typecache), unsafe.Sizeof(typecache))
func makeheapobjbv(p uintptr, size uintptr) bitvector {
// Extend the temp buffer if necessary.
- nptr := size / ptrSize
+ nptr := size / sys.PtrSize
if uintptr(len(tmpbuf)) < nptr/8+1 {
if tmpbuf != nil {
sysFree(unsafe.Pointer(&tmpbuf[0]), uintptr(len(tmpbuf)), &memstats.other_sys)
package runtime
-import "unsafe"
+import (
+ "runtime/internal/atomic"
+ "runtime/internal/sys"
+ "unsafe"
+)
const (
hashSize = 1009
hash [hashSize]*itab
)
-// fInterface is our standard non-empty interface. We use it instead
-// of interface{f()} in function prototypes because gofmt insists on
-// putting lots of newlines in the otherwise concise interface{f()}.
-type fInterface interface {
- f()
-}
-
func getitab(inter *interfacetype, typ *_type, canfail bool) *itab {
if len(inter.mhdr) == 0 {
throw("internal error - misuse of itab")
if locked != 0 {
lock(&ifaceLock)
}
- for m = (*itab)(atomicloadp(unsafe.Pointer(&hash[h]))); m != nil; m = m.link {
+ for m = (*itab)(atomic.Loadp(unsafe.Pointer(&hash[h]))); m != nil; m = m.link {
if m.inter == inter && m._type == typ {
if m.bad != 0 {
m = nil
}
}
- m = (*itab)(persistentalloc(unsafe.Sizeof(itab{})+uintptr(len(inter.mhdr)-1)*ptrSize, 0, &memstats.other_sys))
+ m = (*itab)(persistentalloc(unsafe.Sizeof(itab{})+uintptr(len(inter.mhdr)-1)*sys.PtrSize, 0, &memstats.other_sys))
m.inter = inter
m._type = typ
t := &x.mhdr[j]
if t.mtyp == itype && (t.name == iname || *t.name == *iname) && t.pkgpath == ipkgpath {
if m != nil {
- *(*unsafe.Pointer)(add(unsafe.Pointer(&m.fun[0]), uintptr(k)*ptrSize)) = t.ifn
+ *(*unsafe.Pointer)(add(unsafe.Pointer(&m.fun[0]), uintptr(k)*sys.PtrSize)) = t.ifn
}
goto nextimethod
}
return tab
}
-func convT2E(t *_type, elem unsafe.Pointer, x unsafe.Pointer) (e interface{}) {
+func convT2E(t *_type, elem unsafe.Pointer, x unsafe.Pointer) (e eface) {
if raceenabled {
raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&t)), funcPC(convT2E))
}
- ep := (*eface)(unsafe.Pointer(&e))
+ if msanenabled {
+ msanread(elem, t.size)
+ }
if isDirectIface(t) {
- ep._type = t
- typedmemmove(t, unsafe.Pointer(&ep.data), elem)
+ e._type = t
+ typedmemmove(t, unsafe.Pointer(&e.data), elem)
} else {
if x == nil {
x = newobject(t)
// TODO: We allocate a zeroed object only to overwrite it with
// actual data. Figure out how to avoid zeroing. Also below in convT2I.
typedmemmove(t, x, elem)
- ep._type = t
- ep.data = x
+ e._type = t
+ e.data = x
}
return
}
-func convT2I(t *_type, inter *interfacetype, cache **itab, elem unsafe.Pointer, x unsafe.Pointer) (i fInterface) {
+func convT2I(t *_type, inter *interfacetype, cache **itab, elem unsafe.Pointer, x unsafe.Pointer) (i iface) {
if raceenabled {
raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&t)), funcPC(convT2I))
}
- tab := (*itab)(atomicloadp(unsafe.Pointer(cache)))
+ if msanenabled {
+ msanread(elem, t.size)
+ }
+ tab := (*itab)(atomic.Loadp(unsafe.Pointer(cache)))
if tab == nil {
tab = getitab(inter, t, false)
atomicstorep(unsafe.Pointer(cache), unsafe.Pointer(tab))
}
- pi := (*iface)(unsafe.Pointer(&i))
if isDirectIface(t) {
- pi.tab = tab
- typedmemmove(t, unsafe.Pointer(&pi.data), elem)
+ i.tab = tab
+ typedmemmove(t, unsafe.Pointer(&i.data), elem)
} else {
if x == nil {
x = newobject(t)
}
typedmemmove(t, x, elem)
- pi.tab = tab
- pi.data = x
+ i.tab = tab
+ i.data = x
}
return
}
panic(&TypeAssertionError{*iface._string, haveString, *want._string, ""})
}
-func assertI2T(t *_type, i fInterface, r unsafe.Pointer) {
- ip := (*iface)(unsafe.Pointer(&i))
- tab := ip.tab
+func assertI2T(t *_type, i iface, r unsafe.Pointer) {
+ tab := i.tab
if tab == nil {
panic(&TypeAssertionError{"", "", *t._string, ""})
}
}
if r != nil {
if isDirectIface(t) {
- writebarrierptr((*uintptr)(r), uintptr(ip.data))
+ writebarrierptr((*uintptr)(r), uintptr(i.data))
} else {
- typedmemmove(t, r, ip.data)
+ typedmemmove(t, r, i.data)
}
}
}
-func assertI2T2(t *_type, i fInterface, r unsafe.Pointer) bool {
- ip := (*iface)(unsafe.Pointer(&i))
- tab := ip.tab
+func assertI2T2(t *_type, i iface, r unsafe.Pointer) bool {
+ tab := i.tab
if tab == nil || tab._type != t {
if r != nil {
memclr(r, uintptr(t.size))
}
if r != nil {
if isDirectIface(t) {
- writebarrierptr((*uintptr)(r), uintptr(ip.data))
+ writebarrierptr((*uintptr)(r), uintptr(i.data))
} else {
- typedmemmove(t, r, ip.data)
+ typedmemmove(t, r, i.data)
}
}
return true
}
-func assertE2T(t *_type, e interface{}, r unsafe.Pointer) {
- ep := (*eface)(unsafe.Pointer(&e))
- if ep._type == nil {
+func assertE2T(t *_type, e eface, r unsafe.Pointer) {
+ if e._type == nil {
panic(&TypeAssertionError{"", "", *t._string, ""})
}
- if ep._type != t {
- panic(&TypeAssertionError{"", *ep._type._string, *t._string, ""})
+ if e._type != t {
+ panic(&TypeAssertionError{"", *e._type._string, *t._string, ""})
}
if r != nil {
if isDirectIface(t) {
- writebarrierptr((*uintptr)(r), uintptr(ep.data))
+ writebarrierptr((*uintptr)(r), uintptr(e.data))
} else {
- typedmemmove(t, r, ep.data)
+ typedmemmove(t, r, e.data)
}
}
}
var testingAssertE2T2GC bool
// The compiler ensures that r is non-nil.
-func assertE2T2(t *_type, e interface{}, r unsafe.Pointer) bool {
+func assertE2T2(t *_type, e eface, r unsafe.Pointer) bool {
if testingAssertE2T2GC {
GC()
}
- ep := (*eface)(unsafe.Pointer(&e))
- if ep._type != t {
+ if e._type != t {
memclr(r, uintptr(t.size))
return false
}
if isDirectIface(t) {
- writebarrierptr((*uintptr)(r), uintptr(ep.data))
+ writebarrierptr((*uintptr)(r), uintptr(e.data))
} else {
- typedmemmove(t, r, ep.data)
+ typedmemmove(t, r, e.data)
}
return true
}
-func convI2E(i fInterface) (r interface{}) {
- ip := (*iface)(unsafe.Pointer(&i))
- tab := ip.tab
+func convI2E(i iface) (r eface) {
+ tab := i.tab
if tab == nil {
return
}
- rp := (*eface)(unsafe.Pointer(&r))
- rp._type = tab._type
- rp.data = ip.data
+ r._type = tab._type
+ r.data = i.data
return
}
-func assertI2E(inter *interfacetype, i fInterface, r *interface{}) {
- ip := (*iface)(unsafe.Pointer(&i))
- tab := ip.tab
+func assertI2E(inter *interfacetype, i iface, r *eface) {
+ tab := i.tab
if tab == nil {
// explicit conversions require non-nil interface value.
panic(&TypeAssertionError{"", "", *inter.typ._string, ""})
}
- rp := (*eface)(unsafe.Pointer(r))
- rp._type = tab._type
- rp.data = ip.data
+ r._type = tab._type
+ r.data = i.data
return
}
// The compiler ensures that r is non-nil.
-func assertI2E2(inter *interfacetype, i fInterface, r *interface{}) bool {
- ip := (*iface)(unsafe.Pointer(&i))
- tab := ip.tab
+func assertI2E2(inter *interfacetype, i iface, r *eface) bool {
+ tab := i.tab
if tab == nil {
return false
}
- rp := (*eface)(unsafe.Pointer(r))
- rp._type = tab._type
- rp.data = ip.data
+ r._type = tab._type
+ r.data = i.data
return true
}
-func convI2I(inter *interfacetype, i fInterface) (r fInterface) {
- ip := (*iface)(unsafe.Pointer(&i))
- tab := ip.tab
+func convI2I(inter *interfacetype, i iface) (r iface) {
+ tab := i.tab
if tab == nil {
return
}
- rp := (*iface)(unsafe.Pointer(&r))
if tab.inter == inter {
- rp.tab = tab
- rp.data = ip.data
+ r.tab = tab
+ r.data = i.data
return
}
- rp.tab = getitab(inter, tab._type, false)
- rp.data = ip.data
+ r.tab = getitab(inter, tab._type, false)
+ r.data = i.data
return
}
-func assertI2I(inter *interfacetype, i fInterface, r *fInterface) {
- ip := (*iface)(unsafe.Pointer(&i))
- tab := ip.tab
+func assertI2I(inter *interfacetype, i iface, r *iface) {
+ tab := i.tab
if tab == nil {
// explicit conversions require non-nil interface value.
panic(&TypeAssertionError{"", "", *inter.typ._string, ""})
}
- rp := (*iface)(unsafe.Pointer(r))
if tab.inter == inter {
- rp.tab = tab
- rp.data = ip.data
+ r.tab = tab
+ r.data = i.data
return
}
- rp.tab = getitab(inter, tab._type, false)
- rp.data = ip.data
+ r.tab = getitab(inter, tab._type, false)
+ r.data = i.data
}
-func assertI2I2(inter *interfacetype, i fInterface, r *fInterface) bool {
- ip := (*iface)(unsafe.Pointer(&i))
- tab := ip.tab
+func assertI2I2(inter *interfacetype, i iface, r *iface) bool {
+ tab := i.tab
if tab == nil {
if r != nil {
- *r = nil
+ *r = iface{}
}
return false
}
tab = getitab(inter, tab._type, true)
if tab == nil {
if r != nil {
- *r = nil
+ *r = iface{}
}
return false
}
}
if r != nil {
- rp := (*iface)(unsafe.Pointer(r))
- rp.tab = tab
- rp.data = ip.data
+ r.tab = tab
+ r.data = i.data
}
return true
}
-func assertE2I(inter *interfacetype, e interface{}, r *fInterface) {
- ep := (*eface)(unsafe.Pointer(&e))
- t := ep._type
+func assertE2I(inter *interfacetype, e eface, r *iface) {
+ t := e._type
if t == nil {
// explicit conversions require non-nil interface value.
panic(&TypeAssertionError{"", "", *inter.typ._string, ""})
}
- rp := (*iface)(unsafe.Pointer(r))
- rp.tab = getitab(inter, t, false)
- rp.data = ep.data
+ r.tab = getitab(inter, t, false)
+ r.data = e.data
}
var testingAssertE2I2GC bool
-func assertE2I2(inter *interfacetype, e interface{}, r *fInterface) bool {
+func assertE2I2(inter *interfacetype, e eface, r *iface) bool {
if testingAssertE2I2GC {
GC()
}
- ep := (*eface)(unsafe.Pointer(&e))
- t := ep._type
+ t := e._type
if t == nil {
if r != nil {
- *r = nil
+ *r = iface{}
}
return false
}
tab := getitab(inter, t, true)
if tab == nil {
if r != nil {
- *r = nil
+ *r = iface{}
}
return false
}
if r != nil {
- rp := (*iface)(unsafe.Pointer(r))
- rp.tab = tab
- rp.data = ep.data
+ r.tab = tab
+ r.data = e.data
}
return true
}
//go:linkname reflect_ifaceE2I reflect.ifaceE2I
-func reflect_ifaceE2I(inter *interfacetype, e interface{}, dst *fInterface) {
+func reflect_ifaceE2I(inter *interfacetype, e eface, dst *iface) {
assertE2I(inter, e, dst)
}
-func assertE2E(inter *interfacetype, e interface{}, r *interface{}) {
- ep := (*eface)(unsafe.Pointer(&e))
- if ep._type == nil {
+func assertE2E(inter *interfacetype, e eface, r *eface) {
+ if e._type == nil {
// explicit conversions require non-nil interface value.
panic(&TypeAssertionError{"", "", *inter.typ._string, ""})
}
}
// The compiler ensures that r is non-nil.
-func assertE2E2(inter *interfacetype, e interface{}, r *interface{}) bool {
- ep := (*eface)(unsafe.Pointer(&e))
- if ep._type == nil {
- *r = nil
+func assertE2E2(inter *interfacetype, e eface, r *eface) bool {
+ if e._type == nil {
+ *r = eface{}
return false
}
*r = e
return true
}
-func ifacethash(i fInterface) uint32 {
- ip := (*iface)(unsafe.Pointer(&i))
- tab := ip.tab
+func ifacethash(i iface) uint32 {
+ tab := i.tab
if tab == nil {
return 0
}
return tab._type.hash
}
-func efacethash(e interface{}) uint32 {
- ep := (*eface)(unsafe.Pointer(&e))
- t := ep._type
+func efacethash(e eface) uint32 {
+ t := e._type
if t == nil {
return 0
}
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+TEXT runtime∕internal∕atomic·nop(SB),NOSPLIT,$0-0
+ RET
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+// bool Cas(int32 *val, int32 old, int32 new)
+// Atomically:
+// if(*val == old){
+// *val = new;
+// return 1;
+// }else
+// return 0;
+TEXT runtime∕internal∕atomic·Cas(SB), NOSPLIT, $0-13
+ MOVL ptr+0(FP), BX
+ MOVL old+4(FP), AX
+ MOVL new+8(FP), CX
+ LOCK
+ CMPXCHGL CX, 0(BX)
+ SETEQ ret+12(FP)
+ RET
+
+TEXT runtime∕internal∕atomic·Casuintptr(SB), NOSPLIT, $0-13
+ JMP runtime∕internal∕atomic·Cas(SB)
+
+TEXT runtime∕internal∕atomic·Loaduintptr(SB), NOSPLIT, $0-8
+ JMP runtime∕internal∕atomic·Load(SB)
+
+TEXT runtime∕internal∕atomic·Loaduint(SB), NOSPLIT, $0-8
+ JMP runtime∕internal∕atomic·Load(SB)
+
+TEXT runtime∕internal∕atomic·Storeuintptr(SB), NOSPLIT, $0-8
+ JMP runtime∕internal∕atomic·Store(SB)
+
+TEXT runtime∕internal∕atomic·Xadduintptr(SB), NOSPLIT, $0-8
+ JMP runtime∕internal∕atomic·Xadd(SB)
+
+TEXT runtime∕internal∕atomic·Loadint64(SB), NOSPLIT, $0-16
+ JMP runtime∕internal∕atomic·Load64(SB)
+
+TEXT runtime∕internal∕atomic·Xaddint64(SB), NOSPLIT, $0-16
+ JMP runtime∕internal∕atomic·Xadd64(SB)
+
+
+// bool runtime∕internal∕atomic·Cas64(uint64 *val, uint64 old, uint64 new)
+// Atomically:
+// if(*val == *old){
+// *val = new;
+// return 1;
+// } else {
+// return 0;
+// }
+TEXT runtime∕internal∕atomic·Cas64(SB), NOSPLIT, $0-21
+ MOVL ptr+0(FP), BP
+ MOVL old_lo+4(FP), AX
+ MOVL old_hi+8(FP), DX
+ MOVL new_lo+12(FP), BX
+ MOVL new_hi+16(FP), CX
+ LOCK
+ CMPXCHG8B 0(BP)
+ SETEQ ret+20(FP)
+ RET
+
+// bool Casp(void **p, void *old, void *new)
+// Atomically:
+// if(*p == old){
+// *p = new;
+// return 1;
+// }else
+// return 0;
+TEXT runtime∕internal∕atomic·Casp1(SB), NOSPLIT, $0-13
+ MOVL ptr+0(FP), BX
+ MOVL old+4(FP), AX
+ MOVL new+8(FP), CX
+ LOCK
+ CMPXCHGL CX, 0(BX)
+ SETEQ ret+12(FP)
+ RET
+
+// uint32 Xadd(uint32 volatile *val, int32 delta)
+// Atomically:
+// *val += delta;
+// return *val;
+TEXT runtime∕internal∕atomic·Xadd(SB), NOSPLIT, $0-12
+ MOVL ptr+0(FP), BX
+ MOVL delta+4(FP), AX
+ MOVL AX, CX
+ LOCK
+ XADDL AX, 0(BX)
+ ADDL CX, AX
+ MOVL AX, ret+8(FP)
+ RET
+
+TEXT runtime∕internal∕atomic·Xchg(SB), NOSPLIT, $0-12
+ MOVL ptr+0(FP), BX
+ MOVL new+4(FP), AX
+ XCHGL AX, 0(BX)
+ MOVL AX, ret+8(FP)
+ RET
+
+TEXT runtime∕internal∕atomic·Xchguintptr(SB), NOSPLIT, $0-12
+ JMP runtime∕internal∕atomic·Xchg(SB)
+
+
+TEXT runtime∕internal∕atomic·Storep1(SB), NOSPLIT, $0-8
+ MOVL ptr+0(FP), BX
+ MOVL val+4(FP), AX
+ XCHGL AX, 0(BX)
+ RET
+
+TEXT runtime∕internal∕atomic·Store(SB), NOSPLIT, $0-8
+ MOVL ptr+0(FP), BX
+ MOVL val+4(FP), AX
+ XCHGL AX, 0(BX)
+ RET
+
+// uint64 atomicload64(uint64 volatile* addr);
+TEXT runtime∕internal∕atomic·Load64(SB), NOSPLIT, $0-12
+ MOVL ptr+0(FP), AX
+ TESTL $7, AX
+ JZ 2(PC)
+ MOVL 0, AX // crash with nil ptr deref
+ LEAL ret_lo+4(FP), BX
+ // MOVQ (%EAX), %MM0
+ BYTE $0x0f; BYTE $0x6f; BYTE $0x00
+ // MOVQ %MM0, 0(%EBX)
+ BYTE $0x0f; BYTE $0x7f; BYTE $0x03
+ // EMMS
+ BYTE $0x0F; BYTE $0x77
+ RET
+
+// void runtime∕internal∕atomic·Store64(uint64 volatile* addr, uint64 v);
+TEXT runtime∕internal∕atomic·Store64(SB), NOSPLIT, $0-12
+ MOVL ptr+0(FP), AX
+ TESTL $7, AX
+ JZ 2(PC)
+ MOVL 0, AX // crash with nil ptr deref
+ // MOVQ and EMMS were introduced on the Pentium MMX.
+ // MOVQ 0x8(%ESP), %MM0
+ BYTE $0x0f; BYTE $0x6f; BYTE $0x44; BYTE $0x24; BYTE $0x08
+ // MOVQ %MM0, (%EAX)
+ BYTE $0x0f; BYTE $0x7f; BYTE $0x00
+ // EMMS
+ BYTE $0x0F; BYTE $0x77
+ // This is essentially a no-op, but it provides required memory fencing.
+ // It can be replaced with MFENCE, but MFENCE was introduced only on the Pentium4 (SSE2).
+ MOVL $0, AX
+ LOCK
+ XADDL AX, (SP)
+ RET
+
+// void runtime∕internal∕atomic·Or8(byte volatile*, byte);
+TEXT runtime∕internal∕atomic·Or8(SB), NOSPLIT, $0-5
+ MOVL ptr+0(FP), AX
+ MOVB val+4(FP), BX
+ LOCK
+ ORB BX, (AX)
+ RET
+
+// void runtime∕internal∕atomic·And8(byte volatile*, byte);
+TEXT runtime∕internal∕atomic·And8(SB), NOSPLIT, $0-5
+ MOVL ptr+0(FP), AX
+ MOVB val+4(FP), BX
+ LOCK
+ ANDB BX, (AX)
+ RET
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+// bool Cas(int32 *val, int32 old, int32 new)
+// Atomically:
+// if(*val == old){
+// *val = new;
+// return 1;
+// } else
+// return 0;
+TEXT runtime∕internal∕atomic·Cas(SB),NOSPLIT,$0-17
+ MOVQ ptr+0(FP), BX
+ MOVL old+8(FP), AX
+ MOVL new+12(FP), CX
+ LOCK
+ CMPXCHGL CX, 0(BX)
+ SETEQ ret+16(FP)
+ RET
+
+// bool runtime∕internal∕atomic·Cas64(uint64 *val, uint64 old, uint64 new)
+// Atomically:
+// if(*val == *old){
+// *val = new;
+// return 1;
+// } else {
+// return 0;
+// }
+TEXT runtime∕internal∕atomic·Cas64(SB), NOSPLIT, $0-25
+ MOVQ ptr+0(FP), BX
+ MOVQ old+8(FP), AX
+ MOVQ new+16(FP), CX
+ LOCK
+ CMPXCHGQ CX, 0(BX)
+ SETEQ ret+24(FP)
+ RET
+
+TEXT runtime∕internal∕atomic·Casuintptr(SB), NOSPLIT, $0-25
+ JMP runtime∕internal∕atomic·Cas64(SB)
+
+TEXT runtime∕internal∕atomic·Loaduintptr(SB), NOSPLIT, $0-16
+ JMP runtime∕internal∕atomic·Load64(SB)
+
+TEXT runtime∕internal∕atomic·Loaduint(SB), NOSPLIT, $0-16
+ JMP runtime∕internal∕atomic·Load64(SB)
+
+TEXT runtime∕internal∕atomic·Storeuintptr(SB), NOSPLIT, $0-16
+ JMP runtime∕internal∕atomic·Store64(SB)
+
+TEXT runtime∕internal∕atomic·Loadint64(SB), NOSPLIT, $0-16
+ JMP runtime∕internal∕atomic·Load64(SB)
+
+TEXT runtime∕internal∕atomic·Xaddint64(SB), NOSPLIT, $0-16
+ JMP runtime∕internal∕atomic·Xadd64(SB)
+
+// bool Casp(void **val, void *old, void *new)
+// Atomically:
+// if(*val == old){
+// *val = new;
+// return 1;
+// } else
+// return 0;
+TEXT runtime∕internal∕atomic·Casp1(SB), NOSPLIT, $0-25
+ MOVQ ptr+0(FP), BX
+ MOVQ old+8(FP), AX
+ MOVQ new+16(FP), CX
+ LOCK
+ CMPXCHGQ CX, 0(BX)
+ SETEQ ret+24(FP)
+ RET
+
+// uint32 Xadd(uint32 volatile *val, int32 delta)
+// Atomically:
+// *val += delta;
+// return *val;
+TEXT runtime∕internal∕atomic·Xadd(SB), NOSPLIT, $0-20
+ MOVQ ptr+0(FP), BX
+ MOVL delta+8(FP), AX
+ MOVL AX, CX
+ LOCK
+ XADDL AX, 0(BX)
+ ADDL CX, AX
+ MOVL AX, ret+16(FP)
+ RET
+
+TEXT runtime∕internal∕atomic·Xadd64(SB), NOSPLIT, $0-24
+ MOVQ ptr+0(FP), BX
+ MOVQ delta+8(FP), AX
+ MOVQ AX, CX
+ LOCK
+ XADDQ AX, 0(BX)
+ ADDQ CX, AX
+ MOVQ AX, ret+16(FP)
+ RET
+
+TEXT runtime∕internal∕atomic·Xadduintptr(SB), NOSPLIT, $0-24
+ JMP runtime∕internal∕atomic·Xadd64(SB)
+
+TEXT runtime∕internal∕atomic·Xchg(SB), NOSPLIT, $0-20
+ MOVQ ptr+0(FP), BX
+ MOVL new+8(FP), AX
+ XCHGL AX, 0(BX)
+ MOVL AX, ret+16(FP)
+ RET
+
+TEXT runtime∕internal∕atomic·Xchg64(SB), NOSPLIT, $0-24
+ MOVQ ptr+0(FP), BX
+ MOVQ new+8(FP), AX
+ XCHGQ AX, 0(BX)
+ MOVQ AX, ret+16(FP)
+ RET
+
+TEXT runtime∕internal∕atomic·Xchguintptr(SB), NOSPLIT, $0-24
+ JMP runtime∕internal∕atomic·Xchg64(SB)
+
+TEXT runtime∕internal∕atomic·Storep1(SB), NOSPLIT, $0-16
+ MOVQ ptr+0(FP), BX
+ MOVQ val+8(FP), AX
+ XCHGQ AX, 0(BX)
+ RET
+
+TEXT runtime∕internal∕atomic·Store(SB), NOSPLIT, $0-12
+ MOVQ ptr+0(FP), BX
+ MOVL val+8(FP), AX
+ XCHGL AX, 0(BX)
+ RET
+
+TEXT runtime∕internal∕atomic·Store64(SB), NOSPLIT, $0-16
+ MOVQ ptr+0(FP), BX
+ MOVQ val+8(FP), AX
+ XCHGQ AX, 0(BX)
+ RET
+
+// void runtime∕internal∕atomic·Or8(byte volatile*, byte);
+TEXT runtime∕internal∕atomic·Or8(SB), NOSPLIT, $0-9
+ MOVQ ptr+0(FP), AX
+ MOVB val+8(FP), BX
+ LOCK
+ ORB BX, (AX)
+ RET
+
+// void runtime∕internal∕atomic·And8(byte volatile*, byte);
+TEXT runtime∕internal∕atomic·And8(SB), NOSPLIT, $0-9
+ MOVQ ptr+0(FP), AX
+ MOVB val+8(FP), BX
+ LOCK
+ ANDB BX, (AX)
+ RET
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+// bool Cas(int32 *val, int32 old, int32 new)
+// Atomically:
+// if(*val == old){
+// *val = new;
+// return 1;
+// } else
+// return 0;
+TEXT runtime∕internal∕atomic·Cas(SB), NOSPLIT, $0-17
+ MOVL ptr+0(FP), BX
+ MOVL old+4(FP), AX
+ MOVL new+8(FP), CX
+ LOCK
+ CMPXCHGL CX, 0(BX)
+ SETEQ ret+16(FP)
+ RET
+
+TEXT runtime∕internal∕atomic·Casuintptr(SB), NOSPLIT, $0-17
+ JMP runtime∕internal∕atomic·Cas(SB)
+
+TEXT runtime∕internal∕atomic·Loaduintptr(SB), NOSPLIT, $0-12
+ JMP runtime∕internal∕atomic·Load(SB)
+
+TEXT runtime∕internal∕atomic·Loaduint(SB), NOSPLIT, $0-12
+ JMP runtime∕internal∕atomic·Load(SB)
+
+TEXT runtime∕internal∕atomic·Storeuintptr(SB), NOSPLIT, $0-12
+ JMP runtime∕internal∕atomic·Store(SB)
+
+TEXT runtime∕internal∕atomic·Loadint64(SB), NOSPLIT, $0-24
+ JMP runtime∕internal∕atomic·Load64(SB)
+
+TEXT runtime∕internal∕atomic·Xaddint64(SB), NOSPLIT, $0-24
+ JMP runtime∕internal∕atomic·Xadd64(SB)
+
+// bool runtime∕internal∕atomic·cas64(uint64 *val, uint64 old, uint64 new)
+// Atomically:
+// if(*val == *old){
+// *val = new;
+// return 1;
+// } else {
+// return 0;
+// }
+TEXT runtime∕internal∕atomic·Cas64(SB), NOSPLIT, $0-25
+ MOVL ptr+0(FP), BX
+ MOVQ old+8(FP), AX
+ MOVQ new+16(FP), CX
+ LOCK
+ CMPXCHGQ CX, 0(BX)
+ SETEQ ret+24(FP)
+ RET
+
+// bool Casp(void **val, void *old, void *new)
+// Atomically:
+// if(*val == old){
+// *val = new;
+// return 1;
+// } else
+// return 0;
+TEXT runtime∕internal∕atomic·Casp1(SB), NOSPLIT, $0-17
+ MOVL ptr+0(FP), BX
+ MOVL old+4(FP), AX
+ MOVL new+8(FP), CX
+ LOCK
+ CMPXCHGL CX, 0(BX)
+ SETEQ ret+16(FP)
+ RET
+
+// uint32 Xadd(uint32 volatile *val, int32 delta)
+// Atomically:
+// *val += delta;
+// return *val;
+TEXT runtime∕internal∕atomic·Xadd(SB), NOSPLIT, $0-12
+ MOVL ptr+0(FP), BX
+ MOVL delta+4(FP), AX
+ MOVL AX, CX
+ LOCK
+ XADDL AX, 0(BX)
+ ADDL CX, AX
+ MOVL AX, ret+8(FP)
+ RET
+
+TEXT runtime∕internal∕atomic·Xadd64(SB), NOSPLIT, $0-24
+ MOVL ptr+0(FP), BX
+ MOVQ delta+8(FP), AX
+ MOVQ AX, CX
+ LOCK
+ XADDQ AX, 0(BX)
+ ADDQ CX, AX
+ MOVQ AX, ret+16(FP)
+ RET
+
+TEXT runtime∕internal∕atomic·Xadduintptr(SB), NOSPLIT, $0-12
+ JMP runtime∕internal∕atomic·Xadd(SB)
+
+TEXT runtime∕internal∕atomic·Xchg(SB), NOSPLIT, $0-12
+ MOVL ptr+0(FP), BX
+ MOVL new+4(FP), AX
+ XCHGL AX, 0(BX)
+ MOVL AX, ret+8(FP)
+ RET
+
+TEXT runtime∕internal∕atomic·Xchg64(SB), NOSPLIT, $0-24
+ MOVL ptr+0(FP), BX
+ MOVQ new+8(FP), AX
+ XCHGQ AX, 0(BX)
+ MOVQ AX, ret+16(FP)
+ RET
+
+TEXT runtime∕internal∕atomic·Xchguintptr(SB), NOSPLIT, $0-12
+ JMP runtime∕internal∕atomic·Xchg(SB)
+
+TEXT runtime∕internal∕atomic·Storep1(SB), NOSPLIT, $0-8
+ MOVL ptr+0(FP), BX
+ MOVL val+4(FP), AX
+ XCHGL AX, 0(BX)
+ RET
+
+TEXT runtime∕internal∕atomic·Store(SB), NOSPLIT, $0-8
+ MOVL ptr+0(FP), BX
+ MOVL val+4(FP), AX
+ XCHGL AX, 0(BX)
+ RET
+
+TEXT runtime∕internal∕atomic·Store64(SB), NOSPLIT, $0-16
+ MOVL ptr+0(FP), BX
+ MOVQ val+8(FP), AX
+ XCHGQ AX, 0(BX)
+ RET
+
+// void runtime∕internal∕atomic·Or8(byte volatile*, byte);
+TEXT runtime∕internal∕atomic·Or8(SB), NOSPLIT, $0-5
+ MOVL ptr+0(FP), BX
+ MOVB val+4(FP), AX
+ LOCK
+ ORB AX, 0(BX)
+ RET
+
+// void runtime∕internal∕atomic·And8(byte volatile*, byte);
+TEXT runtime∕internal∕atomic·And8(SB), NOSPLIT, $0-5
+ MOVL ptr+0(FP), BX
+ MOVB val+4(FP), AX
+ LOCK
+ ANDB AX, 0(BX)
+ RET
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+// bool armcas(int32 *val, int32 old, int32 new)
+// Atomically:
+// if(*val == old){
+// *val = new;
+// return 1;
+// }else
+// return 0;
+//
+// To implement runtime∕internal∕atomic·cas in sys_$GOOS_arm.s
+// using the native instructions, use:
+//
+// TEXT runtime∕internal∕atomic·cas(SB),NOSPLIT,$0
+// B runtime∕internal∕atomic·armcas(SB)
+//
+TEXT runtime∕internal∕atomic·armcas(SB),NOSPLIT,$0-13
+ MOVW valptr+0(FP), R1
+ MOVW old+4(FP), R2
+ MOVW new+8(FP), R3
+casl:
+ LDREX (R1), R0
+ CMP R0, R2
+ BNE casfail
+
+ MOVB runtime·goarm(SB), R11
+ CMP $7, R11
+ BLT 2(PC)
+ WORD $0xf57ff05a // dmb ishst
+
+ STREX R3, (R1), R0
+ CMP $0, R0
+ BNE casl
+ MOVW $1, R0
+
+ MOVB runtime·goarm(SB), R11
+ CMP $7, R11
+ BLT 2(PC)
+ WORD $0xf57ff05b // dmb ish
+
+ MOVB R0, ret+12(FP)
+ RET
+casfail:
+ MOVW $0, R0
+ MOVB R0, ret+12(FP)
+ RET
+
+TEXT runtime∕internal∕atomic·Casuintptr(SB),NOSPLIT,$0-13
+ B runtime∕internal∕atomic·Cas(SB)
+
+TEXT runtime∕internal∕atomic·Loaduintptr(SB),NOSPLIT,$0-8
+ B runtime∕internal∕atomic·Load(SB)
+
+TEXT runtime∕internal∕atomic·Loaduint(SB),NOSPLIT,$0-8
+ B runtime∕internal∕atomic·Load(SB)
+
+TEXT runtime∕internal∕atomic·Storeuintptr(SB),NOSPLIT,$0-8
+ B runtime∕internal∕atomic·Store(SB)
+
+TEXT runtime∕internal∕atomic·Xadduintptr(SB),NOSPLIT,$0-8
+ B runtime∕internal∕atomic·Xadd(SB)
+
+TEXT runtime∕internal∕atomic·Loadint64(SB),NOSPLIT,$0-16
+ B runtime∕internal∕atomic·Load64(SB)
+
+TEXT runtime∕internal∕atomic·Xaddint64(SB),NOSPLIT,$0-16
+ B runtime∕internal∕atomic·Xadd64(SB)
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+// bool Cas(uint32 *ptr, uint32 old, uint32 new)
+// Atomically:
+// if(*val == old){
+// *val = new;
+// return 1;
+// } else
+// return 0;
+TEXT runtime∕internal∕atomic·Cas(SB), NOSPLIT, $0-17
+ MOVD ptr+0(FP), R0
+ MOVW old+8(FP), R1
+ MOVW new+12(FP), R2
+again:
+ LDAXRW (R0), R3
+ CMPW R1, R3
+ BNE ok
+ STLXRW R2, (R0), R3
+ CBNZ R3, again
+ok:
+ CSET EQ, R0
+ MOVB R0, ret+16(FP)
+ RET
+
+TEXT runtime∕internal∕atomic·Casuintptr(SB), NOSPLIT, $0-25
+ B runtime∕internal∕atomic·Cas64(SB)
+
+TEXT runtime∕internal∕atomic·Loaduintptr(SB), NOSPLIT, $-8-16
+ B runtime∕internal∕atomic·Load64(SB)
+
+TEXT runtime∕internal∕atomic·Loaduint(SB), NOSPLIT, $-8-16
+ B runtime∕internal∕atomic·Load64(SB)
+
+TEXT runtime∕internal∕atomic·Storeuintptr(SB), NOSPLIT, $0-16
+ B runtime∕internal∕atomic·Store64(SB)
+
+TEXT runtime∕internal∕atomic·Xadduintptr(SB), NOSPLIT, $0-16
+ B runtime∕internal∕atomic·Xadd64(SB)
+
+TEXT runtime∕internal∕atomic·Loadint64(SB), NOSPLIT, $0-16
+ B runtime∕internal∕atomic·Load64(SB)
+
+TEXT runtime∕internal∕atomic·Xaddint64(SB), NOSPLIT, $0-16
+ B runtime∕internal∕atomic·Xadd64(SB)
+
+// bool Casp(void **val, void *old, void *new)
+// Atomically:
+// if(*val == old){
+// *val = new;
+// return 1;
+// } else
+// return 0;
+TEXT runtime∕internal∕atomic·Casp1(SB), NOSPLIT, $0-25
+ B runtime∕internal∕atomic·Cas64(SB)
--- /dev/null
+// Copyright 2015 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 mips64 mips64le
+
+#include "textflag.h"
+
+#define LL(base, rt) WORD $((060<<26)|((base)<<21)|((rt)<<16))
+#define LLV(base, rt) WORD $((064<<26)|((base)<<21)|((rt)<<16))
+#define SC(base, rt) WORD $((070<<26)|((base)<<21)|((rt)<<16))
+#define SCV(base, rt) WORD $((074<<26)|((base)<<21)|((rt)<<16))
+#define SYNC WORD $0xf
+
+// bool cas(uint32 *ptr, uint32 old, uint32 new)
+// Atomically:
+// if(*val == old){
+// *val = new;
+// return 1;
+// } else
+// return 0;
+TEXT ·Cas(SB), NOSPLIT, $0-17
+ MOVV ptr+0(FP), R1
+ MOVW old+8(FP), R2
+ MOVW new+12(FP), R5
+ SYNC
+cas_again:
+ MOVV R5, R3
+ LL(1, 4) // R4 = *R1
+ BNE R2, R4, cas_fail
+ SC(1, 3) // *R1 = R3
+ BEQ R3, cas_again
+ MOVV $1, R1
+ MOVB R1, ret+16(FP)
+ SYNC
+ RET
+cas_fail:
+ MOVV $0, R1
+ JMP -4(PC)
+
+// bool cas64(uint64 *ptr, uint64 old, uint64 new)
+// Atomically:
+// if(*val == *old){
+// *val = new;
+// return 1;
+// } else {
+// return 0;
+// }
+TEXT ·Cas64(SB), NOSPLIT, $0-25
+ MOVV ptr+0(FP), R1
+ MOVV old+8(FP), R2
+ MOVV new+16(FP), R5
+ SYNC
+cas64_again:
+ MOVV R5, R3
+ LLV(1, 4) // R4 = *R1
+ BNE R2, R4, cas64_fail
+ SCV(1, 3) // *R1 = R3
+ BEQ R3, cas64_again
+ MOVV $1, R1
+ MOVB R1, ret+24(FP)
+ SYNC
+ RET
+cas64_fail:
+ MOVV $0, R1
+ JMP -4(PC)
+
+TEXT ·Casuintptr(SB), NOSPLIT, $0-25
+ JMP ·Cas64(SB)
+
+TEXT ·Loaduintptr(SB), NOSPLIT|NOFRAME, $0-16
+ JMP ·Load64(SB)
+
+TEXT ·Loaduint(SB), NOSPLIT|NOFRAME, $0-16
+ JMP ·Load64(SB)
+
+TEXT ·Storeuintptr(SB), NOSPLIT, $0-16
+ JMP ·Store64(SB)
+
+TEXT ·Xadduintptr(SB), NOSPLIT, $0-24
+ JMP ·Xadd64(SB)
+
+TEXT ·Loadint64(SB), NOSPLIT, $0-16
+ JMP ·Load64(SB)
+
+TEXT ·Xaddint64(SB), NOSPLIT, $0-16
+ JMP ·Xadd64(SB)
+
+// bool casp(void **val, void *old, void *new)
+// Atomically:
+// if(*val == old){
+// *val = new;
+// return 1;
+// } else
+// return 0;
+TEXT ·Casp1(SB), NOSPLIT, $0-25
+ JMP runtime∕internal∕atomic·Cas64(SB)
+
+// uint32 xadd(uint32 volatile *ptr, int32 delta)
+// Atomically:
+// *val += delta;
+// return *val;
+TEXT ·Xadd(SB), NOSPLIT, $0-20
+ MOVV ptr+0(FP), R2
+ MOVW delta+8(FP), R3
+ SYNC
+ LL(2, 1) // R1 = *R2
+ ADDU R1, R3, R4
+ MOVV R4, R1
+ SC(2, 4) // *R2 = R4
+ BEQ R4, -4(PC)
+ MOVW R1, ret+16(FP)
+ SYNC
+ RET
+
+TEXT ·Xadd64(SB), NOSPLIT, $0-24
+ MOVV ptr+0(FP), R2
+ MOVV delta+8(FP), R3
+ SYNC
+ LLV(2, 1) // R1 = *R2
+ ADDVU R1, R3, R4
+ MOVV R4, R1
+ SCV(2, 4) // *R2 = R4
+ BEQ R4, -4(PC)
+ MOVV R1, ret+16(FP)
+ SYNC
+ RET
+
+TEXT ·Xchg(SB), NOSPLIT, $0-20
+ MOVV ptr+0(FP), R2
+ MOVW new+8(FP), R5
+
+ SYNC
+ MOVV R5, R3
+ LL(2, 1) // R1 = *R2
+ SC(2, 3) // *R2 = R3
+ BEQ R3, -3(PC)
+ MOVW R1, ret+16(FP)
+ SYNC
+ RET
+
+TEXT ·Xchg64(SB), NOSPLIT, $0-24
+ MOVV ptr+0(FP), R2
+ MOVV new+8(FP), R5
+
+ SYNC
+ MOVV R5, R3
+ LLV(2, 1) // R1 = *R2
+ SCV(2, 3) // *R2 = R3
+ BEQ R3, -3(PC)
+ MOVV R1, ret+16(FP)
+ SYNC
+ RET
+
+TEXT ·Xchguintptr(SB), NOSPLIT, $0-24
+ JMP ·Xchg64(SB)
+
+TEXT ·Storep1(SB), NOSPLIT, $0-16
+ JMP ·Store64(SB)
+
+TEXT ·Store(SB), NOSPLIT, $0-12
+ MOVV ptr+0(FP), R1
+ MOVW val+8(FP), R2
+ SYNC
+ MOVW R2, 0(R1)
+ SYNC
+ RET
+
+TEXT ·Store64(SB), NOSPLIT, $0-16
+ MOVV ptr+0(FP), R1
+ MOVV val+8(FP), R2
+ SYNC
+ MOVV R2, 0(R1)
+ SYNC
+ RET
+
+// void Or8(byte volatile*, byte);
+TEXT ·Or8(SB), NOSPLIT, $0-9
+ MOVV ptr+0(FP), R1
+ MOVBU val+8(FP), R2
+ // Align ptr down to 4 bytes so we can use 32-bit load/store.
+ MOVV $~3, R3
+ AND R1, R3
+ // Compute val shift.
+#ifdef GOARCH_mips64
+ // Big endian. ptr = ptr ^ 3
+ XOR $3, R1
+#endif
+ // R4 = ((ptr & 3) * 8)
+ AND $3, R1, R4
+ SLLV $3, R4
+ // Shift val for aligned ptr. R2 = val << R4
+ SLLV R4, R2
+
+ SYNC
+ LL(3, 4) // R4 = *R3
+ OR R2, R4
+ SC(3, 4) // *R3 = R4
+ BEQ R4, -4(PC)
+ SYNC
+ RET
+
+// void And8(byte volatile*, byte);
+TEXT ·And8(SB), NOSPLIT, $0-9
+ MOVV ptr+0(FP), R1
+ MOVBU val+8(FP), R2
+ // Align ptr down to 4 bytes so we can use 32-bit load/store.
+ MOVV $~3, R3
+ AND R1, R3
+ // Compute val shift.
+#ifdef GOARCH_mips64
+ // Big endian. ptr = ptr ^ 3
+ XOR $3, R1
+#endif
+ // R4 = ((ptr & 3) * 8)
+ AND $3, R1, R4
+ SLLV $3, R4
+ // Shift val for aligned ptr. R2 = val << R4 | ^(0xFF << R4)
+ MOVV $0xFF, R5
+ SLLV R4, R2
+ SLLV R4, R5
+ NOR R0, R5
+ OR R5, R2
+
+ SYNC
+ LL(3, 4) // R4 = *R3
+ AND R2, R4
+ SC(3, 4) // *R3 = R4
+ BEQ R4, -4(PC)
+ SYNC
+ RET
--- /dev/null
+// Copyright 2015 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 ppc64 ppc64le
+
+#include "textflag.h"
+
+// bool cas(uint32 *ptr, uint32 old, uint32 new)
+// Atomically:
+// if(*val == old){
+// *val = new;
+// return 1;
+// } else
+// return 0;
+TEXT runtime∕internal∕atomic·Cas(SB), NOSPLIT, $0-17
+ MOVD ptr+0(FP), R3
+ MOVWZ old+8(FP), R4
+ MOVWZ new+12(FP), R5
+cas_again:
+ SYNC
+ LWAR (R3), R6
+ CMPW R6, R4
+ BNE cas_fail
+ STWCCC R5, (R3)
+ BNE cas_again
+ MOVD $1, R3
+ SYNC
+ ISYNC
+ MOVB R3, ret+16(FP)
+ RET
+cas_fail:
+ MOVD $0, R3
+ BR -5(PC)
+
+// bool runtime∕internal∕atomic·Cas64(uint64 *ptr, uint64 old, uint64 new)
+// Atomically:
+// if(*val == *old){
+// *val = new;
+// return 1;
+// } else {
+// return 0;
+// }
+TEXT runtime∕internal∕atomic·Cas64(SB), NOSPLIT, $0-25
+ MOVD ptr+0(FP), R3
+ MOVD old+8(FP), R4
+ MOVD new+16(FP), R5
+cas64_again:
+ SYNC
+ LDAR (R3), R6
+ CMP R6, R4
+ BNE cas64_fail
+ STDCCC R5, (R3)
+ BNE cas64_again
+ MOVD $1, R3
+ SYNC
+ ISYNC
+ MOVB R3, ret+24(FP)
+ RET
+cas64_fail:
+ MOVD $0, R3
+ BR -5(PC)
+
+TEXT runtime∕internal∕atomic·Casuintptr(SB), NOSPLIT, $0-25
+ BR runtime∕internal∕atomic·Cas64(SB)
+
+TEXT runtime∕internal∕atomic·Loaduintptr(SB), NOSPLIT|NOFRAME, $0-16
+ BR runtime∕internal∕atomic·Load64(SB)
+
+TEXT runtime∕internal∕atomic·Loaduint(SB), NOSPLIT|NOFRAME, $0-16
+ BR runtime∕internal∕atomic·Load64(SB)
+
+TEXT runtime∕internal∕atomic·Storeuintptr(SB), NOSPLIT, $0-16
+ BR runtime∕internal∕atomic·Store64(SB)
+
+TEXT runtime∕internal∕atomic·Xadduintptr(SB), NOSPLIT, $0-24
+ BR runtime∕internal∕atomic·Xadd64(SB)
+
+TEXT runtime∕internal∕atomic·Loadint64(SB), NOSPLIT, $0-16
+ BR runtime∕internal∕atomic·Load64(SB)
+
+TEXT runtime∕internal∕atomic·Xaddint64(SB), NOSPLIT, $0-16
+ BR runtime∕internal∕atomic·Xadd64(SB)
+
+// bool casp(void **val, void *old, void *new)
+// Atomically:
+// if(*val == old){
+// *val = new;
+// return 1;
+// } else
+// return 0;
+TEXT runtime∕internal∕atomic·Casp1(SB), NOSPLIT, $0-25
+ BR runtime∕internal∕atomic·Cas64(SB)
+
+// uint32 xadd(uint32 volatile *ptr, int32 delta)
+// Atomically:
+// *val += delta;
+// return *val;
+TEXT runtime∕internal∕atomic·Xadd(SB), NOSPLIT, $0-20
+ MOVD ptr+0(FP), R4
+ MOVW delta+8(FP), R5
+ SYNC
+ LWAR (R4), R3
+ ADD R5, R3
+ STWCCC R3, (R4)
+ BNE -4(PC)
+ SYNC
+ ISYNC
+ MOVW R3, ret+16(FP)
+ RET
+
+TEXT runtime∕internal∕atomic·Xadd64(SB), NOSPLIT, $0-24
+ MOVD ptr+0(FP), R4
+ MOVD delta+8(FP), R5
+ SYNC
+ LDAR (R4), R3
+ ADD R5, R3
+ STDCCC R3, (R4)
+ BNE -4(PC)
+ SYNC
+ ISYNC
+ MOVD R3, ret+16(FP)
+ RET
+
+TEXT runtime∕internal∕atomic·Xchg(SB), NOSPLIT, $0-20
+ MOVD ptr+0(FP), R4
+ MOVW new+8(FP), R5
+ SYNC
+ LWAR (R4), R3
+ STWCCC R5, (R4)
+ BNE -3(PC)
+ SYNC
+ ISYNC
+ MOVW R3, ret+16(FP)
+ RET
+
+TEXT runtime∕internal∕atomic·Xchg64(SB), NOSPLIT, $0-24
+ MOVD ptr+0(FP), R4
+ MOVD new+8(FP), R5
+ SYNC
+ LDAR (R4), R3
+ STDCCC R5, (R4)
+ BNE -3(PC)
+ SYNC
+ ISYNC
+ MOVD R3, ret+16(FP)
+ RET
+
+TEXT runtime∕internal∕atomic·Xchguintptr(SB), NOSPLIT, $0-24
+ BR runtime∕internal∕atomic·Xchg64(SB)
+
+
+TEXT runtime∕internal∕atomic·Storep1(SB), NOSPLIT, $0-16
+ BR runtime∕internal∕atomic·Store64(SB)
+
+TEXT runtime∕internal∕atomic·Store(SB), NOSPLIT, $0-12
+ MOVD ptr+0(FP), R3
+ MOVW val+8(FP), R4
+ SYNC
+ MOVW R4, 0(R3)
+ RET
+
+TEXT runtime∕internal∕atomic·Store64(SB), NOSPLIT, $0-16
+ MOVD ptr+0(FP), R3
+ MOVD val+8(FP), R4
+ SYNC
+ MOVD R4, 0(R3)
+ RET
+
+// void runtime∕internal∕atomic·Or8(byte volatile*, byte);
+TEXT runtime∕internal∕atomic·Or8(SB), NOSPLIT, $0-9
+ MOVD ptr+0(FP), R3
+ MOVBZ val+8(FP), R4
+ // Align ptr down to 4 bytes so we can use 32-bit load/store.
+ // R5 = (R3 << 0) & ~3
+ RLDCR $0, R3, $~3, R5
+ // Compute val shift.
+#ifdef GOARCH_ppc64
+ // Big endian. ptr = ptr ^ 3
+ XOR $3, R3
+#endif
+ // R6 = ((ptr & 3) * 8) = (ptr << 3) & (3*8)
+ RLDC $3, R3, $(3*8), R6
+ // Shift val for aligned ptr. R4 = val << R6
+ SLD R6, R4, R4
+
+again:
+ SYNC
+ LWAR (R5), R6
+ OR R4, R6
+ STWCCC R6, (R5)
+ BNE again
+ SYNC
+ ISYNC
+ RET
+
+// void runtime∕internal∕atomic·And8(byte volatile*, byte);
+TEXT runtime∕internal∕atomic·And8(SB), NOSPLIT, $0-9
+ MOVD ptr+0(FP), R3
+ MOVBZ val+8(FP), R4
+ // Align ptr down to 4 bytes so we can use 32-bit load/store.
+ // R5 = (R3 << 0) & ~3
+ RLDCR $0, R3, $~3, R5
+ // Compute val shift.
+#ifdef GOARCH_ppc64
+ // Big endian. ptr = ptr ^ 3
+ XOR $3, R3
+#endif
+ // R6 = ((ptr & 3) * 8) = (ptr << 3) & (3*8)
+ RLDC $3, R3, $(3*8), R6
+ // Shift val for aligned ptr. R4 = val << R6 | ^(0xFF << R6)
+ MOVD $0xFF, R7
+ SLD R6, R4
+ SLD R6, R7
+ XOR $-1, R7
+ OR R7, R4
+again:
+ SYNC
+ LWAR (R5), R6
+ AND R4, R6
+ STWCCC R6, (R5)
+ BNE again
+ SYNC
+ ISYNC
+ RET
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package runtime
+// +build 386
+
+package atomic
import "unsafe"
// code by optimizers will preserve the relative order of memory accesses.
//go:nosplit
-func atomicload(ptr *uint32) uint32 {
+func Load(ptr *uint32) uint32 {
nop()
return *ptr
}
//go:nosplit
-func atomicloadp(ptr unsafe.Pointer) unsafe.Pointer {
+func Loadp(ptr unsafe.Pointer) unsafe.Pointer {
nop()
return *(*unsafe.Pointer)(ptr)
}
//go:nosplit
-func xadd64(ptr *uint64, delta int64) uint64 {
+func Xadd64(ptr *uint64, delta int64) uint64 {
for {
old := *ptr
- if cas64(ptr, old, old+uint64(delta)) {
+ if Cas64(ptr, old, old+uint64(delta)) {
return old + uint64(delta)
}
}
}
//go:noescape
-//go:linkname xadduintptr runtime.xadd
-func xadduintptr(ptr *uintptr, delta uintptr) uintptr
+func Xadduintptr(ptr *uintptr, delta uintptr) uintptr
//go:nosplit
-func xchg64(ptr *uint64, new uint64) uint64 {
+func Xchg64(ptr *uint64, new uint64) uint64 {
for {
old := *ptr
- if cas64(ptr, old, new) {
+ if Cas64(ptr, old, new) {
return old
}
}
}
//go:noescape
-func xadd(ptr *uint32, delta int32) uint32
+func Xadd(ptr *uint32, delta int32) uint32
//go:noescape
-func xchg(ptr *uint32, new uint32) uint32
+func Xchg(ptr *uint32, new uint32) uint32
//go:noescape
-func xchguintptr(ptr *uintptr, new uintptr) uintptr
+func Xchguintptr(ptr *uintptr, new uintptr) uintptr
//go:noescape
-func atomicload64(ptr *uint64) uint64
+func Load64(ptr *uint64) uint64
//go:noescape
-func atomicand8(ptr *uint8, val uint8)
+func And8(ptr *uint8, val uint8)
//go:noescape
-func atomicor8(ptr *uint8, val uint8)
+func Or8(ptr *uint8, val uint8)
// NOTE: Do not add atomicxor8 (XOR is not idempotent).
//go:noescape
-func cas64(ptr *uint64, old, new uint64) bool
+func Cas64(ptr *uint64, old, new uint64) bool
//go:noescape
-func atomicstore(ptr *uint32, val uint32)
+func Store(ptr *uint32, val uint32)
//go:noescape
-func atomicstore64(ptr *uint64, val uint64)
+func Store64(ptr *uint64, val uint64)
// NO go:noescape annotation; see atomic_pointer.go.
-func atomicstorep1(ptr unsafe.Pointer, val unsafe.Pointer)
+func Storep1(ptr unsafe.Pointer, val unsafe.Pointer)
// +build amd64 amd64p32
-package runtime
+package atomic
import "unsafe"
// code by optimizers will preserve the relative order of memory accesses.
//go:nosplit
-func atomicload(ptr *uint32) uint32 {
+func Load(ptr *uint32) uint32 {
nop()
return *ptr
}
//go:nosplit
-func atomicloadp(ptr unsafe.Pointer) unsafe.Pointer {
+func Loadp(ptr unsafe.Pointer) unsafe.Pointer {
nop()
return *(*unsafe.Pointer)(ptr)
}
//go:nosplit
-func atomicload64(ptr *uint64) uint64 {
+func Load64(ptr *uint64) uint64 {
nop()
return *ptr
}
//go:noescape
-func xadd(ptr *uint32, delta int32) uint32
+func Xadd(ptr *uint32, delta int32) uint32
//go:noescape
-func xadd64(ptr *uint64, delta int64) uint64
+func Xadd64(ptr *uint64, delta int64) uint64
//go:noescape
-func xadduintptr(ptr *uintptr, delta uintptr) uintptr
+func Xadduintptr(ptr *uintptr, delta uintptr) uintptr
//go:noescape
-func xchg(ptr *uint32, new uint32) uint32
+func Xchg(ptr *uint32, new uint32) uint32
//go:noescape
-func xchg64(ptr *uint64, new uint64) uint64
+func Xchg64(ptr *uint64, new uint64) uint64
//go:noescape
-func xchguintptr(ptr *uintptr, new uintptr) uintptr
+func Xchguintptr(ptr *uintptr, new uintptr) uintptr
//go:noescape
-func atomicand8(ptr *uint8, val uint8)
+func And8(ptr *uint8, val uint8)
//go:noescape
-func atomicor8(ptr *uint8, val uint8)
+func Or8(ptr *uint8, val uint8)
// NOTE: Do not add atomicxor8 (XOR is not idempotent).
//go:noescape
-func cas64(ptr *uint64, old, new uint64) bool
+func Cas64(ptr *uint64, old, new uint64) bool
//go:noescape
-func atomicstore(ptr *uint32, val uint32)
+func Store(ptr *uint32, val uint32)
//go:noescape
-func atomicstore64(ptr *uint64, val uint64)
+func Store64(ptr *uint64, val uint64)
// NO go:noescape annotation; see atomic_pointer.go.
-func atomicstorep1(ptr unsafe.Pointer, val unsafe.Pointer)
+func Storep1(ptr unsafe.Pointer, val unsafe.Pointer)
--- /dev/null
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build arm
+
+package atomic
+
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
+
+type spinlock struct {
+ v uint32
+}
+
+//go:nosplit
+func (l *spinlock) lock() {
+ for {
+ if Cas(&l.v, 0, 1) {
+ return
+ }
+ }
+}
+
+//go:nosplit
+func (l *spinlock) unlock() {
+ Store(&l.v, 0)
+}
+
+var locktab [57]struct {
+ l spinlock
+ pad [sys.CacheLineSize - unsafe.Sizeof(spinlock{})]byte
+}
+
+func addrLock(addr *uint64) *spinlock {
+ return &locktab[(uintptr(unsafe.Pointer(addr))>>3)%uintptr(len(locktab))].l
+}
+
+// Atomic add and return new value.
+//go:nosplit
+func Xadd(val *uint32, delta int32) uint32 {
+ for {
+ oval := *val
+ nval := oval + uint32(delta)
+ if Cas(val, oval, nval) {
+ return nval
+ }
+ }
+}
+
+//go:noescape
+func Xadduintptr(ptr *uintptr, delta uintptr) uintptr
+
+//go:nosplit
+func Xchg(addr *uint32, v uint32) uint32 {
+ for {
+ old := *addr
+ if Cas(addr, old, v) {
+ return old
+ }
+ }
+}
+
+//go:nosplit
+func Xchguintptr(addr *uintptr, v uintptr) uintptr {
+ return uintptr(Xchg((*uint32)(unsafe.Pointer(addr)), uint32(v)))
+}
+
+//go:nosplit
+func Load(addr *uint32) uint32 {
+ return Xadd(addr, 0)
+}
+
+// Should be a built-in for unsafe.Pointer?
+//go:nosplit
+func add(p unsafe.Pointer, x uintptr) unsafe.Pointer {
+ return unsafe.Pointer(uintptr(p) + x)
+}
+
+//go:nosplit
+func Loadp(addr unsafe.Pointer) unsafe.Pointer {
+ return unsafe.Pointer(uintptr(Xadd((*uint32)(addr), 0)))
+}
+
+//go:nosplit
+func Storep1(addr unsafe.Pointer, v unsafe.Pointer) {
+ for {
+ old := *(*unsafe.Pointer)(addr)
+ if Casp1((*unsafe.Pointer)(addr), old, v) {
+ return
+ }
+ }
+}
+
+//go:nosplit
+func Store(addr *uint32, v uint32) {
+ for {
+ old := *addr
+ if Cas(addr, old, v) {
+ return
+ }
+ }
+}
+
+//go:nosplit
+func Cas64(addr *uint64, old, new uint64) bool {
+ var ok bool
+ addrLock(addr).lock()
+ if *addr == old {
+ *addr = new
+ ok = true
+ }
+ addrLock(addr).unlock()
+ return ok
+}
+
+//go:nosplit
+func Xadd64(addr *uint64, delta int64) uint64 {
+ var r uint64
+ addrLock(addr).lock()
+ r = *addr + uint64(delta)
+ *addr = r
+ addrLock(addr).unlock()
+ return r
+}
+
+//go:nosplit
+func Xchg64(addr *uint64, v uint64) uint64 {
+ var r uint64
+ addrLock(addr).lock()
+ r = *addr
+ *addr = v
+ addrLock(addr).unlock()
+ return r
+}
+
+//go:nosplit
+func Load64(addr *uint64) uint64 {
+ var r uint64
+ addrLock(addr).lock()
+ r = *addr
+ addrLock(addr).unlock()
+ return r
+}
+
+//go:nosplit
+func Store64(addr *uint64, v uint64) {
+ addrLock(addr).lock()
+ *addr = v
+ addrLock(addr).unlock()
+}
+
+//go:nosplit
+func Or8(addr *uint8, v uint8) {
+ // Align down to 4 bytes and use 32-bit CAS.
+ uaddr := uintptr(unsafe.Pointer(addr))
+ addr32 := (*uint32)(unsafe.Pointer(uaddr &^ 3))
+ word := uint32(v) << ((uaddr & 3) * 8) // little endian
+ for {
+ old := *addr32
+ if Cas(addr32, old, old|word) {
+ return
+ }
+ }
+}
+
+//go:nosplit
+func And8(addr *uint8, v uint8) {
+ // Align down to 4 bytes and use 32-bit CAS.
+ uaddr := uintptr(unsafe.Pointer(addr))
+ addr32 := (*uint32)(unsafe.Pointer(uaddr &^ 3))
+ word := uint32(v) << ((uaddr & 3) * 8) // little endian
+ mask := uint32(0xFF) << ((uaddr & 3) * 8) // little endian
+ word |= ^mask
+ for {
+ old := *addr32
+ if Cas(addr32, old, old&word) {
+ return
+ }
+ }
+}
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package runtime
+// +build arm64
+
+package atomic
import "unsafe"
//go:noescape
-func xadd(ptr *uint32, delta int32) uint32
+func Xadd(ptr *uint32, delta int32) uint32
//go:noescape
-func xadd64(ptr *uint64, delta int64) uint64
+func Xadd64(ptr *uint64, delta int64) uint64
//go:noescape
-//go:linkname xadduintptr runtime.xadd64
-func xadduintptr(ptr *uintptr, delta uintptr) uintptr
+func Xadduintptr(ptr *uintptr, delta uintptr) uintptr
//go:noescape
-func xchg(ptr *uint32, new uint32) uint32
+func Xchg(ptr *uint32, new uint32) uint32
//go:noescape
-func xchg64(ptr *uint64, new uint64) uint64
+func Xchg64(ptr *uint64, new uint64) uint64
//go:noescape
-func xchguintptr(ptr *uintptr, new uintptr) uintptr
+func Xchguintptr(ptr *uintptr, new uintptr) uintptr
//go:noescape
-func atomicload(ptr *uint32) uint32
+func Load(ptr *uint32) uint32
//go:noescape
-func atomicload64(ptr *uint64) uint64
+func Load64(ptr *uint64) uint64
//go:noescape
-func atomicloadp(ptr unsafe.Pointer) unsafe.Pointer
+func Loadp(ptr unsafe.Pointer) unsafe.Pointer
//go:nosplit
-func atomicor8(addr *uint8, v uint8) {
+func Or8(addr *uint8, v uint8) {
// TODO(dfc) implement this in asm.
// Align down to 4 bytes and use 32-bit CAS.
uaddr := uintptr(unsafe.Pointer(addr))
word := uint32(v) << ((uaddr & 3) * 8) // little endian
for {
old := *addr32
- if cas(addr32, old, old|word) {
+ if Cas(addr32, old, old|word) {
return
}
}
}
//go:nosplit
-func atomicand8(addr *uint8, v uint8) {
+func And8(addr *uint8, v uint8) {
// TODO(dfc) implement this in asm.
// Align down to 4 bytes and use 32-bit CAS.
uaddr := uintptr(unsafe.Pointer(addr))
word |= ^mask
for {
old := *addr32
- if cas(addr32, old, old&word) {
+ if Cas(addr32, old, old&word) {
return
}
}
}
//go:noescape
-func cas64(ptr *uint64, old, new uint64) bool
+func Cas64(ptr *uint64, old, new uint64) bool
//go:noescape
-func atomicstore(ptr *uint32, val uint32)
+func Store(ptr *uint32, val uint32)
//go:noescape
-func atomicstore64(ptr *uint64, val uint64)
+func Store64(ptr *uint64, val uint64)
// NO go:noescape annotation; see atomic_pointer.go.
-func atomicstorep1(ptr unsafe.Pointer, val unsafe.Pointer)
+func Storep1(ptr unsafe.Pointer, val unsafe.Pointer)
--- /dev/null
+// 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.
+
+#include "textflag.h"
+
+// uint32 runtime∕internal∕atomic·Load(uint32 volatile* addr)
+TEXT ·Load(SB),NOSPLIT,$-8-12
+ MOVD ptr+0(FP), R0
+ LDARW (R0), R0
+ MOVW R0, ret+8(FP)
+ RET
+
+// uint64 runtime∕internal∕atomic·Load64(uint64 volatile* addr)
+TEXT ·Load64(SB),NOSPLIT,$-8-16
+ MOVD ptr+0(FP), R0
+ LDAR (R0), R0
+ MOVD R0, ret+8(FP)
+ RET
+
+// void *runtime∕internal∕atomic·Loadp(void *volatile *addr)
+TEXT ·Loadp(SB),NOSPLIT,$-8-16
+ MOVD ptr+0(FP), R0
+ LDAR (R0), R0
+ MOVD R0, ret+8(FP)
+ RET
+
+TEXT runtime∕internal∕atomic·Storep1(SB), NOSPLIT, $0-16
+ B runtime∕internal∕atomic·Store64(SB)
+
+TEXT runtime∕internal∕atomic·Store(SB), NOSPLIT, $0-12
+ MOVD ptr+0(FP), R0
+ MOVW val+8(FP), R1
+ STLRW R1, (R0)
+ RET
+
+TEXT runtime∕internal∕atomic·Store64(SB), NOSPLIT, $0-16
+ MOVD ptr+0(FP), R0
+ MOVD val+8(FP), R1
+ STLR R1, (R0)
+ RET
+
+TEXT runtime∕internal∕atomic·Xchg(SB), NOSPLIT, $0-20
+again:
+ MOVD ptr+0(FP), R0
+ MOVW new+8(FP), R1
+ LDAXRW (R0), R2
+ STLXRW R1, (R0), R3
+ CBNZ R3, again
+ MOVW R2, ret+16(FP)
+ RET
+
+TEXT runtime∕internal∕atomic·Xchg64(SB), NOSPLIT, $0-24
+again:
+ MOVD ptr+0(FP), R0
+ MOVD new+8(FP), R1
+ LDAXR (R0), R2
+ STLXR R1, (R0), R3
+ CBNZ R3, again
+ MOVD R2, ret+16(FP)
+ RET
+
+// bool runtime∕internal∕atomic·Cas64(uint64 *ptr, uint64 old, uint64 new)
+// Atomically:
+// if(*val == *old){
+// *val = new;
+// return 1;
+// } else {
+// return 0;
+// }
+TEXT runtime∕internal∕atomic·Cas64(SB), NOSPLIT, $0-25
+ MOVD ptr+0(FP), R0
+ MOVD old+8(FP), R1
+ MOVD new+16(FP), R2
+again:
+ LDAXR (R0), R3
+ CMP R1, R3
+ BNE ok
+ STLXR R2, (R0), R3
+ CBNZ R3, again
+ok:
+ CSET EQ, R0
+ MOVB R0, ret+24(FP)
+ RET
+
+// uint32 xadd(uint32 volatile *ptr, int32 delta)
+// Atomically:
+// *val += delta;
+// return *val;
+TEXT runtime∕internal∕atomic·Xadd(SB), NOSPLIT, $0-20
+again:
+ MOVD ptr+0(FP), R0
+ MOVW delta+8(FP), R1
+ LDAXRW (R0), R2
+ ADDW R2, R1, R2
+ STLXRW R2, (R0), R3
+ CBNZ R3, again
+ MOVW R2, ret+16(FP)
+ RET
+
+TEXT runtime∕internal∕atomic·Xadd64(SB), NOSPLIT, $0-24
+again:
+ MOVD ptr+0(FP), R0
+ MOVD delta+8(FP), R1
+ LDAXR (R0), R2
+ ADD R2, R1, R2
+ STLXR R2, (R0), R3
+ CBNZ R3, again
+ MOVD R2, ret+16(FP)
+ RET
+
+TEXT runtime∕internal∕atomic·Xchguintptr(SB), NOSPLIT, $0-24
+ B runtime∕internal∕atomic·Xchg64(SB)
--- /dev/null
+// Copyright 2015 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 mips64 mips64le
+
+package atomic
+
+import "unsafe"
+
+//go:noescape
+func Xadd(ptr *uint32, delta int32) uint32
+
+//go:noescape
+func Xadd64(ptr *uint64, delta int64) uint64
+
+//go:noescape
+func Xadduintptr(ptr *uintptr, delta uintptr) uintptr
+
+//go:noescape
+func Xchg(ptr *uint32, new uint32) uint32
+
+//go:noescape
+func Xchg64(ptr *uint64, new uint64) uint64
+
+//go:noescape
+func Xchguintptr(ptr *uintptr, new uintptr) uintptr
+
+//go:noescape
+func Load(ptr *uint32) uint32
+
+//go:noescape
+func Load64(ptr *uint64) uint64
+
+//go:noescape
+func Loadp(ptr unsafe.Pointer) unsafe.Pointer
+
+//go:noescape
+func And8(ptr *uint8, val uint8)
+
+//go:noescape
+func Or8(ptr *uint8, val uint8)
+
+// NOTE: Do not add atomicxor8 (XOR is not idempotent).
+
+//go:noescape
+func Cas64(ptr *uint64, old, new uint64) bool
+
+//go:noescape
+func Store(ptr *uint32, val uint32)
+
+//go:noescape
+func Store64(ptr *uint64, val uint64)
+
+// NO go:noescape annotation; see atomic_pointer.go.
+func Storep1(ptr unsafe.Pointer, val unsafe.Pointer)
--- /dev/null
+// Copyright 2015 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 mips64 mips64le
+
+#include "textflag.h"
+
+#define SYNC WORD $0xf
+
+// uint32 runtime∕internal∕atomic·Load(uint32 volatile* addr)
+TEXT ·Load(SB),NOSPLIT,$-8-12
+ MOVV addr+0(FP), R1
+ SYNC
+ MOVWU 0(R1), R1
+ SYNC
+ MOVW R1, ret+8(FP)
+ RET
+
+// uint64 runtime∕internal∕atomic·Load64(uint64 volatile* addr)
+TEXT ·Load64(SB),NOSPLIT,$-8-16
+ MOVV addr+0(FP), R1
+ SYNC
+ MOVV 0(R1), R1
+ SYNC
+ MOVV R1, ret+8(FP)
+ RET
+
+// void *runtime∕internal∕atomic·Loadp(void *volatile *addr)
+TEXT ·Loadp(SB),NOSPLIT,$-8-16
+ MOVV addr+0(FP), R1
+ SYNC
+ MOVV 0(R1), R1
+ SYNC
+ MOVV R1, ret+8(FP)
+ RET
--- /dev/null
+// 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 ppc64 ppc64le
+
+package atomic
+
+import "unsafe"
+
+//go:noescape
+func Xadd(ptr *uint32, delta int32) uint32
+
+//go:noescape
+func Xadd64(ptr *uint64, delta int64) uint64
+
+//go:noescape
+func Xadduintptr(ptr *uintptr, delta uintptr) uintptr
+
+//go:noescape
+func Xchg(ptr *uint32, new uint32) uint32
+
+//go:noescape
+func Xchg64(ptr *uint64, new uint64) uint64
+
+//go:noescape
+func Xchguintptr(ptr *uintptr, new uintptr) uintptr
+
+//go:noescape
+func Load(ptr *uint32) uint32
+
+//go:noescape
+func Load64(ptr *uint64) uint64
+
+//go:noescape
+func Loadp(ptr unsafe.Pointer) unsafe.Pointer
+
+//go:noescape
+func And8(ptr *uint8, val uint8)
+
+//go:noescape
+func Or8(ptr *uint8, val uint8)
+
+// NOTE: Do not add atomicxor8 (XOR is not idempotent).
+
+//go:noescape
+func Cas64(ptr *uint64, old, new uint64) bool
+
+//go:noescape
+func Store(ptr *uint32, val uint32)
+
+//go:noescape
+func Store64(ptr *uint64, val uint64)
+
+// NO go:noescape annotation; see atomic_pointer.go.
+func Storep1(ptr unsafe.Pointer, val unsafe.Pointer)
--- /dev/null
+// 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 ppc64 ppc64le
+
+#include "textflag.h"
+
+// uint32 runtime∕internal∕atomic·Load(uint32 volatile* addr)
+TEXT ·Load(SB),NOSPLIT|NOFRAME,$-8-12
+ MOVD addr+0(FP), R3
+ SYNC
+ MOVWZ 0(R3), R3
+ CMPW R3, R3, CR7
+ BC 4, 30, 1(PC) // bne- cr7,0x4
+ ISYNC
+ MOVW R3, ret+8(FP)
+ RET
+
+// uint64 runtime∕internal∕atomic·Load64(uint64 volatile* addr)
+TEXT ·Load64(SB),NOSPLIT|NOFRAME,$-8-16
+ MOVD addr+0(FP), R3
+ SYNC
+ MOVD 0(R3), R3
+ CMP R3, R3, CR7
+ BC 4, 30, 1(PC) // bne- cr7,0x4
+ ISYNC
+ MOVD R3, ret+8(FP)
+ RET
+
+// void *runtime∕internal∕atomic·Loadp(void *volatile *addr)
+TEXT ·Loadp(SB),NOSPLIT|NOFRAME,$-8-16
+ MOVD addr+0(FP), R3
+ SYNC
+ MOVD 0(R3), R3
+ CMP R3, R3, CR7
+ BC 4, 30, 1(PC) // bne- cr7,0x4
+ ISYNC
+ MOVD R3, ret+8(FP)
+ RET
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package runtime_test
+package atomic_test
import (
"runtime"
+ "runtime/internal/atomic"
"testing"
"unsafe"
)
inc := uintptr(100)
total := uintptr(0)
runParallel(N, iter, func() {
- runtime.Xadduintptr(&total, inc)
+ atomic.Xadduintptr(&total, inc)
})
if want := uintptr(N * iter * inc); want != total {
t.Fatalf("xadduintpr error, want %d, got %d", want, total)
}
total = 0
runParallel(N, iter, func() {
- runtime.Xadduintptr(&total, inc)
- runtime.Xadduintptr(&total, uintptr(-int64(inc)))
+ atomic.Xadduintptr(&total, inc)
+ atomic.Xadduintptr(&total, uintptr(-int64(inc)))
})
if total != 0 {
t.Fatalf("xadduintpr total error, want %d, got %d", 0, total)
// Tests that xadduintptr correctly updates 64-bit values. The place where
// we actually do so is mstats.go, functions mSysStat{Inc,Dec}.
func TestXadduintptrOnUint64(t *testing.T) {
- if runtime.BigEndian != 0 {
+ /* if runtime.BigEndian != 0 {
// On big endian architectures, we never use xadduintptr to update
// 64-bit values and hence we skip the test. (Note that functions
// mSysStat{Inc,Dec} in mstats.go have explicit checks for
// big-endianness.)
return
- }
+ }*/
const inc = 100
val := uint64(0)
- runtime.Xadduintptr((*uintptr)(unsafe.Pointer(&val)), inc)
+ atomic.Xadduintptr((*uintptr)(unsafe.Pointer(&val)), inc)
if inc != val {
t.Fatalf("xadduintptr should increase lower-order bits, want %d, got %d", inc, val)
}
--- /dev/null
+// Copyright 2015 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 atomic
+
+import "unsafe"
+
+//go:noescape
+func Cas(ptr *uint32, old, new uint32) bool
+
+// NO go:noescape annotation; see atomic_pointer.go.
+func Casp1(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool
+
+func nop() // call to prevent inlining of function body
+
+//go:noescape
+func Casuintptr(ptr *uintptr, old, new uintptr) bool
+
+//go:noescape
+func Storeuintptr(ptr *uintptr, new uintptr)
+
+//go:noescape
+func Loaduintptr(ptr *uintptr) uintptr
+
+//go:noescape
+func Loaduint(ptr *uint) uint
+
+// TODO(matloob): Should these functions have the go:noescape annotation?
+
+//go:noescape
+func Loadint64(ptr *int64) int64
+
+//go:noescape
+func Xaddint64(ptr *int64, delta int64) int64
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+TEXT runtime∕internal∕atomic·Cas(SB),NOSPLIT,$0
+ B runtime∕internal∕atomic·armcas(SB)
+
+TEXT runtime∕internal∕atomic·Casp1(SB),NOSPLIT,$0
+ B runtime∕internal∕atomic·Cas(SB)
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+// TODO(minux): this is only valid for ARMv6+
+// bool armcas(int32 *val, int32 old, int32 new)
+// Atomically:
+// if(*val == old){
+// *val = new;
+// return 1;
+// }else
+// return 0;
+TEXT runtime∕internal∕atomic·Cas(SB),NOSPLIT,$0
+ B runtime∕internal∕atomic·armcas(SB)
+
+TEXT runtime∕internal∕atomic·Casp1(SB),NOSPLIT,$0
+ B runtime∕internal∕atomic·Cas(SB)
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+// Use kernel version instead of native armcas in asm_arm.s.
+// See ../../../sync/atomic/asm_linux_arm.s for details.
+TEXT cas<>(SB),NOSPLIT,$0
+ MOVW $0xffff0fc0, R15 // R15 is hardware PC.
+
+TEXT runtime∕internal∕atomic·Cas(SB),NOSPLIT,$0
+ MOVW ptr+0(FP), R2
+ MOVW old+4(FP), R0
+loop:
+ MOVW new+8(FP), R1
+ BL cas<>(SB)
+ BCC check
+ MOVW $1, R0
+ MOVB R0, ret+12(FP)
+ RET
+check:
+ // Kernel lies; double-check.
+ MOVW ptr+0(FP), R2
+ MOVW old+4(FP), R0
+ MOVW 0(R2), R3
+ CMP R0, R3
+ BEQ loop
+ MOVW $0, R0
+ MOVB R0, ret+12(FP)
+ RET
+
+TEXT runtime∕internal∕atomic·Casp1(SB),NOSPLIT,$0
+ B runtime∕internal∕atomic·Cas(SB)
+
+// As for cas, memory barriers are complicated on ARM, but the kernel
+// provides a user helper. ARMv5 does not support SMP and has no
+// memory barrier instruction at all. ARMv6 added SMP support and has
+// a memory barrier, but it requires writing to a coprocessor
+// register. ARMv7 introduced the DMB instruction, but it's expensive
+// even on single-core devices. The kernel helper takes care of all of
+// this for us.
\ No newline at end of file
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+TEXT runtime∕internal∕atomic·Casp(SB),NOSPLIT,$0
+ B runtime·cas(SB)
+
+// This is only valid for ARMv6+, however, NaCl/ARM is only defined
+// for ARMv7A anyway.
+TEXT runtime∕internal∕atomic·Cas(SB),NOSPLIT,$0
+ B runtime∕internal∕atomic·armcas(SB)
+
+TEXT runtime∕internal∕atomic·Casp1(SB),NOSPLIT,$0
+ B runtime∕internal∕atomic·Cas(SB)
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+// TODO(minux): this is only valid for ARMv6+
+// bool Armcas(int32 *val, int32 old, int32 new)
+// Atomically:
+// if(*val == old){
+// *val = new;
+// return 1;
+// }else
+// return 0;
+TEXT runtime∕internal∕atomic·Cas(SB),NOSPLIT,$0
+ B runtime∕internal∕atomic·armcas(SB)
+
+TEXT runtime∕internal∕atomic·Casp1(SB),NOSPLIT,$0
+ B runtime∕internal∕atomic·Cas(SB)
+
+
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+TEXT runtime∕internal∕atomic·Cas(SB),NOSPLIT,$0
+ B runtime∕internal∕atomic·armcas(SB)
+
+TEXT runtime∕internal∕atomic·Casp1(SB),NOSPLIT,$0
+ B runtime∕internal∕atomic·Cas(SB)
--- /dev/null
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sys
+
+const (
+ TheChar = '8'
+ BigEndian = 0
+ CacheLineSize = 64
+ PhysPageSize = GoosNacl*65536 + (1-GoosNacl)*4096 // 4k normally; 64k on NaCl
+ PCQuantum = 1
+ Int64Align = 4
+ HugePageSize = 1 << 21
+ MinFrameSize = 0
+)
+
+type Uintreg uint32
--- /dev/null
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sys
+
+const (
+ TheChar = '6'
+ BigEndian = 0
+ CacheLineSize = 64
+ PhysPageSize = 4096
+ PCQuantum = 1
+ Int64Align = 8
+ HugePageSize = 1 << 21
+ MinFrameSize = 0
+)
+
+type Uintreg uint64
--- /dev/null
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sys
+
+const (
+ TheChar = '6'
+ BigEndian = 0
+ CacheLineSize = 64
+ PhysPageSize = 65536*GoosNacl + 4096*(1-GoosNacl)
+ PCQuantum = 1
+ Int64Align = 8
+ HugePageSize = 1 << 21
+ MinFrameSize = 0
+)
+
+type Uintreg uint64
--- /dev/null
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sys
+
+const (
+ TheChar = '5'
+ BigEndian = 0
+ CacheLineSize = 32
+ PhysPageSize = 65536*GoosNacl + 4096*(1-GoosNacl)
+ PCQuantum = 4
+ Int64Align = 4
+ HugePageSize = 0
+ MinFrameSize = 4
+)
+
+type Uintreg uint32
--- /dev/null
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sys
+
+const (
+ TheChar = '7'
+ BigEndian = 0
+ CacheLineSize = 32
+ PhysPageSize = 65536
+ PCQuantum = 4
+ Int64Align = 8
+ HugePageSize = 0
+ MinFrameSize = 8
+)
+
+type Uintreg uint64
--- /dev/null
+// Copyright 2015 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 sys
+
+const (
+ TheChar = '0'
+ BigEndian = 1
+ CacheLineSize = 32
+ PhysPageSize = 16384
+ PCQuantum = 4
+ Int64Align = 8
+ HugePageSize = 0
+ MinFrameSize = 8
+)
+
+type Uintreg uint64
--- /dev/null
+// Copyright 2015 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 sys
+
+const (
+ TheChar = '0'
+ BigEndian = 0
+ CacheLineSize = 32
+ PhysPageSize = 16384
+ PCQuantum = 4
+ Int64Align = 8
+ HugePageSize = 0
+ MinFrameSize = 8
+)
+
+type Uintreg uint64
--- /dev/null
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sys
+
+const (
+ TheChar = '9'
+ BigEndian = 1
+ CacheLineSize = 64
+ PhysPageSize = 65536
+ PCQuantum = 4
+ Int64Align = 8
+ HugePageSize = 0
+ MinFrameSize = 32
+)
+
+type Uintreg uint64
--- /dev/null
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sys
+
+const (
+ TheChar = '9'
+ BigEndian = 0
+ CacheLineSize = 64
+ PhysPageSize = 65536
+ PCQuantum = 4
+ Int64Align = 8
+ HugePageSize = 0
+ MinFrameSize = 32
+)
+
+type Uintreg uint64
var gooses, goarches []string
func main() {
- data, err := ioutil.ReadFile("../go/build/syslist.go")
+ data, err := ioutil.ReadFile("../../../go/build/syslist.go")
if err != nil {
log.Fatal(err)
}
if target == "linux" {
fmt.Fprintf(&buf, "// +build !android\n\n") // must explicitly exclude android for linux
}
- fmt.Fprintf(&buf, "package runtime\n\n")
- fmt.Fprintf(&buf, "const theGoos = `%s`\n\n", target)
+ fmt.Fprintf(&buf, "package sys\n\n")
+ fmt.Fprintf(&buf, "const TheGoos = `%s`\n\n", target)
for _, goos := range gooses {
value := 0
if goos == target {
value = 1
}
- fmt.Fprintf(&buf, "const goos_%s = %d\n", goos, value)
+ fmt.Fprintf(&buf, "const Goos%s = %d\n", strings.Title(goos), value)
}
err := ioutil.WriteFile("zgoos_"+target+".go", buf.Bytes(), 0666)
if err != nil {
for _, target := range goarches {
var buf bytes.Buffer
fmt.Fprintf(&buf, "// generated by gengoos.go using 'go generate'\n\n")
- fmt.Fprintf(&buf, "package runtime\n\n")
- fmt.Fprintf(&buf, "const theGoarch = `%s`\n\n", target)
+ fmt.Fprintf(&buf, "package sys\n\n")
+ fmt.Fprintf(&buf, "const TheGoarch = `%s`\n\n", target)
for _, goarch := range goarches {
value := 0
if goarch == target {
value = 1
}
- fmt.Fprintf(&buf, "const goarch_%s = %d\n", goarch, value)
+ fmt.Fprintf(&buf, "const Goarch%s = %d\n", strings.Title(goarch), value)
}
err := ioutil.WriteFile("zgoarch_"+target+".go", buf.Bytes(), 0666)
if err != nil {
--- /dev/null
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sys
+
+// Declarations for runtime services implemented in C or assembly.
+
+const PtrSize = 4 << (^uintptr(0) >> 63) // unsafe.Sizeof(uintptr(0)) but an ideal const
+const RegSize = 4 << (^Uintreg(0) >> 63) // unsafe.Sizeof(uintreg(0)) but an ideal const
+const SpAlign = 1*(1-GoarchArm64) + 16*GoarchArm64 // SP alignment: 1 normally, 16 for ARM64
--- /dev/null
+// Copyright 2015 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 sys contains system- and configuration- and architecture-specific
+// constants used by the runtime.
+package sys
+
+// The next line makes 'go generate' write the zgen_*.go files with
+// per-OS and per-arch information, including constants
+// named goos_$GOOS and goarch_$GOARCH for every
+// known GOOS and GOARCH. The constant is 1 on the
+// current system, 0 otherwise; multiplying by them is
+// useful for defining GOOS- or GOARCH-specific constants.
+//go:generate go run gengoos.go
--- /dev/null
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoarch = `386`
+
+const Goarch386 = 1
+const GoarchAmd64 = 0
+const GoarchAmd64p32 = 0
+const GoarchArm = 0
+const GoarchArmbe = 0
+const GoarchArm64 = 0
+const GoarchArm64be = 0
+const GoarchPpc64 = 0
+const GoarchPpc64le = 0
+const GoarchMips = 0
+const GoarchMipsle = 0
+const GoarchMips64 = 0
+const GoarchMips64le = 0
+const GoarchMips64p32 = 0
+const GoarchMips64p32le = 0
+const GoarchPpc = 0
+const GoarchS390 = 0
+const GoarchS390x = 0
+const GoarchSparc = 0
+const GoarchSparc64 = 0
--- /dev/null
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoarch = `amd64`
+
+const Goarch386 = 0
+const GoarchAmd64 = 1
+const GoarchAmd64p32 = 0
+const GoarchArm = 0
+const GoarchArmbe = 0
+const GoarchArm64 = 0
+const GoarchArm64be = 0
+const GoarchPpc64 = 0
+const GoarchPpc64le = 0
+const GoarchMips = 0
+const GoarchMipsle = 0
+const GoarchMips64 = 0
+const GoarchMips64le = 0
+const GoarchMips64p32 = 0
+const GoarchMips64p32le = 0
+const GoarchPpc = 0
+const GoarchS390 = 0
+const GoarchS390x = 0
+const GoarchSparc = 0
+const GoarchSparc64 = 0
--- /dev/null
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoarch = `amd64p32`
+
+const Goarch386 = 0
+const GoarchAmd64 = 0
+const GoarchAmd64p32 = 1
+const GoarchArm = 0
+const GoarchArmbe = 0
+const GoarchArm64 = 0
+const GoarchArm64be = 0
+const GoarchPpc64 = 0
+const GoarchPpc64le = 0
+const GoarchMips = 0
+const GoarchMipsle = 0
+const GoarchMips64 = 0
+const GoarchMips64le = 0
+const GoarchMips64p32 = 0
+const GoarchMips64p32le = 0
+const GoarchPpc = 0
+const GoarchS390 = 0
+const GoarchS390x = 0
+const GoarchSparc = 0
+const GoarchSparc64 = 0
--- /dev/null
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoarch = `arm`
+
+const Goarch386 = 0
+const GoarchAmd64 = 0
+const GoarchAmd64p32 = 0
+const GoarchArm = 1
+const GoarchArmbe = 0
+const GoarchArm64 = 0
+const GoarchArm64be = 0
+const GoarchPpc64 = 0
+const GoarchPpc64le = 0
+const GoarchMips = 0
+const GoarchMipsle = 0
+const GoarchMips64 = 0
+const GoarchMips64le = 0
+const GoarchMips64p32 = 0
+const GoarchMips64p32le = 0
+const GoarchPpc = 0
+const GoarchS390 = 0
+const GoarchS390x = 0
+const GoarchSparc = 0
+const GoarchSparc64 = 0
--- /dev/null
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoarch = `arm64`
+
+const Goarch386 = 0
+const GoarchAmd64 = 0
+const GoarchAmd64p32 = 0
+const GoarchArm = 0
+const GoarchArmbe = 0
+const GoarchArm64 = 1
+const GoarchArm64be = 0
+const GoarchPpc64 = 0
+const GoarchPpc64le = 0
+const GoarchMips = 0
+const GoarchMipsle = 0
+const GoarchMips64 = 0
+const GoarchMips64le = 0
+const GoarchMips64p32 = 0
+const GoarchMips64p32le = 0
+const GoarchPpc = 0
+const GoarchS390 = 0
+const GoarchS390x = 0
+const GoarchSparc = 0
+const GoarchSparc64 = 0
--- /dev/null
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoarch = `mips64`
+
+const Goarch386 = 0
+const GoarchAmd64 = 0
+const GoarchAmd64p32 = 0
+const GoarchArm = 0
+const GoarchArmbe = 0
+const GoarchArm64 = 0
+const GoarchArm64be = 0
+const GoarchPpc64 = 0
+const GoarchPpc64le = 0
+const GoarchMips = 0
+const GoarchMipsle = 0
+const GoarchMips64 = 1
+const GoarchMips64le = 0
+const GoarchMips64p32 = 0
+const GoarchMips64p32le = 0
+const GoarchPpc = 0
+const GoarchS390 = 0
+const GoarchS390x = 0
+const GoarchSparc = 0
+const GoarchSparc64 = 0
--- /dev/null
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoarch = `mips64le`
+
+const Goarch386 = 0
+const GoarchAmd64 = 0
+const GoarchAmd64p32 = 0
+const GoarchArm = 0
+const GoarchArmbe = 0
+const GoarchArm64 = 0
+const GoarchArm64be = 0
+const GoarchPpc64 = 0
+const GoarchPpc64le = 0
+const GoarchMips = 0
+const GoarchMipsle = 0
+const GoarchMips64 = 0
+const GoarchMips64le = 1
+const GoarchMips64p32 = 0
+const GoarchMips64p32le = 0
+const GoarchPpc = 0
+const GoarchS390 = 0
+const GoarchS390x = 0
+const GoarchSparc = 0
+const GoarchSparc64 = 0
--- /dev/null
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoarch = `ppc64`
+
+const Goarch386 = 0
+const GoarchAmd64 = 0
+const GoarchAmd64p32 = 0
+const GoarchArm = 0
+const GoarchArmbe = 0
+const GoarchArm64 = 0
+const GoarchArm64be = 0
+const GoarchPpc64 = 1
+const GoarchPpc64le = 0
+const GoarchMips = 0
+const GoarchMipsle = 0
+const GoarchMips64 = 0
+const GoarchMips64le = 0
+const GoarchMips64p32 = 0
+const GoarchMips64p32le = 0
+const GoarchPpc = 0
+const GoarchS390 = 0
+const GoarchS390x = 0
+const GoarchSparc = 0
+const GoarchSparc64 = 0
--- /dev/null
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoarch = `ppc64le`
+
+const Goarch386 = 0
+const GoarchAmd64 = 0
+const GoarchAmd64p32 = 0
+const GoarchArm = 0
+const GoarchArmbe = 0
+const GoarchArm64 = 0
+const GoarchArm64be = 0
+const GoarchPpc64 = 0
+const GoarchPpc64le = 1
+const GoarchMips = 0
+const GoarchMipsle = 0
+const GoarchMips64 = 0
+const GoarchMips64le = 0
+const GoarchMips64p32 = 0
+const GoarchMips64p32le = 0
+const GoarchPpc = 0
+const GoarchS390 = 0
+const GoarchS390x = 0
+const GoarchSparc = 0
+const GoarchSparc64 = 0
--- /dev/null
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoos = `android`
+
+const GoosAndroid = 1
+const GoosDarwin = 0
+const GoosDragonfly = 0
+const GoosFreebsd = 0
+const GoosLinux = 0
+const GoosNacl = 0
+const GoosNetbsd = 0
+const GoosOpenbsd = 0
+const GoosPlan9 = 0
+const GoosSolaris = 0
+const GoosWindows = 0
--- /dev/null
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoos = `darwin`
+
+const GoosAndroid = 0
+const GoosDarwin = 1
+const GoosDragonfly = 0
+const GoosFreebsd = 0
+const GoosLinux = 0
+const GoosNacl = 0
+const GoosNetbsd = 0
+const GoosOpenbsd = 0
+const GoosPlan9 = 0
+const GoosSolaris = 0
+const GoosWindows = 0
--- /dev/null
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoos = `dragonfly`
+
+const GoosAndroid = 0
+const GoosDarwin = 0
+const GoosDragonfly = 1
+const GoosFreebsd = 0
+const GoosLinux = 0
+const GoosNacl = 0
+const GoosNetbsd = 0
+const GoosOpenbsd = 0
+const GoosPlan9 = 0
+const GoosSolaris = 0
+const GoosWindows = 0
--- /dev/null
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoos = `freebsd`
+
+const GoosAndroid = 0
+const GoosDarwin = 0
+const GoosDragonfly = 0
+const GoosFreebsd = 1
+const GoosLinux = 0
+const GoosNacl = 0
+const GoosNetbsd = 0
+const GoosOpenbsd = 0
+const GoosPlan9 = 0
+const GoosSolaris = 0
+const GoosWindows = 0
--- /dev/null
+// generated by gengoos.go using 'go generate'
+
+// +build !android
+
+package sys
+
+const TheGoos = `linux`
+
+const GoosAndroid = 0
+const GoosDarwin = 0
+const GoosDragonfly = 0
+const GoosFreebsd = 0
+const GoosLinux = 1
+const GoosNacl = 0
+const GoosNetbsd = 0
+const GoosOpenbsd = 0
+const GoosPlan9 = 0
+const GoosSolaris = 0
+const GoosWindows = 0
--- /dev/null
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoos = `nacl`
+
+const GoosAndroid = 0
+const GoosDarwin = 0
+const GoosDragonfly = 0
+const GoosFreebsd = 0
+const GoosLinux = 0
+const GoosNacl = 1
+const GoosNetbsd = 0
+const GoosOpenbsd = 0
+const GoosPlan9 = 0
+const GoosSolaris = 0
+const GoosWindows = 0
--- /dev/null
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoos = `netbsd`
+
+const GoosAndroid = 0
+const GoosDarwin = 0
+const GoosDragonfly = 0
+const GoosFreebsd = 0
+const GoosLinux = 0
+const GoosNacl = 0
+const GoosNetbsd = 1
+const GoosOpenbsd = 0
+const GoosPlan9 = 0
+const GoosSolaris = 0
+const GoosWindows = 0
--- /dev/null
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoos = `openbsd`
+
+const GoosAndroid = 0
+const GoosDarwin = 0
+const GoosDragonfly = 0
+const GoosFreebsd = 0
+const GoosLinux = 0
+const GoosNacl = 0
+const GoosNetbsd = 0
+const GoosOpenbsd = 1
+const GoosPlan9 = 0
+const GoosSolaris = 0
+const GoosWindows = 0
--- /dev/null
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoos = `plan9`
+
+const GoosAndroid = 0
+const GoosDarwin = 0
+const GoosDragonfly = 0
+const GoosFreebsd = 0
+const GoosLinux = 0
+const GoosNacl = 0
+const GoosNetbsd = 0
+const GoosOpenbsd = 0
+const GoosPlan9 = 1
+const GoosSolaris = 0
+const GoosWindows = 0
--- /dev/null
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoos = `solaris`
+
+const GoosAndroid = 0
+const GoosDarwin = 0
+const GoosDragonfly = 0
+const GoosFreebsd = 0
+const GoosLinux = 0
+const GoosNacl = 0
+const GoosNetbsd = 0
+const GoosOpenbsd = 0
+const GoosPlan9 = 0
+const GoosSolaris = 1
+const GoosWindows = 0
--- /dev/null
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoos = `windows`
+
+const GoosAndroid = 0
+const GoosDarwin = 0
+const GoosDragonfly = 0
+const GoosFreebsd = 0
+const GoosLinux = 0
+const GoosNacl = 0
+const GoosNetbsd = 0
+const GoosOpenbsd = 0
+const GoosPlan9 = 0
+const GoosSolaris = 0
+const GoosWindows = 1
package runtime
-import "unsafe"
+import (
+ "runtime/internal/atomic"
+ "unsafe"
+)
func lfstackpush(head *uint64, node *lfnode) {
node.pushcnt++
new := lfstackPack(node, node.pushcnt)
if node1, _ := lfstackUnpack(new); node1 != node {
- println("runtime: lfstackpush invalid packing: node=", node, " cnt=", hex(node.pushcnt), " packed=", hex(new), " -> node=", node1, "\n")
+ print("runtime: lfstackpush invalid packing: node=", node, " cnt=", hex(node.pushcnt), " packed=", hex(new), " -> node=", node1, "\n")
throw("lfstackpush")
}
for {
- old := atomicload64(head)
+ old := atomic.Load64(head)
node.next = old
- if cas64(head, old, new) {
+ if atomic.Cas64(head, old, new) {
break
}
}
func lfstackpop(head *uint64) unsafe.Pointer {
for {
- old := atomicload64(head)
+ old := atomic.Load64(head)
if old == 0 {
return nil
}
node, _ := lfstackUnpack(old)
- next := atomicload64(&node.next)
- if cas64(head, old, next) {
+ next := atomic.Load64(&node.next)
+ if atomic.Cas64(head, old, next) {
return unsafe.Pointer(node)
}
}
--- /dev/null
+// Copyright 2015 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 mips64 mips64le
+// +build linux
+
+package runtime
+
+import "unsafe"
+
+// On mips64, Linux limits the user address space to 40 bits (see
+// TASK_SIZE64 in the Linux kernel). This has grown over time,
+// so here we allow 48 bit addresses.
+//
+// In addition to the 16 bits taken from the top, we can take 3 from the
+// bottom, because node must be pointer-aligned, giving a total of 19 bits
+// of count.
+const (
+ addrBits = 48
+ cntBits = 64 - addrBits + 3
+)
+
+func lfstackPack(node *lfnode, cnt uintptr) uint64 {
+ return uint64(uintptr(unsafe.Pointer(node)))<<(64-addrBits) | uint64(cnt&(1<<cntBits-1))
+}
+
+func lfstackUnpack(val uint64) (node *lfnode, cnt uintptr) {
+ node = (*lfnode)(unsafe.Pointer(uintptr(val >> cntBits << 3)))
+ cnt = uintptr(val & (1<<cntBits - 1))
+ return
+}
package runtime
-import "unsafe"
+import (
+ "runtime/internal/atomic"
+ "unsafe"
+)
// This implementation depends on OS-specific implementations of
//
gp.m.locks++
// Speculative grab for lock.
- v := xchg(key32(&l.key), mutex_locked)
+ v := atomic.Xchg(key32(&l.key), mutex_locked)
if v == mutex_unlocked {
return
}
// Try for lock, spinning.
for i := 0; i < spin; i++ {
for l.key == mutex_unlocked {
- if cas(key32(&l.key), mutex_unlocked, wait) {
+ if atomic.Cas(key32(&l.key), mutex_unlocked, wait) {
return
}
}
// Try for lock, rescheduling.
for i := 0; i < passive_spin; i++ {
for l.key == mutex_unlocked {
- if cas(key32(&l.key), mutex_unlocked, wait) {
+ if atomic.Cas(key32(&l.key), mutex_unlocked, wait) {
return
}
}
}
// Sleep.
- v = xchg(key32(&l.key), mutex_sleeping)
+ v = atomic.Xchg(key32(&l.key), mutex_sleeping)
if v == mutex_unlocked {
return
}
}
func unlock(l *mutex) {
- v := xchg(key32(&l.key), mutex_unlocked)
+ v := atomic.Xchg(key32(&l.key), mutex_unlocked)
if v == mutex_unlocked {
throw("unlock of unlocked lock")
}
}
func notewakeup(n *note) {
- old := xchg(key32(&n.key), 1)
+ old := atomic.Xchg(key32(&n.key), 1)
if old != 0 {
print("notewakeup - double wakeup (", old, ")\n")
throw("notewakeup - double wakeup")
if gp != gp.m.g0 {
throw("notesleep not on g0")
}
- for atomicload(key32(&n.key)) == 0 {
+ for atomic.Load(key32(&n.key)) == 0 {
gp.m.blocked = true
futexsleep(key32(&n.key), 0, -1)
gp.m.blocked = false
gp := getg()
if ns < 0 {
- for atomicload(key32(&n.key)) == 0 {
+ for atomic.Load(key32(&n.key)) == 0 {
gp.m.blocked = true
futexsleep(key32(&n.key), 0, -1)
gp.m.blocked = false
return true
}
- if atomicload(key32(&n.key)) != 0 {
+ if atomic.Load(key32(&n.key)) != 0 {
return true
}
gp.m.blocked = true
futexsleep(key32(&n.key), 0, ns)
gp.m.blocked = false
- if atomicload(key32(&n.key)) != 0 {
+ if atomic.Load(key32(&n.key)) != 0 {
break
}
now := nanotime()
}
ns = deadline - now
}
- return atomicload(key32(&n.key)) != 0
+ return atomic.Load(key32(&n.key)) != 0
}
func notetsleep(n *note, ns int64) bool {
package runtime
-import "unsafe"
+import (
+ "runtime/internal/atomic"
+ "unsafe"
+)
// This implementation depends on OS-specific implementations of
//
-// uintptr runtime·semacreate(void)
-// Create a semaphore, which will be assigned to m->waitsema.
-// The zero value is treated as absence of any semaphore,
-// so be sure to return a non-zero value.
+// func semacreate(mp *m)
+// Create a semaphore for mp, if it does not already have one.
//
-// int32 runtime·semasleep(int64 ns)
-// If ns < 0, acquire m->waitsema and return 0.
-// If ns >= 0, try to acquire m->waitsema for at most ns nanoseconds.
+// func semasleep(ns int64) int32
+// If ns < 0, acquire m's semaphore and return 0.
+// If ns >= 0, try to acquire m's semaphore for at most ns nanoseconds.
// Return 0 if the semaphore was acquired, -1 if interrupted or timed out.
//
-// int32 runtime·semawakeup(M *mp)
-// Wake up mp, which is or will soon be sleeping on mp->waitsema.
+// func semawakeup(mp *m)
+// Wake up mp, which is or will soon be sleeping on its semaphore.
//
const (
locked uintptr = 1
gp.m.locks++
// Speculative grab for lock.
- if casuintptr(&l.key, 0, locked) {
+ if atomic.Casuintptr(&l.key, 0, locked) {
return
}
- if gp.m.waitsema == 0 {
- gp.m.waitsema = semacreate()
- }
+ semacreate(gp.m)
// On uniprocessor's, no point spinning.
// On multiprocessors, spin for ACTIVE_SPIN attempts.
}
Loop:
for i := 0; ; i++ {
- v := atomicloaduintptr(&l.key)
+ v := atomic.Loaduintptr(&l.key)
if v&locked == 0 {
// Unlocked. Try to lock.
- if casuintptr(&l.key, v, v|locked) {
+ if atomic.Casuintptr(&l.key, v, v|locked) {
return
}
i = 0
// Queue this M.
for {
gp.m.nextwaitm = v &^ locked
- if casuintptr(&l.key, v, uintptr(unsafe.Pointer(gp.m))|locked) {
+ if atomic.Casuintptr(&l.key, v, uintptr(unsafe.Pointer(gp.m))|locked) {
break
}
- v = atomicloaduintptr(&l.key)
+ v = atomic.Loaduintptr(&l.key)
if v&locked == 0 {
continue Loop
}
gp := getg()
var mp *m
for {
- v := atomicloaduintptr(&l.key)
+ v := atomic.Loaduintptr(&l.key)
if v == locked {
- if casuintptr(&l.key, locked, 0) {
+ if atomic.Casuintptr(&l.key, locked, 0) {
break
}
} else {
// Other M's are waiting for the lock.
// Dequeue an M.
mp = (*m)(unsafe.Pointer(v &^ locked))
- if casuintptr(&l.key, v, mp.nextwaitm) {
+ if atomic.Casuintptr(&l.key, v, mp.nextwaitm) {
// Dequeued an M. Wake it.
semawakeup(mp)
break
func notewakeup(n *note) {
var v uintptr
for {
- v = atomicloaduintptr(&n.key)
- if casuintptr(&n.key, v, locked) {
+ v = atomic.Loaduintptr(&n.key)
+ if atomic.Casuintptr(&n.key, v, locked) {
break
}
}
if gp != gp.m.g0 {
throw("notesleep not on g0")
}
- if gp.m.waitsema == 0 {
- gp.m.waitsema = semacreate()
- }
- if !casuintptr(&n.key, 0, uintptr(unsafe.Pointer(gp.m))) {
+ semacreate(gp.m)
+ if !atomic.Casuintptr(&n.key, 0, uintptr(unsafe.Pointer(gp.m))) {
// Must be locked (got wakeup).
if n.key != locked {
throw("notesleep - waitm out of sync")
gp = getg()
// Register for wakeup on n->waitm.
- if !casuintptr(&n.key, 0, uintptr(unsafe.Pointer(gp.m))) {
+ if !atomic.Casuintptr(&n.key, 0, uintptr(unsafe.Pointer(gp.m))) {
// Must be locked (got wakeup).
if n.key != locked {
throw("notetsleep - waitm out of sync")
// so that any notewakeup racing with the return does not
// try to grant us the semaphore when we don't expect it.
for {
- v := atomicloaduintptr(&n.key)
+ v := atomic.Loaduintptr(&n.key)
switch v {
case uintptr(unsafe.Pointer(gp.m)):
// No wakeup yet; unregister if possible.
- if casuintptr(&n.key, v, 0) {
+ if atomic.Casuintptr(&n.key, v, 0) {
return false
}
case locked:
if gp != gp.m.g0 && gp.m.preemptoff != "" {
throw("notetsleep not on g0")
}
- if gp.m.waitsema == 0 {
- gp.m.waitsema = semacreate()
- }
+ semacreate(gp.m)
return notetsleep_internal(n, ns, nil, 0)
}
if gp == gp.m.g0 {
throw("notetsleepg on g0")
}
- if gp.m.waitsema == 0 {
- gp.m.waitsema = semacreate()
- }
+ semacreate(gp.m)
entersyscallblock(0)
ok := notetsleep_internal(n, ns, nil, 0)
exitsyscall(0)
// or the page heap can avoid zeroing altogether.
// 2. the cost of zeroing when reusing a small object is
// charged to the mutator, not the garbage collector.
-//
-// This code was written with an eye toward translating to Go
-// in the future. Methods have the form Type_Method(Type *t, ...).
package runtime
-import "unsafe"
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
const (
debugMalloc = false
// windows/32 | 4KB | 3
// windows/64 | 8KB | 2
// plan9 | 4KB | 3
- _NumStackOrders = 4 - ptrSize/4*goos_windows - 1*goos_plan9
+ _NumStackOrders = 4 - sys.PtrSize/4*sys.GoosWindows - 1*sys.GoosPlan9
// Number of bits in page to span calculations (4k pages).
// On Windows 64-bit we limit the arena to 32GB or 35 bits.
// On Darwin/arm64, we cannot reserve more than ~5GB of virtual memory,
// but as most devices have less than 4GB of physical memory anyway, we
// try to be conservative here, and only ask for a 2GB heap.
- _MHeapMap_TotalBits = (_64bit*goos_windows)*35 + (_64bit*(1-goos_windows)*(1-goos_darwin*goarch_arm64))*39 + goos_darwin*goarch_arm64*31 + (1-_64bit)*32
+ _MHeapMap_TotalBits = (_64bit*sys.GoosWindows)*35 + (_64bit*(1-sys.GoosWindows)*(1-sys.GoosDarwin*sys.GoarchArm64))*39 + sys.GoosDarwin*sys.GoarchArm64*31 + (1-_64bit)*32
_MHeapMap_Bits = _MHeapMap_TotalBits - _PageShift
_MaxMem = uintptr(1<<_MHeapMap_TotalBits - 1)
// Set up the allocation arena, a contiguous area of memory where
// allocated data will be found. The arena begins with a bitmap large
// enough to hold 4 bits per allocated word.
- if ptrSize == 8 && (limit == 0 || limit > 1<<30) {
+ if sys.PtrSize == 8 && (limit == 0 || limit > 1<<30) {
// On a 64-bit machine, allocate from a single contiguous reservation.
// 512 GB (MaxMem) should be big enough for now.
//
// translation buffers, the user address space is limited to 39 bits
// On darwin/arm64, the address space is even smaller.
arenaSize := round(_MaxMem, _PageSize)
- bitmapSize = arenaSize / (ptrSize * 8 / 4)
- spansSize = arenaSize / _PageSize * ptrSize
+ bitmapSize = arenaSize / (sys.PtrSize * 8 / 4)
+ spansSize = arenaSize / _PageSize * sys.PtrSize
spansSize = round(spansSize, _PageSize)
for i := 0; i <= 0x7f; i++ {
switch {
}
for _, arenaSize := range arenaSizes {
- bitmapSize = _MaxArena32 / (ptrSize * 8 / 4)
- spansSize = _MaxArena32 / _PageSize * ptrSize
+ bitmapSize = _MaxArena32 / (sys.PtrSize * 8 / 4)
+ spansSize = _MaxArena32 / _PageSize * sys.PtrSize
if limit > 0 && arenaSize+bitmapSize+spansSize > limit {
bitmapSize = (limit / 9) &^ ((1 << _PageShift) - 1)
arenaSize = bitmapSize * 8
- spansSize = arenaSize / _PageSize * ptrSize
+ spansSize = arenaSize / _PageSize * sys.PtrSize
}
spansSize = round(spansSize, _PageSize)
}
// Initialize the rest of the allocator.
- mHeap_Init(&mheap_, spansSize)
+ mheap_.init(spansSize)
_g_ := getg()
_g_.m.mcache = allocmcache()
}
// needed. This doesn't work well with the "let the kernel pick an address"
// mode, so don't do that. Pick a high address instead.
func sysReserveHigh(n uintptr, reserved *bool) unsafe.Pointer {
- if ptrSize == 4 {
+ if sys.PtrSize == 4 {
return sysReserve(nil, n, reserved)
}
return sysReserve(nil, n, reserved)
}
-func mHeap_SysAlloc(h *mheap, n uintptr) unsafe.Pointer {
- if n > uintptr(h.arena_end)-uintptr(h.arena_used) {
+func (h *mheap) sysAlloc(n uintptr) unsafe.Pointer {
+ if n > h.arena_end-h.arena_used {
// We are in 32-bit mode, maybe we didn't use all possible address space yet.
// Reserve some more space.
p_size := round(n+_PageSize, 256<<20)
if p == h.arena_end {
h.arena_end = new_end
h.arena_reserved = reserved
- } else if p+p_size <= h.arena_start+_MaxArena32 {
+ } else if h.arena_start <= p && p+p_size <= h.arena_start+_MaxArena32 {
// Keep everything page-aligned.
// Our pages are bigger than hardware pages.
h.arena_end = p + p_size
used := p + (-uintptr(p) & (_PageSize - 1))
- mHeap_MapBits(h, used)
- mHeap_MapSpans(h, used)
+ h.mapBits(used)
+ h.mapSpans(used)
h.arena_used = used
h.arena_reserved = reserved
} else {
- var stat uint64
+ // We haven't added this allocation to
+ // the stats, so subtract it from a
+ // fake stat (but avoid underflow).
+ stat := uint64(p_size)
sysFree(unsafe.Pointer(p), p_size, &stat)
}
}
}
- if n <= uintptr(h.arena_end)-uintptr(h.arena_used) {
+ if n <= h.arena_end-h.arena_used {
// Keep taking from our reservation.
p := h.arena_used
sysMap(unsafe.Pointer(p), n, h.arena_reserved, &memstats.heap_sys)
- mHeap_MapBits(h, p+n)
- mHeap_MapSpans(h, p+n)
+ h.mapBits(p + n)
+ h.mapSpans(p + n)
h.arena_used = p + n
if raceenabled {
racemapshadow(unsafe.Pointer(p), n)
}
// If using 64-bit, our reservation is all we have.
- if uintptr(h.arena_end)-uintptr(h.arena_start) >= _MaxArena32 {
+ if h.arena_end-h.arena_start >= _MaxArena32 {
return nil
}
return nil
}
- if p < h.arena_start || uintptr(p)+p_size-uintptr(h.arena_start) >= _MaxArena32 {
+ if p < h.arena_start || uintptr(p)+p_size-h.arena_start >= _MaxArena32 {
print("runtime: memory allocated by OS (", p, ") not in usable range [", hex(h.arena_start), ",", hex(h.arena_start+_MaxArena32), ")\n")
sysFree(unsafe.Pointer(p), p_size, &memstats.heap_sys)
return nil
p_end := p + p_size
p += -p & (_PageSize - 1)
- if uintptr(p)+n > uintptr(h.arena_used) {
- mHeap_MapBits(h, p+n)
- mHeap_MapSpans(h, p+n)
+ if uintptr(p)+n > h.arena_used {
+ h.mapBits(p + n)
+ h.mapSpans(p + n)
h.arena_used = p + n
if p_end > h.arena_end {
h.arena_end = p_end
v := s.freelist
if v.ptr() == nil {
systemstack(func() {
- mCache_Refill(c, tinySizeClass)
+ c.refill(tinySizeClass)
})
shouldhelpgc = true
s = c.alloc[tinySizeClass]
(*[2]uint64)(x)[1] = 0
// See if we need to replace the existing tiny block with the new one
// based on amount of remaining free space.
- if size < c.tinyoffset {
- c.tiny = x
+ if size < c.tinyoffset || c.tiny == nil {
+ // TODO(khr): replace this with "c.tiny = x" when c.tiny use is fixed.
+ writebarrierptr((*uintptr)(unsafe.Pointer(&c.tiny)), uintptr(x))
c.tinyoffset = size
}
size = maxTinySize
v := s.freelist
if v.ptr() == nil {
systemstack(func() {
- mCache_Refill(c, int32(sizeclass))
+ c.refill(int32(sizeclass))
})
shouldhelpgc = true
s = c.alloc[sizeclass]
x = unsafe.Pointer(v)
if flags&flagNoZero == 0 {
v.ptr().next = 0
- if size > 2*ptrSize && ((*[2]uintptr)(x))[1] != 0 {
+ if size > 2*sys.PtrSize && ((*[2]uintptr)(x))[1] != 0 {
memclr(unsafe.Pointer(v), size)
}
}
if raceenabled {
racemalloc(x, size)
}
+ if msanenabled {
+ msanmalloc(x, size)
+ }
mp.mallocing = 0
releasem(mp)
assistG.gcAssistBytes -= int64(size - dataSize)
}
- if shouldhelpgc && shouldtriggergc() {
- startGC(gcBackgroundMode, false)
- } else if shouldhelpgc && bggc.working != 0 && gcBlackenEnabled == 0 {
- // The GC is starting up or shutting down, so we can't
- // assist, but we also can't allocate unabated. Slow
- // down this G's allocation and help the GC stay
- // scheduled by yielding.
- //
- // TODO: This is a workaround. Either help the GC make
- // the transition or block.
- gp := getg()
- if gp != gp.m.g0 && gp.m.locks == 0 && gp.m.preemptoff == "" {
- Gosched()
- }
+ if shouldhelpgc && gcShouldStart(false) {
+ gcStart(gcBackgroundMode, false)
}
return x
// pays the debt down to npage pages.
deductSweepCredit(npages*_PageSize, npages)
- s := mHeap_Alloc(&mheap_, npages, 0, true, flag&_FlagNoZero == 0)
+ s := mheap_.alloc(npages, 0, true, flag&_FlagNoZero == 0)
if s == nil {
throw("out of memory")
}
// distributed random number and applying the cumulative distribution
// function for an exponential.
func nextSample() int32 {
+ if GOOS == "plan9" {
+ // Plan 9 doesn't support floating point in note handler.
+ if g := getg(); g == g.m.gsignal {
+ return nextSampleNoFP()
+ }
+ }
+
period := MemProfileRate
// make nextSample not overflow. Maximum possible step is
return int32(qlog*(minusLog2*float64(period))) + 1
}
+// nextSampleNoFP is similar to nextSample, but uses older,
+// simpler code to avoid floating point.
+func nextSampleNoFP() int32 {
+ // Set first allocation sample size.
+ rate := MemProfileRate
+ if rate > 0x3fffffff { // make 2*rate not overflow
+ rate = 0x3fffffff
+ }
+ if rate != 0 {
+ return int32(int(fastrand1()) % (2 * rate))
+ }
+ return 0
+}
+
type persistentAlloc struct {
base unsafe.Pointer
off uintptr
}
}
+func TestTinyAlloc(t *testing.T) {
+ const N = 16
+ var v [N]unsafe.Pointer
+ for i := range v {
+ v[i] = unsafe.Pointer(new(byte))
+ }
+
+ chunks := make(map[uintptr]bool, N)
+ for _, p := range v {
+ chunks[uintptr(p)&^7] = true
+ }
+
+ if len(chunks) == N {
+ t.Fatal("no bytes allocated within the same 8-byte chunk")
+ }
+}
+
var mallocSink uintptr
func BenchmarkMalloc8(b *testing.B) {
package runtime
-import "unsafe"
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
// markwb is the mark-phase write barrier, the only barrier we have.
// The rest of this file exists only to make calls to this function.
// Dealing with memory ordering:
//
// Dijkstra pointed out that maintaining the no black to white
-// pointers means that white to white pointers not need
+// pointers means that white to white pointers do not need
// to be noted by the write barrier. Furthermore if either
// white object dies before it is reached by the
// GC then the object can be collected during this GC cycle
// instead of waiting for the next cycle. Unfortunately the cost of
-// ensure that the object holding the slot doesn't concurrently
+// ensuring that the object holding the slot doesn't concurrently
// change to black without the mutator noticing seems prohibitive.
//
// Consider the following example where the mutator writes into
// frames that have potentially been active since the concurrent scan,
// so it depends on write barriers to track changes to pointers in
// stack frames that have not been active.
-//go:nowritebarrier
+//go:nowritebarrierrec
func gcmarkwb_m(slot *uintptr, ptr uintptr) {
- if writeBarrierEnabled {
+ if writeBarrier.needed {
if ptr != 0 && inheap(ptr) {
shade(ptr)
}
//go:nosplit
func writebarrierptr(dst *uintptr, src uintptr) {
*dst = src
- if !writeBarrierEnabled {
+ if writeBarrier.cgo {
+ cgoCheckWriteBarrier(dst, src)
+ }
+ if !writeBarrier.needed {
return
}
- if src != 0 && (src < _PhysPageSize || src == poisonStack) {
+ if src != 0 && (src < sys.PhysPageSize || src == poisonStack) {
systemstack(func() {
print("runtime: writebarrierptr *", dst, " = ", hex(src), "\n")
throw("bad pointer in write barrier")
// Do not reapply.
//go:nosplit
func writebarrierptr_nostore(dst *uintptr, src uintptr) {
- if !writeBarrierEnabled {
+ if writeBarrier.cgo {
+ cgoCheckWriteBarrier(dst, src)
+ }
+ if !writeBarrier.needed {
return
}
- if src != 0 && (src < _PhysPageSize || src == poisonStack) {
+ if src != 0 && (src < sys.PhysPageSize || src == poisonStack) {
systemstack(func() { throw("bad pointer in write barrier") })
}
writebarrierptr_nostore1(dst, src)
//go:nosplit
func typedmemmove(typ *_type, dst, src unsafe.Pointer) {
memmove(dst, src, typ.size)
+ if writeBarrier.cgo {
+ cgoCheckMemmove(typ, dst, src, 0, typ.size)
+ }
if typ.kind&kindNoPointers != 0 {
return
}
//go:linkname reflect_typedmemmovepartial reflect.typedmemmovepartial
func reflect_typedmemmovepartial(typ *_type, dst, src unsafe.Pointer, off, size uintptr) {
memmove(dst, src, size)
- if !writeBarrierEnabled || typ.kind&kindNoPointers != 0 || size < ptrSize || !inheap(uintptr(dst)) {
+ if writeBarrier.cgo {
+ cgoCheckMemmove(typ, dst, src, off, size)
+ }
+ if !writeBarrier.needed || typ.kind&kindNoPointers != 0 || size < sys.PtrSize || !inheap(uintptr(dst)) {
return
}
- if frag := -off & (ptrSize - 1); frag != 0 {
+ if frag := -off & (sys.PtrSize - 1); frag != 0 {
dst = add(dst, frag)
size -= frag
}
- heapBitsBulkBarrier(uintptr(dst), size&^(ptrSize-1))
+ heapBitsBulkBarrier(uintptr(dst), size&^(sys.PtrSize-1))
}
// callwritebarrier is invoked at the end of reflectcall, to execute
// not to be preempted before the write barriers have been run.
//go:nosplit
func callwritebarrier(typ *_type, frame unsafe.Pointer, framesize, retoffset uintptr) {
- if !writeBarrierEnabled || typ == nil || typ.kind&kindNoPointers != 0 || framesize-retoffset < ptrSize || !inheap(uintptr(frame)) {
+ if !writeBarrier.needed || typ == nil || typ.kind&kindNoPointers != 0 || framesize-retoffset < sys.PtrSize || !inheap(uintptr(frame)) {
return
}
heapBitsBulkBarrier(uintptr(add(frame, retoffset)), framesize-retoffset)
racewriterangepc(dstp, uintptr(n)*typ.size, callerpc, pc)
racereadrangepc(srcp, uintptr(n)*typ.size, callerpc, pc)
}
+ if msanenabled {
+ msanwrite(dstp, uintptr(n)*typ.size)
+ msanread(srcp, uintptr(n)*typ.size)
+ }
+
+ if writeBarrier.cgo {
+ cgoCheckSliceCopy(typ, dst, src, n)
+ }
// Note: No point in checking typ.kind&kindNoPointers here:
// compiler only emits calls to typedslicecopy for types with pointers,
// and growslice and reflect_typedslicecopy check for pointers
// before calling typedslicecopy.
- if !writeBarrierEnabled {
+ if !writeBarrier.needed {
memmove(dstp, srcp, uintptr(n)*typ.size)
return n
}
package runtime
-import "unsafe"
+import (
+ "runtime/internal/atomic"
+ "runtime/internal/sys"
+ "unsafe"
+)
const (
bitPointer = 1 << 0
bitMarked = 1 << 4
- heapBitsShift = 1 // shift offset between successive bitPointer or bitMarked entries
- heapBitmapScale = ptrSize * (8 / 2) // number of data bytes described by one heap bitmap byte
+ heapBitsShift = 1 // shift offset between successive bitPointer or bitMarked entries
+ heapBitmapScale = sys.PtrSize * (8 / 2) // number of data bytes described by one heap bitmap byte
// all mark/pointer bits in a byte
bitMarkedAll = bitMarked | bitMarked<<heapBitsShift | bitMarked<<(2*heapBitsShift) | bitMarked<<(3*heapBitsShift)
// after observing the change to arena_used.
//
//go:nowritebarrier
-func mHeap_MapBits(h *mheap, arena_used uintptr) {
+func (h *mheap) mapBits(arena_used uintptr) {
// Caller has added extra mappings to the arena.
// Add extra mappings of bitmap words as needed.
// We allocate extra bitmap pieces in chunks of bitmapChunk.
n := (arena_used - mheap_.arena_start) / heapBitmapScale
n = round(n, bitmapChunk)
- n = round(n, _PhysPageSize)
+ n = round(n, sys.PhysPageSize)
if h.bitmap_mapped >= n {
return
}
//go:nosplit
func heapBitsForAddr(addr uintptr) heapBits {
// 2 bits per work, 4 pairs per byte, and a mask is hard coded.
- off := (addr - mheap_.arena_start) / ptrSize
+ off := (addr - mheap_.arena_start) / sys.PtrSize
return heapBits{(*uint8)(unsafe.Pointer(mheap_.arena_start - off/4 - 1)), uint32(off & 3)}
}
// Might be racing with other updates, so use atomic update always.
// We used to be clever here and use a non-atomic update in certain
// cases, but it's not worth the risk.
- atomicor8(h.bitp, bitMarked<<h.shift)
+ atomic.Or8(h.bitp, bitMarked<<h.shift)
}
// setMarkedNonAtomic sets the marked bit in the heap bits, non-atomically.
// far into the bitmap.
// h must describe the initial word of the object.
func (h heapBits) hasPointers(size uintptr) bool {
- if size == ptrSize { // 1-word objects are always pointers
+ if size == sys.PtrSize { // 1-word objects are always pointers
return true
}
// Otherwise, at least a 2-word object, and at least 2-word aligned,
if b&(bitPointer|bitPointer<<heapBitsShift) != 0 {
return true
}
- if size == 2*ptrSize {
+ if size == 2*sys.PtrSize {
return false
}
// At least a 4-word object. Check scan bit (aka marked bit) in third word.
// checkmark bit varies by size.
// h must describe the initial word of the object.
func (h heapBits) isCheckmarked(size uintptr) bool {
- if size == ptrSize {
+ if size == sys.PtrSize {
return (*h.bitp>>h.shift)&bitPointer != 0
}
// All multiword objects are 2-word aligned,
// checkmark bit varies by size.
// h must describe the initial word of the object.
func (h heapBits) setCheckmarked(size uintptr) {
- if size == ptrSize {
- atomicor8(h.bitp, bitPointer<<h.shift)
+ if size == sys.PtrSize {
+ atomic.Or8(h.bitp, bitPointer<<h.shift)
return
}
- atomicor8(h.bitp, bitMarked<<(heapBitsShift+h.shift))
+ atomic.Or8(h.bitp, bitMarked<<(heapBitsShift+h.shift))
}
// heapBitsBulkBarrier executes writebarrierptr_nostore
//
//go:nosplit
func heapBitsBulkBarrier(p, size uintptr) {
- if (p|size)&(ptrSize-1) != 0 {
+ if (p|size)&(sys.PtrSize-1) != 0 {
throw("heapBitsBulkBarrier: unaligned arguments")
}
- if !writeBarrierEnabled {
+ if !writeBarrier.needed {
return
}
if !inheap(p) {
}
h := heapBitsForAddr(p)
- for i := uintptr(0); i < size; i += ptrSize {
+ for i := uintptr(0); i < size; i += sys.PtrSize {
if h.isPointer() {
x := (*uintptr)(unsafe.Pointer(p + i))
writebarrierptr_nostore(x, *x)
println("runtime: typeBitsBulkBarrier with type ", *typ._string, " with GC prog")
throw("runtime: invalid typeBitsBulkBarrier")
}
- if !writeBarrierEnabled {
+ if !writeBarrier.needed {
return
}
ptrmask := typ.gcdata
var bits uint32
- for i := uintptr(0); i < typ.ptrdata; i += ptrSize {
- if i&(ptrSize*8-1) == 0 {
+ for i := uintptr(0); i < typ.ptrdata; i += sys.PtrSize {
+ if i&(sys.PtrSize*8-1) == 0 {
bits = uint32(*ptrmask)
ptrmask = addb(ptrmask, 1)
} else {
throw("initSpan: unaligned length")
}
nbyte := total / heapBitmapScale
- if ptrSize == 8 && size == ptrSize {
+ if sys.PtrSize == 8 && size == sys.PtrSize {
end := h.bitp
bitp := subtractb(end, nbyte-1)
for {
// It clears the checkmark bits, which are set to 1 in normal operation.
func (h heapBits) initCheckmarkSpan(size, n, total uintptr) {
// The ptrSize == 8 is a compile-time constant false on 32-bit and eliminates this code entirely.
- if ptrSize == 8 && size == ptrSize {
+ if sys.PtrSize == 8 && size == sys.PtrSize {
// Checkmark bit is type bit, bottom bit of every 2-bit entry.
// Only possible on 64-bit system, since minimum size is 8.
// Must clear type bit (checkmark bit) of every word.
}
for i := uintptr(0); i < n; i++ {
*h.bitp &^= bitMarked << (heapBitsShift + h.shift)
- h = h.forward(size / ptrSize)
+ h = h.forward(size / sys.PtrSize)
}
}
// but consulted by typedmemmove.)
func (h heapBits) clearCheckmarkSpan(size, n, total uintptr) {
// The ptrSize == 8 is a compile-time constant false on 32-bit and eliminates this code entirely.
- if ptrSize == 8 && size == ptrSize {
+ if sys.PtrSize == 8 && size == sys.PtrSize {
// Checkmark bit is type bit, bottom bit of every 2-bit entry.
// Only possible on 64-bit system, since minimum size is 8.
// Must clear type bit (checkmark bit) of every word.
switch {
default:
throw("heapBitsSweepSpan")
- case ptrSize == 8 && size == ptrSize:
+ case sys.PtrSize == 8 && size == sys.PtrSize:
// Consider mark bits in all four 2-bit entries of each bitmap byte.
bitp := h.bitp
for i := uintptr(0); i < n; i += 4 {
if x&bitMarked != 0 {
x &^= bitMarked
} else {
- f(base + i*ptrSize)
+ f(base + i*sys.PtrSize)
}
if x&(bitMarked<<heapBitsShift) != 0 {
x &^= bitMarked << heapBitsShift
} else {
- f(base + (i+1)*ptrSize)
+ f(base + (i+1)*sys.PtrSize)
}
if x&(bitMarked<<(2*heapBitsShift)) != 0 {
x &^= bitMarked << (2 * heapBitsShift)
} else {
- f(base + (i+2)*ptrSize)
+ f(base + (i+2)*sys.PtrSize)
}
if x&(bitMarked<<(3*heapBitsShift)) != 0 {
x &^= bitMarked << (3 * heapBitsShift)
} else {
- f(base + (i+3)*ptrSize)
+ f(base + (i+3)*sys.PtrSize)
}
*bitp = uint8(x)
bitp = subtract1(bitp)
}
- case size%(4*ptrSize) == 0:
+ case size%(4*sys.PtrSize) == 0:
// Mark bit is in first word of each object.
// Each object starts at bit 0 of a heap bitmap byte.
bitp := h.bitp
bitp = subtractb(bitp, step)
}
- case size%(4*ptrSize) == 2*ptrSize:
+ case size%(4*sys.PtrSize) == 2*sys.PtrSize:
// Mark bit is in first word of each object,
// but every other object starts halfway through a heap bitmap byte.
// Unroll loop 2x to handle alternating shift count and step size.
} else {
x &^= bitMarked | bitPointer | (bitMarked|bitPointer)<<heapBitsShift
f(base + i*size)
- if size > 2*ptrSize {
+ if size > 2*sys.PtrSize {
x = 0
}
}
} else {
x &^= (bitMarked|bitPointer)<<(2*heapBitsShift) | (bitMarked|bitPointer)<<(3*heapBitsShift)
f(base + (i+1)*size)
- if size > 2*ptrSize {
+ if size > 2*sys.PtrSize {
*subtract1(bitp) = 0
}
}
// The checks for size == ptrSize and size == 2*ptrSize can therefore
// assume that dataSize == size without checking it explicitly.
- if ptrSize == 8 && size == ptrSize {
+ if sys.PtrSize == 8 && size == sys.PtrSize {
// It's one word and it has pointers, it must be a pointer.
// In general we'd need an atomic update here if the
// concurrent GC were marking objects in this span,
// This is called out as a special case primarily for 32-bit systems,
// so that on 32-bit systems the code below can assume all objects
// are 4-word aligned (because they're all 16-byte aligned).
- if size == 2*ptrSize {
- if typ.size == ptrSize {
+ if size == 2*sys.PtrSize {
+ if typ.size == sys.PtrSize {
// We're allocating a block big enough to hold two pointers.
// On 64-bit, that means the actual object must be two pointers,
// or else we'd have used the one-pointer-sized block.
// just the smallest block available. Distinguish by checking dataSize.
// (In general the number of instances of typ being allocated is
// dataSize/typ.size.)
- if ptrSize == 4 && dataSize == ptrSize {
+ if sys.PtrSize == 4 && dataSize == sys.PtrSize {
// 1 pointer.
if gcphase == _GCoff {
*h.bitp |= bitPointer << h.shift
} else {
- atomicor8(h.bitp, bitPointer<<h.shift)
+ atomic.Or8(h.bitp, bitPointer<<h.shift)
}
} else {
// 2-element slice of pointer.
if gcphase == _GCoff {
*h.bitp |= (bitPointer | bitPointer<<heapBitsShift) << h.shift
} else {
- atomicor8(h.bitp, (bitPointer|bitPointer<<heapBitsShift)<<h.shift)
+ atomic.Or8(h.bitp, (bitPointer|bitPointer<<heapBitsShift)<<h.shift)
}
}
return
}
// Otherwise typ.size must be 2*ptrSize, and typ.kind&kindGCProg == 0.
if doubleCheck {
- if typ.size != 2*ptrSize || typ.kind&kindGCProg != 0 {
+ if typ.size != 2*sys.PtrSize || typ.kind&kindGCProg != 0 {
print("runtime: heapBitsSetType size=", size, " but typ.size=", typ.size, " gcprog=", typ.kind&kindGCProg != 0, "\n")
throw("heapBitsSetType")
}
if gcphase == _GCoff {
*h.bitp |= uint8(hb << h.shift)
} else {
- atomicor8(h.bitp, uint8(hb<<h.shift))
+ atomic.Or8(h.bitp, uint8(hb<<h.shift))
}
return
}
// Filling in bits for an array of typ.
// Set up for repetition of ptrmask during main loop.
// Note that ptrmask describes only a prefix of
- const maxBits = ptrSize*8 - 7
- if typ.ptrdata/ptrSize <= maxBits {
+ const maxBits = sys.PtrSize*8 - 7
+ if typ.ptrdata/sys.PtrSize <= maxBits {
// Entire ptrmask fits in uintptr with room for a byte fragment.
// Load into pbits and never read from ptrmask again.
// This is especially important when the ptrmask has
// Accumulate ptrmask into b.
// ptrmask is sized to describe only typ.ptrdata, but we record
// it as describing typ.size bytes, since all the high bits are zero.
- nb = typ.ptrdata / ptrSize
+ nb = typ.ptrdata / sys.PtrSize
for i := uintptr(0); i < nb; i += 8 {
b |= uintptr(*p) << i
p = add1(p)
}
- nb = typ.size / ptrSize
+ nb = typ.size / sys.PtrSize
// Replicate ptrmask to fill entire pbits uintptr.
// Doubling and truncating is fewer steps than
pbits = b
endnb = nb
if nb+nb <= maxBits {
- for endnb <= ptrSize*8 {
+ for endnb <= sys.PtrSize*8 {
pbits |= pbits << endnb
endnb += endnb
}
endp = nil
} else {
// Ptrmask is larger. Read it multiple times.
- n := (typ.ptrdata/ptrSize+7)/8 - 1
+ n := (typ.ptrdata/sys.PtrSize+7)/8 - 1
endp = addb(ptrmask, n)
- endnb = typ.size/ptrSize - n*8
+ endnb = typ.size/sys.PtrSize - n*8
}
}
if p != nil {
if typ.size == dataSize {
// Single entry: can stop once we reach the non-pointer data.
- nw = typ.ptrdata / ptrSize
+ nw = typ.ptrdata / sys.PtrSize
} else {
// Repeated instances of typ in an array.
// Have to process first N-1 entries in full, but can stop
// once we reach the non-pointer data in the final entry.
- nw = ((dataSize/typ.size-1)*typ.size + typ.ptrdata) / ptrSize
+ nw = ((dataSize/typ.size-1)*typ.size + typ.ptrdata) / sys.PtrSize
}
if nw == 0 {
// No pointers! Caller was supposed to check.
b >>= 4
nb -= 4
- case ptrSize == 8 && h.shift == 2:
+ case sys.PtrSize == 8 && h.shift == 2:
// Ptrmask and heap bitmap are misaligned.
// The bits for the first two words are in a byte shared with another object
// and must be updated atomically.
if gcphase == _GCoff {
*hbitp |= uint8(hb)
} else {
- atomicor8(hbitp, uint8(hb))
+ atomic.Or8(hbitp, uint8(hb))
}
hbitp = subtract1(hbitp)
if w += 2; w >= nw {
}
// Change nw from counting possibly-pointer words to total words in allocation.
- nw = size / ptrSize
+ nw = size / sys.PtrSize
// Write whole bitmap bytes.
// The first is hb, the rest are zero.
if gcphase == _GCoff {
*hbitp = *hbitp&^(bitPointer|bitMarked|(bitPointer|bitMarked)<<heapBitsShift) | uint8(hb)
} else {
- atomicand8(hbitp, ^uint8(bitPointer|bitMarked|(bitPointer|bitMarked)<<heapBitsShift))
- atomicor8(hbitp, uint8(hb))
+ atomic.And8(hbitp, ^uint8(bitPointer|bitMarked|(bitPointer|bitMarked)<<heapBitsShift))
+ atomic.Or8(hbitp, uint8(hb))
}
}
// Double-check that bits to be written were written correctly.
// Does not check that other bits were not written, unfortunately.
h := heapBitsForAddr(x)
- nptr := typ.ptrdata / ptrSize
- ndata := typ.size / ptrSize
+ nptr := typ.ptrdata / sys.PtrSize
+ ndata := typ.size / sys.PtrSize
count := dataSize / typ.size
- totalptr := ((count-1)*typ.size + typ.ptrdata) / ptrSize
- for i := uintptr(0); i < size/ptrSize; i++ {
+ totalptr := ((count-1)*typ.size + typ.ptrdata) / sys.PtrSize
+ for i := uintptr(0); i < size/sys.PtrSize; i++ {
j := i % ndata
var have, want uint8
have = (*h.bitp >> h.shift) & (bitPointer | bitMarked)
print("initial bits h0.bitp=", h0.bitp, " h0.shift=", h0.shift, "\n")
print("current bits h.bitp=", h.bitp, " h.shift=", h.shift, " *h.bitp=", hex(*h.bitp), "\n")
print("ptrmask=", ptrmask, " p=", p, " endp=", endp, " endnb=", endnb, " pbits=", hex(pbits), " b=", hex(b), " nb=", nb, "\n")
- println("at word", i, "offset", i*ptrSize, "have", have, "want", want)
+ println("at word", i, "offset", i*sys.PtrSize, "have", have, "want", want)
if typ.kind&kindGCProg != 0 {
println("GC program:")
dumpGCProg(addb(typ.gcdata, 4))
// so that the relevant bitmap bytes are not shared with surrounding
// objects and need not be accessed with atomic instructions.
func heapBitsSetTypeGCProg(h heapBits, progSize, elemSize, dataSize, allocSize uintptr, prog *byte) {
- if ptrSize == 8 && allocSize%(4*ptrSize) != 0 {
+ if sys.PtrSize == 8 && allocSize%(4*sys.PtrSize) != 0 {
// Alignment will be wrong.
throw("heapBitsSetTypeGCProg: small allocation")
}
var totalBits uintptr
if elemSize == dataSize {
totalBits = runGCProg(prog, nil, h.bitp, 2)
- if totalBits*ptrSize != progSize {
+ if totalBits*sys.PtrSize != progSize {
println("runtime: heapBitsSetTypeGCProg: total bits", totalBits, "but progSize", progSize)
throw("heapBitsSetTypeGCProg: unexpected bit count")
}
// repeats that first element to fill the array.
var trailer [40]byte // 3 varints (max 10 each) + some bytes
i := 0
- if n := elemSize/ptrSize - progSize/ptrSize; n > 0 {
+ if n := elemSize/sys.PtrSize - progSize/sys.PtrSize; n > 0 {
// literal(0)
trailer[i] = 0x01
i++
// repeat(elemSize/ptrSize, count-1)
trailer[i] = 0x80
i++
- n := elemSize / ptrSize
+ n := elemSize / sys.PtrSize
for ; n >= 0x80; n >>= 7 {
trailer[i] = byte(n | 0x80)
i++
// last element. This will cause the code below to
// memclr the dead section of the final array element,
// so that scanobject can stop early in the final element.
- totalBits = (elemSize*(count-1) + progSize) / ptrSize
+ totalBits = (elemSize*(count-1) + progSize) / sys.PtrSize
}
endProg := unsafe.Pointer(subtractb(h.bitp, (totalBits+3)/4))
endAlloc := unsafe.Pointer(subtractb(h.bitp, allocSize/heapBitmapScale))
// size the size of the region described by prog, in bytes.
// The resulting bitvector will have no more than size/ptrSize bits.
func progToPointerMask(prog *byte, size uintptr) bitvector {
- n := (size/ptrSize + 7) / 8
+ n := (size/sys.PtrSize + 7) / 8
x := (*[1 << 30]byte)(persistentalloc(n+1, 1, &memstats.buckhash_sys))[:n+1]
x[len(x)-1] = 0xa1 // overflow check sentinel
n = runGCProg(prog, nil, &x[0], 1)
// the pattern to a bit buffer holding at most 7 bits (a partial byte)
// it will not overflow.
src := dst
- const maxBits = ptrSize*8 - 7
+ const maxBits = sys.PtrSize*8 - 7
if n <= maxBits {
// Start with bits in output buffer.
pattern := bits
nb := npattern
if nb+nb <= maxBits {
// Double pattern until the whole uintptr is filled.
- for nb <= ptrSize*8 {
+ for nb <= sys.PtrSize*8 {
b |= b << nb
nb += nb
}
//go:linkname reflect_gcbits reflect.gcbits
func reflect_gcbits(x interface{}) []byte {
ret := getgcmask(x)
- typ := (*ptrtype)(unsafe.Pointer((*eface)(unsafe.Pointer(&x))._type)).elem
- nptr := typ.ptrdata / ptrSize
+ typ := (*ptrtype)(unsafe.Pointer(efaceOf(&x)._type)).elem
+ nptr := typ.ptrdata / sys.PtrSize
for uintptr(len(ret)) > nptr && ret[len(ret)-1] == 0 {
ret = ret[:len(ret)-1]
}
// Returns GC type info for object p for testing.
func getgcmask(ep interface{}) (mask []byte) {
- e := *(*eface)(unsafe.Pointer(&ep))
+ e := *efaceOf(&ep)
p := e.data
t := e._type
// data or bss
if datap.data <= uintptr(p) && uintptr(p) < datap.edata {
bitmap := datap.gcdatamask.bytedata
n := (*ptrtype)(unsafe.Pointer(t)).elem.size
- mask = make([]byte, n/ptrSize)
- for i := uintptr(0); i < n; i += ptrSize {
- off := (uintptr(p) + i - datap.data) / ptrSize
- mask[i/ptrSize] = (*addb(bitmap, off/8) >> (off % 8)) & 1
+ mask = make([]byte, n/sys.PtrSize)
+ for i := uintptr(0); i < n; i += sys.PtrSize {
+ off := (uintptr(p) + i - datap.data) / sys.PtrSize
+ mask[i/sys.PtrSize] = (*addb(bitmap, off/8) >> (off % 8)) & 1
}
return
}
if datap.bss <= uintptr(p) && uintptr(p) < datap.ebss {
bitmap := datap.gcbssmask.bytedata
n := (*ptrtype)(unsafe.Pointer(t)).elem.size
- mask = make([]byte, n/ptrSize)
- for i := uintptr(0); i < n; i += ptrSize {
- off := (uintptr(p) + i - datap.bss) / ptrSize
- mask[i/ptrSize] = (*addb(bitmap, off/8) >> (off % 8)) & 1
+ mask = make([]byte, n/sys.PtrSize)
+ for i := uintptr(0); i < n; i += sys.PtrSize {
+ off := (uintptr(p) + i - datap.bss) / sys.PtrSize
+ mask[i/sys.PtrSize] = (*addb(bitmap, off/8) >> (off % 8)) & 1
}
return
}
var n uintptr
var base uintptr
if mlookup(uintptr(p), &base, &n, nil) != 0 {
- mask = make([]byte, n/ptrSize)
- for i := uintptr(0); i < n; i += ptrSize {
+ mask = make([]byte, n/sys.PtrSize)
+ for i := uintptr(0); i < n; i += sys.PtrSize {
hbits := heapBitsForAddr(base + i)
if hbits.isPointer() {
- mask[i/ptrSize] = 1
+ mask[i/sys.PtrSize] = 1
}
- if i >= 2*ptrSize && !hbits.isMarked() {
- mask = mask[:i/ptrSize]
+ if i >= 2*sys.PtrSize && !hbits.isMarked() {
+ mask = mask[:i/sys.PtrSize]
break
}
}
if targetpc != f.entry {
targetpc--
}
- pcdata := pcdatavalue(f, _PCDATA_StackMapIndex, targetpc)
+ pcdata := pcdatavalue(f, _PCDATA_StackMapIndex, targetpc, nil)
if pcdata == -1 {
return
}
return
}
bv := stackmapdata(stkmap, pcdata)
- size := uintptr(bv.n) * ptrSize
+ size := uintptr(bv.n) * sys.PtrSize
n := (*ptrtype)(unsafe.Pointer(t)).elem.size
- mask = make([]byte, n/ptrSize)
- for i := uintptr(0); i < n; i += ptrSize {
+ mask = make([]byte, n/sys.PtrSize)
+ for i := uintptr(0); i < n; i += sys.PtrSize {
bitmap := bv.bytedata
- off := (uintptr(p) + i - frame.varp + size) / ptrSize
- mask[i/ptrSize] = (*addb(bitmap, off/8) >> (off % 8)) & 1
+ off := (uintptr(p) + i - frame.varp + size) / sys.PtrSize
+ mask[i/sys.PtrSize] = (*addb(bitmap, off/8) >> (off % 8)) & 1
}
}
return
func allocmcache() *mcache {
lock(&mheap_.lock)
- c := (*mcache)(fixAlloc_Alloc(&mheap_.cachealloc))
+ c := (*mcache)(mheap_.cachealloc.alloc())
unlock(&mheap_.lock)
memclr(unsafe.Pointer(c), unsafe.Sizeof(*c))
for i := 0; i < _NumSizeClasses; i++ {
func freemcache(c *mcache) {
systemstack(func() {
- mCache_ReleaseAll(c)
+ c.releaseAll()
stackcache_clear(c)
// NOTE(rsc,rlh): If gcworkbuffree comes back, we need to coordinate
lock(&mheap_.lock)
purgecachedstats(c)
- fixAlloc_Free(&mheap_.cachealloc, unsafe.Pointer(c))
+ mheap_.cachealloc.free(unsafe.Pointer(c))
unlock(&mheap_.lock)
})
}
// Gets a span that has a free object in it and assigns it
// to be the cached span for the given sizeclass. Returns this span.
-func mCache_Refill(c *mcache, sizeclass int32) *mspan {
+func (c *mcache) refill(sizeclass int32) *mspan {
_g_ := getg()
_g_.m.locks++
}
// Get a new cached span from the central lists.
- s = mCentral_CacheSpan(&mheap_.central[sizeclass].mcentral)
+ s = mheap_.central[sizeclass].mcentral.cacheSpan()
if s == nil {
throw("out of memory")
}
return s
}
-func mCache_ReleaseAll(c *mcache) {
+func (c *mcache) releaseAll() {
for i := 0; i < _NumSizeClasses; i++ {
s := c.alloc[i]
if s != &emptymspan {
- mCentral_UncacheSpan(&mheap_.central[i].mcentral, s)
+ mheap_.central[i].mcentral.uncacheSpan(s)
c.alloc[i] = &emptymspan
}
}
package runtime
+import "runtime/internal/atomic"
+
// Central list of free objects of a given size.
type mcentral struct {
lock mutex
sizeclass int32
- nonempty mspan // list of spans with a free object
- empty mspan // list of spans with no free objects (or cached in an mcache)
+ nonempty mSpanList // list of spans with a free object
+ empty mSpanList // list of spans with no free objects (or cached in an mcache)
}
// Initialize a single central free list.
-func mCentral_Init(c *mcentral, sizeclass int32) {
+func (c *mcentral) init(sizeclass int32) {
c.sizeclass = sizeclass
- mSpanList_Init(&c.nonempty)
- mSpanList_Init(&c.empty)
+ c.nonempty.init()
+ c.empty.init()
}
// Allocate a span to use in an MCache.
-func mCentral_CacheSpan(c *mcentral) *mspan {
+func (c *mcentral) cacheSpan() *mspan {
// Deduct credit for this span allocation and sweep if necessary.
deductSweepCredit(uintptr(class_to_size[c.sizeclass]), 0)
sg := mheap_.sweepgen
retry:
var s *mspan
- for s = c.nonempty.next; s != &c.nonempty; s = s.next {
- if s.sweepgen == sg-2 && cas(&s.sweepgen, sg-2, sg-1) {
- mSpanList_Remove(s)
- mSpanList_InsertBack(&c.empty, s)
+ for s = c.nonempty.first; s != nil; s = s.next {
+ if s.sweepgen == sg-2 && atomic.Cas(&s.sweepgen, sg-2, sg-1) {
+ c.nonempty.remove(s)
+ c.empty.insertBack(s)
unlock(&c.lock)
- mSpan_Sweep(s, true)
+ s.sweep(true)
goto havespan
}
if s.sweepgen == sg-1 {
continue
}
// we have a nonempty span that does not require sweeping, allocate from it
- mSpanList_Remove(s)
- mSpanList_InsertBack(&c.empty, s)
+ c.nonempty.remove(s)
+ c.empty.insertBack(s)
unlock(&c.lock)
goto havespan
}
- for s = c.empty.next; s != &c.empty; s = s.next {
- if s.sweepgen == sg-2 && cas(&s.sweepgen, sg-2, sg-1) {
+ for s = c.empty.first; s != nil; s = s.next {
+ if s.sweepgen == sg-2 && atomic.Cas(&s.sweepgen, sg-2, sg-1) {
// we have an empty span that requires sweeping,
// sweep it and see if we can free some space in it
- mSpanList_Remove(s)
+ c.empty.remove(s)
// swept spans are at the end of the list
- mSpanList_InsertBack(&c.empty, s)
+ c.empty.insertBack(s)
unlock(&c.lock)
- mSpan_Sweep(s, true)
+ s.sweep(true)
if s.freelist.ptr() != nil {
goto havespan
}
unlock(&c.lock)
// Replenish central list if empty.
- s = mCentral_Grow(c)
+ s = c.grow()
if s == nil {
return nil
}
lock(&c.lock)
- mSpanList_InsertBack(&c.empty, s)
+ c.empty.insertBack(s)
unlock(&c.lock)
// At this point s is a non-empty span, queued at the end of the empty list,
if n == 0 {
throw("empty span")
}
+ usedBytes := uintptr(s.ref) * s.elemsize
+ if usedBytes > 0 {
+ reimburseSweepCredit(usedBytes)
+ }
if s.freelist.ptr() == nil {
throw("freelist empty")
}
}
// Return span from an MCache.
-func mCentral_UncacheSpan(c *mcentral, s *mspan) {
+func (c *mcentral) uncacheSpan(s *mspan) {
lock(&c.lock)
s.incache = false
cap := int32((s.npages << _PageShift) / s.elemsize)
n := cap - int32(s.ref)
if n > 0 {
- mSpanList_Remove(s)
- mSpanList_Insert(&c.nonempty, s)
+ c.empty.remove(s)
+ c.nonempty.insert(s)
}
unlock(&c.lock)
}
// the latest generation.
// If preserve=true, don't return the span to heap nor relink in MCentral lists;
// caller takes care of it.
-func mCentral_FreeSpan(c *mcentral, s *mspan, n int32, start gclinkptr, end gclinkptr, preserve bool) bool {
+func (c *mcentral) freeSpan(s *mspan, n int32, start gclinkptr, end gclinkptr, preserve bool) bool {
if s.incache {
throw("freespan into cached span")
}
if preserve {
// preserve is set only when called from MCentral_CacheSpan above,
// the span must be in the empty list.
- if s.next == nil {
+ if !s.inList() {
throw("can't preserve unlinked span")
}
- atomicstore(&s.sweepgen, mheap_.sweepgen)
+ atomic.Store(&s.sweepgen, mheap_.sweepgen)
return false
}
// Move to nonempty if necessary.
if wasempty {
- mSpanList_Remove(s)
- mSpanList_Insert(&c.nonempty, s)
+ c.empty.remove(s)
+ c.nonempty.insert(s)
}
// delay updating sweepgen until here. This is the signal that
// the span may be used in an MCache, so it must come after the
// linked list operations above (actually, just after the
// lock of c above.)
- atomicstore(&s.sweepgen, mheap_.sweepgen)
+ atomic.Store(&s.sweepgen, mheap_.sweepgen)
if s.ref != 0 {
unlock(&c.lock)
}
// s is completely freed, return it to the heap.
- mSpanList_Remove(s)
+ c.nonempty.remove(s)
s.needzero = 1
s.freelist = 0
unlock(&c.lock)
heapBitsForSpan(s.base()).initSpan(s.layout())
- mHeap_Free(&mheap_, s, 0)
+ mheap_.freeSpan(s, 0)
return true
}
// Fetch a new span from the heap and carve into objects for the free list.
-func mCentral_Grow(c *mcentral) *mspan {
+func (c *mcentral) grow() *mspan {
npages := uintptr(class_to_allocnpages[c.sizeclass])
size := uintptr(class_to_size[c.sizeclass])
n := (npages << _PageShift) / size
- s := mHeap_Alloc(&mheap_, npages, c.sizeclass, false, true)
+ s := mheap_.alloc(npages, c.sizeclass, false, true)
if s == nil {
return nil
}
package runtime
-import "unsafe"
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
// Don't split the stack as this function may be invoked without a valid G,
// which prevents us from allocating more stack.
// On 64-bit, people with ulimit -v set complain if we reserve too
// much address space. Instead, assume that the reservation is okay
// and check the assumption in SysMap.
- if ptrSize == 8 && uint64(n) > 1<<32 || goos_nacl != 0 {
+ if sys.PtrSize == 8 && uint64(n) > 1<<32 || sys.GoosNacl != 0 {
*reserved = false
return v
}
package runtime
-import "unsafe"
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
const (
- _PAGE_SIZE = _PhysPageSize
+ _PAGE_SIZE = sys.PhysPageSize
_EACCES = 13
)
// gets most of the benefit of huge pages while keeping the
// number of VMAs under control. With hugePageSize = 2MB, even
// a pessimal heap can reach 128GB before running out of VMAs.
- if hugePageSize != 0 {
- var s uintptr = hugePageSize // division by constant 0 is a compile-time error :(
+ if sys.HugePageSize != 0 {
+ var s uintptr = sys.HugePageSize // division by constant 0 is a compile-time error :(
// If it's a large allocation, we want to leave huge
// pages enabled. Hence, we only adjust the huge page
// Note that madvise will return EINVAL if the flag is
// already set, which is quite likely. We ignore
// errors.
- if head != 0 && head+hugePageSize == tail {
+ if head != 0 && head+sys.HugePageSize == tail {
// head and tail are different but adjacent,
// so do this in one call.
- madvise(unsafe.Pointer(head), 2*hugePageSize, _MADV_NOHUGEPAGE)
+ madvise(unsafe.Pointer(head), 2*sys.HugePageSize, _MADV_NOHUGEPAGE)
} else {
// Advise the huge pages containing v and v+n-1.
if head != 0 {
- madvise(unsafe.Pointer(head), hugePageSize, _MADV_NOHUGEPAGE)
+ madvise(unsafe.Pointer(head), sys.HugePageSize, _MADV_NOHUGEPAGE)
}
if tail != 0 && tail != head {
- madvise(unsafe.Pointer(tail), hugePageSize, _MADV_NOHUGEPAGE)
+ madvise(unsafe.Pointer(tail), sys.HugePageSize, _MADV_NOHUGEPAGE)
}
}
}
}
func sysUsed(v unsafe.Pointer, n uintptr) {
- if hugePageSize != 0 {
+ if sys.HugePageSize != 0 {
// Partially undo the NOHUGEPAGE marks from sysUnused
// for whole huge pages between v and v+n. This may
// leave huge pages off at the end points v and v+n
// the end points as well, but it's probably not worth
// the cost because when neighboring allocations are
// freed sysUnused will just set NOHUGEPAGE again.
- var s uintptr = hugePageSize
+ var s uintptr = sys.HugePageSize
// Round v up to a huge page boundary.
beg := (uintptr(v) + (s - 1)) &^ (s - 1)
// much address space. Instead, assume that the reservation is okay
// if we can reserve at least 64K and check the assumption in SysMap.
// Only user-mode Linux (UML) rejects these requests.
- if ptrSize == 8 && uint64(n) > 1<<32 {
+ if sys.PtrSize == 8 && uint64(n) > 1<<32 {
p := mmap_fixed(v, 64<<10, _PROT_NONE, _MAP_ANON|_MAP_PRIVATE, -1, 0)
if p != v {
if uintptr(p) >= 4096 {
CMPL BX, $2
JBE _1or2
CMPL BX, $4
- JBE _3or4
+ JB _3
+ JE _4
CMPL BX, $8
JBE _5through8
CMPL BX, $16
RET
_0:
RET
-_3or4:
+_3:
MOVW AX, (DI)
- MOVW AX, -2(DI)(BX*1)
+ MOVB AX, 2(DI)
+ RET
+_4:
+ // We need a separate case for 4 to make sure we clear pointers atomically.
+ MOVL AX, (DI)
RET
_5through8:
MOVL AX, (DI)
CMPQ BX, $4
JBE _3or4
CMPQ BX, $8
- JBE _5through8
+ JB _5through7
+ JE _8
CMPQ BX, $16
JBE _9through16
PXOR X0, X0
MOVW AX, (DI)
MOVW AX, -2(DI)(BX*1)
RET
-_5through8:
+_5through7:
MOVL AX, (DI)
MOVL AX, -4(DI)(BX*1)
RET
+_8:
+ // We need a separate case for 8 to make sure we clear pointers atomically.
+ MOVQ AX, (DI)
+ RET
_9through16:
MOVQ AX, (DI)
MOVQ AX, -8(DI)(BX*1)
--- /dev/null
+// Copyright 2015 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 mips64 mips64le
+
+#include "textflag.h"
+
+// void runtime·memclr(void*, uintptr)
+TEXT runtime·memclr(SB),NOSPLIT,$0-16
+ MOVV ptr+0(FP), R1
+ MOVV n+8(FP), R2
+ ADDV R1, R2, R4
+
+ // if less than 8 bytes, do one byte at a time
+ SGTU $8, R2, R3
+ BNE R3, out
+
+ // do one byte at a time until 8-aligned
+ AND $7, R1, R3
+ BEQ R3, words
+ MOVB R0, (R1)
+ ADDV $1, R1
+ JMP -4(PC)
+
+words:
+ // do 8 bytes at a time if there is room
+ ADDV $-7, R4, R2
+
+ SGTU R2, R1, R3
+ BEQ R3, out
+ MOVV R0, (R1)
+ ADDV $8, R1
+ JMP -4(PC)
+
+out:
+ BEQ R1, R4, done
+ MOVB R0, (R1)
+ ADDV $1, R1
+ JMP -3(PC)
+done:
+ RET
CMPL BX, $2
JBE _1or2
CMPL BX, $4
- JBE _3or4
+ JB _3
+ JE _4
CMPL BX, $8
JBE _5through8
CMPL BX, $16
RET
_0:
RET
-_3or4:
+_3:
MOVW AX, (DI)
- MOVW AX, -2(DI)(BX*1)
+ MOVB AX, 2(DI)
+ RET
+_4:
+ // We need a separate case for 4 to make sure we clear pointers atomically.
+ MOVL AX, (DI)
RET
_5through8:
MOVL AX, (DI)
CMPL BX, $2
JBE move_1or2
CMPL BX, $4
- JBE move_3or4
+ JB move_3
+ JE move_4
CMPL BX, $8
JBE move_5through8
CMPL BX, $16
RET
move_0:
RET
-move_3or4:
+move_3:
MOVW (SI), AX
- MOVW -2(SI)(BX*1), CX
+ MOVB 2(SI), CX
MOVW AX, (DI)
- MOVW CX, -2(DI)(BX*1)
+ MOVB CX, 2(DI)
+ RET
+move_4:
+ // We need a separate case for 4 to make sure we write pointers atomically.
+ MOVL (SI), AX
+ MOVL AX, (DI)
RET
move_5through8:
MOVL (SI), AX
CMPQ BX, $4
JBE move_3or4
CMPQ BX, $8
- JBE move_5through8
+ JB move_5through7
+ JE move_8
CMPQ BX, $16
JBE move_9through16
CMPQ BX, $32
MOVW AX, (DI)
MOVW CX, -2(DI)(BX*1)
RET
-move_5through8:
+move_5through7:
MOVL (SI), AX
MOVL -4(SI)(BX*1), CX
MOVL AX, (DI)
MOVL CX, -4(DI)(BX*1)
RET
+move_8:
+ // We need a separate case for 8 to make sure we write pointers atomically.
+ MOVQ (SI), AX
+ MOVQ AX, (DI)
+ RET
move_9through16:
MOVQ (SI), AX
MOVQ -8(SI)(BX*1), CX
--- /dev/null
+// Copyright 2015 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 mips64 mips64le
+
+#include "textflag.h"
+
+// void runtime·memmove(void*, void*, uintptr)
+TEXT runtime·memmove(SB), NOSPLIT, $-8-24
+ MOVV to+0(FP), R1
+ MOVV from+8(FP), R2
+ MOVV n+16(FP), R3
+ BNE R3, check
+ RET
+
+check:
+ SGTU R1, R2, R4
+ BNE R4, backward
+
+ ADDV R1, R3, R6 // end pointer
+
+ // if the two pointers are not of same alignments, do byte copying
+ SUBVU R2, R1, R4
+ AND $7, R4
+ BNE R4, out
+
+ // if less than 8 bytes, do byte copying
+ SGTU $8, R3, R4
+ BNE R4, out
+
+ // do one byte at a time until 8-aligned
+ AND $7, R1, R5
+ BEQ R5, words
+ MOVB (R2), R4
+ ADDV $1, R2
+ MOVB R4, (R1)
+ ADDV $1, R1
+ JMP -6(PC)
+
+words:
+ // do 8 bytes at a time if there is room
+ ADDV $-7, R6, R3 // R3 is end pointer-7
+
+ SGTU R3, R1, R5
+ BEQ R5, out
+ MOVV (R2), R4
+ ADDV $8, R2
+ MOVV R4, (R1)
+ ADDV $8, R1
+ JMP -6(PC)
+
+out:
+ BEQ R1, R6, done
+ MOVB (R2), R4
+ ADDV $1, R2
+ MOVB R4, (R1)
+ ADDV $1, R1
+ JMP -5(PC)
+done:
+ RET
+
+backward:
+ ADDV R3, R2 // from-end pointer
+ ADDV R1, R3, R6 // to-end pointer
+
+ // if the two pointers are not of same alignments, do byte copying
+ SUBVU R6, R2, R4
+ AND $7, R4
+ BNE R4, out1
+
+ // if less than 8 bytes, do byte copying
+ SGTU $8, R3, R4
+ BNE R4, out1
+
+ // do one byte at a time until 8-aligned
+ AND $7, R6, R5
+ BEQ R5, words1
+ ADDV $-1, R2
+ MOVB (R2), R4
+ ADDV $-1, R6
+ MOVB R4, (R6)
+ JMP -6(PC)
+
+words1:
+ // do 8 bytes at a time if there is room
+ ADDV $7, R1, R3 // R3 is start pointer+7
+
+ SGTU R6, R3, R5
+ BEQ R5, out1
+ ADDV $-8, R2
+ MOVV (R2), R4
+ ADDV $-8, R6
+ MOVV R4, (R6)
+ JMP -6(PC)
+
+out1:
+ BEQ R1, R6, done1
+ ADDV $-1, R2
+ MOVB (R2), R4
+ ADDV $-1, R6
+ MOVB R4, (R6)
+ JMP -5(PC)
+done1:
+ RET
REP; MOVSB
CLD
+ // Note: we copy only 4 bytes at a time so that the tail is at most
+ // 3 bytes. That guarantees that we aren't copying pointers with MOVSB.
+ // See issue 13160.
RET
CMPL BX, $2
JBE move_1or2
CMPL BX, $4
- JBE move_3or4
+ JB move_3
+ JE move_4
CMPL BX, $8
JBE move_5through8
CMPL BX, $16
RET
move_0:
RET
-move_3or4:
+move_3:
MOVW (SI), AX
- MOVW -2(SI)(BX*1), CX
+ MOVB 2(SI), CX
MOVW AX, (DI)
- MOVW CX, -2(DI)(BX*1)
+ MOVB CX, 2(DI)
+ RET
+move_4:
+ // We need a separate case for 4 to make sure we write pointers atomically.
+ MOVL (SI), AX
+ MOVL AX, (DI)
RET
move_5through8:
MOVL (SI), AX
CMPQ BX, $4
JBE move_3or4
CMPQ BX, $8
- JBE move_5through8
+ JB move_5through7
+ JE move_8
CMPQ BX, $16
JBE move_9through16
MOVW AX, (DI)
MOVW CX, -2(DI)(BX*1)
RET
-move_5through8:
+move_5through7:
MOVL (SI), AX
MOVL -4(SI)(BX*1), CX
MOVL AX, (DI)
MOVL CX, -4(DI)(BX*1)
RET
+move_8:
+ // We need a separate case for 8 to make sure we write pointers atomically.
+ MOVQ (SI), AX
+ MOVQ AX, (DI)
+ RET
move_9through16:
MOVQ (SI), AX
MOVQ -8(SI)(BX*1), CX
package runtime
-import "unsafe"
+import (
+ "runtime/internal/atomic"
+ "runtime/internal/sys"
+ "unsafe"
+)
type finblock struct {
alllink *finblock
next *finblock
cnt int32
_ int32
- fin [(_FinBlockSize - 2*ptrSize - 2*4) / unsafe.Sizeof(finalizer{})]finalizer
+ fin [(_FinBlockSize - 2*sys.PtrSize - 2*4) / unsafe.Sizeof(finalizer{})]finalizer
}
var finlock mutex // protects the following variables
var fing *g // goroutine that runs finalizers
var finq *finblock // list of finalizers that are to be executed
var finc *finblock // cache of free blocks
-var finptrmask [_FinBlockSize / ptrSize / 8]byte
+var finptrmask [_FinBlockSize / sys.PtrSize / 8]byte
var fingwait bool
var fingwake bool
var allfin *finblock // list of all blocks
if finptrmask[0] == 0 {
// Build pointer mask for Finalizer array in block.
// Check assumptions made in finalizer1 array above.
- if (unsafe.Sizeof(finalizer{}) != 5*ptrSize ||
+ if (unsafe.Sizeof(finalizer{}) != 5*sys.PtrSize ||
unsafe.Offsetof(finalizer{}.fn) != 0 ||
- unsafe.Offsetof(finalizer{}.arg) != ptrSize ||
- unsafe.Offsetof(finalizer{}.nret) != 2*ptrSize ||
- unsafe.Offsetof(finalizer{}.fint) != 3*ptrSize ||
- unsafe.Offsetof(finalizer{}.ot) != 4*ptrSize) {
+ unsafe.Offsetof(finalizer{}.arg) != sys.PtrSize ||
+ unsafe.Offsetof(finalizer{}.nret) != 2*sys.PtrSize ||
+ unsafe.Offsetof(finalizer{}.fint) != 3*sys.PtrSize ||
+ unsafe.Offsetof(finalizer{}.ot) != 4*sys.PtrSize) {
throw("finalizer out of sync")
}
for i := range finptrmask {
func createfing() {
// start the finalizer goroutine exactly once
- if fingCreate == 0 && cas(&fingCreate, 0, 1) {
+ if fingCreate == 0 && atomic.Cas(&fingCreate, 0, 1) {
go runfinq()
}
}
}
for fb != nil {
for i := fb.cnt; i > 0; i-- {
- f := (*finalizer)(add(unsafe.Pointer(&fb.fin), uintptr(i-1)*unsafe.Sizeof(finalizer{})))
+ f := &fb.fin[i-1]
framesz := unsafe.Sizeof((interface{})(nil)) + uintptr(f.nret)
if framecap < framesz {
if len(ityp.mhdr) != 0 {
// convert to interface with methods
// this conversion is guaranteed to succeed - we checked in SetFinalizer
- assertE2I(ityp, *(*interface{})(frame), (*fInterface)(frame))
+ assertE2I(ityp, *(*eface)(frame), (*iface)(frame))
}
default:
throw("bad kind in runfinq")
// (and we don't have the data structures to record them).
return
}
- e := (*eface)(unsafe.Pointer(&obj))
+ e := efaceOf(&obj)
etyp := e._type
if etyp == nil {
throw("runtime.SetFinalizer: first argument is nil")
}
}
- f := (*eface)(unsafe.Pointer(&finalizer))
+ f := efaceOf(&finalizer)
ftyp := f._type
if ftyp == nil {
// switch to system stack and remove finalizer
throw("runtime.SetFinalizer: second argument is " + *ftyp._string + ", not a function")
}
ft := (*functype)(unsafe.Pointer(ftyp))
- ins := *(*[]*_type)(unsafe.Pointer(&ft.in))
- if ft.dotdotdot || len(ins) != 1 {
+ if ft.dotdotdot || len(ft.in) != 1 {
throw("runtime.SetFinalizer: cannot pass " + *etyp._string + " to finalizer " + *ftyp._string)
}
- fint := ins[0]
+ fint := ft.in[0]
switch {
case fint == etyp:
// ok - same type
// ok - satisfies empty interface
goto okarg
}
- if assertE2I2(ityp, obj, nil) {
+ if assertE2I2(ityp, *efaceOf(&obj), nil) {
goto okarg
}
}
okarg:
// compute size needed for return parameters
nret := uintptr(0)
- for _, t := range *(*[]*_type)(unsafe.Pointer(&ft.out)) {
+ for _, t := range ft.out {
nret = round(nret, uintptr(t.align)) + uintptr(t.size)
}
- nret = round(nret, ptrSize)
+ nret = round(nret, sys.PtrSize)
// make sure we have a finalizer goroutine
createfing()
func findObject(v unsafe.Pointer) (s *mspan, x unsafe.Pointer, n uintptr) {
c := gomcache()
c.local_nlookup++
- if ptrSize == 4 && c.local_nlookup >= 1<<30 {
+ if sys.PtrSize == 4 && c.local_nlookup >= 1<<30 {
// purge cache stats to prevent overflow
lock(&mheap_.lock)
purgecachedstats(c)
}
// find span
- arena_start := uintptr(unsafe.Pointer(mheap_.arena_start))
- arena_used := uintptr(unsafe.Pointer(mheap_.arena_used))
+ arena_start := mheap_.arena_start
+ arena_used := mheap_.arena_used
if uintptr(v) < arena_start || uintptr(v) >= arena_used {
return
}
p := uintptr(v) >> pageShift
q := p - arena_start>>pageShift
- s = *(**mspan)(add(unsafe.Pointer(mheap_.spans), q*ptrSize))
+ s = *(**mspan)(add(unsafe.Pointer(mheap_.spans), q*sys.PtrSize))
if s == nil {
return
}
first func(arg, p unsafe.Pointer) // called first time p is returned
arg unsafe.Pointer
list *mlink
- chunk *byte
+ chunk unsafe.Pointer
nchunk uint32
inuse uintptr // in-use bytes now
stat *uint64
// Initialize f to allocate objects of the given size,
// using the allocator to obtain chunks of memory.
-func fixAlloc_Init(f *fixalloc, size uintptr, first func(arg, p unsafe.Pointer), arg unsafe.Pointer, stat *uint64) {
+func (f *fixalloc) init(size uintptr, first func(arg, p unsafe.Pointer), arg unsafe.Pointer, stat *uint64) {
f.size = size
f.first = first
f.arg = arg
f.stat = stat
}
-func fixAlloc_Alloc(f *fixalloc) unsafe.Pointer {
+func (f *fixalloc) alloc() unsafe.Pointer {
if f.size == 0 {
print("runtime: use of FixAlloc_Alloc before FixAlloc_Init\n")
throw("runtime: internal error")
return v
}
if uintptr(f.nchunk) < f.size {
- f.chunk = (*uint8)(persistentalloc(_FixAllocChunk, 0, f.stat))
+ f.chunk = persistentalloc(_FixAllocChunk, 0, f.stat)
f.nchunk = _FixAllocChunk
}
- v := unsafe.Pointer(f.chunk)
+ v := f.chunk
if f.first != nil {
f.first(f.arg, v)
}
- f.chunk = (*byte)(add(unsafe.Pointer(f.chunk), f.size))
+ f.chunk = add(f.chunk, f.size)
f.nchunk -= uint32(f.size)
f.inuse += f.size
return v
}
-func fixAlloc_Free(f *fixalloc, p unsafe.Pointer) {
+func (f *fixalloc) free(p unsafe.Pointer) {
f.inuse -= f.size
v := (*mlink)(p)
v.next = f.list
package runtime
-import "unsafe"
+import (
+ "runtime/internal/atomic"
+ "runtime/internal/sys"
+ "unsafe"
+)
const (
_DebugGC = 0
_ConcurrentSweep = true
_FinBlockSize = 4 * 1024
- _RootData = 0
- _RootBss = 1
- _RootFinalizers = 2
- _RootFlushCaches = 3
- _RootSpans0 = 4
- _RootSpansShards = 128
- _RootCount = _RootSpans0 + _RootSpansShards
-
// sweepMinHeapDistance is a lower bound on the heap distance
// (in bytes) reserved for concurrent sweeping between GC
// cycles. This will be scaled by gcpercent/100.
throw("size of Workbuf is suboptimal")
}
- work.markfor = parforalloc(_MaxGcproc)
_ = setGCPercent(readgogc())
for datap := &firstmoduledata; datap != nil; datap = datap.next {
datap.gcdatamask = progToPointerMask((*byte)(unsafe.Pointer(datap.gcdata)), datap.edata-datap.data)
datap.gcbssmask = progToPointerMask((*byte)(unsafe.Pointer(datap.gcbss)), datap.ebss-datap.bss)
}
memstats.next_gc = heapminimum
+ work.startSema = 1
+ work.markDoneSema = 1
}
func readgogc() int32 {
// Garbage collector phase.
// Indicates to write barrier and sychronization task to preform.
var gcphase uint32
-var writeBarrierEnabled bool // compiler emits references to this in write barriers
+
+// The compiler knows about this variable.
+// If you change it, you must change the compiler too.
+var writeBarrier struct {
+ enabled bool // compiler emits a check of this before calling write barrier
+ needed bool // whether we need a write barrier for current GC phase
+ cgo bool // whether we need a write barrier for a cgo check
+}
// gcBlackenEnabled is 1 if mutator assists and background mark
// workers are allowed to blacken objects. This must only be set when
const (
_GCoff = iota // GC not running; sweeping in background, write barrier disabled
- _GCstw // unused state
- _GCscan // GC collecting roots into workbufs, write barrier ENABLED
- _GCmark // GC marking from workbufs, write barrier ENABLED
+ _GCmark // GC marking roots and workbufs, write barrier ENABLED
_GCmarktermination // GC mark termination: allocate black, P's help GC, write barrier ENABLED
)
//go:nosplit
func setGCPhase(x uint32) {
- atomicstore(&gcphase, x)
- writeBarrierEnabled = gcphase == _GCmark || gcphase == _GCmarktermination || gcphase == _GCscan
+ atomic.Store(&gcphase, x)
+ writeBarrier.needed = gcphase == _GCmark || gcphase == _GCmarktermination
+ writeBarrier.enabled = writeBarrier.needed || writeBarrier.cgo
}
// gcMarkWorkerMode represents the mode that a concurrent mark worker
const (
// gcMarkWorkerDedicatedMode indicates that the P of a mark
// worker is dedicated to running that mark worker. The mark
- // worker should run without preemption until concurrent mark
- // is done.
+ // worker should run without preemption.
gcMarkWorkerDedicatedMode gcMarkWorkerMode = iota
// gcMarkWorkerFractionalMode indicates that a P is currently
// at the end of of each cycle.
triggerRatio float64
- _ [_CacheLineSize]byte
+ _ [sys.CacheLineSize]byte
// fractionalMarkWorkersNeeded is the number of fractional
// mark workers that need to be started. This is either 0 or
// scheduling point (hence it gets its own cache line).
fractionalMarkWorkersNeeded int64
- _ [_CacheLineSize]byte
+ _ [sys.CacheLineSize]byte
}
// startCycle resets the GC controller's state and computes estimates
}
}
+// enlistWorker encourages another dedicated mark worker to start on
+// another P if there are spare worker slots. It is used by putfull
+// when more work is made available.
+//
+//go:nowritebarrier
+func (c *gcControllerState) enlistWorker() {
+ if c.dedicatedMarkWorkersNeeded <= 0 {
+ return
+ }
+ // Pick a random other P to preempt.
+ if gomaxprocs <= 1 {
+ return
+ }
+ gp := getg()
+ if gp == nil || gp.m == nil || gp.m.p == 0 {
+ return
+ }
+ myID := gp.m.p.ptr().id
+ for tries := 0; tries < 5; tries++ {
+ id := int32(fastrand1() % uint32(gomaxprocs-1))
+ if id >= myID {
+ id++
+ }
+ p := allp[id]
+ if p.status != _Prunning {
+ continue
+ }
+ if preemptone(p) {
+ return
+ }
+ }
+}
+
// findRunnableGCWorker returns the background mark worker for _p_ if it
// should be run. This must only be called when gcBlackenEnabled != 0.
func (c *gcControllerState) findRunnableGCWorker(_p_ *p) *g {
throw("gcControllerState.findRunnable: blackening not enabled")
}
if _p_.gcBgMarkWorker == nil {
- throw("gcControllerState.findRunnable: no background mark worker")
- }
- if work.bgMark1.done != 0 && work.bgMark2.done != 0 {
- // Background mark is done. Don't schedule background
- // mark worker any more. (This is not just an
- // optimization. Without this we can spin scheduling
- // the background worker and having it return
- // immediately with no work to do.)
+ // The mark worker associated with this P is blocked
+ // performing a mark transition. We can't run it
+ // because it may be on some other run or wait queue.
+ return nil
+ }
+
+ if !gcMarkWorkAvailable(_p_) {
+ // No work to be done right now. This can happen at
+ // the end of the mark phase when there are still
+ // assists tapering off. Don't bother running a worker
+ // now because it'll just return immediately.
return nil
}
decIfPositive := func(ptr *int64) bool {
if *ptr > 0 {
- if xaddint64(ptr, -1) >= 0 {
+ if atomic.Xaddint64(ptr, -1) >= 0 {
return true
}
// We lost a race
- xaddint64(ptr, +1)
+ atomic.Xaddint64(ptr, +1)
}
return false
}
// else for a while, so kick everything out of its run
// queue.
} else {
- if _p_.gcw.wbuf == 0 && work.full == 0 {
- // No work to be done right now. This can
- // happen at the end of the mark phase when
- // there are still assists tapering off. Don't
- // bother running background mark because
- // it'll just return immediately.
- if work.nwait == work.nproc {
- // There are also no workers, which
- // means we've reached a completion point.
- // There may not be any workers to
- // signal it, so signal it here.
- readied := false
- if gcBlackenPromptly {
- if work.bgMark1.done == 0 {
- throw("completing mark 2, but bgMark1.done == 0")
- }
- readied = work.bgMark2.complete()
- } else {
- readied = work.bgMark1.complete()
- }
- if readied {
- // complete just called ready,
- // but we're inside the
- // scheduler. Let it know that
- // that's okay.
- resetspinning()
- }
- }
- return nil
- }
if !decIfPositive(&c.fractionalMarkWorkersNeeded) {
// No more workers are need right now.
return nil
timeUsed := c.fractionalMarkTime + gcForcePreemptNS
if then > 0 && float64(timeUsed)/float64(then) > c.fractionalUtilizationGoal {
// Nope, we'd overshoot the utilization goal
- xaddint64(&c.fractionalMarkWorkersNeeded, +1)
+ atomic.Xaddint64(&c.fractionalMarkWorkersNeeded, +1)
return nil
}
_p_.gcMarkWorkerMode = gcMarkWorkerFractionalMode
// of future allocations.
const gcOverAssistBytes = 1 << 20
-// Determine whether to initiate a GC.
-// If the GC is already working no need to trigger another one.
-// This should establish a feedback loop where if the GC does not
-// have sufficient time to complete then more memory will be
-// requested from the OS increasing heap size thus allow future
-// GCs more time to complete.
-// memstat.heap_live read has a benign race.
-// A false negative simple does not start a GC, a false positive
-// will start a GC needlessly. Neither have correctness issues.
-func shouldtriggergc() bool {
- return memstats.heap_live >= memstats.next_gc && atomicloaduint(&bggc.working) == 0
-}
-
-// bgMarkSignal synchronizes the GC coordinator and background mark workers.
-type bgMarkSignal struct {
- // Workers race to cas to 1. Winner signals coordinator.
- done uint32
- // Coordinator to wake up.
- lock mutex
- g *g
- wake bool
-}
-
-func (s *bgMarkSignal) wait() {
- lock(&s.lock)
- if s.wake {
- // Wakeup already happened
- unlock(&s.lock)
- } else {
- s.g = getg()
- goparkunlock(&s.lock, "mark wait (idle)", traceEvGoBlock, 1)
- }
- s.wake = false
- s.g = nil
-}
-
-// complete signals the completion of this phase of marking. This can
-// be called multiple times during a cycle; only the first call has
-// any effect.
-//
-// The caller should arrange to deschedule itself as soon as possible
-// after calling complete in order to let the coordinator goroutine
-// run.
-func (s *bgMarkSignal) complete() bool {
- if cas(&s.done, 0, 1) {
- // This is the first worker to reach this completion point.
- // Signal the main GC goroutine.
- lock(&s.lock)
- if s.g == nil {
- // It hasn't parked yet.
- s.wake = true
- } else {
- ready(s.g, 0)
- }
- unlock(&s.lock)
- return true
- }
- return false
-}
+var work struct {
+ full uint64 // lock-free list of full blocks workbuf
+ empty uint64 // lock-free list of empty blocks workbuf
+ pad0 [sys.CacheLineSize]uint8 // prevents false-sharing between full/empty and nproc/nwait
-func (s *bgMarkSignal) clear() {
- s.done = 0
-}
+ markrootNext uint32 // next markroot job
+ markrootJobs uint32 // number of markroot jobs
-var work struct {
- full uint64 // lock-free list of full blocks workbuf
- empty uint64 // lock-free list of empty blocks workbuf
- pad0 [_CacheLineSize]uint8 // prevents false-sharing between full/empty and nproc/nwait
nproc uint32
tstart int64
nwait uint32
ndone uint32
alldone note
- markfor *parfor
+
+ // Number of roots of various root types. Set by gcMarkRootPrepare.
+ nDataRoots, nBSSRoots, nSpanRoots, nStackRoots int
// finalizersDone indicates that finalizers and objects with
// finalizers have been scanned by markroot. During concurrent
// STW GC, this happens during mark termination.
finalizersDone bool
+ // Each type of GC state transition is protected by a lock.
+ // Since multiple threads can simultaneously detect the state
+ // transition condition, any thread that detects a transition
+ // condition must acquire the appropriate transition lock,
+ // re-check the transition condition and return if it no
+ // longer holds or perform the transition if it does.
+ // Likewise, any transition must invalidate the transition
+ // condition before releasing the lock. This ensures that each
+ // transition is performed by exactly one thread and threads
+ // that need the transition to happen block until it has
+ // happened.
+ //
+ // startSema protects the transition from "off" to mark or
+ // mark termination.
+ startSema uint32
+ // markDoneSema protects transitions from mark 1 to mark 2 and
+ // from mark 2 to mark termination.
+ markDoneSema uint32
+
bgMarkReady note // signal background mark worker has started
bgMarkDone uint32 // cas to 1 when at a background mark completion point
// Background mark completion signaling
- // Coordination for the 2 parts of the mark phase.
- bgMark1 bgMarkSignal
- bgMark2 bgMarkSignal
+ // mode is the concurrency mode of the current GC cycle.
+ mode gcMode
// Copy of mheap.allspans for marker or sweeper.
spans []*mspan
// initialHeapLive is the value of memstats.heap_live at the
// beginning of this GC cycle.
initialHeapLive uint64
+
+ // assistQueue is a queue of assists that are blocked because
+ // there was neither enough credit to steal or enough work to
+ // do.
+ assistQueue struct {
+ lock mutex
+ head, tail guintptr
+ }
+
+ // Timing/utilization stats for this cycle.
+ stwprocs, maxprocs int32
+ tSweepTerm, tMark, tMarkTerm, tEnd int64 // nanotime() of phase start
+
+ pauseNS int64 // total STW time this cycle
+ pauseStart int64 // nanotime() of last STW
+
+ // debug.gctrace heap sizes for this cycle.
+ heap0, heap1, heap2, heapGoal uint64
}
// GC runs a garbage collection and blocks the caller until the
// garbage collection is complete. It may also block the entire
// program.
func GC() {
- startGC(gcForceBlockMode, false)
+ gcStart(gcForceBlockMode, false)
}
// gcMode indicates how concurrent a GC cycle should be.
gcForceBlockMode // stop-the-world GC now and STW sweep
)
-// startGC starts a GC cycle. If mode is gcBackgroundMode, this will
-// start GC in the background and return. Otherwise, this will block
-// until the new GC cycle is started and finishes. If forceTrigger is
-// true, it indicates that GC should be started regardless of the
-// current heap size.
-func startGC(mode gcMode, forceTrigger bool) {
- // The gc is turned off (via enablegc) until the bootstrap has completed.
- // Also, malloc gets called in the guts of a number of libraries that might be
- // holding locks. To avoid deadlocks during stop-the-world, don't bother
- // trying to run gc while holding a lock. The next mallocgc without a lock
- // will do the gc instead.
+// gcShouldStart returns true if the exit condition for the _GCoff
+// phase has been met. The exit condition should be tested when
+// allocating.
+//
+// If forceTrigger is true, it ignores the current heap size, but
+// checks all other conditions. In general this should be false.
+func gcShouldStart(forceTrigger bool) bool {
+ return gcphase == _GCoff && (forceTrigger || memstats.heap_live >= memstats.next_gc) && memstats.enablegc && panicking == 0 && gcpercent >= 0
+}
+
+// gcStart transitions the GC from _GCoff to _GCmark (if mode ==
+// gcBackgroundMode) or _GCmarktermination (if mode !=
+// gcBackgroundMode) by performing sweep termination and GC
+// initialization.
+//
+// This may return without performing this transition in some cases,
+// such as when called on a system stack or with locks held.
+func gcStart(mode gcMode, forceTrigger bool) {
+ // Since this is called from malloc and malloc is called in
+ // the guts of a number of libraries that might be holding
+ // locks, don't attempt to start GC in non-preemptible or
+ // potentially unstable situations.
mp := acquirem()
- if gp := getg(); gp == mp.g0 || mp.locks > 1 || mp.preemptoff != "" || !memstats.enablegc || panicking != 0 || gcpercent < 0 {
+ if gp := getg(); gp == mp.g0 || mp.locks > 1 || mp.preemptoff != "" {
releasem(mp)
return
}
releasem(mp)
mp = nil
- if debug.gcstoptheworld == 1 {
- mode = gcForceMode
- } else if debug.gcstoptheworld == 2 {
- mode = gcForceBlockMode
- }
-
- if mode != gcBackgroundMode {
- // special synchronous cases
- gc(mode)
- return
- }
-
- // trigger concurrent GC
- readied := false
- lock(&bggc.lock)
- // The trigger was originally checked speculatively, so
- // recheck that this really should trigger GC. (For example,
- // we may have gone through a whole GC cycle since the
- // speculative check.)
- if !(forceTrigger || shouldtriggergc()) {
- unlock(&bggc.lock)
- return
- }
- if !bggc.started {
- bggc.working = 1
- bggc.started = true
- readied = true
- go backgroundgc()
- } else if bggc.working == 0 {
- bggc.working = 1
- readied = true
- ready(bggc.g, 0)
- }
- unlock(&bggc.lock)
- if readied {
- // This G just started or ready()d the GC goroutine.
- // Switch directly to it by yielding.
- Gosched()
- }
-}
-
-// State of the background concurrent GC goroutine.
-var bggc struct {
- lock mutex
- g *g
- working uint
- started bool
-}
-
-// backgroundgc is running in a goroutine and does the concurrent GC work.
-// bggc holds the state of the backgroundgc.
-func backgroundgc() {
- bggc.g = getg()
- for {
- gc(gcBackgroundMode)
- lock(&bggc.lock)
- bggc.working = 0
- goparkunlock(&bggc.lock, "Concurrent GC wait", traceEvGoBlock, 1)
- }
-}
-
-func gc(mode gcMode) {
- // Timing/utilization tracking
- var stwprocs, maxprocs int32
- var tSweepTerm, tScan, tInstallWB, tMark, tMarkTerm int64
-
- // debug.gctrace variables
- var heap0, heap1, heap2, heapGoal uint64
-
- // memstats statistics
- var now, pauseStart, pauseNS int64
-
- // Ok, we're doing it! Stop everybody else
- semacquire(&worldsema, false)
-
// Pick up the remaining unswept/not being swept spans concurrently
//
// This shouldn't happen if we're being invoked in background
// sweeping everything, but rounding errors, etc, may leave a
// few spans unswept. In forced mode, this is necessary since
// GC can be forced at any point in the sweeping cycle.
- for gosweepone() != ^uintptr(0) {
+ //
+ // We check the transition condition continuously here in case
+ // this G gets delayed in to the next GC cycle.
+ for (mode != gcBackgroundMode || gcShouldStart(forceTrigger)) && gosweepone() != ^uintptr(0) {
sweep.nbgsweep++
}
+ // Perform GC initialization and the sweep termination
+ // transition.
+ //
+ // If this is a forced GC, don't acquire the transition lock
+ // or re-check the transition condition because we
+ // specifically *don't* want to share the transition with
+ // another thread.
+ useStartSema := mode == gcBackgroundMode
+ if useStartSema {
+ semacquire(&work.startSema, false)
+ // Re-check transition condition under transition lock.
+ if !gcShouldStart(forceTrigger) {
+ semrelease(&work.startSema)
+ return
+ }
+ }
+
+ // In gcstoptheworld debug mode, upgrade the mode accordingly.
+ // We do this after re-checking the transition condition so
+ // that multiple goroutines that detect the heap trigger don't
+ // start multiple STW GCs.
+ if mode == gcBackgroundMode {
+ if debug.gcstoptheworld == 1 {
+ mode = gcForceMode
+ } else if debug.gcstoptheworld == 2 {
+ mode = gcForceBlockMode
+ }
+ }
+
+ // Ok, we're doing it! Stop everybody else
+ semacquire(&worldsema, false)
+
if trace.enabled {
traceGCStart()
}
if mode == gcBackgroundMode {
gcBgMarkStartWorkers()
}
- now = nanotime()
- stwprocs, maxprocs = gcprocs(), gomaxprocs
- tSweepTerm = now
- heap0 = memstats.heap_live
+ now := nanotime()
+ work.stwprocs, work.maxprocs = gcprocs(), gomaxprocs
+ work.tSweepTerm = now
+ work.heap0 = memstats.heap_live
+ work.pauseNS = 0
+ work.mode = mode
- pauseStart = now
+ work.pauseStart = now
systemstack(stopTheWorldWithSema)
// Finish sweep before we start concurrent scan.
systemstack(func() {
if mode == gcBackgroundMode { // Do as much work concurrently as possible
gcController.startCycle()
- heapGoal = gcController.heapGoal
+ work.heapGoal = gcController.heapGoal
+
+ // Enter concurrent mark phase and enable
+ // write barriers.
+ //
+ // Because the world is stopped, all Ps will
+ // observe that write barriers are enabled by
+ // the time we start the world and begin
+ // scanning.
+ //
+ // It's necessary to enable write barriers
+ // during the scan phase for several reasons:
+ //
+ // They must be enabled for writes to higher
+ // stack frames before we scan stacks and
+ // install stack barriers because this is how
+ // we track writes to inactive stack frames.
+ // (Alternatively, we could not install stack
+ // barriers over frame boundaries with
+ // up-pointers).
+ //
+ // They must be enabled before assists are
+ // enabled because they must be enabled before
+ // any non-leaf heap objects are marked. Since
+ // allocations are blocked until assists can
+ // happen, we want enable assists as early as
+ // possible.
+ setGCPhase(_GCmark)
+
+ // markrootSpans uses work.spans, so make sure
+ // it is up to date.
+ gcCopySpans()
+
+ gcBgMarkPrepare() // Must happen before assist enable.
+ gcMarkRootPrepare()
+
+ // At this point all Ps have enabled the write
+ // barrier, thus maintaining the no white to
+ // black invariant. Enable mutator assists to
+ // put back-pressure on fast allocating
+ // mutators.
+ atomic.Store(&gcBlackenEnabled, 1)
+
+ // Assists and workers can start the moment we start
+ // the world.
+ gcController.assistStartTime = now
+ gcController.bgMarkStartTime = now
- systemstack(func() {
- // Enter scan phase. This enables write
- // barriers to track changes to stack frames
- // above the stack barrier.
- //
- // TODO: This has evolved to the point where
- // we carefully ensure invariants we no longer
- // depend on. Either:
- //
- // 1) Enable full write barriers for the scan,
- // but eliminate the ragged barrier below
- // (since the start the world ensures all Ps
- // have observed the write barrier enable) and
- // consider draining during the scan.
- //
- // 2) Only enable write barriers for writes to
- // the stack at this point, and then enable
- // write barriers for heap writes when we
- // enter the mark phase. This means we cannot
- // drain in the scan phase and must perform a
- // ragged barrier to ensure all Ps have
- // enabled heap write barriers before we drain
- // or enable assists.
- //
- // 3) Don't install stack barriers over frame
- // boundaries where there are up-pointers.
- setGCPhase(_GCscan)
-
- // markrootSpans uses work.spans, so make sure
- // it is up to date.
- gcCopySpans()
-
- gcBgMarkPrepare() // Must happen before assist enable.
-
- // At this point all Ps have enabled the write
- // barrier, thus maintaining the no white to
- // black invariant. Enable mutator assists to
- // put back-pressure on fast allocating
- // mutators.
- atomicstore(&gcBlackenEnabled, 1)
-
- // Concurrent scan.
- startTheWorldWithSema()
- now = nanotime()
- pauseNS += now - pauseStart
- tScan = now
- gcController.assistStartTime = now
- gcscan_m()
-
- // Enter mark phase.
- tInstallWB = nanotime()
- setGCPhase(_GCmark)
- // Ensure all Ps have observed the phase
- // change and have write barriers enabled
- // before any blackening occurs.
- forEachP(func(*p) {})
- })
// Concurrent mark.
- tMark = nanotime()
+ systemstack(startTheWorldWithSema)
+ now = nanotime()
+ work.pauseNS += now - work.pauseStart
+ work.tMark = now
+ } else {
+ t := nanotime()
+ work.tMark, work.tMarkTerm = t, t
+ work.heapGoal = work.heap0
+
+ // Perform mark termination. This will restart the world.
+ gcMarkTermination()
+ }
+
+ if useStartSema {
+ semrelease(&work.startSema)
+ }
+}
+
+// gcMarkDone transitions the GC from mark 1 to mark 2 and from mark 2
+// to mark termination.
+//
+// This should be called when all mark work has been drained. In mark
+// 1, this includes all root marking jobs, global work buffers, and
+// active work buffers in assists and background workers; however,
+// work may still be cached in per-P work buffers. In mark 2, per-P
+// caches are disabled.
+func gcMarkDone() {
+ semacquire(&work.markDoneSema, false)
+
+ // Re-check transition condition under transition lock.
+ if !(gcphase == _GCmark && work.nwait == work.nproc && !gcMarkWorkAvailable(nil)) {
+ semrelease(&work.markDoneSema)
+ return
+ }
- // Enable background mark workers and wait for
- // background mark completion.
- gcController.bgMarkStartTime = nanotime()
- work.bgMark1.clear()
- work.bgMark1.wait()
+ // Disallow starting new workers so that any remaining workers
+ // in the current mark phase will drain out.
+ //
+ // TODO(austin): Should dedicated workers keep an eye on this
+ // and exit gcDrain promptly?
+ atomic.Xaddint64(&gcController.dedicatedMarkWorkersNeeded, -0xffffffff)
+ atomic.Xaddint64(&gcController.fractionalMarkWorkersNeeded, -0xffffffff)
+ if !gcBlackenPromptly {
+ // Transition from mark 1 to mark 2.
+ //
// The global work list is empty, but there can still be work
// sitting in the per-P work caches and there can be more
// objects reachable from global roots since they don't have write
// barriers. Rescan some roots and flush work caches.
- systemstack(func() {
- // rescan global data and bss.
- markroot(nil, _RootData)
- markroot(nil, _RootBss)
- // Disallow caching workbufs.
- gcBlackenPromptly = true
+ gcMarkRootCheck()
+
+ // Disallow caching workbufs and indicate that we're in mark 2.
+ gcBlackenPromptly = true
+
+ // Prevent completion of mark 2 until we've flushed
+ // cached workbufs.
+ atomic.Xadd(&work.nwait, -1)
- // Flush all currently cached workbufs. This
- // also forces any remaining background
- // workers out of their loop.
+ // Rescan global data and BSS. There may still work
+ // workers running at this point, so bump "jobs" down
+ // before "next" so they won't try running root jobs
+ // until we set next.
+ atomic.Store(&work.markrootJobs, uint32(fixedRootCount+work.nDataRoots+work.nBSSRoots))
+ atomic.Store(&work.markrootNext, fixedRootCount)
+
+ // GC is set up for mark 2. Let Gs blocked on the
+ // transition lock go while we flush caches.
+ semrelease(&work.markDoneSema)
+
+ systemstack(func() {
+ // Flush all currently cached workbufs and
+ // ensure all Ps see gcBlackenPromptly. This
+ // also blocks until any remaining mark 1
+ // workers have exited their loop so we can
+ // start new mark 2 workers that will observe
+ // the new root marking jobs.
forEachP(func(_p_ *p) {
_p_.gcw.dispose()
})
})
- // Wait for this more aggressive background mark to complete.
- work.bgMark2.clear()
- work.bgMark2.wait()
+ // Now we can start up mark 2 workers.
+ atomic.Xaddint64(&gcController.dedicatedMarkWorkersNeeded, 0xffffffff)
+ atomic.Xaddint64(&gcController.fractionalMarkWorkersNeeded, 0xffffffff)
- // Begin mark termination.
- now = nanotime()
- tMarkTerm = now
- pauseStart = now
+ incnwait := atomic.Xadd(&work.nwait, +1)
+ if incnwait == work.nproc && !gcMarkWorkAvailable(nil) {
+ // This recursion is safe because the call
+ // can't take this same "if" branch.
+ gcMarkDone()
+ }
+ } else {
+ // Transition to mark termination.
+ now := nanotime()
+ work.tMarkTerm = now
+ work.pauseStart = now
systemstack(stopTheWorldWithSema)
// The gcphase is _GCmark, it will transition to _GCmarktermination
// below. The important thing is that the wb remains active until
// in these caches.
gcFlushGCWork()
+ // Wake all blocked assists. These will run when we
+ // start the world again.
+ gcWakeAllAssists()
+
+ // Likewise, release the transition lock. Blocked
+ // workers and assists will run when we start the
+ // world again.
+ semrelease(&work.markDoneSema)
+
gcController.endCycle()
- } else {
- t := nanotime()
- tScan, tInstallWB, tMark, tMarkTerm = t, t, t, t
- heapGoal = heap0
+
+ // Perform mark termination. This will restart the world.
+ gcMarkTermination()
}
+}
+func gcMarkTermination() {
// World is stopped.
// Start marktermination which includes enabling the write barrier.
- atomicstore(&gcBlackenEnabled, 0)
+ atomic.Store(&gcBlackenEnabled, 0)
gcBlackenPromptly = false
setGCPhase(_GCmarktermination)
- heap1 = memstats.heap_live
+ work.heap1 = memstats.heap_live
startTime := nanotime()
mp := acquirem()
})
systemstack(func() {
- heap2 = work.bytesMarked
+ work.heap2 = work.bytesMarked
if debug.gccheckmark > 0 {
// Run a full stop-the-world mark using checkmark bits,
// to check that we didn't forget to mark anything during
// marking is complete so we can turn the write barrier off
setGCPhase(_GCoff)
- gcSweep(mode)
+ gcSweep(work.mode)
if debug.gctrace > 1 {
startTime = nanotime()
setGCPhase(_GCmarktermination)
gcMark(startTime)
setGCPhase(_GCoff) // marking is done, turn off wb.
- gcSweep(mode)
+ gcSweep(work.mode)
}
})
// Update timing memstats
now, unixNow := nanotime(), unixnanotime()
- pauseNS += now - pauseStart
- atomicstore64(&memstats.last_gc, uint64(unixNow)) // must be Unix time to make sense to user
- memstats.pause_ns[memstats.numgc%uint32(len(memstats.pause_ns))] = uint64(pauseNS)
+ work.pauseNS += now - work.pauseStart
+ work.tEnd = now
+ atomic.Store64(&memstats.last_gc, uint64(unixNow)) // must be Unix time to make sense to user
+ memstats.pause_ns[memstats.numgc%uint32(len(memstats.pause_ns))] = uint64(work.pauseNS)
memstats.pause_end[memstats.numgc%uint32(len(memstats.pause_end))] = uint64(unixNow)
- memstats.pause_total_ns += uint64(pauseNS)
+ memstats.pause_total_ns += uint64(work.pauseNS)
// Update work.totaltime.
- sweepTermCpu := int64(stwprocs) * (tScan - tSweepTerm)
- scanCpu := tInstallWB - tScan
- installWBCpu := int64(0)
+ sweepTermCpu := int64(work.stwprocs) * (work.tMark - work.tSweepTerm)
// We report idle marking time below, but omit it from the
// overall utilization here since it's "free".
markCpu := gcController.assistTime + gcController.dedicatedMarkTime + gcController.fractionalMarkTime
- markTermCpu := int64(stwprocs) * (now - tMarkTerm)
- cycleCpu := sweepTermCpu + scanCpu + installWBCpu + markCpu + markTermCpu
+ markTermCpu := int64(work.stwprocs) * (work.tEnd - work.tMarkTerm)
+ cycleCpu := sweepTermCpu + markCpu + markTermCpu
work.totaltime += cycleCpu
// Compute overall GC CPU utilization.
memstats.numgc++
systemstack(startTheWorldWithSema)
+
+ // Free stack spans. This must be done between GC cycles.
+ systemstack(freeStackSpans)
+
semrelease(&worldsema)
releasem(mp)
mp = nil
if debug.gctrace > 0 {
- tEnd := now
util := int(memstats.gc_cpu_fraction * 100)
+ // Install WB phase is no longer used.
+ tInstallWB := work.tMark
+ installWBCpu := int64(0)
+
+ // Scan phase is no longer used.
+ tScan := tInstallWB
+ scanCpu := int64(0)
+
+ // TODO: Clean up the gctrace format.
+
var sbuf [24]byte
printlock()
print("gc ", memstats.numgc,
- " @", string(itoaDiv(sbuf[:], uint64(tSweepTerm-runtimeInitTime)/1e6, 3)), "s ",
+ " @", string(itoaDiv(sbuf[:], uint64(work.tSweepTerm-runtimeInitTime)/1e6, 3)), "s ",
util, "%: ")
- prev := tSweepTerm
- for i, ns := range []int64{tScan, tInstallWB, tMark, tMarkTerm, tEnd} {
+ prev := work.tSweepTerm
+ for i, ns := range []int64{tScan, tInstallWB, work.tMark, work.tMarkTerm, work.tEnd} {
if i != 0 {
print("+")
}
print(string(fmtNSAsMS(sbuf[:], uint64(ns))))
}
print(" ms cpu, ",
- heap0>>20, "->", heap1>>20, "->", heap2>>20, " MB, ",
- heapGoal>>20, " MB goal, ",
- maxprocs, " P")
- if mode != gcBackgroundMode {
+ work.heap0>>20, "->", work.heap1>>20, "->", work.heap2>>20, " MB, ",
+ work.heapGoal>>20, " MB goal, ",
+ work.maxprocs, " P")
+ if work.mode != gcBackgroundMode {
print(" (forced)")
}
print("\n")
// there are no workers.
work.nproc = ^uint32(0)
work.nwait = ^uint32(0)
-
- // Reset background mark completion points.
- work.bgMark1.done = 1
- work.bgMark2.done = 1
}
func gcBgMarkWorker(p *p) {
// Register this G as the background mark worker for p.
- if p.gcBgMarkWorker != nil {
- throw("P already has a background mark worker")
+ casgp := func(gpp **g, old, new *g) bool {
+ return casp((*unsafe.Pointer)(unsafe.Pointer(gpp)), unsafe.Pointer(old), unsafe.Pointer(new))
}
- gp := getg()
+ gp := getg()
mp := acquirem()
- p.gcBgMarkWorker = gp
+ owned := casgp(&p.gcBgMarkWorker, nil, gp)
// After this point, the background mark worker is scheduled
// cooperatively by gcController.findRunnable. Hence, it must
// never be preempted, as this would put it into _Grunnable
// is set, this puts itself into _Gwaiting to be woken up by
// gcController.findRunnable at the appropriate time.
notewakeup(&work.bgMarkReady)
+ if !owned {
+ // A sleeping worker came back and reassociated with
+ // the P. That's fine.
+ releasem(mp)
+ return
+ }
+
for {
// Go to sleep until woken by gcContoller.findRunnable.
// We can't releasem yet since even the call to gopark
gopark(func(g *g, mp unsafe.Pointer) bool {
releasem((*m)(mp))
return true
- }, unsafe.Pointer(mp), "mark worker (idle)", traceEvGoBlock, 0)
+ }, unsafe.Pointer(mp), "GC worker (idle)", traceEvGoBlock, 0)
// Loop until the P dies and disassociates this
// worker. (The P may later be reused, in which case
startTime := nanotime()
- decnwait := xadd(&work.nwait, -1)
+ decnwait := atomic.Xadd(&work.nwait, -1)
if decnwait == work.nproc {
println("runtime: work.nwait=", decnwait, "work.nproc=", work.nproc)
throw("work.nwait was > work.nproc")
}
- done := false
switch p.gcMarkWorkerMode {
default:
throw("gcBgMarkWorker: unexpected gcMarkWorkerMode")
case gcMarkWorkerDedicatedMode:
- gcDrain(&p.gcw, gcDrainBlock|gcDrainFlushBgCredit)
- // gcDrain did the xadd(&work.nwait +1) to
- // match the decrement above. It only returns
- // at a mark completion point.
- done = true
- if !p.gcw.empty() {
- throw("gcDrain returned with buffer")
- }
+ gcDrain(&p.gcw, gcDrainNoBlock|gcDrainFlushBgCredit)
case gcMarkWorkerFractionalMode, gcMarkWorkerIdleMode:
gcDrain(&p.gcw, gcDrainUntilPreempt|gcDrainFlushBgCredit)
-
- // If we are nearing the end of mark, dispose
- // of the cache promptly. We must do this
- // before signaling that we're no longer
- // working so that other workers can't observe
- // no workers and no work while we have this
- // cached, and before we compute done.
- if gcBlackenPromptly {
- p.gcw.dispose()
- }
-
- // Was this the last worker and did we run out
- // of work?
- incnwait := xadd(&work.nwait, +1)
- if incnwait > work.nproc {
- println("runtime: p.gcMarkWorkerMode=", p.gcMarkWorkerMode,
- "work.nwait=", incnwait, "work.nproc=", work.nproc)
- throw("work.nwait > work.nproc")
- }
- done = incnwait == work.nproc && work.full == 0
}
- // If this worker reached a background mark completion
- // point, signal the main GC goroutine.
- if done {
- if gcBlackenPromptly {
- if work.bgMark1.done == 0 {
- throw("completing mark 2, but bgMark1.done == 0")
- }
- work.bgMark2.complete()
- } else {
- work.bgMark1.complete()
- }
+ // If we are nearing the end of mark, dispose
+ // of the cache promptly. We must do this
+ // before signaling that we're no longer
+ // working so that other workers can't observe
+ // no workers and no work while we have this
+ // cached, and before we compute done.
+ if gcBlackenPromptly {
+ p.gcw.dispose()
}
+ // Account for time.
duration := nanotime() - startTime
switch p.gcMarkWorkerMode {
case gcMarkWorkerDedicatedMode:
- xaddint64(&gcController.dedicatedMarkTime, duration)
- xaddint64(&gcController.dedicatedMarkWorkersNeeded, 1)
+ atomic.Xaddint64(&gcController.dedicatedMarkTime, duration)
+ atomic.Xaddint64(&gcController.dedicatedMarkWorkersNeeded, 1)
case gcMarkWorkerFractionalMode:
- xaddint64(&gcController.fractionalMarkTime, duration)
- xaddint64(&gcController.fractionalMarkWorkersNeeded, 1)
+ atomic.Xaddint64(&gcController.fractionalMarkTime, duration)
+ atomic.Xaddint64(&gcController.fractionalMarkWorkersNeeded, 1)
case gcMarkWorkerIdleMode:
- xaddint64(&gcController.idleMarkTime, duration)
+ atomic.Xaddint64(&gcController.idleMarkTime, duration)
+ }
+
+ // Was this the last worker and did we run out
+ // of work?
+ incnwait := atomic.Xadd(&work.nwait, +1)
+ if incnwait > work.nproc {
+ println("runtime: p.gcMarkWorkerMode=", p.gcMarkWorkerMode,
+ "work.nwait=", incnwait, "work.nproc=", work.nproc)
+ throw("work.nwait > work.nproc")
+ }
+
+ // If this worker reached a background mark completion
+ // point, signal the main GC goroutine.
+ if incnwait == work.nproc && !gcMarkWorkAvailable(nil) {
+ // Make this G preemptible and disassociate it
+ // as the worker for this P so
+ // findRunnableGCWorker doesn't try to
+ // schedule it.
+ p.gcBgMarkWorker = nil
+ releasem(mp)
+
+ gcMarkDone()
+
+ // Disable preemption and reassociate with the P.
+ //
+ // We may be running on a different P at this
+ // point, so this has to be done carefully.
+ mp = acquirem()
+ if !casgp(&p.gcBgMarkWorker, nil, gp) {
+ // The P got a new worker.
+ releasem(mp)
+ break
+ }
}
}
}
// gcMarkWorkAvailable returns true if executing a mark worker
-// on p is potentially useful.
+// on p is potentially useful. p may be nil, in which case it only
+// checks the global sources of work.
func gcMarkWorkAvailable(p *p) bool {
- if !p.gcw.empty() {
+ if p != nil && !p.gcw.empty() {
return true
}
- if atomicload64(&work.full) != 0 {
+ if atomic.Load64(&work.full) != 0 {
return true // global work available
}
+ if work.markrootNext < work.markrootJobs {
+ return true // root scan work available
+ }
return false
}
// but must be disposed to the global lists immediately.
gcFlushGCWork()
+ // Queue root marking jobs.
+ gcMarkRootPrepare()
+
work.nwait = 0
work.ndone = 0
work.nproc = uint32(gcprocs())
traceGCScanStart()
}
- parforsetup(work.markfor, work.nproc, uint32(_RootCount+allglen), false, markroot)
if work.nproc > 1 {
noteclear(&work.alldone)
helpgc(int32(work.nproc))
}
gchelperstart()
- parfordo(work.markfor)
var gcw gcWork
gcDrain(&gcw, gcDrainBlock)
gcw.dispose()
+ gcMarkRootCheck()
if work.full != 0 {
throw("work.full != 0")
}
work.finalizersDone = true
for i := 0; i < int(gomaxprocs); i++ {
- if allp[i].gcw.wbuf != 0 {
+ if !allp[i].gcw.empty() {
throw("P has cached GC work at end of mark termination")
}
}
traceGCScanDone()
}
- // TODO(austin): This doesn't have to be done during STW, as
- // long as we block the next GC cycle until this is done. Move
- // it after we start the world, but before dropping worldsema.
- // (See issue #11465.)
- freeStackSpans()
-
cachestats()
// Compute the reachable heap size at the beginning of the
traceGCScanStart()
}
- // parallel mark for over GC roots
- parfordo(work.markfor)
- if gcphase != _GCscan {
+ // Parallel mark over GC roots and heap
+ if gcphase == _GCmarktermination {
var gcw gcWork
gcDrain(&gcw, gcDrainBlock) // blocks in getfull
gcw.dispose()
}
nproc := work.nproc // work.nproc can change right after we increment work.ndone
- if xadd(&work.ndone, +1) == nproc-1 {
+ if atomic.Xadd(&work.ndone, +1) == nproc-1 {
notewakeup(&work.alldone)
}
_g_.m.traceback = 0
package runtime
-import "unsafe"
+import (
+ "runtime/internal/atomic"
+ "runtime/internal/sys"
+ "unsafe"
+)
+
+const (
+ fixedRootFinalizers = iota
+ fixedRootFlushCaches
+ fixedRootCount
+
+ // rootBlockBytes is the number of bytes to scan per data or
+ // BSS root.
+ rootBlockBytes = 256 << 10
+
+ // rootBlockSpans is the number of spans to scan per span
+ // root.
+ rootBlockSpans = 8 * 1024 // 64MB worth of spans
+)
-// Scan all of the stacks, greying (or graying if in America) the referents
-// but not blackening them since the mark write barrier isn't installed.
+// gcMarkRootPrepare queues root scanning jobs (stacks, globals, and
+// some miscellany) and initializes scanning-related state.
+//
+// The caller must have call gcCopySpans().
+//
//go:nowritebarrier
-func gcscan_m() {
- _g_ := getg()
+func gcMarkRootPrepare() {
+ // Compute how many data and BSS root blocks there are.
+ nBlocks := func(bytes uintptr) int {
+ return int((bytes + rootBlockBytes - 1) / rootBlockBytes)
+ }
+
+ work.nDataRoots = 0
+ for datap := &firstmoduledata; datap != nil; datap = datap.next {
+ nDataRoots := nBlocks(datap.edata - datap.data)
+ if nDataRoots > work.nDataRoots {
+ work.nDataRoots = nDataRoots
+ }
+ }
- // Grab the g that called us and potentially allow rescheduling.
- // This allows it to be scanned like other goroutines.
- mastergp := _g_.m.curg
- casgstatus(mastergp, _Grunning, _Gwaiting)
- mastergp.waitreason = "garbage collection scan"
+ work.nBSSRoots = 0
+ for datap := &firstmoduledata; datap != nil; datap = datap.next {
+ nBSSRoots := nBlocks(datap.ebss - datap.bss)
+ if nBSSRoots > work.nBSSRoots {
+ work.nBSSRoots = nBSSRoots
+ }
+ }
- // Span sweeping has been done by finishsweep_m.
- // Long term we will want to make this goroutine runnable
- // by placing it onto a scanenqueue state and then calling
- // runtime·restartg(mastergp) to make it Grunnable.
- // At the bottom we will want to return this p back to the scheduler.
+ // Compute number of span roots.
+ work.nSpanRoots = (len(work.spans) + rootBlockSpans - 1) / rootBlockSpans
// Snapshot of allglen. During concurrent scan, we just need
// to be consistent about how many markroot jobs we create and
- // how many Gs we check. Gs may be created after this and
- // they'll be scanned during mark termination. During mark
- // termination, allglen isn't changing.
- local_allglen := int(atomicloaduintptr(&allglen))
+ // how many Gs we check. Gs may be created after this point,
+ // but it's okay that we ignore them because they begin life
+ // without any roots, so there's nothing to scan, and any
+ // roots they create during the concurrent phase will be
+ // scanned during mark termination. During mark termination,
+ // allglen isn't changing, so we'll scan all Gs.
+ work.nStackRoots = int(atomic.Loaduintptr(&allglen))
+
+ work.markrootNext = 0
+ work.markrootJobs = uint32(fixedRootCount + work.nDataRoots + work.nBSSRoots + work.nSpanRoots + work.nStackRoots)
+}
- work.ndone = 0
- useOneP := uint32(1) // For now do not do this in parallel.
- // ackgcphase is not needed since we are not scanning running goroutines.
- parforsetup(work.markfor, useOneP, uint32(_RootCount+local_allglen), false, markroot)
- parfordo(work.markfor)
+// gcMarkRootCheck checks that all roots have been scanned. It is
+// purely for debugging.
+func gcMarkRootCheck() {
+ if work.markrootNext < work.markrootJobs {
+ print(work.markrootNext, " of ", work.markrootJobs, " markroot jobs done\n")
+ throw("left over markroot jobs")
+ }
lock(&allglock)
// Check that gc work is done.
- for i := 0; i < local_allglen; i++ {
+ for i := 0; i < work.nStackRoots; i++ {
gp := allgs[i]
if !gp.gcscandone {
throw("scan missed a g")
}
}
unlock(&allglock)
-
- casgstatus(mastergp, _Gwaiting, _Grunning)
- // Let the g that called us continue to run.
}
// ptrmask for an allocation containing a single pointer.
var oneptrmask = [...]uint8{1}
+// markroot scans the i'th root.
+//
+// Preemption must be disabled (because this uses a gcWork).
+//
//go:nowritebarrier
-func markroot(desc *parfor, i uint32) {
+func markroot(i uint32) {
// TODO: Consider using getg().m.p.ptr().gcw.
var gcw gcWork
+ baseData := uint32(fixedRootCount)
+ baseBSS := baseData + uint32(work.nDataRoots)
+ baseSpans := baseBSS + uint32(work.nBSSRoots)
+ baseStacks := baseSpans + uint32(work.nSpanRoots)
+
// Note: if you add a case here, please also update heapdump.go:dumproots.
- switch i {
- case _RootData:
+ switch {
+ case baseData <= i && i < baseBSS:
for datap := &firstmoduledata; datap != nil; datap = datap.next {
- scanblock(datap.data, datap.edata-datap.data, datap.gcdatamask.bytedata, &gcw)
+ markrootBlock(datap.data, datap.edata-datap.data, datap.gcdatamask.bytedata, &gcw, int(i-baseData))
}
- case _RootBss:
+ case baseBSS <= i && i < baseSpans:
for datap := &firstmoduledata; datap != nil; datap = datap.next {
- scanblock(datap.bss, datap.ebss-datap.bss, datap.gcbssmask.bytedata, &gcw)
+ markrootBlock(datap.bss, datap.ebss-datap.bss, datap.gcbssmask.bytedata, &gcw, int(i-baseBSS))
}
- case _RootFinalizers:
+ case i == fixedRootFinalizers:
for fb := allfin; fb != nil; fb = fb.alllink {
scanblock(uintptr(unsafe.Pointer(&fb.fin[0])), uintptr(fb.cnt)*unsafe.Sizeof(fb.fin[0]), &finptrmask[0], &gcw)
}
- case _RootFlushCaches:
- if gcphase != _GCscan { // Do not flush mcaches during GCscan phase.
+ case i == fixedRootFlushCaches:
+ if gcphase == _GCmarktermination { // Do not flush mcaches during concurrent phase.
flushallmcaches()
}
- default:
- if _RootSpans0 <= i && i < _RootSpans0+_RootSpansShards {
- // mark MSpan.specials
- markrootSpans(&gcw, int(i)-_RootSpans0)
- break
- }
+ case baseSpans <= i && i < baseStacks:
+ // mark MSpan.specials
+ markrootSpans(&gcw, int(i-baseSpans))
+ default:
// the rest is scanning goroutine stacks
- if uintptr(i-_RootCount) >= allglen {
+ if uintptr(i-baseStacks) >= allglen {
throw("markroot: bad index")
}
- gp := allgs[i-_RootCount]
+ gp := allgs[i-baseStacks]
// remember when we've first observed the G blocked
// needed only to output in traceback
shrinkstack(gp)
}
- scang(gp)
+ if gcphase != _GCmarktermination && gp.startpc == gcBgMarkWorkerPC {
+ // GC background workers may be
+ // non-preemptible, so we may deadlock if we
+ // try to scan them during a concurrent phase.
+ // They also have tiny stacks, so just ignore
+ // them until mark termination.
+ gp.gcscandone = true
+ break
+ }
+
+ // scang must be done on the system stack in case
+ // we're trying to scan our own stack.
+ systemstack(func() {
+ // If this is a self-scan, put the user G in
+ // _Gwaiting to prevent self-deadlock. It may
+ // already be in _Gwaiting if this is mark
+ // termination.
+ userG := getg().m.curg
+ selfScan := gp == userG && readgstatus(userG) == _Grunning
+ if selfScan {
+ casgstatus(userG, _Grunning, _Gwaiting)
+ userG.waitreason = "garbage collection scan"
+ }
+
+ // TODO: scang blocks until gp's stack has
+ // been scanned, which may take a while for
+ // running goroutines. Consider doing this in
+ // two phases where the first is non-blocking:
+ // we scan the stacks we can and ask running
+ // goroutines to scan themselves; and the
+ // second blocks.
+ scang(gp)
+
+ if selfScan {
+ casgstatus(userG, _Gwaiting, _Grunning)
+ }
+ })
}
gcw.dispose()
}
-// markrootSpans marks roots for one shard (out of _RootSpansShards)
-// of work.spans.
+// markrootBlock scans the shard'th shard of the block of memory [b0,
+// b0+n0), with the given pointer mask.
+//
+//go:nowritebarrier
+func markrootBlock(b0, n0 uintptr, ptrmask0 *uint8, gcw *gcWork, shard int) {
+ if rootBlockBytes%(8*sys.PtrSize) != 0 {
+ // This is necessary to pick byte offsets in ptrmask0.
+ throw("rootBlockBytes must be a multiple of 8*ptrSize")
+ }
+
+ b := b0 + uintptr(shard)*rootBlockBytes
+ if b >= b0+n0 {
+ return
+ }
+ ptrmask := (*uint8)(add(unsafe.Pointer(ptrmask0), uintptr(shard)*(rootBlockBytes/(8*sys.PtrSize))))
+ n := uintptr(rootBlockBytes)
+ if b+n > b0+n0 {
+ n = b0 + n0 - b
+ }
+
+ // Scan this shard.
+ scanblock(b, n, ptrmask, gcw)
+}
+
+// markrootSpans marks roots for one shard of work.spans.
//
//go:nowritebarrier
func markrootSpans(gcw *gcWork, shard int) {
}
sg := mheap_.sweepgen
- startSpan := shard * len(work.spans) / _RootSpansShards
- endSpan := (shard + 1) * len(work.spans) / _RootSpansShards
+ startSpan := shard * rootBlockSpans
+ endSpan := (shard + 1) * rootBlockSpans
+ if endSpan > len(work.spans) {
+ endSpan = len(work.spans)
+ }
// Note that work.spans may not include spans that were
// allocated between entering the scan phase and now. This is
// okay because any objects with finalizers in those spans
scanobject(p, gcw)
// The special itself is a root.
- scanblock(uintptr(unsafe.Pointer(&spf.fn)), ptrSize, &oneptrmask[0], gcw)
+ scanblock(uintptr(unsafe.Pointer(&spf.fn)), sys.PtrSize, &oneptrmask[0], gcw)
}
unlock(&s.speciallock)
// will just cause steals to fail until credit is accumulated
// again, so in the long run it doesn't really matter, but we
// do have to handle the negative credit case.
- bgScanCredit := atomicloadint64(&gcController.bgScanCredit)
+ bgScanCredit := atomic.Loadint64(&gcController.bgScanCredit)
stolen := int64(0)
if bgScanCredit > 0 {
if bgScanCredit < scanWork {
stolen = scanWork
gp.gcAssistBytes += debtBytes
}
- xaddint64(&gcController.bgScanCredit, -stolen)
+ atomic.Xaddint64(&gcController.bgScanCredit, -stolen)
scanWork -= stolen
// Perform assist work
completed := false
systemstack(func() {
- if atomicload(&gcBlackenEnabled) == 0 {
+ if atomic.Load(&gcBlackenEnabled) == 0 {
// The gcBlackenEnabled check in malloc races with the
// store that clears it but an atomic check in every malloc
// would be a performance hit.
// stack to determine if we should preform an assist.
// GC is done, so ignore any remaining debt.
- scanWork = 0
+ gp.gcAssistBytes = 0
return
}
// Track time spent in this assist. Since we're on the
// just measure start and end time.
startTime := nanotime()
- decnwait := xadd(&work.nwait, -1)
+ decnwait := atomic.Xadd(&work.nwait, -1)
if decnwait == work.nproc {
println("runtime: work.nwait =", decnwait, "work.nproc=", work.nproc)
throw("nwait > work.nprocs")
}
// Record that we did this much scan work.
- scanWork -= workDone
+ //
// Back out the number of bytes of assist credit that
// this scan work counts for. The "1+" is a poor man's
// round-up, to ensure this adds credit even if
// If this is the last worker and we ran out of work,
// signal a completion point.
- incnwait := xadd(&work.nwait, +1)
+ incnwait := atomic.Xadd(&work.nwait, +1)
if incnwait > work.nproc {
println("runtime: work.nwait=", incnwait,
"work.nproc=", work.nproc,
throw("work.nwait > work.nproc")
}
- if incnwait == work.nproc && work.full == 0 {
+ if incnwait == work.nproc && !gcMarkWorkAvailable(nil) {
// This has reached a background completion
// point.
- if gcBlackenPromptly {
- if work.bgMark1.done == 0 {
- throw("completing mark 2, but bgMark1.done == 0")
- }
- work.bgMark2.complete()
- } else {
- work.bgMark1.complete()
- }
completed = true
}
duration := nanotime() - startTime
_p_ := gp.m.p.ptr()
_p_.gcAssistTime += duration
if _p_.gcAssistTime > gcAssistTimeSlack {
- xaddint64(&gcController.assistTime, _p_.gcAssistTime)
+ atomic.Xaddint64(&gcController.assistTime, _p_.gcAssistTime)
_p_.gcAssistTime = 0
}
})
if completed {
- // We called complete() above, so we should yield to
- // the now-runnable GC coordinator.
- Gosched()
-
- // It's likely that this assist wasn't able to pay off
- // its debt, but it's also likely that the Gosched let
- // the GC finish this cycle and there's no point in
- // waiting. If the GC finished, skip the delay below.
- if atomicload(&gcBlackenEnabled) == 0 {
- scanWork = 0
- }
+ gcMarkDone()
}
- if scanWork > 0 {
+ if gp.gcAssistBytes < 0 {
// We were unable steal enough credit or perform
// enough work to pay off the assist debt. We need to
// do one of these before letting the mutator allocate
- // more, so go around again after performing an
- // interruptible sleep for 100 us (the same as the
- // getfull barrier) to let other mutators run.
+ // more to prevent over-allocation.
+ //
+ // If this is because we were preempted, reschedule
+ // and try some more.
+ if gp.preempt {
+ Gosched()
+ goto retry
+ }
+
+ // Add this G to an assist queue and park. When the GC
+ // has more background credit, it will satisfy queued
+ // assists before flushing to the global credit pool.
+ //
+ // Note that this does *not* get woken up when more
+ // work is added to the work list. The theory is that
+ // there wasn't enough work to do anyway, so we might
+ // as well let background marking take care of the
+ // work that is available.
+ lock(&work.assistQueue.lock)
+
+ // If the GC cycle is over, just return. This is the
+ // likely path if we completed above. We do this
+ // under the lock to prevent a GC cycle from ending
+ // between this check and queuing the assist.
+ if atomic.Load(&gcBlackenEnabled) == 0 {
+ unlock(&work.assistQueue.lock)
+ return
+ }
+
+ oldHead, oldTail := work.assistQueue.head, work.assistQueue.tail
+ if oldHead == 0 {
+ work.assistQueue.head.set(gp)
+ } else {
+ oldTail.ptr().schedlink.set(gp)
+ }
+ work.assistQueue.tail.set(gp)
+ gp.schedlink.set(nil)
+ // Recheck for background credit now that this G is in
+ // the queue, but can still back out. This avoids a
+ // race in case background marking has flushed more
+ // credit since we checked above.
+ if atomic.Loadint64(&gcController.bgScanCredit) > 0 {
+ work.assistQueue.head = oldHead
+ work.assistQueue.tail = oldTail
+ if oldTail != 0 {
+ oldTail.ptr().schedlink.set(nil)
+ }
+ unlock(&work.assistQueue.lock)
+ goto retry
+ }
+ // Park for real.
+ goparkunlock(&work.assistQueue.lock, "GC assist wait", traceEvGoBlock, 2)
+
+ // At this point either background GC has satisfied
+ // this G's assist debt, or the GC cycle is over.
+ }
+}
+
+// gcWakeAllAssists wakes all currently blocked assists. This is used
+// at the end of a GC cycle.
+func gcWakeAllAssists() {
+ lock(&work.assistQueue.lock)
+ injectglist(work.assistQueue.head.ptr())
+ work.assistQueue.head.set(nil)
+ work.assistQueue.tail.set(nil)
+ unlock(&work.assistQueue.lock)
+}
+
+// gcFlushBgCredit flushes scanWork units of background scan work
+// credit. This first satisfies blocked assists on the
+// work.assistQueue and then flushes any remaining credit to
+// gcController.bgScanCredit.
+func gcFlushBgCredit(scanWork int64) {
+ if work.assistQueue.head == 0 {
+ // Fast path; there are no blocked assists. There's a
+ // small window here where an assist may add itself to
+ // the blocked queue and park. If that happens, we'll
+ // just get it on the next flush.
+ atomic.Xaddint64(&gcController.bgScanCredit, scanWork)
+ return
+ }
+
+ scanBytes := int64(float64(scanWork) * gcController.assistBytesPerWork)
+
+ lock(&work.assistQueue.lock)
+ gp := work.assistQueue.head.ptr()
+ for gp != nil && scanBytes > 0 {
+ // Note that gp.gcAssistBytes is negative because gp
+ // is in debt. Think carefully about the signs below.
+ if scanBytes+gp.gcAssistBytes >= 0 {
+ // Satisfy this entire assist debt.
+ scanBytes += gp.gcAssistBytes
+ gp.gcAssistBytes = 0
+ xgp := gp
+ gp = gp.schedlink.ptr()
+ ready(xgp, 0)
+ } else {
+ // Partially satisfy this assist.
+ gp.gcAssistBytes += scanBytes
+ scanBytes = 0
+ // As a heuristic, we move this assist to the
+ // back of the queue so that large assists
+ // can't clog up the assist queue and
+ // substantially delay small assists.
+ xgp := gp
+ gp = gp.schedlink.ptr()
+ if gp == nil {
+ // gp is the only assist in the queue.
+ gp = xgp
+ } else {
+ xgp.schedlink = 0
+ work.assistQueue.tail.ptr().schedlink.set(xgp)
+ work.assistQueue.tail.set(xgp)
+ }
+ break
+ }
+ }
+ work.assistQueue.head.set(gp)
+ if gp == nil {
+ work.assistQueue.tail.set(nil)
+ }
- // timeSleep may allocate, so avoid recursive assist.
- gcAssistBytes := gp.gcAssistBytes
- gp.gcAssistBytes = int64(^uint64(0) >> 1)
- timeSleep(100 * 1000)
- gp.gcAssistBytes = gcAssistBytes
- goto retry
+ if scanBytes > 0 {
+ // Convert from scan bytes back to work.
+ scanWork = int64(float64(scanBytes) * gcController.assistWorkPerByte)
+ atomic.Xaddint64(&gcController.bgScanCredit, scanWork)
}
+ unlock(&work.assistQueue.lock)
}
//go:nowritebarrier
sp = gp.sched.sp
}
switch gcphase {
- case _GCscan:
+ case _GCmark:
// Install stack barriers during stack scan.
barrierOffset = uintptr(firstStackBarrierOffset)
nextBarrier = sp + barrierOffset
} else {
// Only re-scan up to the lowest un-hit
// barrier. Any frames above this have not
- // executed since the _GCscan scan of gp and
+ // executed since the concurrent scan of gp and
// any writes through up-pointers to above
// this barrier had write barriers.
nextBarrier = gp.stkbar[gp.stkbarPos].savedLRPtr
throw("scanstack in wrong phase")
}
+ var cache pcvalueCache
gcw := &getg().m.p.ptr().gcw
n := 0
scanframe := func(frame *stkframe, unused unsafe.Pointer) bool {
- scanframeworker(frame, unused, gcw)
+ scanframeworker(frame, &cache, gcw)
if frame.fp > nextBarrier {
// We skip installing a barrier on bottom-most
// frame because on LR machines this LR is not
// on the stack.
- if gcphase == _GCscan && n != 0 {
+ if gcphase == _GCmark && n != 0 {
if gcInstallStackBarrier(gp, frame) {
barrierOffset *= 2
nextBarrier = sp + barrierOffset
// Scan a stack frame: local variables and function arguments/results.
//go:nowritebarrier
-func scanframeworker(frame *stkframe, unused unsafe.Pointer, gcw *gcWork) {
+func scanframeworker(frame *stkframe, cache *pcvalueCache, gcw *gcWork) {
f := frame.fn
targetpc := frame.continpc
if targetpc != f.entry {
targetpc--
}
- pcdata := pcdatavalue(f, _PCDATA_StackMapIndex, targetpc)
+ pcdata := pcdatavalue(f, _PCDATA_StackMapIndex, targetpc, cache)
if pcdata == -1 {
// We do not have a valid pcdata value but there might be a
// stackmap for this function. It is likely that we are looking
// Scan local variables if stack frame has been allocated.
size := frame.varp - frame.sp
var minsize uintptr
- switch thechar {
+ switch sys.TheChar {
case '7':
- minsize = spAlign
+ minsize = sys.SpAlign
default:
- minsize = minFrameSize
+ minsize = sys.MinFrameSize
}
if size > minsize {
stkmap := (*stackmap)(funcdata(f, _FUNCDATA_LocalsPointerMaps))
throw("scanframe: bad symbol table")
}
bv := stackmapdata(stkmap, pcdata)
- size = uintptr(bv.n) * ptrSize
+ size = uintptr(bv.n) * sys.PtrSize
scanblock(frame.varp-size, size, bv.bytedata, gcw)
}
}
bv = stackmapdata(stkmap, pcdata)
}
- scanblock(frame.argp, uintptr(bv.n)*ptrSize, bv.bytedata, gcw)
+ scanblock(frame.argp, uintptr(bv.n)*sys.PtrSize, bv.bytedata, gcw)
}
}
const (
gcDrainUntilPreempt gcDrainFlags = 1 << iota
+ gcDrainNoBlock
gcDrainFlushBgCredit
- // gcDrainBlock is the opposite of gcDrainUntilPreempt. This
- // is the default, but callers should use the constant for
- // documentation purposes.
+ // gcDrainBlock means neither gcDrainUntilPreempt or
+ // gcDrainNoBlock. It is the default, but callers should use
+ // the constant for documentation purposes.
gcDrainBlock gcDrainFlags = 0
)
-// gcDrain scans objects in work buffers, blackening grey objects
-// until all work buffers have been drained.
+// gcDrain scans roots and objects in work buffers, blackening grey
+// objects until all roots and work buffers have been drained.
+//
+// If flags&gcDrainUntilPreempt != 0, gcDrain returns when g.preempt
+// is set. This implies gcDrainNoBlock.
//
-// If flags&gcDrainUntilPreempt != 0, gcDrain also returns if
-// g.preempt is set. Otherwise, this will block until all dedicated
-// workers are blocked in gcDrain.
+// If flags&gcDrainNoBlock != 0, gcDrain returns as soon as it is
+// unable to get more work. Otherwise, it will block until all
+// blocking calls are blocked in gcDrain.
//
// If flags&gcDrainFlushBgCredit != 0, gcDrain flushes scan work
// credit to gcController.bgScanCredit every gcCreditSlack units of
// scan work.
+//
//go:nowritebarrier
func gcDrain(gcw *gcWork, flags gcDrainFlags) {
- if !writeBarrierEnabled {
+ if !writeBarrier.needed {
throw("gcDrain phase incorrect")
}
- blocking := flags&gcDrainUntilPreempt == 0
+ gp := getg()
+ preemtible := flags&gcDrainUntilPreempt != 0
+ blocking := flags&(gcDrainUntilPreempt|gcDrainNoBlock) == 0
flushBgCredit := flags&gcDrainFlushBgCredit != 0
+ // Drain root marking jobs.
+ if work.markrootNext < work.markrootJobs {
+ for blocking || !gp.preempt {
+ job := atomic.Xadd(&work.markrootNext, +1) - 1
+ if job >= work.markrootJobs {
+ break
+ }
+ // TODO: Pass in gcw.
+ markroot(job)
+ }
+ }
+
initScanWork := gcw.scanWork
- gp := getg()
- for blocking || !gp.preempt {
+ // Drain heap marking jobs.
+ for !(preemtible && gp.preempt) {
// If another proc wants a pointer, give it some.
if work.nwait > 0 && work.full == 0 {
gcw.balance()
// account if we've accumulated enough locally so
// mutator assists can draw on it.
if gcw.scanWork >= gcCreditSlack {
- xaddint64(&gcController.scanWork, gcw.scanWork)
+ atomic.Xaddint64(&gcController.scanWork, gcw.scanWork)
if flushBgCredit {
- xaddint64(&gcController.bgScanCredit, gcw.scanWork-initScanWork)
+ gcFlushBgCredit(gcw.scanWork - initScanWork)
initScanWork = 0
}
gcw.scanWork = 0
// Flush remaining scan work credit.
if gcw.scanWork > 0 {
- xaddint64(&gcController.scanWork, gcw.scanWork)
+ atomic.Xaddint64(&gcController.scanWork, gcw.scanWork)
if flushBgCredit {
- xaddint64(&gcController.bgScanCredit, gcw.scanWork-initScanWork)
+ gcFlushBgCredit(gcw.scanWork - initScanWork)
}
gcw.scanWork = 0
}
}
// gcDrainN blackens grey objects until it has performed roughly
-// scanWork units of scan work. This is best-effort, so it may perform
-// less work if it fails to get a work buffer. Otherwise, it will
-// perform at least n units of work, but may perform more because
-// scanning is always done in whole object increments. It returns the
-// amount of scan work performed.
+// scanWork units of scan work or the G is preempted. This is
+// best-effort, so it may perform less work if it fails to get a work
+// buffer. Otherwise, it will perform at least n units of work, but
+// may perform more because scanning is always done in whole object
+// increments. It returns the amount of scan work performed.
//go:nowritebarrier
func gcDrainN(gcw *gcWork, scanWork int64) int64 {
- if !writeBarrierEnabled {
+ if !writeBarrier.needed {
throw("gcDrainN phase incorrect")
}
// want to claim was done by this call.
workFlushed := -gcw.scanWork
- for workFlushed+gcw.scanWork < scanWork {
+ gp := getg().m.curg
+ for !gp.preempt && workFlushed+gcw.scanWork < scanWork {
// This might be a good place to add prefetch code...
// if(wbuf.nobj > 4) {
// PREFETCH(wbuf->obj[wbuf.nobj - 3];
// Flush background scan work credit.
if gcw.scanWork >= gcCreditSlack {
- xaddint64(&gcController.scanWork, gcw.scanWork)
+ atomic.Xaddint64(&gcController.scanWork, gcw.scanWork)
workFlushed += gcw.scanWork
gcw.scanWork = 0
}
for i := uintptr(0); i < n; {
// Find bits for the next word.
- bits := uint32(*addb(ptrmask, i/(ptrSize*8)))
+ bits := uint32(*addb(ptrmask, i/(sys.PtrSize*8)))
if bits == 0 {
- i += ptrSize * 8
+ i += sys.PtrSize * 8
continue
}
for j := 0; j < 8 && i < n; j++ {
}
}
bits >>= 1
- i += ptrSize
+ i += sys.PtrSize
}
}
}
}
var i uintptr
- for i = 0; i < n; i += ptrSize {
+ for i = 0; i < n; i += sys.PtrSize {
// Find bits for this word.
if i != 0 {
// Avoid needless hbits.next() on last iteration.
// are pointers, or else they'd be merged with other non-pointer
// data into larger allocations.
bits := hbits.bits()
- if i >= 2*ptrSize && bits&bitMarked == 0 {
+ if i >= 2*sys.PtrSize && bits&bitMarked == 0 {
break // no more pointers in this object
}
if bits&bitPointer == 0 {
//go:nowritebarrier
func greyobject(obj, base, off uintptr, hbits heapBits, span *mspan, gcw *gcWork) {
// obj should be start of allocation, and so must be at least pointer-aligned.
- if obj&(ptrSize-1) != 0 {
+ if obj&(sys.PtrSize-1) != 0 {
throw("greyobject: obj not pointer-aligned")
}
}
print(" s.start*_PageSize=", hex(s.start*_PageSize), " s.limit=", hex(s.limit), " s.sizeclass=", s.sizeclass, " s.elemsize=", s.elemsize, "\n")
skipped := false
- for i := uintptr(0); i < s.elemsize; i += ptrSize {
+ for i := uintptr(0); i < s.elemsize; i += sys.PtrSize {
// For big objects, just print the beginning (because
// that usually hints at the object's type) and the
// fields around off.
- if !(i < 128*ptrSize || off-16*ptrSize < i && i < off+16*ptrSize) {
+ if !(i < 128*sys.PtrSize || off-16*sys.PtrSize < i && i < off+16*sys.PtrSize) {
skipped = true
continue
}
throw("gcmarknewobject called while doing checkmark")
}
heapBitsForAddr(obj).setMarked()
- xadd64(&work.bytesMarked, int64(size))
+ atomic.Xadd64(&work.bytesMarked, int64(size))
}
// Checkmarking
package runtime
-import "unsafe"
+import (
+ "runtime/internal/atomic"
+ "runtime/internal/sys"
+ "unsafe"
+)
var sweep sweepdata
sg := mheap_.sweepgen
for _, s := range work.spans {
if s.sweepgen != sg && s.state == _MSpanInUse {
- mSpan_EnsureSwept(s)
+ s.ensureSwept()
}
}
}
_g_.m.locks++
sg := mheap_.sweepgen
for {
- idx := xadd(&sweep.spanidx, 1) - 1
+ idx := atomic.Xadd(&sweep.spanidx, 1) - 1
if idx >= uint32(len(work.spans)) {
mheap_.sweepdone = 1
_g_.m.locks--
s.sweepgen = sg
continue
}
- if s.sweepgen != sg-2 || !cas(&s.sweepgen, sg-2, sg-1) {
+ if s.sweepgen != sg-2 || !atomic.Cas(&s.sweepgen, sg-2, sg-1) {
continue
}
npages := s.npages
- if !mSpan_Sweep(s, false) {
+ if !s.sweep(false) {
npages = 0
}
_g_.m.locks--
// Returns only when span s has been swept.
//go:nowritebarrier
-func mSpan_EnsureSwept(s *mspan) {
+func (s *mspan) ensureSwept() {
// Caller must disable preemption.
// Otherwise when this function returns the span can become unswept again
// (if GC is triggered on another goroutine).
}
sg := mheap_.sweepgen
- if atomicload(&s.sweepgen) == sg {
+ if atomic.Load(&s.sweepgen) == sg {
return
}
// The caller must be sure that the span is a MSpanInUse span.
- if cas(&s.sweepgen, sg-2, sg-1) {
- mSpan_Sweep(s, false)
+ if atomic.Cas(&s.sweepgen, sg-2, sg-1) {
+ s.sweep(false)
return
}
// unfortunate condition, and we don't have efficient means to wait
- for atomicload(&s.sweepgen) != sg {
+ for atomic.Load(&s.sweepgen) != sg {
osyield()
}
}
// If preserve=true, don't return it to heap nor relink in MCentral lists;
// caller takes care of it.
//TODO go:nowritebarrier
-func mSpan_Sweep(s *mspan, preserve bool) bool {
+func (s *mspan) sweep(preserve bool) bool {
// It's critical that we enter this function with preemption disabled,
// GC must not start while we are in the middle of this function.
_g_ := getg()
traceGCSweepStart()
}
- xadd64(&mheap_.pagesSwept, int64(s.npages))
+ atomic.Xadd64(&mheap_.pagesSwept, int64(s.npages))
cl := s.sizeclass
size := s.elemsize
}
// Unlink & free special records for any objects we're about to free.
+ // Two complications here:
+ // 1. An object can have both finalizer and profile special records.
+ // In such case we need to queue finalizer for execution,
+ // mark the object as live and preserve the profile special.
+ // 2. A tiny object can have several finalizers setup for different offsets.
+ // If such object is not marked, we need to queue all finalizers at once.
+ // Both 1 and 2 are possible at the same time.
specialp := &s.specials
special := *specialp
for special != nil {
p := uintptr(s.start<<_PageShift) + uintptr(special.offset)/size*size
hbits := heapBitsForAddr(p)
if !hbits.isMarked() {
- // Find the exact byte for which the special was setup
- // (as opposed to object beginning).
- p := uintptr(s.start<<_PageShift) + uintptr(special.offset)
- // about to free object: splice out special record
- y := special
- special = special.next
- *specialp = special
- if !freespecial(y, unsafe.Pointer(p), size, false) {
- // stop freeing of object if it has a finalizer
- hbits.setMarkedNonAtomic()
+ // This object is not marked and has at least one special record.
+ // Pass 1: see if it has at least one finalizer.
+ hasFin := false
+ endOffset := p - uintptr(s.start<<_PageShift) + size
+ for tmp := special; tmp != nil && uintptr(tmp.offset) < endOffset; tmp = tmp.next {
+ if tmp.kind == _KindSpecialFinalizer {
+ // Stop freeing of object if it has a finalizer.
+ hbits.setMarkedNonAtomic()
+ hasFin = true
+ break
+ }
+ }
+ // Pass 2: queue all finalizers _or_ handle profile record.
+ for special != nil && uintptr(special.offset) < endOffset {
+ // Find the exact byte for which the special was setup
+ // (as opposed to object beginning).
+ p := uintptr(s.start<<_PageShift) + uintptr(special.offset)
+ if special.kind == _KindSpecialFinalizer || !hasFin {
+ // Splice out special record.
+ y := special
+ special = special.next
+ *specialp = special
+ freespecial(y, unsafe.Pointer(p), size)
+ } else {
+ // This is profile record, but the object has finalizers (so kept alive).
+ // Keep special record.
+ specialp = &special.next
+ special = *specialp
+ }
}
} else {
// object is still live: keep special record
if debug.allocfreetrace != 0 {
tracefree(unsafe.Pointer(p), size)
}
+ if msanenabled {
+ msanfree(unsafe.Pointer(p), size)
+ }
// Reset to allocated+noscan.
if cl == 0 {
freeToHeap = true
} else {
// Free small object.
- if size > 2*ptrSize {
- *(*uintptr)(unsafe.Pointer(p + ptrSize)) = uintptrMask & 0xdeaddeaddeaddead // mark as "needs to be zeroed"
- } else if size > ptrSize {
- *(*uintptr)(unsafe.Pointer(p + ptrSize)) = 0
+ if size > 2*sys.PtrSize {
+ *(*uintptr)(unsafe.Pointer(p + sys.PtrSize)) = uintptrMask & 0xdeaddeaddeaddead // mark as "needs to be zeroed"
+ } else if size > sys.PtrSize {
+ *(*uintptr)(unsafe.Pointer(p + sys.PtrSize)) = 0
}
if head.ptr() == nil {
head = gclinkptr(p)
print("MSpan_Sweep: state=", s.state, " sweepgen=", s.sweepgen, " mheap.sweepgen=", sweepgen, "\n")
throw("MSpan_Sweep: bad span state after sweep")
}
- atomicstore(&s.sweepgen, sweepgen)
+ atomic.Store(&s.sweepgen, sweepgen)
}
if nfree > 0 {
c.local_nsmallfree[cl] += uintptr(nfree)
- res = mCentral_FreeSpan(&mheap_.central[cl].mcentral, s, int32(nfree), head, end, preserve)
+ res = mheap_.central[cl].mcentral.freeSpan(s, int32(nfree), head, end, preserve)
// MCentral_FreeSpan updates sweepgen
} else if freeToHeap {
// Free large span to heap
s.limit = 0 // prevent mlookup from finding this span
sysFault(unsafe.Pointer(uintptr(s.start<<_PageShift)), size)
} else {
- mHeap_Free(&mheap_, s, 1)
+ mheap_.freeSpan(s, 1)
}
c.local_nlargefree++
c.local_largefree += size
// also sweep pages (e.g., for a large allocation), it can pass a
// non-zero callerSweepPages to leave that many pages unswept.
//
+// deductSweepCredit makes a worst-case assumption that all spanBytes
+// bytes of the ultimately allocated span will be available for object
+// allocation. The caller should call reimburseSweepCredit if that
+// turns out not to be the case once the span is allocated.
+//
// deductSweepCredit is the core of the "proportional sweep" system.
// It uses statistics gathered by the garbage collector to perform
// enough sweeping so that all pages are swept during the concurrent
}
// Account for this span allocation.
- spanBytesAlloc := xadd64(&mheap_.spanBytesAlloc, int64(spanBytes))
+ spanBytesAlloc := atomic.Xadd64(&mheap_.spanBytesAlloc, int64(spanBytes))
// Fix debt if necessary.
pagesOwed := int64(mheap_.sweepPagesPerByte * float64(spanBytesAlloc))
- for pagesOwed-int64(atomicload64(&mheap_.pagesSwept)) > int64(callerSweepPages) {
+ for pagesOwed-int64(atomic.Load64(&mheap_.pagesSwept)) > int64(callerSweepPages) {
if gosweepone() == ^uintptr(0) {
mheap_.sweepPagesPerByte = 0
break
}
}
+// reimburseSweepCredit records that unusableBytes bytes of a
+// just-allocated span are not available for object allocation. This
+// offsets the worst-case charge performed by deductSweepCredit.
+func reimburseSweepCredit(unusableBytes uintptr) {
+ if mheap_.sweepPagesPerByte == 0 {
+ // Nobody cares about the credit. Avoid the atomic.
+ return
+ }
+ atomic.Xadd64(&mheap_.spanBytesAlloc, -int64(unusableBytes))
+}
+
func dumpFreeList(s *mspan) {
printlock()
print("runtime: free list of span ", s, ":\n")
package runtime
-import "unsafe"
+import (
+ "runtime/internal/atomic"
+ "runtime/internal/sys"
+ "unsafe"
+)
const (
- _Debugwbufs = false // if true check wbufs consistency
- _WorkbufSize = 1 * 256 // in bytes - if small wbufs are passed to GC in a timely fashion.
+ _Debugwbufs = false // if true check wbufs consistency
+ _WorkbufSize = 2048 // in bytes; larger values result in less contention
)
// Garbage collector work pool abstraction.
// gcWork may locally hold GC work buffers. This can be done by
// disabling preemption (systemstack or acquirem).
type gcWork struct {
- // Invariant: wbuf is never full or empty
- wbuf wbufptr
+ // wbuf1 and wbuf2 are the primary and secondary work buffers.
+ //
+ // This can be thought of as a stack of both work buffers'
+ // pointers concatenated. When we pop the last pointer, we
+ // shift the stack up by one work buffer by bringing in a new
+ // full buffer and discarding an empty one. When we fill both
+ // buffers, we shift the stack down by one work buffer by
+ // bringing in a new empty buffer and discarding a full one.
+ // This way we have one buffer's worth of hysteresis, which
+ // amortizes the cost of getting or putting a work buffer over
+ // at least one buffer of work and reduces contention on the
+ // global work lists.
+ //
+ // wbuf1 is always the buffer we're currently pushing to and
+ // popping from and wbuf2 is the buffer that will be discarded
+ // next.
+ //
+ // Invariant: Both wbuf1 and wbuf2 are nil or neither are.
+ wbuf1, wbuf2 wbufptr
// Bytes marked (blackened) on this gcWork. This is aggregated
// into work.bytesMarked by dispose.
scanWork int64
}
+func (w *gcWork) init() {
+ w.wbuf1 = wbufptrOf(getempty(101))
+ wbuf2 := trygetfull(102)
+ if wbuf2 == nil {
+ wbuf2 = getempty(103)
+ }
+ w.wbuf2 = wbufptrOf(wbuf2)
+}
+
// put enqueues a pointer for the garbage collector to trace.
// obj must point to the beginning of a heap object.
//go:nowritebarrier
func (ww *gcWork) put(obj uintptr) {
w := (*gcWork)(noescape(unsafe.Pointer(ww))) // TODO: remove when escape analysis is fixed
- wbuf := w.wbuf.ptr()
+ wbuf := w.wbuf1.ptr()
if wbuf == nil {
- wbuf = getempty(42)
- w.wbuf = wbufptrOf(wbuf)
+ w.init()
+ wbuf = w.wbuf1.ptr()
+ // wbuf is empty at this point.
+ } else if wbuf.nobj == len(wbuf.obj) {
+ w.wbuf1, w.wbuf2 = w.wbuf2, w.wbuf1
+ wbuf = w.wbuf1.ptr()
+ if wbuf.nobj == len(wbuf.obj) {
+ putfull(wbuf, 132)
+ wbuf = getempty(133)
+ w.wbuf1 = wbufptrOf(wbuf)
+ }
}
wbuf.obj[wbuf.nobj] = obj
wbuf.nobj++
-
- if wbuf.nobj == len(wbuf.obj) {
- putfull(wbuf, 50)
- w.wbuf = 0
- }
}
// tryGet dequeues a pointer for the garbage collector to trace.
func (ww *gcWork) tryGet() uintptr {
w := (*gcWork)(noescape(unsafe.Pointer(ww))) // TODO: remove when escape analysis is fixed
- wbuf := w.wbuf.ptr()
+ wbuf := w.wbuf1.ptr()
if wbuf == nil {
- wbuf = trygetfull(74)
- if wbuf == nil {
- return 0
- }
- w.wbuf = wbufptrOf(wbuf)
+ w.init()
+ wbuf = w.wbuf1.ptr()
+ // wbuf is empty at this point.
}
-
- wbuf.nobj--
- obj := wbuf.obj[wbuf.nobj]
-
if wbuf.nobj == 0 {
- putempty(wbuf, 86)
- w.wbuf = 0
+ w.wbuf1, w.wbuf2 = w.wbuf2, w.wbuf1
+ wbuf = w.wbuf1.ptr()
+ if wbuf.nobj == 0 {
+ owbuf := wbuf
+ wbuf = trygetfull(167)
+ if wbuf == nil {
+ return 0
+ }
+ putempty(owbuf, 166)
+ w.wbuf1 = wbufptrOf(wbuf)
+ }
}
- return obj
+ wbuf.nobj--
+ return wbuf.obj[wbuf.nobj]
}
// get dequeues a pointer for the garbage collector to trace, blocking
func (ww *gcWork) get() uintptr {
w := (*gcWork)(noescape(unsafe.Pointer(ww))) // TODO: remove when escape analysis is fixed
- wbuf := w.wbuf.ptr()
+ wbuf := w.wbuf1.ptr()
if wbuf == nil {
- wbuf = getfull(103)
- if wbuf == nil {
- return 0
+ w.init()
+ wbuf = w.wbuf1.ptr()
+ // wbuf is empty at this point.
+ }
+ if wbuf.nobj == 0 {
+ w.wbuf1, w.wbuf2 = w.wbuf2, w.wbuf1
+ wbuf = w.wbuf1.ptr()
+ if wbuf.nobj == 0 {
+ owbuf := wbuf
+ wbuf = getfull(185)
+ if wbuf == nil {
+ return 0
+ }
+ putempty(owbuf, 184)
+ w.wbuf1 = wbufptrOf(wbuf)
}
- wbuf.checknonempty()
- w.wbuf = wbufptrOf(wbuf)
}
// TODO: This might be a good place to add prefetch code
wbuf.nobj--
- obj := wbuf.obj[wbuf.nobj]
-
- if wbuf.nobj == 0 {
- putempty(wbuf, 115)
- w.wbuf = 0
- }
-
- return obj
+ return wbuf.obj[wbuf.nobj]
}
// dispose returns any cached pointers to the global queue.
//
//go:nowritebarrier
func (w *gcWork) dispose() {
- if wbuf := w.wbuf; wbuf != 0 {
- if wbuf.ptr().nobj == 0 {
- throw("dispose: workbuf is empty")
+ if wbuf := w.wbuf1.ptr(); wbuf != nil {
+ if wbuf.nobj == 0 {
+ putempty(wbuf, 212)
+ } else {
+ putfull(wbuf, 214)
}
- putfull(wbuf.ptr(), 166)
- w.wbuf = 0
+ w.wbuf1 = 0
+
+ wbuf = w.wbuf2.ptr()
+ if wbuf.nobj == 0 {
+ putempty(wbuf, 218)
+ } else {
+ putfull(wbuf, 220)
+ }
+ w.wbuf2 = 0
}
if w.bytesMarked != 0 {
// dispose happens relatively infrequently. If this
// atomic becomes a problem, we should first try to
// dispose less and if necessary aggregate in a per-P
// counter.
- xadd64(&work.bytesMarked, int64(w.bytesMarked))
+ atomic.Xadd64(&work.bytesMarked, int64(w.bytesMarked))
w.bytesMarked = 0
}
if w.scanWork != 0 {
- xaddint64(&gcController.scanWork, w.scanWork)
+ atomic.Xaddint64(&gcController.scanWork, w.scanWork)
w.scanWork = 0
}
}
// global queue.
//go:nowritebarrier
func (w *gcWork) balance() {
- if wbuf := w.wbuf; wbuf != 0 && wbuf.ptr().nobj > 4 {
- w.wbuf = wbufptrOf(handoff(wbuf.ptr()))
+ if w.wbuf1 == 0 {
+ return
+ }
+ if wbuf := w.wbuf2.ptr(); wbuf.nobj != 0 {
+ putfull(wbuf, 246)
+ w.wbuf2 = wbufptrOf(getempty(247))
+ } else if wbuf := w.wbuf1.ptr(); wbuf.nobj > 4 {
+ w.wbuf1 = wbufptrOf(handoff(wbuf))
}
}
// empty returns true if w has no mark work available.
//go:nowritebarrier
func (w *gcWork) empty() bool {
- wbuf := w.wbuf
- return wbuf == 0 || wbuf.ptr().nobj == 0
+ return w.wbuf1 == 0 || (w.wbuf1.ptr().nobj == 0 && w.wbuf2.ptr().nobj == 0)
}
// Internally, the GC work pool is kept in arrays in work buffers.
type workbuf struct {
workbufhdr
// account for the above fields
- obj [(_WorkbufSize - unsafe.Sizeof(workbufhdr{})) / ptrSize]uintptr
+ obj [(_WorkbufSize - unsafe.Sizeof(workbufhdr{})) / sys.PtrSize]uintptr
}
// workbuf factory routines. These funcs are used to manage the
}
}
if b == nil {
- b = (*workbuf)(persistentalloc(unsafe.Sizeof(*b), _CacheLineSize, &memstats.gc_sys))
+ b = (*workbuf)(persistentalloc(unsafe.Sizeof(*b), sys.CacheLineSize, &memstats.gc_sys))
}
b.logget(entry)
return b
b.checknonempty()
b.logput(entry)
lfstackpush(&work.full, &b.node)
+
+ // We just made more work available. Let the GC controller
+ // know so it can encourage more workers to run.
+ if gcphase == _GCmark {
+ gcController.enlistWorker()
+ }
}
// trygetfull tries to get a full or partially empty workbuffer.
return b
}
- incnwait := xadd(&work.nwait, +1)
+ incnwait := atomic.Xadd(&work.nwait, +1)
if incnwait > work.nproc {
println("runtime: work.nwait=", incnwait, "work.nproc=", work.nproc)
throw("work.nwait > work.nproc")
}
for i := 0; ; i++ {
if work.full != 0 {
- decnwait := xadd(&work.nwait, -1)
+ decnwait := atomic.Xadd(&work.nwait, -1)
if decnwait == work.nproc {
println("runtime: work.nwait=", decnwait, "work.nproc=", work.nproc)
throw("work.nwait > work.nproc")
b.checknonempty()
return b
}
- incnwait := xadd(&work.nwait, +1)
+ incnwait := atomic.Xadd(&work.nwait, +1)
if incnwait > work.nproc {
println("runtime: work.nwait=", incnwait, "work.nproc=", work.nproc)
throw("work.nwait > work.nproc")
}
}
- if work.nwait == work.nproc {
+ if work.nwait == work.nproc && work.markrootNext >= work.markrootJobs {
return nil
}
_g_ := getg()
package runtime
-import "unsafe"
+import (
+ "runtime/internal/atomic"
+ "runtime/internal/sys"
+ "unsafe"
+)
// Main malloc heap.
// The heap itself is the "free[]" and "large" arrays,
// but all the other global data is here too.
type mheap struct {
lock mutex
- free [_MaxMHeapList]mspan // free lists of given length
- freelarge mspan // free lists length >= _MaxMHeapList
- busy [_MaxMHeapList]mspan // busy lists of large objects of given length
- busylarge mspan // busy lists of large objects length >= _MaxMHeapList
- allspans **mspan // all spans out there
- gcspans **mspan // copy of allspans referenced by gc marker or sweeper
+ free [_MaxMHeapList]mSpanList // free lists of given length
+ freelarge mSpanList // free lists length >= _MaxMHeapList
+ busy [_MaxMHeapList]mSpanList // busy lists of large objects of given length
+ busylarge mSpanList // busy lists of large objects length >= _MaxMHeapList
+ allspans **mspan // all spans out there
+ gcspans **mspan // copy of allspans referenced by gc marker or sweeper
nspan uint32
sweepgen uint32 // sweep generation, see comment in mspan
sweepdone uint32 // all spans are swept
// gets its own cache line.
central [_NumSizeClasses]struct {
mcentral mcentral
- pad [_CacheLineSize]byte
+ pad [sys.CacheLineSize]byte
}
spanalloc fixalloc // allocator for span*
// Every MSpan is in one doubly-linked list,
// either one of the MHeap's free lists or one of the
-// MCentral's span lists. We use empty MSpan structures as list heads.
+// MCentral's span lists.
// An MSpan representing actual memory has state _MSpanInUse,
// _MSpanStack, or _MSpanFree. Transitions between these states are
_MSpanInUse = iota // allocated for garbage collected heap
_MSpanStack // allocated for use by stack allocator
_MSpanFree
- _MSpanListHead
_MSpanDead
)
+// mSpanList heads a linked list of spans.
+//
+// Linked list structure is based on BSD's "tail queue" data structure.
+type mSpanList struct {
+ first *mspan // first span in list, or nil if none
+ last **mspan // last span's next field, or first if none
+}
+
type mspan struct {
- next *mspan // in a span linked list
- prev *mspan // in a span linked list
+ next *mspan // next span in list, or nil if none
+ prev **mspan // previous span's next field, or list head's first field if none
+ list *mSpanList // For debugging. TODO: Remove.
+
start pageID // starting page number
npages uintptr // number of pages in span
freelist gclinkptr // list of free objects
h := (*mheap)(vh)
s := (*mspan)(p)
if len(h_allspans) >= cap(h_allspans) {
- n := 64 * 1024 / ptrSize
+ n := 64 * 1024 / sys.PtrSize
if n < cap(h_allspans)*3/2 {
n = cap(h_allspans) * 3 / 2
}
var new []*mspan
sp := (*slice)(unsafe.Pointer(&new))
- sp.array = sysAlloc(uintptr(n)*ptrSize, &memstats.other_sys)
+ sp.array = sysAlloc(uintptr(n)*sys.PtrSize, &memstats.other_sys)
if sp.array == nil {
throw("runtime: cannot allocate memory")
}
// Don't free the old array if it's referenced by sweep.
// See the comment in mgc.go.
if h.allspans != mheap_.gcspans {
- sysFree(unsafe.Pointer(h.allspans), uintptr(cap(h_allspans))*ptrSize, &memstats.other_sys)
+ sysFree(unsafe.Pointer(h.allspans), uintptr(cap(h_allspans))*sys.PtrSize, &memstats.other_sys)
}
}
h_allspans = new
_g_ := getg()
_g_.m.mcache.local_nlookup++
- if ptrSize == 4 && _g_.m.mcache.local_nlookup >= 1<<30 {
+ if sys.PtrSize == 4 && _g_.m.mcache.local_nlookup >= 1<<30 {
// purge cache stats to prevent overflow
lock(&mheap_.lock)
purgecachedstats(_g_.m.mcache)
unlock(&mheap_.lock)
}
- s := mHeap_LookupMaybe(&mheap_, unsafe.Pointer(v))
+ s := mheap_.lookupMaybe(unsafe.Pointer(v))
if sp != nil {
*sp = s
}
}
// Initialize the heap.
-func mHeap_Init(h *mheap, spans_size uintptr) {
- fixAlloc_Init(&h.spanalloc, unsafe.Sizeof(mspan{}), recordspan, unsafe.Pointer(h), &memstats.mspan_sys)
- fixAlloc_Init(&h.cachealloc, unsafe.Sizeof(mcache{}), nil, nil, &memstats.mcache_sys)
- fixAlloc_Init(&h.specialfinalizeralloc, unsafe.Sizeof(specialfinalizer{}), nil, nil, &memstats.other_sys)
- fixAlloc_Init(&h.specialprofilealloc, unsafe.Sizeof(specialprofile{}), nil, nil, &memstats.other_sys)
+func (h *mheap) init(spans_size uintptr) {
+ h.spanalloc.init(unsafe.Sizeof(mspan{}), recordspan, unsafe.Pointer(h), &memstats.mspan_sys)
+ h.cachealloc.init(unsafe.Sizeof(mcache{}), nil, nil, &memstats.mcache_sys)
+ h.specialfinalizeralloc.init(unsafe.Sizeof(specialfinalizer{}), nil, nil, &memstats.other_sys)
+ h.specialprofilealloc.init(unsafe.Sizeof(specialprofile{}), nil, nil, &memstats.other_sys)
// h->mapcache needs no init
for i := range h.free {
- mSpanList_Init(&h.free[i])
- mSpanList_Init(&h.busy[i])
+ h.free[i].init()
+ h.busy[i].init()
}
- mSpanList_Init(&h.freelarge)
- mSpanList_Init(&h.busylarge)
+ h.freelarge.init()
+ h.busylarge.init()
for i := range h.central {
- mCentral_Init(&h.central[i].mcentral, int32(i))
+ h.central[i].mcentral.init(int32(i))
}
sp := (*slice)(unsafe.Pointer(&h_spans))
sp.array = unsafe.Pointer(h.spans)
- sp.len = int(spans_size / ptrSize)
- sp.cap = int(spans_size / ptrSize)
+ sp.len = int(spans_size / sys.PtrSize)
+ sp.cap = int(spans_size / sys.PtrSize)
}
// mHeap_MapSpans makes sure that the spans are mapped
// Waiting to update arena_used until after the memory has been mapped
// avoids faults when other threads try access the bitmap immediately
// after observing the change to arena_used.
-func mHeap_MapSpans(h *mheap, arena_used uintptr) {
+func (h *mheap) mapSpans(arena_used uintptr) {
// Map spans array, PageSize at a time.
n := arena_used
n -= h.arena_start
- n = n / _PageSize * ptrSize
- n = round(n, _PhysPageSize)
+ n = n / _PageSize * sys.PtrSize
+ n = round(n, sys.PhysPageSize)
if h.spans_mapped >= n {
return
}
// Sweeps spans in list until reclaims at least npages into heap.
// Returns the actual number of pages reclaimed.
-func mHeap_ReclaimList(h *mheap, list *mspan, npages uintptr) uintptr {
+func (h *mheap) reclaimList(list *mSpanList, npages uintptr) uintptr {
n := uintptr(0)
sg := mheap_.sweepgen
retry:
- for s := list.next; s != list; s = s.next {
- if s.sweepgen == sg-2 && cas(&s.sweepgen, sg-2, sg-1) {
- mSpanList_Remove(s)
+ for s := list.first; s != nil; s = s.next {
+ if s.sweepgen == sg-2 && atomic.Cas(&s.sweepgen, sg-2, sg-1) {
+ list.remove(s)
// swept spans are at the end of the list
- mSpanList_InsertBack(list, s)
+ list.insertBack(s)
unlock(&h.lock)
snpages := s.npages
- if mSpan_Sweep(s, false) {
+ if s.sweep(false) {
n += snpages
}
lock(&h.lock)
// Sweeps and reclaims at least npage pages into heap.
// Called before allocating npage pages.
-func mHeap_Reclaim(h *mheap, npage uintptr) {
+func (h *mheap) reclaim(npage uintptr) {
// First try to sweep busy spans with large objects of size >= npage,
// this has good chances of reclaiming the necessary space.
for i := int(npage); i < len(h.busy); i++ {
- if mHeap_ReclaimList(h, &h.busy[i], npage) != 0 {
+ if h.reclaimList(&h.busy[i], npage) != 0 {
return // Bingo!
}
}
// Then -- even larger objects.
- if mHeap_ReclaimList(h, &h.busylarge, npage) != 0 {
+ if h.reclaimList(&h.busylarge, npage) != 0 {
return // Bingo!
}
// One such object is not enough, so we need to reclaim several of them.
reclaimed := uintptr(0)
for i := 0; i < int(npage) && i < len(h.busy); i++ {
- reclaimed += mHeap_ReclaimList(h, &h.busy[i], npage-reclaimed)
+ reclaimed += h.reclaimList(&h.busy[i], npage-reclaimed)
if reclaimed >= npage {
return
}
// Allocate a new span of npage pages from the heap for GC'd memory
// and record its size class in the HeapMap and HeapMapCache.
-func mHeap_Alloc_m(h *mheap, npage uintptr, sizeclass int32, large bool) *mspan {
+func (h *mheap) alloc_m(npage uintptr, sizeclass int32, large bool) *mspan {
_g_ := getg()
if _g_ != _g_.m.g0 {
throw("_mheap_alloc not on g0 stack")
// If GC kept a bit for whether there were any marks
// in a span, we could release these free spans
// at the end of GC and eliminate this entirely.
- mHeap_Reclaim(h, npage)
+ h.reclaim(npage)
}
// transfer stats from cache to global
memstats.tinyallocs += uint64(_g_.m.mcache.local_tinyallocs)
_g_.m.mcache.local_tinyallocs = 0
- s := mHeap_AllocSpanLocked(h, npage)
+ s := h.allocSpanLocked(npage)
if s != nil {
// Record span info, because gc needs to be
// able to map interior pointer to containing span.
- atomicstore(&s.sweepgen, h.sweepgen)
+ atomic.Store(&s.sweepgen, h.sweepgen)
s.state = _MSpanInUse
s.freelist = 0
s.ref = 0
memstats.heap_live += uint64(npage << _PageShift)
// Swept spans are at the end of lists.
if s.npages < uintptr(len(h.free)) {
- mSpanList_InsertBack(&h.busy[s.npages], s)
+ h.busy[s.npages].insertBack(s)
} else {
- mSpanList_InsertBack(&h.busylarge, s)
+ h.busylarge.insertBack(s)
}
}
}
return s
}
-func mHeap_Alloc(h *mheap, npage uintptr, sizeclass int32, large bool, needzero bool) *mspan {
+func (h *mheap) alloc(npage uintptr, sizeclass int32, large bool, needzero bool) *mspan {
// Don't do any operations that lock the heap on the G stack.
// It might trigger stack growth, and the stack growth code needs
// to be able to allocate heap.
var s *mspan
systemstack(func() {
- s = mHeap_Alloc_m(h, npage, sizeclass, large)
+ s = h.alloc_m(npage, sizeclass, large)
})
if s != nil {
return s
}
-func mHeap_AllocStack(h *mheap, npage uintptr) *mspan {
+func (h *mheap) allocStack(npage uintptr) *mspan {
_g_ := getg()
if _g_ != _g_.m.g0 {
throw("mheap_allocstack not on g0 stack")
}
lock(&h.lock)
- s := mHeap_AllocSpanLocked(h, npage)
+ s := h.allocSpanLocked(npage)
if s != nil {
s.state = _MSpanStack
s.freelist = 0
// Allocates a span of the given size. h must be locked.
// The returned span has been removed from the
// free list, but its state is still MSpanFree.
-func mHeap_AllocSpanLocked(h *mheap, npage uintptr) *mspan {
+func (h *mheap) allocSpanLocked(npage uintptr) *mspan {
+ var list *mSpanList
var s *mspan
// Try in fixed-size lists up to max.
for i := int(npage); i < len(h.free); i++ {
- if !mSpanList_IsEmpty(&h.free[i]) {
- s = h.free[i].next
+ list = &h.free[i]
+ if !list.isEmpty() {
+ s = list.first
goto HaveSpan
}
}
// Best fit in list of large spans.
- s = mHeap_AllocLarge(h, npage)
+ list = &h.freelarge
+ s = h.allocLarge(npage)
if s == nil {
- if !mHeap_Grow(h, npage) {
+ if !h.grow(npage) {
return nil
}
- s = mHeap_AllocLarge(h, npage)
+ s = h.allocLarge(npage)
if s == nil {
return nil
}
if s.npages < npage {
throw("MHeap_AllocLocked - bad npages")
}
- mSpanList_Remove(s)
- if s.next != nil || s.prev != nil {
+ list.remove(s)
+ if s.inList() {
throw("still in list")
}
if s.npreleased > 0 {
if s.npages > npage {
// Trim extra and put it back in the heap.
- t := (*mspan)(fixAlloc_Alloc(&h.spanalloc))
- mSpan_Init(t, s.start+pageID(npage), s.npages-npage)
+ t := (*mspan)(h.spanalloc.alloc())
+ t.init(s.start+pageID(npage), s.npages-npage)
s.npages = npage
p := uintptr(t.start)
- p -= (uintptr(unsafe.Pointer(h.arena_start)) >> _PageShift)
+ p -= (h.arena_start >> _PageShift)
if p > 0 {
h_spans[p-1] = s
}
t.needzero = s.needzero
s.state = _MSpanStack // prevent coalescing with s
t.state = _MSpanStack
- mHeap_FreeSpanLocked(h, t, false, false, s.unusedsince)
+ h.freeSpanLocked(t, false, false, s.unusedsince)
s.state = _MSpanFree
}
s.unusedsince = 0
p := uintptr(s.start)
- p -= (uintptr(unsafe.Pointer(h.arena_start)) >> _PageShift)
+ p -= (h.arena_start >> _PageShift)
for n := uintptr(0); n < npage; n++ {
h_spans[p+n] = s
}
memstats.heap_idle -= uint64(npage << _PageShift)
//println("spanalloc", hex(s.start<<_PageShift))
- if s.next != nil || s.prev != nil {
+ if s.inList() {
throw("still in list")
}
return s
}
// Allocate a span of exactly npage pages from the list of large spans.
-func mHeap_AllocLarge(h *mheap, npage uintptr) *mspan {
+func (h *mheap) allocLarge(npage uintptr) *mspan {
return bestFit(&h.freelarge, npage, nil)
}
// Search list for smallest span with >= npage pages.
// If there are multiple smallest spans, take the one
// with the earliest starting address.
-func bestFit(list *mspan, npage uintptr, best *mspan) *mspan {
- for s := list.next; s != list; s = s.next {
+func bestFit(list *mSpanList, npage uintptr, best *mspan) *mspan {
+ for s := list.first; s != nil; s = s.next {
if s.npages < npage {
continue
}
// returning whether it worked.
//
// h must be locked.
-func mHeap_Grow(h *mheap, npage uintptr) bool {
+func (h *mheap) grow(npage uintptr) bool {
// Ask for a big chunk, to reduce the number of mappings
// the operating system needs to track; also amortizes
// the overhead of an operating system mapping.
ask = _HeapAllocChunk
}
- v := mHeap_SysAlloc(h, ask)
+ v := h.sysAlloc(ask)
if v == nil {
if ask > npage<<_PageShift {
ask = npage << _PageShift
- v = mHeap_SysAlloc(h, ask)
+ v = h.sysAlloc(ask)
}
if v == nil {
print("runtime: out of memory: cannot allocate ", ask, "-byte block (", memstats.heap_sys, " in use)\n")
// Create a fake "in use" span and free it, so that the
// right coalescing happens.
- s := (*mspan)(fixAlloc_Alloc(&h.spanalloc))
- mSpan_Init(s, pageID(uintptr(v)>>_PageShift), ask>>_PageShift)
+ s := (*mspan)(h.spanalloc.alloc())
+ s.init(pageID(uintptr(v)>>_PageShift), ask>>_PageShift)
p := uintptr(s.start)
- p -= (uintptr(unsafe.Pointer(h.arena_start)) >> _PageShift)
+ p -= (h.arena_start >> _PageShift)
for i := p; i < p+s.npages; i++ {
h_spans[i] = s
}
- atomicstore(&s.sweepgen, h.sweepgen)
+ atomic.Store(&s.sweepgen, h.sweepgen)
s.state = _MSpanInUse
h.pagesInUse += uint64(npage)
- mHeap_FreeSpanLocked(h, s, false, true, 0)
+ h.freeSpanLocked(s, false, true, 0)
return true
}
// Look up the span at the given address.
// Address is guaranteed to be in map
// and is guaranteed to be start or end of span.
-func mHeap_Lookup(h *mheap, v unsafe.Pointer) *mspan {
+func (h *mheap) lookup(v unsafe.Pointer) *mspan {
p := uintptr(v)
- p -= uintptr(unsafe.Pointer(h.arena_start))
+ p -= h.arena_start
return h_spans[p>>_PageShift]
}
// valid for allocated spans. Free spans may have
// other garbage in their middles, so we have to
// check for that.
-func mHeap_LookupMaybe(h *mheap, v unsafe.Pointer) *mspan {
- if uintptr(v) < uintptr(unsafe.Pointer(h.arena_start)) || uintptr(v) >= uintptr(unsafe.Pointer(h.arena_used)) {
+func (h *mheap) lookupMaybe(v unsafe.Pointer) *mspan {
+ if uintptr(v) < h.arena_start || uintptr(v) >= h.arena_used {
return nil
}
p := uintptr(v) >> _PageShift
q := p
- q -= uintptr(unsafe.Pointer(h.arena_start)) >> _PageShift
+ q -= h.arena_start >> _PageShift
s := h_spans[q]
if s == nil || p < uintptr(s.start) || uintptr(v) >= uintptr(unsafe.Pointer(s.limit)) || s.state != _MSpanInUse {
return nil
}
// Free the span back into the heap.
-func mHeap_Free(h *mheap, s *mspan, acct int32) {
+func (h *mheap) freeSpan(s *mspan, acct int32) {
systemstack(func() {
mp := getg().m
lock(&h.lock)
if gcBlackenEnabled != 0 {
gcController.revise()
}
- mHeap_FreeSpanLocked(h, s, true, true, 0)
+ h.freeSpanLocked(s, true, true, 0)
if trace.enabled {
traceHeapAlloc()
}
})
}
-func mHeap_FreeStack(h *mheap, s *mspan) {
+func (h *mheap) freeStack(s *mspan) {
_g_ := getg()
if _g_ != _g_.m.g0 {
throw("mheap_freestack not on g0 stack")
s.needzero = 1
lock(&h.lock)
memstats.stacks_inuse -= uint64(s.npages << _PageShift)
- mHeap_FreeSpanLocked(h, s, true, true, 0)
+ h.freeSpanLocked(s, true, true, 0)
unlock(&h.lock)
}
-func mHeap_FreeSpanLocked(h *mheap, s *mspan, acctinuse, acctidle bool, unusedsince int64) {
+// s must be on a busy list (h.busy or h.busylarge) or unlinked.
+func (h *mheap) freeSpanLocked(s *mspan, acctinuse, acctidle bool, unusedsince int64) {
switch s.state {
case _MSpanStack:
if s.ref != 0 {
memstats.heap_idle += uint64(s.npages << _PageShift)
}
s.state = _MSpanFree
- mSpanList_Remove(s)
+ if s.inList() {
+ h.busyList(s.npages).remove(s)
+ }
// Stamp newly unused spans. The scavenger will use that
// info to potentially give back some pages to the OS.
// Coalesce with earlier, later spans.
p := uintptr(s.start)
- p -= uintptr(unsafe.Pointer(h.arena_start)) >> _PageShift
+ p -= h.arena_start >> _PageShift
if p > 0 {
t := h_spans[p-1]
- if t != nil && t.state != _MSpanInUse && t.state != _MSpanStack {
+ if t != nil && t.state == _MSpanFree {
s.start = t.start
s.npages += t.npages
s.npreleased = t.npreleased // absorb released pages
s.needzero |= t.needzero
p -= t.npages
h_spans[p] = s
- mSpanList_Remove(t)
+ h.freeList(t.npages).remove(t)
t.state = _MSpanDead
- fixAlloc_Free(&h.spanalloc, unsafe.Pointer(t))
+ h.spanalloc.free(unsafe.Pointer(t))
}
}
- if (p+s.npages)*ptrSize < h.spans_mapped {
+ if (p+s.npages)*sys.PtrSize < h.spans_mapped {
t := h_spans[p+s.npages]
- if t != nil && t.state != _MSpanInUse && t.state != _MSpanStack {
+ if t != nil && t.state == _MSpanFree {
s.npages += t.npages
s.npreleased += t.npreleased
s.needzero |= t.needzero
h_spans[p+s.npages-1] = s
- mSpanList_Remove(t)
+ h.freeList(t.npages).remove(t)
t.state = _MSpanDead
- fixAlloc_Free(&h.spanalloc, unsafe.Pointer(t))
+ h.spanalloc.free(unsafe.Pointer(t))
}
}
// Insert s into appropriate list.
- if s.npages < uintptr(len(h.free)) {
- mSpanList_Insert(&h.free[s.npages], s)
- } else {
- mSpanList_Insert(&h.freelarge, s)
+ h.freeList(s.npages).insert(s)
+}
+
+func (h *mheap) freeList(npages uintptr) *mSpanList {
+ if npages < uintptr(len(h.free)) {
+ return &h.free[npages]
+ }
+ return &h.freelarge
+}
+
+func (h *mheap) busyList(npages uintptr) *mSpanList {
+ if npages < uintptr(len(h.free)) {
+ return &h.busy[npages]
}
+ return &h.busylarge
}
-func scavengelist(list *mspan, now, limit uint64) uintptr {
- if _PhysPageSize > _PageSize {
+func scavengelist(list *mSpanList, now, limit uint64) uintptr {
+ if sys.PhysPageSize > _PageSize {
// golang.org/issue/9993
// If the physical page size of the machine is larger than
// our logical heap page size the kernel may round up the
return 0
}
- if mSpanList_IsEmpty(list) {
+ if list.isEmpty() {
return 0
}
var sumreleased uintptr
- for s := list.next; s != list; s = s.next {
+ for s := list.first; s != nil; s = s.next {
if (now-uint64(s.unusedsince)) > limit && s.npreleased != s.npages {
released := (s.npages - s.npreleased) << _PageShift
memstats.heap_released += uint64(released)
return sumreleased
}
-func mHeap_Scavenge(k int32, now, limit uint64) {
- h := &mheap_
+func (h *mheap) scavenge(k int32, now, limit uint64) {
lock(&h.lock)
var sumreleased uintptr
for i := 0; i < len(h.free); i++ {
//go:linkname runtime_debug_freeOSMemory runtime/debug.freeOSMemory
func runtime_debug_freeOSMemory() {
- startGC(gcForceBlockMode, false)
- systemstack(func() { mHeap_Scavenge(-1, ^uint64(0), 0) })
+ gcStart(gcForceBlockMode, false)
+ systemstack(func() { mheap_.scavenge(-1, ^uint64(0), 0) })
}
// Initialize a new span with the given start and npages.
-func mSpan_Init(span *mspan, start pageID, npages uintptr) {
+func (span *mspan) init(start pageID, npages uintptr) {
span.next = nil
span.prev = nil
+ span.list = nil
span.start = start
span.npages = npages
span.freelist = 0
span.needzero = 0
}
+func (span *mspan) inList() bool {
+ return span.prev != nil
+}
+
// Initialize an empty doubly-linked list.
-func mSpanList_Init(list *mspan) {
- list.state = _MSpanListHead
- list.next = list
- list.prev = list
+func (list *mSpanList) init() {
+ list.first = nil
+ list.last = &list.first
}
-func mSpanList_Remove(span *mspan) {
- if span.prev == nil && span.next == nil {
- return
+func (list *mSpanList) remove(span *mspan) {
+ if span.prev == nil || span.list != list {
+ println("failed MSpanList_Remove", span, span.prev, span.list, list)
+ throw("MSpanList_Remove")
}
- span.prev.next = span.next
- span.next.prev = span.prev
- span.prev = nil
+ if span.next != nil {
+ span.next.prev = span.prev
+ } else {
+ // TODO: After we remove the span.list != list check above,
+ // we could at least still check list.last == &span.next here.
+ list.last = span.prev
+ }
+ *span.prev = span.next
span.next = nil
+ span.prev = nil
+ span.list = nil
}
-func mSpanList_IsEmpty(list *mspan) bool {
- return list.next == list
+func (list *mSpanList) isEmpty() bool {
+ return list.first == nil
}
-func mSpanList_Insert(list *mspan, span *mspan) {
- if span.next != nil || span.prev != nil {
- println("failed MSpanList_Insert", span, span.next, span.prev)
+func (list *mSpanList) insert(span *mspan) {
+ if span.next != nil || span.prev != nil || span.list != nil {
+ println("failed MSpanList_Insert", span, span.next, span.prev, span.list)
throw("MSpanList_Insert")
}
- span.next = list.next
- span.prev = list
- span.next.prev = span
- span.prev.next = span
+ span.next = list.first
+ if list.first != nil {
+ list.first.prev = &span.next
+ } else {
+ list.last = &span.next
+ }
+ list.first = span
+ span.prev = &list.first
+ span.list = list
}
-func mSpanList_InsertBack(list *mspan, span *mspan) {
- if span.next != nil || span.prev != nil {
- println("failed MSpanList_InsertBack", span, span.next, span.prev)
+func (list *mSpanList) insertBack(span *mspan) {
+ if span.next != nil || span.prev != nil || span.list != nil {
+ println("failed MSpanList_InsertBack", span, span.next, span.prev, span.list)
throw("MSpanList_InsertBack")
}
- span.next = list
- span.prev = list.prev
- span.next.prev = span
- span.prev.next = span
+ span.next = nil
+ span.prev = list.last
+ *list.last = span
+ list.last = &span.next
+ span.list = list
}
const (
// (The add will fail only if a record with the same p and s->kind
// already exists.)
func addspecial(p unsafe.Pointer, s *special) bool {
- span := mHeap_LookupMaybe(&mheap_, p)
+ span := mheap_.lookupMaybe(p)
if span == nil {
throw("addspecial on invalid pointer")
}
// Sweeping accesses the specials list w/o locks, so we have
// to synchronize with it. And it's just much safer.
mp := acquirem()
- mSpan_EnsureSwept(span)
+ span.ensureSwept()
offset := uintptr(p) - uintptr(span.start<<_PageShift)
kind := s.kind
// Returns the record if the record existed, nil otherwise.
// The caller must FixAlloc_Free the result.
func removespecial(p unsafe.Pointer, kind uint8) *special {
- span := mHeap_LookupMaybe(&mheap_, p)
+ span := mheap_.lookupMaybe(p)
if span == nil {
throw("removespecial on invalid pointer")
}
// Sweeping accesses the specials list w/o locks, so we have
// to synchronize with it. And it's just much safer.
mp := acquirem()
- mSpan_EnsureSwept(span)
+ span.ensureSwept()
offset := uintptr(p) - uintptr(span.start<<_PageShift)
// Adds a finalizer to the object p. Returns true if it succeeded.
func addfinalizer(p unsafe.Pointer, f *funcval, nret uintptr, fint *_type, ot *ptrtype) bool {
lock(&mheap_.speciallock)
- s := (*specialfinalizer)(fixAlloc_Alloc(&mheap_.specialfinalizeralloc))
+ s := (*specialfinalizer)(mheap_.specialfinalizeralloc.alloc())
unlock(&mheap_.speciallock)
s.special.kind = _KindSpecialFinalizer
s.fn = f
scanobject(uintptr(base), gcw)
// Mark the finalizer itself, since the
// special isn't part of the GC'd heap.
- scanblock(uintptr(unsafe.Pointer(&s.fn)), ptrSize, &oneptrmask[0], gcw)
+ scanblock(uintptr(unsafe.Pointer(&s.fn)), sys.PtrSize, &oneptrmask[0], gcw)
if gcBlackenPromptly {
gcw.dispose()
}
// There was an old finalizer
lock(&mheap_.speciallock)
- fixAlloc_Free(&mheap_.specialfinalizeralloc, unsafe.Pointer(s))
+ mheap_.specialfinalizeralloc.free(unsafe.Pointer(s))
unlock(&mheap_.speciallock)
return false
}
return // there wasn't a finalizer to remove
}
lock(&mheap_.speciallock)
- fixAlloc_Free(&mheap_.specialfinalizeralloc, unsafe.Pointer(s))
+ mheap_.specialfinalizeralloc.free(unsafe.Pointer(s))
unlock(&mheap_.speciallock)
}
// Set the heap profile bucket associated with addr to b.
func setprofilebucket(p unsafe.Pointer, b *bucket) {
lock(&mheap_.speciallock)
- s := (*specialprofile)(fixAlloc_Alloc(&mheap_.specialprofilealloc))
+ s := (*specialprofile)(mheap_.specialprofilealloc.alloc())
unlock(&mheap_.speciallock)
s.special.kind = _KindSpecialProfile
s.b = b
// Do whatever cleanup needs to be done to deallocate s. It has
// already been unlinked from the MSpan specials list.
-// Returns true if we should keep working on deallocating p.
-func freespecial(s *special, p unsafe.Pointer, size uintptr, freed bool) bool {
+func freespecial(s *special, p unsafe.Pointer, size uintptr) {
switch s.kind {
case _KindSpecialFinalizer:
sf := (*specialfinalizer)(unsafe.Pointer(s))
queuefinalizer(p, sf.fn, sf.nret, sf.fint, sf.ot)
lock(&mheap_.speciallock)
- fixAlloc_Free(&mheap_.specialfinalizeralloc, unsafe.Pointer(sf))
+ mheap_.specialfinalizeralloc.free(unsafe.Pointer(sf))
unlock(&mheap_.speciallock)
- return false // don't free p until finalizer is done
case _KindSpecialProfile:
sp := (*specialprofile)(unsafe.Pointer(s))
- mProf_Free(sp.b, size, freed)
+ mProf_Free(sp.b, size)
lock(&mheap_.speciallock)
- fixAlloc_Free(&mheap_.specialprofilealloc, unsafe.Pointer(sp))
+ mheap_.specialprofilealloc.free(unsafe.Pointer(sp))
unlock(&mheap_.speciallock)
- return true
default:
throw("bad special kind")
panic("not reached")
gen("arm", notags, zeroARM, copyARM)
gen("arm64", notags, zeroARM64, copyARM64)
gen("ppc64x", tagsPPC64x, zeroPPC64x, copyPPC64x)
+ gen("mips64x", tagsMIPS64x, zeroMIPS64x, copyMIPS64x)
}
func gen(arch string, tags, zero, copy func(io.Writer)) {
func copyPPC64x(w io.Writer) {
fmt.Fprintln(w, "// TODO: Implement runtime·duffcopy.")
}
+
+func tagsMIPS64x(w io.Writer) {
+ fmt.Fprintln(w)
+ fmt.Fprintln(w, "// +build mips64 mips64le")
+ fmt.Fprintln(w)
+}
+
+func zeroMIPS64x(w io.Writer) {
+ // R0: always zero
+ // R1 (aka REGRT1): ptr to memory to be zeroed - 8
+ // On return, R1 points to the last zeroed dword.
+ fmt.Fprintln(w, "TEXT runtime·duffzero(SB), NOSPLIT, $-8-0")
+ for i := 0; i < 128; i++ {
+ fmt.Fprintln(w, "\tMOVV\tR0, 8(R1)")
+ fmt.Fprintln(w, "\tADDV\t$8, R1")
+ }
+ fmt.Fprintln(w, "\tRET")
+}
+
+func copyMIPS64x(w io.Writer) {
+ fmt.Fprintln(w, "// TODO: Implement runtime·duffcopy.")
+}
package runtime
import (
+ "runtime/internal/atomic"
"unsafe"
)
}
// Called when freeing a profiled block.
-func mProf_Free(b *bucket, size uintptr, freed bool) {
+func mProf_Free(b *bucket, size uintptr) {
lock(&proflock)
mp := b.mp()
- if freed {
- mp.recent_frees++
- mp.recent_free_bytes += size
- } else {
- mp.prev_frees++
- mp.prev_free_bytes += size
- }
+ mp.prev_frees++
+ mp.prev_free_bytes += size
unlock(&proflock)
}
}
}
- atomicstore64(&blockprofilerate, uint64(r))
+ atomic.Store64(&blockprofilerate, uint64(r))
}
func blockevent(cycles int64, skip int) {
if cycles <= 0 {
cycles = 1
}
- rate := int64(atomicload64(&blockprofilerate))
+ rate := int64(atomic.Load64(&blockprofilerate))
if rate <= 0 || (rate > cycles && int64(fastrand1())%rate > cycles) {
return
}
// Most clients should use the runtime/pprof package instead
// of calling ThreadCreateProfile directly.
func ThreadCreateProfile(p []StackRecord) (n int, ok bool) {
- first := (*m)(atomicloadp(unsafe.Pointer(&allm)))
+ first := (*m)(atomic.Loadp(unsafe.Pointer(&allm)))
for mp := first; mp != nil; mp = mp.alllink {
n++
}
--- /dev/null
+// Copyright 2015 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 msan
+
+package runtime
+
+import (
+ "unsafe"
+)
+
+// Public memory sanitizer API.
+
+func MSanRead(addr unsafe.Pointer, len int) {
+ msanread(addr, uintptr(len))
+}
+
+func MSanWrite(addr unsafe.Pointer, len int) {
+ msanwrite(addr, uintptr(len))
+}
+
+// Private interface for the runtime.
+const msanenabled = true
+
+// If we are running on the system stack, the C program may have
+// marked part of that stack as uninitialized. We don't instrument
+// the runtime, but operations like a slice copy can call msanread
+// anyhow for values on the stack. Just ignore msanread when running
+// on the system stack. The other msan functions are fine.
+func msanread(addr unsafe.Pointer, sz uintptr) {
+ g := getg()
+ if g == g.m.g0 || g == g.m.gsignal {
+ return
+ }
+ domsanread(addr, sz)
+}
+
+//go:noescape
+func domsanread(addr unsafe.Pointer, sz uintptr)
+
+//go:noescape
+func msanwrite(addr unsafe.Pointer, sz uintptr)
+
+//go:noescape
+func msanmalloc(addr unsafe.Pointer, sz uintptr)
+
+//go:noescape
+func msanfree(addr unsafe.Pointer, sz uintptr)
+
+// These are called from msan_amd64.s
+//go:cgo_import_static __msan_read_go
+//go:cgo_import_static __msan_write_go
+//go:cgo_import_static __msan_malloc_go
+//go:cgo_import_static __msan_free_go
--- /dev/null
+// Copyright 2015 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 msan,linux,amd64
+
+package msan
+
+/*
+#cgo CFLAGS: -fsanitize=memory
+#cgo LDFLAGS: -fsanitize=memory
+
+#include <stdint.h>
+#include <sanitizer/msan_interface.h>
+
+void __msan_read_go(void *addr, uintptr_t sz) {
+ __msan_check_mem_is_initialized(addr, sz);
+}
+
+void __msan_write_go(void *addr, uintptr_t sz) {
+ __msan_unpoison(addr, sz);
+}
+
+void __msan_malloc_go(void *addr, uintptr_t sz) {
+ __msan_unpoison(addr, sz);
+}
+
+void __msan_free_go(void *addr, uintptr_t sz) {
+ __msan_poison(addr, sz);
+}
+*/
+import "C"
--- /dev/null
+// Copyright 2015 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 !msan
+
+// Dummy MSan support API, used when not built with -msan.
+
+package runtime
+
+import (
+ "unsafe"
+)
+
+const msanenabled = false
+
+// Because msanenabled is false, none of these functions should be called.
+
+func msanread(addr unsafe.Pointer, sz uintptr) { throw("msan") }
+func msanwrite(addr unsafe.Pointer, sz uintptr) { throw("msan") }
+func msanmalloc(addr unsafe.Pointer, sz uintptr) { throw("msan") }
+func msanfree(addr unsafe.Pointer, sz uintptr) { throw("msan") }
--- /dev/null
+// Copyright 2015 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 msan
+
+#include "go_asm.h"
+#include "go_tls.h"
+#include "funcdata.h"
+#include "textflag.h"
+
+// This is like race_amd64.s, but for the msan calls.
+// See race_amd64.s for detailed comments.
+
+#ifdef GOOS_windows
+#define RARG0 CX
+#define RARG1 DX
+#define RARG2 R8
+#define RARG3 R9
+#else
+#define RARG0 DI
+#define RARG1 SI
+#define RARG2 DX
+#define RARG3 CX
+#endif
+
+// func runtime·domsanread(addr unsafe.Pointer, sz uintptr)
+// Called from msanread.
+TEXT runtime·domsanread(SB), NOSPLIT, $0-16
+ MOVQ addr+0(FP), RARG0
+ MOVQ size+8(FP), RARG1
+ // void __msan_read_go(void *addr, uintptr_t sz);
+ MOVQ $__msan_read_go(SB), AX
+ JMP msancall<>(SB)
+
+// func runtime·msanwrite(addr unsafe.Pointer, sz uintptr)
+// Called from instrumented code.
+TEXT runtime·msanwrite(SB), NOSPLIT, $0-16
+ MOVQ addr+0(FP), RARG0
+ MOVQ size+8(FP), RARG1
+ // void __msan_write_go(void *addr, uintptr_t sz);
+ MOVQ $__msan_write_go(SB), AX
+ JMP msancall<>(SB)
+
+// func runtime·msanmalloc(addr unsafe.Pointer, sz uintptr)
+TEXT runtime·msanmalloc(SB), NOSPLIT, $0-16
+ MOVQ addr+0(FP), RARG0
+ MOVQ size+8(FP), RARG1
+ // void __msan_malloc_go(void *addr, uintptr_t sz);
+ MOVQ $__msan_malloc_go(SB), AX
+ JMP msancall<>(SB)
+
+// func runtime·msanfree(addr unsafe.Pointer, sz uintptr)
+TEXT runtime·msanfree(SB), NOSPLIT, $0-16
+ MOVQ addr+0(FP), RARG0
+ MOVQ size+8(FP), RARG1
+ // void __msan_free_go(void *addr, uintptr_t sz);
+ MOVQ $__msan_free_go(SB), AX
+ JMP msancall<>(SB)
+
+// Switches SP to g0 stack and calls (AX). Arguments already set.
+TEXT msancall<>(SB), NOSPLIT, $0-0
+ get_tls(R12)
+ MOVQ g(R12), R14
+ MOVQ g_m(R14), R13
+ // Switch to g0 stack.
+ MOVQ SP, R12 // callee-saved, preserved across the CALL
+ MOVQ m_g0(R13), R10
+ CMPQ R10, R14
+ JE call // already on g0
+ MOVQ (g_sched+gobuf_sp)(R10), SP
+call:
+ ANDQ $~15, SP // alignment for gcc ABI
+ CALL AX
+ MOVQ R12, SP
+ RET
package runtime
-import "unsafe"
+import (
+ "runtime/internal/atomic"
+ "runtime/internal/sys"
+ "unsafe"
+)
// Statistics.
// If you edit this structure, also edit type MemStats below.
if c == nil {
continue
}
- mCache_ReleaseAll(c)
+ c.releaseAll()
stackcache_clear(c)
}
}
// overflow errors.
//go:nosplit
func mSysStatInc(sysStat *uint64, n uintptr) {
- if _BigEndian != 0 {
- xadd64(sysStat, int64(n))
+ if sys.BigEndian != 0 {
+ atomic.Xadd64(sysStat, int64(n))
return
}
- if val := xadduintptr((*uintptr)(unsafe.Pointer(sysStat)), n); val < n {
+ if val := atomic.Xadduintptr((*uintptr)(unsafe.Pointer(sysStat)), n); val < n {
print("runtime: stat overflow: val ", val, ", n ", n, "\n")
exit(2)
}
// mSysStatInc apply.
//go:nosplit
func mSysStatDec(sysStat *uint64, n uintptr) {
- if _BigEndian != 0 {
- xadd64(sysStat, -int64(n))
+ if sys.BigEndian != 0 {
+ atomic.Xadd64(sysStat, -int64(n))
return
}
- if val := xadduintptr((*uintptr)(unsafe.Pointer(sysStat)), uintptr(-int64(n))); val+n < n {
+ if val := atomic.Xadduintptr((*uintptr)(unsafe.Pointer(sysStat)), uintptr(-int64(n))); val+n < n {
print("runtime: stat underflow: val ", val, ", n ", n, "\n")
exit(2)
}
package runtime
-import "unsafe"
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
const debugStackBarrier = false
if usesLR {
lrUintptr = frame.sp
} else {
- lrUintptr = frame.fp - regSize
+ lrUintptr = frame.fp - sys.RegSize
}
- lrPtr := (*uintreg)(unsafe.Pointer(lrUintptr))
+ lrPtr := (*sys.Uintreg)(unsafe.Pointer(lrUintptr))
if debugStackBarrier {
print("install stack barrier at ", hex(lrUintptr), " over ", hex(*lrPtr), ", goid=", gp.goid, "\n")
if uintptr(*lrPtr) != frame.lr {
stkbar := &gp.stkbar[len(gp.stkbar)-1]
stkbar.savedLRPtr = lrUintptr
stkbar.savedLRVal = uintptr(*lrPtr)
- *lrPtr = uintreg(stackBarrierPC)
+ *lrPtr = sys.Uintreg(stackBarrierPC)
return true
}
if debugStackBarrier {
print("remove stack barrier at ", hex(stkbar.savedLRPtr), " with ", hex(stkbar.savedLRVal), ", goid=", gp.goid, "\n")
}
- lrPtr := (*uintreg)(unsafe.Pointer(stkbar.savedLRPtr))
- if val := *lrPtr; val != uintreg(stackBarrierPC) {
+ lrPtr := (*sys.Uintreg)(unsafe.Pointer(stkbar.savedLRPtr))
+ if val := *lrPtr; val != sys.Uintreg(stackBarrierPC) {
printlock()
print("at *", hex(stkbar.savedLRPtr), " expected stack barrier PC ", hex(stackBarrierPC), ", found ", hex(val), ", goid=", gp.goid, "\n")
print("gp.stkbar=")
print(", gp.stkbarPos=", gp.stkbarPos, ", gp.stack=[", hex(gp.stack.lo), ",", hex(gp.stack.hi), ")\n")
throw("stack barrier lost")
}
- *lrPtr = uintreg(stkbar.savedLRVal)
+ *lrPtr = sys.Uintreg(stkbar.savedLRVal)
}
// gcPrintStkbars prints a []stkbar for debugging.
package runtime
-import "unsafe"
+import (
+ "runtime/internal/atomic"
+ "unsafe"
+)
// Integrated network poller (platform-independent part).
// A particular implementation (epoll/kqueue) must define the following functions:
//go:linkname net_runtime_pollServerInit net.runtime_pollServerInit
func net_runtime_pollServerInit() {
netpollinit()
- atomicstore(&netpollInited, 1)
+ atomic.Store(&netpollInited, 1)
}
func netpollinited() bool {
- return atomicload(&netpollInited) != 0
+ return atomic.Load(&netpollInited) != 0
}
//go:linkname net_runtime_pollOpen net.runtime_pollOpen
}
func netpollblockcommit(gp *g, gpp unsafe.Pointer) bool {
- return casuintptr((*uintptr)(gpp), pdWait, uintptr(unsafe.Pointer(gp)))
+ return atomic.Casuintptr((*uintptr)(gpp), pdWait, uintptr(unsafe.Pointer(gp)))
}
// returns true if IO is ready, or false if timedout or closed
if old != 0 {
throw("netpollblock: double wait")
}
- if casuintptr(gpp, 0, pdWait) {
+ if atomic.Casuintptr(gpp, 0, pdWait) {
break
}
}
gopark(netpollblockcommit, unsafe.Pointer(gpp), "IO wait", traceEvGoBlockNet, 5)
}
// be careful to not lose concurrent READY notification
- old := xchguintptr(gpp, 0)
+ old := atomic.Xchguintptr(gpp, 0)
if old > pdWait {
throw("netpollblock: corrupted state")
}
if ioready {
new = pdReady
}
- if casuintptr(gpp, old, new) {
+ if atomic.Casuintptr(gpp, old, new) {
if old == pdReady || old == pdWait {
old = 0
}
// Routines that are implemented in assembly in asm_{amd64,386,arm,arm64,ppc64x}.s
-// +build ignore
+// +build mips64 mips64le
package runtime
//go:nosplit
func semawakeup(mp *m) {
- mach_semrelease(uint32(mp.waitsema))
+ mach_semrelease(mp.waitsema)
}
//go:nosplit
-func semacreate() uintptr {
- var x uintptr
+func semacreate(mp *m) {
+ if mp.waitsema != 0 {
+ return
+ }
systemstack(func() {
- x = uintptr(mach_semcreate())
+ mp.waitsema = mach_semcreate()
})
- return x
}
// BSD interface for threading.
// May run with m.p==nil, so write barriers are not allowed.
//go:nowritebarrier
func newosproc(mp *m, stk unsafe.Pointer) {
- mp.tls[0] = uintptr(mp.id) // so 386 asm can find it
if false {
- print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " id=", mp.id, "/", int(mp.tls[0]), " ostk=", &mp, "\n")
+ print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " id=", mp.id, " ostk=", &mp, "\n")
}
var oset uint32
if ns >= 0 {
var nsecs int32
secs := timediv(ns, 1000000000, &nsecs)
- r := mach_semaphore_timedwait(uint32(_g_.m.waitsema), uint32(secs), uint32(nsecs))
+ r := mach_semaphore_timedwait(_g_.m.waitsema, uint32(secs), uint32(nsecs))
if r == _KERN_ABORTED || r == _KERN_OPERATION_TIMED_OUT {
return -1
}
}
for {
- r := mach_semaphore_wait(uint32(_g_.m.waitsema))
+ r := mach_semaphore_wait(_g_.m.waitsema)
if r == 0 {
break
}
//go:nowritebarrier
func newosproc(mp *m, stk unsafe.Pointer) {
if false {
- print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " lwp_start=", funcPC(lwp_start), " id=", mp.id, "/", mp.tls[0], " ostk=", &mp, "\n")
+ print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " lwp_start=", funcPC(lwp_start), " id=", mp.id, " ostk=", &mp, "\n")
}
var oset sigset
tid2: nil,
}
- mp.tls[0] = uintptr(mp.id) // XXX so 386 asm can find it
-
lwp_create(¶ms)
sigprocmask(_SIG_SETMASK, &oset, nil)
}
package runtime
-import "unsafe"
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
// From FreeBSD's <sys/sysctl.h>
const (
//go:nowritebarrier
func newosproc(mp *m, stk unsafe.Pointer) {
if false {
- print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " thr_start=", funcPC(thr_start), " id=", mp.id, "/", mp.tls[0], " ostk=", &mp, "\n")
+ print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " thr_start=", funcPC(thr_start), " id=", mp.id, " ostk=", &mp, "\n")
}
// NOTE(rsc): This code is confused. stackbase is the top of the stack
tls_base: unsafe.Pointer(&mp.tls[0]),
tls_size: unsafe.Sizeof(mp.tls),
}
- mp.tls[0] = uintptr(mp.id) // so 386 asm can find it
var oset sigset
sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
// m.procid is a uint64, but thr_new writes a uint32 on 32-bit systems.
// Fix it up. (Only matters on big-endian, but be clean anyway.)
- if ptrSize == 4 {
+ if sys.PtrSize == 4 {
_g_.m.procid = uint64(*(*uint32)(unsafe.Pointer(&_g_.m.procid)))
}
package runtime
-import "unsafe"
-
-var sigset_all sigset = sigset{^uint32(0), ^uint32(0)}
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
// Linux futex.
//
// But on real 64-bit systems, where words are larger but the stack limit
// is not, even timediv is too heavy, and we really need to use just an
// ordinary machine instruction.
- if ptrSize == 8 {
+ if sys.PtrSize == 8 {
ts.set_sec(ns / 1000000000)
ts.set_nsec(int32(ns % 1000000000))
} else {
func getproccount() int32 {
// This buffer is huge (8 kB) but we are on the system stack
- // and there should be plenty of space (64 kB) -- except on ARM where
- // the system stack itself is only 8kb (see golang.org/issue/11873).
+ // and there should be plenty of space (64 kB).
// Also this is a leaf, so we're not holding up the memory for long.
// See golang.org/issue/11823.
// The suggested behavior here is to keep trying with ever-larger
// buffers, but we don't have a dynamic memory allocator at the
// moment, so that's a bit tricky and seems like overkill.
- const maxCPUs = 64*1024*(1-goarch_arm) + 1024*goarch_arm
- var buf [maxCPUs / (ptrSize * 8)]uintptr
+ const maxCPUs = 64 * 1024
+ var buf [maxCPUs / (sys.PtrSize * 8)]uintptr
r := sched_getaffinity(0, unsafe.Sizeof(buf), &buf[0])
n := int32(0)
- for _, v := range buf[:r/ptrSize] {
+ for _, v := range buf[:r/sys.PtrSize] {
for v != 0 {
n += int32(v & 1)
v >>= 1
/*
* note: strace gets confused if we use CLONE_PTRACE here.
*/
- mp.tls[0] = uintptr(mp.id) // so 386 asm can find it
if false {
- print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " clone=", funcPC(clone), " id=", mp.id, "/", mp.tls[0], " ostk=", &mp, "\n")
+ print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " clone=", funcPC(clone), " id=", mp.id, " ostk=", &mp, "\n")
}
// Disable signals during clone, so that the new thread starts
nmask := *(*sigset)(unsafe.Pointer(&_g_.m.sigmask))
for i := range sigtable {
if sigtable[i].flags&_SigUnblock != 0 {
- nmask[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31)
+ sigdelset(&nmask, i)
}
}
rtsigprocmask(_SIG_SETMASK, &nmask, nil, int32(unsafe.Sizeof(nmask)))
if restart {
sa.sa_flags |= _SA_RESTART
}
- sa.sa_mask = ^uint64(0)
+ sigfillset(&sa.sa_mask)
// Although Linux manpage says "sa_restorer element is obsolete and
// should not be used". x86_64 kernel requires it. Only use it on
// x86.
fn = funcPC(sigtramp)
}
sa.sa_handler = fn
- if rt_sigaction(uintptr(i), &sa, nil, unsafe.Sizeof(sa.sa_mask)) != 0 {
+ // Qemu rejects rt_sigaction of SIGRTMAX (64).
+ if rt_sigaction(uintptr(i), &sa, nil, unsafe.Sizeof(sa.sa_mask)) != 0 && i != 64 {
throw("rt_sigaction failure")
}
}
func updatesigmask(m sigmask) {
var mask sigset
- copy(mask[:], m[:])
+ sigcopyset(&mask, m)
rtsigprocmask(_SIG_SETMASK, &mask, nil, int32(unsafe.Sizeof(mask)))
}
func unblocksig(sig int32) {
var mask sigset
- mask[(sig-1)/32] |= 1 << ((uint32(sig) - 1) & 31)
+ sigaddset(&mask, int(sig))
rtsigprocmask(_SIG_UNBLOCK, &mask, nil, int32(unsafe.Sizeof(mask)))
}
--- /dev/null
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !mips64
+// +build !mips64le
+// +build linux
+
+package runtime
+
+var sigset_all = sigset{^uint32(0), ^uint32(0)}
+
+func sigaddset(mask *sigset, i int) {
+ (*mask)[(i-1)/32] |= 1 << ((uint32(i) - 1) & 31)
+}
+
+func sigdelset(mask *sigset, i int) {
+ (*mask)[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31)
+}
+
+func sigfillset(mask *uint64) {
+ *mask = ^uint64(0)
+}
+
+func sigcopyset(mask *sigset, m sigmask) {
+ copy((*mask)[:], m[:])
+}
--- /dev/null
+// Copyright 2015 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 mips64 mips64le
+// +build linux
+
+package runtime
+
+var sigset_all = sigset{^uint64(0), ^uint64(0)}
+
+func sigaddset(mask *sigset, i int) {
+ (*mask)[(i-1)/64] |= 1 << ((uint32(i) - 1) & 63)
+}
+
+func sigdelset(mask *sigset, i int) {
+ (*mask)[(i-1)/64] &^= 1 << ((uint32(i) - 1) & 63)
+}
+
+func sigfillset(mask *[2]uint64) {
+ (*mask)[0], (*mask)[1] = ^uint64(0), ^uint64(0)
+}
+
+func sigcopyset(mask *sigset, m sigmask) {
+ (*mask)[0] = uint64(m[0]) | uint64(m[1])<<32
+}
}
//go:nosplit
-func semacreate() uintptr {
- var cond uintptr
+func semacreate(mp *m) {
+ if mp.waitsema != 0 {
+ return
+ }
systemstack(func() {
mu := nacl_mutex_create(0)
if mu < 0 {
}
c := nacl_cond_create(0)
if c < 0 {
- print("nacl_cond_create: error ", -cond, "\n")
+ print("nacl_cond_create: error ", -c, "\n")
throw("semacreate")
}
- cond = uintptr(c)
- _g_ := getg()
- _g_.m.waitsemalock = uint32(mu)
+ mp.waitsema = c
+ mp.waitsemalock = mu
})
- return cond
}
//go:nosplit
systemstack(func() {
_g_ := getg()
- if nacl_mutex_lock(int32(_g_.m.waitsemalock)) < 0 {
+ if nacl_mutex_lock(_g_.m.waitsemalock) < 0 {
throw("semasleep")
}
for _g_.m.waitsemacount == 0 {
if ns < 0 {
- if nacl_cond_wait(int32(_g_.m.waitsema), int32(_g_.m.waitsemalock)) < 0 {
+ if nacl_cond_wait(_g_.m.waitsema, _g_.m.waitsemalock) < 0 {
throw("semasleep")
}
} else {
end := ns + nanotime()
ts.tv_sec = end / 1e9
ts.tv_nsec = int32(end % 1e9)
- r := nacl_cond_timed_wait_abs(int32(_g_.m.waitsema), int32(_g_.m.waitsemalock), &ts)
+ r := nacl_cond_timed_wait_abs(_g_.m.waitsema, _g_.m.waitsemalock, &ts)
if r == -_ETIMEDOUT {
- nacl_mutex_unlock(int32(_g_.m.waitsemalock))
+ nacl_mutex_unlock(_g_.m.waitsemalock)
ret = -1
return
}
}
_g_.m.waitsemacount = 0
- nacl_mutex_unlock(int32(_g_.m.waitsemalock))
+ nacl_mutex_unlock(_g_.m.waitsemalock)
ret = 0
})
return ret
//go:nosplit
func semawakeup(mp *m) {
systemstack(func() {
- if nacl_mutex_lock(int32(mp.waitsemalock)) < 0 {
+ if nacl_mutex_lock(mp.waitsemalock) < 0 {
throw("semawakeup")
}
if mp.waitsemacount != 0 {
throw("semawakeup")
}
mp.waitsemacount = 1
- nacl_cond_signal(int32(mp.waitsema))
- nacl_mutex_unlock(int32(mp.waitsemalock))
+ nacl_cond_signal(mp.waitsema)
+ nacl_mutex_unlock(mp.waitsemalock)
})
}
package runtime
-import "unsafe"
+import (
+ "runtime/internal/atomic"
+ "unsafe"
+)
const (
_ESRCH = 3
}
//go:nosplit
-func semacreate() uintptr {
- return 1
+func semacreate(mp *m) {
}
//go:nosplit
}
for {
- v := atomicload(&_g_.m.waitsemacount)
+ v := atomic.Load(&_g_.m.waitsemacount)
if v > 0 {
- if cas(&_g_.m.waitsemacount, v, v-1) {
+ if atomic.Cas(&_g_.m.waitsemacount, v, v-1) {
return 0 // semaphore acquired
}
continue
//go:nosplit
func semawakeup(mp *m) {
- xadd(&mp.waitsemacount, 1)
+ atomic.Xadd(&mp.waitsemacount, 1)
// From NetBSD's _lwp_unpark(2) manual:
// "If the target LWP is not currently waiting, it will return
// immediately upon the next call to _lwp_park()."
//go:nowritebarrier
func newosproc(mp *m, stk unsafe.Pointer) {
if false {
- print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " id=", mp.id, "/", int32(mp.tls[0]), " ostk=", &mp, "\n")
+ print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " id=", mp.id, " ostk=", &mp, "\n")
}
- mp.tls[0] = uintptr(mp.id) // so 386 asm can find it
-
var uc ucontextt
getcontext(unsafe.Pointer(&uc))
package runtime
-import "unsafe"
+import (
+ "runtime/internal/atomic"
+ "unsafe"
+)
const (
_ESRCH = 3
}
//go:nosplit
-func semacreate() uintptr {
- return 1
+func semacreate(mp *m) {
}
//go:nosplit
}
for {
- v := atomicload(&_g_.m.waitsemacount)
+ v := atomic.Load(&_g_.m.waitsemacount)
if v > 0 {
- if cas(&_g_.m.waitsemacount, v, v-1) {
+ if atomic.Cas(&_g_.m.waitsemacount, v, v-1) {
return 0 // semaphore acquired
}
continue
//go:nosplit
func semawakeup(mp *m) {
- xadd(&mp.waitsemacount, 1)
+ atomic.Xadd(&mp.waitsemacount, 1)
ret := thrwakeup(uintptr(unsafe.Pointer(&mp.waitsemacount)), 1)
if ret != 0 && ret != _ESRCH {
// semawakeup can be called on signal stack.
//go:nowritebarrier
func newosproc(mp *m, stk unsafe.Pointer) {
if false {
- print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " id=", mp.id, "/", int32(mp.tls[0]), " ostk=", &mp, "\n")
+ print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " id=", mp.id, " ostk=", &mp, "\n")
}
- mp.tls[0] = uintptr(mp.id) // so 386 asm can find it
-
param := tforkt{
tf_tcb: unsafe.Pointer(&mp.tls[0]),
tf_tid: (*int32)(unsafe.Pointer(&mp.procid)),
package runtime
-import "unsafe"
+import (
+ "runtime/internal/atomic"
+ "unsafe"
+)
// Called to initialize a new m (including the bootstrap m).
// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
n := copy(buf[:], goexits)
n = copy(buf[n:], gostringnocopy(status))
pid := getpid()
- for mp := (*m)(atomicloadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink {
+ for mp := (*m)(atomic.Loadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink {
if mp.procid != pid {
postnote(mp.procid, buf[:])
}
}
//go:nosplit
-func semacreate() uintptr {
- return 1
+func semacreate(mp *m) {
}
//go:nosplit
package runtime
import (
+ "runtime/internal/atomic"
"unsafe"
)
//go:cgo_import_dynamic runtime._DuplicateHandle DuplicateHandle%7 "kernel32.dll"
//go:cgo_import_dynamic runtime._ExitProcess ExitProcess%1 "kernel32.dll"
//go:cgo_import_dynamic runtime._FreeEnvironmentStringsW FreeEnvironmentStringsW%1 "kernel32.dll"
+//go:cgo_import_dynamic runtime._GetConsoleMode GetConsoleMode%2 "kernel32.dll"
//go:cgo_import_dynamic runtime._GetEnvironmentStringsW GetEnvironmentStringsW%0 "kernel32.dll"
//go:cgo_import_dynamic runtime._GetProcAddress GetProcAddress%2 "kernel32.dll"
+//go:cgo_import_dynamic runtime._GetProcessAffinityMask GetProcessAffinityMask%3 "kernel32.dll"
//go:cgo_import_dynamic runtime._GetQueuedCompletionStatus GetQueuedCompletionStatus%5 "kernel32.dll"
//go:cgo_import_dynamic runtime._GetStdHandle GetStdHandle%1 "kernel32.dll"
//go:cgo_import_dynamic runtime._GetSystemInfo GetSystemInfo%1 "kernel32.dll"
//go:cgo_import_dynamic runtime._VirtualFree VirtualFree%3 "kernel32.dll"
//go:cgo_import_dynamic runtime._WSAGetOverlappedResult WSAGetOverlappedResult%5 "ws2_32.dll"
//go:cgo_import_dynamic runtime._WaitForSingleObject WaitForSingleObject%2 "kernel32.dll"
+//go:cgo_import_dynamic runtime._WriteConsoleW WriteConsoleW%5 "kernel32.dll"
//go:cgo_import_dynamic runtime._WriteFile WriteFile%5 "kernel32.dll"
//go:cgo_import_dynamic runtime._timeBeginPeriod timeBeginPeriod%1 "winmm.dll"
_DuplicateHandle,
_ExitProcess,
_FreeEnvironmentStringsW,
+ _GetConsoleMode,
_GetEnvironmentStringsW,
_GetProcAddress,
+ _GetProcessAffinityMask,
_GetQueuedCompletionStatus,
_GetStdHandle,
_GetSystemInfo,
_VirtualFree,
_WSAGetOverlappedResult,
_WaitForSingleObject,
+ _WriteConsoleW,
_WriteFile,
_timeBeginPeriod stdFunction
}
func getproccount() int32 {
+ var mask, sysmask uintptr
+ ret := stdcall3(_GetProcessAffinityMask, currentProcess, uintptr(unsafe.Pointer(&mask)), uintptr(unsafe.Pointer(&sysmask)))
+ if ret != 0 {
+ n := 0
+ maskbits := int(unsafe.Sizeof(mask) * 8)
+ for i := 0; i < maskbits; i++ {
+ if mask&(1<<uint(i)) != 0 {
+ n++
+ }
+ }
+ if n != 0 {
+ return int32(n)
+ }
+ }
+ // use GetSystemInfo if GetProcessAffinityMask fails
var info systeminfo
stdcall1(_GetSystemInfo, uintptr(unsafe.Pointer(&info)))
return int32(info.dwnumberofprocessors)
// assume fd is real windows handle.
handle = fd
}
+ isASCII := true
+ b := (*[1 << 30]byte)(buf)[:n]
+ for _, x := range b {
+ if x >= 0x80 {
+ isASCII = false
+ break
+ }
+ }
+
+ if !isASCII {
+ var m uint32
+ isConsole := stdcall2(_GetConsoleMode, handle, uintptr(unsafe.Pointer(&m))) != 0
+ // If this is a console output, various non-unicode code pages can be in use.
+ // Use the dedicated WriteConsole call to ensure unicode is printed correctly.
+ if isConsole {
+ return int32(writeConsole(handle, buf, n))
+ }
+ }
var written uint32
stdcall5(_WriteFile, handle, uintptr(buf), uintptr(n), uintptr(unsafe.Pointer(&written)), 0)
return int32(written)
}
+var (
+ utf16ConsoleBack [1000]uint16
+ utf16ConsoleBackLock mutex
+)
+
+// writeConsole writes bufLen bytes from buf to the console File.
+// It returns the number of bytes written.
+func writeConsole(handle uintptr, buf unsafe.Pointer, bufLen int32) int {
+ const surr2 = (surrogateMin + surrogateMax + 1) / 2
+
+ // Do not use defer for unlock. May cause issues when printing a panic.
+ lock(&utf16ConsoleBackLock)
+
+ b := (*[1 << 30]byte)(buf)[:bufLen]
+ s := *(*string)(unsafe.Pointer(&b))
+
+ utf16tmp := utf16ConsoleBack[:]
+
+ total := len(s)
+ w := 0
+ for len(s) > 0 {
+ if w >= len(utf16tmp)-2 {
+ writeConsoleUTF16(handle, utf16tmp[:w])
+ w = 0
+ }
+ r, n := charntorune(s)
+ s = s[n:]
+ if r < 0x10000 {
+ utf16tmp[w] = uint16(r)
+ w++
+ } else {
+ r -= 0x10000
+ utf16tmp[w] = surrogateMin + uint16(r>>10)&0x3ff
+ utf16tmp[w+1] = surr2 + uint16(r)&0x3ff
+ w += 2
+ }
+ }
+ writeConsoleUTF16(handle, utf16tmp[:w])
+ unlock(&utf16ConsoleBackLock)
+ return total
+}
+
+// writeConsoleUTF16 is the dedicated windows calls that correctly prints
+// to the console regardless of the current code page. Input is utf-16 code points.
+// The handle must be a console handle.
+func writeConsoleUTF16(handle uintptr, b []uint16) {
+ l := uint32(len(b))
+ if l == 0 {
+ return
+ }
+ var written uint32
+ stdcall5(_WriteConsoleW,
+ handle,
+ uintptr(unsafe.Pointer(&b[0])),
+ uintptr(l),
+ uintptr(unsafe.Pointer(&written)),
+ 0,
+ )
+ return
+}
+
//go:nosplit
func semasleep(ns int64) int32 {
// store ms in ns to save stack space
}
//go:nosplit
-func semacreate() uintptr {
- return stdcall4(_CreateEventA, 0, 0, 0, 0)
+func semacreate(mp *m) {
+ if mp.waitsema != 0 {
+ return
+ }
+ mp.waitsema = stdcall4(_CreateEventA, 0, 0, 0, 0)
}
// May run with m.p==nil, so write barriers are not allowed.
func minit() {
var thandle uintptr
stdcall7(_DuplicateHandle, currentProcess, currentThread, currentProcess, uintptr(unsafe.Pointer(&thandle)), 0, 0, _DUPLICATE_SAME_ACCESS)
- atomicstoreuintptr(&getg().m.thread, thandle)
+ atomic.Storeuintptr(&getg().m.thread, thandle)
}
// Called from dropm to undo the effect of an minit.
rbuf := make([]byte, unsafe.Sizeof(*r)+15)
tls := &mp.tls[0]
- if mp == &m0 {
- tls = &tls0[0]
- }
gp := *((**g)(unsafe.Pointer(tls)))
// align Context to 16 bytes
for {
stdcall2(_WaitForSingleObject, profiletimer, _INFINITE)
- first := (*m)(atomicloadp(unsafe.Pointer(&allm)))
+ first := (*m)(atomic.Loadp(unsafe.Pointer(&allm)))
for mp := first; mp != nil; mp = mp.alllink {
- thread := atomicloaduintptr(&mp.thread)
+ thread := atomic.Loaduintptr(&mp.thread)
// Do not profile threads blocked on Notes,
// this includes idle worker threads,
// idle timer thread, idle heap scavenger, etc.
lock(&cpuprofilerlock)
if profiletimer == 0 {
timer := stdcall3(_CreateWaitableTimerA, 0, 0, 0)
- atomicstoreuintptr(&profiletimer, timer)
+ atomic.Storeuintptr(&profiletimer, timer)
thread := stdcall6(_CreateThread, 0, 0, funcPC(profileloop), 0, 0, 0)
stdcall2(_SetThreadPriority, thread, _THREAD_PRIORITY_HIGHEST)
stdcall1(_CloseHandle, thread)
due = int64(ms) * -10000
}
stdcall6(_SetWaitableTimer, profiletimer, uintptr(unsafe.Pointer(&due)), uintptr(ms), 0, 0, 0)
- atomicstore((*uint32)(unsafe.Pointer(&getg().m.profilehz)), uint32(hz))
+ atomic.Store((*uint32)(unsafe.Pointer(&getg().m.profilehz)), uint32(hz))
}
func memlimit() uintptr {
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build !mips64
+// +build !mips64le
+// +build linux
+
package runtime
const (
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux
+// +build mips64 mips64le
+
+package runtime
+
+const (
+ _SS_DISABLE = 2
+ _NSIG = 65
+ _SI_USER = 0
+ _SIG_BLOCK = 1
+ _SIG_UNBLOCK = 2
+ _SIG_SETMASK = 3
+ _RLIMIT_AS = 6
+)
+
+type sigset [2]uint64
+
+type rlimit struct {
+ rlim_cur uintptr
+ rlim_max uintptr
+}
package runtime
-import "unsafe"
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
// May run during STW, so write barriers are not allowed.
//go:nowritebarrier
var docrash bool
var sig int
var flags int
+ var level int32
c := &sigctxt{_ureg}
notestr := gostringnocopy(note)
// to sigpanic instead. (Otherwise the trace will end at
// sigpanic and we won't get to see who faulted).
if pc != 0 {
- if regSize > ptrSize {
- sp -= ptrSize
+ if sys.RegSize > sys.PtrSize {
+ sp -= sys.PtrSize
*(*uintptr)(unsafe.Pointer(sp)) = 0
}
- sp -= ptrSize
+ sp -= sys.PtrSize
*(*uintptr)(unsafe.Pointer(sp)) = pc
c.setsp(sp)
}
print(notestr, "\n")
print("PC=", hex(c.pc()), "\n")
print("\n")
- if gotraceback(&docrash) > 0 {
+ level, _, docrash = gotraceback()
+ if level > 0 {
goroutineheader(gp)
tracebacktrap(c.pc(), c.sp(), 0, gp)
tracebackothers(gp)
}
//go:nosplit
-func semacreate() uintptr {
+func semacreate(mp *m) {
+ if mp.waitsema != 0 {
+ return
+ }
+
var sem *semt
_g_ := getg()
if sem_init(sem, 0, 0) != 0 {
throw("sem_init")
}
- return uintptr(unsafe.Pointer(sem))
+ mp.waitsema = uintptr(unsafe.Pointer(sem))
}
//go:nosplit
import "unsafe"
+type mOS struct {
+ waitsema uint32 // semaphore for parking on locks
+}
+
func bsdthread_create(stk, arg unsafe.Pointer, fn uintptr) int32
func bsdthread_register() int32
import "unsafe"
+type mOS struct{}
+
//go:noescape
func lwp_create(param *lwpparams) int32
import "unsafe"
+type mOS struct{}
+
//go:noescape
func thr_new(param *thrparam, size int32)
import "unsafe"
+type mOS struct{}
+
//go:noescape
func futex(addr unsafe.Pointer, op int32, val uint32, ts, addr2 unsafe.Pointer, val3 uint32) int32
package runtime
-import "unsafe"
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
const (
_AT_NULL = 0
n++
}
n++
- auxv := (*[1 << 28]uint32)(add(unsafe.Pointer(argv), uintptr(n)*ptrSize))
+ auxv := (*[1 << 28]uint32)(add(unsafe.Pointer(argv), uintptr(n)*sys.PtrSize))
for i := 0; auxv[i] != _AT_NULL; i += 2 {
switch auxv[i] {
package runtime
-import "unsafe"
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
const (
_AT_NULL = 0
n++
}
n++
- auxv := (*[1 << 28]uint32)(add(unsafe.Pointer(argv), uintptr(n)*ptrSize))
+ auxv := (*[1 << 28]uint32)(add(unsafe.Pointer(argv), uintptr(n)*sys.PtrSize))
for i := 0; auxv[i] != _AT_NULL; i += 2 {
switch auxv[i] {
--- /dev/null
+// Copyright 2015 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 mips64 mips64le
+// +build linux
+
+package runtime
+
+var randomNumber uint32
+
+//go:nosplit
+func cputicks() int64 {
+ // Currently cputicks() is used in blocking profiler and to seed fastrand1().
+ // nanotime() is a poor approximation of CPU ticks that is enough for the profiler.
+ // randomNumber provides better seeding of fastrand1.
+ return nanotime() + int64(randomNumber)
+}
import "unsafe"
+type mOS struct {
+ waitsema int32 // semaphore for parking on locks
+ waitsemacount int32
+ waitsemalock int32
+}
+
func nacl_exception_stack(p uintptr, size int32) int32
func nacl_exception_handler(fn uintptr, arg unsafe.Pointer) int32
func nacl_sem_create(flag int32) int32
import "unsafe"
+type mOS struct {
+ waitsemacount uint32
+}
+
//go:noescape
func setitimer(mode int32, new, old *itimerval)
package runtime
+type mOS struct {
+ waitsemacount uint32
+}
+
//go:noescape
func setitimer(mode int32, new, old *itimerval)
import "unsafe"
+type mOS struct {
+ waitsemacount uint32
+ notesig *int8
+ errstr *byte
+}
+
func closefd(fd int32) int32
//go:noescape
import "unsafe"
+type mts struct {
+ tv_sec int64
+ tv_nsec int64
+}
+
+type mscratch struct {
+ v [6]uintptr
+}
+
+type mOS struct {
+ waitsema uintptr // semaphore for parking on locks
+ perrno *int32 // pointer to tls errno
+ // these are here because they are too large to be on the stack
+ // of low-level NOSPLIT functions.
+ //LibCall libcall;
+ ts mts
+ scratch mscratch
+}
+
type libcFunc uintptr
var asmsysvicall6 libcFunc
import "unsafe"
+type mOS struct {
+ waitsema uintptr // semaphore for parking on locks
+}
+
type stdFunction *byte
//go:linkname os_sigpipe os.sigpipe
package runtime
-import "unsafe"
+import (
+ "runtime/internal/atomic"
+ "unsafe"
+)
var indexError = error(errorString("index out of range"))
case 0:
_g_.m.dying = 1
_g_.writebuf = nil
- xadd(&panicking, 1)
+ atomic.Xadd(&panicking, 1)
lock(&paniclk)
if debug.schedtrace > 0 || debug.scheddetail > 0 {
schedtrace(true)
print("[signal ", hex(gp.sig), " code=", hex(gp.sigcode0), " addr=", hex(gp.sigcode1), " pc=", hex(gp.sigpc), "]\n")
}
- var docrash bool
+ level, all, docrash := gotraceback()
_g_ := getg()
- if t := gotraceback(&docrash); t > 0 {
+ if level > 0 {
+ if gp != gp.m.curg {
+ all = true
+ }
if gp != gp.m.g0 {
print("\n")
goroutineheader(gp)
traceback(pc, sp, 0, gp)
- } else if t >= 2 || _g_.m.throwing > 0 {
+ } else if level >= 2 || _g_.m.throwing > 0 {
print("\nruntime stack:\n")
traceback(pc, sp, 0, gp)
}
- if !didothers {
+ if !didothers && all {
didothers = true
tracebackothers(gp)
}
}
unlock(&paniclk)
- if xadd(&panicking, -1) != 0 {
+ if atomic.Xadd(&panicking, -1) != 0 {
// Some other m is panicking too.
// Let it print what it needs to print.
// Wait forever without chewing up cpu.
package runtime
+import (
+ "runtime/internal/atomic"
+ "runtime/internal/sys"
+)
+
// A parfor holds state for the parallel for operation.
type parfor struct {
body func(*parfor, uint32) // executed for each element
nprocyield uint64
nosyield uint64
nsleep uint64
- pad [_CacheLineSize]byte
+ pad [sys.CacheLineSize]byte
}
func parforalloc(nthrmax uint32) *parfor {
func parfordo(desc *parfor) {
// Obtain 0-based thread index.
- tid := xadd(&desc.thrseq, 1) - 1
+ tid := atomic.Xadd(&desc.thrseq, 1) - 1
if tid >= desc.nthr {
print("tid=", tid, " nthr=", desc.nthr, "\n")
throw("parfor: invalid tid")
for {
// While there is local work,
// bump low index and execute the iteration.
- pos := xadd64(mypos, 1)
+ pos := atomic.Xadd64(mypos, 1)
begin := uint32(pos) - 1
end := uint32(pos >> 32)
if begin < end {
// increment the done counter...
if try > desc.nthr*4 && !idle {
idle = true
- xadd(&desc.done, 1)
+ atomic.Xadd(&desc.done, 1)
}
// ...if all threads have incremented the counter,
}
if desc.done+extra == desc.nthr {
if !idle {
- xadd(&desc.done, 1)
+ atomic.Xadd(&desc.done, 1)
}
goto exit
}
victimpos := &desc.thr[victim].pos
for {
// See if it has any work.
- pos := atomicload64(victimpos)
+ pos := atomic.Load64(victimpos)
begin = uint32(pos)
end = uint32(pos >> 32)
if begin+1 >= end {
break
}
if idle {
- xadd(&desc.done, -1)
+ atomic.Xadd(&desc.done, -1)
idle = false
}
begin2 := begin + (end-begin)/2
newpos := uint64(begin) | uint64(begin2)<<32
- if cas64(victimpos, pos, newpos) {
+ if atomic.Cas64(victimpos, pos, newpos) {
begin = begin2
break
}
if idle {
throw("parfor: should not be idle")
}
- atomicstore64(mypos, uint64(begin)|uint64(end)<<32)
+ atomic.Store64(mypos, uint64(begin)|uint64(end)<<32)
me.nsteal++
me.nstealcnt += uint64(end) - uint64(begin)
break
// If a caller asked not to wait for the others, exit now
// (assume that most work is already done at this point).
if !idle {
- xadd(&desc.done, 1)
+ atomic.Xadd(&desc.done, 1)
}
goto exit
} else if try < 6*desc.nthr {
}
exit:
- xadd64(&desc.nsteal, int64(me.nsteal))
- xadd64(&desc.nstealcnt, int64(me.nstealcnt))
- xadd64(&desc.nprocyield, int64(me.nprocyield))
- xadd64(&desc.nosyield, int64(me.nosyield))
- xadd64(&desc.nsleep, int64(me.nsleep))
+ atomic.Xadd64(&desc.nsteal, int64(me.nsteal))
+ atomic.Xadd64(&desc.nstealcnt, int64(me.nstealcnt))
+ atomic.Xadd64(&desc.nprocyield, int64(me.nprocyield))
+ atomic.Xadd64(&desc.nosyield, int64(me.nosyield))
+ atomic.Xadd64(&desc.nsleep, int64(me.nsleep))
me.nsteal = 0
me.nstealcnt = 0
me.nprocyield = 0
}
}
+//go:noinline
func allocateTransient2M() {
- // prevent inlining
- if memSink == nil {
- panic("bad")
- }
memSink = make([]byte, 2<<20)
}
tests := []string{
fmt.Sprintf(`%v: %v \[%v: %v\] @ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+
-# 0x[0-9,a-f]+ runtime/pprof_test\.allocatePersistent1K\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test\.go:43
-# 0x[0-9,a-f]+ runtime/pprof_test\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test\.go:66
+# 0x[0-9,a-f]+ runtime/pprof_test\.allocatePersistent1K\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test\.go:40
+# 0x[0-9,a-f]+ runtime/pprof_test\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test\.go:63
`, 32*memoryProfilerRun, 1024*memoryProfilerRun, 32*memoryProfilerRun, 1024*memoryProfilerRun),
fmt.Sprintf(`0: 0 \[%v: %v\] @ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+
# 0x[0-9,a-f]+ runtime/pprof_test\.allocateTransient1M\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:21
-# 0x[0-9,a-f]+ runtime/pprof_test\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:64
+# 0x[0-9,a-f]+ runtime/pprof_test\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:61
`, (1<<10)*memoryProfilerRun, (1<<20)*memoryProfilerRun),
fmt.Sprintf(`0: 0 \[%v: %v\] @ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+
-# 0x[0-9,a-f]+ runtime/pprof_test\.allocateTransient2M\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:30
-# 0x[0-9,a-f]+ runtime/pprof_test\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:65
+# 0x[0-9,a-f]+ runtime/pprof_test\.allocateTransient2M\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:27
+# 0x[0-9,a-f]+ runtime/pprof_test\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:62
`, memoryProfilerRun, (2<<20)*memoryProfilerRun),
}
func bytes(s string) (ret []byte) {
rp := (*slice)(unsafe.Pointer(&ret))
- sp := (*_string)(noescape(unsafe.Pointer(&s)))
- rp.array = unsafe.Pointer(sp.str)
+ sp := stringStructOf(&s)
+ rp.array = sp.str
rp.len = sp.len
rp.cap = sp.len
return
print("\n")
}
-func printpc(p unsafe.Pointer) {
- print("PC=", hex(uintptr(p)))
-}
-
func printbool(v bool) {
if v {
print("true")
}
}
-func printbyte(c byte) {
- gwrite((*[1]byte)(unsafe.Pointer(&c))[:])
-}
-
func printfloat(v float64) {
switch {
case v != v:
printpointer(unsafe.Pointer(sp.array))
}
-func printeface(e interface{}) {
- ep := (*eface)(unsafe.Pointer(&e))
- print("(", ep._type, ",", ep.data, ")")
+func printeface(e eface) {
+ print("(", e._type, ",", e.data, ")")
}
-func printiface(i fInterface) {
- ip := (*iface)(unsafe.Pointer(&i))
- print("(", ip.tab, ",", ip.data, ")")
+func printiface(i iface) {
+ print("(", i.tab, ",", i.data, ")")
}
package runtime
-import "unsafe"
+import (
+ "runtime/internal/atomic"
+ "runtime/internal/sys"
+ "unsafe"
+)
// Goroutine scheduler
// The scheduler's job is to distribute ready-to-run goroutines over worker threads.
// Max stack size is 1 GB on 64-bit, 250 MB on 32-bit.
// Using decimal instead of binary GB and MB because
// they look nicer in the stack overflow failure message.
- if ptrSize == 8 {
+ if sys.PtrSize == 8 {
maxstacksize = 1000000000
} else {
maxstacksize = 250000000
if forcegc.idle != 0 {
throw("forcegc: phase error")
}
- atomicstore(&forcegc.idle, 1)
+ atomic.Store(&forcegc.idle, 1)
goparkunlock(&forcegc.lock, "force gc (idle)", traceEvGoBlock, 1)
// this goroutine is explicitly resumed by sysmon
if debug.gctrace > 0 {
println("GC forced")
}
- startGC(gcBackgroundMode, true)
+ gcStart(gcBackgroundMode, true)
}
}
// It assumes that f is a func value. Otherwise the behavior is undefined.
//go:nosplit
func funcPC(f interface{}) uintptr {
- return **(**uintptr)(add(unsafe.Pointer(&f), ptrSize))
+ return **(**uintptr)(add(unsafe.Pointer(&f), sys.PtrSize))
}
// called from assembly
lock(&allglock)
allgs = append(allgs, gp)
- allg = &allgs[0]
allglen = uintptr(len(allgs))
unlock(&allglock)
}
throw("unknown runnable goroutine during bootstrap")
}
- if buildVersion == "" {
+ if sys.BuildVersion == "" {
// Condition should never trigger. This code just serves
// to ensure runtime·buildVersion is kept in the resulting binary.
- buildVersion = "unknown"
+ sys.BuildVersion = "unknown"
}
}
// status is Gwaiting or Gscanwaiting, make Grunnable and put on runq
casgstatus(gp, _Gwaiting, _Grunnable)
runqput(_g_.m.p.ptr(), gp, true)
- if atomicload(&sched.npidle) != 0 && atomicload(&sched.nmspinning) == 0 { // TODO: fast atomic
+ if atomic.Load(&sched.npidle) != 0 && atomic.Load(&sched.nmspinning) == 0 { // TODO: fast atomic
wakep()
}
_g_.m.locks--
- if _g_.m.locks == 0 && _g_.preempt { // restore the preemption request in case we've cleared it in newstack
+ if _g_.m.locks == 0 && _g_.preempt { // restore the preemption request in Case we've cleared it in newstack
_g_.stackguard0 = stackPreempt
}
}
for i := 0; i < 5; i++ {
// this should tell the scheduler to not start any new goroutines
sched.stopwait = freezeStopWait
- atomicstore(&sched.gcwaiting, 1)
+ atomic.Store(&sched.gcwaiting, 1)
// this should stop running goroutines
if !preemptall() {
break // no running goroutines
// castogscanstatus, casfrom_Gscanstatus.
//go:nosplit
func readgstatus(gp *g) uint32 {
- return atomicload(&gp.atomicstatus)
+ return atomic.Load(&gp.atomicstatus)
}
// Ownership of gscanvalid:
_Gscanrunning,
_Gscansyscall:
if newval == oldval&^_Gscan {
- success = cas(&gp.atomicstatus, oldval, newval)
+ success = atomic.Cas(&gp.atomicstatus, oldval, newval)
}
case _Gscanenqueue:
if newval == _Gwaiting {
- success = cas(&gp.atomicstatus, oldval, newval)
+ success = atomic.Cas(&gp.atomicstatus, oldval, newval)
}
}
if !success {
_Gwaiting,
_Gsyscall:
if newval == oldval|_Gscan {
- return cas(&gp.atomicstatus, oldval, newval)
+ return atomic.Cas(&gp.atomicstatus, oldval, newval)
}
case _Grunning:
if newval == _Gscanrunning || newval == _Gscanenqueue {
- return cas(&gp.atomicstatus, oldval, newval)
+ return atomic.Cas(&gp.atomicstatus, oldval, newval)
}
}
print("runtime: castogscanstatus oldval=", hex(oldval), " newval=", hex(newval), "\n")
// loop if gp->atomicstatus is in a scan state giving
// GC time to finish and change the state to oldval.
- for !cas(&gp.atomicstatus, oldval, newval) {
+ for !atomic.Cas(&gp.atomicstatus, oldval, newval) {
if oldval == _Gwaiting && gp.atomicstatus == _Grunnable {
systemstack(func() {
throw("casgstatus: waiting for Gwaiting but is Grunnable")
if oldstatus != _Gwaiting && oldstatus != _Grunnable {
throw("copystack: bad status, not Gwaiting or Grunnable")
}
- if cas(&gp.atomicstatus, oldstatus, _Gcopystack) {
+ if atomic.Cas(&gp.atomicstatus, oldstatus, _Gcopystack) {
return oldstatus
}
}
if !gp.gcscandone {
// Coordinate with traceback
// in sigprof.
- for !cas(&gp.stackLock, 0, 1) {
+ for !atomic.Cas(&gp.stackLock, 0, 1) {
osyield()
}
scanstack(gp)
- atomicstore(&gp.stackLock, 0)
+ atomic.Store(&gp.stackLock, 0)
gp.gcscandone = true
}
restartg(gp)
lock(&sched.lock)
sched.stopwait = gomaxprocs
- atomicstore(&sched.gcwaiting, 1)
+ atomic.Store(&sched.gcwaiting, 1)
preemptall()
// stop current P
_g_.m.p.ptr().status = _Pgcstop // Pgcstop is only diagnostic.
for i := 0; i < int(gomaxprocs); i++ {
p := allp[i]
s := p.status
- if s == _Psyscall && cas(&p.status, s, _Pgcstop) {
+ if s == _Psyscall && atomic.Cas(&p.status, s, _Pgcstop) {
if trace.enabled {
traceGoSysBlock(p)
traceProcStop(p)
// Wakeup an additional proc in case we have excessive runnable goroutines
// in local queues or in the global queue. If we don't, the proc will park itself.
// If we have lots of excessive work, resetspinning will unpark additional procs as necessary.
- if atomicload(&sched.npidle) != 0 && atomicload(&sched.nmspinning) == 0 {
+ if atomic.Load(&sched.npidle) != 0 && atomic.Load(&sched.nmspinning) == 0 {
wakep()
}
// Cgo may have left stack size in stack.hi.
size := _g_.stack.hi
if size == 0 {
- size = 8192 * stackGuardMultiplier
+ size = 8192 * sys.StackGuardMultiplier
}
_g_.stack.hi = uintptr(noescape(unsafe.Pointer(&size)))
_g_.stack.lo = _g_.stack.hi - size + 1024
// memory barrier. GC uses this as a "ragged barrier."
//
// The caller must hold worldsema.
+//
+//go:systemstack
func forEachP(fn func(*p)) {
mp := acquirem()
_p_ := getg().m.p.ptr()
// Ask all Ps to run the safe point function.
for _, p := range allp[:gomaxprocs] {
if p != _p_ {
- atomicstore(&p.runSafePointFn, 1)
+ atomic.Store(&p.runSafePointFn, 1)
}
}
preemptall()
// Run safe point function for all idle Ps. sched.pidle will
// not change because we hold sched.lock.
for p := sched.pidle.ptr(); p != nil; p = p.link.ptr() {
- if cas(&p.runSafePointFn, 1, 0) {
+ if atomic.Cas(&p.runSafePointFn, 1, 0) {
fn(p)
sched.safePointWait--
}
for i := 0; i < int(gomaxprocs); i++ {
p := allp[i]
s := p.status
- if s == _Psyscall && p.runSafePointFn == 1 && cas(&p.status, s, _Pidle) {
+ if s == _Psyscall && p.runSafePointFn == 1 && atomic.Cas(&p.status, s, _Pidle) {
if trace.enabled {
traceGoSysBlock(p)
traceProcStop(p)
for {
// Wait for 100us, then try to re-preempt in
// case of any races.
+ //
+ // Requires system stack.
if notetsleep(&sched.safePointNote, 100*1000) {
noteclear(&sched.safePointNote)
break
// Resolve the race between forEachP running the safe-point
// function on this P's behalf and this P running the
// safe-point function directly.
- if !cas(&p.runSafePointFn, 1, 0) {
+ if !atomic.Cas(&p.runSafePointFn, 1, 0) {
return
}
sched.safePointFn(p)
if iscgo || GOOS == "solaris" || GOOS == "windows" || GOOS == "plan9" {
mp.g0 = malg(-1)
} else {
- mp.g0 = malg(8192 * stackGuardMultiplier)
+ mp.g0 = malg(8192 * sys.StackGuardMultiplier)
}
mp.g0.m = mp
// the goroutine stack ends.
mp := allocm(nil, nil)
gp := malg(4096)
- gp.sched.pc = funcPC(goexit) + _PCQuantum
+ gp.sched.pc = funcPC(goexit) + sys.PCQuantum
gp.sched.sp = gp.stack.hi
- gp.sched.sp -= 4 * regSize // extra space in case of reads slightly beyond frame
+ gp.sched.sp -= 4 * sys.RegSize // extra space in case of reads slightly beyond frame
gp.sched.lr = 0
gp.sched.g = guintptr(unsafe.Pointer(gp))
gp.syscallpc = gp.sched.pc
mp.locked = _LockInternal
mp.lockedg = gp
gp.lockedm = mp
- gp.goid = int64(xadd64(&sched.goidgen, 1))
+ gp.goid = int64(atomic.Xadd64(&sched.goidgen, 1))
if raceenabled {
gp.racectx = racegostart(funcPC(newextram))
}
const locked = 1
for {
- old := atomicloaduintptr(&extram)
+ old := atomic.Loaduintptr(&extram)
if old == locked {
yield := osyield
yield()
usleep(1)
continue
}
- if casuintptr(&extram, old, locked) {
+ if atomic.Casuintptr(&extram, old, locked) {
return (*m)(unsafe.Pointer(old))
}
yield := osyield
//go:nosplit
func unlockextra(mp *m) {
- atomicstoreuintptr(&extram, uintptr(unsafe.Pointer(mp)))
+ atomic.Storeuintptr(&extram, uintptr(unsafe.Pointer(mp)))
}
// Create a new m. It will start off with a call to fn, or else the scheduler.
}
if _g_.m.spinning {
_g_.m.spinning = false
- xadd(&sched.nmspinning, -1)
+ atomic.Xadd(&sched.nmspinning, -1)
}
retry:
// Something (presumably the GC) was readied while the
// runtime was starting up this M, so the M is no
// longer spinning.
- if int32(xadd(&sched.nmspinning, -1)) < 0 {
+ if int32(atomic.Xadd(&sched.nmspinning, -1)) < 0 {
throw("mspinning: nmspinning underflowed")
}
} else {
if _p_ == nil {
unlock(&sched.lock)
if spinning {
- xadd(&sched.nmspinning, -1)
+ atomic.Xadd(&sched.nmspinning, -1)
}
return
}
}
// no local work, check that there are no spinning/idle M's,
// otherwise our help is not required
- if atomicload(&sched.nmspinning)+atomicload(&sched.npidle) == 0 && cas(&sched.nmspinning, 0, 1) { // TODO: fast atomic
+ if atomic.Load(&sched.nmspinning)+atomic.Load(&sched.npidle) == 0 && atomic.Cas(&sched.nmspinning, 0, 1) { // TODO: fast atomic
startm(_p_, true)
return
}
unlock(&sched.lock)
return
}
- if _p_.runSafePointFn != 0 && cas(&_p_.runSafePointFn, 1, 0) {
+ if _p_.runSafePointFn != 0 && atomic.Cas(&_p_.runSafePointFn, 1, 0) {
sched.safePointFn(_p_)
sched.safePointWait--
if sched.safePointWait == 0 {
}
// If this is the last running P and nobody is polling network,
// need to wakeup another M to poll network.
- if sched.npidle == uint32(gomaxprocs-1) && atomicload64(&sched.lastpoll) != 0 {
+ if sched.npidle == uint32(gomaxprocs-1) && atomic.Load64(&sched.lastpoll) != 0 {
unlock(&sched.lock)
startm(_p_, false)
return
// Called when a G is made runnable (newproc, ready).
func wakep() {
// be conservative about spinning threads
- if !cas(&sched.nmspinning, 0, 1) {
+ if !atomic.Cas(&sched.nmspinning, 0, 1) {
return
}
startm(nil, true)
}
if _g_.m.spinning {
_g_.m.spinning = false
- xadd(&sched.nmspinning, -1)
+ atomic.Xadd(&sched.nmspinning, -1)
}
_p_ := releasep()
lock(&sched.lock)
// If number of spinning M's >= number of busy P's, block.
// This is necessary to prevent excessive CPU consumption
// when GOMAXPROCS>>1 but the program parallelism is low.
- if !_g_.m.spinning && 2*atomicload(&sched.nmspinning) >= uint32(gomaxprocs)-atomicload(&sched.npidle) { // TODO: fast atomic
+ if !_g_.m.spinning && 2*atomic.Load(&sched.nmspinning) >= uint32(gomaxprocs)-atomic.Load(&sched.npidle) { // TODO: fast atomic
goto stop
}
if !_g_.m.spinning {
_g_.m.spinning = true
- xadd(&sched.nmspinning, 1)
+ atomic.Xadd(&sched.nmspinning, 1)
}
// random steal from other P's
for i := 0; i < int(4*gomaxprocs); i++ {
stop:
- // We have nothing to do. If we're in the GC mark phase and can
- // safely scan and blacken objects, run idle-time marking
- // rather than give up the P.
+ // We have nothing to do. If we're in the GC mark phase, can
+ // safely scan and blacken objects, and have work to do, run
+ // idle-time marking rather than give up the P.
if _p_ := _g_.m.p.ptr(); gcBlackenEnabled != 0 && _p_.gcBgMarkWorker != nil && gcMarkWorkAvailable(_p_) {
_p_.gcMarkWorkerMode = gcMarkWorkerIdleMode
gp := _p_.gcBgMarkWorker
unlock(&sched.lock)
if _g_.m.spinning {
_g_.m.spinning = false
- xadd(&sched.nmspinning, -1)
+ atomic.Xadd(&sched.nmspinning, -1)
}
// check all runqueues once again
}
// poll network
- if netpollinited() && xchg64(&sched.lastpoll, 0) != 0 {
+ if netpollinited() && atomic.Xchg64(&sched.lastpoll, 0) != 0 {
if _g_.m.p != 0 {
throw("findrunnable: netpoll with p")
}
throw("findrunnable: netpoll with spinning")
}
gp := netpoll(true) // block until new work is available
- atomicstore64(&sched.lastpoll, uint64(nanotime()))
+ atomic.Store64(&sched.lastpoll, uint64(nanotime()))
if gp != nil {
lock(&sched.lock)
_p_ = pidleget()
var nmspinning uint32
if _g_.m.spinning {
_g_.m.spinning = false
- nmspinning = xadd(&sched.nmspinning, -1)
+ nmspinning = atomic.Xadd(&sched.nmspinning, -1)
if int32(nmspinning) < 0 {
throw("findrunnable: negative nmspinning")
}
} else {
- nmspinning = atomicload(&sched.nmspinning)
+ nmspinning = atomic.Load(&sched.nmspinning)
}
// M wakeup policy is deliberately somewhat conservative (see nmspinning handling),
// so see if we need to wakeup another P here.
- if nmspinning == 0 && atomicload(&sched.npidle) > 0 {
+ if nmspinning == 0 && atomic.Load(&sched.npidle) > 0 {
wakep()
}
}
save(pc, sp)
}
- if atomicload(&sched.sysmonwait) != 0 { // TODO: fast atomic
+ if atomic.Load(&sched.sysmonwait) != 0 { // TODO: fast atomic
systemstack(entersyscall_sysmon)
save(pc, sp)
}
_g_.sysblocktraced = true
_g_.m.mcache = nil
_g_.m.p.ptr().m = 0
- atomicstore(&_g_.m.p.ptr().status, _Psyscall)
+ atomic.Store(&_g_.m.p.ptr().status, _Psyscall)
if sched.gcwaiting != 0 {
systemstack(entersyscall_gcwait)
save(pc, sp)
func entersyscall_sysmon() {
lock(&sched.lock)
- if atomicload(&sched.sysmonwait) != 0 {
- atomicstore(&sched.sysmonwait, 0)
+ if atomic.Load(&sched.sysmonwait) != 0 {
+ atomic.Store(&sched.sysmonwait, 0)
notewakeup(&sched.sysmonnote)
}
unlock(&sched.lock)
_p_ := _g_.m.p.ptr()
lock(&sched.lock)
- if sched.stopwait > 0 && cas(&_p_.status, _Psyscall, _Pgcstop) {
+ if sched.stopwait > 0 && atomic.Cas(&_p_.status, _Psyscall, _Pgcstop) {
if trace.enabled {
traceGoSysBlock(_p_)
traceProcStop(_p_)
}
// Try to re-acquire the last P.
- if _g_.m.p != 0 && _g_.m.p.ptr().status == _Psyscall && cas(&_g_.m.p.ptr().status, _Psyscall, _Prunning) {
+ if _g_.m.p != 0 && _g_.m.p.ptr().status == _Psyscall && atomic.Cas(&_g_.m.p.ptr().status, _Psyscall, _Prunning) {
// There's a cpu for us, so we can run.
_g_.m.mcache = _g_.m.p.ptr().mcache
_g_.m.p.ptr().m.set(_g_.m)
func exitsyscallfast_pidle() bool {
lock(&sched.lock)
_p_ := pidleget()
- if _p_ != nil && atomicload(&sched.sysmonwait) != 0 {
- atomicstore(&sched.sysmonwait, 0)
+ if _p_ != nil && atomic.Load(&sched.sysmonwait) != 0 {
+ atomic.Store(&sched.sysmonwait, 0)
notewakeup(&sched.sysmonnote)
}
unlock(&sched.lock)
_p_ := pidleget()
if _p_ == nil {
globrunqput(gp)
- } else if atomicload(&sched.sysmonwait) != 0 {
- atomicstore(&sched.sysmonwait, 0)
+ } else if atomic.Load(&sched.sysmonwait) != 0 {
+ atomic.Store(&sched.sysmonwait, 0)
notewakeup(&sched.sysmonnote)
}
unlock(&sched.lock)
// copied if a stack split occurred.
//go:nosplit
func newproc(siz int32, fn *funcval) {
- argp := add(unsafe.Pointer(&fn), ptrSize)
+ argp := add(unsafe.Pointer(&fn), sys.PtrSize)
pc := getcallerpc(unsafe.Pointer(&siz))
systemstack(func() {
newproc1(fn, (*uint8)(argp), siz, 0, pc)
// Not worth it: this is almost always an error.
// 4*sizeof(uintreg): extra space added below
// sizeof(uintreg): caller's LR (arm) or return address (x86, in gostartcall).
- if siz >= _StackMin-4*regSize-regSize {
+ if siz >= _StackMin-4*sys.RegSize-sys.RegSize {
throw("newproc: function arguments too large for new goroutine")
}
throw("newproc1: new g is not Gdead")
}
- totalSize := 4*regSize + uintptr(siz) + minFrameSize // extra space in case of reads slightly beyond frame
- totalSize += -totalSize & (spAlign - 1) // align to spAlign
+ totalSize := 4*sys.RegSize + uintptr(siz) + sys.MinFrameSize // extra space in case of reads slightly beyond frame
+ totalSize += -totalSize & (sys.SpAlign - 1) // align to spAlign
sp := newg.stack.hi - totalSize
spArg := sp
if usesLR {
// caller's LR
*(*unsafe.Pointer)(unsafe.Pointer(sp)) = nil
- spArg += minFrameSize
+ prepGoExitFrame(sp)
+ spArg += sys.MinFrameSize
}
memmove(unsafe.Pointer(spArg), unsafe.Pointer(argp), uintptr(narg))
memclr(unsafe.Pointer(&newg.sched), unsafe.Sizeof(newg.sched))
newg.sched.sp = sp
newg.stktopsp = sp
- newg.sched.pc = funcPC(goexit) + _PCQuantum // +PCQuantum so that previous instruction is in same function
+ newg.sched.pc = funcPC(goexit) + sys.PCQuantum // +PCQuantum so that previous instruction is in same function
newg.sched.g = guintptr(unsafe.Pointer(newg))
gostartcallfn(&newg.sched, fn)
newg.gopc = callerpc
// Sched.goidgen is the last allocated id,
// this batch must be [sched.goidgen+1, sched.goidgen+GoidCacheBatch].
// At startup sched.goidgen=0, so main goroutine receives goid=1.
- _p_.goidcache = xadd64(&sched.goidgen, _GoidCacheBatch)
+ _p_.goidcache = atomic.Xadd64(&sched.goidgen, _GoidCacheBatch)
_p_.goidcache -= _GoidCacheBatch - 1
_p_.goidcacheend = _p_.goidcache + _GoidCacheBatch
}
}
runqput(_p_, newg, true)
- if atomicload(&sched.npidle) != 0 && atomicload(&sched.nmspinning) == 0 && unsafe.Pointer(fn.fn) != unsafe.Pointer(funcPC(main)) { // TODO: fast atomic
+ if atomic.Load(&sched.npidle) != 0 && atomic.Load(&sched.nmspinning) == 0 && unsafe.Pointer(fn.fn) != unsafe.Pointer(funcPC(main)) { // TODO: fast atomic
wakep()
}
_g_.m.locks--
if raceenabled {
racemalloc(unsafe.Pointer(gp.stack.lo), gp.stackAlloc)
}
+ if msanenabled {
+ msanmalloc(unsafe.Pointer(gp.stack.lo), gp.stackAlloc)
+ }
}
}
return gp
mp.mallocing++
// Coordinate with stack barrier insertion in scanstack.
- for !cas(&gp.stackLock, 0, 1) {
+ for !atomic.Cas(&gp.stackLock, 0, 1) {
osyield()
}
// This is especially important on windows, since all syscalls are cgo calls.
n = gentraceback(mp.curg.syscallpc, mp.curg.syscallsp, 0, mp.curg, 0, &stk[0], len(stk), nil, nil, 0)
} else if traceback {
- n = gentraceback(pc, sp, lr, gp, 0, &stk[0], len(stk), nil, nil, _TraceTrap|_TraceJumpStack)
+ flags := uint(_TraceTrap | _TraceJumpStack)
+ if gp.m.curg != nil && readgstatus(gp.m.curg) == _Gcopystack {
+ // We can traceback the system stack, but
+ // don't jump to the potentially inconsistent
+ // user stack.
+ flags &^= _TraceJumpStack
+ }
+ n = gentraceback(pc, sp, lr, gp, 0, &stk[0], len(stk), nil, nil, flags)
}
if !traceback || n <= 0 {
// Normal traceback is impossible or has failed.
n = 2
// "ExternalCode" is better than "etext".
if pc > firstmoduledata.etext {
- pc = funcPC(_ExternalCode) + _PCQuantum
+ pc = funcPC(_ExternalCode) + sys.PCQuantum
}
stk[0] = pc
if mp.preemptoff != "" || mp.helpgc != 0 {
- stk[1] = funcPC(_GC) + _PCQuantum
+ stk[1] = funcPC(_GC) + sys.PCQuantum
} else {
- stk[1] = funcPC(_System) + _PCQuantum
+ stk[1] = funcPC(_System) + sys.PCQuantum
}
}
}
- atomicstore(&gp.stackLock, 0)
+ atomic.Store(&gp.stackLock, 0)
if prof.hz != 0 {
// Simple cas-lock to coordinate with setcpuprofilerate.
- for !cas(&prof.lock, 0, 1) {
+ for !atomic.Cas(&prof.lock, 0, 1) {
osyield()
}
if prof.hz != 0 {
cpuprof.add(stk[:n])
}
- atomicstore(&prof.lock, 0)
+ atomic.Store(&prof.lock, 0)
}
mp.mallocing--
}
// it would deadlock.
resetcpuprofiler(0)
- for !cas(&prof.lock, 0, 1) {
+ for !atomic.Cas(&prof.lock, 0, 1) {
osyield()
}
prof.hz = hz
- atomicstore(&prof.lock, 0)
+ atomic.Store(&prof.lock, 0)
lock(&sched.lock)
sched.profilehz = hz
for p.runqhead != p.runqtail {
// pop from tail of local queue
p.runqtail--
- gp := p.runq[p.runqtail%uint32(len(p.runq))]
+ gp := p.runq[p.runqtail%uint32(len(p.runq))].ptr()
// push onto head of global queue
globrunqputhead(gp)
}
}
}
var int32p *int32 = &gomaxprocs // make compiler check that gomaxprocs is an int32
- atomicstore((*uint32)(unsafe.Pointer(int32p)), uint32(nprocs))
+ atomic.Store((*uint32)(unsafe.Pointer(int32p)), uint32(nprocs))
return runnablePs
}
}
mp := mget()
if mp == nil {
- newm(nil, _p_)
- } else {
- mp.nextp.set(_p_)
- notewakeup(&mp.park)
+ // There should always be a free M since
+ // nothing is running.
+ throw("checkdead: no m for timer")
}
+ mp.nextp.set(_p_)
+ notewakeup(&mp.park)
return
}
delay = 10 * 1000
}
usleep(delay)
- if debug.schedtrace <= 0 && (sched.gcwaiting != 0 || atomicload(&sched.npidle) == uint32(gomaxprocs)) { // TODO: fast atomic
+ if debug.schedtrace <= 0 && (sched.gcwaiting != 0 || atomic.Load(&sched.npidle) == uint32(gomaxprocs)) { // TODO: fast atomic
lock(&sched.lock)
- if atomicload(&sched.gcwaiting) != 0 || atomicload(&sched.npidle) == uint32(gomaxprocs) {
- atomicstore(&sched.sysmonwait, 1)
+ if atomic.Load(&sched.gcwaiting) != 0 || atomic.Load(&sched.npidle) == uint32(gomaxprocs) {
+ atomic.Store(&sched.sysmonwait, 1)
unlock(&sched.lock)
// Make wake-up period small enough
// for the sampling to be correct.
}
notetsleep(&sched.sysmonnote, maxsleep)
lock(&sched.lock)
- atomicstore(&sched.sysmonwait, 0)
+ atomic.Store(&sched.sysmonwait, 0)
noteclear(&sched.sysmonnote)
idle = 0
delay = 20
unlock(&sched.lock)
}
// poll network if not polled for more than 10ms
- lastpoll := int64(atomicload64(&sched.lastpoll))
+ lastpoll := int64(atomic.Load64(&sched.lastpoll))
now := nanotime()
unixnow := unixnanotime()
if lastpoll != 0 && lastpoll+10*1000*1000 < now {
- cas64(&sched.lastpoll, uint64(lastpoll), uint64(now))
+ atomic.Cas64(&sched.lastpoll, uint64(lastpoll), uint64(now))
gp := netpoll(false) // non-blocking - returns list of goroutines
if gp != nil {
// Need to decrement number of idle locked M's
idle++
}
// check if we need to force a GC
- lastgc := int64(atomicload64(&memstats.last_gc))
- if lastgc != 0 && unixnow-lastgc > forcegcperiod && atomicload(&forcegc.idle) != 0 && atomicloaduint(&bggc.working) == 0 {
+ lastgc := int64(atomic.Load64(&memstats.last_gc))
+ if lastgc != 0 && unixnow-lastgc > forcegcperiod && atomic.Load(&forcegc.idle) != 0 {
lock(&forcegc.lock)
forcegc.idle = 0
forcegc.g.schedlink = 0
}
// scavenge heap once in a while
if lastscavenge+scavengelimit/2 < now {
- mHeap_Scavenge(int32(nscavenge), uint64(now), uint64(scavengelimit))
+ mheap_.scavenge(int32(nscavenge), uint64(now), uint64(scavengelimit))
lastscavenge = now
nscavenge++
}
// On the one hand we don't want to retake Ps if there is no other work to do,
// but on the other hand we want to retake them eventually
// because they can prevent the sysmon thread from deep sleep.
- if runqempty(_p_) && atomicload(&sched.nmspinning)+atomicload(&sched.npidle) > 0 && pd.syscallwhen+10*1000*1000 > now {
+ if runqempty(_p_) && atomic.Load(&sched.nmspinning)+atomic.Load(&sched.npidle) > 0 && pd.syscallwhen+10*1000*1000 > now {
continue
}
// Need to decrement number of idle locked M's
// Otherwise the M from which we retake can exit the syscall,
// increment nmidle and report deadlock.
incidlelocked(-1)
- if cas(&_p_.status, s, _Pidle) {
+ if atomic.Cas(&_p_.status, s, _Pidle) {
if trace.enabled {
traceGoSysBlock(_p_)
traceProcStop(_p_)
continue
}
mp := _p_.m.ptr()
- h := atomicload(&_p_.runqhead)
- t := atomicload(&_p_.runqtail)
+ h := atomic.Load(&_p_.runqhead)
+ t := atomic.Load(&_p_.runqtail)
if detailed {
id := int32(-1)
if mp != nil {
}
_p_.link = sched.pidle
sched.pidle.set(_p_)
- xadd(&sched.npidle, 1) // TODO: fast atomic
+ atomic.Xadd(&sched.npidle, 1) // TODO: fast atomic
}
// Try get a p from _Pidle list.
_p_ := sched.pidle.ptr()
if _p_ != nil {
sched.pidle = _p_.link
- xadd(&sched.npidle, -1) // TODO: fast atomic
+ atomic.Xadd(&sched.npidle, -1) // TODO: fast atomic
}
return _p_
}
}
retry:
- h := atomicload(&_p_.runqhead) // load-acquire, synchronize with consumers
+ h := atomic.Load(&_p_.runqhead) // load-acquire, synchronize with consumers
t := _p_.runqtail
if t-h < uint32(len(_p_.runq)) {
- _p_.runq[t%uint32(len(_p_.runq))] = gp
- atomicstore(&_p_.runqtail, t+1) // store-release, makes the item available for consumption
+ _p_.runq[t%uint32(len(_p_.runq))].set(gp)
+ atomic.Store(&_p_.runqtail, t+1) // store-release, makes the item available for consumption
return
}
if runqputslow(_p_, gp, h, t) {
throw("runqputslow: queue is not full")
}
for i := uint32(0); i < n; i++ {
- batch[i] = _p_.runq[(h+i)%uint32(len(_p_.runq))]
+ batch[i] = _p_.runq[(h+i)%uint32(len(_p_.runq))].ptr()
}
- if !cas(&_p_.runqhead, h, h+n) { // cas-release, commits consume
+ if !atomic.Cas(&_p_.runqhead, h, h+n) { // cas-release, commits consume
return false
}
batch[n] = gp
}
for {
- h := atomicload(&_p_.runqhead) // load-acquire, synchronize with other consumers
+ h := atomic.Load(&_p_.runqhead) // load-acquire, synchronize with other consumers
t := _p_.runqtail
if t == h {
return nil, false
}
- gp := _p_.runq[h%uint32(len(_p_.runq))]
- if cas(&_p_.runqhead, h, h+1) { // cas-release, commits consume
+ gp := _p_.runq[h%uint32(len(_p_.runq))].ptr()
+ if atomic.Cas(&_p_.runqhead, h, h+1) { // cas-release, commits consume
return gp, false
}
}
// Batch is a ring buffer starting at batchHead.
// Returns number of grabbed goroutines.
// Can be executed by any P.
-func runqgrab(_p_ *p, batch *[256]*g, batchHead uint32, stealRunNextG bool) uint32 {
+func runqgrab(_p_ *p, batch *[256]guintptr, batchHead uint32, stealRunNextG bool) uint32 {
for {
- h := atomicload(&_p_.runqhead) // load-acquire, synchronize with other consumers
- t := atomicload(&_p_.runqtail) // load-acquire, synchronize with the producer
+ h := atomic.Load(&_p_.runqhead) // load-acquire, synchronize with other consumers
+ t := atomic.Load(&_p_.runqtail) // load-acquire, synchronize with the producer
n := t - h
n = n - n/2
if n == 0 {
if !_p_.runnext.cas(next, 0) {
continue
}
- batch[batchHead%uint32(len(batch))] = next.ptr()
+ batch[batchHead%uint32(len(batch))] = next
return 1
}
}
g := _p_.runq[(h+i)%uint32(len(_p_.runq))]
batch[(batchHead+i)%uint32(len(batch))] = g
}
- if cas(&_p_.runqhead, h, h+n) { // cas-release, commits consume
+ if atomic.Cas(&_p_.runqhead, h, h+n) { // cas-release, commits consume
return n
}
}
return nil
}
n--
- gp := _p_.runq[(t+n)%uint32(len(_p_.runq))]
+ gp := _p_.runq[(t+n)%uint32(len(_p_.runq))].ptr()
if n == 0 {
return gp
}
- h := atomicload(&_p_.runqhead) // load-acquire, synchronize with consumers
+ h := atomic.Load(&_p_.runqhead) // load-acquire, synchronize with consumers
if t-h+n >= uint32(len(_p_.runq)) {
throw("runqsteal: runq overflow")
}
- atomicstore(&_p_.runqtail, t+n) // store-release, makes the item available for consumption
+ atomic.Store(&_p_.runqtail, t+n) // store-release, makes the item available for consumption
return gp
}
}
func haveexperiment(name string) bool {
- x := goexperiment
+ x := sys.Goexperiment
for x != "" {
xname := ""
i := index(x, ",")
runtime/race package contains the data race detector runtime library.
It is based on ThreadSanitizer race detector, that is currently a part of
-the LLVM project.
+the LLVM project (http://llvm.org/git/compiler-rt.git).
-To update the .syso files you need to:
-$ svn co http://llvm.org/svn/llvm-project/compiler-rt/trunk
-$ cd compiler-rt/lib/tsan/go
-$ ./buildgo.sh
+To update the .syso files use golang.org/x/build/cmd/racebuild.
-Tested with gcc 4.6.1 and 4.7.0. On Windows it's built with 64-bit MinGW.
-
-Current runtime is built on rev 229396.
+Current runtime is built on rev 389d49d4943780efbfcd2a434f4462b6d0f23c44.
x, y int
}
+//go:noinline
func (p InterImpl) Foo(x int) {
- // prevent inlining
- z := 42
- x = 85
- y := x / z
- z = y * z
- x = z * y
- _, _, _ = x, y, z
}
type InterImpl2 InterImpl
min, max Rect
}
+//go:noinline
func NewImage() Image {
- var pleaseDoNotInlineMe stack
- pleaseDoNotInlineMe.push(1)
- _ = pleaseDoNotInlineMe.pop()
return Image{}
}
var makeChanCalls int
+//go:noinline
func makeChan() *RpcChan {
- var pleaseDoNotInlineMe stack
- pleaseDoNotInlineMe.push(1)
- _ = pleaseDoNotInlineMe.pop()
-
makeChanCalls++
c := &RpcChan{make(chan bool, 1)}
c.c <- true
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+TEXT _rt0_386_android(SB),NOSPLIT,$8
+ MOVL 8(SP), AX // argc
+ LEAL 12(SP), BX // argv
+ MOVL AX, 0(SP)
+ MOVL BX, 4(SP)
+ CALL main(SB)
+ INT $3
+
+TEXT _rt0_386_android_lib(SB),NOSPLIT,$0
+ PUSHL $_rt0_386_android_argv(SB) // argv
+ PUSHL $1 // argc
+ CALL _rt0_386_linux_lib(SB)
+ POPL AX
+ POPL AX
+ RET
+
+DATA _rt0_386_android_argv+0x00(SB)/4,$_rt0_386_android_argv0(SB)
+DATA _rt0_386_android_argv+0x04(SB)/4,$0 // argv terminate
+DATA _rt0_386_android_argv+0x08(SB)/4,$0 // envp terminate
+DATA _rt0_386_android_argv+0x0c(SB)/4,$0 // auxv terminate
+GLOBL _rt0_386_android_argv(SB),NOPTR,$0x10
+
+// TODO: wire up necessary VDSO (see os_linux_386.go)
+
+DATA _rt0_386_android_argv0(SB)/8, $"gojni"
+GLOBL _rt0_386_android_argv0(SB),RODATA,$8
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+TEXT _rt0_amd64_android(SB),NOSPLIT,$-8
+ MOVQ 0(SP), DI // argc
+ LEAQ 8(SP), SI // argv
+ MOVQ $main(SB), AX
+ JMP AX
+
+TEXT _rt0_amd64_android_lib(SB),NOSPLIT,$0
+ MOVQ $1, DI // argc
+ MOVQ $_rt0_amd64_android_argv(SB), SI // argv
+ MOVQ $_rt0_amd64_linux_lib(SB), AX
+ JMP AX
+
+DATA _rt0_amd64_android_argv+0x00(SB)/8,$_rt0_amd64_android_argv0(SB)
+DATA _rt0_amd64_android_argv+0x08(SB)/8,$0
+DATA _rt0_amd64_android_argv+0x10(SB)/8,$0
+DATA _rt0_amd64_android_argv+0x18(SB)/8,$15 // AT_PLATFORM
+DATA _rt0_amd64_android_argv+0x20(SB)/8,$_rt0_amd64_android_auxv0(SB)
+DATA _rt0_amd64_android_argv+0x28(SB)/8,$0
+GLOBL _rt0_amd64_android_argv(SB),NOPTR,$0x30
+
+// TODO: AT_HWCAP necessary? If so, what value?
+
+DATA _rt0_amd64_android_argv0(SB)/8, $"gojni"
+GLOBL _rt0_amd64_android_argv0(SB),RODATA,$8
+
+DATA _rt0_amd64_android_auxv0(SB)/8, $"x86_64"
+GLOBL _rt0_amd64_android_auxv0(SB),RODATA,$8
ADD $8, RSP, R1 // argv
BL main(SB)
+// When building with -buildmode=c-shared, this symbol is called when the shared
+// library is loaded.
+TEXT _rt0_arm64_linux_lib(SB),NOSPLIT,$40
+ // R27 is REGTMP, reserved for liblink. It is used below to
+ // move R0/R1 into globals. However in the standard ARM64 calling
+ // convention, it is a callee-saved register.
+ MOVD R27, 24(RSP)
+
+ MOVD R0, _rt0_arm64_linux_lib_argc<>(SB)
+ MOVD R1, _rt0_arm64_linux_lib_argv<>(SB)
+
+ // Create a new thread to do the runtime initialization and return.
+ MOVD _cgo_sys_thread_create(SB), R4
+ CMP $0, R4
+ BEQ nocgo
+ MOVD $_rt0_arm64_linux_lib_go(SB), R0
+ MOVD $0, R1
+ BL (R4)
+ B restore
+
+nocgo:
+ MOVD $0x800000, R0 // stacksize = 8192KB
+ MOVD $_rt0_arm64_linux_lib_go(SB), R1
+ MOVD R0, 8(RSP)
+ MOVD R1, 16(RSP)
+ MOVD $runtime·newosproc0(SB),R4
+ BL (R4)
+
+restore:
+ MOVD 24(RSP), R27
+ RET
+
+TEXT _rt0_arm64_linux_lib_go(SB),NOSPLIT,$0
+ MOVD _rt0_arm64_linux_lib_argc<>(SB), R0
+ MOVD _rt0_arm64_linux_lib_argv<>(SB), R1
+ MOVD $runtime·rt0_go(SB),R4
+ B (R4)
+
+DATA _rt0_arm64_linux_lib_argc<>(SB)/8, $0
+GLOBL _rt0_arm64_linux_lib_argc<>(SB),NOPTR, $8
+DATA _rt0_arm64_linux_lib_argv<>(SB)/8, $0
+GLOBL _rt0_arm64_linux_lib_argv<>(SB),NOPTR, $8
+
+
TEXT main(SB),NOSPLIT,$-8
MOVD $runtime·rt0_go(SB), R2
BL (R2)
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux
+// +build mips64 mips64le
+
+#include "textflag.h"
+
+TEXT _rt0_mips64_linux(SB),NOSPLIT,$0
+ JMP _main<>(SB)
+
+TEXT _rt0_mips64le_linux(SB),NOSPLIT,$0
+ JMP _main<>(SB)
+
+TEXT _main<>(SB),NOSPLIT,$-8
+ // In a statically linked binary, the stack contains argc,
+ // argv as argc string pointers followed by a NULL, envv as a
+ // sequence of string pointers followed by a NULL, and auxv.
+ // There is no TLS base pointer.
+#ifdef GOARCH_mips64
+ MOVW 4(R29), R1 // argc, big-endian ABI places int32 at offset 4
+#else
+ MOVW 0(R29), R1 // argc
+#endif
+ ADDV $8, R29, R2 // argv
+ JMP main(SB)
+
+TEXT main(SB),NOSPLIT,$-8
+ MOVV $runtime·rt0_go(SB), R4
+ JMP (R4)
+#include "go_asm.h"
#include "textflag.h"
TEXT _rt0_ppc64le_linux(SB),NOSPLIT,$0
// Statically linked
MOVD 0(R1), R3 // argc
ADD $8, R1, R4 // argv
- MOVD $runtime·tls0(SB), R13 // TLS
+ MOVD $runtime·m0+m_tls(SB), R13 // TLS
ADD $0x7000, R13
dlink:
MOVL AX, 4(SP)
CALL runtime·rt0_go(SB)
-DATA runtime·isplan9(SB)/4, $1
-GLOBL runtime·isplan9(SB), NOPTR, $4
GLOBL _tos(SB), NOPTR, $4
GLOBL _privates(SB), NOPTR, $4
GLOBL _nprivates(SB), NOPTR, $4
MOVQ $runtime·rt0_go(SB), AX
JMP AX
-DATA runtime·isplan9(SB)/4, $1
-GLOBL runtime·isplan9(SB), NOPTR, $4
GLOBL _tos(SB), NOPTR, $8
GLOBL _privates(SB), NOPTR, $8
GLOBL _nprivates(SB), NOPTR, $4
TEXT main(SB),NOSPLIT,$-8
MOVQ $runtime·rt0_go(SB), AX
JMP AX
-
-DATA runtime·issolaris(SB)/4, $1
-GLOBL runtime·issolaris(SB), NOPTR, $4
TEXT _main(SB),NOSPLIT,$0
JMP runtime·rt0_go(SB)
-
-
-DATA runtime·iswindows(SB)/4, $1
-GLOBL runtime·iswindows(SB), NOPTR, $4
TEXT main(SB),NOSPLIT,$-8
MOVQ $runtime·rt0_go(SB), AX
JMP AX
-
-DATA runtime·iswindows(SB)/4, $1
-GLOBL runtime·iswindows(SB), NOPTR, $4
// stack frames on RISC architectures.
canBackTrace := false
switch runtime.GOARCH {
- case "amd64", "386", "ppc64", "ppc64le", "arm", "arm64":
+ case "amd64", "386", "ppc64", "ppc64le", "arm", "arm64", "mips64", "mips64le":
canBackTrace = true
args = append(args,
"-ex", "echo BEGIN goroutine 2 bt\n",
package runtime
-import _ "unsafe" // for go:linkname
+import (
+ "runtime/internal/atomic"
+ _ "unsafe" // for go:linkname
+)
//go:generate go run wincallback.go
//go:generate go run mkduff.go
val uint64
}
-var tls0 [8]uintptr // available storage for m0's TLS; not necessarily used; opaque to GC
-
// Note: Called by runtime/pprof in addition to runtime code.
func tickspersecond() int64 {
- r := int64(atomicload64(&ticks.val))
+ r := int64(atomic.Load64(&ticks.val))
if r != 0 {
return r
}
if r == 0 {
r++
}
- atomicstore64(&ticks.val, uint64(r))
+ atomic.Store64(&ticks.val, uint64(r))
}
unlock(&ticks.lock)
return r
package runtime
-import "unsafe"
+import (
+ "runtime/internal/atomic"
+ "runtime/internal/sys"
+ "unsafe"
+)
// Keep a cached value to make gotraceback fast,
// since we call it on every call to gentraceback.
-// The cached value is a uint32 in which the low bit
-// is the "crash" setting and the top 31 bits are the
-// gotraceback value.
-var traceback_cache uint32 = 2 << 1
-
-// The GOTRACEBACK environment variable controls the
-// behavior of a Go program that is crashing and exiting.
-// GOTRACEBACK=0 suppress all tracebacks
-// GOTRACEBACK=1 default behavior - show tracebacks but exclude runtime frames
-// GOTRACEBACK=2 show tracebacks including runtime frames
-// GOTRACEBACK=crash show tracebacks including runtime frames, then crash (core dump etc)
+// The cached value is a uint32 in which the low bits
+// are the "crash" and "all" settings and the remaining
+// bits are the traceback value (0 off, 1 on, 2 include system).
+const (
+ tracebackCrash = 1 << iota
+ tracebackAll
+ tracebackShift = iota
+)
+
+var traceback_cache uint32 = 2 << tracebackShift
+
+// gotraceback returns the current traceback settings.
+//
+// If level is 0, suppress all tracebacks.
+// If level is 1, show tracebacks, but exclude runtime frames.
+// If level is 2, show tracebacks including runtime frames.
+// If all is set, print all goroutine stacks. Otherwise, print just the current goroutine.
+// If crash is set, crash (core dump, etc) after tracebacking.
+//
//go:nosplit
-func gotraceback(crash *bool) int32 {
+func gotraceback() (level int32, all, crash bool) {
_g_ := getg()
- if crash != nil {
- *crash = false
- }
+ all = _g_.m.throwing > 0
if _g_.m.traceback != 0 {
- return int32(_g_.m.traceback)
- }
- if crash != nil {
- *crash = traceback_cache&1 != 0
+ level = int32(_g_.m.traceback)
+ return
}
- return int32(traceback_cache >> 1)
+ crash = traceback_cache&tracebackCrash != 0
+ all = all || traceback_cache&tracebackAll != 0
+ level = int32(traceback_cache >> tracebackShift)
+ return
}
var (
// nosplit for use in linux/386 startup linux_setup_vdso
//go:nosplit
func argv_index(argv **byte, i int32) *byte {
- return *(**byte)(add(unsafe.Pointer(argv), uintptr(i)*ptrSize))
+ return *(**byte)(add(unsafe.Pointer(argv), uintptr(i)*sys.PtrSize))
}
func args(c int32, v **byte) {
sysargs(c, v)
}
-var (
- // TODO: Retire in favor of GOOS== checks.
- isplan9 int32
- issolaris int32
- iswindows int32
-)
-
func goargs() {
if GOOS == "windows" {
return
prefetcht1(uintptr(unsafe.Pointer(&test_z64)))
prefetcht2(uintptr(unsafe.Pointer(&test_z64)))
prefetchnta(uintptr(unsafe.Pointer(&test_z64)))
- if cas64(&test_z64, test_x64, 1) {
+ if atomic.Cas64(&test_z64, test_x64, 1) {
throw("cas64 failed")
}
if test_x64 != 0 {
throw("cas64 failed")
}
test_x64 = 42
- if !cas64(&test_z64, test_x64, 1) {
+ if !atomic.Cas64(&test_z64, test_x64, 1) {
throw("cas64 failed")
}
if test_x64 != 42 || test_z64 != 1 {
throw("cas64 failed")
}
- if atomicload64(&test_z64) != 1 {
+ if atomic.Load64(&test_z64) != 1 {
throw("load64 failed")
}
- atomicstore64(&test_z64, (1<<40)+1)
- if atomicload64(&test_z64) != (1<<40)+1 {
+ atomic.Store64(&test_z64, (1<<40)+1)
+ if atomic.Load64(&test_z64) != (1<<40)+1 {
throw("store64 failed")
}
- if xadd64(&test_z64, (1<<40)+1) != (2<<40)+2 {
+ if atomic.Xadd64(&test_z64, (1<<40)+1) != (2<<40)+2 {
throw("xadd64 failed")
}
- if atomicload64(&test_z64) != (2<<40)+2 {
+ if atomic.Load64(&test_z64) != (2<<40)+2 {
throw("xadd64 failed")
}
- if xchg64(&test_z64, (3<<40)+3) != (2<<40)+2 {
+ if atomic.Xchg64(&test_z64, (3<<40)+3) != (2<<40)+2 {
throw("xchg64 failed")
}
- if atomicload64(&test_z64) != (3<<40)+3 {
+ if atomic.Load64(&test_z64) != (3<<40)+3 {
throw("xchg64 failed")
}
}
if unsafe.Sizeof(j) != 8 {
throw("bad j")
}
- if unsafe.Sizeof(k) != ptrSize {
+ if unsafe.Sizeof(k) != sys.PtrSize {
throw("bad k")
}
- if unsafe.Sizeof(l) != ptrSize {
+ if unsafe.Sizeof(l) != sys.PtrSize {
throw("bad l")
}
if unsafe.Sizeof(x1) != 1 {
var z uint32
z = 1
- if !cas(&z, 1, 2) {
+ if !atomic.Cas(&z, 1, 2) {
throw("cas1")
}
if z != 2 {
}
z = 4
- if cas(&z, 5, 6) {
+ if atomic.Cas(&z, 5, 6) {
throw("cas3")
}
if z != 4 {
}
z = 0xffffffff
- if !cas(&z, 0xffffffff, 0xfffffffe) {
+ if !atomic.Cas(&z, 0xffffffff, 0xfffffffe) {
throw("cas5")
}
if z != 0xfffffffe {
}
k = unsafe.Pointer(uintptr(0xfedcb123))
- if ptrSize == 8 {
+ if sys.PtrSize == 8 {
k = unsafe.Pointer(uintptr(unsafe.Pointer(k)) << 10)
}
if casp(&k, nil, nil) {
}
m = [4]byte{1, 1, 1, 1}
- atomicor8(&m[1], 0xf0)
+ atomic.Or8(&m[1], 0xf0)
if m[0] != 1 || m[1] != 0xf1 || m[2] != 1 || m[3] != 1 {
throw("atomicor8")
}
// already have an initial value.
var debug struct {
allocfreetrace int32
+ cgocheck int32
efence int32
gccheckmark int32
gcpacertrace int32
var dbgvars = []dbgVar{
{"allocfreetrace", &debug.allocfreetrace},
+ {"cgocheck", &debug.cgocheck},
{"efence", &debug.efence},
{"gccheckmark", &debug.gccheckmark},
{"gcpacertrace", &debug.gcpacertrace},
func parsedebugvars() {
// defaults
+ debug.cgocheck = 1
debug.invalidptr = 1
for p := gogetenv("GODEBUG"); p != ""; {
}
switch p := gogetenv("GOTRACEBACK"); p {
- case "":
- traceback_cache = 1 << 1
+ case "none":
+ traceback_cache = 0
+ case "single", "":
+ traceback_cache = 1 << tracebackShift
+ case "all":
+ traceback_cache = 1<<tracebackShift | tracebackAll
+ case "system":
+ traceback_cache = 2<<tracebackShift | tracebackAll
case "crash":
- traceback_cache = 2<<1 | 1
+ traceback_cache = 2<<tracebackShift | tracebackAll | tracebackCrash
default:
- traceback_cache = uint32(atoi(p)) << 1
+ traceback_cache = uint32(atoi(p))<<tracebackShift | tracebackAll
}
// when C owns the process, simply exit'ing the process on fatal errors
// and panics is surprising. Be louder and abort instead.
if islibrary || isarchive {
- traceback_cache |= 1
+ traceback_cache |= tracebackCrash
}
if debug.gcstackbarrierall > 0 {
firstStackBarrierOffset = 0
}
+
+ // For cgocheck > 1, we turn on the write barrier at all times
+ // and check all pointer writes.
+ if debug.cgocheck > 1 {
+ writeBarrier.cgo = true
+ writeBarrier.enabled = true
+ }
}
// Poor mans 64-bit division.
}
//go:linkname reflect_typelinks reflect.typelinks
-//go:nosplit
func reflect_typelinks() [][]*_type {
ret := [][]*_type{firstmoduledata.typelinks}
for datap := firstmoduledata.next; datap != nil; datap = datap.next {
package runtime
-import "unsafe"
+import (
+ "runtime/internal/atomic"
+ "runtime/internal/sys"
+ "unsafe"
+)
/*
* defined constants
_Pdead
)
-// The next line makes 'go generate' write the zgen_*.go files with
-// per-OS and per-arch information, including constants
-// named goos_$GOOS and goarch_$GOARCH for every
-// known GOOS and GOARCH. The constant is 1 on the
-// current system, 0 otherwise; multiplying by them is
-// useful for defining GOOS- or GOARCH-specific constants.
-//go:generate go run gengoos.go
-
type mutex struct {
// Futex-based impl treats it as uint32 key,
// while sema-based impl as M* waitm.
key uintptr
}
-type _string struct {
- str *byte
- len int
-}
-
type funcval struct {
fn uintptr
// variable-size, fn-specific data here
data unsafe.Pointer
}
+func efaceOf(ep *interface{}) *eface {
+ return (*eface)(unsafe.Pointer(ep))
+}
+
// The guintptr, muintptr, and puintptr are all used to bypass write barriers.
// It is particularly important to avoid write barriers when the current P has
// been released, because the GC thinks the world is stopped, and an
func (gp guintptr) ptr() *g { return (*g)(unsafe.Pointer(gp)) }
func (gp *guintptr) set(g *g) { *gp = guintptr(unsafe.Pointer(g)) }
func (gp *guintptr) cas(old, new guintptr) bool {
- return casuintptr((*uintptr)(unsafe.Pointer(gp)), uintptr(old), uintptr(new))
+ return atomic.Casuintptr((*uintptr)(unsafe.Pointer(gp)), uintptr(old), uintptr(new))
}
type puintptr uintptr
pc uintptr
g guintptr
ctxt unsafe.Pointer // this has to be a pointer so that gc scans it
- ret uintreg
+ ret sys.Uintreg
lr uintptr
bp uintptr // for GOEXPERIMENT=framepointer
}
gcAssistBytes int64
}
-type mts struct {
- tv_sec int64
- tv_nsec int64
-}
-
-type mscratch struct {
- v [6]uintptr
-}
-
type m struct {
g0 *g // goroutine with scheduling stack
morebuf gobuf // gobuf arg to morestack
procid uint64 // for debuggers, but offset not hard-coded
gsignal *g // signal-handling g
sigmask [4]uintptr // storage for saved signal mask
- tls [4]uintptr // thread-local storage (for x86 extern register)
+ tls [6]uintptr // thread-local storage (for x86 extern register)
mstartfn func()
curg *g // current running goroutine
caughtsig guintptr // goroutine running during fatal signal
fflag uint32 // floating point compare flags
locked uint32 // tracking for lockosthread
nextwaitm uintptr // next m waiting for lock
- waitsema uintptr // semaphore for parking on locks
- waitsemacount uint32
- waitsemalock uint32
gcstats gcstats
needextram bool
traceback uint8
libcallg guintptr
syscall libcall // stores syscall parameters on windows
//#endif
- //#ifdef GOOS_solaris
- perrno *int32 // pointer to tls errno
- // these are here because they are too large to be on the stack
- // of low-level NOSPLIT functions.
- //LibCall libcall;
- ts mts
- scratch mscratch
- //#endif
- //#ifdef GOOS_plan9
- notesig *int8
- errstr *byte
- //#endif
+ mOS
}
type p struct {
// Queue of runnable goroutines. Accessed without lock.
runqhead uint32
runqtail uint32
- runq [256]*g
+ runq [256]guintptr
// runnext, if non-nil, is a runnable G that was ready'd by
// the current G and should be run next instead of what's in
// runq if there's time remaining in the running G's time
sudogcache []*sudog
sudogbuf [128]*sudog
- tracebuf *traceBuf
+ tracebuf traceBufPtr
palloc persistentAlloc // per-P to avoid mutex
entry uintptr // start pc
nameoff int32 // function name
- args int32 // in/out args size
- frame int32 // legacy frame size; use pcsp if possible
+ args int32 // in/out args size
+ _ int32 // Previously: legacy frame size. TODO: Remove this.
pcsp int32
pcfile int32
* known to compiler
*/
const (
- _Structrnd = regSize
+ _Structrnd = sys.RegSize
)
// startup_random_data holds random bytes initialized at startup. These come from
w = 16
}
h := memhash(unsafe.Pointer(&r[n-w]), uintptr(nanotime()), uintptr(w))
- for i := 0; i < ptrSize && n < len(r); i++ {
+ for i := 0; i < sys.PtrSize && n < len(r); i++ {
r[n] = byte(h)
n++
h >>= 8
var (
emptystring string
- allg **g
allglen uintptr
- lastg *g
allm *m
allp [_MaxGomaxprocs + 1]*p
gomaxprocs int32
panicking uint32
- goos *int8
ncpu int32
- signote note
forcegc forcegcstate
sched schedt
newprocs int32
cpuid_ecx uint32
cpuid_edx uint32
lfenceBeforeRdtsc bool
+ support_avx bool
+ support_avx2 bool
goarm uint8 // set by cmd/link on arm systems
)
// This file contains the implementation of Go select statements.
-import "unsafe"
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
const (
debugSelect = false
(size-1)*unsafe.Sizeof(hselect{}.scase[0]) +
size*unsafe.Sizeof(*hselect{}.lockorder) +
size*unsafe.Sizeof(*hselect{}.pollorder)
- return round(selsize, _Int64Align)
+ return round(selsize, sys.Int64Align)
}
func newselect(sel *hselect, selsize int64, size int32) {
k *scase
sglist *sudog
sgnext *sudog
- futile byte
+ qp unsafe.Pointer
)
loop:
switch cas.kind {
case caseRecv:
- if c.dataqsiz > 0 {
- if c.qcount > 0 {
- goto asyncrecv
- }
- } else {
- sg = c.sendq.dequeue()
- if sg != nil {
- goto syncrecv
- }
+ sg = c.sendq.dequeue()
+ if sg != nil {
+ goto recv
+ }
+ if c.qcount > 0 {
+ goto bufrecv
}
if c.closed != 0 {
goto rclose
if c.closed != 0 {
goto sclose
}
- if c.dataqsiz > 0 {
- if c.qcount < c.dataqsiz {
- goto asyncsend
- }
- } else {
- sg = c.recvq.dequeue()
- if sg != nil {
- goto syncsend
- }
+ sg = c.recvq.dequeue()
+ if sg != nil {
+ goto send
+ }
+ if c.qcount < c.dataqsiz {
+ goto bufsend
}
case caseDefault:
// pass 2 - enqueue on all chans
gp = getg()
done = 0
+ if gp.waiting != nil {
+ throw("gp.waiting != nil")
+ }
for i := 0; i < int(sel.ncase); i++ {
cas = &scases[pollorder[i]]
c = cas.c
// wait for someone to wake us up
gp.param = nil
- gopark(selparkcommit, unsafe.Pointer(sel), "select", traceEvGoBlockSelect|futile, 2)
+ gopark(selparkcommit, unsafe.Pointer(sel), "select", traceEvGoBlockSelect, 2)
// someone woke us up
sellock(sel)
}
if cas == nil {
- futile = traceFutileWakeup
+ // This can happen if we were woken up by a close().
+ // TODO: figure that out explicitly so we don't need this loop.
goto loop
}
c = cas.c
- if c.dataqsiz > 0 {
- throw("selectgo: shouldn't happen")
- }
-
if debugSelect {
print("wait-return: sel=", sel, " c=", c, " cas=", cas, " kind=", cas.kind, "\n")
}
raceReadObjectPC(c.elemtype, cas.elem, cas.pc, chansendpc)
}
}
+ if msanenabled {
+ if cas.kind == caseRecv && cas.elem != nil {
+ msanwrite(cas.elem, c.elemtype.size)
+ } else if cas.kind == caseSend {
+ msanread(cas.elem, c.elemtype.size)
+ }
+ }
selunlock(sel)
goto retc
-asyncrecv:
+bufrecv:
// can receive from buffer
if raceenabled {
if cas.elem != nil {
raceacquire(chanbuf(c, c.recvx))
racerelease(chanbuf(c, c.recvx))
}
+ if msanenabled && cas.elem != nil {
+ msanwrite(cas.elem, c.elemtype.size)
+ }
if cas.receivedp != nil {
*cas.receivedp = true
}
+ qp = chanbuf(c, c.recvx)
if cas.elem != nil {
- typedmemmove(c.elemtype, cas.elem, chanbuf(c, c.recvx))
+ typedmemmove(c.elemtype, cas.elem, qp)
}
- memclr(chanbuf(c, c.recvx), uintptr(c.elemsize))
+ memclr(qp, uintptr(c.elemsize))
c.recvx++
if c.recvx == c.dataqsiz {
c.recvx = 0
}
c.qcount--
- sg = c.sendq.dequeue()
- if sg != nil {
- gp = sg.g
- selunlock(sel)
- if sg.releasetime != 0 {
- sg.releasetime = cputicks()
- }
- goready(gp, 3)
- } else {
- selunlock(sel)
- }
+ selunlock(sel)
goto retc
-asyncsend:
+bufsend:
// can send to buffer
if raceenabled {
raceacquire(chanbuf(c, c.sendx))
racerelease(chanbuf(c, c.sendx))
raceReadObjectPC(c.elemtype, cas.elem, cas.pc, chansendpc)
}
+ if msanenabled {
+ msanread(cas.elem, c.elemtype.size)
+ }
typedmemmove(c.elemtype, chanbuf(c, c.sendx), cas.elem)
c.sendx++
if c.sendx == c.dataqsiz {
c.sendx = 0
}
c.qcount++
- sg = c.recvq.dequeue()
- if sg != nil {
- gp = sg.g
- selunlock(sel)
- if sg.releasetime != 0 {
- sg.releasetime = cputicks()
- }
- goready(gp, 3)
- } else {
- selunlock(sel)
- }
+ selunlock(sel)
goto retc
-syncrecv:
+recv:
// can receive from sleeping sender (sg)
- if raceenabled {
- if cas.elem != nil {
- raceWriteObjectPC(c.elemtype, cas.elem, cas.pc, chanrecvpc)
- }
- racesync(c, sg)
- }
- selunlock(sel)
+ recv(c, sg, cas.elem, func() { selunlock(sel) })
if debugSelect {
print("syncrecv: sel=", sel, " c=", c, "\n")
}
if cas.receivedp != nil {
*cas.receivedp = true
}
- if cas.elem != nil {
- typedmemmove(c.elemtype, cas.elem, sg.elem)
- }
- sg.elem = nil
- gp = sg.g
- gp.param = unsafe.Pointer(sg)
- if sg.releasetime != 0 {
- sg.releasetime = cputicks()
- }
- goready(gp, 3)
goto retc
rclose:
}
goto retc
-syncsend:
- // can send to sleeping receiver (sg)
+send:
+ // can send to a sleeping receiver (sg)
if raceenabled {
raceReadObjectPC(c.elemtype, cas.elem, cas.pc, chansendpc)
- racesync(c, sg)
}
- selunlock(sel)
+ if msanenabled {
+ msanread(cas.elem, c.elemtype.size)
+ }
+ send(c, sg, cas.elem, func() { selunlock(sel) })
if debugSelect {
print("syncsend: sel=", sel, " c=", c, "\n")
}
- if sg.elem != nil {
- syncsend(c, sg, cas.elem)
- }
- sg.elem = nil
- gp = sg.g
- gp.param = unsafe.Pointer(sg)
- if sg.releasetime != 0 {
- sg.releasetime = cputicks()
- }
- goready(gp, 3)
+ goto retc
retc:
if cas.releasetime > 0 {
package runtime
-import "unsafe"
+import (
+ "runtime/internal/atomic"
+ "runtime/internal/sys"
+ "unsafe"
+)
// Asynchronous semaphore for sync.Mutex.
var semtable [semTabSize]struct {
root semaRoot
- pad [_CacheLineSize - unsafe.Sizeof(semaRoot{})]byte
+ pad [sys.CacheLineSize - unsafe.Sizeof(semaRoot{})]byte
}
//go:linkname sync_runtime_Semacquire sync.runtime_Semacquire
for {
lock(&root.lock)
// Add ourselves to nwait to disable "easy case" in semrelease.
- xadd(&root.nwait, 1)
+ atomic.Xadd(&root.nwait, 1)
// Check cansemacquire to avoid missed wakeup.
if cansemacquire(addr) {
- xadd(&root.nwait, -1)
+ atomic.Xadd(&root.nwait, -1)
unlock(&root.lock)
break
}
func semrelease(addr *uint32) {
root := semroot(addr)
- xadd(addr, 1)
+ atomic.Xadd(addr, 1)
// Easy case: no waiters?
// This check must happen after the xadd, to avoid a missed wakeup
// (see loop in semacquire).
- if atomicload(&root.nwait) == 0 {
+ if atomic.Load(&root.nwait) == 0 {
return
}
// Harder case: search for a waiter and wake it.
lock(&root.lock)
- if atomicload(&root.nwait) == 0 {
+ if atomic.Load(&root.nwait) == 0 {
// The count is already consumed by another goroutine,
// so no need to wake up another goroutine.
unlock(&root.lock)
s := root.head
for ; s != nil; s = s.next {
if s.elem == unsafe.Pointer(addr) {
- xadd(&root.nwait, -1)
+ atomic.Xadd(&root.nwait, -1)
root.dequeue(s)
break
}
func cansemacquire(addr *uint32) bool {
for {
- v := atomicload(addr)
+ v := atomic.Load(addr)
if v == 0 {
return false
}
- if cas(addr, v, v-1) {
+ if atomic.Cas(addr, v, v-1) {
return true
}
}
package runtime
+import "runtime/internal/sys"
+
const (
_SIG_DFL uintptr = 0
_SIG_IGN uintptr = 1
// this means the OS X core file will be >128 GB and even on a zippy
// workstation can take OS X well over an hour to write (uninterruptible).
// Save users from making that mistake.
- if ptrSize == 8 {
+ if sys.PtrSize == 8 {
return
}
}
package runtime
-import "unsafe"
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
func dumpregs(c *sigctxt) {
print("eax ", hex(c.eax()), "\n")
// (Otherwise the trace will end at runtime.sigpanic and we
// won't get to see who faulted.)
if pc != 0 {
- if regSize > ptrSize {
- sp -= ptrSize
+ if sys.RegSize > sys.PtrSize {
+ sp -= sys.PtrSize
*(*uintptr)(unsafe.Pointer(sp)) = 0
}
- sp -= ptrSize
+ sp -= sys.PtrSize
*(*uintptr)(unsafe.Pointer(sp)) = pc
c.set_esp(uint32(sp))
}
}
print("\n")
- var docrash bool
- if gotraceback(&docrash) > 0 {
+ level, _, docrash := gotraceback()
+ if level > 0 {
goroutineheader(gp)
// On Linux/386, all system calls go through the vdso kernel_vsyscall routine.
package runtime
import (
+ "runtime/internal/sys"
"unsafe"
)
// (Otherwise the trace will end at runtime.sigpanic and we
// won't get to see who faulted.)
if pc != 0 {
- if regSize > ptrSize {
- sp -= ptrSize
+ if sys.RegSize > sys.PtrSize {
+ sp -= sys.PtrSize
*(*uintptr)(unsafe.Pointer(sp)) = 0
}
- sp -= ptrSize
+ sp -= sys.PtrSize
*(*uintptr)(unsafe.Pointer(sp)) = pc
c.set_rsp(uint64(sp))
}
}
print("\n")
- var docrash bool
- if gotraceback(&docrash) > 0 {
+ level, _, docrash := gotraceback()
+ if level > 0 {
goroutineheader(gp)
tracebacktrap(uintptr(c.rip()), uintptr(c.rsp()), 0, gp)
if crashing > 0 && gp != _g_.m.curg && _g_.m.curg != nil && readgstatus(_g_.m.curg)&^_Gscan == _Grunning {
}
print("\n")
- var docrash bool
- if gotraceback(&docrash) > 0 {
+ level, _, docrash := gotraceback()
+ if level > 0 {
goroutineheader(gp)
tracebacktrap(uintptr(c.pc()), uintptr(c.sp()), uintptr(c.lr()), gp)
if crashing > 0 && gp != _g_.m.curg && _g_.m.curg != nil && readgstatus(_g_.m.curg)&^_Gscan == _Grunning {
package runtime
-import "unsafe"
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
func dumpregs(c *sigctxt) {
print("r0 ", hex(c.r0()), "\n")
// functions are correctly handled. This smashes
// the stack frame but we're not going back there
// anyway.
- sp := c.sp() - spAlign // needs only sizeof uint64, but must align the stack
+ sp := c.sp() - sys.SpAlign // needs only sizeof uint64, but must align the stack
c.set_sp(sp)
*(*uint64)(unsafe.Pointer(uintptr(sp))) = c.lr()
}
print("\n")
- var docrash bool
- if gotraceback(&docrash) > 0 {
+ level, _, docrash := gotraceback()
+ if level > 0 {
goroutineheader(gp)
tracebacktrap(uintptr(c.pc()), uintptr(c.sp()), uintptr(c.lr()), gp)
if crashing > 0 && gp != _g_.m.curg && _g_.m.curg != nil && readgstatus(_g_.m.curg)&^_Gscan == _Grunning {
import "unsafe"
-type sigTabT struct {
- flags int32
- name string
-}
-
-var sigtable = [...]sigTabT{
- /* 0 */ {0, "SIGNONE: no trap"},
- /* 1 */ {_SigNotify + _SigKill, "SIGHUP: terminal line hangup"},
- /* 2 */ {_SigNotify + _SigKill, "SIGINT: interrupt"},
- /* 3 */ {_SigNotify + _SigThrow, "SIGQUIT: quit"},
- /* 4 */ {_SigThrow + _SigUnblock, "SIGILL: illegal instruction"},
- /* 5 */ {_SigThrow + _SigUnblock, "SIGTRAP: trace trap"},
- /* 6 */ {_SigNotify + _SigThrow, "SIGABRT: abort"},
- /* 7 */ {_SigPanic + _SigUnblock, "SIGBUS: bus error"},
- /* 8 */ {_SigPanic + _SigUnblock, "SIGFPE: floating-point exception"},
- /* 9 */ {0, "SIGKILL: kill"},
- /* 10 */ {_SigNotify, "SIGUSR1: user-defined signal 1"},
- /* 11 */ {_SigPanic + _SigUnblock, "SIGSEGV: segmentation violation"},
- /* 12 */ {_SigNotify, "SIGUSR2: user-defined signal 2"},
- /* 13 */ {_SigNotify, "SIGPIPE: write to broken pipe"},
- /* 14 */ {_SigNotify, "SIGALRM: alarm clock"},
- /* 15 */ {_SigNotify + _SigKill, "SIGTERM: termination"},
- /* 16 */ {_SigThrow + _SigUnblock, "SIGSTKFLT: stack fault"},
- /* 17 */ {_SigNotify + _SigUnblock, "SIGCHLD: child status has changed"},
- /* 18 */ {0, "SIGCONT: continue"},
- /* 19 */ {0, "SIGSTOP: stop, unblockable"},
- /* 20 */ {_SigNotify + _SigDefault, "SIGTSTP: keyboard stop"},
- /* 21 */ {_SigNotify + _SigDefault, "SIGTTIN: background read from tty"},
- /* 22 */ {_SigNotify + _SigDefault, "SIGTTOU: background write to tty"},
- /* 23 */ {_SigNotify, "SIGURG: urgent condition on socket"},
- /* 24 */ {_SigNotify, "SIGXCPU: cpu limit exceeded"},
- /* 25 */ {_SigNotify, "SIGXFSZ: file size limit exceeded"},
- /* 26 */ {_SigNotify, "SIGVTALRM: virtual alarm clock"},
- /* 27 */ {_SigNotify + _SigUnblock, "SIGPROF: profiling alarm clock"},
- /* 28 */ {_SigNotify, "SIGWINCH: window size change"},
- /* 29 */ {_SigNotify, "SIGIO: i/o now possible"},
- /* 30 */ {_SigNotify, "SIGPWR: power failure restart"},
- /* 31 */ {_SigNotify, "SIGSYS: bad system call"},
- /* 32 */ {_SigSetStack + _SigUnblock, "signal 32"}, /* SIGCANCEL; see issue 6997 */
- /* 33 */ {_SigSetStack + _SigUnblock, "signal 33"}, /* SIGSETXID; see issues 3871, 9400, 12498 */
- /* 34 */ {_SigNotify, "signal 34"},
- /* 35 */ {_SigNotify, "signal 35"},
- /* 36 */ {_SigNotify, "signal 36"},
- /* 37 */ {_SigNotify, "signal 37"},
- /* 38 */ {_SigNotify, "signal 38"},
- /* 39 */ {_SigNotify, "signal 39"},
- /* 40 */ {_SigNotify, "signal 40"},
- /* 41 */ {_SigNotify, "signal 41"},
- /* 42 */ {_SigNotify, "signal 42"},
- /* 43 */ {_SigNotify, "signal 43"},
- /* 44 */ {_SigNotify, "signal 44"},
- /* 45 */ {_SigNotify, "signal 45"},
- /* 46 */ {_SigNotify, "signal 46"},
- /* 47 */ {_SigNotify, "signal 47"},
- /* 48 */ {_SigNotify, "signal 48"},
- /* 49 */ {_SigNotify, "signal 49"},
- /* 50 */ {_SigNotify, "signal 50"},
- /* 51 */ {_SigNotify, "signal 51"},
- /* 52 */ {_SigNotify, "signal 52"},
- /* 53 */ {_SigNotify, "signal 53"},
- /* 54 */ {_SigNotify, "signal 54"},
- /* 55 */ {_SigNotify, "signal 55"},
- /* 56 */ {_SigNotify, "signal 56"},
- /* 57 */ {_SigNotify, "signal 57"},
- /* 58 */ {_SigNotify, "signal 58"},
- /* 59 */ {_SigNotify, "signal 59"},
- /* 60 */ {_SigNotify, "signal 60"},
- /* 61 */ {_SigNotify, "signal 61"},
- /* 62 */ {_SigNotify, "signal 62"},
- /* 63 */ {_SigNotify, "signal 63"},
- /* 64 */ {_SigNotify, "signal 64"},
-}
-
// Continuation of the (assembly) sigtramp() logic.
//go:nosplit
func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
package runtime
-import "unsafe"
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
type sigctxt struct {
info *siginfo
func (c *sigctxt) set_esp(x uint32) { c.regs().esp = x }
func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) }
func (c *sigctxt) set_sigaddr(x uint32) {
- *(*uintptr)(add(unsafe.Pointer(c.info), 2*ptrSize)) = uintptr(x)
+ *(*uintptr)(add(unsafe.Pointer(c.info), 2*sys.PtrSize)) = uintptr(x)
}
package runtime
-import "unsafe"
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
type sigctxt struct {
info *siginfo
func (c *sigctxt) set_rsp(x uint64) { c.regs().rsp = x }
func (c *sigctxt) set_sigcode(x uint64) { c.info.si_code = int32(x) }
func (c *sigctxt) set_sigaddr(x uint64) {
- *(*uintptr)(add(unsafe.Pointer(c.info), 2*ptrSize)) = uintptr(x)
+ *(*uintptr)(add(unsafe.Pointer(c.info), 2*sys.PtrSize)) = uintptr(x)
}
package runtime
-import "unsafe"
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
type sigctxt struct {
info *siginfo
func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) }
func (c *sigctxt) set_sigaddr(x uint32) {
- *(*uintptr)(add(unsafe.Pointer(c.info), 2*ptrSize)) = uintptr(x)
+ *(*uintptr)(add(unsafe.Pointer(c.info), 2*sys.PtrSize)) = uintptr(x)
}
package runtime
-import "unsafe"
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
type sigctxt struct {
info *siginfo
func (c *sigctxt) set_r28(x uint64) { c.regs().regs[28] = x }
func (c *sigctxt) set_sigaddr(x uint64) {
- *(*uintptr)(add(unsafe.Pointer(c.info), 2*ptrSize)) = uintptr(x)
+ *(*uintptr)(add(unsafe.Pointer(c.info), 2*sys.PtrSize)) = uintptr(x)
}
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux
+// +build mips64 mips64le
+
+package runtime
+
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
+
+type sigctxt struct {
+ info *siginfo
+ ctxt unsafe.Pointer
+}
+
+func (c *sigctxt) regs() *sigcontext { return &(*ucontext)(c.ctxt).uc_mcontext }
+func (c *sigctxt) r0() uint64 { return c.regs().sc_regs[0] }
+func (c *sigctxt) r1() uint64 { return c.regs().sc_regs[1] }
+func (c *sigctxt) r2() uint64 { return c.regs().sc_regs[2] }
+func (c *sigctxt) r3() uint64 { return c.regs().sc_regs[3] }
+func (c *sigctxt) r4() uint64 { return c.regs().sc_regs[4] }
+func (c *sigctxt) r5() uint64 { return c.regs().sc_regs[5] }
+func (c *sigctxt) r6() uint64 { return c.regs().sc_regs[6] }
+func (c *sigctxt) r7() uint64 { return c.regs().sc_regs[7] }
+func (c *sigctxt) r8() uint64 { return c.regs().sc_regs[8] }
+func (c *sigctxt) r9() uint64 { return c.regs().sc_regs[9] }
+func (c *sigctxt) r10() uint64 { return c.regs().sc_regs[10] }
+func (c *sigctxt) r11() uint64 { return c.regs().sc_regs[11] }
+func (c *sigctxt) r12() uint64 { return c.regs().sc_regs[12] }
+func (c *sigctxt) r13() uint64 { return c.regs().sc_regs[13] }
+func (c *sigctxt) r14() uint64 { return c.regs().sc_regs[14] }
+func (c *sigctxt) r15() uint64 { return c.regs().sc_regs[15] }
+func (c *sigctxt) r16() uint64 { return c.regs().sc_regs[16] }
+func (c *sigctxt) r17() uint64 { return c.regs().sc_regs[17] }
+func (c *sigctxt) r18() uint64 { return c.regs().sc_regs[18] }
+func (c *sigctxt) r19() uint64 { return c.regs().sc_regs[19] }
+func (c *sigctxt) r20() uint64 { return c.regs().sc_regs[20] }
+func (c *sigctxt) r21() uint64 { return c.regs().sc_regs[21] }
+func (c *sigctxt) r22() uint64 { return c.regs().sc_regs[22] }
+func (c *sigctxt) r23() uint64 { return c.regs().sc_regs[23] }
+func (c *sigctxt) r24() uint64 { return c.regs().sc_regs[24] }
+func (c *sigctxt) r25() uint64 { return c.regs().sc_regs[25] }
+func (c *sigctxt) r26() uint64 { return c.regs().sc_regs[26] }
+func (c *sigctxt) r27() uint64 { return c.regs().sc_regs[27] }
+func (c *sigctxt) r28() uint64 { return c.regs().sc_regs[28] }
+func (c *sigctxt) r29() uint64 { return c.regs().sc_regs[29] }
+func (c *sigctxt) r30() uint64 { return c.regs().sc_regs[30] }
+func (c *sigctxt) r31() uint64 { return c.regs().sc_regs[31] }
+func (c *sigctxt) sp() uint64 { return c.regs().sc_regs[29] }
+func (c *sigctxt) pc() uint64 { return c.regs().sc_pc }
+func (c *sigctxt) link() uint64 { return c.regs().sc_regs[31] }
+func (c *sigctxt) lo() uint64 { return c.regs().sc_mdlo }
+func (c *sigctxt) hi() uint64 { return c.regs().sc_mdhi }
+
+func (c *sigctxt) sigcode() uint32 { return uint32(c.info.si_code) }
+func (c *sigctxt) sigaddr() uint64 { return c.info.si_addr }
+
+func (c *sigctxt) set_r30(x uint64) { c.regs().sc_regs[30] = x }
+func (c *sigctxt) set_pc(x uint64) { c.regs().sc_pc = x }
+func (c *sigctxt) set_sp(x uint64) { c.regs().sc_regs[29] = x }
+func (c *sigctxt) set_link(x uint64) { c.regs().sc_regs[31] = x }
+
+func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) }
+func (c *sigctxt) set_sigaddr(x uint64) {
+ *(*uintptr)(add(unsafe.Pointer(c.info), 2*sys.PtrSize)) = uintptr(x)
+}
package runtime
-import "unsafe"
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
type sigctxt struct {
info *siginfo
func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) }
func (c *sigctxt) set_sigaddr(x uint64) {
- *(*uintptr)(add(unsafe.Pointer(c.info), 2*ptrSize)) = uintptr(x)
+ *(*uintptr)(add(unsafe.Pointer(c.info), 2*sys.PtrSize)) = uintptr(x)
}
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux
+// +build mips64 mips64le
+
+package runtime
+
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
+
+func dumpregs(c *sigctxt) {
+ print("r0 ", hex(c.r0()), "\t")
+ print("r1 ", hex(c.r1()), "\n")
+ print("r2 ", hex(c.r2()), "\t")
+ print("r3 ", hex(c.r3()), "\n")
+ print("r4 ", hex(c.r4()), "\t")
+ print("r5 ", hex(c.r5()), "\n")
+ print("r6 ", hex(c.r6()), "\t")
+ print("r7 ", hex(c.r7()), "\n")
+ print("r8 ", hex(c.r8()), "\t")
+ print("r9 ", hex(c.r9()), "\n")
+ print("r10 ", hex(c.r10()), "\t")
+ print("r11 ", hex(c.r11()), "\n")
+ print("r12 ", hex(c.r12()), "\t")
+ print("r13 ", hex(c.r13()), "\n")
+ print("r14 ", hex(c.r14()), "\t")
+ print("r15 ", hex(c.r15()), "\n")
+ print("r16 ", hex(c.r16()), "\t")
+ print("r17 ", hex(c.r17()), "\n")
+ print("r18 ", hex(c.r18()), "\t")
+ print("r19 ", hex(c.r19()), "\n")
+ print("r20 ", hex(c.r20()), "\t")
+ print("r21 ", hex(c.r21()), "\n")
+ print("r22 ", hex(c.r22()), "\t")
+ print("r23 ", hex(c.r23()), "\n")
+ print("r24 ", hex(c.r24()), "\t")
+ print("r25 ", hex(c.r25()), "\n")
+ print("r26 ", hex(c.r26()), "\t")
+ print("r27 ", hex(c.r27()), "\n")
+ print("r28 ", hex(c.r28()), "\t")
+ print("r29 ", hex(c.r29()), "\n")
+ print("r30 ", hex(c.r30()), "\t")
+ print("r31 ", hex(c.r31()), "\n")
+ print("pc ", hex(c.pc()), "\t")
+ print("link ", hex(c.link()), "\n")
+ print("lo ", hex(c.lo()), "\t")
+ print("hi ", hex(c.hi()), "\n")
+}
+
+var crashing int32
+
+// May run during STW, so write barriers are not allowed.
+//go:nowritebarrier
+func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
+ _g_ := getg()
+ c := &sigctxt{info, ctxt}
+
+ if sig == _SIGPROF {
+ sigprof(uintptr(c.pc()), uintptr(c.sp()), uintptr(c.link()), gp, _g_.m)
+ return
+ }
+ flags := int32(_SigThrow)
+ if sig < uint32(len(sigtable)) {
+ flags = sigtable[sig].flags
+ }
+ if c.sigcode() != _SI_USER && flags&_SigPanic != 0 {
+ // Make it look like a call to the signal func.
+ // Have to pass arguments out of band since
+ // augmenting the stack frame would break
+ // the unwinding code.
+ gp.sig = sig
+ gp.sigcode0 = uintptr(c.sigcode())
+ gp.sigcode1 = uintptr(c.sigaddr())
+ gp.sigpc = uintptr(c.pc())
+
+ // We arrange link, and pc to pretend the panicking
+ // function calls sigpanic directly.
+ // Always save LINK to stack so that panics in leaf
+ // functions are correctly handled. This smashes
+ // the stack frame but we're not going back there
+ // anyway.
+ sp := c.sp() - sys.PtrSize
+ c.set_sp(sp)
+ *(*uint64)(unsafe.Pointer(uintptr(sp))) = c.link()
+
+ pc := uintptr(gp.sigpc)
+
+ // If we don't recognize the PC as code
+ // but we do recognize the link register as code,
+ // then assume this was a call to non-code and treat like
+ // pc == 0, to make unwinding show the context.
+ if pc != 0 && findfunc(pc) == nil && findfunc(uintptr(c.link())) != nil {
+ pc = 0
+ }
+
+ // Don't bother saving PC if it's zero, which is
+ // probably a call to a nil func: the old link register
+ // is more useful in the stack trace.
+ if pc != 0 {
+ c.set_link(uint64(pc))
+ }
+
+ // In case we are panicking from external C code
+ c.set_r30(uint64(uintptr(unsafe.Pointer(gp))))
+ c.set_pc(uint64(funcPC(sigpanic)))
+ return
+ }
+
+ if c.sigcode() == _SI_USER || flags&_SigNotify != 0 {
+ if sigsend(sig) {
+ return
+ }
+ }
+
+ if flags&_SigKill != 0 {
+ exit(2)
+ }
+
+ if flags&_SigThrow == 0 {
+ return
+ }
+
+ _g_.m.throwing = 1
+ _g_.m.caughtsig.set(gp)
+
+ if crashing == 0 {
+ startpanic()
+ }
+
+ if sig < uint32(len(sigtable)) {
+ print(sigtable[sig].name, "\n")
+ } else {
+ print("Signal ", sig, "\n")
+ }
+
+ print("PC=", hex(c.pc()), " m=", _g_.m.id, "\n")
+ if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 {
+ print("signal arrived during cgo execution\n")
+ gp = _g_.m.lockedg
+ }
+ print("\n")
+
+ level, _, docrash := gotraceback()
+ if level > 0 {
+ goroutineheader(gp)
+ tracebacktrap(uintptr(c.pc()), uintptr(c.sp()), uintptr(c.link()), gp)
+ if crashing > 0 && gp != _g_.m.curg && _g_.m.curg != nil && readgstatus(_g_.m.curg)&^_Gscan == _Grunning {
+ // tracebackothers on original m skipped this one; trace it now.
+ goroutineheader(_g_.m.curg)
+ traceback(^uintptr(0), ^uintptr(0), 0, gp)
+ } else if crashing == 0 {
+ tracebackothers(gp)
+ print("\n")
+ }
+ dumpregs(c)
+ }
+
+ if docrash {
+ crashing++
+ if crashing < sched.mcount {
+ // There are other m's that need to dump their stacks.
+ // Relay SIGQUIT to the next m by sending it to the current process.
+ // All m's that have already received SIGQUIT have signal masks blocking
+ // receipt of any signals, so the SIGQUIT will go to an m that hasn't seen it yet.
+ // When the last m receives the SIGQUIT, it will fall through to the call to
+ // crash below. Just in case the relaying gets botched, each m involved in
+ // the relay sleeps for 5 seconds and then does the crash/exit itself.
+ // In expected operation, the last m has received the SIGQUIT and run
+ // crash/exit and the process is gone, all long before any of the
+ // 5-second sleeps have finished.
+ print("\n-----\n\n")
+ raiseproc(_SIGQUIT)
+ usleep(5 * 1000 * 1000)
+ }
+ crash()
+ }
+
+ exit(2)
+}
// Alarms can be handled if desired, otherwise they're ignored.
{_SigNotify, "alarm"},
+
+ // Aborts can be handled if desired, otherwise they cause a stack trace.
+ {_SigNotify + _SigThrow, "abort"},
}
package runtime
-import "unsafe"
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
func dumpregs(c *sigctxt) {
print("r0 ", hex(c.r0()), "\t")
// functions are correctly handled. This smashes
// the stack frame but we're not going back there
// anyway.
- sp := c.sp() - minFrameSize
+ sp := c.sp() - sys.MinFrameSize
c.set_sp(sp)
*(*uint64)(unsafe.Pointer(uintptr(sp))) = c.link()
}
print("\n")
- var docrash bool
- if gotraceback(&docrash) > 0 {
+ level, _, docrash := gotraceback()
+ if level > 0 {
goroutineheader(gp)
tracebacktrap(uintptr(c.pc()), uintptr(c.sp()), uintptr(c.link()), gp)
if crashing > 0 && gp != _g_.m.curg && _g_.m.curg != nil && readgstatus(_g_.m.curg)&^_Gscan == _Grunning {
}
print("\n")
- var docrash bool
- if gotraceback(&docrash) > 0 {
+ level, _, docrash := gotraceback()
+ if level > 0 {
tracebacktrap(r.ip(), r.sp(), 0, gp)
tracebackothers(gp)
dumpregs(r)
package runtime
-import "unsafe"
+import (
+ "runtime/internal/atomic"
+ "unsafe"
+)
var sig struct {
note note
if mask&bit != 0 {
return true // signal already in queue
}
- if cas(&sig.mask[s/32], mask, mask|bit) {
+ if atomic.Cas(&sig.mask[s/32], mask, mask|bit) {
break
}
}
// Notify receiver that queue has new bit.
Send:
for {
- switch atomicload(&sig.state) {
+ switch atomic.Load(&sig.state) {
default:
throw("sigsend: inconsistent state")
case sigIdle:
- if cas(&sig.state, sigIdle, sigSending) {
+ if atomic.Cas(&sig.state, sigIdle, sigSending) {
break Send
}
case sigSending:
// notification already pending
break Send
case sigReceiving:
- if cas(&sig.state, sigReceiving, sigIdle) {
+ if atomic.Cas(&sig.state, sigReceiving, sigIdle) {
notewakeup(&sig.note)
break Send
}
// Wait for updates to be available from signal sender.
Receive:
for {
- switch atomicload(&sig.state) {
+ switch atomic.Load(&sig.state) {
default:
throw("signal_recv: inconsistent state")
case sigIdle:
- if cas(&sig.state, sigIdle, sigReceiving) {
+ if atomic.Cas(&sig.state, sigIdle, sigReceiving) {
notetsleepg(&sig.note, -1)
noteclear(&sig.note)
break Receive
}
case sigSending:
- if cas(&sig.state, sigSending, sigIdle) {
+ if atomic.Cas(&sig.state, sigSending, sigIdle) {
break Receive
}
}
// Incorporate updates from sender into local copy.
for i := range sig.mask {
- sig.recv[i] = xchg(&sig.mask[i], 0)
+ sig.recv[i] = atomic.Xchg(&sig.mask[i], 0)
}
}
}
--- /dev/null
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !mips64
+// +build !mips64le
+// +build linux
+
+package runtime
+
+type sigTabT struct {
+ flags int32
+ name string
+}
+
+var sigtable = [...]sigTabT{
+ /* 0 */ {0, "SIGNONE: no trap"},
+ /* 1 */ {_SigNotify + _SigKill, "SIGHUP: terminal line hangup"},
+ /* 2 */ {_SigNotify + _SigKill, "SIGINT: interrupt"},
+ /* 3 */ {_SigNotify + _SigThrow, "SIGQUIT: quit"},
+ /* 4 */ {_SigThrow + _SigUnblock, "SIGILL: illegal instruction"},
+ /* 5 */ {_SigThrow + _SigUnblock, "SIGTRAP: trace trap"},
+ /* 6 */ {_SigNotify + _SigThrow, "SIGABRT: abort"},
+ /* 7 */ {_SigPanic + _SigUnblock, "SIGBUS: bus error"},
+ /* 8 */ {_SigPanic + _SigUnblock, "SIGFPE: floating-point exception"},
+ /* 9 */ {0, "SIGKILL: kill"},
+ /* 10 */ {_SigNotify, "SIGUSR1: user-defined signal 1"},
+ /* 11 */ {_SigPanic + _SigUnblock, "SIGSEGV: segmentation violation"},
+ /* 12 */ {_SigNotify, "SIGUSR2: user-defined signal 2"},
+ /* 13 */ {_SigNotify, "SIGPIPE: write to broken pipe"},
+ /* 14 */ {_SigNotify, "SIGALRM: alarm clock"},
+ /* 15 */ {_SigNotify + _SigKill, "SIGTERM: termination"},
+ /* 16 */ {_SigThrow + _SigUnblock, "SIGSTKFLT: stack fault"},
+ /* 17 */ {_SigNotify + _SigUnblock, "SIGCHLD: child status has changed"},
+ /* 18 */ {0, "SIGCONT: continue"},
+ /* 19 */ {0, "SIGSTOP: stop, unblockable"},
+ /* 20 */ {_SigNotify + _SigDefault, "SIGTSTP: keyboard stop"},
+ /* 21 */ {_SigNotify + _SigDefault, "SIGTTIN: background read from tty"},
+ /* 22 */ {_SigNotify + _SigDefault, "SIGTTOU: background write to tty"},
+ /* 23 */ {_SigNotify, "SIGURG: urgent condition on socket"},
+ /* 24 */ {_SigNotify, "SIGXCPU: cpu limit exceeded"},
+ /* 25 */ {_SigNotify, "SIGXFSZ: file size limit exceeded"},
+ /* 26 */ {_SigNotify, "SIGVTALRM: virtual alarm clock"},
+ /* 27 */ {_SigNotify + _SigUnblock, "SIGPROF: profiling alarm clock"},
+ /* 28 */ {_SigNotify, "SIGWINCH: window size change"},
+ /* 29 */ {_SigNotify, "SIGIO: i/o now possible"},
+ /* 30 */ {_SigNotify, "SIGPWR: power failure restart"},
+ /* 31 */ {_SigNotify, "SIGSYS: bad system call"},
+ /* 32 */ {_SigSetStack + _SigUnblock, "signal 32"}, /* SIGCANCEL; see issue 6997 */
+ /* 33 */ {_SigSetStack + _SigUnblock, "signal 33"}, /* SIGSETXID; see issues 3871, 9400, 12498 */
+ /* 34 */ {_SigNotify, "signal 34"},
+ /* 35 */ {_SigNotify, "signal 35"},
+ /* 36 */ {_SigNotify, "signal 36"},
+ /* 37 */ {_SigNotify, "signal 37"},
+ /* 38 */ {_SigNotify, "signal 38"},
+ /* 39 */ {_SigNotify, "signal 39"},
+ /* 40 */ {_SigNotify, "signal 40"},
+ /* 41 */ {_SigNotify, "signal 41"},
+ /* 42 */ {_SigNotify, "signal 42"},
+ /* 43 */ {_SigNotify, "signal 43"},
+ /* 44 */ {_SigNotify, "signal 44"},
+ /* 45 */ {_SigNotify, "signal 45"},
+ /* 46 */ {_SigNotify, "signal 46"},
+ /* 47 */ {_SigNotify, "signal 47"},
+ /* 48 */ {_SigNotify, "signal 48"},
+ /* 49 */ {_SigNotify, "signal 49"},
+ /* 50 */ {_SigNotify, "signal 50"},
+ /* 51 */ {_SigNotify, "signal 51"},
+ /* 52 */ {_SigNotify, "signal 52"},
+ /* 53 */ {_SigNotify, "signal 53"},
+ /* 54 */ {_SigNotify, "signal 54"},
+ /* 55 */ {_SigNotify, "signal 55"},
+ /* 56 */ {_SigNotify, "signal 56"},
+ /* 57 */ {_SigNotify, "signal 57"},
+ /* 58 */ {_SigNotify, "signal 58"},
+ /* 59 */ {_SigNotify, "signal 59"},
+ /* 60 */ {_SigNotify, "signal 60"},
+ /* 61 */ {_SigNotify, "signal 61"},
+ /* 62 */ {_SigNotify, "signal 62"},
+ /* 63 */ {_SigNotify, "signal 63"},
+ /* 64 */ {_SigNotify, "signal 64"},
+}
--- /dev/null
+// Copyright 2015 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 mips64 mips64le
+// +build linux
+
+package runtime
+
+type sigTabT struct {
+ flags int32
+ name string
+}
+
+var sigtable = [...]sigTabT{
+ /* 0 */ {0, "SIGNONE: no trap"},
+ /* 1 */ {_SigNotify + _SigKill, "SIGHUP: terminal line hangup"},
+ /* 2 */ {_SigNotify + _SigKill, "SIGINT: interrupt"},
+ /* 3 */ {_SigNotify + _SigThrow, "SIGQUIT: quit"},
+ /* 4 */ {_SigThrow + _SigUnblock, "SIGILL: illegal instruction"},
+ /* 5 */ {_SigThrow + _SigUnblock, "SIGTRAP: trace trap"},
+ /* 6 */ {_SigNotify + _SigThrow, "SIGABRT: abort"},
+ /* 7 */ {_SigNotify, "SIGEMT"},
+ /* 8 */ {_SigPanic + _SigUnblock, "SIGFPE: floating-point exception"},
+ /* 9 */ {0, "SIGKILL: kill"},
+ /* 10 */ {_SigPanic + _SigUnblock, "SIGBUS: bus error"},
+ /* 11 */ {_SigPanic + _SigUnblock, "SIGSEGV: segmentation violation"},
+ /* 12 */ {_SigNotify, "SIGSYS: bad system call"},
+ /* 13 */ {_SigNotify, "SIGPIPE: write to broken pipe"},
+ /* 14 */ {_SigNotify, "SIGALRM: alarm clock"},
+ /* 15 */ {_SigNotify + _SigKill, "SIGTERM: termination"},
+ /* 16 */ {_SigNotify, "SIGUSR1: user-defined signal 1"},
+ /* 17 */ {_SigNotify, "SIGUSR2: user-defined signal 2"},
+ /* 18 */ {_SigNotify + _SigUnblock, "SIGCHLD: child status has changed"},
+ /* 19 */ {_SigNotify, "SIGPWR: power failure restart"},
+ /* 20 */ {_SigNotify, "SIGWINCH: window size change"},
+ /* 21 */ {_SigNotify, "SIGURG: urgent condition on socket"},
+ /* 22 */ {_SigNotify, "SIGIO: i/o now possible"},
+ /* 23 */ {0, "SIGSTOP: stop, unblockable"},
+ /* 24 */ {_SigNotify + _SigDefault, "SIGTSTP: keyboard stop"},
+ /* 25 */ {0, "SIGCONT: continue"},
+ /* 26 */ {_SigNotify + _SigDefault, "SIGTTIN: background read from tty"},
+ /* 27 */ {_SigNotify + _SigDefault, "SIGTTOU: background write to tty"},
+ /* 28 */ {_SigNotify, "SIGVTALRM: virtual alarm clock"},
+ /* 29 */ {_SigNotify + _SigUnblock, "SIGPROF: profiling alarm clock"},
+ /* 30 */ {_SigNotify, "SIGXCPU: cpu limit exceeded"},
+ /* 31 */ {_SigNotify, "SIGXFSZ: file size limit exceeded"},
+ /* 32 */ {_SigSetStack + _SigUnblock, "signal 32"}, /* SIGCANCEL; see issue 6997 */
+ /* 33 */ {_SigSetStack + _SigUnblock, "signal 33"}, /* SIGSETXID; see issues 3871, 9400, 12498 */
+ /* 34 */ {_SigNotify, "signal 34"},
+ /* 35 */ {_SigNotify, "signal 35"},
+ /* 36 */ {_SigNotify, "signal 36"},
+ /* 37 */ {_SigNotify, "signal 37"},
+ /* 38 */ {_SigNotify, "signal 38"},
+ /* 39 */ {_SigNotify, "signal 39"},
+ /* 40 */ {_SigNotify, "signal 40"},
+ /* 41 */ {_SigNotify, "signal 41"},
+ /* 42 */ {_SigNotify, "signal 42"},
+ /* 43 */ {_SigNotify, "signal 43"},
+ /* 44 */ {_SigNotify, "signal 44"},
+ /* 45 */ {_SigNotify, "signal 45"},
+ /* 46 */ {_SigNotify, "signal 46"},
+ /* 47 */ {_SigNotify, "signal 47"},
+ /* 48 */ {_SigNotify, "signal 48"},
+ /* 49 */ {_SigNotify, "signal 49"},
+ /* 50 */ {_SigNotify, "signal 50"},
+ /* 51 */ {_SigNotify, "signal 51"},
+ /* 52 */ {_SigNotify, "signal 52"},
+ /* 53 */ {_SigNotify, "signal 53"},
+ /* 54 */ {_SigNotify, "signal 54"},
+ /* 55 */ {_SigNotify, "signal 55"},
+ /* 56 */ {_SigNotify, "signal 56"},
+ /* 57 */ {_SigNotify, "signal 57"},
+ /* 58 */ {_SigNotify, "signal 58"},
+ /* 59 */ {_SigNotify, "signal 59"},
+ /* 60 */ {_SigNotify, "signal 60"},
+ /* 61 */ {_SigNotify, "signal 61"},
+ /* 62 */ {_SigNotify, "signal 62"},
+ /* 63 */ {_SigNotify, "signal 63"},
+ /* 64 */ {_SigNotify, "signal 64"},
+}
callerpc := getcallerpc(unsafe.Pointer(&t))
racereadrangepc(old.array, uintptr(old.len*int(t.elem.size)), callerpc, funcPC(growslice))
}
+ if msanenabled {
+ msanread(old.array, uintptr(old.len*int(t.elem.size)))
+ }
et := t.elem
if et.size == 0 {
} else {
// Note: can't use rawmem (which avoids zeroing of memory), because then GC can scan uninitialized memory.
p = newarray(et, uintptr(newcap))
- if !writeBarrierEnabled {
+ if !writeBarrier.enabled {
memmove(p, old.array, lenmem)
} else {
for i := uintptr(0); i < lenmem; i += et.size {
racewriterangepc(to.array, uintptr(n*int(width)), callerpc, pc)
racereadrangepc(fm.array, uintptr(n*int(width)), callerpc, pc)
}
+ if msanenabled {
+ msanwrite(to.array, uintptr(n*int(width)))
+ msanread(fm.array, uintptr(n*int(width)))
+ }
size := uintptr(n) * width
if size == 1 { // common case worth about 2x to do here
pc := funcPC(slicestringcopy)
racewriterangepc(unsafe.Pointer(&to[0]), uintptr(n), callerpc, pc)
}
+ if msanenabled {
+ msanwrite(unsafe.Pointer(&to[0]), uintptr(n))
+ }
- memmove(unsafe.Pointer(&to[0]), unsafe.Pointer((*stringStruct)(unsafe.Pointer(&fm)).str), uintptr(n))
+ memmove(unsafe.Pointer(&to[0]), unsafe.Pointer(stringStructOf(&fm).str), uintptr(n))
return n
}
// normalize x
exp := int((ix >> float64Shift) & float64Mask)
if exp == 0 { // subnormal x
- for ix&1<<float64Shift == 0 {
+ for ix&(1<<float64Shift) == 0 {
ix <<= 1
exp--
}
0,
math.Inf(1),
math.NaN(),
+ math.Float64frombits(2),
}
var sqrtSC = []float64{
math.NaN(),
0,
math.Inf(1),
math.NaN(),
+ 3.1434555694052576e-162,
}
package runtime
-import "unsafe"
+import (
+ "runtime/internal/atomic"
+ "runtime/internal/sys"
+ "unsafe"
+)
/*
Stack layout parameters.
// to each stack below the usual guard area for OS-specific
// purposes like signal handling. Used on Windows, Plan 9,
// and Darwin/ARM because they do not use a separate stack.
- _StackSystem = goos_windows*512*ptrSize + goos_plan9*512 + goos_darwin*goarch_arm*1024
+ _StackSystem = sys.GoosWindows*512*sys.PtrSize + sys.GoosPlan9*512 + sys.GoosDarwin*sys.GoarchArm*1024
// The minimum size of stack used by Go code
_StackMin = 2048
// The stack guard is a pointer this many bytes above the
// bottom of the stack.
- _StackGuard = 1024*stackGuardMultiplier + _StackSystem
+ _StackGuard = 1024*sys.StackGuardMultiplier + _StackSystem
// After a stack split check the SP is allowed to be this
// many bytes below the stack guard. This saves an instruction
)
const (
- uintptrMask = 1<<(8*ptrSize) - 1
+ uintptrMask = 1<<(8*sys.PtrSize) - 1
poisonStack = uintptrMask & 0x6868686868686868
// Goroutine preemption request.
// order = log_2(size/FixedStack)
// There is a free list for each order.
// TODO: one lock per order?
-var stackpool [_NumStackOrders]mspan
+var stackpool [_NumStackOrders]mSpanList
var stackpoolmu mutex
// List of stack spans to be freed at the end of GC. Protected by
// stackpoolmu.
-var stackFreeQueue mspan
+var stackFreeQueue mSpanList
// Cached value of haveexperiment("framepointer")
var framepointer_enabled bool
throw("cache size must be a multiple of page size")
}
for i := range stackpool {
- mSpanList_Init(&stackpool[i])
+ stackpool[i].init()
}
- mSpanList_Init(&stackFreeQueue)
+ stackFreeQueue.init()
}
// Allocates a stack from the free pool. Must be called with
// stackpoolmu held.
func stackpoolalloc(order uint8) gclinkptr {
list := &stackpool[order]
- s := list.next
- if s == list {
+ s := list.first
+ if s == nil {
// no free stacks. Allocate another span worth.
- s = mHeap_AllocStack(&mheap_, _StackCacheSize>>_PageShift)
+ s = mheap_.allocStack(_StackCacheSize >> _PageShift)
if s == nil {
throw("out of memory")
}
x.ptr().next = s.freelist
s.freelist = x
}
- mSpanList_Insert(list, s)
+ list.insert(s)
}
x := s.freelist
if x.ptr() == nil {
s.ref++
if s.freelist.ptr() == nil {
// all stacks in s are allocated.
- mSpanList_Remove(s)
+ list.remove(s)
}
return x
}
// Adds stack x to the free pool. Must be called with stackpoolmu held.
func stackpoolfree(x gclinkptr, order uint8) {
- s := mHeap_Lookup(&mheap_, unsafe.Pointer(x))
+ s := mheap_.lookup(unsafe.Pointer(x))
if s.state != _MSpanStack {
throw("freeing stack not in a stack span")
}
if s.freelist.ptr() == nil {
// s will now have a free stack
- mSpanList_Insert(&stackpool[order], s)
+ stackpool[order].insert(s)
}
x.ptr().next = s.freelist
s.freelist = x
// pointer into a free span.
//
// By not freeing, we prevent step #4 until GC is done.
- mSpanList_Remove(s)
+ stackpool[order].remove(s)
s.freelist = 0
- mHeap_FreeStack(&mheap_, s)
+ mheap_.freeStack(s)
}
}
}
v = unsafe.Pointer(x)
} else {
- s := mHeap_AllocStack(&mheap_, round(uintptr(n), _PageSize)>>_PageShift)
+ s := mheap_.allocStack(round(uintptr(n), _PageSize) >> _PageShift)
if s == nil {
throw("out of memory")
}
if raceenabled {
racemalloc(v, uintptr(n))
}
+ if msanenabled {
+ msanmalloc(v, uintptr(n))
+ }
if stackDebug >= 1 {
print(" allocated ", v, "\n")
}
}
return
}
+ if msanenabled {
+ msanfree(v, n)
+ }
if stackCache != 0 && n < _FixedStack<<_NumStackOrders && n < _StackCacheSize {
order := uint8(0)
n2 := n
c.stackcache[order].size += n
}
} else {
- s := mHeap_Lookup(&mheap_, v)
+ s := mheap_.lookup(v)
if s.state != _MSpanStack {
println(hex(s.start<<_PageShift), v)
throw("bad span state")
if gcphase == _GCoff {
// Free the stack immediately if we're
// sweeping.
- mHeap_FreeStack(&mheap_, s)
+ mheap_.freeStack(s)
} else {
// Otherwise, add it to a list of stack spans
// to be freed at the end of GC.
// these spans as stacks, like we do for small
// stack spans. (See issue #11466.)
lock(&stackpoolmu)
- mSpanList_Insert(&stackFreeQueue, s)
+ stackFreeQueue.insert(s)
unlock(&stackpoolmu)
}
}
type adjustinfo struct {
old stack
delta uintptr // ptr distance from old to new stack (newbase - oldbase)
+ cache pcvalueCache
}
// Adjustpointer checks whether *vpp is in the old stack described by adjinfo.
num := uintptr(bv.n)
for i := uintptr(0); i < num; i++ {
if stackDebug >= 4 {
- print(" ", add(scanp, i*ptrSize), ":", ptrnames[ptrbit(&bv, i)], ":", hex(*(*uintptr)(add(scanp, i*ptrSize))), " # ", i, " ", bv.bytedata[i/8], "\n")
+ print(" ", add(scanp, i*sys.PtrSize), ":", ptrnames[ptrbit(&bv, i)], ":", hex(*(*uintptr)(add(scanp, i*sys.PtrSize))), " # ", i, " ", bv.bytedata[i/8], "\n")
}
if ptrbit(&bv, i) == 1 {
- pp := (*uintptr)(add(scanp, i*ptrSize))
+ pp := (*uintptr)(add(scanp, i*sys.PtrSize))
p := *pp
if f != nil && 0 < p && p < _PageSize && debug.invalidptr != 0 || p == poisonStack {
// Looks like a junk value in a pointer slot.
if targetpc != f.entry {
targetpc--
}
- pcdata := pcdatavalue(f, _PCDATA_StackMapIndex, targetpc)
+ pcdata := pcdatavalue(f, _PCDATA_StackMapIndex, targetpc, &adjinfo.cache)
if pcdata == -1 {
pcdata = 0 // in prologue
}
// Adjust local variables if stack frame has been allocated.
size := frame.varp - frame.sp
var minsize uintptr
- switch thechar {
+ switch sys.TheChar {
case '7':
- minsize = spAlign
+ minsize = sys.SpAlign
default:
- minsize = minFrameSize
+ minsize = sys.MinFrameSize
}
if size > minsize {
var bv bitvector
throw("bad symbol table")
}
bv = stackmapdata(stackmap, pcdata)
- size = uintptr(bv.n) * ptrSize
+ size = uintptr(bv.n) * sys.PtrSize
if stackDebug >= 3 {
- print(" locals ", pcdata, "/", stackmap.n, " ", size/ptrSize, " words ", bv.bytedata, "\n")
+ print(" locals ", pcdata, "/", stackmap.n, " ", size/sys.PtrSize, " words ", bv.bytedata, "\n")
}
adjustpointers(unsafe.Pointer(frame.varp-size), &bv, adjinfo, f)
}
// Adjust saved base pointer if there is one.
- if thechar == '6' && frame.argp-frame.varp == 2*regSize {
+ if sys.TheChar == '6' && frame.argp-frame.varp == 2*sys.RegSize {
if !framepointer_enabled {
print("runtime: found space for saved base pointer, but no framepointer experiment\n")
print("argp=", hex(frame.argp), " varp=", hex(frame.varp), "\n")
// NOTE: stackguard0 may change underfoot, if another thread
// is about to try to preempt gp. Read it just once and use that same
// value now and below.
- preempt := atomicloaduintptr(&gp.stackguard0) == stackPreempt
+ preempt := atomic.Loaduintptr(&gp.stackguard0) == stackPreempt
// Be conservative about where we preempt.
// We are interested in preempting user Go code, not runtime code.
throw("missing stack in newstack")
}
sp := gp.sched.sp
- if thechar == '6' || thechar == '8' {
+ if sys.TheChar == '6' || sys.TheChar == '8' {
// The call to morestack cost a word.
- sp -= ptrSize
+ sp -= sys.PtrSize
}
if stackDebug >= 1 || sp < gp.stack.lo {
print("runtime: newstack sp=", hex(sp), " stack=[", hex(gp.stack.lo), ", ", hex(gp.stack.hi), "]\n",
if gp.syscallsp != 0 {
return
}
- if goos_windows != 0 && gp.m != nil && gp.m.libcallsp != 0 {
+ if sys.GoosWindows != 0 && gp.m != nil && gp.m.libcallsp != 0 {
return
}
// Scan stack pools for empty stack spans.
for order := range stackpool {
list := &stackpool[order]
- for s := list.next; s != list; {
+ for s := list.first; s != nil; {
next := s.next
if s.ref == 0 {
- mSpanList_Remove(s)
+ list.remove(s)
s.freelist = 0
- mHeap_FreeStack(&mheap_, s)
+ mheap_.freeStack(s)
}
s = next
}
}
// Free queued stack spans.
- for stackFreeQueue.next != &stackFreeQueue {
- s := stackFreeQueue.next
- mSpanList_Remove(s)
- mHeap_FreeStack(&mheap_, s)
+ for !stackFreeQueue.isEmpty() {
+ s := stackFreeQueue.first
+ stackFreeQueue.remove(s)
+ mheap_.freeStack(s)
}
unlock(&stackpoolmu)
package runtime
import (
+ "runtime/internal/atomic"
"unsafe"
)
getcallerpc(unsafe.Pointer(&b)),
funcPC(slicebytetostring))
}
+ if msanenabled && l > 0 {
+ msanread(unsafe.Pointer(&b[0]), uintptr(l))
+ }
s, c := rawstringtmp(buf, l)
copy(c, b)
return s
// stringDataOnStack reports whether the string's data is
// stored on the current goroutine's stack.
func stringDataOnStack(s string) bool {
- ptr := uintptr((*stringStruct)(unsafe.Pointer(&s)).str)
+ ptr := uintptr(stringStructOf(&s).str)
stk := getg().stack
return stk.lo <= ptr && ptr < stk.hi
}
getcallerpc(unsafe.Pointer(&b)),
funcPC(slicebytetostringtmp))
}
+ if msanenabled && len(b) > 0 {
+ msanread(unsafe.Pointer(&b[0]), uintptr(len(b)))
+ }
return *(*string)(unsafe.Pointer(&b))
}
// The only such case today is:
// for i, c := range []byte(str)
- str := (*stringStruct)(unsafe.Pointer(&s))
+ str := stringStructOf(&s)
ret := slice{array: unsafe.Pointer(str.str), len: str.len, cap: str.len}
return *(*[]byte)(unsafe.Pointer(&ret))
}
getcallerpc(unsafe.Pointer(&a)),
funcPC(slicerunetostring))
}
+ if msanenabled && len(a) > 0 {
+ msanread(unsafe.Pointer(&a[0]), uintptr(len(a))*unsafe.Sizeof(a[0]))
+ }
var dum [4]byte
size1 := 0
for _, r := range a {
len int
}
+// Variant with *byte pointer type for DWARF debugging.
+type stringStructDWARF struct {
+ str *byte
+ len int
+}
+
+func stringStructOf(sp *string) *stringStruct {
+ return (*stringStruct)(unsafe.Pointer(sp))
+}
+
func intstring(buf *[4]byte, v int64) string {
var s string
var b []byte
func rawstring(size int) (s string, b []byte) {
p := mallocgc(uintptr(size), nil, flagNoScan|flagNoZero)
- (*stringStruct)(unsafe.Pointer(&s)).str = p
- (*stringStruct)(unsafe.Pointer(&s)).len = size
+ stringStructOf(&s).str = p
+ stringStructOf(&s).len = size
*(*slice)(unsafe.Pointer(&b)) = slice{p, size, size}
for {
ms := maxstring
- if uintptr(size) <= uintptr(ms) || casuintptr((*uintptr)(unsafe.Pointer(&maxstring)), uintptr(ms), uintptr(size)) {
+ if uintptr(size) <= uintptr(ms) || atomic.Casuintptr((*uintptr)(unsafe.Pointer(&maxstring)), uintptr(ms), uintptr(size)) {
return
}
}
s := *(*string)(unsafe.Pointer(&ss))
for {
ms := maxstring
- if uintptr(len(s)) <= ms || casuintptr(&maxstring, ms, uintptr(len(s))) {
+ if uintptr(len(s)) <= ms || atomic.Casuintptr(&maxstring, ms, uintptr(len(s))) {
break
}
}
import "unsafe"
-// Declarations for runtime services implemented in C or assembly.
-
-const ptrSize = 4 << (^uintptr(0) >> 63) // unsafe.Sizeof(uintptr(0)) but an ideal const
-const regSize = 4 << (^uintreg(0) >> 63) // unsafe.Sizeof(uintreg(0)) but an ideal const
-const spAlign = 1*(1-goarch_arm64) + 16*goarch_arm64 // SP alignment: 1 normally, 16 for ARM64
-
// Should be a built-in for unsafe.Pointer?
//go:nosplit
func add(p unsafe.Pointer, x uintptr) unsafe.Pointer {
// See the assembly implementations for more details.
func cgocallback_gofunc(fv uintptr, frame uintptr, framesize uintptr)
-//go:noescape
-func cas(ptr *uint32, old, new uint32) bool
-
-// NO go:noescape annotation; see atomic_pointer.go.
-func casp1(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool
-
-func nop() // call to prevent inlining of function body
-
-//go:noescape
-func casuintptr(ptr *uintptr, old, new uintptr) bool
-
-//go:noescape
-func atomicstoreuintptr(ptr *uintptr, new uintptr)
-
-//go:noescape
-func atomicloaduintptr(ptr *uintptr) uintptr
-
-//go:noescape
-func atomicloaduint(ptr *uint) uint
-
-// TODO: Write native implementations of int64 atomic ops (or improve
-// inliner). These portable ones can't be inlined right now, so we're
-// taking an extra function call hit.
-
-func atomicstoreint64(ptr *int64, new int64) {
- atomicstore64((*uint64)(unsafe.Pointer(ptr)), uint64(new))
-}
-
-func atomicloadint64(ptr *int64) int64 {
- return int64(atomicload64((*uint64)(unsafe.Pointer(ptr))))
-}
-
-func xaddint64(ptr *int64, delta int64) int64 {
- return int64(xadd64((*uint64)(unsafe.Pointer(ptr)), delta))
-}
-
// publicationBarrier performs a store/store barrier (a "publication"
// or "export" barrier). Some form of synchronization is required
// between initializing an object and making that object accessible to
import "unsafe"
+// Return values of access/connect/socket are the return values of the syscall
+// (may encode error numbers).
+
+// int access(const char *, int)
//go:noescape
func access(name *byte, mode int32) int32
-func connect(fd uintptr, addr unsafe.Pointer, len int32) int32
+// int connect(int, const struct sockaddr*, socklen_t)
+func connect(fd int32, addr unsafe.Pointer, len int32) int32
+// int socket(int, int, int)
func socket(domain int32, typ int32, prot int32) int32
package runtime
-import "unsafe"
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
// NOTE: Func does not expose the actual unexported fields, because we return *Func
// values to users, and we want to keep them from being able to overwrite the data
// and a byte giving the pointer width in bytes.
pcln := *(**[8]byte)(unsafe.Pointer(&datap.pclntable))
pcln32 := *(**[2]uint32)(unsafe.Pointer(&datap.pclntable))
- if pcln32[0] != 0xfffffffb || pcln[4] != 0 || pcln[5] != 0 || pcln[6] != _PCQuantum || pcln[7] != ptrSize {
+ if pcln32[0] != 0xfffffffb || pcln[4] != 0 || pcln[5] != 0 || pcln[6] != sys.PCQuantum || pcln[7] != sys.PtrSize {
println("runtime: function symbol table header:", hex(pcln32[0]), hex(pcln[4]), hex(pcln[5]), hex(pcln[6]), hex(pcln[7]))
throw("invalid function symbol table\n")
}
// ftab is lookup table for function by program counter.
nftab := len(datap.ftab) - 1
+ var pcCache pcvalueCache
for i := 0; i < nftab; i++ {
// NOTE: ftab[nftab].entry is legal; it is the address beyond the final function.
if datap.ftab[i].entry > datap.ftab[i+1].entry {
}
}
}
- pcvalue(f, f.pcfile, end, true)
- pcvalue(f, f.pcln, end, true)
- pcvalue(f, f.pcsp, end, true)
+ pcvalue(f, f.pcfile, end, &pcCache, true)
+ pcvalue(f, f.pcln, end, &pcCache, true)
+ pcvalue(f, f.pcsp, end, &pcCache, true)
}
}
return (*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[idx].funcoff]))
}
-func pcvalue(f *_func, off int32, targetpc uintptr, strict bool) int32 {
+type pcvalueCache struct {
+ entries [16]pcvalueCacheEnt
+}
+
+type pcvalueCacheEnt struct {
+ // targetpc and off together are the key of this cache entry.
+ targetpc uintptr
+ off int32
+ // val is the value of this cached pcvalue entry.
+ val int32
+}
+
+func pcvalue(f *_func, off int32, targetpc uintptr, cache *pcvalueCache, strict bool) int32 {
if off == 0 {
return -1
}
+
+ // Check the cache. This speeds up walks of deep stacks, which
+ // tend to have the same recursive functions over and over.
+ //
+ // This cache is small enough that full associativity is
+ // cheaper than doing the hashing for a less associative
+ // cache.
+ if cache != nil {
+ for _, ent := range cache.entries {
+ // We check off first because we're more
+ // likely to have multiple entries with
+ // different offsets for the same targetpc
+ // than the other way around, so we'll usually
+ // fail in the first clause.
+ if ent.off == off && ent.targetpc == targetpc {
+ return ent.val
+ }
+ }
+ }
+
datap := findmoduledatap(f.entry) // inefficient
if datap == nil {
if strict && panicking == 0 {
break
}
if targetpc < pc {
+ // Replace a random entry in the cache. Random
+ // replacement prevents a performance cliff if
+ // a recursive stack's cycle is slightly
+ // larger than the cache.
+ if cache != nil {
+ ci := fastrand1() % uint32(len(cache.entries))
+ cache.entries[ci] = pcvalueCacheEnt{
+ targetpc: targetpc,
+ off: off,
+ val: val,
+ }
+ }
+
return val
}
}
if datap == nil {
return "?", 0
}
- fileno := int(pcvalue(f, f.pcfile, targetpc, strict))
- line = pcvalue(f, f.pcln, targetpc, strict)
+ fileno := int(pcvalue(f, f.pcfile, targetpc, nil, strict))
+ line = pcvalue(f, f.pcln, targetpc, nil, strict)
if fileno == -1 || line == -1 || fileno >= len(datap.filetab) {
// print("looking for ", hex(targetpc), " in ", funcname(f), " got file=", fileno, " line=", lineno, "\n")
return "?", 0
return funcline1(f, targetpc, true)
}
-func funcspdelta(f *_func, targetpc uintptr) int32 {
- x := pcvalue(f, f.pcsp, targetpc, true)
- if x&(ptrSize-1) != 0 {
+func funcspdelta(f *_func, targetpc uintptr, cache *pcvalueCache) int32 {
+ x := pcvalue(f, f.pcsp, targetpc, cache, true)
+ if x&(sys.PtrSize-1) != 0 {
print("invalid spdelta ", funcname(f), " ", hex(f.entry), " ", hex(targetpc), " ", hex(f.pcsp), " ", x, "\n")
}
return x
}
-func pcdatavalue(f *_func, table int32, targetpc uintptr) int32 {
+func pcdatavalue(f *_func, table int32, targetpc uintptr, cache *pcvalueCache) int32 {
if table < 0 || table >= f.npcdata {
return -1
}
off := *(*int32)(add(unsafe.Pointer(&f.nfuncdata), unsafe.Sizeof(f.nfuncdata)+uintptr(table)*4))
- return pcvalue(f, off, targetpc, true)
+ return pcvalue(f, off, targetpc, cache, true)
}
func funcdata(f *_func, i int32) unsafe.Pointer {
return nil
}
p := add(unsafe.Pointer(&f.nfuncdata), unsafe.Sizeof(f.nfuncdata)+uintptr(f.npcdata)*4)
- if ptrSize == 8 && uintptr(p)&4 != 0 {
+ if sys.PtrSize == 8 && uintptr(p)&4 != 0 {
if uintptr(unsafe.Pointer(f))&4 != 0 {
println("runtime: misaligned func", f)
}
p = add(p, 4)
}
- return *(*unsafe.Pointer)(add(p, uintptr(i)*ptrSize))
+ return *(*unsafe.Pointer)(add(p, uintptr(i)*sys.PtrSize))
}
// step advances to the next pc, value pair in the encoded table.
}
vdelta := int32(uvdelta)
p, pcdelta := readvarint(p)
- *pc += uintptr(pcdelta * _PCQuantum)
+ *pc += uintptr(pcdelta * sys.PCQuantum)
*val += vdelta
return p, true
}
// SP = stack - C_32_STK_ALIGN
TEXT runtime·bsdthread_start(SB),NOSPLIT,$0
// set up ldt 7+id to point at m->tls.
- // m->tls is at m+40. newosproc left
- // the m->id in tls[0].
LEAL m_tls(DX), BP
- MOVL 0(BP), DI
+ MOVL m_id(DX), DI
ADDL $7, DI // m0 is LDT#7. count up.
// setldt(tls#, &tls, sizeof tls)
PUSHAL // save registers
#define SYS_kill 37
#define SYS_getpid 20
#define SYS___pthread_kill 328
+#define SYS_pthread_sigmask 329
#define SYS_setitimer 83
#define SYS___sysctl 202
-#define SYS_sigprocmask 48
#define SYS_sigaction 46
#define SYS_sigreturn 184
#define SYS_select 93
MOVW sig+0(FP), R0
MOVW new+4(FP), R1
MOVW old+8(FP), R2
- MOVW $SYS_sigprocmask, R12
+ MOVW $SYS_pthread_sigmask, R12
SWI $0x80
BL.CS notok<>(SB)
RET
SWI $0x80
RET
-TEXT runtime·cas(SB),NOSPLIT,$0
- B runtime·armcas(SB)
-
-TEXT runtime·casp1(SB),NOSPLIT,$0
- B runtime·cas(SB)
-
TEXT ·publicationBarrier(SB),NOSPLIT,$-4-0
B runtime·armPublicationBarrier(SB)
#define SYS_kill 37
#define SYS_getpid 20
#define SYS___pthread_kill 328
+#define SYS_pthread_sigmask 329
#define SYS_setitimer 83
#define SYS___sysctl 202
-#define SYS_sigprocmask 48
#define SYS_sigaction 46
#define SYS_sigreturn 184
#define SYS_select 93
MOVW sig+0(FP), R0
MOVD new+8(FP), R1
MOVD old+16(FP), R2
- MOVW $SYS_sigprocmask, R16
+ MOVW $SYS_pthread_sigmask, R16
SVC $0x80
BCC 2(PC)
BL notok<>(SB)
MOVL mm+0(FP), AX
MOVL m_g0(AX), BX
LEAL m_tls(AX), BP
- MOVL 0(BP), DI
+ MOVL m_id(AX), DI
ADDL $7, DI
PUSHAL
PUSHL $32
SWI $0
RET
-TEXT runtime·casp1(SB),NOSPLIT,$0
- B runtime·cas(SB)
-
-// TODO(minux): this is only valid for ARMv6+
-// bool armcas(int32 *val, int32 old, int32 new)
-// Atomically:
-// if(*val == old){
-// *val = new;
-// return 1;
-// }else
-// return 0;
-TEXT runtime·cas(SB),NOSPLIT,$0
- B runtime·armcas(SB)
-
// TODO: this is only valid for ARMv7+
TEXT ·publicationBarrier(SB),NOSPLIT,$-4-0
B runtime·armPublicationBarrier(SB)
TEXT runtime·exit(SB),NOSPLIT,$0
MOVL $252, AX // syscall number
MOVL code+0(FP), BX
- CALL *runtime·_vdso(SB)
+ CALL 0x10(GS)
INT $3 // not reached
RET
TEXT runtime·exit1(SB),NOSPLIT,$0
MOVL $1, AX // exit - exit the current os thread
MOVL code+0(FP), BX
- CALL *runtime·_vdso(SB)
+ CALL 0x10(GS)
INT $3 // not reached
RET
MOVL name+0(FP), BX
MOVL mode+4(FP), CX
MOVL perm+8(FP), DX
- CALL *runtime·_vdso(SB)
+ CALL 0x10(GS)
CMPL AX, $0xfffff001
JLS 2(PC)
MOVL $-1, AX
TEXT runtime·closefd(SB),NOSPLIT,$0
MOVL $6, AX // syscall - close
MOVL fd+0(FP), BX
- CALL *runtime·_vdso(SB)
+ CALL 0x10(GS)
CMPL AX, $0xfffff001
JLS 2(PC)
MOVL $-1, AX
MOVL fd+0(FP), BX
MOVL p+4(FP), CX
MOVL n+8(FP), DX
- CALL *runtime·_vdso(SB)
+ CALL 0x10(GS)
CMPL AX, $0xfffff001
JLS 2(PC)
MOVL $-1, AX
MOVL fd+0(FP), BX
MOVL p+4(FP), CX
MOVL n+8(FP), DX
- CALL *runtime·_vdso(SB)
+ CALL 0x10(GS)
CMPL AX, $0xfffff001
JLS 2(PC)
MOVL $-1, AX
MOVL $191, AX // syscall - ugetrlimit
MOVL kind+0(FP), BX
MOVL limit+4(FP), CX
- CALL *runtime·_vdso(SB)
+ CALL 0x10(GS)
MOVL AX, ret+8(FP)
RET
MOVL $0, DX
MOVL $0, SI
LEAL 0(SP), DI
- CALL *runtime·_vdso(SB)
+ CALL 0x10(GS)
RET
TEXT runtime·gettid(SB),NOSPLIT,$0-4
MOVL $224, AX // syscall - gettid
- CALL *runtime·_vdso(SB)
+ CALL 0x10(GS)
MOVL AX, ret+0(FP)
RET
TEXT runtime·raise(SB),NOSPLIT,$12
MOVL $224, AX // syscall - gettid
- CALL *runtime·_vdso(SB)
+ CALL 0x10(GS)
MOVL AX, BX // arg 1 tid
MOVL sig+0(FP), CX // arg 2 signal
MOVL $238, AX // syscall - tkill
- CALL *runtime·_vdso(SB)
+ CALL 0x10(GS)
RET
TEXT runtime·raiseproc(SB),NOSPLIT,$12
MOVL $20, AX // syscall - getpid
- CALL *runtime·_vdso(SB)
+ CALL 0x10(GS)
MOVL AX, BX // arg 1 pid
MOVL sig+0(FP), CX // arg 2 signal
MOVL $37, AX // syscall - kill
- CALL *runtime·_vdso(SB)
+ CALL 0x10(GS)
RET
TEXT runtime·setitimer(SB),NOSPLIT,$0-12
MOVL mode+0(FP), BX
MOVL new+4(FP), CX
MOVL old+8(FP), DX
- CALL *runtime·_vdso(SB)
+ CALL 0x10(GS)
RET
TEXT runtime·mincore(SB),NOSPLIT,$0-16
MOVL addr+0(FP), BX
MOVL n+4(FP), CX
MOVL dst+8(FP), DX
- CALL *runtime·_vdso(SB)
+ CALL 0x10(GS)
MOVL AX, ret+12(FP)
RET
MOVL $0, BX // CLOCK_REALTIME
LEAL 8(SP), CX
MOVL $0, DX
- CALL *runtime·_vdso(SB)
+ CALL 0x10(GS)
MOVL 8(SP), AX // sec
MOVL 12(SP), BX // nsec
MOVL $1, BX // CLOCK_MONOTONIC
LEAL 8(SP), CX
MOVL $0, DX
- CALL *runtime·_vdso(SB)
+ CALL 0x10(GS)
MOVL 8(SP), AX // sec
MOVL 12(SP), BX // nsec
MOVL new+4(FP), CX
MOVL old+8(FP), DX
MOVL size+12(FP), SI
- CALL *runtime·_vdso(SB)
+ CALL 0x10(GS)
CMPL AX, $0xfffff001
JLS 2(PC)
INT $3
MOVL new+4(FP), CX
MOVL old+8(FP), DX
MOVL size+12(FP), SI
- CALL *runtime·_vdso(SB)
+ CALL 0x10(GS)
MOVL AX, ret+16(FP)
RET
TEXT runtime·sigreturn(SB),NOSPLIT,$0
MOVL $173, AX // rt_sigreturn
// Sigreturn expects same SP as signal handler,
- // so cannot CALL *runtime._vsdo(SB) here.
+ // so cannot CALL 0x10(GS) here.
INT $0x80
- INT $3 // not reached
+ INT $3 // not reached
RET
TEXT runtime·mmap(SB),NOSPLIT,$0
MOVL fd+16(FP), DI
MOVL off+20(FP), BP
SHRL $12, BP
- CALL *runtime·_vdso(SB)
+ CALL 0x10(GS)
CMPL AX, $0xfffff001
JLS 3(PC)
NOTL AX
MOVL $91, AX // munmap
MOVL addr+0(FP), BX
MOVL n+4(FP), CX
- CALL *runtime·_vdso(SB)
+ CALL 0x10(GS)
CMPL AX, $0xfffff001
JLS 2(PC)
INT $3
MOVL addr+0(FP), BX
MOVL n+4(FP), CX
MOVL flags+8(FP), DX
- CALL *runtime·_vdso(SB)
+ CALL 0x10(GS)
// ignore failure - maybe pages are locked
RET
MOVL ts+12(FP), SI
MOVL addr2+16(FP), DI
MOVL val3+20(FP), BP
- CALL *runtime·_vdso(SB)
+ CALL 0x10(GS)
MOVL AX, ret+24(FP)
RET
MOVL SI, 8(CX)
MOVL $1234, 12(CX)
- // cannot use CALL *runtime·_vdso(SB) here, because
- // the stack changes during the system call (after
- // CALL *runtime·_vdso(SB), the child is still using
- // the parent's stack when executing its RET instruction).
+ // cannot use CALL 0x10(GS) here, because the stack changes during the
+ // system call (after CALL 0x10(GS), the child is still using the
+ // parent's stack when executing its RET instruction).
INT $0x80
// In parent, return.
// Initialize AX to Linux tid
MOVL $224, AX
- CALL *runtime·_vdso(SB)
+ CALL 0x10(GS)
MOVL 0(SP), BX // m
MOVL 4(SP), DX // g
MOVL AX, m_procid(BX) // save tid as m->procid
// set up ldt 7+id to point at m->tls.
- // newosproc left the id in tls[0].
LEAL m_tls(BX), BP
- MOVL 0(BP), DI
+ MOVL m_id(BX), DI
ADDL $7, DI // m0 is LDT#7. count up.
// setldt(tls#, &tls, sizeof tls)
PUSHAL // save registers
MOVL $186, AX // sigaltstack
MOVL new+4(SP), BX
MOVL old+8(SP), CX
- CALL *runtime·_vdso(SB)
+ CALL 0x10(GS)
CMPL AX, $0xfffff001
JLS 2(PC)
INT $3
MOVL entry+0(FP), BX // entry
MOVL address+4(FP), CX // base address
+#ifdef GOOS_android
+ /*
+ * Same as in sys_darwin_386.s:/ugliness, different constant.
+ * address currently holds m->tls, which must be %gs:0xf8.
+ * See cgo/gcc_android_386.c for the derivation of the constant.
+ */
+ SUBL $0xf8, CX
+ MOVL CX, 0(CX)
+#else
/*
* When linking against the system libraries,
* we use its pthread_create and let it set up %gs
*/
ADDL $0x4, CX // address
MOVL CX, 0(CX)
+#endif
+ // We copy the dynamic linker behaviour of storing the vsyscall entry point
+ // at 0x10(GS) so that it can be invoked by "CALL 0x10(GS)" in all
+ // situations, not only those where the binary is actually dynamically
+ // linked.
+ MOVL runtime·_vdso(SB), AX
+ MOVL AX, 0x10(CX)
// set up user_desc
LEAL 16(SP), AX // struct user_desc
MOVL AX, CX // user_desc
MOVL $16, DX // sizeof(user_desc)
MOVL $123, AX // syscall - modify_ldt
- CALL *runtime·_vdso(SB)
+ // We can't call this via 0x10(GS) because this is called from setldt0 to set that up.
+ INT $0x80
// breakpoint on error
CMPL AX, $0xfffff001
TEXT runtime·osyield(SB),NOSPLIT,$0
MOVL $158, AX
- CALL *runtime·_vdso(SB)
+ CALL 0x10(GS)
RET
TEXT runtime·sched_getaffinity(SB),NOSPLIT,$0
MOVL pid+0(FP), BX
MOVL len+4(FP), CX
MOVL buf+8(FP), DX
- CALL *runtime·_vdso(SB)
+ CALL 0x10(GS)
MOVL AX, ret+12(FP)
RET
TEXT runtime·epollcreate(SB),NOSPLIT,$0
MOVL $254, AX
MOVL size+0(FP), BX
- CALL *runtime·_vdso(SB)
+ CALL 0x10(GS)
MOVL AX, ret+4(FP)
RET
TEXT runtime·epollcreate1(SB),NOSPLIT,$0
MOVL $329, AX
MOVL flags+0(FP), BX
- CALL *runtime·_vdso(SB)
+ CALL 0x10(GS)
MOVL AX, ret+4(FP)
RET
MOVL op+4(FP), CX
MOVL fd+8(FP), DX
MOVL ev+12(FP), SI
- CALL *runtime·_vdso(SB)
+ CALL 0x10(GS)
MOVL AX, ret+16(FP)
RET
MOVL ev+4(FP), CX
MOVL nev+8(FP), DX
MOVL timeout+12(FP), SI
- CALL *runtime·_vdso(SB)
+ CALL 0x10(GS)
MOVL AX, ret+16(FP)
RET
MOVL fd+0(FP), BX // fd
MOVL $2, CX // F_SETFD
MOVL $1, DX // FD_CLOEXEC
- CALL *runtime·_vdso(SB)
+ CALL 0x10(GS)
+ RET
+
+// int access(const char *name, int mode)
+TEXT runtime·access(SB),NOSPLIT,$0
+ MOVL $33, AX // syscall - access
+ MOVL name+0(FP), BX
+ MOVL mode+4(FP), CX
+ CALL 0x10(GS)
+ MOVL AX, ret+8(FP)
+ RET
+
+// int connect(int fd, const struct sockaddr *addr, socklen_t addrlen)
+TEXT runtime·connect(SB),NOSPLIT,$0-16
+ // connect is implemented as socketcall(NR_socket, 3, *(rest of args))
+ // stack already should have fd, addr, addrlen.
+ MOVL $102, AX // syscall - socketcall
+ MOVL $3, BX // connect
+ LEAL fd+0(FP), CX
+ CALL 0x10(GS)
+ MOVL AX, ret+12(FP)
+ RET
+
+// int socket(int domain, int type, int protocol)
+TEXT runtime·socket(SB),NOSPLIT,$0-16
+ // socket is implemented as socketcall(NR_socket, 1, *(rest of args))
+ // stack already should have domain, type, protocol.
+ MOVL $102, AX // syscall - socketcall
+ MOVL $1, BX // socket
+ LEAL domain+0(FP), CX
+ CALL 0x10(GS)
+ MOVL AX, ret+12(FP)
RET
// set tls base to DI
TEXT runtime·settls(SB),NOSPLIT,$32
+#ifdef GOOS_android
+ // Same as in sys_darwin_386.s:/ugliness, different constant.
+ // DI currently holds m->tls, which must be fs:0x1d0.
+ // See cgo/gcc_android_amd64.c for the derivation of the constant.
+ SUBQ $0x1d0, DI // In android, the tls base
+#else
ADDQ $8, DI // ELF wants to use -8(FS)
-
+#endif
MOVQ DI, SI
MOVQ $0x1002, DI // ARCH_SET_FS
MOVQ $158, AX // arch_prctl
MOVL $72, AX // fcntl
SYSCALL
RET
+
+
+// int access(const char *name, int mode)
+TEXT runtime·access(SB),NOSPLIT,$0
+ MOVQ name+0(FP), DI
+ MOVL mode+8(FP), SI
+ MOVL $21, AX // syscall entry
+ SYSCALL
+ MOVL AX, ret+16(FP)
+ RET
+
+// int connect(int fd, const struct sockaddr *addr, socklen_t addrlen)
+TEXT runtime·connect(SB),NOSPLIT,$0-28
+ MOVL fd+0(FP), DI
+ MOVQ addr+8(FP), SI
+ MOVL addrlen+16(FP), DX
+ MOVL $42, AX // syscall entry
+ SYSCALL
+ MOVL AX, ret+24(FP)
+ RET
+
+// int socket(int domain, int type, int protocol)
+TEXT runtime·socket(SB),NOSPLIT,$0-20
+ MOVL domain+0(FP), DI
+ MOVL type+4(FP), SI
+ MOVL protocol+8(FP), DX
+ MOVL $41, AX // syscall entry
+ SYSCALL
+ MOVL AX, ret+16(FP)
+ RET
SWI $0
RET
-// Use kernel version instead of native armcas in asm_arm.s.
-// See ../sync/atomic/asm_linux_arm.s for details.
-TEXT cas<>(SB),NOSPLIT,$0
- MOVW $0xffff0fc0, R15 // R15 is hardware PC.
-
-TEXT runtime·cas(SB),NOSPLIT,$0
- MOVW ptr+0(FP), R2
- MOVW old+4(FP), R0
-loop:
- MOVW new+8(FP), R1
- BL cas<>(SB)
- BCC check
- MOVW $1, R0
- MOVB R0, ret+12(FP)
- RET
-check:
- // Kernel lies; double-check.
- MOVW ptr+0(FP), R2
- MOVW old+4(FP), R0
- MOVW 0(R2), R3
- CMP R0, R3
- BEQ loop
- MOVW $0, R0
- MOVB R0, ret+12(FP)
- RET
-
-TEXT runtime·casp1(SB),NOSPLIT,$0
- B runtime·cas(SB)
-
// As for cas, memory barriers are complicated on ARM, but the kernel
// provides a user helper. ARMv5 does not support SMP and has no
// memory barrier instruction at all. ARMv6 added SMP support and has
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux
+// +build mips64 mips64le
+
+//
+// System calls and other sys.stuff for mips64, Linux
+//
+
+#include "go_asm.h"
+#include "go_tls.h"
+#include "textflag.h"
+
+#define SYS_exit 5058
+#define SYS_read 5000
+#define SYS_write 5001
+#define SYS_open 5002
+#define SYS_close 5003
+#define SYS_getpid 5038
+#define SYS_kill 5060
+#define SYS_fcntl 5080
+#define SYS_gettimeofday 5094
+#define SYS_mmap 5009
+#define SYS_munmap 5011
+#define SYS_setitimer 5036
+#define SYS_clone 5055
+#define SYS_newselect 5022
+#define SYS_sched_yield 5023
+#define SYS_rt_sigreturn 5211
+#define SYS_rt_sigaction 5013
+#define SYS_rt_sigprocmask 5014
+#define SYS_sigaltstack 5129
+#define SYS_getrlimit 5095
+#define SYS_madvise 5027
+#define SYS_mincore 5026
+#define SYS_gettid 5178
+#define SYS_tkill 5192
+#define SYS_futex 5194
+#define SYS_sched_getaffinity 5196
+#define SYS_exit_group 5205
+#define SYS_epoll_create 5207
+#define SYS_epoll_ctl 5208
+#define SYS_epoll_wait 5209
+#define SYS_clock_gettime 5222
+#define SYS_epoll_create1 5285
+
+TEXT runtime·exit(SB),NOSPLIT,$-8-4
+ MOVW code+0(FP), R4
+ MOVV $SYS_exit_group, R2
+ SYSCALL
+ RET
+
+TEXT runtime·exit1(SB),NOSPLIT,$-8-4
+ MOVW code+0(FP), R4
+ MOVV $SYS_exit, R2
+ SYSCALL
+ RET
+
+TEXT runtime·open(SB),NOSPLIT,$-8-20
+ MOVV name+0(FP), R4
+ MOVW mode+8(FP), R5
+ MOVW perm+12(FP), R6
+ MOVV $SYS_open, R2
+ SYSCALL
+ BEQ R7, 2(PC)
+ MOVW $-1, R2
+ MOVW R2, ret+16(FP)
+ RET
+
+TEXT runtime·closefd(SB),NOSPLIT,$-8-12
+ MOVW fd+0(FP), R4
+ MOVV $SYS_close, R2
+ SYSCALL
+ BEQ R7, 2(PC)
+ MOVW $-1, R2
+ MOVW R2, ret+8(FP)
+ RET
+
+TEXT runtime·write(SB),NOSPLIT,$-8-28
+ MOVV fd+0(FP), R4
+ MOVV p+8(FP), R5
+ MOVW n+16(FP), R6
+ MOVV $SYS_write, R2
+ SYSCALL
+ BEQ R7, 2(PC)
+ MOVW $-1, R2
+ MOVW R2, ret+24(FP)
+ RET
+
+TEXT runtime·read(SB),NOSPLIT,$-8-28
+ MOVW fd+0(FP), R4
+ MOVV p+8(FP), R5
+ MOVW n+16(FP), R6
+ MOVV $SYS_read, R2
+ SYSCALL
+ BEQ R7, 2(PC)
+ MOVW $-1, R2
+ MOVW R2, ret+24(FP)
+ RET
+
+TEXT runtime·getrlimit(SB),NOSPLIT,$-8-20
+ MOVW kind+0(FP), R4 // _RLIMIT_AS = 6 on linux/mips
+ MOVV limit+8(FP), R5
+ MOVV $SYS_getrlimit, R2
+ SYSCALL
+ MOVW R2, ret+16(FP)
+ RET
+
+TEXT runtime·usleep(SB),NOSPLIT,$16-4
+ MOVWU usec+0(FP), R3
+ MOVV R3, R5
+ MOVW $1000000, R4
+ DIVVU R4, R3
+ MOVV LO, R3
+ MOVV R3, 8(R29)
+ MULVU R3, R4
+ MOVV LO, R4
+ SUBVU R4, R5
+ MOVV R5, 16(R29)
+
+ // select(0, 0, 0, 0, &tv)
+ MOVW $0, R4
+ MOVW $0, R5
+ MOVW $0, R6
+ MOVW $0, R7
+ ADDV $8, R29, R8
+ MOVV $SYS_newselect, R2
+ SYSCALL
+ RET
+
+TEXT runtime·gettid(SB),NOSPLIT,$0-4
+ MOVV $SYS_gettid, R2
+ SYSCALL
+ MOVW R2, ret+0(FP)
+ RET
+
+TEXT runtime·raise(SB),NOSPLIT,$-8
+ MOVV $SYS_gettid, R2
+ SYSCALL
+ MOVW R2, R4 // arg 1 tid
+ MOVW sig+0(FP), R5 // arg 2
+ MOVV $SYS_tkill, R2
+ SYSCALL
+ RET
+
+TEXT runtime·raiseproc(SB),NOSPLIT,$-8
+ MOVV $SYS_getpid, R2
+ SYSCALL
+ MOVW R2, R4 // arg 1 pid
+ MOVW sig+0(FP), R5 // arg 2
+ MOVV $SYS_kill, R2
+ SYSCALL
+ RET
+
+TEXT runtime·setitimer(SB),NOSPLIT,$-8-24
+ MOVW mode+0(FP), R4
+ MOVV new+8(FP), R5
+ MOVV old+16(FP), R6
+ MOVV $SYS_setitimer, R2
+ SYSCALL
+ RET
+
+TEXT runtime·mincore(SB),NOSPLIT,$-8-28
+ MOVV addr+0(FP), R4
+ MOVV n+8(FP), R5
+ MOVV dst+16(FP), R6
+ MOVV $SYS_mincore, R2
+ SYSCALL
+ MOVW R2, ret+24(FP)
+ RET
+
+// func now() (sec int64, nsec int32)
+TEXT time·now(SB),NOSPLIT,$16
+ MOVV $0(R29), R4
+ MOVV $0, R5
+ MOVV $SYS_gettimeofday, R2
+ SYSCALL
+ MOVV 0(R29), R3 // sec
+ MOVV 8(R29), R5 // usec
+ MOVV $1000, R4
+ MULVU R4, R5
+ MOVV LO, R5
+ MOVV R3, sec+0(FP)
+ MOVW R5, nsec+8(FP)
+ RET
+
+TEXT runtime·nanotime(SB),NOSPLIT,$16
+ MOVW $1, R4 // CLOCK_MONOTONIC
+ MOVV $0(R29), R5
+ MOVV $SYS_clock_gettime, R2
+ SYSCALL
+ MOVV 0(R29), R3 // sec
+ MOVV 8(R29), R5 // nsec
+ // sec is in R3, nsec in R5
+ // return nsec in R3
+ MOVV $1000000000, R4
+ MULVU R4, R3
+ MOVV LO, R3
+ ADDVU R5, R3
+ MOVV R3, ret+0(FP)
+ RET
+
+TEXT runtime·rtsigprocmask(SB),NOSPLIT,$-8-28
+ MOVW sig+0(FP), R4
+ MOVV new+8(FP), R5
+ MOVV old+16(FP), R6
+ MOVW size+24(FP), R7
+ MOVV $SYS_rt_sigprocmask, R2
+ SYSCALL
+ BEQ R7, 2(PC)
+ MOVV R0, 0xf1(R0) // crash
+ RET
+
+TEXT runtime·rt_sigaction(SB),NOSPLIT,$-8-36
+ MOVV sig+0(FP), R4
+ MOVV new+8(FP), R5
+ MOVV old+16(FP), R6
+ MOVV size+24(FP), R7
+ MOVV $SYS_rt_sigaction, R2
+ SYSCALL
+ MOVW R2, ret+32(FP)
+ RET
+
+TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
+ MOVW sig+8(FP), R4
+ MOVV info+16(FP), R5
+ MOVV ctx+24(FP), R6
+ MOVV fn+0(FP), R1
+ JAL (R1)
+ RET
+
+TEXT runtime·sigtramp(SB),NOSPLIT,$64
+ // initialize essential registers (just in case)
+ JAL runtime·reginit(SB)
+
+ // this might be called in external code context,
+ // where g is not set.
+ MOVB runtime·iscgo(SB), R1
+ BEQ R1, 2(PC)
+ JAL runtime·load_g(SB)
+
+ MOVW R4, 8(R29)
+ MOVV R5, 16(R29)
+ MOVV R6, 24(R29)
+ MOVV $runtime·sigtrampgo(SB), R1
+ JAL (R1)
+ RET
+
+TEXT runtime·mmap(SB),NOSPLIT,$-8
+ MOVV addr+0(FP), R4
+ MOVV n+8(FP), R5
+ MOVW prot+16(FP), R6
+ MOVW flags+20(FP), R7
+ MOVW fd+24(FP), R8
+ MOVW off+28(FP), R9
+
+ MOVV $SYS_mmap, R2
+ SYSCALL
+ MOVV R2, ret+32(FP)
+ RET
+
+TEXT runtime·munmap(SB),NOSPLIT,$-8
+ MOVV addr+0(FP), R4
+ MOVV n+8(FP), R5
+ MOVV $SYS_munmap, R2
+ SYSCALL
+ BEQ R7, 2(PC)
+ MOVV R0, 0xf3(R0) // crash
+ RET
+
+TEXT runtime·madvise(SB),NOSPLIT,$-8
+ MOVV addr+0(FP), R4
+ MOVV n+8(FP), R5
+ MOVW flags+16(FP), R6
+ MOVV $SYS_madvise, R2
+ SYSCALL
+ // ignore failure - maybe pages are locked
+ RET
+
+// int64 futex(int32 *uaddr, int32 op, int32 val,
+// struct timespec *timeout, int32 *uaddr2, int32 val2);
+TEXT runtime·futex(SB),NOSPLIT,$-8
+ MOVV addr+0(FP), R4
+ MOVW op+8(FP), R5
+ MOVW val+12(FP), R6
+ MOVV ts+16(FP), R7
+ MOVV addr2+24(FP), R8
+ MOVW val3+32(FP), R9
+ MOVV $SYS_futex, R2
+ SYSCALL
+ MOVW R2, ret+40(FP)
+ RET
+
+// int64 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void));
+TEXT runtime·clone(SB),NOSPLIT,$-8
+ MOVW flags+0(FP), R4
+ MOVV stk+8(FP), R5
+
+ // Copy mp, gp, fn off parent stack for use by child.
+ // Careful: Linux system call clobbers ???.
+ MOVV mm+16(FP), R16
+ MOVV gg+24(FP), R17
+ MOVV fn+32(FP), R18
+
+ MOVV R16, -8(R5)
+ MOVV R17, -16(R5)
+ MOVV R18, -24(R5)
+ MOVV $1234, R16
+ MOVV R16, -32(R5)
+
+ MOVV $SYS_clone, R2
+ SYSCALL
+
+ // In parent, return.
+ BEQ R2, 3(PC)
+ MOVW R2, ret+40(FP)
+ RET
+
+ // In child, on new stack.
+ // initialize essential registers
+ JAL runtime·reginit(SB)
+ MOVV -32(R29), R16
+ MOVV $1234, R1
+ BEQ R16, R1, 2(PC)
+ MOVV R0, 0(R0)
+
+ // Initialize m->procid to Linux tid
+ MOVV $SYS_gettid, R2
+ SYSCALL
+
+ MOVV -24(R29), R18 // fn
+ MOVV -16(R29), R17 // g
+ MOVV -8(R29), R16 // m
+
+ BEQ R16, nog
+ BEQ R17, nog
+
+ MOVV R2, m_procid(R16)
+
+ // TODO: setup TLS.
+
+ // In child, set up new stack
+ MOVV R16, g_m(R17)
+ MOVV R17, g
+ //CALL runtime·stackcheck(SB)
+
+nog:
+ // Call fn
+ JAL (R18)
+
+ // It shouldn't return. If it does, exit that thread.
+ MOVW $111, R4
+ MOVV $SYS_exit, R2
+ SYSCALL
+ JMP -3(PC) // keep exiting
+
+TEXT runtime·sigaltstack(SB),NOSPLIT,$-8
+ MOVV new+0(FP), R4
+ MOVV old+8(FP), R5
+ MOVV $SYS_sigaltstack, R2
+ SYSCALL
+ BEQ R7, 2(PC)
+ MOVV R0, 0xf1(R0) // crash
+ RET
+
+TEXT runtime·osyield(SB),NOSPLIT,$-8
+ MOVV $SYS_sched_yield, R2
+ SYSCALL
+ RET
+
+TEXT runtime·sched_getaffinity(SB),NOSPLIT,$-8
+ MOVV pid+0(FP), R4
+ MOVV len+8(FP), R5
+ MOVV buf+16(FP), R6
+ MOVV $SYS_sched_getaffinity, R2
+ SYSCALL
+ MOVW R2, ret+24(FP)
+ RET
+
+// int32 runtime·epollcreate(int32 size);
+TEXT runtime·epollcreate(SB),NOSPLIT,$-8
+ MOVW size+0(FP), R4
+ MOVV $SYS_epoll_create, R2
+ SYSCALL
+ MOVW R2, ret+8(FP)
+ RET
+
+// int32 runtime·epollcreate1(int32 flags);
+TEXT runtime·epollcreate1(SB),NOSPLIT,$-8
+ MOVW flags+0(FP), R4
+ MOVV $SYS_epoll_create1, R2
+ SYSCALL
+ MOVW R2, ret+8(FP)
+ RET
+
+// func epollctl(epfd, op, fd int32, ev *epollEvent) int
+TEXT runtime·epollctl(SB),NOSPLIT,$-8
+ MOVW epfd+0(FP), R4
+ MOVW op+4(FP), R5
+ MOVW fd+8(FP), R6
+ MOVV ev+16(FP), R7
+ MOVV $SYS_epoll_ctl, R2
+ SYSCALL
+ MOVW R2, ret+24(FP)
+ RET
+
+// int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout);
+TEXT runtime·epollwait(SB),NOSPLIT,$-8
+ MOVW epfd+0(FP), R4
+ MOVV ev+8(FP), R5
+ MOVW nev+16(FP), R6
+ MOVW timeout+20(FP), R7
+ MOVV $SYS_epoll_wait, R2
+ SYSCALL
+ MOVW R2, ret+24(FP)
+ RET
+
+// void runtime·closeonexec(int32 fd);
+TEXT runtime·closeonexec(SB),NOSPLIT,$-8
+ MOVW fd+0(FP), R4 // fd
+ MOVV $2, R5 // F_SETFD
+ MOVV $1, R6 // FD_CLOEXEC
+ MOVV $SYS_fcntl, R2
+ SYSCALL
+ RET
MOVD fn+0(FP), R12
MOVD R12, CTR
BL (CTR)
+ MOVD 24(R1), R2
RET
#ifdef GOARCH_ppc64le
MOVD $runtime·sigtrampgo(SB), R12
MOVD R12, CTR
BL (CTR)
+ MOVD 24(R1), R2
RET
TEXT runtime·mmap(SB),NOSPLIT|NOFRAME,$0
--- /dev/null
+// Copyright 2015 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 mips64 mips64le
+
+package runtime
+
+import "unsafe"
+
+// adjust Gobuf as if it executed a call to fn with context ctxt
+// and then did an immediate Gosave.
+func gostartcall(buf *gobuf, fn, ctxt unsafe.Pointer) {
+ if buf.lr != 0 {
+ throw("invalid use of gostartcall")
+ }
+ buf.lr = buf.pc
+ buf.pc = uintptr(fn)
+ buf.ctxt = ctxt
+}
+
+// Called to rewind context saved during morestack back to beginning of function.
+// To help us, the linker emits a jmp back to the beginning right after the
+// call to morestack. We just have to decode and apply that jump.
+func rewindmorestack(buf *gobuf) {
+ var inst uint32
+ if buf.pc&3 == 0 && buf.pc != 0 {
+ inst = *(*uint32)(unsafe.Pointer(buf.pc))
+ if inst>>26 == 2 { // JMP addr
+ //print("runtime: rewind pc=", hex(buf.pc), " to pc=", hex(buf.pc &^ uintptr(1<<28-1) | uintptr((inst&^0xfc000000)<<2)), "\n");
+ buf.pc &^= 1<<28 - 1
+ buf.pc |= uintptr((inst &^ 0xfc000000) << 2)
+ return
+ }
+ if inst>>16 == 0x1000 { // BEQ R0, R0, offset
+ //print("runtime: rewind pc=", hex(buf.pc), " to pc=", hex(buf.pc + uintptr(int32(int16(inst&0xffff))<<2 + 4)), "\n");
+ buf.pc += uintptr(int32(int16(inst&0xffff))<<2 + 4)
+ return
+ }
+ }
+ print("runtime: pc=", hex(buf.pc), " ", hex(inst), "\n")
+ throw("runtime: misuse of rewindmorestack")
+}
NACL_SYSCALL(SYS_get_random_bytes)
RET
-TEXT runtime·casp1(SB),NOSPLIT,$0
- B runtime·cas(SB)
-
-// This is only valid for ARMv6+, however, NaCl/ARM is only defined
-// for ARMv7A anyway.
-// bool armcas(int32 *val, int32 old, int32 new)
-// AtomiBLy:
-// if(*val == old){
-// *val = new;
-// return 1;
-// }else
-// return 0;
-TEXT runtime·cas(SB),NOSPLIT,$0
- B runtime·armcas(SB)
-
// Likewise, this is only valid for ARMv7+, but that's okay.
TEXT ·publicationBarrier(SB),NOSPLIT,$-4-0
B runtime·armPublicationBarrier(SB)
SWI $0xa0005c // sys_fcntl
RET
-TEXT runtime·casp1(SB),NOSPLIT,$0
- B runtime·cas(SB)
-
-// TODO(minux): this is only valid for ARMv6+
-// bool armcas(int32 *val, int32 old, int32 new)
-// Atomically:
-// if(*val == old){
-// *val = new;
-// return 1;
-// }else
-// return 0;
-TEXT runtime·cas(SB),NOSPLIT,$0
- B runtime·armcas(SB)
-
// TODO: this is only valid for ARMv7+
TEXT ·publicationBarrier(SB),NOSPLIT,$-4-0
B runtime·armPublicationBarrier(SB)
--- /dev/null
+// Copyright 2015 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 !ppc64,!ppc64le
+
+package runtime
+
+func prepGoExitFrame(sp uintptr) {
+}
// set tls base to DI
TEXT runtime·settls(SB),NOSPLIT,$0
- // adjust for ELF: wants to use -16(FS) and -8(FS) for g and m
+ // adjust for ELF: wants to use -8(FS) for g
ADDQ $8, DI
MOVQ $329, AX // sys___settcb
SYSCALL
MOVW R0, ret+4(FP)
RET
-TEXT runtime·casp1(SB),NOSPLIT,$0
- //B runtime·armcas(SB)
- B runtime·cas(SB)
-
-TEXT runtime·cas(SB),NOSPLIT,$0
- B runtime·armcas(SB)
-
TEXT ·publicationBarrier(SB),NOSPLIT,$-4-0
B runtime·armPublicationBarrier(SB)
get_tls(AX)
MOVL g(AX), BX
MOVL g_m(BX), BX
- MOVL m_errstr(BX), CX
+ MOVL (m_mOS+mOS_errstr)(BX), CX
MOVL CX, 0(SP)
MOVL $ERRMAX, 4(SP)
CALL errstr<>(SB)
get_tls(AX)
MOVQ g(AX), BX
MOVQ g_m(BX), BX
- MOVQ m_errstr(BX), CX
+ MOVQ (m_mOS+mOS_errstr)(BX), CX
MOVQ CX, 0(SP)
MOVQ $ERRMAX, 8(SP)
CALL errstr<>(SB)
print("runtime: pc=", hex(buf.pc), " ", hex(inst), "\n")
throw("runtime: misuse of rewindmorestack")
}
+
+func prepGoExitFrame(sp uintptr)
get_tls(CX)
MOVQ g(CX), BX
MOVQ g_m(BX), BX
- MOVQ AX, m_perrno(BX)
+ MOVQ AX, (m_mOS+mOS_perrno)(BX)
RET
// int64 runtime·nanotime1(void);
get_tls(CX)
MOVQ g(CX), BX
MOVQ g_m(BX), BX
- MOVQ m_perrno(BX), DX
+ MOVQ (m_mOS+mOS_perrno)(BX), DX
CMPQ DX, $0
JEQ skiperrno1
MOVL $0, 0(DX)
get_tls(CX)
MOVQ g(CX), BX
MOVQ g_m(BX), BX
- MOVQ m_perrno(BX), AX
+ MOVQ (m_mOS+mOS_perrno)(BX), AX
CMPQ AX, $0
JEQ skiperrno2
MOVL 0(AX), AX
MOVQ R10, 176(SP)
// save m->scratch
- LEAQ m_scratch(BP), R11
+ LEAQ (m_mOS+mOS_scratch)(BP), R11
MOVQ 0(R11), R10
MOVQ R10, 112(SP)
MOVQ 8(R11), R10
MOVQ R10, 152(SP)
// save errno, it might be EINTR; stuff we do here might reset it.
- MOVQ m_perrno(BP), R10
+ MOVQ (m_mOS+mOS_perrno)(BP), R10
MOVL 0(R10), R10
MOVQ R10, 160(SP)
MOVQ R10, libcall_r2(R11)
// restore scratch
- LEAQ m_scratch(BP), R11
+ LEAQ (m_mOS+mOS_scratch)(BP), R11
MOVQ 112(SP), R10
MOVQ R10, 0(R11)
MOVQ 120(SP), R10
MOVQ R10, 40(R11)
// restore errno
- MOVQ m_perrno(BP), R11
+ MOVQ (m_mOS+mOS_perrno)(BP), R11
MOVQ 160(SP), R10
MOVL R10, 0(R11)
package runtime
-import "unsafe"
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
// adjust Gobuf as it if executed a call to fn with context ctxt
// and then did an immediate gosave.
func gostartcall(buf *gobuf, fn, ctxt unsafe.Pointer) {
sp := buf.sp
- if regSize > ptrSize {
- sp -= ptrSize
+ if sys.RegSize > sys.PtrSize {
+ sp -= sys.PtrSize
*(*uintptr)(unsafe.Pointer(sp)) = 0
}
- sp -= ptrSize
+ sp -= sys.PtrSize
*(*uintptr)(unsafe.Pointer(sp)) = buf.pc
buf.sp = sp
buf.pc = uintptr(fn)
panic("compileCallback: not a function")
}
ft := (*functype)(unsafe.Pointer(fn._type))
- if ft.out.len != 1 {
+ if len(ft.out) != 1 {
panic("compileCallback: function must have one output parameter")
}
uintptrSize := unsafe.Sizeof(uintptr(0))
- if t := (**_type)(unsafe.Pointer(ft.out.array)); (*t).size != uintptrSize {
+ if ft.out[0].size != uintptrSize {
panic("compileCallback: output parameter size is wrong")
}
argsize := uintptr(0)
- for _, t := range (*[1024](*_type))(unsafe.Pointer(ft.in.array))[:ft.in.len] {
- if (*t).size > uintptrSize {
+ for _, t := range ft.in {
+ if t.size > uintptrSize {
panic("compileCallback: input parameter size is wrong")
}
argsize += uintptrSize
package runtime_test
import (
+ "bytes"
"fmt"
"io/ioutil"
"os"
t.Fatalf("timeBeginPeriod failed: it returned %d", *runtime.TimeBeginPeriodRetValue)
}
}
+
+// removeOneCPU removes one (any) cpu from affinity mask.
+// It returns new affinity mask.
+func removeOneCPU(mask uintptr) (uintptr, error) {
+ if mask == 0 {
+ return 0, fmt.Errorf("cpu affinity mask is empty")
+ }
+ maskbits := int(unsafe.Sizeof(mask) * 8)
+ for i := 0; i < maskbits; i++ {
+ newmask := mask & ^(1 << uint(i))
+ if newmask != mask {
+ return newmask, nil
+ }
+
+ }
+ panic("not reached")
+}
+
+func resumeChildThread(kernel32 *syscall.DLL, childpid int) error {
+ _OpenThread := kernel32.MustFindProc("OpenThread")
+ _ResumeThread := kernel32.MustFindProc("ResumeThread")
+ _Thread32First := kernel32.MustFindProc("Thread32First")
+ _Thread32Next := kernel32.MustFindProc("Thread32Next")
+
+ snapshot, err := syscall.CreateToolhelp32Snapshot(syscall.TH32CS_SNAPTHREAD, 0)
+ if err != nil {
+ return err
+ }
+ defer syscall.CloseHandle(snapshot)
+
+ const _THREAD_SUSPEND_RESUME = 0x0002
+
+ type ThreadEntry32 struct {
+ Size uint32
+ tUsage uint32
+ ThreadID uint32
+ OwnerProcessID uint32
+ BasePri int32
+ DeltaPri int32
+ Flags uint32
+ }
+
+ var te ThreadEntry32
+ te.Size = uint32(unsafe.Sizeof(te))
+ ret, _, err := _Thread32First.Call(uintptr(snapshot), uintptr(unsafe.Pointer(&te)))
+ if ret == 0 {
+ return err
+ }
+ for te.OwnerProcessID != uint32(childpid) {
+ ret, _, err = _Thread32Next.Call(uintptr(snapshot), uintptr(unsafe.Pointer(&te)))
+ if ret == 0 {
+ return err
+ }
+ }
+ h, _, err := _OpenThread.Call(_THREAD_SUSPEND_RESUME, 1, uintptr(te.ThreadID))
+ if h == 0 {
+ return err
+ }
+ defer syscall.Close(syscall.Handle(h))
+
+ ret, _, err = _ResumeThread.Call(h)
+ if ret == 0xffffffff {
+ return err
+ }
+ return nil
+}
+
+func TestNumCPU(t *testing.T) {
+ if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
+ // in child process
+ fmt.Fprintf(os.Stderr, "%d", runtime.NumCPU())
+ os.Exit(0)
+ }
+
+ switch n := runtime.NumberOfProcessors(); {
+ case n < 1:
+ t.Fatalf("system cannot have %d cpu(s)", n)
+ case n == 1:
+ if runtime.NumCPU() != 1 {
+ t.Fatalf("runtime.NumCPU() returns %d on single cpu system", runtime.NumCPU())
+ }
+ return
+ }
+
+ const (
+ _CREATE_SUSPENDED = 0x00000004
+ _PROCESS_ALL_ACCESS = syscall.STANDARD_RIGHTS_REQUIRED | syscall.SYNCHRONIZE | 0xfff
+ )
+
+ kernel32 := syscall.MustLoadDLL("kernel32.dll")
+ _GetProcessAffinityMask := kernel32.MustFindProc("GetProcessAffinityMask")
+ _SetProcessAffinityMask := kernel32.MustFindProc("SetProcessAffinityMask")
+
+ cmd := exec.Command(os.Args[0], "-test.run=TestNumCPU")
+ cmd.Env = append(os.Environ(), "GO_WANT_HELPER_PROCESS=1")
+ var buf bytes.Buffer
+ cmd.Stdout = &buf
+ cmd.Stderr = &buf
+ cmd.SysProcAttr = &syscall.SysProcAttr{CreationFlags: _CREATE_SUSPENDED}
+ err := cmd.Start()
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer func() {
+ err = cmd.Wait()
+ childOutput := string(buf.Bytes())
+ if err != nil {
+ t.Fatalf("child failed: %v: %v", err, childOutput)
+ }
+ // removeOneCPU should have decreased child cpu count by 1
+ want := fmt.Sprintf("%d", runtime.NumCPU()-1)
+ if childOutput != want {
+ t.Fatalf("child output: want %q, got %q", want, childOutput)
+ }
+ }()
+
+ defer func() {
+ err = resumeChildThread(kernel32, cmd.Process.Pid)
+ if err != nil {
+ t.Fatal(err)
+ }
+ }()
+
+ ph, err := syscall.OpenProcess(_PROCESS_ALL_ACCESS, false, uint32(cmd.Process.Pid))
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer syscall.CloseHandle(ph)
+
+ var mask, sysmask uintptr
+ ret, _, err := _GetProcessAffinityMask.Call(uintptr(ph), uintptr(unsafe.Pointer(&mask)), uintptr(unsafe.Pointer(&sysmask)))
+ if ret == 0 {
+ t.Fatal(err)
+ }
+
+ newmask, err := removeOneCPU(mask)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ ret, _, err = _SetProcessAffinityMask.Call(uintptr(ph), newmask)
+ if ret == 0 {
+ t.Fatal(err)
+ }
+ ret, _, err = _GetProcessAffinityMask.Call(uintptr(ph), uintptr(unsafe.Pointer(&mask)), uintptr(unsafe.Pointer(&sysmask)))
+ if ret == 0 {
+ t.Fatal(err)
+ }
+ if newmask != mask {
+ t.Fatalf("SetProcessAffinityMask didn't set newmask of 0x%x. Current mask is 0x%x.", newmask, mask)
+ }
+}
// Darwin sometimes returns unaligned pointers
AND $0xfffffffffffffff8, R0
#endif
-#ifdef TLSG_IS_VARIABLE
MOVD runtime·tls_g(SB), R27
ADD R27, R0
-#else
- // TODO(minux): use real TLS relocation, instead of hard-code for Linux
- ADD $0x10, R0
-#endif
MOVD 0(R0), g
nocgo:
// Darwin sometimes returns unaligned pointers
AND $0xfffffffffffffff8, R0
#endif
-#ifdef TLSG_IS_VARIABLE
MOVD runtime·tls_g(SB), R27
ADD R27, R0
-#else
- // TODO(minux): use real TLS relocation, instead of hard-code for Linux
- ADD $0x10, R0
-#endif
MOVD g, 0(R0)
nocgo:
#ifdef TLSG_IS_VARIABLE
GLOBL runtime·tls_g+0(SB), NOPTR, $8
+#else
+GLOBL runtime·tls_g+0(SB), TLSBSS, $8
#endif
--- /dev/null
+// Copyright 2015 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 mips64 mips64le
+
+#include "go_asm.h"
+#include "go_tls.h"
+#include "funcdata.h"
+#include "textflag.h"
+
+// If !iscgo, this is a no-op.
+//
+// NOTE: mcall() assumes this clobbers only R28 (REGTMP).
+TEXT runtime·save_g(SB),NOSPLIT,$-8-0
+ MOVB runtime·iscgo(SB), R28
+ BEQ R28, nocgo
+
+nocgo:
+ RET
+
+TEXT runtime·load_g(SB),NOSPLIT,$-8-0
+ RET
MOVB runtime·iscgo(SB), R31
CMP R31, $0
BEQ nocgo
-
- // $runtime.tlsg(SB) is a special linker symbol.
- // It is the offset from the start of TLS to our
- // thread-local storage for g.
- MOVD $runtime·tls_g(SB), R31
- ADD R13, R31
- // The actual TLS base is 0x7000 below R13
- SUB $0x7000, R31
-
- // Store g in TLS
- MOVD g, 0(R31)
+ MOVD runtime·tls_g(SB), R31
+ MOVD g, 0(R13)(R31*1)
nocgo:
RET
//
// NOTE: _cgo_topofstack assumes this only clobbers g (R30), and R31.
TEXT runtime·load_g(SB),NOSPLIT|NOFRAME,$0-0
- MOVD $runtime·tls_g(SB), R31
- // R13 is the C ABI TLS base pointer + 0x7000
- ADD R13, R31
- SUB $0x7000, R31
-
- MOVD 0(R31), g
+ MOVD runtime·tls_g(SB), R31
+ MOVD 0(R13)(R31*1), g
RET
GLOBL runtime·tls_g+0(SB), TLSBSS, $8
package runtime
-import "unsafe"
+import (
+ "runtime/internal/atomic"
+ "runtime/internal/sys"
+ "unsafe"
+)
// Event types in the trace, args are given in square brackets.
const (
// and ppc64le.
// Tracing won't work reliably for architectures where cputicks is emulated
// by nanotime, so the value doesn't matter for those architectures.
- traceTickDiv = 16 + 48*(goarch_386|goarch_amd64|goarch_amd64p32)
+ traceTickDiv = 16 + 48*(sys.Goarch386|sys.GoarchAmd64|sys.GoarchAmd64p32)
// Maximum number of PCs in a single stack trace.
// Since events contain only stack id rather than whole stack trace,
// we can allow quite large values here.
// trace is global tracing context.
var trace struct {
- lock mutex // protects the following members
- lockOwner *g // to avoid deadlocks during recursive lock locks
- enabled bool // when set runtime traces events
- shutdown bool // set when we are waiting for trace reader to finish after setting enabled to false
- headerWritten bool // whether ReadTrace has emitted trace header
- footerWritten bool // whether ReadTrace has emitted trace footer
- shutdownSema uint32 // used to wait for ReadTrace completion
- seqStart uint64 // sequence number when tracing was started
- ticksStart int64 // cputicks when tracing was started
- ticksEnd int64 // cputicks when tracing was stopped
- timeStart int64 // nanotime when tracing was started
- timeEnd int64 // nanotime when tracing was stopped
- reading *traceBuf // buffer currently handed off to user
- empty *traceBuf // stack of empty buffers
- fullHead *traceBuf // queue of full buffers
- fullTail *traceBuf
+ lock mutex // protects the following members
+ lockOwner *g // to avoid deadlocks during recursive lock locks
+ enabled bool // when set runtime traces events
+ shutdown bool // set when we are waiting for trace reader to finish after setting enabled to false
+ headerWritten bool // whether ReadTrace has emitted trace header
+ footerWritten bool // whether ReadTrace has emitted trace footer
+ shutdownSema uint32 // used to wait for ReadTrace completion
+ seqStart uint64 // sequence number when tracing was started
+ ticksStart int64 // cputicks when tracing was started
+ ticksEnd int64 // cputicks when tracing was stopped
+ timeStart int64 // nanotime when tracing was started
+ timeEnd int64 // nanotime when tracing was stopped
+ reading traceBufPtr // buffer currently handed off to user
+ empty traceBufPtr // stack of empty buffers
+ fullHead traceBufPtr // queue of full buffers
+ fullTail traceBufPtr
reader *g // goroutine that called ReadTrace, or nil
stackTab traceStackTable // maps stack traces to unique ids
- bufLock mutex // protects buf
- buf *traceBuf // global trace buffer, used when running without a p
+ bufLock mutex // protects buf
+ buf traceBufPtr // global trace buffer, used when running without a p
}
var traceseq uint64 // global trace sequence number
// that used to call xadd64 and cputicks are sensitive to that.
//go:nosplit
func tracestamp() (seq uint64, ts int64) {
- seq = atomicload64(&traceseq)
- for seq&1 != 0 || !cas64(&traceseq, seq, seq+1) {
- seq = atomicload64(&traceseq)
+ seq = atomic.Load64(&traceseq)
+ for seq&1 != 0 || !atomic.Cas64(&traceseq, seq, seq+1) {
+ seq = atomic.Load64(&traceseq)
}
ts = cputicks()
- atomicstore64(&traceseq, seq+2)
+ atomic.Store64(&traceseq, seq+2)
return seq >> 1, ts
}
// traceBufHeader is per-P tracing buffer.
type traceBufHeader struct {
- link *traceBuf // in trace.empty/full
+ link traceBufPtr // in trace.empty/full
lastSeq uint64 // sequence number of last event
lastTicks uint64 // when we wrote the last event
- buf []byte // trace data, always points to traceBuf.arr
+ pos int // next write offset in arr
stk [traceStackSize]uintptr // scratch buffer for traceback
}
arr [64<<10 - unsafe.Sizeof(traceBufHeader{})]byte // underlying buffer for traceBufHeader.buf
}
+// traceBufPtr is a *traceBuf that is not traced by the garbage
+// collector and doesn't have write barriers. traceBufs are not
+// allocated from the GC'd heap, so this is safe, and are often
+// manipulated in contexts where write barriers are not allowed, so
+// this is necessary.
+type traceBufPtr uintptr
+
+func (tp traceBufPtr) ptr() *traceBuf { return (*traceBuf)(unsafe.Pointer(tp)) }
+func (tp *traceBufPtr) set(b *traceBuf) { *tp = traceBufPtr(unsafe.Pointer(b)) }
+func traceBufPtrOf(b *traceBuf) traceBufPtr {
+ return traceBufPtr(unsafe.Pointer(b))
+}
+
// StartTrace enables tracing for the current process.
// While tracing, the data will be buffered and available via ReadTrace.
// StartTrace returns an error if tracing is already enabled.
break
}
buf := p.tracebuf
- if buf != nil {
+ if buf != 0 {
traceFullQueue(buf)
- p.tracebuf = nil
+ p.tracebuf = 0
}
}
- if trace.buf != nil && len(trace.buf.buf) != 0 {
+ if trace.buf != 0 && trace.buf.ptr().pos != 0 {
buf := trace.buf
- trace.buf = nil
+ trace.buf = 0
traceFullQueue(buf)
}
if p == nil {
break
}
- if p.tracebuf != nil {
+ if p.tracebuf != 0 {
throw("trace: non-empty trace buffer in proc")
}
}
- if trace.buf != nil {
+ if trace.buf != 0 {
throw("trace: non-empty global trace buffer")
}
- if trace.fullHead != nil || trace.fullTail != nil {
+ if trace.fullHead != 0 || trace.fullTail != 0 {
throw("trace: non-empty full trace buffer")
}
- if trace.reading != nil || trace.reader != nil {
+ if trace.reading != 0 || trace.reader != nil {
throw("trace: reading after shutdown")
}
- for trace.empty != nil {
+ for trace.empty != 0 {
buf := trace.empty
- trace.empty = buf.link
- sysFree(unsafe.Pointer(buf), unsafe.Sizeof(*buf), &memstats.other_sys)
+ trace.empty = buf.ptr().link
+ sysFree(unsafe.Pointer(buf), unsafe.Sizeof(*buf.ptr()), &memstats.other_sys)
}
trace.shutdown = false
unlock(&trace.lock)
return nil
}
// Recycle the old buffer.
- if buf := trace.reading; buf != nil {
- buf.link = trace.empty
+ if buf := trace.reading; buf != 0 {
+ buf.ptr().link = trace.empty
trace.empty = buf
- trace.reading = nil
+ trace.reading = 0
}
// Write trace header.
if !trace.headerWritten {
return []byte("go 1.5 trace\x00\x00\x00\x00")
}
// Wait for new data.
- if trace.fullHead == nil && !trace.shutdown {
+ if trace.fullHead == 0 && !trace.shutdown {
trace.reader = getg()
goparkunlock(&trace.lock, "trace reader (blocked)", traceEvGoBlock, 2)
lock(&trace.lock)
}
// Write a buffer.
- if trace.fullHead != nil {
+ if trace.fullHead != 0 {
buf := traceFullDequeue()
trace.reading = buf
trace.lockOwner = nil
unlock(&trace.lock)
- return buf.buf
+ return buf.ptr().arr[:buf.ptr().pos]
}
// Write footer with timer frequency.
if !trace.footerWritten {
// traceReader returns the trace reader that should be woken up, if any.
func traceReader() *g {
- if trace.reader == nil || (trace.fullHead == nil && !trace.shutdown) {
+ if trace.reader == nil || (trace.fullHead == 0 && !trace.shutdown) {
return nil
}
lock(&trace.lock)
- if trace.reader == nil || (trace.fullHead == nil && !trace.shutdown) {
+ if trace.reader == nil || (trace.fullHead == 0 && !trace.shutdown) {
unlock(&trace.lock)
return nil
}
// traceProcFree frees trace buffer associated with pp.
func traceProcFree(pp *p) {
buf := pp.tracebuf
- pp.tracebuf = nil
- if buf == nil {
+ pp.tracebuf = 0
+ if buf == 0 {
return
}
lock(&trace.lock)
}
// traceFullQueue queues buf into queue of full buffers.
-func traceFullQueue(buf *traceBuf) {
- buf.link = nil
- if trace.fullHead == nil {
+func traceFullQueue(buf traceBufPtr) {
+ buf.ptr().link = 0
+ if trace.fullHead == 0 {
trace.fullHead = buf
} else {
- trace.fullTail.link = buf
+ trace.fullTail.ptr().link = buf
}
trace.fullTail = buf
}
// traceFullDequeue dequeues from queue of full buffers.
-func traceFullDequeue() *traceBuf {
+func traceFullDequeue() traceBufPtr {
buf := trace.fullHead
- if buf == nil {
- return nil
+ if buf == 0 {
+ return 0
}
- trace.fullHead = buf.link
- if trace.fullHead == nil {
- trace.fullTail = nil
+ trace.fullHead = buf.ptr().link
+ if trace.fullHead == 0 {
+ trace.fullTail = 0
}
- buf.link = nil
+ buf.ptr().link = 0
return buf
}
traceReleaseBuffer(pid)
return
}
- buf := *bufp
+ buf := (*bufp).ptr()
const maxSize = 2 + 5*traceBytesPerNumber // event type, length, sequence, timestamp, stack id and two add params
- if buf == nil || cap(buf.buf)-len(buf.buf) < maxSize {
- buf = traceFlush(buf)
- *bufp = buf
+ if buf == nil || len(buf.arr)-buf.pos < maxSize {
+ buf = traceFlush(traceBufPtrOf(buf)).ptr()
+ (*bufp).set(buf)
}
seq, ticksraw := tracestamp()
seqDiff := seq - buf.lastSeq
ticks := uint64(ticksraw) / traceTickDiv
tickDiff := ticks - buf.lastTicks
- if len(buf.buf) == 0 {
- data := buf.buf
- data = append(data, traceEvBatch|1<<traceArgCountShift)
- data = traceAppend(data, uint64(pid))
- data = traceAppend(data, seq)
- data = traceAppend(data, ticks)
- buf.buf = data
+ if buf.pos == 0 {
+ buf.byte(traceEvBatch | 1<<traceArgCountShift)
+ buf.varint(uint64(pid))
+ buf.varint(seq)
+ buf.varint(ticks)
seqDiff = 0
tickDiff = 0
}
if narg > 3 {
narg = 3
}
- data := buf.buf
- data = append(data, ev|narg<<traceArgCountShift)
+ startPos := buf.pos
+ buf.byte(ev | narg<<traceArgCountShift)
var lenp *byte
if narg == 3 {
// Reserve the byte for length assuming that length < 128.
- data = append(data, 0)
- lenp = &data[len(data)-1]
+ buf.varint(0)
+ lenp = &buf.arr[buf.pos-1]
}
- data = traceAppend(data, seqDiff)
- data = traceAppend(data, tickDiff)
+ buf.varint(seqDiff)
+ buf.varint(tickDiff)
for _, a := range args {
- data = traceAppend(data, a)
+ buf.varint(a)
}
if skip == 0 {
- data = append(data, 0)
+ buf.varint(0)
} else if skip > 0 {
_g_ := getg()
gp := mp.curg
nstk-- // skip runtime.main
}
id := trace.stackTab.put(buf.stk[:nstk])
- data = traceAppend(data, uint64(id))
+ buf.varint(uint64(id))
}
- evSize := len(data) - len(buf.buf)
+ evSize := buf.pos - startPos
if evSize > maxSize {
throw("invalid length of trace event")
}
// Fill in actual length.
*lenp = byte(evSize - 2)
}
- buf.buf = data
traceReleaseBuffer(pid)
}
// traceAcquireBuffer returns trace buffer to use and, if necessary, locks it.
-func traceAcquireBuffer() (mp *m, pid int32, bufp **traceBuf) {
+func traceAcquireBuffer() (mp *m, pid int32, bufp *traceBufPtr) {
mp = acquirem()
if p := mp.p.ptr(); p != nil {
return mp, p.id, &p.tracebuf
}
// traceFlush puts buf onto stack of full buffers and returns an empty buffer.
-func traceFlush(buf *traceBuf) *traceBuf {
+func traceFlush(buf traceBufPtr) traceBufPtr {
owner := trace.lockOwner
dolock := owner == nil || owner != getg().m.curg
if dolock {
lock(&trace.lock)
}
- if buf != nil {
- if &buf.buf[0] != &buf.arr[0] {
- throw("trace buffer overflow")
- }
+ if buf != 0 {
traceFullQueue(buf)
}
- if trace.empty != nil {
+ if trace.empty != 0 {
buf = trace.empty
- trace.empty = buf.link
+ trace.empty = buf.ptr().link
} else {
- buf = (*traceBuf)(sysAlloc(unsafe.Sizeof(traceBuf{}), &memstats.other_sys))
- if buf == nil {
+ buf = traceBufPtr(sysAlloc(unsafe.Sizeof(traceBuf{}), &memstats.other_sys))
+ if buf == 0 {
throw("trace: out of memory")
}
}
- buf.link = nil
- buf.buf = buf.arr[:0]
- buf.lastTicks = 0
+ bufp := buf.ptr()
+ bufp.link.set(nil)
+ bufp.pos = 0
+ bufp.lastTicks = 0
if dolock {
unlock(&trace.lock)
}
return buf
}
+// varint appends v to buf in little-endian-base-128 encoding.
+func (buf *traceBuf) varint(v uint64) {
+ pos := buf.pos
+ for ; v >= 0x80; v >>= 7 {
+ buf.arr[pos] = 0x80 | byte(v)
+ pos++
+ }
+ buf.arr[pos] = byte(v)
+ pos++
+ buf.pos = pos
+}
+
+// byte appends v to buf.
+func (buf *traceBuf) byte(v byte) {
+ buf.arr[buf.pos] = v
+ buf.pos++
+}
+
// traceStackTable maps stack traces (arrays of PC's) to unique uint32 ids.
// It is lock-free for reading.
type traceStackTable struct {
lock mutex
seq uint32
mem traceAlloc
- tab [1 << 13]*traceStack
+ tab [1 << 13]traceStackPtr
}
// traceStack is a single stack in traceStackTable.
type traceStack struct {
- link *traceStack
+ link traceStackPtr
hash uintptr
id uint32
n int
stk [0]uintptr // real type [n]uintptr
}
+type traceStackPtr uintptr
+
+func (tp traceStackPtr) ptr() *traceStack { return (*traceStack)(unsafe.Pointer(tp)) }
+
// stack returns slice of PCs.
func (ts *traceStack) stack() []uintptr {
return (*[traceStackSize]uintptr)(unsafe.Pointer(&ts.stk))[:ts.n]
func (tab *traceStackTable) find(pcs []uintptr, hash uintptr) uint32 {
part := int(hash % uintptr(len(tab.tab)))
Search:
- for stk := tab.tab[part]; stk != nil; stk = stk.link {
+ for stk := tab.tab[part].ptr(); stk != nil; stk = stk.link.ptr() {
if stk.hash == hash && stk.n == len(pcs) {
for i, stkpc := range stk.stack() {
if stkpc != pcs[i] {
// newStack allocates a new stack of size n.
func (tab *traceStackTable) newStack(n int) *traceStack {
- return (*traceStack)(tab.mem.alloc(unsafe.Sizeof(traceStack{}) + uintptr(n)*ptrSize))
+ return (*traceStack)(tab.mem.alloc(unsafe.Sizeof(traceStack{}) + uintptr(n)*sys.PtrSize))
}
// dump writes all previously cached stacks to trace buffers,
// releases all memory and resets state.
func (tab *traceStackTable) dump() {
var tmp [(2 + traceStackSize) * traceBytesPerNumber]byte
- buf := traceFlush(nil)
+ buf := traceFlush(0).ptr()
for _, stk := range tab.tab {
- for ; stk != nil; stk = stk.link {
+ stk := stk.ptr()
+ for ; stk != nil; stk = stk.link.ptr() {
maxSize := 1 + (3+stk.n)*traceBytesPerNumber
- if cap(buf.buf)-len(buf.buf) < maxSize {
- buf = traceFlush(buf)
+ if len(buf.arr)-buf.pos < maxSize {
+ buf = traceFlush(traceBufPtrOf(buf)).ptr()
}
// Form the event in the temp buffer, we need to know the actual length.
tmpbuf := tmp[:0]
tmpbuf = traceAppend(tmpbuf, uint64(pc))
}
// Now copy to the buffer.
- data := buf.buf
- data = append(data, traceEvStack|3<<traceArgCountShift)
- data = traceAppend(data, uint64(len(tmpbuf)))
- data = append(data, tmpbuf...)
- buf.buf = data
+ buf.byte(traceEvStack | 3<<traceArgCountShift)
+ buf.varint(uint64(len(tmpbuf)))
+ buf.pos += copy(buf.arr[buf.pos:], tmpbuf)
}
}
lock(&trace.lock)
- traceFullQueue(buf)
+ traceFullQueue(traceBufPtrOf(buf))
unlock(&trace.lock)
tab.mem.drop()
// traceAllocBlock is a block in traceAlloc.
type traceAllocBlock struct {
next *traceAllocBlock
- data [64<<10 - ptrSize]byte
+ data [64<<10 - sys.PtrSize]byte
}
// alloc allocates n-byte block.
func (a *traceAlloc) alloc(n uintptr) unsafe.Pointer {
- n = round(n, ptrSize)
+ n = round(n, sys.PtrSize)
if a.head == nil || a.off+n > uintptr(len(a.head.data)) {
if n > uintptr(len(a.head.data)) {
throw("trace: alloc too large")
}
func traceGCStart() {
- traceEvent(traceEvGCStart, 4)
+ traceEvent(traceEvGCStart, 3)
}
func traceGCDone() {
package runtime
-import "unsafe"
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
// The code in this file implements stack trace walking for all architectures.
// The most important fact about a given architecture is whether it uses a link register.
// usesLR is defined below in terms of minFrameSize, which is defined in
// arch_$GOARCH.go. ptrSize and regSize are defined in stubs.go.
-const usesLR = minFrameSize > 0
+const usesLR = sys.MinFrameSize > 0
var (
// initialized in tracebackinit
rt0_goPC uintptr
sigpanicPC uintptr
runfinqPC uintptr
- backgroundgcPC uintptr
bgsweepPC uintptr
forcegchelperPC uintptr
timerprocPC uintptr
rt0_goPC = funcPC(rt0_go)
sigpanicPC = funcPC(sigpanic)
runfinqPC = funcPC(runfinq)
- backgroundgcPC = funcPC(backgroundgc)
bgsweepPC = funcPC(bgsweep)
forcegchelperPC = funcPC(forcegchelper)
timerprocPC = funcPC(timerproc)
// instead on the g0 stack.
throw("gentraceback cannot trace user goroutine on its own stack")
}
- gotraceback := gotraceback(nil)
+ level, _, _ := gotraceback()
// Fix up returns to the stack barrier by fetching the
// original return PC from gp.stkbar.
frame.pc = *(*uintptr)(unsafe.Pointer(frame.sp))
frame.lr = 0
} else {
- frame.pc = uintptr(*(*uintreg)(unsafe.Pointer(frame.sp)))
- frame.sp += regSize
+ frame.pc = uintptr(*(*sys.Uintreg)(unsafe.Pointer(frame.sp)))
+ frame.sp += sys.RegSize
}
}
}
frame.fn = f
+ var cache pcvalueCache
+
n := 0
for n < max {
// Typically:
sp = gp.m.curg.sched.sp
stkbar = gp.m.curg.stkbar[gp.m.curg.stkbarPos:]
}
- frame.fp = sp + uintptr(funcspdelta(f, frame.pc))
+ frame.fp = sp + uintptr(funcspdelta(f, frame.pc, &cache))
if !usesLR {
// On x86, call instruction pushes return PC before entering new function.
- frame.fp += regSize
+ frame.fp += sys.RegSize
}
}
var flr *_func
}
} else {
if frame.lr == 0 {
- lrPtr = frame.fp - regSize
- frame.lr = uintptr(*(*uintreg)(unsafe.Pointer(lrPtr)))
+ lrPtr = frame.fp - sys.RegSize
+ frame.lr = uintptr(*(*sys.Uintreg)(unsafe.Pointer(lrPtr)))
}
}
if frame.lr == stackBarrierPC {
frame.varp = frame.fp
if !usesLR {
// On x86, call instruction pushes return PC before entering new function.
- frame.varp -= regSize
+ frame.varp -= sys.RegSize
}
// If framepointer_enabled and there's a frame, then
// there's a saved bp here.
if framepointer_enabled && GOARCH == "amd64" && frame.varp > frame.sp {
- frame.varp -= regSize
+ frame.varp -= sys.RegSize
}
// Derive size of arguments.
// in package runtime and reflect, and for those we use call-specific
// metadata recorded by f's caller.
if callback != nil || printing {
- frame.argp = frame.fp + minFrameSize
+ frame.argp = frame.fp + sys.MinFrameSize
setArgInfo(&frame, f, callback != nil)
}
}
print(funcname(f), "(")
argp := (*[100]uintptr)(unsafe.Pointer(frame.argp))
- for i := uintptr(0); i < frame.arglen/ptrSize; i++ {
+ for i := uintptr(0); i < frame.arglen/sys.PtrSize; i++ {
if i >= 10 {
print(", ...")
break
if frame.pc > f.entry {
print(" +", hex(frame.pc-f.entry))
}
- if g.m.throwing > 0 && gp == g.m.curg || gotraceback >= 2 {
+ if g.m.throwing > 0 && gp == g.m.curg || level >= 2 {
print(" fp=", hex(frame.fp), " sp=", hex(frame.sp))
}
print("\n")
// before faking a call to sigpanic.
if usesLR && waspanic {
x := *(*uintptr)(unsafe.Pointer(frame.sp))
- frame.sp += minFrameSize
+ frame.sp += sys.MinFrameSize
if GOARCH == "arm64" {
// arm64 needs 16-byte aligned SP, always
- frame.sp += ptrSize
+ frame.sp += sys.PtrSize
}
f = findfunc(frame.pc)
frame.fn = f
if f == nil {
frame.pc = x
- } else if funcspdelta(f, frame.pc) == 0 {
+ } else if funcspdelta(f, frame.pc, &cache) == 0 {
frame.lr = x
}
}
// Extract argument bitmaps for reflect stubs from the calls they made to reflect.
switch funcname(f) {
case "reflect.makeFuncStub", "reflect.methodValueCall":
- arg0 := frame.sp + minFrameSize
+ arg0 := frame.sp + sys.MinFrameSize
fn := *(**[2]uintptr)(unsafe.Pointer(arg0))
if fn[0] != f.entry {
print("runtime: confused by ", funcname(f), "\n")
throw("reflect mismatch")
}
bv := (*bitvector)(unsafe.Pointer(fn[1]))
- frame.arglen = uintptr(bv.n * ptrSize)
+ frame.arglen = uintptr(bv.n * sys.PtrSize)
frame.argmap = bv
}
}
print("created by ", funcname(f), "\n")
tracepc := pc // back up to CALL instruction for funcline.
if pc > f.entry {
- tracepc -= _PCQuantum
+ tracepc -= sys.PCQuantum
}
file, line := funcline(f, tracepc)
print("\t", file, ":", line)
if g.m.throwing > 0 && gp != nil && (gp == g.m.curg || gp == g.m.caughtsig.ptr()) {
return true
}
- traceback := gotraceback(nil)
+ level, _, _ := gotraceback()
name := funcname(f)
// Special case: always show runtime.panic frame, so that we can
return true
}
- return traceback > 1 || f != nil && contains(name, ".") && (!hasprefix(name, "runtime.") || isExportedRuntime(name))
+ return level > 1 || f != nil && contains(name, ".") && (!hasprefix(name, "runtime.") || isExportedRuntime(name))
}
// isExportedRuntime reports whether name is an exported runtime function.
}
func tracebackothers(me *g) {
- level := gotraceback(nil)
+ level, _, _ := gotraceback()
// Show the current goroutine first, if we haven't already.
g := getg()
func isSystemGoroutine(gp *g) bool {
pc := gp.startpc
return pc == runfinqPC && !fingRunning ||
- pc == backgroundgcPC ||
pc == bgsweepPC ||
pc == forcegchelperPC ||
pc == timerprocPC ||
needkeyupdate bool // true if we need to update key on an overwrite
}
+type arraytype struct {
+ typ _type
+ elem *_type
+ slice *_type
+ len uintptr
+}
+
type chantype struct {
typ _type
elem *_type
type functype struct {
typ _type
dotdotdot bool
- in slice
- out slice
+ in []*_type
+ out []*_type
}
type ptrtype struct {
typ _type
elem *_type
}
+
+type structfield struct {
+ name *string
+ pkgpath *string
+ typ *_type
+ tag *string
+ offset uintptr
+}
+
+type structtype struct {
+ typ _type
+ fields []structfield
+}
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build arm ppc64 ppc64le
+// +build arm ppc64 ppc64le mips64 mips64le
package runtime
package runtime
-import "unsafe"
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
// Look up symbols in the Linux vDSO.
n++
// now argv+n is auxv
- auxv := (*[1 << 32]elf64Auxv)(add(unsafe.Pointer(argv), uintptr(n)*ptrSize))
+ auxv := (*[1 << 32]elf64Auxv)(add(unsafe.Pointer(argv), uintptr(n)*sys.PtrSize))
for i := 0; auxv[i].a_type != _AT_NULL; i++ {
av := &auxv[i]
exit(2)
}
- errno := connect(uintptr(fd), unsafe.Pointer(&logdAddr), int32(unsafe.Sizeof(logdAddr)))
+ errno := connect(fd, unsafe.Pointer(&logdAddr), int32(unsafe.Sizeof(logdAddr)))
if errno < 0 {
msg := []byte("runtime: cannot connect to /dev/socket/logdw\x00")
write(2, unsafe.Pointer(&msg[0]), int32(len(msg)))
+++ /dev/null
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoarch = `386`
-
-const goarch_386 = 1
-const goarch_amd64 = 0
-const goarch_amd64p32 = 0
-const goarch_arm = 0
-const goarch_arm64 = 0
-const goarch_ppc64 = 0
-const goarch_ppc64le = 0
+++ /dev/null
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoarch = `amd64`
-
-const goarch_386 = 0
-const goarch_amd64 = 1
-const goarch_amd64p32 = 0
-const goarch_arm = 0
-const goarch_arm64 = 0
-const goarch_ppc64 = 0
-const goarch_ppc64le = 0
+++ /dev/null
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoarch = `amd64p32`
-
-const goarch_386 = 0
-const goarch_amd64 = 0
-const goarch_amd64p32 = 1
-const goarch_arm = 0
-const goarch_arm64 = 0
-const goarch_ppc64 = 0
-const goarch_ppc64le = 0
+++ /dev/null
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoarch = `arm`
-
-const goarch_386 = 0
-const goarch_amd64 = 0
-const goarch_amd64p32 = 0
-const goarch_arm = 1
-const goarch_arm64 = 0
-const goarch_ppc64 = 0
-const goarch_ppc64le = 0
+++ /dev/null
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoarch = `arm64`
-
-const goarch_386 = 0
-const goarch_amd64 = 0
-const goarch_amd64p32 = 0
-const goarch_arm = 0
-const goarch_arm64 = 1
-const goarch_ppc64 = 0
-const goarch_ppc64le = 0
+++ /dev/null
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoarch = `ppc64`
-
-const goarch_386 = 0
-const goarch_amd64 = 0
-const goarch_amd64p32 = 0
-const goarch_arm = 0
-const goarch_arm64 = 0
-const goarch_ppc64 = 1
-const goarch_ppc64le = 0
+++ /dev/null
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoarch = `ppc64le`
-
-const goarch_386 = 0
-const goarch_amd64 = 0
-const goarch_amd64p32 = 0
-const goarch_arm = 0
-const goarch_arm64 = 0
-const goarch_ppc64 = 0
-const goarch_ppc64le = 1
+++ /dev/null
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoos = `android`
-
-const goos_android = 1
-const goos_darwin = 0
-const goos_dragonfly = 0
-const goos_freebsd = 0
-const goos_linux = 0
-const goos_nacl = 0
-const goos_netbsd = 0
-const goos_openbsd = 0
-const goos_plan9 = 0
-const goos_solaris = 0
-const goos_windows = 0
+++ /dev/null
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoos = `darwin`
-
-const goos_android = 0
-const goos_darwin = 1
-const goos_dragonfly = 0
-const goos_freebsd = 0
-const goos_linux = 0
-const goos_nacl = 0
-const goos_netbsd = 0
-const goos_openbsd = 0
-const goos_plan9 = 0
-const goos_solaris = 0
-const goos_windows = 0
+++ /dev/null
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoos = `dragonfly`
-
-const goos_android = 0
-const goos_darwin = 0
-const goos_dragonfly = 1
-const goos_freebsd = 0
-const goos_linux = 0
-const goos_nacl = 0
-const goos_netbsd = 0
-const goos_openbsd = 0
-const goos_plan9 = 0
-const goos_solaris = 0
-const goos_windows = 0
+++ /dev/null
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoos = `freebsd`
-
-const goos_android = 0
-const goos_darwin = 0
-const goos_dragonfly = 0
-const goos_freebsd = 1
-const goos_linux = 0
-const goos_nacl = 0
-const goos_netbsd = 0
-const goos_openbsd = 0
-const goos_plan9 = 0
-const goos_solaris = 0
-const goos_windows = 0
+++ /dev/null
-// generated by gengoos.go using 'go generate'
-
-// +build !android
-
-package runtime
-
-const theGoos = `linux`
-
-const goos_android = 0
-const goos_darwin = 0
-const goos_dragonfly = 0
-const goos_freebsd = 0
-const goos_linux = 1
-const goos_nacl = 0
-const goos_netbsd = 0
-const goos_openbsd = 0
-const goos_plan9 = 0
-const goos_solaris = 0
-const goos_windows = 0
+++ /dev/null
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoos = `nacl`
-
-const goos_android = 0
-const goos_darwin = 0
-const goos_dragonfly = 0
-const goos_freebsd = 0
-const goos_linux = 0
-const goos_nacl = 1
-const goos_netbsd = 0
-const goos_openbsd = 0
-const goos_plan9 = 0
-const goos_solaris = 0
-const goos_windows = 0
+++ /dev/null
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoos = `netbsd`
-
-const goos_android = 0
-const goos_darwin = 0
-const goos_dragonfly = 0
-const goos_freebsd = 0
-const goos_linux = 0
-const goos_nacl = 0
-const goos_netbsd = 1
-const goos_openbsd = 0
-const goos_plan9 = 0
-const goos_solaris = 0
-const goos_windows = 0
+++ /dev/null
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoos = `openbsd`
-
-const goos_android = 0
-const goos_darwin = 0
-const goos_dragonfly = 0
-const goos_freebsd = 0
-const goos_linux = 0
-const goos_nacl = 0
-const goos_netbsd = 0
-const goos_openbsd = 1
-const goos_plan9 = 0
-const goos_solaris = 0
-const goos_windows = 0
+++ /dev/null
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoos = `plan9`
-
-const goos_android = 0
-const goos_darwin = 0
-const goos_dragonfly = 0
-const goos_freebsd = 0
-const goos_linux = 0
-const goos_nacl = 0
-const goos_netbsd = 0
-const goos_openbsd = 0
-const goos_plan9 = 1
-const goos_solaris = 0
-const goos_windows = 0
+++ /dev/null
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoos = `solaris`
-
-const goos_android = 0
-const goos_darwin = 0
-const goos_dragonfly = 0
-const goos_freebsd = 0
-const goos_linux = 0
-const goos_nacl = 0
-const goos_netbsd = 0
-const goos_openbsd = 0
-const goos_plan9 = 0
-const goos_solaris = 1
-const goos_windows = 0
+++ /dev/null
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoos = `windows`
-
-const goos_android = 0
-const goos_darwin = 0
-const goos_dragonfly = 0
-const goos_freebsd = 0
-const goos_linux = 0
-const goos_nacl = 0
-const goos_netbsd = 0
-const goos_openbsd = 0
-const goos_plan9 = 0
-const goos_solaris = 0
-const goos_windows = 1
// Output: true
}
+func ExampleHasPrefix() {
+ fmt.Println(strings.HasPrefix("Gopher", "Go"))
+ fmt.Println(strings.HasPrefix("Gopher", "C"))
+ fmt.Println(strings.HasPrefix("Gopher", ""))
+ // Output:
+ // true
+ // false
+ // true
+}
+
+func ExampleHasSuffix() {
+ fmt.Println(strings.HasSuffix("Amigo", "go"))
+ fmt.Println(strings.HasSuffix("Amigo", "O"))
+ fmt.Println(strings.HasSuffix("Amigo", "Ami"))
+ fmt.Println(strings.HasSuffix("Amigo", ""))
+ // Output:
+ // true
+ // false
+ // false
+ // true
+}
+
func ExampleIndex() {
fmt.Println(strings.Index("chicken", "ken"))
fmt.Println(strings.Index("chicken", "dmr"))
return IndexRune(s, r) >= 0
}
-// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s.
-func Index(s, sep string) int {
- n := len(sep)
- switch {
- case n == 0:
- return 0
- case n == 1:
- return IndexByte(s, sep[0])
- case n == len(s):
- if sep == s {
- return 0
- }
- return -1
- case n > len(s):
- return -1
- }
- // Rabin-Karp search
- hashsep, pow := hashStr(sep)
- var h uint32
- for i := 0; i < n; i++ {
- h = h*primeRK + uint32(s[i])
- }
- if h == hashsep && s[:n] == sep {
- return 0
- }
- for i := n; i < len(s); {
- h *= primeRK
- h += uint32(s[i])
- h -= pow * uint32(s[i-n])
- i++
- if h == hashsep && s[i-n:i] == sep {
- return i - n
- }
- }
- return -1
-}
-
// LastIndex returns the index of the last instance of sep in s, or -1 if sep is not present in s.
func LastIndex(s, sep string) int {
n := len(sep)
--- /dev/null
+// Copyright 2015 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 strings
+
+// indexShortStr returns the index of the first instance of c in s, or -1 if c is not present in s.
+// indexShortStr requires 2 <= len(c) <= shortStringLen
+func indexShortStr(s, c string) int // ../runtime/asm_$GOARCH.s
+const shortStringLen = 31
+
+// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s.
+func Index(s, sep string) int {
+ n := len(sep)
+ switch {
+ case n == 0:
+ return 0
+ case n == 1:
+ return IndexByte(s, sep[0])
+ case n <= shortStringLen:
+ return indexShortStr(s, sep)
+ case n == len(s):
+ if sep == s {
+ return 0
+ }
+ return -1
+ case n > len(s):
+ return -1
+ }
+ // Rabin-Karp search
+ hashsep, pow := hashStr(sep)
+ var h uint32
+ for i := 0; i < n; i++ {
+ h = h*primeRK + uint32(s[i])
+ }
+ if h == hashsep && s[:n] == sep {
+ return 0
+ }
+ for i := n; i < len(s); {
+ h *= primeRK
+ h += uint32(s[i])
+ h -= pow * uint32(s[i-n])
+ i++
+ if h == hashsep && s[i-n:i] == sep {
+ return i - n
+ }
+ }
+ return -1
+}
--- /dev/null
+// Copyright 2015 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 !amd64
+
+package strings
+
+// TODO: implements short string optimization on non amd64 platforms
+// and get rid of strings_amd64.go
+
+// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s.
+func Index(s, sep string) int {
+ n := len(sep)
+ switch {
+ case n == 0:
+ return 0
+ case n == 1:
+ return IndexByte(s, sep[0])
+ case n == len(s):
+ if sep == s {
+ return 0
+ }
+ return -1
+ case n > len(s):
+ return -1
+ }
+ // Rabin-Karp search
+ hashsep, pow := hashStr(sep)
+ var h uint32
+ for i := 0; i < n; i++ {
+ h = h*primeRK + uint32(s[i])
+ }
+ if h == hashsep && s[:n] == sep {
+ return 0
+ }
+ for i := n; i < len(s); {
+ h *= primeRK
+ h += uint32(s[i])
+ h -= pow * uint32(s[i-n])
+ i++
+ if h == hashsep && s[i-n:i] == sep {
+ return i - n
+ }
+ }
+ return -1
+}
{"abc", "b", 1},
{"abc", "c", 2},
{"abc", "x", -1},
+ // test special cases in Index() for short strings
+ {"", "ab", -1},
+ {"bc", "ab", -1},
+ {"ab", "ab", 0},
+ {"xab", "ab", 1},
+ {"xab"[:2], "ab", -1},
+ {"", "abc", -1},
+ {"xbc", "abc", -1},
+ {"abc", "abc", 0},
+ {"xabc", "abc", 1},
+ {"xabc"[:3], "abc", -1},
+ {"xabxc", "abc", -1},
+ {"", "abcd", -1},
+ {"xbcd", "abcd", -1},
+ {"abcd", "abcd", 0},
+ {"xabcd", "abcd", 1},
+ {"xyabcd"[:5], "abcd", -1},
+ {"xbcqq", "abcqq", -1},
+ {"abcqq", "abcqq", 0},
+ {"xabcqq", "abcqq", 1},
+ {"xyabcqq"[:6], "abcqq", -1},
+ {"xabxcqq", "abcqq", -1},
+ {"xabcqxq", "abcqq", -1},
+ {"", "01234567", -1},
+ {"32145678", "01234567", -1},
+ {"01234567", "01234567", 0},
+ {"x01234567", "01234567", 1},
+ {"xx01234567"[:9], "01234567", -1},
+ {"", "0123456789", -1},
+ {"3214567844", "0123456789", -1},
+ {"0123456789", "0123456789", 0},
+ {"x0123456789", "0123456789", 1},
+ {"xyz0123456789"[:12], "0123456789", -1},
+ {"x01234567x89", "0123456789", -1},
+ {"", "0123456789012345", -1},
+ {"3214567889012345", "0123456789012345", -1},
+ {"0123456789012345", "0123456789012345", 0},
+ {"x0123456789012345", "0123456789012345", 1},
+ {"", "01234567890123456789", -1},
+ {"32145678890123456789", "01234567890123456789", -1},
+ {"01234567890123456789", "01234567890123456789", 0},
+ {"x01234567890123456789", "01234567890123456789", 1},
+ {"xyz01234567890123456789"[:22], "01234567890123456789", -1},
+ {"", "0123456789012345678901234567890", -1},
+ {"321456788901234567890123456789012345678911", "0123456789012345678901234567890", -1},
+ {"0123456789012345678901234567890", "0123456789012345678901234567890", 0},
+ {"x0123456789012345678901234567890", "0123456789012345678901234567890", 1},
+ {"xyz0123456789012345678901234567890"[:33], "0123456789012345678901234567890", -1},
+ {"", "01234567890123456789012345678901", -1},
+ {"32145678890123456789012345678901234567890211", "01234567890123456789012345678901", -1},
+ {"01234567890123456789012345678901", "01234567890123456789012345678901", 0},
+ {"x01234567890123456789012345678901", "01234567890123456789012345678901", 1},
+ {"xyz01234567890123456789012345678901"[:34], "01234567890123456789012345678901", -1},
}
var lastIndexTests = []IndexTest{
RET
TEXT ·generalCAS64(SB),NOSPLIT,$0-21
- B runtime·cas64(SB)
+ B runtime∕internal∕atomic·Cas64(SB)
GLOBL armCAS64(SB), NOPTR, $4
--- /dev/null
+// Copyright 2015 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 mips64 mips64le
+
+#include "textflag.h"
+
+#define LL(base, rt) WORD $((060<<26)|((base)<<21)|((rt)<<16))
+#define LLV(base, rt) WORD $((064<<26)|((base)<<21)|((rt)<<16))
+#define SC(base, rt) WORD $((070<<26)|((base)<<21)|((rt)<<16))
+#define SCV(base, rt) WORD $((074<<26)|((base)<<21)|((rt)<<16))
+#define SYNC WORD $0xf
+
+TEXT ·SwapInt32(SB),NOSPLIT,$0-20
+ JMP ·SwapUint32(SB)
+
+TEXT ·SwapUint32(SB),NOSPLIT,$0-20
+ MOVV addr+0(FP), R2
+ MOVW new+8(FP), R5
+ SYNC
+ MOVV R5, R3
+ LL(2, 1) // R1 = *R2
+ SC(2, 3) // *R2 = R3
+ BEQ R3, -3(PC)
+ MOVW R1, old+16(FP)
+ SYNC
+ RET
+
+TEXT ·SwapInt64(SB),NOSPLIT,$0-24
+ JMP ·SwapUint64(SB)
+
+TEXT ·SwapUint64(SB),NOSPLIT,$0-24
+ MOVV addr+0(FP), R2
+ MOVV new+8(FP), R5
+ SYNC
+ MOVV R5, R3
+ LLV(2, 1) // R1 = *R2
+ SCV(2, 3) // *R2 = R3
+ BEQ R3, -3(PC)
+ MOVV R1, old+16(FP)
+ SYNC
+ RET
+
+TEXT ·SwapUintptr(SB),NOSPLIT,$0-24
+ JMP ·SwapUint64(SB)
+
+TEXT ·CompareAndSwapInt32(SB),NOSPLIT,$0-17
+ JMP ·CompareAndSwapUint32(SB)
+
+TEXT ·CompareAndSwapUint32(SB),NOSPLIT,$0-17
+ MOVV addr+0(FP), R1
+ MOVW old+8(FP), R2
+ MOVW new+12(FP), R5
+ SYNC
+cas_again:
+ MOVV R5, R3
+ LL(1, 4) // R4 = *R1
+ BNE R2, R4, cas_fail
+ SC(1, 3) // *R1 = R3
+ BEQ R3, cas_again
+ MOVV $1, R1
+ MOVB R1, swapped+16(FP)
+ SYNC
+ RET
+cas_fail:
+ MOVV $0, R1
+ JMP -4(PC)
+
+TEXT ·CompareAndSwapUintptr(SB),NOSPLIT,$0-25
+ JMP ·CompareAndSwapUint64(SB)
+
+TEXT ·CompareAndSwapInt64(SB),NOSPLIT,$0-25
+ JMP ·CompareAndSwapUint64(SB)
+
+TEXT ·CompareAndSwapUint64(SB),NOSPLIT,$0-25
+ MOVV addr+0(FP), R1
+ MOVV old+8(FP), R2
+ MOVV new+16(FP), R5
+ SYNC
+cas64_again:
+ MOVV R5, R3
+ LLV(1, 4) // R4 = *R1
+ BNE R2, R4, cas64_fail
+ SCV(1, 3) // *R1 = R3
+ BEQ R3, cas64_again
+ MOVV $1, R1
+ MOVB R1, swapped+24(FP)
+ SYNC
+ RET
+cas64_fail:
+ MOVV $0, R1
+ JMP -4(PC)
+
+TEXT ·AddInt32(SB),NOSPLIT,$0-20
+ JMP ·AddUint32(SB)
+
+TEXT ·AddUint32(SB),NOSPLIT,$0-20
+ MOVV addr+0(FP), R2
+ MOVW delta+8(FP), R3
+ SYNC
+ LL(2, 1) // R1 = *R2
+ ADDU R1, R3, R4
+ MOVV R4, R1
+ SC(2, 4) // *R2 = R4
+ BEQ R4, -4(PC)
+ MOVW R1, ret+16(FP)
+ SYNC
+ RET
+
+TEXT ·AddUintptr(SB),NOSPLIT,$0-24
+ JMP ·AddUint64(SB)
+
+TEXT ·AddInt64(SB),NOSPLIT,$0-24
+ JMP ·AddUint64(SB)
+
+TEXT ·AddUint64(SB),NOSPLIT,$0-24
+ MOVV addr+0(FP), R2
+ MOVV delta+8(FP), R3
+ SYNC
+ LLV(2, 1) // R1 = *R2
+ ADDVU R1, R3, R4
+ MOVV R4, R1
+ SCV(2, 4) // *R2 = R4
+ BEQ R4, -4(PC)
+ MOVV R1, ret+16(FP)
+ SYNC
+ RET
+
+TEXT ·LoadInt32(SB),NOSPLIT,$0-12
+ JMP ·LoadUint32(SB)
+
+TEXT ·LoadUint32(SB),NOSPLIT,$0-12
+ MOVV addr+0(FP), R1
+ SYNC
+ MOVWU 0(R1), R1
+ SYNC
+ MOVW R1, val+8(FP)
+ RET
+
+TEXT ·LoadInt64(SB),NOSPLIT,$0-16
+ JMP ·LoadUint64(SB)
+
+TEXT ·LoadUint64(SB),NOSPLIT,$0-16
+ MOVV addr+0(FP), R1
+ SYNC
+ MOVV 0(R1), R1
+ SYNC
+ MOVV R1, val+8(FP)
+ RET
+
+TEXT ·LoadUintptr(SB),NOSPLIT,$0-16
+ JMP ·LoadPointer(SB)
+
+TEXT ·LoadPointer(SB),NOSPLIT,$0-16
+ JMP ·LoadUint64(SB)
+
+TEXT ·StoreInt32(SB),NOSPLIT,$0-12
+ JMP ·StoreUint32(SB)
+
+TEXT ·StoreUint32(SB),NOSPLIT,$0-12
+ MOVV addr+0(FP), R1
+ MOVW val+8(FP), R2
+ SYNC
+ MOVW R2, 0(R1)
+ SYNC
+ RET
+
+TEXT ·StoreInt64(SB),NOSPLIT,$0-16
+ JMP ·StoreUint64(SB)
+
+TEXT ·StoreUint64(SB),NOSPLIT,$0-16
+ MOVV addr+0(FP), R1
+ MOVV val+8(FP), R2
+ SYNC
+ MOVV R2, 0(R1)
+ SYNC
+ RET
+
+TEXT ·StoreUintptr(SB),NOSPLIT,$0-16
+ JMP ·StoreUint64(SB)
--- /dev/null
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux
+// +build mips64 mips64le
+
+#include "textflag.h"
+
+//
+// System calls for mips64, Linux
+//
+
+// func Syscall(trap int64, a1, a2, a3 int64) (r1, r2, err int64);
+
+TEXT ·Syscall(SB),NOSPLIT,$0-56
+ JAL runtime·entersyscall(SB)
+ MOVV a1+8(FP), R4
+ MOVV a2+16(FP), R5
+ MOVV a3+24(FP), R6
+ MOVV R0, R7
+ MOVV R0, R8
+ MOVV R0, R9
+ MOVV trap+0(FP), R2 // syscall entry
+ SYSCALL
+ BEQ R7, ok
+ MOVV $-1, R1
+ MOVV R1, r1+32(FP) // r1
+ MOVV R0, r2+40(FP) // r2
+ MOVV R2, err+48(FP) // errno
+ JAL runtime·exitsyscall(SB)
+ RET
+ok:
+ MOVV R2, r1+32(FP) // r1
+ MOVV R3, r2+40(FP) // r2
+ MOVV R0, err+48(FP) // errno
+ JAL runtime·exitsyscall(SB)
+ RET
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ JAL runtime·entersyscall(SB)
+ MOVV a1+8(FP), R4
+ MOVV a2+16(FP), R5
+ MOVV a3+24(FP), R6
+ MOVV a4+32(FP), R7
+ MOVV a5+40(FP), R8
+ MOVV a6+48(FP), R9
+ MOVV trap+0(FP), R2 // syscall entry
+ SYSCALL
+ BEQ R7, ok6
+ MOVV $-1, R1
+ MOVV R1, r1+56(FP) // r1
+ MOVV R0, r2+64(FP) // r2
+ MOVV R2, err+72(FP) // errno
+ JAL runtime·exitsyscall(SB)
+ RET
+ok6:
+ MOVV R2, r1+56(FP) // r1
+ MOVV R3, r2+64(FP) // r2
+ MOVV R0, err+72(FP) // errno
+ JAL runtime·exitsyscall(SB)
+ RET
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ MOVV a1+8(FP), R4
+ MOVV a2+16(FP), R5
+ MOVV a3+24(FP), R6
+ MOVV R0, R7
+ MOVV R0, R8
+ MOVV R0, R9
+ MOVV trap+0(FP), R2 // syscall entry
+ SYSCALL
+ BEQ R7, ok1
+ MOVV $-1, R1
+ MOVV R1, r1+32(FP) // r1
+ MOVV R0, r2+40(FP) // r2
+ MOVV R2, err+48(FP) // errno
+ RET
+ok1:
+ MOVV R2, r1+32(FP) // r1
+ MOVV R3, r2+40(FP) // r2
+ MOVV R0, err+48(FP) // errno
+ RET
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ MOVV a1+8(FP), R4
+ MOVV a2+16(FP), R5
+ MOVV a3+24(FP), R6
+ MOVV a4+32(FP), R7
+ MOVV a5+40(FP), R8
+ MOVV a6+48(FP), R9
+ MOVV trap+0(FP), R2 // syscall entry
+ SYSCALL
+ BEQ R7, ok2
+ MOVV $-1, R1
+ MOVV R1, r1+56(FP) // r1
+ MOVV R0, r2+64(FP) // r2
+ MOVV R2, err+72(FP) // errno
+ RET
+ok2:
+ MOVV R2, r1+56(FP) // r1
+ MOVV R3, r2+64(FP) // r2
+ MOVV R0, err+72(FP) // errno
+ RET
EACCES = NewError("access permission denied")
EAFNOSUPPORT = NewError("address family not supported by protocol")
)
+
+// Notes
+const (
+ SIGABRT = Note("abort")
+ SIGALRM = Note("alarm")
+ SIGHUP = Note("hangup")
+ SIGINT = Note("interrupt")
+ SIGKILL = Note("kill")
+ SIGTERM = Note("interrupt")
+)
// For the same reason compiler does not race instrument it.
// The calls to RawSyscall are okay because they are assembly
// functions that do not grow the stack.
+//go:norace
func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) {
// Declare all variables at top in case any
// declarations require heap allocation (e.g., err1).
// For the same reason compiler does not race instrument it.
// The calls to RawSyscall are okay because they are assembly
// functions that do not grow the stack.
+//go:norace
func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) {
// Declare all variables at top in case any
// declarations require heap allocation (e.g., err1).
// no rescheduling, no malloc calls, and no new stack segments.
// The calls to RawSyscall are okay because they are assembly
// functions that do not grow the stack.
+//go:norace
func forkAndExecInChild(argv0 *byte, argv []*byte, envv []envItem, dir *byte, attr *ProcAttr, fdsToClose []int, pipe int, rflag int) (pid int, err error) {
// Declare all variables at top in case any
// declarations require heap allocation (e.g., errbuf).
// because we need to avoid lazy-loading the functions (might malloc,
// split the stack, or acquire mutexes). We can't call RawSyscall
// because it's not safe even for BSD-subsystem calls.
+//go:norace
func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) {
// Declare all variables at top in case any
// declarations require heap allocation (e.g., err1).
--- /dev/null
+// Copyright 2015 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 msan
+
+package syscall
+
+import (
+ "runtime"
+ "unsafe"
+)
+
+const msanenabled = true
+
+func msanRead(addr unsafe.Pointer, len int) {
+ runtime.MSanRead(addr, len)
+}
+
+func msanWrite(addr unsafe.Pointer, len int) {
+ runtime.MSanWrite(addr, len)
+}
--- /dev/null
+// Copyright 2015 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 !msan
+
+package syscall
+
+import (
+ "unsafe"
+)
+
+const msanenabled = false
+
+func msanRead(addr unsafe.Pointer, len int) {
+}
+
+func msanWrite(addr unsafe.Pointer, len int) {
+}
if f.listener != nil {
return EINVAL
}
- _, ok := net.listener[netAddr{f.proto, f.sotype, f.addr.key()}]
- if ok {
+ old, ok := net.listener[netAddr{f.proto, f.sotype, f.addr.key()}]
+ if ok && !old.listenerClosed() {
return EADDRINUSE
}
net.listener[netAddr{f.proto, f.sotype, f.addr.key()}] = f
//sys Fdatasync(fd int) (err error)
//sys Flock(fd int, how int) (err error)
//sys Fsync(fd int) (err error)
-//sys Getdents(fd int, buf []byte) (n int, err error) = SYS_GETDENTS64
+//sys Getdents(fd int, buf []byte) (n int, err error) = _SYS_getdents
//sysnb Getpgid(pid int) (pgid int, err error)
func Getpgrp() (pid int) {
return EOPNOTSUPP
}
-func Setgid(uid int) (err error) {
+func Setgid(gid int) (err error) {
return EOPNOTSUPP
}
import "unsafe"
-const _SYS_dup = SYS_DUP2
+const (
+ _SYS_dup = SYS_DUP2
+ _SYS_getdents = SYS_GETDENTS64
+)
func Getpagesize() int { return 4096 }
package syscall
-const _SYS_dup = SYS_DUP2
+const (
+ _SYS_dup = SYS_DUP2
+ _SYS_getdents = SYS_GETDENTS64
+)
//sys Dup2(oldfd int, newfd int) (err error)
//sys Fchown(fd int, uid int, gid int) (err error)
import "unsafe"
-const _SYS_dup = SYS_DUP2
+const (
+ _SYS_dup = SYS_DUP2
+ _SYS_getdents = SYS_GETDENTS64
+)
func Getpagesize() int { return 4096 }
package syscall
-const _SYS_dup = SYS_DUP3
+const (
+ _SYS_dup = SYS_DUP3
+ _SYS_getdents = SYS_GETDENTS64
+)
//sys Fchown(fd int, uid int, gid int) (err error)
//sys Fstat(fd int, stat *Stat_t) (err error)
--- /dev/null
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux
+// +build mips64 mips64le
+
+package syscall
+
+const (
+ _SYS_dup = SYS_DUP2
+
+ // Linux introduced getdents64 syscall for N64 ABI only in 3.10
+ // (May 21 2013, rev dec33abaafc89bcbd78f85fad0513170415a26d5),
+ // to support older kernels, we have to use getdents for mips64.
+ // Also note that struct dirent is different for these two.
+ // Lookup linux_dirent{,64} in kernel source code for details.
+ _SYS_getdents = SYS_GETDENTS
+)
+
+//sys Dup2(oldfd int, newfd int) (err error)
+//sys Fchown(fd int, uid int, gid int) (err error)
+//sys Fstatfs(fd int, buf *Statfs_t) (err error)
+//sys Ftruncate(fd int, length int64) (err error)
+//sysnb Getegid() (egid int)
+//sysnb Geteuid() (euid int)
+//sysnb Getgid() (gid int)
+//sysnb Getrlimit(resource int, rlim *Rlimit) (err error)
+//sysnb Getuid() (uid int)
+//sysnb InotifyInit() (fd int, err error)
+//sys Lchown(path string, uid int, gid int) (err error)
+//sys Listen(s int, n int) (err error)
+//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
+//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
+//sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
+//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS_PSELECT6
+//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
+//sys Setfsgid(gid int) (err error)
+//sys Setfsuid(uid int) (err error)
+//sysnb Setregid(rgid int, egid int) (err error)
+//sysnb Setresgid(rgid int, egid int, sgid int) (err error)
+//sysnb Setresuid(ruid int, euid int, suid int) (err error)
+//sysnb Setrlimit(resource int, rlim *Rlimit) (err error)
+//sysnb Setreuid(ruid int, euid int) (err error)
+//sys Shutdown(fd int, how int) (err error)
+//sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
+//sys Statfs(path string, buf *Statfs_t) (err error)
+//sys SyncFileRange(fd int, off int64, n int64, flags int) (err error)
+//sys Truncate(path string, length int64) (err error)
+//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error)
+//sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error)
+//sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
+//sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
+//sysnb getgroups(n int, list *_Gid_t) (nn int, err error)
+//sysnb setgroups(n int, list *_Gid_t) (err error)
+//sys getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error)
+//sys setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error)
+//sysnb socket(domain int, typ int, proto int) (fd int, err error)
+//sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error)
+//sysnb getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
+//sysnb getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
+//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error)
+//sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error)
+//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error)
+//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error)
+//sys mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error)
+
+func Getpagesize() int { return 65536 }
+
+//sysnb Gettimeofday(tv *Timeval) (err error)
+
+func Time(t *Time_t) (tt Time_t, err error) {
+ var tv Timeval
+ err = Gettimeofday(&tv)
+ if err != nil {
+ return 0, err
+ }
+ if t != nil {
+ *t = Time_t(tv.Sec)
+ }
+ return Time_t(tv.Sec), nil
+}
+
+func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
+
+func NsecToTimespec(nsec int64) (ts Timespec) {
+ ts.Sec = nsec / 1e9
+ ts.Nsec = nsec % 1e9
+ return
+}
+
+func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
+
+func NsecToTimeval(nsec int64) (tv Timeval) {
+ nsec += 999 // round up to microsecond
+ tv.Sec = nsec / 1e9
+ tv.Usec = nsec % 1e9 / 1e3
+ return
+}
+
+func Pipe(p []int) (err error) {
+ if len(p) != 2 {
+ return EINVAL
+ }
+ var pp [2]_C_int
+ err = pipe2(&pp, 0)
+ p[0] = int(pp[0])
+ p[1] = int(pp[1])
+ return
+}
+
+//sysnb pipe2(p *[2]_C_int, flags int) (err error)
+
+func Pipe2(p []int, flags int) (err error) {
+ if len(p) != 2 {
+ return EINVAL
+ }
+ var pp [2]_C_int
+ err = pipe2(&pp, flags)
+ p[0] = int(pp[0])
+ p[1] = int(pp[1])
+ return
+}
+
+func Ioperm(from int, num int, on int) (err error) {
+ return ENOSYS
+}
+
+func Iopl(level int) (err error) {
+ return ENOSYS
+}
+
+type stat_t struct {
+ Dev uint32
+ Pad0 [3]int32
+ Ino uint64
+ Mode uint32
+ Nlink uint32
+ Uid uint32
+ Gid uint32
+ Rdev uint32
+ Pad1 [3]uint32
+ Size int64
+ Atime uint32
+ Atime_nsec uint32
+ Mtime uint32
+ Mtime_nsec uint32
+ Ctime uint32
+ Ctime_nsec uint32
+ Blksize uint32
+ Pad2 uint32
+ Blocks int64
+}
+
+//sys fstat(fd int, st *stat_t) (err error)
+//sys lstat(path string, st *stat_t) (err error)
+//sys stat(path string, st *stat_t) (err error)
+
+func Fstat(fd int, s *Stat_t) (err error) {
+ st := &stat_t{}
+ err = fstat(fd, st)
+ fillStat_t(s, st)
+ return
+}
+
+func Lstat(path string, s *Stat_t) (err error) {
+ st := &stat_t{}
+ err = lstat(path, st)
+ fillStat_t(s, st)
+ return
+}
+
+func Stat(path string, s *Stat_t) (err error) {
+ st := &stat_t{}
+ err = stat(path, st)
+ fillStat_t(s, st)
+ return
+}
+
+func fillStat_t(s *Stat_t, st *stat_t) {
+ s.Dev = st.Dev
+ s.Ino = st.Ino
+ s.Mode = st.Mode
+ s.Nlink = st.Nlink
+ s.Uid = st.Uid
+ s.Gid = st.Gid
+ s.Rdev = st.Rdev
+ s.Size = st.Size
+ s.Atim = Timespec{int64(st.Atime), int64(st.Atime_nsec)}
+ s.Mtim = Timespec{int64(st.Mtime), int64(st.Mtime_nsec)}
+ s.Ctim = Timespec{int64(st.Ctime), int64(st.Ctime_nsec)}
+ s.Blksize = st.Blksize
+ s.Blocks = st.Blocks
+}
+
+func (r *PtraceRegs) PC() uint64 { return r.Regs[64] }
+
+func (r *PtraceRegs) SetPC(pc uint64) { r.Regs[64] = pc }
+
+func (iov *Iovec) SetLen(length int) {
+ iov.Len = uint64(length)
+}
+
+func (msghdr *Msghdr) SetControllen(length int) {
+ msghdr.Controllen = uint64(length)
+}
+
+func (cmsg *Cmsghdr) SetLen(length int) {
+ cmsg.Len = uint64(length)
+}
package syscall
-const _SYS_dup = SYS_DUP2
+const (
+ _SYS_dup = SYS_DUP2
+ _SYS_getdents = SYS_GETDENTS64
+)
//sys Dup2(oldfd int, newfd int) (err error)
//sys Fchown(fd int, uid int, gid int) (err error)
raceAcquire(unsafe.Pointer(&ioSync))
}
}
+ if msanenabled && n > 0 {
+ msanWrite(unsafe.Pointer(&p[0]), n)
+ }
return
}
if raceenabled && n > 0 {
raceReadRange(unsafe.Pointer(&p[0]), n)
}
+ if msanenabled && n > 0 {
+ msanRead(unsafe.Pointer(&p[0]), n)
+ }
return
}
}
raceAcquire(unsafe.Pointer(&ioSync))
}
+ if msanenabled && done > 0 {
+ msanWrite(unsafe.Pointer(&p[0]), int(done))
+ }
return int(done), nil
}
if raceenabled && done > 0 {
raceReadRange(unsafe.Pointer(&p[0]), int(done))
}
+ if msanenabled && done > 0 {
+ msanRead(unsafe.Pointer(&p[0]), int(done))
+ }
return int(done), nil
}
typedef struct user_pt_regs PtraceRegs;
#elif defined(__powerpc64__)
typedef struct pt_regs PtraceRegs;
+#elif defined(__mips__)
+typedef struct user PtraceRegs;
#else
typedef struct user_regs_struct PtraceRegs;
#endif
--- /dev/null
+// mkerrors.sh
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs _const.go
+
+package syscall
+
+const (
+ AF_ALG = 0x26
+ AF_APPLETALK = 0x5
+ AF_ASH = 0x12
+ AF_ATMPVC = 0x8
+ AF_ATMSVC = 0x14
+ AF_AX25 = 0x3
+ AF_BLUETOOTH = 0x1f
+ AF_BRIDGE = 0x7
+ AF_CAIF = 0x25
+ AF_CAN = 0x1d
+ AF_DECnet = 0xc
+ AF_ECONET = 0x13
+ AF_FILE = 0x1
+ AF_IEEE802154 = 0x24
+ AF_INET = 0x2
+ AF_INET6 = 0xa
+ AF_IPX = 0x4
+ AF_IRDA = 0x17
+ AF_ISDN = 0x22
+ AF_IUCV = 0x20
+ AF_KEY = 0xf
+ AF_LLC = 0x1a
+ AF_LOCAL = 0x1
+ AF_MAX = 0x28
+ AF_NETBEUI = 0xd
+ AF_NETLINK = 0x10
+ AF_NETROM = 0x6
+ AF_NFC = 0x27
+ AF_PACKET = 0x11
+ AF_PHONET = 0x23
+ AF_PPPOX = 0x18
+ AF_RDS = 0x15
+ AF_ROSE = 0xb
+ AF_ROUTE = 0x10
+ AF_RXRPC = 0x21
+ AF_SECURITY = 0xe
+ AF_SNA = 0x16
+ AF_TIPC = 0x1e
+ AF_UNIX = 0x1
+ AF_UNSPEC = 0x0
+ AF_WANPIPE = 0x19
+ AF_X25 = 0x9
+ ARPHRD_ADAPT = 0x108
+ ARPHRD_APPLETLK = 0x8
+ ARPHRD_ARCNET = 0x7
+ ARPHRD_ASH = 0x30d
+ ARPHRD_ATM = 0x13
+ ARPHRD_AX25 = 0x3
+ ARPHRD_BIF = 0x307
+ ARPHRD_CAIF = 0x336
+ ARPHRD_CAN = 0x118
+ ARPHRD_CHAOS = 0x5
+ ARPHRD_CISCO = 0x201
+ ARPHRD_CSLIP = 0x101
+ ARPHRD_CSLIP6 = 0x103
+ ARPHRD_DDCMP = 0x205
+ ARPHRD_DLCI = 0xf
+ ARPHRD_ECONET = 0x30e
+ ARPHRD_EETHER = 0x2
+ ARPHRD_ETHER = 0x1
+ ARPHRD_EUI64 = 0x1b
+ ARPHRD_FCAL = 0x311
+ ARPHRD_FCFABRIC = 0x313
+ ARPHRD_FCPL = 0x312
+ ARPHRD_FCPP = 0x310
+ ARPHRD_FDDI = 0x306
+ ARPHRD_FRAD = 0x302
+ ARPHRD_HDLC = 0x201
+ ARPHRD_HIPPI = 0x30c
+ ARPHRD_HWX25 = 0x110
+ ARPHRD_IEEE1394 = 0x18
+ ARPHRD_IEEE802 = 0x6
+ ARPHRD_IEEE80211 = 0x321
+ ARPHRD_IEEE80211_PRISM = 0x322
+ ARPHRD_IEEE80211_RADIOTAP = 0x323
+ ARPHRD_IEEE802154 = 0x324
+ ARPHRD_IEEE802154_MONITOR = 0x325
+ ARPHRD_IEEE802_TR = 0x320
+ ARPHRD_INFINIBAND = 0x20
+ ARPHRD_IP6GRE = 0x337
+ ARPHRD_IPDDP = 0x309
+ ARPHRD_IPGRE = 0x30a
+ ARPHRD_IRDA = 0x30f
+ ARPHRD_LAPB = 0x204
+ ARPHRD_LOCALTLK = 0x305
+ ARPHRD_LOOPBACK = 0x304
+ ARPHRD_METRICOM = 0x17
+ ARPHRD_NETLINK = 0x338
+ ARPHRD_NETROM = 0x0
+ ARPHRD_NONE = 0xfffe
+ ARPHRD_PHONET = 0x334
+ ARPHRD_PHONET_PIPE = 0x335
+ ARPHRD_PIMREG = 0x30b
+ ARPHRD_PPP = 0x200
+ ARPHRD_PRONET = 0x4
+ ARPHRD_RAWHDLC = 0x206
+ ARPHRD_ROSE = 0x10e
+ ARPHRD_RSRVD = 0x104
+ ARPHRD_SIT = 0x308
+ ARPHRD_SKIP = 0x303
+ ARPHRD_SLIP = 0x100
+ ARPHRD_SLIP6 = 0x102
+ ARPHRD_TUNNEL = 0x300
+ ARPHRD_TUNNEL6 = 0x301
+ ARPHRD_VOID = 0xffff
+ ARPHRD_X25 = 0x10f
+ B0 = 0x0
+ B1000000 = 0x1008
+ B110 = 0x3
+ B115200 = 0x1002
+ B1152000 = 0x1009
+ B1200 = 0x9
+ B134 = 0x4
+ B150 = 0x5
+ B1500000 = 0x100a
+ B1800 = 0xa
+ B19200 = 0xe
+ B200 = 0x6
+ B2000000 = 0x100b
+ B230400 = 0x1003
+ B2400 = 0xb
+ B2500000 = 0x100c
+ B300 = 0x7
+ B3000000 = 0x100d
+ B3500000 = 0x100e
+ B38400 = 0xf
+ B4000000 = 0x100f
+ B460800 = 0x1004
+ B4800 = 0xc
+ B50 = 0x1
+ B500000 = 0x1005
+ B57600 = 0x1001
+ B576000 = 0x1006
+ B600 = 0x8
+ B75 = 0x2
+ B921600 = 0x1007
+ B9600 = 0xd
+ BPF_A = 0x10
+ BPF_ABS = 0x20
+ BPF_ADD = 0x0
+ BPF_ALU = 0x4
+ BPF_AND = 0x50
+ BPF_B = 0x10
+ BPF_DIV = 0x30
+ BPF_H = 0x8
+ BPF_IMM = 0x0
+ BPF_IND = 0x40
+ BPF_JA = 0x0
+ BPF_JEQ = 0x10
+ BPF_JGE = 0x30
+ BPF_JGT = 0x20
+ BPF_JMP = 0x5
+ BPF_JSET = 0x40
+ BPF_K = 0x0
+ BPF_LD = 0x0
+ BPF_LDX = 0x1
+ BPF_LEN = 0x80
+ BPF_LSH = 0x60
+ BPF_MAJOR_VERSION = 0x1
+ BPF_MAXINSNS = 0x1000
+ BPF_MEM = 0x60
+ BPF_MEMWORDS = 0x10
+ BPF_MINOR_VERSION = 0x1
+ BPF_MISC = 0x7
+ BPF_MOD = 0x90
+ BPF_MSH = 0xa0
+ BPF_MUL = 0x20
+ BPF_NEG = 0x80
+ BPF_OR = 0x40
+ BPF_RET = 0x6
+ BPF_RSH = 0x70
+ BPF_ST = 0x2
+ BPF_STX = 0x3
+ BPF_SUB = 0x10
+ BPF_TAX = 0x0
+ BPF_TXA = 0x80
+ BPF_W = 0x0
+ BPF_X = 0x8
+ BPF_XOR = 0xa0
+ BRKINT = 0x2
+ CFLUSH = 0xf
+ CLOCAL = 0x800
+ CLONE_CHILD_CLEARTID = 0x200000
+ CLONE_CHILD_SETTID = 0x1000000
+ CLONE_DETACHED = 0x400000
+ CLONE_FILES = 0x400
+ CLONE_FS = 0x200
+ CLONE_IO = 0x80000000
+ CLONE_NEWIPC = 0x8000000
+ CLONE_NEWNET = 0x40000000
+ CLONE_NEWNS = 0x20000
+ CLONE_NEWPID = 0x20000000
+ CLONE_NEWUSER = 0x10000000
+ CLONE_NEWUTS = 0x4000000
+ CLONE_PARENT = 0x8000
+ CLONE_PARENT_SETTID = 0x100000
+ CLONE_PTRACE = 0x2000
+ CLONE_SETTLS = 0x80000
+ CLONE_SIGHAND = 0x800
+ CLONE_SYSVSEM = 0x40000
+ CLONE_THREAD = 0x10000
+ CLONE_UNTRACED = 0x800000
+ CLONE_VFORK = 0x4000
+ CLONE_VM = 0x100
+ CREAD = 0x80
+ CS5 = 0x0
+ CS6 = 0x10
+ CS7 = 0x20
+ CS8 = 0x30
+ CSIGNAL = 0xff
+ CSIZE = 0x30
+ CSTART = 0x11
+ CSTATUS = 0x0
+ CSTOP = 0x13
+ CSTOPB = 0x40
+ CSUSP = 0x1a
+ DT_BLK = 0x6
+ DT_CHR = 0x2
+ DT_DIR = 0x4
+ DT_FIFO = 0x1
+ DT_LNK = 0xa
+ DT_REG = 0x8
+ DT_SOCK = 0xc
+ DT_UNKNOWN = 0x0
+ DT_WHT = 0xe
+ ECHO = 0x8
+ ECHOCTL = 0x200
+ ECHOE = 0x10
+ ECHOK = 0x20
+ ECHOKE = 0x800
+ ECHONL = 0x40
+ ECHOPRT = 0x400
+ ENCODING_DEFAULT = 0x0
+ ENCODING_FM_MARK = 0x3
+ ENCODING_FM_SPACE = 0x4
+ ENCODING_MANCHESTER = 0x5
+ ENCODING_NRZ = 0x1
+ ENCODING_NRZI = 0x2
+ EPOLLERR = 0x8
+ EPOLLET = 0x80000000
+ EPOLLHUP = 0x10
+ EPOLLIN = 0x1
+ EPOLLMSG = 0x400
+ EPOLLONESHOT = 0x40000000
+ EPOLLOUT = 0x4
+ EPOLLPRI = 0x2
+ EPOLLRDBAND = 0x80
+ EPOLLRDHUP = 0x2000
+ EPOLLRDNORM = 0x40
+ EPOLLWAKEUP = 0x20000000
+ EPOLLWRBAND = 0x200
+ EPOLLWRNORM = 0x100
+ EPOLL_CLOEXEC = 0x80000
+ EPOLL_CTL_ADD = 0x1
+ EPOLL_CTL_DEL = 0x2
+ EPOLL_CTL_MOD = 0x3
+ EPOLL_NONBLOCK = 0x80
+ ETH_P_1588 = 0x88f7
+ ETH_P_8021AD = 0x88a8
+ ETH_P_8021AH = 0x88e7
+ ETH_P_8021Q = 0x8100
+ ETH_P_802_2 = 0x4
+ ETH_P_802_3 = 0x1
+ ETH_P_802_3_MIN = 0x600
+ ETH_P_802_EX1 = 0x88b5
+ ETH_P_AARP = 0x80f3
+ ETH_P_AF_IUCV = 0xfbfb
+ ETH_P_ALL = 0x3
+ ETH_P_AOE = 0x88a2
+ ETH_P_ARCNET = 0x1a
+ ETH_P_ARP = 0x806
+ ETH_P_ATALK = 0x809b
+ ETH_P_ATMFATE = 0x8884
+ ETH_P_ATMMPOA = 0x884c
+ ETH_P_AX25 = 0x2
+ ETH_P_BATMAN = 0x4305
+ ETH_P_BPQ = 0x8ff
+ ETH_P_CAIF = 0xf7
+ ETH_P_CAN = 0xc
+ ETH_P_CANFD = 0xd
+ ETH_P_CONTROL = 0x16
+ ETH_P_CUST = 0x6006
+ ETH_P_DDCMP = 0x6
+ ETH_P_DEC = 0x6000
+ ETH_P_DIAG = 0x6005
+ ETH_P_DNA_DL = 0x6001
+ ETH_P_DNA_RC = 0x6002
+ ETH_P_DNA_RT = 0x6003
+ ETH_P_DSA = 0x1b
+ ETH_P_ECONET = 0x18
+ ETH_P_EDSA = 0xdada
+ ETH_P_FCOE = 0x8906
+ ETH_P_FIP = 0x8914
+ ETH_P_HDLC = 0x19
+ ETH_P_IEEE802154 = 0xf6
+ ETH_P_IEEEPUP = 0xa00
+ ETH_P_IEEEPUPAT = 0xa01
+ ETH_P_IP = 0x800
+ ETH_P_IPV6 = 0x86dd
+ ETH_P_IPX = 0x8137
+ ETH_P_IRDA = 0x17
+ ETH_P_LAT = 0x6004
+ ETH_P_LINK_CTL = 0x886c
+ ETH_P_LOCALTALK = 0x9
+ ETH_P_LOOP = 0x60
+ ETH_P_MOBITEX = 0x15
+ ETH_P_MPLS_MC = 0x8848
+ ETH_P_MPLS_UC = 0x8847
+ ETH_P_MVRP = 0x88f5
+ ETH_P_PAE = 0x888e
+ ETH_P_PAUSE = 0x8808
+ ETH_P_PHONET = 0xf5
+ ETH_P_PPPTALK = 0x10
+ ETH_P_PPP_DISC = 0x8863
+ ETH_P_PPP_MP = 0x8
+ ETH_P_PPP_SES = 0x8864
+ ETH_P_PUP = 0x200
+ ETH_P_PUPAT = 0x201
+ ETH_P_QINQ1 = 0x9100
+ ETH_P_QINQ2 = 0x9200
+ ETH_P_QINQ3 = 0x9300
+ ETH_P_RARP = 0x8035
+ ETH_P_SCA = 0x6007
+ ETH_P_SLOW = 0x8809
+ ETH_P_SNAP = 0x5
+ ETH_P_TDLS = 0x890d
+ ETH_P_TEB = 0x6558
+ ETH_P_TIPC = 0x88ca
+ ETH_P_TRAILER = 0x1c
+ ETH_P_TR_802_2 = 0x11
+ ETH_P_WAN_PPP = 0x7
+ ETH_P_WCCP = 0x883e
+ ETH_P_X25 = 0x805
+ EXTA = 0xe
+ EXTB = 0xf
+ EXTPROC = 0x10000
+ FD_CLOEXEC = 0x1
+ FD_SETSIZE = 0x400
+ FLUSHO = 0x2000
+ F_DUPFD = 0x0
+ F_DUPFD_CLOEXEC = 0x406
+ F_EXLCK = 0x4
+ F_GETFD = 0x1
+ F_GETFL = 0x3
+ F_GETLEASE = 0x401
+ F_GETLK = 0xe
+ F_GETLK64 = 0xe
+ F_GETOWN = 0x17
+ F_GETOWN_EX = 0x10
+ F_GETPIPE_SZ = 0x408
+ F_GETSIG = 0xb
+ F_LOCK = 0x1
+ F_NOTIFY = 0x402
+ F_OK = 0x0
+ F_RDLCK = 0x0
+ F_SETFD = 0x2
+ F_SETFL = 0x4
+ F_SETLEASE = 0x400
+ F_SETLK = 0x6
+ F_SETLK64 = 0x6
+ F_SETLKW = 0x7
+ F_SETLKW64 = 0x7
+ F_SETOWN = 0x18
+ F_SETOWN_EX = 0xf
+ F_SETPIPE_SZ = 0x407
+ F_SETSIG = 0xa
+ F_SHLCK = 0x8
+ F_TEST = 0x3
+ F_TLOCK = 0x2
+ F_ULOCK = 0x0
+ F_UNLCK = 0x2
+ F_WRLCK = 0x1
+ HUPCL = 0x400
+ ICANON = 0x2
+ ICMPV6_FILTER = 0x1
+ ICRNL = 0x100
+ IEXTEN = 0x100
+ IFA_F_DADFAILED = 0x8
+ IFA_F_DEPRECATED = 0x20
+ IFA_F_HOMEADDRESS = 0x10
+ IFA_F_NODAD = 0x2
+ IFA_F_OPTIMISTIC = 0x4
+ IFA_F_PERMANENT = 0x80
+ IFA_F_SECONDARY = 0x1
+ IFA_F_TEMPORARY = 0x1
+ IFA_F_TENTATIVE = 0x40
+ IFA_MAX = 0x7
+ IFF_802_1Q_VLAN = 0x1
+ IFF_ALLMULTI = 0x200
+ IFF_ATTACH_QUEUE = 0x200
+ IFF_AUTOMEDIA = 0x4000
+ IFF_BONDING = 0x20
+ IFF_BRIDGE_PORT = 0x4000
+ IFF_BROADCAST = 0x2
+ IFF_DEBUG = 0x4
+ IFF_DETACH_QUEUE = 0x400
+ IFF_DISABLE_NETPOLL = 0x1000
+ IFF_DONT_BRIDGE = 0x800
+ IFF_DORMANT = 0x20000
+ IFF_DYNAMIC = 0x8000
+ IFF_EBRIDGE = 0x2
+ IFF_ECHO = 0x40000
+ IFF_ISATAP = 0x80
+ IFF_LIVE_ADDR_CHANGE = 0x100000
+ IFF_LOOPBACK = 0x8
+ IFF_LOWER_UP = 0x10000
+ IFF_MACVLAN_PORT = 0x2000
+ IFF_MASTER = 0x400
+ IFF_MASTER_8023AD = 0x8
+ IFF_MASTER_ALB = 0x10
+ IFF_MASTER_ARPMON = 0x100
+ IFF_MULTICAST = 0x1000
+ IFF_MULTI_QUEUE = 0x100
+ IFF_NOARP = 0x80
+ IFF_NOFILTER = 0x1000
+ IFF_NOTRAILERS = 0x20
+ IFF_NO_PI = 0x1000
+ IFF_ONE_QUEUE = 0x2000
+ IFF_OVS_DATAPATH = 0x8000
+ IFF_PERSIST = 0x800
+ IFF_POINTOPOINT = 0x10
+ IFF_PORTSEL = 0x2000
+ IFF_PROMISC = 0x100
+ IFF_RUNNING = 0x40
+ IFF_SLAVE = 0x800
+ IFF_SLAVE_INACTIVE = 0x4
+ IFF_SLAVE_NEEDARP = 0x40
+ IFF_SUPP_NOFCS = 0x80000
+ IFF_TAP = 0x2
+ IFF_TEAM_PORT = 0x40000
+ IFF_TUN = 0x1
+ IFF_TUN_EXCL = 0x8000
+ IFF_TX_SKB_SHARING = 0x10000
+ IFF_UNICAST_FLT = 0x20000
+ IFF_UP = 0x1
+ IFF_VNET_HDR = 0x4000
+ IFF_VOLATILE = 0x70c5a
+ IFF_WAN_HDLC = 0x200
+ IFF_XMIT_DST_RELEASE = 0x400
+ IFNAMSIZ = 0x10
+ IGNBRK = 0x1
+ IGNCR = 0x80
+ IGNPAR = 0x4
+ IMAXBEL = 0x2000
+ INLCR = 0x40
+ INPCK = 0x10
+ IN_ACCESS = 0x1
+ IN_ALL_EVENTS = 0xfff
+ IN_ATTRIB = 0x4
+ IN_CLASSA_HOST = 0xffffff
+ IN_CLASSA_MAX = 0x80
+ IN_CLASSA_NET = 0xff000000
+ IN_CLASSA_NSHIFT = 0x18
+ IN_CLASSB_HOST = 0xffff
+ IN_CLASSB_MAX = 0x10000
+ IN_CLASSB_NET = 0xffff0000
+ IN_CLASSB_NSHIFT = 0x10
+ IN_CLASSC_HOST = 0xff
+ IN_CLASSC_NET = 0xffffff00
+ IN_CLASSC_NSHIFT = 0x8
+ IN_CLOEXEC = 0x80000
+ IN_CLOSE = 0x18
+ IN_CLOSE_NOWRITE = 0x10
+ IN_CLOSE_WRITE = 0x8
+ IN_CREATE = 0x100
+ IN_DELETE = 0x200
+ IN_DELETE_SELF = 0x400
+ IN_DONT_FOLLOW = 0x2000000
+ IN_EXCL_UNLINK = 0x4000000
+ IN_IGNORED = 0x8000
+ IN_ISDIR = 0x40000000
+ IN_LOOPBACKNET = 0x7f
+ IN_MASK_ADD = 0x20000000
+ IN_MODIFY = 0x2
+ IN_MOVE = 0xc0
+ IN_MOVED_FROM = 0x40
+ IN_MOVED_TO = 0x80
+ IN_MOVE_SELF = 0x800
+ IN_NONBLOCK = 0x80
+ IN_ONESHOT = 0x80000000
+ IN_ONLYDIR = 0x1000000
+ IN_OPEN = 0x20
+ IN_Q_OVERFLOW = 0x4000
+ IN_UNMOUNT = 0x2000
+ IPPROTO_AH = 0x33
+ IPPROTO_COMP = 0x6c
+ IPPROTO_DCCP = 0x21
+ IPPROTO_DSTOPTS = 0x3c
+ IPPROTO_EGP = 0x8
+ IPPROTO_ENCAP = 0x62
+ IPPROTO_ESP = 0x32
+ IPPROTO_FRAGMENT = 0x2c
+ IPPROTO_GRE = 0x2f
+ IPPROTO_HOPOPTS = 0x0
+ IPPROTO_ICMP = 0x1
+ IPPROTO_ICMPV6 = 0x3a
+ IPPROTO_IDP = 0x16
+ IPPROTO_IGMP = 0x2
+ IPPROTO_IP = 0x0
+ IPPROTO_IPIP = 0x4
+ IPPROTO_IPV6 = 0x29
+ IPPROTO_MTP = 0x5c
+ IPPROTO_NONE = 0x3b
+ IPPROTO_PIM = 0x67
+ IPPROTO_PUP = 0xc
+ IPPROTO_RAW = 0xff
+ IPPROTO_ROUTING = 0x2b
+ IPPROTO_RSVP = 0x2e
+ IPPROTO_SCTP = 0x84
+ IPPROTO_TCP = 0x6
+ IPPROTO_TP = 0x1d
+ IPPROTO_UDP = 0x11
+ IPPROTO_UDPLITE = 0x88
+ IPV6_2292DSTOPTS = 0x4
+ IPV6_2292HOPLIMIT = 0x8
+ IPV6_2292HOPOPTS = 0x3
+ IPV6_2292PKTINFO = 0x2
+ IPV6_2292PKTOPTIONS = 0x6
+ IPV6_2292RTHDR = 0x5
+ IPV6_ADDRFORM = 0x1
+ IPV6_ADD_MEMBERSHIP = 0x14
+ IPV6_AUTHHDR = 0xa
+ IPV6_CHECKSUM = 0x7
+ IPV6_DROP_MEMBERSHIP = 0x15
+ IPV6_DSTOPTS = 0x3b
+ IPV6_HOPLIMIT = 0x34
+ IPV6_HOPOPTS = 0x36
+ IPV6_IPSEC_POLICY = 0x22
+ IPV6_JOIN_ANYCAST = 0x1b
+ IPV6_JOIN_GROUP = 0x14
+ IPV6_LEAVE_ANYCAST = 0x1c
+ IPV6_LEAVE_GROUP = 0x15
+ IPV6_MTU = 0x18
+ IPV6_MTU_DISCOVER = 0x17
+ IPV6_MULTICAST_HOPS = 0x12
+ IPV6_MULTICAST_IF = 0x11
+ IPV6_MULTICAST_LOOP = 0x13
+ IPV6_NEXTHOP = 0x9
+ IPV6_PKTINFO = 0x32
+ IPV6_PMTUDISC_DO = 0x2
+ IPV6_PMTUDISC_DONT = 0x0
+ IPV6_PMTUDISC_PROBE = 0x3
+ IPV6_PMTUDISC_WANT = 0x1
+ IPV6_RECVDSTOPTS = 0x3a
+ IPV6_RECVERR = 0x19
+ IPV6_RECVHOPLIMIT = 0x33
+ IPV6_RECVHOPOPTS = 0x35
+ IPV6_RECVPKTINFO = 0x31
+ IPV6_RECVRTHDR = 0x38
+ IPV6_RECVTCLASS = 0x42
+ IPV6_ROUTER_ALERT = 0x16
+ IPV6_RTHDR = 0x39
+ IPV6_RTHDRDSTOPTS = 0x37
+ IPV6_RTHDR_LOOSE = 0x0
+ IPV6_RTHDR_STRICT = 0x1
+ IPV6_RTHDR_TYPE_0 = 0x0
+ IPV6_RXDSTOPTS = 0x3b
+ IPV6_RXHOPOPTS = 0x36
+ IPV6_TCLASS = 0x43
+ IPV6_UNICAST_HOPS = 0x10
+ IPV6_V6ONLY = 0x1a
+ IPV6_XFRM_POLICY = 0x23
+ IP_ADD_MEMBERSHIP = 0x23
+ IP_ADD_SOURCE_MEMBERSHIP = 0x27
+ IP_BLOCK_SOURCE = 0x26
+ IP_DEFAULT_MULTICAST_LOOP = 0x1
+ IP_DEFAULT_MULTICAST_TTL = 0x1
+ IP_DF = 0x4000
+ IP_DROP_MEMBERSHIP = 0x24
+ IP_DROP_SOURCE_MEMBERSHIP = 0x28
+ IP_FREEBIND = 0xf
+ IP_HDRINCL = 0x3
+ IP_IPSEC_POLICY = 0x10
+ IP_MAXPACKET = 0xffff
+ IP_MAX_MEMBERSHIPS = 0x14
+ IP_MF = 0x2000
+ IP_MINTTL = 0x15
+ IP_MSFILTER = 0x29
+ IP_MSS = 0x240
+ IP_MTU = 0xe
+ IP_MTU_DISCOVER = 0xa
+ IP_MULTICAST_ALL = 0x31
+ IP_MULTICAST_IF = 0x20
+ IP_MULTICAST_LOOP = 0x22
+ IP_MULTICAST_TTL = 0x21
+ IP_OFFMASK = 0x1fff
+ IP_OPTIONS = 0x4
+ IP_ORIGDSTADDR = 0x14
+ IP_PASSSEC = 0x12
+ IP_PKTINFO = 0x8
+ IP_PKTOPTIONS = 0x9
+ IP_PMTUDISC = 0xa
+ IP_PMTUDISC_DO = 0x2
+ IP_PMTUDISC_DONT = 0x0
+ IP_PMTUDISC_PROBE = 0x3
+ IP_PMTUDISC_WANT = 0x1
+ IP_RECVERR = 0xb
+ IP_RECVOPTS = 0x6
+ IP_RECVORIGDSTADDR = 0x14
+ IP_RECVRETOPTS = 0x7
+ IP_RECVTOS = 0xd
+ IP_RECVTTL = 0xc
+ IP_RETOPTS = 0x7
+ IP_RF = 0x8000
+ IP_ROUTER_ALERT = 0x5
+ IP_TOS = 0x1
+ IP_TRANSPARENT = 0x13
+ IP_TTL = 0x2
+ IP_UNBLOCK_SOURCE = 0x25
+ IP_UNICAST_IF = 0x32
+ IP_XFRM_POLICY = 0x11
+ ISIG = 0x1
+ ISTRIP = 0x20
+ IUTF8 = 0x4000
+ IXANY = 0x800
+ IXOFF = 0x1000
+ IXON = 0x400
+ LINUX_REBOOT_CMD_CAD_OFF = 0x0
+ LINUX_REBOOT_CMD_CAD_ON = 0x89abcdef
+ LINUX_REBOOT_CMD_HALT = 0xcdef0123
+ LINUX_REBOOT_CMD_KEXEC = 0x45584543
+ LINUX_REBOOT_CMD_POWER_OFF = 0x4321fedc
+ LINUX_REBOOT_CMD_RESTART = 0x1234567
+ LINUX_REBOOT_CMD_RESTART2 = 0xa1b2c3d4
+ LINUX_REBOOT_CMD_SW_SUSPEND = 0xd000fce2
+ LINUX_REBOOT_MAGIC1 = 0xfee1dead
+ LINUX_REBOOT_MAGIC2 = 0x28121969
+ LOCK_EX = 0x2
+ LOCK_NB = 0x4
+ LOCK_SH = 0x1
+ LOCK_UN = 0x8
+ MADV_DODUMP = 0x11
+ MADV_DOFORK = 0xb
+ MADV_DONTDUMP = 0x10
+ MADV_DONTFORK = 0xa
+ MADV_DONTNEED = 0x4
+ MADV_HUGEPAGE = 0xe
+ MADV_HWPOISON = 0x64
+ MADV_MERGEABLE = 0xc
+ MADV_NOHUGEPAGE = 0xf
+ MADV_NORMAL = 0x0
+ MADV_RANDOM = 0x1
+ MADV_REMOVE = 0x9
+ MADV_SEQUENTIAL = 0x2
+ MADV_UNMERGEABLE = 0xd
+ MADV_WILLNEED = 0x3
+ MAP_ANON = 0x800
+ MAP_ANONYMOUS = 0x800
+ MAP_DENYWRITE = 0x2000
+ MAP_EXECUTABLE = 0x4000
+ MAP_FILE = 0x0
+ MAP_FIXED = 0x10
+ MAP_GROWSDOWN = 0x1000
+ MAP_HUGETLB = 0x80000
+ MAP_LOCKED = 0x8000
+ MAP_NONBLOCK = 0x20000
+ MAP_NORESERVE = 0x400
+ MAP_POPULATE = 0x10000
+ MAP_PRIVATE = 0x2
+ MAP_RENAME = 0x800
+ MAP_SHARED = 0x1
+ MAP_STACK = 0x40000
+ MAP_TYPE = 0xf
+ MCL_CURRENT = 0x1
+ MCL_FUTURE = 0x2
+ MNT_DETACH = 0x2
+ MNT_EXPIRE = 0x4
+ MNT_FORCE = 0x1
+ MSG_CMSG_CLOEXEC = 0x40000000
+ MSG_CONFIRM = 0x800
+ MSG_CTRUNC = 0x8
+ MSG_DONTROUTE = 0x4
+ MSG_DONTWAIT = 0x40
+ MSG_EOR = 0x80
+ MSG_ERRQUEUE = 0x2000
+ MSG_FASTOPEN = 0x20000000
+ MSG_FIN = 0x200
+ MSG_MORE = 0x8000
+ MSG_NOSIGNAL = 0x4000
+ MSG_OOB = 0x1
+ MSG_PEEK = 0x2
+ MSG_PROXY = 0x10
+ MSG_RST = 0x1000
+ MSG_SYN = 0x400
+ MSG_TRUNC = 0x20
+ MSG_TRYHARD = 0x4
+ MSG_WAITALL = 0x100
+ MSG_WAITFORONE = 0x10000
+ MS_ACTIVE = 0x40000000
+ MS_ASYNC = 0x1
+ MS_BIND = 0x1000
+ MS_DIRSYNC = 0x80
+ MS_INVALIDATE = 0x2
+ MS_I_VERSION = 0x800000
+ MS_KERNMOUNT = 0x400000
+ MS_MANDLOCK = 0x40
+ MS_MGC_MSK = 0xffff0000
+ MS_MGC_VAL = 0xc0ed0000
+ MS_MOVE = 0x2000
+ MS_NOATIME = 0x400
+ MS_NODEV = 0x4
+ MS_NODIRATIME = 0x800
+ MS_NOEXEC = 0x8
+ MS_NOSUID = 0x2
+ MS_NOUSER = -0x80000000
+ MS_POSIXACL = 0x10000
+ MS_PRIVATE = 0x40000
+ MS_RDONLY = 0x1
+ MS_REC = 0x4000
+ MS_RELATIME = 0x200000
+ MS_REMOUNT = 0x20
+ MS_RMT_MASK = 0x800051
+ MS_SHARED = 0x100000
+ MS_SILENT = 0x8000
+ MS_SLAVE = 0x80000
+ MS_STRICTATIME = 0x1000000
+ MS_SYNC = 0x4
+ MS_SYNCHRONOUS = 0x10
+ MS_UNBINDABLE = 0x20000
+ NAME_MAX = 0xff
+ NETLINK_ADD_MEMBERSHIP = 0x1
+ NETLINK_AUDIT = 0x9
+ NETLINK_BROADCAST_ERROR = 0x4
+ NETLINK_CONNECTOR = 0xb
+ NETLINK_CRYPTO = 0x15
+ NETLINK_DNRTMSG = 0xe
+ NETLINK_DROP_MEMBERSHIP = 0x2
+ NETLINK_ECRYPTFS = 0x13
+ NETLINK_FIB_LOOKUP = 0xa
+ NETLINK_FIREWALL = 0x3
+ NETLINK_GENERIC = 0x10
+ NETLINK_INET_DIAG = 0x4
+ NETLINK_IP6_FW = 0xd
+ NETLINK_ISCSI = 0x8
+ NETLINK_KOBJECT_UEVENT = 0xf
+ NETLINK_NETFILTER = 0xc
+ NETLINK_NFLOG = 0x5
+ NETLINK_NO_ENOBUFS = 0x5
+ NETLINK_PKTINFO = 0x3
+ NETLINK_RDMA = 0x14
+ NETLINK_ROUTE = 0x0
+ NETLINK_RX_RING = 0x6
+ NETLINK_SCSITRANSPORT = 0x12
+ NETLINK_SELINUX = 0x7
+ NETLINK_SOCK_DIAG = 0x4
+ NETLINK_TX_RING = 0x7
+ NETLINK_UNUSED = 0x1
+ NETLINK_USERSOCK = 0x2
+ NETLINK_XFRM = 0x6
+ NLA_ALIGNTO = 0x4
+ NLA_F_NESTED = 0x8000
+ NLA_F_NET_BYTEORDER = 0x4000
+ NLA_HDRLEN = 0x4
+ NLMSG_ALIGNTO = 0x4
+ NLMSG_DONE = 0x3
+ NLMSG_ERROR = 0x2
+ NLMSG_HDRLEN = 0x10
+ NLMSG_MIN_TYPE = 0x10
+ NLMSG_NOOP = 0x1
+ NLMSG_OVERRUN = 0x4
+ NLM_F_ACK = 0x4
+ NLM_F_APPEND = 0x800
+ NLM_F_ATOMIC = 0x400
+ NLM_F_CREATE = 0x400
+ NLM_F_DUMP = 0x300
+ NLM_F_DUMP_INTR = 0x10
+ NLM_F_ECHO = 0x8
+ NLM_F_EXCL = 0x200
+ NLM_F_MATCH = 0x200
+ NLM_F_MULTI = 0x2
+ NLM_F_REPLACE = 0x100
+ NLM_F_REQUEST = 0x1
+ NLM_F_ROOT = 0x100
+ NOFLSH = 0x80
+ OCRNL = 0x8
+ OFDEL = 0x80
+ OFILL = 0x40
+ ONLCR = 0x4
+ ONLRET = 0x20
+ ONOCR = 0x10
+ OPOST = 0x1
+ O_ACCMODE = 0x3
+ O_APPEND = 0x8
+ O_ASYNC = 0x1000
+ O_CLOEXEC = 0x80000
+ O_CREAT = 0x100
+ O_DIRECT = 0x8000
+ O_DIRECTORY = 0x10000
+ O_DSYNC = 0x10
+ O_EXCL = 0x400
+ O_FSYNC = 0x4010
+ O_LARGEFILE = 0x0
+ O_NDELAY = 0x80
+ O_NOATIME = 0x40000
+ O_NOCTTY = 0x800
+ O_NOFOLLOW = 0x20000
+ O_NONBLOCK = 0x80
+ O_PATH = 0x200000
+ O_RDONLY = 0x0
+ O_RDWR = 0x2
+ O_RSYNC = 0x4010
+ O_SYNC = 0x4010
+ O_TRUNC = 0x200
+ O_WRONLY = 0x1
+ PACKET_ADD_MEMBERSHIP = 0x1
+ PACKET_AUXDATA = 0x8
+ PACKET_BROADCAST = 0x1
+ PACKET_COPY_THRESH = 0x7
+ PACKET_DROP_MEMBERSHIP = 0x2
+ PACKET_FANOUT = 0x12
+ PACKET_FANOUT_CPU = 0x2
+ PACKET_FANOUT_FLAG_DEFRAG = 0x8000
+ PACKET_FANOUT_FLAG_ROLLOVER = 0x1000
+ PACKET_FANOUT_HASH = 0x0
+ PACKET_FANOUT_LB = 0x1
+ PACKET_FANOUT_RND = 0x4
+ PACKET_FANOUT_ROLLOVER = 0x3
+ PACKET_FASTROUTE = 0x6
+ PACKET_HDRLEN = 0xb
+ PACKET_HOST = 0x0
+ PACKET_LOOPBACK = 0x5
+ PACKET_LOSS = 0xe
+ PACKET_MR_ALLMULTI = 0x2
+ PACKET_MR_MULTICAST = 0x0
+ PACKET_MR_PROMISC = 0x1
+ PACKET_MR_UNICAST = 0x3
+ PACKET_MULTICAST = 0x2
+ PACKET_ORIGDEV = 0x9
+ PACKET_OTHERHOST = 0x3
+ PACKET_OUTGOING = 0x4
+ PACKET_RECV_OUTPUT = 0x3
+ PACKET_RESERVE = 0xc
+ PACKET_RX_RING = 0x5
+ PACKET_STATISTICS = 0x6
+ PACKET_TIMESTAMP = 0x11
+ PACKET_TX_HAS_OFF = 0x13
+ PACKET_TX_RING = 0xd
+ PACKET_TX_TIMESTAMP = 0x10
+ PACKET_VERSION = 0xa
+ PACKET_VNET_HDR = 0xf
+ PARENB = 0x100
+ PARITY_CRC16_PR0 = 0x2
+ PARITY_CRC16_PR0_CCITT = 0x4
+ PARITY_CRC16_PR1 = 0x3
+ PARITY_CRC16_PR1_CCITT = 0x5
+ PARITY_CRC32_PR0_CCITT = 0x6
+ PARITY_CRC32_PR1_CCITT = 0x7
+ PARITY_DEFAULT = 0x0
+ PARITY_NONE = 0x1
+ PARMRK = 0x8
+ PARODD = 0x200
+ PENDIN = 0x4000
+ PRIO_PGRP = 0x1
+ PRIO_PROCESS = 0x0
+ PRIO_USER = 0x2
+ PROT_EXEC = 0x4
+ PROT_GROWSDOWN = 0x1000000
+ PROT_GROWSUP = 0x2000000
+ PROT_NONE = 0x0
+ PROT_READ = 0x1
+ PROT_WRITE = 0x2
+ PR_CAPBSET_DROP = 0x18
+ PR_CAPBSET_READ = 0x17
+ PR_ENDIAN_BIG = 0x0
+ PR_ENDIAN_LITTLE = 0x1
+ PR_ENDIAN_PPC_LITTLE = 0x2
+ PR_FPEMU_NOPRINT = 0x1
+ PR_FPEMU_SIGFPE = 0x2
+ PR_FP_EXC_ASYNC = 0x2
+ PR_FP_EXC_DISABLED = 0x0
+ PR_FP_EXC_DIV = 0x10000
+ PR_FP_EXC_INV = 0x100000
+ PR_FP_EXC_NONRECOV = 0x1
+ PR_FP_EXC_OVF = 0x20000
+ PR_FP_EXC_PRECISE = 0x3
+ PR_FP_EXC_RES = 0x80000
+ PR_FP_EXC_SW_ENABLE = 0x80
+ PR_FP_EXC_UND = 0x40000
+ PR_GET_CHILD_SUBREAPER = 0x25
+ PR_GET_DUMPABLE = 0x3
+ PR_GET_ENDIAN = 0x13
+ PR_GET_FPEMU = 0x9
+ PR_GET_FPEXC = 0xb
+ PR_GET_KEEPCAPS = 0x7
+ PR_GET_NAME = 0x10
+ PR_GET_NO_NEW_PRIVS = 0x27
+ PR_GET_PDEATHSIG = 0x2
+ PR_GET_SECCOMP = 0x15
+ PR_GET_SECUREBITS = 0x1b
+ PR_GET_TID_ADDRESS = 0x28
+ PR_GET_TIMERSLACK = 0x1e
+ PR_GET_TIMING = 0xd
+ PR_GET_TSC = 0x19
+ PR_GET_UNALIGN = 0x5
+ PR_MCE_KILL = 0x21
+ PR_MCE_KILL_CLEAR = 0x0
+ PR_MCE_KILL_DEFAULT = 0x2
+ PR_MCE_KILL_EARLY = 0x1
+ PR_MCE_KILL_GET = 0x22
+ PR_MCE_KILL_LATE = 0x0
+ PR_MCE_KILL_SET = 0x1
+ PR_SET_CHILD_SUBREAPER = 0x24
+ PR_SET_DUMPABLE = 0x4
+ PR_SET_ENDIAN = 0x14
+ PR_SET_FPEMU = 0xa
+ PR_SET_FPEXC = 0xc
+ PR_SET_KEEPCAPS = 0x8
+ PR_SET_MM = 0x23
+ PR_SET_MM_ARG_END = 0x9
+ PR_SET_MM_ARG_START = 0x8
+ PR_SET_MM_AUXV = 0xc
+ PR_SET_MM_BRK = 0x7
+ PR_SET_MM_END_CODE = 0x2
+ PR_SET_MM_END_DATA = 0x4
+ PR_SET_MM_ENV_END = 0xb
+ PR_SET_MM_ENV_START = 0xa
+ PR_SET_MM_EXE_FILE = 0xd
+ PR_SET_MM_START_BRK = 0x6
+ PR_SET_MM_START_CODE = 0x1
+ PR_SET_MM_START_DATA = 0x3
+ PR_SET_MM_START_STACK = 0x5
+ PR_SET_NAME = 0xf
+ PR_SET_NO_NEW_PRIVS = 0x26
+ PR_SET_PDEATHSIG = 0x1
+ PR_SET_PTRACER = 0x59616d61
+ PR_SET_PTRACER_ANY = -0x1
+ PR_SET_SECCOMP = 0x16
+ PR_SET_SECUREBITS = 0x1c
+ PR_SET_TIMERSLACK = 0x1d
+ PR_SET_TIMING = 0xe
+ PR_SET_TSC = 0x1a
+ PR_SET_UNALIGN = 0x6
+ PR_TASK_PERF_EVENTS_DISABLE = 0x1f
+ PR_TASK_PERF_EVENTS_ENABLE = 0x20
+ PR_TIMING_STATISTICAL = 0x0
+ PR_TIMING_TIMESTAMP = 0x1
+ PR_TSC_ENABLE = 0x1
+ PR_TSC_SIGSEGV = 0x2
+ PR_UNALIGN_NOPRINT = 0x1
+ PR_UNALIGN_SIGBUS = 0x2
+ PTRACE_ATTACH = 0x10
+ PTRACE_CONT = 0x7
+ PTRACE_DETACH = 0x11
+ PTRACE_EVENT_CLONE = 0x3
+ PTRACE_EVENT_EXEC = 0x4
+ PTRACE_EVENT_EXIT = 0x6
+ PTRACE_EVENT_FORK = 0x1
+ PTRACE_EVENT_SECCOMP = 0x7
+ PTRACE_EVENT_STOP = 0x80
+ PTRACE_EVENT_VFORK = 0x2
+ PTRACE_EVENT_VFORK_DONE = 0x5
+ PTRACE_GETEVENTMSG = 0x4201
+ PTRACE_GETFPREGS = 0xe
+ PTRACE_GETREGS = 0xc
+ PTRACE_GETREGSET = 0x4204
+ PTRACE_GETSIGINFO = 0x4202
+ PTRACE_GETSIGMASK = 0x420a
+ PTRACE_GET_THREAD_AREA = 0x19
+ PTRACE_GET_THREAD_AREA_3264 = 0xc4
+ PTRACE_GET_WATCH_REGS = 0xd0
+ PTRACE_INTERRUPT = 0x4207
+ PTRACE_KILL = 0x8
+ PTRACE_LISTEN = 0x4208
+ PTRACE_OLDSETOPTIONS = 0x15
+ PTRACE_O_EXITKILL = 0x100000
+ PTRACE_O_MASK = 0x1000ff
+ PTRACE_O_TRACECLONE = 0x8
+ PTRACE_O_TRACEEXEC = 0x10
+ PTRACE_O_TRACEEXIT = 0x40
+ PTRACE_O_TRACEFORK = 0x2
+ PTRACE_O_TRACESECCOMP = 0x80
+ PTRACE_O_TRACESYSGOOD = 0x1
+ PTRACE_O_TRACEVFORK = 0x4
+ PTRACE_O_TRACEVFORKDONE = 0x20
+ PTRACE_PEEKDATA = 0x2
+ PTRACE_PEEKDATA_3264 = 0xc1
+ PTRACE_PEEKSIGINFO = 0x4209
+ PTRACE_PEEKSIGINFO_SHARED = 0x1
+ PTRACE_PEEKTEXT = 0x1
+ PTRACE_PEEKTEXT_3264 = 0xc0
+ PTRACE_PEEKUSR = 0x3
+ PTRACE_POKEDATA = 0x5
+ PTRACE_POKEDATA_3264 = 0xc3
+ PTRACE_POKETEXT = 0x4
+ PTRACE_POKETEXT_3264 = 0xc2
+ PTRACE_POKEUSR = 0x6
+ PTRACE_SEIZE = 0x4206
+ PTRACE_SETFPREGS = 0xf
+ PTRACE_SETOPTIONS = 0x4200
+ PTRACE_SETREGS = 0xd
+ PTRACE_SETREGSET = 0x4205
+ PTRACE_SETSIGINFO = 0x4203
+ PTRACE_SETSIGMASK = 0x420b
+ PTRACE_SET_THREAD_AREA = 0x1a
+ PTRACE_SET_WATCH_REGS = 0xd1
+ PTRACE_SINGLESTEP = 0x9
+ PTRACE_SYSCALL = 0x18
+ PTRACE_TRACEME = 0x0
+ RLIMIT_AS = 0x6
+ RLIMIT_CORE = 0x4
+ RLIMIT_CPU = 0x0
+ RLIMIT_DATA = 0x2
+ RLIMIT_FSIZE = 0x1
+ RLIMIT_NOFILE = 0x5
+ RLIMIT_STACK = 0x3
+ RLIM_INFINITY = -0x1
+ RTAX_ADVMSS = 0x8
+ RTAX_CWND = 0x7
+ RTAX_FEATURES = 0xc
+ RTAX_FEATURE_ALLFRAG = 0x8
+ RTAX_FEATURE_ECN = 0x1
+ RTAX_FEATURE_SACK = 0x2
+ RTAX_FEATURE_TIMESTAMP = 0x4
+ RTAX_HOPLIMIT = 0xa
+ RTAX_INITCWND = 0xb
+ RTAX_INITRWND = 0xe
+ RTAX_LOCK = 0x1
+ RTAX_MAX = 0xf
+ RTAX_MTU = 0x2
+ RTAX_QUICKACK = 0xf
+ RTAX_REORDERING = 0x9
+ RTAX_RTO_MIN = 0xd
+ RTAX_RTT = 0x4
+ RTAX_RTTVAR = 0x5
+ RTAX_SSTHRESH = 0x6
+ RTAX_UNSPEC = 0x0
+ RTAX_WINDOW = 0x3
+ RTA_ALIGNTO = 0x4
+ RTA_MAX = 0x11
+ RTCF_DIRECTSRC = 0x4000000
+ RTCF_DOREDIRECT = 0x1000000
+ RTCF_LOG = 0x2000000
+ RTCF_MASQ = 0x400000
+ RTCF_NAT = 0x800000
+ RTCF_VALVE = 0x200000
+ RTF_ADDRCLASSMASK = 0xf8000000
+ RTF_ADDRCONF = 0x40000
+ RTF_ALLONLINK = 0x20000
+ RTF_BROADCAST = 0x10000000
+ RTF_CACHE = 0x1000000
+ RTF_DEFAULT = 0x10000
+ RTF_DYNAMIC = 0x10
+ RTF_FLOW = 0x2000000
+ RTF_GATEWAY = 0x2
+ RTF_HOST = 0x4
+ RTF_INTERFACE = 0x40000000
+ RTF_IRTT = 0x100
+ RTF_LINKRT = 0x100000
+ RTF_LOCAL = 0x80000000
+ RTF_MODIFIED = 0x20
+ RTF_MSS = 0x40
+ RTF_MTU = 0x40
+ RTF_MULTICAST = 0x20000000
+ RTF_NAT = 0x8000000
+ RTF_NOFORWARD = 0x1000
+ RTF_NONEXTHOP = 0x200000
+ RTF_NOPMTUDISC = 0x4000
+ RTF_POLICY = 0x4000000
+ RTF_REINSTATE = 0x8
+ RTF_REJECT = 0x200
+ RTF_STATIC = 0x400
+ RTF_THROW = 0x2000
+ RTF_UP = 0x1
+ RTF_WINDOW = 0x80
+ RTF_XRESOLVE = 0x800
+ RTM_BASE = 0x10
+ RTM_DELACTION = 0x31
+ RTM_DELADDR = 0x15
+ RTM_DELADDRLABEL = 0x49
+ RTM_DELLINK = 0x11
+ RTM_DELMDB = 0x55
+ RTM_DELNEIGH = 0x1d
+ RTM_DELQDISC = 0x25
+ RTM_DELROUTE = 0x19
+ RTM_DELRULE = 0x21
+ RTM_DELTCLASS = 0x29
+ RTM_DELTFILTER = 0x2d
+ RTM_F_CLONED = 0x200
+ RTM_F_EQUALIZE = 0x400
+ RTM_F_NOTIFY = 0x100
+ RTM_F_PREFIX = 0x800
+ RTM_GETACTION = 0x32
+ RTM_GETADDR = 0x16
+ RTM_GETADDRLABEL = 0x4a
+ RTM_GETANYCAST = 0x3e
+ RTM_GETDCB = 0x4e
+ RTM_GETLINK = 0x12
+ RTM_GETMDB = 0x56
+ RTM_GETMULTICAST = 0x3a
+ RTM_GETNEIGH = 0x1e
+ RTM_GETNEIGHTBL = 0x42
+ RTM_GETNETCONF = 0x52
+ RTM_GETQDISC = 0x26
+ RTM_GETROUTE = 0x1a
+ RTM_GETRULE = 0x22
+ RTM_GETTCLASS = 0x2a
+ RTM_GETTFILTER = 0x2e
+ RTM_MAX = 0x57
+ RTM_NEWACTION = 0x30
+ RTM_NEWADDR = 0x14
+ RTM_NEWADDRLABEL = 0x48
+ RTM_NEWLINK = 0x10
+ RTM_NEWMDB = 0x54
+ RTM_NEWNDUSEROPT = 0x44
+ RTM_NEWNEIGH = 0x1c
+ RTM_NEWNEIGHTBL = 0x40
+ RTM_NEWNETCONF = 0x50
+ RTM_NEWPREFIX = 0x34
+ RTM_NEWQDISC = 0x24
+ RTM_NEWROUTE = 0x18
+ RTM_NEWRULE = 0x20
+ RTM_NEWTCLASS = 0x28
+ RTM_NEWTFILTER = 0x2c
+ RTM_NR_FAMILIES = 0x12
+ RTM_NR_MSGTYPES = 0x48
+ RTM_SETDCB = 0x4f
+ RTM_SETLINK = 0x13
+ RTM_SETNEIGHTBL = 0x43
+ RTNH_ALIGNTO = 0x4
+ RTNH_F_DEAD = 0x1
+ RTNH_F_ONLINK = 0x4
+ RTNH_F_PERVASIVE = 0x2
+ RTN_MAX = 0xb
+ RTPROT_BIRD = 0xc
+ RTPROT_BOOT = 0x3
+ RTPROT_DHCP = 0x10
+ RTPROT_DNROUTED = 0xd
+ RTPROT_GATED = 0x8
+ RTPROT_KERNEL = 0x2
+ RTPROT_MROUTED = 0x11
+ RTPROT_MRT = 0xa
+ RTPROT_NTK = 0xf
+ RTPROT_RA = 0x9
+ RTPROT_REDIRECT = 0x1
+ RTPROT_STATIC = 0x4
+ RTPROT_UNSPEC = 0x0
+ RTPROT_XORP = 0xe
+ RTPROT_ZEBRA = 0xb
+ RT_CLASS_DEFAULT = 0xfd
+ RT_CLASS_LOCAL = 0xff
+ RT_CLASS_MAIN = 0xfe
+ RT_CLASS_MAX = 0xff
+ RT_CLASS_UNSPEC = 0x0
+ RUSAGE_CHILDREN = -0x1
+ RUSAGE_SELF = 0x0
+ RUSAGE_THREAD = 0x1
+ SCM_CREDENTIALS = 0x2
+ SCM_RIGHTS = 0x1
+ SCM_TIMESTAMP = 0x1d
+ SCM_TIMESTAMPING = 0x25
+ SCM_TIMESTAMPNS = 0x23
+ SCM_WIFI_STATUS = 0x29
+ SHUT_RD = 0x0
+ SHUT_RDWR = 0x2
+ SHUT_WR = 0x1
+ SIOCADDDLCI = 0x8980
+ SIOCADDMULTI = 0x8931
+ SIOCADDRT = 0x890b
+ SIOCATMARK = 0x40047307
+ SIOCDARP = 0x8953
+ SIOCDELDLCI = 0x8981
+ SIOCDELMULTI = 0x8932
+ SIOCDELRT = 0x890c
+ SIOCDEVPRIVATE = 0x89f0
+ SIOCDIFADDR = 0x8936
+ SIOCDRARP = 0x8960
+ SIOCGARP = 0x8954
+ SIOCGIFADDR = 0x8915
+ SIOCGIFBR = 0x8940
+ SIOCGIFBRDADDR = 0x8919
+ SIOCGIFCONF = 0x8912
+ SIOCGIFCOUNT = 0x8938
+ SIOCGIFDSTADDR = 0x8917
+ SIOCGIFENCAP = 0x8925
+ SIOCGIFFLAGS = 0x8913
+ SIOCGIFHWADDR = 0x8927
+ SIOCGIFINDEX = 0x8933
+ SIOCGIFMAP = 0x8970
+ SIOCGIFMEM = 0x891f
+ SIOCGIFMETRIC = 0x891d
+ SIOCGIFMTU = 0x8921
+ SIOCGIFNAME = 0x8910
+ SIOCGIFNETMASK = 0x891b
+ SIOCGIFPFLAGS = 0x8935
+ SIOCGIFSLAVE = 0x8929
+ SIOCGIFTXQLEN = 0x8942
+ SIOCGPGRP = 0x40047309
+ SIOCGRARP = 0x8961
+ SIOCGSTAMP = 0x8906
+ SIOCGSTAMPNS = 0x8907
+ SIOCPROTOPRIVATE = 0x89e0
+ SIOCRTMSG = 0x890d
+ SIOCSARP = 0x8955
+ SIOCSIFADDR = 0x8916
+ SIOCSIFBR = 0x8941
+ SIOCSIFBRDADDR = 0x891a
+ SIOCSIFDSTADDR = 0x8918
+ SIOCSIFENCAP = 0x8926
+ SIOCSIFFLAGS = 0x8914
+ SIOCSIFHWADDR = 0x8924
+ SIOCSIFHWBROADCAST = 0x8937
+ SIOCSIFLINK = 0x8911
+ SIOCSIFMAP = 0x8971
+ SIOCSIFMEM = 0x8920
+ SIOCSIFMETRIC = 0x891e
+ SIOCSIFMTU = 0x8922
+ SIOCSIFNAME = 0x8923
+ SIOCSIFNETMASK = 0x891c
+ SIOCSIFPFLAGS = 0x8934
+ SIOCSIFSLAVE = 0x8930
+ SIOCSIFTXQLEN = 0x8943
+ SIOCSPGRP = 0x80047308
+ SIOCSRARP = 0x8962
+ SOCK_CLOEXEC = 0x80000
+ SOCK_DCCP = 0x6
+ SOCK_DGRAM = 0x1
+ SOCK_NONBLOCK = 0x80
+ SOCK_PACKET = 0xa
+ SOCK_RAW = 0x3
+ SOCK_RDM = 0x4
+ SOCK_SEQPACKET = 0x5
+ SOCK_STREAM = 0x2
+ SOL_AAL = 0x109
+ SOL_ATM = 0x108
+ SOL_DECNET = 0x105
+ SOL_ICMPV6 = 0x3a
+ SOL_IP = 0x0
+ SOL_IPV6 = 0x29
+ SOL_IRDA = 0x10a
+ SOL_PACKET = 0x107
+ SOL_RAW = 0xff
+ SOL_SOCKET = 0xffff
+ SOL_TCP = 0x6
+ SOL_X25 = 0x106
+ SOMAXCONN = 0x80
+ SO_ACCEPTCONN = 0x1009
+ SO_ATTACH_FILTER = 0x1a
+ SO_BINDTODEVICE = 0x19
+ SO_BROADCAST = 0x20
+ SO_BSDCOMPAT = 0xe
+ SO_BUSY_POLL = 0x2e
+ SO_DEBUG = 0x1
+ SO_DETACH_FILTER = 0x1b
+ SO_DOMAIN = 0x1029
+ SO_DONTROUTE = 0x10
+ SO_ERROR = 0x1007
+ SO_GET_FILTER = 0x1a
+ SO_KEEPALIVE = 0x8
+ SO_LINGER = 0x80
+ SO_LOCK_FILTER = 0x2c
+ SO_MARK = 0x24
+ SO_NOFCS = 0x2b
+ SO_NO_CHECK = 0xb
+ SO_OOBINLINE = 0x100
+ SO_PASSCRED = 0x11
+ SO_PASSSEC = 0x22
+ SO_PEEK_OFF = 0x2a
+ SO_PEERCRED = 0x12
+ SO_PEERNAME = 0x1c
+ SO_PEERSEC = 0x1e
+ SO_PRIORITY = 0xc
+ SO_PROTOCOL = 0x1028
+ SO_RCVBUF = 0x1002
+ SO_RCVBUFFORCE = 0x21
+ SO_RCVLOWAT = 0x1004
+ SO_RCVTIMEO = 0x1006
+ SO_REUSEADDR = 0x4
+ SO_REUSEPORT = 0x200
+ SO_RXQ_OVFL = 0x28
+ SO_SECURITY_AUTHENTICATION = 0x16
+ SO_SECURITY_ENCRYPTION_NETWORK = 0x18
+ SO_SECURITY_ENCRYPTION_TRANSPORT = 0x17
+ SO_SELECT_ERR_QUEUE = 0x2d
+ SO_SNDBUF = 0x1001
+ SO_SNDBUFFORCE = 0x1f
+ SO_SNDLOWAT = 0x1003
+ SO_SNDTIMEO = 0x1005
+ SO_STYLE = 0x1008
+ SO_TIMESTAMP = 0x1d
+ SO_TIMESTAMPING = 0x25
+ SO_TIMESTAMPNS = 0x23
+ SO_TYPE = 0x1008
+ SO_WIFI_STATUS = 0x29
+ S_BLKSIZE = 0x200
+ S_IEXEC = 0x40
+ S_IFBLK = 0x6000
+ S_IFCHR = 0x2000
+ S_IFDIR = 0x4000
+ S_IFIFO = 0x1000
+ S_IFLNK = 0xa000
+ S_IFMT = 0xf000
+ S_IFREG = 0x8000
+ S_IFSOCK = 0xc000
+ S_IREAD = 0x100
+ S_IRGRP = 0x20
+ S_IROTH = 0x4
+ S_IRUSR = 0x100
+ S_IRWXG = 0x38
+ S_IRWXO = 0x7
+ S_IRWXU = 0x1c0
+ S_ISGID = 0x400
+ S_ISUID = 0x800
+ S_ISVTX = 0x200
+ S_IWGRP = 0x10
+ S_IWOTH = 0x2
+ S_IWRITE = 0x80
+ S_IWUSR = 0x80
+ S_IXGRP = 0x8
+ S_IXOTH = 0x1
+ S_IXUSR = 0x40
+ TCFLSH = 0x5407
+ TCIFLUSH = 0x0
+ TCIOFLUSH = 0x2
+ TCOFLUSH = 0x1
+ TCP_CONGESTION = 0xd
+ TCP_CORK = 0x3
+ TCP_DEFER_ACCEPT = 0x9
+ TCP_INFO = 0xb
+ TCP_KEEPCNT = 0x6
+ TCP_KEEPIDLE = 0x4
+ TCP_KEEPINTVL = 0x5
+ TCP_LINGER2 = 0x8
+ TCP_MAXSEG = 0x2
+ TCP_MAXWIN = 0xffff
+ TCP_MAX_WINSHIFT = 0xe
+ TCP_MD5SIG = 0xe
+ TCP_MD5SIG_MAXKEYLEN = 0x50
+ TCP_MSS = 0x200
+ TCP_NODELAY = 0x1
+ TCP_QUICKACK = 0xc
+ TCP_SYNCNT = 0x7
+ TCP_WINDOW_CLAMP = 0xa
+ TCSAFLUSH = 0x5410
+ TIOCCBRK = 0x5428
+ TIOCCONS = 0x80047478
+ TIOCEXCL = 0x740d
+ TIOCGDEV = 0x40045432
+ TIOCGETD = 0x7400
+ TIOCGETP = 0x7408
+ TIOCGEXCL = 0x40045440
+ TIOCGICOUNT = 0x5492
+ TIOCGLCKTRMIOS = 0x548b
+ TIOCGLTC = 0x7474
+ TIOCGPGRP = 0x40047477
+ TIOCGPKT = 0x40045438
+ TIOCGPTLCK = 0x40045439
+ TIOCGPTN = 0x40045430
+ TIOCGSERIAL = 0x5484
+ TIOCGSID = 0x7416
+ TIOCGSOFTCAR = 0x5481
+ TIOCGWINSZ = 0x40087468
+ TIOCINQ = 0x467f
+ TIOCLINUX = 0x5483
+ TIOCMBIC = 0x741c
+ TIOCMBIS = 0x741b
+ TIOCMGET = 0x741d
+ TIOCMIWAIT = 0x5491
+ TIOCMSET = 0x741a
+ TIOCM_CAR = 0x100
+ TIOCM_CD = 0x100
+ TIOCM_CTS = 0x40
+ TIOCM_DSR = 0x400
+ TIOCM_DTR = 0x2
+ TIOCM_LE = 0x1
+ TIOCM_RI = 0x200
+ TIOCM_RNG = 0x200
+ TIOCM_RTS = 0x4
+ TIOCM_SR = 0x20
+ TIOCM_ST = 0x10
+ TIOCNOTTY = 0x5471
+ TIOCNXCL = 0x740e
+ TIOCOUTQ = 0x7472
+ TIOCPKT = 0x5470
+ TIOCPKT_DATA = 0x0
+ TIOCPKT_DOSTOP = 0x20
+ TIOCPKT_FLUSHREAD = 0x1
+ TIOCPKT_FLUSHWRITE = 0x2
+ TIOCPKT_IOCTL = 0x40
+ TIOCPKT_NOSTOP = 0x10
+ TIOCPKT_START = 0x8
+ TIOCPKT_STOP = 0x4
+ TIOCSBRK = 0x5427
+ TIOCSCTTY = 0x5480
+ TIOCSERCONFIG = 0x5488
+ TIOCSERGETLSR = 0x548e
+ TIOCSERGETMULTI = 0x548f
+ TIOCSERGSTRUCT = 0x548d
+ TIOCSERGWILD = 0x5489
+ TIOCSERSETMULTI = 0x5490
+ TIOCSERSWILD = 0x548a
+ TIOCSER_TEMT = 0x1
+ TIOCSETD = 0x7401
+ TIOCSETN = 0x740a
+ TIOCSETP = 0x7409
+ TIOCSIG = 0x80045436
+ TIOCSLCKTRMIOS = 0x548c
+ TIOCSLTC = 0x7475
+ TIOCSPGRP = 0x80047476
+ TIOCSPTLCK = 0x80045431
+ TIOCSSERIAL = 0x5485
+ TIOCSSOFTCAR = 0x5482
+ TIOCSTI = 0x5472
+ TIOCSWINSZ = 0x80087467
+ TIOCVHANGUP = 0x5437
+ TOSTOP = 0x8000
+ TUNATTACHFILTER = 0x801054d5
+ TUNDETACHFILTER = 0x801054d6
+ TUNGETFEATURES = 0x400454cf
+ TUNGETFILTER = 0x401054db
+ TUNGETIFF = 0x400454d2
+ TUNGETSNDBUF = 0x400454d3
+ TUNGETVNETHDRSZ = 0x400454d7
+ TUNSETDEBUG = 0x800454c9
+ TUNSETGROUP = 0x800454ce
+ TUNSETIFF = 0x800454ca
+ TUNSETIFINDEX = 0x800454da
+ TUNSETLINK = 0x800454cd
+ TUNSETNOCSUM = 0x800454c8
+ TUNSETOFFLOAD = 0x800454d0
+ TUNSETOWNER = 0x800454cc
+ TUNSETPERSIST = 0x800454cb
+ TUNSETQUEUE = 0x800454d9
+ TUNSETSNDBUF = 0x800454d4
+ TUNSETTXFILTER = 0x800454d1
+ TUNSETVNETHDRSZ = 0x800454d8
+ VDISCARD = 0xd
+ VEOF = 0x10
+ VEOL = 0x11
+ VEOL2 = 0x6
+ VERASE = 0x2
+ VINTR = 0x0
+ VKILL = 0x3
+ VLNEXT = 0xf
+ VMIN = 0x4
+ VQUIT = 0x1
+ VREPRINT = 0xc
+ VSTART = 0x8
+ VSTOP = 0x9
+ VSUSP = 0xa
+ VSWTC = 0x7
+ VSWTCH = 0x7
+ VT0 = 0x0
+ VT1 = 0x4000
+ VTDLY = 0x4000
+ VTIME = 0x5
+ VWERASE = 0xe
+ WALL = 0x40000000
+ WCLONE = 0x80000000
+ WCONTINUED = 0x8
+ WEXITED = 0x4
+ WNOHANG = 0x1
+ WNOTHREAD = 0x20000000
+ WNOWAIT = 0x1000000
+ WORDSIZE = 0x40
+ WSTOPPED = 0x2
+ WUNTRACED = 0x2
+)
+
+// Errors
+const (
+ E2BIG = Errno(0x7)
+ EACCES = Errno(0xd)
+ EADDRINUSE = Errno(0x7d)
+ EADDRNOTAVAIL = Errno(0x7e)
+ EADV = Errno(0x44)
+ EAFNOSUPPORT = Errno(0x7c)
+ EAGAIN = Errno(0xb)
+ EALREADY = Errno(0x95)
+ EBADE = Errno(0x32)
+ EBADF = Errno(0x9)
+ EBADFD = Errno(0x51)
+ EBADMSG = Errno(0x4d)
+ EBADR = Errno(0x33)
+ EBADRQC = Errno(0x36)
+ EBADSLT = Errno(0x37)
+ EBFONT = Errno(0x3b)
+ EBUSY = Errno(0x10)
+ ECANCELED = Errno(0x9e)
+ ECHILD = Errno(0xa)
+ ECHRNG = Errno(0x25)
+ ECOMM = Errno(0x46)
+ ECONNABORTED = Errno(0x82)
+ ECONNREFUSED = Errno(0x92)
+ ECONNRESET = Errno(0x83)
+ EDEADLK = Errno(0x2d)
+ EDEADLOCK = Errno(0x38)
+ EDESTADDRREQ = Errno(0x60)
+ EDOM = Errno(0x21)
+ EDOTDOT = Errno(0x49)
+ EDQUOT = Errno(0x46d)
+ EEXIST = Errno(0x11)
+ EFAULT = Errno(0xe)
+ EFBIG = Errno(0x1b)
+ EHOSTDOWN = Errno(0x93)
+ EHOSTUNREACH = Errno(0x94)
+ EHWPOISON = Errno(0xa8)
+ EIDRM = Errno(0x24)
+ EILSEQ = Errno(0x58)
+ EINIT = Errno(0x8d)
+ EINPROGRESS = Errno(0x96)
+ EINTR = Errno(0x4)
+ EINVAL = Errno(0x16)
+ EIO = Errno(0x5)
+ EISCONN = Errno(0x85)
+ EISDIR = Errno(0x15)
+ EISNAM = Errno(0x8b)
+ EKEYEXPIRED = Errno(0xa2)
+ EKEYREJECTED = Errno(0xa4)
+ EKEYREVOKED = Errno(0xa3)
+ EL2HLT = Errno(0x2c)
+ EL2NSYNC = Errno(0x26)
+ EL3HLT = Errno(0x27)
+ EL3RST = Errno(0x28)
+ ELIBACC = Errno(0x53)
+ ELIBBAD = Errno(0x54)
+ ELIBEXEC = Errno(0x57)
+ ELIBMAX = Errno(0x56)
+ ELIBSCN = Errno(0x55)
+ ELNRNG = Errno(0x29)
+ ELOOP = Errno(0x5a)
+ EMEDIUMTYPE = Errno(0xa0)
+ EMFILE = Errno(0x18)
+ EMLINK = Errno(0x1f)
+ EMSGSIZE = Errno(0x61)
+ EMULTIHOP = Errno(0x4a)
+ ENAMETOOLONG = Errno(0x4e)
+ ENAVAIL = Errno(0x8a)
+ ENETDOWN = Errno(0x7f)
+ ENETRESET = Errno(0x81)
+ ENETUNREACH = Errno(0x80)
+ ENFILE = Errno(0x17)
+ ENOANO = Errno(0x35)
+ ENOBUFS = Errno(0x84)
+ ENOCSI = Errno(0x2b)
+ ENODATA = Errno(0x3d)
+ ENODEV = Errno(0x13)
+ ENOENT = Errno(0x2)
+ ENOEXEC = Errno(0x8)
+ ENOKEY = Errno(0xa1)
+ ENOLCK = Errno(0x2e)
+ ENOLINK = Errno(0x43)
+ ENOMEDIUM = Errno(0x9f)
+ ENOMEM = Errno(0xc)
+ ENOMSG = Errno(0x23)
+ ENONET = Errno(0x40)
+ ENOPKG = Errno(0x41)
+ ENOPROTOOPT = Errno(0x63)
+ ENOSPC = Errno(0x1c)
+ ENOSR = Errno(0x3f)
+ ENOSTR = Errno(0x3c)
+ ENOSYS = Errno(0x59)
+ ENOTBLK = Errno(0xf)
+ ENOTCONN = Errno(0x86)
+ ENOTDIR = Errno(0x14)
+ ENOTEMPTY = Errno(0x5d)
+ ENOTNAM = Errno(0x89)
+ ENOTRECOVERABLE = Errno(0xa6)
+ ENOTSOCK = Errno(0x5f)
+ ENOTSUP = Errno(0x7a)
+ ENOTTY = Errno(0x19)
+ ENOTUNIQ = Errno(0x50)
+ ENXIO = Errno(0x6)
+ EOPNOTSUPP = Errno(0x7a)
+ EOVERFLOW = Errno(0x4f)
+ EOWNERDEAD = Errno(0xa5)
+ EPERM = Errno(0x1)
+ EPFNOSUPPORT = Errno(0x7b)
+ EPIPE = Errno(0x20)
+ EPROTO = Errno(0x47)
+ EPROTONOSUPPORT = Errno(0x78)
+ EPROTOTYPE = Errno(0x62)
+ ERANGE = Errno(0x22)
+ EREMCHG = Errno(0x52)
+ EREMDEV = Errno(0x8e)
+ EREMOTE = Errno(0x42)
+ EREMOTEIO = Errno(0x8c)
+ ERESTART = Errno(0x5b)
+ ERFKILL = Errno(0xa7)
+ EROFS = Errno(0x1e)
+ ESHUTDOWN = Errno(0x8f)
+ ESOCKTNOSUPPORT = Errno(0x79)
+ ESPIPE = Errno(0x1d)
+ ESRCH = Errno(0x3)
+ ESRMNT = Errno(0x45)
+ ESTALE = Errno(0x97)
+ ESTRPIPE = Errno(0x5c)
+ ETIME = Errno(0x3e)
+ ETIMEDOUT = Errno(0x91)
+ ETOOMANYREFS = Errno(0x90)
+ ETXTBSY = Errno(0x1a)
+ EUCLEAN = Errno(0x87)
+ EUNATCH = Errno(0x2a)
+ EUSERS = Errno(0x5e)
+ EWOULDBLOCK = Errno(0xb)
+ EXDEV = Errno(0x12)
+ EXFULL = Errno(0x34)
+)
+
+// Signals
+const (
+ SIGABRT = Signal(0x6)
+ SIGALRM = Signal(0xe)
+ SIGBUS = Signal(0xa)
+ SIGCHLD = Signal(0x12)
+ SIGCLD = Signal(0x12)
+ SIGCONT = Signal(0x19)
+ SIGEMT = Signal(0x7)
+ SIGFPE = Signal(0x8)
+ SIGHUP = Signal(0x1)
+ SIGILL = Signal(0x4)
+ SIGINT = Signal(0x2)
+ SIGIO = Signal(0x16)
+ SIGIOT = Signal(0x6)
+ SIGKILL = Signal(0x9)
+ SIGPIPE = Signal(0xd)
+ SIGPOLL = Signal(0x16)
+ SIGPROF = Signal(0x1d)
+ SIGPWR = Signal(0x13)
+ SIGQUIT = Signal(0x3)
+ SIGSEGV = Signal(0xb)
+ SIGSTOP = Signal(0x17)
+ SIGSYS = Signal(0xc)
+ SIGTERM = Signal(0xf)
+ SIGTRAP = Signal(0x5)
+ SIGTSTP = Signal(0x18)
+ SIGTTIN = Signal(0x1a)
+ SIGTTOU = Signal(0x1b)
+ SIGURG = Signal(0x15)
+ SIGUSR1 = Signal(0x10)
+ SIGUSR2 = Signal(0x11)
+ SIGVTALRM = Signal(0x1c)
+ SIGWINCH = Signal(0x14)
+ SIGXCPU = Signal(0x1e)
+ SIGXFSZ = Signal(0x1f)
+)
+
+// Error table
+var errors = [...]string{
+ 1: "operation not permitted",
+ 2: "no such file or directory",
+ 3: "no such process",
+ 4: "interrupted system call",
+ 5: "input/output error",
+ 6: "no such device or address",
+ 7: "argument list too long",
+ 8: "exec format error",
+ 9: "bad file descriptor",
+ 10: "no child processes",
+ 11: "resource temporarily unavailable",
+ 12: "cannot allocate memory",
+ 13: "permission denied",
+ 14: "bad address",
+ 15: "block device required",
+ 16: "device or resource busy",
+ 17: "file exists",
+ 18: "invalid cross-device link",
+ 19: "no such device",
+ 20: "not a directory",
+ 21: "is a directory",
+ 22: "invalid argument",
+ 23: "too many open files in system",
+ 24: "too many open files",
+ 25: "inappropriate ioctl for device",
+ 26: "text file busy",
+ 27: "file too large",
+ 28: "no space left on device",
+ 29: "illegal seek",
+ 30: "read-only file system",
+ 31: "too many links",
+ 32: "broken pipe",
+ 33: "numerical argument out of domain",
+ 34: "numerical result out of range",
+ 35: "no message of desired type",
+ 36: "identifier removed",
+ 37: "channel number out of range",
+ 38: "level 2 not synchronized",
+ 39: "level 3 halted",
+ 40: "level 3 reset",
+ 41: "link number out of range",
+ 42: "protocol driver not attached",
+ 43: "no CSI structure available",
+ 44: "level 2 halted",
+ 45: "resource deadlock avoided",
+ 46: "no locks available",
+ 50: "invalid exchange",
+ 51: "invalid request descriptor",
+ 52: "exchange full",
+ 53: "no anode",
+ 54: "invalid request code",
+ 55: "invalid slot",
+ 56: "file locking deadlock error",
+ 59: "bad font file format",
+ 60: "device not a stream",
+ 61: "no data available",
+ 62: "timer expired",
+ 63: "out of streams resources",
+ 64: "machine is not on the network",
+ 65: "package not installed",
+ 66: "object is remote",
+ 67: "link has been severed",
+ 68: "advertise error",
+ 69: "srmount error",
+ 70: "communication error on send",
+ 71: "protocol error",
+ 73: "RFS specific error",
+ 74: "multihop attempted",
+ 77: "bad message",
+ 78: "file name too long",
+ 79: "value too large for defined data type",
+ 80: "name not unique on network",
+ 81: "file descriptor in bad state",
+ 82: "remote address changed",
+ 83: "can not access a needed shared library",
+ 84: "accessing a corrupted shared library",
+ 85: ".lib section in a.out corrupted",
+ 86: "attempting to link in too many shared libraries",
+ 87: "cannot exec a shared library directly",
+ 88: "invalid or incomplete multibyte or wide character",
+ 89: "function not implemented",
+ 90: "too many levels of symbolic links",
+ 91: "interrupted system call should be restarted",
+ 92: "streams pipe error",
+ 93: "directory not empty",
+ 94: "too many users",
+ 95: "socket operation on non-socket",
+ 96: "destination address required",
+ 97: "message too long",
+ 98: "protocol wrong type for socket",
+ 99: "protocol not available",
+ 120: "protocol not supported",
+ 121: "socket type not supported",
+ 122: "operation not supported",
+ 123: "protocol family not supported",
+ 124: "address family not supported by protocol",
+ 125: "address already in use",
+ 126: "cannot assign requested address",
+ 127: "network is down",
+ 128: "network is unreachable",
+ 129: "network dropped connection on reset",
+ 130: "software caused connection abort",
+ 131: "connection reset by peer",
+ 132: "no buffer space available",
+ 133: "transport endpoint is already connected",
+ 134: "transport endpoint is not connected",
+ 135: "structure needs cleaning",
+ 137: "not a XENIX named type file",
+ 138: "no XENIX semaphores available",
+ 139: "is a named type file",
+ 140: "remote I/O error",
+ 141: "unknown error 141",
+ 142: "unknown error 142",
+ 143: "cannot send after transport endpoint shutdown",
+ 144: "too many references: cannot splice",
+ 145: "connection timed out",
+ 146: "connection refused",
+ 147: "host is down",
+ 148: "no route to host",
+ 149: "operation already in progress",
+ 150: "operation now in progress",
+ 151: "stale NFS file handle",
+ 158: "operation canceled",
+ 159: "no medium found",
+ 160: "wrong medium type",
+ 161: "required key not available",
+ 162: "key has expired",
+ 163: "key has been revoked",
+ 164: "key was rejected by service",
+ 165: "owner died",
+ 166: "state not recoverable",
+ 167: "operation not possible due to RF-kill",
+ 168: "memory page has hardware error",
+ 1133: "disk quota exceeded",
+}
+
+// Signal table
+var signals = [...]string{
+ 1: "hangup",
+ 2: "interrupt",
+ 3: "quit",
+ 4: "illegal instruction",
+ 5: "trace/breakpoint trap",
+ 6: "aborted",
+ 7: "EMT trap",
+ 8: "floating point exception",
+ 9: "killed",
+ 10: "bus error",
+ 11: "segmentation fault",
+ 12: "bad system call",
+ 13: "broken pipe",
+ 14: "alarm clock",
+ 15: "terminated",
+ 16: "user defined signal 1",
+ 17: "user defined signal 2",
+ 18: "child exited",
+ 19: "power failure",
+ 20: "window changed",
+ 21: "urgent I/O condition",
+ 22: "I/O possible",
+ 23: "stopped (signal)",
+ 24: "stopped",
+ 25: "continued",
+ 26: "stopped (tty input)",
+ 27: "stopped (tty output)",
+ 28: "virtual timer expired",
+ 29: "profiling timer expired",
+ 30: "CPU time limit exceeded",
+ 31: "file size limit exceeded",
+}
--- /dev/null
+// mkerrors.sh
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs _const.go
+
+package syscall
+
+const (
+ AF_ALG = 0x26
+ AF_APPLETALK = 0x5
+ AF_ASH = 0x12
+ AF_ATMPVC = 0x8
+ AF_ATMSVC = 0x14
+ AF_AX25 = 0x3
+ AF_BLUETOOTH = 0x1f
+ AF_BRIDGE = 0x7
+ AF_CAIF = 0x25
+ AF_CAN = 0x1d
+ AF_DECnet = 0xc
+ AF_ECONET = 0x13
+ AF_FILE = 0x1
+ AF_IEEE802154 = 0x24
+ AF_INET = 0x2
+ AF_INET6 = 0xa
+ AF_IPX = 0x4
+ AF_IRDA = 0x17
+ AF_ISDN = 0x22
+ AF_IUCV = 0x20
+ AF_KEY = 0xf
+ AF_LLC = 0x1a
+ AF_LOCAL = 0x1
+ AF_MAX = 0x28
+ AF_NETBEUI = 0xd
+ AF_NETLINK = 0x10
+ AF_NETROM = 0x6
+ AF_NFC = 0x27
+ AF_PACKET = 0x11
+ AF_PHONET = 0x23
+ AF_PPPOX = 0x18
+ AF_RDS = 0x15
+ AF_ROSE = 0xb
+ AF_ROUTE = 0x10
+ AF_RXRPC = 0x21
+ AF_SECURITY = 0xe
+ AF_SNA = 0x16
+ AF_TIPC = 0x1e
+ AF_UNIX = 0x1
+ AF_UNSPEC = 0x0
+ AF_WANPIPE = 0x19
+ AF_X25 = 0x9
+ ARPHRD_ADAPT = 0x108
+ ARPHRD_APPLETLK = 0x8
+ ARPHRD_ARCNET = 0x7
+ ARPHRD_ASH = 0x30d
+ ARPHRD_ATM = 0x13
+ ARPHRD_AX25 = 0x3
+ ARPHRD_BIF = 0x307
+ ARPHRD_CAIF = 0x336
+ ARPHRD_CAN = 0x118
+ ARPHRD_CHAOS = 0x5
+ ARPHRD_CISCO = 0x201
+ ARPHRD_CSLIP = 0x101
+ ARPHRD_CSLIP6 = 0x103
+ ARPHRD_DDCMP = 0x205
+ ARPHRD_DLCI = 0xf
+ ARPHRD_ECONET = 0x30e
+ ARPHRD_EETHER = 0x2
+ ARPHRD_ETHER = 0x1
+ ARPHRD_EUI64 = 0x1b
+ ARPHRD_FCAL = 0x311
+ ARPHRD_FCFABRIC = 0x313
+ ARPHRD_FCPL = 0x312
+ ARPHRD_FCPP = 0x310
+ ARPHRD_FDDI = 0x306
+ ARPHRD_FRAD = 0x302
+ ARPHRD_HDLC = 0x201
+ ARPHRD_HIPPI = 0x30c
+ ARPHRD_HWX25 = 0x110
+ ARPHRD_IEEE1394 = 0x18
+ ARPHRD_IEEE802 = 0x6
+ ARPHRD_IEEE80211 = 0x321
+ ARPHRD_IEEE80211_PRISM = 0x322
+ ARPHRD_IEEE80211_RADIOTAP = 0x323
+ ARPHRD_IEEE802154 = 0x324
+ ARPHRD_IEEE802154_MONITOR = 0x325
+ ARPHRD_IEEE802_TR = 0x320
+ ARPHRD_INFINIBAND = 0x20
+ ARPHRD_IP6GRE = 0x337
+ ARPHRD_IPDDP = 0x309
+ ARPHRD_IPGRE = 0x30a
+ ARPHRD_IRDA = 0x30f
+ ARPHRD_LAPB = 0x204
+ ARPHRD_LOCALTLK = 0x305
+ ARPHRD_LOOPBACK = 0x304
+ ARPHRD_METRICOM = 0x17
+ ARPHRD_NETLINK = 0x338
+ ARPHRD_NETROM = 0x0
+ ARPHRD_NONE = 0xfffe
+ ARPHRD_PHONET = 0x334
+ ARPHRD_PHONET_PIPE = 0x335
+ ARPHRD_PIMREG = 0x30b
+ ARPHRD_PPP = 0x200
+ ARPHRD_PRONET = 0x4
+ ARPHRD_RAWHDLC = 0x206
+ ARPHRD_ROSE = 0x10e
+ ARPHRD_RSRVD = 0x104
+ ARPHRD_SIT = 0x308
+ ARPHRD_SKIP = 0x303
+ ARPHRD_SLIP = 0x100
+ ARPHRD_SLIP6 = 0x102
+ ARPHRD_TUNNEL = 0x300
+ ARPHRD_TUNNEL6 = 0x301
+ ARPHRD_VOID = 0xffff
+ ARPHRD_X25 = 0x10f
+ B0 = 0x0
+ B1000000 = 0x1008
+ B110 = 0x3
+ B115200 = 0x1002
+ B1152000 = 0x1009
+ B1200 = 0x9
+ B134 = 0x4
+ B150 = 0x5
+ B1500000 = 0x100a
+ B1800 = 0xa
+ B19200 = 0xe
+ B200 = 0x6
+ B2000000 = 0x100b
+ B230400 = 0x1003
+ B2400 = 0xb
+ B2500000 = 0x100c
+ B300 = 0x7
+ B3000000 = 0x100d
+ B3500000 = 0x100e
+ B38400 = 0xf
+ B4000000 = 0x100f
+ B460800 = 0x1004
+ B4800 = 0xc
+ B50 = 0x1
+ B500000 = 0x1005
+ B57600 = 0x1001
+ B576000 = 0x1006
+ B600 = 0x8
+ B75 = 0x2
+ B921600 = 0x1007
+ B9600 = 0xd
+ BPF_A = 0x10
+ BPF_ABS = 0x20
+ BPF_ADD = 0x0
+ BPF_ALU = 0x4
+ BPF_AND = 0x50
+ BPF_B = 0x10
+ BPF_DIV = 0x30
+ BPF_H = 0x8
+ BPF_IMM = 0x0
+ BPF_IND = 0x40
+ BPF_JA = 0x0
+ BPF_JEQ = 0x10
+ BPF_JGE = 0x30
+ BPF_JGT = 0x20
+ BPF_JMP = 0x5
+ BPF_JSET = 0x40
+ BPF_K = 0x0
+ BPF_LD = 0x0
+ BPF_LDX = 0x1
+ BPF_LEN = 0x80
+ BPF_LSH = 0x60
+ BPF_MAJOR_VERSION = 0x1
+ BPF_MAXINSNS = 0x1000
+ BPF_MEM = 0x60
+ BPF_MEMWORDS = 0x10
+ BPF_MINOR_VERSION = 0x1
+ BPF_MISC = 0x7
+ BPF_MOD = 0x90
+ BPF_MSH = 0xa0
+ BPF_MUL = 0x20
+ BPF_NEG = 0x80
+ BPF_OR = 0x40
+ BPF_RET = 0x6
+ BPF_RSH = 0x70
+ BPF_ST = 0x2
+ BPF_STX = 0x3
+ BPF_SUB = 0x10
+ BPF_TAX = 0x0
+ BPF_TXA = 0x80
+ BPF_W = 0x0
+ BPF_X = 0x8
+ BPF_XOR = 0xa0
+ BRKINT = 0x2
+ CFLUSH = 0xf
+ CLOCAL = 0x800
+ CLONE_CHILD_CLEARTID = 0x200000
+ CLONE_CHILD_SETTID = 0x1000000
+ CLONE_DETACHED = 0x400000
+ CLONE_FILES = 0x400
+ CLONE_FS = 0x200
+ CLONE_IO = 0x80000000
+ CLONE_NEWIPC = 0x8000000
+ CLONE_NEWNET = 0x40000000
+ CLONE_NEWNS = 0x20000
+ CLONE_NEWPID = 0x20000000
+ CLONE_NEWUSER = 0x10000000
+ CLONE_NEWUTS = 0x4000000
+ CLONE_PARENT = 0x8000
+ CLONE_PARENT_SETTID = 0x100000
+ CLONE_PTRACE = 0x2000
+ CLONE_SETTLS = 0x80000
+ CLONE_SIGHAND = 0x800
+ CLONE_SYSVSEM = 0x40000
+ CLONE_THREAD = 0x10000
+ CLONE_UNTRACED = 0x800000
+ CLONE_VFORK = 0x4000
+ CLONE_VM = 0x100
+ CREAD = 0x80
+ CS5 = 0x0
+ CS6 = 0x10
+ CS7 = 0x20
+ CS8 = 0x30
+ CSIGNAL = 0xff
+ CSIZE = 0x30
+ CSTART = 0x11
+ CSTATUS = 0x0
+ CSTOP = 0x13
+ CSTOPB = 0x40
+ CSUSP = 0x1a
+ DT_BLK = 0x6
+ DT_CHR = 0x2
+ DT_DIR = 0x4
+ DT_FIFO = 0x1
+ DT_LNK = 0xa
+ DT_REG = 0x8
+ DT_SOCK = 0xc
+ DT_UNKNOWN = 0x0
+ DT_WHT = 0xe
+ ECHO = 0x8
+ ECHOCTL = 0x200
+ ECHOE = 0x10
+ ECHOK = 0x20
+ ECHOKE = 0x800
+ ECHONL = 0x40
+ ECHOPRT = 0x400
+ ENCODING_DEFAULT = 0x0
+ ENCODING_FM_MARK = 0x3
+ ENCODING_FM_SPACE = 0x4
+ ENCODING_MANCHESTER = 0x5
+ ENCODING_NRZ = 0x1
+ ENCODING_NRZI = 0x2
+ EPOLLERR = 0x8
+ EPOLLET = 0x80000000
+ EPOLLHUP = 0x10
+ EPOLLIN = 0x1
+ EPOLLMSG = 0x400
+ EPOLLONESHOT = 0x40000000
+ EPOLLOUT = 0x4
+ EPOLLPRI = 0x2
+ EPOLLRDBAND = 0x80
+ EPOLLRDHUP = 0x2000
+ EPOLLRDNORM = 0x40
+ EPOLLWAKEUP = 0x20000000
+ EPOLLWRBAND = 0x200
+ EPOLLWRNORM = 0x100
+ EPOLL_CLOEXEC = 0x80000
+ EPOLL_CTL_ADD = 0x1
+ EPOLL_CTL_DEL = 0x2
+ EPOLL_CTL_MOD = 0x3
+ EPOLL_NONBLOCK = 0x80
+ ETH_P_1588 = 0x88f7
+ ETH_P_8021AD = 0x88a8
+ ETH_P_8021AH = 0x88e7
+ ETH_P_8021Q = 0x8100
+ ETH_P_802_2 = 0x4
+ ETH_P_802_3 = 0x1
+ ETH_P_802_3_MIN = 0x600
+ ETH_P_802_EX1 = 0x88b5
+ ETH_P_AARP = 0x80f3
+ ETH_P_AF_IUCV = 0xfbfb
+ ETH_P_ALL = 0x3
+ ETH_P_AOE = 0x88a2
+ ETH_P_ARCNET = 0x1a
+ ETH_P_ARP = 0x806
+ ETH_P_ATALK = 0x809b
+ ETH_P_ATMFATE = 0x8884
+ ETH_P_ATMMPOA = 0x884c
+ ETH_P_AX25 = 0x2
+ ETH_P_BATMAN = 0x4305
+ ETH_P_BPQ = 0x8ff
+ ETH_P_CAIF = 0xf7
+ ETH_P_CAN = 0xc
+ ETH_P_CANFD = 0xd
+ ETH_P_CONTROL = 0x16
+ ETH_P_CUST = 0x6006
+ ETH_P_DDCMP = 0x6
+ ETH_P_DEC = 0x6000
+ ETH_P_DIAG = 0x6005
+ ETH_P_DNA_DL = 0x6001
+ ETH_P_DNA_RC = 0x6002
+ ETH_P_DNA_RT = 0x6003
+ ETH_P_DSA = 0x1b
+ ETH_P_ECONET = 0x18
+ ETH_P_EDSA = 0xdada
+ ETH_P_FCOE = 0x8906
+ ETH_P_FIP = 0x8914
+ ETH_P_HDLC = 0x19
+ ETH_P_IEEE802154 = 0xf6
+ ETH_P_IEEEPUP = 0xa00
+ ETH_P_IEEEPUPAT = 0xa01
+ ETH_P_IP = 0x800
+ ETH_P_IPV6 = 0x86dd
+ ETH_P_IPX = 0x8137
+ ETH_P_IRDA = 0x17
+ ETH_P_LAT = 0x6004
+ ETH_P_LINK_CTL = 0x886c
+ ETH_P_LOCALTALK = 0x9
+ ETH_P_LOOP = 0x60
+ ETH_P_MOBITEX = 0x15
+ ETH_P_MPLS_MC = 0x8848
+ ETH_P_MPLS_UC = 0x8847
+ ETH_P_MVRP = 0x88f5
+ ETH_P_PAE = 0x888e
+ ETH_P_PAUSE = 0x8808
+ ETH_P_PHONET = 0xf5
+ ETH_P_PPPTALK = 0x10
+ ETH_P_PPP_DISC = 0x8863
+ ETH_P_PPP_MP = 0x8
+ ETH_P_PPP_SES = 0x8864
+ ETH_P_PUP = 0x200
+ ETH_P_PUPAT = 0x201
+ ETH_P_QINQ1 = 0x9100
+ ETH_P_QINQ2 = 0x9200
+ ETH_P_QINQ3 = 0x9300
+ ETH_P_RARP = 0x8035
+ ETH_P_SCA = 0x6007
+ ETH_P_SLOW = 0x8809
+ ETH_P_SNAP = 0x5
+ ETH_P_TDLS = 0x890d
+ ETH_P_TEB = 0x6558
+ ETH_P_TIPC = 0x88ca
+ ETH_P_TRAILER = 0x1c
+ ETH_P_TR_802_2 = 0x11
+ ETH_P_WAN_PPP = 0x7
+ ETH_P_WCCP = 0x883e
+ ETH_P_X25 = 0x805
+ EXTA = 0xe
+ EXTB = 0xf
+ EXTPROC = 0x10000
+ FD_CLOEXEC = 0x1
+ FD_SETSIZE = 0x400
+ FLUSHO = 0x2000
+ F_DUPFD = 0x0
+ F_DUPFD_CLOEXEC = 0x406
+ F_EXLCK = 0x4
+ F_GETFD = 0x1
+ F_GETFL = 0x3
+ F_GETLEASE = 0x401
+ F_GETLK = 0xe
+ F_GETLK64 = 0xe
+ F_GETOWN = 0x17
+ F_GETOWN_EX = 0x10
+ F_GETPIPE_SZ = 0x408
+ F_GETSIG = 0xb
+ F_LOCK = 0x1
+ F_NOTIFY = 0x402
+ F_OK = 0x0
+ F_RDLCK = 0x0
+ F_SETFD = 0x2
+ F_SETFL = 0x4
+ F_SETLEASE = 0x400
+ F_SETLK = 0x6
+ F_SETLK64 = 0x6
+ F_SETLKW = 0x7
+ F_SETLKW64 = 0x7
+ F_SETOWN = 0x18
+ F_SETOWN_EX = 0xf
+ F_SETPIPE_SZ = 0x407
+ F_SETSIG = 0xa
+ F_SHLCK = 0x8
+ F_TEST = 0x3
+ F_TLOCK = 0x2
+ F_ULOCK = 0x0
+ F_UNLCK = 0x2
+ F_WRLCK = 0x1
+ HUPCL = 0x400
+ ICANON = 0x2
+ ICMPV6_FILTER = 0x1
+ ICRNL = 0x100
+ IEXTEN = 0x100
+ IFA_F_DADFAILED = 0x8
+ IFA_F_DEPRECATED = 0x20
+ IFA_F_HOMEADDRESS = 0x10
+ IFA_F_NODAD = 0x2
+ IFA_F_OPTIMISTIC = 0x4
+ IFA_F_PERMANENT = 0x80
+ IFA_F_SECONDARY = 0x1
+ IFA_F_TEMPORARY = 0x1
+ IFA_F_TENTATIVE = 0x40
+ IFA_MAX = 0x7
+ IFF_802_1Q_VLAN = 0x1
+ IFF_ALLMULTI = 0x200
+ IFF_ATTACH_QUEUE = 0x200
+ IFF_AUTOMEDIA = 0x4000
+ IFF_BONDING = 0x20
+ IFF_BRIDGE_PORT = 0x4000
+ IFF_BROADCAST = 0x2
+ IFF_DEBUG = 0x4
+ IFF_DETACH_QUEUE = 0x400
+ IFF_DISABLE_NETPOLL = 0x1000
+ IFF_DONT_BRIDGE = 0x800
+ IFF_DORMANT = 0x20000
+ IFF_DYNAMIC = 0x8000
+ IFF_EBRIDGE = 0x2
+ IFF_ECHO = 0x40000
+ IFF_ISATAP = 0x80
+ IFF_LIVE_ADDR_CHANGE = 0x100000
+ IFF_LOOPBACK = 0x8
+ IFF_LOWER_UP = 0x10000
+ IFF_MACVLAN_PORT = 0x2000
+ IFF_MASTER = 0x400
+ IFF_MASTER_8023AD = 0x8
+ IFF_MASTER_ALB = 0x10
+ IFF_MASTER_ARPMON = 0x100
+ IFF_MULTICAST = 0x1000
+ IFF_MULTI_QUEUE = 0x100
+ IFF_NOARP = 0x80
+ IFF_NOFILTER = 0x1000
+ IFF_NOTRAILERS = 0x20
+ IFF_NO_PI = 0x1000
+ IFF_ONE_QUEUE = 0x2000
+ IFF_OVS_DATAPATH = 0x8000
+ IFF_PERSIST = 0x800
+ IFF_POINTOPOINT = 0x10
+ IFF_PORTSEL = 0x2000
+ IFF_PROMISC = 0x100
+ IFF_RUNNING = 0x40
+ IFF_SLAVE = 0x800
+ IFF_SLAVE_INACTIVE = 0x4
+ IFF_SLAVE_NEEDARP = 0x40
+ IFF_SUPP_NOFCS = 0x80000
+ IFF_TAP = 0x2
+ IFF_TEAM_PORT = 0x40000
+ IFF_TUN = 0x1
+ IFF_TUN_EXCL = 0x8000
+ IFF_TX_SKB_SHARING = 0x10000
+ IFF_UNICAST_FLT = 0x20000
+ IFF_UP = 0x1
+ IFF_VNET_HDR = 0x4000
+ IFF_VOLATILE = 0x70c5a
+ IFF_WAN_HDLC = 0x200
+ IFF_XMIT_DST_RELEASE = 0x400
+ IFNAMSIZ = 0x10
+ IGNBRK = 0x1
+ IGNCR = 0x80
+ IGNPAR = 0x4
+ IMAXBEL = 0x2000
+ INLCR = 0x40
+ INPCK = 0x10
+ IN_ACCESS = 0x1
+ IN_ALL_EVENTS = 0xfff
+ IN_ATTRIB = 0x4
+ IN_CLASSA_HOST = 0xffffff
+ IN_CLASSA_MAX = 0x80
+ IN_CLASSA_NET = 0xff000000
+ IN_CLASSA_NSHIFT = 0x18
+ IN_CLASSB_HOST = 0xffff
+ IN_CLASSB_MAX = 0x10000
+ IN_CLASSB_NET = 0xffff0000
+ IN_CLASSB_NSHIFT = 0x10
+ IN_CLASSC_HOST = 0xff
+ IN_CLASSC_NET = 0xffffff00
+ IN_CLASSC_NSHIFT = 0x8
+ IN_CLOEXEC = 0x80000
+ IN_CLOSE = 0x18
+ IN_CLOSE_NOWRITE = 0x10
+ IN_CLOSE_WRITE = 0x8
+ IN_CREATE = 0x100
+ IN_DELETE = 0x200
+ IN_DELETE_SELF = 0x400
+ IN_DONT_FOLLOW = 0x2000000
+ IN_EXCL_UNLINK = 0x4000000
+ IN_IGNORED = 0x8000
+ IN_ISDIR = 0x40000000
+ IN_LOOPBACKNET = 0x7f
+ IN_MASK_ADD = 0x20000000
+ IN_MODIFY = 0x2
+ IN_MOVE = 0xc0
+ IN_MOVED_FROM = 0x40
+ IN_MOVED_TO = 0x80
+ IN_MOVE_SELF = 0x800
+ IN_NONBLOCK = 0x80
+ IN_ONESHOT = 0x80000000
+ IN_ONLYDIR = 0x1000000
+ IN_OPEN = 0x20
+ IN_Q_OVERFLOW = 0x4000
+ IN_UNMOUNT = 0x2000
+ IPPROTO_AH = 0x33
+ IPPROTO_COMP = 0x6c
+ IPPROTO_DCCP = 0x21
+ IPPROTO_DSTOPTS = 0x3c
+ IPPROTO_EGP = 0x8
+ IPPROTO_ENCAP = 0x62
+ IPPROTO_ESP = 0x32
+ IPPROTO_FRAGMENT = 0x2c
+ IPPROTO_GRE = 0x2f
+ IPPROTO_HOPOPTS = 0x0
+ IPPROTO_ICMP = 0x1
+ IPPROTO_ICMPV6 = 0x3a
+ IPPROTO_IDP = 0x16
+ IPPROTO_IGMP = 0x2
+ IPPROTO_IP = 0x0
+ IPPROTO_IPIP = 0x4
+ IPPROTO_IPV6 = 0x29
+ IPPROTO_MTP = 0x5c
+ IPPROTO_NONE = 0x3b
+ IPPROTO_PIM = 0x67
+ IPPROTO_PUP = 0xc
+ IPPROTO_RAW = 0xff
+ IPPROTO_ROUTING = 0x2b
+ IPPROTO_RSVP = 0x2e
+ IPPROTO_SCTP = 0x84
+ IPPROTO_TCP = 0x6
+ IPPROTO_TP = 0x1d
+ IPPROTO_UDP = 0x11
+ IPPROTO_UDPLITE = 0x88
+ IPV6_2292DSTOPTS = 0x4
+ IPV6_2292HOPLIMIT = 0x8
+ IPV6_2292HOPOPTS = 0x3
+ IPV6_2292PKTINFO = 0x2
+ IPV6_2292PKTOPTIONS = 0x6
+ IPV6_2292RTHDR = 0x5
+ IPV6_ADDRFORM = 0x1
+ IPV6_ADD_MEMBERSHIP = 0x14
+ IPV6_AUTHHDR = 0xa
+ IPV6_CHECKSUM = 0x7
+ IPV6_DROP_MEMBERSHIP = 0x15
+ IPV6_DSTOPTS = 0x3b
+ IPV6_HOPLIMIT = 0x34
+ IPV6_HOPOPTS = 0x36
+ IPV6_IPSEC_POLICY = 0x22
+ IPV6_JOIN_ANYCAST = 0x1b
+ IPV6_JOIN_GROUP = 0x14
+ IPV6_LEAVE_ANYCAST = 0x1c
+ IPV6_LEAVE_GROUP = 0x15
+ IPV6_MTU = 0x18
+ IPV6_MTU_DISCOVER = 0x17
+ IPV6_MULTICAST_HOPS = 0x12
+ IPV6_MULTICAST_IF = 0x11
+ IPV6_MULTICAST_LOOP = 0x13
+ IPV6_NEXTHOP = 0x9
+ IPV6_PKTINFO = 0x32
+ IPV6_PMTUDISC_DO = 0x2
+ IPV6_PMTUDISC_DONT = 0x0
+ IPV6_PMTUDISC_PROBE = 0x3
+ IPV6_PMTUDISC_WANT = 0x1
+ IPV6_RECVDSTOPTS = 0x3a
+ IPV6_RECVERR = 0x19
+ IPV6_RECVHOPLIMIT = 0x33
+ IPV6_RECVHOPOPTS = 0x35
+ IPV6_RECVPKTINFO = 0x31
+ IPV6_RECVRTHDR = 0x38
+ IPV6_RECVTCLASS = 0x42
+ IPV6_ROUTER_ALERT = 0x16
+ IPV6_RTHDR = 0x39
+ IPV6_RTHDRDSTOPTS = 0x37
+ IPV6_RTHDR_LOOSE = 0x0
+ IPV6_RTHDR_STRICT = 0x1
+ IPV6_RTHDR_TYPE_0 = 0x0
+ IPV6_RXDSTOPTS = 0x3b
+ IPV6_RXHOPOPTS = 0x36
+ IPV6_TCLASS = 0x43
+ IPV6_UNICAST_HOPS = 0x10
+ IPV6_V6ONLY = 0x1a
+ IPV6_XFRM_POLICY = 0x23
+ IP_ADD_MEMBERSHIP = 0x23
+ IP_ADD_SOURCE_MEMBERSHIP = 0x27
+ IP_BLOCK_SOURCE = 0x26
+ IP_DEFAULT_MULTICAST_LOOP = 0x1
+ IP_DEFAULT_MULTICAST_TTL = 0x1
+ IP_DF = 0x4000
+ IP_DROP_MEMBERSHIP = 0x24
+ IP_DROP_SOURCE_MEMBERSHIP = 0x28
+ IP_FREEBIND = 0xf
+ IP_HDRINCL = 0x3
+ IP_IPSEC_POLICY = 0x10
+ IP_MAXPACKET = 0xffff
+ IP_MAX_MEMBERSHIPS = 0x14
+ IP_MF = 0x2000
+ IP_MINTTL = 0x15
+ IP_MSFILTER = 0x29
+ IP_MSS = 0x240
+ IP_MTU = 0xe
+ IP_MTU_DISCOVER = 0xa
+ IP_MULTICAST_ALL = 0x31
+ IP_MULTICAST_IF = 0x20
+ IP_MULTICAST_LOOP = 0x22
+ IP_MULTICAST_TTL = 0x21
+ IP_OFFMASK = 0x1fff
+ IP_OPTIONS = 0x4
+ IP_ORIGDSTADDR = 0x14
+ IP_PASSSEC = 0x12
+ IP_PKTINFO = 0x8
+ IP_PKTOPTIONS = 0x9
+ IP_PMTUDISC = 0xa
+ IP_PMTUDISC_DO = 0x2
+ IP_PMTUDISC_DONT = 0x0
+ IP_PMTUDISC_PROBE = 0x3
+ IP_PMTUDISC_WANT = 0x1
+ IP_RECVERR = 0xb
+ IP_RECVOPTS = 0x6
+ IP_RECVORIGDSTADDR = 0x14
+ IP_RECVRETOPTS = 0x7
+ IP_RECVTOS = 0xd
+ IP_RECVTTL = 0xc
+ IP_RETOPTS = 0x7
+ IP_RF = 0x8000
+ IP_ROUTER_ALERT = 0x5
+ IP_TOS = 0x1
+ IP_TRANSPARENT = 0x13
+ IP_TTL = 0x2
+ IP_UNBLOCK_SOURCE = 0x25
+ IP_UNICAST_IF = 0x32
+ IP_XFRM_POLICY = 0x11
+ ISIG = 0x1
+ ISTRIP = 0x20
+ IUTF8 = 0x4000
+ IXANY = 0x800
+ IXOFF = 0x1000
+ IXON = 0x400
+ LINUX_REBOOT_CMD_CAD_OFF = 0x0
+ LINUX_REBOOT_CMD_CAD_ON = 0x89abcdef
+ LINUX_REBOOT_CMD_HALT = 0xcdef0123
+ LINUX_REBOOT_CMD_KEXEC = 0x45584543
+ LINUX_REBOOT_CMD_POWER_OFF = 0x4321fedc
+ LINUX_REBOOT_CMD_RESTART = 0x1234567
+ LINUX_REBOOT_CMD_RESTART2 = 0xa1b2c3d4
+ LINUX_REBOOT_CMD_SW_SUSPEND = 0xd000fce2
+ LINUX_REBOOT_MAGIC1 = 0xfee1dead
+ LINUX_REBOOT_MAGIC2 = 0x28121969
+ LOCK_EX = 0x2
+ LOCK_NB = 0x4
+ LOCK_SH = 0x1
+ LOCK_UN = 0x8
+ MADV_DODUMP = 0x11
+ MADV_DOFORK = 0xb
+ MADV_DONTDUMP = 0x10
+ MADV_DONTFORK = 0xa
+ MADV_DONTNEED = 0x4
+ MADV_HUGEPAGE = 0xe
+ MADV_HWPOISON = 0x64
+ MADV_MERGEABLE = 0xc
+ MADV_NOHUGEPAGE = 0xf
+ MADV_NORMAL = 0x0
+ MADV_RANDOM = 0x1
+ MADV_REMOVE = 0x9
+ MADV_SEQUENTIAL = 0x2
+ MADV_UNMERGEABLE = 0xd
+ MADV_WILLNEED = 0x3
+ MAP_ANON = 0x800
+ MAP_ANONYMOUS = 0x800
+ MAP_DENYWRITE = 0x2000
+ MAP_EXECUTABLE = 0x4000
+ MAP_FILE = 0x0
+ MAP_FIXED = 0x10
+ MAP_GROWSDOWN = 0x1000
+ MAP_HUGETLB = 0x80000
+ MAP_LOCKED = 0x8000
+ MAP_NONBLOCK = 0x20000
+ MAP_NORESERVE = 0x400
+ MAP_POPULATE = 0x10000
+ MAP_PRIVATE = 0x2
+ MAP_RENAME = 0x800
+ MAP_SHARED = 0x1
+ MAP_STACK = 0x40000
+ MAP_TYPE = 0xf
+ MCL_CURRENT = 0x1
+ MCL_FUTURE = 0x2
+ MNT_DETACH = 0x2
+ MNT_EXPIRE = 0x4
+ MNT_FORCE = 0x1
+ MSG_CMSG_CLOEXEC = 0x40000000
+ MSG_CONFIRM = 0x800
+ MSG_CTRUNC = 0x8
+ MSG_DONTROUTE = 0x4
+ MSG_DONTWAIT = 0x40
+ MSG_EOR = 0x80
+ MSG_ERRQUEUE = 0x2000
+ MSG_FASTOPEN = 0x20000000
+ MSG_FIN = 0x200
+ MSG_MORE = 0x8000
+ MSG_NOSIGNAL = 0x4000
+ MSG_OOB = 0x1
+ MSG_PEEK = 0x2
+ MSG_PROXY = 0x10
+ MSG_RST = 0x1000
+ MSG_SYN = 0x400
+ MSG_TRUNC = 0x20
+ MSG_TRYHARD = 0x4
+ MSG_WAITALL = 0x100
+ MSG_WAITFORONE = 0x10000
+ MS_ACTIVE = 0x40000000
+ MS_ASYNC = 0x1
+ MS_BIND = 0x1000
+ MS_DIRSYNC = 0x80
+ MS_INVALIDATE = 0x2
+ MS_I_VERSION = 0x800000
+ MS_KERNMOUNT = 0x400000
+ MS_MANDLOCK = 0x40
+ MS_MGC_MSK = 0xffff0000
+ MS_MGC_VAL = 0xc0ed0000
+ MS_MOVE = 0x2000
+ MS_NOATIME = 0x400
+ MS_NODEV = 0x4
+ MS_NODIRATIME = 0x800
+ MS_NOEXEC = 0x8
+ MS_NOSUID = 0x2
+ MS_NOUSER = -0x80000000
+ MS_POSIXACL = 0x10000
+ MS_PRIVATE = 0x40000
+ MS_RDONLY = 0x1
+ MS_REC = 0x4000
+ MS_RELATIME = 0x200000
+ MS_REMOUNT = 0x20
+ MS_RMT_MASK = 0x800051
+ MS_SHARED = 0x100000
+ MS_SILENT = 0x8000
+ MS_SLAVE = 0x80000
+ MS_STRICTATIME = 0x1000000
+ MS_SYNC = 0x4
+ MS_SYNCHRONOUS = 0x10
+ MS_UNBINDABLE = 0x20000
+ NAME_MAX = 0xff
+ NETLINK_ADD_MEMBERSHIP = 0x1
+ NETLINK_AUDIT = 0x9
+ NETLINK_BROADCAST_ERROR = 0x4
+ NETLINK_CONNECTOR = 0xb
+ NETLINK_CRYPTO = 0x15
+ NETLINK_DNRTMSG = 0xe
+ NETLINK_DROP_MEMBERSHIP = 0x2
+ NETLINK_ECRYPTFS = 0x13
+ NETLINK_FIB_LOOKUP = 0xa
+ NETLINK_FIREWALL = 0x3
+ NETLINK_GENERIC = 0x10
+ NETLINK_INET_DIAG = 0x4
+ NETLINK_IP6_FW = 0xd
+ NETLINK_ISCSI = 0x8
+ NETLINK_KOBJECT_UEVENT = 0xf
+ NETLINK_NETFILTER = 0xc
+ NETLINK_NFLOG = 0x5
+ NETLINK_NO_ENOBUFS = 0x5
+ NETLINK_PKTINFO = 0x3
+ NETLINK_RDMA = 0x14
+ NETLINK_ROUTE = 0x0
+ NETLINK_RX_RING = 0x6
+ NETLINK_SCSITRANSPORT = 0x12
+ NETLINK_SELINUX = 0x7
+ NETLINK_SOCK_DIAG = 0x4
+ NETLINK_TX_RING = 0x7
+ NETLINK_UNUSED = 0x1
+ NETLINK_USERSOCK = 0x2
+ NETLINK_XFRM = 0x6
+ NLA_ALIGNTO = 0x4
+ NLA_F_NESTED = 0x8000
+ NLA_F_NET_BYTEORDER = 0x4000
+ NLA_HDRLEN = 0x4
+ NLMSG_ALIGNTO = 0x4
+ NLMSG_DONE = 0x3
+ NLMSG_ERROR = 0x2
+ NLMSG_HDRLEN = 0x10
+ NLMSG_MIN_TYPE = 0x10
+ NLMSG_NOOP = 0x1
+ NLMSG_OVERRUN = 0x4
+ NLM_F_ACK = 0x4
+ NLM_F_APPEND = 0x800
+ NLM_F_ATOMIC = 0x400
+ NLM_F_CREATE = 0x400
+ NLM_F_DUMP = 0x300
+ NLM_F_DUMP_INTR = 0x10
+ NLM_F_ECHO = 0x8
+ NLM_F_EXCL = 0x200
+ NLM_F_MATCH = 0x200
+ NLM_F_MULTI = 0x2
+ NLM_F_REPLACE = 0x100
+ NLM_F_REQUEST = 0x1
+ NLM_F_ROOT = 0x100
+ NOFLSH = 0x80
+ OCRNL = 0x8
+ OFDEL = 0x80
+ OFILL = 0x40
+ ONLCR = 0x4
+ ONLRET = 0x20
+ ONOCR = 0x10
+ OPOST = 0x1
+ O_ACCMODE = 0x3
+ O_APPEND = 0x8
+ O_ASYNC = 0x1000
+ O_CLOEXEC = 0x80000
+ O_CREAT = 0x100
+ O_DIRECT = 0x8000
+ O_DIRECTORY = 0x10000
+ O_DSYNC = 0x10
+ O_EXCL = 0x400
+ O_FSYNC = 0x4010
+ O_LARGEFILE = 0x0
+ O_NDELAY = 0x80
+ O_NOATIME = 0x40000
+ O_NOCTTY = 0x800
+ O_NOFOLLOW = 0x20000
+ O_NONBLOCK = 0x80
+ O_PATH = 0x200000
+ O_RDONLY = 0x0
+ O_RDWR = 0x2
+ O_RSYNC = 0x4010
+ O_SYNC = 0x4010
+ O_TRUNC = 0x200
+ O_WRONLY = 0x1
+ PACKET_ADD_MEMBERSHIP = 0x1
+ PACKET_AUXDATA = 0x8
+ PACKET_BROADCAST = 0x1
+ PACKET_COPY_THRESH = 0x7
+ PACKET_DROP_MEMBERSHIP = 0x2
+ PACKET_FANOUT = 0x12
+ PACKET_FANOUT_CPU = 0x2
+ PACKET_FANOUT_FLAG_DEFRAG = 0x8000
+ PACKET_FANOUT_FLAG_ROLLOVER = 0x1000
+ PACKET_FANOUT_HASH = 0x0
+ PACKET_FANOUT_LB = 0x1
+ PACKET_FANOUT_RND = 0x4
+ PACKET_FANOUT_ROLLOVER = 0x3
+ PACKET_FASTROUTE = 0x6
+ PACKET_HDRLEN = 0xb
+ PACKET_HOST = 0x0
+ PACKET_LOOPBACK = 0x5
+ PACKET_LOSS = 0xe
+ PACKET_MR_ALLMULTI = 0x2
+ PACKET_MR_MULTICAST = 0x0
+ PACKET_MR_PROMISC = 0x1
+ PACKET_MR_UNICAST = 0x3
+ PACKET_MULTICAST = 0x2
+ PACKET_ORIGDEV = 0x9
+ PACKET_OTHERHOST = 0x3
+ PACKET_OUTGOING = 0x4
+ PACKET_RECV_OUTPUT = 0x3
+ PACKET_RESERVE = 0xc
+ PACKET_RX_RING = 0x5
+ PACKET_STATISTICS = 0x6
+ PACKET_TIMESTAMP = 0x11
+ PACKET_TX_HAS_OFF = 0x13
+ PACKET_TX_RING = 0xd
+ PACKET_TX_TIMESTAMP = 0x10
+ PACKET_VERSION = 0xa
+ PACKET_VNET_HDR = 0xf
+ PARENB = 0x100
+ PARITY_CRC16_PR0 = 0x2
+ PARITY_CRC16_PR0_CCITT = 0x4
+ PARITY_CRC16_PR1 = 0x3
+ PARITY_CRC16_PR1_CCITT = 0x5
+ PARITY_CRC32_PR0_CCITT = 0x6
+ PARITY_CRC32_PR1_CCITT = 0x7
+ PARITY_DEFAULT = 0x0
+ PARITY_NONE = 0x1
+ PARMRK = 0x8
+ PARODD = 0x200
+ PENDIN = 0x4000
+ PRIO_PGRP = 0x1
+ PRIO_PROCESS = 0x0
+ PRIO_USER = 0x2
+ PROT_EXEC = 0x4
+ PROT_GROWSDOWN = 0x1000000
+ PROT_GROWSUP = 0x2000000
+ PROT_NONE = 0x0
+ PROT_READ = 0x1
+ PROT_WRITE = 0x2
+ PR_CAPBSET_DROP = 0x18
+ PR_CAPBSET_READ = 0x17
+ PR_ENDIAN_BIG = 0x0
+ PR_ENDIAN_LITTLE = 0x1
+ PR_ENDIAN_PPC_LITTLE = 0x2
+ PR_FPEMU_NOPRINT = 0x1
+ PR_FPEMU_SIGFPE = 0x2
+ PR_FP_EXC_ASYNC = 0x2
+ PR_FP_EXC_DISABLED = 0x0
+ PR_FP_EXC_DIV = 0x10000
+ PR_FP_EXC_INV = 0x100000
+ PR_FP_EXC_NONRECOV = 0x1
+ PR_FP_EXC_OVF = 0x20000
+ PR_FP_EXC_PRECISE = 0x3
+ PR_FP_EXC_RES = 0x80000
+ PR_FP_EXC_SW_ENABLE = 0x80
+ PR_FP_EXC_UND = 0x40000
+ PR_GET_CHILD_SUBREAPER = 0x25
+ PR_GET_DUMPABLE = 0x3
+ PR_GET_ENDIAN = 0x13
+ PR_GET_FPEMU = 0x9
+ PR_GET_FPEXC = 0xb
+ PR_GET_KEEPCAPS = 0x7
+ PR_GET_NAME = 0x10
+ PR_GET_NO_NEW_PRIVS = 0x27
+ PR_GET_PDEATHSIG = 0x2
+ PR_GET_SECCOMP = 0x15
+ PR_GET_SECUREBITS = 0x1b
+ PR_GET_TID_ADDRESS = 0x28
+ PR_GET_TIMERSLACK = 0x1e
+ PR_GET_TIMING = 0xd
+ PR_GET_TSC = 0x19
+ PR_GET_UNALIGN = 0x5
+ PR_MCE_KILL = 0x21
+ PR_MCE_KILL_CLEAR = 0x0
+ PR_MCE_KILL_DEFAULT = 0x2
+ PR_MCE_KILL_EARLY = 0x1
+ PR_MCE_KILL_GET = 0x22
+ PR_MCE_KILL_LATE = 0x0
+ PR_MCE_KILL_SET = 0x1
+ PR_SET_CHILD_SUBREAPER = 0x24
+ PR_SET_DUMPABLE = 0x4
+ PR_SET_ENDIAN = 0x14
+ PR_SET_FPEMU = 0xa
+ PR_SET_FPEXC = 0xc
+ PR_SET_KEEPCAPS = 0x8
+ PR_SET_MM = 0x23
+ PR_SET_MM_ARG_END = 0x9
+ PR_SET_MM_ARG_START = 0x8
+ PR_SET_MM_AUXV = 0xc
+ PR_SET_MM_BRK = 0x7
+ PR_SET_MM_END_CODE = 0x2
+ PR_SET_MM_END_DATA = 0x4
+ PR_SET_MM_ENV_END = 0xb
+ PR_SET_MM_ENV_START = 0xa
+ PR_SET_MM_EXE_FILE = 0xd
+ PR_SET_MM_START_BRK = 0x6
+ PR_SET_MM_START_CODE = 0x1
+ PR_SET_MM_START_DATA = 0x3
+ PR_SET_MM_START_STACK = 0x5
+ PR_SET_NAME = 0xf
+ PR_SET_NO_NEW_PRIVS = 0x26
+ PR_SET_PDEATHSIG = 0x1
+ PR_SET_PTRACER = 0x59616d61
+ PR_SET_PTRACER_ANY = -0x1
+ PR_SET_SECCOMP = 0x16
+ PR_SET_SECUREBITS = 0x1c
+ PR_SET_TIMERSLACK = 0x1d
+ PR_SET_TIMING = 0xe
+ PR_SET_TSC = 0x1a
+ PR_SET_UNALIGN = 0x6
+ PR_TASK_PERF_EVENTS_DISABLE = 0x1f
+ PR_TASK_PERF_EVENTS_ENABLE = 0x20
+ PR_TIMING_STATISTICAL = 0x0
+ PR_TIMING_TIMESTAMP = 0x1
+ PR_TSC_ENABLE = 0x1
+ PR_TSC_SIGSEGV = 0x2
+ PR_UNALIGN_NOPRINT = 0x1
+ PR_UNALIGN_SIGBUS = 0x2
+ PTRACE_ATTACH = 0x10
+ PTRACE_CONT = 0x7
+ PTRACE_DETACH = 0x11
+ PTRACE_EVENT_CLONE = 0x3
+ PTRACE_EVENT_EXEC = 0x4
+ PTRACE_EVENT_EXIT = 0x6
+ PTRACE_EVENT_FORK = 0x1
+ PTRACE_EVENT_SECCOMP = 0x7
+ PTRACE_EVENT_STOP = 0x80
+ PTRACE_EVENT_VFORK = 0x2
+ PTRACE_EVENT_VFORK_DONE = 0x5
+ PTRACE_GETEVENTMSG = 0x4201
+ PTRACE_GETFPREGS = 0xe
+ PTRACE_GETREGS = 0xc
+ PTRACE_GETREGSET = 0x4204
+ PTRACE_GETSIGINFO = 0x4202
+ PTRACE_GETSIGMASK = 0x420a
+ PTRACE_GET_THREAD_AREA = 0x19
+ PTRACE_GET_THREAD_AREA_3264 = 0xc4
+ PTRACE_GET_WATCH_REGS = 0xd0
+ PTRACE_INTERRUPT = 0x4207
+ PTRACE_KILL = 0x8
+ PTRACE_LISTEN = 0x4208
+ PTRACE_OLDSETOPTIONS = 0x15
+ PTRACE_O_EXITKILL = 0x100000
+ PTRACE_O_MASK = 0x1000ff
+ PTRACE_O_TRACECLONE = 0x8
+ PTRACE_O_TRACEEXEC = 0x10
+ PTRACE_O_TRACEEXIT = 0x40
+ PTRACE_O_TRACEFORK = 0x2
+ PTRACE_O_TRACESECCOMP = 0x80
+ PTRACE_O_TRACESYSGOOD = 0x1
+ PTRACE_O_TRACEVFORK = 0x4
+ PTRACE_O_TRACEVFORKDONE = 0x20
+ PTRACE_PEEKDATA = 0x2
+ PTRACE_PEEKDATA_3264 = 0xc1
+ PTRACE_PEEKSIGINFO = 0x4209
+ PTRACE_PEEKSIGINFO_SHARED = 0x1
+ PTRACE_PEEKTEXT = 0x1
+ PTRACE_PEEKTEXT_3264 = 0xc0
+ PTRACE_PEEKUSR = 0x3
+ PTRACE_POKEDATA = 0x5
+ PTRACE_POKEDATA_3264 = 0xc3
+ PTRACE_POKETEXT = 0x4
+ PTRACE_POKETEXT_3264 = 0xc2
+ PTRACE_POKEUSR = 0x6
+ PTRACE_SEIZE = 0x4206
+ PTRACE_SETFPREGS = 0xf
+ PTRACE_SETOPTIONS = 0x4200
+ PTRACE_SETREGS = 0xd
+ PTRACE_SETREGSET = 0x4205
+ PTRACE_SETSIGINFO = 0x4203
+ PTRACE_SETSIGMASK = 0x420b
+ PTRACE_SET_THREAD_AREA = 0x1a
+ PTRACE_SET_WATCH_REGS = 0xd1
+ PTRACE_SINGLESTEP = 0x9
+ PTRACE_SYSCALL = 0x18
+ PTRACE_TRACEME = 0x0
+ RLIMIT_AS = 0x6
+ RLIMIT_CORE = 0x4
+ RLIMIT_CPU = 0x0
+ RLIMIT_DATA = 0x2
+ RLIMIT_FSIZE = 0x1
+ RLIMIT_NOFILE = 0x5
+ RLIMIT_STACK = 0x3
+ RLIM_INFINITY = -0x1
+ RTAX_ADVMSS = 0x8
+ RTAX_CWND = 0x7
+ RTAX_FEATURES = 0xc
+ RTAX_FEATURE_ALLFRAG = 0x8
+ RTAX_FEATURE_ECN = 0x1
+ RTAX_FEATURE_SACK = 0x2
+ RTAX_FEATURE_TIMESTAMP = 0x4
+ RTAX_HOPLIMIT = 0xa
+ RTAX_INITCWND = 0xb
+ RTAX_INITRWND = 0xe
+ RTAX_LOCK = 0x1
+ RTAX_MAX = 0xf
+ RTAX_MTU = 0x2
+ RTAX_QUICKACK = 0xf
+ RTAX_REORDERING = 0x9
+ RTAX_RTO_MIN = 0xd
+ RTAX_RTT = 0x4
+ RTAX_RTTVAR = 0x5
+ RTAX_SSTHRESH = 0x6
+ RTAX_UNSPEC = 0x0
+ RTAX_WINDOW = 0x3
+ RTA_ALIGNTO = 0x4
+ RTA_MAX = 0x11
+ RTCF_DIRECTSRC = 0x4000000
+ RTCF_DOREDIRECT = 0x1000000
+ RTCF_LOG = 0x2000000
+ RTCF_MASQ = 0x400000
+ RTCF_NAT = 0x800000
+ RTCF_VALVE = 0x200000
+ RTF_ADDRCLASSMASK = 0xf8000000
+ RTF_ADDRCONF = 0x40000
+ RTF_ALLONLINK = 0x20000
+ RTF_BROADCAST = 0x10000000
+ RTF_CACHE = 0x1000000
+ RTF_DEFAULT = 0x10000
+ RTF_DYNAMIC = 0x10
+ RTF_FLOW = 0x2000000
+ RTF_GATEWAY = 0x2
+ RTF_HOST = 0x4
+ RTF_INTERFACE = 0x40000000
+ RTF_IRTT = 0x100
+ RTF_LINKRT = 0x100000
+ RTF_LOCAL = 0x80000000
+ RTF_MODIFIED = 0x20
+ RTF_MSS = 0x40
+ RTF_MTU = 0x40
+ RTF_MULTICAST = 0x20000000
+ RTF_NAT = 0x8000000
+ RTF_NOFORWARD = 0x1000
+ RTF_NONEXTHOP = 0x200000
+ RTF_NOPMTUDISC = 0x4000
+ RTF_POLICY = 0x4000000
+ RTF_REINSTATE = 0x8
+ RTF_REJECT = 0x200
+ RTF_STATIC = 0x400
+ RTF_THROW = 0x2000
+ RTF_UP = 0x1
+ RTF_WINDOW = 0x80
+ RTF_XRESOLVE = 0x800
+ RTM_BASE = 0x10
+ RTM_DELACTION = 0x31
+ RTM_DELADDR = 0x15
+ RTM_DELADDRLABEL = 0x49
+ RTM_DELLINK = 0x11
+ RTM_DELMDB = 0x55
+ RTM_DELNEIGH = 0x1d
+ RTM_DELQDISC = 0x25
+ RTM_DELROUTE = 0x19
+ RTM_DELRULE = 0x21
+ RTM_DELTCLASS = 0x29
+ RTM_DELTFILTER = 0x2d
+ RTM_F_CLONED = 0x200
+ RTM_F_EQUALIZE = 0x400
+ RTM_F_NOTIFY = 0x100
+ RTM_F_PREFIX = 0x800
+ RTM_GETACTION = 0x32
+ RTM_GETADDR = 0x16
+ RTM_GETADDRLABEL = 0x4a
+ RTM_GETANYCAST = 0x3e
+ RTM_GETDCB = 0x4e
+ RTM_GETLINK = 0x12
+ RTM_GETMDB = 0x56
+ RTM_GETMULTICAST = 0x3a
+ RTM_GETNEIGH = 0x1e
+ RTM_GETNEIGHTBL = 0x42
+ RTM_GETNETCONF = 0x52
+ RTM_GETQDISC = 0x26
+ RTM_GETROUTE = 0x1a
+ RTM_GETRULE = 0x22
+ RTM_GETTCLASS = 0x2a
+ RTM_GETTFILTER = 0x2e
+ RTM_MAX = 0x57
+ RTM_NEWACTION = 0x30
+ RTM_NEWADDR = 0x14
+ RTM_NEWADDRLABEL = 0x48
+ RTM_NEWLINK = 0x10
+ RTM_NEWMDB = 0x54
+ RTM_NEWNDUSEROPT = 0x44
+ RTM_NEWNEIGH = 0x1c
+ RTM_NEWNEIGHTBL = 0x40
+ RTM_NEWNETCONF = 0x50
+ RTM_NEWPREFIX = 0x34
+ RTM_NEWQDISC = 0x24
+ RTM_NEWROUTE = 0x18
+ RTM_NEWRULE = 0x20
+ RTM_NEWTCLASS = 0x28
+ RTM_NEWTFILTER = 0x2c
+ RTM_NR_FAMILIES = 0x12
+ RTM_NR_MSGTYPES = 0x48
+ RTM_SETDCB = 0x4f
+ RTM_SETLINK = 0x13
+ RTM_SETNEIGHTBL = 0x43
+ RTNH_ALIGNTO = 0x4
+ RTNH_F_DEAD = 0x1
+ RTNH_F_ONLINK = 0x4
+ RTNH_F_PERVASIVE = 0x2
+ RTN_MAX = 0xb
+ RTPROT_BIRD = 0xc
+ RTPROT_BOOT = 0x3
+ RTPROT_DHCP = 0x10
+ RTPROT_DNROUTED = 0xd
+ RTPROT_GATED = 0x8
+ RTPROT_KERNEL = 0x2
+ RTPROT_MROUTED = 0x11
+ RTPROT_MRT = 0xa
+ RTPROT_NTK = 0xf
+ RTPROT_RA = 0x9
+ RTPROT_REDIRECT = 0x1
+ RTPROT_STATIC = 0x4
+ RTPROT_UNSPEC = 0x0
+ RTPROT_XORP = 0xe
+ RTPROT_ZEBRA = 0xb
+ RT_CLASS_DEFAULT = 0xfd
+ RT_CLASS_LOCAL = 0xff
+ RT_CLASS_MAIN = 0xfe
+ RT_CLASS_MAX = 0xff
+ RT_CLASS_UNSPEC = 0x0
+ RUSAGE_CHILDREN = -0x1
+ RUSAGE_SELF = 0x0
+ RUSAGE_THREAD = 0x1
+ SCM_CREDENTIALS = 0x2
+ SCM_RIGHTS = 0x1
+ SCM_TIMESTAMP = 0x1d
+ SCM_TIMESTAMPING = 0x25
+ SCM_TIMESTAMPNS = 0x23
+ SCM_WIFI_STATUS = 0x29
+ SHUT_RD = 0x0
+ SHUT_RDWR = 0x2
+ SHUT_WR = 0x1
+ SIOCADDDLCI = 0x8980
+ SIOCADDMULTI = 0x8931
+ SIOCADDRT = 0x890b
+ SIOCATMARK = 0x40047307
+ SIOCDARP = 0x8953
+ SIOCDELDLCI = 0x8981
+ SIOCDELMULTI = 0x8932
+ SIOCDELRT = 0x890c
+ SIOCDEVPRIVATE = 0x89f0
+ SIOCDIFADDR = 0x8936
+ SIOCDRARP = 0x8960
+ SIOCGARP = 0x8954
+ SIOCGIFADDR = 0x8915
+ SIOCGIFBR = 0x8940
+ SIOCGIFBRDADDR = 0x8919
+ SIOCGIFCONF = 0x8912
+ SIOCGIFCOUNT = 0x8938
+ SIOCGIFDSTADDR = 0x8917
+ SIOCGIFENCAP = 0x8925
+ SIOCGIFFLAGS = 0x8913
+ SIOCGIFHWADDR = 0x8927
+ SIOCGIFINDEX = 0x8933
+ SIOCGIFMAP = 0x8970
+ SIOCGIFMEM = 0x891f
+ SIOCGIFMETRIC = 0x891d
+ SIOCGIFMTU = 0x8921
+ SIOCGIFNAME = 0x8910
+ SIOCGIFNETMASK = 0x891b
+ SIOCGIFPFLAGS = 0x8935
+ SIOCGIFSLAVE = 0x8929
+ SIOCGIFTXQLEN = 0x8942
+ SIOCGPGRP = 0x40047309
+ SIOCGRARP = 0x8961
+ SIOCGSTAMP = 0x8906
+ SIOCGSTAMPNS = 0x8907
+ SIOCPROTOPRIVATE = 0x89e0
+ SIOCRTMSG = 0x890d
+ SIOCSARP = 0x8955
+ SIOCSIFADDR = 0x8916
+ SIOCSIFBR = 0x8941
+ SIOCSIFBRDADDR = 0x891a
+ SIOCSIFDSTADDR = 0x8918
+ SIOCSIFENCAP = 0x8926
+ SIOCSIFFLAGS = 0x8914
+ SIOCSIFHWADDR = 0x8924
+ SIOCSIFHWBROADCAST = 0x8937
+ SIOCSIFLINK = 0x8911
+ SIOCSIFMAP = 0x8971
+ SIOCSIFMEM = 0x8920
+ SIOCSIFMETRIC = 0x891e
+ SIOCSIFMTU = 0x8922
+ SIOCSIFNAME = 0x8923
+ SIOCSIFNETMASK = 0x891c
+ SIOCSIFPFLAGS = 0x8934
+ SIOCSIFSLAVE = 0x8930
+ SIOCSIFTXQLEN = 0x8943
+ SIOCSPGRP = 0x80047308
+ SIOCSRARP = 0x8962
+ SOCK_CLOEXEC = 0x80000
+ SOCK_DCCP = 0x6
+ SOCK_DGRAM = 0x1
+ SOCK_NONBLOCK = 0x80
+ SOCK_PACKET = 0xa
+ SOCK_RAW = 0x3
+ SOCK_RDM = 0x4
+ SOCK_SEQPACKET = 0x5
+ SOCK_STREAM = 0x2
+ SOL_AAL = 0x109
+ SOL_ATM = 0x108
+ SOL_DECNET = 0x105
+ SOL_ICMPV6 = 0x3a
+ SOL_IP = 0x0
+ SOL_IPV6 = 0x29
+ SOL_IRDA = 0x10a
+ SOL_PACKET = 0x107
+ SOL_RAW = 0xff
+ SOL_SOCKET = 0xffff
+ SOL_TCP = 0x6
+ SOL_X25 = 0x106
+ SOMAXCONN = 0x80
+ SO_ACCEPTCONN = 0x1009
+ SO_ATTACH_FILTER = 0x1a
+ SO_BINDTODEVICE = 0x19
+ SO_BROADCAST = 0x20
+ SO_BSDCOMPAT = 0xe
+ SO_BUSY_POLL = 0x2e
+ SO_DEBUG = 0x1
+ SO_DETACH_FILTER = 0x1b
+ SO_DOMAIN = 0x1029
+ SO_DONTROUTE = 0x10
+ SO_ERROR = 0x1007
+ SO_GET_FILTER = 0x1a
+ SO_KEEPALIVE = 0x8
+ SO_LINGER = 0x80
+ SO_LOCK_FILTER = 0x2c
+ SO_MARK = 0x24
+ SO_NOFCS = 0x2b
+ SO_NO_CHECK = 0xb
+ SO_OOBINLINE = 0x100
+ SO_PASSCRED = 0x11
+ SO_PASSSEC = 0x22
+ SO_PEEK_OFF = 0x2a
+ SO_PEERCRED = 0x12
+ SO_PEERNAME = 0x1c
+ SO_PEERSEC = 0x1e
+ SO_PRIORITY = 0xc
+ SO_PROTOCOL = 0x1028
+ SO_RCVBUF = 0x1002
+ SO_RCVBUFFORCE = 0x21
+ SO_RCVLOWAT = 0x1004
+ SO_RCVTIMEO = 0x1006
+ SO_REUSEADDR = 0x4
+ SO_REUSEPORT = 0x200
+ SO_RXQ_OVFL = 0x28
+ SO_SECURITY_AUTHENTICATION = 0x16
+ SO_SECURITY_ENCRYPTION_NETWORK = 0x18
+ SO_SECURITY_ENCRYPTION_TRANSPORT = 0x17
+ SO_SELECT_ERR_QUEUE = 0x2d
+ SO_SNDBUF = 0x1001
+ SO_SNDBUFFORCE = 0x1f
+ SO_SNDLOWAT = 0x1003
+ SO_SNDTIMEO = 0x1005
+ SO_STYLE = 0x1008
+ SO_TIMESTAMP = 0x1d
+ SO_TIMESTAMPING = 0x25
+ SO_TIMESTAMPNS = 0x23
+ SO_TYPE = 0x1008
+ SO_WIFI_STATUS = 0x29
+ S_BLKSIZE = 0x200
+ S_IEXEC = 0x40
+ S_IFBLK = 0x6000
+ S_IFCHR = 0x2000
+ S_IFDIR = 0x4000
+ S_IFIFO = 0x1000
+ S_IFLNK = 0xa000
+ S_IFMT = 0xf000
+ S_IFREG = 0x8000
+ S_IFSOCK = 0xc000
+ S_IREAD = 0x100
+ S_IRGRP = 0x20
+ S_IROTH = 0x4
+ S_IRUSR = 0x100
+ S_IRWXG = 0x38
+ S_IRWXO = 0x7
+ S_IRWXU = 0x1c0
+ S_ISGID = 0x400
+ S_ISUID = 0x800
+ S_ISVTX = 0x200
+ S_IWGRP = 0x10
+ S_IWOTH = 0x2
+ S_IWRITE = 0x80
+ S_IWUSR = 0x80
+ S_IXGRP = 0x8
+ S_IXOTH = 0x1
+ S_IXUSR = 0x40
+ TCFLSH = 0x5407
+ TCIFLUSH = 0x0
+ TCIOFLUSH = 0x2
+ TCOFLUSH = 0x1
+ TCP_CONGESTION = 0xd
+ TCP_CORK = 0x3
+ TCP_DEFER_ACCEPT = 0x9
+ TCP_INFO = 0xb
+ TCP_KEEPCNT = 0x6
+ TCP_KEEPIDLE = 0x4
+ TCP_KEEPINTVL = 0x5
+ TCP_LINGER2 = 0x8
+ TCP_MAXSEG = 0x2
+ TCP_MAXWIN = 0xffff
+ TCP_MAX_WINSHIFT = 0xe
+ TCP_MD5SIG = 0xe
+ TCP_MD5SIG_MAXKEYLEN = 0x50
+ TCP_MSS = 0x200
+ TCP_NODELAY = 0x1
+ TCP_QUICKACK = 0xc
+ TCP_SYNCNT = 0x7
+ TCP_WINDOW_CLAMP = 0xa
+ TCSAFLUSH = 0x5410
+ TIOCCBRK = 0x5428
+ TIOCCONS = 0x80047478
+ TIOCEXCL = 0x740d
+ TIOCGDEV = 0x40045432
+ TIOCGETD = 0x7400
+ TIOCGETP = 0x7408
+ TIOCGEXCL = 0x40045440
+ TIOCGICOUNT = 0x5492
+ TIOCGLCKTRMIOS = 0x548b
+ TIOCGLTC = 0x7474
+ TIOCGPGRP = 0x40047477
+ TIOCGPKT = 0x40045438
+ TIOCGPTLCK = 0x40045439
+ TIOCGPTN = 0x40045430
+ TIOCGSERIAL = 0x5484
+ TIOCGSID = 0x7416
+ TIOCGSOFTCAR = 0x5481
+ TIOCGWINSZ = 0x40087468
+ TIOCINQ = 0x467f
+ TIOCLINUX = 0x5483
+ TIOCMBIC = 0x741c
+ TIOCMBIS = 0x741b
+ TIOCMGET = 0x741d
+ TIOCMIWAIT = 0x5491
+ TIOCMSET = 0x741a
+ TIOCM_CAR = 0x100
+ TIOCM_CD = 0x100
+ TIOCM_CTS = 0x40
+ TIOCM_DSR = 0x400
+ TIOCM_DTR = 0x2
+ TIOCM_LE = 0x1
+ TIOCM_RI = 0x200
+ TIOCM_RNG = 0x200
+ TIOCM_RTS = 0x4
+ TIOCM_SR = 0x20
+ TIOCM_ST = 0x10
+ TIOCNOTTY = 0x5471
+ TIOCNXCL = 0x740e
+ TIOCOUTQ = 0x7472
+ TIOCPKT = 0x5470
+ TIOCPKT_DATA = 0x0
+ TIOCPKT_DOSTOP = 0x20
+ TIOCPKT_FLUSHREAD = 0x1
+ TIOCPKT_FLUSHWRITE = 0x2
+ TIOCPKT_IOCTL = 0x40
+ TIOCPKT_NOSTOP = 0x10
+ TIOCPKT_START = 0x8
+ TIOCPKT_STOP = 0x4
+ TIOCSBRK = 0x5427
+ TIOCSCTTY = 0x5480
+ TIOCSERCONFIG = 0x5488
+ TIOCSERGETLSR = 0x548e
+ TIOCSERGETMULTI = 0x548f
+ TIOCSERGSTRUCT = 0x548d
+ TIOCSERGWILD = 0x5489
+ TIOCSERSETMULTI = 0x5490
+ TIOCSERSWILD = 0x548a
+ TIOCSER_TEMT = 0x1
+ TIOCSETD = 0x7401
+ TIOCSETN = 0x740a
+ TIOCSETP = 0x7409
+ TIOCSIG = 0x80045436
+ TIOCSLCKTRMIOS = 0x548c
+ TIOCSLTC = 0x7475
+ TIOCSPGRP = 0x80047476
+ TIOCSPTLCK = 0x80045431
+ TIOCSSERIAL = 0x5485
+ TIOCSSOFTCAR = 0x5482
+ TIOCSTI = 0x5472
+ TIOCSWINSZ = 0x80087467
+ TIOCVHANGUP = 0x5437
+ TOSTOP = 0x8000
+ TUNATTACHFILTER = 0x801054d5
+ TUNDETACHFILTER = 0x801054d6
+ TUNGETFEATURES = 0x400454cf
+ TUNGETFILTER = 0x401054db
+ TUNGETIFF = 0x400454d2
+ TUNGETSNDBUF = 0x400454d3
+ TUNGETVNETHDRSZ = 0x400454d7
+ TUNSETDEBUG = 0x800454c9
+ TUNSETGROUP = 0x800454ce
+ TUNSETIFF = 0x800454ca
+ TUNSETIFINDEX = 0x800454da
+ TUNSETLINK = 0x800454cd
+ TUNSETNOCSUM = 0x800454c8
+ TUNSETOFFLOAD = 0x800454d0
+ TUNSETOWNER = 0x800454cc
+ TUNSETPERSIST = 0x800454cb
+ TUNSETQUEUE = 0x800454d9
+ TUNSETSNDBUF = 0x800454d4
+ TUNSETTXFILTER = 0x800454d1
+ TUNSETVNETHDRSZ = 0x800454d8
+ VDISCARD = 0xd
+ VEOF = 0x10
+ VEOL = 0x11
+ VEOL2 = 0x6
+ VERASE = 0x2
+ VINTR = 0x0
+ VKILL = 0x3
+ VLNEXT = 0xf
+ VMIN = 0x4
+ VQUIT = 0x1
+ VREPRINT = 0xc
+ VSTART = 0x8
+ VSTOP = 0x9
+ VSUSP = 0xa
+ VSWTC = 0x7
+ VSWTCH = 0x7
+ VT0 = 0x0
+ VT1 = 0x4000
+ VTDLY = 0x4000
+ VTIME = 0x5
+ VWERASE = 0xe
+ WALL = 0x40000000
+ WCLONE = 0x80000000
+ WCONTINUED = 0x8
+ WEXITED = 0x4
+ WNOHANG = 0x1
+ WNOTHREAD = 0x20000000
+ WNOWAIT = 0x1000000
+ WORDSIZE = 0x40
+ WSTOPPED = 0x2
+ WUNTRACED = 0x2
+)
+
+// Errors
+const (
+ E2BIG = Errno(0x7)
+ EACCES = Errno(0xd)
+ EADDRINUSE = Errno(0x7d)
+ EADDRNOTAVAIL = Errno(0x7e)
+ EADV = Errno(0x44)
+ EAFNOSUPPORT = Errno(0x7c)
+ EAGAIN = Errno(0xb)
+ EALREADY = Errno(0x95)
+ EBADE = Errno(0x32)
+ EBADF = Errno(0x9)
+ EBADFD = Errno(0x51)
+ EBADMSG = Errno(0x4d)
+ EBADR = Errno(0x33)
+ EBADRQC = Errno(0x36)
+ EBADSLT = Errno(0x37)
+ EBFONT = Errno(0x3b)
+ EBUSY = Errno(0x10)
+ ECANCELED = Errno(0x9e)
+ ECHILD = Errno(0xa)
+ ECHRNG = Errno(0x25)
+ ECOMM = Errno(0x46)
+ ECONNABORTED = Errno(0x82)
+ ECONNREFUSED = Errno(0x92)
+ ECONNRESET = Errno(0x83)
+ EDEADLK = Errno(0x2d)
+ EDEADLOCK = Errno(0x38)
+ EDESTADDRREQ = Errno(0x60)
+ EDOM = Errno(0x21)
+ EDOTDOT = Errno(0x49)
+ EDQUOT = Errno(0x46d)
+ EEXIST = Errno(0x11)
+ EFAULT = Errno(0xe)
+ EFBIG = Errno(0x1b)
+ EHOSTDOWN = Errno(0x93)
+ EHOSTUNREACH = Errno(0x94)
+ EHWPOISON = Errno(0xa8)
+ EIDRM = Errno(0x24)
+ EILSEQ = Errno(0x58)
+ EINIT = Errno(0x8d)
+ EINPROGRESS = Errno(0x96)
+ EINTR = Errno(0x4)
+ EINVAL = Errno(0x16)
+ EIO = Errno(0x5)
+ EISCONN = Errno(0x85)
+ EISDIR = Errno(0x15)
+ EISNAM = Errno(0x8b)
+ EKEYEXPIRED = Errno(0xa2)
+ EKEYREJECTED = Errno(0xa4)
+ EKEYREVOKED = Errno(0xa3)
+ EL2HLT = Errno(0x2c)
+ EL2NSYNC = Errno(0x26)
+ EL3HLT = Errno(0x27)
+ EL3RST = Errno(0x28)
+ ELIBACC = Errno(0x53)
+ ELIBBAD = Errno(0x54)
+ ELIBEXEC = Errno(0x57)
+ ELIBMAX = Errno(0x56)
+ ELIBSCN = Errno(0x55)
+ ELNRNG = Errno(0x29)
+ ELOOP = Errno(0x5a)
+ EMEDIUMTYPE = Errno(0xa0)
+ EMFILE = Errno(0x18)
+ EMLINK = Errno(0x1f)
+ EMSGSIZE = Errno(0x61)
+ EMULTIHOP = Errno(0x4a)
+ ENAMETOOLONG = Errno(0x4e)
+ ENAVAIL = Errno(0x8a)
+ ENETDOWN = Errno(0x7f)
+ ENETRESET = Errno(0x81)
+ ENETUNREACH = Errno(0x80)
+ ENFILE = Errno(0x17)
+ ENOANO = Errno(0x35)
+ ENOBUFS = Errno(0x84)
+ ENOCSI = Errno(0x2b)
+ ENODATA = Errno(0x3d)
+ ENODEV = Errno(0x13)
+ ENOENT = Errno(0x2)
+ ENOEXEC = Errno(0x8)
+ ENOKEY = Errno(0xa1)
+ ENOLCK = Errno(0x2e)
+ ENOLINK = Errno(0x43)
+ ENOMEDIUM = Errno(0x9f)
+ ENOMEM = Errno(0xc)
+ ENOMSG = Errno(0x23)
+ ENONET = Errno(0x40)
+ ENOPKG = Errno(0x41)
+ ENOPROTOOPT = Errno(0x63)
+ ENOSPC = Errno(0x1c)
+ ENOSR = Errno(0x3f)
+ ENOSTR = Errno(0x3c)
+ ENOSYS = Errno(0x59)
+ ENOTBLK = Errno(0xf)
+ ENOTCONN = Errno(0x86)
+ ENOTDIR = Errno(0x14)
+ ENOTEMPTY = Errno(0x5d)
+ ENOTNAM = Errno(0x89)
+ ENOTRECOVERABLE = Errno(0xa6)
+ ENOTSOCK = Errno(0x5f)
+ ENOTSUP = Errno(0x7a)
+ ENOTTY = Errno(0x19)
+ ENOTUNIQ = Errno(0x50)
+ ENXIO = Errno(0x6)
+ EOPNOTSUPP = Errno(0x7a)
+ EOVERFLOW = Errno(0x4f)
+ EOWNERDEAD = Errno(0xa5)
+ EPERM = Errno(0x1)
+ EPFNOSUPPORT = Errno(0x7b)
+ EPIPE = Errno(0x20)
+ EPROTO = Errno(0x47)
+ EPROTONOSUPPORT = Errno(0x78)
+ EPROTOTYPE = Errno(0x62)
+ ERANGE = Errno(0x22)
+ EREMCHG = Errno(0x52)
+ EREMDEV = Errno(0x8e)
+ EREMOTE = Errno(0x42)
+ EREMOTEIO = Errno(0x8c)
+ ERESTART = Errno(0x5b)
+ ERFKILL = Errno(0xa7)
+ EROFS = Errno(0x1e)
+ ESHUTDOWN = Errno(0x8f)
+ ESOCKTNOSUPPORT = Errno(0x79)
+ ESPIPE = Errno(0x1d)
+ ESRCH = Errno(0x3)
+ ESRMNT = Errno(0x45)
+ ESTALE = Errno(0x97)
+ ESTRPIPE = Errno(0x5c)
+ ETIME = Errno(0x3e)
+ ETIMEDOUT = Errno(0x91)
+ ETOOMANYREFS = Errno(0x90)
+ ETXTBSY = Errno(0x1a)
+ EUCLEAN = Errno(0x87)
+ EUNATCH = Errno(0x2a)
+ EUSERS = Errno(0x5e)
+ EWOULDBLOCK = Errno(0xb)
+ EXDEV = Errno(0x12)
+ EXFULL = Errno(0x34)
+)
+
+// Signals
+const (
+ SIGABRT = Signal(0x6)
+ SIGALRM = Signal(0xe)
+ SIGBUS = Signal(0xa)
+ SIGCHLD = Signal(0x12)
+ SIGCLD = Signal(0x12)
+ SIGCONT = Signal(0x19)
+ SIGEMT = Signal(0x7)
+ SIGFPE = Signal(0x8)
+ SIGHUP = Signal(0x1)
+ SIGILL = Signal(0x4)
+ SIGINT = Signal(0x2)
+ SIGIO = Signal(0x16)
+ SIGIOT = Signal(0x6)
+ SIGKILL = Signal(0x9)
+ SIGPIPE = Signal(0xd)
+ SIGPOLL = Signal(0x16)
+ SIGPROF = Signal(0x1d)
+ SIGPWR = Signal(0x13)
+ SIGQUIT = Signal(0x3)
+ SIGSEGV = Signal(0xb)
+ SIGSTOP = Signal(0x17)
+ SIGSYS = Signal(0xc)
+ SIGTERM = Signal(0xf)
+ SIGTRAP = Signal(0x5)
+ SIGTSTP = Signal(0x18)
+ SIGTTIN = Signal(0x1a)
+ SIGTTOU = Signal(0x1b)
+ SIGURG = Signal(0x15)
+ SIGUSR1 = Signal(0x10)
+ SIGUSR2 = Signal(0x11)
+ SIGVTALRM = Signal(0x1c)
+ SIGWINCH = Signal(0x14)
+ SIGXCPU = Signal(0x1e)
+ SIGXFSZ = Signal(0x1f)
+)
+
+// Error table
+var errors = [...]string{
+ 1: "operation not permitted",
+ 2: "no such file or directory",
+ 3: "no such process",
+ 4: "interrupted system call",
+ 5: "input/output error",
+ 6: "no such device or address",
+ 7: "argument list too long",
+ 8: "exec format error",
+ 9: "bad file descriptor",
+ 10: "no child processes",
+ 11: "resource temporarily unavailable",
+ 12: "cannot allocate memory",
+ 13: "permission denied",
+ 14: "bad address",
+ 15: "block device required",
+ 16: "device or resource busy",
+ 17: "file exists",
+ 18: "invalid cross-device link",
+ 19: "no such device",
+ 20: "not a directory",
+ 21: "is a directory",
+ 22: "invalid argument",
+ 23: "too many open files in system",
+ 24: "too many open files",
+ 25: "inappropriate ioctl for device",
+ 26: "text file busy",
+ 27: "file too large",
+ 28: "no space left on device",
+ 29: "illegal seek",
+ 30: "read-only file system",
+ 31: "too many links",
+ 32: "broken pipe",
+ 33: "numerical argument out of domain",
+ 34: "numerical result out of range",
+ 35: "no message of desired type",
+ 36: "identifier removed",
+ 37: "channel number out of range",
+ 38: "level 2 not synchronized",
+ 39: "level 3 halted",
+ 40: "level 3 reset",
+ 41: "link number out of range",
+ 42: "protocol driver not attached",
+ 43: "no CSI structure available",
+ 44: "level 2 halted",
+ 45: "resource deadlock avoided",
+ 46: "no locks available",
+ 50: "invalid exchange",
+ 51: "invalid request descriptor",
+ 52: "exchange full",
+ 53: "no anode",
+ 54: "invalid request code",
+ 55: "invalid slot",
+ 56: "file locking deadlock error",
+ 59: "bad font file format",
+ 60: "device not a stream",
+ 61: "no data available",
+ 62: "timer expired",
+ 63: "out of streams resources",
+ 64: "machine is not on the network",
+ 65: "package not installed",
+ 66: "object is remote",
+ 67: "link has been severed",
+ 68: "advertise error",
+ 69: "srmount error",
+ 70: "communication error on send",
+ 71: "protocol error",
+ 73: "RFS specific error",
+ 74: "multihop attempted",
+ 77: "bad message",
+ 78: "file name too long",
+ 79: "value too large for defined data type",
+ 80: "name not unique on network",
+ 81: "file descriptor in bad state",
+ 82: "remote address changed",
+ 83: "can not access a needed shared library",
+ 84: "accessing a corrupted shared library",
+ 85: ".lib section in a.out corrupted",
+ 86: "attempting to link in too many shared libraries",
+ 87: "cannot exec a shared library directly",
+ 88: "invalid or incomplete multibyte or wide character",
+ 89: "function not implemented",
+ 90: "too many levels of symbolic links",
+ 91: "interrupted system call should be restarted",
+ 92: "streams pipe error",
+ 93: "directory not empty",
+ 94: "too many users",
+ 95: "socket operation on non-socket",
+ 96: "destination address required",
+ 97: "message too long",
+ 98: "protocol wrong type for socket",
+ 99: "protocol not available",
+ 120: "protocol not supported",
+ 121: "socket type not supported",
+ 122: "operation not supported",
+ 123: "protocol family not supported",
+ 124: "address family not supported by protocol",
+ 125: "address already in use",
+ 126: "cannot assign requested address",
+ 127: "network is down",
+ 128: "network is unreachable",
+ 129: "network dropped connection on reset",
+ 130: "software caused connection abort",
+ 131: "connection reset by peer",
+ 132: "no buffer space available",
+ 133: "transport endpoint is already connected",
+ 134: "transport endpoint is not connected",
+ 135: "structure needs cleaning",
+ 137: "not a XENIX named type file",
+ 138: "no XENIX semaphores available",
+ 139: "is a named type file",
+ 140: "remote I/O error",
+ 141: "unknown error 141",
+ 142: "unknown error 142",
+ 143: "cannot send after transport endpoint shutdown",
+ 144: "too many references: cannot splice",
+ 145: "connection timed out",
+ 146: "connection refused",
+ 147: "host is down",
+ 148: "no route to host",
+ 149: "operation already in progress",
+ 150: "operation now in progress",
+ 151: "stale NFS file handle",
+ 158: "operation canceled",
+ 159: "no medium found",
+ 160: "wrong medium type",
+ 161: "required key not available",
+ 162: "key has expired",
+ 163: "key has been revoked",
+ 164: "key was rejected by service",
+ 165: "owner died",
+ 166: "state not recoverable",
+ 167: "operation not possible due to RF-kill",
+ 168: "memory page has hardware error",
+ 1133: "disk quota exceeded",
+}
+
+// Signal table
+var signals = [...]string{
+ 1: "hangup",
+ 2: "interrupt",
+ 3: "quit",
+ 4: "illegal instruction",
+ 5: "trace/breakpoint trap",
+ 6: "aborted",
+ 7: "EMT trap",
+ 8: "floating point exception",
+ 9: "killed",
+ 10: "bus error",
+ 11: "segmentation fault",
+ 12: "bad system call",
+ 13: "broken pipe",
+ 14: "alarm clock",
+ 15: "terminated",
+ 16: "user defined signal 1",
+ 17: "user defined signal 2",
+ 18: "child exited",
+ 19: "power failure",
+ 20: "window changed",
+ 21: "urgent I/O condition",
+ 22: "I/O possible",
+ 23: "stopped (signal)",
+ 24: "stopped",
+ 25: "continued",
+ 26: "stopped (tty input)",
+ 27: "stopped (tty output)",
+ 28: "virtual timer expired",
+ 29: "profiling timer expired",
+ 30: "CPU time limit exceeded",
+ 31: "file size limit exceeded",
+}
} else {
_p0 = unsafe.Pointer(&_zero)
}
- r0, _, e1 := Syscall(SYS_GETDENTS64, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
+ r0, _, e1 := Syscall(_SYS_getdents, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
} else {
_p0 = unsafe.Pointer(&_zero)
}
- r0, _, e1 := Syscall(SYS_GETDENTS64, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
+ r0, _, e1 := Syscall(_SYS_getdents, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
} else {
_p0 = unsafe.Pointer(&_zero)
}
- r0, _, e1 := Syscall(SYS_GETDENTS64, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
+ r0, _, e1 := Syscall(_SYS_getdents, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
} else {
_p0 = unsafe.Pointer(&_zero)
}
- r0, _, e1 := Syscall(SYS_GETDENTS64, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
+ r0, _, e1 := Syscall(_SYS_getdents, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
--- /dev/null
+// mksyscall.pl syscall_linux.go syscall_linux_mips64x.go
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+
+package syscall
+
+import "unsafe"
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(oldpath)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(newpath)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall6(SYS_LINKAT, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ r0, _, e1 := Syscall6(SYS_OPENAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mode), 0, 0)
+ use(unsafe.Pointer(_p0))
+ fd = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func readlinkat(dirfd int, path string, buf []byte) (n int, err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ var _p1 unsafe.Pointer
+ if len(buf) > 0 {
+ _p1 = unsafe.Pointer(&buf[0])
+ } else {
+ _p1 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall6(SYS_READLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)), 0, 0)
+ use(unsafe.Pointer(_p0))
+ n = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func symlinkat(oldpath string, newdirfd int, newpath string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(oldpath)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(newpath)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_SYMLINKAT, uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)))
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func unlinkat(dirfd int, path string, flags int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_UNLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags))
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func utimes(path string, times *[2]Timeval) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), 0)
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func utimensat(dirfd int, path string, times *[2]Timespec) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)))
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func futimesat(dirfd int, path *byte, times *[2]Timeval) (err error) {
+ _, _, e1 := Syscall(SYS_FUTIMESAT, uintptr(dirfd), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(times)))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getcwd(buf []byte) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(buf) > 0 {
+ _p0 = unsafe.Pointer(&buf[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_GETCWD, uintptr(_p0), uintptr(len(buf)), 0)
+ n = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) {
+ r0, _, e1 := Syscall6(SYS_WAIT4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0)
+ wpid = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
+ _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func reboot(magic1 uint, magic2 uint, cmd int, arg string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(arg)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall6(SYS_REBOOT, uintptr(magic1), uintptr(magic2), uintptr(cmd), uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func mount(source string, target string, fstype string, flags uintptr, data *byte) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(source)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(target)
+ if err != nil {
+ return
+ }
+ var _p2 *byte
+ _p2, err = BytePtrFromString(fstype)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall6(SYS_MOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(_p2)), uintptr(flags), uintptr(unsafe.Pointer(data)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
+ use(unsafe.Pointer(_p2))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Acct(path string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_ACCT, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Adjtimex(buf *Timex) (state int, err error) {
+ r0, _, e1 := Syscall(SYS_ADJTIMEX, uintptr(unsafe.Pointer(buf)), 0, 0)
+ state = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Chdir(path string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Chroot(path string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Close(fd int) (err error) {
+ _, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Dup(oldfd int) (fd int, err error) {
+ r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), 0, 0)
+ fd = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Dup3(oldfd int, newfd int, flags int) (err error) {
+ _, _, e1 := Syscall(SYS_DUP3, uintptr(oldfd), uintptr(newfd), uintptr(flags))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func EpollCreate(size int) (fd int, err error) {
+ r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0)
+ fd = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func EpollCreate1(flag int) (fd int, err error) {
+ r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE1, uintptr(flag), 0, 0)
+ fd = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) {
+ _, _, e1 := RawSyscall6(SYS_EPOLL_CTL, uintptr(epfd), uintptr(op), uintptr(fd), uintptr(unsafe.Pointer(event)), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(events) > 0 {
+ _p0 = unsafe.Pointer(&events[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall6(SYS_EPOLL_WAIT, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec), 0, 0)
+ n = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Exit(code int) {
+ Syscall(SYS_EXIT_GROUP, uintptr(code), 0, 0)
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall6(SYS_FACCESSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0)
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fallocate(fd int, mode uint32, off int64, len int64) (err error) {
+ _, _, e1 := Syscall6(SYS_FALLOCATE, uintptr(fd), uintptr(mode), uintptr(off), uintptr(len), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchdir(fd int) (err error) {
+ _, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchmod(fd int, mode uint32) (err error) {
+ _, _, e1 := Syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0)
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall6(SYS_FCHOWNAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func fcntl(fd int, cmd int, arg int) (val int, err error) {
+ r0, _, e1 := Syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg))
+ val = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fdatasync(fd int) (err error) {
+ _, _, e1 := Syscall(SYS_FDATASYNC, uintptr(fd), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Flock(fd int, how int) (err error) {
+ _, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fsync(fd int) (err error) {
+ _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getdents(fd int, buf []byte) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(buf) > 0 {
+ _p0 = unsafe.Pointer(&buf[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(_SYS_getdents, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
+ n = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getpgid(pid int) (pgid int, err error) {
+ r0, _, e1 := RawSyscall(SYS_GETPGID, uintptr(pid), 0, 0)
+ pgid = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getpid() (pid int) {
+ r0, _, _ := RawSyscall(SYS_GETPID, 0, 0, 0)
+ pid = int(r0)
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getppid() (ppid int) {
+ r0, _, _ := RawSyscall(SYS_GETPPID, 0, 0, 0)
+ ppid = int(r0)
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getpriority(which int, who int) (prio int, err error) {
+ r0, _, e1 := Syscall(SYS_GETPRIORITY, uintptr(which), uintptr(who), 0)
+ prio = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getrusage(who int, rusage *Rusage) (err error) {
+ _, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Gettid() (tid int) {
+ r0, _, _ := RawSyscall(SYS_GETTID, 0, 0, 0)
+ tid = int(r0)
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getxattr(path string, attr string, dest []byte) (sz int, err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(attr)
+ if err != nil {
+ return
+ }
+ var _p2 unsafe.Pointer
+ if len(dest) > 0 {
+ _p2 = unsafe.Pointer(&dest[0])
+ } else {
+ _p2 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall6(SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
+ sz = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(pathname)
+ if err != nil {
+ return
+ }
+ r0, _, e1 := Syscall(SYS_INOTIFY_ADD_WATCH, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(mask))
+ use(unsafe.Pointer(_p0))
+ watchdesc = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func InotifyInit1(flags int) (fd int, err error) {
+ r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT1, uintptr(flags), 0, 0)
+ fd = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func InotifyRmWatch(fd int, watchdesc uint32) (success int, err error) {
+ r0, _, e1 := RawSyscall(SYS_INOTIFY_RM_WATCH, uintptr(fd), uintptr(watchdesc), 0)
+ success = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Kill(pid int, sig Signal) (err error) {
+ _, _, e1 := RawSyscall(SYS_KILL, uintptr(pid), uintptr(sig), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Klogctl(typ int, buf []byte) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(buf) > 0 {
+ _p0 = unsafe.Pointer(&buf[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_SYSLOG, uintptr(typ), uintptr(_p0), uintptr(len(buf)))
+ n = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Listxattr(path string, dest []byte) (sz int, err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ var _p1 unsafe.Pointer
+ if len(dest) > 0 {
+ _p1 = unsafe.Pointer(&dest[0])
+ } else {
+ _p1 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_LISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)))
+ use(unsafe.Pointer(_p0))
+ sz = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mkdirat(dirfd int, path string, mode uint32) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_MKDIRAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode))
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall6(SYS_MKNODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0)
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Nanosleep(time *Timespec, leftover *Timespec) (err error) {
+ _, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pause() (err error) {
+ _, _, e1 := Syscall(SYS_PAUSE, 0, 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func PivotRoot(newroot string, putold string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(newroot)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(putold)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_PIVOT_ROOT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) {
+ _, _, e1 := RawSyscall6(SYS_PRLIMIT64, uintptr(pid), uintptr(resource), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(newlimit)), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func read(fd int, p []byte) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(p) > 0 {
+ _p0 = unsafe.Pointer(&p[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(_p0), uintptr(len(p)))
+ n = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Removexattr(path string, attr string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(attr)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_REMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(oldpath)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(newpath)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall6(SYS_RENAMEAT, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)), 0, 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setdomainname(p []byte) (err error) {
+ var _p0 unsafe.Pointer
+ if len(p) > 0 {
+ _p0 = unsafe.Pointer(&p[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ _, _, e1 := Syscall(SYS_SETDOMAINNAME, uintptr(_p0), uintptr(len(p)), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Sethostname(p []byte) (err error) {
+ var _p0 unsafe.Pointer
+ if len(p) > 0 {
+ _p0 = unsafe.Pointer(&p[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ _, _, e1 := Syscall(SYS_SETHOSTNAME, uintptr(_p0), uintptr(len(p)), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setpgid(pid int, pgid int) (err error) {
+ _, _, e1 := RawSyscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setsid() (pid int, err error) {
+ r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0)
+ pid = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Settimeofday(tv *Timeval) (err error) {
+ _, _, e1 := RawSyscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setpriority(which int, who int, prio int) (err error) {
+ _, _, e1 := Syscall(SYS_SETPRIORITY, uintptr(which), uintptr(who), uintptr(prio))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setxattr(path string, attr string, data []byte, flags int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(attr)
+ if err != nil {
+ return
+ }
+ var _p2 unsafe.Pointer
+ if len(data) > 0 {
+ _p2 = unsafe.Pointer(&data[0])
+ } else {
+ _p2 = unsafe.Pointer(&_zero)
+ }
+ _, _, e1 := Syscall6(SYS_SETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Sync() {
+ Syscall(SYS_SYNC, 0, 0, 0)
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Sysinfo(info *Sysinfo_t) (err error) {
+ _, _, e1 := RawSyscall(SYS_SYSINFO, uintptr(unsafe.Pointer(info)), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
+ r0, _, e1 := Syscall6(SYS_TEE, uintptr(rfd), uintptr(wfd), uintptr(len), uintptr(flags), 0, 0)
+ n = int64(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Tgkill(tgid int, tid int, sig Signal) (err error) {
+ _, _, e1 := RawSyscall(SYS_TGKILL, uintptr(tgid), uintptr(tid), uintptr(sig))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Times(tms *Tms) (ticks uintptr, err error) {
+ r0, _, e1 := RawSyscall(SYS_TIMES, uintptr(unsafe.Pointer(tms)), 0, 0)
+ ticks = uintptr(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Umask(mask int) (oldmask int) {
+ r0, _, _ := RawSyscall(SYS_UMASK, uintptr(mask), 0, 0)
+ oldmask = int(r0)
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Uname(buf *Utsname) (err error) {
+ _, _, e1 := RawSyscall(SYS_UNAME, uintptr(unsafe.Pointer(buf)), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Unmount(target string, flags int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(target)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_UMOUNT2, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Unshare(flags int) (err error) {
+ _, _, e1 := Syscall(SYS_UNSHARE, uintptr(flags), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Ustat(dev int, ubuf *Ustat_t) (err error) {
+ _, _, e1 := Syscall(SYS_USTAT, uintptr(dev), uintptr(unsafe.Pointer(ubuf)), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Utime(path string, buf *Utimbuf) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_UTIME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(buf)), 0)
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func write(fd int, p []byte) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(p) > 0 {
+ _p0 = unsafe.Pointer(&p[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)))
+ n = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func exitThread(code int) (err error) {
+ _, _, e1 := Syscall(SYS_EXIT, uintptr(code), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func readlen(fd int, p *byte, np int) (n int, err error) {
+ r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(np))
+ n = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func writelen(fd int, p *byte, np int) (n int, err error) {
+ r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(np))
+ n = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func munmap(addr uintptr, length uintptr) (err error) {
+ _, _, e1 := Syscall(SYS_MUNMAP, uintptr(addr), uintptr(length), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Madvise(b []byte, advice int) (err error) {
+ var _p0 unsafe.Pointer
+ if len(b) > 0 {
+ _p0 = unsafe.Pointer(&b[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ _, _, e1 := Syscall(SYS_MADVISE, uintptr(_p0), uintptr(len(b)), uintptr(advice))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mprotect(b []byte, prot int) (err error) {
+ var _p0 unsafe.Pointer
+ if len(b) > 0 {
+ _p0 = unsafe.Pointer(&b[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ _, _, e1 := Syscall(SYS_MPROTECT, uintptr(_p0), uintptr(len(b)), uintptr(prot))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mlock(b []byte) (err error) {
+ var _p0 unsafe.Pointer
+ if len(b) > 0 {
+ _p0 = unsafe.Pointer(&b[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ _, _, e1 := Syscall(SYS_MLOCK, uintptr(_p0), uintptr(len(b)), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Munlock(b []byte) (err error) {
+ var _p0 unsafe.Pointer
+ if len(b) > 0 {
+ _p0 = unsafe.Pointer(&b[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ _, _, e1 := Syscall(SYS_MUNLOCK, uintptr(_p0), uintptr(len(b)), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mlockall(flags int) (err error) {
+ _, _, e1 := Syscall(SYS_MLOCKALL, uintptr(flags), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Munlockall() (err error) {
+ _, _, e1 := Syscall(SYS_MUNLOCKALL, 0, 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Dup2(oldfd int, newfd int) (err error) {
+ _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchown(fd int, uid int, gid int) (err error) {
+ _, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fstatfs(fd int, buf *Statfs_t) (err error) {
+ _, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(buf)), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Ftruncate(fd int, length int64) (err error) {
+ _, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), uintptr(length), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getegid() (egid int) {
+ r0, _, _ := RawSyscall(SYS_GETEGID, 0, 0, 0)
+ egid = int(r0)
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Geteuid() (euid int) {
+ r0, _, _ := RawSyscall(SYS_GETEUID, 0, 0, 0)
+ euid = int(r0)
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getgid() (gid int) {
+ r0, _, _ := RawSyscall(SYS_GETGID, 0, 0, 0)
+ gid = int(r0)
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getrlimit(resource int, rlim *Rlimit) (err error) {
+ _, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getuid() (uid int) {
+ r0, _, _ := RawSyscall(SYS_GETUID, 0, 0, 0)
+ uid = int(r0)
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func InotifyInit() (fd int, err error) {
+ r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0)
+ fd = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Lchown(path string, uid int, gid int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Listen(s int, n int) (err error) {
+ _, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(n), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pread(fd int, p []byte, offset int64) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(p) > 0 {
+ _p0 = unsafe.Pointer(&p[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall6(SYS_PREAD64, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0)
+ n = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(p) > 0 {
+ _p0 = unsafe.Pointer(&p[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall6(SYS_PWRITE64, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0)
+ n = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Seek(fd int, offset int64, whence int) (off int64, err error) {
+ r0, _, e1 := Syscall(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(whence))
+ off = int64(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) {
+ r0, _, e1 := Syscall6(SYS_PSELECT6, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0)
+ n = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
+ r0, _, e1 := Syscall6(SYS_SENDFILE, uintptr(outfd), uintptr(infd), uintptr(unsafe.Pointer(offset)), uintptr(count), 0, 0)
+ written = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setfsgid(gid int) (err error) {
+ _, _, e1 := Syscall(SYS_SETFSGID, uintptr(gid), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setfsuid(uid int) (err error) {
+ _, _, e1 := Syscall(SYS_SETFSUID, uintptr(uid), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setregid(rgid int, egid int) (err error) {
+ _, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setresgid(rgid int, egid int, sgid int) (err error) {
+ _, _, e1 := RawSyscall(SYS_SETRESGID, uintptr(rgid), uintptr(egid), uintptr(sgid))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setresuid(ruid int, euid int, suid int) (err error) {
+ _, _, e1 := RawSyscall(SYS_SETRESUID, uintptr(ruid), uintptr(euid), uintptr(suid))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setrlimit(resource int, rlim *Rlimit) (err error) {
+ _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setreuid(ruid int, euid int) (err error) {
+ _, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Shutdown(fd int, how int) (err error) {
+ _, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) {
+ r0, _, e1 := Syscall6(SYS_SPLICE, uintptr(rfd), uintptr(unsafe.Pointer(roff)), uintptr(wfd), uintptr(unsafe.Pointer(woff)), uintptr(len), uintptr(flags))
+ n = int64(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Statfs(path string, buf *Statfs_t) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(buf)), 0)
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func SyncFileRange(fd int, off int64, n int64, flags int) (err error) {
+ _, _, e1 := Syscall6(SYS_SYNC_FILE_RANGE, uintptr(fd), uintptr(off), uintptr(n), uintptr(flags), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Truncate(path string, length int64) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), uintptr(length), 0)
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) {
+ r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
+ fd = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) {
+ r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0)
+ fd = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) {
+ _, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) {
+ _, _, e1 := Syscall(SYS_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getgroups(n int, list *_Gid_t) (nn int, err error) {
+ r0, _, e1 := RawSyscall(SYS_GETGROUPS, uintptr(n), uintptr(unsafe.Pointer(list)), 0)
+ nn = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func setgroups(n int, list *_Gid_t) (err error) {
+ _, _, e1 := RawSyscall(SYS_SETGROUPS, uintptr(n), uintptr(unsafe.Pointer(list)), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) {
+ _, _, e1 := Syscall6(SYS_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) {
+ _, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func socket(domain int, typ int, proto int) (fd int, err error) {
+ r0, _, e1 := RawSyscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto))
+ fd = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) {
+ _, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
+ _, _, e1 := RawSyscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
+ _, _, e1 := RawSyscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(p) > 0 {
+ _p0 = unsafe.Pointer(&p[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)))
+ n = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) {
+ var _p0 unsafe.Pointer
+ if len(buf) > 0 {
+ _p0 = unsafe.Pointer(&buf[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ _, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) {
+ r0, _, e1 := Syscall(SYS_RECVMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
+ n = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) {
+ r0, _, e1 := Syscall(SYS_SENDMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
+ n = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) {
+ r0, _, e1 := Syscall6(SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(offset))
+ xaddr = uintptr(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Gettimeofday(tv *Timeval) (err error) {
+ _, _, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func pipe2(p *[2]_C_int, flags int) (err error) {
+ _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func fstat(fd int, stat *stat_t) (err error) {
+ _, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func lstat(path string, stat *stat_t) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func stat(path string, stat *stat_t) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
--- /dev/null
+// mksyscall.pl syscall_linux.go syscall_linux_mips64x.go
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+
+package syscall
+
+import "unsafe"
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(oldpath)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(newpath)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall6(SYS_LINKAT, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ r0, _, e1 := Syscall6(SYS_OPENAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mode), 0, 0)
+ use(unsafe.Pointer(_p0))
+ fd = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func readlinkat(dirfd int, path string, buf []byte) (n int, err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ var _p1 unsafe.Pointer
+ if len(buf) > 0 {
+ _p1 = unsafe.Pointer(&buf[0])
+ } else {
+ _p1 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall6(SYS_READLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)), 0, 0)
+ use(unsafe.Pointer(_p0))
+ n = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func symlinkat(oldpath string, newdirfd int, newpath string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(oldpath)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(newpath)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_SYMLINKAT, uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)))
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func unlinkat(dirfd int, path string, flags int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_UNLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags))
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func utimes(path string, times *[2]Timeval) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), 0)
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func utimensat(dirfd int, path string, times *[2]Timespec) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)))
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func futimesat(dirfd int, path *byte, times *[2]Timeval) (err error) {
+ _, _, e1 := Syscall(SYS_FUTIMESAT, uintptr(dirfd), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(times)))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getcwd(buf []byte) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(buf) > 0 {
+ _p0 = unsafe.Pointer(&buf[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_GETCWD, uintptr(_p0), uintptr(len(buf)), 0)
+ n = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) {
+ r0, _, e1 := Syscall6(SYS_WAIT4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0)
+ wpid = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
+ _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func reboot(magic1 uint, magic2 uint, cmd int, arg string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(arg)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall6(SYS_REBOOT, uintptr(magic1), uintptr(magic2), uintptr(cmd), uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func mount(source string, target string, fstype string, flags uintptr, data *byte) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(source)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(target)
+ if err != nil {
+ return
+ }
+ var _p2 *byte
+ _p2, err = BytePtrFromString(fstype)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall6(SYS_MOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(_p2)), uintptr(flags), uintptr(unsafe.Pointer(data)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
+ use(unsafe.Pointer(_p2))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Acct(path string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_ACCT, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Adjtimex(buf *Timex) (state int, err error) {
+ r0, _, e1 := Syscall(SYS_ADJTIMEX, uintptr(unsafe.Pointer(buf)), 0, 0)
+ state = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Chdir(path string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Chroot(path string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Close(fd int) (err error) {
+ _, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Dup(oldfd int) (fd int, err error) {
+ r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), 0, 0)
+ fd = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Dup3(oldfd int, newfd int, flags int) (err error) {
+ _, _, e1 := Syscall(SYS_DUP3, uintptr(oldfd), uintptr(newfd), uintptr(flags))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func EpollCreate(size int) (fd int, err error) {
+ r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0)
+ fd = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func EpollCreate1(flag int) (fd int, err error) {
+ r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE1, uintptr(flag), 0, 0)
+ fd = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) {
+ _, _, e1 := RawSyscall6(SYS_EPOLL_CTL, uintptr(epfd), uintptr(op), uintptr(fd), uintptr(unsafe.Pointer(event)), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(events) > 0 {
+ _p0 = unsafe.Pointer(&events[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall6(SYS_EPOLL_WAIT, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec), 0, 0)
+ n = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Exit(code int) {
+ Syscall(SYS_EXIT_GROUP, uintptr(code), 0, 0)
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall6(SYS_FACCESSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0)
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fallocate(fd int, mode uint32, off int64, len int64) (err error) {
+ _, _, e1 := Syscall6(SYS_FALLOCATE, uintptr(fd), uintptr(mode), uintptr(off), uintptr(len), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchdir(fd int) (err error) {
+ _, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchmod(fd int, mode uint32) (err error) {
+ _, _, e1 := Syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0)
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall6(SYS_FCHOWNAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func fcntl(fd int, cmd int, arg int) (val int, err error) {
+ r0, _, e1 := Syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg))
+ val = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fdatasync(fd int) (err error) {
+ _, _, e1 := Syscall(SYS_FDATASYNC, uintptr(fd), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Flock(fd int, how int) (err error) {
+ _, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fsync(fd int) (err error) {
+ _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getdents(fd int, buf []byte) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(buf) > 0 {
+ _p0 = unsafe.Pointer(&buf[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(_SYS_getdents, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
+ n = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getpgid(pid int) (pgid int, err error) {
+ r0, _, e1 := RawSyscall(SYS_GETPGID, uintptr(pid), 0, 0)
+ pgid = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getpid() (pid int) {
+ r0, _, _ := RawSyscall(SYS_GETPID, 0, 0, 0)
+ pid = int(r0)
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getppid() (ppid int) {
+ r0, _, _ := RawSyscall(SYS_GETPPID, 0, 0, 0)
+ ppid = int(r0)
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getpriority(which int, who int) (prio int, err error) {
+ r0, _, e1 := Syscall(SYS_GETPRIORITY, uintptr(which), uintptr(who), 0)
+ prio = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getrusage(who int, rusage *Rusage) (err error) {
+ _, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Gettid() (tid int) {
+ r0, _, _ := RawSyscall(SYS_GETTID, 0, 0, 0)
+ tid = int(r0)
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getxattr(path string, attr string, dest []byte) (sz int, err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(attr)
+ if err != nil {
+ return
+ }
+ var _p2 unsafe.Pointer
+ if len(dest) > 0 {
+ _p2 = unsafe.Pointer(&dest[0])
+ } else {
+ _p2 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall6(SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
+ sz = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(pathname)
+ if err != nil {
+ return
+ }
+ r0, _, e1 := Syscall(SYS_INOTIFY_ADD_WATCH, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(mask))
+ use(unsafe.Pointer(_p0))
+ watchdesc = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func InotifyInit1(flags int) (fd int, err error) {
+ r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT1, uintptr(flags), 0, 0)
+ fd = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func InotifyRmWatch(fd int, watchdesc uint32) (success int, err error) {
+ r0, _, e1 := RawSyscall(SYS_INOTIFY_RM_WATCH, uintptr(fd), uintptr(watchdesc), 0)
+ success = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Kill(pid int, sig Signal) (err error) {
+ _, _, e1 := RawSyscall(SYS_KILL, uintptr(pid), uintptr(sig), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Klogctl(typ int, buf []byte) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(buf) > 0 {
+ _p0 = unsafe.Pointer(&buf[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_SYSLOG, uintptr(typ), uintptr(_p0), uintptr(len(buf)))
+ n = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Listxattr(path string, dest []byte) (sz int, err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ var _p1 unsafe.Pointer
+ if len(dest) > 0 {
+ _p1 = unsafe.Pointer(&dest[0])
+ } else {
+ _p1 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_LISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)))
+ use(unsafe.Pointer(_p0))
+ sz = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mkdirat(dirfd int, path string, mode uint32) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_MKDIRAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode))
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall6(SYS_MKNODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0)
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Nanosleep(time *Timespec, leftover *Timespec) (err error) {
+ _, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pause() (err error) {
+ _, _, e1 := Syscall(SYS_PAUSE, 0, 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func PivotRoot(newroot string, putold string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(newroot)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(putold)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_PIVOT_ROOT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) {
+ _, _, e1 := RawSyscall6(SYS_PRLIMIT64, uintptr(pid), uintptr(resource), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(newlimit)), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func read(fd int, p []byte) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(p) > 0 {
+ _p0 = unsafe.Pointer(&p[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(_p0), uintptr(len(p)))
+ n = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Removexattr(path string, attr string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(attr)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_REMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(oldpath)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(newpath)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall6(SYS_RENAMEAT, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)), 0, 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setdomainname(p []byte) (err error) {
+ var _p0 unsafe.Pointer
+ if len(p) > 0 {
+ _p0 = unsafe.Pointer(&p[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ _, _, e1 := Syscall(SYS_SETDOMAINNAME, uintptr(_p0), uintptr(len(p)), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Sethostname(p []byte) (err error) {
+ var _p0 unsafe.Pointer
+ if len(p) > 0 {
+ _p0 = unsafe.Pointer(&p[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ _, _, e1 := Syscall(SYS_SETHOSTNAME, uintptr(_p0), uintptr(len(p)), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setpgid(pid int, pgid int) (err error) {
+ _, _, e1 := RawSyscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setsid() (pid int, err error) {
+ r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0)
+ pid = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Settimeofday(tv *Timeval) (err error) {
+ _, _, e1 := RawSyscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setpriority(which int, who int, prio int) (err error) {
+ _, _, e1 := Syscall(SYS_SETPRIORITY, uintptr(which), uintptr(who), uintptr(prio))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setxattr(path string, attr string, data []byte, flags int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(attr)
+ if err != nil {
+ return
+ }
+ var _p2 unsafe.Pointer
+ if len(data) > 0 {
+ _p2 = unsafe.Pointer(&data[0])
+ } else {
+ _p2 = unsafe.Pointer(&_zero)
+ }
+ _, _, e1 := Syscall6(SYS_SETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Sync() {
+ Syscall(SYS_SYNC, 0, 0, 0)
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Sysinfo(info *Sysinfo_t) (err error) {
+ _, _, e1 := RawSyscall(SYS_SYSINFO, uintptr(unsafe.Pointer(info)), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
+ r0, _, e1 := Syscall6(SYS_TEE, uintptr(rfd), uintptr(wfd), uintptr(len), uintptr(flags), 0, 0)
+ n = int64(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Tgkill(tgid int, tid int, sig Signal) (err error) {
+ _, _, e1 := RawSyscall(SYS_TGKILL, uintptr(tgid), uintptr(tid), uintptr(sig))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Times(tms *Tms) (ticks uintptr, err error) {
+ r0, _, e1 := RawSyscall(SYS_TIMES, uintptr(unsafe.Pointer(tms)), 0, 0)
+ ticks = uintptr(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Umask(mask int) (oldmask int) {
+ r0, _, _ := RawSyscall(SYS_UMASK, uintptr(mask), 0, 0)
+ oldmask = int(r0)
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Uname(buf *Utsname) (err error) {
+ _, _, e1 := RawSyscall(SYS_UNAME, uintptr(unsafe.Pointer(buf)), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Unmount(target string, flags int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(target)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_UMOUNT2, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Unshare(flags int) (err error) {
+ _, _, e1 := Syscall(SYS_UNSHARE, uintptr(flags), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Ustat(dev int, ubuf *Ustat_t) (err error) {
+ _, _, e1 := Syscall(SYS_USTAT, uintptr(dev), uintptr(unsafe.Pointer(ubuf)), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Utime(path string, buf *Utimbuf) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_UTIME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(buf)), 0)
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func write(fd int, p []byte) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(p) > 0 {
+ _p0 = unsafe.Pointer(&p[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)))
+ n = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func exitThread(code int) (err error) {
+ _, _, e1 := Syscall(SYS_EXIT, uintptr(code), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func readlen(fd int, p *byte, np int) (n int, err error) {
+ r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(np))
+ n = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func writelen(fd int, p *byte, np int) (n int, err error) {
+ r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(np))
+ n = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func munmap(addr uintptr, length uintptr) (err error) {
+ _, _, e1 := Syscall(SYS_MUNMAP, uintptr(addr), uintptr(length), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Madvise(b []byte, advice int) (err error) {
+ var _p0 unsafe.Pointer
+ if len(b) > 0 {
+ _p0 = unsafe.Pointer(&b[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ _, _, e1 := Syscall(SYS_MADVISE, uintptr(_p0), uintptr(len(b)), uintptr(advice))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mprotect(b []byte, prot int) (err error) {
+ var _p0 unsafe.Pointer
+ if len(b) > 0 {
+ _p0 = unsafe.Pointer(&b[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ _, _, e1 := Syscall(SYS_MPROTECT, uintptr(_p0), uintptr(len(b)), uintptr(prot))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mlock(b []byte) (err error) {
+ var _p0 unsafe.Pointer
+ if len(b) > 0 {
+ _p0 = unsafe.Pointer(&b[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ _, _, e1 := Syscall(SYS_MLOCK, uintptr(_p0), uintptr(len(b)), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Munlock(b []byte) (err error) {
+ var _p0 unsafe.Pointer
+ if len(b) > 0 {
+ _p0 = unsafe.Pointer(&b[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ _, _, e1 := Syscall(SYS_MUNLOCK, uintptr(_p0), uintptr(len(b)), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mlockall(flags int) (err error) {
+ _, _, e1 := Syscall(SYS_MLOCKALL, uintptr(flags), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Munlockall() (err error) {
+ _, _, e1 := Syscall(SYS_MUNLOCKALL, 0, 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Dup2(oldfd int, newfd int) (err error) {
+ _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchown(fd int, uid int, gid int) (err error) {
+ _, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fstatfs(fd int, buf *Statfs_t) (err error) {
+ _, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(buf)), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Ftruncate(fd int, length int64) (err error) {
+ _, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), uintptr(length), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getegid() (egid int) {
+ r0, _, _ := RawSyscall(SYS_GETEGID, 0, 0, 0)
+ egid = int(r0)
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Geteuid() (euid int) {
+ r0, _, _ := RawSyscall(SYS_GETEUID, 0, 0, 0)
+ euid = int(r0)
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getgid() (gid int) {
+ r0, _, _ := RawSyscall(SYS_GETGID, 0, 0, 0)
+ gid = int(r0)
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getrlimit(resource int, rlim *Rlimit) (err error) {
+ _, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getuid() (uid int) {
+ r0, _, _ := RawSyscall(SYS_GETUID, 0, 0, 0)
+ uid = int(r0)
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func InotifyInit() (fd int, err error) {
+ r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0)
+ fd = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Lchown(path string, uid int, gid int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Listen(s int, n int) (err error) {
+ _, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(n), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pread(fd int, p []byte, offset int64) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(p) > 0 {
+ _p0 = unsafe.Pointer(&p[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall6(SYS_PREAD64, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0)
+ n = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(p) > 0 {
+ _p0 = unsafe.Pointer(&p[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall6(SYS_PWRITE64, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0)
+ n = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Seek(fd int, offset int64, whence int) (off int64, err error) {
+ r0, _, e1 := Syscall(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(whence))
+ off = int64(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) {
+ r0, _, e1 := Syscall6(SYS_PSELECT6, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0)
+ n = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
+ r0, _, e1 := Syscall6(SYS_SENDFILE, uintptr(outfd), uintptr(infd), uintptr(unsafe.Pointer(offset)), uintptr(count), 0, 0)
+ written = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setfsgid(gid int) (err error) {
+ _, _, e1 := Syscall(SYS_SETFSGID, uintptr(gid), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setfsuid(uid int) (err error) {
+ _, _, e1 := Syscall(SYS_SETFSUID, uintptr(uid), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setregid(rgid int, egid int) (err error) {
+ _, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setresgid(rgid int, egid int, sgid int) (err error) {
+ _, _, e1 := RawSyscall(SYS_SETRESGID, uintptr(rgid), uintptr(egid), uintptr(sgid))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setresuid(ruid int, euid int, suid int) (err error) {
+ _, _, e1 := RawSyscall(SYS_SETRESUID, uintptr(ruid), uintptr(euid), uintptr(suid))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setrlimit(resource int, rlim *Rlimit) (err error) {
+ _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setreuid(ruid int, euid int) (err error) {
+ _, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Shutdown(fd int, how int) (err error) {
+ _, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) {
+ r0, _, e1 := Syscall6(SYS_SPLICE, uintptr(rfd), uintptr(unsafe.Pointer(roff)), uintptr(wfd), uintptr(unsafe.Pointer(woff)), uintptr(len), uintptr(flags))
+ n = int64(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Statfs(path string, buf *Statfs_t) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(buf)), 0)
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func SyncFileRange(fd int, off int64, n int64, flags int) (err error) {
+ _, _, e1 := Syscall6(SYS_SYNC_FILE_RANGE, uintptr(fd), uintptr(off), uintptr(n), uintptr(flags), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Truncate(path string, length int64) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), uintptr(length), 0)
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) {
+ r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
+ fd = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) {
+ r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0)
+ fd = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) {
+ _, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) {
+ _, _, e1 := Syscall(SYS_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getgroups(n int, list *_Gid_t) (nn int, err error) {
+ r0, _, e1 := RawSyscall(SYS_GETGROUPS, uintptr(n), uintptr(unsafe.Pointer(list)), 0)
+ nn = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func setgroups(n int, list *_Gid_t) (err error) {
+ _, _, e1 := RawSyscall(SYS_SETGROUPS, uintptr(n), uintptr(unsafe.Pointer(list)), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) {
+ _, _, e1 := Syscall6(SYS_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) {
+ _, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func socket(domain int, typ int, proto int) (fd int, err error) {
+ r0, _, e1 := RawSyscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto))
+ fd = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) {
+ _, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
+ _, _, e1 := RawSyscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
+ _, _, e1 := RawSyscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(p) > 0 {
+ _p0 = unsafe.Pointer(&p[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)))
+ n = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) {
+ var _p0 unsafe.Pointer
+ if len(buf) > 0 {
+ _p0 = unsafe.Pointer(&buf[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ _, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) {
+ r0, _, e1 := Syscall(SYS_RECVMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
+ n = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) {
+ r0, _, e1 := Syscall(SYS_SENDMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
+ n = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) {
+ r0, _, e1 := Syscall6(SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(offset))
+ xaddr = uintptr(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Gettimeofday(tv *Timeval) (err error) {
+ _, _, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func pipe2(p *[2]_C_int, flags int) (err error) {
+ _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func fstat(fd int, stat *stat_t) (err error) {
+ _, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func lstat(path string, stat *stat_t) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func stat(path string, stat *stat_t) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+ use(unsafe.Pointer(_p0))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
} else {
_p0 = unsafe.Pointer(&_zero)
}
- r0, _, e1 := Syscall(SYS_GETDENTS64, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
+ r0, _, e1 := Syscall(_SYS_getdents, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
} else {
_p0 = unsafe.Pointer(&_zero)
}
- r0, _, e1 := Syscall(SYS_GETDENTS64, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
+ r0, _, e1 := Syscall(_SYS_getdents, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
--- /dev/null
+// mksysnum_linux.pl /usr/include/asm/unistd.h
+// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
+
+package syscall
+
+const (
+ SYS_READ = 5000
+ SYS_WRITE = 5001
+ SYS_OPEN = 5002
+ SYS_CLOSE = 5003
+ SYS_STAT = 5004
+ SYS_FSTAT = 5005
+ SYS_LSTAT = 5006
+ SYS_POLL = 5007
+ SYS_LSEEK = 5008
+ SYS_MMAP = 5009
+ SYS_MPROTECT = 5010
+ SYS_MUNMAP = 5011
+ SYS_BRK = 5012
+ SYS_RT_SIGACTION = 5013
+ SYS_RT_SIGPROCMASK = 5014
+ SYS_IOCTL = 5015
+ SYS_PREAD64 = 5016
+ SYS_PWRITE64 = 5017
+ SYS_READV = 5018
+ SYS_WRITEV = 5019
+ SYS_ACCESS = 5020
+ SYS_PIPE = 5021
+ SYS__NEWSELECT = 5022
+ SYS_SCHED_YIELD = 5023
+ SYS_MREMAP = 5024
+ SYS_MSYNC = 5025
+ SYS_MINCORE = 5026
+ SYS_MADVISE = 5027
+ SYS_SHMGET = 5028
+ SYS_SHMAT = 5029
+ SYS_SHMCTL = 5030
+ SYS_DUP = 5031
+ SYS_DUP2 = 5032
+ SYS_PAUSE = 5033
+ SYS_NANOSLEEP = 5034
+ SYS_GETITIMER = 5035
+ SYS_SETITIMER = 5036
+ SYS_ALARM = 5037
+ SYS_GETPID = 5038
+ SYS_SENDFILE = 5039
+ SYS_SOCKET = 5040
+ SYS_CONNECT = 5041
+ SYS_ACCEPT = 5042
+ SYS_SENDTO = 5043
+ SYS_RECVFROM = 5044
+ SYS_SENDMSG = 5045
+ SYS_RECVMSG = 5046
+ SYS_SHUTDOWN = 5047
+ SYS_BIND = 5048
+ SYS_LISTEN = 5049
+ SYS_GETSOCKNAME = 5050
+ SYS_GETPEERNAME = 5051
+ SYS_SOCKETPAIR = 5052
+ SYS_SETSOCKOPT = 5053
+ SYS_GETSOCKOPT = 5054
+ SYS_CLONE = 5055
+ SYS_FORK = 5056
+ SYS_EXECVE = 5057
+ SYS_EXIT = 5058
+ SYS_WAIT4 = 5059
+ SYS_KILL = 5060
+ SYS_UNAME = 5061
+ SYS_SEMGET = 5062
+ SYS_SEMOP = 5063
+ SYS_SEMCTL = 5064
+ SYS_SHMDT = 5065
+ SYS_MSGGET = 5066
+ SYS_MSGSND = 5067
+ SYS_MSGRCV = 5068
+ SYS_MSGCTL = 5069
+ SYS_FCNTL = 5070
+ SYS_FLOCK = 5071
+ SYS_FSYNC = 5072
+ SYS_FDATASYNC = 5073
+ SYS_TRUNCATE = 5074
+ SYS_FTRUNCATE = 5075
+ SYS_GETDENTS = 5076
+ SYS_GETCWD = 5077
+ SYS_CHDIR = 5078
+ SYS_FCHDIR = 5079
+ SYS_RENAME = 5080
+ SYS_MKDIR = 5081
+ SYS_RMDIR = 5082
+ SYS_CREAT = 5083
+ SYS_LINK = 5084
+ SYS_UNLINK = 5085
+ SYS_SYMLINK = 5086
+ SYS_READLINK = 5087
+ SYS_CHMOD = 5088
+ SYS_FCHMOD = 5089
+ SYS_CHOWN = 5090
+ SYS_FCHOWN = 5091
+ SYS_LCHOWN = 5092
+ SYS_UMASK = 5093
+ SYS_GETTIMEOFDAY = 5094
+ SYS_GETRLIMIT = 5095
+ SYS_GETRUSAGE = 5096
+ SYS_SYSINFO = 5097
+ SYS_TIMES = 5098
+ SYS_PTRACE = 5099
+ SYS_GETUID = 5100
+ SYS_SYSLOG = 5101
+ SYS_GETGID = 5102
+ SYS_SETUID = 5103
+ SYS_SETGID = 5104
+ SYS_GETEUID = 5105
+ SYS_GETEGID = 5106
+ SYS_SETPGID = 5107
+ SYS_GETPPID = 5108
+ SYS_GETPGRP = 5109
+ SYS_SETSID = 5110
+ SYS_SETREUID = 5111
+ SYS_SETREGID = 5112
+ SYS_GETGROUPS = 5113
+ SYS_SETGROUPS = 5114
+ SYS_SETRESUID = 5115
+ SYS_GETRESUID = 5116
+ SYS_SETRESGID = 5117
+ SYS_GETRESGID = 5118
+ SYS_GETPGID = 5119
+ SYS_SETFSUID = 5120
+ SYS_SETFSGID = 5121
+ SYS_GETSID = 5122
+ SYS_CAPGET = 5123
+ SYS_CAPSET = 5124
+ SYS_RT_SIGPENDING = 5125
+ SYS_RT_SIGTIMEDWAIT = 5126
+ SYS_RT_SIGQUEUEINFO = 5127
+ SYS_RT_SIGSUSPEND = 5128
+ SYS_SIGALTSTACK = 5129
+ SYS_UTIME = 5130
+ SYS_MKNOD = 5131
+ SYS_PERSONALITY = 5132
+ SYS_USTAT = 5133
+ SYS_STATFS = 5134
+ SYS_FSTATFS = 5135
+ SYS_SYSFS = 5136
+ SYS_GETPRIORITY = 5137
+ SYS_SETPRIORITY = 5138
+ SYS_SCHED_SETPARAM = 5139
+ SYS_SCHED_GETPARAM = 5140
+ SYS_SCHED_SETSCHEDULER = 5141
+ SYS_SCHED_GETSCHEDULER = 5142
+ SYS_SCHED_GET_PRIORITY_MAX = 5143
+ SYS_SCHED_GET_PRIORITY_MIN = 5144
+ SYS_SCHED_RR_GET_INTERVAL = 5145
+ SYS_MLOCK = 5146
+ SYS_MUNLOCK = 5147
+ SYS_MLOCKALL = 5148
+ SYS_MUNLOCKALL = 5149
+ SYS_VHANGUP = 5150
+ SYS_PIVOT_ROOT = 5151
+ SYS__SYSCTL = 5152
+ SYS_PRCTL = 5153
+ SYS_ADJTIMEX = 5154
+ SYS_SETRLIMIT = 5155
+ SYS_CHROOT = 5156
+ SYS_SYNC = 5157
+ SYS_ACCT = 5158
+ SYS_SETTIMEOFDAY = 5159
+ SYS_MOUNT = 5160
+ SYS_UMOUNT2 = 5161
+ SYS_SWAPON = 5162
+ SYS_SWAPOFF = 5163
+ SYS_REBOOT = 5164
+ SYS_SETHOSTNAME = 5165
+ SYS_SETDOMAINNAME = 5166
+ SYS_CREATE_MODULE = 5167
+ SYS_INIT_MODULE = 5168
+ SYS_DELETE_MODULE = 5169
+ SYS_GET_KERNEL_SYMS = 5170
+ SYS_QUERY_MODULE = 5171
+ SYS_QUOTACTL = 5172
+ SYS_NFSSERVCTL = 5173
+ SYS_GETPMSG = 5174
+ SYS_PUTPMSG = 5175
+ SYS_AFS_SYSCALL = 5176
+ SYS_RESERVED177 = 5177
+ SYS_GETTID = 5178
+ SYS_READAHEAD = 5179
+ SYS_SETXATTR = 5180
+ SYS_LSETXATTR = 5181
+ SYS_FSETXATTR = 5182
+ SYS_GETXATTR = 5183
+ SYS_LGETXATTR = 5184
+ SYS_FGETXATTR = 5185
+ SYS_LISTXATTR = 5186
+ SYS_LLISTXATTR = 5187
+ SYS_FLISTXATTR = 5188
+ SYS_REMOVEXATTR = 5189
+ SYS_LREMOVEXATTR = 5190
+ SYS_FREMOVEXATTR = 5191
+ SYS_TKILL = 5192
+ SYS_RESERVED193 = 5193
+ SYS_FUTEX = 5194
+ SYS_SCHED_SETAFFINITY = 5195
+ SYS_SCHED_GETAFFINITY = 5196
+ SYS_CACHEFLUSH = 5197
+ SYS_CACHECTL = 5198
+ SYS_SYSMIPS = 5199
+ SYS_IO_SETUP = 5200
+ SYS_IO_DESTROY = 5201
+ SYS_IO_GETEVENTS = 5202
+ SYS_IO_SUBMIT = 5203
+ SYS_IO_CANCEL = 5204
+ SYS_EXIT_GROUP = 5205
+ SYS_LOOKUP_DCOOKIE = 5206
+ SYS_EPOLL_CREATE = 5207
+ SYS_EPOLL_CTL = 5208
+ SYS_EPOLL_WAIT = 5209
+ SYS_REMAP_FILE_PAGES = 5210
+ SYS_RT_SIGRETURN = 5211
+ SYS_SET_TID_ADDRESS = 5212
+ SYS_RESTART_SYSCALL = 5213
+ SYS_SEMTIMEDOP = 5214
+ SYS_FADVISE64 = 5215
+ SYS_TIMER_CREATE = 5216
+ SYS_TIMER_SETTIME = 5217
+ SYS_TIMER_GETTIME = 5218
+ SYS_TIMER_GETOVERRUN = 5219
+ SYS_TIMER_DELETE = 5220
+ SYS_CLOCK_SETTIME = 5221
+ SYS_CLOCK_GETTIME = 5222
+ SYS_CLOCK_GETRES = 5223
+ SYS_CLOCK_NANOSLEEP = 5224
+ SYS_TGKILL = 5225
+ SYS_UTIMES = 5226
+ SYS_MBIND = 5227
+ SYS_GET_MEMPOLICY = 5228
+ SYS_SET_MEMPOLICY = 5229
+ SYS_MQ_OPEN = 5230
+ SYS_MQ_UNLINK = 5231
+ SYS_MQ_TIMEDSEND = 5232
+ SYS_MQ_TIMEDRECEIVE = 5233
+ SYS_MQ_NOTIFY = 5234
+ SYS_MQ_GETSETATTR = 5235
+ SYS_VSERVER = 5236
+ SYS_WAITID = 5237
+ SYS_ADD_KEY = 5239
+ SYS_REQUEST_KEY = 5240
+ SYS_KEYCTL = 5241
+ SYS_SET_THREAD_AREA = 5242
+ SYS_INOTIFY_INIT = 5243
+ SYS_INOTIFY_ADD_WATCH = 5244
+ SYS_INOTIFY_RM_WATCH = 5245
+ SYS_MIGRATE_PAGES = 5246
+ SYS_OPENAT = 5247
+ SYS_MKDIRAT = 5248
+ SYS_MKNODAT = 5249
+ SYS_FCHOWNAT = 5250
+ SYS_FUTIMESAT = 5251
+ SYS_NEWFSTATAT = 5252
+ SYS_UNLINKAT = 5253
+ SYS_RENAMEAT = 5254
+ SYS_LINKAT = 5255
+ SYS_SYMLINKAT = 5256
+ SYS_READLINKAT = 5257
+ SYS_FCHMODAT = 5258
+ SYS_FACCESSAT = 5259
+ SYS_PSELECT6 = 5260
+ SYS_PPOLL = 5261
+ SYS_UNSHARE = 5262
+ SYS_SPLICE = 5263
+ SYS_SYNC_FILE_RANGE = 5264
+ SYS_TEE = 5265
+ SYS_VMSPLICE = 5266
+ SYS_MOVE_PAGES = 5267
+ SYS_SET_ROBUST_LIST = 5268
+ SYS_GET_ROBUST_LIST = 5269
+ SYS_KEXEC_LOAD = 5270
+ SYS_GETCPU = 5271
+ SYS_EPOLL_PWAIT = 5272
+ SYS_IOPRIO_SET = 5273
+ SYS_IOPRIO_GET = 5274
+ SYS_UTIMENSAT = 5275
+ SYS_SIGNALFD = 5276
+ SYS_TIMERFD = 5277
+ SYS_EVENTFD = 5278
+ SYS_FALLOCATE = 5279
+ SYS_TIMERFD_CREATE = 5280
+ SYS_TIMERFD_GETTIME = 5281
+ SYS_TIMERFD_SETTIME = 5282
+ SYS_SIGNALFD4 = 5283
+ SYS_EVENTFD2 = 5284
+ SYS_EPOLL_CREATE1 = 5285
+ SYS_DUP3 = 5286
+ SYS_PIPE2 = 5287
+ SYS_INOTIFY_INIT1 = 5288
+ SYS_PREADV = 5289
+ SYS_PWRITEV = 5290
+ SYS_RT_TGSIGQUEUEINFO = 5291
+ SYS_PERF_EVENT_OPEN = 5292
+ SYS_ACCEPT4 = 5293
+ SYS_RECVMMSG = 5294
+ SYS_FANOTIFY_INIT = 5295
+ SYS_FANOTIFY_MARK = 5296
+ SYS_PRLIMIT64 = 5297
+ SYS_NAME_TO_HANDLE_AT = 5298
+ SYS_OPEN_BY_HANDLE_AT = 5299
+ SYS_CLOCK_ADJTIME = 5300
+ SYS_SYNCFS = 5301
+ SYS_SENDMMSG = 5302
+ SYS_SETNS = 5303
+ SYS_PROCESS_VM_READV = 5304
+ SYS_PROCESS_VM_WRITEV = 5305
+ SYS_KCMP = 5306
+ SYS_FINIT_MODULE = 5307
+ SYS_GETDENTS64 = 5308
+ SYS_SCHED_SETATTR = 5309
+ SYS_SCHED_GETATTR = 5310
+ SYS_RENAMEAT2 = 5311
+ SYS_SECCOMP = 5312
+ SYS_GETRANDOM = 5313
+ SYS_MEMFD_CREATE = 5314
+ SYS_BPF = 5315
+ SYS_EXECVEAT = 5316
+)
--- /dev/null
+// mksysnum_linux.pl /usr/include/asm/unistd.h
+// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
+
+package syscall
+
+const (
+ SYS_READ = 5000
+ SYS_WRITE = 5001
+ SYS_OPEN = 5002
+ SYS_CLOSE = 5003
+ SYS_STAT = 5004
+ SYS_FSTAT = 5005
+ SYS_LSTAT = 5006
+ SYS_POLL = 5007
+ SYS_LSEEK = 5008
+ SYS_MMAP = 5009
+ SYS_MPROTECT = 5010
+ SYS_MUNMAP = 5011
+ SYS_BRK = 5012
+ SYS_RT_SIGACTION = 5013
+ SYS_RT_SIGPROCMASK = 5014
+ SYS_IOCTL = 5015
+ SYS_PREAD64 = 5016
+ SYS_PWRITE64 = 5017
+ SYS_READV = 5018
+ SYS_WRITEV = 5019
+ SYS_ACCESS = 5020
+ SYS_PIPE = 5021
+ SYS__NEWSELECT = 5022
+ SYS_SCHED_YIELD = 5023
+ SYS_MREMAP = 5024
+ SYS_MSYNC = 5025
+ SYS_MINCORE = 5026
+ SYS_MADVISE = 5027
+ SYS_SHMGET = 5028
+ SYS_SHMAT = 5029
+ SYS_SHMCTL = 5030
+ SYS_DUP = 5031
+ SYS_DUP2 = 5032
+ SYS_PAUSE = 5033
+ SYS_NANOSLEEP = 5034
+ SYS_GETITIMER = 5035
+ SYS_SETITIMER = 5036
+ SYS_ALARM = 5037
+ SYS_GETPID = 5038
+ SYS_SENDFILE = 5039
+ SYS_SOCKET = 5040
+ SYS_CONNECT = 5041
+ SYS_ACCEPT = 5042
+ SYS_SENDTO = 5043
+ SYS_RECVFROM = 5044
+ SYS_SENDMSG = 5045
+ SYS_RECVMSG = 5046
+ SYS_SHUTDOWN = 5047
+ SYS_BIND = 5048
+ SYS_LISTEN = 5049
+ SYS_GETSOCKNAME = 5050
+ SYS_GETPEERNAME = 5051
+ SYS_SOCKETPAIR = 5052
+ SYS_SETSOCKOPT = 5053
+ SYS_GETSOCKOPT = 5054
+ SYS_CLONE = 5055
+ SYS_FORK = 5056
+ SYS_EXECVE = 5057
+ SYS_EXIT = 5058
+ SYS_WAIT4 = 5059
+ SYS_KILL = 5060
+ SYS_UNAME = 5061
+ SYS_SEMGET = 5062
+ SYS_SEMOP = 5063
+ SYS_SEMCTL = 5064
+ SYS_SHMDT = 5065
+ SYS_MSGGET = 5066
+ SYS_MSGSND = 5067
+ SYS_MSGRCV = 5068
+ SYS_MSGCTL = 5069
+ SYS_FCNTL = 5070
+ SYS_FLOCK = 5071
+ SYS_FSYNC = 5072
+ SYS_FDATASYNC = 5073
+ SYS_TRUNCATE = 5074
+ SYS_FTRUNCATE = 5075
+ SYS_GETDENTS = 5076
+ SYS_GETCWD = 5077
+ SYS_CHDIR = 5078
+ SYS_FCHDIR = 5079
+ SYS_RENAME = 5080
+ SYS_MKDIR = 5081
+ SYS_RMDIR = 5082
+ SYS_CREAT = 5083
+ SYS_LINK = 5084
+ SYS_UNLINK = 5085
+ SYS_SYMLINK = 5086
+ SYS_READLINK = 5087
+ SYS_CHMOD = 5088
+ SYS_FCHMOD = 5089
+ SYS_CHOWN = 5090
+ SYS_FCHOWN = 5091
+ SYS_LCHOWN = 5092
+ SYS_UMASK = 5093
+ SYS_GETTIMEOFDAY = 5094
+ SYS_GETRLIMIT = 5095
+ SYS_GETRUSAGE = 5096
+ SYS_SYSINFO = 5097
+ SYS_TIMES = 5098
+ SYS_PTRACE = 5099
+ SYS_GETUID = 5100
+ SYS_SYSLOG = 5101
+ SYS_GETGID = 5102
+ SYS_SETUID = 5103
+ SYS_SETGID = 5104
+ SYS_GETEUID = 5105
+ SYS_GETEGID = 5106
+ SYS_SETPGID = 5107
+ SYS_GETPPID = 5108
+ SYS_GETPGRP = 5109
+ SYS_SETSID = 5110
+ SYS_SETREUID = 5111
+ SYS_SETREGID = 5112
+ SYS_GETGROUPS = 5113
+ SYS_SETGROUPS = 5114
+ SYS_SETRESUID = 5115
+ SYS_GETRESUID = 5116
+ SYS_SETRESGID = 5117
+ SYS_GETRESGID = 5118
+ SYS_GETPGID = 5119
+ SYS_SETFSUID = 5120
+ SYS_SETFSGID = 5121
+ SYS_GETSID = 5122
+ SYS_CAPGET = 5123
+ SYS_CAPSET = 5124
+ SYS_RT_SIGPENDING = 5125
+ SYS_RT_SIGTIMEDWAIT = 5126
+ SYS_RT_SIGQUEUEINFO = 5127
+ SYS_RT_SIGSUSPEND = 5128
+ SYS_SIGALTSTACK = 5129
+ SYS_UTIME = 5130
+ SYS_MKNOD = 5131
+ SYS_PERSONALITY = 5132
+ SYS_USTAT = 5133
+ SYS_STATFS = 5134
+ SYS_FSTATFS = 5135
+ SYS_SYSFS = 5136
+ SYS_GETPRIORITY = 5137
+ SYS_SETPRIORITY = 5138
+ SYS_SCHED_SETPARAM = 5139
+ SYS_SCHED_GETPARAM = 5140
+ SYS_SCHED_SETSCHEDULER = 5141
+ SYS_SCHED_GETSCHEDULER = 5142
+ SYS_SCHED_GET_PRIORITY_MAX = 5143
+ SYS_SCHED_GET_PRIORITY_MIN = 5144
+ SYS_SCHED_RR_GET_INTERVAL = 5145
+ SYS_MLOCK = 5146
+ SYS_MUNLOCK = 5147
+ SYS_MLOCKALL = 5148
+ SYS_MUNLOCKALL = 5149
+ SYS_VHANGUP = 5150
+ SYS_PIVOT_ROOT = 5151
+ SYS__SYSCTL = 5152
+ SYS_PRCTL = 5153
+ SYS_ADJTIMEX = 5154
+ SYS_SETRLIMIT = 5155
+ SYS_CHROOT = 5156
+ SYS_SYNC = 5157
+ SYS_ACCT = 5158
+ SYS_SETTIMEOFDAY = 5159
+ SYS_MOUNT = 5160
+ SYS_UMOUNT2 = 5161
+ SYS_SWAPON = 5162
+ SYS_SWAPOFF = 5163
+ SYS_REBOOT = 5164
+ SYS_SETHOSTNAME = 5165
+ SYS_SETDOMAINNAME = 5166
+ SYS_CREATE_MODULE = 5167
+ SYS_INIT_MODULE = 5168
+ SYS_DELETE_MODULE = 5169
+ SYS_GET_KERNEL_SYMS = 5170
+ SYS_QUERY_MODULE = 5171
+ SYS_QUOTACTL = 5172
+ SYS_NFSSERVCTL = 5173
+ SYS_GETPMSG = 5174
+ SYS_PUTPMSG = 5175
+ SYS_AFS_SYSCALL = 5176
+ SYS_RESERVED177 = 5177
+ SYS_GETTID = 5178
+ SYS_READAHEAD = 5179
+ SYS_SETXATTR = 5180
+ SYS_LSETXATTR = 5181
+ SYS_FSETXATTR = 5182
+ SYS_GETXATTR = 5183
+ SYS_LGETXATTR = 5184
+ SYS_FGETXATTR = 5185
+ SYS_LISTXATTR = 5186
+ SYS_LLISTXATTR = 5187
+ SYS_FLISTXATTR = 5188
+ SYS_REMOVEXATTR = 5189
+ SYS_LREMOVEXATTR = 5190
+ SYS_FREMOVEXATTR = 5191
+ SYS_TKILL = 5192
+ SYS_RESERVED193 = 5193
+ SYS_FUTEX = 5194
+ SYS_SCHED_SETAFFINITY = 5195
+ SYS_SCHED_GETAFFINITY = 5196
+ SYS_CACHEFLUSH = 5197
+ SYS_CACHECTL = 5198
+ SYS_SYSMIPS = 5199
+ SYS_IO_SETUP = 5200
+ SYS_IO_DESTROY = 5201
+ SYS_IO_GETEVENTS = 5202
+ SYS_IO_SUBMIT = 5203
+ SYS_IO_CANCEL = 5204
+ SYS_EXIT_GROUP = 5205
+ SYS_LOOKUP_DCOOKIE = 5206
+ SYS_EPOLL_CREATE = 5207
+ SYS_EPOLL_CTL = 5208
+ SYS_EPOLL_WAIT = 5209
+ SYS_REMAP_FILE_PAGES = 5210
+ SYS_RT_SIGRETURN = 5211
+ SYS_SET_TID_ADDRESS = 5212
+ SYS_RESTART_SYSCALL = 5213
+ SYS_SEMTIMEDOP = 5214
+ SYS_FADVISE64 = 5215
+ SYS_TIMER_CREATE = 5216
+ SYS_TIMER_SETTIME = 5217
+ SYS_TIMER_GETTIME = 5218
+ SYS_TIMER_GETOVERRUN = 5219
+ SYS_TIMER_DELETE = 5220
+ SYS_CLOCK_SETTIME = 5221
+ SYS_CLOCK_GETTIME = 5222
+ SYS_CLOCK_GETRES = 5223
+ SYS_CLOCK_NANOSLEEP = 5224
+ SYS_TGKILL = 5225
+ SYS_UTIMES = 5226
+ SYS_MBIND = 5227
+ SYS_GET_MEMPOLICY = 5228
+ SYS_SET_MEMPOLICY = 5229
+ SYS_MQ_OPEN = 5230
+ SYS_MQ_UNLINK = 5231
+ SYS_MQ_TIMEDSEND = 5232
+ SYS_MQ_TIMEDRECEIVE = 5233
+ SYS_MQ_NOTIFY = 5234
+ SYS_MQ_GETSETATTR = 5235
+ SYS_VSERVER = 5236
+ SYS_WAITID = 5237
+ SYS_ADD_KEY = 5239
+ SYS_REQUEST_KEY = 5240
+ SYS_KEYCTL = 5241
+ SYS_SET_THREAD_AREA = 5242
+ SYS_INOTIFY_INIT = 5243
+ SYS_INOTIFY_ADD_WATCH = 5244
+ SYS_INOTIFY_RM_WATCH = 5245
+ SYS_MIGRATE_PAGES = 5246
+ SYS_OPENAT = 5247
+ SYS_MKDIRAT = 5248
+ SYS_MKNODAT = 5249
+ SYS_FCHOWNAT = 5250
+ SYS_FUTIMESAT = 5251
+ SYS_NEWFSTATAT = 5252
+ SYS_UNLINKAT = 5253
+ SYS_RENAMEAT = 5254
+ SYS_LINKAT = 5255
+ SYS_SYMLINKAT = 5256
+ SYS_READLINKAT = 5257
+ SYS_FCHMODAT = 5258
+ SYS_FACCESSAT = 5259
+ SYS_PSELECT6 = 5260
+ SYS_PPOLL = 5261
+ SYS_UNSHARE = 5262
+ SYS_SPLICE = 5263
+ SYS_SYNC_FILE_RANGE = 5264
+ SYS_TEE = 5265
+ SYS_VMSPLICE = 5266
+ SYS_MOVE_PAGES = 5267
+ SYS_SET_ROBUST_LIST = 5268
+ SYS_GET_ROBUST_LIST = 5269
+ SYS_KEXEC_LOAD = 5270
+ SYS_GETCPU = 5271
+ SYS_EPOLL_PWAIT = 5272
+ SYS_IOPRIO_SET = 5273
+ SYS_IOPRIO_GET = 5274
+ SYS_UTIMENSAT = 5275
+ SYS_SIGNALFD = 5276
+ SYS_TIMERFD = 5277
+ SYS_EVENTFD = 5278
+ SYS_FALLOCATE = 5279
+ SYS_TIMERFD_CREATE = 5280
+ SYS_TIMERFD_GETTIME = 5281
+ SYS_TIMERFD_SETTIME = 5282
+ SYS_SIGNALFD4 = 5283
+ SYS_EVENTFD2 = 5284
+ SYS_EPOLL_CREATE1 = 5285
+ SYS_DUP3 = 5286
+ SYS_PIPE2 = 5287
+ SYS_INOTIFY_INIT1 = 5288
+ SYS_PREADV = 5289
+ SYS_PWRITEV = 5290
+ SYS_RT_TGSIGQUEUEINFO = 5291
+ SYS_PERF_EVENT_OPEN = 5292
+ SYS_ACCEPT4 = 5293
+ SYS_RECVMMSG = 5294
+ SYS_FANOTIFY_INIT = 5295
+ SYS_FANOTIFY_MARK = 5296
+ SYS_PRLIMIT64 = 5297
+ SYS_NAME_TO_HANDLE_AT = 5298
+ SYS_OPEN_BY_HANDLE_AT = 5299
+ SYS_CLOCK_ADJTIME = 5300
+ SYS_SYNCFS = 5301
+ SYS_SENDMMSG = 5302
+ SYS_SETNS = 5303
+ SYS_PROCESS_VM_READV = 5304
+ SYS_PROCESS_VM_WRITEV = 5305
+ SYS_KCMP = 5306
+ SYS_FINIT_MODULE = 5307
+ SYS_GETDENTS64 = 5308
+ SYS_SCHED_SETATTR = 5309
+ SYS_SCHED_GETATTR = 5310
+ SYS_RENAMEAT2 = 5311
+ SYS_SECCOMP = 5312
+ SYS_GETRANDOM = 5313
+ SYS_MEMFD_CREATE = 5314
+ SYS_BPF = 5315
+ SYS_EXECVEAT = 5316
+)
--- /dev/null
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs types_linux.go
+
+package syscall
+
+const (
+ sizeofPtr = 0x8
+ sizeofShort = 0x2
+ sizeofInt = 0x4
+ sizeofLong = 0x8
+ sizeofLongLong = 0x8
+ PathMax = 0x1000
+)
+
+type (
+ _C_short int16
+ _C_int int32
+ _C_long int64
+ _C_long_long int64
+)
+
+type Timespec struct {
+ Sec int64
+ Nsec int64
+}
+
+type Timeval struct {
+ Sec int64
+ Usec int64
+}
+
+type Timex struct {
+ Modes uint32
+ Pad_cgo_0 [4]byte
+ Offset int64
+ Freq int64
+ Maxerror int64
+ Esterror int64
+ Status int32
+ Pad_cgo_1 [4]byte
+ Constant int64
+ Precision int64
+ Tolerance int64
+ Time Timeval
+ Tick int64
+ Ppsfreq int64
+ Jitter int64
+ Shift int32
+ Pad_cgo_2 [4]byte
+ Stabil int64
+ Jitcnt int64
+ Calcnt int64
+ Errcnt int64
+ Stbcnt int64
+ Tai int32
+ Pad_cgo_3 [44]byte
+}
+
+type Time_t int64
+
+type Tms struct {
+ Utime int64
+ Stime int64
+ Cutime int64
+ Cstime int64
+}
+
+type Utimbuf struct {
+ Actime int64
+ Modtime int64
+}
+
+type Rusage struct {
+ Utime Timeval
+ Stime Timeval
+ Maxrss int64
+ Ixrss int64
+ Idrss int64
+ Isrss int64
+ Minflt int64
+ Majflt int64
+ Nswap int64
+ Inblock int64
+ Oublock int64
+ Msgsnd int64
+ Msgrcv int64
+ Nsignals int64
+ Nvcsw int64
+ Nivcsw int64
+}
+
+type Rlimit struct {
+ Cur uint64
+ Max uint64
+}
+
+type _Gid_t uint32
+
+type Stat_t struct {
+ Dev uint32
+ Pad1 [3]int32
+ Ino uint64
+ Mode uint32
+ Nlink uint32
+ Uid uint32
+ Gid uint32
+ Rdev uint32
+ Pad2 [3]uint32
+ Size int64
+ Atim Timespec
+ Mtim Timespec
+ Ctim Timespec
+ Blksize uint32
+ Pad4 uint32
+ Blocks int64
+}
+
+type Statfs_t struct {
+ Type int64
+ Bsize int64
+ Frsize int64
+ Blocks uint64
+ Bfree uint64
+ Files uint64
+ Ffree uint64
+ Bavail uint64
+ Fsid Fsid
+ Namelen int64
+ Flags int64
+ Spare [5]int64
+}
+
+// Note: on mips64, we're using the getdents syscall,
+// so the Dirent struct is different.
+
+type Dirent struct {
+ Ino uint64
+ Off int64
+ Reclen uint16
+ Name [256]int8
+ Type uint8
+ Pad_cgo_0 [5]byte
+}
+
+type Fsid struct {
+ X__val [2]int32
+}
+
+type Flock_t struct {
+ Type int16
+ Whence int16
+ Pad_cgo_0 [4]byte
+ Start int64
+ Len int64
+ Pid int32
+ Pad_cgo_1 [4]byte
+}
+
+type RawSockaddrInet4 struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ Zero [8]uint8
+}
+
+type RawSockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+type RawSockaddrUnix struct {
+ Family uint16
+ Path [108]int8
+}
+
+type RawSockaddrLinklayer struct {
+ Family uint16
+ Protocol uint16
+ Ifindex int32
+ Hatype uint16
+ Pkttype uint8
+ Halen uint8
+ Addr [8]uint8
+}
+
+type RawSockaddrNetlink struct {
+ Family uint16
+ Pad uint16
+ Pid uint32
+ Groups uint32
+}
+
+type RawSockaddr struct {
+ Family uint16
+ Data [14]int8
+}
+
+type RawSockaddrAny struct {
+ Addr RawSockaddr
+ Pad [96]int8
+}
+
+type _Socklen uint32
+
+type Linger struct {
+ Onoff int32
+ Linger int32
+}
+
+type Iovec struct {
+ Base *byte
+ Len uint64
+}
+
+type IPMreq struct {
+ Multiaddr [4]byte /* in_addr */
+ Interface [4]byte /* in_addr */
+}
+
+type IPMreqn struct {
+ Multiaddr [4]byte /* in_addr */
+ Address [4]byte /* in_addr */
+ Ifindex int32
+}
+
+type IPv6Mreq struct {
+ Multiaddr [16]byte /* in6_addr */
+ Interface uint32
+}
+
+type Msghdr struct {
+ Name *byte
+ Namelen uint32
+ Pad_cgo_0 [4]byte
+ Iov *Iovec
+ Iovlen uint64
+ Control *byte
+ Controllen uint64
+ Flags int32
+ Pad_cgo_1 [4]byte
+}
+
+type Cmsghdr struct {
+ Len uint64
+ Level int32
+ Type int32
+ X__cmsg_data [0]uint8
+}
+
+type Inet4Pktinfo struct {
+ Ifindex int32
+ Spec_dst [4]byte /* in_addr */
+ Addr [4]byte /* in_addr */
+}
+
+type Inet6Pktinfo struct {
+ Addr [16]byte /* in6_addr */
+ Ifindex uint32
+}
+
+type IPv6MTUInfo struct {
+ Addr RawSockaddrInet6
+ Mtu uint32
+}
+
+type ICMPv6Filter struct {
+ Data [8]uint32
+}
+
+type Ucred struct {
+ Pid int32
+ Uid uint32
+ Gid uint32
+}
+
+type TCPInfo struct {
+ State uint8
+ Ca_state uint8
+ Retransmits uint8
+ Probes uint8
+ Backoff uint8
+ Options uint8
+ Pad_cgo_0 [2]byte
+ Rto uint32
+ Ato uint32
+ Snd_mss uint32
+ Rcv_mss uint32
+ Unacked uint32
+ Sacked uint32
+ Lost uint32
+ Retrans uint32
+ Fackets uint32
+ Last_data_sent uint32
+ Last_ack_sent uint32
+ Last_data_recv uint32
+ Last_ack_recv uint32
+ Pmtu uint32
+ Rcv_ssthresh uint32
+ Rtt uint32
+ Rttvar uint32
+ Snd_ssthresh uint32
+ Snd_cwnd uint32
+ Advmss uint32
+ Reordering uint32
+ Rcv_rtt uint32
+ Rcv_space uint32
+ Total_retrans uint32
+}
+
+const (
+ SizeofSockaddrInet4 = 0x10
+ SizeofSockaddrInet6 = 0x1c
+ SizeofSockaddrAny = 0x70
+ SizeofSockaddrUnix = 0x6e
+ SizeofSockaddrLinklayer = 0x14
+ SizeofSockaddrNetlink = 0xc
+ SizeofLinger = 0x8
+ SizeofIPMreq = 0x8
+ SizeofIPMreqn = 0xc
+ SizeofIPv6Mreq = 0x14
+ SizeofMsghdr = 0x38
+ SizeofCmsghdr = 0x10
+ SizeofInet4Pktinfo = 0xc
+ SizeofInet6Pktinfo = 0x14
+ SizeofIPv6MTUInfo = 0x20
+ SizeofICMPv6Filter = 0x20
+ SizeofUcred = 0xc
+ SizeofTCPInfo = 0x68
+)
+
+const (
+ IFA_UNSPEC = 0x0
+ IFA_ADDRESS = 0x1
+ IFA_LOCAL = 0x2
+ IFA_LABEL = 0x3
+ IFA_BROADCAST = 0x4
+ IFA_ANYCAST = 0x5
+ IFA_CACHEINFO = 0x6
+ IFA_MULTICAST = 0x7
+ IFLA_UNSPEC = 0x0
+ IFLA_ADDRESS = 0x1
+ IFLA_BROADCAST = 0x2
+ IFLA_IFNAME = 0x3
+ IFLA_MTU = 0x4
+ IFLA_LINK = 0x5
+ IFLA_QDISC = 0x6
+ IFLA_STATS = 0x7
+ IFLA_COST = 0x8
+ IFLA_PRIORITY = 0x9
+ IFLA_MASTER = 0xa
+ IFLA_WIRELESS = 0xb
+ IFLA_PROTINFO = 0xc
+ IFLA_TXQLEN = 0xd
+ IFLA_MAP = 0xe
+ IFLA_WEIGHT = 0xf
+ IFLA_OPERSTATE = 0x10
+ IFLA_LINKMODE = 0x11
+ IFLA_LINKINFO = 0x12
+ IFLA_NET_NS_PID = 0x13
+ IFLA_IFALIAS = 0x14
+ IFLA_MAX = 0x22
+ RT_SCOPE_UNIVERSE = 0x0
+ RT_SCOPE_SITE = 0xc8
+ RT_SCOPE_LINK = 0xfd
+ RT_SCOPE_HOST = 0xfe
+ RT_SCOPE_NOWHERE = 0xff
+ RT_TABLE_UNSPEC = 0x0
+ RT_TABLE_COMPAT = 0xfc
+ RT_TABLE_DEFAULT = 0xfd
+ RT_TABLE_MAIN = 0xfe
+ RT_TABLE_LOCAL = 0xff
+ RT_TABLE_MAX = 0xffffffff
+ RTA_UNSPEC = 0x0
+ RTA_DST = 0x1
+ RTA_SRC = 0x2
+ RTA_IIF = 0x3
+ RTA_OIF = 0x4
+ RTA_GATEWAY = 0x5
+ RTA_PRIORITY = 0x6
+ RTA_PREFSRC = 0x7
+ RTA_METRICS = 0x8
+ RTA_MULTIPATH = 0x9
+ RTA_FLOW = 0xb
+ RTA_CACHEINFO = 0xc
+ RTA_TABLE = 0xf
+ RTN_UNSPEC = 0x0
+ RTN_UNICAST = 0x1
+ RTN_LOCAL = 0x2
+ RTN_BROADCAST = 0x3
+ RTN_ANYCAST = 0x4
+ RTN_MULTICAST = 0x5
+ RTN_BLACKHOLE = 0x6
+ RTN_UNREACHABLE = 0x7
+ RTN_PROHIBIT = 0x8
+ RTN_THROW = 0x9
+ RTN_NAT = 0xa
+ RTN_XRESOLVE = 0xb
+ RTNLGRP_NONE = 0x0
+ RTNLGRP_LINK = 0x1
+ RTNLGRP_NOTIFY = 0x2
+ RTNLGRP_NEIGH = 0x3
+ RTNLGRP_TC = 0x4
+ RTNLGRP_IPV4_IFADDR = 0x5
+ RTNLGRP_IPV4_MROUTE = 0x6
+ RTNLGRP_IPV4_ROUTE = 0x7
+ RTNLGRP_IPV4_RULE = 0x8
+ RTNLGRP_IPV6_IFADDR = 0x9
+ RTNLGRP_IPV6_MROUTE = 0xa
+ RTNLGRP_IPV6_ROUTE = 0xb
+ RTNLGRP_IPV6_IFINFO = 0xc
+ RTNLGRP_IPV6_PREFIX = 0x12
+ RTNLGRP_IPV6_RULE = 0x13
+ RTNLGRP_ND_USEROPT = 0x14
+ SizeofNlMsghdr = 0x10
+ SizeofNlMsgerr = 0x14
+ SizeofRtGenmsg = 0x1
+ SizeofNlAttr = 0x4
+ SizeofRtAttr = 0x4
+ SizeofIfInfomsg = 0x10
+ SizeofIfAddrmsg = 0x8
+ SizeofRtMsg = 0xc
+ SizeofRtNexthop = 0x8
+)
+
+type NlMsghdr struct {
+ Len uint32
+ Type uint16
+ Flags uint16
+ Seq uint32
+ Pid uint32
+}
+
+type NlMsgerr struct {
+ Error int32
+ Msg NlMsghdr
+}
+
+type RtGenmsg struct {
+ Family uint8
+}
+
+type NlAttr struct {
+ Len uint16
+ Type uint16
+}
+
+type RtAttr struct {
+ Len uint16
+ Type uint16
+}
+
+type IfInfomsg struct {
+ Family uint8
+ X__ifi_pad uint8
+ Type uint16
+ Index int32
+ Flags uint32
+ Change uint32
+}
+
+type IfAddrmsg struct {
+ Family uint8
+ Prefixlen uint8
+ Flags uint8
+ Scope uint8
+ Index uint32
+}
+
+type RtMsg struct {
+ Family uint8
+ Dst_len uint8
+ Src_len uint8
+ Tos uint8
+ Table uint8
+ Protocol uint8
+ Scope uint8
+ Type uint8
+ Flags uint32
+}
+
+type RtNexthop struct {
+ Len uint16
+ Flags uint8
+ Hops uint8
+ Ifindex int32
+}
+
+const (
+ SizeofSockFilter = 0x8
+ SizeofSockFprog = 0x10
+)
+
+type SockFilter struct {
+ Code uint16
+ Jt uint8
+ Jf uint8
+ K uint32
+}
+
+type SockFprog struct {
+ Len uint16
+ Pad_cgo_0 [6]byte
+ Filter *SockFilter
+}
+
+type InotifyEvent struct {
+ Wd int32
+ Mask uint32
+ Cookie uint32
+ Len uint32
+ Name [0]int8
+}
+
+const SizeofInotifyEvent = 0x10
+
+type PtraceRegs struct {
+ Regs [102]uint64
+ U_tsize uint64
+ U_dsize uint64
+ U_ssize uint64
+ Start_code uint64
+ Start_data uint64
+ Start_stack uint64
+ Signal int64
+ U_ar0 uint64
+ Magic uint64
+ U_comm [32]int8
+}
+
+type FdSet struct {
+ Bits [16]int64
+}
+
+type Sysinfo_t struct {
+ Uptime int64
+ Loads [3]uint64
+ Totalram uint64
+ Freeram uint64
+ Sharedram uint64
+ Bufferram uint64
+ Totalswap uint64
+ Freeswap uint64
+ Procs uint16
+ Pad uint16
+ Pad_cgo_0 [4]byte
+ Totalhigh uint64
+ Freehigh uint64
+ Unit uint32
+ X_f [0]int8
+ Pad_cgo_1 [4]byte
+}
+
+type Utsname struct {
+ Sysname [65]int8
+ Nodename [65]int8
+ Release [65]int8
+ Version [65]int8
+ Machine [65]int8
+ Domainname [65]int8
+}
+
+type Ustat_t struct {
+ Tfree int32
+ Pad_cgo_0 [4]byte
+ Tinode uint64
+ Fname [6]int8
+ Fpack [6]int8
+ Pad_cgo_1 [4]byte
+}
+
+type EpollEvent struct {
+ Events uint32
+ Fd int32
+ Pad int32
+}
+
+const (
+ _AT_FDCWD = -0x64
+ _AT_REMOVEDIR = 0x200
+ _AT_SYMLINK_NOFOLLOW = 0x100
+)
+
+type Termios struct {
+ Iflag uint32
+ Oflag uint32
+ Cflag uint32
+ Lflag uint32
+ Line uint8
+ Cc [32]uint8
+ Pad_cgo_0 [3]byte
+}
+
+const (
+ IUCLC = 0x200
+ OLCUC = 0x2
+ TCGETS = 0x540d
+ TCSETS = 0x540e
+ XCASE = 0x4
+)
--- /dev/null
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs types_linux.go
+
+package syscall
+
+const (
+ sizeofPtr = 0x8
+ sizeofShort = 0x2
+ sizeofInt = 0x4
+ sizeofLong = 0x8
+ sizeofLongLong = 0x8
+ PathMax = 0x1000
+)
+
+type (
+ _C_short int16
+ _C_int int32
+ _C_long int64
+ _C_long_long int64
+)
+
+type Timespec struct {
+ Sec int64
+ Nsec int64
+}
+
+type Timeval struct {
+ Sec int64
+ Usec int64
+}
+
+type Timex struct {
+ Modes uint32
+ Pad_cgo_0 [4]byte
+ Offset int64
+ Freq int64
+ Maxerror int64
+ Esterror int64
+ Status int32
+ Pad_cgo_1 [4]byte
+ Constant int64
+ Precision int64
+ Tolerance int64
+ Time Timeval
+ Tick int64
+ Ppsfreq int64
+ Jitter int64
+ Shift int32
+ Pad_cgo_2 [4]byte
+ Stabil int64
+ Jitcnt int64
+ Calcnt int64
+ Errcnt int64
+ Stbcnt int64
+ Tai int32
+ Pad_cgo_3 [44]byte
+}
+
+type Time_t int64
+
+type Tms struct {
+ Utime int64
+ Stime int64
+ Cutime int64
+ Cstime int64
+}
+
+type Utimbuf struct {
+ Actime int64
+ Modtime int64
+}
+
+type Rusage struct {
+ Utime Timeval
+ Stime Timeval
+ Maxrss int64
+ Ixrss int64
+ Idrss int64
+ Isrss int64
+ Minflt int64
+ Majflt int64
+ Nswap int64
+ Inblock int64
+ Oublock int64
+ Msgsnd int64
+ Msgrcv int64
+ Nsignals int64
+ Nvcsw int64
+ Nivcsw int64
+}
+
+type Rlimit struct {
+ Cur uint64
+ Max uint64
+}
+
+type _Gid_t uint32
+
+type Stat_t struct {
+ Dev uint32
+ Pad1 [3]int32
+ Ino uint64
+ Mode uint32
+ Nlink uint32
+ Uid uint32
+ Gid uint32
+ Rdev uint32
+ Pad2 [3]uint32
+ Size int64
+ Atim Timespec
+ Mtim Timespec
+ Ctim Timespec
+ Blksize uint32
+ Pad4 uint32
+ Blocks int64
+}
+
+type Statfs_t struct {
+ Type int64
+ Bsize int64
+ Frsize int64
+ Blocks uint64
+ Bfree uint64
+ Files uint64
+ Ffree uint64
+ Bavail uint64
+ Fsid Fsid
+ Namelen int64
+ Flags int64
+ Spare [5]int64
+}
+
+// Note: on mips64, we're using the getdents syscall,
+// so the Dirent struct is different.
+
+type Dirent struct {
+ Ino uint64
+ Off int64
+ Reclen uint16
+ Name [256]int8
+ Type uint8
+ Pad_cgo_0 [5]byte
+}
+
+type Fsid struct {
+ X__val [2]int32
+}
+
+type Flock_t struct {
+ Type int16
+ Whence int16
+ Pad_cgo_0 [4]byte
+ Start int64
+ Len int64
+ Pid int32
+ Pad_cgo_1 [4]byte
+}
+
+type RawSockaddrInet4 struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ Zero [8]uint8
+}
+
+type RawSockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+type RawSockaddrUnix struct {
+ Family uint16
+ Path [108]int8
+}
+
+type RawSockaddrLinklayer struct {
+ Family uint16
+ Protocol uint16
+ Ifindex int32
+ Hatype uint16
+ Pkttype uint8
+ Halen uint8
+ Addr [8]uint8
+}
+
+type RawSockaddrNetlink struct {
+ Family uint16
+ Pad uint16
+ Pid uint32
+ Groups uint32
+}
+
+type RawSockaddr struct {
+ Family uint16
+ Data [14]int8
+}
+
+type RawSockaddrAny struct {
+ Addr RawSockaddr
+ Pad [96]int8
+}
+
+type _Socklen uint32
+
+type Linger struct {
+ Onoff int32
+ Linger int32
+}
+
+type Iovec struct {
+ Base *byte
+ Len uint64
+}
+
+type IPMreq struct {
+ Multiaddr [4]byte /* in_addr */
+ Interface [4]byte /* in_addr */
+}
+
+type IPMreqn struct {
+ Multiaddr [4]byte /* in_addr */
+ Address [4]byte /* in_addr */
+ Ifindex int32
+}
+
+type IPv6Mreq struct {
+ Multiaddr [16]byte /* in6_addr */
+ Interface uint32
+}
+
+type Msghdr struct {
+ Name *byte
+ Namelen uint32
+ Pad_cgo_0 [4]byte
+ Iov *Iovec
+ Iovlen uint64
+ Control *byte
+ Controllen uint64
+ Flags int32
+ Pad_cgo_1 [4]byte
+}
+
+type Cmsghdr struct {
+ Len uint64
+ Level int32
+ Type int32
+ X__cmsg_data [0]uint8
+}
+
+type Inet4Pktinfo struct {
+ Ifindex int32
+ Spec_dst [4]byte /* in_addr */
+ Addr [4]byte /* in_addr */
+}
+
+type Inet6Pktinfo struct {
+ Addr [16]byte /* in6_addr */
+ Ifindex uint32
+}
+
+type IPv6MTUInfo struct {
+ Addr RawSockaddrInet6
+ Mtu uint32
+}
+
+type ICMPv6Filter struct {
+ Data [8]uint32
+}
+
+type Ucred struct {
+ Pid int32
+ Uid uint32
+ Gid uint32
+}
+
+type TCPInfo struct {
+ State uint8
+ Ca_state uint8
+ Retransmits uint8
+ Probes uint8
+ Backoff uint8
+ Options uint8
+ Pad_cgo_0 [2]byte
+ Rto uint32
+ Ato uint32
+ Snd_mss uint32
+ Rcv_mss uint32
+ Unacked uint32
+ Sacked uint32
+ Lost uint32
+ Retrans uint32
+ Fackets uint32
+ Last_data_sent uint32
+ Last_ack_sent uint32
+ Last_data_recv uint32
+ Last_ack_recv uint32
+ Pmtu uint32
+ Rcv_ssthresh uint32
+ Rtt uint32
+ Rttvar uint32
+ Snd_ssthresh uint32
+ Snd_cwnd uint32
+ Advmss uint32
+ Reordering uint32
+ Rcv_rtt uint32
+ Rcv_space uint32
+ Total_retrans uint32
+}
+
+const (
+ SizeofSockaddrInet4 = 0x10
+ SizeofSockaddrInet6 = 0x1c
+ SizeofSockaddrAny = 0x70
+ SizeofSockaddrUnix = 0x6e
+ SizeofSockaddrLinklayer = 0x14
+ SizeofSockaddrNetlink = 0xc
+ SizeofLinger = 0x8
+ SizeofIPMreq = 0x8
+ SizeofIPMreqn = 0xc
+ SizeofIPv6Mreq = 0x14
+ SizeofMsghdr = 0x38
+ SizeofCmsghdr = 0x10
+ SizeofInet4Pktinfo = 0xc
+ SizeofInet6Pktinfo = 0x14
+ SizeofIPv6MTUInfo = 0x20
+ SizeofICMPv6Filter = 0x20
+ SizeofUcred = 0xc
+ SizeofTCPInfo = 0x68
+)
+
+const (
+ IFA_UNSPEC = 0x0
+ IFA_ADDRESS = 0x1
+ IFA_LOCAL = 0x2
+ IFA_LABEL = 0x3
+ IFA_BROADCAST = 0x4
+ IFA_ANYCAST = 0x5
+ IFA_CACHEINFO = 0x6
+ IFA_MULTICAST = 0x7
+ IFLA_UNSPEC = 0x0
+ IFLA_ADDRESS = 0x1
+ IFLA_BROADCAST = 0x2
+ IFLA_IFNAME = 0x3
+ IFLA_MTU = 0x4
+ IFLA_LINK = 0x5
+ IFLA_QDISC = 0x6
+ IFLA_STATS = 0x7
+ IFLA_COST = 0x8
+ IFLA_PRIORITY = 0x9
+ IFLA_MASTER = 0xa
+ IFLA_WIRELESS = 0xb
+ IFLA_PROTINFO = 0xc
+ IFLA_TXQLEN = 0xd
+ IFLA_MAP = 0xe
+ IFLA_WEIGHT = 0xf
+ IFLA_OPERSTATE = 0x10
+ IFLA_LINKMODE = 0x11
+ IFLA_LINKINFO = 0x12
+ IFLA_NET_NS_PID = 0x13
+ IFLA_IFALIAS = 0x14
+ IFLA_MAX = 0x22
+ RT_SCOPE_UNIVERSE = 0x0
+ RT_SCOPE_SITE = 0xc8
+ RT_SCOPE_LINK = 0xfd
+ RT_SCOPE_HOST = 0xfe
+ RT_SCOPE_NOWHERE = 0xff
+ RT_TABLE_UNSPEC = 0x0
+ RT_TABLE_COMPAT = 0xfc
+ RT_TABLE_DEFAULT = 0xfd
+ RT_TABLE_MAIN = 0xfe
+ RT_TABLE_LOCAL = 0xff
+ RT_TABLE_MAX = 0xffffffff
+ RTA_UNSPEC = 0x0
+ RTA_DST = 0x1
+ RTA_SRC = 0x2
+ RTA_IIF = 0x3
+ RTA_OIF = 0x4
+ RTA_GATEWAY = 0x5
+ RTA_PRIORITY = 0x6
+ RTA_PREFSRC = 0x7
+ RTA_METRICS = 0x8
+ RTA_MULTIPATH = 0x9
+ RTA_FLOW = 0xb
+ RTA_CACHEINFO = 0xc
+ RTA_TABLE = 0xf
+ RTN_UNSPEC = 0x0
+ RTN_UNICAST = 0x1
+ RTN_LOCAL = 0x2
+ RTN_BROADCAST = 0x3
+ RTN_ANYCAST = 0x4
+ RTN_MULTICAST = 0x5
+ RTN_BLACKHOLE = 0x6
+ RTN_UNREACHABLE = 0x7
+ RTN_PROHIBIT = 0x8
+ RTN_THROW = 0x9
+ RTN_NAT = 0xa
+ RTN_XRESOLVE = 0xb
+ RTNLGRP_NONE = 0x0
+ RTNLGRP_LINK = 0x1
+ RTNLGRP_NOTIFY = 0x2
+ RTNLGRP_NEIGH = 0x3
+ RTNLGRP_TC = 0x4
+ RTNLGRP_IPV4_IFADDR = 0x5
+ RTNLGRP_IPV4_MROUTE = 0x6
+ RTNLGRP_IPV4_ROUTE = 0x7
+ RTNLGRP_IPV4_RULE = 0x8
+ RTNLGRP_IPV6_IFADDR = 0x9
+ RTNLGRP_IPV6_MROUTE = 0xa
+ RTNLGRP_IPV6_ROUTE = 0xb
+ RTNLGRP_IPV6_IFINFO = 0xc
+ RTNLGRP_IPV6_PREFIX = 0x12
+ RTNLGRP_IPV6_RULE = 0x13
+ RTNLGRP_ND_USEROPT = 0x14
+ SizeofNlMsghdr = 0x10
+ SizeofNlMsgerr = 0x14
+ SizeofRtGenmsg = 0x1
+ SizeofNlAttr = 0x4
+ SizeofRtAttr = 0x4
+ SizeofIfInfomsg = 0x10
+ SizeofIfAddrmsg = 0x8
+ SizeofRtMsg = 0xc
+ SizeofRtNexthop = 0x8
+)
+
+type NlMsghdr struct {
+ Len uint32
+ Type uint16
+ Flags uint16
+ Seq uint32
+ Pid uint32
+}
+
+type NlMsgerr struct {
+ Error int32
+ Msg NlMsghdr
+}
+
+type RtGenmsg struct {
+ Family uint8
+}
+
+type NlAttr struct {
+ Len uint16
+ Type uint16
+}
+
+type RtAttr struct {
+ Len uint16
+ Type uint16
+}
+
+type IfInfomsg struct {
+ Family uint8
+ X__ifi_pad uint8
+ Type uint16
+ Index int32
+ Flags uint32
+ Change uint32
+}
+
+type IfAddrmsg struct {
+ Family uint8
+ Prefixlen uint8
+ Flags uint8
+ Scope uint8
+ Index uint32
+}
+
+type RtMsg struct {
+ Family uint8
+ Dst_len uint8
+ Src_len uint8
+ Tos uint8
+ Table uint8
+ Protocol uint8
+ Scope uint8
+ Type uint8
+ Flags uint32
+}
+
+type RtNexthop struct {
+ Len uint16
+ Flags uint8
+ Hops uint8
+ Ifindex int32
+}
+
+const (
+ SizeofSockFilter = 0x8
+ SizeofSockFprog = 0x10
+)
+
+type SockFilter struct {
+ Code uint16
+ Jt uint8
+ Jf uint8
+ K uint32
+}
+
+type SockFprog struct {
+ Len uint16
+ Pad_cgo_0 [6]byte
+ Filter *SockFilter
+}
+
+type InotifyEvent struct {
+ Wd int32
+ Mask uint32
+ Cookie uint32
+ Len uint32
+ Name [0]int8
+}
+
+const SizeofInotifyEvent = 0x10
+
+type PtraceRegs struct {
+ Regs [102]uint64
+ U_tsize uint64
+ U_dsize uint64
+ U_ssize uint64
+ Start_code uint64
+ Start_data uint64
+ Start_stack uint64
+ Signal int64
+ U_ar0 uint64
+ Magic uint64
+ U_comm [32]int8
+}
+
+type FdSet struct {
+ Bits [16]int64
+}
+
+type Sysinfo_t struct {
+ Uptime int64
+ Loads [3]uint64
+ Totalram uint64
+ Freeram uint64
+ Sharedram uint64
+ Bufferram uint64
+ Totalswap uint64
+ Freeswap uint64
+ Procs uint16
+ Pad uint16
+ Pad_cgo_0 [4]byte
+ Totalhigh uint64
+ Freehigh uint64
+ Unit uint32
+ X_f [0]int8
+ Pad_cgo_1 [4]byte
+}
+
+type Utsname struct {
+ Sysname [65]int8
+ Nodename [65]int8
+ Release [65]int8
+ Version [65]int8
+ Machine [65]int8
+ Domainname [65]int8
+}
+
+type Ustat_t struct {
+ Tfree int32
+ Pad_cgo_0 [4]byte
+ Tinode uint64
+ Fname [6]int8
+ Fpack [6]int8
+ Pad_cgo_1 [4]byte
+}
+
+type EpollEvent struct {
+ Events uint32
+ Fd int32
+ Pad int32
+}
+
+const (
+ _AT_FDCWD = -0x64
+ _AT_REMOVEDIR = 0x200
+ _AT_SYMLINK_NOFOLLOW = 0x100
+)
+
+type Termios struct {
+ Iflag uint32
+ Oflag uint32
+ Cflag uint32
+ Lflag uint32
+ Line uint8
+ Cc [32]uint8
+ Pad_cgo_0 [3]byte
+}
+
+const (
+ IUCLC = 0x200
+ OLCUC = 0x2
+ TCGETS = 0x540d
+ TCSETS = 0x540e
+ XCASE = 0x4
+)
// Run runs the tests. It returns an exit code to pass to os.Exit.
func (m *M) Run() int {
- flag.Parse()
+ // TestMain may have already called flag.Parse.
+ if !flag.Parsed() {
+ flag.Parse()
+ }
+
parseCpuList()
before()
return zero
}
typ := receiver.Type()
- receiver, _ = indirect(receiver)
+ receiver, isNil := indirect(receiver)
// Unless it's an interface, need to get to a value of type *T to guarantee
// we see all methods of T and *T.
ptr := receiver
}
hasArgs := len(args) > 1 || final.IsValid()
// It's not a method; must be a field of a struct or an element of a map. The receiver must not be nil.
- receiver, isNil := indirect(receiver)
if isNil {
s.errorf("nil pointer evaluating %s.%s", typ, fieldName)
}
// RuneCountInString is like RuneCount but its input is a string.
func RuneCountInString(s string) (n int) {
- for range s {
+ for i := 0; i < len(s); {
n++
+ if s[i] < RuneSelf {
+ i++
+ } else {
+ _, size := DecodeRuneInString(s[i:])
+ i += size
+ }
}
- return
+ return n
}
// RuneStart reports whether the byte could be the first byte of
// ValidString reports whether s consists entirely of valid UTF-8-encoded runes.
func ValidString(s string) bool {
- for i, r := range s {
- if r == RuneError {
- // The RuneError value can be an error
- // sentinel value (if it's size 1) or the same
- // value encoded properly. Decode it to see if
- // it's the 1 byte sentinel value.
+ for i := 0; i < len(s); {
+ if s[i] < RuneSelf {
+ i++
+ } else {
_, size := DecodeRuneInString(s[i:])
if size == 1 {
+ // All valid runes of size 1 (those
+ // below RuneSelf) were handled above.
+ // This must be a RuneError.
return false
}
+ i += size
}
}
return true
}
func BenchmarkRuneCountTenASCIIChars(b *testing.B) {
+ s := []byte("0123456789")
for i := 0; i < b.N; i++ {
- RuneCountInString("0123456789")
+ RuneCount(s)
}
}
func BenchmarkRuneCountTenJapaneseChars(b *testing.B) {
+ s := []byte("日本語日本語日本語日")
+ for i := 0; i < b.N; i++ {
+ RuneCount(s)
+ }
+}
+
+func BenchmarkRuneCountInStringTenASCIIChars(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ RuneCountInString("0123456789")
+ }
+}
+
+func BenchmarkRuneCountInStringTenJapaneseChars(b *testing.B) {
for i := 0; i < b.N; i++ {
RuneCountInString("日本語日本語日本語日")
}
}
+func BenchmarkValidTenASCIIChars(b *testing.B) {
+ s := []byte("0123456789")
+ for i := 0; i < b.N; i++ {
+ Valid(s)
+ }
+}
+
+func BenchmarkValidTenJapaneseChars(b *testing.B) {
+ s := []byte("日本語日本語日本語日")
+ for i := 0; i < b.N; i++ {
+ Valid(s)
+ }
+}
+
+func BenchmarkValidStringTenASCIIChars(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ ValidString("0123456789")
+ }
+}
+
+func BenchmarkValidStringTenJapaneseChars(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ ValidString("日本語日本語日本語日")
+ }
+}
+
func BenchmarkEncodeASCIIRune(b *testing.B) {
buf := make([]byte, UTFMax)
for i := 0; i < b.N; i++ {
DecodeRune(nihon)
}
}
+
+func BenchmarkFullASCIIRune(b *testing.B) {
+ a := []byte{'a'}
+ for i := 0; i < b.N; i++ {
+ FullRune(a)
+ }
+}
+
+func BenchmarkFullJapaneseRune(b *testing.B) {
+ nihon := []byte("本")
+ for i := 0; i < b.N; i++ {
+ FullRune(nihon)
+ }
+}
for len(d.buf) > 0 {
err = d.parseHeaderFieldRepr()
if err == errNeedMore {
+ // Extra paranoia, making sure saveBuf won't
+ // get too large. All the varint and string
+ // reading code earlier should already catch
+ // overlong things and return ErrStringLength,
+ // but keep this as a last resort.
const varIntOverhead = 8 // conservative
if d.maxStrLen != 0 && int64(len(d.buf)) > 2*(int64(d.maxStrLen)+varIntOverhead) {
return 0, ErrStringLength
buf.Reset() // don't trust others
defer bufPool.Put(buf)
if err := huffmanDecode(buf, d.maxStrLen, p[:strLen]); err != nil {
+ buf.Reset()
return "", nil, err
}
s = buf.String()
--- /dev/null
+// run
+
+// Copyright 2015 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.
+
+// Test that tiny allocations with finalizers are correctly profiled.
+// Previously profile special records could have been processed prematurely
+// (while the object is still live).
+
+package main
+
+import (
+ "runtime"
+ "time"
+ "unsafe"
+)
+
+func main() {
+ runtime.MemProfileRate = 1
+ // Allocate 1M 4-byte objects and set a finalizer for every third object.
+ // Assuming that tiny block size is 16, some objects get finalizers setup
+ // only for middle bytes. The finalizer resurrects that object.
+ // As the result, all allocated memory must stay alive.
+ const (
+ N = 1 << 20
+ tinyBlockSize = 16 // runtime._TinySize
+ )
+ hold := make([]*int32, 0, N)
+ for i := 0; i < N; i++ {
+ x := new(int32)
+ if i%3 == 0 {
+ runtime.SetFinalizer(x, func(p *int32) {
+ hold = append(hold, p)
+ })
+ }
+ }
+ // Finalize as much as possible.
+ // Note: the sleep only increases probility of bug detection,
+ // it cannot lead to false failure.
+ for i := 0; i < 5; i++ {
+ runtime.GC()
+ time.Sleep(10 * time.Millisecond)
+ }
+ // Read memory profile.
+ var prof []runtime.MemProfileRecord
+ for {
+ if n, ok := runtime.MemProfile(prof, false); ok {
+ prof = prof[:n]
+ break
+ } else {
+ prof = make([]runtime.MemProfileRecord, n+10)
+ }
+ }
+ // See how much memory in tiny objects is profiled.
+ var totalBytes int64
+ for _, p := range prof {
+ bytes := p.AllocBytes - p.FreeBytes
+ nobj := p.AllocObjects - p.FreeObjects
+ size := bytes / nobj
+ if size == tinyBlockSize {
+ totalBytes += bytes
+ }
+ }
+ // 2*tinyBlockSize slack is for any boundary effects.
+ if want := N*int64(unsafe.Sizeof(int32(0))) - 2*tinyBlockSize; totalBytes < want {
+ println("got", totalBytes, "want >=", want)
+ panic("some of the tiny objects are not profiled")
+ }
+ // Just to keep hold alive.
+ if len(hold) != 0 && hold[0] == nil {
+ panic("bad")
+ }
+}
package main
import (
- "io/ioutil" // GCCGO_ERROR "imported and not used"
+ // avoid imported and not used errors
+ // "io/ioutil"
"net/http"
- "os" // GCCGO_ERROR "imported and not used"
+ // "os"
)
func makeHandler(fn func(http.ResponseWriter, *http.Request, string)) http.HandlerFunc {
- return func(w http.ResponseWriter, r *http.Request) // ERROR "syntax error|invalid use of type"
+ return func(w http.ResponseWriter, r *http.Request) // ERROR "syntax error|not an expression|invalid use of type"
}
type Page struct {
type T struct{}
+//go:noinline
func (T) cplx() complex128 {
- for false {
- } // avoid inlining
return complex(1, 0)
}
import "runtime"
-var c bool
-
+//go:noinline
func f() interface{} {
- if c { // disable inlining
- f()
- }
runtime.GC()
return nil
}
+//go:noinline
func g() {
- if c { // disable inlining
- g()
- }
var s interface{}
_ = func() {
s := f()
useiface(s)
}
+//go:noinline
func useiface(x interface{}) {
- if c { // disable inlining
- useiface(x)
- }
}
+//go:noinline
func h() {
- if c { // disable inlining
- h()
- }
var x [16]uintptr
for i := range x {
x[i] = 1
}
-
+
useint(x[0])
useint(x[1])
useint(x[2])
useint(x[3])
}
+//go:noinline
func useint(x uintptr) {
- if c { // disable inlining
- useint(x)
- }
}
func main() {
func big(x int) {
if x >= 0 {
- big(x-1)
+ big(x - 1)
}
}
--- /dev/null
+// Copyright 2015 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 a
+
+type T int
+
+func (a *T) Foo() [1]string {
+ var r [1]string
+ return r
+}
--- /dev/null
+// Copyright 2015 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 b
+
+import "./a"
+
+func F() (interface{}) {
+ var v *a.T
+ return v.Foo()
+}
--- /dev/null
+// compiledir
+
+// Copyright 2015 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.
+
+// https://gcc.gnu.org/PR67968
+
+// gccgo compiler crash building the equality and hash functions for a
+// type when a return statement requires a conversion to interface
+// type of a call of function defined in a different package that
+// returns an unnamed type.
+
+package ignored
foo(&f)
}
+//go:noinline
func foo(f *func()) func() {
- defer func() {}() // prevent inlining of foo
return *f
}
-// +build linux,!ppc64,!ppc64le
+// +build linux,!ppc64,!ppc64le,!mips64,!mips64le
// run
// Copyright 2015 The Go Authors. All rights reserved.
--- /dev/null
+// errorcheck
+
+// Copyright 2015 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.
+
+// identifiers beginning with non-ASCII digits were incorrectly accepted.
+// issue 11359.
+
+package p
+var Û¶ = 0 // ERROR "identifier cannot begin with digit"
--- /dev/null
+// errorcheck
+
+// Copyright 2015 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 p
+
+var _ = int8(4) * 300 // ERROR "constant 300 overflows int8" "constant 1200 overflows int8"
+var _ = complex64(1) * 1e200 // ERROR "constant 1e\+200 overflows complex64"
+var _ = complex128(1) * 1e500 // ERROR "constant 1\.00000e\+500 overflows complex128"
binary.BigEndian.PutUint32(ill, 0x7fe00008) // trap
case "ppc64le":
binary.LittleEndian.PutUint32(ill, 0x7fe00008) // trap
+ case "mips64":
+ binary.BigEndian.PutUint32(ill, 0x00000034) // trap
+ case "mips64le":
+ binary.LittleEndian.PutUint32(ill, 0x00000034) // trap
default:
// Just leave it as 0 and hope for the best.
}
--- /dev/null
+// compile
+
+// Copyright 2015 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.
+
+// issue 11699; used to fail with duplicate _.args_stackmap symbols.
+
+package p
+
+func _()
+func _()
--- /dev/null
+// run
+
+// Copyright 2015 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.
+
+// Issue 11987. The ppc64 SRADCC instruction was misassembled in a way
+// lost bit 5 of the immediate so v>>32 was assembled as v>>0. SRADCC
+// is only ever inserted by peep so it's hard to be sure when it will
+// be used. This formulation worked when the bug was fixed.
+
+package main
+
+import "fmt"
+
+var v int64 = 0x80000000
+
+func main() {
+ s := fmt.Sprintf("%v", v>>32 == 0)
+ if s != "true" {
+ fmt.Printf("BUG: v>>32 == 0 evaluated as %q\n", s)
+ }
+}
panic("bad")
}
}
+
+//go:noinline
func f1(v1 uint) uint {
- switch {
- } // prevent inlining
return v1 >> ((1 >> v1) + (1 >> v1))
}
--- /dev/null
+// compile
+
+// Copyright 2015 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.
+
+// issue 12413: invalid variable name x in type switch: code would fail
+// to compile if the variable used in the short variable declaration was
+// previously declared as a constant.
+
+package main
+
+func main() {
+ const x = 42
+ switch x := interface{}(nil).(type) {
+ default:
+ _ = x
+ }
+}
--- /dev/null
+// run
+
+// Copyright 2015 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.
+
+// Issue 12577: Test that there are no -0 floating-point constants.
+
+package main
+
+import "math"
+
+const (
+ z0 = 0.0
+ z1 = -0.0
+ z2 = -z0
+ z3 = -z2
+)
+
+var (
+ x0 float32 = z0
+ x1 float32 = z1
+ x2 float32 = z2
+ x3 float32 = z3
+
+ y0 float64 = z0
+ y1 float64 = z1
+ y2 float64 = z2
+ y3 float64 = z3
+)
+
+func test32(f float32) {
+ if f != 0 || math.Signbit(float64(f)) {
+ println("BUG: got", f, "want 0.0")
+ return
+ }
+}
+
+func test64(f float64) {
+ if f != 0 || math.Signbit(f) {
+ println("BUG: got", f, "want 0.0")
+ return
+ }
+}
+
+func main() {
+ if f := -x0; f != 0 || !math.Signbit(float64(f)) {
+ println("BUG: got", f, "want -0.0")
+ }
+
+ test32(-0.0)
+ test32(x0)
+ test32(x1)
+ test32(x2)
+ test32(x3)
+
+ if f := -y0; f != 0 || !math.Signbit(f) {
+ println("BUG: got", f, "want -0.0")
+ }
+
+ test64(-0.0)
+ test64(y0)
+ test64(y1)
+ test64(y2)
+ test64(y3)
+}
--- /dev/null
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+ "runtime"
+)
+
+const N = 100000
+
+func main() {
+ // Allocate more Ps than processors. This raises
+ // the chance that we get interrupted by the OS
+ // in exactly the right (wrong!) place.
+ p := runtime.NumCPU()
+ runtime.GOMAXPROCS(2 * p)
+
+ // Allocate some pointers.
+ ptrs := make([]*int, p)
+ for i := 0; i < p; i++ {
+ ptrs[i] = new(int)
+ }
+
+ // Arena where we read and write pointers like crazy.
+ collider := make([]*int, p)
+
+ done := make(chan struct{}, 2*p)
+
+ // Start writers. They alternately write a pointer
+ // and nil to a slot in the collider.
+ for i := 0; i < p; i++ {
+ i := i
+ go func() {
+ for j := 0; j < N; j++ {
+ // Write a pointer using memmove.
+ copy(collider[i:i+1], ptrs[i:i+1])
+ // Write nil using memclr.
+ // (This is a magic loop that gets lowered to memclr.)
+ r := collider[i : i+1]
+ for k := range r {
+ r[k] = nil
+ }
+ }
+ done <- struct{}{}
+ }()
+ }
+ // Start readers. They read pointers from slots
+ // and make sure they are valid.
+ for i := 0; i < p; i++ {
+ i := i
+ go func() {
+ for j := 0; j < N; j++ {
+ var ptr [1]*int
+ copy(ptr[:], collider[i:i+1])
+ if ptr[0] != nil && ptr[0] != ptrs[i] {
+ panic(fmt.Sprintf("bad pointer read %p!", ptr[0]))
+ }
+ }
+ done <- struct{}{}
+ }()
+ }
+ for i := 0; i < 2*p; i++ {
+ <-done
+ }
+}
--- /dev/null
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+type T struct {
+ a, b, c int
+}
+
+func usestack() {
+ usestack1(32)
+}
+func usestack1(d int) byte {
+ if d == 0 {
+ return 0
+ }
+ var b [1024]byte
+ usestack1(d - 1)
+ return b[3]
+}
+
+const n = 100000
+
+func main() {
+ c := make(chan interface{})
+ done := make(chan bool)
+
+ for i := 0; i < 10; i++ {
+ go func() {
+ for j := 0; j < n; j++ {
+ c <- new(T)
+ }
+ done <- true
+ }()
+ go func() {
+ for j := 0; j < n; j++ {
+ _ = (<-c).(*T)
+ usestack()
+ }
+ done <- true
+ }()
+ }
+ for i := 0; i < 20; i++ {
+ <-done
+ }
+}
--- /dev/null
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+// Make sure the compiler knows that DUFFCOPY clobbers X0
+
+import "fmt"
+
+//go:noinline
+func f(x float64) float64 {
+ // y is allocated to X0
+ y := x + 5
+ // marshals z before y. Marshalling z
+ // calls DUFFCOPY.
+ return g(z, y)
+}
+
+//go:noinline
+func g(b [64]byte, y float64) float64 {
+ return y
+}
+
+var z [64]byte
+
+func main() {
+ got := f(5)
+ if got != 10 {
+ panic(fmt.Sprintf("want 10, got %f", got))
+ }
+}
package main
-func DontInline() {}
-
+//go:noinline
func F(e interface{}) (int, int) {
- DontInline()
return 3, 7
}
+//go:noinline
func G() (int, int) {
- DontInline()
return 3, 7
}
Pointer *int
}
-func dontinline() {}
-
+//go:noinline
func Store(t *T) {
global = t.Pointer
- dontinline()
}
+//go:noinline
func Store2(t *T) {
global2 = t.Pointer
- dontinline()
}
func Get() *int {
var P int
-var b bool
-
+//go:noinline
func F(x *int) string {
- if b { // avoid inlining
- F(x)
- }
P = 50
*x = 100
return fmt.Sprintln(P, *x)
type TI [3]uintptr
+//go:noinline
func G() (t TI) {
t[0] = 1
t[1] = 2
t[2] = 3
- runtime.GC() // prevent inlining
return
}
+//go:noinline
func F() (t T) {
t.X = newint()
t.Y = t.X
t.Z = t.Y
- runtime.GC() // prevent inlining
return
}
var xy string
+//go:noinline
func x() bool {
- for false {
- } // no inlining
xy += "x"
return false
}
+//go:noinline
func y() string {
- for false {
- } // no inlining
xy += "y"
return "abc"
}
}
func getMemProfileRecords() []runtime.MemProfileRecord {
+ // Force the runtime to update the object and byte counts.
+ // This can take up to two GC cycles to get a complete
+ // snapshot of the current point in time.
+ runtime.GC()
+ runtime.GC()
+
// Find out how many records there are (MemProfile(nil, true)),
// allocate that many records, and get the data.
// There's a race—more records might be added between
func f(x *byte) *byte { // ERROR "can inline f" "leaking param: x to result"
return add2(x, 1) // ERROR "inlining call to add2" "inlining call to add1"
}
+
+//go:noinline
+func g(x int) int {
+ return x + 1
+}
+
+func h(x int) int { // ERROR "can inline h"
+ return x + 2
+}
// errorcheck -0 -d=nil
// Fails on ppc64x because of incomplete optimization.
// See issues 9058.
-// +build !ppc64,!ppc64le,!amd64
+// Same reason for mips64x.
+// +build !ppc64,!ppc64le,!mips64,!mips64le,!amd64
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
main 136
# A nosplit leaf can use the whole 128-CallSize bytes available on entry.
-main 112 nosplit
-main 116 nosplit
-main 120 nosplit
-main 124 nosplit
+# (CallSize is 32 on ppc64)
+main 96 nosplit
+main 100 nosplit; REJECT ppc64 ppc64le
+main 104 nosplit; REJECT ppc64 ppc64le
+main 108 nosplit; REJECT ppc64 ppc64le
+main 112 nosplit; REJECT ppc64 ppc64le
+main 116 nosplit; REJECT ppc64 ppc64le
+main 120 nosplit; REJECT ppc64 ppc64le
+main 124 nosplit; REJECT ppc64 ppc64le
main 128 nosplit; REJECT
main 132 nosplit; REJECT
main 136 nosplit; REJECT
# Calling a nosplit function from a nosplit function requires
# having room for the saved caller PC and the called frame.
# Because ARM doesn't save LR in the leaf, it gets an extra 4 bytes.
-# Because ppc64 doesn't save LR in the leaf, it gets an extra 8 bytes.
-main 112 nosplit call f; f 0 nosplit
-main 116 nosplit call f; f 0 nosplit
-main 120 nosplit call f; f 0 nosplit; REJECT amd64
-main 124 nosplit call f; f 0 nosplit; REJECT amd64 386
+# Because arm64 doesn't save LR in the leaf, it gets an extra 8 bytes.
+# ppc64 doesn't save LR in the leaf, but CallSize is 32, so it gets 24 fewer bytes than amd64.
+main 96 nosplit call f; f 0 nosplit
+main 100 nosplit call f; f 0 nosplit; REJECT ppc64 ppc64le
+main 104 nosplit call f; f 0 nosplit; REJECT ppc64 ppc64le
+main 108 nosplit call f; f 0 nosplit; REJECT ppc64 ppc64le
+main 112 nosplit call f; f 0 nosplit; REJECT ppc64 ppc64le
+main 116 nosplit call f; f 0 nosplit; REJECT ppc64 ppc64le
+main 120 nosplit call f; f 0 nosplit; REJECT ppc64 ppc64le amd64
+main 124 nosplit call f; f 0 nosplit; REJECT ppc64 ppc64le amd64 386
main 128 nosplit call f; f 0 nosplit; REJECT
main 132 nosplit call f; f 0 nosplit; REJECT
main 136 nosplit call f; f 0 nosplit; REJECT
# Calling a splitting function from a nosplit function requires
# having room for the saved caller PC of the call but also the
# saved caller PC for the call to morestack.
-# Again the ARM and ppc64 work in less space.
-main 104 nosplit call f; f 0 call f
-main 108 nosplit call f; f 0 call f
-main 112 nosplit call f; f 0 call f; REJECT amd64
-main 116 nosplit call f; f 0 call f; REJECT amd64
-main 120 nosplit call f; f 0 call f; REJECT amd64 386
-main 124 nosplit call f; f 0 call f; REJECT amd64 386
+# RISC architectures differ in the same way as before.
+main 96 nosplit call f; f 0 call f
+main 100 nosplit call f; f 0 call f; REJECT ppc64 ppc64le
+main 104 nosplit call f; f 0 call f; REJECT ppc64 ppc64le
+main 108 nosplit call f; f 0 call f; REJECT ppc64 ppc64le
+main 112 nosplit call f; f 0 call f; REJECT ppc64 ppc64le amd64
+main 116 nosplit call f; f 0 call f; REJECT ppc64 ppc64le amd64
+main 120 nosplit call f; f 0 call f; REJECT ppc64 ppc64le amd64 386
+main 124 nosplit call f; f 0 call f; REJECT ppc64 ppc64le amd64 386
main 128 nosplit call f; f 0 call f; REJECT
main 132 nosplit call f; f 0 call f; REJECT
main 136 nosplit call f; f 0 call f; REJECT
# Indirect calls are assumed to be splitting functions.
-main 104 nosplit callind
-main 108 nosplit callind
-main 112 nosplit callind; REJECT amd64
-main 116 nosplit callind; REJECT amd64
-main 120 nosplit callind; REJECT amd64 386
-main 124 nosplit callind; REJECT amd64 386
+main 96 nosplit callind
+main 100 nosplit callind; REJECT ppc64 ppc64le
+main 104 nosplit callind; REJECT ppc64 ppc64le
+main 108 nosplit callind; REJECT ppc64 ppc64le
+main 112 nosplit callind; REJECT ppc64 ppc64le amd64
+main 116 nosplit callind; REJECT ppc64 ppc64le amd64
+main 120 nosplit callind; REJECT ppc64 ppc64le amd64 386
+main 124 nosplit callind; REJECT ppc64 ppc64le amd64 386
main 128 nosplit callind; REJECT
main 132 nosplit callind; REJECT
main 136 nosplit callind; REJECT
var buf bytes.Buffer
ptrSize := 4
switch goarch {
+ case "mips64", "mips64le":
+ ptrSize = 8
+ fmt.Fprintf(&buf, "#define CALL JAL\n#define REGISTER (R0)\n")
case "ppc64", "ppc64le":
ptrSize = 8
fmt.Fprintf(&buf, "#define CALL BL\n#define REGISTER (CTR)\n")
name := m[1]
size, _ := strconv.Atoi(m[2])
- // The limit was originally 128 but is now 512.
+ // The limit was originally 128 but is now 592.
// Instead of rewriting the test cases above, adjust
// the first stack frame to use up the extra bytes.
if i == 0 {
log += "f(" + x + ", " + y + ")"
}
+//go:noinline
func ff(x, y string) {
- for false {
- } // prevent inl
log += "ff(" + x + ", " + y + ")"
}
return x
}
+//go:noinline
func g(x string) string {
- for false {
- } // prevent inl
log += "g(" + x + ")"
return x
}
err++
}
log = ""
-
+
x := 0
switch x {
case 0:
err++
}
log = ""
-
+
if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" {
println("in switch, expecting a(1)b(2)a(2), got ", log)
err++
}
log = ""
}
-
+
c := make(chan int, 1)
c <- 1
select {
err++
}
log = ""
-
+
if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" {
println("in select1, expecting a(1)b(2)a(2), got ", log)
err++
err++
}
log = ""
-
+
if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" {
println("in select2, expecting a(1)b(2)a(2), got ", log)
err++
c <- 1
select {
default:
- case c<-1:
+ case c <- 1:
case <-c:
if a("1")("2")("3"); log != "a(1)a(2)a(3)" {
println("in select3, expecting a(1)a(2)a(3) , got ", log)
err++
}
log = ""
-
+
if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" {
println("in select3, expecting a(1)b(2)a(2), got ", log)
err++
err++
}
log = ""
-
+
if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" {
println("in select4, expecting a(1)b(2)a(2), got ", log)
err++
err++
}
log = ""
-
+
if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" {
println("in select5, expecting a(1)b(2)a(2), got ", log)
err++
type xyz struct {
ch chan
-} // ERROR "unexpected .*}.* in channel type"
+} // ERROR "unexpected .*}.* in channel type|missing channel element type"
-func Foo(y chan) { // ERROR "unexpected .*\).* in channel type"
+func Foo(y chan) { // ERROR "unexpected .*\).* in channel type|missing channel element type"
}
-func Bar(x chan, y int) { // ERROR "unexpected comma in channel type"
+func Bar(x chan, y int) { // ERROR "unexpected comma in channel type|missing channel element type"
}
package main
func main() {
+ var x int // avoid undefined: x error below with recursive-descent parser
for var x = 0; x < 10; x++ { // ERROR "var declaration not allowed in for initializer"
func main() {
for x // GCCGO_ERROR "undefined"
- { // ERROR "missing .*{.* after for clause"
+ { // ERROR "missing .*{.* after for clause|missing operand"
z // GCCGO_ERROR "undefined"
package main
type T // ERROR "unexpected semicolon or newline in type declaration"
-{
-
-
-
+// line below uncommented to avoid follow-up error
+// {
\ No newline at end of file
func main() {
if x { } // GCCGO_ERROR "undefined"
- else { } // ERROR "unexpected semicolon or newline before .?else.?"
+ else { } // ERROR "unexpected semicolon or newline before .?else.?|unexpected else"
}
package main
-var x map[string]string{"a":"b"} // ERROR "unexpected { at end of statement|expected ';' or newline after top level declaration"
+var x map[string]string{"a":"b"} // ERROR "unexpected { at end of statement|unexpected { after top level declaration|expected ';' or newline after top level declaration"
import (
"runtime"
- "sync/atomic"
"time"
)
func main() {
- // Does not work on 32-bits due to partially conservative GC.
+ // Does not work on gccgo due to partially conservative GC.
// Try to enable when we have fully precise GC.
- if runtime.GOARCH != "amd64" {
- return
- }
- // Likewise for gccgo.
if runtime.Compiler == "gccgo" {
return
}
- N := int32(100)
- count := N
- done := make([]bool, N)
- for i := int32(0); i < N; i++ {
- x := i // subject to tiny alloc
+ const N = 100
+ finalized := make(chan int32, N)
+ for i := 0; i < N; i++ {
+ x := new(int32) // subject to tiny alloc
+ *x = int32(i)
// the closure must be big enough to be combined
- runtime.SetFinalizer(&x, func(p *int32) {
+ runtime.SetFinalizer(x, func(p *int32) {
+ finalized <- *p
+ })
+ }
+ runtime.GC()
+ count := 0
+ done := make([]bool, N)
+ timeout := time.After(5*time.Second)
+ for {
+ select {
+ case <-timeout:
+ println("timeout,", count, "finalized so far")
+ panic("not all finalizers are called")
+ case x := <-finalized:
// Check that p points to the correct subobject of the tiny allocation.
// It's a bit tricky, because we can't capture another variable
// with the expected value (it would be combined as well).
- if *p < 0 || *p >= N {
- println("got", *p)
+ if x < 0 || x >= N {
+ println("got", x)
panic("corrupted")
}
- if done[*p] {
- println("got", *p)
+ if done[x] {
+ println("got", x)
panic("already finalized")
}
- done[*p] = true
- atomic.AddInt32(&count, -1)
- })
- }
- for i := 0; i < 4; i++ {
- runtime.GC()
- time.Sleep(10 * time.Millisecond)
- }
- // Some of the finalizers may not be executed,
- // if the outermost allocations are combined with something persistent.
- // Currently 4 int32's are combined into a 16-byte block,
- // ensure that most of them are finalized.
- if count >= N/4 {
- println(count, "out of", N, "finalizer are not called")
- panic("not all finalizers are called")
+ done[x] = true
+ count++
+ if count > N/10*9 {
+ // Some of the finalizers may not be executed,
+ // if the outermost allocations are combined with something persistent.
+ // Currently 4 int32's are combined into a 16-byte block,
+ // ensure that most of them are finalized.
+ return
+ }
+ }
}
}
-