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 clear(pp.Cache[:pp.CacheIndex])
120 }
121
122 *pp = Progs{}
123 }
124
125
126 func (pp *Progs) Prog(as obj.As) *obj.Prog {
127 if pp.NextLive != StackMapDontCare && pp.NextLive != pp.PrevLive {
128
129 idx := pp.NextLive
130 pp.PrevLive = idx
131 p := pp.Prog(obj.APCDATA)
132 p.From.SetConst(abi.PCDATA_StackMapIndex)
133 p.To.SetConst(int64(idx))
134 }
135 if pp.NextUnsafe != pp.PrevUnsafe {
136
137 pp.PrevUnsafe = pp.NextUnsafe
138 p := pp.Prog(obj.APCDATA)
139 p.From.SetConst(abi.PCDATA_UnsafePoint)
140 if pp.NextUnsafe {
141 p.To.SetConst(abi.UnsafePointUnsafe)
142 } else {
143 p.To.SetConst(abi.UnsafePointSafe)
144 }
145 }
146
147 p := pp.Next
148 pp.Next = pp.NewProg()
149 pp.Clear(pp.Next)
150 p.Link = pp.Next
151
152 if !pp.Pos.IsKnown() && base.Flag.K != 0 {
153 base.Warn("prog: unknown position (line 0)")
154 }
155
156 p.As = as
157 p.Pos = pp.Pos
158 if pp.Pos.IsStmt() == src.PosIsStmt {
159
160 if LosesStmtMark(as) {
161 return p
162 }
163 pp.Pos = pp.Pos.WithNotStmt()
164 }
165 return p
166 }
167
168 func (pp *Progs) Clear(p *obj.Prog) {
169 obj.Nopout(p)
170 p.As = obj.AEND
171 p.Pc = pp.PC
172 pp.PC++
173 }
174
175 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 {
176 q := pp.NewProg()
177 pp.Clear(q)
178 q.As = as
179 q.Pos = p.Pos
180 q.From.Type = ftype
181 q.From.Reg = freg
182 q.From.Offset = foffset
183 q.To.Type = ttype
184 q.To.Reg = treg
185 q.To.Offset = toffset
186 q.Link = p.Link
187 p.Link = q
188 return q
189 }
190
191 func (pp *Progs) SetText(fn *ir.Func) {
192 if pp.Text != nil {
193 base.Fatalf("Progs.SetText called twice")
194 }
195 ptxt := pp.Prog(obj.ATEXT)
196 pp.Text = ptxt
197
198 fn.LSym.Func().Text = ptxt
199 ptxt.From.Type = obj.TYPE_MEM
200 ptxt.From.Name = obj.NAME_EXTERN
201 ptxt.From.Sym = fn.LSym
202 }
203
204
205
206
207
208 func LosesStmtMark(as obj.As) bool {
209
210 return as == obj.APCDATA || as == obj.AFUNCDATA
211 }
212
View as plain text