1
2
3
4
5 package obj
6
7 import (
8 "github.com/twitchyliquid64/golang-asm/objabi"
9 "fmt"
10 "strings"
11 )
12
13 type Plist struct {
14 Firstpc *Prog
15 Curfn interface{}
16 }
17
18
19
20 type ProgAlloc func() *Prog
21
22 func Flushplist(ctxt *Link, plist *Plist, newprog ProgAlloc, myimportpath string) {
23
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
44 curtext = nil
45 continue
46 }
47 text = append(text, s)
48 etext = p
49 curtext = s
50 continue
51
52 case AFUNCDATA:
53
54 if curtext == nil {
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
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
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 if myimportpath != "" {
113 ctxt.populateDWARF(plist.Curfn, s, myimportpath)
114 }
115 }
116 }
117
118 func (ctxt *Link) InitTextSym(s *LSym, flag int) {
119 if s == nil {
120
121 return
122 }
123 if s.Func != nil {
124 ctxt.Diag("InitTextSym double init for %s", s.Name)
125 }
126 s.Func = new(FuncInfo)
127 if s.OnList() {
128 ctxt.Diag("symbol %s listed multiple times", s.Name)
129 }
130 name := strings.Replace(s.Name, "\"\"", ctxt.Pkgpath, -1)
131 s.Func.FuncID = objabi.GetFuncID(name, flag&WRAPPER != 0)
132 s.Set(AttrOnList, true)
133 s.Set(AttrDuplicateOK, flag&DUPOK != 0)
134 s.Set(AttrNoSplit, flag&NOSPLIT != 0)
135 s.Set(AttrReflectMethod, flag&REFLECTMETHOD != 0)
136 s.Set(AttrWrapper, flag&WRAPPER != 0)
137 s.Set(AttrNeedCtxt, flag&NEEDCTXT != 0)
138 s.Set(AttrNoFrame, flag&NOFRAME != 0)
139 s.Set(AttrTopFrame, flag&TOPFRAME != 0)
140 s.Type = objabi.STEXT
141 ctxt.Text = append(ctxt.Text, s)
142
143
144 ctxt.dwarfSym(s)
145 }
146
147 func (ctxt *Link) Globl(s *LSym, size int64, flag int) {
148 if s.OnList() {
149 ctxt.Diag("symbol %s listed multiple times", s.Name)
150 }
151 s.Set(AttrOnList, true)
152 ctxt.Data = append(ctxt.Data, s)
153 s.Size = size
154 if s.Type == 0 {
155 s.Type = objabi.SBSS
156 }
157 if flag&DUPOK != 0 {
158 s.Set(AttrDuplicateOK, true)
159 }
160 if flag&RODATA != 0 {
161 s.Type = objabi.SRODATA
162 } else if flag&NOPTR != 0 {
163 if s.Type == objabi.SDATA {
164 s.Type = objabi.SNOPTRDATA
165 } else {
166 s.Type = objabi.SNOPTRBSS
167 }
168 } else if flag&TLSBSS != 0 {
169 s.Type = objabi.STLSBSS
170 }
171 if strings.HasPrefix(s.Name, "\"\"."+StaticNamePref) {
172 s.Set(AttrStatic, true)
173 }
174 }
175
176
177
178
179 func (ctxt *Link) EmitEntryLiveness(s *LSym, p *Prog, newprog ProgAlloc) *Prog {
180 pcdata := ctxt.EmitEntryStackMap(s, p, newprog)
181 pcdata = ctxt.EmitEntryRegMap(s, pcdata, newprog)
182 return pcdata
183 }
184
185
186 func (ctxt *Link) EmitEntryStackMap(s *LSym, p *Prog, newprog ProgAlloc) *Prog {
187 pcdata := Appendp(p, newprog)
188 pcdata.Pos = s.Func.Text.Pos
189 pcdata.As = APCDATA
190 pcdata.From.Type = TYPE_CONST
191 pcdata.From.Offset = objabi.PCDATA_StackMapIndex
192 pcdata.To.Type = TYPE_CONST
193 pcdata.To.Offset = -1
194
195 return pcdata
196 }
197
198
199 func (ctxt *Link) EmitEntryRegMap(s *LSym, p *Prog, newprog ProgAlloc) *Prog {
200 pcdata := Appendp(p, newprog)
201 pcdata.Pos = s.Func.Text.Pos
202 pcdata.As = APCDATA
203 pcdata.From.Type = TYPE_CONST
204 pcdata.From.Offset = objabi.PCDATA_RegMapIndex
205 pcdata.To.Type = TYPE_CONST
206 pcdata.To.Offset = -1
207
208 return pcdata
209 }
210
211
212
213
214
215 func (ctxt *Link) StartUnsafePoint(p *Prog, newprog ProgAlloc) *Prog {
216 pcdata := Appendp(p, newprog)
217 pcdata.As = APCDATA
218 pcdata.From.Type = TYPE_CONST
219 pcdata.From.Offset = objabi.PCDATA_RegMapIndex
220 pcdata.To.Type = TYPE_CONST
221 pcdata.To.Offset = objabi.PCDATA_RegMapUnsafe
222
223 return pcdata
224 }
225
226
227
228
229
230 func (ctxt *Link) EndUnsafePoint(p *Prog, newprog ProgAlloc, oldval int64) *Prog {
231 pcdata := Appendp(p, newprog)
232 pcdata.As = APCDATA
233 pcdata.From.Type = TYPE_CONST
234 pcdata.From.Offset = objabi.PCDATA_RegMapIndex
235 pcdata.To.Type = TYPE_CONST
236 pcdata.To.Offset = oldval
237
238 return pcdata
239 }
240
241
242
243
244
245
246
247
248
249
250
251 func MarkUnsafePoints(ctxt *Link, p0 *Prog, newprog ProgAlloc, isUnsafePoint, isRestartable func(*Prog) bool) {
252 if isRestartable == nil {
253
254 isRestartable = func(*Prog) bool { return false }
255 }
256 prev := p0
257 prevPcdata := int64(-1)
258 prevRestart := int64(0)
259 for p := prev.Link; p != nil; p, prev = p.Link, p {
260 if p.As == APCDATA && p.From.Offset == objabi.PCDATA_RegMapIndex {
261 prevPcdata = p.To.Offset
262 continue
263 }
264 if prevPcdata == objabi.PCDATA_RegMapUnsafe {
265 continue
266 }
267 if isUnsafePoint(p) {
268 q := ctxt.StartUnsafePoint(prev, newprog)
269 q.Pc = p.Pc
270 q.Link = p
271
272 for p.Link != nil && isUnsafePoint(p.Link) {
273 p = p.Link
274 }
275 if p.Link == nil {
276 break
277 }
278 p = ctxt.EndUnsafePoint(p, newprog, prevPcdata)
279 p.Pc = p.Link.Pc
280 continue
281 }
282 if isRestartable(p) {
283 val := int64(objabi.PCDATA_Restart1)
284 if val == prevRestart {
285 val = objabi.PCDATA_Restart2
286 }
287 prevRestart = val
288 q := Appendp(prev, newprog)
289 q.As = APCDATA
290 q.From.Type = TYPE_CONST
291 q.From.Offset = objabi.PCDATA_RegMapIndex
292 q.To.Type = TYPE_CONST
293 q.To.Offset = val
294 q.Pc = p.Pc
295 q.Link = p
296
297 if p.Link == nil {
298 break
299 }
300 if isRestartable(p.Link) {
301
302
303 continue
304 }
305 p = Appendp(p, newprog)
306 p.As = APCDATA
307 p.From.Type = TYPE_CONST
308 p.From.Offset = objabi.PCDATA_RegMapIndex
309 p.To.Type = TYPE_CONST
310 p.To.Offset = prevPcdata
311 p.Pc = p.Link.Pc
312 }
313 }
314 }
315
View as plain text