Skip to content

Commit 0d01934

Browse files
author
Gerrit Code Review
committed
Merge "all: REVERSE MERGE dev.typeparams (4d3cc84) into master"
2 parents 044ec4f + 3601aed commit 0d01934

File tree

924 files changed

+37250
-17414
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

924 files changed

+37250
-17414
lines changed

misc/cgo/errors/testdata/err2.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,18 @@ func main() {
9191

9292
// issue 26745
9393
_ = func(i int) int {
94-
return C.i + 1 // ERROR HERE: 14
94+
// typecheck reports at column 14 ('+'), but types2 reports at
95+
// column 10 ('C').
96+
// TODO(mdempsky): Investigate why, and see if types2 can be
97+
// updated to match typecheck behavior.
98+
return C.i + 1 // ERROR HERE: \b(10|14)\b
9599
}
96100
_ = func(i int) {
97-
C.fi(i) // ERROR HERE: 7
101+
// typecheck reports at column 7 ('('), but types2 reports at
102+
// column 8 ('i'). The types2 position is more correct, but
103+
// updating typecheck here is fundamentally challenging because of
104+
// IR limitations.
105+
C.fi(i) // ERROR HERE: \b(7|8)\b
98106
}
99107

100108
C.fi = C.fi // ERROR HERE

src/cmd/compile/abi-internal.md

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,128 @@ control bits specified by the ELF AMD64 ABI.
505505

506506
The x87 floating-point control word is not used by Go on amd64.
507507

508+
### arm64 architecture
509+
510+
The arm64 architecture uses R0 – R15 for integer arguments and results.
511+
512+
It uses F0 – F15 for floating-point arguments and results.
513+
514+
*Rationale*: 16 integer registers and 16 floating-point registers are
515+
more than enough for passing arguments and results for practically all
516+
functions (see Appendix). While there are more registers available,
517+
using more registers provides little benefit. Additionally, it will add
518+
overhead on code paths where the number of arguments are not statically
519+
known (e.g. reflect call), and will consume more stack space when there
520+
is only limited stack space available to fit in the nosplit limit.
521+
522+
Registers R16 and R17 are permanent scratch registers. They are also
523+
used as scratch registers by the linker (Go linker and external
524+
linker) in trampolines.
525+
526+
Register R18 is reserved and never used. It is reserved for the OS
527+
on some platforms (e.g. macOS).
528+
529+
Registers R19 – R25 are permanent scratch registers. In addition,
530+
R27 is a permanent scratch register used by the assembler when
531+
expanding instructions.
532+
533+
Floating-point registers F16 – F31 are also permanent scratch
534+
registers.
535+
536+
Special-purpose registers are as follows:
537+
538+
| Register | Call meaning | Return meaning | Body meaning |
539+
| --- | --- | --- | --- |
540+
| RSP | Stack pointer | Same | Same |
541+
| R30 | Link register | Same | Scratch (non-leaf functions) |
542+
| R29 | Frame pointer | Same | Same |
543+
| R28 | Current goroutine | Same | Same |
544+
| R27 | Scratch | Scratch | Scratch |
545+
| R26 | Closure context pointer | Scratch | Scratch |
546+
| R18 | Reserved (not used) | Same | Same |
547+
| ZR | Zero value | Same | Same |
548+
549+
*Rationale*: These register meanings are compatible with Go’s
550+
stack-based calling convention.
551+
552+
*Rationale*: The link register, R30, holds the function return
553+
address at the function entry. For functions that have frames
554+
(including most non-leaf functions), R30 is saved to stack in the
555+
function prologue and restored in the epilogue. Within the function
556+
body, R30 can be used as a scratch register.
557+
558+
*Implementation note*: Registers with fixed meaning at calls but not
559+
in function bodies must be initialized by "injected" calls such as
560+
signal-based panics.
561+
562+
#### Stack layout
563+
564+
The stack pointer, RSP, grows down and is always aligned to 16 bytes.
565+
566+
*Rationale*: The arm64 architecture requires the stack pointer to be
567+
16-byte aligned.
568+
569+
A function's stack frame, after the frame is created, is laid out as
570+
follows:
571+
572+
+------------------------------+
573+
| ... locals ... |
574+
| ... outgoing arguments ... |
575+
| return PC | ← RSP points to
576+
| frame pointer on entry |
577+
+------------------------------+ ↓ lower addresses
578+
579+
The "return PC" is loaded to the link register, R30, as part of the
580+
arm64 `CALL` operation.
581+
582+
On entry, a function subtracts from RSP to open its stack frame, and
583+
saves the values of R30 and R29 at the bottom of the frame.
584+
Specifically, R30 is saved at 0(RSP) and R29 is saved at -8(RSP),
585+
after RSP is updated.
586+
587+
A leaf function that does not require any stack space may omit the
588+
saved R30 and R29.
589+
590+
The Go ABI's use of R29 as a frame pointer register is compatible with
591+
arm64 architecture requirement so that Go can inter-operate with platform
592+
debuggers and profilers.
593+
594+
This stack layout is used by both register-based (ABIInternal) and
595+
stack-based (ABI0) calling conventions.
596+
597+
#### Flags
598+
599+
The arithmetic status flags (NZCV) are treated like scratch registers
600+
and not preserved across calls.
601+
All other bits in PSTATE are system flags and are not modified by Go.
602+
603+
The floating-point status register (FPSR) is treated like scratch
604+
registers and not preserved across calls.
605+
606+
At calls, the floating-point control register (FPCR) bits are always
607+
set as follows:
608+
609+
| Flag | Bit | Value | Meaning |
610+
| --- | --- | --- | --- |
611+
| DN | 25 | 0 | Propagate NaN operands |
612+
| FZ | 24 | 0 | Do not flush to zero |
613+
| RC | 23/22 | 0 (RN) | Round to nearest, choose even if tied |
614+
| IDE | 15 | 0 | Denormal operations trap disabled |
615+
| IXE | 12 | 0 | Inexact trap disabled |
616+
| UFE | 11 | 0 | Underflow trap disabled |
617+
| OFE | 10 | 0 | Overflow trap disabled |
618+
| DZE | 9 | 0 | Divide-by-zero trap disabled |
619+
| IOE | 8 | 0 | Invalid operations trap disabled |
620+
| NEP | 2 | 0 | Scalar operations do not affect higher elements in vector registers |
621+
| AH | 1 | 0 | No alternate handling of de-normal inputs |
622+
| FIZ | 0 | 0 | Do not zero de-normals |
623+
624+
*Rationale*: Having a fixed FPCR control configuration allows Go
625+
functions to use floating-point and vector (SIMD) operations without
626+
modifying or saving the FPCR.
627+
Functions are allowed to modify it between calls (as long as they
628+
restore it), but as of this writing Go code never does.
629+
508630
## Future directions
509631

510632
### Spill path improvements

src/cmd/compile/internal/amd64/galign.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,10 @@ func Init(arch *ssagen.ArchInfo) {
1818

1919
arch.ZeroRange = zerorange
2020
arch.Ginsnop = ginsnop
21-
arch.Ginsnopdefer = ginsnop
2221

2322
arch.SSAMarkMoves = ssaMarkMoves
2423
arch.SSAGenValue = ssaGenValue
2524
arch.SSAGenBlock = ssaGenBlock
26-
arch.LoadRegResults = loadRegResults
25+
arch.LoadRegResult = loadRegResult
2726
arch.SpillArgReg = spillArgReg
2827
}

src/cmd/compile/internal/amd64/ggen.go

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ func dzDI(b int64) int64 {
5757
func zerorange(pp *objw.Progs, p *obj.Prog, off, cnt int64, state *uint32) *obj.Prog {
5858
const (
5959
r13 = 1 << iota // if R13 is already zeroed.
60-
x15 // if X15 is already zeroed. Note: in new ABI, X15 is always zero.
6160
)
6261

6362
if cnt == 0 {
@@ -85,11 +84,6 @@ func zerorange(pp *objw.Progs, p *obj.Prog, off, cnt int64, state *uint32) *obj.
8584
}
8685
p = pp.Append(p, x86.AMOVQ, obj.TYPE_REG, x86.REG_R13, 0, obj.TYPE_MEM, x86.REG_SP, off)
8786
} else if !isPlan9 && cnt <= int64(8*types.RegSize) {
88-
if !buildcfg.Experiment.RegabiG && *state&x15 == 0 {
89-
p = pp.Append(p, x86.AXORPS, obj.TYPE_REG, x86.REG_X15, 0, obj.TYPE_REG, x86.REG_X15, 0)
90-
*state |= x15
91-
}
92-
9387
for i := int64(0); i < cnt/16; i++ {
9488
p = pp.Append(p, x86.AMOVUPS, obj.TYPE_REG, x86.REG_X15, 0, obj.TYPE_MEM, x86.REG_SP, off+i*16)
9589
}
@@ -98,10 +92,6 @@ func zerorange(pp *objw.Progs, p *obj.Prog, off, cnt int64, state *uint32) *obj.
9892
p = pp.Append(p, x86.AMOVUPS, obj.TYPE_REG, x86.REG_X15, 0, obj.TYPE_MEM, x86.REG_SP, off+cnt-int64(16))
9993
}
10094
} else if !isPlan9 && (cnt <= int64(128*types.RegSize)) {
101-
if !buildcfg.Experiment.RegabiG && *state&x15 == 0 {
102-
p = pp.Append(p, x86.AXORPS, obj.TYPE_REG, x86.REG_X15, 0, obj.TYPE_REG, x86.REG_X15, 0)
103-
*state |= x15
104-
}
10595
// Save DI to r12. With the amd64 Go register abi, DI can contain
10696
// an incoming parameter, whereas R12 is always scratch.
10797
p = pp.Append(p, x86.AMOVQ, obj.TYPE_REG, x86.REG_DI, 0, obj.TYPE_REG, x86.REG_R12, 0)

src/cmd/compile/internal/amd64/ssa.go

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -823,7 +823,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
823823
p.To.Reg = v.Args[0].Reg()
824824
ssagen.AddAux2(&p.To, v, sc.Off64())
825825
case ssa.OpAMD64MOVOstorezero:
826-
if !buildcfg.Experiment.RegabiG || s.ABI != obj.ABIInternal {
826+
if s.ABI != obj.ABIInternal {
827827
// zero X15 manually
828828
opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15)
829829
}
@@ -914,7 +914,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
914914
p.To.Type = obj.TYPE_REG
915915
p.To.Reg = v.Reg()
916916
case ssa.OpAMD64DUFFZERO:
917-
if !buildcfg.Experiment.RegabiG || s.ABI != obj.ABIInternal {
917+
if s.ABI != obj.ABIInternal {
918918
// zero X15 manually
919919
opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15)
920920
}
@@ -997,22 +997,26 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
997997
// Closure pointer is DX.
998998
ssagen.CheckLoweredGetClosurePtr(v)
999999
case ssa.OpAMD64LoweredGetG:
1000-
if buildcfg.Experiment.RegabiG && s.ABI == obj.ABIInternal {
1000+
if s.ABI == obj.ABIInternal {
10011001
v.Fatalf("LoweredGetG should not appear in ABIInternal")
10021002
}
10031003
r := v.Reg()
10041004
getgFromTLS(s, r)
10051005
case ssa.OpAMD64CALLstatic:
1006-
if buildcfg.Experiment.RegabiG && s.ABI == obj.ABI0 && v.Aux.(*ssa.AuxCall).Fn.ABI() == obj.ABIInternal {
1006+
if s.ABI == obj.ABI0 && v.Aux.(*ssa.AuxCall).Fn.ABI() == obj.ABIInternal {
10071007
// zeroing X15 when entering ABIInternal from ABI0
1008-
opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15)
1008+
if buildcfg.GOOS != "plan9" { // do not use SSE on Plan 9
1009+
opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15)
1010+
}
10091011
// set G register from TLS
10101012
getgFromTLS(s, x86.REG_R14)
10111013
}
10121014
s.Call(v)
1013-
if buildcfg.Experiment.RegabiG && s.ABI == obj.ABIInternal && v.Aux.(*ssa.AuxCall).Fn.ABI() == obj.ABI0 {
1015+
if s.ABI == obj.ABIInternal && v.Aux.(*ssa.AuxCall).Fn.ABI() == obj.ABI0 {
10141016
// zeroing X15 when entering ABIInternal from ABI0
1015-
opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15)
1017+
if buildcfg.GOOS != "plan9" { // do not use SSE on Plan 9
1018+
opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15)
1019+
}
10161020
// set G register from TLS
10171021
getgFromTLS(s, x86.REG_R14)
10181022
}
@@ -1304,9 +1308,11 @@ func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) {
13041308
case ssa.BlockRet:
13051309
s.Prog(obj.ARET)
13061310
case ssa.BlockRetJmp:
1307-
if buildcfg.Experiment.RegabiG && s.ABI == obj.ABI0 && b.Aux.(*obj.LSym).ABI() == obj.ABIInternal {
1311+
if s.ABI == obj.ABI0 && b.Aux.(*obj.LSym).ABI() == obj.ABIInternal {
13081312
// zeroing X15 when entering ABIInternal from ABI0
1309-
opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15)
1313+
if buildcfg.GOOS != "plan9" { // do not use SSE on Plan 9
1314+
opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15)
1315+
}
13101316
// set G register from TLS
13111317
getgFromTLS(s, x86.REG_R14)
13121318
}
@@ -1348,20 +1354,15 @@ func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) {
13481354
}
13491355
}
13501356

