1 /*
2 * Copyright 2021 ByteDance Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package ir
18
19 import (
20 "fmt"
21 "reflect"
22 "strconv"
23 "strings"
24 "unsafe"
25
26 "github.com/bytedance/sonic/internal/encoder/vars"
27 "github.com/bytedance/sonic/internal/resolver"
28 "github.com/bytedance/sonic/internal/rt"
29 )
30
31 type Op uint8
32
33 const (
34 OP_null Op = iota + 1
35 OP_empty_arr
36 OP_empty_obj
37 OP_bool
38 OP_i8
39 OP_i16
40 OP_i32
41 OP_i64
42 OP_u8
43 OP_u16
44 OP_u32
45 OP_u64
46 OP_f32
47 OP_f64
48 OP_str
49 OP_bin
50 OP_quote
51 OP_number
52 OP_eface
53 OP_iface
54 OP_byte
55 OP_text
56 OP_deref
57 OP_index
58 OP_load
59 OP_save
60 OP_drop
61 OP_drop_2
62 OP_recurse
63 OP_is_nil
64 OP_is_nil_p1
65 OP_is_zero_1
66 OP_is_zero_2
67 OP_is_zero_4
68 OP_is_zero_8
69 OP_is_zero_map
70 OP_goto
71 OP_map_iter
72 OP_map_stop
73 OP_map_check_key
74 OP_map_write_key
75 OP_map_value_next
76 OP_slice_len
77 OP_slice_next
78 OP_marshal
79 OP_marshal_p
80 OP_marshal_text
81 OP_marshal_text_p
82 OP_cond_set
83 OP_cond_testc
84 OP_unsupported
85 OP_is_zero
86 )
87
88 const (
89 _INT_SIZE = 32 << (^uint(0) >> 63)
90 _PTR_SIZE = 32 << (^uintptr(0) >> 63)
91 _PTR_BYTE = unsafe.Sizeof(uintptr(0))
92 )
93
94 const OpSize = unsafe.Sizeof(NewInsOp(0))
95
96 var OpNames = [256]string{
97 OP_null: "null",
98 OP_empty_arr: "empty_arr",
99 OP_empty_obj: "empty_obj",
100 OP_bool: "bool",
101 OP_i8: "i8",
102 OP_i16: "i16",
103 OP_i32: "i32",
104 OP_i64: "i64",
105 OP_u8: "u8",
106 OP_u16: "u16",
107 OP_u32: "u32",
108 OP_u64: "u64",
109 OP_f32: "f32",
110 OP_f64: "f64",
111 OP_str: "str",
112 OP_bin: "bin",
113 OP_quote: "quote",
114 OP_number: "number",
115 OP_eface: "eface",
116 OP_iface: "iface",
117 OP_byte: "byte",
118 OP_text: "text",
119 OP_deref: "deref",
120 OP_index: "index",
121 OP_load: "load",
122 OP_save: "save",
123 OP_drop: "drop",
124 OP_drop_2: "drop_2",
125 OP_recurse: "recurse",
126 OP_is_nil: "is_nil",
127 OP_is_nil_p1: "is_nil_p1",
128 OP_is_zero_1: "is_zero_1",
129 OP_is_zero_2: "is_zero_2",
130 OP_is_zero_4: "is_zero_4",
131 OP_is_zero_8: "is_zero_8",
132 OP_is_zero_map: "is_zero_map",
133 OP_goto: "goto",
134 OP_map_iter: "map_iter",
135 OP_map_stop: "map_stop",
136 OP_map_check_key: "map_check_key",
137 OP_map_write_key: "map_write_key",
138 OP_map_value_next: "map_value_next",
139 OP_slice_len: "slice_len",
140 OP_slice_next: "slice_next",
141 OP_marshal: "marshal",
142 OP_marshal_p: "marshal_p",
143 OP_marshal_text: "marshal_text",
144 OP_marshal_text_p: "marshal_text_p",
145 OP_cond_set: "cond_set",
146 OP_cond_testc: "cond_testc",
147 OP_unsupported: "unsupported type",
148 }
149
150 func (self Op) String() string {
151 if ret := OpNames[self]; ret != "" {
152 return ret
153 } else {
154 return "<invalid>"
155 }
156 }
157
158 func OP_int() Op {
159 switch _INT_SIZE {
160 case 32:
161 return OP_i32
162 case 64:
163 return OP_i64
164 default:
165 panic("unsupported int size")
166 }
167 }
168
169 func OP_uint() Op {
170 switch _INT_SIZE {
171 case 32:
172 return OP_u32
173 case 64:
174 return OP_u64
175 default:
176 panic("unsupported uint size")
177 }
178 }
179
180 func OP_uintptr() Op {
181 switch _PTR_SIZE {
182 case 32:
183 return OP_u32
184 case 64:
185 return OP_u64
186 default:
187 panic("unsupported pointer size")
188 }
189 }
190
191 func OP_is_zero_ints() Op {
192 switch _INT_SIZE {
193 case 32:
194 return OP_is_zero_4
195 case 64:
196 return OP_is_zero_8
197 default:
198 panic("unsupported integer size")
199 }
200 }
201
202 type Instr struct {
203 o Op
204 u int // union {op: 8, _: 8, vi: 48}, vi maybe int or len(str)
205 p unsafe.Pointer // maybe GoString.Ptr, or *GoType
206 }
207
208 func NewInsOp(op Op) Instr {
209 return Instr{o: op}
210 }
211
212 func NewInsVi(op Op, vi int) Instr {
213 return Instr{o: op, u: vi}
214 }
215
216 func NewInsVs(op Op, vs string) Instr {
217 return Instr{
218 o: op,
219 u: len(vs),
220 p: (*rt.GoString)(unsafe.Pointer(&vs)).Ptr,
221 }
222 }
223
224 func NewInsVt(op Op, vt reflect.Type) Instr {
225 return Instr{
226 o: op,
227 p: unsafe.Pointer(rt.UnpackType(vt)),
228 }
229 }
230
231 type typAndTab struct {
232 vt *rt.GoType
233 itab *rt.GoItab
234 }
235
236 type typAndField struct {
237 vt reflect.Type
238 fv *resolver.FieldMeta
239 }
240
241 func NewInsVtab(op Op, vt reflect.Type, itab *rt.GoItab) Instr {
242 return Instr{
243 o: op,
244 p: unsafe.Pointer(&typAndTab{
245 vt: rt.UnpackType(vt),
246 itab: itab,
247 }),
248 }
249 }
250
251 func NewInsField(op Op, fv *resolver.FieldMeta) Instr {
252 return Instr{
253 o: op,
254 p: unsafe.Pointer(fv),
255 }
256 }
257
258 func NewInsVp(op Op, vt reflect.Type, pv bool) Instr {
259 i := 0
260 if pv {
261 i = 1
262 }
263 return Instr{
264 o: op,
265 u: i,
266 p: unsafe.Pointer(rt.UnpackType(vt)),
267 }
268 }
269
270 func (self Instr) Op() Op {
271 return Op(self.o)
272 }
273
274 func (self Instr) Vi() int {
275 return self.u
276 }
277
278 func (self Instr) Vf() uint8 {
279 return (*rt.GoType)(self.p).KindFlags
280 }
281
282 func (self Instr) VField() (*resolver.FieldMeta) {
283 return (*resolver.FieldMeta)(self.p)
284 }
285
286 func (self Instr) Vs() (v string) {
287 (*rt.GoString)(unsafe.Pointer(&v)).Ptr = self.p
288 (*rt.GoString)(unsafe.Pointer(&v)).Len = self.Vi()
289 return
290 }
291
292 func (self Instr) Vk() reflect.Kind {
293 return (*rt.GoType)(self.p).Kind()
294 }
295
296 func (self Instr) GoType() *rt.GoType {
297 return (*rt.GoType)(self.p)
298 }
299
300 func (self Instr) Vt() reflect.Type {
301 return (*rt.GoType)(self.p).Pack()
302 }
303
304 func (self Instr) Vr() *rt.GoType {
305 return (*rt.GoType)(self.p)
306 }
307
308 func (self Instr) Vp() (vt reflect.Type, pv bool) {
309 return (*rt.GoType)(self.p).Pack(), self.u == 1
310 }
311
312 func (self Instr) Vtab() (vt *rt.GoType, itab *rt.GoItab) {
313 tt := (*typAndTab)(self.p)
314 return tt.vt, tt.itab
315 }
316
317 func (self Instr) Vp2() (vt *rt.GoType, pv bool) {
318 return (*rt.GoType)(self.p), self.u == 1
319 }
320
321 func (self Instr) I64() int64 {
322 return int64(self.Vi())
323 }
324
325 func (self Instr) Byte() byte {
326 return byte(self.Vi())
327 }
328
329 func (self Instr) Vlen() int {
330 return int((*rt.GoType)(self.p).Size)
331 }
332
333 func (self Instr) isBranch() bool {
334 switch self.Op() {
335 case OP_goto:
336 fallthrough
337 case OP_is_nil:
338 fallthrough
339 case OP_is_nil_p1:
340 fallthrough
341 case OP_is_zero_1:
342 fallthrough
343 case OP_is_zero_2:
344 fallthrough
345 case OP_is_zero_4:
346 fallthrough
347 case OP_is_zero_8:
348 fallthrough
349 case OP_map_check_key:
350 fallthrough
351 case OP_map_write_key:
352 fallthrough
353 case OP_slice_next:
354 fallthrough
355 case OP_cond_testc:
356 return true
357 default:
358 return false
359 }
360 }
361
362 func (self Instr) Disassemble() string {
363 switch self.Op() {
364 case OP_byte:
365 return fmt.Sprintf("%-18s%s", self.Op().String(), strconv.QuoteRune(rune(self.Vi())))
366 case OP_text:
367 return fmt.Sprintf("%-18s%s", self.Op().String(), strconv.Quote(self.Vs()))
368 case OP_index:
369 return fmt.Sprintf("%-18s%d", self.Op().String(), self.Vi())
370 case OP_recurse:
371 fallthrough
372 case OP_map_iter:
373 return fmt.Sprintf("%-18s%s", self.Op().String(), self.Vt())
374 case OP_marshal:
375 fallthrough
376 case OP_marshal_p:
377 fallthrough
378 case OP_marshal_text:
379 fallthrough
380 case OP_marshal_text_p:
381 vt, _ := self.Vtab()
382 return fmt.Sprintf("%-18s%s", self.Op().String(), vt.Pack())
383 case OP_goto:
384 fallthrough
385 case OP_is_nil:
386 fallthrough
387 case OP_is_nil_p1:
388 fallthrough
389 case OP_is_zero_1:
390 fallthrough
391 case OP_is_zero_2:
392 fallthrough
393 case OP_is_zero_4:
394 fallthrough
395 case OP_is_zero_8:
396 fallthrough
397 case OP_is_zero_map:
398 fallthrough
399 case OP_cond_testc:
400 fallthrough
401 case OP_map_check_key:
402 fallthrough
403 case OP_map_write_key:
404 return fmt.Sprintf("%-18sL_%d", self.Op().String(), self.Vi())
405 case OP_slice_next:
406 return fmt.Sprintf("%-18sL_%d, %s", self.Op().String(), self.Vi(), self.Vt())
407 default:
408 return fmt.Sprintf("%#v", self)
409 }
410 }
411
412 type (
413 Program []Instr
414 )
415
416 func (self Program) PC() int {
417 return len(self)
418 }
419
420 func (self Program) Tag(n int) {
421 if n >= vars.MaxStack {
422 panic("type nesting too deep")
423 }
424 }
425
426 func (self Program) Pin(i int) {
427 v := &self[i]
428 v.u = self.PC()
429 }
430
431 func (self Program) Rel(v []int) {
432 for _, i := range v {
433 self.Pin(i)
434 }
435 }
436
437 func (self *Program) Add(op Op) {
438 *self = append(*self, NewInsOp(op))
439 }
440
441 func (self *Program) Key(op Op) {
442 *self = append(*self,
443 NewInsVi(OP_byte, '"'),
444 NewInsOp(op),
445 NewInsVi(OP_byte, '"'),
446 )
447 }
448
449 func (self *Program) Int(op Op, vi int) {
450 *self = append(*self, NewInsVi(op, vi))
451 }
452
453 func (self *Program) Str(op Op, vs string) {
454 *self = append(*self, NewInsVs(op, vs))
455 }
456
457 func (self *Program) Rtt(op Op, vt reflect.Type) {
458 *self = append(*self, NewInsVt(op, vt))
459 }
460
461 func (self *Program) Vp(op Op, vt reflect.Type, pv bool) {
462 *self = append(*self, NewInsVp(op, vt, pv))
463 }
464
465 func (self *Program) Vtab(op Op, vt reflect.Type, itab *rt.GoItab) {
466 *self = append(*self, NewInsVtab(op, vt, itab))
467 }
468
469 func (self *Program) VField(op Op, fv *resolver.FieldMeta) {
470 *self = append(*self, NewInsField(op, fv))
471 }
472
473 func (self Program) Disassemble() string {
474 nb := len(self)
475 tab := make([]bool, nb+1)
476 ret := make([]string, 0, nb+1)
477
478 /* prescan to get all the labels */
479 for _, ins := range self {
480 if ins.isBranch() {
481 tab[ins.Vi()] = true
482 }
483 }
484
485 /* disassemble each instruction */
486 for i, ins := range self {
487 if !tab[i] {
488 ret = append(ret, "\t"+ins.Disassemble())
489 } else {
490 ret = append(ret, fmt.Sprintf("L_%d:\n\t%s", i, ins.Disassemble()))
491 }
492 }
493
494 /* add the last label, if needed */
495 if tab[nb] {
496 ret = append(ret, fmt.Sprintf("L_%d:", nb))
497 }
498
499 /* add an "end" indicator, and join all the strings */
500 return strings.Join(append(ret, "\tend"), "\n")
501 }
502