utils.go raw

   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)
 148