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