a.Type = obj.TYPE_INDIR
}
// Weirdness with statics: Might now have "<>".
- isStatic := 0 // TODO: Really a boolean, but ctxt.Lookup wants a "version" integer.
+ isStatic := false
if p.peek() == '<' {
- isStatic = 1
+ isStatic = true
p.next()
p.get('>')
}
if p.peek() == '+' || p.peek() == '-' {
a.Offset = int64(p.expr())
}
- a.Sym = p.ctxt.Lookup(name, isStatic)
+ if isStatic {
+ a.Sym = p.ctxt.LookupStatic(name)
+ } else {
+ a.Sym = p.ctxt.Lookup(name)
+ }
if p.peek() == scanner.EOF {
if prefix == 0 && p.isJump {
// Symbols without prefix or suffix are jump labels.
p.get('(')
reg := p.get(scanner.Ident).String()
p.get(')')
- p.setPseudoRegister(a, reg, isStatic != 0, prefix)
+ p.setPseudoRegister(a, reg, isStatic, prefix)
}
// setPseudoRegister sets the NAME field of addr for a pseudo-register reference such as (SB).
return nil
}
if s.Lsym == nil {
- s.Lsym = Ctxt.Lookup(linksymname(s), 0)
+ s.Lsym = Ctxt.Lookup(linksymname(s))
}
return s.Lsym
}
const prefix = "go.string."
symdataname := prefix + symname
- symdata := Ctxt.Lookup(symdataname, 0)
+ symdata := Ctxt.Lookup(symdataname)
if !symdata.SeenGlobl() {
// string data
gotype := Linksym(ngotype(n))
fnsym.Func.Autom = append(fnsym.Func.Autom, &obj.Auto{
- Asym: Ctxt.Lookup(n.Sym.Name, 0),
+ Asym: Ctxt.Lookup(n.Sym.Name),
Aoffset: int32(n.Xoffset),
Name: name,
Gotype: gotype,
Name: n.Sym.Name,
Abbrev: abbrev,
Offset: int32(offs),
- Type: Ctxt.Lookup(typename, 0),
+ Type: Ctxt.Lookup(typename),
})
}
str = p.Path
}
- s := Ctxt.Lookup("type..importpath."+p.Prefix+".", 0)
+ s := Ctxt.Lookup("type..importpath." + p.Prefix + ".")
ot := dnameData(s, 0, str, "", nil, false)
ggloblLSym(s, int32(ot), obj.DUPOK|obj.RODATA)
p.Pathsym = s
// type..importpath.""., which the linker will rewrite using the correct import path.
// Every package that imports this one directly defines the symbol.
// See also https://groups.google.com/forum/#!topic/golang-dev/myb9s53HxGQ.
- ns := Ctxt.Lookup(`type..importpath."".`, 0)
+ ns := Ctxt.Lookup(`type..importpath."".`)
return dsymptrLSym(s, ot, ns, 0)
}
// type..importpath.""., which the linker will rewrite using the correct import path.
// Every package that imports this one directly defines the symbol.
// See also https://groups.google.com/forum/#!topic/golang-dev/myb9s53HxGQ.
- ns := Ctxt.Lookup(`type..importpath."".`, 0)
+ ns := Ctxt.Lookup(`type..importpath."".`)
return dsymptrOffLSym(s, ot, ns, 0)
}
sname = fmt.Sprintf(`%s"".%d`, sname, dnameCount)
dnameCount++
}
- s := Ctxt.Lookup(sname, 0)
+ s := Ctxt.Lookup(sname)
if len(s.P) > 0 {
return s
}
// process ptabs
if localpkg.Name == "main" && len(ptabs) > 0 {
ot := 0
- s := Ctxt.Lookup("go.plugin.tabs", 0)
+ s := Ctxt.Lookup("go.plugin.tabs")
for _, p := range ptabs {
// Dump ptab symbol into go.pluginsym package.
//
ggloblLSym(s, int32(ot), int16(obj.RODATA))
ot = 0
- s = Ctxt.Lookup("go.plugin.exports", 0)
+ s = Ctxt.Lookup("go.plugin.exports")
for _, p := range ptabs {
ot = dsymptrLSym(s, ot, Linksym(p.s), 0)
}
func (DummyFrontend) AllocFrame(f *Func) {
}
func (d DummyFrontend) Syslook(s string) *obj.LSym {
- return d.ctxt.Lookup(s, 0)
+ return d.ctxt.Lookup(s)
}
func (DummyFrontend) UseWriteBarrier() bool {
return true // only writebarrier_test cares
return
}
- deferreturn = ctxt.Lookup("runtime.deferreturn", 0)
+ deferreturn = ctxt.Lookup("runtime.deferreturn")
- symdiv = ctxt.Lookup("_div", 0)
- symdivu = ctxt.Lookup("_divu", 0)
- symmod = ctxt.Lookup("_mod", 0)
- symmodu = ctxt.Lookup("_modu", 0)
+ symdiv = ctxt.Lookup("_div")
+ symdivu = ctxt.Lookup("_divu")
+ symmod = ctxt.Lookup("_mod")
+ symmodu = ctxt.Lookup("_modu")
var n int
if objabi.GOARM < 7 {
// Replace it with BL runtime.read_tls_fallback(SB) for ARM CPUs that lack the tls extension.
if progedit_tlsfallback == nil {
- progedit_tlsfallback = ctxt.Lookup("runtime.read_tls_fallback", 0)
+ progedit_tlsfallback = ctxt.Lookup("runtime.read_tls_fallback")
}
// MOVW LR, R11
// CALL (R9)
var sym *obj.LSym
if p.As == obj.ADUFFZERO {
- sym = c.ctxt.Lookup("runtime.duffzero", 0)
+ sym = c.ctxt.Lookup("runtime.duffzero")
} else {
- sym = c.ctxt.Lookup("runtime.duffcopy", 0)
+ sym = c.ctxt.Lookup("runtime.duffcopy")
}
offset := p.To.Offset
p.As = AMOVW
return
}
- symsfloat := c.ctxt.Lookup("_sfloat", 0)
+ symsfloat := c.ctxt.Lookup("_sfloat")
wasfloat := 0
for p := c.cursym.Func.Text; p != nil; p = p.Link {
case !c.cursym.Func.Text.From.Sym.NeedCtxt():
morestack = "runtime.morestack_noctxt"
}
- call.To.Sym = c.ctxt.Lookup(morestack, 0)
+ call.To.Sym = c.ctxt.Lookup(morestack)
// B start
b := obj.Appendp(call, c.newprog)
case !c.cursym.Func.Text.From.Sym.NeedCtxt():
morestack = "runtime.morestack_noctxt"
}
- call.To.Sym = c.ctxt.Lookup(morestack, 0)
+ call.To.Sym = c.ctxt.Lookup(morestack)
// B start
jmp := obj.Appendp(call, c.newprog)
// CALL REGTMP
var sym *obj.LSym
if p.As == obj.ADUFFZERO {
- sym = c.ctxt.Lookup("runtime.duffzero", 0)
+ sym = c.ctxt.Lookup("runtime.duffzero")
} else {
- sym = c.ctxt.Lookup("runtime.duffcopy", 0)
+ sym = c.ctxt.Lookup("runtime.duffcopy")
}
offset := p.To.Offset
p.As = AMOVD
func TestLinkgetlineFromPos(t *testing.T) {
ctxt := new(Link)
ctxt.hash = make(map[string]*LSym)
- ctxt.vhash = make(map[string]*LSym)
+ ctxt.statichash = make(map[string]*LSym)
afile := src.NewFileBase("a.go", "a.go")
bfile := src.NewFileBase("b.go", "/foo/bar/b.go")
// An LSym is the sort of symbol that is written to an object file.
type LSym struct {
- Name string
- Type objabi.SymKind
- Version int16
+ Name string
+ Type objabi.SymKind
Attribute
RefIdx int // Index of this symbol in the symbol reference list.
AttrNoFrame
AttrSeenGlobl
AttrOnList
+ AttrStatic
// MakeTypelink means that the type should have an entry in the typelink table.
AttrMakeTypelink
func (a Attribute) Wrapper() bool { return a&AttrWrapper != 0 }
func (a Attribute) NeedCtxt() bool { return a&AttrNeedCtxt != 0 }
func (a Attribute) NoFrame() bool { return a&AttrNoFrame != 0 }
+func (a Attribute) Static() bool { return a&AttrStatic != 0 }
func (a *Attribute) Set(flag Attribute, value bool) {
if value {
{bit: AttrWrapper, s: "WRAPPER"},
{bit: AttrNeedCtxt, s: "NEEDCTXT"},
{bit: AttrNoFrame, s: "NOFRAME"},
+ {bit: AttrStatic, s: "STATIC"},
}
// TextAttrString formats a for printing in as part of a TEXT prog.
Flag_optimize bool
Bso *bufio.Writer
Pathname string
- hash map[string]*LSym // name -> sym mapping for version == 0
- vhash map[string]*LSym // name -> sym mapping for version == 1
+ hash map[string]*LSym // name -> sym mapping
+ statichash map[string]*LSym // name -> sym mapping for static syms
PosTable src.PosTable
InlTree InlTree // global inlining tree used by gc/inl.go
Imports []string
p.As = AJAL
p.To.Type = obj.TYPE_BRANCH
if c.cursym.CFunc() {
- p.To.Sym = c.ctxt.Lookup("runtime.morestackc", 0)
+ p.To.Sym = c.ctxt.Lookup("runtime.morestackc")
} else if !c.cursym.Func.Text.From.Sym.NeedCtxt() {
- p.To.Sym = c.ctxt.Lookup("runtime.morestack_noctxt", 0)
+ p.To.Sym = c.ctxt.Lookup("runtime.morestack_noctxt")
} else {
- p.To.Sym = c.ctxt.Lookup("runtime.morestack", 0)
+ p.To.Sym = c.ctxt.Lookup("runtime.morestack")
}
p.Mark |= BRANCH
return
}
var m map[string]int
- switch s.Version {
- case 0:
+ if !s.Static() {
m = w.refIdx
- case 1:
+ } else {
m = w.vrefIdx
- default:
- log.Fatalf("%s: invalid version number %d", s.Name, s.Version)
}
- idx := m[s.Name]
- if idx != 0 {
+ if idx := m[s.Name]; idx != 0 {
s.RefIdx = idx
return
}
} else {
w.writeString(s.Name)
}
- w.writeInt(int64(s.Version))
+ // Write "version".
+ if s.Static() {
+ w.writeInt(1)
+ } else {
+ w.writeInt(0)
+ }
w.nRefs++
s.RefIdx = w.nRefs
m[s.Name] = w.nRefs
w.writeRef(d, false)
}
for _, f := range pc.File {
- fsym := w.ctxt.Lookup(f, 0)
+ fsym := w.ctxt.Lookup(f)
w.writeRef(fsym, true)
}
for _, call := range pc.InlTree.nodes {
w.writeRef(call.Func, false)
f, _ := linkgetlineFromPos(w.ctxt, call.Pos)
- fsym := w.ctxt.Lookup(f, 0)
+ fsym := w.ctxt.Lookup(f)
w.writeRef(fsym, true)
}
}
func (w *objWriter) writeSymDebug(s *LSym) {
ctxt := w.ctxt
fmt.Fprintf(ctxt.Bso, "%s ", s.Name)
- if s.Version != 0 {
- fmt.Fprintf(ctxt.Bso, "v=%d ", s.Version)
- }
if s.Type != 0 {
fmt.Fprintf(ctxt.Bso, "%v ", s.Type)
}
+ if s.Static() {
+ fmt.Fprint(ctxt.Bso, "static ")
+ }
if s.DuplicateOK() {
fmt.Fprintf(ctxt.Bso, "dupok ")
}
}
w.writeInt(int64(len(pc.File)))
for _, f := range pc.File {
- fsym := ctxt.Lookup(f, 0)
+ fsym := ctxt.Lookup(f)
w.writeRefIndex(fsym)
}
w.writeInt(int64(len(pc.InlTree.nodes)))
for _, call := range pc.InlTree.nodes {
w.writeInt(int64(call.Parent))
f, l := linkgetlineFromPos(w.ctxt, call.Pos)
- fsym := ctxt.Lookup(f, 0)
+ fsym := ctxt.Lookup(f)
w.writeRefIndex(fsym)
w.writeInt(int64(l))
w.writeRefIndex(call.Func)
ctxt.Diag("dwarfSym of non-TEXT %v", s)
}
if s.Func.dwarfSym == nil {
- s.Func.dwarfSym = ctxt.Lookup(dwarf.InfoPrefix+s.Name, int(s.Version))
+ s.Func.dwarfSym = ctxt.LookupDerived(s, dwarf.InfoPrefix+s.Name)
}
return s.Func.dwarfSym
}
if ctxt.DebugInfo != nil {
vars = ctxt.DebugInfo(s, curfn)
}
- dwarf.PutFunc(dwCtxt{ctxt}, dsym, s.Name, s.Version == 0, s, s.Size, vars)
+ dwarf.PutFunc(dwCtxt{ctxt}, dsym, s.Name, !s.Static(), s, s.Size, vars)
}
if p.From.Type != TYPE_CONST || p.From.Offset != objabi.FUNCDATA_ArgsPointerMaps {
ctxt.Diag("FUNCDATA use of go_args_stackmap(SB) without FUNCDATA_ArgsPointerMaps")
}
- p.To.Sym = ctxt.Lookup(fmt.Sprintf("%s.args_stackmap", curtext.Name), int(curtext.Version))
+ p.To.Sym = ctxt.LookupDerived(curtext, curtext.Name+".args_stackmap")
}
}
p.From.Offset = objabi.FUNCDATA_ArgsPointerMaps
p.To.Type = TYPE_MEM
p.To.Name = NAME_EXTERN
- p.To.Sym = ctxt.Lookup(fmt.Sprintf("%s.args_stackmap", s.Name), int(s.Version))
+ p.To.Sym = ctxt.LookupDerived(s, s.Name+".args_stackmap")
}
}
// that knows the name of the tls variable. Possibly
// we could add some assembly syntax so that the name
// of the variable does not have to be assumed.
- rel.Sym = c.ctxt.Lookup("runtime.tls_g", 0)
+ rel.Sym = c.ctxt.Lookup("runtime.tls_g")
rel.Type = objabi.R_POWER_TLS
}
o1 = AOP_RRR(c.opstorex(p.As), uint32(p.From.Reg), uint32(p.To.Index), uint32(r))
rel := obj.Addrel(c.cursym)
rel.Off = int32(c.pc)
rel.Siz = 4
- rel.Sym = c.ctxt.Lookup("runtime.tls_g", 0)
+ rel.Sym = c.ctxt.Lookup("runtime.tls_g")
rel.Type = objabi.R_POWER_TLS
}
o1 = AOP_RRR(c.oploadx(p.As), uint32(p.To.Reg), uint32(p.From.Index), uint32(r))
// BL (CTR)
var sym *obj.LSym
if p.As == obj.ADUFFZERO {
- sym = c.ctxt.Lookup("runtime.duffzero", 0)
+ sym = c.ctxt.Lookup("runtime.duffzero")
} else {
- sym = c.ctxt.Lookup("runtime.duffcopy", 0)
+ sym = c.ctxt.Lookup("runtime.duffcopy")
}
offset := p.To.Offset
p.As = AMOVD
rel := obj.Addrel(c.cursym)
rel.Off = 0
rel.Siz = 8
- rel.Sym = c.ctxt.Lookup(".TOC.", 0)
+ rel.Sym = c.ctxt.Lookup(".TOC.")
rel.Type = objabi.R_ADDRPOWER_PCREL
}
var morestacksym *obj.LSym
if c.cursym.CFunc() {
- morestacksym = c.ctxt.Lookup("runtime.morestackc", 0)
+ morestacksym = c.ctxt.Lookup("runtime.morestackc")
} else if !c.cursym.Func.Text.From.Sym.NeedCtxt() {
- morestacksym = c.ctxt.Lookup("runtime.morestack_noctxt", 0)
+ morestacksym = c.ctxt.Lookup("runtime.morestack_noctxt")
} else {
- morestacksym = c.ctxt.Lookup("runtime.morestack", 0)
+ morestacksym = c.ctxt.Lookup("runtime.morestack")
}
if c.ctxt.Flag_shared {
p.As = ABL
p.To.Type = obj.TYPE_BRANCH
if c.cursym.CFunc() {
- p.To.Sym = c.ctxt.Lookup("runtime.morestackc", 0)
+ p.To.Sym = c.ctxt.Lookup("runtime.morestackc")
} else if !c.cursym.Func.Text.From.Sym.NeedCtxt() {
- p.To.Sym = c.ctxt.Lookup("runtime.morestack_noctxt", 0)
+ p.To.Sym = c.ctxt.Lookup("runtime.morestack_noctxt")
} else {
- p.To.Sym = c.ctxt.Lookup("runtime.morestack", 0)
+ p.To.Sym = c.ctxt.Lookup("runtime.morestack")
}
// BR start
_64bit uintptr // size on 64bit platforms
}{
{Addr{}, 32, 48},
- {LSym{}, 60, 104},
+ {LSym{}, 56, 104},
{Prog{}, 124, 184},
}
func Linknew(arch *LinkArch) *Link {
ctxt := new(Link)
ctxt.hash = make(map[string]*LSym)
- ctxt.vhash = make(map[string]*LSym)
+ ctxt.statichash = make(map[string]*LSym)
ctxt.Arch = arch
ctxt.Pathname = objabi.WorkingDir()
return ctxt
}
-// Lookup looks up the symbol with name name and version v.
-// If it does not exist, it creates it.
-func (ctxt *Link) Lookup(name string, v int) *LSym {
- return ctxt.LookupInit(name, v, nil)
+// LookupDerived looks up or creates the symbol with name name derived from symbol s.
+// The resulting symbol will be static iff s is.
+func (ctxt *Link) LookupDerived(s *LSym, name string) *LSym {
+ if s.Static() {
+ return ctxt.LookupStatic(name)
+ }
+ return ctxt.Lookup(name)
}
-// LookupInit looks up the symbol with name name and version v.
-// If it does not exist, it creates it and passes it to initfn for one-time initialization.
-func (ctxt *Link) LookupInit(name string, v int, init func(s *LSym)) *LSym {
- var m map[string]*LSym
- switch v {
- case 0:
- m = ctxt.hash
- case 1:
- m = ctxt.vhash
- default:
- ctxt.Diag("LookupInit: bad version %d", v)
- }
- if s := m[name]; s != nil {
- return s
+// LookupStatic looks up the static symbol with name name.
+// If it does not exist, it creates it.
+func (ctxt *Link) LookupStatic(name string) *LSym {
+ s := ctxt.statichash[name]
+ if s == nil {
+ s = &LSym{Name: name, Attribute: AttrStatic}
+ ctxt.statichash[name] = s
}
+ return s
+}
+
+// Lookup looks up the symbol with name name.
+// If it does not exist, it creates it.
+func (ctxt *Link) Lookup(name string) *LSym {
+ return ctxt.LookupInit(name, nil)
+}
- s := &LSym{Name: name, Version: int16(v)}
- m[name] = s
- if init != nil {
- init(s)
+// LookupInit looks up the symbol with name name.
+// If it does not exist, it creates it and
+// passes it to init for one-time initialization.
+func (ctxt *Link) LookupInit(name string, init func(s *LSym)) *LSym {
+ s := ctxt.hash[name]
+ if s == nil {
+ s = &LSym{Name: name}
+ ctxt.hash[name] = s
+ if init != nil {
+ init(s)
+ }
}
return s
}
func (ctxt *Link) Float32Sym(f float32) *LSym {
i := math.Float32bits(f)
name := fmt.Sprintf("$f32.%08x", i)
- return ctxt.LookupInit(name, 0, func(s *LSym) {
+ return ctxt.LookupInit(name, func(s *LSym) {
s.Size = 4
s.Set(AttrLocal, true)
})
func (ctxt *Link) Float64Sym(f float64) *LSym {
i := math.Float64bits(f)
name := fmt.Sprintf("$f64.%016x", i)
- return ctxt.LookupInit(name, 0, func(s *LSym) {
+ return ctxt.LookupInit(name, func(s *LSym) {
s.Size = 8
s.Set(AttrLocal, true)
})
func (ctxt *Link) Int64Sym(i int64) *LSym {
name := fmt.Sprintf("$i64.%016x", uint64(i))
- return ctxt.LookupInit(name, 0, func(s *LSym) {
+ return ctxt.LookupInit(name, func(s *LSym) {
s.Size = 8
s.Set(AttrLocal, true)
})
switch ctxt.Headtype {
case objabi.Hplan9:
- plan9privates = ctxt.Lookup("_privates", 0)
+ plan9privates = ctxt.Lookup("_privates")
case objabi.Hnacl:
- deferreturn = ctxt.Lookup("runtime.deferreturn", 0)
+ deferreturn = ctxt.Lookup("runtime.deferreturn")
}
for i := 1; optab[i].as != 0; i++ {
r.Off = int32(p.Pc + int64(asmbuf.Len()))
r.Type = objabi.R_CALL
r.Siz = 4
- r.Sym = ctxt.Lookup("__x86.get_pc_thunk."+strings.ToLower(rconv(int(dst))), 0)
+ r.Sym = ctxt.Lookup("__x86.get_pc_thunk." + strings.ToLower(rconv(int(dst))))
asmbuf.PutInt32(0)
asmbuf.Put2(0x8B, byte(2<<6|reg[dst]|(reg[dst]<<3)))
// CALL $reg
var sym *obj.LSym
if p.As == obj.ADUFFZERO {
- sym = ctxt.Lookup("runtime.duffzero", 0)
+ sym = ctxt.Lookup("runtime.duffzero")
} else {
- sym = ctxt.Lookup("runtime.duffcopy", 0)
+ sym = ctxt.Lookup("runtime.duffcopy")
}
offset := p.To.Offset
p.As = mov
p1.As = ALEAL
p1.From.Type = obj.TYPE_MEM
p1.From.Name = obj.NAME_STATIC
- p1.From.Sym = ctxt.Lookup("_GLOBAL_OFFSET_TABLE_", 0)
+ p1.From.Sym = ctxt.Lookup("_GLOBAL_OFFSET_TABLE_")
p1.To.Type = obj.TYPE_REG
p1.To.Reg = REG_BX
r.RegTo2 = 1
q.As = obj.ACALL
thunkname := "__x86.get_pc_thunk." + strings.ToLower(rconv(int(dst)))
- q.To.Sym = ctxt.LookupInit(thunkname, 0, func(s *obj.LSym) { s.Set(obj.AttrLocal, true) })
+ q.To.Sym = ctxt.LookupInit(thunkname, func(s *obj.LSym) { s.Set(obj.AttrLocal, true) })
q.To.Type = obj.TYPE_MEM
q.To.Name = obj.NAME_EXTERN
r.As = p.As
case !cursym.Func.Text.From.Sym.NeedCtxt():
morestack = "runtime.morestack_noctxt"
}
- call.To.Sym = ctxt.Lookup(morestack, 0)
+ call.To.Sym = ctxt.Lookup(morestack)
// When compiling 386 code for dynamic linking, the call needs to be adjusted
// to follow PIC rules. This in turn can insert more instructions, so we need
// to keep track of the start of the call (where the jump will be to) and the