github.com/primecitizens/pcz/std@v0.2.1/core/abi/abi.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright 2023 The Prime Citizens 3 // 4 // Copyright 2020 The Go Authors. All rights reserved. 5 // Use of this source code is governed by a BSD-style 6 // license that can be found in the LICENSE file. 7 8 package abi 9 10 import ( 11 "unsafe" 12 13 "github.com/primecitizens/pcz/std/core/arch" 14 "github.com/primecitizens/pcz/std/core/assert" 15 ) 16 17 // RegArgs is a struct that has space for each argument 18 // and return value register on the current architecture. 19 // 20 // Assembly code knows the layout of the first two fields 21 // of RegArgs. 22 // 23 // RegArgs also contains additional space to hold pointers 24 // when it may not be safe to keep them only in the integer 25 // register space otherwise. 26 type RegArgs struct { 27 // Values in these slots should be precisely the bit-by-bit 28 // representation of how they would appear in a register. 29 // 30 // This means that on big endian arches, integer values should 31 // be in the top bits of the slot. Floats are usually just 32 // directly represented, but some architectures treat narrow 33 // width floating point values specially (e.g. they're promoted 34 // first, or they need to be NaN-boxed). 35 Ints [IntArgRegs]uintptr // untyped integer registers 36 Floats [FloatArgRegs]uint64 // untyped float registers 37 38 // Fields above this point are known to assembly. 39 40 // Ptrs is a space that duplicates Ints but with pointer type, 41 // used to make pointers passed or returned in registers 42 // visible to the GC by making the type unsafe.Pointer. 43 Ptrs [IntArgRegs]unsafe.Pointer 44 45 // ReturnIsPtr is a bitmap that indicates which registers 46 // contain or will contain pointers on the return path from 47 // a reflectcall. The i'th bit indicates whether the i'th 48 // register contains or will contain a valid Go pointer. 49 ReturnIsPtr IntArgRegBitmap 50 } 51 52 func (r *RegArgs) Dump() { 53 print("Ints:") 54 for _, x := range r.Ints { 55 print(" ", x) 56 } 57 println() 58 print("Floats:") 59 for _, x := range r.Floats { 60 print(" ", x) 61 } 62 println() 63 print("Ptrs:") 64 for _, x := range r.Ptrs { 65 print(" ", x) 66 } 67 println() 68 } 69 70 // IntRegArgAddr returns a pointer inside of r.Ints[reg] that is appropriately 71 // offset for an argument of size argSize. 72 // 73 // argSize must be non-zero, fit in a register, and a power-of-two. 74 // 75 // This method is a helper for dealing with the endianness of different CPU 76 // architectures, since sub-word-sized arguments in big endian architectures 77 // need to be "aligned" to the upper edge of the register to be interpreted 78 // by the CPU correctly. 79 func (r *RegArgs) IntRegArgAddr(reg int, argSize uintptr) unsafe.Pointer { 80 if argSize > arch.PtrSize || argSize == 0 || argSize&(argSize-1) != 0 { 81 assert.Throw("invalid", "argSize") 82 } 83 offset := uintptr(0) 84 if arch.BigEndian { 85 offset = arch.PtrSize - argSize 86 } 87 return unsafe.Pointer(uintptr(unsafe.Pointer(&r.Ints[reg])) + offset) 88 } 89 90 // IntArgRegBitmap is a bitmap large enough to hold one bit per 91 // integer argument/return register. 92 type IntArgRegBitmap [(IntArgRegs + 7) / 8]uint8 93 94 // Set sets the i'th bit of the bitmap to 1. 95 func (b *IntArgRegBitmap) Set(i int) { 96 b[i/8] |= uint8(1) << (i % 8) 97 } 98 99 // Get returns whether the i'th bit of the bitmap is set. 100 // 101 // nosplit because it's called in extremely sensitive contexts, like 102 // on the reflectcall return path. 103 // 104 //go:nosplit 105 func (b *IntArgRegBitmap) Get(i int) bool { 106 return b[i/8]&(uint8(1)<<(i%8)) != 0 107 }