helpers.odin 4.1 KB

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