Conflicts:
- src/go/internal/gcimporter/iimport.go
CL 325429 and CL 319931 made unrelated changes to adjacent lines
Merge List:
+ 2021-06-07
8212707871 crypto/elliptic: update P-521 docs to say it's constant-time
+ 2021-06-07
7406180012 fmt: split package documentation into more sections
+ 2021-06-07
e3176bbc3e crypto/tls: fix typo in Config.NextProtos docs
+ 2021-06-05
e1fa26026d spec: improve wording consistency by eliminating "specifier"
+ 2021-06-05
f490134126 spec: improve wording by choosing an official term "keyword"
+ 2021-06-05
e3cb381704 go/internal/gcimporter: don't waste CPU copying bytes in `io.ReadAll`
+ 2021-06-05
9d669ed47a misc/cgo/errors: use expected column numbers
+ 2021-06-04
95939e8de7 cmd/compile/internal/abi: fix typo in comment
+ 2021-06-04
831f9376d8 net/http: fix ResponseWriter.ReadFrom with short reads
+ 2021-06-04
3a9d906edc os: avoid finalizer race in windows process object
+ 2021-06-04
105c5b50e0 os: terminate windows processes via handle directly
+ 2021-06-04
79cd407f88 syscall: regenerate zsyscall_windows.go
+ 2021-06-04
c6b6211229 doc/go1.17: document testing changes for Go 1.17
+ 2021-06-04
0214440075 syscall: do not pass console handles to PROC_THREAD_ATTRIBUTE_HANDLE_LIST on Windows 7
+ 2021-06-04
962d5c997a cmd/compile,go/types: restrict use of unsafe.{Add,Slice} to go1.17 or newer
+ 2021-06-04
b29b123e07 cmd/compile: remove spurious ir.Dump
+ 2021-06-03
6d98301114 cmd/link: use correct alignment in PE DWARF sections
+ 2021-06-03
e0d029f758 runtime: avoid gp.lockedm race in exitsyscall0
+ 2021-06-02
dd7ba3ba2c net: don't rely on system hosts in TestCVE202133195
+ 2021-06-02
4f572d7076 io/fs: minor corrections to Sub docs
+ 2021-06-02
e11d14225c doc/go1.17: remove runtime section
+ 2021-06-02
6e189afd3e doc/go1.17: mention SYS_WAIT6/WEXITED on NetBSD
+ 2021-06-02
ff9f5fb859 cmd/link: recognize clang linker error in testCGOLTO
+ 2021-06-02
1c6a2ea2ea doc/go1.17: document time changes for Go1.17
+ 2021-06-02
d743e67e06 doc/go1.17: document flag changes for Go 1.17
+ 2021-06-02
dc8f87b749 runtime/internal/sys: generate //go:build lines in gengoos.go
+ 2021-06-02
84c0e5d47f cmd/link: move issue 43830 tests out of TestScript
+ 2021-06-02
cae68700cc runtime: fix formatting
+ 2021-06-01
567ee865f6 cmd/go: add declaration to cgo_lto_issue43830 test
+ 2021-06-01
24e9707cbf cmd/link, cmd/cgo: support -flto in CFLAGS
Change-Id: I9ef88e7de0f8b1841ed9604b613b41672df67e71
package noder
import (
+ "errors"
"fmt"
"go/constant"
"go/token"
for i, param := range params {
p.setlineno(param)
nodes = append(nodes, p.param(param, dddOk, i+1 == len(params)))
+ if i > 0 && params[i].Type == params[i-1].Type {
+ nodes[i].Ntype = nodes[i-1].Ntype
+ }
}
return nodes
}
if n == nil {
return nil
}
- if _, ok := n.(ir.Ntype); !ok {
- ir.Dump("NOT NTYPE", n)
- }
return n.(ir.Ntype)
}
} else {
n = ir.NewField(p.pos(field), p.name(field.Name), p.typeExpr(field.Type), nil)
}
+ if i > 0 && expr.FieldList[i].Type == expr.FieldList[i-1].Type {
+ n.Ntype = l[i-1].Ntype
+ }
if i < len(expr.TagList) && expr.TagList[i] != nil {
n.Note = constant.StringVal(p.basicLit(expr.TagList[i]))
}
}
func (p *noder) embedded(typ syntax.Expr) *ir.Field {
+ pos := p.pos(syntax.StartPos(typ))
+
op, isStar := typ.(*syntax.Operation)
if isStar {
if op.Op != syntax.Mul || op.Y != nil {
}
sym := p.packname(typ)
- n := ir.NewField(p.pos(typ), typecheck.Lookup(sym.Name), importName(sym).(ir.Ntype), nil)
+ n := ir.NewField(pos, typecheck.Lookup(sym.Name), importName(sym).(ir.Ntype), nil)
n.Embedded = true
if isStar {
- n.Ntype = ir.NewStarExpr(p.pos(op), n.Ntype)
+ n.Ntype = ir.NewStarExpr(pos, n.Ntype)
}
return n
}
}
func varEmbed(makeXPos func(syntax.Pos) src.XPos, name *ir.Name, decl *syntax.VarDecl, pragma *pragmas, haveEmbed bool) {
- if pragma.Embeds == nil {
- return
- }
-
pragmaEmbeds := pragma.Embeds
pragma.Embeds = nil
- pos := makeXPos(pragmaEmbeds[0].Pos)
-
- if !haveEmbed {
- base.ErrorfAt(pos, "go:embed only allowed in Go files that import \"embed\"")
- return
- }
- if len(decl.NameList) > 1 {
- base.ErrorfAt(pos, "go:embed cannot apply to multiple vars")
- return
- }
- if decl.Values != nil {
- base.ErrorfAt(pos, "go:embed cannot apply to var with initializer")
+ if len(pragmaEmbeds) == 0 {
return
}
- if decl.Type == nil {
- // Should not happen, since Values == nil now.
- base.ErrorfAt(pos, "go:embed cannot apply to var without type")
- return
- }
- if typecheck.DeclContext != ir.PEXTERN {
- base.ErrorfAt(pos, "go:embed cannot apply to var inside func")
+
+ if err := checkEmbed(decl, haveEmbed, typecheck.DeclContext != ir.PEXTERN); err != nil {
+ base.ErrorfAt(makeXPos(pragmaEmbeds[0].Pos), "%s", err)
return
}
typecheck.Target.Embeds = append(typecheck.Target.Embeds, name)
name.Embed = &embeds
}
+
+func checkEmbed(decl *syntax.VarDecl, haveEmbed, withinFunc bool) error {
+ switch {
+ case !haveEmbed:
+ return errors.New("go:embed only allowed in Go files that import \"embed\"")
+ case len(decl.NameList) > 1:
+ return errors.New("go:embed cannot apply to multiple vars")
+ case decl.Values != nil:
+ return errors.New("go:embed cannot apply to var with initializer")
+ case decl.Type == nil:
+ // Should not happen, since Values == nil now.
+ return errors.New("go:embed cannot apply to var without type")
+ case withinFunc:
+ return errors.New("go:embed cannot apply to var inside func")
+
+ default:
+ return nil
+ }
+}
"cmd/compile/internal/base"
"cmd/compile/internal/ir"
"cmd/compile/internal/types"
+ "cmd/internal/src"
"fmt"
"go/constant"
)
// package all the arguments that match a ... T parameter into a []T.
-func MakeDotArgs(typ *types.Type, args []ir.Node) ir.Node {
+func MakeDotArgs(pos src.XPos, typ *types.Type, args []ir.Node) ir.Node {
var n ir.Node
if len(args) == 0 {
- n = NodNil()
+ n = ir.NewNilExpr(pos)
n.SetType(typ)
} else {
- lit := ir.NewCompLitExpr(base.Pos, ir.OCOMPLIT, ir.TypeNode(typ), nil)
- lit.List.Append(args...)
+ args = append([]ir.Node(nil), args...)
+ lit := ir.NewCompLitExpr(pos, ir.OCOMPLIT, ir.TypeNode(typ), args)
lit.SetImplicit(true)
n = lit
}
n = Expr(n)
if n.Type() == nil {
- base.Fatalf("mkdotargslice: typecheck failed")
+ base.FatalfAt(pos, "mkdotargslice: typecheck failed")
}
return n
}
args := call.Args
extra := args[vi:]
- slice := MakeDotArgs(vt, extra)
+ slice := MakeDotArgs(call.Pos(), vt, extra)
for i := range extra {
extra[i] = nil // allow GC
}
// The information appears in the binary in the form of type descriptors;
// the struct is unnamed so that closures in multiple packages with the
// same struct type can share the descriptor.
+
+ // Make sure the .F field is in the same package as the rest of the
+ // fields. This deals with closures in instantiated functions, which are
+ // compiled as if from the source package of the generic function.
+ var pkg *types.Pkg
+ if len(clo.Func.ClosureVars) == 0 {
+ pkg = types.LocalPkg
+ } else {
+ for _, v := range clo.Func.ClosureVars {
+ if pkg == nil {
+ pkg = v.Sym().Pkg
+ } else if pkg != v.Sym().Pkg {
+ base.Fatalf("Closure variables from multiple packages")
+ }
+ }
+ }
+
fields := []*types.Field{
- types.NewField(base.Pos, Lookup(".F"), types.Types[types.TUINTPTR]),
+ types.NewField(base.Pos, pkg.Lookup(".F"), types.Types[types.TUINTPTR]),
}
for _, v := range clo.Func.ClosureVars {
typ := v.Type()
// tcUnsafeAdd typechecks an OUNSAFEADD node.
func tcUnsafeAdd(n *ir.BinaryExpr) *ir.BinaryExpr {
+ if !types.AllowsGoVersion(curpkg(), 1, 17) {
+ base.ErrorfVers("go1.17", "unsafe.Add")
+ n.SetType(nil)
+ return n
+ }
+
n.X = AssignConv(Expr(n.X), types.Types[types.TUNSAFEPTR], "argument to unsafe.Add")
n.Y = DefaultLit(Expr(n.Y), types.Types[types.TINT])
if n.X.Type() == nil || n.Y.Type() == nil {
// tcUnsafeSlice typechecks an OUNSAFESLICE node.
func tcUnsafeSlice(n *ir.BinaryExpr) *ir.BinaryExpr {
+ if !types.AllowsGoVersion(curpkg(), 1, 17) {
+ base.ErrorfVers("go1.17", "unsafe.Slice")
+ n.SetType(nil)
+ return n
+ }
+
n.X = Expr(n.X)
n.Y = Expr(n.Y)
if n.X.Type() == nil || n.Y.Type() == nil {
mode = value
}
- case *Sum:
- if t.is(func(t Type) bool {
- switch t := under(t).(type) {
+ case *Union:
+ if t.underIs(func(t Type) bool {
+ switch t := t.(type) {
case *Basic:
if isString(t) && id == _Len {
return true
m = 2
case *Map, *Chan:
m = 1
- case *Sum:
- return t.is(valid)
+ case *Union:
+ return t.underIs(valid)
default:
return false
}
case _Add:
// unsafe.Add(ptr unsafe.Pointer, len IntegerType) unsafe.Pointer
+ if !check.allowVersion(check.pkg, 1, 17) {
+ check.error(call.Fun, "unsafe.Add requires go1.17 or later")
+ return
+ }
+
check.assignment(x, Typ[UnsafePointer], "argument to unsafe.Add")
if x.mode == invalid {
return
case _Slice:
// unsafe.Slice(ptr *T, len IntegerType) []T
+ if !check.allowVersion(check.pkg, 1, 17) {
+ check.error(call.Fun, "unsafe.Slice requires go1.17 or later")
+ return
+ }
+
typ := asPointer(x.typ)
if typ == nil {
check.errorf(x, invalidArg+"%s is not a pointer", x)
// Test if t satisfies the requirements for the argument
// type and collect possible result types at the same time.
var rtypes []Type
- if !tp.Bound().is(func(x Type) bool {
- if r := f(x); r != nil {
+ var tildes []bool
+ if !tp.Bound().is(func(typ Type, tilde bool) bool {
+ if r := f(typ); r != nil {
rtypes = append(rtypes, r)
+ tildes = append(tildes, tilde)
return true
}
return false
// uses of real() where the result is used to
// define type and initialize a variable?
- // construct a suitable new type parameter
- tpar := NewTypeName(nopos, nil /* = Universe pkg */, "<type parameter>", nil)
+ // Construct a suitable new type parameter for the sum type. The
+ // type param is placed in the current package so export/import
+ // works as expected.
+ tpar := NewTypeName(nopos, check.pkg, "<type parameter>", nil)
ptyp := check.NewTypeParam(tpar, 0, &emptyInterface) // assigns type to tpar as a side-effect
- tsum := NewSum(rtypes)
- ptyp.bound = &Interface{types: tsum, allMethods: markComplete, allTypes: tsum}
+ tsum := newUnion(rtypes, tildes)
+ ptyp.bound = &Interface{allMethods: markComplete, allTypes: tsum}
return ptyp
}
package gcimporter
import (
+ "bufio"
"bytes"
"encoding/binary"
"fmt"
)
type intReader struct {
- *bytes.Reader
+ *bufio.Reader
path string
}
return i
}
+// Keep this in sync with constants in iexport.go.
+const (
+ iexportVersionGo1_11 = 0
+ iexportVersionPosCol = 1
+ iexportVersionGenerics = 2
+
+ // Start of the unstable series of versions, remove "+ n" before release.
+ iexportVersionCurrent = iexportVersionGenerics + 1
+)
+
const predeclReserved = 32
type itag uint64
signatureType
structType
interfaceType
+ typeParamType
+ instType
)
// iImportData imports a package from the serialized package data
// and returns the number of bytes consumed and a reference to the package.
// If the export data version is not recognized or the format is otherwise
// compromised, an error is returned.
- func iImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) {
+ func iImportData(fset *token.FileSet, imports map[string]*types.Package, dataReader *bufio.Reader, path string) (pkg *types.Package, err error) {
- const currentVersion = 1
+ const currentVersion = iexportVersionCurrent
version := int64(-1)
defer func() {
if e := recover(); e != nil {
}
}()
- r := &intReader{bytes.NewReader(data), path}
+ r := &intReader{dataReader, path}
version = int64(r.uint64())
switch version {
- case currentVersion, 0:
+ case currentVersion, iexportVersionPosCol, iexportVersionGo1_11:
default:
- errorf("unknown iexport format version %d", version)
+ if version > iexportVersionGenerics {
+ errorf("unstable iexport format version %d, just rebuild compiler and std library", version)
+ } else {
+ errorf("unknown iexport format version %d", version)
+ }
}
sLen := int64(r.uint64())
dLen := int64(r.uint64())
- whence, _ := r.Seek(0, io.SeekCurrent)
- stringData := data[whence : whence+sLen]
- declData := data[whence+sLen : whence+sLen+dLen]
- r.Seek(sLen+dLen, io.SeekCurrent)
+ data := make([]byte, sLen+dLen)
+ if _, err := io.ReadFull(r, data); err != nil {
+ errorf("cannot read %d bytes of stringData and declData: %s", len(data), err)
+ }
+ stringData := data[:sLen]
+ declData := data[sLen:]
p := iimporter{
- ipath: path,
- version: int(version),
+ exportVersion: version,
+ ipath: path,
+ version: int(version),
stringData: stringData,
stringCache: make(map[uint64]string),
// package was imported completely and without errors
localpkg.MarkComplete()
-
- consumed, _ := r.Seek(0, io.SeekCurrent)
- return int(consumed), localpkg, nil
+ return localpkg, nil
}
type iimporter struct {
- ipath string
- version int
+ exportVersion int64
+ ipath string
+ version int
stringData []byte
stringCache map[uint64]string
r.declare(types.NewConst(pos, r.currPkg, name, typ, val))
case 'F':
+ if r.p.exportVersion >= iexportVersionGenerics {
+ numTparams := r.uint64()
+ if numTparams > 0 {
+ errorf("unexpected tparam")
+ }
+ }
sig := r.signature(nil)
r.declare(types.NewFunc(pos, r.currPkg, name, sig))
case 'T':
+ if r.p.exportVersion >= iexportVersionGenerics {
+ numTparams := r.uint64()
+ if numTparams > 0 {
+ errorf("unexpected tparam")
+ }
+ }
+
// Types can be recursive. We need to setup a stub
// declaration before recursing.
obj := types.NewTypeName(pos, r.currPkg, name, nil)
typ := types.NewInterfaceType(methods, embeddeds)
r.p.interfaceList = append(r.p.interfaceList, typ)
return typ
+
+ case typeParamType:
+ errorf("do not handle type param types yet")
+ return nil
+
+ case instType:
+ errorf("do not handle instantiated types yet")
+ return nil
}
}
releasem(mp)
}
-// funcPC returns the entry PC of the function f.
-// It assumes that f is a func value. Otherwise the behavior is undefined.
-// CAREFUL: In programs with plugins, funcPC can return different values
-// for the same function (because there are actually multiple copies of
-// the same function in the address space). To be safe, don't use the
-// results of this function in any == expression. It is only safe to
-// use the result as an address at which to start executing code.
-//go:nosplit
-func funcPC(f interface{}) uintptr {
- return *(*uintptr)(efaceOf(&f).data)
-}
-
// called from assembly
func badmcall(fn func(*g)) {
throw("runtime: mcall called on m->g0 stack")
gp.lockedm.set(mp)
gp.goid = int64(atomic.Xadd64(&sched.goidgen, 1))
if raceenabled {
- gp.racectx = racegostart(funcPC(newextram) + sys.PCQuantum)
+ gp.racectx = racegostart(abi.FuncPCABIInternal(newextram) + sys.PCQuantum)
}
// put on allg for garbage collector
allgadd(gp)
}
ts.g.set(mp.g0)
ts.tls = (*uint64)(unsafe.Pointer(&mp.tls[0]))
- ts.fn = unsafe.Pointer(funcPC(mstart))
+ ts.fn = unsafe.Pointer(abi.FuncPCABI0(mstart))
if msanenabled {
msanwrite(unsafe.Pointer(&ts), unsafe.Sizeof(ts))
}
if schedEnabled(gp) {
_p_ = pidleget()
}
+ var locked bool
if _p_ == nil {
globrunqput(gp)
+
+ // Below, we stoplockedm if gp is locked. globrunqput releases
+ // ownership of gp, so we must check if gp is locked prior to
+ // committing the release by unlocking sched.lock, otherwise we
+ // could race with another M transitioning gp from unlocked to
+ // locked.
+ locked = gp.lockedm != 0
} else if atomic.Load(&sched.sysmonwait) != 0 {
atomic.Store(&sched.sysmonwait, 0)
notewakeup(&sched.sysmonnote)
acquirep(_p_)
execute(gp, false) // Never returns.
}
- if gp.lockedm != 0 {
+ if locked {
// Wait until another thread schedules gp and so m again.
//
// N.B. lockedm must be this M, as this g was running on this M
// If all of the above has failed, account it against abstract "System" or "GC".
n = 2
if inVDSOPage(pc) {
- pc = funcPC(_VDSO) + sys.PCQuantum
+ pc = abi.FuncPCABIInternal(_VDSO) + sys.PCQuantum
} else if pc > firstmoduledata.etext {
// "ExternalCode" is better than "etext".
- pc = funcPC(_ExternalCode) + sys.PCQuantum
+ pc = abi.FuncPCABIInternal(_ExternalCode) + sys.PCQuantum
}
stk[0] = pc
if mp.preemptoff != "" {
- stk[1] = funcPC(_GC) + sys.PCQuantum
+ stk[1] = abi.FuncPCABIInternal(_GC) + sys.PCQuantum
} else {
- stk[1] = funcPC(_System) + sys.PCQuantum
+ stk[1] = abi.FuncPCABIInternal(_System) + sys.PCQuantum
}
}
}
if prof.hz != 0 {
stk := []uintptr{
pc,
- funcPC(_ExternalCode) + sys.PCQuantum,
+ abi.FuncPCABIInternal(_ExternalCode) + sys.PCQuantum,
}
cpuprof.addNonGo(stk)
}
// Load stats non-atomically since tracinit is updated only by this init goroutine.
after := inittrace
- pkg := funcpkgpath(findfunc(funcPC(firstFunc)))
+ f := *(*func())(unsafe.Pointer(&firstFunc))
+ pkg := funcpkgpath(findfunc(abi.FuncPCABIInternal(f)))
var sbuf [24]byte
print("init ", pkg, " @")