[dev.link] all: merge branch 'master' into dev.link

Fixed a couple of minor conflicts in lib.go and deadcode.go
relating to debug logging.

Change-Id: I58335fc42ab1f1f3409fd8354da4f26419e8fb22
This commit is contained in:
Than McIntosh 2019-11-01 10:44:44 -04:00
commit c0555a2a7a
416 changed files with 15398 additions and 7536 deletions

View File

@ -90,7 +90,7 @@ func getTitle(w http.ResponseWriter, r *http.Request) (string, error) {
m := validPath.FindStringSubmatch(r.URL.Path) m := validPath.FindStringSubmatch(r.URL.Path)
if m == nil { if m == nil {
http.NotFound(w, r) http.NotFound(w, r)
return "", errors.New("Invalid Page Title") return "", errors.New("invalid Page Title")
} }
return m[2], nil // The title is the second subexpression. return m[2], nil // The title is the second subexpression.
} }

View File

@ -54,6 +54,15 @@ See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.13.3">Go
1.13.3 milestone</a> on our issue tracker for details. 1.13.3 milestone</a> on our issue tracker for details.
</p> </p>
<p>
go1.13.4 (released 2019/10/31) includes fixes to the <code>net/http</code> and
<code>syscall</code> packages. It also fixes an issue on macOS 10.15 Catalina
where the non-notarized installer and binaries were being
<a href="https://golang.org/issue/34986">rejected by Gatekeeper</a>.
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.13.4">Go
1.13.4 milestone</a> on our issue tracker for details.
</p>
<h2 id="go1.12">go1.12 (released 2019/02/25)</h2> <h2 id="go1.12">go1.12 (released 2019/02/25)</h2>
<p> <p>
@ -150,6 +159,13 @@ See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.12.12">Go
1.12.12 milestone</a> on our issue tracker for details. 1.12.12 milestone</a> on our issue tracker for details.
</p> </p>
<p>
go1.12.13 (released 2019/10/31) fixes an issue on macOS 10.15 Catalina
where the non-notarized installer and binaries were being
<a href="https://golang.org/issue/34986">rejected by Gatekeeper</a>.
Only macOS users who hit this issue need to update.
</p>
<h2 id="go1.11">go1.11 (released 2018/08/24)</h2> <h2 id="go1.11">go1.11 (released 2018/08/24)</h2>
<p> <p>

View File

@ -56,6 +56,14 @@ TODO
Go 1.14 is the last Go release to support 32-bit binaries on Go 1.14 is the last Go release to support 32-bit binaries on
macOS (the <code>darwin/386</code> port). They are no longer macOS (the <code>darwin/386</code> port). They are no longer
supported by macOS, starting with macOS 10.15 (Catalina). supported by macOS, starting with macOS 10.15 (Catalina).
Go continues to support the 64-bit <code>darwin/amd64</code> port.
</p>
<p><!-- golang.org/issue/34751 -->
Go 1.14 will likely be the last Go release to support 32-bit
binaries on iOS, iPadOS, watchOS, and tvOS
(the <code>darwin/arm</code> port). Go continues to support the
64-bit <code>darwin/arm64</code> port.
</p> </p>
<h3 id="nacl">Native Client (NaCl)</h3> <h3 id="nacl">Native Client (NaCl)</h3>
@ -133,6 +141,10 @@ TODO
trimming the ".mod" extension and appending ".sum". trimming the ".mod" extension and appending ".sum".
</p> </p>
<p><!-- golang.org/issue/26092 -->
The <code>go</code> command now supports Subversion repositories in module mode.
</p>
<h2 id="runtime">Runtime</h2> <h2 id="runtime">Runtime</h2>
<p> <p>

View File

