[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)
if m == nil {
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.
}

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.
</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>
<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.
</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>
<p>

View File

@ -56,6 +56,14 @@ TODO
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
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>
<h3 id="nacl">Native Client (NaCl)</h3>
@ -133,6 +141,10 @@ TODO
trimming the ".mod" extension and appending ".sum".
</p>
<p><!-- golang.org/issue/26092 -->
The <code>go</code> command now supports Subversion repositories in module mode.
</p>
<h2 id="runtime">Runtime</h2>
<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,
// this calls the underlying ReadFrom without buffering.
func (b *Writer) ReadFrom(r io.Reader) (n int64, err error) {
if b.err != nil {
return 0, b.err
}
if b.Buffered() == 0 {
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

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) {
// Optimal case is where the underlying reader implements io.WriterTo
srcBuf := bytes.NewBuffer(make([]byte, 8192))

View File

@ -130,27 +130,27 @@ TEXT foo(SB),DUPOK|NOSPLIT,$0
// {
// outcode(int($1), &$2, 0, &$4);
// }
MOVW FCR0, R1
MOVW FCR31, R1 // 4441f800
// LMOVW freg ',' fpscr
// {
// outcode(int($1), &$2, 0, &$4);
// }
MOVW R1, FCR0
MOVW R1, FCR31 // 44c1f800
// LMOVW rreg ',' mreg
// {
// outcode(int($1), &$2, 0, &$4);
// }
MOVW R1, M1
MOVV R1, M1
MOVW R1, M1 // 40810800
MOVV R1, M1 // 40a10800
// LMOVW mreg ',' rreg
// {
// outcode(int($1), &$2, 0, &$4);
// }
MOVW M1, R1
MOVV M1, R1
MOVW M1, R1 // 40010800
MOVV M1, R1 // 40210800
//
@ -406,6 +406,7 @@ label4:
NEGW R1, R2 // 00011023
NEGV R1, R2 // 0001102f
RET
// 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/gc.Node %v": "",
"map[cmd/compile/internal/ssa.ID]uint32 %v": "",
"map[int64]uint32 %v": "",
"math/big.Accuracy %s": "",
"reflect.Type %s": "",
"rune %#U": "",
"rune %c": "",
"rune %q": "",
"string %-*s": "",
"string %-16s": "",
"string %-6s": "",
"string %q": "",
"string %s": "",
"string %v": "",
"time.Duration %d": "",
"time.Duration %v": "",
"uint %04x": "",
"uint %5d": "",
"uint %d": "",
"uint %x": "",
"uint16 %d": "",
"uint16 %x": "",
"uint32 %#U": "",
"uint32 %#x": "",
"uint32 %d": "",
"uint32 %v": "",
"uint32 %x": "",
"uint64 %08x": "",
"uint64 %b": "",
"uint64 %d": "",
"uint64 %x": "",
"uint8 %d": "",
"uint8 %v": "",
"uint8 %x": "",
"uintptr %d": "",
"map[int64]uint32 %v": "",
"math/big.Accuracy %s": "",
"reflect.Type %s": "",
"rune %#U": "",
"rune %c": "",
"rune %q": "",
"string %-*s": "",
"string %-16s": "",
"string %-6s": "",
"string %q": "",
"string %s": "",
"string %v": "",
"time.Duration %d": "",
"time.Duration %v": "",
"uint %04x": "",
"uint %5d": "",
"uint %d": "",
"uint %x": "",
"uint16 %d": "",
"uint16 %x": "",
"uint32 %#U": "",
"uint32 %#x": "",
"uint32 %d": "",
"uint32 %v": "",
"uint32 %x": "",
"uint64 %08x": "",
"uint64 %b": "",
"uint64 %d": "",
"uint64 %x": "",
"uint8 %d": "",
"uint8 %v": "",
"uint8 %x": "",
"uintptr %d": "",
}

View File

@ -17,7 +17,6 @@ func Init(arch *gc.Arch) {
arch.MAXWIDTH = 1 << 50
arch.ZeroRange = zerorange
arch.ZeroAuto = zeroAuto
arch.Ginsnop = 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
}
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 {
// This is a hardware nop (1-byte 0x90) instruction,
// 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)
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg0()
case ssa.OpAMD64XCHGL, ssa.OpAMD64XCHGQ:
case ssa.OpAMD64XCHGB, ssa.OpAMD64XCHGL, ssa.OpAMD64XCHGQ:
r := v.Reg0()
if r != v.Args[0].Reg() {
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.SoftFloat = objabi.GOARM == 5
arch.ZeroRange = zerorange
arch.ZeroAuto = zeroAuto
arch.Ginsnop = 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
}
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 {
p := pp.Prog(arm.AAND)
p.From.Type = obj.TYPE_REG

View File

@ -17,7 +17,6 @@ func Init(arch *gc.Arch) {
arch.PadFrame = padframe
arch.ZeroRange = zerorange
arch.ZeroAuto = zeroAuto
arch.Ginsnop = 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
}
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 {
p := pp.Prog(arm64.AHINT)
p.From.Type = obj.TYPE_CONST

View File

@ -452,6 +452,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
ssa.OpARM64MOVDstore,
ssa.OpARM64FMOVSstore,
ssa.OpARM64FMOVDstore,
ssa.OpARM64STLRB,
ssa.OpARM64STLR,
ssa.OpARM64STLRW:
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
// for all values in the block before SSAGenBlock.
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

View File

@ -179,11 +179,6 @@ func (a *Mpflt) Neg() {
}
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)
if err != nil {
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)
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",
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())
@ -3366,6 +3366,12 @@ func init() {
return nil
},
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",
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())
@ -4099,7 +4105,7 @@ func (s *state) openDeferRecord(n *Node) {
// runtime panic code to use. But in the defer exit code, we will
// call the function directly if it is a static function.
closureVal := s.expr(fn)
closure := s.openDeferSave(fn, fn.Type, closureVal)
closure := s.openDeferSave(nil, fn.Type, closureVal)
opendefer.closureNode = closure.Aux.(*Node)
if !(fn.Op == ONAME && fn.Class() == PFUNC) {
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
// runtime panic code to use. But in the defer exit code, we will
// call the method directly.
closure := s.openDeferSave(fn, fn.Type, closureVal)
closure := s.openDeferSave(nil, fn.Type, closureVal)
opendefer.closureNode = closure.Aux.(*Node)
} else {
if fn.Op != ODOTINTER {
Fatalf("OCALLINTER: n.Left not an ODOTINTER: %v", fn.Op)
}
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
// as a pointer for GC purposes.
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)
}
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)
argNodes = append(argNodes, v.Aux.(*Node))
}
@ -4144,13 +4155,22 @@ func (s *state) openDeferRecord(n *Node) {
s.store(types.Types[TUINT8], s.deferBitsAddr, newDeferBits)
}
// openDeferSave generates SSA nodes to store a value val (with type t) for an
// open-coded defer on the stack at an explicit autotmp location, so it can be
// reloaded and used for the appropriate call on exit. n is the associated node,
// which is only needed if the associated type is non-SSAable. It returns an SSA
// value representing a pointer to the stack location.
// openDeferSave generates SSA nodes to store a value (with type t) for an
// open-coded defer at an explicit autotmp location on the stack, so it can be
// reloaded and used for the appropriate call on exit. If type t is SSAable, then
// val must be non-nil (and n should be nil) and val is the value to be stored. If
// 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 {
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)
var addrArgTemp *ssa.Value
// 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.
argTemp.Name.SetNeedzero(true)
}
if !canSSAType(t) {
if n.Op != ONAME {
panic(fmt.Sprintf("Non-SSAable value should be a named location: %v", n))
}
if !canSSA {
a := s.addr(n, false)
s.move(t, addrArgTemp, a)
return addrArgTemp

View File

@ -32,7 +32,7 @@ func typecheckTypeSwitch(n *Node) {
// declaration itself. So if there are no cases, we won't
// notice that it went unused.
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

View File

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

View File

@ -50,10 +50,10 @@ func walk(fn *Node) {
if defn.Left.Name.Used() {
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
} 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
// to walkexpr, which leads us back here again. Use n.Opt to
// prevent infinite loops.
if n.Opt() == &walkCheckPtrArithmeticMarker {
if opt := n.Opt(); opt == &walkCheckPtrArithmeticMarker {
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)
defer n.SetOpt(nil)

View File

@ -20,7 +20,6 @@ func Init(arch *gc.Arch) {
arch.MAXWIDTH = (1 << 31) - 1
arch.SoftFloat = (objabi.GOMIPS == "softfloat")
arch.ZeroRange = zerorange
arch.ZeroAuto = zeroAuto
arch.Ginsnop = ginsnop
arch.Ginsnopdefer = ginsnop
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
}
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 {
p := pp.Prog(mips.ANOR)
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.Sym = gc.ExtendCheckFunc[v.AuxInt]
s.UseArgs(12) // space used in callee args area by assembly stubs
case ssa.OpMIPSLoweredAtomicLoad:
case ssa.OpMIPSLoweredAtomicLoad8,
ssa.OpMIPSLoweredAtomicLoad32:
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.Reg = v.Args[0].Reg()
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg0()
s.Prog(mips.ASYNC)
case ssa.OpMIPSLoweredAtomicStore:
case ssa.OpMIPSLoweredAtomicStore8,
ssa.OpMIPSLoweredAtomicStore32:
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.Reg = v.Args[1].Reg()
p.To.Type = obj.TYPE_MEM

View File

@ -20,7 +20,6 @@ func Init(arch *gc.Arch) {
arch.MAXWIDTH = 1 << 50
arch.SoftFloat = objabi.GOMIPS64 == "softfloat"
arch.ZeroRange = zerorange
arch.ZeroAuto = zeroAuto
arch.Ginsnop = 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
}
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 {
p := pp.Prog(mips.ANOR)
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.Reg = v.Reg0()
s.Prog(mips.ASYNC)
case ssa.OpMIPS64LoweredAtomicStore32, ssa.OpMIPS64LoweredAtomicStore64:
case ssa.OpMIPS64LoweredAtomicStore8, ssa.OpMIPS64LoweredAtomicStore32, ssa.OpMIPS64LoweredAtomicStore64:
as := mips.AMOVV
if v.Op == ssa.OpMIPS64LoweredAtomicStore32 {
switch v.Op {
case ssa.OpMIPS64LoweredAtomicStore8:
as = mips.AMOVB
case ssa.OpMIPS64LoweredAtomicStore32:
as = mips.AMOVW
}
s.Prog(mips.ASYNC)

View File

@ -19,7 +19,6 @@ func Init(arch *gc.Arch) {
arch.MAXWIDTH = 1 << 60
arch.ZeroRange = zerorange
arch.ZeroAuto = zeroAuto
arch.Ginsnop = ginsnop
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
}
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 {
p := pp.Prog(ppc64.AOR)
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
gc.Patch(p2, pisync)
case ssa.OpPPC64LoweredAtomicStore32,
case ssa.OpPPC64LoweredAtomicStore8,
ssa.OpPPC64LoweredAtomicStore32,
ssa.OpPPC64LoweredAtomicStore64:
// SYNC or LWSYNC
// MOVD/MOVW arg1,(arg0)
// MOVB/MOVW/MOVD arg1,(arg0)
st := ppc64.AMOVD
if v.Op == ssa.OpPPC64LoweredAtomicStore32 {
switch v.Op {
case ssa.OpPPC64LoweredAtomicStore8:
st = ppc64.AMOVB
case ssa.OpPPC64LoweredAtomicStore32:
st = ppc64.AMOVW
}
arg0 := v.Args[0].Reg()

View File

@ -15,7 +15,6 @@ func Init(arch *gc.Arch) {
arch.MAXWIDTH = 1 << 50
arch.ZeroRange = zerorange
arch.ZeroAuto = zeroAuto
arch.Ginsnop = 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
}
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 {
return pp.Prog(s390x.ANOPH)
}

View File

@ -725,7 +725,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
gc.AddAux(&p.From, v)
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg0()
case ssa.OpS390XMOVWatomicstore, ssa.OpS390XMOVDatomicstore:
case ssa.OpS390XMOVBatomicstore, ssa.OpS390XMOVWatomicstore, ssa.OpS390XMOVDatomicstore:
p := s.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_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
// puts a statement mark on it, and returns whether it succeeded
// in this operation.
setBlockPos := func (b *Block) bool {
setBlockPos := func(b *Block) bool {
pos := b.Pos
for _, v := range b.Values {
if pos.SameFileAndLine(v.Pos) && !isPoorStatementOp(v.Op) {

View File

@ -4,13 +4,11 @@
// Lowering arithmetic
(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) && config.PtrSize == 4 -> (ADDL x y)
(AddPtr x y) -> (ADDQ 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)
(SubPtr x y) && config.PtrSize == 8 -> (SUBQ x y)
(SubPtr x y) && config.PtrSize == 4 -> (SUBL x y)
(SubPtr x y) -> (SUBQ 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)
@ -76,9 +74,8 @@
(Not x) -> (XORLconst [1] x)
// Lowering pointer arithmetic
(OffPtr [off] ptr) && config.PtrSize == 8 && is32Bit(off) -> (ADDQconst [off] ptr)
(OffPtr [off] ptr) && config.PtrSize == 8 -> (ADDQ (MOVQconst [off]) ptr)
(OffPtr [off] ptr) && config.PtrSize == 4 -> (ADDLconst [off] ptr)
(OffPtr [off] ptr) && is32Bit(off) -> (ADDQconst [off] ptr)
(OffPtr [off] ptr) -> (ADDQ (MOVQconst [off]) ptr)
// Lowering other arithmetic
(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))
(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) && config.PtrSize == 4 -> (SETEQ (CMPL x y))
(EqPtr x y) -> (SETEQ (CMPQ 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))
(NeqPtr x y) && config.PtrSize == 8 -> (SETNE (CMPQ x y))
(NeqPtr x y) && config.PtrSize == 4 -> (SETNE (CMPL x y))
(NeqPtr x y) -> (SETNE (CMPQ x y))
(Neq(32|64)F x y) -> (SETNEF (UCOMIS(S|D) x y))
// Lowering loads
(Load <t> ptr mem) && (is64BitInt(t) || isPtr(t) && config.PtrSize == 8) -> (MOVQload ptr mem)
(Load <t> ptr mem) && (is32BitInt(t) || isPtr(t) && config.PtrSize == 4) -> (MOVLload ptr mem)
(Load <t> ptr mem) && (is64BitInt(t) || isPtr(t)) -> (MOVQload ptr mem)
(Load <t> ptr mem) && is32BitInt(t) -> (MOVLload 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) && is32BitFloat(t) -> (MOVSSload ptr mem)
@ -420,8 +415,7 @@
(Const64 [val]) -> (MOVQconst [val])
(Const32F [val]) -> (MOVSSconst [val])
(Const64F [val]) -> (MOVSDconst [val])
(ConstNil) && config.PtrSize == 8 -> (MOVQconst [0])
(ConstNil) && config.PtrSize == 4 -> (MOVLconst [0])
(ConstNil) -> (MOVQconst [0])
(ConstBool [b]) -> (MOVLconst [b])
// 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
// Miscellaneous
(IsNonNil p) && config.PtrSize == 8 -> (SETNE (TESTQ p p))
(IsNonNil p) && config.PtrSize == 4 -> (SETNE (TESTL p p))
(IsInBounds idx len) && config.PtrSize == 8 -> (SETB (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))
(IsNonNil p) -> (SETNE (TESTQ p p))
(IsInBounds idx len) -> (SETB (CMPQ idx len))
(IsSliceInBounds idx len) -> (SETBE (CMPQ idx len))
(NilCheck ptr mem) -> (LoweredNilCheck ptr mem)
(GetG mem) -> (LoweredGetG mem)
(GetClosurePtr) -> (LoweredGetClosurePtr)
(GetCallerPC) -> (LoweredGetCallerPC)
(GetCallerSP) -> (LoweredGetCallerSP)
(Addr {sym} base) && config.PtrSize == 8 -> (LEAQ {sym} base)
(Addr {sym} base) && config.PtrSize == 4 -> (LEAL {sym} base)
(LocalAddr {sym} base _) && config.PtrSize == 8 -> (LEAQ {sym} base)
(LocalAddr {sym} base _) && config.PtrSize == 4 -> (LEAL {sym} base)
(Addr {sym} base) -> (LEAQ {sym} base)
(LocalAddr {sym} base _) -> (LEAQ {sym} base)
(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)
@ -528,15 +517,14 @@
(AtomicLoad8 ptr mem) -> (MOVBatomicload ptr mem)
(AtomicLoad32 ptr mem) -> (MOVLatomicload ptr mem)
(AtomicLoad64 ptr mem) -> (MOVQatomicload ptr mem)
(AtomicLoadPtr ptr mem) && config.PtrSize == 8 -> (MOVQatomicload ptr mem)
(AtomicLoadPtr ptr mem) && config.PtrSize == 4 -> (MOVLatomicload ptr mem)
(AtomicLoadPtr ptr mem) -> (MOVQatomicload ptr mem)
// 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?
(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))
(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) && config.PtrSize == 4 -> (Select1 (XCHGL <types.NewTuple(typ.BytePtr,types.TypeMem)> val ptr mem))
(AtomicStorePtrNoWB ptr val mem) -> (Select1 (XCHGQ <types.NewTuple(typ.BytePtr,types.TypeMem)> val ptr mem))
// Atomic exchanges.
(AtomicExchange32 ptr val mem) -> (XCHGL val ptr mem)

View File

@ -746,6 +746,7 @@ func init() {
// store arg0 to arg1+auxint+aux, arg2=mem.
// 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)!
{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: "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)
(AtomicLoadPtr ptr mem) -> (LDAR ptr mem)
(AtomicStore8 ptr val mem) -> (STLRB ptr val mem)
(AtomicStore32 ptr val mem) -> (STLRW ptr val mem)
(AtomicStore64 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.
// 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: "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)
// atomic intrinsics
(AtomicLoad32 ptr mem) -> (LoweredAtomicLoad ptr mem)
(AtomicLoadPtr ptr mem) -> (LoweredAtomicLoad ptr mem)
(AtomicLoad(8|32) ptr mem) -> (LoweredAtomicLoad(8|32) ptr mem)
(AtomicLoadPtr ptr mem) -> (LoweredAtomicLoad32 ptr mem)
(AtomicStore32 ptr val mem) -> (LoweredAtomicStore ptr val mem)
(AtomicStorePtrNoWB ptr val mem) -> (LoweredAtomicStore ptr val mem)
(AtomicStore(8|32) ptr val mem) -> (LoweredAtomicStore(8|32) ptr val mem)
(AtomicStorePtrNoWB ptr val mem) -> (LoweredAtomicStore32 ptr val mem)
(AtomicExchange32 ptr val mem) -> (LoweredAtomicExchange ptr val mem)
(AtomicAdd32 ptr val mem) -> (LoweredAtomicAdd ptr val mem)
@ -708,6 +708,6 @@
(CMOVZ a (MOVWconst [0]) c) -> (CMOVZzero a c)
// 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)

View File

@ -403,6 +403,7 @@
(AtomicLoad64 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)
(AtomicStore64 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.
// 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: "LoweredAtomicStore64", argLength: 3, reg: gpstore, faultOnNilArg0: true, hasSideEffects: true},
// store zero to arg0. arg1=mem. returns memory.

View File

@ -262,15 +262,17 @@ func init() {
// load from arg0. arg1=mem.
// returns <value,memory> so they can be properly ordered with other loads.
// SYNC
// MOVW (Rarg0), Rout
// MOV(B|W) (Rarg0), Rout
// 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.
// SYNC
// MOVW Rarg1, (Rarg0)
// MOV(B|W) Rarg1, (Rarg0)
// 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},
// atomic exchange.

View File

@ -931,7 +931,7 @@
(AtomicLoad(8|32|64|Ptr) ptr mem) -> (LoweredAtomicLoad(8|32|64|Ptr) [1] 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)
//(AtomicStorePtrNoWB ptr val mem) -> (STLR ptr val mem)

View File

@ -495,6 +495,7 @@ func init() {
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: "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,
// 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)
(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.
(AtomicStoreRel32 ptr val mem) -> (MOVWatomicstore ptr val mem)

View File

@ -495,6 +495,7 @@ func init() {
// Atomic stores. These are just normal stores.
// 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: "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.
(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
(Store {t} dst (Load src mem) mem) && !fe.CanSSA(t.(*types.Type)) ->
@ -823,9 +823,9 @@
(Store _ (ArrayMake0) mem) -> 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)
(ArraySelect [0] x:(IData _)) -> x
(ArraySelect [0] (IData x)) -> (IData x)
// string ops
// Decomposing StringMake and lowering of StringPtr and StringLen

View File

@ -316,8 +316,7 @@ var genericOps = []opData{
// See section 7.2 in ieee754.
{name: "Fma", argLength: 3}, // compute (a*b)+c without intermediate rounding
// Data movement, max argument length for Phi is indefinite so just pick
// a really large number
// Data movement. Max argument length for Phi is indefinite.
{name: "Phi", argLength: -1, zeroWidth: true}, // select an argument based on which predecessor block we came from
{name: "Copy", argLength: 1}, // output = arg0
// 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: "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: "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: "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.

View File

@ -877,6 +877,7 @@ const (
OpAMD64MOVBatomicload
OpAMD64MOVLatomicload
OpAMD64MOVQatomicload
OpAMD64XCHGB
OpAMD64XCHGL
OpAMD64XCHGQ
OpAMD64XADDLlock
@ -1434,6 +1435,7 @@ const (
OpARM64LDAR
OpARM64LDARB
OpARM64LDARW
OpARM64STLRB
OpARM64STLR
OpARM64STLRW
OpARM64LoweredAtomicExchange64
@ -1535,8 +1537,10 @@ const (
OpMIPSCALLstatic
OpMIPSCALLclosure
OpMIPSCALLinter
OpMIPSLoweredAtomicLoad
OpMIPSLoweredAtomicStore
OpMIPSLoweredAtomicLoad8
OpMIPSLoweredAtomicLoad32
OpMIPSLoweredAtomicStore8
OpMIPSLoweredAtomicStore32
OpMIPSLoweredAtomicStorezero
OpMIPSLoweredAtomicExchange
OpMIPSLoweredAtomicAdd
@ -1655,6 +1659,7 @@ const (
OpMIPS64LoweredAtomicLoad8
OpMIPS64LoweredAtomicLoad32
OpMIPS64LoweredAtomicLoad64
OpMIPS64LoweredAtomicStore8
OpMIPS64LoweredAtomicStore32
OpMIPS64LoweredAtomicStore64
OpMIPS64LoweredAtomicStorezero32
@ -1848,6 +1853,7 @@ const (
OpPPC64CALLinter
OpPPC64LoweredZero
OpPPC64LoweredMove
OpPPC64LoweredAtomicStore8
OpPPC64LoweredAtomicStore32
OpPPC64LoweredAtomicStore64
OpPPC64LoweredAtomicLoad8
@ -2068,6 +2074,7 @@ const (
OpS390XMOVBZatomicload
OpS390XMOVWZatomicload
OpS390XMOVDatomicload
OpS390XMOVBatomicstore
OpS390XMOVWatomicstore
OpS390XMOVDatomicstore
OpS390XLAA
@ -2553,6 +2560,7 @@ const (
OpAtomicLoad64
OpAtomicLoadPtr
OpAtomicLoadAcq32
OpAtomicStore8
OpAtomicStore32
OpAtomicStore64
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",
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",
argLen: 3,
@ -20278,7 +20318,7 @@ var opcodeTable = [...]opInfo{
},
},
{
name: "LoweredAtomicLoad",
name: "LoweredAtomicLoad8",
argLen: 2,
faultOnNilArg0: true,
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,
faultOnNilArg0: 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",
argLen: 3,
@ -24489,6 +24566,19 @@ var opcodeTable = [...]opInfo{
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",
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",
auxType: auxSymOff,
@ -31347,6 +31453,12 @@ var opcodeTable = [...]opInfo{
argLen: 2,
generic: true,
},
{
name: "AtomicStore8",
argLen: 3,
hasSideEffects: true,
generic: true,
},
{
name: "AtomicStore32",
argLen: 3,

View File

@ -407,56 +407,82 @@ func (po *poset) newconst(n *Value) {
po.upushconst(i, 0)
}
// aliasnode records that n2 is an alias of n1
func (po *poset) aliasnode(n1, n2 *Value) {
// aliasnewnode records that a single node n2 (not in the poset yet) is an alias
// 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]
if i1 == 0 {
panic("aliasnode for non-existing node")
}
if i2s.Test(i1) {
panic("aliasnode i2s contains n1 node")
}
i2 := po.values[n2.ID]
if i2 != 0 {
// Rename all references to i2 into i1
// (do not touch i1 itself, otherwise we can create useless self-loops)
for idx, n := range po.nodes {
if uint32(idx) != i1 {
l, r := n.l, n.r
if l.Target() == i2 {
po.setchl(uint32(idx), newedge(i1, l.Strict()))
po.upush(undoSetChl, uint32(idx), l)
}
if r.Target() == i2 {
po.setchr(uint32(idx), newedge(i1, r.Strict()))
po.upush(undoSetChr, uint32(idx), r)
}
}
// Go through all the nodes to adjust parent/chidlren of nodes in i2s
for idx, n := range po.nodes {
// Do not touch i1 itself, otherwise we can create useless self-loops
if uint32(idx) == i1 {
continue
}
l, r := n.l, n.r
// Rename all references to i2s into i1
if i2s.Test(l.Target()) {
po.setchl(uint32(idx), newedge(i1, l.Strict()))
po.upush(undoSetChl, uint32(idx), l)
}
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.
// This includes n2.ID.
for k, v := range po.values {
if v == i2 {
po.values[k] = i1
po.upushalias(k, i2)
// Connect all chidren of i2s to i1 (unless those children
// are in i2s as well, in which case it would be useless)
if i2s.Test(uint32(idx)) {
if l != 0 && !i2s.Test(l.Target()) {
po.addchild(i1, l.Target(), l.Strict())
}
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() {
val := n2.AuxInt
if po.flags&posetFlagUnsigned != 0 {
val = int64(n2.AuxUnsigned())
}
if po.constants[val] != i2 {
panic("aliasing constant which is not registered")
}
// Reassign all existing IDs that point to i2 to i1.
// This includes n2.ID.
for k, v := range po.values {
if i2s.Test(v) {
po.values[k] = i1
po.upushalias(k, v)
}
}
// 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.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
}
// collapsepath marks i1 and i2 as equal and collapses as equal all
// nodes across all paths between i1 and i2. If a strict edge is
// collapsepath marks n1 and n2 as equal and collapses as equal all
// nodes across all paths between n1 and n2. If a strict edge is
// found, the function does not modify the DAG and returns false.
// Complexity is O(n).
func (po *poset) collapsepath(n1, n2 *Value) bool {
i1, i2 := po.values[n1.ID], po.values[n2.ID]
if po.reaches(i1, i2, true) {
return false
}
// TODO: for now, only handle the simple case of i2 being child of i1
l, r := po.children(i1)
if l.Target() == i2 || r.Target() == i2 {
po.aliasnode(n1, n2)
po.addchild(i1, i2, false)
return true
}
// Find all the paths from i1 to i2
paths := po.findpaths(i1, i2)
// Mark all nodes in all the paths as aliases of n1
// (excluding n1 itself)
paths.Clear(i1)
po.aliasnodes(n1, paths)
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
func (po *poset) isnoneq(i1, i2 uint32) bool {
if i1 == i2 {
@ -1093,11 +1150,11 @@ func (po *poset) SetEqual(n1, n2 *Value) bool {
i1 = po.newnode(n1)
po.roots = append(po.roots, i1)
po.upush(undoNewRoot, i1, 0)
po.aliasnode(n1, n2)
po.aliasnewnode(n1, n2)
case f1 && !f2:
po.aliasnode(n1, n2)
po.aliasnewnode(n1, n2)
case !f1 && f2:
po.aliasnode(n2, n1)
po.aliasnewnode(n2, n1)
case f1 && f2:
if i1 == i2 {
// 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
// to n2 to become references to n1
po.aliasnode(n1, n2)
// Connect i2 (now dummy) as child of i1. This allows to keep the correct
// order with its children.
po.addchild(i1, i2, false)
i2s := newBitset(int(po.lastidx) + 1)
i2s.Set(i2)
po.aliasnodes(n1, i2s)
}
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{
// 10<=20<=30<40, 20<=100<110
{Checkpoint, 0, 0},

View File

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

View File

@ -431,6 +431,8 @@ func rewriteValueARM64(v *Value) bool {
return rewriteValueARM64_OpAtomicStore32_0(v)
case OpAtomicStore64:
return rewriteValueARM64_OpAtomicStore64_0(v)
case OpAtomicStore8:
return rewriteValueARM64_OpAtomicStore8_0(v)
case OpAtomicStorePtrNoWB:
return rewriteValueARM64_OpAtomicStorePtrNoWB_0(v)
case OpAvg64u:
@ -27669,6 +27671,20 @@ func rewriteValueARM64_OpAtomicStore64_0(v *Value) bool {
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 {
// match: (AtomicStorePtrNoWB ptr val mem)
// result: (STLR ptr val mem)

View File

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

View File

@ -57,6 +57,8 @@ func rewriteValueMIPS64(v *Value) bool {
return rewriteValueMIPS64_OpAtomicStore32_0(v)
case OpAtomicStore64:
return rewriteValueMIPS64_OpAtomicStore64_0(v)
case OpAtomicStore8:
return rewriteValueMIPS64_OpAtomicStore8_0(v)
case OpAtomicStorePtrNoWB:
return rewriteValueMIPS64_OpAtomicStorePtrNoWB_0(v)
case OpAvg64u:
@ -938,6 +940,20 @@ func rewriteValueMIPS64_OpAtomicStore64_0(v *Value) bool {
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 {
// match: (AtomicStorePtrNoWB ptr val mem)
// result: (LoweredAtomicStore64 ptr val mem)

View File

@ -71,6 +71,8 @@ func rewriteValuePPC64(v *Value) bool {
return rewriteValuePPC64_OpAtomicStore32_0(v)
case OpAtomicStore64:
return rewriteValuePPC64_OpAtomicStore64_0(v)
case OpAtomicStore8:
return rewriteValuePPC64_OpAtomicStore8_0(v)
case OpAtomicStoreRel32:
return rewriteValuePPC64_OpAtomicStoreRel32_0(v)
case OpAvg64u:
@ -1132,6 +1134,21 @@ func rewriteValuePPC64_OpAtomicStore64_0(v *Value) bool {
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 {
// match: (AtomicStoreRel32 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)
case OpAtomicStore64:
return rewriteValueS390X_OpAtomicStore64_0(v)
case OpAtomicStore8:
return rewriteValueS390X_OpAtomicStore8_0(v)
case OpAtomicStorePtrNoWB:
return rewriteValueS390X_OpAtomicStorePtrNoWB_0(v)
case OpAtomicStoreRel32:
@ -1153,6 +1155,23 @@ func rewriteValueS390X_OpAtomicStore64_0(v *Value) bool {
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 {
b := v.Block
// match: (AtomicStorePtrNoWB ptr val mem)

View File

@ -6142,18 +6142,18 @@ func rewriteValuegeneric_OpArraySelect_0(v *Value) bool {
v.AddArg(x)
return true
}
// match: (ArraySelect [0] x:(IData _))
// result: x
// match: (ArraySelect [0] (IData x))
// result: (IData x)
for {
if v.AuxInt != 0 {
break
}
x := v.Args[0]
if x.Op != OpIData {
v_0 := v.Args[0]
if v_0.Op != OpIData {
break
}
v.reset(OpCopy)
v.Type = x.Type
x := v_0.Args[0]
v.reset(OpIData)
v.AddArg(x)
return true
}
@ -43502,18 +43502,18 @@ func rewriteValuegeneric_OpStructSelect_10(v *Value) bool {
v0.AddArg(mem)
return true
}
// match: (StructSelect [0] x:(IData _))
// result: x
// match: (StructSelect [0] (IData x))
// result: (IData x)
for {
if v.AuxInt != 0 {
break
}
x := v.Args[0]
if x.Op != OpIData {
v_0 := v.Args[0]
if v_0.Op != OpIData {
break
}
v.reset(OpCopy)
v.Type = x.Type
x := v_0.Args[0]
v.reset(OpIData)
v.AddArg(x)
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" {
path := filepath.Join(dir, fi.Name())
if !strings.HasSuffix(path, "/test") {
if !strings.HasSuffix(path, string(filepath.Separator)+"test") {
dirs = append(dirs, path)
}
}

View File

@ -19,7 +19,6 @@ func Init(arch *gc.Arch) {
arch.MAXWIDTH = 1 << 50
arch.ZeroRange = zeroRange
arch.ZeroAuto = zeroAuto
arch.Ginsnop = 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
}
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 {
return pp.Prog(wasm.ANop)
}

View File

@ -30,7 +30,6 @@ func Init(arch *gc.Arch) {
arch.MAXWIDTH = (1 << 32) - 1
arch.ZeroRange = zerorange
arch.ZeroAuto = zeroAuto
arch.Ginsnop = 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
}
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 {
// See comment in ../amd64/ggen.go.
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,
// which is relative to $GOROOT/src.
func runInstall(dir string, ch chan struct{}) {
if dir == "net" || dir == "os/user" || dir == "crypto/x509" {
fatalf("go_bootstrap cannot depend on cgo package %s", dir)
func runInstall(pkg string, ch chan struct{}) {
if pkg == "net" || pkg == "os/user" || pkg == "crypto/x509" {
fatalf("go_bootstrap cannot depend on cgo package %s", pkg)
}
defer close(ch)
if dir == "unsafe" {
if pkg == "unsafe" {
return
}
if vflag > 0 {
if goos != gohostos || goarch != gohostarch {
errprintf("%s (%s/%s)\n", dir, goos, goarch)
errprintf("%s (%s/%s)\n", pkg, goos, goarch)
} else {
errprintf("%s\n", dir)
errprintf("%s\n", pkg)
}
}
workdir := pathf("%s/%s", workdir, dir)
workdir := pathf("%s/%s", workdir, pkg)
xmkdirall(workdir)
var clean []string
@ -634,11 +634,14 @@ func runInstall(dir string, ch chan struct{}) {
}
}()
// path = full path to dir.
path := pathf("%s/src/%s", goroot, dir)
// dir = full path to pkg.
dir := pathf("%s/src/%s", goroot, pkg)
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.
// Note: code below knows that link.p[targ] is the target.
@ -650,7 +653,7 @@ func runInstall(dir string, ch chan struct{}) {
if ispkg {
// Go library (package).
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
xmkdirall(filepath.Dir(link[targ]))
} else {
@ -675,7 +678,7 @@ func runInstall(dir string, ch chan struct{}) {
// Gather files that are sources for this target.
// Everything in that directory, and any target-specific
// additions.
files := xreaddir(path)
files := xreaddir(dir)
// Remove files beginning with . or _,
// which are likely to be editor temporary files.
@ -687,7 +690,7 @@ func runInstall(dir string, ch chan struct{}) {
})
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 {
p = os.ExpandEnv(p)
files = append(files, p)
@ -699,7 +702,7 @@ func runInstall(dir string, ch chan struct{}) {
// Convert to absolute paths.
for i, p := range files {
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
ok:
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
}
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.
if dir == "runtime" {
if pkg == "runtime" {
xmkdirall(pathf("%s/pkg/include", goroot))
// For use by assembly and C files.
copyfile(pathf("%s/pkg/include/textflag.h", goroot),
@ -764,7 +767,7 @@ func runInstall(dir string, ch chan struct{}) {
if vflag > 1 {
errprintf("generate %s\n", p)
}
gt.gen(path, p)
gt.gen(dir, p)
// Do not add generated file to clean list.
// In runtime, we want to be able to
// build the package with the go tool,
@ -782,22 +785,31 @@ func runInstall(dir string, ch chan struct{}) {
built:
}
// Make sure dependencies are installed.
var deps []string
// Resolve imported packages to actual package paths.
// Make sure they're installed.
importMap := make(map[string]string)
for _, p := range gofiles {
deps = append(deps, readimports(p)...)
for _, imp := range readimports(p) {
importMap[imp] = resolveVendor(imp, dir)
}
}
for _, dir1 := range deps {
startInstall(dir1)
sortedImports := make([]string, 0, len(importMap))
for imp := range importMap {
sortedImports = append(sortedImports, imp)
}
for _, dir1 := range deps {
install(dir1)
sort.Strings(sortedImports)
for _, dep := range importMap {
startInstall(dep)
}
for _, dep := range importMap {
install(dep)
}
if goos != gohostos || goarch != gohostarch {
// We've generated the right files; the go command can do the build.
if vflag > 1 {
errprintf("skip build for cross-compile %s\n", dir)
errprintf("skip build for cross-compile %s\n", pkg)
}
return
}
@ -830,18 +842,35 @@ func runInstall(dir string, ch chan struct{}) {
if err := ioutil.WriteFile(goasmh, nil, 0666); err != nil {
fatalf("cannot write empty go_asm.h: %s", err)
}
bgrun(&wg, path, asmabis...)
bgrun(&wg, dir, asmabis...)
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
// The next loop will compile individual non-Go files.
// Hand the Go files to the compiler en masse.
// For packages containing assembly, this writes go_asm.h, which
// the assembly files will need.
pkg := dir
if strings.HasPrefix(dir, "cmd/") && strings.Count(dir, "/") == 1 {
pkg = "main"
pkgName := pkg
if strings.HasPrefix(pkg, "cmd/") && strings.Count(pkg, "/") == 1 {
pkgName = "main"
}
b := pathf("%s/_go_.a", workdir)
clean = append(clean, b)
@ -852,11 +881,11 @@ func runInstall(dir string, ch chan struct{}) {
}
// 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 != "" {
compile = append(compile, strings.Fields(gogcflags)...)
}
if dir == "runtime" {
if pkg == "runtime" {
compile = append(compile, "-+")
}
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.
// This executes all jobs through the bgwork channel and allows the process
// to exit cleanly in case an error occurs.
bgrun(&wg, path, compile...)
bgrun(&wg, dir, compile...)
bgwait(&wg)
// 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).
b = b[:len(b)-1] + "o"
compile = append(compile, "-o", b, p)
bgrun(&wg, path, compile...)
bgrun(&wg, dir, compile...)
link = append(link, b)
if doclean {
@ -909,6 +938,12 @@ func runInstall(dir string, ch chan struct{}) {
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.
// all the elements in the field must be satisfied.
func matchfield(f string) bool {
@ -940,7 +975,7 @@ func matchtag(tag string) bool {
// of GOOS and GOARCH.
// We also allow the special tag cmd_go_bootstrap.
// 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.
name := filepath.Base(file)
excluded := func(list []string, ok string) bool {
@ -982,7 +1017,7 @@ func shouldbuild(file, dir string) bool {
if code == "package documentation" {
return false
}
if code == "package main" && dir != "cmd/go" && dir != "cmd/cgo" {
if code == "package main" && pkg != "cmd/go" && pkg != "cmd/cgo" {
return false
}
if !strings.HasPrefix(p, "//") {
@ -1485,6 +1520,7 @@ var cgoEnabled = map[string]bool{
"freebsd/386": true,
"freebsd/amd64": true,
"freebsd/arm": true,
"freebsd/arm64": true,
"illumos/amd64": true,
"linux/386": true,
"linux/amd64": true,

View File

@ -11,7 +11,10 @@ package main
import (
"bufio"
"errors"
"fmt"
"io"
"path"
"path/filepath"
"strconv"
"strings"
"unicode/utf8"
@ -243,3 +246,31 @@ func readimports(file string) []string {
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, "std")
if !t.race {
if t.shouldTestCmd() {
cmd.Args = append(cmd.Args, "cmd")
}
cmd.Stderr = new(bytes.Buffer)
@ -1455,6 +1455,17 @@ func (t *tester) shouldUsePrecompiledStdTest() bool {
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
// the pre-built go test binary to be on disk when dist test is run with
// a single argument.

View File

@ -15,11 +15,11 @@ import (
"go/token"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"runtime"
"sort"
"strings"
"cmd/internal/diff"
)
var (
@ -186,7 +186,7 @@ func processFile(filename string, useStdin bool) error {
}
if *doDiff {
data, err := diff(src, newSrc)
data, err := diff.Diff("go-fix", src, newSrc)
if err != nil {
return fmt.Errorf("computing diff: %s", err)
}
@ -237,46 +237,3 @@ func isGoFile(f os.FileInfo) bool {
name := f.Name()
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"
"strings"
"testing"
"cmd/internal/diff"
)
type testCase struct {
@ -123,7 +125,7 @@ func TestRewrite(t *testing.T) {
}
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 {
t.Error(err)
return

View File

@ -6,7 +6,8 @@ require (
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f
github.com/ianlancetaylor/demangle v0.0.0-20180524225900-fc6590592b44 // indirect
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/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/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-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
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/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-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/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
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/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-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=

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)
}
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)
}
if _, ok := add[key]; ok {
@ -259,7 +259,7 @@ func runEnv(cmd *base.Command, args []string) {
}
del := make(map[string]bool)
for _, arg := range args {
if err := checkEnvWrite(arg, "", env); err != nil {
if err := checkEnvWrite(arg, ""); err != nil {
base.Fatalf("go env -u: %v", err)
}
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 {
case "GOEXE", "GOGCCFLAGS", "GOHOSTARCH", "GOHOSTOS", "GOMOD", "GOTOOLDIR":
return fmt.Errorf("%s cannot be modified", key)

View File

@ -11,7 +11,7 @@ import (
"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,
// 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)
}
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)
}
}
@ -1321,11 +1321,10 @@ func findInternal(path string) (index int, ok bool) {
return 0, false
}
// disallowVendor checks that srcDir (containing package importerPath, if non-empty)
// is allowed to import p as path.
// disallowVendor checks that srcDir is allowed to import p as path.
// If the import is allowed, disallowVendor returns the original package p.
// 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.
// If that's the only thing on the stack, we started
// with a name given on the command line, not an

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -13,10 +13,11 @@ import (
"cmd/go/internal/base"
"cmd/go/internal/modfetch"
"cmd/go/internal/modfile"
"cmd/go/internal/module"
"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.

View File

@ -19,8 +19,9 @@ import (
"cmd/go/internal/cfg"
"cmd/go/internal/modfetch"
"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) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -18,10 +18,11 @@ import (
"cmd/go/internal/cfg"
"cmd/go/internal/lockedfile"
"cmd/go/internal/modfetch/codehost"
"cmd/go/internal/module"
"cmd/go/internal/par"
"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

View File

@ -22,8 +22,9 @@ import (
"cmd/go/internal/lockedfile"
"cmd/go/internal/par"
"cmd/go/internal/semver"
"cmd/go/internal/web"
"golang.org/x/mod/semver"
)
// 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
import (
"encoding/xml"
"errors"
"fmt"
"internal/lazyregexp"
"io"
@ -122,19 +122,20 @@ func newVCSRepo(vcs, remote string) (Repo, error) {
const vcsWorkDirType = "vcs1."
type vcsCmd struct {
vcs string // vcs name "hg"
init func(remote string) []string // cmd to init repo to track remote
tags func(remote string) []string // cmd to list local tags
tagRE *lazyregexp.Regexp // regexp to extract tag names from output of tags cmd
branches func(remote string) []string // cmd to list local branches
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
statLocal func(rev, remote string) []string // cmd to stat local rev
parseStat func(rev, out string) (*RevInfo, error) // cmd to parse output of statLocal
fetch []string // cmd to fetch everything from remote
latest string // name of latest commit on remote (tip, HEAD, etc)
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
vcs string // vcs name "hg"
init func(remote string) []string // cmd to init repo to track remote
tags func(remote string) []string // cmd to list local tags
tagRE *lazyregexp.Regexp // regexp to extract tag names from output of tags cmd
branches func(remote string) []string // cmd to list local branches
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
statLocal func(rev, remote string) []string // cmd to stat local rev
parseStat func(rev, out string) (*RevInfo, error) // cmd to parse output of statLocal
fetch []string // cmd to fetch everything from remote
latest string // name of latest commit on remote (tip, HEAD, etc)
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
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
@ -191,7 +192,7 @@ var vcsCmds = map[string]*vcsCmd{
readFile: func(rev, file, remote string) []string {
return []string{"svn", "cat", "--", remote + "/" + file + "@" + rev}
},
// TODO: zip
doReadZip: svnReadZip,
},
"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) {
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)
}
@ -435,7 +436,17 @@ func (r *vcsRepo) ReadZip(rev, subdir string, maxSize int64) (zip io.ReadCloser,
if err != nil {
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
// fossil zip -R .fossil --name prefix trunk /tmp/x.zip
// fossil fails with "unable to create directory /tmp" [sic].
@ -502,31 +513,6 @@ func hgParseStat(rev, out string) (*RevInfo, error) {
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) {
var revno int64
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)
}
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"
"cmd/go/internal/modfetch/codehost"
"cmd/go/internal/modfile"
"cmd/go/internal/module"
"cmd/go/internal/semver"
"golang.org/x/mod/modfile"
"golang.org/x/mod/module"
"golang.org/x/mod/semver"
)
// A codeRepo implements modfetch.Repo using an underlying codehost.Repo.

View File

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

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