1 // Copyright 2021 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.
13 "internal/goexperiment"
16 // Experiment contains the toolchain experiments enabled for the
19 // (This is not necessarily the set of experiments the compiler itself
21 var Experiment goexperiment.Flags = parseExperiments()
23 // experimentBaseline specifies the experiment flags that are enabled by
24 // default in the current toolchain. This is, in effect, the "control"
25 // configuration and any variation from this is an experiment.
26 var experimentBaseline goexperiment.Flags
28 // FramePointerEnabled enables the use of platform conventions for
29 // saving frame pointers.
31 // This used to be an experiment, but now it's always enabled on
32 // platforms that support it.
34 // Note: must agree with runtime.framepointer_enabled.
35 var FramePointerEnabled = GOARCH == "amd64" || GOARCH == "arm64"
37 func parseExperiments() goexperiment.Flags {
38 // Start with the statically enabled set of experiments.
39 flags := experimentBaseline
41 // Pick up any changes to the baseline configuration from the
42 // GOEXPERIMENT environment. This can be set at make.bash time
43 // and overridden at build time.
44 env := envOr("GOEXPERIMENT", defaultGOEXPERIMENT)
47 // Create a map of known experiment names.
48 names := make(map[string]reflect.Value)
49 rv := reflect.ValueOf(&flags).Elem()
51 for i := 0; i < rt.NumField(); i++ {
53 names[strings.ToLower(rt.Field(i).Name)] = field
57 for _, f := range strings.Split(env, ",") {
62 // GOEXPERIMENT=none disables all experiment flags.
63 // This is used by cmd/dist, which doesn't know how
64 // to build with any experiment flags.
65 flags = goexperiment.Flags{}
69 if strings.HasPrefix(f, "no") {
74 fmt.Printf("unknown experiment %s\n", f)
81 // regabi is only supported on amd64.
82 if GOARCH != "amd64" {
84 flags.RegabiWrappers = false
86 flags.RegabiReflect = false
87 flags.RegabiDefer = false
88 flags.RegabiArgs = false
90 // Setting regabi sets working sub-experiments.
92 flags.RegabiWrappers = true
94 flags.RegabiReflect = true
95 flags.RegabiDefer = true
97 //flags.RegabiArgs = true
99 // Check regabi dependencies.
100 if flags.RegabiG && !flags.RegabiWrappers {
101 panic("GOEXPERIMENT regabig requires regabiwrappers")
103 if flags.RegabiArgs && !(flags.RegabiWrappers && flags.RegabiG && flags.RegabiReflect && flags.RegabiDefer) {
104 panic("GOEXPERIMENT regabiargs requires regabiwrappers,regabig,regabireflect,regabidefer")
109 // expList returns the list of lower-cased experiment names for
110 // experiments that differ from base. base may be nil to indicate no
111 // experiments. If all is true, then include all experiment flags,
112 // regardless of base.
113 func expList(exp, base *goexperiment.Flags, all bool) []string {
115 rv := reflect.ValueOf(exp).Elem()
116 var rBase reflect.Value
118 rBase = reflect.ValueOf(base).Elem()
121 for i := 0; i < rt.NumField(); i++ {
122 name := strings.ToLower(rt.Field(i).Name)
123 val := rv.Field(i).Bool()
126 baseVal = rBase.Field(i).Bool()
128 if all || val != baseVal {
130 list = append(list, name)
132 list = append(list, "no"+name)
139 // GOEXPERIMENT is a comma-separated list of enabled or disabled
140 // experiments that differ from the baseline experiment configuration.
141 // GOEXPERIMENT is exactly what a user would set on the command line
142 // to get the set of enabled experiments.
143 func GOEXPERIMENT() string {
144 return strings.Join(expList(&Experiment, &experimentBaseline, false), ",")
147 // EnabledExperiments returns a list of enabled experiments, as
148 // lower-cased experiment names.
149 func EnabledExperiments() []string {
150 return expList(&Experiment, nil, false)