aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/internal/obj
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/internal/obj')
-rw-r--r--src/cmd/internal/obj/link.go6
-rw-r--r--src/cmd/internal/obj/obj.go29
-rw-r--r--src/cmd/internal/obj/pass.go1
-rw-r--r--src/cmd/internal/obj/util.go3
-rw-r--r--src/cmd/internal/obj/x86/a.out.go38
-rw-r--r--src/cmd/internal/obj/x86/asm6.go33
-rw-r--r--src/cmd/internal/obj/x86/obj6.go37
-rw-r--r--src/cmd/internal/obj/x86/obj6_test.go4
8 files changed, 97 insertions, 54 deletions
diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go
index e89c1412e2..4ae819178d 100644
--- a/src/cmd/internal/obj/link.go
+++ b/src/cmd/internal/obj/link.go
@@ -214,14 +214,14 @@ type Prog struct {
Spadj int32
As int16
Reg int16
- RegTo2 int16 // 2nd register output operand
- Mark uint16
+ RegTo2 int16 // 2nd register output operand
+ Mark uint16 // bitmask of arch-specific items
Optab uint16
Scond uint8
Back uint8
Ft uint8
Tt uint8
- Isize uint8
+ Isize uint8 // size of the instruction in bytes (x86 only)
Mode int8
Info ProgInfo
diff --git a/src/cmd/internal/obj/obj.go b/src/cmd/internal/obj/obj.go
index 343c93a6ee..f38078fca8 100644
--- a/src/cmd/internal/obj/obj.go
+++ b/src/cmd/internal/obj/obj.go
@@ -25,12 +25,13 @@ import (
// together, so that given (only) calls Push(10, "x.go", 1) and Pop(15),
// virtual line 12 corresponds to x.go line 3.
type LineHist struct {
- Top *LineStack // current top of stack
- Ranges []LineRange // ranges for lookup
- Dir string // directory to qualify relative paths
- TrimPathPrefix string // remove leading TrimPath from recorded file names
- GOROOT string // current GOROOT
- GOROOT_FINAL string // target GOROOT
+ Top *LineStack // current top of stack
+ Ranges []LineRange // ranges for lookup
+ Dir string // directory to qualify relative paths
+ TrimPathPrefix string // remove leading TrimPath from recorded file names
+ PrintFilenameOnly bool // ignore path when pretty-printing a line; internal use only
+ GOROOT string // current GOROOT
+ GOROOT_FINAL string // target GOROOT
}
// A LineStack is an entry in the recorded line history.
@@ -221,20 +222,28 @@ func (h *LineHist) LineString(lineno int) string {
return "<unknown line number>"
}
- text := fmt.Sprintf("%s:%d", stk.File, stk.fileLineAt(lineno))
+ filename := stk.File
+ if h.PrintFilenameOnly {
+ filename = filepath.Base(filename)
+ }
+ text := fmt.Sprintf("%s:%d", filename, stk.fileLineAt(lineno))
if stk.Directive && stk.Parent != nil {
stk = stk.Parent
- text += fmt.Sprintf("[%s:%d]", stk.File, stk.fileLineAt(lineno))
+ filename = stk.File
+ if h.PrintFilenameOnly {
+ filename = filepath.Base(filename)
+ }
+ text += fmt.Sprintf("[%s:%d]", filename, stk.fileLineAt(lineno))
}
const showFullStack = false // was used by old C compilers
if showFullStack {
for stk.Parent != nil {
lineno = stk.Lineno - 1
stk = stk.Parent
- text += fmt.Sprintf(" %s:%d", stk.File, stk.fileLineAt(lineno))
+ text += fmt.Sprintf(" %s:%d", filename, stk.fileLineAt(lineno))
if stk.Directive && stk.Parent != nil {
stk = stk.Parent
- text += fmt.Sprintf("[%s:%d]", stk.File, stk.fileLineAt(lineno))
+ text += fmt.Sprintf("[%s:%d]", filename, stk.fileLineAt(lineno))
}
}
}
diff --git a/src/cmd/internal/obj/pass.go b/src/cmd/internal/obj/pass.go
index ae38c4130a..f10fc60413 100644
--- a/src/cmd/internal/obj/pass.go
+++ b/src/cmd/internal/obj/pass.go
@@ -204,7 +204,6 @@ func linkpatch(ctxt *Link, sym *LSym) {
if ctxt.Flag_optimize {
for p := sym.Text; p != nil; p = p.Link {
- p.Mark = 0 /* initialization for follow */
if p.Pcond != nil {
p.Pcond = brloop(ctxt, p.Pcond)
if p.Pcond != nil {
diff --git a/src/cmd/internal/obj/util.go b/src/cmd/internal/obj/util.go
index 8ecf800502..b6e644372f 100644
--- a/src/cmd/internal/obj/util.go
+++ b/src/cmd/internal/obj/util.go
@@ -406,6 +406,9 @@ func Dconv(p *Prog, a *Addr) string {
if a.Index != REG_NONE {
str += fmt.Sprintf("(%v*%d)", Rconv(int(a.Index)), int(a.Scale))
}
+ if p.As == ATYPE && a.Gotype != nil {
+ str += fmt.Sprintf("%s", a.Gotype.Name)
+ }
case TYPE_CONST:
if a.Reg != 0 {
diff --git a/src/cmd/internal/obj/x86/a.out.go b/src/cmd/internal/obj/x86/a.out.go
index dacf612bc2..64bd865e42 100644
--- a/src/cmd/internal/obj/x86/a.out.go
+++ b/src/cmd/internal/obj/x86/a.out.go
@@ -34,6 +34,12 @@ import "cmd/internal/obj"
//go:generate go run ../stringer.go -i $GOFILE -o anames.go -p x86
+const (
+ /* mark flags */
+ DONE = 1 << iota
+ PRESERVEFLAGS // not allowed to clobber flags
+)
+
/*
* amd64
*/
@@ -114,23 +120,23 @@ const (
AINTO
AIRETL
AIRETW
- AJCC
- AJCS
+ AJCC // >= unsigned
+ AJCS // < unsigned
AJCXZL
- AJEQ
- AJGE
- AJGT
- AJHI
- AJLE
- AJLS
- AJLT
- AJMI
- AJNE
- AJOC
- AJOS
- AJPC
- AJPL
- AJPS
+ AJEQ // == (zero)
+ AJGE // >= signed
+ AJGT // > signed
+ AJHI // > unsigned
+ AJLE // <= signed
+ AJLS // <= unsigned
+ AJLT // < signed
+ AJMI // sign bit set (negative)
+ AJNE // != (nonzero)
+ AJOC // overflow clear
+ AJOS // overflow set
+ AJPC // parity clear
+ AJPL // sign bit clear (positive)
+ AJPS // parity set
ALAHF
ALARL
ALARW
diff --git a/src/cmd/internal/obj/x86/asm6.go b/src/cmd/internal/obj/x86/asm6.go
index 115350637f..9ab6615e43 100644
--- a/src/cmd/internal/obj/x86/asm6.go
+++ b/src/cmd/internal/obj/x86/asm6.go
@@ -1895,7 +1895,7 @@ func span6(ctxt *obj.Link, s *obj.LSym) {
// process forward jumps to p
for q = p.Rel; q != nil; q = q.Forwd {
- v = int32(p.Pc - (q.Pc + int64(q.Mark)))
+ v = int32(p.Pc - (q.Pc + int64(q.Isize)))
if q.Back&2 != 0 { // short
if v > 127 {
loop++
@@ -1908,7 +1908,7 @@ func span6(ctxt *obj.Link, s *obj.LSym) {
s.P[q.Pc+1] = byte(v)
}
} else {
- bp = s.P[q.Pc+int64(q.Mark)-4:]
+ bp = s.P[q.Pc+int64(q.Isize)-4:]
bp[0] = byte(v)
bp = bp[1:]
bp[0] = byte(v >> 8)
@@ -1931,7 +1931,6 @@ func span6(ctxt *obj.Link, s *obj.LSym) {
obj.Symgrow(ctxt, s, p.Pc+int64(m))
copy(s.P[p.Pc:][:m], ctxt.And[:m])
- p.Mark = uint16(m)
c += int32(m)
}
@@ -2272,8 +2271,28 @@ func oclass(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) int {
return Yxxx
case obj.TYPE_MEM:
- if a.Name != obj.NAME_NONE {
- if ctxt.Asmode == 64 && (a.Reg != REG_NONE || a.Index != REG_NONE || a.Scale != 0) {
+ if a.Index == REG_SP {
+ // Can't use SP as the index register
+ return Yxxx
+ }
+ if ctxt.Asmode == 64 {
+ switch a.Name {
+ case obj.NAME_EXTERN, obj.NAME_STATIC, obj.NAME_GOTREF:
+ // Global variables can't use index registers and their
+ // base register is %rip (%rip is encoded as REG_NONE).
+ if a.Reg != REG_NONE || a.Index != REG_NONE || a.Scale != 0 {
+ return Yxxx
+ }
+ case obj.NAME_AUTO, obj.NAME_PARAM:
+ // These names must have a base of SP. The old compiler
+ // uses 0 for the base register. SSA uses REG_SP.
+ if a.Reg != REG_SP && a.Reg != 0 {
+ return Yxxx
+ }
+ case obj.NAME_NONE:
+ // everything is ok
+ default:
+ // unknown name
return Yxxx
}
}
@@ -2321,6 +2340,10 @@ func oclass(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) int {
v = int64(int32(v))
}
if v == 0 {
+ if p.Mark&PRESERVEFLAGS != 0 {
+ // If PRESERVEFLAGS is set, avoid MOV $0, AX turning into XOR AX, AX.
+ return Yu7
+ }
return Yi0
}
if v == 1 {
diff --git a/src/cmd/internal/obj/x86/obj6.go b/src/cmd/internal/obj/x86/obj6.go
index 6332b7e4d9..3f8426ae38 100644
--- a/src/cmd/internal/obj/x86/obj6.go
+++ b/src/cmd/internal/obj/x86/obj6.go
@@ -38,7 +38,7 @@ import (
"math"
)
-func canuse1insntls(ctxt *obj.Link) bool {
+func CanUse1InsnTLS(ctxt *obj.Link) bool {
if isAndroid {
// For android, we use a disgusting hack that assumes
// the thread-local storage slot for g is allocated
@@ -130,7 +130,7 @@ func progedit(ctxt *obj.Link, p *obj.Prog) {
// rewriting the instructions more comprehensively, and it only does because
// we only support a single TLS variable (g).
- if canuse1insntls(ctxt) {
+ if CanUse1InsnTLS(ctxt) {
// Reduce 2-instruction sequence to 1-instruction sequence.
// Sequences like
// MOVQ TLS, BX
@@ -231,7 +231,8 @@ func progedit(ctxt *obj.Link, p *obj.Prog) {
// Convert AMOVSS $(0), Xx to AXORPS Xx, Xx
case AMOVSS:
if p.From.Type == obj.TYPE_FCONST {
- if p.From.Val.(float64) == 0 {
+ // f == 0 can't be used here due to -0, so use Float64bits
+ if f := p.From.Val.(float64); math.Float64bits(f) == 0 {
if p.To.Type == obj.TYPE_REG && REG_X0 <= p.To.Reg && p.To.Reg <= REG_X15 {
p.As = AXORPS
p.From = p.To
@@ -271,7 +272,8 @@ func progedit(ctxt *obj.Link, p *obj.Prog) {
case AMOVSD:
// Convert AMOVSD $(0), Xx to AXORPS Xx, Xx
if p.From.Type == obj.TYPE_FCONST {
- if p.From.Val.(float64) == 0 {
+ // f == 0 can't be used here due to -0, so use Float64bits
+ if f := p.From.Val.(float64); math.Float64bits(f) == 0 {
if p.To.Type == obj.TYPE_REG && REG_X0 <= p.To.Reg && p.To.Reg <= REG_X15 {
p.As = AXORPS
p.From = p.To
@@ -375,7 +377,7 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog) {
}
if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local {
// $MOV $sym, Rx becomes $MOV sym@GOT, Rx
- // $MOV $sym+<off>, Rx becomes $MOV sym@GOT, Rx; $ADD <off>, Rx
+ // $MOV $sym+<off>, Rx becomes $MOV sym@GOT, Rx; $LEA <off>(Rx), Rx
// On 386 only, more complicated things like PUSHL $sym become $MOV sym@GOT, CX; PUSHL CX
cmplxdest := false
pAs := p.As
@@ -397,8 +399,9 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog) {
q := p
if p.From.Offset != 0 {
q = obj.Appendp(ctxt, p)
- q.As = add
- q.From.Type = obj.TYPE_CONST
+ q.As = lea
+ q.From.Type = obj.TYPE_MEM
+ q.From.Reg = p.To.Reg
q.From.Offset = p.From.Offset
q.To = p.To
p.From.Offset = 0
@@ -1212,16 +1215,16 @@ loop:
q = p.Pcond
if q != nil && q.As != obj.ATEXT {
/* mark instruction as done and continue layout at target of jump */
- p.Mark = 1
+ p.Mark |= DONE
p = q
- if p.Mark == 0 {
+ if p.Mark&DONE == 0 {
goto loop
}
}
}
- if p.Mark != 0 {
+ if p.Mark&DONE != 0 {
/*
* p goes here, but already used it elsewhere.
* copy up to 4 instructions or else branch to other copy.
@@ -1244,7 +1247,7 @@ loop:
if nofollow(a) || pushpop(a) {
break // NOTE(rsc): arm does goto copy
}
- if q.Pcond == nil || q.Pcond.Mark != 0 {
+ if q.Pcond == nil || q.Pcond.Mark&DONE != 0 {
continue
}
if a == obj.ACALL || a == ALOOP {
@@ -1258,10 +1261,10 @@ loop:
q = obj.Copyp(ctxt, p)
p = p.Link
- q.Mark = 1
+ q.Mark |= DONE
(*last).Link = q
*last = q
- if int(q.As) != a || q.Pcond == nil || q.Pcond.Mark != 0 {
+ if int(q.As) != a || q.Pcond == nil || q.Pcond.Mark&DONE != 0 {
continue
}
@@ -1271,7 +1274,7 @@ loop:
q.Link = p
xfol(ctxt, q.Link, last)
p = q.Link
- if p.Mark != 0 {
+ if p.Mark&DONE != 0 {
return
}
goto loop
@@ -1288,7 +1291,7 @@ loop:
}
/* emit p */
- p.Mark = 1
+ p.Mark |= DONE
(*last).Link = p
*last = p
@@ -1326,7 +1329,7 @@ loop:
}
} else {
q = p.Link
- if q.Mark != 0 {
+ if q.Mark&DONE != 0 {
if a != ALOOP {
p.As = relinv(int16(a))
p.Link = p.Pcond
@@ -1336,7 +1339,7 @@ loop:
}
xfol(ctxt, p.Link, last)
- if p.Pcond.Mark != 0 {
+ if p.Pcond.Mark&DONE != 0 {
return
}
p = p.Pcond
diff --git a/src/cmd/internal/obj/x86/obj6_test.go b/src/cmd/internal/obj/x86/obj6_test.go
index 5fa1d3bfcf..a5c80cea3b 100644
--- a/src/cmd/internal/obj/x86/obj6_test.go
+++ b/src/cmd/internal/obj/x86/obj6_test.go
@@ -20,9 +20,9 @@ const testdata = `
MOVQ AX, AX -> MOVQ AX, AX
LEAQ name(SB), AX -> MOVQ name@GOT(SB), AX
-LEAQ name+10(SB), AX -> MOVQ name@GOT(SB), AX; ADDQ $10, AX
+LEAQ name+10(SB), AX -> MOVQ name@GOT(SB), AX; LEAQ 10(AX), AX
MOVQ $name(SB), AX -> MOVQ name@GOT(SB), AX
-MOVQ $name+10(SB), AX -> MOVQ name@GOT(SB), AX; ADDQ $10, AX
+MOVQ $name+10(SB), AX -> MOVQ name@GOT(SB), AX; LEAQ 10(AX), AX
MOVQ name(SB), AX -> NOP; MOVQ name@GOT(SB), R15; MOVQ (R15), AX
MOVQ name+10(SB), AX -> NOP; MOVQ name@GOT(SB), R15; MOVQ 10(R15), AX