github.com/bir3/gocompiler@v0.9.2202/src/cmd/compile/internal/base/flag.go (about) 1 // Copyright 2009 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 base 6 7 import ( 8 "github.com/bir3/gocompiler/src/cmd/internal/cov/covcmd" 9 "encoding/json" 10 "github.com/bir3/gocompiler/src/cmd/compile/flag" 11 "github.com/bir3/gocompiler/src/cmd/compile/flag_objabi" 12 "fmt" 13 "github.com/bir3/gocompiler/src/internal/buildcfg" 14 "github.com/bir3/gocompiler/src/internal/platform" 15 "log" 16 "os" 17 "reflect" 18 "runtime" 19 "strings" 20 21 "github.com/bir3/gocompiler/src/cmd/internal/obj" 22 "github.com/bir3/gocompiler/src/cmd/internal/objabi" 23 "github.com/bir3/gocompiler/src/cmd/internal/sys" 24 ) 25 26 func usage() { 27 fmt.Fprintf(os.Stderr, "usage: compile [options] file.go...\n") 28 flag_objabi.Flagprint(os.Stderr) 29 Exit(2) 30 } 31 32 // Flag holds the parsed command-line flags. 33 // See ParseFlag for non-zero defaults. 34 var Flag CmdFlags 35 36 // A CountFlag is a counting integer flag. 37 // It accepts -name=value to set the value directly, 38 // but it also accepts -name with no =value to increment the count. 39 type CountFlag int 40 41 // CmdFlags defines the command-line flags (see var Flag). 42 // Each struct field is a different flag, by default named for the lower-case of the field name. 43 // If the flag name is a single letter, the default flag name is left upper-case. 44 // If the flag name is "Lower" followed by a single letter, the default flag name is the lower-case of the last letter. 45 // 46 // If this default flag name can't be made right, the `flag` struct tag can be used to replace it, 47 // but this should be done only in exceptional circumstances: it helps everyone if the flag name 48 // is obvious from the field name when the flag is used elsewhere in the compiler sources. 49 // The `flag:"-"` struct tag makes a field invisible to the flag logic and should also be used sparingly. 50 // 51 // Each field must have a `help` struct tag giving the flag help message. 52 // 53 // The allowed field types are bool, int, string, pointers to those (for values stored elsewhere), 54 // CountFlag (for a counting flag), and func(string) (for a flag that uses special code for parsing). 55 type CmdFlags struct { 56 // Single letters 57 B CountFlag "help:\"disable bounds checking\"" 58 C CountFlag "help:\"disable printing of columns in error messages\"" 59 D string "help:\"set relative `path` for local imports\"" 60 E CountFlag "help:\"debug symbol export\"" 61 I func(string) "help:\"add `directory` to import search path\"" 62 K CountFlag "help:\"debug missing line numbers\"" 63 L CountFlag "help:\"also show actual source file names in error messages for positions affected by //line directives\"" 64 N CountFlag "help:\"disable optimizations\"" 65 S CountFlag "help:\"print assembly listing\"" 66 // V is added by flag_objabi.AddVersionFlag 67 W CountFlag "help:\"debug parse tree after type checking\"" 68 69 LowerC int "help:\"concurrency during compilation (1 means no concurrency)\"" 70 LowerD flag.Value "help:\"enable debugging settings; try -d help\"" 71 LowerE CountFlag "help:\"no limit on number of errors reported\"" 72 LowerH CountFlag "help:\"halt on error\"" 73 LowerJ CountFlag "help:\"debug runtime-initialized variables\"" 74 LowerL CountFlag "help:\"disable inlining\"" 75 LowerM CountFlag "help:\"print optimization decisions\"" 76 LowerO string "help:\"write output to `file`\"" 77 LowerP *string "help:\"set expected package import `path`\"" // &Ctxt.Pkgpath, set below 78 LowerR CountFlag "help:\"debug generated wrappers\"" 79 LowerT bool "help:\"enable tracing for debugging the compiler\"" 80 LowerW CountFlag "help:\"debug type checking\"" 81 LowerV *bool "help:\"increase debug verbosity\"" 82 83 // Special characters 84 Percent CountFlag "flag:\"%\" help:\"debug non-static initializers\"" 85 CompilingRuntime bool "flag:\"+\" help:\"compiling runtime\"" 86 87 // Longer names 88 AsmHdr string "help:\"write assembly header to `file`\"" 89 ASan bool "help:\"build code compatible with C/C++ address sanitizer\"" 90 Bench string "help:\"append benchmark times to `file`\"" 91 BlockProfile string "help:\"write block profile to `file`\"" 92 BuildID string "help:\"record `id` as the build id in the export metadata\"" 93 CPUProfile string "help:\"write cpu profile to `file`\"" 94 Complete bool "help:\"compiling complete package (no C or assembly)\"" 95 ClobberDead bool "help:\"clobber dead stack slots (for debugging)\"" 96 ClobberDeadReg bool "help:\"clobber dead registers (for debugging)\"" 97 Dwarf bool "help:\"generate DWARF symbols\"" 98 DwarfBASEntries *bool "help:\"use base address selection entries in DWARF\"" // &Ctxt.UseBASEntries, set below 99 DwarfLocationLists *bool "help:\"add location lists to DWARF in optimized mode\"" // &Ctxt.Flag_locationlists, set below 100 Dynlink *bool "help:\"support references to Go symbols defined in other shared libraries\"" // &Ctxt.Flag_dynlink, set below 101 EmbedCfg func(string) "help:\"read go:embed configuration from `file`\"" 102 Env func(string) "help:\"add `definition` of the form key=value to environment\"" 103 GenDwarfInl int "help:\"generate DWARF inline info records\"" // 0=disabled, 1=funcs, 2=funcs+formals/locals 104 GoVersion string "help:\"required version of the runtime\"" 105 ImportCfg func(string) "help:\"read import configuration from `file`\"" 106 InstallSuffix string "help:\"set pkg directory `suffix`\"" 107 JSON string "help:\"version,file for JSON compiler/optimizer detail output\"" 108 Lang string "help:\"Go language version source code expects\"" 109 LinkObj string "help:\"write linker-specific object to `file`\"" 110 LinkShared *bool "help:\"generate code that will be linked against Go shared libraries\"" // &Ctxt.Flag_linkshared, set below 111 Live CountFlag "help:\"debug liveness analysis\"" 112 MSan bool "help:\"build code compatible with C/C++ memory sanitizer\"" 113 MemProfile string "help:\"write memory profile to `file`\"" 114 MemProfileRate int "help:\"set runtime.MemProfileRate to `rate`\"" 115 MutexProfile string "help:\"write mutex profile to `file`\"" 116 NoLocalImports bool "help:\"reject local (relative) imports\"" 117 CoverageCfg func(string) "help:\"read coverage configuration from `file`\"" 118 Pack bool "help:\"write to file.a instead of file.o\"" 119 Race bool "help:\"enable race detector\"" 120 Shared *bool "help:\"generate code that can be linked into a shared library\"" // &Ctxt.Flag_shared, set below 121 SmallFrames bool "help:\"reduce the size limit for stack allocated objects\"" // small stacks, to diagnose GC latency; see golang.org/issue/27732 122 Spectre string "help:\"enable spectre mitigations in `list` (all, index, ret)\"" 123 Std bool "help:\"compiling standard library\"" 124 SymABIs string "help:\"read symbol ABIs from `file`\"" 125 TraceProfile string "help:\"write an execution trace to `file`\"" 126 TrimPath string "help:\"remove `prefix` from recorded source file paths\"" 127 WB bool "help:\"enable write barrier\"" // TODO: remove 128 PgoProfile string "help:\"read profile from `file`\"" 129 ErrorURL bool "help:\"print explanatory URL with error message if applicable\"" 130 131 // Configuration derived from flags; not a flag itself. 132 Cfg struct { 133 Embed struct { // set by -embedcfg 134 Patterns map[string][]string 135 Files map[string]string 136 } 137 ImportDirs []string // appended to by -I 138 ImportMap map[string]string // set by -importcfg 139 PackageFile map[string]string // set by -importcfg; nil means not in use 140 CoverageInfo *covcmd.CoverFixupConfig // set by -coveragecfg 141 SpectreIndex bool // set by -spectre=index or -spectre=all 142 // Whether we are adding any sort of code instrumentation, such as 143 // when the race detector is enabled. 144 Instrumenting bool 145 } 146 } 147 148 func addEnv(s string) { 149 i := strings.Index(s, "=") 150 if i < 0 { 151 log.Fatal("-env argument must be of the form key=value") 152 } 153 os.Setenv(s[:i], s[i+1:]) 154 } 155 156 // ParseFlags parses the command-line flags into Flag. 157 func ParseFlags() { 158 Flag.I = addImportDir 159 160 Flag.LowerC = runtime.GOMAXPROCS(0) 161 Flag.LowerD = flag_objabi.NewDebugFlag(&Debug, DebugSSA) 162 Flag.LowerP = &Ctxt.Pkgpath 163 Flag.LowerV = &Ctxt.Debugvlog 164 165 Flag.Dwarf = buildcfg.GOARCH != "wasm" 166 Flag.DwarfBASEntries = &Ctxt.UseBASEntries 167 Flag.DwarfLocationLists = &Ctxt.Flag_locationlists 168 *Flag.DwarfLocationLists = true 169 Flag.Dynlink = &Ctxt.Flag_dynlink 170 Flag.EmbedCfg = readEmbedCfg 171 Flag.Env = addEnv 172 Flag.GenDwarfInl = 2 173 Flag.ImportCfg = readImportCfg 174 Flag.CoverageCfg = readCoverageCfg 175 Flag.LinkShared = &Ctxt.Flag_linkshared 176 Flag.Shared = &Ctxt.Flag_shared 177 Flag.WB = true 178 179 Debug.ConcurrentOk = true 180 Debug.MaxShapeLen = 500 181 Debug.InlFuncsWithClosures = 1 182 Debug.InlStaticInit = 1 183 Debug.PGOInline = 1 184 Debug.PGODevirtualize = 2 185 Debug.SyncFrames = -1 // disable sync markers by default 186 Debug.ZeroCopy = 1 187 Debug.RangeFuncCheck = 1 188 189 Debug.Checkptr = -1 // so we can tell whether it is set explicitly 190 191 Flag.Cfg.ImportMap = make(map[string]string) 192 193 flag_objabi.AddVersionFlag() // -V 194 registerFlags() 195 flag_objabi.Flagparse(usage) 196 197 if gcd := os.Getenv("GOCOMPILEDEBUG"); gcd != "" { 198 // This will only override the flags set in gcd; 199 // any others set on the command line remain set. 200 Flag.LowerD.Set(gcd) 201 } 202 203 if Debug.Gossahash != "" { 204 hashDebug = NewHashDebug("gossahash", Debug.Gossahash, nil) 205 } 206 207 // Compute whether we're compiling the runtime from the package path. Test 208 // code can also use the flag to set this explicitly. 209 if Flag.Std && objabi.LookupPkgSpecial(Ctxt.Pkgpath).Runtime { 210 Flag.CompilingRuntime = true 211 } 212 213 // Three inputs govern loop iteration variable rewriting, hash, experiment, flag. 214 // The loop variable rewriting is: 215 // IF non-empty hash, then hash determines behavior (function+line match) (*) 216 // ELSE IF experiment and flag==0, then experiment (set flag=1) 217 // ELSE flag (note that build sets flag per-package), with behaviors: 218 // -1 => no change to behavior. 219 // 0 => no change to behavior (unless non-empty hash, see above) 220 // 1 => apply change to likely-iteration-variable-escaping loops 221 // 2 => apply change, log results 222 // 11 => apply change EVERYWHERE, do not log results (for debugging/benchmarking) 223 // 12 => apply change EVERYWHERE, log results (for debugging/benchmarking) 224 // 225 // The expected uses of the these inputs are, in believed most-likely to least likely: 226 // GOEXPERIMENT=loopvar -- apply change to entire application 227 // -gcflags=some_package=-d=loopvar=1 -- apply change to some_package (**) 228 // -gcflags=some_package=-d=loopvar=2 -- apply change to some_package, log it 229 // GOEXPERIMENT=loopvar -gcflags=some_package=-d=loopvar=-1 -- apply change to all but one package 230 // GOCOMPILEDEBUG=loopvarhash=... -- search for failure cause 231 // 232 // (*) For debugging purposes, providing loopvar flag >= 11 will expand the hash-eligible set of loops to all. 233 // (**) Loop semantics, changed or not, follow code from a package when it is inlined; that is, the behavior 234 // of an application compiled with partially modified loop semantics does not depend on inlining. 235 236 if Debug.LoopVarHash != "" { 237 // This first little bit controls the inputs for debug-hash-matching. 238 mostInlineOnly := true 239 if strings.HasPrefix(Debug.LoopVarHash, "IL") { 240 // When hash-searching on a position that is an inline site, default is to use the 241 // most-inlined position only. This makes the hash faster, plus there's no point 242 // reporting a problem with all the inlining; there's only one copy of the source. 243 // However, if for some reason you wanted it per-site, you can get this. (The default 244 // hash-search behavior for compiler debugging is at an inline site.) 245 Debug.LoopVarHash = Debug.LoopVarHash[2:] 246 mostInlineOnly = false 247 } 248 // end of testing trickiness 249 LoopVarHash = NewHashDebug("loopvarhash", Debug.LoopVarHash, nil) 250 if Debug.LoopVar < 11 { // >= 11 means all loops are rewrite-eligible 251 Debug.LoopVar = 1 // 1 means those loops that syntactically escape their dcl vars are eligible. 252 } 253 LoopVarHash.SetInlineSuffixOnly(mostInlineOnly) 254 } else if buildcfg.Experiment.LoopVar && Debug.LoopVar == 0 { 255 Debug.LoopVar = 1 256 } 257 258 if Debug.Fmahash != "" { 259 FmaHash = NewHashDebug("fmahash", Debug.Fmahash, nil) 260 } 261 if Debug.PGOHash != "" { 262 PGOHash = NewHashDebug("pgohash", Debug.PGOHash, nil) 263 } 264 265 if Flag.MSan && !platform.MSanSupported(buildcfg.GOOS, buildcfg.GOARCH) { 266 log.Fatalf("%s/%s does not support -msan", buildcfg.GOOS, buildcfg.GOARCH) 267 } 268 if Flag.ASan && !platform.ASanSupported(buildcfg.GOOS, buildcfg.GOARCH) { 269 log.Fatalf("%s/%s does not support -asan", buildcfg.GOOS, buildcfg.GOARCH) 270 } 271 if Flag.Race && !platform.RaceDetectorSupported(buildcfg.GOOS, buildcfg.GOARCH) { 272 log.Fatalf("%s/%s does not support -race", buildcfg.GOOS, buildcfg.GOARCH) 273 } 274 if (*Flag.Shared || *Flag.Dynlink || *Flag.LinkShared) && !Ctxt.Arch.InFamily(sys.AMD64, sys.ARM, sys.ARM64, sys.I386, sys.Loong64, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X) { 275 log.Fatalf("%s/%s does not support -shared", buildcfg.GOOS, buildcfg.GOARCH) 276 } 277 parseSpectre(Flag.Spectre) // left as string for RecordFlags 278 279 Ctxt.Flag_shared = Ctxt.Flag_dynlink || Ctxt.Flag_shared 280 Ctxt.Flag_optimize = Flag.N == 0 281 Ctxt.Debugasm = int(Flag.S) 282 Ctxt.Flag_maymorestack = Debug.MayMoreStack 283 Ctxt.Flag_noRefName = Debug.NoRefName != 0 284 285 if flag.NArg() < 1 { 286 usage() 287 } 288 289 if Flag.GoVersion != "" && Flag.GoVersion != runtime.Version() { 290 fmt.Printf("compile: version %q does not match go tool version %q\n", runtime.Version(), Flag.GoVersion) 291 Exit(2) 292 } 293 294 if *Flag.LowerP == "" { 295 *Flag.LowerP = obj.UnlinkablePkg 296 } 297 298 if Flag.LowerO == "" { 299 p := flag.Arg(0) 300 if i := strings.LastIndex(p, "/"); i >= 0 { 301 p = p[i+1:] 302 } 303 if runtime.GOOS == "windows" { 304 if i := strings.LastIndex(p, `\`); i >= 0 { 305 p = p[i+1:] 306 } 307 } 308 if i := strings.LastIndex(p, "."); i >= 0 { 309 p = p[:i] 310 } 311 suffix := ".o" 312 if Flag.Pack { 313 suffix = ".a" 314 } 315 Flag.LowerO = p + suffix 316 } 317 switch { 318 case Flag.Race && Flag.MSan: 319 log.Fatal("cannot use both -race and -msan") 320 case Flag.Race && Flag.ASan: 321 log.Fatal("cannot use both -race and -asan") 322 case Flag.MSan && Flag.ASan: 323 log.Fatal("cannot use both -msan and -asan") 324 } 325 if Flag.Race || Flag.MSan || Flag.ASan { 326 // -race, -msan and -asan imply -d=checkptr for now. 327 if Debug.Checkptr == -1 { // if not set explicitly 328 Debug.Checkptr = 1 329 } 330 } 331 332 if Flag.LowerC < 1 { 333 log.Fatalf("-c must be at least 1, got %d", Flag.LowerC) 334 } 335 if !concurrentBackendAllowed() { 336 Flag.LowerC = 1 337 } 338 339 if Flag.CompilingRuntime { 340 // It is not possible to build the runtime with no optimizations, 341 // because the compiler cannot eliminate enough write barriers. 342 Flag.N = 0 343 Ctxt.Flag_optimize = true 344 345 // Runtime can't use -d=checkptr, at least not yet. 346 Debug.Checkptr = 0 347 348 // Fuzzing the runtime isn't interesting either. 349 Debug.Libfuzzer = 0 350 } 351 352 if Debug.Checkptr == -1 { // if not set explicitly 353 Debug.Checkptr = 0 354 } 355 356 // set via a -d flag 357 Ctxt.Debugpcln = Debug.PCTab 358 } 359 360 // registerFlags adds flag registrations for all the fields in Flag. 361 // See the comment on type CmdFlags for the rules. 362 func registerFlags() { 363 var ( 364 boolType = reflect.TypeOf(bool(false)) 365 intType = reflect.TypeOf(int(0)) 366 stringType = reflect.TypeOf(string("")) 367 ptrBoolType = reflect.TypeOf(new(bool)) 368 ptrIntType = reflect.TypeOf(new(int)) 369 ptrStringType = reflect.TypeOf(new(string)) 370 countType = reflect.TypeOf(CountFlag(0)) 371 funcType = reflect.TypeOf((func(string))(nil)) 372 ) 373 374 v := reflect.ValueOf(&Flag).Elem() 375 t := v.Type() 376 for i := 0; i < t.NumField(); i++ { 377 f := t.Field(i) 378 if f.Name == "Cfg" { 379 continue 380 } 381 382 var name string 383 if len(f.Name) == 1 { 384 name = f.Name 385 } else if len(f.Name) == 6 && f.Name[:5] == "Lower" && 'A' <= f.Name[5] && f.Name[5] <= 'Z' { 386 name = string(rune(f.Name[5] + 'a' - 'A')) 387 } else { 388 name = strings.ToLower(f.Name) 389 } 390 if tag := f.Tag.Get("flag"); tag != "" { 391 name = tag 392 } 393 394 help := f.Tag.Get("help") 395 if help == "" { 396 panic(fmt.Sprintf("base.Flag.%s is missing help text", f.Name)) 397 } 398 399 if k := f.Type.Kind(); (k == reflect.Ptr || k == reflect.Func) && v.Field(i).IsNil() { 400 panic(fmt.Sprintf("base.Flag.%s is uninitialized %v", f.Name, f.Type)) 401 } 402 403 switch f.Type { 404 case boolType: 405 p := v.Field(i).Addr().Interface().(*bool) 406 flag.BoolVar(p, name, *p, help) 407 case intType: 408 p := v.Field(i).Addr().Interface().(*int) 409 flag.IntVar(p, name, *p, help) 410 case stringType: 411 p := v.Field(i).Addr().Interface().(*string) 412 flag.StringVar(p, name, *p, help) 413 case ptrBoolType: 414 p := v.Field(i).Interface().(*bool) 415 flag.BoolVar(p, name, *p, help) 416 case ptrIntType: 417 p := v.Field(i).Interface().(*int) 418 flag.IntVar(p, name, *p, help) 419 case ptrStringType: 420 p := v.Field(i).Interface().(*string) 421 flag.StringVar(p, name, *p, help) 422 case countType: 423 p := (*int)(v.Field(i).Addr().Interface().(*CountFlag)) 424 flag_objabi.Flagcount(name, help, p) 425 case funcType: 426 f := v.Field(i).Interface().(func(string)) 427 flag_objabi.Flagfn1(name, help, f) 428 default: 429 if val, ok := v.Field(i).Interface().(flag.Value); ok { 430 flag.Var(val, name, help) 431 } else { 432 panic(fmt.Sprintf("base.Flag.%s has unexpected type %s", f.Name, f.Type)) 433 } 434 } 435 } 436 } 437 438 // concurrentFlagOk reports whether the current compiler flags 439 // are compatible with concurrent compilation. 440 func concurrentFlagOk() bool { 441 // TODO(rsc): Many of these are fine. Remove them. 442 return Flag.Percent == 0 && 443 Flag.E == 0 && 444 Flag.K == 0 && 445 Flag.L == 0 && 446 Flag.LowerH == 0 && 447 Flag.LowerJ == 0 && 448 Flag.LowerM == 0 && 449 Flag.LowerR == 0 450 } 451 452 func concurrentBackendAllowed() bool { 453 if !concurrentFlagOk() { 454 return false 455 } 456 457 // Debug.S by itself is ok, because all printing occurs 458 // while writing the object file, and that is non-concurrent. 459 // Adding Debug_vlog, however, causes Debug.S to also print 460 // while flushing the plist, which happens concurrently. 461 if Ctxt.Debugvlog || !Debug.ConcurrentOk || Flag.Live > 0 { 462 return false 463 } 464 // TODO: Test and delete this condition. 465 if buildcfg.Experiment.FieldTrack { 466 return false 467 } 468 // TODO: fix races and enable the following flags 469 if Ctxt.Flag_dynlink || Flag.Race { 470 return false 471 } 472 return true 473 } 474 475 func addImportDir(dir string) { 476 if dir != "" { 477 Flag.Cfg.ImportDirs = append(Flag.Cfg.ImportDirs, dir) 478 } 479 } 480 481 func readImportCfg(file string) { 482 if Flag.Cfg.ImportMap == nil { 483 Flag.Cfg.ImportMap = make(map[string]string) 484 } 485 Flag.Cfg.PackageFile = map[string]string{} 486 data, err := os.ReadFile(file) 487 if err != nil { 488 log.Fatalf("-importcfg: %v", err) 489 } 490 491 for lineNum, line := range strings.Split(string(data), "\n") { 492 lineNum++ // 1-based 493 line = strings.TrimSpace(line) 494 if line == "" || strings.HasPrefix(line, "#") { 495 continue 496 } 497 498 verb, args, found := strings.Cut(line, " ") 499 if found { 500 args = strings.TrimSpace(args) 501 } 502 before, after, hasEq := strings.Cut(args, "=") 503 504 switch verb { 505 default: 506 log.Fatalf("%s:%d: unknown directive %q", file, lineNum, verb) 507 case "importmap": 508 if !hasEq || before == "" || after == "" { 509 log.Fatalf(`%s:%d: invalid importmap: syntax is "importmap old=new"`, file, lineNum) 510 } 511 Flag.Cfg.ImportMap[before] = after 512 case "packagefile": 513 if !hasEq || before == "" || after == "" { 514 log.Fatalf(`%s:%d: invalid packagefile: syntax is "packagefile path=filename"`, file, lineNum) 515 } 516 Flag.Cfg.PackageFile[before] = after 517 } 518 } 519 } 520 521 func readCoverageCfg(file string) { 522 var cfg covcmd.CoverFixupConfig 523 data, err := os.ReadFile(file) 524 if err != nil { 525 log.Fatalf("-coveragecfg: %v", err) 526 } 527 if err := json.Unmarshal(data, &cfg); err != nil { 528 log.Fatalf("error reading -coveragecfg file %q: %v", file, err) 529 } 530 Flag.Cfg.CoverageInfo = &cfg 531 } 532 533 func readEmbedCfg(file string) { 534 data, err := os.ReadFile(file) 535 if err != nil { 536 log.Fatalf("-embedcfg: %v", err) 537 } 538 if err := json.Unmarshal(data, &Flag.Cfg.Embed); err != nil { 539 log.Fatalf("%s: %v", file, err) 540 } 541 if Flag.Cfg.Embed.Patterns == nil { 542 log.Fatalf("%s: invalid embedcfg: missing Patterns", file) 543 } 544 if Flag.Cfg.Embed.Files == nil { 545 log.Fatalf("%s: invalid embedcfg: missing Files", file) 546 } 547 } 548 549 // parseSpectre parses the spectre configuration from the string s. 550 func parseSpectre(s string) { 551 for _, f := range strings.Split(s, ",") { 552 f = strings.TrimSpace(f) 553 switch f { 554 default: 555 log.Fatalf("unknown setting -spectre=%s", f) 556 case "": 557 // nothing 558 case "all": 559 Flag.Cfg.SpectreIndex = true 560 Ctxt.Retpoline = true 561 case "index": 562 Flag.Cfg.SpectreIndex = true 563 case "ret": 564 Ctxt.Retpoline = true 565 } 566 } 567 568 if Flag.Cfg.SpectreIndex { 569 switch buildcfg.GOARCH { 570 case "amd64": 571 // ok 572 default: 573 log.Fatalf("GOARCH=%s does not support -spectre=index", buildcfg.GOARCH) 574 } 575 } 576 }