Skip to content

Commit e8b5bc6

Browse files
andreybokhankomengzhuo
authored andcommitted
cmd/dist,internal: add GOARM64 environment variable
Adds GOARM64 environment variable with accepted range of values "v8.{0-9}", "v9.{0-5}" and optional ",lse" and ",crypto" suffixes. Right now it doesn't affect anything, but can be used in the future to selectively target specific versions of different ARM64 hardware. For #60905 Change-Id: I6d530041b6931aa884e34f719f8ec41b1cb03ece Reviewed-on: https://go-review.googlesource.com/c/go/+/559555 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Mauri de Souza Meneguzzo <[email protected]> Reviewed-by: Cherry Mui <[email protected]> Reviewed-by: Shu-Chun Weng <[email protected]> Reviewed-by: Fannie Zhang <[email protected]>
1 parent 9e3b1d5 commit e8b5bc6

File tree

7 files changed

+233
-0
lines changed

7 files changed

+233
-0
lines changed

src/cmd/dist/build.go

+11
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ var (
3333
gohostos string
3434
goos string
3535
goarm string
36+
goarm64 string
3637
go386 string
3738
goamd64 string
3839
gomips string
@@ -141,6 +142,12 @@ func xinit() {
141142
}
142143
goarm = b
143144

145+
b = os.Getenv("GOARM64")
146+
if b == "" {
147+
b = "v8.0"
148+
}
149+
goarm64 = b
150+
144151
b = os.Getenv("GO386")
145152
if b == "" {
146153
b = "sse2"
@@ -230,6 +237,7 @@ func xinit() {
230237
os.Setenv("GOAMD64", goamd64)
231238
os.Setenv("GOARCH", goarch)
232239
os.Setenv("GOARM", goarm)
240+
os.Setenv("GOARM64", goarm64)
233241
os.Setenv("GOHOSTARCH", gohostarch)
234242
os.Setenv("GOHOSTOS", gohostos)
235243
os.Setenv("GOOS", goos)
@@ -1239,6 +1247,9 @@ func cmdenv() {
12391247
if goarch == "arm" {
12401248
xprintf(format, "GOARM", goarm)
12411249
}
1250+
if goarch == "arm64" {
1251+
xprintf(format, "GOARM64", goarm64)
1252+
}
12421253
if goarch == "386" {
12431254
xprintf(format, "GO386", go386)
12441255
}

src/cmd/dist/buildruntime.go

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ func mkbuildcfg(file string) {
5454
fmt.Fprintf(&buf, "const defaultGO386 = `%s`\n", go386)
5555
fmt.Fprintf(&buf, "const defaultGOAMD64 = `%s`\n", goamd64)
5656
fmt.Fprintf(&buf, "const defaultGOARM = `%s`\n", goarm)
57+
fmt.Fprintf(&buf, "const defaultGOARM64 = `%s`\n", goarm64)
5758
fmt.Fprintf(&buf, "const defaultGOMIPS = `%s`\n", gomips)
5859
fmt.Fprintf(&buf, "const defaultGOMIPS64 = `%s`\n", gomips64)
5960
fmt.Fprintf(&buf, "const defaultGOPPC64 = `%s`\n", goppc64)

src/cmd/go/alldocs.go

+9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/cmd/go/internal/help/helpdoc.go

+9
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,13 @@ Architecture-specific environment variables:
603603
Valid values are 5, 6, 7.
604604
The value can be followed by an option specifying how to implement floating point instructions.
605605
Valid options are ,softfloat (default for 5) and ,hardfloat (default for 6 and 7).
606+
GOARM64
607+
For GOARCH=arm64, the ARM64 architecture for which to compile.
608+
Valid values are v8.0 (default), v8.{1-9}, v9.{0-5}.
609+
The value can be followed by an option specifying extensions implemented by target hardware.
610+
Valid options are ,lse and ,crypto.
611+
Note that some extensions are enabled by default starting from a certain GOARM64 version;
612+
for example, lse is enabled by default starting from v8.1.
606613
GO386
607614
For GOARCH=386, how to implement floating point instructions.
608615
Valid values are sse2 (default), softfloat.
@@ -893,6 +900,8 @@ The defined architecture feature build tags are:
893900
correspond to the amd64.v1, amd64.v2, and amd64.v3 feature build tags.
894901
- For GOARCH=arm, GOARM=5, 6, and 7
895902
correspond to the arm.5, arm.6, and arm.7 feature build tags.
903+
- For GOARCH=arm64, GOARM64=v8.{0-9} and v9.{0-5}
904+
correspond to the arm64.v8.{0-9} and arm64.v9.{0-5} feature build tags.
896905
- For GOARCH=mips or mipsle,
897906
GOMIPS=hardfloat and softfloat
898907
correspond to the mips.hardfloat and mips.softfloat

src/internal/buildcfg/cfg.go

+117
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ var (
2626
GO386 = envOr("GO386", defaultGO386)
2727
GOAMD64 = goamd64()
2828
GOARM = goarm()
29+
GOARM64 = goarm64()
2930
GOMIPS = gomips()
3031
GOMIPS64 = gomips64()
3132
GOPPC64 = goppc64()
@@ -126,6 +127,106 @@ func goarm() (g goarmFeatures) {
126127
return
127128
}
128129

130+
type goarm64Features struct {
131+
Version string
132+
// Large Systems Extension
133+
LSE bool
134+
// ARM v8.0 Cryptographic Extension. It includes the following features:
135+
// * FEAT_AES, which includes the AESD and AESE instructions.
136+
// * FEAT_PMULL, which includes the PMULL, PMULL2 instructions.
137+
// * FEAT_SHA1, which includes the SHA1* instructions.
138+
// * FEAT_SHA256, which includes the SHA256* instructions.
139+
Crypto bool
140+
}
141+
142+
func (g goarm64Features) String() string {
143+
arm64Str := g.Version
144+
if g.LSE {
145+
arm64Str += ",lse"
146+
}
147+
if g.Crypto {
148+
arm64Str += ",crypto"
149+
}
150+
return arm64Str
151+
}
152+
153+
func parseGoarm64(v string) (g goarm64Features) {
154+
const (
155+
lseOpt = ",lse"
156+
cryptoOpt = ",crypto"
157+
)
158+
159+
g.LSE = false
160+
g.Crypto = false
161+
// We allow any combination of suffixes, in any order
162+
for {
163+
if strings.HasSuffix(v, lseOpt) {
164+
g.LSE = true
165+
v = v[:len(v)-len(lseOpt)]
166+
continue
167+
}
168+
169+
if strings.HasSuffix(v, cryptoOpt) {
170+
g.Crypto = true
171+
v = v[:len(v)-len(cryptoOpt)]
172+
continue
173+
}
174+
175+
break
176+
}
177+
178+
switch v {
179+
case "v8.0":
180+
g.Version = v
181+
case "v8.1", "v8.2", "v8.3", "v8.4", "v8.5", "v8.6", "v8.7", "v8.8", "v8.9",
182+
"v9.0", "v9.1", "v9.2", "v9.3", "v9.4", "v9.5":
183+
g.Version = v
184+
// LSE extension is mandatory starting from 8.1
185+
g.LSE = true
186+
default:
187+
Error = fmt.Errorf("invalid GOARM64: must start with v8.{0-9} or v9.{0-5} and may optionally end in %q and/or %q",
188+
lseOpt, cryptoOpt)
189+
g.Version = defaultGOARM64
190+
}
191+
192+
return
193+
}
194+
195+
func goarm64() goarm64Features {
196+
return parseGoarm64(envOr("GOARM64", defaultGOARM64))
197+
}
198+
199+
// Returns true if g supports giving ARM64 ISA
200+
// Note that this function doesn't accept / test suffixes (like ",lse" or ",crypto")
201+
func (g goarm64Features) Supports(s string) bool {
202+
// We only accept "v{8-9}.{0-9}. Everything else is malformed.
203+
if len(s) != 4 {
204+
return false
205+
}
206+
207+
major := s[1]
208+
minor := s[3]
209+
210+
// We only accept "v{8-9}.{0-9}. Everything else is malformed.
211+
if major < '8' || major > '9' ||
212+
minor < '0' || minor > '9' ||
213+
s[0] != 'v' || s[2] != '.' {
214+
return false
215+
}
216+
217+
g_major := g.Version[1]
218+
g_minor := g.Version[3]
219+
220+
if major == g_major {
221+
return minor <= g_minor
222+
} else if g_major == '9' {
223+
// v9.0 diverged from v8.5. This means we should compare with g_minor increased by five.
224+
return minor <= g_minor+5
225+
} else {
226+
return false
227+
}
228+
}
229+
129230
func gomips() string {
130231
switch v := envOr("GOMIPS", defaultGOMIPS); v {
131232
case "hardfloat", "softfloat":
@@ -238,6 +339,8 @@ func GOGOARCH() (name, value string) {
238339
return "GOAMD64", fmt.Sprintf("v%d", GOAMD64)
239340
case "arm":
240341
return "GOARM", GOARM.String()
342+
case "arm64":
343+
return "GOARM64", GOARM64.String()
241344
case "mips", "mipsle":
242345
return "GOMIPS", GOMIPS
243346
case "mips64", "mips64le":
@@ -266,6 +369,20 @@ func gogoarchTags() []string {
266369
list = append(list, fmt.Sprintf("%s.%d", GOARCH, i))
267370
}
268371
return list
372+
case "arm64":
373+
var list []string
374+
major := int(GOARM64.Version[1] - '0')
375+
minor := int(GOARM64.Version[3] - '0')
376+
for i := 0; i <= minor; i++ {
377+
list = append(list, fmt.Sprintf("%s.v%d.%d", GOARCH, major, i))
378+
}
379+
// ARM64 v9.x also includes support of v8.x+5 (i.e. v9.1 includes v8.(1+5) = v8.6).
380+
if major == 9 {
381+
for i := 0; i <= minor+5 && i <= 9; i++ {
382+
list = append(list, fmt.Sprintf("%s.v%d.%d", GOARCH, 8, i))
383+
}
384+
}
385+
return list
269386
case "mips", "mipsle":
270387
return []string{GOARCH + "." + GOMIPS}
271388
case "mips64", "mips64le":

src/internal/buildcfg/cfg_test.go

+85
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,89 @@ func TestConfigFlags(t *testing.T) {
3737
if _ = goriscv64(); Error == nil {
3838
t.Errorf("Wrong parsing of RISCV64=rva22")
3939
}
40+
Error = nil
41+
os.Setenv("GOARM64", "v7.0")
42+
if _ = goarm64(); Error == nil {
43+
t.Errorf("Wrong parsing of GOARM64=7.0")
44+
}
45+
Error = nil
46+
os.Setenv("GOARM64", "8.0")
47+
if _ = goarm64(); Error == nil {
48+
t.Errorf("Wrong parsing of GOARM64=8.0")
49+
}
50+
Error = nil
51+
os.Setenv("GOARM64", "v8.0,lsb")
52+
if _ = goarm64(); Error == nil {
53+
t.Errorf("Wrong parsing of GOARM64=v8.0,lsb")
54+
}
55+
os.Setenv("GOARM64", "v8.0,lse")
56+
if goarm64().Version != "v8.0" || goarm64().LSE != true || goarm64().Crypto != false {
57+
t.Errorf("Wrong parsing of GOARM64=v8.0,lse")
58+
}
59+
os.Setenv("GOARM64", "v8.0,crypto")
60+
if goarm64().Version != "v8.0" || goarm64().LSE != false || goarm64().Crypto != true {
61+
t.Errorf("Wrong parsing of GOARM64=v8.0,crypto")
62+
}
63+
os.Setenv("GOARM64", "v8.0,crypto,lse")
64+
if goarm64().Version != "v8.0" || goarm64().LSE != true || goarm64().Crypto != true {
65+
t.Errorf("Wrong parsing of GOARM64=v8.0,crypto,lse")
66+
}
67+
os.Setenv("GOARM64", "v8.0,lse,crypto")
68+
if goarm64().Version != "v8.0" || goarm64().LSE != true || goarm64().Crypto != true {
69+
t.Errorf("Wrong parsing of GOARM64=v8.0,lse,crypto")
70+
}
71+
os.Setenv("GOARM64", "v9.0")
72+
if goarm64().Version != "v9.0" || goarm64().LSE != true || goarm64().Crypto != false {
73+
t.Errorf("Wrong parsing of GOARM64=v9.0")
74+
}
75+
}
76+
77+
func TestGoarm64FeaturesSupports(t *testing.T) {
78+
g := parseGoarm64("v9.3")
79+
80+
if !g.Supports("v9.3") {
81+
t.Errorf("Wrong goarm64Features.Supports for v9.3, v9.3")
82+
}
83+
84+
if g.Supports("v9.4") {
85+
t.Errorf("Wrong goarm64Features.Supports for v9.3, v9.4")
86+
}
87+
88+
if !g.Supports("v8.8") {
89+
t.Errorf("Wrong goarm64Features.Supports for v9.3, v8.8")
90+
}
91+
92+
if g.Supports("v8.9") {
93+
t.Errorf("Wrong goarm64Features.Supports for v9.3, v8.9")
94+
}
95+
96+
if g.Supports(",lse") {
97+
t.Errorf("Wrong goarm64Features.Supports for v9.3, ,lse")
98+
}
99+
}
100+
101+
func TestGogoarchTags(t *testing.T) {
102+
old_goarch := GOARCH
103+
old_goarm64 := GOARM64
104+
105+
GOARCH = "arm64"
106+
107+
os.Setenv("GOARM64", "v9.5")
108+
GOARM64 = goarm64()
109+
tags := gogoarchTags()
110+
want := []string{"arm64.v9.0", "arm64.v9.1", "arm64.v9.2", "arm64.v9.3", "arm64.v9.4", "arm64.v9.5",
111+
"arm64.v8.0", "arm64.v8.1", "arm64.v8.2", "arm64.v8.3", "arm64.v8.4", "arm64.v8.5", "arm64.v8.6", "arm64.v8.7", "arm64.v8.8", "arm64.v8.9"}
112+
if len(tags) != len(want) {
113+
t.Errorf("Wrong number of tags for GOARM64=v9.5")
114+
} else {
115+
for i, v := range tags {
116+
if v != want[i] {
117+
t.Error("Wrong tags for GOARM64=v9.5")
118+
break
119+
}
120+
}
121+
}
122+
123+
GOARCH = old_goarch
124+
GOARM64 = old_goarm64
40125
}

src/internal/cfg/cfg.go

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ const KnownEnv = `
3636
GOAMD64
3737
GOARCH
3838
GOARM
39+
GOARM64
3940
GOBIN
4041
GOCACHE
4142
GOCACHEPROG

0 commit comments

Comments
 (0)