[dev.boringcrypto] all: merge master into dev.boringcrypto

Change-Id: Iaf618444dd2d99721c19708df9ce2c1f35854efd
This commit is contained in:
Lasse Folger 2022-04-05 09:19:57 +02:00
commit 4739b353bb
587 changed files with 7214 additions and 5242 deletions

View file

@ -829,6 +829,7 @@ Liberty Fund Inc
Linaro Limited
Lion Yang <lion@aosc.xyz>
Lloyd Dewolf <foolswisdom@gmail.com>
Loongson Technology Corporation Limited
Lorenzo Masini <rugginoso@develer.com>
Lorenzo Stoakes <lstoakes@gmail.com>
Luan Santos <cfcluan@gmail.com>

View file

@ -505,3 +505,5 @@ pkg unicode, const Version = "6.3.0"
pkg unicode, const Version = "7.0.0"
pkg unicode, const Version = "8.0.0"
pkg unicode, const Version = "9.0.0"
pkg html/template, method (*Template) Funcs(FuncMap) *Template
pkg html/template, type FuncMap map[string]interface{}

View file

@ -371,7 +371,7 @@ pkg debug/elf, const ELFCLASSNONE = 0
pkg debug/elf, const ELFDATA2LSB = 1
pkg debug/elf, const ELFDATA2MSB = 2
pkg debug/elf, const ELFDATANONE = 0
pkg debug/elf, const ELFMAG = "\u007fELF"
pkg debug/elf, const ELFMAG = "\x7fELF"
pkg debug/elf, const ELFOSABI_86OPEN = 5
pkg debug/elf, const ELFOSABI_AIX = 7
pkg debug/elf, const ELFOSABI_ARM = 97

1
api/next/46057.txt Normal file
View file

@ -0,0 +1 @@
pkg crypto/x509, method (*CertPool) Equal(*CertPool) bool #46057

2
api/next/46121.txt Normal file
View file

@ -0,0 +1,2 @@
pkg html/template, method (*Template) Funcs(template.FuncMap) *Template #46121
pkg html/template, type FuncMap = template.FuncMap #46121

105
api/next/46229.txt Normal file
View file

@ -0,0 +1,105 @@
pkg debug/elf, const EM_LOONGARCH = 258 #46229
pkg debug/elf, const EM_LOONGARCH Machine #46229
pkg debug/elf, const R_LARCH_32 = 1 #46229
pkg debug/elf, const R_LARCH_32 R_LARCH #46229
pkg debug/elf, const R_LARCH_64 = 2 #46229
pkg debug/elf, const R_LARCH_64 R_LARCH #46229
pkg debug/elf, const R_LARCH_ADD16 = 48 #46229
pkg debug/elf, const R_LARCH_ADD16 R_LARCH #46229
pkg debug/elf, const R_LARCH_ADD24 = 49 #46229
pkg debug/elf, const R_LARCH_ADD24 R_LARCH #46229
pkg debug/elf, const R_LARCH_ADD32 = 50 #46229
pkg debug/elf, const R_LARCH_ADD32 R_LARCH #46229
pkg debug/elf, const R_LARCH_ADD64 = 51 #46229
pkg debug/elf, const R_LARCH_ADD64 R_LARCH #46229
pkg debug/elf, const R_LARCH_ADD8 = 47 #46229
pkg debug/elf, const R_LARCH_ADD8 R_LARCH #46229
pkg debug/elf, const R_LARCH_COPY = 4 #46229
pkg debug/elf, const R_LARCH_COPY R_LARCH #46229
pkg debug/elf, const R_LARCH_IRELATIVE = 12 #46229
pkg debug/elf, const R_LARCH_IRELATIVE R_LARCH #46229
pkg debug/elf, const R_LARCH_JUMP_SLOT = 5 #46229
pkg debug/elf, const R_LARCH_JUMP_SLOT R_LARCH #46229
pkg debug/elf, const R_LARCH_MARK_LA = 20 #46229
pkg debug/elf, const R_LARCH_MARK_LA R_LARCH #46229
pkg debug/elf, const R_LARCH_MARK_PCREL = 21 #46229
pkg debug/elf, const R_LARCH_MARK_PCREL R_LARCH #46229
pkg debug/elf, const R_LARCH_NONE = 0 #46229
pkg debug/elf, const R_LARCH_NONE R_LARCH #46229
pkg debug/elf, const R_LARCH_RELATIVE = 3 #46229
pkg debug/elf, const R_LARCH_RELATIVE R_LARCH #46229
pkg debug/elf, const R_LARCH_SOP_ADD = 35 #46229
pkg debug/elf, const R_LARCH_SOP_ADD R_LARCH #46229
pkg debug/elf, const R_LARCH_SOP_AND = 36 #46229
pkg debug/elf, const R_LARCH_SOP_AND R_LARCH #46229
pkg debug/elf, const R_LARCH_SOP_ASSERT = 30 #46229
pkg debug/elf, const R_LARCH_SOP_ASSERT R_LARCH #46229
pkg debug/elf, const R_LARCH_SOP_IF_ELSE = 37 #46229
pkg debug/elf, const R_LARCH_SOP_IF_ELSE R_LARCH #46229
pkg debug/elf, const R_LARCH_SOP_NOT = 31 #46229
pkg debug/elf, const R_LARCH_SOP_NOT R_LARCH #46229
pkg debug/elf, const R_LARCH_SOP_POP_32_S_0_10_10_16_S2 = 45 #46229
pkg debug/elf, const R_LARCH_SOP_POP_32_S_0_10_10_16_S2 R_LARCH #46229
pkg debug/elf, const R_LARCH_SOP_POP_32_S_0_5_10_16_S2 = 44 #46229
pkg debug/elf, const R_LARCH_SOP_POP_32_S_0_5_10_16_S2 R_LARCH #46229
pkg debug/elf, const R_LARCH_SOP_POP_32_S_10_12 = 40 #46229
pkg debug/elf, const R_LARCH_SOP_POP_32_S_10_12 R_LARCH #46229
pkg debug/elf, const R_LARCH_SOP_POP_32_S_10_16 = 41 #46229
pkg debug/elf, const R_LARCH_SOP_POP_32_S_10_16 R_LARCH #46229
pkg debug/elf, const R_LARCH_SOP_POP_32_S_10_16_S2 = 42 #46229
pkg debug/elf, const R_LARCH_SOP_POP_32_S_10_16_S2 R_LARCH #46229
pkg debug/elf, const R_LARCH_SOP_POP_32_S_10_5 = 38 #46229
pkg debug/elf, const R_LARCH_SOP_POP_32_S_10_5 R_LARCH #46229
pkg debug/elf, const R_LARCH_SOP_POP_32_S_5_20 = 43 #46229
pkg debug/elf, const R_LARCH_SOP_POP_32_S_5_20 R_LARCH #46229
pkg debug/elf, const R_LARCH_SOP_POP_32_U = 46 #46229
pkg debug/elf, const R_LARCH_SOP_POP_32_U R_LARCH #46229
pkg debug/elf, const R_LARCH_SOP_POP_32_U_10_12 = 39 #46229
pkg debug/elf, const R_LARCH_SOP_POP_32_U_10_12 R_LARCH #46229
pkg debug/elf, const R_LARCH_SOP_PUSH_ABSOLUTE = 23 #46229
pkg debug/elf, const R_LARCH_SOP_PUSH_ABSOLUTE R_LARCH #46229
pkg debug/elf, const R_LARCH_SOP_PUSH_DUP = 24 #46229
pkg debug/elf, const R_LARCH_SOP_PUSH_DUP R_LARCH #46229
pkg debug/elf, const R_LARCH_SOP_PUSH_GPREL = 25 #46229
pkg debug/elf, const R_LARCH_SOP_PUSH_GPREL R_LARCH #46229
pkg debug/elf, const R_LARCH_SOP_PUSH_PCREL = 22 #46229
pkg debug/elf, const R_LARCH_SOP_PUSH_PCREL R_LARCH #46229
pkg debug/elf, const R_LARCH_SOP_PUSH_PLT_PCREL = 29 #46229
pkg debug/elf, const R_LARCH_SOP_PUSH_PLT_PCREL R_LARCH #46229
pkg debug/elf, const R_LARCH_SOP_PUSH_TLS_GD = 28 #46229
pkg debug/elf, const R_LARCH_SOP_PUSH_TLS_GD R_LARCH #46229
pkg debug/elf, const R_LARCH_SOP_PUSH_TLS_GOT = 27 #46229
pkg debug/elf, const R_LARCH_SOP_PUSH_TLS_GOT R_LARCH #46229
pkg debug/elf, const R_LARCH_SOP_PUSH_TLS_TPREL = 26 #46229
pkg debug/elf, const R_LARCH_SOP_PUSH_TLS_TPREL R_LARCH #46229
pkg debug/elf, const R_LARCH_SOP_SL = 33 #46229
pkg debug/elf, const R_LARCH_SOP_SL R_LARCH #46229
pkg debug/elf, const R_LARCH_SOP_SR = 34 #46229
pkg debug/elf, const R_LARCH_SOP_SR R_LARCH #46229
pkg debug/elf, const R_LARCH_SOP_SUB = 32 #46229
pkg debug/elf, const R_LARCH_SOP_SUB R_LARCH #46229
pkg debug/elf, const R_LARCH_SUB16 = 53 #46229
pkg debug/elf, const R_LARCH_SUB16 R_LARCH #46229
pkg debug/elf, const R_LARCH_SUB24 = 54 #46229
pkg debug/elf, const R_LARCH_SUB24 R_LARCH #46229
pkg debug/elf, const R_LARCH_SUB32 = 55 #46229
pkg debug/elf, const R_LARCH_SUB32 R_LARCH #46229
pkg debug/elf, const R_LARCH_SUB64 = 56 #46229
pkg debug/elf, const R_LARCH_SUB64 R_LARCH #46229
pkg debug/elf, const R_LARCH_SUB8 = 52 #46229
pkg debug/elf, const R_LARCH_SUB8 R_LARCH #46229
pkg debug/elf, const R_LARCH_TLS_DTPMOD32 = 6 #46229
pkg debug/elf, const R_LARCH_TLS_DTPMOD32 R_LARCH #46229
pkg debug/elf, const R_LARCH_TLS_DTPMOD64 = 7 #46229
pkg debug/elf, const R_LARCH_TLS_DTPMOD64 R_LARCH #46229
pkg debug/elf, const R_LARCH_TLS_DTPREL32 = 8 #46229
pkg debug/elf, const R_LARCH_TLS_DTPREL32 R_LARCH #46229
pkg debug/elf, const R_LARCH_TLS_DTPREL64 = 9 #46229
pkg debug/elf, const R_LARCH_TLS_DTPREL64 R_LARCH #46229
pkg debug/elf, const R_LARCH_TLS_TPREL32 = 10 #46229
pkg debug/elf, const R_LARCH_TLS_TPREL32 R_LARCH #46229
pkg debug/elf, const R_LARCH_TLS_TPREL64 = 11 #46229
pkg debug/elf, const R_LARCH_TLS_TPREL64 R_LARCH #46229
pkg debug/elf, method (R_LARCH) GoString() string #46229
pkg debug/elf, method (R_LARCH) String() string #46229
pkg debug/elf, type R_LARCH int #46229

36
api/next/51868.txt Normal file
View file

@ -0,0 +1,36 @@
pkg debug/pe, const IMAGE_COMDAT_SELECT_ANY = 2 #51686
pkg debug/pe, const IMAGE_COMDAT_SELECT_ANY ideal-int #51686
pkg debug/pe, const IMAGE_COMDAT_SELECT_ASSOCIATIVE = 5 #51686
pkg debug/pe, const IMAGE_COMDAT_SELECT_ASSOCIATIVE ideal-int #51686
pkg debug/pe, const IMAGE_COMDAT_SELECT_EXACT_MATCH = 4 #51686
pkg debug/pe, const IMAGE_COMDAT_SELECT_EXACT_MATCH ideal-int #51686
pkg debug/pe, const IMAGE_COMDAT_SELECT_LARGEST = 6 #51686
pkg debug/pe, const IMAGE_COMDAT_SELECT_LARGEST ideal-int #51686
pkg debug/pe, const IMAGE_COMDAT_SELECT_NODUPLICATES = 1 #51686
pkg debug/pe, const IMAGE_COMDAT_SELECT_NODUPLICATES ideal-int #51686
pkg debug/pe, const IMAGE_COMDAT_SELECT_SAME_SIZE = 3 #51686
pkg debug/pe, const IMAGE_COMDAT_SELECT_SAME_SIZE ideal-int #51686
pkg debug/pe, const IMAGE_SCN_CNT_CODE = 32 #51686
pkg debug/pe, const IMAGE_SCN_CNT_CODE ideal-int #51686
pkg debug/pe, const IMAGE_SCN_CNT_INITIALIZED_DATA = 64 #51686
pkg debug/pe, const IMAGE_SCN_CNT_INITIALIZED_DATA ideal-int #51686
pkg debug/pe, const IMAGE_SCN_CNT_UNINITIALIZED_DATA = 128 #51686
pkg debug/pe, const IMAGE_SCN_CNT_UNINITIALIZED_DATA ideal-int #51686
pkg debug/pe, const IMAGE_SCN_LNK_COMDAT = 4096 #51686
pkg debug/pe, const IMAGE_SCN_LNK_COMDAT ideal-int #51686
pkg debug/pe, const IMAGE_SCN_MEM_DISCARDABLE = 33554432 #51686
pkg debug/pe, const IMAGE_SCN_MEM_DISCARDABLE ideal-int #51686
pkg debug/pe, const IMAGE_SCN_MEM_EXECUTE = 536870912 #51686
pkg debug/pe, const IMAGE_SCN_MEM_EXECUTE ideal-int #51686
pkg debug/pe, const IMAGE_SCN_MEM_READ = 1073741824 #51686
pkg debug/pe, const IMAGE_SCN_MEM_READ ideal-int #51686
pkg debug/pe, const IMAGE_SCN_MEM_WRITE = 2147483648 #51686
pkg debug/pe, const IMAGE_SCN_MEM_WRITE ideal-int #51686
pkg debug/pe, method (*File) COFFSymbolReadSectionDefAux(int) (*COFFSymbolAuxFormat5, error) #51686
pkg debug/pe, type COFFSymbolAuxFormat5 struct #51686
pkg debug/pe, type COFFSymbolAuxFormat5 struct, Checksum uint32 #51686
pkg debug/pe, type COFFSymbolAuxFormat5 struct, NumLineNumbers uint16 #51686
pkg debug/pe, type COFFSymbolAuxFormat5 struct, NumRelocs uint16 #51686
pkg debug/pe, type COFFSymbolAuxFormat5 struct, SecNum uint16 #51686
pkg debug/pe, type COFFSymbolAuxFormat5 struct, Selection uint8 #51686
pkg debug/pe, type COFFSymbolAuxFormat5 struct, Size uint32 #51686

3
api/next/regexpdepth.txt Normal file
View file

@ -0,0 +1,3 @@
pkg regexp/syntax, const ErrInvalidDepth = "invalid nesting depth" #0
pkg regexp/syntax, const ErrInvalidDepth ErrorCode #0

View file

@ -34,6 +34,23 @@ Do not send CLs removing the interior tags from such phrases.
<p>
TODO: complete this section, or delete if not needed
</p>
<h4 id="go-unix">New <code>unix</code> build constraint</h4>
<p><!-- CL 389934 -->
The build constraint <code>unix</code> is now recognized
in <code>//go:build</code> lines. The constraint is satisfied
if the target operating system, also known as <code>GOOS</code>, is
a Unix or Unix-like system. For the 1.19 release it is satisfied
if <code>GOOS</code> is one of
<code>aix</code>, <code>android</code>, <code>darwin</code>,
<code>dragonfly</code>, <code>freebsd</code>, <code>hurd</code>,
<code>illumos</code>, <code>ios</code>, <code>linux</code>,
<code>netbsd</code>, <code>openbsd</code>, or <code>solaris</code>.
In future releases the <code>unix</code> constraint may match
additional newly supported operating systems.
</p>
<h2 id="runtime">Runtime</h2>
<p>
TODO: complete this section, or delete if not needed
@ -72,5 +89,27 @@ Do not send CLs removing the interior tags from such phrases.
Please report any such problems on <a href="/issue/new">the
issue tracker</a>.
</p>
<p><!-- CL 396877 -->
When a net package function or method returns an "I/O timeout"
error, the error will now satisfy <code>errors.Is(err,
context.Canceled)</code>. When a net package function returns
an "operation was canceled" error, the error will now satisfy
<code>errors.Is(err, context.DeadlineExceeded)</code>.
These changes are intended to make it easier for code to test
for cases in which a context cancelation or timeout causes a net
package function or method to return an error, while preserving
backward compatibility for error messages.
</p>
</dd>
</dl>
</dl><!-- net -->
<dl id="strconv"><dt><a href="/pkg/strconv/">strconv</a></dt>
<dd>
<p><!-- CL 397255 -->
<a href="/pkg/strconv/#strconv.Quote"><code>strconv.Quote</code></a>
and related functions now quote the rune 007F as <code>\x7f</code>,
not <code>\u007f</code>.
</p>
</dd>
</dl><!-- strconv -->

View file

@ -1,6 +1,6 @@
<!--{
"Title": "The Go Programming Language Specification",
"Subtitle": "Version of March 10, 2022",
"Subtitle": "Version of March 30, 2022",
"Path": "/ref/spec"
}-->
@ -529,6 +529,7 @@ escaped_char = `\` ( "a" | "b" | "f" | "n" | "r" | "t" | "v" | `\` | "'" | `
'aa' // illegal: too many characters
'\xa' // illegal: too few hexadecimal digits
'\0' // illegal: too few octal digits
'\400' // illegal: octal value over 255
'\uDFFF' // illegal: surrogate half
'\U00110000' // illegal: invalid Unicode code point
</pre>
@ -1454,7 +1455,8 @@ type Float interface {
</pre>
<p>
In a union, a term cannot be a <a href="#Type_parameter_declarations">type parameter</a>, and the type sets of all
The type <code>T</code> in a term of the form <code>T</code> or <code>~T</code> 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>
@ -1462,7 +1464,7 @@ Given a type parameter <code>P</code>:
<pre>
interface {
P // illegal: P is a type parameter
int | 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
}
@ -1878,7 +1880,7 @@ A4, func(int, float64) *[]string, and A5
B0 and C0
D0[int, string] and E0
[]int and []int
struct{ a, b *T5 } and struct{ a, b *T5 }
struct{ a, b *B5 } and struct{ a, b *B5 }
func(x int, y float64) *[]string, func(int, float64) (result *[]string), and A5
</pre>
@ -4195,7 +4197,7 @@ type parameter list type arguments after substitution
<p>
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
A generic function that 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.
A generic function that is called may provide a (possibly partial) type

View file

@ -9,6 +9,7 @@ import (
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"testing"
)
@ -58,9 +59,32 @@ func TestGoDefs(t *testing.T) {
t.Fatalf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, cmd.Stderr)
}
if err := os.WriteFile(filepath.Join(dir, fp+"_defs.go"), out, 0644); err != nil {
fn := fp + "_defs.go"
if err := os.WriteFile(filepath.Join(dir, fn), out, 0644); err != nil {
t.Fatal(err)
}
// Verify that command line arguments are not rewritten in the generated comment,
// see go.dev/issue/52063
hasGeneratedByComment := false
for _, line := range strings.Split(strings.TrimSpace(string(out)), "\n") {
cgoExe := "cgo"
if runtime.GOOS == "windows" {
cgoExe = "cgo.exe"
}
if !strings.HasPrefix(line, "// "+cgoExe+" -godefs") {
continue
}
if want := "// " + cgoExe + " " + strings.Join(cmd.Args[3:], " "); line != want {
t.Errorf("%s: got generated comment %q, want %q", fn, line, want)
}
hasGeneratedByComment = true
break
}
if !hasGeneratedByComment {
t.Errorf("%s: comment with generating cgo -godefs command not found", fn)
}
}
main, err := os.ReadFile(filepath.Join("testdata", "main.go"))

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build aix || linux || darwin || dragonfly || freebsd || openbsd || netbsd || solaris
//go:build unix
package tar

View file

