1
2
3
4
5
6
7 package noder
8
9 import (
10 "bytes"
11 "encoding/binary"
12 "fmt"
13 "go/constant"
14 "io"
15 "math/big"
16 "runtime"
17
18 "cmd/compile/internal/base"
19 )
20
21 type pkgEncoder struct {
22 elems [numRelocs][]string
23
24 stringsIdx map[string]int
25 }
26
27 func newPkgEncoder() pkgEncoder {
28 return pkgEncoder{
29 stringsIdx: make(map[string]int),
30 }
31 }
32
33 func (pw *pkgEncoder) dump(out io.Writer) {
34 writeUint32 := func(x uint32) {
35 assert(binary.Write(out, binary.LittleEndian, x) == nil)
36 }
37
38 var sum uint32
39 for _, elems := range &pw.elems {
40 sum += uint32(len(elems))
41 writeUint32(sum)
42 }
43
44 sum = 0
45 for _, elems := range &pw.elems {
46 for _, elem := range elems {
47 sum += uint32(len(elem))
48 writeUint32(sum)
49 }
50 }
51
52 for _, elems := range &pw.elems {
53 for _, elem := range elems {
54 _, err := io.WriteString(out, elem)
55 assert(err == nil)
56 }
57 }
58 }
59
60 func (pw *pkgEncoder) stringIdx(s string) int {
61 if idx, ok := pw.stringsIdx[s]; ok {
62 assert(pw.elems[relocString][idx] == s)
63 return idx
64 }
65
66 idx := len(pw.elems[relocString])
67 pw.elems[relocString] = append(pw.elems[relocString], s)
68 pw.stringsIdx[s] = idx
69 return idx
70 }
71
72 func (pw *pkgEncoder) newEncoder(k reloc, marker syncMarker) encoder {
73 e := pw.newEncoderRaw(k)
74 e.sync(marker)
75 return e
76 }
77
78 func (pw *pkgEncoder) newEncoderRaw(k reloc) encoder {
79 idx := len(pw.elems[k])
80 pw.elems[k] = append(pw.elems[k], "")
81
82 return encoder{
83 p: pw,
84 k: k,
85 idx: idx,
86 }
87 }
88
89
90
91 type encoder struct {
92 p *pkgEncoder
93
94 relocs []relocEnt
95 data bytes.Buffer
96
97 encodingRelocHeader bool
98
99 k reloc
100 idx int
101 }
102
103 func (w *encoder) flush() int {
104 var sb bytes.Buffer
105
106
107 var tmp bytes.Buffer
108 io.Copy(&tmp, &w.data)
109
110
111
112
113 if w.encodingRelocHeader {
114 base.Fatalf("encodingRelocHeader already true; recursive flush?")
115 }
116 w.encodingRelocHeader = true
117 w.sync(syncRelocs)
118 w.len(len(w.relocs))
119 for _, rent := range w.relocs {
120 w.sync(syncReloc)
121 w.len(int(rent.kind))
122 w.len(rent.idx)
123 }
124
125 io.Copy(&sb, &w.data)
126 io.Copy(&sb, &tmp)
127 w.p.elems[w.k][w.idx] = sb.String()
128
129 return w.idx
130 }
131
132 func (w *encoder) checkErr(err error) {
133 if err != nil {
134 base.Fatalf("unexpected error: %v", err)
135 }
136 }
137
138 func (w *encoder) rawUvarint(x uint64) {
139 var buf [binary.MaxVarintLen64]byte
140 n := binary.PutUvarint(buf[:], x)
141 _, err := w.data.Write(buf[:n])
142 w.checkErr(err)
143 }
144
145 func (w *encoder) rawVarint(x int64) {
146
147 ux := uint64(x) << 1
148 if x < 0 {
149 ux = ^ux
150 }
151
152 w.rawUvarint(ux)
153 }
154
155 func (w *encoder) rawReloc(r reloc, idx int) int {
156
157 for i, rent := range w.relocs {
158 if rent.kind == r && rent.idx == idx {
159 return i
160 }
161 }
162
163 i := len(w.relocs)
164 w.relocs = append(w.relocs, relocEnt{r, idx})
165 return i
166 }
167
168 func (w *encoder) sync(m syncMarker) {
169 if !enableSync {
170 return
171 }
172
173
174
175
176
177 var frames []string
178 if !w.encodingRelocHeader && base.Debug.SyncFrames > 0 {
179 pcs := make([]uintptr, base.Debug.SyncFrames)
180 n := runtime.Callers(2, pcs)
181 frames = fmtFrames(pcs[:n]...)
182 }
183
184
185
186 w.rawUvarint(uint64(m))
187 w.rawUvarint(uint64(len(frames)))
188 for _, frame := range frames {
189 w.rawUvarint(uint64(w.rawReloc(relocString, w.p.stringIdx(frame))))
190 }
191 }
192
193 func (w *encoder) bool(b bool) bool {
194 w.sync(syncBool)
195 var x byte
196 if b {
197 x = 1
198 }
199 err := w.data.WriteByte(x)
200 w.checkErr(err)
201 return b
202 }
203
204 func (w *encoder) int64(x int64) {
205 w.sync(syncInt64)
206 w.rawVarint(x)
207 }
208
209 func (w *encoder) uint64(x uint64) {
210 w.sync(syncUint64)
211 w.rawUvarint(x)
212 }
213
214 func (w *encoder) len(x int) { assert(x >= 0); w.uint64(uint64(x)) }
215 func (w *encoder) int(x int) { w.int64(int64(x)) }
216 func (w *encoder) uint(x uint) { w.uint64(uint64(x)) }
217
218 func (w *encoder) reloc(r reloc, idx int) {
219 w.sync(syncUseReloc)
220 w.len(w.rawReloc(r, idx))
221 }
222
223 func (w *encoder) code(c code) {
224 w.sync(c.marker())
225 w.len(c.value())
226 }
227
228 func (w *encoder) string(s string) {
229 w.sync(syncString)
230 w.reloc(relocString, w.p.stringIdx(s))
231 }
232
233 func (w *encoder) strings(ss []string) {
234 w.len(len(ss))
235 for _, s := range ss {
236 w.string(s)
237 }
238 }
239
240 func (w *encoder) value(val constant.Value) {
241 w.sync(syncValue)
242 if w.bool(val.Kind() == constant.Complex) {
243 w.scalar(constant.Real(val))
244 w.scalar(constant.Imag(val))
245 } else {
246 w.scalar(val)
247 }
248 }
249
250 func (w *encoder) scalar(val constant.Value) {
251 switch v := constant.Val(val).(type) {
252 default:
253 panic(fmt.Sprintf("unhandled %v (%v)", val, val.Kind()))
254 case bool:
255 w.code(valBool)
256 w.bool(v)
257 case string:
258 w.code(valString)
259 w.string(v)
260 case int64:
261 w.code(valInt64)
262 w.int64(v)
263 case *big.Int:
264 w.code(valBigInt)
265 w.bigInt(v)
266 case *big.Rat:
267 w.code(valBigRat)
268 w.bigInt(v.Num())
269 w.bigInt(v.Denom())
270 case *big.Float:
271 w.code(valBigFloat)
272 w.bigFloat(v)
273 }
274 }
275
276 func (w *encoder) bigInt(v *big.Int) {
277 b := v.Bytes()
278 w.string(string(b))
279 w.bool(v.Sign() < 0)
280 }
281
282 func (w *encoder) bigFloat(v *big.Float) {
283 b := v.Append(nil, 'p', -1)
284 w.string(string(b))
285 }
286
View as plain text