mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.regabi] cmd/compile: clean up flag handling [generated]
The flag values have grown fairly haphazard, with no organization
or even common naming convention. This CL moves all flag values
into the Flag struct (formerly misnamed Debug), except for a few
that live in Ctxt fields instead.
This CL is entirely automated changes.
A followup CL will make a few manual cleanups, leaving this CL
completely automated and easier to regenerate during merge
conflicts.
Cleaning up flags is necessary because the printing routines
look at some of them, and the printing routines need to move
out of package gc to a new package shared by gc and any
other packages that split out of gc.
[git-generate]
cd src/cmd/compile/internal/gc
rf '
mv Debug Flag
mv DebugFlags Flags
mv Flags.e Flags.LowerE
mv Flags.h Flags.LowerH
mv Flags.j Flags.LowerJ
mv Flags.l Flags.LowerL
mv Flags.m Flags.LowerM
mv Flags.r Flags.LowerR
mv Flags.w Flags.LowerW
mv Flags.P Flags.Percent
mv compiling_runtime Flag.CompilingRuntime
mv compiling_std Flag.Std
mv localimport Flag.D
mv asmhdr Flag.AsmHdr
mv buildid Flag.BuildID
mv nBackendWorkers Flag.LowerC
mv pure_go Flag.Complete
mv debugstr Flag.LowerD
mv flagDWARF Flag.Dwarf
mv genDwarfInline Flag.GenDwarfInl
mv flag_installsuffix Flag.InstallSuffix
mv flag_lang Flag.Lang
mv linkobj Flag.LinkObj
mv debuglive Flag.Live
mv flag_msan Flag.MSan
mv nolocalimports Flag.NoLocalImports
mv outfile Flag.LowerO
mv myimportpath Ctxt.Pkgpath
mv writearchive Flag.Pack
mv flag_race Flag.Race
mv spectre Flag.Spectre
mv trace Flag.LowerT
mv pathPrefix Flag.TrimPath
mv Debug_vlog Ctxt.Debugvlog
mv use_writebarrier Flag.WB
mv Main.flag_shared Flag.Shared
mv Main.flag_dynlink Flag.Dynlink
mv Main.goversion Flag.GoVersion
mv Main.symabisPath Flag.SymABIs
mv cpuprofile Flag.CPUProfile
mv memprofile Flag.MemProfile
mv traceprofile Flag.TraceProfile
mv blockprofile Flag.BlockProfile
mv mutexprofile Flag.MutexProfile
mv benchfile Flag.Bench
mv Main.smallFrames Flag.SmallFrames
mv Main.jsonLogOpt Flag.JSON
add Flag:$ \
Cfg struct{}
mv embedCfg Flag.Cfg.Embed
mv idirs Flag.Cfg.ImportDirs
mv importMap Flag.Cfg.ImportMap
mv packageFile Flag.Cfg.PackageFile
mv spectreIndex Flag.Cfg.SpectreIndex
mv addidir addImportDir
mv main.go:/Wasm/-0,/ssaDump/-3 ParseFlags
mv usage Flag Flags ParseFlags \
concurrentFlagOk concurrentBackendAllowed \
addImportDir addImportMap \
readImportCfg readEmbedCfg \
flag.go
# Remove //go:generate line copied from main.go
# along with two self-assignments from the merge.
rm flag.go:/go:generate/-+ \
flag.go:/Ctxt.Pkgpath = Ctxt.Pkgpath/-+ \
flag.go:/Ctxt.Debugvlog = Ctxt.Debugvlog/-+
'
Change-Id: I10431c15fe7d9f48024d53141d4224d957dbf334
Reviewed-on: https://go-review.googlesource.com/c/go/+/271667
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
6e583d65ab
commit
18573aea3c
31 changed files with 752 additions and 757 deletions
|
|
@ -282,7 +282,7 @@ func genhash(t *types.Type) *obj.LSym {
|
||||||
}
|
}
|
||||||
|
|
||||||
sym := typesymprefix(".hash", t)
|
sym := typesymprefix(".hash", t)
|
||||||
if Debug.r != 0 {
|
if Flag.LowerR != 0 {
|
||||||
fmt.Printf("genhash %v %v %v\n", closure, sym, t)
|
fmt.Printf("genhash %v %v %v\n", closure, sym, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -374,7 +374,7 @@ func genhash(t *types.Type) *obj.LSym {
|
||||||
r.List.Append(nh)
|
r.List.Append(nh)
|
||||||
fn.Nbody.Append(r)
|
fn.Nbody.Append(r)
|
||||||
|
|
||||||
if Debug.r != 0 {
|
if Flag.LowerR != 0 {
|
||||||
dumplist("genhash body", fn.Nbody)
|
dumplist("genhash body", fn.Nbody)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -509,7 +509,7 @@ func geneq(t *types.Type) *obj.LSym {
|
||||||
return closure
|
return closure
|
||||||
}
|
}
|
||||||
sym := typesymprefix(".eq", t)
|
sym := typesymprefix(".eq", t)
|
||||||
if Debug.r != 0 {
|
if Flag.LowerR != 0 {
|
||||||
fmt.Printf("geneq %v\n", t)
|
fmt.Printf("geneq %v\n", t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -753,7 +753,7 @@ func geneq(t *types.Type) *obj.LSym {
|
||||||
// We should really do a generic CL that shares epilogues across
|
// We should really do a generic CL that shares epilogues across
|
||||||
// the board. See #24936.
|
// the board. See #24936.
|
||||||
|
|
||||||
if Debug.r != 0 {
|
if Flag.LowerR != 0 {
|
||||||
dumplist("geneq body", fn.Nbody)
|
dumplist("geneq body", fn.Nbody)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -203,7 +203,7 @@ func capturevars(dcl *Node) {
|
||||||
outer = nod(OADDR, outer, nil)
|
outer = nod(OADDR, outer, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
if Debug.m > 1 {
|
if Flag.LowerM > 1 {
|
||||||
var name *types.Sym
|
var name *types.Sym
|
||||||
if v.Name.Curfn != nil && v.Name.Curfn.Func.Nname != nil {
|
if v.Name.Curfn != nil && v.Name.Curfn.Func.Nname != nil {
|
||||||
name = v.Name.Curfn.Func.Nname.Sym
|
name = v.Name.Curfn.Func.Nname.Sym
|
||||||
|
|
@ -344,7 +344,7 @@ func closuredebugruntimecheck(clo *Node) {
|
||||||
Warnl(clo.Pos, "stack closure, captured vars = %v", clo.Func.ClosureVars)
|
Warnl(clo.Pos, "stack closure, captured vars = %v", clo.Func.ClosureVars)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if compiling_runtime && clo.Esc == EscHeap {
|
if Flag.CompilingRuntime && clo.Esc == EscHeap {
|
||||||
yyerrorl(clo.Pos, "heap-allocated closure, not allowed in runtime")
|
yyerrorl(clo.Pos, "heap-allocated closure, not allowed in runtime")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -946,7 +946,7 @@ func makefuncsym(s *types.Sym) {
|
||||||
if s.IsBlank() {
|
if s.IsBlank() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if compiling_runtime && (s.Name == "getg" || s.Name == "getclosureptr" || s.Name == "getcallerpc" || s.Name == "getcallersp") {
|
if Flag.CompilingRuntime && (s.Name == "getg" || s.Name == "getclosureptr" || s.Name == "getcallerpc" || s.Name == "getcallersp") {
|
||||||
// runtime.getg(), getclosureptr(), getcallerpc(), and
|
// runtime.getg(), getclosureptr(), getcallerpc(), and
|
||||||
// getcallersp() are not real functions and so do not
|
// getcallersp() are not real functions and so do not
|
||||||
// get funcsyms.
|
// get funcsyms.
|
||||||
|
|
|
||||||
|
|
@ -213,7 +213,7 @@ func genAbstractFunc(fn *obj.LSym) {
|
||||||
if Debug_gendwarfinl != 0 {
|
if Debug_gendwarfinl != 0 {
|
||||||
Ctxt.Logf("DwarfAbstractFunc(%v)\n", fn.Name)
|
Ctxt.Logf("DwarfAbstractFunc(%v)\n", fn.Name)
|
||||||
}
|
}
|
||||||
Ctxt.DwarfAbstractFunc(ifn, fn, myimportpath)
|
Ctxt.DwarfAbstractFunc(ifn, fn, Ctxt.Pkgpath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Undo any versioning performed when a name was written
|
// Undo any versioning performed when a name was written
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,7 @@ import (
|
||||||
"cmd/compile/internal/syntax"
|
"cmd/compile/internal/syntax"
|
||||||
"cmd/compile/internal/types"
|
"cmd/compile/internal/types"
|
||||||
"cmd/internal/obj"
|
"cmd/internal/obj"
|
||||||
"encoding/json"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"path"
|
"path"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
@ -19,27 +17,6 @@ import (
|
||||||
|
|
||||||
var embedlist []*Node
|
var embedlist []*Node
|
||||||
|
|
||||||
var embedCfg struct {
|
|
||||||
Patterns map[string][]string
|
|
||||||
Files map[string]string
|
|
||||||
}
|
|
||||||
|
|
||||||
func readEmbedCfg(file string) {
|
|
||||||
data, err := ioutil.ReadFile(file)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("-embedcfg: %v", err)
|
|
||||||
}
|
|
||||||
if err := json.Unmarshal(data, &embedCfg); err != nil {
|
|
||||||
log.Fatalf("%s: %v", file, err)
|
|
||||||
}
|
|
||||||
if embedCfg.Patterns == nil {
|
|
||||||
log.Fatalf("%s: invalid embedcfg: missing Patterns", file)
|
|
||||||
}
|
|
||||||
if embedCfg.Files == nil {
|
|
||||||
log.Fatalf("%s: invalid embedcfg: missing Files", file)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
embedUnknown = iota
|
embedUnknown = iota
|
||||||
embedBytes
|
embedBytes
|
||||||
|
|
@ -69,7 +46,7 @@ func varEmbed(p *noder, names []*Node, typ *Node, exprs []*Node, embeds []Pragma
|
||||||
p.yyerrorpos(pos, "invalid go:embed: missing import \"embed\"")
|
p.yyerrorpos(pos, "invalid go:embed: missing import \"embed\"")
|
||||||
return exprs
|
return exprs
|
||||||
}
|
}
|
||||||
if embedCfg.Patterns == nil {
|
if Flag.Cfg.Embed.Patterns == nil {
|
||||||
p.yyerrorpos(pos, "invalid go:embed: build system did not supply embed configuration")
|
p.yyerrorpos(pos, "invalid go:embed: build system did not supply embed configuration")
|
||||||
return exprs
|
return exprs
|
||||||
}
|
}
|
||||||
|
|
@ -98,12 +75,12 @@ func varEmbed(p *noder, names []*Node, typ *Node, exprs []*Node, embeds []Pragma
|
||||||
var list []string
|
var list []string
|
||||||
for _, e := range embeds {
|
for _, e := range embeds {
|
||||||
for _, pattern := range e.Patterns {
|
for _, pattern := range e.Patterns {
|
||||||
files, ok := embedCfg.Patterns[pattern]
|
files, ok := Flag.Cfg.Embed.Patterns[pattern]
|
||||||
if !ok {
|
if !ok {
|
||||||
p.yyerrorpos(e.Pos, "invalid go:embed: build system did not map pattern: %s", pattern)
|
p.yyerrorpos(e.Pos, "invalid go:embed: build system did not map pattern: %s", pattern)
|
||||||
}
|
}
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
if embedCfg.Files[file] == "" {
|
if Flag.Cfg.Embed.Files[file] == "" {
|
||||||
p.yyerrorpos(e.Pos, "invalid go:embed: build system did not map file: %s", file)
|
p.yyerrorpos(e.Pos, "invalid go:embed: build system did not map file: %s", file)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
@ -152,7 +129,7 @@ func varEmbed(p *noder, names []*Node, typ *Node, exprs []*Node, embeds []Pragma
|
||||||
// can't tell whether "string" and "byte" really mean "string" and "byte".
|
// can't tell whether "string" and "byte" really mean "string" and "byte".
|
||||||
// The result must be confirmed later, after type checking, using embedKind.
|
// The result must be confirmed later, after type checking, using embedKind.
|
||||||
func embedKindApprox(typ *Node) int {
|
func embedKindApprox(typ *Node) int {
|
||||||
if typ.Sym != nil && typ.Sym.Name == "FS" && (typ.Sym.Pkg.Path == "embed" || (typ.Sym.Pkg == localpkg && myimportpath == "embed")) {
|
if typ.Sym != nil && typ.Sym.Name == "FS" && (typ.Sym.Pkg.Path == "embed" || (typ.Sym.Pkg == localpkg && Ctxt.Pkgpath == "embed")) {
|
||||||
return embedFiles
|
return embedFiles
|
||||||
}
|
}
|
||||||
// These are not guaranteed to match only string and []byte -
|
// These are not guaranteed to match only string and []byte -
|
||||||
|
|
@ -170,7 +147,7 @@ func embedKindApprox(typ *Node) int {
|
||||||
|
|
||||||
// embedKind determines the kind of embedding variable.
|
// embedKind determines the kind of embedding variable.
|
||||||
func embedKind(typ *types.Type) int {
|
func embedKind(typ *types.Type) int {
|
||||||
if typ.Sym != nil && typ.Sym.Name == "FS" && (typ.Sym.Pkg.Path == "embed" || (typ.Sym.Pkg == localpkg && myimportpath == "embed")) {
|
if typ.Sym != nil && typ.Sym.Name == "FS" && (typ.Sym.Pkg.Path == "embed" || (typ.Sym.Pkg == localpkg && Ctxt.Pkgpath == "embed")) {
|
||||||
return embedFiles
|
return embedFiles
|
||||||
}
|
}
|
||||||
if typ == types.Types[TSTRING] {
|
if typ == types.Types[TSTRING] {
|
||||||
|
|
@ -221,7 +198,7 @@ func initEmbed(v *Node) {
|
||||||
|
|
||||||
case embedString, embedBytes:
|
case embedString, embedBytes:
|
||||||
file := files[0]
|
file := files[0]
|
||||||
fsym, size, err := fileStringSym(v.Pos, embedCfg.Files[file], kind == embedString, nil)
|
fsym, size, err := fileStringSym(v.Pos, Flag.Cfg.Embed.Files[file], kind == embedString, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
yyerrorl(v.Pos, "embed %s: %v", file, err)
|
yyerrorl(v.Pos, "embed %s: %v", file, err)
|
||||||
}
|
}
|
||||||
|
|
@ -257,7 +234,7 @@ func initEmbed(v *Node) {
|
||||||
off = duintptr(slicedata, off, 0)
|
off = duintptr(slicedata, off, 0)
|
||||||
off += hashSize
|
off += hashSize
|
||||||
} else {
|
} else {
|
||||||
fsym, size, err := fileStringSym(v.Pos, embedCfg.Files[file], true, hash)
|
fsym, size, err := fileStringSym(v.Pos, Flag.Cfg.Embed.Files[file], true, hash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
yyerrorl(v.Pos, "embed %s: %v", file, err)
|
yyerrorl(v.Pos, "embed %s: %v", file, err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -283,10 +283,10 @@ func addrescapes(n *Node) {
|
||||||
|
|
||||||
// moveToHeap records the parameter or local variable n as moved to the heap.
|
// moveToHeap records the parameter or local variable n as moved to the heap.
|
||||||
func moveToHeap(n *Node) {
|
func moveToHeap(n *Node) {
|
||||||
if Debug.r != 0 {
|
if Flag.LowerR != 0 {
|
||||||
Dump("MOVE", n)
|
Dump("MOVE", n)
|
||||||
}
|
}
|
||||||
if compiling_runtime {
|
if Flag.CompilingRuntime {
|
||||||
yyerror("%v escapes to heap, not allowed in runtime", n)
|
yyerror("%v escapes to heap, not allowed in runtime", n)
|
||||||
}
|
}
|
||||||
if n.Class() == PAUTOHEAP {
|
if n.Class() == PAUTOHEAP {
|
||||||
|
|
@ -360,7 +360,7 @@ func moveToHeap(n *Node) {
|
||||||
n.Xoffset = 0
|
n.Xoffset = 0
|
||||||
n.Name.Param.Heapaddr = heapaddr
|
n.Name.Param.Heapaddr = heapaddr
|
||||||
n.Esc = EscHeap
|
n.Esc = EscHeap
|
||||||
if Debug.m != 0 {
|
if Flag.LowerM != 0 {
|
||||||
Warnl(n.Pos, "moved to heap: %v", n)
|
Warnl(n.Pos, "moved to heap: %v", n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -390,7 +390,7 @@ func (e *Escape) paramTag(fn *Node, narg int, f *types.Field) string {
|
||||||
// but we are reusing the ability to annotate an individual function
|
// but we are reusing the ability to annotate an individual function
|
||||||
// argument and pass those annotations along to importing code.
|
// argument and pass those annotations along to importing code.
|
||||||
if f.Type.IsUintptr() {
|
if f.Type.IsUintptr() {
|
||||||
if Debug.m != 0 {
|
if Flag.LowerM != 0 {
|
||||||
Warnl(f.Pos, "assuming %v is unsafe uintptr", name())
|
Warnl(f.Pos, "assuming %v is unsafe uintptr", name())
|
||||||
}
|
}
|
||||||
return unsafeUintptrTag
|
return unsafeUintptrTag
|
||||||
|
|
@ -405,11 +405,11 @@ func (e *Escape) paramTag(fn *Node, narg int, f *types.Field) string {
|
||||||
// External functions are assumed unsafe, unless
|
// External functions are assumed unsafe, unless
|
||||||
// //go:noescape is given before the declaration.
|
// //go:noescape is given before the declaration.
|
||||||
if fn.Func.Pragma&Noescape != 0 {
|
if fn.Func.Pragma&Noescape != 0 {
|
||||||
if Debug.m != 0 && f.Sym != nil {
|
if Flag.LowerM != 0 && f.Sym != nil {
|
||||||
Warnl(f.Pos, "%v does not escape", name())
|
Warnl(f.Pos, "%v does not escape", name())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if Debug.m != 0 && f.Sym != nil {
|
if Flag.LowerM != 0 && f.Sym != nil {
|
||||||
Warnl(f.Pos, "leaking param: %v", name())
|
Warnl(f.Pos, "leaking param: %v", name())
|
||||||
}
|
}
|
||||||
esc.AddHeap(0)
|
esc.AddHeap(0)
|
||||||
|
|
@ -420,14 +420,14 @@ func (e *Escape) paramTag(fn *Node, narg int, f *types.Field) string {
|
||||||
|
|
||||||
if fn.Func.Pragma&UintptrEscapes != 0 {
|
if fn.Func.Pragma&UintptrEscapes != 0 {
|
||||||
if f.Type.IsUintptr() {
|
if f.Type.IsUintptr() {
|
||||||
if Debug.m != 0 {
|
if Flag.LowerM != 0 {
|
||||||
Warnl(f.Pos, "marking %v as escaping uintptr", name())
|
Warnl(f.Pos, "marking %v as escaping uintptr", name())
|
||||||
}
|
}
|
||||||
return uintptrEscapesTag
|
return uintptrEscapesTag
|
||||||
}
|
}
|
||||||
if f.IsDDD() && f.Type.Elem().IsUintptr() {
|
if f.IsDDD() && f.Type.Elem().IsUintptr() {
|
||||||
// final argument is ...uintptr.
|
// final argument is ...uintptr.
|
||||||
if Debug.m != 0 {
|
if Flag.LowerM != 0 {
|
||||||
Warnl(f.Pos, "marking %v as escaping ...uintptr", name())
|
Warnl(f.Pos, "marking %v as escaping ...uintptr", name())
|
||||||
}
|
}
|
||||||
return uintptrEscapesTag
|
return uintptrEscapesTag
|
||||||
|
|
@ -449,7 +449,7 @@ func (e *Escape) paramTag(fn *Node, narg int, f *types.Field) string {
|
||||||
esc := loc.paramEsc
|
esc := loc.paramEsc
|
||||||
esc.Optimize()
|
esc.Optimize()
|
||||||
|
|
||||||
if Debug.m != 0 && !loc.escapes {
|
if Flag.LowerM != 0 && !loc.escapes {
|
||||||
if esc.Empty() {
|
if esc.Empty() {
|
||||||
Warnl(f.Pos, "%v does not escape", name())
|
Warnl(f.Pos, "%v does not escape", name())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -205,7 +205,7 @@ func (e *Escape) initFunc(fn *Node) {
|
||||||
Fatalf("unexpected node: %v", fn)
|
Fatalf("unexpected node: %v", fn)
|
||||||
}
|
}
|
||||||
fn.Esc = EscFuncPlanned
|
fn.Esc = EscFuncPlanned
|
||||||
if Debug.m > 3 {
|
if Flag.LowerM > 3 {
|
||||||
Dump("escAnalyze", fn)
|
Dump("escAnalyze", fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -282,7 +282,7 @@ func (e *Escape) stmt(n *Node) {
|
||||||
lineno = lno
|
lineno = lno
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if Debug.m > 2 {
|
if Flag.LowerM > 2 {
|
||||||
fmt.Printf("%v:[%d] %v stmt: %v\n", linestr(lineno), e.loopDepth, funcSym(e.curfn), n)
|
fmt.Printf("%v:[%d] %v stmt: %v\n", linestr(lineno), e.loopDepth, funcSym(e.curfn), n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -310,11 +310,11 @@ func (e *Escape) stmt(n *Node) {
|
||||||
case OLABEL:
|
case OLABEL:
|
||||||
switch asNode(n.Sym.Label) {
|
switch asNode(n.Sym.Label) {
|
||||||
case nonlooping:
|
case nonlooping:
|
||||||
if Debug.m > 2 {
|
if Flag.LowerM > 2 {
|
||||||
fmt.Printf("%v:%v non-looping label\n", linestr(lineno), n)
|
fmt.Printf("%v:%v non-looping label\n", linestr(lineno), n)
|
||||||
}
|
}
|
||||||
case looping:
|
case looping:
|
||||||
if Debug.m > 2 {
|
if Flag.LowerM > 2 {
|
||||||
fmt.Printf("%v: %v looping label\n", linestr(lineno), n)
|
fmt.Printf("%v: %v looping label\n", linestr(lineno), n)
|
||||||
}
|
}
|
||||||
e.loopDepth++
|
e.loopDepth++
|
||||||
|
|
@ -752,7 +752,7 @@ func (e *Escape) addrs(l Nodes) []EscHole {
|
||||||
func (e *Escape) assign(dst, src *Node, why string, where *Node) {
|
func (e *Escape) assign(dst, src *Node, why string, where *Node) {
|
||||||
// Filter out some no-op assignments for escape analysis.
|
// Filter out some no-op assignments for escape analysis.
|
||||||
ignore := dst != nil && src != nil && isSelfAssign(dst, src)
|
ignore := dst != nil && src != nil && isSelfAssign(dst, src)
|
||||||
if ignore && Debug.m != 0 {
|
if ignore && Flag.LowerM != 0 {
|
||||||
Warnl(where.Pos, "%v ignoring self-assignment in %S", funcSym(e.curfn), where)
|
Warnl(where.Pos, "%v ignoring self-assignment in %S", funcSym(e.curfn), where)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -966,7 +966,7 @@ func (k EscHole) note(where *Node, why string) EscHole {
|
||||||
if where == nil || why == "" {
|
if where == nil || why == "" {
|
||||||
Fatalf("note: missing where/why")
|
Fatalf("note: missing where/why")
|
||||||
}
|
}
|
||||||
if Debug.m >= 2 || logopt.Enabled() {
|
if Flag.LowerM >= 2 || logopt.Enabled() {
|
||||||
k.notes = &EscNote{
|
k.notes = &EscNote{
|
||||||
next: k.notes,
|
next: k.notes,
|
||||||
where: where,
|
where: where,
|
||||||
|
|
@ -1112,9 +1112,9 @@ func (e *Escape) flow(k EscHole, src *EscLocation) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if dst.escapes && k.derefs < 0 { // dst = &src
|
if dst.escapes && k.derefs < 0 { // dst = &src
|
||||||
if Debug.m >= 2 || logopt.Enabled() {
|
if Flag.LowerM >= 2 || logopt.Enabled() {
|
||||||
pos := linestr(src.n.Pos)
|
pos := linestr(src.n.Pos)
|
||||||
if Debug.m >= 2 {
|
if Flag.LowerM >= 2 {
|
||||||
fmt.Printf("%s: %v escapes to heap:\n", pos, src.n)
|
fmt.Printf("%s: %v escapes to heap:\n", pos, src.n)
|
||||||
}
|
}
|
||||||
explanation := e.explainFlow(pos, dst, src, k.derefs, k.notes, []*logopt.LoggedOpt{})
|
explanation := e.explainFlow(pos, dst, src, k.derefs, k.notes, []*logopt.LoggedOpt{})
|
||||||
|
|
@ -1214,8 +1214,8 @@ func (e *Escape) walkOne(root *EscLocation, walkgen uint32, enqueue func(*EscLoc
|
||||||
// that value flow for tagging the function
|
// that value flow for tagging the function
|
||||||
// later.
|
// later.
|
||||||
if l.isName(PPARAM) {
|
if l.isName(PPARAM) {
|
||||||
if (logopt.Enabled() || Debug.m >= 2) && !l.escapes {
|
if (logopt.Enabled() || Flag.LowerM >= 2) && !l.escapes {
|
||||||
if Debug.m >= 2 {
|
if Flag.LowerM >= 2 {
|
||||||
fmt.Printf("%s: parameter %v leaks to %s with derefs=%d:\n", linestr(l.n.Pos), l.n, e.explainLoc(root), derefs)
|
fmt.Printf("%s: parameter %v leaks to %s with derefs=%d:\n", linestr(l.n.Pos), l.n, e.explainLoc(root), derefs)
|
||||||
}
|
}
|
||||||
explanation := e.explainPath(root, l)
|
explanation := e.explainPath(root, l)
|
||||||
|
|
@ -1231,8 +1231,8 @@ func (e *Escape) walkOne(root *EscLocation, walkgen uint32, enqueue func(*EscLoc
|
||||||
// outlives it, then l needs to be heap
|
// outlives it, then l needs to be heap
|
||||||
// allocated.
|
// allocated.
|
||||||
if addressOf && !l.escapes {
|
if addressOf && !l.escapes {
|
||||||
if logopt.Enabled() || Debug.m >= 2 {
|
if logopt.Enabled() || Flag.LowerM >= 2 {
|
||||||
if Debug.m >= 2 {
|
if Flag.LowerM >= 2 {
|
||||||
fmt.Printf("%s: %v escapes to heap:\n", linestr(l.n.Pos), l.n)
|
fmt.Printf("%s: %v escapes to heap:\n", linestr(l.n.Pos), l.n)
|
||||||
}
|
}
|
||||||
explanation := e.explainPath(root, l)
|
explanation := e.explainPath(root, l)
|
||||||
|
|
@ -1270,7 +1270,7 @@ func (e *Escape) explainPath(root, src *EscLocation) []*logopt.LoggedOpt {
|
||||||
for {
|
for {
|
||||||
// Prevent infinite loop.
|
// Prevent infinite loop.
|
||||||
if visited[src] {
|
if visited[src] {
|
||||||
if Debug.m >= 2 {
|
if Flag.LowerM >= 2 {
|
||||||
fmt.Printf("%s: warning: truncated explanation due to assignment cycle; see golang.org/issue/35518\n", pos)
|
fmt.Printf("%s: warning: truncated explanation due to assignment cycle; see golang.org/issue/35518\n", pos)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
|
|
@ -1298,7 +1298,7 @@ func (e *Escape) explainFlow(pos string, dst, srcloc *EscLocation, derefs int, n
|
||||||
if derefs >= 0 {
|
if derefs >= 0 {
|
||||||
ops = strings.Repeat("*", derefs)
|
ops = strings.Repeat("*", derefs)
|
||||||
}
|
}
|
||||||
print := Debug.m >= 2
|
print := Flag.LowerM >= 2
|
||||||
|
|
||||||
flow := fmt.Sprintf(" flow: %s = %s%v:", e.explainLoc(dst), ops, e.explainLoc(srcloc))
|
flow := fmt.Sprintf(" flow: %s = %s%v:", e.explainLoc(dst), ops, e.explainLoc(srcloc))
|
||||||
if print {
|
if print {
|
||||||
|
|
@ -1452,7 +1452,7 @@ func (e *Escape) finish(fns []*Node) {
|
||||||
|
|
||||||
if loc.escapes {
|
if loc.escapes {
|
||||||
if n.Op != ONAME {
|
if n.Op != ONAME {
|
||||||
if Debug.m != 0 {
|
if Flag.LowerM != 0 {
|
||||||
Warnl(n.Pos, "%S escapes to heap", n)
|
Warnl(n.Pos, "%S escapes to heap", n)
|
||||||
}
|
}
|
||||||
if logopt.Enabled() {
|
if logopt.Enabled() {
|
||||||
|
|
@ -1462,7 +1462,7 @@ func (e *Escape) finish(fns []*Node) {
|
||||||
n.Esc = EscHeap
|
n.Esc = EscHeap
|
||||||
addrescapes(n)
|
addrescapes(n)
|
||||||
} else {
|
} else {
|
||||||
if Debug.m != 0 && n.Op != ONAME {
|
if Flag.LowerM != 0 && n.Op != ONAME {
|
||||||
Warnl(n.Pos, "%S does not escape", n)
|
Warnl(n.Pos, "%S does not escape", n)
|
||||||
}
|
}
|
||||||
n.Esc = EscNone
|
n.Esc = EscNone
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ func exportsym(n *Node) {
|
||||||
}
|
}
|
||||||
n.Sym.SetOnExportList(true)
|
n.Sym.SetOnExportList(true)
|
||||||
|
|
||||||
if Debug.E != 0 {
|
if Flag.E != 0 {
|
||||||
fmt.Printf("export symbol %v\n", n.Sym)
|
fmt.Printf("export symbol %v\n", n.Sym)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -57,7 +57,7 @@ func autoexport(n *Node, ctxt Class) {
|
||||||
if types.IsExported(n.Sym.Name) || initname(n.Sym.Name) {
|
if types.IsExported(n.Sym.Name) || initname(n.Sym.Name) {
|
||||||
exportsym(n)
|
exportsym(n)
|
||||||
}
|
}
|
||||||
if asmhdr != "" && !n.Sym.Asm() {
|
if Flag.AsmHdr != "" && !n.Sym.Asm() {
|
||||||
n.Sym.SetAsm(true)
|
n.Sym.SetAsm(true)
|
||||||
asmlist = append(asmlist, n)
|
asmlist = append(asmlist, n)
|
||||||
}
|
}
|
||||||
|
|
@ -72,7 +72,7 @@ func dumpexport(bout *bio.Writer) {
|
||||||
exportf(bout, "\n$$\n")
|
exportf(bout, "\n$$\n")
|
||||||
|
|
||||||
if Debug_export != 0 {
|
if Debug_export != 0 {
|
||||||
fmt.Printf("BenchmarkExportSize:%s 1 %d bytes\n", myimportpath, size)
|
fmt.Printf("BenchmarkExportSize:%s 1 %d bytes\n", Ctxt.Pkgpath, size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -151,7 +151,7 @@ func importconst(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type, val
|
||||||
|
|
||||||
n.SetVal(val)
|
n.SetVal(val)
|
||||||
|
|
||||||
if Debug.E != 0 {
|
if Flag.E != 0 {
|
||||||
fmt.Printf("import const %v %L = %v\n", s, t, val)
|
fmt.Printf("import const %v %L = %v\n", s, t, val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -166,7 +166,7 @@ func importfunc(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) {
|
||||||
|
|
||||||
n.Func = new(Func)
|
n.Func = new(Func)
|
||||||
|
|
||||||
if Debug.E != 0 {
|
if Flag.E != 0 {
|
||||||
fmt.Printf("import func %v%S\n", s, t)
|
fmt.Printf("import func %v%S\n", s, t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -179,7 +179,7 @@ func importvar(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if Debug.E != 0 {
|
if Flag.E != 0 {
|
||||||
fmt.Printf("import var %v %L\n", s, t)
|
fmt.Printf("import var %v %L\n", s, t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -192,13 +192,13 @@ func importalias(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if Debug.E != 0 {
|
if Flag.E != 0 {
|
||||||
fmt.Printf("import type %v = %L\n", s, t)
|
fmt.Printf("import type %v = %L\n", s, t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func dumpasmhdr() {
|
func dumpasmhdr() {
|
||||||
b, err := bio.Create(asmhdr)
|
b, err := bio.Create(Flag.AsmHdr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fatalf("%v", err)
|
Fatalf("%v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
516
src/cmd/compile/internal/gc/flag.go
Normal file
516
src/cmd/compile/internal/gc/flag.go
Normal file
|
|
@ -0,0 +1,516 @@
|
||||||
|
// Copyright 2009 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 gc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"cmd/compile/internal/logopt"
|
||||||
|
"cmd/compile/internal/ssa"
|
||||||
|
"cmd/compile/internal/types"
|
||||||
|
"cmd/internal/dwarf"
|
||||||
|
"cmd/internal/obj"
|
||||||
|
"cmd/internal/objabi"
|
||||||
|
"cmd/internal/sys"
|
||||||
|
)
|
||||||
|
|
||||||
|
func usage() {
|
||||||
|
fmt.Fprintf(os.Stderr, "usage: compile [options] file.go...\n")
|
||||||
|
objabi.Flagprint(os.Stderr)
|
||||||
|
Exit(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
var Flag Flags
|
||||||
|
|
||||||
|
// gc debug flags
|
||||||
|
type Flags struct {
|
||||||
|
Percent, B, C, E,
|
||||||
|
K, L, N, S,
|
||||||
|
W, LowerE, LowerH, LowerJ,
|
||||||
|
LowerL, LowerM, LowerR, LowerW int
|
||||||
|
CompilingRuntime bool
|
||||||
|
Std bool
|
||||||
|
D string
|
||||||
|
AsmHdr string
|
||||||
|
BuildID string
|
||||||
|
LowerC int
|
||||||
|
Complete bool
|
||||||
|
LowerD string
|
||||||
|
Dwarf bool
|
||||||
|
GenDwarfInl int
|
||||||
|
InstallSuffix string
|
||||||
|
Lang string
|
||||||
|
LinkObj string
|
||||||
|
Live int
|
||||||
|
MSan bool
|
||||||
|
NoLocalImports bool
|
||||||
|
LowerO string
|
||||||
|
Pack bool
|
||||||
|
Race bool
|
||||||
|
Spectre string
|
||||||
|
LowerT bool
|
||||||
|
TrimPath string
|
||||||
|
WB bool
|
||||||
|
Shared bool
|
||||||
|
Dynlink bool
|
||||||
|
GoVersion string
|
||||||
|
SymABIs string
|
||||||
|
CPUProfile string
|
||||||
|
MemProfile string
|
||||||
|
TraceProfile string
|
||||||
|
BlockProfile string
|
||||||
|
MutexProfile string
|
||||||
|
Bench string
|
||||||
|
SmallFrames bool
|
||||||
|
JSON string
|
||||||
|
|
||||||
|
Cfg struct {
|
||||||
|
Embed struct {
|
||||||
|
Patterns map[string][]string
|
||||||
|
Files map[string]string
|
||||||
|
}
|
||||||
|
ImportDirs []string
|
||||||
|
ImportMap map[string]string
|
||||||
|
PackageFile map[string]string
|
||||||
|
SpectreIndex bool
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseFlags() {
|
||||||
|
Wasm := objabi.GOARCH == "wasm"
|
||||||
|
|
||||||
|
// Whether the limit for stack-allocated objects is much smaller than normal.
|
||||||
|
// This can be helpful for diagnosing certain causes of GC latency. See #27732.
|
||||||
|
Flag.SmallFrames = false
|
||||||
|
Flag.JSON = ""
|
||||||
|
|
||||||
|
flag.BoolVar(&Flag.CompilingRuntime, "+", false, "compiling runtime")
|
||||||
|
flag.BoolVar(&Flag.Std, "std", false, "compiling standard library")
|
||||||
|
flag.StringVar(&Flag.D, "D", "", "set relative `path` for local imports")
|
||||||
|
|
||||||
|
objabi.Flagcount("%", "debug non-static initializers", &Flag.Percent)
|
||||||
|
objabi.Flagcount("B", "disable bounds checking", &Flag.B)
|
||||||
|
objabi.Flagcount("C", "disable printing of columns in error messages", &Flag.C)
|
||||||
|
objabi.Flagcount("E", "debug symbol export", &Flag.E)
|
||||||
|
objabi.Flagcount("K", "debug missing line numbers", &Flag.K)
|
||||||
|
objabi.Flagcount("L", "show full file names in error messages", &Flag.L)
|
||||||
|
objabi.Flagcount("N", "disable optimizations", &Flag.N)
|
||||||
|
objabi.Flagcount("S", "print assembly listing", &Flag.S)
|
||||||
|
objabi.Flagcount("W", "debug parse tree after type checking", &Flag.W)
|
||||||
|
objabi.Flagcount("e", "no limit on number of errors reported", &Flag.LowerE)
|
||||||
|
objabi.Flagcount("h", "halt on error", &Flag.LowerH)
|
||||||
|
objabi.Flagcount("j", "debug runtime-initialized variables", &Flag.LowerJ)
|
||||||
|
objabi.Flagcount("l", "disable inlining", &Flag.LowerL)
|
||||||
|
objabi.Flagcount("m", "print optimization decisions", &Flag.LowerM)
|
||||||
|
objabi.Flagcount("r", "debug generated wrappers", &Flag.LowerR)
|
||||||
|
objabi.Flagcount("w", "debug type checking", &Flag.LowerW)
|
||||||
|
|
||||||
|
objabi.Flagfn1("I", "add `directory` to import search path", addImportDir)
|
||||||
|
objabi.AddVersionFlag() // -V
|
||||||
|
flag.StringVar(&Flag.AsmHdr, "asmhdr", "", "write assembly header to `file`")
|
||||||
|
flag.StringVar(&Flag.BuildID, "buildid", "", "record `id` as the build id in the export metadata")
|
||||||
|
flag.IntVar(&Flag.LowerC, "c", 1, "concurrency during compilation, 1 means no concurrency")
|
||||||
|
flag.BoolVar(&Flag.Complete, "complete", false, "compiling complete package (no C or assembly)")
|
||||||
|
flag.StringVar(&Flag.LowerD, "d", "", "print debug information about items in `list`; try -d help")
|
||||||
|
flag.BoolVar(&Flag.Dwarf, "dwarf", !Wasm, "generate DWARF symbols")
|
||||||
|
flag.BoolVar(&Ctxt.Flag_locationlists, "dwarflocationlists", true, "add location lists to DWARF in optimized mode")
|
||||||
|
flag.IntVar(&Flag.GenDwarfInl, "gendwarfinl", 2, "generate DWARF inline info records")
|
||||||
|
objabi.Flagfn1("embedcfg", "read go:embed configuration from `file`", readEmbedCfg)
|
||||||
|
objabi.Flagfn1("importmap", "add `definition` of the form source=actual to import map", addImportMap)
|
||||||
|
objabi.Flagfn1("importcfg", "read import configuration from `file`", readImportCfg)
|
||||||
|
flag.StringVar(&Flag.InstallSuffix, "installsuffix", "", "set pkg directory `suffix`")
|
||||||
|
flag.StringVar(&Flag.Lang, "lang", "", "release to compile for")
|
||||||
|
flag.StringVar(&Flag.LinkObj, "linkobj", "", "write linker-specific object to `file`")
|
||||||
|
objabi.Flagcount("live", "debug liveness analysis", &Flag.Live)
|
||||||
|
if sys.MSanSupported(objabi.GOOS, objabi.GOARCH) {
|
||||||
|
flag.BoolVar(&Flag.MSan, "msan", false, "build code compatible with C/C++ memory sanitizer")
|
||||||
|
}
|
||||||
|
flag.BoolVar(&Flag.NoLocalImports, "nolocalimports", false, "reject local (relative) imports")
|
||||||
|
flag.StringVar(&Flag.LowerO, "o", "", "write output to `file`")
|
||||||
|
flag.StringVar(&Ctxt.Pkgpath, "p", "", "set expected package import `path`")
|
||||||
|
flag.BoolVar(&Flag.Pack, "pack", false, "write to file.a instead of file.o")
|
||||||
|
if sys.RaceDetectorSupported(objabi.GOOS, objabi.GOARCH) {
|
||||||
|
flag.BoolVar(&Flag.Race, "race", false, "enable race detector")
|
||||||
|
}
|
||||||
|
flag.StringVar(&Flag.Spectre, "spectre", Flag.Spectre, "enable spectre mitigations in `list` (all, index, ret)")
|
||||||
|
if enableTrace {
|
||||||
|
flag.BoolVar(&Flag.LowerT, "t", false, "trace type-checking")
|
||||||
|
}
|
||||||
|
flag.StringVar(&Flag.TrimPath, "trimpath", "", "remove `prefix` from recorded source file paths")
|
||||||
|
flag.BoolVar(&Ctxt.Debugvlog, "v", false, "increase debug verbosity")
|
||||||
|
flag.BoolVar(&Flag.WB, "wb", true, "enable write barrier")
|
||||||
|
if supportsDynlink(thearch.LinkArch.Arch) {
|
||||||
|
flag.BoolVar(&Flag.Shared, "shared", false, "generate code that can be linked into a shared library")
|
||||||
|
flag.BoolVar(&Flag.Dynlink, "dynlink", false, "support references to Go symbols defined in other shared libraries")
|
||||||
|
flag.BoolVar(&Ctxt.Flag_linkshared, "linkshared", false, "generate code that will be linked against Go shared libraries")
|
||||||
|
}
|
||||||
|
flag.StringVar(&Flag.CPUProfile, "cpuprofile", "", "write cpu profile to `file`")
|
||||||
|
flag.StringVar(&Flag.MemProfile, "memprofile", "", "write memory profile to `file`")
|
||||||
|
flag.Int64Var(&memprofilerate, "memprofilerate", 0, "set runtime.MemProfileRate to `rate`")
|
||||||
|
flag.StringVar(&Flag.GoVersion, "goversion", "", "required version of the runtime")
|
||||||
|
flag.StringVar(&Flag.SymABIs, "symabis", "", "read symbol ABIs from `file`")
|
||||||
|
flag.StringVar(&Flag.TraceProfile, "traceprofile", "", "write an execution trace to `file`")
|
||||||
|
flag.StringVar(&Flag.BlockProfile, "blockprofile", "", "write block profile to `file`")
|
||||||
|
flag.StringVar(&Flag.MutexProfile, "mutexprofile", "", "write mutex profile to `file`")
|
||||||
|
flag.StringVar(&Flag.Bench, "bench", "", "append benchmark times to `file`")
|
||||||
|
flag.BoolVar(&Flag.SmallFrames, "smallframes", false, "reduce the size limit for stack allocated objects")
|
||||||
|
flag.BoolVar(&Ctxt.UseBASEntries, "dwarfbasentries", Ctxt.UseBASEntries, "use base address selection entries in DWARF")
|
||||||
|
flag.StringVar(&Flag.JSON, "json", "", "version,destination for JSON compiler/optimizer logging")
|
||||||
|
|
||||||
|
objabi.Flagparse(usage)
|
||||||
|
|
||||||
|
for _, f := range strings.Split(Flag.Spectre, ",") {
|
||||||
|
f = strings.TrimSpace(f)
|
||||||
|
switch f {
|
||||||
|
default:
|
||||||
|
log.Fatalf("unknown setting -spectre=%s", f)
|
||||||
|
case "":
|
||||||
|
// nothing
|
||||||
|
case "all":
|
||||||
|
Flag.Cfg.SpectreIndex = true
|
||||||
|
Ctxt.Retpoline = true
|
||||||
|
case "index":
|
||||||
|
Flag.Cfg.SpectreIndex = true
|
||||||
|
case "ret":
|
||||||
|
Ctxt.Retpoline = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if Flag.Cfg.SpectreIndex {
|
||||||
|
switch objabi.GOARCH {
|
||||||
|
case "amd64":
|
||||||
|
// ok
|
||||||
|
default:
|
||||||
|
log.Fatalf("GOARCH=%s does not support -spectre=index", objabi.GOARCH)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record flags that affect the build result. (And don't
|
||||||
|
// record flags that don't, since that would cause spurious
|
||||||
|
// changes in the binary.)
|
||||||
|
recordFlags("B", "N", "l", "msan", "race", "shared", "dynlink", "dwarflocationlists", "dwarfbasentries", "smallframes", "spectre")
|
||||||
|
|
||||||
|
if Flag.SmallFrames {
|
||||||
|
maxStackVarSize = 128 * 1024
|
||||||
|
maxImplicitStackVarSize = 16 * 1024
|
||||||
|
}
|
||||||
|
|
||||||
|
Ctxt.Flag_shared = Flag.Dynlink || Flag.Shared
|
||||||
|
Ctxt.Flag_dynlink = Flag.Dynlink
|
||||||
|
Ctxt.Flag_optimize = Flag.N == 0
|
||||||
|
|
||||||
|
Ctxt.Debugasm = Flag.S
|
||||||
|
if Flag.Dwarf {
|
||||||
|
Ctxt.DebugInfo = debuginfo
|
||||||
|
Ctxt.GenAbstractFunc = genAbstractFunc
|
||||||
|
Ctxt.DwFixups = obj.NewDwarfFixupTable(Ctxt)
|
||||||
|
} else {
|
||||||
|
// turn off inline generation if no dwarf at all
|
||||||
|
Flag.GenDwarfInl = 0
|
||||||
|
Ctxt.Flag_locationlists = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if flag.NArg() < 1 && Flag.LowerD != "help" && Flag.LowerD != "ssa/help" {
|
||||||
|
usage()
|
||||||
|
}
|
||||||
|
|
||||||
|
if Flag.GoVersion != "" && Flag.GoVersion != runtime.Version() {
|
||||||
|
fmt.Printf("compile: version %q does not match go tool version %q\n", runtime.Version(), Flag.GoVersion)
|
||||||
|
Exit(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
checkLang()
|
||||||
|
|
||||||
|
if Flag.SymABIs != "" {
|
||||||
|
readSymABIs(Flag.SymABIs, Ctxt.Pkgpath)
|
||||||
|
}
|
||||||
|
|
||||||
|
thearch.LinkArch.Init(Ctxt)
|
||||||
|
|
||||||
|
if Flag.LowerO == "" {
|
||||||
|
p := flag.Arg(0)
|
||||||
|
if i := strings.LastIndex(p, "/"); i >= 0 {
|
||||||
|
p = p[i+1:]
|
||||||
|
}
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
if i := strings.LastIndex(p, `\`); i >= 0 {
|
||||||
|
p = p[i+1:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if i := strings.LastIndex(p, "."); i >= 0 {
|
||||||
|
p = p[:i]
|
||||||
|
}
|
||||||
|
suffix := ".o"
|
||||||
|
if Flag.Pack {
|
||||||
|
suffix = ".a"
|
||||||
|
}
|
||||||
|
Flag.LowerO = p + suffix
|
||||||
|
}
|
||||||
|
|
||||||
|
startProfile()
|
||||||
|
|
||||||
|
if Flag.Race && Flag.MSan {
|
||||||
|
log.Fatal("cannot use both -race and -msan")
|
||||||
|
}
|
||||||
|
if Flag.Race || Flag.MSan {
|
||||||
|
// -race and -msan imply -d=checkptr for now.
|
||||||
|
Debug_checkptr = 1
|
||||||
|
}
|
||||||
|
if ispkgin(omit_pkgs) {
|
||||||
|
Flag.Race = false
|
||||||
|
Flag.MSan = false
|
||||||
|
}
|
||||||
|
if Flag.Race {
|
||||||
|
racepkg = types.NewPkg("runtime/race", "")
|
||||||
|
}
|
||||||
|
if Flag.MSan {
|
||||||
|
msanpkg = types.NewPkg("runtime/msan", "")
|
||||||
|
}
|
||||||
|
if Flag.Race || Flag.MSan {
|
||||||
|
instrumenting = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if Flag.CompilingRuntime && Flag.N != 0 {
|
||||||
|
log.Fatal("cannot disable optimizations while compiling runtime")
|
||||||
|
}
|
||||||
|
if Flag.LowerC < 1 {
|
||||||
|
log.Fatalf("-c must be at least 1, got %d", Flag.LowerC)
|
||||||
|
}
|
||||||
|
if Flag.LowerC > 1 && !concurrentBackendAllowed() {
|
||||||
|
log.Fatalf("cannot use concurrent backend compilation with provided flags; invoked as %v", os.Args)
|
||||||
|
}
|
||||||
|
if Ctxt.Flag_locationlists && len(Ctxt.Arch.DWARFRegisters) == 0 {
|
||||||
|
log.Fatalf("location lists requested but register mapping not available on %v", Ctxt.Arch.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse -d argument
|
||||||
|
if Flag.LowerD != "" {
|
||||||
|
Split:
|
||||||
|
for _, name := range strings.Split(Flag.LowerD, ",") {
|
||||||
|
if name == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// display help about the -d option itself and quit
|
||||||
|
if name == "help" {
|
||||||
|
fmt.Print(debugHelpHeader)
|
||||||
|
maxLen := len("ssa/help")
|
||||||
|
for _, t := range debugtab {
|
||||||
|
if len(t.name) > maxLen {
|
||||||
|
maxLen = len(t.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, t := range debugtab {
|
||||||
|
fmt.Printf("\t%-*s\t%s\n", maxLen, t.name, t.help)
|
||||||
|
}
|
||||||
|
// ssa options have their own help
|
||||||
|
fmt.Printf("\t%-*s\t%s\n", maxLen, "ssa/help", "print help about SSA debugging")
|
||||||
|
fmt.Print(debugHelpFooter)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
val, valstring, haveInt := 1, "", true
|
||||||
|
if i := strings.IndexAny(name, "=:"); i >= 0 {
|
||||||
|
var err error
|
||||||
|
name, valstring = name[:i], name[i+1:]
|
||||||
|
val, err = strconv.Atoi(valstring)
|
||||||
|
if err != nil {
|
||||||
|
val, haveInt = 1, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, t := range debugtab {
|
||||||
|
if t.name != name {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
switch vp := t.val.(type) {
|
||||||
|
case nil:
|
||||||
|
// Ignore
|
||||||
|
case *string:
|
||||||
|
*vp = valstring
|
||||||
|
case *int:
|
||||||
|
if !haveInt {
|
||||||
|
log.Fatalf("invalid debug value %v", name)
|
||||||
|
}
|
||||||
|
*vp = val
|
||||||
|
default:
|
||||||
|
panic("bad debugtab type")
|
||||||
|
}
|
||||||
|
continue Split
|
||||||
|
}
|
||||||
|
// special case for ssa for now
|
||||||
|
if strings.HasPrefix(name, "ssa/") {
|
||||||
|
// expect form ssa/phase/flag
|
||||||
|
// e.g. -d=ssa/generic_cse/time
|
||||||
|
// _ in phase name also matches space
|
||||||
|
phase := name[4:]
|
||||||
|
flag := "debug" // default flag is debug
|
||||||
|
if i := strings.Index(phase, "/"); i >= 0 {
|
||||||
|
flag = phase[i+1:]
|
||||||
|
phase = phase[:i]
|
||||||
|
}
|
||||||
|
err := ssa.PhaseOption(phase, flag, val, valstring)
|
||||||
|
if err != "" {
|
||||||
|
log.Fatalf(err)
|
||||||
|
}
|
||||||
|
continue Split
|
||||||
|
}
|
||||||
|
log.Fatalf("unknown debug key -d %s\n", name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if Flag.CompilingRuntime {
|
||||||
|
// Runtime can't use -d=checkptr, at least not yet.
|
||||||
|
Debug_checkptr = 0
|
||||||
|
|
||||||
|
// Fuzzing the runtime isn't interesting either.
|
||||||
|
Debug_libfuzzer = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// set via a -d flag
|
||||||
|
Ctxt.Debugpcln = Debug_pctab
|
||||||
|
if Flag.Dwarf {
|
||||||
|
dwarf.EnableLogging(Debug_gendwarfinl != 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if Debug_softfloat != 0 {
|
||||||
|
thearch.SoftFloat = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// enable inlining. for now:
|
||||||
|
// default: inlining on. (Debug.l == 1)
|
||||||
|
// -l: inlining off (Debug.l == 0)
|
||||||
|
// -l=2, -l=3: inlining on again, with extra debugging (Debug.l > 1)
|
||||||
|
if Flag.LowerL <= 1 {
|
||||||
|
Flag.LowerL = 1 - Flag.LowerL
|
||||||
|
}
|
||||||
|
|
||||||
|
if Flag.JSON != "" { // parse version,destination from json logging optimization.
|
||||||
|
logopt.LogJsonOption(Flag.JSON)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// concurrentFlagOk reports whether the current compiler flags
|
||||||
|
// are compatible with concurrent compilation.
|
||||||
|
func concurrentFlagOk() bool {
|
||||||
|
// TODO(rsc): Many of these are fine. Remove them.
|
||||||
|
return Flag.Percent == 0 &&
|
||||||
|
Flag.E == 0 &&
|
||||||
|
Flag.K == 0 &&
|
||||||
|
Flag.L == 0 &&
|
||||||
|
Flag.LowerH == 0 &&
|
||||||
|
Flag.LowerJ == 0 &&
|
||||||
|
Flag.LowerM == 0 &&
|
||||||
|
Flag.LowerR == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func concurrentBackendAllowed() bool {
|
||||||
|
if !concurrentFlagOk() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debug.S by itself is ok, because all printing occurs
|
||||||
|
// while writing the object file, and that is non-concurrent.
|
||||||
|
// Adding Debug_vlog, however, causes Debug.S to also print
|
||||||
|
// while flushing the plist, which happens concurrently.
|
||||||
|
if Ctxt.Debugvlog || Flag.LowerD != "" || Flag.Live > 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// TODO: Test and delete this condition.
|
||||||
|
if objabi.Fieldtrack_enabled != 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// TODO: fix races and enable the following flags
|
||||||
|
if Ctxt.Flag_shared || Ctxt.Flag_dynlink || Flag.Race {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func addImportDir(dir string) {
|
||||||
|
if dir != "" {
|
||||||
|
Flag.Cfg.ImportDirs = append(Flag.Cfg.ImportDirs, dir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func addImportMap(s string) {
|
||||||
|
if Flag.Cfg.ImportMap == nil {
|
||||||
|
Flag.Cfg.ImportMap = make(map[string]string)
|
||||||
|
}
|
||||||
|
if strings.Count(s, "=") != 1 {
|
||||||
|
log.Fatal("-importmap argument must be of the form source=actual")
|
||||||
|
}
|
||||||
|
i := strings.Index(s, "=")
|
||||||
|
source, actual := s[:i], s[i+1:]
|
||||||
|
if source == "" || actual == "" {
|
||||||
|
log.Fatal("-importmap argument must be of the form source=actual; source and actual must be non-empty")
|
||||||
|
}
|
||||||
|
Flag.Cfg.ImportMap[source] = actual
|
||||||
|
}
|
||||||
|
|
||||||
|
func readImportCfg(file string) {
|
||||||
|
if Flag.Cfg.ImportMap == nil {
|
||||||
|
Flag.Cfg.ImportMap = make(map[string]string)
|
||||||
|
}
|
||||||
|
Flag.Cfg.PackageFile = map[string]string{}
|
||||||
|
data, err := ioutil.ReadFile(file)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("-importcfg: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for lineNum, line := range strings.Split(string(data), "\n") {
|
||||||
|
lineNum++ // 1-based
|
||||||
|
line = strings.TrimSpace(line)
|
||||||
|
if line == "" || strings.HasPrefix(line, "#") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var verb, args string
|
||||||
|
if i := strings.Index(line, " "); i < 0 {
|
||||||
|
verb = line
|
||||||
|
} else {
|
||||||
|
verb, args = line[:i], strings.TrimSpace(line[i+1:])
|
||||||
|
}
|
||||||
|
var before, after string
|
||||||
|
if i := strings.Index(args, "="); i >= 0 {
|
||||||
|
before, after = args[:i], args[i+1:]
|
||||||
|
}
|
||||||
|
switch verb {
|
||||||
|
default:
|
||||||
|
log.Fatalf("%s:%d: unknown directive %q", file, lineNum, verb)
|
||||||
|
case "importmap":
|
||||||
|
if before == "" || after == "" {
|
||||||
|
log.Fatalf(`%s:%d: invalid importmap: syntax is "importmap old=new"`, file, lineNum)
|
||||||
|
}
|
||||||
|
Flag.Cfg.ImportMap[before] = after
|
||||||
|
case "packagefile":
|
||||||
|
if before == "" || after == "" {
|
||||||
|
log.Fatalf(`%s:%d: invalid packagefile: syntax is "packagefile path=filename"`, file, lineNum)
|
||||||
|
}
|
||||||
|
Flag.Cfg.PackageFile[before] = after
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func readEmbedCfg(file string) {
|
||||||
|
data, err := ioutil.ReadFile(file)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("-embedcfg: %v", err)
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(data, &Flag.Cfg.Embed); err != nil {
|
||||||
|
log.Fatalf("%s: %v", file, err)
|
||||||
|
}
|
||||||
|
if Flag.Cfg.Embed.Patterns == nil {
|
||||||
|
log.Fatalf("%s: invalid embedcfg: missing Patterns", file)
|
||||||
|
}
|
||||||
|
if Flag.Cfg.Embed.Files == nil {
|
||||||
|
log.Fatalf("%s: invalid embedcfg: missing Files", file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -39,7 +39,7 @@ var (
|
||||||
|
|
||||||
// isRuntimePkg reports whether p is package runtime.
|
// isRuntimePkg reports whether p is package runtime.
|
||||||
func isRuntimePkg(p *types.Pkg) bool {
|
func isRuntimePkg(p *types.Pkg) bool {
|
||||||
if compiling_runtime && p == localpkg {
|
if Flag.CompilingRuntime && p == localpkg {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return p.Path == "runtime"
|
return p.Path == "runtime"
|
||||||
|
|
@ -48,7 +48,7 @@ func isRuntimePkg(p *types.Pkg) bool {
|
||||||
// isReflectPkg reports whether p is package reflect.
|
// isReflectPkg reports whether p is package reflect.
|
||||||
func isReflectPkg(p *types.Pkg) bool {
|
func isReflectPkg(p *types.Pkg) bool {
|
||||||
if p == localpkg {
|
if p == localpkg {
|
||||||
return myimportpath == "reflect"
|
return Ctxt.Pkgpath == "reflect"
|
||||||
}
|
}
|
||||||
return p.Path == "reflect"
|
return p.Path == "reflect"
|
||||||
}
|
}
|
||||||
|
|
@ -99,25 +99,8 @@ var (
|
||||||
|
|
||||||
var pragcgobuf [][]string
|
var pragcgobuf [][]string
|
||||||
|
|
||||||
var outfile string
|
|
||||||
var linkobj string
|
|
||||||
|
|
||||||
var decldepth int32
|
var decldepth int32
|
||||||
|
|
||||||
var nolocalimports bool
|
|
||||||
|
|
||||||
// gc debug flags
|
|
||||||
type DebugFlags struct {
|
|
||||||
P, B, C, E,
|
|
||||||
K, L, N, S,
|
|
||||||
W, e, h, j,
|
|
||||||
l, m, r, w int
|
|
||||||
}
|
|
||||||
|
|
||||||
var Debug DebugFlags
|
|
||||||
|
|
||||||
var debugstr string
|
|
||||||
|
|
||||||
var Debug_checknil int
|
var Debug_checknil int
|
||||||
var Debug_typeassert int
|
var Debug_typeassert int
|
||||||
|
|
||||||
|
|
@ -145,12 +128,6 @@ var gopkg *types.Pkg // pseudo-package for method symbols on anonymous receiver
|
||||||
|
|
||||||
var zerosize int64
|
var zerosize int64
|
||||||
|
|
||||||
var myimportpath string
|
|
||||||
|
|
||||||
var localimport string
|
|
||||||
|
|
||||||
var asmhdr string
|
|
||||||
|
|
||||||
var simtype [NTYPE]types.EType
|
var simtype [NTYPE]types.EType
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -201,23 +178,6 @@ var nblank *Node
|
||||||
|
|
||||||
var typecheckok bool
|
var typecheckok bool
|
||||||
|
|
||||||
var compiling_runtime bool
|
|
||||||
|
|
||||||
// Compiling the standard library
|
|
||||||
var compiling_std bool
|
|
||||||
|
|
||||||
var use_writebarrier bool
|
|
||||||
|
|
||||||
var pure_go bool
|
|
||||||
|
|
||||||
var flag_installsuffix string
|
|
||||||
|
|
||||||
var flag_race bool
|
|
||||||
|
|
||||||
var flag_msan bool
|
|
||||||
|
|
||||||
var flagDWARF bool
|
|
||||||
|
|
||||||
// Whether we are adding any sort of code instrumentation, such as
|
// Whether we are adding any sort of code instrumentation, such as
|
||||||
// when the race detector is enabled.
|
// when the race detector is enabled.
|
||||||
var instrumenting bool
|
var instrumenting bool
|
||||||
|
|
@ -225,17 +185,8 @@ var instrumenting bool
|
||||||
// Whether we are tracking lexical scopes for DWARF.
|
// Whether we are tracking lexical scopes for DWARF.
|
||||||
var trackScopes bool
|
var trackScopes bool
|
||||||
|
|
||||||
// Controls generation of DWARF inlined instance records. Zero
|
|
||||||
// disables, 1 emits inlined routines but suppresses var info,
|
|
||||||
// and 2 emits inlined routines with tracking of formals/locals.
|
|
||||||
var genDwarfInline int
|
|
||||||
|
|
||||||
var debuglive int
|
|
||||||
|
|
||||||
var Ctxt *obj.Link
|
var Ctxt *obj.Link
|
||||||
|
|
||||||
var writearchive bool
|
|
||||||
|
|
||||||
var nodfp *Node
|
var nodfp *Node
|
||||||
|
|
||||||
var disable_checknil int
|
var disable_checknil int
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ type Progs struct {
|
||||||
func newProgs(fn *Node, worker int) *Progs {
|
func newProgs(fn *Node, worker int) *Progs {
|
||||||
pp := new(Progs)
|
pp := new(Progs)
|
||||||
if Ctxt.CanReuseProgs() {
|
if Ctxt.CanReuseProgs() {
|
||||||
sz := len(sharedProgArray) / nBackendWorkers
|
sz := len(sharedProgArray) / Flag.LowerC
|
||||||
pp.progcache = sharedProgArray[sz*worker : sz*(worker+1)]
|
pp.progcache = sharedProgArray[sz*worker : sz*(worker+1)]
|
||||||
}
|
}
|
||||||
pp.curfn = fn
|
pp.curfn = fn
|
||||||
|
|
@ -90,7 +90,7 @@ func (pp *Progs) NewProg() *obj.Prog {
|
||||||
// Flush converts from pp to machine code.
|
// Flush converts from pp to machine code.
|
||||||
func (pp *Progs) Flush() {
|
func (pp *Progs) Flush() {
|
||||||
plist := &obj.Plist{Firstpc: pp.Text, Curfn: pp.curfn}
|
plist := &obj.Plist{Firstpc: pp.Text, Curfn: pp.curfn}
|
||||||
obj.Flushplist(Ctxt, plist, pp.NewProg, myimportpath)
|
obj.Flushplist(Ctxt, plist, pp.NewProg, Ctxt.Pkgpath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free clears pp and any associated resources.
|
// Free clears pp and any associated resources.
|
||||||
|
|
@ -133,7 +133,7 @@ func (pp *Progs) Prog(as obj.As) *obj.Prog {
|
||||||
pp.clearp(pp.next)
|
pp.clearp(pp.next)
|
||||||
p.Link = pp.next
|
p.Link = pp.next
|
||||||
|
|
||||||
if !pp.pos.IsKnown() && Debug.K != 0 {
|
if !pp.pos.IsKnown() && Flag.K != 0 {
|
||||||
Warn("prog: unknown position (line 0)")
|
Warn("prog: unknown position (line 0)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -278,7 +278,7 @@ func (f *Func) initLSym(hasBody bool) {
|
||||||
// Clumsy but important.
|
// Clumsy but important.
|
||||||
// See test/recover.go for test cases and src/reflect/value.go
|
// See test/recover.go for test cases and src/reflect/value.go
|
||||||
// for the actual functions being considered.
|
// for the actual functions being considered.
|
||||||
if myimportpath == "reflect" {
|
if Ctxt.Pkgpath == "reflect" {
|
||||||
switch f.Nname.Sym.Name {
|
switch f.Nname.Sym.Name {
|
||||||
case "callReflect", "callMethod":
|
case "callReflect", "callMethod":
|
||||||
flag |= obj.WRAPPER
|
flag |= obj.WRAPPER
|
||||||
|
|
|
||||||
|
|
@ -714,8 +714,8 @@ func (r *importReader) doInline(n *Node) {
|
||||||
|
|
||||||
importlist = append(importlist, n)
|
importlist = append(importlist, n)
|
||||||
|
|
||||||
if Debug.E > 0 && Debug.m > 2 {
|
if Flag.E > 0 && Flag.LowerM > 2 {
|
||||||
if Debug.m > 3 {
|
if Flag.LowerM > 3 {
|
||||||
fmt.Printf("inl body for %v %#v: %+v\n", n, n.Type, asNodes(n.Func.Inl.Body))
|
fmt.Printf("inl body for %v %#v: %+v\n", n, n.Type, asNodes(n.Func.Inl.Body))
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("inl body for %v %#v: %v\n", n, n.Type, asNodes(n.Func.Inl.Body))
|
fmt.Printf("inl body for %v %#v: %v\n", n, n.Type, asNodes(n.Func.Inl.Body))
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ func typecheckinl(fn *Node) {
|
||||||
return // typecheckinl on local function
|
return // typecheckinl on local function
|
||||||
}
|
}
|
||||||
|
|
||||||
if Debug.m > 2 || Debug_export != 0 {
|
if Flag.LowerM > 2 || Debug_export != 0 {
|
||||||
fmt.Printf("typecheck import [%v] %L { %#v }\n", fn.Sym, fn, asNodes(fn.Func.Inl.Body))
|
fmt.Printf("typecheck import [%v] %L { %#v }\n", fn.Sym, fn, asNodes(fn.Func.Inl.Body))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -118,10 +118,10 @@ func caninl(fn *Node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var reason string // reason, if any, that the function was not inlined
|
var reason string // reason, if any, that the function was not inlined
|
||||||
if Debug.m > 1 || logopt.Enabled() {
|
if Flag.LowerM > 1 || logopt.Enabled() {
|
||||||
defer func() {
|
defer func() {
|
||||||
if reason != "" {
|
if reason != "" {
|
||||||
if Debug.m > 1 {
|
if Flag.LowerM > 1 {
|
||||||
fmt.Printf("%v: cannot inline %v: %s\n", fn.Line(), fn.Func.Nname, reason)
|
fmt.Printf("%v: cannot inline %v: %s\n", fn.Line(), fn.Func.Nname, reason)
|
||||||
}
|
}
|
||||||
if logopt.Enabled() {
|
if logopt.Enabled() {
|
||||||
|
|
@ -138,7 +138,7 @@ func caninl(fn *Node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If marked "go:norace" and -race compilation, don't inline.
|
// If marked "go:norace" and -race compilation, don't inline.
|
||||||
if flag_race && fn.Func.Pragma&Norace != 0 {
|
if Flag.Race && fn.Func.Pragma&Norace != 0 {
|
||||||
reason = "marked go:norace with -race compilation"
|
reason = "marked go:norace with -race compilation"
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -189,7 +189,7 @@ func caninl(fn *Node) {
|
||||||
defer n.Func.SetInlinabilityChecked(true)
|
defer n.Func.SetInlinabilityChecked(true)
|
||||||
|
|
||||||
cc := int32(inlineExtraCallCost)
|
cc := int32(inlineExtraCallCost)
|
||||||
if Debug.l == 4 {
|
if Flag.LowerL == 4 {
|
||||||
cc = 1 // this appears to yield better performance than 0.
|
cc = 1 // this appears to yield better performance than 0.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -222,9 +222,9 @@ func caninl(fn *Node) {
|
||||||
Body: inlcopylist(fn.Nbody.Slice()),
|
Body: inlcopylist(fn.Nbody.Slice()),
|
||||||
}
|
}
|
||||||
|
|
||||||
if Debug.m > 1 {
|
if Flag.LowerM > 1 {
|
||||||
fmt.Printf("%v: can inline %#v with cost %d as: %#v { %#v }\n", fn.Line(), n, inlineMaxBudget-visitor.budget, fn.Type, asNodes(n.Func.Inl.Body))
|
fmt.Printf("%v: can inline %#v with cost %d as: %#v { %#v }\n", fn.Line(), n, inlineMaxBudget-visitor.budget, fn.Type, asNodes(n.Func.Inl.Body))
|
||||||
} else if Debug.m != 0 {
|
} else if Flag.LowerM != 0 {
|
||||||
fmt.Printf("%v: can inline %v\n", fn.Line(), n)
|
fmt.Printf("%v: can inline %v\n", fn.Line(), n)
|
||||||
}
|
}
|
||||||
if logopt.Enabled() {
|
if logopt.Enabled() {
|
||||||
|
|
@ -433,7 +433,7 @@ func (v *hairyVisitor) visit(n *Node) bool {
|
||||||
v.budget--
|
v.budget--
|
||||||
|
|
||||||
// When debugging, don't stop early, to get full cost of inlining this function
|
// When debugging, don't stop early, to get full cost of inlining this function
|
||||||
if v.budget < 0 && Debug.m < 2 && !logopt.Enabled() {
|
if v.budget < 0 && Flag.LowerM < 2 && !logopt.Enabled() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -676,7 +676,7 @@ func inlnode(n *Node, maxCost int32, inlMap map[*Node]bool) *Node {
|
||||||
|
|
||||||
switch n.Op {
|
switch n.Op {
|
||||||
case OCALLFUNC:
|
case OCALLFUNC:
|
||||||
if Debug.m > 3 {
|
if Flag.LowerM > 3 {
|
||||||
fmt.Printf("%v:call to func %+v\n", n.Line(), n.Left)
|
fmt.Printf("%v:call to func %+v\n", n.Line(), n.Left)
|
||||||
}
|
}
|
||||||
if isIntrinsicCall(n) {
|
if isIntrinsicCall(n) {
|
||||||
|
|
@ -687,7 +687,7 @@ func inlnode(n *Node, maxCost int32, inlMap map[*Node]bool) *Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
case OCALLMETH:
|
case OCALLMETH:
|
||||||
if Debug.m > 3 {
|
if Flag.LowerM > 3 {
|
||||||
fmt.Printf("%v:call to meth %L\n", n.Line(), n.Left.Right)
|
fmt.Printf("%v:call to meth %L\n", n.Line(), n.Left.Right)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -922,7 +922,7 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
if inlMap[fn] {
|
if inlMap[fn] {
|
||||||
if Debug.m > 1 {
|
if Flag.LowerM > 1 {
|
||||||
fmt.Printf("%v: cannot inline %v into %v: repeated recursive cycle\n", n.Line(), fn, Curfn.funcname())
|
fmt.Printf("%v: cannot inline %v into %v: repeated recursive cycle\n", n.Line(), fn, Curfn.funcname())
|
||||||
}
|
}
|
||||||
return n
|
return n
|
||||||
|
|
@ -936,12 +936,12 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have a function node, and it has an inlineable body.
|
// We have a function node, and it has an inlineable body.
|
||||||
if Debug.m > 1 {
|
if Flag.LowerM > 1 {
|
||||||
fmt.Printf("%v: inlining call to %v %#v { %#v }\n", n.Line(), fn.Sym, fn.Type, asNodes(fn.Func.Inl.Body))
|
fmt.Printf("%v: inlining call to %v %#v { %#v }\n", n.Line(), fn.Sym, fn.Type, asNodes(fn.Func.Inl.Body))
|
||||||
} else if Debug.m != 0 {
|
} else if Flag.LowerM != 0 {
|
||||||
fmt.Printf("%v: inlining call to %v\n", n.Line(), fn)
|
fmt.Printf("%v: inlining call to %v\n", n.Line(), fn)
|
||||||
}
|
}
|
||||||
if Debug.m > 2 {
|
if Flag.LowerM > 2 {
|
||||||
fmt.Printf("%v: Before inlining: %+v\n", n.Line(), n)
|
fmt.Printf("%v: Before inlining: %+v\n", n.Line(), n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1026,7 +1026,7 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node {
|
||||||
}
|
}
|
||||||
inlf := typecheck(inlvar(ln), ctxExpr)
|
inlf := typecheck(inlvar(ln), ctxExpr)
|
||||||
inlvars[ln] = inlf
|
inlvars[ln] = inlf
|
||||||
if genDwarfInline > 0 {
|
if Flag.GenDwarfInl > 0 {
|
||||||
if ln.Class() == PPARAM {
|
if ln.Class() == PPARAM {
|
||||||
inlf.Name.SetInlFormal(true)
|
inlf.Name.SetInlFormal(true)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1064,7 +1064,7 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node {
|
||||||
m = retvar(t, i)
|
m = retvar(t, i)
|
||||||
}
|
}
|
||||||
|
|
||||||
if genDwarfInline > 0 {
|
if Flag.GenDwarfInl > 0 {
|
||||||
// Don't update the src.Pos on a return variable if it
|
// Don't update the src.Pos on a return variable if it
|
||||||
// was manufactured by the inliner (e.g. "~R2"); such vars
|
// was manufactured by the inliner (e.g. "~R2"); such vars
|
||||||
// were not part of the original callee.
|
// were not part of the original callee.
|
||||||
|
|
@ -1165,7 +1165,7 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node {
|
||||||
inlMark.Xoffset = int64(newIndex)
|
inlMark.Xoffset = int64(newIndex)
|
||||||
ninit.Append(inlMark)
|
ninit.Append(inlMark)
|
||||||
|
|
||||||
if genDwarfInline > 0 {
|
if Flag.GenDwarfInl > 0 {
|
||||||
if !fn.Sym.Linksym().WasInlined() {
|
if !fn.Sym.Linksym().WasInlined() {
|
||||||
Ctxt.DwFixups.SetPrecursorFunc(fn.Sym.Linksym(), fn)
|
Ctxt.DwFixups.SetPrecursorFunc(fn.Sym.Linksym(), fn)
|
||||||
fn.Sym.Linksym().Set(obj.AttrWasInlined, true)
|
fn.Sym.Linksym().Set(obj.AttrWasInlined, true)
|
||||||
|
|
@ -1188,7 +1188,7 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node {
|
||||||
|
|
||||||
typecheckslice(body, ctxStmt)
|
typecheckslice(body, ctxStmt)
|
||||||
|
|
||||||
if genDwarfInline > 0 {
|
if Flag.GenDwarfInl > 0 {
|
||||||
for _, v := range inlfvars {
|
for _, v := range inlfvars {
|
||||||
v.Pos = subst.updatedPos(v.Pos)
|
v.Pos = subst.updatedPos(v.Pos)
|
||||||
}
|
}
|
||||||
|
|
@ -1216,7 +1216,7 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if Debug.m > 2 {
|
if Flag.LowerM > 2 {
|
||||||
fmt.Printf("%v: After inlining %+v\n\n", call.Line(), call)
|
fmt.Printf("%v: After inlining %+v\n\n", call.Line(), call)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1227,7 +1227,7 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node {
|
||||||
// PAUTO's in the calling functions, and link them off of the
|
// PAUTO's in the calling functions, and link them off of the
|
||||||
// PPARAM's, PAUTOS and PPARAMOUTs of the called function.
|
// PPARAM's, PAUTOS and PPARAMOUTs of the called function.
|
||||||
func inlvar(var_ *Node) *Node {
|
func inlvar(var_ *Node) *Node {
|
||||||
if Debug.m > 3 {
|
if Flag.LowerM > 3 {
|
||||||
fmt.Printf("inlvar %+v\n", var_)
|
fmt.Printf("inlvar %+v\n", var_)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1310,13 +1310,13 @@ func (subst *inlsubst) node(n *Node) *Node {
|
||||||
switch n.Op {
|
switch n.Op {
|
||||||
case ONAME:
|
case ONAME:
|
||||||
if inlvar := subst.inlvars[n]; inlvar != nil { // These will be set during inlnode
|
if inlvar := subst.inlvars[n]; inlvar != nil { // These will be set during inlnode
|
||||||
if Debug.m > 2 {
|
if Flag.LowerM > 2 {
|
||||||
fmt.Printf("substituting name %+v -> %+v\n", n, inlvar)
|
fmt.Printf("substituting name %+v -> %+v\n", n, inlvar)
|
||||||
}
|
}
|
||||||
return inlvar
|
return inlvar
|
||||||
}
|
}
|
||||||
|
|
||||||
if Debug.m > 2 {
|
if Flag.LowerM > 2 {
|
||||||
fmt.Printf("not substituting name %+v\n", n)
|
fmt.Printf("not substituting name %+v\n", n)
|
||||||
}
|
}
|
||||||
return n
|
return n
|
||||||
|
|
@ -1449,21 +1449,21 @@ func devirtualizeCall(call *Node) {
|
||||||
x = typecheck(x, ctxExpr|ctxCallee)
|
x = typecheck(x, ctxExpr|ctxCallee)
|
||||||
switch x.Op {
|
switch x.Op {
|
||||||
case ODOTMETH:
|
case ODOTMETH:
|
||||||
if Debug.m != 0 {
|
if Flag.LowerM != 0 {
|
||||||
Warnl(call.Pos, "devirtualizing %v to %v", call.Left, typ)
|
Warnl(call.Pos, "devirtualizing %v to %v", call.Left, typ)
|
||||||
}
|
}
|
||||||
call.Op = OCALLMETH
|
call.Op = OCALLMETH
|
||||||
call.Left = x
|
call.Left = x
|
||||||
case ODOTINTER:
|
case ODOTINTER:
|
||||||
// Promoted method from embedded interface-typed field (#42279).
|
// Promoted method from embedded interface-typed field (#42279).
|
||||||
if Debug.m != 0 {
|
if Flag.LowerM != 0 {
|
||||||
Warnl(call.Pos, "partially devirtualizing %v to %v", call.Left, typ)
|
Warnl(call.Pos, "partially devirtualizing %v to %v", call.Left, typ)
|
||||||
}
|
}
|
||||||
call.Op = OCALLINTER
|
call.Op = OCALLINTER
|
||||||
call.Left = x
|
call.Left = x
|
||||||
default:
|
default:
|
||||||
// TODO(mdempsky): Turn back into Fatalf after more testing.
|
// TODO(mdempsky): Turn back into Fatalf after more testing.
|
||||||
if Debug.m != 0 {
|
if Flag.LowerM != 0 {
|
||||||
Warnl(call.Pos, "failed to devirtualize %v (%v)", x, x.Op)
|
Warnl(call.Pos, "failed to devirtualize %v (%v)", x, x.Op)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"cmd/compile/internal/logopt"
|
"cmd/compile/internal/logopt"
|
||||||
"cmd/compile/internal/ssa"
|
|
||||||
"cmd/compile/internal/types"
|
"cmd/compile/internal/types"
|
||||||
"cmd/internal/bio"
|
"cmd/internal/bio"
|
||||||
"cmd/internal/dwarf"
|
"cmd/internal/dwarf"
|
||||||
|
|
@ -35,12 +35,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
buildid string
|
|
||||||
spectre string
|
|
||||||
spectreIndex bool
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
Debug_append int
|
Debug_append int
|
||||||
Debug_checkptr int
|
Debug_checkptr int
|
||||||
|
|
@ -51,7 +45,6 @@ var (
|
||||||
Debug_libfuzzer int
|
Debug_libfuzzer int
|
||||||
Debug_panic int
|
Debug_panic int
|
||||||
Debug_slice int
|
Debug_slice int
|
||||||
Debug_vlog bool
|
|
||||||
Debug_wb int
|
Debug_wb int
|
||||||
Debug_pctab string
|
Debug_pctab string
|
||||||
Debug_locationlist int
|
Debug_locationlist int
|
||||||
|
|
@ -113,12 +106,6 @@ Key "pctab" supports values:
|
||||||
"pctospadj", "pctofile", "pctoline", "pctoinline", "pctopcdata"
|
"pctospadj", "pctofile", "pctoline", "pctoinline", "pctopcdata"
|
||||||
`
|
`
|
||||||
|
|
||||||
func usage() {
|
|
||||||
fmt.Fprintf(os.Stderr, "usage: compile [options] file.go...\n")
|
|
||||||
objabi.Flagprint(os.Stderr)
|
|
||||||
Exit(2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func hidePanic() {
|
func hidePanic() {
|
||||||
if Debug_panic == 0 && Errors() > 0 {
|
if Debug_panic == 0 && Errors() > 0 {
|
||||||
// If we've already complained about things
|
// If we've already complained about things
|
||||||
|
|
@ -139,7 +126,6 @@ func supportsDynlink(arch *sys.Arch) bool {
|
||||||
|
|
||||||
// timing data for compiler phases
|
// timing data for compiler phases
|
||||||
var timings Timings
|
var timings Timings
|
||||||
var benchfile string
|
|
||||||
|
|
||||||
var nowritebarrierrecCheck *nowritebarrierrecChecker
|
var nowritebarrierrecCheck *nowritebarrierrecChecker
|
||||||
|
|
||||||
|
|
@ -204,321 +190,7 @@ func Main(archInit func(*Arch)) {
|
||||||
// pseudo-package used for methods with anonymous receivers
|
// pseudo-package used for methods with anonymous receivers
|
||||||
gopkg = types.NewPkg("go", "")
|
gopkg = types.NewPkg("go", "")
|
||||||
|
|
||||||
Wasm := objabi.GOARCH == "wasm"
|
ParseFlags()
|
||||||
|
|
||||||
// Whether the limit for stack-allocated objects is much smaller than normal.
|
|
||||||
// This can be helpful for diagnosing certain causes of GC latency. See #27732.
|
|
||||||
smallFrames := false
|
|
||||||
jsonLogOpt := ""
|
|
||||||
|
|
||||||
flag.BoolVar(&compiling_runtime, "+", false, "compiling runtime")
|
|
||||||
flag.BoolVar(&compiling_std, "std", false, "compiling standard library")
|
|
||||||
flag.StringVar(&localimport, "D", "", "set relative `path` for local imports")
|
|
||||||
|
|
||||||
objabi.Flagcount("%", "debug non-static initializers", &Debug.P)
|
|
||||||
objabi.Flagcount("B", "disable bounds checking", &Debug.B)
|
|
||||||
objabi.Flagcount("C", "disable printing of columns in error messages", &Debug.C)
|
|
||||||
objabi.Flagcount("E", "debug symbol export", &Debug.E)
|
|
||||||
objabi.Flagcount("K", "debug missing line numbers", &Debug.K)
|
|
||||||
objabi.Flagcount("L", "show full file names in error messages", &Debug.L)
|
|
||||||
objabi.Flagcount("N", "disable optimizations", &Debug.N)
|
|
||||||
objabi.Flagcount("S", "print assembly listing", &Debug.S)
|
|
||||||
objabi.Flagcount("W", "debug parse tree after type checking", &Debug.W)
|
|
||||||
objabi.Flagcount("e", "no limit on number of errors reported", &Debug.e)
|
|
||||||
objabi.Flagcount("h", "halt on error", &Debug.h)
|
|
||||||
objabi.Flagcount("j", "debug runtime-initialized variables", &Debug.j)
|
|
||||||
objabi.Flagcount("l", "disable inlining", &Debug.l)
|
|
||||||
objabi.Flagcount("m", "print optimization decisions", &Debug.m)
|
|
||||||
objabi.Flagcount("r", "debug generated wrappers", &Debug.r)
|
|
||||||
objabi.Flagcount("w", "debug type checking", &Debug.w)
|
|
||||||
|
|
||||||
objabi.Flagfn1("I", "add `directory` to import search path", addidir)
|
|
||||||
objabi.AddVersionFlag() // -V
|
|
||||||
flag.StringVar(&asmhdr, "asmhdr", "", "write assembly header to `file`")
|
|
||||||
flag.StringVar(&buildid, "buildid", "", "record `id` as the build id in the export metadata")
|
|
||||||
flag.IntVar(&nBackendWorkers, "c", 1, "concurrency during compilation, 1 means no concurrency")
|
|
||||||
flag.BoolVar(&pure_go, "complete", false, "compiling complete package (no C or assembly)")
|
|
||||||
flag.StringVar(&debugstr, "d", "", "print debug information about items in `list`; try -d help")
|
|
||||||
flag.BoolVar(&flagDWARF, "dwarf", !Wasm, "generate DWARF symbols")
|
|
||||||
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.Flagfn1("embedcfg", "read go:embed configuration from `file`", readEmbedCfg)
|
|
||||||
objabi.Flagfn1("importmap", "add `definition` of the form source=actual to import map", addImportMap)
|
|
||||||
objabi.Flagfn1("importcfg", "read import configuration from `file`", readImportCfg)
|
|
||||||
flag.StringVar(&flag_installsuffix, "installsuffix", "", "set pkg directory `suffix`")
|
|
||||||
flag.StringVar(&flag_lang, "lang", "", "release to compile for")
|
|
||||||
flag.StringVar(&linkobj, "linkobj", "", "write linker-specific object to `file`")
|
|
||||||
objabi.Flagcount("live", "debug liveness analysis", &debuglive)
|
|
||||||
if sys.MSanSupported(objabi.GOOS, objabi.GOARCH) {
|
|
||||||
flag.BoolVar(&flag_msan, "msan", false, "build code compatible with C/C++ memory sanitizer")
|
|
||||||
}
|
|
||||||
flag.BoolVar(&nolocalimports, "nolocalimports", false, "reject local (relative) imports")
|
|
||||||
flag.StringVar(&outfile, "o", "", "write output to `file`")
|
|
||||||
flag.StringVar(&myimportpath, "p", "", "set expected package import `path`")
|
|
||||||
flag.BoolVar(&writearchive, "pack", false, "write to file.a instead of file.o")
|
|
||||||
if sys.RaceDetectorSupported(objabi.GOOS, objabi.GOARCH) {
|
|
||||||
flag.BoolVar(&flag_race, "race", false, "enable race detector")
|
|
||||||
}
|
|
||||||
flag.StringVar(&spectre, "spectre", spectre, "enable spectre mitigations in `list` (all, index, ret)")
|
|
||||||
if enableTrace {
|
|
||||||
flag.BoolVar(&trace, "t", false, "trace type-checking")
|
|
||||||
}
|
|
||||||
flag.StringVar(&pathPrefix, "trimpath", "", "remove `prefix` from recorded source file paths")
|
|
||||||
flag.BoolVar(&Debug_vlog, "v", false, "increase debug verbosity")
|
|
||||||
flag.BoolVar(&use_writebarrier, "wb", true, "enable write barrier")
|
|
||||||
var flag_shared bool
|
|
||||||
var flag_dynlink bool
|
|
||||||
if supportsDynlink(thearch.LinkArch.Arch) {
|
|
||||||
flag.BoolVar(&flag_shared, "shared", false, "generate code that can be linked into a shared library")
|
|
||||||
flag.BoolVar(&flag_dynlink, "dynlink", false, "support references to Go symbols defined in other shared libraries")
|
|
||||||
flag.BoolVar(&Ctxt.Flag_linkshared, "linkshared", false, "generate code that will be linked against Go shared libraries")
|
|
||||||
}
|
|
||||||
flag.StringVar(&cpuprofile, "cpuprofile", "", "write cpu profile to `file`")
|
|
||||||
flag.StringVar(&memprofile, "memprofile", "", "write memory profile to `file`")
|
|
||||||
flag.Int64Var(&memprofilerate, "memprofilerate", 0, "set runtime.MemProfileRate to `rate`")
|
|
||||||
var goversion string
|
|
||||||
flag.StringVar(&goversion, "goversion", "", "required version of the runtime")
|
|
||||||
var symabisPath string
|
|
||||||
flag.StringVar(&symabisPath, "symabis", "", "read symbol ABIs from `file`")
|
|
||||||
flag.StringVar(&traceprofile, "traceprofile", "", "write an execution trace to `file`")
|
|
||||||
flag.StringVar(&blockprofile, "blockprofile", "", "write block profile to `file`")
|
|
||||||
flag.StringVar(&mutexprofile, "mutexprofile", "", "write mutex profile to `file`")
|
|
||||||
flag.StringVar(&benchfile, "bench", "", "append benchmark times to `file`")
|
|
||||||
flag.BoolVar(&smallFrames, "smallframes", false, "reduce the size limit for stack allocated objects")
|
|
||||||
flag.BoolVar(&Ctxt.UseBASEntries, "dwarfbasentries", Ctxt.UseBASEntries, "use base address selection entries in DWARF")
|
|
||||||
flag.StringVar(&jsonLogOpt, "json", "", "version,destination for JSON compiler/optimizer logging")
|
|
||||||
|
|
||||||
objabi.Flagparse(usage)
|
|
||||||
|
|
||||||
Ctxt.Pkgpath = myimportpath
|
|
||||||
|
|
||||||
for _, f := range strings.Split(spectre, ",") {
|
|
||||||
f = strings.TrimSpace(f)
|
|
||||||
switch f {
|
|
||||||
default:
|
|
||||||
log.Fatalf("unknown setting -spectre=%s", f)
|
|
||||||
case "":
|
|
||||||
// nothing
|
|
||||||
case "all":
|
|
||||||
spectreIndex = true
|
|
||||||
Ctxt.Retpoline = true
|
|
||||||
case "index":
|
|
||||||
spectreIndex = true
|
|
||||||
case "ret":
|
|
||||||
Ctxt.Retpoline = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if spectreIndex {
|
|
||||||
switch objabi.GOARCH {
|
|
||||||
case "amd64":
|
|
||||||
// ok
|
|
||||||
default:
|
|
||||||
log.Fatalf("GOARCH=%s does not support -spectre=index", objabi.GOARCH)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Record flags that affect the build result. (And don't
|
|
||||||
// record flags that don't, since that would cause spurious
|
|
||||||
// changes in the binary.)
|
|
||||||
recordFlags("B", "N", "l", "msan", "race", "shared", "dynlink", "dwarflocationlists", "dwarfbasentries", "smallframes", "spectre")
|
|
||||||
|
|
||||||
if smallFrames {
|
|
||||||
maxStackVarSize = 128 * 1024
|
|
||||||
maxImplicitStackVarSize = 16 * 1024
|
|
||||||
}
|
|
||||||
|
|
||||||
Ctxt.Flag_shared = flag_dynlink || flag_shared
|
|
||||||
Ctxt.Flag_dynlink = flag_dynlink
|
|
||||||
Ctxt.Flag_optimize = Debug.N == 0
|
|
||||||
|
|
||||||
Ctxt.Debugasm = Debug.S
|
|
||||||
Ctxt.Debugvlog = Debug_vlog
|
|
||||||
if flagDWARF {
|
|
||||||
Ctxt.DebugInfo = debuginfo
|
|
||||||
Ctxt.GenAbstractFunc = genAbstractFunc
|
|
||||||
Ctxt.DwFixups = obj.NewDwarfFixupTable(Ctxt)
|
|
||||||
} else {
|
|
||||||
// turn off inline generation if no dwarf at all
|
|
||||||
genDwarfInline = 0
|
|
||||||
Ctxt.Flag_locationlists = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if flag.NArg() < 1 && debugstr != "help" && debugstr != "ssa/help" {
|
|
||||||
usage()
|
|
||||||
}
|
|
||||||
|
|
||||||
if goversion != "" && goversion != runtime.Version() {
|
|
||||||
fmt.Printf("compile: version %q does not match go tool version %q\n", runtime.Version(), goversion)
|
|
||||||
Exit(2)
|
|
||||||
}
|
|
||||||
|
|
||||||
checkLang()
|
|
||||||
|
|
||||||
if symabisPath != "" {
|
|
||||||
readSymABIs(symabisPath, myimportpath)
|
|
||||||
}
|
|
||||||
|
|
||||||
thearch.LinkArch.Init(Ctxt)
|
|
||||||
|
|
||||||
if outfile == "" {
|
|
||||||
p := flag.Arg(0)
|
|
||||||
if i := strings.LastIndex(p, "/"); i >= 0 {
|
|
||||||
p = p[i+1:]
|
|
||||||
}
|
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
if i := strings.LastIndex(p, `\`); i >= 0 {
|
|
||||||
p = p[i+1:]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if i := strings.LastIndex(p, "."); i >= 0 {
|
|
||||||
p = p[:i]
|
|
||||||
}
|
|
||||||
suffix := ".o"
|
|
||||||
if writearchive {
|
|
||||||
suffix = ".a"
|
|
||||||
}
|
|
||||||
outfile = p + suffix
|
|
||||||
}
|
|
||||||
|
|
||||||
startProfile()
|
|
||||||
|
|
||||||
if flag_race && flag_msan {
|
|
||||||
log.Fatal("cannot use both -race and -msan")
|
|
||||||
}
|
|
||||||
if flag_race || flag_msan {
|
|
||||||
// -race and -msan imply -d=checkptr for now.
|
|
||||||
Debug_checkptr = 1
|
|
||||||
}
|
|
||||||
if ispkgin(omit_pkgs) {
|
|
||||||
flag_race = false
|
|
||||||
flag_msan = false
|
|
||||||
}
|
|
||||||
if flag_race {
|
|
||||||
racepkg = types.NewPkg("runtime/race", "")
|
|
||||||
}
|
|
||||||
if flag_msan {
|
|
||||||
msanpkg = types.NewPkg("runtime/msan", "")
|
|
||||||
}
|
|
||||||
if flag_race || flag_msan {
|
|
||||||
instrumenting = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if compiling_runtime && Debug.N != 0 {
|
|
||||||
log.Fatal("cannot disable optimizations while compiling runtime")
|
|
||||||
}
|
|
||||||
if nBackendWorkers < 1 {
|
|
||||||
log.Fatalf("-c must be at least 1, got %d", nBackendWorkers)
|
|
||||||
}
|
|
||||||
if nBackendWorkers > 1 && !concurrentBackendAllowed() {
|
|
||||||
log.Fatalf("cannot use concurrent backend compilation with provided flags; invoked as %v", os.Args)
|
|
||||||
}
|
|
||||||
if Ctxt.Flag_locationlists && len(Ctxt.Arch.DWARFRegisters) == 0 {
|
|
||||||
log.Fatalf("location lists requested but register mapping not available on %v", Ctxt.Arch.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse -d argument
|
|
||||||
if debugstr != "" {
|
|
||||||
Split:
|
|
||||||
for _, name := range strings.Split(debugstr, ",") {
|
|
||||||
if name == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// display help about the -d option itself and quit
|
|
||||||
if name == "help" {
|
|
||||||
fmt.Print(debugHelpHeader)
|
|
||||||
maxLen := len("ssa/help")
|
|
||||||
for _, t := range debugtab {
|
|
||||||
if len(t.name) > maxLen {
|
|
||||||
maxLen = len(t.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, t := range debugtab {
|
|
||||||
fmt.Printf("\t%-*s\t%s\n", maxLen, t.name, t.help)
|
|
||||||
}
|
|
||||||
// ssa options have their own help
|
|
||||||
fmt.Printf("\t%-*s\t%s\n", maxLen, "ssa/help", "print help about SSA debugging")
|
|
||||||
fmt.Print(debugHelpFooter)
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
val, valstring, haveInt := 1, "", true
|
|
||||||
if i := strings.IndexAny(name, "=:"); i >= 0 {
|
|
||||||
var err error
|
|
||||||
name, valstring = name[:i], name[i+1:]
|
|
||||||
val, err = strconv.Atoi(valstring)
|
|
||||||
if err != nil {
|
|
||||||
val, haveInt = 1, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, t := range debugtab {
|
|
||||||
if t.name != name {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
switch vp := t.val.(type) {
|
|
||||||
case nil:
|
|
||||||
// Ignore
|
|
||||||
case *string:
|
|
||||||
*vp = valstring
|
|
||||||
case *int:
|
|
||||||
if !haveInt {
|
|
||||||
log.Fatalf("invalid debug value %v", name)
|
|
||||||
}
|
|
||||||
*vp = val
|
|
||||||
default:
|
|
||||||
panic("bad debugtab type")
|
|
||||||
}
|
|
||||||
continue Split
|
|
||||||
}
|
|
||||||
// special case for ssa for now
|
|
||||||
if strings.HasPrefix(name, "ssa/") {
|
|
||||||
// expect form ssa/phase/flag
|
|
||||||
// e.g. -d=ssa/generic_cse/time
|
|
||||||
// _ in phase name also matches space
|
|
||||||
phase := name[4:]
|
|
||||||
flag := "debug" // default flag is debug
|
|
||||||
if i := strings.Index(phase, "/"); i >= 0 {
|
|
||||||
flag = phase[i+1:]
|
|
||||||
phase = phase[:i]
|
|
||||||
}
|
|
||||||
err := ssa.PhaseOption(phase, flag, val, valstring)
|
|
||||||
if err != "" {
|
|
||||||
log.Fatalf(err)
|
|
||||||
}
|
|
||||||
continue Split
|
|
||||||
}
|
|
||||||
log.Fatalf("unknown debug key -d %s\n", name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if compiling_runtime {
|
|
||||||
// Runtime can't use -d=checkptr, at least not yet.
|
|
||||||
Debug_checkptr = 0
|
|
||||||
|
|
||||||
// Fuzzing the runtime isn't interesting either.
|
|
||||||
Debug_libfuzzer = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// set via a -d flag
|
|
||||||
Ctxt.Debugpcln = Debug_pctab
|
|
||||||
if flagDWARF {
|
|
||||||
dwarf.EnableLogging(Debug_gendwarfinl != 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
if Debug_softfloat != 0 {
|
|
||||||
thearch.SoftFloat = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// enable inlining. for now:
|
|
||||||
// default: inlining on. (Debug.l == 1)
|
|
||||||
// -l: inlining off (Debug.l == 0)
|
|
||||||
// -l=2, -l=3: inlining on again, with extra debugging (Debug.l > 1)
|
|
||||||
if Debug.l <= 1 {
|
|
||||||
Debug.l = 1 - Debug.l
|
|
||||||
}
|
|
||||||
|
|
||||||
if jsonLogOpt != "" { // parse version,destination from json logging optimization.
|
|
||||||
logopt.LogJsonOption(jsonLogOpt)
|
|
||||||
}
|
|
||||||
|
|
||||||
ssaDump = os.Getenv("GOSSAFUNC")
|
ssaDump = os.Getenv("GOSSAFUNC")
|
||||||
ssaDir = os.Getenv("GOSSADIR")
|
ssaDir = os.Getenv("GOSSADIR")
|
||||||
|
|
@ -534,7 +206,7 @@ func Main(archInit func(*Arch)) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trackScopes = flagDWARF
|
trackScopes = Flag.Dwarf
|
||||||
|
|
||||||
Widthptr = thearch.LinkArch.PtrSize
|
Widthptr = thearch.LinkArch.PtrSize
|
||||||
Widthreg = thearch.LinkArch.RegSize
|
Widthreg = thearch.LinkArch.RegSize
|
||||||
|
|
@ -674,7 +346,7 @@ func Main(archInit func(*Arch)) {
|
||||||
ExitIfErrors()
|
ExitIfErrors()
|
||||||
}
|
}
|
||||||
|
|
||||||
if Debug.l != 0 {
|
if Flag.LowerL != 0 {
|
||||||
// Find functions that can be inlined and clone them before walk expands them.
|
// Find functions that can be inlined and clone them before walk expands them.
|
||||||
visitBottomUp(xtop, func(list []*Node, recursive bool) {
|
visitBottomUp(xtop, func(list []*Node, recursive bool) {
|
||||||
numfns := numNonClosures(list)
|
numfns := numNonClosures(list)
|
||||||
|
|
@ -685,7 +357,7 @@ func Main(archInit func(*Arch)) {
|
||||||
// across more than one function.
|
// across more than one function.
|
||||||
caninl(n)
|
caninl(n)
|
||||||
} else {
|
} else {
|
||||||
if Debug.m > 1 {
|
if Flag.LowerM > 1 {
|
||||||
fmt.Printf("%v: cannot inline %v: recursive\n", n.Line(), n.Func.Nname)
|
fmt.Printf("%v: cannot inline %v: recursive\n", n.Line(), n.Func.Nname)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -716,7 +388,7 @@ func Main(archInit func(*Arch)) {
|
||||||
// checking. This must happen before transformclosure.
|
// checking. This must happen before transformclosure.
|
||||||
// We'll do the final check after write barriers are
|
// We'll do the final check after write barriers are
|
||||||
// inserted.
|
// inserted.
|
||||||
if compiling_runtime {
|
if Flag.CompilingRuntime {
|
||||||
nowritebarrierrecCheck = newNowritebarrierrecChecker()
|
nowritebarrierrecCheck = newNowritebarrierrecChecker()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -768,9 +440,9 @@ func Main(archInit func(*Arch)) {
|
||||||
// DWARF inlining gen so as to avoid problems with generated
|
// DWARF inlining gen so as to avoid problems with generated
|
||||||
// method wrappers.
|
// method wrappers.
|
||||||
if Ctxt.DwFixups != nil {
|
if Ctxt.DwFixups != nil {
|
||||||
Ctxt.DwFixups.Finalize(myimportpath, Debug_gendwarfinl != 0)
|
Ctxt.DwFixups.Finalize(Ctxt.Pkgpath, Debug_gendwarfinl != 0)
|
||||||
Ctxt.DwFixups = nil
|
Ctxt.DwFixups = nil
|
||||||
genDwarfInline = 0
|
Flag.GenDwarfInl = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Phase 9: Check external declarations.
|
// Phase 9: Check external declarations.
|
||||||
|
|
@ -790,7 +462,7 @@ func Main(archInit func(*Arch)) {
|
||||||
dumpdata()
|
dumpdata()
|
||||||
Ctxt.NumberSyms()
|
Ctxt.NumberSyms()
|
||||||
dumpobj()
|
dumpobj()
|
||||||
if asmhdr != "" {
|
if Flag.AsmHdr != "" {
|
||||||
dumpasmhdr()
|
dumpasmhdr()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -813,14 +485,14 @@ func Main(archInit func(*Arch)) {
|
||||||
Fatalf("%d uncompiled functions", len(compilequeue))
|
Fatalf("%d uncompiled functions", len(compilequeue))
|
||||||
}
|
}
|
||||||
|
|
||||||
logopt.FlushLoggedOpts(Ctxt, myimportpath)
|
logopt.FlushLoggedOpts(Ctxt, Ctxt.Pkgpath)
|
||||||
ExitIfErrors()
|
ExitIfErrors()
|
||||||
|
|
||||||
flusherrors()
|
flusherrors()
|
||||||
timings.Stop()
|
timings.Stop()
|
||||||
|
|
||||||
if benchfile != "" {
|
if Flag.Bench != "" {
|
||||||
if err := writebench(benchfile); err != nil {
|
if err := writebench(Flag.Bench); err != nil {
|
||||||
log.Fatalf("cannot write benchmark data: %v", err)
|
log.Fatalf("cannot write benchmark data: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -847,7 +519,7 @@ func writebench(filename string) error {
|
||||||
fmt.Fprintln(&buf, "commit:", objabi.Version)
|
fmt.Fprintln(&buf, "commit:", objabi.Version)
|
||||||
fmt.Fprintln(&buf, "goos:", runtime.GOOS)
|
fmt.Fprintln(&buf, "goos:", runtime.GOOS)
|
||||||
fmt.Fprintln(&buf, "goarch:", runtime.GOARCH)
|
fmt.Fprintln(&buf, "goarch:", runtime.GOARCH)
|
||||||
timings.Write(&buf, "BenchmarkCompile:"+myimportpath+":")
|
timings.Write(&buf, "BenchmarkCompile:"+Ctxt.Pkgpath+":")
|
||||||
|
|
||||||
n, err := f.Write(buf.Bytes())
|
n, err := f.Write(buf.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -860,70 +532,6 @@ func writebench(filename string) error {
|
||||||
return f.Close()
|
return f.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
|
||||||
importMap map[string]string
|
|
||||||
packageFile map[string]string // nil means not in use
|
|
||||||
)
|
|
||||||
|
|
||||||
func addImportMap(s string) {
|
|
||||||
if importMap == nil {
|
|
||||||
importMap = make(map[string]string)
|
|
||||||
}
|
|
||||||
if strings.Count(s, "=") != 1 {
|
|
||||||
log.Fatal("-importmap argument must be of the form source=actual")
|
|
||||||
}
|
|
||||||
i := strings.Index(s, "=")
|
|
||||||
source, actual := s[:i], s[i+1:]
|
|
||||||
if source == "" || actual == "" {
|
|
||||||
log.Fatal("-importmap argument must be of the form source=actual; source and actual must be non-empty")
|
|
||||||
}
|
|
||||||
importMap[source] = actual
|
|
||||||
}
|
|
||||||
|
|
||||||
func readImportCfg(file string) {
|
|
||||||
if importMap == nil {
|
|
||||||
importMap = make(map[string]string)
|
|
||||||
}
|
|
||||||
packageFile = map[string]string{}
|
|
||||||
data, err := ioutil.ReadFile(file)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("-importcfg: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for lineNum, line := range strings.Split(string(data), "\n") {
|
|
||||||
lineNum++ // 1-based
|
|
||||||
line = strings.TrimSpace(line)
|
|
||||||
if line == "" || strings.HasPrefix(line, "#") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
var verb, args string
|
|
||||||
if i := strings.Index(line, " "); i < 0 {
|
|
||||||
verb = line
|
|
||||||
} else {
|
|
||||||
verb, args = line[:i], strings.TrimSpace(line[i+1:])
|
|
||||||
}
|
|
||||||
var before, after string
|
|
||||||
if i := strings.Index(args, "="); i >= 0 {
|
|
||||||
before, after = args[:i], args[i+1:]
|
|
||||||
}
|
|
||||||
switch verb {
|
|
||||||
default:
|
|
||||||
log.Fatalf("%s:%d: unknown directive %q", file, lineNum, verb)
|
|
||||||
case "importmap":
|
|
||||||
if before == "" || after == "" {
|
|
||||||
log.Fatalf(`%s:%d: invalid importmap: syntax is "importmap old=new"`, file, lineNum)
|
|
||||||
}
|
|
||||||
importMap[before] = after
|
|
||||||
case "packagefile":
|
|
||||||
if before == "" || after == "" {
|
|
||||||
log.Fatalf(`%s:%d: invalid packagefile: syntax is "packagefile path=filename"`, file, lineNum)
|
|
||||||
}
|
|
||||||
packageFile[before] = after
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// symabiDefs and symabiRefs record the defined and referenced ABIs of
|
// symabiDefs and symabiRefs record the defined and referenced ABIs of
|
||||||
// symbols required by non-Go code. These are keyed by link symbol
|
// symbols required by non-Go code. These are keyed by link symbol
|
||||||
// name, where the local package prefix is always `"".`
|
// name, where the local package prefix is always `"".`
|
||||||
|
|
@ -1009,14 +617,6 @@ func arsize(b *bufio.Reader, name string) int {
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
var idirs []string
|
|
||||||
|
|
||||||
func addidir(dir string) {
|
|
||||||
if dir != "" {
|
|
||||||
idirs = append(idirs, dir)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func isDriveLetter(b byte) bool {
|
func isDriveLetter(b byte) bool {
|
||||||
return 'a' <= b && b <= 'z' || 'A' <= b && b <= 'Z'
|
return 'a' <= b && b <= 'z' || 'A' <= b && b <= 'Z'
|
||||||
}
|
}
|
||||||
|
|
@ -1031,12 +631,12 @@ func islocalname(name string) bool {
|
||||||
|
|
||||||
func findpkg(name string) (file string, ok bool) {
|
func findpkg(name string) (file string, ok bool) {
|
||||||
if islocalname(name) {
|
if islocalname(name) {
|
||||||
if nolocalimports {
|
if Flag.NoLocalImports {
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
if packageFile != nil {
|
if Flag.Cfg.PackageFile != nil {
|
||||||
file, ok = packageFile[name]
|
file, ok = Flag.Cfg.PackageFile[name]
|
||||||
return file, ok
|
return file, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1062,12 +662,12 @@ func findpkg(name string) (file string, ok bool) {
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
if packageFile != nil {
|
if Flag.Cfg.PackageFile != nil {
|
||||||
file, ok = packageFile[name]
|
file, ok = Flag.Cfg.PackageFile[name]
|
||||||
return file, ok
|
return file, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, dir := range idirs {
|
for _, dir := range Flag.Cfg.ImportDirs {
|
||||||
file = fmt.Sprintf("%s/%s.a", dir, name)
|
file = fmt.Sprintf("%s/%s.a", dir, name)
|
||||||
if _, err := os.Stat(file); err == nil {
|
if _, err := os.Stat(file); err == nil {
|
||||||
return file, true
|
return file, true
|
||||||
|
|
@ -1081,13 +681,13 @@ func findpkg(name string) (file string, ok bool) {
|
||||||
if objabi.GOROOT != "" {
|
if objabi.GOROOT != "" {
|
||||||
suffix := ""
|
suffix := ""
|
||||||
suffixsep := ""
|
suffixsep := ""
|
||||||
if flag_installsuffix != "" {
|
if Flag.InstallSuffix != "" {
|
||||||
suffixsep = "_"
|
suffixsep = "_"
|
||||||
suffix = flag_installsuffix
|
suffix = Flag.InstallSuffix
|
||||||
} else if flag_race {
|
} else if Flag.Race {
|
||||||
suffixsep = "_"
|
suffixsep = "_"
|
||||||
suffix = "race"
|
suffix = "race"
|
||||||
} else if flag_msan {
|
} else if Flag.MSan {
|
||||||
suffixsep = "_"
|
suffixsep = "_"
|
||||||
suffix = "msan"
|
suffix = "msan"
|
||||||
}
|
}
|
||||||
|
|
@ -1161,12 +761,12 @@ func importfile(f constant.Value) *types.Pkg {
|
||||||
errorexit()
|
errorexit()
|
||||||
}
|
}
|
||||||
|
|
||||||
if myimportpath != "" && path_ == myimportpath {
|
if Ctxt.Pkgpath != "" && path_ == Ctxt.Pkgpath {
|
||||||
yyerror("import %q while compiling that package (import cycle)", path_)
|
yyerror("import %q while compiling that package (import cycle)", path_)
|
||||||
errorexit()
|
errorexit()
|
||||||
}
|
}
|
||||||
|
|
||||||
if mapped, ok := importMap[path_]; ok {
|
if mapped, ok := Flag.Cfg.ImportMap[path_]; ok {
|
||||||
path_ = mapped
|
path_ = mapped
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1181,8 +781,8 @@ func importfile(f constant.Value) *types.Pkg {
|
||||||
}
|
}
|
||||||
|
|
||||||
prefix := Ctxt.Pathname
|
prefix := Ctxt.Pathname
|
||||||
if localimport != "" {
|
if Flag.D != "" {
|
||||||
prefix = localimport
|
prefix = Flag.D
|
||||||
}
|
}
|
||||||
path_ = path.Join(prefix, path_)
|
path_ = path.Join(prefix, path_)
|
||||||
|
|
||||||
|
|
@ -1308,7 +908,7 @@ func importfile(f constant.Value) *types.Pkg {
|
||||||
}
|
}
|
||||||
|
|
||||||
// assume files move (get installed) so don't record the full path
|
// assume files move (get installed) so don't record the full path
|
||||||
if packageFile != nil {
|
if Flag.Cfg.PackageFile != nil {
|
||||||
// If using a packageFile map, assume path_ can be recorded directly.
|
// If using a packageFile map, assume path_ can be recorded directly.
|
||||||
Ctxt.AddImport(path_, fingerprint)
|
Ctxt.AddImport(path_, fingerprint)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1401,47 +1001,10 @@ func IsAlias(sym *types.Sym) bool {
|
||||||
return sym.Def != nil && asNode(sym.Def).Sym != sym
|
return sym.Def != nil && asNode(sym.Def).Sym != sym
|
||||||
}
|
}
|
||||||
|
|
||||||
// concurrentFlagOk reports whether the current compiler flags
|
|
||||||
// are compatible with concurrent compilation.
|
|
||||||
func concurrentFlagOk() bool {
|
|
||||||
// TODO(rsc): Many of these are fine. Remove them.
|
|
||||||
return Debug.P == 0 &&
|
|
||||||
Debug.E == 0 &&
|
|
||||||
Debug.K == 0 &&
|
|
||||||
Debug.L == 0 &&
|
|
||||||
Debug.h == 0 &&
|
|
||||||
Debug.j == 0 &&
|
|
||||||
Debug.m == 0 &&
|
|
||||||
Debug.r == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func concurrentBackendAllowed() bool {
|
|
||||||
if !concurrentFlagOk() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Debug.S by itself is ok, because all printing occurs
|
|
||||||
// while writing the object file, and that is non-concurrent.
|
|
||||||
// Adding Debug_vlog, however, causes Debug.S to also print
|
|
||||||
// while flushing the plist, which happens concurrently.
|
|
||||||
if Debug_vlog || debugstr != "" || debuglive > 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// TODO: Test and delete this condition.
|
|
||||||
if objabi.Fieldtrack_enabled != 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// TODO: fix races and enable the following flags
|
|
||||||
if Ctxt.Flag_shared || Ctxt.Flag_dynlink || flag_race {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// recordFlags records the specified command-line flags to be placed
|
// recordFlags records the specified command-line flags to be placed
|
||||||
// in the DWARF info.
|
// in the DWARF info.
|
||||||
func recordFlags(flags ...string) {
|
func recordFlags(flags ...string) {
|
||||||
if myimportpath == "" {
|
if Ctxt.Pkgpath == "" {
|
||||||
// We can't record the flags if we don't know what the
|
// We can't record the flags if we don't know what the
|
||||||
// package name is.
|
// package name is.
|
||||||
return
|
return
|
||||||
|
|
@ -1484,7 +1047,7 @@ func recordFlags(flags ...string) {
|
||||||
if cmd.Len() == 0 {
|
if cmd.Len() == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s := Ctxt.Lookup(dwarf.CUInfoPrefix + "producer." + myimportpath)
|
s := Ctxt.Lookup(dwarf.CUInfoPrefix + "producer." + Ctxt.Pkgpath)
|
||||||
s.Type = objabi.SDWARFCUINFO
|
s.Type = objabi.SDWARFCUINFO
|
||||||
// Sometimes (for example when building tests) we can link
|
// Sometimes (for example when building tests) we can link
|
||||||
// together two package main archives. So allow dups.
|
// together two package main archives. So allow dups.
|
||||||
|
|
@ -1496,7 +1059,7 @@ func recordFlags(flags ...string) {
|
||||||
// recordPackageName records the name of the package being
|
// recordPackageName records the name of the package being
|
||||||
// compiled, so that the linker can save it in the compile unit's DIE.
|
// compiled, so that the linker can save it in the compile unit's DIE.
|
||||||
func recordPackageName() {
|
func recordPackageName() {
|
||||||
s := Ctxt.Lookup(dwarf.CUInfoPrefix + "packagename." + myimportpath)
|
s := Ctxt.Lookup(dwarf.CUInfoPrefix + "packagename." + Ctxt.Pkgpath)
|
||||||
s.Type = objabi.SDWARFCUINFO
|
s.Type = objabi.SDWARFCUINFO
|
||||||
// Sometimes (for example when building tests) we can link
|
// Sometimes (for example when building tests) we can link
|
||||||
// together two package main archives. So allow dups.
|
// together two package main archives. So allow dups.
|
||||||
|
|
@ -1505,9 +1068,6 @@ func recordPackageName() {
|
||||||
s.P = []byte(localpkg.Name)
|
s.P = []byte(localpkg.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// flag_lang is the language version we are compiling for, set by the -lang flag.
|
|
||||||
var flag_lang string
|
|
||||||
|
|
||||||
// currentLang returns the current language version.
|
// currentLang returns the current language version.
|
||||||
func currentLang() string {
|
func currentLang() string {
|
||||||
return fmt.Sprintf("go1.%d", goversion.Version)
|
return fmt.Sprintf("go1.%d", goversion.Version)
|
||||||
|
|
@ -1548,23 +1108,23 @@ func langSupported(major, minor int, pkg *types.Pkg) bool {
|
||||||
// checkLang verifies that the -lang flag holds a valid value, and
|
// checkLang verifies that the -lang flag holds a valid value, and
|
||||||
// exits if not. It initializes data used by langSupported.
|
// exits if not. It initializes data used by langSupported.
|
||||||
func checkLang() {
|
func checkLang() {
|
||||||
if flag_lang == "" {
|
if Flag.Lang == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
langWant, err = parseLang(flag_lang)
|
langWant, err = parseLang(Flag.Lang)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("invalid value %q for -lang: %v", flag_lang, err)
|
log.Fatalf("invalid value %q for -lang: %v", Flag.Lang, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if def := currentLang(); flag_lang != def {
|
if def := currentLang(); Flag.Lang != def {
|
||||||
defVers, err := parseLang(def)
|
defVers, err := parseLang(def)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("internal error parsing default lang %q: %v", def, err)
|
log.Fatalf("internal error parsing default lang %q: %v", def, err)
|
||||||
}
|
}
|
||||||
if langWant.major > defVers.major || (langWant.major == defVers.major && langWant.minor > defVers.minor) {
|
if langWant.major > defVers.major || (langWant.major == defVers.major && langWant.minor > defVers.minor) {
|
||||||
log.Fatalf("invalid value %q for -lang: max known version is %q", flag_lang, def)
|
log.Fatalf("invalid value %q for -lang: max known version is %q", Flag.Lang, def)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -118,15 +118,13 @@ func (p *noder) yyerrorpos(pos syntax.Pos, format string, args ...interface{}) {
|
||||||
yyerrorl(p.makeXPos(pos), format, args...)
|
yyerrorl(p.makeXPos(pos), format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
var pathPrefix string
|
|
||||||
|
|
||||||
// TODO(gri) Can we eliminate fileh in favor of absFilename?
|
// TODO(gri) Can we eliminate fileh in favor of absFilename?
|
||||||
func fileh(name string) string {
|
func fileh(name string) string {
|
||||||
return objabi.AbsFile("", name, pathPrefix)
|
return objabi.AbsFile("", name, Flag.TrimPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
func absFilename(name string) string {
|
func absFilename(name string) string {
|
||||||
return objabi.AbsFile(Ctxt.Pathname, name, pathPrefix)
|
return objabi.AbsFile(Ctxt.Pathname, name, Flag.TrimPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// noder transforms package syntax's AST into a Node tree.
|
// noder transforms package syntax's AST into a Node tree.
|
||||||
|
|
@ -269,10 +267,10 @@ func (p *noder) node() {
|
||||||
} else {
|
} else {
|
||||||
// Use the default object symbol name if the
|
// Use the default object symbol name if the
|
||||||
// user didn't provide one.
|
// user didn't provide one.
|
||||||
if myimportpath == "" {
|
if Ctxt.Pkgpath == "" {
|
||||||
p.yyerrorpos(n.pos, "//go:linkname requires linkname argument or -p compiler flag")
|
p.yyerrorpos(n.pos, "//go:linkname requires linkname argument or -p compiler flag")
|
||||||
} else {
|
} else {
|
||||||
s.Linkname = objabi.PathToPrefix(myimportpath) + "." + n.local
|
s.Linkname = objabi.PathToPrefix(Ctxt.Pkgpath) + "." + n.local
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -561,7 +559,7 @@ func (p *noder) funcDecl(fun *syntax.FuncDecl) *Node {
|
||||||
yyerrorl(f.Pos, "can only use //go:noescape with external func implementations")
|
yyerrorl(f.Pos, "can only use //go:noescape with external func implementations")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if pure_go || strings.HasPrefix(f.funcname(), "init.") {
|
if Flag.Complete || strings.HasPrefix(f.funcname(), "init.") {
|
||||||
// Linknamed functions are allowed to have no body. Hopefully
|
// Linknamed functions are allowed to have no body. Hopefully
|
||||||
// the linkname target has a body. See issue 23311.
|
// the linkname target has a body. See issue 23311.
|
||||||
isLinknamed := false
|
isLinknamed := false
|
||||||
|
|
@ -1621,7 +1619,7 @@ func (p *noder) pragma(pos syntax.Pos, blankLine bool, text string, old syntax.P
|
||||||
// For security, we disallow //go:cgo_* directives other
|
// For security, we disallow //go:cgo_* directives other
|
||||||
// than cgo_import_dynamic outside cgo-generated files.
|
// than cgo_import_dynamic outside cgo-generated files.
|
||||||
// Exception: they are allowed in the standard library, for runtime and syscall.
|
// Exception: they are allowed in the standard library, for runtime and syscall.
|
||||||
if !isCgoGeneratedFile(pos) && !compiling_std {
|
if !isCgoGeneratedFile(pos) && !Flag.Std {
|
||||||
p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s only allowed in cgo-generated code", text)})
|
p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s only allowed in cgo-generated code", text)})
|
||||||
}
|
}
|
||||||
p.pragcgo(pos, text)
|
p.pragcgo(pos, text)
|
||||||
|
|
@ -1633,10 +1631,10 @@ func (p *noder) pragma(pos syntax.Pos, blankLine bool, text string, old syntax.P
|
||||||
}
|
}
|
||||||
flag := pragmaFlag(verb)
|
flag := pragmaFlag(verb)
|
||||||
const runtimePragmas = Systemstack | Nowritebarrier | Nowritebarrierrec | Yeswritebarrierrec
|
const runtimePragmas = Systemstack | Nowritebarrier | Nowritebarrierrec | Yeswritebarrierrec
|
||||||
if !compiling_runtime && flag&runtimePragmas != 0 {
|
if !Flag.CompilingRuntime && flag&runtimePragmas != 0 {
|
||||||
p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s only allowed in runtime", verb)})
|
p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s only allowed in runtime", verb)})
|
||||||
}
|
}
|
||||||
if flag == 0 && !allowedStdPragmas[verb] && compiling_std {
|
if flag == 0 && !allowedStdPragmas[verb] && Flag.Std {
|
||||||
p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s is not allowed in the standard library", verb)})
|
p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s is not allowed in the standard library", verb)})
|
||||||
}
|
}
|
||||||
pragma.Flag |= flag
|
pragma.Flag |= flag
|
||||||
|
|
|
||||||
|
|
@ -47,12 +47,12 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
func dumpobj() {
|
func dumpobj() {
|
||||||
if linkobj == "" {
|
if Flag.LinkObj == "" {
|
||||||
dumpobj1(outfile, modeCompilerObj|modeLinkerObj)
|
dumpobj1(Flag.LowerO, modeCompilerObj|modeLinkerObj)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
dumpobj1(outfile, modeCompilerObj)
|
dumpobj1(Flag.LowerO, modeCompilerObj)
|
||||||
dumpobj1(linkobj, modeLinkerObj)
|
dumpobj1(Flag.LinkObj, modeLinkerObj)
|
||||||
}
|
}
|
||||||
|
|
||||||
func dumpobj1(outfile string, mode int) {
|
func dumpobj1(outfile string, mode int) {
|
||||||
|
|
@ -79,8 +79,8 @@ func dumpobj1(outfile string, mode int) {
|
||||||
|
|
||||||
func printObjHeader(bout *bio.Writer) {
|
func printObjHeader(bout *bio.Writer) {
|
||||||
fmt.Fprintf(bout, "go object %s %s %s %s\n", objabi.GOOS, objabi.GOARCH, objabi.Version, objabi.Expstring())
|
fmt.Fprintf(bout, "go object %s %s %s %s\n", objabi.GOOS, objabi.GOARCH, objabi.Version, objabi.Expstring())
|
||||||
if buildid != "" {
|
if Flag.BuildID != "" {
|
||||||
fmt.Fprintf(bout, "build id %q\n", buildid)
|
fmt.Fprintf(bout, "build id %q\n", Flag.BuildID)
|
||||||
}
|
}
|
||||||
if localpkg.Name == "main" {
|
if localpkg.Name == "main" {
|
||||||
fmt.Fprintf(bout, "main\n")
|
fmt.Fprintf(bout, "main\n")
|
||||||
|
|
@ -261,7 +261,7 @@ func dumpGlobalConst(n *Node) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ctxt.DwarfIntConst(myimportpath, n.Sym.Name, typesymname(t), int64Val(t, v))
|
Ctxt.DwarfIntConst(Ctxt.Pkgpath, n.Sym.Name, typesymname(t), int64Val(t, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
func dumpglobls() {
|
func dumpglobls() {
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ type Order struct {
|
||||||
// Order rewrites fn.Nbody to apply the ordering constraints
|
// Order rewrites fn.Nbody to apply the ordering constraints
|
||||||
// described in the comment at the top of the file.
|
// described in the comment at the top of the file.
|
||||||
func order(fn *Node) {
|
func order(fn *Node) {
|
||||||
if Debug.W > 1 {
|
if Flag.W > 1 {
|
||||||
s := fmt.Sprintf("\nbefore order %v", fn.Func.Nname.Sym)
|
s := fmt.Sprintf("\nbefore order %v", fn.Func.Nname.Sym)
|
||||||
dumplist(s, fn.Nbody)
|
dumplist(s, fn.Nbody)
|
||||||
}
|
}
|
||||||
|
|
@ -323,7 +323,7 @@ func (o *Order) stmtList(l Nodes) {
|
||||||
// and rewrites it to:
|
// and rewrites it to:
|
||||||
// m = OMAKESLICECOPY([]T, x, s); nil
|
// m = OMAKESLICECOPY([]T, x, s); nil
|
||||||
func orderMakeSliceCopy(s []*Node) {
|
func orderMakeSliceCopy(s []*Node) {
|
||||||
if Debug.N != 0 || instrumenting {
|
if Flag.N != 0 || instrumenting {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,7 @@ import (
|
||||||
// "Portable" code generation.
|
// "Portable" code generation.
|
||||||
|
|
||||||
var (
|
var (
|
||||||
nBackendWorkers int // number of concurrent backend workers, set by a compiler flag
|
compilequeue []*Node // functions waiting to be compiled
|
||||||
compilequeue []*Node // functions waiting to be compiled
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func emitptrargsmap(fn *Node) {
|
func emitptrargsmap(fn *Node) {
|
||||||
|
|
@ -292,7 +291,7 @@ func compilenow(fn *Node) bool {
|
||||||
if fn.IsMethod() && isInlinableButNotInlined(fn) {
|
if fn.IsMethod() && isInlinableButNotInlined(fn) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return nBackendWorkers == 1 && Debug_compilelater == 0
|
return Flag.LowerC == 1 && Debug_compilelater == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// isInlinableButNotInlined returns true if 'fn' was marked as an
|
// isInlinableButNotInlined returns true if 'fn' was marked as an
|
||||||
|
|
@ -375,8 +374,8 @@ func compileFunctions() {
|
||||||
}
|
}
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
Ctxt.InParallel = true
|
Ctxt.InParallel = true
|
||||||
c := make(chan *Node, nBackendWorkers)
|
c := make(chan *Node, Flag.LowerC)
|
||||||
for i := 0; i < nBackendWorkers; i++ {
|
for i := 0; i < Flag.LowerC; i++ {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(worker int) {
|
go func(worker int) {
|
||||||
for fn := range c {
|
for fn := range c {
|
||||||
|
|
@ -482,7 +481,7 @@ func debuginfo(fnsym *obj.LSym, infosym *obj.LSym, curfn interface{}) ([]dwarf.S
|
||||||
|
|
||||||
scopes := assembleScopes(fnsym, fn, dwarfVars, varScopes)
|
scopes := assembleScopes(fnsym, fn, dwarfVars, varScopes)
|
||||||
var inlcalls dwarf.InlCalls
|
var inlcalls dwarf.InlCalls
|
||||||
if genDwarfInline > 0 {
|
if Flag.GenDwarfInl > 0 {
|
||||||
inlcalls = assembleInlines(fnsym, dwarfVars)
|
inlcalls = assembleInlines(fnsym, dwarfVars)
|
||||||
}
|
}
|
||||||
return scopes, inlcalls
|
return scopes, inlcalls
|
||||||
|
|
@ -552,7 +551,7 @@ func createSimpleVar(fnsym *obj.LSym, n *Node) *dwarf.Var {
|
||||||
typename := dwarf.InfoPrefix + typesymname(n.Type)
|
typename := dwarf.InfoPrefix + typesymname(n.Type)
|
||||||
delete(fnsym.Func().Autot, ngotype(n).Linksym())
|
delete(fnsym.Func().Autot, ngotype(n).Linksym())
|
||||||
inlIndex := 0
|
inlIndex := 0
|
||||||
if genDwarfInline > 1 {
|
if Flag.GenDwarfInl > 1 {
|
||||||
if n.Name.InlFormal() || n.Name.InlLocal() {
|
if n.Name.InlFormal() || n.Name.InlLocal() {
|
||||||
inlIndex = posInlIndex(n.Pos) + 1
|
inlIndex = posInlIndex(n.Pos) + 1
|
||||||
if n.Name.InlFormal() {
|
if n.Name.InlFormal() {
|
||||||
|
|
@ -673,7 +672,7 @@ func createDwarfVars(fnsym *obj.LSym, complexOK bool, fn *Func, apDecls []*Node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inlIndex := 0
|
inlIndex := 0
|
||||||
if genDwarfInline > 1 {
|
if Flag.GenDwarfInl > 1 {
|
||||||
if n.Name.InlFormal() || n.Name.InlLocal() {
|
if n.Name.InlFormal() || n.Name.InlLocal() {
|
||||||
inlIndex = posInlIndex(n.Pos) + 1
|
inlIndex = posInlIndex(n.Pos) + 1
|
||||||
if n.Name.InlFormal() {
|
if n.Name.InlFormal() {
|
||||||
|
|
@ -762,7 +761,7 @@ func createComplexVar(fnsym *obj.LSym, fn *Func, varID ssa.VarID) *dwarf.Var {
|
||||||
delete(fnsym.Func().Autot, gotype)
|
delete(fnsym.Func().Autot, gotype)
|
||||||
typename := dwarf.InfoPrefix + gotype.Name[len("type."):]
|
typename := dwarf.InfoPrefix + gotype.Name[len("type."):]
|
||||||
inlIndex := 0
|
inlIndex := 0
|
||||||
if genDwarfInline > 1 {
|
if Flag.GenDwarfInl > 1 {
|
||||||
if n.Name.InlFormal() || n.Name.InlLocal() {
|
if n.Name.InlFormal() || n.Name.InlLocal() {
|
||||||
inlIndex = posInlIndex(n.Pos) + 1
|
inlIndex = posInlIndex(n.Pos) + 1
|
||||||
if n.Name.InlFormal() {
|
if n.Name.InlFormal() {
|
||||||
|
|
|
||||||
|
|
@ -509,7 +509,7 @@ func allUnsafe(f *ssa.Func) bool {
|
||||||
// go:nosplit functions are similar. Since safe points used to
|
// go:nosplit functions are similar. Since safe points used to
|
||||||
// be coupled with stack checks, go:nosplit often actually
|
// be coupled with stack checks, go:nosplit often actually
|
||||||
// means "no safe points in this function".
|
// means "no safe points in this function".
|
||||||
return compiling_runtime || f.NoSplit
|
return Flag.CompilingRuntime || f.NoSplit
|
||||||
}
|
}
|
||||||
|
|
||||||
// markUnsafePoints finds unsafe points and computes lv.unsafePoints.
|
// markUnsafePoints finds unsafe points and computes lv.unsafePoints.
|
||||||
|
|
@ -966,7 +966,7 @@ func (lv *Liveness) compact(b *ssa.Block) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lv *Liveness) showlive(v *ssa.Value, live bvec) {
|
func (lv *Liveness) showlive(v *ssa.Value, live bvec) {
|
||||||
if debuglive == 0 || lv.fn.funcname() == "init" || strings.HasPrefix(lv.fn.funcname(), ".") {
|
if Flag.Live == 0 || lv.fn.funcname() == "init" || strings.HasPrefix(lv.fn.funcname(), ".") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !(v == nil || v.Op.IsCall()) {
|
if !(v == nil || v.Op.IsCall()) {
|
||||||
|
|
@ -1235,7 +1235,7 @@ func liveness(e *ssafn, f *ssa.Func, pp *Progs) LivenessMap {
|
||||||
lv.prologue()
|
lv.prologue()
|
||||||
lv.solve()
|
lv.solve()
|
||||||
lv.epilogue()
|
lv.epilogue()
|
||||||
if debuglive > 0 {
|
if Flag.Live > 0 {
|
||||||
lv.showlive(nil, lv.stackMaps[0])
|
lv.showlive(nil, lv.stackMaps[0])
|
||||||
for _, b := range f.Blocks {
|
for _, b := range f.Blocks {
|
||||||
for _, val := range b.Values {
|
for _, val := range b.Values {
|
||||||
|
|
@ -1245,7 +1245,7 @@ func liveness(e *ssafn, f *ssa.Func, pp *Progs) LivenessMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if debuglive >= 2 {
|
if Flag.Live >= 2 {
|
||||||
lv.printDebug()
|
lv.printDebug()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ func linestr(pos src.XPos) string {
|
||||||
if Ctxt == nil {
|
if Ctxt == nil {
|
||||||
return "???"
|
return "???"
|
||||||
}
|
}
|
||||||
return Ctxt.OutermostPos(pos).Format(Debug.C == 0, Debug.L == 1)
|
return Ctxt.OutermostPos(pos).Format(Flag.C == 0, Flag.L == 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// byPos sorts errors by source position.
|
// byPos sorts errors by source position.
|
||||||
|
|
@ -133,7 +133,7 @@ func yyerrorl(pos src.XPos, format string, args ...interface{}) {
|
||||||
numErrors++
|
numErrors++
|
||||||
|
|
||||||
hcrash()
|
hcrash()
|
||||||
if numErrors >= 10 && Debug.e == 0 {
|
if numErrors >= 10 && Flag.LowerE == 0 {
|
||||||
flusherrors()
|
flusherrors()
|
||||||
fmt.Printf("%v: too many errors\n", linestr(pos))
|
fmt.Printf("%v: too many errors\n", linestr(pos))
|
||||||
errorexit()
|
errorexit()
|
||||||
|
|
@ -142,7 +142,7 @@ func yyerrorl(pos src.XPos, format string, args ...interface{}) {
|
||||||
|
|
||||||
// ErrorfVers reports that a language feature (format, args) requires a later version of Go.
|
// ErrorfVers reports that a language feature (format, args) requires a later version of Go.
|
||||||
func yyerrorv(lang string, format string, args ...interface{}) {
|
func yyerrorv(lang string, format string, args ...interface{}) {
|
||||||
yyerror("%s requires %s or later (-lang was set to %s; check go.mod)", fmt.Sprintf(format, args...), lang, flag_lang)
|
yyerror("%s requires %s or later (-lang was set to %s; check go.mod)", fmt.Sprintf(format, args...), lang, Flag.Lang)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateErrorDot is a clumsy hack that rewrites the last error,
|
// UpdateErrorDot is a clumsy hack that rewrites the last error,
|
||||||
|
|
@ -172,7 +172,7 @@ func Warn(format string, args ...interface{}) {
|
||||||
// to additional output by setting a particular flag.
|
// to additional output by setting a particular flag.
|
||||||
func Warnl(pos src.XPos, format string, args ...interface{}) {
|
func Warnl(pos src.XPos, format string, args ...interface{}) {
|
||||||
addErrorMsg(pos, format, args...)
|
addErrorMsg(pos, format, args...)
|
||||||
if Debug.m != 0 {
|
if Flag.LowerM != 0 {
|
||||||
flusherrors()
|
flusherrors()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -232,10 +232,10 @@ func FatalfAt(pos src.XPos, format string, args ...interface{}) {
|
||||||
|
|
||||||
// hcrash crashes the compiler when -h is set, to find out where a message is generated.
|
// hcrash crashes the compiler when -h is set, to find out where a message is generated.
|
||||||
func hcrash() {
|
func hcrash() {
|
||||||
if Debug.h != 0 {
|
if Flag.LowerH != 0 {
|
||||||
flusherrors()
|
flusherrors()
|
||||||
if outfile != "" {
|
if Flag.LowerO != "" {
|
||||||
os.Remove(outfile)
|
os.Remove(Flag.LowerO)
|
||||||
}
|
}
|
||||||
panic("-h")
|
panic("-h")
|
||||||
}
|
}
|
||||||
|
|
@ -245,8 +245,8 @@ func hcrash() {
|
||||||
// It flushes any pending errors, removes the output file, and exits.
|
// It flushes any pending errors, removes the output file, and exits.
|
||||||
func errorexit() {
|
func errorexit() {
|
||||||
flusherrors()
|
flusherrors()
|
||||||
if outfile != "" {
|
if Flag.LowerO != "" {
|
||||||
os.Remove(outfile)
|
os.Remove(Flag.LowerO)
|
||||||
}
|
}
|
||||||
os.Exit(2)
|
os.Exit(2)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,9 +47,9 @@ var omit_pkgs = []string{
|
||||||
var norace_inst_pkgs = []string{"sync", "sync/atomic"}
|
var norace_inst_pkgs = []string{"sync", "sync/atomic"}
|
||||||
|
|
||||||
func ispkgin(pkgs []string) bool {
|
func ispkgin(pkgs []string) bool {
|
||||||
if myimportpath != "" {
|
if Ctxt.Pkgpath != "" {
|
||||||
for _, p := range pkgs {
|
for _, p := range pkgs {
|
||||||
if myimportpath == p {
|
if Ctxt.Pkgpath == p {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -63,11 +63,11 @@ func instrument(fn *Node) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !flag_race || !ispkgin(norace_inst_pkgs) {
|
if !Flag.Race || !ispkgin(norace_inst_pkgs) {
|
||||||
fn.Func.SetInstrumentBody(true)
|
fn.Func.SetInstrumentBody(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
if flag_race {
|
if Flag.Race {
|
||||||
lno := lineno
|
lno := lineno
|
||||||
lineno = src.NoXPos
|
lineno = src.NoXPos
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -466,7 +466,7 @@ func walkrange(n *Node) *Node {
|
||||||
//
|
//
|
||||||
// where == for keys of map m is reflexive.
|
// where == for keys of map m is reflexive.
|
||||||
func isMapClear(n *Node) bool {
|
func isMapClear(n *Node) bool {
|
||||||
if Debug.N != 0 || instrumenting {
|
if Flag.N != 0 || instrumenting {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -533,7 +533,7 @@ func mapClear(m *Node) *Node {
|
||||||
//
|
//
|
||||||
// Parameters are as in walkrange: "for v1, v2 = range a".
|
// Parameters are as in walkrange: "for v1, v2 = range a".
|
||||||
func arrayClear(n, v1, v2, a *Node) bool {
|
func arrayClear(n, v1, v2, a *Node) bool {
|
||||||
if Debug.N != 0 || instrumenting {
|
if Flag.N != 0 || instrumenting {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -488,14 +488,14 @@ func dimportpath(p *types.Pkg) {
|
||||||
// If we are compiling the runtime package, there are two runtime packages around
|
// If we are compiling the runtime package, there are two runtime packages around
|
||||||
// -- localpkg and Runtimepkg. We don't want to produce import path symbols for
|
// -- localpkg and Runtimepkg. We don't want to produce import path symbols for
|
||||||
// both of them, so just produce one for localpkg.
|
// both of them, so just produce one for localpkg.
|
||||||
if myimportpath == "runtime" && p == Runtimepkg {
|
if Ctxt.Pkgpath == "runtime" && p == Runtimepkg {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
str := p.Path
|
str := p.Path
|
||||||
if p == localpkg {
|
if p == localpkg {
|
||||||
// Note: myimportpath != "", or else dgopkgpath won't call dimportpath.
|
// Note: myimportpath != "", or else dgopkgpath won't call dimportpath.
|
||||||
str = myimportpath
|
str = Ctxt.Pkgpath
|
||||||
}
|
}
|
||||||
|
|
||||||
s := Ctxt.Lookup("type..importpath." + p.Prefix + ".")
|
s := Ctxt.Lookup("type..importpath." + p.Prefix + ".")
|
||||||
|
|
@ -510,7 +510,7 @@ func dgopkgpath(s *obj.LSym, ot int, pkg *types.Pkg) int {
|
||||||
return duintptr(s, ot, 0)
|
return duintptr(s, ot, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
if pkg == localpkg && myimportpath == "" {
|
if pkg == localpkg && Ctxt.Pkgpath == "" {
|
||||||
// If we don't know the full import path of the package being compiled
|
// If we don't know the full import path of the package being compiled
|
||||||
// (i.e. -p was not passed on the compiler command line), emit a reference to
|
// (i.e. -p was not passed on the compiler command line), emit a reference to
|
||||||
// type..importpath.""., which the linker will rewrite using the correct import path.
|
// type..importpath.""., which the linker will rewrite using the correct import path.
|
||||||
|
|
@ -529,7 +529,7 @@ func dgopkgpathOff(s *obj.LSym, ot int, pkg *types.Pkg) int {
|
||||||
if pkg == nil {
|
if pkg == nil {
|
||||||
return duint32(s, ot, 0)
|
return duint32(s, ot, 0)
|
||||||
}
|
}
|
||||||
if pkg == localpkg && myimportpath == "" {
|
if pkg == localpkg && Ctxt.Pkgpath == "" {
|
||||||
// If we don't know the full import path of the package being compiled
|
// If we don't know the full import path of the package being compiled
|
||||||
// (i.e. -p was not passed on the compiler command line), emit a reference to
|
// (i.e. -p was not passed on the compiler command line), emit a reference to
|
||||||
// type..importpath.""., which the linker will rewrite using the correct import path.
|
// type..importpath.""., which the linker will rewrite using the correct import path.
|
||||||
|
|
@ -1158,7 +1158,7 @@ func dtypesym(t *types.Type) *obj.LSym {
|
||||||
dupok = obj.DUPOK
|
dupok = obj.DUPOK
|
||||||
}
|
}
|
||||||
|
|
||||||
if myimportpath != "runtime" || (tbase != types.Types[tbase.Etype] && tbase != types.Bytetype && tbase != types.Runetype && tbase != types.Errortype) { // int, float, etc
|
if Ctxt.Pkgpath != "runtime" || (tbase != types.Types[tbase.Etype] && tbase != types.Bytetype && tbase != types.Runetype && tbase != types.Errortype) { // int, float, etc
|
||||||
// named types from other files are defined only by those files
|
// named types from other files are defined only by those files
|
||||||
if tbase.Sym != nil && tbase.Sym.Pkg != localpkg {
|
if tbase.Sym != nil && tbase.Sym.Pkg != localpkg {
|
||||||
if i, ok := typeSymIdx[tbase]; ok {
|
if i, ok := typeSymIdx[tbase]; ok {
|
||||||
|
|
@ -1613,7 +1613,7 @@ func dumpbasictypes() {
|
||||||
// so this is as good as any.
|
// so this is as good as any.
|
||||||
// another possible choice would be package main,
|
// another possible choice would be package main,
|
||||||
// but using runtime means fewer copies in object files.
|
// but using runtime means fewer copies in object files.
|
||||||
if myimportpath == "runtime" {
|
if Ctxt.Pkgpath == "runtime" {
|
||||||
for i := types.EType(1); i <= TBOOL; i++ {
|
for i := types.EType(1); i <= TBOOL; i++ {
|
||||||
dtypesym(types.NewPtr(types.Types[i]))
|
dtypesym(types.NewPtr(types.Types[i]))
|
||||||
}
|
}
|
||||||
|
|
@ -1629,10 +1629,10 @@ func dumpbasictypes() {
|
||||||
// add paths for runtime and main, which 6l imports implicitly.
|
// add paths for runtime and main, which 6l imports implicitly.
|
||||||
dimportpath(Runtimepkg)
|
dimportpath(Runtimepkg)
|
||||||
|
|
||||||
if flag_race {
|
if Flag.Race {
|
||||||
dimportpath(racepkg)
|
dimportpath(racepkg)
|
||||||
}
|
}
|
||||||
if flag_msan {
|
if Flag.MSan {
|
||||||
dimportpath(msanpkg)
|
dimportpath(msanpkg)
|
||||||
}
|
}
|
||||||
dimportpath(types.NewPkg("main", ""))
|
dimportpath(types.NewPkg("main", ""))
|
||||||
|
|
|
||||||
|
|
@ -255,7 +255,7 @@ func walkselectcases(cases *Nodes) []*Node {
|
||||||
order := temp(types.NewArray(types.Types[TUINT16], 2*int64(ncas)))
|
order := temp(types.NewArray(types.Types[TUINT16], 2*int64(ncas)))
|
||||||
|
|
||||||
var pc0, pcs *Node
|
var pc0, pcs *Node
|
||||||
if flag_race {
|
if Flag.Race {
|
||||||
pcs = temp(types.NewArray(types.Types[TUINTPTR], int64(ncas)))
|
pcs = temp(types.NewArray(types.Types[TUINTPTR], int64(ncas)))
|
||||||
pc0 = typecheck(nod(OADDR, nod(OINDEX, pcs, nodintconst(0)), nil), ctxExpr)
|
pc0 = typecheck(nod(OADDR, nod(OINDEX, pcs, nodintconst(0)), nil), ctxExpr)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -308,7 +308,7 @@ func walkselectcases(cases *Nodes) []*Node {
|
||||||
|
|
||||||
// TODO(mdempsky): There should be a cleaner way to
|
// TODO(mdempsky): There should be a cleaner way to
|
||||||
// handle this.
|
// handle this.
|
||||||
if flag_race {
|
if Flag.Race {
|
||||||
r = mkcall("selectsetpc", nil, nil, nod(OADDR, nod(OINDEX, pcs, nodintconst(int64(i))), nil))
|
r = mkcall("selectsetpc", nil, nil, nod(OADDR, nod(OINDEX, pcs, nodintconst(int64(i))), nil))
|
||||||
init = append(init, r)
|
init = append(init, r)
|
||||||
}
|
}
|
||||||
|
|
@ -331,7 +331,7 @@ func walkselectcases(cases *Nodes) []*Node {
|
||||||
// selv and order are no longer alive after selectgo.
|
// selv and order are no longer alive after selectgo.
|
||||||
init = append(init, nod(OVARKILL, selv, nil))
|
init = append(init, nod(OVARKILL, selv, nil))
|
||||||
init = append(init, nod(OVARKILL, order, nil))
|
init = append(init, nod(OVARKILL, order, nil))
|
||||||
if flag_race {
|
if Flag.Race {
|
||||||
init = append(init, nod(OVARKILL, pcs, nil))
|
init = append(init, nod(OVARKILL, pcs, nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ func (s *InitSchedule) append(n *Node) {
|
||||||
// staticInit adds an initialization statement n to the schedule.
|
// staticInit adds an initialization statement n to the schedule.
|
||||||
func (s *InitSchedule) staticInit(n *Node) {
|
func (s *InitSchedule) staticInit(n *Node) {
|
||||||
if !s.tryStaticInit(n) {
|
if !s.tryStaticInit(n) {
|
||||||
if Debug.P != 0 {
|
if Flag.Percent != 0 {
|
||||||
Dump("nonstatic", n)
|
Dump("nonstatic", n)
|
||||||
}
|
}
|
||||||
s.append(n)
|
s.append(n)
|
||||||
|
|
|
||||||
|
|
@ -60,10 +60,10 @@ func initssaconfig() {
|
||||||
_ = types.NewPtr(types.Types[TINT64]) // *int64
|
_ = types.NewPtr(types.Types[TINT64]) // *int64
|
||||||
_ = types.NewPtr(types.Errortype) // *error
|
_ = types.NewPtr(types.Errortype) // *error
|
||||||
types.NewPtrCacheEnabled = false
|
types.NewPtrCacheEnabled = false
|
||||||
ssaConfig = ssa.NewConfig(thearch.LinkArch.Name, *types_, Ctxt, Debug.N == 0)
|
ssaConfig = ssa.NewConfig(thearch.LinkArch.Name, *types_, Ctxt, Flag.N == 0)
|
||||||
ssaConfig.SoftFloat = thearch.SoftFloat
|
ssaConfig.SoftFloat = thearch.SoftFloat
|
||||||
ssaConfig.Race = flag_race
|
ssaConfig.Race = Flag.Race
|
||||||
ssaCaches = make([]ssa.Cache, nBackendWorkers)
|
ssaCaches = make([]ssa.Cache, Flag.LowerC)
|
||||||
|
|
||||||
// Set up some runtime functions we'll need to call.
|
// Set up some runtime functions we'll need to call.
|
||||||
assertE2I = sysfunc("assertE2I")
|
assertE2I = sysfunc("assertE2I")
|
||||||
|
|
@ -291,7 +291,7 @@ func buildssa(fn *Node, worker int) *ssa.Func {
|
||||||
name := fn.funcname()
|
name := fn.funcname()
|
||||||
printssa := false
|
printssa := false
|
||||||
if ssaDump != "" { // match either a simple name e.g. "(*Reader).Reset", or a package.name e.g. "compress/gzip.(*Reader).Reset"
|
if ssaDump != "" { // match either a simple name e.g. "(*Reader).Reset", or a package.name e.g. "compress/gzip.(*Reader).Reset"
|
||||||
printssa = name == ssaDump || myimportpath+"."+name == ssaDump
|
printssa = name == ssaDump || Ctxt.Pkgpath+"."+name == ssaDump
|
||||||
}
|
}
|
||||||
var astBuf *bytes.Buffer
|
var astBuf *bytes.Buffer
|
||||||
if printssa {
|
if printssa {
|
||||||
|
|
@ -342,7 +342,7 @@ func buildssa(fn *Node, worker int) *ssa.Func {
|
||||||
if printssa {
|
if printssa {
|
||||||
ssaDF := ssaDumpFile
|
ssaDF := ssaDumpFile
|
||||||
if ssaDir != "" {
|
if ssaDir != "" {
|
||||||
ssaDF = filepath.Join(ssaDir, myimportpath+"."+name+".html")
|
ssaDF = filepath.Join(ssaDir, Ctxt.Pkgpath+"."+name+".html")
|
||||||
ssaD := filepath.Dir(ssaDF)
|
ssaD := filepath.Dir(ssaDF)
|
||||||
os.MkdirAll(ssaD, 0755)
|
os.MkdirAll(ssaD, 0755)
|
||||||
}
|
}
|
||||||
|
|
@ -358,7 +358,7 @@ func buildssa(fn *Node, worker int) *ssa.Func {
|
||||||
s.fwdVars = map[*Node]*ssa.Value{}
|
s.fwdVars = map[*Node]*ssa.Value{}
|
||||||
s.startmem = s.entryNewValue0(ssa.OpInitMem, types.TypeMem)
|
s.startmem = s.entryNewValue0(ssa.OpInitMem, types.TypeMem)
|
||||||
|
|
||||||
s.hasOpenDefers = Debug.N == 0 && s.hasdefer && !s.curfn.Func.OpenCodedDeferDisallowed()
|
s.hasOpenDefers = Flag.N == 0 && s.hasdefer && !s.curfn.Func.OpenCodedDeferDisallowed()
|
||||||
switch {
|
switch {
|
||||||
case s.hasOpenDefers && (Ctxt.Flag_shared || Ctxt.Flag_dynlink) && thearch.LinkArch.Name == "386":
|
case s.hasOpenDefers && (Ctxt.Flag_shared || Ctxt.Flag_dynlink) && thearch.LinkArch.Name == "386":
|
||||||
// Don't support open-coded defers for 386 ONLY when using shared
|
// Don't support open-coded defers for 386 ONLY when using shared
|
||||||
|
|
@ -752,7 +752,7 @@ func (s *state) pushLine(line src.XPos) {
|
||||||
// the frontend may emit node with line number missing,
|
// the frontend may emit node with line number missing,
|
||||||
// use the parent line number in this case.
|
// use the parent line number in this case.
|
||||||
line = s.peekPos()
|
line = s.peekPos()
|
||||||
if Debug.K != 0 {
|
if Flag.K != 0 {
|
||||||
Warn("buildssa: unknown position (line 0)")
|
Warn("buildssa: unknown position (line 0)")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -988,13 +988,13 @@ func (s *state) instrument(t *types.Type, addr *ssa.Value, wr bool) {
|
||||||
var fn *obj.LSym
|
var fn *obj.LSym
|
||||||
needWidth := false
|
needWidth := false
|
||||||
|
|
||||||
if flag_msan {
|
if Flag.MSan {
|
||||||
fn = msanread
|
fn = msanread
|
||||||
if wr {
|
if wr {
|
||||||
fn = msanwrite
|
fn = msanwrite
|
||||||
}
|
}
|
||||||
needWidth = true
|
needWidth = true
|
||||||
} else if flag_race && t.NumComponents(types.CountBlankFields) > 1 {
|
} else if Flag.Race && t.NumComponents(types.CountBlankFields) > 1 {
|
||||||
// for composite objects we have to write every address
|
// for composite objects we have to write every address
|
||||||
// because a write might happen to any subobject.
|
// because a write might happen to any subobject.
|
||||||
// composites with only one element don't have subobjects, though.
|
// composites with only one element don't have subobjects, though.
|
||||||
|
|
@ -1003,7 +1003,7 @@ func (s *state) instrument(t *types.Type, addr *ssa.Value, wr bool) {
|
||||||
fn = racewriterange
|
fn = racewriterange
|
||||||
}
|
}
|
||||||
needWidth = true
|
needWidth = true
|
||||||
} else if flag_race {
|
} else if Flag.Race {
|
||||||
// for non-composite objects we can write just the start
|
// for non-composite objects we can write just the start
|
||||||
// address, as any write must write the first byte.
|
// address, as any write must write the first byte.
|
||||||
fn = raceread
|
fn = raceread
|
||||||
|
|
@ -1090,7 +1090,7 @@ func (s *state) stmt(n *Node) {
|
||||||
case OCALLMETH, OCALLINTER:
|
case OCALLMETH, OCALLINTER:
|
||||||
s.callResult(n, callNormal)
|
s.callResult(n, callNormal)
|
||||||
if n.Op == OCALLFUNC && n.Left.Op == ONAME && n.Left.Class() == PFUNC {
|
if n.Op == OCALLFUNC && n.Left.Op == ONAME && n.Left.Class() == PFUNC {
|
||||||
if fn := n.Left.Sym.Name; compiling_runtime && fn == "throw" ||
|
if fn := n.Left.Sym.Name; Flag.CompilingRuntime && fn == "throw" ||
|
||||||
n.Left.Sym.Pkg == Runtimepkg && (fn == "throwinit" || fn == "gopanic" || fn == "panicwrap" || fn == "block" || fn == "panicmakeslicelen" || fn == "panicmakeslicecap") {
|
n.Left.Sym.Pkg == Runtimepkg && (fn == "throwinit" || fn == "gopanic" || fn == "panicwrap" || fn == "block" || fn == "panicmakeslicelen" || fn == "panicmakeslicecap") {
|
||||||
m := s.mem()
|
m := s.mem()
|
||||||
b := s.endBlock()
|
b := s.endBlock()
|
||||||
|
|
@ -1225,7 +1225,7 @@ func (s *state) stmt(n *Node) {
|
||||||
// Check whether we're writing the result of an append back to the same slice.
|
// Check whether we're writing the result of an append back to the same slice.
|
||||||
// If so, we handle it specially to avoid write barriers on the fast
|
// If so, we handle it specially to avoid write barriers on the fast
|
||||||
// (non-growth) path.
|
// (non-growth) path.
|
||||||
if !samesafeexpr(n.Left, rhs.List.First()) || Debug.N != 0 {
|
if !samesafeexpr(n.Left, rhs.List.First()) || Flag.N != 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// If the slice can be SSA'd, it'll be on the stack,
|
// If the slice can be SSA'd, it'll be on the stack,
|
||||||
|
|
@ -4130,9 +4130,9 @@ func findIntrinsic(sym *types.Sym) intrinsicBuilder {
|
||||||
}
|
}
|
||||||
pkg := sym.Pkg.Path
|
pkg := sym.Pkg.Path
|
||||||
if sym.Pkg == localpkg {
|
if sym.Pkg == localpkg {
|
||||||
pkg = myimportpath
|
pkg = Ctxt.Pkgpath
|
||||||
}
|
}
|
||||||
if flag_race && pkg == "sync/atomic" {
|
if Flag.Race && pkg == "sync/atomic" {
|
||||||
// The race detector needs to be able to intercept these calls.
|
// The race detector needs to be able to intercept these calls.
|
||||||
// We can't intrinsify them.
|
// We can't intrinsify them.
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -4930,7 +4930,7 @@ func (s *state) addr(n *Node) *ssa.Value {
|
||||||
// canSSA reports whether n is SSA-able.
|
// canSSA reports whether n is SSA-able.
|
||||||
// n must be an ONAME (or an ODOT sequence with an ONAME base).
|
// n must be an ONAME (or an ODOT sequence with an ONAME base).
|
||||||
func (s *state) canSSA(n *Node) bool {
|
func (s *state) canSSA(n *Node) bool {
|
||||||
if Debug.N != 0 {
|
if Flag.N != 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for n.Op == ODOT || (n.Op == OINDEX && n.Left.Type.IsArray()) {
|
for n.Op == ODOT || (n.Op == OINDEX && n.Left.Type.IsArray()) {
|
||||||
|
|
@ -5041,7 +5041,7 @@ func (s *state) nilCheck(ptr *ssa.Value) {
|
||||||
func (s *state) boundsCheck(idx, len *ssa.Value, kind ssa.BoundsKind, bounded bool) *ssa.Value {
|
func (s *state) boundsCheck(idx, len *ssa.Value, kind ssa.BoundsKind, bounded bool) *ssa.Value {
|
||||||
idx = s.extendIndex(idx, len, kind, bounded)
|
idx = s.extendIndex(idx, len, kind, bounded)
|
||||||
|
|
||||||
if bounded || Debug.B != 0 {
|
if bounded || Flag.B != 0 {
|
||||||
// If bounded or bounds checking is flag-disabled, then no check necessary,
|
// If bounded or bounds checking is flag-disabled, then no check necessary,
|
||||||
// just return the extended index.
|
// just return the extended index.
|
||||||
//
|
//
|
||||||
|
|
@ -5114,7 +5114,7 @@ func (s *state) boundsCheck(idx, len *ssa.Value, kind ssa.BoundsKind, bounded bo
|
||||||
s.startBlock(bNext)
|
s.startBlock(bNext)
|
||||||
|
|
||||||
// In Spectre index mode, apply an appropriate mask to avoid speculative out-of-bounds accesses.
|
// In Spectre index mode, apply an appropriate mask to avoid speculative out-of-bounds accesses.
|
||||||
if spectreIndex {
|
if Flag.Cfg.SpectreIndex {
|
||||||
op := ssa.OpSpectreIndex
|
op := ssa.OpSpectreIndex
|
||||||
if kind != ssa.BoundsIndex && kind != ssa.BoundsIndexU {
|
if kind != ssa.BoundsIndex && kind != ssa.BoundsIndexU {
|
||||||
op = ssa.OpSpectreSliceIndex
|
op = ssa.OpSpectreSliceIndex
|
||||||
|
|
@ -6235,7 +6235,7 @@ func emitStackObjects(e *ssafn, pp *Progs) {
|
||||||
p.To.Name = obj.NAME_EXTERN
|
p.To.Name = obj.NAME_EXTERN
|
||||||
p.To.Sym = x
|
p.To.Sym = x
|
||||||
|
|
||||||
if debuglive != 0 {
|
if Flag.Live != 0 {
|
||||||
for _, v := range vars {
|
for _, v := range vars {
|
||||||
Warnl(v.Pos, "stack object %v %s", v, v.Type.String())
|
Warnl(v.Pos, "stack object %v %s", v, v.Type.String())
|
||||||
}
|
}
|
||||||
|
|
@ -6397,7 +6397,7 @@ func genssa(f *ssa.Func, pp *Progs) {
|
||||||
}
|
}
|
||||||
// Emit control flow instructions for block
|
// Emit control flow instructions for block
|
||||||
var next *ssa.Block
|
var next *ssa.Block
|
||||||
if i < len(f.Blocks)-1 && Debug.N == 0 {
|
if i < len(f.Blocks)-1 && Flag.N == 0 {
|
||||||
// If -N, leave next==nil so every block with successors
|
// If -N, leave next==nil so every block with successors
|
||||||
// ends in a JMP (except call blocks - plive doesn't like
|
// ends in a JMP (except call blocks - plive doesn't like
|
||||||
// select{send,recv} followed by a JMP call). Helps keep
|
// select{send,recv} followed by a JMP call). Helps keep
|
||||||
|
|
@ -6705,7 +6705,7 @@ func (s *state) extendIndex(idx, len *ssa.Value, kind ssa.BoundsKind, bounded bo
|
||||||
} else {
|
} else {
|
||||||
lo = s.newValue1(ssa.OpInt64Lo, types.Types[TUINT], idx)
|
lo = s.newValue1(ssa.OpInt64Lo, types.Types[TUINT], idx)
|
||||||
}
|
}
|
||||||
if bounded || Debug.B != 0 {
|
if bounded || Flag.B != 0 {
|
||||||
return lo
|
return lo
|
||||||
}
|
}
|
||||||
bNext := s.f.NewBlock(ssa.BlockPlain)
|
bNext := s.f.NewBlock(ssa.BlockPlain)
|
||||||
|
|
@ -7117,7 +7117,7 @@ func (e *ssafn) Debug_checknil() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *ssafn) UseWriteBarrier() bool {
|
func (e *ssafn) UseWriteBarrier() bool {
|
||||||
return use_writebarrier
|
return Flag.WB
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *ssafn) Syslook(name string) *obj.LSym {
|
func (e *ssafn) Syslook(name string) *obj.LSym {
|
||||||
|
|
@ -7142,7 +7142,7 @@ func (e *ssafn) SetWBPos(pos src.XPos) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *ssafn) MyImportPath() string {
|
func (e *ssafn) MyImportPath() string {
|
||||||
return myimportpath
|
return Ctxt.Pkgpath
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Node) Typ() *types.Type {
|
func (n *Node) Typ() *types.Type {
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ func hasUniquePos(n *Node) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !n.Pos.IsKnown() {
|
if !n.Pos.IsKnown() {
|
||||||
if Debug.K != 0 {
|
if Flag.K != 0 {
|
||||||
Warn("setlineno: unknown position (line 0)")
|
Warn("setlineno: unknown position (line 0)")
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|
@ -1334,7 +1334,7 @@ func structargs(tl *types.Type, mustname bool) []*Node {
|
||||||
// method - M func (t T)(), a TFIELD type struct
|
// method - M func (t T)(), a TFIELD type struct
|
||||||
// newnam - the eventual mangled name of this function
|
// newnam - the eventual mangled name of this function
|
||||||
func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) {
|
func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) {
|
||||||
if false && Debug.r != 0 {
|
if false && Flag.LowerR != 0 {
|
||||||
fmt.Printf("genwrapper rcvrtype=%v method=%v newnam=%v\n", rcvr, method, newnam)
|
fmt.Printf("genwrapper rcvrtype=%v method=%v newnam=%v\n", rcvr, method, newnam)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1407,7 +1407,7 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) {
|
||||||
fn.Nbody.Append(call)
|
fn.Nbody.Append(call)
|
||||||
}
|
}
|
||||||
|
|
||||||
if false && Debug.r != 0 {
|
if false && Flag.LowerR != 0 {
|
||||||
dumplist("genwrapper body", fn.Nbody)
|
dumplist("genwrapper body", fn.Nbody)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1548,7 +1548,7 @@ func implements(t, iface *types.Type, m, samename **types.Field, ptr *int) bool
|
||||||
// the method does not exist for value types.
|
// the method does not exist for value types.
|
||||||
rcvr := tm.Type.Recv().Type
|
rcvr := tm.Type.Recv().Type
|
||||||
if rcvr.IsPtr() && !t0.IsPtr() && !followptr && !isifacemethod(tm.Type) {
|
if rcvr.IsPtr() && !t0.IsPtr() && !followptr && !isifacemethod(tm.Type) {
|
||||||
if false && Debug.r != 0 {
|
if false && Flag.LowerR != 0 {
|
||||||
yyerror("interface pointer mismatch")
|
yyerror("interface pointer mismatch")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -284,7 +284,7 @@ func (n *Node) Val() constant.Value {
|
||||||
// which must not have been used with SetOpt.
|
// which must not have been used with SetOpt.
|
||||||
func (n *Node) SetVal(v constant.Value) {
|
func (n *Node) SetVal(v constant.Value) {
|
||||||
if n.HasOpt() {
|
if n.HasOpt() {
|
||||||
Debug.h = 1
|
Flag.LowerH = 1
|
||||||
Dump("have Opt", n)
|
Dump("have Opt", n)
|
||||||
Fatalf("have Opt")
|
Fatalf("have Opt")
|
||||||
}
|
}
|
||||||
|
|
@ -314,7 +314,7 @@ func (n *Node) SetOpt(x interface{}) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if n.HasVal() {
|
if n.HasVal() {
|
||||||
Debug.h = 1
|
Flag.LowerH = 1
|
||||||
Dump("have Val", n)
|
Dump("have Val", n)
|
||||||
Fatalf("have Val")
|
Fatalf("have Val")
|
||||||
}
|
}
|
||||||
|
|
@ -367,7 +367,7 @@ func (n *Node) pkgFuncName() string {
|
||||||
}
|
}
|
||||||
pkg := s.Pkg
|
pkg := s.Pkg
|
||||||
|
|
||||||
p := myimportpath
|
p := Ctxt.Pkgpath
|
||||||
if pkg != nil && pkg.Path != "" {
|
if pkg != nil && pkg.Path != "" {
|
||||||
p = pkg.Path
|
p = pkg.Path
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ import (
|
||||||
// To enable tracing support (-t flag), set enableTrace to true.
|
// To enable tracing support (-t flag), set enableTrace to true.
|
||||||
const enableTrace = false
|
const enableTrace = false
|
||||||
|
|
||||||
var trace bool
|
|
||||||
var traceIndent []byte
|
var traceIndent []byte
|
||||||
var skipDowidthForTracing bool
|
var skipDowidthForTracing bool
|
||||||
|
|
||||||
|
|
@ -85,7 +84,7 @@ func resolve(n *Node) (res *Node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// only trace if there's work to do
|
// only trace if there's work to do
|
||||||
if enableTrace && trace {
|
if enableTrace && Flag.LowerT {
|
||||||
defer tracePrint("resolve", n)(&res)
|
defer tracePrint("resolve", n)(&res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -212,7 +211,7 @@ func typecheck(n *Node, top int) (res *Node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// only trace if there's work to do
|
// only trace if there's work to do
|
||||||
if enableTrace && trace {
|
if enableTrace && Flag.LowerT {
|
||||||
defer tracePrint("typecheck", n)(&res)
|
defer tracePrint("typecheck", n)(&res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -326,7 +325,7 @@ func indexlit(n *Node) *Node {
|
||||||
// The result of typecheck1 MUST be assigned back to n, e.g.
|
// The result of typecheck1 MUST be assigned back to n, e.g.
|
||||||
// n.Left = typecheck1(n.Left, top)
|
// n.Left = typecheck1(n.Left, top)
|
||||||
func typecheck1(n *Node, top int) (res *Node) {
|
func typecheck1(n *Node, top int) (res *Node) {
|
||||||
if enableTrace && trace {
|
if enableTrace && Flag.LowerT {
|
||||||
defer tracePrint("typecheck1", n)(&res)
|
defer tracePrint("typecheck1", n)(&res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2359,7 +2358,7 @@ func lookdot1(errnode *Node, s *types.Sym, t *types.Type, fs *types.Fields, dost
|
||||||
// typecheckMethodExpr checks selector expressions (ODOT) where the
|
// typecheckMethodExpr checks selector expressions (ODOT) where the
|
||||||
// base expression is a type expression (OTYPE).
|
// base expression is a type expression (OTYPE).
|
||||||
func typecheckMethodExpr(n *Node) (res *Node) {
|
func typecheckMethodExpr(n *Node) (res *Node) {
|
||||||
if enableTrace && trace {
|
if enableTrace && Flag.LowerT {
|
||||||
defer tracePrint("typecheckMethodExpr", n)(&res)
|
defer tracePrint("typecheckMethodExpr", n)(&res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2797,7 +2796,7 @@ func pushtype(n *Node, t *types.Type) *Node {
|
||||||
// The result of typecheckcomplit MUST be assigned back to n, e.g.
|
// The result of typecheckcomplit MUST be assigned back to n, e.g.
|
||||||
// n.Left = typecheckcomplit(n.Left)
|
// n.Left = typecheckcomplit(n.Left)
|
||||||
func typecheckcomplit(n *Node) (res *Node) {
|
func typecheckcomplit(n *Node) (res *Node) {
|
||||||
if enableTrace && trace {
|
if enableTrace && Flag.LowerT {
|
||||||
defer tracePrint("typecheckcomplit", n)(&res)
|
defer tracePrint("typecheckcomplit", n)(&res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3215,7 +3214,7 @@ func samesafeexpr(l *Node, r *Node) bool {
|
||||||
// if this assignment is the definition of a var on the left side,
|
// if this assignment is the definition of a var on the left side,
|
||||||
// fill in the var's type.
|
// fill in the var's type.
|
||||||
func typecheckas(n *Node) {
|
func typecheckas(n *Node) {
|
||||||
if enableTrace && trace {
|
if enableTrace && Flag.LowerT {
|
||||||
defer tracePrint("typecheckas", n)(nil)
|
defer tracePrint("typecheckas", n)(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3273,7 +3272,7 @@ func checkassignto(src *types.Type, dst *Node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func typecheckas2(n *Node) {
|
func typecheckas2(n *Node) {
|
||||||
if enableTrace && trace {
|
if enableTrace && Flag.LowerT {
|
||||||
defer tracePrint("typecheckas2", n)(nil)
|
defer tracePrint("typecheckas2", n)(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3406,7 +3405,7 @@ out:
|
||||||
|
|
||||||
// type check function definition
|
// type check function definition
|
||||||
func typecheckfunc(n *Node) {
|
func typecheckfunc(n *Node) {
|
||||||
if enableTrace && trace {
|
if enableTrace && Flag.LowerT {
|
||||||
defer tracePrint("typecheckfunc", n)(nil)
|
defer tracePrint("typecheckfunc", n)(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3520,7 +3519,7 @@ func setUnderlying(t, underlying *types.Type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func typecheckdeftype(n *Node) {
|
func typecheckdeftype(n *Node) {
|
||||||
if enableTrace && trace {
|
if enableTrace && Flag.LowerT {
|
||||||
defer tracePrint("typecheckdeftype", n)(nil)
|
defer tracePrint("typecheckdeftype", n)(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3540,7 +3539,7 @@ func typecheckdeftype(n *Node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func typecheckdef(n *Node) {
|
func typecheckdef(n *Node) {
|
||||||
if enableTrace && trace {
|
if enableTrace && Flag.LowerT {
|
||||||
defer tracePrint("typecheckdef", n)(nil)
|
defer tracePrint("typecheckdef", n)(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,18 +32,13 @@ func Exit(code int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
blockprofile string
|
|
||||||
cpuprofile string
|
|
||||||
memprofile string
|
|
||||||
memprofilerate int64
|
memprofilerate int64
|
||||||
traceprofile string
|
|
||||||
traceHandler func(string)
|
traceHandler func(string)
|
||||||
mutexprofile string
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func startProfile() {
|
func startProfile() {
|
||||||
if cpuprofile != "" {
|
if Flag.CPUProfile != "" {
|
||||||
f, err := os.Create(cpuprofile)
|
f, err := os.Create(Flag.CPUProfile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fatalf("%v", err)
|
Fatalf("%v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -52,11 +47,11 @@ func startProfile() {
|
||||||
}
|
}
|
||||||
atExit(pprof.StopCPUProfile)
|
atExit(pprof.StopCPUProfile)
|
||||||
}
|
}
|
||||||
if memprofile != "" {
|
if Flag.MemProfile != "" {
|
||||||
if memprofilerate != 0 {
|
if memprofilerate != 0 {
|
||||||
runtime.MemProfileRate = int(memprofilerate)
|
runtime.MemProfileRate = int(memprofilerate)
|
||||||
}
|
}
|
||||||
f, err := os.Create(memprofile)
|
f, err := os.Create(Flag.MemProfile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fatalf("%v", err)
|
Fatalf("%v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -75,8 +70,8 @@ func startProfile() {
|
||||||
// Not doing memory profiling; disable it entirely.
|
// Not doing memory profiling; disable it entirely.
|
||||||
runtime.MemProfileRate = 0
|
runtime.MemProfileRate = 0
|
||||||
}
|
}
|
||||||
if blockprofile != "" {
|
if Flag.BlockProfile != "" {
|
||||||
f, err := os.Create(blockprofile)
|
f, err := os.Create(Flag.BlockProfile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fatalf("%v", err)
|
Fatalf("%v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -86,8 +81,8 @@ func startProfile() {
|
||||||
f.Close()
|
f.Close()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if mutexprofile != "" {
|
if Flag.MutexProfile != "" {
|
||||||
f, err := os.Create(mutexprofile)
|
f, err := os.Create(Flag.MutexProfile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fatalf("%v", err)
|
Fatalf("%v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -97,7 +92,7 @@ func startProfile() {
|
||||||
f.Close()
|
f.Close()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if traceprofile != "" && traceHandler != nil {
|
if Flag.TraceProfile != "" && traceHandler != nil {
|
||||||
traceHandler(traceprofile)
|
traceHandler(Flag.TraceProfile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ func walk(fn *Node) {
|
||||||
Curfn = fn
|
Curfn = fn
|
||||||
errorsBefore := Errors()
|
errorsBefore := Errors()
|
||||||
|
|
||||||
if Debug.W != 0 {
|
if Flag.W != 0 {
|
||||||
s := fmt.Sprintf("\nbefore walk %v", Curfn.Func.Nname.Sym)
|
s := fmt.Sprintf("\nbefore walk %v", Curfn.Func.Nname.Sym)
|
||||||
dumplist(s, Curfn.Nbody)
|
dumplist(s, Curfn.Nbody)
|
||||||
}
|
}
|
||||||
|
|
@ -66,14 +66,14 @@ func walk(fn *Node) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
walkstmtlist(Curfn.Nbody.Slice())
|
walkstmtlist(Curfn.Nbody.Slice())
|
||||||
if Debug.W != 0 {
|
if Flag.W != 0 {
|
||||||
s := fmt.Sprintf("after walk %v", Curfn.Func.Nname.Sym)
|
s := fmt.Sprintf("after walk %v", Curfn.Func.Nname.Sym)
|
||||||
dumplist(s, Curfn.Nbody)
|
dumplist(s, Curfn.Nbody)
|
||||||
}
|
}
|
||||||
|
|
||||||
zeroResults()
|
zeroResults()
|
||||||
heapmoves()
|
heapmoves()
|
||||||
if Debug.W != 0 && Curfn.Func.Enter.Len() > 0 {
|
if Flag.W != 0 && Curfn.Func.Enter.Len() > 0 {
|
||||||
s := fmt.Sprintf("enter %v", Curfn.Func.Nname.Sym)
|
s := fmt.Sprintf("enter %v", Curfn.Func.Nname.Sym)
|
||||||
dumplist(s, Curfn.Func.Enter)
|
dumplist(s, Curfn.Func.Enter)
|
||||||
}
|
}
|
||||||
|
|
@ -186,7 +186,7 @@ func walkstmt(n *Node) *Node {
|
||||||
case ODCL:
|
case ODCL:
|
||||||
v := n.Left
|
v := n.Left
|
||||||
if v.Class() == PAUTOHEAP {
|
if v.Class() == PAUTOHEAP {
|
||||||
if compiling_runtime {
|
if Flag.CompilingRuntime {
|
||||||
yyerror("%v escapes to heap, not allowed in runtime", v)
|
yyerror("%v escapes to heap, not allowed in runtime", v)
|
||||||
}
|
}
|
||||||
if prealloc[v] == nil {
|
if prealloc[v] == nil {
|
||||||
|
|
@ -439,7 +439,7 @@ func walkexpr(n *Node, init *Nodes) *Node {
|
||||||
|
|
||||||
lno := setlineno(n)
|
lno := setlineno(n)
|
||||||
|
|
||||||
if Debug.w > 1 {
|
if Flag.LowerW > 1 {
|
||||||
Dump("before walk expr", n)
|
Dump("before walk expr", n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1046,7 +1046,7 @@ opswitch:
|
||||||
}
|
}
|
||||||
if t.IsArray() {
|
if t.IsArray() {
|
||||||
n.SetBounded(bounded(r, t.NumElem()))
|
n.SetBounded(bounded(r, t.NumElem()))
|
||||||
if Debug.m != 0 && n.Bounded() && !Isconst(n.Right, constant.Int) {
|
if Flag.LowerM != 0 && n.Bounded() && !Isconst(n.Right, constant.Int) {
|
||||||
Warn("index bounds check elided")
|
Warn("index bounds check elided")
|
||||||
}
|
}
|
||||||
if smallintconst(n.Right) && !n.Bounded() {
|
if smallintconst(n.Right) && !n.Bounded() {
|
||||||
|
|
@ -1054,7 +1054,7 @@ opswitch:
|
||||||
}
|
}
|
||||||
} else if Isconst(n.Left, constant.String) {
|
} else if Isconst(n.Left, constant.String) {
|
||||||
n.SetBounded(bounded(r, int64(len(n.Left.StringVal()))))
|
n.SetBounded(bounded(r, int64(len(n.Left.StringVal()))))
|
||||||
if Debug.m != 0 && n.Bounded() && !Isconst(n.Right, constant.Int) {
|
if Flag.LowerM != 0 && n.Bounded() && !Isconst(n.Right, constant.Int) {
|
||||||
Warn("index bounds check elided")
|
Warn("index bounds check elided")
|
||||||
}
|
}
|
||||||
if smallintconst(n.Right) && !n.Bounded() {
|
if smallintconst(n.Right) && !n.Bounded() {
|
||||||
|
|
@ -1174,7 +1174,7 @@ opswitch:
|
||||||
Fatalf("append outside assignment")
|
Fatalf("append outside assignment")
|
||||||
|
|
||||||
case OCOPY:
|
case OCOPY:
|
||||||
n = copyany(n, init, instrumenting && !compiling_runtime)
|
n = copyany(n, init, instrumenting && !Flag.CompilingRuntime)
|
||||||
|
|
||||||
// cannot use chanfn - closechan takes any, not chan any
|
// cannot use chanfn - closechan takes any, not chan any
|
||||||
case OCLOSE:
|
case OCLOSE:
|
||||||
|
|
@ -1596,7 +1596,7 @@ opswitch:
|
||||||
|
|
||||||
updateHasCall(n)
|
updateHasCall(n)
|
||||||
|
|
||||||
if Debug.w != 0 && n != nil {
|
if Flag.LowerW != 0 && n != nil {
|
||||||
Dump("after walk expr", n)
|
Dump("after walk expr", n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2784,7 +2784,7 @@ func appendslice(n *Node, init *Nodes) *Node {
|
||||||
ptr1, len1 := nptr1.backingArrayPtrLen()
|
ptr1, len1 := nptr1.backingArrayPtrLen()
|
||||||
ptr2, len2 := nptr2.backingArrayPtrLen()
|
ptr2, len2 := nptr2.backingArrayPtrLen()
|
||||||
ncopy = mkcall1(fn, types.Types[TINT], &nodes, typename(elemtype), ptr1, len1, ptr2, len2)
|
ncopy = mkcall1(fn, types.Types[TINT], &nodes, typename(elemtype), ptr1, len1, ptr2, len2)
|
||||||
} else if instrumenting && !compiling_runtime {
|
} else if instrumenting && !Flag.CompilingRuntime {
|
||||||
// rely on runtime to instrument:
|
// rely on runtime to instrument:
|
||||||
// copy(s[len(l1):], l2)
|
// copy(s[len(l1):], l2)
|
||||||
// l2 can be a slice or string.
|
// l2 can be a slice or string.
|
||||||
|
|
@ -2827,7 +2827,7 @@ func appendslice(n *Node, init *Nodes) *Node {
|
||||||
// isAppendOfMake reports whether n is of the form append(x , make([]T, y)...).
|
// isAppendOfMake reports whether n is of the form append(x , make([]T, y)...).
|
||||||
// isAppendOfMake assumes n has already been typechecked.
|
// isAppendOfMake assumes n has already been typechecked.
|
||||||
func isAppendOfMake(n *Node) bool {
|
func isAppendOfMake(n *Node) bool {
|
||||||
if Debug.N != 0 || instrumenting {
|
if Flag.N != 0 || instrumenting {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3036,7 +3036,7 @@ func walkappend(n *Node, init *Nodes, dst *Node) *Node {
|
||||||
|
|
||||||
// General case, with no function calls left as arguments.
|
// General case, with no function calls left as arguments.
|
||||||
// Leave for gen, except that instrumentation requires old form.
|
// Leave for gen, except that instrumentation requires old form.
|
||||||
if !instrumenting || compiling_runtime {
|
if !instrumenting || Flag.CompilingRuntime {
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3991,7 +3991,7 @@ func canMergeLoads() bool {
|
||||||
// isRuneCount reports whether n is of the form len([]rune(string)).
|
// isRuneCount reports whether n is of the form len([]rune(string)).
|
||||||
// These are optimized into a call to runtime.countrunes.
|
// These are optimized into a call to runtime.countrunes.
|
||||||
func isRuneCount(n *Node) bool {
|
func isRuneCount(n *Node) bool {
|
||||||
return Debug.N == 0 && !instrumenting && n.Op == OLEN && n.Left.Op == OSTR2RUNES
|
return Flag.N == 0 && !instrumenting && n.Op == OLEN && n.Left.Op == OSTR2RUNES
|
||||||
}
|
}
|
||||||
|
|
||||||
func walkCheckPtrAlignment(n *Node, init *Nodes, count *Node) *Node {
|
func walkCheckPtrAlignment(n *Node, init *Nodes, count *Node) *Node {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue