github.com/cloudwego/frugal@v0.1.15/internal/binary/decoder/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 decoder
    18  
    19  import (
    20      `fmt`
    21      `reflect`
    22  
    23      `github.com/cloudwego/frugal/internal/atm/hir`
    24      `github.com/cloudwego/frugal/internal/binary/defs`
    25      `github.com/cloudwego/frugal/internal/rt`
    26  )
    27  
    28  /** Function Prototype
    29   *
    30   *      func(buf unsafe.Pointer, nb int, i int, p unsafe.Pointer, rs *RuntimeState, st int) (pos int, err error)
    31   */
    32  
    33  const (
    34      ARG_buf = 0
    35      ARG_nb  = 1
    36      ARG_i   = 2
    37      ARG_p   = 3
    38      ARG_rs  = 4
    39      ARG_st  = 5
    40  )
    41  
    42  /** Register Allocations
    43   *
    44   *      P1      Current Working Pointer
    45   *      P2      Input Buffer Pointer
    46   *      P3      Runtime State Pointer
    47   *      P4      Error Type Pointer
    48   *      P5      Error Value Pointer
    49   *
    50   *      R2      Input Cursor
    51   *      R3      State Index
    52   *      R4      Field Tag
    53   */
    54  
    55  const (
    56      WP = hir.P1
    57      IP = hir.P2
    58      RS = hir.P3
    59      ET = hir.P4 // may also be used as a temporary pointer register
    60      EP = hir.P5 // may also be used as a temporary pointer register
    61  )
    62  
    63  const (
    64      IC = hir.R2
    65      ST = hir.R3
    66      TG = hir.R4
    67  )
    68  
    69  const (
    70      TP = hir.P0
    71      TR = hir.R0
    72      UR = hir.R1
    73  )
    74  
    75  const (
    76      LB_eof      = "_eof"
    77      LB_halt     = "_halt"
    78      LB_type     = "_type"
    79      LB_skip     = "_skip"
    80      LB_error    = "_error"
    81      LB_missing  = "_missing"
    82      LB_overflow = "_overflow"
    83  )
    84  
    85  var (
    86      _T_byte      *rt.GoType
    87      _E_overflow  error
    88      _V_zerovalue uint64
    89  )
    90  
    91  func init() {
    92      _T_byte     = rt.UnpackType(reflect.TypeOf(byte(0)))
    93      _E_overflow = fmt.Errorf("frugal: decoder stack overflow")
    94  }
    95  
    96  func Translate(s Program) hir.Program {
    97      p := hir.CreateBuilder()
    98      prologue (p)
    99      program  (p, s)
   100      epilogue (p)
   101      errors   (p)
   102      return p.Build()
   103  }
   104  
   105  func errors(p *hir.Builder) {
   106      p.Label (LB_eof)
   107      p.LDAQ  (ARG_nb, UR)
   108      p.SUB   (TR, UR, TR)
   109      p.GCALL (F_error_eof).
   110        A0    (TR).
   111        R0    (ET).
   112        R1    (EP)
   113      p.JMP   (LB_error)
   114      p.Label (LB_type)
   115      p.GCALL (F_error_type).
   116        A0    (UR).
   117        A1    (TR).
   118        R0    (ET).
   119        R1    (EP)
   120      p.JMP   (LB_error)
   121      p.Label (LB_skip)
   122      p.GCALL (F_error_skip).
   123        A0    (TR).
   124        R0    (ET).
   125        R1    (EP)
   126      p.JMP   (LB_error)
   127      p.Label (LB_missing)
   128      p.GCALL (F_error_missing).
   129        A0    (ET).
   130        A1    (UR).
   131        A2    (TR).
   132        R0    (ET).
   133        R1    (EP)
   134      p.JMP   (LB_error)
   135      p.Label (LB_overflow)
   136      p.IP    (&_E_overflow, TP)
   137      p.LP    (TP, 0, ET)
   138      p.LP    (TP, 8, EP)
   139      p.JMP   (LB_error)
   140  }
   141  
   142  func program(p *hir.Builder, s Program) {
   143      for i, v := range s {
   144          p.Mark(i)
   145          translators[v.Op](p, v)
   146      }
   147  }
   148  
   149  func prologue(p *hir.Builder) {
   150      p.LDAP  (ARG_buf, IP)
   151      p.LDAQ  (ARG_i, IC)
   152      p.LDAP  (ARG_p, WP)
   153      p.LDAP  (ARG_rs, RS)
   154      p.LDAQ  (ARG_st, ST)
   155      p.MOV   (hir.Rz, TR)
   156      p.MOV   (hir.Rz, UR)
   157  }
   158  
   159  func epilogue(p *hir.Builder) {
   160      p.Label (LB_halt)
   161      p.MOVP  (hir.Pn, ET)
   162      p.MOVP  (hir.Pn, EP)
   163      p.Label (LB_error)
   164      p.RET   ().
   165        R0    (IC).
   166        R1    (ET).
   167        R2    (EP)
   168  }
   169  
   170  var translators = [256]func(*hir.Builder, Instr) {
   171      OP_int               : translate_OP_int,
   172      OP_str               : translate_OP_str,
   173      OP_str_nocopy        : translate_OP_str_nocopy,
   174      OP_bin               : translate_OP_bin,
   175      OP_bin_nocopy        : translate_OP_bin_nocopy,
   176      OP_enum              : translate_OP_enum,
   177      OP_size              : translate_OP_size,
   178      OP_type              : translate_OP_type,
   179      OP_seek              : translate_OP_seek,
   180      OP_deref             : translate_OP_deref,
   181      OP_ctr_load          : translate_OP_ctr_load,
   182      OP_ctr_decr          : translate_OP_ctr_decr,
   183      OP_ctr_is_zero       : translate_OP_ctr_is_zero,
   184      OP_map_alloc         : translate_OP_map_alloc,
   185      OP_map_close         : translate_OP_map_close,
   186      OP_map_set_i8        : translate_OP_map_set_i8,
   187      OP_map_set_i16       : translate_OP_map_set_i16,
   188      OP_map_set_i32       : translate_OP_map_set_i32,
   189      OP_map_set_i64       : translate_OP_map_set_i64,
   190      OP_map_set_str       : translate_OP_map_set_str,
   191      OP_map_set_enum      : translate_OP_map_set_enum,
   192      OP_map_set_pointer   : translate_OP_map_set_pointer,
   193      OP_list_alloc        : translate_OP_list_alloc,
   194      OP_struct_skip       : translate_OP_struct_skip,
   195      OP_struct_ignore     : translate_OP_struct_ignore,
   196      OP_struct_bitmap     : translate_OP_struct_bitmap,
   197      OP_struct_switch     : translate_OP_struct_switch,
   198      OP_struct_require    : translate_OP_struct_require,
   199      OP_struct_is_stop    : translate_OP_struct_is_stop,
   200      OP_struct_mark_tag   : translate_OP_struct_mark_tag,
   201      OP_struct_read_type  : translate_OP_struct_read_type,
   202      OP_struct_check_type : translate_OP_struct_check_type,
   203      OP_make_state        : translate_OP_make_state,
   204      OP_drop_state        : translate_OP_drop_state,
   205      OP_construct         : translate_OP_construct,
   206      OP_initialize        : translate_OP_initialize,
   207      OP_defer             : translate_OP_defer,
   208      OP_goto              : translate_OP_goto,
   209      OP_halt              : translate_OP_halt,
   210  }
   211  
   212  func translate_OP_int(p *hir.Builder, v Instr) {
   213      switch v.Iv {
   214          case 1  : p.ADDP(IP, IC, EP); p.LB(EP, 0, TR);                  p.SB(TR, WP, 0); p.ADDI(IC, 1, IC)
   215          case 2  : p.ADDP(IP, IC, EP); p.LW(EP, 0, TR); p.SWAPW(TR, TR); p.SW(TR, WP, 0); p.ADDI(IC, 2, IC)
   216          case 4  : p.ADDP(IP, IC, EP); p.LL(EP, 0, TR); p.SWAPL(TR, TR); p.SL(TR, WP, 0); p.ADDI(IC, 4, IC)
   217          case 8  : p.ADDP(IP, IC, EP); p.LQ(EP, 0, TR); p.SWAPQ(TR, TR); p.SQ(TR, WP, 0); p.ADDI(IC, 8, IC)
   218          default : panic("can only convert 1, 2, 4 or 8 bytes at a time")
   219      }
   220  }
   221  
   222  func translate_OP_str(p *hir.Builder, _ Instr) {
   223      p.SP    (hir.Pn, WP, 0)
   224      p.ADDP  (IP, IC, EP)
   225      p.ADDI  (IC, 4, IC)
   226      p.LL    (EP, 0, TR)
   227      p.SWAPL (TR, TR)
   228      p.LDAQ  (ARG_nb, UR)
   229      p.BLTU  (UR, TR, LB_eof)
   230      p.BEQ   (TR, hir.Rz, "_empty_{n}")
   231      p.ADDPI (EP, 4, EP)
   232      p.ADD   (IC, TR, IC)
   233      p.GCALL (F_slicebytetostring).
   234        A0    (hir.Pn).
   235        A1    (EP).
   236        A2    (TR).
   237        R0    (TP).
   238        R1    (TR)
   239      p.SP    (TP, WP, 0)
   240      p.Label ("_empty_{n}")
   241      p.SQ    (TR, WP, 8)
   242  }
   243  
   244  func translate_OP_str_nocopy(p *hir.Builder, _ Instr) {
   245      p.SP    (hir.Pn, WP, 0)
   246      translate_OP_binstr_nocopy(p)
   247  }
   248  
   249  func translate_OP_bin(p *hir.Builder, _ Instr) {
   250      p.IP    (&_V_zerovalue, TP)
   251      p.SP    (TP, WP, 0)
   252      p.ADDP  (IP, IC, EP)
   253      p.ADDI  (IC, 4, IC)
   254      p.LL    (EP, 0, TR)
   255      p.SWAPL (TR, TR)
   256      p.LDAQ  (ARG_nb, UR)
   257      p.BLTU  (UR, TR, LB_eof)
   258      p.BEQ   (TR, hir.Rz, "_empty_{n}")
   259      p.ADDPI (EP, 4, EP)
   260      p.ADD   (IC, TR, IC)
   261      p.IP    (_T_byte, TP)
   262      p.GCALL (F_mallocgc).
   263        A0    (TR).
   264        A1    (TP).
   265        A2    (hir.Rz).
   266        R0    (TP)
   267      p.BCOPY (EP, TR, TP)
   268      p.SP    (TP, WP, 0)
   269      p.Label ("_empty_{n}")
   270      p.SQ    (TR, WP, 8)
   271      p.SQ    (TR, WP, 16)
   272  }
   273  
   274  func translate_OP_bin_nocopy(p *hir.Builder, _ Instr) {
   275      p.IP    (&_V_zerovalue, TP)
   276      p.SP    (TP, WP, 0)
   277      translate_OP_binstr_nocopy(p)
   278      p.SQ    (TR, WP, 16)
   279  }
   280  
   281  func translate_OP_binstr_nocopy(p *hir.Builder) {
   282      p.ADDP  (IP, IC, EP)
   283      p.ADDI  (IC, 4, IC)
   284      p.LL    (EP, 0, TR)
   285      p.SWAPL (TR, TR)
   286      p.LDAQ  (ARG_nb, UR)
   287      p.BLTU  (UR, TR, LB_eof)
   288      p.BEQ   (TR, hir.Rz, "_empty_{n}")
   289      p.ADDPI (EP, 4, EP)
   290      p.ADD   (IC, TR, IC)
   291      p.SP    (EP, WP, 0)
   292      p.Label ("_empty_{n}")
   293      p.SQ    (TR, WP, 8)
   294  }
   295  
   296  func translate_OP_enum(p *hir.Builder, _ Instr) {
   297      p.ADDP  (IP, IC, EP)
   298      p.LL    (EP, 0, TR)
   299      p.SWAPL (TR, TR)
   300      p.SXLQ  (TR, TR)
   301      p.SQ    (TR, WP, 0)
   302      p.ADDI  (IC, 4, IC)
   303  }
   304  
   305  func translate_OP_size(p *hir.Builder, v Instr) {
   306      p.IQ    (v.Iv, TR)
   307      p.LDAQ  (ARG_nb, UR)
   308      p.BLTU  (UR, TR, LB_eof)
   309  }
   310  
   311  func translate_OP_type(p *hir.Builder, v Instr) {
   312      p.ADDP  (IP, IC, TP)
   313      p.LB    (TP, 0, TR)
   314      p.IB    (int8(v.Tx), UR)
   315      p.BNE   (TR, UR, LB_type)
   316      p.ADDI  (IC, 1, IC)
   317  }
   318  
   319  func translate_OP_seek(p *hir.Builder, v Instr) {
   320      p.ADDPI (WP, v.Iv, WP)
   321  }
   322  
   323  func translate_OP_deref(p *hir.Builder, v Instr) {
   324      p.LQ    (WP, 0, TR)
   325      p.BNE   (TR, hir.Rz, "_skip_{n}")
   326      p.IB    (1, UR)
   327      p.IP    (v.Vt, TP)
   328      p.IQ    (int64(v.Vt.Size), TR)
   329      p.GCALL (F_mallocgc).
   330        A0    (TR).
   331        A1    (TP).
   332        A2    (UR).
   333        R0    (TP)
   334      p.SP    (TP, WP, 0)
   335      p.Label ("_skip_{n}")
   336      p.LP    (WP, 0, WP)
   337  }
   338  
   339  func translate_OP_ctr_load(p *hir.Builder, _ Instr) {
   340      p.ADDP  (IP, IC, EP)
   341      p.ADDI  (IC, 4, IC)
   342      p.LL    (EP, 0, TR)
   343      p.SWAPL (TR, TR)
   344      p.ADDP  (RS, ST, TP)
   345      p.SQ    (TR, TP, NbOffset)
   346  }
   347  
   348  func translate_OP_ctr_decr(p *hir.Builder, _ Instr) {
   349      p.ADDP  (RS, ST, TP)
   350      p.LQ    (TP, NbOffset, TR)
   351      p.SUBI  (TR, 1, TR)
   352      p.SQ    (TR, TP, NbOffset)
   353  }
   354  
   355  func translate_OP_ctr_is_zero(p *hir.Builder, v Instr) {
   356      p.ADDP  (RS, ST, TP)
   357      p.LQ    (TP, NbOffset, TR)
   358      p.BEQ   (TR, hir.Rz, p.At(v.To))
   359  }
   360  
   361  func translate_OP_map_alloc(p *hir.Builder, v Instr) {
   362      p.ADDP  (RS, ST, TP)
   363      p.LQ    (TP, NbOffset, TR)
   364      p.IP    (v.Vt, ET)
   365      p.GCALL (F_makemap).
   366        A0    (ET).
   367        A1    (TR).
   368        A2    (hir.Pn).
   369        R0    (TP)
   370      p.SP    (TP, WP, 0)
   371      p.ADDP  (RS, ST, EP)
   372      p.SP    (TP, EP, MpOffset)
   373  }
   374  
   375  func translate_OP_map_close(p *hir.Builder, _ Instr) {
   376      p.ADDP  (RS, ST, TP)
   377      p.SP    (hir.Pn, TP, MpOffset)
   378  }
   379  
   380  func translate_OP_map_set_i8(p *hir.Builder, v Instr) {
   381      p.ADDP  (IP, IC, EP)
   382      p.ADDP  (RS, ST, TP)
   383      p.LP    (TP, MpOffset, TP)
   384      p.IP    (v.Vt, ET)
   385      p.GCALL (F_mapassign).
   386        A0    (ET).
   387        A1    (TP).
   388        A2    (EP).
   389        R0    (WP)
   390      p.ADDI  (IC, 1, IC)
   391  }
   392  
   393  func translate_OP_map_set_i16(p *hir.Builder, v Instr) {
   394      p.ADDP  (IP, IC, ET)
   395      p.ADDI  (IC, 2, IC)
   396      p.ADDP  (RS, ST, TP)
   397      p.LP    (TP, MpOffset, EP)
   398      p.LW    (ET, 0, TR)
   399      p.SWAPW (TR, TR)
   400      p.SW    (TR, RS, IvOffset)
   401      p.ADDPI (RS, IvOffset, TP)
   402      p.IP    (v.Vt, ET)
   403      p.GCALL (F_mapassign).
   404        A0    (ET).
   405        A1    (EP).
   406        A2    (TP).
   407        R0    (WP)
   408  }
   409  
   410  func translate_OP_map_set_i32(p *hir.Builder, v Instr) {
   411      if rt.MapType(v.Vt).IsFastMap() {
   412          translate_OP_map_set_i32_fast(p, v)
   413      } else {
   414          translate_OP_map_set_i32_safe(p, v)
   415      }
   416  }
   417  
   418  func translate_OP_map_set_i32_fast(p *hir.Builder, v Instr) {
   419      p.ADDP  (IP, IC, EP)
   420      p.ADDI  (IC, 4, IC)
   421      p.ADDP  (RS, ST, TP)
   422      p.LP    (TP, MpOffset, TP)
   423      p.LL    (EP, 0, TR)
   424      p.SWAPL (TR, TR)
   425      p.IP    (v.Vt, ET)
   426      p.GCALL (F_mapassign_fast32).
   427        A0    (ET).
   428        A1    (TP).
   429        A2    (TR).
   430        R0    (WP)
   431  }
   432  
   433  func translate_OP_map_set_i32_safe(p *hir.Builder, v Instr) {
   434      p.ADDP  (IP, IC, ET)
   435      p.ADDI  (IC, 4, IC)
   436      p.ADDP  (RS, ST, TP)
   437      p.LP    (TP, MpOffset, EP)
   438      p.LL    (ET, 0, TR)
   439      p.SWAPL (TR, TR)
   440      p.SL    (TR, RS, IvOffset)
   441      p.ADDPI (RS, IvOffset, TP)
   442      p.IP    (v.Vt, ET)
   443      p.GCALL (F_mapassign).
   444        A0    (ET).
   445        A1    (EP).
   446        A2    (TP).
   447        R0    (WP)
   448  }
   449  
   450  func translate_OP_map_set_i64(p *hir.Builder, v Instr) {
   451      if rt.MapType(v.Vt).IsFastMap() {
   452          translate_OP_map_set_i64_fast(p, v)
   453      } else {
   454          translate_OP_map_set_i64_safe(p, v)
   455      }
   456  }
   457  
   458  func translate_OP_map_set_i64_fast(p *hir.Builder, v Instr) {
   459      p.ADDP  (IP, IC, EP)
   460      p.ADDI  (IC, 8, IC)
   461      p.ADDP  (RS, ST, TP)
   462      p.LP    (TP, MpOffset, TP)
   463      p.LQ    (EP, 0, TR)
   464      p.SWAPQ (TR, TR)
   465      p.IP    (v.Vt, ET)
   466      p.GCALL (F_mapassign_fast64).
   467        A0    (ET).
   468        A1    (TP).
   469        A2    (TR).
   470        R0    (WP)
   471  }
   472  
   473  func translate_OP_map_set_i64_safe(p *hir.Builder, v Instr) {
   474      p.ADDP  (IP, IC, ET)
   475      p.ADDI  (IC, 2, IC)
   476      p.ADDP  (RS, ST, TP)
   477      p.LP    (TP, MpOffset, EP)
   478      p.LQ    (ET, 0, TR)
   479      p.SWAPQ (TR, TR)
   480      p.SQ    (TR, RS, IvOffset)
   481      p.ADDPI (RS, IvOffset, TP)
   482      p.IP    (v.Vt, ET)
   483      p.GCALL (F_mapassign).
   484        A0    (ET).
   485        A1    (EP).
   486        A2    (TP).
   487        R0    (WP)
   488  }
   489  
   490  func translate_OP_map_set_str(p *hir.Builder, v Instr) {
   491      if rt.MapType(v.Vt).IsFastMap() {
   492          translate_OP_map_set_str_fast(p, v)
   493      } else {
   494          translate_OP_map_set_str_safe(p, v)
   495      }
   496  }
   497  
   498  func translate_OP_map_set_str_fast(p *hir.Builder, v Instr) {
   499      p.ADDP  (IP, IC, EP)
   500      p.ADDI  (IC, 4, IC)
   501      p.LL    (EP, 0, TR)
   502      p.SWAPL (TR, TR)
   503      p.LDAQ  (ARG_nb, UR)
   504      p.BLTU  (UR, TR, LB_eof)
   505      p.MOVP  (hir.Pn, EP)
   506      p.BEQ   (TR, hir.Rz, "_empty_{n}")
   507      p.ADDP  (IP, IC, ET)
   508      p.ADD   (IC, TR, IC)
   509      p.GCALL (F_slicebytetostring).
   510        A0    (hir.Pn).
   511        A1    (ET).
   512        A2    (TR).
   513        R0    (EP).
   514        R1    (TR)
   515      p.Label ("_empty_{n}")
   516      p.ADDP  (RS, ST, TP)
   517      p.LP    (TP, MpOffset, TP)
   518      p.IP    (v.Vt, ET)
   519      p.GCALL (F_mapassign_faststr).
   520        A0    (ET).
   521        A1    (TP).
   522        A2    (EP).
   523        A3    (TR).
   524        R0    (WP)
   525  }
   526  
   527  func translate_OP_map_set_str_safe(p *hir.Builder, v Instr) {
   528      p.ADDP  (IP, IC, ET)
   529      p.ADDI  (IC, 4, IC)
   530      p.LL    (ET, 0, TR)
   531      p.SWAPL (TR, TR)
   532      p.LDAQ  (ARG_nb, UR)
   533      p.BLTU  (UR, TR, LB_eof)
   534      p.SQ    (TR, RS, IvOffset)
   535      p.SP    (hir.Pn, RS, PrOffset)
   536      p.BEQ   (TR, hir.Rz, "_empty_{n}")
   537      p.ADDPI (ET, 4, ET)
   538      p.ADD   (IC, TR, IC)
   539      p.GCALL (F_slicebytetostring).
   540        A0    (hir.Pn).
   541        A1    (ET).
   542        A2    (TR).
   543        R0    (TP).
   544        R1    (TR)
   545      p.SP    (TP, RS, PrOffset)
   546      p.Label ("_empty_{n}")
   547      p.ADDP  (RS, ST, EP)
   548      p.LP    (EP, MpOffset, EP)
   549      p.IP    (v.Vt, ET)
   550      p.ADDPI (RS, PrOffset, TP)
   551      p.GCALL (F_mapassign).
   552        A0    (ET).
   553        A1    (EP).
   554        A2    (TP).
   555        R0    (WP)
   556      p.SP    (hir.Pn, RS, PrOffset)
   557  }
   558  
   559  func translate_OP_map_set_enum(p *hir.Builder, v Instr) {
   560      if rt.MapType(v.Vt).IsFastMap() {
   561          translate_OP_map_set_enum_fast(p, v)
   562      } else {
   563          translate_OP_map_set_enum_safe(p, v)
   564      }
   565  }
   566  
   567  func translate_OP_map_set_enum_fast(p *hir.Builder, v Instr) {
   568      p.ADDP  (IP, IC, EP)
   569      p.ADDI  (IC, 4, IC)
   570      p.ADDP  (RS, ST, TP)
   571      p.LP    (TP, MpOffset, TP)
   572      p.LL    (EP, 0, TR)
   573      p.SWAPL (TR, TR)
   574      p.SXLQ  (TR, TR)
   575      p.IP    (v.Vt, ET)
   576      p.GCALL (F_mapassign_fast64).
   577          A0    (ET).
   578          A1    (TP).
   579          A2    (TR).
   580          R0    (WP)
   581  }
   582  
   583  func translate_OP_map_set_enum_safe(p *hir.Builder, v Instr) {
   584      p.ADDP  (IP, IC, ET)
   585      p.ADDI  (IC, 4, IC)
   586      p.ADDP  (RS, ST, TP)
   587      p.LP    (TP, MpOffset, EP)
   588      p.LL    (ET, 0, TR)
   589      p.SWAPL (TR, TR)
   590      p.SXLQ  (TR, TR)
   591      p.SQ    (TR, RS, IvOffset)
   592      p.ADDPI (RS, IvOffset, TP)
   593      p.IP    (v.Vt, ET)
   594      p.GCALL (F_mapassign).
   595          A0    (ET).
   596          A1    (EP).
   597          A2    (TP).
   598          R0    (WP)
   599  }
   600  
   601  func translate_OP_map_set_pointer(p *hir.Builder, v Instr) {
   602      if rt.MapType(v.Vt).IsFastMap() {
   603          translate_OP_map_set_pointer_fast(p, v)
   604      } else {
   605          translate_OP_map_set_pointer_safe(p, v)
   606      }
   607  }
   608  
   609  func translate_OP_map_set_pointer_fast(p *hir.Builder, v Instr) {
   610      p.ADDP  (RS, ST, TP)
   611      p.LP    (TP, MpOffset, TP)
   612      p.IP    (v.Vt, ET)
   613      p.GCALL (F_mapassign_fast64ptr).
   614        A0    (ET).
   615        A1    (TP).
   616        A2    (WP).
   617        R0    (WP)
   618  }
   619  
   620  func translate_OP_map_set_pointer_safe(p *hir.Builder, v Instr) {
   621      p.ADDP  (RS, ST, TP)
   622      p.LP    (TP, MpOffset, EP)
   623      p.SP    (WP, RS, PrOffset)
   624      p.IP    (v.Vt, ET)
   625      p.ADDPI (RS, PrOffset, TP)
   626      p.GCALL (F_mapassign).
   627        A0    (ET).
   628        A1    (EP).
   629        A2    (TP).
   630        R0    (WP)
   631      p.SP    (hir.Pn, RS, PrOffset)
   632  }
   633  
   634  func translate_OP_list_alloc(p *hir.Builder, v Instr) {
   635      p.ADDP  (RS, ST, TP)
   636      p.LQ    (TP, NbOffset, TR)
   637      p.SQ    (TR, WP, 8)
   638      p.LQ    (WP, 16, UR)
   639      p.BNE   (TR, hir.Rz, "_alloc_{n}")
   640      p.BNE   (UR, hir.Rz, "_done_{n}")
   641      p.IP    (&_V_zerovalue, TP)
   642      p.SP    (TP, WP, 0)
   643      p.SQ    (hir.Rz, WP, 16)
   644      p.JMP   ("_done_{n}")
   645      p.Label ("_alloc_{n}")
   646      p.BGEU  (UR, TR, "_done_{n}")
   647      p.SQ    (TR, WP, 16)
   648      p.IB    (1, UR)
   649      p.IP    (v.Vt, TP)
   650      p.MULI  (TR, int64(v.Vt.Size), TR)
   651      p.GCALL (F_mallocgc).
   652        A0    (TR).
   653        A1    (TP).
   654        A2    (UR).
   655        R0    (TP)
   656      p.SP    (TP, WP, 0)
   657      p.Label ("_done_{n}")
   658      p.LP    (WP, 0, WP)
   659  }
   660  
   661  func translate_OP_struct_skip(p *hir.Builder, _ Instr) {
   662      p.ADDPI (RS, SkOffset, TP)
   663      p.LDAQ  (ARG_nb, TR)
   664      p.SUB   (TR, IC, TR)
   665      p.ADDP  (IP, IC, EP)
   666      p.CCALL (C_skip).
   667        A0    (TP).
   668        A1    (EP).
   669        A2    (TR).
   670        A3    (TG).
   671        R0    (TR)
   672      p.BLT   (TR, hir.Rz, LB_skip)
   673      p.ADD   (IC, TR, IC)
   674  }
   675  
   676  func translate_OP_struct_ignore(p *hir.Builder, _ Instr) {
   677      p.ADDPI (RS, SkOffset, TP)
   678      p.LDAQ  (ARG_nb, TR)
   679      p.SUB   (TR, IC, TR)
   680      p.ADDP  (IP, IC, EP)
   681      p.IB    (int8(defs.T_struct), TG)
   682      p.CCALL (C_skip).
   683        A0    (TP).
   684        A1    (EP).
   685        A2    (TR).
   686        A3    (TG).
   687        R0    (TR)
   688      p.BLT   (TR, hir.Rz, LB_skip)
   689      p.ADD   (IC, TR, IC)
   690  }
   691  
   692  func translate_OP_struct_bitmap(p *hir.Builder, v Instr) {
   693      buf := newFieldBitmap()
   694      buf.Clear()
   695  
   696      /* add all the bits */
   697      for _, i := range v.IntSeq() {
   698          buf.Append(i)
   699      }
   700  
   701      /* allocate a new bitmap */
   702      p.GCALL (F_newFieldBitmap).R0(TP)
   703      p.ADDP  (RS, ST, EP)
   704      p.SP    (TP, EP, FmOffset)
   705  
   706      /* clear bits of required fields if any */
   707      for i := int64(0); i < MaxBitmap; i++ {
   708          if buf[i] != 0 {
   709              p.SQ(hir.Rz, TP, i * 8)
   710          }
   711      }
   712  
   713      /* release the buffer */
   714      buf.Clear()
   715      buf.Free()
   716  }
   717  
   718  func translate_OP_struct_switch(p *hir.Builder, v Instr) {
   719      stab := v.IntSeq()
   720      ptab := make([]string, v.Iv)
   721  
   722      /* convert the switch table */
   723      for i, to := range stab {
   724          if to >= 0 {
   725              ptab[i] = p.At(to)
   726          }
   727      }
   728  
   729      /* load and dispatch the field */
   730      p.ADDP  (IP, IC, EP)
   731      p.ADDI  (IC, 2, IC)
   732      p.LW    (EP, 0, TR)
   733      p.SWAPW (TR, TR)
   734      p.BSW   (TR, ptab)
   735  }
   736  
   737  func translate_OP_struct_require(p *hir.Builder, v Instr) {
   738      buf := newFieldBitmap()
   739      buf.Clear()
   740  
   741      /* add all the bits */
   742      for _, i := range v.IntSeq() {
   743          buf.Append(i)
   744      }
   745  
   746      /* load the bitmap */
   747      p.ADDP  (RS, ST, EP)
   748      p.LP    (EP, FmOffset, TP)
   749  
   750      /* test mask for each word if any */
   751      for i := int64(0); i < MaxBitmap; i++ {
   752          if buf[i] != 0 {
   753              p.LQ    (TP, i * 8, TR)
   754              p.ANDI  (TR, buf[i], TR)
   755              p.XORI  (TR, buf[i], TR)
   756              p.IQ    (i, UR)
   757              p.IP    (v.Vt, ET)
   758              p.BNE   (TR, hir.Rz, LB_missing)
   759          }
   760      }
   761  
   762      /* free the bitmap */
   763      p.SP    (hir.Pn, EP, FmOffset)
   764      p.GCALL (F_FieldBitmap_Free).A0(TP)
   765  
   766      /* release the buffer */
   767      buf.Clear()
   768      buf.Free()
   769  }
   770  
   771  func translate_OP_struct_is_stop(p *hir.Builder, v Instr) {
   772      p.BEQ   (TG, hir.Rz, p.At(v.To))
   773  }
   774  
   775  func translate_OP_struct_mark_tag(p *hir.Builder, v Instr) {
   776      p.ADDP  (RS, ST, TP)
   777      p.LP    (TP, FmOffset, TP)
   778      p.LQ    (TP, v.Iv / 64 * 8, TR)
   779      p.BSI   (TR, v.Iv % 64, TR)
   780      p.SQ    (TR, TP, v.Iv / 64 * 8)
   781  }
   782  
   783  func translate_OP_struct_read_type(p *hir.Builder, _ Instr) {
   784      p.ADDP  (IP, IC, EP)
   785      p.ADDI  (IC, 1, IC)
   786      p.LB    (EP, 0, TG)
   787  }
   788  
   789  func translate_OP_struct_check_type(p *hir.Builder, v Instr) {
   790      p.IB    (int8(v.Tx), TR)
   791      p.BNE   (TG, TR, p.At(v.To))
   792  }
   793  
   794  func translate_OP_make_state(p *hir.Builder, _ Instr) {
   795      p.IQ    (StateMax, TR)
   796      p.BGEU  (ST, TR, LB_overflow)
   797      p.ADDP  (RS, ST, TP)
   798      p.SP    (WP, TP, WpOffset)
   799      p.ADDI  (ST, StateSize, ST)
   800  }
   801  
   802  func translate_OP_drop_state(p *hir.Builder, _ Instr) {
   803      p.SUBI  (ST, StateSize, ST)
   804      p.ADDP  (RS, ST, TP)
   805      p.LP    (TP, WpOffset, WP)
   806      p.SP    (hir.Pn, TP, WpOffset)
   807  }
   808  
   809  func translate_OP_construct(p *hir.Builder, v Instr) {
   810      p.IB    (1, UR)
   811      p.IP    (v.Vt, TP)
   812      p.IQ    (int64(v.Vt.Size), TR)
   813      p.GCALL (F_mallocgc).
   814        A0    (TR).
   815        A1    (TP).
   816        A2    (UR).
   817        R0    (WP)
   818  }
   819  
   820  func translate_OP_initialize(p *hir.Builder, v Instr) {
   821      p.GCALL (addInitFn(v.Fn)).
   822        A0    (WP)
   823  }
   824  
   825  func translate_OP_defer(p *hir.Builder, v Instr) {
   826      p.IP    (v.Vt, TP)
   827      p.LDAQ  (ARG_nb, TR)
   828      p.GCALL (F_decode).
   829        A0    (TP).
   830        A1    (IP).
   831        A2    (TR).
   832        A3    (IC).
   833        A4    (WP).
   834        A5    (RS).
   835        A6    (ST).
   836        R0    (IC).
   837        R1    (ET).
   838        R2    (EP)
   839      p.BNEP  (ET, hir.Pn, LB_error)
   840  }
   841  
   842  func translate_OP_goto(p *hir.Builder, v Instr) {
   843      p.JMP   (p.At(v.To))
   844  }
   845  
   846  func translate_OP_halt(p *hir.Builder, _ Instr) {
   847      p.JMP   (LB_halt)
   848  }