1351-
func loadRegResults(s *ssagen.State, f *ssa.Func) {
1352-
for _, o := range f.OwnAux.ABIInfo().OutParams() {
1353-
n := o.Name.(*ir.Name)
1354-
rts, offs := o.RegisterTypesAndOffsets()
1355-
for i := range o.Registers {
1356-
p := s.Prog(loadByType(rts[i]))
1357-
p.From.Type = obj.TYPE_MEM
1358-
p.From.Name = obj.NAME_AUTO
1359-
p.From.Sym = n.Linksym()
1360-
p.From.Offset = n.FrameOffset() + offs[i]
1361-
p.To.Type = obj.TYPE_REG
1362-
p.To.Reg = ssa.ObjRegForAbiReg(o.Registers[i], f.Config)
1363-
}
1364-
}
1357+
func loadRegResult(s *ssagen.State, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog {
1358+
p := s.Prog(loadByType(t))
1359+
p.From.Type = obj.TYPE_MEM
1360+
p.From.Name = obj.NAME_AUTO
1361+
p.From.Sym = n.Linksym()
1362+
p.From.Offset = n.FrameOffset() + off
1363+
p.To.Type = obj.TYPE_REG
1364+
p.To.Reg = reg
1365+
return p
13651366
}
13661367

13671368
func spillArgReg(pp *objw.Progs, p *obj.Prog, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog {

src/cmd/compile/internal/arm/galign.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ func Init(arch *ssagen.ArchInfo) {
1818
arch.SoftFloat = buildcfg.GOARM == 5
1919
arch.ZeroRange = zerorange
2020
arch.Ginsnop = ginsnop
21-
arch.Ginsnopdefer = ginsnop
2221

2322
arch.SSAMarkMoves = func(s *ssagen.State, b *ssa.Block) {}
2423
arch.SSAGenValue = ssaGenValue

src/cmd/compile/internal/arm64/galign.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ func Init(arch *ssagen.ArchInfo) {
1818
arch.PadFrame = padframe
1919
arch.ZeroRange = zerorange
2020
arch.Ginsnop = ginsnop
21-
arch.Ginsnopdefer = ginsnop
2221

2322
arch.SSAMarkMoves = func(s *ssagen.State, b *ssa.Block) {}
2423
arch.SSAGenValue = ssaGenValue
2524
arch.SSAGenBlock = ssaGenBlock
25+
arch.LoadRegResult = loadRegResult
26+
arch.SpillArgReg = spillArgReg
2627
}

src/cmd/compile/internal/arm64/ssa.go

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"cmd/compile/internal/base"
1111
"cmd/compile/internal/ir"
1212
"cmd/compile/internal/logopt"
13+
"cmd/compile/internal/objw"
1314
"cmd/compile/internal/ssa"
1415
"cmd/compile/internal/ssagen"
1516
"cmd/compile/internal/types"
@@ -161,6 +162,18 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
161162
p.From.Type = obj.TYPE_REG
162163
p.From.Reg = v.Args[0].Reg()
163164
ssagen.AddrAuto(&p.To, v)
165+
case ssa.OpArgIntReg, ssa.OpArgFloatReg:
166+
// The assembler needs to wrap the entry safepoint/stack growth code with spill/unspill
167+
// The loop only runs once.
168+
for _, a := range v.Block.Func.RegArgs {
169+
// Pass the spill/unspill information along to the assembler, offset by size of
170+
// the saved LR slot.
171+
addr := ssagen.SpillSlotAddr(a, arm64.REGSP, base.Ctxt.FixedFrameSize())
172+
s.FuncInfo().AddSpill(
173+
obj.RegSpill{Reg: a.Reg, Addr: addr, Unspill: loadByType(a.Type), Spill: storeByType(a.Type)})
174+
}
175+
v.Block.Func.RegArgs = nil
176+
ssagen.CheckArgReg(v)
164177
case ssa.OpARM64ADD,
165178
ssa.OpARM64SUB,
166179
ssa.OpARM64AND,
@@ -1101,8 +1114,34 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
11011114
v.Fatalf("FlagConstant op should never make it to codegen %v", v.LongString())
11021115
case ssa.OpARM64InvertFlags:
11031116
v.Fatalf("InvertFlags should never make it to codegen %v", v.LongString())
1104-
case ssa.OpClobber, ssa.OpClobberReg:
1105-
// TODO: implement for clobberdead experiment. Nop is ok for now.
1117+
case ssa.OpClobber:
1118+
// MOVW $0xdeaddead, REGTMP
1119+
// MOVW REGTMP, (slot)
1120+
// MOVW REGTMP, 4(slot)
1121+
p := s.Prog(arm64.AMOVW)
1122+
p.From.Type = obj.TYPE_CONST
1123+
p.From.Offset = 0xdeaddead
1124+
p.To.Type = obj.TYPE_REG
1125+
p.To.Reg = arm64.REGTMP
1126+
p = s.Prog(arm64.AMOVW)
1127+
p.From.Type = obj.TYPE_REG
1128+
p.From.Reg = arm64.REGTMP
1129+
p.To.Type = obj.TYPE_MEM
1130+
p.To.Reg = arm64.REGSP
1131+
ssagen.AddAux(&p.To, v)
1132+
p = s.Prog(arm64.AMOVW)
1133+
p.From.Type = obj.TYPE_REG
1134+
p.From.Reg = arm64.REGTMP
1135+
p.To.Type = obj.TYPE_MEM
1136+
p.To.Reg = arm64.REGSP
1137+
ssagen.AddAux2(&p.To, v, v.AuxInt+4)
1138+
case ssa.OpClobberReg:
1139+
x := uint64(0xdeaddeaddeaddead)
1140+
p := s.Prog(arm64.AMOVD)
1141+
p.From.Type = obj.TYPE_CONST
1142+
p.From.Offset = int64(x)
1143+
p.To.Type = obj.TYPE_REG
1144+
p.To.Reg = v.Reg()
11061145
default:
11071146
v.Fatalf("genValue not implemented: %s", v.LongString())
11081147
}
@@ -1266,3 +1305,22 @@ func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) {
12661305
b.Fatalf("branch not implemented: %s", b.LongString())
12671306
}
12681307
}
1308+
1309+
func loadRegResult(s *ssagen.State, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog {
1310+
p := s.Prog(loadByType(t))
1311+
p.From.Type = obj.TYPE_MEM
1312+
p.From.Name = obj.NAME_AUTO
1313+
p.From.Sym = n.Linksym()
1314+
p.From.Offset = n.FrameOffset() + off
1315+
p.To.Type = obj.TYPE_REG
1316+
p.To.Reg = reg
1317+
return p
1318+
}
1319+
1320+
func spillArgReg(pp *objw.Progs, p *obj.Prog, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog {
1321+
p = pp.Append(p, storeByType(t), obj.TYPE_REG, reg, 0, obj.TYPE_MEM, 0, n.FrameOffset()+off)
1322+
p.To.Name = obj.NAME_PARAM
1323+
p.To.Sym = n.Linksym()
1324+
p.Pos = p.Pos.WithNotStmt()
1325+
return p
1326+
}

0 commit comments

Comments
 (0)