util.go raw

   1  // Copyright 2015 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 objabi
   6  
   7  import (
   8  	"fmt"
   9  	"log"
  10  	"os"
  11  	"strings"
  12  )
  13  
  14  func envOr(key, value string) string {
  15  	if x := os.Getenv(key); x != "" {
  16  		return x
  17  	}
  18  	return value
  19  }
  20  
  21  var (
  22  	defaultGOROOT string // set by linker
  23  
  24  	GOROOT   = envOr("GOROOT", defaultGOROOT)
  25  	GOARCH   = envOr("GOARCH", "amd64")
  26  	GOOS     = envOr("GOOS", "linux")
  27  	GO386    = envOr("GO386", "")
  28  	GOAMD64  = goamd64()
  29  	GOARM    = goarm()
  30  	GOMIPS   = gomips()
  31  	GOMIPS64 = gomips64()
  32  	GOPPC64  = goppc64()
  33  	GOWASM   = gowasm()
  34  	GO_LDSO  = ""
  35  	Version  = ""
  36  )
  37  
  38  const (
  39  	ElfRelocOffset   = 256
  40  	MachoRelocOffset = 2048           // reserve enough space for ELF relocations
  41  	Go115AMD64       = "alignedjumps" // Should be "alignedjumps" or "normaljumps"; this replaces environment variable introduced in CL 219357.
  42  )
  43  
  44  // TODO(1.16): assuming no issues in 1.15 release, remove this and related constant.
  45  func goamd64() string {
  46  	return Go115AMD64
  47  }
  48  
  49  func goarm() int {
  50  	switch v := envOr("GOARM", "7"); v {
  51  	case "5":
  52  		return 5
  53  	case "6":
  54  		return 6
  55  	case "7":
  56  		return 7
  57  	}
  58  	// Fail here, rather than validate at multiple call sites.
  59  	log.Fatalf("Invalid GOARM value. Must be 5, 6, or 7.")
  60  	panic("unreachable")
  61  }
  62  
  63  func gomips() string {
  64  	switch v := envOr("GOMIPS", "hardfloat"); v {
  65  	case "hardfloat", "softfloat":
  66  		return v
  67  	}
  68  	log.Fatalf("Invalid GOMIPS value. Must be hardfloat or softfloat.")
  69  	panic("unreachable")
  70  }
  71  
  72  func gomips64() string {
  73  	switch v := envOr("GOMIPS64", "hardfloat"); v {
  74  	case "hardfloat", "softfloat":
  75  		return v
  76  	}
  77  	log.Fatalf("Invalid GOMIPS64 value. Must be hardfloat or softfloat.")
  78  	panic("unreachable")
  79  }
  80  
  81  func goppc64() int {
  82  	switch v := envOr("GOPPC64", "power8"); v {
  83  	case "power8":
  84  		return 8
  85  	case "power9":
  86  		return 9
  87  	}
  88  	log.Fatalf("Invalid GOPPC64 value. Must be power8 or power9.")
  89  	panic("unreachable")
  90  }
  91  
  92  type gowasmFeatures struct {
  93  	SignExt bool
  94  	SatConv bool
  95  }
  96  
  97  func (f gowasmFeatures) String() string {
  98  	var flags []string
  99  	if f.SatConv {
 100  		flags = append(flags, "satconv")
 101  	}
 102  	if f.SignExt {
 103  		flags = append(flags, "signext")
 104  	}
 105  	return strings.Join(flags, ",")
 106  }
 107  
 108  func gowasm() (f gowasmFeatures) {
 109  	for _, opt := range strings.Split(envOr("GOWASM", ""), ",") {
 110  		switch opt {
 111  		case "satconv":
 112  			f.SatConv = true
 113  		case "signext":
 114  			f.SignExt = true
 115  		case "":
 116  			// ignore
 117  		default:
 118  			log.Fatalf("Invalid GOWASM value. No such feature: " + opt)
 119  		}
 120  	}
 121  	return
 122  }
 123  
 124  func Getgoextlinkenabled() string {
 125  	return envOr("GO_EXTLINK_ENABLED", "")
 126  }
 127  
 128  func init() {
 129  	for _, f := range strings.Split("", ",") {
 130  		if f != "" {
 131  			addexp(f)
 132  		}
 133  	}
 134  
 135  	// regabi is only supported on amd64.
 136  	if GOARCH != "amd64" {
 137  		Regabi_enabled = 0
 138  	}
 139  }
 140  
 141  // Note: must agree with runtime.framepointer_enabled.
 142  var Framepointer_enabled = GOARCH == "amd64" || GOARCH == "arm64" && (GOOS == "linux" || GOOS == "darwin")
 143  
 144  func addexp(s string) {
 145  	// Could do general integer parsing here, but the runtime copy doesn't yet.
 146  	v := 1
 147  	name := s
 148  	if len(name) > 2 && name[:2] == "no" {
 149  		v = 0
 150  		name = name[2:]
 151  	}
 152  	for i := 0; i < len(exper); i++ {
 153  		if exper[i].name == name {
 154  			if exper[i].val != nil {
 155  				*exper[i].val = v
 156  			}
 157  			return
 158  		}
 159  	}
 160  
 161  	fmt.Printf("unknown experiment %s\n", s)
 162  	os.Exit(2)
 163  }
 164  
 165  var (
 166  	Fieldtrack_enabled        int
 167  	Preemptibleloops_enabled  int
 168  	Staticlockranking_enabled int
 169  	Regabi_enabled            int
 170  )
 171  
 172  // Toolchain experiments.
 173  // These are controlled by the GOEXPERIMENT environment
 174  // variable recorded when the toolchain is built.
 175  // This list is also known to cmd/gc.
 176  var exper = []struct {
 177  	name string
 178  	val  *int
 179  }{
 180  	{"fieldtrack", &Fieldtrack_enabled},
 181  	{"preemptibleloops", &Preemptibleloops_enabled},
 182  	{"staticlockranking", &Staticlockranking_enabled},
 183  	{"regabi", &Regabi_enabled},
 184  }
 185  
 186  var defaultExpstring = Expstring()
 187  
 188  func DefaultExpstring() string {
 189  	return defaultExpstring
 190  }
 191  
 192  func Expstring() string {
 193  	buf := "X"
 194  	for i := range exper {
 195  		if *exper[i].val != 0 {
 196  			buf += "," + exper[i].name
 197  		}
 198  	}
 199  	if buf == "X" {
 200  		buf += ",none"
 201  	}
 202  	return "X:" + buf[2:]
 203  }
 204