@ -865,7 +865,6 @@ func returnRecursiveZip() (r io.ReaderAt, size int64) {
//
// It's here in hex for the same reason as rZipBytes above: to avoid
// problems with on-disk virus scanners or other zip processors.
//
func biggestZipBytes() []byte {
s := `
0000000 50 4b 03 04 14 00 08 00 08 00 00 00 00 00 00 00

View file

@ -26,7 +26,6 @@ import (
// advanced arbitrarily far past the last token. Programs that need more
// control over error handling or large tokens, or must run sequential scans
// on a reader, should use bufio.Reader instead.
//
type Scanner struct {
r io.Reader // The reader provided by the client.
split SplitFunc // The function to split the tokens.

View file

@ -278,46 +278,7 @@ func archArm64() *Arch {
}
register["LR"] = arm64.REGLINK
register["DAIFSet"] = arm64.REG_DAIFSet
register["DAIFClr"] = arm64.REG_DAIFClr
register["PLDL1KEEP"] = arm64.REG_PLDL1KEEP
register["PLDL1STRM"] = arm64.REG_PLDL1STRM
register["PLDL2KEEP"] = arm64.REG_PLDL2KEEP
register["PLDL2STRM"] = arm64.REG_PLDL2STRM
register["PLDL3KEEP"] = arm64.REG_PLDL3KEEP
register["PLDL3STRM"] = arm64.REG_PLDL3STRM
register["PLIL1KEEP"] = arm64.REG_PLIL1KEEP
register["PLIL1STRM"] = arm64.REG_PLIL1STRM
register["PLIL2KEEP"] = arm64.REG_PLIL2KEEP
register["PLIL2STRM"] = arm64.REG_PLIL2STRM
register["PLIL3KEEP"] = arm64.REG_PLIL3KEEP
register["PLIL3STRM"] = arm64.REG_PLIL3STRM
register["PSTL1KEEP"] = arm64.REG_PSTL1KEEP
register["PSTL1STRM"] = arm64.REG_PSTL1STRM
register["PSTL2KEEP"] = arm64.REG_PSTL2KEEP
register["PSTL2STRM"] = arm64.REG_PSTL2STRM
register["PSTL3KEEP"] = arm64.REG_PSTL3KEEP
register["PSTL3STRM"] = arm64.REG_PSTL3STRM
// Conditional operators, like EQ, NE, etc.
register["EQ"] = arm64.COND_EQ
register["NE"] = arm64.COND_NE
register["HS"] = arm64.COND_HS
register["CS"] = arm64.COND_HS
register["LO"] = arm64.COND_LO
register["CC"] = arm64.COND_LO
register["MI"] = arm64.COND_MI
register["PL"] = arm64.COND_PL
register["VS"] = arm64.COND_VS
register["VC"] = arm64.COND_VC
register["HI"] = arm64.COND_HI
register["LS"] = arm64.COND_LS
register["GE"] = arm64.COND_GE
register["LT"] = arm64.COND_LT
register["GT"] = arm64.COND_GT
register["LE"] = arm64.COND_LE
register["AL"] = arm64.COND_AL
register["NV"] = arm64.COND_NV
// Pseudo-registers.
register["SB"] = RSB
register["FP"] = RFP

View file

@ -12,6 +12,7 @@ import (
"cmd/internal/obj"
"cmd/internal/obj/arm64"
"errors"
"fmt"
)
var arm64LS = map[string]uint8{
@ -52,7 +53,35 @@ func jumpArm64(word string) bool {
return arm64Jump[word]
}
// IsARM64CMP reports whether the op (as defined by an arm.A* constant) is
var arm64SpecialOperand map[string]arm64.SpecialOperand
// GetARM64SpecialOperand returns the internal representation of a special operand.
func GetARM64SpecialOperand(name string) arm64.SpecialOperand {
if arm64SpecialOperand == nil {
// Generate the mapping automatically when the first time the function is called.
arm64SpecialOperand = map[string]arm64.SpecialOperand{}
for opd := arm64.SPOP_BEGIN; opd < arm64.SPOP_END; opd++ {
s := fmt.Sprintf("%s", opd)
arm64SpecialOperand[s] = opd
}
// Handle some special cases.
specialMapping := map[string]arm64.SpecialOperand{
// The internal representation of CS(CC) and HS(LO) are the same.
"CS": arm64.SPOP_HS,
"CC": arm64.SPOP_LO,
}
for s, opd := range specialMapping {
arm64SpecialOperand[s] = opd
}
}
if opd, ok := arm64SpecialOperand[name]; ok {
return opd
}
return arm64.SPOP_END
}
// IsARM64CMP reports whether the op (as defined by an arm64.A* constant) is
// one of the comparison instructions that require special handling.
func IsARM64CMP(op obj.As) bool {
switch op {

View file

@ -19,6 +19,7 @@ import (
"cmd/asm/internal/flags"
"cmd/asm/internal/lex"
"cmd/internal/obj"
"cmd/internal/obj/arm64"
"cmd/internal/obj/x86"
"cmd/internal/src"
"cmd/internal/sys"
@ -389,8 +390,19 @@ func (p *Parser) operand(a *obj.Addr) {
tok := p.next()
name := tok.String()
if tok.ScanToken == scanner.Ident && !p.atStartOfRegister(name) {
// We have a symbol. Parse $sym±offset(symkind)
p.symbolReference(a, name, prefix)
switch p.arch.Family {
case sys.ARM64:
// arm64 special operands.
if opd := arch.GetARM64SpecialOperand(name); opd != arm64.SPOP_END {
a.Type = obj.TYPE_SPECIAL
a.Offset = int64(opd)
break
}
fallthrough
default:
// We have a symbol. Parse $sym±offset(symkind)
p.symbolReference(a, name, prefix)
}
// fmt.Printf("SYM %s\n", obj.Dconv(&emptyProg, 0, a))
if p.peek() == scanner.EOF {
return
@ -843,7 +855,6 @@ func (p *Parser) setPseudoRegister(addr *obj.Addr, reg string, isStatic bool, pr
//
// Anything else beginning with "<" logs an error if issueError is
// true, otherwise returns (false, obj.ABI0).
//
func (p *Parser) symRefAttrs(name string, issueError bool) (bool, obj.ABI) {
abi := obj.ABI0
isStatic := false

View file

@ -628,7 +628,8 @@ again:
CSELW LT, R2, R3, R4 // 44b0831a
CSINC GT, R1, ZR, R3 // 23c49f9a
CSNEG MI, R1, R2, R3 // 234482da
CSINV CS, R1, R2, R3 // CSINV HS, R1, R2, R3 // 232082da
CSINV CS, R1, R2, R3 // CSINV HS, R1, R2, R3 // 232082da
CSINV HS, R1, R2, R3 // 232082da
CSINVW MI, R2, ZR, R2 // 42409f5a
CINC EQ, R4, R9 // 8914849a
CINCW PL, R2, ZR // 5f44821a
@ -1627,4 +1628,116 @@ again:
MSR R13, ZCR_EL1 // 0d1218d5
MRS ZCR_EL1, R23 // 171238d5
MSR R17, ZCR_EL1 // 111218d5
SYS $32768, R1 // 018008d5
SYS $32768 // 1f8008d5
// TLBI instruction
TLBI VMALLE1IS // 1f8308d5
TLBI VMALLE1 // 1f8708d5
TLBI ALLE2IS // 1f830cd5
TLBI ALLE1IS // 9f830cd5
TLBI VMALLS12E1IS // df830cd5
TLBI ALLE2 // 1f870cd5
TLBI ALLE1 // 9f870cd5
TLBI VMALLS12E1 // df870cd5
TLBI ALLE3IS // 1f830ed5
TLBI ALLE3 // 1f870ed5
TLBI VMALLE1OS // 1f8108d5
TLBI ALLE2OS // 1f810cd5
TLBI ALLE1OS // 9f810cd5
TLBI VMALLS12E1OS // df810cd5
TLBI ALLE3OS // 1f810ed5
TLBI VAE1IS, R0 // 208308d5
TLBI ASIDE1IS, R1 // 418308d5
TLBI VAAE1IS, R2 // 628308d5
TLBI VALE1IS, R3 // a38308d5
TLBI VAALE1IS, R4 // e48308d5
TLBI VAE1, R5 // 258708d5
TLBI ASIDE1, R6 // 468708d5
TLBI VAAE1, R7 // 678708d5
TLBI VALE1, R8 // a88708d5
TLBI VAALE1, R9 // e98708d5
TLBI IPAS2E1IS, R10 // 2a800cd5
TLBI IPAS2LE1IS, R11 // ab800cd5
TLBI VAE2IS, R12 // 2c830cd5
TLBI VALE2IS, R13 // ad830cd5
TLBI IPAS2E1, R14 // 2e840cd5
TLBI IPAS2LE1, R15 // af840cd5
TLBI VAE2, R16 // 30870cd5
TLBI VALE2, R17 // b1870cd5
TLBI VAE3IS, ZR // 3f830ed5
TLBI VALE3IS, R19 // b3830ed5
TLBI VAE3, R20 // 34870ed5
TLBI VALE3, R21 // b5870ed5
TLBI VAE1OS, R22 // 368108d5
TLBI ASIDE1OS, R23 // 578108d5
TLBI VAAE1OS, R24 // 788108d5
TLBI VALE1OS, R25 // b98108d5
TLBI VAALE1OS, R26 // fa8108d5
TLBI RVAE1IS, R27 // 3b8208d5
TLBI RVAAE1IS, ZR // 7f8208d5
TLBI RVALE1IS, R29 // bd8208d5
TLBI RVAALE1IS, R30 // fe8208d5
TLBI RVAE1OS, ZR // 3f8508d5
TLBI RVAAE1OS, R0 // 608508d5
TLBI RVALE1OS, R1 // a18508d5
TLBI RVAALE1OS, R2 // e28508d5
TLBI RVAE1, R3 // 238608d5
TLBI RVAAE1, R4 // 648608d5
TLBI RVALE1, R5 // a58608d5
TLBI RVAALE1, R6 // e68608d5
TLBI RIPAS2E1IS, R7 // 47800cd5
TLBI RIPAS2LE1IS, R8 // c8800cd5
TLBI VAE2OS, R9 // 29810cd5
TLBI VALE2OS, R10 // aa810cd5
TLBI RVAE2IS, R11 // 2b820cd5
TLBI RVALE2IS, R12 // ac820cd5
TLBI IPAS2E1OS, R13 // 0d840cd5
TLBI RIPAS2E1, R14 // 4e840cd5
TLBI RIPAS2E1OS, R15 // 6f840cd5
TLBI IPAS2LE1OS, R16 // 90840cd5
TLBI RIPAS2LE1, R17 // d1840cd5
TLBI RIPAS2LE1OS, ZR // ff840cd5
TLBI RVAE2OS, R19 // 33850cd5
TLBI RVALE2OS, R20 // b4850cd5
TLBI RVAE2, R21 // 35860cd5
TLBI RVALE2, R22 // b6860cd5
TLBI VAE3OS, R23 // 37810ed5
TLBI VALE3OS, R24 // b8810ed5
TLBI RVAE3IS, R25 // 39820ed5
TLBI RVALE3IS, R26 // ba820ed5
TLBI RVAE3OS, R27 // 3b850ed5
TLBI RVALE3OS, ZR // bf850ed5
TLBI RVAE3, R29 // 3d860ed5
TLBI RVALE3, R30 // be860ed5
// DC instruction
DC IVAC, R0 // 207608d5
DC ISW, R1 // 417608d5
DC CSW, R2 // 427a08d5
DC CISW, R3 // 437e08d5
DC ZVA, R4 // 24740bd5
DC CVAC, R5 // 257a0bd5
DC CVAU, R6 // 267b0bd5
DC CIVAC, R7 // 277e0bd5
DC IGVAC, R8 // 687608d5
DC IGSW, R9 // 897608d5
DC IGDVAC, R10 // aa7608d5
DC IGDSW, R11 // cb7608d5
DC CGSW, R12 // 8c7a08d5
DC CGDSW, R13 // cd7a08d5
DC CIGSW, R14 // 8e7e08d5
DC CIGDSW, R15 // cf7e08d5
DC GVA, R16 // 70740bd5
DC GZVA, R17 // 91740bd5
DC CGVAC, ZR // 7f7a0bd5
DC CGDVAC, R19 // b37a0bd5
DC CGVAP, R20 // 747c0bd5
DC CGDVAP, R21 // b57c0bd5
DC CGVADP, R22 // 767d0bd5
DC CGDVADP, R23 // b77d0bd5
DC CIGVAC, R24 // 787e0bd5
DC CIGDVAC, R25 // b97e0bd5
DC CVAP, R26 // 3a7c0bd5
DC CVADP, R27 // 3b7d0bd5
END

View file

@ -134,7 +134,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
CSINV LO, R2, R11, R14 // 4e308bda
CSNEGW HS, R16, R29, R10 // 0a269d5a
CSNEG NE, R21, R19, R11 // ab1693da
//TODO DC
DC IVAC, R1 // 217608d5
DCPS1 $11378 // 418ea5d4
DCPS2 $10699 // 6239a5d4
DCPS3 $24415 // e3ebabd4
@ -397,7 +397,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
SXTH R17, R25 // 393e4093
SXTW R0, R27 // 1b7c4093
SYSL $285440, R12 // 0c5b2cd5
//TODO TLBI
TLBI VAE1IS, R1 // 218308d5
TSTW $0x80000007, R9 // TSTW $2147483655, R9 // 3f0d0172
TST $0xfffffff0, LR // TST $4294967280, R30 // df6f7cf2
TSTW R10@>21, R2 // 5f54ca6a

View file

@ -432,4 +432,14 @@ TEXT errors(SB),$0
STP (R26, R27), 700(R2) // ERROR "cannot use REGTMP as source"
MOVK $0, R10 // ERROR "zero shifts cannot be handled correctly"
MOVK $(0<<32), R10 // ERROR "zero shifts cannot be handled correctly"
TLBI PLDL1KEEP // ERROR "illegal argument"
TLBI VMALLE1IS, R0 // ERROR "extraneous register at operand 2"
TLBI ALLE3OS, ZR // ERROR "extraneous register at operand 2"
TLBI VAE1IS // ERROR "missing register at operand 2"
TLBI RVALE3 // ERROR "missing register at operand 2"
DC PLDL1KEEP // ERROR "illegal argument"
DC VMALLE1IS // ERROR "illegal argument"
DC VAE1IS // ERROR "illegal argument"
DC VAE1IS, R0 // ERROR "illegal argument"
DC IVAC // ERROR "missing register at operand 2"
RET

View file

@ -145,6 +145,19 @@ start:
SRLW X5, X6, X7 // bb535300
SUBW X5, X6, X7 // bb035340
SRAW X5, X6, X7 // bb535340
ADDIW $1, X6 // 1b031300
SLLIW $1, X6 // 1b131300
SRLIW $1, X6 // 1b531300
SRAIW $1, X6 // 1b531340
ADDW X5, X7 // bb835300
SLLW X5, X7 // bb935300
SRLW X5, X7 // bbd35300
SUBW X5, X7 // bb835340
SRAW X5, X7 // bbd35340
ADDW $1, X6 // 1b031300
SLLW $1, X6 // 1b131300
SRLW $1, X6 // 1b531300
SRAW $1, X6 // 1b531340
// 5.3: Load and Store Instructions (RV64I)
LD (X5), X6 // 03b30200

View file

@ -22,5 +22,9 @@ TEXT errors(SB),$0
MOVBU X5, (X6) // ERROR "unsupported unsigned store"
MOVHU X5, (X6) // ERROR "unsupported unsigned store"
MOVWU X5, (X6) // ERROR "unsupported unsigned store"
MOVF F0, F1, F2 // ERROR "illegal MOV instruction"
MOVD F0, F1, F2 // ERROR "illegal MOV instruction"
MOV X10, X11, X12 // ERROR "illegal MOV instruction"
MOVW X10, X11, X12 // ERROR "illegal MOV instruction"
RET

View file

@ -119,7 +119,6 @@ func (p *Package) addToFlag(flag string, args []string) {
// Would be parsed as:
//
// []string{"a", "b:c d", "ef", `g"`}
//
func splitQuoted(s string) (r []string, err error) {
var args []string
arg := make([]rune, len(s))

View file

@ -16,11 +16,11 @@ import (
)
// godefs returns the output for -godefs mode.
func (p *Package) godefs(f *File) string {
func (p *Package) godefs(f *File, args []string) string {
var buf bytes.Buffer
fmt.Fprintf(&buf, "// Code generated by cmd/cgo -godefs; DO NOT EDIT.\n")
fmt.Fprintf(&buf, "// %s %s\n", filepath.Base(os.Args[0]), strings.Join(os.Args[1:], " "))
fmt.Fprintf(&buf, "// %s %s\n", filepath.Base(args[0]), strings.Join(args[1:], " "))
fmt.Fprintf(&buf, "\n")
override := make(map[string]string)

View file

@ -291,6 +291,10 @@ func main() {
usage()
}
// Save original command line arguments for the godefs generated comment. Relative file
// paths in os.Args will be rewritten to absolute file paths in the loop below.
osArgs := make([]string, len(os.Args))
copy(osArgs, os.Args[:])
goFiles := args[i:]
for _, arg := range args[:i] {
@ -390,7 +394,7 @@ func main() {
p.PackagePath = f.Package
p.Record(f)
if *godefs {
os.Stdout.WriteString(p.godefs(f))
os.Stdout.WriteString(p.godefs(f, osArgs))
} else {
p.writeOutput(f, input)
}

View file

@ -57,18 +57,19 @@ func (p *Package) writeDefs() {
fflg.Close()
// Write C main file for using gcc to resolve imports.
fmt.Fprintf(fm, "#include <stddef.h>\n") // For size_t below.
fmt.Fprintf(fm, "int main() { return 0; }\n")
if *importRuntimeCgo {
fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*) __attribute__((unused)), void *a __attribute__((unused)), int c __attribute__((unused)), __SIZE_TYPE__ ctxt __attribute__((unused))) { }\n")
fmt.Fprintf(fm, "__SIZE_TYPE__ _cgo_wait_runtime_init_done(void) { return 0; }\n")
fmt.Fprintf(fm, "void _cgo_release_context(__SIZE_TYPE__ ctxt __attribute__((unused))) { }\n")
fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*) __attribute__((unused)), void *a __attribute__((unused)), int c __attribute__((unused)), size_t ctxt __attribute__((unused))) { }\n")
fmt.Fprintf(fm, "size_t _cgo_wait_runtime_init_done(void) { return 0; }\n")
fmt.Fprintf(fm, "void _cgo_release_context(size_t ctxt __attribute__((unused))) { }\n")
fmt.Fprintf(fm, "char* _cgo_topofstack(void) { return (char*)0; }\n")
} else {
// If we're not importing runtime/cgo, we *are* runtime/cgo,
// which provides these functions. We just need a prototype.
fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*), void *a, int c, __SIZE_TYPE__ ctxt);\n")
fmt.Fprintf(fm, "__SIZE_TYPE__ _cgo_wait_runtime_init_done(void);\n")
fmt.Fprintf(fm, "void _cgo_release_context(__SIZE_TYPE__);\n")
fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*), void *a, int c, size_t ctxt);\n")
fmt.Fprintf(fm, "size_t _cgo_wait_runtime_init_done(void);\n")
fmt.Fprintf(fm, "void _cgo_release_context(size_t);\n")
}
fmt.Fprintf(fm, "void _cgo_allocate(void *a __attribute__((unused)), int c __attribute__((unused))) { }\n")
fmt.Fprintf(fm, "void _cgo_panic(void *a __attribute__((unused)), int c __attribute__((unused))) { }\n")
@ -886,9 +887,9 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
fmt.Fprintf(fgcc, "#pragma GCC diagnostic ignored \"-Wpragmas\"\n")
fmt.Fprintf(fgcc, "#pragma GCC diagnostic ignored \"-Waddress-of-packed-member\"\n")
fmt.Fprintf(fgcc, "extern void crosscall2(void (*fn)(void *), void *, int, __SIZE_TYPE__);\n")
fmt.Fprintf(fgcc, "extern __SIZE_TYPE__ _cgo_wait_runtime_init_done(void);\n")
fmt.Fprintf(fgcc, "extern void _cgo_release_context(__SIZE_TYPE__);\n\n")
fmt.Fprintf(fgcc, "extern void crosscall2(void (*fn)(void *), void *, int, size_t);\n")
fmt.Fprintf(fgcc, "extern size_t _cgo_wait_runtime_init_done(void);\n")
fmt.Fprintf(fgcc, "extern void _cgo_release_context(size_t);\n\n")
fmt.Fprintf(fgcc, "extern char* _cgo_topofstack(void);")
fmt.Fprintf(fgcc, "%s\n", tsanProlog)
fmt.Fprintf(fgcc, "%s\n", msanProlog)
@ -992,7 +993,7 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
fmt.Fprintf(fgcc, "\nCGO_NO_SANITIZE_THREAD")
fmt.Fprintf(fgcc, "\n%s\n", s)
fmt.Fprintf(fgcc, "{\n")
fmt.Fprintf(fgcc, "\t__SIZE_TYPE__ _cgo_ctxt = _cgo_wait_runtime_init_done();\n")
fmt.Fprintf(fgcc, "\tsize_t _cgo_ctxt = _cgo_wait_runtime_init_done();\n")
// The results part of the argument structure must be
// initialized to 0 so the write barriers generated by
// the assignments to these fields in Go are safe.
@ -1561,7 +1562,7 @@ var msanProlog = noMsanProlog
const builtinProlog = `
#line 1 "cgo-builtin-prolog"
#include <stddef.h> /* for ptrdiff_t and size_t below */
#include <stddef.h>
/* Define intgo when compiling with GCC. */
typedef ptrdiff_t intgo;
@ -1604,6 +1605,7 @@ const goStringDef = `
//go:linkname _cgo_runtime_gostring runtime.gostring
func _cgo_runtime_gostring(*_Ctype_char) string
// GoString converts the C string p into a Go string.
func _Cfunc_GoString(p *_Ctype_char) string {
return _cgo_runtime_gostring(p)
}
@ -1613,6 +1615,7 @@ const goStringNDef = `
//go:linkname _cgo_runtime_gostringn runtime.gostringn
func _cgo_runtime_gostringn(*_Ctype_char, int) string
// GoStringN converts the C data p with explicit length l to a Go string.
func _Cfunc_GoStringN(p *_Ctype_char, l _Ctype_int) string {
return _cgo_runtime_gostringn(p, int(l))
}
@ -1622,12 +1625,19 @@ const goBytesDef = `
//go:linkname _cgo_runtime_gobytes runtime.gobytes
func _cgo_runtime_gobytes(unsafe.Pointer, int) []byte
// GoBytes converts the C data p with explicit length l to a Go []byte.
func _Cfunc_GoBytes(p unsafe.Pointer, l _Ctype_int) []byte {
return _cgo_runtime_gobytes(p, int(l))
}
`
const cStringDef = `
// CString converts the Go string s to a C string.
//
// The C string is allocated in the C heap using malloc.
// It is the caller's responsibility to arrange for it to be
// freed, such as by calling C.free (be sure to include stdlib.h
// if C.free is needed).
func _Cfunc_CString(s string) *_Ctype_char {
p := _cgo_cmalloc(uint64(len(s)+1))
pp := (*[1<<30]byte)(p)
@ -1638,6 +1648,12 @@ func _Cfunc_CString(s string) *_Ctype_char {
`
const cBytesDef = `
// CBytes converts the Go []byte slice b to a C array.
//
// The C array is allocated in the C heap using malloc.
// It is the caller's responsibility to arrange for it to be
// freed, such as by calling C.free (be sure to include stdlib.h
// if C.free is needed).
func _Cfunc_CBytes(b []byte) unsafe.Pointer {
p := _cgo_cmalloc(uint64(len(b)))
pp := (*[1<<30]byte)(p)
@ -1830,7 +1846,7 @@ void localCgoCheckResult(Eface val) {
const builtinExportProlog = `
#line 1 "cgo-builtin-export-prolog"
#include <stddef.h> /* for ptrdiff_t below */
#include <stddef.h>
#ifndef GO_CGO_EXPORT_PROLOGUE_H
#define GO_CGO_EXPORT_PROLOGUE_H
@ -1876,7 +1892,7 @@ typedef long long GoInt64;
typedef unsigned long long GoUint64;
typedef GoIntGOINTBITS GoInt;
typedef GoUintGOINTBITS GoUint;
typedef __SIZE_TYPE__ GoUintptr;
typedef size_t GoUintptr;
typedef float GoFloat32;
typedef double GoFloat64;
typedef float _Complex GoComplex64;
@ -1926,5 +1942,5 @@ static void GoInit(void) {
runtime_iscgo = 1;
}
extern __SIZE_TYPE__ _cgo_wait_runtime_init_done(void) __attribute__ ((weak));
extern size_t _cgo_wait_runtime_init_done(void) __attribute__ ((weak));
`

View file

@ -788,12 +788,12 @@ func (state *assignState) assignParamOrReturn(pt *types.Type, n types.Object, is
// field. For things that are not structs (or structs without padding)
// it returns a list of zeros. Example:
//
// type small struct {
// x uint16
// y uint8
// z int32
// w int32
// }
// type small struct {
// x uint16
// y uint8
// z int32
// w int32
// }
//
// For this struct we would return a list [0, 1, 0, 0], meaning that
// we have one byte of padding after the second field, and no bytes of

View file

@ -265,8 +265,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
case ssa.OpAMD64BLSIQ, ssa.OpAMD64BLSIL,
ssa.OpAMD64BLSMSKQ, ssa.OpAMD64BLSMSKL,
ssa.OpAMD64BLSRQ, ssa.OpAMD64BLSRL,
ssa.OpAMD64TZCNTQ, ssa.OpAMD64TZCNTL:
ssa.OpAMD64BLSRQ, ssa.OpAMD64BLSRL:
p := s.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_REG
p.From.Reg = v.Args[0].Reg()
@ -281,6 +280,23 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
p.To.Reg = v.Reg()
p.SetFrom3Reg(v.Args[1].Reg())
case ssa.OpAMD64SHLXLload, ssa.OpAMD64SHLXQload,
ssa.OpAMD64SHRXLload, ssa.OpAMD64SHRXQload:
p := opregreg(s, v.Op.Asm(), v.Reg(), v.Args[1].Reg())
m := obj.Addr{Type: obj.TYPE_MEM, Reg: v.Args[0].Reg()}
ssagen.AddAux(&m, v)
p.SetFrom3(m)
case ssa.OpAMD64SHLXLloadidx1, ssa.OpAMD64SHLXLloadidx4, ssa.OpAMD64SHLXLloadidx8,
ssa.OpAMD64SHRXLloadidx1, ssa.OpAMD64SHRXLloadidx4, ssa.OpAMD64SHRXLloadidx8,
ssa.OpAMD64SHLXQloadidx1, ssa.OpAMD64SHLXQloadidx8,
ssa.OpAMD64SHRXQloadidx1, ssa.OpAMD64SHRXQloadidx8:
p := opregreg(s, v.Op.Asm(), v.Reg(), v.Args[2].Reg())
m := obj.Addr{Type: obj.TYPE_MEM}
memIdx(&m, v)
ssagen.AddAux(&m, v)
p.SetFrom3(m)
case ssa.OpAMD64DIVQU, ssa.OpAMD64DIVLU, ssa.OpAMD64DIVWU:
// Arg[0] (the dividend) is in AX.
// Arg[1] (the divisor) can be in any other register.
@ -289,11 +305,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
r := v.Args[1].Reg()
// Zero extend dividend.
c := s.Prog(x86.AXORL)
c.From.Type = obj.TYPE_REG
c.From.Reg = x86.REG_DX
c.To.Type = obj.TYPE_REG
c.To.Reg = x86.REG_DX
opregreg(s, x86.AXORL, x86.REG_DX, x86.REG_DX)
// Issue divide.
p := s.Prog(v.Op.Asm())
@ -363,11 +375,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
n1.To.Reg = x86.REG_AX
// n % -1 == 0
n2 := s.Prog(x86.AXORL)
n2.From.Type = obj.TYPE_REG
n2.From.Reg = x86.REG_DX
n2.To.Type = obj.TYPE_REG
n2.To.Reg = x86.REG_DX
opregreg(s, x86.AXORL, x86.REG_DX, x86.REG_DX)
// TODO(khr): issue only the -1 fixup code we need.
// For instance, if only the quotient is used, no point in zeroing the remainder.
@ -745,11 +753,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
// If flags aren't live (indicated by v.Aux == nil),
// then we can rewrite MOV $0, AX into XOR AX, AX.
if v.AuxInt == 0 && v.Aux == nil {
p := s.Prog(x86.AXORL)
p.From.Type = obj.TYPE_REG
p.From.Reg = x
p.To.Type = obj.TYPE_REG
p.To.Reg = x
opregreg(s, x86.AXORL, x, x)
break
}
@ -791,7 +795,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
case ssa.OpAMD64MOVQstore, ssa.OpAMD64MOVSSstore, ssa.OpAMD64MOVSDstore, ssa.OpAMD64MOVLstore, ssa.OpAMD64MOVWstore, ssa.OpAMD64MOVBstore, ssa.OpAMD64MOVOstore,
ssa.OpAMD64ADDQmodify, ssa.OpAMD64SUBQmodify, ssa.OpAMD64ANDQmodify, ssa.OpAMD64ORQmodify, ssa.OpAMD64XORQmodify,
ssa.OpAMD64ADDLmodify, ssa.OpAMD64SUBLmodify, ssa.OpAMD64ANDLmodify, ssa.OpAMD64ORLmodify, ssa.OpAMD64XORLmodify,
ssa.OpAMD64MOVBEQstore, ssa.OpAMD64MOVBELstore:
ssa.OpAMD64MOVBEQstore, ssa.OpAMD64MOVBELstore, ssa.OpAMD64MOVBEWstore:
p := s.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_REG
p.From.Reg = v.Args[1].Reg()
@ -1137,15 +1141,14 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
p.SetFrom3Reg(v.Args[0].Reg())
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg()
case ssa.OpAMD64POPCNTQ, ssa.OpAMD64POPCNTL:
case ssa.OpAMD64POPCNTQ, ssa.OpAMD64POPCNTL,
ssa.OpAMD64TZCNTQ, ssa.OpAMD64TZCNTL,
ssa.OpAMD64LZCNTQ, ssa.OpAMD64LZCNTL:
if v.Args[0].Reg() != v.Reg() {
// POPCNT on Intel has a false dependency on the destination register.
// POPCNT/TZCNT/LZCNT have a false dependency on the destination register on Intel cpus.
// TZCNT/LZCNT problem affects pre-Skylake models. See discussion at https://gcc.gnu.org/bugzilla/show_bug.cgi?id=62011#c7.
// Xor register with itself to break the dependency.
p := s.Prog(x86.AXORL)
p.From.Type = obj.TYPE_REG
p.From.Reg = v.Reg()
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg()
opregreg(s, x86.AXORL, v.Reg(), v.Reg())
}
p := s.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_REG

View file

@ -244,6 +244,7 @@ var featureToOpcodes = map[string][]string{
"sse41": {"roundsd"},
"fma": {"vfmadd231sd"},
"movbe": {"movbeqq", "movbeq", "movbell", "movbel", "movbe"},
"lzcnt": {"lzcntq", "lzcntl", "lzcnt"},
}
// Test to use POPCNT instruction, if available

View file

@ -728,8 +728,8 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
p4.To.Type = obj.TYPE_BRANCH
p4.To.SetTarget(p)
p5 := s.Prog(arm64.ACSET)
p5.From.Type = obj.TYPE_REG // assembler encodes conditional bits in Reg
p5.From.Reg = arm64.COND_EQ
p5.From.Type = obj.TYPE_SPECIAL // assembler encodes conditional bits in Offset
p5.From.Offset = int64(arm64.SPOP_EQ)
p5.To.Type = obj.TYPE_REG
p5.To.Reg = out
p2.To.SetTarget(p5)
@ -778,8 +778,8 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
// CSET EQ, Rout
p3 := s.Prog(arm64.ACSET)
p3.From.Type = obj.TYPE_REG
p3.From.Reg = arm64.COND_EQ
p3.From.Type = obj.TYPE_SPECIAL // assembler encodes conditional bits in Offset
p3.From.Offset = int64(arm64.SPOP_EQ)
p3.To.Type = obj.TYPE_REG
p3.To.Reg = out
@ -978,24 +978,27 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
r1 = v.Args[1].Reg()
}
p := s.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_REG // assembler encodes conditional bits in Reg
p.From.Reg = condBits[ssa.Op(v.AuxInt)]
p.From.Type = obj.TYPE_SPECIAL // assembler encodes conditional bits in Offset
condCode := condBits[ssa.Op(v.AuxInt)]
p.From.Offset = int64(condCode)
p.Reg = v.Args[0].Reg()
p.SetFrom3Reg(r1)
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg()
case ssa.OpARM64CSINC, ssa.OpARM64CSINV, ssa.OpARM64CSNEG:
p := s.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_REG // assembler encodes conditional bits in Reg
p.From.Reg = condBits[ssa.Op(v.AuxInt)]
p.From.Type = obj.TYPE_SPECIAL // assembler encodes conditional bits in Offset
condCode := condBits[ssa.Op(v.AuxInt)]
p.From.Offset = int64(condCode)
p.Reg = v.Args[0].Reg()
p.SetFrom3Reg(v.Args[1].Reg())
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg()
case ssa.OpARM64CSETM:
p := s.Prog(arm64.ACSETM)
p.From.Type = obj.TYPE_REG // assembler encodes conditional bits in Reg
p.From.Reg = condBits[ssa.Op(v.AuxInt)]
p.From.Type = obj.TYPE_SPECIAL // assembler encodes conditional bits in Offset
condCode := condBits[ssa.Op(v.AuxInt)]
p.From.Offset = int64(condCode)
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg()
case ssa.OpARM64DUFFZERO:
@ -1107,8 +1110,9 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
ssa.OpARM64NotGreaterEqualF:
// generate boolean values using CSET
p := s.Prog(arm64.ACSET)
p.From.Type = obj.TYPE_REG // assembler encodes conditional bits in Reg
p.From.Reg = condBits[v.Op]
p.From.Type = obj.TYPE_SPECIAL // assembler encodes conditional bits in Offset
condCode := condBits[v.Op]
p.From.Offset = int64(condCode)
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg()
case ssa.OpARM64PRFM:
@ -1173,27 +1177,27 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
}
}
var condBits = map[ssa.Op]int16{
ssa.OpARM64Equal: arm64.COND_EQ,
ssa.OpARM64NotEqual: arm64.COND_NE,
ssa.OpARM64LessThan: arm64.COND_LT,
ssa.OpARM64LessThanU: arm64.COND_LO,
ssa.OpARM64LessEqual: arm64.COND_LE,
ssa.OpARM64LessEqualU: arm64.COND_LS,
ssa.OpARM64GreaterThan: arm64.COND_GT,
ssa.OpARM64GreaterThanU: arm64.COND_HI,
ssa.OpARM64GreaterEqual: arm64.COND_GE,
ssa.OpARM64GreaterEqualU: arm64.COND_HS,
ssa.OpARM64LessThanF: arm64.COND_MI, // Less than
ssa.OpARM64LessEqualF: arm64.COND_LS, // Less than or equal to
ssa.OpARM64GreaterThanF: arm64.COND_GT, // Greater than
ssa.OpARM64GreaterEqualF: arm64.COND_GE, // Greater than or equal to
var condBits = map[ssa.Op]arm64.SpecialOperand{
ssa.OpARM64Equal: arm64.SPOP_EQ,
ssa.OpARM64NotEqual: arm64.SPOP_NE,
ssa.OpARM64LessThan: arm64.SPOP_LT,
ssa.OpARM64LessThanU: arm64.SPOP_LO,
ssa.OpARM64LessEqual: arm64.SPOP_LE,
ssa.OpARM64LessEqualU: arm64.SPOP_LS,
ssa.OpARM64GreaterThan: arm64.SPOP_GT,
ssa.OpARM64GreaterThanU: arm64.SPOP_HI,
ssa.OpARM64GreaterEqual: arm64.SPOP_GE,
ssa.OpARM64GreaterEqualU: arm64.SPOP_HS,
ssa.OpARM64LessThanF: arm64.SPOP_MI, // Less than
ssa.OpARM64LessEqualF: arm64.SPOP_LS, // Less than or equal to
ssa.OpARM64GreaterThanF: arm64.SPOP_GT, // Greater than
ssa.OpARM64GreaterEqualF: arm64.SPOP_GE, // Greater than or equal to
// The following condition codes have unordered to handle comparisons related to NaN.
ssa.OpARM64NotLessThanF: arm64.COND_PL, // Greater than, equal to, or unordered
ssa.OpARM64NotLessEqualF: arm64.COND_HI, // Greater than or unordered
ssa.OpARM64NotGreaterThanF: arm64.COND_LE, // Less than, equal to or unordered
ssa.OpARM64NotGreaterEqualF: arm64.COND_LT, // Less than or unordered
ssa.OpARM64NotLessThanF: arm64.SPOP_PL, // Greater than, equal to, or unordered
ssa.OpARM64NotLessEqualF: arm64.SPOP_HI, // Greater than or unordered
ssa.OpARM64NotGreaterThanF: arm64.SPOP_LE, // Less than, equal to or unordered
ssa.OpARM64NotGreaterEqualF: arm64.SPOP_LT, // Less than or unordered
}
var blockJump = map[ssa.BlockKind]struct {

View file

@ -41,7 +41,9 @@ func readGopackHeader(r *bufio.Reader) (name string, size int, err error) {
// start of the file before calling this function. The hdr result
// is the string before the export data, either "$$" or "$$B".
//
func FindExportData(r *bufio.Reader) (hdr string, err error) {
// If size is non-negative, it's the number of bytes of export data
// still available to read from r.
func FindExportData(r *bufio.Reader) (hdr string, size int, err error) {
// Read first line to make sure this is an object file.
line, err := r.ReadSlice('\n')
if err != nil {
@ -52,7 +54,7 @@ func FindExportData(r *bufio.Reader) (hdr string, err error) {
if string(line) == "!<arch>\n" {
// Archive file. Scan to __.PKGDEF.
var name string
if name, _, err = readGopackHeader(r); err != nil {
if name, size, err = readGopackHeader(r); err != nil {
return
}
@ -76,6 +78,7 @@ func FindExportData(r *bufio.Reader) (hdr string, err error) {
err = fmt.Errorf("not a Go object file")
return
}
size -= len(line)
// Skip over object header to export data.
// Begins after first line starting with $$.
@ -84,6 +87,7 @@ func FindExportData(r *bufio.Reader) (hdr string, err error) {
err = fmt.Errorf("can't find export data (%v)", err)
return
}
size -= len(line)
}
hdr = string(line)

View file

@ -10,6 +10,7 @@ import (
"cmd/compile/internal/types2"
"fmt"
"go/build"
"internal/pkgbits"
"io"
"io/ioutil"
"os"
@ -27,7 +28,6 @@ var pkgExts = [...]string{".a", ".o"}
// the build.Default build.Context). A relative srcDir is interpreted
// relative to the current working directory.
// If no file was found, an empty filename is returned.
//
func FindPkg(path, srcDir string) (filename, id string) {
if path == "" {
return
@ -83,7 +83,6 @@ func FindPkg(path, srcDir string) (filename, id string) {
// Import imports a gc-generated package given its import path and srcDir, adds
// the corresponding package object to the packages map, and returns the object.
// The packages map must contain all packages already imported.
//
func Import(packages map[string]*types2.Package, path, srcDir string, lookup func(path string) (io.ReadCloser, error)) (pkg *types2.Package, err error) {
var rc io.ReadCloser
var id string
@ -134,9 +133,9 @@ func Import(packages map[string]*types2.Package, path, srcDir string, lookup fun
}
defer rc.Close()
var hdr string
buf := bufio.NewReader(rc)
if hdr, err = FindExportData(buf); err != nil {
hdr, size, err := FindExportData(buf)
if err != nil {
return
}
@ -146,17 +145,33 @@ func Import(packages map[string]*types2.Package, path, srcDir string, lookup fun
case "$$B\n":
var data []byte
data, err = ioutil.ReadAll(buf)
var r io.Reader = buf
if size >= 0 {
r = io.LimitReader(r, int64(size))
}
data, err = ioutil.ReadAll(r)
if err != nil {
break
}
if len(data) == 0 {
err = fmt.Errorf("import %q: missing export data", path)
break
}
exportFormat := data[0]
s := string(data[1:])
// The indexed export format starts with an 'i'; the older
// binary export format starts with a 'c', 'd', or 'v'
// (from "version"). Select appropriate importer.
if len(data) > 0 && data[0] == 'i' {
pkg, err = ImportData(packages, string(data[1:]), id)
} else {
switch exportFormat {
case 'u':
s = s[:strings.Index(s, "\n$$\n")]
input := pkgbits.NewPkgDecoder(id, s)
pkg = ReadPackage(nil, packages, input)
case 'i':
pkg, err = ImportData(packages, s, id)
default:
err = fmt.Errorf("import %q: old binary export format no longer supported (recompile library)", path)
}

View file

@ -115,10 +115,14 @@ func TestImportTestdata(t *testing.T) {
}
testfiles := map[string][]string{
"exports.go": {"go/ast", "go/token"},
"exports.go": {"go/ast", "go/token"},
"generics.go": nil,
}
if !goexperiment.Unified {
testfiles["generics.go"] = nil
if goexperiment.Unified {
// TODO(mdempsky): Fix test below to flatten the transitive
// Package.Imports graph. Unified IR is more precise about
// recreating the package import graph.
testfiles["exports.go"] = []string{"go/ast"}
}
for testfile, wantImports := range testfiles {
@ -326,6 +330,14 @@ func verifyInterfaceMethodRecvs(t *testing.T, named *types2.Named, level int) {
return // not an interface
}
// The unified IR importer always sets interface method receiver
// parameters to point to the Interface type, rather than the Named.
// See #49906.
var want types2.Type = named
if goexperiment.Unified {
want = iface
}
// check explicitly declared methods
for i := 0; i < iface.NumExplicitMethods(); i++ {
m := iface.ExplicitMethod(i)
@ -334,7 +346,7 @@ func verifyInterfaceMethodRecvs(t *testing.T, named *types2.Named, level int) {
t.Errorf("%s: missing receiver type", m)
continue
}
if recv.Type() != named {
if recv.Type() != want {
t.Errorf("%s: got recv type %s; want %s", m, recv.Type(), named)
}
}

View file

@ -951,11 +951,11 @@ var IsIntrinsicCall = func(*CallExpr) bool { return false }
// instead of computing both. SameSafeExpr assumes that l and r are
// used in the same statement or expression. In order for it to be
// safe to reuse l or r, they must:
// * be the same expression
// * not have side-effects (no function calls, no channel ops);
// however, panics are ok
// * not cause inappropriate aliasing; e.g. two string to []byte
// conversions, must result in two distinct slices
// * be the same expression
// * not have side-effects (no function calls, no channel ops);
// however, panics are ok
// * not cause inappropriate aliasing; e.g. two string to []byte
// conversions, must result in two distinct slices
//
// The handling of OINDEXMAP is subtle. OINDEXMAP can occur both
// as an lvalue (map assignment) and an rvalue (map access). This is

View file

@ -105,7 +105,6 @@ func (o Op) GoString() string {
//
// %v Go syntax ("+", "<-", "print")
// %+v Debug syntax ("ADD", "RECV", "PRINT")
//
func (o Op) Format(s fmt.State, verb rune) {
switch verb {
default:
@ -129,7 +128,6 @@ func (o Op) Format(s fmt.State, verb rune) {
// %v Go syntax
// %L Go syntax followed by " (type T)" if type is known.
// %+v Debug syntax, as in Dump.
//
func fmtNode(n Node, s fmt.State, verb rune) {
// %+v prints Dump.
// Otherwise we print Go syntax.
@ -926,7 +924,6 @@ func ellipsisIf(b bool) string {
// %v Go syntax, semicolon-separated
// %.v Go syntax, comma-separated
// %+v Debug syntax, as in DumpList.
//
func (l Nodes) Format(s fmt.State, verb rune) {
if s.Flag('+') && verb == 'v' {
// %+v is DumpList output

View file

@ -27,7 +27,6 @@ import (
// The embedding struct should also fill in n.op in its constructor,
// for more useful panic messages when invalid methods are called,
// instead of implementing Op itself.
//
type miniNode struct {
pos src.XPos // uint32
op Op // uint8

View file

@ -14,52 +14,22 @@ import (
"cmd/internal/bio"
)
// writeNewExportFunc is a hook that can be added to append extra
// export data after the normal export data section. It allows
// experimenting with new export data format designs without requiring
// immediate support in the go/internal or x/tools importers.
var writeNewExportFunc func(out io.Writer)
func WriteExports(out *bio.Writer) {
// When unified IR exports are enable, we simply append it to the
// end of the normal export data (with compiler extensions
// disabled), and write an extra header giving its size.
//
// If the compiler sees this header, it knows to read the new data
// instead; meanwhile the go/types importers will silently ignore it
// and continue processing the old export instead.
//
// This allows us to experiment with changes to the new export data
// format without needing to update the go/internal/gcimporter or
// (worse) x/tools/go/gcexportdata.
var data bytes.Buffer
useNewExport := writeNewExportFunc != nil
var old, new bytes.Buffer
typecheck.WriteExports(&old, !useNewExport)
if useNewExport {
writeNewExportFunc(&new)
}
oldLen := old.Len()
newLen := new.Len()
if useNewExport {
fmt.Fprintf(out, "\nnewexportsize %v\n", newLen)
if base.Debug.Unified != 0 {
data.WriteByte('u')
writeUnifiedExport(&data)
} else {
typecheck.WriteExports(&data, true)
}
// The linker also looks for the $$ marker - use char after $$ to distinguish format.
out.WriteString("\n$$B\n") // indicate binary export format
io.Copy(out, &old)
io.Copy(out, &data)
out.WriteString("\n$$\n")
io.Copy(out, &new)
if base.Debug.Export != 0 {
fmt.Printf("BenchmarkExportSize:%s 1 %d bytes\n", base.Ctxt.Pkgpath, oldLen)
if useNewExport {
fmt.Printf("BenchmarkNewExportSize:%s 1 %d bytes\n", base.Ctxt.Pkgpath, newLen)
}
fmt.Printf("BenchmarkExportSize:%s 1 %d bytes\n", base.Ctxt.Pkgpath, data.Len())
}
}

View file

@ -8,10 +8,10 @@ import (
"errors"
"fmt"
"internal/buildcfg"
"internal/pkgbits"
"os"
pathpkg "path"
"runtime"
"strconv"
"strings"
"unicode"
"unicode/utf8"
@ -28,22 +28,6 @@ import (
"cmd/internal/objabi"
)
// haveLegacyImports records whether we've imported any packages
// without a new export data section. This is useful for experimenting
// with new export data format designs, when you need to support
// existing tests that manually compile files with inconsistent
// compiler flags.
var haveLegacyImports = false
// newReadImportFunc is an extension hook for experimenting with new
// export data formats. If a new export data payload was written out
// for an imported package by overloading writeNewExportFunc, then
// that payload will be mapped into memory and passed to
// newReadImportFunc.
var newReadImportFunc = func(data string, pkg1 *types.Pkg, env *types2.Context, packages map[string]*types2.Package) (pkg2 *types2.Package, err error) {
panic("unexpected new export data payload")
}
type gcimports struct {
ctxt *types2.Context
packages map[string]*types2.Package
@ -220,7 +204,7 @@ func readImportFile(path string, target *ir.Package, env *types2.Context, packag
}
defer f.Close()
r, end, newsize, err := findExportData(f)
r, end, err := findExportData(f)
if err != nil {
return
}
@ -229,41 +213,40 @@ func readImportFile(path string, target *ir.Package, env *types2.Context, packag
fmt.Printf("importing %s (%s)\n", path, f.Name())
}
if newsize != 0 {
// We have unified IR data. Map it, and feed to the importers.
end -= newsize
var data string
data, err = base.MapFile(r.File(), end, newsize)
if err != nil {
return
c, err := r.ReadByte()
if err != nil {
return
}
pos := r.Offset()
// Map export data section into memory as a single large
// string. This reduces heap fragmentation and allows returning
// individual substrings very efficiently.
var data string
data, err = base.MapFile(r.File(), pos, end-pos)
if err != nil {
return
}
switch c {
case 'u':
if !buildcfg.Experiment.Unified {
base.Fatalf("unexpected export data format")
}
pkg2, err = newReadImportFunc(data, pkg1, env, packages)
} else {
// We only have old data. Oh well, fall back to the legacy importers.
haveLegacyImports = true
// TODO(mdempsky): This seems a bit clunky.
data = strings.TrimSuffix(data, "\n$$\n")
var c byte
switch c, err = r.ReadByte(); {
case err != nil:
return
pr := pkgbits.NewPkgDecoder(pkg1.Path, data)
case c != 'i':
// Indexed format is distinguished by an 'i' byte,
// whereas previous export formats started with 'c', 'd', or 'v'.
err = fmt.Errorf("unexpected package format byte: %v", c)
return
}
// Read package descriptors for both types2 and compiler backend.
readPackage(newPkgReader(pr), pkg1)
pkg2 = importer.ReadPackage(env, packages, pr)
pos := r.Offset()
// Map string (and data) section into memory as a single large
// string. This reduces heap fragmentation and allows
// returning individual substrings very efficiently.
var data string
data, err = base.MapFile(r.File(), pos, end-pos)
if err != nil {
return
case 'i':
if buildcfg.Experiment.Unified {
base.Fatalf("unexpected export data format")
}
typecheck.ReadImports(pkg1, data)
@ -274,6 +257,12 @@ func readImportFile(path string, target *ir.Package, env *types2.Context, packag
return
}
}
default:
// Indexed format is distinguished by an 'i' byte,
// whereas previous export formats started with 'c', 'd', or 'v'.
err = fmt.Errorf("unexpected package format byte: %v", c)
return
}
err = addFingerprint(path, f, end)
@ -283,7 +272,7 @@ func readImportFile(path string, target *ir.Package, env *types2.Context, packag
// findExportData returns a *bio.Reader positioned at the start of the
// binary export data section, and a file offset for where to stop
// reading.
func findExportData(f *os.File) (r *bio.Reader, end, newsize int64, err error) {
func findExportData(f *os.File) (r *bio.Reader, end int64, err error) {
r = bio.NewReader(f)
// check object header
@ -326,14 +315,6 @@ func findExportData(f *os.File) (r *bio.Reader, end, newsize int64, err error) {
// process header lines
for !strings.HasPrefix(line, "$$") {
if strings.HasPrefix(line, "newexportsize ") {
fields := strings.Fields(line)
newsize, err = strconv.ParseInt(fields[1], 10, 64)
if err != nil {
return
}
}
line, err = r.ReadString('\n')
if err != nil {
return

View file

@ -27,7 +27,7 @@ import (
func LoadPackage(filenames []string) {
base.Timer.Start("fe", "parse")
mode := syntax.CheckBranches | syntax.AllowGenerics
mode := syntax.CheckBranches
// Limit the number of simultaneously open files.
sem := make(chan struct{}, runtime.GOMAXPROCS(0)+10)

View file

@ -442,9 +442,21 @@ func (r *reader) doTyp() *types.Type {
return r.structType()
case pkgbits.TypeInterface:
return r.interfaceType()
case pkgbits.TypeUnion:
return r.unionType()
}
}
func (r *reader) unionType() *types.Type {
terms := make([]*types.Type, r.Len())
tildes := make([]bool, len(terms))
for i := range terms {
tildes[i] = r.Bool()
terms[i] = r.typ()
}
return types.NewUnion(terms, tildes)
}
func (r *reader) interfaceType() *types.Type {
tpkg := types.LocalPkg // TODO(mdempsky): Remove after iexport is gone.
@ -577,10 +589,6 @@ func (pr *pkgReader) objIdx(idx int, implicits, explicits []*types.Type) ir.Node
if pri, ok := objReader[sym]; ok {
return pri.pr.objIdx(pri.idx, nil, explicits)
}
if haveLegacyImports {
assert(len(explicits) == 0)
return typecheck.Resolve(ir.NewIdent(src.NoXPos, sym))
}
base.Fatalf("unresolved stub: %v", sym)
}
@ -1960,12 +1968,6 @@ func InlineCall(call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.InlinedCallExp
pri, ok := bodyReader[fn]
if !ok {
// Assume it's an imported function or something that we don't
// have access to in quirks mode.
if haveLegacyImports {
return nil
}
base.FatalfAt(call.Pos(), "missing function body for call to %v", fn)
}

View file

@ -16,7 +16,6 @@ import (
"sort"
"cmd/compile/internal/base"
"cmd/compile/internal/importer"
"cmd/compile/internal/inline"
"cmd/compile/internal/ir"
"cmd/compile/internal/typecheck"
@ -34,38 +33,38 @@ var localPkgReader *pkgReader
//
// The pipeline contains 2 steps:
//
// (1) Generate package export data "stub".
// 1) Generate package export data "stub".
//
// (2) Generate package IR from package export data.
// 2) Generate package IR from package export data.
//
// The package data "stub" at step (1) contains everything from the local package,
// but nothing that have been imported. When we're actually writing out export data
// to the output files (see writeNewExport function), we run the "linker", which does
// a few things:
//
// + Updates compiler extensions data (e.g., inlining cost, escape analysis results).
// + Updates compiler extensions data (e.g., inlining cost, escape analysis results).
//
// + Handles re-exporting any transitive dependencies.
// + Handles re-exporting any transitive dependencies.
//
// + Prunes out any unnecessary details (e.g., non-inlineable functions, because any
// downstream importers only care about inlinable functions).
// + Prunes out any unnecessary details (e.g., non-inlineable functions, because any
// downstream importers only care about inlinable functions).
//
// The source files are typechecked twice, once before writing export data
// using types2 checker, once after read export data using gc/typecheck.
// This duplication of work will go away once we always use types2 checker,
// we can remove the gc/typecheck pass. The reason it is still here:
//
// + It reduces engineering costs in maintaining a fork of typecheck
// (e.g., no need to backport fixes like CL 327651).
// + It reduces engineering costs in maintaining a fork of typecheck
// (e.g., no need to backport fixes like CL 327651).
//
// + It makes it easier to pass toolstash -cmp.
// + It makes it easier to pass toolstash -cmp.
//
// + Historically, we would always re-run the typechecker after import, even though
// we know the imported data is valid. It's not ideal, but also not causing any
// problem either.
// + Historically, we would always re-run the typechecker after import, even though
// we know the imported data is valid. It's not ideal, but also not causing any
// problem either.
//
// + There's still transformation that being done during gc/typecheck, like rewriting
// multi-valued function call, or transform ir.OINDEX -> ir.OINDEXMAP.
// + There's still transformation that being done during gc/typecheck, like rewriting
// multi-valued function call, or transform ir.OINDEX -> ir.OINDEXMAP.
//
// Using syntax+types2 tree, which already has a complete representation of generics,
// the unified IR has the full typed AST for doing introspection during step (1).
@ -74,17 +73,6 @@ var localPkgReader *pkgReader
func unified(noders []*noder) {
inline.NewInline = InlineCall
writeNewExportFunc = writeNewExport
newReadImportFunc = func(data string, pkg1 *types.Pkg, ctxt *types2.Context, packages map[string]*types2.Package) (pkg2 *types2.Package, err error) {
pr := pkgbits.NewPkgDecoder(pkg1.Path, data)
// Read package descriptors for both types2 and compiler backend.
readPackage(newPkgReader(pr), pkg1)
pkg2 = importer.ReadPackage(ctxt, packages, pr)
return
}
data := writePkgStub(noders)
// We already passed base.Flag.Lang to types2 to handle validating
@ -266,7 +254,7 @@ func readPackage(pr *pkgReader, importpkg *types.Pkg) {
}
}
func writeNewExport(out io.Writer) {
func writeUnifiedExport(out io.Writer) {
l := linker{
pw: pkgbits.NewPkgEncoder(base.Debug.SyncFrames),
@ -332,5 +320,5 @@ func writeNewExport(out io.Writer) {
w.Flush()
}
l.pw.DumpTo(out)
base.Ctxt.Fingerprint = l.pw.DumpTo(out)
}

View file

@ -733,6 +733,41 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg()
case ssa.OpPPC64ADDC, ssa.OpPPC64ADDE, ssa.OpPPC64SUBC, ssa.OpPPC64SUBE:
r := v.Reg0() // CA is the first, implied argument.
r1 := v.Args[0].Reg()
r2 := v.Args[1].Reg()
p := s.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_REG
p.From.Reg = r2
p.Reg = r1
p.To.Type = obj.TYPE_REG
p.To.Reg = r
case ssa.OpPPC64ADDZEzero, ssa.OpPPC64SUBZEzero:
p := s.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_REG
p.From.Reg = ppc64.REG_R0
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg()
case ssa.OpPPC64ADDCconst:
p := s.Prog(v.Op.Asm())
p.Reg = v.Args[0].Reg()
p.From.Type = obj.TYPE_CONST
p.From.Offset = v.AuxInt
p.To.Type = obj.TYPE_REG
// Output is a pair, the second is the CA, which is implied.
p.To.Reg = v.Reg0()
case ssa.OpPPC64SUBCconst:
p := s.Prog(v.Op.Asm())
p.SetFrom3Const(v.AuxInt)
p.From.Type = obj.TYPE_REG
p.From.Reg = v.Args[0].Reg()
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg0()
case ssa.OpPPC64SUBFCconst:
p := s.Prog(v.Op.Asm())
p.SetFrom3Const(v.AuxInt)

View file

@ -667,10 +667,10 @@ var kinds = []int{
// tflag is documented in reflect/type.go.
//
// tflag values must be kept in sync with copies in:
// cmd/compile/internal/reflectdata/reflect.go
// cmd/link/internal/ld/decodesym.go
// reflect/type.go
// runtime/type.go
// - cmd/compile/internal/reflectdata/reflect.go
// - cmd/link/internal/ld/decodesym.go
// - reflect/type.go
// - runtime/type.go
const (
tflagUncommon = 1 << 0
tflagExtraStar = 1 << 1
@ -1527,7 +1527,6 @@ func (a typesByString) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
// use bitmaps for objects up to 64 kB in size.
//
// Also known to reflect/type.go.
//
const maxPtrmaskBytes = 2048
// GCSym returns a data symbol containing GC information for type t, along

View file

@ -340,6 +340,22 @@ var combine = map[[2]Op]Op{
[2]Op{OpAMD64DIVSDload, OpAMD64LEAQ1}: OpAMD64DIVSDloadidx1,
[2]Op{OpAMD64DIVSDload, OpAMD64LEAQ8}: OpAMD64DIVSDloadidx8,
[2]Op{OpAMD64SHLXLload, OpAMD64ADDQ}: OpAMD64SHLXLloadidx1,
[2]Op{OpAMD64SHLXQload, OpAMD64ADDQ}: OpAMD64SHLXQloadidx1,
[2]Op{OpAMD64SHRXLload, OpAMD64ADDQ}: OpAMD64SHRXLloadidx1,
[2]Op{OpAMD64SHRXQload, OpAMD64ADDQ}: OpAMD64SHRXQloadidx1,
[2]Op{OpAMD64SHLXLload, OpAMD64LEAQ1}: OpAMD64SHLXLloadidx1,
[2]Op{OpAMD64SHLXLload, OpAMD64LEAQ4}: OpAMD64SHLXLloadidx4,
[2]Op{OpAMD64SHLXLload, OpAMD64LEAQ8}: OpAMD64SHLXLloadidx8,
[2]Op{OpAMD64SHLXQload, OpAMD64LEAQ1}: OpAMD64SHLXQloadidx1,
[2]Op{OpAMD64SHLXQload, OpAMD64LEAQ8}: OpAMD64SHLXQloadidx8,
[2]Op{OpAMD64SHRXLload, OpAMD64LEAQ1}: OpAMD64SHRXLloadidx1,
[2]Op{OpAMD64SHRXLload, OpAMD64LEAQ4}: OpAMD64SHRXLloadidx4,
[2]Op{OpAMD64SHRXLload, OpAMD64LEAQ8}: OpAMD64SHRXLloadidx8,
[2]Op{OpAMD64SHRXQload, OpAMD64LEAQ1}: OpAMD64SHRXQloadidx1,
[2]Op{OpAMD64SHRXQload, OpAMD64LEAQ8}: OpAMD64SHRXQloadidx8,
// 386
[2]Op{Op386MOVBload, Op386ADDL}: Op386MOVBloadidx1,
[2]Op{Op386MOVWload, Op386ADDL}: Op386MOVWloadidx1,

View file

@ -76,10 +76,10 @@ type Block struct {
// d.Preds = [?, {b,1}, ?]
// These indexes allow us to edit the CFG in constant time.
// In addition, it informs phi ops in degenerate cases like:
// b:
// if k then c else c
// c:
// v = Phi(x, y)
// b:
// if k then c else c
// c:
// v = Phi(x, y)
// Then the indexes tell you whether x is chosen from
// the if or else branch from b.
// b.Succs = [{c,0},{c,1}]
@ -105,6 +105,7 @@ func (e Edge) String() string {
return fmt.Sprintf("{%v,%d}", e.b, e.i)
}
// BlockKind is the kind of SSA block.
// kind controls successors
// ------------------------------------------
// Exit [return mem] []

View file

@ -11,11 +11,11 @@ import "cmd/internal/src"
//
// Search for basic blocks that look like
//
// bb0 bb0
// | \ / \
// | bb1 or bb1 bb2 <- trivial if/else blocks
// | / \ /
// bb2 bb3
// bb0 bb0
// | \ / \
// | bb1 or bb1 bb2 <- trivial if/else blocks
// | / \ /
// bb2 bb3
//
// where the intermediate blocks are mostly empty (with no side-effects);
// rewrite Phis in the postdominator as CondSelects.

View file

@ -24,10 +24,10 @@ import (
// Compile is the main entry point for this package.
// Compile modifies f so that on return:
// · all Values in f map to 0 or 1 assembly instructions of the target architecture
// · the order of f.Blocks is the order to emit the Blocks
// · the order of b.Values is the order to emit the Values in each Block
// · f has a non-nil regAlloc field
// - all Values in f map to 0 or 1 assembly instructions of the target architecture
// - the order of f.Blocks is the order to emit the Blocks
// - the order of b.Values is the order to emit the Values in each Block
// - f has a non-nil regAlloc field
func Compile(f *Func) {
// TODO: debugging - set flags to control verbosity of compiler,
// which phases to dump IR before/after, etc.
@ -250,8 +250,8 @@ var GenssaDump map[string]bool = make(map[string]bool) // names of functions to
// version is used as a regular expression to match the phase name(s).
//
// Special cases that have turned out to be useful:
// ssa/check/on enables checking after each phase
// ssa/all/time enables time reporting for all phases
// - ssa/check/on enables checking after each phase
// - ssa/all/time enables time reporting for all phases
//
// See gc/lex.go for dissection of the option string.
// Example uses:
@ -259,7 +259,6 @@ var GenssaDump map[string]bool = make(map[string]bool) // names of functions to
// GO_GCFLAGS=-d=ssa/generic_cse/time,ssa/generic_cse/stats,ssa/generic_cse/debug=3 ./make.bash
//
// BOOT_GO_GCFLAGS=-d='ssa/~^.*scc$/off' GO_GCFLAGS='-d=ssa/~^.*scc$/off' ./make.bash
//
func PhaseOption(phase, flag string, val int, valString string) string {
switch phase {
case "", "help":

View file

@ -239,6 +239,7 @@ func NewConfig(arch string, types Types, ctxt *obj.Link, optimize, softfloat boo
c.registers = registersPPC64[:]
c.gpRegMask = gpRegMaskPPC64
c.fpRegMask = fpRegMaskPPC64
c.specialRegMask = specialRegMaskPPC64
c.intParamRegs = paramIntRegPPC64
c.floatParamRegs = paramFloatRegPPC64
c.FPReg = framepointerRegPPC64

View file

@ -428,7 +428,6 @@ func (sc *slotCanonicalizer) canonSlot(idx SlKeyIdx) LocalSlot {
// This function examines the live OpArg{Int,Float}Reg values and
// synthesizes new (dead) values for the non-live params or the
// non-live pieces of partially live params.
//
func PopulateABIInRegArgOps(f *Func) {
pri := f.ABISelf.ABIAnalyzeFuncType(f.Type.FuncType())

View file

@ -93,7 +93,6 @@ var optimizedLibs = (!strings.Contains(gogcflags, "-N") && !strings.Contains(gog
// go test debug_test.go -args -u
// (for Delve)
// go test debug_test.go -args -u -d
//
func TestNexting(t *testing.T) {
testenv.SkipFlaky(t, 37404)

View file

@ -820,12 +820,12 @@ func (f *Func) invalidateCFG() {
}
// DebugHashMatch reports whether environment variable evname
// 1) is empty (this is a special more-quickly implemented case of 3)
// 2) is "y" or "Y"
// 3) is a suffix of the sha1 hash of name
// 4) is a suffix of the environment variable
// fmt.Sprintf("%s%d", evname, n)
// provided that all such variables are nonempty for 0 <= i <= n
// 1) is empty (this is a special more-quickly implemented case of 3)
// 2) is "y" or "Y"
// 3) is a suffix of the sha1 hash of name
// 4) is a suffix of the environment variable
// fmt.Sprintf("%s%d", evname, n)
// provided that all such variables are nonempty for 0 <= i <= n
// Otherwise it returns false.
// When true is returned the message
// "%s triggered %s\n", evname, name

View file

@ -34,7 +34,7 @@ package ssa
// TODO(matloob): Choose better names for Fun, Bloc, Goto, etc.
// TODO(matloob): Write a parser for the Func disassembly. Maybe
// the parser can be used instead of Fun.
// the parser can be used instead of Fun.
import (
"cmd/compile/internal/types"

View file

@ -8,21 +8,21 @@ package ssa
// of an If block can be derived from its predecessor If block, in
// some such cases, we can redirect the predecessor If block to the
// corresponding successor block directly. For example:
// p:
// v11 = Less64 <bool> v10 v8
// If v11 goto b else u
// b: <- p ...
// v17 = Leq64 <bool> v10 v8
// If v17 goto s else o
// p:
// v11 = Less64 <bool> v10 v8
// If v11 goto b else u
// b: <- p ...
// v17 = Leq64 <bool> v10 v8
// If v17 goto s else o
// We can redirect p to s directly.
//
// The implementation here borrows the framework of the prove pass.
// 1, Traverse all blocks of function f to find If blocks.
// 2, For any If block b, traverse all its predecessors to find If blocks.
// 3, For any If block predecessor p, update relationship p->b.
// 4, Traverse all successors of b.
// 5, For any successor s of b, try to update relationship b->s, if a
// contradiction is found then redirect p to another successor of b.
// 1, Traverse all blocks of function f to find If blocks.
// 2, For any If block b, traverse all its predecessors to find If blocks.
// 3, For any If block predecessor p, update relationship p->b.
// 4, Traverse all successors of b.
// 5, For any successor s of b, try to update relationship b->s, if a
// contradiction is found then redirect p to another successor of b.
func fuseBranchRedirect(f *Func) bool {
ft := newFactsTable(f)
ft.checkpoint()

View file

@ -306,7 +306,7 @@ func init() {
{name: "BSRL", argLength: 1, reg: gp11, asm: "BSRL", clobberFlags: true}, // arg0 # of high-order zeroes ; undef if zero
{name: "BSRW", argLength: 1, reg: gp11, asm: "BSRW", clobberFlags: true}, // arg0 # of high-order zeroes ; undef if zero
{name: "BSWAPL", argLength: 1, reg: gp11, asm: "BSWAPL", resultInArg0: true, clobberFlags: true}, // arg0 swap bytes
{name: "BSWAPL", argLength: 1, reg: gp11, asm: "BSWAPL", resultInArg0: true}, // arg0 swap bytes
{name: "SQRTSD", argLength: 1, reg: fp11, asm: "SQRTSD"}, // sqrt(arg0)
{name: "SQRTSS", argLength: 1, reg: fp11, asm: "SQRTSS"}, // sqrt(arg0), float32

View file

@ -98,10 +98,14 @@
// However, for zero-extended values, we can cheat a bit, and calculate
// BSR(x<<1 + 1), which is guaranteed to be non-zero, and which conveniently
// places the index of the highest set bit where we want it.
(BitLen64 <t> x) => (ADDQconst [1] (CMOVQEQ <t> (Select0 <t> (BSRQ x)) (MOVQconst <t> [-1]) (Select1 <types.TypeFlags> (BSRQ x))))
(BitLen32 x) => (Select0 (BSRQ (LEAQ1 <typ.UInt64> [1] (MOVLQZX <typ.UInt64> x) (MOVLQZX <typ.UInt64> x))))
(BitLen16 x) => (BSRL (LEAL1 <typ.UInt32> [1] (MOVWQZX <typ.UInt32> x) (MOVWQZX <typ.UInt32> x)))
(BitLen8 x) => (BSRL (LEAL1 <typ.UInt32> [1] (MOVBQZX <typ.UInt32> x) (MOVBQZX <typ.UInt32> x)))
// For GOAMD64>=3, BitLen can be calculated by OperandSize - LZCNT(x).
(BitLen64 <t> x) && buildcfg.GOAMD64 < 3 => (ADDQconst [1] (CMOVQEQ <t> (Select0 <t> (BSRQ x)) (MOVQconst <t> [-1]) (Select1 <types.TypeFlags> (BSRQ x))))
(BitLen32 x) && buildcfg.GOAMD64 < 3 => (Select0 (BSRQ (LEAQ1 <typ.UInt64> [1] (MOVLQZX <typ.UInt64> x) (MOVLQZX <typ.UInt64> x))))
(BitLen16 x) && buildcfg.GOAMD64 < 3 => (BSRL (LEAL1 <typ.UInt32> [1] (MOVWQZX <typ.UInt32> x) (MOVWQZX <typ.UInt32> x)))
(BitLen8 x) && buildcfg.GOAMD64 < 3 => (BSRL (LEAL1 <typ.UInt32> [1] (MOVBQZX <typ.UInt32> x) (MOVBQZX <typ.UInt32> x)))
(BitLen64 <t> x) && buildcfg.GOAMD64 >= 3 => (NEGQ (ADDQconst <t> [-64] (LZCNTQ x)))
// Use 64-bit version to allow const-fold remove unnecessary arithmetic.
(BitLen(32|16|8) <t> x) && buildcfg.GOAMD64 >= 3 => (NEGQ (ADDQconst <t> [-32] (LZCNTL x)))
(Bswap(64|32) ...) => (BSWAP(Q|L) ...)
@ -2225,6 +2229,8 @@
(BSWAP(Q|L) x:(MOV(Q|L)load [i] {s} p mem)) && x.Uses == 1 && buildcfg.GOAMD64 >= 3 => (MOVBE(Q|L)load [i] {s} p mem)
(BSWAP(Q|L) (MOVBE(Q|L)load [i] {s} p m)) => (MOV(Q|L)load [i] {s} p m)
(MOVBE(Q|L)store [i] {s} p (BSWAP(Q|L) x) m) => (MOV(Q|L)store [i] {s} p x m)
(MOVWstore [i] {s} p x:(ROLWconst [8] w) mem) && x.Uses == 1 && buildcfg.GOAMD64 >= 3 => (MOVBEWstore [i] {s} p w mem)
(MOVBEWstore [i] {s} p x:(ROLWconst [8] w) mem) && x.Uses == 1 => (MOVWstore [i] {s} p w mem)
(ORQ x0:(MOVBELload [i0] {s} p mem)
sh:(SHLQconst [32] x1:(MOVBELload [i1] {s} p mem)))
@ -2245,3 +2251,6 @@
&& mergePoint(b,x0,x1) != nil
&& clobber(x0, x1, sh)
=> @mergePoint(b,x0,x1) (MOVBEQload [i] {s} p1 mem)
(SHL(Q|L) l:(MOV(Q|L)load [off] {sym} ptr mem) x) && buildcfg.GOAMD64 >= 3 && canMergeLoad(v, l) && clobber(l) => (SHLX(Q|L)load [off] {sym} ptr x mem)
(SHR(Q|L) l:(MOV(Q|L)load [off] {sym} ptr mem) x) && buildcfg.GOAMD64 >= 3 && canMergeLoad(v, l) && clobber(l) => (SHRX(Q|L)load [off] {sym} ptr x mem)

View file

@ -141,11 +141,13 @@ func init() {
readflags = regInfo{inputs: nil, outputs: gponly}
flagsgpax = regInfo{inputs: nil, clobbers: ax, outputs: []regMask{gp &^ ax}}
gpload = regInfo{inputs: []regMask{gpspsbg, 0}, outputs: gponly}
gp21load = regInfo{inputs: []regMask{gp, gpspsbg, 0}, outputs: gponly}
gploadidx = regInfo{inputs: []regMask{gpspsbg, gpsp, 0}, outputs: gponly}
gp21loadidx = regInfo{inputs: []regMask{gp, gpspsbg, gpsp, 0}, outputs: gponly}
gp21pax = regInfo{inputs: []regMask{gp &^ ax, gp}, outputs: []regMask{gp &^ ax}, clobbers: ax}
gpload = regInfo{inputs: []regMask{gpspsbg, 0}, outputs: gponly}
gp21load = regInfo{inputs: []regMask{gp, gpspsbg, 0}, outputs: gponly}
gploadidx = regInfo{inputs: []regMask{gpspsbg, gpsp, 0}, outputs: gponly}
gp21loadidx = regInfo{inputs: []regMask{gp, gpspsbg, gpsp, 0}, outputs: gponly}
gp21pax = regInfo{inputs: []regMask{gp &^ ax, gp}, outputs: []regMask{gp &^ ax}, clobbers: ax}
gp21shxload = regInfo{inputs: []regMask{gpspsbg, gp, 0}, outputs: gponly}
gp21shxloadidx = regInfo{inputs: []regMask{gpspsbg, gpsp, gp, 0}, outputs: gponly}
gpstore = regInfo{inputs: []regMask{gpspsbg, gpsp, 0}}
gpstoreconst = regInfo{inputs: []regMask{gpspsbg, 0}}
@ -577,8 +579,8 @@ func init() {
{name: "CMOVWGTF", argLength: 3, reg: gp21, asm: "CMOVWHI", resultInArg0: true},
{name: "CMOVWGEF", argLength: 3, reg: gp21, asm: "CMOVWCC", resultInArg0: true},
{name: "BSWAPQ", argLength: 1, reg: gp11, asm: "BSWAPQ", resultInArg0: true, clobberFlags: true}, // arg0 swap bytes
{name: "BSWAPL", argLength: 1, reg: gp11, asm: "BSWAPL", resultInArg0: true, clobberFlags: true}, // arg0 swap bytes
{name: "BSWAPQ", argLength: 1, reg: gp11, asm: "BSWAPQ", resultInArg0: true}, // arg0 swap bytes
{name: "BSWAPL", argLength: 1, reg: gp11, asm: "BSWAPL", resultInArg0: true}, // arg0 swap bytes
// POPCNT instructions aren't guaranteed to be on the target platform (they are SSE4).
// Any use must be preceded by a successful check of runtime.x86HasPOPCNT.
@ -923,11 +925,35 @@ func init() {
{name: "TZCNTQ", argLength: 1, reg: gp11, asm: "TZCNTQ", clobberFlags: true},
{name: "TZCNTL", argLength: 1, reg: gp11, asm: "TZCNTL", clobberFlags: true},
// CPUID feature: LZCNT.
// count the number of leading zero bits.
{name: "LZCNTQ", argLength: 1, reg: gp11, asm: "LZCNTQ", typ: "UInt64", clobberFlags: true},
{name: "LZCNTL", argLength: 1, reg: gp11, asm: "LZCNTL", typ: "UInt32", clobberFlags: true},
// CPUID feature: MOVBE
// MOVBEWload does not satisfy zero extended, so only use MOVBEWstore
{name: "MOVBEWstore", argLength: 3, reg: gpstore, asm: "MOVBEW", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // swap and store 2 bytes in arg1 to arg0+auxint+aux. arg2=mem
{name: "MOVBELload", argLength: 2, reg: gpload, asm: "MOVBEL", aux: "SymOff", typ: "UInt32", faultOnNilArg0: true, symEffect: "Read"}, // load and swap 4 bytes from arg0+auxint+aux. arg1=mem. Zero extend.
{name: "MOVBELstore", argLength: 3, reg: gpstore, asm: "MOVBEL", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // swap and store 4 bytes in arg1 to arg0+auxint+aux. arg2=mem
{name: "MOVBEQload", argLength: 2, reg: gpload, asm: "MOVBEQ", aux: "SymOff", typ: "UInt64", faultOnNilArg0: true, symEffect: "Read"}, // load and swap 8 bytes from arg0+auxint+aux. arg1=mem
{name: "MOVBEQstore", argLength: 3, reg: gpstore, asm: "MOVBEQ", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // swap and store 8 bytes in arg1 to arg0+auxint+aux. arg2=mem
// CPUID feature: BMI2.
{name: "SHLXLload", argLength: 3, reg: gp21shxload, asm: "SHLXL", aux: "SymOff", typ: "Uint32", faultOnNilArg0: true, symEffect: "Read"}, // *(arg0+auxint+aux) << arg1, arg2=mem, shift amount is mod 32
{name: "SHLXQload", argLength: 3, reg: gp21shxload, asm: "SHLXQ", aux: "SymOff", typ: "Uint64", faultOnNilArg0: true, symEffect: "Read"}, // *(arg0+auxint+aux) << arg1, arg2=mem, shift amount is mod 64
{name: "SHRXLload", argLength: 3, reg: gp21shxload, asm: "SHRXL", aux: "SymOff", typ: "Uint32", faultOnNilArg0: true, symEffect: "Read"}, // unsigned *(arg0+auxint+aux) >> arg1, arg2=mem, shift amount is mod 32
{name: "SHRXQload", argLength: 3, reg: gp21shxload, asm: "SHRXQ", aux: "SymOff", typ: "Uint64", faultOnNilArg0: true, symEffect: "Read"}, // unsigned *(arg0+auxint+aux) >> arg1, arg2=mem, shift amount is mod 64
{name: "SHLXLloadidx1", argLength: 4, reg: gp21shxloadidx, asm: "SHLXL", scale: 1, aux: "SymOff", typ: "Uint32", faultOnNilArg0: true, symEffect: "Read"}, // *(arg0+1*arg1+auxint+aux) << arg2, arg3=mem, shift amount is mod 32
{name: "SHLXLloadidx4", argLength: 4, reg: gp21shxloadidx, asm: "SHLXL", scale: 4, aux: "SymOff", typ: "Uint32", faultOnNilArg0: true, symEffect: "Read"}, // *(arg0+4*arg1+auxint+aux) << arg2, arg3=mem, shift amount is mod 32
{name: "SHLXLloadidx8", argLength: 4, reg: gp21shxloadidx, asm: "SHLXL", scale: 8, aux: "SymOff", typ: "Uint32", faultOnNilArg0: true, symEffect: "Read"}, // *(arg0+8*arg1+auxint+aux) << arg2, arg3=mem, shift amount is mod 32
{name: "SHLXQloadidx1", argLength: 4, reg: gp21shxloadidx, asm: "SHLXQ", scale: 1, aux: "SymOff", typ: "Uint64", faultOnNilArg0: true, symEffect: "Read"}, // *(arg0+1*arg1+auxint+aux) << arg2, arg3=mem, shift amount is mod 64
{name: "SHLXQloadidx8", argLength: 4, reg: gp21shxloadidx, asm: "SHLXQ", scale: 8, aux: "SymOff", typ: "Uint64", faultOnNilArg0: true, symEffect: "Read"}, // *(arg0+8*arg1+auxint+aux) << arg2, arg3=mem, shift amount is mod 64
{name: "SHRXLloadidx1", argLength: 4, reg: gp21shxloadidx, asm: "SHRXL", scale: 1, aux: "SymOff", typ: "Uint32", faultOnNilArg0: true, symEffect: "Read"}, // unsigned *(arg0+1*arg1+auxint+aux) >> arg2, arg3=mem, shift amount is mod 32
{name: "SHRXLloadidx4", argLength: 4, reg: gp21shxloadidx, asm: "SHRXL", scale: 4, aux: "SymOff", typ: "Uint32", faultOnNilArg0: true, symEffect: "Read"}, // unsigned *(arg0+4*arg1+auxint+aux) >> arg2, arg3=mem, shift amount is mod 32
{name: "SHRXLloadidx8", argLength: 4, reg: gp21shxloadidx, asm: "SHRXL", scale: 8, aux: "SymOff", typ: "Uint32", faultOnNilArg0: true, symEffect: "Read"}, // unsigned *(arg0+8*arg1+auxint+aux) >> arg2, arg3=mem, shift amount is mod 32
{name: "SHRXQloadidx1", argLength: 4, reg: gp21shxloadidx, asm: "SHRXQ", scale: 1, aux: "SymOff", typ: "Uint64", faultOnNilArg0: true, symEffect: "Read"}, // unsigned *(arg0+1*arg1+auxint+aux) >> arg2, arg3=mem, shift amount is mod 64
{name: "SHRXQloadidx8", argLength: 4, reg: gp21shxloadidx, asm: "SHRXQ", scale: 8, aux: "SymOff", typ: "Uint64", faultOnNilArg0: true, symEffect: "Read"}, // unsigned *(arg0+8*arg1+auxint+aux) >> arg2, arg3=mem, shift amount is mod 64
}
var AMD64blocks = []blockData{

View file

@ -98,7 +98,6 @@ var regNamesPPC64 = []string{
// "CR7",
// "CR",
// "XER",
// "LR",
// "CTR",
}
@ -125,11 +124,12 @@ 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("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")
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("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")
xer = buildReg("XER")
// cr = buildReg("CR")
// ctr = buildReg("CTR")
// lr = buildReg("LR")
@ -139,8 +139,14 @@ func init() {
// tls = buildReg("R13")
gp01 = regInfo{inputs: nil, outputs: []regMask{gp}}
gp11 = regInfo{inputs: []regMask{gp | sp | sb}, outputs: []regMask{gp}}
xergp = regInfo{inputs: []regMask{xer}, outputs: []regMask{gp}, clobbers: xer}
gp11cxer = regInfo{inputs: []regMask{gp | sp | sb}, outputs: []regMask{gp}, clobbers: xer}
gp11xer = regInfo{inputs: []regMask{gp | sp | sb}, outputs: []regMask{gp, xer}}
gp21 = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb}, outputs: []regMask{gp}}
gp21a0 = regInfo{inputs: []regMask{gp, gp | sp | sb}, outputs: []regMask{gp}}
gp21cxer = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb}, outputs: []regMask{gp}, clobbers: xer}
gp21xer = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb}, outputs: []regMask{gp, xer}, clobbers: xer}
gp2xer1xer = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb, xer}, outputs: []regMask{gp, xer}, clobbers: xer}
gp31 = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb, gp | sp | sb}, outputs: []regMask{gp}}
gp22 = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb}, outputs: []regMask{gp, gp}}
gp32 = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb, gp | sp | sb}, outputs: []regMask{gp, gp}}
@ -168,21 +174,21 @@ func init() {
fploadidx = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb}, outputs: []regMask{fp}}
fpstore = regInfo{inputs: []regMask{gp | sp | sb, fp}}
fpstoreidx = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb, fp}}
callerSave = regMask(gp | fp | gr)
callerSave = regMask(gp | fp | gr | xer)
r3 = buildReg("R3")
r4 = buildReg("R4")
r5 = buildReg("R5")
r6 = buildReg("R6")
)
ops := []opData{
{name: "ADD", argLength: 2, reg: gp21, asm: "ADD", commutative: true}, // arg0 + arg1
{name: "ADDconst", argLength: 1, reg: gp11, asm: "ADD", aux: "Int64"}, // arg0 + auxInt
{name: "FADD", argLength: 2, reg: fp21, asm: "FADD", commutative: true}, // arg0+arg1
{name: "FADDS", argLength: 2, reg: fp21, asm: "FADDS", commutative: true}, // arg0+arg1
{name: "SUB", argLength: 2, reg: gp21, asm: "SUB"}, // arg0-arg1
{name: "SUBFCconst", argLength: 1, reg: gp11, asm: "SUBC", aux: "Int64"}, // auxInt - arg0 (with carry)
{name: "FSUB", argLength: 2, reg: fp21, asm: "FSUB"}, // arg0-arg1
{name: "FSUBS", argLength: 2, reg: fp21, asm: "FSUBS"}, // arg0-arg1
{name: "ADD", argLength: 2, reg: gp21, asm: "ADD", commutative: true}, // arg0 + arg1
{name: "ADDconst", argLength: 1, reg: gp11, asm: "ADD", aux: "Int64"}, // arg0 + auxInt
{name: "FADD", argLength: 2, reg: fp21, asm: "FADD", commutative: true}, // arg0+arg1
{name: "FADDS", argLength: 2, reg: fp21, asm: "FADDS", commutative: true}, // arg0+arg1
{name: "SUB", argLength: 2, reg: gp21, asm: "SUB"}, // arg0-arg1
{name: "SUBFCconst", argLength: 1, reg: gp11cxer, asm: "SUBC", aux: "Int64"}, // auxInt - arg0 (carry is ignored)
{name: "FSUB", argLength: 2, reg: fp21, asm: "FSUB"}, // arg0-arg1
{name: "FSUBS", argLength: 2, reg: fp21, asm: "FSUBS"}, // arg0-arg1
{name: "MULLD", argLength: 2, reg: gp21, asm: "MULLD", typ: "Int64", commutative: true}, // arg0*arg1 (signed 64-bit)
{name: "MULLW", argLength: 2, reg: gp21, asm: "MULLW", typ: "Int32", commutative: true}, // arg0*arg1 (signed 32-bit)
@ -204,12 +210,12 @@ func init() {
{name: "FMSUB", argLength: 3, reg: fp31, asm: "FMSUB"}, // arg0*arg1 - arg2
{name: "FMSUBS", argLength: 3, reg: fp31, asm: "FMSUBS"}, // arg0*arg1 - arg2
{name: "SRAD", argLength: 2, reg: gp21, asm: "SRAD"}, // signed arg0 >> (arg1&127), 64 bit width (note: 127, not 63!)
{name: "SRAW", argLength: 2, reg: gp21, asm: "SRAW"}, // signed arg0 >> (arg1&63), 32 bit width
{name: "SRD", argLength: 2, reg: gp21, asm: "SRD"}, // unsigned arg0 >> (arg1&127), 64 bit width
{name: "SRW", argLength: 2, reg: gp21, asm: "SRW"}, // unsigned arg0 >> (arg1&63), 32 bit width
{name: "SLD", argLength: 2, reg: gp21, asm: "SLD"}, // arg0 << (arg1&127), 64 bit width
{name: "SLW", argLength: 2, reg: gp21, asm: "SLW"}, // arg0 << (arg1&63), 32 bit width
{name: "SRAD", argLength: 2, reg: gp21cxer, asm: "SRAD"}, // signed arg0 >> (arg1&127), 64 bit width (note: 127, not 63!)
{name: "SRAW", argLength: 2, reg: gp21cxer, asm: "SRAW"}, // signed arg0 >> (arg1&63), 32 bit width
{name: "SRD", argLength: 2, reg: gp21, asm: "SRD"}, // unsigned arg0 >> (arg1&127), 64 bit width
{name: "SRW", argLength: 2, reg: gp21, asm: "SRW"}, // unsigned arg0 >> (arg1&63), 32 bit width
{name: "SLD", argLength: 2, reg: gp21, asm: "SLD"}, // arg0 << (arg1&127), 64 bit width
{name: "SLW", argLength: 2, reg: gp21, asm: "SLW"}, // arg0 << (arg1&63), 32 bit width
{name: "ROTL", argLength: 2, reg: gp21, asm: "ROTL"}, // arg0 rotate left by arg1 mod 64
{name: "ROTLW", argLength: 2, reg: gp21, asm: "ROTLW"}, // uint32(arg0) rotate left by arg1 mod 32
@ -221,12 +227,22 @@ func init() {
{name: "LoweredAdd64Carry", argLength: 3, reg: gp32, resultNotInArgs: true}, // arg0 + arg1 + carry, returns (sum, carry)
{name: "SRADconst", argLength: 1, reg: gp11, asm: "SRAD", aux: "Int64"}, // signed arg0 >> auxInt, 0 <= auxInt < 64, 64 bit width
{name: "SRAWconst", argLength: 1, reg: gp11, asm: "SRAW", aux: "Int64"}, // signed arg0 >> auxInt, 0 <= auxInt < 32, 32 bit width
{name: "SRDconst", argLength: 1, reg: gp11, asm: "SRD", aux: "Int64"}, // unsigned arg0 >> auxInt, 0 <= auxInt < 64, 64 bit width
{name: "SRWconst", argLength: 1, reg: gp11, asm: "SRW", aux: "Int64"}, // unsigned arg0 >> auxInt, 0 <= auxInt < 32, 32 bit width
{name: "SLDconst", argLength: 1, reg: gp11, asm: "SLD", aux: "Int64"}, // arg0 << auxInt, 0 <= auxInt < 64, 64 bit width
{name: "SLWconst", argLength: 1, reg: gp11, asm: "SLW", aux: "Int64"}, // arg0 << auxInt, 0 <= auxInt < 32, 32 bit width
// Operations which consume or generate the CA (xer)
{name: "ADDC", argLength: 2, reg: gp21xer, asm: "ADDC", commutative: true, typ: "(UInt64, UInt64)"}, // arg0 + arg1 -> out, CA
{name: "SUBC", argLength: 2, reg: gp21xer, asm: "SUBC", typ: "(UInt64, UInt64)"}, // arg0 - arg1 -> out, CA
{name: "ADDCconst", argLength: 1, reg: gp11xer, asm: "ADDC", typ: "(UInt64, UInt64)", aux: "Int64"}, // arg0 + imm16 -> out, CA
{name: "SUBCconst", argLength: 1, reg: gp11xer, asm: "SUBC", typ: "(UInt64, UInt64)", aux: "Int64"}, // imm16 - arg0 -> out, CA
{name: "ADDE", argLength: 3, reg: gp2xer1xer, asm: "ADDE", typ: "(UInt64, UInt64)", commutative: true}, // arg0 + arg1 + CA (arg2) -> out, CA
{name: "SUBE", argLength: 3, reg: gp2xer1xer, asm: "SUBE", typ: "(UInt64, UInt64)"}, // arg0 - arg1 - CA (arg2) -> out, CA
{name: "ADDZEzero", argLength: 1, reg: xergp, asm: "ADDZE", typ: "UInt64"}, // CA (arg0) + $0 -> out
{name: "SUBZEzero", argLength: 1, reg: xergp, asm: "SUBZE", typ: "UInt64"}, // $0 - CA (arg0) -> out
{name: "SRADconst", argLength: 1, reg: gp11cxer, asm: "SRAD", aux: "Int64"}, // signed arg0 >> auxInt, 0 <= auxInt < 64, 64 bit width
{name: "SRAWconst", argLength: 1, reg: gp11cxer, asm: "SRAW", aux: "Int64"}, // signed arg0 >> auxInt, 0 <= auxInt < 32, 32 bit width
{name: "SRDconst", argLength: 1, reg: gp11, asm: "SRD", aux: "Int64"}, // unsigned arg0 >> auxInt, 0 <= auxInt < 64, 64 bit width
{name: "SRWconst", argLength: 1, reg: gp11, asm: "SRW", aux: "Int64"}, // unsigned arg0 >> auxInt, 0 <= auxInt < 32, 32 bit width
{name: "SLDconst", argLength: 1, reg: gp11, asm: "SLD", aux: "Int64"}, // arg0 << auxInt, 0 <= auxInt < 64, 64 bit width
{name: "SLWconst", argLength: 1, reg: gp11, asm: "SLW", aux: "Int64"}, // arg0 << auxInt, 0 <= auxInt < 32, 32 bit width
{name: "ROTLconst", argLength: 1, reg: gp11, asm: "ROTL", aux: "Int64"}, // arg0 rotate left by auxInt bits
{name: "ROTLWconst", argLength: 1, reg: gp11, asm: "ROTLW", aux: "Int64"}, // uint32(arg0) rotate left by auxInt bits
@ -722,6 +738,7 @@ func init() {
ParamFloatRegNames: "F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12",
gpregmask: gp,
fpregmask: fp,
specialregmask: xer,
framepointerreg: -1,
linkreg: -1, // not used
})

View file

@ -46,19 +46,19 @@ func (r *Register) GCNum() int16 {
// variable that has been decomposed into multiple stack slots.
// As an example, a string could have the following configurations:
//
// stack layout LocalSlots
// stack layout LocalSlots
//
// Optimizations are disabled. s is on the stack and represented in its entirety.
// [ ------- s string ---- ] { N: s, Type: string, Off: 0 }
// Optimizations are disabled. s is on the stack and represented in its entirety.
// [ ------- s string ---- ] { N: s, Type: string, Off: 0 }
//
// s was not decomposed, but the SSA operates on its parts individually, so
// there is a LocalSlot for each of its fields that points into the single stack slot.
// [ ------- s string ---- ] { N: s, Type: *uint8, Off: 0 }, {N: s, Type: int, Off: 8}
// s was not decomposed, but the SSA operates on its parts individually, so
// there is a LocalSlot for each of its fields that points into the single stack slot.
// [ ------- s string ---- ] { N: s, Type: *uint8, Off: 0 }, {N: s, Type: int, Off: 8}
//
// s was decomposed. Each of its fields is in its own stack slot and has its own LocalSLot.
// [ ptr *uint8 ] [ len int] { N: ptr, Type: *uint8, Off: 0, SplitOf: parent, SplitOffset: 0},
// { N: len, Type: int, Off: 0, SplitOf: parent, SplitOffset: 8}
// parent = &{N: s, Type: string}
// s was decomposed. Each of its fields is in its own stack slot and has its own LocalSLot.
// [ ptr *uint8 ] [ len int] { N: ptr, Type: *uint8, Off: 0, SplitOf: parent, SplitOffset: 0},
// { N: len, Type: int, Off: 0, SplitOf: parent, SplitOffset: 8}
// parent = &{N: s, Type: string}
type LocalSlot struct {
N *ir.Name // an ONAME *ir.Name representing a stack location.
Type *types.Type // type of slot

View file

@ -66,18 +66,18 @@ func parseIndVar(ind *Value) (min, inc, nxt *Value) {
//
// Look for variables and blocks that satisfy the following
//
// loop:
// ind = (Phi min nxt),
// if ind < max
// then goto enter_loop
// else goto exit_loop
// loop:
// ind = (Phi min nxt),
// if ind < max
// then goto enter_loop
// else goto exit_loop
//
// enter_loop:
// do something
// nxt = inc + ind
// goto loop
// enter_loop:
// do something
// nxt = inc + ind
// goto loop
//
// exit_loop:
// exit_loop:
//
//
// TODO: handle 32 bit operations

View file

@ -1043,10 +1043,27 @@ const (
OpAMD64BLSRL
OpAMD64TZCNTQ
OpAMD64TZCNTL
OpAMD64LZCNTQ
OpAMD64LZCNTL
OpAMD64MOVBEWstore
OpAMD64MOVBELload
OpAMD64MOVBELstore
OpAMD64MOVBEQload
OpAMD64MOVBEQstore
OpAMD64SHLXLload
OpAMD64SHLXQload
OpAMD64SHRXLload
OpAMD64SHRXQload
OpAMD64SHLXLloadidx1
OpAMD64SHLXLloadidx4
OpAMD64SHLXLloadidx8
OpAMD64SHLXQloadidx1
OpAMD64SHLXQloadidx8
OpAMD64SHRXLloadidx1
OpAMD64SHRXLloadidx4
OpAMD64SHRXLloadidx8
OpAMD64SHRXQloadidx1
OpAMD64SHRXQloadidx8
OpARMADD
OpARMADDconst
@ -1911,6 +1928,14 @@ const (
OpPPC64CLRLSLWI
OpPPC64CLRLSLDI
OpPPC64LoweredAdd64Carry
OpPPC64ADDC
OpPPC64SUBC
OpPPC64ADDCconst
OpPPC64SUBCconst
OpPPC64ADDE
OpPPC64SUBE
OpPPC64ADDZEzero
OpPPC64SUBZEzero
OpPPC64SRADconst
OpPPC64SRAWconst
OpPPC64SRDconst
@ -4807,7 +4832,6 @@ var opcodeTable = [...]opInfo{
name: "BSWAPL",
argLen: 1,
resultInArg0: true,
clobberFlags: true,
asm: x86.ABSWAPL,
reg: regInfo{
inputs: []inputInfo{
@ -11498,7 +11522,6 @@ var opcodeTable = [...]opInfo{
name: "BSWAPQ",
argLen: 1,
resultInArg0: true,
clobberFlags: true,
asm: x86.ABSWAPQ,
reg: regInfo{
inputs: []inputInfo{
@ -11513,7 +11536,6 @@ var opcodeTable = [...]opInfo{
name: "BSWAPL",
argLen: 1,
resultInArg0: true,
clobberFlags: true,
asm: x86.ABSWAPL,
reg: regInfo{
inputs: []inputInfo{
@ -13786,6 +13808,48 @@ var opcodeTable = [...]opInfo{
},
},
},
{
name: "LZCNTQ",
argLen: 1,
clobberFlags: true,
asm: x86.ALZCNTQ,
reg: regInfo{
inputs: []inputInfo{
{0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
},
outputs: []outputInfo{
{0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
},
},
},
{
name: "LZCNTL",
argLen: 1,
clobberFlags: true,
asm: x86.ALZCNTL,
reg: regInfo{
inputs: []inputInfo{
{0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
},
outputs: []outputInfo{
{0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
},
},
},
{
name: "MOVBEWstore",
auxType: auxSymOff,
argLen: 3,
faultOnNilArg0: true,
symEffect: SymWrite,
asm: x86.AMOVBEW,
reg: regInfo{
inputs: []inputInfo{
{1, 49151}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R15
{0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 g R15 SB
},
},
},
{
name: "MOVBELload",
auxType: auxSymOff,
@ -13846,6 +13910,264 @@ var opcodeTable = [...]opInfo{
},
},
},
{
name: "SHLXLload",
auxType: auxSymOff,
argLen: 3,
faultOnNilArg0: true,
symEffect: SymRead,
asm: x86.ASHLXL,
reg: regInfo{
inputs: []inputInfo{
{1, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
{0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 g R15 SB
},
outputs: []outputInfo{
{0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
},
},
},
{
name: "SHLXQload",
auxType: auxSymOff,
argLen: 3,
faultOnNilArg0: true,
symEffect: SymRead,
asm: x86.ASHLXQ,
reg: regInfo{
inputs: []inputInfo{
{1, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
{0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 g R15 SB
},
outputs: []outputInfo{
{0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
},
},
},
{
name: "SHRXLload",
auxType: auxSymOff,
argLen: 3,
faultOnNilArg0: true,
symEffect: SymRead,
asm: x86.ASHRXL,
reg: regInfo{
inputs: []inputInfo{
{1, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
{0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 g R15 SB
},
outputs: []outputInfo{
{0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
},
},
},
{
name: "SHRXQload",
auxType: auxSymOff,
argLen: 3,
faultOnNilArg0: true,
symEffect: SymRead,
asm: x86.ASHRXQ,
reg: regInfo{
inputs: []inputInfo{
{1, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
{0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 g R15 SB
},
outputs: []outputInfo{
{0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
},
},
},
{
name: "SHLXLloadidx1",
auxType: auxSymOff,
argLen: 4,
faultOnNilArg0: true,
symEffect: SymRead,
asm: x86.ASHLXL,
scale: 1,
reg: regInfo{
inputs: []inputInfo{
{2, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
{1, 49151}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R15
{0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 g R15 SB
},
outputs: []outputInfo{
{0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
},
},
},
{
name: "SHLXLloadidx4",
auxType: auxSymOff,
argLen: 4,
faultOnNilArg0: true,
symEffect: SymRead,
asm: x86.ASHLXL,
scale: 4,
reg: regInfo{
inputs: []inputInfo{
{2, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
{1, 49151}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R15
{0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 g R15 SB
},
outputs: []outputInfo{
{0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
},
},
},
{
name: "SHLXLloadidx8",
auxType: auxSymOff,
argLen: 4,
faultOnNilArg0: true,
symEffect: SymRead,
asm: x86.ASHLXL,
scale: 8,
reg: regInfo{
inputs: []inputInfo{
{2, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
{1, 49151}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R15
{0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 g R15 SB
},
outputs: []outputInfo{
{0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
},
},
},
{
name: "SHLXQloadidx1",
auxType: auxSymOff,
argLen: 4,
faultOnNilArg0: true,
symEffect: SymRead,
asm: x86.ASHLXQ,
scale: 1,
reg: regInfo{
inputs: []inputInfo{
{2, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
{1, 49151}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R15
{0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 g R15 SB
},
outputs: []outputInfo{
{0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
},
},
},
{
name: "SHLXQloadidx8",
auxType: auxSymOff,
argLen: 4,
faultOnNilArg0: true,
symEffect: SymRead,
asm: x86.ASHLXQ,
scale: 8,
reg: regInfo{
inputs: []inputInfo{
{2, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
{1, 49151}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R15
{0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 g R15 SB
},
outputs: []outputInfo{
{0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
},
},
},
{
name: "SHRXLloadidx1",
auxType: auxSymOff,
argLen: 4,
faultOnNilArg0: true,
symEffect: SymRead,
asm: x86.ASHRXL,
scale: 1,
reg: regInfo{
inputs: []inputInfo{
{2, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
{1, 49151}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R15
{0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 g R15 SB
},
outputs: []outputInfo{
{0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
},
},
},
{
name: "SHRXLloadidx4",
auxType: auxSymOff,
argLen: 4,
faultOnNilArg0: true,
symEffect: SymRead,
asm: x86.ASHRXL,
scale: 4,
reg: regInfo{
inputs: []inputInfo{
{2, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
{1, 49151}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R15
{0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 g R15 SB
},
outputs: []outputInfo{
{0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
},
},
},
{
name: "SHRXLloadidx8",
auxType: auxSymOff,
argLen: 4,
faultOnNilArg0: true,
symEffect: SymRead,
asm: x86.ASHRXL,
scale: 8,
reg: regInfo{
inputs: []inputInfo{
{2, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
{1, 49151}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R15
{0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 g R15 SB
},
outputs: []outputInfo{
{0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
},
},
},
{
name: "SHRXQloadidx1",
auxType: auxSymOff,
argLen: 4,
faultOnNilArg0: true,
symEffect: SymRead,
asm: x86.ASHRXQ,
scale: 1,
reg: regInfo{
inputs: []inputInfo{
{2, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
{1, 49151}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R15
{0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 g R15 SB
},
outputs: []outputInfo{
{0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
},
},
},
{
name: "SHRXQloadidx8",
auxType: auxSymOff,
argLen: 4,
faultOnNilArg0: true,
symEffect: SymRead,
asm: x86.ASHRXQ,
scale: 8,
reg: regInfo{
inputs: []inputInfo{
{2, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
{1, 49151}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R15
{0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 g R15 SB
},
outputs: []outputInfo{
{0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
},
},
},
{
name: "ADD",
@ -25134,6 +25456,7 @@ var opcodeTable = [...]opInfo{
inputs: []inputInfo{
{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
},
clobbers: 9223372036854775808, // XER
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
},
@ -25414,6 +25737,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
{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
},
clobbers: 9223372036854775808, // XER
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
},
@ -25428,6 +25752,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
{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
},
clobbers: 9223372036854775808, // XER
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
},
@ -25575,6 +25900,132 @@ var opcodeTable = [...]opInfo{
},
},
},
{
name: "ADDC",
argLen: 2,
commutative: true,
asm: ppc64.AADDC,
reg: regInfo{
inputs: []inputInfo{
{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
},
clobbers: 9223372036854775808, // XER
outputs: []outputInfo{
{1, 9223372036854775808}, // XER
{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
},
},
},
{
name: "SUBC",
argLen: 2,
asm: ppc64.ASUBC,
reg: regInfo{
inputs: []inputInfo{
{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
},
clobbers: 9223372036854775808, // XER
outputs: []outputInfo{
{1, 9223372036854775808}, // XER
{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
},
},
},
{
name: "ADDCconst",
auxType: auxInt64,
argLen: 1,
asm: ppc64.AADDC,
reg: regInfo{
inputs: []inputInfo{
{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{
{1, 9223372036854775808}, // XER
{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
},
},
},
{
name: "SUBCconst",
auxType: auxInt64,
argLen: 1,
asm: ppc64.ASUBC,
reg: regInfo{
inputs: []inputInfo{
{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{
{1, 9223372036854775808}, // XER
{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
},
},
},
{
name: "ADDE",
argLen: 3,
commutative: true,
asm: ppc64.AADDE,
reg: regInfo{
inputs: []inputInfo{
{2, 9223372036854775808}, // XER
{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
},
clobbers: 9223372036854775808, // XER
outputs: []outputInfo{
{1, 9223372036854775808}, // XER
{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
},
},
},
{
name: "SUBE",
argLen: 3,
asm: ppc64.ASUBE,
reg: regInfo{
inputs: []inputInfo{
{2, 9223372036854775808}, // XER
{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
},
clobbers: 9223372036854775808, // XER
outputs: []outputInfo{
{1, 9223372036854775808}, // XER
{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
},
},
},
{
name: "ADDZEzero",
argLen: 1,
asm: ppc64.AADDZE,
reg: regInfo{
inputs: []inputInfo{
{0, 9223372036854775808}, // XER
},
clobbers: 9223372036854775808, // XER
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
},
},
},
{
name: "SUBZEzero",
argLen: 1,
asm: ppc64.ASUBZE,
reg: regInfo{
inputs: []inputInfo{
{0, 9223372036854775808}, // XER
},
clobbers: 9223372036854775808, // XER
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
},
},
},
{
name: "SRADconst",
auxType: auxInt64,
@ -25584,6 +26035,7 @@ var opcodeTable = [...]opInfo{
inputs: []inputInfo{
{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
},
clobbers: 9223372036854775808, // XER
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
},
@ -25598,6 +26050,7 @@ var opcodeTable = [...]opInfo{
inputs: []inputInfo{
{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
},
clobbers: 9223372036854775808, // XER
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
},
@ -27461,7 +27914,7 @@ var opcodeTable = [...]opInfo{
clobberFlags: true,
call: true,
reg: regInfo{
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
clobbers: 18446744071562059768, // 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 XER
},
},
{
@ -27472,7 +27925,7 @@ var opcodeTable = [...]opInfo{
call: true,
tailCall: true,
reg: regInfo{
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
clobbers: 18446744071562059768, // 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 XER
},
},
{
@ -27486,7 +27939,7 @@ var opcodeTable = [...]opInfo{
{0, 4096}, // R12
{1, 2048}, // R11
},
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
clobbers: 18446744071562059768, // 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 XER
},
},
{
@ -27499,7 +27952,7 @@ var opcodeTable = [...]opInfo{
inputs: []inputInfo{
{0, 4096}, // R12
},
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
clobbers: 18446744071562059768, // 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 XER
},
},
{
@ -27882,7 +28335,7 @@ var opcodeTable = [...]opInfo{
{0, 1048576}, // R20
{1, 2097152}, // R21
},
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
clobbers: 18446744072632408064, // 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 XER
},
},
{
@ -37287,7 +37740,7 @@ 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(9223372032559808512)
var specialRegMaskPPC64 = regMask(0)
var specialRegMaskPPC64 = regMask(9223372036854775808)
var framepointerRegPPC64 = int8(-1)
var linkRegPPC64 = int8(-1)
var registersRISCV64 = [...]Register{

View file

@ -15,12 +15,12 @@ package ssa
//
// In SSA code this appears as
//
// b0
// If b -> b1 b2
// b1
// Plain -> b2
// b2
// x = (OpPhi (ConstBool [true]) (ConstBool [false]))
// b0
// If b -> b1 b2
// b1
// Plain -> b2
// b2
// x = (OpPhi (ConstBool [true]) (ConstBool [false]))
//
// In this case we can replace x with a copy of b.
func phiopt(f *Func) {

View file

@ -145,7 +145,6 @@ type posetNode struct {
// I extra
// / \
// J K
//
type poset struct {
lastidx uint32 // last generated dense index
flags uint8 // internal flags

View file

@ -27,17 +27,17 @@ const (
//
// E.g.
//
// r := relation(...)
// r := relation(...)
//
// if v < w {
// newR := r & lt
// }
// if v >= w {
// newR := r & (eq|gt)
// }
// if v != w {
// newR := r & (lt|gt)
// }
// if v < w {
// newR := r & lt
// }
// if v >= w {
// newR := r & (eq|gt)
// }
// if v != w {
// newR := r & (lt|gt)
// }
type relation uint
const (

View file

@ -1237,7 +1237,7 @@ func (s *regAllocState) regalloc(f *Func) {
desired.clobber(j.regs)
desired.add(v.Args[j.idx].ID, pickReg(j.regs))
}
if opcodeTable[v.Op].resultInArg0 {
if opcodeTable[v.Op].resultInArg0 || v.Op == OpAMD64ADDQconst || v.Op == OpAMD64ADDLconst || v.Op == OpSelect0 {
if opcodeTable[v.Op].commutative {
desired.addList(v.Args[1].ID, prefs)
}
@ -1598,11 +1598,13 @@ func (s *regAllocState) regalloc(f *Func) {
}
}
}
for _, r := range dinfo[idx].out {
if r != noRegister && (mask&^s.used)>>r&1 != 0 {
// Desired register is allowed and unused.
mask = regMask(1) << r
break
if out.idx == 0 { // desired registers only apply to the first element of a tuple result
for _, r := range dinfo[idx].out {
if r != noRegister && (mask&^s.used)>>r&1 != 0 {
// Desired register is allowed and unused.
mask = regMask(1) << r
break
}
}
}
// Avoid registers we're saving for other values.
@ -2581,7 +2583,12 @@ func (s *regAllocState) computeLive() {
desired.add(v.Args[j.idx].ID, pickReg(j.regs))
}
// Set desired register of input 0 if this is a 2-operand instruction.
if opcodeTable[v.Op].resultInArg0 {
if opcodeTable[v.Op].resultInArg0 || v.Op == OpAMD64ADDQconst || v.Op == OpAMD64ADDLconst || v.Op == OpSelect0 {
// ADDQconst is added here because we want to treat it as resultInArg0 for
// the purposes of desired registers, even though it is not an absolute requirement.
// This is because we'd rather implement it as ADDQ instead of LEAQ.
// Same for ADDLconst
// Select0 is added here to propagate the desired register to the tuple-generating instruction.
if opcodeTable[v.Op].commutative {
desired.addList(v.Args[1].ID, prefs)
}
@ -2706,6 +2713,8 @@ type desiredStateEntry struct {
ID ID
// Registers it would like to be in, in priority order.
// Unused slots are filled with noRegister.
// For opcodes that return tuples, we track desired registers only
// for the first element of the tuple.
regs [4]register
}

View file

@ -226,6 +226,8 @@ func rewriteValueAMD64(v *Value) bool {
return rewriteValueAMD64_OpAMD64MOVBELstore(v)
case OpAMD64MOVBEQstore:
return rewriteValueAMD64_OpAMD64MOVBEQstore(v)
case OpAMD64MOVBEWstore:
return rewriteValueAMD64_OpAMD64MOVBEWstore(v)
case OpAMD64MOVBQSX:
return rewriteValueAMD64_OpAMD64MOVBQSX(v)
case OpAMD64MOVBQSXload:
@ -9542,6 +9544,34 @@ func rewriteValueAMD64_OpAMD64MOVBEQstore(v *Value) bool {
}
return false
}
func rewriteValueAMD64_OpAMD64MOVBEWstore(v *Value) bool {
v_2 := v.Args[2]
v_1 := v.Args[1]
v_0 := v.Args[0]
// match: (MOVBEWstore [i] {s} p x:(ROLWconst [8] w) mem)
// cond: x.Uses == 1
// result: (MOVWstore [i] {s} p w mem)
for {
i := auxIntToInt32(v.AuxInt)
s := auxToSym(v.Aux)
p := v_0
x := v_1
if x.Op != OpAMD64ROLWconst || auxIntToInt8(x.AuxInt) != 8 {
break
}
w := x.Args[0]
mem := v_2
if !(x.Uses == 1) {
break
}
v.reset(OpAMD64MOVWstore)
v.AuxInt = int32ToAuxInt(i)
v.Aux = symToAux(s)
v.AddArg3(p, w, mem)
return true
}
return false
}
func rewriteValueAMD64_OpAMD64MOVBQSX(v *Value) bool {
v_0 := v.Args[0]
b := v.Block
@ -14466,6 +14496,28 @@ func rewriteValueAMD64_OpAMD64MOVWstore(v *Value) bool {
v.AddArg3(p, v0, mem)
return true
}
// match: (MOVWstore [i] {s} p x:(ROLWconst [8] w) mem)
// cond: x.Uses == 1 && buildcfg.GOAMD64 >= 3
// result: (MOVBEWstore [i] {s} p w mem)
for {
i := auxIntToInt32(v.AuxInt)
s := auxToSym(v.Aux)
p := v_0
x := v_1
if x.Op != OpAMD64ROLWconst || auxIntToInt8(x.AuxInt) != 8 {
break
}
w := x.Args[0]
mem := v_2
if !(x.Uses == 1 && buildcfg.GOAMD64 >= 3) {
break
}
v.reset(OpAMD64MOVBEWstore)
v.AuxInt = int32ToAuxInt(i)
v.Aux = symToAux(s)
v.AddArg3(p, w, mem)
return true
}
return false
}
func rewriteValueAMD64_OpAMD64MOVWstoreconst(v *Value) bool {
@ -24589,6 +24641,28 @@ func rewriteValueAMD64_OpAMD64SHLL(v *Value) bool {
v.AddArg2(x, v0)
return true
}
// match: (SHLL l:(MOVLload [off] {sym} ptr mem) x)
// cond: buildcfg.GOAMD64 >= 3 && canMergeLoad(v, l) && clobber(l)
// result: (SHLXLload [off] {sym} ptr x mem)
for {
l := v_0
if l.Op != OpAMD64MOVLload {
break
}
off := auxIntToInt32(l.AuxInt)
sym := auxToSym(l.Aux)
mem := l.Args[1]
ptr := l.Args[0]
x := v_1
if !(buildcfg.GOAMD64 >= 3 && canMergeLoad(v, l) && clobber(l)) {
break
}
v.reset(OpAMD64SHLXLload)
v.AuxInt = int32ToAuxInt(off)
v.Aux = symToAux(sym)
v.AddArg3(ptr, x, mem)
return true
}
return false
}
func rewriteValueAMD64_OpAMD64SHLLconst(v *Value) bool {
@ -24823,6 +24897,28 @@ func rewriteValueAMD64_OpAMD64SHLQ(v *Value) bool {
v.AddArg2(x, v0)
return true
}
// match: (SHLQ l:(MOVQload [off] {sym} ptr mem) x)
// cond: buildcfg.GOAMD64 >= 3 && canMergeLoad(v, l) && clobber(l)
// result: (SHLXQload [off] {sym} ptr x mem)
for {
l := v_0
if l.Op != OpAMD64MOVQload {
break
}
off := auxIntToInt32(l.AuxInt)
sym := auxToSym(l.Aux)
mem := l.Args[1]
ptr := l.Args[0]
x := v_1
if !(buildcfg.GOAMD64 >= 3 && canMergeLoad(v, l) && clobber(l)) {
break
}
v.reset(OpAMD64SHLXQload)
v.AuxInt = int32ToAuxInt(off)
v.Aux = symToAux(sym)
v.AddArg3(ptr, x, mem)
return true
}
return false
}
func rewriteValueAMD64_OpAMD64SHLQconst(v *Value) bool {
@ -25152,6 +25248,28 @@ func rewriteValueAMD64_OpAMD64SHRL(v *Value) bool {
v.AddArg2(x, v0)
return true
}
// match: (SHRL l:(MOVLload [off] {sym} ptr mem) x)
// cond: buildcfg.GOAMD64 >= 3 && canMergeLoad(v, l) && clobber(l)
// result: (SHRXLload [off] {sym} ptr x mem)
for {
l := v_0
if l.Op != OpAMD64MOVLload {
break
}
off := auxIntToInt32(l.AuxInt)
sym := auxToSym(l.Aux)
mem := l.Args[1]
ptr := l.Args[0]
x := v_1
if !(buildcfg.GOAMD64 >= 3 && canMergeLoad(v, l) && clobber(l)) {
break
}
v.reset(OpAMD64SHRXLload)
v.AuxInt = int32ToAuxInt(off)
v.Aux = symToAux(sym)
v.AddArg3(ptr, x, mem)
return true
}
return false
}
func rewriteValueAMD64_OpAMD64SHRLconst(v *Value) bool {
@ -25374,6 +25492,28 @@ func rewriteValueAMD64_OpAMD64SHRQ(v *Value) bool {
v.AddArg2(x, v0)
return true
}
// match: (SHRQ l:(MOVQload [off] {sym} ptr mem) x)
// cond: buildcfg.GOAMD64 >= 3 && canMergeLoad(v, l) && clobber(l)
// result: (SHRXQload [off] {sym} ptr x mem)
for {
l := v_0
if l.Op != OpAMD64MOVQload {
break
}
off := auxIntToInt32(l.AuxInt)
sym := auxToSym(l.Aux)
mem := l.Args[1]
ptr := l.Args[0]
x := v_1
if !(buildcfg.GOAMD64 >= 3 && canMergeLoad(v, l) && clobber(l)) {
break
}
v.reset(OpAMD64SHRXQload)
v.AuxInt = int32ToAuxInt(off)
v.Aux = symToAux(sym)
v.AddArg3(ptr, x, mem)
return true
}
return false
}
func rewriteValueAMD64_OpAMD64SHRQconst(v *Value) bool {
@ -27974,9 +28114,13 @@ func rewriteValueAMD64_OpBitLen16(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (BitLen16 x)
// cond: buildcfg.GOAMD64 < 3
// result: (BSRL (LEAL1 <typ.UInt32> [1] (MOVWQZX <typ.UInt32> x) (MOVWQZX <typ.UInt32> x)))
for {
x := v_0
if !(buildcfg.GOAMD64 < 3) {
break
}
v.reset(OpAMD64BSRL)
v0 := b.NewValue0(v.Pos, OpAMD64LEAL1, typ.UInt32)
v0.AuxInt = int32ToAuxInt(1)
@ -27986,15 +28130,38 @@ func rewriteValueAMD64_OpBitLen16(v *Value) bool {
v.AddArg(v0)
return true
}
// match: (BitLen16 <t> x)
// cond: buildcfg.GOAMD64 >= 3
// result: (NEGQ (ADDQconst <t> [-32] (LZCNTL x)))
for {
t := v.Type
x := v_0
if !(buildcfg.GOAMD64 >= 3) {
break
}
v.reset(OpAMD64NEGQ)
v0 := b.NewValue0(v.Pos, OpAMD64ADDQconst, t)
v0.AuxInt = int32ToAuxInt(-32)
v1 := b.NewValue0(v.Pos, OpAMD64LZCNTL, typ.UInt32)
v1.AddArg(x)
v0.AddArg(v1)
v.AddArg(v0)
return true
}
return false
}
func rewriteValueAMD64_OpBitLen32(v *Value) bool {
v_0 := v.Args[0]
b := v.Block
typ := &b.Func.Config.Types
// match: (BitLen32 x)
// cond: buildcfg.GOAMD64 < 3
// result: (Select0 (BSRQ (LEAQ1 <typ.UInt64> [1] (MOVLQZX <typ.UInt64> x) (MOVLQZX <typ.UInt64> x))))
for {
x := v_0
if !(buildcfg.GOAMD64 < 3) {
break
}
v.reset(OpSelect0)
v0 := b.NewValue0(v.Pos, OpAMD64BSRQ, types.NewTuple(typ.UInt64, types.TypeFlags))
v1 := b.NewValue0(v.Pos, OpAMD64LEAQ1, typ.UInt64)
@ -28006,16 +28173,39 @@ func rewriteValueAMD64_OpBitLen32(v *Value) bool {
v.AddArg(v0)
return true
}
// match: (BitLen32 <t> x)
// cond: buildcfg.GOAMD64 >= 3
// result: (NEGQ (ADDQconst <t> [-32] (LZCNTL x)))
for {
t := v.Type
x := v_0
if !(buildcfg.GOAMD64 >= 3) {
break
}
v.reset(OpAMD64NEGQ)
v0 := b.NewValue0(v.Pos, OpAMD64ADDQconst, t)
v0.AuxInt = int32ToAuxInt(-32)
v1 := b.NewValue0(v.Pos, OpAMD64LZCNTL, typ.UInt32)
v1.AddArg(x)
v0.AddArg(v1)
v.AddArg(v0)
return true
}
return false
}
func rewriteValueAMD64_OpBitLen64(v *Value) bool {
v_0 := v.Args[0]
b := v.Block
typ := &b.Func.Config.Types
// match: (BitLen64 <t> x)
// cond: buildcfg.GOAMD64 < 3
// result: (ADDQconst [1] (CMOVQEQ <t> (Select0 <t> (BSRQ x)) (MOVQconst <t> [-1]) (Select1 <types.TypeFlags> (BSRQ x))))
for {
t := v.Type
x := v_0
if !(buildcfg.GOAMD64 < 3) {
break
}
v.reset(OpAMD64ADDQconst)
v.AuxInt = int32ToAuxInt(1)
v0 := b.NewValue0(v.Pos, OpAMD64CMOVQEQ, t)
@ -28031,15 +28221,38 @@ func rewriteValueAMD64_OpBitLen64(v *Value) bool {
v.AddArg(v0)
return true
}
// match: (BitLen64 <t> x)
// cond: buildcfg.GOAMD64 >= 3
// result: (NEGQ (ADDQconst <t> [-64] (LZCNTQ x)))
for {
t := v.Type
x := v_0
if !(buildcfg.GOAMD64 >= 3) {
break
}
v.reset(OpAMD64NEGQ)
v0 := b.NewValue0(v.Pos, OpAMD64ADDQconst, t)
v0.AuxInt = int32ToAuxInt(-64)
v1 := b.NewValue0(v.Pos, OpAMD64LZCNTQ, typ.UInt64)
v1.AddArg(x)
v0.AddArg(v1)
v.AddArg(v0)
return true
}
return false
}
func rewriteValueAMD64_OpBitLen8(v *Value) bool {
v_0 := v.Args[0]
b := v.Block
typ := &b.Func.Config.Types
// match: (BitLen8 x)
// cond: buildcfg.GOAMD64 < 3
// result: (BSRL (LEAL1 <typ.UInt32> [1] (MOVBQZX <typ.UInt32> x) (MOVBQZX <typ.UInt32> x)))
for {
x := v_0
if !(buildcfg.GOAMD64 < 3) {
break
}
v.reset(OpAMD64BSRL)
v0 := b.NewValue0(v.Pos, OpAMD64LEAL1, typ.UInt32)
v0.AuxInt = int32ToAuxInt(1)
@ -28049,6 +28262,25 @@ func rewriteValueAMD64_OpBitLen8(v *Value) bool {
v.AddArg(v0)
return true
}
// match: (BitLen8 <t> x)
// cond: buildcfg.GOAMD64 >= 3
// result: (NEGQ (ADDQconst <t> [-32] (LZCNTL x)))
for {
t := v.Type
x := v_0
if !(buildcfg.GOAMD64 >= 3) {
break
}
v.reset(OpAMD64NEGQ)
v0 := b.NewValue0(v.Pos, OpAMD64ADDQconst, t)
v0.AuxInt = int32ToAuxInt(-32)
v1 := b.NewValue0(v.Pos, OpAMD64LZCNTL, typ.UInt32)
v1.AddArg(x)
v0.AddArg(v1)
v.AddArg(v0)
return true
}
return false
}
func rewriteValueAMD64_OpCeil(v *Value) bool {
v_0 := v.Args[0]

View file

@ -207,8 +207,8 @@ func (t SparseTree) isAncestor(x, y *Block) bool {
// domorder returns a value for dominator-oriented sorting.
// Block domination does not provide a total ordering,
// but domorder two has useful properties.
// (1) If domorder(x) > domorder(y) then x does not dominate y.
// (2) If domorder(x) < domorder(y) and domorder(y) < domorder(z) and x does not dominate y,
// 1. If domorder(x) > domorder(y) then x does not dominate y.
// 2. If domorder(x) < domorder(y) and domorder(y) < domorder(z) and x does not dominate y,
// then x does not dominate z.
// Property (1) means that blocks sorted by domorder always have a maximal dominant block first.
// Property (2) allows searches for dominated blocks to exit early.

View file

@ -80,11 +80,11 @@ func needwb(v *Value, zeroes map[ID]ZeroRegion) bool {
// when necessary (the condition above). It rewrites store ops to branches
// and runtime calls, like
//
// if writeBarrier.enabled {
// gcWriteBarrier(ptr, val) // Not a regular Go call
// } else {
// *ptr = val
// }
// if writeBarrier.enabled {
// gcWriteBarrier(ptr, val) // Not a regular Go call
// } else {
// *ptr = val
// }
//
// A sequence of WB stores for many pointer fields of a single type will
// be emitted together, with a single branch.

View file

@ -14,7 +14,6 @@ import (
"cmd/compile/internal/base"
"cmd/compile/internal/ir"
"cmd/compile/internal/staticdata"
"cmd/compile/internal/typecheck"
"cmd/compile/internal/types"
"cmd/internal/obj"
@ -243,17 +242,6 @@ func InitLSym(f *ir.Func, hasBody bool) {
if f.Pragma&ir.Systemstack != 0 {
f.LSym.Set(obj.AttrCFunc, true)
}
if f.ABI == obj.ABIInternal || !buildcfg.Experiment.RegabiWrappers {
// Function values can only point to
// ABIInternal entry points. This will create
// the funcsym for either the defining
// function or its wrapper as appropriate.
//
// If we're not using ABI wrappers, we only
// InitLSym for the defining ABI of a function,
// so we make the funcsym when we see that.
staticdata.NeedFuncSym(f)
}
}
if hasBody {
setupTextLSym(f, 0)

View file

@ -4496,9 +4496,6 @@ func InitTables() {
sys.ARM64)
addF("math/bits", "Reverse",
func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
if s.config.PtrSize == 4 {
return s.newValue1(ssa.OpBitRev32, types.Types[types.TINT], args[0])
}
return s.newValue1(ssa.OpBitRev64, types.Types[types.TINT], args[0])
},
sys.ARM64)

View file

@ -8,7 +8,6 @@ import (
"crypto/sha256"
"fmt"
"go/constant"
"internal/buildcfg"
"io"
"io/ioutil"
"os"
@ -236,15 +235,9 @@ func FuncLinksym(n *ir.Name) *obj.LSym {
// except for the types package, which is protected separately.
// Reusing funcsymsmu to also cover this package lookup
// avoids a general, broader, expensive package lookup mutex.
// Note NeedFuncSym also does package look-up of func sym names,
// but that it is only called serially, from the front end.
funcsymsmu.Lock()
sf, existed := s.Pkg.LookupOK(ir.FuncSymName(s))
// Don't export s·f when compiling for dynamic linking.
// When dynamically linking, the necessary function
// symbols will be created explicitly with NeedFuncSym.
// See the NeedFuncSym comment for details.
if !base.Ctxt.Flag_dynlink && !existed {
if !existed {
funcsyms = append(funcsyms, n)
}
funcsymsmu.Unlock()
@ -259,48 +252,6 @@ func GlobalLinksym(n *ir.Name) *obj.LSym {
return n.Linksym()
}
// NeedFuncSym ensures that fn·f is exported, if needed.
// It is only used with -dynlink.
// When not compiling for dynamic linking,
// the funcsyms are created as needed by
// the packages that use them.
// Normally we emit the fn·f stubs as DUPOK syms,
// but DUPOK doesn't work across shared library boundaries.
// So instead, when dynamic linking, we only create
// the fn·f stubs in fn's package.
func NeedFuncSym(fn *ir.Func) {
if base.Ctxt.InParallel {
// The append below probably just needs to lock
// funcsymsmu, like in FuncSym.
base.Fatalf("NeedFuncSym must be called in serial")
}
if fn.ABI != obj.ABIInternal && buildcfg.Experiment.RegabiWrappers {
// Function values must always reference ABIInternal
// entry points, so it doesn't make sense to create a
// funcsym for other ABIs.
//
// (If we're not using ABI wrappers, it doesn't matter.)
base.Fatalf("expected ABIInternal: %v has %v", fn.Nname, fn.ABI)
}
if ir.IsBlank(fn.Nname) {
// Blank functions aren't unique, so we can't make a
// funcsym for them.
base.Fatalf("NeedFuncSym called for _")
}
if !base.Ctxt.Flag_dynlink {
return
}
s := fn.Nname.Sym()
if base.Flag.CompilingRuntime && (s.Name == "getg" || s.Name == "getclosureptr" || s.Name == "getcallerpc" || s.Name == "getcallersp") ||
(base.Ctxt.Pkgpath == "internal/abi" && (s.Name == "FuncPCABI0" || s.Name == "FuncPCABIInternal")) {
// runtime.getg(), getclosureptr(), getcallerpc(), getcallersp(),
// and internal/abi.FuncPCABIxxx() are not real functions and so
// do not get funcsyms.
return
}
funcsyms = append(funcsyms, fn.Nname)
}
func WriteFuncSyms() {
sort.Slice(funcsyms, func(i, j int) bool {
return funcsyms[i].Linksym().Name < funcsyms[j].Linksym().Name

View file

@ -13,7 +13,7 @@ func TestDump(t *testing.T) {
t.Skip("skipping test in short mode")
}
ast, _ := ParseFile(*src_, func(err error) { t.Error(err) }, nil, CheckBranches|AllowGenerics)
ast, _ := ParseFile(*src_, func(err error) { t.Error(err) }, nil, CheckBranches)
if ast != nil {
Fdump(testOut(), ast)

View file

@ -128,10 +128,6 @@ func testSyntaxErrors(t *testing.T, filename string) {
}
defer f.Close()
var mode Mode
if strings.HasSuffix(filename, ".go2") {
mode = AllowGenerics
}
ParseFile(filename, func(err error) {
e, ok := err.(Error)
if !ok {
@ -166,7 +162,7 @@ func testSyntaxErrors(t *testing.T, filename string) {
} else {
t.Errorf("%s:%s: unexpected error: %s", filename, orig, e.Msg)
}
}, nil, mode)
}, nil, 0)
if *print {
fmt.Println()

View file

@ -462,7 +462,7 @@ func (simpleStmt) aSimpleStmt() {}
// Comments
// TODO(gri) Consider renaming to CommentPos, CommentPlacement, etc.
// Kind = Above doesn't make much sense.
// Kind = Above doesn't make much sense.
type CommentKind uint
const (

View file

@ -87,8 +87,6 @@ func (p *parser) init(file *PosBase, r io.Reader, errh ErrorHandler, pragh Pragm
p.indent = nil
}
func (p *parser) allowGenerics() bool { return p.mode&AllowGenerics != 0 }
// takePragma returns the current parsed pragmas
// and clears them from the parser state.
func (p *parser) takePragma() Pragma {
@ -473,8 +471,7 @@ func isEmptyFuncDecl(dcl Decl) bool {
// elements are accepted. list returns the position of the closing token.
//
// list = [ f { sep f } [sep] ] close .
//
func (p *parser) list(sep, close token, f func() bool) Pos {
func (p *parser) list(context string, sep, close token, f func() bool) Pos {
if debug && (sep != _Comma && sep != _Semi || close != _Rparen && close != _Rbrace && close != _Rbrack) {
panic("invalid sep or close argument for list")
}
@ -484,7 +481,7 @@ func (p *parser) list(sep, close token, f func() bool) Pos {
done = f()
// sep is optional before close
if !p.got(sep) && p.tok != close {
p.syntaxError(fmt.Sprintf("expecting %s or %s", tokstring(sep), tokstring(close)))
p.syntaxError(fmt.Sprintf("in %s; possibly missing %s or %s", context, tokstring(sep), tokstring(close)))
p.advance(_Rparen, _Rbrack, _Rbrace)
if p.tok != close {
// position could be better but we had an error so we don't care
@ -504,7 +501,7 @@ func (p *parser) appendGroup(list []Decl, f func(*Group) Decl) []Decl {
g := new(Group)
p.clearPragma()
p.next() // must consume "(" after calling clearPragma!
p.list(_Semi, _Rparen, func() bool {
p.list("grouped declaration", _Semi, _Rparen, func() bool {
if x := f(g); x != nil {
list = append(list, x)
}
@ -586,7 +583,7 @@ func (p *parser) typeDecl(group *Group) Decl {
d.Pragma = p.takePragma()
d.Name = p.name()
if p.allowGenerics() && p.tok == _Lbrack {
if p.tok == _Lbrack {
// d.Name "[" ...
// array/slice type or type parameter list
pos := p.pos()
@ -762,7 +759,7 @@ func (p *parser) funcDeclOrNil() *FuncDecl {
f.Name = p.name()
context := ""
if f.Recv != nil && p.mode&AllowMethodTypeParams == 0 {
if f.Recv != nil {
context = "method" // don't permit (method) type parameters in funcType
}
f.TParamList, f.Type = p.funcType(context)
@ -1024,22 +1021,24 @@ func (p *parser) operand(keep_parens bool) Expr {
// as well (operand is only called from pexpr).
}
// PrimaryExpr =
// Operand |
// Conversion |
// PrimaryExpr Selector |
// PrimaryExpr Index |
// PrimaryExpr Slice |
// PrimaryExpr TypeAssertion |
// PrimaryExpr Arguments .
// pexpr parses a PrimaryExpr.
//
// Selector = "." identifier .
// Index = "[" Expression "]" .
// Slice = "[" ( [ Expression ] ":" [ Expression ] ) |
// ( [ Expression ] ":" Expression ":" Expression )
// "]" .
// TypeAssertion = "." "(" Type ")" .
// Arguments = "(" [ ( ExpressionList | Type [ "," ExpressionList ] ) [ "..." ] [ "," ] ] ")" .
// PrimaryExpr =
// Operand |
// Conversion |
// PrimaryExpr Selector |
// PrimaryExpr Index |
// PrimaryExpr Slice |
// PrimaryExpr TypeAssertion |
// PrimaryExpr Arguments .
//
// Selector = "." identifier .
// Index = "[" Expression "]" .
// Slice = "[" ( [ Expression ] ":" [ Expression ] ) |
// ( [ Expression ] ":" Expression ":" Expression )
// "]" .
// TypeAssertion = "." "(" Type ")" .
// Arguments = "(" [ ( ExpressionList | Type [ "," ExpressionList ] ) [ "..." ] [ "," ] ] ")" .
func (p *parser) pexpr(x Expr, keep_parens bool) Expr {
if trace {
defer p.trace("pexpr")()
@ -1098,45 +1097,25 @@ loop:
var i Expr
if p.tok != _Colon {
if p.mode&AllowGenerics == 0 {
p.xnest++
i = p.expr()
p.xnest--
if p.got(_Rbrack) {
// x[i]
t := new(IndexExpr)
t.pos = pos
t.X = x
t.Index = i
x = t
break
}
} else {
var comma bool
i, comma = p.typeList()
if comma || p.tok == _Rbrack {
p.want(_Rbrack)
// x[i,] or x[i, j, ...]
t := new(IndexExpr)
t.pos = pos
t.X = x
t.Index = i
x = t
break
}
var comma bool
i, comma = p.typeList()
if comma || p.tok == _Rbrack {
p.want(_Rbrack)
// x[i,] or x[i, j, ...]
t := new(IndexExpr)
t.pos = pos
t.X = x
t.Index = i
x = t
break
}
}
// x[i:...
// For better error message, don't simply use p.want(_Colon) here (issue #47704).
if !p.got(_Colon) {
if p.mode&AllowGenerics == 0 {
p.syntaxError("expecting : or ]")
p.advance(_Colon, _Rbrack)
} else {
p.syntaxError("expecting comma, : or ]")
p.advance(_Comma, _Colon, _Rbrack)
}
p.syntaxError("expecting comma, : or ]")
p.advance(_Comma, _Colon, _Rbrack)
}
p.xnest++
t := new(SliceExpr)
@ -1255,7 +1234,7 @@ func (p *parser) complitexpr() *CompositeLit {
p.xnest++
p.want(_Lbrace)
x.Rbrace = p.list(_Comma, _Rbrace, func() bool {
x.Rbrace = p.list("composite literal", _Comma, _Rbrace, func() bool {
// value
e := p.bare_complitexpr()
if p.tok == _Colon {
@ -1305,10 +1284,10 @@ func newIndirect(pos Pos, typ Expr) Expr {
// typeOrNil is like type_ but it returns nil if there was no type
// instead of reporting an error.
//
// Type = TypeName | TypeLit | "(" Type ")" .
// TypeName = identifier | QualifiedIdent .
// TypeLit = ArrayType | StructType | PointerType | FunctionType | InterfaceType |
// SliceType | MapType | Channel_Type .
// Type = TypeName | TypeLit | "(" Type ")" .
// TypeName = identifier | QualifiedIdent .
// TypeLit = ArrayType | StructType | PointerType | FunctionType | InterfaceType |
// SliceType | MapType | Channel_Type .
func (p *parser) typeOrNil() Expr {
if trace {
defer p.trace("typeOrNil")()
@ -1418,7 +1397,7 @@ func (p *parser) funcType(context string) ([]*Field, *FuncType) {
typ.pos = p.pos()
var tparamList []*Field
if p.allowGenerics() && p.got(_Lbrack) {
if p.got(_Lbrack) {
if context != "" {
// accept but complain
p.syntaxErrorAt(typ.pos, context+" must have no type parameters")
@ -1499,7 +1478,7 @@ func (p *parser) structType() *StructType {
p.want(_Struct)
p.want(_Lbrace)
p.list(_Semi, _Rbrace, func() bool {
p.list("struct type", _Semi, _Rbrace, func() bool {
p.fieldDecl(typ)
return false
})
@ -1509,7 +1488,6 @@ func (p *parser) structType() *StructType {
// InterfaceType = "interface" "{" { ( MethodDecl | EmbeddedElem | TypeList ) ";" } "}" .
// TypeList = "type" Type { "," Type } .
// TODO(gri) remove TypeList syntax if we accept #45346
func (p *parser) interfaceType() *InterfaceType {
if trace {
defer p.trace("interfaceType")()
@ -1520,18 +1498,17 @@ func (p *parser) interfaceType() *InterfaceType {
p.want(_Interface)
p.want(_Lbrace)
p.list(_Semi, _Rbrace, func() bool {
p.list("interface type", _Semi, _Rbrace, func() bool {
switch p.tok {
case _Name:
f := p.methodDecl()
if f.Name == nil && p.allowGenerics() {
if f.Name == nil {
f = p.embeddedElem(f)
}
typ.MethodList = append(typ.MethodList, f)
return false
case _Lparen:
// TODO(gri) Need to decide how to adjust this restriction.
p.syntaxError("cannot parenthesize embedded type")
f := new(Field)
f.pos = p.pos()
@ -1542,31 +1519,23 @@ func (p *parser) interfaceType() *InterfaceType {
return false
case _Operator:
if p.op == Tilde && p.allowGenerics() {
if p.op == Tilde {
typ.MethodList = append(typ.MethodList, p.embeddedElem(nil))
return false
}
default:
if p.allowGenerics() {
pos := p.pos()
if t := p.typeOrNil(); t != nil {
f := new(Field)
f.pos = pos
f.Type = t
typ.MethodList = append(typ.MethodList, p.embeddedElem(f))
return false
}
pos := p.pos()
if t := p.typeOrNil(); t != nil {
f := new(Field)
f.pos = pos
f.Type = t
typ.MethodList = append(typ.MethodList, p.embeddedElem(f))
return false
}
}
if p.allowGenerics() {
p.syntaxError("expecting method or embedded element")
p.advance(_Semi, _Rbrace)
return false
}
p.syntaxError("expecting method or interface name")
p.syntaxError("expecting method or embedded element")
p.advance(_Semi, _Rbrace)
return false
})
@ -1640,7 +1609,7 @@ func (p *parser) fieldDecl(styp *StructType) {
// Careful dance: We don't know if we have an embedded instantiated
// type T[P1, P2, ...] or a field T of array/slice type [P]E or []E.
if p.allowGenerics() && len(names) == 1 && p.tok == _Lbrack {
if len(names) == 1 && p.tok == _Lbrack {
typ = p.arrayOrTArgs()
if typ, ok := typ.(*IndexExpr); ok {
// embedded type T[P1, P2, ...]
@ -1757,20 +1726,6 @@ func (p *parser) methodDecl() *Field {
f.pos = p.pos()
name := p.name()
// accept potential name list but complain
// TODO(gri) We probably don't need this special check anymore.
// Nobody writes this kind of code. It's from ancient
// Go beginnings.
hasNameList := false
for p.got(_Comma) {
p.name()
hasNameList = true
}
if hasNameList {
p.syntaxError("name list not allowed in interface type")
// already progressed, no need to advance
}
const context = "interface method"
switch p.tok {
@ -1780,79 +1735,72 @@ func (p *parser) methodDecl() *Field {
_, f.Type = p.funcType(context)
case _Lbrack:
if p.allowGenerics() {
// Careful dance: We don't know if we have a generic method m[T C](x T)
// or an embedded instantiated type T[P1, P2] (we accept generic methods
// for generality and robustness of parsing).
// Careful dance: We don't know if we have a generic method m[T C](x T)
// or an embedded instantiated type T[P1, P2] (we accept generic methods
// for generality and robustness of parsing but complain with an error).
pos := p.pos()
p.next()
// Empty type parameter or argument lists are not permitted.
// Treat as if [] were absent.
if p.tok == _Rbrack {
// name[]
pos := p.pos()
p.next()
// Empty type parameter or argument lists are not permitted.
// Treat as if [] were absent.
if p.tok == _Rbrack {
// name[]
pos := p.pos()
p.next()
if p.tok == _Lparen {
// name[](
p.errorAt(pos, "empty type parameter list")
f.Name = name
_, f.Type = p.funcType(context)
} else {
p.errorAt(pos, "empty type argument list")
f.Type = name
}
break
}
// A type argument list looks like a parameter list with only
// types. Parse a parameter list and decide afterwards.
list := p.paramList(nil, nil, _Rbrack, false)
if len(list) == 0 {
// The type parameter list is not [] but we got nothing
// due to other errors (reported by paramList). Treat
// as if [] were absent.
if p.tok == _Lparen {
f.Name = name
_, f.Type = p.funcType(context)
} else {
f.Type = name
}
break
}
// len(list) > 0
if list[0].Name != nil {
// generic method
if p.tok == _Lparen {
// name[](
p.errorAt(pos, "empty type parameter list")
f.Name = name
_, f.Type = p.funcType(context)
// TODO(gri) Record list as type parameter list with f.Type
// if we want to type-check the generic method.
// For now, report an error so this is not a silent event.
p.errorAt(pos, "interface method must have no type parameters")
break
}
// embedded instantiated type
t := new(IndexExpr)
t.pos = pos
t.X = name
if len(list) == 1 {
t.Index = list[0].Type
} else {
// len(list) > 1
l := new(ListExpr)
l.pos = list[0].Pos()
l.ElemList = make([]Expr, len(list))
for i := range list {
l.ElemList[i] = list[i].Type
}
t.Index = l
p.errorAt(pos, "empty type argument list")
f.Type = name
}
f.Type = t
break
}
fallthrough
// A type argument list looks like a parameter list with only
// types. Parse a parameter list and decide afterwards.
list := p.paramList(nil, nil, _Rbrack, false)
if len(list) == 0 {
// The type parameter list is not [] but we got nothing
// due to other errors (reported by paramList). Treat
// as if [] were absent.
if p.tok == _Lparen {
f.Name = name
_, f.Type = p.funcType(context)
} else {
f.Type = name
}
break
}
// len(list) > 0
if list[0].Name != nil {
// generic method
f.Name = name
_, f.Type = p.funcType(context)
p.errorAt(pos, "interface method must have no type parameters")
break
}
// embedded instantiated type
t := new(IndexExpr)
t.pos = pos
t.X = name
if len(list) == 1 {
t.Index = list[0].Type
} else {
// len(list) > 1
l := new(ListExpr)
l.pos = list[0].Pos()
l.ElemList = make([]Expr, len(list))
for i := range list {
l.ElemList[i] = list[i].Type
}
t.Index = l
}
f.Type = t
default:
// embedded type
@ -1938,7 +1886,7 @@ func (p *parser) paramDeclOrNil(name *Name, follow token) *Field {
name = p.name()
}
if p.allowGenerics() && p.tok == _Lbrack {
if p.tok == _Lbrack {
// name "[" ...
f.Type = p.arrayOrTArgs()
if typ, ok := f.Type.(*IndexExpr); ok {
@ -2033,7 +1981,7 @@ func (p *parser) paramList(name *Name, typ Expr, close token, requireNames bool)
var named int // number of parameters that have an explicit name and type
var typed int // number of parameters that have an explicit type
end := p.list(_Comma, close, func() bool {
end := p.list("parameter list", _Comma, close, func() bool {
var par *Field
if typ != nil {
if debug && name == nil {
@ -2572,11 +2520,13 @@ func (p *parser) commClause() *CommClause {
return c
}
// Statement =
// Declaration | LabeledStmt | SimpleStmt |
// GoStmt | ReturnStmt | BreakStmt | ContinueStmt | GotoStmt |
// FallthroughStmt | Block | IfStmt | SwitchStmt | SelectStmt | ForStmt |
// DeferStmt .
// stmtOrNil parses a statement if one is present, or else returns nil.
//
// Statement =
// Declaration | LabeledStmt | SimpleStmt |
// GoStmt | ReturnStmt | BreakStmt | ContinueStmt | GotoStmt |
// FallthroughStmt | Block | IfStmt | SwitchStmt | SelectStmt | ForStmt |
// DeferStmt .
func (p *parser) stmtOrNil() Stmt {
if trace {
defer p.trace("stmt " + p.tok.String())()
@ -2713,7 +2663,7 @@ func (p *parser) argList() (list []Expr, hasDots bool) {
}
p.xnest++
p.list(_Comma, _Rparen, func() bool {
p.list("argument list", _Comma, _Rparen, func() bool {
list = append(list, p.expr())
hasDots = p.got(_DotDotDot)
return hasDots
@ -2787,7 +2737,7 @@ func (p *parser) qualifiedName(name *Name) Expr {
x = s
}
if p.allowGenerics() && p.tok == _Lbrack {
if p.tok == _Lbrack {
x = p.typeInstance(x)
}

View file

@ -27,31 +27,17 @@ var (
)
func TestParse(t *testing.T) {
ParseFile(*src_, func(err error) { t.Error(err) }, nil, AllowGenerics)
ParseFile(*src_, func(err error) { t.Error(err) }, nil, 0)
}
func TestVerify(t *testing.T) {
ast, err := ParseFile(*src_, func(err error) { t.Error(err) }, nil, AllowGenerics)
ast, err := ParseFile(*src_, func(err error) { t.Error(err) }, nil, 0)
if err != nil {
return // error already reported
}
verifyPrint(t, *src_, ast)
}
func TestParseGo2(t *testing.T) {
dir := filepath.Join(testdata, "go2")
list, err := ioutil.ReadDir(dir)
if err != nil {
t.Fatal(err)
}
for _, fi := range list {
name := fi.Name()
if !fi.IsDir() && !strings.HasPrefix(name, ".") {
ParseFile(filepath.Join(dir, name), func(err error) { t.Error(err) }, nil, AllowGenerics|AllowMethodTypeParams)
}
}
}
func TestStdLib(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode")
@ -94,7 +80,7 @@ func TestStdLib(t *testing.T) {
if debug {
fmt.Printf("parsing %s\n", filename)
}
ast, err := ParseFile(filename, nil, nil, AllowGenerics)
ast, err := ParseFile(filename, nil, nil, 0)
if err != nil {
t.Error(err)
return

View file

@ -24,7 +24,7 @@ type Pos struct {
func MakePos(base *PosBase, line, col uint) Pos { return Pos{base, sat32(line), sat32(col)} }
// TODO(gri) IsKnown makes an assumption about linebase < 1.
// Maybe we should check for Base() != nil instead.
// Maybe we should check for Base() != nil instead.
func (pos Pos) Pos() Pos { return pos }
func (pos Pos) IsKnown() bool { return pos.line > 0 }

View file

@ -18,7 +18,7 @@ func TestPrint(t *testing.T) {
t.Skip("skipping test in short mode")
}
ast, _ := ParseFile(*src_, func(err error) { t.Error(err) }, nil, AllowGenerics)
ast, _ := ParseFile(*src_, func(err error) { t.Error(err) }, nil, 0)
if ast != nil {
Fprint(testOut(), ast, LineForm)
@ -117,7 +117,7 @@ var stringTests = [][2]string{
func TestPrintString(t *testing.T) {
for _, test := range stringTests {
ast, err := Parse(nil, strings.NewReader(test[0]), nil, nil, AllowGenerics)
ast, err := Parse(nil, strings.NewReader(test[0]), nil, nil, 0)
if err != nil {
t.Error(err)
continue
@ -237,7 +237,7 @@ var exprTests = [][2]string{
func TestShortString(t *testing.T) {
for _, test := range exprTests {
src := "package p; var _ = " + test[0]
ast, err := Parse(nil, strings.NewReader(src), nil, nil, AllowGenerics)
ast, err := Parse(nil, strings.NewReader(src), nil, nil, 0)
if err != nil {
t.Errorf("%s: %s", test[0], err)
continue

View file

@ -16,8 +16,6 @@ type Mode uint
// Modes supported by the parser.
const (
CheckBranches Mode = 1 << iota // check correct use of labels, break, continue, and goto statements
AllowGenerics
AllowMethodTypeParams // does not support interface methods yet; ignored if AllowGenerics is not set
)
// Error describes a syntax error. Error implements the error interface.
@ -65,7 +63,6 @@ type PragmaHandler func(pos Pos, blank bool, text string, current Pragma) Pragma
// error, and the returned syntax tree is nil.
//
// If pragh != nil, it is called with each pragma encountered.
//
func Parse(base *PosBase, src io.Reader, errh ErrorHandler, pragh PragmaHandler, mode Mode) (_ *File, first error) {
defer func() {
if p := recover(); p != nil {

View file

@ -1,3 +1,7 @@
// 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 chans
import "runtime"
@ -22,7 +26,7 @@ func Ranger[T any]() (*Sender[T], *Receiver[T]) {
// A sender is used to send values to a Receiver.
type Sender[T any] struct {
values chan<- T
done <-chan bool
done <-chan bool
}
// Send sends a value to the receiver. It returns whether any more
@ -45,7 +49,7 @@ func (s *Sender[T]) Close() {
// A Receiver receives values from a Sender.
type Receiver[T any] struct {
values <-chan T
done chan<- bool
done chan<- bool
}
// Next returns the next value from the channel. The bool result

View file

@ -1,60 +0,0 @@
// Copyright 2019 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 myInt int
// Parameterized type declarations
type T1[P any] P
type T2[P any] struct {
f P
g int // int should still be in scope chain
}
type List[P any] []P
// Alias type declarations cannot have type parameters. Syntax error.
// TODO(gri) Disabled for now as we don't check syntax error here.
// type A1[P any] = /* ERROR cannot be alias */ P
// But an alias may refer to a generic, uninstantiated type.
type A2 = List
var _ A2[int]
var _ A2 /* ERROR without instantiation */
type A3 = List[int]
var _ A3
// Parameterized type instantiations
var x int
type _ x /* ERROR not a type */ [int]
type _ int /* ERROR not a generic type */ [int]
type _ myInt /* ERROR not a generic type */ [int]
// TODO(gri) better error messages
type _ T1[int]
type _ T1[x /* ERROR not a type */ ]
type _ T1 /* ERROR got 2 arguments but 1 type parameters */ [int, float32]
var _ T2[int] = T2[int]{}
var _ List[int] = []int{1, 2, 3}
var _ List[[]int] = [][]int{{1, 2, 3}}
var _ List[List[List[int]]]
// Parameterized types containing parameterized types
type T3[P any] List[P]
var _ T3[int] = T3[int](List[int]{1, 2, 3})
// Self-recursive generic types are not permitted
type self1[P any] self1 /* ERROR illegal cycle */ [P]
type self2[P any] *self2[P] // this is ok

View file

@ -1,232 +0,0 @@
// Copyright 2019 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 List[E any] []E
var _ List[List[List[int]]]
var _ List[List[List[int]]] = []List[List[int]]{}
type (
T1[P1 any] struct {
f1 T2[P1, float32]
}
T2[P2, P3 any] struct {
f2 P2
f3 P3
}
)
func _() {
var x1 T1[int]
var x2 T2[int, float32]
x1.f1.f2 = 0
x1.f1 = x2
}
type T3[P any] T1[T2[P, P]]
func _() {
var x1 T3[int]
var x2 T2[int, int]
x1.f1.f2 = x2
}
func f[P any] (x P) List[P] {
return List[P]{x}
}
var (
_ []int = f(0)
_ []float32 = f[float32](10)
_ List[complex128] = f(1i)
_ []List[int] = f(List[int]{})
_ List[List[int]] = []List[int]{}
_ = []List[int]{}
)
// Parameterized types with methods
func (l List[E]) Head() (_ E, _ bool) {
if len(l) > 0 {
return l[0], true
}
return
}
// A test case for instantiating types with other types (extracted from map.go2)
type Pair[K any] struct {
key K
}
type Receiver[T any] struct {
values T
}
type Iterator[K any] struct {
r Receiver[Pair[K]]
}
func Values [T any] (r Receiver[T]) T {
return r.values
}
func (it Iterator[K]) Next() K {
return Values[Pair[K]](it.r).key
}
// A more complex test case testing type bounds (extracted from linalg.go2 and reduced to essence)
type NumericAbs[T any] interface {
Abs() T
}
func AbsDifference[T NumericAbs[T]](x T)
type OrderedAbs[T any] T
func (a OrderedAbs[T]) Abs() OrderedAbs[T]
func OrderedAbsDifference[T any](x T) {
AbsDifference(OrderedAbs[T](x))
}
// same code, reduced to essence
func g[P interface{ m() P }](x P)
type T4[P any] P
func (_ T4[P]) m() T4[P]
func _[Q any](x Q) {
g(T4[Q](x))
}
// Another test case that caused problems in the past
type T5[_ interface { a() }, _ interface{}] struct{}
type A[P any] struct{ x P }
func (_ A[P]) a() {}
var _ T5[A[int], int]
// Invoking methods with parameterized receiver types uses
// type inference to determine the actual type arguments matching
// the receiver type parameters from the actual receiver argument.
// Go does implicit address-taking and dereferenciation depending
// on the actual receiver and the method's receiver type. To make
// type inference work, the type-checker matches "pointer-ness"
// of the actual receiver and the method's receiver type.
// The following code tests this mechanism.
type R1[A any] struct{}
func (_ R1[A]) vm()
func (_ *R1[A]) pm()
func _[T any](r R1[T], p *R1[T]) {
r.vm()
r.pm()
p.vm()
p.pm()
}
type R2[A, B any] struct{}
func (_ R2[A, B]) vm()
func (_ *R2[A, B]) pm()
func _[T any](r R2[T, int], p *R2[string, T]) {
r.vm()
r.pm()
p.vm()
p.pm()
}
// Interface type constraints can contain any type, incl. *Named types.
// Verify that we use the underlying type to compute the operational type.
type MyInt int
func add1[T interface{ ~MyInt }](x T) T {
return x + 1
}
type MyString string
func double[T interface{ ~MyInt | ~MyString }](x T) T {
return x + x
}
// Embedding of interfaces with type constraints leads to interfaces
// with type constraints that are the intersection of the embedded
// type constraints.
type E0 interface {
~int | ~bool | ~string
}
type E1 interface {
~int | ~float64 | ~string
}
type E2 interface {
~float64
}
type I0 interface {
E0
}
func f0[T I0]()
var _ = f0[int]
var _ = f0[bool]
var _ = f0[string]
var _ = f0[float64 /* ERROR does not satisfy I0 */ ]
type I01 interface {
E0
E1
}
func f01[T I01]()
var _ = f01[int]
var _ = f01[bool /* ERROR does not satisfy I0 */ ]
var _ = f01[string]
var _ = f01[float64 /* ERROR does not satisfy I0 */ ]
type I012 interface {
E0
E1
E2
}
func f012[T I012]()
var _ = f012[int /* ERROR does not satisfy I012 */ ]
var _ = f012[bool /* ERROR does not satisfy I012 */ ]
var _ = f012[string /* ERROR does not satisfy I012 */ ]
var _ = f012[float64 /* ERROR does not satisfy I012 */ ]
type I12 interface {
E1
E2
}
func f12[T I12]()
var _ = f12[int /* ERROR does not satisfy I12 */ ]
var _ = f12[bool /* ERROR does not satisfy I12 */ ]
var _ = f12[string /* ERROR does not satisfy I12 */ ]
var _ = f12[float64]
type I0_ interface {
E0
~int
}
func f0_[T I0_]()
var _ = f0_[int]
var _ = f0_[bool /* ERROR does not satisfy I0_ */ ]
var _ = f0_[string /* ERROR does not satisfy I0_ */ ]
var _ = f0_[float64 /* ERROR does not satisfy I0_ */ ]

View file

@ -1,451 +0,0 @@
// Copyright 2018 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
// import "io" // for type assertion tests
// The predeclared identifier "any" is only visible as a constraint
// in a type parameter list.
var _ any // ERROR undeclared
func _[_ any /* ok here */ , _ interface{any /* ERROR undeclared */ }](any /* ERROR undeclared */ ) {
var _ any /* ERROR undeclared */
}
func identity[T any](x T) T { return x }
func _[_ any](x int) int
func _[T any](T /* ERROR redeclared */ T)()
func _[T, T /* ERROR redeclared */ any]()
func reverse[T any](list []T) []T {
rlist := make([]T, len(list))
i := len(list)
for _, x := range list {
i--
rlist[i] = x
}
return rlist
}
var _ = reverse /* ERROR cannot use generic function reverse */
var _ = reverse[int, float32 /* ERROR got 2 type arguments */ ] ([]int{1, 2, 3})
var _ = reverse[int]([ /* ERROR cannot use */ ]float32{1, 2, 3})
var f = reverse[chan int]
var _ = f(0 /* ERROR cannot convert 0 .* to \[\]chan int */ )
func swap[A, B any](a A, b B) (B, A) { return b, a }
var _ = swap /* ERROR single value is expected */ [int, float32](1, 2)
var f32, i = swap[int, float32](swap(float32, int)(1, 2))
var _ float32 = f32
var _ int = i
func swapswap[A, B any](a A, b B) (A, B) {
return swap[B, A](b, a)
}
type F[A, B any] func(A, B) (B, A)
func min[T interface{ ~int }](x, y T) T {
if x < y {
return x
}
return y
}
func _[T interface{ ~int | ~float32 }](x, y T) bool { return x < y }
func _[T any](x, y T) bool { return x /* ERROR cannot compare */ < y }
func _[T interface{ ~int | ~float32 | ~bool }](x, y T) bool { return x /* ERROR cannot compare */ < y }
func _[T C1[T]](x, y T) bool { return x /* ERROR cannot compare */ < y }
func _[T C2[T]](x, y T) bool { return x < y }
type C1[T any] interface{}
type C2[T any] interface{ ~int | ~float32 }
func new[T any]() *T {
var x T
return &x
}
var _ = new /* ERROR cannot use generic function new */
var _ *int = new[int]()
func _[T any](map[T /* ERROR invalid map key type T \(missing comparable constraint\) */]int) // w/o constraint we don't know if T is comparable
func f1[T1 any](struct{T1}) int
var _ = f1(int)(struct{T1}{})
type T1 = int
func f2[t1 any](struct{t1; x float32}) int
var _ = f2(t1)(struct{t1; x float32}{})
type t1 = int
func f3[A, B, C any](A, struct{x B}, func(A, struct{x B}, *C)) int
var _ = f3[int, rune, bool](1, struct{x rune}{}, nil)
// indexing
func _[T any] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] }
func _[T interface{ ~int }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] }
func _[T interface{ ~string }] (x T, i int) { _ = x[i] }
func _[T interface{ ~[]int }] (x T, i int) { _ = x[i] }
func _[T interface{ ~[10]int | ~*[20]int | ~map[string]int }] (x T, i int) { _ = x[i] }
func _[T interface{ ~string | ~[]byte }] (x T, i int) { _ = x[i] }
func _[T interface{ ~[]int | ~[1]rune }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] }
func _[T interface{ ~string | ~[]rune }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] }
// slicing
// TODO(gri) implement this
func _[T interface{ ~string }] (x T, i, j, k int) { _ = x /* ERROR invalid operation */ [i:j:k] }
// len/cap built-ins
func _[T any](x T) { _ = len(x /* ERROR invalid argument */ ) }
func _[T interface{ ~int }](x T) { _ = len(x /* ERROR invalid argument */ ) }
func _[T interface{ ~string | ~[]byte | ~int }](x T) { _ = len(x /* ERROR invalid argument */ ) }
func _[T interface{ ~string }](x T) { _ = len(x) }
func _[T interface{ ~[10]int }](x T) { _ = len(x) }
func _[T interface{ ~[]byte }](x T) { _ = len(x) }
func _[T interface{ ~map[int]int }](x T) { _ = len(x) }
func _[T interface{ ~chan int }](x T) { _ = len(x) }
func _[T interface{ ~string | ~[]byte | ~chan int }](x T) { _ = len(x) }
func _[T any](x T) { _ = cap(x /* ERROR invalid argument */ ) }
func _[T interface{ ~int }](x T) { _ = cap(x /* ERROR invalid argument */ ) }
func _[T interface{ ~string | ~[]byte | ~int }](x T) { _ = cap(x /* ERROR invalid argument */ ) }
func _[T interface{ ~string }](x T) { _ = cap(x /* ERROR invalid argument */ ) }
func _[T interface{ ~[10]int }](x T) { _ = cap(x) }
func _[T interface{ ~[]byte }](x T) { _ = cap(x) }
func _[T interface{ ~map[int]int }](x T) { _ = cap(x /* ERROR invalid argument */ ) }
func _[T interface{ ~chan int }](x T) { _ = cap(x) }
func _[T interface{ ~[]byte | ~chan int }](x T) { _ = cap(x) }
// range iteration
func _[T interface{}](x T) {
for range x /* ERROR cannot range */ {}
}
func _[T interface{ ~string | ~[]string }](x T) {
for range x {}
for i := range x { _ = i }
for i, _ := range x { _ = i }
for i, e := range x /* ERROR must have the same element type */ { _ = i }
for _, e := range x /* ERROR must have the same element type */ {}
var e rune
_ = e
for _, (e) = range x /* ERROR must have the same element type */ {}
}
func _[T interface{ ~string | ~[]rune | ~map[int]rune }](x T) {
for _, e := range x { _ = e }
for i, e := range x { _ = i; _ = e }
}
func _[T interface{ ~string | ~[]rune | ~map[string]rune }](x T) {
for _, e := range x { _ = e }
for i, e := range x /* ERROR must have the same key type */ { _ = e }
}
func _[T interface{ ~string | ~chan int }](x T) {
for range x {}
for i := range x { _ = i }
for i, _ := range x { _ = i } // TODO(gri) should get an error here: channels only return one value
}
func _[T interface{ ~string | ~chan<-int }](x T) {
for i := range x /* ERROR send-only channel */ { _ = i }
}
// type inference checks
var _ = new() /* ERROR cannot infer T */
func f4[A, B, C any](A, B) C
var _ = f4(1, 2) /* ERROR cannot infer C */
var _ = f4[int, float32, complex128](1, 2)
func f5[A, B, C any](A, []*B, struct{f []C}) int
var _ = f5[int, float32, complex128](0, nil, struct{f []complex128}{})
var _ = f5(0, nil, struct{f []complex128}{}) // ERROR cannot infer
var _ = f5(0, []*float32{new[float32]()}, struct{f []complex128}{})
func f6[A any](A, []A) int
var _ = f6(0, nil)
func f6nil[A any](A) int
var _ = f6nil(nil) // ERROR cannot infer
// type inference with variadic functions
func f7[T any](...T) T
var _ int = f7() /* ERROR cannot infer T */
var _ int = f7(1)
var _ int = f7(1, 2)
var _ int = f7([]int{}...)
var _ int = f7 /* ERROR cannot use */ ([]float64{}...)
var _ float64 = f7([]float64{}...)
var _ = f7[float64](1, 2.3)
var _ = f7(float64(1), 2.3)
var _ = f7(1, 2.3 /* ERROR does not match */ )
var _ = f7(1.2, 3 /* ERROR does not match */ )
func f8[A, B any](A, B, ...B) int
var _ = f8(1) /* ERROR not enough arguments */
var _ = f8(1, 2.3)
var _ = f8(1, 2.3, 3.4, 4.5)
var _ = f8(1, 2.3, 3.4, 4 /* ERROR does not match */ )
var _ = f8(int, float64)(1, 2.3, 3.4, 4)
var _ = f8(int, float64)(0, 0, nil...) // test case for #18268
// init functions cannot have type parameters
func init() {}
func init[/* ERROR func init must have no type parameters */ _ any]() {}
func init[/* ERROR func init must have no type parameters */ P any]() {}
type T struct {}
func (T) m1() {}
// The type checker accepts method type parameters if configured accordingly.
func (T) m2[_ any]() {}
func (T) m3[P any]() {}
// type inference across parameterized types
type S1[P any] struct { f P }
func f9[P any](x S1[P])
func _() {
f9[int](S1[int]{42})
f9(S1[int]{42})
}
type S2[A, B, C any] struct{}
func f10[X, Y, Z any](a S2[X, int, Z], b S2[X, Y, bool])
func _[P any]() {
f10[int, float32, string](S2[int, int, string]{}, S2[int, float32, bool]{})
f10(S2[int, int, string]{}, S2[int, float32, bool]{})
f10(S2[P, int, P]{}, S2[P, float32, bool]{})
}
// corner case for type inference
// (was bug: after instanting f11, the type-checker didn't mark f11 as non-generic)
func f11[T any]()
func _() {
f11[int]()
}
// the previous example was extracted from
func f12[T interface{m() T}]()
type A[T any] T
func (a A[T]) m() A[T]
func _[T any]() {
f12(A[T])()
}
// method expressions
func (_ S1[P]) m()
func _() {
m := S1[int].m
m(struct { f int }{42})
}
func _[T any] (x T) {
m := S1[T].m
m(S1[T]{x})
}
// type parameters in methods (generalization)
type R0 struct{}
func (R0) _[T any](x T)
func (R0 /* ERROR invalid receiver */ ) _[R0 any]() // scope of type parameters starts at "func"
type R1[A, B any] struct{}
func (_ R1[A, B]) m0(A, B)
func (_ R1[A, B]) m1[T any](A, B, T) T
func (_ R1 /* ERROR not a generic type */ [R1, _]) _()
func (_ R1[A, B]) _[A /* ERROR redeclared */ any](B)
func _() {
var r R1[int, string]
r.m1[rune](42, "foo", 'a')
r.m1[rune](42, "foo", 1.2 /* ERROR truncated to rune */)
r.m1(42, "foo", 1.2) // using type inference
var _ float64 = r.m1(42, "foo", 1.2)
}
type I1[A any] interface {
m1(A)
}
var _ I1[int] = r1[int]{}
type r1[T any] struct{}
func (_ r1[T]) m1(T)
type I2[A, B any] interface {
m1(A)
m2(A) B
}
var _ I2[int, float32] = R2[int, float32]{}
type R2[P, Q any] struct{}
func (_ R2[X, Y]) m1(X)
func (_ R2[X, Y]) m2(X) Y
// type assertions and type switches over generic types
// NOTE: These are currently disabled because it's unclear what the correct
// approach is, and one can always work around by assigning the variable to
// an interface first.
// // ReadByte1 corresponds to the ReadByte example in the draft design.
// func ReadByte1[T io.Reader](r T) (byte, error) {
// if br, ok := r.(io.ByteReader); ok {
// return br.ReadByte()
// }
// var b [1]byte
// _, err := r.Read(b[:])
// return b[0], err
// }
//
// // ReadBytes2 is like ReadByte1 but uses a type switch instead.
// func ReadByte2[T io.Reader](r T) (byte, error) {
// switch br := r.(type) {
// case io.ByteReader:
// return br.ReadByte()
// }
// var b [1]byte
// _, err := r.Read(b[:])
// return b[0], err
// }
//
// // type assertions and type switches over generic types are strict
// type I3 interface {
// m(int)
// }
//
// type I4 interface {
// m() int // different signature from I3.m
// }
//
// func _[T I3](x I3, p T) {
// // type assertions and type switches over interfaces are not strict
// _ = x.(I4)
// switch x.(type) {
// case I4:
// }
//
// // type assertions and type switches over generic types are strict
// _ = p /* ERROR cannot have dynamic type I4 */.(I4)
// switch p.(type) {
// case I4 /* ERROR cannot have dynamic type I4 */ :
// }
// }
// type assertions and type switches over generic types lead to errors for now
func _[T any](x T) {
_ = x /* ERROR not an interface */ .(int)
switch x /* ERROR not an interface */ .(type) {
}
// work-around
var t interface{} = x
_ = t.(int)
switch t.(type) {
}
}
func _[T interface{ ~int }](x T) {
_ = x /* ERROR not an interface */ .(int)
switch x /* ERROR not an interface */ .(type) {
}
// work-around
var t interface{} = x
_ = t.(int)
switch t.(type) {
}
}
// error messages related to type bounds mention those bounds
type C[P any] interface{}
func _[P C[P]] (x P) {
x.m /* ERROR x.m undefined */ ()
}
type I interface {}
func _[P I] (x P) {
x.m /* ERROR interface I has no method m */ ()
}
func _[P interface{}] (x P) {
x.m /* ERROR type bound for P has no method m */ ()
}
func _[P any] (x P) {
x.m /* ERROR type bound for P has no method m */ ()
}
// automatic distinguishing between array and generic types
// NOTE: Disabled when using unified parameter list syntax.
/*
const P = 10
type A1 [P]byte
func _(a A1) {
assert(len(a) == 10)
}
type A2 [P]struct{
f [P]byte
}
func _(a A2) {
assert(len(a) == 10)
assert(len(a[0].f) == 10)
}
type A3 [P]func(x [P]A3)
func _(a A3) {
assert(len(a) == 10)
}
type T2[P] struct{ P }
var _ T2[int]
type T3[P] func(P)
var _ T3[int]
*/

View file

@ -4,7 +4,6 @@
package p
// error messages for parser in generic mode
func _() {
_ = m[] // ERROR expecting operand
_ = m[x,]

View file

@ -1,18 +0,0 @@
// Copyright 2021 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
// error messages for parser in non-generic mode
func _() {
_ = m[] // ERROR expecting operand
_ = m[x,] // ERROR unexpected comma, expecting \: or \]
_ = m[x /* ERROR unexpected a */ a b c d]
}
// test case from the issue
func f(m map[int]int) int {
return m[0 // ERROR expecting \: or \]
]
}

View 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 p
// test case from issue
type _ interface{
m /* ERROR unexpected int in interface type; possibly missing semicolon or newline or } */ int
}
// other cases where the fix for this issue affects the error message
const (
x int = 10 /* ERROR unexpected literal "foo" in grouped declaration; possibly missing semicolon or newline or \) */ "foo"
)
var _ = []int{1, 2, 3 /* ERROR unexpected int in composite literal; possibly missing comma or } */ int }
type _ struct {
x y /* ERROR syntax error: unexpected comma in struct type; possibly missing semicolon or newline or } */ ,
}
func f(a, b c /* ERROR unexpected d in parameter list; possibly missing comma or \) */ d) {
f(a, b, c /* ERROR unexpected d in argument list; possibly missing comma or \) */ d)
}

View file

@ -5,8 +5,7 @@
// Package orderedmap provides an ordered map, implemented as a binary tree.
package orderedmap
// TODO(gri) fix imports for tests
import "chans" // ERROR could not import
import "chans"
// Map is an ordered map.
type Map[K, V any] struct {

View file

@ -56,7 +56,7 @@ func reducer(x float64, y int) float64 {
}
var reduced1 = Reduce[int, float64](input, 0, reducer)
var reduced2 = Reduce(input, 1i /* ERROR overflows */, reducer) // using type inference
var reduced2 = Reduce(input, 1i, reducer) // using type inference
var reduced3 = Reduce(input, 1, reducer) // using type inference
func filter(x int) bool {

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