mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.boringcrypto] all: merge master into dev.boringcrypto
Merge at CL 144340, in order to cherry-pick CL 149459 next to it, which fixes a BoringCrypto specific breakage in the toolchain. Change-Id: I30aeac344bbff279449e27876dc8f9c406e55e43
This commit is contained in:
commit
11e916773e
33 changed files with 688 additions and 176 deletions
|
|
@ -14,6 +14,7 @@ import (
|
||||||
// io.ByteScanner, and io.RuneScanner interfaces by reading from
|
// io.ByteScanner, and io.RuneScanner interfaces by reading from
|
||||||
// a byte slice.
|
// a byte slice.
|
||||||
// Unlike a Buffer, a Reader is read-only and supports seeking.
|
// Unlike a Buffer, a Reader is read-only and supports seeking.
|
||||||
|
// The zero value for Reader operates like a Reader of an empty slice.
|
||||||
type Reader struct {
|
type Reader struct {
|
||||||
s []byte
|
s []byte
|
||||||
i int64 // current reading index
|
i int64 // current reading index
|
||||||
|
|
@ -75,10 +76,10 @@ func (r *Reader) ReadByte() (byte, error) {
|
||||||
|
|
||||||
// UnreadByte complements ReadByte in implementing the io.ByteScanner interface.
|
// UnreadByte complements ReadByte in implementing the io.ByteScanner interface.
|
||||||
func (r *Reader) UnreadByte() error {
|
func (r *Reader) UnreadByte() error {
|
||||||
r.prevRune = -1
|
|
||||||
if r.i <= 0 {
|
if r.i <= 0 {
|
||||||
return errors.New("bytes.Reader.UnreadByte: at beginning of slice")
|
return errors.New("bytes.Reader.UnreadByte: at beginning of slice")
|
||||||
}
|
}
|
||||||
|
r.prevRune = -1
|
||||||
r.i--
|
r.i--
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -101,6 +102,9 @@ func (r *Reader) ReadRune() (ch rune, size int, err error) {
|
||||||
|
|
||||||
// UnreadRune complements ReadRune in implementing the io.RuneScanner interface.
|
// UnreadRune complements ReadRune in implementing the io.RuneScanner interface.
|
||||||
func (r *Reader) UnreadRune() error {
|
func (r *Reader) UnreadRune() error {
|
||||||
|
if r.i <= 0 {
|
||||||
|
return errors.New("bytes.Reader.UnreadRune: at beginning of slice")
|
||||||
|
}
|
||||||
if r.prevRune < 0 {
|
if r.prevRune < 0 {
|
||||||
return errors.New("bytes.Reader.UnreadRune: previous operation was not ReadRune")
|
return errors.New("bytes.Reader.UnreadRune: previous operation was not ReadRune")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -276,3 +276,45 @@ func TestReaderReset(t *testing.T) {
|
||||||
t.Errorf("ReadAll: got %q, want %q", got, want)
|
t.Errorf("ReadAll: got %q, want %q", got, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestReaderZero(t *testing.T) {
|
||||||
|
if l := (&Reader{}).Len(); l != 0 {
|
||||||
|
t.Errorf("Len: got %d, want 0", l)
|
||||||
|
}
|
||||||
|
|
||||||
|
if n, err := (&Reader{}).Read(nil); n != 0 || err != io.EOF {
|
||||||
|
t.Errorf("Read: got %d, %v; want 0, io.EOF", n, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if n, err := (&Reader{}).ReadAt(nil, 11); n != 0 || err != io.EOF {
|
||||||
|
t.Errorf("ReadAt: got %d, %v; want 0, io.EOF", n, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b, err := (&Reader{}).ReadByte(); b != 0 || err != io.EOF {
|
||||||
|
t.Errorf("ReadByte: got %d, %v; want 0, io.EOF", b, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ch, size, err := (&Reader{}).ReadRune(); ch != 0 || size != 0 || err != io.EOF {
|
||||||
|
t.Errorf("ReadRune: got %d, %d, %v; want 0, 0, io.EOF", ch, size, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if offset, err := (&Reader{}).Seek(11, io.SeekStart); offset != 11 || err != nil {
|
||||||
|
t.Errorf("Seek: got %d, %v; want 11, nil", offset, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if s := (&Reader{}).Size(); s != 0 {
|
||||||
|
t.Errorf("Size: got %d, want 0", s)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (&Reader{}).UnreadByte() == nil {
|
||||||
|
t.Errorf("UnreadByte: got nil, want error")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (&Reader{}).UnreadRune() == nil {
|
||||||
|
t.Errorf("UnreadRune: got nil, want error")
|
||||||
|
}
|
||||||
|
|
||||||
|
if n, err := (&Reader{}).WriteTo(ioutil.Discard); n != 0 || err != nil {
|
||||||
|
t.Errorf("WriteTo: got %d, %v; want 0, nil", n, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,9 @@ Flags:
|
||||||
instead of $GOROOT/pkg/$GOOS_$GOARCH.
|
instead of $GOROOT/pkg/$GOOS_$GOARCH.
|
||||||
-l
|
-l
|
||||||
Disable inlining.
|
Disable inlining.
|
||||||
|
-lang version
|
||||||
|
Set language version to compile, as in -lang=go1.12.
|
||||||
|
Default is current version.
|
||||||
-largemodel
|
-largemodel
|
||||||
Generate code that assumes a large memory model.
|
Generate code that assumes a large memory model.
|
||||||
-linkobj file
|
-linkobj file
|
||||||
|
|
|
||||||
|
|
@ -762,12 +762,20 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||||
sc := v.AuxValAndOff()
|
sc := v.AuxValAndOff()
|
||||||
off := sc.Off()
|
off := sc.Off()
|
||||||
val := sc.Val()
|
val := sc.Val()
|
||||||
if val == 1 {
|
if val == 1 || val == -1 {
|
||||||
var asm obj.As
|
var asm obj.As
|
||||||
if v.Op == ssa.OpAMD64ADDQconstmodify {
|
if v.Op == ssa.OpAMD64ADDQconstmodify {
|
||||||
asm = x86.AINCQ
|
if val == 1 {
|
||||||
|
asm = x86.AINCQ
|
||||||
|
} else {
|
||||||
|
asm = x86.ADECQ
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
asm = x86.AINCL
|
if val == 1 {
|
||||||
|
asm = x86.AINCL
|
||||||
|
} else {
|
||||||
|
asm = x86.ADECL
|
||||||
|
}
|
||||||
}
|
}
|
||||||
p := s.Prog(asm)
|
p := s.Prog(asm)
|
||||||
p.To.Type = obj.TYPE_MEM
|
p.To.Type = obj.TYPE_MEM
|
||||||
|
|
|
||||||
|
|
@ -117,8 +117,8 @@ var runtimeDecls = [...]struct {
|
||||||
{"selectsetpc", funcTag, 56},
|
{"selectsetpc", funcTag, 56},
|
||||||
{"selectgo", funcTag, 93},
|
{"selectgo", funcTag, 93},
|
||||||
{"block", funcTag, 5},
|
{"block", funcTag, 5},
|
||||||
{"makeslice", funcTag, 95},
|
{"makeslice", funcTag, 94},
|
||||||
{"makeslice64", funcTag, 96},
|
{"makeslice64", funcTag, 95},
|
||||||
{"growslice", funcTag, 97},
|
{"growslice", funcTag, 97},
|
||||||
{"memmove", funcTag, 98},
|
{"memmove", funcTag, 98},
|
||||||
{"memclrNoHeapPointers", funcTag, 99},
|
{"memclrNoHeapPointers", funcTag, 99},
|
||||||
|
|
@ -249,10 +249,10 @@ func runtimeTypes() []*types.Type {
|
||||||
typs[91] = types.NewPtr(typs[11])
|
typs[91] = types.NewPtr(typs[11])
|
||||||
typs[92] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[91]), anonfield(typs[79])}, []*Node{anonfield(typs[11])})
|
typs[92] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[91]), anonfield(typs[79])}, []*Node{anonfield(typs[11])})
|
||||||
typs[93] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[32])}, []*Node{anonfield(typs[32]), anonfield(typs[11])})
|
typs[93] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[32])}, []*Node{anonfield(typs[32]), anonfield(typs[11])})
|
||||||
typs[94] = types.NewSlice(typs[2])
|
typs[94] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32]), anonfield(typs[32])}, []*Node{anonfield(typs[58])})
|
||||||
typs[95] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32]), anonfield(typs[32])}, []*Node{anonfield(typs[94])})
|
typs[95] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[58])})
|
||||||
typs[96] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[94])})
|
typs[96] = types.NewSlice(typs[2])
|
||||||
typs[97] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[94]), anonfield(typs[32])}, []*Node{anonfield(typs[94])})
|
typs[97] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[96]), anonfield(typs[32])}, []*Node{anonfield(typs[96])})
|
||||||
typs[98] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[47])}, nil)
|
typs[98] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[47])}, nil)
|
||||||
typs[99] = functype(nil, []*Node{anonfield(typs[58]), anonfield(typs[47])}, nil)
|
typs[99] = functype(nil, []*Node{anonfield(typs[58]), anonfield(typs[47])}, nil)
|
||||||
typs[100] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[47])}, []*Node{anonfield(typs[11])})
|
typs[100] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[47])}, []*Node{anonfield(typs[11])})
|
||||||
|
|
|
||||||
|
|
@ -153,8 +153,8 @@ func selectsetpc(cas *byte)
|
||||||
func selectgo(cas0 *byte, order0 *byte, ncases int) (int, bool)
|
func selectgo(cas0 *byte, order0 *byte, ncases int) (int, bool)
|
||||||
func block()
|
func block()
|
||||||
|
|
||||||
func makeslice(typ *byte, len int, cap int) (ary []any)
|
func makeslice(typ *byte, len int, cap int) unsafe.Pointer
|
||||||
func makeslice64(typ *byte, len int64, cap int64) (ary []any)
|
func makeslice64(typ *byte, len int64, cap int64) unsafe.Pointer
|
||||||
func growslice(typ *byte, old []any, cap int) (ary []any)
|
func growslice(typ *byte, old []any, cap int) (ary []any)
|
||||||
func memmove(to *any, frm *any, length uintptr)
|
func memmove(to *any, frm *any, length uintptr)
|
||||||
func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
||||||
|
|
|
||||||
59
src/cmd/compile/internal/gc/lang_test.go
Normal file
59
src/cmd/compile/internal/gc/lang_test.go
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
// 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 gc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"internal/testenv"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
const aliasSrc = `
|
||||||
|
package x
|
||||||
|
|
||||||
|
type T = int
|
||||||
|
`
|
||||||
|
|
||||||
|
func TestInvalidLang(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
testenv.MustHaveGoBuild(t)
|
||||||
|
|
||||||
|
dir, err := ioutil.TempDir("", "TestInvalidLang")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
|
src := filepath.Join(dir, "alias.go")
|
||||||
|
if err := ioutil.WriteFile(src, []byte(aliasSrc), 0644); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
outfile := filepath.Join(dir, "alias.o")
|
||||||
|
|
||||||
|
if testLang(t, "go9.99", src, outfile) == nil {
|
||||||
|
t.Error("compilation with -lang=go9.99 succeeded unexpectedly")
|
||||||
|
}
|
||||||
|
|
||||||
|
if testLang(t, "go1.8", src, outfile) == nil {
|
||||||
|
t.Error("compilation with -lang=go1.8 succeeded unexpectedly")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := testLang(t, "go1.9", src, outfile); err != nil {
|
||||||
|
t.Errorf("compilation with -lang=go1.9 failed unexpectedly: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testLang(t *testing.T, lang, src, outfile string) error {
|
||||||
|
run := []string{testenv.GoToolPath(t), "tool", "compile", "-lang", lang, "-o", outfile, src}
|
||||||
|
t.Log(run)
|
||||||
|
out, err := exec.Command(run[0], run[1:]...).CombinedOutput()
|
||||||
|
t.Logf("%s", out)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
@ -19,11 +19,13 @@ import (
|
||||||
"cmd/internal/sys"
|
"cmd/internal/sys"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"go/build"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"regexp"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
@ -211,6 +213,7 @@ func Main(archInit func(*Arch)) {
|
||||||
flag.StringVar(&flag_installsuffix, "installsuffix", "", "set pkg directory `suffix`")
|
flag.StringVar(&flag_installsuffix, "installsuffix", "", "set pkg directory `suffix`")
|
||||||
objabi.Flagcount("j", "debug runtime-initialized variables", &Debug['j'])
|
objabi.Flagcount("j", "debug runtime-initialized variables", &Debug['j'])
|
||||||
objabi.Flagcount("l", "disable inlining", &Debug['l'])
|
objabi.Flagcount("l", "disable inlining", &Debug['l'])
|
||||||
|
flag.StringVar(&flag_lang, "lang", defaultLang(), "release to compile for")
|
||||||
flag.StringVar(&linkobj, "linkobj", "", "write linker-specific object to `file`")
|
flag.StringVar(&linkobj, "linkobj", "", "write linker-specific object to `file`")
|
||||||
objabi.Flagcount("live", "debug liveness analysis", &debuglive)
|
objabi.Flagcount("live", "debug liveness analysis", &debuglive)
|
||||||
objabi.Flagcount("m", "print optimization decisions", &Debug['m'])
|
objabi.Flagcount("m", "print optimization decisions", &Debug['m'])
|
||||||
|
|
@ -277,6 +280,8 @@ func Main(archInit func(*Arch)) {
|
||||||
Exit(2)
|
Exit(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkLang()
|
||||||
|
|
||||||
thearch.LinkArch.Init(Ctxt)
|
thearch.LinkArch.Init(Ctxt)
|
||||||
|
|
||||||
if outfile == "" {
|
if outfile == "" {
|
||||||
|
|
@ -1304,3 +1309,66 @@ func recordFlags(flags ...string) {
|
||||||
Ctxt.Data = append(Ctxt.Data, s)
|
Ctxt.Data = append(Ctxt.Data, s)
|
||||||
s.P = cmd.Bytes()[1:]
|
s.P = cmd.Bytes()[1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// flag_lang is the language version we are compiling for, set by the -lang flag.
|
||||||
|
var flag_lang string
|
||||||
|
|
||||||
|
// defaultLang returns the default value for the -lang flag.
|
||||||
|
func defaultLang() string {
|
||||||
|
tags := build.Default.ReleaseTags
|
||||||
|
return tags[len(tags)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// goVersionRE is a regular expression that matches the valid
|
||||||
|
// arguments to the -lang flag.
|
||||||
|
var goVersionRE = regexp.MustCompile(`^go([1-9][0-9]*)\.(0|[1-9][0-9]*)$`)
|
||||||
|
|
||||||
|
// A lang is a language version broken into major and minor numbers.
|
||||||
|
type lang struct {
|
||||||
|
major, minor int
|
||||||
|
}
|
||||||
|
|
||||||
|
// langWant is the desired language version set by the -lang flag.
|
||||||
|
var langWant lang
|
||||||
|
|
||||||
|
// langSupported reports whether language version major.minor is supported.
|
||||||
|
func langSupported(major, minor int) bool {
|
||||||
|
return langWant.major > major || (langWant.major == major && langWant.minor >= minor)
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkLang verifies that the -lang flag holds a valid value, and
|
||||||
|
// exits if not. It initializes data used by langSupported.
|
||||||
|
func checkLang() {
|
||||||
|
var err error
|
||||||
|
langWant, err = parseLang(flag_lang)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("invalid value %q for -lang: %v", flag_lang, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if def := defaultLang(); flag_lang != def {
|
||||||
|
defVers, err := parseLang(def)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("internal error parsing default lang %q: %v", def, err)
|
||||||
|
}
|
||||||
|
if langWant.major > defVers.major || (langWant.major == defVers.major && langWant.major > defVers.minor) {
|
||||||
|
log.Fatalf("invalid value %q for -lang: max known version is %q", flag_lang, def)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseLang parses a -lang option into a langVer.
|
||||||
|
func parseLang(s string) (lang, error) {
|
||||||
|
matches := goVersionRE.FindStringSubmatch(s)
|
||||||
|
if matches == nil {
|
||||||
|
return lang{}, fmt.Errorf(`should be something like "go1.12"`)
|
||||||
|
}
|
||||||
|
major, err := strconv.Atoi(matches[1])
|
||||||
|
if err != nil {
|
||||||
|
return lang{}, err
|
||||||
|
}
|
||||||
|
minor, err := strconv.Atoi(matches[2])
|
||||||
|
if err != nil {
|
||||||
|
return lang{}, err
|
||||||
|
}
|
||||||
|
return lang{major: major, minor: minor}, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -417,8 +417,11 @@ func (p *noder) typeDecl(decl *syntax.TypeDecl) *Node {
|
||||||
param.Pragma = 0
|
param.Pragma = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.nod(decl, ODCLTYPE, n, nil)
|
nod := p.nod(decl, ODCLTYPE, n, nil)
|
||||||
|
if param.Alias && !langSupported(1, 9) {
|
||||||
|
yyerrorl(nod.Pos, "type aliases only supported as of -lang=go1.9")
|
||||||
|
}
|
||||||
|
return nod
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *noder) declNames(names []*syntax.Name) []*Node {
|
func (p *noder) declNames(names []*syntax.Name) []*Node {
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,9 @@ package gc
|
||||||
|
|
||||||
import "strconv"
|
import "strconv"
|
||||||
|
|
||||||
const _Op_name = "XXXNAMENONAMETYPEPACKLITERALADDSUBORXORADDSTRADDRANDANDAPPENDARRAYBYTESTRARRAYBYTESTRTMPARRAYRUNESTRSTRARRAYBYTESTRARRAYBYTETMPSTRARRAYRUNEASAS2AS2FUNCAS2RECVAS2MAPRAS2DOTTYPEASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLFIELDDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTINDINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMULDIVMODLSHRSHANDANDNOTNEWNOTCOMPLUSMINUSORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRRECOVERRECVRUNESTRSELRECVSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFBLOCKBREAKCASEXCASECONTINUEDEFEREMPTYFALLFORFORUNTILGOTOIFLABELPROCRANGERETURNSELECTSWITCHTYPESWTCHANTMAPTSTRUCTTINTERTFUNCTARRAYDDDDDDARGINLCALLEFACEITABIDATASPTRCLOSUREVARCFUNCCHECKNILVARDEFVARKILLVARLIVEINDREGSPRETJMPGETGEND"
|
const _Op_name = "XXXNAMENONAMETYPEPACKLITERALADDSUBORXORADDSTRADDRANDANDAPPENDARRAYBYTESTRARRAYBYTESTRTMPARRAYRUNESTRSTRARRAYBYTESTRARRAYBYTETMPSTRARRAYRUNEASAS2AS2FUNCAS2RECVAS2MAPRAS2DOTTYPEASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLFIELDDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTINDINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMULDIVMODLSHRSHANDANDNOTNEWNOTCOMPLUSMINUSORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICEHEADERSLICE3SLICE3ARRRECOVERRECVRUNESTRSELRECVSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFBLOCKBREAKCASEXCASECONTINUEDEFEREMPTYFALLFORFORUNTILGOTOIFLABELPROCRANGERETURNSELECTSWITCHTYPESWTCHANTMAPTSTRUCTTINTERTFUNCTARRAYDDDDDDARGINLCALLEFACEITABIDATASPTRCLOSUREVARCFUNCCHECKNILVARDEFVARKILLVARLIVEINDREGSPRETJMPGETGEND"
|
||||||
|
|
||||||
var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 36, 39, 45, 49, 55, 61, 73, 88, 100, 112, 127, 139, 141, 144, 151, 158, 165, 175, 179, 183, 191, 199, 208, 216, 219, 224, 231, 238, 244, 253, 261, 269, 275, 279, 288, 295, 299, 302, 309, 317, 325, 332, 338, 341, 347, 354, 362, 366, 373, 381, 383, 385, 387, 389, 391, 393, 396, 401, 409, 412, 421, 424, 428, 436, 443, 452, 455, 458, 461, 464, 467, 470, 476, 479, 482, 485, 489, 494, 498, 503, 508, 514, 519, 523, 528, 536, 544, 550, 559, 566, 570, 577, 584, 592, 596, 600, 604, 611, 618, 626, 632, 637, 642, 646, 651, 659, 664, 669, 673, 676, 684, 688, 690, 695, 699, 704, 710, 716, 722, 728, 733, 737, 744, 750, 755, 761, 764, 770, 777, 782, 786, 791, 795, 805, 810, 818, 824, 831, 838, 846, 852, 856, 859}
|
var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 36, 39, 45, 49, 55, 61, 73, 88, 100, 112, 127, 139, 141, 144, 151, 158, 165, 175, 179, 183, 191, 199, 208, 216, 219, 224, 231, 238, 244, 253, 261, 269, 275, 279, 288, 295, 299, 302, 309, 317, 325, 332, 338, 341, 347, 354, 362, 366, 373, 381, 383, 385, 387, 389, 391, 393, 396, 401, 409, 412, 421, 424, 428, 436, 443, 452, 455, 458, 461, 464, 467, 470, 476, 479, 482, 485, 489, 494, 498, 503, 508, 514, 519, 523, 528, 536, 544, 555, 561, 570, 577, 581, 588, 595, 603, 607, 611, 615, 622, 629, 637, 643, 648, 653, 657, 662, 670, 675, 680, 684, 687, 695, 699, 701, 706, 710, 715, 721, 727, 733, 739, 744, 748, 755, 761, 766, 772, 775, 781, 788, 793, 797, 802, 806, 816, 821, 829, 835, 842, 849, 857, 863, 867, 870}
|
||||||
|
|
||||||
func (i Op) String() string {
|
func (i Op) String() string {
|
||||||
if i >= Op(len(_Op_index)-1) {
|
if i >= Op(len(_Op_index)-1) {
|
||||||
|
|
|
||||||
|
|
@ -2321,6 +2321,12 @@ func (s *state) expr(n *Node) *ssa.Value {
|
||||||
data := s.expr(n.Right)
|
data := s.expr(n.Right)
|
||||||
return s.newValue2(ssa.OpIMake, n.Type, tab, data)
|
return s.newValue2(ssa.OpIMake, n.Type, tab, data)
|
||||||
|
|
||||||
|
case OSLICEHEADER:
|
||||||
|
p := s.expr(n.Left)
|
||||||
|
l := s.expr(n.List.First())
|
||||||
|
c := s.expr(n.List.Second())
|
||||||
|
return s.newValue3(ssa.OpSliceMake, n.Type, p, l, c)
|
||||||
|
|
||||||
case OSLICE, OSLICEARR, OSLICE3, OSLICE3ARR:
|
case OSLICE, OSLICEARR, OSLICE3, OSLICE3ARR:
|
||||||
v := s.expr(n.Left)
|
v := s.expr(n.Left)
|
||||||
var i, j, k *ssa.Value
|
var i, j, k *ssa.Value
|
||||||
|
|
|
||||||
|
|
@ -636,65 +636,66 @@ const (
|
||||||
ODCLCONST // const pi = 3.14
|
ODCLCONST // const pi = 3.14
|
||||||
ODCLTYPE // type Int int or type Int = int
|
ODCLTYPE // type Int int or type Int = int
|
||||||
|
|
||||||
ODELETE // delete(Left, Right)
|
ODELETE // delete(Left, Right)
|
||||||
ODOT // Left.Sym (Left is of struct type)
|
ODOT // Left.Sym (Left is of struct type)
|
||||||
ODOTPTR // Left.Sym (Left is of pointer to struct type)
|
ODOTPTR // Left.Sym (Left is of pointer to struct type)
|
||||||
ODOTMETH // Left.Sym (Left is non-interface, Right is method name)
|
ODOTMETH // Left.Sym (Left is non-interface, Right is method name)
|
||||||
ODOTINTER // Left.Sym (Left is interface, Right is method name)
|
ODOTINTER // Left.Sym (Left is interface, Right is method name)
|
||||||
OXDOT // Left.Sym (before rewrite to one of the preceding)
|
OXDOT // Left.Sym (before rewrite to one of the preceding)
|
||||||
ODOTTYPE // Left.Right or Left.Type (.Right during parsing, .Type once resolved); after walk, .Right contains address of interface type descriptor and .Right.Right contains address of concrete type descriptor
|
ODOTTYPE // Left.Right or Left.Type (.Right during parsing, .Type once resolved); after walk, .Right contains address of interface type descriptor and .Right.Right contains address of concrete type descriptor
|
||||||
ODOTTYPE2 // Left.Right or Left.Type (.Right during parsing, .Type once resolved; on rhs of OAS2DOTTYPE); after walk, .Right contains address of interface type descriptor
|
ODOTTYPE2 // Left.Right or Left.Type (.Right during parsing, .Type once resolved; on rhs of OAS2DOTTYPE); after walk, .Right contains address of interface type descriptor
|
||||||
OEQ // Left == Right
|
OEQ // Left == Right
|
||||||
ONE // Left != Right
|
ONE // Left != Right
|
||||||
OLT // Left < Right
|
OLT // Left < Right
|
||||||
OLE // Left <= Right
|
OLE // Left <= Right
|
||||||
OGE // Left >= Right
|
OGE // Left >= Right
|
||||||
OGT // Left > Right
|
OGT // Left > Right
|
||||||
OIND // *Left
|
OIND // *Left
|
||||||
OINDEX // Left[Right] (index of array or slice)
|
OINDEX // Left[Right] (index of array or slice)
|
||||||
OINDEXMAP // Left[Right] (index of map)
|
OINDEXMAP // Left[Right] (index of map)
|
||||||
OKEY // Left:Right (key:value in struct/array/map literal)
|
OKEY // Left:Right (key:value in struct/array/map literal)
|
||||||
OSTRUCTKEY // Sym:Left (key:value in struct literal, after type checking)
|
OSTRUCTKEY // Sym:Left (key:value in struct literal, after type checking)
|
||||||
OLEN // len(Left)
|
OLEN // len(Left)
|
||||||
OMAKE // make(List) (before type checking converts to one of the following)
|
OMAKE // make(List) (before type checking converts to one of the following)
|
||||||
OMAKECHAN // make(Type, Left) (type is chan)
|
OMAKECHAN // make(Type, Left) (type is chan)
|
||||||
OMAKEMAP // make(Type, Left) (type is map)
|
OMAKEMAP // make(Type, Left) (type is map)
|
||||||
OMAKESLICE // make(Type, Left, Right) (type is slice)
|
OMAKESLICE // make(Type, Left, Right) (type is slice)
|
||||||
OMUL // Left * Right
|
OMUL // Left * Right
|
||||||
ODIV // Left / Right
|
ODIV // Left / Right
|
||||||
OMOD // Left % Right
|
OMOD // Left % Right
|
||||||
OLSH // Left << Right
|
OLSH // Left << Right
|
||||||
ORSH // Left >> Right
|
ORSH // Left >> Right
|
||||||
OAND // Left & Right
|
OAND // Left & Right
|
||||||
OANDNOT // Left &^ Right
|
OANDNOT // Left &^ Right
|
||||||
ONEW // new(Left)
|
ONEW // new(Left)
|
||||||
ONOT // !Left
|
ONOT // !Left
|
||||||
OCOM // ^Left
|
OCOM // ^Left
|
||||||
OPLUS // +Left
|
OPLUS // +Left
|
||||||
OMINUS // -Left
|
OMINUS // -Left
|
||||||
OOROR // Left || Right
|
OOROR // Left || Right
|
||||||
OPANIC // panic(Left)
|
OPANIC // panic(Left)
|
||||||
OPRINT // print(List)
|
OPRINT // print(List)
|
||||||
OPRINTN // println(List)
|
OPRINTN // println(List)
|
||||||
OPAREN // (Left)
|
OPAREN // (Left)
|
||||||
OSEND // Left <- Right
|
OSEND // Left <- Right
|
||||||
OSLICE // Left[List[0] : List[1]] (Left is untypechecked or slice)
|
OSLICE // Left[List[0] : List[1]] (Left is untypechecked or slice)
|
||||||
OSLICEARR // Left[List[0] : List[1]] (Left is array)
|
OSLICEARR // Left[List[0] : List[1]] (Left is array)
|
||||||
OSLICESTR // Left[List[0] : List[1]] (Left is string)
|
OSLICESTR // Left[List[0] : List[1]] (Left is string)
|
||||||
OSLICE3 // Left[List[0] : List[1] : List[2]] (Left is untypedchecked or slice)
|
OSLICE3 // Left[List[0] : List[1] : List[2]] (Left is untypedchecked or slice)
|
||||||
OSLICE3ARR // Left[List[0] : List[1] : List[2]] (Left is array)
|
OSLICE3ARR // Left[List[0] : List[1] : List[2]] (Left is array)
|
||||||
ORECOVER // recover()
|
OSLICEHEADER // sliceheader{Left, List[0], List[1]} (Left is unsafe.Pointer, List[0] is length, List[1] is capacity)
|
||||||
ORECV // <-Left
|
ORECOVER // recover()
|
||||||
ORUNESTR // Type(Left) (Type is string, Left is rune)
|
ORECV // <-Left
|
||||||
OSELRECV // Left = <-Right.Left: (appears as .Left of OCASE; Right.Op == ORECV)
|
ORUNESTR // Type(Left) (Type is string, Left is rune)
|
||||||
OSELRECV2 // List = <-Right.Left: (apperas as .Left of OCASE; count(List) == 2, Right.Op == ORECV)
|
OSELRECV // Left = <-Right.Left: (appears as .Left of OCASE; Right.Op == ORECV)
|
||||||
OIOTA // iota
|
OSELRECV2 // List = <-Right.Left: (apperas as .Left of OCASE; count(List) == 2, Right.Op == ORECV)
|
||||||
OREAL // real(Left)
|
OIOTA // iota
|
||||||
OIMAG // imag(Left)
|
OREAL // real(Left)
|
||||||
OCOMPLEX // complex(Left, Right)
|
OIMAG // imag(Left)
|
||||||
OALIGNOF // unsafe.Alignof(Left)
|
OCOMPLEX // complex(Left, Right)
|
||||||
OOFFSETOF // unsafe.Offsetof(Left)
|
OALIGNOF // unsafe.Alignof(Left)
|
||||||
OSIZEOF // unsafe.Sizeof(Left)
|
OOFFSETOF // unsafe.Offsetof(Left)
|
||||||
|
OSIZEOF // unsafe.Sizeof(Left)
|
||||||
|
|
||||||
// statements
|
// statements
|
||||||
OBLOCK // { List } (block of code)
|
OBLOCK // { List } (block of code)
|
||||||
|
|
|
||||||
|
|
@ -1086,6 +1086,47 @@ func typecheck1(n *Node, top int) *Node {
|
||||||
n.Right = assignconv(r, t.Elem(), "send")
|
n.Right = assignconv(r, t.Elem(), "send")
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
|
|
||||||
|
case OSLICEHEADER:
|
||||||
|
// Errors here are Fatalf instead of yyerror because only the compiler
|
||||||
|
// can construct an OSLICEHEADER node.
|
||||||
|
// Components used in OSLICEHEADER that are supplied by parsed source code
|
||||||
|
// have already been typechecked in e.g. OMAKESLICE earlier.
|
||||||
|
ok |= Erv
|
||||||
|
|
||||||
|
t := n.Type
|
||||||
|
if !t.IsSlice() {
|
||||||
|
Fatalf("invalid type %v for OSLICEHEADER", n.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !n.Left.Type.IsUnsafePtr() {
|
||||||
|
Fatalf("need unsafe.Pointer for OSLICEHEADER")
|
||||||
|
}
|
||||||
|
|
||||||
|
if x := n.List.Len(); x != 2 {
|
||||||
|
Fatalf("expected 2 params (len, cap) for OSLICEHEADER, got %d", x)
|
||||||
|
}
|
||||||
|
|
||||||
|
n.Left = typecheck(n.Left, Erv)
|
||||||
|
l := typecheck(n.List.First(), Erv)
|
||||||
|
c := typecheck(n.List.Second(), Erv)
|
||||||
|
l = defaultlit(l, types.Types[TINT])
|
||||||
|
c = defaultlit(c, types.Types[TINT])
|
||||||
|
|
||||||
|
if Isconst(l, CTINT) && l.Int64() < 0 {
|
||||||
|
Fatalf("len for OSLICEHEADER must be non-negative")
|
||||||
|
}
|
||||||
|
|
||||||
|
if Isconst(c, CTINT) && c.Int64() < 0 {
|
||||||
|
Fatalf("cap for OSLICEHEADER must be non-negative")
|
||||||
|
}
|
||||||
|
|
||||||
|
if Isconst(l, CTINT) && Isconst(c, CTINT) && l.Val().U.(*Mpint).Cmp(c.Val().U.(*Mpint)) > 0 {
|
||||||
|
Fatalf("len larger than cap for OSLICEHEADER")
|
||||||
|
}
|
||||||
|
|
||||||
|
n.List.SetFirst(l)
|
||||||
|
n.List.SetSecond(c)
|
||||||
|
|
||||||
case OSLICE, OSLICE3:
|
case OSLICE, OSLICE3:
|
||||||
ok |= Erv
|
ok |= Erv
|
||||||
n.Left = typecheck(n.Left, Erv)
|
n.Left = typecheck(n.Left, Erv)
|
||||||
|
|
|
||||||
|
|
@ -1118,6 +1118,11 @@ opswitch:
|
||||||
case ORECV:
|
case ORECV:
|
||||||
Fatalf("walkexpr ORECV") // should see inside OAS only
|
Fatalf("walkexpr ORECV") // should see inside OAS only
|
||||||
|
|
||||||
|
case OSLICEHEADER:
|
||||||
|
n.Left = walkexpr(n.Left, init)
|
||||||
|
n.List.SetFirst(walkexpr(n.List.First(), init))
|
||||||
|
n.List.SetSecond(walkexpr(n.List.Second(), init))
|
||||||
|
|
||||||
case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR:
|
case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR:
|
||||||
n.Left = walkexpr(n.Left, init)
|
n.Left = walkexpr(n.Left, init)
|
||||||
low, high, max := n.SliceBounds()
|
low, high, max := n.SliceBounds()
|
||||||
|
|
@ -1339,8 +1344,13 @@ opswitch:
|
||||||
}
|
}
|
||||||
|
|
||||||
fn := syslook(fnname)
|
fn := syslook(fnname)
|
||||||
fn = substArgTypes(fn, t.Elem()) // any-1
|
n.Left = mkcall1(fn, types.Types[TUNSAFEPTR], init, typename(t.Elem()), conv(len, argtype), conv(cap, argtype))
|
||||||
n = mkcall1(fn, t, init, typename(t.Elem()), conv(len, argtype), conv(cap, argtype))
|
n.Left.SetNonNil(true)
|
||||||
|
n.List.Set2(conv(len, types.Types[TINT]), conv(cap, types.Types[TINT]))
|
||||||
|
n.Op = OSLICEHEADER
|
||||||
|
n.Type = t
|
||||||
|
n = typecheck(n, Erv)
|
||||||
|
n = walkexpr(n, init)
|
||||||
}
|
}
|
||||||
|
|
||||||
case ORUNESTR:
|
case ORUNESTR:
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ package main_test
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"cmd/internal/sys"
|
"cmd/internal/sys"
|
||||||
|
"context"
|
||||||
"debug/elf"
|
"debug/elf"
|
||||||
"debug/macho"
|
"debug/macho"
|
||||||
"flag"
|
"flag"
|
||||||
|
|
@ -108,6 +109,12 @@ var testGo string
|
||||||
var testTmpDir string
|
var testTmpDir string
|
||||||
var testBin string
|
var testBin string
|
||||||
|
|
||||||
|
// testCtx is canceled when the test binary is about to time out.
|
||||||
|
//
|
||||||
|
// If https://golang.org/issue/28135 is accepted, uses of this variable in test
|
||||||
|
// functions should be replaced by t.Context().
|
||||||
|
var testCtx = context.Background()
|
||||||
|
|
||||||
// The TestMain function creates a go command for testing purposes and
|
// The TestMain function creates a go command for testing purposes and
|
||||||
// deletes it after the tests have been run.
|
// deletes it after the tests have been run.
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
|
|
@ -120,6 +127,20 @@ func TestMain(m *testing.M) {
|
||||||
os.Unsetenv("GOROOT_FINAL")
|
os.Unsetenv("GOROOT_FINAL")
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
|
timeoutFlag := flag.Lookup("test.timeout")
|
||||||
|
if timeoutFlag != nil {
|
||||||
|
// TODO(golang.org/issue/28147): The go command does not pass the
|
||||||
|
// test.timeout flag unless either -timeout or -test.timeout is explicitly
|
||||||
|
// set on the command line.
|
||||||
|
if d := timeoutFlag.Value.(flag.Getter).Get().(time.Duration); d != 0 {
|
||||||
|
aBitShorter := d * 95 / 100
|
||||||
|
var cancel context.CancelFunc
|
||||||
|
testCtx, cancel = context.WithTimeout(testCtx, aBitShorter)
|
||||||
|
defer cancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if *proxyAddr != "" {
|
if *proxyAddr != "" {
|
||||||
StartProxy()
|
StartProxy()
|
||||||
select {}
|
select {}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ package main_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"internal/testenv"
|
"internal/testenv"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
|
@ -55,21 +56,28 @@ func TestScript(t *testing.T) {
|
||||||
|
|
||||||
// A testScript holds execution state for a single test script.
|
// A testScript holds execution state for a single test script.
|
||||||
type testScript struct {
|
type testScript struct {
|
||||||
t *testing.T
|
t *testing.T
|
||||||
workdir string // temporary work dir ($WORK)
|
workdir string // temporary work dir ($WORK)
|
||||||
log bytes.Buffer // test execution log (printed at end of test)
|
log bytes.Buffer // test execution log (printed at end of test)
|
||||||
mark int // offset of next log truncation
|
mark int // offset of next log truncation
|
||||||
cd string // current directory during test execution; initially $WORK/gopath/src
|
cd string // current directory during test execution; initially $WORK/gopath/src
|
||||||
name string // short name of test ("foo")
|
name string // short name of test ("foo")
|
||||||
file string // full file name ("testdata/script/foo.txt")
|
file string // full file name ("testdata/script/foo.txt")
|
||||||
lineno int // line number currently executing
|
lineno int // line number currently executing
|
||||||
line string // line currently executing
|
line string // line currently executing
|
||||||
env []string // environment list (for os/exec)
|
env []string // environment list (for os/exec)
|
||||||
envMap map[string]string // environment mapping (matches env)
|
envMap map[string]string // environment mapping (matches env)
|
||||||
stdout string // standard output from last 'go' command; for 'stdout' command
|
stdout string // standard output from last 'go' command; for 'stdout' command
|
||||||
stderr string // standard error from last 'go' command; for 'stderr' command
|
stderr string // standard error from last 'go' command; for 'stderr' command
|
||||||
stopped bool // test wants to stop early
|
stopped bool // test wants to stop early
|
||||||
start time.Time // time phase started
|
start time.Time // time phase started
|
||||||
|
background []backgroundCmd // backgrounded 'exec' and 'go' commands
|
||||||
|
}
|
||||||
|
|
||||||
|
type backgroundCmd struct {
|
||||||
|
cmd *exec.Cmd
|
||||||
|
wait <-chan struct{}
|
||||||
|
neg bool // if true, cmd should fail
|
||||||
}
|
}
|
||||||
|
|
||||||
var extraEnvKeys = []string{
|
var extraEnvKeys = []string{
|
||||||
|
|
@ -146,6 +154,17 @@ func (ts *testScript) run() {
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
// On a normal exit from the test loop, background processes are cleaned up
|
||||||
|
// before we print PASS. If we return early (e.g., due to a test failure),
|
||||||
|
// don't print anything about the processes that were still running.
|
||||||
|
for _, bg := range ts.background {
|
||||||
|
interruptProcess(bg.cmd.Process)
|
||||||
|
}
|
||||||
|
for _, bg := range ts.background {
|
||||||
|
<-bg.wait
|
||||||
|
}
|
||||||
|
ts.background = nil
|
||||||
|
|
||||||
markTime()
|
markTime()
|
||||||
// Flush testScript log to testing.T log.
|
// Flush testScript log to testing.T log.
|
||||||
ts.t.Log("\n" + ts.abbrev(ts.log.String()))
|
ts.t.Log("\n" + ts.abbrev(ts.log.String()))
|
||||||
|
|
@ -284,14 +303,23 @@ Script:
|
||||||
|
|
||||||
// Command can ask script to stop early.
|
// Command can ask script to stop early.
|
||||||
if ts.stopped {
|
if ts.stopped {
|
||||||
return
|
// Break instead of returning, so that we check the status of any
|
||||||
|
// background processes and print PASS.
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, bg := range ts.background {
|
||||||
|
interruptProcess(bg.cmd.Process)
|
||||||
|
}
|
||||||
|
ts.cmdWait(false, nil)
|
||||||
|
|
||||||
// Final phase ended.
|
// Final phase ended.
|
||||||
rewind()
|
rewind()
|
||||||
markTime()
|
markTime()
|
||||||
fmt.Fprintf(&ts.log, "PASS\n")
|
if !ts.stopped {
|
||||||
|
fmt.Fprintf(&ts.log, "PASS\n")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// scriptCmds are the script command implementations.
|
// scriptCmds are the script command implementations.
|
||||||
|
|
@ -317,6 +345,7 @@ var scriptCmds = map[string]func(*testScript, bool, []string){
|
||||||
"stdout": (*testScript).cmdStdout,
|
"stdout": (*testScript).cmdStdout,
|
||||||
"stop": (*testScript).cmdStop,
|
"stop": (*testScript).cmdStop,
|
||||||
"symlink": (*testScript).cmdSymlink,
|
"symlink": (*testScript).cmdSymlink,
|
||||||
|
"wait": (*testScript).cmdWait,
|
||||||
}
|
}
|
||||||
|
|
||||||
// addcrlf adds CRLF line endings to the named files.
|
// addcrlf adds CRLF line endings to the named files.
|
||||||
|
|
@ -451,26 +480,43 @@ func (ts *testScript) cmdEnv(neg bool, args []string) {
|
||||||
|
|
||||||
// exec runs the given command.
|
// exec runs the given command.
|
||||||
func (ts *testScript) cmdExec(neg bool, args []string) {
|
func (ts *testScript) cmdExec(neg bool, args []string) {
|
||||||
if len(args) < 1 {
|
if len(args) < 1 || (len(args) == 1 && args[0] == "&") {
|
||||||
ts.fatalf("usage: exec program [args...]")
|
ts.fatalf("usage: exec program [args...] [&]")
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
ts.stdout, ts.stderr, err = ts.exec(args[0], args[1:]...)
|
if len(args) > 0 && args[len(args)-1] == "&" {
|
||||||
if ts.stdout != "" {
|
var cmd *exec.Cmd
|
||||||
fmt.Fprintf(&ts.log, "[stdout]\n%s", ts.stdout)
|
cmd, err = ts.execBackground(args[0], args[1:len(args)-1]...)
|
||||||
}
|
if err == nil {
|
||||||
if ts.stderr != "" {
|
wait := make(chan struct{})
|
||||||
fmt.Fprintf(&ts.log, "[stderr]\n%s", ts.stderr)
|
go func() {
|
||||||
|
ctxWait(testCtx, cmd)
|
||||||
|
close(wait)
|
||||||
|
}()
|
||||||
|
ts.background = append(ts.background, backgroundCmd{cmd, wait, neg})
|
||||||
|
}
|
||||||
|
ts.stdout, ts.stderr = "", ""
|
||||||
|
} else {
|
||||||
|
ts.stdout, ts.stderr, err = ts.exec(args[0], args[1:]...)
|
||||||
|
if ts.stdout != "" {
|
||||||
|
fmt.Fprintf(&ts.log, "[stdout]\n%s", ts.stdout)
|
||||||
|
}
|
||||||
|
if ts.stderr != "" {
|
||||||
|
fmt.Fprintf(&ts.log, "[stderr]\n%s", ts.stderr)
|
||||||
|
}
|
||||||
|
if err == nil && neg {
|
||||||
|
ts.fatalf("unexpected command success")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(&ts.log, "[%v]\n", err)
|
fmt.Fprintf(&ts.log, "[%v]\n", err)
|
||||||
if !neg {
|
if testCtx.Err() != nil {
|
||||||
|
ts.fatalf("test timed out while running command")
|
||||||
|
} else if !neg {
|
||||||
ts.fatalf("unexpected command failure")
|
ts.fatalf("unexpected command failure")
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if neg {
|
|
||||||
ts.fatalf("unexpected command success")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -545,6 +591,14 @@ func (ts *testScript) cmdSkip(neg bool, args []string) {
|
||||||
if neg {
|
if neg {
|
||||||
ts.fatalf("unsupported: ! skip")
|
ts.fatalf("unsupported: ! skip")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Before we mark the test as skipped, shut down any background processes and
|
||||||
|
// make sure they have returned the correct status.
|
||||||
|
for _, bg := range ts.background {
|
||||||
|
interruptProcess(bg.cmd.Process)
|
||||||
|
}
|
||||||
|
ts.cmdWait(false, nil)
|
||||||
|
|
||||||
if len(args) == 1 {
|
if len(args) == 1 {
|
||||||
ts.t.Skip(args[0])
|
ts.t.Skip(args[0])
|
||||||
}
|
}
|
||||||
|
|
@ -687,6 +741,52 @@ func (ts *testScript) cmdSymlink(neg bool, args []string) {
|
||||||
ts.check(os.Symlink(args[2], ts.mkabs(args[0])))
|
ts.check(os.Symlink(args[2], ts.mkabs(args[0])))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// wait waits for background commands to exit, setting stderr and stdout to their result.
|
||||||
|
func (ts *testScript) cmdWait(neg bool, args []string) {
|
||||||
|
if neg {
|
||||||
|
ts.fatalf("unsupported: ! wait")
|
||||||
|
}
|
||||||
|
if len(args) > 0 {
|
||||||
|
ts.fatalf("usage: wait")
|
||||||
|
}
|
||||||
|
|
||||||
|
var stdouts, stderrs []string
|
||||||
|
for _, bg := range ts.background {
|
||||||
|
<-bg.wait
|
||||||
|
|
||||||
|
args := append([]string{filepath.Base(bg.cmd.Args[0])}, bg.cmd.Args[1:]...)
|
||||||
|
fmt.Fprintf(&ts.log, "[background] %s: %v\n", strings.Join(args, " "), bg.cmd.ProcessState)
|
||||||
|
|
||||||
|
cmdStdout := bg.cmd.Stdout.(*strings.Builder).String()
|
||||||
|
if cmdStdout != "" {
|
||||||
|
fmt.Fprintf(&ts.log, "[stdout]\n%s", cmdStdout)
|
||||||
|
stdouts = append(stdouts, cmdStdout)
|
||||||
|
}
|
||||||
|
|
||||||
|
cmdStderr := bg.cmd.Stderr.(*strings.Builder).String()
|
||||||
|
if cmdStderr != "" {
|
||||||
|
fmt.Fprintf(&ts.log, "[stderr]\n%s", cmdStderr)
|
||||||
|
stderrs = append(stderrs, cmdStderr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if bg.cmd.ProcessState.Success() {
|
||||||
|
if bg.neg {
|
||||||
|
ts.fatalf("unexpected command success")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if testCtx.Err() != nil {
|
||||||
|
ts.fatalf("test timed out while running command")
|
||||||
|
} else if !bg.neg {
|
||||||
|
ts.fatalf("unexpected command failure")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ts.stdout = strings.Join(stdouts, "")
|
||||||
|
ts.stderr = strings.Join(stderrs, "")
|
||||||
|
ts.background = nil
|
||||||
|
}
|
||||||
|
|
||||||
// Helpers for command implementations.
|
// Helpers for command implementations.
|
||||||
|
|
||||||
// abbrev abbreviates the actual work directory in the string s to the literal string "$WORK".
|
// abbrev abbreviates the actual work directory in the string s to the literal string "$WORK".
|
||||||
|
|
@ -716,10 +816,51 @@ func (ts *testScript) exec(command string, args ...string) (stdout, stderr strin
|
||||||
var stdoutBuf, stderrBuf strings.Builder
|
var stdoutBuf, stderrBuf strings.Builder
|
||||||
cmd.Stdout = &stdoutBuf
|
cmd.Stdout = &stdoutBuf
|
||||||
cmd.Stderr = &stderrBuf
|
cmd.Stderr = &stderrBuf
|
||||||
err = cmd.Run()
|
if err = cmd.Start(); err == nil {
|
||||||
|
err = ctxWait(testCtx, cmd)
|
||||||
|
}
|
||||||
return stdoutBuf.String(), stderrBuf.String(), err
|
return stdoutBuf.String(), stderrBuf.String(), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// execBackground starts the given command line (an actual subprocess, not simulated)
|
||||||
|
// in ts.cd with environment ts.env.
|
||||||
|
func (ts *testScript) execBackground(command string, args ...string) (*exec.Cmd, error) {
|
||||||
|
cmd := exec.Command(command, args...)
|
||||||
|
cmd.Dir = ts.cd
|
||||||
|
cmd.Env = append(ts.env, "PWD="+ts.cd)
|
||||||
|
var stdoutBuf, stderrBuf strings.Builder
|
||||||
|
cmd.Stdout = &stdoutBuf
|
||||||
|
cmd.Stderr = &stderrBuf
|
||||||
|
return cmd, cmd.Start()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ctxWait is like cmd.Wait, but terminates cmd with os.Interrupt if ctx becomes done.
|
||||||
|
//
|
||||||
|
// This differs from exec.CommandContext in that it prefers os.Interrupt over os.Kill.
|
||||||
|
// (See https://golang.org/issue/21135.)
|
||||||
|
func ctxWait(ctx context.Context, cmd *exec.Cmd) error {
|
||||||
|
errc := make(chan error, 1)
|
||||||
|
go func() { errc <- cmd.Wait() }()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case err := <-errc:
|
||||||
|
return err
|
||||||
|
case <-ctx.Done():
|
||||||
|
interruptProcess(cmd.Process)
|
||||||
|
return <-errc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// interruptProcess sends os.Interrupt to p if supported, or os.Kill otherwise.
|
||||||
|
func interruptProcess(p *os.Process) {
|
||||||
|
if err := p.Signal(os.Interrupt); err != nil {
|
||||||
|
// Per https://golang.org/pkg/os/#Signal, “Interrupt is not implemented on
|
||||||
|
// Windows; using it with os.Process.Signal will return an error.”
|
||||||
|
// Fall back to Kill instead.
|
||||||
|
p.Kill()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// expand applies environment variable expansion to the string s.
|
// expand applies environment variable expansion to the string s.
|
||||||
func (ts *testScript) expand(s string) string {
|
func (ts *testScript) expand(s string) string {
|
||||||
return os.Expand(s, func(key string) string { return ts.envMap[key] })
|
return os.Expand(s, func(key string) string { return ts.envMap[key] })
|
||||||
|
|
|
||||||
22
src/cmd/go/testdata/script/README
vendored
22
src/cmd/go/testdata/script/README
vendored
|
|
@ -99,16 +99,23 @@ The commands are:
|
||||||
With no arguments, print the environment (useful for debugging).
|
With no arguments, print the environment (useful for debugging).
|
||||||
Otherwise add the listed key=value pairs to the environment.
|
Otherwise add the listed key=value pairs to the environment.
|
||||||
|
|
||||||
- [!] exec program [args...]
|
- [!] exec program [args...] [&]
|
||||||
Run the given executable program with the arguments.
|
Run the given executable program with the arguments.
|
||||||
It must (or must not) succeed.
|
It must (or must not) succeed.
|
||||||
Note that 'exec' does not terminate the script (unlike in Unix shells).
|
Note that 'exec' does not terminate the script (unlike in Unix shells).
|
||||||
|
|
||||||
|
If the last token is '&', the program executes in the background. The standard
|
||||||
|
output and standard error of the previous command is cleared, but the output
|
||||||
|
of the background process is buffered — and checking of its exit status is
|
||||||
|
delayed — until the next call to 'wait', 'skip', or 'stop' or the end of the
|
||||||
|
test. At the end of the test, any remaining background processes are
|
||||||
|
terminated using os.Interrupt (if supported) or os.Kill.
|
||||||
|
|
||||||
- [!] exists [-readonly] file...
|
- [!] exists [-readonly] file...
|
||||||
Each of the listed files or directories must (or must not) exist.
|
Each of the listed files or directories must (or must not) exist.
|
||||||
If -readonly is given, the files or directories must be unwritable.
|
If -readonly is given, the files or directories must be unwritable.
|
||||||
|
|
||||||
- [!] go args...
|
- [!] go args... [&]
|
||||||
Run the (test copy of the) go command with the given arguments.
|
Run the (test copy of the) go command with the given arguments.
|
||||||
It must (or must not) succeed.
|
It must (or must not) succeed.
|
||||||
|
|
||||||
|
|
@ -131,11 +138,11 @@ The commands are:
|
||||||
|
|
||||||
- [!] stderr [-count=N] pattern
|
- [!] stderr [-count=N] pattern
|
||||||
Apply the grep command (see above) to the standard error
|
Apply the grep command (see above) to the standard error
|
||||||
from the most recent exec or go command.
|
from the most recent exec, go, or wait command.
|
||||||
|
|
||||||
- [!] stdout [-count=N] pattern
|
- [!] stdout [-count=N] pattern
|
||||||
Apply the grep command (see above) to the standard output
|
Apply the grep command (see above) to the standard output
|
||||||
from the most recent exec or go command.
|
from the most recent exec, go, or wait command.
|
||||||
|
|
||||||
- stop [message]
|
- stop [message]
|
||||||
Stop the test early (marking it as passing), including the message if given.
|
Stop the test early (marking it as passing), including the message if given.
|
||||||
|
|
@ -143,6 +150,13 @@ The commands are:
|
||||||
- symlink file -> target
|
- symlink file -> target
|
||||||
Create file as a symlink to target. The -> (like in ls -l output) is required.
|
Create file as a symlink to target. The -> (like in ls -l output) is required.
|
||||||
|
|
||||||
|
- wait
|
||||||
|
Wait for all 'exec' and 'go' commands started in the background (with the '&'
|
||||||
|
token) to exit, and display success or failure status for them.
|
||||||
|
After a call to wait, the 'stderr' and 'stdout' commands will apply to the
|
||||||
|
concatenation of the corresponding streams of the background commands,
|
||||||
|
in the order in which those commands were started.
|
||||||
|
|
||||||
When TestScript runs a script and the script fails, by default TestScript shows
|
When TestScript runs a script and the script fails, by default TestScript shows
|
||||||
the execution of the most recent phase of the script (since the last # comment)
|
the execution of the most recent phase of the script (since the last # comment)
|
||||||
and only shows the # comments for earlier phases. For example, here is a
|
and only shows the # comments for earlier phases. For example, here is a
|
||||||
|
|
|
||||||
22
src/cmd/go/testdata/script/script_wait.txt
vendored
Normal file
22
src/cmd/go/testdata/script/script_wait.txt
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
[!exec:echo] skip
|
||||||
|
[!exec:false] skip
|
||||||
|
|
||||||
|
exec echo foo
|
||||||
|
stdout foo
|
||||||
|
|
||||||
|
exec echo foo &
|
||||||
|
exec echo bar &
|
||||||
|
! exec false &
|
||||||
|
|
||||||
|
# Starting a background process should clear previous output.
|
||||||
|
! stdout foo
|
||||||
|
|
||||||
|
# Wait should set the output to the concatenated outputs of the background
|
||||||
|
# programs, in the order in which they were started.
|
||||||
|
wait
|
||||||
|
stdout 'foo\nbar'
|
||||||
|
|
||||||
|
# The end of the test should interrupt or kill any remaining background
|
||||||
|
# programs.
|
||||||
|
[!exec:sleep] skip
|
||||||
|
! exec sleep 86400 &
|
||||||
|
|
@ -11,7 +11,6 @@ package tls
|
||||||
// https://www.imperialviolet.org/2013/02/04/luckythirteen.html.
|
// https://www.imperialviolet.org/2013/02/04/luckythirteen.html.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"crypto"
|
"crypto"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
|
|
@ -30,10 +29,7 @@ import (
|
||||||
// The configuration config must be non-nil and must include
|
// The configuration config must be non-nil and must include
|
||||||
// at least one certificate or else set GetCertificate.
|
// at least one certificate or else set GetCertificate.
|
||||||
func Server(conn net.Conn, config *Config) *Conn {
|
func Server(conn net.Conn, config *Config) *Conn {
|
||||||
return &Conn{
|
return &Conn{conn: conn, config: config}
|
||||||
conn: conn, config: config,
|
|
||||||
input: *bytes.NewReader(nil), // Issue 28269
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client returns a new TLS client side connection
|
// Client returns a new TLS client side connection
|
||||||
|
|
@ -41,10 +37,7 @@ func Server(conn net.Conn, config *Config) *Conn {
|
||||||
// The config cannot be nil: users must set either ServerName or
|
// The config cannot be nil: users must set either ServerName or
|
||||||
// InsecureSkipVerify in the config.
|
// InsecureSkipVerify in the config.
|
||||||
func Client(conn net.Conn, config *Config) *Conn {
|
func Client(conn net.Conn, config *Config) *Conn {
|
||||||
return &Conn{
|
return &Conn{conn: conn, config: config, isClient: true}
|
||||||
conn: conn, config: config, isClient: true,
|
|
||||||
input: *bytes.NewReader(nil), // Issue 28269
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// A listener implements a network listener (net.Listener) for TLS connections.
|
// A listener implements a network listener (net.Listener) for TLS connections.
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ type Context struct {
|
||||||
// which defaults to the list of Go releases the current release is compatible with.
|
// which defaults to the list of Go releases the current release is compatible with.
|
||||||
// In addition to the BuildTags and ReleaseTags, build constraints
|
// In addition to the BuildTags and ReleaseTags, build constraints
|
||||||
// consider the values of GOARCH and GOOS as satisfied tags.
|
// consider the values of GOARCH and GOOS as satisfied tags.
|
||||||
|
// The last element in ReleaseTags is assumed to be the current release.
|
||||||
BuildTags []string
|
BuildTags []string
|
||||||
ReleaseTags []string
|
ReleaseTags []string
|
||||||
|
|
||||||
|
|
@ -296,6 +297,7 @@ func defaultContext() Context {
|
||||||
// say "+build go1.x", and code that should only be built before Go 1.x
|
// say "+build go1.x", and code that should only be built before Go 1.x
|
||||||
// (perhaps it is the stub to use in that case) should say "+build !go1.x".
|
// (perhaps it is the stub to use in that case) should say "+build !go1.x".
|
||||||
// NOTE: If you add to this list, also update the doc comment in doc.go.
|
// NOTE: If you add to this list, also update the doc comment in doc.go.
|
||||||
|
// NOTE: The last element in ReleaseTags should be the current release.
|
||||||
const version = 11 // go1.11
|
const version = 11 // go1.11
|
||||||
for i := 1; i <= version; i++ {
|
for i := 1; i <= version; i++ {
|
||||||
c.ReleaseTags = append(c.ReleaseTags, "go1."+strconv.Itoa(i))
|
c.ReleaseTags = append(c.ReleaseTags, "go1."+strconv.Itoa(i))
|
||||||
|
|
|
||||||
|
|
@ -47,27 +47,18 @@ type x86 struct {
|
||||||
|
|
||||||
var PPC64 ppc64
|
var PPC64 ppc64
|
||||||
|
|
||||||
// For ppc64x, it is safe to check only for ISA level starting on ISA v3.00,
|
// For ppc64(le), it is safe to check only for ISA level starting on ISA v3.00,
|
||||||
// since there are no optional categories. There are some exceptions that also
|
// since there are no optional categories. There are some exceptions that also
|
||||||
// require kernel support to work (darn, scv), so there are feature bits for
|
// require kernel support to work (darn, scv), so there are feature bits for
|
||||||
// those as well. The minimum processor requirement is POWER8 (ISA 2.07), so we
|
// those as well. The minimum processor requirement is POWER8 (ISA 2.07).
|
||||||
// maintain some of the old feature checks for optional categories for
|
|
||||||
// safety.
|
|
||||||
// The struct is padded to avoid false sharing.
|
// The struct is padded to avoid false sharing.
|
||||||
type ppc64 struct {
|
type ppc64 struct {
|
||||||
_ CacheLinePad
|
_ CacheLinePad
|
||||||
HasVMX bool // Vector unit (Altivec)
|
HasDARN bool // Hardware random number generator (requires kernel enablement)
|
||||||
HasDFP bool // Decimal Floating Point unit
|
HasSCV bool // Syscall vectored (requires kernel enablement)
|
||||||
HasVSX bool // Vector-scalar unit
|
IsPOWER8 bool // ISA v2.07 (POWER8)
|
||||||
HasHTM bool // Hardware Transactional Memory
|
IsPOWER9 bool // ISA v3.00 (POWER9)
|
||||||
HasISEL bool // Integer select
|
_ CacheLinePad
|
||||||
HasVCRYPTO bool // Vector cryptography
|
|
||||||
HasHTMNOSC bool // HTM: kernel-aborted transaction in syscalls
|
|
||||||
HasDARN bool // Hardware random number generator (requires kernel enablement)
|
|
||||||
HasSCV bool // Syscall vectored (requires kernel enablement)
|
|
||||||
IsPOWER8 bool // ISA v2.07 (POWER8)
|
|
||||||
IsPOWER9 bool // ISA v3.00 (POWER9)
|
|
||||||
_ CacheLinePad
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var ARM arm
|
var ARM arm
|
||||||
|
|
|
||||||
|
|
@ -21,44 +21,22 @@ const (
|
||||||
_PPC_FEATURE2_ARCH_3_00 = 0x00800000
|
_PPC_FEATURE2_ARCH_3_00 = 0x00800000
|
||||||
|
|
||||||
// CPU features
|
// CPU features
|
||||||
_PPC_FEATURE_HAS_ALTIVEC = 0x10000000
|
_PPC_FEATURE2_DARN = 0x00200000
|
||||||
_PPC_FEATURE_HAS_DFP = 0x00000400
|
_PPC_FEATURE2_SCV = 0x00100000
|
||||||
_PPC_FEATURE_HAS_VSX = 0x00000080
|
|
||||||
_PPC_FEATURE2_HAS_HTM = 0x40000000
|
|
||||||
_PPC_FEATURE2_HAS_ISEL = 0x08000000
|
|
||||||
_PPC_FEATURE2_HAS_VEC_CRYPTO = 0x02000000
|
|
||||||
_PPC_FEATURE2_HTM_NOSC = 0x01000000
|
|
||||||
_PPC_FEATURE2_DARN = 0x00200000
|
|
||||||
_PPC_FEATURE2_SCV = 0x00100000
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func doinit() {
|
func doinit() {
|
||||||
options = []option{
|
options = []option{
|
||||||
{Name: "htm", Feature: &PPC64.HasHTM},
|
|
||||||
{Name: "htmnosc", Feature: &PPC64.HasHTMNOSC},
|
|
||||||
{Name: "darn", Feature: &PPC64.HasDARN},
|
{Name: "darn", Feature: &PPC64.HasDARN},
|
||||||
{Name: "scv", Feature: &PPC64.HasSCV},
|
{Name: "scv", Feature: &PPC64.HasSCV},
|
||||||
|
{Name: "power9", Feature: &PPC64.IsPOWER9},
|
||||||
|
|
||||||
// These capabilities should always be enabled on ppc64 and ppc64le:
|
// These capabilities should always be enabled on ppc64 and ppc64le:
|
||||||
{Name: "power8", Feature: &PPC64.IsPOWER8, Required: true},
|
{Name: "power8", Feature: &PPC64.IsPOWER8, Required: true},
|
||||||
{Name: "vmx", Feature: &PPC64.HasVMX, Required: true},
|
|
||||||
{Name: "dfp", Feature: &PPC64.HasDFP, Required: true},
|
|
||||||
{Name: "vsx", Feature: &PPC64.HasVSX, Required: true},
|
|
||||||
{Name: "isel", Feature: &PPC64.HasISEL, Required: true},
|
|
||||||
{Name: "vcrypto", Feature: &PPC64.HasVCRYPTO, Required: true},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// HWCAP feature bits
|
|
||||||
PPC64.HasVMX = isSet(HWCap, _PPC_FEATURE_HAS_ALTIVEC)
|
|
||||||
PPC64.HasDFP = isSet(HWCap, _PPC_FEATURE_HAS_DFP)
|
|
||||||
PPC64.HasVSX = isSet(HWCap, _PPC_FEATURE_HAS_VSX)
|
|
||||||
|
|
||||||
// HWCAP2 feature bits
|
// HWCAP2 feature bits
|
||||||
PPC64.IsPOWER8 = isSet(HWCap2, _PPC_FEATURE2_ARCH_2_07)
|
PPC64.IsPOWER8 = isSet(HWCap2, _PPC_FEATURE2_ARCH_2_07)
|
||||||
PPC64.HasHTM = isSet(HWCap2, _PPC_FEATURE2_HAS_HTM)
|
|
||||||
PPC64.HasISEL = isSet(HWCap2, _PPC_FEATURE2_HAS_ISEL)
|
|
||||||
PPC64.HasVCRYPTO = isSet(HWCap2, _PPC_FEATURE2_HAS_VEC_CRYPTO)
|
|
||||||
PPC64.HasHTMNOSC = isSet(HWCap2, _PPC_FEATURE2_HTM_NOSC)
|
|
||||||
PPC64.IsPOWER9 = isSet(HWCap2, _PPC_FEATURE2_ARCH_3_00)
|
PPC64.IsPOWER9 = isSet(HWCap2, _PPC_FEATURE2_ARCH_3_00)
|
||||||
PPC64.HasDARN = isSet(HWCap2, _PPC_FEATURE2_DARN)
|
PPC64.HasDARN = isSet(HWCap2, _PPC_FEATURE2_DARN)
|
||||||
PPC64.HasSCV = isSet(HWCap2, _PPC_FEATURE2_SCV)
|
PPC64.HasSCV = isSet(HWCap2, _PPC_FEATURE2_SCV)
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ const debugFloat = false // enable for debugging
|
||||||
// precision of the argument with the largest precision value before any
|
// precision of the argument with the largest precision value before any
|
||||||
// rounding takes place, and the rounding mode remains unchanged. Thus,
|
// rounding takes place, and the rounding mode remains unchanged. Thus,
|
||||||
// uninitialized Floats provided as result arguments will have their
|
// uninitialized Floats provided as result arguments will have their
|
||||||
// precision set to a reasonable value determined by the operands and
|
// precision set to a reasonable value determined by the operands, and
|
||||||
// their mode is the zero value for RoundingMode (ToNearestEven).
|
// their mode is the zero value for RoundingMode (ToNearestEven).
|
||||||
//
|
//
|
||||||
// By setting the desired precision to 24 or 53 and using matching rounding
|
// By setting the desired precision to 24 or 53 and using matching rounding
|
||||||
|
|
@ -56,6 +56,12 @@ const debugFloat = false // enable for debugging
|
||||||
// The zero (uninitialized) value for a Float is ready to use and represents
|
// The zero (uninitialized) value for a Float is ready to use and represents
|
||||||
// the number +0.0 exactly, with precision 0 and rounding mode ToNearestEven.
|
// the number +0.0 exactly, with precision 0 and rounding mode ToNearestEven.
|
||||||
//
|
//
|
||||||
|
// Operations always take pointer arguments (*Float) rather
|
||||||
|
// than Float values, and each unique Float value requires
|
||||||
|
// its own unique *Float pointer. To "copy" a Float value,
|
||||||
|
// an existing (or newly allocated) Float must be set to
|
||||||
|
// a new value using the Float.Set method; shallow copies
|
||||||
|
// of Floats are not supported and may lead to errors.
|
||||||
type Float struct {
|
type Float struct {
|
||||||
prec uint32
|
prec uint32
|
||||||
mode RoundingMode
|
mode RoundingMode
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,13 @@ import (
|
||||||
|
|
||||||
// An Int represents a signed multi-precision integer.
|
// An Int represents a signed multi-precision integer.
|
||||||
// The zero value for an Int represents the value 0.
|
// The zero value for an Int represents the value 0.
|
||||||
|
//
|
||||||
|
// Operations always take pointer arguments (*Int) rather
|
||||||
|
// than Int values, and each unique Int value requires
|
||||||
|
// its own unique *Int pointer. To "copy" an Int value,
|
||||||
|
// an existing (or newly allocated) Int must be set to
|
||||||
|
// a new value using the Int.Set method; shallow copies
|
||||||
|
// of Ints are not supported and may lead to errors.
|
||||||
type Int struct {
|
type Int struct {
|
||||||
neg bool // sign
|
neg bool // sign
|
||||||
abs nat // absolute value of the integer
|
abs nat // absolute value of the integer
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,13 @@ import (
|
||||||
|
|
||||||
// A Rat represents a quotient a/b of arbitrary precision.
|
// A Rat represents a quotient a/b of arbitrary precision.
|
||||||
// The zero value for a Rat represents the value 0.
|
// The zero value for a Rat represents the value 0.
|
||||||
|
//
|
||||||
|
// Operations always take pointer arguments (*Rat) rather
|
||||||
|
// than Rat values, and each unique Rat value requires
|
||||||
|
// its own unique *Rat pointer. To "copy" a Rat value,
|
||||||
|
// an existing (or newly allocated) Rat must be set to
|
||||||
|
// a new value using the Rat.Set method; shallow copies
|
||||||
|
// of Rats are not supported and may lead to errors.
|
||||||
type Rat struct {
|
type Rat struct {
|
||||||
// To make zero values for Rat work w/o initialization,
|
// To make zero values for Rat work w/o initialization,
|
||||||
// a zero value of b (len(b) == 0) acts like b == 1.
|
// a zero value of b (len(b) == 0) acts like b == 1.
|
||||||
|
|
|
||||||
|
|
@ -53,8 +53,9 @@ var (
|
||||||
// available.
|
// available.
|
||||||
ErrNotSupported = &ProtocolError{"feature not supported"}
|
ErrNotSupported = &ProtocolError{"feature not supported"}
|
||||||
|
|
||||||
// ErrUnexpectedTrailer is returned by the Transport when a server
|
// Deprecated: ErrUnexpectedTrailer is no longer returned by
|
||||||
// replies with a Trailer header, but without a chunked reply.
|
// anything in the net/http package. Callers should not
|
||||||
|
// compare errors against this variable.
|
||||||
ErrUnexpectedTrailer = &ProtocolError{"trailer header without chunked transfer encoding"}
|
ErrUnexpectedTrailer = &ProtocolError{"trailer header without chunked transfer encoding"}
|
||||||
|
|
||||||
// ErrMissingBoundary is returned by Request.MultipartReader when the
|
// ErrMissingBoundary is returned by Request.MultipartReader when the
|
||||||
|
|
|
||||||
|
|
@ -157,6 +157,34 @@ var respTests = []respTest{
|
||||||
"Body here\ncontinued",
|
"Body here\ncontinued",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Trailer header but no TransferEncoding
|
||||||
|
{
|
||||||
|
"HTTP/1.0 200 OK\r\n" +
|
||||||
|
"Trailer: Content-MD5, Content-Sources\r\n" +
|
||||||
|
"Content-Length: 10\r\n" +
|
||||||
|
"Connection: close\r\n" +
|
||||||
|
"\r\n" +
|
||||||
|
"Body here\n",
|
||||||
|
|
||||||
|
Response{
|
||||||
|
Status: "200 OK",
|
||||||
|
StatusCode: 200,
|
||||||
|
Proto: "HTTP/1.0",
|
||||||
|
ProtoMajor: 1,
|
||||||
|
ProtoMinor: 0,
|
||||||
|
Request: dummyReq("GET"),
|
||||||
|
Header: Header{
|
||||||
|
"Connection": {"close"},
|
||||||
|
"Content-Length": {"10"},
|
||||||
|
"Trailer": []string{"Content-MD5, Content-Sources"},
|
||||||
|
},
|
||||||
|
Close: true,
|
||||||
|
ContentLength: 10,
|
||||||
|
},
|
||||||
|
|
||||||
|
"Body here\n",
|
||||||
|
},
|
||||||
|
|
||||||
// Chunked response with Content-Length.
|
// Chunked response with Content-Length.
|
||||||
{
|
{
|
||||||
"HTTP/1.1 200 OK\r\n" +
|
"HTTP/1.1 200 OK\r\n" +
|
||||||
|
|
|
||||||
|
|
@ -740,6 +740,16 @@ func fixTrailer(header Header, te []string) (Header, error) {
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
if !chunked(te) {
|
||||||
|
// Trailer and no chunking:
|
||||||
|
// this is an invalid use case for trailer header.
|
||||||
|
// Nevertheless, no error will be returned and we
|
||||||
|
// let users decide if this is a valid HTTP message.
|
||||||
|
// The Trailer header will be kept in Response.Header
|
||||||
|
// but not populate Response.Trailer.
|
||||||
|
// See issue #27197.
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
header.Del("Trailer")
|
header.Del("Trailer")
|
||||||
|
|
||||||
trailer := make(Header)
|
trailer := make(Header)
|
||||||
|
|
@ -763,10 +773,6 @@ func fixTrailer(header Header, te []string) (Header, error) {
|
||||||
if len(trailer) == 0 {
|
if len(trailer) == 0 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
if !chunked(te) {
|
|
||||||
// Trailer and no chunking
|
|
||||||
return nil, ErrUnexpectedTrailer
|
|
||||||
}
|
|
||||||
return trailer, nil
|
return trailer, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -266,8 +266,11 @@ func testGdbPython(t *testing.T, cgo bool) {
|
||||||
infoLocalsRe1 := regexp.MustCompile(`slicevar *= *\[\]string *= *{"def"}`)
|
infoLocalsRe1 := regexp.MustCompile(`slicevar *= *\[\]string *= *{"def"}`)
|
||||||
// Format output from gdb v8.2
|
// Format output from gdb v8.2
|
||||||
infoLocalsRe2 := regexp.MustCompile(`^slicevar = .*\nmapvar = .*\nstrvar = 0x[0-9a-f]+ "abc"`)
|
infoLocalsRe2 := regexp.MustCompile(`^slicevar = .*\nmapvar = .*\nstrvar = 0x[0-9a-f]+ "abc"`)
|
||||||
|
// Format output from gdb v7.7
|
||||||
|
infoLocalsRe3 := regexp.MustCompile(`^mapvar = .*\nstrvar = "abc"\nslicevar *= *\[\]string`)
|
||||||
if bl := blocks["info locals"]; !infoLocalsRe1.MatchString(bl) &&
|
if bl := blocks["info locals"]; !infoLocalsRe1.MatchString(bl) &&
|
||||||
!infoLocalsRe2.MatchString(bl) {
|
!infoLocalsRe2.MatchString(bl) &&
|
||||||
|
!infoLocalsRe3.MatchString(bl) {
|
||||||
t.Fatalf("info locals failed: %s", bl)
|
t.Fatalf("info locals failed: %s", bl)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ func panicmakeslicecap() {
|
||||||
panic(errorString("makeslice: cap out of range"))
|
panic(errorString("makeslice: cap out of range"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeslice(et *_type, len, cap int) slice {
|
func makeslice(et *_type, len, cap int) unsafe.Pointer {
|
||||||
mem, overflow := math.MulUintptr(et.size, uintptr(cap))
|
mem, overflow := math.MulUintptr(et.size, uintptr(cap))
|
||||||
if overflow || mem > maxAlloc || len < 0 || len > cap {
|
if overflow || mem > maxAlloc || len < 0 || len > cap {
|
||||||
// NOTE: Produce a 'len out of range' error instead of a
|
// NOTE: Produce a 'len out of range' error instead of a
|
||||||
|
|
@ -45,12 +45,11 @@ func makeslice(et *_type, len, cap int) slice {
|
||||||
}
|
}
|
||||||
panicmakeslicecap()
|
panicmakeslicecap()
|
||||||
}
|
}
|
||||||
p := mallocgc(mem, et, true)
|
|
||||||
|
|
||||||
return slice{p, len, cap}
|
return mallocgc(mem, et, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeslice64(et *_type, len64, cap64 int64) slice {
|
func makeslice64(et *_type, len64, cap64 int64) unsafe.Pointer {
|
||||||
len := int(len64)
|
len := int(len64)
|
||||||
if int64(len) != len64 {
|
if int64(len) != len64 {
|
||||||
panicmakeslicelen()
|
panicmakeslicelen()
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import (
|
||||||
// A Reader implements the io.Reader, io.ReaderAt, io.Seeker, io.WriterTo,
|
// A Reader implements the io.Reader, io.ReaderAt, io.Seeker, io.WriterTo,
|
||||||
// io.ByteScanner, and io.RuneScanner interfaces by reading
|
// io.ByteScanner, and io.RuneScanner interfaces by reading
|
||||||
// from a string.
|
// from a string.
|
||||||
|
// The zero value for Reader operates like a Reader of an empty string.
|
||||||
type Reader struct {
|
type Reader struct {
|
||||||
s string
|
s string
|
||||||
i int64 // current reading index
|
i int64 // current reading index
|
||||||
|
|
@ -70,10 +71,10 @@ func (r *Reader) ReadByte() (byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Reader) UnreadByte() error {
|
func (r *Reader) UnreadByte() error {
|
||||||
r.prevRune = -1
|
|
||||||
if r.i <= 0 {
|
if r.i <= 0 {
|
||||||
return errors.New("strings.Reader.UnreadByte: at beginning of string")
|
return errors.New("strings.Reader.UnreadByte: at beginning of string")
|
||||||
}
|
}
|
||||||
|
r.prevRune = -1
|
||||||
r.i--
|
r.i--
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -94,6 +95,9 @@ func (r *Reader) ReadRune() (ch rune, size int, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Reader) UnreadRune() error {
|
func (r *Reader) UnreadRune() error {
|
||||||
|
if r.i <= 0 {
|
||||||
|
return errors.New("strings.Reader.UnreadRune: at beginning of string")
|
||||||
|
}
|
||||||
if r.prevRune < 0 {
|
if r.prevRune < 0 {
|
||||||
return errors.New("strings.Reader.UnreadRune: previous operation was not ReadRune")
|
return errors.New("strings.Reader.UnreadRune: previous operation was not ReadRune")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -190,3 +190,45 @@ func TestReaderReset(t *testing.T) {
|
||||||
t.Errorf("ReadAll: got %q, want %q", got, want)
|
t.Errorf("ReadAll: got %q, want %q", got, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestReaderZero(t *testing.T) {
|
||||||
|
if l := (&strings.Reader{}).Len(); l != 0 {
|
||||||
|
t.Errorf("Len: got %d, want 0", l)
|
||||||
|
}
|
||||||
|
|
||||||
|
if n, err := (&strings.Reader{}).Read(nil); n != 0 || err != io.EOF {
|
||||||
|
t.Errorf("Read: got %d, %v; want 0, io.EOF", n, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if n, err := (&strings.Reader{}).ReadAt(nil, 11); n != 0 || err != io.EOF {
|
||||||
|
t.Errorf("ReadAt: got %d, %v; want 0, io.EOF", n, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b, err := (&strings.Reader{}).ReadByte(); b != 0 || err != io.EOF {
|
||||||
|
t.Errorf("ReadByte: got %d, %v; want 0, io.EOF", b, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ch, size, err := (&strings.Reader{}).ReadRune(); ch != 0 || size != 0 || err != io.EOF {
|
||||||
|
t.Errorf("ReadRune: got %d, %d, %v; want 0, 0, io.EOF", ch, size, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if offset, err := (&strings.Reader{}).Seek(11, io.SeekStart); offset != 11 || err != nil {
|
||||||
|
t.Errorf("Seek: got %d, %v; want 11, nil", offset, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if s := (&strings.Reader{}).Size(); s != 0 {
|
||||||
|
t.Errorf("Size: got %d, want 0", s)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (&strings.Reader{}).UnreadByte() == nil {
|
||||||
|
t.Errorf("UnreadByte: got nil, want error")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (&strings.Reader{}).UnreadRune() == nil {
|
||||||
|
t.Errorf("UnreadRune: got nil, want error")
|
||||||
|
}
|
||||||
|
|
||||||
|
if n, err := (&strings.Reader{}).WriteTo(ioutil.Discard); n != 0 || err != nil {
|
||||||
|
t.Errorf("WriteTo: got %d, %v; want 0, nil", n, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,8 @@ func SubMem(arr []int, b, c, d int) int {
|
||||||
arr[d] -= 15
|
arr[d] -= 15
|
||||||
// 386:`DECL\s\([A-Z]+\)\([A-Z]+\*4\)`
|
// 386:`DECL\s\([A-Z]+\)\([A-Z]+\*4\)`
|
||||||
arr[b]--
|
arr[b]--
|
||||||
|
// amd64:`DECQ\s64\([A-Z]+\)`
|
||||||
|
arr[8]--
|
||||||
// 386:"SUBL\t4"
|
// 386:"SUBL\t4"
|
||||||
// amd64:"SUBQ\t8"
|
// amd64:"SUBQ\t8"
|
||||||
return arr[0] - arr[1]
|
return arr[0] - arr[1]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue