go/src/cmd/asm/main.go

118 lines
2.5 KiB
Go
Raw Normal View History

// Copyright 2014 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 main
import (
"bufio"
"flag"
"fmt"
"internal/buildcfg"
"log"
"os"
"cmd/asm/internal/arch"
"cmd/asm/internal/asm"
"cmd/asm/internal/flags"
"cmd/asm/internal/lex"
"cmd/internal/bio"
"cmd/internal/obj"
"cmd/internal/objabi"
)
func main() {
log.SetFlags(0)
log.SetPrefix("asm: ")
buildcfg.Check()
GOARCH := buildcfg.GOARCH
flags.Parse()
architecture := arch.Set(GOARCH, *flags.Shared || *flags.Dynlink)
if architecture == nil {
log.Fatalf("unrecognized architecture %s", GOARCH)
}
ctxt := obj.Linknew(architecture.LinkArch)
ctxt.Debugasm = flags.PrintOut
cmd/asm, cmd/link, runtime: introduce FuncInfo flag bits The runtime traceback code has its own definition of which functions mark the top frame of a stack, separate from the TOPFRAME bits that exist in the assembly and are passed along in DWARF information. It's error-prone and redundant to have two different sources of truth. This CL provides the actual TOPFRAME bits to the runtime, so that the runtime can use those bits instead of reinventing its own category. This CL also adds a new bit, SPWRITE, which marks functions that write directly to SP (anything but adding and subtracting constants). Such functions must stop a traceback, because the traceback has no way to rederive the SP on entry. Again, the runtime has its own definition which is mostly correct, but also missing some functions. During ordinary goroutine context switches, such functions do not appear on the stack, so the incompleteness in the runtime usually doesn't matter. But profiling signals can arrive at any moment, and the runtime may crash during traceback if it attempts to unwind an SP-writing frame and gets out-of-sync with the actual stack. The runtime contains code to try to detect likely candidates but again it is incomplete. Deriving the SPWRITE bit automatically from the actual assembly code provides the complete truth, and passing it to the runtime lets the runtime use it. This CL is part of a stack adding windows/arm64 support (#36439), intended to land in the Go 1.17 cycle. This CL is, however, not windows/arm64-specific. It is cleanup meant to make the port (and future ports) easier. Change-Id: I227f53b23ac5b3dabfcc5e8ee3f00df4e113cf58 Reviewed-on: https://go-review.googlesource.com/c/go/+/288800 Trust: Russ Cox <rsc@golang.org> Trust: Jason A. Donenfeld <Jason@zx2c4.com> Reviewed-by: Cherry Zhang <cherryyz@google.com> Reviewed-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-01-28 15:21:33 -05:00
ctxt.Debugvlog = flags.DebugV
ctxt.Flag_dynlink = *flags.Dynlink
ctxt.Flag_linkshared = *flags.Linkshared
ctxt.Flag_shared = *flags.Shared || *flags.Dynlink
ctxt.Flag_maymorestack = flags.DebugFlags.MayMoreStack
ctxt.IsAsm = true
ctxt.Pkgpath = *flags.Importpath
switch *flags.Spectre {
default:
log.Printf("unknown setting -spectre=%s", *flags.Spectre)
os.Exit(2)
case "":
// nothing
case "index":
// known to compiler; ignore here so people can use
// the same list with -gcflags=-spectre=LIST and -asmflags=-spectrre=LIST
case "all", "ret":
ctxt.Retpoline = true
}
ctxt.Bso = bufio.NewWriter(os.Stdout)
defer ctxt.Bso.Flush()
architecture.Init(ctxt)
// Create object file, write header.
buf, err := bio.Create(*flags.OutputFile)
if err != nil {
log.Fatal(err)
}
defer buf.Close()
if !*flags.SymABIs {
buf.WriteString(objabi.HeaderString())
fmt.Fprintf(buf, "!\n")
}
var ok, diag bool
var failedFile string
for _, f := range flag.Args() {
[dev.inline] cmd/internal/src: replace src.Pos with syntax.Pos This replaces the src.Pos LineHist-based position tracking with the syntax.Pos implementation and updates all uses. The LineHist table is not used anymore - the respective code is still there but should be removed eventually. CL forthcoming. Passes toolstash -cmp when comparing to the master repo (with the exception of a couple of swapped assembly instructions, likely due to different instruction scheduling because the line-based sorting has changed; though this is won't affect correctness). The sizes of various important compiler data structures have increased significantly (see the various sizes_test.go files); this is probably the reason for an increase of compilation times (to be addressed). Here are the results of compilebench -count 5, run on a "quiet" machine (no apps running besides a terminal): name old time/op new time/op delta Template 256ms ± 1% 280ms ±15% +9.54% (p=0.008 n=5+5) Unicode 132ms ± 1% 132ms ± 1% ~ (p=0.690 n=5+5) GoTypes 891ms ± 1% 917ms ± 2% +2.88% (p=0.008 n=5+5) Compiler 3.84s ± 2% 3.99s ± 2% +3.95% (p=0.016 n=5+5) MakeBash 47.1s ± 1% 47.2s ± 2% ~ (p=0.841 n=5+5) name old user-ns/op new user-ns/op delta Template 309M ± 1% 326M ± 2% +5.18% (p=0.008 n=5+5) Unicode 165M ± 1% 168M ± 4% ~ (p=0.421 n=5+5) GoTypes 1.14G ± 2% 1.18G ± 1% +3.47% (p=0.008 n=5+5) Compiler 5.00G ± 1% 5.16G ± 1% +3.12% (p=0.008 n=5+5) Change-Id: I241c4246cdff627d7ecb95cac23060b38f9775ec Reviewed-on: https://go-review.googlesource.com/34273 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-12-09 17:15:05 -08:00
lexer := lex.NewLexer(f)
parser := asm.NewParser(ctxt, architecture, lexer,
*flags.CompilingRuntime)
ctxt.DiagFunc = func(format string, args ...interface{}) {
diag = true
log.Printf(format, args...)
}
if *flags.SymABIs {
ok = parser.ParseSymABIs(buf)
} else {
pList := new(obj.Plist)
pList.Firstpc, ok = parser.Parse()
// reports errors to parser.Errorf
if ok {
obj.Flushplist(ctxt, pList, nil, *flags.Importpath)
}
}
if !ok {
failedFile = f
break
}
}
if ok && !*flags.SymABIs {
ctxt.NumberSyms()
obj.WriteObjFile(ctxt, buf)
}
if !ok || diag {
if failedFile != "" {
log.Printf("assembly of %s failed", failedFile)
} else {
log.Print("assembly failed")
}
buf.Close()
os.Remove(*flags.OutputFile)
os.Exit(1)
}
}