Compare commits

...

1354 Commits

Author SHA1 Message Date
gingerBill af9ae4897a Merge pull request #4290 from flysand7/pipe-has-data
[os2/process]: Implement `process_exec`, and `pipe_has_data`
2024-10-01 11:30:28 +01:00
gingerBill 9f813a6263 Merge pull request #4331 from olimpiu/patch-1
Fixed confusing (and incorrect) warning
2024-10-01 11:29:45 +01:00
olimpiu 5d57fe77be Fixed confusing (and incorrect) warning
Verbose errors *is* the new default
2024-09-30 20:46:03 -04:00
Laytan Laats ab54ad3a75 sys/posix: use '#max_field_align' 2024-09-30 16:39:14 +02:00
gingerBill 9919a0cacd Merge branch 'master' of https://github.com/odin-lang/Odin 2024-09-30 15:35:52 +01:00
gingerBill 91dece1656 Change struct alignment rules for #max_field_align 2024-09-30 15:35:47 +01:00
gingerBill 1e1904e9ab Merge pull request #4323 from laytan/bit-array-init
container/bit_array: add 'init' procedure
2024-09-30 15:00:45 +01:00
gingerBill d6f6099419 Merge pull request #4324 from laytan/va-list-stb-sprintf-raylib-fixe
va_list fixes for raylib & stb sprintf
2024-09-30 15:00:14 +01:00
gingerBill d712ea43eb Merge pull request #4325 from mtarik34b/document-container-of-proc
Add documentation to `runtime.container_of`
2024-09-30 15:00:03 +01:00
gingerBill 962af780ae Merge pull request #4328 from Yawning/fix/cshake-bytepad
core/crypto/_sha3: Fix edge case in cSHAKE bytepad
2024-09-30 13:56:31 +01:00
Yawning Angel cf7d705c1f core/crypto/_sha3: Fix edge case in cSHAKE bytepad
If the domain separator happens to be exactly the rate, we would
previously incorrectly add another rate-bytes of 0s.
2024-09-30 21:50:18 +09:00
gingerBill a7d7c92a53 #min_field_align & #max_field_align; deprecate #field_align in favour of #min_field_align 2024-09-30 13:05:28 +01:00
gingerBill 4b6410e225 ABI BREAKING for SysV: Change how multiple return values are handled to be separate like all other ABIs 2024-09-30 12:32:55 +01:00
gingerBill b173fa1b9a Fix LLVM 18 ABI for 128-bit integers (because LLVM broke things) 2024-09-30 11:45:24 +01:00
gingerBill 225ffdec36 Fix union comparison bug 2024-09-30 11:10:16 +01:00
Jeroen van Rijn 7f9cfd1579 Merge pull request #4327 from beaumccartney/fix-deferred-attrib-error-report
fix #4326
2024-09-30 08:01:36 +02:00
Beau McCartney e3eea1b9fa print proc types in same order as procs 2024-09-29 23:55:55 -06:00
Beau McCartney fe8325f0ad fix deferred procedure errors 2024-09-29 23:34:09 -06:00
Laytan 38fedf2631 Merge pull request #4304 from kawaii-Code/linear_search_reverse
Add linear_search_reverse and linear_search_reverse_proc
2024-09-29 21:18:49 +02:00
Nia 253edb51f7 Fix markup in linear_search and binary_search docs 2024-09-29 17:08:54 +03:00
mtarik34b 82aefd4203 Add documentation to runtime.container_of 2024-09-29 16:04:39 +02:00
Nia 3c80f15a7a Remove pointless #no_bounds_check 2024-09-29 15:51:30 +03:00
Laytan 085b725774 Merge pull request #4302 from Pariatech/enable_static_glfw_linux
Add static GLFW bindings for Linux
2024-09-29 13:55:36 +02:00
Gabriel Pariat 3039131a5f do recommendation 2024-09-29 07:46:01 -04:00
Laytan daa3bb9a3b Merge pull request #4322 from laytan/fix-errors-not-printed-after-parse-warnings
fix errors not being printed after parse warnings
2024-09-29 12:51:21 +02:00
Laytan Laats 152479052e va_list fixes for raylib & stb sprintf 2024-09-29 11:45:57 +02:00
gingerBill 90cb62c5ac Merge branch 'master' of https://github.com/odin-lang/Odin 2024-09-29 10:15:02 +01:00
gingerBill 4a616d97df Pass delta time instead of current time to odin.js step 2024-09-29 10:14:56 +01:00
Laytan Laats 642ecc363b fix errors not being printed after parse warnings
Fixes #4299
2024-09-29 11:04:37 +02:00
Laytan Laats bd45900257 container/bit_array: add 'init' procedure 2024-09-29 10:57:42 +02:00
Laytan Laats eccb548935 fix box2d World_Draw not taking a pointer 2024-09-29 10:50:31 +02:00
Laytan a82f26f4c0 Merge pull request #4320 from laytan/fix-wgpu-examples-after-js-move
fix wgpu examples after move of files in 95721fe
2024-09-29 10:46:13 +02:00
Laytan Laats eeaa9f048b fix wgpu examples after move of files in 95721fe 2024-09-29 10:39:28 +02:00
flysand7 ca9cfc7167 remove extra binary 2024-09-29 08:01:47 +11:00
flysand7 0e446e1d68 adjust docs 2024-09-29 07:54:29 +11:00
gingerBill 90d024fb70 Merge pull request #4310 from wrapperup/fix-vulkan-wrapper
`vendor:vulkan` Update header files (to 1.3.296) and fix code generation
2024-09-28 18:22:17 +01:00
flysand7 d830069e5c [os2/process]: Implement process_exec 2024-09-28 11:25:32 +11:00
flysand7 7deb28c810 [os2/process]: Unindent doc comments 2024-09-28 10:30:54 +11:00
wrapperup 2b5c2cab1f generate new vulkan files (1.3.296) 2024-09-26 18:20:00 -04:00
wrapperup 39c8749d8f fix mismatching type generation with newer vulkan headers 2024-09-26 18:16:38 -04:00
gingerBill 4f2915a9b5 Merge pull request #4307 from flysand7/ptrace-user-regs
Fix missing registers in User_Regs on AMD64
2024-09-26 16:41:28 +01:00
gingerBill d3bff23bce Merge pull request #4308 from karl-zylinski/fix-constant-array-conversion-crash
Fix for crash when emitting a comparison between a constant array and a non-constant value.
2024-09-26 16:40:43 +01:00
Karl Zylinski 007730bfbc Fix for crash when emitting a comparison between a constant array and a non-constant value. 2024-09-25 23:42:35 +02:00
flysand7 e54b1560ee Add missing registers in User_Regs on AMD64 2024-09-26 07:27:11 +11:00
flysand7 abd52529a6 Revert "Add missing registers in User_Regs on AMD64"
This reverts commit acfac3cf2d.
2024-09-26 07:26:01 +11:00
flysand7 acfac3cf2d Add missing registers in User_Regs on AMD64 2024-09-26 07:25:40 +11:00
flysand7 842f1ae304 Fix indentation issues 2024-09-26 07:13:00 +11:00
gingerBill 8371ef6681 Merge pull request #4279 from obiwan87/master
Fix compile errors
2024-09-25 17:32:30 +01:00
gingerBill 987faa3f18 Merge pull request #4280 from Feoramund/fix-4278
Forbid parsing more fields if no separator was found
2024-09-25 16:12:33 +01:00
gingerBill e397fb6a7f Merge pull request #4297 from flysand7/ini-section
[encoding/ini]: Add missing line terminator at the end of the section
2024-09-25 16:07:03 +01:00
Nia 3337d6b264 Add linear_search_reverse and linear_search_reverse_proc 2024-09-25 16:41:55 +03:00
Gabriel Pariat fdc56c4d9a adding binding for static for linux 2024-09-24 19:44:11 -04:00
Jeroen van Rijn 791b05b14f Merge pull request #2600 from Hyrtwol/icon-for-odin-exe
Icon for odin.exe
2024-09-24 17:03:38 +02:00
flysand7 45d26dc7f9 [encoding/ini]: Add missing line terminator at the end of the section 2024-09-24 18:57:42 +11:00
flysand7 dbad23385d [os2]: Implement pipe_has_data procedure 2024-09-24 08:12:21 +11:00
Antonino Simone Di Stefano e9e7863033 Merge branch 'odin-lang:master' into master 2024-09-22 23:32:22 +02:00
Antonino Simone Di Stefano 5bced00f5d Return Allocator_Error in map_entry_infos 2024-09-22 23:25:46 +02:00
Antonino Simone Di Stefano 357c8f6f34 Replace "." with "," in parameter list 2024-09-22 23:19:36 +02:00
Antonino Simone Di Stefano baf5a06fba Remove address operator, which lead to a type error 2024-09-22 23:16:59 +02:00
Antonino Simone Di Stefano 3d202da63f Add missing package qualifier to alloc 2024-09-22 23:15:48 +02:00
Antonino Simone Di Stefano 5a6f761535 Add missing package qualifier to Context 2024-09-22 23:15:36 +02:00
gingerBill f7d74ff3a8 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-09-22 19:29:15 +01:00
gingerBill 95721fe296 Add gamepad support 2024-09-22 19:29:05 +01:00
Jeroen van Rijn ba3d545c96 Merge pull request #4281 from c-cube/add-time-to-rfc3339
add a time-to-RFC3339 conversion function
2024-09-22 17:46:26 +02:00
gingerBill 66e83ef30d Add gamepad events 2024-09-22 16:24:46 +01:00
gingerBill 94288161e9 Add new js events 2024-09-22 15:52:04 +01:00
gingerBill 130318d003 Fix assert caused by typo 2024-09-22 14:19:31 +01:00
gingerBill 1ae57d8d20 Fix more JS stuff 2024-09-22 13:32:28 +01:00
gingerBill 26d00925cc Clean-up libc usage 2024-09-22 13:20:45 +01:00
gingerBill 634fa7aa30 Move vendor:wasm/js to core:sys/wasm/js 2024-09-22 13:13:34 +01:00
gingerBill 096258b5d5 Rename runtime.js to odin.js 2024-09-22 13:08:42 +01:00
gingerBill 6bdd572a30 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-09-22 13:04:29 +01:00
gingerBill c39b934e7f Remove unused imports 2024-09-22 13:04:23 +01:00
Simon Cruanes a1349d8776 fix vet warnings 2024-09-22 00:08:07 -04:00
Simon Cruanes 32e13f17ae Apply suggestions from code review
Co-authored-by: flysand7 <yyakut.ac@gmail.com>
2024-09-21 21:08:35 -04:00
Simon Cruanes d08b3d3b82 add tests for time.time_to_rfc3339 2024-09-21 00:48:39 -04:00
Simon Cruanes a89d22b291 add time.time_to_rfc3339, a printer to RFC3339 dates
this is the counterpart to the existing parsing function
`rfc3339_to_time_utc` and others. It prints the timestamp as a string,
allocated dynamically.
2024-09-21 00:47:21 -04:00
Feoramund 84700e09c9 Forbid parsing more fields if no separator was found
Fixes #4278
2024-09-20 19:02:00 -04:00
Antonino Simone Di Stefano 355f84d0cd Use package qualifier for type_info_base and Type_Info_map 2024-09-21 00:30:50 +02:00
Antonino Simone Di Stefano b33f6ba1b0 Fix type in parameter of atomic_compare_exchange_weak_explicit
desited -> desired
2024-09-21 00:30:36 +02:00
gingerBill c1264c2a79 Merge pull request #4275 from karl-zylinski/fix-file-tags-infinite-loop
Fix for infinite loop in core:odin file tags parser when a file uses \r
2024-09-20 14:36:52 +01:00
Karl Zylinski 9a8fb2fb27 Fix for infinite loop in core:odin file tags parser when your local copy uses \r 2024-09-20 15:12:35 +02:00
gingerBill 2c5be4e054 Use .shift() instead 2024-09-20 11:18:11 +01:00
gingerBill 02884207d5 Update wasm's runtime.js 2024-09-20 11:15:47 +01:00
gingerBill b116e8ff55 Fix 128-bit integer support for wasm targets 2024-09-20 01:29:39 +01:00
gingerBill a4dd489284 Add fmt tags 2024-09-19 17:12:47 +01:00
gingerBill 290561a39b Merge pull request #4270 from flysand7/heap-alloc-resize-fix
Fix resize OOB when copying old data that's bigger than new data
2024-09-19 12:57:18 +01:00
gingerBill a7fe647c8c Merge pull request #4269 from Feoramund/fix-4256
Specify integer-like only for some `atomic_*` intrinsics
2024-09-19 12:54:11 +01:00
gingerBill 327ca2ab71 Merge pull request #4261 from laytan/net-bound-endpoint
net: add `bound_endpoint` procedure
2024-09-19 12:53:42 +01:00
gingerBill 68960e7d0a Use #+ tags 2024-09-19 12:39:56 +01:00
gingerBill 6bbeb0a243 Merge pull request #4203 from karl-zylinski/file-tags-without-comments
Make tags use #+ syntax instead of //+
2024-09-19 12:36:43 +01:00
Laytan a52b1e0321 Merge pull request #4271 from Feoramund/forbid-defer-orbreak
Forbid labelled or-branch expressions within `defer`
2024-09-19 13:25:28 +02:00
gingerBill d560dad0d8 Add missing import that was accidentally deleted before commit 2024-09-19 12:09:30 +01:00
gingerBill 5441620b6c Merge branch 'master' of https://github.com/odin-lang/Odin 2024-09-19 12:06:36 +01:00
gingerBill 244907149a Move os stuff to OS specific files 2024-09-19 12:06:31 +01:00
flysand7 bec09d82df Fix vet errors 2024-09-19 21:07:08 +11:00
Feoramund acbf5c8d97 Forbid labelled or-branch expressions within defer 2024-09-19 05:59:37 -04:00
flysand7 e0bb07728d Fix resize OOB when copying old data that's bigger than new data 2024-09-19 20:55:52 +11:00
Laytan 0ca5e70c7d Merge pull request #4266 from greenya/os-get-current-directory-allocator-arg
[core/os] get_current_directory: Add allocator arg to targets where i…
2024-09-19 02:17:20 +02:00
Feoramund 9456c36684 Specify integer-like only for some atomic_* intrinsics
Fixes #4256
2024-09-18 17:18:48 -04:00
Yuriy Grynevych 80622bcb3a Merge branch 'odin-lang:master' into os-get-current-directory-allocator-arg 2024-09-19 00:13:19 +03:00
Yuriy Grynevych 18fd1fefc3 Update core/os/os_openbsd.odin
Co-authored-by: Laytan <laytanlaats@hotmail.com>
2024-09-19 00:11:17 +03:00
Yuriy Grynevych 568705069c Update core/os/os_netbsd.odin
Co-authored-by: Laytan <laytanlaats@hotmail.com>
2024-09-19 00:11:12 +03:00
Yuriy Grynevych cbf0471c72 Update core/os/os_linux.odin
Co-authored-by: Laytan <laytanlaats@hotmail.com>
2024-09-19 00:11:06 +03:00
Yuriy Grynevych 35f0dcbb92 Update core/os/os_freebsd.odin
Co-authored-by: Laytan <laytanlaats@hotmail.com>
2024-09-19 00:11:00 +03:00
Yuriy Grynevych 6e979a96a1 Update core/os/os_darwin.odin
Co-authored-by: Laytan <laytanlaats@hotmail.com>
2024-09-19 00:10:53 +03:00
Laytan Laats 7491b3c332 Fix #4265 2024-09-18 22:45:27 +02:00
Yuriy Grynevych 4ff836609c [core/os] get_current_directory: Add allocator arg to targets where its missing 2024-09-18 21:03:48 +03:00
gingerBill 8814170edf Merge branch 'master' of https://github.com/odin-lang/Odin 2024-09-18 00:13:44 +01:00
gingerBill e17dfcf7a2 Remove distinct from core:math/linalg/(glsl|hlsl) types 2024-09-18 00:13:34 +01:00
Laytan Laats 80cc2f5416 fix it more 2024-09-17 23:28:34 +02:00
Laytan Laats 9973e0255c fix error interrupt error check 2024-09-17 23:19:20 +02:00
Laytan 4dd3248507 Merge pull request #4262 from flysand7/ptrace-args
[sys/linux]: Fix the order of arguments for ptrace cont, singlestep and syscall
2024-09-17 23:15:52 +02:00
flysand7 833157ecc9 [sys/linux]: Fix the order of arguments for ptrace cont, singlestep and syscall 2024-09-18 07:52:22 +11:00
Laytan Laats 652557bfcd net: add bound_endpoint procedure 2024-09-17 22:22:19 +02:00
Karl Zylinski 29fedc1808 Changed some recently added //+ usages to #+ and also fixed some //+ usages in some code generators. 2024-09-17 19:39:48 +02:00
Karl Zylinski 093ade0504 Merge branch 'master' into file-tags-without-comments 2024-09-17 19:36:17 +02:00
Laytan Laats 6ef779cd5c add new macos releases to 'odin report' and sys/info 2024-09-17 17:47:26 +02:00
Jeroen van Rijn 9508a1f031 Merge pull request #4255 from avanspector/master
init ansi on a standalone testing exe
2024-09-17 17:15:41 +02:00
avanspector c794f853e9 init ansi on a standalone testing exe 2024-09-17 16:57:02 +02:00
Laytan Laats 0975820c48 fix wrong ulock timeout calculation, add version check for ios 2024-09-17 15:52:35 +02:00
gingerBill 0d33df15b4 Merge pull request #4208 from laytan/more-wasm-vendor-support
wasm: support more vendor libraries
2024-09-17 11:37:10 +01:00
gingerBill 4a3b4da73c Merge pull request #4253 from pkova/master
Fix core sync test deadlock on darwin
2024-09-17 11:35:18 +01:00
gingerBill 09588836e7 Add -vet-unused-procedures 2024-09-17 11:33:42 +01:00
gingerBill 19c1ed154c Add -vet-packages:<comma-separated-string-array> 2024-09-17 11:01:26 +01:00
gingerBill abf6ea7732 Fix minor bug with addressability 2024-09-17 10:24:19 +01:00
pkova 6e0f1cc866 Pass microseconds instead of nanoseconds to __ulock_wait 2024-09-17 02:35:00 +03:00
Pyry Kovanen 4d6f7dcac0 Fix code alignment in futex_darwin.odin
Co-authored-by: Feoramund <161657516+Feoramund@users.noreply.github.com>
2024-09-17 02:21:00 +03:00
pkova aa25714d43 Remove comment from core sync tests now that they're fixed 2024-09-17 02:11:41 +03:00
pkova fff99c726e Fix core sync test deadlock on darwin 2024-09-17 01:52:51 +03:00
gingerBill a16d3b6c9a Merge pull request #4242 from laytan/caller-expression
add '#caller_expression'
2024-09-16 17:36:46 +01:00
gingerBill 68619f299e Merge pull request #4209 from flysand7/core-mem
[core/mem]: Document, refactor, reformat!
2024-09-16 17:35:19 +01:00
gingerBill 017d6bdf73 Merge pull request #4232 from Feoramund/test-sync
Add test suites for `core:sync` and `core:sync/chan`
2024-09-16 17:27:20 +01:00
Feoramund 16ef59700b Check for EINTR in sys/posix test 2024-09-15 23:58:03 -04:00
Feoramund d38f5ffb49 Remove unneeded synchronizations in Chan
Everything was already guarded by `c.mutex`.
2024-09-15 22:59:30 -04:00
Laytan Laats d03d9e49a6 fix #4243 2024-09-15 00:03:20 +02:00
Laytan d2d2026736 Merge pull request #4241 from laytan/improve-bit-field-debug-info
improve bit field debug info
2024-09-14 22:15:47 +02:00
Laytan Laats 603efa860a add '#caller_expression' 2024-09-14 22:13:37 +02:00
Karl Zylinski 3d7b924260 Fix a few incorrectly placed build tags. 2024-09-14 18:41:05 +02:00
Karl Zylinski 19f0127e55 Moved all packages in core, base, vendor, tests and examples to use new #+ file tag syntax. 2024-09-14 18:27:49 +02:00
Karl Zylinski b12d312408 core/odin: Added new file tag syntax as token. parse_file stores a list of tags that the file tag parser can use later. 2024-09-14 17:59:50 +02:00
Laytan Laats 4f3f256375 improve bit field debug info 2024-09-14 15:52:37 +02:00
Karl Zylinski c24e18bf10 Fix incorrect syntax error in parse_file 2024-09-14 14:36:33 +02:00
Karl Zylinski 8b84b9a4a2 Docs are generated as expected again. 2024-09-14 14:32:46 +02:00
Karl Zylinski 86e291235d Merge remote-tracking branch 'origin/master' into file-tags-without-comments 2024-09-14 11:26:41 +02:00
flysand7 466e29bb38 [mem]: Rollback allocator API consistency 2024-09-14 13:15:02 +11:00
flysand7 016d1a84d4 [mem]: Document mutex, rollback stack and tracking allocators 2024-09-14 10:46:35 +11:00
flysand7 3ed2ab6e2c [mem]: Adjust the docs for calc_padding_with_header 2024-09-14 10:18:51 +11:00
flysand7 e90f5d2528 [mem]: Adjust the docs on the buddy allocator 2024-09-14 10:03:04 +11:00
Laytan 129d85fe7d Merge pull request #4236 from laytan/box2d-release-build
vendor/box2d: build in release mode
2024-09-13 21:09:57 +02:00
Laytan Laats 18a63037d1 vendor/box2d: build in release mode 2024-09-13 20:51:06 +02:00
gingerBill 3166c7bef9 Add Suggested Example for using an inline procedure which enables a target feature 2024-09-12 10:07:09 +01:00
Laytan 275f1cc0de Merge pull request #4233 from laytan/fix-poly-variadic-reuse-slice
fix reuse of slice for varargs with poly types
2024-09-12 02:34:01 +02:00
Laytan Laats 387f56634d fix reuse of slice for varargs with poly types 2024-09-12 02:25:44 +02:00
Jeroen van Rijn c94829f4d3 Merge pull request #4231 from InKryption/enable-doc-out-param
Enable -out:<filename> for doc subcommand
2024-09-12 01:43:22 +02:00
Laytan Laats 201a7b90bb fix EventMaskAny definition 2024-09-12 00:11:27 +02:00
gingerBill 27ed10746d Allow transmute(Bit_Set)~T(0) 2024-09-11 23:08:38 +01:00
Laytan Laats 3b22c0854c fix some LLVM assertions 2024-09-11 22:45:16 +02:00
InKryption 1025b9e6c0 Enable -out:<filename> for doc subcommand
The logic for writing the .odin-doc file to the value assigned
to out_filepath already exists, this just enables it on the CLI
frontend.
2024-09-11 21:11:32 +02:00
Laytan 244a4acfa1 Merge pull request #4230 from laytan/cbor-unmarshal-non-string-keys
core/encoding/cbor: allow unmarshalling non-string map keys
2024-09-11 16:08:53 +02:00
Laytan Laats 788e4b2b6a core/encoding/cbor: allow unmarshalling non-string map keys 2024-09-11 15:57:56 +02:00
Feoramund 7f7cfebc91 Add tests for core:sync and core:sync/chan 2024-09-11 08:39:38 -04:00
Feoramund 16cd16b91e Fix comments 2024-09-11 08:39:23 -04:00
Feoramund 2938655a3d Fix CPU count detection in FreeBSD & NetBSD 2024-09-11 08:39:23 -04:00
Feoramund b1db33b519 Add cpu_relax to sync.auto_reset_event_signal 2024-09-11 08:39:23 -04:00
Feoramund a1435a6a90 Fix deadlock in Auto_Reset_Event 2024-09-11 08:39:23 -04:00
Feoramund fec1ccd7a3 Fix data races in sync.Recursive_Benaphore 2024-09-11 08:39:23 -04:00
gingerBill 9b06ea5bfd Fix #4229 for edge case os.Error/os.Errno legacy bodge 2024-09-11 12:01:01 +01:00
Laytan Laats b379d25a12 ci: try updating deprecated setup-python 2024-09-11 03:05:56 +02:00
Laytan Laats a15afccd36 ci: aware 2024-09-11 02:56:24 +02:00
Laytan Laats 83b5f82a92 ci: ohhh, I am dumb 2024-09-11 02:45:58 +02:00
Laytan Laats 496d732aaf ci: does backblaze not like tar archives? 2024-09-11 02:41:28 +02:00
Laytan Laats 26db1c8860 ci: show me files 2024-09-11 02:30:43 +02:00
Laytan Laats 7ff424d148 ci: specify path 2024-09-11 02:26:39 +02:00
Laytan Laats f4322886f3 ci: really, what's in there? 2024-09-11 02:19:39 +02:00
Laytan Laats 005cadb52c ci: what's in there? 2024-09-11 02:10:55 +02:00
Laytan Laats 90ba78cdfc ci: no UTC on this python 2024-09-11 02:01:14 +02:00
Laytan Laats a66524b0b2 ci: fix run step 2024-09-11 01:55:33 +02:00
flysand7 f16ed256ea [mem]: Fix handling of default resize to check alignment 2024-09-11 08:00:27 +11:00
gingerBill b442ea8601 Merge pull request #4206 from laytan/improve-linking-shared-libraries
Improve linking shared libraries
2024-09-10 21:59:21 +01:00
Jeroen van Rijn 309ea50a7c Merge pull request #4204 from A1029384756/static_builds
Changed Linux CI builds to static linking with Musl for better compatibility
2024-09-10 22:41:25 +02:00
Jeroen van Rijn 5c4f241f22 upload v4 2024-09-10 22:21:50 +02:00
Jeroen van Rijn fce7bcec49 Merge branch 'master' into static_builds 2024-09-10 22:15:06 +02:00
Jeroen van Rijn 459de29a87 Merge pull request #4193 from odin-lang/dependabot/github_actions/dot-github/workflows/actions/download-artifact-4.1.7
Bump actions/download-artifact from 1 to 4.1.7 in /.github/workflows
2024-09-10 22:13:01 +02:00
Feoramund b2c2235e58 Fix recursive_benaphore_try_lock
Previously, if the owner called this, it would fail.
2024-09-10 14:52:20 -04:00
Feoramund 3a60109180 Fix signalling test child threads crashing test 0
A thread made inside a test does not share the test index of its parent,
so any time one of those threads failed an assert, it would tell the
runner to shutdown test index zero.
2024-09-10 14:52:20 -04:00
Feoramund 074314b887 Fix data race in test_core_flags 2024-09-10 14:52:20 -04:00
Feoramund 8a14a656fb Fix chan.can_send for unbuffered channels
`w_waiting` is the signal that says a caller is waiting to be able to
send something. It is incremented upon send and - in the case of an
unbuffered channel - it can only hold one message.

Therefore, check that `w_waiting` is zero instead.
2024-09-10 14:52:20 -04:00
Feoramund e9a6a34480 Forbid chan.try_send on closed buffered channels 2024-09-10 14:52:20 -04:00
Feoramund 026aef69e3 Fix deadlock on sending to full, buffered, closed Chan
This will also keep messages from being sent to closed, buffered
channels in general.
2024-09-10 14:52:20 -04:00
Feoramund 73f5ab473c Keep chan.can_recv from deadlocking 2024-09-10 14:52:20 -04:00
Feoramund 0a594147af Use contextless procs in core:sync instead 2024-09-10 14:52:20 -04:00
Jeroen van Rijn beb10cce63 Fix #4227 2024-09-10 15:31:57 +02:00
Jeroen van Rijn 4df668fa22 Merge pull request #4226 from Kelimion/fix-4225
Fix #4225
2024-09-10 15:30:43 +02:00
Jeroen van Rijn 564c7821c5 Allow ExactValue_Invalid in assert.
Fixes #4225
2024-09-10 15:19:12 +02:00
flysand7 fdd4882568 [mem]: Adjust docs for alloc 2024-09-10 19:51:20 +11:00
Feoramund c3f363cfbc Fix data race when pool_stop_task is called 2024-09-09 16:19:15 -04:00
Feoramund dbb783fbf2 Fix atomic memory order for sync.ticket_mutex_unlock 2024-09-09 16:19:15 -04:00
Feoramund 45da009377 Use more atomic handling of thread flags
This can prevent a data race on Linux with `Self_Cleanup`.
2024-09-09 16:19:15 -04:00
Feoramund 4d14b4257e Convert POSIX Thread to use semaphore instead
One less value to store, and it should be less of a hack too.

Semaphores will not wait around if they have the go-ahead; they depend
on an internal value being non-zero, instead of whatever was loaded when
they started waiting, which is the case with a `Cond`.
2024-09-09 16:19:14 -04:00
Feoramund cbd4d5e765 Fix data race in atomic_sema_wait_with_timeout 2024-09-09 16:19:14 -04:00
Feoramund 74b28f1ff9 Fix rare double-join possibility in POSIX thread._join
This was occuring about 1/100 times with the test runner's thread pool.
2024-09-09 16:19:14 -04:00
Feoramund 9d6f71fd2e Fix sync.Benaphore
The calls to `atomic_add*` return the value before adding, not after, so
the previous code was causing the occasional data race.
2024-09-09 16:19:14 -04:00
Karl Zylinski f9de8fdaba Documentation typo fix in tokenizer. 2024-09-09 21:51:34 +02:00
Karl Zylinski 580f0599cd parse_file: Removed some nesting and removed probable incorrect safety check. 2024-09-09 21:24:41 +02:00
Karl Zylinski cc724ff5d2 Made error handling code in parse_file clearer. 2024-09-09 21:13:39 +02:00
Karl Zylinski 957cd64699 Rename process_file_tag -> parse_file_tag 2024-09-09 21:06:43 +02:00
Karl Zylinski 3637dcbd04 Simplified error messages in parse_build_tag, removed the idea of making multiple notted operating systems since it was misinformed. 2024-09-09 21:03:28 +02:00
Thomas la Cour 954dd86f7a nightly define fix 2024-09-09 19:55:00 +02:00
Thomas la Cour 6298b23e07 tag nightly builds 2024-09-09 19:34:19 +02:00
Thomas la Cour 053425e8d7 trim version digits, release=YYYY.MM.0.0 else YYYY.MM.DD.0 2024-09-09 19:29:43 +02:00
Laytan Laats 5ae27c6ebc wasm: support more vendor libraries
Adds support for:
- box2d
- cgltf
- stb image
- stb rect pack
2024-09-09 18:49:13 +02:00
Laytan d783bca297 Merge pull request #4218 from pkova/master
Fix os2/heap_linux.odin deadlock
2024-09-09 17:25:00 +02:00
Laytan ce3f6b60d2 Merge pull request #4223 from hstormo/bugfix
Remove stb_rect_pack implementation from stb_truetype (fix #4215)
2024-09-09 17:21:41 +02:00
gingerBill a25a9e6ebe Check for LLVM_VERSION_MAJOR >= 18 2024-09-09 14:47:44 +01:00
gingerBill 0dddd2b97e Add internal flag
`-internal-fast-isel`
2024-09-09 14:39:53 +01:00
laytan aa75909418 recompile bundled stb truetype on windows 2024-09-09 15:14:26 +02:00
Laytan Laats 0f379d7378 recompile bundled stb truetype 2024-09-09 17:09:49 +02:00
Håkon Stormo ae020ffb2e Remove stb_rect_pack implementation from stb_truetype (fix #4215) 2024-09-09 15:50:00 +02:00
A1029384756 036d7edda9 Changed Linux CI builds to static linking with Musl for better
compatibility

Changed to tarball distribution for mac and linux

Updated upload-artifact to v4
2024-09-08 18:35:16 -04:00
Laytan Laats 75dd562a0a fix #4219 - recursive mutex lock 2024-09-08 22:23:03 +02:00
pkova 0a17525791 Remove unused base:runtime from os2/heap_linux.odin 2024-09-08 17:25:30 +00:00
pkova 499a5d1f9c Fix os2/heap_linux.odin deadlock 2024-09-08 16:47:16 +00:00
gingerBill e72d0ba804 Move around mutex guard 2024-09-08 14:11:05 +01:00
Karl Zylinski f3a2b625ae Merge remote-tracking branch 'origin/master' into file-tags-without-comments 2024-09-08 11:29:21 +02:00
flysand7 167ced8ad1 [mem]: Don't use named params for dynamic pool in tests 2024-09-08 18:52:55 +11:00
flysand7 05df34f99c [mem]: Start documenting allocators.odin 2024-09-08 18:44:33 +11:00
flysand7 299accb717 [mem]: Put panic allocator after nil allocator, adjust @require_results 2024-09-08 14:17:32 +11:00
flysand7 3b30bc305c [mem]: Document raw.odin 2024-09-08 14:13:03 +11:00
Karl Zylinski 73e4954346 Better #+build tag error messages: Error when using more than one !notted operating system per build line. Error when using more than one operating system within a 'kind', such as writing #+build windows linux. 2024-09-08 03:13:21 +02:00
flysand7 f1f5dc614e [mem]: Remove old comments 2024-09-08 11:17:27 +11:00
flysand7 6eb80831b5 [mem]: Panic when allocator is not initialized 2024-09-08 11:12:28 +11:00
flysand7 b78d546010 [mem]: Add non_zeroed versions of resize 2024-09-08 11:02:17 +11:00
flysand7 c719a86312 [mem]: Document alloc.odin 2024-09-08 10:58:40 +11:00
Karl Zylinski dc767da12b Make tags use #+ syntax instead of //+ syntax so it no longer looks like a comment. Old style still works but is deprecated with a warning. Using unknown tags is now an error instead of a warning. There is a new token for #+ which consumes the whole line (or until it hits a comment). The tags are parsed like before. There are errors to tell you if you use something invalid in the pre-package-line block. 2024-09-08 01:50:56 +02:00
Jeroen van Rijn 300b01d77d Return "" for rune < 0 in strconv. 2024-09-08 00:32:46 +02:00
Laytan 1ab0745ca8 Merge pull request #4212 from karl-zylinski/fix-build-tags
Fix build tags that use ! multiple times on one line.
2024-09-07 22:18:29 +02:00
Karl Zylinski 8c636ac37b Fix build tags that use ! multiple times on one line. Those don't actually do anything since build tags use OR within the line. So something like //+build !windows, !linux would actually build on both linux and windows. What was intended in all these cases was probably AND, which you get by splitting them into separate lines. 2024-09-07 22:02:17 +02:00
Jeroen van Rijn 466a90010f Fix #4211 2024-09-07 21:07:29 +02:00
gingerBill 5a4746c3a0 Improve debug information for procedure types 2024-09-07 17:41:16 +01:00
flysand7 1842cd6297 Fix typo
Co-authored-by: FourteenBrush <74827262+FourteenBrush@users.noreply.github.com>
2024-09-08 00:09:18 +11:00
Jeroen van Rijn c4c2282595 Update 4210 test to use unaligned_load. 2024-09-07 14:05:56 +02:00
Jeroen van Rijn d2202416d2 Add test for #4210 2024-09-07 13:43:19 +02:00
gingerBill 0a08a65202 Simplify #row_major matrix and matrix_flatten behaviour 2024-09-07 12:21:29 +01:00
flysand7 f8cd13767e [mem]: Fix the issue with unbranched version of ptr align 2024-09-07 18:08:11 +11:00
flysand7 3a351ec407 [mem]: Document mem.odin 2024-09-07 18:01:41 +11:00
flysand7 7c9d2f61f5 [mem]: Update package documentation 2024-09-07 15:16:20 +11:00
flysand7 6017a20e1c [mem]: Make resize_bytes take a slice for the old memory 2024-09-07 15:11:04 +11:00
flysand7 2d988bbc5f [mem]: Rename alloc to alloc_bytes and add alloc 2024-09-07 14:45:15 +11:00
flysand7 64814f4199 [mem]: Document the package 2024-09-07 14:19:50 +11:00
flysand7 c0112d1c70 [mem]: Add free_all for buddy allocator 2024-09-07 13:27:17 +11:00
flysand7 c0e17808d4 [mem]: Split alloc and alloc_non_zeroed for buddy allocator 2024-09-07 13:26:09 +11:00
flysand7 6d3cffa13c [mem]: Add @require_results to all functions returning values 2024-09-07 13:14:58 +11:00
flysand7 b350a35b77 [mem]: Add resize_non_zeroed variant to dynamic arena, and rename pool to arena 2024-09-07 13:10:29 +11:00
flysand7 03f6b9bbf6 [mem]: Add alloc_non_zeroed variant to dynamic pool 2024-09-07 12:59:19 +11:00
flysand7 f8641ddd1b [mem]: Rename dynamic pool to dynamic arena 2024-09-07 12:33:12 +11:00
flysand7 aea3e9a585 [mem]: Fix vet errors 2024-09-07 12:26:47 +11:00
flysand7 4843db0960 [mem]: API for using small stack allocator directly 2024-09-07 12:23:55 +11:00
flysand7 de220a9aa5 [mem]: Remove the extra word 'allocator' in procedures 2024-09-07 11:07:06 +11:00
flysand7 9750b64096 [mem]: API for using stack allocator directly 2024-09-07 10:55:54 +11:00
flysand7 834f082dba [mem]: Initialize scratch allocator during calls to free and resize 2024-09-07 10:24:00 +11:00
flysand7 e5106e48a8 [mem]: API for using scratch allocator directly 2024-09-07 10:09:05 +11:00
flysand7 da6213196d [mem]: API for using arena directly 2024-09-07 09:42:04 +11:00
flysand7 2b9096517c [mem]: Code formatting 2024-09-07 09:20:56 +11:00
gingerBill 90358f97d5 Merge pull request #4205 from Valakor/wgpu
Fix wgpu on Windows - missing links to ole32.lib and oleaut32.lib
2024-09-06 14:08:07 +01:00
Matthew Pohlmann c19da21d81 Fix wgpu on Windows - missing links to ole32.lib and oleaut32.lib 2024-09-05 21:40:15 -07:00
gingerBill 78506b97a3 Merge pull request #4202 from laytan/add-fixed-point-dependency
add fixed point sign extend to 128 int deps
2024-09-05 19:08:38 +01:00
Laytan Laats 490f8c1568 add fixed point sign extend to 128 int deps 2024-09-05 15:55:55 +02:00
laytan a99e57c62c bytes: fix last_index_byte off-by-one 2024-09-05 13:30:46 +02:00
Laytan Laats ddf5ca7adf remove deprecation, technically deprecated but widely used 2024-09-05 01:08:09 +02:00
Laytan Laats 6778598bc6 support the rpath changes on macos 2024-09-05 00:12:16 +02:00
Laytan 0aa971207b add -no-rpath 2024-09-04 22:38:19 +02:00
gingerBill a4fd0c133e Merge pull request #4191 from laytan/improve-package-doc-comments
core: improve package doc comments for the documentation generator
2024-09-04 21:37:48 +01:00
Laytan ce018b4e6f Merge pull request #4197 from dekdevy/master
fix wgpu vendor lib error message
2024-09-04 22:22:25 +02:00
Laytan 1a7c1d107a set -rpath to \$ORIGIN and expect libraries next to executable just like Windows 2024-09-04 22:19:46 +02:00
dek d2d5ac33f4 fix wgpu vendor lib error message 2024-09-04 22:04:06 +02:00
Laytan 578de09775 types with explicit custom alignment are identical to types with the same natural alignment 2024-09-04 18:48:11 +02:00
Laytan dcf339517e make c vararg with any vs concrete type similar enough 2024-09-04 18:47:08 +02:00
gingerBill b2c5998e78 Merge pull request #4196 from jakubtomsu/unmarshal-json-bit-sets
Support unmarshalling bit_sets in `core:encoding/json`
2024-09-04 13:27:25 +01:00
jakubtomsu 7487d507be unmarshal bitset ints like cbor does 2024-09-04 11:08:45 +02:00
Jeroen van Rijn c6b551d2c3 Merge pull request #4194 from Feoramund/update-bit-array
Update `bit_array`
2024-09-03 23:42:27 +02:00
Feoramund 2f1228baa0 Add tests for Bit_Array 2024-09-03 17:23:42 -04:00
dependabot[bot] 73eea33b56 Bump actions/download-artifact from 1 to 4.1.7 in /.github/workflows
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 1 to 4.1.7.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v1...v4.1.7)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-03 21:01:48 +00:00
Feoramund c3bd94a27e Change Bit_Array.max_index to length
This will allow correct iteration of empty `bit_array`s.
2024-09-03 16:56:02 -04:00
Jeroen van Rijn 645207b8b0 Merge pull request #4192 from laytan/strings-substring-rune-wise
strings: add `substring`, `substring_to` and `substring_from`
2024-09-03 22:47:56 +02:00
Feoramund d86e56089a Fix iteration of biased Bit_Array 2024-09-03 15:34:38 -04:00
Laytan Laats 597ba796b7 strings: add substring, substring_to and substring_from 2024-09-03 21:13:35 +02:00
Laytan Laats 288312a812 core: improve package doc comments for the documentation generator 2024-09-03 19:59:04 +02:00
Laytan 6bbc165121 Merge pull request #4181 from laytan/more-riscv-sysinfo
sys/info: more CPU feature detection for RISC-V
2024-09-03 19:54:15 +02:00
Feoramund b8f8cb9582 Add bit_array.shrink 2024-09-03 13:33:15 -04:00
Feoramund 001b2b9d8f Let bit_array.create make zero-length arrays 2024-09-03 13:33:11 -04:00
Laytan 33735ba5cc Merge pull request #4180 from dvrd/alt
fix(os2): mkdir_all on path_posix
2024-09-03 19:31:04 +02:00
Jeroen van Rijn 3da77bcd67 Merge pull request #4190 from Kelimion/strings.cut
strings.cut without allocation.
2024-09-03 19:09:27 +02:00
Jeroen van Rijn 996175753c strings.cut without allocation. 2024-09-03 19:02:40 +02:00
gingerBill 0e6109e171 Merge pull request #4189 from pkova/master
Fix thread sanitizer errors surfaced by tests/core/io
2024-09-03 15:57:45 +01:00
pkova 5b9b21e756 Fix thread sanitizer errors surfaced by tests/core/io 2024-09-03 16:30:51 +03:00
gingerBill d93aca647b Merge pull request #4171 from yay/objc-runtime-bindings
More Objective-C Runtime bindings.
2024-09-03 14:28:02 +01:00
gingerBill 6ed4bfeba1 Merge pull request #4186 from Feoramund/fix-4177
Return false if `Small_Array` can't append multiple elements
2024-09-03 14:25:15 +01:00
gingerBill 99a3e9a510 Merge pull request #4187 from Feoramund/fix-slice-equal
Check for zero-length slices in `slice.equal`
2024-09-03 14:24:45 +01:00
gingerBill c0154bffad Merge pull request #4188 from FrancisTheCat/master
Added `#any_int` to some `soa` procs to mirror the behaviour of their non `soa` counterparts
2024-09-03 14:24:36 +01:00
Jeroen van Rijn 9276476760 Merge pull request #4185 from Feoramund/add-time-to-datetime
Add `time.time_to_datetime`
2024-09-03 15:05:42 +02:00
Vitalii Kravchenko c86bbc61bc More Objective-C Runtime bindings. 2024-09-03 11:41:23 +01:00
Franz Hoeltermann 02da1ac9af Added #any_int directive to some more builtin slice/dynamic array
procedures
2024-09-03 12:36:32 +02:00
Franz Hoeltermann b618b665c6 Added #any_int to some #soa procs to mirror the behaviour of their
non-soa counterparts
2024-09-03 11:46:09 +02:00
Feoramund 806c87d71d Check for zero-length slices in slice.equal 2024-09-03 02:48:26 -04:00
Feoramund 309953e0f2 Return false if Small_Array can't append multiple elements
Fixes #4177
2024-09-03 01:14:17 -04:00
Feoramund f6f2c67f37 Add time.time_to_datetime 2024-09-03 00:55:09 -04:00
Jeroen van Rijn 71b2527df0 Merge pull request #4184 from Dimension4/help-text-build-mode
Add missing help text for -build-mode:test
2024-09-03 00:17:17 +02:00
Dimension4 b24157738f Add missing help text for -build-mode:test 2024-09-02 23:40:13 +02:00
Laytan Laats 60321d98d4 also fix the doc comment in the code generator 2024-09-02 20:22:02 +02:00
Laytan Laats 195259e88b fix some doc comments 2024-09-02 20:10:11 +02:00
laytan 35731e66cf sys/info: more CPU feature detection for RISC-V 2024-09-02 14:06:19 +00:00
Dan Castrillo 54b46247bd fix(os2): mkdir_all on path_posix 2024-09-02 08:47:26 -04:00
gingerBill 16c5c69a40 Merge pull request #4175 from laytan/riscv-compiler
Support RISC-V for the compiler itself
2024-09-02 00:20:04 +01:00
gingerBill 39b49cb6fb Merge pull request #4176 from Feoramund/fix-context-error-msg
Remove extra format item at end of `context` error message
2024-09-02 00:18:15 +01:00
Feoramund 9871ad5fc8 Remove extra format item at end of context error message 2024-09-01 17:50:50 -04:00
Laytan 28c643d23f riscv compiler support 2024-09-01 21:42:47 +02:00
Jeroen van Rijn dd1f151696 Add math.remap_clamped. 2024-09-01 17:22:58 +02:00
Jeroen van Rijn c1605b5b4f Merge pull request #4173 from karl-zylinski/clamp-remap
Make math.remap clamp the result in range [new_min, new_max]
2024-09-01 16:54:17 +02:00
Karl Zylinski 6e150d1d58 Make math.remap clamp the result in range [new_min, new_max]. 2024-09-01 16:30:48 +02:00
Laytan 722b638e2c "fix" #4169, looks like llvm 14 bug 2024-08-31 19:40:05 +02:00
Jeroen van Rijn c1cb1a3d7e Simplified #assert check 2024-08-31 19:13:37 +02:00
Jeroen van Rijn a4ac50a5b4 Check for #assert condition to be a constant bool
Fixes #4170
2024-08-31 19:06:17 +02:00
gingerBill 6ba1506aa9 Fix possible leaks in os2.user_* calls 2024-08-31 15:12:47 +01:00
gingerBill b4bdb73158 Fix new(sync.Mutex) 2024-08-31 15:06:20 +01:00
gingerBill 476030dd28 Fix #4156 2024-08-31 13:51:35 +01:00
Laytan Laats e0a2e52601 c/libc: fix time link name 2024-08-31 02:49:53 +02:00
Laytan Laats 7f3d8e115f remove comma 2024-08-31 02:45:17 +02:00
Laytan 584e8859bf Merge pull request #4168 from laytan/fix-bad-import-name-errors
fix some issues with the "bad import name" errors
2024-08-31 02:44:16 +02:00
Laytan Laats 8e855155fd fix bad import 2024-08-31 02:38:07 +02:00
Laytan Laats 7624ecf4ba fix some issues with the "bad import name" errors
There was so much wrong here:
- The `if` statement was never entered because even on invalid import
  names `path_to_entity_name` returns "_"
- Two errors were shown where one doesn't make sense, need to choose one
  based on context
- Structure of the messages were different from other error messages
- Suggestion was using the wrong import path
2024-08-31 02:30:32 +02:00
Laytan Laats bfedcd7035 encoding/csv: fix examples 2024-08-30 23:31:31 +02:00
Laytan Laats 6ef49d4f24 core/odin: support #type_assert and #no_type_assert 2024-08-30 23:21:35 +02:00
Jeroen van Rijn 8ad4427a25 Add a few more reflect.bit_field_* helpers. 2024-08-30 22:40:14 +02:00
Jeroen van Rijn db3bcd2cea Add reflect.bit_fields_zipped 2024-08-30 22:04:10 +02:00
Jeroen van Rijn 3072a02d5d Attempt to account for BuildTools installer's lack of \ 2024-08-30 18:54:51 +02:00
gingerBill 773703bc83 Merge pull request #4009 from thetarnav/file-tag-parser
Add a file tag parser to core:odin/parser
2024-08-30 11:58:18 +01:00
gingerBill a4e865f90b Fix #4166 2024-08-30 11:01:06 +01:00
gingerBill 9197a126fc Use XOR directly rather than (~x) & mask 2024-08-30 10:52:11 +01:00
gingerBill 38ea276231 Make ~some_bit_set work on only the possible bits by doing a mask with the full set 2024-08-30 10:48:21 +01:00
gingerBill b020b91df2 Merge pull request #4112 from Feoramund/fix-test-io-issues
Add `core:io` test suite
2024-08-30 09:57:02 +01:00
gingerBill 291048cb3b Merge pull request #4165 from avanspector/master
Add missing lexer checking delay for foreign blocks
2024-08-30 09:56:36 +01:00
avanspector 3135c89a0a Merge branch 'master' of https://github.com/avanspector/Odin 2024-08-30 01:32:21 +02:00
avanspector 47f423c123 Set a flag for delayed checking 2024-08-30 01:32:06 +02:00
avanspector a7a2611efc Merge branch 'odin-lang:master' into master 2024-08-29 23:44:14 +02:00
avanspector 9866c83d61 Add missing checker delaying 2024-08-29 23:43:01 +02:00
Damian Tarnawski 655610ec87 Satisfy vet 2024-08-29 23:06:50 +02:00
Damian Tarnawski a28d574272 Add and test match_build_tags 2024-08-29 23:02:49 +02:00
Damian Tarnawski f93779d425 Parse build_project_name as [][]string 2024-08-29 22:08:01 +02:00
Damian Tarnawski a10f988020 Move some types to runtime, use reflection instead of lut 2024-08-29 21:12:33 +02:00
Damian Tarnawski 39bdf4d710 Add missing require_results attr 2024-08-29 20:52:27 +02:00
Damian Tarnawski 7862460374 Remove useless code 2024-08-29 20:52:27 +02:00
Damian Tarnawski 92821300e4 Add a file tag parser to core:odin/parser 2024-08-29 20:52:27 +02:00
Laytan 94a1a7aed5 Merge pull request #4164 from laytan/virtual-growing-min-block-size-fix
mem/virtual: make sure the given size is used for subsequent blocks
2024-08-29 18:27:54 +02:00
Laytan Laats 5a22d49b72 mem/virtual: make sure the given size is used for subsequent blocks 2024-08-29 14:48:36 +02:00
Laytan 942017b958 Merge pull request #4163 from laytan/sysconf-pagesize
mem/virtual: use `sysconf` for retrieving page size and actually use these init procs
2024-08-29 14:44:54 +02:00
Laytan Laats fd2ad20cd4 mem/virtual: use sysconf for retrieving page size and actually use these init procs 2024-08-29 14:36:32 +02:00
Laytan Laats cca385209b Remove double close 2024-08-28 19:53:20 +02:00
Laytan Laats fe2d256468 Properly close the temporary files in io tests 2024-08-28 19:53:20 +02:00
Laytan Laats 0f2ad95014 Fix EOF detection is os2 window read 2024-08-28 19:53:20 +02:00
Feoramund 7fa2e56cd9 Add io tests for bufio streams 2024-08-28 19:53:20 +02:00
Feoramund 24a53c246f Make sure seek succeeds in io.Limited_Reader test setup 2024-08-28 19:53:20 +02:00
Feoramund b11fa90ed2 Test empty slice usage in io procs 2024-08-28 19:53:20 +02:00
Feoramund f453054aff Return 0, nil in all io cases where an empty slice is provided 2024-08-28 19:53:20 +02:00
Feoramund ef99373c31 Fix pread and pwrite on os2 Windows
The previous code was jumping ahead by the specified offset, instead of
getting the current offset.
2024-08-28 19:53:20 +02:00
Feoramund 1cd5cbb0e4 Test io unexpected pointer movement 2024-08-28 19:53:20 +02:00
Feoramund 56f232e5fc Report invalid whence & offset on os2 Windows 2024-08-28 19:53:20 +02:00
Feoramund de1432b315 Fix Windows infinite recursion with os2._flush 2024-08-28 19:53:20 +02:00
Feoramund e7d6e2d163 Add documentation to os2.close
Make it explicit that using a stream after closing is like a
use-after-free bug.
2024-08-28 19:53:20 +02:00
Feoramund 8b40be50b9 Update core:io tests
- Relax return value requirements on errors. Only the error is checked,
  as there are multiple conflicting return styles throughout the `os`
  API.

  Some return the error along with `0`, `-1`, or another value. This can
  be smoothed out later.

- Test `os2` files now.
- No longer test streams after closing; this is considered similar to a
  use-after-free in `os2`.
2024-08-28 19:53:20 +02:00
Feoramund 6798d15ecb Check int(abs) instead to avoid overflows 2024-08-28 19:53:20 +02:00
Feoramund 6aedb2695a Report Invalid_Whence on some os platforms
- Move `Seek`-related checks into OS-specific files for granularity.

Platforms:
- Darwin
- FreeBSD
- Haiku
- Linux
- NetBSD
- OpenBSD
2024-08-28 19:53:20 +02:00
Feoramund 0243647e15 Add missing flush functionality to os platforms
Platforms:
- FreeBSD
- Haiku
- Linux
- NetBSD
- OpenBSD
2024-08-28 19:53:20 +02:00
Feoramund 3ec4db212b Report Invalid_Whence in os2 Linux seek 2024-08-28 19:53:20 +02:00
Feoramund 7683c1f4bb Report Invalid_Whence in os2 POSIX seek 2024-08-28 19:53:20 +02:00
Feoramund ef2cd9d97f Copy missing errors in os2._get_platform_error from posix to linux 2024-08-28 19:53:20 +02:00
Feoramund 5b9e9fb822 Add test suite for core:io 2024-08-28 19:53:20 +02:00
Feoramund 741ccd7ff5 Zero n on error in _file_stream_proc 2024-08-28 19:53:20 +02:00
Feoramund eb92a2df71 Fix indentation 2024-08-28 19:53:20 +02:00
Feoramund d60f404bb4 Fix OpenBSD implementations of read_at and write_at 2024-08-28 19:53:20 +02:00
Feoramund 6c4806835c Fix indentation 2024-08-28 19:53:20 +02:00
Feoramund e1555e04ad Fix Haiku implementations of read_at and write_at 2024-08-28 19:53:20 +02:00
Feoramund 7061032db6 Fix NetBSD implementations of read_at and write_at
These procedures must not modify the underlying file pointer.
2024-08-28 19:53:20 +02:00
Feoramund 861d892ffe Make Windows pread and pwrite conform to POSIX 2024-08-28 19:53:20 +02:00
Feoramund 5c8c63ae04 Fix FreeBSD implementations of read_at and write_at
These procedures must not modify the underlying file pointer.
2024-08-28 19:53:20 +02:00
Feoramund 1ced76cdd1 Fix broken cases of Seek usage in _file_stream_proc
Handles `EINVAL`, among other fixes.
2024-08-28 19:53:20 +02:00
Feoramund e83b982afe Measure bytes.Buffer size by length instead of capacity 2024-08-28 19:53:20 +02:00
Feoramund 7c6cc81041 Add Seek behavior to bytes.Buffer 2024-08-28 19:53:20 +02:00
Feoramund 521e47ffee Don't invalidate prev_rune if Reader seek failed 2024-08-28 19:53:20 +02:00
Feoramund 8251f4d7d0 Return .EOF in bytes.buffer_read_at instead
This is consistent with the other stream `read` procs
2024-08-28 19:53:20 +02:00
Feoramund da49f7eb4e Make bytes.reader_init return an io.Stream
Makes the API like the other stream `init` procs.
2024-08-28 19:53:20 +02:00
Feoramund d66486c17e Make io.Section_Reader set base too
This should fix seeking from `.Start`, getting the `size`, and
`read_at`.

Also make the API consistent with the other `*_init` procs in
`util.odin` by returning the `io.Reader`.
2024-08-28 19:53:20 +02:00
Feoramund 981a2e1a00 Add missing io.Stream_Mode responses 2024-08-28 19:53:19 +02:00
Laytan eb6e5ee3a1 Merge pull request #4162 from laytan/os2-disable-custom-heap-allocator
os2: disable custom heap allocator
2024-08-28 19:51:22 +02:00
Laytan 5e850e24d6 os2: disable custom heap allocator
See #4161
2024-08-28 19:45:34 +02:00
Jeroen van Rijn 17d10b72d5 Merge pull request #4158 from sqrt-negativeone/master
Win32 clipboard procedures
2024-08-28 19:02:18 +02:00
Fakhri Mouad b08c14b710 fix style, ensure we compile with flags -vet -strict-style -disallow-do 2024-08-28 17:52:58 +01:00
Jeroen van Rijn d3fca60e4d Merge pull request #4160 from Kelimion/vsdd
-vet -strict-style -disallow-do
2024-08-28 18:49:44 +02:00
Jeroen van Rijn d602e2cc74 Remove duplicate vet flag. 2024-08-28 18:43:54 +02:00
Jeroen van Rijn 831e26cb6f Remove unused import. 2024-08-28 18:42:54 +02:00
Jeroen van Rijn 7b276cbc7e -vet -strict-style -disallow-do 2024-08-28 18:36:49 +02:00
Fakhri Mouad 7e4750c303 fix indentation in test file 2024-08-28 17:30:30 +01:00
Fakhri Mouad 967b6d46b2 avoid using do statement in odin codebase 2024-08-28 17:27:27 +01:00
Jeroen van Rijn fcafd83506 Merge pull request #4159 from Kelimion/disallow-do
More -disallow-do in CI.
2024-08-28 18:20:39 +02:00
Jeroen van Rijn 21dab9673d More -disallow-do in CI. 2024-08-28 18:13:53 +02:00
Fakhri Mouad 16503c3b91 Add Win32 procs needed to handle clipboard 2024-08-28 16:36:06 +01:00
Laytan Laats 1e6419b5b7 fix zombie thread leak in thread self cleanup 2024-08-28 16:22:38 +02:00
Laytan Laats ef66f96cf2 fix windows bindings where BOOL is not actually a boolean
Fixes #4157
2024-08-28 15:45:41 +02:00
Laytan Laats 9684ade23e fix -vet-tabs 2024-08-27 19:13:46 +02:00
gingerBill 8694fa5f78 Minor cleanup of CFString.odin 2024-08-27 11:22:28 +01:00
gingerBill fb248056c9 Merge pull request #4146 from Feoramund/fix-i128-transmute-align
Fix inline transmutation of `[16]i8` to `i128`
2024-08-26 22:38:24 +01:00
gingerBill ade4e312fe Merge pull request #4154 from avanspector/master
Delay lexical checking for foreign blocks that are in file scope
2024-08-26 22:38:13 +01:00
gingerBill 12bd07d2df Merge pull request #4150 from laytan/update-wgpu-to-22-1-0
wgpu: update to v22.1.0.1
2024-08-26 22:37:31 +01:00
gingerBill 91f8c626bb Merge pull request #4148 from Feoramund/tls-cleaner
Add API for freeing `thread_local` state
2024-08-26 22:37:08 +01:00
Laytan c1684d6335 Merge pull request #4136 from flysand7/process-info-fix
[os2/process]: Don't free process info fields in partial success scenarios
2024-08-26 23:25:21 +02:00
flysand7 1a4faff9c9 [os2/process]: Fix typo on doc comments 2024-08-27 08:06:11 +11:00
Laytan 6c17642b91 Merge pull request #4155 from Feoramund/fix-test-vet-style
Fix `-vet` and `-strict-style` failures in tests
2024-08-26 23:01:21 +02:00
Laytan ef254ec055 Merge pull request #4153 from Feoramund/fix-4151
Fix #4151
2024-08-26 22:59:48 +02:00
Feoramund 1f04f541cf Fix -vet and -strict-style failures in tests 2024-08-26 16:20:08 -04:00
avanspector dd86a8f013 Merge branch 'odin-lang:master' into master 2024-08-26 21:00:25 +02:00
avanspector 43ec2b9253 checker: delay foreign block checking
if file scope, otherwise as before
2024-08-26 20:59:16 +02:00
Laytan Laats 60cd0da2ed wgpu: cont. fix sdl2glue on Linux 2024-08-26 20:24:26 +02:00
avanspector c21bbae427 Merge branch 'master' of https://github.com/avanspector/Odin 2024-08-26 19:59:20 +02:00
avanspector d7e977069a Update checker.cpp 2024-08-26 19:59:15 +02:00
Jeroen van Rijn ef98aa1fe1 Merge pull request #4152 from edyu/master
Fix error for uuid to require 36 bytes instead 32 (4 bytes for dashes)
2024-08-26 19:35:04 +02:00
Ed Yu 4e2bce0c83 Fix error for uuid to require 36 bytes instead 32 (4 bytes for dashes) 2024-08-26 10:25:10 -07:00
Feoramund d43c6e39f6 Fix #4151
The `core:mem` procs were calling the wrong `runtime` procs for their
number of arguments.
2024-08-26 13:23:04 -04:00
Laytan f56b895c05 wgpu: fix sdl2glue not using GetWindowWMInfo properly
Fixes #4127
2024-08-26 16:08:14 +02:00
Laytan Laats 54a420f3eb wgpu: update to v22.1.0.1 2024-08-26 15:49:12 +02:00
Jeroen van Rijn 3e0f6bda91 Merge pull request #4149 from Feoramund/fix-thread-pool-use-after-free
Fix use-after-free in `thread.Pool`
2024-08-26 13:05:23 +02:00
Feoramund 9fac03b84c Fix use-after-free in thread.Pool 2024-08-26 06:39:05 -04:00
Laytan 0a8f85e879 Merge pull request #4147 from Feoramund/cleanup-test-runtime-arenas
Free the arenas allocated in `test_core_runtime`
2024-08-26 12:09:34 +02:00
Feoramund 49606ec3ea Use thread_local_cleaner API in os2 2024-08-26 06:01:59 -04:00
Feoramund d338642dc4 Add API for freeing thread_local state 2024-08-26 06:01:59 -04:00
Feoramund 95d1c29c2a Free the arenas allocated in test_core_runtime
Found by using `-sanitize:address`.
2024-08-26 05:45:24 -04:00
Feoramund c424c94030 Fix inline transmutation of [16]i8 to i128
Forbids LLVM from generating SSE aligned loads on unaligned data.
2024-08-26 04:48:31 -04:00
gingerBill 8de1e88c4f Merge pull request #4144 from laytan/riscv-error-on-atomics-without-extension
riscv: add an error when atomics are used without the atomics extension
2024-08-25 22:49:42 +01:00
flysand7 3119e0489f [os2/process]: Fix vet errors 2024-08-26 07:23:59 +11:00
flysand7 db94e646e0 [os2/process]: Adjust documentation for process info 2024-08-26 07:21:54 +11:00
flysand7 4737485f09 [os2/process]: Force return on allocation errors and process not existing 2024-08-26 07:19:39 +11:00
Laytan d299d4e1cd riscv: add an error when atomics are used without the atomics extension 2024-08-25 21:17:00 +02:00
Laytan 9aeb0d0fb6 Merge pull request #4142 from laytan/os2-propogate-errors-from-execv
os2: propagate errors from execv
2024-08-25 21:09:54 +02:00
Laytan 0ea6809b49 os2: remove return on file_size error from read_entire_file
file_size can't return .No_Size because it uses io.size and only returns
an io.Error, removing this so it works when file_size fails (linux pipes
for instance)
2024-08-25 18:43:23 +02:00
Laytan Laats a0fe6da10b os2: propogate errors from execv functions to parent 2024-08-25 18:01:33 +02:00
gingerBill 8c952878fb Allow empty strings in link_prefix and link_suffix 2024-08-25 14:03:14 +01:00
gingerBill eda58357b6 Merge pull request #4141 from VladPavliuk/fix-dwmapi-enum
Fix win32 dwmapi DWMWINDOWATTRIBUTE enum.
2024-08-25 12:46:51 +01:00
gingerBill 7b14c267fb Merge pull request #4138 from z64/z64/fix-cmark
Fix binding to cmark_node_get_fence_info
2024-08-25 12:43:07 +01:00
VladPavliuk cc2ed2b302 Fix win32 dwmapi enum. 2024-08-25 14:34:24 +03:00
Zac Nowicki 17cc423a17 Fix binding to cmark_node_get_fence_info
https://github.com/commonmark/cmark/blob/master/src/cmark.h#L334
2024-08-25 01:42:12 -04:00
flysand7 fa84e86766 [os2/process]: Allow for partial success scenarios 2024-08-25 14:22:27 +11:00
flysand7 0d7e6430eb [os2/process]: Don't free process info fields in partial success scenarios 2024-08-25 13:08:24 +11:00
Jeroen van Rijn 4cf1af3f7d Merge pull request #4135 from gelatinstudios/master
fix core:reflect/iterator.odin
2024-08-24 23:23:33 +02:00
Laytan eef4dffa12 Merge pull request #4134 from karl-zylinski/fix-raylib-LoadImageAnim-binding
Fix binding: Make rl.LoadImageAnim take a pointer instead of a multi-pointer.
2024-08-24 22:56:49 +02:00
Karl Zylinski 25e8a6353d Fix comment indentation. 2024-08-24 22:02:17 +02:00
unknown ae5ef0ce9c fix core:reflect/iterator.odin 2024-08-24 16:01:49 -04:00
Karl Zylinski 574a5015d6 Make rl.LoadImageAnim take a pointer instead of a multipointer. The param frames is just for returning an int, it's not for passing a multipointer into the proc. 2024-08-24 22:00:29 +02:00
Jeroen van Rijn 0a825fc44d Improve SRV handling in dns_windows.odin 2024-08-24 18:43:25 +02:00
gingerBill aa659a637a Fix #4132 2024-08-24 15:46:54 +01:00
gingerBill 0e71e93b22 Remove unused import 2024-08-24 14:51:28 +01:00
gingerBill 61b3af5b08 MemFree as a procedure group for both rawptr and cstring 2024-08-24 14:51:05 +01:00
gingerBill 19b95349a6 Use fmt.caprintf directly 2024-08-24 14:47:33 +01:00
gingerBill d0eaf7642d Add intrinsics.type_has_shared_fields 2024-08-24 14:36:18 +01:00
gingerBill eb799393d5 Fix -vet-tabs issues 2024-08-24 13:56:41 +01:00
gingerBill 8ba87e01bd Improve parse_enforce_tabs usage 2024-08-24 13:56:30 +01:00
gingerBill daccd72162 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-08-24 13:36:51 +01:00
gingerBill 8b248673c1 Fix #4105 2024-08-24 13:36:43 +01:00
Jeroen van Rijn faec52623d Merge pull request #4128 from gordonshamway23/mini_fix_in_image
Added missing slice advancing.
2024-08-24 14:23:42 +02:00
gingerBill b6d9a0c32e Manually implement tail-recursion for parse_if_stmt 2024-08-24 13:16:55 +01:00
gingerBill a4cc207022 Add a recursion depth limit for #3987 with a consideration to use a switch statement or refactor the code to not use a large if-else chain 2024-08-24 12:59:17 +01:00
gingerBill 683dde1fa0 Disallow labelled branches in defer - fix #3960 2024-08-24 12:47:29 +01:00
gingerBill ca4d91a8a3 Fix #4079 2024-08-24 12:26:41 +01:00
gingerBill 65543b993f Merge pull request #4130 from fusion32/fix-ambiguous-generic-type-names
fix ambiguous generic type names
2024-08-24 11:50:02 +01:00
gingerBill 00fb60d3d9 #4115 Add Suggestion: 'typeid_of(T)' 2024-08-24 11:48:32 +01:00
gingerBill 68a83abcd6 #4119 Add error when doing {.A | .B} instead of {.A, .B} with a suggestion to do surround it in parentheses to make it clear it is intended 2024-08-24 11:44:59 +01:00
gingerBill 4458ca4585 Fix #4126 2024-08-24 11:40:02 +01:00
fusion32 5ef8a092f6 fix wrong exact value kind comparison 2024-08-23 17:50:27 -03:00
fusion32 c969bee86d fix ambiguous generic type names 2024-08-23 17:18:10 -03:00
gordonshamway23 426367c522 Added missing slice advancing. 2024-08-23 21:28:59 +02:00
Laytan Laats d410281766 os2: do read_entire_file in parts if the file size is 0 2024-08-23 20:25:47 +02:00
Laytan Laats ce53805d94 os2: fix read_entire_file wrong slice end variable 2024-08-23 20:25:19 +02:00
Laytan Laats 963e8544f4 os2: CLOEXEC the fds from pipe for posix implementation 2024-08-23 20:25:05 +02:00
Laytan Laats c2a7c29ce8 os2: fix using uuid as process handle for darwin, once it goes zombie it changes 2024-08-23 20:24:06 +02:00
Laytan b3f22133f3 Merge pull request #4123 from laytan/more-core-orca-support
orca: implement core:time and core:log
2024-08-23 18:47:00 +02:00
Laytan Laats caef37bc18 orca: implement core:time and core:log 2024-08-23 18:25:10 +02:00
gingerBill 574dc5efe6 Merge pull request #4120 from laytan/posix-process
os2: process API for Darwin and most of it for BSDs
2024-08-22 22:51:48 +01:00
Laytan Laats a66520ba57 os2: process API for Darwin and most of it for BSDs 2024-08-22 23:07:24 +02:00
Laytan Laats b9043db434 os2: make platform error more ergonomic by making it an alias 2024-08-22 22:59:13 +02:00
Laytan Laats 58e5078b66 add riscv to simd.IS_EMULATED 2024-08-22 14:17:45 +02:00
gingerBill 70932dc478 Merge pull request #4089 from laytan/riscv64
add support for linux_riscv64 and freestanding_riscv64
2024-08-22 11:20:03 +01:00
Jeroen van Rijn a8bc6f08a9 Merge pull request #4116 from Kelimion/article
Add table-driven (in)definite article to some errors.
2024-08-21 18:51:43 +02:00
Jeroen van Rijn 07aedb0b89 , 2024-08-21 18:42:11 +02:00
Thomas la Cour 171d917b7e odin manifest file 2024-08-21 16:26:10 +02:00
Laytan 63cd9a031a fix variadic parameter with default value error check 2024-08-21 15:11:16 +02:00
gingerBill c77e8ca401 Fix tests 2024-08-21 14:06:04 +01:00
gingerBill 58e811eea5 Merge pull request #3962 from Feoramund/regex
Add `core:text/regex`
2024-08-21 13:55:11 +01:00
Laytan c0125f3192 correct the riscv64 stat structs 2024-08-21 14:41:23 +02:00
Jeroen van Rijn 1bcc074223 dash 2024-08-21 14:18:12 +02:00
gingerBill e7b8e61c68 Merge pull request #4106 from yeongjukang/master
core:sys/linux - implement clock_settime, clock_getres and clock_nanosleep
2024-08-21 09:41:14 +01:00
Yeongju Kang bbe4c32e32 changed signature of clock_getres 2024-08-21 08:25:14 +09:00
Laytan 0d39f52b4d Merge pull request #4117 from yay/vet-tabs
A couple of foundation binding. Vet tabs.
2024-08-21 01:16:30 +02:00
Vitalii Kravchenko 14169ae5b4 A couple of foundation binding. Vet tabs. 2024-08-21 00:09:09 +01:00
Jeroen van Rijn 6b4b0cea5d Add table-driven (in)definite article to some errors. 2024-08-20 22:13:31 +02:00
Laytan 85a33a1c9b add constant_log2 to intrinsics file 2024-08-20 19:14:50 +02:00
Laytan 8f2d3dc955 fix i128 division? 2024-08-20 19:01:09 +02:00
Jeroen van Rijn daa0779c01 Rewrite compound_to_time without using i128. 2024-08-20 18:50:05 +02:00
Laytan d7e81e86f5 Merge pull request #4110 from andradei/termios-linux
Add support for Linux on os/sys/posix termios.
2024-08-20 17:23:53 +02:00
Laytan 06fb500dfe make sure net.Network_Error is of size 8 2024-08-20 15:52:07 +02:00
Jeroen van Rijn 5ef58049dc Merge pull request #4114 from it-a-me/master
fix wiki link in the README.md
2024-08-20 14:27:47 +02:00
Laytan Laats 5b22bfa2b7 unify LB_ABI_INFO and LB_ABI_INFO_CTX 2024-08-20 14:07:47 +02:00
Laytan ca6ef95b03 add support for linux_riscv64 and freestanding_riscv64 2024-08-20 14:06:40 +02:00
it-a-me 53500699a9 README.md: Fix wiki link 2024-08-19 23:00:26 -07:00
Jeroen van Rijn 29838da782 Merge pull request #4111 from RoryO/simd-typo
fix simd var typo
2024-08-20 00:52:37 +02:00
Rory OConnell 97795ff3a2 fix simd var typo 2024-08-19 15:50:42 -07:00
Isaac Andrade 6df51b42a8 Fix termios NCCS size on linux. 2024-08-19 15:32:55 -06:00
Isaac Andrade 3228178d87 Add support for Linux on os/sys/posix termios. 2024-08-19 14:56:37 -06:00
Jeroen van Rijn 3fc1f6f1cd Merge pull request #4101 from Yawning/feature/index-byte-tweaks
core/bytes: Tweak `index_byte`/`last_index_byte`
2024-08-19 20:43:37 +02:00
gingerBill 2999c02f65 Fix random typo 2024-08-19 16:33:17 +01:00
gingerBill 9d7ab8d5ca Add strings.contains_space 2024-08-19 16:31:03 +01:00
gingerBill 2a0785037b Fix switch val in ptr 2024-08-19 12:19:45 +01:00
Yawning Angel 9e65e229d0 core/bytes: Tweak index_byte and last_index_byte
- Assume unaligned loads are cheap
- Explicilty use 256-bit or 128-bit SIMD to avoid AVX512
- Limit "vectorized" scanning to 128-bits if SIMD is emulated via SWAR
- Add a few more benchmark cases
2024-08-19 11:40:36 +09:00
Jeroen van Rijn 34a9e20531 Merge pull request #4108 from Feoramund/remove-deprecated-testing-log
Remove deprecated `log` procs from `core:testing`
2024-08-19 04:19:22 +02:00
Feoramund 0fa24ac3c4 Remove deprecated log procs from core:testing 2024-08-18 21:30:32 -04:00
Jeroen van Rijn 17eb0b5ee0 Merge pull request #4107 from Feoramund/add-digit-count
Add `core:math.count_digits_of_base`
2024-08-19 02:36:05 +02:00
Feoramund b49b80bdf9 Add test for count_digits_of_base 2024-08-18 20:14:14 -04:00
Feoramund 2906f2aa7e Add core:math.count_digits_of_base 2024-08-18 20:14:14 -04:00
Yeongju Kang f96991364a implement clock_settime, clock_getres and clock_nanosleep 2024-08-19 08:53:07 +09:00
Laytan 359a212a78 Merge pull request #4104 from laytan/find-llvm-config-through-brew
query brew for llvm-config location if possible
2024-08-19 00:41:06 +02:00
Laytan Laats ea7e8f075d query brew for llvm-config location if possible 2024-08-19 00:02:14 +02:00
gingerBill d99a6ad003 Add suggestion for ~uint(0) if cast(uint)-1 is done 2024-08-18 22:52:57 +01:00
gingerBill 95c3b8a8de Move assert to else branch 2024-08-18 22:45:26 +01:00
Laytan Laats ae41779366 remove redundant & 2024-08-18 21:10:21 +02:00
Laytan bb3f848b4a Merge pull request #4103 from laytan/wait-shared-on-macos-10-15
UL_COMPARE_AND_WAIT_SHARED is macOS 10.15+
2024-08-18 19:38:52 +02:00
gingerBill a51b9c6fb0 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-08-18 18:37:45 +01:00
gingerBill 8e52a52580 Cache the paddding filler type 2024-08-18 18:37:40 +01:00
Laytan Laats b7b3ada3b1 UL_COMPARE_AND_WAIT_SHARED is macOS 10.15+ 2024-08-18 19:31:52 +02:00
Laytan 9a895a318c Merge pull request #4102 from laytan/wasm-lshrti3
Implement lshrti3 on wasm
2024-08-18 17:18:05 +02:00
Laytan Laats b2e64b7ce0 implement lshrti3 on wasm 2024-08-18 17:09:57 +02:00
Yawning Angel 7020e9b66a core/simd: Add IS_EMULTATED so there is one place to look for potatos 2024-08-18 22:52:39 +09:00
gingerBill f49ebae956 Correct lbAddr_SoaVariable logic 2024-08-18 12:37:15 +01:00
gingerBill 0e82a46047 Fix #3999 2024-08-18 12:35:25 +01:00
gingerBill c4e0cbcd87 Fix #4005 2024-08-18 12:21:35 +01:00
gingerBill f82bf6cd42 Fix #4022 2024-08-18 12:13:52 +01:00
gingerBill 60b2979cfd Fix #4024 2024-08-18 12:10:46 +01:00
gingerBill 17740966e5 Fix #4040 2024-08-18 12:06:58 +01:00
gingerBill 5c06fcd346 Fix #4064 2024-08-18 12:00:27 +01:00
gingerBill 22a82e73d6 Fix #3976 2024-08-18 11:45:27 +01:00
Jeroen van Rijn bbb5593f87 Merge pull request #4098 from jolson88/raygui/vertical-text-alignment
(raygui) Restores vertical text alignment broken after 4.0 migration
2024-08-17 22:29:38 +02:00
Jason Olson d00057c803 Add missing trailing comma 2024-08-17 13:23:42 -07:00
Jason Olson acfd9dcd1b Restores vertical text alignment broken after 4.0 migration
A series of changes between raygui 3.6 and 4.0 were that various text box
properties were moved from the text box specific properties up into the
extended default control properties. This change corrects the various
property enums to match the raygui 4.0 API.

One additional aspect of this change was rolling back a previous commit
made to this vendor file that changed the signature of GuiSetStyle and
GuiGetStyle from using a c.int as property value to a more strongly-defined
GuiControlProperty enum. Unfortunately, this breaks the raygui API by
disallowing the use of various control-specific extended properties due to
how the enums are built.
2024-08-17 12:35:50 -07:00
Jeroen van Rijn 9553bc3689 If missing type is newline, print "newline", not \n
Turns:

W:/Odin/bug/bug.odin(3:27) Syntax Error: Expected a type, got '
'
        Storage :: distinct map[]

Into:

W:/Odin/bug/bug.odin(3:27) Syntax Error: Expected a type, got newline
        Storage :: distinct map[]
2024-08-17 17:25:52 +02:00
Jeroen van Rijn ebbb70f11d Error if missing map key type
Fixes #4096
2024-08-17 17:12:27 +02:00
Laytan Laats 142bda2804 posix: start on process API 2024-08-17 15:48:01 +02:00
Jeroen van Rijn 478f529744 Merge pull request #4094 from amad00r/fix-nil-logger
Fix log unnecessary allocations
2024-08-17 01:50:13 +02:00
gingerBill 536a342873 Merge pull request #4092 from laytan/fix-open-bindings
fix `open` bindings
2024-08-17 00:22:46 +01:00
Amadeu Moya 43dc7704a5 Fix log unnecessary allocations 2024-08-17 00:37:01 +02:00
Laytan Laats e8933e43ec add haiku to unsupported time file 2024-08-16 23:18:59 +02:00
Laytan Laats f7d7d65bc0 fix open bindings
`open` specifies the `mode` argument as vararg (presumably to make it
optional). varargs actually have rules about casting, in this case the
rule that any integer arg of size <= 4 has to be casted to `i32` before
passing it.

Not doing that implicit cast makes the permissions wrong or not apply at
all.
2024-08-16 22:54:53 +02:00
Jeroen van Rijn 970dc7a1f2 Merge pull request #4091 from Feoramund/fix-darwin-os-open
Check if file open-mode is `O_CREATE` on Darwin before forcing chmod
2024-08-16 20:31:22 +02:00
Feoramund a07878be71 Check if file open-mode is O_CREATE on Darwin before forcing chmod
Fixes #4087
2024-08-16 14:08:55 -04:00
Jeroen van Rijn 14e207088a Merge pull request #4088 from Kelimion/benchmark
Improve benchmarks.
2024-08-16 17:16:59 +02:00
Jeroen van Rijn 6c46c9e04b Improve benchmarks. 2024-08-16 17:00:16 +02:00
gingerBill 40b8150a23 Minor clean ups 2024-08-16 12:47:23 +01:00
gingerBill 31bb3dc4f0 Merge pull request #3971 from jasonKercher/os2-process-linux
os2 process linux implementation
2024-08-16 12:38:27 +01:00
gingerBill 65ce7687d7 Merge pull request #4004 from Skytrias/orca-odin-bindings
Add autogenerated orca bindings and macros from laytan
2024-08-16 12:37:36 +01:00
Laytan 6fc39c1b5d Merge pull request #4075 from yay/more-foundation-bindings
More Foundation bindings.
2024-08-16 13:08:15 +02:00
jason 07a9c69714 update core:filepath's clean, join and split_list to return optional Allocator_Errors 2024-08-16 01:48:27 -04:00
Vitalii Kravchenko 004036dc59 More Foundation bindings. 2024-08-16 00:00:29 +01:00
Laytan d91fa162d8 Merge pull request #3280 from beaumccartney/shm_syscalls
add shm_open and shm_unlink syscalls for darwin
2024-08-15 17:08:41 +02:00
gingerBill 6e91f6ab31 Merge pull request #4081 from DerTee/master
fix error handling in os2.read_entire_file_from_file()
2024-08-14 22:12:06 +01:00
gingerBill b16d5198a3 Merge pull request #4082 from FourteenBrush/master
Fix 'odin [run|test] --' giving a compiler out of bounds
2024-08-14 22:11:55 +01:00
FourteenBrush 12813e5d48 Fix 'odin [run|test] --' giving a compiler out of bounds 2024-08-14 21:37:40 +02:00
DerTee 6422e49255 fix error handling in os2.read_entire_file_from_file()
even when an error in file_size() happened, os2.ERROR_NONE was returned
2024-08-14 17:30:02 +02:00
Jeroen van Rijn f7234e2ed3 Allow ODIN_TEST_LOG_LEVEL override when -debug. 2024-08-14 16:29:51 +02:00
gingerBill e810c3eace Merge pull request #4012 from laytan/posix
core:sys/posix and core:os/os2 based on it (for darwin, netbsd, freebsd and openbsd)
2024-08-14 15:10:31 +01:00
gingerBill 18b6af1858 Minor clean up of comments 2024-08-14 14:15:20 +01:00
gingerBill 03dd38f203 Minor changes to vendor:ENet 2024-08-14 14:09:36 +01:00
gingerBill eb6f2078cf Add fmt:"v,extensions_count" tags to many struct fields 2024-08-14 14:03:41 +01:00
gingerBill df61096317 Improve doc comments for vendor:ggpo 2024-08-14 13:55:25 +01:00
gingerBill 8abe054665 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-08-14 13:02:28 +01:00
gingerBill 324d9c2284 Fix doc writer bug caused by using an iterator rather than a for loop 2024-08-14 13:02:23 +01:00
Laytan Laats f657b4cc0c time: use assert_contextless in wasi implementation 2024-08-14 13:27:58 +02:00
gingerBill c98c95fcf0 Add require_results and change some of the wrapper to return a slice 2024-08-14 11:29:23 +01:00
gingerBill fd5376ba88 Allow @(require_results) on foreign blocks 2024-08-14 11:28:49 +01:00
gingerBill 78fa675c1a Add assert_contextless, panic_contextless, unimplemented_contextless 2024-08-14 11:18:24 +01:00
gingerBill 4c19f507ff Merge pull request #4074 from odin-lang/vendor/box2d
`vendor:box2d`
2024-08-14 11:15:34 +01:00
gingerBill 651122e9db Fix foreign import paths 2024-08-14 11:01:54 +01:00
gingerBill d1e114742e Add deprecated and require_results attributes to math_functions.odin 2024-08-14 10:55:40 +01:00
Laytan 29a6959a56 Merge pull request #2977 from jakubtomsu/disallow-variadic-param-default
Report error when a variadic procedure parameter has a default value
2024-08-14 11:55:09 +02:00
gingerBill 491def9d5b Fix paths for amd64 targets 2024-08-14 10:50:53 +01:00
gingerBill 427c48221d Clean up foreign import code for library path determination 2024-08-14 10:28:07 +01:00
gingerBill 1c97739ca3 Merge branch 'vendor/box2d' of https://github.com/odin-lang/Odin into vendor/box2d 2024-08-14 10:18:41 +01:00
gingerBill 0b26115805 Improve presentation 2024-08-14 10:18:36 +01:00
gingerBill 1c8672ac6c Merge pull request #4078 from funkkiy/fix-rodata-index
Error if assigning to `rodata` variable with index
2024-08-14 09:41:35 +01:00
jason 0f052dbde7 os2/process_linux: improve error handling, use pidfd where possible, remove usage of fmt 2024-08-14 00:45:25 -04:00
Davi 4bb51249d1 Error if assigning to rodata variable with index 2024-08-13 23:28:34 -03:00
Laytan Laats e29f0a0f40 os2: dup the file descriptor before fdopendir 2024-08-14 01:45:24 +02:00
Laytan Laats f837e35f4b os2: fix bad free for posix file closure 2024-08-14 01:45:24 +02:00
Laytan Laats 61ee2efa35 os2: just use runtime._heap_allocator_proc instead of a copy for posix 2024-08-14 01:45:24 +02:00
Laytan Laats e94c4e1e18 posix: remove the is_temp things that prevented use-after-frees
https://github.com/odin-lang/Odin/commit/d0709a7de21efded4625167dbff4a7dd13d561b4
fixes those another way.
2024-08-14 01:45:24 +02:00
Laytan Laats b07d0b38b1 os2: improve absolute/full path handling for posix 2024-08-14 01:45:23 +02:00
Laytan Laats a73677d21a os2: nice != priority 2024-08-14 01:44:37 +02:00
Laytan Laats 67ea7bb65a posix: address some freebsd feedback 2024-08-14 01:44:37 +02:00
Laytan Laats 175f5b0bb1 os2: don't rely on PATH_MAX in posix read_directory implementation 2024-08-14 01:44:37 +02:00
Laytan Laats 939ba4cf08 os2: fix leak and always close directory 2024-08-14 01:44:37 +02:00
Laytan Laats f00f68ef6f posix/os2: fix test and add back in removed temp guard 2024-08-14 01:44:37 +02:00
Laytan Laats de9abe1f7b os2: skip . and .. in read dir 2024-08-14 01:44:37 +02:00
Laytan Laats bd808f9ec6 os2: fix wiping results with temp allocator guard 2024-08-14 01:44:37 +02:00
Laytan Laats 7474db6a34 os2: fix lstat logic 2024-08-14 01:44:37 +02:00
Laytan Laats 00eb702c4a os2: implement the iterator based read directory 2024-08-14 01:44:37 +02:00
Laytan Laats ea5783c2ac os2: fixes after rebasing 2024-08-14 01:44:37 +02:00
Laytan Laats e05fddc001 posix: fix file type checks in stat 2024-08-14 01:44:37 +02:00
Laytan Laats 406e60f5dd posix: revert change to os that was done for testing 2024-08-14 01:44:37 +02:00
Laytan Laats 5115aee23f posix: actually fix netbsd test 2024-08-14 01:44:37 +02:00
Laytan Laats 72220a855f posix: fix write error check 2024-08-14 01:44:37 +02:00
Laytan Laats 4a61bac100 posix: fix test on netbsd 2024-08-14 01:44:37 +02:00
Laytan Laats 726891588f posix: more tests 2024-08-14 01:44:37 +02:00
Laytan Laats 2a5ceff667 posix: move doc 2024-08-14 01:44:37 +02:00
Laytan Laats 9e2c5acb9d os2: fix bit checks 2024-08-14 01:44:37 +02:00
Laytan Laats 7c9ca60ff0 mem/virtual: support the BSDs 2024-08-14 01:44:37 +02:00
Laytan Laats 379cd6fe66 os2: cleanup 2024-08-14 01:44:37 +02:00
Laytan Laats ffff3c3c88 posix: fix foreign import of dl for free/netbsd 2024-08-14 01:44:37 +02:00
Laytan Laats a4d459f651 os2: initial implementation for Darwin&BSDs, process API is only thing incomplete 2024-08-14 01:44:37 +02:00
Laytan Laats ff0ca0bd53 os2: make config directory on darwin also ~/.config, it is the proper place 2024-08-14 01:44:37 +02:00
Laytan Laats 07b9f7d280 os2: fix read_entire_file bad logic 2024-08-14 01:44:37 +02:00
Laytan Laats 9f80191f60 os2: add default make_directory permissions 2024-08-14 01:44:37 +02:00
Laytan Laats efe68c2e24 posix: add package 2024-08-14 01:44:35 +02:00
Laytan 3847d03248 Merge pull request #3281 from erjohnson/patch-1
Update mem doc example formatting
2024-08-14 00:10:03 +02:00
Laytan Laats bb54a0a972 fix whitespace 2024-08-14 00:08:46 +02:00
Laytan Laats ac68a9d52c update MacOS releases 2024-08-14 00:00:50 +02:00
Laytan Laats d4d46df2fc box2d: add build script and MacOS libraries 2024-08-13 22:15:31 +02:00
gingerBill 660b6ff0f1 Add vendor:box2d to examples/all 2024-08-13 17:08:31 +01:00
gingerBill 9ccaca7f1a Minor style change 2024-08-13 17:01:55 +01:00
gingerBill 926c419ef8 Change .lib to be /MT compatible; Fix comments 2024-08-13 16:58:35 +01:00
gingerBill 22b32ab0fa Use intrinsics.has_target_feature 2024-08-13 16:35:28 +01:00
gingerBill 40361f877e Add libraries for windows 2024-08-13 16:34:31 +01:00
gingerBill f2ba3da895 Create bindings for box2d
Currently missing lib binaries
2024-08-13 16:18:24 +01:00
Laytan 55be3e60a0 Merge pull request #3125 from marcs-feh/master
sys/linux: Add binding to ioctl syscall + standard fd constants.
2024-08-13 15:30:50 +02:00
gingerBill 62911539cd Minor style change 2024-08-13 14:27:25 +01:00
Laytan c7af8af76a Update core/sys/linux/sys.odin 2024-08-13 15:22:35 +02:00
gingerBill e3d5bbe62c Merge pull request #4065 from laytan/fix-max-alignments
fix max alignments
2024-08-13 14:09:45 +01:00
gingerBill 2584c6bcd7 Merge pull request #4069 from zen3ger/1738-aliased-procedure-resolution
Fix alias handling of procedures
2024-08-13 14:07:51 +01:00
gingerBill 66d3082a9a Merge pull request #4056 from laytan/re-enable-runtime-wasm-stuff
re-enable some wasm things in runtime
2024-08-13 14:04:19 +01:00
gingerBill 09a07bd7e0 Merge pull request #4055 from laytan/time-wasi
time: wasi implementation
2024-08-13 14:03:02 +01:00
gingerBill 848f7e117f Merge pull request #4050 from IllusionMan1212/egl-procs
vendor/egl: added a few more egl procedures and constants
2024-08-13 14:01:20 +01:00
gingerBill d93364ce52 Merge pull request #4049 from IllusionMan1212/xrandr-xinput-xfixes
vendor/x11: added a few procedures for xrandr, xinput, and xfixes
2024-08-13 14:00:08 +01:00
gingerBill 4c4f24b5f4 Merge pull request #4041 from zen3ger/1079-parametric-struct-from-other-package
Check if procedure parameter type declares polymorphic args
2024-08-13 13:59:06 +01:00
Jeroen van Rijn 069ad446cd Merge pull request #4070 from Feoramund/test-runner-mem-fail-as-error
Let memory failures be errors in the test runner
2024-08-13 13:50:46 +02:00
Jeroen van Rijn 02b4bb8491 Merge pull request #4072 from laytan/fix-32-bit-math-round
fix type hint propagation for shift
2024-08-13 00:34:19 +02:00
Laytan Laats 2808ecc5b6 remove panic workaround 2024-08-12 23:48:36 +02:00
Laytan Laats a1d518442a fix type hint propogation for shift
Fixes #3856
2024-08-12 23:39:07 +02:00
Jeroen van Rijn 0d916a659e Merge pull request #4053 from Feoramund/fix-gitignore
Fix `.gitignore`
2024-08-12 21:34:26 +02:00
Feoramund 3a32250b80 Add .gitignore for tests directory 2024-08-12 15:16:52 -04:00
Jeroen van Rijn 053e65a1c8 Merge pull request #4071 from andreas-jonsson/andreas-jonsson-patch-2
Use another URL for pkgsrc on CI
2024-08-12 20:58:41 +02:00
Andreas T Jonsson 7af0291c7d Try use another arch URL for pkgsrc 2024-08-12 20:27:20 +02:00
Feoramund 0af025d056 Add explicit copyright info to core:testing 2024-08-12 14:16:22 -04:00
Roland Kovacs 9eb7186cda Fix alias handling of procedures
An incorrect memmove when overriding entities caused multiple ones to point to
the same procedure with incomplete variant data, resulting in later hiting a
compiler assertion.

Introduced delayed type checking for procedure aliases, as it was masked by
the previous error in the override logic.
2024-08-12 19:52:42 +02:00
Laytan d68cc41782 Merge pull request #4068 from laytan/fix-read-dir-closing-given-fd
fix `os.read_dir` closing the given file descriptor
2024-08-12 19:23:48 +02:00
Laytan fb09ec06d3 Merge pull request #4066 from Tetralux/fmt-bitfields-pointers
[fmt] Add bit fields to the pointer printing logic
2024-08-12 19:14:15 +02:00
Laytan Laats a4ac3cc6e8 fix os.read_dir closing the given file descriptor 2024-08-12 18:51:27 +02:00
Tetralux 4f56822204 [fmt] Add bit fields to the pointer printing logic
core:fmt prints pointers to structs as `&StructName{ ... }` but `bit_field`s are currently printed
the same as rawptrs (`0xAABBCCDDEEFF` only).

This commit changes that so they behave the same as structs and unions.
2024-08-12 16:25:22 +00:00
Laytan Laats f22ff21039 fix max alignments 2024-08-12 17:05:51 +02:00
Laytan b71e0c2e36 Merge pull request #4059 from laytan/loop-write-entire-file
loop write_entire_file to write more than MAX_RW
2024-08-12 13:54:46 +02:00
Laytan fd9a008e1e Merge pull request #4058 from laytan/fix-cvararg-bitset
fix c_vararg bit_set
2024-08-12 13:54:28 +02:00
Laytan 450fc3ec77 Merge pull request #4060 from laytan/support-field-tag-bitsets-in-core-odin
core/odin: support field tags on bit_field fields
2024-08-12 13:53:33 +02:00
Laytan 0a118a14ab Merge pull request #4061 from laytan/fix-fmt-maybe-pointer-detection
fix `type_info_union_is_pure_maybe` only working with regular pointers
2024-08-12 13:53:17 +02:00
Feoramund f42a22369e Fix wrong define name in test runner log messages 2024-08-11 23:01:28 -04:00
Feoramund 675add4d90 Optionally treat memory failures as errors in the test runner
Enable with `-define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true`.
2024-08-11 22:59:20 -04:00
Jeroen van Rijn 1761802330 Merge pull request #4062 from laytan/fix-switch-over-internal-pointer-union
fix type switching over internal pointer union
2024-08-12 00:25:47 +02:00
Laytan Laats 99aa0d3a35 fix type switching over internal pointer union
Fixes #3947
2024-08-12 00:02:05 +02:00
Laytan Laats dec97cbddb fix type_info_union_is_pure_maybe only working with regular pointers
Fixes #3996
2024-08-11 21:07:21 +02:00
Laytan Laats f0840ed24e core/odin: support field tags on bit_field fields
Fixes #4044
2024-08-11 20:59:54 +02:00
Laytan b9e68ee3c1 Merge pull request #4054 from Feoramund/zlib-reverse-bits
Use `intrinsics.reverse_bits` in `core:compress/zlib`
2024-08-11 17:42:28 +02:00
Laytan Laats d6336e7252 add orca to examples/all for docs 2024-08-11 17:35:19 +02:00
Laytan Laats c6a0d302b3 loop write_entire_file to write more than MAX_RW
Fixes #4042
2024-08-11 17:27:54 +02:00
Laytan Laats 26fa3aca44 fix copy-paste error in make docs 2024-08-11 17:09:26 +02:00
Laytan Laats e3f375afd8 fix c_vararg bit_set
Fixes #4051
2024-08-11 17:00:49 +02:00
Jeroen van Rijn 8a67221bd4 Merge pull request #4057 from asibahi/patch-1
typo fix
2024-08-11 13:35:10 +02:00
Abdul Rahman Sibahi 67251ad5b8 typo fix 2024-08-11 14:30:48 +03:00
Laytan 938e81e341 sys/orca: add missing using 2024-08-10 23:59:51 +02:00
Laytan Laats f5fe0de0fd add clarity for diverging mismatch error 2024-08-10 23:34:35 +02:00
Laytan Laats 7fd8b9c55b re-enable some wasm things in runtime
No idea why the floattidf procs are bodged to return 0, does somebody
know? I have just enabled the original codepath, if nobody knows I
suggest just enabling it and see if we get complaints, it works on all
wasm stuff I tried.

The linkage being set to "internal" instead of "strong" is actually
causing problems in my projects which is what prompted looking at this
in the first place, some of these functions were actually needed but not
added/used because they had internal linkage. This only happens on
bigger projects (or just when using f16?).

Unfortunately `git blame` gave me this generic commit: https://github.com/odin-lang/Odin/commit/94bad4d7861c78b9e7191ec0c3114861a1536d5c#diff-fb9f42022cb95efa59d16813546b8cb310234428c85edfabf09b1425c9dc46af
2024-08-10 23:10:30 +02:00
Laytan Laats a2cd763dbb time: wasi implementation 2024-08-10 23:01:31 +02:00
Feoramund cf8f6afeff Use intrinsics.reverse_bits in core:compress/zlib 2024-08-10 15:29:44 -04:00
Feoramund afbdc78f85 Fix .gitignore
- Remove all-encompassing `benchmark`
- Add exception for `core:simd/x86`
2024-08-10 15:16:12 -04:00
Laytan Laats 6918d8aaa6 possibly fix init_core_type_info race condition 2024-08-10 21:03:40 +02:00
Jeroen van Rijn e226d37803 Merge pull request #4023 from Feoramund/simd-index
Vectorize `index_byte`
2024-08-10 21:01:41 +02:00
Feoramund 4f816aabb3 Use SIMD_SCAN_WIDTH constant in core:bytes test 2024-08-10 13:54:12 -04:00
Laytan Laats d98f848247 fix debug compiler build message not ending output with a newline 2024-08-10 19:07:30 +02:00
Jeroen van Rijn 1242b6e82f Improve slice.binary_search_by 2024-08-10 18:26:59 +02:00
Jeroen van Rijn 9759d56c81 Merge pull request #4003 from Yawning/feature/crypto-improvements
core:crypto: Various improvements
2024-08-10 17:17:00 +02:00
Laytan d73ad8eb1e Merge pull request #4046 from laytan/cbor-fixes
encoding/cbor: various fixes
2024-08-10 17:02:41 +02:00
jason a52f7c129f stop trying to handle child pipe read errors in process_start 2024-08-10 09:13:07 -04:00
jason e54d6e5a11 Ignore process_open errors in process_start. This enforces a contract
with the user that any process returned without error must eventually be
waited on.
2024-08-10 09:03:34 -04:00
jason f7a73b9555 fix error handling; close read end of the child pipe instead of the write end twice 2024-08-10 08:55:40 -04:00
Feoramund 9d2b4b2f03 Simplify core:bytes test 2024-08-10 08:13:22 -04:00
Feoramund 5d5addd48f Set SIMD_SCAN_WIDTH based on size_of(uintptr) 2024-08-10 07:43:14 -04:00
Feoramund c69fa87d53 Merge core:simd/util into core:bytes 2024-08-10 07:17:03 -04:00
Jeroen van Rijn bf53d2f6db Fix time.precise_clock on 32-bit platforms. 2024-08-10 12:44:40 +02:00
Jeroen van Rijn d267735d99 Fixed time.precise_clock 2024-08-10 12:35:58 +02:00
IllusionMan1212 554b0e5bf7 vendor/x11: added a few procedures for xrandr, xinput, and xfixes 2024-08-10 12:06:52 +02:00
Yawning Angel ba1ad82c2b core/crypto/aead: Initial import 2024-08-10 18:32:37 +09:00
Yawning Angel 38aea1f907 core/crypto/aes,chacha20poly1305: Add require_results to open 2024-08-10 18:32:37 +09:00
Yawning Angel b381791f42 core/crypto/chacha20: Change API terminology to be consistent with AES 2024-08-10 18:32:37 +09:00
Yawning Angel 14ceb0b19d core/crypto/chacha20poly1305: Support AEAD_XChaCha20_Poly1305
IETF-draft flavor (32-bit counter) though this makes no practical
difference.
2024-08-10 18:32:37 +09:00
Yawning Angel 8efc98ce90 core/crypto/chacha20poly1305: Change the interface to match GCM 2024-08-10 18:32:37 +09:00
Yawning Angel 1f3107e693 core/crypto/chacha20: Use 128-bit/256-bit SIMD 2024-08-10 18:32:37 +09:00
Yawning Angel 708f053fe6 core/crypto/aes: Use NIST terminology for the IV 2024-08-10 18:32:37 +09:00
Yawning Angel ac7f44b1b8 core/crypto/aes: Slightly tweak GHASH to look less spooky 2024-08-10 18:32:37 +09:00
Yawning Angel b1d6e4139e core/crypto/aes: Disable bounds checking for the CTR loops 2024-08-10 18:32:37 +09:00
Yawning Angel dfc4df9807 core/crypto/_aes/hw_intel: Use a constant for the PSHUFB indicies 2024-08-10 18:32:37 +09:00
Yawning Angel b9293334ca core/crypto/ed25519: Rename a member for clarity
This better matches the spec.
2024-08-10 18:32:37 +09:00
Yawning Angel b68311d777 core/crypto/hash: Make the _to_buffer routines return the hash slice
Quality of life improvement.
2024-08-10 18:32:37 +09:00
Yawning Angel c0f9655ec4 test/core/crypto: Minor changes to AES related tests
- Test against the non-standard GCM nonce length vectors
- Fix the CTR mode test to match the comment

Correctness was fine without this change.
2024-08-10 18:32:37 +09:00
IllusionMan1212 7875e4a1ab vendor/egl: added a few more egl procedures and constants 2024-08-10 10:21:03 +02:00
Jeroen van Rijn be7a1f671c Revert "Add time.precise_clock_from_time + time.precise_clock_from_duration"
This reverts commit c9ca192f33.
2024-08-10 03:26:09 +02:00
Jeroen van Rijn c9ca192f33 Add time.precise_clock_from_time + time.precise_clock_from_duration 2024-08-10 03:23:08 +02:00
Feoramund e7e7fe766a Add test for misaligned data to core:simd/util suite 2024-08-09 18:54:04 -04:00
Feoramund 0d29cc3375 Use for x in y construct for bytes iteration
This cannot be applied to the `strings` version, as that would cause a
rune-by-rune iteration, not a byte-by-byte one.
2024-08-09 18:54:04 -04:00
Feoramund c8a62ee4ec Make simd_util index procs contextless where applicable 2024-08-09 18:54:04 -04:00
Feoramund 12dd0cb72a Simplify and make simd_util cross-platform
This new algorithm uses a Scalar->Vector->Scalar iteration loop which
requires no masking off of any incomplete data chunks.

Also, the width was reduced to 32 bytes instead of 64, as I found this
to be about as fast as the previous 64-byte x86 version.
2024-08-09 18:54:04 -04:00
Laytan Laats 912f99abc8 encoding/cbor: various fixes
- "null" is the proper way to represent the nil value in the diagnostic
  format
- hex encoding in diagnostic format was wrong
- struct keys weren't sorted the right deterministic way
2024-08-09 21:56:54 +02:00
jason baacc512e3 fix child pipe in process_start 2024-08-09 15:21:11 -04:00
Jeroen van Rijn c5ed7083d2 Disable NetBSD CI 2024-08-09 19:44:51 +02:00
Jeroen van Rijn d69e0bfa00 NetBSD vm fix. 2024-08-09 19:37:26 +02:00
Jeroen van Rijn fa6f343261 Remove unused import. 2024-08-09 19:06:50 +02:00
jason c4d43bbab0 os2 linux process_wait rework; add Sig_Child_Code to sys/linux bits 2024-08-09 09:16:44 -04:00
Jeroen van Rijn cc24d2de3e Merge pull request #3810 from Feoramund/freebsd-core-net
Port `core:net` to FreeBSD
2024-08-09 09:50:05 +02:00
Jeroen van Rijn bc6deab175 echo -> printf for build_odin.sh message 2024-08-09 09:46:45 +02:00
Laytan b5a612202f Merge pull request #4036 from laytan/master
add debug build message and align more with build.bat
2024-08-08 22:21:17 +02:00
Jeroen van Rijn 1e09ff3b2e Merge pull request #4043 from Kelimion/expect_leak_or_bad_free
Allow testing for intentional leaks in test runner
2024-08-08 21:40:17 +02:00
Jeroen van Rijn 933f9f9bd1 Enable test leak = fatal on CI. 2024-08-08 21:31:30 +02:00
Jeroen van Rijn b82cfc5f15 Fix shoco heisenleak 2024-08-08 21:15:59 +02:00
Jeroen van Rijn a05b73c632 Keep -vet happy when mem tracking is disabled. 2024-08-08 21:02:35 +02:00
Jeroen van Rijn 4d27898418 Use test runner's own tracking allocator. 2024-08-08 20:58:25 +02:00
Jeroen van Rijn 80d1e1ba82 Allow testing for intentional leaks in test runner
Adds `expect_leak_or_bad_free :: proc(t: ^T, client_test: proc(t: ^T), verifier: Memory_Verifier_Proc)`.

It sets up its own `Tracking_Allocator`, runs the `client_test`, and then calls the `verifier` procedure.
The verifier can then inspect the contents of the tracking allocator and call `testing.expect*` as sensible for the test in question.

Any allocations are then cleared so that the test runner doesn't itself complain about leaks.

Additionally, `ODIN_TEST_LOG_LEVEL_MEMORY` has been added as a define to set the severity of the test runner's memory tracker. You can use `-define:ODIN_TEST_LOG_LEVEL_MEMORY=error` to make tests fail rather than warn if leaks or bad frees have been found.
2024-08-08 20:41:32 +02:00
Roland Kovacs dda89a69bf Check if procedure parameter type declares polymorphic args
When a procedure parameter's type was declared in an imported package the type
checker correctly resolved to the parametric type, but it did not check if the
expression that refers to that type conforms to a polymorphic type declaration.

This error was not detected if the procedure was unused, since it was marked as
polymorphic, where further type check is done on instantiation.
2024-08-08 19:50:05 +02:00
Jeroen van Rijn f328929939 Merge pull request #4038 from Hyrtwol/core-sys-windows-rawinput-code
Core sys windows rawinput code
2024-08-08 18:23:02 +02:00
Thomas la Cour 3d0519fe6c trim whitespace 2024-08-08 18:05:41 +02:00
Thomas la Cour a4eeb6ed02 rawinput code 2024-08-08 18:03:59 +02:00
Jeroen van Rijn 94c62fb630 Fix typo. 2024-08-08 18:01:09 +02:00
Jeroen van Rijn a7fe9eec73 Merge pull request #4037 from Kelimion/symlink_test
Allow symlink test to work irrespective of git settings.
2024-08-08 17:56:05 +02:00
Jeroen van Rijn d93f3c63d8 Rename package to test_core_os to fit with the rest of test_* 2024-08-08 17:49:08 +02:00
Jeroen van Rijn ada3df303e Allow symlink test to work irrespective of git settings. 2024-08-08 17:46:00 +02:00
Laytan Laats 8b98fff98e add debug build message and align more with build.bat
1. if ran without choosing a build type (just `make` or
   `build_odin.sh`), print out a message about it being a debug build
2. Add `make release-native` alongside `make release_native` to align
   with `build_odin.sh release-native`
3. Only run the demo if it is a debug build (just like `build.bat`)
2024-08-08 15:33:40 +02:00
jason c3ba8fbd09 add child pipe for reporting post-fork errors 2024-08-08 08:56:29 -04:00
Jeroen van Rijn 4b9ca39522 Merge pull request #4035 from karl-zylinski/build-release-hint
Added a hint at end of build.bat about release mode when building in debug mode
2024-08-08 14:48:48 +02:00
Karl Zylinski 26633bbce6 Added a hint at end of build.bat about release mode when building in debug mode. 2024-08-08 14:15:32 +02:00
jason 9625798513 merge commit 2024-08-07 23:27:45 -04:00
Jeroen van Rijn 796feeead9 Remove LLVM copy from nightly. 2024-08-07 22:12:23 +02:00
Jeroen van Rijn 2bf055ec6e Delete empty file after access check. 2024-08-07 19:38:36 +02:00
Laytan Laats c9b69d76b0 text/edit: fix undo_state_push wrong builder check 2024-08-07 17:21:56 +02:00
Jeroen van Rijn 69a15ca5b6 Don't copy LLVM shared object on Linux
We copy the LLVM shared object when building Odin on Linux. Contrary the comment in `build_odin.sh`,
this is unnecessary, and Odin can be compiled and itself compile things just fine without this step.

This is then packaged up at release and leads to #4019 and #4033. The Linux release builds are built
on Ubuntu and not strictly supported on other Linux distributions. Building from source is preferred.
2024-08-07 14:50:45 +02:00
Laytan Laats 6fe938b946 darwin: add setAllowedFileTypes binding for open panels 2024-08-06 21:42:33 +02:00
Laytan Laats e5a478d393 wgpu: fix examples after changing color to an array 2024-08-06 21:42:33 +02:00
Feoramund 793811b219 Add simd_util to examples/all 2024-08-06 15:19:05 -04:00
Feoramund 0418d27bdf Add benchmarks for vectorized index_* procs 2024-08-06 15:19:05 -04:00
Feoramund 28c98c2e7a Add tests for vectorized index_* procs 2024-08-06 15:19:05 -04:00
Feoramund f66fcd9acb Use vectorized index_* procs in core 2024-08-06 15:19:05 -04:00
Feoramund 8deeb40e5d Add vectorized index_byte and last_index_byte 2024-08-06 15:19:01 -04:00
gingerBill 39d557bcb4 Merge pull request #4032 from Feoramund/fix-intrinsic-wording
Fix SIMD intrinsics wording
2024-08-06 20:13:10 +01:00
Feoramund e27a424f4d Swap reduce_any and reduce_all
`llvm.vector.reduce.or` will return true if any lane is true.
`llvm.vector.reduce.and` will return true if all lanes are true.
2024-08-06 14:50:34 -04:00
Feoramund 7a367c9c08 Fix documented names of a few SIMD procedures 2024-08-06 14:49:56 -04:00
Laytan 4423aac3de Merge pull request #4031 from RilleP/bit-field-closing-brace-fix
Fix missing closing brace for Bit_Field in core:odin/parser
2024-08-06 20:49:49 +02:00
gingerBill 94ded29b5f Merge pull request #4030 from Kelimion/struct_field_count
Add `reflect.struct_field_count` that returns the number of fields in a struct type
2024-08-06 18:56:24 +01:00
Rikard Petré 6a6f078186 Fix missing closing brace for Bit_Field in core:odin/parser 2024-08-06 19:48:38 +02:00
gingerBill bed18a17e6 Bodge: Improve aligned_resize logic 2024-08-06 11:22:34 +01:00
Jeroen van Rijn 17ebaffce8 Update comment. 2024-08-05 22:12:22 +02:00
Jeroen van Rijn 4902288a5a Add reflect.struct_field_count that returns the number of fields in a struct type
Example:
```odin
package struct_count_example

import "core:fmt"
import "core:reflect"
import "core:dynlib"

Foo :: struct{
	one: int,
	two: f32,
}

Bar :: struct {
	three: int,
	four:  bool,
	five:  f64,
}

Game_Api :: struct {
	init:      proc(api: ^Game_Api),
	update:    proc(api: ^Game_Api),

	using foo: Foo,
	bar:       Bar,

	// Private stuff
	reload_count: int,
	__handle:     rawptr,
}
API_PRIVATE_COUNT :: 2

game_api: Game_Api

main :: proc() {
	fmt.printfln("Game_Api, .Top:       %v", reflect.struct_field_count(Game_Api))              // 6
	fmt.printfln("Game_Api, .Using:     %v", reflect.struct_field_count(Game_Api, .Using))      // 8
	fmt.printfln("Game_Api, .Recursive: %v", reflect.struct_field_count(Game_Api, .Recursive))  // 11

	symbols_loaded, _  := dynlib.initialize_symbols(&game_api, "game.dll")
	symbols_expected   := reflect.struct_field_count(Game_Api) - API_PRIVATE_COUNT

	if symbols_loaded == -1 {
		fmt.eprintln("Couldn't load game.dll")
		return
	} else if symbols_loaded != symbols_expected {
		fmt.eprintfln("Expected %v symbols, got %v", symbols_expected, symbols_loaded)
		return
	}
}
```
2024-08-05 22:04:16 +02:00
Laytan a1c3c38f04 Merge pull request #4029 from Feoramund/fix-darwin-sigpipe-send
Prevent `SIGPIPE` on Darwin when writing to a closed `core:net` socket
2024-08-05 19:26:16 +02:00
Feoramund 4c0ab09c9a Handle EPIPE in Darwin core:net 2024-08-05 13:15:08 -04:00
Feoramund 6cc7f3b451 Add FreeBSD Accept_Error.Would_Block alias 2024-08-05 13:00:44 -04:00
Feoramund 3512d7c672 Move Darwin MSG_NOSIGNAL to core:os 2024-08-05 12:49:12 -04:00
Feoramund eba0774bf3 Prevent SIGPIPE on Darwin when writing to a closed core:net socket
Mimics behavior found on Linux implementation.
2024-08-05 12:23:09 -04:00
gingerBill 7c3461b0df Merge pull request #4028 from Kelimion/fix-4026
Fix crash if referencing import "aliased" in other file.
2024-08-05 16:57:58 +01:00
Jeroen van Rijn 2cc3795686 Merge pull request #4027 from karl-zylinski/blend-pixel-compile-fix
Fix for blend_pixel.odin in core/image/common.odin not compiling
2024-08-05 17:38:30 +02:00
Karl Zylinski b63657d293 Fix for blend_pixel.odin in core/image/common.odin not compiling 2024-08-05 17:23:58 +02:00
Jeroen van Rijn 6175efde3d Fix crash if referencing import "aliased" in other file.
Fixes #4026
2024-08-05 17:23:50 +02:00
Jeroen van Rijn 030220eb22 Merge pull request #4025 from karl-zylinski/patch-2
core/image/common.odin compile fix
2024-08-05 16:42:09 +02:00
Karl Zylinski 2d32b819dc common.odin compile fix
Fix for "Error: Prefer to separate 'where' clauses with a comma rather than '&&'"
2024-08-05 16:32:34 +02:00
gingerBill f56abf3780 Add intrinsics.masked_expand_load and intrinsics.masked_compress_store 2024-08-05 14:54:09 +01:00
gingerBill 78919f8524 Fix typos 2024-08-05 14:48:55 +01:00
gingerBill 80ea4e0aeb Remove dead code 2024-08-05 14:25:33 +01:00
gingerBill 84ac56f778 Add intrinsics.simd_masked_load and intrinsics.simd_masked_store 2024-08-05 14:08:41 +01:00
gingerBill 7e701d1677 Add intrinsics.simd_gather and `intrinsics.simd_scatter 2024-08-05 13:46:24 +01:00
gingerBill b67ed78afd add_sat -> saturating_add 2024-08-05 13:21:27 +01:00
gingerBill 90fc52c2ee Rename add_sat -> saturating_add 2024-08-05 13:19:01 +01:00
gingerBill 9a01a13914 Add simd_reduce_any and simd_reduce_all 2024-08-05 13:13:19 +01:00
gingerBill eeb92e2644 Allow cast between #simd[N]rawptr <-> #simd[N]uintptr 2024-08-05 13:06:55 +01:00
gingerBill fd06be2243 Allow swizzle to take more arguments than the original array length 2024-08-05 12:33:02 +01:00
gingerBill a06cb8ba46 Add #simd[N]rawptr support 2024-08-05 12:04:36 +01:00
Feoramund d0d4f19097 Remove debug line from test 2024-08-05 03:50:41 -04:00
Feoramund 8f5b838a07 Review manual for loops in core:text/regex 2024-08-05 03:49:29 -04:00
Feoramund ba0581ae79 Give FreeBSD access to core:net in core:flags 2024-08-05 03:05:50 -04:00
Feoramund d9404d928c Add copyright info to core:sys/freebsd 2024-08-05 03:05:50 -04:00
Feoramund fe754af13d Add new contribution notes to core:net 2024-08-05 03:05:49 -04:00
Feoramund 61e770d943 Clean up some FreeBSD core:net code 2024-08-05 03:05:43 -04:00
Feoramund 2b63684ccf Fix integer socket option values for FreeBSD 2024-08-05 02:14:41 -04:00
Feoramund 5ece6980eb Make EINVAL generic in FreeBSD Socket_Option_Error
The documentation for `setsockopt(2)` mentioned accept filters for
`EINVAL`, but I've found that it can arise for any manner of invalid
values for setting socket options.

We'll just have to leave this as a generic error.
2024-08-05 02:14:27 -04:00
Feoramund 42a2297d31 Add core:net tests specifically for FreeBSD 2024-08-05 02:08:48 -04:00
Feoramund 8de48d81ea Use common name for ENOBUFS 2024-08-05 00:30:39 -04:00
Feoramund 32fb1fb61c Add missing ECONNRESET TCP_Send_Error
This was not specifically documented in `send(2)`.
2024-08-05 00:30:39 -04:00
Feoramund 05c50561ae Set NOSIGPIPE on all core:net FreeBSD sockets 2024-08-05 00:30:39 -04:00
Feoramund 46455dd0a6 Add more socket options for FreeBSD core:net 2024-08-05 00:30:24 -04:00
Feoramund 3f9ddfe029 Clarify what umtx is 2024-08-04 22:24:55 -04:00
Feoramund 14858309f0 Add explicit license info to core:text/regex 2024-08-04 19:18:16 -04:00
Feoramund e17fc8272b Document rationale behind RegEx shorthand classes 2024-08-04 19:12:46 -04:00
Feoramund dde42f0ebc Add more documentation for core:text/regex API 2024-08-04 18:56:29 -04:00
Feoramund ca7e46d56f Add explicit test case for Capture pos 2024-08-04 18:56:29 -04:00
Feoramund 743480b1a4 Use regex.destroy for test captures 2024-08-04 18:56:29 -04:00
Feoramund 1ccb0b2558 Remove unused code 2024-08-04 18:56:29 -04:00
Feoramund babdc432e9 Move Flag_To_Letter to core:text/regex/common 2024-08-04 18:56:25 -04:00
Feoramund d3a51e208d Hide Regular_Expression values
We don't directly support printing these.

To prevent future issues being raised about the pattern being missing if
someone tries to print one, hide everything.
2024-08-04 18:40:27 -04:00
Feoramund cd8272557f Test that a RegEx Capture pos corresponds to its groups 2024-08-04 18:33:36 -04:00
gingerBill 7e0fa795e4 Just compare against nil directly if the comparator is known to be nil too 2024-08-04 21:17:58 +01:00
Feoramund 6252712363 Add missing features to regex package documentation 2024-08-04 13:21:13 -04:00
gingerBill 60bc7f53d2 Comment out open_buffered 2024-08-04 17:41:48 +01:00
gingerBill cf3c1a85ec Remove temp parameter 2024-08-04 17:36:28 +01:00
gingerBill 046f72befd Mock out open_buffered 2024-08-04 17:31:39 +01:00
gingerBill f19436fb4d Only swap if there was an arena 2024-08-04 17:17:09 +01:00
gingerBill d0709a7de2 Allow for nested temp_allocator() calls to flip between arenas on TEMP_ALLOCATOR_GUARDs 2024-08-04 17:14:24 +01:00
gingerBill f427f040fd Merge pull request #4020 from odin-lang/bill/os-errno
`os.Error` to replace `os.Errno`
2024-08-04 15:53:18 +01:00
gingerBill c078b2dd1b Add @(require_results) 2024-08-04 15:24:26 +01:00
gingerBill bf948ab8ae Add stubs for flush on platforms that didn't have it 2024-08-04 15:07:24 +01:00
gingerBill acb1ebddf6 Fix err != 0 uses 2024-08-04 15:01:04 +01:00
gingerBill 0bedd3357a Disallow err != 0 with os.Error when -strict-style is enabled 2024-08-04 14:58:12 +01:00
gingerBill 93fabf8628 Replace err != 0 with err != nil where possible 2024-08-04 14:57:25 +01:00
gingerBill fc10b781af Update core/os/os2/process.odin
Co-authored-by: Laytan <laytanlaats@hotmail.com>
2024-08-04 14:47:44 +01:00
gingerBill 6a6b5061db Update core/os/os_darwin.odin
Co-authored-by: Laytan <laytanlaats@hotmail.com>
2024-08-04 14:47:35 +01:00
gingerBill b67817517e Fix replace typo 2024-08-04 14:46:32 +01:00
gingerBill fff1d509d5 Add read_entire_file_or_err and write_entire_file_or_err 2024-08-04 14:41:55 +01:00
gingerBill e8d26c5797 Move errors to where appropriate 2024-08-04 13:41:34 +01:00
gingerBill 3d992e2704 Improve _error_string for Linux 2024-08-04 13:25:35 +01:00
gingerBill 0c5b645dde Correct EOF value 2024-08-04 13:20:33 +01:00
gingerBill cf5ec25873 Add extra cases for flush 2024-08-04 13:18:51 +01:00
gingerBill 7663a2036a Add read_at/write_at to missing platforms 2024-08-04 13:16:37 +01:00
gingerBill c32f345c68 Move error stuff to errors.odin 2024-08-04 12:55:08 +01:00
gingerBill 649b25fba6 Update the demo.odin to use nil instead of os.ERROR_NONE 2024-08-04 12:47:49 +01:00
gingerBill bdbbbf5c95 Fix typo; remove unneeded casts 2024-08-04 12:39:21 +01:00
gingerBill e8b6d15db9 Fix replace typo 2024-08-04 12:31:22 +01:00
gingerBill 5f7fef92fa Update example to use err != nil instead 2024-08-04 12:25:50 +01:00
gingerBill 66b86bc7e0 Correct os errors for darwin 2024-08-04 12:23:18 +01:00
gingerBill 5187bb68bb Hack: Convert 0 to nil 2024-08-04 12:08:52 +01:00
gingerBill 97c499dbb4 Begin mapping os.Error in the rest of the codebase 2024-08-04 11:58:04 +01:00
gingerBill 1d75a612d5 os.Errno -> os.Error 2024-08-04 11:47:23 +01:00
gingerBill 160048eaee Errno -> Error 2024-08-04 11:46:42 +01:00
gingerBill def2e2e271 Try to map to General_Error where possible 2024-08-04 11:44:45 +01:00
gingerBill 28666414bc More clean ups of ERROR_NONE and != nil usage 2024-08-04 11:37:49 +01:00
gingerBill a241168142 Clean up err != nil usage 2024-08-04 11:26:35 +01:00
gingerBill 29b6eebcd5 Clean up error handling 2024-08-04 11:21:09 +01:00
gingerBill 7dae38ce89 Begin mocking out for other errors 2024-08-04 11:12:45 +01:00
gingerBill 1826b0c700 Fix copy-replace errors 2024-08-04 11:10:17 +01:00
gingerBill 9f9abb8fb3 Use union #shared_nil for os.Error 2024-08-04 11:05:30 +01:00
gingerBill e60951a902 Begin converting os.Errno to be a nil-able type as a transition period 2024-08-04 10:51:08 +01:00
gingerBill 71932628cc Add alias 2024-08-04 10:08:48 +01:00
jason c691c7dc68 point stdin, stdout, stderr to /dev/null if unused in os2.process_start 2024-08-04 01:47:10 -04:00
jason 2a7db08c20 Remove returned bool from access and faccessat in sys/linux.
Switch to using AT_EMPTY_PATH to execve with file descriptors.
2024-08-04 00:59:40 -04:00
jason 2b89829b52 minor edits in process_linux.odin 2024-08-03 18:08:00 -04:00
Laytan Laats e77977c8ef fix vet errors in stb truetype 2024-08-03 23:56:19 +02:00
jason 38b96a7981 change child error behavior to trap instead of exit 2024-08-03 17:50:47 -04:00
Laytan Laats 4dd846fa29 fix readir_r link name for netbsd 2024-08-03 15:54:29 +02:00
Laytan Laats 61008232e4 actually fail CI when NetBSD tests fail 2024-08-03 15:43:35 +02:00
Jeroen van Rijn 90e573c54a Add image.premultiply_alpha helper. 2024-08-03 12:58:43 +02:00
Laytan ac483f72eb Merge pull request #4013 from laytan/fix-os-read-dir-with-symlinks
fix os.read_dir with symlinks
2024-08-03 01:08:23 +02:00
Laytan Laats 99d9e8f8b1 fix os.read_dir with symlinks 2024-08-03 00:26:46 +02:00
skytrias 9f5854e24e Update orca bindings and macros to requested changes 2024-08-02 23:46:02 +02:00
Laytan 772dce7e42 Merge pull request #3969 from elvodqa/master
Add `sdl2glue` to `vendor:wgpu` package
2024-08-02 17:18:34 +02:00
Emir e55d09bdfa Update vendor/wgpu/examples/sdl2/main.odin
Co-authored-by: Laytan <laytanlaats@hotmail.com>
2024-08-02 18:04:36 +03:00
Jeroen van Rijn 1a16585b10 Add image.pixels_to_image helper. 2024-08-02 14:54:52 +02:00
Laytan 500c117312 Merge pull request #4008 from Daxode/wasm-quality-of-life
Quality of Life changes to wgpu/js
2024-08-02 13:51:47 +02:00
daniel-andersen 723e6d19be right number whoops! 2024-08-02 13:38:36 +02:00
Jeroen van Rijn 8e8660fdfc Merge pull request #4007 from marcosantos98/fix-wasm
Fix: compilation error when using BufferSubDataSlice in webgl package
2024-08-02 12:31:23 +02:00
marcosantos98 3bfccde6f9 Fix: remove extra usage in webgl.odin:250
Compilation error when using webgl.BufferSubDataSlice.
The `usage` parameter is nowhere to be found.
This is probably a copy-pasta leftover.
2024-08-02 10:50:16 +01:00
daniel-andersen e7041f785a Quality of life changes to wgpu/wasm stuff 2024-08-02 11:04:10 +02:00
gingerBill 83599957b1 Merge pull request #3998 from zen3ger/os2-temp_file_linux
[os2] Add missing temp_file implementation for Linux
2024-08-01 20:07:21 +01:00
skytrias f8e0cda113 Add autogenerated orca bindings and macros from laytan 2024-08-01 19:19:24 +02:00
Jeroen van Rijn 0fa62937d5 Fix NetBSD CI 2024-07-31 20:19:13 +02:00
Jeroen van Rijn f627a38b4f Update rand.reset() example. 2024-07-31 20:00:55 +02:00
Jeroen van Rijn cc8c2f236b Merge pull request #4002 from thetarnav/update-builtin-constants
Update comments for builtin constants
2024-07-31 19:47:01 +02:00
Damian Tarnawski 953ae32607 Update builtin constants 2024-07-31 18:55:04 +02:00
Jeroen van Rijn fdfe6b00e0 Improve output path checking
Fixes #4001
2024-07-31 15:16:09 +02:00
Laytan 8a9901aeab Merge pull request #4000 from lxmcf/master
[vendor:raylib] Remove GuiStyleProp
2024-07-31 12:34:00 +02:00
Alex Macafee 1f2ab84e82 Use GuiControlProperty instead of c.int 2024-07-31 19:08:08 +10:00
Alex Macafee 92831d7ca3 Remove GuiStyleProp 2024-07-31 18:58:43 +10:00
Alex Macafee f33b4ecd3e Update Raygui Style set/get functions 2024-07-31 18:48:16 +10:00
gingerBill 62191f54a0 Merge pull request #3997 from Hyrtwol/reource-fix-windows
fix for using .rc files
2024-07-30 21:26:07 +01:00
gingerBill 04c3723985 Merge pull request #3992 from thetarnav/parser-patch
Correct the Array_Type.len comment and assign tok when making Ellipsis node
2024-07-30 21:25:21 +01:00
gingerBill ac19bb3a8c Merge pull request #3985 from flysand7/docs-sync
[sync]: Document all procedures
2024-07-30 21:24:59 +01:00
Roland Kovacs 1913c08b7b [os2] Add missing temp_file implementation for Linux 2024-07-30 18:11:44 +02:00
Thomas la Cour 744d7f7ef4 fix for using .rc files 2024-07-30 16:53:14 +02:00
jason c7eb2ae6bb use sys/linux dirent instead of manual iteration 2024-07-30 10:19:09 -04:00
jason 792640df1f remove File_Impl_Kind from file_linux 2024-07-30 09:41:49 -04:00
jason 278a63caaa remove pidfd availability caching 2024-07-30 09:28:40 -04:00
jason a03dffcd1a improve error handling; do not report errors from failed execve 2024-07-30 08:45:53 -04:00
flysand7 3aac4b1a3e [sync]: Document all procedures 2024-07-30 19:13:35 +11:00
Damian Tarnawski 478b2d7444 Correct the Array_Type.len comment and assign tok when making Ellipsis node 2024-07-29 22:14:42 +02:00
Laytan 7f17d4eb7f Merge pull request #3991 from laytan/fix-in-map-with-union-variants
fix `specific_union_variant in map_keyed_by_union` not converting to union type
2024-07-29 02:39:47 +02:00
Laytan Laats 4d1d754cae fix specific_union_variant in map_keyed_by_union not converting to union type 2024-07-29 02:32:13 +02:00
Jeroen van Rijn 24e6f16f4a Clamp dot in angle_between to avoid precision errors.
Fixes #3978
2024-07-28 15:00:29 +02:00
Laytan f852aac0e7 Merge pull request #3989 from colrdavidson/spall_doc
Improve Spall Docs slightly to reduce onboarding friction
2024-07-28 12:46:04 +02:00
Colin Davidson 27f75c40ab make example compile 2024-07-28 01:29:33 -07:00
Colin Davidson 1d598f8287 tweak doc a little to reduce onboarding friction for thread-users 2024-07-28 01:23:47 -07:00
Jeroen van Rijn cb31df34c1 Merge pull request #3362 from Hyrtwol/sys-windows-2
core/sys/windows part 2
2024-07-26 14:29:56 +02:00
Thomas la Cour 271ec643ed removed some comments 2024-07-26 11:30:48 +02:00
Thomas la Cour fe587ee79a try to add sys/windows to the normal core tests 2024-07-26 11:04:13 +02:00
Thomas la Cour b149b3d6c6 Merge remote-tracking branch 'upstream/master' into sys-windows-2 2024-07-26 10:45:09 +02:00
Thomas la Cour 03f3ea5a9e removed old test stuff 2024-07-26 10:43:26 +02:00
Thomas la Cour 6e6f2a1f6b removed obsolete fiels on WIN32_FIND_DATAW to match the size from the winsdk headers 2024-07-26 10:14:13 +02:00
Thomas la Cour 58ab6e5f94 missign cursorinfo 2024-07-26 10:07:20 +02:00
Jeroen van Rijn 4e194d5dbd Merge pull request #3980 from Kelimion/format-time
Add `time.to_string*` formatters.
2024-07-25 21:09:51 +02:00
Jeroen van Rijn 00c6b83537 Use constants in example. 2024-07-25 21:02:38 +02:00
Jeroen van Rijn ca7d86084e Improve docs. 2024-07-25 20:58:47 +02:00
Jeroen van Rijn 9088a493d9 Add time.to_string* formatters. 2024-07-25 19:43:42 +02:00
Thomas la Cour fe4754a77c format 2024-07-25 10:27:49 +02:00
Thomas la Cour 9d67d12d22 Merge remote-tracking branch 'upstream/master' into sys-windows-2
# Conflicts:
#	core/sys/windows/shell32.odin
2024-07-25 10:05:41 +02:00
gingerBill 9e82ae10ac Merge branch 'master' of https://github.com/odin-lang/Odin 2024-07-24 21:55:55 +01:00
gingerBill 85880f9def Add more NtDll stuff 2024-07-24 21:55:51 +01:00
Jeroen van Rijn 4ff62994bf Add CLSCTX_ALL 2024-07-24 22:54:17 +02:00
Feoramund 90f1f7fbdf Use unaligned_store in regex too 2024-07-24 16:48:49 -04:00
gingerBill 9b624ef9e1 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-07-24 21:45:40 +01:00
gingerBill f03c2b7783 General clean up of os2.read_directory for Windows 2024-07-24 21:45:35 +01:00
Feoramund ff492e615c Use unaligned_load for regex virtual machine
This should hopefully avoid any issues with loading operands greater
than 8 bits on alignment-sensitive platforms.
2024-07-24 16:27:20 -04:00
Feoramund 042f6de478 Remove printing facilities for Regular_Expression
The `original_pattern` introduced a tenuous dependency to the expression
value as a whole, and after some consideration, I decided that it would
be better for the developer to manage their own pattern strings.

In the event you need to print the text representation of a pattern,
it's usually better that you manage the memory of it as well.
2024-07-24 16:27:20 -04:00
Feoramund c52a8a5f86 Allow configuring of MAX_CAPTURE_GROUPS for n > 10 2024-07-24 16:27:08 -04:00
Feoramund 16b644ad79 Use slice.zero instead 2024-07-24 15:23:20 -04:00
Feoramund e8537a3134 Add test cases for unclosed classes and repetition
Simplified error checking while I was at it, too.
2024-07-24 15:21:41 -04:00
Feoramund e642be8550 Fix handling of unclosed regex classes and repetitions 2024-07-24 15:17:37 -04:00
Jeroen van Rijn 33d6677514 Merge pull request #3951 from Kelimion/lua_test
Add Lua example to `vendor:lua` as well as basic tests.
2024-07-24 17:50:49 +02:00
Jeroen van Rijn 8d6ff51922 Copy lua54.dll during CI test 2024-07-24 17:43:51 +02:00
jason a5fa93e06d remove ctprintf; use fmt.caprintf; fix pipe_linux that I broke. 2024-07-24 10:23:23 -04:00
jasonKercher 215b21811e Merge branch 'master' into os2-process-linux 2024-07-24 10:14:59 -04:00
jason 95a8a4e7f0 typo - inverted logic 2024-07-24 10:12:16 -04:00
jason ecdd3887b2 fix process_info assumptions 2024-07-24 10:09:50 -04:00
gingerBill 2dbccbde54 Improve win32 types 2024-07-24 14:53:48 +01:00
gingerBill 07b1819dc8 Improve os2.read_directory 2024-07-24 14:53:33 +01:00
gingerBill 9d8953538b Add missing attribute 2024-07-24 14:25:42 +01:00
gingerBill d4af7b86a7 Begin cleaning up os2.read_directory 2024-07-24 14:19:30 +01:00
gingerBill 38e983cac6 Remove dead code 2024-07-24 13:47:57 +01:00
gingerBill 2ddaae45f3 Better handling of allocators 2024-07-24 13:47:22 +01:00
jason 16bdc6d240 use more iterators; global "has pidfd open" state is now thread-safe 2024-07-24 08:43:22 -04:00
gingerBill 6d2487a692 Add some more Ntdll calls 2024-07-24 13:38:14 +01:00
gingerBill c407e423d9 Add inode to os2.Stat 2024-07-24 13:37:56 +01:00
gingerBill 0e91c8368c Add allocator parameters to fmt.caprint* 2024-07-24 09:01:41 +01:00
gingerBill f08a53015c Merge pull request #3972 from laytan/testing-json-report
testing: add json reporting
2024-07-24 08:35:37 +01:00
Emir c98bb7da39 Update README.md 2024-07-24 10:33:34 +03:00
Emir ba81a81ca8 Update os_sdl2.odin 2024-07-24 10:29:34 +03:00
Emir 57dc6c2e94 Update os_sdl2.odin 2024-07-24 10:27:22 +03:00
Emir 95412df129 Add newline to glue_darwin.odin 2024-07-24 10:27:00 +03:00
Emir 2a2bedc85c Fix indentation and add full example 2024-07-24 10:22:18 +03:00
Laytan Laats f6488383d7 fix instrumentation features on LLVM versions with typed pointers
Fixes #3970
2024-07-24 02:43:53 +02:00
jason 0455e4b60f remove unused constants; fix comment 2024-07-23 19:48:18 -04:00
Laytan Laats 545fbc54c7 testing: add json reporting 2024-07-24 01:33:22 +02:00
jason 82deaa59ad os2 linux: fix order of operations bug in _open; fix process_info routine 2024-07-23 17:50:30 -04:00
jason 3c7d1f35db os2 process implementation for linux 2024-07-23 16:50:00 -04:00
Emir f9ef951b22 Add sdl2glue/glue_linux.odin 2024-07-23 22:39:50 +03:00
Laytan Laats fc2e31fcd0 fix build comment in os_freestanding 2024-07-23 20:51:00 +02:00
Emir e8e51db9ff Update glue.odin 2024-07-23 20:42:26 +03:00
Emir a429603195 Remove unused variable from example 2024-07-23 20:39:09 +03:00
Emir 42833d0471 Merge branch 'odin-lang:master' into master 2024-07-23 20:38:04 +03:00
Emir f3f08a4b47 Add sdl2glue to vendor:wgpu package + triangle example 2024-07-23 20:37:26 +03:00
gingerBill efa8c92bab Implement init_long_path_support 2024-07-23 17:46:22 +01:00
gingerBill 65fec9134e Use SHFileOperationW for remove_all on Windows 2024-07-23 17:30:42 +01:00
gingerBill a28392852a Mock out os2.remove_all for Windows 2024-07-23 17:05:41 +01:00
gingerBill 8037ace873 Begin work on os2/dir.odin 2024-07-23 16:47:49 +01:00
gingerBill 182454a1c0 Minor clean ups 2024-07-23 16:09:15 +01:00
gingerBill 24f9e2bbeb Begin mocking out the linux stuff on os2 2024-07-23 16:06:14 +01:00
gingerBill 61b9a5dbb2 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-07-23 15:57:23 +01:00
gingerBill 0403626acf Add utility calls to os2 2024-07-23 15:57:17 +01:00
Laytan 6fc3d32d4b Merge pull request #3967 from thetarnav/remove-space
Remove space in indentation
2024-07-23 13:58:50 +02:00
Damian Tarnawski eb4f850b7f Remove space in indentation 2024-07-23 13:48:03 +02:00
Jeroen van Rijn da80c51195 Merge pull request #3966 from KyleNBurke/sys-windows-add-type
Add `NCCALCSIZE_PARAMS` to `sys/windows`
2024-07-23 07:45:44 +02:00
Kyle Burke 9d99f98194 Remove semicolon 2024-07-23 00:22:19 -05:00
Kyle Burke c32e12c3f5 Add NCCALCSIZE_PARAMS to sys/windows 2024-07-23 00:09:50 -05:00
Laytan c5fb72340a Merge pull request #3963 from andreas-jonsson/andreas-jonsson-patch-1
Use pkgsrc llvm for NetBSD CI
2024-07-23 04:20:54 +02:00
gingerBill b0fe777ede Propagate rodata a bit more in lb_const_value 2024-07-23 03:01:09 +01:00
gingerBill bc5b41938e Fix #3964 2024-07-23 02:40:51 +01:00
gingerBill 527c0b3202 Change lib for lz4 2024-07-23 00:19:42 +01:00
gingerBill 6eb28aeafc Check to see if people are return a slice of a local fixed array from a procedure 2024-07-22 22:52:10 +01:00
gingerBill 12b971746c vendor:compress/lz4
Bindings to lz4 library
2024-07-22 22:42:29 +01:00
gingerBill ef84382f23 Add suggestion for #3961 2024-07-22 20:11:23 +01:00
Feoramund b8f3d0fb53 Add core:text/regex to examples/all 2024-07-22 15:07:13 -04:00
Feoramund be38ba6c5e Add benchmarks for core:text/regex 2024-07-22 15:07:13 -04:00
Feoramund 3e49ceb82a Add tests for core:text/regex 2024-07-22 15:07:13 -04:00
Feoramund 730e10bd6f Support printing Regular_Expression in fmt 2024-07-22 14:25:12 -04:00
Feoramund cb0704d51c Add core:text/regex 2024-07-22 14:25:12 -04:00
Jeroen van Rijn 9cad8179b7 Clarify core:time Unix timestamp 2024-07-22 20:00:25 +02:00
Jeroen van Rijn ccf8b2764d Create README.md 2024-07-22 18:00:57 +02:00
gingerBill 915c5c3a87 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-07-22 16:29:35 +01:00
gingerBill fcaa47986a Improve error handling for invalid syntax doing [*]T 2024-07-22 16:29:29 +01:00
Jeroen van Rijn 07d2aba310 Simplify exe path check. 2024-07-22 16:36:21 +02:00
Jeroen van Rijn 4889641af4 Merge pull request #3959 from Kelimion/fix-output-is-directory-check
Fix .exe path is directory check.
2024-07-22 16:22:17 +02:00
Jeroen van Rijn 90a4d12b30 Fix .exe path is directory check. 2024-07-22 16:11:33 +02:00
Jeroen van Rijn a39b6de18c Merge pull request #3958 from Kelimion/fix-3473
Fix #3473
2024-07-22 15:41:39 +02:00
Jeroen van Rijn 39657e4d96 Fix #3473
Fix the problem where the initial package's directory name ended in .odin.
2024-07-22 15:15:51 +02:00
Laytan 73a9a97413 Merge pull request #3476 from PucklaJ/syscall-fix
[sys/linux] Fix fork and execve syscalls on arm64
2024-07-22 13:58:17 +02:00
PucklaJ 1873f7215d [sys/linux]: Change execveat flags type to Execveat_Flags 2024-07-22 11:03:25 +02:00
Laytan Laats 4d86012d96 install lua for new lua vendor tests 2024-07-22 01:13:50 +02:00
Laytan Laats a055c03de9 use #directory in lua test 2024-07-22 01:11:01 +02:00
Laytan 68550cf915 Merge pull request #3957 from laytan/fix-any_base-and-any_core
fix `reflect.any_base` and `reflect.any_core` with any's containing nil
2024-07-22 01:09:38 +02:00
Laytan Laats 3e618bed40 fix reflect.any_base and reflect.any_core with any's containing nil 2024-07-22 00:51:38 +02:00
Jeroen van Rijn 51733fce68 Merge pull request #3952 from Ronaldr1985/master
Ensure that values in ini map are unquoted
2024-07-21 14:58:15 +02:00
Jeroen van Rijn a056e9da81 Merge pull request #3954 from flysand7/docs-thread
[thread]: Document all functions in core:thread
2024-07-21 14:10:49 +02:00
flysand7 b84b4c47d7 [thread]: Document all functions in core:thread 2024-07-21 14:34:36 +11:00
Jeroen van Rijn 431227d4c5 Add NULL check in check_range_stmt
Fixes #3953
2024-07-21 02:52:53 +02:00
Ronald 1a6885c2a3 Tidy up code 2024-07-21 00:08:20 +01:00
Ronald c3a57853e2 Ensure that values in ini map are unquoted 2024-07-21 00:00:47 +01:00
Jeroen van Rijn fc5ce30f34 Allow json to unmarshal empty struct. 2024-07-21 00:37:11 +02:00
Jeroen van Rijn 572b400d8e Merge pull request #3950 from Ronaldr1985/master
Add tests for encoding/ini
2024-07-20 18:47:08 +02:00
Jeroen van Rijn f78a792d48 Add Lua example to vendor\lua as well as basic tests. 2024-07-20 18:30:41 +02:00
Ronald e0a8bd04d5 Ensure deletion of maybe is delayed until we're finished with it. 2024-07-20 17:10:34 +01:00
Ronald f560b14d10 Fix typo in name of test 2024-07-20 17:10:19 +01:00
Ronald b584eeaade Add encoding/ini tests 2024-07-20 16:53:54 +01:00
Jeroen van Rijn cdd2c98b8d Merge pull request #3948 from flysand7/docs-time
[time]: Document all functions
2024-07-20 16:06:07 +02:00
Jeroen van Rijn 9d6ed991cb Remove LUA panic for non-big-3 OS 2024-07-20 14:33:34 +02:00
Jeroen van Rijn 2385e1ddd9 Update LUA imports for Darwin. 2024-07-20 14:24:01 +02:00
flysand7 b3ca2d5e0a [time]: Document all functions 2024-07-20 18:48:50 +11:00
Jeroen van Rijn 64614889de Merge pull request #3946 from flysand7/x11-fixes
[vendor/x11]: Fix missing argument in XDefaultDepth, wrong types in CreateSimpleWindow
2024-07-20 04:00:00 +02:00
Jeroen van Rijn d9d044970e Merge pull request #3945 from flysand7/docs-datetime
[time/datetime]: Document package datetime
2024-07-20 03:56:21 +02:00
flysand7 0c78cab336 [time/datetime]: Document package datetime 2024-07-20 12:49:40 +11:00
flysand7 15997d2a90 [vendor/x11]: Fix missing argument in XDefaultDepth, wrong types in CreateSimpleWindow 2024-07-20 12:47:00 +11:00
Jeroen van Rijn 7237f9c9f8 Help text default -o:none -> -o:minimal. 2024-07-19 20:47:26 +02:00
gingerBill ba3d7ba5d3 Add core:encoding/ini to examples/all 2024-07-19 12:03:34 +01:00
gingerBill f226eba342 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-07-19 12:00:54 +01:00
gingerBill 393ca40c23 Minor clean ups 2024-07-19 12:00:49 +01:00
gingerBill 62f455f47b Merge branch 'master' into syscall-fix 2024-07-19 11:43:56 +01:00
gingerBill 163287d9ce Merge pull request #3938 from Ronaldr1985/master
Fix memory leak in encoding/ini
2024-07-19 11:42:35 +01:00
gingerBill 2f8399fe20 Merge pull request #3940 from flysand7/os2-handle-inheritance
[os2] Make all handles non-inheritable by default
2024-07-19 11:38:03 +01:00
gingerBill 685dbddcb5 Merge pull request #3939 from flysand7/os2-file-type
[os2]: Split file type from mode bits et other small fixes
2024-07-19 11:37:54 +01:00
Laytan Laats 27f9f0ba17 fix OLS #431, #393 2024-07-18 21:06:37 +02:00
Laytan Laats 2b6a926bb6 fix OLS #52 2024-07-18 21:06:37 +02:00
Laytan b3d798cb76 Merge pull request #3941 from laytan/wgpu-wayland-improvements
improve WGPU / GLFW / Wayland story by weak linking and adjusting docs
2024-07-18 20:20:01 +02:00
Laytan 7134015f56 improve WGPU / GLFW / Wayland story by weak linking and adjusting docs 2024-07-18 19:28:15 +02:00
flysand7 7b501b22bb [os2]: Split file type from mode bits 2024-07-18 23:09:27 +11:00
flysand7 75605a47e7 [os2]: Make anonymous pipes always inheritable 2024-07-18 22:57:30 +11:00
flysand7 4dcb75af6d Make all handles non-inheritable by default
The sockets are left as non-inheritable because they
never should be inherited.
2024-07-18 22:50:47 +11:00
Ronald c768d0719a Remove unnecessary change
This was accidentally added, it was a change I made whilst testing.
2024-07-17 21:57:35 +01:00
Ronald f04db7145c Fix memory leak in encoding/ini
A simple change that fixes a memory leak caused by not deleting all the
values in the map
2024-07-17 21:19:14 +01:00
gingerBill 0bb4cc6ce5 Merge pull request #3935 from IllusionMan1212/win32-drag-n-drop
core/sys/windows: added drag and drop procedures
2024-07-16 23:41:52 +01:00
IllusionMan1212 07121f81ff core/sys/windows: added drag and drop procedures 2024-07-17 00:32:25 +02:00
Jeroen van Rijn 5520b45457 Add glfw LICENSE file 2024-07-16 22:59:32 +02:00
Laytan cb16d2ddaf Merge pull request #3934 from laytan/fix-saturating-intrinsics
fix `add_sat` and `sub_sat` intrinsics
2024-07-16 22:30:06 +02:00
Laytan Laats a6d1a2e46c add #optional_ok to docs file for intrinsics 2024-07-16 22:22:06 +02:00
Laytan Laats 47f14dd9ea type is never a tuple here 2024-07-16 22:11:54 +02:00
Laytan Laats 853487e86c fix add_sat and sub_sat intrinsics 2024-07-16 22:07:49 +02:00
gingerBill 0d881e1561 Improve rand.shuffle further by splitting into 64-bit and 32-bit parts 2024-07-16 18:36:31 +01:00
gingerBill ba49950454 Improve rand.shuffle 2024-07-16 18:33:01 +01:00
gingerBill f66133959f Merge pull request #3933 from laytan/fix-some-bugs-with-disable-assert
fix some bugs with -disable-assert
2024-07-16 17:54:21 +01:00
Laytan Laats 28fac62a02 fix some bugs with -disable-assert 2024-07-16 18:44:18 +02:00
gingerBill a3fe5754d9 Make complex32 use higher precision where possible for calculations 2024-07-16 15:31:00 +01:00
gingerBill df56655ab1 Fix formatting inconsistencies 2024-07-16 14:03:02 +01:00
gingerBill 6702f07762 rawptr -> cstring 2024-07-16 14:02:07 +01:00
gingerBill 03e90bf924 Use RTTI to get the error_string for Windows 2024-07-16 12:26:24 +01:00
gingerBill 8d70a264ab Check for specific error directly 2024-07-16 12:21:55 +01:00
gingerBill fe718460c6 Clean up bit_set usage 2024-07-16 12:17:48 +01:00
gingerBill 1afb10109e Remove the need for temporary variables where possible 2024-07-16 12:13:39 +01:00
gingerBill 3a162de18f More clean up for process_windows.odin 2024-07-16 12:08:59 +01:00
gingerBill 321ef82d76 Add @(require_results) where needed 2024-07-16 11:57:22 +01:00
gingerBill 169fc4d3be General clean up of the os2/process_windows.odin code 2024-07-16 11:56:31 +01:00
gingerBill affe8f7144 Merge pull request #3310 from flysand7/core-process
Addition of `core:os2/process` api.
2024-07-16 11:24:24 +01:00
gingerBill 23ca27f40b Add intrinsics add_sat and sub_sat 2024-07-16 00:48:17 +01:00
Laytan Laats 03426175ae add workaround for kernel panics on MacOS 2024-07-15 22:45:16 +02:00
Jeroen van Rijn 0a9c150748 Merge pull request #3929 from laytan/fix-fmt-len-transfer-to-children
fmt: fix optional_len or use_nul_termination being used by both array and elems
2024-07-15 19:36:20 +02:00
Laytan Laats f362e0fa20 add test for leaking struct tag into elems 2024-07-15 19:27:48 +02:00
Laytan Laats d4d910bcfc fmt: fix optional_len or use_nul_termination being used by both array and elems
```odin
My_Struct :: struct {
	names:      [^]string `fmt:"v,name_count"`,
	name_count: int,
}

main :: proc() {
	name := "hello?"
	foo := My_Struct {
		names = &name,
		name_count = 1,
	}
	fmt.println(foo)
}
```

Before: `My_Struct{names = ["h"], name_count = 1}`
After:  `My_Struct{names = ["hello?"], name_count = 1}`
2024-07-15 18:51:18 +02:00
Jeroen van Rijn 3a75a8dd1b Merge pull request #3928 from Yawning/feature/aes-ni
core/crypto: Support AES-NI + PCLMUL
2024-07-15 18:41:21 +02:00
Yawning Angel 33dae2e26c core/crypto/aes: Support the full range of GCM nonce sizes 2024-07-16 01:29:43 +09:00
Yawning Angel 69026852ce core/crypto/aes: Add Intel AES-NI support
This supports AES-NI + PCLMUL, and provides optimized key schedule, ECB,
CTR, and GCM.  Other modes are trivial to add later if required.
2024-07-16 01:29:43 +09:00
Yawning Angel f578994fa6 core/simd/x86: Make the AES-NI intrinsics consistent with Intel 2024-07-16 01:29:43 +09:00
Yawning Angel 1bc21c3481 core/crypto/_aes: Remove redundant sanity checks 2024-07-16 01:29:43 +09:00
Yawning Angel c9c0b9ea7b core/crypto: Fix/add some documentation (NFC) 2024-07-16 01:29:43 +09:00
Yawning Angel 390cd3c30d core/simd/x86: Fix some intrinsics
- _mm_slli_si128 produced totally incorrect output
- _mm_storeu_si128 refered to a LLVM intrinsic that is missing
2024-07-16 01:29:43 +09:00
Yawning Angel 401877184f tests/benchmark/crypto: Benchmark AES256-CTR 2024-07-16 01:29:43 +09:00
Yawning Angel 4815154c31 test/core/crypto: Fix a copy-paste issue in failure spew 2024-07-16 01:29:43 +09:00
Yawning Angel 0d8dadec8a tests/core/crypto: Fix new -vet issues 2024-07-16 01:29:43 +09:00
Yawning Angel ff13ee3281 core/crypto: Enforce aliasing restrictions 2024-07-16 01:29:43 +09:00
Yawning Angel dcaf085bfa core/bytes: Add alias and alias_inexactly 2024-07-16 01:29:43 +09:00
Laytan Laats 55e0f97cc4 help fmt with Type_Info_Struct and Type_Info_Bit_Field changes 2024-07-15 18:29:06 +02:00
gingerBill 65c91b7dde Fix code gen issue with bit_set 2024-07-15 15:16:23 +01:00
gingerBill bd562116b8 Minor change to an internal flag 2024-07-15 15:08:26 +01:00
gingerBill 1e37eaf54d Begin work for bit_set[...; [N]T] (not working) 2024-07-15 14:49:20 +01:00
flysand7 8df61b7209 [os2/process]: Make get_args() private and use heap_allocator 2024-07-15 23:28:03 +11:00
Yawning Angel 1a30d47ee8 repo: Cleanup the .gitignore to match the new test runner 2024-07-15 21:25:07 +09:00
gingerBill 5cefab8229 Fix case: in type switch issue 2024-07-15 13:22:50 +01:00
gingerBill 7d643bcae3 Make linkage weak in certain places 2024-07-15 12:30:32 +01:00
gingerBill 549311fac9 Fix global variables being "missing" with -use-separate-modules 2024-07-15 12:21:42 +01:00
gingerBill c5decd3eae Fix possible race and correct linkage _after_ generation 2024-07-15 11:49:07 +01:00
flysand7 255f00d971 [os2/process]: Implement missing functionality, update docs 2024-07-15 20:24:05 +11:00
gingerBill 664a71454b -use-separate-modules default on Windows only 2024-07-15 02:53:01 +01:00
gingerBill 432388ac7f Generate backing array in the case where there is no DeclInfo for the procedure body 2024-07-15 02:42:28 +01:00
gingerBill cc3cf12ae2 Disable -use-separate-modules by default on darwin until problem is determined 2024-07-15 02:28:27 +01:00
gingerBill d87583bead Minimize mutex lock for #load_directory 2024-07-15 02:22:23 +01:00
gingerBill 1b0e98116d Revert changes to in_single_threaded_checker_stage 2024-07-15 01:47:52 +01:00
gingerBill eb6805ef40 Disable the need for mutexes in single threaded checker stage 2024-07-15 01:44:23 +01:00
gingerBill a45e05bb18 Remove need for BlockingMutex in Arena 2024-07-15 01:36:54 +01:00
gingerBill e4ba786948 Remove use of mutex in single threaded code 2024-07-15 01:29:57 +01:00
gingerBill cae8c1e94f Minimize use of mutex in Arena 2024-07-15 01:15:00 +01:00
gingerBill a8f84c87ae Add the permanent and temporary arenas directly on the Thread 2024-07-15 01:05:29 +01:00
gingerBill c64702ae5a Make -use-separate-modules the default behaviour for -o:none and -o:minimal 2024-07-15 00:43:46 +01:00
gingerBill 3311ea1c76 Keep MSVC happy with secure versions of C calls 2024-07-15 00:38:10 +01:00
gingerBill 018026d844 Use gb_zero_* calls 2024-07-15 00:36:00 +01:00
gingerBill 139c1bcdda Comment out debug code 2024-07-15 00:25:41 +01:00
gingerBill 46817e8f68 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-07-15 00:01:31 +01:00
gingerBill 196ac7e6d6 Type erase _make_dynamic_array_len_cap 2024-07-15 00:01:26 +01:00
Jeroen van Rijn e3e31b42d0 #force_no_inline build_huffman to avoid bloat 2024-07-15 00:54:08 +02:00
gingerBill f7cb711874 Add #force_no_inline 2024-07-14 23:48:33 +01:00
gingerBill f657055f12 Add slice variable if not exists 2024-07-14 23:36:54 +01:00
gingerBill 26a9416a41 Minor clean ups 2024-07-14 23:33:35 +01:00
gingerBill e768bddaeb Inline _append_elem_string further 2024-07-14 23:22:22 +01:00
gingerBill 83b7dd122a Type erase for append_elems 2024-07-14 23:20:50 +01:00
gingerBill b0fbaf24a0 Type erase append_elem 2024-07-14 23:16:11 +01:00
gingerBill 1c3240b6b5 Add #force_no_inline 2024-07-14 23:09:58 +01:00
gingerBill 7673d478b6 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-07-14 23:09:17 +01:00
gingerBill 15fb4ded2a type erase resize and reserve internals 2024-07-14 23:09:10 +01:00
Jeroen van Rijn 03cb585845 Merge pull request #3908 from NicknEma/Intrusive-list-docs
Write docs for `core:container/intrusive/list` package
2024-07-14 23:28:53 +02:00
gingerBill 9d84e00502 Clean up unquote code 2024-07-14 22:25:26 +01:00
gingerBill 7703b37a1b Merge branch 'master' of https://github.com/odin-lang/Odin 2024-07-14 22:23:52 +01:00
gingerBill 95a695e4cd Fix #3926 2024-07-14 22:23:46 +01:00
gingerBill 02408b713a Merge pull request #3910 from VladPavliuk/json-add-int-key-map-support
Allow to `marshal` and `unmarshal` maps with int keys
2024-07-14 22:00:01 +01:00
gingerBill 251fa477af Fix type 2024-07-14 21:39:33 +01:00
gingerBill 15a0655988 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-07-14 21:37:41 +01:00
gingerBill 399c3ab067 Reduce the size of runtime.Type_Info 2024-07-14 21:37:35 +01:00
flysand7 b7ccfed9af [os2/process]: Implement process_kill 2024-07-15 07:27:44 +11:00
flysand7 4eca60946c [os2/process]: Refactor process_info procs, add process_info_by_handle 2024-07-15 07:27:44 +11:00
flysand7 8f4755532e [os2/process]: Adjust docs on process_close function 2024-07-15 07:27:44 +11:00
flysand7 63d94301fc [os2/process]: Implement process creation procedures 2024-07-15 07:27:43 +11:00
flysand7 e1eed7610c [os2/process]: Fix leaking memory on errors 2024-07-15 07:27:43 +11:00
flysand7 5d6e0bc793 [os2/process]: Implement retrieving command args in process info 2024-07-15 07:27:43 +11:00
flysand7 c1f5d8f006 [os2/process]: Improve documentation for *process_info() family of function 2024-07-15 07:27:43 +11:00
flysand7 f3d4a734d8 [os2/process]: Fix environment block null-terminator counting 2024-07-15 07:27:43 +11:00
flysand7 6387cd2c24 [os2/process] Added process_info() procedure 2024-07-15 07:27:43 +11:00
flysand7 56d55e4a86 Rebase master 2024-07-15 07:27:43 +11:00
flysand7 6fab055f43 [os2/process]: Add process list function 2024-07-15 07:27:43 +11:00
flysand7 2495f1c39a [os2/process]: Fill in basic functions 2024-07-15 07:27:43 +11:00
Jeroen van Rijn 65dab3a3b1 Merge pull request #3925 from Feoramund/fix-no-return-switch
Fix compiler crash when switching on no value
2024-07-14 21:26:46 +02:00
Feoramund b38237e8f0 Fix compiler crash when switching on no value 2024-07-14 14:59:00 -04:00
NicknEma 63276a85ba Fixed grammar and expanded info
Fixed points made by Jeroen.
2024-07-14 18:18:12 +02:00
VladPavliuk 3f8712edb0 Merge branch 'master' into json-add-int-key-map-support 2024-07-14 18:22:20 +03:00
gingerBill e7d37607ef Fix parameter to none 2024-07-14 16:05:47 +01:00
gingerBill 6feace2351 Add pseudo flag -fast-build 2024-07-14 16:05:07 +01:00
gingerBill a867378418 Default to -o:minimal again 2024-07-14 15:55:26 +01:00
gingerBill 11e2aa2d51 Improve error message 2024-07-14 15:31:40 +01:00
gingerBill 556355ef05 Disallow global use of target specific procedure calls 2024-07-14 15:30:40 +01:00
gingerBill 5de6016e7f Clean up os2.File.impl usage 2024-07-14 15:26:59 +01:00
gingerBill 2d56e3805b Merge branch 'master' of https://github.com/odin-lang/Odin 2024-07-14 15:09:38 +01:00
gingerBill 4f73b35da5 Make os2.File a more generic interface 2024-07-14 15:09:33 +01:00
Jeroen van Rijn 76b0562acd Merge pull request #3923 from laytan/fix-off-by-one-in-queue-back
Fix off-by-one in queue `back` and `back_ptr` procs
2024-07-14 16:09:16 +02:00
Laytan Laats d90d7ed002 Fix off-by-one in queue back and back_ptr procs 2024-07-14 16:00:55 +02:00
gingerBill 3d38f14202 Use fstat on os2.File directly 2024-07-14 14:51:22 +01:00
gingerBill d1450e3d88 Fix styling issues 2024-07-14 14:44:22 +01:00
gingerBill eff46c2e5f Merge pull request #3919 from colrdavidson/growing_workpool
move to a growing workstealing queue
2024-07-14 14:39:49 +01:00
gingerBill 8319917898 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-07-14 14:07:42 +01:00
gingerBill 2e0c5fefde Reuse the slice value too for variadic parameters (LLVM >= 13) 2024-07-14 14:07:36 +01:00
Jeroen van Rijn 88823c4024 Merge pull request #3921 from Ronaldr1985/master
Fix logic bug in core/encoding/ini/ini.odin
2024-07-14 14:48:47 +02:00
gingerBill 6959554040 Calculate size and alignment, and reuse memory for all variadic calls within a procedure body 2024-07-14 13:44:47 +01:00
gingerBill 0a530b5ce8 Add error for #no_capture being reserved for future use 2024-07-14 13:20:12 +01:00
gingerBill 8650180ccc Change Odin calling convention to not do a copy on byval for SysV 2024-07-14 12:59:55 +01:00
gingerBill 5027c7081e Reuse slice variable for variadic parameters 2024-07-14 12:50:33 +01:00
gingerBill 3533094cc2 Restrict #no_capture to pointer-like types only 2024-07-14 12:44:13 +01:00
gingerBill 5ce6676914 Make #no_capture map to nocapture 2024-07-14 12:41:16 +01:00
gingerBill 3dff83f3dc Mock out #no_capture for future use 2024-07-14 12:39:30 +01:00
gingerBill 8642d719f0 Imply #no_capture to all variadic parameters 2024-07-14 12:19:47 +01:00
gingerBill 891cf54b5c Add f16 to #c_vararg promotion rules 2024-07-14 12:03:34 +01:00
gingerBill 3ba19d94cf Add #no_capture to core:odin/ast 2024-07-14 11:58:26 +01:00
gingerBill c7bd954752 Add more uses of #no_capture 2024-07-14 11:56:04 +01:00
Ronald 7e4e3429d7 Fix logic bug in core/encoding/ini/ini.odin
The load_map_from_path had incorrect logic where it would return false
for ok when err was equal to nil and true when there was an error.
2024-07-14 11:48:34 +01:00
gingerBill edc793d7c1 Add #no_capture args: ..T to reuse the backing array stack memory 2024-07-14 11:39:05 +01:00
gingerBill f98a7b84df Merge pull request #3914 from VladPavliuk/json-add-ignore-tag-support
Add support of `ignore` tag for `json.marshal`
2024-07-14 10:38:15 +01:00
gingerBill 0050cb9471 Merge pull request #3918 from flysand7/file-handle-inheritance2
[os2/file]: Fixes related to handle inheritance
2024-07-14 10:36:10 +01:00
Colin Davidson 64feb7599e move to isize 2024-07-14 00:33:40 -07:00
Colin Davidson 4420128dc1 handle steal-fail vs steal-empty 2024-07-14 00:29:58 -07:00
Colin Davidson cdede4928c move to a growing queue 2024-07-13 23:16:22 -07:00
flysand7 b686b072d5 [os2/file]: Fixes related to handle inheritance
All file handles created on Windows used to be made
non-inheritable, by forcing the .Close_On_Exec flag
in _open() function. In addition, there was an
issue with security descriptor being freed before
use, which has been fixed.
2024-07-14 15:06:28 +11:00
VladPavliuk 76fe5d1346 Align ignore syntax of json tags with fmt, cbor 2024-07-14 00:21:05 +03:00
gingerBill 8cebc7cc0c Merge pull request #3915 from tadeohepperle/vendor-wgpu-RenderPassEncoderSetPushConstants-signature
vendor/wgpu: RenderPassEncoderSetPushConstants should take a rawptr instead of cstring
2024-07-13 15:16:21 +01:00
Tadeo hepperle 75076e2d64 RenderPassEncoderSetPushConstants should take a rawptr instead of cstring for the data 2024-07-13 16:01:33 +02:00
VladPavliuk 64ae99f016 Add support of ignore tag for json.marshal 2024-07-13 14:13:59 +03:00
Jeroen van Rijn d845a07519 Merge pull request #3912 from xzores/master
Update stb_truetype.odin
2024-07-13 00:16:34 +02:00
xzores b4683f4399 Update stb_truetype.odin 2024-07-12 23:57:45 +02:00
VladPavliuk 79e2f63182 Small code refactoring in test_core_json 2024-07-13 00:38:58 +03:00
VladPavliuk 39983eaaa4 Remove unused imports in test_core_json 2024-07-13 00:26:54 +03:00
VladPavliuk dbdad0476d Allow to marshal and unmarshal maps with int keys 2024-07-13 00:07:48 +03:00
Thomas la Cour 3627a51daf Merge remote-tracking branch 'upstream/master' into sys-windows-2 2024-07-12 16:06:48 +02:00
gingerBill e715674512 Merge pull request #3907 from flysand7/console-read-fix
[core/os]: Fix read_console edge case bug
2024-07-12 14:58:40 +01:00
gingerBill 9e0c4098be Merge pull request #3905 from flysand7/winapi-process-procs
[sys/windows]: Advapi bindings, process-related functions and thread context
2024-07-12 14:58:27 +01:00
NicknEma d10694901f Simplify and fix doc examples
Remove unnecessary examples;
fix compilation errors in the remaining ones
2024-07-12 15:48:47 +02:00
NicknEma c75a872909 Write doc comments in intrusive_list.odin
Write description, inputs/returns and some examples for each procedure
2024-07-12 15:37:34 +02:00
NicknEma a348a7e84e Create doc.odin
Create a doc file with a brief of the package and an example program (copied from a discord message by laytan)
2024-07-12 15:18:58 +02:00
flysand7 a7d95ab3e1 [core/os]: Fix read_console not stopping the read when newline can't fit in output slice 2024-07-12 20:28:38 +11:00
flysand7 6ae47c6f43 [sys/windows] Add advapi bindings, process-related functions and context-related stuff 2024-07-12 19:21:44 +11:00
Thomas la Cour 3291c59728 post rebase 2024-07-11 21:37:37 +02:00
Thomas la Cour dd75b7a4d9 Merge remote-tracking branch 'upstream/master' into sys-windows-2
# Conflicts:
#	core/sys/windows/kernel32.odin
#	core/sys/windows/types.odin
#	core/sys/windows/user32.odin
#	core/sys/windows/winerror.odin
2024-07-11 21:20:53 +02:00
gingerBill 1770e3a9a9 Fix typo 2024-07-11 17:19:12 +01:00
gingerBill 19753ed8a3 Add rand.Generator and other calls 2024-07-11 17:12:42 +01:00
gingerBill 59d87d1f05 Add gen := context.random_generator parameters to rand calls 2024-07-11 17:01:34 +01:00
gingerBill 6b3453cc64 Fix #3902 2024-07-11 13:08:38 +01:00
gingerBill 5e7634d90c Merge branch 'master' of https://github.com/odin-lang/Odin 2024-07-11 13:04:32 +01:00
gingerBill fc7c7cd8ab Merge pull request #3900 from Kelimion/winres
Allow precompiled resources with `-resource:foo.res`
2024-07-11 12:51:25 +01:00
gingerBill e05e99253b Merge pull request #3904 from laytan/make-instrumentation-work-on-wasm
make instrumentation "work" on wasm
2024-07-11 12:50:51 +01:00
Jeroen van Rijn a8ce5bd005 Merge pull request #3903 from laytan/allow-mem-virtual-import-on-more-targets
allow `core:mem/virtual` import on more targets by expanding the `other` implementation
2024-07-11 02:12:53 +02:00
Laytan Laats 65ca03a930 make instrumentation "work" on wasm
Using instrumentation on WASM causes it to complain about the
llvm.returnaddress instrinsic. This PR could be considered a "hack" but
makes this work by just passing `nil` instead of the return address.
2024-07-11 01:57:00 +02:00
Laytan Laats 0dfc660c71 allow core:mem/virtual import on more targets by expanding the other implementation 2024-07-11 01:55:59 +02:00
Jeroen van Rijn c49afb0039 Add hinstdll forward to runtime globals 2024-07-10 19:58:29 +02:00
Jeroen van Rijn b02291b20a Compile demo with -vet -strict-style. 2024-07-10 19:26:35 +02:00
gingerBill f75a45c3fa Add aliases starts_with and ends_with 2024-07-10 16:34:15 +01:00
gingerBill 7e41340510 Unify IUnknown COM interface 2024-07-10 15:20:07 +01:00
Jeroen van Rijn 4148c6d6c7 #if WINDOWS 2024-07-10 15:25:49 +02:00
Jeroen van Rijn cc73e06a46 Allow precompiled resources with -resource:foo.res
And add them to the magic new feature.
2024-07-10 15:09:13 +02:00
gingerBill 733b7c704c Merge branch 'master' of https://github.com/odin-lang/Odin 2024-07-10 13:45:27 +01:00
gingerBill c54e3d3c4f Improve warning handling for possible default: typo 2024-07-10 13:45:21 +01:00
Jeroen van Rijn 8dc4eca4d2 Allow using precompiled .res file. 2024-07-10 14:25:18 +02:00
gingerBill 34c6868e78 Merge pull request #3895 from laytan/fix-optimization-mode-attribute
remove misleading @(optimization_mode) values and make "none" inhibit optimizations
2024-07-10 13:22:57 +01:00
gingerBill 38315f83da Merge pull request #3898 from laytan/fix-enable-target-features-for-poly-procs
fix require/enable target feature attribute on poly procs
2024-07-10 13:22:06 +01:00
gingerBill 5aa1f3751b Merge pull request #3899 from laytan/fix-more-attributes-not-applied-to-poly-procs
fix optimization mode, cold, and disabled not being applied to poly procs
2024-07-10 13:21:57 +01:00
gingerBill 36301d0359 Give better syntax error messages for things like #define Example 123 2024-07-10 13:03:38 +01:00
gingerBill c83307f26f Give error message suggestion when doing ^x instead of x^ if x is an r-value 2024-07-10 12:39:42 +01:00
gingerBill 30204837ce Merge branch 'master' of https://github.com/odin-lang/Odin 2024-07-10 12:28:23 +01:00
gingerBill f85f6b338a Change .. variadic logic; comment out unneeded error message 2024-07-10 12:28:15 +01:00
Laytan Laats 40625b24e2 fix optimization mode, cold, and disabled not being applied to poly procs 2024-07-09 19:49:12 +02:00
Laytan Laats 1fce5791a1 fix require/enable target feature attribute on poly procs 2024-07-09 19:33:25 +02:00
Jeroen van Rijn d43a2daa17 Merge pull request #3897 from Kelimion/simd-vet
Let simd/x86 pass new transmute/cast vet.
2024-07-09 17:04:45 +02:00
Jeroen van Rijn 7b31acd2d7 Let simd/x86 pass new transmute/cast vet. 2024-07-09 16:50:55 +02:00
gingerBill b83822fd35 #3892 - Use temporary directory for asm file generation 2024-07-09 15:41:05 +01:00
gingerBill ae2f16edea Fix #3894 2024-07-09 15:29:36 +01:00
gingerBill 9782d7b928 Merge pull request #3896 from odin-lang/cached-builds
Internal Cached Builds
2024-07-09 15:27:45 +01:00
gingerBill 5627af582a Add RPROMPT to blacklist 2024-07-09 15:18:15 +01:00
gingerBill d701642293 Check for PROMPT 2024-07-09 15:15:23 +01:00
gingerBill 4c1754b1dc environ is only for Linux 2024-07-09 14:56:12 +01:00
gingerBill 666703f430 Mock out \*nix stuff for cached.cpp 2024-07-09 14:47:22 +01:00
gingerBill 14dc3598b4 Add gb_internal to procedures 2024-07-09 14:33:01 +01:00
gingerBill 330d0e7a2a Add debugf calls 2024-07-09 14:30:38 +01:00
gingerBill 952fb998e6 Check for CURR_DATE_TIME 2024-07-09 14:20:55 +01:00
gingerBill 886ee66e7f Cache files, env, and args 2024-07-09 14:16:56 +01:00
gingerBill 68b70a2183 Check for bounds check error 2024-07-09 13:35:52 +01:00
gingerBill ccdad8b8dd Add odin clear-cache 2024-07-09 13:31:54 +01:00
gingerBill 45bf180847 Add subtarget to cached executable 2024-07-08 23:55:01 +01:00
gingerBill 87ac68fcf2 Add -internal-cached 2024-07-08 23:39:14 +01:00
Jeroen van Rijn 9575d85f1a Merge pull request #3511 from IllusionMan1212/x11-xkb
vendor/x11: some XKB extension procedures and constants
2024-07-08 21:14:26 +02:00
Laytan Laats 2d8d0dd851 fix @(optimization_mode) usage in builtin collections 2024-07-08 21:07:53 +02:00
Laytan Laats 1a20b78633 remove misleading @(optimization_mode) values and make "none" inhibit optimizations 2024-07-08 21:06:57 +02:00
IllusionMan1212 0c27d95679 vendor/x11: some XKB extension procedures and constants 2024-07-08 21:00:19 +02:00
gingerBill a3af94eeae Merge pull request #3893 from laytan/temporary-directory-non-windows
implement `temporary_directory` on non-windows
2024-07-08 18:25:34 +01:00
Laytan Laats 9ff77397c6 implement temporary_directory on non-windows 2024-07-08 18:58:17 +02:00
gingerBill 48aef50164 Add #load cache files to -export-dependencies:json 2024-07-08 17:46:10 +01:00
gingerBill fc9c995dc4 Fix fmt for code compilation bug with any 2024-07-08 16:39:13 +01:00
gingerBill 564d5af8b2 Default to -o:none for all builds 2024-07-08 16:12:22 +01:00
gingerBill 2c9ef6907a Clean up timings messages showing used module count 2024-07-08 15:30:33 +01:00
gingerBill 505dec7b14 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-07-08 15:13:45 +01:00
gingerBill 2a219fa830 Correct -use-separate-module behaviour 2024-07-08 15:13:40 +01:00
gingerBill 498fb00c25 Merge pull request #3890 from laytan/llvm-18-non-windows-releases
ci: make releases use LLVM 18
2024-07-08 14:57:21 +01:00
Jeroen van Rijn ec2234560a Merge pull request #3889 from laytan/darwin-remove-implicit-syscall-usage
darwin: remove syscall usage (without -no-crt) to comply to Apple guidelines
2024-07-08 15:54:24 +02:00
Laytan Laats 5dd89a29e6 ci: make releases use LLVM 18
Since we updated to LLVM 18 on Windows now, we should make the releases
for non-windows use LLVM 18 too, this way all releases use the same version.
2024-07-08 15:49:37 +02:00
gingerBill 8491e2491c Experiment with different uses of -use-separate-modules 2024-07-08 14:48:59 +01:00
Laytan Laats ddad2011e2 darwin: remove syscall usage (without -no-crt) to comply to Apple guidelines 2024-07-08 15:39:23 +02:00
gingerBill 7dd4cccce7 Use a temporary directory for -use-separate-modules
Windows only currently
2024-07-08 14:21:07 +01:00
gingerBill 0f664893dd Add sort for global types and procedures 2024-07-08 13:59:25 +01:00
gingerBill 04e0b3e270 Merge pull request #3887 from odin-lang/windows-llvm-18
Update to LLVM 18.1.8 for Windows
2024-07-08 13:25:22 +01:00
gingerBill 930a147f24 Update to LLVM 18.1.8 2024-07-08 13:08:18 +01:00
gingerBill 86c58167ed Add -print-linker-flags 2024-07-08 10:40:04 +01:00
Jeroen van Rijn 212906ecd2 Merge pull request #3886 from laytan/cbor-enhancements
CBOR enhancements
2024-07-08 02:01:39 +02:00
Laytan Laats 6ab559437a encoding/cbor: add a custom tag to the example 2024-07-08 01:01:11 +02:00
Laytan Laats db3b4ceb4a encoding/cbor: improve perf of marshalling array-like types 2024-07-08 00:37:40 +02:00
Laytan Laats 39e9b65c59 encoding/cbor: fix umarshal of big fixed arrays 2024-07-08 00:35:19 +02:00
Laytan Laats 56856b6307 io: remove dead code in io.write_at_least 2024-07-08 00:33:50 +02:00
Jeroen van Rijn 861ad2037f Merge pull request #3884 from Feoramund/fix-3883
Forbid `$T=` parameter from crashing compiler
2024-07-06 22:08:05 +02:00
Feoramund 77d64a5461 Forbid $T= parameter from crashing compiler
Fixes #3883
2024-07-06 15:32:17 -04:00
gingerBill 88c9512d5f Merge pull request #3828 from laytan/re-raise-signals-from-odin-run
re-raise signals from the `odin run` binary
2024-07-06 18:55:37 +01:00
Jeroen van Rijn b79a098c2e Merge pull request #3882 from Kelimion/clean_up_iterator
Remove nil checks.
2024-07-06 18:45:45 +02:00
Jeroen van Rijn 258f120d52 Remove nil checks.
The caller should really not pass `foo: ^string = nil`. A `for ch, in foo` would also crash,
so let's not introduce new semantics for iteration.

A caller shouldn't pass garbage if they can help it, and a `nil` ^string is not a useful ZII usage here.
2024-07-06 18:34:52 +02:00
gingerBill 80d122f531 Merge pull request #3879 from caquillo07/hm/adding-missing-env-calls-to-core-os-darwin
Add Darwin setenv and unsetenv syscalls
2024-07-06 12:55:29 +01:00
gingerBill efe5e9e349 Merge pull request #3858 from flysand7/wow64-apiset
Add bindings for WOW64 API set
2024-07-06 00:23:47 +01:00
Jeroen van Rijn 25904e8f89 Merge pull request #3878 from Poaetce/setsid-returns-pid
[sys/linux]: change setsid to return Pid
2024-07-06 01:21:22 +02:00
Hector Mejia 2b854c94da added the setenv and unsetenv bindings for darwin, inspired but os_linux.odin 2024-07-05 16:26:03 -04:00
poa 8c98ca3a10 updated return value of setsid to return Pid 2024-07-05 22:53:45 +09:00
Jeroen van Rijn ecffe5a082 Merge pull request #3877 from Kelimion/wstring_fix
Fix utf8_to_wstring given zero bytes.
2024-07-05 13:58:49 +02:00
Jeroen van Rijn 9ecc33570b Improve fix. 2024-07-05 13:51:38 +02:00
Jeroen van Rijn 164a5e587e Fix utf8_to_wstring given zero bytes. 2024-07-05 13:46:07 +02:00
Jeroen van Rijn c8432df248 Merge pull request #3874 from laytan/fix-not-detecting-duplicate-proc-case
Fix not detecting duplicate proc cases
2024-07-05 01:00:14 +02:00
Laytan Laats f66b7021a6 Fix not detecting duplicate proc cases
Fixes #3864
2024-07-05 00:50:52 +02:00
Jeroen van Rijn 22fabba2f6 Fix #3873 2024-07-05 00:48:08 +02:00
gingerBill c77f5b00bc Merge pull request #3872 from laytan/fix-assertion-failure-on-old-llvm
Fix assertion false negative
2024-07-04 23:27:11 +01:00
Laytan Laats 1bd9fe04c4 Fix assertion false positive
Assertion was added in #3855 - https://github.com/odin-lang/Odin/pull/3855/commits/723314909679b89e159cb4cb05d250d12ac64436
to mimic LLVM's own internal assertion for this, turns out their
assertion is more sophisticated than an `==` so lets just remove it.

To be clear their internal assertion is not hit while this one is, which
defeats the purpose of ours.
2024-07-04 23:55:21 +02:00
Jeroen van Rijn 3c2161b196 Merge pull request #3870 from laytan/fix-fontstash-proc-group
vendor/fontstash: fix 'AddFont' proc group for JS target
2024-07-04 17:05:49 +02:00
Jeroen van Rijn 5247d3749c Merge pull request #3871 from Kelimion/dynlib_temp
Remove implicit allocator usage in `core:dynlib`
2024-07-04 17:05:21 +02:00
Jeroen van Rijn 8bee73b08e Remove implicit allocator usage in core:dynlib 2024-07-04 16:53:00 +02:00
Laytan Laats bcdb202639 vendor/fontstash: fix 'AddFont' proc group for JS target 2024-07-04 16:50:58 +02:00
gingerBill 1eb0bc1408 Remove *_test.odin; always compile it for all targets 2024-07-04 14:43:57 +01:00
gingerBill e9a54666e2 Fix typo. 2024-07-04 14:41:10 +01:00
gingerBill 8b7c6a23ba Restrict a bit more 2024-07-04 14:06:02 +01:00
gingerBill bf711b282d Remove when check in check_entity_from_ident_or_selector 2024-07-04 13:58:36 +01:00
gingerBill 87bccc8f3f Remove import name cases 2024-07-04 13:53:52 +01:00
gingerBill 657bc88535 Allow x :: y when cond else proc(...){...} 2024-07-04 13:48:52 +01:00
gingerBill 45b2a6a19e Fix reflect.as_pointer 2024-07-04 13:37:47 +01:00
gingerBill d78ff0be52 Fix lb_store_type_case_implicit 2024-07-04 13:20:36 +01:00
gingerBill 52c219690a Ff @(disabled=true), do not add that entity's dependencies to the set 2024-07-04 13:09:31 +01:00
gingerBill 053f1759d7 Merge pull request #3866 from DerTee/test_mem_dynamic_pool
add test for mem.dynamic_pool and fix alignment bug
2024-07-03 22:17:57 +01:00
gingerBill b65aa9c439 Merge pull request #3867 from karl-zylinski/error-on-typeof-untyped-type
error on type_of(value of untyped type)
2024-07-03 22:09:59 +01:00
Karl Zylinski 782286357b error on type_of(value of untyped type) 2024-07-03 22:21:32 +02:00
DerTee 6b373cf49e fix #3692 memory alignment bug in core:mem.dynamic_pool_alloc_bytes 2024-07-03 22:14:28 +02:00
DerTee a76f9a70d5 add test for allocator mem.Dynamic_Pool
this test currently fails because of bug #3692
2024-07-03 22:13:20 +02:00
Jeroen van Rijn a276722da5 Merge pull request #3865 from Feoramund/fix-sdl-constants
Fix SDL constants
2024-07-03 21:31:53 +02:00
Feoramund bb6cbf6559 Fix SDL constants 2024-07-03 15:22:39 -04:00
Jeroen van Rijn f6892d2236 Fix help text. 2024-07-03 19:30:25 +02:00
gingerBill 075384b2bb Fix #soa assignment bug 2024-07-03 00:33:13 +01:00
gingerBill 7e6acdf800 Merge pull request #3855 from laytan/master
Fix two LLVM assertion failures
2024-07-02 22:16:49 +01:00
gingerBill 8b49549fd3 Merge pull request #3859 from laytan/wasm-stbtt-object-linking-preopens
wasm: support `vendor:stb/truetype` and `vendor:fontstash`
2024-07-02 22:14:54 +01:00
Jeroen van Rijn 0ceae51223 Merge pull request #3862 from laytan/fix-empty-webgpu-link-errors
vendor/wgpu: fix linker errors with empty project
2024-07-02 23:05:34 +02:00
Laytan Laats 761a50e145 vendor/wgpu: fix linker errors with empty project 2024-07-02 22:37:02 +02:00
Laytan Laats 5399093050 make preopens a slice and remove bad current_dir 2024-07-02 20:17:24 +02:00
Laytan Laats 0ef5191540 use slice.ptr_swap instead of alloca 2024-07-02 20:11:44 +02:00
Laytan Laats 10c68a8951 wasm: support vendor:stb/truetype and vendor:fontstash 2024-07-02 16:03:42 +02:00
Laytan Laats 4e18e1b191 wasi: make os.open work with absolute paths 2024-07-02 15:29:24 +02:00
Laytan Laats 6f1cc8071c wasm: add foreign import and linking of wasm object files 2024-07-02 15:28:08 +02:00
flysand7 41282b5211 Add bindings for WOW64 API set 2024-07-02 21:56:04 +11:00
Jeroen van Rijn 0697fd0101 Merge pull request #3857 from flysand7/tlhelp-modentry
[sys/windows]: Fix the type declaration for MODULEENTRY32W
2024-07-02 12:42:18 +02:00
flysand7 62d107bea5 [sys/windows]: Fix the type declaration for MODULEENTRY32W 2024-07-02 21:34:54 +11:00
Andreas T Jonsson b26f4e0766 Use pkgsrc llvm for NetBSD CI 2024-07-02 11:43:01 +02:00
Laytan Laats 7233149096 fix llvm assertion failure when const initializer is not the same type 2024-07-02 01:25:52 +02:00
Laytan Laats c822f0b8c8 fix llvm assertion about metadata on non-instruction 2024-07-02 01:14:50 +02:00
Jeroen van Rijn d912c6e320 Merge pull request #3849 from Feoramund/zero-mantissa
Don't factor trailing zeroes into mantissa division
2024-07-01 20:53:07 +02:00
Jeroen van Rijn f7243eac74 Force cl.exe to parse Odin source as utf-8. 2024-07-01 20:48:00 +02:00
Jeroen van Rijn c2ab2bf25a Add UTF-8 BOM for ucg.c, because reasons. 2024-07-01 20:23:48 +02:00
Feoramund 8cd7fd95a3 Don't factor trailing zeroes into mantissa division
This should fix issues where `N00 / (pow+2)` results in a different number
than `N / pow`.
2024-06-30 22:18:25 -04:00
Feoramund 8b915aae5e Update code for new -vet 2024-06-30 11:18:40 -04:00
Feoramund f0cf1052d0 Fix FreeBSD recvfrom
`fromlen` must be a pointer, not a value.
2024-06-30 10:17:32 -04:00
Laytan Laats fa5be93da2 re-raise signals from the odin run binary 2024-06-28 19:33:34 +02:00
Feoramund ba05c74936 Enable core:net tests for FreeBSD 2024-06-26 10:05:24 -04:00
Feoramund e61d893a74 Port core:net to FreeBSD 2024-06-26 10:05:24 -04:00
Feoramund 10ce76fcc2 Fix FreeBSD futex implementation
- Add missing size of timeout struct to `_umtx_op`.
- Use `WAIT_UINT` not `WAIT`, as the expected value is an unsigned integer.
- Use new native calls instead of libc.
2024-06-26 10:02:07 -04:00
Feoramund c61f5bbfe7 Add core:sys/freebsd 2024-06-26 10:02:06 -04:00
Thomas la Cour acce9acb6d Merge remote-tracking branch 'upstream/master' into sys-windows-2 2024-06-13 18:31:53 +02:00
Thomas la Cour 8403952fd2 win32gen 2024-06-11 18:30:41 +02:00
Thomas la Cour 32dcb3caef windows bindings test 2024-06-11 18:19:29 +02:00
Thomas la Cour 465ac74020 more windows stuff 2024-06-11 18:19:16 +02:00
PucklaJ 37b026cb9b [sys/linux] Directly call syscall in execve on arm64 2024-04-28 12:00:40 +02:00
PucklaJ d1a205e2cf [sys/linux]: Remove clone syscall and call it directly in fork on arm64 2024-04-28 11:56:19 +02:00
PucklaJ 7f301790d0 [sys/linux] Change flags parameter of execveat to bit_set 2024-04-28 11:48:18 +02:00
PucklaJ b0fe6212bb [sys/linux]: Fix return statement 2024-04-27 13:21:04 +02:00
PucklaJ a2ad66cd9d [sys/linux]: Add clone syscall and use it in fork for arm64 2024-04-24 15:32:43 +02:00
PucklaJ 2bf00d9b3f [sys/linux]: Add flags parameter to execveat and fix execve on arm64 2024-04-24 15:15:38 +02:00
Beau McCartney 43e8da2e06 shm_open: comment with notes abt permissions 2024-03-19 09:36:49 -06:00
Beau McCartney 1758bd683e sys_shm_open: fchmod the returned descriptor to get correct perms
this doesn't happen by default
2024-03-16 12:13:00 -06:00
Eric Johnson 4b7f32c287 Update mem doc example formatting 2024-03-15 12:26:01 -07:00
Beau McCartney 24f9e16dfd sys_open() calls _sys_open_mode() to get a permission flags integer
_sys_open_mode() does exactly what sys_open() was originally doing
inline, I simply factored it into a separate function so that other
wrappers could call it (similar to _sys_permission_mode())
2024-03-15 08:32:25 -06:00
Beau McCartney 56a29685b4 darwin: sys_shm_open() helper
wraps syscall_shm_open() in the same way that sys_open() wraps
syscall_open()
2024-03-15 08:27:27 -06:00
Beau McCartney cf949e541f helper function to convert Open_Flags bitset to a u32
- analagous to _sys_permission_mode()
- uses the already-existing conversion logic in sys_open()
2024-03-15 08:26:25 -06:00
Beau McCartney 44167800ad darwin: syscall wrappers for shm_open() and shm_unlink() 2024-03-15 08:26:03 -06:00
marcs feh 9c6574e053 Merge branch 'odin-lang:master' into master 2024-02-11 23:55:39 +00:00
marcs feh fc113315f6 Merge branch 'odin-lang:master' into master 2024-02-02 21:56:40 -03:00
marcs-feh d931bfcf83 resolve conflict 2024-01-26 16:23:16 -03:00
marcs-feh b58627490b Adjust signture + Fix rebase conflict 2024-01-26 12:10:15 -03:00
marcs feh dbaa82b581 Merge branch 'odin-lang:master' into master 2024-01-24 20:10:44 -03:00
marcs-feh 84123cc879 sys/linux: Adjust ioctl signature to fit the actual Linux Kernel implementation 2024-01-24 13:40:50 -03:00
marcs-feh 7b1f58a06a sys/linux: Add binding to ioctl syscall + fd consts
Add binding to ioctl syscall, due to the vast nature of this syscall
adding more device specific request values is possible. Also added the
stdin, stdout and stderr, to constants.odin
2024-01-22 16:09:44 -03:00
jakubtomsu fe268a9dd2 Add nullptr check back 2023-11-25 13:29:28 +01:00
jakubtomsu 3c25d93eae Check for variadic param default val 2023-11-25 13:20:34 +01:00
932 changed files with 84553 additions and 13911 deletions
+73 -33
View File
@@ -6,7 +6,7 @@ jobs:
name: NetBSD Build, Check, and Test
runs-on: ubuntu-latest
env:
PKGSRC_BRANCH: 2024Q1
PKGSRC_BRANCH: 2024Q2
steps:
- uses: actions/checkout@v4
- name: Build, Check, and Test
@@ -18,13 +18,11 @@ jobs:
usesh: true
copyback: false
prepare: |
PKG_PATH="https://cdn.NetBSD.org/pub/pkgsrc/packages/NetBSD/$(uname -p)/$(uname -r | cut -d_ -f1)_${PKGSRC_BRANCH}/All" /usr/sbin/pkg_add pkgin
pkgin -y in gmake git bash python311
pkgin -y in libxml2 perl zstd
/usr/sbin/pkg_add https://github.com/andreas-jonsson/llvm17-netbsd-bin/releases/download/pkgsrc-current/llvm-17.0.6.tgz
/usr/sbin/pkg_add https://github.com/andreas-jonsson/llvm17-netbsd-bin/releases/download/pkgsrc-current/clang-17.0.6.tgz
PKG_PATH="https://cdn.NetBSD.org/pub/pkgsrc/packages/NetBSD/amd64/$(uname -r | cut -d_ -f1)_${PKGSRC_BRANCH}/All" /usr/sbin/pkg_add pkgin
pkgin -y in gmake git bash python311 llvm clang
ln -s /usr/pkg/bin/python3.11 /usr/bin/python3
run: |
set -e -x
git config --global --add safe.directory $(pwd)
gmake release
./odin version
@@ -34,10 +32,9 @@ jobs:
gmake -C vendor/miniaudio/src
./odin check examples/all -vet -strict-style -disallow-do -target:netbsd_amd64
./odin check examples/all -vet -strict-style -disallow-do -target:netbsd_arm64
./odin test tests/core/normal.odin -file -all-packages -define:ODIN_TEST_FANCY=false
./odin test tests/core/speed.odin -file -all-packages -o:speed -define:ODIN_TEST_FANCY=false
./odin test tests/vendor -all-packages -define:ODIN_TEST_FANCY=false
./odin test tests/benchmark -all-packages -define:ODIN_TEST_FANCY=false
./odin test tests/core/normal.odin -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
./odin test tests/core/speed.odin -file -all-packages -vet -strict-style -disallow-do -o:speed -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
./odin test tests/vendor -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
(cd tests/issues; ./run.sh)
build_freebsd:
name: FreeBSD Build, Check, and Test
@@ -63,10 +60,9 @@ jobs:
gmake -C vendor/cgltf/src
gmake -C vendor/miniaudio/src
./odin check examples/all -vet -strict-style -disallow-do -target:freebsd_amd64
./odin test tests/core/normal.odin -file -all-packages -define:ODIN_TEST_FANCY=false
./odin test tests/core/speed.odin -file -all-packages -o:speed -define:ODIN_TEST_FANCY=false
./odin test tests/vendor -all-packages -define:ODIN_TEST_FANCY=false
./odin test tests/benchmark -all-packages -define:ODIN_TEST_FANCY=false
./odin test tests/core/normal.odin -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
./odin test tests/core/speed.odin -file -all-packages -vet -strict-style -disallow-do -o:speed -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
./odin test tests/vendor -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
(cd tests/issues; ./run.sh)
ci:
strategy:
@@ -91,13 +87,13 @@ jobs:
- name: Download LLVM (MacOS Intel)
if: matrix.os == 'macos-13'
run: |
brew install llvm@17
brew install llvm@17 lua@5.4
echo "/usr/local/opt/llvm@17/bin" >> $GITHUB_PATH
- name: Download LLVM (MacOS ARM)
if: matrix.os == 'macos-14'
run: |
brew install llvm@17 wasmtime
brew install llvm@17 wasmtime lua@5.4
echo "/opt/homebrew/opt/llvm@17/bin" >> $GITHUB_PATH
- name: Build Odin
@@ -120,15 +116,13 @@ jobs:
- name: Odin check examples/all
run: ./odin check examples/all -strict-style
- name: Normal Core library tests
run: ./odin test tests/core/normal.odin -file -all-packages -define:ODIN_TEST_FANCY=false
run: ./odin test tests/core/normal.odin -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
- name: Optimized Core library tests
run: ./odin test tests/core/speed.odin -o:speed -file -all-packages -define:ODIN_TEST_FANCY=false
run: ./odin test tests/core/speed.odin -o:speed -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
- name: Vendor library tests
run: ./odin test tests/vendor -all-packages -define:ODIN_TEST_FANCY=false
run: ./odin test tests/vendor -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
- name: Internals tests
run: ./odin test tests/internal -all-packages -define:ODIN_TEST_FANCY=false
- name: Core library benchmarks
run: ./odin test tests/benchmark -all-packages -define:ODIN_TEST_FANCY=false
run: ./odin test tests/internal -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
- name: GitHub Issue tests
run: |
cd tests/issues
@@ -182,37 +176,33 @@ jobs:
shell: cmd
run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin run examples/demo -debug
odin run examples/demo -debug -vet -strict-style -disallow-do
- name: Odin check examples/all
shell: cmd
run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin check examples/all -strict-style
odin check examples/all -vet -strict-style -disallow-do
- name: Core library tests
shell: cmd
run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin test tests/core/normal.odin -file -all-packages -define:ODIN_TEST_FANCY=false
odin test tests/core/normal.odin -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
- name: Optimized core library tests
shell: cmd
run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin test tests/core/speed.odin -o:speed -file -all-packages -define:ODIN_TEST_FANCY=false
- name: Core library benchmarks
shell: cmd
run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin test tests/benchmark -all-packages -define:ODIN_TEST_FANCY=false
odin test tests/core/speed.odin -o:speed -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
- name: Vendor library tests
shell: cmd
run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin test tests/vendor -all-packages -define:ODIN_TEST_FANCY=false
copy vendor\lua\5.4\windows\*.dll .
odin test tests/vendor -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
- name: Odin internals tests
shell: cmd
run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin test tests/internal -all-packages -define:ODIN_TEST_FANCY=false
odin test tests/internal -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
- name: Odin documentation tests
shell: cmd
run: |
@@ -230,3 +220,53 @@ jobs:
run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin check examples/all -strict-style -target:windows_i386
build_linux_riscv64:
runs-on: ubuntu-latest
name: Linux riscv64 (emulated) Build, Check and Test
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- name: Download LLVM (Linux)
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 18
echo "/usr/lib/llvm-18/bin" >> $GITHUB_PATH
- name: Build Odin
run: ./build_odin.sh release
- name: Odin version
run: ./odin version
- name: Odin report
run: ./odin report
- name: Compile needed Vendor
run: |
make -C vendor/stb/src
make -C vendor/cgltf/src
make -C vendor/miniaudio/src
- name: Odin check
run: ./odin check examples/all -target:linux_riscv64 -vet -strict-style -disallow-do
- name: Install riscv64 toolchain and qemu
run: sudo apt-get install -y qemu-user qemu-user-static gcc-12-riscv64-linux-gnu libc6-riscv64-cross
- name: Odin run
run: ./odin run examples/demo -vet -strict-style -disallow-do -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" -no-rpath
- name: Odin run -debug
run: ./odin run examples/demo -debug -vet -strict-style -disallow-do -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" -no-rpath
- name: Normal Core library tests
run: ./odin test tests/core/normal.odin -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" -no-rpath
- name: Optimized Core library tests
run: ./odin test tests/core/speed.odin -o:speed -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" -no-rpath
- name: Internals tests
run: ./odin test tests/internal -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" -no-rpath
+90 -64
View File
@@ -36,44 +36,54 @@ jobs:
cp -r bin dist
cp -r examples dist
- name: Upload artifact
uses: actions/upload-artifact@v1
uses: actions/upload-artifact@v4
with:
name: windows_artifacts
path: dist
build_ubuntu:
name: Ubuntu Build
build_linux:
name: Linux Build
if: github.repository == 'odin-lang/Odin'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: jirutka/setup-alpine@v1
with:
branch: v3.20
- name: (Linux) Download LLVM
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 17
echo "/usr/lib/llvm-17/bin" >> $GITHUB_PATH
apk add --no-cache \
musl-dev llvm18-dev clang18 git mold lz4 \
libxml2-static llvm18-static zlib-static zstd-static \
make
shell: alpine.sh --root {0}
- name: build odin
run: make nightly
# NOTE: this build does slow compile times because of musl
run: ci/build_linux_static.sh
shell: alpine.sh {0}
- name: Odin run
run: ./odin run examples/demo
- name: Copy artifacts
run: |
mkdir dist
cp odin dist
cp LICENSE dist
cp libLLVM* dist
cp -r shared dist
cp -r base dist
cp -r core dist
cp -r vendor dist
cp -r examples dist
# Zipping so executable permissions are retained, see https://github.com/actions/upload-artifact/issues/38
zip -r dist.zip dist
FILE="odin-linux-amd64-nightly+$(date -I)"
mkdir $FILE
cp odin $FILE
cp LICENSE $FILE
cp -r shared $FILE
cp -r base $FILE
cp -r core $FILE
cp -r vendor $FILE
cp -r examples $FILE
# Creating a tarball so executable permissions are retained, see https://github.com/actions/upload-artifact/issues/38
tar -czvf dist.tar.gz $FILE
- name: Odin run
run: |
FILE="odin-linux-amd64-nightly+$(date -I)"
$FILE/odin run examples/demo
- name: Upload artifact
uses: actions/upload-artifact@v1
uses: actions/upload-artifact@v4
with:
name: ubuntu_artifacts
path: dist.zip
name: linux_artifacts
path: dist.tar.gz
build_macos:
name: MacOS Build
if: github.repository == 'odin-lang/Odin'
@@ -82,32 +92,35 @@ jobs:
- uses: actions/checkout@v4
- name: Download LLVM and setup PATH
run: |
brew install llvm@17 dylibbundler
echo "/usr/local/opt/llvm@17/bin" >> $GITHUB_PATH
brew install llvm@18 dylibbundler
echo "/usr/local/opt/llvm@18/bin" >> $GITHUB_PATH
- name: build odin
# These -L makes the linker prioritize system libraries over LLVM libraries, this is mainly to
# not link with libunwind bundled with LLVM but link with libunwind on the system.
run: CXXFLAGS="-L/usr/lib/system -L/usr/lib" make nightly
- name: Bundle
run: |
mkdir dist
cp odin dist
cp LICENSE dist
cp -r shared dist
cp -r base dist
cp -r core dist
cp -r vendor dist
cp -r examples dist
dylibbundler -b -x dist/odin -d dist/libs -od -p @executable_path/libs
# Zipping so executable permissions are retained, see https://github.com/actions/upload-artifact/issues/38
zip -r dist.zip dist
FILE="odin-macos-amd64-nightly+$(date -I)"
mkdir $FILE
cp odin $FILE
cp LICENSE $FILE
cp -r shared $FILE
cp -r base $FILE
cp -r core $FILE
cp -r vendor $FILE
cp -r examples $FILE
dylibbundler -b -x $FILE/odin -d $FILE/libs -od -p @executable_path/libs
# Creating a tarball so executable permissions are retained, see https://github.com/actions/upload-artifact/issues/38
tar -czvf dist.tar.gz $FILE
- name: Odin run
run: ./dist/odin run examples/demo
run: |
FILE="odin-macos-amd64-nightly+$(date -I)"
$FILE/odin run examples/demo
- name: Upload artifact
uses: actions/upload-artifact@v1
uses: actions/upload-artifact@v4
with:
name: macos_artifacts
path: dist.zip
path: dist.tar.gz
build_macos_arm:
name: MacOS ARM Build
if: github.repository == 'odin-lang/Odin'
@@ -116,38 +129,41 @@ jobs:
- uses: actions/checkout@v4
- name: Download LLVM and setup PATH
run: |
brew install llvm@17 dylibbundler
echo "/opt/homebrew/opt/llvm@17/bin" >> $GITHUB_PATH
brew install llvm@18 dylibbundler
echo "/opt/homebrew/opt/llvm@18/bin" >> $GITHUB_PATH
- name: build odin
# These -L makes the linker prioritize system libraries over LLVM libraries, this is mainly to
# not link with libunwind bundled with LLVM but link with libunwind on the system.
run: CXXFLAGS="-L/usr/lib/system -L/usr/lib" make nightly
- name: Bundle
run: |
mkdir dist
cp odin dist
cp LICENSE dist
cp -r shared dist
cp -r base dist
cp -r core dist
cp -r vendor dist
cp -r examples dist
dylibbundler -b -x dist/odin -d dist/libs -od -p @executable_path/libs
# Zipping so executable permissions are retained, see https://github.com/actions/upload-artifact/issues/38
zip -r dist.zip dist
FILE="odin-macos-arm64-nightly+$(date -I)"
mkdir $FILE
cp odin $FILE
cp LICENSE $FILE
cp -r shared $FILE
cp -r base $FILE
cp -r core $FILE
cp -r vendor $FILE
cp -r examples $FILE
dylibbundler -b -x $FILE/odin -d $FILE/libs -od -p @executable_path/libs
# Creating a tarball so executable permissions are retained, see https://github.com/actions/upload-artifact/issues/38
tar -czvf dist.tar.gz $FILE
- name: Odin run
run: ./dist/odin run examples/demo
run: |
FILE="odin-macos-arm64-nightly+$(date -I)"
$FILE/odin run examples/demo
- name: Upload artifact
uses: actions/upload-artifact@v1
uses: actions/upload-artifact@v4
with:
name: macos_arm_artifacts
path: dist.zip
path: dist.tar.gz
upload_b2:
runs-on: [ubuntu-latest]
needs: [build_windows, build_macos, build_macos_arm, build_ubuntu]
needs: [build_windows, build_macos, build_macos_arm, build_linux]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v2
- uses: actions/setup-python@v5
with:
python-version: '3.8.x'
@@ -161,24 +177,33 @@ jobs:
run: python -c "import sys; print(sys.version)"
- name: Download Windows artifacts
uses: actions/download-artifact@v1
uses: actions/download-artifact@v4.1.7
with:
name: windows_artifacts
path: windows_artifacts
- name: Download Ubuntu artifacts
uses: actions/download-artifact@v1
uses: actions/download-artifact@v4.1.7
with:
name: ubuntu_artifacts
name: linux_artifacts
path: linux_artifacts
- name: Download macOS artifacts
uses: actions/download-artifact@v1
uses: actions/download-artifact@v4.1.7
with:
name: macos_artifacts
path: macos_artifacts
- name: Download macOS arm artifacts
uses: actions/download-artifact@v1
uses: actions/download-artifact@v4.1.7
with:
name: macos_arm_artifacts
path: macos_arm_artifacts
- name: Debug
run: |
tree -L 2
- name: Create archives and upload
shell: bash
@@ -188,9 +213,10 @@ jobs:
BUCKET: ${{ secrets.B2_BUCKET }}
DAYS_TO_KEEP: ${{ secrets.B2_DAYS_TO_KEEP }}
run: |
file linux_artifacts/dist.tar.gz
python3 ci/nightly.py artifact windows-amd64 windows_artifacts/
python3 ci/nightly.py artifact ubuntu-amd64 ubuntu_artifacts/dist.zip
python3 ci/nightly.py artifact macos-amd64 macos_artifacts/dist.zip
python3 ci/nightly.py artifact macos-arm64 macos_arm_artifacts/dist.zip
python3 ci/nightly.py artifact linux-amd64 linux_artifacts/dist.tar.gz
python3 ci/nightly.py artifact macos-amd64 macos_artifacts/dist.tar.gz
python3 ci/nightly.py artifact macos-arm64 macos_arm_artifacts/dist.tar.gz
python3 ci/nightly.py prune
python3 ci/nightly.py json
+4 -34
View File
@@ -17,45 +17,12 @@
[Rr]eleases/
x64/
x86/
!/core/simd/x86
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
![Cc]ore/[Ll]og/
tests/documentation/verify/
tests/documentation/all.odin-doc
tests/internal/test_map
tests/internal/test_pow
tests/internal/test_rtti
tests/core/test_base64
tests/core/test_cbor
tests/core/test_core_compress
tests/core/test_core_container
tests/core/test_core_filepath
tests/core/test_core_fmt
tests/core/test_core_i18n
tests/core/test_core_image
tests/core/test_core_libc
tests/core/test_core_match
tests/core/test_core_math
tests/core/test_core_net
tests/core/test_core_os_exit
tests/core/test_core_reflect
tests/core/test_core_strings
tests/core/test_core_time
tests/core/test_crypto
tests/core/test_hash
tests/core/test_hex
tests/core/test_hxa
tests/core/test_json
tests/core/test_linalg_glsl_math
tests/core/test_noise
tests/core/test_varint
tests/core/test_xml
tests/core/test_core_slice
tests/core/test_core_thread
tests/core/test_core_runtime
tests/vendor/vendor_botan
# Visual Studio 2015 cache/options directory
.vs/
# Visual Studio Code options directory
@@ -299,6 +266,9 @@ bin/
*.exe
*.obj
*.pdb
*.res
desktop.ini
Thumbs.db
# - Linux/MacOS
odin
BIN
View File
Binary file not shown.
+7 -1
View File
@@ -1,4 +1,4 @@
all: debug
all: default
demo:
./odin run examples/demo/demo.odin -file
@@ -6,12 +6,18 @@ demo:
report:
./odin report
default:
PROGRAM=make ./build_odin.sh # debug
debug:
./build_odin.sh debug
release:
./build_odin.sh release
release-native:
./build_odin.sh release-native
release_native:
./build_odin.sh release-native
+2 -2
View File
@@ -76,9 +76,9 @@ Answers to common questions about Odin.
Documentation for all the official packages part of the [core](https://pkg.odin-lang.org/core/) and [vendor](https://pkg.odin-lang.org/vendor/) library collections.
#### [The Odin Wiki](https://github.com/odin-lang/Odin/wiki)
#### [Odin Documentation](https://odin-lang.org/docs/)
A wiki maintained by the Odin community.
Documentation for the Odin language itself.
#### [Odin Discord](https://discord.gg/sVBPHEv)
+40 -18
View File
@@ -1,5 +1,5 @@
// This is purely for documentation
//+build ignore
#+build ignore
package intrinsics
// Package-Related
@@ -38,9 +38,12 @@ count_leading_zeros :: proc(x: $T) -> T where type_is_integer(T) || type_is_sim
reverse_bits :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) ---
byte_swap :: proc(x: $T) -> T where type_is_integer(T) || type_is_float(T) ---
overflow_add :: proc(lhs, rhs: $T) -> (T, bool) ---
overflow_sub :: proc(lhs, rhs: $T) -> (T, bool) ---
overflow_mul :: proc(lhs, rhs: $T) -> (T, bool) ---
overflow_add :: proc(lhs, rhs: $T) -> (T, bool) where type_is_integer(T) #optional_ok ---
overflow_sub :: proc(lhs, rhs: $T) -> (T, bool) where type_is_integer(T) #optional_ok ---
overflow_mul :: proc(lhs, rhs: $T) -> (T, bool) where type_is_integer(T) #optional_ok ---
saturating_add :: proc(lhs, rhs: $T) -> T where type_is_integer(T) ---
saturating_sub :: proc(lhs, rhs: $T) -> T where type_is_integer(T) ---
sqrt :: proc(x: $T) -> T where type_is_float(T) || (type_is_simd_vector(T) && type_is_float(type_elem_type(T))) ---
@@ -216,14 +219,21 @@ type_map_cell_info :: proc($T: typeid) -> ^runtime.Map_Cell_Info ---
type_convert_variants_to_pointers :: proc($T: typeid) -> typeid where type_is_union(T) ---
type_merge :: proc($U, $V: typeid) -> typeid where type_is_union(U), type_is_union(V) ---
type_has_shared_fields :: proc($U, $V: typeid) -> bool typeid where type_is_struct(U), type_is_struct(V) ---
constant_utf16_cstring :: proc($literal: string) -> [^]u16 ---
constant_log2 :: proc($v: $T) -> T where type_is_integer(T) ---
// SIMD related
simd_add :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_sub :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_mul :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_div :: proc(a, b: #simd[N]T) -> #simd[N]T where type_is_float(T) ---
simd_saturating_add :: proc(a, b: #simd[N]T) -> #simd[N]T where type_is_integer(T) ---
simd_saturating_sub :: proc(a, b: #simd[N]T) -> #simd[N]T where type_is_integer(T) ---
// Keeps Odin's Behaviour
// (x << y) if y <= mask else 0
simd_shl :: proc(a: #simd[N]T, b: #simd[N]Unsigned_Integer) -> #simd[N]T ---
@@ -234,9 +244,6 @@ simd_shr :: proc(a: #simd[N]T, b: #simd[N]Unsigned_Integer) -> #simd[N]T ---
simd_shl_masked :: proc(a: #simd[N]T, b: #simd[N]Unsigned_Integer) -> #simd[N]T ---
simd_shr_masked :: proc(a: #simd[N]T, b: #simd[N]Unsigned_Integer) -> #simd[N]T ---
simd_add_sat :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_sub_sat :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_bit_and :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_bit_or :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_bit_xor :: proc(a, b: #simd[N]T) -> #simd[N]T ---
@@ -265,13 +272,28 @@ simd_lanes_ge :: proc(a, b: #simd[N]T) -> #simd[N]Integer ---
simd_extract :: proc(a: #simd[N]T, idx: uint) -> T ---
simd_replace :: proc(a: #simd[N]T, idx: uint, elem: T) -> #simd[N]T ---
simd_reduce_add_ordered :: proc(a: #simd[N]T) -> T ---
simd_reduce_mul_ordered :: proc(a: #simd[N]T) -> T ---
simd_reduce_min :: proc(a: #simd[N]T) -> T ---
simd_reduce_max :: proc(a: #simd[N]T) -> T ---
simd_reduce_and :: proc(a: #simd[N]T) -> T ---
simd_reduce_or :: proc(a: #simd[N]T) -> T ---
simd_reduce_xor :: proc(a: #simd[N]T) -> T ---
simd_reduce_add_ordered :: proc(a: #simd[N]T) -> T where type_is_integer(T) || type_is_float(T)---
simd_reduce_mul_ordered :: proc(a: #simd[N]T) -> T where type_is_integer(T) || type_is_float(T)---
simd_reduce_min :: proc(a: #simd[N]T) -> T where type_is_integer(T) || type_is_float(T)---
simd_reduce_max :: proc(a: #simd[N]T) -> T where type_is_integer(T) || type_is_float(T)---
simd_reduce_and :: proc(a: #simd[N]T) -> T where type_is_integer(T) || type_is_float(T)---
simd_reduce_or :: proc(a: #simd[N]T) -> T where type_is_integer(T) || type_is_float(T)---
simd_reduce_xor :: proc(a: #simd[N]T) -> T where type_is_integer(T) || type_is_float(T)---
simd_reduce_any :: proc(a: #simd[N]T) -> T where type_is_boolean(T) ---
simd_reduce_all :: proc(a: #simd[N]T) -> T where type_is_boolean(T) ---
simd_gather :: proc(ptr: #simd[N]rawptr, val: #simd[N]T, mask: #simd[N]U) -> #simd[N]T where type_is_integer(U) || type_is_boolean(U) ---
simd_scatter :: proc(ptr: #simd[N]rawptr, val: #simd[N]T, mask: #simd[N]U) where type_is_integer(U) || type_is_boolean(U) ---
simd_masked_load :: proc(ptr: rawptr, val: #simd[N]T, mask: #simd[N]U) -> #simd[N]T where type_is_integer(U) || type_is_boolean(U) ---
simd_masked_store :: proc(ptr: rawptr, val: #simd[N]T, mask: #simd[N]U) where type_is_integer(U) || type_is_boolean(U) ---
simd_masked_expand_load :: proc(ptr: rawptr, val: #simd[N]T, mask: #simd[N]U) -> #simd[N]T where type_is_integer(U) || type_is_boolean(U) ---
simd_masked_compress_store :: proc(ptr: rawptr, val: #simd[N]T, mask: #simd[N]U) where type_is_integer(U) || type_is_boolean(U) ---
simd_shuffle :: proc(a, b: #simd[N]T, indices: ..int) -> #simd[len(indices)]T ---
simd_select :: proc(cond: #simd[N]boolean_or_integer, true, false: #simd[N]T) -> #simd[N]T ---
@@ -285,11 +307,11 @@ simd_nearest :: proc(a: #simd[N]any_float) -> #simd[N]any_float ---
simd_to_bits :: proc(v: #simd[N]T) -> #simd[N]Integer where size_of(T) == size_of(Integer), type_is_unsigned(Integer) ---
// equivalent a swizzle with descending indices, e.g. reserve(a, 3, 2, 1, 0)
simd_reverse :: proc(a: #simd[N]T) -> #simd[N]T ---
// equivalent to a swizzle with descending indices, e.g. reserve(a, 3, 2, 1, 0)
simd_lanes_reverse :: proc(a: #simd[N]T) -> #simd[N]T ---
simd_rotate_left :: proc(a: #simd[N]T, $offset: int) -> #simd[N]T ---
simd_rotate_right :: proc(a: #simd[N]T, $offset: int) -> #simd[N]T ---
simd_lanes_rotate_left :: proc(a: #simd[N]T, $offset: int) -> #simd[N]T ---
simd_lanes_rotate_right :: proc(a: #simd[N]T, $offset: int) -> #simd[N]T ---
// Checks if the current target supports the given target features.
//
+70 -24
View File
@@ -18,7 +18,7 @@
// This could change at a later date if the all these data structures are
// implemented within the compiler rather than in this "preload" file
//
//+no-instrumentation
#+no-instrumentation
package runtime
import "base:intrinsics"
@@ -66,7 +66,7 @@ Type_Info_Named :: struct {
name: string,
base: ^Type_Info,
pkg: string,
loc: Source_Code_Location,
loc: ^Source_Code_Location,
}
Type_Info_Integer :: struct {signed: bool, endianness: Platform_Endianness}
Type_Info_Rune :: struct {}
@@ -112,23 +112,32 @@ Type_Info_Parameters :: struct { // Only used for procedures parameters and resu
}
Type_Info_Tuple :: Type_Info_Parameters // Will be removed eventually
Type_Info_Struct :: struct {
types: []^Type_Info,
names: []string,
offsets: []uintptr,
usings: []bool,
tags: []string,
is_packed: bool,
is_raw_union: bool,
is_no_copy: bool,
custom_align: bool,
Type_Info_Struct_Flags :: distinct bit_set[Type_Info_Struct_Flag; u8]
Type_Info_Struct_Flag :: enum u8 {
packed = 0,
raw_union = 1,
no_copy = 2,
align = 3,
}
equal: Equal_Proc, // set only when the struct has .Comparable set but does not have .Simple_Compare set
Type_Info_Struct :: struct {
// Slice these with `field_count`
types: [^]^Type_Info `fmt:"v,field_count"`,
names: [^]string `fmt:"v,field_count"`,
offsets: [^]uintptr `fmt:"v,field_count"`,
usings: [^]bool `fmt:"v,field_count"`,
tags: [^]string `fmt:"v,field_count"`,
field_count: i32,
flags: Type_Info_Struct_Flags,
// These are only set iff this structure is an SOA structure
soa_kind: Type_Info_Struct_Soa_Kind,
soa_len: i32,
soa_base_type: ^Type_Info,
soa_len: int,
equal: Equal_Proc, // set only when the struct has .Comparable set but does not have .Simple_Compare set
}
Type_Info_Union :: struct {
variants: []^Type_Info,
@@ -142,9 +151,9 @@ Type_Info_Union :: struct {
shared_nil: bool,
}
Type_Info_Enum :: struct {
base: ^Type_Info,
names: []string,
values: []Type_Info_Enum_Value,
base: ^Type_Info,
names: []string,
values: []Type_Info_Enum_Value,
}
Type_Info_Map :: struct {
key: ^Type_Info,
@@ -187,11 +196,12 @@ Type_Info_Soa_Pointer :: struct {
}
Type_Info_Bit_Field :: struct {
backing_type: ^Type_Info,
names: []string,
types: []^Type_Info,
bit_sizes: []uintptr,
bit_offsets: []uintptr,
tags: []string,
names: [^]string `fmt:"v,field_count"`,
types: [^]^Type_Info `fmt:"v,field_count"`,
bit_sizes: [^]uintptr `fmt:"v,field_count"`,
bit_offsets: [^]uintptr `fmt:"v,field_count"`,
tags: [^]string `fmt:"v,field_count"`,
field_count: int,
}
Type_Info_Flag :: enum u8 {
@@ -299,6 +309,8 @@ when ODIN_OS == .Windows {
Thread_Detach = 3,
}
dll_forward_reason: DLL_Forward_Reason
dll_instance: rawptr
}
// IMPORTANT NOTE(bill): Must be in this order (as the compiler relies upon it)
@@ -513,11 +525,12 @@ Raw_Quaternion256_Vector_Scalar :: struct {vector: [3]f64, scalar: f64}
Linux,
Essence,
FreeBSD,
Haiku,
OpenBSD,
NetBSD,
Haiku,
WASI,
JS,
Orca,
Freestanding,
}
*/
@@ -533,10 +546,23 @@ Odin_OS_Type :: type_of(ODIN_OS)
arm64,
wasm32,
wasm64p32,
riscv64,
}
*/
Odin_Arch_Type :: type_of(ODIN_ARCH)
Odin_Arch_Types :: bit_set[Odin_Arch_Type]
ALL_ODIN_ARCH_TYPES :: Odin_Arch_Types{
.amd64,
.i386,
.arm32,
.arm64,
.wasm32,
.wasm64p32,
.riscv64,
}
/*
// Defined internally by the compiler
Odin_Build_Mode_Type :: enum int {
@@ -560,6 +586,22 @@ Odin_Build_Mode_Type :: type_of(ODIN_BUILD_MODE)
*/
Odin_Endian_Type :: type_of(ODIN_ENDIAN)
Odin_OS_Types :: bit_set[Odin_OS_Type]
ALL_ODIN_OS_TYPES :: Odin_OS_Types{
.Windows,
.Darwin,
.Linux,
.Essence,
.FreeBSD,
.OpenBSD,
.NetBSD,
.Haiku,
.WASI,
.JS,
.Orca,
.Freestanding,
}
/*
// Defined internally by the compiler
@@ -577,7 +619,7 @@ Odin_Platform_Subtarget_Type :: type_of(ODIN_PLATFORM_SUBTARGET)
Memory = 1,
Thread = 2,
}
Odin_Sanitizer_Flags :: distinct bitset[Odin_Sanitizer_Flag; u32]
Odin_Sanitizer_Flags :: distinct bit_set[Odin_Sanitizer_Flag; u32]
ODIN_SANITIZER_FLAGS // is a constant
*/
@@ -737,6 +779,10 @@ __init_context :: proc "contextless" (c: ^Context) {
}
default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code_Location) -> ! {
default_assertion_contextless_failure_proc(prefix, message, loc)
}
default_assertion_contextless_failure_proc :: proc "contextless" (prefix, message: string, loc: Source_Code_Location) -> ! {
when ODIN_OS == .Freestanding {
// Do nothing
} else {
+178 -113
View File
@@ -6,6 +6,39 @@ import "base:intrinsics"
Maybe :: union($T: typeid) {T}
/*
Recovers the containing/parent struct from a pointer to one of its fields.
Works by "walking back" to the struct's starting address using the offset between the field and the struct.
Inputs:
- ptr: Pointer to the field of a container struct
- T: The type of the container struct
- field_name: The name of the field in the `T` struct
Returns:
- A pointer to the container struct based on a pointer to a field in it
Example:
package container_of
import "base:runtime"
Node :: struct {
value: int,
prev: ^Node,
next: ^Node,
}
main :: proc() {
node: Node
field_ptr := &node.next
container_struct_ptr: ^Node = runtime.container_of(field_ptr, Node, "next")
assert(container_struct_ptr == &node)
assert(uintptr(field_ptr) - uintptr(container_struct_ptr) == size_of(node.value) + size_of(node.prev))
}
Output:
^Node
*/
@(builtin, require_results)
container_of :: #force_inline proc "contextless" (ptr: $P/^$Field_Type, $T: typeid, $field_name: string) -> ^T
where intrinsics.type_has_field(T, field_name),
@@ -68,7 +101,7 @@ copy :: proc{copy_slice, copy_from_string}
// Note: If you want the elements to remain in their order, use `ordered_remove`.
// Note: If the index is out of bounds, this procedure will panic.
@builtin
unordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_location) #no_bounds_check {
unordered_remove :: proc(array: ^$D/[dynamic]$T, #any_int index: int, loc := #caller_location) #no_bounds_check {
bounds_check_error_loc(loc, index, len(array))
n := len(array)-1
if index != n {
@@ -82,7 +115,7 @@ unordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_loca
// Note: If the elements do not have to remain in their order, prefer `unordered_remove`.
// Note: If the index is out of bounds, this procedure will panic.
@builtin
ordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_location) #no_bounds_check {
ordered_remove :: proc(array: ^$D/[dynamic]$T, #any_int index: int, loc := #caller_location) #no_bounds_check {
bounds_check_error_loc(loc, index, len(array))
if index+1 < len(array) {
copy(array[index:], array[index+1:])
@@ -95,7 +128,7 @@ ordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_locati
// Note: This is an O(N) operation.
// Note: If the range is out of bounds, this procedure will panic.
@builtin
remove_range :: proc(array: ^$D/[dynamic]$T, lo, hi: int, loc := #caller_location) #no_bounds_check {
remove_range :: proc(array: ^$D/[dynamic]$T, #any_int lo, hi: int, loc := #caller_location) #no_bounds_check {
slice_expr_error_lo_hi_loc(loc, lo, hi, len(array))
n := max(hi-lo, 0)
if n > 0 {
@@ -333,17 +366,24 @@ make_dynamic_array_len :: proc($T: typeid/[dynamic]$E, #any_int len: int, alloca
// Note: Prefer using the procedure group `make`.
@(builtin, require_results)
make_dynamic_array_len_cap :: proc($T: typeid/[dynamic]$E, #any_int len: int, #any_int cap: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_allocator_error {
make_dynamic_array_error_loc(loc, len, cap)
array.allocator = allocator // initialize allocator before just in case it fails to allocate any memory
data := mem_alloc_bytes(size_of(E)*cap, align_of(E), allocator, loc) or_return
s := Raw_Dynamic_Array{raw_data(data), len, cap, allocator}
if data == nil && size_of(E) != 0 {
s.len, s.cap = 0, 0
}
array = transmute(T)s
err = _make_dynamic_array_len_cap((^Raw_Dynamic_Array)(&array), size_of(E), align_of(E), len, cap, allocator, loc)
return
}
// `make_map` allocates and initializes a dynamic array. Like `new`, the first argument is a type, not a value.
@(require_results)
_make_dynamic_array_len_cap :: proc(array: ^Raw_Dynamic_Array, size_of_elem, align_of_elem: int, #any_int len: int, #any_int cap: int, allocator := context.allocator, loc := #caller_location) -> (err: Allocator_Error) {
make_dynamic_array_error_loc(loc, len, cap)
array.allocator = allocator // initialize allocator before just in case it fails to allocate any memory
data := mem_alloc_bytes(size_of_elem*cap, align_of_elem, allocator, loc) or_return
use_zero := data == nil && size_of_elem != 0
array.data = raw_data(data)
array.len = 0 if use_zero else len
array.cap = 0 if use_zero else cap
array.allocator = allocator
return
}
// `make_map` allocates and initializes a map. Like `new`, the first argument is a type, not a value.
// Unlike `new`, `make`'s return value is the same as the type of its argument, not a pointer to it.
//
// Note: Prefer using the procedure group `make`.
@@ -355,7 +395,7 @@ make_map :: proc($T: typeid/map[$K]$E, #any_int capacity: int = 1<<MAP_MIN_LOG2_
err = reserve_map(&m, capacity, loc)
return
}
// `make_multi_pointer` allocates and initializes a dynamic array. Like `new`, the first argument is a type, not a value.
// `make_multi_pointer` allocates and initializes a multi-pointer. Like `new`, the first argument is a type, not a value.
// Unlike `new`, `make`'s return value is the same as the type of its argument, not a pointer to it.
//
// This is "similar" to doing `raw_data(make([]E, len, allocator))`.
@@ -440,107 +480,103 @@ delete_key :: proc(m: ^$T/map[$K]$V, key: K) -> (deleted_key: K, deleted_value:
return
}
_append_elem :: #force_inline proc(array: ^$T/[dynamic]$E, arg: E, should_zero: bool, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
_append_elem :: #force_inline proc(array: ^Raw_Dynamic_Array, size_of_elem, align_of_elem: int, arg_ptr: rawptr, should_zero: bool, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
if array == nil {
return 0, nil
return
}
when size_of(E) == 0 {
array := (^Raw_Dynamic_Array)(array)
array.len += 1
return 1, nil
} else {
if cap(array) < len(array)+1 {
// Same behavior as _append_elems but there's only one arg, so we always just add DEFAULT_DYNAMIC_ARRAY_CAPACITY.
cap := 2 * cap(array) + DEFAULT_DYNAMIC_ARRAY_CAPACITY
// do not 'or_return' here as it could be a partial success
if should_zero {
err = reserve(array, cap, loc)
} else {
err = non_zero_reserve(array, cap, loc)
}
}
if cap(array)-len(array) > 0 {
a := (^Raw_Dynamic_Array)(array)
when size_of(E) != 0 {
data := ([^]E)(a.data)
assert(data != nil, loc=loc)
data[a.len] = arg
}
a.len += 1
return 1, err
}
return 0, err
if array.cap < array.len+1 {
// Same behavior as _append_elems but there's only one arg, so we always just add DEFAULT_DYNAMIC_ARRAY_CAPACITY.
cap := 2 * array.cap + DEFAULT_DYNAMIC_ARRAY_CAPACITY
// do not 'or_return' here as it could be a partial success
err = _reserve_dynamic_array(array, size_of_elem, align_of_elem, cap, should_zero, loc)
}
if array.cap-array.len > 0 {
data := ([^]byte)(array.data)
assert(data != nil, loc=loc)
data = data[array.len*size_of_elem:]
intrinsics.mem_copy_non_overlapping(data, arg_ptr, size_of_elem)
array.len += 1
n = 1
}
return
}
@builtin
append_elem :: proc(array: ^$T/[dynamic]$E, #no_broadcast arg: E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
return _append_elem(array, arg, true, loc=loc)
when size_of(E) == 0 {
(^Raw_Dynamic_Array)(array).len += 1
return 1, nil
} else {
arg := arg
return _append_elem((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), &arg, true, loc=loc)
}
}
@builtin
non_zero_append_elem :: proc(array: ^$T/[dynamic]$E, #no_broadcast arg: E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
return _append_elem(array, arg, false, loc=loc)
when size_of(E) == 0 {
(^Raw_Dynamic_Array)(array).len += 1
return 1, nil
} else {
arg := arg
return _append_elem((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), &arg, false, loc=loc)
}
}
_append_elems :: #force_inline proc(array: ^$T/[dynamic]$E, should_zero: bool, loc := #caller_location, args: ..E) -> (n: int, err: Allocator_Error) #optional_allocator_error {
_append_elems :: #force_inline proc(array: ^Raw_Dynamic_Array, size_of_elem, align_of_elem: int, should_zero: bool, loc := #caller_location, args: rawptr, arg_len: int) -> (n: int, err: Allocator_Error) #optional_allocator_error {
if array == nil {
return 0, nil
}
arg_len := len(args)
if arg_len <= 0 {
return 0, nil
}
when size_of(E) == 0 {
array := (^Raw_Dynamic_Array)(array)
array.len += arg_len
return arg_len, nil
} else {
if cap(array) < len(array)+arg_len {
cap := 2 * cap(array) + max(DEFAULT_DYNAMIC_ARRAY_CAPACITY, arg_len)
if array.cap < array.len+arg_len {
cap := 2 * array.cap + max(DEFAULT_DYNAMIC_ARRAY_CAPACITY, arg_len)
// do not 'or_return' here as it could be a partial success
if should_zero {
err = reserve(array, cap, loc)
} else {
err = non_zero_reserve(array, cap, loc)
}
}
arg_len = min(cap(array)-len(array), arg_len)
if arg_len > 0 {
a := (^Raw_Dynamic_Array)(array)
when size_of(E) != 0 {
data := ([^]E)(a.data)
assert(data != nil, loc=loc)
intrinsics.mem_copy(&data[a.len], raw_data(args), size_of(E) * arg_len)
}
a.len += arg_len
}
return arg_len, err
// do not 'or_return' here as it could be a partial success
err = _reserve_dynamic_array(array, size_of_elem, align_of_elem, cap, should_zero, loc)
}
arg_len := arg_len
arg_len = min(array.cap-array.len, arg_len)
if arg_len > 0 {
data := ([^]byte)(array.data)
assert(data != nil, loc=loc)
data = data[array.len*size_of_elem:]
intrinsics.mem_copy(data, args, size_of_elem * arg_len) // must be mem_copy (overlapping)
array.len += arg_len
}
return arg_len, err
}
@builtin
append_elems :: proc(array: ^$T/[dynamic]$E, #no_broadcast args: ..E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
return _append_elems(array, true, loc, ..args)
when size_of(E) == 0 {
a := (^Raw_Dynamic_Array)(array)
a.len += len(args)
return len(args), nil
} else {
return _append_elems((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), true, loc, raw_data(args), len(args))
}
}
@builtin
non_zero_append_elems :: proc(array: ^$T/[dynamic]$E, #no_broadcast args: ..E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
return _append_elems(array, false, loc, ..args)
when size_of(E) == 0 {
a := (^Raw_Dynamic_Array)(array)
a.len += len(args)
return len(args), nil
} else {
return _append_elems((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), false, loc, raw_data(args), len(args))
}
}
// The append_string built-in procedure appends a string to the end of a [dynamic]u8 like type
_append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, should_zero: bool, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
args := transmute([]E)arg
if should_zero {
return append_elems(array, ..args, loc=loc)
} else {
return non_zero_append_elems(array, ..args, loc=loc)
}
return _append_elems((^Raw_Dynamic_Array)(array), 1, 1, should_zero, loc, raw_data(arg), len(arg))
}
@builtin
@@ -599,7 +635,7 @@ append_nothing :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (n: i
@builtin
inject_at_elem :: proc(array: ^$T/[dynamic]$E, index: int, #no_broadcast arg: E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
inject_at_elem :: proc(array: ^$T/[dynamic]$E, #any_int index: int, #no_broadcast arg: E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
if array == nil {
return
}
@@ -617,7 +653,7 @@ inject_at_elem :: proc(array: ^$T/[dynamic]$E, index: int, #no_broadcast arg: E,
}
@builtin
inject_at_elems :: proc(array: ^$T/[dynamic]$E, index: int, #no_broadcast args: ..E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
inject_at_elems :: proc(array: ^$T/[dynamic]$E, #any_int index: int, #no_broadcast args: ..E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
if array == nil {
return
}
@@ -640,7 +676,7 @@ inject_at_elems :: proc(array: ^$T/[dynamic]$E, index: int, #no_broadcast args:
}
@builtin
inject_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, index: int, arg: string, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
inject_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, #any_int index: int, arg: string, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
if array == nil {
return
}
@@ -665,7 +701,7 @@ inject_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, index: int, arg: string
@builtin
assign_at_elem :: proc(array: ^$T/[dynamic]$E, index: int, arg: E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
assign_at_elem :: proc(array: ^$T/[dynamic]$E, #any_int index: int, arg: E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
if index < len(array) {
array[index] = arg
ok = true
@@ -679,7 +715,7 @@ assign_at_elem :: proc(array: ^$T/[dynamic]$E, index: int, arg: E, loc := #calle
@builtin
assign_at_elems :: proc(array: ^$T/[dynamic]$E, index: int, args: ..E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
assign_at_elems :: proc(array: ^$T/[dynamic]$E, #any_int index: int, #no_broadcast args: ..E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
new_size := index + len(args)
if len(args) == 0 {
ok = true
@@ -696,7 +732,7 @@ assign_at_elems :: proc(array: ^$T/[dynamic]$E, index: int, args: ..E, loc := #c
@builtin
assign_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, index: int, arg: string, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
assign_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, #any_int index: int, arg: string, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
new_size := index + len(arg)
if len(arg) == 0 {
ok = true
@@ -729,11 +765,10 @@ clear_dynamic_array :: proc "contextless" (array: ^$T/[dynamic]$E) {
// `reserve_dynamic_array` will try to reserve memory of a passed dynamic array or map to the requested element count (setting the `cap`).
//
// Note: Prefer the procedure group `reserve`.
_reserve_dynamic_array :: #force_inline proc(array: ^$T/[dynamic]$E, capacity: int, should_zero: bool, loc := #caller_location) -> Allocator_Error {
if array == nil {
_reserve_dynamic_array :: #force_inline proc(a: ^Raw_Dynamic_Array, size_of_elem, align_of_elem: int, capacity: int, should_zero: bool, loc := #caller_location) -> Allocator_Error {
if a == nil {
return nil
}
a := (^Raw_Dynamic_Array)(array)
if capacity <= a.cap {
return nil
@@ -744,15 +779,15 @@ _reserve_dynamic_array :: #force_inline proc(array: ^$T/[dynamic]$E, capacity: i
}
assert(a.allocator.procedure != nil)
old_size := a.cap * size_of(E)
new_size := capacity * size_of(E)
old_size := a.cap * size_of_elem
new_size := capacity * size_of_elem
allocator := a.allocator
new_data: []byte
if should_zero {
new_data = mem_resize(a.data, old_size, new_size, align_of(E), allocator, loc) or_return
new_data = mem_resize(a.data, old_size, new_size, align_of_elem, allocator, loc) or_return
} else {
new_data = non_zero_mem_resize(a.data, old_size, new_size, align_of(E), allocator, loc) or_return
new_data = non_zero_mem_resize(a.data, old_size, new_size, align_of_elem, allocator, loc) or_return
}
if new_data == nil && new_size > 0 {
return .Out_Of_Memory
@@ -765,26 +800,23 @@ _reserve_dynamic_array :: #force_inline proc(array: ^$T/[dynamic]$E, capacity: i
@builtin
reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int capacity: int, loc := #caller_location) -> Allocator_Error {
return _reserve_dynamic_array(array, capacity, true, loc)
return _reserve_dynamic_array((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), capacity, true, loc)
}
@builtin
non_zero_reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int capacity: int, loc := #caller_location) -> Allocator_Error {
return _reserve_dynamic_array(array, capacity, false, loc)
return _reserve_dynamic_array((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), capacity, false, loc)
}
// `resize_dynamic_array` will try to resize memory of a passed dynamic array or map to the requested element count (setting the `len`, and possibly `cap`).
//
// Note: Prefer the procedure group `resize`
_resize_dynamic_array :: #force_inline proc(array: ^$T/[dynamic]$E, length: int, should_zero: bool, loc := #caller_location) -> Allocator_Error {
if array == nil {
_resize_dynamic_array :: #force_inline proc(a: ^Raw_Dynamic_Array, size_of_elem, align_of_elem: int, length: int, should_zero: bool, loc := #caller_location) -> Allocator_Error {
if a == nil {
return nil
}
a := (^Raw_Dynamic_Array)(array)
if length <= a.cap {
if should_zero && a.len < length {
intrinsics.mem_zero(([^]E)(a.data)[a.len:], (length-a.len)*size_of(E))
intrinsics.mem_zero(([^]byte)(a.data)[a.len*size_of_elem:], (length-a.len)*size_of_elem)
}
a.len = max(length, 0)
return nil
@@ -795,15 +827,15 @@ _resize_dynamic_array :: #force_inline proc(array: ^$T/[dynamic]$E, length: int,
}
assert(a.allocator.procedure != nil)
old_size := a.cap * size_of(E)
new_size := length * size_of(E)
old_size := a.cap * size_of_elem
new_size := length * size_of_elem
allocator := a.allocator
new_data : []byte
if should_zero {
new_data = mem_resize(a.data, old_size, new_size, align_of(E), allocator, loc) or_return
new_data = mem_resize(a.data, old_size, new_size, align_of_elem, allocator, loc) or_return
} else {
new_data = non_zero_mem_resize(a.data, old_size, new_size, align_of(E), allocator, loc) or_return
new_data = non_zero_mem_resize(a.data, old_size, new_size, align_of_elem, allocator, loc) or_return
}
if new_data == nil && new_size > 0 {
return .Out_Of_Memory
@@ -815,14 +847,17 @@ _resize_dynamic_array :: #force_inline proc(array: ^$T/[dynamic]$E, length: int,
return nil
}
// `resize_dynamic_array` will try to resize memory of a passed dynamic array or map to the requested element count (setting the `len`, and possibly `cap`).
//
// Note: Prefer the procedure group `resize`
@builtin
resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int length: int, loc := #caller_location) -> Allocator_Error {
return _resize_dynamic_array(array, length, true, loc=loc)
return _resize_dynamic_array((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), length, true, loc=loc)
}
@builtin
non_zero_resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int length: int, loc := #caller_location) -> Allocator_Error {
return _resize_dynamic_array(array, length, false, loc=loc)
return _resize_dynamic_array((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), length, false, loc=loc)
}
/*
@@ -836,11 +871,14 @@ non_zero_resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int length: i
Note: Prefer the procedure group `shrink`
*/
shrink_dynamic_array :: proc(array: ^$T/[dynamic]$E, new_cap := -1, loc := #caller_location) -> (did_shrink: bool, err: Allocator_Error) {
if array == nil {
shrink_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int new_cap := -1, loc := #caller_location) -> (did_shrink: bool, err: Allocator_Error) {
return _shrink_dynamic_array((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), new_cap, loc)
}
_shrink_dynamic_array :: proc(a: ^Raw_Dynamic_Array, size_of_elem, align_of_elem: int, new_cap := -1, loc := #caller_location) -> (did_shrink: bool, err: Allocator_Error) {
if a == nil {
return
}
a := (^Raw_Dynamic_Array)(array)
new_cap := new_cap if new_cap >= 0 else a.len
@@ -853,10 +891,10 @@ shrink_dynamic_array :: proc(array: ^$T/[dynamic]$E, new_cap := -1, loc := #call
}
assert(a.allocator.procedure != nil)
old_size := a.cap * size_of(E)
new_size := new_cap * size_of(E)
old_size := a.cap * size_of_elem
new_size := new_cap * size_of_elem
new_data := mem_resize(a.data, old_size, new_size, align_of(E), a.allocator, loc) or_return
new_data := mem_resize(a.data, old_size, new_size, align_of_elem, a.allocator, loc) or_return
a.data = raw_data(new_data)
a.len = min(new_cap, a.len)
@@ -908,7 +946,7 @@ card :: proc "contextless" (s: $S/bit_set[$E; $U]) -> int {
@builtin
@(disabled=ODIN_DISABLE_ASSERT)
assert :: proc(condition: bool, message := "", loc := #caller_location) {
assert :: proc(condition: bool, message := #caller_expression(condition), loc := #caller_location) {
if !condition {
// NOTE(bill): This is wrapped in a procedure call
// to improve performance to make the CPU not
@@ -943,3 +981,30 @@ unimplemented :: proc(message := "", loc := #caller_location) -> ! {
}
p("not yet implemented", message, loc)
}
@builtin
@(disabled=ODIN_DISABLE_ASSERT)
assert_contextless :: proc "contextless" (condition: bool, message := #caller_expression(condition), loc := #caller_location) {
if !condition {
// NOTE(bill): This is wrapped in a procedure call
// to improve performance to make the CPU not
// execute speculatively, making it about an order of
// magnitude faster
@(cold)
internal :: proc "contextless" (message: string, loc: Source_Code_Location) {
default_assertion_contextless_failure_proc("runtime assertion", message, loc)
}
internal(message, loc)
}
}
@builtin
panic_contextless :: proc "contextless" (message: string, loc := #caller_location) -> ! {
default_assertion_contextless_failure_proc("panic", message, loc)
}
@builtin
unimplemented_contextless :: proc "contextless" (message := "", loc := #caller_location) -> ! {
default_assertion_contextless_failure_proc("not yet implemented", message, loc)
}
+9 -9
View File
@@ -76,7 +76,7 @@ raw_soa_footer :: proc{
@(builtin, require_results)
make_soa_aligned :: proc($T: typeid/#soa[]$E, length: int, alignment: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_allocator_error {
make_soa_aligned :: proc($T: typeid/#soa[]$E, #any_int length, alignment: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_allocator_error {
if length <= 0 {
return
}
@@ -135,7 +135,7 @@ make_soa_aligned :: proc($T: typeid/#soa[]$E, length: int, alignment: int, alloc
}
@(builtin, require_results)
make_soa_slice :: proc($T: typeid/#soa[]$E, length: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_allocator_error {
make_soa_slice :: proc($T: typeid/#soa[]$E, #any_int length: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_allocator_error {
return make_soa_aligned(T, length, align_of(E), allocator, loc)
}
@@ -172,7 +172,7 @@ make_soa :: proc{
@builtin
resize_soa :: proc(array: ^$T/#soa[dynamic]$E, length: int, loc := #caller_location) -> Allocator_Error {
resize_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int length: int, loc := #caller_location) -> Allocator_Error {
if array == nil {
return nil
}
@@ -183,7 +183,7 @@ resize_soa :: proc(array: ^$T/#soa[dynamic]$E, length: int, loc := #caller_locat
}
@builtin
non_zero_resize_soa :: proc(array: ^$T/#soa[dynamic]$E, length: int, loc := #caller_location) -> Allocator_Error {
non_zero_resize_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int length: int, loc := #caller_location) -> Allocator_Error {
if array == nil {
return nil
}
@@ -194,12 +194,12 @@ non_zero_resize_soa :: proc(array: ^$T/#soa[dynamic]$E, length: int, loc := #cal
}
@builtin
reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, loc := #caller_location) -> Allocator_Error {
reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int capacity: int, loc := #caller_location) -> Allocator_Error {
return _reserve_soa(array, capacity, true, loc)
}
@builtin
non_zero_reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, loc := #caller_location) -> Allocator_Error {
non_zero_reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int capacity: int, loc := #caller_location) -> Allocator_Error {
return _reserve_soa(array, capacity, false, loc)
}
@@ -352,7 +352,7 @@ non_zero_append_soa_elems :: proc(array: ^$T/#soa[dynamic]$E, #no_broadcast args
}
_append_soa_elems :: proc(array: ^$T/#soa[dynamic]$E, zero_memory: bool, #no_broadcast args: ..E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
_append_soa_elems :: proc(array: ^$T/#soa[dynamic]$E, zero_memory: bool, #no_broadcast args: []E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
if array == nil {
return
}
@@ -484,7 +484,7 @@ into_dynamic_soa :: proc(array: $T/#soa[]$E) -> #soa[dynamic]E {
// Note: If you the elements to remain in their order, use `ordered_remove_soa`.
// Note: If the index is out of bounds, this procedure will panic.
@builtin
unordered_remove_soa :: proc(array: ^$T/#soa[dynamic]$E, index: int, loc := #caller_location) #no_bounds_check {
unordered_remove_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int index: int, loc := #caller_location) #no_bounds_check {
bounds_check_error_loc(loc, index, len(array))
if index+1 < len(array) {
ti := type_info_of(typeid_of(T))
@@ -512,7 +512,7 @@ unordered_remove_soa :: proc(array: ^$T/#soa[dynamic]$E, index: int, loc := #cal
// Note: If you the elements do not have to remain in their order, prefer `unordered_remove_soa`.
// Note: If the index is out of bounds, this procedure will panic.
@builtin
ordered_remove_soa :: proc(array: ^$T/#soa[dynamic]$E, index: int, loc := #caller_location) #no_bounds_check {
ordered_remove_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int index: int, loc := #caller_location) #no_bounds_check {
bounds_check_error_loc(loc, index, len(array))
if index+1 < len(array) {
ti := type_info_of(typeid_of(T))
+2 -2
View File
@@ -1,8 +1,8 @@
package runtime
nil_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
size, alignment: int,
old_memory: rawptr, old_size: int, loc := #caller_location) -> ([]byte, Allocator_Error) {
size, alignment: int,
old_memory: rawptr, old_size: int, loc := #caller_location) -> ([]byte, Allocator_Error) {
switch mode {
case .Alloc, .Alloc_Non_Zeroed:
return nil, .Out_Of_Memory
@@ -129,7 +129,7 @@ arena_alloc :: proc(arena: ^Arena, size, alignment: uint, loc := #caller_locatio
return
}
// `arena_init` will initialize the arena with a usuable block.
// `arena_init` will initialize the arena with a usable block.
// This procedure is not necessary to use the Arena as the default zero as `arena_alloc` will set things up if necessary
@(require_results)
arena_init :: proc(arena: ^Arena, size: uint, backing_allocator: Allocator, loc := #caller_location) -> Allocator_Error {
+6 -6
View File
@@ -577,7 +577,7 @@ map_grow_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Inf
@(require_results)
map_reserve_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, new_capacity: uintptr, loc := #caller_location) -> Allocator_Error {
map_reserve_dynamic :: #force_no_inline proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, new_capacity: uintptr, loc := #caller_location) -> Allocator_Error {
@(require_results)
ceil_log2 :: #force_inline proc "contextless" (x: uintptr) -> uintptr {
z := intrinsics.count_leading_zeros(x)
@@ -641,7 +641,7 @@ map_reserve_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_
@(require_results)
map_shrink_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, loc := #caller_location) -> (did_shrink: bool, err: Allocator_Error) {
map_shrink_dynamic :: #force_no_inline proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, loc := #caller_location) -> (did_shrink: bool, err: Allocator_Error) {
if m.allocator.procedure == nil {
m.allocator = context.allocator
}
@@ -688,7 +688,7 @@ map_shrink_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_I
}
@(require_results)
map_free_dynamic :: proc "odin" (m: Raw_Map, info: ^Map_Info, loc := #caller_location) -> Allocator_Error {
map_free_dynamic :: #force_no_inline proc "odin" (m: Raw_Map, info: ^Map_Info, loc := #caller_location) -> Allocator_Error {
ptr := rawptr(map_data(m))
size := int(map_total_allocation_size(uintptr(map_cap(m)), info))
err := mem_free_with_size(ptr, size, m.allocator, loc)
@@ -700,7 +700,7 @@ map_free_dynamic :: proc "odin" (m: Raw_Map, info: ^Map_Info, loc := #caller_loc
}
@(require_results)
map_lookup_dynamic :: proc "contextless" (m: Raw_Map, #no_alias info: ^Map_Info, k: uintptr) -> (index: uintptr, ok: bool) {
map_lookup_dynamic :: #force_no_inline proc "contextless" (m: Raw_Map, #no_alias info: ^Map_Info, k: uintptr) -> (index: uintptr, ok: bool) {
if map_len(m) == 0 {
return 0, false
}
@@ -723,7 +723,7 @@ map_lookup_dynamic :: proc "contextless" (m: Raw_Map, #no_alias info: ^Map_Info,
}
}
@(require_results)
map_exists_dynamic :: proc "contextless" (m: Raw_Map, #no_alias info: ^Map_Info, k: uintptr) -> (ok: bool) {
map_exists_dynamic :: #force_no_inline proc "contextless" (m: Raw_Map, #no_alias info: ^Map_Info, k: uintptr) -> (ok: bool) {
if map_len(m) == 0 {
return false
}
@@ -749,7 +749,7 @@ map_exists_dynamic :: proc "contextless" (m: Raw_Map, #no_alias info: ^Map_Info,
@(require_results)
map_erase_dynamic :: #force_inline proc "contextless" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, k: uintptr) -> (old_k, old_v: uintptr, ok: bool) {
map_erase_dynamic :: #force_no_inline proc "contextless" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, k: uintptr) -> (old_k, old_v: uintptr, ok: bool) {
index := map_lookup_dynamic(m^, info, k) or_return
ks, vs, hs, _, _ := map_kvh_data_dynamic(m^, info)
hs[index] |= TOMBSTONE_MASK
+6 -3
View File
@@ -1,6 +1,6 @@
//+private
//+build linux, darwin, freebsd, openbsd, netbsd, haiku
//+no-instrumentation
#+private
#+build linux, darwin, freebsd, openbsd, netbsd, haiku
#+no-instrumentation
package runtime
import "base:intrinsics"
@@ -34,6 +34,9 @@ when ODIN_BUILD_MODE == .Dynamic {
} else when ODIN_OS == .Darwin && ODIN_ARCH == .arm64 {
@require foreign import entry "entry_unix_no_crt_darwin_arm64.asm"
SYS_exit :: 1
} else when ODIN_ARCH == .riscv64 {
@require foreign import entry "entry_unix_no_crt_riscv64.asm"
SYS_exit :: 93
}
@(link_name="_start_odin", linkage="strong", require)
_start_odin :: proc "c" (argc: i32, argv: [^]cstring) -> ! {
@@ -0,0 +1,10 @@
.text
.globl _start
_start:
ld a0, 0(sp)
addi a1, sp, 8
addi sp, sp, ~15
call _start_odin
ebreak
+3 -3
View File
@@ -1,6 +1,6 @@
//+private
//+build wasm32, wasm64p32
//+no-instrumentation
#+private
#+build wasm32, wasm64p32
#+no-instrumentation
package runtime
import "base:intrinsics"
+5 -4
View File
@@ -1,6 +1,6 @@
//+private
//+build windows
//+no-instrumentation
#+private
#+build windows
#+no-instrumentation
package runtime
import "base:intrinsics"
@@ -10,8 +10,9 @@ when ODIN_BUILD_MODE == .Dynamic {
DllMain :: proc "system" (hinstDLL: rawptr, fdwReason: u32, lpReserved: rawptr) -> b32 {
context = default_context()
// Populate Windows DLL-specific global
// Populate Windows DLL-specific globals
dll_forward_reason = DLL_Forward_Reason(fdwReason)
dll_instance = hinstDLL
switch dll_forward_reason {
case .Process_Attach:
+24 -15
View File
@@ -19,29 +19,41 @@ heap_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
// the pointer we return to the user.
//
aligned_alloc :: proc(size, alignment: int, old_ptr: rawptr = nil, zero_memory := true) -> ([]byte, Allocator_Error) {
aligned_alloc :: proc(size, alignment: int, old_ptr: rawptr, old_size: int, zero_memory := true) -> ([]byte, Allocator_Error) {
// Not(flysand): We need to reserve enough space for alignment, which
// includes the user data itself, the space to store the pointer to
// allocation start, as well as the padding required to align both
// the user data and the pointer.
a := max(alignment, align_of(rawptr))
space := size + a - 1
space := a-1 + size_of(rawptr) + size
allocated_mem: rawptr
if old_ptr != nil {
force_copy := old_ptr != nil && alignment > align_of(rawptr)
if old_ptr != nil && !force_copy {
original_old_ptr := ([^]rawptr)(old_ptr)[-1]
allocated_mem = heap_resize(original_old_ptr, space+size_of(rawptr))
allocated_mem = heap_resize(original_old_ptr, space)
} else {
allocated_mem = heap_alloc(space+size_of(rawptr), zero_memory)
allocated_mem = heap_alloc(space, zero_memory)
}
aligned_mem := rawptr(([^]u8)(allocated_mem)[size_of(rawptr):])
ptr := uintptr(aligned_mem)
aligned_ptr := (ptr - 1 + uintptr(a)) & -uintptr(a)
diff := int(aligned_ptr - ptr)
if (size + diff) > space || allocated_mem == nil {
aligned_ptr := (ptr + uintptr(a)-1) & ~(uintptr(a)-1)
if allocated_mem == nil {
aligned_free(old_ptr)
aligned_free(allocated_mem)
return nil, .Out_Of_Memory
}
aligned_mem = rawptr(aligned_ptr)
([^]rawptr)(aligned_mem)[-1] = allocated_mem
if force_copy {
mem_copy_non_overlapping(aligned_mem, old_ptr, min(old_size, size))
aligned_free(old_ptr)
}
return byte_slice(aligned_mem, size), nil
}
@@ -53,10 +65,10 @@ heap_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
aligned_resize :: proc(p: rawptr, old_size: int, new_size: int, new_alignment: int, zero_memory := true) -> (new_memory: []byte, err: Allocator_Error) {
if p == nil {
return nil, nil
return aligned_alloc(new_size, new_alignment, nil, old_size, zero_memory)
}
new_memory = aligned_alloc(new_size, new_alignment, p, zero_memory) or_return
new_memory = aligned_alloc(new_size, new_alignment, p, old_size, zero_memory) or_return
// NOTE: heap_resize does not zero the new memory, so we do it
if zero_memory && new_size > old_size {
@@ -68,7 +80,7 @@ heap_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
switch mode {
case .Alloc, .Alloc_Non_Zeroed:
return aligned_alloc(size, alignment, nil, mode == .Alloc)
return aligned_alloc(size, alignment, nil, 0, mode == .Alloc)
case .Free:
aligned_free(old_memory)
@@ -77,9 +89,6 @@ heap_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
return nil, .Mode_Not_Implemented
case .Resize, .Resize_Non_Zeroed:
if old_memory == nil {
return aligned_alloc(size, alignment, nil, mode == .Resize)
}
return aligned_resize(old_memory, old_size, size, alignment, mode == .Resize)
case .Query_Features:
+2 -2
View File
@@ -1,5 +1,5 @@
//+build orca
//+private
#+build orca
#+private
package runtime
foreign {
+2 -2
View File
@@ -1,5 +1,5 @@
//+build js, wasi, freestanding, essence
//+private
#+build js, wasi, freestanding, essence
#+private
package runtime
_heap_alloc :: proc "contextless" (size: int, zero_memory := true) -> rawptr {
+2 -2
View File
@@ -1,5 +1,5 @@
//+build linux, darwin, freebsd, openbsd, netbsd, haiku
//+private
#+build linux, darwin, freebsd, openbsd, netbsd, haiku
#+private
package runtime
when ODIN_OS == .Darwin {
+32 -20
View File
@@ -1,4 +1,4 @@
//+vet !cast
#+vet !cast
package runtime
import "base:intrinsics"
@@ -8,10 +8,9 @@ IS_WASM :: ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32
@(private)
RUNTIME_LINKAGE :: "strong" when (
(ODIN_USE_SEPARATE_MODULES ||
ODIN_USE_SEPARATE_MODULES ||
ODIN_BUILD_MODE == .Dynamic ||
!ODIN_NO_CRT) &&
!IS_WASM) else "internal"
!ODIN_NO_CRT) else "internal"
RUNTIME_REQUIRE :: false // !ODIN_TILDE
@(private)
@@ -119,16 +118,15 @@ mem_copy_non_overlapping :: proc "contextless" (dst, src: rawptr, len: int) -> r
DEFAULT_ALIGNMENT :: 2*align_of(rawptr)
mem_alloc_bytes :: #force_inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) {
if size == 0 {
return nil, nil
}
if allocator.procedure == nil {
assert(is_power_of_two_int(alignment), "Alignment must be a power of two", loc)
if size == 0 || allocator.procedure == nil{
return nil, nil
}
return allocator.procedure(allocator.data, .Alloc, size, alignment, nil, 0, loc)
}
mem_alloc :: #force_inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) {
assert(is_power_of_two_int(alignment), "Alignment must be a power of two", loc)
if size == 0 || allocator.procedure == nil {
return nil, nil
}
@@ -136,6 +134,7 @@ mem_alloc :: #force_inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, a
}
mem_alloc_non_zeroed :: #force_inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) {
assert(is_power_of_two_int(alignment), "Alignment must be a power of two", loc)
if size == 0 || allocator.procedure == nil {
return nil, nil
}
@@ -175,6 +174,7 @@ mem_free_all :: #force_inline proc(allocator := context.allocator, loc := #calle
}
_mem_resize :: #force_inline proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, should_zero: bool, loc := #caller_location) -> (data: []byte, err: Allocator_Error) {
assert(is_power_of_two_int(alignment), "Alignment must be a power of two", loc)
if allocator.procedure == nil {
return nil, nil
}
@@ -216,9 +216,11 @@ _mem_resize :: #force_inline proc(ptr: rawptr, old_size, new_size: int, alignmen
}
mem_resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> (data: []byte, err: Allocator_Error) {
assert(is_power_of_two_int(alignment), "Alignment must be a power of two", loc)
return _mem_resize(ptr, old_size, new_size, alignment, allocator, true, loc)
}
non_zero_mem_resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> (data: []byte, err: Allocator_Error) {
assert(is_power_of_two_int(alignment), "Alignment must be a power of two", loc)
return _mem_resize(ptr, old_size, new_size, alignment, allocator, false, loc)
}
@@ -879,9 +881,6 @@ extendhfsf2 :: proc "c" (value: __float16) -> f32 {
@(link_name="__floattidf", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
floattidf :: proc "c" (a: i128) -> f64 {
when IS_WASM {
return 0
} else {
DBL_MANT_DIG :: 53
if a == 0 {
return 0.0
@@ -921,14 +920,10 @@ when IS_WASM {
fb[0] = u32(a) // mantissa-low
return transmute(f64)fb
}
}
@(link_name="__floattidf_unsigned", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
floattidf_unsigned :: proc "c" (a: u128) -> f64 {
when IS_WASM {
return 0
} else {
DBL_MANT_DIG :: 53
if a == 0 {
return 0.0
@@ -966,7 +961,6 @@ when IS_WASM {
fb[0] = u32(a) // mantissa-low
return transmute(f64)fb
}
}
@@ -1023,14 +1017,32 @@ modti3 :: proc "c" (a, b: i128) -> i128 {
@(link_name="__divmodti4", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
divmodti4 :: proc "c" (a, b: i128, rem: ^i128) -> i128 {
u := udivmod128(u128(a), u128(b), (^u128)(rem))
return i128(u)
s_a := a >> (128 - 1) // -1 if negative or 0
s_b := b >> (128 - 1)
an := (a ~ s_a) - s_a // absolute
bn := (b ~ s_b) - s_b
s_b ~= s_a // quotient sign
u_s_b := u128(s_b)
u_s_a := u128(s_a)
r: u128 = ---
u := i128((udivmodti4(u128(an), u128(bn), &r) ~ u_s_b) - u_s_b) // negate if negative
rem^ = i128((r ~ u_s_a) - u_s_a)
return u
}
@(link_name="__divti3", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
divti3 :: proc "c" (a, b: i128) -> i128 {
u := udivmodti4(u128(a), u128(b), nil)
return i128(u)
s_a := a >> (128 - 1) // -1 if negative or 0
s_b := b >> (128 - 1)
an := (a ~ s_a) - s_a // absolute
bn := (b ~ s_b) - s_b
s_a ~= s_b // quotient sign
u_s_a := u128(s_a)
return i128((udivmodti4(u128(an), u128(bn), nil) ~ u_s_a) - u_s_a) // negate if negative
}
+2 -2
View File
@@ -1,5 +1,5 @@
//+build freebsd, openbsd, netbsd
//+private
#+build freebsd, openbsd, netbsd
#+private
package runtime
foreign import libc "system:c"
+20 -7
View File
@@ -1,15 +1,28 @@
//+build darwin
//+private
#+build darwin
#+private
package runtime
import "base:intrinsics"
_stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
WRITE :: 0x2000004
STDERR :: 2
ret := intrinsics.syscall(WRITE, STDERR, uintptr(raw_data(data)), uintptr(len(data)))
if ret < 0 {
return 0, _OS_Errno(-ret)
when ODIN_NO_CRT {
WRITE :: 0x2000004
ret := intrinsics.syscall(WRITE, STDERR, uintptr(raw_data(data)), uintptr(len(data)))
if ret < 0 {
return 0, _OS_Errno(-ret)
}
return int(ret), 0
} else {
foreign {
write :: proc(handle: i32, buffer: [^]byte, count: uint) -> int ---
__error :: proc() -> ^i32 ---
}
if ret := write(STDERR, raw_data(data), len(data)); ret >= 0 {
return int(ret), 0
}
return 0, _OS_Errno(__error()^)
}
return int(ret), 0
}
+2 -2
View File
@@ -1,5 +1,5 @@
//+build freestanding
//+private
#+build freestanding
#+private
package runtime
// TODO(bill): reimplement `os.write`
+2 -2
View File
@@ -1,5 +1,5 @@
//+build haiku
//+private
#+build haiku
#+private
package runtime
foreign import libc "system:c"
+2 -2
View File
@@ -1,5 +1,5 @@
//+build js
//+private
#+build js
#+private
package runtime
foreign import "odin_env"
+3 -1
View File
@@ -1,4 +1,4 @@
//+private
#+private
package runtime
import "base:intrinsics"
@@ -12,6 +12,8 @@ _stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
SYS_write :: uintptr(4)
} else when ODIN_ARCH == .arm32 {
SYS_write :: uintptr(4)
} else when ODIN_ARCH == .riscv64 {
SYS_write :: uintptr(64)
}
stderr :: 2
+2 -2
View File
@@ -1,5 +1,5 @@
//+build orca
//+private
#+build orca
#+private
package runtime
import "base:intrinsics"
+2 -2
View File
@@ -1,5 +1,5 @@
//+build wasi
//+private
#+build wasi
#+private
package runtime
foreign import wasi "wasi_snapshot_preview1"
+2 -2
View File
@@ -1,5 +1,5 @@
//+build windows
//+private
#+build windows
#+private
package runtime
foreign import kernel32 "system:Kernel32.lib"
+7 -6
View File
@@ -262,7 +262,7 @@ print_typeid :: #force_no_inline proc "contextless" (id: typeid) {
}
}
@(optimization_mode="size")
@(optimization_mode="favor_size")
print_type :: #force_no_inline proc "contextless" (ti: ^Type_Info) {
if ti == nil {
print_string("nil")
@@ -401,15 +401,16 @@ print_type :: #force_no_inline proc "contextless" (ti: ^Type_Info) {
}
print_string("struct ")
if info.is_packed { print_string("#packed ") }
if info.is_raw_union { print_string("#raw_union ") }
if info.custom_align {
if .packed in info.flags { print_string("#packed ") }
if .raw_union in info.flags { print_string("#raw_union ") }
if .no_copy in info.flags { print_string("#no_copy ") }
if .align in info.flags {
print_string("#align(")
print_u64(u64(ti.align))
print_string(") ")
}
print_byte('{')
for name, i in info.names {
for name, i in info.names[:info.field_count] {
if i > 0 { print_string(", ") }
print_string(name)
print_string(": ")
@@ -469,7 +470,7 @@ print_type :: #force_no_inline proc "contextless" (ti: ^Type_Info) {
print_string("bit_field ")
print_type(info.backing_type)
print_string(" {")
for name, i in info.names {
for name, i in info.names[:info.field_count] {
if i > 0 { print_string(", ") }
print_string(name)
print_string(": ")
+1 -1
View File
@@ -1,4 +1,4 @@
//+private
#+private
package runtime
foreign import "system:Foundation.framework"
+1 -1
View File
@@ -1,4 +1,4 @@
//+build js
#+build js
package runtime
init_default_context_for_js: Context
+57 -14
View File
@@ -1,4 +1,4 @@
//+build wasm32, wasm64p32
#+build wasm32, wasm64p32
package runtime
@(private="file")
@@ -14,33 +14,57 @@ ti_uint :: struct #raw_union {
}
@(link_name="__ashlti3", linkage="strong")
__ashlti3 :: proc "contextless" (la, ha: u64, b_: u32) -> i128 {
bits_in_dword :: size_of(u32)*8
b := u32(b_)
__ashlti3 :: proc "contextless" (a: i128, b: u32) -> i128 {
bits :: 64
input, result: ti_int
input.lo, input.hi = la, ha
if b & bits_in_dword != 0 {
input: ti_int = ---
result: ti_int = ---
input.all = a
if b & bits != 0 {
result.lo = 0
result.hi = input.lo << (b-bits_in_dword)
result.hi = input.lo << (b-bits)
} else {
if b == 0 {
return input.all
return a
}
result.lo = input.lo<<b
result.hi = (input.hi<<b) | (input.lo>>(bits_in_dword-b))
result.hi = (input.hi<<b) | (input.lo>>(bits-b))
}
return result.all
}
__ashlti3_unsigned :: proc "contextless" (a: u128, b: u32) -> u128 {
return cast(u128)__ashlti3(cast(i128)a, b)
}
@(link_name="__mulddi3", linkage="strong")
__mulddi3 :: proc "contextless" (a, b: u64) -> i128 {
r: ti_int
bits :: 32
mask :: ~u64(0) >> bits
r.lo = (a & mask) * (b & mask)
t := r.lo >> bits
r.lo &= mask
t += (a >> bits) * (b & mask)
r.lo += (t & mask) << bits
r.hi = t >> bits
t = r.lo >> bits
r.lo &= mask
t += (b >> bits) * (a & mask)
r.lo += (t & mask) << bits
r.hi += t >> bits
r.hi += (a >> bits) * (b >> bits)
return r.all
}
@(link_name="__multi3", linkage="strong")
__multi3 :: proc "contextless" (la, ha, lb, hb: u64) -> i128 {
__multi3 :: proc "contextless" (a, b: i128) -> i128 {
x, y, r: ti_int
x.lo, x.hi = la, ha
y.lo, y.hi = lb, hb
r.all = i128(x.lo * y.lo) // TODO this is incorrect
x.all = a
y.all = b
r.all = __mulddi3(x.lo, y.lo)
r.hi += x.hi*y.lo + x.lo*y.hi
return r.all
}
@@ -52,3 +76,22 @@ udivti3 :: proc "c" (la, ha, lb, hb: u64) -> u128 {
b.lo, b.hi = lb, hb
return udivmodti4(a.all, b.all, nil)
}
@(link_name="__lshrti3", linkage="strong")
__lshrti3 :: proc "c" (a: i128, b: u32) -> i128 {
bits :: 64
input, result: ti_int
input.all = a
if b & bits != 0 {
result.hi = 0
result.lo = input.hi >> (b - bits)
} else if b == 0 {
return a
} else {
result.hi = input.hi >> b
result.lo = (input.hi << (bits - b)) | (input.lo >> b)
}
return result.all
}
+2 -2
View File
@@ -1,5 +1,5 @@
//+private
//+no-instrumentation
#+private
#+no-instrumentation
package runtime
foreign import kernel32 "system:Kernel32.lib"
+2 -2
View File
@@ -1,5 +1,5 @@
//+private
//+no-instrumentation
#+private
#+no-instrumentation
package runtime
@require foreign import "system:int64.lib"
+34
View File
@@ -0,0 +1,34 @@
package runtime
Thread_Local_Cleaner :: #type proc "odin" ()
@(private="file")
thread_local_cleaners: [8]Thread_Local_Cleaner
// Add a procedure that will be run at the end of a thread for the purpose of
// deallocating state marked as `thread_local`.
//
// Intended to be called in an `init` procedure of a package with
// dynamically-allocated memory that is stored in `thread_local` variables.
add_thread_local_cleaner :: proc "contextless" (p: Thread_Local_Cleaner) {
for &v in thread_local_cleaners {
if v == nil {
v = p
return
}
}
panic_contextless("There are no more thread-local cleaner slots available.")
}
// Run all of the thread-local cleaner procedures.
//
// Intended to be called by the internals of a threading API at the end of a
// thread's lifetime.
run_thread_local_cleaners :: proc "odin" () {
for p in thread_local_cleaners {
if p == nil {
break
}
p()
}
}
+3 -2
View File
@@ -1,4 +1,4 @@
//+build wasm32, wasm64p32
#+build wasm32, wasm64p32
package runtime
import "base:intrinsics"
@@ -297,7 +297,8 @@ lock :: proc(a: ^WASM_Allocator) {
return
}
assert(intrinsics.wasm_memory_atomic_wait32((^u32)(&a.mu), u32(new_state), -1) != 0)
ret := intrinsics.wasm_memory_atomic_wait32((^u32)(&a.mu), u32(new_state), -1)
assert(ret != 0)
intrinsics.cpu_relax()
}
}
Binary file not shown.
Binary file not shown.
+39 -6
View File
@@ -22,9 +22,9 @@ if "%VSCMD_ARG_TGT_ARCH%" neq "x64" (
for /f "usebackq tokens=1,2 delims=,=- " %%i in (`wmic os get LocalDateTime /value`) do @if %%i==LocalDateTime (
set CURR_DATE_TIME=%%j
)
set curr_year=%CURR_DATE_TIME:~0,4%
set curr_month=%CURR_DATE_TIME:~4,2%
set curr_day=%CURR_DATE_TIME:~6,2%
:: Make sure this is a decent name and not generic
set exe_name=odin.exe
@@ -45,23 +45,49 @@ if "%2" == "1" (
set nightly=0
)
set odin_version_raw="dev-%curr_year%-%curr_month%"
if %release_mode% equ 0 (
set V1=%curr_year%
set V2=%curr_month%
set V3=%curr_day%
) else (
set V1=%curr_year%
set V2=%curr_month%
set V3=0
)
set V4=0
set odin_version_full="%V1%.%V2%.%V3%.%V4%"
set odin_version_raw="dev-%V1%-%V2%"
set compiler_flags= -nologo -Oi -TP -fp:precise -Gm- -MP -FC -EHsc- -GR- -GF
rem Parse source code as utf-8 even on shift-jis and other codepages
rem See https://learn.microsoft.com/en-us/cpp/build/reference/utf-8-set-source-and-executable-character-sets-to-utf-8?view=msvc-170
set compiler_flags= %compiler_flags% /utf-8
set compiler_defines= -DODIN_VERSION_RAW=\"%odin_version_raw%\"
rem fileversion is defined as {Major,Minor,Build,Private: u16} so a bit limited
set rc_flags=-nologo ^
-DV1=%V1% -DV2=%V2% -DV3=%V3% -DV4=%V4% ^
-DVF=%odin_version_full% -DNIGHTLY=%nightly%
if not exist .git\ goto skip_git_hash
for /f "tokens=1,2" %%i IN ('git show "--pretty=%%cd %%h" "--date=format:%%Y-%%m" --no-patch --no-notes HEAD') do (
set odin_version_raw=dev-%%i
set GIT_SHA=%%j
)
if %ERRORLEVEL% equ 0 set compiler_defines=%compiler_defines% -DGIT_SHA=\"%GIT_SHA%\"
if %ERRORLEVEL% equ 0 (
set compiler_defines=%compiler_defines% -DGIT_SHA=\"%GIT_SHA%\"
set rc_flags=%rc_flags% -DGIT_SHA=%GIT_SHA% -DVP=%odin_version_raw%:%GIT_SHA%
) else (
set rc_flags=%rc_flags% -DVP=%odin_version_raw%
)
:skip_git_hash
if %nightly% equ 1 set compiler_defines=%compiler_defines% -DNIGHTLY
if %release_mode% EQU 0 ( rem Debug
set compiler_flags=%compiler_flags% -Od -MDd -Z7
set rc_flags=%rc_flags% -D_DEBUG
) else ( rem Release
set compiler_flags=%compiler_flags% -O2 -MT -Z7
set compiler_defines=%compiler_defines% -DNO_ARRAY_BOUNDS_CHECK
@@ -79,6 +105,8 @@ set libs= ^
kernel32.lib ^
Synchronization.lib ^
bin\llvm\windows\LLVM-C.lib
set odin_res=misc\odin.res
set odin_rc=misc\odin.rc
rem DO NOT TOUCH!
rem THIS TILDE STUFF IS FOR DEVELOPMENT ONLY!
@@ -90,7 +118,7 @@ if %tilde_backend% EQU 1 (
rem DO NOT TOUCH!
set linker_flags= -incremental:no -opt:ref -subsystem:console
set linker_flags= -incremental:no -opt:ref -subsystem:console -MANIFEST:EMBED
if %release_mode% EQU 0 ( rem Debug
set linker_flags=%linker_flags% -debug /NATVIS:src\odin_compiler.natvis
@@ -99,19 +127,24 @@ if %release_mode% EQU 0 ( rem Debug
)
set compiler_settings=%compiler_includes% %compiler_flags% %compiler_warnings% %compiler_defines%
set linker_settings=%libs% %linker_flags%
set linker_settings=%libs% %odin_res% %linker_flags%
del *.pdb > NUL 2> NUL
del *.ilk > NUL 2> NUL
rc %rc_flags% %odin_rc%
cl %compiler_settings% "src\main.cpp" "src\libtommath.cpp" /link %linker_settings% -OUT:%exe_name%
mt -nologo -inputresource:%exe_name%;#1 -manifest misc\odin.manifest -outputresource:%exe_name%;#1 -validate_manifest -identity:"odin, processorArchitecture=amd64, version=%odin_version_full%, type=win32"
if %errorlevel% neq 0 goto end_of_build
call build_vendor.bat
if %errorlevel% neq 0 goto end_of_build
rem If the demo doesn't run for you and your CPU is more than a decade old, try -microarch:native
if %release_mode% EQU 0 odin run examples/demo -- Hellope World
if %release_mode% EQU 0 odin run examples/demo -vet -strict-style -resource:examples/demo/demo.rc -- Hellope World
rem Many non-compiler devs seem to run debug build but don't realize.
if %release_mode% EQU 0 echo: & echo Debug compiler built. Note: run "build.bat release" if you want a faster, release mode compiler.
del *.obj > NUL 2> NUL
+15 -2
View File
@@ -23,6 +23,14 @@ error() {
exit 1
}
# Brew advises people not to add llvm to their $PATH, so try and use brew to find it.
if [ -z "$LLVM_CONFIG" ] && [ -n "$(command -v brew)" ]; then
if [ -n "$(command -v $(brew --prefix llvm@18)/bin/llvm-config)" ]; then LLVM_CONFIG="$(brew --prefix llvm@18)/bin/llvm-config"
elif [ -n "$(command -v $(brew --prefix llvm@17)/bin/llvm-config)" ]; then LLVM_CONFIG="$(brew --prefix llvm@17)/bin/llvm-config"
elif [ -n "$(command -v $(brew --prefix llvm@14)/bin/llvm-config)" ]; then LLVM_CONFIG="$(brew --prefix llvm@14)/bin/llvm-config"
fi
fi
if [ -z "$LLVM_CONFIG" ]; then
# darwin, linux, openbsd
if [ -n "$(command -v llvm-config-18)" ]; then LLVM_CONFIG="llvm-config-18"
@@ -95,7 +103,7 @@ Linux)
LDFLAGS="$LDFLAGS -ldl $($LLVM_CONFIG --libs core native --system-libs --libfiles)"
# Copy libLLVM*.so into current directory for linking
# NOTE: This is needed by the Linux release pipeline!
cp $(readlink -f $($LLVM_CONFIG --libfiles)) ./
# cp $(readlink -f $($LLVM_CONFIG --libfiles)) ./
LDFLAGS="$LDFLAGS -Wl,-rpath=\$ORIGIN"
;;
OpenBSD)
@@ -144,12 +152,17 @@ build_odin() {
}
run_demo() {
./odin run examples/demo/demo.odin -file -- Hellope World
if [ $# -eq 0 ] || [ "$1" = "debug" ]; then
./odin run examples/demo -vet -strict-style -- Hellope World
fi
}
if [ $# -eq 0 ]; then
build_odin debug
run_demo
: ${PROGRAM:=$0}
printf "\nDebug compiler built. Note: run \"$PROGRAM release\" or \"$PROGRAM release-native\" if you want a faster, release mode compiler.\n"
elif [ $# -eq 1 ]; then
case $1 in
report)
+19
View File
@@ -0,0 +1,19 @@
#!/usr/bin/env sh
# Intended for use in Alpine containers, see the "nightly" Github action for a list of dependencies
CXX="clang++-18"
LLVM_CONFIG="llvm-config-18"
DISABLED_WARNINGS="-Wno-switch -Wno-macro-redefined -Wno-unused-value"
CPPFLAGS="-DODIN_VERSION_RAW=\"dev-$(date +"%Y-%m")\""
CXXFLAGS="-std=c++14 $($LLVM_CONFIG --cxxflags --ldflags)"
LDFLAGS="-static -lm -lzstd -lz -lffi -pthread -ldl -fuse-ld=mold"
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --link-static --ldflags --libs --system-libs --libfiles)"
LDFLAGS="$LDFLAGS -Wl,-rpath=\$ORIGIN"
EXTRAFLAGS="-DNIGHTLY -O3"
set -x
$CXX src/main.cpp src/libtommath.cpp $DISABLED_WARNINGS $CPPFLAGS $CXXFLAGS $EXTRAFLAGS $LDFLAGS -o odin
+24 -19
View File
@@ -2,7 +2,7 @@ import os
import sys
from zipfile import ZipFile, ZIP_DEFLATED
from b2sdk.v2 import InMemoryAccountInfo, B2Api
from datetime import datetime
from datetime import datetime, timezone
import json
UPLOAD_FOLDER = "nightly/"
@@ -22,7 +22,7 @@ def auth() -> bool:
pass # Not yet authenticated
err = b2_api.authorize_account("production", application_key_id, application_key)
return err == None
return err is None
def get_bucket():
if not auth(): sys.exit(1)
@@ -32,30 +32,35 @@ def remove_prefix(text: str, prefix: str) -> str:
return text[text.startswith(prefix) and len(prefix):]
def create_and_upload_artifact_zip(platform: str, artifact: str) -> int:
now = datetime.utcnow().replace(hour=0, minute=0, second=0, microsecond=0)
destination_zip_name = "odin-{}-nightly+{}.zip".format(platform, now.strftime("%Y-%m-%d"))
now = datetime.now(timezone.utc).replace(hour=0, minute=0, second=0, microsecond=0)
source_zip_name = artifact
if not artifact.endswith(".zip"):
print(f"Creating archive {destination_zip_name} from {artifact} and uploading to {bucket_name}")
source_archive: str
destination_name = f'odin-{platform}-nightly+{now.strftime("%Y-%m-%d")}'
source_zip_name = destination_zip_name
with ZipFile(source_zip_name, mode='w', compression=ZIP_DEFLATED, compresslevel=9) as z:
if platform.startswith("linux") or platform.startswith("macos"):
destination_name += ".tar.gz"
source_archive = artifact
else:
destination_name += ".zip"
source_archive = destination_name
print(f"Creating archive {destination_name} from {artifact} and uploading to {bucket_name}")
with ZipFile(source_archive, mode='w', compression=ZIP_DEFLATED, compresslevel=9) as z:
for root, directory, filenames in os.walk(artifact):
for file in filenames:
file_path = os.path.join(root, file)
zip_path = os.path.join("dist", os.path.relpath(file_path, artifact))
z.write(file_path, zip_path)
if not os.path.exists(source_zip_name):
print(f"Error: Newly created ZIP archive {source_zip_name} not found.")
return 1
if not os.path.exists(source_archive):
print(f"Error: archive {source_archive} not found.")
return 1
print("Uploading {} to {}".format(source_zip_name, UPLOAD_FOLDER + destination_zip_name))
print("Uploading {} to {}".format(source_archive, UPLOAD_FOLDER + destination_name))
bucket = get_bucket()
res = bucket.upload_local_file(
source_zip_name, # Local file to upload
"nightly/" + destination_zip_name, # B2 destination path
source_archive, # Local file to upload
"nightly/" + destination_name, # B2 destination path
)
return 0
@@ -65,8 +70,8 @@ def prune_artifacts():
bucket = get_bucket()
for file, _ in bucket.ls(UPLOAD_FOLDER, latest_only=False):
# Timestamp is in milliseconds
date = datetime.fromtimestamp(file.upload_timestamp / 1_000.0).replace(hour=0, minute=0, second=0, microsecond=0)
now = datetime.utcnow().replace(hour=0, minute=0, second=0, microsecond=0)
date = datetime.fromtimestamp(file.upload_timestamp / 1_000.0, tz=timezone.utc).replace(hour=0, minute=0, second=0, microsecond=0)
now = datetime.now(timezone.utc).replace(hour=0, minute=0, second=0, microsecond=0)
delta = now - date
if delta.days > int(days_to_keep):
@@ -100,7 +105,7 @@ def update_nightly_json():
'sizeInBytes': size,
})
now = datetime.utcnow().isoformat()
now = datetime.now(timezone.utc).isoformat()
nightly = json.dumps({
'last_updated' : now,
@@ -137,4 +142,4 @@ if __name__ == "__main__":
elif command == "json":
res = update_nightly_json()
sys.exit(res)
sys.exit(res)
+33 -3
View File
@@ -144,6 +144,9 @@ buffer_grow :: proc(b: ^Buffer, n: int, loc := #caller_location) {
}
buffer_write_at :: proc(b: ^Buffer, p: []byte, offset: int, loc := #caller_location) -> (n: int, err: io.Error) {
if len(p) == 0 {
return 0, nil
}
b.last_read = .Invalid
if offset < 0 {
err = .Invalid_Offset
@@ -246,10 +249,13 @@ buffer_read_ptr :: proc(b: ^Buffer, ptr: rawptr, size: int) -> (n: int, err: io.
}
buffer_read_at :: proc(b: ^Buffer, p: []byte, offset: int) -> (n: int, err: io.Error) {
if len(p) == 0 {
return 0, nil
}
b.last_read = .Invalid
if uint(offset) >= len(b.buf) {
err = .Invalid_Offset
err = .EOF
return
}
n = copy(p, b.buf[offset:])
@@ -310,6 +316,27 @@ buffer_unread_rune :: proc(b: ^Buffer) -> io.Error {
return nil
}
buffer_seek :: proc(b: ^Buffer, offset: i64, whence: io.Seek_From) -> (i64, io.Error) {
abs: i64
switch whence {
case .Start:
abs = offset
case .Current:
abs = i64(b.off) + offset
case .End:
abs = i64(len(b.buf)) + offset
case:
return 0, .Invalid_Whence
}
abs_int := int(abs)
if abs_int < 0 {
return 0, .Invalid_Offset
}
b.last_read = .Invalid
b.off = abs_int
return abs, nil
}
buffer_read_bytes :: proc(b: ^Buffer, delim: byte) -> (line: []byte, err: io.Error) {
i := index_byte(b.buf[b.off:], delim)
@@ -395,14 +422,17 @@ _buffer_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offse
return io._i64_err(buffer_write(b, p))
case .Write_At:
return io._i64_err(buffer_write_at(b, p, int(offset)))
case .Seek:
n, err = buffer_seek(b, offset, whence)
return
case .Size:
n = i64(buffer_capacity(b))
n = i64(buffer_length(b))
return
case .Destroy:
buffer_destroy(b)
return
case .Query:
return io.query_utility({.Read, .Read_At, .Write, .Write_At, .Size, .Destroy})
return io.query_utility({.Read, .Read_At, .Write, .Write_At, .Seek, .Size, .Destroy, .Query})
}
return 0, .Empty
}
+309 -6
View File
@@ -1,9 +1,38 @@
package bytes
import "base:intrinsics"
import "core:mem"
import "core:simd"
import "core:unicode"
import "core:unicode/utf8"
when ODIN_ARCH == .amd64 && intrinsics.has_target_feature("avx2") {
@(private)
SCANNER_INDICES_256 : simd.u8x32 : {
0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31,
}
@(private)
SCANNER_SENTINEL_MAX_256: simd.u8x32 : u8(0x00)
@(private)
SCANNER_SENTINEL_MIN_256: simd.u8x32 : u8(0xff)
@(private)
SIMD_REG_SIZE_256 :: 32
}
@(private)
SCANNER_INDICES_128 : simd.u8x16 : {
0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15,
}
@(private)
SCANNER_SENTINEL_MAX_128: simd.u8x16 : u8(0x00)
@(private)
SCANNER_SENTINEL_MIN_128: simd.u8x16 : u8(0xff)
@(private)
SIMD_REG_SIZE_128 :: 16
clone :: proc(s: []byte, allocator := context.allocator, loc := #caller_location) -> []byte {
c := make([]byte, len(s), allocator, loc)
copy(c, s)
@@ -293,28 +322,277 @@ split_after_iterator :: proc(s: ^[]byte, sep: []byte) -> ([]byte, bool) {
return _split_iterator(s, sep, len(sep))
}
/*
Scan a slice of bytes for a specific byte.
index_byte :: proc(s: []byte, c: byte) -> int {
for i := 0; i < len(s); i += 1 {
This procedure safely handles slices of any length, including empty slices.
Inputs:
- data: A slice of bytes.
- c: The byte to search for.
Returns:
- index: The index of the byte `c`, or -1 if it was not found.
*/
index_byte :: proc "contextless" (s: []byte, c: byte) -> (index: int) #no_bounds_check {
i, l := 0, len(s)
// Guard against small strings. On modern systems, it is ALWAYS
// worth vectorizing assuming there is a hardware vector unit, and
// the data size is large enough.
if l < SIMD_REG_SIZE_128 {
for /**/; i < l; i += 1 {
if s[i] == c {
return i
}
}
return -1
}
c_vec: simd.u8x16 = c
when !simd.IS_EMULATED {
// Note: While this is something that could also logically take
// advantage of AVX512, the various downclocking and power
// consumption related woes make premature to have a dedicated
// code path.
when ODIN_ARCH == .amd64 && intrinsics.has_target_feature("avx2") {
c_vec_256: simd.u8x32 = c
s_vecs: [4]simd.u8x32 = ---
c_vecs: [4]simd.u8x32 = ---
m_vec: [4]u8 = ---
// Scan 128-byte chunks, using 256-bit SIMD.
for nr_blocks := l / (4 * SIMD_REG_SIZE_256); nr_blocks > 0; nr_blocks -= 1 {
#unroll for j in 0..<4 {
s_vecs[j] = intrinsics.unaligned_load(cast(^simd.u8x32)raw_data(s[i+j*SIMD_REG_SIZE_256:]))
c_vecs[j] = simd.lanes_eq(s_vecs[j], c_vec_256)
m_vec[j] = simd.reduce_or(c_vecs[j])
}
if m_vec[0] | m_vec[1] | m_vec[2] | m_vec[3] > 0 {
#unroll for j in 0..<4 {
if m_vec[j] > 0 {
sel := simd.select(c_vecs[j], SCANNER_INDICES_256, SCANNER_SENTINEL_MIN_256)
off := simd.reduce_min(sel)
return i + j * SIMD_REG_SIZE_256 + int(off)
}
}
}
i += 4 * SIMD_REG_SIZE_256
}
// Scan 64-byte chunks, using 256-bit SIMD.
for nr_blocks := (l - i) / (2 * SIMD_REG_SIZE_256); nr_blocks > 0; nr_blocks -= 1 {
#unroll for j in 0..<2 {
s_vecs[j] = intrinsics.unaligned_load(cast(^simd.u8x32)raw_data(s[i+j*SIMD_REG_SIZE_256:]))
c_vecs[j] = simd.lanes_eq(s_vecs[j], c_vec_256)
m_vec[j] = simd.reduce_or(c_vecs[j])
}
if m_vec[0] | m_vec[1] > 0 {
#unroll for j in 0..<2 {
if m_vec[j] > 0 {
sel := simd.select(c_vecs[j], SCANNER_INDICES_256, SCANNER_SENTINEL_MIN_256)
off := simd.reduce_min(sel)
return i + j * SIMD_REG_SIZE_256 + int(off)
}
}
}
i += 2 * SIMD_REG_SIZE_256
}
} else {
s_vecs: [4]simd.u8x16 = ---
c_vecs: [4]simd.u8x16 = ---
m_vecs: [4]u8 = ---
// Scan 64-byte chunks, using 128-bit SIMD.
for nr_blocks := l / (4 * SIMD_REG_SIZE_128); nr_blocks > 0; nr_blocks -= 1 {
#unroll for j in 0..<4 {
s_vecs[j]= intrinsics.unaligned_load(cast(^simd.u8x16)raw_data(s[i+j*SIMD_REG_SIZE_128:]))
c_vecs[j] = simd.lanes_eq(s_vecs[j], c_vec)
m_vecs[j] = simd.reduce_or(c_vecs[j])
}
if m_vecs[0] | m_vecs[1] | m_vecs[2] | m_vecs[3] > 0 {
#unroll for j in 0..<4 {
if m_vecs[j] > 0 {
sel := simd.select(c_vecs[j], SCANNER_INDICES_128, SCANNER_SENTINEL_MIN_128)
off := simd.reduce_min(sel)
return i + j * SIMD_REG_SIZE_128 + int(off)
}
}
}
i += 4 * SIMD_REG_SIZE_128
}
}
}
// Scan the remaining SIMD register sized chunks.
//
// Apparently LLVM does ok with 128-bit SWAR, so this path is also taken
// on potato targets. Scanning more at a time when LLVM is emulating SIMD
// likely does not buy much, as all that does is increase GP register
// pressure.
for nr_blocks := (l - i) / SIMD_REG_SIZE_128; nr_blocks > 0; nr_blocks -= 1 {
s0 := intrinsics.unaligned_load(cast(^simd.u8x16)raw_data(s[i:]))
c0 := simd.lanes_eq(s0, c_vec)
if simd.reduce_or(c0) > 0 {
sel := simd.select(c0, SCANNER_INDICES_128, SCANNER_SENTINEL_MIN_128)
off := simd.reduce_min(sel)
return i + int(off)
}
i += SIMD_REG_SIZE_128
}
// Scan serially for the remainder.
for /**/; i < l; i += 1 {
if s[i] == c {
return i
}
}
return -1
}
// Returns -1 if c is not present
last_index_byte :: proc(s: []byte, c: byte) -> int {
for i := len(s)-1; i >= 0; i -= 1 {
/*
Scan a slice of bytes for a specific byte, starting from the end and working
backwards to the start.
This procedure safely handles slices of any length, including empty slices.
Inputs:
- data: A slice of bytes.
- c: The byte to search for.
Returns:
- index: The index of the byte `c`, or -1 if it was not found.
*/
last_index_byte :: proc "contextless" (s: []byte, c: byte) -> int #no_bounds_check {
i := len(s)
// Guard against small strings. On modern systems, it is ALWAYS
// worth vectorizing assuming there is a hardware vector unit, and
// the data size is large enough.
if i < SIMD_REG_SIZE_128 {
#reverse for ch, j in s {
if ch == c {
return j
}
}
return -1
}
c_vec: simd.u8x16 = c
when !simd.IS_EMULATED {
// Note: While this is something that could also logically take
// advantage of AVX512, the various downclocking and power
// consumption related woes make premature to have a dedicated
// code path.
when ODIN_ARCH == .amd64 && intrinsics.has_target_feature("avx2") {
c_vec_256: simd.u8x32 = c
s_vecs: [4]simd.u8x32 = ---
c_vecs: [4]simd.u8x32 = ---
m_vec: [4]u8 = ---
// Scan 128-byte chunks, using 256-bit SIMD.
for i >= 4 * SIMD_REG_SIZE_256 {
i -= 4 * SIMD_REG_SIZE_256
#unroll for j in 0..<4 {
s_vecs[j] = intrinsics.unaligned_load(cast(^simd.u8x32)raw_data(s[i+j*SIMD_REG_SIZE_256:]))
c_vecs[j] = simd.lanes_eq(s_vecs[j], c_vec_256)
m_vec[j] = simd.reduce_or(c_vecs[j])
}
if m_vec[0] | m_vec[1] | m_vec[2] | m_vec[3] > 0 {
#unroll for j in 0..<4 {
if m_vec[3-j] > 0 {
sel := simd.select(c_vecs[3-j], SCANNER_INDICES_256, SCANNER_SENTINEL_MAX_256)
off := simd.reduce_max(sel)
return i + (3-j) * SIMD_REG_SIZE_256 + int(off)
}
}
}
}
// Scan 64-byte chunks, using 256-bit SIMD.
for i >= 2 * SIMD_REG_SIZE_256 {
i -= 2 * SIMD_REG_SIZE_256
#unroll for j in 0..<2 {
s_vecs[j] = intrinsics.unaligned_load(cast(^simd.u8x32)raw_data(s[i+j*SIMD_REG_SIZE_256:]))
c_vecs[j] = simd.lanes_eq(s_vecs[j], c_vec_256)
m_vec[j] = simd.reduce_or(c_vecs[j])
}
if m_vec[0] | m_vec[1] > 0 {
#unroll for j in 0..<2 {
if m_vec[1-j] > 0 {
sel := simd.select(c_vecs[1-j], SCANNER_INDICES_256, SCANNER_SENTINEL_MAX_256)
off := simd.reduce_max(sel)
return i + (1-j) * SIMD_REG_SIZE_256 + int(off)
}
}
}
}
} else {
s_vecs: [4]simd.u8x16 = ---
c_vecs: [4]simd.u8x16 = ---
m_vecs: [4]u8 = ---
// Scan 64-byte chunks, using 128-bit SIMD.
for i >= 4 * SIMD_REG_SIZE_128 {
i -= 4 * SIMD_REG_SIZE_128
#unroll for j in 0..<4 {
s_vecs[j] = intrinsics.unaligned_load(cast(^simd.u8x16)raw_data(s[i+j*SIMD_REG_SIZE_128:]))
c_vecs[j] = simd.lanes_eq(s_vecs[j], c_vec)
m_vecs[j] = simd.reduce_or(c_vecs[j])
}
if m_vecs[0] | m_vecs[1] | m_vecs[2] | m_vecs[3] > 0 {
#unroll for j in 0..<4 {
if m_vecs[3-j] > 0 {
sel := simd.select(c_vecs[3-j], SCANNER_INDICES_128, SCANNER_SENTINEL_MAX_128)
off := simd.reduce_max(sel)
return i + (3-j) * SIMD_REG_SIZE_128 + int(off)
}
}
}
}
}
}
// Scan the remaining SIMD register sized chunks.
//
// Apparently LLVM does ok with 128-bit SWAR, so this path is also taken
// on potato targets. Scanning more at a time when LLVM is emulating SIMD
// likely does not buy much, as all that does is increase GP register
// pressure.
for i >= SIMD_REG_SIZE_128 {
i -= SIMD_REG_SIZE_128
s0 := intrinsics.unaligned_load(cast(^simd.u8x16)raw_data(s[i:]))
c0 := simd.lanes_eq(s0, c_vec)
if simd.reduce_or(c0) > 0 {
sel := simd.select(c0, SCANNER_INDICES_128, SCANNER_SENTINEL_MAX_128)
off := simd.reduce_max(sel)
return i + int(off)
}
}
// Scan serially for the remainder.
for i > 0 {
i -= 1
if s[i] == c {
return i
}
}
return -1
}
@private PRIME_RABIN_KARP :: 16777619
index :: proc(s, substr: []byte) -> int {
@@ -1167,3 +1445,28 @@ fields_proc :: proc(s: []byte, f: proc(rune) -> bool, allocator := context.alloc
return subslices[:]
}
// alias returns true iff a and b have a non-zero length, and any part of
// a overlaps with b.
alias :: proc "contextless" (a, b: []byte) -> bool {
a_len, b_len := len(a), len(b)
if a_len == 0 || b_len == 0 {
return false
}
a_start, b_start := uintptr(raw_data(a)), uintptr(raw_data(b))
a_end, b_end := a_start + uintptr(a_len-1), b_start + uintptr(b_len-1)
return a_start <= b_end && b_start <= a_end
}
// alias_inexactly returns true iff a and b have a non-zero length,
// the base pointer of a and b are NOT equal, and any part of a overlaps
// with b (ie: `alias(a, b)` with an exception that returns false for
// `a == b`, `b = a[:len(a)-69]` and similar conditions).
alias_inexactly :: proc "contextless" (a, b: []byte) -> bool {
if raw_data(a) == raw_data(b) {
return false
}
return alias(a, b)
}
+9 -2
View File
@@ -9,10 +9,11 @@ Reader :: struct {
prev_rune: int, // previous reading index of rune or < 0
}
reader_init :: proc(r: ^Reader, s: []byte) {
reader_init :: proc(r: ^Reader, s: []byte) -> io.Stream {
r.s = s
r.i = 0
r.prev_rune = -1
return reader_to_stream(r)
}
reader_to_stream :: proc(r: ^Reader) -> (s: io.Stream) {
@@ -33,6 +34,9 @@ reader_size :: proc(r: ^Reader) -> i64 {
}
reader_read :: proc(r: ^Reader, p: []byte) -> (n: int, err: io.Error) {
if len(p) == 0 {
return 0, nil
}
if r.i >= i64(len(r.s)) {
return 0, .EOF
}
@@ -42,6 +46,9 @@ reader_read :: proc(r: ^Reader, p: []byte) -> (n: int, err: io.Error) {
return
}
reader_read_at :: proc(r: ^Reader, p: []byte, off: i64) -> (n: int, err: io.Error) {
if len(p) == 0 {
return 0, nil
}
if off < 0 {
return 0, .Invalid_Offset
}
@@ -97,7 +104,6 @@ reader_unread_rune :: proc(r: ^Reader) -> io.Error {
return nil
}
reader_seek :: proc(r: ^Reader, offset: i64, whence: io.Seek_From) -> (i64, io.Error) {
r.prev_rune = -1
abs: i64
switch whence {
case .Start:
@@ -114,6 +120,7 @@ reader_seek :: proc(r: ^Reader, offset: i64, whence: io.Seek_From) -> (i64, io.E
return 0, .Invalid_Offset
}
r.i = abs
r.prev_rune = -1
return abs, nil
}
reader_write_to :: proc(r: ^Reader, w: io.Writer) -> (n: i64, err: io.Error) {
+2 -2
View File
@@ -47,8 +47,8 @@ foreign libc {
clogf :: proc(z: complex_float) -> complex_float ---
// 7.3.8 Power and absolute-value functions
cabs :: proc(z: complex_double) -> complex_double ---
cabsf :: proc(z: complex_float) -> complex_float ---
cabs :: proc(z: complex_double) -> double ---
cabsf :: proc(z: complex_float) -> float ---
cpow :: proc(x, y: complex_double) -> complex_double ---
cpowf :: proc(x, y: complex_float) -> complex_float ---
csqrt :: proc(z: complex_double) -> complex_double ---
+9 -1
View File
@@ -98,10 +98,18 @@ when ODIN_OS == .Haiku {
ERANGE :: B_POSIX_ERROR_BASE + 17
}
when ODIN_OS == .JS {
_ :: libc
_get_errno :: proc "c" () -> ^int {
@(static) errno: int
return &errno
}
}
// Odin has no way to make an identifier "errno" behave as a function call to
// read the value, or to produce an lvalue such that you can assign a different
// error value to errno. To work around this, just expose it as a function like
// it actually is.
errno :: #force_inline proc() -> ^int {
errno :: #force_inline proc "contextless" () -> ^int {
return _get_errno()
}
+12 -7
View File
@@ -32,24 +32,21 @@ when ODIN_OS == .Windows {
// the RDX register will contain zero and correctly set the flag to disable
// stack unwinding.
@(link_name="_setjmp")
setjmp :: proc(env: ^jmp_buf, hack: rawptr = nil) -> int ---
setjmp :: proc(env: ^jmp_buf, hack: rawptr = nil) -> int ---
}
} else {
@(default_calling_convention="c")
foreign libc {
// 7.13.1 Save calling environment
//
// NOTE(dweiler): C11 requires setjmp be a macro, which means it won't
// necessarily export a symbol named setjmp but rather _setjmp in the case
// of musl, glibc, BSD libc, and msvcrt.
@(link_name="_setjmp")
setjmp :: proc(env: ^jmp_buf) -> int ---
@(link_name=LSETJMP)
setjmp :: proc(env: ^jmp_buf) -> int ---
}
}
@(default_calling_convention="c")
foreign libc {
// 7.13.2 Restore calling environment
@(link_name=LLONGJMP)
longjmp :: proc(env: ^jmp_buf, val: int) -> ! ---
}
@@ -64,3 +61,11 @@ foreign libc {
// The choice of 4096 bytes for storage of this type is more than enough on all
// relevant platforms.
jmp_buf :: struct #align(16) { _: [4096]char, }
when ODIN_OS == .NetBSD {
@(private) LSETJMP :: "__setjmp14"
@(private) LLONGJMP :: "__longjmp14"
} else {
@(private) LSETJMP :: "setjmp"
@(private) LLONGJMP :: "longjmp"
}
+1 -1
View File
@@ -235,7 +235,7 @@ atomic_compare_exchange_weak :: #force_inline proc(object, expected: ^$T, desire
return ok
}
atomic_compare_exchange_weak_explicit :: #force_inline proc(object, expected: ^$T, desited: T, success, failure: memory_order) -> bool {
atomic_compare_exchange_weak_explicit :: #force_inline proc(object, expected: ^$T, desired: T, success, failure: memory_order) -> bool {
assert(failure != .release)
assert(failure != .acq_rel)
+60 -9
View File
@@ -17,6 +17,12 @@ when ODIN_OS == .Windows {
FILE :: struct {}
Whence :: enum int {
SET = SEEK_SET,
CUR = SEEK_CUR,
END = SEEK_END,
}
// MSVCRT compatible.
when ODIN_OS == .Windows {
_IOFBF :: 0x0000
@@ -83,6 +89,30 @@ when ODIN_OS == .Linux {
}
}
when ODIN_OS == .JS {
fpos_t :: struct #raw_union { _: [16]char, _: longlong, _: double, }
_IOFBF :: 0
_IOLBF :: 1
_IONBF :: 2
BUFSIZ :: 1024
EOF :: int(-1)
FOPEN_MAX :: 1000
FILENAME_MAX :: 4096
L_tmpnam :: 20
SEEK_SET :: 0
SEEK_CUR :: 1
SEEK_END :: 2
TMP_MAX :: 308915776
}
when ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD {
fpos_t :: distinct i64
@@ -101,6 +131,8 @@ when ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD {
SEEK_CUR :: 1
SEEK_END :: 2
TMP_MAX :: 308915776
foreign libc {
__sF: [3]FILE
}
@@ -128,6 +160,8 @@ when ODIN_OS == .FreeBSD {
SEEK_CUR :: 1
SEEK_END :: 2
TMP_MAX :: 308915776
foreign libc {
@(link_name="__stderrp") stderr: ^FILE
@(link_name="__stdinp") stdin: ^FILE
@@ -195,10 +229,21 @@ when ODIN_OS == .Haiku {
}
}
when ODIN_OS == .NetBSD {
@(private) LRENAME :: "__posix_rename"
@(private) LFGETPOS :: "__fgetpos50"
@(private) LFSETPOS :: "__fsetpos50"
} else {
@(private) LRENAME :: "rename"
@(private) LFGETPOS :: "fgetpos"
@(private) LFSETPOS :: "fsetpos"
}
@(default_calling_convention="c")
foreign libc {
// 7.21.4 Operations on files
remove :: proc(filename: cstring) -> int ---
@(link_name=LRENAME)
rename :: proc(old, new: cstring) -> int ---
tmpfile :: proc() -> ^FILE ---
tmpnam :: proc(s: [^]char) -> [^]char ---
@@ -240,8 +285,10 @@ foreign libc {
fwrite :: proc(ptr: rawptr, size: size_t, nmemb: size_t, stream: ^FILE) -> size_t ---
// 7.21.9 File positioning functions
@(link_name=LFGETPOS)
fgetpos :: proc(stream: ^FILE, pos: ^fpos_t) -> int ---
fseek :: proc(stream: ^FILE, offset: long, whence: int) -> int ---
fseek :: proc(stream: ^FILE, offset: long, whence: Whence) -> int ---
@(link_name=LFSETPOS)
fsetpos :: proc(stream: ^FILE, pos: ^fpos_t) -> int ---
ftell :: proc(stream: ^FILE) -> long ---
rewind :: proc(stream: ^FILE) ---
@@ -288,11 +335,11 @@ to_stream :: proc(file: ^FILE) -> io.Stream {
return 0, unknown_or_eof(file)
}
if fseek(file, long(offset), SEEK_SET) != 0 {
if fseek(file, long(offset), .SET) != 0 {
return 0, unknown_or_eof(file)
}
defer fseek(file, long(curr), SEEK_SET)
defer fseek(file, long(curr), .SET)
n = i64(fread(raw_data(p), size_of(byte), len(p), file))
if n == 0 { err = unknown_or_eof(file) }
@@ -307,17 +354,21 @@ to_stream :: proc(file: ^FILE) -> io.Stream {
return 0, unknown_or_eof(file)
}
if fseek(file, long(offset), SEEK_SET) != 0 {
if fseek(file, long(offset), .SET) != 0 {
return 0, unknown_or_eof(file)
}
defer fseek(file, long(curr), SEEK_SET)
defer fseek(file, long(curr), .SET)
n = i64(fwrite(raw_data(p), size_of(byte), len(p), file))
if n == 0 { err = unknown_or_eof(file) }
case .Seek:
if fseek(file, long(offset), int(whence)) != 0 {
#assert(int(Whence.SET) == int(io.Seek_From.Start))
#assert(int(Whence.CUR) == int(io.Seek_From.Current))
#assert(int(Whence.END) == int(io.Seek_From.End))
if fseek(file, long(offset), Whence(whence)) != 0 {
return 0, unknown_or_eof(file)
}
@@ -326,9 +377,9 @@ to_stream :: proc(file: ^FILE) -> io.Stream {
if curr == -1 {
return 0, unknown_or_eof(file)
}
defer fseek(file, curr, SEEK_SET)
defer fseek(file, curr, .SET)
if fseek(file, 0, SEEK_END) != 0 {
if fseek(file, 0, .END) != 0 {
return 0, unknown_or_eof(file)
}
@@ -341,7 +392,7 @@ to_stream :: proc(file: ^FILE) -> io.Stream {
return 0, .Empty
case .Query:
return io.query_utility({ .Close, .Flush, .Read, .Read_At, .Write, .Write_At, .Seek, .Size })
return io.query_utility({ .Close, .Flush, .Read, .Read_At, .Write, .Write_At, .Seek, .Size, .Query })
}
return
}
+27 -4
View File
@@ -10,6 +10,9 @@ when ODIN_OS == .Windows {
foreign import libc "system:c"
}
@(require)
import "base:runtime"
when ODIN_OS == .Windows {
RAND_MAX :: 0x7fff
@@ -40,10 +43,9 @@ when ODIN_OS == .Linux {
}
when ODIN_OS == .Darwin {
when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .OpenBSD {
RAND_MAX :: 0x7fffffff
// GLIBC and MUSL only
@(private="file")
@(default_calling_convention="c")
foreign libc {
@@ -55,6 +57,20 @@ when ODIN_OS == .Darwin {
}
}
when ODIN_OS == .NetBSD {
RAND_MAX :: 0x7fffffff
@(private="file")
@(default_calling_convention="c")
foreign libc {
__mb_cur_max: size_t
}
MB_CUR_MAX :: #force_inline proc() -> size_t {
return __mb_cur_max
}
}
// C does not declare what these values should be, as an implementation is free
// to use any two distinct values it wants to indicate success or failure.
// However, nobody actually does and everyone appears to have agreed upon these
@@ -99,7 +115,7 @@ foreign libc {
at_quick_exit :: proc(func: proc "c" ()) -> int ---
exit :: proc(status: int) -> ! ---
_Exit :: proc(status: int) -> ! ---
getenv :: proc(name: cstring) -> [^]char ---
getenv :: proc(name: cstring) -> cstring ---
quick_exit :: proc(status: int) -> ! ---
system :: proc(cmd: cstring) -> int ---
@@ -132,6 +148,10 @@ aligned_alloc :: #force_inline proc "c" (alignment, size: size_t) -> rawptr {
_aligned_malloc :: proc(size, alignment: size_t) -> rawptr ---
}
return _aligned_malloc(size=size, alignment=alignment)
} else when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
context = runtime.default_context()
data, _ := runtime.mem_alloc_bytes(auto_cast size, auto_cast alignment)
return raw_data(data)
} else {
foreign libc {
aligned_alloc :: proc(alignment, size: size_t) -> rawptr ---
@@ -147,7 +167,10 @@ aligned_free :: #force_inline proc "c" (ptr: rawptr) {
_aligned_free :: proc(ptr: rawptr) ---
}
_aligned_free(ptr)
} else when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
context = runtime.default_context()
runtime.mem_free(ptr)
} else {
free(ptr)
}
}
}
+2 -1
View File
@@ -12,6 +12,7 @@ when ODIN_OS == .Windows {
foreign import libc "system:c"
}
@(default_calling_convention="c")
foreign libc {
// 7.24.2 Copying functions
memcpy :: proc(s1, s2: rawptr, n: size_t) -> rawptr ---
@@ -40,7 +41,7 @@ foreign libc {
strtok :: proc(s1: [^]char, s2: cstring) -> [^]char ---
// 7.24.6 Miscellaneous functions
strerror :: proc(errnum: int) -> [^]char ---
strerror :: proc(errnum: int) -> cstring ---
strlen :: proc(s: cstring) -> size_t ---
}
memset :: proc "c" (s: rawptr, c: int, n: size_t) -> rawptr {
+30 -4
View File
@@ -45,35 +45,61 @@ when ODIN_OS == .Windows {
}
}
when ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .Darwin || ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD || ODIN_OS == .Haiku {
when ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .Darwin || ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD || ODIN_OS == .Haiku || ODIN_OS == .JS {
@(default_calling_convention="c")
foreign libc {
// 7.27.2 Time manipulation functions
clock :: proc() -> clock_t ---
@(link_name=LDIFFTIME)
difftime :: proc(time1, time2: time_t) -> double ---
@(link_name=LMKTIME)
mktime :: proc(timeptr: ^tm) -> time_t ---
@(link_name=LTIME)
time :: proc(timer: ^time_t) -> time_t ---
timespec_get :: proc(ts: ^timespec, base: int) -> int ---
// 7.27.3 Time conversion functions
asctime :: proc(timeptr: ^tm) -> [^]char ---
@(link_name=LCTIME)
ctime :: proc(timer: ^time_t) -> [^]char ---
@(link_name=LGMTIME)
gmtime :: proc(timer: ^time_t) -> ^tm ---
@(link_name=LLOCALTIME)
localtime :: proc(timer: ^time_t) -> ^tm ---
strftime :: proc(s: [^]char, maxsize: size_t, format: cstring, timeptr: ^tm) -> size_t ---
}
when ODIN_OS == .NetBSD {
@(private) LDIFFTIME :: "__difftime50"
@(private) LMKTIME :: "__mktime50"
@(private) LTIME :: "__time50"
@(private) LCTIME :: "__ctime50"
@(private) LGMTIME :: "__gmtime50"
@(private) LLOCALTIME :: "__localtime50"
} else {
@(private) LDIFFTIME :: "difftime"
@(private) LMKTIME :: "mktime"
@(private) LTIME :: "time"
@(private) LCTIME :: "ctime"
@(private) LGMTIME :: "gmtime"
@(private) LLOCALTIME :: "localtime"
}
when ODIN_OS == .OpenBSD {
CLOCKS_PER_SEC :: 100
} else {
CLOCKS_PER_SEC :: 1000000
}
TIME_UTC :: 1
TIME_UTC :: 1
time_t :: distinct i64
time_t :: distinct i64
clock_t :: long
when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD {
clock_t :: distinct int32_t
} else {
clock_t :: distinct long
}
timespec :: struct {
tv_sec: time_t,
+1 -1
View File
@@ -14,7 +14,7 @@ when ODIN_OS == .Windows {
wctrans_t :: distinct wchar_t
wctype_t :: distinct ushort
} else when ODIN_OS == .Linux {
} else when ODIN_OS == .Linux || ODIN_OS == .JS {
wctrans_t :: distinct intptr_t
wctype_t :: distinct ulong
+25 -25
View File
@@ -186,7 +186,7 @@ input_size_from_stream :: proc(z: ^Context_Stream_Input) -> (res: i64, err: Erro
input_size :: proc{input_size_from_memory, input_size_from_stream}
@(optimization_mode="speed")
@(optimization_mode="favor_size")
read_slice_from_memory :: #force_inline proc(z: ^Context_Memory_Input, size: int) -> (res: []u8, err: io.Error) {
#no_bounds_check {
if len(z.input_data) >= size {
@@ -203,7 +203,7 @@ read_slice_from_memory :: #force_inline proc(z: ^Context_Memory_Input, size: int
}
}
@(optimization_mode="speed")
@(optimization_mode="favor_size")
read_slice_from_stream :: #force_inline proc(z: ^Context_Stream_Input, size: int) -> (res: []u8, err: io.Error) {
// TODO: REMOVE ALL USE OF context.temp_allocator here
// there is literally no need for it
@@ -214,13 +214,13 @@ read_slice_from_stream :: #force_inline proc(z: ^Context_Stream_Input, size: int
read_slice :: proc{read_slice_from_memory, read_slice_from_stream}
@(optimization_mode="speed")
@(optimization_mode="favor_size")
read_data :: #force_inline proc(z: ^$C, $T: typeid) -> (res: T, err: io.Error) {
b := read_slice(z, size_of(T)) or_return
return (^T)(&b[0])^, nil
}
@(optimization_mode="speed")
@(optimization_mode="favor_size")
read_u8_from_memory :: #force_inline proc(z: ^Context_Memory_Input) -> (res: u8, err: io.Error) {
#no_bounds_check {
if len(z.input_data) >= 1 {
@@ -232,7 +232,7 @@ read_u8_from_memory :: #force_inline proc(z: ^Context_Memory_Input) -> (res: u8,
return 0, .EOF
}
@(optimization_mode="speed")
@(optimization_mode="favor_size")
read_u8_from_stream :: #force_inline proc(z: ^Context_Stream_Input) -> (res: u8, err: io.Error) {
b := read_slice_from_stream(z, 1) or_return
return b[0], nil
@@ -242,7 +242,7 @@ read_u8 :: proc{read_u8_from_memory, read_u8_from_stream}
// You would typically only use this at the end of Inflate, to drain bits from the code buffer
// preferentially.
@(optimization_mode="speed")
@(optimization_mode="favor_size")
read_u8_prefer_code_buffer_lsb :: #force_inline proc(z: ^$C) -> (res: u8, err: io.Error) {
if z.num_bits >= 8 {
res = u8(read_bits_no_refill_lsb(z, 8))
@@ -257,7 +257,7 @@ read_u8_prefer_code_buffer_lsb :: #force_inline proc(z: ^$C) -> (res: u8, err: i
return
}
@(optimization_mode="speed")
@(optimization_mode="favor_size")
peek_data_from_memory :: #force_inline proc(z: ^Context_Memory_Input, $T: typeid) -> (res: T, err: io.Error) {
size :: size_of(T)
@@ -275,7 +275,7 @@ peek_data_from_memory :: #force_inline proc(z: ^Context_Memory_Input, $T: typeid
}
}
@(optimization_mode="speed")
@(optimization_mode="favor_size")
peek_data_at_offset_from_memory :: #force_inline proc(z: ^Context_Memory_Input, $T: typeid, #any_int offset: int) -> (res: T, err: io.Error) {
size :: size_of(T)
@@ -293,7 +293,7 @@ peek_data_at_offset_from_memory :: #force_inline proc(z: ^Context_Memory_Input,
}
}
@(optimization_mode="speed")
@(optimization_mode="favor_size")
peek_data_from_stream :: #force_inline proc(z: ^Context_Stream_Input, $T: typeid) -> (res: T, err: io.Error) {
size :: size_of(T)
@@ -317,7 +317,7 @@ peek_data_from_stream :: #force_inline proc(z: ^Context_Stream_Input, $T: typeid
return res, .None
}
@(optimization_mode="speed")
@(optimization_mode="favor_size")
peek_data_at_offset_from_stream :: #force_inline proc(z: ^Context_Stream_Input, $T: typeid, #any_int offset: int) -> (res: T, err: io.Error) {
size :: size_of(T)
@@ -352,14 +352,14 @@ peek_data :: proc{peek_data_from_memory, peek_data_from_stream, peek_data_at_off
// Sliding window read back
@(optimization_mode="speed")
@(optimization_mode="favor_size")
peek_back_byte :: #force_inline proc(z: ^$C, offset: i64) -> (res: u8, err: io.Error) {
// Look back into the sliding window.
return z.output.buf[z.bytes_written - offset], .None
}
// Generalized bit reader LSB
@(optimization_mode="speed")
@(optimization_mode="favor_size")
refill_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width := i8(48)) {
refill := u64(width)
b := u64(0)
@@ -385,7 +385,7 @@ refill_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width :=
}
// Generalized bit reader LSB
@(optimization_mode="speed")
@(optimization_mode="favor_size")
refill_lsb_from_stream :: proc(z: ^Context_Stream_Input, width := i8(24)) {
refill := u64(width)
@@ -414,13 +414,13 @@ refill_lsb_from_stream :: proc(z: ^Context_Stream_Input, width := i8(24)) {
refill_lsb :: proc{refill_lsb_from_memory, refill_lsb_from_stream}
@(optimization_mode="speed")
@(optimization_mode="favor_size")
consume_bits_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width: u8) {
z.code_buffer >>= width
z.num_bits -= u64(width)
}
@(optimization_mode="speed")
@(optimization_mode="favor_size")
consume_bits_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Input, width: u8) {
z.code_buffer >>= width
z.num_bits -= u64(width)
@@ -428,7 +428,7 @@ consume_bits_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Input, wid
consume_bits_lsb :: proc{consume_bits_lsb_from_memory, consume_bits_lsb_from_stream}
@(optimization_mode="speed")
@(optimization_mode="favor_size")
peek_bits_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width: u8) -> u32 {
if z.num_bits < u64(width) {
refill_lsb(z)
@@ -436,7 +436,7 @@ peek_bits_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width:
return u32(z.code_buffer &~ (~u64(0) << width))
}
@(optimization_mode="speed")
@(optimization_mode="favor_size")
peek_bits_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Input, width: u8) -> u32 {
if z.num_bits < u64(width) {
refill_lsb(z)
@@ -446,13 +446,13 @@ peek_bits_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Input, width:
peek_bits_lsb :: proc{peek_bits_lsb_from_memory, peek_bits_lsb_from_stream}
@(optimization_mode="speed")
@(optimization_mode="favor_size")
peek_bits_no_refill_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width: u8) -> u32 {
assert(z.num_bits >= u64(width))
return u32(z.code_buffer &~ (~u64(0) << width))
}
@(optimization_mode="speed")
@(optimization_mode="favor_size")
peek_bits_no_refill_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Input, width: u8) -> u32 {
assert(z.num_bits >= u64(width))
return u32(z.code_buffer &~ (~u64(0) << width))
@@ -460,14 +460,14 @@ peek_bits_no_refill_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Inp
peek_bits_no_refill_lsb :: proc{peek_bits_no_refill_lsb_from_memory, peek_bits_no_refill_lsb_from_stream}
@(optimization_mode="speed")
@(optimization_mode="favor_size")
read_bits_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width: u8) -> u32 {
k := #force_inline peek_bits_lsb(z, width)
#force_inline consume_bits_lsb(z, width)
return k
}
@(optimization_mode="speed")
@(optimization_mode="favor_size")
read_bits_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Input, width: u8) -> u32 {
k := peek_bits_lsb(z, width)
consume_bits_lsb(z, width)
@@ -476,14 +476,14 @@ read_bits_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Input, width:
read_bits_lsb :: proc{read_bits_lsb_from_memory, read_bits_lsb_from_stream}
@(optimization_mode="speed")
@(optimization_mode="favor_size")
read_bits_no_refill_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width: u8) -> u32 {
k := #force_inline peek_bits_no_refill_lsb(z, width)
#force_inline consume_bits_lsb(z, width)
return k
}
@(optimization_mode="speed")
@(optimization_mode="favor_size")
read_bits_no_refill_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Input, width: u8) -> u32 {
k := peek_bits_no_refill_lsb(z, width)
consume_bits_lsb(z, width)
@@ -493,14 +493,14 @@ read_bits_no_refill_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Inp
read_bits_no_refill_lsb :: proc{read_bits_no_refill_lsb_from_memory, read_bits_no_refill_lsb_from_stream}
@(optimization_mode="speed")
@(optimization_mode="favor_size")
discard_to_next_byte_lsb_from_memory :: proc(z: ^Context_Memory_Input) {
discard := u8(z.num_bits & 7)
#force_inline consume_bits_lsb(z, discard)
}
@(optimization_mode="speed")
@(optimization_mode="favor_size")
discard_to_next_byte_lsb_from_stream :: proc(z: ^Context_Stream_Input) {
discard := u8(z.num_bits & 7)
consume_bits_lsb(z, discard)
+90
View File
@@ -0,0 +1,90 @@
/*
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license.
List of contributors:
Jeroen van Rijn: Initial implementation.
Ginger Bill: Cosmetic changes.
A small GZIP implementation as an example.
*/
/*
Example:
import "core:bytes"
import "core:os"
import "core:compress"
import "core:fmt"
// Small GZIP file with fextra, fname and fcomment present.
@private
TEST: []u8 = {
0x1f, 0x8b, 0x08, 0x1c, 0xcb, 0x3b, 0x3a, 0x5a,
0x02, 0x03, 0x07, 0x00, 0x61, 0x62, 0x03, 0x00,
0x63, 0x64, 0x65, 0x66, 0x69, 0x6c, 0x65, 0x6e,
0x61, 0x6d, 0x65, 0x00, 0x54, 0x68, 0x69, 0x73,
0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x63, 0x6f,
0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x2b, 0x48,
0xac, 0xcc, 0xc9, 0x4f, 0x4c, 0x01, 0x00, 0x15,
0x6a, 0x2c, 0x42, 0x07, 0x00, 0x00, 0x00,
}
main :: proc() {
// Set up output buffer.
buf := bytes.Buffer{}
stdout :: proc(s: string) {
os.write_string(os.stdout, s)
}
stderr :: proc(s: string) {
os.write_string(os.stderr, s)
}
args := os.args
if len(args) < 2 {
stderr("No input file specified.\n")
err := load(data=TEST, buf=&buf, known_gzip_size=len(TEST))
if err == nil {
stdout("Displaying test vector: ")
stdout(bytes.buffer_to_string(&buf))
stdout("\n")
} else {
fmt.printf("gzip.load returned %v\n", err)
}
bytes.buffer_destroy(&buf)
os.exit(0)
}
// The rest are all files.
args = args[1:]
err: Error
for file in args {
if file == "-" {
// Read from stdin
s := os.stream_from_handle(os.stdin)
ctx := &compress.Context_Stream_Input{
input = s,
}
err = load(ctx, &buf)
} else {
err = load(file, &buf)
}
if err != nil {
if err != E_General.File_Not_Found {
stderr("File not found: ")
stderr(file)
stderr("\n")
os.exit(1)
}
stderr("GZIP returned an error.\n")
bytes.buffer_destroy(&buf)
os.exit(2)
}
stdout(bytes.buffer_to_string(&buf))
}
bytes.buffer_destroy(&buf)
}
*/
package compress_gzip
-89
View File
@@ -1,89 +0,0 @@
//+build ignore
package compress_gzip
/*
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license.
List of contributors:
Jeroen van Rijn: Initial implementation.
Ginger Bill: Cosmetic changes.
A small GZIP implementation as an example.
*/
import "core:bytes"
import "core:os"
import "core:compress"
import "core:fmt"
// Small GZIP file with fextra, fname and fcomment present.
@private
TEST: []u8 = {
0x1f, 0x8b, 0x08, 0x1c, 0xcb, 0x3b, 0x3a, 0x5a,
0x02, 0x03, 0x07, 0x00, 0x61, 0x62, 0x03, 0x00,
0x63, 0x64, 0x65, 0x66, 0x69, 0x6c, 0x65, 0x6e,
0x61, 0x6d, 0x65, 0x00, 0x54, 0x68, 0x69, 0x73,
0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x63, 0x6f,
0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x2b, 0x48,
0xac, 0xcc, 0xc9, 0x4f, 0x4c, 0x01, 0x00, 0x15,
0x6a, 0x2c, 0x42, 0x07, 0x00, 0x00, 0x00,
}
main :: proc() {
// Set up output buffer.
buf := bytes.Buffer{}
stdout :: proc(s: string) {
os.write_string(os.stdout, s)
}
stderr :: proc(s: string) {
os.write_string(os.stderr, s)
}
args := os.args
if len(args) < 2 {
stderr("No input file specified.\n")
err := load(data=TEST, buf=&buf, known_gzip_size=len(TEST))
if err == nil {
stdout("Displaying test vector: ")
stdout(bytes.buffer_to_string(&buf))
stdout("\n")
} else {
fmt.printf("gzip.load returned %v\n", err)
}
bytes.buffer_destroy(&buf)
os.exit(0)
}
// The rest are all files.
args = args[1:]
err: Error
for file in args {
if file == "-" {
// Read from stdin
s := os.stream_from_handle(os.stdin)
ctx := &compress.Context_Stream_Input{
input = s,
}
err = load(ctx, &buf)
} else {
err = load(file, &buf)
}
if err != nil {
if err != E_General.File_Not_Found {
stderr("File not found: ")
stderr(file)
stderr("\n")
os.exit(1)
}
stderr("GZIP returned an error.\n")
bytes.buffer_destroy(&buf)
os.exit(2)
}
stdout(bytes.buffer_to_string(&buf))
}
bytes.buffer_destroy(&buf)
}
+1 -2
View File
@@ -4,7 +4,6 @@
which is an English word model.
*/
// package shoco is an implementation of the shoco short string compressor
package compress_shoco
DEFAULT_MODEL :: Shoco_Model {
@@ -145,4 +144,4 @@ DEFAULT_MODEL :: Shoco_Model {
{ 0xc0000000, 2, 4, { 25, 22, 19, 16, 16, 16, 16, 16 }, { 15, 7, 7, 7, 0, 0, 0, 0 }, 0xe0, 0xc0 },
{ 0xe0000000, 4, 8, { 23, 19, 15, 11, 8, 5, 2, 0 }, { 31, 15, 15, 15, 7, 7, 7, 3 }, 0xf0, 0xe0 },
},
}
}
+2 -2
View File
@@ -8,7 +8,7 @@
An implementation of [shoco](https://github.com/Ed-von-Schleck/shoco) by Christian Schramm.
*/
// package shoco is an implementation of the shoco short string compressor
// package shoco is an implementation of the shoco short string compressor.
package compress_shoco
import "base:intrinsics"
@@ -308,4 +308,4 @@ compress_string :: proc(input: string, model := DEFAULT_MODEL, allocator := cont
resize(&buf, length) or_return
return buf[:length], result
}
compress :: proc{compress_string_to_buffer, compress_string}
compress :: proc{compress_string_to_buffer, compress_string}
+50
View File
@@ -0,0 +1,50 @@
/*
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license.
List of contributors:
Jeroen van Rijn: Initial implementation.
An example of how to use `zlib.inflate`.
*/
/*
Example:
package main
import "core:bytes"
import "core:fmt"
main :: proc() {
ODIN_DEMO := []u8{
120, 218, 101, 144, 65, 110, 131, 48, 16, 69, 215, 246, 41, 190, 44, 69, 73, 32, 148, 182,
75, 75, 28, 32, 251, 46, 217, 88, 238, 0, 86, 192, 32, 219, 36, 170, 170, 172, 122, 137,
238, 122, 197, 30, 161, 70, 162, 20, 81, 203, 139, 25, 191, 255, 191, 60, 51, 40, 125, 81,
53, 33, 144, 15, 156, 155, 110, 232, 93, 128, 208, 189, 35, 89, 117, 65, 112, 222, 41, 99,
33, 37, 6, 215, 235, 195, 17, 239, 156, 197, 170, 118, 170, 131, 44, 32, 82, 164, 72, 240,
253, 245, 249, 129, 12, 185, 224, 76, 105, 61, 118, 99, 171, 66, 239, 38, 193, 35, 103, 85,
172, 66, 127, 33, 139, 24, 244, 235, 141, 49, 204, 223, 76, 208, 205, 204, 166, 7, 173, 60,
97, 159, 238, 37, 214, 41, 105, 129, 167, 5, 102, 27, 152, 173, 97, 178, 129, 73, 129, 231,
5, 230, 27, 152, 175, 225, 52, 192, 127, 243, 170, 157, 149, 18, 121, 142, 115, 109, 227, 122,
64, 87, 114, 111, 161, 49, 182, 6, 181, 158, 162, 226, 206, 167, 27, 215, 246, 48, 56, 99,
67, 117, 16, 47, 13, 45, 35, 151, 98, 231, 75, 1, 173, 90, 61, 101, 146, 71, 136, 244,
170, 218, 145, 176, 123, 45, 173, 56, 113, 134, 191, 51, 219, 78, 235, 95, 28, 249, 253, 7,
159, 150, 133, 125,
}
OUTPUT_SIZE :: 432
buf: bytes.Buffer
// We can pass ", true" to inflate a raw DEFLATE stream instead of a ZLIB wrapped one.
err := inflate(input=ODIN_DEMO, buf=&buf, expected_output_size=OUTPUT_SIZE)
defer bytes.buffer_destroy(&buf)
if err != nil {
fmt.printf("\nError: %v\n", err)
}
s := bytes.buffer_to_string(&buf)
fmt.printf("Input: %v bytes, output (%v bytes):\n%v\n", len(ODIN_DEMO), len(s), s)
assert(len(s) == OUTPUT_SIZE)
}
*/
package compress_zlib
-47
View File
@@ -1,47 +0,0 @@
//+build ignore
package compress_zlib
/*
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license.
List of contributors:
Jeroen van Rijn: Initial implementation.
An example of how to use `zlib.inflate`.
*/
import "core:bytes"
import "core:fmt"
main :: proc() {
ODIN_DEMO := []u8{
120, 218, 101, 144, 65, 110, 131, 48, 16, 69, 215, 246, 41, 190, 44, 69, 73, 32, 148, 182,
75, 75, 28, 32, 251, 46, 217, 88, 238, 0, 86, 192, 32, 219, 36, 170, 170, 172, 122, 137,
238, 122, 197, 30, 161, 70, 162, 20, 81, 203, 139, 25, 191, 255, 191, 60, 51, 40, 125, 81,
53, 33, 144, 15, 156, 155, 110, 232, 93, 128, 208, 189, 35, 89, 117, 65, 112, 222, 41, 99,
33, 37, 6, 215, 235, 195, 17, 239, 156, 197, 170, 118, 170, 131, 44, 32, 82, 164, 72, 240,
253, 245, 249, 129, 12, 185, 224, 76, 105, 61, 118, 99, 171, 66, 239, 38, 193, 35, 103, 85,
172, 66, 127, 33, 139, 24, 244, 235, 141, 49, 204, 223, 76, 208, 205, 204, 166, 7, 173, 60,
97, 159, 238, 37, 214, 41, 105, 129, 167, 5, 102, 27, 152, 173, 97, 178, 129, 73, 129, 231,
5, 230, 27, 152, 175, 225, 52, 192, 127, 243, 170, 157, 149, 18, 121, 142, 115, 109, 227, 122,
64, 87, 114, 111, 161, 49, 182, 6, 181, 158, 162, 226, 206, 167, 27, 215, 246, 48, 56, 99,
67, 117, 16, 47, 13, 45, 35, 151, 98, 231, 75, 1, 173, 90, 61, 101, 146, 71, 136, 244,
170, 218, 145, 176, 123, 45, 173, 56, 113, 134, 191, 51, 219, 78, 235, 95, 28, 249, 253, 7,
159, 150, 133, 125,
}
OUTPUT_SIZE :: 432
buf: bytes.Buffer
// We can pass ", true" to inflate a raw DEFLATE stream instead of a ZLIB wrapped one.
err := inflate(input=ODIN_DEMO, buf=&buf, expected_output_size=OUTPUT_SIZE)
defer bytes.buffer_destroy(&buf)
if err != nil {
fmt.printf("\nError: %v\n", err)
}
s := bytes.buffer_to_string(&buf)
fmt.printf("Input: %v bytes, output (%v bytes):\n%v\n", len(ODIN_DEMO), len(s), s)
assert(len(s) == OUTPUT_SIZE)
}
+16 -21
View File
@@ -1,4 +1,4 @@
//+vet !using-param
#+vet !using-param
package compress_zlib
/*
@@ -12,6 +12,7 @@ package compress_zlib
import "core:compress"
import "base:intrinsics"
import "core:mem"
import "core:io"
import "core:hash"
@@ -120,23 +121,17 @@ Huffman_Table :: struct {
}
// Implementation starts here
@(optimization_mode="speed")
@(optimization_mode="favor_size")
z_bit_reverse :: #force_inline proc(n: u16, bits: u8) -> (r: u16) {
assert(bits <= 16)
// NOTE: Can optimize with llvm.bitreverse.i64 or some bit twiddling
// by reversing all of the bits and masking out the unneeded ones.
r = n
r = ((r & 0xAAAA) >> 1) | ((r & 0x5555) << 1)
r = ((r & 0xCCCC) >> 2) | ((r & 0x3333) << 2)
r = ((r & 0xF0F0) >> 4) | ((r & 0x0F0F) << 4)
r = ((r & 0xFF00) >> 8) | ((r & 0x00FF) << 8)
r = intrinsics.reverse_bits(n)
r >>= (16 - bits)
return
}
@(optimization_mode="speed")
@(optimization_mode="favor_size")
grow_buffer :: proc(buf: ^[dynamic]u8) -> (err: compress.Error) {
/*
That we get here at all means that we didn't pass an expected output size,
@@ -154,7 +149,7 @@ grow_buffer :: proc(buf: ^[dynamic]u8) -> (err: compress.Error) {
TODO: Make these return compress.Error.
*/
@(optimization_mode="speed")
@(optimization_mode="favor_size")
write_byte :: #force_inline proc(z: ^$C, c: u8) -> (err: io.Error) #no_bounds_check {
/*
Resize if needed.
@@ -173,7 +168,7 @@ write_byte :: #force_inline proc(z: ^$C, c: u8) -> (err: io.Error) #no_bounds_ch
return .None
}
@(optimization_mode="speed")
@(optimization_mode="favor_size")
repl_byte :: proc(z: ^$C, count: u16, c: u8) -> (err: io.Error) #no_bounds_check {
/*
TODO(Jeroen): Once we have a magic ring buffer, we can just peek/write into it
@@ -201,7 +196,7 @@ repl_byte :: proc(z: ^$C, count: u16, c: u8) -> (err: io.Error) #no_bounds_check
return .None
}
@(optimization_mode="speed")
@(optimization_mode="favor_size")
repl_bytes :: proc(z: ^$C, count: u16, distance: u16) -> (err: io.Error) {
/*
TODO(Jeroen): Once we have a magic ring buffer, we can just peek/write into it
@@ -234,8 +229,8 @@ allocate_huffman_table :: proc(allocator := context.allocator) -> (z: ^Huffman_T
return new(Huffman_Table, allocator), nil
}
@(optimization_mode="speed")
build_huffman :: proc(z: ^Huffman_Table, code_lengths: []u8) -> (err: Error) {
@(optimization_mode="favor_size")
build_huffman :: #force_no_inline proc(z: ^Huffman_Table, code_lengths: []u8) -> (err: Error) {
sizes: [HUFFMAN_MAX_BITS+1]int
next_code: [HUFFMAN_MAX_BITS+1]int
@@ -293,7 +288,7 @@ build_huffman :: proc(z: ^Huffman_Table, code_lengths: []u8) -> (err: Error) {
return nil
}
@(optimization_mode="speed")
@(optimization_mode="favor_size")
decode_huffman_slowpath :: proc(z: ^$C, t: ^Huffman_Table) -> (r: u16, err: Error) #no_bounds_check {
code := u16(compress.peek_bits_lsb(z,16))
@@ -324,7 +319,7 @@ decode_huffman_slowpath :: proc(z: ^$C, t: ^Huffman_Table) -> (r: u16, err: Erro
return r, nil
}
@(optimization_mode="speed")
@(optimization_mode="favor_size")
decode_huffman :: proc(z: ^$C, t: ^Huffman_Table) -> (r: u16, err: Error) #no_bounds_check {
if z.num_bits < 16 {
if z.num_bits > 63 {
@@ -344,7 +339,7 @@ decode_huffman :: proc(z: ^$C, t: ^Huffman_Table) -> (r: u16, err: Error) #no_bo
return decode_huffman_slowpath(z, t)
}
@(optimization_mode="speed")
@(optimization_mode="favor_size")
parse_huffman_block :: proc(z: ^$C, z_repeat, z_offset: ^Huffman_Table) -> (err: Error) #no_bounds_check {
#no_bounds_check for {
value, e := decode_huffman(z, z_repeat)
@@ -413,7 +408,7 @@ parse_huffman_block :: proc(z: ^$C, z_repeat, z_offset: ^Huffman_Table) -> (err:
}
}
@(optimization_mode="speed")
@(optimization_mode="favor_size")
inflate_from_context :: proc(using ctx: ^compress.Context_Memory_Input, raw := false, expected_output_size := -1, allocator := context.allocator) -> (err: Error) #no_bounds_check {
/*
ctx.output must be a bytes.Buffer for now. We'll add a separate implementation that writes to a stream.
@@ -486,7 +481,7 @@ inflate_from_context :: proc(using ctx: ^compress.Context_Memory_Input, raw := f
// TODO: Check alignment of reserve/resize.
@(optimization_mode="speed")
@(optimization_mode="favor_size")
inflate_raw :: proc(z: ^$C, expected_output_size := -1, allocator := context.allocator) -> (err: Error) #no_bounds_check {
context.allocator = allocator
expected_output_size := expected_output_size
@@ -670,4 +665,4 @@ inflate_from_byte_array_raw :: proc(input: []u8, buf: ^bytes.Buffer, raw := fals
return inflate_raw(&ctx, expected_output_size=expected_output_size)
}
inflate :: proc{inflate_from_context, inflate_from_byte_array}
inflate :: proc{inflate_from_context, inflate_from_byte_array}
+97 -22
View File
@@ -1,5 +1,6 @@
package container_dynamic_bit_array
import "base:builtin"
import "base:intrinsics"
import "core:mem"
@@ -18,7 +19,7 @@ NUM_BITS :: 64
Bit_Array :: struct {
bits: [dynamic]u64,
bias: int,
max_index: int,
length: int,
free_pointer: bool,
}
@@ -52,9 +53,9 @@ Returns:
*/
iterate_by_all :: proc (it: ^Bit_Array_Iterator) -> (set: bool, index: int, ok: bool) {
index = it.word_idx * NUM_BITS + int(it.bit_idx) + it.array.bias
if index > it.array.max_index { return false, 0, false }
if index >= it.array.length + it.array.bias { return false, 0, false }
word := it.array.bits[it.word_idx] if len(it.array.bits) > it.word_idx else 0
word := it.array.bits[it.word_idx] if builtin.len(it.array.bits) > it.word_idx else 0
set = (word >> it.bit_idx & 1) == 1
it.bit_idx += 1
@@ -106,22 +107,22 @@ Returns:
*/
@(private="file")
iterate_internal_ :: proc (it: ^Bit_Array_Iterator, $ITERATE_SET_BITS: bool) -> (index: int, ok: bool) {
word := it.array.bits[it.word_idx] if len(it.array.bits) > it.word_idx else 0
word := it.array.bits[it.word_idx] if builtin.len(it.array.bits) > it.word_idx else 0
when ! ITERATE_SET_BITS { word = ~word }
// If the word is empty or we have already gone over all the bits in it,
// b.bit_idx is greater than the index of any set bit in the word,
// meaning that word >> b.bit_idx == 0.
for it.word_idx < len(it.array.bits) && word >> it.bit_idx == 0 {
for it.word_idx < builtin.len(it.array.bits) && word >> it.bit_idx == 0 {
it.word_idx += 1
it.bit_idx = 0
word = it.array.bits[it.word_idx] if len(it.array.bits) > it.word_idx else 0
word = it.array.bits[it.word_idx] if builtin.len(it.array.bits) > it.word_idx else 0
when ! ITERATE_SET_BITS { word = ~word }
}
// If we are iterating the set bits, reaching the end of the array means we have no more bits to check
when ITERATE_SET_BITS {
if it.word_idx >= len(it.array.bits) {
if it.word_idx >= builtin.len(it.array.bits) {
return 0, false
}
}
@@ -135,7 +136,7 @@ iterate_internal_ :: proc (it: ^Bit_Array_Iterator, $ITERATE_SET_BITS: bool) ->
it.bit_idx = 0
it.word_idx += 1
}
return index, index <= it.array.max_index
return index, index < it.array.length + it.array.bias
}
/*
Gets the state of a bit in the bit-array
@@ -160,7 +161,7 @@ get :: proc(ba: ^Bit_Array, #any_int index: uint) -> (res: bool, ok: bool) #opti
If we `get` a bit that doesn't fit in the Bit Array, it's naturally `false`.
This early-out prevents unnecessary resizing.
*/
if leg_index + 1 > len(ba.bits) { return false, true }
if leg_index + 1 > builtin.len(ba.bits) { return false, true }
val := u64(1 << uint(bit_index))
res = ba.bits[leg_index] & val == val
@@ -208,7 +209,7 @@ set :: proc(ba: ^Bit_Array, #any_int index: uint, set_to: bool = true, allocator
resize_if_needed(ba, leg_index) or_return
ba.max_index = max(idx, ba.max_index)
ba.length = max(1 + idx, ba.length)
if set_to {
ba.bits[leg_index] |= 1 << uint(bit_index)
@@ -258,9 +259,13 @@ Inputs:
unsafe_unset :: proc(b: ^Bit_Array, bit: int) #no_bounds_check {
b.bits[bit >> INDEX_SHIFT] &~= 1 << uint(bit & INDEX_MASK)
}
/*
A helper function to create a Bit Array with optional bias, in case your smallest index is non-zero (including negative).
The range of bits created by this procedure is `min_index..<max_index`, and the
array will be able to expand beyond `max_index` if needed.
*Allocates (`new(Bit_Array) & make(ba.bits)`)*
Inputs:
@@ -272,22 +277,50 @@ Returns:
- ba: Allocates a bit_Array, backing data is set to `max-min / 64` indices, rounded up (eg 65 - 0 allocates for [2]u64).
*/
create :: proc(max_index: int, min_index: int = 0, allocator := context.allocator) -> (res: ^Bit_Array, ok: bool) #optional_ok {
context.allocator = allocator
size_in_bits := max_index - min_index
if size_in_bits < 1 { return {}, false }
if size_in_bits < 0 { return {}, false }
legs := size_in_bits >> INDEX_SHIFT
if size_in_bits & INDEX_MASK > 0 {legs+=1}
bits, err := make([dynamic]u64, legs)
ok = err == mem.Allocator_Error.None
res = new(Bit_Array)
res.bits = bits
res.bias = min_index
res.max_index = max_index
res = new(Bit_Array, allocator)
ok = init(res, max_index, min_index, allocator)
res.free_pointer = true
if !ok { free(res, allocator) }
return
}
/*
A helper function to initialize a Bit Array with optional bias, in case your smallest index is non-zero (including negative).
The range of bits created by this procedure is `min_index..<max_index`, and the
array will be able to expand beyond `max_index` if needed.
*Allocates (`make(ba.bits)`)*
Inputs:
- max_index: maximum starting index
- min_index: minimum starting index (used as a bias)
- allocator: (default is context.allocator)
*/
init :: proc(res: ^Bit_Array, max_index: int, min_index: int = 0, allocator := context.allocator) -> (ok: bool) {
size_in_bits := max_index - min_index
if size_in_bits < 0 { return false }
legs := size_in_bits >> INDEX_SHIFT
if size_in_bits & INDEX_MASK > 0 { legs += 1 }
bits, err := make([dynamic]u64, legs, allocator)
ok = err == nil
res.bits = bits
res.bias = min_index
res.length = max_index - min_index
res.free_pointer = false
return
}
/*
Sets all values in the Bit_Array to zero.
@@ -299,6 +332,48 @@ clear :: proc(ba: ^Bit_Array) {
mem.zero_slice(ba.bits[:])
}
/*
Gets the length of set and unset valid bits in the Bit_Array.
Inputs:
- ba: The target Bit_Array
Returns:
- length: The length of valid bits.
*/
len :: proc(ba: ^Bit_Array) -> (length: int) {
if ba == nil { return }
return ba.length
}
/*
Shrinks the Bit_Array's backing storage to the smallest possible size.
Inputs:
- ba: The target Bit_Array
*/
shrink :: proc(ba: ^Bit_Array) #no_bounds_check {
if ba == nil { return }
legs_needed := builtin.len(ba.bits)
for i := legs_needed - 1; i >= 0; i -= 1 {
if ba.bits[i] == 0 {
legs_needed -= 1
} else {
break
}
}
if legs_needed == builtin.len(ba.bits) {
return
}
ba.length = 0
if legs_needed > 0 {
if legs_needed > 1 {
ba.length = (legs_needed - 1) * NUM_BITS
}
ba.length += NUM_BITS - int(intrinsics.count_leading_zeros(ba.bits[legs_needed - 1]))
}
resize(&ba.bits, legs_needed)
builtin.shrink(&ba.bits)
}
/*
Deallocates the Bit_Array and its backing storage
Inputs:
@@ -321,8 +396,8 @@ resize_if_needed :: proc(ba: ^Bit_Array, legs: int, allocator := context.allocat
context.allocator = allocator
if legs + 1 > len(ba.bits) {
if legs + 1 > builtin.len(ba.bits) {
resize(&ba.bits, legs + 1)
}
return len(ba.bits) > legs
return builtin.len(ba.bits) > legs
}
+4 -4
View File
@@ -1,8 +1,8 @@
/*
The Bit Array can be used in several ways:
- By default you don't need to instantiate a Bit Array:
By default you don't need to instantiate a Bit Array.
Example:
package test
import "core:fmt"
@@ -22,8 +22,8 @@ The Bit Array can be used in several ways:
destroy(&bits)
}
- A Bit Array can optionally allow for negative indices, if the minimum value was given during creation:
A Bit Array can optionally allow for negative indices, if the minimum value was given during creation.
Example:
package test
import "core:fmt"
+49
View File
@@ -0,0 +1,49 @@
/*
Package list implements an intrusive doubly-linked list.
An intrusive container requires a `Node` to be embedded in your own structure, like this.
Example:
My_String :: struct {
node: list.Node,
value: string,
}
Embedding the members of a `list.Node` in your structure with the `using` keyword is also allowed.
Example:
My_String :: struct {
using node: list.Node,
value: string,
}
Here is a full example.
Example:
package test
import "core:fmt"
import "core:container/intrusive/list"
main :: proc() {
l: list.List
one := My_String{value="Hello"}
two := My_String{value="World"}
list.push_back(&l, &one.node)
list.push_back(&l, &two.node)
iter := list.iterator_head(l, My_String, "node")
for s in list.iterate_next(&iter) {
fmt.println(s.value)
}
}
My_String :: struct {
node: list.Node,
value: string,
}
Output:
Hello
World
*/
package container_intrusive_list
@@ -18,11 +18,18 @@ List :: struct {
tail: ^Node,
}
// The list link you must include in your own structure.
Node :: struct {
prev, next: ^Node,
}
/*
Inserts a new element at the front of the list with O(1) time complexity.
**Inputs**
- list: The container list
- node: The node member of the user-defined element structure
*/
push_front :: proc "contextless" (list: ^List, node: ^Node) {
if list.head != nil {
list.head.prev = node
@@ -33,7 +40,13 @@ push_front :: proc "contextless" (list: ^List, node: ^Node) {
node.prev, node.next = nil, nil
}
}
/*
Inserts a new element at the back of the list with O(1) time complexity.
**Inputs**
- list: The container list
- node: The node member of the user-defined element structure
*/
push_back :: proc "contextless" (list: ^List, node: ^Node) {
if list.tail != nil {
list.tail.next = node
@@ -45,6 +58,13 @@ push_back :: proc "contextless" (list: ^List, node: ^Node) {
}
}
/*
Removes an element from a list with O(1) time complexity.
**Inputs**
- list: The container list
- node: The node member of the user-defined element structure to be removed
*/
remove :: proc "contextless" (list: ^List, node: ^Node) {
if node != nil {
if node.next != nil {
@@ -61,7 +81,13 @@ remove :: proc "contextless" (list: ^List, node: ^Node) {
}
}
}
/*
Removes from the given list all elements that satisfy a condition with O(N) time complexity.
**Inputs**
- list: The container list
- to_erase: The condition procedure. It should return `true` if a node should be removed, `false` otherwise
*/
remove_by_proc :: proc(list: ^List, to_erase: proc(^Node) -> bool) {
for node := list.head; node != nil; {
next := node.next
@@ -82,7 +108,13 @@ remove_by_proc :: proc(list: ^List, to_erase: proc(^Node) -> bool) {
node = next
}
}
/*
Removes from the given list all elements that satisfy a condition with O(N) time complexity.
**Inputs**
- list: The container list
- to_erase: The _contextless_ condition procedure. It should return `true` if a node should be removed, `false` otherwise
*/
remove_by_proc_contextless :: proc(list: ^List, to_erase: proc "contextless" (^Node) -> bool) {
for node := list.head; node != nil; {
next := node.next
@@ -104,12 +136,26 @@ remove_by_proc_contextless :: proc(list: ^List, to_erase: proc "contextless" (^N
}
}
/*
Checks whether the given list does not contain any element.
**Inputs**
- list: The container list
**Returns** `true` if `list` is empty, `false` otherwise
*/
is_empty :: proc "contextless" (list: ^List) -> bool {
return list.head == nil
}
/*
Removes and returns the element at the front of the list with O(1) time complexity.
**Inputs**
- list: The container list
**Returns** The node member of the user-defined element structure, or `nil` if the list is empty
*/
pop_front :: proc "contextless" (list: ^List) -> ^Node {
link := list.head
if link == nil {
@@ -130,6 +176,14 @@ pop_front :: proc "contextless" (list: ^List) -> ^Node {
return link
}
/*
Removes and returns the element at the back of the list with O(1) time complexity.
**Inputs**
- list: The container list
**Returns** The node member of the user-defined element structure, or `nil` if the list is empty
*/
pop_back :: proc "contextless" (list: ^List) -> ^Node {
link := list.tail
if link == nil {
@@ -151,29 +205,102 @@ pop_back :: proc "contextless" (list: ^List) -> ^Node {
}
Iterator :: struct($T: typeid) {
curr: ^Node,
offset: uintptr,
}
/*
Creates an iterator pointing at the head of the given list. For an example, see `iterate_next`.
**Inputs**
- list: The container list
- T: The type of the list's elements
- field_name: The name of the node field in the `T` structure
**Returns** An iterator pointing at the head of `list`
*/
iterator_head :: proc "contextless" (list: List, $T: typeid, $field_name: string) -> Iterator(T)
where intrinsics.type_has_field(T, field_name),
intrinsics.type_field_type(T, field_name) == Node {
return {list.head, offset_of_by_string(T, field_name)}
}
/*
Creates an iterator pointing at the tail of the given list. For an example, see `iterate_prev`.
**Inputs**
- list: The container list
- T: The type of the list's elements
- field_name: The name of the node field in the `T` structure
**Returns** An iterator pointing at the tail of `list`
*/
iterator_tail :: proc "contextless" (list: List, $T: typeid, $field_name: string) -> Iterator(T)
where intrinsics.type_has_field(T, field_name),
intrinsics.type_field_type(T, field_name) == Node {
return {list.tail, offset_of_by_string(T, field_name)}
}
/*
Creates an iterator pointing at the specified node of a list.
**Inputs**
- node: a list node
- T: The type of the list's elements
- field_name: The name of the node field in the `T` structure
**Returns** An iterator pointing at `node`
*/
iterator_from_node :: proc "contextless" (node: ^Node, $T: typeid, $field_name: string) -> Iterator(T)
where intrinsics.type_has_field(T, field_name),
intrinsics.type_field_type(T, field_name) == Node {
return {node, offset_of_by_string(T, field_name)}
}
/*
Retrieves the next element in a list and advances the iterator.
**Inputs**
- it: The iterator
**Returns**
- ptr: The next list element
- ok: `true` if the element is valid (the iterator could advance), `false` otherwise
Example:
import "core:fmt"
import "core:container/intrusive/list"
iterate_next_example :: proc() {
l: list.List
one := My_Struct{value=1}
two := My_Struct{value=2}
list.push_back(&l, &one.node)
list.push_back(&l, &two.node)
it := list.iterator_head(l, My_Struct, "node")
for num in list.iterate_next(&it) {
fmt.println(num.value)
}
}
My_Struct :: struct {
node : list.Node,
value: int,
}
Output:
1
2
*/
iterate_next :: proc "contextless" (it: ^Iterator($T)) -> (ptr: ^T, ok: bool) {
node := it.curr
if node == nil {
@@ -183,7 +310,47 @@ iterate_next :: proc "contextless" (it: ^Iterator($T)) -> (ptr: ^T, ok: bool) {
return (^T)(uintptr(node) - it.offset), true
}
/*
Retrieves the previous element in a list and recede the iterator.
**Inputs**
- it: The iterator
**Returns**
- ptr: The previous list element
- ok: `true` if the element is valid (the iterator could recede), `false` otherwise
Example:
import "core:fmt"
import "core:container/intrusive/list"
iterate_next_example :: proc() {
l: list.List
one := My_Struct{value=1}
two := My_Struct{value=2}
list.push_back(&l, &one.node)
list.push_back(&l, &two.node)
it := list.iterator_tail(l, My_Struct, "node")
for num in list.iterate_prev(&it) {
fmt.println(num.value)
}
}
My_Struct :: struct {
node : list.Node,
value: int,
}
Output:
2
1
*/
iterate_prev :: proc "contextless" (it: ^Iterator($T)) -> (ptr: ^T, ok: bool) {
node := it.curr
if node == nil {
@@ -192,4 +359,4 @@ iterate_prev :: proc "contextless" (it: ^Iterator($T)) -> (ptr: ^T, ok: bool) {
it.curr = node.prev
return (^T)(uintptr(node) - it.offset), true
}
}
+2 -2
View File
@@ -95,11 +95,11 @@ front_ptr :: proc(q: ^$Q/Queue($T)) -> ^T {
}
back :: proc(q: ^$Q/Queue($T)) -> T {
idx := (q.offset+uint(q.len))%builtin.len(q.data)
idx := (q.offset+uint(q.len - 1))%builtin.len(q.data)
return q.data[idx]
}
back_ptr :: proc(q: ^$Q/Queue($T)) -> ^T {
idx := (q.offset+uint(q.len))%builtin.len(q.data)
idx := (q.offset+uint(q.len - 1))%builtin.len(q.data)
return &q.data[idx]
}
+7 -3
View File
@@ -139,9 +139,13 @@ clear :: proc "contextless" (a: ^$A/Small_Array($N, $T)) {
resize(a, 0)
}
push_back_elems :: proc "contextless" (a: ^$A/Small_Array($N, $T), items: ..T) {
n := copy(a.data[a.len:], items[:])
a.len += n
push_back_elems :: proc "contextless" (a: ^$A/Small_Array($N, $T), items: ..T) -> bool {
if a.len + builtin.len(items) <= cap(a^) {
n := copy(a.data[a.len:], items[:])
a.len += n
return true
}
return false
}
inject_at :: proc "contextless" (a: ^$A/Small_Array($N, $T), item: T, index: int) -> bool #no_bounds_check {
+2 -12
View File
@@ -7,9 +7,8 @@ STRIDE :: 4
// Context is a keyed AES (ECB) instance.
Context :: struct {
_sk_exp: [120]u64,
_num_rounds: int,
_is_initialized: bool,
_sk_exp: [120]u64,
_num_rounds: int,
}
// init initializes a context for AES with the provided key.
@@ -18,13 +17,10 @@ init :: proc(ctx: ^Context, key: []byte) {
ctx._num_rounds = keysched(skey[:], key)
skey_expand(ctx._sk_exp[:], skey[:], ctx._num_rounds)
ctx._is_initialized = true
}
// encrypt_block sets `dst` to `AES-ECB-Encrypt(src)`.
encrypt_block :: proc(ctx: ^Context, dst, src: []byte) {
assert(ctx._is_initialized)
q: [8]u64
load_blockx1(&q, src)
_encrypt(&q, ctx._sk_exp[:], ctx._num_rounds)
@@ -33,8 +29,6 @@ encrypt_block :: proc(ctx: ^Context, dst, src: []byte) {
// encrypt_block sets `dst` to `AES-ECB-Decrypt(src)`.
decrypt_block :: proc(ctx: ^Context, dst, src: []byte) {
assert(ctx._is_initialized)
q: [8]u64
load_blockx1(&q, src)
_decrypt(&q, ctx._sk_exp[:], ctx._num_rounds)
@@ -43,8 +37,6 @@ decrypt_block :: proc(ctx: ^Context, dst, src: []byte) {
// encrypt_blocks sets `dst` to `AES-ECB-Encrypt(src[0], .. src[n])`.
encrypt_blocks :: proc(ctx: ^Context, dst, src: [][]byte) {
assert(ctx._is_initialized)
q: [8]u64 = ---
src, dst := src, dst
@@ -67,8 +59,6 @@ encrypt_blocks :: proc(ctx: ^Context, dst, src: [][]byte) {
// decrypt_blocks sets dst to `AES-ECB-Decrypt(src[0], .. src[n])`.
decrypt_blocks :: proc(ctx: ^Context, dst, src: [][]byte) {
assert(ctx._is_initialized)
q: [8]u64 = ---
src, dst := src, dst
+1 -1
View File
@@ -80,8 +80,8 @@ ghash :: proc "contextless" (dst, key, data: []byte) {
h2 := h0 ~ h1
h2r := h0r ~ h1r
src: []byte
for l > 0 {
src: []byte = ---
if l >= _aes.GHASH_BLOCK_SIZE {
src = buf
buf = buf[_aes.GHASH_BLOCK_SIZE:]
+43
View File
@@ -0,0 +1,43 @@
#+build amd64
package aes_hw_intel
import "core:sys/info"
// is_supported returns true iff hardware accelerated AES
// is supported.
is_supported :: proc "contextless" () -> bool {
features, ok := info.cpu_features.?
if !ok {
return false
}
// Note: Everything with AES-NI and PCLMULQDQ has support for
// the required SSE extxtensions.
req_features :: info.CPU_Features{
.sse2,
.ssse3,
.sse41,
.aes,
.pclmulqdq,
}
return features >= req_features
}
// Context is a keyed AES (ECB) instance.
Context :: struct {
// Note: The ideal thing to do is for the expanded round keys to be
// arrays of `__m128i`, however that implies alignment (or using AVX).
//
// All the people using e-waste processors that don't support an
// insturction set that has been around for over 10 years are why
// we can't have nice things.
_sk_exp_enc: [15][16]byte,
_sk_exp_dec: [15][16]byte,
_num_rounds: int,
}
// init initializes a context for AES with the provided key.
init :: proc(ctx: ^Context, key: []byte) {
keysched(ctx, key)
}
+277
View File
@@ -0,0 +1,277 @@
// Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHORS “AS IS” AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#+build amd64
package aes_hw_intel
import "base:intrinsics"
import "core:crypto/_aes"
import "core:simd/x86"
@(private = "file")
GHASH_STRIDE_HW :: 4
@(private = "file")
GHASH_STRIDE_BYTES_HW :: GHASH_STRIDE_HW * _aes.GHASH_BLOCK_SIZE
// GHASH is defined over elements of GF(2^128) with "full little-endian"
// representation: leftmost byte is least significant, and, within each
// byte, leftmost _bit_ is least significant. The natural ordering in
// x86 is "mixed little-endian": bytes are ordered from least to most
// significant, but bits within a byte are in most-to-least significant
// order. Going to full little-endian representation would require
// reversing bits within each byte, which is doable but expensive.
//
// Instead, we go to full big-endian representation, by swapping bytes
// around, which is done with a single _mm_shuffle_epi8() opcode (it
// comes with SSSE3; all CPU that offer pclmulqdq also have SSSE3). We
// can use a full big-endian representation because in a carryless
// multiplication, we have a nice bit reversal property:
//
// rev_128(x) * rev_128(y) = rev_255(x * y)
//
// So by using full big-endian, we still get the right result, except
// that it is right-shifted by 1 bit. The left-shift is relatively
// inexpensive, and it can be mutualised.
//
// Since SSE2 opcodes do not have facilities for shitfting full 128-bit
// values with bit precision, we have to break down values into 64-bit
// chunks. We number chunks from 0 to 3 in left to right order.
@(private = "file")
_BYTESWAP_INDEX: x86.__m128i : { 0x08090a0b0c0d0e0f, 0x0001020304050607 }
@(private = "file", require_results, enable_target_feature = "sse2,ssse3")
byteswap :: #force_inline proc "contextless" (x: x86.__m128i) -> x86.__m128i {
return x86._mm_shuffle_epi8(x, _BYTESWAP_INDEX)
}
// From a 128-bit value kw, compute kx as the XOR of the two 64-bit
// halves of kw (into the right half of kx; left half is unspecified),
// and return kx.
@(private = "file", require_results, enable_target_feature = "sse2")
bk :: #force_inline proc "contextless" (kw: x86.__m128i) -> x86.__m128i {
return x86._mm_xor_si128(kw, x86._mm_shuffle_epi32(kw, 0x0e))
}
// Combine two 64-bit values (k0:k1) into a 128-bit (kw) value and
// the XOR of the two values (kx), and return (kw, kx).
@(private = "file", enable_target_feature = "sse2")
pbk :: #force_inline proc "contextless" (k0, k1: x86.__m128i) -> (x86.__m128i, x86.__m128i) {
kw := x86._mm_unpacklo_epi64(k1, k0)
kx := x86._mm_xor_si128(k0, k1)
return kw, kx
}
// Left-shift by 1 bit a 256-bit value (in four 64-bit words).
@(private = "file", require_results, enable_target_feature = "sse2")
sl_256 :: #force_inline proc "contextless" (x0, x1, x2, x3: x86.__m128i) -> (x86.__m128i, x86.__m128i, x86.__m128i, x86.__m128i) {
x0, x1, x2, x3 := x0, x1, x2, x3
x0 = x86._mm_or_si128(x86._mm_slli_epi64(x0, 1), x86._mm_srli_epi64(x1, 63))
x1 = x86._mm_or_si128(x86._mm_slli_epi64(x1, 1), x86._mm_srli_epi64(x2, 63))
x2 = x86._mm_or_si128(x86._mm_slli_epi64(x2, 1), x86._mm_srli_epi64(x3, 63))
x3 = x86._mm_slli_epi64(x3, 1)
return x0, x1, x2, x3
}
// Perform reduction in GF(2^128).
@(private = "file", require_results, enable_target_feature = "sse2")
reduce_f128 :: #force_inline proc "contextless" (x0, x1, x2, x3: x86.__m128i) -> (x86.__m128i, x86.__m128i) {
x0, x1, x2 := x0, x1, x2
x1 = x86._mm_xor_si128(
x1,
x86._mm_xor_si128(
x86._mm_xor_si128(
x3,
x86._mm_srli_epi64(x3, 1)),
x86._mm_xor_si128(
x86._mm_srli_epi64(x3, 2),
x86._mm_srli_epi64(x3, 7))))
x2 = x86._mm_xor_si128(
x86._mm_xor_si128(
x2,
x86._mm_slli_epi64(x3, 63)),
x86._mm_xor_si128(
x86._mm_slli_epi64(x3, 62),
x86._mm_slli_epi64(x3, 57)))
x0 = x86._mm_xor_si128(
x0,
x86._mm_xor_si128(
x86._mm_xor_si128(
x2,
x86._mm_srli_epi64(x2, 1)),
x86._mm_xor_si128(
x86._mm_srli_epi64(x2, 2),
x86._mm_srli_epi64(x2, 7))))
x1 = x86._mm_xor_si128(
x86._mm_xor_si128(
x1,
x86._mm_slli_epi64(x2, 63)),
x86._mm_xor_si128(
x86._mm_slli_epi64(x2, 62),
x86._mm_slli_epi64(x2, 57)))
return x0, x1
}
// Square value kw in GF(2^128) into (dw,dx).
@(private = "file", require_results, enable_target_feature = "sse2,pclmul")
square_f128 :: #force_inline proc "contextless" (kw: x86.__m128i) -> (x86.__m128i, x86.__m128i) {
z1 := x86._mm_clmulepi64_si128(kw, kw, 0x11)
z3 := x86._mm_clmulepi64_si128(kw, kw, 0x00)
z0 := x86._mm_shuffle_epi32(z1, 0x0E)
z2 := x86._mm_shuffle_epi32(z3, 0x0E)
z0, z1, z2, z3 = sl_256(z0, z1, z2, z3)
z0, z1 = reduce_f128(z0, z1, z2, z3)
return pbk(z0, z1)
}
// ghash calculates the GHASH of data, with the key `key`, and input `dst`
// and `data`, and stores the resulting digest in `dst`.
//
// Note: `dst` is both an input and an output, to support easy implementation
// of GCM.
@(enable_target_feature = "sse2,ssse3,pclmul")
ghash :: proc "contextless" (dst, key, data: []byte) #no_bounds_check {
if len(dst) != _aes.GHASH_BLOCK_SIZE || len(key) != _aes.GHASH_BLOCK_SIZE {
intrinsics.trap()
}
// Note: BearSSL opts to copy the remainder into a zero-filled
// 64-byte buffer. We do something slightly more simple.
// Load key and dst (h and y).
yw := intrinsics.unaligned_load((^x86.__m128i)(raw_data(dst)))
h1w := intrinsics.unaligned_load((^x86.__m128i)(raw_data(key)))
yw = byteswap(yw)
h1w = byteswap(h1w)
h1x := bk(h1w)
// Process 4 blocks at a time
buf := data
l := len(buf)
if l >= GHASH_STRIDE_BYTES_HW {
// Compute h2 = h^2
h2w, h2x := square_f128(h1w)
// Compute h3 = h^3 = h*(h^2)
t1 := x86._mm_clmulepi64_si128(h1w, h2w, 0x11)
t3 := x86._mm_clmulepi64_si128(h1w, h2w, 0x00)
t2 := x86._mm_xor_si128(
x86._mm_clmulepi64_si128(h1x, h2x, 0x00),
x86._mm_xor_si128(t1, t3))
t0 := x86._mm_shuffle_epi32(t1, 0x0E)
t1 = x86._mm_xor_si128(t1, x86._mm_shuffle_epi32(t2, 0x0E))
t2 = x86._mm_xor_si128(t2, x86._mm_shuffle_epi32(t3, 0x0E))
t0, t1, t2, t3 = sl_256(t0, t1, t2, t3)
t0, t1 = reduce_f128(t0, t1, t2, t3)
h3w, h3x := pbk(t0, t1)
// Compute h4 = h^4 = (h^2)^2
h4w, h4x := square_f128(h2w)
for l >= GHASH_STRIDE_BYTES_HW {
aw0 := intrinsics.unaligned_load((^x86.__m128i)(raw_data(buf)))
aw1 := intrinsics.unaligned_load((^x86.__m128i)(raw_data(buf[16:])))
aw2 := intrinsics.unaligned_load((^x86.__m128i)(raw_data(buf[32:])))
aw3 := intrinsics.unaligned_load((^x86.__m128i)(raw_data(buf[48:])))
aw0 = byteswap(aw0)
aw1 = byteswap(aw1)
aw2 = byteswap(aw2)
aw3 = byteswap(aw3)
buf, l = buf[GHASH_STRIDE_BYTES_HW:], l - GHASH_STRIDE_BYTES_HW
aw0 = x86._mm_xor_si128(aw0, yw)
ax1 := bk(aw1)
ax2 := bk(aw2)
ax3 := bk(aw3)
ax0 := bk(aw0)
t1 = x86._mm_xor_si128(
x86._mm_xor_si128(
x86._mm_clmulepi64_si128(aw0, h4w, 0x11),
x86._mm_clmulepi64_si128(aw1, h3w, 0x11)),
x86._mm_xor_si128(
x86._mm_clmulepi64_si128(aw2, h2w, 0x11),
x86._mm_clmulepi64_si128(aw3, h1w, 0x11)))
t3 = x86._mm_xor_si128(
x86._mm_xor_si128(
x86._mm_clmulepi64_si128(aw0, h4w, 0x00),
x86._mm_clmulepi64_si128(aw1, h3w, 0x00)),
x86._mm_xor_si128(
x86._mm_clmulepi64_si128(aw2, h2w, 0x00),
x86._mm_clmulepi64_si128(aw3, h1w, 0x00)))
t2 = x86._mm_xor_si128(
x86._mm_xor_si128(
x86._mm_clmulepi64_si128(ax0, h4x, 0x00),
x86._mm_clmulepi64_si128(ax1, h3x, 0x00)),
x86._mm_xor_si128(
x86._mm_clmulepi64_si128(ax2, h2x, 0x00),
x86._mm_clmulepi64_si128(ax3, h1x, 0x00)))
t2 = x86._mm_xor_si128(t2, x86._mm_xor_si128(t1, t3))
t0 = x86._mm_shuffle_epi32(t1, 0x0E)
t1 = x86._mm_xor_si128(t1, x86._mm_shuffle_epi32(t2, 0x0E))
t2 = x86._mm_xor_si128(t2, x86._mm_shuffle_epi32(t3, 0x0E))
t0, t1, t2, t3 = sl_256(t0, t1, t2, t3)
t0, t1 = reduce_f128(t0, t1, t2, t3)
yw = x86._mm_unpacklo_epi64(t1, t0)
}
}
// Process 1 block at a time
for l > 0 {
src: []byte = ---
if l >= _aes.GHASH_BLOCK_SIZE {
src = buf
buf = buf[_aes.GHASH_BLOCK_SIZE:]
l -= _aes.GHASH_BLOCK_SIZE
} else {
tmp: [_aes.GHASH_BLOCK_SIZE]byte
copy(tmp[:], buf)
src = tmp[:]
l = 0
}
aw := intrinsics.unaligned_load((^x86.__m128i)(raw_data(src)))
aw = byteswap(aw)
aw = x86._mm_xor_si128(aw, yw)
ax := bk(aw)
t1 := x86._mm_clmulepi64_si128(aw, h1w, 0x11)
t3 := x86._mm_clmulepi64_si128(aw, h1w, 0x00)
t2 := x86._mm_clmulepi64_si128(ax, h1x, 0x00)
t2 = x86._mm_xor_si128(t2, x86._mm_xor_si128(t1, t3))
t0 := x86._mm_shuffle_epi32(t1, 0x0E)
t1 = x86._mm_xor_si128(t1, x86._mm_shuffle_epi32(t2, 0x0E))
t2 = x86._mm_xor_si128(t2, x86._mm_shuffle_epi32(t3, 0x0E))
t0, t1, t2, t3 = sl_256(t0, t1, t2, t3)
t0, t1 = reduce_f128(t0, t1, t2, t3)
yw = x86._mm_unpacklo_epi64(t1, t0)
}
// Write back the hash (dst, aka y)
yw = byteswap(yw)
intrinsics.unaligned_store((^x86.__m128i)(raw_data(dst)), yw)
}
@@ -0,0 +1,178 @@
// Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHORS “AS IS” AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#+build amd64
package aes_hw_intel
import "base:intrinsics"
import "core:crypto/_aes"
import "core:mem"
import "core:simd/x86"
// Intel AES-NI based implementation. Inspiration taken from BearSSL.
//
// Note: This assumes that the SROA optimization pass is enabled to be
// anything resembling performat otherwise, LLVM will not elide a massive
// number of redundant loads/stores it generates for every intrinsic call.
@(private = "file", require_results, enable_target_feature = "sse2")
expand_step128 :: #force_inline proc(k1, k2: x86.__m128i) -> x86.__m128i {
k1, k2 := k1, k2
k2 = x86._mm_shuffle_epi32(k2, 0xff)
k1 = x86._mm_xor_si128(k1, x86._mm_slli_si128(k1, 0x04))
k1 = x86._mm_xor_si128(k1, x86._mm_slli_si128(k1, 0x04))
k1 = x86._mm_xor_si128(k1, x86._mm_slli_si128(k1, 0x04))
return x86._mm_xor_si128(k1, k2)
}
@(private = "file", require_results, enable_target_feature = "sse,sse2")
expand_step192a :: #force_inline proc (k1_, k2_: ^x86.__m128i, k3: x86.__m128i) -> (x86.__m128i, x86.__m128i) {
k1, k2, k3 := k1_^, k2_^, k3
k3 = x86._mm_shuffle_epi32(k3, 0x55)
k1 = x86._mm_xor_si128(k1, x86._mm_slli_si128(k1, 0x04))
k1 = x86._mm_xor_si128(k1, x86._mm_slli_si128(k1, 0x04))
k1 = x86._mm_xor_si128(k1, x86._mm_slli_si128(k1, 0x04))
k1 = x86._mm_xor_si128(k1, k3)
tmp := k2
k2 = x86._mm_xor_si128(k2, x86._mm_slli_si128(k2, 0x04))
k2 = x86._mm_xor_si128(k2, x86._mm_shuffle_epi32(k1, 0xff))
k1_, k2_ := k1_, k2_
k1_^, k2_^ = k1, k2
r1 := transmute(x86.__m128i)(x86._mm_shuffle_ps(transmute(x86.__m128)(tmp), transmute(x86.__m128)(k1), 0x44))
r2 := transmute(x86.__m128i)(x86._mm_shuffle_ps(transmute(x86.__m128)(k1), transmute(x86.__m128)(k2), 0x4e))
return r1, r2
}
@(private = "file", require_results, enable_target_feature = "sse2")
expand_step192b :: #force_inline proc (k1_, k2_: ^x86.__m128i, k3: x86.__m128i) -> x86.__m128i {
k1, k2, k3 := k1_^, k2_^, k3
k3 = x86._mm_shuffle_epi32(k3, 0x55)
k1 = x86._mm_xor_si128(k1, x86._mm_slli_si128(k1, 0x04))
k1 = x86._mm_xor_si128(k1, x86._mm_slli_si128(k1, 0x04))
k1 = x86._mm_xor_si128(k1, x86._mm_slli_si128(k1, 0x04))
k1 = x86._mm_xor_si128(k1, k3)
k2 = x86._mm_xor_si128(k2, x86._mm_slli_si128(k2, 0x04))
k2 = x86._mm_xor_si128(k2, x86._mm_shuffle_epi32(k1, 0xff))
k1_, k2_ := k1_, k2_
k1_^, k2_^ = k1, k2
return k1
}
@(private = "file", require_results, enable_target_feature = "sse2")
expand_step256b :: #force_inline proc(k1, k2: x86.__m128i) -> x86.__m128i {
k1, k2 := k1, k2
k2 = x86._mm_shuffle_epi32(k2, 0xaa)
k1 = x86._mm_xor_si128(k1, x86._mm_slli_si128(k1, 0x04))
k1 = x86._mm_xor_si128(k1, x86._mm_slli_si128(k1, 0x04))
k1 = x86._mm_xor_si128(k1, x86._mm_slli_si128(k1, 0x04))
return x86._mm_xor_si128(k1, k2)
}
@(private = "file", enable_target_feature = "aes")
derive_dec_keys :: proc(ctx: ^Context, sks: ^[15]x86.__m128i, num_rounds: int) {
intrinsics.unaligned_store((^x86.__m128i)(&ctx._sk_exp_dec[0]), sks[num_rounds])
for i in 1 ..< num_rounds {
tmp := x86._mm_aesimc_si128(sks[i])
intrinsics.unaligned_store((^x86.__m128i)(&ctx._sk_exp_dec[num_rounds - i]), tmp)
}
intrinsics.unaligned_store((^x86.__m128i)(&ctx._sk_exp_dec[num_rounds]), sks[0])
}
@(private, enable_target_feature = "sse,sse2,aes")
keysched :: proc(ctx: ^Context, key: []byte) {
sks: [15]x86.__m128i = ---
// Compute the encryption keys.
num_rounds, key_len := 0, len(key)
switch key_len {
case _aes.KEY_SIZE_128:
sks[0] = intrinsics.unaligned_load((^x86.__m128i)(raw_data(key)))
sks[1] = expand_step128(sks[0], x86._mm_aeskeygenassist_si128(sks[0], 0x01))
sks[2] = expand_step128(sks[1], x86._mm_aeskeygenassist_si128(sks[1], 0x02))
sks[3] = expand_step128(sks[2], x86._mm_aeskeygenassist_si128(sks[2], 0x04))
sks[4] = expand_step128(sks[3], x86._mm_aeskeygenassist_si128(sks[3], 0x08))
sks[5] = expand_step128(sks[4], x86._mm_aeskeygenassist_si128(sks[4], 0x10))
sks[6] = expand_step128(sks[5], x86._mm_aeskeygenassist_si128(sks[5], 0x20))
sks[7] = expand_step128(sks[6], x86._mm_aeskeygenassist_si128(sks[6], 0x40))
sks[8] = expand_step128(sks[7], x86._mm_aeskeygenassist_si128(sks[7], 0x80))
sks[9] = expand_step128(sks[8], x86._mm_aeskeygenassist_si128(sks[8], 0x1b))
sks[10] = expand_step128(sks[9], x86._mm_aeskeygenassist_si128(sks[9], 0x36))
num_rounds = _aes.ROUNDS_128
case _aes.KEY_SIZE_192:
k0 := intrinsics.unaligned_load((^x86.__m128i)(raw_data(key)))
k1 := x86.__m128i{
intrinsics.unaligned_load((^i64)(raw_data(key[16:]))),
0,
}
sks[0] = k0
sks[1], sks[2] = expand_step192a(&k0, &k1, x86._mm_aeskeygenassist_si128(k1, 0x01))
sks[3] = expand_step192b(&k0, &k1, x86._mm_aeskeygenassist_si128(k1, 0x02))
sks[4], sks[5] = expand_step192a(&k0, &k1, x86._mm_aeskeygenassist_si128(k1, 0x04))
sks[6] = expand_step192b(&k0, &k1, x86._mm_aeskeygenassist_si128(k1, 0x08))
sks[7], sks[8] = expand_step192a(&k0, &k1, x86._mm_aeskeygenassist_si128(k1, 0x10))
sks[9] = expand_step192b(&k0, &k1, x86._mm_aeskeygenassist_si128(k1, 0x20))
sks[10], sks[11] = expand_step192a(&k0, &k1, x86._mm_aeskeygenassist_si128(k1, 0x40))
sks[12] = expand_step192b(&k0, &k1, x86._mm_aeskeygenassist_si128(k1, 0x80))
num_rounds = _aes.ROUNDS_192
case _aes.KEY_SIZE_256:
sks[0] = intrinsics.unaligned_load((^x86.__m128i)(raw_data(key)))
sks[1] = intrinsics.unaligned_load((^x86.__m128i)(raw_data(key[16:])))
sks[2] = expand_step128(sks[0], x86._mm_aeskeygenassist_si128(sks[1], 0x01))
sks[3] = expand_step256b(sks[1], x86._mm_aeskeygenassist_si128(sks[2], 0x01))
sks[4] = expand_step128(sks[2], x86._mm_aeskeygenassist_si128(sks[3], 0x02))
sks[5] = expand_step256b(sks[3], x86._mm_aeskeygenassist_si128(sks[4], 0x02))
sks[6] = expand_step128(sks[4], x86._mm_aeskeygenassist_si128(sks[5], 0x04))
sks[7] = expand_step256b(sks[5], x86._mm_aeskeygenassist_si128(sks[6], 0x04))
sks[8] = expand_step128(sks[6], x86._mm_aeskeygenassist_si128(sks[7], 0x08))
sks[9] = expand_step256b(sks[7], x86._mm_aeskeygenassist_si128(sks[8], 0x08))
sks[10] = expand_step128(sks[8], x86._mm_aeskeygenassist_si128(sks[9], 0x10))
sks[11] = expand_step256b(sks[9], x86._mm_aeskeygenassist_si128(sks[10], 0x10))
sks[12] = expand_step128(sks[10], x86._mm_aeskeygenassist_si128(sks[11], 0x20))
sks[13] = expand_step256b(sks[11], x86._mm_aeskeygenassist_si128(sks[12], 0x20))
sks[14] = expand_step128(sks[12], x86._mm_aeskeygenassist_si128(sks[13], 0x40))
num_rounds = _aes.ROUNDS_256
case:
panic("crypto/aes: invalid AES key size")
}
for i in 0 ..= num_rounds {
intrinsics.unaligned_store((^x86.__m128i)(&ctx._sk_exp_enc[i]), sks[i])
}
// Compute the decryption keys. GCM and CTR do not need this, however
// ECB, CBC, OCB3, etc do.
derive_dec_keys(ctx, &sks, num_rounds)
ctx._num_rounds = num_rounds
mem.zero_explicit(&sks, size_of(sks))
}
+123
View File
@@ -0,0 +1,123 @@
package _chacha20
import "base:intrinsics"
import "core:encoding/endian"
import "core:math/bits"
import "core:mem"
// KEY_SIZE is the (X)ChaCha20 key size in bytes.
KEY_SIZE :: 32
// IV_SIZE is the ChaCha20 IV size in bytes.
IV_SIZE :: 12
// XIV_SIZE is the XChaCha20 IV size in bytes.
XIV_SIZE :: 24
// MAX_CTR_IETF is the maximum counter value for the IETF flavor ChaCha20.
MAX_CTR_IETF :: 0xffffffff
// BLOCK_SIZE is the (X)ChaCha20 block size in bytes.
BLOCK_SIZE :: 64
// STATE_SIZE_U32 is the (X)ChaCha20 state size in u32s.
STATE_SIZE_U32 :: 16
// Rounds is the (X)ChaCha20 round count.
ROUNDS :: 20
// SIGMA_0 is sigma[0:4].
SIGMA_0: u32 : 0x61707865
// SIGMA_1 is sigma[4:8].
SIGMA_1: u32 : 0x3320646e
// SIGMA_2 is sigma[8:12].
SIGMA_2: u32 : 0x79622d32
// SIGMA_3 is sigma[12:16].
SIGMA_3: u32 : 0x6b206574
// Context is a ChaCha20 or XChaCha20 instance.
Context :: struct {
_s: [STATE_SIZE_U32]u32,
_buffer: [BLOCK_SIZE]byte,
_off: int,
_is_ietf_flavor: bool,
_is_initialized: bool,
}
// init inititializes a Context for ChaCha20 with the provided key and
// iv.
//
// WARNING: This ONLY handles ChaCha20. XChaCha20 sub-key and IV
// derivation is expected to be handled by the caller, so that the
// HChaCha call can be suitably accelerated.
init :: proc "contextless" (ctx: ^Context, key, iv: []byte, is_xchacha: bool) {
if len(key) != KEY_SIZE || len(iv) != IV_SIZE {
intrinsics.trap()
}
k, n := key, iv
ctx._s[0] = SIGMA_0
ctx._s[1] = SIGMA_1
ctx._s[2] = SIGMA_2
ctx._s[3] = SIGMA_3
ctx._s[4] = endian.unchecked_get_u32le(k[0:4])
ctx._s[5] = endian.unchecked_get_u32le(k[4:8])
ctx._s[6] = endian.unchecked_get_u32le(k[8:12])
ctx._s[7] = endian.unchecked_get_u32le(k[12:16])
ctx._s[8] = endian.unchecked_get_u32le(k[16:20])
ctx._s[9] = endian.unchecked_get_u32le(k[20:24])
ctx._s[10] = endian.unchecked_get_u32le(k[24:28])
ctx._s[11] = endian.unchecked_get_u32le(k[28:32])
ctx._s[12] = 0
ctx._s[13] = endian.unchecked_get_u32le(n[0:4])
ctx._s[14] = endian.unchecked_get_u32le(n[4:8])
ctx._s[15] = endian.unchecked_get_u32le(n[8:12])
ctx._off = BLOCK_SIZE
ctx._is_ietf_flavor = !is_xchacha
ctx._is_initialized = true
}
// seek seeks the (X)ChaCha20 stream counter to the specified block.
seek :: proc(ctx: ^Context, block_nr: u64) {
assert(ctx._is_initialized)
if ctx._is_ietf_flavor {
if block_nr > MAX_CTR_IETF {
panic("crypto/chacha20: attempted to seek past maximum counter")
}
} else {
ctx._s[13] = u32(block_nr >> 32)
}
ctx._s[12] = u32(block_nr)
ctx._off = BLOCK_SIZE
}
// reset sanitizes the Context. The Context must be re-initialized to
// be used again.
reset :: proc(ctx: ^Context) {
mem.zero_explicit(&ctx._s, size_of(ctx._s))
mem.zero_explicit(&ctx._buffer, size_of(ctx._buffer))
ctx._is_initialized = false
}
check_counter_limit :: proc(ctx: ^Context, nr_blocks: int) {
// Enforce the maximum consumed keystream per IV.
//
// While all modern "standard" definitions of ChaCha20 use
// the IETF 32-bit counter, for XChaCha20 most common
// implementations allow for a 64-bit counter.
//
// Honestly, the answer here is "use a MRAE primitive", but
// go with "common" practice in the case of XChaCha20.
ERR_CTR_EXHAUSTED :: "crypto/chacha20: maximum (X)ChaCha20 keystream per IV reached"
if ctx._is_ietf_flavor {
if u64(ctx._s[12]) + u64(nr_blocks) > MAX_CTR_IETF {
panic(ERR_CTR_EXHAUSTED)
}
} else {
ctr := (u64(ctx._s[13]) << 32) | u64(ctx._s[12])
if _, carry := bits.add_u64(ctr, u64(nr_blocks), 0); carry != 0 {
panic(ERR_CTR_EXHAUSTED)
}
}
}
+360
View File
@@ -0,0 +1,360 @@
package chacha20_ref
import "core:crypto/_chacha20"
import "core:encoding/endian"
import "core:math/bits"
stream_blocks :: proc(ctx: ^_chacha20.Context, dst, src: []byte, nr_blocks: int) {
// Enforce the maximum consumed keystream per IV.
_chacha20.check_counter_limit(ctx, nr_blocks)
dst, src := dst, src
x := &ctx._s
for n := 0; n < nr_blocks; n = n + 1 {
x0, x1, x2, x3 :=
_chacha20.SIGMA_0, _chacha20.SIGMA_1, _chacha20.SIGMA_2, _chacha20.SIGMA_3
x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15 :=
x[4], x[5], x[6], x[7], x[8], x[9], x[10], x[11], x[12], x[13], x[14], x[15]
for i := _chacha20.ROUNDS; i > 0; i = i - 2 {
// Even when forcing inlining manually inlining all of
// these is decently faster.
// quarterround(x, 0, 4, 8, 12)
x0 += x4
x12 ~= x0
x12 = bits.rotate_left32(x12, 16)
x8 += x12
x4 ~= x8
x4 = bits.rotate_left32(x4, 12)
x0 += x4
x12 ~= x0
x12 = bits.rotate_left32(x12, 8)
x8 += x12
x4 ~= x8
x4 = bits.rotate_left32(x4, 7)
// quarterround(x, 1, 5, 9, 13)
x1 += x5
x13 ~= x1
x13 = bits.rotate_left32(x13, 16)
x9 += x13
x5 ~= x9
x5 = bits.rotate_left32(x5, 12)
x1 += x5
x13 ~= x1
x13 = bits.rotate_left32(x13, 8)
x9 += x13
x5 ~= x9
x5 = bits.rotate_left32(x5, 7)
// quarterround(x, 2, 6, 10, 14)
x2 += x6
x14 ~= x2
x14 = bits.rotate_left32(x14, 16)
x10 += x14
x6 ~= x10
x6 = bits.rotate_left32(x6, 12)
x2 += x6
x14 ~= x2
x14 = bits.rotate_left32(x14, 8)
x10 += x14
x6 ~= x10
x6 = bits.rotate_left32(x6, 7)
// quarterround(x, 3, 7, 11, 15)
x3 += x7
x15 ~= x3
x15 = bits.rotate_left32(x15, 16)
x11 += x15
x7 ~= x11
x7 = bits.rotate_left32(x7, 12)
x3 += x7
x15 ~= x3
x15 = bits.rotate_left32(x15, 8)
x11 += x15
x7 ~= x11
x7 = bits.rotate_left32(x7, 7)
// quarterround(x, 0, 5, 10, 15)
x0 += x5
x15 ~= x0
x15 = bits.rotate_left32(x15, 16)
x10 += x15
x5 ~= x10
x5 = bits.rotate_left32(x5, 12)
x0 += x5
x15 ~= x0
x15 = bits.rotate_left32(x15, 8)
x10 += x15
x5 ~= x10
x5 = bits.rotate_left32(x5, 7)
// quarterround(x, 1, 6, 11, 12)
x1 += x6
x12 ~= x1
x12 = bits.rotate_left32(x12, 16)
x11 += x12
x6 ~= x11
x6 = bits.rotate_left32(x6, 12)
x1 += x6
x12 ~= x1
x12 = bits.rotate_left32(x12, 8)
x11 += x12
x6 ~= x11
x6 = bits.rotate_left32(x6, 7)
// quarterround(x, 2, 7, 8, 13)
x2 += x7
x13 ~= x2
x13 = bits.rotate_left32(x13, 16)
x8 += x13
x7 ~= x8
x7 = bits.rotate_left32(x7, 12)
x2 += x7
x13 ~= x2
x13 = bits.rotate_left32(x13, 8)
x8 += x13
x7 ~= x8
x7 = bits.rotate_left32(x7, 7)
// quarterround(x, 3, 4, 9, 14)
x3 += x4
x14 ~= x3
x14 = bits.rotate_left32(x14, 16)
x9 += x14
x4 ~= x9
x4 = bits.rotate_left32(x4, 12)
x3 += x4
x14 ~= x3
x14 = bits.rotate_left32(x14, 8)
x9 += x14
x4 ~= x9
x4 = bits.rotate_left32(x4, 7)
}
x0 += _chacha20.SIGMA_0
x1 += _chacha20.SIGMA_1
x2 += _chacha20.SIGMA_2
x3 += _chacha20.SIGMA_3
x4 += x[4]
x5 += x[5]
x6 += x[6]
x7 += x[7]
x8 += x[8]
x9 += x[9]
x10 += x[10]
x11 += x[11]
x12 += x[12]
x13 += x[13]
x14 += x[14]
x15 += x[15]
// - The caller(s) ensure that src/dst are valid.
// - The compiler knows if the target is picky about alignment.
#no_bounds_check {
if src != nil {
endian.unchecked_put_u32le(dst[0:4], endian.unchecked_get_u32le(src[0:4]) ~ x0)
endian.unchecked_put_u32le(dst[4:8], endian.unchecked_get_u32le(src[4:8]) ~ x1)
endian.unchecked_put_u32le(dst[8:12], endian.unchecked_get_u32le(src[8:12]) ~ x2)
endian.unchecked_put_u32le(dst[12:16], endian.unchecked_get_u32le(src[12:16]) ~ x3)
endian.unchecked_put_u32le(dst[16:20], endian.unchecked_get_u32le(src[16:20]) ~ x4)
endian.unchecked_put_u32le(dst[20:24], endian.unchecked_get_u32le(src[20:24]) ~ x5)
endian.unchecked_put_u32le(dst[24:28], endian.unchecked_get_u32le(src[24:28]) ~ x6)
endian.unchecked_put_u32le(dst[28:32], endian.unchecked_get_u32le(src[28:32]) ~ x7)
endian.unchecked_put_u32le(dst[32:36], endian.unchecked_get_u32le(src[32:36]) ~ x8)
endian.unchecked_put_u32le(dst[36:40], endian.unchecked_get_u32le(src[36:40]) ~ x9)
endian.unchecked_put_u32le(
dst[40:44],
endian.unchecked_get_u32le(src[40:44]) ~ x10,
)
endian.unchecked_put_u32le(
dst[44:48],
endian.unchecked_get_u32le(src[44:48]) ~ x11,
)
endian.unchecked_put_u32le(
dst[48:52],
endian.unchecked_get_u32le(src[48:52]) ~ x12,
)
endian.unchecked_put_u32le(
dst[52:56],
endian.unchecked_get_u32le(src[52:56]) ~ x13,
)
endian.unchecked_put_u32le(
dst[56:60],
endian.unchecked_get_u32le(src[56:60]) ~ x14,
)
endian.unchecked_put_u32le(
dst[60:64],
endian.unchecked_get_u32le(src[60:64]) ~ x15,
)
src = src[_chacha20.BLOCK_SIZE:]
} else {
endian.unchecked_put_u32le(dst[0:4], x0)
endian.unchecked_put_u32le(dst[4:8], x1)
endian.unchecked_put_u32le(dst[8:12], x2)
endian.unchecked_put_u32le(dst[12:16], x3)
endian.unchecked_put_u32le(dst[16:20], x4)
endian.unchecked_put_u32le(dst[20:24], x5)
endian.unchecked_put_u32le(dst[24:28], x6)
endian.unchecked_put_u32le(dst[28:32], x7)
endian.unchecked_put_u32le(dst[32:36], x8)
endian.unchecked_put_u32le(dst[36:40], x9)
endian.unchecked_put_u32le(dst[40:44], x10)
endian.unchecked_put_u32le(dst[44:48], x11)
endian.unchecked_put_u32le(dst[48:52], x12)
endian.unchecked_put_u32le(dst[52:56], x13)
endian.unchecked_put_u32le(dst[56:60], x14)
endian.unchecked_put_u32le(dst[60:64], x15)
}
dst = dst[_chacha20.BLOCK_SIZE:]
}
// Increment the counter. Overflow checking is done upon
// entry into the routine, so a 64-bit increment safely
// covers both cases.
new_ctr := ((u64(ctx._s[13]) << 32) | u64(ctx._s[12])) + 1
x[12] = u32(new_ctr)
x[13] = u32(new_ctr >> 32)
}
}
hchacha20 :: proc "contextless" (dst, key, iv: []byte) {
x0, x1, x2, x3 := _chacha20.SIGMA_0, _chacha20.SIGMA_1, _chacha20.SIGMA_2, _chacha20.SIGMA_3
x4 := endian.unchecked_get_u32le(key[0:4])
x5 := endian.unchecked_get_u32le(key[4:8])
x6 := endian.unchecked_get_u32le(key[8:12])
x7 := endian.unchecked_get_u32le(key[12:16])
x8 := endian.unchecked_get_u32le(key[16:20])
x9 := endian.unchecked_get_u32le(key[20:24])
x10 := endian.unchecked_get_u32le(key[24:28])
x11 := endian.unchecked_get_u32le(key[28:32])
x12 := endian.unchecked_get_u32le(iv[0:4])
x13 := endian.unchecked_get_u32le(iv[4:8])
x14 := endian.unchecked_get_u32le(iv[8:12])
x15 := endian.unchecked_get_u32le(iv[12:16])
for i := _chacha20.ROUNDS; i > 0; i = i - 2 {
// quarterround(x, 0, 4, 8, 12)
x0 += x4
x12 ~= x0
x12 = bits.rotate_left32(x12, 16)
x8 += x12
x4 ~= x8
x4 = bits.rotate_left32(x4, 12)
x0 += x4
x12 ~= x0
x12 = bits.rotate_left32(x12, 8)
x8 += x12
x4 ~= x8
x4 = bits.rotate_left32(x4, 7)
// quarterround(x, 1, 5, 9, 13)
x1 += x5
x13 ~= x1
x13 = bits.rotate_left32(x13, 16)
x9 += x13
x5 ~= x9
x5 = bits.rotate_left32(x5, 12)
x1 += x5
x13 ~= x1
x13 = bits.rotate_left32(x13, 8)
x9 += x13
x5 ~= x9
x5 = bits.rotate_left32(x5, 7)
// quarterround(x, 2, 6, 10, 14)
x2 += x6
x14 ~= x2
x14 = bits.rotate_left32(x14, 16)
x10 += x14
x6 ~= x10
x6 = bits.rotate_left32(x6, 12)
x2 += x6
x14 ~= x2
x14 = bits.rotate_left32(x14, 8)
x10 += x14
x6 ~= x10
x6 = bits.rotate_left32(x6, 7)
// quarterround(x, 3, 7, 11, 15)
x3 += x7
x15 ~= x3
x15 = bits.rotate_left32(x15, 16)
x11 += x15
x7 ~= x11
x7 = bits.rotate_left32(x7, 12)
x3 += x7
x15 ~= x3
x15 = bits.rotate_left32(x15, 8)
x11 += x15
x7 ~= x11
x7 = bits.rotate_left32(x7, 7)
// quarterround(x, 0, 5, 10, 15)
x0 += x5
x15 ~= x0
x15 = bits.rotate_left32(x15, 16)
x10 += x15
x5 ~= x10
x5 = bits.rotate_left32(x5, 12)
x0 += x5
x15 ~= x0
x15 = bits.rotate_left32(x15, 8)
x10 += x15
x5 ~= x10
x5 = bits.rotate_left32(x5, 7)
// quarterround(x, 1, 6, 11, 12)
x1 += x6
x12 ~= x1
x12 = bits.rotate_left32(x12, 16)
x11 += x12
x6 ~= x11
x6 = bits.rotate_left32(x6, 12)
x1 += x6
x12 ~= x1
x12 = bits.rotate_left32(x12, 8)
x11 += x12
x6 ~= x11
x6 = bits.rotate_left32(x6, 7)
// quarterround(x, 2, 7, 8, 13)
x2 += x7
x13 ~= x2
x13 = bits.rotate_left32(x13, 16)
x8 += x13
x7 ~= x8
x7 = bits.rotate_left32(x7, 12)
x2 += x7
x13 ~= x2
x13 = bits.rotate_left32(x13, 8)
x8 += x13
x7 ~= x8
x7 = bits.rotate_left32(x7, 7)
// quarterround(x, 3, 4, 9, 14)
x3 += x4
x14 ~= x3
x14 = bits.rotate_left32(x14, 16)
x9 += x14
x4 ~= x9
x4 = bits.rotate_left32(x4, 12)
x3 += x4
x14 ~= x3
x14 = bits.rotate_left32(x14, 8)
x9 += x14
x4 ~= x9
x4 = bits.rotate_left32(x4, 7)
}
endian.unchecked_put_u32le(dst[0:4], x0)
endian.unchecked_put_u32le(dst[4:8], x1)
endian.unchecked_put_u32le(dst[8:12], x2)
endian.unchecked_put_u32le(dst[12:16], x3)
endian.unchecked_put_u32le(dst[16:20], x12)
endian.unchecked_put_u32le(dst[20:24], x13)
endian.unchecked_put_u32le(dst[24:28], x14)
endian.unchecked_put_u32le(dst[28:32], x15)
}
@@ -0,0 +1,481 @@
package chacha20_simd128
import "base:intrinsics"
import "core:crypto/_chacha20"
import "core:simd"
@(require) import "core:sys/info"
// Portable 128-bit `core:simd` implementation.
//
// This is loosely based on Ted Krovetz's public domain C intrinsic
// implementation.
//
// This is written to perform adequately on any target that has "enough"
// 128-bit vector registers, the current thought is that 4 blocks at at
// time is reasonable for amd64, though Ted's code is more conservative.
//
// See:
// supercop-20230530/crypto_stream/chacha20/krovetz/vec128
// Ensure the compiler emits SIMD instructions. This is a minimum, and
// setting the microarchitecture at compile time will allow for better
// code gen when applicable (eg: AVX). This is somewhat redundant with
// the default microarchitecture configurations.
when ODIN_ARCH == .arm64 || ODIN_ARCH == .arm32 {
@(private = "file")
TARGET_SIMD_FEATURES :: "neon"
} else when ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 {
// Note: LLVM appears to be smart enough to use PSHUFB despite not
// explicitly using simd.u8x16 shuffles.
@(private = "file")
TARGET_SIMD_FEATURES :: "sse2,ssse3"
} else {
@(private = "file")
TARGET_SIMD_FEATURES :: ""
}
@(private = "file")
_ROT_7L: simd.u32x4 : {7, 7, 7, 7}
@(private = "file")
_ROT_7R: simd.u32x4 : {25, 25, 25, 25}
@(private = "file")
_ROT_12L: simd.u32x4 : {12, 12, 12, 12}
@(private = "file")
_ROT_12R: simd.u32x4 : {20, 20, 20, 20}
@(private = "file")
_ROT_8L: simd.u32x4 : {8, 8, 8, 8}
@(private = "file")
_ROT_8R: simd.u32x4 : {24, 24, 24, 24}
@(private = "file")
_ROT_16: simd.u32x4 : {16, 16, 16, 16}
when ODIN_ENDIAN == .Big {
@(private = "file")
_increment_counter :: #force_inline proc "contextless" (ctx: ^_chacha20.Context) -> simd.u32x4 {
// In the Big Endian case, the low and high portions in the vector
// are flipped, so the 64-bit addition can't be done with a simple
// vector add.
x := &ctx._s
new_ctr := ((u64(ctx._s[13]) << 32) | u64(ctx._s[12])) + 1
x[12] = u32(new_ctr)
x[13] = u32(new_ctr >> 32)
return intrinsics.unaligned_load(transmute(^simd.u32x4)&x[12])
}
// Convert the endian-ness of the components of a u32x4 vector, for
// the purposes of output.
@(private = "file")
_byteswap_u32x4 :: #force_inline proc "contextless" (v: simd.u32x4) -> simd.u32x4 {
return(
transmute(simd.u32x4)simd.shuffle(
transmute(simd.u8x16)v,
transmute(simd.u8x16)v,
3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12,
)
)
}
} else {
@(private = "file")
_VEC_ONE: simd.u64x2 : {1, 0}
}
@(private = "file")
_dq_round_simd128 :: #force_inline proc "contextless" (
v0, v1, v2, v3: simd.u32x4,
) -> (
simd.u32x4,
simd.u32x4,
simd.u32x4,
simd.u32x4,
) {
v0, v1, v2, v3 := v0, v1, v2, v3
// a += b; d ^= a; d = ROTW16(d);
v0 = simd.add(v0, v1)
v3 = simd.bit_xor(v3, v0)
v3 = simd.bit_xor(simd.shl(v3, _ROT_16), simd.shr(v3, _ROT_16))
// c += d; b ^= c; b = ROTW12(b);
v2 = simd.add(v2, v3)
v1 = simd.bit_xor(v1, v2)
v1 = simd.bit_xor(simd.shl(v1, _ROT_12L), simd.shr(v1, _ROT_12R))
// a += b; d ^= a; d = ROTW8(d);
v0 = simd.add(v0, v1)
v3 = simd.bit_xor(v3, v0)
v3 = simd.bit_xor(simd.shl(v3, _ROT_8L), simd.shr(v3, _ROT_8R))
// c += d; b ^= c; b = ROTW7(b);
v2 = simd.add(v2, v3)
v1 = simd.bit_xor(v1, v2)
v1 = simd.bit_xor(simd.shl(v1, _ROT_7L), simd.shr(v1, _ROT_7R))
// b = ROTV1(b); c = ROTV2(c); d = ROTV3(d);
v1 = simd.shuffle(v1, v1, 1, 2, 3, 0)
v2 = simd.shuffle(v2, v2, 2, 3, 0, 1)
v3 = simd.shuffle(v3, v3, 3, 0, 1, 2)
// a += b; d ^= a; d = ROTW16(d);
v0 = simd.add(v0, v1)
v3 = simd.bit_xor(v3, v0)
v3 = simd.bit_xor(simd.shl(v3, _ROT_16), simd.shr(v3, _ROT_16))
// c += d; b ^= c; b = ROTW12(b);
v2 = simd.add(v2, v3)
v1 = simd.bit_xor(v1, v2)
v1 = simd.bit_xor(simd.shl(v1, _ROT_12L), simd.shr(v1, _ROT_12R))
// a += b; d ^= a; d = ROTW8(d);
v0 = simd.add(v0, v1)
v3 = simd.bit_xor(v3, v0)
v3 = simd.bit_xor(simd.shl(v3, _ROT_8L), simd.shr(v3, _ROT_8R))
// c += d; b ^= c; b = ROTW7(b);
v2 = simd.add(v2, v3)
v1 = simd.bit_xor(v1, v2)
v1 = simd.bit_xor(simd.shl(v1, _ROT_7L), simd.shr(v1, _ROT_7R))
// b = ROTV3(b); c = ROTV2(c); d = ROTV1(d);
v1 = simd.shuffle(v1, v1, 3, 0, 1, 2)
v2 = simd.shuffle(v2, v2, 2, 3, 0, 1)
v3 = simd.shuffle(v3, v3, 1, 2, 3, 0)
return v0, v1, v2, v3
}
@(private = "file")
_add_state_simd128 :: #force_inline proc "contextless" (
v0, v1, v2, v3, s0, s1, s2, s3: simd.u32x4,
) -> (
simd.u32x4,
simd.u32x4,
simd.u32x4,
simd.u32x4,
) {
v0, v1, v2, v3 := v0, v1, v2, v3
v0 = simd.add(v0, s0)
v1 = simd.add(v1, s1)
v2 = simd.add(v2, s2)
v3 = simd.add(v3, s3)
when ODIN_ENDIAN == .Big {
v0 = _byteswap_u32x4(v0)
v1 = _byteswap_u32x4(v1)
v2 = _byteswap_u32x4(v2)
v3 = _byteswap_u32x4(v3)
}
return v0, v1, v2, v3
}
@(private = "file")
_xor_simd128 :: #force_inline proc "contextless" (
src: [^]simd.u32x4,
v0, v1, v2, v3: simd.u32x4,
) -> (
simd.u32x4,
simd.u32x4,
simd.u32x4,
simd.u32x4,
) {
v0, v1, v2, v3 := v0, v1, v2, v3
v0 = simd.bit_xor(v0, intrinsics.unaligned_load((^simd.u32x4)(src[0:])))
v1 = simd.bit_xor(v1, intrinsics.unaligned_load((^simd.u32x4)(src[1:])))
v2 = simd.bit_xor(v2, intrinsics.unaligned_load((^simd.u32x4)(src[2:])))
v3 = simd.bit_xor(v3, intrinsics.unaligned_load((^simd.u32x4)(src[3:])))
return v0, v1, v2, v3
}
@(private = "file")
_store_simd128 :: #force_inline proc "contextless" (
dst: [^]simd.u32x4,
v0, v1, v2, v3: simd.u32x4,
) {
intrinsics.unaligned_store((^simd.u32x4)(dst[0:]), v0)
intrinsics.unaligned_store((^simd.u32x4)(dst[1:]), v1)
intrinsics.unaligned_store((^simd.u32x4)(dst[2:]), v2)
intrinsics.unaligned_store((^simd.u32x4)(dst[3:]), v3)
}
// is_performant returns true iff the target and current host both support
// "enough" 128-bit SIMD to make this implementation performant.
is_performant :: proc "contextless" () -> bool {
when ODIN_ARCH == .arm64 || ODIN_ARCH == .arm32 || ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 {
when ODIN_ARCH == .arm64 || ODIN_ARCH == .arm32 {
req_features :: info.CPU_Features{.asimd}
} else when ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 {
req_features :: info.CPU_Features{.sse2, .ssse3}
}
features, ok := info.cpu_features.?
if !ok {
return false
}
return features >= req_features
} else when ODIN_ARCH == .wasm64p32 || ODIN_ARCH == .wasm32 {
return intrinsics.has_target_feature("simd128")
} else {
return false
}
}
@(enable_target_feature = TARGET_SIMD_FEATURES)
stream_blocks :: proc(ctx: ^_chacha20.Context, dst, src: []byte, nr_blocks: int) {
// Enforce the maximum consumed keystream per IV.
_chacha20.check_counter_limit(ctx, nr_blocks)
dst_v := ([^]simd.u32x4)(raw_data(dst))
src_v := ([^]simd.u32x4)(raw_data(src))
x := &ctx._s
n := nr_blocks
// The state vector is an array of uint32s in native byte-order.
x_v := ([^]simd.u32x4)(raw_data(x))
s0 := intrinsics.unaligned_load((^simd.u32x4)(x_v[0:]))
s1 := intrinsics.unaligned_load((^simd.u32x4)(x_v[1:]))
s2 := intrinsics.unaligned_load((^simd.u32x4)(x_v[2:]))
s3 := intrinsics.unaligned_load((^simd.u32x4)(x_v[3:]))
// 8 blocks at a time.
//
// Note: This is only worth it on Aarch64.
when ODIN_ARCH == .arm64 {
for ; n >= 8; n = n - 8 {
v0, v1, v2, v3 := s0, s1, s2, s3
when ODIN_ENDIAN == .Little {
s7 := transmute(simd.u32x4)simd.add(transmute(simd.u64x2)s3, _VEC_ONE)
} else {
s7 := _increment_counter(ctx)
}
v4, v5, v6, v7 := s0, s1, s2, s7
when ODIN_ENDIAN == .Little {
s11 := transmute(simd.u32x4)simd.add(transmute(simd.u64x2)s7, _VEC_ONE)
} else {
s11 := _increment_counter(ctx)
}
v8, v9, v10, v11 := s0, s1, s2, s11
when ODIN_ENDIAN == .Little {
s15 := transmute(simd.u32x4)simd.add(transmute(simd.u64x2)s11, _VEC_ONE)
} else {
s15 := _increment_counter(ctx)
}
v12, v13, v14, v15 := s0, s1, s2, s15
when ODIN_ENDIAN == .Little {
s19 := transmute(simd.u32x4)simd.add(transmute(simd.u64x2)s15, _VEC_ONE)
} else {
s19 := _increment_counter(ctx)
}
v16, v17, v18, v19 := s0, s1, s2, s19
when ODIN_ENDIAN == .Little {
s23 := transmute(simd.u32x4)simd.add(transmute(simd.u64x2)s19, _VEC_ONE)
} else {
s23 := _increment_counter(ctx)
}
v20, v21, v22, v23 := s0, s1, s2, s23
when ODIN_ENDIAN == .Little {
s27 := transmute(simd.u32x4)simd.add(transmute(simd.u64x2)s23, _VEC_ONE)
} else {
s27 := _increment_counter(ctx)
}
v24, v25, v26, v27 := s0, s1, s2, s27
when ODIN_ENDIAN == .Little {
s31 := transmute(simd.u32x4)simd.add(transmute(simd.u64x2)s27, _VEC_ONE)
} else {
s31 := _increment_counter(ctx)
}
v28, v29, v30, v31 := s0, s1, s2, s31
for i := _chacha20.ROUNDS; i > 0; i = i - 2 {
v0, v1, v2, v3 = _dq_round_simd128(v0, v1, v2, v3)
v4, v5, v6, v7 = _dq_round_simd128(v4, v5, v6, v7)
v8, v9, v10, v11 = _dq_round_simd128(v8, v9, v10, v11)
v12, v13, v14, v15 = _dq_round_simd128(v12, v13, v14, v15)
v16, v17, v18, v19 = _dq_round_simd128(v16, v17, v18, v19)
v20, v21, v22, v23 = _dq_round_simd128(v20, v21, v22, v23)
v24, v25, v26, v27 = _dq_round_simd128(v24, v25, v26, v27)
v28, v29, v30, v31 = _dq_round_simd128(v28, v29, v30, v31)
}
v0, v1, v2, v3 = _add_state_simd128(v0, v1, v2, v3, s0, s1, s2, s3)
v4, v5, v6, v7 = _add_state_simd128(v4, v5, v6, v7, s0, s1, s2, s7)
v8, v9, v10, v11 = _add_state_simd128(v8, v9, v10, v11, s0, s1, s2, s11)
v12, v13, v14, v15 = _add_state_simd128(v12, v13, v14, v15, s0, s1, s2, s15)
v16, v17, v18, v19 = _add_state_simd128(v16, v17, v18, v19, s0, s1, s2, s19)
v20, v21, v22, v23 = _add_state_simd128(v20, v21, v22, v23, s0, s1, s2, s23)
v24, v25, v26, v27 = _add_state_simd128(v24, v25, v26, v27, s0, s1, s2, s27)
v28, v29, v30, v31 = _add_state_simd128(v28, v29, v30, v31, s0, s1, s2, s31)
#no_bounds_check {
if src != nil {
v0, v1, v2, v3 = _xor_simd128(src_v, v0, v1, v2, v3)
v4, v5, v6, v7 = _xor_simd128(src_v[4:], v4, v5, v6, v7)
v8, v9, v10, v11 = _xor_simd128(src_v[8:], v8, v9, v10, v11)
v12, v13, v14, v15 = _xor_simd128(src_v[12:], v12, v13, v14, v15)
v16, v17, v18, v19 = _xor_simd128(src_v[16:], v16, v17, v18, v19)
v20, v21, v22, v23 = _xor_simd128(src_v[20:], v20, v21, v22, v23)
v24, v25, v26, v27 = _xor_simd128(src_v[24:], v24, v25, v26, v27)
v28, v29, v30, v31 = _xor_simd128(src_v[28:], v28, v29, v30, v31)
src_v = src_v[32:]
}
_store_simd128(dst_v, v0, v1, v2, v3)
_store_simd128(dst_v[4:], v4, v5, v6, v7)
_store_simd128(dst_v[8:], v8, v9, v10, v11)
_store_simd128(dst_v[12:], v12, v13, v14, v15)
_store_simd128(dst_v[16:], v16, v17, v18, v19)
_store_simd128(dst_v[20:], v20, v21, v22, v23)
_store_simd128(dst_v[24:], v24, v25, v26, v27)
_store_simd128(dst_v[28:], v28, v29, v30, v31)
dst_v = dst_v[32:]
}
when ODIN_ENDIAN == .Little {
// s31 holds the most current counter, so `s3 = s31 + 1`.
s3 = transmute(simd.u32x4)simd.add(transmute(simd.u64x2)s31, _VEC_ONE)
} else {
s3 = _increment_counter(ctx)
}
}
}
// 4 blocks at a time.
//
// Note: The i386 target lacks the required number of registers
// for this to be performant, so it is skipped.
when ODIN_ARCH != .i386 {
for ; n >= 4; n = n - 4 {
v0, v1, v2, v3 := s0, s1, s2, s3
when ODIN_ENDIAN == .Little {
s7 := transmute(simd.u32x4)simd.add(transmute(simd.u64x2)s3, _VEC_ONE)
} else {
s7 := _increment_counter(ctx)
}
v4, v5, v6, v7 := s0, s1, s2, s7
when ODIN_ENDIAN == .Little {
s11 := transmute(simd.u32x4)simd.add(transmute(simd.u64x2)s7, _VEC_ONE)
} else {
s11 := _increment_counter(ctx)
}
v8, v9, v10, v11 := s0, s1, s2, s11
when ODIN_ENDIAN == .Little {
s15 := transmute(simd.u32x4)simd.add(transmute(simd.u64x2)s11, _VEC_ONE)
} else {
s15 := _increment_counter(ctx)
}
v12, v13, v14, v15 := s0, s1, s2, s15
for i := _chacha20.ROUNDS; i > 0; i = i - 2 {
v0, v1, v2, v3 = _dq_round_simd128(v0, v1, v2, v3)
v4, v5, v6, v7 = _dq_round_simd128(v4, v5, v6, v7)
v8, v9, v10, v11 = _dq_round_simd128(v8, v9, v10, v11)
v12, v13, v14, v15 = _dq_round_simd128(v12, v13, v14, v15)
}
v0, v1, v2, v3 = _add_state_simd128(v0, v1, v2, v3, s0, s1, s2, s3)
v4, v5, v6, v7 = _add_state_simd128(v4, v5, v6, v7, s0, s1, s2, s7)
v8, v9, v10, v11 = _add_state_simd128(v8, v9, v10, v11, s0, s1, s2, s11)
v12, v13, v14, v15 = _add_state_simd128(v12, v13, v14, v15, s0, s1, s2, s15)
#no_bounds_check {
if src != nil {
v0, v1, v2, v3 = _xor_simd128(src_v, v0, v1, v2, v3)
v4, v5, v6, v7 = _xor_simd128(src_v[4:], v4, v5, v6, v7)
v8, v9, v10, v11 = _xor_simd128(src_v[8:], v8, v9, v10, v11)
v12, v13, v14, v15 = _xor_simd128(src_v[12:], v12, v13, v14, v15)
src_v = src_v[16:]
}
_store_simd128(dst_v, v0, v1, v2, v3)
_store_simd128(dst_v[4:], v4, v5, v6, v7)
_store_simd128(dst_v[8:], v8, v9, v10, v11)
_store_simd128(dst_v[12:], v12, v13, v14, v15)
dst_v = dst_v[16:]
}
when ODIN_ENDIAN == .Little {
// s15 holds the most current counter, so `s3 = s15 + 1`.
s3 = transmute(simd.u32x4)simd.add(transmute(simd.u64x2)s15, _VEC_ONE)
} else {
s3 = _increment_counter(ctx)
}
}
}
// 1 block at a time.
for ; n > 0; n = n - 1 {
v0, v1, v2, v3 := s0, s1, s2, s3
for i := _chacha20.ROUNDS; i > 0; i = i - 2 {
v0, v1, v2, v3 = _dq_round_simd128(v0, v1, v2, v3)
}
v0, v1, v2, v3 = _add_state_simd128(v0, v1, v2, v3, s0, s1, s2, s3)
#no_bounds_check {
if src != nil {
v0, v1, v2, v3 = _xor_simd128(src_v, v0, v1, v2, v3)
src_v = src_v[4:]
}
_store_simd128(dst_v, v0, v1, v2, v3)
dst_v = dst_v[4:]
}
// Increment the counter. Overflow checking is done upon
// entry into the routine, so a 64-bit increment safely
// covers both cases.
when ODIN_ENDIAN == .Little {
s3 = transmute(simd.u32x4)simd.add(transmute(simd.u64x2)s3, _VEC_ONE)
} else {
s3 = _increment_counter(ctx)
}
}
when ODIN_ENDIAN == .Little {
// Write back the counter to the state.
intrinsics.unaligned_store((^simd.u32x4)(x_v[3:]), s3)
}
}
@(enable_target_feature = TARGET_SIMD_FEATURES)
hchacha20 :: proc "contextless" (dst, key, iv: []byte) {
v0 := simd.u32x4{_chacha20.SIGMA_0, _chacha20.SIGMA_1, _chacha20.SIGMA_2, _chacha20.SIGMA_3}
v1 := intrinsics.unaligned_load((^simd.u32x4)(&key[0]))
v2 := intrinsics.unaligned_load((^simd.u32x4)(&key[16]))
v3 := intrinsics.unaligned_load((^simd.u32x4)(&iv[0]))
when ODIN_ENDIAN == .Big {
v1 = _byteswap_u32x4(v1)
v2 = _byteswap_u32x4(v2)
v3 = _byteswap_u32x4(v3)
}
for i := _chacha20.ROUNDS; i > 0; i = i - 2 {
v0, v1, v2, v3 = _dq_round_simd128(v0, v1, v2, v3)
}
when ODIN_ENDIAN == .Big {
v0 = _byteswap_u32x4(v0)
v3 = _byteswap_u32x4(v3)
}
dst_v := ([^]simd.u32x4)(raw_data(dst))
intrinsics.unaligned_store((^simd.u32x4)(dst_v[0:]), v0)
intrinsics.unaligned_store((^simd.u32x4)(dst_v[1:]), v3)
}
@@ -0,0 +1,319 @@
#+build amd64
package chacha20_simd256
import "base:intrinsics"
import "core:crypto/_chacha20"
import chacha_simd128 "core:crypto/_chacha20/simd128"
import "core:simd"
import "core:sys/info"
// This is loosely based on Ted Krovetz's public domain C intrinsic
// implementations. While written using `core:simd`, this is currently
// amd64 specific because we do not have a way to detect ARM SVE.
//
// See:
// supercop-20230530/crypto_stream/chacha20/krovetz/vec128
// supercop-20230530/crypto_stream/chacha20/krovetz/avx2
#assert(ODIN_ENDIAN == .Little)
@(private = "file")
_ROT_7L: simd.u32x8 : {7, 7, 7, 7, 7, 7, 7, 7}
@(private = "file")
_ROT_7R: simd.u32x8 : {25, 25, 25, 25, 25, 25, 25, 25}
@(private = "file")
_ROT_12L: simd.u32x8 : {12, 12, 12, 12, 12, 12, 12, 12}
@(private = "file")
_ROT_12R: simd.u32x8 : {20, 20, 20, 20, 20, 20, 20, 20}
@(private = "file")
_ROT_8L: simd.u32x8 : {8, 8, 8, 8, 8, 8, 8, 8}
@(private = "file")
_ROT_8R: simd.u32x8 : {24, 24, 24, 24, 24, 24, 24, 24}
@(private = "file")
_ROT_16: simd.u32x8 : {16, 16, 16, 16, 16, 16, 16, 16}
@(private = "file")
_VEC_ZERO_ONE: simd.u64x4 : {0, 0, 1, 0}
@(private = "file")
_VEC_TWO: simd.u64x4 : {2, 0, 2, 0}
// is_performant returns true iff the target and current host both support
// "enough" SIMD to make this implementation performant.
is_performant :: proc "contextless" () -> bool {
req_features :: info.CPU_Features{.avx, .avx2}
features, ok := info.cpu_features.?
if !ok {
return false
}
return features >= req_features
}
@(private = "file")
_dq_round_simd256 :: #force_inline proc "contextless" (
v0, v1, v2, v3: simd.u32x8,
) -> (
simd.u32x8,
simd.u32x8,
simd.u32x8,
simd.u32x8,
) {
v0, v1, v2, v3 := v0, v1, v2, v3
// a += b; d ^= a; d = ROTW16(d);
v0 = simd.add(v0, v1)
v3 = simd.bit_xor(v3, v0)
v3 = simd.bit_xor(simd.shl(v3, _ROT_16), simd.shr(v3, _ROT_16))
// c += d; b ^= c; b = ROTW12(b);
v2 = simd.add(v2, v3)
v1 = simd.bit_xor(v1, v2)
v1 = simd.bit_xor(simd.shl(v1, _ROT_12L), simd.shr(v1, _ROT_12R))
// a += b; d ^= a; d = ROTW8(d);
v0 = simd.add(v0, v1)
v3 = simd.bit_xor(v3, v0)
v3 = simd.bit_xor(simd.shl(v3, _ROT_8L), simd.shr(v3, _ROT_8R))
// c += d; b ^= c; b = ROTW7(b);
v2 = simd.add(v2, v3)
v1 = simd.bit_xor(v1, v2)
v1 = simd.bit_xor(simd.shl(v1, _ROT_7L), simd.shr(v1, _ROT_7R))
// b = ROTV1(b); c = ROTV2(c); d = ROTV3(d);
v1 = simd.shuffle(v1, v1, 1, 2, 3, 0, 5, 6, 7, 4)
v2 = simd.shuffle(v2, v2, 2, 3, 0, 1, 6, 7, 4, 5)
v3 = simd.shuffle(v3, v3, 3, 0, 1, 2, 7, 4, 5, 6)
// a += b; d ^= a; d = ROTW16(d);
v0 = simd.add(v0, v1)
v3 = simd.bit_xor(v3, v0)
v3 = simd.bit_xor(simd.shl(v3, _ROT_16), simd.shr(v3, _ROT_16))
// c += d; b ^= c; b = ROTW12(b);
v2 = simd.add(v2, v3)
v1 = simd.bit_xor(v1, v2)
v1 = simd.bit_xor(simd.shl(v1, _ROT_12L), simd.shr(v1, _ROT_12R))
// a += b; d ^= a; d = ROTW8(d);
v0 = simd.add(v0, v1)
v3 = simd.bit_xor(v3, v0)
v3 = simd.bit_xor(simd.shl(v3, _ROT_8L), simd.shr(v3, _ROT_8R))
// c += d; b ^= c; b = ROTW7(b);
v2 = simd.add(v2, v3)
v1 = simd.bit_xor(v1, v2)
v1 = simd.bit_xor(simd.shl(v1, _ROT_7L), simd.shr(v1, _ROT_7R))
// b = ROTV3(b); c = ROTV2(c); d = ROTV1(d);
v1 = simd.shuffle(v1, v1, 3, 0, 1, 2, 7, 4, 5, 6)
v2 = simd.shuffle(v2, v2, 2, 3, 0, 1, 6, 7, 4, 5)
v3 = simd.shuffle(v3, v3, 1, 2, 3, 0, 5, 6, 7, 4)
return v0, v1, v2, v3
}
@(private = "file")
_add_and_permute_state_simd256 :: #force_inline proc "contextless" (
v0, v1, v2, v3, s0, s1, s2, s3: simd.u32x8,
) -> (
simd.u32x8,
simd.u32x8,
simd.u32x8,
simd.u32x8,
) {
t0 := simd.add(v0, s0)
t1 := simd.add(v1, s1)
t2 := simd.add(v2, s2)
t3 := simd.add(v3, s3)
// Big Endian would byteswap here.
// Each of v0 .. v3 has 128-bits of keystream for 2 separate blocks.
// permute the state such that (r0, r1) contains block 0, and (r2, r3)
// contains block 1.
r0 := simd.shuffle(t0, t1, 0, 1, 2, 3, 8, 9, 10, 11)
r2 := simd.shuffle(t0, t1, 4, 5, 6, 7, 12, 13, 14, 15)
r1 := simd.shuffle(t2, t3, 0, 1, 2, 3, 8, 9, 10, 11)
r3 := simd.shuffle(t2, t3, 4, 5, 6, 7, 12, 13, 14, 15)
return r0, r1, r2, r3
}
@(private = "file")
_xor_simd256 :: #force_inline proc "contextless" (
src: [^]simd.u32x8,
v0, v1, v2, v3: simd.u32x8,
) -> (
simd.u32x8,
simd.u32x8,
simd.u32x8,
simd.u32x8,
) {
v0, v1, v2, v3 := v0, v1, v2, v3
v0 = simd.bit_xor(v0, intrinsics.unaligned_load((^simd.u32x8)(src[0:])))
v1 = simd.bit_xor(v1, intrinsics.unaligned_load((^simd.u32x8)(src[1:])))
v2 = simd.bit_xor(v2, intrinsics.unaligned_load((^simd.u32x8)(src[2:])))
v3 = simd.bit_xor(v3, intrinsics.unaligned_load((^simd.u32x8)(src[3:])))
return v0, v1, v2, v3
}
@(private = "file")
_xor_simd256_x1 :: #force_inline proc "contextless" (
src: [^]simd.u32x8,
v0, v1: simd.u32x8,
) -> (
simd.u32x8,
simd.u32x8,
) {
v0, v1 := v0, v1
v0 = simd.bit_xor(v0, intrinsics.unaligned_load((^simd.u32x8)(src[0:])))
v1 = simd.bit_xor(v1, intrinsics.unaligned_load((^simd.u32x8)(src[1:])))
return v0, v1
}
@(private = "file")
_store_simd256 :: #force_inline proc "contextless" (
dst: [^]simd.u32x8,
v0, v1, v2, v3: simd.u32x8,
) {
intrinsics.unaligned_store((^simd.u32x8)(dst[0:]), v0)
intrinsics.unaligned_store((^simd.u32x8)(dst[1:]), v1)
intrinsics.unaligned_store((^simd.u32x8)(dst[2:]), v2)
intrinsics.unaligned_store((^simd.u32x8)(dst[3:]), v3)
}
@(private = "file")
_store_simd256_x1 :: #force_inline proc "contextless" (
dst: [^]simd.u32x8,
v0, v1: simd.u32x8,
) {
intrinsics.unaligned_store((^simd.u32x8)(dst[0:]), v0)
intrinsics.unaligned_store((^simd.u32x8)(dst[1:]), v1)
}
@(enable_target_feature = "sse2,ssse3,avx,avx2")
stream_blocks :: proc(ctx: ^_chacha20.Context, dst, src: []byte, nr_blocks: int) {
// Enforce the maximum consumed keystream per IV.
_chacha20.check_counter_limit(ctx, nr_blocks)
dst_v := ([^]simd.u32x8)(raw_data(dst))
src_v := ([^]simd.u32x8)(raw_data(src))
x := &ctx._s
n := nr_blocks
// The state vector is an array of uint32s in native byte-order.
// Setup s0 .. s3 such that each register stores 2 copies of the
// state.
x_v := ([^]simd.u32x4)(raw_data(x))
t0 := intrinsics.unaligned_load((^simd.u32x4)(x_v[0:]))
t1 := intrinsics.unaligned_load((^simd.u32x4)(x_v[1:]))
t2 := intrinsics.unaligned_load((^simd.u32x4)(x_v[2:]))
t3 := intrinsics.unaligned_load((^simd.u32x4)(x_v[3:]))
s0 := simd.swizzle(t0, 0, 1, 2, 3, 0, 1, 2, 3)
s1 := simd.swizzle(t1, 0, 1, 2, 3, 0, 1, 2, 3)
s2 := simd.swizzle(t2, 0, 1, 2, 3, 0, 1, 2, 3)
s3 := simd.swizzle(t3, 0, 1, 2, 3, 0, 1, 2, 3)
// Advance the counter in the 2nd copy of the state by one.
s3 = transmute(simd.u32x8)simd.add(transmute(simd.u64x4)s3, _VEC_ZERO_ONE)
// 8 blocks at a time.
for ; n >= 8; n = n - 8 {
v0, v1, v2, v3 := s0, s1, s2, s3
s7 := transmute(simd.u32x8)simd.add(transmute(simd.u64x4)s3, _VEC_TWO)
v4, v5, v6, v7 := s0, s1, s2, s7
s11 := transmute(simd.u32x8)simd.add(transmute(simd.u64x4)s7, _VEC_TWO)
v8, v9, v10, v11 := s0, s1, s2, s11
s15 := transmute(simd.u32x8)simd.add(transmute(simd.u64x4)s11, _VEC_TWO)
v12, v13, v14, v15 := s0, s1, s2, s15
for i := _chacha20.ROUNDS; i > 0; i = i - 2 {
v0, v1, v2, v3 = _dq_round_simd256(v0, v1, v2, v3)
v4, v5, v6, v7 = _dq_round_simd256(v4, v5, v6, v7)
v8, v9, v10, v11 = _dq_round_simd256(v8, v9, v10, v11)
v12, v13, v14, v15 = _dq_round_simd256(v12, v13, v14, v15)
}
v0, v1, v2, v3 = _add_and_permute_state_simd256(v0, v1, v2, v3, s0, s1, s2, s3)
v4, v5, v6, v7 = _add_and_permute_state_simd256(v4, v5, v6, v7, s0, s1, s2, s7)
v8, v9, v10, v11 = _add_and_permute_state_simd256(v8, v9, v10, v11, s0, s1, s2, s11)
v12, v13, v14, v15 = _add_and_permute_state_simd256(v12, v13, v14, v15, s0, s1, s2, s15)
#no_bounds_check {
if src != nil {
v0, v1, v2, v3 = _xor_simd256(src_v, v0, v1, v2, v3)
v4, v5, v6, v7 = _xor_simd256(src_v[4:], v4, v5, v6, v7)
v8, v9, v10, v11 = _xor_simd256(src_v[8:], v8, v9, v10, v11)
v12, v13, v14, v15 = _xor_simd256(src_v[12:], v12, v13, v14, v15)
src_v = src_v[16:]
}
_store_simd256(dst_v, v0, v1, v2, v3)
_store_simd256(dst_v[4:], v4, v5, v6, v7)
_store_simd256(dst_v[8:], v8, v9, v10, v11)
_store_simd256(dst_v[12:], v12, v13, v14, v15)
dst_v = dst_v[16:]
}
s3 = transmute(simd.u32x8)simd.add(transmute(simd.u64x4)s15, _VEC_TWO)
}
// 2 (or 1) block at a time.
for ; n > 0; n = n - 2 {
v0, v1, v2, v3 := s0, s1, s2, s3
for i := _chacha20.ROUNDS; i > 0; i = i - 2 {
v0, v1, v2, v3 = _dq_round_simd256(v0, v1, v2, v3)
}
v0, v1, v2, v3 = _add_and_permute_state_simd256(v0, v1, v2, v3, s0, s1, s2, s3)
if n == 1 {
// Note: No need to advance src_v, dst_v, or increment the counter
// since this is guaranteed to be the final block.
#no_bounds_check {
if src != nil {
v0, v1 = _xor_simd256_x1(src_v, v0, v1)
}
_store_simd256_x1(dst_v, v0, v1)
}
break
}
#no_bounds_check {
if src != nil {
v0, v1, v2, v3 = _xor_simd256(src_v, v0, v1, v2, v3)
src_v = src_v[4:]
}
_store_simd256(dst_v, v0, v1, v2, v3)
dst_v = dst_v[4:]
}
s3 = transmute(simd.u32x8)simd.add(transmute(simd.u64x4)s3, _VEC_TWO)
}
// Write back the counter. Doing it this way, saves having to
// pull out the correct counter value from s3.
new_ctr := ((u64(ctx._s[13]) << 32) | u64(ctx._s[12])) + u64(nr_blocks)
ctx._s[12] = u32(new_ctr)
ctx._s[13] = u32(new_ctr >> 32)
}
@(enable_target_feature = "sse2,ssse3,avx")
hchacha20 :: proc "contextless" (dst, key, iv: []byte) {
// We can just enable AVX and call the simd128 code as going
// wider has 0 performance benefit, but VEX encoded instructions
// is nice.
#force_inline chacha_simd128.hchacha20(dst, key, iv)
}
@@ -0,0 +1,17 @@
#+build !amd64
package chacha20_simd256
import "base:intrinsics"
import "core:crypto/_chacha20"
is_performant :: proc "contextless" () -> bool {
return false
}
stream_blocks :: proc(ctx: ^_chacha20.Context, dst, src: []byte, nr_blocks: int) {
panic("crypto/chacha20: simd256 implementation unsupported")
}
hchacha20 :: proc "contextless" (dst, key, iv: []byte) {
intrinsics.trap()
}
+8 -6
View File
@@ -81,16 +81,18 @@ bytepad :: proc(ctx: ^Context, x_strings: [][]byte, w: int) {
// 2. while len(z) mod 8 0:
// z = z || 0
// 3. while (len(z)/8) mod w 0:
// 3. while (len(z)/8) mod w != 0:
// z = z || 00000000
z_len := u128(z_hi) << 64 | u128(z_lo)
z_rem := int(z_len % u128(w))
pad := _PAD[:w - z_rem]
if z_rem != 0 {
pad := _PAD[:w - z_rem]
// We just add the padding to the state, instead of returning z.
//
// 4. return z.
update(ctx, pad)
// We just add the padding to the state, instead of returning z.
//
// 4. return z.
update(ctx, pad)
}
}
encode_string :: #force_inline proc(ctx: ^Context, s: []byte) -> (u64, u64) {
+36
View File
@@ -0,0 +1,36 @@
package aead
// seal_oneshot encrypts the plaintext and authenticates the aad and ciphertext,
// with the provided algorithm, key, and iv, stores the output in dst and tag.
//
// dst and plaintext MUST alias exactly or not at all.
seal_oneshot :: proc(algo: Algorithm, dst, tag, key, iv, aad, plaintext: []byte, impl: Implementation = nil) {
ctx: Context
init(&ctx, algo, key, impl)
defer reset(&ctx)
seal_ctx(&ctx, dst, tag, iv, aad, plaintext)
}
// open authenticates the aad and ciphertext, and decrypts the ciphertext,
// with the provided algorithm, key, iv, and tag, and stores the output in dst,
// returning true iff the authentication was successful. If authentication
// fails, the destination buffer will be zeroed.
//
// dst and plaintext MUST alias exactly or not at all.
@(require_results)
open_oneshot :: proc(algo: Algorithm, dst, key, iv, aad, ciphertext, tag: []byte, impl: Implementation = nil) -> bool {
ctx: Context
init(&ctx, algo, key, impl)
defer reset(&ctx)
return open_ctx(&ctx, dst, iv, aad, ciphertext, tag)
}
seal :: proc {
seal_ctx,
seal_oneshot,
}
open :: proc {
open_ctx,
open_oneshot,
}
+57
View File
@@ -0,0 +1,57 @@
/*
package aead provides a generic interface to the supported Authenticated
Encryption with Associated Data algorithms.
Both a one-shot and context based interface are provided, with similar
usage. If multiple messages are to be sealed/opened via the same key,
the context based interface may be more efficient, depending on the
algorithm.
WARNING: Reusing the same key + iv to seal (encrypt) multiple messages
results in catastrophic loss of security for most algorithms.
Example:
package aead_example
import "core:bytes"
import "core:crypto"
import "core:crypto/aead"
main :: proc() {
algo := aead.Algorithm.XCHACHA20POLY1305
// The example added associated data, and plaintext.
aad_str := "Get your ass in gear boys."
pt_str := "They're immanetizing the Eschaton."
aad := transmute([]byte)aad_str
plaintext := transmute([]byte)pt_str
pt_len := len(plaintext)
// Generate a random key for the purposes of illustration.
key := make([]byte, aead.KEY_SIZES[algo])
defer delete(key)
crypto.rand_bytes(key)
// `ciphertext || tag`, is a common way data is transmitted, so
// demonstrate that.
buf := make([]byte, pt_len + aead.TAG_SIZES[algo])
defer delete(buf)
ciphertext, tag := buf[:pt_len], buf[pt_len:]
// Seal the AAD + Plaintext.
iv := make([]byte, aead.IV_SIZES[algo])
defer delete(iv)
crypto.rand_bytes(iv) // Random IVs are safe with XChaCha20-Poly1305.
aead.seal(algo, ciphertext, tag, key, iv, aad, plaintext)
// Open the AAD + Ciphertext.
opened_pt := buf[:pt_len]
if ok := aead.open(algo, opened_pt, key, iv, aad, ciphertext, tag); !ok {
panic("aead example: failed to open")
}
assert(bytes.equal(opened_pt, plaintext))
}
*/
package aead
+187
View File
@@ -0,0 +1,187 @@
package aead
import "core:crypto/aes"
import "core:crypto/chacha20"
import "core:crypto/chacha20poly1305"
import "core:reflect"
// Implementation is an AEAD implementation. Most callers will not need
// to use this as the package will automatically select the most performant
// implementation available.
Implementation :: union {
aes.Implementation,
chacha20.Implementation,
}
// MAX_TAG_SIZE is the maximum size tag that can be returned by any of the
// Algorithms supported via this package.
MAX_TAG_SIZE :: 16
// Algorithm is the algorithm identifier associated with a given Context.
Algorithm :: enum {
Invalid,
AES_GCM_128,
AES_GCM_192,
AES_GCM_256,
CHACHA20POLY1305,
XCHACHA20POLY1305,
}
// ALGORITM_NAMES is the Agorithm to algorithm name string.
ALGORITHM_NAMES := [Algorithm]string {
.Invalid = "Invalid",
.AES_GCM_128 = "AES-GCM-128",
.AES_GCM_192 = "AES-GCM-192",
.AES_GCM_256 = "AES-GCM-256",
.CHACHA20POLY1305 = "chacha20poly1305",
.XCHACHA20POLY1305 = "xchacha20poly1305",
}
// TAG_SIZES is the Algorithm to tag size in bytes.
TAG_SIZES := [Algorithm]int {
.Invalid = 0,
.AES_GCM_128 = aes.GCM_TAG_SIZE,
.AES_GCM_192 = aes.GCM_TAG_SIZE,
.AES_GCM_256 = aes.GCM_TAG_SIZE,
.CHACHA20POLY1305 = chacha20poly1305.TAG_SIZE,
.XCHACHA20POLY1305 = chacha20poly1305.TAG_SIZE,
}
// KEY_SIZES is the Algorithm to key size in bytes.
KEY_SIZES := [Algorithm]int {
.Invalid = 0,
.AES_GCM_128 = aes.KEY_SIZE_128,
.AES_GCM_192 = aes.KEY_SIZE_192,
.AES_GCM_256 = aes.KEY_SIZE_256,
.CHACHA20POLY1305 = chacha20poly1305.KEY_SIZE,
.XCHACHA20POLY1305 = chacha20poly1305.KEY_SIZE,
}
// IV_SIZES is the Algorithm to initialization vector size in bytes.
//
// Note: Some algorithms (such as AES-GCM) support variable IV sizes.
IV_SIZES := [Algorithm]int {
.Invalid = 0,
.AES_GCM_128 = aes.GCM_IV_SIZE,
.AES_GCM_192 = aes.GCM_IV_SIZE,
.AES_GCM_256 = aes.GCM_IV_SIZE,
.CHACHA20POLY1305 = chacha20poly1305.IV_SIZE,
.XCHACHA20POLY1305 = chacha20poly1305.XIV_SIZE,
}
// Context is a concrete instantiation of a specific AEAD algorithm.
Context :: struct {
_algo: Algorithm,
_impl: union {
aes.Context_GCM,
chacha20poly1305.Context,
},
}
@(private)
_IMPL_IDS := [Algorithm]typeid {
.Invalid = nil,
.AES_GCM_128 = typeid_of(aes.Context_GCM),
.AES_GCM_192 = typeid_of(aes.Context_GCM),
.AES_GCM_256 = typeid_of(aes.Context_GCM),
.CHACHA20POLY1305 = typeid_of(chacha20poly1305.Context),
.XCHACHA20POLY1305 = typeid_of(chacha20poly1305.Context),
}
// init initializes a Context with a specific AEAD Algorithm.
init :: proc(ctx: ^Context, algorithm: Algorithm, key: []byte, impl: Implementation = nil) {
if ctx._impl != nil {
reset(ctx)
}
if len(key) != KEY_SIZES[algorithm] {
panic("crypto/aead: invalid key size")
}
// Directly specialize the union by setting the type ID (save a copy).
reflect.set_union_variant_typeid(
ctx._impl,
_IMPL_IDS[algorithm],
)
switch algorithm {
case .AES_GCM_128, .AES_GCM_192, .AES_GCM_256:
impl_ := impl != nil ? impl.(aes.Implementation) : aes.DEFAULT_IMPLEMENTATION
aes.init_gcm(&ctx._impl.(aes.Context_GCM), key, impl_)
case .CHACHA20POLY1305:
impl_ := impl != nil ? impl.(chacha20.Implementation) : chacha20.DEFAULT_IMPLEMENTATION
chacha20poly1305.init(&ctx._impl.(chacha20poly1305.Context), key, impl_)
case .XCHACHA20POLY1305:
impl_ := impl != nil ? impl.(chacha20.Implementation) : chacha20.DEFAULT_IMPLEMENTATION
chacha20poly1305.init_xchacha(&ctx._impl.(chacha20poly1305.Context), key, impl_)
case .Invalid:
panic("crypto/aead: uninitialized algorithm")
case:
panic("crypto/aead: invalid algorithm")
}
ctx._algo = algorithm
}
// seal_ctx encrypts the plaintext and authenticates the aad and ciphertext,
// with the provided Context and iv, stores the output in dst and tag.
//
// dst and plaintext MUST alias exactly or not at all.
seal_ctx :: proc(ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) {
switch &impl in ctx._impl {
case aes.Context_GCM:
aes.seal_gcm(&impl, dst, tag, iv, aad, plaintext)
case chacha20poly1305.Context:
chacha20poly1305.seal(&impl, dst, tag, iv, aad, plaintext)
case:
panic("crypto/aead: uninitialized algorithm")
}
}
// open_ctx authenticates the aad and ciphertext, and decrypts the ciphertext,
// with the provided Context, iv, and tag, and stores the output in dst,
// returning true iff the authentication was successful. If authentication
// fails, the destination buffer will be zeroed.
//
// dst and plaintext MUST alias exactly or not at all.
@(require_results)
open_ctx :: proc(ctx: ^Context, dst, iv, aad, ciphertext, tag: []byte) -> bool {
switch &impl in ctx._impl {
case aes.Context_GCM:
return aes.open_gcm(&impl, dst, iv, aad, ciphertext, tag)
case chacha20poly1305.Context:
return chacha20poly1305.open(&impl, dst, iv, aad, ciphertext, tag)
case:
panic("crypto/aead: uninitialized algorithm")
}
}
// reset sanitizes the Context. The Context must be re-initialized to
// be used again.
reset :: proc(ctx: ^Context) {
switch &impl in ctx._impl {
case aes.Context_GCM:
aes.reset_gcm(&impl)
case chacha20poly1305.Context:
chacha20poly1305.reset(&impl)
case:
// Calling reset repeatedly is fine.
}
ctx._algo = .Invalid
ctx._impl = nil
}
// algorithm returns the Algorithm used by a Context instance.
algorithm :: proc(ctx: ^Context) -> Algorithm {
return ctx._algo
}
// iv_size returns the IV size of a Context instance in bytes.
iv_size :: proc(ctx: ^Context) -> int {
return IV_SIZES[ctx._algo]
}
// tag_size returns the tag size of a Context instance in bytes.
tag_size :: proc(ctx: ^Context) -> int {
return TAG_SIZES[ctx._algo]
}
+3 -4
View File
@@ -2,11 +2,10 @@
package aes implements the AES block cipher and some common modes.
See:
- https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197-upd1.pdf
- https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf
- https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf
- [[ https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197-upd1.pdf ]]
- [[ https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf ]]
- [[ https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf ]]
*/
package aes
import "core:crypto/_aes"
+20 -18
View File
@@ -1,5 +1,6 @@
package aes
import "core:bytes"
import "core:crypto/_aes/ct64"
import "core:encoding/endian"
import "core:math/bits"
@@ -19,7 +20,7 @@ Context_CTR :: struct {
}
// init_ctr initializes a Context_CTR with the provided key and IV.
init_ctr :: proc(ctx: ^Context_CTR, key, iv: []byte, impl := Implementation.Hardware) {
init_ctr :: proc(ctx: ^Context_CTR, key, iv: []byte, impl := DEFAULT_IMPLEMENTATION) {
if len(iv) != CTR_IV_SIZE {
panic("crypto/aes: invalid CTR IV size")
}
@@ -37,15 +38,16 @@ init_ctr :: proc(ctx: ^Context_CTR, key, iv: []byte, impl := Implementation.Hard
xor_bytes_ctr :: proc(ctx: ^Context_CTR, dst, src: []byte) {
assert(ctx._is_initialized)
// TODO: Enforcing that dst and src alias exactly or not at all
// is a good idea, though odd aliasing should be extremely uncommon.
src, dst := src, dst
if dst_len := len(dst); dst_len < len(src) {
src = src[:dst_len]
}
for remaining := len(src); remaining > 0; {
if bytes.alias_inexactly(dst, src) {
panic("crypto/aes: dst and src alias inexactly")
}
#no_bounds_check for remaining := len(src); remaining > 0; {
// Process multiple blocks at once
if ctx._off == BLOCK_SIZE {
if nr_blocks := remaining / BLOCK_SIZE; nr_blocks > 0 {
@@ -83,7 +85,7 @@ keystream_bytes_ctr :: proc(ctx: ^Context_CTR, dst: []byte) {
assert(ctx._is_initialized)
dst := dst
for remaining := len(dst); remaining > 0; {
#no_bounds_check for remaining := len(dst); remaining > 0; {
// Process multiple blocks at once
if ctx._off == BLOCK_SIZE {
if nr_blocks := remaining / BLOCK_SIZE; nr_blocks > 0 {
@@ -123,8 +125,8 @@ reset_ctr :: proc "contextless" (ctx: ^Context_CTR) {
ctx._is_initialized = false
}
@(private)
ctr_blocks :: proc(ctx: ^Context_CTR, dst, src: []byte, nr_blocks: int) {
@(private = "file")
ctr_blocks :: proc(ctx: ^Context_CTR, dst, src: []byte, nr_blocks: int) #no_bounds_check {
// Use the optimized hardware implementation if available.
if _, is_hw := ctx._impl.(Context_Impl_Hardware); is_hw {
ctr_blocks_hw(ctx, dst, src, nr_blocks)
@@ -183,17 +185,17 @@ xor_blocks :: #force_inline proc "contextless" (dst, src: []byte, blocks: [][]by
// performance of this implementation matters to where that
// optimization would be worth it, use chacha20poly1305, or a
// CPU that isn't e-waste.
if src != nil {
#no_bounds_check {
for i in 0 ..< len(blocks) {
off := i * BLOCK_SIZE
for j in 0 ..< BLOCK_SIZE {
blocks[i][j] ~= src[off + j]
#no_bounds_check {
if src != nil {
for i in 0 ..< len(blocks) {
off := i * BLOCK_SIZE
for j in 0 ..< BLOCK_SIZE {
blocks[i][j] ~= src[off + j]
}
}
}
}
for i in 0 ..< len(blocks) {
copy(dst[i * BLOCK_SIZE:], blocks[i])
}
}
for i in 0 ..< len(blocks) {
copy(dst[i * BLOCK_SIZE:], blocks[i])
}
}
+151
View File
@@ -0,0 +1,151 @@
#+build amd64
package aes
import "base:intrinsics"
import "core:crypto/_aes"
import "core:math/bits"
import "core:mem"
import "core:simd/x86"
@(private)
CTR_STRIDE_HW :: 4
@(private)
CTR_STRIDE_BYTES_HW :: CTR_STRIDE_HW * BLOCK_SIZE
@(private, enable_target_feature = "sse2,aes")
ctr_blocks_hw :: proc(ctx: ^Context_CTR, dst, src: []byte, nr_blocks: int) #no_bounds_check {
hw_ctx := ctx._impl.(Context_Impl_Hardware)
sks: [15]x86.__m128i = ---
for i in 0 ..= hw_ctx._num_rounds {
sks[i] = intrinsics.unaligned_load((^x86.__m128i)(&hw_ctx._sk_exp_enc[i]))
}
hw_inc_ctr := #force_inline proc "contextless" (hi, lo: u64) -> (x86.__m128i, u64, u64) {
ret := x86.__m128i{
i64(intrinsics.byte_swap(hi)),
i64(intrinsics.byte_swap(lo)),
}
hi, lo := hi, lo
carry: u64
lo, carry = bits.add_u64(lo, 1, 0)
hi, _ = bits.add_u64(hi, 0, carry)
return ret, hi, lo
}
// The latency of AESENC depends on mfg and microarchitecture:
// - 7 -> up to Broadwell
// - 4 -> AMD and Skylake - Cascade Lake
// - 3 -> Ice Lake and newer
//
// This implementation does 4 blocks at once, since performance
// should be "adequate" across most CPUs.
src, dst := src, dst
nr_blocks := nr_blocks
ctr_hi, ctr_lo := ctx._ctr_hi, ctx._ctr_lo
blks: [CTR_STRIDE_HW]x86.__m128i = ---
for nr_blocks >= CTR_STRIDE_HW {
#unroll for i in 0..< CTR_STRIDE_HW {
blks[i], ctr_hi, ctr_lo = hw_inc_ctr(ctr_hi, ctr_lo)
}
#unroll for i in 0 ..< CTR_STRIDE_HW {
blks[i] = x86._mm_xor_si128(blks[i], sks[0])
}
#unroll for i in 1 ..= 9 {
#unroll for j in 0 ..< CTR_STRIDE_HW {
blks[j] = x86._mm_aesenc_si128(blks[j], sks[i])
}
}
switch hw_ctx._num_rounds {
case _aes.ROUNDS_128:
#unroll for i in 0 ..< CTR_STRIDE_HW {
blks[i] = x86._mm_aesenclast_si128(blks[i], sks[10])
}
case _aes.ROUNDS_192:
#unroll for i in 10 ..= 11 {
#unroll for j in 0 ..< CTR_STRIDE_HW {
blks[j] = x86._mm_aesenc_si128(blks[j], sks[i])
}
}
#unroll for i in 0 ..< CTR_STRIDE_HW {
blks[i] = x86._mm_aesenclast_si128(blks[i], sks[12])
}
case _aes.ROUNDS_256:
#unroll for i in 10 ..= 13 {
#unroll for j in 0 ..< CTR_STRIDE_HW {
blks[j] = x86._mm_aesenc_si128(blks[j], sks[i])
}
}
#unroll for i in 0 ..< CTR_STRIDE_HW {
blks[i] = x86._mm_aesenclast_si128(blks[i], sks[14])
}
}
xor_blocks_hw(dst, src, blks[:])
if src != nil {
src = src[CTR_STRIDE_BYTES_HW:]
}
dst = dst[CTR_STRIDE_BYTES_HW:]
nr_blocks -= CTR_STRIDE_HW
}
// Handle the remainder.
for nr_blocks > 0 {
blks[0], ctr_hi, ctr_lo = hw_inc_ctr(ctr_hi, ctr_lo)
blks[0] = x86._mm_xor_si128(blks[0], sks[0])
#unroll for i in 1 ..= 9 {
blks[0] = x86._mm_aesenc_si128(blks[0], sks[i])
}
switch hw_ctx._num_rounds {
case _aes.ROUNDS_128:
blks[0] = x86._mm_aesenclast_si128(blks[0], sks[10])
case _aes.ROUNDS_192:
#unroll for i in 10 ..= 11 {
blks[0] = x86._mm_aesenc_si128(blks[0], sks[i])
}
blks[0] = x86._mm_aesenclast_si128(blks[0], sks[12])
case _aes.ROUNDS_256:
#unroll for i in 10 ..= 13 {
blks[0] = x86._mm_aesenc_si128(blks[0], sks[i])
}
blks[0] = x86._mm_aesenclast_si128(blks[0], sks[14])
}
xor_blocks_hw(dst, src, blks[:1])
if src != nil {
src = src[BLOCK_SIZE:]
}
dst = dst[BLOCK_SIZE:]
nr_blocks -= 1
}
// Write back the counter.
ctx._ctr_hi, ctx._ctr_lo = ctr_hi, ctr_lo
mem.zero_explicit(&blks, size_of(blks))
mem.zero_explicit(&sks, size_of(sks))
}
@(private, enable_target_feature = "sse2")
xor_blocks_hw :: proc(dst, src: []byte, blocks: []x86.__m128i) {
#no_bounds_check {
if src != nil {
for i in 0 ..< len(blocks) {
off := i * BLOCK_SIZE
tmp := intrinsics.unaligned_load((^x86.__m128i)(raw_data(src[off:])))
blocks[i] = x86._mm_xor_si128(blocks[i], tmp)
}
}
for i in 0 ..< len(blocks) {
intrinsics.unaligned_store((^x86.__m128i)(raw_data(dst[i * BLOCK_SIZE:])), blocks[i])
}
}
}
+1 -1
View File
@@ -12,7 +12,7 @@ Context_ECB :: struct {
}
// init_ecb initializes a Context_ECB with the provided key.
init_ecb :: proc(ctx: ^Context_ECB, key: []byte, impl := Implementation.Hardware) {
init_ecb :: proc(ctx: ^Context_ECB, key: []byte, impl := DEFAULT_IMPLEMENTATION) {
init_impl(&ctx._impl, key, impl)
ctx._is_initialized = true
}
+58
View File
@@ -0,0 +1,58 @@
#+build amd64
package aes
import "base:intrinsics"
import "core:crypto/_aes"
import "core:simd/x86"
@(private, enable_target_feature = "sse2,aes")
encrypt_block_hw :: proc(ctx: ^Context_Impl_Hardware, dst, src: []byte) {
blk := intrinsics.unaligned_load((^x86.__m128i)(raw_data(src)))
blk = x86._mm_xor_si128(blk, intrinsics.unaligned_load((^x86.__m128i)(&ctx._sk_exp_enc[0])))
#unroll for i in 1 ..= 9 {
blk = x86._mm_aesenc_si128(blk, intrinsics.unaligned_load((^x86.__m128i)(&ctx._sk_exp_enc[i])))
}
switch ctx._num_rounds {
case _aes.ROUNDS_128:
blk = x86._mm_aesenclast_si128(blk, intrinsics.unaligned_load((^x86.__m128i)(&ctx._sk_exp_enc[10])))
case _aes.ROUNDS_192:
#unroll for i in 10 ..= 11 {
blk = x86._mm_aesenc_si128(blk, intrinsics.unaligned_load((^x86.__m128i)(&ctx._sk_exp_enc[i])))
}
blk = x86._mm_aesenclast_si128(blk, intrinsics.unaligned_load((^x86.__m128i)(&ctx._sk_exp_enc[12])))
case _aes.ROUNDS_256:
#unroll for i in 10 ..= 13 {
blk = x86._mm_aesenc_si128(blk, intrinsics.unaligned_load((^x86.__m128i)(&ctx._sk_exp_enc[i])))
}
blk = x86._mm_aesenclast_si128(blk, intrinsics.unaligned_load((^x86.__m128i)(&ctx._sk_exp_enc[14])))
}
intrinsics.unaligned_store((^x86.__m128i)(raw_data(dst)), blk)
}
@(private, enable_target_feature = "sse2,aes")
decrypt_block_hw :: proc(ctx: ^Context_Impl_Hardware, dst, src: []byte) {
blk := intrinsics.unaligned_load((^x86.__m128i)(raw_data(src)))
blk = x86._mm_xor_si128(blk, intrinsics.unaligned_load((^x86.__m128i)(&ctx._sk_exp_dec[0])))
#unroll for i in 1 ..= 9 {
blk = x86._mm_aesdec_si128(blk, intrinsics.unaligned_load((^x86.__m128i)(&ctx._sk_exp_dec[i])))
}
switch ctx._num_rounds {
case _aes.ROUNDS_128:
blk = x86._mm_aesdeclast_si128(blk, intrinsics.unaligned_load((^x86.__m128i)(&ctx._sk_exp_dec[10])))
case _aes.ROUNDS_192:
#unroll for i in 10 ..= 11 {
blk = x86._mm_aesdec_si128(blk, intrinsics.unaligned_load((^x86.__m128i)(&ctx._sk_exp_dec[i])))
}
blk = x86._mm_aesdeclast_si128(blk, intrinsics.unaligned_load((^x86.__m128i)(&ctx._sk_exp_dec[12])))
case _aes.ROUNDS_256:
#unroll for i in 10 ..= 13 {
blk = x86._mm_aesdec_si128(blk, intrinsics.unaligned_load((^x86.__m128i)(&ctx._sk_exp_dec[i])))
}
blk = x86._mm_aesdeclast_si128(blk, intrinsics.unaligned_load((^x86.__m128i)(&ctx._sk_exp_dec[14])))
}
intrinsics.unaligned_store((^x86.__m128i)(raw_data(dst)), blk)
}
+60 -43
View File
@@ -1,13 +1,16 @@
package aes
import "core:bytes"
import "core:crypto"
import "core:crypto/_aes"
import "core:crypto/_aes/ct64"
import "core:encoding/endian"
import "core:mem"
// GCM_NONCE_SIZE is the size of the GCM nonce in bytes.
GCM_NONCE_SIZE :: 12
// GCM_IV_SIZE is the default size of the GCM IV in bytes.
GCM_IV_SIZE :: 12
// GCM_IV_SIZE_MAX is the maximum size of the GCM IV in bytes.
GCM_IV_SIZE_MAX :: 0x2000000000000000 // floor((2^64 - 1) / 8) bits
// GCM_TAG_SIZE is the size of a GCM tag in bytes.
GCM_TAG_SIZE :: _aes.GHASH_TAG_SIZE
@@ -23,69 +26,79 @@ Context_GCM :: struct {
}
// init_gcm initializes a Context_GCM with the provided key.
init_gcm :: proc(ctx: ^Context_GCM, key: []byte, impl := Implementation.Hardware) {
init_gcm :: proc(ctx: ^Context_GCM, key: []byte, impl := DEFAULT_IMPLEMENTATION) {
init_impl(&ctx._impl, key, impl)
ctx._is_initialized = true
}
// seal_gcm encrypts the plaintext and authenticates the aad and ciphertext,
// with the provided Context_GCM and nonce, stores the output in dst and tag.
// with the provided Context_GCM and iv, stores the output in dst and tag.
//
// dst and plaintext MUST alias exactly or not at all.
seal_gcm :: proc(ctx: ^Context_GCM, dst, tag, nonce, aad, plaintext: []byte) {
seal_gcm :: proc(ctx: ^Context_GCM, dst, tag, iv, aad, plaintext: []byte) {
assert(ctx._is_initialized)
gcm_validate_common_slice_sizes(tag, nonce, aad, plaintext)
gcm_validate_common_slice_sizes(tag, iv, aad, plaintext)
if len(dst) != len(plaintext) {
panic("crypto/aes: invalid destination ciphertext size")
}
if bytes.alias_inexactly(dst, plaintext) {
panic("crypto/aes: dst and plaintext alias inexactly")
}
if impl, is_hw := ctx._impl.(Context_Impl_Hardware); is_hw {
gcm_seal_hw(&impl, dst, tag, nonce, aad, plaintext)
gcm_seal_hw(&impl, dst, tag, iv, aad, plaintext)
return
}
h: [_aes.GHASH_KEY_SIZE]byte
j0: [_aes.GHASH_BLOCK_SIZE]byte
j0_enc: [_aes.GHASH_BLOCK_SIZE]byte
s: [_aes.GHASH_TAG_SIZE]byte
init_ghash_ct64(ctx, &h, &j0, nonce)
init_ghash_ct64(ctx, &h, &j0, &j0_enc, iv)
// Note: Our GHASH implementation handles appending padding.
ct64.ghash(s[:], h[:], aad)
gctr_ct64(ctx, dst, &s, plaintext, &h, nonce, true)
final_ghash_ct64(&s, &h, &j0, len(aad), len(plaintext))
gctr_ct64(ctx, dst, &s, plaintext, &h, &j0, true)
final_ghash_ct64(&s, &h, &j0_enc, len(aad), len(plaintext))
copy(tag, s[:])
mem.zero_explicit(&h, len(h))
mem.zero_explicit(&j0, len(j0))
mem.zero_explicit(&j0_enc, len(j0_enc))
}
// open_gcm authenticates the aad and ciphertext, and decrypts the ciphertext,
// with the provided Context_GCM, nonce, and tag, and stores the output in dst,
// with the provided Context_GCM, iv, and tag, and stores the output in dst,
// returning true iff the authentication was successful. If authentication
// fails, the destination buffer will be zeroed.
//
// dst and plaintext MUST alias exactly or not at all.
open_gcm :: proc(ctx: ^Context_GCM, dst, nonce, aad, ciphertext, tag: []byte) -> bool {
@(require_results)
open_gcm :: proc(ctx: ^Context_GCM, dst, iv, aad, ciphertext, tag: []byte) -> bool {
assert(ctx._is_initialized)
gcm_validate_common_slice_sizes(tag, nonce, aad, ciphertext)
gcm_validate_common_slice_sizes(tag, iv, aad, ciphertext)
if len(dst) != len(ciphertext) {
panic("crypto/aes: invalid destination plaintext size")
}
if bytes.alias_inexactly(dst, ciphertext) {
panic("crypto/aes: dst and ciphertext alias inexactly")
}
if impl, is_hw := ctx._impl.(Context_Impl_Hardware); is_hw {
return gcm_open_hw(&impl, dst, nonce, aad, ciphertext, tag)
return gcm_open_hw(&impl, dst, iv, aad, ciphertext, tag)
}
h: [_aes.GHASH_KEY_SIZE]byte
j0: [_aes.GHASH_BLOCK_SIZE]byte
j0_enc: [_aes.GHASH_BLOCK_SIZE]byte
s: [_aes.GHASH_TAG_SIZE]byte
init_ghash_ct64(ctx, &h, &j0, nonce)
init_ghash_ct64(ctx, &h, &j0, &j0_enc, iv)
ct64.ghash(s[:], h[:], aad)
gctr_ct64(ctx, dst, &s, ciphertext, &h, nonce, false)
final_ghash_ct64(&s, &h, &j0, len(aad), len(ciphertext))
gctr_ct64(ctx, dst, &s, ciphertext, &h, &j0, false)
final_ghash_ct64(&s, &h, &j0_enc, len(aad), len(ciphertext))
ok := crypto.compare_constant_time(s[:], tag) == 1
if !ok {
@@ -94,32 +107,28 @@ open_gcm :: proc(ctx: ^Context_GCM, dst, nonce, aad, ciphertext, tag: []byte) ->
mem.zero_explicit(&h, len(h))
mem.zero_explicit(&j0, len(j0))
mem.zero_explicit(&j0_enc, len(j0_enc))
mem.zero_explicit(&s, len(s))
return ok
}
// reset_ctr sanitizes the Context_GCM. The Context_GCM must be
// reset_gcm sanitizes the Context_GCM. The Context_GCM must be
// re-initialized to be used again.
reset_gcm :: proc "contextless" (ctx: ^Context_GCM) {
reset_impl(&ctx._impl)
ctx._is_initialized = false
}
@(private)
gcm_validate_common_slice_sizes :: proc(tag, nonce, aad, text: []byte) {
@(private = "file")
gcm_validate_common_slice_sizes :: proc(tag, iv, aad, text: []byte) {
if len(tag) != GCM_TAG_SIZE {
panic("crypto/aes: invalid GCM tag size")
}
// The specification supports nonces in the range [1, 2^64) bits
// however per NIST SP 800-38D 5.2.1.1:
//
// > For IVs, it is recommended that implementations restrict support
// > to the length of 96 bits, to promote interoperability, efficiency,
// > and simplicity of design.
if len(nonce) != GCM_NONCE_SIZE {
panic("crypto/aes: invalid GCM nonce size")
// The specification supports IVs in the range [1, 2^64) bits.
if l := len(iv); l == 0 || u64(l) >= GCM_IV_SIZE_MAX {
panic("crypto/aes: invalid GCM IV size")
}
if aad_len := u64(len(aad)); aad_len > GCM_A_MAX {
@@ -135,19 +144,33 @@ init_ghash_ct64 :: proc(
ctx: ^Context_GCM,
h: ^[_aes.GHASH_KEY_SIZE]byte,
j0: ^[_aes.GHASH_BLOCK_SIZE]byte,
nonce: []byte,
j0_enc: ^[_aes.GHASH_BLOCK_SIZE]byte,
iv: []byte,
) {
impl := &ctx._impl.(ct64.Context)
// 1. Let H = CIPH(k, 0^128)
ct64.encrypt_block(impl, h[:], h[:])
// Define a block, J0, as follows:
if l := len(iv); l == GCM_IV_SIZE {
// if len(IV) = 96, then let J0 = IV || 0^31 || 1
copy(j0[:], iv)
j0[_aes.GHASH_BLOCK_SIZE - 1] = 1
} else {
// If len(IV) != 96, then let s = 128 ceil(len(IV)/128) - len(IV),
// and let J0 = GHASHH(IV || 0^(s+64) || ceil(len(IV))^64).
ct64.ghash(j0[:], h[:], iv)
tmp: [_aes.GHASH_BLOCK_SIZE]byte
endian.unchecked_put_u64be(tmp[8:], u64(l) * 8)
ct64.ghash(j0[:], h[:], tmp[:])
}
// ECB encrypt j0, so that we can just XOR with the tag. In theory
// this could be processed along with the final GCTR block, to
// potentially save a call to AES-ECB, but... just use AES-NI.
copy(j0[:], nonce)
j0[_aes.GHASH_BLOCK_SIZE - 1] = 1
ct64.encrypt_block(impl, j0[:], j0[:])
ct64.encrypt_block(impl, j0_enc[:], j0[:])
}
@(private = "file")
@@ -175,33 +198,27 @@ gctr_ct64 :: proc(
s: ^[_aes.GHASH_BLOCK_SIZE]byte,
src: []byte,
h: ^[_aes.GHASH_KEY_SIZE]byte,
nonce: []byte,
iv: ^[_aes.GHASH_BLOCK_SIZE]byte,
is_seal: bool,
) {
) #no_bounds_check {
ct64_inc_ctr32 := #force_inline proc "contextless" (dst: []byte, ctr: u32) -> u32 {
endian.unchecked_put_u32be(dst[12:], ctr)
return ctr + 1
}
// 2. Define a block J_0 as follows:
// if len(IV) = 96, then let J0 = IV || 0^31 || 1
//
// Note: We only support 96 bit IVs.
// Setup the counter blocks.
tmp, tmp2: [ct64.STRIDE][BLOCK_SIZE]byte = ---, ---
ctrs, blks: [ct64.STRIDE][]byte = ---, ---
ctr: u32 = 2
ctr := endian.unchecked_get_u32be(iv[GCM_IV_SIZE:]) + 1
for i in 0 ..< ct64.STRIDE {
// Setup scratch space for the keystream.
blks[i] = tmp2[i][:]
// Pre-copy the IV to all the counter blocks.
ctrs[i] = tmp[i][:]
copy(ctrs[i], nonce)
copy(ctrs[i], iv[:GCM_IV_SIZE])
}
// We stitch the GCTR and GHASH operations together, so that only
// one pass over the ciphertext is required.
impl := &ctx._impl.(ct64.Context)
src, dst := src, dst
+243
View File
@@ -0,0 +1,243 @@
#+build amd64
package aes
import "base:intrinsics"
import "core:crypto"
import "core:crypto/_aes"
import "core:crypto/_aes/hw_intel"
import "core:encoding/endian"
import "core:mem"
import "core:simd/x86"
@(private)
gcm_seal_hw :: proc(ctx: ^Context_Impl_Hardware, dst, tag, iv, aad, plaintext: []byte) {
h: [_aes.GHASH_KEY_SIZE]byte
j0: [_aes.GHASH_BLOCK_SIZE]byte
j0_enc: [_aes.GHASH_BLOCK_SIZE]byte
s: [_aes.GHASH_TAG_SIZE]byte
init_ghash_hw(ctx, &h, &j0, &j0_enc, iv)
// Note: Our GHASH implementation handles appending padding.
hw_intel.ghash(s[:], h[:], aad)
gctr_hw(ctx, dst, &s, plaintext, &h, &j0, true)
final_ghash_hw(&s, &h, &j0_enc, len(aad), len(plaintext))
copy(tag, s[:])
mem.zero_explicit(&h, len(h))
mem.zero_explicit(&j0, len(j0))
mem.zero_explicit(&j0_enc, len(j0_enc))
}
@(private)
gcm_open_hw :: proc(ctx: ^Context_Impl_Hardware, dst, iv, aad, ciphertext, tag: []byte) -> bool {
h: [_aes.GHASH_KEY_SIZE]byte
j0: [_aes.GHASH_BLOCK_SIZE]byte
j0_enc: [_aes.GHASH_BLOCK_SIZE]byte
s: [_aes.GHASH_TAG_SIZE]byte
init_ghash_hw(ctx, &h, &j0, &j0_enc, iv)
hw_intel.ghash(s[:], h[:], aad)
gctr_hw(ctx, dst, &s, ciphertext, &h, &j0, false)
final_ghash_hw(&s, &h, &j0_enc, len(aad), len(ciphertext))
ok := crypto.compare_constant_time(s[:], tag) == 1
if !ok {
mem.zero_explicit(raw_data(dst), len(dst))
}
mem.zero_explicit(&h, len(h))
mem.zero_explicit(&j0, len(j0))
mem.zero_explicit(&j0_enc, len(j0_enc))
mem.zero_explicit(&s, len(s))
return ok
}
@(private = "file")
init_ghash_hw :: proc(
ctx: ^Context_Impl_Hardware,
h: ^[_aes.GHASH_KEY_SIZE]byte,
j0: ^[_aes.GHASH_BLOCK_SIZE]byte,
j0_enc: ^[_aes.GHASH_BLOCK_SIZE]byte,
iv: []byte,
) {
// 1. Let H = CIPH(k, 0^128)
encrypt_block_hw(ctx, h[:], h[:])
// Define a block, J0, as follows:
if l := len(iv); l == GCM_IV_SIZE {
// if len(IV) = 96, then let J0 = IV || 0^31 || 1
copy(j0[:], iv)
j0[_aes.GHASH_BLOCK_SIZE - 1] = 1
} else {
// If len(IV) != 96, then let s = 128 ceil(len(IV)/128) - len(IV),
// and let J0 = GHASHH(IV || 0^(s+64) || ceil(len(IV))^64).
hw_intel.ghash(j0[:], h[:], iv)
tmp: [_aes.GHASH_BLOCK_SIZE]byte
endian.unchecked_put_u64be(tmp[8:], u64(l) * 8)
hw_intel.ghash(j0[:], h[:], tmp[:])
}
// ECB encrypt j0, so that we can just XOR with the tag.
encrypt_block_hw(ctx, j0_enc[:], j0[:])
}
@(private = "file", enable_target_feature = "sse2")
final_ghash_hw :: proc(
s: ^[_aes.GHASH_BLOCK_SIZE]byte,
h: ^[_aes.GHASH_KEY_SIZE]byte,
j0: ^[_aes.GHASH_BLOCK_SIZE]byte,
a_len: int,
t_len: int,
) {
blk: [_aes.GHASH_BLOCK_SIZE]byte
endian.unchecked_put_u64be(blk[0:], u64(a_len) * 8)
endian.unchecked_put_u64be(blk[8:], u64(t_len) * 8)
hw_intel.ghash(s[:], h[:], blk[:])
j0_vec := intrinsics.unaligned_load((^x86.__m128i)(j0))
s_vec := intrinsics.unaligned_load((^x86.__m128i)(s))
s_vec = x86._mm_xor_si128(s_vec, j0_vec)
intrinsics.unaligned_store((^x86.__m128i)(s), s_vec)
}
@(private = "file", enable_target_feature = "sse2,sse4.1,aes")
gctr_hw :: proc(
ctx: ^Context_Impl_Hardware,
dst: []byte,
s: ^[_aes.GHASH_BLOCK_SIZE]byte,
src: []byte,
h: ^[_aes.GHASH_KEY_SIZE]byte,
iv: ^[_aes.GHASH_BLOCK_SIZE]byte,
is_seal: bool,
) #no_bounds_check {
sks: [15]x86.__m128i = ---
for i in 0 ..= ctx._num_rounds {
sks[i] = intrinsics.unaligned_load((^x86.__m128i)(&ctx._sk_exp_enc[i]))
}
// Setup the counter block
ctr_blk := intrinsics.unaligned_load((^x86.__m128i)(iv))
ctr := endian.unchecked_get_u32be(iv[GCM_IV_SIZE:]) + 1
src, dst := src, dst
// Note: Instead of doing GHASH and CTR separately, it is more
// performant to interleave (stitch) the two operations together.
// This results in an unreadable mess, so we opt for simplicity
// as performance is adequate.
blks: [CTR_STRIDE_HW]x86.__m128i = ---
nr_blocks := len(src) / BLOCK_SIZE
for nr_blocks >= CTR_STRIDE_HW {
if !is_seal {
hw_intel.ghash(s[:], h[:], src[:CTR_STRIDE_BYTES_HW])
}
#unroll for i in 0 ..< CTR_STRIDE_HW {
blks[i], ctr = hw_inc_ctr32(&ctr_blk, ctr)
}
#unroll for i in 0 ..< CTR_STRIDE_HW {
blks[i] = x86._mm_xor_si128(blks[i], sks[0])
}
#unroll for i in 1 ..= 9 {
#unroll for j in 0 ..< CTR_STRIDE_HW {
blks[j] = x86._mm_aesenc_si128(blks[j], sks[i])
}
}
switch ctx._num_rounds {
case _aes.ROUNDS_128:
#unroll for i in 0 ..< CTR_STRIDE_HW {
blks[i] = x86._mm_aesenclast_si128(blks[i], sks[10])
}
case _aes.ROUNDS_192:
#unroll for i in 10 ..= 11 {
#unroll for j in 0 ..< CTR_STRIDE_HW {
blks[j] = x86._mm_aesenc_si128(blks[j], sks[i])
}
}
#unroll for i in 0 ..< CTR_STRIDE_HW {
blks[i] = x86._mm_aesenclast_si128(blks[i], sks[12])
}
case _aes.ROUNDS_256:
#unroll for i in 10 ..= 13 {
#unroll for j in 0 ..< CTR_STRIDE_HW {
blks[j] = x86._mm_aesenc_si128(blks[j], sks[i])
}
}
#unroll for i in 0 ..< CTR_STRIDE_HW {
blks[i] = x86._mm_aesenclast_si128(blks[i], sks[14])
}
}
xor_blocks_hw(dst, src, blks[:])
if is_seal {
hw_intel.ghash(s[:], h[:], dst[:CTR_STRIDE_BYTES_HW])
}
src = src[CTR_STRIDE_BYTES_HW:]
dst = dst[CTR_STRIDE_BYTES_HW:]
nr_blocks -= CTR_STRIDE_HW
}
// Handle the remainder.
for n := len(src); n > 0; {
l := min(n, BLOCK_SIZE)
if !is_seal {
hw_intel.ghash(s[:], h[:], src[:l])
}
blks[0], ctr = hw_inc_ctr32(&ctr_blk, ctr)
blks[0] = x86._mm_xor_si128(blks[0], sks[0])
#unroll for i in 1 ..= 9 {
blks[0] = x86._mm_aesenc_si128(blks[0], sks[i])
}
switch ctx._num_rounds {
case _aes.ROUNDS_128:
blks[0] = x86._mm_aesenclast_si128(blks[0], sks[10])
case _aes.ROUNDS_192:
#unroll for i in 10 ..= 11 {
blks[0] = x86._mm_aesenc_si128(blks[0], sks[i])
}
blks[0] = x86._mm_aesenclast_si128(blks[0], sks[12])
case _aes.ROUNDS_256:
#unroll for i in 10 ..= 13 {
blks[0] = x86._mm_aesenc_si128(blks[0], sks[i])
}
blks[0] = x86._mm_aesenclast_si128(blks[0], sks[14])
}
if l == BLOCK_SIZE {
xor_blocks_hw(dst, src, blks[:1])
} else {
blk: [BLOCK_SIZE]byte
copy(blk[:], src)
xor_blocks_hw(blk[:], blk[:], blks[:1])
copy(dst, blk[:l])
}
if is_seal {
hw_intel.ghash(s[:], h[:], dst[:l])
}
dst = dst[l:]
src = src[l:]
n -= l
}
mem.zero_explicit(&blks, size_of(blks))
mem.zero_explicit(&sks, size_of(sks))
}
// BUG: Sticking this in gctr_hw (like the other implementations) crashes
// the compiler.
//
// src/check_expr.cpp(7892): Assertion Failure: `c->curr_proc_decl->entity`
@(private = "file", enable_target_feature = "sse4.1")
hw_inc_ctr32 :: #force_inline proc "contextless" (src: ^x86.__m128i, ctr: u32) -> (x86.__m128i, u32) {
ret := x86._mm_insert_epi32(src^, i32(intrinsics.byte_swap(ctr)), 3)
return ret, ctr + 1
}
+4
View File
@@ -10,6 +10,10 @@ Context_Impl :: union {
Context_Impl_Hardware,
}
// DEFAULT_IMPLEMENTATION is the implementation that will be used by
// default if possible.
DEFAULT_IMPLEMENTATION :: Implementation.Hardware
// Implementation is an AES implementation. Most callers will not need
// to use this as the package will automatically select the most performant
// implementation available (See `is_hardware_accelerated()`).
+3 -2
View File
@@ -1,3 +1,4 @@
#+build !amd64
package aes
@(private = "file")
@@ -33,11 +34,11 @@ ctr_blocks_hw :: proc(ctx: ^Context_CTR, dst, src: []byte, nr_blocks: int) {
}
@(private)
gcm_seal_hw :: proc(ctx: ^Context_Impl_Hardware, dst, tag, nonce, aad, plaintext: []byte) {
gcm_seal_hw :: proc(ctx: ^Context_Impl_Hardware, dst, tag, iv, aad, plaintext: []byte) {
panic(ERR_HW_NOT_SUPPORTED)
}
@(private)
gcm_open_hw :: proc(ctx: ^Context_Impl_Hardware, dst, nonce, aad, ciphertext, tag: []byte) -> bool {
gcm_open_hw :: proc(ctx: ^Context_Impl_Hardware, dst, iv, aad, ciphertext, tag: []byte) -> bool {
panic(ERR_HW_NOT_SUPPORTED)
}
+18
View File
@@ -0,0 +1,18 @@
#+build amd64
package aes
import "core:crypto/_aes/hw_intel"
// is_hardware_accelerated returns true iff hardware accelerated AES
// is supported.
is_hardware_accelerated :: proc "contextless" () -> bool {
return hw_intel.is_supported()
}
@(private)
Context_Impl_Hardware :: hw_intel.Context
@(private, enable_target_feature = "sse2,aes")
init_impl_hw :: proc(ctx: ^Context_Impl_Hardware, key: []byte) {
hw_intel.init(ctx, key)
}
+2 -2
View File
@@ -2,8 +2,8 @@
package blake2b implements the BLAKE2b hash algorithm.
See:
- https://datatracker.ietf.org/doc/html/rfc7693
- https://www.blake2.net
- [[ https://datatracker.ietf.org/doc/html/rfc7693 ]]
- [[ https://www.blake2.net ]]
*/
package blake2b
+2 -2
View File
@@ -2,8 +2,8 @@
package blake2s implements the BLAKE2s hash algorithm.
See:
- https://datatracker.ietf.org/doc/html/rfc7693
- https://www.blake2.net/
- [[ https://datatracker.ietf.org/doc/html/rfc7693 ]]
- [[ https://www.blake2.net/ ]]
*/
package blake2s
+58 -469
View File
@@ -2,139 +2,89 @@
package chacha20 implements the ChaCha20 and XChaCha20 stream ciphers.
See:
- https://datatracker.ietf.org/doc/html/rfc8439
- https://datatracker.ietf.org/doc/draft-irtf-cfrg-xchacha/03/
- [[ https://datatracker.ietf.org/doc/html/rfc8439 ]]
- [[ https://datatracker.ietf.org/doc/draft-irtf-cfrg-xchacha/03/ ]]
*/
package chacha20
import "core:encoding/endian"
import "core:math/bits"
import "core:bytes"
import "core:crypto/_chacha20"
import "core:mem"
// KEY_SIZE is the (X)ChaCha20 key size in bytes.
KEY_SIZE :: 32
// NONCE_SIZE is the ChaCha20 nonce size in bytes.
NONCE_SIZE :: 12
// XNONCE_SIZE is the XChaCha20 nonce size in bytes.
XNONCE_SIZE :: 24
@(private)
_MAX_CTR_IETF :: 0xffffffff
@(private)
_BLOCK_SIZE :: 64
@(private)
_STATE_SIZE_U32 :: 16
@(private)
_ROUNDS :: 20
@(private)
_SIGMA_0: u32 : 0x61707865
@(private)
_SIGMA_1: u32 : 0x3320646e
@(private)
_SIGMA_2: u32 : 0x79622d32
@(private)
_SIGMA_3: u32 : 0x6b206574
KEY_SIZE :: _chacha20.KEY_SIZE
// IV_SIZE is the ChaCha20 IV size in bytes.
IV_SIZE :: _chacha20.IV_SIZE
// XIV_SIZE is the XChaCha20 IV size in bytes.
XIV_SIZE :: _chacha20.XIV_SIZE
// Context is a ChaCha20 or XChaCha20 instance.
Context :: struct {
_s: [_STATE_SIZE_U32]u32,
_buffer: [_BLOCK_SIZE]byte,
_off: int,
_is_ietf_flavor: bool,
_is_initialized: bool,
_state: _chacha20.Context,
_impl: Implementation,
}
// init inititializes a Context for ChaCha20 or XChaCha20 with the provided
// key and nonce.
init :: proc(ctx: ^Context, key, nonce: []byte) {
// key and iv.
init :: proc(ctx: ^Context, key, iv: []byte, impl := DEFAULT_IMPLEMENTATION) {
if len(key) != KEY_SIZE {
panic("crypto/chacha20: invalid ChaCha20 key size")
panic("crypto/chacha20: invalid (X)ChaCha20 key size")
}
if n_len := len(nonce); n_len != NONCE_SIZE && n_len != XNONCE_SIZE {
panic("crypto/chacha20: invalid (X)ChaCha20 nonce size")
if l := len(iv); l != IV_SIZE && l != XIV_SIZE {
panic("crypto/chacha20: invalid (X)ChaCha20 IV size")
}
k, n := key, nonce
k, n := key, iv
// Derive the XChaCha20 subkey and sub-nonce via HChaCha20.
is_xchacha := len(nonce) == XNONCE_SIZE
init_impl(ctx, impl)
is_xchacha := len(iv) == XIV_SIZE
if is_xchacha {
sub_key := ctx._buffer[:KEY_SIZE]
_hchacha20(sub_key, k, n)
sub_iv: [IV_SIZE]byte
sub_key := ctx._state._buffer[:KEY_SIZE]
hchacha20(sub_key, k, n, ctx._impl)
k = sub_key
n = n[16:24]
copy(sub_iv[4:], n[16:])
n = sub_iv[:]
}
ctx._s[0] = _SIGMA_0
ctx._s[1] = _SIGMA_1
ctx._s[2] = _SIGMA_2
ctx._s[3] = _SIGMA_3
ctx._s[4] = endian.unchecked_get_u32le(k[0:4])
ctx._s[5] = endian.unchecked_get_u32le(k[4:8])
ctx._s[6] = endian.unchecked_get_u32le(k[8:12])
ctx._s[7] = endian.unchecked_get_u32le(k[12:16])
ctx._s[8] = endian.unchecked_get_u32le(k[16:20])
ctx._s[9] = endian.unchecked_get_u32le(k[20:24])
ctx._s[10] = endian.unchecked_get_u32le(k[24:28])
ctx._s[11] = endian.unchecked_get_u32le(k[28:32])
ctx._s[12] = 0
if !is_xchacha {
ctx._s[13] = endian.unchecked_get_u32le(n[0:4])
ctx._s[14] = endian.unchecked_get_u32le(n[4:8])
ctx._s[15] = endian.unchecked_get_u32le(n[8:12])
} else {
ctx._s[13] = 0
ctx._s[14] = endian.unchecked_get_u32le(n[0:4])
ctx._s[15] = endian.unchecked_get_u32le(n[4:8])
_chacha20.init(&ctx._state, k, n, is_xchacha)
if is_xchacha {
// The sub-key is stored in the keystream buffer. While
// this will be overwritten in most circumstances, explicitly
// clear it out early.
mem.zero_explicit(&ctx._buffer, KEY_SIZE)
mem.zero_explicit(&ctx._state._buffer, KEY_SIZE)
}
ctx._off = _BLOCK_SIZE
ctx._is_ietf_flavor = !is_xchacha
ctx._is_initialized = true
}
// seek seeks the (X)ChaCha20 stream counter to the specified block.
seek :: proc(ctx: ^Context, block_nr: u64) {
assert(ctx._is_initialized)
if ctx._is_ietf_flavor {
if block_nr > _MAX_CTR_IETF {
panic("crypto/chacha20: attempted to seek past maximum counter")
}
} else {
ctx._s[13] = u32(block_nr >> 32)
}
ctx._s[12] = u32(block_nr)
ctx._off = _BLOCK_SIZE
_chacha20.seek(&ctx._state, block_nr)
}
// xor_bytes XORs each byte in src with bytes taken from the (X)ChaCha20
// keystream, and writes the resulting output to dst. Dst and src MUST
// alias exactly or not at all.
xor_bytes :: proc(ctx: ^Context, dst, src: []byte) {
assert(ctx._is_initialized)
// TODO: Enforcing that dst and src alias exactly or not at all
// is a good idea, though odd aliasing should be extremely uncommon.
assert(ctx._state._is_initialized)
src, dst := src, dst
if dst_len := len(dst); dst_len < len(src) {
src = src[:dst_len]
}
for remaining := len(src); remaining > 0; {
if bytes.alias_inexactly(dst, src) {
panic("crypto/chacha20: dst and src alias inexactly")
}
st := &ctx._state
#no_bounds_check for remaining := len(src); remaining > 0; {
// Process multiple blocks at once
if ctx._off == _BLOCK_SIZE {
if nr_blocks := remaining / _BLOCK_SIZE; nr_blocks > 0 {
direct_bytes := nr_blocks * _BLOCK_SIZE
_do_blocks(ctx, dst, src, nr_blocks)
if st._off == _chacha20.BLOCK_SIZE {
if nr_blocks := remaining / _chacha20.BLOCK_SIZE; nr_blocks > 0 {
direct_bytes := nr_blocks * _chacha20.BLOCK_SIZE
stream_blocks(ctx, dst, src, nr_blocks)
remaining -= direct_bytes
if remaining == 0 {
return
@@ -145,17 +95,17 @@ xor_bytes :: proc(ctx: ^Context, dst, src: []byte) {
// If there is a partial block, generate and buffer 1 block
// worth of keystream.
_do_blocks(ctx, ctx._buffer[:], nil, 1)
ctx._off = 0
stream_blocks(ctx, st._buffer[:], nil, 1)
st._off = 0
}
// Process partial blocks from the buffered keystream.
to_xor := min(_BLOCK_SIZE - ctx._off, remaining)
buffered_keystream := ctx._buffer[ctx._off:]
to_xor := min(_chacha20.BLOCK_SIZE - st._off, remaining)
buffered_keystream := st._buffer[st._off:]
for i := 0; i < to_xor; i = i + 1 {
dst[i] = buffered_keystream[i] ~ src[i]
}
ctx._off += to_xor
st._off += to_xor
dst = dst[to_xor:]
src = src[to_xor:]
remaining -= to_xor
@@ -164,15 +114,15 @@ xor_bytes :: proc(ctx: ^Context, dst, src: []byte) {
// keystream_bytes fills dst with the raw (X)ChaCha20 keystream output.
keystream_bytes :: proc(ctx: ^Context, dst: []byte) {
assert(ctx._is_initialized)
assert(ctx._state._is_initialized)
dst := dst
for remaining := len(dst); remaining > 0; {
dst, st := dst, &ctx._state
#no_bounds_check for remaining := len(dst); remaining > 0; {
// Process multiple blocks at once
if ctx._off == _BLOCK_SIZE {
if nr_blocks := remaining / _BLOCK_SIZE; nr_blocks > 0 {
direct_bytes := nr_blocks * _BLOCK_SIZE
_do_blocks(ctx, dst, nil, nr_blocks)
if st._off == _chacha20.BLOCK_SIZE {
if nr_blocks := remaining / _chacha20.BLOCK_SIZE; nr_blocks > 0 {
direct_bytes := nr_blocks * _chacha20.BLOCK_SIZE
stream_blocks(ctx, dst, nil, nr_blocks)
remaining -= direct_bytes
if remaining == 0 {
return
@@ -182,15 +132,15 @@ keystream_bytes :: proc(ctx: ^Context, dst: []byte) {
// If there is a partial block, generate and buffer 1 block
// worth of keystream.
_do_blocks(ctx, ctx._buffer[:], nil, 1)
ctx._off = 0
stream_blocks(ctx, st._buffer[:], nil, 1)
st._off = 0
}
// Process partial blocks from the buffered keystream.
to_copy := min(_BLOCK_SIZE - ctx._off, remaining)
buffered_keystream := ctx._buffer[ctx._off:]
to_copy := min(_chacha20.BLOCK_SIZE - st._off, remaining)
buffered_keystream := st._buffer[st._off:]
copy(dst[:to_copy], buffered_keystream[:to_copy])
ctx._off += to_copy
st._off += to_copy
dst = dst[to_copy:]
remaining -= to_copy
}
@@ -199,366 +149,5 @@ keystream_bytes :: proc(ctx: ^Context, dst: []byte) {
// reset sanitizes the Context. The Context must be re-initialized to
// be used again.
reset :: proc(ctx: ^Context) {
mem.zero_explicit(&ctx._s, size_of(ctx._s))
mem.zero_explicit(&ctx._buffer, size_of(ctx._buffer))
ctx._is_initialized = false
}
@(private)
_do_blocks :: proc(ctx: ^Context, dst, src: []byte, nr_blocks: int) {
// Enforce the maximum consumed keystream per nonce.
//
// While all modern "standard" definitions of ChaCha20 use
// the IETF 32-bit counter, for XChaCha20 most common
// implementations allow for a 64-bit counter.
//
// Honestly, the answer here is "use a MRAE primitive", but
// go with common practice in the case of XChaCha20.
if ctx._is_ietf_flavor {
if u64(ctx._s[12]) + u64(nr_blocks) > 0xffffffff {
panic("crypto/chacha20: maximum ChaCha20 keystream per nonce reached")
}
} else {
ctr := (u64(ctx._s[13]) << 32) | u64(ctx._s[12])
if _, carry := bits.add_u64(ctr, u64(nr_blocks), 0); carry != 0 {
panic("crypto/chacha20: maximum XChaCha20 keystream per nonce reached")
}
}
dst, src := dst, src
x := &ctx._s
for n := 0; n < nr_blocks; n = n + 1 {
x0, x1, x2, x3 := _SIGMA_0, _SIGMA_1, _SIGMA_2, _SIGMA_3
x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15 := x[4], x[5], x[6], x[7], x[8], x[9], x[10], x[11], x[12], x[13], x[14], x[15]
for i := _ROUNDS; i > 0; i = i - 2 {
// Even when forcing inlining manually inlining all of
// these is decently faster.
// quarterround(x, 0, 4, 8, 12)
x0 += x4
x12 ~= x0
x12 = bits.rotate_left32(x12, 16)
x8 += x12
x4 ~= x8
x4 = bits.rotate_left32(x4, 12)
x0 += x4
x12 ~= x0
x12 = bits.rotate_left32(x12, 8)
x8 += x12
x4 ~= x8
x4 = bits.rotate_left32(x4, 7)
// quarterround(x, 1, 5, 9, 13)
x1 += x5
x13 ~= x1
x13 = bits.rotate_left32(x13, 16)
x9 += x13
x5 ~= x9
x5 = bits.rotate_left32(x5, 12)
x1 += x5
x13 ~= x1
x13 = bits.rotate_left32(x13, 8)
x9 += x13
x5 ~= x9
x5 = bits.rotate_left32(x5, 7)
// quarterround(x, 2, 6, 10, 14)
x2 += x6
x14 ~= x2
x14 = bits.rotate_left32(x14, 16)
x10 += x14
x6 ~= x10
x6 = bits.rotate_left32(x6, 12)
x2 += x6
x14 ~= x2
x14 = bits.rotate_left32(x14, 8)
x10 += x14
x6 ~= x10
x6 = bits.rotate_left32(x6, 7)
// quarterround(x, 3, 7, 11, 15)
x3 += x7
x15 ~= x3
x15 = bits.rotate_left32(x15, 16)
x11 += x15
x7 ~= x11
x7 = bits.rotate_left32(x7, 12)
x3 += x7
x15 ~= x3
x15 = bits.rotate_left32(x15, 8)
x11 += x15
x7 ~= x11
x7 = bits.rotate_left32(x7, 7)
// quarterround(x, 0, 5, 10, 15)
x0 += x5
x15 ~= x0
x15 = bits.rotate_left32(x15, 16)
x10 += x15
x5 ~= x10
x5 = bits.rotate_left32(x5, 12)
x0 += x5
x15 ~= x0
x15 = bits.rotate_left32(x15, 8)
x10 += x15
x5 ~= x10
x5 = bits.rotate_left32(x5, 7)
// quarterround(x, 1, 6, 11, 12)
x1 += x6
x12 ~= x1
x12 = bits.rotate_left32(x12, 16)
x11 += x12
x6 ~= x11
x6 = bits.rotate_left32(x6, 12)
x1 += x6
x12 ~= x1
x12 = bits.rotate_left32(x12, 8)
x11 += x12
x6 ~= x11
x6 = bits.rotate_left32(x6, 7)
// quarterround(x, 2, 7, 8, 13)
x2 += x7
x13 ~= x2
x13 = bits.rotate_left32(x13, 16)
x8 += x13
x7 ~= x8
x7 = bits.rotate_left32(x7, 12)
x2 += x7
x13 ~= x2
x13 = bits.rotate_left32(x13, 8)
x8 += x13
x7 ~= x8
x7 = bits.rotate_left32(x7, 7)
// quarterround(x, 3, 4, 9, 14)
x3 += x4
x14 ~= x3
x14 = bits.rotate_left32(x14, 16)
x9 += x14
x4 ~= x9
x4 = bits.rotate_left32(x4, 12)
x3 += x4
x14 ~= x3
x14 = bits.rotate_left32(x14, 8)
x9 += x14
x4 ~= x9
x4 = bits.rotate_left32(x4, 7)
}
x0 += _SIGMA_0
x1 += _SIGMA_1
x2 += _SIGMA_2
x3 += _SIGMA_3
x4 += x[4]
x5 += x[5]
x6 += x[6]
x7 += x[7]
x8 += x[8]
x9 += x[9]
x10 += x[10]
x11 += x[11]
x12 += x[12]
x13 += x[13]
x14 += x[14]
x15 += x[15]
// While the "correct" answer to getting more performance out of
// this is "use vector operations", support for that is currently
// a work in progress/to be designed.
//
// In the meantime:
// - The caller(s) ensure that src/dst are valid.
// - The compiler knows if the target is picky about alignment.
#no_bounds_check {
if src != nil {
endian.unchecked_put_u32le(dst[0:4], endian.unchecked_get_u32le(src[0:4]) ~ x0)
endian.unchecked_put_u32le(dst[4:8], endian.unchecked_get_u32le(src[4:8]) ~ x1)
endian.unchecked_put_u32le(dst[8:12], endian.unchecked_get_u32le(src[8:12]) ~ x2)
endian.unchecked_put_u32le(dst[12:16], endian.unchecked_get_u32le(src[12:16]) ~ x3)
endian.unchecked_put_u32le(dst[16:20], endian.unchecked_get_u32le(src[16:20]) ~ x4)
endian.unchecked_put_u32le(dst[20:24], endian.unchecked_get_u32le(src[20:24]) ~ x5)
endian.unchecked_put_u32le(dst[24:28], endian.unchecked_get_u32le(src[24:28]) ~ x6)
endian.unchecked_put_u32le(dst[28:32], endian.unchecked_get_u32le(src[28:32]) ~ x7)
endian.unchecked_put_u32le(dst[32:36], endian.unchecked_get_u32le(src[32:36]) ~ x8)
endian.unchecked_put_u32le(dst[36:40], endian.unchecked_get_u32le(src[36:40]) ~ x9)
endian.unchecked_put_u32le(dst[40:44], endian.unchecked_get_u32le(src[40:44]) ~ x10)
endian.unchecked_put_u32le(dst[44:48], endian.unchecked_get_u32le(src[44:48]) ~ x11)
endian.unchecked_put_u32le(dst[48:52], endian.unchecked_get_u32le(src[48:52]) ~ x12)
endian.unchecked_put_u32le(dst[52:56], endian.unchecked_get_u32le(src[52:56]) ~ x13)
endian.unchecked_put_u32le(dst[56:60], endian.unchecked_get_u32le(src[56:60]) ~ x14)
endian.unchecked_put_u32le(dst[60:64], endian.unchecked_get_u32le(src[60:64]) ~ x15)
src = src[_BLOCK_SIZE:]
} else {
endian.unchecked_put_u32le(dst[0:4], x0)
endian.unchecked_put_u32le(dst[4:8], x1)
endian.unchecked_put_u32le(dst[8:12], x2)
endian.unchecked_put_u32le(dst[12:16], x3)
endian.unchecked_put_u32le(dst[16:20], x4)
endian.unchecked_put_u32le(dst[20:24], x5)
endian.unchecked_put_u32le(dst[24:28], x6)
endian.unchecked_put_u32le(dst[28:32], x7)
endian.unchecked_put_u32le(dst[32:36], x8)
endian.unchecked_put_u32le(dst[36:40], x9)
endian.unchecked_put_u32le(dst[40:44], x10)
endian.unchecked_put_u32le(dst[44:48], x11)
endian.unchecked_put_u32le(dst[48:52], x12)
endian.unchecked_put_u32le(dst[52:56], x13)
endian.unchecked_put_u32le(dst[56:60], x14)
endian.unchecked_put_u32le(dst[60:64], x15)
}
dst = dst[_BLOCK_SIZE:]
}
// Increment the counter. Overflow checking is done upon
// entry into the routine, so a 64-bit increment safely
// covers both cases.
new_ctr := ((u64(ctx._s[13]) << 32) | u64(ctx._s[12])) + 1
x[12] = u32(new_ctr)
x[13] = u32(new_ctr >> 32)
}
}
@(private)
_hchacha20 :: proc "contextless" (dst, key, nonce: []byte) {
x0, x1, x2, x3 := _SIGMA_0, _SIGMA_1, _SIGMA_2, _SIGMA_3
x4 := endian.unchecked_get_u32le(key[0:4])
x5 := endian.unchecked_get_u32le(key[4:8])
x6 := endian.unchecked_get_u32le(key[8:12])
x7 := endian.unchecked_get_u32le(key[12:16])
x8 := endian.unchecked_get_u32le(key[16:20])
x9 := endian.unchecked_get_u32le(key[20:24])
x10 := endian.unchecked_get_u32le(key[24:28])
x11 := endian.unchecked_get_u32le(key[28:32])
x12 := endian.unchecked_get_u32le(nonce[0:4])
x13 := endian.unchecked_get_u32le(nonce[4:8])
x14 := endian.unchecked_get_u32le(nonce[8:12])
x15 := endian.unchecked_get_u32le(nonce[12:16])
for i := _ROUNDS; i > 0; i = i - 2 {
// quarterround(x, 0, 4, 8, 12)
x0 += x4
x12 ~= x0
x12 = bits.rotate_left32(x12, 16)
x8 += x12
x4 ~= x8
x4 = bits.rotate_left32(x4, 12)
x0 += x4
x12 ~= x0
x12 = bits.rotate_left32(x12, 8)
x8 += x12
x4 ~= x8
x4 = bits.rotate_left32(x4, 7)
// quarterround(x, 1, 5, 9, 13)
x1 += x5
x13 ~= x1
x13 = bits.rotate_left32(x13, 16)
x9 += x13
x5 ~= x9
x5 = bits.rotate_left32(x5, 12)
x1 += x5
x13 ~= x1
x13 = bits.rotate_left32(x13, 8)
x9 += x13
x5 ~= x9
x5 = bits.rotate_left32(x5, 7)
// quarterround(x, 2, 6, 10, 14)
x2 += x6
x14 ~= x2
x14 = bits.rotate_left32(x14, 16)
x10 += x14
x6 ~= x10
x6 = bits.rotate_left32(x6, 12)
x2 += x6
x14 ~= x2
x14 = bits.rotate_left32(x14, 8)
x10 += x14
x6 ~= x10
x6 = bits.rotate_left32(x6, 7)
// quarterround(x, 3, 7, 11, 15)
x3 += x7
x15 ~= x3
x15 = bits.rotate_left32(x15, 16)
x11 += x15
x7 ~= x11
x7 = bits.rotate_left32(x7, 12)
x3 += x7
x15 ~= x3
x15 = bits.rotate_left32(x15, 8)
x11 += x15
x7 ~= x11
x7 = bits.rotate_left32(x7, 7)
// quarterround(x, 0, 5, 10, 15)
x0 += x5
x15 ~= x0
x15 = bits.rotate_left32(x15, 16)
x10 += x15
x5 ~= x10
x5 = bits.rotate_left32(x5, 12)
x0 += x5
x15 ~= x0
x15 = bits.rotate_left32(x15, 8)
x10 += x15
x5 ~= x10
x5 = bits.rotate_left32(x5, 7)
// quarterround(x, 1, 6, 11, 12)
x1 += x6
x12 ~= x1
x12 = bits.rotate_left32(x12, 16)
x11 += x12
x6 ~= x11
x6 = bits.rotate_left32(x6, 12)
x1 += x6
x12 ~= x1
x12 = bits.rotate_left32(x12, 8)
x11 += x12
x6 ~= x11
x6 = bits.rotate_left32(x6, 7)
// quarterround(x, 2, 7, 8, 13)
x2 += x7
x13 ~= x2
x13 = bits.rotate_left32(x13, 16)
x8 += x13
x7 ~= x8
x7 = bits.rotate_left32(x7, 12)
x2 += x7
x13 ~= x2
x13 = bits.rotate_left32(x13, 8)
x8 += x13
x7 ~= x8
x7 = bits.rotate_left32(x7, 7)
// quarterround(x, 3, 4, 9, 14)
x3 += x4
x14 ~= x3
x14 = bits.rotate_left32(x14, 16)
x9 += x14
x4 ~= x9
x4 = bits.rotate_left32(x4, 12)
x3 += x4
x14 ~= x3
x14 = bits.rotate_left32(x14, 8)
x9 += x14
x4 ~= x9
x4 = bits.rotate_left32(x4, 7)
}
endian.unchecked_put_u32le(dst[0:4], x0)
endian.unchecked_put_u32le(dst[4:8], x1)
endian.unchecked_put_u32le(dst[8:12], x2)
endian.unchecked_put_u32le(dst[12:16], x3)
endian.unchecked_put_u32le(dst[16:20], x12)
endian.unchecked_put_u32le(dst[20:24], x13)
endian.unchecked_put_u32le(dst[24:28], x14)
endian.unchecked_put_u32le(dst[28:32], x15)
_chacha20.reset(&ctx._state)
}
+56
View File
@@ -0,0 +1,56 @@
package chacha20
import "base:intrinsics"
import "core:crypto/_chacha20/ref"
import "core:crypto/_chacha20/simd128"
import "core:crypto/_chacha20/simd256"
// DEFAULT_IMPLEMENTATION is the implementation that will be used by
// default if possible.
DEFAULT_IMPLEMENTATION :: Implementation.Simd256
// Implementation is a ChaCha20 implementation. Most callers will not need
// to use this as the package will automatically select the most performant
// implementation available.
Implementation :: enum {
Portable,
Simd128,
Simd256,
}
@(private)
init_impl :: proc(ctx: ^Context, impl: Implementation) {
impl := impl
if impl == .Simd256 && !simd256.is_performant() {
impl = .Simd128
}
if impl == .Simd128 && !simd128.is_performant() {
impl = .Portable
}
ctx._impl = impl
}
@(private)
stream_blocks :: proc(ctx: ^Context, dst, src: []byte, nr_blocks: int) {
switch ctx._impl {
case .Simd256:
simd256.stream_blocks(&ctx._state, dst, src, nr_blocks)
case .Simd128:
simd128.stream_blocks(&ctx._state, dst, src, nr_blocks)
case .Portable:
ref.stream_blocks(&ctx._state, dst, src, nr_blocks)
}
}
@(private)
hchacha20 :: proc "contextless" (dst, key, iv: []byte, impl: Implementation) {
switch impl {
case .Simd256:
simd256.hchacha20(dst, key, iv)
case .Simd128:
simd128.hchacha20(dst, key, iv)
case .Portable:
ref.hchacha20(dst, key, iv)
}
}
@@ -1,9 +1,11 @@
/*
package chacha20poly1305 implements the AEAD_CHACHA20_POLY1305 Authenticated
Encryption with Additional Data algorithm.
package chacha20poly1305 implements the AEAD_CHACHA20_POLY1305 and
AEAD_XChaCha20_Poly1305 Authenticated Encryption with Additional Data
algorithms.
See:
- https://www.rfc-editor.org/rfc/rfc8439
- [[ https://www.rfc-editor.org/rfc/rfc8439 ]]
- [[ https://datatracker.ietf.org/doc/html/draft-arciszewski-xchacha-03 ]]
*/
package chacha20poly1305
@@ -15,8 +17,10 @@ import "core:mem"
// KEY_SIZE is the chacha20poly1305 key size in bytes.
KEY_SIZE :: chacha20.KEY_SIZE
// NONCE_SIZE is the chacha20poly1305 nonce size in bytes.
NONCE_SIZE :: chacha20.NONCE_SIZE
// IV_SIZE is the chacha20poly1305 IV size in bytes.
IV_SIZE :: chacha20.IV_SIZE
// XIV_SIZE is the xchacha20poly1305 IV size in bytes.
XIV_SIZE :: chacha20.XIV_SIZE
// TAG_SIZE is the chacha20poly1305 tag size in bytes.
TAG_SIZE :: poly1305.TAG_SIZE
@@ -24,15 +28,13 @@ TAG_SIZE :: poly1305.TAG_SIZE
_P_MAX :: 64 * 0xffffffff // 64 * (2^32-1)
@(private)
_validate_common_slice_sizes :: proc (tag, key, nonce, aad, text: []byte) {
_validate_common_slice_sizes :: proc (tag, iv, aad, text: []byte, is_xchacha: bool) {
if len(tag) != TAG_SIZE {
panic("crypto/chacha20poly1305: invalid destination tag size")
}
if len(key) != KEY_SIZE {
panic("crypto/chacha20poly1305: invalid key size")
}
if len(nonce) != NONCE_SIZE {
panic("crypto/chacha20poly1305: invalid nonce size")
expected_iv_len := is_xchacha ? XIV_SIZE : IV_SIZE
if len(iv) != expected_iv_len {
panic("crypto/chacha20poly1305: invalid IV size")
}
#assert(size_of(int) == 8 || size_of(int) <= 4)
@@ -59,18 +61,52 @@ _update_mac_pad16 :: #force_inline proc (ctx: ^poly1305.Context, x_len: int) {
}
}
// encrypt encrypts the plaintext and authenticates the aad and ciphertext,
// with the provided key and nonce, stores the output in ciphertext and tag.
encrypt :: proc (ciphertext, tag, key, nonce, aad, plaintext: []byte) {
_validate_common_slice_sizes(tag, key, nonce, aad, plaintext)
// Context is a keyed (X)Chacha20Poly1305 instance.
Context :: struct {
_key: [KEY_SIZE]byte,
_impl: chacha20.Implementation,
_is_xchacha: bool,
_is_initialized: bool,
}
// init initializes a Context with the provided key, for AEAD_CHACHA20_POLY1305.
init :: proc(ctx: ^Context, key: []byte, impl := chacha20.DEFAULT_IMPLEMENTATION) {
if len(key) != KEY_SIZE {
panic("crypto/chacha20poly1305: invalid key size")
}
copy(ctx._key[:], key)
ctx._impl = impl
ctx._is_xchacha = false
ctx._is_initialized = true
}
// init_xchacha initializes a Context with the provided key, for
// AEAD_XChaCha20_Poly1305.
//
// Note: While there are multiple definitions of XChaCha20-Poly1305
// this sticks to the IETF draft and uses a 32-bit counter.
init_xchacha :: proc(ctx: ^Context, key: []byte, impl := chacha20.DEFAULT_IMPLEMENTATION) {
init(ctx, key, impl)
ctx._is_xchacha = true
}
// seal encrypts the plaintext and authenticates the aad and ciphertext,
// with the provided Context and iv, stores the output in dst and tag.
//
// dst and plaintext MUST alias exactly or not at all.
seal :: proc(ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) {
ciphertext := dst
_validate_common_slice_sizes(tag, iv, aad, plaintext, ctx._is_xchacha)
if len(ciphertext) != len(plaintext) {
panic("crypto/chacha20poly1305: invalid destination ciphertext size")
}
stream_ctx: chacha20.Context = ---
chacha20.init(&stream_ctx, key, nonce)
chacha20.init(&stream_ctx, ctx._key[:],iv, ctx._impl)
stream_ctx._state._is_ietf_flavor = true
// otk = poly1305_key_gen(key, nonce)
// otk = poly1305_key_gen(key, iv)
otk: [poly1305.KEY_SIZE]byte = ---
chacha20.keystream_bytes(&stream_ctx, otk[:])
mac_ctx: poly1305.Context = ---
@@ -87,7 +123,7 @@ encrypt :: proc (ciphertext, tag, key, nonce, aad, plaintext: []byte) {
poly1305.update(&mac_ctx, aad)
_update_mac_pad16(&mac_ctx, aad_len)
// ciphertext = chacha20_encrypt(key, 1, nonce, plaintext)
// ciphertext = chacha20_encrypt(key, 1, iv, plaintext)
chacha20.seek(&stream_ctx, 1)
chacha20.xor_bytes(&stream_ctx, ciphertext, plaintext)
chacha20.reset(&stream_ctx) // Don't need the stream context anymore.
@@ -107,13 +143,16 @@ encrypt :: proc (ciphertext, tag, key, nonce, aad, plaintext: []byte) {
poly1305.final(&mac_ctx, tag) // Implicitly sanitizes context.
}
// decrypt authenticates the aad and ciphertext, and decrypts the ciphertext,
// with the provided key, nonce, and tag, and stores the output in plaintext,
// returning true iff the authentication was successful.
// open authenticates the aad and ciphertext, and decrypts the ciphertext,
// with the provided Context, iv, and tag, and stores the output in dst,
// returning true iff the authentication was successful. If authentication
// fails, the destination buffer will be zeroed.
//
// If authentication fails, the destination plaintext buffer will be zeroed.
decrypt :: proc (plaintext, tag, key, nonce, aad, ciphertext: []byte) -> bool {
_validate_common_slice_sizes(tag, key, nonce, aad, ciphertext)
// dst and plaintext MUST alias exactly or not at all.
@(require_results)
open :: proc(ctx: ^Context, dst, iv, aad, ciphertext, tag: []byte) -> bool {
plaintext := dst
_validate_common_slice_sizes(tag, iv, aad, ciphertext, ctx._is_xchacha)
if len(ciphertext) != len(plaintext) {
panic("crypto/chacha20poly1305: invalid destination plaintext size")
}
@@ -123,9 +162,10 @@ decrypt :: proc (plaintext, tag, key, nonce, aad, ciphertext: []byte) -> bool {
// points where needed.
stream_ctx: chacha20.Context = ---
chacha20.init(&stream_ctx, key, nonce)
chacha20.init(&stream_ctx, ctx._key[:], iv, ctx._impl)
stream_ctx._state._is_ietf_flavor = true
// otk = poly1305_key_gen(key, nonce)
// otk = poly1305_key_gen(key, iv)
otk: [poly1305.KEY_SIZE]byte = ---
chacha20.keystream_bytes(&stream_ctx, otk[:])
defer chacha20.reset(&stream_ctx)
@@ -160,9 +200,17 @@ decrypt :: proc (plaintext, tag, key, nonce, aad, ciphertext: []byte) -> bool {
return false
}
// plaintext = chacha20_decrypt(key, 1, nonce, ciphertext)
// plaintext = chacha20_decrypt(key, 1, iv, ciphertext)
chacha20.seek(&stream_ctx, 1)
chacha20.xor_bytes(&stream_ctx, plaintext, ciphertext)
return true
}
// reset sanitizes the Context. The Context must be
// re-initialized to be used again.
reset :: proc "contextless" (ctx: ^Context) {
mem.zero_explicit(&ctx._key, len(ctx._key))
ctx._is_xchacha = false
ctx._is_initialized = false
}

Some files were not shown because too many files have changed in this diff Show More