2020-11-16 00:59:30 -05:00
|
|
|
// 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.
|
|
|
|
|
|
2020-11-19 20:49:23 -05:00
|
|
|
package base
|
2020-11-16 00:59:30 -05:00
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"encoding/json"
|
|
|
|
|
"flag"
|
|
|
|
|
"fmt"
|
|
|
|
|
"io/ioutil"
|
|
|
|
|
"log"
|
|
|
|
|
"os"
|
2020-11-16 01:15:33 -05:00
|
|
|
"reflect"
|
2020-11-16 00:59:30 -05:00
|
|
|
"runtime"
|
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
|
|
"cmd/internal/objabi"
|
|
|
|
|
"cmd/internal/sys"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func usage() {
|
|
|
|
|
fmt.Fprintf(os.Stderr, "usage: compile [options] file.go...\n")
|
|
|
|
|
objabi.Flagprint(os.Stderr)
|
|
|
|
|
Exit(2)
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-16 01:15:33 -05:00
|
|
|
// Flag holds the parsed command-line flags.
|
|
|
|
|
// See ParseFlag for non-zero defaults.
|
|
|
|
|
var Flag CmdFlags
|
|
|
|
|
|
|
|
|
|
// A CountFlag is a counting integer flag.
|
|
|
|
|
// It accepts -name=value to set the value directly,
|
|
|
|
|
// but it also accepts -name with no =value to increment the count.
|
|
|
|
|
type CountFlag int
|
|
|
|
|
|
|
|
|
|
// CmdFlags defines the command-line flags (see var Flag).
|
|
|
|
|
// Each struct field is a different flag, by default named for the lower-case of the field name.
|
|
|
|
|
// If the flag name is a single letter, the default flag name is left upper-case.
|
|
|
|
|
// If the flag name is "Lower" followed by a single letter, the default flag name is the lower-case of the last letter.
|
|
|
|
|
//
|
|
|
|
|
// If this default flag name can't be made right, the `flag` struct tag can be used to replace it,
|
|
|
|
|
// but this should be done only in exceptional circumstances: it helps everyone if the flag name
|
|
|
|
|
// is obvious from the field name when the flag is used elsewhere in the compiler sources.
|
|
|
|
|
// The `flag:"-"` struct tag makes a field invisible to the flag logic and should also be used sparingly.
|
|
|
|
|
//
|
|
|
|
|
// Each field must have a `help` struct tag giving the flag help message.
|
|
|
|
|
//
|
|
|
|
|
// The allowed field types are bool, int, string, pointers to those (for values stored elsewhere),
|
|
|
|
|
// CountFlag (for a counting flag), and func(string) (for a flag that uses special code for parsing).
|
|
|
|
|
type CmdFlags struct {
|
|
|
|
|
// Single letters
|
|
|
|
|
B CountFlag "help:\"disable bounds checking\""
|
|
|
|
|
C CountFlag "help:\"disable printing of columns in error messages\""
|
|
|
|
|
D string "help:\"set relative `path` for local imports\""
|
|
|
|
|
E CountFlag "help:\"debug symbol export\""
|
|
|
|
|
I func(string) "help:\"add `directory` to import search path\""
|
|
|
|
|
K CountFlag "help:\"debug missing line numbers\""
|
|
|
|
|
L CountFlag "help:\"show full file names in error messages\""
|
|
|
|
|
N CountFlag "help:\"disable optimizations\""
|
|
|
|
|
S CountFlag "help:\"print assembly listing\""
|
|
|
|
|
// V is added by objabi.AddVersionFlag
|
|
|
|
|
W CountFlag "help:\"debug parse tree after type checking\""
|
|
|
|
|
|
2020-11-16 01:44:47 -05:00
|
|
|
LowerC int "help:\"concurrency during compilation (1 means no concurrency)\""
|
|
|
|
|
LowerD func(string) "help:\"enable debugging settings; try -d help\""
|
|
|
|
|
LowerE CountFlag "help:\"no limit on number of errors reported\""
|
|
|
|
|
LowerH CountFlag "help:\"halt on error\""
|
|
|
|
|
LowerJ CountFlag "help:\"debug runtime-initialized variables\""
|
|
|
|
|
LowerL CountFlag "help:\"disable inlining\""
|
|
|
|
|
LowerM CountFlag "help:\"print optimization decisions\""
|
|
|
|
|
LowerO string "help:\"write output to `file`\""
|
|
|
|
|
LowerP *string "help:\"set expected package import `path`\"" // &Ctxt.Pkgpath, set below
|
|
|
|
|
LowerR CountFlag "help:\"debug generated wrappers\""
|
|
|
|
|
LowerT bool "help:\"enable tracing for debugging the compiler\""
|
|
|
|
|
LowerW CountFlag "help:\"debug type checking\""
|
|
|
|
|
LowerV *bool "help:\"increase debug verbosity\""
|
2020-11-16 01:15:33 -05:00
|
|
|
|
|
|
|
|
// Special characters
|
|
|
|
|
Percent int "flag:\"%\" help:\"debug non-static initializers\""
|
|
|
|
|
CompilingRuntime bool "flag:\"+\" help:\"compiling runtime\""
|
|
|
|
|
|
|
|
|
|
// Longer names
|
|
|
|
|
AsmHdr string "help:\"write assembly header to `file`\""
|
|
|
|
|
Bench string "help:\"append benchmark times to `file`\""
|
|
|
|
|
BlockProfile string "help:\"write block profile to `file`\""
|
|
|
|
|
BuildID string "help:\"record `id` as the build id in the export metadata\""
|
|
|
|
|
CPUProfile string "help:\"write cpu profile to `file`\""
|
|
|
|
|
Complete bool "help:\"compiling complete package (no C or assembly)\""
|
|
|
|
|
Dwarf bool "help:\"generate DWARF symbols\""
|
|
|
|
|
DwarfBASEntries *bool "help:\"use base address selection entries in DWARF\"" // &Ctxt.UseBASEntries, set below
|
|
|
|
|
DwarfLocationLists *bool "help:\"add location lists to DWARF in optimized mode\"" // &Ctxt.Flag_locationlists, set below
|
|
|
|
|
Dynlink *bool "help:\"support references to Go symbols defined in other shared libraries\"" // &Ctxt.Flag_dynlink, set below
|
|
|
|
|
EmbedCfg func(string) "help:\"read go:embed configuration from `file`\""
|
|
|
|
|
GenDwarfInl int "help:\"generate DWARF inline info records\"" // 0=disabled, 1=funcs, 2=funcs+formals/locals
|
|
|
|
|
GoVersion string "help:\"required version of the runtime\""
|
|
|
|
|
ImportCfg func(string) "help:\"read import configuration from `file`\""
|
|
|
|
|
ImportMap func(string) "help:\"add `definition` of the form source=actual to import map\""
|
|
|
|
|
InstallSuffix string "help:\"set pkg directory `suffix`\""
|
|
|
|
|
JSON string "help:\"version,file for JSON compiler/optimizer detail output\""
|
|
|
|
|
Lang string "help:\"Go language version source code expects\""
|
|
|
|
|
LinkObj string "help:\"write linker-specific object to `file`\""
|
|
|
|
|
LinkShared *bool "help:\"generate code that will be linked against Go shared libraries\"" // &Ctxt.Flag_linkshared, set below
|
|
|
|
|
Live CountFlag "help:\"debug liveness analysis\""
|
|
|
|
|
MSan bool "help:\"build code compatible with C/C++ memory sanitizer\""
|
|
|
|
|
MemProfile string "help:\"write memory profile to `file`\""
|
|
|
|
|
MemProfileRate int64 "help:\"set runtime.MemProfileRate to `rate`\""
|
|
|
|
|
MutexProfile string "help:\"write mutex profile to `file`\""
|
|
|
|
|
NoLocalImports bool "help:\"reject local (relative) imports\""
|
|
|
|
|
Pack bool "help:\"write to file.a instead of file.o\""
|
|
|
|
|
Race bool "help:\"enable race detector\""
|
|
|
|
|
Shared *bool "help:\"generate code that can be linked into a shared library\"" // &Ctxt.Flag_shared, set below
|
|
|
|
|
SmallFrames bool "help:\"reduce the size limit for stack allocated objects\"" // small stacks, to diagnose GC latency; see golang.org/issue/27732
|
|
|
|
|
Spectre string "help:\"enable spectre mitigations in `list` (all, index, ret)\""
|
|
|
|
|
Std bool "help:\"compiling standard library\""
|
|
|
|
|
SymABIs string "help:\"read symbol ABIs from `file`\""
|
|
|
|
|
TraceProfile string "help:\"write an execution trace to `file`\""
|
|
|
|
|
TrimPath string "help:\"remove `prefix` from recorded source file paths\""
|
|
|
|
|
WB bool "help:\"enable write barrier\"" // TODO: remove
|
|
|
|
|
|
|
|
|
|
// Configuration derived from flags; not a flag itself.
|
2020-11-16 00:59:30 -05:00
|
|
|
Cfg struct {
|
2020-11-16 01:15:33 -05:00
|
|
|
Embed struct { // set by -embedcfg
|
2020-11-16 00:59:30 -05:00
|
|
|
Patterns map[string][]string
|
|
|
|
|
Files map[string]string
|
|
|
|
|
}
|
2020-11-16 01:15:33 -05:00
|
|
|
ImportDirs []string // appended to by -I
|
|
|
|
|
ImportMap map[string]string // set by -importmap OR -importcfg
|
|
|
|
|
PackageFile map[string]string // set by -importcfg; nil means not in use
|
|
|
|
|
SpectreIndex bool // set by -spectre=index or -spectre=all
|
2020-11-16 00:59:30 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-16 01:15:33 -05:00
|
|
|
// ParseFlags parses the command-line flags into Flag.
|
2020-11-16 00:59:30 -05:00
|
|
|
func ParseFlags() {
|
2020-11-16 01:15:33 -05:00
|
|
|
Flag.I = addImportDir
|
|
|
|
|
|
|
|
|
|
Flag.LowerC = 1
|
2020-11-16 01:44:47 -05:00
|
|
|
Flag.LowerD = parseDebug
|
2020-11-16 01:15:33 -05:00
|
|
|
Flag.LowerP = &Ctxt.Pkgpath
|
|
|
|
|
Flag.LowerV = &Ctxt.Debugvlog
|
|
|
|
|
|
|
|
|
|
Flag.Dwarf = objabi.GOARCH != "wasm"
|
|
|
|
|
Flag.DwarfBASEntries = &Ctxt.UseBASEntries
|
|
|
|
|
Flag.DwarfLocationLists = &Ctxt.Flag_locationlists
|
|
|
|
|
*Flag.DwarfLocationLists = true
|
|
|
|
|
Flag.Dynlink = &Ctxt.Flag_dynlink
|
|
|
|
|
Flag.EmbedCfg = readEmbedCfg
|
|
|
|
|
Flag.GenDwarfInl = 2
|
|
|
|
|
Flag.ImportCfg = readImportCfg
|
|
|
|
|
Flag.ImportMap = addImportMap
|
|
|
|
|
Flag.LinkShared = &Ctxt.Flag_linkshared
|
|
|
|
|
Flag.Shared = &Ctxt.Flag_shared
|
|
|
|
|
Flag.WB = true
|
|
|
|
|
|
|
|
|
|
Flag.Cfg.ImportMap = make(map[string]string)
|
2020-11-16 00:59:30 -05:00
|
|
|
|
2020-11-16 01:15:33 -05:00
|
|
|
objabi.AddVersionFlag() // -V
|
|
|
|
|
registerFlags()
|
2020-11-16 00:59:30 -05:00
|
|
|
objabi.Flagparse(usage)
|
|
|
|
|
|
2020-11-16 01:15:33 -05:00
|
|
|
if Flag.MSan && !sys.MSanSupported(objabi.GOOS, objabi.GOARCH) {
|
|
|
|
|
log.Fatalf("%s/%s does not support -msan", objabi.GOOS, objabi.GOARCH)
|
2020-11-16 00:59:30 -05:00
|
|
|
}
|
2020-11-16 01:15:33 -05:00
|
|
|
if Flag.Race && !sys.RaceDetectorSupported(objabi.GOOS, objabi.GOARCH) {
|
|
|
|
|
log.Fatalf("%s/%s does not support -race", objabi.GOOS, objabi.GOARCH)
|
2020-11-16 00:59:30 -05:00
|
|
|
}
|
2020-11-16 01:15:33 -05:00
|
|
|
if (*Flag.Shared || *Flag.Dynlink || *Flag.LinkShared) && !Ctxt.Arch.InFamily(sys.AMD64, sys.ARM, sys.ARM64, sys.I386, sys.PPC64, sys.RISCV64, sys.S390X) {
|
|
|
|
|
log.Fatalf("%s/%s does not support -shared", objabi.GOOS, objabi.GOARCH)
|
2020-11-16 00:59:30 -05:00
|
|
|
}
|
2020-11-16 01:15:33 -05:00
|
|
|
parseSpectre(Flag.Spectre) // left as string for recordFlags
|
2020-11-16 00:59:30 -05:00
|
|
|
|
2020-11-16 01:15:33 -05:00
|
|
|
Ctxt.Flag_shared = Ctxt.Flag_dynlink || Ctxt.Flag_shared
|
2020-11-16 00:59:30 -05:00
|
|
|
Ctxt.Flag_optimize = Flag.N == 0
|
2020-11-16 01:15:33 -05:00
|
|
|
Ctxt.Debugasm = int(Flag.S)
|
2020-11-16 00:59:30 -05:00
|
|
|
|
2020-11-16 01:44:47 -05:00
|
|
|
if flag.NArg() < 1 {
|
2020-11-16 00:59:30 -05:00
|
|
|
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)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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.
|
2020-11-16 01:17:25 -05:00
|
|
|
Debug.Checkptr = 1
|
2020-11-16 00:59:30 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 Flag.CompilingRuntime {
|
|
|
|
|
// Runtime can't use -d=checkptr, at least not yet.
|
2020-11-16 01:17:25 -05:00
|
|
|
Debug.Checkptr = 0
|
2020-11-16 00:59:30 -05:00
|
|
|
|
|
|
|
|
// Fuzzing the runtime isn't interesting either.
|
2020-11-16 01:17:25 -05:00
|
|
|
Debug.Libfuzzer = 0
|
2020-11-16 00:59:30 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// set via a -d flag
|
2020-11-16 01:17:25 -05:00
|
|
|
Ctxt.Debugpcln = Debug.PCTab
|
2020-11-16 01:15:33 -05:00
|
|
|
}
|
2020-11-16 00:59:30 -05:00
|
|
|
|
2020-11-16 01:15:33 -05:00
|
|
|
// registerFlags adds flag registrations for all the fields in Flag.
|
|
|
|
|
// See the comment on type CmdFlags for the rules.
|
|
|
|
|
func registerFlags() {
|
|
|
|
|
var (
|
|
|
|
|
boolType = reflect.TypeOf(bool(false))
|
|
|
|
|
intType = reflect.TypeOf(int(0))
|
|
|
|
|
stringType = reflect.TypeOf(string(""))
|
|
|
|
|
ptrBoolType = reflect.TypeOf(new(bool))
|
|
|
|
|
ptrIntType = reflect.TypeOf(new(int))
|
|
|
|
|
ptrStringType = reflect.TypeOf(new(string))
|
|
|
|
|
countType = reflect.TypeOf(CountFlag(0))
|
|
|
|
|
funcType = reflect.TypeOf((func(string))(nil))
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
v := reflect.ValueOf(&Flag).Elem()
|
|
|
|
|
t := v.Type()
|
|
|
|
|
for i := 0; i < t.NumField(); i++ {
|
|
|
|
|
f := t.Field(i)
|
|
|
|
|
if f.Name == "Cfg" {
|
|
|
|
|
continue
|
|
|
|
|
}
|
2020-11-16 00:59:30 -05:00
|
|
|
|
2020-11-16 01:15:33 -05:00
|
|
|
var name string
|
|
|
|
|
if len(f.Name) == 1 {
|
|
|
|
|
name = f.Name
|
|
|
|
|
} else if len(f.Name) == 6 && f.Name[:5] == "Lower" && 'A' <= f.Name[5] && f.Name[5] <= 'Z' {
|
|
|
|
|
name = string(rune(f.Name[5] + 'a' - 'A'))
|
|
|
|
|
} else {
|
|
|
|
|
name = strings.ToLower(f.Name)
|
|
|
|
|
}
|
|
|
|
|
if tag := f.Tag.Get("flag"); tag != "" {
|
|
|
|
|
name = tag
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
help := f.Tag.Get("help")
|
|
|
|
|
if help == "" {
|
|
|
|
|
panic(fmt.Sprintf("base.Flag.%s is missing help text", f.Name))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if k := f.Type.Kind(); (k == reflect.Ptr || k == reflect.Func) && v.Field(i).IsNil() {
|
|
|
|
|
panic(fmt.Sprintf("base.Flag.%s is uninitialized %v", f.Name, f.Type))
|
|
|
|
|
}
|
2020-11-16 00:59:30 -05:00
|
|
|
|
2020-11-16 01:15:33 -05:00
|
|
|
switch f.Type {
|
|
|
|
|
case boolType:
|
|
|
|
|
p := v.Field(i).Addr().Interface().(*bool)
|
|
|
|
|
flag.BoolVar(p, name, *p, help)
|
|
|
|
|
case intType:
|
|
|
|
|
p := v.Field(i).Addr().Interface().(*int)
|
|
|
|
|
flag.IntVar(p, name, *p, help)
|
|
|
|
|
case stringType:
|
|
|
|
|
p := v.Field(i).Addr().Interface().(*string)
|
|
|
|
|
flag.StringVar(p, name, *p, help)
|
|
|
|
|
case ptrBoolType:
|
|
|
|
|
p := v.Field(i).Interface().(*bool)
|
|
|
|
|
flag.BoolVar(p, name, *p, help)
|
|
|
|
|
case ptrIntType:
|
|
|
|
|
p := v.Field(i).Interface().(*int)
|
|
|
|
|
flag.IntVar(p, name, *p, help)
|
|
|
|
|
case ptrStringType:
|
|
|
|
|
p := v.Field(i).Interface().(*string)
|
|
|
|
|
flag.StringVar(p, name, *p, help)
|
|
|
|
|
case countType:
|
|
|
|
|
p := (*int)(v.Field(i).Addr().Interface().(*CountFlag))
|
|
|
|
|
objabi.Flagcount(name, help, p)
|
|
|
|
|
case funcType:
|
|
|
|
|
f := v.Field(i).Interface().(func(string))
|
|
|
|
|
objabi.Flagfn1(name, help, f)
|
|
|
|
|
}
|
2020-11-16 00:59:30 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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.
|
2020-11-16 01:44:47 -05:00
|
|
|
if Ctxt.Debugvlog || Debug.Any() || Flag.Live > 0 {
|
2020-11-16 00:59:30 -05:00
|
|
|
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)
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-11-16 01:15:33 -05:00
|
|
|
|
|
|
|
|
// parseSpectre parses the spectre configuration from the string s.
|
|
|
|
|
func parseSpectre(s string) {
|
|
|
|
|
for _, f := range strings.Split(s, ",") {
|
|
|
|
|
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)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|