// 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" "cmd/internal/telemetry/counter" ) func main() { log.SetFlags(0) log.SetPrefix("asm: ") counter.Open() buildcfg.Check() GOARCH := buildcfg.GOARCH flags.Parse() counter.Inc("asm/invocations") counter.CountFlags("asm/flag:", *flag.CommandLine) 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 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.Debugpcln = flags.DebugFlags.PCTab 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") } // Set macros for GOEXPERIMENTs so we can easily switch // runtime assembly code based on them. if objabi.LookupPkgSpecial(ctxt.Pkgpath).AllowAsmABI { for _, exp := range buildcfg.Experiment.Enabled() { flags.D = append(flags.D, "GOEXPERIMENT_"+exp) } } var ok, diag bool var failedFile string for _, f := range flag.Args() { lexer := lex.NewLexer(f) parser := asm.NewParser(ctxt, architecture, lexer) 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) } } 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) } }