github.com/gotranspile/cxgo@v0.3.7/runtime/libc/memory.go (about)

     1  package libc
     2  
     3  import (
     4  	"unsafe"
     5  )
     6  
     7  var allocs syncMap[unsafe.Pointer, []byte]
     8  
     9  // makePad creates a slice with a given size, but adds padding before and after the slice.
    10  // It is required to make some unsafe C code work, e.g. indexing elements after the slice end.
    11  func makePad(sz int, pad int) []byte {
    12  	if sz <= 0 {
    13  		panic("size should be > 0")
    14  	}
    15  	if pad == 0 {
    16  		pad = int(unsafe.Sizeof(uintptr(0)))
    17  	}
    18  	p := make([]byte, sz+pad*2)
    19  	p = p[pad:]
    20  	p = p[:sz:sz]
    21  	return p
    22  }
    23  
    24  func malloc(sz int) []byte {
    25  	b := makePad(sz, 0)
    26  	p := unsafe.Pointer(&b[0])
    27  	allocs.Store(p, b)
    28  	return b
    29  }
    30  
    31  // Malloc allocates a region of memory.
    32  func Malloc(sz int) unsafe.Pointer {
    33  	b := malloc(sz)
    34  	return unsafe.Pointer(&b[0])
    35  }
    36  
    37  // Calloc allocates a region of memory for num elements of size sz.
    38  func Calloc(num, sz int) unsafe.Pointer {
    39  	if num == 0 {
    40  		return nil
    41  	}
    42  	if sz <= 0 {
    43  		panic("size should be > 0")
    44  	}
    45  	b := makePad(num*sz, sz)
    46  	p := unsafe.Pointer(&b[0])
    47  	allocs.Store(p, b)
    48  	return p
    49  }
    50  
    51  func withSize(p unsafe.Pointer) ([]byte, bool) {
    52  	return allocs.Load(p)
    53  }
    54  
    55  func Realloc(buf unsafe.Pointer, sz int) unsafe.Pointer {
    56  	if buf == nil {
    57  		return Malloc(sz)
    58  	}
    59  	p := malloc(sz)
    60  	src, ok := withSize(buf)
    61  	if !ok {
    62  		panic("realloc of a pointer not managed by cxgo")
    63  	}
    64  	copy(p, src)
    65  	Free(buf)
    66  	return unsafe.Pointer(&p[0])
    67  }
    68  
    69  // Free marks the memory as freed. May be a nop in Go.
    70  func Free(p unsafe.Pointer) {
    71  	allocs.Delete(p)
    72  }
    73  
    74  // ToPointer converts a uintptr to unsafe.Pointer.
    75  func ToPointer(p uintptr) unsafe.Pointer {
    76  	return unsafe.Pointer(p)
    77  }
    78  
    79  // ToUintptr converts a unsafe.Pointer to uintptr.
    80  func ToUintptr(p unsafe.Pointer) uintptr {
    81  	return uintptr(p)
    82  }
    83  
    84  // PointerDiff calculates (a - b).
    85  func PointerDiff(a, b unsafe.Pointer) int {
    86  	return int(uintptr(a) - uintptr(b))
    87  }
    88  
    89  // IndexUnsafePtr unsafely moves a pointer by i bytes. An offset may be negative.
    90  //
    91  // Deprecated: use unsafe.Add
    92  func IndexUnsafePtr(p unsafe.Pointer, i int) unsafe.Pointer {
    93  	return unsafe.Add(p, i)
    94  }
    95  
    96  // IndexBytePtr unsafely moves a byte pointer by i bytes. An offset may be negative.
    97  //
    98  // Deprecated: use unsafe.Add
    99  func IndexBytePtr(p *byte, i int) *byte {
   100  	return (*byte)(unsafe.Add(unsafe.Pointer(p), i))
   101  }
   102  
   103  // UnsafeBytesN makes a slice of a given size starting at ptr.
   104  //
   105  // Deprecated: use unsafe.Slice
   106  func UnsafeBytesN(ptr unsafe.Pointer, sz int) []byte {
   107  	return unsafe.Slice((*byte)(ptr), sz)
   108  }
   109  
   110  // BytesN makes a slice of a given size starting at ptr.
   111  // It accepts a *byte instead of unsafe pointer as UnsafeBytesN does, which allows to avoid unsafe import.
   112  //
   113  // Deprecated: use unsafe.Slice
   114  func BytesN(p *byte, sz int) []byte {
   115  	return unsafe.Slice(p, sz)
   116  }
   117  
   118  // UnsafeUint16N makes a uint16 slice of a given size starting at ptr.
   119  //
   120  // Deprecated: use unsafe.Slice
   121  func UnsafeUint16N(ptr unsafe.Pointer, sz int) []uint16 {
   122  	return unsafe.Slice((*WChar)(ptr), sz)
   123  }
   124  
   125  // Uint16N makes a uint16 slice of a given size starting at ptr.
   126  // It accepts a *uint16 instead of unsafe pointer as UnsafeUint16N does, which allows to avoid unsafe import.
   127  //
   128  // Deprecated: use unsafe.Slice
   129  func Uint16N(p *uint16, sz int) []uint16 {
   130  	return unsafe.Slice(p, sz)
   131  }
   132  
   133  // UnsafeUint32N makes a uint32 slice of a given size starting at ptr.
   134  //
   135  // Deprecated: use unsafe.Slice
   136  func UnsafeUint32N(ptr unsafe.Pointer, sz int) []uint32 {
   137  	return unsafe.Slice((*uint32)(ptr), sz)
   138  }
   139  
   140  // Uint32N makes a uint32 slice of a given size starting at ptr.
   141  // It accepts a *uint32 instead of unsafe pointer as UnsafeUint32N does, which allows to avoid unsafe import.
   142  //
   143  // Deprecated: use unsafe.Slice
   144  func Uint32N(p *uint32, sz int) []uint32 {
   145  	return unsafe.Slice(p, sz)
   146  }