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 }