mem.odin 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695
  1. package mem
  2. import "base:runtime"
  3. import "base:intrinsics"
  4. /*
  5. The size, in bytes, of a single byte.
  6. This constant is equal to the value of `1`.
  7. */
  8. Byte :: runtime.Byte
  9. /*
  10. The size, in bytes, of one kilobyte.
  11. This constant is equal to the amount of bytes in one kilobyte (also known as
  12. kibibyte), which is equal to 1024 bytes.
  13. */
  14. Kilobyte :: runtime.Kilobyte
  15. /*
  16. The size, in bytes, of one megabyte.
  17. This constant is equal to the amount of bytes in one megabyte (also known as
  18. mebibyte), which is equal to 1024 kilobyte.
  19. */
  20. Megabyte :: runtime.Megabyte
  21. /*
  22. The size, in bytes, of one gigabyte.
  23. This constant is equal to the amount of bytes in one gigabyte (also known as
  24. gibiibyte), which is equal to 1024 megabytes.
  25. */
  26. Gigabyte :: runtime.Gigabyte
  27. /*
  28. The size, in bytes, of one terabyte.
  29. This constant is equal to the amount of bytes in one terabyte (also known as
  30. tebiibyte), which is equal to 1024 gigabytes.
  31. */
  32. Terabyte :: runtime.Terabyte
  33. /*
  34. The size, in bytes, of one petabyte.
  35. This constant is equal to the amount of bytes in one petabyte (also known as
  36. pebiibyte), which is equal to 1024 terabytes.
  37. */
  38. Petabyte :: runtime.Petabyte
  39. /*
  40. The size, in bytes, of one exabyte.
  41. This constant is equal to the amount of bytes in one exabyte (also known as
  42. exbibyte), which is equal to 1024 petabytes.
  43. */
  44. Exabyte :: runtime.Exabyte
  45. /*
  46. Set each byte of a memory range to a specific value.
  47. This procedure copies value specified by the `value` parameter into each of the
  48. `len` bytes of a memory range, located at address `data`.
  49. This procedure returns the pointer to `data`.
  50. */
  51. set :: proc "contextless" (data: rawptr, value: byte, len: int) -> rawptr {
  52. return runtime.memset(data, i32(value), len)
  53. }
  54. /*
  55. Set each byte of a memory range to zero.
  56. This procedure copies the value `0` into the `len` bytes of a memory range,
  57. starting at address `data`.
  58. This procedure returns the pointer to `data`.
  59. */
  60. zero :: proc "contextless" (data: rawptr, len: int) -> rawptr {
  61. intrinsics.mem_zero(data, len)
  62. return data
  63. }
  64. /*
  65. Set each byte of a memory range to zero.
  66. This procedure copies the value `0` into the `len` bytes of a memory range,
  67. starting at address `data`.
  68. This procedure returns the pointer to `data`.
  69. Unlike the `zero()` procedure, which can be optimized away or reordered by the
  70. compiler under certain circumstances, `zero_explicit()` procedure can not be
  71. optimized away or reordered with other memory access operations, and the
  72. compiler assumes volatile semantics of the memory.
  73. */
  74. zero_explicit :: proc "contextless" (data: rawptr, len: int) -> rawptr {
  75. // This routine tries to avoid the compiler optimizing away the call,
  76. // so that it is always executed. It is intended to provide
  77. // equivalent semantics to those provided by the C11 Annex K 3.7.4.1
  78. // memset_s call.
  79. intrinsics.mem_zero_volatile(data, len) // Use the volatile mem_zero
  80. intrinsics.atomic_thread_fence(.Seq_Cst) // Prevent reordering
  81. return data
  82. }
  83. /*
  84. Zero-fill the memory of an object.
  85. This procedure sets each byte of the object pointed to by the pointer `item`
  86. to zero, and returns the pointer to `item`.
  87. */
  88. zero_item :: proc "contextless" (item: $P/^$T) -> P {
  89. intrinsics.mem_zero(item, size_of(T))
  90. return item
  91. }
  92. /*
  93. Zero-fill the memory of the slice.
  94. This procedure sets each byte of the slice pointed to by the slice `data`
  95. to zero, and returns the slice `data`.
  96. */
  97. zero_slice :: proc "contextless" (data: $T/[]$E) -> T {
  98. zero(raw_data(data), size_of(E)*len(data))
  99. return data
  100. }
  101. /*
  102. Copy bytes from one memory range to another.
  103. This procedure copies `len` bytes of data, from the memory range pointed to by
  104. the `src` pointer into the memory range pointed to by the `dst` pointer, and
  105. returns the `dst` pointer.
  106. */
  107. copy :: proc "contextless" (dst, src: rawptr, len: int) -> rawptr {
  108. intrinsics.mem_copy(dst, src, len)
  109. return dst
  110. }
  111. /*
  112. Copy bytes between two non-overlapping memory ranges.
  113. This procedure copies `len` bytes of data, from the memory range pointed to by
  114. the `src` pointer into the memory range pointed to by the `dst` pointer, and
  115. returns the `dst` pointer.
  116. This is a slightly more optimized version of the `copy` procedure that requires
  117. that memory ranges specified by the parameters to this procedure are not
  118. overlapping. If the memory ranges specified by `dst` and `src` pointers overlap,
  119. the behavior of this function may be unpredictable.
  120. */
  121. copy_non_overlapping :: proc "contextless" (dst, src: rawptr, len: int) -> rawptr {
  122. intrinsics.mem_copy_non_overlapping(dst, src, len)
  123. return dst
  124. }
  125. /*
  126. Compare two memory ranges defined by slices.
  127. This procedure performs a byte-by-byte comparison between memory ranges
  128. specified by slices `a` and `b`, and returns a value, specifying their relative
  129. ordering.
  130. If the return value is:
  131. - Equal to `-1`, then `a` is "smaller" than `b`.
  132. - Equal to `+1`, then `a` is "bigger" than `b`.
  133. - Equal to `0`, then `a` and `b` are equal.
  134. The comparison is performed as follows:
  135. 1. Each byte, upto `min(len(a), len(b))` bytes is compared between `a` and `b`.
  136. - If the byte in slice `a` is smaller than a byte in slice `b`, then comparison
  137. stops and this procedure returns `-1`.
  138. - If the byte in slice `a` is bigger than a byte in slice `b`, then comparison
  139. stops and this procedure returns `+1`.
  140. - Otherwise the comparison continues until `min(len(a), len(b))` are compared.
  141. 2. If all the bytes in the range are equal, then the lengths of the slices are
  142. compared.
  143. - If the length of slice `a` is smaller than the length of slice `b`, then `-1` is returned.
  144. - If the length of slice `b` is smaller than the length of slice `b`, then `+1` is returned.
  145. - Otherwise `0` is returned.
  146. */
  147. @(require_results)
  148. compare :: proc "contextless" (a, b: []byte) -> int {
  149. res := compare_byte_ptrs(raw_data(a), raw_data(b), min(len(a), len(b)))
  150. if res == 0 && len(a) != len(b) {
  151. return len(a) <= len(b) ? -1 : +1
  152. } else if len(a) == 0 && len(b) == 0 {
  153. return 0
  154. }
  155. return res
  156. }
  157. /*
  158. Compare two memory ranges defined by byte pointers.
  159. This procedure performs a byte-by-byte comparison between memory ranges of size
  160. `n` located at addresses `a` and `b`, and returns a value, specifying their relative
  161. ordering.
  162. If the return value is:
  163. - Equal to `-1`, then `a` is "smaller" than `b`.
  164. - Equal to `+1`, then `a` is "bigger" than `b`.
  165. - Equal to `0`, then `a` and `b` are equal.
  166. The comparison is performed as follows:
  167. 1. Each byte, upto `n` bytes is compared between `a` and `b`.
  168. - If the byte in `a` is smaller than a byte in `b`, then comparison stops
  169. and this procedure returns `-1`.
  170. - If the byte in `a` is bigger than a byte in `b`, then comparison stops
  171. and this procedure returns `+1`.
  172. - Otherwise the comparison continues until `n` bytes are compared.
  173. 2. If all the bytes in the range are equal, this procedure returns `0`.
  174. */
  175. @(require_results)
  176. compare_byte_ptrs :: proc "contextless" (a, b: ^byte, n: int) -> int #no_bounds_check {
  177. return runtime.memory_compare(a, b, n)
  178. }
  179. /*
  180. Compare two memory ranges defined by pointers.
  181. This procedure performs a byte-by-byte comparison between memory ranges of size
  182. `n` located at addresses `a` and `b`, and returns a value, specifying their relative
  183. ordering.
  184. If the return value is:
  185. - Equal to `-1`, then `a` is "smaller" than `b`.
  186. - Equal to `+1`, then `a` is "bigger" than `b`.
  187. - Equal to `0`, then `a` and `b` are equal.
  188. The comparison is performed as follows:
  189. 1. Each byte, upto `n` bytes is compared between `a` and `b`.
  190. - If the byte in `a` is smaller than a byte in `b`, then comparison stops
  191. and this procedure returns `-1`.
  192. - If the byte in `a` is bigger than a byte in `b`, then comparison stops
  193. and this procedure returns `+1`.
  194. - Otherwise the comparison continues until `n` bytes are compared.
  195. 2. If all the bytes in the range are equal, this procedure returns `0`.
  196. */
  197. @(require_results)
  198. compare_ptrs :: proc "contextless" (a, b: rawptr, n: int) -> int {
  199. return compare_byte_ptrs((^byte)(a), (^byte)(b), n)
  200. }
  201. /*
  202. Check whether two objects are equal on binary level.
  203. This procedure checks whether the memory ranges occupied by objects `a` and
  204. `b` are equal. See `compare_byte_ptrs()` for how this comparison is done.
  205. */
  206. @(require_results)
  207. simple_equal :: proc "contextless" (a, b: $T) -> bool where intrinsics.type_is_simple_compare(T) {
  208. a, b := a, b
  209. return compare_byte_ptrs((^byte)(&a), (^byte)(&b), size_of(T)) == 0
  210. }
  211. /*
  212. Check if the memory range defined by a slice is zero-filled.
  213. This procedure checks whether every byte, pointed to by the slice, specified
  214. by the parameter `data`, is zero. If all bytes of the slice are zero, this
  215. procedure returns `true`. Otherwise this procedure returns `false`.
  216. */
  217. @(require_results)
  218. check_zero :: proc(data: []byte) -> bool {
  219. return check_zero_ptr(raw_data(data), len(data))
  220. }
  221. /*
  222. Check if the memory range defined defined by a pointer is zero-filled.
  223. This procedure checks whether each of the `len` bytes, starting at address
  224. `ptr` is zero. If all bytes of this range are zero, this procedure returns
  225. `true`. Otherwise this procedure returns `false`.
  226. */
  227. @(require_results)
  228. check_zero_ptr :: proc(ptr: rawptr, len: int) -> bool {
  229. switch {
  230. case len <= 0:
  231. return true
  232. case ptr == nil:
  233. return true
  234. }
  235. switch len {
  236. case 1: return (^u8)(ptr)^ == 0
  237. case 2: return intrinsics.unaligned_load((^u16)(ptr)) == 0
  238. case 4: return intrinsics.unaligned_load((^u32)(ptr)) == 0
  239. case 8: return intrinsics.unaligned_load((^u64)(ptr)) == 0
  240. }
  241. start := uintptr(ptr)
  242. start_aligned := align_forward_uintptr(start, align_of(uintptr))
  243. end := start + uintptr(len)
  244. end_aligned := align_backward_uintptr(end, align_of(uintptr))
  245. for b in start..<start_aligned {
  246. if (^byte)(b)^ != 0 {
  247. return false
  248. }
  249. }
  250. for b := start_aligned; b < end_aligned; b += size_of(uintptr) {
  251. if (^uintptr)(b)^ != 0 {
  252. return false
  253. }
  254. }
  255. for b in end_aligned..<end {
  256. if (^byte)(b)^ != 0 {
  257. return false
  258. }
  259. }
  260. return true
  261. }
  262. /*
  263. Offset a given pointer by a given amount.
  264. This procedure offsets the pointer `ptr` to an object of type `T`, by the amount
  265. of bytes specified by `offset*size_of(T)`, and returns the pointer `ptr`.
  266. **Note**: Prefer to use multipointer types, if possible.
  267. */
  268. ptr_offset :: intrinsics.ptr_offset
  269. /*
  270. Offset a given pointer by a given amount backwards.
  271. This procedure offsets the pointer `ptr` to an object of type `T`, by the amount
  272. of bytes specified by `offset*size_of(T)` in the negative direction, and
  273. returns the pointer `ptr`.
  274. */
  275. ptr_sub :: intrinsics.ptr_sub
  276. /*
  277. Construct a slice from pointer and length.
  278. This procedure creates a slice, that points to `len` amount of objects located
  279. at an address, specified by `ptr`.
  280. */
  281. @(require_results)
  282. slice_ptr :: proc "contextless" (ptr: ^$T, len: int) -> []T {
  283. return ([^]T)(ptr)[:len]
  284. }
  285. /*
  286. Construct a byte slice from raw pointer and length.
  287. This procedure creates a byte slice, that points to `len` amount of bytes
  288. located at an address specified by `data`.
  289. */
  290. @(require_results)
  291. byte_slice :: #force_inline proc "contextless" (data: rawptr, #any_int len: int) -> []byte {
  292. return ([^]u8)(data)[:max(len, 0)]
  293. }
  294. /*
  295. Create a byte slice from pointer and length.
  296. This procedure creates a byte slice, pointing to `len` objects, starting from
  297. the address specified by `ptr`.
  298. */
  299. @(require_results)
  300. ptr_to_bytes :: proc "contextless" (ptr: ^$T, len := 1) -> []byte {
  301. return transmute([]byte)Raw_Slice{ptr, len*size_of(T)}
  302. }
  303. /*
  304. Obtain the slice, pointing to the contents of `any`.
  305. This procedure returns the slice, pointing to the contents of the specified
  306. value of the `any` type.
  307. */
  308. @(require_results)
  309. any_to_bytes :: proc "contextless" (val: any) -> []byte {
  310. ti := type_info_of(val.id)
  311. size := ti != nil ? ti.size : 0
  312. return transmute([]byte)Raw_Slice{val.data, size}
  313. }
  314. /*
  315. Obtain a byte slice from any slice.
  316. This procedure returns a slice, that points to the same bytes as the slice,
  317. specified by `slice` and returns the resulting byte slice.
  318. */
  319. @(require_results)
  320. slice_to_bytes :: proc "contextless" (slice: $E/[]$T) -> []byte {
  321. s := transmute(Raw_Slice)slice
  322. s.len *= size_of(T)
  323. return transmute([]byte)s
  324. }
  325. /*
  326. Transmute slice to a different type.
  327. This procedure performs an operation similar to transmute, returning a slice of
  328. type `T` that points to the same bytes as the slice specified by `slice`
  329. parameter. Unlike plain transmute operation, this procedure adjusts the length
  330. of the resulting slice, such that the resulting slice points to the correct
  331. amount of objects to cover the memory region pointed to by `slice`.
  332. */
  333. @(require_results)
  334. slice_data_cast :: proc "contextless" ($T: typeid/[]$A, slice: $S/[]$B) -> T {
  335. when size_of(A) == 0 || size_of(B) == 0 {
  336. return nil
  337. } else {
  338. s := transmute(Raw_Slice)slice
  339. s.len = (len(slice) * size_of(B)) / size_of(A)
  340. return transmute(T)s
  341. }
  342. }
  343. /*
  344. Obtain data and length of a slice.
  345. This procedure returns the pointer to the start of the memory region pointed to
  346. by slice `slice` and the length of the slice.
  347. */
  348. @(require_results)
  349. slice_to_components :: proc "contextless" (slice: $E/[]$T) -> (data: ^T, len: int) {
  350. s := transmute(Raw_Slice)slice
  351. return (^T)(s.data), s.len
  352. }
  353. /*
  354. Create a dynamic array from slice.
  355. This procedure creates a dynamic array, using slice `backing` as the backing
  356. buffer for the dynamic array. The resulting dynamic array can not grow beyond
  357. the size of the specified slice.
  358. */
  359. @(require_results)
  360. buffer_from_slice :: proc "contextless" (backing: $T/[]$E) -> [dynamic]E {
  361. return transmute([dynamic]E)Raw_Dynamic_Array{
  362. data = raw_data(backing),
  363. len = 0,
  364. cap = len(backing),
  365. allocator = Allocator{
  366. procedure = nil_allocator_proc,
  367. data = nil,
  368. },
  369. }
  370. }
  371. /*
  372. Check whether a number is a power of two.
  373. This procedure checks whether a given pointer-sized unsigned integer contains
  374. a power-of-two value.
  375. */
  376. @(require_results)
  377. is_power_of_two :: proc "contextless" (x: uintptr) -> bool {
  378. if x <= 0 {
  379. return false
  380. }
  381. return (x & (x-1)) == 0
  382. }
  383. /*
  384. Check if a pointer is aligned.
  385. This procedure checks whether a pointer `x` is aligned to a boundary specified
  386. by `align`, and returns `true` if the pointer is aligned, and false otherwise.
  387. The specified alignment must be a power of 2.
  388. */
  389. is_aligned :: proc "contextless" (x: rawptr, align: int) -> bool {
  390. p := uintptr(x)
  391. return (p & (uintptr(align) - 1)) == 0
  392. }
  393. /*
  394. Align uintptr forward.
  395. This procedure returns the next address after `ptr`, that is located on the
  396. alignment boundary specified by `align`. If `ptr` is already aligned to `align`
  397. bytes, `ptr` is returned.
  398. The specified alignment must be a power of 2.
  399. */
  400. @(require_results)
  401. align_forward_uintptr :: proc(ptr, align: uintptr) -> uintptr {
  402. assert(is_power_of_two(align))
  403. return (ptr + align-1) & ~(align-1)
  404. }
  405. /*
  406. Align pointer forward.
  407. This procedure returns the next address after `ptr`, that is located on the
  408. alignment boundary specified by `align`. If `ptr` is already aligned to `align`
  409. bytes, `ptr` is returned.
  410. The specified alignment must be a power of 2.
  411. */
  412. @(require_results)
  413. align_forward :: proc(ptr: rawptr, align: uintptr) -> rawptr {
  414. return rawptr(align_forward_uintptr(uintptr(ptr), align))
  415. }
  416. /*
  417. Align int forward.
  418. This procedure returns the next address after `ptr`, that is located on the
  419. alignment boundary specified by `align`. If `ptr` is already aligned to `align`
  420. bytes, `ptr` is returned.
  421. The specified alignment must be a power of 2.
  422. */
  423. @(require_results)
  424. align_forward_int :: proc(ptr, align: int) -> int {
  425. return int(align_forward_uintptr(uintptr(ptr), uintptr(align)))
  426. }
  427. /*
  428. Align uint forward.
  429. This procedure returns the next address after `ptr`, that is located on the
  430. alignment boundary specified by `align`. If `ptr` is already aligned to `align`
  431. bytes, `ptr` is returned.
  432. The specified alignment must be a power of 2.
  433. */
  434. @(require_results)
  435. align_forward_uint :: proc(ptr, align: uint) -> uint {
  436. return uint(align_forward_uintptr(uintptr(ptr), uintptr(align)))
  437. }
  438. /*
  439. Align uintptr backwards.
  440. This procedure returns the previous address before `ptr`, that is located on the
  441. alignment boundary specified by `align`. If `ptr` is already aligned to `align`
  442. bytes, `ptr` is returned.
  443. The specified alignment must be a power of 2.
  444. */
  445. @(require_results)
  446. align_backward_uintptr :: proc(ptr, align: uintptr) -> uintptr {
  447. assert(is_power_of_two(align))
  448. return ptr & ~(align-1)
  449. }
  450. /*
  451. Align rawptr backwards.
  452. This procedure returns the previous address before `ptr`, that is located on the
  453. alignment boundary specified by `align`. If `ptr` is already aligned to `align`
  454. bytes, `ptr` is returned.
  455. The specified alignment must be a power of 2.
  456. */
  457. @(require_results)
  458. align_backward :: proc(ptr: rawptr, align: uintptr) -> rawptr {
  459. return rawptr(align_backward_uintptr(uintptr(ptr), align))
  460. }
  461. /*
  462. Align int backwards.
  463. This procedure returns the previous address before `ptr`, that is located on the
  464. alignment boundary specified by `align`. If `ptr` is already aligned to `align`
  465. bytes, `ptr` is returned.
  466. The specified alignment must be a power of 2.
  467. */
  468. @(require_results)
  469. align_backward_int :: proc(ptr, align: int) -> int {
  470. return int(align_backward_uintptr(uintptr(ptr), uintptr(align)))
  471. }
  472. /*
  473. Align uint backwards.
  474. This procedure returns the previous address before `ptr`, that is located on the
  475. alignment boundary specified by `align`. If `ptr` is already aligned to `align`
  476. bytes, `ptr` is returned.
  477. The specified alignment must be a power of 2.
  478. */
  479. @(require_results)
  480. align_backward_uint :: proc(ptr, align: uint) -> uint {
  481. return uint(align_backward_uintptr(uintptr(ptr), uintptr(align)))
  482. }
  483. /*
  484. Create a context with a given allocator.
  485. This procedure returns a copy of the current context with the allocator replaced
  486. by the allocator `a`.
  487. */
  488. @(require_results)
  489. context_from_allocator :: proc(a: Allocator) -> type_of(context) {
  490. context.allocator = a
  491. return context
  492. }
  493. /*
  494. Copy the value from a pointer into a value.
  495. This procedure copies the object of type `T` pointed to by the pointer `ptr`
  496. into a new stack-allocated value and returns that value.
  497. */
  498. @(require_results)
  499. reinterpret_copy :: proc "contextless" ($T: typeid, ptr: rawptr) -> (value: T) {
  500. copy(&value, ptr, size_of(T))
  501. return
  502. }
  503. /*
  504. Dynamic array with a fixed capacity buffer.
  505. This type represents dynamic arrays with a fixed-size backing buffer. Upon
  506. allocating memory beyond reaching the maximum capacity, allocations from fixed
  507. byte buffers return `nil` and no error.
  508. */
  509. Fixed_Byte_Buffer :: distinct [dynamic]byte
  510. /*
  511. Create a fixed byte buffer from a slice.
  512. */
  513. @(require_results)
  514. make_fixed_byte_buffer :: proc "contextless" (backing: []byte) -> Fixed_Byte_Buffer {
  515. s := transmute(Raw_Slice)backing
  516. d: Raw_Dynamic_Array
  517. d.data = s.data
  518. d.len = 0
  519. d.cap = s.len
  520. d.allocator = Allocator{
  521. procedure = nil_allocator_proc,
  522. data = nil,
  523. }
  524. return transmute(Fixed_Byte_Buffer)d
  525. }
  526. /*
  527. General-purpose align formula.
  528. This procedure is equivalent to `align_forward`, but it does not require the
  529. alignment to be a power of two.
  530. */
  531. @(require_results)
  532. align_formula :: proc "contextless" (size, align: int) -> int {
  533. result := size + align-1
  534. return result - result%align
  535. }
  536. /*
  537. Calculate the padding for header preceding aligned data.
  538. This procedure returns the padding, following the specified pointer `ptr` that
  539. will be able to fit in a header of the size `header_size`, immediately
  540. preceding the memory region, aligned on a boundary specified by `align`. See
  541. the following diagram for a visual representation.
  542. header size
  543. |<------>|
  544. +---+--------+------------- - - -
  545. | HEADER | DATA...
  546. +---+--------+------------- - - -
  547. ^ ^
  548. |<---------->|
  549. | padding |
  550. ptr aligned ptr
  551. The function takes in `ptr` and `header_size`, as well as the required
  552. alignment for `DATA`. The return value of the function is the padding between
  553. `ptr` and `aligned_ptr` that will be able to fit the header.
  554. */
  555. @(require_results)
  556. calc_padding_with_header :: proc "contextless" (ptr: uintptr, align: uintptr, header_size: int) -> int {
  557. p, a := ptr, align
  558. modulo := p & (a-1)
  559. padding := uintptr(0)
  560. if modulo != 0 {
  561. padding = a - modulo
  562. }
  563. needed_space := uintptr(header_size)
  564. if padding < needed_space {
  565. needed_space -= padding
  566. if needed_space & (a-1) > 0 {
  567. padding += align * (1+(needed_space/align))
  568. } else {
  569. padding += align * (needed_space/align)
  570. }
  571. }
  572. return int(padding)
  573. }
  574. @(require_results, deprecated="prefer 'slice.clone'")
  575. clone_slice :: proc(slice: $T/[]$E, allocator := context.allocator, loc := #caller_location) -> (new_slice: T) {
  576. new_slice, _ = make(T, len(slice), allocator, loc)
  577. runtime.copy(new_slice, slice)
  578. return new_slice
  579. }