helpers.odin 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  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 cast(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 cast(int) intrinsics.syscall(nr, cast(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 cast(int) intrinsics.syscall(nr,
  28. cast(uintptr) p1, cast(uintptr) p2)
  29. }
  30. @(private)
  31. syscall3 :: #force_inline proc "contextless" (nr: uintptr, p1: $T1, p2: $T2, p3: $T3) -> int
  32. where
  33. size_of(p1) <= size_of(uintptr) &&
  34. size_of(p2) <= size_of(uintptr) &&
  35. size_of(p3) <= size_of(uintptr)
  36. {
  37. return cast(int) intrinsics.syscall(nr,
  38. cast(uintptr) p1,
  39. cast(uintptr) p2,
  40. cast(uintptr) p3)
  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 cast(int) intrinsics.syscall(nr,
  51. cast(uintptr) p1,
  52. cast(uintptr) p2,
  53. cast(uintptr) p3,
  54. cast(uintptr) p4)
  55. }
  56. @(private)
  57. syscall5 :: #force_inline proc "contextless" (nr: uintptr, p1: $T1, p2: $T2, p3: $T3, p4: $T4, p5: $T5) -> int
  58. where
  59. size_of(p1) <= size_of(uintptr) &&
  60. size_of(p2) <= size_of(uintptr) &&
  61. size_of(p3) <= size_of(uintptr) &&
  62. size_of(p4) <= size_of(uintptr) &&
  63. size_of(p5) <= size_of(uintptr)
  64. {
  65. return cast(int) intrinsics.syscall(nr,
  66. cast(uintptr) p1,
  67. cast(uintptr) p2,
  68. cast(uintptr) p3,
  69. cast(uintptr) p4,
  70. cast(uintptr) p5)
  71. }
  72. @(private)
  73. syscall6 :: #force_inline proc "contextless" (nr: uintptr, p1: $T1, p2: $T2, p3: $T3, p4: $T4, p5: $T5, p6: $T6) -> int
  74. where
  75. size_of(p1) <= size_of(uintptr) &&
  76. size_of(p2) <= size_of(uintptr) &&
  77. size_of(p3) <= size_of(uintptr) &&
  78. size_of(p4) <= size_of(uintptr) &&
  79. size_of(p5) <= size_of(uintptr) &&
  80. size_of(p6) <= size_of(uintptr)
  81. {
  82. return cast(int) intrinsics.syscall(nr,
  83. cast(uintptr) p1,
  84. cast(uintptr) p2,
  85. cast(uintptr) p3,
  86. cast(uintptr) p4,
  87. cast(uintptr) p5,
  88. cast(uintptr) p6)
  89. }
  90. syscall :: proc {syscall0, syscall1, syscall2, syscall3, syscall4, syscall5, syscall6}
  91. // Note(bumbread): This should shrug off a few lines from every syscall.
  92. // Since not any type can be trivially casted to another type, we take two arguments:
  93. // the final type to cast to, and the type to transmute to before casting.
  94. // One transmute + one cast should allow us to get to any type we might want
  95. // to return from a syscall wrapper.
  96. @(private)
  97. errno_unwrap3 :: #force_inline proc "contextless" (ret: $P, $T: typeid, $U: typeid) -> (T, Errno)
  98. where
  99. intrinsics.type_is_ordered_numeric(P)
  100. {
  101. if ret < 0 {
  102. default_value: T
  103. return default_value, Errno(-ret)
  104. } else {
  105. return cast(T) transmute(U) ret, Errno(.NONE)
  106. }
  107. }
  108. @(private)
  109. errno_unwrap2 :: #force_inline proc "contextless" (ret: $P, $T: typeid) -> (T, Errno) {
  110. if ret < 0 {
  111. default_value: T
  112. return default_value, Errno(-ret)
  113. } else {
  114. return cast(T) ret, Errno(.NONE)
  115. }
  116. }
  117. @(private)
  118. errno_unwrap :: proc {errno_unwrap2, errno_unwrap3}
  119. // Note(flysand): 32-bit architectures sometimes take in a 64-bit argument in a
  120. // register pair. This function should help me avoid typing the same code a few times..
  121. when size_of(int) == 4 {
  122. // xxx64 system calls take some parameters as pairs of ulongs rather than a single pointer
  123. @(private)
  124. compat64_arg_pair :: #force_inline proc "contextless" (a: i64) -> (hi: uint, lo: uint) {
  125. no_sign := uint(a)
  126. hi = uint(no_sign >> 32)
  127. lo = uint(no_sign & 0xffff_ffff)
  128. return
  129. }
  130. } else {
  131. // ... and on 64-bit architectures it's just a long
  132. @(private)
  133. compat64_arg_pair :: #force_inline proc "contextless" (a: i64) -> (uint) {
  134. return uint(a)
  135. }
  136. }