github.com/cloudwego/iasm@v0.2.0/x86_64/utils.go (about)

     1  //
     2  // Copyright 2024 CloudWeGo Authors
     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 x86_64
    18  
    19  import (
    20      `encoding/binary`
    21      `errors`
    22      `reflect`
    23      `strconv`
    24      `unicode/utf8`
    25      `unsafe`
    26  )
    27  
    28  const (
    29      _CC_digit = 1 << iota
    30      _CC_ident
    31      _CC_ident0
    32      _CC_number
    33  )
    34  
    35  func ispow2(v uint64) bool {
    36      return (v & (v - 1)) == 0
    37  }
    38  
    39  func isdigit(cc rune) bool {
    40      return '0' <= cc && cc <= '9'
    41  }
    42  
    43  func isalpha(cc rune) bool {
    44      return (cc >= 'a' && cc <= 'z') || (cc >= 'A' && cc <= 'Z')
    45  }
    46  
    47  func isident(cc rune) bool {
    48      return cc == '_' || isalpha(cc) || isdigit(cc)
    49  }
    50  
    51  func isident0(cc rune) bool {
    52      return cc == '_' || isalpha(cc)
    53  }
    54  
    55  func isnumber(cc rune) bool {
    56      return (cc == 'b' || cc == 'B') ||
    57             (cc == 'o' || cc == 'O') ||
    58             (cc == 'x' || cc == 'X') ||
    59             (cc >= '0' && cc <= '9') ||
    60             (cc >= 'a' && cc <= 'f') ||
    61             (cc >= 'A' && cc <= 'F')
    62  }
    63  
    64  func align(v int, n int) int {
    65      return (((v - 1) >> n) + 1) << n
    66  }
    67  
    68  func append8(m *[]byte, v byte) {
    69      *m = append(*m, v)
    70  }
    71  
    72  func append16(m *[]byte, v uint16) {
    73      p := len(*m)
    74      *m = append(*m, 0, 0)
    75      binary.LittleEndian.PutUint16((*m)[p:], v)
    76  }
    77  
    78  func append32(m *[]byte, v uint32) {
    79      p := len(*m)
    80      *m = append(*m, 0, 0, 0, 0)
    81      binary.LittleEndian.PutUint32((*m)[p:], v)
    82  }
    83  
    84  func append64(m *[]byte, v uint64) {
    85      p := len(*m)
    86      *m = append(*m, 0, 0, 0, 0, 0, 0, 0, 0)
    87      binary.LittleEndian.PutUint64((*m)[p:], v)
    88  }
    89  
    90  func expandmm(m *[]byte, n int, v byte) {
    91      sl := (*_GoSlice)(unsafe.Pointer(m))
    92      nb := sl.len + n
    93  
    94      /* grow as needed */
    95      if nb > cap(*m) {
    96          *m = growslice(byteType, *m, nb)
    97      }
    98  
    99      /* fill the new area */
   100      memset(unsafe.Pointer(uintptr(sl.ptr) + uintptr(sl.len)), v, uintptr(n))
   101      sl.len = nb
   102  }
   103  
   104  func memset(p unsafe.Pointer, c byte, n uintptr) {
   105      if c != 0 {
   106          memsetv(p, c, n)
   107      } else {
   108          memclrNoHeapPointers(p, n)
   109      }
   110  }
   111  
   112  func memsetv(p unsafe.Pointer, c byte, n uintptr) {
   113      for i := uintptr(0); i < n; i++ {
   114          *(*byte)(unsafe.Pointer(uintptr(p) + i)) = c
   115      }
   116  }
   117  
   118  func literal64(v string) (uint64, error) {
   119      var nb int
   120      var ch rune
   121      var ex error
   122      var mm [12]byte
   123  
   124      /* unquote the runes */
   125      for v != "" {
   126          if ch, _, v, ex = strconv.UnquoteChar(v, '\''); ex != nil {
   127              return 0, ex
   128          } else if nb += utf8.EncodeRune(mm[nb:], ch); nb > 8 {
   129              return 0, errors.New("multi-char constant too large")
   130          }
   131      }
   132  
   133      /* convert to uint64 */
   134      return *(*uint64)(unsafe.Pointer(&mm)), nil
   135  }
   136  
   137  var (
   138      byteWrap = reflect.TypeOf(byte(0))
   139      byteType = (*_GoType)(efaceOf(byteWrap).ptr)
   140  )
   141  
   142  //go:linkname growslice runtime.growslice
   143  func growslice(_ *_GoType, _ []byte, _ int) []byte
   144  
   145  //go:noescape
   146  //go:linkname memclrNoHeapPointers runtime.memclrNoHeapPointers
   147  func memclrNoHeapPointers(_ unsafe.Pointer, _ uintptr)