1
2
3
4
5 package buildcfg
6
7 import (
8 "fmt"
9 "reflect"
10 "strings"
11
12 "internal/goexperiment"
13 )
14
15
16
17
18
19
20
21
22
23
24 var Experiment, experimentBaseline = func() (goexperiment.Flags, goexperiment.Flags) {
25 flags, baseline, err := ParseGOEXPERIMENT(GOOS, GOARCH, envOr("GOEXPERIMENT", defaultGOEXPERIMENT))
26 if err != nil {
27 Error = err
28 }
29 return flags, baseline
30 }()
31
32 const DefaultGOEXPERIMENT = defaultGOEXPERIMENT
33
34
35
36
37
38
39
40
41 var FramePointerEnabled = GOARCH == "amd64" || GOARCH == "arm64"
42
43
44
45
46
47
48 func ParseGOEXPERIMENT(goos, goarch, goexp string) (flags, baseline goexperiment.Flags, err error) {
49 regabiSupported := goarch == "amd64" && (goos == "android" || goos == "linux" || goos == "darwin" || goos == "windows")
50
51 baseline = goexperiment.Flags{
52 RegabiWrappers: regabiSupported,
53 RegabiG: regabiSupported,
54 RegabiReflect: regabiSupported,
55 RegabiDefer: regabiSupported,
56 RegabiArgs: regabiSupported,
57 }
58
59
60 flags = baseline
61
62
63
64
65 if goexp != "" {
66
67 names := make(map[string]func(bool))
68 rv := reflect.ValueOf(&flags).Elem()
69 rt := rv.Type()
70 for i := 0; i < rt.NumField(); i++ {
71 field := rv.Field(i)
72 names[strings.ToLower(rt.Field(i).Name)] = field.SetBool
73 }
74
75
76
77
78
79 names["regabi"] = func(v bool) {
80 flags.RegabiWrappers = v
81 flags.RegabiG = v
82 flags.RegabiReflect = v
83 flags.RegabiDefer = v
84 flags.RegabiArgs = v
85 }
86
87
88 for _, f := range strings.Split(goexp, ",") {
89 if f == "" {
90 continue
91 }
92 if f == "none" {
93
94
95
96 flags = goexperiment.Flags{}
97 continue
98 }
99 val := true
100 if strings.HasPrefix(f, "no") {
101 f, val = f[2:], false
102 }
103 set, ok := names[f]
104 if !ok {
105 err = fmt.Errorf("unknown GOEXPERIMENT %s", f)
106 return
107 }
108 set(val)
109 }
110 }
111
112
113 if goarch != "amd64" {
114 flags.RegabiWrappers = false
115 flags.RegabiG = false
116 flags.RegabiReflect = false
117 flags.RegabiDefer = false
118 flags.RegabiArgs = false
119 }
120
121 if flags.RegabiG && !flags.RegabiWrappers {
122 err = fmt.Errorf("GOEXPERIMENT regabig requires regabiwrappers")
123 }
124 if flags.RegabiArgs && !(flags.RegabiWrappers && flags.RegabiG && flags.RegabiReflect && flags.RegabiDefer) {
125 err = fmt.Errorf("GOEXPERIMENT regabiargs requires regabiwrappers,regabig,regabireflect,regabidefer")
126 }
127 return
128 }
129
130
131
132
133
134 func expList(exp, base *goexperiment.Flags, all bool) []string {
135 var list []string
136 rv := reflect.ValueOf(exp).Elem()
137 var rBase reflect.Value
138 if base != nil {
139 rBase = reflect.ValueOf(base).Elem()
140 }
141 rt := rv.Type()
142 for i := 0; i < rt.NumField(); i++ {
143 name := strings.ToLower(rt.Field(i).Name)
144 val := rv.Field(i).Bool()
145 baseVal := false
146 if base != nil {
147 baseVal = rBase.Field(i).Bool()
148 }
149 if all || val != baseVal {
150 if val {
151 list = append(list, name)
152 } else {
153 list = append(list, "no"+name)
154 }
155 }
156 }
157 return list
158 }
159
160
161
162
163
164 func GOEXPERIMENT() string {
165 return strings.Join(expList(&Experiment, &experimentBaseline, false), ",")
166 }
167
168
169
170 func EnabledExperiments() []string {
171 return expList(&Experiment, nil, false)
172 }
173
174
175
176 func AllExperiments() []string {
177 return expList(&Experiment, nil, true)
178 }
179
180
181
182
183 func UpdateExperiments(goos, goarch, goexperiment string) {
184 var err error
185 Experiment, experimentBaseline, err = ParseGOEXPERIMENT(goos, goarch, goexperiment)
186 if err != nil {
187 Error = err
188 }
189 }
190
View as plain text