summaryrefslogtreecommitdiff
path: root/src/cmd/internal/obj/pass.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/internal/obj/pass.go')
-rw-r--r--src/cmd/internal/obj/pass.go102
1 files changed, 95 insertions, 7 deletions
diff --git a/src/cmd/internal/obj/pass.go b/src/cmd/internal/obj/pass.go
index a8c1c77d83..812e00b557 100644
--- a/src/cmd/internal/obj/pass.go
+++ b/src/cmd/internal/obj/pass.go
@@ -33,11 +33,10 @@ package obj
// Code and data passes.
func Brchain(ctxt *Link, p *Prog) *Prog {
-
var i int
for i = 0; i < 20; i++ {
- if p == nil || int(p.As) != ctxt.Arch.AJMP || p.Pcond == nil {
+ if p == nil || p.As != AJMP || p.Pcond == nil {
return p
}
p = p.Pcond
@@ -52,7 +51,7 @@ func brloop(ctxt *Link, p *Prog) *Prog {
c = 0
for q = p; q != nil; q = q.Pcond {
- if int(q.As) != ctxt.Arch.AJMP || q.Pcond == nil {
+ if q.As != AJMP || q.Pcond == nil {
break
}
c++
@@ -64,6 +63,92 @@ func brloop(ctxt *Link, p *Prog) *Prog {
return q
}
+func checkaddr(ctxt *Link, p *Prog, a *Addr) {
+ // Check expected encoding, especially TYPE_CONST vs TYPE_ADDR.
+ switch a.Type {
+ case TYPE_NONE:
+ return
+
+ case TYPE_BRANCH:
+ if a.Reg != 0 || a.Index != 0 || a.Scale != 0 || a.Name != 0 {
+ break
+ }
+ return
+
+ case TYPE_TEXTSIZE:
+ if a.Reg != 0 || a.Index != 0 || a.Scale != 0 || a.Name != 0 {
+ break
+ }
+ return
+
+ //if(a->u.bits != 0)
+ // break;
+ case TYPE_MEM:
+ return
+
+ // TODO(rsc): After fixing SHRQ, check a->index != 0 too.
+ case TYPE_CONST:
+ if a.Name != 0 || a.Sym != nil || a.Reg != 0 {
+ ctxt.Diag("argument is TYPE_CONST, should be TYPE_ADDR, in %v", p)
+ return
+ }
+
+ if a.Reg != 0 || a.Scale != 0 || a.Name != 0 || a.Sym != nil || a.U.Bits != 0 {
+ break
+ }
+ return
+
+ case TYPE_FCONST,
+ TYPE_SCONST:
+ if a.Reg != 0 || a.Index != 0 || a.Scale != 0 || a.Name != 0 || a.Offset != 0 || a.Sym != nil {
+ break
+ }
+ return
+
+ // TODO(rsc): After fixing PINSRQ, check a->offset != 0 too.
+ // TODO(rsc): After fixing SHRQ, check a->index != 0 too.
+ case TYPE_REG:
+ if a.Scale != 0 || a.Name != 0 || a.Sym != nil {
+ break
+ }
+ return
+
+ case TYPE_ADDR:
+ if a.U.Bits != 0 {
+ break
+ }
+ if a.Reg == 0 && a.Index == 0 && a.Scale == 0 && a.Name == 0 && a.Sym == nil {
+ ctxt.Diag("argument is TYPE_ADDR, should be TYPE_CONST, in %v", p)
+ }
+ return
+
+ case TYPE_SHIFT:
+ if a.Index != 0 || a.Scale != 0 || a.Name != 0 || a.Sym != nil || a.U.Bits != 0 {
+ break
+ }
+ return
+
+ case TYPE_REGREG:
+ if a.Index != 0 || a.Scale != 0 || a.Name != 0 || a.Sym != nil || a.U.Bits != 0 {
+ break
+ }
+ return
+
+ case TYPE_REGREG2:
+ return
+
+ // Expect sym and name to be set, nothing else.
+ // Technically more is allowed, but this is only used for *name(SB).
+ case TYPE_INDIR:
+ if a.Reg != 0 || a.Index != 0 || a.Scale != 0 || a.Name == 0 || a.Offset != 0 || a.Sym == nil || a.U.Bits != 0 {
+ break
+ }
+ return
+ }
+
+ ctxt.Diag("invalid encoding for argument %v", p)
+}
+
func linkpatch(ctxt *Link, sym *LSym) {
var c int32
var name string
@@ -73,10 +158,14 @@ func linkpatch(ctxt *Link, sym *LSym) {
ctxt.Cursym = sym
for p = sym.Text; p != nil; p = p.Link {
+ checkaddr(ctxt, p, &p.From)
+ checkaddr(ctxt, p, &p.From3)
+ checkaddr(ctxt, p, &p.To)
+
if ctxt.Arch.Progedit != nil {
ctxt.Arch.Progedit(ctxt, p)
}
- if int(p.To.Type) != ctxt.Arch.D_BRANCH {
+ if p.To.Type != TYPE_BRANCH {
continue
}
if p.To.U.Branch != nil {
@@ -97,7 +186,6 @@ func linkpatch(ctxt *Link, sym *LSym) {
if q.Forwd != nil && int64(c) >= q.Forwd.Pc {
q = q.Forwd
} else {
-
q = q.Link
}
}
@@ -108,7 +196,7 @@ func linkpatch(ctxt *Link, sym *LSym) {
name = p.To.Sym.Name
}
ctxt.Diag("branch out of range (%#x)\n%v [%s]", uint32(c), p, name)
- p.To.Type = int16(ctxt.Arch.D_NONE)
+ p.To.Type = TYPE_NONE
}
p.To.U.Branch = q
@@ -120,7 +208,7 @@ func linkpatch(ctxt *Link, sym *LSym) {
if p.Pcond != nil {
p.Pcond = brloop(ctxt, p.Pcond)
if p.Pcond != nil {
- if int(p.To.Type) == ctxt.Arch.D_BRANCH {
+ if p.To.Type == TYPE_BRANCH {
p.To.Offset = p.Pcond.Pc
}
}