bytevectors.scm 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050
  1. ;;; Bytevectors
  2. ;;; Copyright (C) 2024 Igalia, S.L.
  3. ;;;
  4. ;;; Licensed under the Apache License, Version 2.0 (the "License");
  5. ;;; you may not use this file except in compliance with the License.
  6. ;;; You may obtain a copy of the License at
  7. ;;;
  8. ;;; http://www.apache.org/licenses/LICENSE-2.0
  9. ;;;
  10. ;;; Unless required by applicable law or agreed to in writing, software
  11. ;;; distributed under the License is distributed on an "AS IS" BASIS,
  12. ;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. ;;; See the License for the specific language governing permissions and
  14. ;;; limitations under the License.
  15. ;;; Commentary:
  16. ;;;
  17. ;;; Bytevectors.
  18. ;;;
  19. ;;; Code:
  20. (library (hoot bytevectors)
  21. (export make-bytevector
  22. bytevector-length
  23. bytevector-u8-ref
  24. bytevector-u8-set!
  25. bytevector-s8-ref
  26. bytevector-s8-set!
  27. bytevector-u16-ref
  28. bytevector-u16-native-ref
  29. bytevector-u16-set!
  30. bytevector-u16-native-set!
  31. bytevector-s16-ref
  32. bytevector-s16-native-ref
  33. bytevector-s16-set!
  34. bytevector-s16-native-set!
  35. bytevector-u32-ref
  36. bytevector-u32-native-ref
  37. bytevector-u32-set!
  38. bytevector-u32-native-set!
  39. bytevector-s32-ref
  40. bytevector-s32-native-ref
  41. bytevector-s32-set!
  42. bytevector-s32-native-set!
  43. bytevector-u64-ref
  44. bytevector-u64-native-ref
  45. bytevector-u64-set!
  46. bytevector-u64-native-set!
  47. bytevector-s64-ref
  48. bytevector-s64-native-ref
  49. bytevector-s64-set!
  50. bytevector-s64-native-set!
  51. bytevector-uint-ref
  52. bytevector-sint-ref
  53. bytevector-uint-set!
  54. bytevector-sint-set!
  55. bytevector-ieee-single-ref
  56. bytevector-ieee-single-native-ref
  57. bytevector-ieee-single-set!
  58. bytevector-ieee-single-native-set!
  59. bytevector-ieee-double-ref
  60. bytevector-ieee-double-native-ref
  61. bytevector-ieee-double-set!
  62. bytevector-ieee-double-native-set!
  63. bytevector?
  64. bytevector
  65. bytevector-concatenate
  66. bytevector-concatenate-reverse
  67. bytevector-append
  68. bytevector-copy
  69. bytevector-copy!
  70. bytevector-slice
  71. endianness
  72. native-endianness)
  73. (import (rename (only (hoot primitives)
  74. %null? %car %cdr
  75. %bytevector-length %bytevector?
  76. %bytevector-u8-ref %bytevector-u8-set!
  77. %bytevector-s8-ref %bytevector-s8-set!
  78. %bytevector-u16-native-ref %bytevector-u16-native-set!
  79. %bytevector-s16-native-ref %bytevector-s16-native-set!
  80. %bytevector-u32-native-ref %bytevector-u32-native-set!
  81. %bytevector-s32-native-ref %bytevector-s32-native-set!
  82. %bytevector-u64-native-ref %bytevector-u64-native-set!
  83. %bytevector-s64-native-ref %bytevector-s64-native-set!
  84. %bytevector-ieee-single-native-ref
  85. %bytevector-ieee-single-native-set!
  86. %bytevector-ieee-double-native-ref
  87. %bytevector-ieee-double-native-set!
  88. guile:make-bytevector guile:bytevector-copy!)
  89. (%null? null?)
  90. (%car car)
  91. (%cdr cdr))
  92. (hoot cond-expand)
  93. (hoot errors)
  94. (hoot inline-wasm)
  95. (hoot match)
  96. (hoot numbers)
  97. (hoot syntax)
  98. (hoot syntax-objects)
  99. (hoot bitwise))
  100. (define (bytevector? x) (%bytevector? x))
  101. (define (bytevector-length bv) (%bytevector-length bv))
  102. (cond-expand
  103. (guile-vm
  104. (define make-bytevector guile:make-bytevector))
  105. (hoot
  106. (define* (make-bytevector len #:optional (init 0))
  107. (check-size len (1- (ash 1 29)) 'make-bytevector)
  108. (check-range init -128 255 'make-bytevector)
  109. (%inline-wasm
  110. '(func (param $len i32) (param $init i32)
  111. (result (ref eq))
  112. (struct.new
  113. $mutable-bytevector
  114. (i32.const 0)
  115. (array.new $raw-bytevector (local.get $init) (local.get $len))))
  116. len init))))
  117. (define (bytevector-u8-ref bv i) (%bytevector-u8-ref bv i))
  118. (define (bytevector-u8-set! bv i x) (%bytevector-u8-set! bv i x))
  119. (define (bytevector-s8-ref bv i) (%bytevector-s8-ref bv i))
  120. (define (bytevector-s8-set! bv i x) (%bytevector-s8-set! bv i x))
  121. (define (bytevector-u16-native-ref bv i) (%bytevector-u16-native-ref bv i))
  122. (define (bytevector-u16-native-set! bv i x) (%bytevector-u16-native-set! bv i x))
  123. (define (bytevector-s16-native-ref bv i) (%bytevector-s16-native-ref bv i))
  124. (define (bytevector-s16-native-set! bv i x) (%bytevector-s16-native-set! bv i x))
  125. (define (bytevector-u32-native-ref bv i) (%bytevector-u32-native-ref bv i))
  126. (define (bytevector-u32-native-set! bv i x) (%bytevector-u32-native-set! bv i x))
  127. (define (bytevector-s32-native-ref bv i) (%bytevector-s32-native-ref bv i))
  128. (define (bytevector-s32-native-set! bv i x) (%bytevector-s32-native-set! bv i x))
  129. (define (bytevector-u64-native-ref bv i) (%bytevector-u64-native-ref bv i))
  130. (define (bytevector-u64-native-set! bv i x) (%bytevector-u64-native-set! bv i x))
  131. (define (bytevector-s64-native-ref bv i) (%bytevector-s64-native-ref bv i))
  132. (define (bytevector-s64-native-set! bv i x) (%bytevector-s64-native-set! bv i x))
  133. (define (bytevector-ieee-single-native-ref bv i) (%bytevector-ieee-single-native-ref bv i))
  134. (define (bytevector-ieee-single-native-set! bv i x) (%bytevector-ieee-single-native-set! bv i x))
  135. (define (bytevector-ieee-double-native-ref bv i) (%bytevector-ieee-double-native-ref bv i))
  136. (define (bytevector-ieee-double-native-set! bv i x) (%bytevector-ieee-double-native-set! bv i x))
  137. (define-syntax endianness
  138. (lambda (x)
  139. (syntax-case x ()
  140. ((_ sym)
  141. (match (syntax->datum #'sym)
  142. ((or 'big 'little) #''sym)
  143. (_ (syntax-violation 'endianness "unsupported endianness" #'sym)))))))
  144. (define (native-endianness) (endianness little))
  145. (define (bytevector-u16-ref bv index endianness)
  146. (check-size index (- (bytevector-length bv) 2) 'bytevector-u16-ref)
  147. (match endianness
  148. ('little (bytevector-u16-native-ref bv index))
  149. ('big
  150. (%inline-wasm
  151. '(func (param $bv (ref $bytevector)) (param $idx i32) (result i64)
  152. (local $vu0 (ref $raw-bytevector))
  153. (local.set $vu0 (struct.get $bytevector $vals (local.get $bv)))
  154. (array.get_u $raw-bytevector
  155. (local.get $vu0)
  156. (i32.add (local.get $idx)
  157. (i32.const 1)))
  158. (i32.shl (array.get_u $raw-bytevector
  159. (local.get $vu0)
  160. (local.get $idx))
  161. (i32.const 8))
  162. (i32.or)
  163. (i64.extend_i32_u))
  164. bv index))))
  165. (define (bytevector-u16-set! bv index value endianness)
  166. (check-size index (- (bytevector-length bv) 2) 'bytevector-u16-set!)
  167. (check-size value (1- (ash 1 16)) 'bytevector-u16-set!)
  168. (match endianness
  169. ('little (bytevector-u16-native-set! bv index value))
  170. ('big
  171. (%inline-wasm
  172. '(func (param $bv (ref $bytevector)) (param $idx i32) (param $value i32)
  173. (local $vu0 (ref $raw-bytevector))
  174. (local.set $vu0 (struct.get $bytevector $vals (local.get $bv)))
  175. (array.set $raw-bytevector
  176. (local.get $vu0)
  177. (i32.add (local.get $idx)
  178. (i32.const 1))
  179. (local.get $value))
  180. (array.set $raw-bytevector
  181. (local.get $vu0)
  182. (local.get $idx)
  183. (i32.shr_u (local.get $value) (i32.const 8))))
  184. bv index value))))
  185. (define (bytevector-s16-ref bv index endianness)
  186. (check-size index (- (bytevector-length bv) 2) 'bytevector-s16-ref)
  187. (match endianness
  188. ('little (bytevector-s16-native-ref bv index))
  189. ('big
  190. (%inline-wasm
  191. '(func (param $bv (ref $bytevector)) (param $idx i32) (result i64)
  192. (local $vu0 (ref $raw-bytevector))
  193. (local.set $vu0 (struct.get $bytevector $vals (local.get $bv)))
  194. (array.get_u $raw-bytevector
  195. (local.get $vu0)
  196. (i32.add (local.get $idx)
  197. (i32.const 1)))
  198. (i32.shl (array.get_s $raw-bytevector
  199. (local.get $vu0)
  200. (local.get $idx))
  201. (i32.const 8))
  202. (i32.or)
  203. (i64.extend_i32_s))
  204. bv index))))
  205. (define (bytevector-s16-set! bv index value endianness)
  206. (check-size index (- (bytevector-length bv) 2) 'bytevector-s16-set!)
  207. (check-range value (ash -1 15) (1- (ash 1 15)) 'bytevector-s16-set!)
  208. (match endianness
  209. ('little (bytevector-u16-native-set! bv index value))
  210. ('big
  211. (%inline-wasm
  212. '(func (param $bv (ref $bytevector)) (param $idx i32) (param $value i32)
  213. (local $vu0 (ref $raw-bytevector))
  214. (local.set $vu0 (struct.get $bytevector $vals (local.get $bv)))
  215. (array.set $raw-bytevector
  216. (local.get $vu0)
  217. (i32.add (local.get $idx)
  218. (i32.const 1))
  219. (local.get $value))
  220. (array.set $raw-bytevector
  221. (local.get $vu0)
  222. (local.get $idx)
  223. (i32.shr_s (local.get $value) (i32.const 8))))
  224. bv index value))))
  225. (define (bytevector-u32-ref bv index endianness)
  226. (check-size index (- (bytevector-length bv) 4) 'bytevector-u32-ref)
  227. (match endianness
  228. ('little (bytevector-u32-native-ref bv index))
  229. ('big
  230. (%inline-wasm
  231. '(func (param $bv (ref $bytevector)) (param $idx i32) (result i64)
  232. (local $vu0 (ref $raw-bytevector))
  233. (local.set $vu0 (struct.get $bytevector $vals (local.get $bv)))
  234. (array.get_u $raw-bytevector
  235. (local.get $vu0)
  236. (i32.add (local.get $idx)
  237. (i32.const 3)))
  238. (i32.shl (array.get_u $raw-bytevector
  239. (local.get $vu0)
  240. (i32.add (local.get $idx)
  241. (i32.const 2)))
  242. (i32.const 8))
  243. (i32.or)
  244. (i32.shl (array.get_u $raw-bytevector
  245. (local.get $vu0)
  246. (i32.add (local.get $idx)
  247. (i32.const 1)))
  248. (i32.const 16))
  249. (i32.or)
  250. (i32.shl (array.get_u $raw-bytevector
  251. (local.get $vu0)
  252. (local.get $idx))
  253. (i32.const 24))
  254. (i32.or)
  255. (i64.extend_i32_u))
  256. bv index))))
  257. (define (bytevector-u32-set! bv index value endianness)
  258. (check-size index (- (bytevector-length bv) 4) 'bytevector-u32-set!)
  259. (check-size value (1- (ash 1 32)) 'bytevector-u32-set!)
  260. (match endianness
  261. ('little (bytevector-u32-native-set! bv index value))
  262. ('big
  263. (%inline-wasm
  264. '(func (param $bv (ref $bytevector)) (param $idx i32) (param $value i32)
  265. (local $vu0 (ref $raw-bytevector))
  266. (local.set $vu0 (struct.get $bytevector $vals (local.get $bv)))
  267. (array.set $raw-bytevector
  268. (local.get $vu0)
  269. (i32.add (local.get $idx)
  270. (i32.const 3))
  271. (local.get $value))
  272. (array.set $raw-bytevector
  273. (local.get $vu0)
  274. (i32.add (local.get $idx)
  275. (i32.const 2))
  276. (i32.shr_u (local.get $value) (i32.const 8)))
  277. (array.set $raw-bytevector
  278. (local.get $vu0)
  279. (i32.add (local.get $idx)
  280. (i32.const 1))
  281. (i32.shr_u (local.get $value) (i32.const 16)))
  282. (array.set $raw-bytevector
  283. (local.get $vu0)
  284. (local.get $idx)
  285. (i32.shr_u (local.get $value) (i32.const 24))))
  286. bv index value))))
  287. (define (bytevector-s32-ref bv index endianness)
  288. (check-size index (- (bytevector-length bv) 4) 'bytevector-s32-ref)
  289. (match endianness
  290. ('little (bytevector-s32-native-ref bv index))
  291. ('big
  292. (%inline-wasm
  293. '(func (param $bv (ref $bytevector)) (param $idx i32) (result i64)
  294. (local $vu0 (ref $raw-bytevector))
  295. (local.set $vu0 (struct.get $bytevector $vals (local.get $bv)))
  296. (array.get_u $raw-bytevector
  297. (local.get $vu0)
  298. (i32.add (local.get $idx)
  299. (i32.const 3)))
  300. (i32.shl (array.get_u $raw-bytevector
  301. (local.get $vu0)
  302. (i32.add (local.get $idx)
  303. (i32.const 2)))
  304. (i32.const 8))
  305. (i32.or)
  306. (i32.shl (array.get_u $raw-bytevector
  307. (local.get $vu0)
  308. (i32.add (local.get $idx)
  309. (i32.const 1)))
  310. (i32.const 16))
  311. (i32.or)
  312. (i32.shl (array.get_s $raw-bytevector
  313. (local.get $vu0)
  314. (local.get $idx))
  315. (i32.const 24))
  316. (i32.or)
  317. (i64.extend_i32_s))
  318. bv index))))
  319. (define (bytevector-s32-set! bv index value endianness)
  320. (check-size index (- (bytevector-length bv) 4) 'bytevector-s32-set!)
  321. (check-range value (ash -1 31) (1- (ash 1 31)) 'bytevector-s32-set!)
  322. (match endianness
  323. ('little (bytevector-s32-native-set! bv index value))
  324. ('big
  325. (%inline-wasm
  326. '(func (param $bv (ref $bytevector)) (param $idx i32) (param $value i32)
  327. (local $vu0 (ref $raw-bytevector))
  328. (local.set $vu0 (struct.get $bytevector $vals (local.get $bv)))
  329. (array.set $raw-bytevector
  330. (local.get $vu0)
  331. (i32.add (local.get $idx)
  332. (i32.const 3))
  333. (local.get $value))
  334. (array.set $raw-bytevector
  335. (local.get $vu0)
  336. (i32.add (local.get $idx)
  337. (i32.const 2))
  338. (i32.shr_u (local.get $value) (i32.const 8)))
  339. (array.set $raw-bytevector
  340. (local.get $vu0)
  341. (i32.add (local.get $idx)
  342. (i32.const 1))
  343. (i32.shr_u (local.get $value) (i32.const 16)))
  344. (array.set $raw-bytevector
  345. (local.get $vu0)
  346. (local.get $idx)
  347. (i32.shr_s (local.get $value) (i32.const 24))))
  348. bv index value))))
  349. (define (bytevector-u64-ref bv index endianness)
  350. (check-size index (- (bytevector-length bv) 8) 'bytevector-u64-ref)
  351. (match endianness
  352. ('little (bytevector-u64-native-ref bv index))
  353. ('big
  354. (%inline-wasm
  355. '(func (param $bv (ref $bytevector)) (param $idx i32) (result i64)
  356. (local $vu0 (ref $raw-bytevector))
  357. (local.set $vu0 (struct.get $bytevector $vals (local.get $bv)))
  358. (i64.extend_i32_u
  359. (array.get_u $raw-bytevector
  360. (local.get $vu0)
  361. (i32.add (local.get $idx)
  362. (i32.const 7))))
  363. (i64.shl (i64.extend_i32_u
  364. (array.get_u $raw-bytevector
  365. (local.get $vu0)
  366. (i32.add (local.get $idx)
  367. (i32.const 6))))
  368. (i64.const 8))
  369. (i64.or)
  370. (i64.shl (i64.extend_i32_u
  371. (array.get_u $raw-bytevector
  372. (local.get $vu0)
  373. (i32.add (local.get $idx)
  374. (i32.const 5))))
  375. (i64.const 16))
  376. (i64.or)
  377. (i64.shl (i64.extend_i32_u
  378. (array.get_u $raw-bytevector
  379. (local.get $vu0)
  380. (i32.add (local.get $idx)
  381. (i32.const 4))))
  382. (i64.const 24))
  383. (i64.or)
  384. (i64.shl (i64.extend_i32_u
  385. (array.get_u $raw-bytevector
  386. (local.get $vu0)
  387. (i32.add (local.get $idx)
  388. (i32.const 3))))
  389. (i64.const 32))
  390. (i64.or)
  391. (i64.shl (i64.extend_i32_u
  392. (array.get_u $raw-bytevector
  393. (local.get $vu0)
  394. (i32.add (local.get $idx)
  395. (i32.const 2))))
  396. (i64.const 40))
  397. (i64.or)
  398. (i64.shl (i64.extend_i32_u
  399. (array.get_u $raw-bytevector
  400. (local.get $vu0)
  401. (i32.add (local.get $idx)
  402. (i32.const 1))))
  403. (i64.const 48))
  404. (i64.or)
  405. (i64.shl (i64.extend_i32_u
  406. (array.get_u $raw-bytevector
  407. (local.get $vu0)
  408. (local.get $idx)))
  409. (i64.const 56))
  410. (i64.or))
  411. bv index))))
  412. (define (bytevector-u64-set! bv index value endianness)
  413. (check-size index (- (bytevector-length bv) 4) 'bytevector-u64-set!)
  414. (check-size value (1- (ash 1 64)) 'bytevector-u64-set!)
  415. (match endianness
  416. ('little (bytevector-u64-native-set! bv index value))
  417. ('big
  418. (%inline-wasm
  419. '(func (param $bv (ref $bytevector)) (param $idx i32) (param $value i64)
  420. (local $vu0 (ref $raw-bytevector))
  421. (local.set $vu0 (struct.get $bytevector $vals (local.get $bv)))
  422. (array.set $raw-bytevector
  423. (local.get $vu0)
  424. (i32.add (local.get $idx)
  425. (i32.const 7))
  426. (i32.wrap_i64 (local.get $value)))
  427. (array.set $raw-bytevector
  428. (local.get $vu0)
  429. (i32.add (local.get $idx)
  430. (i32.const 6))
  431. (i32.wrap_i64
  432. (i64.shr_u (local.get $value)
  433. (i64.const 8))))
  434. (array.set $raw-bytevector
  435. (local.get $vu0)
  436. (i32.add (local.get $idx)
  437. (i32.const 5))
  438. (i32.wrap_i64
  439. (i64.shr_u (local.get $value)
  440. (i64.const 16))))
  441. (array.set $raw-bytevector
  442. (local.get $vu0)
  443. (i32.add (local.get $idx)
  444. (i32.const 4))
  445. (i32.wrap_i64
  446. (i64.shr_u (local.get $value)
  447. (i64.const 24))))
  448. (array.set $raw-bytevector
  449. (local.get $vu0)
  450. (i32.add (local.get $idx)
  451. (i32.const 3))
  452. (i32.wrap_i64
  453. (i64.shr_u (local.get $value)
  454. (i64.const 32))))
  455. (array.set $raw-bytevector
  456. (local.get $vu0)
  457. (i32.add (local.get $idx)
  458. (i32.const 2))
  459. (i32.wrap_i64
  460. (i64.shr_u (local.get $value)
  461. (i64.const 40))))
  462. (array.set $raw-bytevector
  463. (local.get $vu0)
  464. (i32.add (local.get $idx)
  465. (i32.const 1))
  466. (i32.wrap_i64
  467. (i64.shr_u (local.get $value)
  468. (i64.const 48))))
  469. (array.set $raw-bytevector
  470. (local.get $vu0)
  471. (local.get $idx)
  472. (i32.wrap_i64
  473. (i64.shr_u (local.get $value)
  474. (i64.const 56)))))
  475. bv index value))))
  476. (define (bytevector-s64-ref bv index endianness)
  477. (check-size index (- (bytevector-length bv) 8) 'bytevector-s64-ref)
  478. (match endianness
  479. ('little (bytevector-s64-native-ref bv index))
  480. ('big
  481. (%inline-wasm
  482. '(func (param $bv (ref $bytevector)) (param $idx i32) (result i64)
  483. (local $vu0 (ref $raw-bytevector))
  484. (local.set $vu0 (struct.get $bytevector $vals (local.get $bv)))
  485. (i64.extend_i32_u
  486. (array.get_u $raw-bytevector
  487. (local.get $vu0)
  488. (i32.add (local.get $idx)
  489. (i32.const 7))))
  490. (i64.shl (i64.extend_i32_u
  491. (array.get_u $raw-bytevector
  492. (local.get $vu0)
  493. (i32.add (local.get $idx)
  494. (i32.const 6))))
  495. (i64.const 8))
  496. (i64.or)
  497. (i64.shl (i64.extend_i32_u
  498. (array.get_u $raw-bytevector
  499. (local.get $vu0)
  500. (i32.add (local.get $idx)
  501. (i32.const 5))))
  502. (i64.const 16))
  503. (i64.or)
  504. (i64.shl (i64.extend_i32_u
  505. (array.get_u $raw-bytevector
  506. (local.get $vu0)
  507. (i32.add (local.get $idx)
  508. (i32.const 4))))
  509. (i64.const 24))
  510. (i64.or)
  511. (i64.shl (i64.extend_i32_u
  512. (array.get_u $raw-bytevector
  513. (local.get $vu0)
  514. (i32.add (local.get $idx)
  515. (i32.const 3))))
  516. (i64.const 32))
  517. (i64.or)
  518. (i64.shl (i64.extend_i32_u
  519. (array.get_u $raw-bytevector
  520. (local.get $vu0)
  521. (i32.add (local.get $idx)
  522. (i32.const 2))))
  523. (i64.const 40))
  524. (i64.or)
  525. (i64.shl (i64.extend_i32_u
  526. (array.get_u $raw-bytevector
  527. (local.get $vu0)
  528. (i32.add (local.get $idx)
  529. (i32.const 1))))
  530. (i64.const 48))
  531. (i64.or)
  532. (i64.shl (i64.extend_i32_u
  533. (array.get_s $raw-bytevector
  534. (local.get $vu0)
  535. (local.get $idx)))
  536. (i64.const 56))
  537. (i64.or))
  538. bv index))))
  539. (define (bytevector-s64-set! bv index value endianness)
  540. (check-size index (- (bytevector-length bv) 4) 'bytevector-s64-set!)
  541. (check-range value (ash -1 63) (1- (ash 1 63)) 'bytevector-s64-set!)
  542. (match endianness
  543. ('little (bytevector-s64-native-set! bv index value))
  544. ('big
  545. (%inline-wasm
  546. '(func (param $bv (ref $bytevector)) (param $idx i32) (param $value i64)
  547. (local $vu0 (ref $raw-bytevector))
  548. (local.set $vu0 (struct.get $bytevector $vals (local.get $bv)))
  549. (array.set $raw-bytevector
  550. (local.get $vu0)
  551. (i32.add (local.get $idx)
  552. (i32.const 7))
  553. (i32.wrap_i64 (local.get $value)))
  554. (array.set $raw-bytevector
  555. (local.get $vu0)
  556. (i32.add (local.get $idx)
  557. (i32.const 6))
  558. (i32.wrap_i64
  559. (i64.shr_u (local.get $value)
  560. (i64.const 8))))
  561. (array.set $raw-bytevector
  562. (local.get $vu0)
  563. (i32.add (local.get $idx)
  564. (i32.const 5))
  565. (i32.wrap_i64
  566. (i64.shr_u (local.get $value)
  567. (i64.const 16))))
  568. (array.set $raw-bytevector
  569. (local.get $vu0)
  570. (i32.add (local.get $idx)
  571. (i32.const 4))
  572. (i32.wrap_i64
  573. (i64.shr_u (local.get $value)
  574. (i64.const 24))))
  575. (array.set $raw-bytevector
  576. (local.get $vu0)
  577. (i32.add (local.get $idx)
  578. (i32.const 3))
  579. (i32.wrap_i64
  580. (i64.shr_u (local.get $value)
  581. (i64.const 32))))
  582. (array.set $raw-bytevector
  583. (local.get $vu0)
  584. (i32.add (local.get $idx)
  585. (i32.const 2))
  586. (i32.wrap_i64
  587. (i64.shr_u (local.get $value)
  588. (i64.const 40))))
  589. (array.set $raw-bytevector
  590. (local.get $vu0)
  591. (i32.add (local.get $idx)
  592. (i32.const 1))
  593. (i32.wrap_i64
  594. (i64.shr_u (local.get $value)
  595. (i64.const 48))))
  596. (array.set $raw-bytevector
  597. (local.get $vu0)
  598. (local.get $idx)
  599. (i32.wrap_i64
  600. (i64.shr_s (local.get $value)
  601. (i64.const 56)))))
  602. bv index value))))
  603. (define (bytevector-uint-ref bv index endianness size)
  604. (check-size index (- (bytevector-length bv) size) 'bytevector-uint-ref)
  605. (match endianness
  606. ('little
  607. (case size
  608. ((1) (bytevector-u8-ref bv index))
  609. ((2) (bytevector-u16-native-ref bv index))
  610. ((4) (bytevector-u32-native-ref bv index))
  611. ((8) (bytevector-u64-native-ref bv index))
  612. (else
  613. (let lp ((i 0))
  614. (if (= i size)
  615. 0
  616. (logior (ash (bytevector-u8-ref bv (+ index i))
  617. (* i 8))
  618. (lp (1+ i))))))))
  619. ('big
  620. (case size
  621. ((1) (bytevector-u8-ref bv index))
  622. ((2) (bytevector-u16-ref bv index endianness))
  623. ((4) (bytevector-u32-ref bv index endianness))
  624. ((8) (bytevector-u64-ref bv index endianness))
  625. (else
  626. (let lp ((i 0))
  627. (if (= i size)
  628. 0
  629. (logior (ash (bytevector-u8-ref bv (+ index (- size 1 i)))
  630. (* i 8))
  631. (lp (1+ i))))))))))
  632. (define (bytevector-uint-set! bv index value endianness size)
  633. (check-size index (- (bytevector-length bv) size) 'bytevector-uint-set!)
  634. (check-size value (1- (ash 1 (* size 8))) 'bytevector-uint-set!)
  635. (match endianness
  636. ('little
  637. (case size
  638. ((1) (bytevector-u8-set! bv index value))
  639. ((2) (bytevector-u16-native-set! bv index value))
  640. ((4) (bytevector-u32-native-set! bv index value))
  641. ((8) (bytevector-u64-native-set! bv index value))
  642. (else
  643. (let lp ((i 0))
  644. (unless (= i size)
  645. (bytevector-u8-set! bv (+ index i) (logand #xff (ash value (- (* i 8)))))
  646. (lp (1+ i)))))))
  647. ('big
  648. (case size
  649. ((1) (bytevector-u8-set! bv index value))
  650. ((2) (bytevector-u16-set! bv index endianness value))
  651. ((4) (bytevector-u32-set! bv index endianness value))
  652. ((8) (bytevector-u64-set! bv index endianness value))
  653. (else
  654. (let lp ((i 0))
  655. (unless (= i size)
  656. (bytevector-u8-set! bv (+ index (- size 1 i))
  657. (logand #xff (ash value (- (* i 8)))))
  658. (lp (1+ i)))))))))
  659. (define (bytevector-sint-ref bv index endianness size)
  660. (check-size index (- (bytevector-length bv) size) 'bytevector-sint-ref)
  661. (match endianness
  662. ('little
  663. (case size
  664. ((1) (bytevector-s8-ref bv index))
  665. ((2) (bytevector-s16-native-ref bv index))
  666. ((4) (bytevector-s32-native-ref bv index))
  667. ((8) (bytevector-s64-native-ref bv index))
  668. (else
  669. (let lp ((i 0))
  670. (if (= i (1- size))
  671. (ash (bytevector-s8-ref bv (+ index i))
  672. (* i 8))
  673. (logior (ash (bytevector-u8-ref bv (+ index i))
  674. (* i 8))
  675. (lp (1+ i))))))))
  676. ('big
  677. (case size
  678. ((1) (bytevector-s8-ref bv index))
  679. ((2) (bytevector-s16-ref bv index endianness))
  680. ((4) (bytevector-s32-ref bv index endianness))
  681. ((8) (bytevector-s64-ref bv index endianness))
  682. (else
  683. (let ((k (1- size)))
  684. (let lp ((i 0))
  685. (if (= i k)
  686. (ash (bytevector-s8-ref bv (+ index (- k i)))
  687. (* i 8))
  688. (logior (ash (bytevector-u8-ref bv (+ index (- k i)))
  689. (* i 8))
  690. (lp (1+ i)))))))))))
  691. (define (bytevector-sint-set! bv index value endianness size)
  692. (check-size index (- (bytevector-length bv) size) 'bytevector-sint-set!)
  693. (check-range value (ash -1 (1- (* size 8)))
  694. (1- (ash 1 (1- (* size 8))))
  695. 'bytevector-sint-set!)
  696. (match endianness
  697. ('little
  698. (case size
  699. ((1) (bytevector-u8-set! bv index value))
  700. ((2) (bytevector-u16-native-set! bv index value))
  701. ((4) (bytevector-u32-native-set! bv index value))
  702. ((8) (bytevector-u64-native-set! bv index value))
  703. (else
  704. (let lp ((i 0))
  705. (cond
  706. ((= i (1- size))
  707. (bytevector-s8-set! bv (+ index i) (ash value (- (* i 8)))))
  708. (else
  709. (bytevector-u8-set! bv (+ index i) (logand #xff (ash value (- (* i 8)))))
  710. (lp (1+ i))))))))
  711. ('big
  712. (case size
  713. ((1) (bytevector-u8-set! bv index value))
  714. ((2) (bytevector-u16-set! bv index endianness value))
  715. ((4) (bytevector-u32-set! bv index endianness value))
  716. ((8) (bytevector-u64-set! bv index endianness value))
  717. (else
  718. (let ((k (1- size)))
  719. (let lp ((i 0))
  720. (cond
  721. ((= i k)
  722. (bytevector-s8-set! bv (+ index (- k i))
  723. (ash value (- (* i 8)))))
  724. (else
  725. (bytevector-u8-set! bv (+ index (- k i))
  726. (logand #xff (ash value (- (* i 8)))))
  727. (lp (1+ i)))))))))))
  728. (define (bytevector-ieee-single-ref bv index endianness)
  729. (check-size index (- (bytevector-length bv) 4) 'bytevector-ieee-single-ref)
  730. (match endianness
  731. ('little (bytevector-ieee-single-native-ref bv index))
  732. ('big
  733. (%inline-wasm
  734. '(func (param $bv (ref $bytevector)) (param $idx i32) (result f64)
  735. (local $vu0 (ref $raw-bytevector))
  736. (local.set $vu0 (struct.get $bytevector $vals (local.get $bv)))
  737. (array.get_u $raw-bytevector
  738. (local.get $vu0)
  739. (i32.add (local.get $idx)
  740. (i32.const 3)))
  741. (i32.shl (array.get_u $raw-bytevector
  742. (local.get $vu0)
  743. (i32.add (local.get $idx)
  744. (i32.const 2)))
  745. (i32.const 8))
  746. (i32.or)
  747. (i32.shl (array.get_u $raw-bytevector
  748. (local.get $vu0)
  749. (i32.add (local.get $idx)
  750. (i32.const 1)))
  751. (i32.const 16))
  752. (i32.or)
  753. (i32.shl (array.get_u $raw-bytevector
  754. (local.get $vu0)
  755. (local.get $idx))
  756. (i32.const 24))
  757. (i32.or)
  758. (f32.reinterpret_i32)
  759. (f64.promote_f32))
  760. bv index))))
  761. (define (bytevector-ieee-single-set! bv index value endianness)
  762. (check-size index (- (bytevector-length bv) 4) 'bytevector-ieee-single-set!)
  763. (match endianness
  764. ('little (bytevector-ieee-single-native-set! bv index value))
  765. ('big
  766. (%inline-wasm
  767. '(func (param $bv (ref $bytevector)) (param $idx i32) (param $value f32)
  768. (local $vu0 (ref $raw-bytevector))
  769. (local $i0 i32)
  770. (local.set $vu0 (struct.get $bytevector $vals (local.get $bv)))
  771. (local.set $i0 (i32.reinterpret_f32 (local.get $value)))
  772. (array.set $raw-bytevector
  773. (local.get $vu0)
  774. (i32.add (local.get $idx)
  775. (i32.const 3))
  776. (local.get $i0))
  777. (array.set $raw-bytevector
  778. (local.get $vu0)
  779. (i32.add (local.get $idx)
  780. (i32.const 2))
  781. (i32.shr_u (local.get $i0) (i32.const 8)))
  782. (array.set $raw-bytevector
  783. (local.get $vu0)
  784. (i32.add (local.get $idx)
  785. (i32.const 1))
  786. (i32.shr_u (local.get $i0) (i32.const 16)))
  787. (array.set $raw-bytevector
  788. (local.get $vu0)
  789. (local.get $idx)
  790. (i32.shr_u (local.get $i0) (i32.const 24))))
  791. bv index value))))
  792. (define (bytevector-ieee-double-ref bv index endianness)
  793. (check-size index (- (bytevector-length bv) 4) 'bytevector-ieee-double-ref)
  794. (match endianness
  795. ('little (bytevector-ieee-double-native-ref bv index))
  796. ('big
  797. (%inline-wasm
  798. '(func (param $bv (ref $bytevector)) (param $idx i32) (result f64)
  799. (local $vu0 (ref $raw-bytevector))
  800. (local.set $vu0 (struct.get $bytevector $vals (local.get $bv)))
  801. (i64.extend_i32_u
  802. (array.get_u $raw-bytevector
  803. (local.get $vu0)
  804. (i32.add (local.get $idx)
  805. (i32.const 7))))
  806. (i64.shl (i64.extend_i32_u
  807. (array.get_u $raw-bytevector
  808. (local.get $vu0)
  809. (i32.add (local.get $idx)
  810. (i32.const 6))))
  811. (i64.const 8))
  812. (i64.or)
  813. (i64.shl (i64.extend_i32_u
  814. (array.get_u $raw-bytevector
  815. (local.get $vu0)
  816. (i32.add (local.get $idx)
  817. (i32.const 5))))
  818. (i64.const 16))
  819. (i64.or)
  820. (i64.shl (i64.extend_i32_u
  821. (array.get_u $raw-bytevector
  822. (local.get $vu0)
  823. (i32.add (local.get $idx)
  824. (i32.const 4))))
  825. (i64.const 24))
  826. (i64.or)
  827. (i64.shl (i64.extend_i32_u
  828. (array.get_u $raw-bytevector
  829. (local.get $vu0)
  830. (i32.add (local.get $idx)
  831. (i32.const 3))))
  832. (i64.const 32))
  833. (i64.or)
  834. (i64.shl (i64.extend_i32_u
  835. (array.get_u $raw-bytevector
  836. (local.get $vu0)
  837. (i32.add (local.get $idx)
  838. (i32.const 2))))
  839. (i64.const 40))
  840. (i64.or)
  841. (i64.shl (i64.extend_i32_u
  842. (array.get_u $raw-bytevector
  843. (local.get $vu0)
  844. (i32.add (local.get $idx)
  845. (i32.const 1))))
  846. (i64.const 48))
  847. (i64.or)
  848. (i64.shl (i64.extend_i32_u
  849. (array.get_u $raw-bytevector
  850. (local.get $vu0)
  851. (local.get $idx)))
  852. (i64.const 56))
  853. (i64.or)
  854. (f64.reinterpret_i64))
  855. bv index))))
  856. (define (bytevector-ieee-double-set! bv index value endianness)
  857. (check-size index (- (bytevector-length bv) 4) 'bytevector-ieee-double-set!)
  858. (match endianness
  859. ('little (bytevector-ieee-double-native-set! bv index value))
  860. ('big
  861. (%inline-wasm
  862. '(func (param $bv (ref $bytevector)) (param $idx i32) (param $value f64)
  863. (local $vu0 (ref $raw-bytevector))
  864. (local $j0 i64)
  865. (local.set $vu0 (struct.get $bytevector $vals (local.get $bv)))
  866. (local.set $j0 (i64.reinterpret_f64 (local.get $value)))
  867. (array.set $raw-bytevector
  868. (local.get $vu0)
  869. (i32.add (local.get $idx)
  870. (i32.const 7))
  871. (i32.wrap_i64 (local.get $j0)))
  872. (array.set $raw-bytevector
  873. (local.get $vu0)
  874. (i32.add (local.get $idx)
  875. (i32.const 6))
  876. (i32.wrap_i64
  877. (i64.shr_u (local.get $j0)
  878. (i64.const 8))))
  879. (array.set $raw-bytevector
  880. (local.get $vu0)
  881. (i32.add (local.get $idx)
  882. (i32.const 5))
  883. (i32.wrap_i64
  884. (i64.shr_u (local.get $j0)
  885. (i64.const 16))))
  886. (array.set $raw-bytevector
  887. (local.get $vu0)
  888. (i32.add (local.get $idx)
  889. (i32.const 4))
  890. (i32.wrap_i64
  891. (i64.shr_u (local.get $j0)
  892. (i64.const 24))))
  893. (array.set $raw-bytevector
  894. (local.get $vu0)
  895. (i32.add (local.get $idx)
  896. (i32.const 3))
  897. (i32.wrap_i64
  898. (i64.shr_u (local.get $j0)
  899. (i64.const 32))))
  900. (array.set $raw-bytevector
  901. (local.get $vu0)
  902. (i32.add (local.get $idx)
  903. (i32.const 2))
  904. (i32.wrap_i64
  905. (i64.shr_u (local.get $j0)
  906. (i64.const 40))))
  907. (array.set $raw-bytevector
  908. (local.get $vu0)
  909. (i32.add (local.get $idx)
  910. (i32.const 1))
  911. (i32.wrap_i64
  912. (i64.shr_u (local.get $j0)
  913. (i64.const 48))))
  914. (array.set $raw-bytevector
  915. (local.get $vu0)
  916. (local.get $idx)
  917. (i32.wrap_i64
  918. (i64.shr_u (local.get $j0)
  919. (i64.const 56)))))
  920. bv index value))))
  921. (define (bytevector . inits)
  922. (define (length l)
  923. (let lp ((len 0) (l l))
  924. (if (null? l) len (lp (+ len 1) (cdr l)))))
  925. (let* ((len (length inits))
  926. (bv (make-bytevector len)))
  927. (let lp ((i 0) (inits inits))
  928. (when (< i len)
  929. (bytevector-u8-set! bv i (car inits))
  930. (lp (1+ i) (cdr inits))))
  931. bv))
  932. (define (bytevector-length* bv*)
  933. (let lp ((bv* bv*) (len 0))
  934. (match bv*
  935. (() len)
  936. ((bv . bv*) (lp bv* (+ len (bytevector-length bv)))))))
  937. (define (bytevector-concatenate bv*)
  938. (match bv*
  939. (() #vu8())
  940. ((bv) bv)
  941. (bv*
  942. (let* ((len (bytevector-length* bv*))
  943. (flattened (make-bytevector len 0)))
  944. (let lp ((bv* bv*) (cur 0))
  945. (match bv*
  946. (() flattened)
  947. ((bv . bv*)
  948. (bytevector-copy! flattened cur bv)
  949. (lp bv* (+ cur (bytevector-length bv))))))))))
  950. (define (bytevector-concatenate-reverse bv*)
  951. (match bv*
  952. (() #vu8())
  953. ((bv) bv)
  954. (bv*
  955. (let* ((len (bytevector-length* bv*))
  956. (flattened (make-bytevector len 0)))
  957. (let lp ((bv* bv*) (cur len))
  958. (match bv*
  959. (() flattened)
  960. ((bv . bv*)
  961. (let ((cur (- cur (bytevector-length bv))))
  962. (bytevector-copy! flattened cur bv)
  963. (lp bv* cur)))))))))
  964. (define (bytevector-append . args)
  965. (bytevector-concatenate args))
  966. (cond-expand
  967. (guile-vm
  968. (define* (bytevector-copy x #:optional (start 0) (end (bytevector-length x)))
  969. (let* ((len (- end start))
  970. (new (make-bytevector len)))
  971. (guile:bytevector-copy! x start new 0 len)
  972. new))
  973. (define* (bytevector-copy! to at from #:optional
  974. (start 0) (end (bytevector-length from)))
  975. (guile:bytevector-copy! from start to at (- end start))))
  976. (hoot
  977. (define* (bytevector-copy x #:optional (start 0) (end (bytevector-length x)))
  978. (check-type x bytevector? 'bytevector-copy)
  979. (check-range start 0 (bytevector-length x) 'bytevector-copy)
  980. (check-range end start (bytevector-length x) 'bytevector-copy)
  981. (%inline-wasm
  982. '(func (param $src (ref $bytevector)) (param $start i32) (param $end i32)
  983. (result (ref eq))
  984. (local $i0 i32)
  985. (local $vu0 (ref $raw-bytevector))
  986. (local.set $i0 (i32.sub (local.get $end) (local.get $start)))
  987. (local.set $vu0 (array.new_default $raw-bytevector (local.get $i0)))
  988. (array.copy $raw-bytevector $raw-bytevector
  989. (local.get $vu0) (i32.const 0)
  990. (struct.get $bytevector $vals (local.get $src))
  991. (local.get $start) (local.get $i0))
  992. (struct.new $bytevector (i32.const 0) (local.get $vu0)))
  993. x start end))
  994. (define* (bytevector-copy! to at from #:optional
  995. (start 0) (end (bytevector-length from)))
  996. ;; FIXME: check that `to` is mutable
  997. (check-type to bytevector? 'bytevector-copy!)
  998. (check-range at 0 (bytevector-length to) 'bytevector-copy!)
  999. (check-type from bytevector? 'bytevector-copy!)
  1000. (check-range start 0 (bytevector-length from) 'bytevector-copy!)
  1001. (check-range end start (bytevector-length from) 'bytevector-copy!)
  1002. (%inline-wasm
  1003. '(func (param $to (ref $mutable-bytevector)) (param $at i32)
  1004. (param $from (ref $bytevector)) (param $start i32) (param $end i32)
  1005. (array.copy $raw-bytevector $raw-bytevector
  1006. (struct.get $mutable-bytevector $vals (local.get $to))
  1007. (local.get $at)
  1008. (struct.get $bytevector $vals (local.get $from))
  1009. (local.get $start)
  1010. (i32.sub (local.get $end) (local.get $start))))
  1011. to at from start end))))
  1012. (define* (bytevector-slice bv offset #:optional
  1013. (size (- (bytevector-length bv) offset)))
  1014. (raise (make-unimplemented-error 'bytevector-slice))))