1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 package objw
32
33 import (
34 "cmd/compile/internal/base"
35 "cmd/compile/internal/ir"
36 "cmd/internal/obj"
37 "cmd/internal/objabi"
38 "cmd/internal/src"
39 )
40
41 var sharedProgArray = new([10000]obj.Prog)
42
43
44
45 func NewProgs(fn *ir.Func, worker int) *Progs {
46 pp := new(Progs)
47 if base.Ctxt.CanReuseProgs() {
48 sz := len(sharedProgArray) / base.Flag.LowerC
49 pp.Cache = sharedProgArray[sz*worker : sz*(worker+1)]
50 }
51 pp.CurFunc = fn
52
53
54 pp.Next = pp.NewProg()
55 pp.Clear(pp.Next)
56
57 pp.Pos = fn.Pos()
58 pp.SetText(fn)
59
60 pp.PrevLive = LivenessIndex{-1, false}
61 pp.NextLive = pp.PrevLive
62 return pp
63 }
64
65
66 type Progs struct {
67 Text *obj.Prog
68 Next *obj.Prog
69 PC int64
70 Pos src.XPos
71 CurFunc *ir.Func
72 Cache []obj.Prog
73 CacheIndex int
74
75 NextLive LivenessIndex
76 PrevLive LivenessIndex
77 }
78
79
80 type LivenessIndex struct {
81 StackMapIndex int
82
83
84
85
86
87
88
89 IsUnsafePoint bool
90 }
91
92
93
94
95
96
97
98 const StackMapDontCare = -1000
99
100
101
102
103 var LivenessDontCare = LivenessIndex{StackMapDontCare, true}
104
105 func (idx LivenessIndex) StackMapValid() bool {
106 return idx.StackMapIndex != StackMapDontCare
107 }
108
109 func (pp *Progs) NewProg() *obj.Prog {
110 var p *obj.Prog
111 if pp.CacheIndex < len(pp.Cache) {
112 p = &pp.Cache[pp.CacheIndex]
113 pp.CacheIndex++
114 } else {
115 p = new(obj.Prog)
116 }
117 p.Ctxt = base.Ctxt
118 return p
119 }
120
121
122 func (pp *Progs) Flush() {
123 plist := &obj.Plist{Firstpc: pp.Text, Curfn: pp.CurFunc}
124 obj.Flushplist(base.Ctxt, plist, pp.NewProg, base.Ctxt.Pkgpath)
125 }
126
127
128 func (pp *Progs) Free() {
129 if base.Ctxt.CanReuseProgs() {
130
131 s := pp.Cache[:pp.CacheIndex]
132 for i := range s {
133 s[i] = obj.Prog{}
134 }
135 }
136
137 *pp = Progs{}
138 }
139
140
141 func (pp *Progs) Prog(as obj.As) *obj.Prog {
142 if pp.NextLive.StackMapValid() && pp.NextLive.StackMapIndex != pp.PrevLive.StackMapIndex {
143
144 idx := pp.NextLive.StackMapIndex
145 pp.PrevLive.StackMapIndex = idx
146 p := pp.Prog(obj.APCDATA)
147 p.From.SetConst(objabi.PCDATA_StackMapIndex)
148 p.To.SetConst(int64(idx))
149 }
150 if pp.NextLive.IsUnsafePoint != pp.PrevLive.IsUnsafePoint {
151
152 pp.PrevLive.IsUnsafePoint = pp.NextLive.IsUnsafePoint
153 p := pp.Prog(obj.APCDATA)
154 p.From.SetConst(objabi.PCDATA_UnsafePoint)
155 if pp.NextLive.IsUnsafePoint {
156 p.To.SetConst(objabi.PCDATA_UnsafePointUnsafe)
157 } else {
158 p.To.SetConst(objabi.PCDATA_UnsafePointSafe)
159 }
160 }
161
162 p := pp.Next
163 pp.Next = pp.NewProg()
164 pp.Clear(pp.Next)
165 p.Link = pp.Next
166
167 if !pp.Pos.IsKnown() && base.Flag.K != 0 {
168 base.Warn("prog: unknown position (line 0)")
169 }
170
171 p.As = as
172 p.Pos = pp.Pos
173 if pp.Pos.IsStmt() == src.PosIsStmt {
174
175 if LosesStmtMark(as) {
176 return p
177 }
178 pp.Pos = pp.Pos.WithNotStmt()
179 }
180 return p
181 }
182
183 func (pp *Progs) Clear(p *obj.Prog) {
184 obj.Nopout(p)
185 p.As = obj.AEND
186 p.Pc = pp.PC
187 pp.PC++
188 }
189
190 func (pp *Progs) Append(p *obj.Prog, as obj.As, ftype obj.AddrType, freg int16, foffset int64, ttype obj.AddrType, treg int16, toffset int64) *obj.Prog {
191 q := pp.NewProg()
192 pp.Clear(q)
193 q.As = as
194 q.Pos = p.Pos
195 q.From.Type = ftype
196 q.From.Reg = freg
197 q.From.Offset = foffset
198 q.To.Type = ttype
199 q.To.Reg = treg
200 q.To.Offset = toffset
201 q.Link = p.Link
202 p.Link = q
203 return q
204 }
205
206 func (pp *Progs) SetText(fn *ir.Func) {
207 if pp.Text != nil {
208 base.Fatalf("Progs.SetText called twice")
209 }
210 ptxt := pp.Prog(obj.ATEXT)
211 pp.Text = ptxt
212
213 fn.LSym.Func().Text = ptxt
214 ptxt.From.Type = obj.TYPE_MEM
215 ptxt.From.Name = obj.NAME_EXTERN
216 ptxt.From.Sym = fn.LSym
217 }
218
219
220
221
222
223 func LosesStmtMark(as obj.As) bool {
224
225 return as == obj.APCDATA || as == obj.AFUNCDATA
226 }
227
View as plain text