github.com/cloudwego/frugal@v0.1.15/internal/binary/encoder/translator.go (about) 1 /* 2 * Copyright 2022 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 encoder 18 19 import ( 20 `fmt` 21 `os` 22 `reflect` 23 24 `github.com/cloudwego/frugal/internal/atm/abi` 25 `github.com/cloudwego/frugal/internal/atm/hir` 26 `github.com/cloudwego/frugal/internal/binary/defs` 27 `github.com/cloudwego/frugal/internal/rt` 28 `github.com/cloudwego/frugal/internal/utils` 29 ) 30 31 /** Function Prototype 32 * 33 * func ( 34 * buf unsafe.Pointer, 35 * len int, 36 * mem iov.BufferWriter, 37 * p unsafe.Pointer, 38 * rs *RuntimeState, 39 * st int, 40 * ) ( 41 * pos int, 42 * err error, 43 * ) 44 */ 45 46 const ( 47 ARG_buf = 0 48 ARG_len = 1 49 ARG_mem_itab = 2 50 ARG_mem_data = 3 51 ARG_p = 4 52 ARG_rs = 5 53 ARG_st = 6 54 ) 55 56 /** Register Allocations 57 * 58 * P1 Current Working Pointer 59 * P2 Output Buffer Pointer 60 * P3 Runtime State Pointer 61 * P4 Error Type Pointer 62 * P5 Error Value Pointer 63 * 64 * R2 Output Buffer Length 65 * R3 Output Buffer Capacity 66 * R4 State Index 67 */ 68 69 const ( 70 WP = hir.P1 71 RP = hir.P2 72 RS = hir.P3 73 ET = hir.P4 // may also be used as a temporary pointer register 74 EP = hir.P5 // may also be used as a temporary pointer register 75 ) 76 77 const ( 78 RL = hir.R2 79 RC = hir.R3 80 ST = hir.R4 81 ) 82 83 const ( 84 TP = hir.P0 85 TR = hir.R0 86 UR = hir.R1 87 ) 88 89 const ( 90 LB_halt = "_halt" 91 LB_error = "_error" 92 LB_nomem = "_nomem" 93 LB_overflow = "_overflow" 94 LB_duplicated = "_duplicated" 95 ) 96 97 var ( 98 _N_page = int64(os.Getpagesize()) 99 _E_nomem = fmt.Errorf("frugal: buffer is too small") 100 _E_overflow = fmt.Errorf("frugal: encoder stack overflow") 101 _E_duplicated = fmt.Errorf("frugal: duplicated element within sets") 102 ) 103 104 func Translate(s Program) hir.Program { 105 p := hir.CreateBuilder() 106 prologue (p) 107 program (p, s) 108 epilogue (p) 109 errors (p) 110 return p.Build() 111 } 112 113 func errors(p *hir.Builder) { 114 p.Label (LB_nomem) 115 p.MOV (UR, RL) 116 p.IP (&_E_nomem, TP) 117 p.JMP ("_basic_error") 118 p.Label (LB_overflow) 119 p.IP (&_E_overflow, TP) 120 p.JMP ("_basic_error") 121 p.Label (LB_duplicated) 122 p.IP (&_E_duplicated, TP) 123 p.Label ("_basic_error") 124 p.LP (TP, 0, ET) 125 p.LP (TP, 8, EP) 126 p.JMP (LB_error) 127 } 128 129 func program(p *hir.Builder, s Program) { 130 for i, v := range s { 131 p.Mark(i) 132 translators[v.Op](p, v) 133 } 134 } 135 136 func prologue(p *hir.Builder) { 137 p.LDAP (ARG_buf, RP) 138 p.LDAQ (ARG_len, RC) 139 p.LDAP (ARG_p, WP) 140 p.LDAP (ARG_rs, RS) 141 p.LDAQ (ARG_st, ST) 142 p.MOV (hir.Rz, UR) 143 p.MOV (hir.Rz, RL) 144 } 145 146 func epilogue(p *hir.Builder) { 147 p.Label (LB_halt) 148 p.MOVP (hir.Pn, ET) 149 p.MOVP (hir.Pn, EP) 150 p.Label (LB_error) 151 p.RET (). 152 R0 (RL). 153 R1 (ET). 154 R2 (EP) 155 } 156 157 var translators = [256]func(*hir.Builder, Instr) { 158 OP_size_check : translate_OP_size_check, 159 OP_size_const : translate_OP_size_const, 160 OP_size_dyn : translate_OP_size_dyn, 161 OP_size_map : translate_OP_size_map, 162 OP_size_defer : translate_OP_size_defer, 163 OP_byte : translate_OP_byte, 164 OP_word : translate_OP_word, 165 OP_long : translate_OP_long, 166 OP_quad : translate_OP_quad, 167 OP_sint : translate_OP_sint, 168 OP_length : translate_OP_length, 169 OP_memcpy_be : translate_OP_memcpy_be, 170 OP_seek : translate_OP_seek, 171 OP_deref : translate_OP_deref, 172 OP_defer : translate_OP_defer, 173 OP_map_len : translate_OP_map_len, 174 OP_map_key : translate_OP_map_key, 175 OP_map_next : translate_OP_map_next, 176 OP_map_value : translate_OP_map_value, 177 OP_map_begin : translate_OP_map_begin, 178 OP_map_if_next : translate_OP_map_if_next, 179 OP_map_if_empty : translate_OP_map_if_empty, 180 OP_list_decr : translate_OP_list_decr, 181 OP_list_begin : translate_OP_list_begin, 182 OP_list_if_next : translate_OP_list_if_next, 183 OP_list_if_empty : translate_OP_list_if_empty, 184 OP_unique : translate_OP_unique, 185 OP_goto : translate_OP_goto, 186 OP_if_nil : translate_OP_if_nil, 187 OP_if_hasbuf : translate_OP_if_hasbuf, 188 OP_if_eq_imm : translate_OP_if_eq_imm, 189 OP_if_eq_str : translate_OP_if_eq_str, 190 OP_make_state : translate_OP_make_state, 191 OP_drop_state : translate_OP_drop_state, 192 OP_halt : translate_OP_halt, 193 } 194 195 func translate_OP_size_check(p *hir.Builder, v Instr) { 196 p.ADDI (RL, v.Iv, UR) 197 p.BLTU (RC, UR, LB_nomem) 198 } 199 200 func translate_OP_size_const(p *hir.Builder, v Instr) { 201 p.ADDI (RL, v.Iv, RL) 202 } 203 204 func translate_OP_size_dyn(p *hir.Builder, v Instr) { 205 p.LQ (WP, int64(v.Uv), TR) 206 p.MULI (TR, v.Iv, TR) 207 p.ADD (RL, TR, RL) 208 } 209 210 func translate_OP_size_map(p *hir.Builder, v Instr) { 211 p.LP (WP, 0, TP) 212 p.LQ (TP, 0, TR) 213 p.MULI (TR, v.Iv, TR) 214 p.ADD (RL, TR, RL) 215 } 216 217 func translate_OP_size_defer(p *hir.Builder, v Instr) { 218 p.IP (v.Vt(), TP) 219 p.GCALL (F_encode). 220 A0 (TP). 221 A1 (hir.Pn). 222 A2 (hir.Rz). 223 A3 (hir.Pn). 224 A4 (hir.Pn). 225 A5 (WP). 226 A6 (RS). 227 A7 (ST). 228 R0 (TR). 229 R1 (ET). 230 R2 (EP) 231 p.BNEP (ET, hir.Pn, LB_error) 232 p.ADD (RL, TR, RL) 233 } 234 235 func translate_OP_byte(p *hir.Builder, v Instr) { 236 p.ADDP (RP, RL, TP) 237 p.ADDI (RL, 1, RL) 238 p.IB (int8(v.Iv), TR) 239 p.SB (TR, TP, 0) 240 } 241 242 func translate_OP_word(p *hir.Builder, v Instr) { 243 p.ADDP (RP, RL, TP) 244 p.ADDI (RL, 2, RL) 245 p.IW (bswap16(v.Iv), TR) 246 p.SW (TR, TP, 0) 247 } 248 249 func translate_OP_long(p *hir.Builder, v Instr) { 250 p.ADDP (RP, RL, TP) 251 p.ADDI (RL, 4, RL) 252 p.IL (bswap32(v.Iv), TR) 253 p.SL (TR, TP, 0) 254 } 255 256 func translate_OP_quad(p *hir.Builder, v Instr) { 257 p.ADDP (RP, RL, TP) 258 p.ADDI (RL, 8, RL) 259 p.IQ (bswap64(v.Iv), TR) 260 p.SQ (TR, TP, 0) 261 } 262 263 func translate_OP_sint(p *hir.Builder, v Instr) { 264 p.ADDP (RP, RL, TP) 265 p.ADDI (RL, v.Iv, RL) 266 267 /* check for copy size */ 268 switch v.Iv { 269 case 1 : p.LB(WP, 0, TR); p.SB(TR, TP, 0) 270 case 2 : p.LW(WP, 0, TR); p.SWAPW(TR, TR); p.SW(TR, TP, 0) 271 case 4 : p.LL(WP, 0, TR); p.SWAPL(TR, TR); p.SL(TR, TP, 0) 272 case 8 : p.LQ(WP, 0, TR); p.SWAPQ(TR, TR); p.SQ(TR, TP, 0) 273 default : panic("can only convert 1, 2, 4 or 8 bytes at a time") 274 } 275 } 276 277 func translate_OP_length(p *hir.Builder, v Instr) { 278 p.LL (WP, v.Iv, TR) 279 p.SWAPL (TR, TR) 280 p.ADDP (RP, RL, TP) 281 p.ADDI (RL, 4, RL) 282 p.SL (TR, TP, 0) 283 } 284 285 func translate_OP_memcpy_1(p *hir.Builder) { 286 p.IQ (_N_page, UR) 287 p.BGEU (UR, TR, "_do_copy_{n}") 288 p.LDAP (ARG_mem_itab, ET) 289 p.LDAP (ARG_mem_data, EP) 290 p.BEQP (EP, hir.Pn, "_do_copy_{n}") 291 p.SUB (RC, RL, UR) 292 p.ICALL (ET, EP, utils.FnWrite). 293 A0 (TP). 294 A1 (TR). 295 A2 (TR). 296 A3 (UR). 297 R0 (ET). 298 R1 (EP) 299 p.BNEP (ET, hir.Pn, LB_error) 300 p.JMP ("_done_{n}") 301 p.Label ("_do_copy_{n}") 302 p.ADD (RL, TR, UR) 303 p.BLTU (RC, UR, LB_nomem) 304 p.ADDP (RP, RL, EP) 305 p.MOV (UR, RL) 306 p.BCOPY (TP, TR, EP) 307 p.Label ("_done_{n}") 308 } 309 310 func translate_OP_memcpy_be(p *hir.Builder, v Instr) { 311 p.LQ (WP, int64(v.Uv), TR) 312 p.BEQ (TR, hir.Rz, "_done_{n}") 313 p.LP (WP, 0, TP) 314 315 /* special case: unit of a single byte */ 316 if v.Iv == 1 { 317 translate_OP_memcpy_1(p) 318 return 319 } 320 321 /* adjust the buffer length */ 322 p.MULI (TR, v.Iv, UR) 323 p.ADD (RL, UR, UR) 324 p.BLTU (RC, UR, LB_nomem) 325 p.ADDP (RP, RL, EP) 326 p.MOV (UR, RL) 327 p.Label ("_loop_{n}") 328 p.BEQ (TR, hir.Rz, "_done_{n}") 329 330 /* load-swap-store sequence */ 331 switch v.Iv { 332 case 2 : p.LW(TP, 0, UR); p.SWAPW(UR, UR); p.SW(UR, EP, 0) 333 case 4 : p.LL(TP, 0, UR); p.SWAPL(UR, UR); p.SL(UR, EP, 0) 334 case 8 : p.LQ(TP, 0, UR); p.SWAPQ(UR, UR); p.SQ(UR, EP, 0) 335 default : panic("can only swap 2, 4 or 8 bytes at a time") 336 } 337 338 /* update loop counter */ 339 p.SUBI (TR, 1, TR) 340 p.ADDPI (TP, v.Iv, TP) 341 p.ADDPI (EP, v.Iv, EP) 342 p.JMP ("_loop_{n}") 343 p.Label ("_done_{n}") 344 } 345 346 func translate_OP_seek(p *hir.Builder, v Instr) { 347 p.ADDPI (WP, v.Iv, WP) 348 } 349 350 func translate_OP_deref(p *hir.Builder, _ Instr) { 351 p.LP (WP, 0, WP) 352 } 353 354 func translate_OP_defer(p *hir.Builder, v Instr) { 355 p.IP (v.Vt(), TP) 356 p.LDAP (ARG_mem_itab, ET) 357 p.LDAP (ARG_mem_data, EP) 358 p.SUB (RC, RL, TR) 359 p.ADDP (RP, RL, RP) 360 p.GCALL (F_encode). 361 A0 (TP). 362 A1 (RP). 363 A2 (TR). 364 A3 (ET). 365 A4 (EP). 366 A5 (WP). 367 A6 (RS). 368 A7 (ST). 369 R0 (TR). 370 R1 (ET). 371 R2 (EP) 372 p.SUBP (RP, RL, RP) 373 p.BNEP (ET, hir.Pn, LB_error) 374 p.ADD (RL, TR, RL) 375 } 376 377 func translate_OP_map_len(p *hir.Builder, _ Instr) { 378 p.LP (WP, 0, TP) 379 p.LQ (TP, 0, TR) 380 p.SWAPL (TR, TR) 381 p.ADDP (RP, RL, TP) 382 p.ADDI (RL, 4, RL) 383 p.SL (TR, TP, 0) 384 } 385 386 func translate_OP_map_key(p *hir.Builder, _ Instr) { 387 p.ADDP (RS, ST, TP) 388 p.LP (TP, MiOffset + MiKeyOffset, WP) 389 } 390 391 func translate_OP_map_next(p *hir.Builder, _ Instr) { 392 p.ADDP (RS, ST, TP) 393 p.ADDPI (TP, MiOffset, TP) 394 p.GCALL (F_mapiternext).A0(TP) 395 } 396 397 func translate_OP_map_value(p *hir.Builder, _ Instr) { 398 p.ADDP (RS, ST, TP) 399 p.LP (TP, MiOffset + MiValueOffset, WP) 400 } 401 402 func translate_OP_map_begin(p *hir.Builder, v Instr) { 403 p.IP (v.Vt(), ET) 404 p.LP (WP, 0, EP) 405 p.ADDP (RS, ST, TP) 406 p.ADDPI (TP, MiOffset, TP) 407 p.GCALL (F_mapiterstart). 408 A0 (ET). 409 A1 (EP). 410 A2 (TP) 411 } 412 413 func translate_OP_map_if_next(p *hir.Builder, v Instr) { 414 p.ADDP (RS, ST, TP) 415 p.LP (TP, MiOffset + MiKeyOffset, TP) 416 p.BNEP (TP, hir.Pn, p.At(v.To)) 417 } 418 419 func translate_OP_map_if_empty(p *hir.Builder, v Instr) { 420 p.LP (WP, 0, TP) 421 p.LQ (TP, 0, TR) 422 p.BEQ (TR, hir.Rz, p.At(v.To)) 423 } 424 425 func translate_OP_list_decr(p *hir.Builder, _ Instr) { 426 p.ADDP (RS, ST, TP) 427 p.LQ (TP, LnOffset, TR) 428 p.SUBI (TR, 1, TR) 429 p.SQ (TR, TP, LnOffset) 430 } 431 432 func translate_OP_list_begin(p *hir.Builder, _ Instr) { 433 p.LQ (WP, abi.PtrSize, TR) 434 p.LP (WP, 0, WP) 435 p.ADDP (RS, ST, TP) 436 p.SQ (TR, TP, LnOffset) 437 } 438 439 func translate_OP_list_if_next(p *hir.Builder, v Instr) { 440 p.ADDP (RS, ST, TP) 441 p.LQ (TP, LnOffset, TR) 442 p.BNE (TR, hir.Rz, p.At(v.To)) 443 } 444 445 func translate_OP_list_if_empty(p *hir.Builder, v Instr) { 446 p.LQ (WP, abi.PtrSize, TR) 447 p.BEQ (TR, hir.Rz, p.At(v.To)) 448 } 449 450 func translate_OP_unique(p *hir.Builder, v Instr) { 451 p.IB (2, UR) 452 p.LQ (WP, abi.PtrSize, TR) 453 p.BLTU (TR, UR, "_ok_{n}") 454 translate_OP_unique_type(p, v.Vt()) 455 p.Label ("_ok_{n}") 456 } 457 458 func translate_OP_unique_type(p *hir.Builder, vt *rt.GoType) { 459 switch vt.Kind() { 460 case reflect.Bool : translate_OP_unique_b(p) 461 case reflect.Int : translate_OP_unique_int(p) 462 case reflect.Int8 : translate_OP_unique_i8(p) 463 case reflect.Int16 : translate_OP_unique_i16(p) 464 case reflect.Int32 : translate_OP_unique_i32(p) 465 case reflect.Int64 : translate_OP_unique_i64(p) 466 case reflect.Float64 : translate_OP_unique_i64(p) 467 case reflect.Map : break 468 case reflect.Ptr : break 469 case reflect.Slice : break 470 case reflect.String : translate_OP_unique_str(p) 471 case reflect.Struct : break 472 default : panic("unique: invalid type: " + vt.String()) 473 } 474 } 475 476 func translate_OP_unique_b(p *hir.Builder) { 477 p.BLTU (UR, TR, LB_duplicated) 478 p.LP (WP, 0, TP) 479 p.LB (TP, 0, TR) 480 p.LB (TP, 1, UR) 481 p.BEQ (TR, UR, LB_duplicated) 482 } 483 484 func translate_OP_unique_i8(p *hir.Builder) { 485 p.IQ (RangeUint8, UR) 486 p.BLTU (UR, TR, LB_duplicated) 487 translate_OP_unique_small(p, RangeUint8 / 8, 1, p.LB) 488 } 489 490 func translate_OP_unique_i16(p *hir.Builder) { 491 p.IQ (RangeUint16, UR) 492 p.BLTU (UR, TR, LB_duplicated) 493 translate_OP_unique_small(p, RangeUint16 / 8, 2, p.LW) 494 } 495 496 func translate_OP_unique_int(p *hir.Builder) { 497 switch defs.IntSize { 498 case 4 : translate_OP_unique_i32(p) 499 case 8 : translate_OP_unique_i64(p) 500 default : panic("invalid int size") 501 } 502 } 503 504 func translate_OP_unique_small(p *hir.Builder, nb int64, dv int64, ld func(hir.PointerRegister, int64, hir.GenericRegister) *hir.Ir) { 505 p.ADDPI (RS, BmOffset, ET) 506 p.BZERO (nb, ET) 507 p.LP (WP, 0, EP) 508 p.JMP ("_first_{n}") 509 p.Label ("_loop_{n}") 510 p.ADDPI (EP, dv, EP) 511 p.Label ("_first_{n}") 512 ld (EP, 0, RC) 513 p.SHRI (RC, 3, UR) 514 p.ANDI (RC, 0x3f, RC) 515 p.ANDI (UR, ^0x07, UR) 516 p.ADDP (ET, UR, TP) 517 p.LQ (TP, 0, UR) 518 p.BTS (RC, UR, RC) 519 p.SQ (UR, TP, 0) 520 p.BNE (RC, hir.Rz, LB_duplicated) 521 p.SUBI (TR, 1, TR) 522 p.BNE (TR, hir.Rz, "_loop_{n}") 523 p.LDAQ (ARG_len, RC) 524 } 525 526 func translate_OP_unique_i32(p *hir.Builder) { 527 p.LP (WP, 0, TP) 528 p.GCALL (F_unique32). 529 A0 (TP). 530 A1 (TR). 531 R0 (TR) 532 p.BNE (TR, hir.Rz, LB_duplicated) 533 } 534 535 func translate_OP_unique_i64(p *hir.Builder) { 536 p.LP (WP, 0, TP) 537 p.GCALL (F_unique64). 538 A0 (TP). 539 A1 (TR). 540 R0 (TR) 541 p.BNE (TR, hir.Rz, LB_duplicated) 542 } 543 544 func translate_OP_unique_str(p *hir.Builder) { 545 p.LP (WP, 0, TP) 546 p.GCALL (F_uniquestr). 547 A0 (TP). 548 A1 (TR). 549 R0 (TR) 550 p.BNE (TR, hir.Rz, LB_duplicated) 551 } 552 553 func translate_OP_goto(p *hir.Builder, v Instr) { 554 p.JMP (p.At(v.To)) 555 } 556 557 func translate_OP_if_nil(p *hir.Builder, v Instr) { 558 p.LP (WP, 0, TP) 559 p.BEQP (TP, hir.Pn, p.At(v.To)) 560 } 561 562 func translate_OP_if_hasbuf(p *hir.Builder, v Instr) { 563 p.BNEP (RP, hir.Pn, p.At(v.To)) 564 } 565 566 func translate_OP_if_eq_imm(p *hir.Builder, v Instr) { 567 switch v.Uv { 568 case 1 : p.LB(WP, 0, TR); p.IB( int8(v.Iv), UR); p.BEQ(TR, UR, p.At(v.To)) 569 case 2 : p.LW(WP, 0, TR); p.IW(int16(v.Iv), UR); p.BEQ(TR, UR, p.At(v.To)) 570 case 4 : p.LL(WP, 0, TR); p.IL(int32(v.Iv), UR); p.BEQ(TR, UR, p.At(v.To)) 571 case 8 : p.LQ(WP, 0, TR); p.IQ( v.Iv , UR); p.BEQ(TR, UR, p.At(v.To)) 572 default : panic("invalid imm size") 573 } 574 } 575 576 func translate_OP_if_eq_str(p *hir.Builder, v Instr) { 577 nb := v.Iv 578 to := p.At(v.To) 579 580 /* load the string length */ 581 p.IQ (v.Iv, TR) 582 p.LQ (WP, abi.PtrSize, UR) 583 584 /* empty string */ 585 if v.Iv == 0 { 586 p.BEQ(TR, UR, to) 587 return 588 } 589 590 /* compare the string pointers */ 591 p.BNE (TR, UR, "_neq_{n}") 592 p.IP (v.Pr, TP) 593 p.LP (WP, 0, EP) 594 p.BEQP (TP, EP, to) 595 596 /* compare the content, 4-byte loop */ 597 for nb >= 4 { 598 p.LL (EP, v.Iv - nb, TR) 599 p.IL (v.Long(v.Iv - nb), UR) 600 p.BNE (TR, UR, "_neq_{n}") 601 nb -= 4 602 } 603 604 /* compare the content, 2-byte test */ 605 if nb >= 2 { 606 p.LW (EP, v.Iv - nb, TR) 607 p.IW (v.Word(v.Iv - nb), UR) 608 p.BNE (TR, UR, "_neq_{n}") 609 nb -= 2 610 } 611 612 /* compare the content, the last byte */ 613 if nb != 0 { 614 p.LB (EP, v.Iv - 1, TR) 615 p.IB (v.Byte(v.Iv - 1), UR) 616 p.BNE (TR, UR, "_neq_{n}") 617 } 618 619 /* two string are equal */ 620 p.JMP (to) 621 p.Label ("_neq_{n}") 622 } 623 624 func translate_OP_make_state(p *hir.Builder, _ Instr) { 625 p.IQ (StateMax, TR) 626 p.BGEU (ST, TR, LB_overflow) 627 p.ADDP (RS, ST, TP) 628 p.SP (WP, TP, WpOffset) 629 p.ADDI (ST, StateSize, ST) 630 } 631 632 func translate_OP_drop_state(p *hir.Builder, _ Instr) { 633 p.SUBI (ST, StateSize, ST) 634 p.ADDP (RS, ST, TP) 635 p.LP (TP, WpOffset, WP) 636 p.SP (hir.Pn, TP, WpOffset) 637 } 638 639 func translate_OP_halt(p *hir.Builder, _ Instr) { 640 p.JMP (LB_halt) 641 }