mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.boringcrypto] all: merge master into dev.boringcrypto
Change-Id: Ice4172e2058a45b1a24da561fd420244ab2a97bd
This commit is contained in:
commit
af07f7734b
150 changed files with 4372 additions and 1832 deletions
|
|
@ -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_")
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
3
src/cmd/asm/internal/asm/testdata/s390x.s
vendored
3
src/cmd/asm/internal/asm/testdata/s390x.s
vendored
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
62
src/cmd/go/internal/cache/default.go
vendored
62
src/cmd/go/internal/cache/default.go
vendored
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
28
src/cmd/go/testdata/script/mod_replace.txt
vendored
28
src/cmd/go/testdata/script/mod_replace.txt
vendored
|
|
@ -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
|
||||
|
||||
|
|
|
|||
71
src/cmd/go/testdata/script/mod_tidy_replace.txt
vendored
Normal file
71
src/cmd/go/testdata/script/mod_tidy_replace.txt
vendored
Normal 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"
|
||||
)
|
||||
48
src/cmd/go/testdata/script/mod_vendor.txt
vendored
48
src/cmd/go/testdata/script/mod_vendor.txt
vendored
|
|
@ -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
|
||||
|
|
|
|||
39
src/cmd/go/testdata/script/mod_vendor_replace.txt
vendored
Normal file
39
src/cmd/go/testdata/script/mod_vendor_replace.txt
vendored
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -945,6 +945,9 @@ const (
|
|||
AVUPLHW
|
||||
AVUPLF
|
||||
AVMSLG
|
||||
AVMSLEG
|
||||
AVMSLOG
|
||||
AVMSLEOG
|
||||
|
||||
// binary
|
||||
ABYTE
|
||||
|
|
|
|||
|
|
@ -678,6 +678,9 @@ var Anames = []string{
|
|||
"VUPLHW",
|
||||
"VUPLF",
|
||||
"VMSLG",
|
||||
"VMSLEG",
|
||||
"VMSLOG",
|
||||
"VMSLEOG",
|
||||
"BYTE",
|
||||
"WORD",
|
||||
"DWORD",
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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.")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
/*
|
||||
|
|
|
|||
1232
src/cmd/link/internal/ld/xcoff.go
Normal file
1232
src/cmd/link/internal/ld/xcoff.go
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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},
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -418,7 +418,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
|
|||
byte(certTypeECDSASign),
|
||||
}
|
||||
if c.vers >= VersionTLS12 {
|
||||
certReq.hasSignatureAndHash = true
|
||||
certReq.hasSignatureAlgorithm = true
|
||||
certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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": {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
12
src/go/types/testdata/shifts.src
vendored
12
src/go/types/testdata/shifts.src
vendored
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
|
@ -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},
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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++ {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue