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/src"
38 "internal/abi"
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 = -1
61 pp.NextLive = pp.PrevLive
62 pp.NextUnsafe = pp.PrevUnsafe
63 return pp
64 }
65
66
67 type Progs struct {
68 Text *obj.Prog
69 Next *obj.Prog
70 PC int64
71 Pos src.XPos
72 CurFunc *ir.Func
73 Cache []obj.Prog
74 CacheIndex int
75
76 NextLive StackMapIndex
77 PrevLive StackMapIndex
78
79 NextUnsafe bool
80 PrevUnsafe bool
81 }
82
83 type StackMapIndex int
84
85
86
87
88
89
90
91 const StackMapDontCare StackMapIndex = -1000
92
93 func (s StackMapIndex) StackMapValid() bool {
94 return s != StackMapDontCare
95 }
96
97 func (pp *Progs) NewProg() *obj.Prog {
98 var p *obj.Prog
99 if pp.CacheIndex < len(pp.Cache) {
100 p = &pp.Cache[pp.CacheIndex]
101 pp.CacheIndex++
102 } else {
103 p = new(obj.Prog)
104 }
105 p.Ctxt = base.Ctxt
106 return p
107 }
108
109
110 func (pp *Progs) Flush() {
111 plist := &obj.Plist{Firstpc: pp.Text, Curfn: pp.CurFunc}
112 obj.Flushplist(base.Ctxt, plist, pp.NewProg)
113 }
114
115
116 func (pp *Progs) Free() {
117 if base.Ctxt.CanReuseProgs() {
118
119 s := pp.Cache[:pp.CacheIndex]
120 for i := range s {
121 s[i] = obj.Prog{}
122 }
123 }
124
125 *pp = Progs{}
126 }
127
128
129 func (pp *Progs) Prog(as obj.As) *obj.Prog {
130 if pp.NextLive != StackMapDontCare && pp.NextLive != pp.PrevLive {
131
132 idx := pp.NextLive
133 pp.PrevLive = idx
134 p := pp.Prog(obj.APCDATA)
135 p.From.SetConst(abi.PCDATA_StackMapIndex)
136 p.To.SetConst(int64(idx))
137 }
138 if pp.NextUnsafe != pp.PrevUnsafe {
139
140 pp.PrevUnsafe = pp.NextUnsafe
141 p := pp.Prog(obj.APCDATA)
142 p.From.SetConst(abi.PCDATA_UnsafePoint)
143 if pp.NextUnsafe {
144 p.To.SetConst(abi.UnsafePointUnsafe)
145 } else {
146 p.To.SetConst(abi.UnsafePointSafe)
147 }
148 }
149
150 p := pp.Next
151 pp.Next = pp.NewProg()
152 pp.Clear(pp.Next)
153 p.Link = pp.Next
154
155 if !pp.Pos.IsKnown() && base.Flag.K != 0 {
156 base.Warn("prog: unknown position (line 0)")
157 }
158
159 p.As = as
160 p.Pos = pp.Pos
161 if pp.Pos.IsStmt() == src.PosIsStmt {
162
163 if LosesStmtMark(as) {
164 return p
165 }
166 pp.Pos = pp.Pos.WithNotStmt()
167 }
168 return p
169 }
170
171 func (pp *Progs) Clear(p *obj.Prog) {
172 obj.Nopout(p)
173 p.As = obj.AEND
174 p.Pc = pp.PC
175 pp.PC++
176 }
177
178 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 {
179 q := pp.NewProg()
180 pp.Clear(q)
181 q.As = as
182 q.Pos = p.Pos
183 q.From.Type = ftype
184 q.From.Reg = freg
185 q.From.Offset = foffset
186 q.To.Type = ttype
187 q.To.Reg = treg
188 q.To.Offset = toffset
189 q.Link = p.Link
190 p.Link = q
191 return q
192 }
193
194 func (pp *Progs) SetText(fn *ir.Func) {
195 if pp.Text != nil {
196 base.Fatalf("Progs.SetText called twice")
197 }
198 ptxt := pp.Prog(obj.ATEXT)
199 pp.Text = ptxt
200
201 fn.LSym.Func().Text = ptxt
202 ptxt.From.Type = obj.TYPE_MEM
203 ptxt.From.Name = obj.NAME_EXTERN
204 ptxt.From.Sym = fn.LSym
205 }
206
207
208
209
210
211 func LosesStmtMark(as obj.As) bool {
212
213 return as == obj.APCDATA || as == obj.AFUNCDATA
214 }
215
View as plain text