[dev.regabi] cmd/compile: separate noder more cleanly

Separate embed, cgo pragmas, and Main trackScopes variable
from noder more cleanly.

This lets us split embed and noder into new packages.
It also assumes that the local embedded variables will be
removed and deletes them now for simplicity.

Change-Id: I9638bcc2c5f0e76440de056c6285b6aa2f73a00d
Reviewed-on: https://go-review.googlesource.com/c/go/+/279299
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
Russ Cox 2020-12-21 01:36:15 -05:00
parent 85ce6ecfe3
commit 4836e28ac0
7 changed files with 72 additions and 120 deletions

View file

@ -24,8 +24,6 @@ const (
embedFiles embedFiles
) )
var numLocalEmbed int
func varEmbed(p *noder, names []ir.Node, typ ir.Ntype, exprs []ir.Node, embeds []PragmaEmbed) (newExprs []ir.Node) { func varEmbed(p *noder, names []ir.Node, typ ir.Ntype, exprs []ir.Node, embeds []PragmaEmbed) (newExprs []ir.Node) {
haveEmbed := false haveEmbed := false
for _, decl := range p.file.DeclList { for _, decl := range p.file.DeclList {
@ -63,25 +61,39 @@ func varEmbed(p *noder, names []ir.Node, typ ir.Ntype, exprs []ir.Node, embeds [
p.errorAt(pos, "go:embed cannot apply to var without type") p.errorAt(pos, "go:embed cannot apply to var without type")
return exprs return exprs
} }
if dclcontext != ir.PEXTERN {
kind := embedKindApprox(typ) p.errorAt(pos, "go:embed cannot apply to var inside func")
if kind == embedUnknown {
p.errorAt(pos, "go:embed cannot apply to var of type %v", typ)
return exprs return exprs
} }
v := names[0].(*ir.Name)
Target.Embeds = append(Target.Embeds, v)
v.Embed = new([]ir.Embed)
for _, e := range embeds {
*v.Embed = append(*v.Embed, ir.Embed{Pos: p.makeXPos(e.Pos), Patterns: e.Patterns})
}
return exprs
}
func embedFileList(v *ir.Name) []string {
kind := embedKind(v.Type())
if kind == embedUnknown {
base.ErrorfAt(v.Pos(), "go:embed cannot apply to var of type %v", v.Type())
return nil
}
// Build list of files to store. // Build list of files to store.
have := make(map[string]bool) have := make(map[string]bool)
var list []string var list []string
for _, e := range embeds { for _, e := range *v.Embed {
for _, pattern := range e.Patterns { for _, pattern := range e.Patterns {
files, ok := base.Flag.Cfg.Embed.Patterns[pattern] files, ok := base.Flag.Cfg.Embed.Patterns[pattern]
if !ok { if !ok {
p.errorAt(e.Pos, "invalid go:embed: build system did not map pattern: %s", pattern) base.ErrorfAt(e.Pos, "invalid go:embed: build system did not map pattern: %s", pattern)
} }
for _, file := range files { for _, file := range files {
if base.Flag.Cfg.Embed.Files[file] == "" { if base.Flag.Cfg.Embed.Files[file] == "" {
p.errorAt(e.Pos, "invalid go:embed: build system did not map file: %s", file) base.ErrorfAt(e.Pos, "invalid go:embed: build system did not map file: %s", file)
continue continue
} }
if !have[file] { if !have[file] {
@ -103,25 +115,12 @@ func varEmbed(p *noder, names []ir.Node, typ ir.Ntype, exprs []ir.Node, embeds [
if kind == embedString || kind == embedBytes { if kind == embedString || kind == embedBytes {
if len(list) > 1 { if len(list) > 1 {
p.errorAt(pos, "invalid go:embed: multiple files for type %v", typ) base.ErrorfAt(v.Pos(), "invalid go:embed: multiple files for type %v", v.Type())
return exprs return nil
} }
} }
v := names[0].(*ir.Name) return list
if dclcontext != ir.PEXTERN {
numLocalEmbed++
v = ir.NewNameAt(v.Pos(), lookupN("embed.", numLocalEmbed))
v.Sym().Def = v
v.Name().Ntype = typ
v.SetClass(ir.PEXTERN)
Target.Externs = append(Target.Externs, v)
exprs = []ir.Node{v}
}
v.Name().SetEmbedFiles(list)
Target.Embeds = append(Target.Embeds, v)
return exprs
} }
// embedKindApprox determines the kind of embedding variable, approximately. // embedKindApprox determines the kind of embedding variable, approximately.
@ -192,8 +191,8 @@ func dumpembeds() {
// initEmbed emits the init data for a //go:embed variable, // initEmbed emits the init data for a //go:embed variable,
// which is either a string, a []byte, or an embed.FS. // which is either a string, a []byte, or an embed.FS.
func initEmbed(v ir.Node) { func initEmbed(v *ir.Name) {
files := v.Name().EmbedFiles() files := embedFileList(v)
switch kind := embedKind(v.Type()); kind { switch kind := embedKind(v.Type()); kind {
case embedUnknown: case embedUnknown:
base.ErrorfAt(v.Pos(), "go:embed cannot apply to var of type %v", v.Type()) base.ErrorfAt(v.Pos(), "go:embed cannot apply to var of type %v", v.Type())

View file

@ -116,13 +116,14 @@ var (
okforadd [types.NTYPE]bool okforadd [types.NTYPE]bool
okforand [types.NTYPE]bool okforand [types.NTYPE]bool
okfornone [types.NTYPE]bool okfornone [types.NTYPE]bool
okforcmp [types.NTYPE]bool
okforbool [types.NTYPE]bool okforbool [types.NTYPE]bool
okforcap [types.NTYPE]bool okforcap [types.NTYPE]bool
okforlen [types.NTYPE]bool okforlen [types.NTYPE]bool
okforarith [types.NTYPE]bool okforarith [types.NTYPE]bool
) )
var okforcmp [types.NTYPE]bool
var ( var (
okfor [ir.OEND][]bool okfor [ir.OEND][]bool
iscmp [ir.OEND]bool iscmp [ir.OEND]bool
@ -149,9 +150,6 @@ var typecheckok bool
// when the race detector is enabled. // when the race detector is enabled.
var instrumenting bool var instrumenting bool
// Whether we are tracking lexical scopes for DWARF.
var trackScopes bool
var nodfp *ir.Name var nodfp *ir.Name
var autogeneratedPos src.XPos var autogeneratedPos src.XPos

View file

@ -205,8 +205,6 @@ func Main(archInit func(*Arch)) {
} }
} }
trackScopes = base.Flag.Dwarf
Widthptr = thearch.LinkArch.PtrSize Widthptr = thearch.LinkArch.PtrSize
Widthreg = thearch.LinkArch.RegSize Widthreg = thearch.LinkArch.RegSize
@ -226,6 +224,7 @@ func Main(archInit func(*Arch)) {
timings.Start("fe", "parse") timings.Start("fe", "parse")
lines := parseFiles(flag.Args()) lines := parseFiles(flag.Args())
cgoSymABIs()
timings.Stop() timings.Stop()
timings.AddEvent(int64(lines), "lines") timings.AddEvent(int64(lines), "lines")
@ -477,6 +476,20 @@ func Main(archInit func(*Arch)) {
} }
} }
func cgoSymABIs() {
// The linker expects an ABI0 wrapper for all cgo-exported
// functions.
for _, prag := range Target.CgoPragmas {
switch prag[0] {
case "cgo_export_static", "cgo_export_dynamic":
if symabiRefs == nil {
symabiRefs = make(map[string]obj.ABI)
}
symabiRefs[prag[1]] = obj.ABI0
}
}
}
// numNonClosures returns the number of functions in list which are not closures. // numNonClosures returns the number of functions in list which are not closures.
func numNonClosures(list []*ir.Func) int { func numNonClosures(list []*ir.Func) int {
count := 0 count := 0

View file

@ -20,7 +20,6 @@ import (
"cmd/compile/internal/ir" "cmd/compile/internal/ir"
"cmd/compile/internal/syntax" "cmd/compile/internal/syntax"
"cmd/compile/internal/types" "cmd/compile/internal/types"
"cmd/internal/obj"
"cmd/internal/objabi" "cmd/internal/objabi"
"cmd/internal/src" "cmd/internal/src"
) )
@ -36,8 +35,9 @@ func parseFiles(filenames []string) uint {
for _, filename := range filenames { for _, filename := range filenames {
p := &noder{ p := &noder{
basemap: make(map[*syntax.PosBase]*src.PosBase), basemap: make(map[*syntax.PosBase]*src.PosBase),
err: make(chan syntax.Error), err: make(chan syntax.Error),
trackScopes: base.Flag.Dwarf,
} }
noders = append(noders, p) noders = append(noders, p)
@ -151,7 +151,8 @@ type noder struct {
// scopeVars is a stack tracking the number of variables declared in the // scopeVars is a stack tracking the number of variables declared in the
// current function at the moment each open scope was opened. // current function at the moment each open scope was opened.
scopeVars []int trackScopes bool
scopeVars []int
lastCloseScopePos syntax.Pos lastCloseScopePos syntax.Pos
} }
@ -179,7 +180,7 @@ func (p *noder) funcBody(fn *ir.Func, block *syntax.BlockStmt) {
func (p *noder) openScope(pos syntax.Pos) { func (p *noder) openScope(pos syntax.Pos) {
types.Markdcl() types.Markdcl()
if trackScopes { if p.trackScopes {
Curfn.Parents = append(Curfn.Parents, p.scope) Curfn.Parents = append(Curfn.Parents, p.scope)
p.scopeVars = append(p.scopeVars, len(Curfn.Dcl)) p.scopeVars = append(p.scopeVars, len(Curfn.Dcl))
p.scope = ir.ScopeID(len(Curfn.Parents)) p.scope = ir.ScopeID(len(Curfn.Parents))
@ -192,7 +193,7 @@ func (p *noder) closeScope(pos syntax.Pos) {
p.lastCloseScopePos = pos p.lastCloseScopePos = pos
types.Popdcl() types.Popdcl()
if trackScopes { if p.trackScopes {
scopeVars := p.scopeVars[len(p.scopeVars)-1] scopeVars := p.scopeVars[len(p.scopeVars)-1]
p.scopeVars = p.scopeVars[:len(p.scopeVars)-1] p.scopeVars = p.scopeVars[:len(p.scopeVars)-1]
if scopeVars == len(Curfn.Dcl) { if scopeVars == len(Curfn.Dcl) {
@ -284,19 +285,6 @@ func (p *noder) processPragmas() {
} }
n.Sym().Linkname = l.remote n.Sym().Linkname = l.remote
} }
// The linker expects an ABI0 wrapper for all cgo-exported
// functions.
for _, prag := range p.pragcgobuf {
switch prag[0] {
case "cgo_export_static", "cgo_export_dynamic":
if symabiRefs == nil {
symabiRefs = make(map[string]obj.ABI)
}
symabiRefs[prag[1]] = obj.ABI0
}
}
Target.CgoPragmas = append(Target.CgoPragmas, p.pragcgobuf...) Target.CgoPragmas = append(Target.CgoPragmas, p.pragcgobuf...)
} }

View file

@ -34,16 +34,16 @@ func (*Ident) CanBeNtype() {}
// Name holds Node fields used only by named nodes (ONAME, OTYPE, some OLITERAL). // Name holds Node fields used only by named nodes (ONAME, OTYPE, some OLITERAL).
type Name struct { type Name struct {
miniExpr miniExpr
BuiltinOp Op // uint8 BuiltinOp Op // uint8
Class_ Class // uint8 Class_ Class // uint8
flags bitset16 flags bitset16
pragma PragmaFlag // int16 pragma PragmaFlag // int16
sym *types.Sym sym *types.Sym
fn *Func fn *Func
Offset_ int64 Offset_ int64
val constant.Value val constant.Value
orig Node orig Node
embedFiles *[]string // list of embedded files, for ONAME var Embed *[]Embed // list of embedded files, for ONAME var
PkgName *PkgName // real package for import . names PkgName *PkgName // real package for import . names
// For a local variable (not param) or extern, the initializing assignment (OAS or OAS2). // For a local variable (not param) or extern, the initializing assignment (OAS or OAS2).
@ -139,14 +139,14 @@ type Name struct {
Outer *Name Outer *Name
} }
func (n *Name) isExpr() {}
// CloneName makes a cloned copy of the name. // CloneName makes a cloned copy of the name.
// It's not ir.Copy(n) because in general that operation is a mistake on names, // It's not ir.Copy(n) because in general that operation is a mistake on names,
// which uniquely identify variables. // which uniquely identify variables.
// Callers must use n.CloneName to make clear they intend to create a separate name. // Callers must use n.CloneName to make clear they intend to create a separate name.
func (n *Name) CloneName() *Name { c := *n; return &c } func (n *Name) CloneName() *Name { c := *n; return &c }
func (n *Name) isExpr() {}
// NewNameAt returns a new ONAME Node associated with symbol s at position pos. // NewNameAt returns a new ONAME Node associated with symbol s at position pos.
// The caller is responsible for setting Curfn. // The caller is responsible for setting Curfn.
func NewNameAt(pos src.XPos, sym *types.Sym) *Name { func NewNameAt(pos src.XPos, sym *types.Sym) *Name {
@ -231,27 +231,6 @@ func (n *Name) Alias() bool { return n.flags&nameAlias != 0 }
// SetAlias sets whether p, which must be for an OTYPE, is a type alias. // SetAlias sets whether p, which must be for an OTYPE, is a type alias.
func (n *Name) SetAlias(alias bool) { n.flags.set(nameAlias, alias) } func (n *Name) SetAlias(alias bool) { n.flags.set(nameAlias, alias) }
// EmbedFiles returns the list of embedded files for p,
// which must be for an ONAME var.
func (n *Name) EmbedFiles() []string {
if n.embedFiles == nil {
return nil
}
return *n.embedFiles
}
// SetEmbedFiles sets the list of embedded files for p,
// which must be for an ONAME var.
func (n *Name) SetEmbedFiles(list []string) {
if n.embedFiles == nil && list == nil {
return
}
if n.embedFiles == nil {
n.embedFiles = new([]string)
}
*n.embedFiles = list
}
const ( const (
nameCaptured = 1 << iota // is the variable captured by a closure nameCaptured = 1 << iota // is the variable captured by a closure
nameReadonly nameReadonly
@ -389,6 +368,11 @@ const (
_ = uint((1 << 3) - iota) // static assert for iota <= (1 << 3) _ = uint((1 << 3) - iota) // static assert for iota <= (1 << 3)
) )
type Embed struct {
Pos src.XPos
Patterns []string
}
// A Pack is an identifier referring to an imported package. // A Pack is an identifier referring to an imported package.
type PkgName struct { type PkgName struct {
miniNode miniNode

View file

@ -73,24 +73,14 @@ func TestGlobal(t *testing.T) {
testString(t, string(glass), "glass", "I can eat glass and it doesn't hurt me.\n") testString(t, string(glass), "glass", "I can eat glass and it doesn't hurt me.\n")
} }
func TestLocal(t *testing.T) { //go:embed testdata
//go:embed testdata/k*.txt var dir embed.FS
var local embed.FS
testFiles(t, local, "testdata/ken.txt", "If a program is too slow, it must have a loop.\n")
//go:embed testdata/k*.txt //go:embed testdata/*
var s string var star embed.FS
testString(t, s, "local variable s", "If a program is too slow, it must have a loop.\n")
//go:embed testdata/h*.txt
var b []byte
testString(t, string(b), "local variable b", "hello, world\n")
}
func TestDir(t *testing.T) { func TestDir(t *testing.T) {
//go:embed testdata all := dir
var all embed.FS
testFiles(t, all, "testdata/hello.txt", "hello, world\n") testFiles(t, all, "testdata/hello.txt", "hello, world\n")
testFiles(t, all, "testdata/i/i18n.txt", "internationalization\n") testFiles(t, all, "testdata/i/i18n.txt", "internationalization\n")
testFiles(t, all, "testdata/i/j/k/k8s.txt", "kubernetes\n") testFiles(t, all, "testdata/i/j/k/k8s.txt", "kubernetes\n")
@ -103,12 +93,6 @@ func TestDir(t *testing.T) {
} }
func TestHidden(t *testing.T) { func TestHidden(t *testing.T) {
//go:embed testdata
var dir embed.FS
//go:embed testdata/*
var star embed.FS
t.Logf("//go:embed testdata") t.Logf("//go:embed testdata")
testDir(t, dir, "testdata", testDir(t, dir, "testdata",

View file

@ -90,17 +90,3 @@ func TestXGlobal(t *testing.T) {
} }
bbig[0] = old bbig[0] = old
} }
func TestXLocal(t *testing.T) {
//go:embed testdata/*o.txt
var local embed.FS
testFiles(t, local, "testdata/hello.txt", "hello, world\n")
//go:embed testdata/k*.txt
var s string
testString(t, s, "local variable s", "If a program is too slow, it must have a loop.\n")
//go:embed testdata/h*.txt
var b []byte
testString(t, string(b), "local variable b", "hello, world\n")
}