@ -706,9 +706,14 @@ func (b *Writer) WriteString(s string) (int, error) {
// supports the ReadFrom method, and b has no buffered data yet, // supports the ReadFrom method, and b has no buffered data yet,
// this calls the underlying ReadFrom without buffering. // this calls the underlying ReadFrom without buffering.
func (b *Writer) ReadFrom(r io.Reader) (n int64, err error) { func (b *Writer) ReadFrom(r io.Reader) (n int64, err error) {
if b.err != nil {
return 0, b.err
}
if b.Buffered() == 0 { if b.Buffered() == 0 {
if w, ok := b.wr.(io.ReaderFrom); ok { if w, ok := b.wr.(io.ReaderFrom); ok {
return w.ReadFrom(r) n, err = w.ReadFrom(r)
b.err = err
return n, err
} }
} }
var m int var m int

View File

@ -1535,6 +1535,52 @@ func TestPartialReadEOF(t *testing.T) {
} }
} }
type writerWithReadFromError struct{}
func (w writerWithReadFromError) ReadFrom(r io.Reader) (int64, error) {
return 0, errors.New("writerWithReadFromError error")
}
func (w writerWithReadFromError) Write(b []byte) (n int, err error) {
return 10, nil
}
func TestWriterReadFromMustSetUnderlyingError(t *testing.T) {
var wr = NewWriter(writerWithReadFromError{})
if _, err := wr.ReadFrom(strings.NewReader("test2")); err == nil {
t.Fatal("expected ReadFrom returns error, got nil")
}
if _, err := wr.Write([]byte("123")); err == nil {
t.Fatal("expected Write returns error, got nil")
}
}
type writeErrorOnlyWriter struct{}
func (w writeErrorOnlyWriter) Write(p []byte) (n int, err error) {
return 0, errors.New("writeErrorOnlyWriter error")
}
// Ensure that previous Write errors are immediately returned
// on any ReadFrom. See golang.org/issue/35194.
func TestWriterReadFromMustReturnUnderlyingError(t *testing.T) {
var wr = NewWriter(writeErrorOnlyWriter{})
s := "test1"
wantBuffered := len(s)
if _, err := wr.WriteString(s); err != nil {
t.Fatalf("unexpected error: %v", err)
}
if err := wr.Flush(); err == nil {
t.Error("expected flush error, got nil")
}
if _, err := wr.ReadFrom(strings.NewReader("test2")); err == nil {
t.Fatal("expected error, got nil")
}
if buffered := wr.Buffered(); buffered != wantBuffered {
t.Fatalf("Buffered = %v; want %v", buffered, wantBuffered)
}
}
func BenchmarkReaderCopyOptimal(b *testing.B) { func BenchmarkReaderCopyOptimal(b *testing.B) {
// Optimal case is where the underlying reader implements io.WriterTo // Optimal case is where the underlying reader implements io.WriterTo
srcBuf := bytes.NewBuffer(make([]byte, 8192)) srcBuf := bytes.NewBuffer(make([]byte, 8192))

View File

@ -130,27 +130,27 @@ TEXT foo(SB),DUPOK|NOSPLIT,$0
// { // {
// outcode(int($1), &$2, 0, &$4); // outcode(int($1), &$2, 0, &$4);
// } // }
MOVW FCR0, R1 MOVW FCR31, R1 // 4441f800
// LMOVW freg ',' fpscr // LMOVW freg ',' fpscr
// { // {
// outcode(int($1), &$2, 0, &$4); // outcode(int($1), &$2, 0, &$4);
// } // }
MOVW R1, FCR0 MOVW R1, FCR31 // 44c1f800
// LMOVW rreg ',' mreg // LMOVW rreg ',' mreg
// { // {
// outcode(int($1), &$2, 0, &$4); // outcode(int($1), &$2, 0, &$4);
// } // }
MOVW R1, M1 MOVW R1, M1 // 40810800
MOVV R1, M1 MOVV R1, M1 // 40a10800
// LMOVW mreg ',' rreg // LMOVW mreg ',' rreg
// { // {
// outcode(int($1), &$2, 0, &$4); // outcode(int($1), &$2, 0, &$4);
// } // }
MOVW M1, R1 MOVW M1, R1 // 40010800
MOVV M1, R1 MOVV M1, R1 // 40210800
// //
@ -406,6 +406,7 @@ label4:
NEGW R1, R2 // 00011023 NEGW R1, R2 // 00011023
NEGV R1, R2 // 0001102f NEGV R1, R2 // 0001102f
RET
// END // END
// //

View File

@ -171,37 +171,37 @@ var knownFormats = map[string]string{
"map[*cmd/compile/internal/gc.Node]*cmd/compile/internal/ssa.Value %v": "", "map[*cmd/compile/internal/gc.Node]*cmd/compile/internal/ssa.Value %v": "",
"map[*cmd/compile/internal/gc.Node][]*cmd/compile/internal/gc.Node %v": "", "map[*cmd/compile/internal/gc.Node][]*cmd/compile/internal/gc.Node %v": "",
"map[cmd/compile/internal/ssa.ID]uint32 %v": "", "map[cmd/compile/internal/ssa.ID]uint32 %v": "",
"map[int64]uint32 %v": "", "map[int64]uint32 %v": "",
"math/big.Accuracy %s": "", "math/big.Accuracy %s": "",
"reflect.Type %s": "", "reflect.Type %s": "",
"rune %#U": "", "rune %#U": "",
"rune %c": "", "rune %c": "",
"rune %q": "", "rune %q": "",
"string %-*s": "", "string %-*s": "",
"string %-16s": "", "string %-16s": "",
"string %-6s": "", "string %-6s": "",
"string %q": "", "string %q": "",
"string %s": "", "string %s": "",
"string %v": "", "string %v": "",
"time.Duration %d": "", "time.Duration %d": "",
"time.Duration %v": "", "time.Duration %v": "",
"uint %04x": "", "uint %04x": "",
"uint %5d": "", "uint %5d": "",
"uint %d": "", "uint %d": "",
"uint %x": "", "uint %x": "",
"uint16 %d": "", "uint16 %d": "",
"uint16 %x": "", "uint16 %x": "",
"uint32 %#U": "", "uint32 %#U": "",
"uint32 %#x": "", "uint32 %#x": "",
"uint32 %d": "", "uint32 %d": "",
"uint32 %v": "", "uint32 %v": "",
"uint32 %x": "", "uint32 %x": "",
"uint64 %08x": "", "uint64 %08x": "",
"uint64 %b": "", "uint64 %b": "",
"uint64 %d": "", "uint64 %d": "",
"uint64 %x": "", "uint64 %x": "",
"uint8 %d": "", "uint8 %d": "",
"uint8 %v": "", "uint8 %v": "",
"uint8 %x": "", "uint8 %x": "",
"uintptr %d": "", "uintptr %d": "",
} }

View File

@ -17,7 +17,6 @@ func Init(arch *gc.Arch) {
arch.MAXWIDTH = 1 << 50 arch.MAXWIDTH = 1 << 50
arch.ZeroRange = zerorange arch.ZeroRange = zerorange
arch.ZeroAuto = zeroAuto
arch.Ginsnop = ginsnop arch.Ginsnop = ginsnop
arch.Ginsnopdefer = ginsnop arch.Ginsnopdefer = ginsnop

View File

@ -121,26 +121,6 @@ func zerorange(pp *gc.Progs, p *obj.Prog, off, cnt int64, state *uint32) *obj.Pr
return p return p
} }
func zeroAuto(pp *gc.Progs, n *gc.Node) {
// Note: this code must not clobber any registers.
op := x86.AMOVQ
if gc.Widthptr == 4 {
op = x86.AMOVL
}
sym := n.Sym.Linksym()
size := n.Type.Size()
for i := int64(0); i < size; i += int64(gc.Widthptr) {
p := pp.Prog(op)
p.From.Type = obj.TYPE_CONST
p.From.Offset = 0
p.To.Type = obj.TYPE_MEM
p.To.Name = obj.NAME_AUTO
p.To.Reg = x86.REG_SP
p.To.Offset = n.Xoffset + i
p.To.Sym = sym
}
}
func ginsnop(pp *gc.Progs) *obj.Prog { func ginsnop(pp *gc.Progs) *obj.Prog {
// This is a hardware nop (1-byte 0x90) instruction, // This is a hardware nop (1-byte 0x90) instruction,
// even though we describe it as an explicit XCHGL here. // even though we describe it as an explicit XCHGL here.

View File

@ -1091,7 +1091,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
gc.AddAux(&p.From, v) gc.AddAux(&p.From, v)
p.To.Type = obj.TYPE_REG p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg0() p.To.Reg = v.Reg0()
case ssa.OpAMD64XCHGL, ssa.OpAMD64XCHGQ: case ssa.OpAMD64XCHGB, ssa.OpAMD64XCHGL, ssa.OpAMD64XCHGQ:
r := v.Reg0() r := v.Reg0()
if r != v.Args[0].Reg() { if r != v.Args[0].Reg() {
v.Fatalf("input[0] and output[0] not in same register %s", v.LongString()) v.Fatalf("input[0] and output[0] not in same register %s", v.LongString())

View File

@ -17,7 +17,6 @@ func Init(arch *gc.Arch) {
arch.MAXWIDTH = (1 << 32) - 1 arch.MAXWIDTH = (1 << 32) - 1
arch.SoftFloat = objabi.GOARM == 5 arch.SoftFloat = objabi.GOARM == 5
arch.ZeroRange = zerorange arch.ZeroRange = zerorange
arch.ZeroAuto = zeroAuto
arch.Ginsnop = ginsnop arch.Ginsnop = ginsnop
arch.Ginsnopdefer = ginsnop arch.Ginsnopdefer = ginsnop

View File

@ -47,27 +47,6 @@ func zerorange(pp *gc.Progs, p *obj.Prog, off, cnt int64, r0 *uint32) *obj.Prog
return p return p
} }
func zeroAuto(pp *gc.Progs, n *gc.Node) {
// Note: this code must not clobber any registers.
sym := n.Sym.Linksym()
size := n.Type.Size()
p := pp.Prog(arm.AMOVW)
p.From.Type = obj.TYPE_CONST
p.From.Offset = 0
p.To.Type = obj.TYPE_REG
p.To.Reg = arm.REGTMP
for i := int64(0); i < size; i += 4 {
p := pp.Prog(arm.AMOVW)
p.From.Type = obj.TYPE_REG
p.From.Reg = arm.REGTMP
p.To.Type = obj.TYPE_MEM
p.To.Name = obj.NAME_AUTO
p.To.Reg = arm.REGSP
p.To.Offset = n.Xoffset + i
p.To.Sym = sym
}
}
func ginsnop(pp *gc.Progs) *obj.Prog { func ginsnop(pp *gc.Progs) *obj.Prog {
p := pp.Prog(arm.AAND) p := pp.Prog(arm.AAND)
p.From.Type = obj.TYPE_REG p.From.Type = obj.TYPE_REG

View File

@ -17,7 +17,6 @@ func Init(arch *gc.Arch) {
arch.PadFrame = padframe arch.PadFrame = padframe
arch.ZeroRange = zerorange arch.ZeroRange = zerorange
arch.ZeroAuto = zeroAuto
arch.Ginsnop = ginsnop arch.Ginsnop = ginsnop
arch.Ginsnopdefer = ginsnop arch.Ginsnopdefer = ginsnop

View File

@ -63,22 +63,6 @@ func zerorange(pp *gc.Progs, p *obj.Prog, off, cnt int64, _ *uint32) *obj.Prog {
return p return p
} }
func zeroAuto(pp *gc.Progs, n *gc.Node) {
// Note: this code must not clobber any registers.
sym := n.Sym.Linksym()
size := n.Type.Size()
for i := int64(0); i < size; i += 8 {
p := pp.Prog(arm64.AMOVD)
p.From.Type = obj.TYPE_REG
p.From.Reg = arm64.REGZERO
p.To.Type = obj.TYPE_MEM
p.To.Name = obj.NAME_AUTO
p.To.Reg = arm64.REGSP
p.To.Offset = n.Xoffset + i
p.To.Sym = sym
}
}
func ginsnop(pp *gc.Progs) *obj.Prog { func ginsnop(pp *gc.Progs) *obj.Prog {
p := pp.Prog(arm64.AHINT) p := pp.Prog(arm64.AHINT)
p.From.Type = obj.TYPE_CONST p.From.Type = obj.TYPE_CONST

View File

@ -452,6 +452,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
ssa.OpARM64MOVDstore, ssa.OpARM64MOVDstore,
ssa.OpARM64FMOVSstore, ssa.OpARM64FMOVSstore,
ssa.OpARM64FMOVDstore, ssa.OpARM64FMOVDstore,
ssa.OpARM64STLRB,
ssa.OpARM64STLR, ssa.OpARM64STLR,
ssa.OpARM64STLRW: ssa.OpARM64STLRW:
p := s.Prog(v.Op.Asm()) p := s.Prog(v.Op.Asm())

View File

@ -270,11 +270,6 @@ type Arch struct {
// SSAGenBlock emits end-of-block Progs. SSAGenValue should be called // SSAGenBlock emits end-of-block Progs. SSAGenValue should be called
// for all values in the block before SSAGenBlock. // for all values in the block before SSAGenBlock.
SSAGenBlock func(s *SSAGenState, b, next *ssa.Block) SSAGenBlock func(s *SSAGenState, b, next *ssa.Block)
// ZeroAuto emits code to zero the given auto stack variable.
// ZeroAuto must not use any non-temporary registers.
// ZeroAuto will only be called for variables which contain a pointer.
ZeroAuto func(*Progs, *Node)
} }
var thearch Arch var thearch Arch

View File

@ -179,11 +179,6 @@ func (a *Mpflt) Neg() {
} }
func (a *Mpflt) SetString(as string) { func (a *Mpflt) SetString(as string) {
// TODO(gri) why is this needed?
for len(as) > 0 && (as[0] == ' ' || as[0] == '\t') {
as = as[1:]
}
f, _, err := a.Val.Parse(as, 0) f, _, err := a.Val.Parse(as, 0)
if err != nil { if err != nil {
yyerror("malformed constant: %s (%v)", as, err) yyerror("malformed constant: %s (%v)", as, err)

View File

@ -3337,7 +3337,7 @@ func init() {
s.vars[&memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v) s.vars[&memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v)
return s.newValue1(ssa.OpSelect0, types.Types[TUINT8], v) return s.newValue1(ssa.OpSelect0, types.Types[TUINT8], v)
}, },
sys.AMD64, sys.ARM64, sys.S390X, sys.MIPS64, sys.PPC64) sys.AMD64, sys.ARM64, sys.S390X, sys.MIPS, sys.MIPS64, sys.PPC64)
addF("runtime/internal/atomic", "Load64", addF("runtime/internal/atomic", "Load64",
func(s *state, n *Node, args []*ssa.Value) *ssa.Value { func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
v := s.newValue2(ssa.OpAtomicLoad64, types.NewTuple(types.Types[TUINT64], types.TypeMem), args[0], s.mem()) v := s.newValue2(ssa.OpAtomicLoad64, types.NewTuple(types.Types[TUINT64], types.TypeMem), args[0], s.mem())
@ -3366,6 +3366,12 @@ func init() {
return nil return nil
}, },
sys.AMD64, sys.ARM64, sys.S390X, sys.MIPS, sys.MIPS64, sys.PPC64) sys.AMD64, sys.ARM64, sys.S390X, sys.MIPS, sys.MIPS64, sys.PPC64)
addF("runtime/internal/atomic", "Store8",
func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
s.vars[&memVar] = s.newValue3(ssa.OpAtomicStore8, types.TypeMem, args[0], args[1], s.mem())
return nil
},
sys.AMD64, sys.ARM64, sys.S390X, sys.MIPS, sys.MIPS64, sys.PPC64)
addF("runtime/internal/atomic", "Store64", addF("runtime/internal/atomic", "Store64",
func(s *state, n *Node, args []*ssa.Value) *ssa.Value { func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
s.vars[&memVar] = s.newValue3(ssa.OpAtomicStore64, types.TypeMem, args[0], args[1], s.mem()) s.vars[&memVar] = s.newValue3(ssa.OpAtomicStore64, types.TypeMem, args[0], args[1], s.mem())
@ -4099,7 +4105,7 @@ func (s *state) openDeferRecord(n *Node) {
// runtime panic code to use. But in the defer exit code, we will // runtime panic code to use. But in the defer exit code, we will
// call the function directly if it is a static function. // call the function directly if it is a static function.
closureVal := s.expr(fn) closureVal := s.expr(fn)
closure := s.openDeferSave(fn, fn.Type, closureVal) closure := s.openDeferSave(nil, fn.Type, closureVal)
opendefer.closureNode = closure.Aux.(*Node) opendefer.closureNode = closure.Aux.(*Node)
if !(fn.Op == ONAME && fn.Class() == PFUNC) { if !(fn.Op == ONAME && fn.Class() == PFUNC) {
opendefer.closure = closure opendefer.closure = closure
@ -4112,14 +4118,14 @@ func (s *state) openDeferRecord(n *Node) {
// We must always store the function value in a stack slot for the // We must always store the function value in a stack slot for the
// runtime panic code to use. But in the defer exit code, we will // runtime panic code to use. But in the defer exit code, we will
// call the method directly. // call the method directly.
closure := s.openDeferSave(fn, fn.Type, closureVal) closure := s.openDeferSave(nil, fn.Type, closureVal)
opendefer.closureNode = closure.Aux.(*Node) opendefer.closureNode = closure.Aux.(*Node)
} else { } else {
if fn.Op != ODOTINTER { if fn.Op != ODOTINTER {
Fatalf("OCALLINTER: n.Left not an ODOTINTER: %v", fn.Op) Fatalf("OCALLINTER: n.Left not an ODOTINTER: %v", fn.Op)
} }
closure, rcvr := s.getClosureAndRcvr(fn) closure, rcvr := s.getClosureAndRcvr(fn)
opendefer.closure = s.openDeferSave(fn, closure.Type, closure) opendefer.closure = s.openDeferSave(nil, closure.Type, closure)
// Important to get the receiver type correct, so it is recognized // Important to get the receiver type correct, so it is recognized
// as a pointer for GC purposes. // as a pointer for GC purposes.
opendefer.rcvr = s.openDeferSave(nil, fn.Type.Recv().Type, rcvr) opendefer.rcvr = s.openDeferSave(nil, fn.Type.Recv().Type, rcvr)
@ -4127,7 +4133,12 @@ func (s *state) openDeferRecord(n *Node) {
opendefer.rcvrNode = opendefer.rcvr.Aux.(*Node) opendefer.rcvrNode = opendefer.rcvr.Aux.(*Node)
} }
for _, argn := range n.Rlist.Slice() { for _, argn := range n.Rlist.Slice() {
v := s.openDeferSave(argn, argn.Type, s.expr(argn)) var v *ssa.Value
if canSSAType(argn.Type) {
v = s.openDeferSave(nil, argn.Type, s.expr(argn))
} else {
v = s.openDeferSave(argn, argn.Type, nil)
}
args = append(args, v) args = append(args, v)
argNodes = append(argNodes, v.Aux.(*Node)) argNodes = append(argNodes, v.Aux.(*Node))
} }
@ -4144,13 +4155,22 @@ func (s *state) openDeferRecord(n *Node) {
s.store(types.Types[TUINT8], s.deferBitsAddr, newDeferBits) s.store(types.Types[TUINT8], s.deferBitsAddr, newDeferBits)
} }
// openDeferSave generates SSA nodes to store a value val (with type t) for an // openDeferSave generates SSA nodes to store a value (with type t) for an
// open-coded defer on the stack at an explicit autotmp location, so it can be // open-coded defer at an explicit autotmp location on the stack, so it can be
// reloaded and used for the appropriate call on exit. n is the associated node, // reloaded and used for the appropriate call on exit. If type t is SSAable, then
// which is only needed if the associated type is non-SSAable. It returns an SSA // val must be non-nil (and n should be nil) and val is the value to be stored. If
// value representing a pointer to the stack location. // type t is non-SSAable, then n must be non-nil (and val should be nil) and n is
// evaluated (via s.addr() below) to get the value that is to be stored. The
// function returns an SSA value representing a pointer to the autotmp location.
func (s *state) openDeferSave(n *Node, t *types.Type, val *ssa.Value) *ssa.Value { func (s *state) openDeferSave(n *Node, t *types.Type, val *ssa.Value) *ssa.Value {
argTemp := tempAt(val.Pos.WithNotStmt(), s.curfn, t) canSSA := canSSAType(t)
var pos src.XPos
if canSSA {
pos = val.Pos
} else {
pos = n.Pos
}
argTemp := tempAt(pos.WithNotStmt(), s.curfn, t)
argTemp.Name.SetOpenDeferSlot(true) argTemp.Name.SetOpenDeferSlot(true)
var addrArgTemp *ssa.Value var addrArgTemp *ssa.Value
// Use OpVarLive to make sure stack slots for the args, etc. are not // Use OpVarLive to make sure stack slots for the args, etc. are not
@ -4179,10 +4199,7 @@ func (s *state) openDeferSave(n *Node, t *types.Type, val *ssa.Value) *ssa.Value
// uninitialized pointer value. // uninitialized pointer value.
argTemp.Name.SetNeedzero(true) argTemp.Name.SetNeedzero(true)
} }
if !canSSAType(t) { if !canSSA {
if n.Op != ONAME {
panic(fmt.Sprintf("Non-SSAable value should be a named location: %v", n))
}
a := s.addr(n, false) a := s.addr(n, false)
s.move(t, addrArgTemp, a) s.move(t, addrArgTemp, a)
return addrArgTemp return addrArgTemp

View File

@ -32,7 +32,7 @@ func typecheckTypeSwitch(n *Node) {
// declaration itself. So if there are no cases, we won't // declaration itself. So if there are no cases, we won't
// notice that it went unused. // notice that it went unused.
if v := n.Left.Left; v != nil && !v.isBlank() && n.List.Len() == 0 { if v := n.Left.Left; v != nil && !v.isBlank() && n.List.Len() == 0 {
yyerrorl(v.Pos, "%v declared and not used", v.Sym) yyerrorl(v.Pos, "%v declared but not used", v.Sym)
} }
var defCase, nilCase *Node var defCase, nilCase *Node

View File

@ -2782,7 +2782,7 @@ func typecheckcomplit(n *Node) (res *Node) {
} }
elemType := n.Right.Right.Type elemType := n.Right.Right.Type
length := typecheckarraylit(elemType, -1, n.List.Slice()) length := typecheckarraylit(elemType, -1, n.List.Slice(), "array literal")
n.Op = OARRAYLIT n.Op = OARRAYLIT
n.Type = types.NewArray(elemType, length) n.Type = types.NewArray(elemType, length)
@ -2804,12 +2804,12 @@ func typecheckcomplit(n *Node) (res *Node) {
n.Type = nil n.Type = nil
case TARRAY: case TARRAY:
typecheckarraylit(t.Elem(), t.NumElem(), n.List.Slice()) typecheckarraylit(t.Elem(), t.NumElem(), n.List.Slice(), "array literal")
n.Op = OARRAYLIT n.Op = OARRAYLIT
n.Right = nil n.Right = nil
case TSLICE: case TSLICE:
length := typecheckarraylit(t.Elem(), -1, n.List.Slice()) length := typecheckarraylit(t.Elem(), -2, n.List.Slice(), "slice literal")
n.Op = OSLICELIT n.Op = OSLICELIT
n.Right = nodintconst(length) n.Right = nodintconst(length)
@ -2960,7 +2960,8 @@ func typecheckcomplit(n *Node) (res *Node) {
return n return n
} }
func typecheckarraylit(elemType *types.Type, bound int64, elts []*Node) int64 { // typecheckarraylit type-checks a sequence of slice/array literal elements.
func typecheckarraylit(elemType *types.Type, bound int64, elts []*Node, ctx string) int64 {
// If there are key/value pairs, create a map to keep seen // If there are key/value pairs, create a map to keep seen
// keys so we can check for duplicate indices. // keys so we can check for duplicate indices.
var indices map[int64]bool var indices map[int64]bool
@ -2995,12 +2996,12 @@ func typecheckarraylit(elemType *types.Type, bound int64, elts []*Node) int64 {
r := *vp r := *vp
r = pushtype(r, elemType) r = pushtype(r, elemType)
r = typecheck(r, ctxExpr) r = typecheck(r, ctxExpr)
*vp = assignconv(r, elemType, "array or slice literal") *vp = assignconv(r, elemType, ctx)
if key >= 0 { if key >= 0 {
if indices != nil { if indices != nil {
if indices[key] { if indices[key] {
yyerror("duplicate index in array literal: %d", key) yyerror("duplicate index in %s: %d", ctx, key)
} else { } else {
indices[key] = true indices[key] = true
} }

View File

@ -50,10 +50,10 @@ func walk(fn *Node) {
if defn.Left.Name.Used() { if defn.Left.Name.Used() {
continue continue
} }
yyerrorl(defn.Left.Pos, "%v declared and not used", ln.Sym) yyerrorl(defn.Left.Pos, "%v declared but not used", ln.Sym)
defn.Left.Name.SetUsed(true) // suppress repeats defn.Left.Name.SetUsed(true) // suppress repeats
} else { } else {
yyerrorl(ln.Pos, "%v declared and not used", ln.Sym) yyerrorl(ln.Pos, "%v declared but not used", ln.Sym)
} }
} }
@ -3965,8 +3965,12 @@ func walkCheckPtrArithmetic(n *Node, init *Nodes) *Node {
// Calling cheapexpr(n, init) below leads to a recursive call // Calling cheapexpr(n, init) below leads to a recursive call
// to walkexpr, which leads us back here again. Use n.Opt to // to walkexpr, which leads us back here again. Use n.Opt to
// prevent infinite loops. // prevent infinite loops.
if n.Opt() == &walkCheckPtrArithmeticMarker { if opt := n.Opt(); opt == &walkCheckPtrArithmeticMarker {
return n return n
} else if opt != nil {
// We use n.Opt() here because today it's not used for OCONVNOP. If that changes,
// there's no guarantee that temporarily replacing it is safe, so just hard fail here.
Fatalf("unexpected Opt: %v", opt)
} }
n.SetOpt(&walkCheckPtrArithmeticMarker) n.SetOpt(&walkCheckPtrArithmeticMarker)
defer n.SetOpt(nil) defer n.SetOpt(nil)

View File

@ -20,7 +20,6 @@ func Init(arch *gc.Arch) {
arch.MAXWIDTH = (1 << 31) - 1 arch.MAXWIDTH = (1 << 31) - 1
arch.SoftFloat = (objabi.GOMIPS == "softfloat") arch.SoftFloat = (objabi.GOMIPS == "softfloat")
arch.ZeroRange = zerorange arch.ZeroRange = zerorange
arch.ZeroAuto = zeroAuto
arch.Ginsnop = ginsnop arch.Ginsnop = ginsnop
arch.Ginsnopdefer = ginsnop arch.Ginsnopdefer = ginsnop
arch.SSAMarkMoves = func(s *gc.SSAGenState, b *ssa.Block) {} arch.SSAMarkMoves = func(s *gc.SSAGenState, b *ssa.Block) {}

View File

@ -43,22 +43,6 @@ func zerorange(pp *gc.Progs, p *obj.Prog, off, cnt int64, _ *uint32) *obj.Prog {
return p return p
} }
func zeroAuto(pp *gc.Progs, n *gc.Node) {
// Note: this code must not clobber any registers.
sym := n.Sym.Linksym()
size := n.Type.Size()
for i := int64(0); i < size; i += 4 {
p := pp.Prog(mips.AMOVW)
p.From.Type = obj.TYPE_REG
p.From.Reg = mips.REGZERO
p.To.Type = obj.TYPE_MEM
p.To.Name = obj.NAME_AUTO
p.To.Reg = mips.REGSP
p.To.Offset = n.Xoffset + i
p.To.Sym = sym
}
}
func ginsnop(pp *gc.Progs) *obj.Prog { func ginsnop(pp *gc.Progs) *obj.Prog {
p := pp.Prog(mips.ANOR) p := pp.Prog(mips.ANOR)
p.From.Type = obj.TYPE_REG p.From.Type = obj.TYPE_REG

View File

@ -497,20 +497,36 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p.To.Name = obj.NAME_EXTERN p.To.Name = obj.NAME_EXTERN
p.To.Sym = gc.ExtendCheckFunc[v.AuxInt] p.To.Sym = gc.ExtendCheckFunc[v.AuxInt]
s.UseArgs(12) // space used in callee args area by assembly stubs s.UseArgs(12) // space used in callee args area by assembly stubs
case ssa.OpMIPSLoweredAtomicLoad: case ssa.OpMIPSLoweredAtomicLoad8,
ssa.OpMIPSLoweredAtomicLoad32:
s.Prog(mips.ASYNC) s.Prog(mips.ASYNC)
p := s.Prog(mips.AMOVW) var op obj.As
switch v.Op {
case ssa.OpMIPSLoweredAtomicLoad8:
op = mips.AMOVB
case ssa.OpMIPSLoweredAtomicLoad32:
op = mips.AMOVW
}
p := s.Prog(op)
p.From.Type = obj.TYPE_MEM p.From.Type = obj.TYPE_MEM
p.From.Reg = v.Args[0].Reg() p.From.Reg = v.Args[0].Reg()
p.To.Type = obj.TYPE_REG p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg0() p.To.Reg = v.Reg0()
s.Prog(mips.ASYNC) s.Prog(mips.ASYNC)
case ssa.OpMIPSLoweredAtomicStore: case ssa.OpMIPSLoweredAtomicStore8,
ssa.OpMIPSLoweredAtomicStore32:
s.Prog(mips.ASYNC) s.Prog(mips.ASYNC)
p := s.Prog(mips.AMOVW) var op obj.As
switch v.Op {
case ssa.OpMIPSLoweredAtomicStore8:
op = mips.AMOVB
case ssa.OpMIPSLoweredAtomicStore32:
op = mips.AMOVW
}
p := s.Prog(op)
p.From.Type = obj.TYPE_REG p.From.Type = obj.TYPE_REG
p.From.Reg = v.Args[1].Reg() p.From.Reg = v.Args[1].Reg()
p.To.Type = obj.TYPE_MEM p.To.Type = obj.TYPE_MEM

View File

@ -20,7 +20,6 @@ func Init(arch *gc.Arch) {
arch.MAXWIDTH = 1 << 50 arch.MAXWIDTH = 1 << 50
arch.SoftFloat = objabi.GOMIPS64 == "softfloat" arch.SoftFloat = objabi.GOMIPS64 == "softfloat"
arch.ZeroRange = zerorange arch.ZeroRange = zerorange
arch.ZeroAuto = zeroAuto
arch.Ginsnop = ginsnop arch.Ginsnop = ginsnop
arch.Ginsnopdefer = ginsnop arch.Ginsnopdefer = ginsnop

View File

@ -47,22 +47,6 @@ func zerorange(pp *gc.Progs, p *obj.Prog, off, cnt int64, _ *uint32) *obj.Prog {
return p return p
} }
func zeroAuto(pp *gc.Progs, n *gc.Node) {
// Note: this code must not clobber any registers.
sym := n.Sym.Linksym()
size := n.Type.Size()
for i := int64(0); i < size; i += 8 {
p := pp.Prog(mips.AMOVV)
p.From.Type = obj.TYPE_REG
p.From.Reg = mips.REGZERO
p.To.Type = obj.TYPE_MEM
p.To.Name = obj.NAME_AUTO
p.To.Reg = mips.REGSP
p.To.Offset = n.Xoffset + i
p.To.Sym = sym
}
}
func ginsnop(pp *gc.Progs) *obj.Prog { func ginsnop(pp *gc.Progs) *obj.Prog {
p := pp.Prog(mips.ANOR) p := pp.Prog(mips.ANOR)
p.From.Type = obj.TYPE_REG p.From.Type = obj.TYPE_REG

View File

@ -516,9 +516,12 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p.To.Type = obj.TYPE_REG p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg0() p.To.Reg = v.Reg0()
s.Prog(mips.ASYNC) s.Prog(mips.ASYNC)
case ssa.OpMIPS64LoweredAtomicStore32, ssa.OpMIPS64LoweredAtomicStore64: case ssa.OpMIPS64LoweredAtomicStore8, ssa.OpMIPS64LoweredAtomicStore32, ssa.OpMIPS64LoweredAtomicStore64:
as := mips.AMOVV as := mips.AMOVV
if v.Op == ssa.OpMIPS64LoweredAtomicStore32 { switch v.Op {
case ssa.OpMIPS64LoweredAtomicStore8:
as = mips.AMOVB
case ssa.OpMIPS64LoweredAtomicStore32:
as = mips.AMOVW as = mips.AMOVW
} }
s.Prog(mips.ASYNC) s.Prog(mips.ASYNC)

View File

@ -19,7 +19,6 @@ func Init(arch *gc.Arch) {
arch.MAXWIDTH = 1 << 60 arch.MAXWIDTH = 1 << 60
arch.ZeroRange = zerorange arch.ZeroRange = zerorange
arch.ZeroAuto = zeroAuto
arch.Ginsnop = ginsnop arch.Ginsnop = ginsnop
arch.Ginsnopdefer = ginsnopdefer arch.Ginsnopdefer = ginsnopdefer

View File

@ -42,22 +42,6 @@ func zerorange(pp *gc.Progs, p *obj.Prog, off, cnt int64, _ *uint32) *obj.Prog {
return p return p
} }
func zeroAuto(pp *gc.Progs, n *gc.Node) {
// Note: this code must not clobber any registers.
sym := n.Sym.Linksym()
size := n.Type.Size()
for i := int64(0); i < size; i += 8 {
p := pp.Prog(ppc64.AMOVD)
p.From.Type = obj.TYPE_REG
p.From.Reg = ppc64.REGZERO
p.To.Type = obj.TYPE_MEM
p.To.Name = obj.NAME_AUTO
p.To.Reg = ppc64.REGSP
p.To.Offset = n.Xoffset + i
p.To.Sym = sym
}
}
func ginsnop(pp *gc.Progs) *obj.Prog { func ginsnop(pp *gc.Progs) *obj.Prog {
p := pp.Prog(ppc64.AOR) p := pp.Prog(ppc64.AOR)
p.From.Type = obj.TYPE_REG p.From.Type = obj.TYPE_REG

View File

@ -335,12 +335,16 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
pisync.To.Type = obj.TYPE_NONE pisync.To.Type = obj.TYPE_NONE
gc.Patch(p2, pisync) gc.Patch(p2, pisync)
case ssa.OpPPC64LoweredAtomicStore32, case ssa.OpPPC64LoweredAtomicStore8,
ssa.OpPPC64LoweredAtomicStore32,
ssa.OpPPC64LoweredAtomicStore64: ssa.OpPPC64LoweredAtomicStore64:
// SYNC or LWSYNC // SYNC or LWSYNC
// MOVD/MOVW arg1,(arg0) // MOVB/MOVW/MOVD arg1,(arg0)
st := ppc64.AMOVD st := ppc64.AMOVD
if v.Op == ssa.OpPPC64LoweredAtomicStore32 { switch v.Op {
case ssa.OpPPC64LoweredAtomicStore8:
st = ppc64.AMOVB
case ssa.OpPPC64LoweredAtomicStore32:
st = ppc64.AMOVW st = ppc64.AMOVW
} }
arg0 := v.Args[0].Reg() arg0 := v.Args[0].Reg()

View File

@ -15,7 +15,6 @@ func Init(arch *gc.Arch) {
arch.MAXWIDTH = 1 << 50 arch.MAXWIDTH = 1 << 50
arch.ZeroRange = zerorange arch.ZeroRange = zerorange
arch.ZeroAuto = zeroAuto
arch.Ginsnop = ginsnop arch.Ginsnop = ginsnop
arch.Ginsnopdefer = ginsnop arch.Ginsnopdefer = ginsnop

View File

@ -83,23 +83,6 @@ func zerorange(pp *gc.Progs, p *obj.Prog, off, cnt int64, _ *uint32) *obj.Prog {
return p return p
} }
func zeroAuto(pp *gc.Progs, n *gc.Node) {
// Note: this code must not clobber any registers or the
// condition code.
sym := n.Sym.Linksym()
size := n.Type.Size()
for i := int64(0); i < size; i += int64(gc.Widthptr) {
p := pp.Prog(s390x.AMOVD)
p.From.Type = obj.TYPE_CONST
p.From.Offset = 0
p.To.Type = obj.TYPE_MEM
p.To.Name = obj.NAME_AUTO
p.To.Reg = s390x.REGSP
p.To.Offset = n.Xoffset + i
p.To.Sym = sym
}
}
func ginsnop(pp *gc.Progs) *obj.Prog { func ginsnop(pp *gc.Progs) *obj.Prog {
return pp.Prog(s390x.ANOPH) return pp.Prog(s390x.ANOPH)
} }

View File

@ -725,7 +725,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
gc.AddAux(&p.From, v) gc.AddAux(&p.From, v)
p.To.Type = obj.TYPE_REG p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg0() p.To.Reg = v.Reg0()
case ssa.OpS390XMOVWatomicstore, ssa.OpS390XMOVDatomicstore: case ssa.OpS390XMOVBatomicstore, ssa.OpS390XMOVWatomicstore, ssa.OpS390XMOVDatomicstore:
p := s.Prog(v.Op.Asm()) p := s.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_REG p.From.Type = obj.TYPE_REG
p.From.Reg = v.Args[1].Reg() p.From.Reg = v.Args[1].Reg()

View File

@ -220,7 +220,7 @@ func elimIf(f *Func, loadAddr *sparseSet, dom *Block) bool {
// that has the same line number as the Pos for b itself, and // that has the same line number as the Pos for b itself, and
// puts a statement mark on it, and returns whether it succeeded // puts a statement mark on it, and returns whether it succeeded
// in this operation. // in this operation.
setBlockPos := func (b *Block) bool { setBlockPos := func(b *Block) bool {
pos := b.Pos pos := b.Pos
for _, v := range b.Values { for _, v := range b.Values {
if pos.SameFileAndLine(v.Pos) && !isPoorStatementOp(v.Op) { if pos.SameFileAndLine(v.Pos) && !isPoorStatementOp(v.Op) {

View File

@ -4,13 +4,11 @@
// Lowering arithmetic // Lowering arithmetic
(Add(64|32|16|8) x y) -> (ADD(Q|L|L|L) x y) (Add(64|32|16|8) x y) -> (ADD(Q|L|L|L) x y)
(AddPtr x y) && config.PtrSize == 8 -> (ADDQ x y) (AddPtr x y) -> (ADDQ x y)
(AddPtr x y) && config.PtrSize == 4 -> (ADDL x y)
(Add(32|64)F x y) -> (ADDS(S|D) x y) (Add(32|64)F x y) -> (ADDS(S|D) x y)
(Sub(64|32|16|8) x y) -> (SUB(Q|L|L|L) x y) (Sub(64|32|16|8) x y) -> (SUB(Q|L|L|L) x y)
(SubPtr x y) && config.PtrSize == 8 -> (SUBQ x y) (SubPtr x y) -> (SUBQ x y)
(SubPtr x y) && config.PtrSize == 4 -> (SUBL x y)
(Sub(32|64)F x y) -> (SUBS(S|D) x y) (Sub(32|64)F x y) -> (SUBS(S|D) x y)
(Mul(64|32|16|8) x y) -> (MUL(Q|L|L|L) x y) (Mul(64|32|16|8) x y) -> (MUL(Q|L|L|L) x y)
@ -76,9 +74,8 @@
(Not x) -> (XORLconst [1] x) (Not x) -> (XORLconst [1] x)
// Lowering pointer arithmetic // Lowering pointer arithmetic
(OffPtr [off] ptr) && config.PtrSize == 8 && is32Bit(off) -> (ADDQconst [off] ptr) (OffPtr [off] ptr) && is32Bit(off) -> (ADDQconst [off] ptr)
(OffPtr [off] ptr) && config.PtrSize == 8 -> (ADDQ (MOVQconst [off]) ptr) (OffPtr [off] ptr) -> (ADDQ (MOVQconst [off]) ptr)
(OffPtr [off] ptr) && config.PtrSize == 4 -> (ADDLconst [off] ptr)
// Lowering other arithmetic // Lowering other arithmetic
(Ctz64 <t> x) -> (CMOVQEQ (Select0 <t> (BSFQ x)) (MOVQconst <t> [64]) (Select1 <types.TypeFlags> (BSFQ x))) (Ctz64 <t> x) -> (CMOVQEQ (Select0 <t> (BSFQ x)) (MOVQconst <t> [64]) (Select1 <types.TypeFlags> (BSFQ x)))
@ -217,18 +214,16 @@
(Geq(32|64)F x y) -> (SETGEF (UCOMIS(S|D) x y)) (Geq(32|64)F x y) -> (SETGEF (UCOMIS(S|D) x y))
(Eq(64|32|16|8|B) x y) -> (SETEQ (CMP(Q|L|W|B|B) x y)) (Eq(64|32|16|8|B) x y) -> (SETEQ (CMP(Q|L|W|B|B) x y))
(EqPtr x y) && config.PtrSize == 8 -> (SETEQ (CMPQ x y)) (EqPtr x y) -> (SETEQ (CMPQ x y))
(EqPtr x y) && config.PtrSize == 4 -> (SETEQ (CMPL x y))
(Eq(32|64)F x y) -> (SETEQF (UCOMIS(S|D) x y)) (Eq(32|64)F x y) -> (SETEQF (UCOMIS(S|D) x y))
(Neq(64|32|16|8|B) x y) -> (SETNE (CMP(Q|L|W|B|B) x y)) (Neq(64|32|16|8|B) x y) -> (SETNE (CMP(Q|L|W|B|B) x y))
(NeqPtr x y) && config.PtrSize == 8 -> (SETNE (CMPQ x y)) (NeqPtr x y) -> (SETNE (CMPQ x y))
(NeqPtr x y) && config.PtrSize == 4 -> (SETNE (CMPL x y))
(Neq(32|64)F x y) -> (SETNEF (UCOMIS(S|D) x y)) (Neq(32|64)F x y) -> (SETNEF (UCOMIS(S|D) x y))
// Lowering loads // Lowering loads
(Load <t> ptr mem) && (is64BitInt(t) || isPtr(t) && config.PtrSize == 8) -> (MOVQload ptr mem) (Load <t> ptr mem) && (is64BitInt(t) || isPtr(t)) -> (MOVQload ptr mem)
(Load <t> ptr mem) && (is32BitInt(t) || isPtr(t) && config.PtrSize == 4) -> (MOVLload ptr mem) (Load <t> ptr mem) && is32BitInt(t) -> (MOVLload ptr mem)
(Load <t> ptr mem) && is16BitInt(t) -> (MOVWload ptr mem) (Load <t> ptr mem) && is16BitInt(t) -> (MOVWload ptr mem)
(Load <t> ptr mem) && (t.IsBoolean() || is8BitInt(t)) -> (MOVBload ptr mem) (Load <t> ptr mem) && (t.IsBoolean() || is8BitInt(t)) -> (MOVBload ptr mem)
(Load <t> ptr mem) && is32BitFloat(t) -> (MOVSSload ptr mem) (Load <t> ptr mem) && is32BitFloat(t) -> (MOVSSload ptr mem)
@ -420,8 +415,7 @@
(Const64 [val]) -> (MOVQconst [val]) (Const64 [val]) -> (MOVQconst [val])
(Const32F [val]) -> (MOVSSconst [val]) (Const32F [val]) -> (MOVSSconst [val])
(Const64F [val]) -> (MOVSDconst [val]) (Const64F [val]) -> (MOVSDconst [val])
(ConstNil) && config.PtrSize == 8 -> (MOVQconst [0]) (ConstNil) -> (MOVQconst [0])
(ConstNil) && config.PtrSize == 4 -> (MOVLconst [0])
(ConstBool [b]) -> (MOVLconst [b]) (ConstBool [b]) -> (MOVLconst [b])
// Lowering calls // Lowering calls
@ -476,21 +470,16 @@
(CMOV(QEQ|QGT|QGE|QCS|QLS|LEQ|LGT|LGE|LCS|LLS|WEQ|WGT|WGE|WCS|WLS) y _ (FlagLT_UGT)) -> y (CMOV(QEQ|QGT|QGE|QCS|QLS|LEQ|LGT|LGE|LCS|LLS|WEQ|WGT|WGE|WCS|WLS) y _ (FlagLT_UGT)) -> y
// Miscellaneous // Miscellaneous
(IsNonNil p) && config.PtrSize == 8 -> (SETNE (TESTQ p p)) (IsNonNil p) -> (SETNE (TESTQ p p))
(IsNonNil p) && config.PtrSize == 4 -> (SETNE (TESTL p p)) (IsInBounds idx len) -> (SETB (CMPQ idx len))
(IsInBounds idx len) && config.PtrSize == 8 -> (SETB (CMPQ idx len)) (IsSliceInBounds idx len) -> (SETBE (CMPQ idx len))
(IsInBounds idx len) && config.PtrSize == 4 -> (SETB (CMPL idx len))
(IsSliceInBounds idx len) && config.PtrSize == 8 -> (SETBE (CMPQ idx len))
(IsSliceInBounds idx len) && config.PtrSize == 4 -> (SETBE (CMPL idx len))
(NilCheck ptr mem) -> (LoweredNilCheck ptr mem) (NilCheck ptr mem) -> (LoweredNilCheck ptr mem)
(GetG mem) -> (LoweredGetG mem) (GetG mem) -> (LoweredGetG mem)
(GetClosurePtr) -> (LoweredGetClosurePtr) (GetClosurePtr) -> (LoweredGetClosurePtr)
(GetCallerPC) -> (LoweredGetCallerPC) (GetCallerPC) -> (LoweredGetCallerPC)
(GetCallerSP) -> (LoweredGetCallerSP) (GetCallerSP) -> (LoweredGetCallerSP)
(Addr {sym} base) && config.PtrSize == 8 -> (LEAQ {sym} base) (Addr {sym} base) -> (LEAQ {sym} base)
(Addr {sym} base) && config.PtrSize == 4 -> (LEAL {sym} base) (LocalAddr {sym} base _) -> (LEAQ {sym} base)
(LocalAddr {sym} base _) && config.PtrSize == 8 -> (LEAQ {sym} base)
(LocalAddr {sym} base _) && config.PtrSize == 4 -> (LEAL {sym} base)
(MOVBstore [off] {sym} ptr y:(SETL x) mem) && y.Uses == 1 -> (SETLstore [off] {sym} ptr x mem) (MOVBstore [off] {sym} ptr y:(SETL x) mem) && y.Uses == 1 -> (SETLstore [off] {sym} ptr x mem)
(MOVBstore [off] {sym} ptr y:(SETLE x) mem) && y.Uses == 1 -> (SETLEstore [off] {sym} ptr x mem) (MOVBstore [off] {sym} ptr y:(SETLE x) mem) && y.Uses == 1 -> (SETLEstore [off] {sym} ptr x mem)
@ -528,15 +517,14 @@
(AtomicLoad8 ptr mem) -> (MOVBatomicload ptr mem) (AtomicLoad8 ptr mem) -> (MOVBatomicload ptr mem)
(AtomicLoad32 ptr mem) -> (MOVLatomicload ptr mem) (AtomicLoad32 ptr mem) -> (MOVLatomicload ptr mem)
(AtomicLoad64 ptr mem) -> (MOVQatomicload ptr mem) (AtomicLoad64 ptr mem) -> (MOVQatomicload ptr mem)
(AtomicLoadPtr ptr mem) && config.PtrSize == 8 -> (MOVQatomicload ptr mem) (AtomicLoadPtr ptr mem) -> (MOVQatomicload ptr mem)
(AtomicLoadPtr ptr mem) && config.PtrSize == 4 -> (MOVLatomicload ptr mem)
// Atomic stores. We use XCHG to prevent the hardware reordering a subsequent load. // Atomic stores. We use XCHG to prevent the hardware reordering a subsequent load.
// TODO: most runtime uses of atomic stores don't need that property. Use normal stores for those? // TODO: most runtime uses of atomic stores don't need that property. Use normal stores for those?
(AtomicStore8 ptr val mem) -> (Select1 (XCHGB <types.NewTuple(typ.UInt8,types.TypeMem)> val ptr mem))
(AtomicStore32 ptr val mem) -> (Select1 (XCHGL <types.NewTuple(typ.UInt32,types.TypeMem)> val ptr mem)) (AtomicStore32 ptr val mem) -> (Select1 (XCHGL <types.NewTuple(typ.UInt32,types.TypeMem)> val ptr mem))
(AtomicStore64 ptr val mem) -> (Select1 (XCHGQ <types.NewTuple(typ.UInt64,types.TypeMem)> val ptr mem)) (AtomicStore64 ptr val mem) -> (Select1 (XCHGQ <types.NewTuple(typ.UInt64,types.TypeMem)> val ptr mem))
(AtomicStorePtrNoWB ptr val mem) && config.PtrSize == 8 -> (Select1 (XCHGQ <types.NewTuple(typ.BytePtr,types.TypeMem)> val ptr mem)) (AtomicStorePtrNoWB ptr val mem) -> (Select1 (XCHGQ <types.NewTuple(typ.BytePtr,types.TypeMem)> val ptr mem))
(AtomicStorePtrNoWB ptr val mem) && config.PtrSize == 4 -> (Select1 (XCHGL <types.NewTuple(typ.BytePtr,types.TypeMem)> val ptr mem))
// Atomic exchanges. // Atomic exchanges.
(AtomicExchange32 ptr val mem) -> (XCHGL val ptr mem) (AtomicExchange32 ptr val mem) -> (XCHGL val ptr mem)

View File

@ -746,6 +746,7 @@ func init() {
// store arg0 to arg1+auxint+aux, arg2=mem. // store arg0 to arg1+auxint+aux, arg2=mem.
// These ops return a tuple of <old contents of *(arg1+auxint+aux), memory>. // These ops return a tuple of <old contents of *(arg1+auxint+aux), memory>.
// Note: arg0 and arg1 are backwards compared to MOVLstore (to facilitate resultInArg0)! // Note: arg0 and arg1 are backwards compared to MOVLstore (to facilitate resultInArg0)!
{name: "XCHGB", argLength: 3, reg: gpstorexchg, asm: "XCHGB", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true, hasSideEffects: true, symEffect: "RdWr"},
{name: "XCHGL", argLength: 3, reg: gpstorexchg, asm: "XCHGL", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true, hasSideEffects: true, symEffect: "RdWr"}, {name: "XCHGL", argLength: 3, reg: gpstorexchg, asm: "XCHGL", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true, hasSideEffects: true, symEffect: "RdWr"},
{name: "XCHGQ", argLength: 3, reg: gpstorexchg, asm: "XCHGQ", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true, hasSideEffects: true, symEffect: "RdWr"}, {name: "XCHGQ", argLength: 3, reg: gpstorexchg, asm: "XCHGQ", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true, hasSideEffects: true, symEffect: "RdWr"},

View File

@ -589,6 +589,7 @@
(AtomicLoad64 ptr mem) -> (LDAR ptr mem) (AtomicLoad64 ptr mem) -> (LDAR ptr mem)
(AtomicLoadPtr ptr mem) -> (LDAR ptr mem) (AtomicLoadPtr ptr mem) -> (LDAR ptr mem)
(AtomicStore8 ptr val mem) -> (STLRB ptr val mem)
(AtomicStore32 ptr val mem) -> (STLRW ptr val mem) (AtomicStore32 ptr val mem) -> (STLRW ptr val mem)
(AtomicStore64 ptr val mem) -> (STLR ptr val mem) (AtomicStore64 ptr val mem) -> (STLR ptr val mem)
(AtomicStorePtrNoWB ptr val mem) -> (STLR ptr val mem) (AtomicStorePtrNoWB ptr val mem) -> (STLR ptr val mem)

View File

@ -611,6 +611,7 @@ func init() {
// atomic stores. // atomic stores.
// store arg1 to arg0. arg2=mem. returns memory. auxint must be zero. // store arg1 to arg0. arg2=mem. returns memory. auxint must be zero.
{name: "STLRB", argLength: 3, reg: gpstore, asm: "STLRB", faultOnNilArg0: true, hasSideEffects: true},
{name: "STLR", argLength: 3, reg: gpstore, asm: "STLR", faultOnNilArg0: true, hasSideEffects: true}, {name: "STLR", argLength: 3, reg: gpstore, asm: "STLR", faultOnNilArg0: true, hasSideEffects: true},
{name: "STLRW", argLength: 3, reg: gpstore, asm: "STLRW", faultOnNilArg0: true, hasSideEffects: true}, {name: "STLRW", argLength: 3, reg: gpstore, asm: "STLRW", faultOnNilArg0: true, hasSideEffects: true},

View File

@ -351,11 +351,11 @@
(InterCall [argwid] entry mem) -> (CALLinter [argwid] entry mem) (InterCall [argwid] entry mem) -> (CALLinter [argwid] entry mem)
// atomic intrinsics // atomic intrinsics
(AtomicLoad32 ptr mem) -> (LoweredAtomicLoad ptr mem) (AtomicLoad(8|32) ptr mem) -> (LoweredAtomicLoad(8|32) ptr mem)
(AtomicLoadPtr ptr mem) -> (LoweredAtomicLoad ptr mem) (AtomicLoadPtr ptr mem) -> (LoweredAtomicLoad32 ptr mem)
(AtomicStore32 ptr val mem) -> (LoweredAtomicStore ptr val mem) (AtomicStore(8|32) ptr val mem) -> (LoweredAtomicStore(8|32) ptr val mem)
(AtomicStorePtrNoWB ptr val mem) -> (LoweredAtomicStore ptr val mem) (AtomicStorePtrNoWB ptr val mem) -> (LoweredAtomicStore32 ptr val mem)
(AtomicExchange32 ptr val mem) -> (LoweredAtomicExchange ptr val mem) (AtomicExchange32 ptr val mem) -> (LoweredAtomicExchange ptr val mem)
(AtomicAdd32 ptr val mem) -> (LoweredAtomicAdd ptr val mem) (AtomicAdd32 ptr val mem) -> (LoweredAtomicAdd ptr val mem)
@ -708,6 +708,6 @@
(CMOVZ a (MOVWconst [0]) c) -> (CMOVZzero a c) (CMOVZ a (MOVWconst [0]) c) -> (CMOVZzero a c)
// atomic // atomic
(LoweredAtomicStore ptr (MOVWconst [0]) mem) -> (LoweredAtomicStorezero ptr mem) (LoweredAtomicStore32 ptr (MOVWconst [0]) mem) -> (LoweredAtomicStorezero ptr mem)
(LoweredAtomicAdd ptr (MOVWconst [c]) mem) && is16Bit(c) -> (LoweredAtomicAddconst [c] ptr mem) (LoweredAtomicAdd ptr (MOVWconst [c]) mem) && is16Bit(c) -> (LoweredAtomicAddconst [c] ptr mem)

View File

@ -403,6 +403,7 @@
(AtomicLoad64 ptr mem) -> (LoweredAtomicLoad64 ptr mem) (AtomicLoad64 ptr mem) -> (LoweredAtomicLoad64 ptr mem)
(AtomicLoadPtr ptr mem) -> (LoweredAtomicLoad64 ptr mem) (AtomicLoadPtr ptr mem) -> (LoweredAtomicLoad64 ptr mem)
(AtomicStore8 ptr val mem) -> (LoweredAtomicStore8 ptr val mem)
(AtomicStore32 ptr val mem) -> (LoweredAtomicStore32 ptr val mem) (AtomicStore32 ptr val mem) -> (LoweredAtomicStore32 ptr val mem)
(AtomicStore64 ptr val mem) -> (LoweredAtomicStore64 ptr val mem) (AtomicStore64 ptr val mem) -> (LoweredAtomicStore64 ptr val mem)
(AtomicStorePtrNoWB ptr val mem) -> (LoweredAtomicStore64 ptr val mem) (AtomicStorePtrNoWB ptr val mem) -> (LoweredAtomicStore64 ptr val mem)

View File

@ -367,6 +367,7 @@ func init() {
// atomic stores. // atomic stores.
// store arg1 to arg0. arg2=mem. returns memory. // store arg1 to arg0. arg2=mem. returns memory.
{name: "LoweredAtomicStore8", argLength: 3, reg: gpstore, faultOnNilArg0: true, hasSideEffects: true},
{name: "LoweredAtomicStore32", argLength: 3, reg: gpstore, faultOnNilArg0: true, hasSideEffects: true}, {name: "LoweredAtomicStore32", argLength: 3, reg: gpstore, faultOnNilArg0: true, hasSideEffects: true},
{name: "LoweredAtomicStore64", argLength: 3, reg: gpstore, faultOnNilArg0: true, hasSideEffects: true}, {name: "LoweredAtomicStore64", argLength: 3, reg: gpstore, faultOnNilArg0: true, hasSideEffects: true},
// store zero to arg0. arg1=mem. returns memory. // store zero to arg0. arg1=mem. returns memory.

View File

@ -262,15 +262,17 @@ func init() {
// load from arg0. arg1=mem. // load from arg0. arg1=mem.
// returns <value,memory> so they can be properly ordered with other loads. // returns <value,memory> so they can be properly ordered with other loads.
// SYNC // SYNC
// MOVW (Rarg0), Rout // MOV(B|W) (Rarg0), Rout
// SYNC // SYNC
{name: "LoweredAtomicLoad", argLength: 2, reg: gpload, faultOnNilArg0: true}, {name: "LoweredAtomicLoad8", argLength: 2, reg: gpload, faultOnNilArg0: true},
{name: "LoweredAtomicLoad32", argLength: 2, reg: gpload, faultOnNilArg0: true},
// store arg1 to arg0. arg2=mem. returns memory. // store arg1 to arg0. arg2=mem. returns memory.
// SYNC // SYNC
// MOVW Rarg1, (Rarg0) // MOV(B|W) Rarg1, (Rarg0)
// SYNC // SYNC
{name: "LoweredAtomicStore", argLength: 3, reg: gpstore, faultOnNilArg0: true, hasSideEffects: true}, {name: "LoweredAtomicStore8", argLength: 3, reg: gpstore, faultOnNilArg0: true, hasSideEffects: true},
{name: "LoweredAtomicStore32", argLength: 3, reg: gpstore, faultOnNilArg0: true, hasSideEffects: true},
{name: "LoweredAtomicStorezero", argLength: 2, reg: gpstore0, faultOnNilArg0: true, hasSideEffects: true}, {name: "LoweredAtomicStorezero", argLength: 2, reg: gpstore0, faultOnNilArg0: true, hasSideEffects: true},
// atomic exchange. // atomic exchange.

View File

@ -931,7 +931,7 @@
(AtomicLoad(8|32|64|Ptr) ptr mem) -> (LoweredAtomicLoad(8|32|64|Ptr) [1] ptr mem) (AtomicLoad(8|32|64|Ptr) ptr mem) -> (LoweredAtomicLoad(8|32|64|Ptr) [1] ptr mem)
(AtomicLoadAcq32 ptr mem) -> (LoweredAtomicLoad32 [0] ptr mem) (AtomicLoadAcq32 ptr mem) -> (LoweredAtomicLoad32 [0] ptr mem)
(AtomicStore(32|64) ptr val mem) -> (LoweredAtomicStore(32|64) [1] ptr val mem) (AtomicStore(8|32|64) ptr val mem) -> (LoweredAtomicStore(8|32|64) [1] ptr val mem)
(AtomicStoreRel32 ptr val mem) -> (LoweredAtomicStore32 [0] ptr val mem) (AtomicStoreRel32 ptr val mem) -> (LoweredAtomicStore32 [0] ptr val mem)
//(AtomicStorePtrNoWB ptr val mem) -> (STLR ptr val mem) //(AtomicStorePtrNoWB ptr val mem) -> (STLR ptr val mem)

View File

@ -495,6 +495,7 @@ func init() {
faultOnNilArg1: true, faultOnNilArg1: true,
}, },
{name: "LoweredAtomicStore8", argLength: 3, reg: gpstore, typ: "Mem", aux: "Int64", faultOnNilArg0: true, hasSideEffects: true},
{name: "LoweredAtomicStore32", argLength: 3, reg: gpstore, typ: "Mem", aux: "Int64", faultOnNilArg0: true, hasSideEffects: true}, {name: "LoweredAtomicStore32", argLength: 3, reg: gpstore, typ: "Mem", aux: "Int64", faultOnNilArg0: true, hasSideEffects: true},
{name: "LoweredAtomicStore64", argLength: 3, reg: gpstore, typ: "Mem", aux: "Int64", faultOnNilArg0: true, hasSideEffects: true}, {name: "LoweredAtomicStore64", argLength: 3, reg: gpstore, typ: "Mem", aux: "Int64", faultOnNilArg0: true, hasSideEffects: true},

View File

@ -146,7 +146,7 @@
// reordering. Other sequences of memory operations (load-load, // reordering. Other sequences of memory operations (load-load,
// store-store and load-store) are already guaranteed not to be reordered. // store-store and load-store) are already guaranteed not to be reordered.
(AtomicLoad(8|32|Acq32|64|Ptr) ptr mem) -> (MOV(BZ|WZ|WZ|D|D)atomicload ptr mem) (AtomicLoad(8|32|Acq32|64|Ptr) ptr mem) -> (MOV(BZ|WZ|WZ|D|D)atomicload ptr mem)
(AtomicStore(32|64|PtrNoWB) ptr val mem) -> (SYNC (MOV(W|D|D)atomicstore ptr val mem)) (AtomicStore(8|32|64|PtrNoWB) ptr val mem) -> (SYNC (MOV(B|W|D|D)atomicstore ptr val mem))
// Store-release doesn't require store-load ordering. // Store-release doesn't require store-load ordering.
(AtomicStoreRel32 ptr val mem) -> (MOVWatomicstore ptr val mem) (AtomicStoreRel32 ptr val mem) -> (MOVWatomicstore ptr val mem)

View File

@ -495,6 +495,7 @@ func init() {
// Atomic stores. These are just normal stores. // Atomic stores. These are just normal stores.
// store arg1 to arg0+auxint+aux. arg2=mem. // store arg1 to arg0+auxint+aux. arg2=mem.
{name: "MOVBatomicstore", argLength: 3, reg: gpstore, asm: "MOVB", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, symEffect: "Write"},
{name: "MOVWatomicstore", argLength: 3, reg: gpstore, asm: "MOVW", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, symEffect: "Write"}, {name: "MOVWatomicstore", argLength: 3, reg: gpstore, asm: "MOVW", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, symEffect: "Write"},
{name: "MOVDatomicstore", argLength: 3, reg: gpstore, asm: "MOVD", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, symEffect: "Write"}, {name: "MOVDatomicstore", argLength: 3, reg: gpstore, asm: "MOVD", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, symEffect: "Write"},

View File

@ -803,7 +803,7 @@
// Putting struct{*byte} and similar into direct interfaces. // Putting struct{*byte} and similar into direct interfaces.
(IMake typ (StructMake1 val)) -> (IMake typ val) (IMake typ (StructMake1 val)) -> (IMake typ val)
(StructSelect [0] x:(IData _)) -> x (StructSelect [0] (IData x)) -> (IData x)
// un-SSAable values use mem->mem copies // un-SSAable values use mem->mem copies
(Store {t} dst (Load src mem) mem) && !fe.CanSSA(t.(*types.Type)) -> (Store {t} dst (Load src mem) mem) && !fe.CanSSA(t.(*types.Type)) ->
@ -823,9 +823,9 @@
(Store _ (ArrayMake0) mem) -> mem (Store _ (ArrayMake0) mem) -> mem
(Store dst (ArrayMake1 e) mem) -> (Store {e.Type} dst e mem) (Store dst (ArrayMake1 e) mem) -> (Store {e.Type} dst e mem)
// Putting [1]{*byte} and similar into direct interfaces. // Putting [1]*byte and similar into direct interfaces.
(IMake typ (ArrayMake1 val)) -> (IMake typ val) (IMake typ (ArrayMake1 val)) -> (IMake typ val)
(ArraySelect [0] x:(IData _)) -> x (ArraySelect [0] (IData x)) -> (IData x)
// string ops // string ops
// Decomposing StringMake and lowering of StringPtr and StringLen // Decomposing StringMake and lowering of StringPtr and StringLen

View File

@ -316,8 +316,7 @@ var genericOps = []opData{
// See section 7.2 in ieee754. // See section 7.2 in ieee754.
{name: "Fma", argLength: 3}, // compute (a*b)+c without intermediate rounding {name: "Fma", argLength: 3}, // compute (a*b)+c without intermediate rounding
// Data movement, max argument length for Phi is indefinite so just pick // Data movement. Max argument length for Phi is indefinite.
// a really large number
{name: "Phi", argLength: -1, zeroWidth: true}, // select an argument based on which predecessor block we came from {name: "Phi", argLength: -1, zeroWidth: true}, // select an argument based on which predecessor block we came from
{name: "Copy", argLength: 1}, // output = arg0 {name: "Copy", argLength: 1}, // output = arg0
// Convert converts between pointers and integers. // Convert converts between pointers and integers.
@ -546,6 +545,7 @@ var genericOps = []opData{
{name: "AtomicLoad64", argLength: 2, typ: "(UInt64,Mem)"}, // Load from arg0. arg1=memory. Returns loaded value and new memory. {name: "AtomicLoad64", argLength: 2, typ: "(UInt64,Mem)"}, // Load from arg0. arg1=memory. Returns loaded value and new memory.
{name: "AtomicLoadPtr", argLength: 2, typ: "(BytePtr,Mem)"}, // Load from arg0. arg1=memory. Returns loaded value and new memory. {name: "AtomicLoadPtr", argLength: 2, typ: "(BytePtr,Mem)"}, // Load from arg0. arg1=memory. Returns loaded value and new memory.
{name: "AtomicLoadAcq32", argLength: 2, typ: "(UInt32,Mem)"}, // Load from arg0. arg1=memory. Lock acquisition, returns loaded value and new memory. {name: "AtomicLoadAcq32", argLength: 2, typ: "(UInt32,Mem)"}, // Load from arg0. arg1=memory. Lock acquisition, returns loaded value and new memory.
{name: "AtomicStore8", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns memory.
{name: "AtomicStore32", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns memory. {name: "AtomicStore32", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns memory.
{name: "AtomicStore64", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns memory. {name: "AtomicStore64", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns memory.
{name: "AtomicStorePtrNoWB", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns memory. {name: "AtomicStorePtrNoWB", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns memory.

View File

@ -877,6 +877,7 @@ const (
OpAMD64MOVBatomicload OpAMD64MOVBatomicload
OpAMD64MOVLatomicload OpAMD64MOVLatomicload
OpAMD64MOVQatomicload OpAMD64MOVQatomicload
OpAMD64XCHGB
OpAMD64XCHGL OpAMD64XCHGL
OpAMD64XCHGQ OpAMD64XCHGQ
OpAMD64XADDLlock OpAMD64XADDLlock
@ -1434,6 +1435,7 @@ const (
OpARM64LDAR OpARM64LDAR
OpARM64LDARB OpARM64LDARB
OpARM64LDARW OpARM64LDARW
OpARM64STLRB
OpARM64STLR OpARM64STLR
OpARM64STLRW OpARM64STLRW
OpARM64LoweredAtomicExchange64 OpARM64LoweredAtomicExchange64
@ -1535,8 +1537,10 @@ const (
OpMIPSCALLstatic OpMIPSCALLstatic
OpMIPSCALLclosure OpMIPSCALLclosure
OpMIPSCALLinter OpMIPSCALLinter
OpMIPSLoweredAtomicLoad OpMIPSLoweredAtomicLoad8
OpMIPSLoweredAtomicStore OpMIPSLoweredAtomicLoad32
OpMIPSLoweredAtomicStore8
OpMIPSLoweredAtomicStore32
OpMIPSLoweredAtomicStorezero OpMIPSLoweredAtomicStorezero
OpMIPSLoweredAtomicExchange OpMIPSLoweredAtomicExchange
OpMIPSLoweredAtomicAdd OpMIPSLoweredAtomicAdd
@ -1655,6 +1659,7 @@ const (
OpMIPS64LoweredAtomicLoad8 OpMIPS64LoweredAtomicLoad8
OpMIPS64LoweredAtomicLoad32 OpMIPS64LoweredAtomicLoad32
OpMIPS64LoweredAtomicLoad64 OpMIPS64LoweredAtomicLoad64
OpMIPS64LoweredAtomicStore8
OpMIPS64LoweredAtomicStore32 OpMIPS64LoweredAtomicStore32
OpMIPS64LoweredAtomicStore64 OpMIPS64LoweredAtomicStore64
OpMIPS64LoweredAtomicStorezero32 OpMIPS64LoweredAtomicStorezero32
@ -1848,6 +1853,7 @@ const (
OpPPC64CALLinter OpPPC64CALLinter
OpPPC64LoweredZero OpPPC64LoweredZero
OpPPC64LoweredMove OpPPC64LoweredMove
OpPPC64LoweredAtomicStore8
OpPPC64LoweredAtomicStore32 OpPPC64LoweredAtomicStore32
OpPPC64LoweredAtomicStore64 OpPPC64LoweredAtomicStore64
OpPPC64LoweredAtomicLoad8 OpPPC64LoweredAtomicLoad8
@ -2068,6 +2074,7 @@ const (
OpS390XMOVBZatomicload OpS390XMOVBZatomicload
OpS390XMOVWZatomicload OpS390XMOVWZatomicload
OpS390XMOVDatomicload OpS390XMOVDatomicload
OpS390XMOVBatomicstore
OpS390XMOVWatomicstore OpS390XMOVWatomicstore
OpS390XMOVDatomicstore OpS390XMOVDatomicstore
OpS390XLAA OpS390XLAA
@ -2553,6 +2560,7 @@ const (
OpAtomicLoad64 OpAtomicLoad64
OpAtomicLoadPtr OpAtomicLoadPtr
OpAtomicLoadAcq32 OpAtomicLoadAcq32
OpAtomicStore8
OpAtomicStore32 OpAtomicStore32
OpAtomicStore64 OpAtomicStore64
OpAtomicStorePtrNoWB OpAtomicStorePtrNoWB
@ -11406,6 +11414,25 @@ var opcodeTable = [...]opInfo{
}, },
}, },
}, },
{
name: "XCHGB",
auxType: auxSymOff,
argLen: 3,
resultInArg0: true,
faultOnNilArg1: true,
hasSideEffects: true,
symEffect: SymRdWr,
asm: x86.AXCHGB,
reg: regInfo{
inputs: []inputInfo{
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
{1, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
},
outputs: []outputInfo{
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
},
},
},
{ {
name: "XCHGL", name: "XCHGL",
auxType: auxSymOff, auxType: auxSymOff,
@ -18876,6 +18903,19 @@ var opcodeTable = [...]opInfo{
}, },
}, },
}, },
{
name: "STLRB",
argLen: 3,
faultOnNilArg0: true,
hasSideEffects: true,
asm: arm64.ASTLRB,
reg: regInfo{
inputs: []inputInfo{
{1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
{0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB
},
},
},
{ {
name: "STLR", name: "STLR",
argLen: 3, argLen: 3,
@ -20278,7 +20318,7 @@ var opcodeTable = [...]opInfo{
}, },
}, },
{ {
name: "LoweredAtomicLoad", name: "LoweredAtomicLoad8",
argLen: 2, argLen: 2,
faultOnNilArg0: true, faultOnNilArg0: true,
reg: regInfo{ reg: regInfo{
@ -20291,7 +20331,32 @@ var opcodeTable = [...]opInfo{
}, },
}, },
{ {
name: "LoweredAtomicStore", name: "LoweredAtomicLoad32",
argLen: 2,
faultOnNilArg0: true,
reg: regInfo{
inputs: []inputInfo{
{0, 140738025226238}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP g R31 SB
},
outputs: []outputInfo{
{0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
},
},
},
{
name: "LoweredAtomicStore8",
argLen: 3,
faultOnNilArg0: true,
hasSideEffects: true,
reg: regInfo{
inputs: []inputInfo{
{1, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
{0, 140738025226238}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP g R31 SB
},
},
},
{
name: "LoweredAtomicStore32",
argLen: 3, argLen: 3,
faultOnNilArg0: true, faultOnNilArg0: true,
hasSideEffects: true, hasSideEffects: true,
@ -21882,6 +21947,18 @@ var opcodeTable = [...]opInfo{
}, },
}, },
}, },
{
name: "LoweredAtomicStore8",
argLen: 3,
faultOnNilArg0: true,
hasSideEffects: true,
reg: regInfo{
inputs: []inputInfo{
{1, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
{0, 4611686018695823358}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 SP g R31 SB
},
},
},
{ {
name: "LoweredAtomicStore32", name: "LoweredAtomicStore32",
argLen: 3, argLen: 3,
@ -24489,6 +24566,19 @@ var opcodeTable = [...]opInfo{
clobbers: 16408, // R3 R4 R14 clobbers: 16408, // R3 R4 R14
}, },
}, },
{
name: "LoweredAtomicStore8",
auxType: auxInt64,
argLen: 3,
faultOnNilArg0: true,
hasSideEffects: true,
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
},
},
},
{ {
name: "LoweredAtomicStore32", name: "LoweredAtomicStore32",
auxType: auxInt64, auxType: auxInt64,
@ -27632,6 +27722,22 @@ var opcodeTable = [...]opInfo{
}, },
}, },
}, },
{
name: "MOVBatomicstore",
auxType: auxSymOff,
argLen: 3,
clobberFlags: true,
faultOnNilArg0: true,
hasSideEffects: true,
symEffect: SymWrite,
asm: s390x.AMOVB,
reg: regInfo{
inputs: []inputInfo{
{0, 4295023614}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP SB
{1, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
},
},
},
{ {
name: "MOVWatomicstore", name: "MOVWatomicstore",
auxType: auxSymOff, auxType: auxSymOff,
@ -31347,6 +31453,12 @@ var opcodeTable = [...]opInfo{
argLen: 2, argLen: 2,
generic: true, generic: true,
}, },
{
name: "AtomicStore8",
argLen: 3,
hasSideEffects: true,
generic: true,
},
{ {
name: "AtomicStore32", name: "AtomicStore32",
argLen: 3, argLen: 3,

View File

@ -407,56 +407,82 @@ func (po *poset) newconst(n *Value) {
po.upushconst(i, 0) po.upushconst(i, 0)
} }
// aliasnode records that n2 is an alias of n1 // aliasnewnode records that a single node n2 (not in the poset yet) is an alias
func (po *poset) aliasnode(n1, n2 *Value) { // of the master node n1.
func (po *poset) aliasnewnode(n1, n2 *Value) {
i1, i2 := po.values[n1.ID], po.values[n2.ID]
if i1 == 0 || i2 != 0 {
panic("aliasnewnode invalid arguments")
}
po.values[n2.ID] = i1
po.upushalias(n2.ID, 0)
}
// aliasnodes records that all the nodes i2s are aliases of a single master node n1.
// aliasnodes takes care of rearranging the DAG, changing references of parent/children
// of nodes in i2s, so that they point to n1 instead.
// Complexity is O(n) (with n being the total number of nodes in the poset, not just
// the number of nodes being aliased).
func (po *poset) aliasnodes(n1 *Value, i2s bitset) {
i1 := po.values[n1.ID] i1 := po.values[n1.ID]
if i1 == 0 { if i1 == 0 {
panic("aliasnode for non-existing node") panic("aliasnode for non-existing node")
} }
if i2s.Test(i1) {
panic("aliasnode i2s contains n1 node")
}
i2 := po.values[n2.ID] // Go through all the nodes to adjust parent/chidlren of nodes in i2s
if i2 != 0 { for idx, n := range po.nodes {
// Rename all references to i2 into i1 // Do not touch i1 itself, otherwise we can create useless self-loops
// (do not touch i1 itself, otherwise we can create useless self-loops) if uint32(idx) == i1 {
for idx, n := range po.nodes { continue
if uint32(idx) != i1 { }
l, r := n.l, n.r l, r := n.l, n.r
if l.Target() == i2 {
po.setchl(uint32(idx), newedge(i1, l.Strict())) // Rename all references to i2s into i1
po.upush(undoSetChl, uint32(idx), l) if i2s.Test(l.Target()) {
} po.setchl(uint32(idx), newedge(i1, l.Strict()))
if r.Target() == i2 { po.upush(undoSetChl, uint32(idx), l)
po.setchr(uint32(idx), newedge(i1, r.Strict())) }
po.upush(undoSetChr, uint32(idx), r) if i2s.Test(r.Target()) {
} po.setchr(uint32(idx), newedge(i1, r.Strict()))
} po.upush(undoSetChr, uint32(idx), r)
} }
// Reassign all existing IDs that point to i2 to i1. // Connect all chidren of i2s to i1 (unless those children
// This includes n2.ID. // are in i2s as well, in which case it would be useless)
for k, v := range po.values { if i2s.Test(uint32(idx)) {
if v == i2 { if l != 0 && !i2s.Test(l.Target()) {
po.values[k] = i1 po.addchild(i1, l.Target(), l.Strict())
po.upushalias(k, i2)
} }
if r != 0 && !i2s.Test(r.Target()) {
po.addchild(i1, r.Target(), r.Strict())
}
po.setchl(uint32(idx), 0)
po.setchr(uint32(idx), 0)
po.upush(undoSetChl, uint32(idx), l)
po.upush(undoSetChr, uint32(idx), r)
} }
}
if n2.isGenericIntConst() { // Reassign all existing IDs that point to i2 to i1.
val := n2.AuxInt // This includes n2.ID.
if po.flags&posetFlagUnsigned != 0 { for k, v := range po.values {
val = int64(n2.AuxUnsigned()) if i2s.Test(v) {
} po.values[k] = i1
if po.constants[val] != i2 { po.upushalias(k, v)
panic("aliasing constant which is not registered") }
} }
// If one of the aliased nodes is a constant, then make sure
// po.constants is updated to point to the master node.
for val, idx := range po.constants {
if i2s.Test(idx) {
po.constants[val] = i1 po.constants[val] = i1
po.upushconst(i1, i2) po.upushconst(i1, idx)
} }
} else {
// n2.ID wasn't seen before, so record it as alias to i1
po.values[n2.ID] = i1
po.upushalias(n2.ID, 0)
} }
} }
@ -603,25 +629,56 @@ func (po *poset) mergeroot(r1, r2 uint32) uint32 {
return r return r
} }
// collapsepath marks i1 and i2 as equal and collapses as equal all // collapsepath marks n1 and n2 as equal and collapses as equal all
// nodes across all paths between i1 and i2. If a strict edge is // nodes across all paths between n1 and n2. If a strict edge is
// found, the function does not modify the DAG and returns false. // found, the function does not modify the DAG and returns false.
// Complexity is O(n).
func (po *poset) collapsepath(n1, n2 *Value) bool { func (po *poset) collapsepath(n1, n2 *Value) bool {
i1, i2 := po.values[n1.ID], po.values[n2.ID] i1, i2 := po.values[n1.ID], po.values[n2.ID]
if po.reaches(i1, i2, true) { if po.reaches(i1, i2, true) {
return false return false
} }
// TODO: for now, only handle the simple case of i2 being child of i1 // Find all the paths from i1 to i2
l, r := po.children(i1) paths := po.findpaths(i1, i2)
if l.Target() == i2 || r.Target() == i2 { // Mark all nodes in all the paths as aliases of n1
po.aliasnode(n1, n2) // (excluding n1 itself)
po.addchild(i1, i2, false) paths.Clear(i1)
return true po.aliasnodes(n1, paths)
}
return true return true
} }
// findpaths is a recursive function that calculates all paths from cur to dst
// and return them as a bitset (the index of a node is set in the bitset if
// that node is on at least one path from cur to dst).
// We do a DFS from cur (stopping going deep any time we reach dst, if ever),
// and mark as part of the paths any node that has a children which is already
// part of the path (or is dst itself).
func (po *poset) findpaths(cur, dst uint32) bitset {
seen := newBitset(int(po.lastidx + 1))
path := newBitset(int(po.lastidx + 1))
path.Set(dst)
po.findpaths1(cur, dst, seen, path)
return path
}
func (po *poset) findpaths1(cur, dst uint32, seen bitset, path bitset) {
if cur == dst {
return
}
seen.Set(cur)
l, r := po.chl(cur), po.chr(cur)
if !seen.Test(l) {
po.findpaths1(l, dst, seen, path)
}
if !seen.Test(r) {
po.findpaths1(r, dst, seen, path)
}
if path.Test(l) || path.Test(r) {
path.Set(cur)
}
}
// Check whether it is recorded that i1!=i2 // Check whether it is recorded that i1!=i2
func (po *poset) isnoneq(i1, i2 uint32) bool { func (po *poset) isnoneq(i1, i2 uint32) bool {
if i1 == i2 { if i1 == i2 {
@ -1093,11 +1150,11 @@ func (po *poset) SetEqual(n1, n2 *Value) bool {
i1 = po.newnode(n1) i1 = po.newnode(n1)
po.roots = append(po.roots, i1) po.roots = append(po.roots, i1)
po.upush(undoNewRoot, i1, 0) po.upush(undoNewRoot, i1, 0)
po.aliasnode(n1, n2) po.aliasnewnode(n1, n2)
case f1 && !f2: case f1 && !f2:
po.aliasnode(n1, n2) po.aliasnewnode(n1, n2)
case !f1 && f2: case !f1 && f2:
po.aliasnode(n2, n1) po.aliasnewnode(n2, n1)
case f1 && f2: case f1 && f2:
if i1 == i2 { if i1 == i2 {
// Already aliased, ignore // Already aliased, ignore
@ -1127,11 +1184,9 @@ func (po *poset) SetEqual(n1, n2 *Value) bool {
// Set n2 as alias of n1. This will also update all the references // Set n2 as alias of n1. This will also update all the references
// to n2 to become references to n1 // to n2 to become references to n1
po.aliasnode(n1, n2) i2s := newBitset(int(po.lastidx) + 1)
i2s.Set(i2)
// Connect i2 (now dummy) as child of i1. This allows to keep the correct po.aliasnodes(n1, i2s)
// order with its children.
po.addchild(i1, i2, false)
} }
return true return true
} }

View File

@ -438,7 +438,127 @@ func TestPosetStrict(t *testing.T) {
}) })
} }
func TestSetEqual(t *testing.T) { func TestPosetCollapse(t *testing.T) {
testPosetOps(t, false, []posetTestOp{
{Checkpoint, 0, 0},
// Create a complex graph of <= relations among nodes between 10 and 25.
{SetOrderOrEqual, 10, 15},
{SetOrderOrEqual, 15, 20},
{SetOrderOrEqual, 20, vconst(20)},
{SetOrderOrEqual, vconst(20), 25},
{SetOrderOrEqual, 10, 12},
{SetOrderOrEqual, 12, 16},
{SetOrderOrEqual, 16, vconst(20)},
{SetOrderOrEqual, 10, 17},
{SetOrderOrEqual, 17, 25},
{SetOrderOrEqual, 15, 18},
{SetOrderOrEqual, 18, vconst(20)},
{SetOrderOrEqual, 15, 19},
{SetOrderOrEqual, 19, 25},
// These are other paths not part of the main collapsing path
{SetOrderOrEqual, 10, 11},
{SetOrderOrEqual, 11, 26},
{SetOrderOrEqual, 13, 25},
{SetOrderOrEqual, 100, 25},
{SetOrderOrEqual, 101, 15},
{SetOrderOrEqual, 102, 10},
{SetOrderOrEqual, 25, 103},
{SetOrderOrEqual, 20, 104},
{Checkpoint, 0, 0},
// Collapse everything by setting 10 >= 25: this should make everything equal
{SetOrderOrEqual, 25, 10},
// Check that all nodes are pairwise equal now
{Equal, 10, 12},
{Equal, 10, 15},
{Equal, 10, 16},
{Equal, 10, 17},
{Equal, 10, 18},
{Equal, 10, 19},
{Equal, 10, vconst(20)},
{Equal, 10, vconst2(20)},
{Equal, 10, 25},
{Equal, 12, 15},
{Equal, 12, 16},
{Equal, 12, 17},
{Equal, 12, 18},
{Equal, 12, 19},
{Equal, 12, vconst(20)},
{Equal, 12, vconst2(20)},
{Equal, 12, 25},
{Equal, 15, 16},
{Equal, 15, 17},
{Equal, 15, 18},
{Equal, 15, 19},
{Equal, 15, vconst(20)},
{Equal, 15, vconst2(20)},
{Equal, 15, 25},
{Equal, 16, 17},
{Equal, 16, 18},
{Equal, 16, 19},
{Equal, 16, vconst(20)},
{Equal, 16, vconst2(20)},
{Equal, 16, 25},
{Equal, 17, 18},
{Equal, 17, 19},
{Equal, 17, vconst(20)},
{Equal, 17, vconst2(20)},
{Equal, 17, 25},
{Equal, 18, 19},
{Equal, 18, vconst(20)},
{Equal, 18, vconst2(20)},
{Equal, 18, 25},
{Equal, 19, vconst(20)},
{Equal, 19, vconst2(20)},
{Equal, 19, 25},
{Equal, vconst(20), vconst2(20)},
{Equal, vconst(20), 25},
{Equal, vconst2(20), 25},
// ... but not 11/26/100/101/102, which were on a different path
{Equal_Fail, 10, 11},
{Equal_Fail, 10, 26},
{Equal_Fail, 10, 100},
{Equal_Fail, 10, 101},
{Equal_Fail, 10, 102},
{OrderedOrEqual, 10, 26},
{OrderedOrEqual, 25, 26},
{OrderedOrEqual, 13, 25},
{OrderedOrEqual, 13, 10},
{Undo, 0, 0},
{OrderedOrEqual, 10, 25},
{Equal_Fail, 10, 12},
{Equal_Fail, 10, 15},
{Equal_Fail, 10, 25},
{Undo, 0, 0},
})
testPosetOps(t, false, []posetTestOp{
{Checkpoint, 0, 0},
{SetOrderOrEqual, 10, 15},
{SetOrderOrEqual, 15, 20},
{SetOrderOrEqual, 20, 25},
{SetOrder, 10, 16},
{SetOrderOrEqual, 16, 20},
// Check that we cannot collapse here because of the strict relation 10<16
{SetOrderOrEqual_Fail, 20, 10},
{Undo, 0, 0},
})
}
func TestPosetSetEqual(t *testing.T) {
testPosetOps(t, false, []posetTestOp{ testPosetOps(t, false, []posetTestOp{
// 10<=20<=30<40, 20<=100<110 // 10<=20<=30<40, 20<=100<110
{Checkpoint, 0, 0}, {Checkpoint, 0, 0},

View File

@ -646,6 +646,8 @@ func rewriteValueAMD64(v *Value) bool {
return rewriteValueAMD64_OpAtomicStore32_0(v) return rewriteValueAMD64_OpAtomicStore32_0(v)
case OpAtomicStore64: case OpAtomicStore64:
return rewriteValueAMD64_OpAtomicStore64_0(v) return rewriteValueAMD64_OpAtomicStore64_0(v)
case OpAtomicStore8:
return rewriteValueAMD64_OpAtomicStore8_0(v)
case OpAtomicStorePtrNoWB: case OpAtomicStorePtrNoWB:
return rewriteValueAMD64_OpAtomicStorePtrNoWB_0(v) return rewriteValueAMD64_OpAtomicStorePtrNoWB_0(v)
case OpAvg64u: case OpAvg64u:
@ -50035,70 +50037,28 @@ func rewriteValueAMD64_OpAdd8_0(v *Value) bool {
} }
} }
func rewriteValueAMD64_OpAddPtr_0(v *Value) bool { func rewriteValueAMD64_OpAddPtr_0(v *Value) bool {
b := v.Block
config := b.Func.Config
// match: (AddPtr x y) // match: (AddPtr x y)
// cond: config.PtrSize == 8
// result: (ADDQ x y) // result: (ADDQ x y)
for { for {
y := v.Args[1] y := v.Args[1]
x := v.Args[0] x := v.Args[0]
if !(config.PtrSize == 8) {
break
}
v.reset(OpAMD64ADDQ) v.reset(OpAMD64ADDQ)
v.AddArg(x) v.AddArg(x)
v.AddArg(y) v.AddArg(y)
return true return true
} }
// match: (AddPtr x y)
// cond: config.PtrSize == 4
// result: (ADDL x y)
for {
y := v.Args[1]
x := v.Args[0]
if !(config.PtrSize == 4) {
break
}
v.reset(OpAMD64ADDL)
v.AddArg(x)
v.AddArg(y)
return true
}
return false
} }
func rewriteValueAMD64_OpAddr_0(v *Value) bool { func rewriteValueAMD64_OpAddr_0(v *Value) bool {
b := v.Block
config := b.Func.Config
// match: (Addr {sym} base) // match: (Addr {sym} base)
// cond: config.PtrSize == 8
// result: (LEAQ {sym} base) // result: (LEAQ {sym} base)
for { for {
sym := v.Aux sym := v.Aux
base := v.Args[0] base := v.Args[0]
if !(config.PtrSize == 8) {
break
}
v.reset(OpAMD64LEAQ) v.reset(OpAMD64LEAQ)
v.Aux = sym v.Aux = sym
v.AddArg(base) v.AddArg(base)
return true return true
} }
// match: (Addr {sym} base)
// cond: config.PtrSize == 4
// result: (LEAL {sym} base)
for {
sym := v.Aux
base := v.Args[0]
if !(config.PtrSize == 4) {
break
}
v.reset(OpAMD64LEAL)
v.Aux = sym
v.AddArg(base)
return true
}
return false
} }
func rewriteValueAMD64_OpAnd16_0(v *Value) bool { func rewriteValueAMD64_OpAnd16_0(v *Value) bool {
// match: (And16 x y) // match: (And16 x y)
@ -50309,37 +50269,16 @@ func rewriteValueAMD64_OpAtomicLoad8_0(v *Value) bool {
} }
} }
func rewriteValueAMD64_OpAtomicLoadPtr_0(v *Value) bool { func rewriteValueAMD64_OpAtomicLoadPtr_0(v *Value) bool {
b := v.Block
config := b.Func.Config
// match: (AtomicLoadPtr ptr mem) // match: (AtomicLoadPtr ptr mem)
// cond: config.PtrSize == 8
// result: (MOVQatomicload ptr mem) // result: (MOVQatomicload ptr mem)
for { for {
mem := v.Args[1] mem := v.Args[1]
ptr := v.Args[0] ptr := v.Args[0]
if !(config.PtrSize == 8) {
break
}
v.reset(OpAMD64MOVQatomicload) v.reset(OpAMD64MOVQatomicload)
v.AddArg(ptr) v.AddArg(ptr)
v.AddArg(mem) v.AddArg(mem)
return true return true
} }
// match: (AtomicLoadPtr ptr mem)
// cond: config.PtrSize == 4
// result: (MOVLatomicload ptr mem)
for {
mem := v.Args[1]
ptr := v.Args[0]
if !(config.PtrSize == 4) {
break
}
v.reset(OpAMD64MOVLatomicload)
v.AddArg(ptr)
v.AddArg(mem)
return true
}
return false
} }
func rewriteValueAMD64_OpAtomicOr8_0(v *Value) bool { func rewriteValueAMD64_OpAtomicOr8_0(v *Value) bool {
// match: (AtomicOr8 ptr val mem) // match: (AtomicOr8 ptr val mem)
@ -50391,20 +50330,33 @@ func rewriteValueAMD64_OpAtomicStore64_0(v *Value) bool {
return true return true
} }
} }
func rewriteValueAMD64_OpAtomicStore8_0(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (AtomicStore8 ptr val mem)
// result: (Select1 (XCHGB <types.NewTuple(typ.UInt8,types.TypeMem)> val ptr mem))
for {
mem := v.Args[2]
ptr := v.Args[0]
val := v.Args[1]
v.reset(OpSelect1)
v0 := b.NewValue0(v.Pos, OpAMD64XCHGB, types.NewTuple(typ.UInt8, types.TypeMem))
v0.AddArg(val)
v0.AddArg(ptr)
v0.AddArg(mem)
v.AddArg(v0)
return true
}
}
func rewriteValueAMD64_OpAtomicStorePtrNoWB_0(v *Value) bool { func rewriteValueAMD64_OpAtomicStorePtrNoWB_0(v *Value) bool {
b := v.Block b := v.Block
config := b.Func.Config
typ := &b.Func.Config.Types typ := &b.Func.Config.Types
// match: (AtomicStorePtrNoWB ptr val mem) // match: (AtomicStorePtrNoWB ptr val mem)
// cond: config.PtrSize == 8
// result: (Select1 (XCHGQ <types.NewTuple(typ.BytePtr,types.TypeMem)> val ptr mem)) // result: (Select1 (XCHGQ <types.NewTuple(typ.BytePtr,types.TypeMem)> val ptr mem))
for { for {
mem := v.Args[2] mem := v.Args[2]
ptr := v.Args[0] ptr := v.Args[0]
val := v.Args[1] val := v.Args[1]
if !(config.PtrSize == 8) {
break
}
v.reset(OpSelect1) v.reset(OpSelect1)
v0 := b.NewValue0(v.Pos, OpAMD64XCHGQ, types.NewTuple(typ.BytePtr, types.TypeMem)) v0 := b.NewValue0(v.Pos, OpAMD64XCHGQ, types.NewTuple(typ.BytePtr, types.TypeMem))
v0.AddArg(val) v0.AddArg(val)
@ -50413,25 +50365,6 @@ func rewriteValueAMD64_OpAtomicStorePtrNoWB_0(v *Value) bool {
v.AddArg(v0) v.AddArg(v0)
return true return true
} }
// match: (AtomicStorePtrNoWB ptr val mem)
// cond: config.PtrSize == 4
// result: (Select1 (XCHGL <types.NewTuple(typ.BytePtr,types.TypeMem)> val ptr mem))
for {
mem := v.Args[2]
ptr := v.Args[0]
val := v.Args[1]
if !(config.PtrSize == 4) {
break
}
v.reset(OpSelect1)
v0 := b.NewValue0(v.Pos, OpAMD64XCHGL, types.NewTuple(typ.BytePtr, types.TypeMem))
v0.AddArg(val)
v0.AddArg(ptr)
v0.AddArg(mem)
v.AddArg(v0)
return true
}
return false
} }
func rewriteValueAMD64_OpAvg64u_0(v *Value) bool { func rewriteValueAMD64_OpAvg64u_0(v *Value) bool {
// match: (Avg64u x y) // match: (Avg64u x y)
@ -51754,31 +51687,13 @@ func rewriteValueAMD64_OpConstBool_0(v *Value) bool {
} }
} }
func rewriteValueAMD64_OpConstNil_0(v *Value) bool { func rewriteValueAMD64_OpConstNil_0(v *Value) bool {
b := v.Block
config := b.Func.Config
// match: (ConstNil) // match: (ConstNil)
// cond: config.PtrSize == 8
// result: (MOVQconst [0]) // result: (MOVQconst [0])
for { for {
if !(config.PtrSize == 8) {
break
}
v.reset(OpAMD64MOVQconst) v.reset(OpAMD64MOVQconst)
v.AuxInt = 0 v.AuxInt = 0
return true return true
} }
// match: (ConstNil)
// cond: config.PtrSize == 4
// result: (MOVLconst [0])
for {
if !(config.PtrSize == 4) {
break
}
v.reset(OpAMD64MOVLconst)
v.AuxInt = 0
return true
}
return false
} }
func rewriteValueAMD64_OpCtz16_0(v *Value) bool { func rewriteValueAMD64_OpCtz16_0(v *Value) bool {
b := v.Block b := v.Block
@ -52283,16 +52198,11 @@ func rewriteValueAMD64_OpEqB_0(v *Value) bool {
} }
func rewriteValueAMD64_OpEqPtr_0(v *Value) bool { func rewriteValueAMD64_OpEqPtr_0(v *Value) bool {
b := v.Block b := v.Block
config := b.Func.Config
// match: (EqPtr x y) // match: (EqPtr x y)
// cond: config.PtrSize == 8
// result: (SETEQ (CMPQ x y)) // result: (SETEQ (CMPQ x y))
for { for {
y := v.Args[1] y := v.Args[1]
x := v.Args[0] x := v.Args[0]
if !(config.PtrSize == 8) {
break
}
v.reset(OpAMD64SETEQ) v.reset(OpAMD64SETEQ)
v0 := b.NewValue0(v.Pos, OpAMD64CMPQ, types.TypeFlags) v0 := b.NewValue0(v.Pos, OpAMD64CMPQ, types.TypeFlags)
v0.AddArg(x) v0.AddArg(x)
@ -52300,23 +52210,6 @@ func rewriteValueAMD64_OpEqPtr_0(v *Value) bool {
v.AddArg(v0) v.AddArg(v0)
return true return true
} }
// match: (EqPtr x y)
// cond: config.PtrSize == 4
// result: (SETEQ (CMPL x y))
for {
y := v.Args[1]
x := v.Args[0]
if !(config.PtrSize == 4) {
break
}
v.reset(OpAMD64SETEQ)
v0 := b.NewValue0(v.Pos, OpAMD64CMPL, types.TypeFlags)
v0.AddArg(x)
v0.AddArg(y)
v.AddArg(v0)
return true
}
return false
} }
func rewriteValueAMD64_OpFloor_0(v *Value) bool { func rewriteValueAMD64_OpFloor_0(v *Value) bool {
// match: (Floor x) // match: (Floor x)
@ -52741,16 +52634,11 @@ func rewriteValueAMD64_OpInterCall_0(v *Value) bool {
} }
func rewriteValueAMD64_OpIsInBounds_0(v *Value) bool { func rewriteValueAMD64_OpIsInBounds_0(v *Value) bool {
b := v.Block b := v.Block
config := b.Func.Config
// match: (IsInBounds idx len) // match: (IsInBounds idx len)
// cond: config.PtrSize == 8
// result: (SETB (CMPQ idx len)) // result: (SETB (CMPQ idx len))
for { for {
len := v.Args[1] len := v.Args[1]
idx := v.Args[0] idx := v.Args[0]
if !(config.PtrSize == 8) {
break
}
v.reset(OpAMD64SETB) v.reset(OpAMD64SETB)
v0 := b.NewValue0(v.Pos, OpAMD64CMPQ, types.TypeFlags) v0 := b.NewValue0(v.Pos, OpAMD64CMPQ, types.TypeFlags)
v0.AddArg(idx) v0.AddArg(idx)
@ -52758,35 +52646,13 @@ func rewriteValueAMD64_OpIsInBounds_0(v *Value) bool {
v.AddArg(v0) v.AddArg(v0)
return true return true
} }
// match: (IsInBounds idx len)
// cond: config.PtrSize == 4
// result: (SETB (CMPL idx len))
for {
len := v.Args[1]
idx := v.Args[0]
if !(config.PtrSize == 4) {
break
}
v.reset(OpAMD64SETB)
v0 := b.NewValue0(v.Pos, OpAMD64CMPL, types.TypeFlags)
v0.AddArg(idx)
v0.AddArg(len)
v.AddArg(v0)
return true
}
return false
} }
func rewriteValueAMD64_OpIsNonNil_0(v *Value) bool { func rewriteValueAMD64_OpIsNonNil_0(v *Value) bool {
b := v.Block b := v.Block
config := b.Func.Config
// match: (IsNonNil p) // match: (IsNonNil p)
// cond: config.PtrSize == 8
// result: (SETNE (TESTQ p p)) // result: (SETNE (TESTQ p p))
for { for {
p := v.Args[0] p := v.Args[0]
if !(config.PtrSize == 8) {
break
}
v.reset(OpAMD64SETNE) v.reset(OpAMD64SETNE)
v0 := b.NewValue0(v.Pos, OpAMD64TESTQ, types.TypeFlags) v0 := b.NewValue0(v.Pos, OpAMD64TESTQ, types.TypeFlags)
v0.AddArg(p) v0.AddArg(p)
@ -52794,35 +52660,14 @@ func rewriteValueAMD64_OpIsNonNil_0(v *Value) bool {
v.AddArg(v0) v.AddArg(v0)
return true return true
} }
// match: (IsNonNil p)
// cond: config.PtrSize == 4
// result: (SETNE (TESTL p p))
for {
p := v.Args[0]
if !(config.PtrSize == 4) {
break
}
v.reset(OpAMD64SETNE)
v0 := b.NewValue0(v.Pos, OpAMD64TESTL, types.TypeFlags)
v0.AddArg(p)
v0.AddArg(p)
v.AddArg(v0)
return true
}
return false
} }
func rewriteValueAMD64_OpIsSliceInBounds_0(v *Value) bool { func rewriteValueAMD64_OpIsSliceInBounds_0(v *Value) bool {
b := v.Block b := v.Block
config := b.Func.Config
// match: (IsSliceInBounds idx len) // match: (IsSliceInBounds idx len)
// cond: config.PtrSize == 8
// result: (SETBE (CMPQ idx len)) // result: (SETBE (CMPQ idx len))
for { for {
len := v.Args[1] len := v.Args[1]
idx := v.Args[0] idx := v.Args[0]
if !(config.PtrSize == 8) {
break
}
v.reset(OpAMD64SETBE) v.reset(OpAMD64SETBE)
v0 := b.NewValue0(v.Pos, OpAMD64CMPQ, types.TypeFlags) v0 := b.NewValue0(v.Pos, OpAMD64CMPQ, types.TypeFlags)
v0.AddArg(idx) v0.AddArg(idx)
@ -52830,23 +52675,6 @@ func rewriteValueAMD64_OpIsSliceInBounds_0(v *Value) bool {
v.AddArg(v0) v.AddArg(v0)
return true return true
} }
// match: (IsSliceInBounds idx len)
// cond: config.PtrSize == 4
// result: (SETBE (CMPL idx len))
for {
len := v.Args[1]
idx := v.Args[0]
if !(config.PtrSize == 4) {
break
}
v.reset(OpAMD64SETBE)
v0 := b.NewValue0(v.Pos, OpAMD64CMPL, types.TypeFlags)
v0.AddArg(idx)
v0.AddArg(len)
v.AddArg(v0)
return true
}
return false
} }
func rewriteValueAMD64_OpLeq16_0(v *Value) bool { func rewriteValueAMD64_OpLeq16_0(v *Value) bool {
b := v.Block b := v.Block
@ -53149,16 +52977,14 @@ func rewriteValueAMD64_OpLess8U_0(v *Value) bool {
} }
} }
func rewriteValueAMD64_OpLoad_0(v *Value) bool { func rewriteValueAMD64_OpLoad_0(v *Value) bool {
b := v.Block
config := b.Func.Config
// match: (Load <t> ptr mem) // match: (Load <t> ptr mem)
// cond: (is64BitInt(t) || isPtr(t) && config.PtrSize == 8) // cond: (is64BitInt(t) || isPtr(t))
// result: (MOVQload ptr mem) // result: (MOVQload ptr mem)
for { for {
t := v.Type t := v.Type
mem := v.Args[1] mem := v.Args[1]
ptr := v.Args[0] ptr := v.Args[0]
if !(is64BitInt(t) || isPtr(t) && config.PtrSize == 8) { if !(is64BitInt(t) || isPtr(t)) {
break break
} }
v.reset(OpAMD64MOVQload) v.reset(OpAMD64MOVQload)
@ -53167,13 +52993,13 @@ func rewriteValueAMD64_OpLoad_0(v *Value) bool {
return true return true
} }
// match: (Load <t> ptr mem) // match: (Load <t> ptr mem)
// cond: (is32BitInt(t) || isPtr(t) && config.PtrSize == 4) // cond: is32BitInt(t)
// result: (MOVLload ptr mem) // result: (MOVLload ptr mem)
for { for {
t := v.Type t := v.Type
mem := v.Args[1] mem := v.Args[1]
ptr := v.Args[0] ptr := v.Args[0]
if !(is32BitInt(t) || isPtr(t) && config.PtrSize == 4) { if !(is32BitInt(t)) {
break break
} }
v.reset(OpAMD64MOVLload) v.reset(OpAMD64MOVLload)
@ -53244,39 +53070,17 @@ func rewriteValueAMD64_OpLoad_0(v *Value) bool {
return false return false
} }
func rewriteValueAMD64_OpLocalAddr_0(v *Value) bool { func rewriteValueAMD64_OpLocalAddr_0(v *Value) bool {
b := v.Block
config := b.Func.Config
// match: (LocalAddr {sym} base _) // match: (LocalAddr {sym} base _)
// cond: config.PtrSize == 8
// result: (LEAQ {sym} base) // result: (LEAQ {sym} base)
for { for {
sym := v.Aux sym := v.Aux
_ = v.Args[1] _ = v.Args[1]
base := v.Args[0] base := v.Args[0]
if !(config.PtrSize == 8) {
break
}
v.reset(OpAMD64LEAQ) v.reset(OpAMD64LEAQ)
v.Aux = sym v.Aux = sym
v.AddArg(base) v.AddArg(base)
return true return true
} }
// match: (LocalAddr {sym} base _)
// cond: config.PtrSize == 4
// result: (LEAL {sym} base)
for {
sym := v.Aux
_ = v.Args[1]
base := v.Args[0]
if !(config.PtrSize == 4) {
break
}
v.reset(OpAMD64LEAL)
v.Aux = sym
v.AddArg(base)
return true
}
return false
} }
func rewriteValueAMD64_OpLsh16x16_0(v *Value) bool { func rewriteValueAMD64_OpLsh16x16_0(v *Value) bool {
b := v.Block b := v.Block
@ -54939,16 +54743,11 @@ func rewriteValueAMD64_OpNeqB_0(v *Value) bool {
} }
func rewriteValueAMD64_OpNeqPtr_0(v *Value) bool { func rewriteValueAMD64_OpNeqPtr_0(v *Value) bool {
b := v.Block b := v.Block
config := b.Func.Config
// match: (NeqPtr x y) // match: (NeqPtr x y)
// cond: config.PtrSize == 8
// result: (SETNE (CMPQ x y)) // result: (SETNE (CMPQ x y))
for { for {
y := v.Args[1] y := v.Args[1]
x := v.Args[0] x := v.Args[0]
if !(config.PtrSize == 8) {
break
}
v.reset(OpAMD64SETNE) v.reset(OpAMD64SETNE)
v0 := b.NewValue0(v.Pos, OpAMD64CMPQ, types.TypeFlags) v0 := b.NewValue0(v.Pos, OpAMD64CMPQ, types.TypeFlags)
v0.AddArg(x) v0.AddArg(x)
@ -54956,23 +54755,6 @@ func rewriteValueAMD64_OpNeqPtr_0(v *Value) bool {
v.AddArg(v0) v.AddArg(v0)
return true return true
} }
// match: (NeqPtr x y)
// cond: config.PtrSize == 4
// result: (SETNE (CMPL x y))
for {
y := v.Args[1]
x := v.Args[0]
if !(config.PtrSize == 4) {
break
}
v.reset(OpAMD64SETNE)
v0 := b.NewValue0(v.Pos, OpAMD64CMPL, types.TypeFlags)
v0.AddArg(x)
v0.AddArg(y)
v.AddArg(v0)
return true
}
return false
} }
func rewriteValueAMD64_OpNilCheck_0(v *Value) bool { func rewriteValueAMD64_OpNilCheck_0(v *Value) bool {
// match: (NilCheck ptr mem) // match: (NilCheck ptr mem)
@ -54999,15 +54781,14 @@ func rewriteValueAMD64_OpNot_0(v *Value) bool {
} }
func rewriteValueAMD64_OpOffPtr_0(v *Value) bool { func rewriteValueAMD64_OpOffPtr_0(v *Value) bool {
b := v.Block b := v.Block
config := b.Func.Config
typ := &b.Func.Config.Types typ := &b.Func.Config.Types
// match: (OffPtr [off] ptr) // match: (OffPtr [off] ptr)
// cond: config.PtrSize == 8 && is32Bit(off) // cond: is32Bit(off)
// result: (ADDQconst [off] ptr) // result: (ADDQconst [off] ptr)
for { for {
off := v.AuxInt off := v.AuxInt
ptr := v.Args[0] ptr := v.Args[0]
if !(config.PtrSize == 8 && is32Bit(off)) { if !(is32Bit(off)) {
break break
} }
v.reset(OpAMD64ADDQconst) v.reset(OpAMD64ADDQconst)
@ -55016,14 +54797,10 @@ func rewriteValueAMD64_OpOffPtr_0(v *Value) bool {
return true return true
} }
// match: (OffPtr [off] ptr) // match: (OffPtr [off] ptr)
// cond: config.PtrSize == 8
// result: (ADDQ (MOVQconst [off]) ptr) // result: (ADDQ (MOVQconst [off]) ptr)
for { for {
off := v.AuxInt off := v.AuxInt
ptr := v.Args[0] ptr := v.Args[0]
if !(config.PtrSize == 8) {
break
}
v.reset(OpAMD64ADDQ) v.reset(OpAMD64ADDQ)
v0 := b.NewValue0(v.Pos, OpAMD64MOVQconst, typ.UInt64) v0 := b.NewValue0(v.Pos, OpAMD64MOVQconst, typ.UInt64)
v0.AuxInt = off v0.AuxInt = off
@ -55031,21 +54808,6 @@ func rewriteValueAMD64_OpOffPtr_0(v *Value) bool {
v.AddArg(ptr) v.AddArg(ptr)
return true return true
} }
// match: (OffPtr [off] ptr)
// cond: config.PtrSize == 4
// result: (ADDLconst [off] ptr)
for {
off := v.AuxInt
ptr := v.Args[0]
if !(config.PtrSize == 4) {
break
}
v.reset(OpAMD64ADDLconst)
v.AuxInt = off
v.AddArg(ptr)
return true
}
return false
} }
func rewriteValueAMD64_OpOr16_0(v *Value) bool { func rewriteValueAMD64_OpOr16_0(v *Value) bool {
// match: (Or16 x y) // match: (Or16 x y)
@ -57203,37 +56965,16 @@ func rewriteValueAMD64_OpSub8_0(v *Value) bool {
} }
} }
func rewriteValueAMD64_OpSubPtr_0(v *Value) bool { func rewriteValueAMD64_OpSubPtr_0(v *Value) bool {
b := v.Block
config := b.Func.Config
// match: (SubPtr x y) // match: (SubPtr x y)
// cond: config.PtrSize == 8
// result: (SUBQ x y) // result: (SUBQ x y)
for { for {
y := v.Args[1] y := v.Args[1]
x := v.Args[0] x := v.Args[0]
if !(config.PtrSize == 8) {
break
}
v.reset(OpAMD64SUBQ) v.reset(OpAMD64SUBQ)
v.AddArg(x) v.AddArg(x)
v.AddArg(y) v.AddArg(y)
return true return true
} }
// match: (SubPtr x y)
// cond: config.PtrSize == 4
// result: (SUBL x y)
for {
y := v.Args[1]
x := v.Args[0]
if !(config.PtrSize == 4) {
break
}
v.reset(OpAMD64SUBL)
v.AddArg(x)
v.AddArg(y)
return true
}
return false
} }
func rewriteValueAMD64_OpTrunc_0(v *Value) bool { func rewriteValueAMD64_OpTrunc_0(v *Value) bool {
// match: (Trunc x) // match: (Trunc x)

View File

@ -431,6 +431,8 @@ func rewriteValueARM64(v *Value) bool {
return rewriteValueARM64_OpAtomicStore32_0(v) return rewriteValueARM64_OpAtomicStore32_0(v)
case OpAtomicStore64: case OpAtomicStore64:
return rewriteValueARM64_OpAtomicStore64_0(v) return rewriteValueARM64_OpAtomicStore64_0(v)
case OpAtomicStore8:
return rewriteValueARM64_OpAtomicStore8_0(v)
case OpAtomicStorePtrNoWB: case OpAtomicStorePtrNoWB:
return rewriteValueARM64_OpAtomicStorePtrNoWB_0(v) return rewriteValueARM64_OpAtomicStorePtrNoWB_0(v)
case OpAvg64u: case OpAvg64u:
@ -27669,6 +27671,20 @@ func rewriteValueARM64_OpAtomicStore64_0(v *Value) bool {
return true return true
} }
} }
func rewriteValueARM64_OpAtomicStore8_0(v *Value) bool {
// match: (AtomicStore8 ptr val mem)
// result: (STLRB ptr val mem)
for {
mem := v.Args[2]
ptr := v.Args[0]
val := v.Args[1]
v.reset(OpARM64STLRB)
v.AddArg(ptr)
v.AddArg(val)
v.AddArg(mem)
return true
}
}
func rewriteValueARM64_OpAtomicStorePtrNoWB_0(v *Value) bool { func rewriteValueARM64_OpAtomicStorePtrNoWB_0(v *Value) bool {
// match: (AtomicStorePtrNoWB ptr val mem) // match: (AtomicStorePtrNoWB ptr val mem)
// result: (STLR ptr val mem) // result: (STLR ptr val mem)

View File

@ -41,12 +41,16 @@ func rewriteValueMIPS(v *Value) bool {
return rewriteValueMIPS_OpAtomicExchange32_0(v) return rewriteValueMIPS_OpAtomicExchange32_0(v)
case OpAtomicLoad32: case OpAtomicLoad32:
return rewriteValueMIPS_OpAtomicLoad32_0(v) return rewriteValueMIPS_OpAtomicLoad32_0(v)
case OpAtomicLoad8:
return rewriteValueMIPS_OpAtomicLoad8_0(v)
case OpAtomicLoadPtr: case OpAtomicLoadPtr:
return rewriteValueMIPS_OpAtomicLoadPtr_0(v) return rewriteValueMIPS_OpAtomicLoadPtr_0(v)
case OpAtomicOr8: case OpAtomicOr8:
return rewriteValueMIPS_OpAtomicOr8_0(v) return rewriteValueMIPS_OpAtomicOr8_0(v)
case OpAtomicStore32: case OpAtomicStore32:
return rewriteValueMIPS_OpAtomicStore32_0(v) return rewriteValueMIPS_OpAtomicStore32_0(v)
case OpAtomicStore8:
return rewriteValueMIPS_OpAtomicStore8_0(v)
case OpAtomicStorePtrNoWB: case OpAtomicStorePtrNoWB:
return rewriteValueMIPS_OpAtomicStorePtrNoWB_0(v) return rewriteValueMIPS_OpAtomicStorePtrNoWB_0(v)
case OpAvg32u: case OpAvg32u:
@ -245,8 +249,8 @@ func rewriteValueMIPS(v *Value) bool {
return rewriteValueMIPS_OpMIPSCMOVZzero_0(v) return rewriteValueMIPS_OpMIPSCMOVZzero_0(v)
case OpMIPSLoweredAtomicAdd: case OpMIPSLoweredAtomicAdd:
return rewriteValueMIPS_OpMIPSLoweredAtomicAdd_0(v) return rewriteValueMIPS_OpMIPSLoweredAtomicAdd_0(v)
case OpMIPSLoweredAtomicStore: case OpMIPSLoweredAtomicStore32:
return rewriteValueMIPS_OpMIPSLoweredAtomicStore_0(v) return rewriteValueMIPS_OpMIPSLoweredAtomicStore32_0(v)
case OpMIPSMOVBUload: case OpMIPSMOVBUload:
return rewriteValueMIPS_OpMIPSMOVBUload_0(v) return rewriteValueMIPS_OpMIPSMOVBUload_0(v)
case OpMIPSMOVBUreg: case OpMIPSMOVBUreg:
@ -826,11 +830,23 @@ func rewriteValueMIPS_OpAtomicExchange32_0(v *Value) bool {
} }
func rewriteValueMIPS_OpAtomicLoad32_0(v *Value) bool { func rewriteValueMIPS_OpAtomicLoad32_0(v *Value) bool {
// match: (AtomicLoad32 ptr mem) // match: (AtomicLoad32 ptr mem)
// result: (LoweredAtomicLoad ptr mem) // result: (LoweredAtomicLoad32 ptr mem)
for { for {
mem := v.Args[1] mem := v.Args[1]
ptr := v.Args[0] ptr := v.Args[0]
v.reset(OpMIPSLoweredAtomicLoad) v.reset(OpMIPSLoweredAtomicLoad32)
v.AddArg(ptr)
v.AddArg(mem)
return true
}
}
func rewriteValueMIPS_OpAtomicLoad8_0(v *Value) bool {
// match: (AtomicLoad8 ptr mem)
// result: (LoweredAtomicLoad8 ptr mem)
for {
mem := v.Args[1]
ptr := v.Args[0]
v.reset(OpMIPSLoweredAtomicLoad8)
v.AddArg(ptr) v.AddArg(ptr)
v.AddArg(mem) v.AddArg(mem)
return true return true
@ -838,11 +854,11 @@ func rewriteValueMIPS_OpAtomicLoad32_0(v *Value) bool {
} }
func rewriteValueMIPS_OpAtomicLoadPtr_0(v *Value) bool { func rewriteValueMIPS_OpAtomicLoadPtr_0(v *Value) bool {
// match: (AtomicLoadPtr ptr mem) // match: (AtomicLoadPtr ptr mem)
// result: (LoweredAtomicLoad ptr mem) // result: (LoweredAtomicLoad32 ptr mem)
for { for {
mem := v.Args[1] mem := v.Args[1]
ptr := v.Args[0] ptr := v.Args[0]
v.reset(OpMIPSLoweredAtomicLoad) v.reset(OpMIPSLoweredAtomicLoad32)
v.AddArg(ptr) v.AddArg(ptr)
v.AddArg(mem) v.AddArg(mem)
return true return true
@ -923,12 +939,26 @@ func rewriteValueMIPS_OpAtomicOr8_0(v *Value) bool {
} }
func rewriteValueMIPS_OpAtomicStore32_0(v *Value) bool { func rewriteValueMIPS_OpAtomicStore32_0(v *Value) bool {
// match: (AtomicStore32 ptr val mem) // match: (AtomicStore32 ptr val mem)
// result: (LoweredAtomicStore ptr val mem) // result: (LoweredAtomicStore32 ptr val mem)
for { for {
mem := v.Args[2] mem := v.Args[2]
ptr := v.Args[0] ptr := v.Args[0]
val := v.Args[1] val := v.Args[1]
v.reset(OpMIPSLoweredAtomicStore) v.reset(OpMIPSLoweredAtomicStore32)
v.AddArg(ptr)
v.AddArg(val)
v.AddArg(mem)
return true
}
}
func rewriteValueMIPS_OpAtomicStore8_0(v *Value) bool {
// match: (AtomicStore8 ptr val mem)
// result: (LoweredAtomicStore8 ptr val mem)
for {
mem := v.Args[2]
ptr := v.Args[0]
val := v.Args[1]
v.reset(OpMIPSLoweredAtomicStore8)
v.AddArg(ptr) v.AddArg(ptr)
v.AddArg(val) v.AddArg(val)
v.AddArg(mem) v.AddArg(mem)
@ -937,12 +967,12 @@ func rewriteValueMIPS_OpAtomicStore32_0(v *Value) bool {
} }
func rewriteValueMIPS_OpAtomicStorePtrNoWB_0(v *Value) bool { func rewriteValueMIPS_OpAtomicStorePtrNoWB_0(v *Value) bool {
// match: (AtomicStorePtrNoWB ptr val mem) // match: (AtomicStorePtrNoWB ptr val mem)
// result: (LoweredAtomicStore ptr val mem) // result: (LoweredAtomicStore32 ptr val mem)
for { for {
mem := v.Args[2] mem := v.Args[2]
ptr := v.Args[0] ptr := v.Args[0]
val := v.Args[1] val := v.Args[1]
v.reset(OpMIPSLoweredAtomicStore) v.reset(OpMIPSLoweredAtomicStore32)
v.AddArg(ptr) v.AddArg(ptr)
v.AddArg(val) v.AddArg(val)
v.AddArg(mem) v.AddArg(mem)
@ -3000,8 +3030,8 @@ func rewriteValueMIPS_OpMIPSLoweredAtomicAdd_0(v *Value) bool {
} }
return false return false
} }
func rewriteValueMIPS_OpMIPSLoweredAtomicStore_0(v *Value) bool { func rewriteValueMIPS_OpMIPSLoweredAtomicStore32_0(v *Value) bool {
// match: (LoweredAtomicStore ptr (MOVWconst [0]) mem) // match: (LoweredAtomicStore32 ptr (MOVWconst [0]) mem)
// result: (LoweredAtomicStorezero ptr mem) // result: (LoweredAtomicStorezero ptr mem)
for { for {
mem := v.Args[2] mem := v.Args[2]

View File

@ -57,6 +57,8 @@ func rewriteValueMIPS64(v *Value) bool {
return rewriteValueMIPS64_OpAtomicStore32_0(v) return rewriteValueMIPS64_OpAtomicStore32_0(v)
case OpAtomicStore64: case OpAtomicStore64:
return rewriteValueMIPS64_OpAtomicStore64_0(v) return rewriteValueMIPS64_OpAtomicStore64_0(v)
case OpAtomicStore8:
return rewriteValueMIPS64_OpAtomicStore8_0(v)
case OpAtomicStorePtrNoWB: case OpAtomicStorePtrNoWB:
return rewriteValueMIPS64_OpAtomicStorePtrNoWB_0(v) return rewriteValueMIPS64_OpAtomicStorePtrNoWB_0(v)
case OpAvg64u: case OpAvg64u:
@ -938,6 +940,20 @@ func rewriteValueMIPS64_OpAtomicStore64_0(v *Value) bool {
return true return true
} }
} }
func rewriteValueMIPS64_OpAtomicStore8_0(v *Value) bool {
// match: (AtomicStore8 ptr val mem)
// result: (LoweredAtomicStore8 ptr val mem)
for {
mem := v.Args[2]
ptr := v.Args[0]
val := v.Args[1]
v.reset(OpMIPS64LoweredAtomicStore8)
v.AddArg(ptr)
v.AddArg(val)
v.AddArg(mem)
return true
}
}
func rewriteValueMIPS64_OpAtomicStorePtrNoWB_0(v *Value) bool { func rewriteValueMIPS64_OpAtomicStorePtrNoWB_0(v *Value) bool {
// match: (AtomicStorePtrNoWB ptr val mem) // match: (AtomicStorePtrNoWB ptr val mem)
// result: (LoweredAtomicStore64 ptr val mem) // result: (LoweredAtomicStore64 ptr val mem)

View File

@ -71,6 +71,8 @@ func rewriteValuePPC64(v *Value) bool {
return rewriteValuePPC64_OpAtomicStore32_0(v) return rewriteValuePPC64_OpAtomicStore32_0(v)
case OpAtomicStore64: case OpAtomicStore64:
return rewriteValuePPC64_OpAtomicStore64_0(v) return rewriteValuePPC64_OpAtomicStore64_0(v)
case OpAtomicStore8:
return rewriteValuePPC64_OpAtomicStore8_0(v)
case OpAtomicStoreRel32: case OpAtomicStoreRel32:
return rewriteValuePPC64_OpAtomicStoreRel32_0(v) return rewriteValuePPC64_OpAtomicStoreRel32_0(v)
case OpAvg64u: case OpAvg64u:
@ -1132,6 +1134,21 @@ func rewriteValuePPC64_OpAtomicStore64_0(v *Value) bool {
return true return true
} }
} }
func rewriteValuePPC64_OpAtomicStore8_0(v *Value) bool {
// match: (AtomicStore8 ptr val mem)
// result: (LoweredAtomicStore8 [1] ptr val mem)
for {
mem := v.Args[2]
ptr := v.Args[0]
val := v.Args[1]
v.reset(OpPPC64LoweredAtomicStore8)
v.AuxInt = 1
v.AddArg(ptr)
v.AddArg(val)
v.AddArg(mem)
return true
}
}
func rewriteValuePPC64_OpAtomicStoreRel32_0(v *Value) bool { func rewriteValuePPC64_OpAtomicStoreRel32_0(v *Value) bool {
// match: (AtomicStoreRel32 ptr val mem) // match: (AtomicStoreRel32 ptr val mem)
// result: (LoweredAtomicStore32 [0] ptr val mem) // result: (LoweredAtomicStore32 [0] ptr val mem)

View File

@ -60,6 +60,8 @@ func rewriteValueS390X(v *Value) bool {
return rewriteValueS390X_OpAtomicStore32_0(v) return rewriteValueS390X_OpAtomicStore32_0(v)
case OpAtomicStore64: case OpAtomicStore64:
return rewriteValueS390X_OpAtomicStore64_0(v) return rewriteValueS390X_OpAtomicStore64_0(v)
case OpAtomicStore8:
return rewriteValueS390X_OpAtomicStore8_0(v)
case OpAtomicStorePtrNoWB: case OpAtomicStorePtrNoWB:
return rewriteValueS390X_OpAtomicStorePtrNoWB_0(v) return rewriteValueS390X_OpAtomicStorePtrNoWB_0(v)
case OpAtomicStoreRel32: case OpAtomicStoreRel32:
@ -1153,6 +1155,23 @@ func rewriteValueS390X_OpAtomicStore64_0(v *Value) bool {
return true return true
} }
} }
func rewriteValueS390X_OpAtomicStore8_0(v *Value) bool {
b := v.Block
// match: (AtomicStore8 ptr val mem)
// result: (SYNC (MOVBatomicstore ptr val mem))
for {
mem := v.Args[2]
ptr := v.Args[0]
val := v.Args[1]
v.reset(OpS390XSYNC)
v0 := b.NewValue0(v.Pos, OpS390XMOVBatomicstore, types.TypeMem)
v0.AddArg(ptr)
v0.AddArg(val)
v0.AddArg(mem)
v.AddArg(v0)
return true
}
}
func rewriteValueS390X_OpAtomicStorePtrNoWB_0(v *Value) bool { func rewriteValueS390X_OpAtomicStorePtrNoWB_0(v *Value) bool {
b := v.Block b := v.Block
// match: (AtomicStorePtrNoWB ptr val mem) // match: (AtomicStorePtrNoWB ptr val mem)

View File

@ -6142,18 +6142,18 @@ func rewriteValuegeneric_OpArraySelect_0(v *Value) bool {
v.AddArg(x) v.AddArg(x)
return true return true
} }
// match: (ArraySelect [0] x:(IData _)) // match: (ArraySelect [0] (IData x))
// result: x // result: (IData x)
for { for {
if v.AuxInt != 0 { if v.AuxInt != 0 {
break break
} }
x := v.Args[0] v_0 := v.Args[0]
if x.Op != OpIData { if v_0.Op != OpIData {
break break
} }
v.reset(OpCopy) x := v_0.Args[0]
v.Type = x.Type v.reset(OpIData)
v.AddArg(x) v.AddArg(x)
return true return true
} }
@ -43502,18 +43502,18 @@ func rewriteValuegeneric_OpStructSelect_10(v *Value) bool {
v0.AddArg(mem) v0.AddArg(mem)
return true return true
} }
// match: (StructSelect [0] x:(IData _)) // match: (StructSelect [0] (IData x))
// result: x // result: (IData x)
for { for {
if v.AuxInt != 0 { if v.AuxInt != 0 {
break break
} }
x := v.Args[0] v_0 := v.Args[0]
if x.Op != OpIData { if v_0.Op != OpIData {
break break
} }
v.reset(OpCopy) x := v_0.Args[0]
v.Type = x.Type v.reset(OpIData)
v.AddArg(x) v.AddArg(x)
return true return true
} }

View File

@ -96,7 +96,7 @@ func walkDirs(t *testing.T, dir string, action func(string)) {
} }
} else if fi.IsDir() && fi.Name() != "testdata" { } else if fi.IsDir() && fi.Name() != "testdata" {
path := filepath.Join(dir, fi.Name()) path := filepath.Join(dir, fi.Name())
if !strings.HasSuffix(path, "/test") { if !strings.HasSuffix(path, string(filepath.Separator)+"test") {
dirs = append(dirs, path) dirs = append(dirs, path)
} }
} }

View File

@ -19,7 +19,6 @@ func Init(arch *gc.Arch) {
arch.MAXWIDTH = 1 << 50 arch.MAXWIDTH = 1 << 50
arch.ZeroRange = zeroRange arch.ZeroRange = zeroRange
arch.ZeroAuto = zeroAuto
arch.Ginsnop = ginsnop arch.Ginsnop = ginsnop
arch.Ginsnopdefer = ginsnop arch.Ginsnopdefer = ginsnop
@ -45,21 +44,6 @@ func zeroRange(pp *gc.Progs, p *obj.Prog, off, cnt int64, state *uint32) *obj.Pr
return p return p
} }
func zeroAuto(pp *gc.Progs, n *gc.Node) {
sym := n.Sym.Linksym()
size := n.Type.Size()
for i := int64(0); i < size; i += 8 {
p := pp.Prog(wasm.AGet)
p.From = obj.Addr{Type: obj.TYPE_REG, Reg: wasm.REG_SP}
p = pp.Prog(wasm.AI64Const)
p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: 0}
p = pp.Prog(wasm.AI64Store)
p.To = obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_AUTO, Offset: n.Xoffset + i, Sym: sym}
}
}
func ginsnop(pp *gc.Progs) *obj.Prog { func ginsnop(pp *gc.Progs) *obj.Prog {
return pp.Prog(wasm.ANop) return pp.Prog(wasm.ANop)
} }

View File

@ -30,7 +30,6 @@ func Init(arch *gc.Arch) {
arch.MAXWIDTH = (1 << 32) - 1 arch.MAXWIDTH = (1 << 32) - 1
arch.ZeroRange = zerorange arch.ZeroRange = zerorange
arch.ZeroAuto = zeroAuto
arch.Ginsnop = ginsnop arch.Ginsnop = ginsnop
arch.Ginsnopdefer = ginsnop arch.Ginsnopdefer = ginsnop

View File

@ -37,22 +37,6 @@ func zerorange(pp *gc.Progs, p *obj.Prog, off, cnt int64, ax *uint32) *obj.Prog
return p return p
} }
func zeroAuto(pp *gc.Progs, n *gc.Node) {
// Note: this code must not clobber any registers.
sym := n.Sym.Linksym()
size := n.Type.Size()
for i := int64(0); i < size; i += 4 {
p := pp.Prog(x86.AMOVL)
p.From.Type = obj.TYPE_CONST
p.From.Offset = 0
p.To.Type = obj.TYPE_MEM
p.To.Name = obj.NAME_AUTO
p.To.Reg = x86.REG_SP
p.To.Offset = n.Xoffset + i
p.To.Sym = sym
}
}
func ginsnop(pp *gc.Progs) *obj.Prog { func ginsnop(pp *gc.Progs) *obj.Prog {
// See comment in ../amd64/ggen.go. // See comment in ../amd64/ggen.go.
p := pp.Prog(x86.AXCHGL) p := pp.Prog(x86.AXCHGL)

106
src/cmd/dist/build.go vendored
View File

@ -605,26 +605,26 @@ func startInstall(dir string) chan struct{} {
// runInstall installs the library, package, or binary associated with dir, // runInstall installs the library, package, or binary associated with dir,
// which is relative to $GOROOT/src. // which is relative to $GOROOT/src.
func runInstall(dir string, ch chan struct{}) { func runInstall(pkg string, ch chan struct{}) {
if dir == "net" || dir == "os/user" || dir == "crypto/x509" { if pkg == "net" || pkg == "os/user" || pkg == "crypto/x509" {
fatalf("go_bootstrap cannot depend on cgo package %s", dir) fatalf("go_bootstrap cannot depend on cgo package %s", pkg)
} }
defer close(ch) defer close(ch)
if dir == "unsafe" { if pkg == "unsafe" {
return return
} }
if vflag > 0 { if vflag > 0 {
if goos != gohostos || goarch != gohostarch { if goos != gohostos || goarch != gohostarch {
errprintf("%s (%s/%s)\n", dir, goos, goarch) errprintf("%s (%s/%s)\n", pkg, goos, goarch)
} else { } else {
errprintf("%s\n", dir) errprintf("%s\n", pkg)
} }
} }
workdir := pathf("%s/%s", workdir, dir) workdir := pathf("%s/%s", workdir, pkg)
xmkdirall(workdir) xmkdirall(workdir)
var clean []string var clean []string
@ -634,11 +634,14 @@ func runInstall(dir string, ch chan struct{}) {
} }
}() }()
// path = full path to dir. // dir = full path to pkg.
path := pathf("%s/src/%s", goroot, dir) dir := pathf("%s/src/%s", goroot, pkg)
name := filepath.Base(dir) name := filepath.Base(dir)
ispkg := !strings.HasPrefix(dir, "cmd/") || strings.Contains(dir, "/internal/") // ispkg predicts whether the package should be linked as a binary, based
// on the name. There should be no "main" packages in vendor, since
// 'go mod vendor' will only copy imported packages there.
ispkg := !strings.HasPrefix(pkg, "cmd/") || strings.Contains(pkg, "/internal/") || strings.Contains(pkg, "/vendor/")
// Start final link command line. // Start final link command line.
// Note: code below knows that link.p[targ] is the target. // Note: code below knows that link.p[targ] is the target.
@ -650,7 +653,7 @@ func runInstall(dir string, ch chan struct{}) {
if ispkg { if ispkg {
// Go library (package). // Go library (package).
ispackcmd = true ispackcmd = true
link = []string{"pack", pathf("%s/pkg/%s_%s/%s.a", goroot, goos, goarch, dir)} link = []string{"pack", packagefile(pkg)}
targ = len(link) - 1 targ = len(link) - 1
xmkdirall(filepath.Dir(link[targ])) xmkdirall(filepath.Dir(link[targ]))
} else { } else {
@ -675,7 +678,7 @@ func runInstall(dir string, ch chan struct{}) {
// Gather files that are sources for this target. // Gather files that are sources for this target.
// Everything in that directory, and any target-specific // Everything in that directory, and any target-specific
// additions. // additions.
files := xreaddir(path) files := xreaddir(dir)
// Remove files beginning with . or _, // Remove files beginning with . or _,
// which are likely to be editor temporary files. // which are likely to be editor temporary files.
@ -687,7 +690,7 @@ func runInstall(dir string, ch chan struct{}) {
}) })
for _, dt := range deptab { for _, dt := range deptab {
if dir == dt.prefix || strings.HasSuffix(dt.prefix, "/") && strings.HasPrefix(dir, dt.prefix) { if pkg == dt.prefix || strings.HasSuffix(dt.prefix, "/") && strings.HasPrefix(pkg, dt.prefix) {
for _, p := range dt.dep { for _, p := range dt.dep {
p = os.ExpandEnv(p) p = os.ExpandEnv(p)
files = append(files, p) files = append(files, p)
@ -699,7 +702,7 @@ func runInstall(dir string, ch chan struct{}) {
// Convert to absolute paths. // Convert to absolute paths.
for i, p := range files { for i, p := range files {
if !filepath.IsAbs(p) { if !filepath.IsAbs(p) {
files[i] = pathf("%s/%s", path, p) files[i] = pathf("%s/%s", dir, p)
} }
} }
@ -715,7 +718,7 @@ func runInstall(dir string, ch chan struct{}) {
return false return false
ok: ok:
t := mtime(p) t := mtime(p)
if !t.IsZero() && !strings.HasSuffix(p, ".a") && !shouldbuild(p, dir) { if !t.IsZero() && !strings.HasSuffix(p, ".a") && !shouldbuild(p, pkg) {
return false return false
} }
if strings.HasSuffix(p, ".go") { if strings.HasSuffix(p, ".go") {
@ -742,7 +745,7 @@ func runInstall(dir string, ch chan struct{}) {
} }
// For package runtime, copy some files into the work space. // For package runtime, copy some files into the work space.
if dir == "runtime" { if pkg == "runtime" {
xmkdirall(pathf("%s/pkg/include", goroot)) xmkdirall(pathf("%s/pkg/include", goroot))
// For use by assembly and C files. // For use by assembly and C files.
copyfile(pathf("%s/pkg/include/textflag.h", goroot), copyfile(pathf("%s/pkg/include/textflag.h", goroot),
@ -764,7 +767,7 @@ func runInstall(dir string, ch chan struct{}) {
if vflag > 1 { if vflag > 1 {
errprintf("generate %s\n", p) errprintf("generate %s\n", p)
} }
gt.gen(path, p) gt.gen(dir, p)
// Do not add generated file to clean list. // Do not add generated file to clean list.
// In runtime, we want to be able to // In runtime, we want to be able to
// build the package with the go tool, // build the package with the go tool,
@ -782,22 +785,31 @@ func runInstall(dir string, ch chan struct{}) {
built: built:
} }
// Make sure dependencies are installed. // Resolve imported packages to actual package paths.
var deps []string // Make sure they're installed.
importMap := make(map[string]string)
for _, p := range gofiles { for _, p := range gofiles {
deps = append(deps, readimports(p)...) for _, imp := range readimports(p) {
importMap[imp] = resolveVendor(imp, dir)
}
} }
for _, dir1 := range deps { sortedImports := make([]string, 0, len(importMap))
startInstall(dir1) for imp := range importMap {
sortedImports = append(sortedImports, imp)
} }
for _, dir1 := range deps { sort.Strings(sortedImports)
install(dir1)
for _, dep := range importMap {
startInstall(dep)
}
for _, dep := range importMap {
install(dep)
} }
if goos != gohostos || goarch != gohostarch { if goos != gohostos || goarch != gohostarch {
// We've generated the right files; the go command can do the build. // We've generated the right files; the go command can do the build.
if vflag > 1 { if vflag > 1 {
errprintf("skip build for cross-compile %s\n", dir) errprintf("skip build for cross-compile %s\n", pkg)
} }
return return
} }
@ -830,18 +842,35 @@ func runInstall(dir string, ch chan struct{}) {
if err := ioutil.WriteFile(goasmh, nil, 0666); err != nil { if err := ioutil.WriteFile(goasmh, nil, 0666); err != nil {
fatalf("cannot write empty go_asm.h: %s", err) fatalf("cannot write empty go_asm.h: %s", err)
} }
bgrun(&wg, path, asmabis...) bgrun(&wg, dir, asmabis...)
bgwait(&wg) bgwait(&wg)
} }
// Build an importcfg file for the compiler.
buf := &bytes.Buffer{}
for _, imp := range sortedImports {
if imp == "unsafe" {
continue
}
dep := importMap[imp]
if imp != dep {
fmt.Fprintf(buf, "importmap %s=%s\n", imp, dep)
}
fmt.Fprintf(buf, "packagefile %s=%s\n", dep, packagefile(dep))
}
importcfg := pathf("%s/importcfg", workdir)
if err := ioutil.WriteFile(importcfg, buf.Bytes(), 0666); err != nil {
fatalf("cannot write importcfg file: %v", err)
}
var archive string var archive string
// The next loop will compile individual non-Go files. // The next loop will compile individual non-Go files.
// Hand the Go files to the compiler en masse. // Hand the Go files to the compiler en masse.
// For packages containing assembly, this writes go_asm.h, which // For packages containing assembly, this writes go_asm.h, which
// the assembly files will need. // the assembly files will need.
pkg := dir pkgName := pkg
if strings.HasPrefix(dir, "cmd/") && strings.Count(dir, "/") == 1 { if strings.HasPrefix(pkg, "cmd/") && strings.Count(pkg, "/") == 1 {
pkg = "main" pkgName = "main"
} }
b := pathf("%s/_go_.a", workdir) b := pathf("%s/_go_.a", workdir)
clean = append(clean, b) clean = append(clean, b)
@ -852,11 +881,11 @@ func runInstall(dir string, ch chan struct{}) {
} }
// Compile Go code. // Compile Go code.
compile := []string{pathf("%s/compile", tooldir), "-std", "-pack", "-o", b, "-p", pkg} compile := []string{pathf("%s/compile", tooldir), "-std", "-pack", "-o", b, "-p", pkgName, "-importcfg", importcfg}
if gogcflags != "" { if gogcflags != "" {
compile = append(compile, strings.Fields(gogcflags)...) compile = append(compile, strings.Fields(gogcflags)...)
} }
if dir == "runtime" { if pkg == "runtime" {
compile = append(compile, "-+") compile = append(compile, "-+")
} }
if len(sfiles) > 0 { if len(sfiles) > 0 {
@ -874,7 +903,7 @@ func runInstall(dir string, ch chan struct{}) {
// We use bgrun and immediately wait for it instead of calling run() synchronously. // We use bgrun and immediately wait for it instead of calling run() synchronously.
// This executes all jobs through the bgwork channel and allows the process // This executes all jobs through the bgwork channel and allows the process
// to exit cleanly in case an error occurs. // to exit cleanly in case an error occurs.
bgrun(&wg, path, compile...) bgrun(&wg, dir, compile...)
bgwait(&wg) bgwait(&wg)
// Compile the files. // Compile the files.
@ -888,7 +917,7 @@ func runInstall(dir string, ch chan struct{}) {
// Change the last character of the output file (which was c or s). // Change the last character of the output file (which was c or s).
b = b[:len(b)-1] + "o" b = b[:len(b)-1] + "o"
compile = append(compile, "-o", b, p) compile = append(compile, "-o", b, p)
bgrun(&wg, path, compile...) bgrun(&wg, dir, compile...)
link = append(link, b) link = append(link, b)
if doclean { if doclean {
@ -909,6 +938,12 @@ func runInstall(dir string, ch chan struct{}) {
bgwait(&wg) bgwait(&wg)
} }
// packagefile returns the path to a compiled .a file for the given package
// path. Paths may need to be resolved with resolveVendor first.
func packagefile(pkg string) string {
return pathf("%s/pkg/%s_%s/%s.a", goroot, goos, goarch, pkg)
}
// matchfield reports whether the field (x,y,z) matches this build. // matchfield reports whether the field (x,y,z) matches this build.
// all the elements in the field must be satisfied. // all the elements in the field must be satisfied.
func matchfield(f string) bool { func matchfield(f string) bool {
@ -940,7 +975,7 @@ func matchtag(tag string) bool {
// of GOOS and GOARCH. // of GOOS and GOARCH.
// We also allow the special tag cmd_go_bootstrap. // We also allow the special tag cmd_go_bootstrap.
// See ../go/bootstrap.go and package go/build. // See ../go/bootstrap.go and package go/build.
func shouldbuild(file, dir string) bool { func shouldbuild(file, pkg string) bool {
// Check file name for GOOS or GOARCH. // Check file name for GOOS or GOARCH.
name := filepath.Base(file) name := filepath.Base(file)
excluded := func(list []string, ok string) bool { excluded := func(list []string, ok string) bool {
@ -982,7 +1017,7 @@ func shouldbuild(file, dir string) bool {
if code == "package documentation" { if code == "package documentation" {
return false return false
} }
if code == "package main" && dir != "cmd/go" && dir != "cmd/cgo" { if code == "package main" && pkg != "cmd/go" && pkg != "cmd/cgo" {
return false return false
} }
if !strings.HasPrefix(p, "//") { if !strings.HasPrefix(p, "//") {
@ -1485,6 +1520,7 @@ var cgoEnabled = map[string]bool{
"freebsd/386": true, "freebsd/386": true,
"freebsd/amd64": true, "freebsd/amd64": true,
"freebsd/arm": true, "freebsd/arm": true,
"freebsd/arm64": true,
"illumos/amd64": true, "illumos/amd64": true,
"linux/386": true, "linux/386": true,
"linux/amd64": true, "linux/amd64": true,

View File

@ -11,7 +11,10 @@ package main
import ( import (
"bufio" "bufio"
"errors" "errors"
"fmt"
"io" "io"
"path"
"path/filepath"
"strconv" "strconv"
"strings" "strings"
"unicode/utf8" "unicode/utf8"
@ -243,3 +246,31 @@ func readimports(file string) []string {
return imports return imports
} }
// resolveVendor returns a unique package path imported with the given import
// path from srcDir.
//
// resolveVendor assumes that a package is vendored if and only if its first
// path component contains a dot. If a package is vendored, its import path
// is returned with a "vendor" or "cmd/vendor" prefix, depending on srcDir.
// Otherwise, the import path is returned verbatim.
func resolveVendor(imp, srcDir string) string {
var first string
if i := strings.Index(imp, "/"); i < 0 {
first = imp
} else {
first = imp[:i]
}
isStandard := !strings.Contains(first, ".")
if isStandard {
return imp
}
if strings.HasPrefix(srcDir, filepath.Join(goroot, "src", "cmd")) {
return path.Join("cmd", "vendor", imp)
} else if strings.HasPrefix(srcDir, filepath.Join(goroot, "src")) {
return path.Join("vendor", imp)
} else {
panic(fmt.Sprintf("srcDir %q not in GOOROT/src", srcDir))
}
}

13
src/cmd/dist/test.go vendored
View File

@ -418,7 +418,7 @@ func (t *tester) registerTests() {
cmd.Args = append(cmd.Args, "-tags=race") cmd.Args = append(cmd.Args, "-tags=race")
} }
cmd.Args = append(cmd.Args, "std") cmd.Args = append(cmd.Args, "std")
if !t.race { if t.shouldTestCmd() {
cmd.Args = append(cmd.Args, "cmd") cmd.Args = append(cmd.Args, "cmd")
} }
cmd.Stderr = new(bytes.Buffer) cmd.Stderr = new(bytes.Buffer)
@ -1455,6 +1455,17 @@ func (t *tester) shouldUsePrecompiledStdTest() bool {
return err == nil return err == nil
} }
func (t *tester) shouldTestCmd() bool {
if t.race {
return false
}
if goos == "js" && goarch == "wasm" {
// Issues 25911, 35220
return false
}
return true
}
// prebuiltGoPackageTestBinary returns the path where we'd expect // prebuiltGoPackageTestBinary returns the path where we'd expect
// the pre-built go test binary to be on disk when dist test is run with // the pre-built go test binary to be on disk when dist test is run with
// a single argument. // a single argument.

View File

@ -15,11 +15,11 @@ import (
"go/token" "go/token"
"io/ioutil" "io/ioutil"
"os" "os"
"os/exec"
"path/filepath" "path/filepath"
"runtime"
"sort" "sort"
"strings" "strings"
"cmd/internal/diff"
) )
var ( var (
@ -186,7 +186,7 @@ func processFile(filename string, useStdin bool) error {
} }
if *doDiff { if *doDiff {
data, err := diff(src, newSrc) data, err := diff.Diff("go-fix", src, newSrc)
if err != nil { if err != nil {
return fmt.Errorf("computing diff: %s", err) return fmt.Errorf("computing diff: %s", err)
} }
@ -237,46 +237,3 @@ func isGoFile(f os.FileInfo) bool {
name := f.Name() name := f.Name()
return !f.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go") return !f.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go")
} }
func writeTempFile(dir, prefix string, data []byte) (string, error) {
file, err := ioutil.TempFile(dir, prefix)
if err != nil {
return "", err
}
_, err = file.Write(data)
if err1 := file.Close(); err == nil {
err = err1
}
if err != nil {
os.Remove(file.Name())
return "", err
}
return file.Name(), nil
}
func diff(b1, b2 []byte) (data []byte, err error) {
f1, err := writeTempFile("", "go-fix", b1)
if err != nil {
return
}
defer os.Remove(f1)
f2, err := writeTempFile("", "go-fix", b2)
if err != nil {
return
}
defer os.Remove(f2)
cmd := "diff"
if runtime.GOOS == "plan9" {
cmd = "/bin/ape/diff"
}
data, err = exec.Command(cmd, "-u", f1, f2).CombinedOutput()
if len(data) > 0 {
// diff exits with a non-zero status when the files don't match.
// Ignore that failure as long as we get output.
err = nil
}
return
}

View File

@ -9,6 +9,8 @@ import (
"go/parser" "go/parser"
"strings" "strings"
"testing" "testing"
"cmd/internal/diff"
) )
type testCase struct { type testCase struct {
@ -123,7 +125,7 @@ func TestRewrite(t *testing.T) {
} }
func tdiff(t *testing.T, a, b string) { func tdiff(t *testing.T, a, b string) {
data, err := diff([]byte(a), []byte(b)) data, err := diff.Diff("go-fix-test", []byte(a), []byte(b))
if err != nil { if err != nil {
t.Error(err) t.Error(err)
return return

View File

@ -6,7 +6,8 @@ require (
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f github.com/google/pprof v0.0.0-20190515194954-54271f7e092f
github.com/ianlancetaylor/demangle v0.0.0-20180524225900-fc6590592b44 // indirect github.com/ianlancetaylor/demangle v0.0.0-20180524225900-fc6590592b44 // indirect
golang.org/x/arch v0.0.0-20190815191158-8a70ba74b3a1 golang.org/x/arch v0.0.0-20190815191158-8a70ba74b3a1
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550
golang.org/x/mod v0.1.1-0.20191029194233-18c3998b6452
golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82 // indirect golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82 // indirect
golang.org/x/tools v0.0.0-20191018203202-04252eccb9d5 golang.org/x/tools v0.0.0-20191018203202-04252eccb9d5
) )

View File

@ -5,11 +5,15 @@ github.com/ianlancetaylor/demangle v0.0.0-20180524225900-fc6590592b44/go.mod h1:
golang.org/x/arch v0.0.0-20190815191158-8a70ba74b3a1 h1:A71BZbKSu+DtCNry/x5JKn20C+64DirDHmePEA8k0FY= golang.org/x/arch v0.0.0-20190815191158-8a70ba74b3a1 h1:A71BZbKSu+DtCNry/x5JKn20C+64DirDHmePEA8k0FY=
golang.org/x/arch v0.0.0-20190815191158-8a70ba74b3a1/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4= golang.org/x/arch v0.0.0-20190815191158-8a70ba74b3a1/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/mod v0.1.1-0.20191029194233-18c3998b6452 h1:ES2W0A+AqNBCkgWga22gheu9IUDjq3TDmeCdY1A7jhk=
golang.org/x/mod v0.1.1-0.20191029194233-18c3998b6452/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82 h1:vsphBvatvfbhlb4PO1BYSr9dzugGxJ/SQHoNufZJq1w= golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82 h1:vsphBvatvfbhlb4PO1BYSr9dzugGxJ/SQHoNufZJq1w=
golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
@ -17,4 +21,6 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20191018203202-04252eccb9d5 h1:TFUhCYbgGMOGnRxJv+j0iAcxCjk8oGjXXWNejQBhUUs= golang.org/x/tools v0.0.0-20191018203202-04252eccb9d5 h1:TFUhCYbgGMOGnRxJv+j0iAcxCjk8oGjXXWNejQBhUUs=
golang.org/x/tools v0.0.0-20191018203202-04252eccb9d5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191018203202-04252eccb9d5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

View File

@ -1,135 +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 dirhash
import (
"archive/zip"
"crypto/sha256"
"encoding/base64"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"strings"
"testing"
)
func h(s string) string {
return fmt.Sprintf("%x", sha256.Sum256([]byte(s)))
}
func htop(k string, s string) string {
sum := sha256.Sum256([]byte(s))
return k + ":" + base64.StdEncoding.EncodeToString(sum[:])
}
func TestHash1(t *testing.T) {
files := []string{"xyz", "abc"}
open := func(name string) (io.ReadCloser, error) {
return ioutil.NopCloser(strings.NewReader("data for " + name)), nil
}
want := htop("h1", fmt.Sprintf("%s %s\n%s %s\n", h("data for abc"), "abc", h("data for xyz"), "xyz"))
out, err := Hash1(files, open)
if err != nil {
t.Fatal(err)
}
if out != want {
t.Errorf("Hash1(...) = %s, want %s", out, want)
}
_, err = Hash1([]string{"xyz", "a\nbc"}, open)
if err == nil {
t.Error("Hash1: expected error on newline in filenames")
}
}
func TestHashDir(t *testing.T) {
dir, err := ioutil.TempDir("", "dirhash-test-")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(dir)
if err := ioutil.WriteFile(filepath.Join(dir, "xyz"), []byte("data for xyz"), 0666); err != nil {
t.Fatal(err)
}
if err := ioutil.WriteFile(filepath.Join(dir, "abc"), []byte("data for abc"), 0666); err != nil {
t.Fatal(err)
}
want := htop("h1", fmt.Sprintf("%s %s\n%s %s\n", h("data for abc"), "prefix/abc", h("data for xyz"), "prefix/xyz"))
out, err := HashDir(dir, "prefix", Hash1)
if err != nil {
t.Fatalf("HashDir: %v", err)
}
if out != want {
t.Errorf("HashDir(...) = %s, want %s", out, want)
}
}
func TestHashZip(t *testing.T) {
f, err := ioutil.TempFile("", "dirhash-test-")
if err != nil {
t.Fatal(err)
}
defer os.Remove(f.Name())
defer f.Close()
z := zip.NewWriter(f)
w, err := z.Create("prefix/xyz")
if err != nil {
t.Fatal(err)
}
w.Write([]byte("data for xyz"))
w, err = z.Create("prefix/abc")
if err != nil {
t.Fatal(err)
}
w.Write([]byte("data for abc"))
if err := z.Close(); err != nil {
t.Fatal(err)
}
if err := f.Close(); err != nil {
t.Fatal(err)
}
want := htop("h1", fmt.Sprintf("%s %s\n%s %s\n", h("data for abc"), "prefix/abc", h("data for xyz"), "prefix/xyz"))
out, err := HashZip(f.Name(), Hash1)
if err != nil {
t.Fatalf("HashDir: %v", err)
}
if out != want {
t.Errorf("HashDir(...) = %s, want %s", out, want)
}
}
func TestDirFiles(t *testing.T) {
dir, err := ioutil.TempDir("", "dirfiles-test-")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(dir)
if err := ioutil.WriteFile(filepath.Join(dir, "xyz"), []byte("data for xyz"), 0666); err != nil {
t.Fatal(err)
}
if err := ioutil.WriteFile(filepath.Join(dir, "abc"), []byte("data for abc"), 0666); err != nil {
t.Fatal(err)
}
if err := os.Mkdir(filepath.Join(dir, "subdir"), 0777); err != nil {
t.Fatal(err)
}
if err := ioutil.WriteFile(filepath.Join(dir, "subdir", "xyz"), []byte("data for subdir xyz"), 0666); err != nil {
t.Fatal(err)
}
prefix := "foo/bar@v2.3.4"
out, err := DirFiles(dir, prefix)
if err != nil {
t.Fatalf("DirFiles: %v", err)
}
for _, file := range out {
if !strings.HasPrefix(file, prefix) {
t.Errorf("Dir file = %s, want prefix %s", file, prefix)
}
}
}

View File

@ -237,7 +237,7 @@ func runEnv(cmd *base.Command, args []string) {
base.Fatalf("go env -w: arguments must be KEY=VALUE: invalid argument: %s", arg) base.Fatalf("go env -w: arguments must be KEY=VALUE: invalid argument: %s", arg)
} }
key, val := arg[:i], arg[i+1:] key, val := arg[:i], arg[i+1:]
if err := checkEnvWrite(key, val, env); err != nil { if err := checkEnvWrite(key, val); err != nil {
base.Fatalf("go env -w: %v", err) base.Fatalf("go env -w: %v", err)
} }
if _, ok := add[key]; ok { if _, ok := add[key]; ok {
@ -259,7 +259,7 @@ func runEnv(cmd *base.Command, args []string) {
} }
del := make(map[string]bool) del := make(map[string]bool)
for _, arg := range args { for _, arg := range args {
if err := checkEnvWrite(arg, "", env); err != nil { if err := checkEnvWrite(arg, ""); err != nil {
base.Fatalf("go env -u: %v", err) base.Fatalf("go env -u: %v", err)
} }
del[arg] = true del[arg] = true
@ -330,7 +330,7 @@ func printEnvAsJSON(env []cfg.EnvVar) {
} }
} }
func checkEnvWrite(key, val string, env []cfg.EnvVar) error { func checkEnvWrite(key, val string) error {
switch key { switch key {
case "GOEXE", "GOGCCFLAGS", "GOHOSTARCH", "GOHOSTOS", "GOMOD", "GOTOOLDIR": case "GOEXE", "GOGCCFLAGS", "GOHOSTARCH", "GOHOSTOS", "GOMOD", "GOTOOLDIR":
return fmt.Errorf("%s cannot be modified", key) return fmt.Errorf("%s cannot be modified", key)

View File

@ -11,7 +11,7 @@ import (
"unicode/utf8" "unicode/utf8"
) )
// The following functions are copied verbatim from cmd/go/internal/module/module.go, // The following functions are copied verbatim from golang.org/x/mod/module/module.go,
// with a change to additionally reject Windows short-names, // with a change to additionally reject Windows short-names,
// and one to accept arbitrary letters (golang.org/issue/29101). // and one to accept arbitrary letters (golang.org/issue/29101).
// //

View File

@ -593,7 +593,7 @@ func loadImport(pre *preload, path, srcDir string, parent *Package, stk *ImportS
return setErrorPos(perr, importPos) return setErrorPos(perr, importPos)
} }
if mode&ResolveImport != 0 { if mode&ResolveImport != 0 {
if perr := disallowVendor(srcDir, parent, parentPath, path, p, stk); perr != p { if perr := disallowVendor(srcDir, path, p, stk); perr != p {
return setErrorPos(perr, importPos) return setErrorPos(perr, importPos)
} }
} }
@ -1321,11 +1321,10 @@ func findInternal(path string) (index int, ok bool) {
return 0, false return 0, false
} }
// disallowVendor checks that srcDir (containing package importerPath, if non-empty) // disallowVendor checks that srcDir is allowed to import p as path.
// is allowed to import p as path.
// If the import is allowed, disallowVendor returns the original package p. // If the import is allowed, disallowVendor returns the original package p.
// If not, it returns a new package containing just an appropriate error. // If not, it returns a new package containing just an appropriate error.
func disallowVendor(srcDir string, importer *Package, importerPath, path string, p *Package, stk *ImportStack) *Package { func disallowVendor(srcDir string, path string, p *Package, stk *ImportStack) *Package {
// The stack includes p.ImportPath. // The stack includes p.ImportPath.
// If that's the only thing on the stack, we started // If that's the only thing on the stack, we started
// with a name given on the command line, not an // with a name given on the command line, not an

View File

@ -5,16 +5,17 @@
package modcmd package modcmd
import ( import (
"cmd/go/internal/cfg"
"encoding/json" "encoding/json"
"os" "os"
"cmd/go/internal/base" "cmd/go/internal/base"
"cmd/go/internal/cfg"
"cmd/go/internal/modfetch" "cmd/go/internal/modfetch"
"cmd/go/internal/modload" "cmd/go/internal/modload"
"cmd/go/internal/module"
"cmd/go/internal/par" "cmd/go/internal/par"
"cmd/go/internal/work" "cmd/go/internal/work"
"golang.org/x/mod/module"
) )
var cmdDownload = &base.Command{ var cmdDownload = &base.Command{

View File

@ -16,10 +16,11 @@ import (
"cmd/go/internal/base" "cmd/go/internal/base"
"cmd/go/internal/modfetch" "cmd/go/internal/modfetch"
"cmd/go/internal/modfile"
"cmd/go/internal/modload" "cmd/go/internal/modload"
"cmd/go/internal/module"
"cmd/go/internal/work" "cmd/go/internal/work"
"golang.org/x/mod/modfile"
"golang.org/x/mod/module"
) )
var cmdEdit = &base.Command{ var cmdEdit = &base.Command{

View File

@ -8,15 +8,16 @@ package modcmd
import ( import (
"bufio" "bufio"
"cmd/go/internal/cfg"
"os" "os"
"sort" "sort"
"cmd/go/internal/base" "cmd/go/internal/base"
"cmd/go/internal/cfg"
"cmd/go/internal/modload" "cmd/go/internal/modload"
"cmd/go/internal/module"
"cmd/go/internal/par" "cmd/go/internal/par"
"cmd/go/internal/work" "cmd/go/internal/work"
"golang.org/x/mod/module"
) )
var cmdGraph = &base.Command{ var cmdGraph = &base.Command{

View File

@ -14,8 +14,9 @@ import (
"cmd/go/internal/cfg" "cmd/go/internal/cfg"
"cmd/go/internal/modfetch" "cmd/go/internal/modfetch"
"cmd/go/internal/modload" "cmd/go/internal/modload"
"cmd/go/internal/module"
"cmd/go/internal/work" "cmd/go/internal/work"
"golang.org/x/mod/module"
) )
var cmdTidy = &base.Command{ var cmdTidy = &base.Command{

View File

@ -18,9 +18,10 @@ import (
"cmd/go/internal/cfg" "cmd/go/internal/cfg"
"cmd/go/internal/imports" "cmd/go/internal/imports"
"cmd/go/internal/modload" "cmd/go/internal/modload"
"cmd/go/internal/module"
"cmd/go/internal/semver"
"cmd/go/internal/work" "cmd/go/internal/work"
"golang.org/x/mod/module"
"golang.org/x/mod/semver"
) )
var cmdVendor = &base.Command{ var cmdVendor = &base.Command{

View File

@ -6,17 +6,18 @@ package modcmd
import ( import (
"bytes" "bytes"
"cmd/go/internal/cfg"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"cmd/go/internal/base" "cmd/go/internal/base"
"cmd/go/internal/dirhash" "cmd/go/internal/cfg"
"cmd/go/internal/modfetch" "cmd/go/internal/modfetch"
"cmd/go/internal/modload" "cmd/go/internal/modload"
"cmd/go/internal/module"
"cmd/go/internal/work" "cmd/go/internal/work"
"golang.org/x/mod/module"
"golang.org/x/mod/sumdb/dirhash"
) )
var cmdVerify = &base.Command{ var cmdVerify = &base.Command{

View File

@ -5,12 +5,14 @@
package modcmd package modcmd
import ( import (
"cmd/go/internal/base"
"cmd/go/internal/modload"
"cmd/go/internal/module"
"cmd/go/internal/work"
"fmt" "fmt"
"strings" "strings"
"cmd/go/internal/base"
"cmd/go/internal/modload"
"cmd/go/internal/work"
"golang.org/x/mod/module"
) )
var cmdWhy = &base.Command{ var cmdWhy = &base.Command{

View File

@ -13,10 +13,11 @@ import (
"cmd/go/internal/base" "cmd/go/internal/base"
"cmd/go/internal/modfetch" "cmd/go/internal/modfetch"
"cmd/go/internal/modfile"
"cmd/go/internal/module"
"cmd/go/internal/par" "cmd/go/internal/par"
"cmd/go/internal/semver"
"golang.org/x/mod/modfile"
"golang.org/x/mod/module"
"golang.org/x/mod/semver"
) )
// ConvertLegacyConfig converts legacy config to modfile. // ConvertLegacyConfig converts legacy config to modfile.

View File

@ -19,8 +19,9 @@ import (
"cmd/go/internal/cfg" "cmd/go/internal/cfg"
"cmd/go/internal/modfetch" "cmd/go/internal/modfetch"
"cmd/go/internal/modfetch/codehost" "cmd/go/internal/modfetch/codehost"
"cmd/go/internal/modfile"
"cmd/go/internal/module" "golang.org/x/mod/modfile"
"golang.org/x/mod/module"
) )
func TestMain(m *testing.M) { func TestMain(m *testing.M) {

View File

@ -12,9 +12,9 @@ import (
"strconv" "strconv"
"strings" "strings"
"cmd/go/internal/modfile" "golang.org/x/mod/modfile"
"cmd/go/internal/module" "golang.org/x/mod/module"
"cmd/go/internal/semver" "golang.org/x/mod/semver"
) )
func ParseGopkgLock(file string, data []byte) (*modfile.File, error) { func ParseGopkgLock(file string, data []byte) (*modfile.File, error) {

View File

@ -7,8 +7,8 @@ package modconv
import ( import (
"strings" "strings"
"cmd/go/internal/modfile" "golang.org/x/mod/modfile"
"cmd/go/internal/module" "golang.org/x/mod/module"
) )
func ParseGlideLock(file string, data []byte) (*modfile.File, error) { func ParseGlideLock(file string, data []byte) (*modfile.File, error) {

View File

@ -7,8 +7,8 @@ package modconv
import ( import (
"strings" "strings"
"cmd/go/internal/modfile" "golang.org/x/mod/modfile"
"cmd/go/internal/module" "golang.org/x/mod/module"
) )
func ParseGLOCKFILE(file string, data []byte) (*modfile.File, error) { func ParseGLOCKFILE(file string, data []byte) (*modfile.File, error) {

View File

@ -7,8 +7,8 @@ package modconv
import ( import (
"encoding/json" "encoding/json"
"cmd/go/internal/modfile" "golang.org/x/mod/modfile"
"cmd/go/internal/module" "golang.org/x/mod/module"
) )
func ParseGodepsJSON(file string, data []byte) (*modfile.File, error) { func ParseGodepsJSON(file string, data []byte) (*modfile.File, error) {

View File

@ -4,7 +4,7 @@
package modconv package modconv
import "cmd/go/internal/modfile" import "golang.org/x/mod/modfile"
var Converters = map[string]func(string, []byte) (*modfile.File, error){ var Converters = map[string]func(string, []byte) (*modfile.File, error){
"GLOCKFILE": ParseGLOCKFILE, "GLOCKFILE": ParseGLOCKFILE,

View File

@ -7,8 +7,8 @@ package modconv
import ( import (
"strings" "strings"
"cmd/go/internal/modfile" "golang.org/x/mod/modfile"
"cmd/go/internal/module" "golang.org/x/mod/module"
) )
func ParseDependenciesTSV(file string, data []byte) (*modfile.File, error) { func ParseDependenciesTSV(file string, data []byte) (*modfile.File, error) {

View File

@ -7,8 +7,8 @@ package modconv
import ( import (
"strings" "strings"
"cmd/go/internal/modfile" "golang.org/x/mod/modfile"
"cmd/go/internal/module" "golang.org/x/mod/module"
) )
func ParseVendorConf(file string, data []byte) (*modfile.File, error) { func ParseVendorConf(file string, data []byte) (*modfile.File, error) {

View File

@ -7,8 +7,8 @@ package modconv
import ( import (
"encoding/json" "encoding/json"
"cmd/go/internal/modfile" "golang.org/x/mod/modfile"
"cmd/go/internal/module" "golang.org/x/mod/module"
) )
func ParseVendorJSON(file string, data []byte) (*modfile.File, error) { func ParseVendorJSON(file string, data []byte) (*modfile.File, error) {

View File

@ -7,8 +7,8 @@ package modconv
import ( import (
"encoding/json" "encoding/json"
"cmd/go/internal/modfile" "golang.org/x/mod/modfile"
"cmd/go/internal/module" "golang.org/x/mod/module"
) )
func ParseVendorManifest(file string, data []byte) (*modfile.File, error) { func ParseVendorManifest(file string, data []byte) (*modfile.File, error) {

View File

@ -7,8 +7,8 @@ package modconv
import ( import (
"strings" "strings"
"cmd/go/internal/modfile" "golang.org/x/mod/modfile"
"cmd/go/internal/module" "golang.org/x/mod/module"
) )
func ParseVendorYML(file string, data []byte) (*modfile.File, error) { func ParseVendorYML(file string, data []byte) (*modfile.File, error) {

View File

@ -6,7 +6,7 @@
package modfetch package modfetch
import "cmd/go/internal/module" import "golang.org/x/mod/module"
func useSumDB(mod module.Version) bool { func useSumDB(mod module.Version) bool {
return false return false

View File

@ -18,10 +18,11 @@ import (
"cmd/go/internal/cfg" "cmd/go/internal/cfg"
"cmd/go/internal/lockedfile" "cmd/go/internal/lockedfile"
"cmd/go/internal/modfetch/codehost" "cmd/go/internal/modfetch/codehost"
"cmd/go/internal/module"
"cmd/go/internal/par" "cmd/go/internal/par"
"cmd/go/internal/renameio" "cmd/go/internal/renameio"
"cmd/go/internal/semver"
"golang.org/x/mod/module"
"golang.org/x/mod/semver"
) )
var QuietLookup bool // do not print about lookups var QuietLookup bool // do not print about lookups

View File

@ -22,8 +22,9 @@ import (
"cmd/go/internal/lockedfile" "cmd/go/internal/lockedfile"
"cmd/go/internal/par" "cmd/go/internal/par"
"cmd/go/internal/semver"
"cmd/go/internal/web" "cmd/go/internal/web"
"golang.org/x/mod/semver"
) )
// GitRepo returns the code repository at the given Git remote reference. // GitRepo returns the code repository at the given Git remote reference.

View File

@ -0,0 +1,154 @@
// 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 codehost
import (
"archive/zip"
"encoding/xml"
"fmt"
"io"
"os"
"path"
"path/filepath"
"time"
)
func svnParseStat(rev, out string) (*RevInfo, error) {
var log struct {
Logentry struct {
Revision int64 `xml:"revision,attr"`
Date string `xml:"date"`
} `xml:"logentry"`
}
if err := xml.Unmarshal([]byte(out), &log); err != nil {
return nil, vcsErrorf("unexpected response from svn log --xml: %v\n%s", err, out)
}
t, err := time.Parse(time.RFC3339, log.Logentry.Date)
if err != nil {
return nil, vcsErrorf("unexpected response from svn log --xml: %v\n%s", err, out)
}
info := &RevInfo{
Name: fmt.Sprintf("%d", log.Logentry.Revision),
Short: fmt.Sprintf("%012d", log.Logentry.Revision),
Time: t.UTC(),
Version: rev,
}
return info, nil
}
func svnReadZip(dst io.Writer, workDir, rev, subdir, remote string) (err error) {
// The subversion CLI doesn't provide a command to write the repository
// directly to an archive, so we need to export it to the local filesystem
// instead. Unfortunately, the local filesystem might apply arbitrary
// normalization to the filenames, so we need to obtain those directly.
//
// 'svn export' prints the filenames as they are written, but from reading the
// svn source code (as of revision 1868933), those filenames are encoded using
// the system locale rather than preserved byte-for-byte from the origin. For
// our purposes, that won't do, but we don't want to go mucking around with
// the user's locale settings either — that could impact error messages, and
// we don't know what locales the user has available or what LC_* variables
// their platform supports.
//
// Instead, we'll do a two-pass export: first we'll run 'svn list' to get the
// canonical filenames, then we'll 'svn export' and look for those filenames
// in the local filesystem. (If there is an encoding problem at that point, we
// would probably reject the resulting module anyway.)
remotePath := remote
if subdir != "" {
remotePath += "/" + subdir
}
out, err := Run(workDir, []string{
"svn", "list",
"--non-interactive",
"--xml",
"--incremental",
"--recursive",
"--revision", rev,
"--", remotePath,
})
if err != nil {
return err
}
type listEntry struct {
Kind string `xml:"kind,attr"`
Name string `xml:"name"`
Size int64 `xml:"size"`
}
var list struct {
Entries []listEntry `xml:"entry"`
}
if err := xml.Unmarshal(out, &list); err != nil {
return vcsErrorf("unexpected response from svn list --xml: %v\n%s", err, out)
}
exportDir := filepath.Join(workDir, "export")
// Remove any existing contents from a previous (failed) run.
if err := os.RemoveAll(exportDir); err != nil {
return err
}
defer os.RemoveAll(exportDir) // best-effort
_, err = Run(workDir, []string{
"svn", "export",
"--non-interactive",
"--quiet",
// Suppress any platform- or host-dependent transformations.
"--native-eol", "LF",
"--ignore-externals",
"--ignore-keywords",
"--revision", rev,
"--", remotePath,
exportDir,
})
if err != nil {
return err
}
// Scrape the exported files out of the filesystem and encode them in the zipfile.
// “All files in the zip file are expected to be
// nested in a single top-level directory, whose name is not specified.”
// We'll (arbitrarily) choose the base of the remote path.
basePath := path.Join(path.Base(remote), subdir)
zw := zip.NewWriter(dst)
for _, e := range list.Entries {
if e.Kind != "file" {
continue
}
zf, err := zw.Create(path.Join(basePath, e.Name))
if err != nil {
return err
}
f, err := os.Open(filepath.Join(exportDir, e.Name))
if err != nil {
if os.IsNotExist(err) {
return vcsErrorf("file reported by 'svn list', but not written by 'svn export': %s", e.Name)
}
return fmt.Errorf("error opening file created by 'svn export': %v", err)
}
n, err := io.Copy(zf, f)
f.Close()
if err != nil {
return err
}
if n != e.Size {
return vcsErrorf("file size differs between 'svn list' and 'svn export': file %s listed as %v bytes, but exported as %v bytes", e.Name, e.Size, n)
}
}
return zw.Close()
}

View File

@ -5,7 +5,7 @@
package codehost package codehost
import ( import (
"encoding/xml" "errors"
"fmt" "fmt"
"internal/lazyregexp" "internal/lazyregexp"
"io" "io"
@ -122,19 +122,20 @@ func newVCSRepo(vcs, remote string) (Repo, error) {
const vcsWorkDirType = "vcs1." const vcsWorkDirType = "vcs1."
type vcsCmd struct { type vcsCmd struct {
vcs string // vcs name "hg" vcs string // vcs name "hg"
init func(remote string) []string // cmd to init repo to track remote init func(remote string) []string // cmd to init repo to track remote
tags func(remote string) []string // cmd to list local tags tags func(remote string) []string // cmd to list local tags
tagRE *lazyregexp.Regexp // regexp to extract tag names from output of tags cmd tagRE *lazyregexp.Regexp // regexp to extract tag names from output of tags cmd
branches func(remote string) []string // cmd to list local branches branches func(remote string) []string // cmd to list local branches
branchRE *lazyregexp.Regexp // regexp to extract branch names from output of tags cmd branchRE *lazyregexp.Regexp // regexp to extract branch names from output of tags cmd
badLocalRevRE *lazyregexp.Regexp // regexp of names that must not be served out of local cache without doing fetch first badLocalRevRE *lazyregexp.Regexp // regexp of names that must not be served out of local cache without doing fetch first
statLocal func(rev, remote string) []string // cmd to stat local rev statLocal func(rev, remote string) []string // cmd to stat local rev
parseStat func(rev, out string) (*RevInfo, error) // cmd to parse output of statLocal parseStat func(rev, out string) (*RevInfo, error) // cmd to parse output of statLocal
fetch []string // cmd to fetch everything from remote fetch []string // cmd to fetch everything from remote
latest string // name of latest commit on remote (tip, HEAD, etc) latest string // name of latest commit on remote (tip, HEAD, etc)
readFile func(rev, file, remote string) []string // cmd to read rev's file readFile func(rev, file, remote string) []string // cmd to read rev's file
readZip func(rev, subdir, remote, target string) []string // cmd to read rev's subdir as zip file readZip func(rev, subdir, remote, target string) []string // cmd to read rev's subdir as zip file
doReadZip func(dst io.Writer, workDir, rev, subdir, remote string) error // arbitrary function to read rev's subdir as zip file
} }
var re = lazyregexp.New var re = lazyregexp.New
@ -191,7 +192,7 @@ var vcsCmds = map[string]*vcsCmd{
readFile: func(rev, file, remote string) []string { readFile: func(rev, file, remote string) []string {
return []string{"svn", "cat", "--", remote + "/" + file + "@" + rev} return []string{"svn", "cat", "--", remote + "/" + file + "@" + rev}
}, },
// TODO: zip doReadZip: svnReadZip,
}, },
"bzr": { "bzr": {
@ -418,7 +419,7 @@ func (r *vcsRepo) DescendsFrom(rev, tag string) (bool, error) {
} }
func (r *vcsRepo) ReadZip(rev, subdir string, maxSize int64) (zip io.ReadCloser, err error) { func (r *vcsRepo) ReadZip(rev, subdir string, maxSize int64) (zip io.ReadCloser, err error) {
if r.cmd.readZip == nil { if r.cmd.readZip == nil && r.cmd.doReadZip == nil {
return nil, vcsErrorf("ReadZip not implemented for %s", r.cmd.vcs) return nil, vcsErrorf("ReadZip not implemented for %s", r.cmd.vcs)
} }
@ -435,7 +436,17 @@ func (r *vcsRepo) ReadZip(rev, subdir string, maxSize int64) (zip io.ReadCloser,
if err != nil { if err != nil {
return nil, err return nil, err
} }
if r.cmd.vcs == "fossil" { if r.cmd.doReadZip != nil {
lw := &limitedWriter{
W: f,
N: maxSize,
ErrLimitReached: errors.New("ReadZip: encoded file exceeds allowed size"),
}
err = r.cmd.doReadZip(lw, r.dir, rev, subdir, r.remote)
if err == nil {
_, err = f.Seek(0, io.SeekStart)
}
} else if r.cmd.vcs == "fossil" {
// If you run // If you run
// fossil zip -R .fossil --name prefix trunk /tmp/x.zip // fossil zip -R .fossil --name prefix trunk /tmp/x.zip
// fossil fails with "unable to create directory /tmp" [sic]. // fossil fails with "unable to create directory /tmp" [sic].
@ -502,31 +513,6 @@ func hgParseStat(rev, out string) (*RevInfo, error) {
return info, nil return info, nil
} }
func svnParseStat(rev, out string) (*RevInfo, error) {
var log struct {
Logentry struct {
Revision int64 `xml:"revision,attr"`
Date string `xml:"date"`
} `xml:"logentry"`
}
if err := xml.Unmarshal([]byte(out), &log); err != nil {
return nil, vcsErrorf("unexpected response from svn log --xml: %v\n%s", err, out)
}
t, err := time.Parse(time.RFC3339, log.Logentry.Date)
if err != nil {
return nil, vcsErrorf("unexpected response from svn log --xml: %v\n%s", err, out)
}
info := &RevInfo{
Name: fmt.Sprintf("%d", log.Logentry.Revision),
Short: fmt.Sprintf("%012d", log.Logentry.Revision),
Time: t.UTC(),
Version: rev,
}
return info, nil
}
func bzrParseStat(rev, out string) (*RevInfo, error) { func bzrParseStat(rev, out string) (*RevInfo, error) {
var revno int64 var revno int64
var tm time.Time var tm time.Time
@ -606,3 +592,25 @@ func fossilParseStat(rev, out string) (*RevInfo, error) {
} }
return nil, vcsErrorf("unexpected response from fossil info: %q", out) return nil, vcsErrorf("unexpected response from fossil info: %q", out)
} }
type limitedWriter struct {
W io.Writer
N int64
ErrLimitReached error
}
func (l *limitedWriter) Write(p []byte) (n int, err error) {
if l.N > 0 {
max := len(p)
if l.N < int64(max) {
max = int(l.N)
}
n, err = l.W.Write(p[:max])
l.N -= int64(n)
if err != nil || n >= len(p) {
return n, err
}
}
return n, l.ErrLimitReached
}

View File

@ -16,9 +16,10 @@ import (
"time" "time"
"cmd/go/internal/modfetch/codehost" "cmd/go/internal/modfetch/codehost"
"cmd/go/internal/modfile"
"cmd/go/internal/module" "golang.org/x/mod/modfile"
"cmd/go/internal/semver" "golang.org/x/mod/module"
"golang.org/x/mod/semver"
) )
// A codeRepo implements modfetch.Repo using an underlying codehost.Repo. // A codeRepo implements modfetch.Repo using an underlying codehost.Repo.

View File

@ -6,7 +6,11 @@ package modfetch
import ( import (
"archive/zip" "archive/zip"
"crypto/sha256"
"encoding/hex"
"hash"
"internal/testenv" "internal/testenv"
"io"
"io/ioutil" "io/ioutil"
"log" "log"
"os" "os"
@ -17,6 +21,8 @@ import (
"cmd/go/internal/cfg" "cmd/go/internal/cfg"
"cmd/go/internal/modfetch/codehost" "cmd/go/internal/modfetch/codehost"
"golang.org/x/mod/sumdb/dirhash"
) )
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
@ -52,20 +58,22 @@ var altVgotests = map[string]string{
} }
type codeRepoTest struct { type codeRepoTest struct {
vcs string vcs string
path string path string
lookerr string lookErr string
mpath string mpath string
rev string rev string
err string err string
version string version string
name string name string
short string short string
time time.Time time time.Time
gomod string gomod string
gomoderr string gomodErr string
zip []string zip []string
ziperr string zipErr string
zipSum string
zipFileHash string
} }
var codeRepoTests = []codeRepoTest{ var codeRepoTests = []codeRepoTest{
@ -82,6 +90,8 @@ var codeRepoTests = []codeRepoTest{
"README.md", "README.md",
"pkg/p.go", "pkg/p.go",
}, },
zipSum: "h1:zVEjciLdlk/TPWCOyZo7k24T+tOKRQC+u8MKq/xS80I=",
zipFileHash: "738a00ddbfe8c329dce6b48e1f23c8e22a92db50f3cfb2653caa0d62676bc09c",
}, },
{ {
vcs: "git", vcs: "git",
@ -96,6 +106,8 @@ var codeRepoTests = []codeRepoTest{
"README.md", "README.md",
"pkg/p.go", "pkg/p.go",
}, },
zipSum: "h1:nOznk2xKsLGkTnXe0q9t1Ewt9jxK+oadtafSUqHM3Ec=",
zipFileHash: "bacb08f391e29d2eaaef8281b5c129ee6d890e608ee65877e0003c0181a766c8",
}, },
{ {
vcs: "git", vcs: "git",
@ -116,6 +128,8 @@ var codeRepoTests = []codeRepoTest{
"README.md", "README.md",
"pkg/p.go", "pkg/p.go",
}, },
zipSum: "h1:e040hOoWGeuJLawDjK9DW6med+cz9FxMFYDMOVG8ctQ=",
zipFileHash: "74caab65cfbea427c341fa815f3bb0378681d8f0e3cf62a7f207014263ec7be3",
}, },
{ {
vcs: "git", vcs: "git",
@ -140,6 +154,8 @@ var codeRepoTests = []codeRepoTest{
"README.md", "README.md",
"pkg/p.go", "pkg/p.go",
}, },
zipSum: "h1:e040hOoWGeuJLawDjK9DW6med+cz9FxMFYDMOVG8ctQ=",
zipFileHash: "74caab65cfbea427c341fa815f3bb0378681d8f0e3cf62a7f207014263ec7be3",
}, },
{ {
vcs: "git", vcs: "git",
@ -201,6 +217,8 @@ var codeRepoTests = []codeRepoTest{
"pkg/p.go", "pkg/p.go",
"LICENSE", "LICENSE",
}, },
zipSum: "h1:iMsJ/9uQsk6MnZNnJK311f11QiSlmN92Q2aSjCywuJY=",
zipFileHash: "95801bfa69c5197ae809af512946d22f22850068527cd78100ae3f176bc8043b",
}, },
{ {
vcs: "git", vcs: "git",
@ -217,16 +235,20 @@ var codeRepoTests = []codeRepoTest{
"go.mod", "go.mod",
"pkg/p.go", "pkg/p.go",
}, },
zipSum: "h1:M69k7q+8bQ+QUpHov45Z/NoR8rj3DsQJUnXLWvf01+Q=",
zipFileHash: "58af45fb248d320ea471f568e006379e2b8d71d6d1663f9b19b2e00fd9ac9265",
}, },
{ {
vcs: "git", vcs: "git",
path: "github.com/rsc/vgotest1/v2", path: "github.com/rsc/vgotest1/v2",
rev: "v2.0.1", rev: "v2.0.1",
version: "v2.0.1", version: "v2.0.1",
name: "ea65f87c8f52c15ea68f3bdd9925ef17e20d91e9", name: "ea65f87c8f52c15ea68f3bdd9925ef17e20d91e9",
short: "ea65f87c8f52", short: "ea65f87c8f52",
time: time.Date(2018, 2, 19, 23, 14, 23, 0, time.UTC), time: time.Date(2018, 2, 19, 23, 14, 23, 0, time.UTC),
gomod: "module \"github.com/rsc/vgotest1/v2\" // root go.mod\n", gomod: "module \"github.com/rsc/vgotest1/v2\" // root go.mod\n",
zipSum: "h1:QmgYy/zt+uoWhDpcsgrSVzYFvKtBEjl5zT/FRz9GTzA=",
zipFileHash: "1aedf1546d322a0121879ddfd6d0e8bfbd916d2cafbeb538ddb440e04b04b9ef",
}, },
{ {
vcs: "git", vcs: "git",
@ -249,25 +271,29 @@ var codeRepoTests = []codeRepoTest{
err: "github.com/rsc/vgotest1/go.mod and .../v2/go.mod both have .../v2 module paths at revision v2.0.4", err: "github.com/rsc/vgotest1/go.mod and .../v2/go.mod both have .../v2 module paths at revision v2.0.4",
}, },
{ {
vcs: "git", vcs: "git",
path: "github.com/rsc/vgotest1/v2", path: "github.com/rsc/vgotest1/v2",
rev: "v2.0.5", rev: "v2.0.5",
version: "v2.0.5", version: "v2.0.5",
name: "2f615117ce481c8efef46e0cc0b4b4dccfac8fea", name: "2f615117ce481c8efef46e0cc0b4b4dccfac8fea",
short: "2f615117ce48", short: "2f615117ce48",
time: time.Date(2018, 2, 20, 0, 3, 59, 0, time.UTC), time: time.Date(2018, 2, 20, 0, 3, 59, 0, time.UTC),
gomod: "module \"github.com/rsc/vgotest1/v2\" // v2/go.mod\n", gomod: "module \"github.com/rsc/vgotest1/v2\" // v2/go.mod\n",
zipSum: "h1:RIEb9q1SUSEQOzMn0zfl/LQxGFWlhWEAdeEguf1MLGU=",
zipFileHash: "7d92c2c328c5e9b0694101353705d5843746ec1d93a1e986d0da54c8a14dfe6d",
}, },
{ {
// redirect to github // redirect to github
vcs: "git", vcs: "git",
path: "rsc.io/quote", path: "rsc.io/quote",
rev: "v1.0.0", rev: "v1.0.0",
version: "v1.0.0", version: "v1.0.0",
name: "f488df80bcdbd3e5bafdc24ad7d1e79e83edd7e6", name: "f488df80bcdbd3e5bafdc24ad7d1e79e83edd7e6",
short: "f488df80bcdb", short: "f488df80bcdb",
time: time.Date(2018, 2, 14, 0, 45, 20, 0, time.UTC), time: time.Date(2018, 2, 14, 0, 45, 20, 0, time.UTC),
gomod: "module \"rsc.io/quote\"\n", gomod: "module \"rsc.io/quote\"\n",
zipSum: "h1:haUSojyo3j2M9g7CEUFG8Na09dtn7QKxvPGaPVQdGwM=",
zipFileHash: "5c08ba2c09a364f93704aaa780e7504346102c6ef4fe1333a11f09904a732078",
}, },
{ {
// redirect to static hosting proxy // redirect to static hosting proxy
@ -281,22 +307,26 @@ var codeRepoTests = []codeRepoTest{
}, },
{ {
// redirect to googlesource // redirect to googlesource
vcs: "git", vcs: "git",
path: "golang.org/x/text", path: "golang.org/x/text",
rev: "4e4a3210bb", rev: "4e4a3210bb",
version: "v0.3.1-0.20180208041248-4e4a3210bb54", version: "v0.3.1-0.20180208041248-4e4a3210bb54",
name: "4e4a3210bb54bb31f6ab2cdca2edcc0b50c420c1", name: "4e4a3210bb54bb31f6ab2cdca2edcc0b50c420c1",
short: "4e4a3210bb54", short: "4e4a3210bb54",
time: time.Date(2018, 2, 8, 4, 12, 48, 0, time.UTC), time: time.Date(2018, 2, 8, 4, 12, 48, 0, time.UTC),
zipSum: "h1:Yxu6pHX9X2RECiuw/Q5/4uvajuaowck8zOFKXgbfNBk=",
zipFileHash: "ac2c165a5c10aa5a7545dea60a08e019270b982fa6c8bdcb5943931de64922fe",
}, },
{ {
vcs: "git", vcs: "git",
path: "github.com/pkg/errors", path: "github.com/pkg/errors",
rev: "v0.8.0", rev: "v0.8.0",
version: "v0.8.0", version: "v0.8.0",
name: "645ef00459ed84a119197bfb8d8205042c6df63d", name: "645ef00459ed84a119197bfb8d8205042c6df63d",
short: "645ef00459ed", short: "645ef00459ed",
time: time.Date(2016, 9, 29, 1, 48, 1, 0, time.UTC), time: time.Date(2016, 9, 29, 1, 48, 1, 0, time.UTC),
zipSum: "h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=",
zipFileHash: "e4fa69ba057356614edbc1da881a7d3ebb688505be49f65965686bcb859e2fae",
}, },
{ {
// package in subdirectory - custom domain // package in subdirectory - custom domain
@ -304,7 +334,7 @@ var codeRepoTests = []codeRepoTest{
// but gopkg.in is special. // but gopkg.in is special.
vcs: "git", vcs: "git",
path: "gopkg.in/yaml.v2/abc", path: "gopkg.in/yaml.v2/abc",
lookerr: "invalid module path \"gopkg.in/yaml.v2/abc\"", lookErr: "invalid module path \"gopkg.in/yaml.v2/abc\"",
}, },
{ {
// package in subdirectory - github // package in subdirectory - github
@ -315,54 +345,64 @@ var codeRepoTests = []codeRepoTest{
err: "missing github.com/rsc/quote/buggy/go.mod at revision c4d4236f9242", err: "missing github.com/rsc/quote/buggy/go.mod at revision c4d4236f9242",
}, },
{ {
vcs: "git", vcs: "git",
path: "gopkg.in/yaml.v2", path: "gopkg.in/yaml.v2",
rev: "d670f940", rev: "d670f940",
version: "v2.0.0", version: "v2.0.0",
name: "d670f9405373e636a5a2765eea47fac0c9bc91a4", name: "d670f9405373e636a5a2765eea47fac0c9bc91a4",
short: "d670f9405373", short: "d670f9405373",
time: time.Date(2018, 1, 9, 11, 43, 31, 0, time.UTC), time: time.Date(2018, 1, 9, 11, 43, 31, 0, time.UTC),
gomod: "module gopkg.in/yaml.v2\n", gomod: "module gopkg.in/yaml.v2\n",
zipSum: "h1:uUkhRGrsEyx/laRdeS6YIQKIys8pg+lRSRdVMTYjivs=",
zipFileHash: "7b0a141b1b0b49772ab4eecfd11dfd6609a94a5e868cab04a3abb1861ffaa877",
}, },
{ {
vcs: "git", vcs: "git",
path: "gopkg.in/check.v1", path: "gopkg.in/check.v1",
rev: "20d25e280405", rev: "20d25e280405",
version: "v1.0.0-20161208181325-20d25e280405", version: "v1.0.0-20161208181325-20d25e280405",
name: "20d25e2804050c1cd24a7eea1e7a6447dd0e74ec", name: "20d25e2804050c1cd24a7eea1e7a6447dd0e74ec",
short: "20d25e280405", short: "20d25e280405",
time: time.Date(2016, 12, 8, 18, 13, 25, 0, time.UTC), time: time.Date(2016, 12, 8, 18, 13, 25, 0, time.UTC),
gomod: "module gopkg.in/check.v1\n", gomod: "module gopkg.in/check.v1\n",
zipSum: "h1:829vOVxxusYHC+IqBtkX5mbKtsY9fheQiQn0MZRVLfQ=",
zipFileHash: "9e7cb3f4f1e66d722306442b0dbe1f6f43d74d1736d54c510537bdfb1d6f432f",
}, },
{ {
vcs: "git", vcs: "git",
path: "gopkg.in/yaml.v2", path: "gopkg.in/yaml.v2",
rev: "v2", rev: "v2",
version: "v2.2.5-0.20191002202810-970885f01c8b", version: "v2.2.5-0.20191002202810-970885f01c8b",
name: "970885f01c8bc1fecb7ab1c8ce8e7609bda45530", name: "970885f01c8bc1fecb7ab1c8ce8e7609bda45530",
short: "970885f01c8b", short: "970885f01c8b",
time: time.Date(2019, 10, 2, 20, 28, 10, 0, time.UTC), time: time.Date(2019, 10, 2, 20, 28, 10, 0, time.UTC),
gomod: "module \"gopkg.in/yaml.v2\"\n\nrequire (\n\t\"gopkg.in/check.v1\" v0.0.0-20161208181325-20d25e280405\n)\n", gomod: "module \"gopkg.in/yaml.v2\"\n\nrequire (\n\t\"gopkg.in/check.v1\" v0.0.0-20161208181325-20d25e280405\n)\n",
zipSum: "h1:c7zdkYUaqShimBvZzvhOA+Absl0aDaGKX267vSm0Z7E=",
zipFileHash: "5856a108e1aa8ec9c35f4479f8e806652b326b648c80abd08fc403707f4eb5f1",
}, },
{ {
vcs: "git", vcs: "git",
path: "vcs-test.golang.org/go/mod/gitrepo1", path: "vcs-test.golang.org/go/mod/gitrepo1",
rev: "master", rev: "master",
version: "v1.2.4-annotated", version: "v1.2.4-annotated",
name: "ede458df7cd0fdca520df19a33158086a8a68e81", name: "ede458df7cd0fdca520df19a33158086a8a68e81",
short: "ede458df7cd0", short: "ede458df7cd0",
time: time.Date(2018, 4, 17, 19, 43, 22, 0, time.UTC), time: time.Date(2018, 4, 17, 19, 43, 22, 0, time.UTC),
gomod: "module vcs-test.golang.org/go/mod/gitrepo1\n", gomod: "module vcs-test.golang.org/go/mod/gitrepo1\n",
zipSum: "h1:YJYZRsM9BHFTlVr8YADjT0cJH8uFIDtoc5NLiVqZEx8=",
zipFileHash: "c15e49d58b7a4c37966cbe5bc01a0330cd5f2927e990e1839bda1d407766d9c5",
}, },
{ {
vcs: "git", vcs: "git",
path: "gopkg.in/natefinch/lumberjack.v2", path: "gopkg.in/natefinch/lumberjack.v2",
rev: "latest", rev: "latest",
version: "v2.0.0-20170531160350-a96e63847dc3", version: "v2.0.0-20170531160350-a96e63847dc3",
name: "a96e63847dc3c67d17befa69c303767e2f84e54f", name: "a96e63847dc3c67d17befa69c303767e2f84e54f",
short: "a96e63847dc3", short: "a96e63847dc3",
time: time.Date(2017, 5, 31, 16, 3, 50, 0, time.UTC), time: time.Date(2017, 5, 31, 16, 3, 50, 0, time.UTC),
gomod: "module gopkg.in/natefinch/lumberjack.v2\n", gomod: "module gopkg.in/natefinch/lumberjack.v2\n",
zipSum: "h1:AFxeG48hTWHhDTQDk/m2gorfVHUEa9vo3tp3D7TzwjI=",
zipFileHash: "b5de0da7bbbec76709eef1ac71b6c9ff423b9fbf3bb97b56743450d4937b06d5",
}, },
{ {
vcs: "git", vcs: "git",
@ -381,14 +421,16 @@ var codeRepoTests = []codeRepoTest{
gomod: "module gopkg.in/natefinch/lumberjack.v2\n", gomod: "module gopkg.in/natefinch/lumberjack.v2\n",
}, },
{ {
vcs: "git", vcs: "git",
path: "vcs-test.golang.org/go/v2module/v2", path: "vcs-test.golang.org/go/v2module/v2",
rev: "v2.0.0", rev: "v2.0.0",
version: "v2.0.0", version: "v2.0.0",
name: "203b91c896acd173aa719e4cdcb7d463c4b090fa", name: "203b91c896acd173aa719e4cdcb7d463c4b090fa",
short: "203b91c896ac", short: "203b91c896ac",
time: time.Date(2019, 4, 3, 15, 52, 15, 0, time.UTC), time: time.Date(2019, 4, 3, 15, 52, 15, 0, time.UTC),
gomod: "module vcs-test.golang.org/go/v2module/v2\n\ngo 1.12\n", gomod: "module vcs-test.golang.org/go/v2module/v2\n\ngo 1.12\n",
zipSum: "h1:JItBZ+gwA5WvtZEGEbuDL4lUttGtLrs53lmdurq3bOg=",
zipFileHash: "9ea9ae1673cffcc44b7fdd3cc89953d68c102449b46c982dbf085e4f2e394da5",
}, },
} }
@ -411,21 +453,23 @@ func TestCodeRepo(t *testing.T) {
} }
repo, err := Lookup("direct", tt.path) repo, err := Lookup("direct", tt.path)
if tt.lookerr != "" { if tt.lookErr != "" {
if err != nil && err.Error() == tt.lookerr { if err != nil && err.Error() == tt.lookErr {
return return
} }
t.Errorf("Lookup(%q): %v, want error %q", tt.path, err, tt.lookerr) t.Errorf("Lookup(%q): %v, want error %q", tt.path, err, tt.lookErr)
} }
if err != nil { if err != nil {
t.Fatalf("Lookup(%q): %v", tt.path, err) t.Fatalf("Lookup(%q): %v", tt.path, err)
} }
if tt.mpath == "" { if tt.mpath == "" {
tt.mpath = tt.path tt.mpath = tt.path
} }
if mpath := repo.ModulePath(); mpath != tt.mpath { if mpath := repo.ModulePath(); mpath != tt.mpath {
t.Errorf("repo.ModulePath() = %q, want %q", mpath, tt.mpath) t.Errorf("repo.ModulePath() = %q, want %q", mpath, tt.mpath)
} }
info, err := repo.Stat(tt.rev) info, err := repo.Stat(tt.rev)
if err != nil { if err != nil {
if tt.err != "" { if tt.err != "" {
@ -451,56 +495,86 @@ func TestCodeRepo(t *testing.T) {
if !info.Time.Equal(tt.time) { if !info.Time.Equal(tt.time) {
t.Errorf("info.Time = %v, want %v", info.Time, tt.time) t.Errorf("info.Time = %v, want %v", info.Time, tt.time)
} }
if tt.gomod != "" || tt.gomoderr != "" {
if tt.gomod != "" || tt.gomodErr != "" {
data, err := repo.GoMod(tt.version) data, err := repo.GoMod(tt.version)
if err != nil && tt.gomoderr == "" { if err != nil && tt.gomodErr == "" {
t.Errorf("repo.GoMod(%q): %v", tt.version, err) t.Errorf("repo.GoMod(%q): %v", tt.version, err)
} else if err != nil && tt.gomoderr != "" { } else if err != nil && tt.gomodErr != "" {
if err.Error() != tt.gomoderr { if err.Error() != tt.gomodErr {
t.Errorf("repo.GoMod(%q): %v, want %q", tt.version, err, tt.gomoderr) t.Errorf("repo.GoMod(%q): %v, want %q", tt.version, err, tt.gomodErr)
} }
} else if tt.gomoderr != "" { } else if tt.gomodErr != "" {
t.Errorf("repo.GoMod(%q) = %q, want error %q", tt.version, data, tt.gomoderr) t.Errorf("repo.GoMod(%q) = %q, want error %q", tt.version, data, tt.gomodErr)
} else if string(data) != tt.gomod { } else if string(data) != tt.gomod {
t.Errorf("repo.GoMod(%q) = %q, want %q", tt.version, data, tt.gomod) t.Errorf("repo.GoMod(%q) = %q, want %q", tt.version, data, tt.gomod)
} }
} }
if tt.zip != nil || tt.ziperr != "" {
needHash := !testing.Short() && (tt.zipFileHash != "" || tt.zipSum != "")
if tt.zip != nil || tt.zipErr != "" || needHash {
f, err := ioutil.TempFile(tmpdir, tt.version+".zip.") f, err := ioutil.TempFile(tmpdir, tt.version+".zip.")
if err != nil { if err != nil {
t.Fatalf("ioutil.TempFile: %v", err) t.Fatalf("ioutil.TempFile: %v", err)
} }
zipfile := f.Name() zipfile := f.Name()
err = repo.Zip(f, tt.version) defer func() {
f.Close()
os.Remove(zipfile)
}()
var w io.Writer
var h hash.Hash
if needHash {
h = sha256.New()
w = io.MultiWriter(f, h)
} else {
w = f
}
err = repo.Zip(w, tt.version)
f.Close() f.Close()
if err != nil { if err != nil {
if tt.ziperr != "" { if tt.zipErr != "" {
if err.Error() == tt.ziperr { if err.Error() == tt.zipErr {
return return
} }
t.Fatalf("repo.Zip(%q): %v, want error %q", tt.version, err, tt.ziperr) t.Fatalf("repo.Zip(%q): %v, want error %q", tt.version, err, tt.zipErr)
} }
t.Fatalf("repo.Zip(%q): %v", tt.version, err) t.Fatalf("repo.Zip(%q): %v", tt.version, err)
} }
if tt.ziperr != "" { if tt.zipErr != "" {
t.Errorf("repo.Zip(%q): success, want error %q", tt.version, tt.ziperr) t.Errorf("repo.Zip(%q): success, want error %q", tt.version, tt.zipErr)
} }
prefix := tt.path + "@" + tt.version + "/"
z, err := zip.OpenReader(zipfile) if tt.zip != nil {
if err != nil { prefix := tt.path + "@" + tt.version + "/"
t.Fatalf("open zip %s: %v", zipfile, err) z, err := zip.OpenReader(zipfile)
} if err != nil {
var names []string t.Fatalf("open zip %s: %v", zipfile, err)
for _, file := range z.File { }
if !strings.HasPrefix(file.Name, prefix) { var names []string
t.Errorf("zip entry %v does not start with prefix %v", file.Name, prefix) for _, file := range z.File {
continue if !strings.HasPrefix(file.Name, prefix) {
t.Errorf("zip entry %v does not start with prefix %v", file.Name, prefix)
continue
}
names = append(names, file.Name[len(prefix):])
}
z.Close()
if !reflect.DeepEqual(names, tt.zip) {
t.Fatalf("zip = %v\nwant %v\n", names, tt.zip)
} }
names = append(names, file.Name[len(prefix):])
} }
z.Close()
if !reflect.DeepEqual(names, tt.zip) { if needHash {
t.Fatalf("zip = %v\nwant %v\n", names, tt.zip) sum, err := dirhash.HashZip(zipfile, dirhash.Hash1)
if err != nil {
t.Errorf("repo.Zip(%q): %v", tt.version, err)
} else if sum != tt.zipSum {
t.Errorf("repo.Zip(%q): got file with sum %q, want %q", tt.version, sum, tt.zipSum)
} else if zipFileHash := hex.EncodeToString(h.Sum(nil)); zipFileHash != tt.zipFileHash {
t.Errorf("repo.Zip(%q): got file with hash %q, want %q (but content has correct sum)", tt.version, zipFileHash, tt.zipFileHash)
}
} }
} }
} }
@ -508,26 +582,26 @@ func TestCodeRepo(t *testing.T) {
t.Run(strings.ReplaceAll(tt.path, "/", "_")+"/"+tt.rev, f(tt)) t.Run(strings.ReplaceAll(tt.path, "/", "_")+"/"+tt.rev, f(tt))
if strings.HasPrefix(tt.path, vgotest1git) { if strings.HasPrefix(tt.path, vgotest1git) {
for vcs, alt := range altVgotests { for vcs, alt := range altVgotests {
// Note: Communicating with f through tt; should be cleaned up. altTest := tt
old := tt altTest.vcs = vcs
tt.vcs = vcs altTest.path = alt + strings.TrimPrefix(altTest.path, vgotest1git)
tt.path = alt + strings.TrimPrefix(tt.path, vgotest1git) if strings.HasPrefix(altTest.mpath, vgotest1git) {
if strings.HasPrefix(tt.mpath, vgotest1git) { altTest.mpath = alt + strings.TrimPrefix(altTest.mpath, vgotest1git)
tt.mpath = alt + strings.TrimPrefix(tt.mpath, vgotest1git)
} }
var m map[string]string var m map[string]string
if alt == vgotest1hg { if alt == vgotest1hg {
m = hgmap m = hgmap
} }
tt.version = remap(tt.version, m) altTest.version = remap(altTest.version, m)
tt.name = remap(tt.name, m) altTest.name = remap(altTest.name, m)
tt.short = remap(tt.short, m) altTest.short = remap(altTest.short, m)
tt.rev = remap(tt.rev, m) altTest.rev = remap(altTest.rev, m)
tt.err = remap(tt.err, m) altTest.err = remap(altTest.err, m)
tt.gomoderr = remap(tt.gomoderr, m) altTest.gomodErr = remap(altTest.gomodErr, m)
tt.ziperr = remap(tt.ziperr, m) altTest.zipErr = remap(altTest.zipErr, m)
t.Run(strings.ReplaceAll(tt.path, "/", "_")+"/"+tt.rev, f(tt)) altTest.zipSum = ""
tt = old altTest.zipFileHash = ""
t.Run(strings.ReplaceAll(altTest.path, "/", "_")+"/"+altTest.rev, f(altTest))
} }
} }
} }

View File

@ -19,10 +19,11 @@ import (
"cmd/go/internal/base" "cmd/go/internal/base"
"cmd/go/internal/cfg" "cmd/go/internal/cfg"
"cmd/go/internal/dirhash"
"cmd/go/internal/module"
"cmd/go/internal/par" "cmd/go/internal/par"
"cmd/go/internal/renameio" "cmd/go/internal/renameio"
"golang.org/x/mod/module"
"golang.org/x/mod/sumdb/dirhash"
) )
var downloadCache par.Cache var downloadCache par.Cache

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