github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/internal/obj/plist.go (about) 1 // Copyright 2013 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package obj 6 7 import ( 8 "github.com/gagliardetto/golang-go/cmd/internal/objabi" 9 "fmt" 10 "strings" 11 ) 12 13 type Plist struct { 14 Firstpc *Prog 15 Curfn interface{} // holds a *gc.Node, if non-nil 16 } 17 18 // ProgAlloc is a function that allocates Progs. 19 // It is used to provide access to cached/bulk-allocated Progs to the assemblers. 20 type ProgAlloc func() *Prog 21 22 func Flushplist(ctxt *Link, plist *Plist, newprog ProgAlloc, myimportpath string) { 23 // Build list of symbols, and assign instructions to lists. 24 var curtext *LSym 25 var etext *Prog 26 var text []*LSym 27 28 var plink *Prog 29 for p := plist.Firstpc; p != nil; p = plink { 30 if ctxt.Debugasm > 0 && ctxt.Debugvlog { 31 fmt.Printf("obj: %v\n", p) 32 } 33 plink = p.Link 34 p.Link = nil 35 36 switch p.As { 37 case AEND: 38 continue 39 40 case ATEXT: 41 s := p.From.Sym 42 if s == nil { 43 // func _() { } 44 curtext = nil 45 continue 46 } 47 text = append(text, s) 48 etext = p 49 curtext = s 50 continue 51 52 case AFUNCDATA: 53 // Rewrite reference to go_args_stackmap(SB) to the Go-provided declaration information. 54 if curtext == nil { // func _() {} 55 continue 56 } 57 if p.To.Sym.Name == "go_args_stackmap" { 58 if p.From.Type != TYPE_CONST || p.From.Offset != objabi.FUNCDATA_ArgsPointerMaps { 59 ctxt.Diag("FUNCDATA use of go_args_stackmap(SB) without FUNCDATA_ArgsPointerMaps") 60 } 61 p.To.Sym = ctxt.LookupDerived(curtext, curtext.Name+".args_stackmap") 62 } 63 64 } 65 66 if curtext == nil { 67 etext = nil 68 continue 69 } 70 etext.Link = p 71 etext = p 72 } 73 74 if newprog == nil { 75 newprog = ctxt.NewProg 76 } 77 78 // Add reference to Go arguments for C or assembly functions without them. 79 for _, s := range text { 80 if !strings.HasPrefix(s.Name, "\"\".") { 81 continue 82 } 83 found := false 84 for p := s.Func.Text; p != nil; p = p.Link { 85 if p.As == AFUNCDATA && p.From.Type == TYPE_CONST && p.From.Offset == objabi.FUNCDATA_ArgsPointerMaps { 86 found = true 87 break 88 } 89 } 90 91 if !found { 92 p := Appendp(s.Func.Text, newprog) 93 p.As = AFUNCDATA 94 p.From.Type = TYPE_CONST 95 p.From.Offset = objabi.FUNCDATA_ArgsPointerMaps 96 p.To.Type = TYPE_MEM 97 p.To.Name = NAME_EXTERN 98 p.To.Sym = ctxt.LookupDerived(s, s.Name+".args_stackmap") 99 } 100 } 101 102 // Turn functions into machine code images. 103 for _, s := range text { 104 mkfwd(s) 105 linkpatch(ctxt, s, newprog) 106 ctxt.Arch.Preprocess(ctxt, s, newprog) 107 ctxt.Arch.Assemble(ctxt, s, newprog) 108 if ctxt.Errors > 0 { 109 continue 110 } 111 linkpcln(ctxt, s) 112 ctxt.populateDWARF(plist.Curfn, s, myimportpath) 113 } 114 } 115 116 func (ctxt *Link) InitTextSym(s *LSym, flag int) { 117 if s == nil { 118 // func _() { } 119 return 120 } 121 if s.Func != nil { 122 ctxt.Diag("InitTextSym double init for %s", s.Name) 123 } 124 s.Func = new(FuncInfo) 125 if s.OnList() { 126 ctxt.Diag("symbol %s listed multiple times", s.Name) 127 } 128 s.Set(AttrOnList, true) 129 s.Set(AttrDuplicateOK, flag&DUPOK != 0) 130 s.Set(AttrNoSplit, flag&NOSPLIT != 0) 131 s.Set(AttrReflectMethod, flag&REFLECTMETHOD != 0) 132 s.Set(AttrWrapper, flag&WRAPPER != 0) 133 s.Set(AttrNeedCtxt, flag&NEEDCTXT != 0) 134 s.Set(AttrNoFrame, flag&NOFRAME != 0) 135 s.Set(AttrTopFrame, flag&TOPFRAME != 0) 136 s.Type = objabi.STEXT 137 ctxt.Text = append(ctxt.Text, s) 138 139 // Set up DWARF entries for s. 140 info, loc, ranges, _, lines := ctxt.dwarfSym(s) 141 info.Type = objabi.SDWARFINFO 142 info.Set(AttrDuplicateOK, s.DuplicateOK()) 143 if loc != nil { 144 loc.Type = objabi.SDWARFLOC 145 loc.Set(AttrDuplicateOK, s.DuplicateOK()) 146 ctxt.Data = append(ctxt.Data, loc) 147 } 148 ranges.Type = objabi.SDWARFRANGE 149 ranges.Set(AttrDuplicateOK, s.DuplicateOK()) 150 ctxt.Data = append(ctxt.Data, info, ranges) 151 lines.Type = objabi.SDWARFLINES 152 lines.Set(AttrDuplicateOK, s.DuplicateOK()) 153 ctxt.Data = append(ctxt.Data, lines) 154 } 155 156 func (ctxt *Link) Globl(s *LSym, size int64, flag int) { 157 if s.SeenGlobl() { 158 fmt.Printf("duplicate %v\n", s) 159 } 160 s.Set(AttrSeenGlobl, true) 161 if s.OnList() { 162 ctxt.Diag("symbol %s listed multiple times", s.Name) 163 } 164 s.Set(AttrOnList, true) 165 ctxt.Data = append(ctxt.Data, s) 166 s.Size = size 167 if s.Type == 0 { 168 s.Type = objabi.SBSS 169 } 170 if flag&DUPOK != 0 { 171 s.Set(AttrDuplicateOK, true) 172 } 173 if flag&RODATA != 0 { 174 s.Type = objabi.SRODATA 175 } else if flag&NOPTR != 0 { 176 if s.Type == objabi.SDATA { 177 s.Type = objabi.SNOPTRDATA 178 } else { 179 s.Type = objabi.SNOPTRBSS 180 } 181 } else if flag&TLSBSS != 0 { 182 s.Type = objabi.STLSBSS 183 } 184 } 185 186 // EmitEntryLiveness generates PCDATA Progs after p to switch to the 187 // liveness map active at the entry of function s. It returns the last 188 // Prog generated. 189 func (ctxt *Link) EmitEntryLiveness(s *LSym, p *Prog, newprog ProgAlloc) *Prog { 190 pcdata := ctxt.EmitEntryStackMap(s, p, newprog) 191 pcdata = ctxt.EmitEntryRegMap(s, pcdata, newprog) 192 return pcdata 193 } 194 195 // Similar to EmitEntryLiveness, but just emit stack map. 196 func (ctxt *Link) EmitEntryStackMap(s *LSym, p *Prog, newprog ProgAlloc) *Prog { 197 pcdata := Appendp(p, newprog) 198 pcdata.Pos = s.Func.Text.Pos 199 pcdata.As = APCDATA 200 pcdata.From.Type = TYPE_CONST 201 pcdata.From.Offset = objabi.PCDATA_StackMapIndex 202 pcdata.To.Type = TYPE_CONST 203 pcdata.To.Offset = -1 // pcdata starts at -1 at function entry 204 205 return pcdata 206 } 207 208 // Similar to EmitEntryLiveness, but just emit register map. 209 func (ctxt *Link) EmitEntryRegMap(s *LSym, p *Prog, newprog ProgAlloc) *Prog { 210 pcdata := Appendp(p, newprog) 211 pcdata.Pos = s.Func.Text.Pos 212 pcdata.As = APCDATA 213 pcdata.From.Type = TYPE_CONST 214 pcdata.From.Offset = objabi.PCDATA_RegMapIndex 215 pcdata.To.Type = TYPE_CONST 216 pcdata.To.Offset = -1 217 218 return pcdata 219 } 220 221 // StartUnsafePoint generates PCDATA Progs after p to mark the 222 // beginning of an unsafe point. The unsafe point starts immediately 223 // after p. 224 // It returns the last Prog generated. 225 func (ctxt *Link) StartUnsafePoint(p *Prog, newprog ProgAlloc) *Prog { 226 pcdata := Appendp(p, newprog) 227 pcdata.As = APCDATA 228 pcdata.From.Type = TYPE_CONST 229 pcdata.From.Offset = objabi.PCDATA_RegMapIndex 230 pcdata.To.Type = TYPE_CONST 231 pcdata.To.Offset = -2 // pcdata -2 marks unsafe point 232 233 return pcdata 234 } 235 236 // EndUnsafePoint generates PCDATA Progs after p to mark the end of an 237 // unsafe point, restoring the stack map index to oldval. 238 // The unsafe point ends right after p. 239 // It returns the last Prog generated. 240 func (ctxt *Link) EndUnsafePoint(p *Prog, newprog ProgAlloc, oldval int64) *Prog { 241 pcdata := Appendp(p, newprog) 242 pcdata.As = APCDATA 243 pcdata.From.Type = TYPE_CONST 244 pcdata.From.Offset = objabi.PCDATA_RegMapIndex 245 pcdata.To.Type = TYPE_CONST 246 pcdata.To.Offset = oldval 247 248 // TODO: register map? 249 250 return pcdata 251 } 252 253 // MarkUnsafePoints inserts PCDATAs to mark nonpreemptible instruction 254 // sequences, based on isUnsafePoint predicate. p0 is the start of the 255 // instruction stream. 256 func MarkUnsafePoints(ctxt *Link, p0 *Prog, newprog ProgAlloc, isUnsafePoint func(*Prog) bool) { 257 prev := p0 258 oldval := int64(-1) // entry pcdata 259 for p := prev.Link; p != nil; p, prev = p.Link, p { 260 if p.As == APCDATA && p.From.Offset == objabi.PCDATA_RegMapIndex { 261 oldval = p.To.Offset 262 continue 263 } 264 if oldval == -2 { 265 continue // already unsafe 266 } 267 if isUnsafePoint(p) { 268 q := ctxt.StartUnsafePoint(prev, newprog) 269 q.Pc = p.Pc 270 q.Link = p 271 // Advance to the end of unsafe point. 272 for p.Link != nil && isUnsafePoint(p.Link) { 273 p = p.Link 274 } 275 if p.Link == nil { 276 break // Reached the end, don't bother marking the end 277 } 278 p = ctxt.EndUnsafePoint(p, newprog, oldval) 279 p.Pc = p.Link.Pc 280 } 281 } 282 }