mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/internal/obj: remove Follow pass
The Follow pass in the assembler backend reorders and copies instructions. This even applies to hand-written assembly code, which in many cases don't want to be reordered. Now that the SSA compiler does a good job for laying out instructions, the benefit of this pass is very little: AMD64: (old = with Follow, new = without Follow) name old time/op new time/op delta BinaryTree17-12 2.78s ± 1% 2.79s ± 1% +0.44% (p=0.000 n=20+19) Fannkuch11-12 3.11s ± 0% 3.31s ± 1% +6.16% (p=0.000 n=19+19) FmtFprintfEmpty-12 50.9ns ± 1% 51.6ns ± 3% +1.40% (p=0.000 n=17+20) FmtFprintfString-12 127ns ± 0% 128ns ± 1% +0.88% (p=0.000 n=17+17) FmtFprintfInt-12 122ns ± 0% 123ns ± 1% +0.76% (p=0.000 n=20+19) FmtFprintfIntInt-12 185ns ± 1% 186ns ± 1% +0.65% (p=0.000 n=20+19) FmtFprintfPrefixedInt-12 192ns ± 1% 202ns ± 1% +4.99% (p=0.000 n=20+19) FmtFprintfFloat-12 284ns ± 0% 288ns ± 0% +1.33% (p=0.000 n=15+19) FmtManyArgs-12 807ns ± 0% 804ns ± 0% -0.44% (p=0.000 n=16+18) GobDecode-12 7.23ms ± 1% 7.21ms ± 1% ~ (p=0.052 n=20+20) GobEncode-12 6.09ms ± 1% 6.12ms ± 1% +0.41% (p=0.002 n=19+19) Gzip-12 253ms ± 1% 255ms ± 1% +0.95% (p=0.000 n=18+20) Gunzip-12 38.4ms ± 0% 38.5ms ± 0% +0.34% (p=0.000 n=17+17) HTTPClientServer-12 95.4µs ± 2% 96.1µs ± 1% +0.78% (p=0.002 n=19+19) JSONEncode-12 16.5ms ± 1% 16.6ms ± 1% +1.17% (p=0.000 n=19+19) JSONDecode-12 54.6ms ± 1% 55.3ms ± 1% +1.23% (p=0.000 n=18+18) Mandelbrot200-12 4.47ms ± 0% 4.47ms ± 0% +0.06% (p=0.000 n=18+18) GoParse-12 3.47ms ± 1% 3.47ms ± 1% ~ (p=0.583 n=20+20) RegexpMatchEasy0_32-12 84.8ns ± 1% 85.2ns ± 2% +0.51% (p=0.022 n=20+20) RegexpMatchEasy0_1K-12 206ns ± 1% 206ns ± 1% ~ (p=0.770 n=20+20) RegexpMatchEasy1_32-12 82.8ns ± 1% 83.4ns ± 1% +0.64% (p=0.000 n=20+19) RegexpMatchEasy1_1K-12 363ns ± 1% 361ns ± 1% -0.48% (p=0.007 n=20+20) RegexpMatchMedium_32-12 126ns ± 1% 126ns ± 0% +0.72% (p=0.000 n=20+20) RegexpMatchMedium_1K-12 39.1µs ± 1% 39.8µs ± 0% +1.73% (p=0.000 n=19+19) RegexpMatchHard_32-12 1.97µs ± 0% 1.98µs ± 1% +0.29% (p=0.005 n=18+20) RegexpMatchHard_1K-12 59.5µs ± 1% 59.8µs ± 1% +0.36% (p=0.000 n=18+20) Revcomp-12 442ms ± 1% 445ms ± 2% +0.67% (p=0.000 n=19+20) Template-12 58.0ms ± 1% 57.5ms ± 1% -0.85% (p=0.000 n=19+19) TimeParse-12 311ns ± 0% 314ns ± 0% +0.94% (p=0.000 n=20+18) TimeFormat-12 350ns ± 3% 346ns ± 0% ~ (p=0.076 n=20+19) [Geo mean] 55.9µs 56.4µs +0.80% ARM32: name old time/op new time/op delta BinaryTree17-4 30.4s ± 0% 30.1s ± 0% -1.14% (p=0.000 n=10+8) Fannkuch11-4 13.7s ± 0% 13.6s ± 0% -0.75% (p=0.000 n=10+10) FmtFprintfEmpty-4 664ns ± 1% 651ns ± 1% -1.96% (p=0.000 n=7+8) FmtFprintfString-4 1.83µs ± 2% 1.77µs ± 2% -3.21% (p=0.000 n=10+10) FmtFprintfInt-4 1.57µs ± 2% 1.54µs ± 2% -2.25% (p=0.007 n=10+10) FmtFprintfIntInt-4 2.37µs ± 2% 2.31µs ± 1% -2.68% (p=0.000 n=10+10) FmtFprintfPrefixedInt-4 2.14µs ± 2% 2.10µs ± 1% -1.83% (p=0.006 n=10+10) FmtFprintfFloat-4 3.69µs ± 2% 3.74µs ± 1% +1.60% (p=0.000 n=10+10) FmtManyArgs-4 9.43µs ± 1% 9.17µs ± 1% -2.70% (p=0.000 n=10+10) GobDecode-4 76.3ms ± 1% 75.5ms ± 1% -1.14% (p=0.003 n=10+10) GobEncode-4 70.7ms ± 2% 69.0ms ± 1% -2.36% (p=0.000 n=10+10) Gzip-4 2.64s ± 1% 2.65s ± 0% +0.59% (p=0.002 n=10+10) Gunzip-4 402ms ± 0% 398ms ± 0% -1.11% (p=0.000 n=10+9) HTTPClientServer-4 458µs ± 0% 457µs ± 0% ~ (p=0.247 n=10+10) JSONEncode-4 171ms ± 0% 172ms ± 0% +0.56% (p=0.000 n=10+10) JSONDecode-4 672ms ± 1% 668ms ± 1% ~ (p=0.105 n=10+10) Mandelbrot200-4 33.5ms ± 0% 33.5ms ± 0% ~ (p=0.156 n=9+10) GoParse-4 33.9ms ± 0% 34.0ms ± 0% +0.36% (p=0.031 n=9+9) RegexpMatchEasy0_32-4 823ns ± 1% 835ns ± 1% +1.49% (p=0.000 n=8+8) RegexpMatchEasy0_1K-4 3.99µs ± 0% 4.02µs ± 1% +0.92% (p=0.000 n=8+10) RegexpMatchEasy1_32-4 877ns ± 3% 904ns ± 2% +3.07% (p=0.012 n=10+10) RegexpMatchEasy1_1K-4 5.99µs ± 0% 5.97µs ± 1% -0.38% (p=0.023 n=8+8) RegexpMatchMedium_32-4 1.40µs ± 2% 1.40µs ± 2% ~ (p=0.590 n=10+9) RegexpMatchMedium_1K-4 357µs ± 0% 355µs ± 1% -0.72% (p=0.000 n=7+8) RegexpMatchHard_32-4 22.3µs ± 0% 22.1µs ± 0% -0.49% (p=0.000 n=8+7) RegexpMatchHard_1K-4 661µs ± 0% 658µs ± 0% -0.42% (p=0.000 n=8+7) Revcomp-4 46.3ms ± 0% 46.3ms ± 0% ~ (p=0.393 n=10+10) Template-4 753ms ± 1% 750ms ± 0% ~ (p=0.211 n=10+9) TimeParse-4 4.28µs ± 1% 4.22µs ± 1% -1.34% (p=0.000 n=8+10) TimeFormat-4 9.00µs ± 0% 9.05µs ± 0% +0.59% (p=0.000 n=10+10) [Geo mean] 538µs 535µs -0.55% ARM64: name old time/op new time/op delta BinaryTree17-8 8.39s ± 0% 8.39s ± 0% ~ (p=0.684 n=10+10) Fannkuch11-8 5.95s ± 0% 5.99s ± 0% +0.63% (p=0.000 n=10+10) FmtFprintfEmpty-8 116ns ± 0% 116ns ± 0% ~ (all equal) FmtFprintfString-8 361ns ± 0% 360ns ± 0% -0.31% (p=0.003 n=8+6) FmtFprintfInt-8 290ns ± 0% 290ns ± 0% ~ (p=0.620 n=9+9) FmtFprintfIntInt-8 476ns ± 1% 469ns ± 0% -1.47% (p=0.000 n=10+6) FmtFprintfPrefixedInt-8 412ns ± 2% 417ns ± 2% +1.39% (p=0.006 n=9+10) FmtFprintfFloat-8 652ns ± 1% 652ns ± 0% ~ (p=0.161 n=10+8) FmtManyArgs-8 1.94µs ± 0% 1.94µs ± 2% ~ (p=0.781 n=10+10) GobDecode-8 17.7ms ± 1% 17.7ms ± 0% ~ (p=0.962 n=10+7) GobEncode-8 15.6ms ± 0% 15.6ms ± 1% ~ (p=0.063 n=10+10) Gzip-8 786ms ± 0% 787ms ± 0% ~ (p=0.356 n=10+9) Gunzip-8 127ms ± 0% 127ms ± 0% +0.08% (p=0.028 n=10+9) HTTPClientServer-8 198µs ± 6% 198µs ± 7% ~ (p=0.796 n=10+10) JSONEncode-8 42.5ms ± 0% 42.2ms ± 0% -0.73% (p=0.000 n=9+8) JSONDecode-8 158ms ± 1% 162ms ± 0% +2.28% (p=0.000 n=10+9) Mandelbrot200-8 10.1ms ± 0% 10.1ms ± 0% -0.01% (p=0.000 n=10+9) GoParse-8 8.54ms ± 1% 8.63ms ± 1% +1.06% (p=0.000 n=10+9) RegexpMatchEasy0_32-8 231ns ± 1% 225ns ± 0% -2.52% (p=0.000 n=9+10) RegexpMatchEasy0_1K-8 1.63µs ± 0% 1.63µs ± 0% ~ (p=0.170 n=10+10) RegexpMatchEasy1_32-8 253ns ± 0% 249ns ± 0% -1.41% (p=0.000 n=9+10) RegexpMatchEasy1_1K-8 2.08µs ± 0% 2.08µs ± 0% -0.32% (p=0.000 n=9+10) RegexpMatchMedium_32-8 355ns ± 1% 351ns ± 0% -1.04% (p=0.007 n=10+7) RegexpMatchMedium_1K-8 104µs ± 0% 104µs ± 0% ~ (p=0.148 n=10+10) RegexpMatchHard_32-8 5.79µs ± 0% 5.79µs ± 0% ~ (p=0.578 n=10+10) RegexpMatchHard_1K-8 176µs ± 0% 176µs ± 0% ~ (p=0.137 n=10+10) Revcomp-8 1.37s ± 1% 1.36s ± 1% -0.26% (p=0.023 n=10+10) Template-8 151ms ± 1% 154ms ± 1% +2.14% (p=0.000 n=9+10) TimeParse-8 723ns ± 2% 721ns ± 1% ~ (p=0.592 n=10+10) TimeFormat-8 804ns ± 2% 798ns ± 3% ~ (p=0.344 n=10+10) [Geo mean] 154µs 154µs -0.02% Therefore remove this pass. Also reduce text size by 0.5~2%. Comment out some dead code in runtime/sys_nacl_amd64p32.s which contains undefined symbols. Change-Id: I1473986fe5b18b3d2554ce96cdc6f0999b8d955d Reviewed-on: https://go-review.googlesource.com/36205 Run-TryBot: Cherry Zhang <cherryyz@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
parent
76d4274491
commit
bed8129ee6
9 changed files with 34 additions and 1126 deletions
|
|
@ -34,7 +34,6 @@ import (
|
||||||
"cmd/internal/obj"
|
"cmd/internal/obj"
|
||||||
"cmd/internal/sys"
|
"cmd/internal/sys"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"math"
|
"math"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -862,183 +861,6 @@ func initdiv(ctxt *obj.Link) {
|
||||||
ctxt.Sym_modu = obj.Linklookup(ctxt, "_modu", 0)
|
ctxt.Sym_modu = obj.Linklookup(ctxt, "_modu", 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func follow(ctxt *obj.Link, s *obj.LSym) {
|
|
||||||
ctxt.Cursym = s
|
|
||||||
|
|
||||||
firstp := ctxt.NewProg()
|
|
||||||
lastp := firstp
|
|
||||||
xfol(ctxt, s.Text, &lastp)
|
|
||||||
lastp.Link = nil
|
|
||||||
s.Text = firstp.Link
|
|
||||||
}
|
|
||||||
|
|
||||||
func relinv(a obj.As) obj.As {
|
|
||||||
switch a {
|
|
||||||
case ABEQ:
|
|
||||||
return ABNE
|
|
||||||
case ABNE:
|
|
||||||
return ABEQ
|
|
||||||
case ABCS:
|
|
||||||
return ABCC
|
|
||||||
case ABHS:
|
|
||||||
return ABLO
|
|
||||||
case ABCC:
|
|
||||||
return ABCS
|
|
||||||
case ABLO:
|
|
||||||
return ABHS
|
|
||||||
case ABMI:
|
|
||||||
return ABPL
|
|
||||||
case ABPL:
|
|
||||||
return ABMI
|
|
||||||
case ABVS:
|
|
||||||
return ABVC
|
|
||||||
case ABVC:
|
|
||||||
return ABVS
|
|
||||||
case ABHI:
|
|
||||||
return ABLS
|
|
||||||
case ABLS:
|
|
||||||
return ABHI
|
|
||||||
case ABGE:
|
|
||||||
return ABLT
|
|
||||||
case ABLT:
|
|
||||||
return ABGE
|
|
||||||
case ABGT:
|
|
||||||
return ABLE
|
|
||||||
case ABLE:
|
|
||||||
return ABGT
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Fatalf("unknown relation: %s", Anames[a])
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func xfol(ctxt *obj.Link, p *obj.Prog, last **obj.Prog) {
|
|
||||||
var q *obj.Prog
|
|
||||||
var r *obj.Prog
|
|
||||||
var i int
|
|
||||||
|
|
||||||
loop:
|
|
||||||
if p == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
a := p.As
|
|
||||||
if a == AB {
|
|
||||||
q = p.Pcond
|
|
||||||
if q != nil && q.As != obj.ATEXT {
|
|
||||||
p.Mark |= FOLL
|
|
||||||
p = q
|
|
||||||
if p.Mark&FOLL == 0 {
|
|
||||||
goto loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.Mark&FOLL != 0 {
|
|
||||||
i = 0
|
|
||||||
q = p
|
|
||||||
for ; i < 4; i, q = i+1, q.Link {
|
|
||||||
if q == *last || q == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
a = q.As
|
|
||||||
if a == obj.ANOP {
|
|
||||||
i--
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if a == AB || (a == obj.ARET && q.Scond == C_SCOND_NONE) || a == ARFE || a == obj.AUNDEF {
|
|
||||||
goto copy
|
|
||||||
}
|
|
||||||
if q.Pcond == nil || (q.Pcond.Mark&FOLL != 0) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if a != ABEQ && a != ABNE {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
copy:
|
|
||||||
for {
|
|
||||||
r = ctxt.NewProg()
|
|
||||||
*r = *p
|
|
||||||
if r.Mark&FOLL == 0 {
|
|
||||||
fmt.Printf("can't happen 1\n")
|
|
||||||
}
|
|
||||||
r.Mark |= FOLL
|
|
||||||
if p != q {
|
|
||||||
p = p.Link
|
|
||||||
(*last).Link = r
|
|
||||||
*last = r
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
(*last).Link = r
|
|
||||||
*last = r
|
|
||||||
if a == AB || (a == obj.ARET && q.Scond == C_SCOND_NONE) || a == ARFE || a == obj.AUNDEF {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
r.As = ABNE
|
|
||||||
if a == ABNE {
|
|
||||||
r.As = ABEQ
|
|
||||||
}
|
|
||||||
r.Pcond = p.Link
|
|
||||||
r.Link = p.Pcond
|
|
||||||
if r.Link.Mark&FOLL == 0 {
|
|
||||||
xfol(ctxt, r.Link, last)
|
|
||||||
}
|
|
||||||
if r.Pcond.Mark&FOLL == 0 {
|
|
||||||
fmt.Printf("can't happen 2\n")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
a = AB
|
|
||||||
q = ctxt.NewProg()
|
|
||||||
q.As = a
|
|
||||||
q.Pos = p.Pos
|
|
||||||
q.To.Type = obj.TYPE_BRANCH
|
|
||||||
q.To.Offset = p.Pc
|
|
||||||
q.Pcond = p
|
|
||||||
p = q
|
|
||||||
}
|
|
||||||
|
|
||||||
p.Mark |= FOLL
|
|
||||||
(*last).Link = p
|
|
||||||
*last = p
|
|
||||||
if a == AB || (a == obj.ARET && p.Scond == C_SCOND_NONE) || a == ARFE || a == obj.AUNDEF {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.Pcond != nil {
|
|
||||||
if a != ABL && a != ABX && p.Link != nil {
|
|
||||||
q = obj.Brchain(ctxt, p.Link)
|
|
||||||
if a != obj.ATEXT {
|
|
||||||
if q != nil && (q.Mark&FOLL != 0) {
|
|
||||||
p.As = relinv(a)
|
|
||||||
p.Link = p.Pcond
|
|
||||||
p.Pcond = q
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
xfol(ctxt, p.Link, last)
|
|
||||||
q = obj.Brchain(ctxt, p.Pcond)
|
|
||||||
if q == nil {
|
|
||||||
q = p.Pcond
|
|
||||||
}
|
|
||||||
if q.Mark&FOLL != 0 {
|
|
||||||
p.Pcond = q
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
p = q
|
|
||||||
goto loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p = p.Link
|
|
||||||
goto loop
|
|
||||||
}
|
|
||||||
|
|
||||||
var unaryDst = map[obj.As]bool{
|
var unaryDst = map[obj.As]bool{
|
||||||
ASWI: true,
|
ASWI: true,
|
||||||
AWORD: true,
|
AWORD: true,
|
||||||
|
|
@ -1048,7 +870,6 @@ var Linkarm = obj.LinkArch{
|
||||||
Arch: sys.ArchARM,
|
Arch: sys.ArchARM,
|
||||||
Preprocess: preprocess,
|
Preprocess: preprocess,
|
||||||
Assemble: span5,
|
Assemble: span5,
|
||||||
Follow: follow,
|
|
||||||
Progedit: progedit,
|
Progedit: progedit,
|
||||||
UnaryDst: unaryDst,
|
UnaryDst: unaryDst,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,6 @@ import (
|
||||||
"cmd/internal/obj"
|
"cmd/internal/obj"
|
||||||
"cmd/internal/sys"
|
"cmd/internal/sys"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"math"
|
"math"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -443,191 +442,6 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog) {
|
||||||
obj.Nopout(p)
|
obj.Nopout(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
func follow(ctxt *obj.Link, s *obj.LSym) {
|
|
||||||
ctxt.Cursym = s
|
|
||||||
|
|
||||||
firstp := ctxt.NewProg()
|
|
||||||
lastp := firstp
|
|
||||||
xfol(ctxt, s.Text, &lastp)
|
|
||||||
lastp.Link = nil
|
|
||||||
s.Text = firstp.Link
|
|
||||||
}
|
|
||||||
|
|
||||||
func relinv(a obj.As) obj.As {
|
|
||||||
switch a {
|
|
||||||
case ABEQ:
|
|
||||||
return ABNE
|
|
||||||
case ABNE:
|
|
||||||
return ABEQ
|
|
||||||
case ABCS:
|
|
||||||
return ABCC
|
|
||||||
case ABHS:
|
|
||||||
return ABLO
|
|
||||||
case ABCC:
|
|
||||||
return ABCS
|
|
||||||
case ABLO:
|
|
||||||
return ABHS
|
|
||||||
case ABMI:
|
|
||||||
return ABPL
|
|
||||||
case ABPL:
|
|
||||||
return ABMI
|
|
||||||
case ABVS:
|
|
||||||
return ABVC
|
|
||||||
case ABVC:
|
|
||||||
return ABVS
|
|
||||||
case ABHI:
|
|
||||||
return ABLS
|
|
||||||
case ABLS:
|
|
||||||
return ABHI
|
|
||||||
case ABGE:
|
|
||||||
return ABLT
|
|
||||||
case ABLT:
|
|
||||||
return ABGE
|
|
||||||
case ABGT:
|
|
||||||
return ABLE
|
|
||||||
case ABLE:
|
|
||||||
return ABGT
|
|
||||||
case ACBZ:
|
|
||||||
return ACBNZ
|
|
||||||
case ACBNZ:
|
|
||||||
return ACBZ
|
|
||||||
case ACBZW:
|
|
||||||
return ACBNZW
|
|
||||||
case ACBNZW:
|
|
||||||
return ACBZW
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Fatalf("unknown relation: %s", Anames[a-obj.ABaseARM64])
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func xfol(ctxt *obj.Link, p *obj.Prog, last **obj.Prog) {
|
|
||||||
var q *obj.Prog
|
|
||||||
var r *obj.Prog
|
|
||||||
var i int
|
|
||||||
|
|
||||||
loop:
|
|
||||||
if p == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
a := p.As
|
|
||||||
if a == AB {
|
|
||||||
q = p.Pcond
|
|
||||||
if q != nil {
|
|
||||||
p.Mark |= FOLL
|
|
||||||
p = q
|
|
||||||
if !(p.Mark&FOLL != 0) {
|
|
||||||
goto loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.Mark&FOLL != 0 {
|
|
||||||
i = 0
|
|
||||||
q = p
|
|
||||||
for ; i < 4; i, q = i+1, q.Link {
|
|
||||||
if q == *last || q == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
a = q.As
|
|
||||||
if a == obj.ANOP {
|
|
||||||
i--
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if a == AB || a == obj.ARET || a == AERET {
|
|
||||||
goto copy
|
|
||||||
}
|
|
||||||
if q.Pcond == nil || (q.Pcond.Mark&FOLL != 0) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if a != ABEQ && a != ABNE {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
copy:
|
|
||||||
for {
|
|
||||||
r = ctxt.NewProg()
|
|
||||||
*r = *p
|
|
||||||
if !(r.Mark&FOLL != 0) {
|
|
||||||
fmt.Printf("can't happen 1\n")
|
|
||||||
}
|
|
||||||
r.Mark |= FOLL
|
|
||||||
if p != q {
|
|
||||||
p = p.Link
|
|
||||||
(*last).Link = r
|
|
||||||
*last = r
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
(*last).Link = r
|
|
||||||
*last = r
|
|
||||||
if a == AB || a == obj.ARET || a == AERET {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if a == ABNE {
|
|
||||||
r.As = ABEQ
|
|
||||||
} else {
|
|
||||||
r.As = ABNE
|
|
||||||
}
|
|
||||||
r.Pcond = p.Link
|
|
||||||
r.Link = p.Pcond
|
|
||||||
if !(r.Link.Mark&FOLL != 0) {
|
|
||||||
xfol(ctxt, r.Link, last)
|
|
||||||
}
|
|
||||||
if !(r.Pcond.Mark&FOLL != 0) {
|
|
||||||
fmt.Printf("can't happen 2\n")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
a = AB
|
|
||||||
q = ctxt.NewProg()
|
|
||||||
q.As = a
|
|
||||||
q.Pos = p.Pos
|
|
||||||
q.To.Type = obj.TYPE_BRANCH
|
|
||||||
q.To.Offset = p.Pc
|
|
||||||
q.Pcond = p
|
|
||||||
p = q
|
|
||||||
}
|
|
||||||
|
|
||||||
p.Mark |= FOLL
|
|
||||||
(*last).Link = p
|
|
||||||
*last = p
|
|
||||||
if a == AB || a == obj.ARET || a == AERET {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if p.Pcond != nil {
|
|
||||||
if a != ABL && p.Link != nil {
|
|
||||||
q = obj.Brchain(ctxt, p.Link)
|
|
||||||
if a != obj.ATEXT {
|
|
||||||
if q != nil && (q.Mark&FOLL != 0) {
|
|
||||||
p.As = relinv(a)
|
|
||||||
p.Link = p.Pcond
|
|
||||||
p.Pcond = q
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
xfol(ctxt, p.Link, last)
|
|
||||||
q = obj.Brchain(ctxt, p.Pcond)
|
|
||||||
if q == nil {
|
|
||||||
q = p.Pcond
|
|
||||||
}
|
|
||||||
if q.Mark&FOLL != 0 {
|
|
||||||
p.Pcond = q
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
p = q
|
|
||||||
goto loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p = p.Link
|
|
||||||
goto loop
|
|
||||||
}
|
|
||||||
|
|
||||||
func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
|
func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
|
||||||
ctxt.Cursym = cursym
|
ctxt.Cursym = cursym
|
||||||
|
|
||||||
|
|
@ -998,7 +812,6 @@ var Linkarm64 = obj.LinkArch{
|
||||||
Arch: sys.ArchARM64,
|
Arch: sys.ArchARM64,
|
||||||
Preprocess: preprocess,
|
Preprocess: preprocess,
|
||||||
Assemble: span7,
|
Assemble: span7,
|
||||||
Follow: follow,
|
|
||||||
Progedit: progedit,
|
Progedit: progedit,
|
||||||
UnaryDst: unaryDst,
|
UnaryDst: unaryDst,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -804,7 +804,6 @@ type LinkArch struct {
|
||||||
*sys.Arch
|
*sys.Arch
|
||||||
Preprocess func(*Link, *LSym)
|
Preprocess func(*Link, *LSym)
|
||||||
Assemble func(*Link, *LSym)
|
Assemble func(*Link, *LSym)
|
||||||
Follow func(*Link, *LSym)
|
|
||||||
Progedit func(*Link, *Prog)
|
Progedit func(*Link, *Prog)
|
||||||
UnaryDst map[As]bool // Instruction takes one operand, a destination.
|
UnaryDst map[As]bool // Instruction takes one operand, a destination.
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1418,151 +1418,10 @@ func compound(ctxt *obj.Link, p *obj.Prog) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func follow(ctxt *obj.Link, s *obj.LSym) {
|
|
||||||
ctxt.Cursym = s
|
|
||||||
|
|
||||||
firstp := ctxt.NewProg()
|
|
||||||
lastp := firstp
|
|
||||||
xfol(ctxt, s.Text, &lastp)
|
|
||||||
lastp.Link = nil
|
|
||||||
s.Text = firstp.Link
|
|
||||||
}
|
|
||||||
|
|
||||||
func xfol(ctxt *obj.Link, p *obj.Prog, last **obj.Prog) {
|
|
||||||
var q *obj.Prog
|
|
||||||
var r *obj.Prog
|
|
||||||
var i int
|
|
||||||
|
|
||||||
loop:
|
|
||||||
if p == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
a := p.As
|
|
||||||
if a == AJMP {
|
|
||||||
q = p.Pcond
|
|
||||||
if (p.Mark&NOSCHED != 0) || q != nil && (q.Mark&NOSCHED != 0) {
|
|
||||||
p.Mark |= FOLL
|
|
||||||
(*last).Link = p
|
|
||||||
*last = p
|
|
||||||
p = p.Link
|
|
||||||
xfol(ctxt, p, last)
|
|
||||||
p = q
|
|
||||||
if p != nil && p.Mark&FOLL == 0 {
|
|
||||||
goto loop
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if q != nil {
|
|
||||||
p.Mark |= FOLL
|
|
||||||
p = q
|
|
||||||
if p.Mark&FOLL == 0 {
|
|
||||||
goto loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.Mark&FOLL != 0 {
|
|
||||||
i = 0
|
|
||||||
q = p
|
|
||||||
for ; i < 4; i, q = i+1, q.Link {
|
|
||||||
if q == *last || (q.Mark&NOSCHED != 0) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
a = q.As
|
|
||||||
if a == obj.ANOP {
|
|
||||||
i--
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if a == AJMP || a == ARET || a == ARFE {
|
|
||||||
goto copy
|
|
||||||
}
|
|
||||||
if q.Pcond == nil || (q.Pcond.Mark&FOLL != 0) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if a != ABEQ && a != ABNE {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
copy:
|
|
||||||
for {
|
|
||||||
r = ctxt.NewProg()
|
|
||||||
*r = *p
|
|
||||||
if r.Mark&FOLL == 0 {
|
|
||||||
fmt.Printf("can't happen 1\n")
|
|
||||||
}
|
|
||||||
r.Mark |= FOLL
|
|
||||||
if p != q {
|
|
||||||
p = p.Link
|
|
||||||
(*last).Link = r
|
|
||||||
*last = r
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
(*last).Link = r
|
|
||||||
*last = r
|
|
||||||
if a == AJMP || a == ARET || a == ARFE {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
r.As = ABNE
|
|
||||||
if a == ABNE {
|
|
||||||
r.As = ABEQ
|
|
||||||
}
|
|
||||||
r.Pcond = p.Link
|
|
||||||
r.Link = p.Pcond
|
|
||||||
if r.Link.Mark&FOLL == 0 {
|
|
||||||
xfol(ctxt, r.Link, last)
|
|
||||||
}
|
|
||||||
if r.Pcond.Mark&FOLL == 0 {
|
|
||||||
fmt.Printf("can't happen 2\n")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
a = AJMP
|
|
||||||
q = ctxt.NewProg()
|
|
||||||
q.As = a
|
|
||||||
q.Pos = p.Pos
|
|
||||||
q.To.Type = obj.TYPE_BRANCH
|
|
||||||
q.To.Offset = p.Pc
|
|
||||||
q.Pcond = p
|
|
||||||
p = q
|
|
||||||
}
|
|
||||||
|
|
||||||
p.Mark |= FOLL
|
|
||||||
(*last).Link = p
|
|
||||||
*last = p
|
|
||||||
if a == AJMP || a == ARET || a == ARFE {
|
|
||||||
if p.Mark&NOSCHED != 0 {
|
|
||||||
p = p.Link
|
|
||||||
goto loop
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.Pcond != nil {
|
|
||||||
if a != AJAL && p.Link != nil {
|
|
||||||
xfol(ctxt, p.Link, last)
|
|
||||||
p = p.Pcond
|
|
||||||
if p == nil || (p.Mark&FOLL != 0) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
goto loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p = p.Link
|
|
||||||
goto loop
|
|
||||||
}
|
|
||||||
|
|
||||||
var Linkmips64 = obj.LinkArch{
|
var Linkmips64 = obj.LinkArch{
|
||||||
Arch: sys.ArchMIPS64,
|
Arch: sys.ArchMIPS64,
|
||||||
Preprocess: preprocess,
|
Preprocess: preprocess,
|
||||||
Assemble: span0,
|
Assemble: span0,
|
||||||
Follow: follow,
|
|
||||||
Progedit: progedit,
|
Progedit: progedit,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1570,7 +1429,6 @@ var Linkmips64le = obj.LinkArch{
|
||||||
Arch: sys.ArchMIPS64LE,
|
Arch: sys.ArchMIPS64LE,
|
||||||
Preprocess: preprocess,
|
Preprocess: preprocess,
|
||||||
Assemble: span0,
|
Assemble: span0,
|
||||||
Follow: follow,
|
|
||||||
Progedit: progedit,
|
Progedit: progedit,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1578,7 +1436,6 @@ var Linkmips = obj.LinkArch{
|
||||||
Arch: sys.ArchMIPS,
|
Arch: sys.ArchMIPS,
|
||||||
Preprocess: preprocess,
|
Preprocess: preprocess,
|
||||||
Assemble: span0,
|
Assemble: span0,
|
||||||
Follow: follow,
|
|
||||||
Progedit: progedit,
|
Progedit: progedit,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1586,6 +1443,5 @@ var Linkmipsle = obj.LinkArch{
|
||||||
Arch: sys.ArchMIPSLE,
|
Arch: sys.ArchMIPSLE,
|
||||||
Preprocess: preprocess,
|
Preprocess: preprocess,
|
||||||
Assemble: span0,
|
Assemble: span0,
|
||||||
Follow: follow,
|
|
||||||
Progedit: progedit,
|
Progedit: progedit,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -159,9 +159,6 @@ func flushplist(ctxt *Link, freeProgs bool) {
|
||||||
for _, s := range text {
|
for _, s := range text {
|
||||||
mkfwd(s)
|
mkfwd(s)
|
||||||
linkpatch(ctxt, s)
|
linkpatch(ctxt, s)
|
||||||
if ctxt.Flag_optimize {
|
|
||||||
ctxt.Arch.Follow(ctxt, s)
|
|
||||||
}
|
|
||||||
ctxt.Arch.Preprocess(ctxt, s)
|
ctxt.Arch.Preprocess(ctxt, s)
|
||||||
ctxt.Arch.Assemble(ctxt, s)
|
ctxt.Arch.Assemble(ctxt, s)
|
||||||
fieldtrack(ctxt, s)
|
fieldtrack(ctxt, s)
|
||||||
|
|
|
||||||
|
|
@ -1067,177 +1067,10 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32) *obj.Prog {
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func follow(ctxt *obj.Link, s *obj.LSym) {
|
|
||||||
ctxt.Cursym = s
|
|
||||||
|
|
||||||
firstp := ctxt.NewProg()
|
|
||||||
lastp := firstp
|
|
||||||
xfol(ctxt, s.Text, &lastp)
|
|
||||||
lastp.Link = nil
|
|
||||||
s.Text = firstp.Link
|
|
||||||
}
|
|
||||||
|
|
||||||
func relinv(a obj.As) obj.As {
|
|
||||||
switch a {
|
|
||||||
case ABEQ:
|
|
||||||
return ABNE
|
|
||||||
case ABNE:
|
|
||||||
return ABEQ
|
|
||||||
|
|
||||||
case ABGE:
|
|
||||||
return ABLT
|
|
||||||
case ABLT:
|
|
||||||
return ABGE
|
|
||||||
|
|
||||||
case ABGT:
|
|
||||||
return ABLE
|
|
||||||
case ABLE:
|
|
||||||
return ABGT
|
|
||||||
|
|
||||||
case ABVC:
|
|
||||||
return ABVS
|
|
||||||
case ABVS:
|
|
||||||
return ABVC
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func xfol(ctxt *obj.Link, p *obj.Prog, last **obj.Prog) {
|
|
||||||
var q *obj.Prog
|
|
||||||
var r *obj.Prog
|
|
||||||
var b obj.As
|
|
||||||
var i int
|
|
||||||
|
|
||||||
loop:
|
|
||||||
if p == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
a := p.As
|
|
||||||
if a == ABR {
|
|
||||||
q = p.Pcond
|
|
||||||
if (p.Mark&NOSCHED != 0) || q != nil && (q.Mark&NOSCHED != 0) {
|
|
||||||
p.Mark |= FOLL
|
|
||||||
(*last).Link = p
|
|
||||||
*last = p
|
|
||||||
p = p.Link
|
|
||||||
xfol(ctxt, p, last)
|
|
||||||
p = q
|
|
||||||
if p != nil && p.Mark&FOLL == 0 {
|
|
||||||
goto loop
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if q != nil {
|
|
||||||
p.Mark |= FOLL
|
|
||||||
p = q
|
|
||||||
if p.Mark&FOLL == 0 {
|
|
||||||
goto loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.Mark&FOLL != 0 {
|
|
||||||
i = 0
|
|
||||||
q = p
|
|
||||||
for ; i < 4; i, q = i+1, q.Link {
|
|
||||||
if q == *last || (q.Mark&NOSCHED != 0) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
b = 0 /* set */
|
|
||||||
a = q.As
|
|
||||||
if a == obj.ANOP {
|
|
||||||
i--
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if a == ABR || a == obj.ARET || a == ARFI || a == ARFCI || a == ARFID || a == AHRFID {
|
|
||||||
goto copy
|
|
||||||
}
|
|
||||||
if q.Pcond == nil || (q.Pcond.Mark&FOLL != 0) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
b = relinv(a)
|
|
||||||
if b == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
copy:
|
|
||||||
for {
|
|
||||||
r = ctxt.NewProg()
|
|
||||||
*r = *p
|
|
||||||
if r.Mark&FOLL == 0 {
|
|
||||||
fmt.Printf("can't happen 1\n")
|
|
||||||
}
|
|
||||||
r.Mark |= FOLL
|
|
||||||
if p != q {
|
|
||||||
p = p.Link
|
|
||||||
(*last).Link = r
|
|
||||||
*last = r
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
(*last).Link = r
|
|
||||||
*last = r
|
|
||||||
if a == ABR || a == obj.ARET || a == ARFI || a == ARFCI || a == ARFID || a == AHRFID {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
r.As = b
|
|
||||||
r.Pcond = p.Link
|
|
||||||
r.Link = p.Pcond
|
|
||||||
if r.Link.Mark&FOLL == 0 {
|
|
||||||
xfol(ctxt, r.Link, last)
|
|
||||||
}
|
|
||||||
if r.Pcond.Mark&FOLL == 0 {
|
|
||||||
fmt.Printf("can't happen 2\n")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
a = ABR
|
|
||||||
q = ctxt.NewProg()
|
|
||||||
q.As = a
|
|
||||||
q.Pos = p.Pos
|
|
||||||
q.To.Type = obj.TYPE_BRANCH
|
|
||||||
q.To.Offset = p.Pc
|
|
||||||
q.Pcond = p
|
|
||||||
p = q
|
|
||||||
}
|
|
||||||
|
|
||||||
p.Mark |= FOLL
|
|
||||||
(*last).Link = p
|
|
||||||
*last = p
|
|
||||||
if a == ABR || a == obj.ARET || a == ARFI || a == ARFCI || a == ARFID || a == AHRFID {
|
|
||||||
if p.Mark&NOSCHED != 0 {
|
|
||||||
p = p.Link
|
|
||||||
goto loop
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.Pcond != nil {
|
|
||||||
if a != ABL && p.Link != nil {
|
|
||||||
xfol(ctxt, p.Link, last)
|
|
||||||
p = p.Pcond
|
|
||||||
if p == nil || (p.Mark&FOLL != 0) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
goto loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p = p.Link
|
|
||||||
goto loop
|
|
||||||
}
|
|
||||||
|
|
||||||
var Linkppc64 = obj.LinkArch{
|
var Linkppc64 = obj.LinkArch{
|
||||||
Arch: sys.ArchPPC64,
|
Arch: sys.ArchPPC64,
|
||||||
Preprocess: preprocess,
|
Preprocess: preprocess,
|
||||||
Assemble: span9,
|
Assemble: span9,
|
||||||
Follow: follow,
|
|
||||||
Progedit: progedit,
|
Progedit: progedit,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1245,6 +1078,5 @@ var Linkppc64le = obj.LinkArch{
|
||||||
Arch: sys.ArchPPC64LE,
|
Arch: sys.ArchPPC64LE,
|
||||||
Preprocess: preprocess,
|
Preprocess: preprocess,
|
||||||
Assemble: span9,
|
Assemble: span9,
|
||||||
Follow: follow,
|
|
||||||
Progedit: progedit,
|
Progedit: progedit,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -837,176 +837,6 @@ func stacksplitPost(ctxt *obj.Link, p *obj.Prog, pPre *obj.Prog, pPreempt *obj.P
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
var pc_cnt int64
|
|
||||||
|
|
||||||
func follow(ctxt *obj.Link, s *obj.LSym) {
|
|
||||||
ctxt.Cursym = s
|
|
||||||
|
|
||||||
pc_cnt = 0
|
|
||||||
firstp := ctxt.NewProg()
|
|
||||||
lastp := firstp
|
|
||||||
xfol(ctxt, s.Text, &lastp)
|
|
||||||
lastp.Link = nil
|
|
||||||
s.Text = firstp.Link
|
|
||||||
}
|
|
||||||
|
|
||||||
func relinv(a obj.As) obj.As {
|
|
||||||
switch a {
|
|
||||||
case ABEQ:
|
|
||||||
return ABNE
|
|
||||||
case ABNE:
|
|
||||||
return ABEQ
|
|
||||||
|
|
||||||
case ABGE:
|
|
||||||
return ABLT
|
|
||||||
case ABLT:
|
|
||||||
return ABGE
|
|
||||||
|
|
||||||
case ABGT:
|
|
||||||
return ABLE
|
|
||||||
case ABLE:
|
|
||||||
return ABGT
|
|
||||||
|
|
||||||
case ABVC:
|
|
||||||
return ABVS
|
|
||||||
case ABVS:
|
|
||||||
return ABVC
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func xfol(ctxt *obj.Link, p *obj.Prog, last **obj.Prog) {
|
|
||||||
var q *obj.Prog
|
|
||||||
var r *obj.Prog
|
|
||||||
var b obj.As
|
|
||||||
|
|
||||||
for p != nil {
|
|
||||||
a := p.As
|
|
||||||
if a == ABR {
|
|
||||||
q = p.Pcond
|
|
||||||
if (p.Mark&NOSCHED != 0) || q != nil && (q.Mark&NOSCHED != 0) {
|
|
||||||
p.Mark |= FOLL
|
|
||||||
(*last).Link = p
|
|
||||||
*last = p
|
|
||||||
(*last).Pc = pc_cnt
|
|
||||||
pc_cnt += 1
|
|
||||||
p = p.Link
|
|
||||||
xfol(ctxt, p, last)
|
|
||||||
p = q
|
|
||||||
if p != nil && p.Mark&FOLL == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if q != nil {
|
|
||||||
p.Mark |= FOLL
|
|
||||||
p = q
|
|
||||||
if p.Mark&FOLL == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.Mark&FOLL != 0 {
|
|
||||||
q = p
|
|
||||||
for i := 0; i < 4; i, q = i+1, q.Link {
|
|
||||||
if q == *last || (q.Mark&NOSCHED != 0) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
b = 0 /* set */
|
|
||||||
a = q.As
|
|
||||||
if a == obj.ANOP {
|
|
||||||
i--
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if a != ABR && a != obj.ARET {
|
|
||||||
if q.Pcond == nil || (q.Pcond.Mark&FOLL != 0) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
b = relinv(a)
|
|
||||||
if b == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for {
|
|
||||||
r = ctxt.NewProg()
|
|
||||||
*r = *p
|
|
||||||
if r.Mark&FOLL == 0 {
|
|
||||||
fmt.Printf("can't happen 1\n")
|
|
||||||
}
|
|
||||||
r.Mark |= FOLL
|
|
||||||
if p != q {
|
|
||||||
p = p.Link
|
|
||||||
(*last).Link = r
|
|
||||||
*last = r
|
|
||||||
(*last).Pc = pc_cnt
|
|
||||||
pc_cnt += 1
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
(*last).Link = r
|
|
||||||
*last = r
|
|
||||||
(*last).Pc = pc_cnt
|
|
||||||
pc_cnt += 1
|
|
||||||
if a == ABR || a == obj.ARET {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
r.As = b
|
|
||||||
r.Pcond = p.Link
|
|
||||||
r.Link = p.Pcond
|
|
||||||
if r.Link.Mark&FOLL == 0 {
|
|
||||||
xfol(ctxt, r.Link, last)
|
|
||||||
}
|
|
||||||
if r.Pcond.Mark&FOLL == 0 {
|
|
||||||
fmt.Printf("can't happen 2\n")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
a = ABR
|
|
||||||
q = ctxt.NewProg()
|
|
||||||
q.As = a
|
|
||||||
q.Pos = p.Pos
|
|
||||||
q.To.Type = obj.TYPE_BRANCH
|
|
||||||
q.To.Offset = p.Pc
|
|
||||||
q.Pcond = p
|
|
||||||
p = q
|
|
||||||
}
|
|
||||||
|
|
||||||
p.Mark |= FOLL
|
|
||||||
(*last).Link = p
|
|
||||||
*last = p
|
|
||||||
(*last).Pc = pc_cnt
|
|
||||||
pc_cnt += 1
|
|
||||||
|
|
||||||
if a == ABR || a == obj.ARET {
|
|
||||||
if p.Mark&NOSCHED != 0 {
|
|
||||||
p = p.Link
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.Pcond != nil {
|
|
||||||
if a != ABL && p.Link != nil {
|
|
||||||
xfol(ctxt, p.Link, last)
|
|
||||||
p = p.Pcond
|
|
||||||
if p == nil || (p.Mark&FOLL != 0) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p = p.Link
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var unaryDst = map[obj.As]bool{
|
var unaryDst = map[obj.As]bool{
|
||||||
ASTCK: true,
|
ASTCK: true,
|
||||||
ASTCKC: true,
|
ASTCKC: true,
|
||||||
|
|
@ -1022,7 +852,6 @@ var Links390x = obj.LinkArch{
|
||||||
Arch: sys.ArchS390X,
|
Arch: sys.ArchS390X,
|
||||||
Preprocess: preprocess,
|
Preprocess: preprocess,
|
||||||
Assemble: spanz,
|
Assemble: spanz,
|
||||||
Follow: follow,
|
|
||||||
Progedit: progedit,
|
Progedit: progedit,
|
||||||
UnaryDst: unaryDst,
|
UnaryDst: unaryDst,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,6 @@ import (
|
||||||
"cmd/internal/obj"
|
"cmd/internal/obj"
|
||||||
"cmd/internal/sys"
|
"cmd/internal/sys"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"math"
|
"math"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
@ -1183,241 +1182,6 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32, textarg int32) *ob
|
||||||
return jls
|
return jls
|
||||||
}
|
}
|
||||||
|
|
||||||
func follow(ctxt *obj.Link, s *obj.LSym) {
|
|
||||||
ctxt.Cursym = s
|
|
||||||
|
|
||||||
firstp := ctxt.NewProg()
|
|
||||||
lastp := firstp
|
|
||||||
xfol(ctxt, s.Text, &lastp)
|
|
||||||
lastp.Link = nil
|
|
||||||
s.Text = firstp.Link
|
|
||||||
}
|
|
||||||
|
|
||||||
func nofollow(a obj.As) bool {
|
|
||||||
switch a {
|
|
||||||
case obj.AJMP,
|
|
||||||
obj.ARET,
|
|
||||||
AIRETL,
|
|
||||||
AIRETQ,
|
|
||||||
AIRETW,
|
|
||||||
ARETFL,
|
|
||||||
ARETFQ,
|
|
||||||
ARETFW,
|
|
||||||
obj.AUNDEF:
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func pushpop(a obj.As) bool {
|
|
||||||
switch a {
|
|
||||||
case APUSHL,
|
|
||||||
APUSHFL,
|
|
||||||
APUSHQ,
|
|
||||||
APUSHFQ,
|
|
||||||
APUSHW,
|
|
||||||
APUSHFW,
|
|
||||||
APOPL,
|
|
||||||
APOPFL,
|
|
||||||
APOPQ,
|
|
||||||
APOPFQ,
|
|
||||||
APOPW,
|
|
||||||
APOPFW:
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func relinv(a obj.As) obj.As {
|
|
||||||
switch a {
|
|
||||||
case AJEQ:
|
|
||||||
return AJNE
|
|
||||||
case AJNE:
|
|
||||||
return AJEQ
|
|
||||||
case AJLE:
|
|
||||||
return AJGT
|
|
||||||
case AJLS:
|
|
||||||
return AJHI
|
|
||||||
case AJLT:
|
|
||||||
return AJGE
|
|
||||||
case AJMI:
|
|
||||||
return AJPL
|
|
||||||
case AJGE:
|
|
||||||
return AJLT
|
|
||||||
case AJPL:
|
|
||||||
return AJMI
|
|
||||||
case AJGT:
|
|
||||||
return AJLE
|
|
||||||
case AJHI:
|
|
||||||
return AJLS
|
|
||||||
case AJCS:
|
|
||||||
return AJCC
|
|
||||||
case AJCC:
|
|
||||||
return AJCS
|
|
||||||
case AJPS:
|
|
||||||
return AJPC
|
|
||||||
case AJPC:
|
|
||||||
return AJPS
|
|
||||||
case AJOS:
|
|
||||||
return AJOC
|
|
||||||
case AJOC:
|
|
||||||
return AJOS
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Fatalf("unknown relation: %s", a)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func xfol(ctxt *obj.Link, p *obj.Prog, last **obj.Prog) {
|
|
||||||
var q *obj.Prog
|
|
||||||
var i int
|
|
||||||
var a obj.As
|
|
||||||
|
|
||||||
loop:
|
|
||||||
if p == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if p.As == obj.AJMP {
|
|
||||||
q = p.Pcond
|
|
||||||
if q != nil && q.As != obj.ATEXT {
|
|
||||||
/* mark instruction as done and continue layout at target of jump */
|
|
||||||
p.Mark |= DONE
|
|
||||||
|
|
||||||
p = q
|
|
||||||
if p.Mark&DONE == 0 {
|
|
||||||
goto loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.Mark&DONE != 0 {
|
|
||||||
/*
|
|
||||||
* p goes here, but already used it elsewhere.
|
|
||||||
* copy up to 4 instructions or else branch to other copy.
|
|
||||||
*/
|
|
||||||
i = 0
|
|
||||||
q = p
|
|
||||||
for ; i < 4; i, q = i+1, q.Link {
|
|
||||||
if q == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if q == *last {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
a = q.As
|
|
||||||
if a == obj.ANOP {
|
|
||||||
i--
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if nofollow(a) || pushpop(a) {
|
|
||||||
break // NOTE(rsc): arm does goto copy
|
|
||||||
}
|
|
||||||
if q.Pcond == nil || q.Pcond.Mark&DONE != 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if a == obj.ACALL || a == ALOOP {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for {
|
|
||||||
if p.As == obj.ANOP {
|
|
||||||
p = p.Link
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
q = obj.Copyp(ctxt, p)
|
|
||||||
p = p.Link
|
|
||||||
q.Mark |= DONE
|
|
||||||
(*last).Link = q
|
|
||||||
*last = q
|
|
||||||
if q.As != a || q.Pcond == nil || q.Pcond.Mark&DONE != 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
q.As = relinv(q.As)
|
|
||||||
p = q.Pcond
|
|
||||||
q.Pcond = q.Link
|
|
||||||
q.Link = p
|
|
||||||
xfol(ctxt, q.Link, last)
|
|
||||||
p = q.Link
|
|
||||||
if p.Mark&DONE != 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
goto loop
|
|
||||||
/* */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
q = ctxt.NewProg()
|
|
||||||
q.As = obj.AJMP
|
|
||||||
q.Pos = p.Pos
|
|
||||||
q.To.Type = obj.TYPE_BRANCH
|
|
||||||
q.To.Offset = p.Pc
|
|
||||||
q.Pcond = p
|
|
||||||
p = q
|
|
||||||
}
|
|
||||||
|
|
||||||
/* emit p */
|
|
||||||
p.Mark |= DONE
|
|
||||||
|
|
||||||
(*last).Link = p
|
|
||||||
*last = p
|
|
||||||
a = p.As
|
|
||||||
|
|
||||||
/* continue loop with what comes after p */
|
|
||||||
if nofollow(a) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if p.Pcond != nil && a != obj.ACALL {
|
|
||||||
/*
|
|
||||||
* some kind of conditional branch.
|
|
||||||
* recurse to follow one path.
|
|
||||||
* continue loop on the other.
|
|
||||||
*/
|
|
||||||
q = obj.Brchain(ctxt, p.Pcond)
|
|
||||||
if q != nil {
|
|
||||||
p.Pcond = q
|
|
||||||
}
|
|
||||||
q = obj.Brchain(ctxt, p.Link)
|
|
||||||
if q != nil {
|
|
||||||
p.Link = q
|
|
||||||
}
|
|
||||||
if p.From.Type == obj.TYPE_CONST {
|
|
||||||
if p.From.Offset == 1 {
|
|
||||||
/*
|
|
||||||
* expect conditional jump to be taken.
|
|
||||||
* rewrite so that's the fall-through case.
|
|
||||||
*/
|
|
||||||
p.As = relinv(a)
|
|
||||||
|
|
||||||
q = p.Link
|
|
||||||
p.Link = p.Pcond
|
|
||||||
p.Pcond = q
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
q = p.Link
|
|
||||||
if q.Mark&DONE != 0 {
|
|
||||||
if a != ALOOP {
|
|
||||||
p.As = relinv(a)
|
|
||||||
p.Link = p.Pcond
|
|
||||||
p.Pcond = q
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
xfol(ctxt, p.Link, last)
|
|
||||||
if p.Pcond.Mark&DONE != 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
p = p.Pcond
|
|
||||||
goto loop
|
|
||||||
}
|
|
||||||
|
|
||||||
p = p.Link
|
|
||||||
goto loop
|
|
||||||
}
|
|
||||||
|
|
||||||
var unaryDst = map[obj.As]bool{
|
var unaryDst = map[obj.As]bool{
|
||||||
ABSWAPL: true,
|
ABSWAPL: true,
|
||||||
ABSWAPQ: true,
|
ABSWAPQ: true,
|
||||||
|
|
@ -1472,7 +1236,6 @@ var Linkamd64 = obj.LinkArch{
|
||||||
Arch: sys.ArchAMD64,
|
Arch: sys.ArchAMD64,
|
||||||
Preprocess: preprocess,
|
Preprocess: preprocess,
|
||||||
Assemble: span6,
|
Assemble: span6,
|
||||||
Follow: follow,
|
|
||||||
Progedit: progedit,
|
Progedit: progedit,
|
||||||
UnaryDst: unaryDst,
|
UnaryDst: unaryDst,
|
||||||
}
|
}
|
||||||
|
|
@ -1481,7 +1244,6 @@ var Linkamd64p32 = obj.LinkArch{
|
||||||
Arch: sys.ArchAMD64P32,
|
Arch: sys.ArchAMD64P32,
|
||||||
Preprocess: preprocess,
|
Preprocess: preprocess,
|
||||||
Assemble: span6,
|
Assemble: span6,
|
||||||
Follow: follow,
|
|
||||||
Progedit: progedit,
|
Progedit: progedit,
|
||||||
UnaryDst: unaryDst,
|
UnaryDst: unaryDst,
|
||||||
}
|
}
|
||||||
|
|
@ -1490,7 +1252,6 @@ var Link386 = obj.LinkArch{
|
||||||
Arch: sys.Arch386,
|
Arch: sys.Arch386,
|
||||||
Preprocess: preprocess,
|
Preprocess: preprocess,
|
||||||
Assemble: span6,
|
Assemble: span6,
|
||||||
Follow: follow,
|
|
||||||
Progedit: progedit,
|
Progedit: progedit,
|
||||||
UnaryDst: unaryDst,
|
UnaryDst: unaryDst,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -366,40 +366,40 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$80
|
||||||
// 136(SI) is saved EFLAGS, never to be seen again
|
// 136(SI) is saved EFLAGS, never to be seen again
|
||||||
JMP SI
|
JMP SI
|
||||||
|
|
||||||
debughandler:
|
//debughandler:
|
||||||
// print basic information
|
//// print basic information
|
||||||
LEAL ctxt+0(FP), DI
|
//LEAL ctxt+0(FP), DI
|
||||||
MOVL $runtime·sigtrampf(SB), AX
|
//MOVL $runtime·sigtrampf(SB), AX
|
||||||
MOVL AX, 0(SP)
|
//MOVL AX, 0(SP)
|
||||||
MOVQ (16*4+16*8)(DI), BX // rip
|
//MOVQ (16*4+16*8)(DI), BX // rip
|
||||||
MOVQ BX, 8(SP)
|
//MOVQ BX, 8(SP)
|
||||||
MOVQ (16*4+0*8)(DI), BX // rax
|
//MOVQ (16*4+0*8)(DI), BX // rax
|
||||||
MOVQ BX, 16(SP)
|
//MOVQ BX, 16(SP)
|
||||||
MOVQ (16*4+1*8)(DI), BX // rcx
|
//MOVQ (16*4+1*8)(DI), BX // rcx
|
||||||
MOVQ BX, 24(SP)
|
//MOVQ BX, 24(SP)
|
||||||
MOVQ (16*4+2*8)(DI), BX // rdx
|
//MOVQ (16*4+2*8)(DI), BX // rdx
|
||||||
MOVQ BX, 32(SP)
|
//MOVQ BX, 32(SP)
|
||||||
MOVQ (16*4+3*8)(DI), BX // rbx
|
//MOVQ (16*4+3*8)(DI), BX // rbx
|
||||||
MOVQ BX, 40(SP)
|
//MOVQ BX, 40(SP)
|
||||||
MOVQ (16*4+7*8)(DI), BX // rdi
|
//MOVQ (16*4+7*8)(DI), BX // rdi
|
||||||
MOVQ BX, 48(SP)
|
//MOVQ BX, 48(SP)
|
||||||
MOVQ (16*4+15*8)(DI), BX // r15
|
//MOVQ (16*4+15*8)(DI), BX // r15
|
||||||
MOVQ BX, 56(SP)
|
//MOVQ BX, 56(SP)
|
||||||
MOVQ (16*4+4*8)(DI), BX // rsp
|
//MOVQ (16*4+4*8)(DI), BX // rsp
|
||||||
MOVQ 0(BX), BX
|
//MOVQ 0(BX), BX
|
||||||
MOVQ BX, 64(SP)
|
//MOVQ BX, 64(SP)
|
||||||
CALL runtime·printf(SB)
|
//CALL runtime·printf(SB)
|
||||||
|
//
|
||||||
LEAL ctxt+0(FP), DI
|
//LEAL ctxt+0(FP), DI
|
||||||
MOVQ (16*4+16*8)(DI), BX // rip
|
//MOVQ (16*4+16*8)(DI), BX // rip
|
||||||
MOVL BX, 0(SP)
|
//MOVL BX, 0(SP)
|
||||||
MOVQ (16*4+4*8)(DI), BX // rsp
|
//MOVQ (16*4+4*8)(DI), BX // rsp
|
||||||
MOVL BX, 4(SP)
|
//MOVL BX, 4(SP)
|
||||||
MOVL $0, 8(SP) // lr
|
//MOVL $0, 8(SP) // lr
|
||||||
get_tls(CX)
|
//get_tls(CX)
|
||||||
MOVL g(CX), BX
|
//MOVL g(CX), BX
|
||||||
MOVL BX, 12(SP) // gp
|
//MOVL BX, 12(SP) // gp
|
||||||
CALL runtime·traceback(SB)
|
//CALL runtime·traceback(SB)
|
||||||
|
|
||||||
notls:
|
notls:
|
||||||
MOVL 0, AX
|
MOVL 0, AX
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue