Source file src/cmd/asm/main.go

     1  // Copyright 2014 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package main
     6  
     7  import (
     8  	"bufio"
     9  	"flag"
    10  	"fmt"
    11  	"internal/buildcfg"
    12  	"log"
    13  	"os"
    14  
    15  	"cmd/asm/internal/arch"
    16  	"cmd/asm/internal/asm"
    17  	"cmd/asm/internal/flags"
    18  	"cmd/asm/internal/lex"
    19  
    20  	"cmd/internal/bio"
    21  	"cmd/internal/obj"
    22  	"cmd/internal/objabi"
    23  	"cmd/internal/telemetry/counter"
    24  )
    25  
    26  func main() {
    27  	log.SetFlags(0)
    28  	log.SetPrefix("asm: ")
    29  	counter.Open()
    30  
    31  	buildcfg.Check()
    32  	GOARCH := buildcfg.GOARCH
    33  
    34  	flags.Parse()
    35  	counter.Inc("asm/invocations")
    36  	counter.CountFlags("asm/flag:", *flag.CommandLine)
    37  
    38  	architecture := arch.Set(GOARCH, *flags.Shared || *flags.Dynlink)
    39  	if architecture == nil {
    40  		log.Fatalf("unrecognized architecture %s", GOARCH)
    41  	}
    42  	ctxt := obj.Linknew(architecture.LinkArch)
    43  	ctxt.CompressInstructions = flags.DebugFlags.CompressInstructions != 0
    44  	ctxt.Debugasm = flags.PrintOut
    45  	ctxt.Debugvlog = flags.DebugV
    46  	ctxt.Flag_dynlink = *flags.Dynlink
    47  	ctxt.Flag_linkshared = *flags.Linkshared
    48  	ctxt.Flag_shared = *flags.Shared || *flags.Dynlink
    49  	ctxt.Flag_maymorestack = flags.DebugFlags.MayMoreStack
    50  	ctxt.Debugpcln = flags.DebugFlags.PCTab
    51  	ctxt.IsAsm = true
    52  	ctxt.Pkgpath = *flags.Importpath
    53  	ctxt.Std = *flags.Std
    54  	ctxt.DwTextCount = objabi.DummyDwarfFunctionCountForAssembler()
    55  	switch *flags.Spectre {
    56  	default:
    57  		log.Printf("unknown setting -spectre=%s", *flags.Spectre)
    58  		os.Exit(2)
    59  	case "":
    60  		// nothing
    61  	case "index":
    62  		// known to compiler; ignore here so people can use
    63  		// the same list with -gcflags=-spectre=LIST and -asmflags=-spectre=LIST
    64  	case "all", "ret":
    65  		ctxt.Retpoline = true
    66  	}
    67  
    68  	ctxt.Bso = bufio.NewWriter(os.Stdout)
    69  	defer ctxt.Bso.Flush()
    70  
    71  	architecture.Init(ctxt)
    72  
    73  	// Create object file, write header.
    74  	buf, err := bio.Create(*flags.OutputFile)
    75  	if err != nil {
    76  		log.Fatal(err)
    77  	}
    78  	defer buf.Close()
    79  
    80  	if !*flags.SymABIs {
    81  		buf.WriteString(objabi.HeaderString())
    82  		fmt.Fprintf(buf, "!\n")
    83  	}
    84  
    85  	// Set macros for GOEXPERIMENTs so we can easily switch
    86  	// runtime assembly code based on them.
    87  	if objabi.LookupPkgSpecial(ctxt.Pkgpath).AllowAsmABI {
    88  		for _, exp := range buildcfg.Experiment.Enabled() {
    89  			flags.D = append(flags.D, "GOEXPERIMENT_"+exp)
    90  		}
    91  	}
    92  
    93  	var ok, diag bool
    94  	var failedFile string
    95  	for _, f := range flag.Args() {
    96  		lexer := lex.NewLexer(f)
    97  		parser := asm.NewParser(ctxt, architecture, lexer)
    98  		ctxt.DiagFunc = func(format string, args ...any) {
    99  			diag = true
   100  			log.Printf(format, args...)
   101  		}
   102  		if *flags.SymABIs {
   103  			ok = parser.ParseSymABIs(buf)
   104  		} else {
   105  			pList := new(obj.Plist)
   106  			pList.Firstpc, ok = parser.Parse()
   107  			// reports errors to parser.Errorf
   108  			if ok {
   109  				obj.Flushplist(ctxt, pList, nil)
   110  			}
   111  		}
   112  		if !ok {
   113  			failedFile = f
   114  			break
   115  		}
   116  	}
   117  	if ok && !*flags.SymABIs {
   118  		ctxt.NumberSyms()
   119  		obj.WriteObjFile(ctxt, buf)
   120  	}
   121  	if !ok || diag {
   122  		if failedFile != "" {
   123  			log.Printf("assembly of %s failed", failedFile)
   124  		} else {
   125  			log.Print("assembly failed")
   126  		}
   127  		buf.Close()
   128  		os.Remove(*flags.OutputFile)
   129  		os.Exit(1)
   130  	}
   131  }
   132  

View as plain text