github.com/primecitizens/pcz/std@v0.2.1/runtime/builtin_unsafe.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright 2023 The Prime Citizens
     3  
     4  //go:build pcz
     5  
     6  package runtime
     7  
     8  import (
     9  	"unsafe"
    10  
    11  	stdptr "github.com/primecitizens/pcz/std/builtin/ptr"
    12  	"github.com/primecitizens/pcz/std/core/abi"
    13  	"github.com/primecitizens/pcz/std/core/assert"
    14  	"github.com/primecitizens/pcz/std/core/math"
    15  )
    16  
    17  // functions required by compiler for unsafe.Slice and unsafe.String
    18  //
    19  // see $GOROOT/src/runtime/unsafe.go
    20  
    21  //
    22  // unsafe.Slice
    23  //
    24  
    25  // This is called only from compiler-generated code, so we can get the
    26  // source of the panic.
    27  func panicunsafeslicelen()    { panicunsafeslicelen1(getcallerpc()) }
    28  func panicunsafeslicenilptr() { panicunsafeslicenilptr1(getcallerpc()) }
    29  
    30  func panicunsafeslicelen1(pc uintptr) {
    31  	// panicCheck1(pc, "unsafe.Slice: len out of range")
    32  	assert.Panic("unsafe.Slice: len out of range")
    33  }
    34  
    35  func panicunsafeslicenilptr1(pc uintptr) {
    36  	// panicCheck1(pc, "unsafe.Slice: ptr is nil and len is not zero")
    37  	assert.Panic("unsafe.Slice:", "ptr", "is", "nil", "and", "len", "is", "not", "zero")
    38  }
    39  
    40  // Keep this code in sync with cmd/compile/internal/walk/builtin.go:walkUnsafeSlice
    41  func unsafeslice(et *abi.Type, ptr unsafe.Pointer, len int) {
    42  	if len < 0 {
    43  		panicunsafeslicelen1(getcallerpc())
    44  	}
    45  
    46  	if et.Size_ == 0 {
    47  		if ptr == nil && len > 0 {
    48  			panicunsafeslicenilptr1(getcallerpc())
    49  		}
    50  	}
    51  
    52  	mem, overflow := math.MulUintptr(et.Size_, uintptr(len))
    53  	if overflow || mem > -uintptr(ptr) {
    54  		if ptr == nil {
    55  			panicunsafeslicenilptr1(getcallerpc())
    56  		}
    57  		panicunsafeslicelen1(getcallerpc())
    58  	}
    59  }
    60  
    61  // Keep this code in sync with cmd/compile/internal/walk/builtin.go:walkUnsafeSlice
    62  func unsafeslice64(et *abi.Type, ptr unsafe.Pointer, len64 int64) {
    63  	len := int(len64)
    64  	if int64(len) != len64 {
    65  		panicunsafeslicelen1(getcallerpc())
    66  	}
    67  	unsafeslice(et, ptr, len)
    68  }
    69  
    70  func unsafeslicecheckptr(et *abi.Type, ptr unsafe.Pointer, len64 int64) {
    71  	unsafeslice64(et, ptr, len64)
    72  
    73  	// Check that underlying array doesn't straddle multiple heap objects.
    74  	// unsafeslice64 has already checked for overflow.
    75  	if stdptr.CheckptrStraddles(ptr, uintptr(len64)*et.Size_) {
    76  		assert.Throw("checkptr:", "unsafe.Slice", "result", "straddles", "multiple", "allocations")
    77  	}
    78  }
    79  
    80  //
    81  // unsafe.String
    82  //
    83  
    84  func panicunsafestringlen() {
    85  	assert.Panic("unsafe.String:", "len", "out", "of", "range")
    86  }
    87  
    88  func panicunsafestringnilptr() {
    89  	assert.Panic("unsafe.String:", "ptr", "is", "nil", "and", "len", "is", "not", "zero")
    90  }
    91  
    92  func unsafestring(ptr unsafe.Pointer, len int) {
    93  	if len < 0 {
    94  		panicunsafestringlen()
    95  	}
    96  
    97  	if uintptr(len) > -uintptr(ptr) {
    98  		if ptr == nil {
    99  			panicunsafestringnilptr()
   100  		}
   101  		panicunsafestringlen()
   102  	}
   103  }
   104  
   105  // Keep this code in sync with cmd/compile/internal/walk/builtin.go:walkUnsafeString
   106  func unsafestring64(ptr unsafe.Pointer, len64 int64) {
   107  	len := int(len64)
   108  	if int64(len) != len64 {
   109  		panicunsafestringlen()
   110  	}
   111  	unsafestring(ptr, len)
   112  }
   113  
   114  func unsafestringcheckptr(ptr unsafe.Pointer, len64 int64) {
   115  	unsafestring64(ptr, len64)
   116  
   117  	// Check that underlying array doesn't straddle multiple heap objects.
   118  	// unsafestring64 has already checked for overflow.
   119  	if stdptr.CheckptrStraddles(ptr, uintptr(len64)) {
   120  		assert.Throw("checkptr:", "unsafe.String", "result", "straddles", "multiple", "allocations")
   121  	}
   122  }