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  }