mirror of
https://github.com/golang/go
synced 2024-11-23 00:50:05 -07:00
[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:
parent
85ce6ecfe3
commit
4836e28ac0
@ -24,8 +24,6 @@ const (
|
||||
embedFiles
|
||||
)
|
||||
|
||||
var numLocalEmbed int
|
||||
|
||||
func varEmbed(p *noder, names []ir.Node, typ ir.Ntype, exprs []ir.Node, embeds []PragmaEmbed) (newExprs []ir.Node) {
|
||||
haveEmbed := false
|
||||
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")
|
||||
return exprs
|
||||
}
|
||||
|
||||
kind := embedKindApprox(typ)
|
||||
if kind == embedUnknown {
|
||||
p.errorAt(pos, "go:embed cannot apply to var of type %v", typ)
|
||||
if dclcontext != ir.PEXTERN {
|
||||
p.errorAt(pos, "go:embed cannot apply to var inside func")
|
||||
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.
|
||||
have := make(map[string]bool)
|
||||
var list []string
|
||||
for _, e := range embeds {
|
||||
for _, e := range *v.Embed {
|
||||
for _, pattern := range e.Patterns {
|
||||
files, ok := base.Flag.Cfg.Embed.Patterns[pattern]
|
||||
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 {
|
||||
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
|
||||
}
|
||||
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 len(list) > 1 {
|
||||
p.errorAt(pos, "invalid go:embed: multiple files for type %v", typ)
|
||||
return exprs
|
||||
base.ErrorfAt(v.Pos(), "invalid go:embed: multiple files for type %v", v.Type())
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
v := names[0].(*ir.Name)
|
||||
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
|
||||
return list
|
||||
}
|
||||
|
||||
// embedKindApprox determines the kind of embedding variable, approximately.
|
||||
@ -192,8 +191,8 @@ func dumpembeds() {
|
||||
|
||||
// initEmbed emits the init data for a //go:embed variable,
|
||||
// which is either a string, a []byte, or an embed.FS.
|
||||
func initEmbed(v ir.Node) {
|
||||
files := v.Name().EmbedFiles()
|
||||
func initEmbed(v *ir.Name) {
|
||||
files := embedFileList(v)
|
||||
switch kind := embedKind(v.Type()); kind {
|
||||
case embedUnknown:
|
||||
base.ErrorfAt(v.Pos(), "go:embed cannot apply to var of type %v", v.Type())
|
||||
|
@ -116,13 +116,14 @@ var (
|
||||
okforadd [types.NTYPE]bool
|
||||
okforand [types.NTYPE]bool
|
||||
okfornone [types.NTYPE]bool
|
||||
okforcmp [types.NTYPE]bool
|
||||
okforbool [types.NTYPE]bool
|
||||
okforcap [types.NTYPE]bool
|
||||
okforlen [types.NTYPE]bool
|
||||
okforarith [types.NTYPE]bool
|
||||
)
|
||||
|
||||
var okforcmp [types.NTYPE]bool
|
||||
|
||||
var (
|
||||
okfor [ir.OEND][]bool
|
||||
iscmp [ir.OEND]bool
|
||||
@ -149,9 +150,6 @@ var typecheckok bool
|
||||
// when the race detector is enabled.
|
||||
var instrumenting bool
|
||||
|
||||
// Whether we are tracking lexical scopes for DWARF.
|
||||
var trackScopes bool
|
||||
|
||||
var nodfp *ir.Name
|
||||
|
||||
var autogeneratedPos src.XPos
|
||||
|
@ -205,8 +205,6 @@ func Main(archInit func(*Arch)) {
|
||||
}
|
||||
}
|
||||
|
||||
trackScopes = base.Flag.Dwarf
|
||||
|
||||
Widthptr = thearch.LinkArch.PtrSize
|
||||
Widthreg = thearch.LinkArch.RegSize
|
||||
|
||||
@ -226,6 +224,7 @@ func Main(archInit func(*Arch)) {
|
||||
|
||||
timings.Start("fe", "parse")
|
||||
lines := parseFiles(flag.Args())
|
||||
cgoSymABIs()
|
||||
timings.Stop()
|
||||
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.
|
||||
func numNonClosures(list []*ir.Func) int {
|
||||
count := 0
|
||||
|
@ -20,7 +20,6 @@ import (
|
||||
"cmd/compile/internal/ir"
|
||||
"cmd/compile/internal/syntax"
|
||||
"cmd/compile/internal/types"
|
||||
"cmd/internal/obj"
|
||||
"cmd/internal/objabi"
|
||||
"cmd/internal/src"
|
||||
)
|
||||
@ -36,8 +35,9 @@ func parseFiles(filenames []string) uint {
|
||||
|
||||
for _, filename := range filenames {
|
||||
p := &noder{
|
||||
basemap: make(map[*syntax.PosBase]*src.PosBase),
|
||||
err: make(chan syntax.Error),
|
||||
basemap: make(map[*syntax.PosBase]*src.PosBase),
|
||||
err: make(chan syntax.Error),
|
||||
trackScopes: base.Flag.Dwarf,
|
||||
}
|
||||
noders = append(noders, p)
|
||||
|
||||
@ -151,7 +151,8 @@ type noder struct {
|
||||
|
||||
// scopeVars is a stack tracking the number of variables declared in the
|
||||
// current function at the moment each open scope was opened.
|
||||
scopeVars []int
|
||||
trackScopes bool
|
||||
scopeVars []int
|
||||
|
||||
lastCloseScopePos syntax.Pos
|
||||
}
|
||||
@ -179,7 +180,7 @@ func (p *noder) funcBody(fn *ir.Func, block *syntax.BlockStmt) {
|
||||
func (p *noder) openScope(pos syntax.Pos) {
|
||||
types.Markdcl()
|
||||
|
||||
if trackScopes {
|
||||
if p.trackScopes {
|
||||
Curfn.Parents = append(Curfn.Parents, p.scope)
|
||||
p.scopeVars = append(p.scopeVars, len(Curfn.Dcl))
|
||||
p.scope = ir.ScopeID(len(Curfn.Parents))
|
||||
@ -192,7 +193,7 @@ func (p *noder) closeScope(pos syntax.Pos) {
|
||||
p.lastCloseScopePos = pos
|
||||
types.Popdcl()
|
||||
|
||||
if trackScopes {
|
||||
if p.trackScopes {
|
||||
scopeVars := p.scopeVars[len(p.scopeVars)-1]
|
||||
p.scopeVars = p.scopeVars[:len(p.scopeVars)-1]
|
||||
if scopeVars == len(Curfn.Dcl) {
|
||||
@ -284,19 +285,6 @@ func (p *noder) processPragmas() {
|
||||
}
|
||||
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...)
|
||||
}
|
||||
|
||||
|
@ -34,16 +34,16 @@ func (*Ident) CanBeNtype() {}
|
||||
// Name holds Node fields used only by named nodes (ONAME, OTYPE, some OLITERAL).
|
||||
type Name struct {
|
||||
miniExpr
|
||||
BuiltinOp Op // uint8
|
||||
Class_ Class // uint8
|
||||
flags bitset16
|
||||
pragma PragmaFlag // int16
|
||||
sym *types.Sym
|
||||
fn *Func
|
||||
Offset_ int64
|
||||
val constant.Value
|
||||
orig Node
|
||||
embedFiles *[]string // list of embedded files, for ONAME var
|
||||
BuiltinOp Op // uint8
|
||||
Class_ Class // uint8
|
||||
flags bitset16
|
||||
pragma PragmaFlag // int16
|
||||
sym *types.Sym
|
||||
fn *Func
|
||||
Offset_ int64
|
||||
val constant.Value
|
||||
orig Node
|
||||
Embed *[]Embed // list of embedded files, for ONAME var
|
||||
|
||||
PkgName *PkgName // real package for import . names
|
||||
// For a local variable (not param) or extern, the initializing assignment (OAS or OAS2).
|
||||
@ -139,14 +139,14 @@ type Name struct {
|
||||
Outer *Name
|
||||
}
|
||||
|
||||
func (n *Name) isExpr() {}
|
||||
|
||||
// CloneName makes a cloned copy of the name.
|
||||
// It's not ir.Copy(n) because in general that operation is a mistake on names,
|
||||
// which uniquely identify variables.
|
||||
// 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) isExpr() {}
|
||||
|
||||
// NewNameAt returns a new ONAME Node associated with symbol s at position pos.
|
||||
// The caller is responsible for setting Curfn.
|
||||
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.
|
||||
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 (
|
||||
nameCaptured = 1 << iota // is the variable captured by a closure
|
||||
nameReadonly
|
||||
@ -389,6 +368,11 @@ const (
|
||||
_ = 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.
|
||||
type PkgName struct {
|
||||
miniNode
|
||||
|
@ -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")
|
||||
}
|
||||
|
||||
func TestLocal(t *testing.T) {
|
||||
//go:embed testdata/k*.txt
|
||||
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
|
||||
var dir embed.FS
|
||||
|
||||
//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")
|
||||
}
|
||||
//go:embed testdata/*
|
||||
var star embed.FS
|
||||
|
||||
func TestDir(t *testing.T) {
|
||||
//go:embed testdata
|
||||
var all embed.FS
|
||||
|
||||
all := dir
|
||||
testFiles(t, all, "testdata/hello.txt", "hello, world\n")
|
||||
testFiles(t, all, "testdata/i/i18n.txt", "internationalization\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) {
|
||||
//go:embed testdata
|
||||
var dir embed.FS
|
||||
|
||||
//go:embed testdata/*
|
||||
var star embed.FS
|
||||
|
||||
t.Logf("//go:embed testdata")
|
||||
|
||||
testDir(t, dir, "testdata",
|
||||
|
@ -90,17 +90,3 @@ func TestXGlobal(t *testing.T) {
|
||||
}
|
||||
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")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user