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)