helpers.odin 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. //+build linux
  2. //+no-instrumentation
  3. package linux
  4. import "base:intrinsics"
  5. // Note(flysand): In the case of syscall let's get rid of extra
  6. // casting. First of all, let these syscalls return int, because
  7. // we'll need to check for Errno anyway. Second of all
  8. // most parameters are going to be trivially-castable to
  9. // uintptr, so we'll have that.
  10. @(private)
  11. syscall0 :: #force_inline proc "contextless" (nr: uintptr) -> int {
  12. return int(intrinsics.syscall(nr))
  13. }
  14. @(private)
  15. syscall1 :: #force_inline proc "contextless" (nr: uintptr, p1: $T) -> int
  16. where
  17. size_of(p1) <= size_of(uintptr)
  18. {
  19. return int(intrinsics.syscall(nr, uintptr(p1)))
  20. }
  21. @(private)
  22. syscall2 :: #force_inline proc "contextless" (nr: uintptr,p1: $T1, p2: $T2) -> int
  23. where
  24. size_of(p1) <= size_of(uintptr),
  25. size_of(p2) <= size_of(uintptr)
  26. {
  27. return int(intrinsics.syscall(nr, uintptr(p1), uintptr(p2)))
  28. }
  29. @(private)
  30. syscall3 :: #force_inline proc "contextless" (nr: uintptr, p1: $T1, p2: $T2, p3: $T3) -> int
  31. where
  32. size_of(p1) <= size_of(uintptr),
  33. size_of(p2) <= size_of(uintptr),
  34. size_of(p3) <= size_of(uintptr)
  35. {
  36. return int(intrinsics.syscall(nr,
  37. uintptr(p1),
  38. uintptr(p2),
  39. uintptr(p3),
  40. ))
  41. }
  42. @(private)
  43. syscall4 :: #force_inline proc "contextless" (nr: uintptr, p1: $T1, p2: $T2, p3: $T3, p4: $T4) -> int
  44. where
  45. size_of(p1) <= size_of(uintptr),
  46. size_of(p2) <= size_of(uintptr),
  47. size_of(p3) <= size_of(uintptr),
  48. size_of(p4) <= size_of(uintptr)
  49. {
  50. return int(intrinsics.syscall(nr,
  51. uintptr(p1),
  52. uintptr(p2),
  53. uintptr(p3),
  54. uintptr(p4),
  55. ))
  56. }
  57. @(private)
  58. syscall5 :: #force_inline proc "contextless" (nr: uintptr, p1: $T1, p2: $T2, p3: $T3, p4: $T4, p5: $T5) -> int
  59. where
  60. size_of(p1) <= size_of(uintptr),
  61. size_of(p2) <= size_of(uintptr),
  62. size_of(p3) <= size_of(uintptr),
  63. size_of(p4) <= size_of(uintptr),
  64. size_of(p5) <= size_of(uintptr)
  65. {
  66. return int(intrinsics.syscall(nr,
  67. uintptr(p1),
  68. uintptr(p2),
  69. uintptr(p3),
  70. uintptr(p4),
  71. uintptr(p5),
  72. ))
  73. }
  74. @(private)
  75. syscall6 :: #force_inline proc "contextless" (nr: uintptr, p1: $T1, p2: $T2, p3: $T3, p4: $T4, p5: $T5, p6: $T6) -> int
  76. where
  77. size_of(p1) <= size_of(uintptr),
  78. size_of(p2) <= size_of(uintptr),
  79. size_of(p3) <= size_of(uintptr),
  80. size_of(p4) <= size_of(uintptr),
  81. size_of(p5) <= size_of(uintptr),
  82. size_of(p6) <= size_of(uintptr)
  83. {
  84. return int(intrinsics.syscall(nr,
  85. uintptr(p1),
  86. uintptr(p2),
  87. uintptr(p3),
  88. uintptr(p4),
  89. uintptr(p5),
  90. uintptr(p6),
  91. ))
  92. }
  93. syscall :: proc {syscall0, syscall1, syscall2, syscall3, syscall4, syscall5, syscall6}
  94. // Note(bumbread): This should shrug off a few lines from every syscall.
  95. // Since not any type can be trivially casted to another type, we take two arguments:
  96. // the final type to cast to, and the type to transmute to before casting.
  97. // One transmute + one cast should allow us to get to any type we might want
  98. // to return from a syscall wrapper.
  99. @(private)
  100. errno_unwrap3 :: #force_inline proc "contextless" (ret: $P, $T: typeid, $U: typeid) -> (T, Errno)
  101. where
  102. intrinsics.type_is_ordered_numeric(P)
  103. {
  104. if ret < 0 {
  105. default_value: T
  106. return default_value, Errno(-ret)
  107. } else {
  108. return T(transmute(U)ret), Errno(.NONE)
  109. }
  110. }
  111. @(private)
  112. errno_unwrap2 :: #force_inline proc "contextless" (ret: $P, $T: typeid) -> (T, Errno) {
  113. if ret < 0 {
  114. default_value: T
  115. return default_value, Errno(-ret)
  116. } else {
  117. return T(ret), Errno(.NONE)
  118. }
  119. }
  120. @(private)
  121. errno_unwrap :: proc {errno_unwrap2, errno_unwrap3}
  122. // Note(flysand): 32-bit architectures sometimes take in a 64-bit argument in a
  123. // register pair. This function should help me avoid typing the same code a few times..
  124. when size_of(int) == 4 {
  125. // xxx64 system calls take some parameters as pairs of ulongs rather than a single pointer
  126. @(private)
  127. compat64_arg_pair :: #force_inline proc "contextless" (a: i64) -> (hi: uint, lo: uint) {
  128. no_sign := uint(a)
  129. hi = uint(no_sign >> 32)
  130. lo = uint(no_sign & 0xffff_ffff)
  131. return
  132. }
  133. } else {
  134. // ... and on 64-bit architectures it's just a long
  135. @(private)
  136. compat64_arg_pair :: #force_inline proc "contextless" (a: i64) -> (uint) {
  137. return uint(a)
  138. }
  139. }