github.com/cloudwego/frugal@v0.1.15/internal/binary/encoder/compiler_encode.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      `math`
    21  
    22      `github.com/cloudwego/frugal/internal/atm/abi`
    23      `github.com/cloudwego/frugal/internal/binary/defs`
    24  )
    25  
    26  func (self *Compiler) compile(p *Program, sp int, vt *defs.Type, startpc int) {
    27      rt := vt.S
    28      tt := vt.T
    29  
    30      /* only recurse on structs */
    31      if tt != defs.T_struct {
    32          self.compileOne(p, sp, vt, startpc)
    33          return
    34      }
    35  
    36      /* check for loops */
    37      if self.t[rt] || !self.o.CanInline(sp, (p.pc() - startpc) * 2) {
    38          p.rtt(OP_defer, rt)
    39          return
    40      }
    41  
    42      /* compile the type recursively */
    43      self.t[rt] = true
    44      self.compileOne(p, sp, vt, startpc)
    45      delete(self.t, rt)
    46  }
    47  
    48  func (self *Compiler) compileOne(p *Program, sp int, vt *defs.Type, startpc int) {
    49      switch vt.T {
    50          case defs.T_bool    : p.i64(OP_size_check, 1); p.i64(OP_sint, 1)
    51          case defs.T_i8      : p.i64(OP_size_check, 1); p.i64(OP_sint, 1)
    52          case defs.T_i16     : p.i64(OP_size_check, 2); p.i64(OP_sint, 2)
    53          case defs.T_i32     : p.i64(OP_size_check, 4); p.i64(OP_sint, 4)
    54          case defs.T_i64     : p.i64(OP_size_check, 8); p.i64(OP_sint, 8)
    55          case defs.T_enum    : p.i64(OP_size_check, 4); p.i64(OP_sint, 4)
    56          case defs.T_double  : p.i64(OP_size_check, 8); p.i64(OP_sint, 8)
    57          case defs.T_string  : p.i64(OP_size_check, 4); p.i64(OP_length, abi.PtrSize); p.dyn(OP_memcpy_be, abi.PtrSize, 1)
    58          case defs.T_binary  : p.i64(OP_size_check, 4); p.i64(OP_length, abi.PtrSize); p.dyn(OP_memcpy_be, abi.PtrSize, 1)
    59          case defs.T_map     : self.compileMap(p, sp, vt, startpc)
    60          case defs.T_set     : self.compileSeq(p, sp, vt, startpc, true)
    61          case defs.T_list    : self.compileSeq(p, sp, vt, startpc, false)
    62          case defs.T_struct  : self.compileStruct(p, sp, vt, startpc)
    63          case defs.T_pointer : self.compilePtr(p, sp, vt, startpc)
    64          default             : panic("unreachable")
    65      }
    66  }
    67  
    68  func (self *Compiler) compilePtr(p *Program, sp int, vt *defs.Type, startpc int) {
    69      i := p.pc()
    70      p.tag(sp)
    71      p.add(OP_if_nil)
    72      p.add(OP_make_state)
    73      p.add(OP_deref)
    74      self.compile(p, sp + 1, vt.V, startpc)
    75      p.add(OP_drop_state)
    76      p.pin(i)
    77  }
    78  
    79  func (self *Compiler) compileMap(p *Program, sp int, vt *defs.Type, startpc int) {
    80      kt := vt.K
    81      et := vt.V
    82  
    83      /* 6-byte map header */
    84      p.tag(sp)
    85      p.i64(OP_size_check, 6)
    86      p.i64(OP_byte, int64(kt.Tag()))
    87      p.i64(OP_byte, int64(et.Tag()))
    88  
    89      /* check for nil maps */
    90      i := p.pc()
    91      p.add(OP_if_nil)
    92  
    93      /* encode the map */
    94      p.add(OP_map_len)
    95      j := p.pc()
    96      p.add(OP_map_if_empty)
    97      p.add(OP_make_state)
    98      p.rtt(OP_map_begin, vt.S)
    99      k := p.pc()
   100      p.add(OP_map_key)
   101      self.compileItem(p, sp + 1, kt, startpc)
   102      p.add(OP_map_value)
   103      self.compileItem(p, sp + 1, et, startpc)
   104      p.add(OP_map_next)
   105      p.jmp(OP_map_if_next, k)
   106      p.add(OP_drop_state)
   107  
   108      /* encode the length for nil maps */
   109      r := p.pc()
   110      p.add(OP_goto)
   111      p.pin(i)
   112      p.i64(OP_long, 0)
   113      p.pin(j)
   114      p.pin(r)
   115  }
   116  
   117  func (self *Compiler) compileSeq(p *Program, sp int, vt *defs.Type, startpc int, verifyUnique bool) {
   118      nb := -1
   119      et := vt.V
   120  
   121      /* 5-byte set or list header */
   122      p.tag(sp)
   123      p.i64(OP_size_check, 5)
   124      p.i64(OP_byte, int64(et.Tag()))
   125      p.i64(OP_length, abi.PtrSize)
   126  
   127      /* check for nil slice */
   128      i := p.pc()
   129      p.add(OP_if_nil)
   130  
   131      /* special case of primitive sets or lists */
   132      switch et.T {
   133          case defs.T_bool   : nb = 1
   134          case defs.T_i8     : nb = 1
   135          case defs.T_i16    : nb = 2
   136          case defs.T_i32    : nb = 4
   137          case defs.T_i64    : nb = 8
   138          case defs.T_double : nb = 8
   139      }
   140  
   141      /* check for uniqueness if needed */
   142      if verifyUnique {
   143          p.rtt(OP_unique, et.S)
   144      }
   145  
   146      /* check if this is the special case */
   147      if nb != -1 {
   148          p.dyn(OP_memcpy_be, abi.PtrSize, int64(nb))
   149          p.pin(i)
   150          return
   151      }
   152  
   153      /* complex sets or lists */
   154      j := p.pc()
   155      p.add(OP_list_if_empty)
   156      p.add(OP_make_state)
   157      p.add(OP_list_begin)
   158      k := p.pc()
   159      p.add(OP_goto)
   160      r := p.pc()
   161      p.i64(OP_seek, int64(et.S.Size()))
   162      p.pin(k)
   163      self.compileItem(p, sp + 1, et, startpc)
   164      p.add(OP_list_decr)
   165      p.jmp(OP_list_if_next, r)
   166      p.add(OP_drop_state)
   167      p.pin(i)
   168      p.pin(j)
   169  }
   170  
   171  func (self *Compiler) compileItem(p *Program, sp int, vt *defs.Type, startpc int) {
   172      tag := vt.T
   173      elem := vt.V
   174  
   175      /* special handling for pointers */
   176      if tag != defs.T_pointer {
   177          self.compile(p, sp, vt, startpc)
   178          return
   179      }
   180  
   181      /* must be pointer struct at this point */
   182      if elem.T != defs.T_struct {
   183          panic("fatal: non-struct pointers within container elements")
   184      }
   185  
   186      /* always add the STOP field for structs */
   187      i := p.pc()
   188      p.tag(sp)
   189      p.add(OP_if_nil)
   190      p.add(OP_make_state)
   191      p.add(OP_deref)
   192      self.compile(p, sp + 1, elem, startpc)
   193      p.add(OP_drop_state)
   194      j := p.pc()
   195      p.add(OP_goto)
   196      p.pin(i)
   197      p.i64(OP_size_check, 1)
   198      p.i64(OP_byte, 0)
   199      p.pin(j)
   200  }
   201  
   202  func (self *Compiler) compileStruct(p *Program, sp int, vt *defs.Type, startpc int) {
   203      var err error
   204      var fvs []defs.Field
   205  
   206      /* resolve the field */
   207      if fvs, err = defs.ResolveFields(vt.S); err != nil {
   208          panic(err)
   209      }
   210  
   211      /* compile every field */
   212      for _, fv := range fvs {
   213          p.tag(sp)
   214          p.i64(OP_seek, int64(fv.F))
   215          self.compileStructField(p, sp + 1, fv, startpc)
   216          p.i64(OP_seek, -int64(fv.F))
   217      }
   218  
   219      /* add the STOP field */
   220      p.i64(OP_size_check, 1)
   221      p.i64(OP_byte, 0)
   222  }
   223  
   224  func (self *Compiler) compileStructField(p *Program, sp int, fv defs.Field, startpc int) {
   225      switch fv.Type.T {
   226          default: {
   227              panic("fatal: invalid field type: " + fv.Type.String())
   228          }
   229  
   230          /* non-pointer types */
   231          case defs.T_bool   : fallthrough
   232          case defs.T_i8     : fallthrough
   233          case defs.T_double : fallthrough
   234          case defs.T_i16    : fallthrough
   235          case defs.T_i32    : fallthrough
   236          case defs.T_i64    : fallthrough
   237          case defs.T_string : fallthrough
   238          case defs.T_enum   : fallthrough
   239          case defs.T_binary : {
   240              if fv.Default.IsValid() && fv.Spec == defs.Optional {
   241                  self.compileStructDefault(p, sp, fv, startpc)
   242              } else {
   243                  self.compileStructRequired(p, sp, fv, startpc)
   244              }
   245          }
   246  
   247          /* struct types, only available in hand-written structs */
   248          case defs.T_struct: {
   249              self.compileStructRequired(p, sp, fv, startpc)
   250          }
   251  
   252          /* sequencial types */
   253          case defs.T_map  : fallthrough
   254          case defs.T_set  : fallthrough
   255          case defs.T_list : {
   256              if fv.Spec == defs.Optional {
   257                  self.compileStructIterable(p, sp, fv, startpc)
   258              } else {
   259                  self.compileStructRequired(p, sp, fv, startpc)
   260              }
   261          }
   262  
   263          /* pointers */
   264          case defs.T_pointer: {
   265              if fv.Spec == defs.Optional {
   266                  self.compileStructOptional(p, sp, fv, startpc)
   267              } else if fv.Type.V.T == defs.T_struct {
   268                  self.compileStructPointer(p, sp, fv, startpc)
   269              } else {
   270                  panic("fatal: non-optional non-struct pointers")
   271              }
   272          }
   273      }
   274  }
   275  
   276  func (self *Compiler) compileStructDefault(p *Program, sp int, fv defs.Field, startpc int) {
   277      i := p.pc()
   278      t := fv.Type.T
   279  
   280      /* check for default values */
   281      switch t {
   282          case defs.T_bool   : p.dyn(OP_if_eq_imm, 1, bool2i64(fv.Default.Bool()))
   283          case defs.T_i8     : p.dyn(OP_if_eq_imm, 1, fv.Default.Int())
   284          case defs.T_double : p.dyn(OP_if_eq_imm, 8, int64(math.Float64bits(fv.Default.Float())))
   285          case defs.T_i16    : p.dyn(OP_if_eq_imm, 2, fv.Default.Int())
   286          case defs.T_i32    : p.dyn(OP_if_eq_imm, 4, fv.Default.Int())
   287          case defs.T_i64    : p.dyn(OP_if_eq_imm, 8, fv.Default.Int())
   288          case defs.T_string : p.str(OP_if_eq_str, fv.Default.String())
   289          case defs.T_enum   : p.dyn(OP_if_eq_imm, 4, fv.Default.Int())
   290          case defs.T_binary : p.str(OP_if_eq_str, mem2str(fv.Default.Bytes()))
   291          default            : panic("unreachable")
   292      }
   293  
   294      /* compile if it's not the default value */
   295      self.compileStructFieldBegin(p, fv, 3)
   296      self.compile(p, sp, fv.Type, startpc)
   297      p.pin(i)
   298  }
   299  
   300  func (self *Compiler) compileStructPointer(p *Program, sp int, fv defs.Field, startpc int) {
   301      i := p.pc()
   302      p.add(OP_if_nil)
   303      self.compileStructFieldBegin(p, fv, 4)
   304      p.add(OP_make_state)
   305      p.add(OP_deref)
   306      self.compile(p, sp + 1, fv.Type.V, startpc)
   307      p.add(OP_drop_state)
   308      j := p.pc()
   309      p.add(OP_goto)
   310      p.pin(i)
   311      self.compileStructFieldBegin(p, fv, 4)
   312      p.i64(OP_byte, 0)
   313      p.pin(j)
   314  }
   315  
   316  func (self *Compiler) compileStructIterable(p *Program, sp int, fv defs.Field, startpc int) {
   317      i := p.pc()
   318      p.add(OP_if_nil)
   319      self.compileStructFieldBegin(p, fv, 3)
   320      self.compile(p, sp, fv.Type, startpc)
   321      p.pin(i)
   322  }
   323  
   324  func (self *Compiler) compileStructOptional(p *Program, sp int, fv defs.Field, startpc int) {
   325      i := p.pc()
   326      p.add(OP_if_nil)
   327      self.compileStructFieldBegin(p, fv, 3)
   328      p.add(OP_make_state)
   329      p.add(OP_deref)
   330      self.compile(p, sp + 1, fv.Type.V, startpc)
   331      p.add(OP_drop_state)
   332      p.pin(i)
   333  }
   334  
   335  func (self *Compiler) compileStructRequired(p *Program, sp int, fv defs.Field, startpc int) {
   336      self.compileStructFieldBegin(p, fv, 3)
   337      self.compile(p, sp, fv.Type, startpc)
   338  }
   339  
   340  func (self *Compiler) compileStructFieldBegin(p *Program, fv defs.Field, nb int64) {
   341      p.i64(OP_size_check, nb)
   342      p.i64(OP_byte, int64(fv.Type.Tag()))
   343      p.i64(OP_word, int64(fv.ID))
   344  }