mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.boringcrypto] all: merge master into dev.boringcrypto
Change-Id: I04d511ed8e3e7ca4a3267f226a0c3e248c0f84a9
This commit is contained in:
commit
50b8f490e1
1269 changed files with 14918 additions and 17877 deletions
5
AUTHORS
5
AUTHORS
|
|
@ -202,7 +202,7 @@ Ben Burkert <ben@benburkert.com>
|
|||
Ben Haines <bhainesva@gmail.com>
|
||||
Ben Lubar <ben.lubar@gmail.com>
|
||||
Ben Olive <sionide21@gmail.com>
|
||||
Ben Shi <powerman1st@163.com>
|
||||
Ben Shi <powerman1st@163.com> <ben.shi@streamcomputing.com>
|
||||
Benjamin Black <b@b3k.us>
|
||||
Benjamin Cable <cable.benjamin@gmail.com>
|
||||
Benjamin Hsieh <tanookiben@users.noreply.github.com>
|
||||
|
|
@ -263,6 +263,7 @@ Casey Callendrello <squeed@gmail.com>
|
|||
Casey Marshall <casey.marshall@gmail.com>
|
||||
Cezar Sá Espinola <cezarsa@gmail.com>
|
||||
ChaiShushan <chaishushan@gmail.com>
|
||||
Changkun Ou <hi@changkun.de> <hi@changkun.us>
|
||||
Chaoqun Han <hanssccv@gmail.com>
|
||||
Charles Fenwick Elliott <Charles@FenwickElliott.io>
|
||||
Charles L. Dorian <cldorian@gmail.com>
|
||||
|
|
@ -569,6 +570,7 @@ Hootsuite Inc.
|
|||
Hsin-Ho Yeh <yhh92u@gmail.com>
|
||||
Hu Keping <hukeping@huawei.com>
|
||||
Hugues Bruant <hugues.bruant@gmail.com>
|
||||
HyperConnect Inc.
|
||||
Ian Gudger <ian@loosescre.ws>
|
||||
Ian Kent <iankent85@gmail.com>
|
||||
IBM
|
||||
|
|
@ -1146,6 +1148,7 @@ Piers <google@hellopiers.pro>
|
|||
Pieter Droogendijk <pieter@binky.org.uk>
|
||||
Pietro Gagliardi <pietro10@mac.com>
|
||||
Piyush Mishra <piyush@codeitout.com>
|
||||
PlanetScale, Inc.
|
||||
Platform.sh
|
||||
Pontus Leitzler <leitzler@gmail.com>
|
||||
Prasanga Siripala <pj@pjebs.com.au>
|
||||
|
|
|
|||
|
|
@ -365,7 +365,7 @@ Ben Lubar <ben.lubar@gmail.com>
|
|||
Ben Lynn <benlynn@gmail.com>
|
||||
Ben Olive <sionide21@gmail.com>
|
||||
Ben Schwartz <bemasc@google.com>
|
||||
Ben Shi <powerman1st@163.com>
|
||||
Ben Shi <powerman1st@163.com> <ben.shi@streamcomputing.com>
|
||||
Ben Toews <mastahyeti@gmail.com>
|
||||
Benjamin Barenblat <bbaren@google.com>
|
||||
Benjamin Black <b@b3k.us>
|
||||
|
|
@ -451,6 +451,7 @@ Bryan Ford <brynosaurus@gmail.com>
|
|||
Bryan Heden <b.heden@gmail.com>
|
||||
Bulat Gaifullin <gaifullinbf@gmail.com>
|
||||
Burak Guven <bguven@gmail.com>
|
||||
Byoungchan Lee <daniel.l@hpcnt.com>
|
||||
Caine Tighe <arctanofyourface@gmail.com>
|
||||
Caio Marcelo de Oliveira Filho <caio.oliveira@intel.com>
|
||||
Caleb Martinez <accounts@calebmartinez.com>
|
||||
|
|
@ -486,7 +487,7 @@ Cedric Staub <cs@squareup.com>
|
|||
Cezar Sá Espinola <cezarsa@gmail.com>
|
||||
Chad Rosier <mrosier.qdt@qualcommdatacenter.com>
|
||||
ChaiShushan <chaishushan@gmail.com>
|
||||
Changkun Ou <hi@changkun.us>
|
||||
Changkun Ou <hi@changkun.de> <hi@changkun.us>
|
||||
Channing Kimble-Brown <channing@golang.org>
|
||||
Chao Xu <xuchao@google.com>
|
||||
Chaoqun Han <hanssccv@gmail.com>
|
||||
|
|
@ -1791,7 +1792,7 @@ Matt Jibson <matt.jibson@gmail.com>
|
|||
Matt Joiner <anacrolix@gmail.com>
|
||||
Matt Jones <mrjones@google.com>
|
||||
Matt Juran <thepciet@gmail.com>
|
||||
Matt Layher <mdlayher@gmail.com>
|
||||
Matt Layher <mdlayher@gmail.com> <mdlayher@planetscale.com>
|
||||
Matt Masurka <masurka@google.com>
|
||||
Matt Pearring <broskies@google.com>
|
||||
Matt Reiferson <mreiferson@gmail.com>
|
||||
|
|
|
|||
|
|
@ -16,23 +16,23 @@ BSD-style license found in the LICENSE file.
|
|||
|
||||
#### Binary Distributions
|
||||
|
||||
Official binary distributions are available at https://golang.org/dl/.
|
||||
Official binary distributions are available at https://go.dev/dl/.
|
||||
|
||||
After downloading a binary release, visit https://golang.org/doc/install
|
||||
After downloading a binary release, visit https://go.dev/doc/install
|
||||
for installation instructions.
|
||||
|
||||
#### Install From Source
|
||||
|
||||
If a binary distribution is not available for your combination of
|
||||
operating system and architecture, visit
|
||||
https://golang.org/doc/install/source
|
||||
https://go.dev/doc/install/source
|
||||
for source installation instructions.
|
||||
|
||||
### Contributing
|
||||
|
||||
Go is the work of thousands of contributors. We appreciate your help!
|
||||
|
||||
To contribute, please read the contribution guidelines at https://golang.org/doc/contribute.
|
||||
To contribute, please read the contribution guidelines at https://go.dev/doc/contribute.
|
||||
|
||||
Note that the Go project uses the issue tracker for bug reports and
|
||||
proposals only. See https://golang.org/wiki/Questions for a list of
|
||||
|
|
|
|||
16
api/README
16
api/README
|
|
@ -8,6 +8,16 @@ shipped. Each file adds new lines but does not remove any.
|
|||
except.txt lists features that may disappear without breaking true
|
||||
compatibility.
|
||||
|
||||
next.txt is the only file intended to be mutated. It's a list of
|
||||
features that may be added to the next version. It only affects
|
||||
warning output from the go api tool.
|
||||
Starting with go1.19.txt, each API feature line must end in "#nnnnn"
|
||||
giving the GitHub issue number of the proposal issue that accepted
|
||||
the new API. This helps with our end-of-cycle audit of new APIs.
|
||||
The same requirement applies to next/* (described below), which will
|
||||
become a go1.XX.txt for XX >= 19.
|
||||
|
||||
The next/ directory contains the only files intended to be mutated.
|
||||
Each file in that directory contains a list of features that may be added
|
||||
to the next release of Go. The files in this directory only affect the
|
||||
warning output from the go api tool. Each file should be named
|
||||
nnnnn.txt, after the issue number for the accepted proposal.
|
||||
(The #nnnnn suffix must also appear at the end of each line in the file;
|
||||
that will be preserved when next/*.txt is concatenated into go1.XX.txt.)
|
||||
|
|
|
|||
1
api/next/45628.txt
Normal file
1
api/next/45628.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
pkg encoding/xml, method (*Decoder) InputPos() (int, int) #45628
|
||||
2
api/next/45754.txt
Normal file
2
api/next/45754.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
pkg flag, func TextVar(encoding.TextUnmarshaler, string, encoding.TextMarshaler, string) #45754
|
||||
pkg flag, method (*FlagSet) TextVar(encoding.TextUnmarshaler, string, encoding.TextMarshaler, string) #45754
|
||||
2
api/next/46059.txt
Normal file
2
api/next/46059.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
pkg net/url, type URL struct, OmitHost bool #46059
|
||||
|
||||
2
api/next/47005.txt
Normal file
2
api/next/47005.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
pkg net/url, func JoinPath(string, ...string) (string, error) #47005
|
||||
pkg net/url, method (*URL) JoinPath(...string) *URL #47005
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
pkg encoding/binary, type AppendByteOrder interface { AppendUint16, AppendUint32, AppendUint64, String }
|
||||
pkg encoding/binary, type AppendByteOrder interface, AppendUint16([]uint8, uint16) []uint8
|
||||
pkg encoding/binary, type AppendByteOrder interface, AppendUint32([]uint8, uint32) []uint8
|
||||
pkg encoding/binary, type AppendByteOrder interface, AppendUint64([]uint8, uint64) []uint8
|
||||
pkg encoding/binary, type AppendByteOrder interface, String() string
|
||||
pkg encoding/binary, type AppendByteOrder interface { AppendUint16, AppendUint32, AppendUint64, String } #50601
|
||||
pkg encoding/binary, type AppendByteOrder interface, AppendUint16([]uint8, uint16) []uint8 #50601
|
||||
pkg encoding/binary, type AppendByteOrder interface, AppendUint32([]uint8, uint32) []uint8 #50601
|
||||
pkg encoding/binary, type AppendByteOrder interface, AppendUint64([]uint8, uint64) []uint8 #50601
|
||||
pkg encoding/binary, type AppendByteOrder interface, String() string #50601
|
||||
1
api/next/51414.txt
Normal file
1
api/next/51414.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
pkg time, method (Duration) Abs() Duration #51414
|
||||
|
|
@ -59,3 +59,18 @@ Do not send CLs removing the interior tags from such phrases.
|
|||
<p>
|
||||
TODO: complete this section
|
||||
</p>
|
||||
<dl id="net"><dt><a href="/pkg/net/">net</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 386016 -->
|
||||
The pure Go resolver will now use EDNS(0) to include a suggested
|
||||
maximum reply packet length, permitting reply packets to contain
|
||||
up to 1232 bytes (the previous maximum was 512).
|
||||
In the unlikely event that this causes problems with a local DNS
|
||||
resolver, setting the environment variable
|
||||
<code>GODEBUG=netdns=cgo</code> to use the cgo-based resolver
|
||||
should work.
|
||||
Please report any such problems on <a href="/issue/new">the
|
||||
issue tracker</a>.
|
||||
</p>
|
||||
</dd>
|
||||
</dl>
|
||||
|
|
|
|||
412
doc/go_spec.html
412
doc/go_spec.html
|
|
@ -1,26 +1,16 @@
|
|||
<!--{
|
||||
"Title": "The Go Programming Language Specification - Go 1.18 Draft",
|
||||
"Subtitle": "Version of Feb 28, 2022",
|
||||
"Title": "The Go Programming Language Specification",
|
||||
"Subtitle": "Version of March 10, 2022",
|
||||
"Path": "/ref/spec"
|
||||
}-->
|
||||
|
||||
<h2>Earlier version</h2>
|
||||
|
||||
<p>
|
||||
For the pre-Go1.18 specification without generics support see
|
||||
<a href="/doc/go1.17_spec.html">The Go Programming Language Specification</a>.
|
||||
</p>
|
||||
|
||||
<!-- TODO(gri) remove this before the final release -->
|
||||
<p><b>
|
||||
[For reviewers: Sections where we know of missing prose are marked like this. The markers will be removed before the release.]
|
||||
</b></p>
|
||||
|
||||
<h2 id="Introduction">Introduction</h2>
|
||||
|
||||
<p>
|
||||
This is a reference manual for the Go programming language. For
|
||||
more information and other documents, see <a href="/">golang.org</a>.
|
||||
This is the reference manual for the Go programming language.
|
||||
The pre-Go1.18 version, without generics, can be found
|
||||
<a href="/doc/go1.17_spec.html">here</a>.
|
||||
For more information and other documents, see <a href="/">golang.org</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
|
@ -766,7 +756,7 @@ type given in its declaration, the type provided in the
|
|||
<code>new</code> call or composite literal, or the type of
|
||||
an element of a structured variable.
|
||||
Variables of interface type also have a distinct <i>dynamic type</i>,
|
||||
which is the concrete type of the value assigned to the variable at run time
|
||||
which is the (non-interface) type of the value assigned to the variable at run time
|
||||
(unless the value is the predeclared identifier <code>nil</code>,
|
||||
which has no type).
|
||||
The dynamic type may vary during execution but values stored in interface
|
||||
|
|
@ -812,7 +802,7 @@ TypeLit = ArrayType | StructType | PointerType | FunctionType | InterfaceType
|
|||
<p>
|
||||
The language <a href="#Predeclared_identifiers">predeclares</a> certain type names.
|
||||
Others are introduced with <a href="#Type_declarations">type declarations</a>
|
||||
or <a href="#Type_parameter_lists">type parameter lists</a>.
|
||||
or <a href="#Type_parameter_declarations">type parameter lists</a>.
|
||||
<i>Composite types</i>—array, struct, pointer, function,
|
||||
interface, slice, map, and channel types—may be constructed using
|
||||
type literals.
|
||||
|
|
@ -987,7 +977,7 @@ built-in function <a href="#Length_and_capacity"><code>cap(a)</code></a>.
|
|||
</p>
|
||||
|
||||
<p>
|
||||
A new, initialized slice value for a given element type <code>T</code> is
|
||||
A new, initialized slice value for a given element type <code>T</code> may be
|
||||
made using the built-in function
|
||||
<a href="#Making_slices_maps_and_channels"><code>make</code></a>,
|
||||
which takes a slice type
|
||||
|
|
@ -1422,7 +1412,7 @@ interface {
|
|||
~int
|
||||
}
|
||||
|
||||
// An interface representing all types with underlying type int which implement the String method.
|
||||
// An interface representing all types with underlying type int that implement the String method.
|
||||
interface {
|
||||
~int
|
||||
String() string
|
||||
|
|
@ -1455,32 +1445,32 @@ Union elements denote unions of type sets:
|
|||
</p>
|
||||
|
||||
<pre>
|
||||
// The Floats interface represents all floating-point types
|
||||
// The Float interface represents all floating-point types
|
||||
// (including any named types whose underlying types are
|
||||
// either float32 or float64).
|
||||
type Floats interface {
|
||||
type Float interface {
|
||||
~float32 | ~float64
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
In a union, a term cannot be a type parameter, and the type sets of all
|
||||
In a union, a term cannot be a <a href="#Type_parameter_declarations">type parameter</a>, and the type sets of all
|
||||
non-interface terms must be pairwise disjoint (the pairwise intersection of the type sets must be empty).
|
||||
Given a type parameter <code>P</code>:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
interface {
|
||||
P // illegal: the term P is a type parameter
|
||||
int | P // illegal: the term P is a type parameter
|
||||
~int | MyInt // illegal: the type sets for ~int and MyInt are not disjoint (~int includes MyInt)
|
||||
float32 | Floats // overlapping type sets but Floats is an interface
|
||||
P // illegal: P is a type parameter
|
||||
int | P // illegal: P is a type parameter
|
||||
~int | MyInt // illegal: the type sets for ~int and MyInt are not disjoint (~int includes MyInt)
|
||||
float32 | Float // overlapping type sets but Float is an interface
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Implementation restriction:
|
||||
A union with more than one term cannot contain the
|
||||
A union (with more than one term) cannot contain the
|
||||
<a href="#Predeclared_identifiers">predeclared identifier</a> <code>comparable</code>
|
||||
or interfaces that specify methods, or embed <code>comparable</code> or interfaces
|
||||
that specify methods.
|
||||
|
|
@ -1494,12 +1484,12 @@ non-interface types.
|
|||
</p>
|
||||
|
||||
<pre>
|
||||
var x Floats // illegal: Floats is not a basic interface
|
||||
var x Float // illegal: Float is not a basic interface
|
||||
|
||||
var x interface{} = Floats(nil) // illegal
|
||||
var x interface{} = Float(nil) // illegal
|
||||
|
||||
type Floatish struct {
|
||||
f Floats // illegal
|
||||
f Float // illegal
|
||||
}
|
||||
</pre>
|
||||
|
||||
|
|
@ -1545,7 +1535,7 @@ A type <code>T</code> implements an interface <code>I</code> if
|
|||
</ul>
|
||||
|
||||
<p>
|
||||
A value <code>x</code> of type <code>T</code> implements an interface if <code>T</code>
|
||||
A value of type <code>T</code> implements an interface if <code>T</code>
|
||||
implements the interface.
|
||||
</p>
|
||||
|
||||
|
|
@ -1701,10 +1691,9 @@ Each type <code>T</code> has an <i>underlying type</i>: If <code>T</code>
|
|||
is one of the predeclared boolean, numeric, or string types, or a type literal,
|
||||
the corresponding underlying type is <code>T</code> itself.
|
||||
Otherwise, <code>T</code>'s underlying type is the underlying type of the
|
||||
type to which <code>T</code> refers in its <a href="#Type_declarations">type
|
||||
declaration</a>. The underlying type of a type parameter is the
|
||||
underlying type of its <a href="#Type_constraints">type constraint</a>, which
|
||||
is always an interface.
|
||||
type to which <code>T</code> refers in its declaration.
|
||||
For a type parameter that is the underlying type of its
|
||||
<a href="#Type_constraints">type constraint</a>, which is always an interface.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
|
|
@ -1755,7 +1744,7 @@ direction.
|
|||
</ol>
|
||||
|
||||
<p>
|
||||
All other interfaces don't have a core type.
|
||||
No other interfaces have a core type.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
|
@ -1775,7 +1764,7 @@ depending on the direction of the directional channels present.
|
|||
|
||||
<p>
|
||||
By definition, a core type is never a <a href="#Type_definitions">defined type</a>,
|
||||
<a href="#Type_parameter_lists">type parameter</a>, or
|
||||
<a href="#Type_parameter_declarations">type parameter</a>, or
|
||||
<a href="#Interface_types">interface type</a>.
|
||||
</p>
|
||||
|
||||
|
|
@ -1795,7 +1784,7 @@ interface{ ~[]*data; String() string } // []*data
|
|||
</pre>
|
||||
|
||||
<p>
|
||||
Examples of interfaces whithout core types:
|
||||
Examples of interfaces without core types:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
|
|
@ -1805,70 +1794,6 @@ interface{ chan int | chan<- string } // channels have different element
|
|||
interface{ <-chan int | chan<- int } // directional channels have different directions
|
||||
</pre>
|
||||
|
||||
<h3 id="Specific_types">Specific types</h3>
|
||||
|
||||
<p><b>
|
||||
[The definition of specific types is not quite correct yet.]
|
||||
</b></p>
|
||||
|
||||
<p>
|
||||
An interface specification that contains <a href="#Interface_types">type elements</a>
|
||||
defines a (possibly empty) set of <i>specific types</i>.
|
||||
Loosely speaking, these are the types <code>T</code> that appear in the
|
||||
interface definition in terms of the form <code>T</code>, <code>~T</code>,
|
||||
or in unions of such terms.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
More precisely, for a given interface, the set of specific types corresponds to
|
||||
the set 𝑅 of representative types of the interface, if 𝑅 is non-empty and finite.
|
||||
Otherwise, if 𝑅 is empty or infinite, the interface has <i>no specific types</i>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For a given interface, type element or type term, the set 𝑅 of representative types is defined as follows:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>For an interface with no type elements, 𝑅 is the (infinite) set of all types.
|
||||
</li>
|
||||
|
||||
<li>For an interface with type elements,
|
||||
𝑅 is the intersection of the representative types of its type elements.
|
||||
</li>
|
||||
|
||||
<li>For a non-interface type term <code>T</code> or a term of the form <code>~T</code>,
|
||||
𝑅 is the set consisting of the type <code>T</code>.
|
||||
</li>
|
||||
|
||||
<li>For a <i>union</i> of terms
|
||||
<code>t<sub>1</sub>|t<sub>2</sub>|…|t<sub>n</sub></code>,
|
||||
𝑅 is the union of the representative types of the terms.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
An interface may have specific types even if its <a href="#Interface_types">type set</a>
|
||||
is empty.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Examples of interfaces with their specific types:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
interface{} // no specific types
|
||||
interface{ int } // int
|
||||
interface{ ~string } // string
|
||||
interface{ int|~string } // int, string
|
||||
interface{ Celsius|Kelvin } // Celsius, Kelvin
|
||||
interface{ float64|any } // no specific types (union is all types)
|
||||
interface{ int; m() } // int (but type set is empty because int has no method m)
|
||||
interface{ ~int; m() } // int (but type set is infinite because many integer types have a method m)
|
||||
interface{ int; any } // int
|
||||
interface{ int; string } // no specific types (intersection is empty)
|
||||
</pre>
|
||||
|
||||
<h3 id="Type_identity">Type identity</h3>
|
||||
|
||||
<p>
|
||||
|
|
@ -1973,21 +1898,21 @@ defined type while the latter is a type literal
|
|||
<h3 id="Assignability">Assignability</h3>
|
||||
|
||||
<p>
|
||||
A value <code>x</code> is <i>assignable</i> to a <a href="#Variables">variable</a> of type <code>T</code>
|
||||
A value <code>x</code> of type <code>V</code> is <i>assignable</i> to a <a href="#Variables">variable</a> of type <code>T</code>
|
||||
("<code>x</code> is assignable to <code>T</code>") if one of the following conditions applies:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<code>x</code>'s type is identical to <code>T</code>.
|
||||
<code>V</code> and <code>T</code> are identical.
|
||||
</li>
|
||||
<li>
|
||||
<code>x</code>'s type <code>V</code> and <code>T</code> have identical
|
||||
<code>V</code> and <code>T</code> have identical
|
||||
<a href="#Underlying_types">underlying types</a> and at least one of <code>V</code>
|
||||
or <code>T</code> is not a <a href="#Types">named type</a>.
|
||||
</li>
|
||||
<li>
|
||||
<code>x</code>'s type <code>V</code> and <code>T</code> are channel types with
|
||||
<code>V</code> and <code>T</code> are channel types with
|
||||
identical element types, <code>V</code> is a bidirectional channel,
|
||||
and at least one of <code>V</code> or <code>T</code> is not a <a href="#Types">named type</a>.
|
||||
</li>
|
||||
|
|
@ -2008,25 +1933,24 @@ by a value of type <code>T</code>.
|
|||
</ul>
|
||||
|
||||
<p>
|
||||
Additionally, if <code>x</code>'s type <code>V</code> or <code>T</code> are type parameters
|
||||
with <a href="#Specific_types">specific types</a>, <code>x</code>
|
||||
Additionally, if <code>x</code>'s type <code>V</code> or <code>T</code> are type parameters, <code>x</code>
|
||||
is assignable to a variable of type <code>T</code> if one of the following conditions applies:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<code>x</code> is the predeclared identifier <code>nil</code>, <code>T</code> is
|
||||
a type parameter, and <code>x</code> is assignable to each specific type of
|
||||
<code>T</code>.
|
||||
a type parameter, and <code>x</code> is assignable to each type in
|
||||
<code>T</code>'s type set.
|
||||
</li>
|
||||
<li>
|
||||
<code>V</code> is not a <a href="#Types">named type</a>, <code>T</code> is
|
||||
a type parameter, and <code>x</code> is assignable to each specific type of
|
||||
<code>T</code>.
|
||||
a type parameter, and <code>x</code> is assignable to each type in
|
||||
<code>T</code>'s type set.
|
||||
</li>
|
||||
<li>
|
||||
<code>V</code> is a type parameter and <code>T</code> is not a named type,
|
||||
and values of each specific type of <code>V</code> are assignable
|
||||
and values of each type in <code>V</code>'s type set are assignable
|
||||
to <code>T</code>.
|
||||
</li>
|
||||
</ul>
|
||||
|
|
@ -2036,7 +1960,7 @@ to <code>T</code>.
|
|||
<p>
|
||||
A <a href="#Constants">constant</a> <code>x</code> is <i>representable</i>
|
||||
by a value of type <code>T</code>,
|
||||
where <code>T</code> is not a <a href="#Type_parameter_lists">type parameter</a>,
|
||||
where <code>T</code> is not a <a href="#Type_parameter_declarations">type parameter</a>,
|
||||
if one of the following conditions applies:
|
||||
</p>
|
||||
|
||||
|
|
@ -2061,9 +1985,9 @@ are representable by values of <code>T</code>'s component type (<code>float32</c
|
|||
</ul>
|
||||
|
||||
<p>
|
||||
If <code>T</code> is a type parameter with <a href="#Specific_types">specific types</a>,
|
||||
If <code>T</code> is a type parameter,
|
||||
<code>x</code> is representable by a value of type <code>T</code> if <code>x</code> is representable
|
||||
by a value of each specific type of <code>T</code>.
|
||||
by a value of each type in <code>T</code>'s type set.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
|
|
@ -2176,6 +2100,7 @@ Blocks nest and influence <a href="#Declarations_and_scope">scoping</a>.
|
|||
A <i>declaration</i> binds a non-<a href="#Blank_identifier">blank</a> identifier to a
|
||||
<a href="#Constant_declarations">constant</a>,
|
||||
<a href="#Type_declarations">type</a>,
|
||||
<a href="#Type_parameter_declarations">type parameter</a>,
|
||||
<a href="#Variable_declarations">variable</a>,
|
||||
<a href="#Function_declarations">function</a>,
|
||||
<a href="#Labeled_statements">label</a>, or
|
||||
|
|
@ -2220,13 +2145,13 @@ Go is lexically scoped using <a href="#Blocks">blocks</a>:
|
|||
<li>The scope of an identifier denoting a method receiver, function parameter,
|
||||
or result variable is the function body.</li>
|
||||
|
||||
<li>The scope of an identifier denoting a type parameter of a generic function
|
||||
<li>The scope of an identifier denoting a type parameter of a function
|
||||
or declared by a method receiver is the function body and all parameter lists of the
|
||||
function.
|
||||
</li>
|
||||
|
||||
<li>The scope of an identifier denoting a type parameter of a generic type
|
||||
begins after the name of the generic type and ends at the end
|
||||
<li>The scope of an identifier denoting a type parameter of a type
|
||||
begins after the name of the type and ends at the end
|
||||
of the TypeSpec.</li>
|
||||
|
||||
<li>The scope of a constant or variable identifier declared
|
||||
|
|
@ -2512,7 +2437,7 @@ type (
|
|||
|
||||
type TreeNode struct {
|
||||
left, right *TreeNode
|
||||
value *Comparable
|
||||
value any
|
||||
}
|
||||
|
||||
type Block interface {
|
||||
|
|
@ -2573,7 +2498,7 @@ func (tz TimeZone) String() string {
|
|||
</pre>
|
||||
|
||||
<p>
|
||||
If the type definition specifies <a href="#Type_parameter_lists">type parameters</a>,
|
||||
If the type definition specifies <a href="#Type_parameter_declarations">type parameters</a>,
|
||||
the type name denotes a <i>generic type</i>.
|
||||
Generic types must be <a href="#Instantiations">instantiated</a> when they
|
||||
are used.
|
||||
|
|
@ -2584,15 +2509,10 @@ type List[T any] struct {
|
|||
next *List[T]
|
||||
value T
|
||||
}
|
||||
|
||||
type Tree[T constraints.Ordered] struct {
|
||||
left, right *Tree[T]
|
||||
value T
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The given type cannot be a type parameter in a type definition.
|
||||
In a type definition the given type cannot be a type parameter.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
|
|
@ -2604,8 +2524,8 @@ func f[T any]() {
|
|||
</pre>
|
||||
|
||||
<p>
|
||||
A generic type may also have methods associated with it. In this case,
|
||||
the method receivers must declare the same number of type parameters as
|
||||
A generic type may also have <a href="#Method_declarations">methods</a> associated with it.
|
||||
In this case, the method receivers must declare the same number of type parameters as
|
||||
present in the generic type definition.
|
||||
</p>
|
||||
|
||||
|
|
@ -2614,7 +2534,7 @@ present in the generic type definition.
|
|||
func (l *List[T]) Len() int { … }
|
||||
</pre>
|
||||
|
||||
<h3 id="Type_parameter_lists">Type parameter lists</h3>
|
||||
<h3 id="Type_parameter_declarations">Type parameter declarations</h3>
|
||||
|
||||
<p>
|
||||
A type parameter list declares the <i>type parameters</i> of a generic function or type declaration.
|
||||
|
|
@ -2653,22 +2573,22 @@ has a corresponding (meta-)type which is called its
|
|||
|
||||
<p>
|
||||
A parsing ambiguity arises when the type parameter list for a generic type
|
||||
declares a single type parameter with a type constraint of the form <code>*C</code>
|
||||
or <code>(C)</code> where <code>C</code> is not a (possibly parenthesized)
|
||||
<a href="#Types">type literal</a>:
|
||||
declares a single type parameter <code>P</code> with a constraint <code>C</code>
|
||||
such that the text <code>P C</code> forms a valid expression:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
type T[P *C] …
|
||||
type T[P (C)] …
|
||||
type T[P *C|Q] …
|
||||
…
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
In these rare cases, the type parameter declaration is indistinguishable from
|
||||
the expressions <code>P*C</code> or <code>P(C)</code> and the type declaration
|
||||
is parsed as an array type declaration.
|
||||
To resolve the ambiguity, embed the constraint in an interface or use a trailing
|
||||
comma:
|
||||
In these rare cases, the type parameter list is indistinguishable from an
|
||||
expression and the type declaration is parsed as an array type declaration.
|
||||
To resolve the ambiguity, embed the constraint in an
|
||||
<a href="#Interface_types">interface</a> or use a trailing comma:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
|
|
@ -2682,6 +2602,11 @@ of a <a href="#Method_declarations">method declaration</a> associated
|
|||
with a generic type.
|
||||
</p>
|
||||
|
||||
<!--
|
||||
This section needs to explain if and what kind of cycles are permitted
|
||||
using type parameters in a type parameter list.
|
||||
-->
|
||||
|
||||
<h4 id="Type_constraints">Type constraints</h4>
|
||||
|
||||
<p>
|
||||
|
|
@ -2701,10 +2626,10 @@ the enclosing <code>interface{ … }</code> may be omitted for convenience:
|
|||
</p>
|
||||
|
||||
<pre>
|
||||
[T *P] // = [T interface{*P}]
|
||||
[T ~int] // = [T interface{~int}]
|
||||
[T int|string] // = [T interface{int|string}]
|
||||
type Constraint ~int // illegal: ~int is not inside a type parameter list
|
||||
[T []P] // = [T interface{[]P}]
|
||||
[T ~int] // = [T interface{~int}]
|
||||
[T int|string] // = [T interface{int|string}]
|
||||
type Constraint ~int // illegal: ~int is not inside a type parameter list
|
||||
</pre>
|
||||
|
||||
<!--
|
||||
|
|
@ -2716,7 +2641,7 @@ other interfaces based on their type sets. But this should get us going for now.
|
|||
<p>
|
||||
The <a href="#Predeclared_identifiers">predeclared</a>
|
||||
<a href="#Interface_types">interface type</a> <code>comparable</code>
|
||||
denotes the set of all concrete (non-interface) types that are
|
||||
denotes the set of all non-interface types that are
|
||||
<a href="#Comparison_operators">comparable</a>. Specifically,
|
||||
a type <code>T</code> implements <code>comparable</code> if:
|
||||
</p>
|
||||
|
|
@ -2897,14 +2822,14 @@ func IndexRune(s string, r rune) int {
|
|||
</pre>
|
||||
|
||||
<p>
|
||||
If the function declaration specifies <a href="#Type_parameter_lists">type parameters</a>,
|
||||
If the function declaration specifies <a href="#Type_parameter_declarations">type parameters</a>,
|
||||
the function name denotes a <i>generic function</i>.
|
||||
Generic functions must be <a href="#Instantiations">instantiated</a> when they
|
||||
are used.
|
||||
A generic function must be <a href="#Instantiations">instantiated</a> before it can be
|
||||
called or used as a value.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
func min[T constraints.Ordered](x, y T) T {
|
||||
func min[T ~int|~float64](x, y T) T {
|
||||
if x < y {
|
||||
return x
|
||||
}
|
||||
|
|
@ -2963,7 +2888,7 @@ the non-blank method and field names must be distinct.
|
|||
</p>
|
||||
|
||||
<p>
|
||||
Given defined type <code>Point</code>, the declarations
|
||||
Given defined type <code>Point</code> the declarations
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
|
|
@ -2987,13 +2912,10 @@ to the base type <code>Point</code>.
|
|||
If the receiver base type is a <a href="#Type_declarations">generic type</a>, the
|
||||
receiver specification must declare corresponding type parameters for the method
|
||||
to use. This makes the receiver type parameters available to the method.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Syntactically, this type parameter declaration looks like an
|
||||
<a href="#Instantiations">instantiation</a> of the receiver base type, except that
|
||||
the type arguments are the type parameters being declared, one for each type parameter
|
||||
of the receiver base type.
|
||||
<a href="#Instantiations">instantiation</a> of the receiver base type: the type
|
||||
arguments must be identifiers denoting the type parameters being declared, one
|
||||
for each type parameter of the receiver base type.
|
||||
The type parameter names do not need to match their corresponding parameter names in the
|
||||
receiver base type definition, and all non-blank parameter names must be unique in the
|
||||
receiver parameter section and the method signature.
|
||||
|
|
@ -3007,8 +2929,8 @@ type Pair[A, B any] struct {
|
|||
b B
|
||||
}
|
||||
|
||||
func (p Pair[A, B]) Swap() Pair[B, A] { return Pair[B, A]{p.b, p.a} }
|
||||
func (p Pair[First, _]) First() First { return p.a }
|
||||
func (p Pair[A, B]) Swap() Pair[B, A] { … } // receiver declares A, B
|
||||
func (p Pair[First, _]) First() First { … } // receiver declares First, corresponds to A in Pair
|
||||
</pre>
|
||||
|
||||
<h2 id="Expressions">Expressions</h2>
|
||||
|
|
@ -3048,6 +2970,14 @@ The <a href="#Blank_identifier">blank identifier</a> may appear as an
|
|||
operand only on the left-hand side of an <a href="#Assignments">assignment</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Implementation restriction: A compiler need not report an error if an operand's
|
||||
type is a <a href="#Type_parameter_declarations">type parameter</a> with an empty
|
||||
<a href="#Interface_types">type set</a>. Functions with such type parameters
|
||||
cannot be <a href="#Instantiations">instantiated</a>; any attempt will lead
|
||||
to an error at the instantiation site.
|
||||
</p>
|
||||
|
||||
<h3 id="Qualified_identifiers">Qualified identifiers</h3>
|
||||
|
||||
<p>
|
||||
|
|
@ -3354,10 +3284,6 @@ f.p[i].x()
|
|||
|
||||
<h3 id="Selectors">Selectors</h3>
|
||||
|
||||
<p><b>
|
||||
[This section is missing rules for x.f where x's type is a type parameter and f is a field.]
|
||||
</b></p>
|
||||
|
||||
<p>
|
||||
For a <a href="#Primary_expressions">primary expression</a> <code>x</code>
|
||||
that is not a <a href="#Package_clause">package name</a>, the
|
||||
|
|
@ -3758,7 +3684,7 @@ The following rules apply:
|
|||
</p>
|
||||
|
||||
<p>
|
||||
If <code>a</code> is not a map:
|
||||
If <code>a</code> is neither a map nor a type parameter:
|
||||
</p>
|
||||
<ul>
|
||||
<li>the index <code>x</code> must be an untyped constant or its
|
||||
|
|
@ -3827,23 +3753,22 @@ For <code>a</code> of <a href="#Map_types">map type</a> <code>M</code>:
|
|||
</ul>
|
||||
|
||||
<p>
|
||||
For <code>a</code> of <a href="#Type_parameter_lists">type parameter type</a> <code>P</code>:
|
||||
For <code>a</code> of <a href="#Type_parameter_declarations">type parameter type</a> <code>P</code>:
|
||||
</p>
|
||||
<ul>
|
||||
<li><code>P</code> must have <a href="#Specific_types">specific types</a>.</li>
|
||||
<li>The index expression <code>a[x]</code> must be valid for values
|
||||
of all specific types of <code>P</code>.</li>
|
||||
<li>The element types of all specific types of <code>P</code> must be identical.
|
||||
of all types in <code>P</code>'s type set.</li>
|
||||
<li>The element types of all types in <code>P</code>'s type set must be identical.
|
||||
In this context, the element type of a string type is <code>byte</code>.</li>
|
||||
<li>If there is a map type among the specific types of <code>P</code>,
|
||||
all specific types must be map types, and the respective key types
|
||||
<li>If there is a map type in the type set of <code>P</code>,
|
||||
all types in that type set must be map types, and the respective key types
|
||||
must be all identical.</li>
|
||||
<li><code>a[x]</code> is the array, slice, or string element at index <code>x</code>,
|
||||
or the map element with key <code>x</code> of the type argument
|
||||
that <code>P</code> is instantiated with, and the type of <code>a[x]</code> is
|
||||
the type of the (identical) element types.</li>
|
||||
<li><code>a[x]</code> may not be assigned to if the specific types of <code>P</code>
|
||||
include string types.
|
||||
<li><code>a[x]</code> may not be assigned to if <code>P</code>'s type set
|
||||
includes string types.
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
|
|
@ -4021,7 +3946,7 @@ If the indices are out of range at run time, a <a href="#Run_time_panics">run-ti
|
|||
|
||||
<p>
|
||||
For an expression <code>x</code> of <a href="#Interface_types">interface type</a>,
|
||||
but not a <a href="#Type_parameter_lists">type parameter</a>, and a type <code>T</code>,
|
||||
but not a <a href="#Type_parameter_declarations">type parameter</a>, and a type <code>T</code>,
|
||||
the primary expression
|
||||
</p>
|
||||
|
||||
|
|
@ -4236,7 +4161,7 @@ with the same underlying array.
|
|||
<p>
|
||||
A generic function or type is <i>instantiated</i> by substituting <i>type arguments</i>
|
||||
for the type parameters.
|
||||
Instantiation proceeds in two phases:
|
||||
Instantiation proceeds in two steps:
|
||||
</p>
|
||||
|
||||
<ol>
|
||||
|
|
@ -4249,7 +4174,7 @@ including the type parameter list itself and any types in that list.
|
|||
|
||||
<li>
|
||||
After substitution, each type argument must <a href="#Interface_types">implement</a>
|
||||
the <a href="#Type_parameter_lists">constraint</a> (instantiated, if necessary)
|
||||
the <a href="#Type_parameter_declarations">constraint</a> (instantiated, if necessary)
|
||||
of the corresponding type parameter. Otherwise instantiation fails.
|
||||
</li>
|
||||
</ol>
|
||||
|
|
@ -4262,55 +4187,57 @@ instantiating a function produces a new non-generic function.
|
|||
<pre>
|
||||
type parameter list type arguments after substitution
|
||||
|
||||
[P any] int [int any]
|
||||
[S ~[]E, E any] []int, int [[]int ~[]int, int any]
|
||||
[P io.Writer] string [string io.Writer] // illegal: string doesn't implement io.Writer
|
||||
[P any] int int implements any
|
||||
[S ~[]E, E any] []int, int []int implements ~[]int, int implements any
|
||||
[P io.Writer] string illegal: string doesn't implement io.Writer
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Type arguments may be provided explicitly, or they may be partially or completely
|
||||
<a href="#Type_inference">inferred</a>.
|
||||
A partially provided type argument list cannot be empty; there must be at least the
|
||||
first argument.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
type T[P1 ~int, P2 ~[]P1] struct{ … }
|
||||
|
||||
T[] // illegal: at least the first type argument must be present, even if it could be inferred
|
||||
T[int] // argument for P1 explicitly provided, argument for P2 inferred
|
||||
T[int, []int] // both arguments explicitly provided
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
A partial type argument list specifies a prefix of the full list of type arguments, leaving
|
||||
the remaining arguments to be inferred. Loosely speaking, type arguments may be omitted from
|
||||
"right to left".
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Generic types, and generic functions that are not <a href="#Calls">called</a>,
|
||||
require a type argument list for instantiation; if the list is partial, all
|
||||
For a generic function, type arguments may be provided explicitly, or they
|
||||
may be partially or completely <a href="#Type_inference">inferred</a>.
|
||||
A generic function that is is <i>not</i> <a href="#Calls">called</a> requires a
|
||||
type argument list for instantiation; if the list is partial, all
|
||||
remaining type arguments must be inferrable.
|
||||
Calls to generic functions may provide a (possibly partial) type
|
||||
A generic function that is called may provide a (possibly partial) type
|
||||
argument list, or may omit it entirely if the omitted type arguments are
|
||||
inferrable from the ordinary (non-type) function arguments.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
func min[T constraints.Ordered](x, y T) T { … }
|
||||
func min[T ~int|~float64](x, y T) T { … }
|
||||
|
||||
f := min // illegal: min must be instantiated when used without being called
|
||||
f := min // illegal: min must be instantiated with type arguments when used without being called
|
||||
minInt := min[int] // minInt has type func(x, y int) int
|
||||
a := minInt(2, 3) // a has value 2 of type int
|
||||
b := min[float64](2.0, 3) // b has value 2.0 of type float64
|
||||
c := min(b, -1) // c has value -1.0 of type float64
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
A partial type argument list cannot be empty; at least the first argument must be present.
|
||||
The list is a prefix of the full list of type arguments, leaving the remaining arguments
|
||||
to be inferred. Loosely speaking, type arguments may be omitted from "right to left".
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
func apply[S ~[]E, E any](s S, f(E) E) S { … }
|
||||
|
||||
f0 := apply[] // illegal: type argument list cannot be empty
|
||||
f1 := apply[[]int] // type argument for S explicitly provided, type argument for E inferred
|
||||
f2 := apply[[]string, string] // both type arguments explicitly provided
|
||||
|
||||
var bytes []byte
|
||||
r := apply(bytes, func(byte) byte { … }) // both type arguments inferred from the function arguments
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
For a generic type, all type arguments must always be provided explicitly.
|
||||
</p>
|
||||
|
||||
<h3 id="Type_inference">Type inference</h3>
|
||||
|
||||
<p>
|
||||
Missing type arguments may be <i>inferred</i> by a series of steps, described below.
|
||||
Missing function type arguments may be <i>inferred</i> by a series of steps, described below.
|
||||
Each step attempts to use known information to infer additional type arguments.
|
||||
Type inference stops as soon as all type arguments are known.
|
||||
After type inference is complete, it is still necessary to substitute all type arguments
|
||||
|
|
@ -4326,7 +4253,7 @@ Type inference is based on
|
|||
|
||||
<ul>
|
||||
<li>
|
||||
a <a href="#Type_parameter_lists">type parameter list</a>
|
||||
a <a href="#Type_parameter_declarations">type parameter list</a>
|
||||
</li>
|
||||
<li>
|
||||
a substitution map <i>M</i> initialized with the known type arguments, if any
|
||||
|
|
@ -4491,9 +4418,8 @@ unresolved type parameters left.
|
|||
</p>
|
||||
|
||||
<p>
|
||||
Function argument type inference can be used when the function has ordinary parameters
|
||||
whose types are defined using the function's type parameters. Inference happens in two
|
||||
separate phases; each phase operates on a specific list of (parameter, argument) pairs:
|
||||
Inference happens in two separate phases; each phase operates on a specific list of
|
||||
(parameter, argument) pairs:
|
||||
</p>
|
||||
|
||||
<ol>
|
||||
|
|
@ -4550,7 +4476,7 @@ Example:
|
|||
</p>
|
||||
|
||||
<pre>
|
||||
func min[T constraints.Ordered](x, y T) T
|
||||
func min[T ~int|~float64](x, y T) T
|
||||
|
||||
var x int
|
||||
min(x, 2.0) // T is int, inferred from typed argument x; 2.0 is assignable to int
|
||||
|
|
@ -4841,9 +4767,8 @@ The bitwise logical and shift operators apply to integers only.
|
|||
</pre>
|
||||
|
||||
<p>
|
||||
Excluding shifts, if the operand type is a <a href="#Type_parameter_lists">type parameter</a>,
|
||||
it must have <a href="#Specific_types">specific types</a>, and the operator must
|
||||
apply to each specific type.
|
||||
If the operand type is a <a href="#Type_parameter_declarations">type parameter</a>,
|
||||
the operator must apply to each type in that type set.
|
||||
The operands are represented as values of the type argument that the type parameter
|
||||
is <a href="#Instantiations">instantiated</a> with, and the operation is computed
|
||||
with the precision of that type argument. For example, given the function:
|
||||
|
|
@ -4866,11 +4791,6 @@ are computed with <code>float32</code> or <code>float64</code> precision,
|
|||
respectively, depending on the type argument for <code>F</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For shifts, the <a href="#Core_types">core type</a> of both operands must be
|
||||
an integer.
|
||||
</p>
|
||||
|
||||
<h4 id="Integer_operators">Integer operators</h4>
|
||||
|
||||
<p>
|
||||
|
|
@ -5296,7 +5216,7 @@ as for non-constant <code>x</code>.
|
|||
</p>
|
||||
|
||||
<p>
|
||||
Converting a constant to a type that is not a <a href="#Type_parameter_lists">type parameter</a>
|
||||
Converting a constant to a type that is not a <a href="#Type_parameter_declarations">type parameter</a>
|
||||
yields a typed constant.
|
||||
</p>
|
||||
|
||||
|
|
@ -5351,7 +5271,7 @@ in any of these cases:
|
|||
<li>
|
||||
ignoring struct tags (see below),
|
||||
<code>x</code>'s type and <code>T</code> are not
|
||||
<a href="#Type_parameter_lists">type parameters</a> but have
|
||||
<a href="#Type_parameter_declarations">type parameters</a> but have
|
||||
<a href="#Type_identity">identical</a> <a href="#Types">underlying types</a>.
|
||||
</li>
|
||||
<li>
|
||||
|
|
@ -5383,23 +5303,23 @@ in any of these cases:
|
|||
|
||||
<p>
|
||||
Additionally, if <code>T</code> or <code>x</code>'s type <code>V</code> are type
|
||||
parameters with <a href="#Specific_types">specific types</a>, <code>x</code>
|
||||
parameters, <code>x</code>
|
||||
can also be converted to type <code>T</code> if one of the following conditions applies:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Both <code>V</code> and <code>T</code> are type parameters and a value of each
|
||||
specific type of <code>V</code> can be converted to each specific type
|
||||
of <code>T</code>.
|
||||
type in <code>V</code>'s type set can be converted to each type in <code>T</code>'s
|
||||
type set.
|
||||
</li>
|
||||
<li>
|
||||
Only <code>V</code> is a type parameter and a value of each
|
||||
specific type of <code>V</code> can be converted to <code>T</code>.
|
||||
type in <code>V</code>'s type set can be converted to <code>T</code>.
|
||||
</li>
|
||||
<li>
|
||||
Only <code>T</code> is a type parameter and <code>x</code> can be converted to each
|
||||
specific type of <code>T</code>.
|
||||
type in <code>T</code>'s type set.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
|
@ -6270,7 +6190,7 @@ switch x.(type) {
|
|||
Cases then match actual types <code>T</code> against the dynamic type of the
|
||||
expression <code>x</code>. As with type assertions, <code>x</code> must be of
|
||||
<a href="#Interface_types">interface type</a>, but not a
|
||||
<a href="#Type_parameter_lists">type parameter</a>, and each non-interface type
|
||||
<a href="#Type_parameter_declarations">type parameter</a>, and each non-interface type
|
||||
<code>T</code> listed in a case must implement the type of <code>x</code>.
|
||||
The types listed in the cases of a type switch must all be
|
||||
<a href="#Type_identity">different</a>.
|
||||
|
|
@ -6352,7 +6272,7 @@ if v == nil {
|
|||
</pre>
|
||||
|
||||
<p>
|
||||
A <a href="#Type_parameter_lists">type parameter</a> or a <a href="#Type_declarations">generic type</a>
|
||||
A <a href="#Type_parameter_declarations">type parameter</a> or a <a href="#Type_declarations">generic type</a>
|
||||
may be used as a type in a case. If upon <a href="#Instantiations">instantiation</a> that type turns
|
||||
out to duplicate another entry in the switch, the first matching case is chosen.
|
||||
</p>
|
||||
|
|
@ -7093,10 +7013,9 @@ cap(s) [n]T, *[n]T array length (== n)
|
|||
</pre>
|
||||
|
||||
<p>
|
||||
If the argument type is a <a href="#Type_parameter_lists">type parameter</a> <code>P</code>,
|
||||
<code>P</code> must have <a href="#Specific_types">specific types</a>, and
|
||||
If the argument type is a <a href="#Type_parameter_declarations">type parameter</a> <code>P</code>,
|
||||
the call <code>len(e)</code> (or <code>cap(e)</code> respectively) must be valid for
|
||||
each specific type of <code>P</code>.
|
||||
each type in <code>P</code>'s type set.
|
||||
The result is the length (or capacity, respectively) of the argument whose type
|
||||
corresponds to the type argument with which <code>P</code> was
|
||||
<a href="#Instantiations">instantiated</a>.
|
||||
|
|
@ -7197,8 +7116,9 @@ make(T, n) channel buffered channel of type T, buffer size n
|
|||
|
||||
|
||||
<p>
|
||||
Each of the size arguments <code>n</code> and <code>m</code> must be of <a href="#Numeric_types">integer type</a>
|
||||
or an untyped <a href="#Constants">constant</a>.
|
||||
Each of the size arguments <code>n</code> and <code>m</code> must be of <a href="#Numeric_types">integer type</a>,
|
||||
have a <a href="#Interface_types">type set</a> containing only integer types,
|
||||
or be an untyped <a href="#Constants">constant</a>.
|
||||
A constant size argument must be non-negative and <a href="#Representability">representable</a>
|
||||
by a value of type <code>int</code>; if it is an untyped constant it is given type <code>int</code>.
|
||||
If both <code>n</code> and <code>m</code> are provided and are constant, then
|
||||
|
|
@ -7235,9 +7155,9 @@ by the arguments overlaps.
|
|||
<p>
|
||||
The <a href="#Function_types">variadic</a> function <code>append</code>
|
||||
appends zero or more values <code>x</code> to a slice <code>s</code>
|
||||
and returns the resulting slice.
|
||||
and returns the resulting slice of the same type as <code>s</code>.
|
||||
The <a href="#Core_types">core type</a> of <code>s</code> must be a slice
|
||||
of the form <code>[]E</code>.
|
||||
of type <code>[]E</code>.
|
||||
The values <code>x</code> are passed to a parameter of type <code>...E</code>
|
||||
and the respective <a href="#Passing_arguments_to_..._parameters">parameter
|
||||
passing rules</a> apply.
|
||||
|
|
@ -7247,7 +7167,7 @@ followed by <code>...</code>. This form appends the bytes of the string.
|
|||
</p>
|
||||
|
||||
<pre class="grammar">
|
||||
append(s S, x ...E) S // E is the element type of the core type of S
|
||||
append(s S, x ...E) S // core type of S is []E
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
|
|
@ -7317,9 +7237,8 @@ delete(m, k) // remove element m[k] from map m
|
|||
</pre>
|
||||
|
||||
<p>
|
||||
If the type of <code>m</code> is a <a href="#Type_parameter_lists">type parameter</a>,
|
||||
it must have <a href="#Specific_types">specific types</a>, all specific types
|
||||
must be maps, and they must all have identical key types.
|
||||
If the type of <code>m</code> is a <a href="#Type_parameter_declarations">type parameter</a>,
|
||||
all types in that type set must be maps, and they must all have identical key types.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
|
@ -7330,10 +7249,6 @@ does not exist, <code>delete</code> is a no-op.
|
|||
|
||||
<h3 id="Complex_numbers">Manipulating complex numbers</h3>
|
||||
|
||||
<p><b>
|
||||
[We don't support generic arguments for these built-ins for Go 1.18.]
|
||||
</b></p>
|
||||
|
||||
<p>
|
||||
Three functions assemble and disassemble complex numbers.
|
||||
The built-in function <code>complex</code> constructs a complex
|
||||
|
|
@ -7396,6 +7311,10 @@ const c = imag(b) // untyped constant -1.4
|
|||
_ = imag(3 << s) // illegal: 3 assumes complex type, cannot shift
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Arguments of type parameter type are not permitted.
|
||||
</p>
|
||||
|
||||
<h3 id="Handling_panics">Handling panics</h3>
|
||||
|
||||
<p> Two built-in functions, <code>panic</code> and <code>recover</code>,
|
||||
|
|
@ -8004,11 +7923,17 @@ func Add(ptr Pointer, len IntegerType) Pointer
|
|||
func Slice(ptr *ArbitraryType, len IntegerType) []ArbitraryType
|
||||
</pre>
|
||||
|
||||
<!--
|
||||
These conversions also apply to type parameters with suitable core types.
|
||||
Determine if we can simply use core type insted of underlying type here,
|
||||
of if the general conversion rules take care of this.
|
||||
-->
|
||||
|
||||
<p>
|
||||
A <code>Pointer</code> is a <a href="#Pointer_types">pointer type</a> but a <code>Pointer</code>
|
||||
value may not be <a href="#Address_operators">dereferenced</a>.
|
||||
Any pointer or value of <a href="#Types">underlying type</a> <code>uintptr</code> can be converted to
|
||||
a type of underlying type <code>Pointer</code> and vice versa.
|
||||
Any pointer or value of <a href="#Types">underlying type</a> <code>uintptr</code> can be
|
||||
<a href="#Conversions">converted</a> to a type of underlying type <code>Pointer</code> and vice versa.
|
||||
The effect of converting between <code>Pointer</code> and <code>uintptr</code> is implementation-defined.
|
||||
</p>
|
||||
|
||||
|
|
@ -8055,7 +7980,8 @@ uintptr(unsafe.Pointer(&x)) % unsafe.Alignof(x) == 0
|
|||
|
||||
<p>
|
||||
A (variable of) type <code>T</code> has <i>variable size</i> if <code>T</code>
|
||||
is a type parameter, or if it is an array or struct type containing elements
|
||||
is a <a href="#Type_parameter_declarations">type parameter</a>, or if it is an
|
||||
array or struct type containing elements
|
||||
or fields of variable size. Otherwise the size is <i>constant</i>.
|
||||
Calls to <code>Alignof</code>, <code>Offsetof</code>, and <code>Sizeof</code>
|
||||
are compile-time <a href="#Constant_expressions">constant expressions</a> of
|
||||
|
|
|
|||
|
|
@ -283,6 +283,12 @@ func TestMethod2(t *testing.T) {
|
|||
run(t, "./method2.exe")
|
||||
}
|
||||
|
||||
func TestMethod3(t *testing.T) {
|
||||
goCmd(t, "build", "-buildmode=plugin", "-o", "method3.so", "./method3/plugin.go")
|
||||
goCmd(t, "build", "-o", "method3.exe", "./method3/main.go")
|
||||
run(t, "./method3.exe")
|
||||
}
|
||||
|
||||
func TestIssue44956(t *testing.T) {
|
||||
goCmd(t, "build", "-buildmode=plugin", "-o", "issue44956p1.so", "./issue44956/plugin1.go")
|
||||
goCmd(t, "build", "-buildmode=plugin", "-o", "issue44956p2.so", "./issue44956/plugin2.go")
|
||||
|
|
|
|||
32
misc/cgo/testplugin/testdata/method3/main.go
vendored
Normal file
32
misc/cgo/testplugin/testdata/method3/main.go
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright 2022 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.
|
||||
|
||||
// An unexported method can be reachable from the plugin via interface
|
||||
// when a package is shared. So it need to be live.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"plugin"
|
||||
|
||||
"testplugin/method3/p"
|
||||
)
|
||||
|
||||
var i p.I
|
||||
|
||||
func main() {
|
||||
pl, err := plugin.Open("method3.so")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
f, err := pl.Lookup("F")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
f.(func())()
|
||||
|
||||
i = p.T(123)
|
||||
}
|
||||
17
misc/cgo/testplugin/testdata/method3/p/p.go
vendored
Normal file
17
misc/cgo/testplugin/testdata/method3/p/p.go
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright 2022 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
|
||||
|
||||
type T int
|
||||
|
||||
func (T) m() { println("m") }
|
||||
|
||||
type I interface { m() }
|
||||
|
||||
func F() {
|
||||
i.m()
|
||||
}
|
||||
|
||||
var i I = T(123)
|
||||
11
misc/cgo/testplugin/testdata/method3/plugin.go
vendored
Normal file
11
misc/cgo/testplugin/testdata/method3/plugin.go
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
// Copyright 2022 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 "testplugin/method3/p"
|
||||
|
||||
func main() {}
|
||||
|
||||
func F() { p.F() }
|
||||
|
|
@ -41,6 +41,9 @@ func TestASAN(t *testing.T) {
|
|||
{src: "asan4_fail.go", memoryAccessError: "use-after-poison", errorLocation: "asan4_fail.go:13"},
|
||||
{src: "asan5_fail.go", memoryAccessError: "use-after-poison", errorLocation: "asan5_fail.go:18"},
|
||||
{src: "asan_useAfterReturn.go"},
|
||||
{src: "asan_unsafe_fail1.go", memoryAccessError: "use-after-poison", errorLocation: "asan_unsafe_fail1.go:25"},
|
||||
{src: "asan_unsafe_fail2.go", memoryAccessError: "use-after-poison", errorLocation: "asan_unsafe_fail2.go:25"},
|
||||
{src: "asan_unsafe_fail3.go", memoryAccessError: "use-after-poison", errorLocation: "asan_unsafe_fail3.go:18"},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
|
|
|
|||
27
misc/cgo/testsanitizers/testdata/asan_unsafe_fail1.go
vendored
Normal file
27
misc/cgo/testsanitizers/testdata/asan_unsafe_fail1.go
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright 2022 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"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func main() {
|
||||
a := 1
|
||||
b := 2
|
||||
c := add(a, b)
|
||||
d := a + b
|
||||
fmt.Println(c, d)
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func add(a1, b1 int) int {
|
||||
// The arguments.
|
||||
// When -asan is enabled, unsafe.Pointer(&a1) conversion is escaping.
|
||||
var p *int = (*int)(unsafe.Add(unsafe.Pointer(&a1), 1*unsafe.Sizeof(int(1))))
|
||||
*p = 10 // BOOM
|
||||
return a1 + b1
|
||||
}
|
||||
28
misc/cgo/testsanitizers/testdata/asan_unsafe_fail2.go
vendored
Normal file
28
misc/cgo/testsanitizers/testdata/asan_unsafe_fail2.go
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright 2022 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"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func main() {
|
||||
a := 1
|
||||
b := 2
|
||||
c := add(a, b)
|
||||
d := a + b
|
||||
fmt.Println(c, d)
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func add(a1, b1 int) (ret int) {
|
||||
// The return value
|
||||
// When -asan is enabled, the unsafe.Pointer(&ret) conversion is escaping.
|
||||
var p *int = (*int)(unsafe.Add(unsafe.Pointer(&ret), 1*unsafe.Sizeof(int(1))))
|
||||
*p = 123 // BOOM
|
||||
ret = a1 + b1
|
||||
return
|
||||
}
|
||||
21
misc/cgo/testsanitizers/testdata/asan_unsafe_fail3.go
vendored
Normal file
21
misc/cgo/testsanitizers/testdata/asan_unsafe_fail3.go
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright 2022 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"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func main() {
|
||||
a := 1
|
||||
b := 2
|
||||
// The local variables.
|
||||
// When -asan is enabled, the unsafe.Pointer(&a) conversion is escaping.
|
||||
var p *int = (*int)(unsafe.Add(unsafe.Pointer(&a), 1*unsafe.Sizeof(int(1))))
|
||||
*p = 20 // BOOM
|
||||
d := a + b
|
||||
fmt.Println(d)
|
||||
}
|
||||
|
|
@ -3,10 +3,10 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
Package builtin provides documentation for Go's predeclared identifiers.
|
||||
The items documented here are not actually in package builtin
|
||||
but their descriptions here allow godoc to present documentation
|
||||
for the language's special identifiers.
|
||||
Package builtin provides documentation for Go's predeclared identifiers.
|
||||
The items documented here are not actually in package builtin
|
||||
but their descriptions here allow godoc to present documentation
|
||||
for the language's special identifiers.
|
||||
*/
|
||||
package builtin
|
||||
|
||||
|
|
|
|||
|
|
@ -138,10 +138,8 @@ func (b *Buffer) grow(n int) int {
|
|||
} else if c > maxInt-c-n {
|
||||
panic(ErrTooLarge)
|
||||
} else {
|
||||
// Not enough space anywhere, we need to allocate.
|
||||
buf := makeSlice(2*c + n)
|
||||
copy(buf, b.buf[b.off:])
|
||||
b.buf = buf
|
||||
// Add b.off to account for b.buf[:b.off] being sliced off the front.
|
||||
b.buf = growSlice(b.buf[b.off:], b.off+n)
|
||||
}
|
||||
// Restore b.off and len(b.buf).
|
||||
b.off = 0
|
||||
|
|
@ -217,16 +215,31 @@ func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error) {
|
|||
}
|
||||
}
|
||||
|
||||
// makeSlice allocates a slice of size n. If the allocation fails, it panics
|
||||
// with ErrTooLarge.
|
||||
func makeSlice(n int) []byte {
|
||||
// If the make fails, give a known error.
|
||||
// growSlice grows b by n, preserving the original content of b.
|
||||
// If the allocation fails, it panics with ErrTooLarge.
|
||||
func growSlice(b []byte, n int) []byte {
|
||||
defer func() {
|
||||
if recover() != nil {
|
||||
panic(ErrTooLarge)
|
||||
}
|
||||
}()
|
||||
return make([]byte, n)
|
||||
// TODO(http://golang.org/issue/51462): We should rely on the append-make
|
||||
// pattern so that the compiler can call runtime.growslice. For example:
|
||||
// return append(b, make([]byte, n)...)
|
||||
// This avoids unnecessary zero-ing of the first len(b) bytes of the
|
||||
// allocated slice, but this pattern causes b to escape onto the heap.
|
||||
//
|
||||
// Instead use the append-make pattern with a nil slice to ensure that
|
||||
// we allocate buffers rounded up to the closest size class.
|
||||
c := len(b) + n // ensure enough space for n elements
|
||||
if c < 2*cap(b) {
|
||||
// The growth rate has historically always been 2x. In the future,
|
||||
// we could rely purely on append to determine the growth rate.
|
||||
c = 2 * cap(b)
|
||||
}
|
||||
b2 := append([]byte(nil), make([]byte, c)...)
|
||||
copy(b2, b)
|
||||
return b2[:len(b)]
|
||||
}
|
||||
|
||||
// WriteTo writes data to w until the buffer is drained or an error occurs.
|
||||
|
|
|
|||
|
|
@ -672,3 +672,18 @@ func BenchmarkBufferFullSmallReads(b *testing.B) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkBufferWriteBlock(b *testing.B) {
|
||||
block := make([]byte, 1024)
|
||||
for _, n := range []int{1 << 12, 1 << 16, 1 << 20} {
|
||||
b.Run(fmt.Sprintf("N%d", n), func(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
var bb Buffer
|
||||
for bb.Len() < n {
|
||||
bb.Write(block)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -909,7 +909,11 @@ func containsRune(s string, r rune) bool {
|
|||
// Trim returns a subslice of s by slicing off all leading and
|
||||
// trailing UTF-8-encoded code points contained in cutset.
|
||||
func Trim(s []byte, cutset string) []byte {
|
||||
if len(s) == 0 || cutset == "" {
|
||||
if len(s) == 0 {
|
||||
// This is what we've historically done.
|
||||
return nil
|
||||
}
|
||||
if cutset == "" {
|
||||
return s
|
||||
}
|
||||
if len(cutset) == 1 && cutset[0] < utf8.RuneSelf {
|
||||
|
|
@ -924,7 +928,11 @@ func Trim(s []byte, cutset string) []byte {
|
|||
// TrimLeft returns a subslice of s by slicing off all leading
|
||||
// UTF-8-encoded code points contained in cutset.
|
||||
func TrimLeft(s []byte, cutset string) []byte {
|
||||
if len(s) == 0 || cutset == "" {
|
||||
if len(s) == 0 {
|
||||
// This is what we've historically done.
|
||||
return nil
|
||||
}
|
||||
if cutset == "" {
|
||||
return s
|
||||
}
|
||||
if len(cutset) == 1 && cutset[0] < utf8.RuneSelf {
|
||||
|
|
@ -940,6 +948,10 @@ func trimLeftByte(s []byte, c byte) []byte {
|
|||
for len(s) > 0 && s[0] == c {
|
||||
s = s[1:]
|
||||
}
|
||||
if len(s) == 0 {
|
||||
// This is what we've historically done.
|
||||
return nil
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
|
|
@ -950,6 +962,10 @@ func trimLeftASCII(s []byte, as *asciiSet) []byte {
|
|||
}
|
||||
s = s[1:]
|
||||
}
|
||||
if len(s) == 0 {
|
||||
// This is what we've historically done.
|
||||
return nil
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
|
|
@ -964,6 +980,10 @@ func trimLeftUnicode(s []byte, cutset string) []byte {
|
|||
}
|
||||
s = s[n:]
|
||||
}
|
||||
if len(s) == 0 {
|
||||
// This is what we've historically done.
|
||||
return nil
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1278,24 +1278,69 @@ var trimTests = []TrimTest{
|
|||
{"TrimSuffix", "aabb", "b", "aab"},
|
||||
}
|
||||
|
||||
type TrimNilTest struct {
|
||||
f string
|
||||
in []byte
|
||||
arg string
|
||||
out []byte
|
||||
}
|
||||
|
||||
var trimNilTests = []TrimNilTest{
|
||||
{"Trim", nil, "", nil},
|
||||
{"Trim", []byte{}, "", nil},
|
||||
{"Trim", []byte{'a'}, "a", nil},
|
||||
{"Trim", []byte{'a', 'a'}, "a", nil},
|
||||
{"Trim", []byte{'a'}, "ab", nil},
|
||||
{"Trim", []byte{'a', 'b'}, "ab", nil},
|
||||
{"Trim", []byte("☺"), "☺", nil},
|
||||
{"TrimLeft", nil, "", nil},
|
||||
{"TrimLeft", []byte{}, "", nil},
|
||||
{"TrimLeft", []byte{'a'}, "a", nil},
|
||||
{"TrimLeft", []byte{'a', 'a'}, "a", nil},
|
||||
{"TrimLeft", []byte{'a'}, "ab", nil},
|
||||
{"TrimLeft", []byte{'a', 'b'}, "ab", nil},
|
||||
{"TrimLeft", []byte("☺"), "☺", nil},
|
||||
{"TrimRight", nil, "", nil},
|
||||
{"TrimRight", []byte{}, "", []byte{}},
|
||||
{"TrimRight", []byte{'a'}, "a", []byte{}},
|
||||
{"TrimRight", []byte{'a', 'a'}, "a", []byte{}},
|
||||
{"TrimRight", []byte{'a'}, "ab", []byte{}},
|
||||
{"TrimRight", []byte{'a', 'b'}, "ab", []byte{}},
|
||||
{"TrimRight", []byte("☺"), "☺", []byte{}},
|
||||
{"TrimPrefix", nil, "", nil},
|
||||
{"TrimPrefix", []byte{}, "", []byte{}},
|
||||
{"TrimPrefix", []byte{'a'}, "a", []byte{}},
|
||||
{"TrimPrefix", []byte("☺"), "☺", []byte{}},
|
||||
{"TrimSuffix", nil, "", nil},
|
||||
{"TrimSuffix", []byte{}, "", []byte{}},
|
||||
{"TrimSuffix", []byte{'a'}, "a", []byte{}},
|
||||
{"TrimSuffix", []byte("☺"), "☺", []byte{}},
|
||||
}
|
||||
|
||||
func TestTrim(t *testing.T) {
|
||||
for _, tc := range trimTests {
|
||||
name := tc.f
|
||||
var f func([]byte, string) []byte
|
||||
var fb func([]byte, []byte) []byte
|
||||
toFn := func(name string) (func([]byte, string) []byte, func([]byte, []byte) []byte) {
|
||||
switch name {
|
||||
case "Trim":
|
||||
f = Trim
|
||||
return Trim, nil
|
||||
case "TrimLeft":
|
||||
f = TrimLeft
|
||||
return TrimLeft, nil
|
||||
case "TrimRight":
|
||||
f = TrimRight
|
||||
return TrimRight, nil
|
||||
case "TrimPrefix":
|
||||
fb = TrimPrefix
|
||||
return nil, TrimPrefix
|
||||
case "TrimSuffix":
|
||||
fb = TrimSuffix
|
||||
return nil, TrimSuffix
|
||||
default:
|
||||
t.Errorf("Undefined trim function %s", name)
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
for _, tc := range trimTests {
|
||||
name := tc.f
|
||||
f, fb := toFn(name)
|
||||
if f == nil && fb == nil {
|
||||
continue
|
||||
}
|
||||
var actual string
|
||||
if f != nil {
|
||||
|
|
@ -1307,6 +1352,36 @@ func TestTrim(t *testing.T) {
|
|||
t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.arg, actual, tc.out)
|
||||
}
|
||||
}
|
||||
|
||||
for _, tc := range trimNilTests {
|
||||
name := tc.f
|
||||
f, fb := toFn(name)
|
||||
if f == nil && fb == nil {
|
||||
continue
|
||||
}
|
||||
var actual []byte
|
||||
if f != nil {
|
||||
actual = f(tc.in, tc.arg)
|
||||
} else {
|
||||
actual = fb(tc.in, []byte(tc.arg))
|
||||
}
|
||||
report := func(s []byte) string {
|
||||
if s == nil {
|
||||
return "nil"
|
||||
} else {
|
||||
return fmt.Sprintf("%q", s)
|
||||
}
|
||||
}
|
||||
if len(actual) != 0 {
|
||||
t.Errorf("%s(%s, %q) returned non-empty value", name, report(tc.in), tc.arg)
|
||||
} else {
|
||||
actualNil := actual == nil
|
||||
outNil := tc.out == nil
|
||||
if actualNil != outNil {
|
||||
t.Errorf("%s(%s, %q) got nil %t; want nil %t", name, report(tc.in), tc.arg, actualNil, outNil)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type predicate struct {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Binary api computes the exported API of a set of Go packages.
|
||||
// Api computes the exported API of a set of Go packages.
|
||||
package main
|
||||
|
||||
import (
|
||||
|
|
@ -24,6 +24,7 @@ import (
|
|||
"regexp"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
|
@ -33,21 +34,24 @@ func goCmd() string {
|
|||
if runtime.GOOS == "windows" {
|
||||
exeSuffix = ".exe"
|
||||
}
|
||||
path := filepath.Join(runtime.GOROOT(), "bin", "go"+exeSuffix)
|
||||
if _, err := os.Stat(path); err == nil {
|
||||
return path
|
||||
if goroot := build.Default.GOROOT; goroot != "" {
|
||||
path := filepath.Join(goroot, "bin", "go"+exeSuffix)
|
||||
if _, err := os.Stat(path); err == nil {
|
||||
return path
|
||||
}
|
||||
}
|
||||
return "go"
|
||||
}
|
||||
|
||||
// Flags
|
||||
var (
|
||||
checkFile = flag.String("c", "", "optional comma-separated filename(s) to check API against")
|
||||
allowNew = flag.Bool("allow_new", true, "allow API additions")
|
||||
exceptFile = flag.String("except", "", "optional filename of packages that are allowed to change without triggering a failure in the tool")
|
||||
nextFile = flag.String("next", "", "optional filename of tentative upcoming API features for the next release. This file can be lazily maintained. It only affects the delta warnings from the -c file printed on success.")
|
||||
verbose = flag.Bool("v", false, "verbose debugging")
|
||||
forceCtx = flag.String("contexts", "", "optional comma-separated list of <goos>-<goarch>[-cgo] to override default contexts.")
|
||||
checkFiles = flag.String("c", "", "optional comma-separated filename(s) to check API against")
|
||||
requireApproval = flag.String("approval", "", "require approvals in comma-separated list of `files`")
|
||||
allowNew = flag.Bool("allow_new", true, "allow API additions")
|
||||
exceptFile = flag.String("except", "", "optional filename of packages that are allowed to change without triggering a failure in the tool")
|
||||
nextFiles = flag.String("next", "", "comma-separated list of `files` for upcoming API features for the next release. These files can be lazily maintained. They only affects the delta warnings from the -c file printed on success.")
|
||||
verbose = flag.Bool("v", false, "verbose debugging")
|
||||
forceCtx = flag.String("contexts", "", "optional comma-separated list of <goos>-<goarch>[-cgo] to override default contexts.")
|
||||
)
|
||||
|
||||
// contexts are the default contexts which are scanned, unless
|
||||
|
|
@ -125,10 +129,14 @@ var internalPkg = regexp.MustCompile(`(^|/)internal($|/)`)
|
|||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
if build.Default.GOROOT == "" {
|
||||
log.Fatalf("GOROOT not found. (If binary was built with -trimpath, $GOROOT must be set.)")
|
||||
}
|
||||
|
||||
if !strings.Contains(runtime.Version(), "weekly") && !strings.Contains(runtime.Version(), "devel") {
|
||||
if *nextFile != "" {
|
||||
fmt.Printf("Go version is %q, ignoring -next %s\n", runtime.Version(), *nextFile)
|
||||
*nextFile = ""
|
||||
if *nextFiles != "" {
|
||||
fmt.Printf("Go version is %q, ignoring -next %s\n", runtime.Version(), *nextFiles)
|
||||
*nextFiles = ""
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -201,7 +209,7 @@ func main() {
|
|||
bw := bufio.NewWriter(os.Stdout)
|
||||
defer bw.Flush()
|
||||
|
||||
if *checkFile == "" {
|
||||
if *checkFiles == "" {
|
||||
sort.Strings(features)
|
||||
for _, f := range features {
|
||||
fmt.Fprintln(bw, f)
|
||||
|
|
@ -210,10 +218,15 @@ func main() {
|
|||
}
|
||||
|
||||
var required []string
|
||||
for _, file := range strings.Split(*checkFile, ",") {
|
||||
for _, file := range strings.Split(*checkFiles, ",") {
|
||||
required = append(required, fileFeatures(file)...)
|
||||
}
|
||||
optional := fileFeatures(*nextFile)
|
||||
var optional []string
|
||||
if *nextFiles != "" {
|
||||
for _, file := range strings.Split(*nextFiles, ",") {
|
||||
optional = append(optional, fileFeatures(file)...)
|
||||
}
|
||||
}
|
||||
exception := fileFeatures(*exceptFile)
|
||||
fail = !compareAPI(bw, features, required, optional, exception, *allowNew)
|
||||
}
|
||||
|
|
@ -340,6 +353,13 @@ func fileFeatures(filename string) []string {
|
|||
if filename == "" {
|
||||
return nil
|
||||
}
|
||||
needApproval := false
|
||||
for _, name := range strings.Split(*requireApproval, ",") {
|
||||
if filename == name {
|
||||
needApproval = true
|
||||
break
|
||||
}
|
||||
}
|
||||
bs, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
log.Fatalf("Error reading file %s: %v", filename, err)
|
||||
|
|
@ -348,11 +368,23 @@ func fileFeatures(filename string) []string {
|
|||
s = aliasReplacer.Replace(s)
|
||||
lines := strings.Split(s, "\n")
|
||||
var nonblank []string
|
||||
for _, line := range lines {
|
||||
for i, line := range lines {
|
||||
line = strings.TrimSpace(line)
|
||||
if line != "" && !strings.HasPrefix(line, "#") {
|
||||
nonblank = append(nonblank, line)
|
||||
if line == "" || strings.HasPrefix(line, "#") {
|
||||
continue
|
||||
}
|
||||
if needApproval {
|
||||
feature, approval, ok := strings.Cut(line, "#")
|
||||
if !ok {
|
||||
log.Fatalf("%s:%d: missing proposal approval\n", filename, i+1)
|
||||
}
|
||||
_, err := strconv.Atoi(approval)
|
||||
if err != nil {
|
||||
log.Fatalf("%s:%d: malformed proposal approval #%s\n", filename, i+1, approval)
|
||||
}
|
||||
line = strings.TrimSpace(feature)
|
||||
}
|
||||
nonblank = append(nonblank, line)
|
||||
}
|
||||
return nonblank
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import (
|
|||
"flag"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"internal/testenv"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
|
|
@ -22,6 +23,7 @@ func TestMain(m *testing.M) {
|
|||
for _, c := range contexts {
|
||||
c.Compiler = build.Default.Compiler
|
||||
}
|
||||
build.Default.GOROOT = testenv.GOROOT(nil)
|
||||
|
||||
// Warm up the import cache in parallel.
|
||||
var wg sync.WaitGroup
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
|
@ -41,51 +42,65 @@ func main() {
|
|||
if goroot == "" {
|
||||
log.Fatal("No $GOROOT set.")
|
||||
}
|
||||
if err := os.Chdir(filepath.Join(goroot, "api")); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
apiDir := filepath.Join(goroot, "api")
|
||||
out, err := exec.Command(goCmd(), "tool", "api",
|
||||
"-c", findAPIDirFiles(apiDir),
|
||||
allowNew(apiDir),
|
||||
"-next", filepath.Join(apiDir, "next.txt"),
|
||||
"-except", filepath.Join(apiDir, "except.txt")).CombinedOutput()
|
||||
files, err := filepath.Glob("go1*.txt")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
next, err := filepath.Glob(filepath.Join("next", "*.txt"))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
cmd := exec.Command(goCmd(), "tool", "api",
|
||||
"-c", strings.Join(files, ","),
|
||||
"-approval", strings.Join(append(approvalNeeded(files), next...), ","),
|
||||
allowNew(),
|
||||
"-next", strings.Join(next, ","),
|
||||
"-except", "except.txt",
|
||||
)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
log.Fatalf("Error running API checker: %v\n%s", err, out)
|
||||
}
|
||||
fmt.Print(string(out))
|
||||
}
|
||||
|
||||
// findAPIDirFiles returns a comma-separated list of Go API files
|
||||
// (go1.txt, go1.1.txt, etc.) located in apiDir.
|
||||
func findAPIDirFiles(apiDir string) string {
|
||||
dir, err := os.Open(apiDir)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer dir.Close()
|
||||
fs, err := dir.Readdirnames(-1)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
var apiFiles []string
|
||||
for _, fn := range fs {
|
||||
if strings.HasPrefix(fn, "go1") {
|
||||
apiFiles = append(apiFiles, filepath.Join(apiDir, fn))
|
||||
func approvalNeeded(files []string) []string {
|
||||
var out []string
|
||||
for _, f := range files {
|
||||
name := filepath.Base(f)
|
||||
if name == "go1.txt" {
|
||||
continue
|
||||
}
|
||||
minor := strings.TrimSuffix(strings.TrimPrefix(name, "go1."), ".txt")
|
||||
n, err := strconv.Atoi(minor)
|
||||
if err != nil {
|
||||
log.Fatalf("unexpected api file: %v", f)
|
||||
}
|
||||
if n >= 19 { // approvals started being tracked in Go 1.19
|
||||
out = append(out, f)
|
||||
}
|
||||
}
|
||||
return strings.Join(apiFiles, ",")
|
||||
return out
|
||||
}
|
||||
|
||||
// allowNew returns the -allow_new flag to use for the 'go tool api' invocation.
|
||||
func allowNew(apiDir string) string {
|
||||
func allowNew() string {
|
||||
// Experiment for Go 1.19: always require api file updates.
|
||||
return "-allow_new=false"
|
||||
|
||||
// Verify that the api/go1.n.txt for previous Go version exists.
|
||||
// It definitely should, otherwise it's a signal that the logic below may be outdated.
|
||||
if _, err := os.Stat(filepath.Join(apiDir, fmt.Sprintf("go1.%d.txt", goversion.Version-1))); err != nil {
|
||||
if _, err := os.Stat(fmt.Sprintf("go1.%d.txt", goversion.Version-1)); err != nil {
|
||||
log.Fatalln("Problem with api file for previous release:", err)
|
||||
}
|
||||
|
||||
// See whether the api/go1.n.txt for this Go version has been created.
|
||||
// (As of April 2021, it gets created during the release of the first Beta.)
|
||||
_, err := os.Stat(filepath.Join(apiDir, fmt.Sprintf("go1.%d.txt", goversion.Version)))
|
||||
_, err := os.Stat(fmt.Sprintf("go1.%d.txt", goversion.Version))
|
||||
if errors.Is(err, fs.ErrNotExist) {
|
||||
// It doesn't exist, so we're in development or before Beta 1.
|
||||
// At this stage, unmentioned API additions are deemed okay.
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import (
|
|||
|
||||
func jumpPPC64(word string) bool {
|
||||
switch word {
|
||||
case "BC", "BCL", "BEQ", "BGE", "BGT", "BL", "BLE", "BLT", "BNE", "BR", "BVC", "BVS", "CALL", "JMP":
|
||||
case "BC", "BCL", "BEQ", "BGE", "BGT", "BL", "BLE", "BLT", "BNE", "BR", "BVC", "BVS", "BDNZ", "BDZ", "CALL", "JMP":
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
|
|
|||
4
src/cmd/asm/internal/asm/testdata/arm64.s
vendored
4
src/cmd/asm/internal/asm/testdata/arm64.s
vendored
|
|
@ -241,6 +241,10 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
|||
FADDS F2, F3, F4 // 6428221e
|
||||
FADDD F1, F2 // 4228611e
|
||||
VDUP V19.S[0], V17.S4 // 7106044e
|
||||
VTRN1 V3.D2, V2.D2, V20.D2 // 5428c34e
|
||||
VTRN2 V3.D2, V2.D2, V21.D2 // 5568c34e
|
||||
VTRN1 V5.D2, V4.D2, V22.D2 // 9628c54e
|
||||
VTRN2 V5.D2, V4.D2, V23.D2 // 9768c54e
|
||||
|
||||
|
||||
// special
|
||||
|
|
|
|||
|
|
@ -417,8 +417,8 @@ TEXT errors(SB),$0
|
|||
CASPD (R2, R4), (R2), (R8, R9) // ERROR "source register pair must be contiguous"
|
||||
CASPD (R2, R3), (R2), (R8, R10) // ERROR "destination register pair must be contiguous"
|
||||
ADD R1>>2, RSP, R3 // ERROR "illegal combination"
|
||||
ADDS R2<<3, R3, RSP // ERROR "unexpected SP reference"
|
||||
CMP R1<<5, RSP // ERROR "the left shift amount out of range 0 to 4"
|
||||
ADDS R2<<3, R3, RSP // ERROR "illegal destination register"
|
||||
CMP R1<<5, RSP // ERROR "shift amount out of range 0 to 4"
|
||||
MOVD.P y+8(FP), R1 // ERROR "illegal combination"
|
||||
MOVD.W x-8(SP), R1 // ERROR "illegal combination"
|
||||
LDP.P x+8(FP), (R0, R1) // ERROR "illegal combination"
|
||||
|
|
|
|||
28
src/cmd/asm/internal/asm/testdata/ppc64.s
vendored
28
src/cmd/asm/internal/asm/testdata/ppc64.s
vendored
|
|
@ -751,17 +751,23 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
|||
MOVD XER, R3 // 7c6102a6
|
||||
MOVFL CR3, CR1 // 4c8c0000
|
||||
|
||||
MOVW CR0, R1 // 7c380026
|
||||
MOVW CR7, R1 // 7c301026
|
||||
MOVW CR, R1 // 7c200026
|
||||
MOVW CR0, R1 // 7c380026
|
||||
MOVW CR7, R1 // 7c301026
|
||||
MOVW CR, R1 // 7c200026
|
||||
|
||||
MOVW R1, CR // 7c2ff120
|
||||
MOVFL R1, CR // 7c2ff120
|
||||
MOVW R1, CR2 // 7c320120
|
||||
MOVFL R1, CR2 // 7c320120
|
||||
MOVFL R1, $255 // 7c2ff120
|
||||
MOVFL R1, $1 // 7c301120
|
||||
MOVFL R1, $128 // 7c380120
|
||||
MOVFL R1, $3 // 7c203120
|
||||
MOVW R1, CR // 7c2ff120
|
||||
MOVFL R1, CR // 7c2ff120
|
||||
MOVW R1, CR2 // 7c320120
|
||||
MOVFL R1, CR2 // 7c320120
|
||||
MOVFL R1, $255 // 7c2ff120
|
||||
MOVFL R1, $1 // 7c301120
|
||||
MOVFL R1, $128 // 7c380120
|
||||
MOVFL R1, $3 // 7c203120
|
||||
|
||||
// Verify supported bdnz/bdz encodings.
|
||||
BC 16,0,0(PC) // BC $16,R0,0(PC) // 42000000
|
||||
BDNZ 0(PC) // 42000000
|
||||
BDZ 0(PC) // 42400000
|
||||
BC 18,0,0(PC) // BC $18,R0,0(PC) // 42400000
|
||||
|
||||
RET
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ var (
|
|||
|
||||
var DebugFlags struct {
|
||||
MayMoreStack string `help:"call named function before all stack growth checks"`
|
||||
PCTab string `help:"print named pc-value table\nOne of: pctospadj, pctofile, pctoline, pctoinline, pctopcdata"`
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ func predefine(defines flags.MultiFlag) map[string]*Macro {
|
|||
// Set macros for GOEXPERIMENTs so we can easily switch
|
||||
// runtime assembly code based on them.
|
||||
if *flags.CompilingRuntime {
|
||||
for _, exp := range buildcfg.EnabledExperiments() {
|
||||
for _, exp := range buildcfg.Experiment.Enabled() {
|
||||
// Define macro.
|
||||
name := "GOEXPERIMENT_" + exp
|
||||
macros[name] = &Macro{
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ func main() {
|
|||
ctxt.Flag_linkshared = *flags.Linkshared
|
||||
ctxt.Flag_shared = *flags.Shared || *flags.Dynlink
|
||||
ctxt.Flag_maymorestack = flags.DebugFlags.MayMoreStack
|
||||
ctxt.Debugpcln = flags.DebugFlags.PCTab
|
||||
ctxt.IsAsm = true
|
||||
ctxt.Pkgpath = *flags.Importpath
|
||||
switch *flags.Spectre {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Go internal ABI specification
|
||||
|
||||
Self-link: [go.dev/s/regabi](https://go.dev/s/regabi)
|
||||
|
||||
This document describes Go’s internal application binary interface
|
||||
(ABI), known as ABIInternal.
|
||||
Go's ABI defines the layout of data in memory and the conventions for
|
||||
|
|
@ -730,6 +732,57 @@ The floating point status and control register (FPSCR) is initialized
|
|||
to 0 by the kernel at startup of the Go program and not changed by
|
||||
the Go generated code.
|
||||
|
||||
### riscv64 architecture
|
||||
|
||||
The riscv64 architecture uses X10 – X17, X8, X9, X18 – X23 for integer arguments
|
||||
and results.
|
||||
|
||||
It uses F10 – F17, F8, F9, F18 – F23 for floating-point arguments and results.
|
||||
|
||||
Special-purpose registers used within Go generated code and Go
|
||||
assembly code are as follows:
|
||||
|
||||
| Register | Call meaning | Return meaning | Body meaning |
|
||||
| --- | --- | --- | --- |
|
||||
| X0 | Zero value | Same | Same |
|
||||
| X1 | Link register | Link register | Scratch |
|
||||
| X2 | Stack pointer | Same | Same |
|
||||
| X3 | Global pointer | Same | Used by dynamic linker |
|
||||
| X4 | TLS (thread pointer) | TLS | Scratch |
|
||||
| X24,X25 | Scratch | Scratch | Used by duffcopy, duffzero |
|
||||
| X26 | Closure context pointer | Scratch | Scratch |
|
||||
| X27 | Current goroutine | Same | Same |
|
||||
| X31 | Scratch | Scratch | Scratch |
|
||||
|
||||
*Rationale*: These register meanings are compatible with Go’s
|
||||
stack-based calling convention. Context register X20 will change to X26,
|
||||
duffcopy, duffzero register will change to X24, X25 before this register ABI been adopted.
|
||||
X10 – X17, X8, X9, X18 – X23, is the same order as A0 – A7, S0 – S7 in platform ABI.
|
||||
F10 – F17, F8, F9, F18 – F23, is the same order as FA0 – FA7, FS0 – FS7 in platform ABI.
|
||||
X8 – X23, F8 – F15 are used for compressed instruction (RVC) which will benefit code size in the future.
|
||||
|
||||
#### Stack layout
|
||||
|
||||
The stack pointer, X2, grows down and is aligned to 8 bytes.
|
||||
|
||||
A function's stack frame, after the frame is created, is laid out as
|
||||
follows:
|
||||
|
||||
+------------------------------+
|
||||
| ... locals ... |
|
||||
| ... outgoing arguments ... |
|
||||
| return PC | ← X2 points to
|
||||
+------------------------------+ ↓ lower addresses
|
||||
|
||||
The "return PC" is loaded to the link register, X1, as part of the
|
||||
riscv64 `CALL` operation.
|
||||
|
||||
#### Flags
|
||||
|
||||
The riscv64 has Zicsr extension for control and status register (CSR) and
|
||||
treated as scratch register.
|
||||
All bits in CSR are system flags and are not modified by Go.
|
||||
|
||||
## Future directions
|
||||
|
||||
### Spill path improvements
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import (
|
|||
"bufio"
|
||||
"debug/elf"
|
||||
"debug/macho"
|
||||
"errors"
|
||||
"fmt"
|
||||
"internal/testenv"
|
||||
"io"
|
||||
|
|
@ -117,9 +118,12 @@ func clobber(t *testing.T, src string, dst *os.File, opcodes map[string]bool) {
|
|||
var err error
|
||||
disasm, err = cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
t.Skipf("can't run test due to missing objdump: %s", err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := cmd.Start(); err != nil {
|
||||
if errors.Is(err, exec.ErrNotFound) {
|
||||
t.Skipf("can't run test due to missing objdump: %s", err)
|
||||
}
|
||||
t.Fatal(err)
|
||||
}
|
||||
re = regexp.MustCompile(`^\s*([0-9a-f]+):\s*((?:[0-9a-f][0-9a-f] )+)\s*([a-z0-9]+)`)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import (
|
|||
"runtime"
|
||||
"strings"
|
||||
|
||||
"cmd/internal/obj"
|
||||
"cmd/internal/objabi"
|
||||
"cmd/internal/sys"
|
||||
)
|
||||
|
|
@ -57,7 +58,7 @@ type CmdFlags struct {
|
|||
E CountFlag "help:\"debug symbol export\""
|
||||
I func(string) "help:\"add `directory` to import search path\""
|
||||
K CountFlag "help:\"debug missing line numbers\""
|
||||
L CountFlag "help:\"show full file names in error messages\""
|
||||
L CountFlag "help:\"also show actual source file names in error messages for positions affected by //line directives\""
|
||||
N CountFlag "help:\"disable optimizations\""
|
||||
S CountFlag "help:\"print assembly listing\""
|
||||
// V is added by objabi.AddVersionFlag
|
||||
|
|
@ -201,6 +202,10 @@ func ParseFlags() {
|
|||
Exit(2)
|
||||
}
|
||||
|
||||
if *Flag.LowerP == "" {
|
||||
*Flag.LowerP = obj.UnlinkablePkg
|
||||
}
|
||||
|
||||
if Flag.LowerO == "" {
|
||||
p := flag.Arg(0)
|
||||
if i := strings.LastIndex(p, "/"); i >= 0 {
|
||||
|
|
|
|||
|
|
@ -163,4 +163,5 @@ func markHiddenClosureDead(n ir.Node) {
|
|||
if clo.Func.IsHiddenClosure() {
|
||||
clo.Func.SetIsDeadcodeClosure(true)
|
||||
}
|
||||
ir.VisitList(clo.Func.Body, markHiddenClosureDead)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -297,14 +297,6 @@ func (b *batch) finish(fns []*ir.Func) {
|
|||
// TODO(mdempsky): Update tests to expect this.
|
||||
goDeferWrapper := n.Op() == ir.OCLOSURE && n.(*ir.ClosureExpr).Func.Wrapper()
|
||||
|
||||
if n.Op() == ir.OCONVIDATA && n.(*ir.ConvExpr).NonEscaping {
|
||||
// The allocation for the data word of an interface is known to not escape.
|
||||
// See issue 50182.
|
||||
// (But we do still need to process that allocation, as pointers inside
|
||||
// the data word may escape.)
|
||||
loc.escapes = false
|
||||
}
|
||||
|
||||
if loc.escapes {
|
||||
if n.Op() == ir.ONAME {
|
||||
if base.Flag.CompilingRuntime {
|
||||
|
|
|
|||
|
|
@ -100,9 +100,9 @@ func (e *escape) exprSkipInit(k hole, n ir.Node) {
|
|||
|
||||
case ir.OCONV, ir.OCONVNOP:
|
||||
n := n.(*ir.ConvExpr)
|
||||
if ir.ShouldCheckPtr(e.curfn, 2) && n.Type().IsUnsafePtr() && n.X.Type().IsPtr() {
|
||||
// When -d=checkptr=2 is enabled, treat
|
||||
// conversions to unsafe.Pointer as an
|
||||
if (ir.ShouldCheckPtr(e.curfn, 2) || ir.ShouldAsanCheckPtr(e.curfn)) && n.Type().IsUnsafePtr() && n.X.Type().IsPtr() {
|
||||
// When -d=checkptr=2 or -asan is enabled,
|
||||
// treat conversions to unsafe.Pointer as an
|
||||
// escaping operation. This allows better
|
||||
// runtime instrumentation, since we can more
|
||||
// easily detect object boundaries on the heap
|
||||
|
|
|
|||
|
|
@ -188,6 +188,9 @@ func Main(archInit func(*ssagen.ArchInfo)) {
|
|||
|
||||
// Parse and typecheck input.
|
||||
noder.LoadPackage(flag.Args())
|
||||
if base.Ctxt.Pkgpath == obj.UnlinkablePkg && types.LocalPkg.Name == "main" {
|
||||
base.Ctxt.Pkgpath = "main"
|
||||
}
|
||||
|
||||
dwarfgen.RecordPackageName()
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import (
|
|||
"bytes"
|
||||
"cmd/compile/internal/types2"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"internal/goexperiment"
|
||||
"internal/testenv"
|
||||
"os"
|
||||
|
|
@ -19,6 +20,11 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
build.Default.GOROOT = testenv.GOROOT(nil)
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
// skipSpecialPlatforms causes the test to be skipped for platforms where
|
||||
// builders (build.golang.org) don't have access to compiled packages for
|
||||
// import.
|
||||
|
|
@ -38,7 +44,7 @@ func compile(t *testing.T, dirname, filename, outdirname string) string {
|
|||
}
|
||||
basename := filepath.Base(filename)
|
||||
outname := filepath.Join(outdirname, basename[:len(basename)-2]+"o")
|
||||
cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-o", outname, filename)
|
||||
cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-p=p", "-o", outname, filename)
|
||||
cmd.Dir = dirname
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
|
|
@ -62,7 +68,7 @@ func testPath(t *testing.T, path, srcDir string) *types2.Package {
|
|||
const maxTime = 30 * time.Second
|
||||
|
||||
func testDir(t *testing.T, dir string, endTime time.Time) (nimports int) {
|
||||
dirname := filepath.Join(runtime.GOROOT(), "pkg", runtime.GOOS+"_"+runtime.GOARCH, dir)
|
||||
dirname := filepath.Join(testenv.GOROOT(t), "pkg", runtime.GOOS+"_"+runtime.GOARCH, dir)
|
||||
list, err := os.ReadDir(dirname)
|
||||
if err != nil {
|
||||
t.Fatalf("testDir(%s): %s", dirname, err)
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ const (
|
|||
)
|
||||
|
||||
type ident struct {
|
||||
pkg string
|
||||
pkg *types2.Package
|
||||
name string
|
||||
}
|
||||
|
||||
|
|
@ -402,7 +402,7 @@ func (r *importReader) obj(name string) {
|
|||
t := types2.NewTypeParam(tn, nil)
|
||||
// To handle recursive references to the typeparam within its
|
||||
// bound, save the partial type in tparamIndex before reading the bounds.
|
||||
id := ident{r.currPkg.Name(), name}
|
||||
id := ident{r.currPkg, name}
|
||||
r.p.tparamIndex[id] = t
|
||||
|
||||
var implicit bool
|
||||
|
|
@ -687,7 +687,7 @@ func (r *importReader) doType(base *types2.Named) types2.Type {
|
|||
errorf("unexpected type param type")
|
||||
}
|
||||
pkg, name := r.qualifiedIdent()
|
||||
id := ident{pkg.Name(), name}
|
||||
id := ident{pkg, name}
|
||||
if t, ok := r.p.tparamIndex[id]; ok {
|
||||
// We're already in the process of importing this typeparam.
|
||||
return t
|
||||
|
|
|
|||
|
|
@ -358,8 +358,7 @@ func (v *hairyVisitor) doNode(n ir.Node) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
case ir.OSELECT,
|
||||
ir.OGO,
|
||||
case ir.OGO,
|
||||
ir.ODEFER,
|
||||
ir.ODCLTYPE, // can't print yet
|
||||
ir.OTAILCALL:
|
||||
|
|
@ -1310,7 +1309,7 @@ func (subst *inlsubst) node(n ir.Node) ir.Node {
|
|||
ir.EditChildren(m, subst.edit)
|
||||
|
||||
if subst.newclofn == nil {
|
||||
// Translate any label on FOR, RANGE loops or SWITCH
|
||||
// Translate any label on FOR, RANGE loops, SWITCH or SELECT
|
||||
switch m.Op() {
|
||||
case ir.OFOR:
|
||||
m := m.(*ir.ForStmt)
|
||||
|
|
@ -1326,8 +1325,12 @@ func (subst *inlsubst) node(n ir.Node) ir.Node {
|
|||
m := m.(*ir.SwitchStmt)
|
||||
m.Label = translateLabel(m.Label)
|
||||
return m
|
||||
}
|
||||
|
||||
case ir.OSELECT:
|
||||
m := m.(*ir.SelectStmt)
|
||||
m.Label = translateLabel(m.Label)
|
||||
return m
|
||||
}
|
||||
}
|
||||
|
||||
switch m := m.(type) {
|
||||
|
|
|
|||
|
|
@ -186,14 +186,6 @@ type ClosureExpr struct {
|
|||
IsGoWrap bool // whether this is wrapper closure of a go statement
|
||||
}
|
||||
|
||||
// Deprecated: Use NewClosureFunc instead.
|
||||
func NewClosureExpr(pos src.XPos, fn *Func) *ClosureExpr {
|
||||
n := &ClosureExpr{Func: fn}
|
||||
n.op = OCLOSURE
|
||||
n.pos = pos
|
||||
return n
|
||||
}
|
||||
|
||||
// A CompLitExpr is a composite literal Type{Vals}.
|
||||
// Before type-checking, the type is Ntype.
|
||||
type CompLitExpr struct {
|
||||
|
|
@ -242,7 +234,6 @@ func NewConstExpr(val constant.Value, orig Node) Node {
|
|||
n.orig = orig
|
||||
n.SetType(orig.Type())
|
||||
n.SetTypecheck(orig.Typecheck())
|
||||
n.SetDiag(orig.Diag())
|
||||
return n
|
||||
}
|
||||
|
||||
|
|
@ -253,8 +244,7 @@ func (n *ConstExpr) Val() constant.Value { return n.val }
|
|||
// It may end up being a value or a type.
|
||||
type ConvExpr struct {
|
||||
miniExpr
|
||||
X Node
|
||||
NonEscaping bool // The allocation needed for the conversion to interface is known not to escape
|
||||
X Node
|
||||
}
|
||||
|
||||
func NewConvExpr(pos src.XPos, op Op, typ *types.Type, x Node) *ConvExpr {
|
||||
|
|
@ -973,6 +963,12 @@ var IsIntrinsicCall = func(*CallExpr) bool { return false }
|
|||
// lvalue expression is for OSLICE and OAPPEND optimizations, and it
|
||||
// is correct in those settings.
|
||||
func SameSafeExpr(l Node, r Node) bool {
|
||||
for l.Op() == OCONVNOP {
|
||||
l = l.(*ConvExpr).X
|
||||
}
|
||||
for r.Op() == OCONVNOP {
|
||||
r = r.(*ConvExpr).X
|
||||
}
|
||||
if l.Op() != r.Op() || !types.Identical(l.Type(), r.Type()) {
|
||||
return false
|
||||
}
|
||||
|
|
@ -996,11 +992,6 @@ func SameSafeExpr(l Node, r Node) bool {
|
|||
r := r.(*UnaryExpr)
|
||||
return SameSafeExpr(l.X, r.X)
|
||||
|
||||
case OCONVNOP:
|
||||
l := l.(*ConvExpr)
|
||||
r := r.(*ConvExpr)
|
||||
return SameSafeExpr(l.X, r.X)
|
||||
|
||||
case OCONV:
|
||||
l := l.(*ConvExpr)
|
||||
r := r.(*ConvExpr)
|
||||
|
|
@ -1035,6 +1026,12 @@ func ShouldCheckPtr(fn *Func, level int) bool {
|
|||
return base.Debug.Checkptr >= level && fn.Pragma&NoCheckPtr == 0
|
||||
}
|
||||
|
||||
// ShouldAsanCheckPtr reports whether pointer checking should be enabled for
|
||||
// function fn when -asan is enabled.
|
||||
func ShouldAsanCheckPtr(fn *Func) bool {
|
||||
return base.Flag.ASan && fn.Pragma&NoCheckPtr == 0
|
||||
}
|
||||
|
||||
// IsReflectHeaderDataField reports whether l is an expression p.Data
|
||||
// where p has type reflect.SliceHeader or reflect.StringHeader.
|
||||
func IsReflectHeaderDataField(l Node) bool {
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@ import (
|
|||
type Func struct {
|
||||
miniNode
|
||||
Body Nodes
|
||||
Iota int64
|
||||
|
||||
Nname *Name // ONAME node
|
||||
OClosure *ClosureExpr // OCLOSURE node
|
||||
|
|
@ -140,7 +139,6 @@ func NewFunc(pos src.XPos) *Func {
|
|||
f := new(Func)
|
||||
f.pos = pos
|
||||
f.op = ODCLFUNC
|
||||
f.Iota = -1
|
||||
// Most functions are ABIInternal. The importer or symabis
|
||||
// pass may override this.
|
||||
f.ABI = obj.ABIInternal
|
||||
|
|
@ -370,7 +368,9 @@ func NewClosureFunc(pos src.XPos, hidden bool) *Func {
|
|||
fn.Nname.Func = fn
|
||||
fn.Nname.Defn = fn
|
||||
|
||||
fn.OClosure = NewClosureExpr(pos, fn)
|
||||
fn.OClosure = &ClosureExpr{Func: fn}
|
||||
fn.OClosure.op = OCLOSURE
|
||||
fn.OClosure.pos = pos
|
||||
|
||||
return fn
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,10 +54,8 @@ func (n *miniNode) Esc() uint16 { return n.esc }
|
|||
func (n *miniNode) SetEsc(x uint16) { n.esc = x }
|
||||
|
||||
const (
|
||||
miniWalkdefShift = 0 // TODO(mdempsky): Move to Name.flags.
|
||||
miniTypecheckShift = 2
|
||||
miniDiag = 1 << 4
|
||||
miniWalked = 1 << 5 // to prevent/catch re-walking
|
||||
miniTypecheckShift = 0
|
||||
miniWalked = 1 << 2 // to prevent/catch re-walking
|
||||
)
|
||||
|
||||
func (n *miniNode) Typecheck() uint8 { return n.bits.get2(miniTypecheckShift) }
|
||||
|
|
@ -68,9 +66,6 @@ func (n *miniNode) SetTypecheck(x uint8) {
|
|||
n.bits.set2(miniTypecheckShift, x)
|
||||
}
|
||||
|
||||
func (n *miniNode) Diag() bool { return n.bits&miniDiag != 0 }
|
||||
func (n *miniNode) SetDiag(x bool) { n.bits.set(miniDiag, x) }
|
||||
|
||||
func (n *miniNode) Walked() bool { return n.bits&miniWalked != 0 }
|
||||
func (n *miniNode) SetWalked(x bool) { n.bits.set(miniWalked, x) }
|
||||
|
||||
|
|
|
|||
|
|
@ -166,14 +166,6 @@ func NewNameAt(pos src.XPos, sym *types.Sym) *Name {
|
|||
return newNameAt(pos, ONAME, sym)
|
||||
}
|
||||
|
||||
// NewIota returns a new OIOTA Node.
|
||||
func NewIota(pos src.XPos, sym *types.Sym) *Name {
|
||||
if sym == nil {
|
||||
base.Fatalf("NewIota nil")
|
||||
}
|
||||
return newNameAt(pos, OIOTA, sym)
|
||||
}
|
||||
|
||||
// NewDeclNameAt returns a new Name associated with symbol s at position pos.
|
||||
// The caller is responsible for setting Curfn.
|
||||
func NewDeclNameAt(pos src.XPos, op Op, sym *types.Sym) *Name {
|
||||
|
|
@ -223,15 +215,6 @@ func (n *Name) SetOffset(x int64) {
|
|||
}
|
||||
func (n *Name) FrameOffset() int64 { return n.Offset_ }
|
||||
func (n *Name) SetFrameOffset(x int64) { n.Offset_ = x }
|
||||
func (n *Name) Iota() int64 { return n.Offset_ }
|
||||
func (n *Name) SetIota(x int64) { n.Offset_ = x }
|
||||
func (n *Name) Walkdef() uint8 { return n.bits.get2(miniWalkdefShift) }
|
||||
func (n *Name) SetWalkdef(x uint8) {
|
||||
if x > 3 {
|
||||
panic(fmt.Sprintf("cannot SetWalkdef %d", x))
|
||||
}
|
||||
n.bits.set2(miniWalkdefShift, x)
|
||||
}
|
||||
|
||||
func (n *Name) Linksym() *obj.LSym { return n.sym.Linksym() }
|
||||
func (n *Name) LinksymABI(abi obj.ABI) *obj.LSym { return n.sym.LinksymABI(abi) }
|
||||
|
|
|
|||
|
|
@ -46,8 +46,6 @@ type Node interface {
|
|||
// Storage for analysis passes.
|
||||
Esc() uint16
|
||||
SetEsc(x uint16)
|
||||
Diag() bool
|
||||
SetDiag(x bool)
|
||||
|
||||
// Typecheck values:
|
||||
// 0 means the node is not typechecked
|
||||
|
|
@ -240,7 +238,6 @@ const (
|
|||
ORECV // <-X
|
||||
ORUNESTR // Type(X) (Type is string, X is rune)
|
||||
OSELRECV2 // like OAS2: Lhs = Rhs where len(Lhs)=2, len(Rhs)=1, Rhs[0].Op = ORECV (appears as .Var of OCASE)
|
||||
OIOTA // iota
|
||||
OREAL // real(X)
|
||||
OIMAG // imag(X)
|
||||
OCOMPLEX // complex(X, Y)
|
||||
|
|
|
|||
|
|
@ -112,62 +112,61 @@ func _() {
|
|||
_ = x[ORECV-101]
|
||||
_ = x[ORUNESTR-102]
|
||||
_ = x[OSELRECV2-103]
|
||||
_ = x[OIOTA-104]
|
||||
_ = x[OREAL-105]
|
||||
_ = x[OIMAG-106]
|
||||
_ = x[OCOMPLEX-107]
|
||||
_ = x[OALIGNOF-108]
|
||||
_ = x[OOFFSETOF-109]
|
||||
_ = x[OSIZEOF-110]
|
||||
_ = x[OUNSAFEADD-111]
|
||||
_ = x[OUNSAFESLICE-112]
|
||||
_ = x[OMETHEXPR-113]
|
||||
_ = x[OMETHVALUE-114]
|
||||
_ = x[OBLOCK-115]
|
||||
_ = x[OBREAK-116]
|
||||
_ = x[OCASE-117]
|
||||
_ = x[OCONTINUE-118]
|
||||
_ = x[ODEFER-119]
|
||||
_ = x[OFALL-120]
|
||||
_ = x[OFOR-121]
|
||||
_ = x[OFORUNTIL-122]
|
||||
_ = x[OGOTO-123]
|
||||
_ = x[OIF-124]
|
||||
_ = x[OLABEL-125]
|
||||
_ = x[OGO-126]
|
||||
_ = x[ORANGE-127]
|
||||
_ = x[ORETURN-128]
|
||||
_ = x[OSELECT-129]
|
||||
_ = x[OSWITCH-130]
|
||||
_ = x[OTYPESW-131]
|
||||
_ = x[OFUNCINST-132]
|
||||
_ = x[OTFUNC-133]
|
||||
_ = x[OINLCALL-134]
|
||||
_ = x[OEFACE-135]
|
||||
_ = x[OITAB-136]
|
||||
_ = x[OIDATA-137]
|
||||
_ = x[OSPTR-138]
|
||||
_ = x[OCFUNC-139]
|
||||
_ = x[OCHECKNIL-140]
|
||||
_ = x[OVARDEF-141]
|
||||
_ = x[OVARKILL-142]
|
||||
_ = x[OVARLIVE-143]
|
||||
_ = x[ORESULT-144]
|
||||
_ = x[OINLMARK-145]
|
||||
_ = x[OLINKSYMOFFSET-146]
|
||||
_ = x[ODYNAMICDOTTYPE-147]
|
||||
_ = x[ODYNAMICDOTTYPE2-148]
|
||||
_ = x[ODYNAMICTYPE-149]
|
||||
_ = x[OTAILCALL-150]
|
||||
_ = x[OGETG-151]
|
||||
_ = x[OGETCALLERPC-152]
|
||||
_ = x[OGETCALLERSP-153]
|
||||
_ = x[OEND-154]
|
||||
_ = x[OREAL-104]
|
||||
_ = x[OIMAG-105]
|
||||
_ = x[OCOMPLEX-106]
|
||||
_ = x[OALIGNOF-107]
|
||||
_ = x[OOFFSETOF-108]
|
||||
_ = x[OSIZEOF-109]
|
||||
_ = x[OUNSAFEADD-110]
|
||||
_ = x[OUNSAFESLICE-111]
|
||||
_ = x[OMETHEXPR-112]
|
||||
_ = x[OMETHVALUE-113]
|
||||
_ = x[OBLOCK-114]
|
||||
_ = x[OBREAK-115]
|
||||
_ = x[OCASE-116]
|
||||
_ = x[OCONTINUE-117]
|
||||
_ = x[ODEFER-118]
|
||||
_ = x[OFALL-119]
|
||||
_ = x[OFOR-120]
|
||||
_ = x[OFORUNTIL-121]
|
||||
_ = x[OGOTO-122]
|
||||
_ = x[OIF-123]
|
||||
_ = x[OLABEL-124]
|
||||
_ = x[OGO-125]
|
||||
_ = x[ORANGE-126]
|
||||
_ = x[ORETURN-127]
|
||||
_ = x[OSELECT-128]
|
||||
_ = x[OSWITCH-129]
|
||||
_ = x[OTYPESW-130]
|
||||
_ = x[OFUNCINST-131]
|
||||
_ = x[OTFUNC-132]
|
||||
_ = x[OINLCALL-133]
|
||||
_ = x[OEFACE-134]
|
||||
_ = x[OITAB-135]
|
||||
_ = x[OIDATA-136]
|
||||
_ = x[OSPTR-137]
|
||||
_ = x[OCFUNC-138]
|
||||
_ = x[OCHECKNIL-139]
|
||||
_ = x[OVARDEF-140]
|
||||
_ = x[OVARKILL-141]
|
||||
_ = x[OVARLIVE-142]
|
||||
_ = x[ORESULT-143]
|
||||
_ = x[OINLMARK-144]
|
||||
_ = x[OLINKSYMOFFSET-145]
|
||||
_ = x[ODYNAMICDOTTYPE-146]
|
||||
_ = x[ODYNAMICDOTTYPE2-147]
|
||||
_ = x[ODYNAMICTYPE-148]
|
||||
_ = x[OTAILCALL-149]
|
||||
_ = x[OGETG-150]
|
||||
_ = x[OGETCALLERPC-151]
|
||||
_ = x[OGETCALLERSP-152]
|
||||
_ = x[OEND-153]
|
||||
}
|
||||
|
||||
const _Op_name = "XXXNAMENONAMETYPELITERALNILADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESSLICE2ARRPTRASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVIDATACONVNOPCOPYDCLDCLFUNCDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECOVERFPRECVRUNESTRSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFUNSAFEADDUNSAFESLICEMETHEXPRMETHVALUEBLOCKBREAKCASECONTINUEDEFERFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWFUNCINSTTFUNCINLCALLEFACEITABIDATASPTRCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKLINKSYMOFFSETDYNAMICDOTTYPEDYNAMICDOTTYPE2DYNAMICTYPETAILCALLGETGGETCALLERPCGETCALLERSPEND"
|
||||
const _Op_name = "XXXNAMENONAMETYPELITERALNILADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESSLICE2ARRPTRASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVIDATACONVNOPCOPYDCLDCLFUNCDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECOVERFPRECVRUNESTRSELRECV2REALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFUNSAFEADDUNSAFESLICEMETHEXPRMETHVALUEBLOCKBREAKCASECONTINUEDEFERFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWFUNCINSTTFUNCINLCALLEFACEITABIDATASPTRCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKLINKSYMOFFSETDYNAMICDOTTYPEDYNAMICDOTTYPE2DYNAMICTYPETAILCALLGETGGETCALLERPCGETCALLERSPEND"
|
||||
|
||||
var _Op_index = [...]uint16{0, 3, 7, 13, 17, 24, 27, 30, 33, 35, 38, 44, 48, 54, 60, 69, 81, 90, 99, 111, 120, 132, 134, 137, 147, 154, 161, 168, 172, 176, 184, 192, 201, 204, 209, 216, 223, 229, 238, 246, 254, 260, 264, 273, 282, 289, 293, 296, 303, 311, 318, 324, 327, 333, 340, 348, 352, 359, 367, 369, 371, 373, 375, 377, 379, 384, 389, 397, 400, 409, 412, 416, 424, 431, 440, 453, 456, 459, 462, 465, 468, 471, 477, 480, 483, 489, 493, 496, 500, 505, 510, 516, 521, 525, 530, 538, 546, 552, 561, 572, 579, 588, 592, 599, 607, 611, 615, 619, 626, 633, 641, 647, 656, 667, 675, 684, 689, 694, 698, 706, 711, 715, 718, 726, 730, 732, 737, 739, 744, 750, 756, 762, 768, 776, 781, 788, 793, 797, 802, 806, 811, 819, 825, 832, 839, 845, 852, 865, 879, 894, 905, 913, 917, 928, 939, 942}
|
||||
var _Op_index = [...]uint16{0, 3, 7, 13, 17, 24, 27, 30, 33, 35, 38, 44, 48, 54, 60, 69, 81, 90, 99, 111, 120, 132, 134, 137, 147, 154, 161, 168, 172, 176, 184, 192, 201, 204, 209, 216, 223, 229, 238, 246, 254, 260, 264, 273, 282, 289, 293, 296, 303, 311, 318, 324, 327, 333, 340, 348, 352, 359, 367, 369, 371, 373, 375, 377, 379, 384, 389, 397, 400, 409, 412, 416, 424, 431, 440, 453, 456, 459, 462, 465, 468, 471, 477, 480, 483, 489, 493, 496, 500, 505, 510, 516, 521, 525, 530, 538, 546, 552, 561, 572, 579, 588, 592, 599, 607, 611, 615, 622, 629, 637, 643, 652, 663, 671, 680, 685, 690, 694, 702, 707, 711, 714, 722, 726, 728, 733, 735, 740, 746, 752, 758, 764, 772, 777, 784, 789, 793, 798, 802, 807, 815, 821, 828, 835, 841, 848, 861, 875, 890, 901, 909, 913, 924, 935, 938}
|
||||
|
||||
func (i Op) String() string {
|
||||
if i >= Op(len(_Op_index)-1) {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ func TestSizeof(t *testing.T) {
|
|||
_32bit uintptr // size on 32bit platforms
|
||||
_64bit uintptr // size on 64bit platforms
|
||||
}{
|
||||
{Func{}, 192, 328},
|
||||
{Func{}, 184, 320},
|
||||
{Name{}, 108, 192},
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -362,7 +362,7 @@ func NewSendStmt(pos src.XPos, ch, value Node) *SendStmt {
|
|||
return n
|
||||
}
|
||||
|
||||
// A SwitchStmt is a switch statement: switch Init; Expr { Cases }.
|
||||
// A SwitchStmt is a switch statement: switch Init; Tag { Cases }.
|
||||
type SwitchStmt struct {
|
||||
miniStmt
|
||||
Tag Node
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ package ir
|
|||
|
||||
import (
|
||||
"go/constant"
|
||||
"math"
|
||||
|
||||
"cmd/compile/internal/base"
|
||||
"cmd/compile/internal/types"
|
||||
|
|
@ -19,27 +18,6 @@ func ConstType(n Node) constant.Kind {
|
|||
return n.Val().Kind()
|
||||
}
|
||||
|
||||
// ConstValue returns the constant value stored in n as an interface{}.
|
||||
// It returns int64s for ints and runes, float64s for floats,
|
||||
// and complex128s for complex values.
|
||||
func ConstValue(n Node) interface{} {
|
||||
switch v := n.Val(); v.Kind() {
|
||||
default:
|
||||
base.Fatalf("unexpected constant: %v", v)
|
||||
panic("unreachable")
|
||||
case constant.Bool:
|
||||
return constant.BoolVal(v)
|
||||
case constant.String:
|
||||
return constant.StringVal(v)
|
||||
case constant.Int:
|
||||
return IntVal(n.Type(), v)
|
||||
case constant.Float:
|
||||
return Float64Val(v)
|
||||
case constant.Complex:
|
||||
return complex(Float64Val(constant.Real(v)), Float64Val(constant.Imag(v)))
|
||||
}
|
||||
}
|
||||
|
||||
// IntVal returns v converted to int64.
|
||||
// Note: if t is uint64, very large values will be converted to negative int64.
|
||||
func IntVal(t *types.Type, v constant.Value) int64 {
|
||||
|
|
@ -56,14 +34,6 @@ func IntVal(t *types.Type, v constant.Value) int64 {
|
|||
panic("unreachable")
|
||||
}
|
||||
|
||||
func Float64Val(v constant.Value) float64 {
|
||||
if x, _ := constant.Float64Val(v); !math.IsInf(x, 0) {
|
||||
return x + 0 // avoid -0 (should not be needed, but be conservative)
|
||||
}
|
||||
base.Fatalf("bad float64 value: %v", v)
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
func AssertValidTypeForConst(t *types.Type, v constant.Value) {
|
||||
if !ValidTypeForConst(t, v) {
|
||||
base.Fatalf("%v (%v) does not represent %v (%v)", t, t.Kind(), v, v.Kind())
|
||||
|
|
@ -114,18 +84,6 @@ func idealType(ct constant.Kind) *types.Type {
|
|||
|
||||
var OKForConst [types.NTYPE]bool
|
||||
|
||||
// CanInt64 reports whether it is safe to call Int64Val() on n.
|
||||
func CanInt64(n Node) bool {
|
||||
if !IsConst(n, constant.Int) {
|
||||
return false
|
||||
}
|
||||
|
||||
// if the value inside n cannot be represented as an int64, the
|
||||
// return value of Int64 is undefined
|
||||
_, ok := constant.Int64Val(n.Val())
|
||||
return ok
|
||||
}
|
||||
|
||||
// Int64Val returns n as an int64.
|
||||
// n must be an integer or rune constant.
|
||||
func Int64Val(n Node) int64 {
|
||||
|
|
|
|||
|
|
@ -405,7 +405,7 @@ func uriIfy(f string) DocumentURI {
|
|||
// Return filename, replacing a first occurrence of $GOROOT with the
|
||||
// actual value of the GOROOT (because LSP does not speak "$GOROOT").
|
||||
func uprootedPath(filename string) string {
|
||||
if !strings.HasPrefix(filename, "$GOROOT/") {
|
||||
if buildcfg.GOROOT == "" || !strings.HasPrefix(filename, "$GOROOT/") {
|
||||
return filename
|
||||
}
|
||||
return buildcfg.GOROOT + filename[len("$GOROOT"):]
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ func s15a8(x *[15]int64) [15]int64 {
|
|||
}
|
||||
|
||||
func testLogOpt(t *testing.T, flag, src, outfile string) (string, error) {
|
||||
run := []string{testenv.GoToolPath(t), "tool", "compile", flag, "-o", outfile, src}
|
||||
run := []string{testenv.GoToolPath(t), "tool", "compile", "-p=p", flag, "-o", outfile, src}
|
||||
t.Log(run)
|
||||
cmd := exec.Command(run[0], run[1:]...)
|
||||
out, err := cmd.CombinedOutput()
|
||||
|
|
@ -236,7 +236,7 @@ func testLogOpt(t *testing.T, flag, src, outfile string) (string, error) {
|
|||
|
||||
func testLogOptDir(t *testing.T, dir, flag, src, outfile string) (string, error) {
|
||||
// Notice the specified import path "x"
|
||||
run := []string{testenv.GoToolPath(t), "tool", "compile", "-p", "x", flag, "-o", outfile, src}
|
||||
run := []string{testenv.GoToolPath(t), "tool", "compile", "-p=x", flag, "-o", outfile, src}
|
||||
t.Log(run)
|
||||
cmd := exec.Command(run[0], run[1:]...)
|
||||
cmd.Dir = dir
|
||||
|
|
@ -247,7 +247,7 @@ func testLogOptDir(t *testing.T, dir, flag, src, outfile string) (string, error)
|
|||
|
||||
func testCopy(t *testing.T, dir, goarch, goos, src, outfile string) (string, error) {
|
||||
// Notice the specified import path "x"
|
||||
run := []string{testenv.GoToolPath(t), "tool", "compile", "-p", "x", "-json=0,file://log/opt", "-o", outfile, src}
|
||||
run := []string{testenv.GoToolPath(t), "tool", "compile", "-p=x", "-json=0,file://log/opt", "-o", outfile, src}
|
||||
t.Log(run)
|
||||
cmd := exec.Command(run[0], run[1:]...)
|
||||
cmd.Dir = dir
|
||||
|
|
|
|||
|
|
@ -29,9 +29,6 @@ const (
|
|||
stmtFor
|
||||
stmtSwitch
|
||||
stmtSelect
|
||||
|
||||
// TODO(mdempsky): Remove after we don't care about toolstash -cmp.
|
||||
stmtTypeDeclHack
|
||||
)
|
||||
|
||||
type codeExpr int
|
||||
|
|
|
|||
|
|
@ -114,11 +114,11 @@ func (g *irgen) funcDecl(out *ir.Nodes, decl *syntax.FuncDecl) {
|
|||
// the Fields to represent the receiver's method set.
|
||||
if recv := fn.Type().Recv(); recv != nil {
|
||||
typ := types.ReceiverBaseType(recv.Type)
|
||||
if typ.OrigSym() != nil {
|
||||
if orig := typ.OrigType(); orig != nil {
|
||||
// For a generic method, we mark the methods on the
|
||||
// base generic type, since those are the methods
|
||||
// that will be stenciled.
|
||||
typ = typ.OrigSym().Def.Type()
|
||||
typ = orig
|
||||
}
|
||||
meth := typecheck.Lookdot1(fn, typecheck.Lookup(decl.Name.Value), typ, typ.Methods(), 0)
|
||||
meth.SetNointerface(true)
|
||||
|
|
|
|||
|
|
@ -439,7 +439,6 @@ func (g *irgen) funcLit(typ2 types2.Type, expr *syntax.FuncLit) ir.Node {
|
|||
for _, cv := range fn.ClosureVars {
|
||||
cv.SetType(cv.Canonical().Type())
|
||||
cv.SetTypecheck(1)
|
||||
cv.SetWalkdef(1)
|
||||
}
|
||||
|
||||
if g.topFuncIsGeneric {
|
||||
|
|
|
|||
|
|
@ -369,16 +369,8 @@ func addFingerprint(path string, f *os.File, end int64) error {
|
|||
}
|
||||
|
||||
copy(fingerprint[:], buf[:])
|
||||
base.Ctxt.AddImport(path, fingerprint)
|
||||
|
||||
// assume files move (get installed) so don't record the full path
|
||||
if base.Flag.Cfg.PackageFile != nil {
|
||||
// If using a packageFile map, assume path_ can be recorded directly.
|
||||
base.Ctxt.AddImport(path, fingerprint)
|
||||
} else {
|
||||
// For file "/Users/foo/go/pkg/darwin_amd64/math.a" record "math.a".
|
||||
file := f.Name()
|
||||
base.Ctxt.AddImport(file[len(file)-len(path)-len(".a"):], fingerprint)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -99,8 +99,8 @@ type subDictInfo struct {
|
|||
}
|
||||
|
||||
// dictInfo is the dictionary format for an instantiation of a generic function with
|
||||
// particular shapes. shapeParams, derivedTypes, subDictCalls, and itabConvs describe
|
||||
// the actual dictionary entries in order, and the remaining fields are other info
|
||||
// particular shapes. shapeParams, derivedTypes, subDictCalls, itabConvs, and methodExprClosures
|
||||
// describe the actual dictionary entries in order, and the remaining fields are other info
|
||||
// needed in doing dictionary processing during compilation.
|
||||
type dictInfo struct {
|
||||
// Types substituted for the type parameters, which are shape types.
|
||||
|
|
@ -114,6 +114,11 @@ type dictInfo struct {
|
|||
// Nodes in the instantiation that are a conversion from a typeparam/derived
|
||||
// type to a specific interface.
|
||||
itabConvs []ir.Node
|
||||
// Method expression closures. For a generic type T with method M(arg1, arg2) res,
|
||||
// these closures are func(rcvr T, arg1, arg2) res.
|
||||
// These closures capture no variables, they are just the generic version of ·f symbols
|
||||
// that live in the dictionary instead of in the readonly globals section.
|
||||
methodExprClosures []methodExprClosure
|
||||
|
||||
// Mapping from each shape type that substitutes a type param, to its
|
||||
// type bound (which is also substituted with shapes if it is parameterized)
|
||||
|
|
@ -123,9 +128,15 @@ type dictInfo struct {
|
|||
// HasShape type, to the interface type we're switching from.
|
||||
type2switchType map[ir.Node]*types.Type
|
||||
|
||||
startSubDict int // Start of dict entries for subdictionaries
|
||||
startItabConv int // Start of dict entries for itab conversions
|
||||
dictLen int // Total number of entries in dictionary
|
||||
startSubDict int // Start of dict entries for subdictionaries
|
||||
startItabConv int // Start of dict entries for itab conversions
|
||||
startMethodExprClosures int // Start of dict entries for closures for method expressions
|
||||
dictLen int // Total number of entries in dictionary
|
||||
}
|
||||
|
||||
type methodExprClosure struct {
|
||||
idx int // index in list of shape parameters
|
||||
name string // method name
|
||||
}
|
||||
|
||||
// instInfo is information gathered on an shape instantiation of a function.
|
||||
|
|
@ -182,7 +193,7 @@ type genInst struct {
|
|||
instInfoMap map[*types.Sym]*instInfo
|
||||
|
||||
// Dictionary syms which we need to finish, by writing out any itabconv
|
||||
// entries.
|
||||
// or method expression closure entries.
|
||||
dictSymsToFinalize []*delayInfo
|
||||
|
||||
// New instantiations created during this round of buildInstantiations().
|
||||
|
|
|
|||
|
|
@ -472,7 +472,7 @@ func checkEmbed(decl *syntax.VarDecl, haveEmbed, withinFunc bool) error {
|
|||
return errors.New("go:embed cannot apply to var without type")
|
||||
case withinFunc:
|
||||
return errors.New("go:embed cannot apply to var inside func")
|
||||
case !types.AllowsGoVersion(types.LocalPkg, 1, 16):
|
||||
case !types.AllowsGoVersion(1, 16):
|
||||
return fmt.Errorf("go:embed requires go1.16 or later (-lang was set to %s; check go.mod)", base.Flag.Lang)
|
||||
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -171,7 +171,6 @@ func (g *irgen) objFinish(name *ir.Name, class ir.Class, typ *types.Type) {
|
|||
}
|
||||
|
||||
name.SetTypecheck(1)
|
||||
name.SetWalkdef(1)
|
||||
|
||||
if ir.IsBlank(name) {
|
||||
return
|
||||
|
|
|
|||
|
|
@ -26,12 +26,6 @@ import (
|
|||
"cmd/internal/src"
|
||||
)
|
||||
|
||||
// TODO(mdempsky): Suppress duplicate type/const errors that can arise
|
||||
// during typecheck due to naive type substitution (e.g., see #42758).
|
||||
// I anticipate these will be handled as a consequence of adding
|
||||
// dictionaries support, so it's probably not important to focus on
|
||||
// this until after that's done.
|
||||
|
||||
type pkgReader struct {
|
||||
pkgbits.PkgDecoder
|
||||
|
||||
|
|
@ -147,6 +141,13 @@ type readerDict struct {
|
|||
|
||||
funcs []objInfo
|
||||
funcsObj []ir.Node
|
||||
|
||||
itabs []itabInfo2
|
||||
}
|
||||
|
||||
type itabInfo2 struct {
|
||||
typ *types.Type
|
||||
lsym *obj.LSym
|
||||
}
|
||||
|
||||
func setType(n ir.Node, typ *types.Type) {
|
||||
|
|
@ -154,7 +155,6 @@ func setType(n ir.Node, typ *types.Type) {
|
|||
n.SetTypecheck(1)
|
||||
|
||||
if name, ok := n.(*ir.Name); ok {
|
||||
name.SetWalkdef(1)
|
||||
name.Ntype = ir.TypeNode(name.Type())
|
||||
}
|
||||
}
|
||||
|
|
@ -209,7 +209,7 @@ func (pr *pkgReader) posBaseIdx(idx int) *src.PosBase {
|
|||
// require being more consistent about when we use native vs UNIX
|
||||
// file paths.
|
||||
const dollarGOROOT = "$GOROOT"
|
||||
if strings.HasPrefix(filename, dollarGOROOT) {
|
||||
if buildcfg.GOROOT != "" && strings.HasPrefix(filename, dollarGOROOT) {
|
||||
filename = buildcfg.GOROOT + filename[len(dollarGOROOT):]
|
||||
}
|
||||
|
||||
|
|
@ -643,6 +643,10 @@ func (pr *pkgReader) objIdx(idx int, implicits, explicits []*types.Type) ir.Node
|
|||
name.Func = ir.NewFunc(r.pos())
|
||||
name.Func.Nname = name
|
||||
|
||||
if r.hasTypeParams() {
|
||||
name.Func.SetDupok(true)
|
||||
}
|
||||
|
||||
rext.funcExt(name)
|
||||
return name
|
||||
|
||||
|
|
@ -745,6 +749,22 @@ func (pr *pkgReader) objDictIdx(sym *types.Sym, idx int, implicits, explicits []
|
|||
dict.funcs[i] = objInfo{idx: objIdx, explicits: targs}
|
||||
}
|
||||
|
||||
dict.itabs = make([]itabInfo2, r.Len())
|
||||
for i := range dict.itabs {
|
||||
typ := pr.typIdx(typeInfo{idx: r.Len(), derived: true}, &dict, true)
|
||||
ifaceInfo := r.typInfo()
|
||||
|
||||
var lsym *obj.LSym
|
||||
if typ.IsInterface() {
|
||||
lsym = reflectdata.TypeLinksym(typ)
|
||||
} else {
|
||||
iface := pr.typIdx(ifaceInfo, &dict, true)
|
||||
lsym = reflectdata.ITabLsym(typ, iface)
|
||||
}
|
||||
|
||||
dict.itabs[i] = itabInfo2{typ: typ, lsym: lsym}
|
||||
}
|
||||
|
||||
return &dict
|
||||
}
|
||||
|
||||
|
|
@ -773,6 +793,10 @@ func (r *reader) method(rext *reader) *types.Field {
|
|||
name.Func = ir.NewFunc(r.pos())
|
||||
name.Func.Nname = name
|
||||
|
||||
if r.hasTypeParams() {
|
||||
name.Func.SetDupok(true)
|
||||
}
|
||||
|
||||
rext.funcExt(name)
|
||||
|
||||
meth := types.NewField(name.Func.Pos(), sym, typ)
|
||||
|
|
@ -930,11 +954,6 @@ var bodyReader = map[*ir.Func]pkgReaderIndex{}
|
|||
// constructed.
|
||||
var todoBodies []*ir.Func
|
||||
|
||||
// todoBodiesDone signals that we constructed all function in todoBodies.
|
||||
// This is necessary to prevent reader.addBody adds thing to todoBodies
|
||||
// when nested inlining happens.
|
||||
var todoBodiesDone = false
|
||||
|
||||
func (r *reader) addBody(fn *ir.Func) {
|
||||
pri := pkgReaderIndex{r.p, r.Reloc(pkgbits.RelocBody), r.dict}
|
||||
bodyReader[fn] = pri
|
||||
|
|
@ -945,7 +964,7 @@ func (r *reader) addBody(fn *ir.Func) {
|
|||
return
|
||||
}
|
||||
|
||||
if r.curfn == nil && !todoBodiesDone {
|
||||
if r.curfn == nil {
|
||||
todoBodies = append(todoBodies, fn)
|
||||
return
|
||||
}
|
||||
|
|
@ -1412,25 +1431,22 @@ func (r *reader) switchStmt(label *types.Sym) ir.Node {
|
|||
init := r.stmt()
|
||||
|
||||
var tag ir.Node
|
||||
var ident *ir.Ident
|
||||
var iface *types.Type
|
||||
if r.Bool() {
|
||||
pos := r.pos()
|
||||
var ident *ir.Ident
|
||||
if r.Bool() {
|
||||
pos := r.pos()
|
||||
sym := typecheck.Lookup(r.String())
|
||||
ident = ir.NewIdent(pos, sym)
|
||||
}
|
||||
x := r.expr()
|
||||
iface = x.Type()
|
||||
tag = ir.NewTypeSwitchGuard(pos, ident, x)
|
||||
} else {
|
||||
tag = r.expr()
|
||||
}
|
||||
|
||||
tswitch, ok := tag.(*ir.TypeSwitchGuard)
|
||||
if ok && tswitch.Tag == nil {
|
||||
tswitch = nil
|
||||
}
|
||||
|
||||
clauses := make([]*ir.CaseClause, r.Len())
|
||||
for i := range clauses {
|
||||
if i > 0 {
|
||||
|
|
@ -1439,18 +1455,30 @@ func (r *reader) switchStmt(label *types.Sym) ir.Node {
|
|||
r.openScope()
|
||||
|
||||
pos := r.pos()
|
||||
cases := r.exprList()
|
||||
var cases []ir.Node
|
||||
if iface != nil {
|
||||
cases = make([]ir.Node, r.Len())
|
||||
if len(cases) == 0 {
|
||||
cases = nil // TODO(mdempsky): Unclear if this matters.
|
||||
}
|
||||
for i := range cases {
|
||||
cases[i] = r.exprType(true)
|
||||
}
|
||||
} else {
|
||||
cases = r.exprList()
|
||||
}
|
||||
|
||||
clause := ir.NewCaseStmt(pos, cases, nil)
|
||||
if tswitch != nil {
|
||||
|
||||
if ident != nil {
|
||||
pos := r.pos()
|
||||
typ := r.typ()
|
||||
|
||||
name := ir.NewNameAt(pos, tswitch.Tag.Sym())
|
||||
name := ir.NewNameAt(pos, ident.Sym())
|
||||
setType(name, typ)
|
||||
r.addLocal(name, ir.PAUTO)
|
||||
clause.Var = name
|
||||
name.Defn = tswitch
|
||||
name.Defn = tag
|
||||
}
|
||||
|
||||
clause.Body = r.stmts()
|
||||
|
|
@ -1534,10 +1562,7 @@ func (r *reader) expr() (res ir.Node) {
|
|||
return typecheck.Callee(r.obj())
|
||||
|
||||
case exprType:
|
||||
// TODO(mdempsky): ir.TypeNode should probably return a typecheck'd node.
|
||||
n := ir.TypeNode(r.typ())
|
||||
n.SetTypecheck(1)
|
||||
return n
|
||||
return r.exprType(false)
|
||||
|
||||
case exprConst:
|
||||
pos := r.pos()
|
||||
|
|
@ -1557,6 +1582,15 @@ func (r *reader) expr() (res ir.Node) {
|
|||
x := r.expr()
|
||||
pos := r.pos()
|
||||
_, sym := r.selector()
|
||||
|
||||
// Method expression with derived receiver type.
|
||||
if x.Op() == ir.ODYNAMICTYPE {
|
||||
// TODO(mdempsky): Handle with runtime dictionary lookup.
|
||||
n := ir.TypeNode(x.Type())
|
||||
n.SetTypecheck(1)
|
||||
x = n
|
||||
}
|
||||
|
||||
n := typecheck.Expr(ir.NewSelectorExpr(pos, ir.OXDOT, x, sym)).(*ir.SelectorExpr)
|
||||
if n.Op() == ir.OMETHVALUE {
|
||||
wrapper := methodValueWrapper{
|
||||
|
|
@ -1593,8 +1627,12 @@ func (r *reader) expr() (res ir.Node) {
|
|||
case exprAssert:
|
||||
x := r.expr()
|
||||
pos := r.pos()
|
||||
typ := r.expr().(ir.Ntype)
|
||||
return typecheck.Expr(ir.NewTypeAssertExpr(pos, x, typ))
|
||||
typ := r.exprType(false)
|
||||
|
||||
if typ, ok := typ.(*ir.DynamicType); ok && typ.Op() == ir.ODYNAMICTYPE {
|
||||
return typed(typ.Type(), ir.NewDynamicTypeAssertExpr(pos, ir.ODYNAMICDOTTYPE, x, typ.X))
|
||||
}
|
||||
return typecheck.Expr(ir.NewTypeAssertExpr(pos, x, typ.(ir.Ntype)))
|
||||
|
||||
case exprUnaryOp:
|
||||
op := r.op()
|
||||
|
|
@ -1637,6 +1675,20 @@ func (r *reader) expr() (res ir.Node) {
|
|||
typ := r.typ()
|
||||
pos := r.pos()
|
||||
x := r.expr()
|
||||
|
||||
// TODO(mdempsky): Stop constructing expressions of untyped type.
|
||||
x = typecheck.DefaultLit(x, typ)
|
||||
|
||||
if op, why := typecheck.Convertop(x.Op() == ir.OLITERAL, x.Type(), typ); op == ir.OXXX {
|
||||
// types2 ensured that x is convertable to typ under standard Go
|
||||
// semantics, but cmd/compile also disallows some conversions
|
||||
// involving //go:notinheap.
|
||||
//
|
||||
// TODO(mdempsky): This can be removed after #46731 is implemented.
|
||||
base.ErrorfAt(pos, "cannot convert %L to type %v%v", x, typ, why)
|
||||
base.ErrorExit() // harsh, but prevents constructing invalid IR
|
||||
}
|
||||
|
||||
return typecheck.Expr(ir.NewConvExpr(pos, ir.OCONV, typ, x))
|
||||
}
|
||||
}
|
||||
|
|
@ -1739,6 +1791,39 @@ func (r *reader) exprs() []ir.Node {
|
|||
return nodes
|
||||
}
|
||||
|
||||
func (r *reader) exprType(nilOK bool) ir.Node {
|
||||
r.Sync(pkgbits.SyncExprType)
|
||||
|
||||
if nilOK && r.Bool() {
|
||||
return typecheck.Expr(types.BuiltinPkg.Lookup("nil").Def.(*ir.NilExpr))
|
||||
}
|
||||
|
||||
pos := r.pos()
|
||||
|
||||
var typ *types.Type
|
||||
var lsym *obj.LSym
|
||||
|
||||
if r.Bool() {
|
||||
itab := r.dict.itabs[r.Len()]
|
||||
typ, lsym = itab.typ, itab.lsym
|
||||
} else {
|
||||
info := r.typInfo()
|
||||
typ = r.p.typIdx(info, r.dict, true)
|
||||
|
||||
if !info.derived {
|
||||
// TODO(mdempsky): ir.TypeNode should probably return a typecheck'd node.
|
||||
n := ir.TypeNode(typ)
|
||||
n.SetTypecheck(1)
|
||||
return n
|
||||
}
|
||||
|
||||
lsym = reflectdata.TypeLinksym(typ)
|
||||
}
|
||||
|
||||
ptr := typecheck.Expr(typecheck.NodAddr(ir.NewLinksymExpr(pos, lsym, types.Types[types.TUINT8])))
|
||||
return typed(typ, ir.NewDynamicType(pos, ptr))
|
||||
}
|
||||
|
||||
func (r *reader) op() ir.Op {
|
||||
r.Sync(pkgbits.SyncOp)
|
||||
return ir.Op(r.Len())
|
||||
|
|
@ -1974,6 +2059,13 @@ func InlineCall(call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.InlinedCallExp
|
|||
r.curfn.Body = r.stmts()
|
||||
r.curfn.Endlineno = r.pos()
|
||||
|
||||
// TODO(mdempsky): This shouldn't be necessary. Inlining might
|
||||
// read in new function/method declarations, which could
|
||||
// potentially be recursively inlined themselves; but we shouldn't
|
||||
// need to read in the non-inlined bodies for the declarations
|
||||
// themselves. But currently it's an easy fix to #50552.
|
||||
readBodies(typecheck.Target)
|
||||
|
||||
deadcode.Func(r.curfn)
|
||||
|
||||
// Replace any "return" statements within the function body.
|
||||
|
|
|
|||
|
|
@ -193,8 +193,7 @@ func (g *genInst) scanForGenCalls(decl ir.Node) {
|
|||
targs := deref(meth.Type().Recv().Type).RParams()
|
||||
|
||||
t := meth.X.Type()
|
||||
baseSym := deref(t).OrigSym()
|
||||
baseType := baseSym.Def.(*ir.Name).Type()
|
||||
baseType := deref(t).OrigType()
|
||||
var gf *ir.Name
|
||||
for _, m := range baseType.Methods().Slice() {
|
||||
if meth.Sel == m.Sym {
|
||||
|
|
@ -348,7 +347,7 @@ func (g *genInst) buildClosure(outer *ir.Func, x ir.Node) ir.Node {
|
|||
// actually generic, so no need to build a closure.
|
||||
return x
|
||||
}
|
||||
baseType := recv.OrigSym().Def.Type()
|
||||
baseType := recv.OrigType()
|
||||
var gf *ir.Name
|
||||
for _, m := range baseType.Methods().Slice() {
|
||||
if se.Sel == m.Sym {
|
||||
|
|
@ -543,8 +542,7 @@ func (g *genInst) instantiateMethods() {
|
|||
typecheck.NeedRuntimeType(typ)
|
||||
// Lookup the method on the base generic type, since methods may
|
||||
// not be set on imported instantiated types.
|
||||
baseSym := typ.OrigSym()
|
||||
baseType := baseSym.Def.(*ir.Name).Type()
|
||||
baseType := typ.OrigType()
|
||||
for j, _ := range typ.Methods().Slice() {
|
||||
if baseType.Methods().Slice()[j].Nointerface() {
|
||||
typ.Methods().Slice()[j].SetNointerface(true)
|
||||
|
|
@ -644,7 +642,7 @@ func (g *genInst) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMe
|
|||
if recvType.IsFullyInstantiated() {
|
||||
// Get the type of the base generic type, so we get
|
||||
// its original typeparams.
|
||||
recvType = recvType.OrigSym().Def.(*ir.Name).Type()
|
||||
recvType = recvType.OrigType()
|
||||
}
|
||||
tparams = recvType.RParams()
|
||||
} else {
|
||||
|
|
@ -890,6 +888,13 @@ func getDictionaryEntry(pos src.XPos, dict *ir.Name, i int, size int) ir.Node {
|
|||
return r
|
||||
}
|
||||
|
||||
// getDictionaryEntryAddr gets the address of the i'th entry in dictionary dict.
|
||||
func getDictionaryEntryAddr(pos src.XPos, dict *ir.Name, i int, size int) ir.Node {
|
||||
a := ir.NewAddrExpr(pos, getDictionaryEntry(pos, dict, i, size))
|
||||
typed(types.Types[types.TUINTPTR].PtrTo(), a)
|
||||
return a
|
||||
}
|
||||
|
||||
// getDictionaryType returns a *runtime._type from the dictionary entry i (which
|
||||
// refers to a type param or a derived type that uses type params). It uses the
|
||||
// specified dictionary dictParam, rather than the one in info.dictParam.
|
||||
|
|
@ -898,7 +903,7 @@ func getDictionaryType(info *instInfo, dictParam *ir.Name, pos src.XPos, i int)
|
|||
base.Fatalf(fmt.Sprintf("bad dict index %d", i))
|
||||
}
|
||||
|
||||
r := getDictionaryEntry(pos, info.dictParam, i, info.dictInfo.startSubDict)
|
||||
r := getDictionaryEntry(pos, dictParam, i, info.dictInfo.startSubDict)
|
||||
// change type of retrieved dictionary entry to *byte, which is the
|
||||
// standard typing of a *runtime._type in the compiler
|
||||
typed(types.Types[types.TUINT8].PtrTo(), r)
|
||||
|
|
@ -1179,6 +1184,26 @@ func (subst *subster) node(n ir.Node) ir.Node {
|
|||
subst.g.newInsts = append(subst.g.newInsts, m.(*ir.ClosureExpr).Func)
|
||||
m.(*ir.ClosureExpr).SetInit(subst.list(x.Init()))
|
||||
|
||||
case ir.OSWITCH:
|
||||
m := m.(*ir.SwitchStmt)
|
||||
if m.Tag != nil && m.Tag.Op() == ir.OTYPESW {
|
||||
break // Nothing to do here for type switches.
|
||||
}
|
||||
if m.Tag != nil && !m.Tag.Type().IsInterface() && m.Tag.Type().HasShape() {
|
||||
// To implement a switch on a value that is or has a type parameter, we first convert
|
||||
// that thing we're switching on to an interface{}.
|
||||
m.Tag = assignconvfn(m.Tag, types.Types[types.TINTER])
|
||||
}
|
||||
for _, c := range m.Cases {
|
||||
for i, x := range c.List {
|
||||
// If we have a case that is or has a type parameter, convert that case
|
||||
// to an interface{}.
|
||||
if !x.Type().IsInterface() && x.Type().HasShape() {
|
||||
c.List[i] = assignconvfn(x, types.Types[types.TINTER])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
|
@ -1192,8 +1217,14 @@ func (g *genInst) dictPass(info *instInfo) {
|
|||
savef := ir.CurFunc
|
||||
ir.CurFunc = info.fun
|
||||
|
||||
callMap := make(map[ir.Node]bool)
|
||||
|
||||
var edit func(ir.Node) ir.Node
|
||||
edit = func(m ir.Node) ir.Node {
|
||||
if m.Op() == ir.OCALL && m.(*ir.CallExpr).X.Op() == ir.OXDOT {
|
||||
callMap[m.(*ir.CallExpr).X] = true
|
||||
}
|
||||
|
||||
ir.EditChildren(m, edit)
|
||||
|
||||
switch m.Op() {
|
||||
|
|
@ -1221,9 +1252,10 @@ func (g *genInst) dictPass(info *instInfo) {
|
|||
|
||||
if mse.X.Op() == ir.OTYPE {
|
||||
// Method expression T.M
|
||||
m = g.buildClosure2(info, m)
|
||||
// No need for transformDot - buildClosure2 has already
|
||||
// transformed to OCALLINTER/ODOTINTER.
|
||||
idx := findMethodExprClosure(info.dictInfo, mse)
|
||||
c := getDictionaryEntryAddr(m.Pos(), info.dictParam, info.dictInfo.startMethodExprClosures+idx, info.dictInfo.dictLen)
|
||||
m = ir.NewConvExpr(m.Pos(), ir.OCONVNOP, mse.Type(), c)
|
||||
m.SetTypecheck(1)
|
||||
} else {
|
||||
// If we can't find the selected method in the
|
||||
// AllMethods of the bound, then this must be an access
|
||||
|
|
@ -1231,20 +1263,23 @@ func (g *genInst) dictPass(info *instInfo) {
|
|||
// dictionary lookups - transformDot() will convert to
|
||||
// the desired direct field access.
|
||||
if isBoundMethod(info.dictInfo, mse) {
|
||||
if callMap[m] {
|
||||
// The OCALL surrounding this XDOT will rewrite the call
|
||||
// to use the method expression closure directly.
|
||||
break
|
||||
}
|
||||
// Convert this method value to a closure.
|
||||
// TODO: use method expression closure.
|
||||
dst := info.dictInfo.shapeToBound[mse.X.Type()]
|
||||
// Implement x.M as a conversion-to-bound-interface
|
||||
// 1) convert x to the bound interface
|
||||
// 2) call M on that interface
|
||||
// 2) select method value M on that interface
|
||||
if src.IsInterface() {
|
||||
// If type arg is an interface (unusual case),
|
||||
// we do a type assert to the type bound.
|
||||
mse.X = assertToBound(info, info.dictParam, m.Pos(), mse.X, dst)
|
||||
} else {
|
||||
mse.X = convertUsingDictionary(info, info.dictParam, m.Pos(), mse.X, m, dst, true)
|
||||
// Note: we set nonEscaping==true, because we can assume the backing store for the
|
||||
// interface conversion doesn't escape. The method call will immediately go to
|
||||
// a wrapper function which copies all the data out of the interface value.
|
||||
// (It only matters for non-pointer-shaped interface conversions. See issue 50182.)
|
||||
mse.X = convertUsingDictionary(info, info.dictParam, m.Pos(), mse.X, m, dst)
|
||||
}
|
||||
}
|
||||
transformDot(mse, false)
|
||||
|
|
@ -1252,6 +1287,25 @@ func (g *genInst) dictPass(info *instInfo) {
|
|||
case ir.OCALL:
|
||||
call := m.(*ir.CallExpr)
|
||||
op := call.X.Op()
|
||||
if op == ir.OXDOT {
|
||||
// This is a call of a method value where the value has a type parameter type.
|
||||
// We transform to a call of the appropriate method expression closure
|
||||
// in the dictionary.
|
||||
// So if x has a type parameter type:
|
||||
// _ = x.m(a)
|
||||
// Rewrite to:
|
||||
// _ = methexpr<m>(x, a)
|
||||
se := call.X.(*ir.SelectorExpr)
|
||||
call.SetOp(ir.OCALLFUNC)
|
||||
idx := findMethodExprClosure(info.dictInfo, se)
|
||||
c := getDictionaryEntryAddr(se.Pos(), info.dictParam, info.dictInfo.startMethodExprClosures+idx, info.dictInfo.dictLen)
|
||||
t := typecheck.NewMethodType(se.Type(), se.X.Type())
|
||||
call.X = ir.NewConvExpr(se.Pos(), ir.OCONVNOP, t, c)
|
||||
typed(t, call.X)
|
||||
call.Args.Prepend(se.X)
|
||||
break
|
||||
// TODO: deref case?
|
||||
}
|
||||
if op == ir.OMETHVALUE {
|
||||
// Redo the transformation of OXDOT, now that we
|
||||
// know the method value is being called.
|
||||
|
|
@ -1271,7 +1325,7 @@ func (g *genInst) dictPass(info *instInfo) {
|
|||
// Note: x's argument is still typed as a type parameter.
|
||||
// m's argument now has an instantiated type.
|
||||
if mce.X.Type().HasShape() || (mce.X.Type().IsInterface() && m.Type().HasShape()) {
|
||||
m = convertUsingDictionary(info, info.dictParam, m.Pos(), m.(*ir.ConvExpr).X, m, m.Type(), false)
|
||||
m = convertUsingDictionary(info, info.dictParam, m.Pos(), m.(*ir.ConvExpr).X, m, m.Type())
|
||||
}
|
||||
case ir.ODOTTYPE, ir.ODOTTYPE2:
|
||||
if !m.Type().HasShape() {
|
||||
|
|
@ -1364,9 +1418,7 @@ func findDictType(info *instInfo, t *types.Type) int {
|
|||
// type dst, by returning a new set of nodes that make use of a dictionary entry. in is the
|
||||
// instantiated node of the CONVIFACE node or XDOT node (for a bound method call) that is causing the
|
||||
// conversion.
|
||||
// If nonEscaping is true, the caller guarantees that the backing store needed for the interface data
|
||||
// word will not escape.
|
||||
func convertUsingDictionary(info *instInfo, dictParam *ir.Name, pos src.XPos, v ir.Node, in ir.Node, dst *types.Type, nonEscaping bool) ir.Node {
|
||||
func convertUsingDictionary(info *instInfo, dictParam *ir.Name, pos src.XPos, v ir.Node, in ir.Node, dst *types.Type) ir.Node {
|
||||
assert(v.Type().HasShape() || v.Type().IsInterface() && in.Type().HasShape())
|
||||
assert(dst.IsInterface())
|
||||
|
||||
|
|
@ -1436,7 +1488,6 @@ func convertUsingDictionary(info *instInfo, dictParam *ir.Name, pos src.XPos, v
|
|||
// Figure out what the data field of the interface will be.
|
||||
data := ir.NewConvExpr(pos, ir.OCONVIDATA, nil, v)
|
||||
typed(types.Types[types.TUNSAFEPTR], data)
|
||||
data.NonEscaping = nonEscaping
|
||||
|
||||
// Build an interface from the type and data parts.
|
||||
var i ir.Node = ir.NewBinaryExpr(pos, ir.OEFACE, rt, data)
|
||||
|
|
@ -1608,7 +1659,7 @@ func (g *genInst) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool
|
|||
// instantiated type, so we need a
|
||||
// sub-dictionary.
|
||||
targs := recvType.RParams()
|
||||
genRecvType := recvType.OrigSym().Def.Type()
|
||||
genRecvType := recvType.OrigType()
|
||||
nameNode = typecheck.Lookdot1(call.X, se.Sel, genRecvType, genRecvType.Methods(), 1).Nname.(*ir.Name)
|
||||
sym = g.getDictionarySym(nameNode, targs, true)
|
||||
} else {
|
||||
|
|
@ -1687,7 +1738,7 @@ func (g *genInst) getSymForMethodCall(se *ir.SelectorExpr, subst *typecheck.Tsub
|
|||
// also give the receiver type. For method expressions with embedded types, we
|
||||
// need to look at the type of the selection to get the final receiver type.
|
||||
recvType := deref(se.Selection.Type.Recv().Type)
|
||||
genRecvType := recvType.OrigSym().Def.Type()
|
||||
genRecvType := recvType.OrigType()
|
||||
nameNode := typecheck.Lookdot1(se, se.Sel, genRecvType, genRecvType.Methods(), 1).Nname.(*ir.Name)
|
||||
subtargs := recvType.RParams()
|
||||
s2targs := make([]*types.Type, len(subtargs))
|
||||
|
|
@ -1702,6 +1753,7 @@ func (g *genInst) getSymForMethodCall(se *ir.SelectorExpr, subst *typecheck.Tsub
|
|||
// dictionaries and method instantiations to be complete, so, to avoid recursive
|
||||
// dependencies, we finalize the itab lsyms only after all dictionaries syms and
|
||||
// instantiations have been created.
|
||||
// Also handles writing method expression closures into the dictionaries.
|
||||
func (g *genInst) finalizeSyms() {
|
||||
for _, d := range g.dictSymsToFinalize {
|
||||
infoPrint("=== Finalizing dictionary %s\n", d.sym.Name)
|
||||
|
|
@ -1750,6 +1802,31 @@ func (g *genInst) finalizeSyms() {
|
|||
}
|
||||
}
|
||||
|
||||
// Emit an entry for each method expression closure.
|
||||
// Each entry is a (captureless) closure pointing to the method on the instantiating type.
|
||||
// In other words, the entry is a runtime.funcval whose fn field is set to the method
|
||||
// in question, and has no other fields. The address of this dictionary entry can be
|
||||
// cast to a func of the appropriate type.
|
||||
// TODO: do these need to be done when finalizing, or can we do them earlier?
|
||||
for _, bf := range info.methodExprClosures {
|
||||
rcvr := d.targs[bf.idx]
|
||||
rcvr2 := deref(rcvr)
|
||||
found := false
|
||||
typecheck.CalcMethods(rcvr2) // Ensure methods on all instantiating types are computed.
|
||||
for _, f := range rcvr2.AllMethods().Slice() {
|
||||
if f.Sym.Name == bf.name {
|
||||
codePtr := ir.MethodSym(rcvr, f.Sym).Linksym()
|
||||
d.off = objw.SymPtr(lsym, d.off, codePtr, 0)
|
||||
infoPrint(" + MethodExprClosure for %v.%s\n", rcvr, bf.name)
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
base.Fatalf("method %s on %v not found", bf.name, rcvr)
|
||||
}
|
||||
}
|
||||
|
||||
objw.Global(lsym, int32(d.off), obj.DUPOK|obj.RODATA)
|
||||
infoPrint("=== Finalized dictionary %s\n", d.sym.Name)
|
||||
}
|
||||
|
|
@ -1806,7 +1883,7 @@ func hasShapeTypes(targs []*types.Type) bool {
|
|||
}
|
||||
|
||||
// getInstInfo get the dictionary format for a function instantiation- type params, derived
|
||||
// types, and needed subdictionaries and itabs.
|
||||
// types, and needed subdictionaries, itabs, and method expression closures.
|
||||
func (g *genInst) getInstInfo(st *ir.Func, shapes []*types.Type, instInfo *instInfo) {
|
||||
info := instInfo.dictInfo
|
||||
info.shapeParams = shapes
|
||||
|
|
@ -1902,10 +1979,22 @@ func (g *genInst) getInstInfo(st *ir.Func, shapes []*types.Type, instInfo *instI
|
|||
}
|
||||
case ir.OXDOT:
|
||||
se := n.(*ir.SelectorExpr)
|
||||
if se.X.Op() == ir.OTYPE && se.X.Type().IsShape() {
|
||||
// Method expression.
|
||||
addMethodExprClosure(info, se)
|
||||
break
|
||||
}
|
||||
if isBoundMethod(info, se) {
|
||||
if callMap[n] {
|
||||
// Method value called directly. Use method expression closure.
|
||||
addMethodExprClosure(info, se)
|
||||
break
|
||||
}
|
||||
// Method value not called directly. Still doing the old way.
|
||||
infoPrint(" Itab for bound call: %v\n", n)
|
||||
info.itabConvs = append(info.itabConvs, n)
|
||||
}
|
||||
|
||||
case ir.ODOTTYPE, ir.ODOTTYPE2:
|
||||
if !n.(*ir.TypeAssertExpr).Type().IsInterface() && !n.(*ir.TypeAssertExpr).X.Type().IsEmptyInterface() {
|
||||
infoPrint(" Itab for dot type: %v\n", n)
|
||||
|
|
@ -1955,7 +2044,8 @@ func (g *genInst) getInstInfo(st *ir.Func, shapes []*types.Type, instInfo *instI
|
|||
}
|
||||
info.startSubDict = len(info.shapeParams) + len(info.derivedTypes)
|
||||
info.startItabConv = len(info.shapeParams) + len(info.derivedTypes) + len(info.subDictCalls)
|
||||
info.dictLen = len(info.shapeParams) + len(info.derivedTypes) + len(info.subDictCalls) + len(info.itabConvs)
|
||||
info.startMethodExprClosures = len(info.shapeParams) + len(info.derivedTypes) + len(info.subDictCalls) + len(info.itabConvs)
|
||||
info.dictLen = len(info.shapeParams) + len(info.derivedTypes) + len(info.subDictCalls) + len(info.itabConvs) + len(info.methodExprClosures)
|
||||
}
|
||||
|
||||
// isBoundMethod returns true if the selection indicated by se is a bound method of
|
||||
|
|
@ -1967,6 +2057,46 @@ func isBoundMethod(info *dictInfo, se *ir.SelectorExpr) bool {
|
|||
return typecheck.Lookdot1(se, se.Sel, bound, bound.AllMethods(), 1) != nil
|
||||
}
|
||||
|
||||
func shapeIndex(info *dictInfo, t *types.Type) int {
|
||||
for i, s := range info.shapeParams {
|
||||
if s == t {
|
||||
return i
|
||||
}
|
||||
}
|
||||
base.Fatalf("can't find type %v in shape params", t)
|
||||
return -1
|
||||
}
|
||||
|
||||
// addMethodExprClosure adds the T.M method expression to the list of bound method expressions
|
||||
// used in the generic body.
|
||||
// isBoundMethod must have returned true on the same arguments.
|
||||
func addMethodExprClosure(info *dictInfo, se *ir.SelectorExpr) {
|
||||
idx := shapeIndex(info, se.X.Type())
|
||||
name := se.Sel.Name
|
||||
for _, b := range info.methodExprClosures {
|
||||
if idx == b.idx && name == b.name {
|
||||
return
|
||||
}
|
||||
}
|
||||
infoPrint(" Method expression closure for %v.%s\n", info.shapeParams[idx], name)
|
||||
info.methodExprClosures = append(info.methodExprClosures, methodExprClosure{idx: idx, name: name})
|
||||
}
|
||||
|
||||
// findMethodExprClosure finds the entry in the dictionary to use for the T.M
|
||||
// method expression encoded in se.
|
||||
// isBoundMethod must have returned true on the same arguments.
|
||||
func findMethodExprClosure(info *dictInfo, se *ir.SelectorExpr) int {
|
||||
idx := shapeIndex(info, se.X.Type())
|
||||
name := se.Sel.Name
|
||||
for i, b := range info.methodExprClosures {
|
||||
if idx == b.idx && name == b.name {
|
||||
return i
|
||||
}
|
||||
}
|
||||
base.Fatalf("can't find method expression closure for %s %s", se.X.Type(), name)
|
||||
return -1
|
||||
}
|
||||
|
||||
// addType adds t to info.derivedTypes if it is parameterized type (which is not
|
||||
// just a simple shape) that is different from any existing type on
|
||||
// info.derivedTypes.
|
||||
|
|
@ -2136,68 +2266,3 @@ func assertToBound(info *instInfo, dictVar *ir.Name, pos src.XPos, rcvr ir.Node,
|
|||
}
|
||||
return rcvr
|
||||
}
|
||||
|
||||
// buildClosure2 makes a closure to implement a method expression m (generic form x)
|
||||
// which has a shape type as receiver. If the receiver is exactly a shape (i.e. from
|
||||
// a typeparam), then the body of the closure converts m.X (the receiver) to the
|
||||
// interface bound type, and makes an interface call with the remaining arguments.
|
||||
//
|
||||
// The returned closure is fully substituted and has already had any needed
|
||||
// transformations done.
|
||||
func (g *genInst) buildClosure2(info *instInfo, m ir.Node) ir.Node {
|
||||
outer := info.fun
|
||||
pos := m.Pos()
|
||||
typ := m.Type() // type of the closure
|
||||
|
||||
fn, formalParams, formalResults := startClosure(pos, outer, typ)
|
||||
|
||||
// Capture dictionary calculated in the outer function
|
||||
dictVar := ir.CaptureName(pos, fn, info.dictParam)
|
||||
typed(types.Types[types.TUINTPTR], dictVar)
|
||||
|
||||
// Build arguments to call inside the closure.
|
||||
var args []ir.Node
|
||||
for i := 0; i < typ.NumParams(); i++ {
|
||||
args = append(args, formalParams[i].Nname.(*ir.Name))
|
||||
}
|
||||
|
||||
// Build call itself. This involves converting the first argument to the
|
||||
// bound type (an interface) using the dictionary, and then making an
|
||||
// interface call with the remaining arguments.
|
||||
var innerCall ir.Node
|
||||
rcvr := args[0]
|
||||
args = args[1:]
|
||||
assert(m.(*ir.SelectorExpr).X.Type().IsShape())
|
||||
dst := info.dictInfo.shapeToBound[m.(*ir.SelectorExpr).X.Type()]
|
||||
if m.(*ir.SelectorExpr).X.Type().IsInterface() {
|
||||
// If type arg is an interface (unusual case), we do a type assert to
|
||||
// the type bound.
|
||||
rcvr = assertToBound(info, dictVar, pos, rcvr, dst)
|
||||
} else {
|
||||
rcvr = convertUsingDictionary(info, dictVar, pos, rcvr, m, dst, false)
|
||||
}
|
||||
dot := ir.NewSelectorExpr(pos, ir.ODOTINTER, rcvr, m.(*ir.SelectorExpr).Sel)
|
||||
dot.Selection = typecheck.Lookdot1(dot, dot.Sel, dot.X.Type(), dot.X.Type().AllMethods(), 1)
|
||||
|
||||
typed(dot.Selection.Type, dot)
|
||||
innerCall = ir.NewCallExpr(pos, ir.OCALLINTER, dot, args)
|
||||
t := m.Type()
|
||||
if t.NumResults() == 0 {
|
||||
innerCall.SetTypecheck(1)
|
||||
} else if t.NumResults() == 1 {
|
||||
typed(t.Results().Field(0).Type, innerCall)
|
||||
} else {
|
||||
typed(t.Results(), innerCall)
|
||||
}
|
||||
if len(formalResults) > 0 {
|
||||
innerCall = ir.NewReturnStmt(pos, []ir.Node{innerCall})
|
||||
innerCall.SetTypecheck(1)
|
||||
}
|
||||
fn.Body = []ir.Node{innerCall}
|
||||
|
||||
// We're all done with the captured dictionary
|
||||
ir.FinishCaptureNames(pos, outer, fn)
|
||||
|
||||
// Do final checks on closure and return it.
|
||||
return ir.UseClosure(fn.OClosure, typecheck.Target)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -242,7 +242,7 @@ func transformCompare(n *ir.BinaryExpr) {
|
|||
aop, _ := typecheck.Assignop(rt, lt)
|
||||
if aop != ir.OXXX {
|
||||
types.CalcSize(rt)
|
||||
if rt.HasTParam() || rt.IsInterface() == lt.IsInterface() || rt.Size() >= 1<<16 {
|
||||
if rt.HasShape() || rt.IsInterface() == lt.IsInterface() || rt.Size() >= 1<<16 {
|
||||
r = ir.NewConvExpr(base.Pos, aop, lt, r)
|
||||
r.SetTypecheck(1)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -166,7 +166,7 @@ func (g *irgen) typ0(typ types2.Type) *types.Type {
|
|||
//fmt.Printf("Saw new type %v %v\n", instName, ntyp.HasTParam())
|
||||
|
||||
// Save the symbol for the base generic type.
|
||||
ntyp.SetOrigSym(g.pkg(typ.Obj().Pkg()).Lookup(typ.Obj().Name()))
|
||||
ntyp.SetOrigType(base.Type())
|
||||
ntyp.SetUnderlying(g.typ1(typ.Underlying()))
|
||||
if typ.NumMethods() != 0 {
|
||||
// Save a delayed call to g.fillinMethods() (once
|
||||
|
|
|
|||
|
|
@ -116,6 +116,28 @@ func unified(noders []*noder) {
|
|||
}
|
||||
}
|
||||
|
||||
readBodies(target)
|
||||
|
||||
// Check that nothing snuck past typechecking.
|
||||
for _, n := range target.Decls {
|
||||
if n.Typecheck() == 0 {
|
||||
base.FatalfAt(n.Pos(), "missed typecheck: %v", n)
|
||||
}
|
||||
|
||||
// For functions, check that at least their first statement (if
|
||||
// any) was typechecked too.
|
||||
if fn, ok := n.(*ir.Func); ok && len(fn.Body) != 0 {
|
||||
if stmt := fn.Body[0]; stmt.Typecheck() == 0 {
|
||||
base.FatalfAt(stmt.Pos(), "missed typecheck: %v", stmt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
base.ExitIfErrors() // just in case
|
||||
}
|
||||
|
||||
// readBodies reads in bodies for any
|
||||
func readBodies(target *ir.Package) {
|
||||
// Don't use range--bodyIdx can add closures to todoBodies.
|
||||
for len(todoBodies) > 0 {
|
||||
// The order we expand bodies doesn't matter, so pop from the end
|
||||
|
|
@ -134,24 +156,6 @@ func unified(noders []*noder) {
|
|||
}
|
||||
}
|
||||
todoBodies = nil
|
||||
todoBodiesDone = true
|
||||
|
||||
// Check that nothing snuck past typechecking.
|
||||
for _, n := range target.Decls {
|
||||
if n.Typecheck() == 0 {
|
||||
base.FatalfAt(n.Pos(), "missed typecheck: %v", n)
|
||||
}
|
||||
|
||||
// For functions, check that at least their first statement (if
|
||||
// any) was typechecked too.
|
||||
if fn, ok := n.(*ir.Func); ok && len(fn.Body) != 0 {
|
||||
if stmt := fn.Body[0]; stmt.Typecheck() == 0 {
|
||||
base.FatalfAt(stmt.Pos(), "missed typecheck: %v", stmt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
base.ExitIfErrors() // just in case
|
||||
}
|
||||
|
||||
// writePkgStub type checks the given parsed source files,
|
||||
|
|
|
|||
|
|
@ -103,6 +103,10 @@ type writerDict struct {
|
|||
// instantiated with derived types (i.e., that require
|
||||
// sub-dictionaries when called at run time).
|
||||
funcs []objInfo
|
||||
|
||||
// itabs lists itabs that are needed for dynamic type assertions
|
||||
// (including type switches).
|
||||
itabs []itabInfo
|
||||
}
|
||||
|
||||
type derivedInfo struct {
|
||||
|
|
@ -120,6 +124,11 @@ type objInfo struct {
|
|||
explicits []typeInfo // info for the type arguments
|
||||
}
|
||||
|
||||
type itabInfo struct {
|
||||
typIdx int // always a derived type index
|
||||
iface typeInfo // always a non-empty interface type
|
||||
}
|
||||
|
||||
func (info objInfo) anyDerived() bool {
|
||||
for _, explicit := range info.explicits {
|
||||
if explicit.derived {
|
||||
|
|
@ -284,10 +293,7 @@ func (pw *pkgWriter) typIdx(typ types2.Type, dict *writerDict) typeInfo {
|
|||
}
|
||||
|
||||
case *types2.Named:
|
||||
// Type aliases can refer to uninstantiated generic types, so we
|
||||
// might see len(TParams) != 0 && len(TArgs) == 0 here.
|
||||
// TODO(mdempsky): Revisit after #46477 is resolved.
|
||||
assert(typ.TypeParams().Len() == typ.TypeArgs().Len() || typ.TypeArgs().Len() == 0)
|
||||
assert(typ.TypeParams().Len() == typ.TypeArgs().Len())
|
||||
|
||||
// TODO(mdempsky): Why do we need to loop here?
|
||||
orig := typ
|
||||
|
|
@ -636,6 +642,13 @@ func (w *writer) objDict(obj types2.Object, dict *writerDict) {
|
|||
}
|
||||
}
|
||||
|
||||
nitabs := len(dict.itabs)
|
||||
w.Len(nitabs)
|
||||
for _, itab := range dict.itabs {
|
||||
w.Len(itab.typIdx)
|
||||
w.typInfo(itab.iface)
|
||||
}
|
||||
|
||||
assert(len(dict.derived) == nderived)
|
||||
assert(len(dict.funcs) == nfuncs)
|
||||
}
|
||||
|
|
@ -1076,7 +1089,12 @@ func (w *writer) switchStmt(stmt *syntax.SwitchStmt) {
|
|||
w.pos(stmt)
|
||||
w.stmt(stmt.Init)
|
||||
|
||||
var iface types2.Type
|
||||
if guard, ok := stmt.Tag.(*syntax.TypeSwitchGuard); w.Bool(ok) {
|
||||
tv, ok := w.p.info.Types[guard.X]
|
||||
assert(ok && tv.IsValue())
|
||||
iface = tv.Type
|
||||
|
||||
w.pos(guard)
|
||||
if tag := guard.Lhs; w.Bool(tag != nil) {
|
||||
w.pos(tag)
|
||||
|
|
@ -1095,7 +1113,16 @@ func (w *writer) switchStmt(stmt *syntax.SwitchStmt) {
|
|||
w.openScope(clause.Pos())
|
||||
|
||||
w.pos(clause)
|
||||
w.exprList(clause.Cases)
|
||||
|
||||
if iface != nil {
|
||||
cases := unpackListExpr(clause.Cases)
|
||||
w.Len(len(cases))
|
||||
for _, cas := range cases {
|
||||
w.exprType(iface, cas, true)
|
||||
}
|
||||
} else {
|
||||
w.exprList(clause.Cases)
|
||||
}
|
||||
|
||||
if obj, ok := w.p.info.Implicits[clause]; ok {
|
||||
// TODO(mdempsky): These pos details are quirkish, but also
|
||||
|
|
@ -1155,13 +1182,13 @@ func (w *writer) expr(expr syntax.Expr) {
|
|||
|
||||
if tv.IsType() {
|
||||
w.Code(exprType)
|
||||
w.typ(tv.Type)
|
||||
w.exprType(nil, expr, false)
|
||||
return
|
||||
}
|
||||
|
||||
if tv.Value != nil {
|
||||
w.Code(exprConst)
|
||||
w.pos(expr.Pos())
|
||||
w.pos(expr)
|
||||
w.typ(tv.Type)
|
||||
w.Value(tv.Value)
|
||||
|
||||
|
|
@ -1235,10 +1262,13 @@ func (w *writer) expr(expr syntax.Expr) {
|
|||
}
|
||||
|
||||
case *syntax.AssertExpr:
|
||||
tv, ok := w.p.info.Types[expr.X]
|
||||
assert(ok && tv.IsValue())
|
||||
|
||||
w.Code(exprAssert)
|
||||
w.expr(expr.X)
|
||||
w.pos(expr)
|
||||
w.expr(expr.Type)
|
||||
w.exprType(tv.Type, expr.Type, false)
|
||||
|
||||
case *syntax.Operation:
|
||||
if expr.Y == nil {
|
||||
|
|
@ -1373,6 +1403,55 @@ func (w *writer) exprs(exprs []syntax.Expr) {
|
|||
}
|
||||
}
|
||||
|
||||
func (w *writer) exprType(iface types2.Type, typ syntax.Expr, nilOK bool) {
|
||||
base.Assertf(iface == nil || isInterface(iface), "%v must be nil or an interface type", iface)
|
||||
|
||||
tv, ok := w.p.info.Types[typ]
|
||||
assert(ok)
|
||||
|
||||
w.Sync(pkgbits.SyncExprType)
|
||||
|
||||
if nilOK && w.Bool(tv.IsNil()) {
|
||||
return
|
||||
}
|
||||
|
||||
assert(tv.IsType())
|
||||
info := w.p.typIdx(tv.Type, w.dict)
|
||||
|
||||
w.pos(typ)
|
||||
|
||||
if w.Bool(info.derived && iface != nil && !iface.Underlying().(*types2.Interface).Empty()) {
|
||||
ifaceInfo := w.p.typIdx(iface, w.dict)
|
||||
|
||||
idx := -1
|
||||
for i, itab := range w.dict.itabs {
|
||||
if itab.typIdx == info.idx && itab.iface == ifaceInfo {
|
||||
idx = i
|
||||
}
|
||||
}
|
||||
if idx < 0 {
|
||||
idx = len(w.dict.itabs)
|
||||
w.dict.itabs = append(w.dict.itabs, itabInfo{typIdx: info.idx, iface: ifaceInfo})
|
||||
}
|
||||
w.Len(idx)
|
||||
return
|
||||
}
|
||||
|
||||
w.typInfo(info)
|
||||
}
|
||||
|
||||
func isInterface(typ types2.Type) bool {
|
||||
if _, ok := typ.(*types2.TypeParam); ok {
|
||||
// typ is a type parameter and may be instantiated as either a
|
||||
// concrete or interface type, so the writer can't depend on
|
||||
// knowing this.
|
||||
base.Fatalf("%v is a type parameter", typ)
|
||||
}
|
||||
|
||||
_, ok := typ.Underlying().(*types2.Interface)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (w *writer) op(op ir.Op) {
|
||||
// TODO(mdempsky): Remove in favor of explicit codes? Would make
|
||||
// export data more stable against internal refactorings, but low
|
||||
|
|
@ -1630,15 +1709,6 @@ func (w *writer) pkgDecl(decl syntax.Decl) {
|
|||
break
|
||||
}
|
||||
|
||||
// Skip aliases to uninstantiated generic types.
|
||||
// TODO(mdempsky): Revisit after #46477 is resolved.
|
||||
if name.IsAlias() {
|
||||
named, ok := name.Type().(*types2.Named)
|
||||
if ok && named.TypeParams().Len() != 0 && named.TypeArgs().Len() == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
w.Code(declOther)
|
||||
w.pkgObjs(decl.Name)
|
||||
|
||||
|
|
|
|||
|
|
@ -1223,10 +1223,17 @@ func writeType(t *types.Type) *obj.LSym {
|
|||
}
|
||||
}
|
||||
|
||||
ot = dextratypeData(lsym, ot, t)
|
||||
objw.Global(lsym, int32(ot), int16(obj.DUPOK|obj.RODATA))
|
||||
// Note: DUPOK is required to ensure that we don't end up with more
|
||||
// than one type descriptor for a given type.
|
||||
// than one type descriptor for a given type, if the type descriptor
|
||||
// can be defined in multiple packages, that is, unnamed types and
|
||||
// instantiated types.
|
||||
dupok := 0
|
||||
if tbase.Sym() == nil || tbase.IsFullyInstantiated() {
|
||||
dupok = obj.DUPOK
|
||||
}
|
||||
|
||||
ot = dextratypeData(lsym, ot, t)
|
||||
objw.Global(lsym, int32(ot), int16(dupok|obj.RODATA))
|
||||
|
||||
// The linker will leave a table of all the typelinks for
|
||||
// types in the binary, so the runtime can find them.
|
||||
|
|
@ -1846,16 +1853,17 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy
|
|||
|
||||
newnam := ir.MethodSym(rcvr, method.Sym)
|
||||
lsym := newnam.Linksym()
|
||||
if newnam.Siggen() {
|
||||
return lsym
|
||||
}
|
||||
newnam.SetSiggen(true)
|
||||
|
||||
// Unified IR creates its own wrappers.
|
||||
if base.Debug.Unified != 0 {
|
||||
return lsym
|
||||
}
|
||||
|
||||
if newnam.Siggen() {
|
||||
return lsym
|
||||
}
|
||||
newnam.SetSiggen(true)
|
||||
|
||||
methodrcvr := method.Type.Recv().Type
|
||||
// For generic methods, we need to generate the wrapper even if the receiver
|
||||
// types are identical, because we want to add the dictionary.
|
||||
|
|
@ -1946,7 +1954,7 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy
|
|||
|
||||
// Target method uses shaped names.
|
||||
targs2 := make([]*types.Type, len(targs))
|
||||
origRParams := deref(orig).OrigSym().Def.(*ir.Name).Type().RParams()
|
||||
origRParams := deref(orig).OrigType().RParams()
|
||||
for i, t := range targs {
|
||||
targs2[i] = typecheck.Shapify(t, i, origRParams[i])
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,4 +21,6 @@ func Init(arch *ssagen.ArchInfo) {
|
|||
arch.SSAMarkMoves = ssaMarkMoves
|
||||
arch.SSAGenValue = ssaGenValue
|
||||
arch.SSAGenBlock = ssaGenBlock
|
||||
arch.LoadRegResult = loadRegResult
|
||||
arch.SpillArgReg = spillArgReg
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ func zeroRange(pp *objw.Progs, p *obj.Prog, off, cnt int64, _ *uint32) *obj.Prog
|
|||
}
|
||||
|
||||
if cnt <= int64(128*types.PtrSize) {
|
||||
p = pp.Append(p, riscv.AADDI, obj.TYPE_CONST, 0, off, obj.TYPE_REG, riscv.REG_A0, 0)
|
||||
p = pp.Append(p, riscv.AADDI, obj.TYPE_CONST, 0, off, obj.TYPE_REG, riscv.REG_X25, 0)
|
||||
p.Reg = riscv.REG_SP
|
||||
p = pp.Append(p, obj.ADUFFZERO, obj.TYPE_NONE, 0, 0, obj.TYPE_MEM, 0, 0)
|
||||
p.To.Name = obj.NAME_EXTERN
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ package riscv64
|
|||
import (
|
||||
"cmd/compile/internal/base"
|
||||
"cmd/compile/internal/ir"
|
||||
"cmd/compile/internal/objw"
|
||||
"cmd/compile/internal/ssa"
|
||||
"cmd/compile/internal/ssagen"
|
||||
"cmd/compile/internal/types"
|
||||
|
|
@ -230,6 +231,19 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
|
|||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = v.Args[0].Reg()
|
||||
ssagen.AddrAuto(&p.To, v)
|
||||
case ssa.OpArgIntReg, ssa.OpArgFloatReg:
|
||||
// The assembler needs to wrap the entry safepoint/stack growth code with spill/unspill
|
||||
// The loop only runs once.
|
||||
for _, a := range v.Block.Func.RegArgs {
|
||||
// Pass the spill/unspill information along to the assembler, offset by size of
|
||||
// the saved LR slot.
|
||||
addr := ssagen.SpillSlotAddr(a, riscv.REG_SP, base.Ctxt.FixedFrameSize())
|
||||
s.FuncInfo().AddSpill(
|
||||
obj.RegSpill{Reg: a.Reg, Addr: addr, Unspill: loadByType(a.Type), Spill: storeByType(a.Type)})
|
||||
}
|
||||
v.Block.Func.RegArgs = nil
|
||||
|
||||
ssagen.CheckArgReg(v)
|
||||
case ssa.OpSP, ssa.OpSB, ssa.OpGetG:
|
||||
// nothing to do
|
||||
case ssa.OpRISCV64MOVBreg, ssa.OpRISCV64MOVHreg, ssa.OpRISCV64MOVWreg,
|
||||
|
|
@ -648,7 +662,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
|
|||
}
|
||||
|
||||
case ssa.OpRISCV64LoweredGetClosurePtr:
|
||||
// Closure pointer is S4 (riscv.REG_CTXT).
|
||||
// Closure pointer is S10 (riscv.REG_CTXT).
|
||||
ssagen.CheckLoweredGetClosurePtr(v)
|
||||
|
||||
case ssa.OpRISCV64LoweredGetCallerSP:
|
||||
|
|
@ -773,3 +787,22 @@ func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) {
|
|||
b.Fatalf("Unhandled block: %s", b.LongString())
|
||||
}
|
||||
}
|
||||
|
||||
func loadRegResult(s *ssagen.State, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog {
|
||||
p := s.Prog(loadByType(t))
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Name = obj.NAME_AUTO
|
||||
p.From.Sym = n.Linksym()
|
||||
p.From.Offset = n.FrameOffset() + off
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = reg
|
||||
return p
|
||||
}
|
||||
|
||||
func spillArgReg(pp *objw.Progs, p *obj.Prog, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog {
|
||||
p = pp.Append(p, storeByType(t), obj.TYPE_REG, reg, 0, obj.TYPE_MEM, 0, n.FrameOffset()+off)
|
||||
p.To.Name = obj.NAME_PARAM
|
||||
p.To.Sym = n.Linksym()
|
||||
p.Pos = p.Pos.WithNotStmt()
|
||||
return p
|
||||
}
|
||||
|
|
|
|||
|
|
@ -296,6 +296,8 @@ func NewConfig(arch string, types Types, ctxt *obj.Link, optimize, softfloat boo
|
|||
c.registers = registersRISCV64[:]
|
||||
c.gpRegMask = gpRegMaskRISCV64
|
||||
c.fpRegMask = fpRegMaskRISCV64
|
||||
// c.intParamRegs = paramIntRegRISCV64
|
||||
// c.floatParamRegs = paramFloatRegRISCV64
|
||||
c.FPReg = framepointerRegRISCV64
|
||||
c.hasGReg = true
|
||||
case "wasm":
|
||||
|
|
|
|||
|
|
@ -2073,7 +2073,7 @@
|
|||
(CMPXCHGLlock [off1+off2] {sym} ptr old new_ mem)
|
||||
|
||||
// We don't need the conditional move if we know the arg of BSF is not zero.
|
||||
(CMOVQEQ x _ (Select1 (BSFQ (ORQconst [c] _)))) && c != 0 => x
|
||||
(CMOVQEQ x _ (Select1 (BS(F|R)Q (ORQconst [c] _)))) && c != 0 => x
|
||||
// Extension is unnecessary for trailing zeros.
|
||||
(BSFQ (ORQconst <t> [1<<8] (MOVBQZX x))) => (BSFQ (ORQconst <t> [1<<8] x))
|
||||
(BSFQ (ORQconst <t> [1<<16] (MOVWQZX x))) => (BSFQ (ORQconst <t> [1<<16] x))
|
||||
|
|
|
|||
|
|
@ -1918,7 +1918,11 @@
|
|||
// (x & ac) >> sc
|
||||
(SRLconst [sc] (ANDconst [ac] x)) && isARM64BFMask(sc, ac, sc)
|
||||
=> (UBFX [armBFAuxInt(sc, arm64BFWidth(ac, sc))] x)
|
||||
|
||||
// merge ANDconst and ubfx into ubfx
|
||||
(ANDconst [c] (UBFX [bfc] x)) && isARM64BFMask(0, c, 0) =>
|
||||
(UBFX [armBFAuxInt(bfc.getARM64BFlsb(), min(bfc.getARM64BFwidth(), arm64BFWidth(c, 0)))] x)
|
||||
(UBFX [bfc] (ANDconst [c] x)) && isARM64BFMask(0, c, 0) && bfc.getARM64BFlsb() + bfc.getARM64BFwidth() <= arm64BFWidth(c, 0) =>
|
||||
(UBFX [bfc] x)
|
||||
// merge ubfx and zerso-extension into ubfx
|
||||
(MOVWUreg (UBFX [bfc] x)) && bfc.getARM64BFwidth() <= 32 => (UBFX [bfc] x)
|
||||
(MOVHUreg (UBFX [bfc] x)) && bfc.getARM64BFwidth() <= 16 => (UBFX [bfc] x)
|
||||
|
|
|
|||
|
|
@ -1479,7 +1479,11 @@
|
|||
&& clobber(call)
|
||||
=> (Move [sz] dst src mem)
|
||||
|
||||
// Prefetch instructions (aux is option: 0 - DCBT ; 8 - DCBT stream)
|
||||
// Prefetch instructions (TH specified using aux field)
|
||||
// For DCBT Ra,Rb,TH, A value of TH indicates:
|
||||
// 0, hint this cache line will be used soon. (PrefetchCache)
|
||||
// 16, hint this cache line will not be used for long. (PrefetchCacheStreamed)
|
||||
// See ISA 3.0 Book II 4.3.2 for more detail. https://openpower.foundation/specifications/isa/
|
||||
(PrefetchCache ptr mem) => (DCBT ptr mem [0])
|
||||
(PrefetchCacheStreamed ptr mem) => (DCBT ptr mem [8])
|
||||
(PrefetchCacheStreamed ptr mem) => (DCBT ptr mem [16])
|
||||
|
||||
|
|
|
|||
|
|
@ -82,7 +82,9 @@ var regNamesPPC64 = []string{
|
|||
"F28",
|
||||
"F29",
|
||||
"F30",
|
||||
"F31",
|
||||
// "F31", the allocator is limited to 64 entries. We sacrifice this FPR to support XER.
|
||||
|
||||
"XER",
|
||||
|
||||
// If you add registers, update asyncPreempt in runtime.
|
||||
|
||||
|
|
@ -124,7 +126,7 @@ func init() {
|
|||
|
||||
var (
|
||||
gp = buildReg("R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29")
|
||||
fp = buildReg("F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26")
|
||||
fp = buildReg("F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30")
|
||||
sp = buildReg("SP")
|
||||
sb = buildReg("SB")
|
||||
gr = buildReg("g")
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import (
|
|||
|
||||
const (
|
||||
riscv64REG_G = 27
|
||||
riscv64REG_CTXT = 20
|
||||
riscv64REG_CTXT = 26
|
||||
riscv64REG_LR = 1
|
||||
riscv64REG_SP = 2
|
||||
riscv64REG_GP = 3
|
||||
|
|
@ -115,7 +115,7 @@ func init() {
|
|||
panic("Too many RISCV64 registers")
|
||||
}
|
||||
|
||||
regCtxt := regNamed["X20"]
|
||||
regCtxt := regNamed["X26"]
|
||||
callerSave := gpMask | fpMask | regNamed["g"]
|
||||
|
||||
var (
|
||||
|
|
@ -241,13 +241,13 @@ func init() {
|
|||
{name: "MOVconvert", argLength: 2, reg: gp11, asm: "MOV"}, // arg0, but converted to int/ptr as appropriate; arg1=mem
|
||||
|
||||
// Calls
|
||||
{name: "CALLstatic", argLength: 1, reg: call, aux: "CallOff", call: true}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLtail", argLength: 1, reg: call, aux: "CallOff", call: true, tailCall: true}, // tail call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLclosure", argLength: 3, reg: callClosure, aux: "CallOff", call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
|
||||
{name: "CALLinter", argLength: 2, reg: callInter, aux: "CallOff", call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
|
||||
{name: "CALLstatic", argLength: -1, reg: call, aux: "CallOff", call: true}, // call static function aux.(*gc.Sym). last arg=mem, auxint=argsize, returns mem
|
||||
{name: "CALLtail", argLength: -1, reg: call, aux: "CallOff", call: true, tailCall: true}, // tail call static function aux.(*gc.Sym). last arg=mem, auxint=argsize, returns mem
|
||||
{name: "CALLclosure", argLength: -1, reg: callClosure, aux: "CallOff", call: true}, // call function via closure. arg0=codeptr, arg1=closure, last arg=mem, auxint=argsize, returns mem
|
||||
{name: "CALLinter", argLength: -1, reg: callInter, aux: "CallOff", call: true}, // call fn by pointer. arg0=codeptr, last arg=mem, auxint=argsize, returns mem
|
||||
|
||||
// duffzero
|
||||
// arg0 = address of memory to zero (in X10, changed as side effect)
|
||||
// arg0 = address of memory to zero (in X25, changed as side effect)
|
||||
// arg1 = mem
|
||||
// auxint = offset into duffzero code to start executing
|
||||
// X1 (link register) changed because of function call
|
||||
|
|
@ -257,16 +257,16 @@ func init() {
|
|||
aux: "Int64",
|
||||
argLength: 2,
|
||||
reg: regInfo{
|
||||
inputs: []regMask{regNamed["X10"]},
|
||||
clobbers: regNamed["X1"] | regNamed["X10"],
|
||||
inputs: []regMask{regNamed["X25"]},
|
||||
clobbers: regNamed["X1"] | regNamed["X25"],
|
||||
},
|
||||
typ: "Mem",
|
||||
faultOnNilArg0: true,
|
||||
},
|
||||
|
||||
// duffcopy
|
||||
// arg0 = address of dst memory (in X11, changed as side effect)
|
||||
// arg1 = address of src memory (in X10, changed as side effect)
|
||||
// arg0 = address of dst memory (in X25, changed as side effect)
|
||||
// arg1 = address of src memory (in X24, changed as side effect)
|
||||
// arg2 = mem
|
||||
// auxint = offset into duffcopy code to start executing
|
||||
// X1 (link register) changed because of function call
|
||||
|
|
@ -276,8 +276,8 @@ func init() {
|
|||
aux: "Int64",
|
||||
argLength: 3,
|
||||
reg: regInfo{
|
||||
inputs: []regMask{regNamed["X11"], regNamed["X10"]},
|
||||
clobbers: regNamed["X1"] | regNamed["X10"] | regNamed["X11"],
|
||||
inputs: []regMask{regNamed["X25"], regNamed["X24"]},
|
||||
clobbers: regNamed["X1"] | regNamed["X24"] | regNamed["X25"],
|
||||
},
|
||||
typ: "Mem",
|
||||
faultOnNilArg0: true,
|
||||
|
|
@ -477,5 +477,9 @@ func init() {
|
|||
gpregmask: gpMask,
|
||||
fpregmask: fpMask,
|
||||
framepointerreg: -1, // not used
|
||||
// Integer parameters passed in register X10-X17, X8-X9, X18-X23
|
||||
ParamIntRegNames: "X10 X11 X12 X13 X14 X15 X16 X17 X8 X9 X18 X19 X20 X21 X22 X23",
|
||||
// Float parameters passed in register F10-F17, F8-F9, F18-F23
|
||||
ParamFloatRegNames: "F10 F11 F12 F13 F14 F15 F16 F17 F8 F9 F18 F19 F20 F21 F22 F23",
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25088,11 +25088,11 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFADD,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{1, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
{1, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -25103,11 +25103,11 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFADDS,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{1, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
{1, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -25145,11 +25145,11 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFSUB,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{1, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
{1, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -25159,11 +25159,11 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFSUBS,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{1, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
{1, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -25322,11 +25322,11 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFMUL,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{1, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
{1, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -25337,11 +25337,11 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFMULS,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{1, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
{1, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -25351,12 +25351,12 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFMADD,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{1, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{2, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
{1, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
{2, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -25366,12 +25366,12 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFMADDS,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{1, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{2, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
{1, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
{2, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -25381,12 +25381,12 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFMSUB,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{1, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{2, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
{1, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
{2, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -25396,12 +25396,12 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFMSUBS,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{1, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{2, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
{1, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
{2, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -25845,11 +25845,11 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFDIV,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{1, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
{1, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -25859,11 +25859,11 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFDIVS,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{1, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
{1, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -25985,10 +25985,10 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFCTIDZ,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -25998,10 +25998,10 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFCTIWZ,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -26011,10 +26011,10 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFCFID,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -26024,10 +26024,10 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFCFIDS,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -26037,10 +26037,10 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFRSP,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -26050,7 +26050,7 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AMFVSRD,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
|
||||
|
|
@ -26066,7 +26066,7 @@ var opcodeTable = [...]opInfo{
|
|||
{0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -26228,10 +26228,10 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFNEG,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -26241,10 +26241,10 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFSQRT,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -26254,10 +26254,10 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFSQRTS,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -26267,10 +26267,10 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFRIM,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -26280,10 +26280,10 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFRIP,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -26293,10 +26293,10 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFRIZ,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -26306,10 +26306,10 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFRIN,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -26319,10 +26319,10 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFABS,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -26332,10 +26332,10 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFNABS,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -26345,11 +26345,11 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFCPSGN,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{1, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
{1, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -26765,7 +26765,7 @@ var opcodeTable = [...]opInfo{
|
|||
{1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -26779,7 +26779,7 @@ var opcodeTable = [...]opInfo{
|
|||
{1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -26849,7 +26849,7 @@ var opcodeTable = [...]opInfo{
|
|||
{0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -26865,7 +26865,7 @@ var opcodeTable = [...]opInfo{
|
|||
{0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -26934,8 +26934,8 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFMOVD,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{1, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
|
||||
{0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
|
||||
{1, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -26948,8 +26948,8 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFMOVS,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{1, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
|
||||
{0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
|
||||
{1, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -27007,9 +27007,9 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFMOVD,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{2, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
|
||||
{1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
|
||||
{0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
|
||||
{1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
|
||||
{2, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -27019,9 +27019,9 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFMOVS,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{2, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
|
||||
{1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
|
||||
{0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
|
||||
{1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
|
||||
{2, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -27149,7 +27149,7 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFMOVD,
|
||||
reg: regInfo{
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -27161,7 +27161,7 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFMOVS,
|
||||
reg: regInfo{
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -27171,8 +27171,8 @@ var opcodeTable = [...]opInfo{
|
|||
asm: ppc64.AFCMPU,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{1, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
{1, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -27433,10 +27433,10 @@ var opcodeTable = [...]opInfo{
|
|||
zeroWidth: true,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -27447,10 +27447,10 @@ var opcodeTable = [...]opInfo{
|
|||
zeroWidth: true,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
{0, 9223372032559808512}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -27461,7 +27461,7 @@ var opcodeTable = [...]opInfo{
|
|||
clobberFlags: true,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
clobbers: 576460745860964344, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29 g F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
clobbers: 9223372034707283960, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29 g F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -27472,7 +27472,7 @@ var opcodeTable = [...]opInfo{
|
|||
call: true,
|
||||
tailCall: true,
|
||||
reg: regInfo{
|
||||
clobbers: 576460745860964344, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29 g F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
clobbers: 9223372034707283960, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29 g F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -27486,7 +27486,7 @@ var opcodeTable = [...]opInfo{
|
|||
{0, 4096}, // R12
|
||||
{1, 2048}, // R11
|
||||
},
|
||||
clobbers: 576460745860964344, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29 g F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
clobbers: 9223372034707283960, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29 g F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -27499,7 +27499,7 @@ var opcodeTable = [...]opInfo{
|
|||
inputs: []inputInfo{
|
||||
{0, 4096}, // R12
|
||||
},
|
||||
clobbers: 576460745860964344, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29 g F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
clobbers: 9223372034707283960, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29 g F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -27882,7 +27882,7 @@ var opcodeTable = [...]opInfo{
|
|||
{0, 1048576}, // R20
|
||||
{1, 2097152}, // R21
|
||||
},
|
||||
clobbers: 576460746931312640, // R11 R12 R18 R19 R22 R23 R24 R25 R26 R27 R28 R29 R31 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
clobbers: 9223372035777632256, // R11 R12 R18 R19 R22 R23 R24 R25 R26 R27 R28 R29 R31 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -28875,7 +28875,7 @@ var opcodeTable = [...]opInfo{
|
|||
{
|
||||
name: "CALLstatic",
|
||||
auxType: auxCallOff,
|
||||
argLen: 1,
|
||||
argLen: -1,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
clobbers: 9223372035781033968, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
|
||||
|
|
@ -28884,7 +28884,7 @@ var opcodeTable = [...]opInfo{
|
|||
{
|
||||
name: "CALLtail",
|
||||
auxType: auxCallOff,
|
||||
argLen: 1,
|
||||
argLen: -1,
|
||||
call: true,
|
||||
tailCall: true,
|
||||
reg: regInfo{
|
||||
|
|
@ -28894,11 +28894,11 @@ var opcodeTable = [...]opInfo{
|
|||
{
|
||||
name: "CALLclosure",
|
||||
auxType: auxCallOff,
|
||||
argLen: 3,
|
||||
argLen: -1,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{1, 524288}, // X20
|
||||
{1, 33554432}, // X26
|
||||
{0, 1006632946}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
|
||||
},
|
||||
clobbers: 9223372035781033968, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
|
||||
|
|
@ -28907,7 +28907,7 @@ var opcodeTable = [...]opInfo{
|
|||
{
|
||||
name: "CALLinter",
|
||||
auxType: auxCallOff,
|
||||
argLen: 2,
|
||||
argLen: -1,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
|
|
@ -28923,9 +28923,9 @@ var opcodeTable = [...]opInfo{
|
|||
faultOnNilArg0: true,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 512}, // X10
|
||||
{0, 16777216}, // X25
|
||||
},
|
||||
clobbers: 512, // X10
|
||||
clobbers: 16777216, // X25
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -28936,10 +28936,10 @@ var opcodeTable = [...]opInfo{
|
|||
faultOnNilArg1: true,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 1024}, // X11
|
||||
{1, 512}, // X10
|
||||
{0, 16777216}, // X25
|
||||
{1, 8388608}, // X24
|
||||
},
|
||||
clobbers: 1536, // X10 X11
|
||||
clobbers: 25165824, // X24 X25
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -29189,7 +29189,7 @@ var opcodeTable = [...]opInfo{
|
|||
argLen: 0,
|
||||
reg: regInfo{
|
||||
outputs: []outputInfo{
|
||||
{0, 524288}, // X20
|
||||
{0, 33554432}, // X26
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -37281,12 +37281,12 @@ var registersPPC64 = [...]Register{
|
|||
{60, ppc64.REG_F28, -1, "F28"},
|
||||
{61, ppc64.REG_F29, -1, "F29"},
|
||||
{62, ppc64.REG_F30, -1, "F30"},
|
||||
{63, ppc64.REG_F31, -1, "F31"},
|
||||
{63, ppc64.REG_XER, -1, "XER"},
|
||||
}
|
||||
var paramIntRegPPC64 = []int8{3, 4, 5, 6, 7, 8, 9, 10, 14, 15, 16, 17}
|
||||
var paramFloatRegPPC64 = []int8{33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44}
|
||||
var gpRegMaskPPC64 = regMask(1073733624)
|
||||
var fpRegMaskPPC64 = regMask(576460743713488896)
|
||||
var fpRegMaskPPC64 = regMask(9223372032559808512)
|
||||
var specialRegMaskPPC64 = regMask(0)
|
||||
var framepointerRegPPC64 = int8(-1)
|
||||
var linkRegPPC64 = int8(-1)
|
||||
|
|
@ -37356,8 +37356,8 @@ var registersRISCV64 = [...]Register{
|
|||
{62, riscv.REG_F31, -1, "F31"},
|
||||
{63, 0, -1, "SB"},
|
||||
}
|
||||
var paramIntRegRISCV64 = []int8(nil)
|
||||
var paramFloatRegRISCV64 = []int8(nil)
|
||||
var paramIntRegRISCV64 = []int8{9, 10, 11, 12, 13, 14, 15, 16, 7, 8, 17, 18, 19, 20, 21, 22}
|
||||
var paramFloatRegRISCV64 = []int8{41, 42, 43, 44, 45, 46, 47, 48, 39, 40, 49, 50, 51, 52, 53, 54}
|
||||
var gpRegMaskRISCV64 = regMask(1006632944)
|
||||
var fpRegMaskRISCV64 = regMask(9223372034707292160)
|
||||
var specialRegMaskRISCV64 = regMask(0)
|
||||
|
|
|
|||
|
|
@ -824,6 +824,9 @@ func prove(f *Func) {
|
|||
}
|
||||
lensVars[b] = append(lensVars[b], v)
|
||||
}
|
||||
case OpCtz64, OpCtz32, OpCtz16, OpCtz8, OpBitLen64, OpBitLen32, OpBitLen16, OpBitLen8:
|
||||
ft.update(b, v, ft.zero, signed, gt|eq)
|
||||
// TODO: we could also do <= 64/32/16/8, if that helped.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1372,7 +1375,9 @@ func isNonNegative(v *Value) bool {
|
|||
case OpStringLen, OpSliceLen, OpSliceCap,
|
||||
OpZeroExt8to64, OpZeroExt16to64, OpZeroExt32to64,
|
||||
OpZeroExt8to32, OpZeroExt16to32, OpZeroExt8to16,
|
||||
OpCtz64, OpCtz32, OpCtz16, OpCtz8:
|
||||
OpCtz64, OpCtz32, OpCtz16, OpCtz8,
|
||||
OpCtz64NonZero, OpCtz32NonZero, OpCtz16NonZero, OpCtz8NonZero,
|
||||
OpBitLen64, OpBitLen32, OpBitLen16, OpBitLen8:
|
||||
return true
|
||||
|
||||
case OpRsh64Ux64, OpRsh32Ux64:
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ func applyRewrite(f *Func, rb blockRewriter, rv valueRewriter, deadcode deadValu
|
|||
var states map[string]bool
|
||||
for {
|
||||
change := false
|
||||
deadChange := false
|
||||
for _, b := range f.Blocks {
|
||||
var b0 *Block
|
||||
if debug > 1 {
|
||||
|
|
@ -73,7 +74,7 @@ func applyRewrite(f *Func, rb blockRewriter, rv valueRewriter, deadcode deadValu
|
|||
// Not quite a deadcode pass, because it does not handle cycles.
|
||||
// But it should help Uses==1 rules to fire.
|
||||
v.reset(OpInvalid)
|
||||
change = true
|
||||
deadChange = true
|
||||
}
|
||||
// No point rewriting values which aren't used.
|
||||
continue
|
||||
|
|
@ -145,15 +146,16 @@ func applyRewrite(f *Func, rb blockRewriter, rv valueRewriter, deadcode deadValu
|
|||
}
|
||||
}
|
||||
}
|
||||
if !change {
|
||||
if !change && !deadChange {
|
||||
break
|
||||
}
|
||||
iters++
|
||||
if iters > 1000 || debug >= 2 {
|
||||
if (iters > 1000 || debug >= 2) && change {
|
||||
// We've done a suspiciously large number of rewrites (or we're in debug mode).
|
||||
// As of Sep 2021, 90% of rewrites complete in 4 iterations or fewer
|
||||
// and the maximum value encountered during make.bash is 12.
|
||||
// Start checking for cycles. (This is too expensive to do routinely.)
|
||||
// Note: we avoid this path for deadChange-only iterations, to fix #51639.
|
||||
if states == nil {
|
||||
states = make(map[string]bool)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5191,6 +5191,29 @@ func rewriteValueAMD64_OpAMD64CMOVQEQ(v *Value) bool {
|
|||
v.copyOf(x)
|
||||
return true
|
||||
}
|
||||
// match: (CMOVQEQ x _ (Select1 (BSRQ (ORQconst [c] _))))
|
||||
// cond: c != 0
|
||||
// result: x
|
||||
for {
|
||||
x := v_0
|
||||
if v_2.Op != OpSelect1 {
|
||||
break
|
||||
}
|
||||
v_2_0 := v_2.Args[0]
|
||||
if v_2_0.Op != OpAMD64BSRQ {
|
||||
break
|
||||
}
|
||||
v_2_0_0 := v_2_0.Args[0]
|
||||
if v_2_0_0.Op != OpAMD64ORQconst {
|
||||
break
|
||||
}
|
||||
c := auxIntToInt32(v_2_0_0.AuxInt)
|
||||
if !(c != 0) {
|
||||
break
|
||||
}
|
||||
v.copyOf(x)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValueAMD64_OpAMD64CMOVQGE(v *Value) bool {
|
||||
|
|
|
|||
|
|
@ -2283,6 +2283,24 @@ func rewriteValueARM64_OpARM64ANDconst(v *Value) bool {
|
|||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (ANDconst [c] (UBFX [bfc] x))
|
||||
// cond: isARM64BFMask(0, c, 0)
|
||||
// result: (UBFX [armBFAuxInt(bfc.getARM64BFlsb(), min(bfc.getARM64BFwidth(), arm64BFWidth(c, 0)))] x)
|
||||
for {
|
||||
c := auxIntToInt64(v.AuxInt)
|
||||
if v_0.Op != OpARM64UBFX {
|
||||
break
|
||||
}
|
||||
bfc := auxIntToArm64BitField(v_0.AuxInt)
|
||||
x := v_0.Args[0]
|
||||
if !(isARM64BFMask(0, c, 0)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64UBFX)
|
||||
v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(bfc.getARM64BFlsb(), min(bfc.getARM64BFwidth(), arm64BFWidth(c, 0))))
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValueARM64_OpARM64ANDshiftLL(v *Value) bool {
|
||||
|
|
@ -21802,6 +21820,24 @@ func rewriteValueARM64_OpARM64UBFIZ(v *Value) bool {
|
|||
}
|
||||
func rewriteValueARM64_OpARM64UBFX(v *Value) bool {
|
||||
v_0 := v.Args[0]
|
||||
// match: (UBFX [bfc] (ANDconst [c] x))
|
||||
// cond: isARM64BFMask(0, c, 0) && bfc.getARM64BFlsb() + bfc.getARM64BFwidth() <= arm64BFWidth(c, 0)
|
||||
// result: (UBFX [bfc] x)
|
||||
for {
|
||||
bfc := auxIntToArm64BitField(v.AuxInt)
|
||||
if v_0.Op != OpARM64ANDconst {
|
||||
break
|
||||
}
|
||||
c := auxIntToInt64(v_0.AuxInt)
|
||||
x := v_0.Args[0]
|
||||
if !(isARM64BFMask(0, c, 0) && bfc.getARM64BFlsb()+bfc.getARM64BFwidth() <= arm64BFWidth(c, 0)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64UBFX)
|
||||
v.AuxInt = arm64BitFieldToAuxInt(bfc)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (UBFX [bfc] (SRLconst [sc] x))
|
||||
// cond: sc+bfc.getARM64BFwidth()+bfc.getARM64BFlsb() < 64
|
||||
// result: (UBFX [armBFAuxInt(bfc.getARM64BFlsb()+sc, bfc.getARM64BFwidth())] x)
|
||||
|
|
|
|||
|
|
@ -14140,12 +14140,12 @@ func rewriteValuePPC64_OpPrefetchCacheStreamed(v *Value) bool {
|
|||
v_1 := v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
// match: (PrefetchCacheStreamed ptr mem)
|
||||
// result: (DCBT ptr mem [8])
|
||||
// result: (DCBT ptr mem [16])
|
||||
for {
|
||||
ptr := v_0
|
||||
mem := v_1
|
||||
v.reset(OpPPC64DCBT)
|
||||
v.AuxInt = int64ToAuxInt(8)
|
||||
v.AuxInt = int64ToAuxInt(16)
|
||||
v.AddArg2(ptr, mem)
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -224,11 +224,6 @@ func AbiForBodylessFuncStackMap(fn *ir.Func) *abi.ABIConfig {
|
|||
return ssaConfig.ABI0.Copy() // No idea what races will result, be safe
|
||||
}
|
||||
|
||||
// These are disabled but remain ready for use in case they are needed for the next regabi port.
|
||||
// TODO if they are not needed for 1.18 / next register abi port, delete them.
|
||||
const magicNameDotSuffix = ".*disabled*MagicMethodNameForTestingRegisterABI"
|
||||
const magicLastTypeName = "*disabled*MagicLastTypeNameForTestingRegisterABI"
|
||||
|
||||
// abiForFunc implements ABI policy for a function, but does not return a copy of the ABI.
|
||||
// Passing a nil function returns the default ABI based on experiment configuration.
|
||||
func abiForFunc(fn *ir.Func, abi0, abi1 *abi.ABIConfig) *abi.ABIConfig {
|
||||
|
|
@ -251,36 +246,13 @@ func abiForFunc(fn *ir.Func, abi0, abi1 *abi.ABIConfig) *abi.ABIConfig {
|
|||
|
||||
a := abi0
|
||||
if fn != nil {
|
||||
name := ir.FuncName(fn)
|
||||
magicName := strings.HasSuffix(name, magicNameDotSuffix)
|
||||
if fn.Pragma&ir.RegisterParams != 0 { // TODO(register args) remove after register abi is working
|
||||
if strings.Contains(name, ".") {
|
||||
if !magicName {
|
||||
base.ErrorfAt(fn.Pos(), "Calls to //go:registerparams method %s won't work, remove the pragma from the declaration.", name)
|
||||
}
|
||||
}
|
||||
a = abi1
|
||||
} else if magicName {
|
||||
if base.FmtPos(fn.Pos()) == "<autogenerated>:1" {
|
||||
// no way to put a pragma here, and it will error out in the real source code if they did not do it there.
|
||||
a = abi1
|
||||
} else {
|
||||
base.ErrorfAt(fn.Pos(), "Methods with magic name %s (method %s) must also specify //go:registerparams", magicNameDotSuffix[1:], name)
|
||||
}
|
||||
}
|
||||
if regAbiForFuncType(fn.Type().FuncType()) {
|
||||
// fmt.Printf("Saw magic last type name for function %s\n", name)
|
||||
a = abi1
|
||||
}
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
func regAbiForFuncType(ft *types.Func) bool {
|
||||
np := ft.Params.NumFields()
|
||||
return np > 0 && strings.Contains(ft.Params.FieldType(np-1).String(), magicLastTypeName)
|
||||
}
|
||||
|
||||
// dvarint writes a varint v to the funcdata in symbol x and returns the new offset
|
||||
func dvarint(x *obj.LSym, off int, v int64) int {
|
||||
if v < 0 || v > 1e9 {
|
||||
|
|
@ -4950,24 +4922,6 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val
|
|||
|
||||
callABI := s.f.ABIDefault
|
||||
|
||||
if !buildcfg.Experiment.RegabiArgs {
|
||||
var magicFnNameSym *types.Sym
|
||||
if fn.Name() != nil {
|
||||
magicFnNameSym = fn.Name().Sym()
|
||||
ss := magicFnNameSym.Name
|
||||
if strings.HasSuffix(ss, magicNameDotSuffix) {
|
||||
callABI = s.f.ABI1
|
||||
}
|
||||
}
|
||||
if magicFnNameSym == nil && n.Op() == ir.OCALLINTER {
|
||||
magicFnNameSym = fn.(*ir.SelectorExpr).Sym()
|
||||
ss := magicFnNameSym.Name
|
||||
if strings.HasSuffix(ss, magicNameDotSuffix[1:]) {
|
||||
callABI = s.f.ABI1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if k != callNormal && k != callTail && (len(n.Args) != 0 || n.Op() == ir.OCALLINTER || n.X.Type().NumResults() != 0) {
|
||||
s.Fatalf("go/defer call with arguments: %v", n)
|
||||
}
|
||||
|
|
@ -5016,13 +4970,6 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val
|
|||
}
|
||||
}
|
||||
|
||||
if !buildcfg.Experiment.RegabiArgs {
|
||||
if regAbiForFuncType(n.X.Type().FuncType()) {
|
||||
// Magic last type in input args to call
|
||||
callABI = s.f.ABI1
|
||||
}
|
||||
}
|
||||
|
||||
params := callABI.ABIAnalyze(n.X.Type(), false /* Do not set (register) nNames from caller side -- can cause races. */)
|
||||
types.CalcSize(fn.Type())
|
||||
stksize := params.ArgWidth() // includes receiver, args, and results
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import (
|
|||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"internal/testenv"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
|
|
@ -74,11 +75,14 @@ func TestStdLib(t *testing.T) {
|
|||
lines uint
|
||||
}
|
||||
|
||||
goroot := testenv.GOROOT(t)
|
||||
|
||||
results := make(chan parseResult)
|
||||
go func() {
|
||||
defer close(results)
|
||||
for _, dir := range []string{
|
||||
runtime.GOROOT(),
|
||||
filepath.Join(goroot, "src"),
|
||||
filepath.Join(goroot, "misc"),
|
||||
} {
|
||||
walkDirs(t, dir, func(filename string) {
|
||||
if skipRx != nil && skipRx.MatchString(filename) {
|
||||
|
|
|
|||
|
|
@ -39,8 +39,8 @@ type scanner struct {
|
|||
lit string // valid if tok is _Name, _Literal, or _Semi ("semicolon", "newline", or "EOF"); may be malformed if bad is true
|
||||
bad bool // valid if tok is _Literal, true if a syntax error occurred, lit may be malformed
|
||||
kind LitKind // valid if tok is _Literal
|
||||
op Operator // valid if tok is _Operator, _AssignOp, or _IncOp
|
||||
prec int // valid if tok is _Operator, _AssignOp, or _IncOp
|
||||
op Operator // valid if tok is _Operator, _Star, _AssignOp, or _IncOp
|
||||
prec int // valid if tok is _Operator, _Star, _AssignOp, or _IncOp
|
||||
}
|
||||
|
||||
func (s *scanner) init(src io.Reader, errh func(line, col uint, msg string), mode uint) {
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ func TestIssue16214(t *testing.T) {
|
|||
t.Fatalf("could not write file: %v", err)
|
||||
}
|
||||
|
||||
cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-S", "-o", filepath.Join(dir, "out.o"), src)
|
||||
cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-p=main", "-S", "-o", filepath.Join(dir, "out.o"), src)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("go tool compile: %v\n%s", err, out)
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ func TestInvalidLang(t *testing.T) {
|
|||
}
|
||||
|
||||
func testLang(t *testing.T, lang, src, outfile string) error {
|
||||
run := []string{testenv.GoToolPath(t), "tool", "compile", "-lang", lang, "-o", outfile, src}
|
||||
run := []string{testenv.GoToolPath(t), "tool", "compile", "-p=p", "-lang", lang, "-o", outfile, src}
|
||||
t.Log(run)
|
||||
out, err := exec.Command(run[0], run[1:]...).CombinedOutput()
|
||||
t.Logf("%s", out)
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ func TestReproducibleBuilds(t *testing.T) {
|
|||
for i := 0; i < iters; i++ {
|
||||
// Note: use -c 2 to expose any nondeterminism which is the result
|
||||
// of the runtime scheduler.
|
||||
out, err := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-c", "2", "-o", tmp.Name(), filepath.Join("testdata", "reproducible", test)).CombinedOutput()
|
||||
out, err := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-p=p", "-c", "2", "-o", tmp.Name(), filepath.Join("testdata", "reproducible", test)).CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to compile: %v\n%s", err, out)
|
||||
}
|
||||
|
|
@ -89,7 +89,7 @@ func TestIssue38068(t *testing.T) {
|
|||
s := &scenarios[i]
|
||||
s.libpath = filepath.Join(tmpdir, s.tag+".a")
|
||||
// Note: use of "-p" required in order for DWARF to be generated.
|
||||
cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-trimpath", "-p=issue38068", "-buildid=", s.args, "-o", s.libpath, src)
|
||||
cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-p=issue38068", "-buildid=", s.args, "-o", s.libpath, src)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("%v: %v:\n%s", cmd.Args, err, out)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ import (
|
|||
"cmd/compile/internal/base"
|
||||
"cmd/compile/internal/ir"
|
||||
"cmd/compile/internal/types"
|
||||
"cmd/internal/src"
|
||||
)
|
||||
|
||||
func roundFloat(v constant.Value, sz int64) constant.Value {
|
||||
|
|
@ -99,10 +98,7 @@ func convlit1(n ir.Node, t *types.Type, explicit bool, context func() string) ir
|
|||
}
|
||||
n = ir.Copy(n)
|
||||
if t == nil {
|
||||
base.Errorf("use of untyped nil")
|
||||
n.SetDiag(true)
|
||||
n.SetType(nil)
|
||||
return n
|
||||
base.Fatalf("use of untyped nil")
|
||||
}
|
||||
|
||||
if !t.HasNil() {
|
||||
|
|
@ -199,18 +195,14 @@ func convlit1(n ir.Node, t *types.Type, explicit bool, context func() string) ir
|
|||
return n
|
||||
}
|
||||
|
||||
if !n.Diag() {
|
||||
if !t.Broke() {
|
||||
if explicit {
|
||||
base.Errorf("cannot convert %L to type %v", n, t)
|
||||
} else if context != nil {
|
||||
base.Errorf("cannot use %L as type %v in %s", n, t, context())
|
||||
} else {
|
||||
base.Errorf("cannot use %L as type %v", n, t)
|
||||
}
|
||||
}
|
||||
n.SetDiag(true)
|
||||
if explicit {
|
||||
base.Fatalf("cannot convert %L to type %v", n, t)
|
||||
} else if context != nil {
|
||||
base.Fatalf("cannot use %L as type %v in %s", n, t, context())
|
||||
} else {
|
||||
base.Fatalf("cannot use %L as type %v", n, t)
|
||||
}
|
||||
|
||||
n.SetType(nil)
|
||||
return n
|
||||
}
|
||||
|
|
@ -773,94 +765,6 @@ func anyCallOrChan(n ir.Node) bool {
|
|||
})
|
||||
}
|
||||
|
||||
// A constSet represents a set of Go constant expressions.
|
||||
type constSet struct {
|
||||
m map[constSetKey]src.XPos
|
||||
}
|
||||
|
||||
type constSetKey struct {
|
||||
typ *types.Type
|
||||
val interface{}
|
||||
}
|
||||
|
||||
// add adds constant expression n to s. If a constant expression of
|
||||
// equal value and identical type has already been added, then add
|
||||
// reports an error about the duplicate value.
|
||||
//
|
||||
// pos provides position information for where expression n occurred
|
||||
// (in case n does not have its own position information). what and
|
||||
// where are used in the error message.
|
||||
//
|
||||
// n must not be an untyped constant.
|
||||
func (s *constSet) add(pos src.XPos, n ir.Node, what, where string) {
|
||||
if conv := n; conv.Op() == ir.OCONVIFACE {
|
||||
conv := conv.(*ir.ConvExpr)
|
||||
if conv.Implicit() {
|
||||
n = conv.X
|
||||
}
|
||||
}
|
||||
|
||||
if !ir.IsConstNode(n) || n.Type() == nil {
|
||||
return
|
||||
}
|
||||
if n.Type().IsUntyped() {
|
||||
base.Fatalf("%v is untyped", n)
|
||||
}
|
||||
|
||||
// Consts are only duplicates if they have the same value and
|
||||
// identical types.
|
||||
//
|
||||
// In general, we have to use types.Identical to test type
|
||||
// identity, because == gives false negatives for anonymous
|
||||
// types and the byte/uint8 and rune/int32 builtin type
|
||||
// aliases. However, this is not a problem here, because
|
||||
// constant expressions are always untyped or have a named
|
||||
// type, and we explicitly handle the builtin type aliases
|
||||
// below.
|
||||
//
|
||||
// This approach may need to be revisited though if we fix
|
||||
// #21866 by treating all type aliases like byte/uint8 and
|
||||
// rune/int32.
|
||||
|
||||
typ := n.Type()
|
||||
switch typ {
|
||||
case types.ByteType:
|
||||
typ = types.Types[types.TUINT8]
|
||||
case types.RuneType:
|
||||
typ = types.Types[types.TINT32]
|
||||
}
|
||||
k := constSetKey{typ, ir.ConstValue(n)}
|
||||
|
||||
if ir.HasUniquePos(n) {
|
||||
pos = n.Pos()
|
||||
}
|
||||
|
||||
if s.m == nil {
|
||||
s.m = make(map[constSetKey]src.XPos)
|
||||
}
|
||||
|
||||
if prevPos, isDup := s.m[k]; isDup {
|
||||
base.ErrorfAt(pos, "duplicate %s %s in %s\n\tprevious %s at %v",
|
||||
what, nodeAndVal(n), where,
|
||||
what, base.FmtPos(prevPos))
|
||||
} else {
|
||||
s.m[k] = pos
|
||||
}
|
||||
}
|
||||
|
||||
// nodeAndVal reports both an expression and its constant value, if
|
||||
// the latter is non-obvious.
|
||||
//
|
||||
// TODO(mdempsky): This could probably be a fmt.go flag.
|
||||
func nodeAndVal(n ir.Node) string {
|
||||
show := fmt.Sprint(n)
|
||||
val := ir.ConstValue(n)
|
||||
if s := fmt.Sprintf("%#v", val); show != s {
|
||||
show += " (value " + s + ")"
|
||||
}
|
||||
return show
|
||||
}
|
||||
|
||||
// evalunsafe evaluates a package unsafe operation and returns the result.
|
||||
func evalunsafe(n ir.Node) int64 {
|
||||
switch n.Op() {
|
||||
|
|
|
|||
|
|
@ -66,9 +66,9 @@ func (p *crawler) markObject(n *ir.Name) {
|
|||
// inline bodies may be needed. For instantiated generic types, it visits the base
|
||||
// generic type, which has the relevant methods.
|
||||
func (p *crawler) markType(t *types.Type) {
|
||||
if t.OrigSym() != nil {
|
||||
if orig := t.OrigType(); orig != nil {
|
||||
// Convert to the base generic type.
|
||||
t = t.OrigSym().Def.Type()
|
||||
t = orig
|
||||
}
|
||||
if p.marked[t] {
|
||||
return
|
||||
|
|
@ -154,9 +154,9 @@ func (p *crawler) markEmbed(t *types.Type) {
|
|||
t = t.Elem()
|
||||
}
|
||||
|
||||
if t.OrigSym() != nil {
|
||||
if orig := t.OrigType(); orig != nil {
|
||||
// Convert to the base generic type.
|
||||
t = t.OrigSym().Def.Type()
|
||||
t = orig
|
||||
}
|
||||
|
||||
if p.embedded[t] {
|
||||
|
|
@ -194,9 +194,9 @@ func (p *crawler) markGeneric(t *types.Type) {
|
|||
if t.IsPtr() {
|
||||
t = t.Elem()
|
||||
}
|
||||
if t.OrigSym() != nil {
|
||||
if orig := t.OrigType(); orig != nil {
|
||||
// Convert to the base generic type.
|
||||
t = t.OrigSym().Def.Type()
|
||||
t = orig
|
||||
}
|
||||
if p.generic[t] {
|
||||
return
|
||||
|
|
@ -229,7 +229,7 @@ func (p *crawler) checkForFullyInst(t *types.Type) {
|
|||
// them available for import, and so will not need
|
||||
// another round of method and dictionary
|
||||
// instantiation after inlining.
|
||||
baseType := t.OrigSym().Def.(*ir.Name).Type()
|
||||
baseType := t.OrigType()
|
||||
shapes := make([]*types.Type, len(t.RParams()))
|
||||
for i, t1 := range t.RParams() {
|
||||
shapes[i] = Shapify(t1, i, baseType.RParams()[i])
|
||||
|
|
|
|||
|
|
@ -70,8 +70,6 @@ func Declare(n *ir.Name, ctxt ir.Class) {
|
|||
n.SetFrameOffset(0)
|
||||
}
|
||||
|
||||
s.Block = types.Block
|
||||
s.Lastlineno = base.Pos
|
||||
s.Def = n
|
||||
n.Class = ctxt
|
||||
if ctxt == ir.PFUNC {
|
||||
|
|
|
|||
|
|
@ -58,10 +58,6 @@ func tcShift(n, l, r ir.Node) (ir.Node, ir.Node, *types.Type) {
|
|||
base.Errorf("invalid operation: %v (shift count type %v, must be integer)", n, r.Type())
|
||||
return l, r, nil
|
||||
}
|
||||
if t.IsSigned() && !types.AllowsGoVersion(curpkg(), 1, 13) {
|
||||
base.ErrorfVers("go1.13", "invalid operation: %v (signed shift count type %v)", n, r.Type())
|
||||
return l, r, nil
|
||||
}
|
||||
t = l.Type()
|
||||
if t != nil && t.Kind() != types.TIDEAL && !t.IsInteger() {
|
||||
base.Errorf("invalid operation: %v (shift of type %v)", n, t)
|
||||
|
|
@ -245,7 +241,6 @@ func tcCompLit(n *ir.CompLitExpr) (res ir.Node) {
|
|||
n.Len = length
|
||||
|
||||
case types.TMAP:
|
||||
var cs constSet
|
||||
for i3, l := range n.List {
|
||||
ir.SetPos(l)
|
||||
if l.Op() != ir.OKEY {
|
||||
|
|
@ -259,7 +254,6 @@ func tcCompLit(n *ir.CompLitExpr) (res ir.Node) {
|
|||
r = pushtype(r, t.Key())
|
||||
r = Expr(r)
|
||||
l.Key = AssignConv(r, t.Key(), "map key")
|
||||
cs.add(base.Pos, l.Key, "key", "map literal")
|
||||
|
||||
r = l.Value
|
||||
r = pushtype(r, t.Elem())
|
||||
|
|
@ -415,13 +409,7 @@ func tcConv(n *ir.ConvExpr) ir.Node {
|
|||
}
|
||||
op, why := Convertop(n.X.Op() == ir.OLITERAL, t, n.Type())
|
||||
if op == ir.OXXX {
|
||||
if !n.Diag() && !n.Type().Broke() && !n.X.Diag() {
|
||||
base.Errorf("cannot convert %L to type %v%s", n.X, n.Type(), why)
|
||||
n.SetDiag(true)
|
||||
}
|
||||
n.SetOp(ir.OCONV)
|
||||
n.SetType(nil)
|
||||
return n
|
||||
base.Fatalf("cannot convert %L to type %v%s", n.X, n.Type(), why)
|
||||
}
|
||||
|
||||
n.SetOp(op)
|
||||
|
|
|
|||
|
|
@ -241,12 +241,6 @@ func tcClosure(clo *ir.ClosureExpr, top int) ir.Node {
|
|||
base.FatalfAt(fn.Pos(), "underlying closure func already typechecked: %v", fn)
|
||||
}
|
||||
|
||||
// Set current associated iota value, so iota can be used inside
|
||||
// function in ConstSpec, see issue #22344
|
||||
if x := getIotaValue(); x >= 0 {
|
||||
fn.Iota = x
|
||||
}
|
||||
|
||||
ir.NameClosure(clo, ir.CurFunc)
|
||||
Func(fn)
|
||||
|
||||
|
|
@ -301,16 +295,19 @@ func tcFunc(n *ir.Func) {
|
|||
defer tracePrint("tcFunc", n)(nil)
|
||||
}
|
||||
|
||||
n.Nname = AssignExpr(n.Nname).(*ir.Name)
|
||||
if name := n.Nname; name.Typecheck() == 0 {
|
||||
if name.Ntype != nil {
|
||||
name.Ntype = typecheckNtype(name.Ntype)
|
||||
name.SetType(name.Ntype.Type())
|
||||
}
|
||||
name.SetTypecheck(1)
|
||||
}
|
||||
}
|
||||
|
||||
// tcCall typechecks an OCALL node.
|
||||
func tcCall(n *ir.CallExpr, top int) ir.Node {
|
||||
Stmts(n.Init()) // imported rewritten f(g()) calls (#30907)
|
||||
n.X = typecheck(n.X, ctxExpr|ctxType|ctxCallee)
|
||||
if n.X.Diag() {
|
||||
n.SetDiag(true)
|
||||
}
|
||||
|
||||
l := n.X
|
||||
|
||||
|
|
@ -360,10 +357,7 @@ func tcCall(n *ir.CallExpr, top int) ir.Node {
|
|||
l = n.X
|
||||
if l.Op() == ir.OTYPE {
|
||||
if n.IsDDD {
|
||||
if !l.Type().Broke() {
|
||||
base.Errorf("invalid use of ... in type conversion to %v", l.Type())
|
||||
}
|
||||
n.SetDiag(true)
|
||||
base.Fatalf("invalid use of ... in type conversion to %v", l.Type())
|
||||
}
|
||||
|
||||
// pick off before type-checking arguments
|
||||
|
|
@ -909,12 +903,6 @@ func tcRecoverFP(n *ir.CallExpr) ir.Node {
|
|||
|
||||
// tcUnsafeAdd typechecks an OUNSAFEADD node.
|
||||
func tcUnsafeAdd(n *ir.BinaryExpr) *ir.BinaryExpr {
|
||||
if !types.AllowsGoVersion(curpkg(), 1, 17) {
|
||||
base.ErrorfVers("go1.17", "unsafe.Add")
|
||||
n.SetType(nil)
|
||||
return n
|
||||
}
|
||||
|
||||
n.X = AssignConv(Expr(n.X), types.Types[types.TUNSAFEPTR], "argument to unsafe.Add")
|
||||
n.Y = DefaultLit(Expr(n.Y), types.Types[types.TINT])
|
||||
if n.X.Type() == nil || n.Y.Type() == nil {
|
||||
|
|
@ -931,12 +919,6 @@ func tcUnsafeAdd(n *ir.BinaryExpr) *ir.BinaryExpr {
|
|||
|
||||
// tcUnsafeSlice typechecks an OUNSAFESLICE node.
|
||||
func tcUnsafeSlice(n *ir.BinaryExpr) *ir.BinaryExpr {
|
||||
if !types.AllowsGoVersion(curpkg(), 1, 17) {
|
||||
base.ErrorfVers("go1.17", "unsafe.Slice")
|
||||
n.SetType(nil)
|
||||
return n
|
||||
}
|
||||
|
||||
n.X = Expr(n.X)
|
||||
n.Y = Expr(n.Y)
|
||||
if n.X.Type() == nil || n.Y.Type() == nil {
|
||||
|
|
|
|||
|
|
@ -948,7 +948,7 @@ func (w *exportWriter) startType(k itag) {
|
|||
|
||||
func (w *exportWriter) doTyp(t *types.Type) {
|
||||
s := t.Sym()
|
||||
if s != nil && t.OrigSym() != nil {
|
||||
if s != nil && t.OrigType() != nil {
|
||||
// This is an instantiated type - could be a re-instantiation like
|
||||
// Value[T2] or a full instantiation like Value[int].
|
||||
if strings.Index(s.Name, "[") < 0 {
|
||||
|
|
@ -964,7 +964,7 @@ func (w *exportWriter) doTyp(t *types.Type) {
|
|||
// types or existing typeparams from the function/method header.
|
||||
w.typeList(t.RParams())
|
||||
// Export a reference to the base type.
|
||||
baseType := t.OrigSym().Def.(*ir.Name).Type()
|
||||
baseType := t.OrigType()
|
||||
w.typ(baseType)
|
||||
return
|
||||
}
|
||||
|
|
@ -1835,7 +1835,10 @@ func (w *exportWriter) expr(n ir.Node) {
|
|||
n := n.(*ir.ClosureExpr)
|
||||
w.op(ir.OCLOSURE)
|
||||
w.pos(n.Pos())
|
||||
old := w.currPkg
|
||||
w.setPkg(n.Type().Pkg(), true)
|
||||
w.signature(n.Type())
|
||||
w.setPkg(old, true)
|
||||
|
||||
// Write out id for the Outer of each conditional variable. The
|
||||
// conditional variable itself for this closure will be re-created
|
||||
|
|
|
|||
|
|
@ -761,7 +761,7 @@ func (p *iimporter) typAt(off uint64) *types.Type {
|
|||
// No need to calc sizes for re-instantiated generic types, and
|
||||
// they are not necessarily resolved until the top-level type is
|
||||
// defined (because of recursive types).
|
||||
if t.OrigSym() == nil || !t.HasTParam() {
|
||||
if t.OrigType() == nil || !t.HasTParam() {
|
||||
types.CheckSize(t)
|
||||
}
|
||||
p.typCache[off] = t
|
||||
|
|
@ -1374,7 +1374,9 @@ func (r *importReader) node() ir.Node {
|
|||
case ir.OCLOSURE:
|
||||
//println("Importing CLOSURE")
|
||||
pos := r.pos()
|
||||
r.setPkg()
|
||||
typ := r.signature(nil, nil)
|
||||
r.setPkg()
|
||||
|
||||
// All the remaining code below is similar to (*noder).funcLit(), but
|
||||
// with Dcls and ClosureVars lists already set up
|
||||
|
|
@ -1480,7 +1482,7 @@ func (r *importReader) node() ir.Node {
|
|||
} else {
|
||||
genType := types.ReceiverBaseType(n1.X.Type())
|
||||
if genType.IsInstantiatedGeneric() {
|
||||
genType = genType.OrigSym().Def.Type()
|
||||
genType = genType.OrigType()
|
||||
}
|
||||
m = Lookdot1(n1, sel, genType, genType.Methods(), 1)
|
||||
}
|
||||
|
|
@ -1911,7 +1913,7 @@ func Instantiate(pos src.XPos, baseType *types.Type, targs []*types.Type) *types
|
|||
|
||||
t := NewIncompleteNamedType(baseType.Pos(), instSym)
|
||||
t.SetRParams(targs)
|
||||
t.SetOrigSym(baseSym)
|
||||
t.SetOrigType(baseType)
|
||||
|
||||
// baseType may still be TFORW or its methods may not be fully filled in
|
||||
// (since we are in the middle of importing it). So, delay call to
|
||||
|
|
@ -1936,7 +1938,7 @@ func resumeDoInst() {
|
|||
for len(deferredInstStack) > 0 {
|
||||
t := deferredInstStack[0]
|
||||
deferredInstStack = deferredInstStack[1:]
|
||||
substInstType(t, t.OrigSym().Def.(*ir.Name).Type(), t.RParams())
|
||||
substInstType(t, t.OrigType(), t.RParams())
|
||||
}
|
||||
}
|
||||
deferInst--
|
||||
|
|
@ -1948,7 +1950,7 @@ func resumeDoInst() {
|
|||
// instantiations of mutually recursive types.
|
||||
func doInst(t *types.Type) *types.Type {
|
||||
assert(t.Kind() == types.TFORW)
|
||||
return Instantiate(t.Pos(), t.OrigSym().Def.(*ir.Name).Type(), t.RParams())
|
||||
return Instantiate(t.Pos(), t.OrigType(), t.RParams())
|
||||
}
|
||||
|
||||
// substInstType completes the instantiation of a generic type by doing a
|
||||
|
|
|
|||
|
|
@ -309,16 +309,13 @@ func tcGoDefer(n *ir.GoDeferStmt) {
|
|||
|
||||
// type is broken or missing, most likely a method call on a broken type
|
||||
// we will warn about the broken type elsewhere. no need to emit a potentially confusing error
|
||||
if n.Call.Type() == nil || n.Call.Type().Broke() {
|
||||
if n.Call.Type() == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !n.Diag() {
|
||||
// The syntax made sure it was a call, so this must be
|
||||
// a conversion.
|
||||
n.SetDiag(true)
|
||||
base.ErrorfAt(n.Pos(), "%s requires function call, not conversion", what)
|
||||
}
|
||||
// The syntax made sure it was a call, so this must be
|
||||
// a conversion.
|
||||
base.FatalfAt(n.Pos(), "%s requires function call, not conversion", what)
|
||||
}
|
||||
|
||||
// tcIf typechecks an OIF node.
|
||||
|
|
@ -519,7 +516,6 @@ func tcSwitchExpr(n *ir.SwitchStmt) {
|
|||
}
|
||||
|
||||
var defCase ir.Node
|
||||
var cs constSet
|
||||
for _, ncase := range n.Cases {
|
||||
ls := ncase.List
|
||||
if len(ls) == 0 { // default:
|
||||
|
|
@ -554,16 +550,6 @@ func tcSwitchExpr(n *ir.SwitchStmt) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Don't check for duplicate bools. Although the spec allows it,
|
||||
// (1) the compiler hasn't checked it in the past, so compatibility mandates it, and
|
||||
// (2) it would disallow useful things like
|
||||
// case GOARCH == "arm" && GOARM == "5":
|
||||
// case GOARCH == "arm":
|
||||
// which would both evaluate to false for non-ARM compiles.
|
||||
if !n1.Type().IsBoolean() {
|
||||
cs.add(ncase.Pos(), n1, "case", "switch")
|
||||
}
|
||||
}
|
||||
|
||||
Stmts(ncase.Body)
|
||||
|
|
@ -615,12 +601,15 @@ func tcSwitchType(n *ir.SwitchStmt) {
|
|||
}
|
||||
continue
|
||||
}
|
||||
if n1.Op() == ir.ODYNAMICTYPE {
|
||||
continue
|
||||
}
|
||||
if n1.Op() != ir.OTYPE {
|
||||
base.ErrorfAt(ncase.Pos(), "%L is not a type", n1)
|
||||
continue
|
||||
}
|
||||
if !n1.Type().IsInterface() && !implements(n1.Type(), t, &missing, &have, &ptr) && !missing.Broke() {
|
||||
if have != nil && !have.Broke() {
|
||||
if !n1.Type().IsInterface() && !implements(n1.Type(), t, &missing, &have, &ptr) {
|
||||
if have != nil {
|
||||
base.ErrorfAt(ncase.Pos(), "impossible type switch case: %L cannot have dynamic type %v"+
|
||||
" (wrong type for %v method)\n\thave %v%S\n\twant %v%S", guard.X, n1.Type(), missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
|
||||
} else if ptr != 0 {
|
||||
|
|
@ -640,7 +629,7 @@ func tcSwitchType(n *ir.SwitchStmt) {
|
|||
// Assign the clause variable's type.
|
||||
vt := t
|
||||
if len(ls) == 1 {
|
||||
if ls[0].Op() == ir.OTYPE {
|
||||
if ls[0].Op() == ir.OTYPE || ls[0].Op() == ir.ODYNAMICTYPE {
|
||||
vt = ls[0].Type()
|
||||
} else if !ir.IsNil(ls[0]) {
|
||||
// Invalid single-type case;
|
||||
|
|
@ -656,7 +645,6 @@ func tcSwitchType(n *ir.SwitchStmt) {
|
|||
} else {
|
||||
// Clause variable is broken; prevent typechecking.
|
||||
nvar.SetTypecheck(1)
|
||||
nvar.SetWalkdef(1)
|
||||
}
|
||||
ncase.Var = nvar
|
||||
}
|
||||
|
|
|
|||
|
|
@ -135,9 +135,6 @@ func NodNil() ir.Node {
|
|||
// modifies the tree with missing field names.
|
||||
func AddImplicitDots(n *ir.SelectorExpr) *ir.SelectorExpr {
|
||||
n.X = typecheck(n.X, ctxType|ctxExpr)
|
||||
if n.X.Diag() {
|
||||
n.SetDiag(true)
|
||||
}
|
||||
t := n.X.Type()
|
||||
if t == nil {
|
||||
return n
|
||||
|
|
@ -291,7 +288,7 @@ var dotlist = make([]dlist, 10)
|
|||
|
||||
// Convert node n for assignment to type t.
|
||||
func assignconvfn(n ir.Node, t *types.Type, context func() string) ir.Node {
|
||||
if n == nil || n.Type() == nil || n.Type().Broke() {
|
||||
if n == nil || n.Type() == nil {
|
||||
return n
|
||||
}
|
||||
|
||||
|
|
@ -396,11 +393,6 @@ func Assignop1(src, dst *types.Type) (ir.Op, string) {
|
|||
return ir.OCONVIFACE, ""
|
||||
}
|
||||
|
||||
// we'll have complained about this method anyway, suppress spurious messages.
|
||||
if have != nil && have.Sym == missing.Sym && (have.Type.Broke() || missing.Type.Broke()) {
|
||||
return ir.OCONVIFACE, ""
|
||||
}
|
||||
|
||||
var why string
|
||||
if isptrto(src, types.TINTER) {
|
||||
why = fmt.Sprintf(":\n\t%v is pointer to interface, not interface", src)
|
||||
|
|
@ -593,9 +585,6 @@ func Convertop(srcConstant bool, src, dst *types.Type) (ir.Op, string) {
|
|||
// They must have same element type.
|
||||
if src.IsSlice() && dst.IsPtr() && dst.Elem().IsArray() &&
|
||||
types.Identical(src.Elem(), dst.Elem().Elem()) {
|
||||
if !types.AllowsGoVersion(curpkg(), 1, 17) {
|
||||
return ir.OXXX, ":\n\tconversion of slices to array pointers only supported as of -lang=go1.17"
|
||||
}
|
||||
return ir.OSLICE2ARRPTR, ""
|
||||
}
|
||||
|
||||
|
|
@ -785,9 +774,6 @@ func implements(t, iface *types.Type, m, samename **types.Field, ptr *int) bool
|
|||
}
|
||||
i := 0
|
||||
for _, im := range iface.AllMethods().Slice() {
|
||||
if im.Broke() {
|
||||
continue
|
||||
}
|
||||
for i < len(tms) && tms[i].Sym != im.Sym {
|
||||
i++
|
||||
}
|
||||
|
|
@ -1116,10 +1102,10 @@ func (ts *Tsubster) typ1(t *types.Type) *types.Type {
|
|||
forw = NewIncompleteNamedType(t.Pos(), newsym)
|
||||
//println("Creating new type by sub", newsym.Name, forw.HasTParam())
|
||||
forw.SetRParams(neededTargs)
|
||||
// Copy the OrigSym from the re-instantiated type (which is the sym of
|
||||
// Copy the OrigType from the re-instantiated type (which is the sym of
|
||||
// the base generic type).
|
||||
assert(t.OrigSym() != nil)
|
||||
forw.SetOrigSym(t.OrigSym())
|
||||
assert(t.OrigType() != nil)
|
||||
forw.SetOrigType(t.OrigType())
|
||||
}
|
||||
|
||||
var newt *types.Type
|
||||
|
|
@ -1532,13 +1518,10 @@ func Shapify(t *types.Type, index int, tparam *types.Type) *types.Type {
|
|||
// Note: pointers to arrays are special because of slice-to-array-pointer
|
||||
// conversions. See issue 49295.
|
||||
if u.Kind() == types.TPTR && u.Elem().Kind() != types.TARRAY &&
|
||||
tparam.Bound().StructuralType() == nil {
|
||||
tparam.Bound().StructuralType() == nil && !u.Elem().NotInHeap() {
|
||||
u = types.Types[types.TUINT8].PtrTo()
|
||||
}
|
||||
|
||||
if shapeMap == nil {
|
||||
shapeMap = map[int]map[*types.Type]*types.Type{}
|
||||
}
|
||||
submap := shapeMap[index]
|
||||
if submap == nil {
|
||||
submap = map[*types.Type]*types.Type{}
|
||||
|
|
@ -1569,4 +1552,4 @@ func Shapify(t *types.Type, index int, tparam *types.Type) *types.Type {
|
|||
return s
|
||||
}
|
||||
|
||||
var shapeMap map[int]map[*types.Type]*types.Type
|
||||
var shapeMap = map[int]map[*types.Type]*types.Type{}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue