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

Change-Id: Ice4172e2058a45b1a24da561fd420244ab2a97bd
This commit is contained in:
Filippo Valsorda 2018-11-13 13:58:50 -05:00
commit af07f7734b
150 changed files with 4372 additions and 1832 deletions

View file

@ -33,9 +33,9 @@ func main() {
fail("did not find mobile provision matching device udids %q", udids)
}
fmt.Println("Available provisioning profiles below.")
fmt.Println("NOTE: Any existing app on the device with the app id specified by GOIOS_APP_ID")
fmt.Println("will be overwritten when running Go programs.")
fmt.Println("# Available provisioning profiles below.")
fmt.Println("# NOTE: Any existing app on the device with the app id specified by GOIOS_APP_ID")
fmt.Println("# will be overwritten when running Go programs.")
for _, mp := range mps {
fmt.Println()
f, err := ioutil.TempFile("", "go_ios_detect_")

View file

@ -3,8 +3,18 @@
// license that can be found in the LICENSE file.
(() => {
if (typeof global !== "undefined") {
// global already exists
} else if (typeof window !== "undefined") {
window.global = window;
} else if (typeof self !== "undefined") {
self.global = self;
} else {
throw new Error("cannot export Go (neither global, window nor self is defined)");
}
// Map web browser API and Node.js API to a single common API (preferring web standards over Node.js API).
const isNodeJS = typeof process !== "undefined";
const isNodeJS = global.process && global.process.title === "node";
if (isNodeJS) {
global.require = require;
global.fs = require("fs");
@ -27,14 +37,6 @@
global.TextEncoder = util.TextEncoder;
global.TextDecoder = util.TextDecoder;
} else {
if (typeof window !== "undefined") {
window.global = window;
} else if (typeof self !== "undefined") {
self.global = self;
} else {
throw new Error("cannot export Go (neither window nor self is defined)");
}
let outputBuf = "";
global.fs = {
constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1 }, // unused

View file

@ -369,6 +369,9 @@ TEXT main·foo(SB),DUPOK|NOSPLIT,$16-0 // TEXT main.foo(SB), DUPOK|NOSPLIT, $16-
VSTEH $7, V31, (R2) // e7f020007809
VSTEB $15, V29, 4094(R12) // e7d0cffef808
VMSLG V21, V22, V23, V24 // e78563007fb8
VMSLEG V21, V22, V23, V24 // e78563807fb8
VMSLOG V21, V22, V23, V24 // e78563407fb8
VMSLEOG V21, V22, V23, V24 // e78563c07fb8
RET
RET foo(SB)

View file

@ -211,6 +211,8 @@ var exportHeader = flag.String("exportheader", "", "where to write export header
var gccgo = flag.Bool("gccgo", false, "generate files for use with gccgo")
var gccgoprefix = flag.String("gccgoprefix", "", "-fgo-prefix option used with gccgo")
var gccgopkgpath = flag.String("gccgopkgpath", "", "-fgo-pkgpath option used with gccgo")
var gccgoMangleCheckDone bool
var gccgoNewmanglingInEffect bool
var importRuntimeCgo = flag.Bool("import_runtime_cgo", true, "import runtime/cgo in generated code")
var importSyscall = flag.Bool("import_syscall", true, "import syscall in generated code")
var goarch, goos string

View file

@ -15,7 +15,9 @@ import (
"go/printer"
"go/token"
"io"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"regexp"
"sort"
@ -1186,12 +1188,91 @@ func (p *Package) writeExportHeader(fgcch io.Writer) {
fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog())
}
// Return the package prefix when using gccgo.
func (p *Package) gccgoSymbolPrefix() string {
if !*gccgo {
return ""
// gccgoUsesNewMangling returns whether gccgo uses the new collision-free
// packagepath mangling scheme (see determineGccgoManglingScheme for more
// info).
func gccgoUsesNewMangling() bool {
if !gccgoMangleCheckDone {
gccgoNewmanglingInEffect = determineGccgoManglingScheme()
gccgoMangleCheckDone = true
}
return gccgoNewmanglingInEffect
}
const mangleCheckCode = `
package läufer
func Run(x int) int {
return 1
}
`
// determineGccgoManglingScheme performs a runtime test to see which
// flavor of packagepath mangling gccgo is using. Older versions of
// gccgo use a simple mangling scheme where there can be collisions
// between packages whose paths are different but mangle to the same
// string. More recent versions of gccgo use a new mangler that avoids
// these collisions. Return value is whether gccgo uses the new mangling.
func determineGccgoManglingScheme() bool {
// Emit a small Go file for gccgo to compile.
filepat := "*_gccgo_manglecheck.go"
var f *os.File
var err error
if f, err = ioutil.TempFile(*objDir, filepat); err != nil {
fatalf("%v", err)
}
gofilename := f.Name()
defer os.Remove(gofilename)
if err = ioutil.WriteFile(gofilename, []byte(mangleCheckCode), 0666); err != nil {
fatalf("%v", err)
}
// Compile with gccgo, capturing generated assembly.
gccgocmd := os.Getenv("GCCGO")
if gccgocmd == "" {
gpath, gerr := exec.LookPath("gccgo")
if gerr != nil {
fatalf("unable to locate gccgo: %v", gerr)
}
gccgocmd = gpath
}
cmd := exec.Command(gccgocmd, "-S", "-o", "-", gofilename)
buf, cerr := cmd.CombinedOutput()
if cerr != nil {
fatalf("%s", err)
}
// New mangling: expect go.l..u00e4ufer.Run
// Old mangling: expect go.l__ufer.Run
return regexp.MustCompile(`go\.l\.\.u00e4ufer\.Run`).Match(buf)
}
// gccgoPkgpathToSymbolNew converts a package path to a gccgo-style
// package symbol.
func gccgoPkgpathToSymbolNew(ppath string) string {
bsl := []byte{}
changed := false
for _, c := range []byte(ppath) {
switch {
case 'A' <= c && c <= 'Z', 'a' <= c && c <= 'z',
'0' <= c && c <= '9', '_' == c:
bsl = append(bsl, c)
default:
changed = true
encbytes := []byte(fmt.Sprintf("..z%02x", c))
bsl = append(bsl, encbytes...)
}
}
if !changed {
return ppath
}
return string(bsl)
}
// gccgoPkgpathToSymbolOld converts a package path to a gccgo-style
// package symbol using the older mangling scheme.
func gccgoPkgpathToSymbolOld(ppath string) string {
clean := func(r rune) rune {
switch {
case 'A' <= r && r <= 'Z', 'a' <= r && r <= 'z',
@ -1200,14 +1281,32 @@ func (p *Package) gccgoSymbolPrefix() string {
}
return '_'
}
return strings.Map(clean, ppath)
}
// gccgoPkgpathToSymbol converts a package path to a mangled packagepath
// symbol.
func gccgoPkgpathToSymbol(ppath string) string {
if gccgoUsesNewMangling() {
return gccgoPkgpathToSymbolNew(ppath)
} else {
return gccgoPkgpathToSymbolOld(ppath)
}
}
// Return the package prefix when using gccgo.
func (p *Package) gccgoSymbolPrefix() string {
if !*gccgo {
return ""
}
if *gccgopkgpath != "" {
return strings.Map(clean, *gccgopkgpath)
return gccgoPkgpathToSymbol(*gccgopkgpath)
}
if *gccgoprefix == "" && p.PackageName == "main" {
return "main"
}
prefix := strings.Map(clean, *gccgoprefix)
prefix := gccgoPkgpathToSymbol(*gccgoprefix)
if prefix == "" {
prefix = "go"
}

View file

@ -360,6 +360,41 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p.To.Type = obj.TYPE_REG
p.To.Reg = r
case ssa.OpAMD64ADDQcarry, ssa.OpAMD64ADCQ:
r := v.Reg0()
r0 := v.Args[0].Reg()
r1 := v.Args[1].Reg()
switch r {
case r0:
p := s.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_REG
p.From.Reg = r1
p.To.Type = obj.TYPE_REG
p.To.Reg = r
case r1:
p := s.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_REG
p.From.Reg = r0
p.To.Type = obj.TYPE_REG
p.To.Reg = r
default:
v.Fatalf("output not in same register as an input %s", v.LongString())
}
case ssa.OpAMD64SUBQborrow, ssa.OpAMD64SBBQ:
p := s.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_REG
p.From.Reg = v.Args[1].Reg()
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg0()
case ssa.OpAMD64ADDQconstcarry, ssa.OpAMD64ADCQconst, ssa.OpAMD64SUBQconstborrow, ssa.OpAMD64SBBQconst:
p := s.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_CONST
p.From.Offset = v.AuxInt
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg0()
case ssa.OpAMD64ADDQconst, ssa.OpAMD64ADDLconst:
r := v.Reg()
a := v.Args[0].Reg()
@ -946,6 +981,16 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p := s.Prog(v.Op.Asm())
p.To.Type = obj.TYPE_REG
p.To.Reg = r
case ssa.OpAMD64NEGLflags:
r := v.Reg0()
if r != v.Args[0].Reg() {
v.Fatalf("input[0] and output not in same register %s", v.LongString())
}
p := s.Prog(v.Op.Asm())
p.To.Type = obj.TYPE_REG
p.To.Reg = r
case ssa.OpAMD64BSFQ, ssa.OpAMD64BSRQ, ssa.OpAMD64BSFL, ssa.OpAMD64BSRL, ssa.OpAMD64SQRTSD:
p := s.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_REG

View file

@ -863,7 +863,7 @@ func methodSymSuffix(recv *types.Type, msym *types.Sym, suffix string) *types.Sy
// Add a method, declared as a function.
// - msym is the method symbol
// - t is function type (with receiver)
// Returns a pointer to the existing or added Field.
// Returns a pointer to the existing or added Field; or nil if there's an error.
func addmethod(msym *types.Sym, t *types.Type, local, nointerface bool) *types.Field {
if msym == nil {
Fatalf("no method symbol")
@ -918,6 +918,7 @@ func addmethod(msym *types.Sym, t *types.Type, local, nointerface bool) *types.F
for _, f := range mt.Fields().Slice() {
if f.Sym == msym {
yyerror("type %v has both field and method named %v", mt, msym)
f.SetBroke(true)
return nil
}
}
@ -927,7 +928,7 @@ func addmethod(msym *types.Sym, t *types.Type, local, nointerface bool) *types.F
if msym.Name != f.Sym.Name {
continue
}
// eqtype only checks that incoming and result parameters match,
// types.Identical only checks that incoming and result parameters match,
// so explicitly check that the receiver parameters match too.
if !types.Identical(t, f.Type) || !types.Identical(t.Recv().Type, f.Type.Recv().Type) {
yyerror("method redeclared: %v.%v\n\t%v\n\t%v", mt, msym, f.Type, t)

View file

@ -621,23 +621,23 @@ func (e *EscState) escloopdepth(n *Node) {
switch n.Op {
case OLABEL:
if n.Left == nil || n.Left.Sym == nil {
if n.Sym == nil {
Fatalf("esc:label without label: %+v", n)
}
// Walk will complain about this label being already defined, but that's not until
// after escape analysis. in the future, maybe pull label & goto analysis out of walk and put before esc
n.Left.Sym.Label = asTypesNode(&nonlooping)
n.Sym.Label = asTypesNode(&nonlooping)
case OGOTO:
if n.Left == nil || n.Left.Sym == nil {
if n.Sym == nil {
Fatalf("esc:goto without label: %+v", n)
}
// If we come past one that's uninitialized, this must be a (harmless) forward jump
// but if it's set to nonlooping the label must have preceded this goto.
if asNode(n.Left.Sym.Label) == &nonlooping {
n.Left.Sym.Label = asTypesNode(&looping)
if asNode(n.Sym.Label) == &nonlooping {
n.Sym.Label = asTypesNode(&looping)
}
}
@ -851,18 +851,19 @@ opSwitch:
}
case OLABEL:
if asNode(n.Left.Sym.Label) == &nonlooping {
switch asNode(n.Sym.Label) {
case &nonlooping:
if Debug['m'] > 2 {
fmt.Printf("%v:%v non-looping label\n", linestr(lineno), n)
}
} else if asNode(n.Left.Sym.Label) == &looping {
case &looping:
if Debug['m'] > 2 {
fmt.Printf("%v: %v looping label\n", linestr(lineno), n)
}
e.loopdepth++
}
n.Left.Sym.Label = nil
n.Sym.Label = nil
case ORANGE:
if n.List.Len() >= 2 {

View file

@ -1045,8 +1045,8 @@ func (n *Node) stmtfmt(s fmt.State, mode fmtMode) {
mode.Fprintf(s, ": %v", n.Nbody)
case OBREAK, OCONTINUE, OGOTO, OFALL:
if n.Left != nil {
mode.Fprintf(s, "%#v %v", n.Op, n.Left)
if n.Sym != nil {
mode.Fprintf(s, "%#v %v", n.Op, n.Sym)
} else {
mode.Fprintf(s, "%#v", n.Op)
}
@ -1055,7 +1055,7 @@ func (n *Node) stmtfmt(s fmt.State, mode fmtMode) {
break
case OLABEL:
mode.Fprintf(s, "%v: ", n.Left)
mode.Fprintf(s, "%v: ", n.Sym)
}
if extrablock {

View file

@ -1102,7 +1102,7 @@ func (w *exportWriter) stmt(n *Node) {
case OGOTO, OLABEL:
w.op(op)
w.pos(n.Pos)
w.expr(n.Left)
w.string(n.Sym.Name)
default:
Fatalf("exporter: CANNOT EXPORT: %v\nPlease notify gri@\n", n.Op)

View file

@ -1043,7 +1043,9 @@ func (r *importReader) node() *Node {
// unreachable - not emitted by exporter
case OGOTO, OLABEL:
return nodl(r.pos(), op, newname(r.expr().Sym), nil)
n := nodl(r.pos(), op, nil, nil)
n.Sym = lookup(r.string())
return n
case OEND:
return nil

View file

@ -1072,7 +1072,7 @@ func mkinlcall(n, fn *Node, maxCost int32) *Node {
body := subst.list(asNodes(fn.Func.Inl.Body))
lab := nod(OLABEL, retlabel, nil)
lab := nodSym(OLABEL, nil, retlabel)
body = append(body, lab)
typecheckslice(body, Etop)
@ -1158,7 +1158,7 @@ func argvar(t *types.Type, i int) *Node {
// function call.
type inlsubst struct {
// Target of the goto substituted in place of a return.
retlabel *Node
retlabel *types.Sym
// Temporary result variables.
retvars []*Node
@ -1218,7 +1218,7 @@ func (subst *inlsubst) node(n *Node) *Node {
// dump("Return before substitution", n);
case ORETURN:
m := nod(OGOTO, subst.retlabel, nil)
m := nodSym(OGOTO, nil, subst.retlabel)
m.Ninit.Set(subst.list(n.Ninit))
if len(subst.retvars) != 0 && n.List.Len() != 0 {
@ -1245,8 +1245,8 @@ func (subst *inlsubst) node(n *Node) *Node {
m := n.copy()
m.Pos = subst.updatedPos(m.Pos)
m.Ninit.Set(nil)
p := fmt.Sprintf("%s·%d", n.Left.Sym.Name, inlgen)
m.Left = newname(lookup(p))
p := fmt.Sprintf("%s·%d", n.Sym.Name, inlgen)
m.Sym = lookup(p)
return m
}

View file

@ -205,7 +205,6 @@ func Main(archInit func(*Arch)) {
flag.BoolVar(&Ctxt.Flag_locationlists, "dwarflocationlists", true, "add location lists to DWARF in optimized mode")
flag.IntVar(&genDwarfInline, "gendwarfinl", 2, "generate DWARF inline info records")
objabi.Flagcount("e", "no limit on number of errors reported", &Debug['e'])
objabi.Flagcount("f", "debug stack frames", &Debug['f'])
objabi.Flagcount("h", "halt on error", &Debug['h'])
objabi.Flagfn1("importmap", "add `definition` of the form source=actual to import map", addImportMap)
objabi.Flagfn1("importcfg", "read import configuration from `file`", readImportCfg)
@ -478,9 +477,6 @@ func Main(archInit func(*Arch)) {
finishUniverse()
typecheckok = true
if Debug['f'] != 0 {
frame(1)
}
// Process top-level declarations in phases.
@ -693,10 +689,14 @@ func Main(archInit func(*Arch)) {
// Check whether any of the functions we have compiled have gigantic stack frames.
obj.SortSlice(largeStackFrames, func(i, j int) bool {
return largeStackFrames[i].Before(largeStackFrames[j])
return largeStackFrames[i].pos.Before(largeStackFrames[j].pos)
})
for _, largePos := range largeStackFrames {
yyerrorl(largePos, "stack frame too large (>1GB)")
for _, large := range largeStackFrames {
if large.callee != 0 {
yyerrorl(large.pos, "stack frame too large (>1GB): %d MB locals + %d MB args + %d MB callee", large.locals>>20, large.args>>20, large.callee>>20)
} else {
yyerrorl(large.pos, "stack frame too large (>1GB): %d MB locals + %d MB args", large.locals>>20, large.args>>20)
}
}
if len(compilequeue) != 0 {

View file

@ -819,13 +819,18 @@ func (p *noder) packname(expr syntax.Expr) *types.Sym {
return name
case *syntax.SelectorExpr:
name := p.name(expr.X.(*syntax.Name))
def := asNode(name.Def)
if def == nil {
yyerror("undefined: %v", name)
return name
}
var pkg *types.Pkg
if asNode(name.Def) == nil || asNode(name.Def).Op != OPACK {
if def.Op != OPACK {
yyerror("%v is not a package", name)
pkg = localpkg
} else {
asNode(name.Def).Name.SetUsed(true)
pkg = asNode(name.Def).Name.Pkg
def.Name.SetUsed(true)
pkg = def.Name.Pkg
}
return restrictlookup(expr.Sel.Value, pkg)
}
@ -936,7 +941,7 @@ func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) *Node {
}
n := p.nod(stmt, op, nil, nil)
if stmt.Label != nil {
n.Left = p.newname(stmt.Label)
n.Sym = p.name(stmt.Label)
}
return n
case *syntax.CallStmt:
@ -1200,7 +1205,7 @@ func (p *noder) commClauses(clauses []*syntax.CommClause, rbrace syntax.Pos) []*
}
func (p *noder) labeledStmt(label *syntax.LabeledStmt, fallOK bool) *Node {
lhs := p.nod(label, OLABEL, p.newname(label.Label), nil)
lhs := p.nodSym(label, OLABEL, nil, p.name(label.Label))
var ls *Node
if label.Stmt != nil { // TODO(mdempsky): Should always be present.

View file

@ -279,7 +279,7 @@ func compileSSA(fn *Node, worker int) {
// Note: check arg size to fix issue 25507.
if f.Frontend().(*ssafn).stksize >= maxStackSize || fn.Type.ArgWidth() >= maxStackSize {
largeStackFramesMu.Lock()
largeStackFrames = append(largeStackFrames, fn.Pos)
largeStackFrames = append(largeStackFrames, largeStack{locals: f.Frontend().(*ssafn).stksize, args: fn.Type.ArgWidth(), pos: fn.Pos})
largeStackFramesMu.Unlock()
return
}
@ -294,7 +294,8 @@ func compileSSA(fn *Node, worker int) {
// the assembler may emit inscrutable complaints about invalid instructions.
if pp.Text.To.Offset >= maxStackSize {
largeStackFramesMu.Lock()
largeStackFrames = append(largeStackFrames, fn.Pos)
locals := f.Frontend().(*ssafn).stksize
largeStackFrames = append(largeStackFrames, largeStack{locals: locals, args: fn.Type.ArgWidth(), callee: pp.Text.To.Offset - locals, pos: fn.Pos})
largeStackFramesMu.Unlock()
return
}

View file

@ -845,7 +845,7 @@ func (s *state) stmt(n *Node) {
}
case OLABEL:
sym := n.Left.Sym
sym := n.Sym
lab := s.label(sym)
// Associate label with its control flow node, if any
@ -867,7 +867,7 @@ func (s *state) stmt(n *Node) {
s.startBlock(lab.target)
case OGOTO:
sym := n.Left.Sym
sym := n.Sym
lab := s.label(sym)
if lab.target == nil {
@ -1033,7 +1033,7 @@ func (s *state) stmt(n *Node) {
case OCONTINUE, OBREAK:
var to *ssa.Block
if n.Left == nil {
if n.Sym == nil {
// plain break/continue
switch n.Op {
case OCONTINUE:
@ -1043,7 +1043,7 @@ func (s *state) stmt(n *Node) {
}
} else {
// labeled break/continue; look up the target
sym := n.Left.Sym
sym := n.Sym
lab := s.label(sym)
switch n.Op {
case OCONTINUE:
@ -3474,12 +3474,26 @@ func init() {
addF("math/bits", "OnesCount",
makeOnesCountAMD64(ssa.OpPopCount64, ssa.OpPopCount32),
sys.AMD64)
alias("math/bits", "Mul", "math/bits", "Mul64", sys.ArchAMD64, sys.ArchARM64, sys.ArchPPC64)
addF("math/bits", "Mul64",
func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
return s.newValue2(ssa.OpMul64uhilo, types.NewTuple(types.Types[TUINT64], types.Types[TUINT64]), args[0], args[1])
},
sys.AMD64, sys.ARM64, sys.PPC64)
alias("math/bits", "Mul", "math/bits", "Mul64", sys.ArchAMD64, sys.ArchARM64, sys.ArchPPC64)
addF("math/bits", "Add64",
func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
return s.newValue3(ssa.OpAdd64carry, types.NewTuple(types.Types[TUINT64], types.Types[TUINT64]), args[0], args[1], args[2])
},
sys.AMD64)
alias("math/bits", "Add", "math/bits", "Add64", sys.ArchAMD64)
addF("math/bits", "Sub64",
func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
return s.newValue3(ssa.OpSub64borrow, types.NewTuple(types.Types[TUINT64], types.Types[TUINT64]), args[0], args[1], args[2])
},
sys.AMD64)
alias("math/bits", "Sub", "math/bits", "Sub64", sys.ArchAMD64)
/******** sync/atomic ********/
@ -5225,9 +5239,6 @@ func genssa(f *ssa.Func, pp *Progs) {
}
defframe(&s, e)
if Debug['f'] != 0 {
frame(0)
}
f.HTMLWriter.Close()
f.HTMLWriter = nil

View file

@ -28,9 +28,17 @@ type Error struct {
var errors []Error
// largeStack is info about a function whose stack frame is too large (rare).
type largeStack struct {
locals int64
args int64
callee int64
pos src.XPos
}
var (
largeStackFramesMu sync.Mutex // protects largeStackFrames
largeStackFrames []src.XPos // positions of functions whose stack frames are too large (rare)
largeStackFrames []largeStack
)
func errorexit() {
@ -234,7 +242,7 @@ func lookupN(prefix string, n int) *types.Sym {
// to help with debugging.
// It should begin with "." to avoid conflicts with
// user labels.
func autolabel(prefix string) *Node {
func autolabel(prefix string) *types.Sym {
if prefix[0] != '.' {
Fatalf("autolabel prefix must start with '.', have %q", prefix)
}
@ -244,7 +252,7 @@ func autolabel(prefix string) *Node {
}
n := fn.Func.Label
fn.Func.Label++
return newname(lookupN(prefix, int(n)))
return lookupN(prefix, int(n))
}
func restrictlookup(name string, pkg *types.Pkg) *types.Sym {
@ -954,36 +962,6 @@ func typehash(t *types.Type) uint32 {
return binary.LittleEndian.Uint32(h[:4])
}
func frame(context int) {
if context != 0 {
fmt.Printf("--- external frame ---\n")
for _, n := range externdcl {
printframenode(n)
}
return
}
if Curfn != nil {
fmt.Printf("--- %v frame ---\n", Curfn.Func.Nname.Sym)
for _, ln := range Curfn.Func.Dcl {
printframenode(ln)
}
}
}
func printframenode(n *Node) {
w := int64(-1)
if n.Type != nil {
w = n.Type.Width
}
switch n.Op {
case ONAME:
fmt.Printf("%v %v G%d %v width=%d\n", n.Op, n.Sym, n.Name.Vargen, n.Type, w)
case OTYPE:
fmt.Printf("%v %v width=%d\n", n.Op, n.Type, w)
}
}
// updateHasCall checks whether expression n contains any function
// calls and sets the n.HasCall flag if so.
func updateHasCall(n *Node) {

View file

@ -421,7 +421,8 @@ func casebody(sw *Node, typeswvar *Node) {
n.Op = OCASE
needvar := n.List.Len() != 1 || n.List.First().Op == OLITERAL
jmp := nod(OGOTO, autolabel(".s"), nil)
lbl := autolabel(".s")
jmp := nodSym(OGOTO, nil, lbl)
switch n.List.Len() {
case 0:
// default
@ -486,7 +487,7 @@ func casebody(sw *Node, typeswvar *Node) {
}
}
stat = append(stat, nod(OLABEL, jmp.Left, nil))
stat = append(stat, nodSym(OLABEL, nil, lbl))
if typeswvar != nil && needvar && n.Rlist.Len() != 0 {
l := []*Node{
nod(ODCL, n.Rlist.First(), nil),
@ -778,10 +779,10 @@ func (s *typeSwitch) walk(sw *Node) {
} else {
// Jump to default case.
lbl := autolabel(".s")
i.Nbody.Set1(nod(OGOTO, lbl, nil))
i.Nbody.Set1(nodSym(OGOTO, nil, lbl))
// Wrap default case with label.
blk := nod(OBLOCK, nil, nil)
blk.List.Set2(nod(OLABEL, lbl, nil), def)
blk.List.Set2(nodSym(OLABEL, nil, lbl), def)
def = blk
}
i.Left = typecheck(i.Left, Erv)

View file

@ -574,7 +574,7 @@ const (
OXXX Op = iota
// names
ONAME // var, const or func name
ONAME // var or func name
ONONAME // unnamed arg or return value: f(int, string) (int, error) { etc }
OTYPE // type name
OPACK // import
@ -698,10 +698,10 @@ const (
// statements
OBLOCK // { List } (block of code)
OBREAK // break
OBREAK // break [Sym]
OCASE // case Left or List[0]..List[1]: Nbody (select case after processing; Left==nil and List==nil means default)
OXCASE // case List: Nbody (select case before processing; List==nil means default)
OCONTINUE // continue
OCONTINUE // continue [Sym]
ODEFER // defer Left (Left must be call)
OEMPTY // no-op (empty statement)
OFALL // fallthrough
@ -716,9 +716,9 @@ const (
// }
// OFORUNTIL is created by walk. There's no way to write this in Go code.
OFORUNTIL
OGOTO // goto Left
OGOTO // goto Sym
OIF // if Ninit; Left { Nbody } else { Rlist }
OLABEL // Left:
OLABEL // Sym:
OPROC // go Left (Left must be call)
ORANGE // for List = range Right { Nbody }
ORETURN // return List

View file

@ -1984,7 +1984,7 @@ func typecheck1(n *Node, top int) *Node {
case OLABEL:
ok |= Etop
decldepth++
if n.Left.Sym.IsBlank() {
if n.Sym.IsBlank() {
// Empty identifier is valid but useless.
// Eliminate now to simplify life later.
// See issues 7538, 11589, 11593.
@ -2443,7 +2443,7 @@ func lookdot(n *Node, t *types.Type, dostrcmp int) *types.Field {
}
if f1 != nil {
if dostrcmp > 1 {
if dostrcmp > 1 || f1.Broke() {
// Already in the process of diagnosing an error.
return f1
}
@ -3831,12 +3831,12 @@ func markbreak(n *Node, implicit *Node) {
switch n.Op {
case OBREAK:
if n.Left == nil {
if n.Sym == nil {
if implicit != nil {
implicit.SetHasBreak(true)
}
} else {
lab := asNode(n.Left.Sym.Label)
lab := asNode(n.Sym.Label)
if lab != nil {
lab.SetHasBreak(true)
}
@ -3864,9 +3864,9 @@ func markbreaklist(l Nodes, implicit *Node) {
if n.Op == OLABEL && i+1 < len(s) && n.Name.Defn == s[i+1] {
switch n.Name.Defn.Op {
case OFOR, OFORUNTIL, OSWITCH, OTYPESW, OSELECT, ORANGE:
n.Left.Sym.Label = asTypesNode(n.Name.Defn)
n.Sym.Label = asTypesNode(n.Name.Defn)
markbreak(n.Name.Defn, n.Name.Defn)
n.Left.Sym.Label = nil
n.Sym.Label = nil
i++
continue
}

View file

@ -1772,10 +1772,22 @@ func walkCall(n *Node, init *Nodes) {
var tempAssigns []*Node
for i, arg := range args {
updateHasCall(arg)
if instrumenting || arg.HasCall() {
// Determine param type.
var t *types.Type
if n.Op == OCALLMETH {
if i == 0 {
t = n.Left.Type.Recv().Type
} else {
t = params.Field(i - 1).Type
}
} else {
t = params.Field(i).Type
}
if instrumenting || fncall(arg, t) {
// make assignment of fncall to tempname
tmp := temp(arg.Type)
tmp := temp(t)
a := nod(OAS, tmp, arg)
a = convas(a, init)
tempAssigns = append(tempAssigns, a)
// replace arg with temp
args[i] = tmp

View file

@ -771,14 +771,14 @@
(MOVSDstoreidx8 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVSDstoreidx8 [int64(int32(c+8*d))] {sym} ptr idx val mem)
// Merge load/store to op
((ADD|AND|OR|XOR|SUB|MUL)L x l:(MOVLload [off] {sym} ptr mem)) && canMergeLoad(v, l, x) && clobber(l) -> ((ADD|AND|OR|XOR|SUB|MUL)Lload x [off] {sym} ptr mem)
((ADD|AND|OR|XOR|SUB|MUL)L x l:(MOVLloadidx4 [off] {sym} ptr idx mem)) && canMergeLoad(v, l, x) && clobber(l) ->
((ADD|AND|OR|XOR|SUB|MUL)L x l:(MOVLload [off] {sym} ptr mem)) && canMergeLoadClobber(v, l, x) && clobber(l) -> ((ADD|AND|OR|XOR|SUB|MUL)Lload x [off] {sym} ptr mem)
((ADD|AND|OR|XOR|SUB|MUL)L x l:(MOVLloadidx4 [off] {sym} ptr idx mem)) && canMergeLoadClobber(v, l, x) && clobber(l) ->
((ADD|AND|OR|XOR|SUB|MUL)Lloadidx4 x [off] {sym} ptr idx mem)
((ADD|SUB|MUL|AND|OR|XOR)Lload [off1] {sym1} val (LEAL4 [off2] {sym2} ptr idx) mem)
&& is32Bit(off1+off2) && canMergeSym(sym1, sym2) ->
((ADD|SUB|MUL|AND|OR|XOR)Lloadidx4 [off1+off2] {mergeSym(sym1,sym2)} val ptr idx mem)
((ADD|SUB|MUL|DIV)SD x l:(MOVSDload [off] {sym} ptr mem)) && canMergeLoad(v, l, x) && !config.use387 && clobber(l) -> ((ADD|SUB|MUL|DIV)SDload x [off] {sym} ptr mem)
((ADD|SUB|MUL|DIV)SS x l:(MOVSSload [off] {sym} ptr mem)) && canMergeLoad(v, l, x) && !config.use387 && clobber(l) -> ((ADD|SUB|MUL|DIV)SSload x [off] {sym} ptr mem)
((ADD|SUB|MUL|DIV)SD x l:(MOVSDload [off] {sym} ptr mem)) && canMergeLoadClobber(v, l, x) && !config.use387 && clobber(l) -> ((ADD|SUB|MUL|DIV)SDload x [off] {sym} ptr mem)
((ADD|SUB|MUL|DIV)SS x l:(MOVSSload [off] {sym} ptr mem)) && canMergeLoadClobber(v, l, x) && !config.use387 && clobber(l) -> ((ADD|SUB|MUL|DIV)SSload x [off] {sym} ptr mem)
(MOVLstore {sym} [off] ptr y:((ADD|AND|OR|XOR)Lload x [off] {sym} ptr mem) mem) && y.Uses==1 && clobber(y) -> ((ADD|AND|OR|XOR)Lmodify [off] {sym} ptr x mem)
(MOVLstore {sym} [off] ptr y:((ADD|SUB|AND|OR|XOR)L l:(MOVLload [off] {sym} ptr mem) x) mem) && y.Uses==1 && l.Uses==1 && clobber(y) && clobber(l) ->
((ADD|SUB|AND|OR|XOR)Lmodify [off] {sym} ptr x mem)
@ -1217,8 +1217,8 @@
(MOVSSconst [c]) && config.ctxt.Flag_shared -> (MOVSSconst2 (MOVSSconst1 [c]))
(MOVSDconst [c]) && config.ctxt.Flag_shared -> (MOVSDconst2 (MOVSDconst1 [c]))
(CMP(L|W|B) l:(MOV(L|W|B)load {sym} [off] ptr mem) x) && canMergeLoad(v, l, x) && clobber(l) -> (CMP(L|W|B)load {sym} [off] ptr x mem)
(CMP(L|W|B) x l:(MOV(L|W|B)load {sym} [off] ptr mem)) && canMergeLoad(v, l, x) && clobber(l) -> (InvertFlags (CMP(L|W|B)load {sym} [off] ptr x mem))
(CMP(L|W|B) l:(MOV(L|W|B)load {sym} [off] ptr mem) x) && canMergeLoad(v, l) && clobber(l) -> (CMP(L|W|B)load {sym} [off] ptr x mem)
(CMP(L|W|B) x l:(MOV(L|W|B)load {sym} [off] ptr mem)) && canMergeLoad(v, l) && clobber(l) -> (InvertFlags (CMP(L|W|B)load {sym} [off] ptr x mem))
(CMP(L|W|B)const l:(MOV(L|W|B)load {sym} [off] ptr mem) [c])
&& l.Uses == 1

View file

@ -29,6 +29,28 @@
(Div8u x y) -> (Select0 (DIVWU (ZeroExt8to16 x) (ZeroExt8to16 y)))
(Div(32|64)F x y) -> (DIVS(S|D) x y)
(Select0 (Add64carry x y c)) ->
(Select0 <typ.UInt64> (ADCQ x y (Select1 <types.TypeFlags> (NEGLflags c))))
(Select1 (Add64carry x y c)) ->
(NEGQ <typ.UInt64> (SBBQcarrymask <typ.UInt64> (Select1 <types.TypeFlags> (ADCQ x y (Select1 <types.TypeFlags> (NEGLflags c))))))
(Select0 (Sub64borrow x y c)) ->
(Select0 <typ.UInt64> (SBBQ x y (Select1 <types.TypeFlags> (NEGLflags c))))
(Select1 (Sub64borrow x y c)) ->
(NEGQ <typ.UInt64> (SBBQcarrymask <typ.UInt64> (Select1 <types.TypeFlags> (SBBQ x y (Select1 <types.TypeFlags> (NEGLflags c))))))
// Optimize ADCQ and friends
(ADCQ x (MOVQconst [c]) carry) && is32Bit(c) -> (ADCQconst x [c] carry)
(ADCQ x y (FlagEQ)) -> (ADDQcarry x y)
(ADCQconst x [c] (FlagEQ)) -> (ADDQconstcarry x [c])
(ADDQcarry x (MOVQconst [c])) && is32Bit(c) -> (ADDQconstcarry x [c])
(SBBQ x (MOVQconst [c]) borrow) && is32Bit(c) -> (SBBQconst x [c] borrow)
(SBBQ x y (FlagEQ)) -> (SUBQborrow x y)
(SBBQconst x [c] (FlagEQ)) -> (SUBQconstborrow x [c])
(SUBQborrow x (MOVQconst [c])) && is32Bit(c) -> (SUBQconstborrow x [c])
(Select1 (NEGLflags (MOVQconst [0]))) -> (FlagEQ)
(Select1 (NEGLflags (NEGQ (SBBQcarrymask x)))) -> x
(Mul64uhilo x y) -> (MULQU2 x y)
(Div128u xhi xlo y) -> (DIVQU2 xhi xlo y)
@ -2340,10 +2362,10 @@
// Merge load and op
// TODO: add indexed variants?
((ADD|SUB|AND|OR|XOR)Q x l:(MOVQload [off] {sym} ptr mem)) && canMergeLoad(v, l, x) && clobber(l) -> ((ADD|SUB|AND|OR|XOR)Qload x [off] {sym} ptr mem)
((ADD|SUB|AND|OR|XOR)L x l:(MOVLload [off] {sym} ptr mem)) && canMergeLoad(v, l, x) && clobber(l) -> ((ADD|SUB|AND|OR|XOR)Lload x [off] {sym} ptr mem)
((ADD|SUB|MUL|DIV)SD x l:(MOVSDload [off] {sym} ptr mem)) && canMergeLoad(v, l, x) && clobber(l) -> ((ADD|SUB|MUL|DIV)SDload x [off] {sym} ptr mem)
((ADD|SUB|MUL|DIV)SS x l:(MOVSSload [off] {sym} ptr mem)) && canMergeLoad(v, l, x) && clobber(l) -> ((ADD|SUB|MUL|DIV)SSload x [off] {sym} ptr mem)
((ADD|SUB|AND|OR|XOR)Q x l:(MOVQload [off] {sym} ptr mem)) && canMergeLoadClobber(v, l, x) && clobber(l) -> ((ADD|SUB|AND|OR|XOR)Qload x [off] {sym} ptr mem)
((ADD|SUB|AND|OR|XOR)L x l:(MOVLload [off] {sym} ptr mem)) && canMergeLoadClobber(v, l, x) && clobber(l) -> ((ADD|SUB|AND|OR|XOR)Lload x [off] {sym} ptr mem)
((ADD|SUB|MUL|DIV)SD x l:(MOVSDload [off] {sym} ptr mem)) && canMergeLoadClobber(v, l, x) && clobber(l) -> ((ADD|SUB|MUL|DIV)SDload x [off] {sym} ptr mem)
((ADD|SUB|MUL|DIV)SS x l:(MOVSSload [off] {sym} ptr mem)) && canMergeLoadClobber(v, l, x) && clobber(l) -> ((ADD|SUB|MUL|DIV)SSload x [off] {sym} ptr mem)
(MOVLstore {sym} [off] ptr y:((ADD|AND|OR|XOR)Lload x [off] {sym} ptr mem) mem) && y.Uses==1 && clobber(y) -> ((ADD|AND|OR|XOR)Lmodify [off] {sym} ptr x mem)
(MOVLstore {sym} [off] ptr y:((ADD|SUB|AND|OR|XOR|BTC|BTR|BTS)L l:(MOVLload [off] {sym} ptr mem) x) mem) && y.Uses==1 && l.Uses==1 && clobber(y) && clobber(l) ->
((ADD|SUB|AND|OR|XOR|BTC|BTR|BTS)Lmodify [off] {sym} ptr x mem)
@ -2492,8 +2514,8 @@
// Fold loads into compares
// Note: these may be undone by the flagalloc pass.
(CMP(Q|L|W|B) l:(MOV(Q|L|W|B)load {sym} [off] ptr mem) x) && canMergeLoad(v, l, x) && clobber(l) -> (CMP(Q|L|W|B)load {sym} [off] ptr x mem)
(CMP(Q|L|W|B) x l:(MOV(Q|L|W|B)load {sym} [off] ptr mem)) && canMergeLoad(v, l, x) && clobber(l) -> (InvertFlags (CMP(Q|L|W|B)load {sym} [off] ptr x mem))
(CMP(Q|L|W|B) l:(MOV(Q|L|W|B)load {sym} [off] ptr mem) x) && canMergeLoad(v, l) && clobber(l) -> (CMP(Q|L|W|B)load {sym} [off] ptr x mem)
(CMP(Q|L|W|B) x l:(MOV(Q|L|W|B)load {sym} [off] ptr mem)) && canMergeLoad(v, l) && clobber(l) -> (InvertFlags (CMP(Q|L|W|B)load {sym} [off] ptr x mem))
(CMP(Q|L|W|B)const l:(MOV(Q|L|W|B)load {sym} [off] ptr mem) [c])
&& l.Uses == 1

View file

@ -107,16 +107,18 @@ func init() {
// Common regInfo
var (
gp01 = regInfo{inputs: nil, outputs: gponly}
gp11 = regInfo{inputs: []regMask{gp}, outputs: gponly}
gp11sp = regInfo{inputs: []regMask{gpsp}, outputs: gponly}
gp11sb = regInfo{inputs: []regMask{gpspsb}, outputs: gponly}
gp21 = regInfo{inputs: []regMask{gp, gp}, outputs: gponly}
gp21sp = regInfo{inputs: []regMask{gpsp, gp}, outputs: gponly}
gp21sb = regInfo{inputs: []regMask{gpspsb, gpsp}, outputs: gponly}
gp21shift = regInfo{inputs: []regMask{gp, cx}, outputs: []regMask{gp}}
gp11div = regInfo{inputs: []regMask{ax, gpsp &^ dx}, outputs: []regMask{ax, dx}}
gp21hmul = regInfo{inputs: []regMask{ax, gpsp}, outputs: []regMask{dx}, clobbers: ax}
gp01 = regInfo{inputs: nil, outputs: gponly}
gp11 = regInfo{inputs: []regMask{gp}, outputs: gponly}
gp11sp = regInfo{inputs: []regMask{gpsp}, outputs: gponly}
gp11sb = regInfo{inputs: []regMask{gpspsb}, outputs: gponly}
gp21 = regInfo{inputs: []regMask{gp, gp}, outputs: gponly}
gp21sp = regInfo{inputs: []regMask{gpsp, gp}, outputs: gponly}
gp21sb = regInfo{inputs: []regMask{gpspsb, gpsp}, outputs: gponly}
gp21shift = regInfo{inputs: []regMask{gp, cx}, outputs: []regMask{gp}}
gp11div = regInfo{inputs: []regMask{ax, gpsp &^ dx}, outputs: []regMask{ax, dx}}
gp21hmul = regInfo{inputs: []regMask{ax, gpsp}, outputs: []regMask{dx}, clobbers: ax}
gp21flags = regInfo{inputs: []regMask{gp, gp}, outputs: []regMask{gp, 0}}
gp2flags1flags = regInfo{inputs: []regMask{gp, gp, 0}, outputs: []regMask{gp, 0}}
gp2flags = regInfo{inputs: []regMask{gpsp, gpsp}}
gp1flags = regInfo{inputs: []regMask{gpsp}}
@ -124,7 +126,8 @@ func init() {
gp1flagsLoad = regInfo{inputs: []regMask{gpspsb, gpsp, 0}}
flagsgp = regInfo{inputs: nil, outputs: gponly}
gp11flags = regInfo{inputs: []regMask{gp}, outputs: []regMask{gp, 0}}
gp11flags = regInfo{inputs: []regMask{gp}, outputs: []regMask{gp, 0}}
gp1flags1flags = regInfo{inputs: []regMask{gp, 0}, outputs: []regMask{gp, 0}}
readflags = regInfo{inputs: nil, outputs: gponly}
flagsgpax = regInfo{inputs: nil, clobbers: ax, outputs: []regMask{gp &^ ax}}
@ -229,6 +232,21 @@ func init() {
{name: "DIVLU", argLength: 2, reg: gp11div, typ: "(UInt32,UInt32)", asm: "DIVL", clobberFlags: true}, // [arg0 / arg1, arg0 % arg1]
{name: "DIVWU", argLength: 2, reg: gp11div, typ: "(UInt16,UInt16)", asm: "DIVW", clobberFlags: true}, // [arg0 / arg1, arg0 % arg1]
{name: "NEGLflags", argLength: 1, reg: gp11flags, typ: "(UInt32,Flags)", asm: "NEGL", resultInArg0: true}, // -arg0, flags set for 0-arg0.
// The following 4 add opcodes return the low 64 bits of the sum in the first result and
// the carry (the 65th bit) in the carry flag.
{name: "ADDQcarry", argLength: 2, reg: gp21flags, typ: "(UInt64,Flags)", asm: "ADDQ", commutative: true, resultInArg0: true}, // r = arg0+arg1
{name: "ADCQ", argLength: 3, reg: gp2flags1flags, typ: "(UInt64,Flags)", asm: "ADCQ", commutative: true, resultInArg0: true}, // r = arg0+arg1+carry(arg2)
{name: "ADDQconstcarry", argLength: 1, reg: gp11flags, typ: "(UInt64,Flags)", asm: "ADDQ", aux: "Int32", resultInArg0: true}, // r = arg0+auxint
{name: "ADCQconst", argLength: 2, reg: gp1flags1flags, typ: "(UInt64,Flags)", asm: "ADCQ", aux: "Int32", resultInArg0: true}, // r = arg0+auxint+carry(arg1)
// The following 4 add opcodes return the low 64 bits of the difference in the first result and
// the borrow (if the result is negative) in the carry flag.
{name: "SUBQborrow", argLength: 2, reg: gp21flags, typ: "(UInt64,Flags)", asm: "SUBQ", resultInArg0: true}, // r = arg0-arg1
{name: "SBBQ", argLength: 3, reg: gp2flags1flags, typ: "(UInt64,Flags)", asm: "SBBQ", resultInArg0: true}, // r = arg0-(arg1+carry(arg2))
{name: "SUBQconstborrow", argLength: 1, reg: gp11flags, typ: "(UInt64,Flags)", asm: "SUBQ", aux: "Int32", resultInArg0: true}, // r = arg0-auxint
{name: "SBBQconst", argLength: 2, reg: gp1flags1flags, typ: "(UInt64,Flags)", asm: "SBBQ", aux: "Int32", resultInArg0: true}, // r = arg0-(auxint+carry(arg1))
{name: "MULQU2", argLength: 2, reg: regInfo{inputs: []regMask{ax, gpsp}, outputs: []regMask{dx, ax}}, commutative: true, asm: "MULQ", clobberFlags: true}, // arg0 * arg1, returns (hi, lo)
{name: "DIVQU2", argLength: 3, reg: regInfo{inputs: []regMask{dx, ax, gpsp}, outputs: []regMask{ax, dx}}, asm: "DIVQ", clobberFlags: true}, // arg0:arg1 / arg2 (128-bit divided by 64-bit), returns (q, r)

View file

@ -1125,71 +1125,71 @@
// Exclude global data (SB) because these instructions cannot handle relative addresses.
// TODO(mundaym): use LARL in the assembler to handle SB?
// TODO(mundaym): indexed versions of these?
(ADD <t> x g:(MOVDload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoad(v, g, x) && clobber(g)
(ADD <t> x g:(MOVDload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoadClobber(v, g, x) && clobber(g)
-> (ADDload <t> [off] {sym} x ptr mem)
(ADD <t> g:(MOVDload [off] {sym} ptr mem) x) && ptr.Op != OpSB && is20Bit(off) && canMergeLoad(v, g, x) && clobber(g)
(ADD <t> g:(MOVDload [off] {sym} ptr mem) x) && ptr.Op != OpSB && is20Bit(off) && canMergeLoadClobber(v, g, x) && clobber(g)
-> (ADDload <t> [off] {sym} x ptr mem)
(ADDW <t> x g:(MOVWload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoad(v, g, x) && clobber(g)
(ADDW <t> x g:(MOVWload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoadClobber(v, g, x) && clobber(g)
-> (ADDWload <t> [off] {sym} x ptr mem)
(ADDW <t> g:(MOVWload [off] {sym} ptr mem) x) && ptr.Op != OpSB && is20Bit(off) && canMergeLoad(v, g, x) && clobber(g)
(ADDW <t> g:(MOVWload [off] {sym} ptr mem) x) && ptr.Op != OpSB && is20Bit(off) && canMergeLoadClobber(v, g, x) && clobber(g)
-> (ADDWload <t> [off] {sym} x ptr mem)
(ADDW <t> x g:(MOVWZload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoad(v, g, x) && clobber(g)
(ADDW <t> x g:(MOVWZload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoadClobber(v, g, x) && clobber(g)
-> (ADDWload <t> [off] {sym} x ptr mem)
(ADDW <t> g:(MOVWZload [off] {sym} ptr mem) x) && ptr.Op != OpSB && is20Bit(off) && canMergeLoad(v, g, x) && clobber(g)
(ADDW <t> g:(MOVWZload [off] {sym} ptr mem) x) && ptr.Op != OpSB && is20Bit(off) && canMergeLoadClobber(v, g, x) && clobber(g)
-> (ADDWload <t> [off] {sym} x ptr mem)
(MULLD <t> x g:(MOVDload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoad(v, g, x) && clobber(g)
(MULLD <t> x g:(MOVDload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoadClobber(v, g, x) && clobber(g)
-> (MULLDload <t> [off] {sym} x ptr mem)
(MULLD <t> g:(MOVDload [off] {sym} ptr mem) x) && ptr.Op != OpSB && is20Bit(off) && canMergeLoad(v, g, x) && clobber(g)
(MULLD <t> g:(MOVDload [off] {sym} ptr mem) x) && ptr.Op != OpSB && is20Bit(off) && canMergeLoadClobber(v, g, x) && clobber(g)
-> (MULLDload <t> [off] {sym} x ptr mem)
(MULLW <t> x g:(MOVWload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoad(v, g, x) && clobber(g)
(MULLW <t> x g:(MOVWload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoadClobber(v, g, x) && clobber(g)
-> (MULLWload <t> [off] {sym} x ptr mem)
(MULLW <t> g:(MOVWload [off] {sym} ptr mem) x) && ptr.Op != OpSB && is20Bit(off) && canMergeLoad(v, g, x) && clobber(g)
(MULLW <t> g:(MOVWload [off] {sym} ptr mem) x) && ptr.Op != OpSB && is20Bit(off) && canMergeLoadClobber(v, g, x) && clobber(g)
-> (MULLWload <t> [off] {sym} x ptr mem)
(MULLW <t> x g:(MOVWZload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoad(v, g, x) && clobber(g)
(MULLW <t> x g:(MOVWZload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoadClobber(v, g, x) && clobber(g)
-> (MULLWload <t> [off] {sym} x ptr mem)
(MULLW <t> g:(MOVWZload [off] {sym} ptr mem) x) && ptr.Op != OpSB && is20Bit(off) && canMergeLoad(v, g, x) && clobber(g)
(MULLW <t> g:(MOVWZload [off] {sym} ptr mem) x) && ptr.Op != OpSB && is20Bit(off) && canMergeLoadClobber(v, g, x) && clobber(g)
-> (MULLWload <t> [off] {sym} x ptr mem)
(SUB <t> x g:(MOVDload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoad(v, g, x) && clobber(g)
(SUB <t> x g:(MOVDload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoadClobber(v, g, x) && clobber(g)
-> (SUBload <t> [off] {sym} x ptr mem)
(SUBW <t> x g:(MOVWload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoad(v, g, x) && clobber(g)
(SUBW <t> x g:(MOVWload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoadClobber(v, g, x) && clobber(g)
-> (SUBWload <t> [off] {sym} x ptr mem)
(SUBW <t> x g:(MOVWZload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoad(v, g, x) && clobber(g)
(SUBW <t> x g:(MOVWZload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoadClobber(v, g, x) && clobber(g)
-> (SUBWload <t> [off] {sym} x ptr mem)
(AND <t> x g:(MOVDload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoad(v, g, x) && clobber(g)
(AND <t> x g:(MOVDload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoadClobber(v, g, x) && clobber(g)
-> (ANDload <t> [off] {sym} x ptr mem)
(AND <t> g:(MOVDload [off] {sym} ptr mem) x) && ptr.Op != OpSB && is20Bit(off) && canMergeLoad(v, g, x) && clobber(g)
(AND <t> g:(MOVDload [off] {sym} ptr mem) x) && ptr.Op != OpSB && is20Bit(off) && canMergeLoadClobber(v, g, x) && clobber(g)
-> (ANDload <t> [off] {sym} x ptr mem)
(ANDW <t> x g:(MOVWload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoad(v, g, x) && clobber(g)
(ANDW <t> x g:(MOVWload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoadClobber(v, g, x) && clobber(g)
-> (ANDWload <t> [off] {sym} x ptr mem)
(ANDW <t> g:(MOVWload [off] {sym} ptr mem) x) && ptr.Op != OpSB && is20Bit(off) && canMergeLoad(v, g, x) && clobber(g)
(ANDW <t> g:(MOVWload [off] {sym} ptr mem) x) && ptr.Op != OpSB && is20Bit(off) && canMergeLoadClobber(v, g, x) && clobber(g)
-> (ANDWload <t> [off] {sym} x ptr mem)
(ANDW <t> x g:(MOVWZload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoad(v, g, x) && clobber(g)
(ANDW <t> x g:(MOVWZload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoadClobber(v, g, x) && clobber(g)
-> (ANDWload <t> [off] {sym} x ptr mem)
(ANDW <t> g:(MOVWZload [off] {sym} ptr mem) x) && ptr.Op != OpSB && is20Bit(off) && canMergeLoad(v, g, x) && clobber(g)
(ANDW <t> g:(MOVWZload [off] {sym} ptr mem) x) && ptr.Op != OpSB && is20Bit(off) && canMergeLoadClobber(v, g, x) && clobber(g)
-> (ANDWload <t> [off] {sym} x ptr mem)
(OR <t> x g:(MOVDload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoad(v, g, x) && clobber(g)
(OR <t> x g:(MOVDload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoadClobber(v, g, x) && clobber(g)
-> (ORload <t> [off] {sym} x ptr mem)
(OR <t> g:(MOVDload [off] {sym} ptr mem) x) && ptr.Op != OpSB && is20Bit(off) && canMergeLoad(v, g, x) && clobber(g)
(OR <t> g:(MOVDload [off] {sym} ptr mem) x) && ptr.Op != OpSB && is20Bit(off) && canMergeLoadClobber(v, g, x) && clobber(g)
-> (ORload <t> [off] {sym} x ptr mem)
(ORW <t> x g:(MOVWload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoad(v, g, x) && clobber(g)
(ORW <t> x g:(MOVWload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoadClobber(v, g, x) && clobber(g)
-> (ORWload <t> [off] {sym} x ptr mem)
(ORW <t> g:(MOVWload [off] {sym} ptr mem) x) && ptr.Op != OpSB && is20Bit(off) && canMergeLoad(v, g, x) && clobber(g)
(ORW <t> g:(MOVWload [off] {sym} ptr mem) x) && ptr.Op != OpSB && is20Bit(off) && canMergeLoadClobber(v, g, x) && clobber(g)
-> (ORWload <t> [off] {sym} x ptr mem)
(ORW <t> x g:(MOVWZload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoad(v, g, x) && clobber(g)
(ORW <t> x g:(MOVWZload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoadClobber(v, g, x) && clobber(g)
-> (ORWload <t> [off] {sym} x ptr mem)
(ORW <t> g:(MOVWZload [off] {sym} ptr mem) x) && ptr.Op != OpSB && is20Bit(off) && canMergeLoad(v, g, x) && clobber(g)
(ORW <t> g:(MOVWZload [off] {sym} ptr mem) x) && ptr.Op != OpSB && is20Bit(off) && canMergeLoadClobber(v, g, x) && clobber(g)
-> (ORWload <t> [off] {sym} x ptr mem)
(XOR <t> x g:(MOVDload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoad(v, g, x) && clobber(g)
(XOR <t> x g:(MOVDload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoadClobber(v, g, x) && clobber(g)
-> (XORload <t> [off] {sym} x ptr mem)
(XOR <t> g:(MOVDload [off] {sym} ptr mem) x) && ptr.Op != OpSB && is20Bit(off) && canMergeLoad(v, g, x) && clobber(g)
(XOR <t> g:(MOVDload [off] {sym} ptr mem) x) && ptr.Op != OpSB && is20Bit(off) && canMergeLoadClobber(v, g, x) && clobber(g)
-> (XORload <t> [off] {sym} x ptr mem)
(XORW <t> x g:(MOVWload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoad(v, g, x) && clobber(g)
(XORW <t> x g:(MOVWload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoadClobber(v, g, x) && clobber(g)
-> (XORWload <t> [off] {sym} x ptr mem)
(XORW <t> g:(MOVWload [off] {sym} ptr mem) x) && ptr.Op != OpSB && is20Bit(off) && canMergeLoad(v, g, x) && clobber(g)
(XORW <t> g:(MOVWload [off] {sym} ptr mem) x) && ptr.Op != OpSB && is20Bit(off) && canMergeLoadClobber(v, g, x) && clobber(g)
-> (XORWload <t> [off] {sym} x ptr mem)
(XORW <t> x g:(MOVWZload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoad(v, g, x) && clobber(g)
(XORW <t> x g:(MOVWZload [off] {sym} ptr mem)) && ptr.Op != OpSB && is20Bit(off) && canMergeLoadClobber(v, g, x) && clobber(g)
-> (XORWload <t> [off] {sym} x ptr mem)
(XORW <t> g:(MOVWZload [off] {sym} ptr mem) x) && ptr.Op != OpSB && is20Bit(off) && canMergeLoad(v, g, x) && clobber(g)
(XORW <t> g:(MOVWZload [off] {sym} ptr mem) x) && ptr.Op != OpSB && is20Bit(off) && canMergeLoadClobber(v, g, x) && clobber(g)
-> (XORWload <t> [off] {sym} x ptr mem)
// Combine constant stores into larger (unaligned) stores.

View file

@ -491,6 +491,9 @@ var genericOps = []opData{
{name: "Sub32carry", argLength: 2, typ: "(UInt32,Flags)"}, // arg0 - arg1, returns (value, carry)
{name: "Sub32withcarry", argLength: 3}, // arg0 - arg1 - arg2, arg2=carry (0 or 1)
{name: "Add64carry", argLength: 3, commutative: true, typ: "(UInt64,UInt64)"}, // arg0 + arg1 + arg2, arg2 must be 0 or 1. returns (value, value>>64)
{name: "Sub64borrow", argLength: 3, typ: "(UInt64,UInt64)"}, // arg0 - (arg1 + arg2), arg2 must be 0 or 1. returns (value, value>>64&1)
{name: "Signmask", argLength: 1, typ: "Int32"}, // 0 if arg0 >= 0, -1 if arg0 < 0
{name: "Zeromask", argLength: 1, typ: "UInt32"}, // 0 if arg0 == 0, 0xffffffff if arg0 != 0
{name: "Slicemask", argLength: 1}, // 0 if arg0 == 0, -1 if arg0 > 0, undef if arg0<0. Type is native int size.

View file

@ -160,10 +160,12 @@ func genRules(arch arch) {
fmt.Fprintln(w, "// generated with: cd gen; go run *.go")
fmt.Fprintln(w)
fmt.Fprintln(w, "package ssa")
fmt.Fprintln(w, "import \"fmt\"")
fmt.Fprintln(w, "import \"math\"")
fmt.Fprintln(w, "import \"cmd/internal/obj\"")
fmt.Fprintln(w, "import \"cmd/internal/objabi\"")
fmt.Fprintln(w, "import \"cmd/compile/internal/types\"")
fmt.Fprintln(w, "var _ = fmt.Println // in case not otherwise used")
fmt.Fprintln(w, "var _ = math.MinInt8 // in case not otherwise used")
fmt.Fprintln(w, "var _ = obj.ANOP // in case not otherwise used")
fmt.Fprintln(w, "var _ = objabi.GOROOT // in case not otherwise used")

View file

@ -50,10 +50,14 @@ body {
font-family: Arial, sans-serif;
}
h1 {
font-size: 18px;
display: inline-block;
margin: 0 1em .5em 0;
}
#helplink {
margin-bottom: 15px;
display: block;
margin-top: -15px;
display: inline-block;
}
#help {

View file

@ -523,6 +523,15 @@ const (
OpAMD64DIVQU
OpAMD64DIVLU
OpAMD64DIVWU
OpAMD64NEGLflags
OpAMD64ADDQcarry
OpAMD64ADCQ
OpAMD64ADDQconstcarry
OpAMD64ADCQconst
OpAMD64SUBQborrow
OpAMD64SBBQ
OpAMD64SUBQconstborrow
OpAMD64SBBQconst
OpAMD64MULQU2
OpAMD64DIVQU2
OpAMD64ANDQ
@ -2393,6 +2402,8 @@ const (
OpAdd32withcarry
OpSub32carry
OpSub32withcarry
OpAdd64carry
OpSub64borrow
OpSignmask
OpZeromask
OpSlicemask
@ -6540,6 +6551,151 @@ var opcodeTable = [...]opInfo{
},
},
},
{
name: "NEGLflags",
argLen: 1,
resultInArg0: true,
asm: x86.ANEGL,
reg: regInfo{
inputs: []inputInfo{
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
},
outputs: []outputInfo{
{1, 0},
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
},
},
},
{
name: "ADDQcarry",
argLen: 2,
commutative: true,
resultInArg0: true,
asm: x86.AADDQ,
reg: regInfo{
inputs: []inputInfo{
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
},
outputs: []outputInfo{
{1, 0},
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
},
},
},
{
name: "ADCQ",
argLen: 3,
commutative: true,
resultInArg0: true,
asm: x86.AADCQ,
reg: regInfo{
inputs: []inputInfo{
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
},
outputs: []outputInfo{
{1, 0},
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
},
},
},
{
name: "ADDQconstcarry",
auxType: auxInt32,
argLen: 1,
resultInArg0: true,
asm: x86.AADDQ,
reg: regInfo{
inputs: []inputInfo{
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
},
outputs: []outputInfo{
{1, 0},
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
},
},
},
{
name: "ADCQconst",
auxType: auxInt32,
argLen: 2,
resultInArg0: true,
asm: x86.AADCQ,
reg: regInfo{
inputs: []inputInfo{
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
},
outputs: []outputInfo{
{1, 0},
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
},
},
},
{
name: "SUBQborrow",
argLen: 2,
resultInArg0: true,
asm: x86.ASUBQ,
reg: regInfo{
inputs: []inputInfo{
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
},
outputs: []outputInfo{
{1, 0},
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
},
},
},
{
name: "SBBQ",
argLen: 3,
resultInArg0: true,
asm: x86.ASBBQ,
reg: regInfo{
inputs: []inputInfo{
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
},
outputs: []outputInfo{
{1, 0},
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
},
},
},
{
name: "SUBQconstborrow",
auxType: auxInt32,
argLen: 1,
resultInArg0: true,
asm: x86.ASUBQ,
reg: regInfo{
inputs: []inputInfo{
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
},
outputs: []outputInfo{
{1, 0},
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
},
},
},
{
name: "SBBQconst",
auxType: auxInt32,
argLen: 2,
resultInArg0: true,
asm: x86.ASBBQ,
reg: regInfo{
inputs: []inputInfo{
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
},
outputs: []outputInfo{
{1, 0},
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
},
},
},
{
name: "MULQU2",
argLen: 2,
@ -29629,6 +29785,17 @@ var opcodeTable = [...]opInfo{
argLen: 3,
generic: true,
},
{
name: "Add64carry",
argLen: 3,
commutative: true,
generic: true,
},
{
name: "Sub64borrow",
argLen: 3,
generic: true,
},
{
name: "Signmask",
argLen: 1,

View file

@ -177,23 +177,11 @@ func canMergeSym(x, y interface{}) bool {
return x == nil || y == nil
}
// canMergeLoad reports whether the load can be merged into target without
// canMergeLoadClobber reports whether the load can be merged into target without
// invalidating the schedule.
// It also checks that the other non-load argument x is something we
// are ok with clobbering (all our current load+op instructions clobber
// their input register).
func canMergeLoad(target, load, x *Value) bool {
if target.Block.ID != load.Block.ID {
// If the load is in a different block do not merge it.
return false
}
// We can't merge the load into the target if the load
// has more than one use.
if load.Uses != 1 {
return false
}
// are ok with clobbering.
func canMergeLoadClobber(target, load, x *Value) bool {
// The register containing x is going to get clobbered.
// Don't merge if we still need the value of x.
// We don't have liveness information here, but we can
@ -208,6 +196,22 @@ func canMergeLoad(target, load, x *Value) bool {
if loopnest.depth(target.Block.ID) > loopnest.depth(x.Block.ID) {
return false
}
return canMergeLoad(target, load)
}
// canMergeLoad reports whether the load can be merged into target without
// invalidating the schedule.
func canMergeLoad(target, load *Value) bool {
if target.Block.ID != load.Block.ID {
// If the load is in a different block do not merge it.
return false
}
// We can't merge the load into the target if the load
// has more than one use.
if load.Uses != 1 {
return false
}
mem := load.MemoryArg()

View file

@ -3,11 +3,13 @@
package ssa
import "fmt"
import "math"
import "cmd/internal/obj"
import "cmd/internal/objabi"
import "cmd/compile/internal/types"
var _ = fmt.Println // in case not otherwise used
var _ = math.MinInt8 // in case not otherwise used
var _ = obj.ANOP // in case not otherwise used
var _ = objabi.GOROOT // in case not otherwise used
@ -1297,7 +1299,7 @@ func rewriteValue386_Op386ADDL_20(v *Value) bool {
return true
}
// match: (ADDL x l:(MOVLload [off] {sym} ptr mem))
// cond: canMergeLoad(v, l, x) && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && clobber(l)
// result: (ADDLload x [off] {sym} ptr mem)
for {
_ = v.Args[1]
@ -1311,7 +1313,7 @@ func rewriteValue386_Op386ADDL_20(v *Value) bool {
_ = l.Args[1]
ptr := l.Args[0]
mem := l.Args[1]
if !(canMergeLoad(v, l, x) && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
break
}
v.reset(Op386ADDLload)
@ -1323,7 +1325,7 @@ func rewriteValue386_Op386ADDL_20(v *Value) bool {
return true
}
// match: (ADDL l:(MOVLload [off] {sym} ptr mem) x)
// cond: canMergeLoad(v, l, x) && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && clobber(l)
// result: (ADDLload x [off] {sym} ptr mem)
for {
_ = v.Args[1]
@ -1337,7 +1339,7 @@ func rewriteValue386_Op386ADDL_20(v *Value) bool {
ptr := l.Args[0]
mem := l.Args[1]
x := v.Args[1]
if !(canMergeLoad(v, l, x) && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
break
}
v.reset(Op386ADDLload)
@ -1349,7 +1351,7 @@ func rewriteValue386_Op386ADDL_20(v *Value) bool {
return true
}
// match: (ADDL x l:(MOVLloadidx4 [off] {sym} ptr idx mem))
// cond: canMergeLoad(v, l, x) && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && clobber(l)
// result: (ADDLloadidx4 x [off] {sym} ptr idx mem)
for {
_ = v.Args[1]
@ -1364,7 +1366,7 @@ func rewriteValue386_Op386ADDL_20(v *Value) bool {
ptr := l.Args[0]
idx := l.Args[1]
mem := l.Args[2]
if !(canMergeLoad(v, l, x) && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
break
}
v.reset(Op386ADDLloadidx4)
@ -1377,7 +1379,7 @@ func rewriteValue386_Op386ADDL_20(v *Value) bool {
return true
}
// match: (ADDL l:(MOVLloadidx4 [off] {sym} ptr idx mem) x)
// cond: canMergeLoad(v, l, x) && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && clobber(l)
// result: (ADDLloadidx4 x [off] {sym} ptr idx mem)
for {
_ = v.Args[1]
@ -1392,7 +1394,7 @@ func rewriteValue386_Op386ADDL_20(v *Value) bool {
idx := l.Args[1]
mem := l.Args[2]
x := v.Args[1]
if !(canMergeLoad(v, l, x) && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
break
}
v.reset(Op386ADDLloadidx4)
@ -2163,7 +2165,7 @@ func rewriteValue386_Op386ADDSD_0(v *Value) bool {
config := b.Func.Config
_ = config
// match: (ADDSD x l:(MOVSDload [off] {sym} ptr mem))
// cond: canMergeLoad(v, l, x) && !config.use387 && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && !config.use387 && clobber(l)
// result: (ADDSDload x [off] {sym} ptr mem)
for {
_ = v.Args[1]
@ -2177,7 +2179,7 @@ func rewriteValue386_Op386ADDSD_0(v *Value) bool {
_ = l.Args[1]
ptr := l.Args[0]
mem := l.Args[1]
if !(canMergeLoad(v, l, x) && !config.use387 && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && !config.use387 && clobber(l)) {
break
}
v.reset(Op386ADDSDload)
@ -2189,7 +2191,7 @@ func rewriteValue386_Op386ADDSD_0(v *Value) bool {
return true
}
// match: (ADDSD l:(MOVSDload [off] {sym} ptr mem) x)
// cond: canMergeLoad(v, l, x) && !config.use387 && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && !config.use387 && clobber(l)
// result: (ADDSDload x [off] {sym} ptr mem)
for {
_ = v.Args[1]
@ -2203,7 +2205,7 @@ func rewriteValue386_Op386ADDSD_0(v *Value) bool {
ptr := l.Args[0]
mem := l.Args[1]
x := v.Args[1]
if !(canMergeLoad(v, l, x) && !config.use387 && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && !config.use387 && clobber(l)) {
break
}
v.reset(Op386ADDSDload)
@ -2282,7 +2284,7 @@ func rewriteValue386_Op386ADDSS_0(v *Value) bool {
config := b.Func.Config
_ = config
// match: (ADDSS x l:(MOVSSload [off] {sym} ptr mem))
// cond: canMergeLoad(v, l, x) && !config.use387 && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && !config.use387 && clobber(l)
// result: (ADDSSload x [off] {sym} ptr mem)
for {
_ = v.Args[1]
@ -2296,7 +2298,7 @@ func rewriteValue386_Op386ADDSS_0(v *Value) bool {
_ = l.Args[1]
ptr := l.Args[0]
mem := l.Args[1]
if !(canMergeLoad(v, l, x) && !config.use387 && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && !config.use387 && clobber(l)) {
break
}
v.reset(Op386ADDSSload)
@ -2308,7 +2310,7 @@ func rewriteValue386_Op386ADDSS_0(v *Value) bool {
return true
}
// match: (ADDSS l:(MOVSSload [off] {sym} ptr mem) x)
// cond: canMergeLoad(v, l, x) && !config.use387 && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && !config.use387 && clobber(l)
// result: (ADDSSload x [off] {sym} ptr mem)
for {
_ = v.Args[1]
@ -2322,7 +2324,7 @@ func rewriteValue386_Op386ADDSS_0(v *Value) bool {
ptr := l.Args[0]
mem := l.Args[1]
x := v.Args[1]
if !(canMergeLoad(v, l, x) && !config.use387 && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && !config.use387 && clobber(l)) {
break
}
v.reset(Op386ADDSSload)
@ -2429,7 +2431,7 @@ func rewriteValue386_Op386ANDL_0(v *Value) bool {
return true
}
// match: (ANDL x l:(MOVLload [off] {sym} ptr mem))
// cond: canMergeLoad(v, l, x) && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && clobber(l)
// result: (ANDLload x [off] {sym} ptr mem)
for {
_ = v.Args[1]
@ -2443,7 +2445,7 @@ func rewriteValue386_Op386ANDL_0(v *Value) bool {
_ = l.Args[1]
ptr := l.Args[0]
mem := l.Args[1]
if !(canMergeLoad(v, l, x) && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
break
}
v.reset(Op386ANDLload)
@ -2455,7 +2457,7 @@ func rewriteValue386_Op386ANDL_0(v *Value) bool {
return true
}
// match: (ANDL l:(MOVLload [off] {sym} ptr mem) x)
// cond: canMergeLoad(v, l, x) && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && clobber(l)
// result: (ANDLload x [off] {sym} ptr mem)
for {
_ = v.Args[1]
@ -2469,7 +2471,7 @@ func rewriteValue386_Op386ANDL_0(v *Value) bool {
ptr := l.Args[0]
mem := l.Args[1]
x := v.Args[1]
if !(canMergeLoad(v, l, x) && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
break
}
v.reset(Op386ANDLload)
@ -2481,7 +2483,7 @@ func rewriteValue386_Op386ANDL_0(v *Value) bool {
return true
}
// match: (ANDL x l:(MOVLloadidx4 [off] {sym} ptr idx mem))
// cond: canMergeLoad(v, l, x) && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && clobber(l)
// result: (ANDLloadidx4 x [off] {sym} ptr idx mem)
for {
_ = v.Args[1]
@ -2496,7 +2498,7 @@ func rewriteValue386_Op386ANDL_0(v *Value) bool {
ptr := l.Args[0]
idx := l.Args[1]
mem := l.Args[2]
if !(canMergeLoad(v, l, x) && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
break
}
v.reset(Op386ANDLloadidx4)
@ -2509,7 +2511,7 @@ func rewriteValue386_Op386ANDL_0(v *Value) bool {
return true
}
// match: (ANDL l:(MOVLloadidx4 [off] {sym} ptr idx mem) x)
// cond: canMergeLoad(v, l, x) && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && clobber(l)
// result: (ANDLloadidx4 x [off] {sym} ptr idx mem)
for {
_ = v.Args[1]
@ -2524,7 +2526,7 @@ func rewriteValue386_Op386ANDL_0(v *Value) bool {
idx := l.Args[1]
mem := l.Args[2]
x := v.Args[1]
if !(canMergeLoad(v, l, x) && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
break
}
v.reset(Op386ANDLloadidx4)
@ -3151,7 +3153,7 @@ func rewriteValue386_Op386CMPB_0(v *Value) bool {
return true
}
// match: (CMPB l:(MOVBload {sym} [off] ptr mem) x)
// cond: canMergeLoad(v, l, x) && clobber(l)
// cond: canMergeLoad(v, l) && clobber(l)
// result: (CMPBload {sym} [off] ptr x mem)
for {
_ = v.Args[1]
@ -3165,7 +3167,7 @@ func rewriteValue386_Op386CMPB_0(v *Value) bool {
ptr := l.Args[0]
mem := l.Args[1]
x := v.Args[1]
if !(canMergeLoad(v, l, x) && clobber(l)) {
if !(canMergeLoad(v, l) && clobber(l)) {
break
}
v.reset(Op386CMPBload)
@ -3177,7 +3179,7 @@ func rewriteValue386_Op386CMPB_0(v *Value) bool {
return true
}
// match: (CMPB x l:(MOVBload {sym} [off] ptr mem))
// cond: canMergeLoad(v, l, x) && clobber(l)
// cond: canMergeLoad(v, l) && clobber(l)
// result: (InvertFlags (CMPBload {sym} [off] ptr x mem))
for {
_ = v.Args[1]
@ -3191,7 +3193,7 @@ func rewriteValue386_Op386CMPB_0(v *Value) bool {
_ = l.Args[1]
ptr := l.Args[0]
mem := l.Args[1]
if !(canMergeLoad(v, l, x) && clobber(l)) {
if !(canMergeLoad(v, l) && clobber(l)) {
break
}
v.reset(Op386InvertFlags)
@ -3455,7 +3457,7 @@ func rewriteValue386_Op386CMPL_0(v *Value) bool {
return true
}
// match: (CMPL l:(MOVLload {sym} [off] ptr mem) x)
// cond: canMergeLoad(v, l, x) && clobber(l)
// cond: canMergeLoad(v, l) && clobber(l)
// result: (CMPLload {sym} [off] ptr x mem)
for {
_ = v.Args[1]
@ -3469,7 +3471,7 @@ func rewriteValue386_Op386CMPL_0(v *Value) bool {
ptr := l.Args[0]
mem := l.Args[1]
x := v.Args[1]
if !(canMergeLoad(v, l, x) && clobber(l)) {
if !(canMergeLoad(v, l) && clobber(l)) {
break
}
v.reset(Op386CMPLload)
@ -3481,7 +3483,7 @@ func rewriteValue386_Op386CMPL_0(v *Value) bool {
return true
}
// match: (CMPL x l:(MOVLload {sym} [off] ptr mem))
// cond: canMergeLoad(v, l, x) && clobber(l)
// cond: canMergeLoad(v, l) && clobber(l)
// result: (InvertFlags (CMPLload {sym} [off] ptr x mem))
for {
_ = v.Args[1]
@ -3495,7 +3497,7 @@ func rewriteValue386_Op386CMPL_0(v *Value) bool {
_ = l.Args[1]
ptr := l.Args[0]
mem := l.Args[1]
if !(canMergeLoad(v, l, x) && clobber(l)) {
if !(canMergeLoad(v, l) && clobber(l)) {
break
}
v.reset(Op386InvertFlags)
@ -3778,7 +3780,7 @@ func rewriteValue386_Op386CMPW_0(v *Value) bool {
return true
}
// match: (CMPW l:(MOVWload {sym} [off] ptr mem) x)
// cond: canMergeLoad(v, l, x) && clobber(l)
// cond: canMergeLoad(v, l) && clobber(l)
// result: (CMPWload {sym} [off] ptr x mem)
for {
_ = v.Args[1]
@ -3792,7 +3794,7 @@ func rewriteValue386_Op386CMPW_0(v *Value) bool {
ptr := l.Args[0]
mem := l.Args[1]
x := v.Args[1]
if !(canMergeLoad(v, l, x) && clobber(l)) {
if !(canMergeLoad(v, l) && clobber(l)) {
break
}
v.reset(Op386CMPWload)
@ -3804,7 +3806,7 @@ func rewriteValue386_Op386CMPW_0(v *Value) bool {
return true
}
// match: (CMPW x l:(MOVWload {sym} [off] ptr mem))
// cond: canMergeLoad(v, l, x) && clobber(l)
// cond: canMergeLoad(v, l) && clobber(l)
// result: (InvertFlags (CMPWload {sym} [off] ptr x mem))
for {
_ = v.Args[1]
@ -3818,7 +3820,7 @@ func rewriteValue386_Op386CMPW_0(v *Value) bool {
_ = l.Args[1]
ptr := l.Args[0]
mem := l.Args[1]
if !(canMergeLoad(v, l, x) && clobber(l)) {
if !(canMergeLoad(v, l) && clobber(l)) {
break
}
v.reset(Op386InvertFlags)
@ -4050,7 +4052,7 @@ func rewriteValue386_Op386DIVSD_0(v *Value) bool {
config := b.Func.Config
_ = config
// match: (DIVSD x l:(MOVSDload [off] {sym} ptr mem))
// cond: canMergeLoad(v, l, x) && !config.use387 && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && !config.use387 && clobber(l)
// result: (DIVSDload x [off] {sym} ptr mem)
for {
_ = v.Args[1]
@ -4064,7 +4066,7 @@ func rewriteValue386_Op386DIVSD_0(v *Value) bool {
_ = l.Args[1]
ptr := l.Args[0]
mem := l.Args[1]
if !(canMergeLoad(v, l, x) && !config.use387 && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && !config.use387 && clobber(l)) {
break
}
v.reset(Op386DIVSDload)
@ -4143,7 +4145,7 @@ func rewriteValue386_Op386DIVSS_0(v *Value) bool {
config := b.Func.Config
_ = config
// match: (DIVSS x l:(MOVSSload [off] {sym} ptr mem))
// cond: canMergeLoad(v, l, x) && !config.use387 && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && !config.use387 && clobber(l)
// result: (DIVSSload x [off] {sym} ptr mem)
for {
_ = v.Args[1]
@ -4157,7 +4159,7 @@ func rewriteValue386_Op386DIVSS_0(v *Value) bool {
_ = l.Args[1]
ptr := l.Args[0]
mem := l.Args[1]
if !(canMergeLoad(v, l, x) && !config.use387 && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && !config.use387 && clobber(l)) {
break
}
v.reset(Op386DIVSSload)
@ -12773,7 +12775,7 @@ func rewriteValue386_Op386MULL_0(v *Value) bool {
return true
}
// match: (MULL x l:(MOVLload [off] {sym} ptr mem))
// cond: canMergeLoad(v, l, x) && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && clobber(l)
// result: (MULLload x [off] {sym} ptr mem)
for {
_ = v.Args[1]
@ -12787,7 +12789,7 @@ func rewriteValue386_Op386MULL_0(v *Value) bool {
_ = l.Args[1]
ptr := l.Args[0]
mem := l.Args[1]
if !(canMergeLoad(v, l, x) && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
break
}
v.reset(Op386MULLload)
@ -12799,7 +12801,7 @@ func rewriteValue386_Op386MULL_0(v *Value) bool {
return true
}
// match: (MULL l:(MOVLload [off] {sym} ptr mem) x)
// cond: canMergeLoad(v, l, x) && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && clobber(l)
// result: (MULLload x [off] {sym} ptr mem)
for {
_ = v.Args[1]
@ -12813,7 +12815,7 @@ func rewriteValue386_Op386MULL_0(v *Value) bool {
ptr := l.Args[0]
mem := l.Args[1]
x := v.Args[1]
if !(canMergeLoad(v, l, x) && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
break
}
v.reset(Op386MULLload)
@ -12825,7 +12827,7 @@ func rewriteValue386_Op386MULL_0(v *Value) bool {
return true
}
// match: (MULL x l:(MOVLloadidx4 [off] {sym} ptr idx mem))
// cond: canMergeLoad(v, l, x) && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && clobber(l)
// result: (MULLloadidx4 x [off] {sym} ptr idx mem)
for {
_ = v.Args[1]
@ -12840,7 +12842,7 @@ func rewriteValue386_Op386MULL_0(v *Value) bool {
ptr := l.Args[0]
idx := l.Args[1]
mem := l.Args[2]
if !(canMergeLoad(v, l, x) && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
break
}
v.reset(Op386MULLloadidx4)
@ -12853,7 +12855,7 @@ func rewriteValue386_Op386MULL_0(v *Value) bool {
return true
}
// match: (MULL l:(MOVLloadidx4 [off] {sym} ptr idx mem) x)
// cond: canMergeLoad(v, l, x) && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && clobber(l)
// result: (MULLloadidx4 x [off] {sym} ptr idx mem)
for {
_ = v.Args[1]
@ -12868,7 +12870,7 @@ func rewriteValue386_Op386MULL_0(v *Value) bool {
idx := l.Args[1]
mem := l.Args[2]
x := v.Args[1]
if !(canMergeLoad(v, l, x) && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
break
}
v.reset(Op386MULLloadidx4)
@ -13575,7 +13577,7 @@ func rewriteValue386_Op386MULSD_0(v *Value) bool {
config := b.Func.Config
_ = config
// match: (MULSD x l:(MOVSDload [off] {sym} ptr mem))
// cond: canMergeLoad(v, l, x) && !config.use387 && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && !config.use387 && clobber(l)
// result: (MULSDload x [off] {sym} ptr mem)
for {
_ = v.Args[1]
@ -13589,7 +13591,7 @@ func rewriteValue386_Op386MULSD_0(v *Value) bool {
_ = l.Args[1]
ptr := l.Args[0]
mem := l.Args[1]
if !(canMergeLoad(v, l, x) && !config.use387 && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && !config.use387 && clobber(l)) {
break
}
v.reset(Op386MULSDload)
@ -13601,7 +13603,7 @@ func rewriteValue386_Op386MULSD_0(v *Value) bool {
return true
}
// match: (MULSD l:(MOVSDload [off] {sym} ptr mem) x)
// cond: canMergeLoad(v, l, x) && !config.use387 && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && !config.use387 && clobber(l)
// result: (MULSDload x [off] {sym} ptr mem)
for {
_ = v.Args[1]
@ -13615,7 +13617,7 @@ func rewriteValue386_Op386MULSD_0(v *Value) bool {
ptr := l.Args[0]
mem := l.Args[1]
x := v.Args[1]
if !(canMergeLoad(v, l, x) && !config.use387 && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && !config.use387 && clobber(l)) {
break
}
v.reset(Op386MULSDload)
@ -13694,7 +13696,7 @@ func rewriteValue386_Op386MULSS_0(v *Value) bool {
config := b.Func.Config
_ = config
// match: (MULSS x l:(MOVSSload [off] {sym} ptr mem))
// cond: canMergeLoad(v, l, x) && !config.use387 && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && !config.use387 && clobber(l)
// result: (MULSSload x [off] {sym} ptr mem)
for {
_ = v.Args[1]
@ -13708,7 +13710,7 @@ func rewriteValue386_Op386MULSS_0(v *Value) bool {
_ = l.Args[1]
ptr := l.Args[0]
mem := l.Args[1]
if !(canMergeLoad(v, l, x) && !config.use387 && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && !config.use387 && clobber(l)) {
break
}
v.reset(Op386MULSSload)
@ -13720,7 +13722,7 @@ func rewriteValue386_Op386MULSS_0(v *Value) bool {
return true
}
// match: (MULSS l:(MOVSSload [off] {sym} ptr mem) x)
// cond: canMergeLoad(v, l, x) && !config.use387 && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && !config.use387 && clobber(l)
// result: (MULSSload x [off] {sym} ptr mem)
for {
_ = v.Args[1]
@ -13734,7 +13736,7 @@ func rewriteValue386_Op386MULSS_0(v *Value) bool {
ptr := l.Args[0]
mem := l.Args[1]
x := v.Args[1]
if !(canMergeLoad(v, l, x) && !config.use387 && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && !config.use387 && clobber(l)) {
break
}
v.reset(Op386MULSSload)
@ -14039,7 +14041,7 @@ func rewriteValue386_Op386ORL_0(v *Value) bool {
return true
}
// match: (ORL x l:(MOVLload [off] {sym} ptr mem))
// cond: canMergeLoad(v, l, x) && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && clobber(l)
// result: (ORLload x [off] {sym} ptr mem)
for {
_ = v.Args[1]
@ -14053,7 +14055,7 @@ func rewriteValue386_Op386ORL_0(v *Value) bool {
_ = l.Args[1]
ptr := l.Args[0]
mem := l.Args[1]
if !(canMergeLoad(v, l, x) && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
break
}
v.reset(Op386ORLload)
@ -14065,7 +14067,7 @@ func rewriteValue386_Op386ORL_0(v *Value) bool {
return true
}
// match: (ORL l:(MOVLload [off] {sym} ptr mem) x)
// cond: canMergeLoad(v, l, x) && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && clobber(l)
// result: (ORLload x [off] {sym} ptr mem)
for {
_ = v.Args[1]
@ -14079,7 +14081,7 @@ func rewriteValue386_Op386ORL_0(v *Value) bool {
ptr := l.Args[0]
mem := l.Args[1]
x := v.Args[1]
if !(canMergeLoad(v, l, x) && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
break
}
v.reset(Op386ORLload)
@ -14098,7 +14100,7 @@ func rewriteValue386_Op386ORL_10(v *Value) bool {
typ := &b.Func.Config.Types
_ = typ
// match: (ORL x l:(MOVLloadidx4 [off] {sym} ptr idx mem))
// cond: canMergeLoad(v, l, x) && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && clobber(l)
// result: (ORLloadidx4 x [off] {sym} ptr idx mem)
for {
_ = v.Args[1]
@ -14113,7 +14115,7 @@ func rewriteValue386_Op386ORL_10(v *Value) bool {
ptr := l.Args[0]
idx := l.Args[1]
mem := l.Args[2]
if !(canMergeLoad(v, l, x) && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
break
}
v.reset(Op386ORLloadidx4)
@ -14126,7 +14128,7 @@ func rewriteValue386_Op386ORL_10(v *Value) bool {
return true
}
// match: (ORL l:(MOVLloadidx4 [off] {sym} ptr idx mem) x)
// cond: canMergeLoad(v, l, x) && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && clobber(l)
// result: (ORLloadidx4 x [off] {sym} ptr idx mem)
for {
_ = v.Args[1]
@ -14141,7 +14143,7 @@ func rewriteValue386_Op386ORL_10(v *Value) bool {
idx := l.Args[1]
mem := l.Args[2]
x := v.Args[1]
if !(canMergeLoad(v, l, x) && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
break
}
v.reset(Op386ORLloadidx4)
@ -19618,7 +19620,7 @@ func rewriteValue386_Op386SUBL_0(v *Value) bool {
return true
}
// match: (SUBL x l:(MOVLload [off] {sym} ptr mem))
// cond: canMergeLoad(v, l, x) && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && clobber(l)
// result: (SUBLload x [off] {sym} ptr mem)
for {
_ = v.Args[1]
@ -19632,7 +19634,7 @@ func rewriteValue386_Op386SUBL_0(v *Value) bool {
_ = l.Args[1]
ptr := l.Args[0]
mem := l.Args[1]
if !(canMergeLoad(v, l, x) && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
break
}
v.reset(Op386SUBLload)
@ -19644,7 +19646,7 @@ func rewriteValue386_Op386SUBL_0(v *Value) bool {
return true
}
// match: (SUBL x l:(MOVLloadidx4 [off] {sym} ptr idx mem))
// cond: canMergeLoad(v, l, x) && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && clobber(l)
// result: (SUBLloadidx4 x [off] {sym} ptr idx mem)
for {
_ = v.Args[1]
@ -19659,7 +19661,7 @@ func rewriteValue386_Op386SUBL_0(v *Value) bool {
ptr := l.Args[0]
idx := l.Args[1]
mem := l.Args[2]
if !(canMergeLoad(v, l, x) && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
break
}
v.reset(Op386SUBLloadidx4)
@ -20098,7 +20100,7 @@ func rewriteValue386_Op386SUBSD_0(v *Value) bool {
config := b.Func.Config
_ = config
// match: (SUBSD x l:(MOVSDload [off] {sym} ptr mem))
// cond: canMergeLoad(v, l, x) && !config.use387 && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && !config.use387 && clobber(l)
// result: (SUBSDload x [off] {sym} ptr mem)
for {
_ = v.Args[1]
@ -20112,7 +20114,7 @@ func rewriteValue386_Op386SUBSD_0(v *Value) bool {
_ = l.Args[1]
ptr := l.Args[0]
mem := l.Args[1]
if !(canMergeLoad(v, l, x) && !config.use387 && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && !config.use387 && clobber(l)) {
break
}
v.reset(Op386SUBSDload)
@ -20191,7 +20193,7 @@ func rewriteValue386_Op386SUBSS_0(v *Value) bool {
config := b.Func.Config
_ = config
// match: (SUBSS x l:(MOVSSload [off] {sym} ptr mem))
// cond: canMergeLoad(v, l, x) && !config.use387 && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && !config.use387 && clobber(l)
// result: (SUBSSload x [off] {sym} ptr mem)
for {
_ = v.Args[1]
@ -20205,7 +20207,7 @@ func rewriteValue386_Op386SUBSS_0(v *Value) bool {
_ = l.Args[1]
ptr := l.Args[0]
mem := l.Args[1]
if !(canMergeLoad(v, l, x) && !config.use387 && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && !config.use387 && clobber(l)) {
break
}
v.reset(Op386SUBSSload)
@ -20478,7 +20480,7 @@ func rewriteValue386_Op386XORL_0(v *Value) bool {
return true
}
// match: (XORL x l:(MOVLload [off] {sym} ptr mem))
// cond: canMergeLoad(v, l, x) && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && clobber(l)
// result: (XORLload x [off] {sym} ptr mem)
for {
_ = v.Args[1]
@ -20492,7 +20494,7 @@ func rewriteValue386_Op386XORL_0(v *Value) bool {
_ = l.Args[1]
ptr := l.Args[0]
mem := l.Args[1]
if !(canMergeLoad(v, l, x) && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
break
}
v.reset(Op386XORLload)
@ -20504,7 +20506,7 @@ func rewriteValue386_Op386XORL_0(v *Value) bool {
return true
}
// match: (XORL l:(MOVLload [off] {sym} ptr mem) x)
// cond: canMergeLoad(v, l, x) && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && clobber(l)
// result: (XORLload x [off] {sym} ptr mem)
for {
_ = v.Args[1]
@ -20518,7 +20520,7 @@ func rewriteValue386_Op386XORL_0(v *Value) bool {
ptr := l.Args[0]
mem := l.Args[1]
x := v.Args[1]
if !(canMergeLoad(v, l, x) && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
break
}
v.reset(Op386XORLload)
@ -20533,7 +20535,7 @@ func rewriteValue386_Op386XORL_0(v *Value) bool {
}
func rewriteValue386_Op386XORL_10(v *Value) bool {
// match: (XORL x l:(MOVLloadidx4 [off] {sym} ptr idx mem))
// cond: canMergeLoad(v, l, x) && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && clobber(l)
// result: (XORLloadidx4 x [off] {sym} ptr idx mem)
for {
_ = v.Args[1]
@ -20548,7 +20550,7 @@ func rewriteValue386_Op386XORL_10(v *Value) bool {
ptr := l.Args[0]
idx := l.Args[1]
mem := l.Args[2]
if !(canMergeLoad(v, l, x) && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
break
}
v.reset(Op386XORLloadidx4)
@ -20561,7 +20563,7 @@ func rewriteValue386_Op386XORL_10(v *Value) bool {
return true
}
// match: (XORL l:(MOVLloadidx4 [off] {sym} ptr idx mem) x)
// cond: canMergeLoad(v, l, x) && clobber(l)
// cond: canMergeLoadClobber(v, l, x) && clobber(l)
// result: (XORLloadidx4 x [off] {sym} ptr idx mem)
for {
_ = v.Args[1]
@ -20576,7 +20578,7 @@ func rewriteValue386_Op386XORL_10(v *Value) bool {
idx := l.Args[1]
mem := l.Args[2]
x := v.Args[1]
if !(canMergeLoad(v, l, x) && clobber(l)) {
if !(canMergeLoadClobber(v, l, x) && clobber(l)) {
break
}
v.reset(Op386XORLloadidx4)

File diff suppressed because it is too large Load diff

View file

@ -3,11 +3,13 @@
package ssa
import "fmt"
import "math"
import "cmd/internal/obj"
import "cmd/internal/objabi"
import "cmd/compile/internal/types"
var _ = fmt.Println // in case not otherwise used
var _ = math.MinInt8 // in case not otherwise used
var _ = obj.ANOP // in case not otherwise used
var _ = objabi.GOROOT // in case not otherwise used

View file

@ -3,11 +3,13 @@
package ssa
import "fmt"
import "math"
import "cmd/internal/obj"
import "cmd/internal/objabi"
import "cmd/compile/internal/types"
var _ = fmt.Println // in case not otherwise used
var _ = math.MinInt8 // in case not otherwise used
var _ = obj.ANOP // in case not otherwise used
var _ = objabi.GOROOT // in case not otherwise used

View file

@ -3,11 +3,13 @@
package ssa
import "fmt"
import "math"
import "cmd/internal/obj"
import "cmd/internal/objabi"
import "cmd/compile/internal/types"
var _ = fmt.Println // in case not otherwise used
var _ = math.MinInt8 // in case not otherwise used
var _ = obj.ANOP // in case not otherwise used
var _ = objabi.GOROOT // in case not otherwise used

View file

@ -3,11 +3,13 @@
package ssa
import "fmt"
import "math"
import "cmd/internal/obj"
import "cmd/internal/objabi"
import "cmd/compile/internal/types"
var _ = fmt.Println // in case not otherwise used
var _ = math.MinInt8 // in case not otherwise used
var _ = obj.ANOP // in case not otherwise used
var _ = objabi.GOROOT // in case not otherwise used

View file

@ -3,11 +3,13 @@
package ssa
import "fmt"
import "math"
import "cmd/internal/obj"
import "cmd/internal/objabi"
import "cmd/compile/internal/types"
var _ = fmt.Println // in case not otherwise used
var _ = math.MinInt8 // in case not otherwise used
var _ = obj.ANOP // in case not otherwise used
var _ = objabi.GOROOT // in case not otherwise used

File diff suppressed because it is too large Load diff

View file

@ -3,11 +3,13 @@
package ssa
import "fmt"
import "math"
import "cmd/internal/obj"
import "cmd/internal/objabi"
import "cmd/compile/internal/types"
var _ = fmt.Println // in case not otherwise used
var _ = math.MinInt8 // in case not otherwise used
var _ = obj.ANOP // in case not otherwise used
var _ = objabi.GOROOT // in case not otherwise used

View file

@ -3,11 +3,13 @@
package ssa
import "fmt"
import "math"
import "cmd/internal/obj"
import "cmd/internal/objabi"
import "cmd/compile/internal/types"
var _ = fmt.Println // in case not otherwise used
var _ = math.MinInt8 // in case not otherwise used
var _ = obj.ANOP // in case not otherwise used
var _ = objabi.GOROOT // in case not otherwise used

View file

@ -3,11 +3,13 @@
package ssa
import "fmt"
import "math"
import "cmd/internal/obj"
import "cmd/internal/objabi"
import "cmd/compile/internal/types"
var _ = fmt.Println // in case not otherwise used
var _ = math.MinInt8 // in case not otherwise used
var _ = obj.ANOP // in case not otherwise used
var _ = objabi.GOROOT // in case not otherwise used

View file

@ -3,11 +3,13 @@
package ssa
import "fmt"
import "math"
import "cmd/internal/obj"
import "cmd/internal/objabi"
import "cmd/compile/internal/types"
var _ = fmt.Println // in case not otherwise used
var _ = math.MinInt8 // in case not otherwise used
var _ = obj.ANOP // in case not otherwise used
var _ = objabi.GOROOT // in case not otherwise used

View file

@ -13,6 +13,7 @@ const (
ScoreReadTuple
ScoreVarDef
ScoreMemory
ScoreReadFlags
ScoreDefault
ScoreFlags
ScoreControl // towards bottom of block
@ -129,13 +130,19 @@ func schedule(f *Func) {
// false dependency on the other part of the tuple.
// Also ensures tuple is never spilled.
score[v.ID] = ScoreReadTuple
case v.Type.IsFlags() || v.Type.IsTuple():
case v.Type.IsFlags() || v.Type.IsTuple() && v.Type.FieldType(1).IsFlags():
// Schedule flag register generation as late as possible.
// This makes sure that we only have one live flags
// value at a time.
score[v.ID] = ScoreFlags
default:
score[v.ID] = ScoreDefault
// If we're reading flags, schedule earlier to keep flag lifetime short.
for _, a := range v.Args {
if a.Type.IsFlags() {
score[v.ID] = ScoreReadFlags
}
}
}
}
}

View file

@ -1,6 +1,7 @@
package ssa_test
import (
"cmd/internal/xcoff"
"debug/dwarf"
"debug/elf"
"debug/macho"
@ -25,6 +26,10 @@ func open(path string) (*dwarf.Data, error) {
return fh.DWARF()
}
if fh, err := xcoff.Open(path); err == nil {
return fh.DWARF()
}
return nil, fmt.Errorf("unrecognized executable format")
}

View file

@ -2499,7 +2499,7 @@
// In general, adding a new dependency may require upgrading
// existing dependencies to keep a working build, and 'go get' does
// this automatically. Similarly, downgrading one dependency may
// require downgrading other dependenceis, and 'go get' does
// require downgrading other dependencies, and 'go get' does
// this automatically as well.
//
// The -m flag instructs get to stop here, after resolving, upgrading,

View file

@ -9,7 +9,6 @@ import (
"io/ioutil"
"os"
"path/filepath"
"runtime"
"sync"
)
@ -78,52 +77,19 @@ func defaultDir() (string, bool) {
}
// Compute default location.
// TODO(rsc): This code belongs somewhere else,
// like maybe ioutil.CacheDir or os.CacheDir.
showWarnings := true
switch runtime.GOOS {
case "windows":
dir = os.Getenv("LocalAppData")
if dir == "" {
// Fall back to %AppData%, the old name of
// %LocalAppData% on Windows XP.
dir = os.Getenv("AppData")
}
if dir == "" {
return "off", true
}
case "darwin":
dir = os.Getenv("HOME")
if dir == "" {
return "off", true
}
dir += "/Library/Caches"
case "plan9":
dir = os.Getenv("home")
if dir == "" {
return "off", true
}
// Plan 9 has no established per-user cache directory,
// but $home/lib/xyz is the usual equivalent of $HOME/.xyz on Unix.
dir += "/lib/cache"
default: // Unix
// https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
dir = os.Getenv("XDG_CACHE_HOME")
if dir == "" {
dir = os.Getenv("HOME")
if dir == "" {
return "off", true
}
if dir == "/" {
// probably docker run with -u flag
// https://golang.org/issue/26280
showWarnings = false
}
dir += "/.cache"
}
dir, err := os.UserCacheDir()
if err != nil {
return "off", true
}
return filepath.Join(dir, "go-build"), showWarnings
dir = filepath.Join(dir, "go-build")
// Do this after filepath.Join, so that the path has been cleaned.
showWarnings := true
switch dir {
case "/.cache/go-build":
// probably docker run with -u flag
// https://golang.org/issue/26280
showWarnings = false
}
return dir, showWarnings
}

View file

@ -45,7 +45,7 @@ func runVendor(cmd *base.Command, args []string) {
vdir := filepath.Join(modload.ModRoot, "vendor")
if err := os.RemoveAll(vdir); err != nil {
base.Fatalf("go vendor: %v", err)
base.Fatalf("go mod vendor: %v", err)
}
modpkgs := make(map[module.Version][]string)
@ -85,7 +85,7 @@ func runVendor(cmd *base.Command, args []string) {
return
}
if err := ioutil.WriteFile(filepath.Join(vdir, "modules.txt"), buf.Bytes(), 0666); err != nil {
base.Fatalf("go vendor: %v", err)
base.Fatalf("go mod vendor: %v", err)
}
}
@ -172,10 +172,10 @@ func matchNonTest(info os.FileInfo) bool {
func copyDir(dst, src string, match func(os.FileInfo) bool) {
files, err := ioutil.ReadDir(src)
if err != nil {
base.Fatalf("go vendor: %v", err)
base.Fatalf("go mod vendor: %v", err)
}
if err := os.MkdirAll(dst, 0777); err != nil {
base.Fatalf("go vendor: %v", err)
base.Fatalf("go mod vendor: %v", err)
}
for _, file := range files {
if file.IsDir() || !file.Mode().IsRegular() || !match(file) {
@ -183,18 +183,18 @@ func copyDir(dst, src string, match func(os.FileInfo) bool) {
}
r, err := os.Open(filepath.Join(src, file.Name()))
if err != nil {
base.Fatalf("go vendor: %v", err)
base.Fatalf("go mod vendor: %v", err)
}
w, err := os.Create(filepath.Join(dst, file.Name()))
if err != nil {
base.Fatalf("go vendor: %v", err)
base.Fatalf("go mod vendor: %v", err)
}
if _, err := io.Copy(w, r); err != nil {
base.Fatalf("go vendor: %v", err)
base.Fatalf("go mod vendor: %v", err)
}
r.Close()
if err := w.Close(); err != nil {
base.Fatalf("go vendor: %v", err)
base.Fatalf("go mod vendor: %v", err)
}
}
}

View file

@ -78,7 +78,7 @@ to use newer patch releases when available. Continuing the previous example,
In general, adding a new dependency may require upgrading
existing dependencies to keep a working build, and 'go get' does
this automatically. Similarly, downgrading one dependency may
require downgrading other dependenceis, and 'go get' does
require downgrading other dependencies, and 'go get' does
this automatically as well.
The -m flag instructs get to stop here, after resolving, upgrading,

View file

@ -145,34 +145,38 @@ func moduleInfo(m module.Version, fromBuildList bool) *modinfo.ModulePublic {
}
}
}
if cfg.BuildMod == "vendor" {
m.Dir = filepath.Join(ModRoot, "vendor", m.Path)
}
}
complete(info)
if fromBuildList {
if r := Replacement(m); r.Path != "" {
info.Replace = &modinfo.ModulePublic{
Path: r.Path,
Version: r.Version,
GoVersion: info.GoVersion,
}
if r.Version == "" {
if filepath.IsAbs(r.Path) {
info.Replace.Dir = r.Path
} else {
info.Replace.Dir = filepath.Join(ModRoot, r.Path)
}
}
complete(info.Replace)
info.Dir = info.Replace.Dir
info.GoMod = filepath.Join(info.Dir, "go.mod")
info.Error = nil // ignore error loading original module version (it has been replaced)
}
if !fromBuildList {
complete(info)
return info
}
r := Replacement(m)
if r.Path == "" {
complete(info)
return info
}
// Don't hit the network to fill in extra data for replaced modules.
// The original resolved Version and Time don't matter enough to be
// worth the cost, and we're going to overwrite the GoMod and Dir from the
// replacement anyway. See https://golang.org/issue/27859.
info.Replace = &modinfo.ModulePublic{
Path: r.Path,
Version: r.Version,
GoVersion: info.GoVersion,
}
if r.Version == "" {
if filepath.IsAbs(r.Path) {
info.Replace.Dir = r.Path
} else {
info.Replace.Dir = filepath.Join(ModRoot, r.Path)
}
}
complete(info.Replace)
info.Dir = info.Replace.Dir
info.GoMod = filepath.Join(info.Dir, "go.mod")
return info
}
@ -224,6 +228,10 @@ func findModule(target, path string) module.Version {
if path == "." {
return buildList[0]
}
if cfg.BuildMod == "vendor" {
readVendorList()
return vendorMap[path]
}
for _, mod := range buildList {
if maybeInModule(path, mod.Path) {
return mod

View file

@ -68,6 +68,7 @@ func (e *MissingModuleError) Error() string {
}
// BuildList returns the build list for the target module.
// The first element is the target itself, with the remainder of the list sorted by path.
func BuildList(target module.Version, reqs Reqs) ([]module.Version, error) {
return buildList(target, reqs, nil)
}

View file

@ -2080,14 +2080,37 @@ func (b *Builder) ccompile(a *Action, p *load.Package, outfile string, flags []s
}
// gccld runs the gcc linker to create an executable from a set of object files.
func (b *Builder) gccld(p *load.Package, objdir, out string, flags []string, objs []string) error {
func (b *Builder) gccld(p *load.Package, objdir, outfile string, flags []string, objs []string) error {
var cmd []string
if len(p.CXXFiles) > 0 || len(p.SwigCXXFiles) > 0 {
cmd = b.GxxCmd(p.Dir, objdir)
} else {
cmd = b.GccCmd(p.Dir, objdir)
}
return b.run(nil, p.Dir, p.ImportPath, b.cCompilerEnv(), cmd, "-o", out, objs, flags)
cmdargs := []interface{}{cmd, "-o", outfile, objs, flags}
dir := p.Dir
out, err := b.runOut(dir, b.cCompilerEnv(), cmdargs...)
if len(out) > 0 {
// Filter out useless linker warnings caused by bugs outside Go.
// See also cmd/link/internal/ld's hostlink method.
var save [][]byte
for _, line := range bytes.SplitAfter(out, []byte("\n")) {
// golang.org/issue/26073 - Apple Xcode bug
if bytes.Contains(line, []byte("ld: warning: text-based stub file")) {
continue
}
save = append(save, line)
}
out = bytes.Join(save, nil)
if len(out) > 0 {
b.showOutput(nil, dir, p.ImportPath, b.processOutput(out))
if err != nil {
err = errPrintedOutput
}
}
}
return err
}
// Grab these before main helpfully overwrites them.

View file

@ -1,10 +1,14 @@
env GO111MODULE=on
cp go.mod go.mod.orig
# Make sure the test builds without replacement.
go build -o a1.exe .
exec ./a1.exe
stdout 'Don''t communicate by sharing memory'
# Modules can be replaced by local packages.
cp go.mod.orig go.mod
go mod edit -replace=rsc.io/quote/v3=./local/rsc.io/quote/v3
go build -o a2.exe .
exec ./a2.exe
@ -12,16 +16,26 @@ stdout 'Concurrency is not parallelism.'
# The module path of the replacement doesn't need to match.
# (For example, it could be a long-running fork with its own import path.)
cp go.mod.orig go.mod
go mod edit -replace=rsc.io/quote/v3=./local/not-rsc.io/quote/v3
go build -o a3.exe .
exec ./a3.exe
stdout 'Clear is better than clever.'
# However, the same module can't be used as two different paths.
go mod edit -dropreplace=rsc.io/quote/v3 -replace=not-rsc.io/quote/v3@v3.0.0=rsc.io/quote/v3@v3.0.0 -require=not-rsc.io/quote/v3@v3.0.0
cp go.mod.orig go.mod
go mod edit -replace=not-rsc.io/quote/v3@v3.0.0=rsc.io/quote/v3@v3.0.0 -require=not-rsc.io/quote/v3@v3.0.0
! go build -o a4.exe .
stderr 'rsc.io/quote/v3@v3.0.0 used for two different module paths \(not-rsc.io/quote/v3 and rsc.io/quote/v3\)'
# Modules that do not (yet) exist upstream can be replaced too.
cp go.mod.orig go.mod
go mod edit -require not-rsc.io/quote/v3@v3.0.0 -replace=not-rsc.io/quote/v3=./local/rsc.io/quote/v3
go build -o a5.exe ./usenewmodule
! stderr 'finding not-rsc.io/quote/v3'
exec ./a5.exe
stdout 'Concurrency is not parallelism.'
-- go.mod --
module quoter
@ -39,6 +53,18 @@ func main() {
fmt.Println(quote.GoV3())
}
-- usenewmodule/main.go --
package main
import (
"fmt"
"not-rsc.io/quote/v3"
)
func main() {
fmt.Println(quote.GoV3())
}
-- local/rsc.io/quote/v3/go.mod --
module rsc.io/quote/v3

View file

@ -0,0 +1,71 @@
env GO111MODULE=on
# From inside the module, 'go list -m all' should NOT include transitive
# requirements of modules that have been replaced.
go list -m all
stdout 'rsc.io/quote/v3 v3.0.0'
! stdout 'rsc.io/sampler'
! stdout 'golang.org/x/text'
# From outside the module, 'go list -m all' should include them.
cd outside
go list -m all
stdout 'rsc.io/quote/v3 v3.0.0'
stdout 'rsc.io/sampler v1.3.0'
stdout 'golang.org/x/text'
cd ..
# 'go list all' should add indirect requirements to satisfy the packages
# imported from replacement modules.
! grep 'rsc.io/sampler' go.mod
! grep 'golang.org/x/text' go.mod
go list all
grep 'rsc.io/sampler' go.mod
grep 'golang.org/x/text' go.mod
# 'go get' and 'go mod tidy' should follow the requirements of the replacements,
# not the originals, even if that results in a set of versions that are
# misleading or redundant without those replacements.
go get rsc.io/sampler@v1.2.0
go mod tidy
go list -m all
stdout 'rsc.io/quote/v3 v3.0.0'
stdout 'rsc.io/sampler v1.2.0'
stdout 'golang.org/x/text'
# The requirements seen from outside may be higher (or lower)
# than those seen from within the module.
grep 'rsc.io/sampler v1.2.0' go.mod
cd outside
go list -m all
stdout 'rsc.io/sampler v1.3.0'
-- go.mod --
module example.com/tidy
require rsc.io/quote/v3 v3.0.0
replace rsc.io/quote/v3 => ./not-rsc.io/quote/v3
-- imports.go --
package tidy
import _ "rsc.io/quote/v3"
-- outside/go.mod --
module example.com/tidy/outside
require example.com/tidy v0.0.0
replace example.com/tidy => ./..
-- not-rsc.io/quote/v3/go.mod --
module not-rsc.io/quote/v3
// No requirements specified!
-- not-rsc.io/quote/v3/quote.go --
package quote
import (
_ "rsc.io/sampler"
_ "golang.org/x/text/language"
)

View file

@ -67,6 +67,7 @@ module m
require (
a v1.0.0
diamondroot v0.0.0
mysite/myname/mypkg v1.0.0
w v1.0.0 // indirect
x v1.0.0
@ -76,6 +77,10 @@ require (
replace (
a v1.0.0 => ./a
diamondleft => ./diamondleft
diamondpoint => ./diamondpoint
diamondright => ./diamondright
diamondroot => ./diamondroot
mysite/myname/mypkg v1.0.0 => ./mypkg
w v1.0.0 => ./w
x v1.0.0 => ./x
@ -200,6 +205,10 @@ import _ "z"
package m
import _ "x/x1"
-- importdiamond.go --
package m
import _ "diamondroot"
-- w/go.mod --
module w
-- w/w.go --
@ -228,3 +237,42 @@ package y
module z
-- z/z.go --
package z
-- diamondroot/go.mod --
module diamondroot
require (
diamondleft v0.0.0
diamondright v0.0.0
)
-- diamondroot/x.go --
package diamondroot
import (
_ "diamondleft"
_ "diamondright"
)
-- diamondleft/go.mod --
module diamondleft
require (
diamondpoint v0.0.0
)
-- diamondleft/x.go --
package diamondleft
import _ "diamondpoint"
-- diamondright/go.mod --
module diamondright
require (
diamondpoint v0.0.0
)
-- diamondright/x.go --
package diamondright
import _ "diamondpoint"
-- diamondpoint/go.mod --
module diamondpoint
-- diamondpoint/x.go --
package diamondpoint

View file

@ -0,0 +1,39 @@
env GO111MODULE=on
# Before vendoring, we expect to see the original directory.
go list -f '{{.Version}} {{.Dir}}' -m rsc.io/quote/v3
stdout 'v3.0.0'
stdout '.*[/\\]not-rsc.io[/\\]quote[/\\]v3'
# Since all dependencies are replaced, 'go mod vendor' should not
# have to download anything from the network.
go mod vendor
! stderr 'downloading'
! stderr 'finding'
# After vendoring, we expect to see the replacement in the vendor directory,
# without attempting to look up the non-replaced version.
cmp vendor/rsc.io/quote/v3/quote.go local/not-rsc.io/quote/v3/quote.go
go list -mod=vendor -f '{{.Version}} {{.Dir}}' -m rsc.io/quote/v3
stdout 'v3.0.0'
stdout '.*[/\\]vendor[/\\]rsc.io[/\\]quote[/\\]v3'
! stderr 'finding'
! stderr 'lookup disabled'
-- go.mod --
module example.com/replace
require rsc.io/quote/v3 v3.0.0
replace rsc.io/quote/v3 => ./local/not-rsc.io/quote/v3
-- imports.go --
package replace
import _ "rsc.io/quote/v3"
-- local/not-rsc.io/quote/v3/go.mod --
module not-rsc.io/quote/v3
-- local/not-rsc.io/quote/v3/quote.go --
package quote

View file

@ -179,7 +179,7 @@ type Context interface {
AddBytes(s Sym, b []byte)
AddAddress(s Sym, t interface{}, ofs int64)
AddSectionOffset(s Sym, size int, t interface{}, ofs int64)
AddDWARFSectionOffset(s Sym, size int, t interface{}, ofs int64)
AddDWARFAddrSectionOffset(s Sym, t interface{}, ofs int64)
CurrentOffset(s Sym) int64
RecordDclReference(from Sym, to Sym, dclIdx int, inlIndex int)
RecordChildDieOffsets(s Sym, vars []*Var, offsets []int32)
@ -895,7 +895,7 @@ func putattr(ctxt Context, s Sym, abbrev int, form int, cls int, value int64, da
case DW_FORM_data4: // constant, {line,loclist,mac,rangelist}ptr
if cls == DW_CLS_PTR { // DW_AT_stmt_list and DW_AT_ranges
ctxt.AddDWARFSectionOffset(s, 4, data, value)
ctxt.AddDWARFAddrSectionOffset(s, data, value)
break
}
ctxt.AddInt(s, 4, value)
@ -932,7 +932,7 @@ func putattr(ctxt Context, s Sym, abbrev int, form int, cls int, value int64, da
if data == nil {
return fmt.Errorf("dwarf: null reference in %d", abbrev)
}
ctxt.AddDWARFSectionOffset(s, 4, data, value)
ctxt.AddDWARFAddrSectionOffset(s, data, value)
case DW_FORM_ref1, // reference within the compilation unit
DW_FORM_ref2, // reference

View file

@ -459,7 +459,12 @@ func (c dwCtxt) AddAddress(s dwarf.Sym, data interface{}, value int64) {
func (c dwCtxt) AddSectionOffset(s dwarf.Sym, size int, t interface{}, ofs int64) {
panic("should be used only in the linker")
}
func (c dwCtxt) AddDWARFSectionOffset(s dwarf.Sym, size int, t interface{}, ofs int64) {
func (c dwCtxt) AddDWARFAddrSectionOffset(s dwarf.Sym, t interface{}, ofs int64) {
size := 4
if isDwarf64(c.Link) {
size = 8
}
ls := s.(*LSym)
rsym := t.(*LSym)
ls.WriteAddr(c.Link, ls.Size, size, rsym, ofs)
@ -500,6 +505,10 @@ func (c dwCtxt) Logf(format string, args ...interface{}) {
c.Link.Logf(format, args...)
}
func isDwarf64(ctxt *Link) bool {
return ctxt.Headtype == objabi.Haix
}
func (ctxt *Link) dwarfSym(s *LSym) (dwarfInfoSym, dwarfLocSym, dwarfRangesSym, dwarfAbsFnSym, dwarfIsStmtSym *LSym) {
if s.Type != objabi.STEXT {
ctxt.Diag("dwarfSym of non-TEXT %v", s)

View file

@ -945,6 +945,9 @@ const (
AVUPLHW
AVUPLF
AVMSLG
AVMSLEG
AVMSLOG
AVMSLEOG
// binary
ABYTE

View file

@ -678,6 +678,9 @@ var Anames = []string{
"VUPLHW",
"VUPLF",
"VMSLG",
"VMSLEG",
"VMSLOG",
"VMSLEOG",
"BYTE",
"WORD",
"DWORD",

View file

@ -1379,6 +1379,9 @@ func buildop(ctxt *obj.Link) {
opset(AVSBCBIQ, r)
opset(AVSBIQ, r)
opset(AVMSLG, r)
opset(AVMSLEG, r)
opset(AVMSLOG, r)
opset(AVMSLEOG, r)
case AVSEL:
opset(AVFMADB, r)
opset(AWFMADB, r)

View file

@ -45,7 +45,7 @@ func vop(as obj.As) (opcode, es, cs uint32) {
return op_VAC, 0, 0
case AVACQ:
return op_VAC, 4, 0
case AVMSLG:
case AVMSLG, AVMSLEG, AVMSLOG, AVMSLEOG:
return op_VMSL, 3, 0
case AVACCC:
return op_VACCC, 0, 0
@ -1058,6 +1058,12 @@ func singleElementMask(as obj.As) uint32 {
AWFTCIDB,
AWFIDB:
return 8
case AVMSLEG:
return 8
case AVMSLOG:
return 4
case AVMSLEOG:
return 12
}
return 0
}

View file

@ -314,6 +314,18 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
break
}
// On AIX, if a relocated symbol is in .data, a second relocation
// must be done by the loader, as the section .data will be moved.
// The "default" symbol address is still needed by the loader so
// the current relocation can't be skipped.
// runtime.algarray is different because it will end up in .rodata section
if ctxt.HeadType == objabi.Haix && r.Sym.Sect.Seg == &Segdata && r.Sym.Name != "runtime.algarray" {
// It's not possible to make a loader relocation to a DWARF section.
// FIXME
if s.Sect.Seg != &Segdwarf {
xcoffaddloaderreloc(ctxt, s, r)
}
}
o = Symaddr(r.Sym) + r.Add
@ -606,6 +618,7 @@ func dynrelocsym(ctxt *Link, s *sym.Symbol) {
thearch.Adddynrel(ctxt, s, r)
continue
}
if r.Sym != nil && r.Sym.Type == sym.SDYNIMPORT || r.Type >= 256 {
if r.Sym != nil && !r.Sym.Attr.Reachable() {
Errorf(s, "dynamic relocation to unreachable symbol %s", r.Sym.Name)
@ -1329,6 +1342,14 @@ func (ctxt *Link) dodata() {
gc.AddSym(s)
datsize += s.Size
}
// On AIX, TOC entries must be the last of .data
for _, s := range data[sym.SXCOFFTOC] {
s.Sect = sect
s.Type = sym.SDATA
datsize = aligndatsize(datsize, s)
s.Value = int64(uint64(datsize) - sect.Vaddr)
datsize += s.Size
}
checkdatsize(ctxt, datsize, sym.SDATA)
sect.Length = uint64(datsize) - sect.Vaddr
gc.End(int64(sect.Length))
@ -1688,6 +1709,10 @@ func (ctxt *Link) dodata() {
}
for _, sect := range Segdata.Sections {
sect.Extnum = int16(n)
if ctxt.HeadType == objabi.Haix && (sect.Name == ".noptrdata" || sect.Name == ".bss") {
// On AIX, "noptr" sections are merged with their "ptr" section
continue
}
n++
}
for _, sect := range Segdwarf.Sections {

View file

@ -67,7 +67,12 @@ func (c dwctxt) AddSectionOffset(s dwarf.Sym, size int, t interface{}, ofs int64
r.Add = ofs
}
func (c dwctxt) AddDWARFSectionOffset(s dwarf.Sym, size int, t interface{}, ofs int64) {
func (c dwctxt) AddDWARFAddrSectionOffset(s dwarf.Sym, t interface{}, ofs int64) {
size := 4
if isDwarf64(c.linkctxt) {
size = 8
}
c.AddSectionOffset(s, size, t, ofs)
ls := s.(*sym.Symbol)
ls.R[len(ls.R)-1].Type = objabi.R_DWARFSECREF
@ -95,6 +100,10 @@ func (c dwctxt) RecordChildDieOffsets(s dwarf.Sym, vars []*dwarf.Var, offsets []
panic("should be used only in the compiler")
}
func isDwarf64(ctxt *Link) bool {
return ctxt.HeadType == objabi.Haix
}
var gdbscript string
var dwarfp []*sym.Symbol
@ -873,6 +882,33 @@ func defdwsymb(ctxt *Link, s *sym.Symbol, str string, t SymbolType, v int64, got
}
}
// createUnitLength creates the initial length field with value v and update
// offset of unit_length if needed.
func createUnitLength(ctxt *Link, s *sym.Symbol, v uint64) {
if isDwarf64(ctxt) {
s.AddUint32(ctxt.Arch, 0xFFFFFFFF)
}
addDwarfAddrField(ctxt, s, v)
}
// addDwarfAddrField adds a DWARF field in DWARF 64bits or 32bits.
func addDwarfAddrField(ctxt *Link, s *sym.Symbol, v uint64) {
if isDwarf64(ctxt) {
s.AddUint(ctxt.Arch, v)
} else {
s.AddUint32(ctxt.Arch, uint32(v))
}
}
// addDwarfAddrRef adds a DWARF pointer in DWARF 64bits or 32bits.
func addDwarfAddrRef(ctxt *Link, s *sym.Symbol, t *sym.Symbol) {
if isDwarf64(ctxt) {
adddwarfref(ctxt, s, t, 8)
} else {
adddwarfref(ctxt, s, t, 4)
}
}
// compilationUnit is per-compilation unit (equivalently, per-package)
// debug-related data.
type compilationUnit struct {
@ -1081,11 +1117,11 @@ func writelines(ctxt *Link, unit *compilationUnit, ls *sym.Symbol) {
// Write .debug_line Line Number Program Header (sec 6.2.4)
// Fields marked with (*) must be changed for 64-bit dwarf
unitLengthOffset := ls.Size
ls.AddUint32(ctxt.Arch, 0) // unit_length (*), filled in at end.
createUnitLength(ctxt, ls, 0) // unit_length (*), filled in at end
unitstart = ls.Size
ls.AddUint16(ctxt.Arch, 2) // dwarf version (appendix F) -- version 3 is incompatible w/ XCode 9.0's dsymutil, latest supported on OSX 10.12 as of 2018-05
headerLengthOffset := ls.Size
ls.AddUint32(ctxt.Arch, 0) // header_length (*), filled in at end.
addDwarfAddrField(ctxt, ls, 0) // header_length (*), filled in at end
headerstart = ls.Size
// cpos == unitstart + 4 + 2 + 4
@ -1238,8 +1274,16 @@ func writelines(ctxt *Link, unit *compilationUnit, ls *sym.Symbol) {
dwarf.Uleb128put(dwarfctxt, ls, 1)
ls.AddUint8(dwarf.DW_LNE_end_sequence)
ls.SetUint32(ctxt.Arch, unitLengthOffset, uint32(ls.Size-unitstart))
ls.SetUint32(ctxt.Arch, headerLengthOffset, uint32(headerend-headerstart))
if ctxt.HeadType == objabi.Haix {
saveDwsectCUSize(".debug_line", unit.lib.String(), uint64(ls.Size-unitLengthOffset))
}
if isDwarf64(ctxt) {
ls.SetUint(ctxt.Arch, unitLengthOffset+4, uint64(ls.Size-unitstart)) // +4 because of 0xFFFFFFFF
ls.SetUint(ctxt.Arch, headerLengthOffset, uint64(headerend-headerstart))
} else {
ls.SetUint32(ctxt.Arch, unitLengthOffset, uint32(ls.Size-unitstart))
ls.SetUint32(ctxt.Arch, headerLengthOffset, uint32(headerend-headerstart))
}
// Apply any R_DWARFFILEREF relocations, since we now know the
// line table file indices for this compilation unit. Note that
@ -1329,8 +1373,8 @@ func writeframes(ctxt *Link, syms []*sym.Symbol) []*sym.Symbol {
if haslinkregister(ctxt) {
cieReserve = 32
}
fs.AddUint32(ctxt.Arch, cieReserve) // initial length, must be multiple of thearch.ptrsize
fs.AddUint32(ctxt.Arch, 0xffffffff) // cid.
createUnitLength(ctxt, fs, uint64(cieReserve)) // initial length, must be multiple of thearch.ptrsize
addDwarfAddrField(ctxt, fs, 0xffffffff) // cid.
fs.AddUint8(3) // dwarf version (appendix F)
fs.AddUint8(0) // augmentation ""
dwarf.Uleb128put(dwarfctxt, fs, 1) // code_alignment_factor
@ -1418,9 +1462,9 @@ func writeframes(ctxt *Link, syms []*sym.Symbol) []*sym.Symbol {
// ptrsize: address range
fs.AddUint32(ctxt.Arch, uint32(4+2*ctxt.Arch.PtrSize+len(deltaBuf))) // length (excludes itself)
if ctxt.LinkMode == LinkExternal {
adddwarfref(ctxt, fs, fs, 4)
addDwarfAddrRef(ctxt, fs, fs)
} else {
fs.AddUint32(ctxt.Arch, 0) // CIE offset
addDwarfAddrField(ctxt, fs, 0) // CIE offset
}
fs.AddAddr(ctxt.Arch, s)
fs.AddUintXX(ctxt.Arch, uint64(s.Size), ctxt.Arch.PtrSize) // address range
@ -1455,11 +1499,11 @@ func writeinfo(ctxt *Link, syms []*sym.Symbol, units []*compilationUnit, abbrevs
// Write .debug_info Compilation Unit Header (sec 7.5.1)
// Fields marked with (*) must be changed for 64-bit dwarf
// This must match COMPUNITHEADERSIZE above.
s.AddUint32(ctxt.Arch, 0) // unit_length (*), will be filled in later.
s.AddUint16(ctxt.Arch, 4) // dwarf version (appendix F)
createUnitLength(ctxt, s, 0) // unit_length (*), will be filled in later.
s.AddUint16(ctxt.Arch, 4) // dwarf version (appendix F)
// debug_abbrev_offset (*)
adddwarfref(ctxt, s, abbrevsym, 4)
addDwarfAddrRef(ctxt, s, abbrevsym)
s.AddUint8(uint8(ctxt.Arch.PtrSize)) // address_size
@ -1477,8 +1521,17 @@ func writeinfo(ctxt *Link, syms []*sym.Symbol, units []*compilationUnit, abbrevs
for _, child := range cu {
cusize += child.Size
}
cusize -= 4 // exclude the length field.
s.SetUint32(ctxt.Arch, 0, uint32(cusize))
// Save size for AIX symbol table.
if ctxt.HeadType == objabi.Haix {
saveDwsectCUSize(".debug_info", getPkgFromCUSym(s), uint64(cusize))
}
if isDwarf64(ctxt) {
cusize -= 12 // exclude the length field.
s.SetUint(ctxt.Arch, 4, uint64(cusize)) // 4 because of 0XFFFFFFFF
} else {
cusize -= 4 // exclude the length field.
s.SetUint32(ctxt.Arch, 0, uint32(cusize))
}
// Leave a breadcrumb for writepub. This does not
// appear in the DWARF output.
newattr(compunit, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, cusize, 0)
@ -1519,10 +1572,10 @@ func writepub(ctxt *Link, sname string, ispub func(*dwarf.DWDie) bool, syms []*s
culength := uint32(getattr(compunit, dwarf.DW_AT_byte_size).Value) + 4
// Write .debug_pubnames/types Header (sec 6.1.1)
s.AddUint32(ctxt.Arch, 0) // unit_length (*), will be filled in later.
s.AddUint16(ctxt.Arch, 2) // dwarf version (appendix F)
adddwarfref(ctxt, s, dtolsym(compunit.Sym), 4) // debug_info_offset (of the Comp unit Header)
s.AddUint32(ctxt.Arch, culength) // debug_info_length
createUnitLength(ctxt, s, 0) // unit_length (*), will be filled in later.
s.AddUint16(ctxt.Arch, 2) // dwarf version (appendix F)
addDwarfAddrRef(ctxt, s, dtolsym(compunit.Sym)) // debug_info_offset (of the Comp unit Header)
addDwarfAddrField(ctxt, s, uint64(culength)) // debug_info_length
for die := compunit.Child; die != nil; die = die.Link {
if !ispub(die) {
@ -1533,19 +1586,31 @@ func writepub(ctxt *Link, sname string, ispub func(*dwarf.DWDie) bool, syms []*s
if die.Sym == nil {
fmt.Println("Missing sym for ", name)
}
adddwarfref(ctxt, s, dtolsym(die.Sym), 4)
addDwarfAddrRef(ctxt, s, dtolsym(die.Sym))
Addstring(s, name)
}
s.AddUint32(ctxt.Arch, 0)
addDwarfAddrField(ctxt, s, 0) // Null offset
s.SetUint32(ctxt.Arch, sectionstart, uint32(s.Size-sectionstart)-4) // exclude the length field.
// On AIX, save the current size of this compilation unit.
if ctxt.HeadType == objabi.Haix {
saveDwsectCUSize(sname, getPkgFromCUSym(dtolsym(compunit.Sym)), uint64(s.Size-sectionstart))
}
if isDwarf64(ctxt) {
s.SetUint(ctxt.Arch, sectionstart+4, uint64(s.Size-sectionstart)-12) // exclude the length field.
} else {
s.SetUint32(ctxt.Arch, sectionstart, uint32(s.Size-sectionstart)-4) // exclude the length field.
}
}
return syms
}
func writegdbscript(ctxt *Link, syms []*sym.Symbol) []*sym.Symbol {
// TODO (aix): make it available
if ctxt.HeadType == objabi.Haix {
return syms
}
if ctxt.LinkMode == LinkExternal && ctxt.HeadType == objabi.Hwindows && ctxt.BuildMode == BuildModeCArchive {
// gcc on Windows places .debug_gdb_scripts in the wrong location, which
// causes the program not to run. See https://golang.org/issue/20183
@ -2019,3 +2084,27 @@ func (v compilationUnitByStartPC) Less(i, j int) bool {
return v[i].lib.Textp[0].Value < v[j].lib.Textp[0].Value
}
}
// On AIX, the symbol table needs to know where are the compilation units parts
// for a specific package in each .dw section.
// dwsectCUSize map will save the size of a compilation unit for
// the corresponding .dw section.
// This size can later be retrieved with the index "sectionName.pkgName".
var dwsectCUSize map[string]uint64
// getDwsectCUSize retrieves the corresponding package size inside the current section.
func getDwsectCUSize(sname string, pkgname string) uint64 {
return dwsectCUSize[sname+"."+pkgname]
}
func saveDwsectCUSize(sname string, pkgname string, size uint64) {
dwsectCUSize[sname+"."+pkgname] = size
}
// getPkgFromCUSym returns the package name for the compilation unit
// represented by s.
// The prefix dwarf.InfoPrefix+".pkg." needs to be removed in order to get
// the package name.
func getPkgFromCUSym(s *sym.Symbol) string {
return strings.TrimPrefix(s.Name, dwarf.InfoPrefix+".pkg.")
}

View file

@ -163,6 +163,10 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) {
}
havedynamic = 1
}
if ctxt.HeadType == objabi.Haix {
xcoffadddynimpsym(ctxt, s)
}
continue
case "cgo_import_static":
@ -317,7 +321,8 @@ func fieldtrack(ctxt *Link) {
}
func (ctxt *Link) addexport() {
if ctxt.HeadType == objabi.Hdarwin {
// TODO(aix)
if ctxt.HeadType == objabi.Hdarwin || ctxt.HeadType == objabi.Haix {
return
}

View file

@ -39,6 +39,7 @@ import (
"cmd/link/internal/loadelf"
"cmd/link/internal/loadmacho"
"cmd/link/internal/loadpe"
"cmd/link/internal/loadxcoff"
"cmd/link/internal/objfile"
"cmd/link/internal/sym"
"crypto/sha1"
@ -1338,9 +1339,24 @@ func (ctxt *Link) hostlink() {
ctxt.Logf("\n")
}
if out, err := exec.Command(argv[0], argv[1:]...).CombinedOutput(); err != nil {
out, err := exec.Command(argv[0], argv[1:]...).CombinedOutput()
if err != nil {
Exitf("running %s failed: %v\n%s", argv[0], err, out)
} else if len(out) > 0 {
}
// Filter out useless linker warnings caused by bugs outside Go.
// See also cmd/go/internal/work/exec.go's gccld method.
var save [][]byte
for _, line := range bytes.SplitAfter(out, []byte("\n")) {
// golang.org/issue/26073 - Apple Xcode bug
if bytes.Contains(line, []byte("ld: warning: text-based stub file")) {
continue
}
save = append(save, line)
}
out = bytes.Join(save, nil)
if len(out) > 0 {
// always print external output even if the command is successful, so that we don't
// swallow linker warnings (see https://golang.org/issue/17935).
ctxt.Logf("%s", out)
@ -1518,6 +1534,18 @@ func ldobj(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, pn string,
return ldhostobj(ldpe, ctxt.HeadType, f, pkg, length, pn, file)
}
if c1 == 0x01 && (c2 == 0xD7 || c2 == 0xF7) {
ldxcoff := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
textp, err := loadxcoff.Load(ctxt.Arch, ctxt.Syms, f, pkg, length, pn)
if err != nil {
Errorf(nil, "%v", err)
return
}
ctxt.Textp = append(ctxt.Textp, textp...)
}
return ldhostobj(ldxcoff, ctxt.HeadType, f, pkg, length, pn, file)
}
/* check the header */
line, err := f.ReadString('\n')
if err != nil {
@ -2244,7 +2272,7 @@ func Entryvalue(ctxt *Link) int64 {
if s.Type == 0 {
return *FlagTextAddr
}
if s.Type != sym.STEXT {
if ctxt.HeadType != objabi.Haix && s.Type != sym.STEXT {
Errorf(s, "entry not text")
}
return s.Value

View file

@ -224,6 +224,10 @@ func Main(arch *sys.Arch, theArch Arch) {
ctxt.dope()
ctxt.windynrelocsyms()
}
if ctxt.HeadType == objabi.Haix {
ctxt.doxcoff()
}
ctxt.addexport()
thearch.Gentext(ctxt) // trampolines, call stubs, etc.
ctxt.textbuildid()

View file

@ -66,7 +66,7 @@ func (ctxt *Link) computeTLSOffset() {
default:
log.Fatalf("unknown thread-local storage offset for %v", ctxt.HeadType)
case objabi.Hplan9, objabi.Hwindows, objabi.Hjs:
case objabi.Hplan9, objabi.Hwindows, objabi.Hjs, objabi.Haix:
break
/*

File diff suppressed because it is too large Load diff

View file

@ -692,6 +692,11 @@ func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bo
// Runtime Handling" of "Power Architecture 64-Bit ELF V2 ABI
// Specification".
v := r.Sym.Value - 0x7000
if ctxt.HeadType == objabi.Haix {
// On AIX, the thread pointer points 0x7800 bytes after
// the TLS.
v -= 0x800
}
if int64(int16(v)) != v {
ld.Errorf(s, "TLS offset out of range %d", v)
}
@ -941,6 +946,13 @@ func asmb(ctxt *ld.Link) {
ctxt.Out.SeekSet(int64(ld.Segdwarf.Fileoff))
ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
loadersize := uint64(0)
if ctxt.HeadType == objabi.Haix && ctxt.BuildMode == ld.BuildModeExe {
loadero := uint64(ld.Rnd(int64(ld.Segdwarf.Fileoff+ld.Segdwarf.Filelen), int64(*ld.FlagRound)))
ctxt.Out.SeekSet(int64(loadero))
loadersize = ld.Loaderblk(ctxt, loadero)
}
/* output symbol table */
ld.Symsize = 0
@ -960,6 +972,16 @@ func asmb(ctxt *ld.Link) {
case objabi.Hplan9:
symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
case objabi.Haix:
symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
// Add loader size if needed
if ctxt.BuildMode == ld.BuildModeExe {
symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
symo += uint32(loadersize)
}
symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
}
ctxt.Out.SeekSet(int64(symo))
@ -988,6 +1010,10 @@ func asmb(ctxt *ld.Link) {
ctxt.Out.Write(sym.P)
ctxt.Out.Flush()
}
case objabi.Haix:
ld.Asmaixsym(ctxt)
ctxt.Out.Flush()
}
}
@ -1013,6 +1039,9 @@ func asmb(ctxt *ld.Link) {
objabi.Hopenbsd,
objabi.Hnacl:
ld.Asmbelf(ctxt, int64(symo))
case objabi.Haix:
ld.Asmbxcoff(ctxt)
}
ctxt.Out.Flush()

View file

@ -121,6 +121,10 @@ func archinit(ctxt *ld.Link) {
if *ld.FlagRound == -1 {
*ld.FlagRound = 0x10000
}
case objabi.Haix:
ld.Xcoffinit(ctxt)
}
if *ld.FlagDataAddr != 0 && *ld.FlagRound != 0 {

View file

@ -116,6 +116,23 @@ func (l *List) remove(e *Element) *Element {
return e
}
// move moves e to next to at and returns e.
func (l *List) move(e, at *Element) *Element {
if e == at {
return e
}
e.prev.next = e.next
e.next.prev = e.prev
n := at.next
at.next = e
e.prev = at
e.next = n
n.prev = e
return e
}
// Remove removes e from l if e is an element of list l.
// It returns the element value e.Value.
// The element must not be nil.
@ -170,7 +187,7 @@ func (l *List) MoveToFront(e *Element) {
return
}
// see comment in List.Remove about initialization of l
l.insert(l.remove(e), &l.root)
l.move(e, &l.root)
}
// MoveToBack moves element e to the back of list l.
@ -181,7 +198,7 @@ func (l *List) MoveToBack(e *Element) {
return
}
// see comment in List.Remove about initialization of l
l.insert(l.remove(e), l.root.prev)
l.move(e, l.root.prev)
}
// MoveBefore moves element e to its new position before mark.
@ -191,7 +208,7 @@ func (l *List) MoveBefore(e, mark *Element) {
if e.list != l || e == mark || mark.list != l {
return
}
l.insert(l.remove(e), mark.prev)
l.move(e, mark.prev)
}
// MoveAfter moves element e to its new position after mark.
@ -201,7 +218,7 @@ func (l *List) MoveAfter(e, mark *Element) {
if e.list != l || e == mark || mark.list != l {
return
}
l.insert(l.remove(e), mark)
l.move(e, mark)
}
// PushBackList inserts a copy of an other list at the back of list l.

View file

@ -28,6 +28,7 @@ func TestBoringServerProtocolVersion(t *testing.T) {
serverConfig.MinVersion = VersionSSL30
clientHello := &clientHelloMsg{
vers: v,
random: make([]byte, 32),
cipherSuites: allCipherSuites(),
compressionMethods: []uint8{compressionNone},
}
@ -110,6 +111,7 @@ func TestBoringServerCipherSuites(t *testing.T) {
t.Run(fmt.Sprintf("suite=%#x", id), func(t *testing.T) {
clientHello := &clientHelloMsg{
vers: VersionTLS12,
random: make([]byte, 32),
cipherSuites: []uint16{id},
compressionMethods: []uint8{compressionNone},
supportedCurves: defaultCurvePreferences,
@ -141,6 +143,7 @@ func TestBoringServerCurves(t *testing.T) {
t.Run(fmt.Sprintf("curve=%d", curveid), func(t *testing.T) {
clientHello := &clientHelloMsg{
vers: VersionTLS12,
random: make([]byte, 32),
cipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
compressionMethods: []uint8{compressionNone},
supportedCurves: []CurveID{curveid},

View file

@ -478,12 +478,18 @@ type RecordHeaderError struct {
// RecordHeader contains the five bytes of TLS record header that
// triggered the error.
RecordHeader [5]byte
// Conn provides the underlying net.Conn in the case that a client
// sent an initial handshake that didn't look like TLS.
// It is nil if there's already been a handshake or a TLS alert has
// been written to the connection.
Conn net.Conn
}
func (e RecordHeaderError) Error() string { return "tls: " + e.Msg }
func (c *Conn) newRecordHeaderError(msg string) (err RecordHeaderError) {
func (c *Conn) newRecordHeaderError(conn net.Conn, msg string) (err RecordHeaderError) {
err.Msg = msg
err.Conn = conn
copy(err.RecordHeader[:], c.rawInput.Bytes())
return err
}
@ -535,7 +541,7 @@ func (c *Conn) readRecord(want recordType) error {
// an SSLv2 client.
if want == recordTypeHandshake && typ == 0x80 {
c.sendAlert(alertProtocolVersion)
return c.in.setErrorLocked(c.newRecordHeaderError("unsupported SSLv2 handshake received"))
return c.in.setErrorLocked(c.newRecordHeaderError(nil, "unsupported SSLv2 handshake received"))
}
vers := uint16(hdr[1])<<8 | uint16(hdr[2])
@ -543,12 +549,7 @@ func (c *Conn) readRecord(want recordType) error {
if c.haveVers && vers != c.vers {
c.sendAlert(alertProtocolVersion)
msg := fmt.Sprintf("received record with version %x when expecting version %x", vers, c.vers)
return c.in.setErrorLocked(c.newRecordHeaderError(msg))
}
if n > maxCiphertext {
c.sendAlert(alertRecordOverflow)
msg := fmt.Sprintf("oversized record received with length %d", n)
return c.in.setErrorLocked(c.newRecordHeaderError(msg))
return c.in.setErrorLocked(c.newRecordHeaderError(nil, msg))
}
if !c.haveVers {
// First message, be extra suspicious: this might not be a TLS
@ -556,10 +557,14 @@ func (c *Conn) readRecord(want recordType) error {
// The current max version is 3.3 so if the version is >= 16.0,
// it's probably not real.
if (typ != recordTypeAlert && typ != want) || vers >= 0x1000 {
c.sendAlert(alertUnexpectedMessage)
return c.in.setErrorLocked(c.newRecordHeaderError("first record does not look like a TLS handshake"))
return c.in.setErrorLocked(c.newRecordHeaderError(c.conn, "first record does not look like a TLS handshake"))
}
}
if n > maxCiphertext {
c.sendAlert(alertRecordOverflow)
msg := fmt.Sprintf("oversized record received with length %d", n)
return c.in.setErrorLocked(c.newRecordHeaderError(nil, msg))
}
if err := c.readFromUntil(c.conn, recordHeaderLen+n); err != nil {
if e, ok := err.(net.Error); !ok || !e.Temporary() {
c.in.setErrorLocked(err)
@ -894,7 +899,7 @@ func (c *Conn) readHandshake() (interface{}, error) {
m = new(certificateMsg)
case typeCertificateRequest:
m = &certificateRequestMsg{
hasSignatureAndHash: c.vers >= VersionTLS12,
hasSignatureAlgorithm: c.vers >= VersionTLS12,
}
case typeCertificateStatus:
m = new(certificateStatusMsg)
@ -906,7 +911,7 @@ func (c *Conn) readHandshake() (interface{}, error) {
m = new(clientKeyExchangeMsg)
case typeCertificateVerify:
m = &certificateVerifyMsg{
hasSignatureAndHash: c.vers >= VersionTLS12,
hasSignatureAlgorithm: c.vers >= VersionTLS12,
}
case typeNextProtocol:
m = new(nextProtoMsg)

View file

@ -476,7 +476,7 @@ func (hs *clientHandshakeState) doFullHandshake() error {
if chainToSend != nil && len(chainToSend.Certificate) > 0 {
certVerify := &certificateVerifyMsg{
hasSignatureAndHash: c.vers >= VersionTLS12,
hasSignatureAlgorithm: c.vers >= VersionTLS12,
}
key, ok := chainToSend.PrivateKey.(crypto.Signer)
@ -491,7 +491,7 @@ func (hs *clientHandshakeState) doFullHandshake() error {
return err
}
// SignatureAndHashAlgorithm was introduced in TLS 1.2.
if certVerify.hasSignatureAndHash {
if certVerify.hasSignatureAlgorithm {
certVerify.signatureAlgorithm = signatureAlgorithm
}
digest, err := hs.finishedHash.hashForClientCertificate(sigType, hashFunc, hs.masterSecret)
@ -744,7 +744,7 @@ func (hs *clientHandshakeState) getCertificate(certReq *certificateRequestMsg) (
if c.config.GetClientCertificate != nil {
var signatureSchemes []SignatureScheme
if !certReq.hasSignatureAndHash {
if !certReq.hasSignatureAlgorithm {
// Prior to TLS 1.2, the signature schemes were not
// included in the certificate request message. In this
// case we use a plausible list based on the acceptable

View file

@ -384,10 +384,12 @@ func (test *clientTest) run(t *testing.T, write bool) {
}
for i, b := range flows {
if i%2 == 1 {
serverConn.SetWriteDeadline(time.Now().Add(1 * time.Minute))
serverConn.Write(b)
continue
}
bb := make([]byte, len(b))
serverConn.SetReadDeadline(time.Now().Add(1 * time.Minute))
_, err := io.ReadFull(serverConn, bb)
if err != nil {
t.Fatalf("%s #%d: %s", test.name, i, err)
@ -1644,7 +1646,7 @@ func TestCloseClientConnectionOnIdleServer(t *testing.T) {
serverConn.Read(b[:])
client.Close()
}()
client.SetWriteDeadline(time.Now().Add(time.Second))
client.SetWriteDeadline(time.Now().Add(time.Minute))
err := client.Handshake()
if err != nil {
if err, ok := err.(net.Error); ok && err.Timeout() {

File diff suppressed because it is too large Load diff

View file

@ -20,7 +20,9 @@ var tests = []interface{}{
&certificateMsg{},
&certificateRequestMsg{},
&certificateVerifyMsg{},
&certificateVerifyMsg{
hasSignatureAlgorithm: true,
},
&certificateStatusMsg{},
&clientKeyExchangeMsg{},
&nextProtoMsg{},
@ -28,12 +30,6 @@ var tests = []interface{}{
&sessionState{},
}
type testMessage interface {
marshal() []byte
unmarshal([]byte) bool
equal(interface{}) bool
}
func TestMarshalUnmarshal(t *testing.T) {
rand := rand.New(rand.NewSource(0))
@ -51,16 +47,16 @@ func TestMarshalUnmarshal(t *testing.T) {
break
}
m1 := v.Interface().(testMessage)
m1 := v.Interface().(handshakeMessage)
marshaled := m1.marshal()
m2 := iface.(testMessage)
m2 := iface.(handshakeMessage)
if !m2.unmarshal(marshaled) {
t.Errorf("#%d failed to unmarshal %#v %x", i, m1, marshaled)
break
}
m2.marshal() // to fill any marshal cache in the message
if !m1.equal(m2) {
if !reflect.DeepEqual(m1, m2) {
t.Errorf("#%d got:%#v want:%#v %x", i, m2, m1, marshaled)
break
}
@ -85,7 +81,7 @@ func TestMarshalUnmarshal(t *testing.T) {
func TestFuzz(t *testing.T) {
rand := rand.New(rand.NewSource(0))
for _, iface := range tests {
m := iface.(testMessage)
m := iface.(handshakeMessage)
for j := 0; j < 1000; j++ {
len := rand.Intn(100)
@ -142,18 +138,23 @@ func (*clientHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
m.ticketSupported = true
if rand.Intn(10) > 5 {
m.sessionTicket = randomBytes(rand.Intn(300), rand)
} else {
m.sessionTicket = make([]byte, 0)
}
}
if rand.Intn(10) > 5 {
m.supportedSignatureAlgorithms = supportedSignatureAlgorithms()
}
m.alpnProtocols = make([]string, rand.Intn(5))
for i := range m.alpnProtocols {
m.alpnProtocols[i] = randomString(rand.Intn(20)+1, rand)
for i := 0; i < rand.Intn(5); i++ {
m.alpnProtocols = append(m.alpnProtocols, randomString(rand.Intn(20)+1, rand))
}
if rand.Intn(10) > 5 {
m.scts = true
}
if rand.Intn(10) > 5 {
m.secureRenegotiationSupported = true
m.secureRenegotiation = randomBytes(rand.Intn(50)+1, rand)
}
return reflect.ValueOf(m)
}
@ -168,11 +169,8 @@ func (*serverHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
if rand.Intn(10) > 5 {
m.nextProtoNeg = true
n := rand.Intn(10)
m.nextProtos = make([]string, n)
for i := 0; i < n; i++ {
m.nextProtos[i] = randomString(20, rand)
for i := 0; i < rand.Intn(10); i++ {
m.nextProtos = append(m.nextProtos, randomString(20, rand))
}
}
@ -184,12 +182,13 @@ func (*serverHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
}
m.alpnProtocol = randomString(rand.Intn(32)+1, rand)
for i := 0; i < rand.Intn(4); i++ {
m.scts = append(m.scts, randomBytes(rand.Intn(500)+1, rand))
}
if rand.Intn(10) > 5 {
numSCTs := rand.Intn(4)
m.scts = make([][]byte, numSCTs)
for i := range m.scts {
m.scts[i] = randomBytes(rand.Intn(500)+1, rand)
}
m.secureRenegotiationSupported = true
m.secureRenegotiation = randomBytes(rand.Intn(50)+1, rand)
}
return reflect.ValueOf(m)
@ -208,16 +207,16 @@ func (*certificateMsg) Generate(rand *rand.Rand, size int) reflect.Value {
func (*certificateRequestMsg) Generate(rand *rand.Rand, size int) reflect.Value {
m := &certificateRequestMsg{}
m.certificateTypes = randomBytes(rand.Intn(5)+1, rand)
numCAs := rand.Intn(100)
m.certificateAuthorities = make([][]byte, numCAs)
for i := 0; i < numCAs; i++ {
m.certificateAuthorities[i] = randomBytes(rand.Intn(15)+1, rand)
for i := 0; i < rand.Intn(100); i++ {
m.certificateAuthorities = append(m.certificateAuthorities, randomBytes(rand.Intn(15)+1, rand))
}
return reflect.ValueOf(m)
}
func (*certificateVerifyMsg) Generate(rand *rand.Rand, size int) reflect.Value {
m := &certificateVerifyMsg{}
m.hasSignatureAlgorithm = true
m.signatureAlgorithm = SignatureScheme(rand.Intn(30000))
m.signature = randomBytes(rand.Intn(15)+1, rand)
return reflect.ValueOf(m)
}

View file

@ -418,7 +418,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
byte(certTypeECDSASign),
}
if c.vers >= VersionTLS12 {
certReq.hasSignatureAndHash = true
certReq.hasSignatureAlgorithm = true
certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms()
}

View file

@ -101,13 +101,17 @@ var badProtocolVersions = []uint16{0x0000, 0x0005, 0x0100, 0x0105, 0x0200, 0x020
func TestRejectBadProtocolVersion(t *testing.T) {
for _, v := range badProtocolVersions {
testClientHelloFailure(t, testConfig, &clientHelloMsg{vers: v}, "unsupported, maximum protocol version")
testClientHelloFailure(t, testConfig, &clientHelloMsg{
vers: v,
random: make([]byte, 32),
}, "unsupported, maximum protocol version")
}
}
func TestNoSuiteOverlap(t *testing.T) {
clientHello := &clientHelloMsg{
vers: VersionTLS10,
random: make([]byte, 32),
cipherSuites: []uint16{0xff00},
compressionMethods: []uint8{compressionNone},
}
@ -117,6 +121,7 @@ func TestNoSuiteOverlap(t *testing.T) {
func TestNoCompressionOverlap(t *testing.T) {
clientHello := &clientHelloMsg{
vers: VersionTLS10,
random: make([]byte, 32),
cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
compressionMethods: []uint8{0xff},
}
@ -126,6 +131,7 @@ func TestNoCompressionOverlap(t *testing.T) {
func TestNoRC4ByDefault(t *testing.T) {
clientHello := &clientHelloMsg{
vers: VersionTLS10,
random: make([]byte, 32),
cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
compressionMethods: []uint8{compressionNone},
}
@ -137,7 +143,11 @@ func TestNoRC4ByDefault(t *testing.T) {
}
func TestRejectSNIWithTrailingDot(t *testing.T) {
testClientHelloFailure(t, testConfig, &clientHelloMsg{vers: VersionTLS12, serverName: "foo.com."}, "unexpected message")
testClientHelloFailure(t, testConfig, &clientHelloMsg{
vers: VersionTLS12,
random: make([]byte, 32),
serverName: "foo.com.",
}, "unexpected message")
}
func TestDontSelectECDSAWithRSAKey(t *testing.T) {
@ -145,6 +155,7 @@ func TestDontSelectECDSAWithRSAKey(t *testing.T) {
// won't be selected if the server's private key doesn't support it.
clientHello := &clientHelloMsg{
vers: VersionTLS10,
random: make([]byte, 32),
cipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
compressionMethods: []uint8{compressionNone},
supportedCurves: []CurveID{CurveP256},
@ -170,6 +181,7 @@ func TestDontSelectRSAWithECDSAKey(t *testing.T) {
// won't be selected if the server's private key doesn't support it.
clientHello := &clientHelloMsg{
vers: VersionTLS10,
random: make([]byte, 32),
cipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
compressionMethods: []uint8{compressionNone},
supportedCurves: []CurveID{CurveP256},
@ -242,11 +254,9 @@ func TestRenegotiationExtension(t *testing.T) {
func TestTLS12OnlyCipherSuites(t *testing.T) {
// Test that a Server doesn't select a TLS 1.2-only cipher suite when
// the client negotiates TLS 1.1.
var zeros [32]byte
clientHello := &clientHelloMsg{
vers: VersionTLS11,
random: zeros[:],
random: make([]byte, 32),
cipherSuites: []uint16{
// The Server, by default, will use the client's
// preference order. So the GCM cipher suite
@ -615,10 +625,12 @@ func (test *serverTest) run(t *testing.T, write bool) {
}
for i, b := range flows {
if i%2 == 0 {
clientConn.SetWriteDeadline(time.Now().Add(1 * time.Minute))
clientConn.Write(b)
continue
}
bb := make([]byte, len(b))
clientConn.SetReadDeadline(time.Now().Add(1 * time.Minute))
n, err := io.ReadFull(clientConn, bb)
if err != nil {
t.Fatalf("%s #%d: %s\nRead %d, wanted %d, got %x, wanted %x\n", test.name, i+1, err, n, len(bb), bb[:n], b)
@ -876,6 +888,7 @@ func TestHandshakeServerSNIGetCertificateError(t *testing.T) {
clientHello := &clientHelloMsg{
vers: VersionTLS10,
random: make([]byte, 32),
cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
compressionMethods: []uint8{compressionNone},
serverName: "test",
@ -896,6 +909,7 @@ func TestHandshakeServerEmptyCertificates(t *testing.T) {
clientHello := &clientHelloMsg{
vers: VersionTLS10,
random: make([]byte, 32),
cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
compressionMethods: []uint8{compressionNone},
}
@ -907,6 +921,7 @@ func TestHandshakeServerEmptyCertificates(t *testing.T) {
clientHello = &clientHelloMsg{
vers: VersionTLS10,
random: make([]byte, 32),
cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
compressionMethods: []uint8{compressionNone},
}
@ -1210,6 +1225,7 @@ func TestSNIGivenOnFailure(t *testing.T) {
clientHello := &clientHelloMsg{
vers: VersionTLS10,
random: make([]byte, 32),
cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
compressionMethods: []uint8{compressionNone},
serverName: expectedServerName,
@ -1432,7 +1448,7 @@ func TestCloseServerConnectionOnIdleClient(t *testing.T) {
clientConn.Write([]byte{'0'})
server.Close()
}()
server.SetReadDeadline(time.Now().Add(time.Second))
server.SetReadDeadline(time.Now().Add(time.Minute))
err := server.Handshake()
if err != nil {
if err, ok := err.(net.Error); ok && err.Timeout() {

View file

@ -27,31 +27,6 @@ type sessionState struct {
usedOldKey bool
}
func (s *sessionState) equal(i interface{}) bool {
s1, ok := i.(*sessionState)
if !ok {
return false
}
if s.vers != s1.vers ||
s.cipherSuite != s1.cipherSuite ||
!bytes.Equal(s.masterSecret, s1.masterSecret) {
return false
}
if len(s.certificates) != len(s1.certificates) {
return false
}
for i := range s.certificates {
if !bytes.Equal(s.certificates[i], s1.certificates[i]) {
return false
}
}
return true
}
func (s *sessionState) marshal() []byte {
length := 2 + 2 + 2 + len(s.masterSecret) + 2
for _, cert := range s.certificates {

View file

@ -2605,6 +2605,15 @@ type Rows struct {
lastcols []driver.Value
}
// lasterrOrErrLocked returns either lasterr or the provided err.
// rs.closemu must be read-locked.
func (rs *Rows) lasterrOrErrLocked(err error) error {
if rs.lasterr != nil && rs.lasterr != io.EOF {
return rs.lasterr
}
return err
}
func (rs *Rows) initContextClose(ctx, txctx context.Context) {
if ctx.Done() == nil && (txctx == nil || txctx.Done() == nil) {
return
@ -2728,22 +2737,22 @@ func (rs *Rows) NextResultSet() bool {
func (rs *Rows) Err() error {
rs.closemu.RLock()
defer rs.closemu.RUnlock()
if rs.lasterr == io.EOF {
return nil
}
return rs.lasterr
return rs.lasterrOrErrLocked(nil)
}
var errRowsClosed = errors.New("sql: Rows are closed")
var errNoRows = errors.New("sql: no Rows available")
// Columns returns the column names.
// Columns returns an error if the rows are closed.
func (rs *Rows) Columns() ([]string, error) {
rs.closemu.RLock()
defer rs.closemu.RUnlock()
if rs.closed {
return nil, errors.New("sql: Rows are closed")
return nil, rs.lasterrOrErrLocked(errRowsClosed)
}
if rs.rowsi == nil {
return nil, errors.New("sql: no Rows available")
return nil, rs.lasterrOrErrLocked(errNoRows)
}
rs.dc.Lock()
defer rs.dc.Unlock()
@ -2757,10 +2766,10 @@ func (rs *Rows) ColumnTypes() ([]*ColumnType, error) {
rs.closemu.RLock()
defer rs.closemu.RUnlock()
if rs.closed {
return nil, errors.New("sql: Rows are closed")
return nil, rs.lasterrOrErrLocked(errRowsClosed)
}
if rs.rowsi == nil {
return nil, errors.New("sql: no Rows available")
return nil, rs.lasterrOrErrLocked(errNoRows)
}
rs.dc.Lock()
defer rs.dc.Unlock()
@ -2916,8 +2925,9 @@ func (rs *Rows) Scan(dest ...interface{}) error {
return rs.lasterr
}
if rs.closed {
err := rs.lasterrOrErrLocked(errRowsClosed)
rs.closemu.RUnlock()
return errors.New("sql: Rows are closed")
return err
}
rs.closemu.RUnlock()

View file

@ -292,3 +292,12 @@ func ExampleMarshalIndent() {
// <prefix><indent>"b": 2
// <prefix>}
}
func ExampleValid() {
goodJSON := `{"example": 1}`
badJSON := `{"example":2:]}}`
fmt.Println(json.Valid([]byte(goodJSON)), json.Valid([]byte(badJSON)))
// Output:
// true false
}

View file

@ -166,6 +166,7 @@ var pkgDeps = map[string][]string{
// Other time dependencies:
"internal/syscall/windows/registry",
"syscall",
"syscall/js",
},
"internal/poll": {"L0", "internal/race", "syscall", "time", "unicode/utf16", "unicode/utf8", "internal/syscall/windows"},
@ -395,7 +396,7 @@ var pkgDeps = map[string][]string{
// SSL/TLS.
"crypto/tls": {
"L4", "CRYPTO-MATH", "OS",
"L4", "CRYPTO-MATH", "OS", "golang_org/x/crypto/cryptobyte",
"container/list", "crypto/x509", "encoding/pem", "net", "syscall",
},
"crypto/x509": {

View file

@ -461,7 +461,11 @@ func (check *Checker) updateExprType(x ast.Expr, typ Type, final bool) {
check.invalidOp(x.Pos(), "shifted operand %s (type %s) must be integer", x, typ)
return
}
} else if old.val != nil {
// Even if we have an integer, if the value is a constant we
// still must check that it is representable as the specific
// int type requested (was issue #22969). Fall through here.
}
if old.val != nil {
// If x is a constant, it must be representable as a value of typ.
c := operand{old.mode, x, old.typ, old.val, 0}
check.convertUntyped(&c, typ)

View file

@ -46,8 +46,11 @@ func TestStdlib(t *testing.T) {
}
}
// firstComment returns the contents of the first comment in
// the given file, assuming there's one within the first KB.
// firstComment returns the contents of the first non-empty comment in
// the given file, "skip", or the empty string. No matter the present
// comments, if any of them contains a build tag, the result is always
// "skip". Only comments before the "package" token and within the first
// 4K of the file are considered.
func firstComment(filename string) string {
f, err := os.Open(filename)
if err != nil {
@ -55,11 +58,12 @@ func firstComment(filename string) string {
}
defer f.Close()
var src [1 << 10]byte // read at most 1KB
var src [4 << 10]byte // read at most 4KB
n, _ := f.Read(src[:])
var first string
var s scanner.Scanner
s.Init(fset.AddFile("", fset.Base(), n), src[:n], nil, scanner.ScanComments)
s.Init(fset.AddFile("", fset.Base(), n), src[:n], nil /* ignore errors */, scanner.ScanComments)
for {
_, tok, lit := s.Scan()
switch tok {
@ -68,9 +72,17 @@ func firstComment(filename string) string {
if lit[1] == '*' {
lit = lit[:len(lit)-2]
}
return strings.TrimSpace(lit[2:])
case token.EOF:
return ""
contents := strings.TrimSpace(lit[2:])
if strings.HasPrefix(contents, "+build ") {
return "skip"
}
if first == "" {
first = contents // contents may be "" but that's ok
}
// continue as we may still see build tags
case token.PACKAGE, token.EOF:
return first
}
}
}
@ -142,15 +154,8 @@ func TestStdTest(t *testing.T) {
t.Skip("skipping in short mode")
}
// test/recover4.go is only built for Linux and Darwin.
// TODO(gri) Remove once tests consider +build tags (issue 10370).
if runtime.GOOS != "linux" && runtime.GOOS != "darwin" {
return
}
testTestDir(t, filepath.Join(runtime.GOROOT(), "test"),
"cmplxdivide.go", // also needs file cmplxdivide1.go - ignore
"sigchld.go", // don't work on Windows; testTestDir should consult build tags
)
}
@ -166,7 +171,6 @@ func TestStdFixed(t *testing.T) {
"issue6889.go", // gc-specific test
"issue7746.go", // large constants - consumes too much memory
"issue11362.go", // canonical import path check
"issue15002.go", // uses Mmap; testTestDir should consult build tags
"issue16369.go", // go/types handles this correctly - not an issue
"issue18459.go", // go/types doesn't check validity of //go:xxx directives
"issue18882.go", // go/types doesn't check validity of //go:xxx directives

View file

@ -354,3 +354,15 @@ func issue21727() {
var _ = string(1 << s)
var _ = string(1.0 /* ERROR "cannot convert" */ << s)
}
func issue22969() {
var s uint
var a []byte
_ = a[0xffffffffffffffff /* ERROR "overflows int" */ <<s] // example from issue 22969
_ = make([]int, 0xffffffffffffffff /* ERROR "overflows int" */ << s)
_ = make([]int, 0, 0xffffffffffffffff /* ERROR "overflows int" */ << s)
var _ byte = 0x100 /* ERROR "overflows byte" */ << s
var _ int8 = 0xff /* ERROR "overflows int8" */ << s
var _ int16 = 0xffff /* ERROR "overflows int16" */ << s
var _ int32 = 0x80000000 /* ERROR "overflows int32" */ << s
}

View file

@ -62,15 +62,13 @@ func TestGolden(t *testing.T) {
io.WriteString(c, g.in)
s := c.Sum64()
if s != g.outISO {
t.Errorf("ISO crc64(%s) = 0x%x want 0x%x", g.in, s, g.outISO)
t.FailNow()
t.Fatalf("ISO crc64(%s) = 0x%x want 0x%x", g.in, s, g.outISO)
}
c = New(tabECMA)
io.WriteString(c, g.in)
s = c.Sum64()
if s != g.outECMA {
t.Errorf("ECMA crc64(%s) = 0x%x want 0x%x", g.in, s, g.outECMA)
t.FailNow()
t.Fatalf("ECMA crc64(%s) = 0x%x want 0x%x", g.in, s, g.outECMA)
}
}
}

View file

@ -1,26 +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 cpu_test
import (
. "internal/cpu"
"runtime"
"testing"
)
func TestARM64minimalFeatures(t *testing.T) {
switch runtime.GOOS {
case "linux", "android":
default:
t.Skipf("%s/arm64 is not supported", runtime.GOOS)
}
if !ARM64.HasASIMD {
t.Fatalf("HasASIMD expected true, got false")
}
if !ARM64.HasFP {
t.Fatalf("HasFP expected true, got false")
}
}

View file

@ -40,6 +40,7 @@ func doinit() {
{Name: "scv", Feature: &PPC64.HasSCV},
// These capabilities should always be enabled on ppc64 and ppc64le:
{Name: "power8", Feature: &PPC64.IsPOWER8, Required: true},
{Name: "vmx", Feature: &PPC64.HasVMX, Required: true},
{Name: "dfp", Feature: &PPC64.HasDFP, Required: true},
{Name: "vsx", Feature: &PPC64.HasVSX, Required: true},

View file

@ -1,33 +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.
// +build ppc64 ppc64le
package cpu_test
import (
. "internal/cpu"
"testing"
)
func TestPPC64minimalFeatures(t *testing.T) {
if !PPC64.IsPOWER8 {
t.Fatalf("IsPOWER8 expected true, got false")
}
if !PPC64.HasVMX {
t.Fatalf("HasVMX expected true, got false")
}
if !PPC64.HasDFP {
t.Fatalf("HasDFP expected true, got false")
}
if !PPC64.HasVSX {
t.Fatalf("HasVSX expected true, got false")
}
if !PPC64.HasISEL {
t.Fatalf("HasISEL expected true, got false")
}
if !PPC64.HasVCRYPTO {
t.Fatalf("HasVCRYPTO expected true, got false")
}
}

View file

@ -9,10 +9,27 @@ import (
"internal/testenv"
"os"
"os/exec"
"runtime"
"strings"
"testing"
)
func TestMinimalFeatures(t *testing.T) {
if runtime.GOARCH == "arm64" {
switch runtime.GOOS {
case "linux", "android":
default:
t.Skipf("%s/%s is not supported", runtime.GOOS, runtime.GOARCH)
}
}
for _, o := range Options {
if o.Required && !*o.Feature {
t.Errorf("%v expected true, got false", o.Name)
}
}
}
func MustHaveDebugOptionsSupport(t *testing.T) {
if !DebugOptions {
t.Skipf("skipping test: cpu feature options not supported by OS")

View file

@ -13,16 +13,6 @@ import (
"testing"
)
func TestAMD64minimalFeatures(t *testing.T) {
if runtime.GOARCH != "amd64" {
return
}
if !X86.HasSSE2 {
t.Fatalf("HasSSE2 expected true, got false")
}
}
func TestX86ifAVX2hasAVX(t *testing.T) {
if X86.HasAVX2 && !X86.HasAVX {
t.Fatalf("HasAVX expected true when HasAVX2 is true, got false")

View file

@ -28,9 +28,6 @@ const (
// GetRandom calls the FreeBSD getrandom system call.
func GetRandom(p []byte, flags GetRandomFlag) (n int, err error) {
if randomTrap == 0 {
return 0, syscall.ENOSYS
}
if len(p) == 0 {
return 0, nil
}

View file

@ -26,9 +26,6 @@ const (
// GetRandom calls the Linux getrandom system call.
// See https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=c6e9d6f38894798696f23c8084ca7edbf16ee895
func GetRandom(p []byte, flags GetRandomFlag) (n int, err error) {
if randomTrap == 0 {
return 0, syscall.ENOSYS
}
if len(p) == 0 {
return 0, nil
}

View file

@ -8,6 +8,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
"runtime"
"strings"
"testing"
)
@ -27,6 +28,9 @@ var (
)
func TestRemoteFiles(t *testing.T) {
if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
t.Skipf("files from outside the package are not available on %s/%s", runtime.GOOS, runtime.GOARCH)
}
files, err := ioutil.ReadDir(otherDir)
if err != nil {
t.Fatal(err)

View file

@ -254,6 +254,13 @@ func (l *Logger) SetPrefix(prefix string) {
l.prefix = prefix
}
// Writer returns the output destination for the logger.
func (l *Logger) Writer() io.Writer {
l.mu.Lock()
defer l.mu.Unlock()
return l.out
}
// SetOutput sets the output destination for the standard logger.
func SetOutput(w io.Writer) {
std.mu.Lock()

View file

@ -82,7 +82,7 @@ func nlz(x Word) uint {
return uint(bits.LeadingZeros(uint(x)))
}
// q = (u1<<_W + u0 - r)/y
// q = (u1<<_W + u0 - r)/v
// Adapted from Warren, Hacker's Delight, p. 152.
func divWW_g(u1, u0, v Word) (q, r Word) {
if u1 >= v {

View file

@ -899,6 +899,21 @@ func BenchmarkAdd64(b *testing.B) {
Output = int(z + c)
}
func BenchmarkAdd64multiple(b *testing.B) {
var z0 = uint64(Input)
var z1 = uint64(Input)
var z2 = uint64(Input)
var z3 = uint64(Input)
for i := 0; i < b.N; i++ {
var c uint64
z0, c = Add64(z0, uint64(i), c)
z1, c = Add64(z1, uint64(i), c)
z2, c = Add64(z2, uint64(i), c)
z3, _ = Add64(z3, uint64(i), c)
}
Output = int(z0 + z1 + z2 + z3)
}
func BenchmarkSub(b *testing.B) {
var z, c uint
for i := 0; i < b.N; i++ {
@ -918,11 +933,26 @@ func BenchmarkSub32(b *testing.B) {
func BenchmarkSub64(b *testing.B) {
var z, c uint64
for i := 0; i < b.N; i++ {
z, c = Add64(uint64(Input), uint64(i), c)
z, c = Sub64(uint64(Input), uint64(i), c)
}
Output = int(z + c)
}
func BenchmarkSub64multiple(b *testing.B) {
var z0 = uint64(Input)
var z1 = uint64(Input)
var z2 = uint64(Input)
var z3 = uint64(Input)
for i := 0; i < b.N; i++ {
var c uint64
z0, c = Sub64(z0, uint64(i), c)
z1, c = Sub64(z1, uint64(i), c)
z2, c = Sub64(z2, uint64(i), c)
z3, _ = Sub64(z3, uint64(i), c)
}
Output = int(z0 + z1 + z2 + z3)
}
func BenchmarkMul(b *testing.B) {
var hi, lo uint
for i := 0; i < b.N; i++ {

View file

@ -24,7 +24,7 @@ func cgoLookupPort(ctx context.Context, network, service string) (port int, err
return 0, nil, false
}
func cgoLookupIP(ctx context.Context, name string) (addrs []IPAddr, err error, completed bool) {
func cgoLookupIP(ctx context.Context, network, name string) (addrs []IPAddr, err error, completed bool) {
return nil, nil, false
}

View file

@ -49,7 +49,7 @@ type reverseLookupResult struct {
}
func cgoLookupHost(ctx context.Context, name string) (hosts []string, err error, completed bool) {
addrs, err, completed := cgoLookupIP(ctx, name)
addrs, err, completed := cgoLookupIP(ctx, "ip", name)
for _, addr := range addrs {
hosts = append(hosts, addr.String())
}
@ -69,13 +69,11 @@ func cgoLookupPort(ctx context.Context, network, service string) (port int, err
default:
return 0, &DNSError{Err: "unknown network", Name: network + "/" + service}, true
}
if len(network) >= 4 {
switch network[3] {
case '4':
hints.ai_family = C.AF_INET
case '6':
hints.ai_family = C.AF_INET6
}
switch ipVersion(network) {
case '4':
hints.ai_family = C.AF_INET
case '6':
hints.ai_family = C.AF_INET6
}
if ctx.Done() == nil {
port, err := cgoLookupServicePort(&hints, network, service)
@ -135,13 +133,20 @@ func cgoPortLookup(result chan<- portLookupResult, hints *C.struct_addrinfo, net
result <- portLookupResult{port, err}
}
func cgoLookupIPCNAME(name string) (addrs []IPAddr, cname string, err error) {
func cgoLookupIPCNAME(network, name string) (addrs []IPAddr, cname string, err error) {
acquireThread()
defer releaseThread()
var hints C.struct_addrinfo
hints.ai_flags = cgoAddrInfoFlags
hints.ai_socktype = C.SOCK_STREAM
hints.ai_family = C.AF_UNSPEC
switch ipVersion(network) {
case '4':
hints.ai_family = C.AF_INET
case '6':
hints.ai_family = C.AF_INET6
}
h := make([]byte, len(name)+1)
copy(h, name)
@ -197,18 +202,18 @@ func cgoLookupIPCNAME(name string) (addrs []IPAddr, cname string, err error) {
return addrs, cname, nil
}
func cgoIPLookup(result chan<- ipLookupResult, name string) {
addrs, cname, err := cgoLookupIPCNAME(name)
func cgoIPLookup(result chan<- ipLookupResult, network, name string) {
addrs, cname, err := cgoLookupIPCNAME(network, name)
result <- ipLookupResult{addrs, cname, err}
}
func cgoLookupIP(ctx context.Context, name string) (addrs []IPAddr, err error, completed bool) {
func cgoLookupIP(ctx context.Context, network, name string) (addrs []IPAddr, err error, completed bool) {
if ctx.Done() == nil {
addrs, _, err = cgoLookupIPCNAME(name)
addrs, _, err = cgoLookupIPCNAME(network, name)
return addrs, err, true
}
result := make(chan ipLookupResult, 1)
go cgoIPLookup(result, name)
go cgoIPLookup(result, network, name)
select {
case r := <-result:
return r.addrs, r.err, true
@ -219,11 +224,11 @@ func cgoLookupIP(ctx context.Context, name string) (addrs []IPAddr, err error, c
func cgoLookupCNAME(ctx context.Context, name string) (cname string, err error, completed bool) {
if ctx.Done() == nil {
_, cname, err = cgoLookupIPCNAME(name)
_, cname, err = cgoLookupIPCNAME("ip", name)
return cname, err, true
}
result := make(chan ipLookupResult, 1)
go cgoIPLookup(result, name)
go cgoIPLookup(result, "ip", name)
select {
case r := <-result:
return r.cname, r.err, true

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