Compare commits

..

1855 Commits

Author SHA1 Message Date
gingerBill b4ca044ae0 Merge pull request #3846 from Feoramund/add-more-net-tests
Add more `core:net` tests
2024-07-01 17:56:07 +01:00
gingerBill a2b23de0a7 Sanity check for a nullptr 2024-07-01 12:24:46 +01:00
gingerBill 42ff711114 Fix #3515 2024-07-01 12:22:18 +01:00
gingerBill 544959326b Add intrinsics.type_struct_has_implicit_padding #3844 2024-07-01 12:13:35 +01:00
gingerBill 942f3f5220 Add non_zero_* variants for #soa dynamic array 2024-07-01 12:04:29 +01:00
gingerBill 8ddfcf174d Add #soa support to append directly 2024-07-01 11:51:28 +01:00
gingerBill 4086a62167 Fix showing error when not meant to 2024-07-01 11:50:35 +01:00
gingerBill 3a43928184 Add #no_broadcast to append_soa 2024-07-01 11:47:33 +01:00
gingerBill 7f6fe91896 Add #soa forms to reserve, clear, and resize 2024-07-01 11:37:21 +01:00
gingerBill 11617af8f5 Add support for make(#soa[]T) etc 2024-07-01 11:34:50 +01:00
gingerBill 4a2b87672c Unify #soa code for structs and arrays 2024-07-01 11:11:06 +01:00
gingerBill fb0b95bcad Merge pull request #3760 from Feoramund/refactor-show-error-on-line
Refactor `show_error_on_line`
2024-07-01 11:03:29 +01:00
gingerBill 1a4edad63e Merge pull request #3848 from laytan/wasm-c-abi-indirect-multifield-struct
make structs with multiple fields always return indirect in wasm c abi
2024-07-01 11:02:49 +01:00
Laytan Laats ef6a73c7ef fix not setting cc before using it in abi computations 2024-07-01 01:30:44 +02:00
Laytan Laats e3dde8caf8 make structs with multiple fields always return indirect in wasm c abi 2024-07-01 00:50:10 +02:00
Feoramund 8e64265aed Replace unneeded transmute 2024-06-30 16:39:22 -04:00
Feoramund 1e7dfd0e34 Add more core:net tests
- UDP send & read
- DNS resolution
- Nonblocking socket option
2024-06-30 16:39:22 -04:00
gingerBill 13ace1dac9 Merge pull request #3839 from flysand7/tlhelp-fix
[sys/windows]: Fix the value for TH32CS_SNAPPROCESS constant
2024-06-30 20:15:33 +01:00
Jeroen van Rijn efd933e221 Merge pull request #3842 from karl-zylinski/fix-poly-bitset-size
Fix for bit_set[$T] proc params always being generated as i8
2024-06-30 21:10:42 +02:00
Karl Zylinski e0face1ac8 Make types like bit_set[$T] have their upper and lower bits overwritten by upper/lower from the source types when checking if polymorphic type is assignable. This fixes an issue where an i8 was always generated for bit_sets with generic elements, because it couldn't figure out upper/lower when check_bit_set_type was run. Fixes #2860 2024-06-30 20:36:51 +02:00
Jeroen van Rijn 4fbd22b668 Merge pull request #3840 from H0mTanks/master
Add missing enum member for WSAEWOULDBLOCK in TCP_Send_Error for windows.
2024-06-30 11:29:31 +02:00
h0mtanks 2b615b09f0 fixed whitespace 2024-06-30 13:47:11 +05:30
h0mtanks d1603ebac4 added missing would_block enum member 2024-06-30 13:42:55 +05:30
flysand7 561b96b20d [sys/windows]: Fix the value for TH32CS_SNAPPROCESS constant 2024-06-30 13:34:08 +11:00
gingerBill afe24a0d4d Merge pull request #3838 from flysand7/windows-tlhelp
[core/windows]: Bind tlhelp.h functions from kernel32.dll
2024-06-30 02:52:35 +01:00
flysand7 2737ccab3d [core/windows]: Bind tlhelp.h functions from kernel32.dll 2024-06-30 12:35:42 +11:00
Feoramund 8ed5cb283b Re-implement the error squiggles with visual width 2024-06-29 18:55:12 -04:00
Feoramund 8b305a4c67 Add UCG library to Odin compiler 2024-06-29 18:42:56 -04:00
gingerBill 80592f0f51 Add -disallow-do in CI 2024-06-29 22:50:23 +01:00
gingerBill af3401631a Remove the -disallow-do aspect from -strict-style 2024-06-29 22:48:43 +01:00
gingerBill 5637ed9ecd Merge pull request #3836 from laytan/run-wasi-demo-in-ci
wasi: make the demo run on wasi and run it in CI
2024-06-29 22:30:31 +01:00
Laytan Laats 604551eb2d wasi: make the demo run on wasi and run it in CI 2024-06-29 23:15:31 +02:00
Jeroen van Rijn 476d0087c8 Fix bug in div3 fast path. 2024-06-29 23:14:12 +02:00
gingerBill 34fce83d66 Improve -strict-style rules for if-else statements 2024-06-29 20:04:34 +01:00
gingerBill b1a1da6618 Add -vet-tabs 2024-06-29 19:54:31 +01:00
gingerBill e296d6fb90 Fix loads of indentation issues with mixing spaces and tabs 2024-06-29 19:50:51 +01:00
gingerBill 90244a0849 Fix accidental deletion in the -strict-style help comment 2024-06-29 19:41:45 +01:00
gingerBill f4abdf716e Move microarch stuff to a separate file 2024-06-29 19:29:20 +01:00
gingerBill f64d1df90b Add note regarding -strict-style 2024-06-29 19:27:26 +01:00
gingerBill 888bf28076 -strict-style implies -disallow-do 2024-06-29 19:26:11 +01:00
gingerBill 103eccf104 More style improvements 2024-06-29 19:23:58 +01:00
gingerBill 663661db53 Update core to -strict-style 2024-06-29 19:16:32 +01:00
gingerBill 835e8bf87a Update -strict-style 2024-06-29 19:15:33 +01:00
gingerBill 2187f3e7ff -strict-style enforce 1TBS (mostly) 2024-06-29 19:14:24 +01:00
gingerBill 5413a8b744 Even more style fixes 2024-06-29 19:11:36 +01:00
gingerBill 3f9a58808c More style improvements 2024-06-29 19:07:34 +01:00
gingerBill e8517e2694 -strict-style: enforce case to be in the same column as switch 2024-06-29 18:56:45 +01:00
gingerBill 96330996a6 Fix indentation 2024-06-29 18:51:39 +01:00
gingerBill b0cbda4ee0 Fix indentation of tests 2024-06-29 18:51:28 +01:00
gingerBill 930c929294 Indentation fixes 2024-06-29 18:49:57 +01:00
gingerBill 7f05b4caf2 Fix generation for unicode entities 2024-06-29 18:43:09 +01:00
gingerBill 6db748b4a4 Remove debug message 2024-06-29 16:18:43 +01:00
gingerBill a935ade0d2 Keep -sanitize:address happy with bit_field loads 2024-06-29 16:18:07 +01:00
gingerBill ff2d042313 Remove unneeded transmute 2024-06-29 13:54:15 +01:00
gingerBill 913c08a33e Add bit_field to demo.odin 2024-06-29 12:56:46 +01:00
gingerBill c88a1bef91 Add another -vet-cast check 2024-06-29 12:40:04 +01:00
gingerBill 706adb1232 Update for transmute -vet-cast 2024-06-29 12:16:43 +01:00
gingerBill b9861a0cf6 cast to transmute 2024-06-29 12:14:21 +01:00
gingerBill e46d772b6d Add check for integer casts 2024-06-29 12:13:41 +01:00
gingerBill c18c0a3364 Adhere to -vet-cast 2024-06-29 12:07:21 +01:00
gingerBill d6b8544f50 Add internal flag for testing stuff 2024-06-29 12:04:31 +01:00
gingerBill 4b71c47fd5 Check for unneeded transmute with -vet-cast 2024-06-29 12:02:31 +01:00
gingerBill 704530497b Rename -vet-identical-cast to -vet-cast; with minor code clean up 2024-06-29 11:44:45 +01:00
gingerBill 4be0fc05bb Merge pull request #3832 from Feoramund/vet-identical-cast
Add `-vet-identical-cast`
2024-06-29 11:37:35 +01:00
gingerBill 52aa7085e4 Use f32 as the immediate type for addition and subtraction for complex32/quaternion64 2024-06-29 11:09:54 +01:00
gingerBill 9113f389d8 Merge pull request #3831 from Feoramund/fix-darwin-test-runner-cancel
Let Darwin safely panic in a test
2024-06-29 11:01:01 +01:00
gingerBill 55e9b8d994 Use explicit calling conventions 2024-06-29 10:48:41 +01:00
gingerBill ee2a0c4010 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-06-29 10:47:15 +01:00
gingerBill f974002839 Use f32 operations rather than f16 in complex32 and quaternion64 to improve accuracy and performance 2024-06-29 10:47:09 +01:00
gingerBill 83b575aec2 Merge pull request #3833 from karl-zylinski/consistent-default-dynamic-array-capacity
Consistent dynamic array default capacity and avoid unnecessary dynamic array allocations
2024-06-29 10:38:22 +01:00
gingerBill 906afa4154 Allow for when x in y { (minor oversight in syntax) 2024-06-29 10:13:15 +01:00
Karl Zylinski 679f9b4e41 Made default capacity of dynamic arrays more consistent.
Before this if you do `arr: [dynamic]int` and then append to arr, then it will have capacity 8.
But if you did `arr := make([dynamic]int, context.temp_allocator)` then arr would have capacity 16.

Now both `arr: [dynamic]int` and `arr := make([dynamic]int, context.temp_allocator)` will resut in arr having zero 0. The only reason to use `make` without an explicit len or cap now is because you want to set it up for a non-default allocator. After the first call to `append` it will now in both cases have capacity 8.

I also updated the documentation on the strings builder, both to reflect this, and also to fix it incorrectly saying that len would be 'max(16,len)', which wasn't true even before these changes.
2024-06-29 08:57:21 +02:00
Feoramund b3caae6db4 Keep -vet happy 2024-06-28 23:14:03 -04:00
Feoramund 6496432b80 Add -vet-identical-cast 2024-06-28 23:14:03 -04:00
Feoramund 0ea0fac2f9 Call pthread_cancel on Darwin, with advisory comment 2024-06-28 20:47:37 -04:00
Feoramund 13539d3be1 Catch SIGTRAP in the test runner
Fixes `panic` for Darwin.
2024-06-28 19:43:03 -04:00
Feoramund 929cc48703 Merge Darwin signals into other UNIX-likes
They're all the same.
2024-06-28 19:03:43 -04:00
Jeroen van Rijn 06652bebce Merge pull request #3829 from Feoramund/fix-vetted-test-name
Let `-vet` be used with `-define:ODIN_TEST_NAMES`
2024-06-28 23:06:25 +02:00
Feoramund 574342af6f Let -vet be used with -define:ODIN_TEST_NAMES 2024-06-28 15:58:22 -04:00
Jeroen van Rijn 007832488d Merge pull request #3827 from Feoramund/require-runtime-linalg-import
Require `base:runtime` import in `core:math/linalg`
2024-06-28 17:44:10 +02:00
Feoramund 2af121752a Require base:runtime import in core:math/linalg 2024-06-28 11:34:35 -04:00
gingerBill 0c8924ea85 Merge pull request #3822 from jasonKercher/os2-rebase
os2 linux round 2
2024-06-28 15:43:18 +01:00
jason 6a894195cb revert os2/process 2024-06-28 09:45:22 -04:00
jason dc954307d7 fix assumption about std handles in os2/file.odin 2024-06-28 07:55:33 -04:00
jason a15cbc474d change error strings to an enumerated array in rodata; print_error takes a file argument 2024-06-28 07:45:24 -04:00
gingerBill 37afd469c6 Merge pull request #3339 from axxeny/patch-1
fix comments in core:container/queue.
2024-06-28 12:00:34 +01:00
gingerBill 853173a11b Merge pull request #3517 from timosperisen/patch-1
Update builder.odin
2024-06-28 12:00:23 +01:00
gingerBill a1ae6f161b Merge pull request #3502 from ARtemachka/master
Fix typo in core_builtin
2024-06-28 12:00:10 +01:00
gingerBill 883f6c129a Merge pull request #3643 from korvahkh/fix-omitempty-comma
encoding/json: Fix struct marshal() emitting comma after omitted field
2024-06-28 11:50:31 +01:00
gingerBill 861d51b760 Merge pull request #3825 from Valakor/wgpu
wgpu_native fixes
2024-06-28 11:49:35 +01:00
gingerBill 17efb87eef Add -custom-attribute 2024-06-28 11:44:39 +01:00
gingerBill 1747fdc3f0 Fix signature 2024-06-28 11:07:54 +01:00
gingerBill bef3ca98f0 Fix signature 2024-06-28 11:01:57 +01:00
gingerBill e15c5c4692 Fix missing import 2024-06-28 10:32:16 +01:00
gingerBill 9a4ffa79db Add missing libraries to examples/all 2024-06-28 10:17:00 +01:00
gingerBill ec38215842 Fix #3803 2024-06-28 10:09:46 +01:00
gingerBill 67e9a6fd9b Improve error reporting on "Failed to parse fail" and show the line error if possible 2024-06-28 10:04:08 +01:00
gingerBill 4824050c99 Merge pull request #3792 from Feoramund/core-uuid
Add `core:encoding/uuid`
2024-06-28 09:49:23 +01:00
gingerBill 35651cfc17 Improve tokenization for false integer literals but not effect possible float literals 2024-06-28 09:24:34 +01:00
gingerBill dde7cb6e7f Improve error message for #3754 2024-06-28 09:21:33 +01:00
gingerBill 862a04376f Improve tokenizing wrong number literals 2024-06-28 09:16:01 +01:00
gingerBill 5a9698e8cb Properly fix #3820 2024-06-28 09:08:57 +01:00
gingerBill 0c8a81d298 Fix #3819 2024-06-28 08:57:31 +01:00
gingerBill 06ff08b9cf Fix #3820 2024-06-28 08:53:05 +01:00
gingerBill 52ea63f89c Fix #3471 2024-06-28 08:43:25 +01:00
gingerBill f883cd5053 Initialize default context in heap_allocator_other.odin 2024-06-28 08:33:12 +01:00
Matthew Pohlmann 4bf9de7237 SupportedLimitsExtras.chain should be a ChainedStructOut to properly chain from SupportedLimits 2024-06-27 21:53:16 -07:00
Matthew Pohlmann 0a504c2647 Some fixes to wgpu_native.
1. LogCallback should have the "c" calling convention and takes a
   userdata pointer like other callbacks.
2. DevicePoll's wrappedSubmissionIndex argument is an optional in/out
   parameter. The previous wrapper method was broken since it passed a
   non-nil structure to the underlying API with invalid members.
2024-06-27 21:41:48 -07:00
Jeroen van Rijn d31f88bfaa Merge pull request #3823 from laytan/enforce-global-foreign-import-variables
disallow non-global foreign import of variables on wasm
2024-06-28 02:11:50 +02:00
Laytan Laats b79d7e6917 disallow non-global foreign import of variables on wasm 2024-06-28 01:34:09 +02:00
Jeroen van Rijn ed7d34beb0 Avoid sporadic wasm crash 2024-06-28 00:39:51 +02:00
Jeroen van Rijn aba274cf75 Merge pull request #3821 from Kelimion/clang_override
Allow `ODIN_CLANG_PATH=clang-path` overrides for link stage.
2024-06-27 23:36:39 +02:00
Jeroen van Rijn 140ee036ce wasm error is no longer relevant 2024-06-27 23:29:36 +02:00
Jeroen van Rijn 58cd75350b Allow ODIN_CLANG_PATH=clang-path overrides
Link using `clang`, unless overridden by `ODIN_CLANG_PATH` environment variable.

Fixes #3783
2024-06-27 23:21:58 +02:00
jason f24f72c280 convert all to use sys/linux over sys/unix; new implementations for pipe, process and env 2024-06-27 17:14:48 -04:00
jason f22754fc90 sys/linux: fix some syscalls and types; add more to Sig_Action and Sig_Info; Pid int->i32 2024-06-27 16:29:47 -04:00
Jeroen van Rijn a0a48bfe34 Fix alignment. 2024-06-27 21:56:26 +02:00
Jeroen van Rijn 9f8b84c212 Merge pull request #3815 from laytan/tlsf-fixes
tlsf: destroy first pool & properly zero memory
2024-06-27 19:50:24 +02:00
Laytan Laats 1c199f52d6 tlsf: destroy first pool & properly zero memory 2024-06-27 19:27:07 +02:00
gingerBill 521182a100 Merge pull request #3813 from tadeohepperle/fix-vulkan-codegen-arrays-as-proc-args
Fix `vender:vulkan` codegen for procedures with fixed size arrays are arguments
2024-06-27 16:34:17 +01:00
Jeroen van Rijn aa27cd4b0b Allow core:odin to parse @(require) import 2024-06-27 16:14:16 +02:00
gingerBill b1d06ea03f Merge pull request #3808 from karl-zylinski/fix-append-elem-max-confusion
Replace `max(8, 1)` in _append_elem with just `8` and a comment.
2024-06-26 21:14:08 +01:00
Jeroen van Rijn e37afa3ada Merge pull request #3814 from Kelimion/fix_fixed
Fix core:math/fixed.
2024-06-26 20:46:46 +02:00
Tadeo hepperle b834bd32f5 fix typo 2024-06-26 20:31:43 +02:00
Jeroen van Rijn 3726f0b73c Merge pull request #3812 from Feoramund/add-table-decorations
Add `write_decorated_table` to `text/table`
2024-06-26 20:15:11 +02:00
Jeroen van Rijn c33bf7673f Fix core:math/fixed. 2024-06-26 20:12:55 +02:00
Tadeo hepperle 67e69f7196 Merge branch 'master' into fix-vulkan-codegen-arrays-as-proc-args 2024-06-26 19:31:00 +02:00
Tadeo hepperle 18dadd94e3 fix proc parsing 2024-06-26 19:30:21 +02:00
Feoramund ba354e0524 Add documentation for write_decorated_table 2024-06-26 12:53:34 -04:00
Feoramund f13d30ad23 Add write_decorated_table API 2024-06-26 12:50:43 -04:00
Jeroen van Rijn 8d1827838f Merge pull request #3807 from karl-zylinski/ctprint
Added fmt.ctprint
2024-06-25 22:52:48 +02:00
Karl Zylinski f227a40652 Replace max(8, 1) in _append_elem with just 8 and a comment. 2024-06-25 22:48:14 +02:00
Karl Zylinski 4e2d12c540 Added fmt.ctprint 2024-06-25 22:32:20 +02:00
Jeroen van Rijn 5d1d98cef3 Merge pull request #3806 from NicknEma/windows_fixes
Update CommandLineToArgvW return type
2024-06-25 12:22:27 +02:00
NicknEma 845613c404 Update CommandLineToArgvW return type
It now returns a multi-pointer so it can be iterated without any casting.
2024-06-25 12:10:17 +02:00
gingerBill 93441a043a Make runtime.heap_alloc contextless 2024-06-25 09:38:49 +01:00
gingerBill c098739484 Remove @(warning) and #warning(...) 2024-06-25 09:36:59 +01:00
Jeroen van Rijn e42029c5ed wgpu ld -> dl 2024-06-25 01:35:26 +02:00
Jeroen van Rijn d97fe41834 Mark deux 2024-06-24 22:45:12 +02:00
Jeroen van Rijn d3d73590d3 Fix CSV comments. 2024-06-24 22:43:14 +02:00
Jeroen van Rijn 185e39e53d Merge pull request #3791 from Feoramund/fix-text-table-alignment
Refactor `core:text/table`
2024-06-24 21:59:33 +02:00
Feoramund 8b05ec1765 Add string caching example documentation 2024-06-24 15:11:43 -04:00
Feoramund fbd609fa37 Add complete example showcasing Unicode support 2024-06-24 15:04:45 -04:00
Feoramund f325a08e57 Make core:text/table examples more complete
They should be completely copy-and-paste friendly now, without the
assumption of someone using `using table`.
2024-06-24 15:04:45 -04:00
Feoramund 7a43404ea1 Add Width_Proc documentation 2024-06-24 15:04:45 -04:00
Feoramund 7da96c484d Remove table.dirty 2024-06-24 14:28:05 -04:00
Feoramund e397bdf11d Let WIDTH_PROC be specified as proc argument to write_*_table 2024-06-24 13:38:59 -04:00
Feoramund 67b4cb0038 Crunch the ranges 2024-06-24 13:18:54 -04:00
Jeroen van Rijn 8eafd9eb82 wgpu import 2024-06-23 22:19:29 +02:00
Feoramund ca58d7771b Use new API from_nanoseconds in uuid 2024-06-22 18:36:42 -04:00
Feoramund 8a4a3ed66e Change how Time is constructed in uuid 2024-06-22 18:21:32 -04:00
Feoramund 4481f9c695 Clarify some uuid legacy documentation 2024-06-22 18:21:32 -04:00
Feoramund 5a75cac5b9 Add API for creating custom version 8 UUIDs 2024-06-22 18:21:32 -04:00
Feoramund e9b882be05 Add vendor-specific version 8 UUID generation (hashing) 2024-06-22 18:21:32 -04:00
Feoramund 859cbf7d72 Test if v1 and v6 UUID node is set correctly 2024-06-22 18:21:32 -04:00
Feoramund d559feb701 Add uuid test for timestamps 2024-06-22 18:21:32 -04:00
Feoramund f6344577d3 Add UUID sorting tests 2024-06-22 18:21:32 -04:00
Feoramund 339b2b23f6 Add unsafe_write to uuid package 2024-06-22 18:21:32 -04:00
Feoramund 8b8f8c7f7d Address minor organizational issues 2024-06-22 18:21:32 -04:00
Feoramund 95a9c9b016 Fix indentation 2024-06-22 18:21:32 -04:00
Feoramund 9b3a104640 Add buffer-based to_string to uuid package 2024-06-22 18:21:32 -04:00
Feoramund 9b265b2309 Improve time-related API in uuid package
- Let timestamps be specified by the user.
- Change `time_v*` to `raw_time_v*` and implement an API that returns
  timestamps from the `time` package.
2024-06-22 18:21:32 -04:00
Feoramund ea771d0cb7 Update uuid package documentation 2024-06-22 18:21:31 -04:00
Feoramund fcdba334ea Require CSPRNG in UUID generation where applicable 2024-06-22 18:21:31 -04:00
Feoramund 3aa232a894 Move v3 and v5 UUID procs to uuid/legacy 2024-06-22 18:21:31 -04:00
Feoramund 9866b54d59 Add version 6 UUID generation 2024-06-22 18:21:31 -04:00
Feoramund 525bfca4ef Add version 1 UUID generation 2024-06-22 18:21:31 -04:00
Feoramund 4cfbd83b10 Add version 7 UUID generation 2024-06-22 18:21:31 -04:00
Feoramund fee81985b4 Make UUID namespaces @(rodata) 2024-06-22 18:21:31 -04:00
Feoramund 6da99b888a Make UUID Identfier only a distinct byte array 2024-06-22 18:21:31 -04:00
Feoramund 31873ed466 Fix wrong comments 2024-06-22 18:21:31 -04:00
Feoramund 4dacddd85e Add core:encoding/uuid 2024-06-22 18:21:27 -04:00
Jeroen van Rijn 3af9d31bd5 Add time.from_nanoseconds 2024-06-23 00:19:24 +02:00
Jeroen van Rijn dae9a8dfff Merge pull request #3796 from Feoramund/fix-lack-of-str-arg-or-cont
Fix print segfault by missing argument in `or_*` shadowed error
2024-06-22 17:57:02 +02:00
Feoramund f58eded5d2 Fix print segfault by missing argument in or_* shadowed error 2024-06-22 11:45:43 -04:00
Jeroen van Rijn 13c58948f4 Merge pull request #3793 from Kelimion/build_test_only
Add `-build-mode:test`
2024-06-21 16:12:13 +02:00
Jeroen van Rijn 9f696a646f Add -build-mode:test. 2024-06-21 16:02:55 +02:00
gingerBill bad4a6237e Delete misc/roadmap.md 2024-06-21 00:02:12 +01:00
Feoramund bf44a94065 Update core:text/table documentation 2024-06-20 18:22:03 -04:00
Feoramund 82d92dc46c Use log.error instead of eprintf 2024-06-20 17:53:45 -04:00
Feoramund b81458073e Add new API to core:text/table
- `header/row_of_values`, same `header/row`, more verbose name
- `aligned_header/row_of_values`, set alignment for an entire row
- `header/row_of_aligned_values`, set alignment per value
2024-06-20 17:53:45 -04:00
Feoramund 585747bbbf Clarify error message 2024-06-20 17:53:34 -04:00
Feoramund 99c955d124 Remove unneeded loc argument 2024-06-20 15:26:00 -04:00
Feoramund fd28199178 Optimize printing of markdown tables
Check only once if the table has a header row, instead of every row.
2024-06-20 15:01:09 -04:00
Feoramund dd099d9dd6 Add Unicode support to core:text/table 2024-06-20 15:01:09 -04:00
Feoramund 2241ca8e72 Use tabs to indent HTML tables 2024-06-20 13:06:32 -04:00
Feoramund b66b960e7e Don't build HTML tables
`build` only recalculates length and width information, and this is not
needed for HTML tables.
2024-06-20 13:06:32 -04:00
Feoramund 4a3684c5e8 Rename write_ascii_table to write_plain_table 2024-06-20 13:06:28 -04:00
Jeroen van Rijn 91cc006e8f Fix unaligned store for rand 2024-06-20 17:54:37 +02:00
Jeroen van Rijn ac4577ca66 Merge pull request #3790 from Feoramund/optimize-common-rng-dest-size
Optimize default RNG for the common case
2024-06-20 17:41:13 +02:00
Feoramund 1dfc89567e Optimize default RNG for the common case 2024-06-20 11:27:51 -04:00
gingerBill 28e33d86de Merge pull request #3776 from IllusionMan1212/os2-read-fix
fix(os2): check for 0 bytes read and return EOF
2024-06-20 15:37:41 +01:00
gingerBill dab3c832e0 Add #warning(<string>) builtin compile time procedure 2024-06-20 15:32:30 +01:00
Jeroen van Rijn 94a8c38d86 Add GetNumberOfConsoleInputEvents 2024-06-20 15:19:25 +02:00
gingerBill 8c760e140f Move import to a windows specific file 2024-06-20 12:38:09 +01:00
gingerBill 3db7780a2c Add vendor:wgpu to examples/all 2024-06-20 12:20:06 +01:00
gingerBill 8b446fc88d Fix wgpu paths for Windows 2024-06-20 12:18:26 +01:00
gingerBill c9884906d9 Add #directory 2024-06-20 12:15:55 +01:00
gingerBill 5dc98336a8 Merge pull request #3524 from Feoramund/freebsd-amd64-syscall-errno
Add `intrinsics.syscall_bsd`
2024-06-20 11:47:01 +01:00
gingerBill 23351ca8be Merge pull request #3137 from laytan/show-defineable
Add flags to show/export defineable values and warn if a -define is unused in the project
2024-06-20 11:45:52 +01:00
gingerBill 56383e45a7 Fix #3768 2024-06-20 11:44:00 +01:00
gingerBill 7184792f7a Merge pull request #3740 from laytan/wgpu
Add `vendor:wgpu`
2024-06-20 11:39:58 +01:00
gingerBill d4aa6c3288 Merge pull request #3788 from Beefster09/builder-utils
Add to_cstring for Builders
2024-06-20 11:34:03 +01:00
gingerBill 7703bc595c Merge pull request #3789 from Feoramund/unicode-annex-11
Measure `East_Asian_Width` during grapheme decoding
2024-06-20 11:32:06 +01:00
Feoramund e620645a03 Measure East_Asian_Width during grapheme decoding 2024-06-19 22:35:36 -04:00
Justin Snyder 1a6bb59125 drop unnecessary defer 2024-06-19 18:25:42 -06:00
Justin Snyder 271782d2f4 fix typo
apparently i had a moment of dyslexia
2024-06-19 17:53:34 -06:00
Justin Snyder 1b7c4c2efe trim added null byte 2024-06-19 17:35:16 -06:00
Jeroen van Rijn 4380934283 Merge pull request #3787 from jasonKercher/more-windows-comm
Add more bindings for comm ports and console events
2024-06-19 23:32:12 +02:00
Jeroen van Rijn 21806e5fa5 Merge pull request #3786 from fabiansperber/fix-d3d11-infoqueue
Fix d3d11 IInfoQueue_VTable & Add LoadLibraryExW
2024-06-19 23:26:40 +02:00
jason 93e67f6bec make -strict-style happy 2024-06-19 17:15:09 -04:00
jason 6b1e76985c move DCB to types.odin; add more bindings for comm functions 2024-06-19 17:04:18 -04:00
Fabian Sperber 0e9bf86123 Fix d3d11 IInfoQueue_VTable & Add LoadLibraryExW
- wrong order & was missing PushStorageFilter & PushRetrievalFilter
2024-06-19 22:22:26 +02:00
Justin Snyder 8f2c4a7ecf Add builder to_cstring 2024-06-19 11:55:19 -06:00
jason e6d84d18d3 Merge remote-tracking branch 'origin/master' into more-windows-comm 2024-06-19 12:33:13 -04:00
jason a9b6d28291 save before merging from upstream 2024-06-19 12:33:05 -04:00
Jeroen van Rijn 2797dc6452 Merge pull request #3785 from mgavioli/new_i18n_API
Separate I18N calls for immutable and for pluraliseable strings. Fixes #3687
2024-06-19 11:50:24 +02:00
Jeroen van Rijn 322b7f1f2f Spell check i18n.odin. 2024-06-19 11:41:58 +02:00
Jeroen van Rijn e0de52efa1 Spell check doc.odin. 2024-06-19 11:15:17 +02:00
Maurizio M. Gavioli 53755824fb Separate the I18N calls for immutable strings and for pluraliseable strings.
Also update tests.
2024-06-19 10:10:26 +02:00
Jeroen van Rijn 7064166da2 Merge pull request #3767 from Feoramund/use-rng-context-in-test-runner
Setup `context.random_generator` in test runner
2024-06-19 09:51:13 +02:00
Feoramund d4803583ff Work around Windows test failure
I am uncertain why this works, but it does. Previously, `rtti_test` was
failing due to non-zero data appearing in the `l_buggy` `Buggy_Struct`.

The issue was caused by calling `runtime.default_random_generator` with
a pointer to the state, somehow. The pointer could be on the stack or in
the heap; it did not matter.

I found two workarounds.

- One is to move the RNG setup behind the call to `free_all`.
- The other is to construct the random generator manually.

Despite my digging and testing, I could find no reason as to why this
works or what the fundamental issue was to begin with. If anyone comes
upon this in the future with direct access to a Windows machine, I
recommend stepping through the program with a debugger to investigate
more deeply into why this happens.
2024-06-18 23:21:04 -04:00
Jeroen van Rijn dff8a9153e Merge pull request #3781 from Feoramund/add-missing-test-imports
Add missing imports to `core` test suite
2024-06-18 18:20:02 +02:00
Feoramund e3f4772d01 Fix removal of temporary file in core:flags test 2024-06-18 11:06:49 -04:00
IllusionMan1212 c987b964c8 fix(os2): check for 0 bytes read and return EOF 2024-06-18 17:03:54 +02:00
Feoramund 6b25d17ef9 Add missing imports to core test suite 2024-06-18 10:38:43 -04:00
gingerBill 3d9db56410 Minor formatting changes to unicode stuff 2024-06-18 12:53:56 +01:00
gingerBill 02cd53d42c Merge pull request #3700 from Feoramund/core-flags
Add package `core:flags`
2024-06-18 12:48:57 +01:00
gingerBill de23965ecb Merge pull request #3775 from Feoramund/unicode-graphemes
Add grapheme analysis facilities to `core:unicode`
2024-06-18 12:48:31 +01:00
gingerBill e8c17ac356 Merge pull request #3778 from Feoramund/fix-2824
Allow custom `main` when `-no-entry-point` is set
2024-06-18 12:46:33 +01:00
gingerBill dc03e8380d Merge pull request #3779 from karl-zylinski/clarify-usage-of-temp-allocator-arena
Clarify when the arena in base:runtime should be used
2024-06-18 12:45:43 +01:00
Jeroen van Rijn aad7ddf2d1 Merge pull request #3780 from destroycomputers/fix/rbtree/key-ordering-constraint
Loosen constraint on the Key type in rb & avl tree
2024-06-18 13:42:36 +02:00
destroycomputers de44dd5412 Loosen constraint on the Key type in rb & avl tree
The current constraint on the `init_ordered' function accepts only
numeric types. While one still can init a non-numerically-keyed tree by
passing a comparator explicitly, the reason to disallow non-numeric
ordered types is nowhere to be found.
2024-06-18 13:31:45 +02:00
Karl Zylinski 11e586494b Clarify that the arena in base:runtime shouldn't be used for anything but the default temp allocator. This is done by renaming the file in which it lives, and also by improving the comment above Arena :: struct {. This should avoid some confusion where people end up using the Arena in base:runtime because they thought it was the 'default arena'. 2024-06-18 12:48:16 +02:00
Jeroen van Rijn dd364c0c0f Merge pull request #3777 from Feoramund/fix-3047
Forbid private test cases
2024-06-18 12:09:58 +02:00
Feoramund 0196cc46e3 Allow custom main when -no-entry-point is set 2024-06-18 01:49:55 -04:00
Feoramund eb5a66c944 Forbid private test cases 2024-06-18 01:28:05 -04:00
Feoramund 9e4899d35c Add tests for decode_grapheme_clusters 2024-06-17 21:57:32 -04:00
Feoramund 63973f431e Make core:unicode letter procs @(require_results) 2024-06-17 21:57:32 -04:00
Feoramund 1620a69398 Add decode_grapheme_clusters to core:unicode/utf8 2024-06-17 21:57:32 -04:00
Feoramund 1a93dfd28f Fix indentation 2024-06-17 13:24:47 -04:00
gingerBill f280ba8511 Merge pull request #3756 from matias-eduardo/empty_structs_hash_fmt
Handle empty structs in hash (#v) fmt
2024-06-16 19:54:28 +01:00
Jeroen van Rijn a66ce4f871 Merge pull request #3773 from Kelimion/res_path_bug
Fix `rc.exe` bug with double-quoted `.res` path.
2024-06-16 19:27:13 +02:00
Jeroen van Rijn fe3baae7a6 Merge pull request #3772 from Feoramund/fix-constant-wrong-type-bitset
Fix `bit_set` construction crash on constant non-integer field
2024-06-16 19:15:50 +02:00
Jeroen van Rijn eebc0dd026 Fix rc.exe bug with double-quoted .res path. 2024-06-16 19:11:54 +02:00
Feoramund 78a5a27212 Fix bit_set construction crash on constant non-integer field 2024-06-16 12:27:42 -04:00
Jeroen van Rijn 339bafe6ff Merge pull request #3770 from skaman/fix-slice-unique
Fix `slice.unique` wrong result
2024-06-16 13:48:21 +02:00
Jeroen van Rijn 0268be1925 Add tests for slice.unique and slice.unique_proc 2024-06-16 13:41:25 +02:00
Sandro Cavazzoni e41878a64f Fix slice.unique wrong result
When you try to make this array unique `[]int{1, 2, 4, 4, 5}` you get
`[]int{1, 4, 5}` instead of `[]int{1, 2, 4, 5}`.
Our index `i` should be increased even with both indices `i` and `j`
have the same value
2024-06-16 11:36:20 +02:00
Feoramund 8b31cddaba Keep -vet happy 2024-06-15 15:49:05 -04:00
Feoramund aab5338134 Add tests for core:math/rand 2024-06-15 15:49:05 -04:00
Feoramund 1a52cf1f1c Use test's random generator
This removes the `create` calls when a test was only setting up a
generator, and it replaces them with `reset` when run in a loop.
2024-06-15 15:49:05 -04:00
Feoramund 5dfd303fd1 Setup default context.random_generator for tests 2024-06-15 15:44:56 -04:00
gingerBill a619ea3bcd Merge pull request #3766 from Feoramund/fix-rng-state
Fix `default_random_generator_proc` not using state
2024-06-15 20:36:10 +01:00
Feoramund 53140dca15 Fix default_random_generator_proc not using state 2024-06-15 12:54:30 -04:00
Jeroen van Rijn ed99e77433 Merge pull request #3765 from Feoramund/add-short-test-logs
Add `ODIN_TEST_SHORT_LOGS` define
2024-06-15 18:01:49 +02:00
gingerBill bacb915ff8 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-06-15 16:24:07 +01:00
gingerBill e41ad2bf16 to_random_generator -> random_generator 2024-06-15 16:24:01 +01:00
gingerBill 4c7469a264 Merge pull request #3764 from Feoramund/test-runner-fixes
Fix half-implemented features in the test runner
2024-06-15 16:19:58 +01:00
Feoramund 753516c392 Add ODIN_TEST_SHORT_LOGS define
Strips out the procedure, date, and time information, for when you just
need to know the file, line, and message.
2024-06-15 11:18:40 -04:00
Feoramund f353adc7fb Prefer log.error over fail_now in this case 2024-06-15 10:53:21 -04:00
Feoramund bb823d5ba0 Make testing.fail_now divergent
This is in line with the old way it worked on Windows.
2024-06-15 10:53:21 -04:00
gingerBill 1c940e3968 Remove dead variable 2024-06-15 15:53:16 +01:00
gingerBill c97ffbecbc Fix rand in container tests 2024-06-15 15:50:35 +01:00
gingerBill 2380720fa2 Fix core:sync/chan for rand 2024-06-15 15:46:48 +01:00
Feoramund 784408358d Call cleanups after test signal 2024-06-15 10:46:47 -04:00
gingerBill 149ecafdef Remove the need for rand in core:math/big 2024-06-15 15:43:57 +01:00
gingerBill 7ec17ecf98 Update core:math/rand to use context.random_generator and remove rand.Rand 2024-06-15 15:33:24 +01:00
gingerBill 318d5e4a7e Add Reset mode 2024-06-15 15:17:23 +01:00
gingerBill eaec8a2bbf Add runtime.default_random_generator 2024-06-15 15:08:49 +01:00
gingerBill c2a01096c4 Remove unneeded reassignment of r 2024-06-15 14:49:09 +01:00
gingerBill 827cb24023 Add random_generator.odin 2024-06-15 14:47:37 +01:00
gingerBill dc4ec8638c Add runtime.Random_Generator interface 2024-06-15 14:45:57 +01:00
Jeroen van Rijn 94ec647923 Merge pull request #3750 from Kelimion/dcb_bitfield
Update kernel32 struct DCB.
2024-06-15 12:14:27 +02:00
Feoramund 51a013fcf1 Work around BSD lack of core:net support 2024-06-15 01:32:48 -04:00
Feoramund f28c6c3bba Keep -vet happy 2024-06-15 00:50:12 -04:00
Feoramund 53e2cdf7af Add core:flags to examples/all 2024-06-15 00:28:47 -04:00
Feoramund 76575e834b Raise error on spaced UNIX-style flag with no value 2024-06-15 00:24:59 -04:00
Feoramund 42a5a2cf17 Fix memory leak in core:flags validation 2024-06-15 00:01:33 -04:00
Feoramund c3acdeb310 Add -- parsing to UNIX-style core:flags
This will allow a user to indicate all arguments after `--` are parsed
into the variadic array.
2024-06-14 23:59:01 -04:00
Feoramund d4e2fa0377 Refactor show_error_on_line
This should adequately solve any issues with Unicode alignment by
sidestepping the issue entirely. With this change, we make use of the
built-in ANSI facilities of the terminal to underline the text.

If the terminal does not support underlining, there are still the
fallback bold markers at the start and end of error locations.
2024-06-14 18:28:47 -04:00
Feoramund 582154f20d Remove unused code from tokenizer 2024-06-14 15:44:50 -04:00
Jeroen van Rijn 908a6ff2d4 Elide unnecessary condition 2024-06-14 21:34:05 +02:00
Jeroen van Rijn 09b3f5a7a7 Merge pull request #3757 from thetarnav/patch-2
Add `#no_bounds_check` to `slice.equal`
2024-06-14 21:27:21 +02:00
Jeroen van Rijn fa4fbbe1ce Merge pull request #3758 from jones-josh/master
Fix big.shrink not actually shrinking
2024-06-14 20:27:03 +02:00
Josh Jones 759139089f Fix big.shrink not actually shrinking 2024-06-14 19:58:13 +02:00
Damian Tarnawski 8ba644dd79 Add #no_bounds_check to slice.equal 2024-06-14 19:45:54 +02:00
Feoramund 8626d38db1 Fix displaying emptiness when error is on first line 2024-06-14 13:02:54 -04:00
Jeroen van Rijn b19bf5bbda Merge pull request #3732 from FrancisTheCat/master
add missing functions to core:sys/windows
2024-06-14 17:57:23 +02:00
Feoramund ca481dc52d Fix displaying error on wrong line with token at EOL
Previously, this would get a token on text like "\n*\n" where `*`
is the token's position, and it would advance off that line.
2024-06-14 11:51:03 -04:00
Franz Höltermann c3302615a3 Merge branch 'master' of https://github.com/FrancisTheCat/Odin 2024-06-14 17:43:09 +02:00
Franz Höltermann 3c3f0f90c2 Fixed WinEventFlags 2024-06-14 17:41:21 +02:00
FrancisTheCat cd5fa8523f Merge branch 'odin-lang:master' into master 2024-06-14 16:34:21 +02:00
Franz Höltermann ec7b77fc0f Improved win32 bindings according to Kelimions suggestions with enums and bitsets 2024-06-14 16:32:41 +02:00
Matias Fernandez 4baf101f15 Handle empty structs in fmt with hash 2024-06-14 05:36:23 -04:00
Jeroen van Rijn ff4787070d Revert "Merge pull request #3744 from Mango0x45/master"
This reverts commit 45044de0b7, reversing
changes made to 20c17ba6f9.
2024-06-14 00:06:55 +02:00
Jeroen van Rijn 54a3cfb540 Merge pull request #3753 from Feoramund/fix-silent-token-fail
Fix compiler silently returning if `parse_packages` fails
2024-06-13 19:33:02 +02:00
Feoramund c560553c21 Fix compiler silently returning if parse_packages fails 2024-06-13 13:01:51 -04:00
Jeroen van Rijn 45044de0b7 Merge pull request #3744 from Mango0x45/master
Pad ‘^~~~^’-style diagnostic ranges properly
2024-06-13 17:34:17 +02:00
Jeroen van Rijn c9c7d3270d Merge branch 'master' of https://github.com/Mango0x45/Odin into pr/3744 2024-06-13 17:27:00 +02:00
Thomas Voss 9f7ac1469f Generate ranges of the correct length 2024-06-13 17:24:56 +02:00
Jeroen van Rijn ca9d1f940d Just change squiggle_extra type to i32. 2024-06-13 17:23:30 +02:00
Thomas Voss 9f190f3937 Generate ranges of the correct length 2024-06-13 17:00:13 +02:00
Thomas Voss 657c516360 Pad ‘^~~~^’-style diagnostic ranges properly 2024-06-13 16:23:34 +02:00
Jeroen van Rijn 20c17ba6f9 Merge pull request #3751 from Kelimion/custom_formatter
Add example of a custom formatter.
2024-06-13 11:42:38 +02:00
Jeroen van Rijn 3d4e23d741 Add example of a custom formatter. 2024-06-13 11:33:37 +02:00
Jeroen van Rijn 50564a301e Update kernel32 struct DCB. 2024-06-13 10:22:44 +02:00
Jeroen van Rijn f8f6f2dada Merge pull request #3749 from Feoramund/fix-w
Improve support for `%w`
2024-06-13 10:07:48 +02:00
korvahkh 104ca2ce22 Merge branch 'odin-lang:master' into fix-omitempty-comma 2024-06-13 01:27:44 +00:00
Feoramund abe5c2ca83 Add test for %w 2024-06-12 21:07:15 -04:00
Feoramund 0c9f487783 Fix and document %w verb for core:fmt 2024-06-12 20:35:50 -04:00
gingerBill a67df07392 Merge pull request #3742 from karl-zylinski/fix-raymath-matrix-to-float
Make rl.MatrixToFloatV do same thing in Odin as in C
2024-06-12 23:15:48 +01:00
Jeroen van Rijn 05972eb26b Merge pull request #3746 from jasonKercher/add-commtimeouts
add COMMTIMEOUTS, get/setCommTimeouts
2024-06-12 21:50:10 +02:00
gingerBill 4ccc473e97 Merge pull request #3745 from karl-zylinski/rlgl-add-missing-types
rlgl: Pull in raylib and expose missing types
2024-06-12 20:48:22 +01:00
gingerBill 90815452ca Merge pull request #3747 from Feoramund/fix-3739
Fix #3739
2024-06-12 20:48:02 +01:00
jasonkercher a804463a57 add COMMTIMEOUTS, get/setCommTimeouts 2024-06-12 15:31:59 -04:00
Feoramund 33270f14a4 Fix #3739 2024-06-12 15:31:43 -04:00
Karl Zylinski c7ea4ec71c rlgl: Pull in raylib and expose missing types, so it is the same as rlgl.h. This makes rlgl less stand-alone, but I left some notes in rlgl.odin how to easily make it stand-alone if one really wants to. 2024-06-12 21:13:12 +02:00
Karl Zylinski d37b5a7b67 Make rl.MatrixToFloatV transpose the matrix before transmuting it to [16]f32, so it does the same thing as the raymath version implemented in C. 2024-06-12 19:54:14 +02:00
Feoramund 1128bd1d7f Use syscall_bsd on NetBSD 2024-06-12 13:34:36 -04:00
Feoramund 20c32c807d Fix info.init_os_version on FreeBSD
It's possible for the return string to be longer than 128 characters
these days, so I've increased it to 1024, same as the other BSDs.

SYSCTL was otherwise erring out due to lack of buffer space.
2024-06-12 13:10:19 -04:00
Feoramund 5b5402fb23 Add intrinsics.syscall_bsd
This is a BSD-style syscall that checks for a high Carry Flag as the
error state. If the CF is high, the boolean return value is false, and
if it is low (no errors) then the boolean return value is true.
2024-06-12 13:07:13 -04:00
Laytan Laats 108b8feb35 Add vendor:wgpu 2024-06-12 17:22:02 +02:00
Jeroen van Rijn 603581aa53 Merge pull request #3738 from Kelimion/xml_attr
Xml attr
2024-06-12 14:06:40 +02:00
gingerBill c5f7788652 Check to see if matrices are exactly the same type 2024-06-12 12:54:57 +01:00
gingerBill f57c03c170 Improve matrix type hinting rules a little 2024-06-12 12:40:29 +01:00
Jeroen van Rijn 2fe961cbcd Fold XML attribute whitespace. 2024-06-12 13:30:00 +02:00
Jeroen van Rijn ebadff555d Update XML reader to normalize whitespace, part 1. 2024-06-12 12:52:48 +02:00
gingerBill cb45aa58fd Merge pull request #3731 from karl-zylinski/rlgl-subpackage
Move rlgl to vendor:raylib/rlgl
2024-06-12 11:51:16 +01:00
gingerBill e87c5bca58 Merge pull request #3737 from karl-zylinski/raylib-shader-location-index-any-int
Made rl.SetShaderValue etc take a c.int like in original raylib
2024-06-11 21:45:40 +01:00
Jeroen van Rijn 0398388a59 Merge pull request #3729 from Feoramund/fix-3460
Fix #3460
2024-06-11 20:32:37 +02:00
Karl Zylinski 1a22f82f94 Changed rl.SetShaderValue etc to take a c.int like in original raylib.h. You should be able to use other values than the ShaderLocationIndex enum, that enum is only for build in things in raylib. Added #any_int on those procs so you can pass both int and also a ShaderLocationIndex. 2024-06-11 18:03:20 +02:00
gingerBill 35a845b93f Fix indentation 2024-06-11 13:12:41 +01:00
gingerBill 3ff8952813 Replace panic(fmt.tprintf( antipattern with fmt.panicf 2024-06-11 13:11:14 +01:00
gingerBill 56c5e93fd1 Merge pull request #3728 from Feoramund/mem-any-int
Use `#any_int` for `reserve_*` and `resize_*` procs
2024-06-11 12:52:50 +01:00
gingerBill 39b166edd3 Merge pull request #3733 from Feoramund/ci-freebsd
Add FreeBSD to the CI
2024-06-11 12:51:42 +01:00
gingerBill eaf1d88287 Merge pull request #3734 from Feoramund/fix-3730
Fix #3730
2024-06-11 12:50:41 +01:00
gingerBill 1dc90103bd Make verification ignorable with a define flag 2024-06-11 12:30:24 +01:00
gingerBill 0b02c67cdf Minor clean up for backend 2024-06-11 12:19:52 +01:00
gingerBill 9b0e87544a Unify LLVMVerifyFunction invocations into on place 2024-06-11 12:07:22 +01:00
Feoramund 61c630bbf8 Fix #3730 2024-06-11 05:23:43 -04:00
Feoramund 0e6bcd0dbb Add FreeBSD to CI 2024-06-11 04:16:42 -04:00
Feoramund fc88de12c2 Implement absolute_path_from_handle for FreeBSD 2024-06-11 04:16:42 -04:00
Feoramund a3da796d54 Fix file_size on FreeBSD
It was using the generic UNIX `fstat` implemented in Odin, which is more
than what is needed here.

This also avoids the issue of needing a proper
`absolute_path_from_handle` implementation for it to work without error.
2024-06-11 03:55:41 -04:00
Feoramund 40e99ebb10 Fix file open O_* flags on FreeBSD 2024-06-11 03:55:41 -04:00
Feoramund c68560c573 Use correct __error link name for FreeBSD 2024-06-11 03:55:41 -04:00
Feoramund 76292c8ed5 Forbid all BSDs from running core:net tests
`net` is not yet implemented on them.
2024-06-11 03:55:41 -04:00
Franz Höltermann c6c00c706a Merge branch 'master' of https://github.com/odin-lang/Odin 2024-06-11 09:37:20 +02:00
Franz Höltermann 6454c6f087 Added some missing functions to core/sys/windows 2024-06-11 09:35:59 +02:00
Karl Zylinski c9e732d141 rlgl.RLGL_VERSION -> rlgl.VERSION 2024-06-11 08:59:30 +02:00
Karl Zylinski d2cd96c3c8 Made rlgl.odin work as a subpackage of raylib. So now you import vendor:raylib/rlgl. Instead of rl.rlBegin(rl.RL_TRIANGLES) you now type rlgl.Begin(rlgl.TRIANGLES). 2024-06-11 08:46:44 +02:00
Karl Zylinski 34af2bb8ad Moved rlgl.odin to subpackage 'raylib/rlgl' 2024-06-11 08:34:45 +02:00
Feoramund bd198aeada Fix #3460 2024-06-10 23:37:54 -04:00
Feoramund 50464bdce3 Use #any_int for reserve_* and resize_* procs
Resolves #3088
2024-06-10 20:51:58 -04:00
gingerBill f1779c85de Fix #3727 2024-06-10 18:50:53 +01:00
gingerBill 903e254e36 Merge pull request #3725 from laytan/add-forced-shutdown-to-test-runner
add forced shutdown to new test runner
2024-06-10 15:08:09 +01:00
gingerBill eef2aef021 Fix #3724 2024-06-10 15:07:45 +01:00
gingerBill c1e81dc14d Fix #3726 2024-06-10 15:05:24 +01:00
gingerBill fa3cae2bb0 Add intrinsics.procedure_of
```odin
foo :: proc(x: $T) { fmt.println(x) }
bar :: intrinsics.procedure_of(foo(int(123))) // parameters are never ran at compile time, similar to `size_of`
bar(333) // prints 333
```
2024-06-10 15:02:34 +01:00
Laytan Laats 71929f737b add forced shutdown to new test runner
Currently, a Ctrl+c starts a graceful shutdown of the tests and runner.
Sometimes tests get stuck and this would never complete.

This simply adds an extra step, if Ctrl+c is given for the second time,
just `os.exit` right away.
2024-06-10 15:35:23 +02:00
gingerBill 1945218f6d Improve parsing for label: #reverse for and label: #partial switch 2024-06-10 14:18:33 +01:00
Jeroen van Rijn bedeaa34d9 Merge pull request #3723 from Feoramund/use-final-march
Use `get_final_microarchitecture()` for `ODIN_MICROARCH_STRING`
2024-06-10 11:40:01 +02:00
Feoramund 71a812e7fe Use get_final_microarchitecture() for ODIN_MICROARCH_STRING 2024-06-10 05:30:16 -04:00
Jeroen van Rijn 741ee00b64 Merge pull request #3721 from Feoramund/add-tuning-consts
Add compilation-related constants
2024-06-10 10:31:12 +02:00
Jeroen van Rijn d3ae70264e Merge pull request #3720 from Feoramund/fix-force-inline-err-typo
Fix typo in a `#force_inline` error message
2024-06-10 10:25:09 +02:00
Jeroen van Rijn c8b376f07f Merge pull request #3719 from Feoramund/fix-orbranch-error
Fix `or_or_<branch>` error message
2024-06-10 10:21:05 +02:00
Feoramund ff7fcb6d38 Add compilation-related constants
`ODIN_VERSION_HASH` is the `git` SHA hash of the commit the Odin
compiler was built with.

`ODIN_MICROARCH_STRING` is the string passed to `-microarch` when
the program was built.

`ODIN_OPTIMIZATION_MODE` is an enum value of which optimization mode was
used to build the program.
2024-06-10 03:47:20 -04:00
Feoramund 45d1328a85 Fix typo in a #force_inline error message 2024-06-10 00:50:16 -04:00
Feoramund 8702bf00d5 Remove _ in Syntax_Error verbose message 2024-06-09 22:47:43 -04:00
Feoramund 9d28f2e18c Fix or_or_<branch> error messages 2024-06-09 22:46:45 -04:00
Jeroen van Rijn 5985c6e3df Merge pull request #3718 from Feoramund/add-missing-big-atoi-alias
Add missing `string_to_int` alias in `core:math/big`
2024-06-10 03:58:56 +02:00
Jeroen van Rijn 82e2d1916f Merge pull request #3717 from Feoramund/big-combo
Add permutation & combination procs to `core:math/big`
2024-06-10 03:47:55 +02:00
Feoramund 70820c2c40 Add missing string_to_int alias in core:math/big 2024-06-09 21:42:31 -04:00
Feoramund fe5c278fca Add test for core:math/big permutation & combination procs 2024-06-09 20:42:09 -04:00
Feoramund f0d65112b8 Rename math/big test package
This is in line with the other tests, and it does not seem to affect
building the library.
2024-06-09 20:42:07 -04:00
Feoramund 5fbd876db1 Add permutation & combination procedures to core:math/big 2024-06-09 20:42:04 -04:00
Jeroen van Rijn 4ea593bde0 Merge pull request #3716 from Feoramund/slice-permute
Add in-place permutation iterator to `core:slice`
2024-06-09 22:42:43 +02:00
Feoramund 047b505836 Add test for slice.permute 2024-06-09 16:15:43 -04:00
Feoramund 1f64d8d5bd Add slice.permute 2024-06-09 16:15:41 -04:00
gingerBill 7c529e990d Add -target:freestanding_arm32 (experimental) 2024-06-09 17:48:46 +01:00
gingerBill 828870004b Change indentation 2024-06-09 17:15:08 +01:00
Jeroen van Rijn 7e60e21934 Merge pull request #3714 from Kelimion/png_cleanup
PNG cleanup
2024-06-09 18:09:17 +02:00
Jeroen van Rijn 5be7d8e32d Clean up PNG code. 2024-06-09 17:59:59 +02:00
Jeroen van Rijn fc2ba81be0 Merge branch 'master' into png_cleanup 2024-06-09 17:13:43 +02:00
gingerBill edcbca51c3 Merge pull request #3684 from odin-lang/tlsf-allocator
`core:mem/tlsf` - "Two-Level Segregated Fit" memory allocator
2024-06-09 15:54:46 +01:00
Jeroen van Rijn 3c7e2659ac Merge branch 'master' into tlsf-allocator 2024-06-09 16:42:23 +02:00
Jeroen van Rijn 6b88d0a820 Use new blend helper 2024-06-09 16:37:27 +02:00
Jeroen van Rijn d2a2c1e74e Image: Add improved blending method and test it. 2024-06-09 16:10:06 +02:00
gingerBill ef7c6b9895 Re Fix #3713 2024-06-09 14:07:07 +01:00
gingerBill c17981ac38 Add edge case to error_operand_no_value 2024-06-09 14:02:01 +01:00
gingerBill 4b52f7fe2b Fix #3713 2024-06-09 13:35:22 +01:00
gingerBill 8fcfd8c506 Fix sign flag 2024-06-09 13:21:22 +01:00
gingerBill e0d0dc704c Make f32(u8) etc do an immediate cast to f32(u32(u8)) in code generation 2024-06-09 13:20:48 +01:00
Jeroen van Rijn 14f08ff02b Merge pull request #3712 from laytan/fix-large-ints-amd64sysv-abi
fix large ints amd64 sysv abi
2024-06-09 11:01:31 +02:00
Jeroen van Rijn 5d5ef78de9 Merge pull request #3711 from laytan/fix-swizzle-crash
fix swizzle crash due to wrong alignment
2024-06-09 11:00:15 +02:00
Jeroen van Rijn e595bdc805 Merge pull request #3710 from laytan/fix-unreachable-with-complex-param-or-return-inits
fix unreachable hit when param and/or return have complex inits
2024-06-09 10:59:26 +02:00
Laytan Laats 6d862cc4e5 fix unreachable hit when param and/or return have complex inits
Fixes #3630
2024-06-09 04:43:19 +02:00
Laytan Laats 3628154849 fix swizzle crash due to wrong alignment
Fixes #3691
2024-06-09 03:33:23 +02:00
Laytan Laats 9ad9236c3b fix large ints amd64 sysv abi
Fixes #3707
2024-06-09 02:47:05 +02:00
Jeroen van Rijn 0d698c7b53 Merge pull request #3709 from Feoramund/stop-low-swizzle
Prevent panic when `swizzle` called with < 2 indices
2024-06-08 23:14:55 +02:00
Feoramund 49f147cc86 Prevent panic when swizzle called with < 2 indices
The requirement for at least 2 indices has been sourced from
`lb_addr_swizzle` in `llvm_backend_general.cpp`, where there is an
assert to ensure the swizzle_count is `1 < n <= 4`.
2024-06-08 17:05:00 -04:00
Jeroen van Rijn e5bf6fd3aa Merge pull request #3708 from Feoramund/ignore-bmp-assets
Add `*.bmp` to core tests `.gitignore`
2024-06-08 22:45:08 +02:00
Feoramund 5c8f78a25a Add *.bmp to core tests .gitignore 2024-06-08 16:43:45 -04:00
Jeroen van Rijn 1f4cfd52fd Merge pull request #3706 from leidegre/os_read_dir_windows
Fixed error handling in read_dir on Windows
2024-06-08 17:14:49 +02:00
gingerBill be0774acc8 Add error message on return a constant slice value from a procedure 2024-06-08 16:07:28 +01:00
Jeroen van Rijn de7d3e2487 Update dir_windows.odin 2024-06-08 17:00:38 +02:00
gingerBill 7e994b6d21 Remove empty line preventing a suggestion from happening 2024-06-08 15:42:19 +01:00
John Leidegren 35e57fdef8 Fixed error handling in read_dir on Windows 2024-06-08 15:58:34 +02:00
gingerBill 371749d474 Make certain procedures "contextless" for microui 2024-06-08 14:48:04 +01:00
Jeroen van Rijn 575e5a255b Merge pull request #3704 from Feoramund/fix-fmt-p-verb
Fix `%p` pointers not printing leading `0x`
2024-06-07 23:00:29 +02:00
Jeroen van Rijn 323a6e0728 Nuke ancient comment. 2024-06-07 22:19:01 +02:00
Feoramund affd48c791 Add #caller_location to check in fmt tests
This makes it much easier to track down which line failed.
2024-06-07 16:08:37 -04:00
Feoramund b65589d036 Add %p tests for fmt 2024-06-07 16:07:11 -04:00
Feoramund 61c481bd81 Fix %p pointers not printing leading 0x 2024-06-07 15:27:43 -04:00
Jeroen van Rijn 96c06185dd Merge pull request #3701 from laytan/fix-thread-deadlock
Fix thread deadlock
2024-06-07 20:39:40 +02:00
Laytan Laats 00dfff7ee0 core/thread: fix a deadlock situation on unix 2024-06-07 20:28:09 +02:00
Laytan Laats b35e72c82b core/sync: fix wrong timeout calculation, time.Duration is ns already 2024-06-07 20:27:33 +02:00
Feoramund edb685f04b Add package core:flags 2024-06-07 13:16:13 -04:00
Jeroen van Rijn 7c977bb859 Merge pull request #3699 from laytan/macos-14.5
add MacOS 14.5 to 'core:sys/info' and 'odin report'
2024-06-07 17:44:09 +02:00
Laytan Laats 072825ac5a add MacOS 14.5 to 'core:sys/info' and 'odin report' 2024-06-07 17:42:41 +02:00
Jeroen van Rijn 4c45f7d3ae Merge pull request #3698 from laytan/utilize-odin-test-instead-of-scrips-to-run-tests
Utilise `odin test` instead of scripts to run tests
2024-06-07 17:36:23 +02:00
Jeroen van Rijn 11137cfec5 Merge pull request #3697 from laytan/add-error-message-for-unknown-test-log-level
add error message for unknown test log level
2024-06-07 17:11:48 +02:00
Laytan Laats e627fcb0e6 fix not printing Error: when terminal has no color support 2024-06-07 16:58:23 +02:00
Laytan Laats 29250f2657 fix regression in test_issue_2395 2024-06-07 16:33:38 +02:00
Laytan Laats 9122c20d4b update actions/checkout 2024-06-07 15:57:09 +02:00
Laytan Laats 0a528777e8 utilize odin test -all-packages instead of (make/bat) scripts for running tests 2024-06-07 15:50:00 +02:00
Laytan Laats f2be35f1f0 remove caught unused define 2024-06-07 15:22:14 +02:00
Laytan Laats ee93d7c05e add error message for unknown test log level
It would previously just be a compilation error about a missing
return statement.
2024-06-07 15:13:09 +02:00
Laytan Laats 315695b4f8 collect and show docs of defineables 2024-06-07 15:08:41 +02:00
gingerBill 68781f8dd3 Remove unnecessary Wait_Signal checks 2024-06-07 00:11:00 +01:00
gingerBill 1d99bc0f87 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-06-06 23:55:54 +01:00
gingerBill 7044a7d776 Try to fix a possible race condition with polymorphic record parameters 2024-06-06 23:55:48 +01:00
Jeroen van Rijn 4b6fe2baa7 Merge pull request #3696 from Kelimion/bmp_save
BMP save
2024-06-07 00:23:55 +02:00
Jeroen van Rijn ed060819f3 Test roundtripping BMP 2024-06-07 00:14:15 +02:00
Jeroen van Rijn 566119ff83 Add saving of 24 and 32-bit images to BMP format. 2024-06-06 23:53:15 +02:00
gingerBill 08612423b9 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-06-06 21:03:44 +01:00
gingerBill ff37a7435c Add parentheses around the foreign import paths 2024-06-06 21:03:35 +01:00
Laytan Laats fa08690686 explicit integer conversions 2024-06-06 19:49:51 +02:00
Laytan Laats b818a77131 check if -define is actually used 2024-06-06 19:46:01 +02:00
Laytan Laats 9a95049393 -show-defineables and -export-defineables 2024-06-06 19:44:54 +02:00
Jeroen van Rijn b196b84ef2 Merge pull request #3695 from laytan/fix-linking-on-weird-linuxes
fix linking on weird linuxes
2024-06-06 19:37:31 +02:00
Laytan e2eb3cdd8a fix linking on weird linuxes 2024-06-06 19:23:36 +02:00
gingerBill d0dbe9a1bd Merge branch 'master' of https://github.com/odin-lang/Odin 2024-06-06 17:59:19 +01:00
gingerBill 039bb8794a Improve matrix_align_of logic when it has invalid inputs. 2024-06-06 17:59:12 +01:00
gingerBill f010544eff Merge pull request #3609 from Kelimion/bmp
Add core:image/bmp
2024-06-06 16:29:35 +01:00
Jeroen van Rijn 4a290f47ad Re-add BMP test suite download. 2024-06-06 16:55:03 +02:00
Jeroen van Rijn 678fdae966 Rebased. 2024-06-06 16:32:18 +02:00
gingerBill 3a9b86628a Add @(rodata) and @(static, rodata) where appropriate 2024-06-06 15:23:52 +01:00
gingerBill bea47db495 Allow @(rodata) on @(static) variables 2024-06-06 15:20:47 +01:00
gingerBill 9ef43fc782 Add @(rodata) 2024-06-06 15:16:34 +01:00
Jeroen van Rijn 28ea9425fd Add core:mem tests. 2024-06-06 14:59:19 +02:00
Jeroen van Rijn 72f6b5479d Fix fls_uint 2024-06-06 14:42:19 +02:00
Jeroen van Rijn 0b6d73c86e Add original LICENSE 2024-06-06 14:29:28 +02:00
gingerBill 971229fe66 Fix #3686 2024-06-06 13:27:55 +01:00
gingerBill c4ef8e7f6c Merge branch 'master' of https://github.com/odin-lang/Odin 2024-06-06 13:02:16 +01:00
gingerBill 155516b897 Fix -ignore-warnings 2024-06-06 13:02:08 +01:00
Jeroen van Rijn 9b66b0c8e6 Merge pull request #3694 from rope-hmg/master
Updated SDL_CreateTexture to take `PixelFormatEnum` instead of `u32`
2024-06-06 13:03:16 +02:00
Hector 483015fe57 Updated SDL_CreateTexture to take PixelFormatEnum instead of u32 2024-06-06 11:47:59 +01:00
gingerBill a73741d3b7 Merge pull request #3690 from laytan/orcas
Runtime support for orca
2024-06-06 11:03:51 +01:00
Jeroen van Rijn fb2849e02e Merge pull request #3693 from colrdavidson/x11-title-change-support
Add support functions for title changes, cursor config, and dnd
2024-06-06 11:48:16 +02:00
Colin Davidson 70592630a4 add support for title changes, cursor config, and dnd 2024-06-06 02:39:48 -07:00
Jeroen van Rijn fcfc1cb97f Nightly ZIP level 9 2024-06-05 22:26:03 +02:00
Jeroen van Rijn cdd90a9a0b Merge pull request #3688 from Kelimion/nightly
Rewrite upload_b2 nightly action against B2 SDK
2024-06-05 21:11:25 +02:00
Jeroen van Rijn 460ffe1aee Rewrite upload_b2 nightly action against B2 SDK 2024-06-05 21:04:35 +02:00
laytan 08382cb05d orca windows 2024-06-05 19:28:40 +02:00
Laytan Laats 8455e159f5 improve orca target 2024-06-05 20:57:39 +02:00
gingerBill 76d3be7912 Merge pull request #3683 from andreas-jonsson/test-make-cleanup
Minor cleanup of makefiles and scripts
2024-06-05 15:44:27 +01:00
gingerBill 97f0f72080 Merge pull request #3685 from markersniffen/sniffen
D3D11.odin - fix VIDEO_SUPPORT flag
2024-06-05 15:43:55 +01:00
gingerBill a667878d23 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-06-05 15:43:21 +01:00
gingerBill cbabcb0907 Fix #3682 2024-06-05 15:43:15 +01:00
gingerBill fac9ce5d83 Change to init from create 2024-06-05 15:30:35 +01:00
gingerBill d3342c2381 core:mem/tlsf - "Two-Level Segregated Fit" memory allocator 2024-06-05 15:15:39 +01:00
Mark Sniffen cd4375061c D3D11 - fixed VIDEO_SUPPORT flag 2024-06-05 10:11:18 -04:00
Andreas T Jonsson f0e98372fb Minor cleanup of makefiles and scripts 2024-06-05 15:37:02 +02:00
gingerBill a747e47582 Merge pull request #3675 from Feoramund/fix-partial-infinity
Fix partial parsing of `infinity`
2024-06-05 12:48:44 +01:00
gingerBill adcda88501 Merge pull request #3680 from andreas-jonsson/netbsd-arm64
ARM64 support for NetBSD
2024-06-05 12:47:29 +01:00
gingerBill e7190aab41 Merge pull request #3681 from andreas-jonsson/netbsd-lwp-self
Proper thread identification on NetBSD
2024-06-05 12:47:23 +01:00
Andreas T Jonsson 929437c7bc Fixed broken import 2024-06-05 11:17:13 +02:00
Andreas T Jonsson ed6667ebf2 Propper thread identification on NetBSD 2024-06-05 11:06:14 +02:00
Andreas T Jonsson 58f07698e8 Added arm64 support for NetBSD 2024-06-05 10:18:47 +02:00
Jeroen van Rijn c406bbb6e3 Merge pull request #3679 from Feoramund/fix-typos
Fix some typos
2024-06-05 09:30:10 +02:00
Feoramund b2f9f0af68 Fix some typos 2024-06-04 19:01:30 -04:00
Feoramund 25feff3eb4 Permit parsing of incomplete infinity but do not return true
To clarify, `parse_f64` will indeed take `infi` to mean `+Inf` and
return that as the value, but it will not return `ok = true`. It treats
it as `inf` followed by any other trailing character.

`parse_f64_prefix` is the lenient one which will return true so long as
it finds some meaningful value.
2024-06-04 18:55:13 -04:00
Feoramund 1fc6ff91b2 Add test for infinity with trailing characters 2024-06-04 18:55:13 -04:00
gingerBill 2c580aa6fb Merge pull request #3676 from laytan/fix-passing-pointer-to-constant-to-non-odin-cc
fix passing pointer to constant in non-odin cc
2024-06-04 23:12:46 +01:00
Jeroen van Rijn f0a6fb4057 Merge pull request #3678 from Feoramund/fix-p-f64-p-doc
Strike incorrect note from `parse_f64_prefix` doc
2024-06-05 00:02:34 +02:00
Jeroen van Rijn 448c0d8dd3 Merge pull request #3677 from Feoramund/parse-compquat
Add `parse_complex/quaternion*` to `core:strconv`
2024-06-04 23:58:43 +02:00
Feoramund b4cfae222c Strike incorrect note from parse_f64_prefix doc 2024-06-04 17:50:19 -04:00
Feoramund 265e6aa781 Add parse_complex/quaternion* to core:strconv 2024-06-04 17:12:55 -04:00
Jeroen van Rijn 9d234998c0 Update create_nightly_json 2024-06-04 22:44:49 +02:00
Jeroen van Rijn c2ddf4266f Update delete_old_binaries.py 2024-06-04 22:26:51 +02:00
gingerBill a0b1b8d1c3 Merge pull request #3673 from laytan/implement-foreign-import-improvements-on-vendor
Implement `#exists(path)` and use it to provide good errors for common missing vendor libraries
2024-06-04 19:57:09 +01:00
Laytan Laats dbaf1a1ce0 compile stb_vorbis 2024-06-04 20:26:21 +02:00
Feoramund c656a9e4cd Fix and subsume test_issue_2087 into strconv test suite
The full "infinity" strings were expected to be partial consumes, but
this is not the case. That has been fixed and the relevant extra tests
from that file have been added to this test suite.

Fixes #2670
2024-06-04 14:23:48 -04:00
Laytan Laats cd99625dd3 ci: compile needed libraries 2024-06-04 20:21:52 +02:00
Feoramund 7d670f6562 Add initial test suite for core:strconv 2024-06-04 14:20:31 -04:00
laytan 2a526058b3 fix passing pointer to constant in non-odin cc 2024-06-04 20:15:47 +02:00
Laytan Laats 3e159736cd use #exists to provide good errors for common missing libraries 2024-06-04 20:13:51 +02:00
Feoramund d33668fa91 Fix partial parsing of "infinity" in parse_f64_prefix
It was previously reporting an invalid number of characters parsed for
any string other than "inf", "+inf", or "-inf".
2024-06-04 13:24:46 -04:00
Laytan Laats b47a15733d implement #exists(path) 2024-06-04 19:06:13 +02:00
Laytan Laats 4f5b2bd127 fix crash when you have 2 #load_directory calls with the same path 2024-06-04 19:01:50 +02:00
gingerBill 3b7100f8e5 raygui: change c.int to their correct enum types 2024-06-04 16:17:49 +01:00
gingerBill 6b386631dd Improve error message suggestion for passing enums to integers 2024-06-04 16:16:27 +01:00
gingerBill 11b1a48bf0 Fix extra_linker_flags for raylib on windows 2024-06-04 15:54:57 +01:00
gingerBill 72ce111a95 Keep -vet happy 2024-06-04 15:51:19 +01:00
gingerBill 606608c02b Utilize foreign import constant strings for foreign imports 2024-06-04 15:49:17 +01:00
gingerBill eacf2918ad Merge pull request #3469 from hodgka/raylib_resizable_doc_patch
Fixed typo in raylib documentation
2024-06-04 15:41:15 +01:00
gingerBill afcccfdec5 Merge pull request #3615 from puzzleddev/export-dependencies
Add build flag to export dependencies.
2024-06-04 15:40:54 +01:00
gingerBill 60a064984d Merge pull request #3670 from colrdavidson/x11-tweaks
Correct X11 prefix issues
2024-06-04 15:02:03 +01:00
gingerBill 0504c12f04 Merge pull request #3672 from laytan/fix-old-llvm-debug-info
fix debug info IR error on LLVM < 13
2024-06-04 15:01:30 +01:00
Laytan Laats 7d29389834 fix debug info IR error on LLVM < 13 2024-06-04 14:41:42 +02:00
Colin Davidson 52ba3357ee oops, missed shuffling a few x-funcs 2024-06-04 04:48:24 -07:00
Jeroen van Rijn 78a67ef31e Merge pull request #3667 from Feoramund/fix-fmt-compquat-sign
Fix printing of duplicate signs in complex and quaternion types
2024-06-04 13:32:13 +02:00
Jeroen van Rijn f9d59ef6d4 Merge branch 'master' into fix-fmt-compquat-sign 2024-06-04 13:25:57 +02:00
Jeroen van Rijn c3b94b9e1d Merge pull request #3646 from Feoramund/multi-test
Refactor the test runner
2024-06-04 13:23:52 +02:00
Jeroen van Rijn 02f11dfded Merge branch 'master' of github.com:odin-lang/Odin 2024-06-04 11:27:01 +02:00
Jeroen van Rijn 303d86ab7e Complete nightly scripts update to new b2 cli version 2024-06-04 11:26:57 +02:00
Jeroen van Rijn 50374d9396 Merge pull request #3640 from harold-b/fix-darwin-libc-open
Fix open() foreign libc signature on Darwin
2024-06-04 10:54:08 +02:00
Jeroen van Rijn dfffc57536 Merge pull request #3668 from colrdavidson/x11-tweaks
add a few more x11 funcs, fix egl bug
2024-06-04 10:53:57 +02:00
Colin Davidson e46e22e21b add a few more x11 funcs, fix egl bug 2024-06-04 01:12:10 -07:00
Feoramund eb93779f63 Fix duplicate sign printing of complex and quaternion types
Negative zero wasn't being detected (so it would appear as `+-0`), and
`+Inf` was appearing as `++Inf` when imaginary.
2024-06-03 19:51:17 -04:00
Feoramund d2a9122176 Add fmt tests for printing complex and quaternion types 2024-06-03 19:48:09 -04:00
Jeroen van Rijn 36627d7d29 Merge pull request #3666 from Feoramund/add-missing-compquat
Add missing `Raw_*` complex and quaternion types
2024-06-04 01:28:18 +02:00
Jeroen van Rijn f745a1c470 b2 uri 2024-06-04 00:22:49 +02:00
gingerBill 17225131f7 Try / rather than 2024-06-03 23:12:24 +01:00
gingerBill c8f9af64db Add print to delete_old_binaries.py 2024-06-03 23:01:39 +01:00
gingerBill 0ef0894213 Fix to bl.tok = path 2024-06-03 22:55:24 +01:00
gingerBill dc6a8e5ffb Fix typo 2024-06-03 22:44:12 +01:00
gingerBill 5b5106baee Try updating nightly stuff 2024-06-03 22:36:54 +01:00
gingerBill 4dac577caa Add attributes to Foreign_Import_Decl in clone 2024-06-03 22:21:54 +01:00
gingerBill 8e9716ea2f Add ast.Foreign_Import_Decl to ast.clone 2024-06-03 22:20:39 +01:00
Feoramund d7f6def8ad Add aliases for Raw_* complex/quaternion types into core:mem 2024-06-03 17:18:27 -04:00
gingerBill 50b4a63fe1 Add ast.Foreign_Impot_Decl.fullpaths to walk.odin 2024-06-03 22:02:35 +01:00
Jeroen van Rijn 2cb3028086 Merge pull request #3664 from reduf/fix-signatures-of-some-functions
Fix signatures of two Win32 functions
2024-06-03 22:06:07 +02:00
Feoramund 88598c2c64 Make use of runtime.Raw_* types in core:math/linalg 2024-06-03 15:58:33 -04:00
Feoramund 97f1d12e04 Add missing Raw_* types for complex and quaternion 2024-06-03 15:41:14 -04:00
Feoramund 4e1dd4ced2 Move Raw_Complex/Quaternion types to base:runtime 2024-06-03 15:40:28 -04:00
Laurent Dufresne 1617060f46 Fix type of two Win32 functions 2024-06-03 20:41:31 +02:00
Feoramund 0ff130d82b Fix ad hoc printf in test runner signal handler 2024-06-02 23:36:04 -04:00
Feoramund fa29974dab Use Warning log level for reporting memory leaks
Works well with `-define:ODIN_TEST_LOG_LEVEL=warning`.
2024-06-02 23:21:44 -04:00
Feoramund 7764ab2ab0 Prevent test runner deadlock on NetBSD
Add `pthread_testcancel` to `core:sys/unix`
2024-06-02 21:27:36 -04:00
Feoramund 6a5633df2d Fix wrong PTHREAD_CANCEL_ASYNCHRONOUS on FreeBSD and OpenBSD
The test runner was deadlocking when a test raised a signal on FreeBSD.

This is untested on OpenBSD, but I have referenced this file:
https://github.com/openbsd/src/blob/master/include/pthread.h
2024-06-02 20:41:25 -04:00
Feoramund c8539fe411 Revert "Disable NetBSD tests until 'undefined reference to stdout' is solved."
This reverts commit 21a1ddfbae.
2024-06-02 19:29:27 -04:00
Feoramund ac9484206b Fix STDIN, STDOUT, STDERR handles for BSDs
Tested on FreeBSD 14.0 and NetBSD 10.0

OpenBSD is untested, but link names were sourced from:
https://github.com/openbsd/src/blob/master/include/stdio.h

According to this, OpenBSD shares the same layout as NetBSD.

FreeBSD has the same as Darwin in this regard.
2024-06-02 19:29:27 -04:00
Jeroen van Rijn 10d354aea8 Merge pull request #3662 from Feoramund/fix-3660
Fix #3660 and #3661
2024-06-02 23:22:16 +02:00
Feoramund f030603f0d Fix #3660
This also prevents a segfault if you do `odin build .odin -file`
2024-06-02 16:47:46 -04:00
Feoramund f77ce359ce Be pedantic about not overwriting Odin errors
I was encountering bounds-check error messages being overwritten during
a test, if the test failed for another reason and sent a log message.

The original intent of having this check inside of the above `if` block
was that if a test sent an error message, then it was assumed an
overwrite would be safe, but it's completely possible for a test to fail
for a legitimate reason, then do an unrelated bounds check somewhere
else that would be buried under the animation.

This change will make sure that, no matter what, the progress display
will not trigger a clear if a signal was raised. There's still no
guarantee that bounds-check messages will be printed properly, and it's
best to redirect STDERR.

The only way that can be fixed is if they get a similar hook to
`context.assertion_failure_proc`.
2024-06-02 15:51:26 -04:00
Feoramund 3f1249c27e Tell user about ODIN_TEST_RANDOM_SEED option 2024-06-02 15:34:13 -04:00
Feoramund 8d8c42e962 Use T.seed in tests where applicable 2024-06-02 15:30:23 -04:00
Jeroen van Rijn 60d0c03134 Strip old test runner back out of internal, issues and vendor 2024-06-02 21:15:25 +02:00
Jeroen van Rijn 9d8d864400 Plug leak in AES tests. 2024-06-02 21:12:24 +02:00
Jeroen van Rijn 21a1ddfbae Disable NetBSD tests until 'undefined reference to stdout' is solved. 2024-06-02 21:03:22 +02:00
Feoramund 890fe07c6e Disable FANCY_OUTPUT in Odin test scripts
This should tidy up the CI output logs a bit.
2024-06-02 14:54:32 -04:00
Feoramund d581dbbec5 Keep test runner main thread from using 100% of a CPU core 2024-06-02 14:54:32 -04:00
Feoramund 5e3e958574 Add -define:ODIN_TEST_LOG_LEVEL to set lowest log level 2024-06-02 14:54:32 -04:00
Feoramund 6a9203328b Log thread count at test run start
Provides a helpful info message about the option to change how many
threads are used per run.
2024-06-02 14:54:32 -04:00
Feoramund 5db65aa796 Make it easier to learn about ODIN_TEST_CLIPBOARD 2024-06-02 14:54:32 -04:00
Feoramund cb00b8022b Add note about SIGSEGV edge case on UNIX-likes 2024-06-02 14:54:32 -04:00
Feoramund 4875f745c8 Remove Windows test runner in favor of libc implementation 2024-06-02 14:54:32 -04:00
Feoramund ccdbd4b6ce Simplify casts in mem.Rollback_Stack procs 2024-06-02 14:54:32 -04:00
Feoramund 9dcf345795 Set thread pool is_running to false on shutdown 2024-06-02 14:54:32 -04:00
Feoramund 21064fbb60 Clear thread pool task data on restart 2024-06-02 14:54:32 -04:00
Feoramund 45fa9d8148 Expand documentation comment for ODIN_TEST_NAMES 2024-06-02 14:54:32 -04:00
Feoramund cb8faf5b74 Remove -test-name in favor of test runner option
`-define:ODIN_TEST_NAMES=...` is capable of selecting test by package
and name or name only, with the ability to access packages included by
`-all-packages`.
2024-06-02 14:54:32 -04:00
Feoramund 6a5d51f0d6 Use more concise way of satisfying -vet 2024-06-02 14:54:31 -04:00
Feoramund 433ca538bf Be specific about platforms not implementing test runner signal handler 2024-06-02 14:54:31 -04:00
Feoramund d1723664a7 Catch SIGILL, SIGFPE, SIGSEGV in the test runner 2024-06-02 14:54:31 -04:00
Feoramund fb37572c4c Rename signal_handler.odin to signal_handler_libc.odin 2024-06-02 14:54:31 -04:00
Jeroen van Rijn 6050bc3bf6 Add missing benchmarks build.bat. 2024-06-02 14:54:31 -04:00
Jeroen van Rijn 306169699c Update ci.yml 2024-06-02 14:54:31 -04:00
Jeroen van Rijn 3354212f8e Update ci.yml
Disable benchmark on Windows for a moment.
2024-06-02 14:54:31 -04:00
Jeroen van Rijn 54dae06ad1 Update CI 2024-06-02 14:54:31 -04:00
Jeroen van Rijn 8d93379e29 Factor benchmarks out into tests\benchmark\<pkg> 2024-06-02 14:54:29 -04:00
Jeroen van Rijn 62b7d8de97 Port tests\core\net 2024-06-02 14:47:09 -04:00
Jeroen van Rijn dacb0f7786 Port tests\core\thread 2024-06-02 14:47:09 -04:00
Jeroen van Rijn 5b1ffba915 Port testing\core\time 2024-06-02 14:47:09 -04:00
Jeroen van Rijn a406ff7063 Port tests\core\strings 2024-06-02 14:47:09 -04:00
Jeroen van Rijn 9ba02e888d Port tests\core\slice 2024-06-02 14:47:09 -04:00
Jeroen van Rijn ed0384c102 Port tests\core\runtime 2024-06-02 14:47:09 -04:00
Jeroen van Rijn 80b115748f Port tests\core\reflect 2024-06-02 14:47:09 -04:00
Jeroen van Rijn 9829a02571 Port tests\core\odin 2024-06-02 14:47:09 -04:00
Jeroen van Rijn 8383a45b62 Port tests\core\text\match 2024-06-02 14:47:09 -04:00
Jeroen van Rijn b0faab29e0 Port tests\core\math, math\linalg\glsl and math\noise 2024-06-02 14:47:09 -04:00
Jeroen van Rijn d7bfbe0552 Port testing\core\text\i18n 2024-06-02 14:47:08 -04:00
Jeroen van Rijn 39fd73fe17 Port testing\core\hash 2024-06-02 14:47:08 -04:00
Jeroen van Rijn 6f7c5a7577 Port tests\core\fmt 2024-06-02 14:47:08 -04:00
Jeroen van Rijn d334b8c72a Port tests\core\path\filepath 2024-06-02 14:47:08 -04:00
Jeroen van Rijn 9d0f4833bf Port tests\core\encoding\xml
Made them run in parallel as well.
2024-06-02 14:47:08 -04:00
Jeroen van Rijn 6641a6f6c9 Port tests\core\encoding\varint 2024-06-02 14:47:08 -04:00
Jeroen van Rijn 601df0e8f7 Port tests\core\encoding\json 2024-06-02 14:47:08 -04:00
Jeroen van Rijn 1b32e27aa4 Port tests\core\encoding\hxa
And fix a few leaks in `core:encoding/hxa` while at it.
2024-06-02 14:47:08 -04:00
Jeroen van Rijn 3404dea8ac Port tests\encoding\hex 2024-06-02 14:47:08 -04:00
Jeroen van Rijn 40b20fb473 Port tests\core\c\libc 2024-06-02 14:47:08 -04:00
Feoramund b74b956fda Remove unneeded import 2024-06-02 14:47:08 -04:00
Feoramund 1f6a6f2cd3 Support deterministic random seeding of tests
Add a new option `ODIN_TEST_RANDOM_SEED` which is picked from the cycle
counter at startup, if it's not specified by the user.

This number is sent to every test in the `T` struct and reset every test
(just in case).
2024-06-02 14:47:07 -04:00
Jeroen van Rijn a27b167218 Update tests\core\encoding\cbor to use new test runner.
It was leaky and required a substantial number of `loc := #caller_location` additions to parts of the core library to make it easier to track down how and where it leaked.

The tests now run fine multi-threaded.
2024-06-02 14:47:07 -04:00
Jeroen van Rijn 6a1649d8aa Update using new defaults for memory + reporting width 2024-06-02 14:47:07 -04:00
Feoramund 84ad71fdb3 Support ODIN_TEST_PROGRESS_WIDTH=0
This will automatically calculate how wide the progress bars should be
based on the package with the greatest number of tests.

The progress width is now capped to 100.
2024-06-02 14:47:07 -04:00
Feoramund 49fa66370f Report test memory usage only if there's an issue
Adds new option `ODIN_TEST_ALWAYS_REPORT_MEMORY`, for when you always
want to see the memory usage report.
2024-06-02 14:47:07 -04:00
Feoramund e1a3c0e21d Track memory in the test runner by default 2024-06-02 14:47:07 -04:00
Feoramund bf42e39b1c Be specific about int size for Rollback_Stack asserts
This should fix tests failing on 32-bit platforms.
2024-06-02 14:47:07 -04:00
Jeroen van Rijn c531427ee5 Update -define for crypto 2024-06-02 14:47:07 -04:00
Feoramund b7e1ae7073 Change test runner options to SCREAMING_SNAKE_CASE
This commit also changes the name of `test_select` to `ODIN_TEST_NAMES`,
to better conform with the already-existing `-test-name:<name>` option.
2024-06-02 14:47:07 -04:00
Feoramund e11f3d2520 Fix missing - for define in tests/core/build.bat 2024-06-02 14:47:07 -04:00
Feoramund dcfda195d2 Send terminal control code to STDOUT instead
`STDERR` might be redirected, and this code signals to the terminal to
show the cursor again. Otherwise, the cursor will be invisible.
2024-06-02 14:47:07 -04:00
Feoramund a1c5bebac7 Fix ANSI redraw eating last log line 2024-06-02 14:47:07 -04:00
Feoramund 89d8df28be Combine multi-line attributes onto one line 2024-06-02 14:47:07 -04:00
Feoramund dffc3af86c Remove safe_heap_allocator from test runner
I was under the impression that the default `context.allocator` was not
thread-safe, but I've been told that this is not the case.
2024-06-02 14:47:06 -04:00
Feoramund eadfbb1318 Forbid singleton allocations from shrinking their block offset 2024-06-02 14:47:06 -04:00
Feoramund 1afc235359 Use plain sort for internal_tests 2024-06-02 14:47:06 -04:00
Feoramund 09ef08f035 Add more sanity checking to mem.Rollback_Stack 2024-06-02 14:47:06 -04:00
Feoramund 0f675fa436 Use uintptr where applicable in mem.Rollback_Stack 2024-06-02 14:47:06 -04:00
Feoramund 568b746c98 Fix indentation 2024-06-02 14:47:06 -04:00
Jeroen van Rijn a0b2ea6d6e Update tests\core\crypto 2024-06-02 14:46:59 -04:00
Jeroen van Rijn a463e282db Update core:container tests 2024-06-02 14:34:31 -04:00
Jeroen van Rijn e3181c13c6 Update core:compress tests 2024-06-02 14:34:31 -04:00
Jeroen van Rijn 22c092f846 Delete duplicated flag. 2024-06-02 14:34:31 -04:00
Jeroen van Rijn eb3d6d7d75 Update core:image tests to use new runner. 2024-06-02 14:34:31 -04:00
Feoramund 852f694bee Get tests passing again
`T` no longer has a writer assigned to it.

`test_core_cbor.odin` has global state and is run with `odin test`,
so I've set it to use only one thread.
2024-06-02 14:34:31 -04:00
Feoramund 87ea4a2652 Temporarily disable Windows-specific test runner
I do not have a Windows machine to test the refactored test runner, and
I am unsure if it would even run correctly on Windows without this
disabled.
2024-06-02 14:34:31 -04:00
Feoramund d03024088a Remove unneeded code 2024-06-02 14:34:31 -04:00
Feoramund b6c4dfb68d Refactor the test runner
Changes

- Support multi-threaded testing.
- Support `set_fail_timeout` on all platforms.
- Display an animated progress report.
- Setup all tests with a context logger.
- Give all tests their own separate custom allocators.
- Support tracking test memory usage.
- Display a summary of the failed tests at the end.
- Let users select only specific tests to run.
- Support copying failed tests to the clipboard to run again.
- Support catching SIGINT (CTRL-C) to cancel early.
- Record context in cleanup procs.
- Write all log messages to STDERR for easy redirection.
- Possibly more I've forgotten.

New Options

- `-define:test_threads=N`: Specify thread count.
- `-define:test_thread_memory=B`: Specify initial memory block size in bytes to each thread.
- `-define:test_track_memory=true`: Track the memory usage of individual tests.
- `-define:test_fancy=false`: Disable animated progress report.
- `-define:test_select=package.test_name,...`: Run only select tests.
- `-define:test_clipboard=true`: Copy names of failed tests to the clipboard.
- `-define:test_progress_width=24`: Change the width of the animated progress bars.
2024-06-02 14:34:31 -04:00
Feoramund 95c2e020ff Share libc signal definitions with more platforms
I confirmed that these 3 platforms share the same signal definitions
from these sources.

Haiku: https://github.com/haiku/haiku/blob/master/headers/posix/signal.h
OpenBSD: https://github.com/openbsd/src/blob/master/sys/sys/signal.h
NetBSD: http://fxr.watson.org/fxr/source/sys/signal.h?v=NETBSD
2024-06-02 14:34:30 -04:00
Feoramund 50dffaf131 Add mem.Rollback_Stack 2024-06-02 14:34:30 -04:00
Feoramund fc4f6b87bb Add core:encoding/ansi package 2024-06-02 14:34:30 -04:00
Feoramund 8137b9dd75 Add mem.tracking_allocator_reset 2024-06-02 14:34:30 -04:00
Feoramund 558c330028 Add task-stopping functionality to thread.Pool 2024-06-02 14:34:30 -04:00
Feoramund 1875e7c36a Make log.do_*_header argument orders consistent 2024-06-02 14:34:30 -04:00
Feoramund 7d4da6eaa7 Fix trailing space with only .Date log option 2024-06-02 14:34:30 -04:00
Feoramund 8ae375dbff Move log timestamping out to do_time_header proc 2024-06-02 14:34:30 -04:00
Jeroen van Rijn c07a46abc9 Merge pull request #3635 from Yawning/feature/aes
core/crypto: Add AES
2024-06-01 21:42:59 +02:00
Yawning Angel c751e4b2eb core/crypto/aes: Add AES implementation 2024-06-01 22:55:42 +09:00
Yawning Angel 1ade62b630 core/crypto/_aes/ct64: Add GHASH 2024-06-01 22:55:42 +09:00
Yawning Angel cba58924a8 core/crypto/_aes: 64-bit portable implementation 2024-06-01 22:55:42 +09:00
Yawning Angel f49575f1fb core/simd/x86: Add the AES-NI intrinsics 2024-06-01 22:55:42 +09:00
gingerBill 72a5e74ef3 Merge pull request #3658 from laytan/wasm64p32-runtime-fixes
wasm: fix runtime.js even more for wasm64p32
2024-05-31 23:17:52 +01:00
gingerBill 881340fd3b Merge pull request #3659 from thetarnav/unreachable
Add unreachable to base/builtin/builtin.odin
2024-05-31 23:17:08 +01:00
Damian Tarnawski 451dc645df Add unreachable to base/builtin/builtin.odin 2024-05-31 21:55:40 +02:00
Laytan Laats 8a521648b9 wasm: fix runtime.js even more for wasm64p32
- make the int size configurable in the `runWasm` call, no more
  constants to hunt down and change
- make storeU64 and storeI64 handle bigints, this is needed in the
  odin_dom library
- fix alignment issues within init_event_raw
2024-05-31 20:57:15 +02:00
gingerBill 5628cfabe5 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-05-31 16:35:38 +01:00
gingerBill 31a9b3f428 core:encoding/ini 2024-05-31 16:35:30 +01:00
Jeroen van Rijn e12ff63b16 Merge pull request #3657 from laytan/fix-wasm64p32-procs
wasm: fix target wasm64p32 runtime procs
2024-05-31 17:03:52 +02:00
Laytan Laats 3a0ec3d6a8 wasm: fix target wasm64p32 runtime procs
LLVM generates calls with `i32` regardless of target, so if a call to
any of these procs was generated this failed to compile.

I opted to fix by changing from `int` to `i32` on wasm64p32 and adding
`#any_int` so existing code keeps working.
2024-05-31 16:32:27 +02:00
gingerBill ffded3d557 Merge pull request #3655 from iErik/master
core:sys/linux - Add support for Unix Domain Socket addresses
2024-05-31 10:32:19 +01:00
gingerBill ae63fd9230 Fix #3649 2024-05-30 23:08:42 +01:00
gingerBill 6d9957d7e4 Fix types again 2024-05-30 21:59:01 +01:00
gingerBill e737122ce8 Add experimental target orca_wasm32 2024-05-30 21:58:27 +01:00
gingerBill 8db87170a9 Clean up handle_link_name handling of link_suffix 2024-05-30 21:53:23 +01:00
gingerBill ba1e9c8abe Fix #3651 2024-05-30 21:50:30 +01:00
gingerBill 66acbb7fed Add @(link_suffix=<string>) 2024-05-30 21:48:23 +01:00
Erik Isidore 0514ee0410 PR#3655 - small linter issue correction 2024-05-30 16:12:20 -03:00
gingerBill 7bcf33c881 Merge pull request #3656 from laytan/microui-optional-clipboard
microui: make clipboard optional during init
2024-05-30 17:37:35 +01:00
Laytan Laats 6bbe7d88b8 microui: make clipboard optional during init
Clipboard is an optional addition to the microui functionality, but the
init function makes it look like it is required. Additionally, a bunch of
the examples both on the Odin-Lang/examples repo and others are now
"broken".
2024-05-30 16:19:33 +02:00
gingerBill 7058d6f320 Merge pull request #3652 from Dudejoe870/compile-time-hash
Add #hash built-in directive for compile-time string hashing
2024-05-30 11:30:26 +01:00
gingerBill f86bb11f84 Merge pull request #3653 from laytan/fix-wheel-event-js-wsam
wasm: fix the WheelEvent not storing data properly
2024-05-30 11:13:44 +01:00
gingerBill 5391605961 Merge pull request #3654 from laytan/darwin-fix-sdkpath
darwin: fix sysroot retrieval for some systems
2024-05-30 11:13:32 +01:00
Erik Isidore f6e699cd22 core:sys/linux - Add support for Unix Domain Socket addresses 2024-05-30 00:14:00 -03:00
Laytan Laats eeb057b76d darwin: fix sysroot retrieval for some systems
Got a report on Discord that the current way didn't work for a user,
this change did work and I confirmed with @harold-b (who initially added
this) that it also works for them and is actually a better way.
2024-05-30 01:53:38 +02:00
Laytan Laats 692ca13ffd wasm: fix the WheelEvent not storing data properly
A `WheelEvent` is also an instanceof `MouseEvent` so it was never
hitting the if statement for the `WheelEvent`.
2024-05-30 01:49:30 +02:00
Dudejoe870 9b78061c8f Initial hash directive implementation 2024-05-28 22:42:10 -05:00
gingerBill ba8672ad29 Merge pull request #3650 from yay/destroy-multi-logger-no-pointer
Take logger itself, not a pointer to logger in multi-logger destructor.
2024-05-29 00:49:02 +01:00
Vitalii Kravchenko 223c987db2 Take logger itself, not a pointer to logger in multi-logger destructor. 2024-05-28 21:13:25 +01:00
gingerBill 74524b6050 Merge pull request #3644 from odin-lang/foreign-import-improvements
Allow `foreign import` import paths to be evaluated in the semantic phase rather than parsing
2024-05-28 12:18:15 +01:00
Jeroen van Rijn 23852c16be Merge pull request #3647 from Feoramund/fix-core-data-comments
Make `ODIN_OS`, `ODIN_BUILD_MODE` comments congruent to underlying data
2024-05-28 09:14:44 +02:00
Jeroen van Rijn 4c6b824658 Merge pull request #3648 from Feoramund/rem-unused-prime-code
Remove unused code in `internal_random_prime`
2024-05-28 08:55:04 +02:00
Feoramund 01ad69413a Remove unused code in internal_random_prime 2024-05-28 01:36:44 -04:00
Feoramund fa6e07d976 Make ODIN_OS, ODIN_BUILD_MODE comments congruent to underlying data
Sourced from `src/checker.cpp`.
2024-05-28 01:32:20 -04:00
gingerBill d91054b615 Change parser to use ^Expr rather than string for the foreign import paths 2024-05-28 00:27:13 +01:00
gingerBill a1b8749e74 Delay checking foreign import paths until after global scope is checked 2024-05-28 00:23:23 +01:00
gingerBill 38fffff06a Begin moving foreign import import paths to be evaluated in the semantic phase rather than parsing. 2024-05-27 23:51:43 +01:00
korvahkh a7a6ff8c69 encoding/json: Fix struct marshal() emitting comma after omitted field
Previously:
```odin
package main

import "core:fmt"
import "core:encoding/json"

T :: struct {
	a: string `json:",omitempty"`,
	b: string,
}

main :: proc() {
	data, _ := json.marshal(T{b = "foo"})
	fmt.println(string(data))
}
```
would output:
```
{,"b":"foo"}
```

which is not correct.

Also cleaned up some whitespace while I'm at it.
2024-05-27 16:59:46 -05:00
gingerBill 74ac2667e7 Merge pull request #3642 from 2nafish117/fix-pitch-from-quat
Fix pitch_from_quaternion
2024-05-27 22:24:46 +01:00
shashank fb6248925a fix pitch_from_quaternion 2024-05-27 23:38:50 +05:30
Harold Brenes 2ecf909be0 Fix open() foreign libc signature on Darwin 2024-05-27 11:55:58 -04:00
Jeroen van Rijn 75f1215ed2 Merge pull request #3639 from yay/destroy-file-logger-no-pointer
Make destroy_file_logger take logger instead of logger pointer.
2024-05-27 17:25:59 +02:00
Vitalii Kravchenko bdc4daca54 Make destroy_file_logger take logger instead of logger pointer. 2024-05-27 16:19:44 +01:00
gingerBill 6d163cee8a Merge pull request #3638 from harold-b/fix-darwin-libc-proc-sigs
Fix a few darwin libc signatures with incorrect parameters.
2024-05-27 02:06:50 +01:00
Harold Brenes cfd4fc835b Fix a few darwin libc signatures with incorrect parameters. 2024-05-26 19:40:08 -04:00
gingerBill 8421950546 Merge pull request #3637 from laytan/revert-clang++-detection
revert `$(llvm-config --bindir)/clang++` to get the cpp compiler
2024-05-26 19:16:32 +01:00
Laytan Laats 5027cfb618 revert $(llvm-config --bindir)/clang++ to get the cpp compiler
A few reports of either people not having this clang++ or having it but
it not finding system headers. On top of that, the reason we added this
in the first place was a bug that surfaced on clang-18 which we've since
fixed.

Order will now be clang++ from path, then the llvm bindir clang++, then an
error.

This can all still be overwritten with `CXX=blah make` like before.
2024-05-26 20:11:07 +02:00
gingerBill 149ae70be1 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-05-26 12:17:09 +01:00
gingerBill 64bdb3a097 Fix #3630 (first part) 2024-05-26 12:17:03 +01:00
gingerBill ef7a155f9a Merge pull request #3633 from korvahkh/fix-slice-has-affix
Fix slice.has_prefix & slice.has_suffix
2024-05-25 21:48:31 +01:00
korvahkh 58ae96c821 Fix slice.has_prefix & slice.has_suffix
The needle was the element type instead of the slice type.
2024-05-25 15:52:35 -05:00
Jeroen van Rijn cfadca04f9 Merge pull request #3628 from IllusionMan1212/bitset-json-marshalling-fix
fix(core/encoding/json): remove Unsupported_Type return when marshalling bit_set
2024-05-25 08:34:59 +02:00
IllusionMan1212 65a4a56a83 fix(core/encoding/json): remove Unsupported_Type return when marshalling bit_set 2024-05-25 00:45:30 +02:00
Jeroen van Rijn fb22c59d1b Merge pull request #3625 from Kelimion/iso8061
Add dedicated ISO 8601 parser.
2024-05-24 23:56:20 +02:00
Jeroen van Rijn b945e3e708 Limit to max of 9 fraction second digits, part deux. 2024-05-24 23:48:18 +02:00
Jeroen van Rijn 1473374bba Limit to max of 9 fraction second digits. 2024-05-24 23:45:46 +02:00
Jeroen van Rijn 3526042f1e Add dedicated ISO 8601 parser. 2024-05-24 23:40:14 +02:00
Jeroen van Rijn e1c4b9b06a Allow lowercase z TZ indicator. 2024-05-24 19:16:24 +02:00
Jeroen van Rijn ff34970d79 Merge pull request #3623 from yay/allow-space-in-rfc-3339
Allow space (in addition to T and t) as RFC 3339 date/time separator.
2024-05-24 19:10:04 +02:00
Vitalii Kravchenko ff94ca9e42 Allow space (in addition to T and t) as RFC 3339 date/time separator. 2024-05-24 18:03:52 +01:00
gingerBill 590db0838a Fix types 2024-05-24 17:21:00 +01:00
Jeroen van Rijn d698d4cdae Merge pull request #3621 from laytan/enable-default-temp-allocator-wasm
wasm: enable default temp allocator
2024-05-24 15:42:51 +02:00
Jeroen van Rijn d99e1616cf Merge pull request #3620 from Kelimion/deprecate_odin_printer
Deprecate `core:odin/printer` in favor of OLS.
2024-05-24 15:02:59 +02:00
Laytan Laats aa72050586 wasm: enable default temp allocator
After #3592 I think it makes sense to also enable the temp allocator by default
2024-05-24 15:01:02 +02:00
Jeroen van Rijn b7cecc5762 Keep -vet happy. 2024-05-24 14:57:48 +02:00
Jeroen van Rijn 5c06480ce0 Add core:container/rbtree to examples/all 2024-05-24 14:55:21 +02:00
Jeroen van Rijn dc744411c5 Deprecate core:odin/printer + format in favor of OLS. 2024-05-24 14:49:11 +02:00
Jeroen van Rijn e2af3652c5 Merge pull request #3619 from Kelimion/csv_iterator
Add iterator_next(&r) to CSV.
2024-05-24 14:06:42 +02:00
Jeroen van Rijn 479d301e92 Merge pull request #3614 from Kelimion/rbtree
Add `core:container/rbtree`
2024-05-24 14:04:56 +02:00
Jeroen van Rijn 11e57fd3fd Address concerns. 2024-05-24 13:58:30 +02:00
tim4242 0cba33075f Add the option to export dependencies as JSON. 2024-05-24 13:44:38 +02:00
Jeroen van Rijn 2a4ddbb7be Remove core:mem import in example. 2024-05-24 13:35:32 +02:00
Jeroen van Rijn 3b739dc5cc Add iterator_next(&r) to CSV. 2024-05-24 13:26:12 +02:00
gingerBill 0658778a30 Merge pull request #3611 from hstormo/textbox
vendor/microui: nicer textbox
2024-05-24 11:51:09 +01:00
gingerBill 1081e9ac09 Fix enum definition for bit_set use 2024-05-24 11:41:56 +01:00
Jeroen van Rijn c43d189a33 Fix package line. 2024-05-24 01:43:17 +02:00
tim4242 8664b88c8f Improved depdendency formatting to support paths containing spaces 2024-05-24 01:20:45 +02:00
tim4242 7934e92d14 Initial dependency file generation 2024-05-24 01:04:41 +02:00
Håkon Stormo 4328562e2c Satisfy -vet 2024-05-23 23:50:26 +02:00
Håkon Stormo ee79c409b4 microui: use the text_edit procs 2024-05-23 23:28:58 +02:00
Håkon Stormo d3bbe29faa text_edit: better handle failure to resize underlying buffer 2024-05-23 23:28:39 +02:00
Jeroen van Rijn 410876b36a Add core:container/rbtree
Add a red-black tree with configurable $Key and $Value.
Also includes tests that verify it maintains RB invariants, doesn't leak.

Originally based on the CC0 implementation from literateprograms.org.
But reworked to the same API used by @Yawning's excellent `core:container/avl` for ease of use.
2024-05-23 23:00:00 +02:00
Håkon Stormo f411fcedb0 microui: textbox cut/copy/paste 2024-05-23 21:38:37 +02:00
Håkon Stormo 043ddd83a9 microui: textbox selection 2024-05-23 21:36:31 +02:00
gingerBill 7dc1f114b9 Add shadow suggestion 2024-05-22 22:22:41 +01:00
gingerBill f3f08c264f Be very particular with the cases for the error notes 2024-05-22 21:55:48 +01:00
gingerBill 2f35ee9671 Improve errors a lot for assigning procedures of the wrong signature 2024-05-22 21:52:15 +01:00
gingerBill 856537f0ce Fix #3603 2024-05-20 15:54:53 +01:00
gingerBill bc706f8b0c Fix indexing type when using a #row_major matrix 2024-05-20 15:04:15 +01:00
gingerBill a68c635c00 Remove constant indexing for matrix value propagation 2024-05-20 15:00:43 +01:00
gingerBill f600562ca5 Improve fmt parsing of struct field tags 2024-05-20 14:45:49 +01:00
gingerBill 5ed93563a1 Merge pull request #3606 from Kelimion/fmtfix
Fix the way '%32b' and other prefixed numbers are written.
2024-05-20 14:29:50 +01:00
gingerBill c49a291347 Merge pull request #3607 from Szwagi/fix-atomic-memory-order
Fix Odin to LLVM memory order mapping for .Relaxed and .Consume
2024-05-20 14:29:06 +01:00
Kamil T f6ef395057 Fix Odin to LLVM memory order mapping for .Relaxed and .Consume 2024-05-20 13:57:08 +01:00
Jeroen van Rijn e0d3d68ce5 Fix the way '%32b' and other prefixed numbers are written. 2024-05-20 14:42:13 +02:00
gingerBill 46b3e7b6fa Fix for &v in &fixed_array 2024-05-20 13:36:32 +01:00
gingerBill a80011c830 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-05-20 13:32:22 +01:00
gingerBill 542c3d7561 Improve "Expected a type" syntax error 2024-05-20 13:32:16 +01:00
gingerBill f641399870 Merge pull request #3604 from matias-eduardo/master
remove extra newline in enumerated array hash fmt
2024-05-20 10:52:41 +01:00
gingerBill 891fefe117 Merge pull request #3592 from laytan/wasm-gpa
add a default heap/general purpose allocator for wasm to `base:runtime`
2024-05-20 10:38:09 +01:00
gingerBill 5473758467 Add intrinsics type_is_matrix_row_major & type_is_matrix_column_major 2024-05-20 10:15:21 +01:00
gingerBill 8eb7fe1859 Merge pull request #3482 from andreas-jonsson/netbsd-ci
NetBSD CI setup
2024-05-20 10:03:32 +01:00
gingerBill 8dec4f6ed3 Merge pull request #3570 from jasonKercher/linux-arm32
Get the compiler to build and work on arm32 Linux
2024-05-20 00:05:57 +01:00
gingerBill b6d5be8593 Merge pull request #3593 from harold-b/fix-build-sysroot-macos
Attempt to automatically resolve the sysroot on build_odin.sh on macOS
2024-05-19 23:59:44 +01:00
gingerBill 1207d64c64 Fix intrinsics.ptr_sub 2024-05-19 23:55:45 +01:00
Matias Fernandez a9629679ed remove extra newline in enumerated array hash fmt 2024-05-18 23:24:05 -04:00
Jeroen van Rijn c091b0d060 Merge pull request #3602 from Kelimion/qoifix
Apply fix to QOI decoder as well.
2024-05-18 19:48:37 +02:00
Jeroen van Rijn 58a1bb32e5 Apply fix to QOI decoder as well. 2024-05-18 19:41:07 +02:00
Jeroen van Rijn 5b92425e93 Merge pull request #3601 from Kelimion/qoifix
Fix qoi encoding bug.
2024-05-18 14:06:25 +02:00
Jeroen van Rijn 7955f4ddf1 Fix qoi encode bug. 2024-05-18 13:59:50 +02:00
gingerBill 98f8624447 Merge pull request #3594 from laytan/runtime-wasm64p32-fixes
correctly load/store uint&int in the runtime.js for wasm64p32
2024-05-17 17:32:36 +01:00
Laytan Laats e08b51ed73 correctly load/store uint&int in the runtime.js for wasm64p32 2024-05-17 16:32:34 +02:00
Jeroen van Rijn cf10c6d993 Merge pull request #3598 from Kelimion/i18n-fix
i18n: Add section merge + duplicate key detection to gettext.
2024-05-17 15:57:17 +02:00
Jeroen van Rijn f8c4ee3d3c i18n: Add section merge + duplicate key detection to gettext. 2024-05-17 15:50:37 +02:00
Jeroen van Rijn 419641ad8f Merge pull request #3596 from Kelimion/i18n-fix
Fix .mo contexts
2024-05-17 14:26:57 +02:00
Jeroen van Rijn 6139da3d41 Fix .mo contexts
Fixes #3590

- `get("key")`
- `get("context", "key")`
2024-05-17 14:15:56 +02:00
Jeroen van Rijn b51eb53d04 Merge pull request #3595 from Kelimion/i18n-fix
Fix .mo parser: Number of plurals
2024-05-17 12:15:40 +02:00
Jeroen van Rijn 5a76b3c7c5 Fix .mo parser: Number of plurals
Fixes #3591

Added plur.mo to tests
2024-05-17 12:00:20 +02:00
Harold Brenes f1b291ed62 Attempt to automatically resolve the sysroot on build_odin.sh on macOS 2024-05-16 17:53:41 -04:00
Laytan Laats f42b1c4973 add a default heap/general purpose allocator for wasm to base:runtime 2024-05-16 23:08:40 +02:00
gingerBill ab8e3db7e9 Remove bad code 2024-05-16 17:18:37 +01:00
gingerBill 575b268e88 Fix more #soa changes 2024-05-16 17:15:38 +01:00
gingerBill 7cf62f00c3 Correct #soa RTTI usage 2024-05-16 16:30:45 +01:00
gingerBill c9b1c99a40 Fix soa_zip and soa_unzip 2024-05-16 16:27:09 +01:00
gingerBill 32245e93a1 Fix #3514 along with soa.a[i] bounds checking 2024-05-16 16:18:21 +01:00
gingerBill 330d6117e3 Fix #3589 2024-05-16 15:43:08 +01:00
gingerBill b2dc5cc812 Fix error reporting for enforce new switch/for syntax 2024-05-16 15:32:15 +01:00
gingerBill a344bc4c0e Remove the old switch/for semantics entirely and enforce switch &x in y 2024-05-16 14:39:16 +01:00
gingerBill e71cd871c4 Reimplement -build-mode:static/-build-mode:lib 2024-05-16 14:27:05 +01:00
Andreas T Jonsson a93bbf6f92 Merge branch 'master' into netbsd-ci 2024-05-16 13:48:44 +02:00
gingerBill f9fd8f0c25 Merge pull request #3439 from andreas-jonsson/netbsd
NetBSD support
2024-05-15 10:33:52 +01:00
gingerBill 59c33dd9fc Add Fstat_Callback for File.user_fstat 2024-05-14 18:57:03 +01:00
gingerBill 6f9dcb4e02 Add missing @(require_results) 2024-05-14 18:46:45 +01:00
gingerBill 2b43535961 Fix typo 2024-05-14 18:45:47 +01:00
gingerBill 61826594c9 Add comment state to prefer virtual.Arena over runtime.Arena 2024-05-14 18:37:23 +01:00
gingerBill 9a487ccb6f Delete dead code 2024-05-14 18:35:24 +01:00
gingerBill 453fc5182b Remove all uses of context stuff in os2 2024-05-14 18:34:05 +01:00
gingerBill 450b9ceaec Add @(require_results) everywhere in os2 2024-05-14 18:25:15 +01:00
gingerBill 48c1822709 Move utility stuff to internal_util.odin 2024-05-14 18:14:44 +01:00
gingerBill 91b7cdaad2 Mock out temp_file.odin stuff 2024-05-14 18:11:50 +01:00
gingerBill 361be301fa Use internal temp_allocator() 2024-05-14 17:24:37 +01:00
gingerBill ecd7846ec3 Clean up allocator stuff into allocators.odin 2024-05-14 17:10:53 +01:00
gingerBill e05315831f Fix #3586 2024-05-14 00:18:38 +01:00
gingerBill 7734b12f9a Fix #3587 2024-05-14 00:16:32 +01:00
gingerBill 20f8f9012d Attempt at fixing #3588 2024-05-14 00:11:57 +01:00
gingerBill 0cf9dcd314 Make .. ranges a complete error rather than a warning now.
This should have been an error years ago.
2024-05-13 18:15:29 +01:00
gingerBill 8fa20fb875 Extra check for field being nullptr 2024-05-13 14:44:53 +01:00
gingerBill 1b593fc1ca Correct core:intrinsics to base:intrinsics 2024-05-13 13:27:44 +01:00
gingerBill 215ef3d985 Make core:runtime etc a warning, and an error with -vet 2024-05-13 13:26:47 +01:00
gingerBill 8808e5584a If only warnings exist on print_all_errors, next time it is called, clear the error list.
This is mostly only syntax errors too
2024-05-13 13:26:22 +01:00
gingerBill 54ebfa6179 Fix hanging on thread.join for windows where the thread had not been started 2024-05-13 12:58:18 +01:00
gingerBill 4bdc8548bd Fix #3554 2024-05-13 12:55:49 +01:00
gingerBill 6dc0ee3877 Fix #3577 2024-05-13 12:54:01 +01:00
gingerBill 8d687a959d Fix #3516 2024-05-13 12:52:28 +01:00
gingerBill 8b4a8e4d80 Fix #3569 2024-05-13 12:49:12 +01:00
gingerBill 90f26368d9 Merge pull request #3572 from Feoramund/fix-unix-nonstart-thread-stall
Fix joining non-`Started` threads from blocking main thread
2024-05-13 12:45:02 +01:00
gingerBill e4ec7cc3f3 Merge pull request #3580 from Feoramund/suggest-test-all-packages
Suggest `-all-packages` flag when testing empty directory
2024-05-13 12:42:48 +01:00
gingerBill 34c8739b69 Fix #3578 2024-05-13 12:42:06 +01:00
gingerBill d1217340f5 Fix #3573 2024-05-13 12:26:01 +01:00
gingerBill 4eab735b13 Minor clean up of is_terminating code
This does not fix all known issues with it
2024-05-13 12:24:50 +01:00
gingerBill f8d235b6f5 Fix #3581 due to typo 2024-05-13 12:02:02 +01:00
gingerBill 7905f0533f Fix #3582 by disallowing it 2024-05-13 12:01:16 +01:00
gingerBill 3fb0d52a74 Fix #3585 2024-05-13 11:57:04 +01:00
gingerBill 07a538cd82 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-05-13 11:54:05 +01:00
gingerBill facae34354 Fix #3584 2024-05-13 11:53:59 +01:00
Andreas T Jonsson 5541f60233 Check examples/all on NetBSD 2024-05-13 10:02:48 +02:00
Andreas T Jonsson bde8407ce8 Merge branch 'netbsd' into netbsd-ci 2024-05-13 10:01:12 +02:00
Andreas T Jonsson 6298d4a36c Fixed some build tags in vendor libs 2024-05-13 10:00:19 +02:00
Andreas T Jonsson 3e181af409 Merge branch 'netbsd' into netbsd-ci 2024-05-13 09:44:27 +02:00
Andreas T Jonsson 88528f7613 Updated makefiles to exclude some tests on BSDs 2024-05-13 09:41:54 +02:00
Andreas T Jonsson 5d82f0cad5 Merge branch 'master' into netbsd 2024-05-13 09:21:32 +02:00
Feoramund 971201182a Fix read_directory() skipping directories on UNIX-likes 2024-05-12 19:52:36 -04:00
Feoramund 1935811b2c Suggest -all-packages if testing empty directory 2024-05-12 19:51:19 -04:00
Jeroen van Rijn 1183f4794b Merge pull request #3579 from Kelimion/test_string_compare
Test string compare
2024-05-12 23:52:39 +02:00
Jeroen van Rijn 23545c3f37 Enable in Makefile 2024-05-12 23:47:42 +02:00
Jeroen van Rijn 41b8f06f51 Add 1 more each for < and > 2024-05-12 23:43:05 +02:00
Jeroen van Rijn 55d21f4c2f Test string compare
To avoid regression of the bug fixed in f8581537e4.
2024-05-12 23:38:17 +02:00
gingerBill f8581537e4 Fix >= for strings
How did this not get noticed?!?!
2024-05-12 20:25:13 +01:00
gingerBill 0f76c22c46 Check for illegal use of distinct 2024-05-12 17:48:06 +01:00
gingerBill 6bfaf4a093 Fix another oversight for bit_field endian with 1-byte types 2024-05-11 22:36:17 +01:00
gingerBill f650690f61 Merge pull request #3574 from jasonKercher/i386-syscall6
fix 6 argument syscall on i386
2024-05-11 21:50:49 +01:00
gingerBill 321e4c45b0 Merge pull request #3576 from korvahkh/json-marshal-no-nil
encoding/json: Properly marshal `#no_nil` unions
2024-05-11 21:50:26 +01:00
korvahkh 9b759f39fc encoding/json: Properly marshal #no_nil unions
Previously the first variant of a `#no_nil` would always be output as
`null`, and following variants would be treated as the wrong type.
2024-05-11 14:36:56 -05:00
Jeroen van Rijn 3a3ae6d0df Fix and re-enable .doc tests. 2024-05-11 19:25:35 +02:00
gingerBill ad0053b798 Make doc writer use the old "Ordered Insertion" based PtrMap 2024-05-11 16:24:37 +01:00
gingerBill 8e263de4aa Fix error message handling 2024-05-11 13:59:06 +01:00
gingerBill 811d53b305 Generalize to any 1-byte element in bit_field 2024-05-11 13:48:19 +01:00
gingerBill aea28d5189 Allow edge-case where backing type of a bit_field is (array of) u8, to allow any endian type 2024-05-11 13:47:33 +01:00
jason 20752d904b fix 6 argument syscall on i386 2024-05-10 23:06:49 -04:00
Feoramund 33c6f75a2e Fix joining non-Started threads from blocking main thread 2024-05-10 17:24:45 -04:00
jasonkercher 2183140e71 arm32 now compiles and runs demo 2024-05-10 13:24:43 -04:00
Andreas T Jonsson f428e30211 Minor code cleanup 2024-05-10 17:49:56 +02:00
Jeroen van Rijn 2250eb3e78 Enable core:fmt tests. 2024-05-10 17:05:18 +02:00
gingerBill aebb5a5178 Merge pull request #3506 from IllusionMan1212/windows-hid
core/sys/windows: added various procedures and constants for the hid library
2024-05-10 16:03:13 +01:00
gingerBill b4d0b1d17d Merge pull request #3544 from ntn9995/fix-parser-empty-or-no-pkg
Fix core:odin/parser crashing on empty and/or no package files
2024-05-10 16:01:16 +01:00
gingerBill 20d35acce1 Fix parser 2024-05-10 15:59:14 +01:00
gingerBill 6c4672c158 Merge pull request #3566 from Feoramund/fmt-refactor
Refactor `wprintf`
2024-05-10 15:56:26 +01:00
gingerBill 3095f46d7e Add runtime.Typeid_Bit_Field 2024-05-10 15:50:47 +01:00
ikarus 3add85e7a7 fix typo & free memory when skipping empty files 2024-05-10 14:51:09 +01:00
gingerBill ad5c9469d8 Fix #3522 2024-05-10 14:22:43 +01:00
gingerBill 710bb4369f Fix #3567 2024-05-10 13:55:15 +01:00
Andreas T Jonsson a9b94f4019 Merge branch 'netbsd' into netbsd-ci 2024-05-10 13:34:02 +02:00
gingerBill 944fdd11f2 Keep -vet happy 2024-05-10 12:03:08 +01:00
gingerBill 07739b48ee Merge pull request #3565 from wschiefer/update-d3d12
Update d3d12 API
2024-05-10 12:00:39 +01:00
gingerBill b269fd00f0 Merge pull request #3560 from wschiefer/add-more-win32-console-apis
Add more win32 console APIs
2024-05-10 12:00:28 +01:00
gingerBill 04c391074d Merge pull request #3561 from wschiefer/update-dxgi
Adding DXGI 1.5 & 1.6 APIs
2024-05-10 12:00:11 +01:00
Andreas T Jonsson a45e69e656 Removed dead code 2024-05-10 09:12:56 +02:00
Andreas T Jonsson b72c2edabb Merge branch 'master' into netbsd 2024-05-10 09:04:52 +02:00
Andreas T Jonsson 273e4c6b4c Changed target data layout 2024-05-10 08:47:51 +02:00
Andreas T Jonsson f1491280ab Fixed invalid alignment 2024-05-10 08:16:10 +02:00
Feoramund fb2549a7da Extend test suite for fmt 2024-05-09 19:44:16 -04:00
Feoramund 11180e36ae Amend fmt documentation 2024-05-09 19:38:44 -04:00
Feoramund 8c111f1baf Fix %e printing incorrect precision
For example, `%.2e` with 30.56 as the value would produce `30.60e+01`,
as opposed to C's printf producing `30.6e+01`.
2024-05-09 19:37:17 -04:00
Feoramund 5e149d2cae Refactor wprintf
- Extracts common code between C and Python-like syntax into its own
   sub-procedures.
 - Fixes Python-like syntax from treating `}` as a verb.
 - Makes C-like syntax treat ' ' as a missing verb.
 - Fixes EXTRA arguments being formatted with options that were
   previously set, instead using default options now.
 - Makes error messaging more consistent between C and Python-like
   syntax.
 - Requires argument index to be specified immediately before the verb
   in C-like syntax, per the documentation, instead of after `%` _or_
   before the verb.
 - Tracks argument usage through a `bit_set`, allowing for reporting of
   unused arguments even when reordered.
 - Moves exit for C-like syntax if next byte is `%` to beginning of
   block instead of needlessly trying to parse through all options.
 - Pops next unused argument for unspecified formatters like `%i` or
   `{}`, instead of taking the argument after the last one used.
 - Fixes unspecified precision `%.f` from not setting precision to zero,
   per the documentation.
2024-05-09 19:28:04 -04:00
Jeroen van Rijn 41bd8cf714 Merge pull request #3563 from laytan/fix-duplicate-suggestions
fix duplicate suggestions and add missing newline
2024-05-09 20:20:18 +02:00
Jeroen van Rijn 1604f37cb8 Merge pull request #3564 from laytan/fix-some-vet-style-failures
fix a couple of `-vet-style` failures
2024-05-09 20:19:46 +02:00
Waldemar Schiefer 935865a978 Update d3d12 API 2024-05-09 19:46:02 +02:00
Laytan d7fdccb08c fix a couple of -vet-style failures after f54977336b 2024-05-09 19:39:48 +02:00
Laytan 98827c867d fix duplicate suggestions and add missing newline 2024-05-09 19:21:39 +02:00
Jeroen van Rijn 8a1e7bb6fb Merge pull request #3562 from Kelimion/bitset_to_enum_slice
Bitset to enum slice
2024-05-09 18:03:42 +02:00
Jeroen van Rijn 8f706a14f8 Add allocator param. 2024-05-09 17:58:48 +02:00
Jeroen van Rijn e5af98eabe Simplify bitset_to_enum_slice 2024-05-09 17:55:50 +02:00
Jeroen van Rijn 858c78b844 Pass new -vet-style check. 2024-05-09 17:47:19 +02:00
Jeroen van Rijn a61d8daec1 Add make version of bitset to slice. 2024-05-09 17:44:39 +02:00
Waldemar Schiefer cceac781e7 Add DXGI 1.5 & 1.6 APIs 2024-05-09 17:36:26 +02:00
Jeroen van Rijn 113feacbc7 Merge pull request #3559 from Kelimion/bitset_to_enum_slice
Add slice.enum_slice_to_bitset & slice.bitset_to_enum_slice
2024-05-09 17:21:04 +02:00
Jeroen van Rijn 7bcf3b1a0d Add slice.enum_slice_to_bitset & slice.bitset_to_enum_slice 2024-05-09 17:15:45 +02:00
gingerBill f54977336b With -vet-style, give suggestion of separating where clauses with a comma rather than '&&'
This improves the error messages
2024-05-09 15:56:00 +01:00
gingerBill b0f0e4d02a Add intrinsics type_bit_set_elem_type & type_bit_set_underlying_type 2024-05-09 15:47:09 +01:00
Waldemar Schiefer abcbb8b47a Add more win32 console APIs 2024-05-09 16:41:09 +02:00
gingerBill d85c8f0b2c Fix #3555 2024-05-09 10:58:57 +01:00
gingerBill 97e9c50d11 Fix #3556 2024-05-09 10:44:06 +01:00
gingerBill 9b75656400 Merge pull request #3308 from laytan/llvm-18
Support LLVM 18 (non-windows targets for now)
2024-05-08 13:39:57 +01:00
ikarus 60b6c798a5 tabs for indentation 2024-05-08 09:07:53 +01:00
IllusionMan1212 ad3675cdd6 core/sys/windows: added various procedures and constants related to the hid library 2024-05-07 21:18:25 +02:00
Laytan Laats 9d1db48549 remove is_packed bodge 2024-05-07 17:25:17 +02:00
Laytan b0b60fe7ed fix segfault in release builds of the compiler with clang++-18 2024-05-07 16:52:46 +02:00
Laytan 87b099b5aa fix merge conflict 2024-05-07 16:52:46 +02:00
Laytan Laats 77efdcd899 fix packed gep loads with wrong alignment 2024-05-07 16:52:46 +02:00
Laytan Laats 58c0abb98d revert wrong approach in fixing the load alignment 2024-05-07 16:52:46 +02:00
Laytan d93cc18dac fix packed gep loads with wrong alignment 2024-05-07 16:52:46 +02:00
Laytan Laats ecddf3b7f1 llvm-18: cleanup 2024-05-07 16:52:46 +02:00
Laytan Laats a3821615dc llvm-18: fix windows build error because of include 2024-05-07 16:52:46 +02:00
Laytan Laats f9a7d2bf04 llvm-18: enable static map calls on non amd64sysv targets 2024-05-07 16:52:46 +02:00
Laytan c219ca5b1b llvm-18: fix undocumented breaking change on i128 alignment 2024-05-07 16:52:46 +02:00
Laytan Laats f64e8ffd64 llvm-18: fix linking the compiler with clang-18 2024-05-07 16:52:46 +02:00
Laytan Laats e3e04ffa22 llvm-18: enable sroa and static map calls 2024-05-07 16:52:46 +02:00
Laytan 043dd98e91 fix demo out of bounds error 2024-05-07 16:52:46 +02:00
Laytan b91e7f5c51 llvm-18: linux (amd64) 2024-05-07 16:52:46 +02:00
Laytan Laats bb58926b7a llvm 18: general unix and darwin specifics 2024-05-07 16:52:46 +02:00
gingerBill 1d3c061add Fix typo 2024-05-07 15:52:13 +01:00
gingerBill de5ce90fa7 Add metadata to packed structs field accesses to state it is packed 2024-05-07 15:28:09 +01:00
gingerBill 3f7a369aa1 Check for specialization in typeid/T for parapoly records 2024-05-07 14:53:02 +01:00
gingerBill 94b4af5d36 Merge pull request #3540 from VictorSohier/handle-fixed-soa-arrays
Handle fixed soa arrays
2024-05-07 14:33:25 +01:00
gingerBill e378516011 Merge pull request #3547 from hnakamur/pass_size_to_epoll_create
sys/linux: Pass size to epoll_create
2024-05-07 14:33:18 +01:00
Jeroen van Rijn 2b1afa0762 Merge pull request #3521 from Su3h7aM/correct-clang++
Uses correct `clang++` binary for non-standard versions
2024-05-07 13:25:59 +02:00
gingerBill 0cec2d7827 Fix #3527 2024-05-07 11:51:06 +01:00
gingerBill 8d96c68528 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-05-07 11:42:53 +01:00
gingerBill 0da6a3e214 Fix #3530 2024-05-07 11:42:48 +01:00
gingerBill 41d38bf964 Merge pull request #3468 from Feoramund/fix-pthread-cancel
Fix discrepancy with pthread cancelability state
2024-05-07 11:30:07 +01:00
gingerBill 05a1704898 Fix #3464 2024-05-07 11:24:21 +01:00
gingerBill 1818df786d Free memory for the error messages just in case 2024-05-07 11:21:12 +01:00
gingerBill b23f1dd5ff Merge neighbouring error messages with the same location 2024-05-07 11:19:16 +01:00
Jeroen van Rijn 96abe8627c Merge pull request #3551 from Feoramund/fix-max-bitfield-size
Fix lack of adding to `total_bit_size`
2024-05-07 00:47:15 +02:00
Feoramund 6ec7845249 Fix #3531
Individual `bit_field` size was not being added to the total size.
Error message was changed to be more explicit.
2024-05-06 18:30:04 -04:00
Victor Sohier 56b62996c3 Remove breakpoint hook 2024-05-06 18:20:20 -04:00
Victor Sohier 6cb0f5d8c5 Explicitly handle previously implicitly handled case 2024-05-06 18:04:35 -04:00
Hiroaki Nakamura df53fec828 sys/linux: Pass size to epoll_create
Without this fix, you can see a random size value is passed to
epoll_create by using strace.
2024-05-06 21:44:59 +09:00
ikarus 16fbfd0418 ignore empty files and errors on no package 2024-05-06 09:25:22 +01:00
Victor Sohier a9b18c1ec0 Formatting 2024-05-05 21:15:41 -04:00
Victor Sohier 8e4f9cb777 Fix: Fixed #soa arrays 2024-05-05 21:08:33 -04:00
gingerBill 15f7148eae Merge pull request #3526 from laytan/target-features
Improve target features support
2024-05-05 21:50:57 +01:00
gingerBill 1e5267c8e7 Merge pull request #3532 from laytan/fix-invalid-json
fix invalid JSON when an error does not have a position
2024-05-05 16:48:12 +01:00
gingerBill 96a4cecee5 Merge pull request #3536 from laytan/linux-fix-open-bits
sys/linux: fix open bits
2024-05-05 16:47:42 +01:00
gingerBill 8ba36ca85c Merge pull request #3535 from Feoramund/freebsd-arm64-minimal
Minimally support compiling Odin on FreeBSD arm64
2024-05-05 16:47:28 +01:00
Laytan Laats eaab17f8fb sys/linux: fix open bits 2024-05-05 14:16:21 +02:00
Feoramund 1165d65c94 Minimally support compiling Odin on FreeBSD arm64
This is enough to get Odin itself compiling and the demo running.
2024-05-05 07:26:45 -04:00
Laytan Laats ee818304f3 fix invalid JSON when an error does not have a position 2024-05-05 00:01:14 +02:00
Su3h7aM 30ff15e538 build: uses correct clang++ binary for non-standard versions 2024-05-03 13:20:51 -03:00
gingerBill 17a01a81d8 Merge pull request #3528 from laytan/fix-some-sync-issues
Fix some sync issues
2024-05-03 17:14:50 +01:00
gingerBill 595726e6c5 Merge pull request #3369 from joakin/fix-dynamic-library-from-vendor-on-linux
Fix vendor dynamic libraries not working on Linux
2024-05-03 17:14:32 +01:00
gingerBill fed03e896c Merge pull request #3525 from Feoramund/fix-more-error-racecond
Fix more race conditions in error reporting
2024-05-03 17:14:13 +01:00
gingerBill 2201f365a1 Allow #no_alias on multi-pointers 2024-05-03 14:51:02 +01:00
gingerBill f2505b096d Improve error message's suggestion for if !integer 2024-05-03 14:22:30 +01:00
gingerBill 242307dd44 Revert to old StringMap internal layout 2024-05-03 12:34:12 +01:00
Laytan Laats 8aab395c70 darwin: fix minimum os version check not being inclusive 2024-05-02 21:18:49 +02:00
Laytan Laats 8506e64345 sync: fix deadlock in one shot event 2024-05-02 20:49:29 +02:00
Andreas T Jonsson 1d3845abf5 Added prebuilt clang17 2024-05-02 16:52:46 +02:00
Andreas T Jonsson ecaa26710b Fixed invalid package name 2024-05-02 14:50:13 +02:00
Andreas T Jonsson 9de9223578 Use custom llvm binaries 2024-05-02 14:38:54 +02:00
Andreas T Jonsson 021271091a Merge branch 'netbsd' into netbsd-ci 2024-05-02 09:34:17 +02:00
Andreas T Jonsson 7feff1c113 Merged with master 2024-05-02 09:27:46 +02:00
Laytan Laats 25f1d0906d compiler: improve target features support 2024-05-02 00:59:52 +02:00
Feoramund 67b786c738 Fix more race conditions in error reporting 2024-05-01 16:41:02 -04:00
Jeroen van Rijn fd582015fe Remove stray binary. 2024-04-30 20:58:36 +02:00
Jeroen van Rijn 58e12f0b17 Merge pull request #3520 from flysand7/sys-linux-oflags
[sys/linux]: Fix bit numbers for open flags
2024-04-30 20:40:24 +02:00
flysand7 9ffa4a4eb1 [sys/linux]: Fix bit numbers for open flags 2024-05-01 05:24:02 +11:00
gingerBill eb06cb5d23 Merge pull request #3518 from laytan/sysinfo-arm-additions
sys/info: add arm feature detection, fix Linux implementation, show more CPU info on Darwin
2024-04-30 12:48:48 +01:00
gingerBill 5c1201fa42 Fix #3459 2024-04-30 09:10:00 +01:00
Laytan Laats c0ca26ac17 sys/info: add missing @(private)'s 2024-04-30 00:24:09 +02:00
Laytan Laats b41395e3b4 sys/info: update doc.odin 2024-04-30 00:24:09 +02:00
Laytan Laats d40c207fde sys/info: retrieve better CPU description on Darwin
Previously either `ARM` or `ARM64`, now you get something like `Apple
M1`
2024-04-30 00:24:09 +02:00
Laytan Laats 8660718ebe sys/info: add feature detection for Darwin and Linux ARM 2024-04-30 00:24:09 +02:00
Laytan Laats 485afb011c sys/info: improve platform_linux
1. fix the `linux.open` call, passing `{ .RDONLY }` becomes `0x00000001`
   while `RDONLY` is supposed to be `0x00000000`
2. fix the case where `/etc/os-release` starts with `PRETTY_NAME`
   `strings.index` was used but was checking `> 0` while `0` is valid
3. remove unneccesary temporary allocations
4. simplify the logic
2024-04-30 00:24:09 +02:00
Laytan Laats 9e94e9dac1 sys/info: remove unneccesary build tags 2024-04-30 00:24:09 +02:00
Laytan Laats cebe6bd982 sys/unix: add sysctlbyname for darwin 2024-04-30 00:24:09 +02:00
Laytan Laats c58da76562 sys/darwin: fix sysctl and sysctlbyname syscalls 2024-04-30 00:24:09 +02:00
Laytan Laats e896efdaeb sys/info: add easy way of getting the MacOS version 2024-04-30 00:24:09 +02:00
Timo 2918baa3e8 Update builder.odin
Modify documentation-text for procedure write_f64 :

change type f32 to f64
2024-04-29 20:22:53 +02:00
gingerBill ff0973e0f5 Merge pull request #3513 from thetarnav/patch-2
Remove instrinsics and utf16 imports from os/os_js
2024-04-29 16:51:45 +01:00
Damian Tarnawski ae322739b5 Remove instrinsics and utf16 imports from os/os_js 2024-04-29 16:59:52 +02:00
gingerBill f6345d20f7 Merge pull request #3508 from Feoramund/fmt-alloc-print-reqres
Require results for non-buffered `print` procs
2024-04-29 12:04:58 +01:00
gingerBill 227aab8f39 Merge pull request #3507 from IllusionMan1212/glsl-fix
fix(linalg/glsl): incorrect quat by vector3 multiplication
2024-04-29 12:04:07 +01:00
gingerBill d6824ea607 Merge pull request #3505 from Feoramund/allow-disabled-init-procs
Allow `@(init)` procs to be `@(disabled)`
2024-04-29 12:03:54 +01:00
gingerBill 2f88ded81a Merge pull request #3504 from Feoramund/fix-racecond-error-va
Fix race condition in `error_va`
2024-04-29 12:03:26 +01:00
Feoramund bbebb4ad60 Fix unseen print call in demo 2024-04-28 17:20:52 -04:00
Feoramund 700f9c94bd Combine adjacent sbprint*/to_string calls
The `sbprint*` procs already return a string conversion.
2024-04-28 17:18:46 -04:00
Feoramund c712de0cd0 Require results for non-buffered print procs 2024-04-28 17:17:01 -04:00
IllusionMan1212 1f5f417116 fix(linalg/glsl): incorrect quat by vector3 multiplication 2024-04-28 21:44:34 +02:00
Feoramund a573161abd Allow @(init) procs to be @(disabled) 2024-04-28 14:42:04 -04:00
Feoramund f1c13d6bd8 Fix race condition in error_va
If the error count exceeded `MAX_ERROR_COLLECTOR_COUNT`, multiple
threads could print and exit simultaneously, causing a segfault.

This change moves the mutex lock back before the conditional.
2024-04-28 14:03:11 -04:00
Artsiom Babukh 805bb69c6c Fix typo in core_builtin 2024-04-28 15:27:34 +00:00
gingerBill a37826e646 Merge pull request #3268 from olesya-wo/core-mem-tracking_allocator-improve
Improved statistics for core/mem/Tracking_Allocator
2024-04-28 16:01:01 +01:00
gingerBill 3b4169c903 Merge pull request #3495 from Feoramund/fix-rune-literal-error-double-reporting
Fix invalid rune literal reported twice
2024-04-28 15:22:05 +01:00
gingerBill 0eb97dba6e Merge pull request #3496 from laytan/allow-default-to-nil-allocator-on-wasm
wasm: allow `-default-to-nil-allocator`
2024-04-28 15:21:45 +01:00
gingerBill fa5e6d2d84 Merge pull request #3497 from laytan/fix-buddy-allocator-wrong-query-info
fix: buddy allocator wrong query info pointer
2024-04-28 15:21:35 +01:00
gingerBill 4668dafa2b Merge pull request #3498 from laytan/add-fprint-to-wasm
wasm: add the `fprint` procedures to `fmt`
2024-04-28 15:21:27 +01:00
Laytan Laats cc5faecced wasm: add the fprint procedures to fmt
This makes the `log` package work on wasm
2024-04-28 16:10:04 +02:00
Laytan Laats 0530f86a48 fix: buddy allocator wrong query info pointer 2024-04-28 16:09:03 +02:00
Laytan Laats 4fea5720a5 wasm: allow -default-to-nil-allocator 2024-04-28 16:05:41 +02:00
gingerBill 30cfdd73b0 Add extra asserts 2024-04-28 14:45:59 +01:00
gingerBill 950fd2d5ce Rename trace_linux.odin to trace_cpp.odin 2024-04-28 13:52:52 +01:00
gingerBill 74d75fb7fb Correct types on windows 2024-04-28 13:51:46 +01:00
gingerBill 7ee2c1084f Update doc.odin 2024-04-28 13:51:10 +01:00
gingerBill c0b7dd7da6 Remove need for allocator and MAX_FRAMES in trace.frames 2024-04-28 13:05:19 +01:00
gingerBill be09584ea5 Increase MAX_FRAMES 2024-04-28 12:56:53 +01:00
gingerBill 5ac8e8f9fd Add doc.odin 2024-04-28 12:52:02 +01:00
gingerBill 2eea06fc73 Set in_resolve for linux 2024-04-28 12:51:10 +01:00
gingerBill 0fa269811a Change layout of Frame_Location 2024-04-28 12:49:17 +01:00
gingerBill 6c185a5dca Add core:debug/trace for Linux 2024-04-28 12:43:27 +01:00
gingerBill f428f26c8e Merge branch 'master' of https://github.com/odin-lang/Odin 2024-04-28 12:05:21 +01:00
gingerBill 44c9b988bb Add default debug/trace to do nothing 2024-04-28 12:05:15 +01:00
Feoramund 29987c20c0 Fix invalid rune literal reported twice
The tokenizer and the parser were reporting it in different positions.
This way, they'll report in the same spot.
2024-04-28 07:02:21 -04:00
gingerBill 51d4dde63c Merge pull request #3494 from Feoramund/fix-3481
Clear unused `global_error_collector.curr_error`
2024-04-28 11:59:18 +01:00
gingerBill 362aa82f59 Begin work on core:debug/trace 2024-04-28 11:58:16 +01:00
Feoramund ebfbe4d260 Clear unused global_error_collector.curr_error
This should cleanly prevent acknowledging duplicate errors on the same
position as seems to be the intent based on the prior `else if`
condition.
2024-04-28 06:44:28 -04:00
gingerBill e71cf96bbc Keep -vet happy 2024-04-28 11:35:51 +01:00
gingerBill 383c17e842 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-04-28 11:31:55 +01:00
gingerBill 00b1a41540 Add stack frame procedures for core:sys/windows 2024-04-28 11:31:50 +01:00
Jeroen van Rijn 8fd318ea7a Merge pull request #3492 from DreepyYunky/Add-SetMenu
Add `SetMenu()`
2024-04-27 20:04:15 +02:00
Yunky 1deb53cddb Add SetMenu 2024-04-27 18:58:46 +01:00
gingerBill 05b5b8503d Merge pull request #3491 from Feoramund/fix-json-omitempty
Fix `omitempty` in `json.marshal`
2024-04-27 15:32:21 +01:00
gingerBill 5e1b376e22 Disallow for x in bitset_or_map if x is a variable that matches the "key" 2024-04-27 10:34:17 +01:00
Feoramund 309a770cbf Fix omitempty in json.marshal 2024-04-27 05:24:59 -04:00
gingerBill 393e4a9db6 Generalize Odin call-based "iterators" to work with more than 2-values: for x, y, z, w in iterate(&it)
It has an artificial limitation of 100 values because if you need for than that, you're doing something wrong.
2024-04-27 09:53:02 +01:00
gingerBill efae99971b Fix missing _ = 2024-04-27 09:19:50 +01:00
gingerBill 4454849252 Add attributes to procedures in text/scanner 2024-04-27 09:16:36 +01:00
gingerBill c752d0b541 Fix printing of big endian integers in a bit_field 2024-04-27 09:16:18 +01:00
gingerBill 5969796fbf Merge pull request #3490 from odin-lang/new-string-map
Change layout of compiler hash map types
2024-04-27 09:03:05 +01:00
gingerBill 6520794764 Fix wrong allocator usage 2024-04-27 08:50:05 +01:00
gingerBill 9d3f835e31 Merge pull request #3462 from Yawning/feature/math-sys-rand
core:math/rand: Use `crypto.rand_bytes()` for the system RNG
2024-04-27 08:43:02 +01:00
gingerBill 70aa2ff90a Merge pull request #3489 from Feoramund/fix-build-freebsd
Fix wrong llvm-config in build script for FreeBSD
2024-04-27 08:40:23 +01:00
gingerBill a60a7f64b9 Merge pull request #3483 from laytan/negative-improvements
improve some Negative_Read/Negative_Write logic
2024-04-27 08:38:29 +01:00
gingerBill 2368014d06 Merge pull request #3486 from Feoramund/fix-chan-memleak
Fix memory leak in `sync/chan`
2024-04-27 08:37:52 +01:00
Feoramund 92402a75f6 Fix wrong llvm-config in build script for FreeBSD 2024-04-26 18:40:59 -04:00
gingerBill 4bea5dbac1 Correct map usage 2024-04-26 15:09:08 +01:00
gingerBill 2b26384b89 Implement dumb PtrMap 2024-04-26 15:04:46 +01:00
gingerBill c685b404ea Implement dumb StringMap 2024-04-26 14:15:22 +01:00
gingerBill a3e77dcc3b Minor clean up 2024-04-26 13:25:08 +01:00
gingerBill 7305478261 Minor changes 2024-04-26 13:12:23 +01:00
gingerBill 94e0707456 Fix minor bug 2024-04-26 13:12:15 +01:00
Feoramund f95bb77f72 Fix memory leak in sync/chan 2024-04-26 05:19:52 -04:00
Andreas T Jonsson 6bbdbb4447 Added missing core:sys/info package for NetBSD 2024-04-26 11:04:27 +02:00
Andreas T Jonsson 22fa420c4f Should pass 0 as the rest of futex arguments 2024-04-25 22:22:59 +02:00
Andreas T Jonsson 9a008d10f3 Merge branch 'master' into netbsd 2024-04-25 22:04:40 +02:00
Andreas T Jonsson 3000508c02 Switched to native futex on NetBSD 2024-04-25 21:50:34 +02:00
Laytan Laats d3bd1c2110 improve some Negative_Read/Negative_Write logic
Returns the actual error if one is set, instead of swallowing it for the
less descriptive negative error.

Also fixes a out-of-bounds slice error in `bufio.writer_write` because
it wasn't checking the returned `m`.
2024-04-25 19:08:48 +02:00
gingerBill f745fff640 Merge pull request #3467 from laytan/clang-18-linking-backport
fix linking with clang-18
2024-04-25 16:09:17 +01:00
Andreas T Jonsson c1ff7894df Should only run BSD tests 2024-04-25 13:47:55 +02:00
gingerBill 8f4e3b552e Merge pull request #3478 from laytan/fix-send-event-proc-signature
sys/darwin/foundation: fix Application->sendEvent signature
2024-04-25 12:32:10 +01:00
gingerBill 1ea353dbf7 Merge pull request #3479 from laytan/support-0-sized-return-arm64-abi
compiler: support returning 0 sized types in arm64 abi
2024-04-25 12:31:56 +01:00
Andreas T Jonsson b6eaadb9a8 Fixed invalid git path 2024-04-25 13:31:33 +02:00
Andreas T Jonsson f53abf736b Print the path of the git safe directory 2024-04-25 13:25:46 +02:00
Andreas T Jonsson 4c9c0899a9 Added git safe directory config 2024-04-25 13:14:09 +02:00
Andreas T Jonsson 2b8836e29a Fixed broken export 2024-04-25 13:03:19 +02:00
Andreas T Jonsson 101abb3004 Simple CI setup for NetBSD 2024-04-25 12:46:55 +02:00
Andreas T Jonsson ce80c37c75 Fixed potential memory leak 2024-04-25 11:04:44 +02:00
Andreas T Jonsson 642391eb49 Implemented absolute_path_from_handle for NetBSD 2024-04-25 09:45:28 +02:00
Andreas T Jonsson 8ffe577a15 Added missing build tags in core 2024-04-25 09:43:54 +02:00
gingerBill e3d41f0a9e Merge branch 'master' of https://github.com/odin-lang/Odin 2024-04-24 20:55:22 +01:00
gingerBill 3b53c99576 Improve support for big-endian bit_fields 2024-04-24 20:55:18 +01:00
Laytan Laats a4cec2e8b8 sys/darwin/foundation: fix Application->sendEvent signature 2024-04-24 19:51:08 +02:00
Laytan Laats e8c5bb4629 compiler: support returning 0 sized types in arm64 abi 2024-04-24 19:50:39 +02:00
gingerBill c72a269b7c Merge pull request #3477 from laytan/fix-macos-versions
ci: fix macOS versions
2024-04-24 17:48:45 +01:00
gingerBill 94d35d9918 Disallow mixing endian types within a bit_field 2024-04-24 17:31:31 +01:00
Laytan Laats 448827c0e4 ci: fix macOS versions 2024-04-24 18:29:28 +02:00
gingerBill 04278cd654 Remove line info in message with -json-errors 2024-04-24 17:13:53 +01:00
gingerBill 15942fbf25 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-04-24 17:01:16 +01:00
gingerBill 214537b420 Improve codegen for bit_field [N]T compound literals 2024-04-24 17:01:09 +01:00
gingerBill c330e5b5c1 Improve codegen for bit_field compound literals with an integer backing 2024-04-24 14:46:34 +01:00
gingerBill ec5a84a537 Improve code generation for loading bit_field fields 2024-04-24 13:10:58 +01:00
gingerBill 5b6c96cd18 Merge pull request #3466 from laytan/fix-proc-args-debug-info
fix direct proc args debug info
2024-04-23 13:07:25 +01:00
Yawning Angel e2fa9be7e2 core/math/rand: Use core:crypto for the system RNG
This removes some code duplication and expands support for the system
RNG to all targets that `core:crypto` supports.
2024-04-23 11:47:43 +09:00
Yawning Angel a6eb64df6c core/crypto: Add a HAS_RAND_BYTES constant 2024-04-23 11:47:43 +09:00
alec hodgkinson 3b632b4d90 Fixed typo in raylib documentation 2024-04-22 15:13:52 -07:00
Feoramund 9cdb7b2584 Fix discrepancy with pthread cancelability state 2024-04-22 17:16:33 -04:00
Laytan d1a1e8f646 fix linking with clang-18
Because we currently just use the clang from the user's path linking
suddenly breaks when the user updates their system clang to 18 with an
error about an unknown option -arch.

I had already fixed it for my LLVM 18 PR but it seems like a good idea
to get this in already to avoid that breakage (had a few people come to
the Discord with it and an issue).

This fixes #3461
2024-04-22 20:58:54 +02:00
gingerBill 75fcd50b9a Merge branch 'master' of https://github.com/odin-lang/Odin 2024-04-22 18:41:51 +01:00
gingerBill c6a446fe87 Add check for build. and run. typos 2024-04-22 18:41:48 +01:00
Laytan Laats 90369b669b fix direct proc args debug info 2024-04-22 19:36:24 +02:00
gingerBill f5719ae47c Merge pull request #3465 from thetarnav/fmt-printfln-js
Add printfln and eprintfln procs to fmt_js.odin
2024-04-22 16:01:36 +01:00
Andreas T Jonsson 384137d4e9 Use PHYSMEM64 on NetBSD
I realize we should use PHYSMEM64 on NetBSD. So we can not share code with FreeBSD.
2024-04-22 10:15:52 +02:00
Andreas T Jonsson 1b15d8b453 Added build tag
Added build tag to rand_bsd.odin and fixed build warning.
2024-04-22 09:32:19 +02:00
Damian Tarnawski 2a70faca14 Add printfln and eprintfln functions to fmt_js.odin 2024-04-21 22:37:04 +02:00
Yawning Angel 902e877467 repo: Add more test binaries to .gitignore 2024-04-21 21:22:05 +09:00
Jeroen van Rijn caa8863c97 Merge pull request #3455 from Hyrtwol/normalize-path
Normalize ODIN_ROOT path
2024-04-20 12:08:12 +02:00
Thomas la Cour ebb1a07dd0 spelling 2024-04-20 09:37:30 +02:00
Thomas la Cour 0a16f7a6f1 normalize_path 2024-04-20 09:37:30 +02:00
gingerBill 3620e62ff7 Merge pull request #3453 from GoNZooo/gonz.add-nosignal-broken-pipe
fix(net/linux): add `NOSIGNAL` to `send` options
2024-04-19 14:05:49 +01:00
gingerBill d84b29866f Merge pull request #3447 from matias-eduardo/fix-soa-hash-formatting
fix #soa '%#v' formatting
2024-04-19 14:05:15 +01:00
Andreas T Jonsson 50cbb802b7 Fixed bug report information for NetBSD 2024-04-19 14:44:35 +02:00
Rickard Andersson 68f663ea85 fix(net): fix return type for send_tcp
Was `.Connection_Closed` but this is only inferrable if our return type
is not a sub-union of another.
2024-04-19 15:39:04 +03:00
Rickard Andersson efc84cd390 docs(net): add comment about EPIPE -> Connection_Closed 2024-04-19 15:37:20 +03:00
gingerBill ea49331799 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-04-19 13:33:02 +01:00
gingerBill 059175de3b Do not print column of a runtime.Source_Code_Location if the column == 0 2024-04-19 13:32:55 +01:00
Rickard Andersson 7b95562827 feat(net): turn EPIPE into Connection_Closed 2024-04-19 15:29:28 +03:00
Rickard Andersson c44f618b7d fix(net): add NOSIGNAL to send options
This is a better default than not having it, since it turns errors that
would be signals into error values instead. We could take these as
options but given that we currently don't I think this at the very least
improves on the status quo.
2024-04-19 15:17:21 +03:00
joakin 60ef4fda4d Recognize dynamic library names like libraylib.so.5.0.0 2024-04-19 13:35:53 +02:00
Andreas T Jonsson a23c378513 Make the linter happy 2024-04-19 12:32:09 +02:00
Andreas T Jonsson dd95a8d11d More std lib fixes
Just selecting the same codepath as other BSD's for the most part.
2024-04-19 10:42:09 +02:00
Jeroen van Rijn 1b143b9fa3 Merge pull request #3452 from mgavioli/Fix_i18n_get-section_number_default
Fix #3451 - `core:text/i18n` default `number` value in `get_*_section`
2024-04-19 09:24:17 +02:00
Maurizio M. Gavioli ec7e75a57f Fix #3451 - core:text/i18n default number value in get_*_section proc.
In the to procs `get_single_section()` and `get_by_section()` the `number` parameter should have a default of `1` rather than `0`.

See the issue for more details.
2024-04-19 08:23:28 +02:00
gingerBill 20223345a4 Return partial reads 2024-04-19 00:33:31 +01:00
gingerBill 3812d5e002 Only override the comma value on *_init if it is "invalid" 2024-04-19 00:19:02 +01:00
Andreas T Jonsson 07fc07822d Added some libc bindings for NetBSD 2024-04-18 16:22:07 +02:00
Andreas T Jonsson 41d4dfbcd5 Fixed concurrency issue
Fixed broken thread policy causing deadlocks.
2024-04-18 16:20:49 +02:00
gingerBill 2416380f34 Enforce as global constant 2024-04-18 12:56:18 +01:00
gingerBill 5200e3fe7a Set __$ti- stuff to be private linkage 2024-04-18 12:45:20 +01:00
gingerBill b72d49ceb5 Set linkage to private for __$type_info_data 2024-04-18 12:41:05 +01:00
gingerBill 689982a38d Force runtime type table to be in rodata/rdata section 2024-04-18 12:22:41 +01:00
gingerBill 334e08c750 Update numerous package declaration names 2024-04-18 12:17:39 +01:00
gingerBill f84a092977 Fix typo. 2024-04-18 11:28:46 +01:00
gingerBill aad41fc762 Fix #3445 2024-04-18 11:27:42 +01:00
gingerBill ece78d22d2 Add -no-type-assert and ODIN_NO_TYPE_ASSERT 2024-04-18 11:22:31 +01:00
gingerBill 5c52f3cf2f Add ODIN_NO_BOUNDS_CHECK 2024-04-18 11:13:44 +01:00
gingerBill 889cd5461c Add @(optimization_mode="size") to runtime.print_type 2024-04-18 11:00:47 +01:00
gingerBill 6127339c56 Add #force_no_inline to many of the runtime print procedures 2024-04-18 10:59:02 +01:00
Andreas T Jonsson 38640d5d9e Updated core lib and did cleanup
Updated core with some path related functions and did some minor code cleanup.
Most of the standard library function is just a matter of copy what is there for the other BSDs.
2024-04-18 10:12:42 +02:00
Matias Fernandez e296b050ee fix #soa '%#v' formatting 2024-04-17 22:54:30 -04:00
gingerBill 9bbe26f80f Merge pull request #3441 from Chickenkeeper/copy-from-string-docs-fix
Correct `copy_from_string` docs
2024-04-17 13:50:08 +01:00
gingerBill 7cd2bc26f4 Clear error message on collisions with using on struct fields 2024-04-17 13:31:32 +01:00
Andreas T Jonsson 2055f2b933 Fixed link warnings
Hardlink libc functions to the correct version on NetBSD 10 since we do not use the micro-magic from C.
2024-04-17 09:46:57 +02:00
Andreas T Jonsson 80067a959b Added thread name
Call pthread_setname_np with the correct number of arguments on NetBSD.
2024-04-17 09:42:41 +02:00
Chris 6dcf38b85b Correct copy_from_string docs 2024-04-16 21:36:54 +01:00
gingerBill a61ae7c861 Fix #3427 2024-04-16 13:31:49 +01:00
Andreas T Jonsson 4558f3992a Initial commit of NetBSD port 2024-04-16 14:27:29 +02:00
gingerBill 8a0f9ae108 Print to string buffer before printing errors 2024-04-16 13:15:23 +01:00
Jeroen van Rijn fd1eb17771 Merge pull request #3437 from Feoramund/fisher-yates-shuffle
Implement Fisher-Yates shuffle
2024-04-16 10:28:35 +02:00
Feoramund 3e449e93dd Implement Fisher-Yates shuffle 2024-04-15 17:07:05 -04:00
Jeroen van Rijn 436c5dc40c Merge pull request #3436 from karl-zylinski/fix-vet-unused-in-dynlib
Fix for dynlib:initialize_symbols not passing -vet-unused
2024-04-15 21:55:12 +02:00
Karl Zylinski 0729f2b4fb Fix for dynlib:initialize_symbols not passing -vet-unused 2024-04-15 21:26:30 +02:00
gingerBill 76229cabfa Fix typo 2024-04-15 15:44:03 +01:00
gingerBill a7e492e2c2 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-04-15 15:40:43 +01:00
gingerBill 69db9c6390 Add loads of nil checks when doing s.builder 2024-04-15 15:40:32 +01:00
Jeroen van Rijn 6def86bb4b Merge pull request #3431 from Feoramund/fix-randprime-2ndmsb
Fix `big.internal_random_prime` with `Second_MSB_On`
2024-04-15 16:30:16 +02:00
gingerBill 38c1fd5824 Keep -vet happy 2024-04-15 14:35:51 +01:00
gingerBill d5e6d722d3 Merge pull request #3045 from laytan/cbor
encoding/cbor
2024-04-15 14:28:52 +01:00
gingerBill 2af777b6cb Merge pull request #3419 from puzzleddev/fixup-d3d12-thiscall-affected-methods
Fixup vendor/d3d12 calling convention mistakes
2024-04-15 13:19:19 +01:00
gingerBill 5bda2546f7 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-04-15 12:43:50 +01:00
gingerBill 36644a3c09 Add template specialization for compared against "" with String internally 2024-04-15 12:43:45 +01:00
gingerBill 7e582dd671 Add basic suggestion to missing package name 2024-04-15 12:43:27 +01:00
gingerBill c7ac28f6a1 Merge pull request #3434 from flysand7/sys-linux-fixes
[sys/linux]: Fix syscall calls for open and fstat
2024-04-15 12:28:59 +01:00
flysand7 4bfa1ea76c [sys/linux]: Fix syscall calls for open and fstat 2024-04-15 22:16:03 +11:00
gingerBill 758ace844c Merge pull request #3428 from mgavioli/fix_core_docs
Fix the format of some `doc.odin` files of the `core` library…
2024-04-15 12:12:20 +01:00
gingerBill b9d7b8d616 Merge pull request #3429 from flysand7/sys-linux-wait4-fix
[sys/linux]: Fix signature on wait4 syscall
2024-04-15 11:51:51 +01:00
Feoramund a294f067a9 Fix big.internal_random_prime with Second_MSB_On 2024-04-15 05:49:15 -04:00
gingerBill 2e29687cee Fix #3425 2024-04-15 10:28:14 +01:00
flysand7 a0e25be196 [sys/linux]: Fix signature on wait4 syscall 2024-04-15 11:16:52 +11:00
Maurizio M. Gavioli a0cff82320 Fix the format of some doc.odin files of the core library which did not made into the documentation.
`c/frontend/tokenizer`:
   add proper "Example:" header to demo example code,
   removed empty lines.
`container/bit_array`:
   moved comment before package;
   aligned narrative lines to left margin;
   converted case lines into bulleted lines ("- ");
   converted individual examples to single-tab-indented preformatted text.
`dynlib`:
   removed "//+build ignore" line;
   added newline at EOF.
`image/netpmb`:
   converted indented lines of "Reading", "Wrting" and "Some syntax..." into bulleted lists;
   "Formats" indented lines kept as they are as the preformatted text seems relevant to keep the alignments;
   doubly indented lines kept as single-indented to keep them different (as the format does not allow for two-level bulleted lists);
   removed empy lines.
`os/os2`:	WIP, not modified
`sys/info`:
   removed "//+build ignore" line;
   converted tab-indented initial description into regular left-margin comment;
   moved uncommented sample code within the doc comment as an "Example:";
   moved simple- and double-tabbed separate comments with sample Windows and macOS outputs within the doc comment as bulleted headlines with preformatted output listings;
   removed now empty comments and blank lines after the package line.
`text/i18n`:
   removed "//+build ignore" line;
   moved the pacakge line at the end;
   de-indented the tab-indented introductory narrative;
   moved sample code comments into the doc comment as tab-indented code with a proper "Example:" heading;
   removed "```" MD attempts at code formatting.
`text/table`:
   unindented the comment lines of a descriptive kind;
   headlines of major subdivisions are marked as bold;
   kept code samples as tab-indented preformatted text (as there are several of them, the standard "Example:" and "Output:" headings cannot be used) removing the "```" MD attempts at code formatting;
   removed in-between blank lines.
2024-04-14 17:18:08 +02:00
Jeroen van Rijn d510d5e49f Merge pull request #3426 from Kelimion/crlf
Tell Git to always treat Makefile and build_odin.sh as Nix EOL
2024-04-14 16:51:42 +02:00
Jeroen van Rijn 9591eb2ed5 Tell Git to always treat Makefile and build_odin.sh as Nix EOL 2024-04-14 16:41:10 +02:00
gingerBill 21969fec61 Merge pull request #3421 from laytan/add-odin-root-command
add `odin root` command
2024-04-13 22:44:53 +01:00
gingerBill 6ee818b394 Merge pull request #3422 from wrapperup/add-dxc-vendor-docs
Add dxc to all_vendor.odin, fix dxc build on freebsd/openbsd
2024-04-13 22:42:03 +01:00
wrapperup b22e43c335 add freebsd, openbsd to dxcdef_unix.odin 2024-04-13 15:27:02 -04:00
gingerBill 6dc9fdb718 Merge pull request #3420 from laytan/fix-wasm-runtime-store-string-with-unicode
fix wasm runtime.js storeString to support Unicode
2024-04-13 20:15:41 +01:00
wrapperup f252084b1f add dxc to all_vendor.odin 2024-04-13 15:05:51 -04:00
Laytan Laats 9f97056c14 add 'odin root' command 2024-04-13 20:08:57 +02:00
Laytan Laats d2ca91b830 fix wasm runtime.js storeString to support Unicode 2024-04-13 19:34:13 +02:00
gingerBill 59705035f9 Merge pull request #3365 from yay/core-foundation-security
Core Foundation and Security core packages.
2024-04-13 10:56:24 +01:00
Vitalii Kravchenko befb0f7868 Core Foundation and Security vendor libraries. 2024-04-13 00:11:42 +01:00
tim4242 d5bb67e9e6 Fixup vendor/d3d12 calling convention mistakes 2024-04-12 20:47:02 +02:00
Jeroen van Rijn f086b4710a Merge pull request #3418 from blob1807/add-url-fragment-to-split-join-url
core:net Add support for URL fragments
2024-04-12 17:19:29 +02:00
blob1807 a4d16e97a1 Fix CI's parser 2024-04-13 01:14:55 +10:00
blob1807 6348b56c8b Move rounded tests 2024-04-13 00:57:36 +10:00
blob1807 2d1260bec9 uniformity change
small change to check things uniform
2024-04-13 00:47:49 +10:00
blob1807 c753711d86 Added support for URL fragments
Added support for a URL's fragment/anchor to `split_url` & `join_url` in `core:net` plus 4 new tests to cover it.
2024-04-13 00:39:32 +10:00
gingerBill 5726b7d954 Remove warning on clang 2024-04-12 14:51:22 +01:00
gingerBill 4240e0025e Improve scalar -> array assignment when the scalar is constant in LLVM 2024-04-12 14:20:46 +01:00
gingerBill caa344c88d Simplify scalar -> array conversions in LLVM to use a loop after a certain size 2024-04-12 14:05:36 +01:00
gingerBill 46b9bd8c0e Improve error messages for switch and for r-values with a suggestion 2024-04-12 13:35:14 +01:00
gingerBill 3426af2d6c Fix #3415 2024-04-12 12:33:25 +01:00
gingerBill efc3f9916e Fix #3414 2024-04-12 12:30:16 +01:00
Jeroen van Rijn 95bc1892f5 Merge pull request #3413 from hodgka/trig_funcs_doc
Added docs for trig function procedure groups
2024-04-11 19:02:41 +02:00
alec hodgkinson 4cdadeedc3 Added docs for trig function procedure groups 2024-04-11 09:55:43 -07:00
gingerBill cb0a57eaa9 Add -target:freestanding_amd64_win64 2024-04-11 17:18:51 +01:00
gingerBill aab122ede8 Remove ? 2024-04-11 15:59:22 +01:00
gingerBill 503964c769 Add @(static) check 2024-04-11 15:57:13 +01:00
gingerBill b2e887be36 Change stack overflow check to >256 KiB 2024-04-11 15:55:01 +01:00
gingerBill f36fb6d1ef Add nil checks 2024-04-11 15:41:01 +01:00
gingerBill 45d7a670ce Fix @(static) error message bug 2024-04-11 15:34:34 +01:00
gingerBill 86e82dc182 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-04-11 15:24:42 +01:00
gingerBill b6d2ac11b8 Add -vet-unused-variables and `-vet-unused-imports (-vet-unused is both) 2024-04-11 15:24:36 +01:00
gingerBill 6c38ae3658 Remove #optional_ok from docs 2024-04-11 15:24:08 +01:00
Jeroen van Rijn 532d477705 Merge pull request #3121 from RilleP/parsing-package-fixes
core:odin parsing fixes
2024-04-11 15:19:10 +02:00
gingerBill 0abbf3ba0a Fix #3412 2024-04-11 13:57:37 +01:00
RilleP 330c161625 remove semicolon 2024-04-11 09:36:28 +02:00
gingerBill 97db075e45 Add #panic to tell of moved package 2024-04-10 20:32:55 +01:00
RilleP 730f992bff fix indentation 2024-04-10 19:16:38 +02:00
RilleP 95a38d5a96 Merge branch 'master' into parsing-package-fixes 2024-04-10 19:10:33 +02:00
gingerBill 13e459980b Fix ptr_to_bit_field.field 2024-04-10 16:18:44 +01:00
gingerBill 3b5e515a22 Fix #3386 - fixed.to_string 2024-04-10 14:35:14 +01:00
gingerBill 3ad95d6be3 Add append_u128 2024-04-10 14:35:00 +01:00
gingerBill abd5fc606c Fix #3407 2024-04-10 14:12:41 +01:00
gingerBill 6678242280 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-04-10 13:40:31 +01:00
gingerBill fd487f66bc Add json:"name,omitempty" 2024-04-10 13:40:25 +01:00
gingerBill d0dc7395e9 Allow for comma-separate json names json:"name,flag" 2024-04-10 13:29:10 +01:00
Jeroen van Rijn 2ba2bc1fec Merge pull request #3288 from Yawning/feature/even-moar-crypto
core/crypto: Even more improvments
2024-04-10 14:19:25 +02:00
gingerBill 97e2d8916a Merge branch 'master' of https://github.com/odin-lang/Odin 2024-04-10 12:32:32 +01:00
gingerBill 3dfd61dd4f Make intrinsics.overflow_* NOT #optional_ok 2024-04-10 12:32:26 +01:00
gingerBill 0f39b9ef22 Merge pull request #3403 from iciuperca/master
Avoid loop index shadowing in vendor:OpenGL
2024-04-10 12:01:08 +01:00
gingerBill af67cc7afe Merge pull request #3397 from wrapperup/add-movefile-flags
Add flags for windows `MoveFileEx`
2024-04-10 12:01:01 +01:00
gingerBill 53558313d8 Merge pull request #3402 from Chickenkeeper/using-param-error-typo-fix
Fix typo in using parameter error message
2024-04-10 11:53:08 +01:00
Jeroen van Rijn 8a6a3e883c Merge pull request #3406 from laytan/bit-field-core-parser
add bit_field to `core:odin`
2024-04-10 03:12:40 +02:00
Laytan Laats af6d2480fa add bit_field parsing to core:odin/parser
Also adds it to the core type thingy like it is in the compiler.
2024-04-10 01:01:32 +02:00
iciuperca c644f79573 Avoid loop index shadowing
The inner loop uses the same index variable name "i" as the parent.

This causes an error message with -vet -strict-style
2024-04-09 18:24:57 +01:00
Chris 219eb58c08 Fix typo in using parameter error message 2024-04-09 12:03:41 +01:00
gingerBill 2207a01494 Merge pull request #3400 from Chickenkeeper/datetime-using-parameter-fix
Remove using parameter from validate_datetime
2024-04-09 12:03:11 +01:00
Chris 60478c0e07 Remove using from validate_datetime 2024-04-09 10:57:51 +01:00
wrapperup 9b496e82f3 add movefile flags 2024-04-09 01:50:16 -04:00
Yawning Angel fa1d681e65 tests/core/crypto: Start adding comprehensive curve25519 tests 2024-04-09 14:37:59 +09:00
Yawning Angel 893c3bef9a core/crypto/ed25519: Initial import 2024-04-09 14:37:59 +09:00
Yawning Angel d96f8bb5c1 core/crypto/ristretto255: Initial import 2024-04-09 14:37:59 +09:00
Yawning Angel 563c527419 core/crypto/_edwards25519: Initial import 2024-04-09 14:37:59 +09:00
Yawning Angel fec42a6d74 core/crypto/_fiat/field_scalar25519: Initial import 2024-04-09 10:23:58 +09:00
Yawning Angel 4defe88dec core/crypto/_fiat/field_poly1305: Mark more functions contextless 2024-04-09 10:23:58 +09:00
Yawning Angel 36f3001d59 core/crypto/_fiat/field_poly1305: Use multiply to calculate the mask 2024-04-09 10:23:58 +09:00
Yawning Angel 1ce279e6a1 core/crypto/_fiat/field_curve25519: Mark more functions contextless 2024-04-09 10:23:58 +09:00
Yawning Angel c951cbdbbc core/crypto/_fiat: odinfmt (NFC) 2024-04-09 10:23:58 +09:00
Yawning Angel 31aba5a728 core/crypto/_fiat/field_poly1305: Move routines (NFC) 2024-04-09 10:23:58 +09:00
Yawning Angel 9a418fd27b core/crypto/_fiat/field_curve25519: Move routines (NFC) 2024-04-09 10:23:58 +09:00
Yawning Angel f9b9521bf0 core/crypto/_fiat/field_curve25519: Use multiply to calculate the mask
Largely for consistency with the generic code, either is valid with Odin
semantics, but this is easier to comprehend.
2024-04-09 10:23:58 +09:00
Yawning Angel b155fdf8c9 core/crypto: Add has_rand_bytes
This allows runtime detection as to if `rand_bytes` is supported or not,
and lets us enable the test-case on all of the supported targets.
2024-04-09 10:23:58 +09:00
Yawning Angel a43a5b053c core/crypto: Add more documentation about assumptions (NFC) 2024-04-09 10:23:58 +09:00
gingerBill a14f0d8f58 Merge pull request #3396 from laytan/fix-nasm-check
fix nasm check
2024-04-09 00:09:13 +01:00
gingerBill 25f781d64b Merge branch 'master' of https://github.com/odin-lang/Odin 2024-04-08 23:58:36 +01:00
gingerBill 9933ca8b56 Make map_total_allocation_size public; Add map_total_allocation_size_from_value 2024-04-08 23:58:30 +01:00
Laytan Laats 9c958ee66d fix nasm check 2024-04-08 20:43:52 +02:00
gingerBill a00d96c0de Merge pull request #3395 from odin-lang/darwin-reorganization
Move `vendor:darwin/Foundation` to `core:sys/darwin/Foundation`
2024-04-08 16:30:44 +01:00
gingerBill ecac3aef32 Change allocator to permanent 2024-04-08 16:18:14 +01:00
gingerBill ec45504631 Obfuscate #line 2024-04-08 16:14:47 +01:00
gingerBill 810cf22e5d Obfuscate #file and #procedure when -obfuscate-source-code-locations is enabled 2024-04-08 16:08:35 +01:00
gingerBill ef82f3e71e Move vendor:darwin/Foundation to core:sys/darwin/Foundation 2024-04-08 13:47:46 +01:00
gingerBill 16dc79fc5c Add "type" field to -json-errors 2024-04-08 13:36:23 +01:00
gingerBill 2aca370a0a Merge pull request #3394 from laytan/wasm-fixes
Wasm fixes
2024-04-08 13:33:29 +01:00
Laytan Laats ce196529dc enable the required target feature atomics when using them in wasm 2024-04-08 13:56:04 +02:00
Laytan Laats 9d8bb7f4e4 fix _end being called before the actual end when using the step function 2024-04-08 13:54:23 +02:00
Laytan Laats 667883b3d5 fix js_wasm time.tick_now, performance.now() returns a float 2024-04-08 13:53:16 +02:00
gingerBill 114ddc4a10 Fix printing error when field name could not be found 2024-04-08 12:06:06 +01:00
gingerBill 0df9c8bffc Improve error messages for people using keywords instead of identifiers 2024-04-08 12:04:33 +01:00
Jeroen van Rijn 0a73ed0799 Merge pull request #3390 from Lperlind/master
Update "core:runtime" to "base:runtime"
2024-04-07 01:09:47 +02:00
Lucas Perlind a71cd07b36 Update "core:runtime" to "base:runtime" 2024-04-07 09:02:01 +10:00
gingerBill 2bb20a2c1c Merge pull request #3388 from laytan/fix-raygui-symbol
fix raygui `GuiFade` being renamed to `GuiSetAlpha`
2024-04-06 22:52:08 +01:00
gingerBill 352d526b94 Merge pull request #3389 from laytan/fix-wasm-atomics
fix wasm atomics
2024-04-06 22:51:58 +01:00
Laytan Laats b150f49c46 fix wasm atomics
Fixes #2745
2024-04-06 23:32:38 +02:00
Laytan Laats d83532d29e fix raygui GuiFade being renamed to GuiSetAlpha 2024-04-06 20:20:16 +02:00
gingerBill 83d3bc74b0 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-04-06 16:59:07 +01:00
gingerBill fbf01543d1 Remove duplicate table 2024-04-06 16:59:02 +01:00
gingerBill 8a98ee800a Merge pull request #3379 from atomicptr/task/add-sdl-sempost
Add missing SDL2_SemPost binding
2024-04-06 16:12:41 +01:00
gingerBill f72e3f689b Merge pull request #3383 from oskarnp/or_return_crash
Fix checker crash when or_return used for non-existing proc
2024-04-06 16:10:09 +01:00
Jeroen van Rijn cd6153a125 Merge pull request #3385 from blob1807/fixed-removed-undefined-var
core:math/fixed Removed undefined & usused vars in init_from_parts
2024-04-06 14:01:25 +02:00
blob1807 fde4e8c905 Removed undefined & usused vars
Removed undefined& usused vars in init_from_parts
2024-04-06 21:49:50 +10:00
oskarnp ca46484ae3 Fix checker crash when or_return/or_break/or_continue used for non-existing proc 2024-04-06 11:02:43 +02:00
Jeroen van Rijn 280adc8a85 Merge pull request #3381 from Yawning/fix/chacha20poly1305
core/crypto/poly1305: The final addition is NOT mod p
2024-04-05 16:57:31 +02:00
Yawning Angel a45721e9ad core/crypto/poly1305: The final addition is NOT mod p 2024-04-05 23:45:41 +09:00
Christopher Kaster 8d399fa7c0 add missing SDL2_SemPost binding 2024-04-05 09:00:57 +02:00
gingerBill 1422e5bc26 Merge pull request #3377 from laytan/fix-amd64-sysv-abi
fix amd64 sysv abi to pass asan everywhere
2024-04-05 00:06:56 +01:00
Laytan Laats 133b45d843 fix amd64 sysv abi to pass asan everywhere
I verified the PR by running the entire test suite of Odin itself with
`-sanitize:address` and also the ols test suite (which caused unique problems
before).

A test has also been added with some problematic code, Windows seems to
have problems with asan in CI or in general so it is not ran there.

The LB_ABI_COMPUTE_RETURN_TYPES block has been removed entirely because
it was unused, I got pretty confused why it didn't effect anything at
first.

Fixes #3211
2024-04-04 23:45:23 +02:00
gingerBill 510574aa7f Merge pull request #3373 from laytan/add-some-windows-wsa-symbols
add some wsa based additions to `core:sys/windows`
2024-04-04 20:40:31 +01:00
gingerBill 3fd3bf2d4d Merge pull request #3371 from mailgerigk/windows-setevent
Add windows.SetEvent
2024-04-04 18:09:21 +01:00
gingerBill fbff2b4fd6 Merge pull request #3372 from laytan/fix-lbarg-ignore-logic
fix lbArg_Ignore logic
2024-04-04 18:09:12 +01:00
gingerBill 7f0ca315b3 Merge pull request #3374 from laytan/fix-128-ints-alignment-arm64
fix 128 bit int alignment on arm64
2024-04-04 18:06:01 +01:00
Laytan Laats 31407d9b1b fix 128 bit int alignment on arm64
Fixes #2403
2024-04-04 18:39:41 +02:00
gingerBill 83e2f5ff74 Add better error messages with suggestions for using context as an identifier 2024-04-04 17:01:31 +01:00
gingerBill 2375ac22a7 Improve error messages for A variable declaration must be an identifier 2024-04-04 16:57:08 +01:00
gingerBill b979fd4c43 Remove consecutive linking libraries 2024-04-04 16:14:05 +01:00
gingerBill 0e5a482c42 Default to "smart" linker behaviour; Add -min-link-libs to use minimize link libs if wanted 2024-04-04 16:11:26 +01:00
Laytan Laats 1af84e082c add some wsa based additions to core:sys/windows 2024-04-04 17:09:12 +02:00
gingerBill d248cddf90 Remove dead newline 2024-04-04 16:07:55 +01:00
Laytan Laats a7056f2b4f fix lbArg_Ignore logic
Fixes #2698
2024-04-04 16:58:22 +02:00
gerigk 62cebe1bc9 Add windows.SetEvent 2024-04-04 16:00:01 +02:00
gingerBill 99aff7e3fb Merge pull request #3370 from laytan/fix-objc-proc-group-edge-case
fix objc proc group edge case
2024-04-04 13:03:27 +01:00
Laytan Laats 5339e1e1b6 fix objc proc group edge case
Fixes #2648
2024-04-03 21:21:46 +02:00
gingerBill 5fe0788cff Minimize code duplication in core:mem by using the base:runtime calls 2024-04-03 11:47:39 +01:00
gingerBill e42b16b106 Merge pull request #3366 from laytan/fix-vet-scope-bug
fix vet scope bug skipping some scopes
2024-04-03 11:40:01 +01:00
gingerBill a1d9442380 Merge pull request #3367 from laytan/fix-stack-overflow-warning
fix -vet warning for stack overflows not showing up
2024-04-03 11:39:25 +01:00
Laytan Laats b754c1e072 fix -vet warning for stack overflows not showing up
Due to the placement of this code, the warning would only ever be added
if the variable was also either unused or shadowed.
2024-04-03 01:05:54 +02:00
Laytan Laats 3a0df80066 correct newly found vets 2024-04-03 00:52:58 +02:00
gingerBill a9bfb3ac2e Clarity warning and error printing 2024-04-02 23:39:14 +01:00
gingerBill 692a47f080 Fix printing of warnings 2024-04-02 23:36:36 +01:00
Laytan Laats 21fcf7c874 fix vet scope bug skipping some scopes
Fixes #3146
2024-04-02 23:59:38 +02:00
gingerBill 05d07983c3 Merge pull request #3363 from laytan/fix-c-varargs-named-args
fix named arguments and untyped nil with #c_vararg
2024-04-02 18:36:10 +01:00
Laytan Laats fc30bde0f6 fix untyped nil into c varargs
Fixes #2842
2024-04-02 18:49:35 +02:00
Laytan Laats a8d8696e2f fix named arguments with #c_vararg
Previously `args=1`, `args={}`, `args={1, 2, 3}` would all crash the
compiler. Now it passes them correctly, and if given a compound literal,
the values are expanded into the call so you can use a named arg while
passing multiple values.

Fixes #3168
2024-04-02 17:25:11 +02:00
gingerBill 66f9ef9a00 Merge pull request #3361 from yay/ns-application-activate
Add NSApplication.activate to Foundation bindings.
2024-04-02 06:59:13 +01:00
Vitalii Kravchenko fdd4ef3c59 Add NSApplication.active to Foundation bindings. 2024-04-02 02:35:00 +01:00
Jeroen van Rijn f9f6fbfe1f Merge pull request #3360 from laytan/debug-info-fixes
fix wrong type in map debug info
2024-04-01 19:12:24 +02:00
Laytan Laats 4fc96e1ca5 change unneeded permanent allocation to temporary 2024-04-01 19:06:05 +02:00
Laytan Laats cfc85fd737 fix wrong type in map debug info 2024-04-01 18:42:10 +02:00
Jeroen van Rijn 6b7e9f0a2d Merge pull request #3359 from Kelimion/tests_digests
Add SHA3-512 digests verification to test assets.
2024-04-01 18:24:36 +02:00
Jeroen van Rijn b3580fa63a Make it a HMAC. 2024-04-01 18:20:14 +02:00
gingerBill 406aa587e2 Merge pull request #3358 from laytan/debug-info-fixes
debug info fixes/refactor
2024-04-01 16:53:56 +01:00
Jeroen van Rijn b2f432c223 Add SHA3-512 digests verification to test assets. 2024-04-01 17:18:31 +02:00
Laytan Laats 7c2352ea08 remove soa handling in debug info, fields are already added in checker 2024-04-01 16:51:16 +02:00
Laytan Laats 9647cb74ad debug info fixes/refactor
This fixes (on my end) #3340, #3117, #2945, #2922, and #2762

A general refactor of debug info generation in order to fix issues and
increase stability.

What I believe is the root cause of a bunch of issues is that we use the
temporary metadata/forward declarations too much (/ hold onto them for
too long). It seems to cause problems with the reference counting inside
LLVM.

This PR reduces the use of these forward declarations to a minimum, it
creates it, fills in the fields, and resolves it, instead of waiting
until the end of generating code.

Some smaller issues I came across have also been solved.
2024-04-01 16:28:44 +02:00
gingerBill bb72ff9c35 Fix nested ERROR_BLOCK bug 2024-04-01 14:28:11 +01:00
gingerBill 397c2aa201 Merge pull request #3318 from flysand7/os2-file-pipe-read
[core/os2]: Fix read_entire_file for reads from pipe and console.
2024-04-01 13:38:10 +01:00
gingerBill b47d73c651 Fix type checking for invalid enum backing type 2024-04-01 13:34:30 +01:00
flysand7 3ee9184537 [core/os2]: Fix memory leak on read_entire_file 2024-04-01 23:32:16 +11:00
gingerBill 2938def707 Remove dead comment 2024-04-01 13:27:51 +01:00
gingerBill 84686c70c5 Error message when RTTI is disabled when iterating over an enum type or a bit_set of enum with for in 2024-04-01 13:16:49 +01:00
gingerBill 3fa02427b3 Unify error message logic for ranges over bit_set 2024-04-01 13:12:09 +01:00
gingerBill b862691d75 Support for in with bit_set 2024-04-01 13:08:07 +01:00
gingerBill f482cc8374 Fix error message 2024-04-01 12:33:56 +01:00
gingerBill 030b8d3f66 Merge pull request #3354 from serberoth/issue-3349
Patch for #3349 to address API concerns for Darwin platform in core:os
2024-04-01 12:25:17 +01:00
Jeroen van Rijn 0d8dadb084 Merge pull request #3357 from DragosPopse/win32-coinit-fix
Fixed windows.COINIT.MULTITHREADED declaration.
2024-03-31 20:41:13 +02:00
Dragos Popescu d0674cb70f Fixed windows.COINIT.MULTITHREADED declaration. It's supposed to be 0 rather than 3 2024-03-31 21:29:49 +03:00
nicola 3975b5e736 :Updated core:os for darwin to include flush function and match close to api documentation returning errno 2024-03-30 16:48:52 -04:00
gingerBill 2bdf5f58ef Enforce error on old style for/switch l-value 2024-03-30 14:23:47 +00:00
gingerBill 8e1a2094a7 Fix debug info for map 2024-03-30 13:46:23 +00:00
gingerBill 9271372fef Fix #field_align issues, by simplifying the LLVM struct type generation 2024-03-30 13:06:51 +00:00
gingerBill 4edcaa6124 Try storing a pointer to a fake metadata type in the debug info for a map 2024-03-30 10:29:20 +00:00
gingerBill d84d65ba45 Merge pull request #3348 from rick-masters/fix_convert_smaller_float_endian
Implement endian conversions for smaller float types.
2024-03-29 22:13:58 +00:00
gingerBill 28fb1ba83d Merge pull request #3350 from laytan/fix-gb.h-for-fsanitize-address
fix gb.h to be able to use -fsanitize=address
2024-03-29 22:13:32 +00:00
gingerBill db95ed7cdd Merge pull request #3353 from laytan/fix-incomplete-types-resize-segfault
fix a segfault when incomplete types array resizes while processing
2024-03-29 22:13:01 +00:00
Laytan Laats e6a552e0ce fix gb.h to be able to use -fsanitize=address 2024-03-29 22:51:58 +01:00
Laytan Laats 915f63b3f9 fix a segfault when incomplete types array resizes while processing 2024-03-29 22:42:12 +01:00
rick-masters e1b545860f Implement endian conversions for smaller float types. 2024-03-29 11:05:27 +00:00
Jeroen van Rijn 8899f42478 Merge pull request #3347 from harold-b/macos-timing-fix
Fix incorrect timings on macOS
2024-03-29 10:15:16 +01:00
Harold Brenes 13b8a5b73d Reverting to calculated frequency timings method on macOS, but fixed 2024-03-29 05:04:40 -04:00
Harold Brenes b84a660806 Fix incorrect timings on macOS 2024-03-28 21:09:37 -04:00
Jeroen van Rijn d325c8ad23 Merge pull request #3346 from laytan/add-macos-14.4.1
add MacOS 14.4.1 to sys/info and odin report
2024-03-28 19:43:57 +01:00
Laytan Laats b7fd51a251 add MacOS 14.4.1 to sys/info and odin report 2024-03-28 19:39:18 +01:00
Jeroen van Rijn 7325120ca9 Merge pull request #3345 from laytan/speed-up-path-to-fullpath
fix not setting ok in cached code path
2024-03-28 19:27:31 +01:00
Laytan Laats 9a5a39c07d fix not setting ok in cached code path 2024-03-28 19:16:55 +01:00
Jeroen van Rijn 9b43aa3c94 Merge pull request #3344 from laytan/speed-up-path-to-fullpath
compiler: speed up path_to_fullpath on Linux/MacOS
2024-03-28 19:02:39 +01:00
Laytan Laats 63f30a8207 speed up path_to_fullpath on Linux/MacOS
We did some profiling for #3343 and this seems to be the biggest
problem. `realpath` is expensive, and we are locking here for no reason
that I can think of.

This improves the "check procedure bodies" timing (of the linked issue)
from 2.4s to .4s on my machine.
2024-03-28 18:44:21 +01:00
gingerBill 308e9112f2 Disable packing on ARM64 and AMD64 2024-03-28 10:58:40 +00:00
gingerBill 58d0635f48 Merge pull request #3342 from FrancisTheCat/master
Json: Improved unmarshalling of `using _: T` fields
2024-03-27 18:57:34 +00:00
FrancisTheCat 2ccb326a41 Merge branch 'odin-lang:master' into master 2024-03-27 17:52:29 +01:00
gingerBill cf9bdc134c Fix #3341 2024-03-27 16:48:51 +00:00
FrancisTheCat 29e4e85152 Merge branch 'odin-lang:master' into master 2024-03-27 16:43:02 +01:00
Franz Höltermann a422aba578 Json: improved unmarshalling of using _: T fields.
`using _: T` fields will now have their members unmarshalled to their
parent types reflecting the new behaviour of json.marshall.

Example:
```go
A :: struct {
    using _: B,
}

B :: struct {
    field: string,
}

data := `{"field": "Hello World"}`

a: A
json.unmarshal_string(data, &a)
```
2024-03-27 15:46:44 +01:00
gingerBill 7b387fd3aa Improve C-like syntax mistakes error messages 2024-03-27 13:10:46 +00:00
gingerBill 12ec9bce7d Fix parsing bug on bit_set[;x] 2024-03-27 13:05:15 +00:00
gingerBill b378eb2df3 Fix free bug not using the correct allocator 2024-03-27 12:54:52 +00:00
gingerBill 6422c090f2 Make hash procedures contextless where possible 2024-03-27 12:54:37 +00:00
gingerBill 3bc7c51325 Merge pull request #3283 from laytan/darwin-new-wait-on-address-api
darwin: use new wait on address API if possible
2024-03-27 11:20:32 +00:00
gingerBill f57cc6beb1 Merge pull request #3331 from laytan/darwin-fix-entrypoint-warning-dylibs
darwin: fix linker warning when building dynamic library
2024-03-27 11:19:11 +00:00
gingerBill 2031d2769a Merge branch 'master' of https://github.com/odin-lang/Odin 2024-03-27 00:58:35 +00:00
gingerBill 83c9739a7d Update year 2024-03-27 00:58:21 +00:00
gingerBill d9ba698b7b Merge pull request #3337 from FrancisTheCat/master
Json: Improve marshalling of `using _: T` fields
2024-03-27 00:57:03 +00:00
Arseniy Poroshin 77a0e50298 fix comments in core:container/queue. 2024-03-26 22:39:43 +00:00
Laytan Laats 19d566ebc5 darwin: fix linker warning when building dynamic library
Trying to fix all linker warnings that macOS comes up with, when
building a dynamic library it currently emits `ld: warning: ignoring -e, not used for output type`
2024-03-26 21:00:14 +01:00
Franz Höltermann 92a5666c1c Json: fields on structs like 'using _: T' will now have T's fields
marshalled directly into the parent type without an '"_":{ ... }'.
This seems like desirable behavior to me, since you can't access the
fields with 'Parent_Type._.field' either.
2024-03-26 20:22:51 +01:00
gingerBill 63d6b4752b Fix type info layout for wasm64p32 targets 2024-03-26 17:16:12 +00:00
gingerBill 6588fe35b3 Fix wasm abi 2024-03-26 16:47:29 +00:00
gingerBill fa84272d5e Merge pull request #3335 from rick-masters/fix_incomplete_struct_type
Don't add type info for incomplete structs.
2024-03-26 16:08:12 +00:00
rick-masters c90a6ab0d5 Remove accidentally added test binary. 2024-03-26 15:08:32 +00:00
gingerBill 0989eac681 Add extra sanity check for nullptr 2024-03-26 14:57:06 +00:00
rick-masters b8c0a02164 Don't add type info for incomplete structs. 2024-03-26 14:34:56 +00:00
gingerBill df526549e2 Fix min/max for wasm 2024-03-26 14:31:28 +00:00
gingerBill 1009182f7b Fix another #soa race condition bug 2024-03-26 14:13:55 +00:00
gingerBill 620dd2c812 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-03-26 13:06:46 +00:00
gingerBill 533ba63c82 Fix #3327 #3204 #3200 2024-03-26 13:06:39 +00:00
gingerBill 2165303f5e Merge pull request #3332 from laytan/darwin-be-less-annoying-about-library-versions
darwin: be less annoying about "incompatible" library versions
2024-03-26 11:16:25 +00:00
gingerBill c59f6d548b Merge pull request #3333 from blob1807/change-time-sleep-doc
time.accurate_sleep Windows Doc update
2024-03-26 11:15:55 +00:00
blob1807 8eed65ad4c Update time.odin 2024-03-26 11:20:05 +10:00
blob1807 bc0a2b8d39 Update time.odin 2024-03-26 11:17:44 +10:00
blob1807 a405c72d4d Updated windows time period call
Updated win32.time_begin_period to windows.timeBeginPeriod
Added a note about calling windows.timeEndPeriod once you don't need accurate_sleep, as per MS's docs https://learn.microsoft.com/en-us/windows/win32/api/timeapi/nf-timeapi-timebeginperiod#remarks
2024-03-26 11:13:27 +10:00
Laytan Laats b26a685b76 darwin: be less annoying about "incompatible" library versions
After #3316 we set a default minimum version, now this will warn if you
link with a library that is targeting later versions.

This might be a bit annoying, especially when the user hasn't actually
given Odin a minimum target.

So this PR makes these warnings only show when you explicitly give a
target version (afaik that is the only thing that -mmacosx-min-version
actually does for us because we don't use it to compile anything, just
to link).
2024-03-25 22:11:20 +01:00
gingerBill 3a8971c260 Merge pull request #3330 from laytan/remove-mistaken-dll
remove mistakenly added dll
2024-03-25 17:14:36 +00:00
Laytan Laats ed742efc33 remove mistakenly added dll
Just noticed I oopsied the glfw dll into the repo
2024-03-25 18:11:41 +01:00
gingerBill 06ee9117d2 Merge pull request #3124 from laytan/update-releases-llvm-version
update LLVM to 17 for CI/releases
2024-03-25 16:36:38 +00:00
gingerBill e100d9264f Merge pull request #3329 from laytan/fix-darwin_amd64-f16-emulation-on-older-microarches
darwin: fix amd64 f16 emulation
2024-03-25 16:35:57 +00:00
gingerBill 53b02c5e6f Fix printing errors issue 2024-03-25 14:46:45 +00:00
gingerBill 50618759a6 Fix error reporting for type cycles 2024-03-25 13:44:00 +00:00
gingerBill 600ca83386 Merge pull request #3326 from rick-masters/fix_fields_wait_signal
Fix fields_wait_signal futex.
2024-03-25 13:29:08 +00:00
gingerBill e5629dafd0 Potentially fix a race condition with parapoly types (related to #3328) 2024-03-25 13:23:43 +00:00
Laytan Laats a2167587ae Merge branch 'fix-darwin_amd64-f16-emulation-on-older-microarches' of github.com:laytan/Odin into update-releases-llvm-version 2024-03-25 14:15:18 +01:00
Laytan Laats b2a35683a4 darwin: fix amd64 f16 emulation
Fixes #3222
2024-03-25 14:07:49 +01:00
Laytan Laats dcc263c618 re-enable core tests on macos arm 2024-03-25 14:05:07 +01:00
Laytan Laats 3b34cf6dbb Also update to LLVM 17 for general CI 2024-03-25 14:05:07 +01:00
Laytan ae9f026f4b llvm 17 on macos arm releases 2024-03-25 14:05:07 +01:00
Laytan Laats 46093bad1e update LLVM to 17 for releases 2024-03-25 14:05:07 +01:00
flysand7 c843002d07 [core/os2]: Move .Broken_Pipe to General_Error enum 2024-03-25 23:35:01 +11:00
rick-masters 6d4f30de1a Fix fields_wait_signal futex. 2024-03-24 16:28:55 +00:00
gingerBill 68ff945419 Remove old error message for #3062 2024-03-24 14:39:42 +00:00
gingerBill cab53e12b7 Add assert message to tell me people to report the bug 2024-03-24 13:53:09 +00:00
gingerBill d92767cb77 Fix #3226 2024-03-24 13:49:51 +00:00
gingerBill 670fc70f1f Remove private attributes for #3227 2024-03-24 13:46:26 +00:00
gingerBill 223a336eb4 Fix #3249 2024-03-24 13:45:10 +00:00
gingerBill 1ea1229516 Fix #3319 2024-03-24 13:42:37 +00:00
gingerBill 6da6393735 Fix #3320 2024-03-24 13:40:10 +00:00
gingerBill 87688936c6 Improve error messages for some wrong constant value attributes 2024-03-24 13:36:50 +00:00
gingerBill 590e52cc05 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-03-24 13:33:37 +00:00
gingerBill 398af659e5 Fix #3323 2024-03-24 13:33:30 +00:00
gingerBill 2e416c1a48 Merge pull request #3316 from laytan/fix-ld-warnings-and-set-default-minimum-version
darwin: fix ld warnings and set minimum os version
2024-03-24 13:26:35 +00:00
gingerBill 34247b2658 Fix resize bug caused by typo 2024-03-24 12:24:44 +00:00
gingerBill 45d7dd8f27 Fix resize zeroing behaviour 2024-03-24 12:20:39 +00:00
gingerBill 09d7f1337b Merge pull request #3317 from laytan/arm64-abi-fixes
darwin: arm64 abi fixes
2024-03-24 00:41:52 +00:00
flysand7 0f944bc0a1 [core/os2]: Reading from unsized files 2024-03-24 10:52:48 +11:00
Laytan Laats 07a9969a41 darwin: arm64 abi fixes
Since commit b4fe9677a1 some core tests
segfault during build, upon investigation it is because some arg types
were of size 0 and you can't have a 0 sized int.

It also applies the earlier fix for parameters to the return types, this
fixes #3223

Thought I would put this PR up, but I am in no way an expert in abi so
feel free to close for a better fix if there is one.

I am able to run the entire core test suite with `-sanitize:address`
with these changes.
2024-03-23 23:17:01 +01:00
Laytan Laats 15c1e8274d darwin: fix ld warnings and set minimum os version 2024-03-23 22:12:05 +01:00
gingerBill 517d7ae0b0 Add error block around error_line calls 2024-03-23 17:51:56 +00:00
gingerBill efb0933965 Improve error suggestion and propagation for x->y 2024-03-23 16:57:35 +00:00
gingerBill eb51cc6835 Improve error propagation for (*x).y style errors from C-programmers 2024-03-23 16:53:40 +00:00
gingerBill 1d46adb598 Treat *x as an unary operator to improve error messages for common C-programmer mistakes 2024-03-23 16:51:04 +00:00
gingerBill 61aa4558dc Fix #3314 2024-03-23 16:41:50 +00:00
gingerBill 194d3fe6bd Ignore wrong types 2024-03-23 14:59:35 +00:00
gingerBill 624b870f28 Add some basic escape analysis errors for return &x 2024-03-23 14:58:10 +00:00
gingerBill eb61cf6043 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-03-23 12:56:09 +00:00
gingerBill 7abb459861 Add missing field flags in debug printing 2024-03-23 12:56:04 +00:00
gingerBill e9ac7d5fab Merge pull request #3311 from laytan/fix-simd128-wasm
fix wasm with `-target-features:"simd128"`
2024-03-23 10:42:36 +00:00
Laytan Laats bb5dab342a fix wasm with -target-features:"simd128"
the required procs within wasm would compile to take native v128
arguments in, but the procs are supposed to take in i64's causing bad wasm
modules.

Fixes #3263
2024-03-22 17:04:15 +01:00
gingerBill 7d6e9ef39c Merge branch 'master' of https://github.com/odin-lang/Odin 2024-03-21 20:44:00 +00:00
gingerBill d47ba09743 Fix at error printing bug 2024-03-21 20:43:52 +00:00
gingerBill 5c9da66595 Merge pull request #3294 from laytan/update-glfw-from-3.3.8-to-3.4
glfw: update from 3.3.8 to 3.4
2024-03-21 15:43:25 +00:00
gingerBill 9cbb9d8551 Merge pull request #3304 from mailgerigk/master
Remove entry point when compiled with no-entry-point as shared library
2024-03-21 15:19:38 +00:00
gingerBill 6b6f72e7bd Fix #3305 2024-03-21 14:59:47 +00:00
gingerBill c8cdb22f0b Disallow for x in y.(T) and for x in y.? 2024-03-21 14:42:48 +00:00
gingerBill 6e2efce670 Fix missing ERROR_BLOCK(); calls 2024-03-21 12:05:15 +00:00
gingerBill 6d7afd3fa9 Update format version 2024-03-21 11:59:45 +00:00
gingerBill 006ea11c56 Update doc-format for #by_ptr and #no_broadcast parameters 2024-03-21 11:58:32 +00:00
gingerBill 010ffc486c Minor clean up of #no_broadcast handling 2024-03-21 11:54:40 +00:00
gingerBill 29e5f94c2a Add #no_broadcast procedure parameter to disallow automatic array programming broadcasting on procedure arguments 2024-03-21 11:52:48 +00:00
mailgerigk 6a0d2ffcac Merge branch 'odin-lang:master' into master 2024-03-21 00:26:42 +01:00
gingerBill fc587c507a Merge branch 'master' of https://github.com/odin-lang/Odin 2024-03-20 22:44:43 +00:00
gingerBill 65cb382135 Fix error handling for type switch statement 2024-03-20 22:44:35 +00:00
Jeroen van Rijn 8f0d74c08d Merge pull request #3292 from Kelimion/rfc3339
Add WiP datetime package and tests.
2024-03-20 23:23:27 +01:00
gerigk 800014e40c Remove entry point when compiled with no-entry-point as shared library 2024-03-20 23:18:08 +01:00
Jeroen van Rijn fda283c55e More better validation. 2024-03-20 23:09:09 +01:00
gingerBill f39b34a8b7 Fix error message 2024-03-20 18:17:06 +00:00
gingerBill 1cc5e23801 Fix #3299 2024-03-20 18:16:46 +00:00
gingerBill 8e0806be2d Fix #3301 2024-03-20 18:09:57 +00:00
gingerBill c17adc98f5 Try doing <{i64, i32}> instead of [i64, i64] for ARM64 12-byte parameters 2024-03-20 17:39:00 +00:00
gingerBill d381b77164 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-03-20 17:27:12 +00:00
gingerBill e804fbd891 Force packed structs in ABI parameters 2024-03-20 17:27:05 +00:00
Jeroen van Rijn ed5fd15f6e Ensmallen Date struct. 2024-03-20 18:13:29 +01:00
Jeroen van Rijn 89ca15014c Ensmallen Time struct. 2024-03-20 18:09:07 +01:00
gingerBill a5efcfdd78 Merge pull request #3303 from laytan/allow-darwin-cross-arch-linking
darwin: allow cross linking darwin_amd64 from darwin_arm64
2024-03-20 16:56:24 +00:00
Jeroen van Rijn 9c144dd24f Change Ordinal from int to i64 2024-03-20 17:56:22 +01:00
gingerBill c0f9e8d6a3 Merge pull request #3302 from laytan/missing-cmark-api
commonmark: add missing on_exit api
2024-03-20 16:56:11 +00:00
Laytan Laats f312adb26a darwin: allow cross linking darwin_amd64 from darwin_arm64 2024-03-20 17:44:35 +01:00
Laytan Laats 9c879e5e17 commonmark: add missing on_exit api 2024-03-20 17:42:20 +01:00
gingerBill b4fe9677a1 Change ARM64 ABI for integer-like parameters 2024-03-20 16:06:50 +00:00
gingerBill 1951bc45a6 Fix #3133 by show the line of the syntax error 2024-03-20 13:55:47 +00:00
gingerBill ba77a9464c Add suggestion for x: ^T; y = x to be x^ 2024-03-20 13:36:14 +00:00
gingerBill b1dae2d59a Add x: T; y: ^T = x suggestion to do &x 2024-03-20 13:28:17 +00:00
gingerBill 1514d64964 Update ARM64 ABI return type 2024-03-20 11:12:43 +00:00
gingerBill e4c502e79b Add offset (in bytes) field to -json-errors 2024-03-20 11:06:02 +00:00
gingerBill 553a244fec Fix bounds checking 2024-03-20 10:24:39 +00:00
gingerBill 3bff922b6f m[i] on #row_major matrices will reduce the i-th row-vector 2024-03-20 10:23:57 +00:00
gingerBill 56004c56fc Merge pull request #3295 from kavalee/parser-newline-fix
Fixed issue #3264 regarding `core:odin/parser` compound literal not allowing a newline
2024-03-20 10:09:55 +00:00
gingerBill 863ee0b8d1 Merge pull request #3297 from laytan/linker-improvements
linker improvements
2024-03-20 10:09:45 +00:00
Jeroen van Rijn 89ba8b4139 Merge pull request #3298 from laytan/update-macos-releases
update macOS releases for `core:sys/info` and `odin report`
2024-03-20 00:23:53 +01:00
Laytan Laats d0b3b18e26 update macOS releases for core:sys/info and odin report 2024-03-20 00:14:01 +01:00
gingerBill cd7137af60 Update raylib to use #row_major matrices 2024-03-19 21:16:04 +00:00
gingerBill 18fb665bf6 Correct matrix builtins for #row_major 2024-03-19 21:15:47 +00:00
gingerBill a750fc0ba6 Add #row_major matrix[R, C]T
As well as `#column_major matrix[R, C]T` as an alias for just `matrix[R, C]T`.
This is because some libraries require a row_major internal layout but still want to be used with row or major oriented vectors.
2024-03-19 21:05:23 +00:00
Laytan Laats a555862522 linker improvements
`path_to_fullpath` did different things on Windows&Unix, an attempt to
bring them closer together was made here.
This was prompted by the compiler completely ignoring
`foreign import "foo.dylib"` when `foo.dylib` does not exist (because
`path_to_fullpath` returns an empty string).
Causing just unresolved symbol errors, when on Windows it would pass
along the path to the linker and actually say it doesn't exist, which
is now also the case for Unix.
This also fixes some checker errors that relied on the Windows
behaviour, for example: `Error: File name, , cannot be as a library name
as it is not a valid identifier`.

Made `-no-crt` require either `-default-to-nil-allocator` or
`-default-to-panic-allocator` on Unix, the current default allocators
rely on libc and this was not obvious and would immediately bring up
unresolved symbol errors for the linked memory management functions, or
just link with libc anyways because it was foreign imported.

Added a suggestion to install `nasm` with the user's package manager
when assembling using `nasm` fails on Unix, I saw some confusion about
it in the Discord.

Ignore explicit foreign imports of libc. It is already linked in later
on in the linking process and would otherwise (at least on macOS) cause
linker warnings for duplicate libraries. This also makes it so when
using `-no-crt` and importing something that requires libc, linker
errors are given (like I would expect), instead of silently still
linking with libc because it was foreign imported.
2024-03-19 19:57:35 +01:00
gingerBill 433109ff52 Replace gb_exit(1) with exit_with_errors() where appropriate 2024-03-19 16:29:45 +00:00
gingerBill ba428fecdb Add -json-errors 2024-03-19 16:25:09 +00:00
gingerBill 17cc7a2c5e General clean-up for error.cpp 2024-03-19 15:42:59 +00:00
gingerBill 9a2fc6cf4c Serialize errors to make them sortable, deterministic, and generally more control 2024-03-19 15:34:29 +00:00
gingerBill 8ff788f4ff Add better suggestion for [?]T mistake 2024-03-19 13:38:13 +00:00
gingerBill 80ecf5b68a On x: [?]T = {...}, minimize errors by using the [?]T expression as a kind of hint 2024-03-19 13:32:37 +00:00
gingerBill 5159f30c9c Fix error block handling 2024-03-19 13:10:35 +00:00
gingerBill d5daa9fda5 Minimize error propagation of bad array syntax by treating this like a type 2024-03-19 13:05:28 +00:00
gingerBill 89315986d4 Add suggestion when mistyping an array backwards e.g. T[] 2024-03-19 12:37:11 +00:00
Aaron Kavaler 096b4f5454 fixed issue #3264 regarding core:odin/parser not allowing a newline at the end of a compound literal 2024-03-18 20:33:02 -07:00
Laytan Laats 65e68f11f8 glfw: update from 3.3.8 to 3.4 2024-03-18 23:54:26 +01:00
gingerBill ec9ac59323 Unify "Did you mean" strings 2024-03-18 21:37:40 +00:00
gingerBill 97be7feb99 Add list of C identifier suggestions (types and keywords) 2024-03-18 17:32:26 +00:00
gingerBill 00344e1323 Add check to people trying to foreign import C files. 2024-03-18 16:56:01 +00:00
Laytan Laats dd92d3054d add ODIN_ prefix to the new constant 2024-03-18 17:22:58 +01:00
Jeroen van Rijn 07ef969546 Fix test label. 2024-03-18 17:05:40 +01:00
Jeroen van Rijn 72c15d7699 Add WiP datetime package and tests.
A new package `core:time/datetime` has been added which can represent moments much further in the past and future than `core:time`.
It is based on *the* reference work on the subject, Calendrical Calculations Ultimate Edition, Reingold & Dershowitz.

More procedures will be added to it in the future, to for example calculate the 3rd Thursday in March to figure out holidays.
The package has been tested for more than a year and can handle dates 25 quadrillion years into the past and future with 64-bit day ordinals, or 5 million with 32-bit ones.

This also fixes a longstanding bug where converting between YYYY-MM:DD hh:mm:ss and `time.Time` and back could result in a mismatch.

RFC 3339 timestamps can now also be parsed using the `core:time` package.
2024-03-18 16:47:16 +01:00
gingerBill 009b6f44e3 Add loads of checks for common mistakes for C programmer 2024-03-18 15:18:10 +00:00
gingerBill ebd3065aa2 Add error message for C programmers which do Foo{.x = 123} rather than Foo{x = 123} 2024-03-18 14:17:13 +00:00
gingerBill 6cb74b63ec Fix #3286 2024-03-18 12:39:34 +00:00
gingerBill effc71ca43 Fix case: bug with by-ref unions 2024-03-18 12:20:53 +00:00
gingerBill 43d695a990 Fix for x in y where y is an "optional ok" value, but ignores #optional_allocator_error values 2024-03-18 11:21:06 +00:00
gingerBill 19eb2a8890 Fix #3282 2024-03-16 22:24:34 +00:00
gingerBill 3875fb08e8 Fix #3284 2024-03-16 22:12:17 +00:00
Laytan Laats 9c455b2213 darwin: use new wait on address API if possible 2024-03-15 21:43:16 +01:00
gingerBill 04f0fbf23a Merge pull request #3272 from iansimonson/add_getrusage_darwin
Add getrusage syscall for mac/darwin
2024-03-14 19:45:25 +00:00
gingerBill 51d6a254cf Merge pull request #3277 from kavalee/slice-unique-fixes
fixed slice.unique and slice.unique_proc
2024-03-14 19:40:18 +00:00
Ian Simonson 835effdef1 Use c.long rather than int 2024-03-14 09:36:57 -07:00
Ian Simonson c7bec2962e Fix __darwin_suseconds_t definition
__darwin_suseconds_t is defined as long which on macos
64 bit systems is equivalent to 8 bytes. It is equivalent
to Odin int type _not_ i32
2024-03-14 07:21:26 -07:00
Aaron Kavaler ac634acd4b fixed slice.unique and slice.unique_proc 2024-03-13 19:19:31 -07:00
Ian Simonson 34c4389d75 No need for timeval definition
It already existed so lets just use that rather than
redeclaring it
2024-03-13 14:58:56 -07:00
Ian Simonson 8917a7ef88 Make RUsage more inline with macos man page
Swap to tabs to adhere to the Odin Core library standard
and also rename the rusage fields to match the actual
definitions from the macos bsd man pages
2024-03-13 14:51:17 -07:00
gingerBill 45d5066029 Merge pull request #3274 from iansimonson/darwin_munmap_syscall_fix
Fix syscall_munmap in darwin
2024-03-13 20:17:31 +00:00
gingerBill b47eeac414 Merge pull request #3275 from Chickenkeeper/bit-set-error-message-fix
Improve bit_set error message
2024-03-13 20:17:06 +00:00
Chris 5cc936245c Improve bit_set error message 2024-03-13 19:50:41 +00:00
gingerBill e68d3c8bbc Merge pull request #3143 from Pariatech/cgltf-linux-build
Adding linux & darwin makefile for cgltf
2024-03-13 17:47:18 +00:00
Ian Simonson d7b1901b16 Fix syscall_munmap in darwin
this was using the .mmap syscall number when it should be
using the .munmap syscall number
2024-03-13 10:39:50 -07:00
gingerBill 97d6bf6d8f Merge branch 'master' of https://github.com/odin-lang/Odin 2024-03-13 16:30:28 +00:00
gingerBill 271f84ab5b Expect stream as a field directly on os2.File 2024-03-13 16:30:22 +00:00
gingerBill 75b60fdb12 Merge pull request #3273 from Chickenkeeper/mutex-allocator-fix
Make Mutex_Allocator use Ada_Case
2024-03-13 15:45:52 +00:00
Chris 55141bdbb1 Make Mutex_Allocator use Ada_Case 2024-03-13 15:29:02 +00:00
gingerBill 5f2496226f Change return to panic 2024-03-13 15:17:21 +00:00
gingerBill dee66b8451 Fix typo due to deletion 2024-03-13 15:14:31 +00:00
gingerBill 4aec2de7bd Merge branch 'master' of https://github.com/odin-lang/Odin 2024-03-13 15:12:19 +00:00
gingerBill ac10f504e4 Add infinite loop check and early out in map_insert_hash_dynamic 2024-03-13 15:12:14 +00:00
Ian Simonson 26d107ce64 Add getrusage syscall for mac/darwin
The syscall number existed but the wrapper for calling it
did not. Also adds the RUsage struct to receive the data.

Naming is kept the same as in sys/linux
2024-03-13 08:07:12 -07:00
gingerBill d62c92f5a9 Merge pull request #3267 from harold-b/copy-dirent-path
Retain copies of `dirent->name` for .odin files when using `read_directory`
2024-03-13 12:23:28 +00:00
gingerBill 5c1646a6b3 Merge pull request #3271 from rick-masters/too_many_poly_args
Fix check for too many arguments to a polymorphic record type
2024-03-13 12:23:19 +00:00
Pariatech b539bb2693 Update vendor/cgltf/src/Makefile
missing darwin folder

Co-authored-by: Laytan <laytanlaats@hotmail.com>
2024-03-13 07:37:42 -04:00
rick-masters 7bc962b852 Fix variable used to index polymorphic parameter. 2024-03-12 23:58:20 +00:00
rick-masters f7ec628cb2 Fix check for too many arguments to a polymorphic record type. 2024-03-12 23:57:13 +00:00
Jeroen van Rijn 23f3898b4e Merge pull request #3270 from edyu/master
Expose internal invmod and int_exponent_mod with more consistent naming
2024-03-12 19:06:10 +01:00
Ed Yu dd74a57c44 Expose internal invmod and int_exponent_mod with more consistent naming 2024-03-12 11:01:09 -07:00
olesya-wo 51a4d97f03 type conversion fix 2024-03-12 18:25:54 +03:00
olesya-wo d979129a50 Naming and type changes 2024-03-12 16:32:17 +03:00
gingerBill d6353daf91 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-03-12 12:11:53 +00:00
gingerBill c7c6852057 Support swizzle selector syntax .xyzw for #simd vectors 2024-03-12 12:11:48 +00:00
olesya-wo 9045c9ed0c Improved statistics for core/mem/Tracking_Allocator 2024-03-12 13:53:31 +03:00
Harold Brenes b543be0d15 Copy file names fromdirent into FileInfo during read_directory 2024-03-11 18:09:41 -04:00
gingerBill 47837b206e Merge pull request #3266 from nnym/master
Use a POSIX-compliant equality operator in `build_odin.sh`.
2024-03-11 13:00:01 +00:00
gingerBill 9a41a450e7 Add builtin map_upsert 2024-03-11 12:30:24 +00:00
Muhammad f20d0202fa Use a POSIX-compliant equality operator. 2024-03-11 06:05:42 +00:00
gingerBill 8721d03cfe Merge pull request #3199 from JamesDSource/soa
Add into_dynamic_soa, unordered_remove_soa, and ordered_remove_soa
2024-03-09 16:56:04 +00:00
gingerBill d06575dd49 Merge pull request #3149 from IllusionMan1212/missing-x11-funcs
vendor/x11: added XQueryExtension, XGetEventData, and XFreeEventData
2024-03-09 16:53:11 +00:00
gingerBill 568b07473f Merge pull request #3148 from IllusionMan1212/cookie-struct-fix
vendor/x11: fix "display" with no pointer in XGenericEventCookie
2024-03-09 16:52:53 +00:00
gingerBill 04666746d7 Merge pull request #3261 from spindlebink/fix-orthonormalize
Properly initialize return matrices in linalg.orthonormalize
2024-03-09 15:51:53 +00:00
spindlebink b2e7eb4db4 Properly initialize return matrices in linalg.orthonormalize 2024-03-09 09:10:25 -06:00
gingerBill f88af59372 Merge pull request #3258 from deckarep/patch-1
Base/runtime (darwin): Incorrect write syscall on Darwin - fixes stderr output.
2024-03-09 11:11:09 +00:00
Ralph Caraveo a974c08aff Incorrect write syscall on Darwin - fixes stderr output.
On macos, Odin was previously swallowing errors that would be reported via stderr. 

I've confirmed with @laytan on Discord that this fixes the issue.
2024-03-08 16:19:59 -08:00
Jeroen van Rijn fc9d3ec5a7 Merge branch 'master' of github.com:odin-lang/Odin 2024-03-08 18:06:13 +01:00
Jeroen van Rijn db03c86544 Fix typo in big.internal_invmod
Fixes #3253
2024-03-08 18:05:34 +01:00
gingerBill 51d12acab3 Enforce linalg 2024-03-08 13:28:15 +00:00
gingerBill 032e193d0d Merge branch 'master' of https://github.com/odin-lang/Odin 2024-03-08 13:20:33 +00:00
gingerBill 0f83ab466f Minor change to spacing when printing a map 2024-03-08 13:20:27 +00:00
gingerBill 53ce945034 Merge pull request #3230 from avanspector/haiku
Add Haiku OS support
2024-03-08 11:15:13 +00:00
gingerBill 0e168dd292 Merge pull request #3241 from Hyrtwol/sys-windows
Gathered what I made for sys/windows
2024-03-07 15:26:31 +00:00
gingerBill 5ff6a25bdc Improve formatting for %# on maps 2024-03-07 13:45:52 +00:00
gingerBill b6b8e640f5 Replace b with _ as it is not needed 2024-03-07 13:41:54 +00:00
gingerBill 573402c97e Begin work on %w - 'w'rite as valid Odin literals 2024-03-07 13:39:44 +00:00
gingerBill e01701ce0e Fix typo 2024-03-07 12:32:46 +00:00
gingerBill f9b14500be Add default_commit_size to virtual.Arena 2024-03-07 12:30:34 +00:00
gingerBill 4bb7cd5e4b Add bit_field option to core_type in the compiler 2024-03-07 11:31:00 +00:00
gingerBill 6d5b1800fe Fix typo 2024-03-06 16:34:17 +00:00
gingerBill 0f5328973e Add mem.Mutex_Allocator 2024-03-06 16:33:54 +00:00
gingerBill 65277ddd6b Add missing attribute 2024-03-06 16:30:39 +00:00
gingerBill 46718d6d85 Add Query_Info to Buddy_Allocator 2024-03-06 16:26:10 +00:00
gingerBill 2a0543d2f0 Add mem.Buddy_Allocator 2024-03-06 16:14:45 +00:00
gingerBill 792f06a234 Fix indentation 2024-03-06 15:29:07 +00:00
gingerBill 14f7619cdc Merge pull request #3069 from pcleavelin/master
Respect `-lld` CLI arg on non-windows machines
2024-03-06 15:25:16 +00:00
gingerBill ffa3669d02 Add virtual.Arena utilities: new, new_aligned, make 2024-03-06 15:23:56 +00:00
gingerBill b1903b915b Change to IEEE 754-2008 conformance for min/max runtime operations. 2024-03-06 15:16:11 +00:00
gingerBill a7bab89c93 Unify min/max semantics for simd_(min|max) 2024-03-06 15:07:21 +00:00
gingerBill a1ee9e7035 Change min/max runtime behaviour to match IEEE 754-2019 2024-03-06 15:04:46 +00:00
gingerBill c05a92ab3e Merge pull request #3215 from blob1807/json-better-enum-support
core:encoding/json Add support for writing enum value names
2024-03-06 14:56:19 +00:00
gingerBill 5789df5c0c Disable core library tests for ARM (Silly CI) 2024-03-06 14:54:23 +00:00
gingerBill 78c05a49a3 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-03-06 14:52:04 +00:00
gingerBill 8d496dc3d0 Fix #3173 2024-03-06 14:51:56 +00:00
gingerBill 703eab2f15 Merge pull request #3229 from Yawning/feature/moar-crypto
core/crypto: More improvements/additions
2024-03-06 14:49:15 +00:00
gingerBill 04bfc926ee Merge pull request #3238 from laytan/libc-free-raylib-and-rectpack
makes raylib and stb_rect_pack free of libc
2024-03-06 14:11:41 +00:00
gingerBill 791c9c16ba Merge pull request #3242 from laytan/fix-cgltf-binding
fix minor cgltf binding issue
2024-03-06 14:11:27 +00:00
gingerBill 6d3a57b4ac Zero intrinsics.alloca 2024-03-06 13:48:37 +00:00
gingerBill c7b8f1fb0a Use intrinsics.alloca rather than context.temp_allocator in json.unmarshal_object 2024-03-06 13:42:38 +00:00
gingerBill 462f3f4abd Merge branch 'master' of https://github.com/odin-lang/Odin 2024-03-06 11:49:24 +00:00
gingerBill 5eef29290c Fix #3250 2024-03-06 11:49:17 +00:00
gingerBill a944aa406d Merge pull request #3246 from edyu/master
For invmod, b has to be > 1, fix a logic typo
2024-03-05 14:00:52 +00:00
gingerBill 8c6c2543da Merge pull request #2999 from laytan/crypto-random-bytes-on-freebsd-and-darwin
add crypto.rand_bytes for Darwin and BSD
2024-03-05 12:55:37 +00:00
gingerBill 7ae22b7ce5 Update are_types_identical for bit_field 2024-03-04 20:22:49 +00:00
gingerBill 3e295734cb Correct is_type_comparable for bit_field 2024-03-04 20:10:34 +00:00
Ed Yu de41c2256d For invmod, b has to be > 1, fix a logic typo 2024-03-04 10:16:19 -08:00
Laytan Laats 9a5f3fed8c encoding/cbor: fix conflict 2024-03-04 17:29:30 +01:00
Laytan Laats 04bd3cc525 encoding/cbor: rename diagnose to to_diagnostic_format to be clearer 2024-03-04 17:26:19 +01:00
Laytan 9fc8587e2c encoding/cbor: untouch net/common.odin 2024-03-04 17:26:19 +01:00
Laytan 2a39c60fe4 encoding/cbor: respect default to panic allocator 2024-03-04 17:26:19 +01:00
Laytan b11d839fb6 encoding/cbor: make temp allocations more explicit 2024-03-04 17:26:19 +01:00
Laytan 0076c07076 encoding/cbor: core -> base 2024-03-04 17:26:19 +01:00
Laytan a664d9804f encoding/cbor: remove usage of incl_elem and excl_elem 2024-03-04 17:26:19 +01:00
Laytan Laats c4e45d509a encoding/cbor: adhere to new quaternion rules of master 2024-03-04 17:26:19 +01:00
Laytan Laats c1cf6c1a95 encoding/cbor: add general docs and example 2024-03-04 17:26:19 +01:00
Laytan Laats 317931a3c5 encoding/cbor: deterministically store bit sets as big endian 2024-03-04 17:26:19 +01:00
Laytan Laats 759d095548 encoding/cbor: ignore struct fields with cbor:"-" 2024-03-04 17:26:19 +01:00
Laytan Laats 7854aa22d9 encoding/cbor: fix unused import 2024-03-04 17:26:19 +01:00
Laytan Laats 72d5b87b52 encoding/cbor: clean 2024-03-04 17:26:19 +01:00
Laytan Laats 154e0d41c6 encoding/cbor: fix wrong allocator bug 2024-03-04 17:26:19 +01:00
Laytan Laats 3fccc77829 encoding/cbor: clean and fixup some allocations 2024-03-04 17:26:19 +01:00
Laytan Laats 85f1a60cf3 encoding/cbor: cleanup comments about tags 2024-03-04 17:26:19 +01:00
Laytan Laats cb8bb8bfd8 encoding/cbor: cleanup default temp allocator 2024-03-04 17:26:19 +01:00
Laytan Laats 46b58ad48d encoding/cbor: don't zero bytes we are going to write/read to/from anyway 2024-03-04 17:26:19 +01:00
Laytan Laats 7283b5e75c encoding/cbor: minor things 2024-03-04 17:26:19 +01:00
Laytan Laats 21e6e28a3a encoding/cbor: add decoder flags and protect from malicious untrusted input 2024-03-04 17:26:19 +01:00
Laytan Laats d77ae9abab encoding/cbor: fully support marshal/unmarshal of unions 2024-03-04 17:26:19 +01:00
Laytan Laats 363769d4d3 encoding/cbor: cleanup base64 tag 2024-03-04 17:26:19 +01:00
Laytan Laats b6c47e7963 encoding/base64: add decode_into, add tests 2024-03-04 17:26:17 +01:00
Laytan Laats 5533a327eb encoding/cbor: initial package implementation 2024-03-04 17:25:34 +01:00
blob1807 b419615002 Apply suggestions from code review
Fixing spelling mistakes pointed out & fixed by layton.

Co-authored-by: Laytan <laytanlaats@hotmail.com>
2024-03-04 21:20:13 +10:00
Yawning Angel c044e295ce vendor/botan: Remove
This is infrequently maintained, and has been a strict subset of what is
available in `core:crypto` for a while.  Instead of improving the
bindings, it is better to spend resources improving `core:crypto`.
2024-03-04 18:20:56 +09:00
Yawning Angel 87ab3f5dc8 tests/core/crypto: Use the tests/common boilerplate 2024-03-04 18:20:56 +09:00
Yawning Angel fa8dd5a13b core/crypto: Misc cleanups and documentation improvements 2024-03-04 17:50:45 +09:00
Yawning Angel b818ebc02f core/crypto/kmac: Initial import 2024-03-04 17:50:45 +09:00
Yawning Angel c04a53e453 core/crypto/tuplehash: Initial import 2024-03-04 17:50:43 +09:00
Yawning Angel 15287a771f core/crypto/shake: Support cSHAKE 2024-03-04 17:50:24 +09:00
Yawning Angel 2db31cf0d5 core/crypto/_sha3: Cleanups, prepare for cSHAKE 2024-03-04 14:51:38 +09:00
Yawning Angel 550e798c1b core/crypto/hkdf: Initial import 2024-03-04 14:51:38 +09:00
Yawning Angel 290168f862 core/crypto/pbkdf2: Initial import 2024-03-04 14:51:38 +09:00
Yawning Angel 2f2a92866b core/crypto/hmac: Add a clone method 2024-03-04 14:51:38 +09:00
blob1807 116edb9052 convert spaces to tabs 2024-03-04 15:09:17 +10:00
blob1807 9070e613a4 Return underlining value instead of panicing
when no name it found.

Renamed use_enum_value_names to use_enum_names
it get the same point across & inline with the
reflect procs
2024-03-04 15:06:30 +10:00
Thomas la Cour 6243160ecd Cleanup of ShowCursor after Bill pushed a fix 2024-03-03 19:53:34 +01:00
Thomas la Cour 980ee3310f didn't help :/ so removed it to see if it can build again 2024-03-03 19:53:34 +01:00
Thomas la Cour c5d5d055ac Trying to resolve a strange nameclash on ShowCursor seems like raylib is also defining that. Unsure why exactly this is related so for now just tried to change the name here to _ShowCursor :/ 2024-03-03 19:53:34 +01:00
Thomas la Cour a783d4ce5b Callback types 2024-03-03 19:53:33 +01:00
Thomas la Cour a7b09a24b7 Waveform Functions
https://learn.microsoft.com/en-us/windows/win32/multimedia/waveform-functions
2024-03-03 19:53:33 +01:00
Thomas la Cour 602e000379 hid usage flags
https://learn.microsoft.com/en-us/windows-hardware/drivers/hid/hid-usages
2024-03-03 19:53:33 +01:00
Thomas la Cour f93074a082 A few extra gdi procs for icons, cursors and drawing 2024-03-03 19:53:33 +01:00
Thomas la Cour 28f05e8aaa SHChangeNotify + flags
https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shchangenotify
2024-03-03 19:53:33 +01:00
Thomas la Cour 9eb1596939 Flags for GlobalAlloc
https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-globalalloc
2024-03-03 19:53:33 +01:00
Thomas la Cour 8412352e5a bitmap v5 header
https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapv5header
2024-03-03 19:53:33 +01:00
Jeroen van Rijn 4c35633e01 math.big constants were no longer initialized
Fixes #3243
2024-03-03 15:09:38 +01:00
Laytan Laats b1371d5c7a fix minor cgltf binding issue 2024-03-01 20:33:23 +01:00
Laytan Laats 3ada83a503 clean imports 2024-03-01 20:32:07 +01:00
Laytan Laats 50ded324e0 move va_list into core:c 2024-03-01 20:30:19 +01:00
gingerBill 674bd94f72 Add check to see if raylib is imported with ShowCursor on sys/windows 2024-03-01 18:30:23 +00:00
gingerBill ff24cfe314 Fix debug issue with maps 2024-03-01 14:00:14 +00:00
gingerBill bc191d4f84 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-03-01 13:36:12 +00:00
gingerBill 5c20676c76 Fix type for SDL LoadFile(_RW) 2024-03-01 13:36:06 +00:00
gingerBill 11b7be1640 Merge pull request #3203 from listeriaceae/master
port math.round from Golang
2024-03-01 11:33:43 +00:00
gingerBill 6ae8288142 Merge pull request #3240 from laytan/macos-self-contained-releases
reduce dynamic library dependencies for macos release
2024-03-01 11:33:20 +00:00
gingerBill 7f1069cb0b Add Recursive_Mutex procedures to procedure groups 2024-03-01 11:31:13 +00:00
blob1807 41fbaaf1d3 changed to use reflect.enum_name_from_value_any 2024-03-01 14:53:39 +10:00
blob1807 f14babe419 Merge branch 'odin-lang:master' into json-better-enum-support 2024-03-01 14:24:51 +10:00
avanspector 0bb2327d76 Merge branch 'haiku' of https://github.com/avanspector/Odin into haiku 2024-03-01 00:43:13 +01:00
avanspector f92042e7dd Merge branch 'odin-lang:master' into haiku 2024-03-01 00:42:28 +01:00
avanspector 1861ecff86 Merge branch 'haiku' of https://github.com/avanspector/Odin into haiku 2024-03-01 00:42:08 +01:00
avanspector d4d9f55556 Update threading.cpp 2024-03-01 00:41:28 +01:00
Laytan Laats 23cd64ec35 reduce dynamic library dependencies for macos release 2024-02-29 23:39:18 +01:00
Laytan Laats 6734a7096a makes raylib and stb_rect_pack free of libc 2024-02-29 23:33:25 +01:00
gingerBill 3263e54144 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-02-29 20:20:43 +00:00
gingerBill 6805b85f89 Fix leap year bug 2024-02-29 20:20:37 +00:00
gingerBill 88c97cbbd0 Merge pull request #3237 from laytan/macos-self-contained-releases
fix releases being a zip of a zip
2024-02-29 16:16:04 +00:00
Laytan Laats 17b1c8d338 fix releases being a zip of a zip 2024-02-29 17:00:20 +01:00
gingerBill 0a5c85f8e3 Merge pull request #3207 from Tetralux/printfln
Add `fmt.*printfln`
2024-02-29 14:04:38 +00:00
gingerBill 9c20df5b1b Merge pull request #3201 from Yawning/feature/avl
core/container/avl: Add an AVL tree implementation
2024-02-29 14:02:45 +00:00
avanspector 5d6b4eda1e Merge branch 'odin-lang:master' into haiku 2024-02-29 03:16:04 +01:00
avanspector 290ada7f90 add exit to core:os 2024-02-28 22:43:55 +01:00
avanspector bf37bee4f7 improve core:sys 2024-02-28 22:29:06 +01:00
gingerBill 7df7fec6f7 Keep -vet happy 2024-02-28 18:27:49 +00:00
gingerBill e423a6d692 Make types distinct 2024-02-28 18:25:29 +00:00
gingerBill f4c74a9f32 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-02-28 18:25:06 +00:00
gingerBill dce176fa39 Remove unnecessary use of transmute 2024-02-28 18:24:59 +00:00
gingerBill d666ff3744 Merge pull request #3135 from colrdavidson/basic_egl
Add support for basic EGL on Linux
2024-02-28 14:42:49 +00:00
gingerBill 1678391db3 Merge pull request #3224 from laytan/macos-self-contained-releases
Make MacOS releases self contained / bundle LLVM
2024-02-28 13:44:50 +00:00
gingerBill d1174f66bc Fix #3233 2024-02-28 13:41:54 +00:00
gingerBill 84a7e03178 Merge pull request #3220 from laytan/promote-types-in-c-varargs
Promote types in `#c_varargs` according to C rules
2024-02-28 10:49:28 +00:00
gingerBill 1bffc8baac Merge pull request #3228 from EddieWoodley/glfw-raw-mouse-supported
vendor/glfw: Add RawMouseMotionSupported to wrapper
2024-02-28 10:48:08 +00:00
gingerBill c558b694eb Merge pull request #3232 from karl-zylinski/raylib-5-binding-errors
Additional fixes for errors in Raylib bindings since Raylib 4 -> 5 upgrade.
2024-02-28 10:46:41 +00:00
gingerBill a06bde729b Merge pull request #3234 from odin-lang/rtti-table-layout
Change `runtime.type_table` layout to allow RTTI to be constantly initialized
2024-02-27 16:25:47 +00:00
gingerBill 5107bdc06b Make lb_type_info use a procedure to load the global value 2024-02-27 15:45:53 +00:00
gingerBill 5137d12d36 Fix lb_type_info for the new layout 2024-02-27 15:40:45 +00:00
gingerBill c6ee025063 Add type info generation for bit_field 2024-02-27 15:27:51 +00:00
gingerBill 826cf1508b Remove __$startup_type_info procedure 2024-02-27 15:09:33 +00:00
gingerBill 51edf01162 Change type info table to be initializable constantly
[]Type_Info -> []^Type_Info
2024-02-27 15:07:55 +00:00
avanspector 87f6f3a1fe Merge branch 'haiku' of https://github.com/avanspector/Odin into haiku 2024-02-27 02:38:19 +01:00
avanspector fca691a066 fix core:thread and a memory leak
in the future probably native non-pthread implementation for haiku will be required
2024-02-27 02:38:06 +01:00
avanspector 494cac02d7 Merge branch 'odin-lang:master' into haiku 2024-02-27 02:00:19 +01:00
avanspector 38c69b9691 small fixes 2024-02-27 01:59:17 +01:00
Colin Davidson deb8922181 Merge branch 'master' into basic_egl 2024-02-26 12:17:53 -05:00
Karl Zylinski cdda8f0eb9 Additional fixes for errors in Raylib bindings since Raylib 4 -> 5 upgrade. 2024-02-26 17:16:45 +01:00
gingerBill cba8cb2201 Merge pull request #3231 from karl-zylinski/raylib-model-animation-binding-fix
Fix ModelAnimation in raylib.odin missing a field
2024-02-26 12:57:39 +00:00
Karl Zylinski ae67f37fc1 Fix ModelAnimation in raylib.odin missing a field. 2024-02-26 13:32:16 +01:00
avanspector 8d4bb35bcc Update futex_haiku.odin 2024-02-26 08:14:05 +01:00
avanspector 180902468f Revert "fix haiku"
This reverts commit 7290c69257.
2024-02-26 08:09:58 +01:00
avanspector 7290c69257 fix haiku 2024-02-26 08:07:17 +01:00
avanspector 3ebf5dcc0e fix haiku 2024-02-26 07:59:53 +01:00
avanspector 9d4c2ba0d8 fix haiku 2024-02-26 07:43:10 +01:00
avanspector 1d79521e81 fix sys/haiku 2024-02-26 06:18:33 +01:00
avanspector 31d7ef5696 Update os_haiku.odin 2024-02-26 06:16:13 +01:00
avanspector 8c621453ae update sys/haiku 2024-02-26 06:13:54 +01:00
avanspector c712af3bc2 Update os_haiku.odin 2024-02-26 04:54:21 +01:00
avanspector f0a89f8d5d add sys/haiku 2024-02-26 04:41:30 +01:00
avanspector 9b839621a9 Update os_haiku.odin 2024-02-25 18:49:42 +01:00
avanspector 66456714e1 update pthread 2024-02-25 18:45:00 +01:00
avanspector fc8e5b8a61 Update os_haiku.odin 2024-02-25 18:31:14 +01:00
avanspector 05cfc89283 fix core:os 2024-02-25 18:20:03 +01:00
avanspector dc5cf23066 add haiku to unix 2024-02-25 16:50:04 +01:00
avanspector 2e80879e88 Update os_haiku.odin 2024-02-25 16:24:50 +01:00
avanspector dfa0ccf976 Update entry_unix.odin 2024-02-25 03:46:52 +01:00
avanspector 6c16860be6 fix runtime and libc 2024-02-25 03:43:41 +01:00
avanspector d032cff23b Update os_specific_haiku.odin 2024-02-25 03:38:15 +01:00
avanspector c3746d9f56 fix core and libc 2024-02-25 03:32:35 +01:00
avanspector 0fa6ba726f add haiku build token 2024-02-25 03:03:12 +01:00
avanspector b03f17dd8d add haiku to base:runtime and core:c/libc 2024-02-25 02:59:45 +01:00
avanspector 24c8b15409 small fixes 2024-02-25 02:38:35 +01:00
avanspector 028a79e66c Update threading.cpp 2024-02-25 02:34:41 +01:00
avanspector 0a6673220b Merge branch 'haiku' of https://github.com/avanspector/Odin into haiku 2024-02-25 02:24:58 +01:00
avanspector 88add0b6b1 Improve Haiku support 2024-02-25 02:24:52 +01:00
Eddie Woodley 8a78b0d241 vendor/glfw Add RawMouseMotionSupported to wrapper 2024-02-24 23:06:05 +00:00
avanspector 824c831190 Implement futex 2024-02-24 23:46:55 +01:00
Yawning Angel 874d6ccb60 core/container/avl: Initial import 2024-02-24 14:05:15 +09:00
Yawning Angel db3279e7da test/core/container: Refactor for multiple container types 2024-02-24 14:05:15 +09:00
Yawning Angel 9251e06143 tests/core: Bring the Makefile more in-sync with build.bat 2024-02-24 14:05:15 +09:00
gingerBill a642ea0b28 Add intrinsics.type_bit_set_backing_type 2024-02-23 11:38:23 +00:00
gingerBill 00fc4c4e1b Make that warning an error with -vet-style 2024-02-22 20:21:21 +00:00
gingerBill 9ea11da00f Add warning when using bit_field when a bit_set would be a much better idea. 2024-02-22 20:10:56 +00:00
gingerBill a8909f06ae Improve parsing for bit_field 2024-02-22 20:10:38 +00:00
Laytan Laats ee543a304a Zip so compiler keeps executable permissions 2024-02-22 21:04:08 +01:00
gingerBill 5c5b78cbbe Improve bit_field printing 2024-02-22 19:48:44 +00:00
gingerBill 54515af8cc Add field tags to bit_field 2024-02-22 19:41:48 +00:00
Laytan Laats b894df2125 Make MacOS releases self contained / bundle LLVM 2024-02-22 20:38:25 +01:00
gingerBill 3f193d7446 Format change 2024-02-22 19:27:13 +00:00
gingerBill e127d21fed Check for pseudo-fields before bit fields 2024-02-22 19:24:50 +00:00
gingerBill 3060225f46 Simplify usage code 2024-02-22 19:24:16 +00:00
gingerBill c14b9d461a Support using of a bit_field within a struct 2024-02-22 19:14:16 +00:00
gingerBill 8060e3170e Remove debug message 2024-02-22 18:53:02 +00:00
gingerBill 980947b355 Give a better error message when the user uses context as if it was an identifier in a field list. 2024-02-22 18:52:17 +00:00
gingerBill fd987b29ff Improve error handling with assignments to bit_field using constants 2024-02-22 18:47:43 +00:00
gingerBill afcc2889ec Support compound literals for bit_field 2024-02-22 18:41:15 +00:00
gingerBill 5f001f6d51 Allow casting between a bit_field and its backing type 2024-02-22 18:15:13 +00:00
gingerBill fc07211772 Change hack a little 2024-02-22 17:43:37 +00:00
gingerBill c9e37a08be Add backing type of a bit_field to the doc-format 2024-02-22 17:41:22 +00:00
gingerBill dcbcf75269 Add doc-format support for bit_field 2024-02-22 17:37:42 +00:00
gingerBill 59479b2ba6 Fix typo 2024-02-22 17:26:32 +00:00
gingerBill 007bd993a6 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-02-22 17:24:48 +00:00
gingerBill 5a84a08225 Add general support for bit_fields 2024-02-22 17:24:42 +00:00
Laytan Laats bb23648c71 Also convert and promote bit_set types for #c_varargs 2024-02-22 18:17:52 +01:00
gingerBill a4b8c1ea17 Begin work adding bit_field 2024-02-22 15:55:54 +00:00
Jeroen van Rijn 20e75cd463 Merge pull request #3221 from Tetralux/net/reservedports
[net] Better error code for binding a privileged port without root access
2024-02-22 16:23:15 +01:00
Tetralux d74ddb2d91 fixup 2024-02-22 15:01:55 +00:00
Tetralux ec0831da70 [net] Better error code for binding a privileged port without root access on Darwin
This condition results in os.EACCESS, which we were translating to Broadcast_Disabled.
This was the case because binding to the broadcast address on a UDP port, without setting the BROADCAST flag, also results in this error.

Given the fact that reserved ports also produce this error, we now check for this condition in net.bind() and translate it to a custom, clearer error:
Privileged_Port_Without_Root.
2024-02-22 14:55:27 +00:00
gingerBill b12ba1508e Update vulkan bindings for to work with the new keyword bit_field 2024-02-22 14:09:12 +00:00
gingerBill f3b0b82461 Fix futex 2024-02-22 14:04:31 +00:00
gingerBill fea38f6910 Minor changes to futex implementation on Linux 2024-02-22 14:01:39 +00:00
gingerBill 213b2fd0f8 Add bit_field as a keyword 2024-02-22 14:01:23 +00:00
gingerBill 42d595f6a1 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-02-22 13:59:27 +00:00
gingerBill 656de10ba4 Minor changes to sync/chan (HIGHLY EXPERIMENTAL) 2024-02-22 13:59:22 +00:00
Laytan Laats f6f3a760bc Promote types in #c_varargs according to C rules 2024-02-21 22:05:11 +01:00
gingerBill bafc791f1c Merge pull request #3219 from laytan/fix-terminators-in-defer
Fix divergent proc call in `defer`
2024-02-21 18:53:40 +00:00
Laytan Laats 1fc256dd90 Fix divergent proc call in defer
Fixes #3216
Fixes #2985
2024-02-21 19:43:34 +01:00
gingerBill 41549b502b Basic concept of core:sync/chan 2024-02-21 15:24:24 +00:00
gingerBill f989f4df3e Add sync.One_Shot_Event 2024-02-21 13:08:12 +00:00
gingerBill 21d1c0e5a4 Revert change since it is not needed 2024-02-21 12:58:26 +00:00
gingerBill d7b7804215 if -> while in wait_signal_until_available to check for spurious wake-ups 2024-02-21 12:55:26 +00:00
gingerBill 8472338bfa Add reflect.enum_name_from_value and reflect.enum_name_from_value_any 2024-02-21 12:43:09 +00:00
gingerBill 1de1d97429 Merge pull request #3213 from laytan/add-backend-info-to-odin-report
Add backend info to odin report
2024-02-21 12:33:06 +00:00
gingerBill f21ead4f78 Merge pull request #3212 from laytan/improve-net-tests
Improve net tests
2024-02-21 12:32:43 +00:00
blob1807 a95cead8e7 add all inter types to switch 2024-02-21 14:05:50 +10:00
blob1807 c276b1c0bc replace spaces with tabs 2024-02-21 11:51:29 +10:00
blob1807 b39ef29ec6 add missing comma 2024-02-21 11:15:35 +10:00
blob1807 b2b8b14955 Add better support for Enums in json
Can now output enum value's name instead of its underlineing value
2024-02-21 11:07:03 +10:00
blob1807 7e0473dded Revert json union fix 2024-02-21 11:03:15 +10:00
Laytan Laats e6bd79c882 Make sure we are listening before starting the client 2024-02-20 23:54:11 +01:00
Laytan Laats 9e417592e3 Add logs to flaky test 2024-02-20 23:45:15 +01:00
Laytan Laats db87c34613 Add backend info to odin report 2024-02-20 23:23:56 +01:00
Laytan Laats 159257597a Convert weird DOS line-endings to UNIX 2024-02-20 23:22:05 +01:00
Laytan Laats bdd6a86d73 Remove flaky test
It wasn't testing the right thing in the previous
iteration.
And in this iteration the behaviour is a timeout on Unix, and
nothing on Windows.
2024-02-20 23:15:18 +01:00
Laytan Laats 1ab3ec5731 Improve net tests
Watching the sporadic CI failures it seems to come from these tests a
lot of the time, this PR cleans up and simplifies (while testing the
same things):

1. Lots of tests were using threads without a need for it
2. Tests had hardcoded `time.sleep` calls which is never a good idea
3. An unclear abstraction was implemented without a real need
4. They weren't being ran on non-windows
5. The `client_connects_to_open_but_not_accepting_port` was not doing
   what you wanted to test for, the `tcp_server` proc was returning, and
   then `dial` was called, which meant that the server already closed
   and you got a refusal error. Now it correctly listens without
   accepting, which even results in a different error because the kernel
   buffer would have buffered the send
2024-02-20 23:06:18 +01:00
blob1807 004cd4933d Merge branch 'master' of https://github.com/blob1807/Odin 2024-02-21 00:43:27 +10:00
blob1807 14ee2181cb Fix bug https://github.com/odin-lang/Odin/issues/3173 2024-02-21 00:42:11 +10:00
gingerBill b43c1f2b5b Merge pull request #3134 from laytan/non-universal-binaries-raylib
vendor/raylib: change to non-universal binaries
2024-02-19 14:18:44 +00:00
Tetralux b1e608bfba [fmt] Add *printfln()
Adds the following procedures, which just call through to the `printf` versions, with `newline = true`; a new parameter
also added in this commit.
In all cases, `wprintf` is the one that ultimately writes the newline, if requested.

- printfln
- fprintfln
- eprintfln
- aprintfln
- tprintfln
- bprintfln
- caprintfln
- ctprintfln
- sbprintfln
- wprintfln
2024-02-18 16:14:59 +00:00
gingerBill 57c5455827 Merge pull request #3206 from flysand7/linux-fdflags-fix
[sys/linux]: Fix numeric values for socket fd flags
2024-02-18 14:56:31 +00:00
flysand7 cc185d98b4 [sys/linux]: Fix numeric values for socket fd flags 2024-02-18 23:04:41 +11:00
Juan Ignacio Díaz cd61251d39 add Go license 2024-02-17 11:49:07 -03:00
gingerBill 43a199b57b Merge branch 'master' of https://github.com/odin-lang/Odin 2024-02-17 13:42:02 +00:00
gingerBill fa1875a8f1 Minor changes to os2 2024-02-17 13:41:54 +00:00
James Duran 44aae76294 Fix syntax mistake again
Sorry for being blind
2024-02-16 10:55:55 -08:00
James Duran 009cebe8bf Fix Syntax Mistake 2024-02-16 10:50:54 -08:00
James Duran 9399cb53b6 Make into_dynamic_soa more concise and remove builtin tag from it 2024-02-16 10:46:46 -08:00
gingerBill bed81c8829 Merge pull request #3197 from laytan/update-miniaudio
Update miniaudio to 0.11.21
2024-02-16 18:08:29 +00:00
Juan Ignacio Díaz 7a592cbb31 port math.round from Golang 2024-02-16 13:23:44 -03:00
Slendi c178f7199d Get Odin to compile on Haiku
This patch makes Odin to compile on Haiku which is a good first step.
Now, all that's needed to do is to figure out how to do futexes, which
I am blaming for the program crashing.
2024-02-15 15:51:28 +02:00
James Duran a4d3777ab2 Added into_dynamic_soa, unordered_remove_soa, and ordered_remove_soa 2024-02-14 16:51:09 -08:00
Laytan Laats e931c82b9b miniaudio: add version mismatch check 2024-02-14 21:55:15 +01:00
laytan a7f0275093 miniaudio: update .lib to 0.11.21 2024-02-14 21:17:12 +01:00
laytan 9ab2fbea00 miniaudio: update .lib 2024-02-14 21:07:57 +01:00
Laytan Laats 7fe86ed565 miniaudio: fix wrong sizes for ma_device 2024-02-14 21:00:26 +01:00
Laytan Laats 16584779fb miniaudio: update to 0.11.21 2024-02-14 19:57:57 +01:00
gingerBill c5c2a4d09d Fix typo 2024-02-13 17:13:39 +00:00
gingerBill 912c326d8b Fix typo that causes map info debug issues 2024-02-13 17:06:04 +00:00
gingerBill d496dbf3a0 Fix race condition with #soa 2024-02-13 16:54:41 +00:00
Laytan Laats 88e6980b13 fix build tags 2024-02-13 17:34:40 +01:00
Laytan Laats 0d413b8136 implement part of core foundation framework bindings for err message 2024-02-13 17:34:40 +01:00
Laytan Laats 32a4a5e601 remove darwin from bsd filename 2024-02-13 17:34:40 +01:00
Laytan Laats 91cf0826c1 use Security.framework with SecRandomCopyBytes for rand_bytes on darwin 2024-02-13 17:34:40 +01:00
Laytan Laats 3bc172c70b add crypto.rand_bytes for Darwin and FreeBSD 2024-02-13 17:34:00 +01:00
gingerBill cbfb32c34c Fix race condition with regards to #soa arrays by using the fields mutex 2024-02-13 16:21:41 +00:00
gingerBill 5cd57a3a7f Use Raw_Map as the debug information for a map 2024-02-13 15:50:07 +00:00
gingerBill 563ce2bd81 Merge pull request #3193 from Lperlind/master
Add ID3DUserDefinedAnnotation
2024-02-13 14:17:20 +00:00
Lucas Perlind 9469b90b01 Add ID3DUserDefinedAnnotation 2024-02-13 17:13:17 +11:00
gingerBill d2e1ec13f0 Merge pull request #3192 from Lperlind/revert-the-matrices
Revert the matrices
2024-02-12 23:44:36 +00:00
Lucas Perlind 6df07a2c0a Remove bounds checking on a lot of linalg 2024-02-13 10:23:29 +11:00
Lucas Perlind c0d407a2b4 Revert "Change minor/adjoint to be row, col from c, r to be consistent with [row, col] syntax; Add #no_bounds_check were appropriate"
This reverts commit 5dd2e38aff.
2024-02-13 10:13:34 +11:00
gingerBill f378367fe7 Store cell data in map debug metadata 2024-02-12 15:17:06 +00:00
gingerBill c291fffce1 Add metadata type to maps debug information to aid debuggers knowing what is in it it 2024-02-12 12:29:37 +00:00
gingerBill 900fe95ba0 Split out linalg.identity between matrices and array-based matrix 2024-02-12 12:08:43 +00:00
gingerBill 5dd2e38aff Change minor/adjoint to be row, col from c, r to be consistent with [row, col] syntax; Add #no_bounds_check were appropriate 2024-02-12 11:54:24 +00:00
gingerBill 5ad8ebba9f Merge pull request #3188 from Tetralux/fixchdir
[os] Fix os.change_directory(), os.set_current_directory()
2024-02-12 11:24:45 +00:00
gingerBill e7719eed65 Merge pull request #3189 from mothfuzz/json_unmarshal_enumerated_enums_fix
remove return statement from case Type_Info_Enumerated_Array
2024-02-12 11:23:51 +00:00
Kay 5f49b8997a remove return statement from case Type_Info_Enumerated_Array, as it causes early exit in JSON unmarshalling. 2024-02-12 01:45:11 -06:00
Tetralux d6734c85b8 [os] Fix os.change_directory(), os.set_current_directory()
- set_current_directory() was leaking the wstring path string because it wasn't using the temp allocator.
- change_directory() wasn't calling SetCurrentDirectoryW() under the lock!
2024-02-12 06:03:51 +00:00
gingerBill 4ca23499fa Add raymath procedures (with numerous deprecated attributes to suggest to use array programming) 2024-02-10 16:31:03 +00:00
gingerBill e201a2fabb Add rand.choice_enum 2024-02-10 15:13:09 +00:00
gingerBill 5c4485f657 Add #load_directory(path: string) > []runtime.Load_Directory_File 2024-02-09 15:18:29 +00:00
gingerBill bae2a6fc1e Merge pull request #3184 from Lperlind/master
Add more window procedures
2024-02-09 11:59:12 +00:00
Lucas Perlind 8777fa1c04 Add more window procedures 2024-02-09 14:04:16 +11:00
gingerBill d771b3286d Merge pull request #3182 from laytan/fix-instrumentation-in-debug-mode
fix instrumentation in debug mode
2024-02-08 21:36:43 +00:00
Laytan 0e6dd56ac1 fix instrumentation in debug mode 2024-02-08 22:29:45 +01:00
gingerBill 9127e584c5 Merge pull request #3181 from laytan/fix-no-crt-on-linux
fix -no-crt on Linux
2024-02-08 21:07:42 +00:00
Laytan eab0e730a0 fix -no-crt on Linux 2024-02-08 19:48:37 +01:00
gingerBill 7128bc4b34 Add core:relative
This will eventually replace the #relative types
2024-02-08 15:15:16 +00:00
gingerBill 7b672ac72a Disallow mixture of polymorphic $ names and normal identifiers within record parameters 2024-02-08 14:03:03 +00:00
gingerBill 8f4ab3c07d Add check for a procedure 2024-02-08 13:49:27 +00:00
gingerBill dc5cfacc0a Fix edge case for procedures 2024-02-08 13:45:18 +00:00
gingerBill 3aea2e1fff Merge branch 'master' of https://github.com/odin-lang/Odin 2024-02-08 13:41:07 +00:00
gingerBill 59933b244d Allow polymorphic checking with intrinsics.type_is_subtype_of(Derived_Type, Poly_Type) 2024-02-08 13:41:02 +00:00
gingerBill 42aca72d9f Correct the logic for parapoly records to match that of procedures (polymorphic non-typeid parameters) 2024-02-08 13:21:41 +00:00
gingerBill 7034a31745 Merge pull request #3180 from z64/z64/fix
Remove invalid allocator assignment to slice
2024-02-08 12:39:49 +00:00
Zac Nowicki 9d0786ded7 Remove invalid allocator assignment to slice
`T` is `#soa[]$E`, which does not carry an allocator.
2024-02-08 04:14:16 -05:00
gingerBill 4c51706941 Merge pull request #3179 from laytan/fix-ci
fix ci
2024-02-07 19:09:04 +00:00
Laytan Laats a8c4f46747 fix ci 2024-02-07 19:53:52 +01:00
gingerBill 8e367d221b Merge branch 'master' of https://github.com/odin-lang/Odin 2024-02-07 17:16:05 +00:00
gingerBill a08250ac5b Improve error handling for missing library collection provided by the compiler 2024-02-07 17:15:59 +00:00
gingerBill 131c71ea76 Merge pull request #3142 from jay-j/feature/gl-allow-geometry-shaders
Expose OpenGL shader procs to allow creation of pipelines with geometry shaders
2024-02-07 16:09:58 +00:00
gingerBill 9db04fe446 Merge pull request #3156 from laytan/spall-instrumentation
Make spall able to be used in instrumentation procedures
2024-02-07 12:16:20 +00:00
gingerBill abaa906f34 Fix lb_hasher_proc_for_type 2024-02-07 11:05:38 +00:00
gingerBill fa093d9b09 Add runtime.map_insert_and_check_for_previous 2024-02-06 23:58:22 +00:00
gingerBill 4035a226da Fix filepath.rel allocation behaviour 2024-02-06 23:39:20 +00:00
gingerBill df5ee2dd06 Merge pull request #3178 from laytan/fix-virtual-static-reset-logic
mem/virtual: fix arena_static_reset_to inverted logic
2024-02-06 23:31:07 +00:00
Laytan 9b4cd0743c mem/virtual: fix arena_static_reset_to inverted logic 2024-02-06 20:24:38 +01:00
laytan 3f090ed523 fix for instrumenting on Windows 2024-02-06 19:55:09 +01:00
gingerBill 79173ef119 Merge pull request #3136 from Yawning/feature/crypto-hash
core:crypto/hash - Add and refactor
2024-02-06 17:40:45 +00:00
Yawning Angel 44758f2a60 core/crypto: Stop using context.temp_allocator
The max digest size for the foreseeable future will be 512 bits, and the
max block size is currently 1152 bits (SHA3-224).  If people add more
exotic hash algorithms without bumping the constants when required,
tests will fail.

The stream buffer will currently be 576 bytes, which is "fine" to just
stick on the stack, and is a sensible multiple of the more common block
size of 64 bytes.
2024-02-07 02:33:53 +09:00
gingerBill 1f0b24b735 Remove unneeded casts 2024-02-06 17:22:13 +00:00
gingerBill 327853ab92 Merge branch 'master' of https://github.com/odin-lang/Odin 2024-02-06 17:20:13 +00:00
gingerBill a6878fcd91 Clean up code for initialize_symbols 2024-02-06 17:20:07 +00:00
gingerBill 61202b5abd Merge pull request #3174 from thetarnav/webgl2-matrix-flatten-2
Use `intrinsics.matrix_flatten` in `webgl2.odin`
2024-02-06 17:00:33 +00:00
Yawning Angel 56516ee8b2 core/crypto/poly1305: Relax the tag length check on the verify helper 2024-02-07 00:42:01 +09:00
Yawning Angel 1cc639bc93 core/crypto/hmac: Initial import 2024-02-07 00:42:01 +09:00
Yawning Angel 2357293e05 core/crypto/hash: Make the low level interface allocator-less
Just (ab)using reflect to victory is probably fine.
2024-02-07 00:37:18 +09:00
Yawning Angel 7a8b1669b0 core/crypto: Expose the block sizes for every hash algorithm
While I just went and made this private, this information is required
for keying HMAC.
2024-02-07 00:37:18 +09:00
Yawning Angel bc160d2eb7 tests/core/crypto: Reorganize
All of our crypto is modern now unless exiled to the legacy sub-package,
so move the test cases for the currently un-unified algorithms into the
main test driver file, and rename the benchmark driver to reflect
reality.
2024-02-07 00:37:18 +09:00
Yawning Angel b02b85d242 core/crypto/shake: SHAKE is an XOF, not a hash 2024-02-07 00:37:18 +09:00
Yawning Angel 1d151c4c92 tests/core/crypto: Cleanup/modernize a bit 2024-02-07 00:37:18 +09:00
Yawning Angel 899fab64d9 core/crypto: Documentation cleanups 2024-02-07 00:37:18 +09:00
Yawning Angel 00ab3beed9 core:crypto/hash: Add a generic higher level hash interface
There is a lot of code duplicated in convenience methods in each hash
implementation, and having a generic hash type makes implementing
higher-level constructs such as HMAC significantly easier down the road.
2024-02-07 00:37:18 +09:00
Yawning Angel ca10fc2d47 repo: Add yet another test binary to .gitignore 2024-02-07 00:37:18 +09:00
gingerBill 1ed6a484ac Merge pull request #3175 from Murtagy/patch-1
Update raylib.odin
2024-02-06 14:59:35 +00:00
gingerBill b0675358c3 Add angle_between and matrix2_rotate 2024-02-06 14:09:05 +00:00
Murtagy 456dd22dc4 Update raylib.odin 2024-02-05 21:38:17 +03:00
Laytan 02b8fefa30 indent doc.odin, makes it render nicely on the documentation site 2024-02-05 18:59:08 +01:00
Laytan 95808fd2e7 remove unneeded no instrumentation comment, are all foreign procs anyway 2024-02-05 18:54:37 +01:00
Laytan e63d71c23b implement bsd's, same as darwin 2024-02-05 18:48:17 +01:00
Damian Tarnawski 23a49ce65b USe intrinsics.matrix_flatten in webgl2.odin 2024-02-05 18:28:03 +01:00
Laytan Laats ca6300c860 spall instrumentation 2024-02-05 16:54:22 +01:00
gingerBill 1ebb7f8e9d Merge pull request #3170 from flysand7/run-args-fix
Make run args take the first '--' as the start of the args, instead of the last '--'
2024-02-05 13:58:32 +00:00
gingerBill 4685cf1085 Merge pull request #3140 from JustinRyanH/master
Implement `last_write_time` and `last_write_time_by_name` for Darwin
2024-02-05 13:57:28 +00:00
gingerBill 80a0b161b0 Force 128-bit calls on wasm 2024-02-05 13:51:16 +00:00
gingerBill 27feb5998c Add require to 128-bit and f16 casts 2024-02-05 13:49:10 +00:00
gingerBill e88db2818b force requiring the 128-bit calls on WASM targets 2024-02-05 13:48:08 +00:00
gingerBill 19535d8721 Add require flags to 128-bit integer procedures 2024-02-05 11:11:28 +00:00
flysand7 8ea8fbeccb Make run args take the first '--' as the start of the args, instead of the last '--' 2024-02-04 14:25:53 +11:00
Jeroen van Rijn 4e300ff90a Merge pull request #3167 from Murtagy/patch-1
Typo in comment in raylib
2024-02-03 17:04:10 +01:00
Murtagy 7bf25a4cf2 typo in comment 2024-02-03 18:43:34 +03:00
gingerBill 5f0f9f477e Merge pull request #3161 from laytan/fix-no-crt-darwin
fix -no-crt on Darwin
2024-02-03 12:30:00 +00:00
gingerBill dd7c65a89c Merge pull request #2998 from laytan/os-improvements
OS improvements
2024-02-03 12:29:39 +00:00
gingerBill 8620281191 Merge pull request #3163 from laytan/arm-releases-and-ci
Add MacOS ARM releases and CI
2024-02-03 12:25:49 +00:00
gingerBill c311a60aaf Merge pull request #3164 from FourteenBrush/master
Fix compiler panic: "src/parser.cpp(128): Panic: Unhandled Ast or branch expression"
2024-02-03 12:24:54 +00:00
gingerBill 2993490c75 Merge pull request #3165 from korvahkh/fix-dyn-array-init
Fix #3155
2024-02-03 12:24:40 +00:00
gingerBill 60b324d4ed Merge pull request #3166 from mothfuzz/patch-2
Change ClearMask to ColorMask in webgl.odin
2024-02-03 12:24:10 +00:00
Kay 89a2fdd106 Change ClearMask to ColorMask in webgl.odin
https://registry.khronos.org/OpenGL-Refpages/gl4/html/glColorMask.xhtml
2024-02-02 23:42:37 -06:00
korvahkh 8530829ca4 Fix dynamic array index = value with const value initializing to 0 2024-02-02 15:27:39 -06:00
FourteenBrush 0e5d7801dd Fix code style 2024-02-02 21:17:10 +01:00
Laytan Laats d5db49a3b0 name the workflows 2024-02-02 21:10:35 +01:00
Laytan Laats 606f11ebe8 fix hxa test use after free, skip weird pow test failure 2024-02-02 21:10:11 +01:00
Laytan Laats 07a4f4d017 add MacOS ARM target to CI and releases 2024-02-02 21:09:57 +01:00
FourteenBrush d463adfe4f Merge remote-tracking branch 'upstream/master' 2024-02-02 21:01:52 +01:00
FourteenBrush 16bd19ed43 Fix Unhandled Ast_OrBranchExpr 2024-02-02 21:00:00 +01:00
Laytan Laats eb811e8341 fix -no-crt on Darwin 2024-02-02 19:49:40 +01:00
Justin Hurstwright 8a63b6dff7 fix: remove returns ErrNo for Windows, FreeBSD, Unix 2024-02-02 09:10:25 -06:00
Justin Hurstwright 829654e3a2 steal the last_write from freebsd implementation 2024-02-02 09:10:25 -06:00
gingerBill cec08114fd Mock out comments 2024-02-02 14:57:22 +00:00
gingerBill bf90b61908 Fix type_elem_type for complex32 and quaternion64 2024-02-02 14:52:42 +00:00
gingerBill ae0a5b1a87 RUNTIME_REQUIRE :: false 2024-02-02 12:03:14 +00:00
gingerBill 55ff9b857e Add contextless where missing 2024-02-02 11:51:26 +00:00
gingerBill e7122a0950 Minimize extra dependencies if u128/i128 and f16 are not used 2024-02-02 11:42:22 +00:00
IllusionMan1212 301b9eef31 vendor/x11: added XQueryExtension, XGetEventData, and XFreeEventData 2024-01-29 06:22:33 +02:00
IllusionMan1212 36ed8fe55d vendor/x11: change display to be a ^Display in XGenericEventCookie struct 2024-01-29 05:54:14 +02:00
Patrick Cleavelin 7b9ea9eca0 Merge branch 'odin-lang:master' into master 2024-01-27 14:12:19 -06:00
Gabriel Pariat 89404147f6 fix whitespace 2024-01-27 14:10:32 -05:00
Gabriel Pariat 29d4bdc80b Revert "fix whitespace"
This reverts commit 594078cc1d.
2024-01-27 14:09:08 -05:00
Gabriel Pariat 594078cc1d fix whitespace 2024-01-27 14:08:14 -05:00
Gabriel Pariat ab68e4c6c4 change ordering 2024-01-27 14:06:58 -05:00
Gabriel Pariat 4956f9dad3 fix typo 2024-01-27 14:04:43 -05:00
Gabriel Pariat fd090c6672 adding linux + unix makefile for cgltf 2024-01-27 14:00:02 -05:00
jay-j b46b3010ec Expose OpenGL shader procedures to allow creation of shader pipelines with geometry shaders 2024-01-26 19:43:47 -08:00
Colin Davidson f93f2dfd5c Add support for basic EGL on Linux 2024-01-24 13:24:25 -08:00
Laytan Laats 9ac619f4a2 vendor/raylib: change to non-universal binaries
We already have 2 different folders for the different architectures, so
this does should not have any usage impact.

Main motivation for doing this is hombrew requiring non-universal
binaries in their installation, so this is a step to getting homebrew
and vendor to play nice.
2024-01-24 20:58:14 +01:00
Rikard Petré 239d4e1076 odin/tokenizer: Reset insert_semicolon to false in tokenizer.init to fix bug when tokenizing multiple files. 2024-01-20 16:09:41 +01:00
Rikard Petré 99825a28d7 odin/parser: Allow semicolon after return statement for the case:
if x do return y;
else do return z;
2024-01-20 16:00:41 +01:00
Rikard Petré 144504a752 odin/parser: Fix parsing of struct literal/call expression when closing brace/paren is on a new line without a comma after the last argument. 2024-01-20 15:57:14 +01:00
Patrick Cleavelin 59aa05170d respect -lld CLI arg 2024-01-04 13:55:36 -06:00
Laytan Laats 0b2f357bbe fix eof logic 2023-12-14 18:05:06 +01:00
Laytan Laats 9a1c4dc56d implement a max read/write at a time for non-windows (windows already has this) 2023-12-14 18:05:06 +01:00
Laytan Laats 7eabeda870 make sure an eof is also returned from the file streams on non-windows 2023-12-14 18:05:06 +01:00
756 changed files with 106619 additions and 48248 deletions
+5 -1
View File
@@ -1,2 +1,6 @@
*.odin linguist-language=Odin
* text=auto
* text=auto
# These files must always have *nix line-endings
Makefile text eol=lf
*.sh text eol=lf
+149 -97
View File
@@ -2,106 +2,163 @@ name: CI
on: [push, pull_request, workflow_dispatch]
jobs:
build_linux:
build_netbsd:
name: NetBSD Build, Check, and Test
runs-on: ubuntu-latest
env:
PKGSRC_BRANCH: 2024Q1
steps:
- uses: actions/checkout@v4
- name: Build, Check, and Test
timeout-minutes: 15
uses: vmactions/netbsd-vm@v1
with:
release: "10.0"
envs: PKGSRC_BRANCH
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
ln -s /usr/pkg/bin/python3.11 /usr/bin/python3
run: |
git config --global --add safe.directory $(pwd)
gmake release
./odin version
./odin report
gmake -C vendor/stb/src
gmake -C vendor/cgltf/src
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
(cd tests/issues; ./run.sh)
build_freebsd:
name: FreeBSD Build, Check, and Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Download LLVM, botan
run: sudo apt-get install llvm-11 clang-11 libbotan-2-dev botan
- name: build odin
- uses: actions/checkout@v4
- name: Build, Check, and Test
timeout-minutes: 15
uses: vmactions/freebsd-vm@v1
with:
usesh: true
copyback: false
prepare: |
pkg install -y gmake git bash python3 libxml2 llvm17
run: |
# `set -e` is needed for test failures to register. https://github.com/vmactions/freebsd-vm/issues/72
set -e -x
git config --global --add safe.directory $(pwd)
gmake release
./odin version
./odin report
gmake -C vendor/stb/src
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
(cd tests/issues; ./run.sh)
ci:
strategy:
fail-fast: false
matrix:
# MacOS 13 runs on Intel, 14 runs on ARM
os: [ubuntu-latest, macos-13, macos-14]
runs-on: ${{ matrix.os }}
name: ${{ matrix.os == 'macos-14' && 'MacOS ARM' || (matrix.os == 'macos-13' && 'MacOS Intel' || 'Ubuntu') }} Build, Check, and Test
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- name: Download LLVM (Linux)
if: matrix.os == 'ubuntu-latest'
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 17
echo "/usr/lib/llvm-17/bin" >> $GITHUB_PATH
- name: Download LLVM (MacOS Intel)
if: matrix.os == 'macos-13'
run: |
brew install llvm@17
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
echo "/opt/homebrew/opt/llvm@17/bin" >> $GITHUB_PATH
- name: Build Odin
run: ./build_odin.sh release
- name: Odin version
run: ./odin version
timeout-minutes: 1
- name: Odin report
run: ./odin report
timeout-minutes: 1
- 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/demo -vet
timeout-minutes: 10
- name: Odin run
run: ./odin run examples/demo
timeout-minutes: 10
- name: Odin run -debug
run: ./odin run examples/demo -debug
timeout-minutes: 10
- name: Odin check examples/all
run: ./odin check examples/all -strict-style
timeout-minutes: 10
- name: Core library tests
run: |
cd tests/core
make
timeout-minutes: 10
- name: Normal Core library tests
run: ./odin test tests/core/normal.odin -file -all-packages -define:ODIN_TEST_FANCY=false
- name: Optimized Core library tests
run: ./odin test tests/core/speed.odin -o:speed -file -all-packages -define:ODIN_TEST_FANCY=false
- name: Vendor library tests
run: ./odin test tests/vendor -all-packages -define:ODIN_TEST_FANCY=false
- 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
- name: GitHub Issue tests
run: |
cd tests/vendor
make
timeout-minutes: 10
- name: Odin internals tests
run: |
cd tests/internal
make
timeout-minutes: 10
cd tests/issues
./run.sh
- name: Odin check examples/all for Linux i386
run: ./odin check examples/all -vet -strict-style -target:linux_i386
timeout-minutes: 10
- name: Odin check examples/all for FreeBSD amd64
run: ./odin check examples/all -vet -strict-style -target:freebsd_amd64
timeout-minutes: 10
- name: Odin check examples/all for OpenBSD amd64
run: ./odin check examples/all -vet -strict-style -target:openbsd_amd64
timeout-minutes: 10
build_macOS:
runs-on: macos-latest
steps:
- uses: actions/checkout@v1
- name: Download LLVM, botan and setup PATH
run: |
brew install llvm@13 botan
echo "/usr/local/opt/llvm@13/bin" >> $GITHUB_PATH
TMP_PATH=$(xcrun --show-sdk-path)/user/include
echo "CPATH=$TMP_PATH" >> $GITHUB_ENV
- name: build odin
run: ./build_odin.sh release
- name: Odin version
run: ./odin version
timeout-minutes: 1
- name: Odin report
run: ./odin report
timeout-minutes: 1
- name: Odin check
run: ./odin check examples/demo -vet
timeout-minutes: 10
- name: Odin run
run: ./odin run examples/demo
timeout-minutes: 10
- name: Odin run -debug
run: ./odin run examples/demo -debug
timeout-minutes: 10
- name: Odin check examples/all
run: ./odin check examples/all -strict-style
timeout-minutes: 10
- name: Core library tests
run: |
cd tests/core
make
timeout-minutes: 10
- name: Odin internals tests
run: |
cd tests/internal
make
timeout-minutes: 10
- name: Odin check examples/all for Darwin arm64
run: ./odin check examples/all -vet -strict-style -target:darwin_arm64
timeout-minutes: 10
run: ./odin check examples/all -vet -strict-style -disallow-do -target:linux_i386
if: matrix.os == 'ubuntu-latest'
- name: Odin check examples/all for Linux arm64
run: ./odin check examples/all -vet -strict-style -target:linux_arm64
timeout-minutes: 10
run: ./odin check examples/all -vet -strict-style -disallow-do -target:linux_arm64
if: matrix.os == 'ubuntu-latest'
- name: Odin check examples/all for FreeBSD amd64
run: ./odin check examples/all -vet -strict-style -disallow-do -target:freebsd_amd64
if: matrix.os == 'ubuntu-latest'
- name: Odin check examples/all for OpenBSD amd64
run: ./odin check examples/all -vet -strict-style -disallow-do -target:openbsd_amd64
if: matrix.os == 'ubuntu-latest'
- name: Run demo on WASI WASM32
run: |
./odin build examples/demo -target:wasi_wasm32 -vet -strict-style -disallow-do -out:demo.wasm
wasmtime ./demo.wasm
if: matrix.os == 'macos-14'
build_windows:
name: Windows Build, Check, and Test
runs-on: windows-2022
timeout-minutes: 15
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v4
- name: build Odin
shell: cmd
run: |
@@ -109,72 +166,67 @@ jobs:
./build.bat 1
- name: Odin version
run: ./odin version
timeout-minutes: 1
- name: Odin report
run: ./odin report
timeout-minutes: 1
- name: Odin check
shell: cmd
run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin check examples/demo -vet
timeout-minutes: 10
- name: Odin run
shell: cmd
run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin run examples/demo
timeout-minutes: 10
- name: Odin run -debug
shell: cmd
run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin run examples/demo -debug
timeout-minutes: 10
- 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
timeout-minutes: 10
- name: Core library tests
shell: cmd
run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
cd tests\core
call build.bat
timeout-minutes: 10
odin test tests/core/normal.odin -file -all-packages -define:ODIN_TEST_FANCY=false
- 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
- name: Vendor library tests
shell: cmd
run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
cd tests\vendor
call build.bat
timeout-minutes: 10
odin test tests/vendor -all-packages -define:ODIN_TEST_FANCY=false
- name: Odin internals tests
shell: cmd
run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
cd tests\internal
call build.bat
timeout-minutes: 10
odin test tests/internal -all-packages -define:ODIN_TEST_FANCY=false
- name: Odin documentation tests
shell: cmd
run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
cd tests\documentation
rem call build.bat
timeout-minutes: 10
call build.bat
- name: core:math/big tests
shell: cmd
run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
cd tests\core\math\big
call build.bat
timeout-minutes: 10
- name: Odin check examples/all for Windows 32bits
shell: cmd
run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin check examples/all -strict-style -target:windows_i386
timeout-minutes: 10
+76 -39
View File
@@ -7,10 +7,11 @@ on:
jobs:
build_windows:
name: Windows Build
if: github.repository == 'odin-lang/Odin'
runs-on: windows-2022
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v4
- name: build Odin
shell: cmd
run: |
@@ -40,12 +41,17 @@ jobs:
name: windows_artifacts
path: dist
build_ubuntu:
name: Ubuntu Build
if: github.repository == 'odin-lang/Odin'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v4
- name: (Linux) Download LLVM
run: sudo apt-get install llvm-11 clang-11
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 17
echo "/usr/lib/llvm-17/bin" >> $GITHUB_PATH
- name: build odin
run: make nightly
- name: Odin run
@@ -61,27 +67,28 @@ jobs:
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
- name: Upload artifact
uses: actions/upload-artifact@v1
with:
name: ubuntu_artifacts
path: dist
path: dist.zip
build_macos:
name: MacOS Build
if: github.repository == 'odin-lang/Odin'
runs-on: macOS-latest
runs-on: macos-13
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v4
- name: Download LLVM and setup PATH
run: |
brew install llvm@13
echo "/usr/local/opt/llvm@13/bin" >> $GITHUB_PATH
TMP_PATH=$(xcrun --show-sdk-path)/user/include
echo "CPATH=$TMP_PATH" >> $GITHUB_ENV
brew install llvm@17 dylibbundler
echo "/usr/local/opt/llvm@17/bin" >> $GITHUB_PATH
- name: build odin
run: make nightly
- name: Odin run
run: ./odin run examples/demo
- name: Copy artifacts
# 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
@@ -91,25 +98,64 @@ jobs:
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
- name: Odin run
run: ./dist/odin run examples/demo
- name: Upload artifact
uses: actions/upload-artifact@v1
with:
name: macos_artifacts
path: dist
path: dist.zip
build_macos_arm:
name: MacOS ARM Build
if: github.repository == 'odin-lang/Odin'
runs-on: macos-14 # ARM machine
steps:
- 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
- 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
- name: Odin run
run: ./dist/odin run examples/demo
- name: Upload artifact
uses: actions/upload-artifact@v1
with:
name: macos_arm_artifacts
path: dist.zip
upload_b2:
runs-on: [ubuntu-latest]
needs: [build_windows, build_macos, build_ubuntu]
needs: [build_windows, build_macos, build_macos_arm, build_ubuntu]
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v4
- uses: actions/setup-python@v2
with:
python-version: '3.8.x'
- name: Install B2 CLI
- name: Install B2 SDK
shell: bash
run: |
python -m pip install --upgrade pip
pip install --upgrade b2
pip install --upgrade b2sdk
- name: Display Python version
run: python -c "import sys; print(sys.version)"
@@ -129,6 +175,11 @@ jobs:
with:
name: macos_artifacts
- name: Download macOS arm artifacts
uses: actions/download-artifact@v1
with:
name: macos_arm_artifacts
- name: Create archives and upload
shell: bash
env:
@@ -137,23 +188,9 @@ jobs:
BUCKET: ${{ secrets.B2_BUCKET }}
DAYS_TO_KEEP: ${{ secrets.B2_DAYS_TO_KEEP }}
run: |
echo Authorizing B2 account
b2 authorize-account "$APPID" "$APPKEY"
echo Uploading artifcates to B2
chmod +x ./ci/upload_create_nightly.sh
./ci/upload_create_nightly.sh "$BUCKET" windows-amd64 windows_artifacts/
./ci/upload_create_nightly.sh "$BUCKET" ubuntu-amd64 ubuntu_artifacts/
./ci/upload_create_nightly.sh "$BUCKET" macos-amd64 macos_artifacts/
echo Deleting old artifacts in B2
python3 ci/delete_old_binaries.py "$BUCKET" "$DAYS_TO_KEEP"
echo Creating nightly.json
python3 ci/create_nightly_json.py "$BUCKET" > nightly.json
echo Uploading nightly.json
b2 upload-file "$BUCKET" nightly.json nightly.json
echo Clear B2 account info
b2 clear-account
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 prune
python3 ci/nightly.py json
+11 -3
View File
@@ -27,7 +27,10 @@ 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
@@ -39,8 +42,10 @@ tests/core/test_core_net
tests/core/test_core_os_exit
tests/core/test_core_reflect
tests/core/test_core_strings
tests/core/test_crypto_hash
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
@@ -49,6 +54,7 @@ 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/
@@ -297,7 +303,7 @@ bin/
# - Linux/MacOS
odin
!odin/
odin.dSYM
**/*.dSYM
*.bin
demo.bin
libLLVM*.so*
@@ -316,4 +322,6 @@ build.sh
!core/debug/
# RAD debugger project file
*.raddbg
*.raddbg
misc/featuregen/featuregen
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2016-2022 Ginger Bill. All rights reserved.
Copyright (c) 2016-2024 Ginger Bill. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
+2
View File
@@ -126,3 +126,5 @@ clamp :: proc(value, minimum, maximum: T) -> T ---
soa_zip :: proc(slices: ...) -> #soa[]Struct ---
soa_unzip :: proc(value: $S/#soa[]$E) -> (slices: ...) ---
unreachable :: proc() -> ! ---
+33 -12
View File
@@ -38,9 +38,9 @@ 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) #optional_ok ---
overflow_sub :: proc(lhs, rhs: $T) -> (T, bool) #optional_ok ---
overflow_mul :: proc(lhs, rhs: $T) -> (T, bool) #optional_ok ---
overflow_add :: proc(lhs, rhs: $T) -> (T, bool) ---
overflow_sub :: proc(lhs, rhs: $T) -> (T, bool) ---
overflow_mul :: proc(lhs, rhs: $T) -> (T, bool) ---
sqrt :: proc(x: $T) -> T where type_is_float(T) || (type_is_simd_vector(T) && type_is_float(type_elem_type(T))) ---
@@ -73,6 +73,8 @@ expect :: proc(val, expected_val: T) -> T ---
// Linux and Darwin Only
syscall :: proc(id: uintptr, args: ..uintptr) -> uintptr ---
// FreeBSD, NetBSD, et cetera
syscall_bsd :: proc(id: uintptr, args: ..uintptr) -> (uintptr, bool) ---
// Atomics
@@ -167,17 +169,23 @@ type_is_matrix :: proc($T: typeid) -> bool ---
type_has_nil :: proc($T: typeid) -> bool ---
type_is_matrix_row_major :: proc($T: typeid) -> bool where type_is_matrix(T) ---
type_is_matrix_column_major :: proc($T: typeid) -> bool where type_is_matrix(T) ---
type_is_specialization_of :: proc($T, $S: typeid) -> bool ---
type_is_variant_of :: proc($U, $V: typeid) -> bool where type_is_union(U) ---
type_union_tag_type :: proc($T: typeid) -> typeid where type_is_union(T) ---
type_union_tag_offset :: proc($T: typeid) -> uintptr where type_is_union(T) ---
type_union_base_tag_value :: proc($T: typeid) -> int where type_is_union(U) ---
type_union_variant_count :: proc($T: typeid) -> int where type_is_union(T) ---
type_variant_type_of :: proc($T: typeid, $index: int) -> typeid where type_is_union(T) ---
type_variant_index_of :: proc($U, $V: typeid) -> int where type_is_union(U) ---
type_is_variant_of :: proc($U, $V: typeid) -> bool where type_is_union(U) ---
type_union_tag_type :: proc($T: typeid) -> typeid where type_is_union(T) ---
type_union_tag_offset :: proc($T: typeid) -> uintptr where type_is_union(T) ---
type_union_base_tag_value :: proc($T: typeid) -> int where type_is_union(U) ---
type_union_variant_count :: proc($T: typeid) -> int where type_is_union(T) ---
type_variant_type_of :: proc($T: typeid, $index: int) -> typeid where type_is_union(T) ---
type_variant_index_of :: proc($U, $V: typeid) -> int where type_is_union(U) ---
type_has_field :: proc($T: typeid, $name: string) -> bool ---
type_bit_set_elem_type :: proc($T: typeid) -> typeid where type_is_bit_set(T) ---
type_bit_set_underlying_type :: proc($T: typeid) -> typeid where type_is_bit_set(T) ---
type_has_field :: proc($T: typeid, $name: string) -> bool ---
type_field_type :: proc($T: typeid, $name: string) -> typeid ---
type_proc_parameter_count :: proc($T: typeid) -> int where type_is_proc(T) ---
@@ -186,7 +194,8 @@ type_proc_return_count :: proc($T: typeid) -> int where type_is_proc(T) ---
type_proc_parameter_type :: proc($T: typeid, index: int) -> typeid where type_is_proc(T) ---
type_proc_return_type :: proc($T: typeid, index: int) -> typeid where type_is_proc(T) ---
type_struct_field_count :: proc($T: typeid) -> int where type_is_struct(T) ---
type_struct_field_count :: proc($T: typeid) -> int where type_is_struct(T) ---
type_struct_has_implicit_padding :: proc($T: typeid) -> bool where type_is_struct(T) ---
type_polymorphic_record_parameter_count :: proc($T: typeid) -> typeid ---
type_polymorphic_record_parameter_value :: proc($T: typeid, index: int) -> $V ---
@@ -282,6 +291,16 @@ simd_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 ---
// Checks if the current target supports the given target features.
//
// Takes a constant comma-seperated string (eg: "sha512,sse4.1"), or a procedure type which has either
// `@(require_target_feature)` or `@(enable_target_feature)` as its input and returns a boolean indicating
// if all listed features are supported.
has_target_feature :: proc($test: $T) -> bool where type_is_string(T) || type_is_proc(T) ---
// Returns the value of the procedure where `x` must be a call expression
procedure_of :: proc(x: $T) -> T where type_is_proc(T) ---
// WASM targets only
wasm_memory_grow :: proc(index, delta: uintptr) -> int ---
@@ -293,7 +312,9 @@ wasm_memory_size :: proc(index: uintptr) -> int ---
// 0 - indicates that the thread blocked and then was woken up
// 1 - the loaded value from `ptr` did not match `expected`, the thread did not block
// 2 - the thread blocked, but the timeout
@(require_target_feature="atomics")
wasm_memory_atomic_wait32 :: proc(ptr: ^u32, expected: u32, timeout_ns: i64) -> u32 ---
@(require_target_feature="atomics")
wasm_memory_atomic_notify32 :: proc(ptr: ^u32, waiters: u32) -> (waiters_woken_up: u32) ---
// x86 Targets (i386, amd64)
+99 -14
View File
@@ -177,10 +177,22 @@ Type_Info_Matrix :: struct {
row_count: int,
column_count: int,
// Total element count = column_count * elem_stride
layout: enum u8 {
Column_Major, // array of column vectors
Row_Major, // array of row vectors
},
}
Type_Info_Soa_Pointer :: struct {
elem: ^Type_Info,
}
Type_Info_Bit_Field :: struct {
backing_type: ^Type_Info,
names: []string,
types: []^Type_Info,
bit_sizes: []uintptr,
bit_offsets: []uintptr,
tags: []string,
}
Type_Info_Flag :: enum u8 {
Comparable = 0,
@@ -223,6 +235,7 @@ Type_Info :: struct {
Type_Info_Relative_Multi_Pointer,
Type_Info_Matrix,
Type_Info_Soa_Pointer,
Type_Info_Bit_Field,
},
}
@@ -256,21 +269,22 @@ Typeid_Kind :: enum u8 {
Relative_Multi_Pointer,
Matrix,
Soa_Pointer,
Bit_Field,
}
#assert(len(Typeid_Kind) < 32)
// Typeid_Bit_Field :: bit_field #align(align_of(uintptr)) {
// index: 8*size_of(uintptr) - 8,
// kind: 5, // Typeid_Kind
// named: 1,
// special: 1, // signed, cstring, etc
// reserved: 1,
// }
// #assert(size_of(Typeid_Bit_Field) == size_of(uintptr));
Typeid_Bit_Field :: bit_field uintptr {
index: uintptr | 8*size_of(uintptr) - 8,
kind: Typeid_Kind | 5, // Typeid_Kind
named: bool | 1,
special: bool | 1, // signed, cstring, etc
reserved: bool | 1,
}
#assert(size_of(Typeid_Bit_Field) == size_of(uintptr))
// NOTE(bill): only the ones that are needed (not all types)
// This will be set by the compiler
type_table: []Type_Info
type_table: []^Type_Info
args__: []cstring
@@ -296,6 +310,14 @@ Source_Code_Location :: struct {
procedure: string,
}
/*
Used by the built-in directory `#load_directory(path: string) -> []Load_Directory_File`
*/
Load_Directory_File :: struct {
name: string,
data: []byte, // immutable data
}
Assertion_Failure_Proc :: #type proc(prefix, message: string, loc: Source_Code_Location) -> !
// Allocation Stuff
@@ -375,11 +397,34 @@ Logger :: struct {
options: Logger_Options,
}
Random_Generator_Mode :: enum {
Read,
Reset,
Query_Info,
}
Random_Generator_Query_Info_Flag :: enum u32 {
Cryptographic,
Uniform,
External_Entropy,
Resettable,
}
Random_Generator_Query_Info :: distinct bit_set[Random_Generator_Query_Info_Flag; u32]
Random_Generator_Proc :: #type proc(data: rawptr, mode: Random_Generator_Mode, p: []byte)
Random_Generator :: struct {
procedure: Random_Generator_Proc,
data: rawptr,
}
Context :: struct {
allocator: Allocator,
temp_allocator: Allocator,
assertion_failure_proc: Assertion_Failure_Proc,
logger: Logger,
random_generator: Random_Generator,
user_ptr: rawptr,
user_index: int,
@@ -448,6 +493,15 @@ Raw_Soa_Pointer :: struct {
index: int,
}
Raw_Complex32 :: struct {real, imag: f16}
Raw_Complex64 :: struct {real, imag: f32}
Raw_Complex128 :: struct {real, imag: f64}
Raw_Quaternion64 :: struct {imag, jmag, kmag: f16, real: f16}
Raw_Quaternion128 :: struct {imag, jmag, kmag: f32, real: f32}
Raw_Quaternion256 :: struct {imag, jmag, kmag: f64, real: f64}
Raw_Quaternion64_Vector_Scalar :: struct {vector: [3]f16, scalar: f16}
Raw_Quaternion128_Vector_Scalar :: struct {vector: [3]f32, scalar: f32}
Raw_Quaternion256_Vector_Scalar :: struct {vector: [3]f64, scalar: f64}
/*
@@ -459,7 +513,9 @@ Raw_Soa_Pointer :: struct {
Linux,
Essence,
FreeBSD,
Haiku,
OpenBSD,
NetBSD,
WASI,
JS,
Freestanding,
@@ -486,6 +542,7 @@ Odin_Arch_Type :: type_of(ODIN_ARCH)
Odin_Build_Mode_Type :: enum int {
Executable,
Dynamic,
Static,
Object,
Assembly,
LLVM_IR,
@@ -526,6 +583,19 @@ Odin_Platform_Subtarget_Type :: type_of(ODIN_PLATFORM_SUBTARGET)
*/
Odin_Sanitizer_Flags :: type_of(ODIN_SANITIZER_FLAGS)
/*
// Defined internally by the compiler
Odin_Optimization_Mode :: enum int {
None = -1,
Minimal = 0,
Size = 1,
Speed = 2,
Aggressive = 3,
}
ODIN_OPTIMIZATION_MODE // is a constant
*/
Odin_Optimization_Mode :: type_of(ODIN_OPTIMIZATION_MODE)
/////////////////////////////
// Init Startup Procedures //
@@ -575,8 +645,9 @@ type_info_core :: proc "contextless" (info: ^Type_Info) -> ^Type_Info {
base := info
loop: for {
#partial switch i in base.variant {
case Type_Info_Named: base = i.base
case Type_Info_Enum: base = i.base
case Type_Info_Named: base = i.base
case Type_Info_Enum: base = i.base
case Type_Info_Bit_Field: base = i.backing_type
case: break loop
}
}
@@ -591,7 +662,7 @@ __type_info_of :: proc "contextless" (id: typeid) -> ^Type_Info #no_bounds_check
if n < 0 || n >= len(type_table) {
n = 0
}
return &type_table[n]
return type_table[n]
}
when !ODIN_NO_RTTI {
@@ -660,13 +731,16 @@ __init_context :: proc "contextless" (c: ^Context) {
c.logger.procedure = default_logger_proc
c.logger.data = nil
c.random_generator.procedure = default_random_generator_proc
c.random_generator.data = nil
}
default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code_Location) -> ! {
when ODIN_OS == .Freestanding {
// Do nothing
} else {
when !ODIN_DISABLE_ASSERT {
when ODIN_OS != .Orca && !ODIN_DISABLE_ASSERT {
print_caller_location(loc)
print_string(" ")
}
@@ -675,7 +749,18 @@ default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code
print_string(": ")
print_string(message)
}
print_byte('\n')
when ODIN_OS == .Orca {
assert_fail(
cstring(raw_data(loc.file_path)),
cstring(raw_data(loc.procedure)),
loc.line,
"",
cstring(raw_data(orca_stderr_buffer[:orca_stderr_buffer_idx])),
)
} else {
print_byte('\n')
}
}
trap()
}
+91 -29
View File
@@ -40,7 +40,7 @@ copy_slice :: proc "contextless" (dst, src: $T/[]$E) -> int {
}
return n
}
// `copy_from_string` is a built-in procedure that copies elements from a source slice `src` to a destination string `dst`.
// `copy_from_string` is a built-in procedure that copies elements from a source string `src` to a destination slice `dst`.
// The source and destination may overlap. Copy returns the number of elements copied, which will be the minimum
// of len(src) and len(dst).
//
@@ -53,7 +53,7 @@ copy_from_string :: proc "contextless" (dst: $T/[]$E/u8, src: $S/string) -> int
}
return n
}
// `copy` is a built-in procedure that copies elements from a source slice `src` to a destination slice/string `dst`.
// `copy` is a built-in procedure that copies elements from a source slice/string `src` to a destination slice `dst`.
// The source and destination may overlap. Copy returns the number of elements copied, which will be the minimum
// of len(src) and len(dst).
@builtin
@@ -65,7 +65,7 @@ copy :: proc{copy_slice, copy_from_string}
// with the old value, and reducing the length of the dynamic array by 1.
//
// Note: This is an O(1) operation.
// Note: If you the elements to remain in their order, use `ordered_remove`.
// 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 {
@@ -79,7 +79,7 @@ unordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_loca
// `ordered_remove` removed the element at the specified `index` whilst keeping the order of the other elements.
//
// Note: This is an O(N) operation.
// Note: If you the elements do not have to remain in their order, prefer `unordered_remove`.
// 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 {
@@ -122,7 +122,7 @@ pop :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (res: E) #no_bou
// `pop_safe` trys to remove and return the end value of dynamic array `array` and reduces the length of `array` by 1.
// If the operation is not possible, it will return false.
@builtin
pop_safe :: proc(array: ^$T/[dynamic]$E) -> (res: E, ok: bool) #no_bounds_check {
pop_safe :: proc "contextless" (array: ^$T/[dynamic]$E) -> (res: E, ok: bool) #no_bounds_check {
if len(array) == 0 {
return
}
@@ -148,7 +148,7 @@ pop_front :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (res: E) #
// `pop_front_safe` trys to return and remove the first value of dynamic array `array` and reduces the length of `array` by 1.
// If the operation is not possible, it will return false.
@builtin
pop_front_safe :: proc(array: ^$T/[dynamic]$E) -> (res: E, ok: bool) #no_bounds_check {
pop_front_safe :: proc "contextless" (array: ^$T/[dynamic]$E) -> (res: E, ok: bool) #no_bounds_check {
if len(array) == 0 {
return
}
@@ -163,21 +163,43 @@ pop_front_safe :: proc(array: ^$T/[dynamic]$E) -> (res: E, ok: bool) #no_bounds_
// `clear` will set the length of a passed dynamic array or map to `0`
@builtin
clear :: proc{clear_dynamic_array, clear_map}
clear :: proc{
clear_dynamic_array,
clear_map,
clear_soa_dynamic_array,
}
// `reserve` will try to reserve memory of a passed dynamic array or map to the requested element count (setting the `cap`).
@builtin
reserve :: proc{reserve_dynamic_array, reserve_map}
reserve :: proc{
reserve_dynamic_array,
reserve_map,
reserve_soa,
}
@builtin
non_zero_reserve :: proc{non_zero_reserve_dynamic_array}
non_zero_reserve :: proc{
non_zero_reserve_dynamic_array,
non_zero_reserve_soa,
}
// `resize` will try to resize memory of a passed dynamic array to the requested element count (setting the `len`, and possibly `cap`).
@builtin
resize :: proc{resize_dynamic_array}
resize :: proc{
resize_dynamic_array,
resize_soa,
}
@builtin
non_zero_resize :: proc{non_zero_resize_dynamic_array}
non_zero_resize :: proc{
non_zero_resize_dynamic_array,
non_zero_resize_soa,
}
// Shrinks the capacity of a dynamic array or map down to the current length, or the given capacity.
@builtin
@@ -268,7 +290,7 @@ new_clone :: proc(data: $T, allocator := context.allocator, loc := #caller_locat
return
}
DEFAULT_RESERVE_CAPACITY :: 16
DEFAULT_DYNAMIC_ARRAY_CAPACITY :: 8
@(require_results)
make_aligned :: proc($T: typeid/[]$E, #any_int len: int, alignment: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_allocator_error {
@@ -295,7 +317,7 @@ make_slice :: proc($T: typeid/[]$E, #any_int len: int, allocator := context.allo
// Note: Prefer using the procedure group `make`.
@(builtin, require_results)
make_dynamic_array :: proc($T: typeid/[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_allocator_error {
return make_dynamic_array_len_cap(T, 0, DEFAULT_RESERVE_CAPACITY, allocator, loc)
return make_dynamic_array_len_cap(T, 0, 0, allocator, loc)
}
// `make_dynamic_array_len` allocates and initializes a dynamic array. 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.
@@ -364,6 +386,11 @@ make :: proc{
make_dynamic_array_len_cap,
make_map,
make_multi_pointer,
make_soa_slice,
make_soa_dynamic_array,
make_soa_dynamic_array_len,
make_soa_dynamic_array_len_cap,
}
@@ -383,7 +410,7 @@ clear_map :: proc "contextless" (m: ^$T/map[$K]$V) {
//
// Note: Prefer the procedure group `reserve`
@builtin
reserve_map :: proc(m: ^$T/map[$K]$V, capacity: int, loc := #caller_location) -> Allocator_Error {
reserve_map :: proc(m: ^$T/map[$K]$V, #any_int capacity: int, loc := #caller_location) -> Allocator_Error {
return __dynamic_map_reserve((^Raw_Map)(m), map_info(T), uint(capacity), loc) if m != nil else nil
}
@@ -423,7 +450,8 @@ _append_elem :: #force_inline proc(array: ^$T/[dynamic]$E, arg: E, should_zero:
return 1, nil
} else {
if cap(array) < len(array)+1 {
cap := 2 * cap(array) + max(8, 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 {
@@ -447,12 +475,12 @@ _append_elem :: #force_inline proc(array: ^$T/[dynamic]$E, arg: E, should_zero:
}
@builtin
append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
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)
}
@builtin
non_zero_append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
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)
}
@@ -472,7 +500,7 @@ _append_elems :: #force_inline proc(array: ^$T/[dynamic]$E, should_zero: bool, l
return arg_len, nil
} else {
if cap(array) < len(array)+arg_len {
cap := 2 * cap(array) + max(8, arg_len)
cap := 2 * cap(array) + max(DEFAULT_DYNAMIC_ARRAY_CAPACITY, arg_len)
// do not 'or_return' here as it could be a partial success
if should_zero {
@@ -496,12 +524,12 @@ _append_elems :: #force_inline proc(array: ^$T/[dynamic]$E, should_zero: bool, l
}
@builtin
append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
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)
}
@builtin
non_zero_append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
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)
}
@@ -540,8 +568,23 @@ append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_
}
// The append built-in procedure appends elements to the end of a dynamic array
@builtin append :: proc{append_elem, append_elems, append_elem_string}
@builtin non_zero_append :: proc{non_zero_append_elem, non_zero_append_elems, non_zero_append_elem_string}
@builtin append :: proc{
append_elem,
append_elems,
append_elem_string,
append_soa_elem,
append_soa_elems,
}
@builtin non_zero_append :: proc{
non_zero_append_elem,
non_zero_append_elems,
non_zero_append_elem_string,
non_zero_append_soa_elem,
non_zero_append_soa_elems,
}
@builtin
@@ -556,7 +599,7 @@ append_nothing :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (n: i
@builtin
inject_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 {
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 {
if array == nil {
return
}
@@ -574,7 +617,7 @@ inject_at_elem :: proc(array: ^$T/[dynamic]$E, index: int, arg: E, loc := #calle
}
@builtin
inject_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 {
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 {
if array == nil {
return
}
@@ -721,12 +764,12 @@ _reserve_dynamic_array :: #force_inline proc(array: ^$T/[dynamic]$E, capacity: i
}
@builtin
reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #caller_location) -> Allocator_Error {
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)
}
@builtin
non_zero_reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #caller_location) -> Allocator_Error {
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)
}
@@ -740,6 +783,9 @@ _resize_dynamic_array :: #force_inline proc(array: ^$T/[dynamic]$E, length: int,
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))
}
a.len = max(length, 0)
return nil
}
@@ -770,12 +816,12 @@ _resize_dynamic_array :: #force_inline proc(array: ^$T/[dynamic]$E, length: int,
}
@builtin
resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller_location) -> Allocator_Error {
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)
}
@builtin
non_zero_resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller_location) -> Allocator_Error {
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)
}
@@ -824,9 +870,25 @@ map_insert :: proc(m: ^$T/map[$K]$V, key: K, value: V, loc := #caller_location)
return (^V)(__dynamic_map_set_without_hash((^Raw_Map)(m), map_info(T), rawptr(&key), rawptr(&value), loc))
}
// Explicitly inserts a key and value into a map `m`, the same as `map_insert`, but the return values differ.
// - `prev_key` will return the previous pointer of a key if it exists, check `found_previous` if was previously found
// - `value_ptr` will return the pointer of the memory where the insertion happens, and `nil` if the map failed to resize
// - `found_previous` will be true a previous key was found
@(builtin, require_results)
map_upsert :: proc(m: ^$T/map[$K]$V, key: K, value: V, loc := #caller_location) -> (prev_key: K, value_ptr: ^V, found_previous: bool) {
key, value := key, value
kp, vp := __dynamic_map_set_extra_without_hash((^Raw_Map)(m), map_info(T), rawptr(&key), rawptr(&value), loc)
if kp != nil {
prev_key = (^K)(kp)^
found_previous = true
}
value_ptr = (^V)(vp)
return
}
@builtin
card :: proc(s: $S/bit_set[$E; $U]) -> int {
card :: proc "contextless" (s: $S/bit_set[$E; $U]) -> int {
when size_of(S) == 1 {
return int(intrinsics.count_ones(transmute(u8)s))
} else when size_of(S) == 2 {
+146 -40
View File
@@ -55,7 +55,7 @@ raw_soa_footer_slice :: proc(array: ^$T/#soa[]$E) -> (footer: ^Raw_SOA_Footer_Sl
if array == nil {
return nil
}
field_count := uintptr(intrinsics.type_struct_field_count(E))
field_count := uintptr(len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E))
footer = (^Raw_SOA_Footer_Slice)(uintptr(array) + field_count*size_of(rawptr))
return
}
@@ -64,12 +64,7 @@ raw_soa_footer_dynamic_array :: proc(array: ^$T/#soa[dynamic]$E) -> (footer: ^Ra
if array == nil {
return nil
}
field_count: uintptr
when intrinsics.type_is_array(E) {
field_count = len(E)
} else {
field_count = uintptr(intrinsics.type_struct_field_count(E))
}
field_count := uintptr(len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E))
footer = (^Raw_SOA_Footer_Dynamic_Array)(uintptr(array) + field_count*size_of(rawptr))
return
}
@@ -86,7 +81,6 @@ make_soa_aligned :: proc($T: typeid/#soa[]$E, length: int, alignment: int, alloc
return
}
array.allocator = allocator
footer := raw_soa_footer(&array)
if size_of(E) == 0 {
footer.len = length
@@ -99,11 +93,11 @@ make_soa_aligned :: proc($T: typeid/#soa[]$E, length: int, alignment: int, alloc
ti = type_info_base(ti)
si := &ti.variant.(Type_Info_Struct)
field_count := uintptr(intrinsics.type_struct_field_count(E))
field_count := uintptr(len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E))
total_size := 0
for i in 0..<field_count {
type := si.types[i].variant.(Type_Info_Pointer).elem
type := si.types[i].variant.(Type_Info_Multi_Pointer).elem
total_size += type.size * length
total_size = align_forward_int(total_size, max_align)
}
@@ -127,7 +121,7 @@ make_soa_aligned :: proc($T: typeid/#soa[]$E, length: int, alignment: int, alloc
data := uintptr(&array)
offset := 0
for i in 0..<field_count {
type := si.types[i].variant.(Type_Info_Pointer).elem
type := si.types[i].variant.(Type_Info_Multi_Pointer).elem
offset = align_forward_int(offset, max_align)
@@ -148,7 +142,7 @@ make_soa_slice :: proc($T: typeid/#soa[]$E, length: int, allocator := context.al
@(builtin, require_results)
make_soa_dynamic_array :: proc($T: typeid/#soa[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_allocator_error {
context.allocator = allocator
reserve_soa(&array, DEFAULT_RESERVE_CAPACITY, loc) or_return
reserve_soa(&array, 0, loc) or_return
return array, nil
}
@@ -188,8 +182,28 @@ resize_soa :: proc(array: ^$T/#soa[dynamic]$E, length: int, loc := #caller_locat
return nil
}
@builtin
non_zero_resize_soa :: proc(array: ^$T/#soa[dynamic]$E, length: int, loc := #caller_location) -> Allocator_Error {
if array == nil {
return nil
}
non_zero_reserve_soa(array, length, loc) or_return
footer := raw_soa_footer(array)
footer.len = length
return nil
}
@builtin
reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, 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 {
return _reserve_soa(array, capacity, false, loc)
}
_reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, zero_memory: bool, loc := #caller_location) -> Allocator_Error {
if array == nil {
return nil
}
@@ -214,12 +228,7 @@ reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, loc := #caller_lo
ti = type_info_base(ti)
si := &ti.variant.(Type_Info_Struct)
field_count: uintptr
when intrinsics.type_is_array(E) {
field_count = len(E)
} else {
field_count = uintptr(intrinsics.type_struct_field_count(E))
}
field_count := uintptr(len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E))
assert(footer.cap == old_cap)
old_size := 0
@@ -227,7 +236,7 @@ reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, loc := #caller_lo
max_align :: align_of(E)
for i in 0..<field_count {
type := si.types[i].variant.(Type_Info_Pointer).elem
type := si.types[i].variant.(Type_Info_Multi_Pointer).elem
old_size += type.size * old_cap
new_size += type.size * capacity
@@ -239,7 +248,7 @@ reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, loc := #caller_lo
old_data := (^rawptr)(array)^
new_bytes := array.allocator.procedure(
array.allocator.data, .Alloc, new_size, max_align,
array.allocator.data, .Alloc if zero_memory else .Alloc_Non_Zeroed, new_size, max_align,
nil, old_size, loc,
) or_return
new_data := raw_data(new_bytes)
@@ -250,7 +259,7 @@ reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, loc := #caller_lo
old_offset := 0
new_offset := 0
for i in 0..<field_count {
type := si.types[i].variant.(Type_Info_Pointer).elem
type := si.types[i].variant.(Type_Info_Multi_Pointer).elem
old_offset = align_forward_int(old_offset, max_align)
new_offset = align_forward_int(new_offset, max_align)
@@ -274,15 +283,26 @@ reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, loc := #caller_lo
return nil
}
@builtin
append_soa_elem :: proc(array: ^$T/#soa[dynamic]$E, arg: E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
append_soa_elem :: proc(array: ^$T/#soa[dynamic]$E, #no_broadcast arg: E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
return _append_soa_elem(array, true, arg, loc)
}
@builtin
non_zero_append_soa_elem :: proc(array: ^$T/#soa[dynamic]$E, #no_broadcast arg: E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
return _append_soa_elem(array, false, arg, loc)
}
_append_soa_elem :: proc(array: ^$T/#soa[dynamic]$E, zero_memory: bool, #no_broadcast arg: E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
if array == nil {
return 0, nil
}
if cap(array) <= len(array) + 1 {
cap := 2 * cap(array) + 8
err = reserve_soa(array, cap, loc) // do not 'or_return' here as it could be a partial success
// Same behavior as append_soa_elems but there's only one arg, so we always just add DEFAULT_DYNAMIC_ARRAY_CAPACITY.
cap := 2 * cap(array) + DEFAULT_DYNAMIC_ARRAY_CAPACITY
err = _reserve_soa(array, cap, zero_memory, loc) // do not 'or_return' here as it could be a partial success
}
footer := raw_soa_footer(array)
@@ -291,12 +311,7 @@ append_soa_elem :: proc(array: ^$T/#soa[dynamic]$E, arg: E, loc := #caller_locat
ti := type_info_of(T)
ti = type_info_base(ti)
si := &ti.variant.(Type_Info_Struct)
field_count: uintptr
when intrinsics.type_is_array(E) {
field_count = len(E)
} else {
field_count = uintptr(intrinsics.type_struct_field_count(E))
}
field_count := uintptr(len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E))
data := (^rawptr)(array)^
@@ -308,7 +323,7 @@ append_soa_elem :: proc(array: ^$T/#soa[dynamic]$E, arg: E, loc := #caller_locat
max_align :: align_of(E)
for i in 0..<field_count {
type := si.types[i].variant.(Type_Info_Pointer).elem
type := si.types[i].variant.(Type_Info_Multi_Pointer).elem
soa_offset = align_forward_int(soa_offset, max_align)
item_offset = align_forward_int(item_offset, type.align)
@@ -327,7 +342,17 @@ append_soa_elem :: proc(array: ^$T/#soa[dynamic]$E, arg: E, loc := #caller_locat
}
@builtin
append_soa_elems :: proc(array: ^$T/#soa[dynamic]$E, args: ..E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
append_soa_elems :: proc(array: ^$T/#soa[dynamic]$E, #no_broadcast args: ..E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
return _append_soa_elems(array, true, args=args, loc=loc)
}
@builtin
non_zero_append_soa_elems :: proc(array: ^$T/#soa[dynamic]$E, #no_broadcast args: ..E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
return _append_soa_elems(array, false, args=args, loc=loc)
}
_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
}
@@ -338,8 +363,8 @@ append_soa_elems :: proc(array: ^$T/#soa[dynamic]$E, args: ..E, loc := #caller_l
}
if cap(array) <= len(array)+arg_len {
cap := 2 * cap(array) + max(8, arg_len)
err = reserve_soa(array, cap, loc) // do not 'or_return' here as it could be a partial success
cap := 2 * cap(array) + max(DEFAULT_DYNAMIC_ARRAY_CAPACITY, arg_len)
err = _reserve_soa(array, cap, zero_memory, loc) // do not 'or_return' here as it could be a partial success
}
arg_len = min(cap(array)-len(array), arg_len)
@@ -348,7 +373,7 @@ append_soa_elems :: proc(array: ^$T/#soa[dynamic]$E, args: ..E, loc := #caller_l
ti := type_info_of(typeid_of(T))
ti = type_info_base(ti)
si := &ti.variant.(Type_Info_Struct)
field_count := uintptr(intrinsics.type_struct_field_count(E))
field_count := uintptr(len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E))
data := (^rawptr)(array)^
@@ -359,7 +384,7 @@ append_soa_elems :: proc(array: ^$T/#soa[dynamic]$E, args: ..E, loc := #caller_l
max_align :: align_of(E)
for i in 0..<field_count {
type := si.types[i].variant.(Type_Info_Pointer).elem
type := si.types[i].variant.(Type_Info_Multi_Pointer).elem
soa_offset = align_forward_int(soa_offset, max_align)
item_offset = align_forward_int(item_offset, type.align)
@@ -390,7 +415,8 @@ append_soa :: proc{
delete_soa_slice :: proc(array: $T/#soa[]$E, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
when intrinsics.type_struct_field_count(E) != 0 {
field_count :: len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E)
when field_count != 0 {
array := array
ptr := (^rawptr)(&array)^
free(ptr, allocator, loc) or_return
@@ -399,7 +425,8 @@ delete_soa_slice :: proc(array: $T/#soa[]$E, allocator := context.allocator, loc
}
delete_soa_dynamic_array :: proc(array: $T/#soa[dynamic]$E, loc := #caller_location) -> Allocator_Error {
when intrinsics.type_struct_field_count(E) != 0 {
field_count :: len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E)
when field_count != 0 {
array := array
ptr := (^rawptr)(&array)^
footer := raw_soa_footer(&array)
@@ -417,7 +444,8 @@ delete_soa :: proc{
clear_soa_dynamic_array :: proc(array: ^$T/#soa[dynamic]$E) {
when intrinsics.type_struct_field_count(E) != 0 {
field_count :: len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E)
when field_count != 0 {
footer := raw_soa_footer(array)
footer.len = 0
}
@@ -426,4 +454,82 @@ clear_soa_dynamic_array :: proc(array: ^$T/#soa[dynamic]$E) {
@builtin
clear_soa :: proc{
clear_soa_dynamic_array,
}
}
// Converts soa slice into a soa dynamic array without cloning or allocating memory
@(require_results)
into_dynamic_soa :: proc(array: $T/#soa[]$E) -> #soa[dynamic]E {
d: #soa[dynamic]E
footer := raw_soa_footer_dynamic_array(&d)
footer^ = {
cap = len(array),
len = 0,
allocator = nil_allocator(),
}
field_count := uintptr(len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E))
array := array
dynamic_data := ([^]rawptr)(&d)[:field_count]
slice_data := ([^]rawptr)(&array)[:field_count]
copy(dynamic_data, slice_data)
return d
}
// `unordered_remove_soa` removed the element at the specified `index`. It does so by replacing the current end value
// with the old value, and reducing the length of the dynamic array by 1.
//
// Note: This is an O(1) operation.
// 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 {
bounds_check_error_loc(loc, index, len(array))
if index+1 < len(array) {
ti := type_info_of(typeid_of(T))
ti = type_info_base(ti)
si := &ti.variant.(Type_Info_Struct)
field_count := uintptr(len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E))
data := uintptr(array)
for i in 0..<field_count {
type := si.types[i].variant.(Type_Info_Multi_Pointer).elem
offset := rawptr((^uintptr)(data)^ + uintptr(index*type.size))
final := rawptr((^uintptr)(data)^ + uintptr((len(array)-1)*type.size))
mem_copy(offset, final, type.size)
data += size_of(rawptr)
}
}
raw_soa_footer_dynamic_array(array).len -= 1
}
// `ordered_remove_soa` removed the element at the specified `index` whilst keeping the order of the other elements.
//
// Note: This is an O(N) operation.
// 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 {
bounds_check_error_loc(loc, index, len(array))
if index+1 < len(array) {
ti := type_info_of(typeid_of(T))
ti = type_info_base(ti)
si := &ti.variant.(Type_Info_Struct)
field_count := uintptr(len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E))
data := uintptr(array)
for i in 0..<field_count {
type := si.types[i].variant.(Type_Info_Multi_Pointer).elem
offset := (^uintptr)(data)^ + uintptr(index*type.size)
length := type.size*(len(array) - index - 1)
mem_copy(rawptr(offset), rawptr(offset + uintptr(type.size)), length)
data += size_of(rawptr)
}
}
raw_soa_footer_dynamic_array(array).len -= 1
}
@@ -6,6 +6,9 @@ when ODIN_DEFAULT_TO_NIL_ALLOCATOR {
} else when ODIN_DEFAULT_TO_PANIC_ALLOCATOR {
default_allocator_proc :: panic_allocator_proc
default_allocator :: panic_allocator
} else when ODIN_OS != .Orca && (ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32) {
default_allocator :: default_wasm_allocator
default_allocator_proc :: wasm_allocator_proc
} else {
default_allocator :: heap_allocator
default_allocator_proc :: heap_allocator_proc
@@ -12,6 +12,8 @@ Memory_Block :: struct {
capacity: uint,
}
// NOTE: This is a growing arena that is only used for the default temp allocator.
// For your own growing arena needs, prefer `Arena` from `core:mem/virtual`.
Arena :: struct {
backing_allocator: Allocator,
curr_block: ^Memory_Block,
@@ -1,7 +1,7 @@
package runtime
DEFAULT_TEMP_ALLOCATOR_BACKING_SIZE: int : #config(DEFAULT_TEMP_ALLOCATOR_BACKING_SIZE, 4 * Megabyte)
NO_DEFAULT_TEMP_ALLOCATOR: bool : ODIN_OS == .Freestanding || ODIN_OS == .JS || ODIN_DEFAULT_TO_NIL_ALLOCATOR
NO_DEFAULT_TEMP_ALLOCATOR: bool : ODIN_OS == .Freestanding || ODIN_DEFAULT_TO_NIL_ALLOCATOR
when NO_DEFAULT_TEMP_ALLOCATOR {
Default_Temp_Allocator :: struct {}
+4 -3
View File
@@ -44,7 +44,7 @@ memcpy
memove
## Procedures required by the LLVM backend
## Procedures required by the LLVM backend if u128/i128 is used
umodti3
udivti3
modti3
@@ -59,11 +59,12 @@ truncdfhf2
gnu_h2f_ieee
gnu_f2h_ieee
extendhfsf2
## Procedures required by the LLVM backend if f16 is used
__ashlti3 // wasm specific
__multi3 // wasm specific
## Required an entry point is defined (i.e. 'main')
args__
@@ -156,7 +157,7 @@ __dynamic_map_get // dynamic map calls
__dynamic_map_set // dynamic map calls
## Dynamic literals ([dymamic]T and map[K]V) (can be disabled with -no-dynamic-literals)
## Dynamic literals ([dynamic]T and map[K]V) (can be disabled with -no-dynamic-literals)
__dynamic_array_reserve
__dynamic_array_append
+70 -3
View File
@@ -333,7 +333,7 @@ map_kvh_data_values_dynamic :: proc "contextless" (m: Raw_Map, #no_alias info: ^
}
@(private, require_results)
@(require_results)
map_total_allocation_size :: #force_inline proc "contextless" (capacity: uintptr, info: ^Map_Info) -> uintptr {
round :: #force_inline proc "contextless" (value: uintptr) -> uintptr {
CACHE_MASK :: MAP_CACHE_LINE_SIZE - 1
@@ -350,6 +350,12 @@ map_total_allocation_size :: #force_inline proc "contextless" (capacity: uintptr
return size
}
@(require_results)
map_total_allocation_size_from_value :: #force_inline proc "contextless" (m: $M/map[$K]$V) -> uintptr {
return map_total_allocation_size(uintptr(cap(m)), map_info(M))
}
// The only procedure which needs access to the context is the one which allocates the map.
@(require_results)
map_alloc_dynamic :: proc "odin" (info: ^Map_Info, log2_capacity: uintptr, allocator := context.allocator, loc := #caller_location) -> (result: Raw_Map, err: Allocator_Error) {
@@ -391,7 +397,8 @@ map_alloc_dynamic :: proc "odin" (info: ^Map_Info, log2_capacity: uintptr, alloc
// arrays to reduce variance. This swapping can only be done with memcpy since
// there is no type information.
//
// This procedure returns the address of the just inserted value.
// This procedure returns the address of the just inserted value, and will
// return 'nil' if there was no room to insert the entry
@(require_results)
map_insert_hash_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, h: Map_Hash, ik: uintptr, iv: uintptr) -> (result: uintptr) {
h := h
@@ -415,6 +422,11 @@ map_insert_hash_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^
tv := map_cell_index_dynamic(sv, info.vs, 1)
swap_loop: for {
if distance > mask {
// Failed to find an empty slot and prevent infinite loop
panic("unable to insert into a map")
}
element_hash := hs[pos]
if map_hash_is_empty(element_hash) {
@@ -841,6 +853,33 @@ __dynamic_map_get :: proc "contextless" (#no_alias m: ^Raw_Map, #no_alias info:
}
}
__dynamic_map_get_key_and_value :: proc "contextless" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, h: Map_Hash, key: rawptr) -> (key_ptr, value_ptr: rawptr) {
if m.len == 0 {
return nil, nil
}
pos := map_desired_position(m^, h)
distance := uintptr(0)
mask := (uintptr(1) << map_log2_cap(m^)) - 1
ks, vs, hs, _, _ := map_kvh_data_dynamic(m^, info)
for {
element_hash := hs[pos]
if map_hash_is_empty(element_hash) {
return nil, nil
} else if distance > map_probe_distance(m^, element_hash, pos) {
return nil, nil
} else if element_hash == h {
other_key := rawptr(map_cell_index_dynamic(ks, info.ks, pos))
if info.key_equal(key, other_key) {
key_ptr = other_key
value_ptr = rawptr(map_cell_index_dynamic(vs, info.vs, pos))
return
}
}
pos = (pos + 1) & mask
distance += 1
}
}
// IMPORTANT: USED WITHIN THE COMPILER
__dynamic_map_check_grow :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, loc := #caller_location) -> (err: Allocator_Error, has_grown: bool) {
if m.len >= map_resize_threshold(m^) {
@@ -871,9 +910,37 @@ __dynamic_map_set :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_In
}
result := map_insert_hash_dynamic(m, info, hash, uintptr(key), uintptr(value))
m.len += 1
if result != 0 {
m.len += 1
}
return rawptr(result)
}
__dynamic_map_set_extra_without_hash :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, key, value: rawptr, loc := #caller_location) -> (prev_key_ptr, value_ptr: rawptr) {
return __dynamic_map_set_extra(m, info, info.key_hasher(key, map_seed(m^)), key, value, loc)
}
__dynamic_map_set_extra :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, hash: Map_Hash, key, value: rawptr, loc := #caller_location) -> (prev_key_ptr, value_ptr: rawptr) {
if prev_key_ptr, value_ptr = __dynamic_map_get_key_and_value(m, info, hash, key); value_ptr != nil {
intrinsics.mem_copy_non_overlapping(value_ptr, value, info.vs.size_of_type)
return
}
hash := hash
err, has_grown := __dynamic_map_check_grow(m, info, loc)
if err != nil {
return nil, nil
}
if has_grown {
hash = info.key_hasher(key, map_seed(m^))
}
result := map_insert_hash_dynamic(m, info, hash, uintptr(key), uintptr(value))
if result != 0 {
m.len += 1
}
return nil, rawptr(result)
}
// IMPORTANT: USED WITHIN THE COMPILER
@(private)
+1 -1
View File
@@ -1,5 +1,5 @@
//+private
//+build linux, darwin, freebsd, openbsd
//+build linux, darwin, freebsd, openbsd, netbsd, haiku
//+no-instrumentation
package runtime
+30 -11
View File
@@ -6,15 +6,34 @@ package runtime
import "base:intrinsics"
when !ODIN_TEST && !ODIN_NO_ENTRY_POINT {
@(link_name="_start", linkage="strong", require, export)
_start :: proc "c" () {
context = default_context()
#force_no_inline _startup_runtime()
intrinsics.__entry_point()
when ODIN_OS == .Orca {
@(linkage="strong", require, export)
oc_on_init :: proc "c" () {
context = default_context()
#force_no_inline _startup_runtime()
intrinsics.__entry_point()
}
@(linkage="strong", require, export)
oc_on_terminate :: proc "c" () {
context = default_context()
#force_no_inline _cleanup_runtime()
}
} else {
@(link_name="_start", linkage="strong", require, export)
_start :: proc "c" () {
context = default_context()
when ODIN_OS == .WASI {
_wasi_setup_args()
}
#force_no_inline _startup_runtime()
intrinsics.__entry_point()
}
@(link_name="_end", linkage="strong", require, export)
_end :: proc "c" () {
context = default_context()
#force_no_inline _cleanup_runtime()
}
}
@(link_name="_end", linkage="strong", require, export)
_end :: proc "c" () {
context = default_context()
#force_no_inline _cleanup_runtime()
}
}
}
+17 -1
View File
@@ -4,6 +4,8 @@ package runtime
bounds_trap :: proc "contextless" () -> ! {
when ODIN_OS == .Windows {
windows_trap_array_bounds()
} else when ODIN_OS == .Orca {
abort_ext("", "", 0, "bounds trap")
} else {
trap()
}
@@ -13,12 +15,15 @@ bounds_trap :: proc "contextless" () -> ! {
type_assertion_trap :: proc "contextless" () -> ! {
when ODIN_OS == .Windows {
windows_trap_type_assertion()
} else when ODIN_OS == .Orca {
abort_ext("", "", 0, "type assertion trap")
} else {
trap()
}
}
@(disabled=ODIN_NO_BOUNDS_CHECK)
bounds_check_error :: proc "contextless" (file: string, line, column: i32, index, count: int) {
if uint(index) < uint(count) {
return
@@ -61,6 +66,7 @@ multi_pointer_slice_handle_error :: proc "contextless" (file: string, line, colu
}
@(disabled=ODIN_NO_BOUNDS_CHECK)
multi_pointer_slice_expr_error :: proc "contextless" (file: string, line, column: i32, lo, hi: int) {
if lo <= hi {
return
@@ -68,6 +74,7 @@ multi_pointer_slice_expr_error :: proc "contextless" (file: string, line, column
multi_pointer_slice_handle_error(file, line, column, lo, hi)
}
@(disabled=ODIN_NO_BOUNDS_CHECK)
slice_expr_error_hi :: proc "contextless" (file: string, line, column: i32, hi: int, len: int) {
if 0 <= hi && hi <= len {
return
@@ -75,6 +82,7 @@ slice_expr_error_hi :: proc "contextless" (file: string, line, column: i32, hi:
slice_handle_error(file, line, column, 0, hi, len)
}
@(disabled=ODIN_NO_BOUNDS_CHECK)
slice_expr_error_lo_hi :: proc "contextless" (file: string, line, column: i32, lo, hi: int, len: int) {
if 0 <= lo && lo <= len && lo <= hi && hi <= len {
return
@@ -82,6 +90,7 @@ slice_expr_error_lo_hi :: proc "contextless" (file: string, line, column: i32, l
slice_handle_error(file, line, column, lo, hi, len)
}
@(disabled=ODIN_NO_BOUNDS_CHECK)
dynamic_array_expr_error :: proc "contextless" (file: string, line, column: i32, low, high, max: int) {
if 0 <= low && low <= high && high <= max {
return
@@ -102,6 +111,7 @@ dynamic_array_expr_error :: proc "contextless" (file: string, line, column: i32,
}
@(disabled=ODIN_NO_BOUNDS_CHECK)
matrix_bounds_check_error :: proc "contextless" (file: string, line, column: i32, row_index, column_index, row_count, column_count: int) {
if uint(row_index) < uint(row_count) &&
uint(column_index) < uint(column_count) {
@@ -224,6 +234,7 @@ when ODIN_NO_RTTI {
}
@(disabled=ODIN_NO_BOUNDS_CHECK)
make_slice_error_loc :: #force_inline proc "contextless" (loc := #caller_location, len: int) {
if 0 <= len {
return
@@ -239,6 +250,7 @@ make_slice_error_loc :: #force_inline proc "contextless" (loc := #caller_locatio
handle_error(loc, len)
}
@(disabled=ODIN_NO_BOUNDS_CHECK)
make_dynamic_array_error_loc :: #force_inline proc "contextless" (loc := #caller_location, len, cap: int) {
if 0 <= len && len <= cap {
return
@@ -256,6 +268,7 @@ make_dynamic_array_error_loc :: #force_inline proc "contextless" (loc := #caller
handle_error(loc, len, cap)
}
@(disabled=ODIN_NO_BOUNDS_CHECK)
make_map_expr_error_loc :: #force_inline proc "contextless" (loc := #caller_location, cap: int) {
if 0 <= cap {
return
@@ -274,19 +287,22 @@ make_map_expr_error_loc :: #force_inline proc "contextless" (loc := #caller_loca
@(disabled=ODIN_NO_BOUNDS_CHECK)
bounds_check_error_loc :: #force_inline proc "contextless" (loc := #caller_location, index, count: int) {
bounds_check_error(loc.file_path, loc.line, loc.column, index, count)
}
@(disabled=ODIN_NO_BOUNDS_CHECK)
slice_expr_error_hi_loc :: #force_inline proc "contextless" (loc := #caller_location, hi: int, len: int) {
slice_expr_error_hi(loc.file_path, loc.line, loc.column, hi, len)
}
@(disabled=ODIN_NO_BOUNDS_CHECK)
slice_expr_error_lo_hi_loc :: #force_inline proc "contextless" (loc := #caller_location, lo, hi: int, len: int) {
slice_expr_error_lo_hi(loc.file_path, loc.line, loc.column, lo, hi, len)
}
@(disabled=ODIN_NO_BOUNDS_CHECK)
dynamic_array_expr_error_loc :: #force_inline proc "contextless" (loc := #caller_location, low, high, max: int) {
dynamic_array_expr_error(loc.file_path, loc.line, loc.column, low, high, max)
}
+3 -3
View File
@@ -97,14 +97,14 @@ heap_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
}
heap_alloc :: proc(size: int, zero_memory := true) -> rawptr {
heap_alloc :: proc "contextless" (size: int, zero_memory := true) -> rawptr {
return _heap_alloc(size, zero_memory)
}
heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
heap_resize :: proc "contextless" (ptr: rawptr, new_size: int) -> rawptr {
return _heap_resize(ptr, new_size)
}
heap_free :: proc(ptr: rawptr) {
heap_free :: proc "contextless" (ptr: rawptr) {
_heap_free(ptr)
}
+29
View File
@@ -0,0 +1,29 @@
//+build orca
//+private
package runtime
foreign {
@(link_name="malloc") _orca_malloc :: proc "c" (size: int) -> rawptr ---
@(link_name="calloc") _orca_calloc :: proc "c" (num, size: int) -> rawptr ---
@(link_name="free") _orca_free :: proc "c" (ptr: rawptr) ---
@(link_name="realloc") _orca_realloc :: proc "c" (ptr: rawptr, size: int) -> rawptr ---
}
_heap_alloc :: proc "contextless" (size: int, zero_memory := true) -> rawptr {
if size <= 0 {
return nil
}
if zero_memory {
return _orca_calloc(1, size)
} else {
return _orca_malloc(size)
}
}
_heap_resize :: proc "contextless" (ptr: rawptr, new_size: int) -> rawptr {
return _orca_realloc(ptr, new_size)
}
_heap_free :: proc "contextless" (ptr: rawptr) {
_orca_free(ptr)
}
+7 -4
View File
@@ -2,14 +2,17 @@
//+private
package runtime
_heap_alloc :: proc(size: int, zero_memory := true) -> rawptr {
_heap_alloc :: proc "contextless" (size: int, zero_memory := true) -> rawptr {
context = default_context()
unimplemented("base:runtime 'heap_alloc' procedure is not supported on this platform")
}
_heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
_heap_resize :: proc "contextless" (ptr: rawptr, new_size: int) -> rawptr {
context = default_context()
unimplemented("base:runtime 'heap_resize' procedure is not supported on this platform")
}
_heap_free :: proc(ptr: rawptr) {
_heap_free :: proc "contextless" (ptr: rawptr) {
context = default_context()
unimplemented("base:runtime 'heap_free' procedure is not supported on this platform")
}
}
+5 -5
View File
@@ -1,4 +1,4 @@
//+build linux, darwin, freebsd, openbsd
//+build linux, darwin, freebsd, openbsd, netbsd, haiku
//+private
package runtime
@@ -16,7 +16,7 @@ foreign libc {
@(link_name="realloc") _unix_realloc :: proc(ptr: rawptr, size: int) -> rawptr ---
}
_heap_alloc :: proc(size: int, zero_memory := true) -> rawptr {
_heap_alloc :: proc "contextless" (size: int, zero_memory := true) -> rawptr {
if size <= 0 {
return nil
}
@@ -27,12 +27,12 @@ _heap_alloc :: proc(size: int, zero_memory := true) -> rawptr {
}
}
_heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
_heap_resize :: proc "contextless" (ptr: rawptr, new_size: int) -> rawptr {
// NOTE: _unix_realloc doesn't guarantee new memory will be zeroed on
// POSIX platforms. Ensure your caller takes this into account.
return _unix_realloc(ptr, new_size)
}
_heap_free :: proc(ptr: rawptr) {
_heap_free :: proc "contextless" (ptr: rawptr) {
_unix_free(ptr)
}
}
+3 -3
View File
@@ -14,11 +14,11 @@ foreign kernel32 {
HeapFree :: proc(hHeap: rawptr, dwFlags: u32, lpMem: rawptr) -> b32 ---
}
_heap_alloc :: proc(size: int, zero_memory := true) -> rawptr {
_heap_alloc :: proc "contextless" (size: int, zero_memory := true) -> rawptr {
HEAP_ZERO_MEMORY :: 0x00000008
return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY if zero_memory else 0, uint(size))
}
_heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
_heap_resize :: proc "contextless" (ptr: rawptr, new_size: int) -> rawptr {
if new_size == 0 {
_heap_free(ptr)
return nil
@@ -30,7 +30,7 @@ _heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
HEAP_ZERO_MEMORY :: 0x00000008
return HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ptr, uint(new_size))
}
_heap_free :: proc(ptr: rawptr) {
_heap_free :: proc "contextless" (ptr: rawptr) {
if ptr == nil {
return
}
+94 -34
View File
@@ -1,3 +1,4 @@
//+vet !cast
package runtime
import "base:intrinsics"
@@ -11,7 +12,7 @@ RUNTIME_LINKAGE :: "strong" when (
ODIN_BUILD_MODE == .Dynamic ||
!ODIN_NO_CRT) &&
!IS_WASM) else "internal"
RUNTIME_REQUIRE :: !ODIN_TILDE
RUNTIME_REQUIRE :: false // !ODIN_TILDE
@(private)
__float16 :: f16 when __ODIN_LLVM_F16_SUPPORTED else u16
@@ -22,14 +23,14 @@ byte_slice :: #force_inline proc "contextless" (data: rawptr, len: int) -> []byt
return ([^]byte)(data)[:max(len, 0)]
}
is_power_of_two_int :: #force_inline proc(x: int) -> bool {
is_power_of_two_int :: #force_inline proc "contextless" (x: int) -> bool {
if x <= 0 {
return false
}
return (x & (x-1)) == 0
}
align_forward_int :: #force_inline proc(ptr, align: int) -> int {
align_forward_int :: #force_inline proc "odin" (ptr, align: int) -> int {
assert(is_power_of_two_int(align))
p := ptr
@@ -40,14 +41,32 @@ align_forward_int :: #force_inline proc(ptr, align: int) -> int {
return p
}
is_power_of_two_uintptr :: #force_inline proc(x: uintptr) -> bool {
is_power_of_two_uint :: #force_inline proc "contextless" (x: uint) -> bool {
if x <= 0 {
return false
}
return (x & (x-1)) == 0
}
align_forward_uintptr :: #force_inline proc(ptr, align: uintptr) -> uintptr {
align_forward_uint :: #force_inline proc "odin" (ptr, align: uint) -> uint {
assert(is_power_of_two_uint(align))
p := ptr
modulo := p & (align-1)
if modulo != 0 {
p += align - modulo
}
return p
}
is_power_of_two_uintptr :: #force_inline proc "contextless" (x: uintptr) -> bool {
if x <= 0 {
return false
}
return (x & (x-1)) == 0
}
align_forward_uintptr :: #force_inline proc "odin" (ptr, align: uintptr) -> uintptr {
assert(is_power_of_two_uintptr(align))
p := ptr
@@ -58,6 +77,18 @@ align_forward_uintptr :: #force_inline proc(ptr, align: uintptr) -> uintptr {
return p
}
is_power_of_two :: proc {
is_power_of_two_int,
is_power_of_two_uint,
is_power_of_two_uintptr,
}
align_forward :: proc {
align_forward_int,
align_forward_uint,
align_forward_uintptr,
}
mem_zero :: proc "contextless" (data: rawptr, len: int) -> rawptr {
if data == nil {
return nil
@@ -453,7 +484,7 @@ quaternion256_ne :: #force_inline proc "contextless" (a, b: quaternion256) -> bo
string_decode_rune :: #force_inline proc "contextless" (s: string) -> (rune, int) {
// NOTE(bill): Duplicated here to remove dependency on package unicode/utf8
@static accept_sizes := [256]u8{
@(static, rodata) accept_sizes := [256]u8{
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x00-0x0f
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x10-0x1f
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x20-0x2f
@@ -474,7 +505,7 @@ string_decode_rune :: #force_inline proc "contextless" (s: string) -> (rune, int
}
Accept_Range :: struct {lo, hi: u8}
@static accept_ranges := [5]Accept_Range{
@(static, rodata) accept_ranges := [5]Accept_Range{
{0x80, 0xbf},
{0xa0, 0xbf},
{0x80, 0x9f},
@@ -612,21 +643,24 @@ abs_quaternion256 :: #force_inline proc "contextless" (x: quaternion256) -> f64
quo_complex32 :: proc "contextless" (n, m: complex32) -> complex32 {
e, f: f16
nr, ni := f32(real(n)), f32(imag(n))
mr, mi := f32(real(m)), f32(imag(m))
if abs(real(m)) >= abs(imag(m)) {
ratio := imag(m) / real(m)
denom := real(m) + ratio*imag(m)
e = (real(n) + imag(n)*ratio) / denom
f = (imag(n) - real(n)*ratio) / denom
e, f: f32
if abs(mr) >= abs(mi) {
ratio := mi / mr
denom := mr + ratio*mi
e = (nr + ni*ratio) / denom
f = (ni - nr*ratio) / denom
} else {
ratio := real(m) / imag(m)
denom := imag(m) + ratio*real(m)
e = (real(n)*ratio + imag(n)) / denom
f = (imag(n)*ratio - real(n)) / denom
ratio := mr / mi
denom := mi + ratio*mr
e = (nr*ratio + ni) / denom
f = (ni*ratio - nr) / denom
}
return complex(e, f)
return complex(f16(e), f16(f))
}
@@ -667,15 +701,15 @@ quo_complex128 :: proc "contextless" (n, m: complex128) -> complex128 {
}
mul_quaternion64 :: proc "contextless" (q, r: quaternion64) -> quaternion64 {
q0, q1, q2, q3 := real(q), imag(q), jmag(q), kmag(q)
r0, r1, r2, r3 := real(r), imag(r), jmag(r), kmag(r)
q0, q1, q2, q3 := f32(real(q)), f32(imag(q)), f32(jmag(q)), f32(kmag(q))
r0, r1, r2, r3 := f32(real(r)), f32(imag(r)), f32(jmag(r)), f32(kmag(r))
t0 := r0*q0 - r1*q1 - r2*q2 - r3*q3
t1 := r0*q1 + r1*q0 - r2*q3 + r3*q2
t2 := r0*q2 + r1*q3 + r2*q0 - r3*q1
t3 := r0*q3 - r1*q2 + r2*q1 + r3*q0
return quaternion(w=t0, x=t1, y=t2, z=t3)
return quaternion(w=f16(t0), x=f16(t1), y=f16(t2), z=f16(t3))
}
mul_quaternion128 :: proc "contextless" (q, r: quaternion128) -> quaternion128 {
@@ -703,8 +737,8 @@ mul_quaternion256 :: proc "contextless" (q, r: quaternion256) -> quaternion256 {
}
quo_quaternion64 :: proc "contextless" (q, r: quaternion64) -> quaternion64 {
q0, q1, q2, q3 := real(q), imag(q), jmag(q), kmag(q)
r0, r1, r2, r3 := real(r), imag(r), jmag(r), kmag(r)
q0, q1, q2, q3 := f32(real(q)), f32(imag(q)), f32(jmag(q)), f32(kmag(q))
r0, r1, r2, r3 := f32(real(r)), f32(imag(r)), f32(jmag(r)), f32(kmag(r))
invmag2 := 1.0 / (r0*r0 + r1*r1 + r2*r2 + r3*r3)
@@ -713,7 +747,7 @@ quo_quaternion64 :: proc "contextless" (q, r: quaternion64) -> quaternion64 {
t2 := (r0*q2 - r1*q3 - r2*q0 + r3*q1) * invmag2
t3 := (r0*q3 + r1*q2 + r2*q1 - r3*q0) * invmag2
return quaternion(w=t0, x=t1, y=t2, z=t3)
return quaternion(w=f16(t0), x=f16(t1), y=f16(t2), z=f16(t3))
}
quo_quaternion128 :: proc "contextless" (q, r: quaternion128) -> quaternion128 {
@@ -801,6 +835,10 @@ truncsfhf2 :: proc "c" (value: f32) -> __float16 {
}
}
@(link_name="__aeabi_d2h", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
aeabi_d2h :: proc "c" (value: f64) -> __float16 {
return truncsfhf2(f32(value))
}
@(link_name="__truncdfhf2", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
truncdfhf2 :: proc "c" (value: f64) -> __float16 {
@@ -962,9 +1000,11 @@ udivmodti4 :: proc "c" (a, b: u128, rem: ^u128) -> u128 {
return udivmod128(a, b, rem)
}
@(link_name="__udivti3", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
udivti3 :: proc "c" (a, b: u128) -> u128 {
return udivmodti4(a, b, nil)
when !IS_WASM {
@(link_name="__udivti3", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
udivti3 :: proc "c" (a, b: u128) -> u128 {
return udivmodti4(a, b, nil)
}
}
@@ -976,26 +1016,26 @@ modti3 :: proc "c" (a, b: i128) -> i128 {
bn := (b ~ s_b) - s_b
r: u128 = ---
_ = udivmod128(transmute(u128)an, transmute(u128)bn, &r)
return (transmute(i128)r ~ s_a) - s_a
_ = udivmod128(u128(an), u128(bn), &r)
return (i128(r) ~ s_a) - s_a
}
@(link_name="__divmodti4", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
divmodti4 :: proc "c" (a, b: i128, rem: ^i128) -> i128 {
u := udivmod128(transmute(u128)a, transmute(u128)b, cast(^u128)rem)
return transmute(i128)u
u := udivmod128(u128(a), u128(b), (^u128)(rem))
return i128(u)
}
@(link_name="__divti3", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
divti3 :: proc "c" (a, b: i128) -> i128 {
u := udivmodti4(transmute(u128)a, transmute(u128)b, nil)
return transmute(i128)u
u := udivmodti4(u128(a), u128(b), nil)
return i128(u)
}
@(link_name="__fixdfti", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
fixdfti :: proc(a: u64) -> i128 {
fixdfti :: proc "c" (a: u64) -> i128 {
significandBits :: 52
typeWidth :: (size_of(u64)*8)
exponentBits :: (typeWidth - significandBits - 1)
@@ -1034,3 +1074,23 @@ fixdfti :: proc(a: u64) -> i128 {
}
}
__write_bits :: proc "contextless" (dst, src: [^]byte, offset: uintptr, size: uintptr) {
for i in 0..<size {
j := offset+i
the_bit := byte((src[i>>3]) & (1<<(i&7)) != 0)
dst[j>>3] &~= 1<<(j&7)
dst[j>>3] |= the_bit<<(j&7)
}
}
__read_bits :: proc "contextless" (dst, src: [^]byte, offset: uintptr, size: uintptr) {
for j in 0..<size {
i := offset+j
the_bit := byte((src[i>>3]) & (1<<(i&7)) != 0)
dst[j>>3] &~= 1<<(j&7)
dst[j>>3] |= the_bit<<(j&7)
}
}
+6 -2
View File
@@ -1,4 +1,4 @@
//+build freebsd, openbsd
//+build freebsd, openbsd, netbsd
//+private
package runtime
@@ -9,7 +9,11 @@ foreign libc {
@(link_name="write")
_unix_write :: proc(fd: i32, buf: rawptr, size: int) -> int ---
__error :: proc() -> ^i32 ---
when ODIN_OS == .NetBSD {
@(link_name="__errno") __error :: proc() -> ^i32 ---
} else {
__error :: proc() -> ^i32 ---
}
}
_stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
+6 -17
View File
@@ -2,25 +2,14 @@
//+private
package runtime
foreign import libc "system:System.framework"
@(default_calling_convention="c")
foreign libc {
@(link_name="__stderrp")
_stderr: rawptr
@(link_name="fwrite")
_fwrite :: proc(ptr: rawptr, size: uint, nmemb: uint, stream: rawptr) -> uint ---
@(link_name="__error")
_get_errno :: proc() -> ^i32 ---
}
import "base:intrinsics"
_stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
ret := _fwrite(raw_data(data), 1, len(data), _stderr)
if ret < len(data) {
err := _get_errno()
return int(ret), _OS_Errno(err^ if err != nil else 0)
WRITE :: 0x2000004
STDERR :: 2
ret := intrinsics.syscall(WRITE, STDERR, uintptr(raw_data(data)), uintptr(len(data)))
if ret < 0 {
return 0, _OS_Errno(-ret)
}
return int(ret), 0
}
+21
View File
@@ -0,0 +1,21 @@
//+build haiku
//+private
package runtime
foreign import libc "system:c"
foreign libc {
@(link_name="write")
_unix_write :: proc(fd: i32, buf: rawptr, size: int) -> int ---
_errnop :: proc() -> ^i32 ---
}
_stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
ret := _unix_write(2, raw_data(data), len(data))
if ret < len(data) {
err := _errnop()
return int(ret), _OS_Errno(err^ if err != nil else 0)
}
return int(ret), 0
}
+43
View File
@@ -0,0 +1,43 @@
//+build orca
//+private
package runtime
import "base:intrinsics"
// Constants allowing to specify the level of logging verbosity.
log_level :: enum u32 {
// Only errors are logged.
ERROR = 0,
// Only warnings and errors are logged.
WARNING = 1,
// All messages are logged.
INFO = 2,
COUNT = 3,
}
@(default_calling_convention="c", link_prefix="oc_")
foreign {
abort_ext :: proc(file: cstring, function: cstring, line: i32, fmt: cstring, #c_vararg args: ..any) -> ! ---
assert_fail :: proc(file: cstring, function: cstring, line: i32, src: cstring, fmt: cstring, #c_vararg args: ..any) -> ! ---
log_ext :: proc(level: log_level, function: cstring, file: cstring, line: i32, fmt: cstring, #c_vararg args: ..any) ---
}
// NOTE: This is all pretty gross, don't look.
// WASM is single threaded so this should be fine.
orca_stderr_buffer: [4096]byte
orca_stderr_buffer_idx: int
_stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
for b in data {
orca_stderr_buffer[orca_stderr_buffer_idx] = b
orca_stderr_buffer_idx += 1
if b == '\n' || orca_stderr_buffer_idx == len(orca_stderr_buffer)-1 {
log_ext(.ERROR, "", "", 0, cstring(raw_data(orca_stderr_buffer[:orca_stderr_buffer_idx])))
orca_stderr_buffer_idx = 0
}
}
return len(data), 0
}
+47 -3
View File
@@ -2,10 +2,54 @@
//+private
package runtime
import "core:sys/wasm/wasi"
foreign import wasi "wasi_snapshot_preview1"
@(default_calling_convention="contextless")
foreign wasi {
fd_write :: proc(
fd: i32,
iovs: [][]byte,
n: ^uint,
) -> u16 ---
@(private="file")
args_sizes_get :: proc(
num_of_args: ^uint,
size_of_args: ^uint,
) -> u16 ---
@(private="file")
args_get :: proc(
argv: [^]cstring,
argv_buf: [^]byte,
) -> u16 ---
}
_stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
data := (wasi.ciovec_t)(data)
n, err := wasi.fd_write(1, {data})
n: uint
err := fd_write(1, {data}, &n)
return int(n), _OS_Errno(err)
}
_wasi_setup_args :: proc() {
num_of_args, size_of_args: uint
if errno := args_sizes_get(&num_of_args, &size_of_args); errno != 0 {
return
}
err: Allocator_Error
if args__, err = make([]cstring, num_of_args); err != nil {
return
}
args_buf: []byte
if args_buf, err = make([]byte, size_of_args); err != nil {
delete(args__)
return
}
if errno := args_get(raw_data(args__), raw_data(args_buf)); errno != 0 {
delete(args__)
delete(args_buf)
}
}
+36 -16
View File
@@ -6,7 +6,7 @@ _INTEGER_DIGITS :: "0123456789abcdefghijklmnopqrstuvwxyz"
_INTEGER_DIGITS_VAR := _INTEGER_DIGITS
when !ODIN_NO_RTTI {
print_any_single :: proc "contextless" (arg: any) {
print_any_single :: #force_no_inline proc "contextless" (arg: any) {
x := arg
if x.data == nil {
print_string("nil")
@@ -72,7 +72,7 @@ when !ODIN_NO_RTTI {
print_string("<invalid-value>")
}
}
println_any :: proc "contextless" (args: ..any) {
println_any :: #force_no_inline proc "contextless" (args: ..any) {
context = default_context()
loop: for arg, i in args {
assert(arg.id != nil)
@@ -122,12 +122,12 @@ encode_rune :: proc "contextless" (c: rune) -> ([4]u8, int) {
return buf, 4
}
print_string :: proc "contextless" (str: string) -> (n: int) {
print_string :: #force_no_inline proc "contextless" (str: string) -> (n: int) {
n, _ = stderr_write(transmute([]byte)str)
return
}
print_strings :: proc "contextless" (args: ..string) -> (n: int) {
print_strings :: #force_no_inline proc "contextless" (args: ..string) -> (n: int) {
for str in args {
m, err := stderr_write(transmute([]byte)str)
n += m
@@ -138,12 +138,12 @@ print_strings :: proc "contextless" (args: ..string) -> (n: int) {
return
}
print_byte :: proc "contextless" (b: byte) -> (n: int) {
print_byte :: #force_no_inline proc "contextless" (b: byte) -> (n: int) {
n, _ = stderr_write([]byte{b})
return
}
print_encoded_rune :: proc "contextless" (r: rune) {
print_encoded_rune :: #force_no_inline proc "contextless" (r: rune) {
print_byte('\'')
switch r {
@@ -170,7 +170,7 @@ print_encoded_rune :: proc "contextless" (r: rune) {
print_byte('\'')
}
print_rune :: proc "contextless" (r: rune) -> int #no_bounds_check {
print_rune :: #force_no_inline proc "contextless" (r: rune) -> int #no_bounds_check {
RUNE_SELF :: 0x80
if r < RUNE_SELF {
@@ -183,7 +183,7 @@ print_rune :: proc "contextless" (r: rune) -> int #no_bounds_check {
}
print_u64 :: proc "contextless" (x: u64) #no_bounds_check {
print_u64 :: #force_no_inline proc "contextless" (x: u64) #no_bounds_check {
a: [129]byte
i := len(a)
b := u64(10)
@@ -198,7 +198,7 @@ print_u64 :: proc "contextless" (x: u64) #no_bounds_check {
}
print_i64 :: proc "contextless" (x: i64) #no_bounds_check {
print_i64 :: #force_no_inline proc "contextless" (x: i64) #no_bounds_check {
b :: i64(10)
u := x
@@ -223,25 +223,29 @@ print_uint :: proc "contextless" (x: uint) { print_u64(u64(x)) }
print_uintptr :: proc "contextless" (x: uintptr) { print_u64(u64(x)) }
print_int :: proc "contextless" (x: int) { print_i64(i64(x)) }
print_caller_location :: proc "contextless" (loc: Source_Code_Location) {
print_caller_location :: #force_no_inline proc "contextless" (loc: Source_Code_Location) {
print_string(loc.file_path)
when ODIN_ERROR_POS_STYLE == .Default {
print_byte('(')
print_u64(u64(loc.line))
print_byte(':')
print_u64(u64(loc.column))
if loc.column != 0 {
print_byte(':')
print_u64(u64(loc.column))
}
print_byte(')')
} else when ODIN_ERROR_POS_STYLE == .Unix {
print_byte(':')
print_u64(u64(loc.line))
print_byte(':')
print_u64(u64(loc.column))
if loc.column != 0 {
print_byte(':')
print_u64(u64(loc.column))
}
print_byte(':')
} else {
#panic("unhandled ODIN_ERROR_POS_STYLE")
}
}
print_typeid :: proc "contextless" (id: typeid) {
print_typeid :: #force_no_inline proc "contextless" (id: typeid) {
when ODIN_NO_RTTI {
if id == nil {
print_string("nil")
@@ -257,7 +261,9 @@ print_typeid :: proc "contextless" (id: typeid) {
}
}
}
print_type :: proc "contextless" (ti: ^Type_Info) {
@(optimization_mode="size")
print_type :: #force_no_inline proc "contextless" (ti: ^Type_Info) {
if ti == nil {
print_string("nil")
return
@@ -459,6 +465,20 @@ print_type :: proc "contextless" (ti: ^Type_Info) {
}
print_byte(']')
case Type_Info_Bit_Field:
print_string("bit_field ")
print_type(info.backing_type)
print_string(" {")
for name, i in info.names {
if i > 0 { print_string(", ") }
print_string(name)
print_string(": ")
print_type(info.types[i])
print_string(" | ")
print_u64(u64(info.bit_sizes[i]))
}
print_byte('}')
case Type_Info_Simd_Vector:
print_string("#simd[")
+16 -10
View File
@@ -25,13 +25,19 @@ when ODIN_NO_CRT && ODIN_OS == .Windows {
RtlMoveMemory(dst, src, len)
return dst
}
} else when ODIN_NO_CRT || (ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32) {
} else when ODIN_NO_CRT || (ODIN_OS != .Orca && (ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32)) {
// NOTE: on wasm, calls to these procs are generated (by LLVM) with type `i32` instead of `int`.
//
// NOTE: `#any_int` is also needed, because calls that we generate (and package code)
// will be using `int` and need to be converted.
int_t :: i32 when ODIN_ARCH == .wasm64p32 else int
@(link_name="memset", linkage="strong", require)
memset :: proc "c" (ptr: rawptr, val: i32, len: int) -> rawptr {
memset :: proc "c" (ptr: rawptr, val: i32, #any_int len: int_t) -> rawptr {
if ptr != nil && len != 0 {
b := byte(val)
p := ([^]byte)(ptr)
for i := 0; i < len; i += 1 {
for i := int_t(0); i < len; i += 1 {
p[i] = b
}
}
@@ -39,10 +45,10 @@ when ODIN_NO_CRT && ODIN_OS == .Windows {
}
@(link_name="bzero", linkage="strong", require)
bzero :: proc "c" (ptr: rawptr, len: int) -> rawptr {
bzero :: proc "c" (ptr: rawptr, #any_int len: int_t) -> rawptr {
if ptr != nil && len != 0 {
p := ([^]byte)(ptr)
for i := 0; i < len; i += 1 {
for i := int_t(0); i < len; i += 1 {
p[i] = 0
}
}
@@ -50,7 +56,7 @@ when ODIN_NO_CRT && ODIN_OS == .Windows {
}
@(link_name="memmove", linkage="strong", require)
memmove :: proc "c" (dst, src: rawptr, len: int) -> rawptr {
memmove :: proc "c" (dst, src: rawptr, #any_int len: int_t) -> rawptr {
d, s := ([^]byte)(dst), ([^]byte)(src)
if d == s || len == 0 {
return dst
@@ -63,7 +69,7 @@ when ODIN_NO_CRT && ODIN_OS == .Windows {
}
if s > d && uintptr(s)-uintptr(d) < uintptr(len) {
for i := 0; i < len; i += 1 {
for i := int_t(0); i < len; i += 1 {
d[i] = s[i]
}
return dst
@@ -71,10 +77,10 @@ when ODIN_NO_CRT && ODIN_OS == .Windows {
return memcpy(dst, src, len)
}
@(link_name="memcpy", linkage="strong", require)
memcpy :: proc "c" (dst, src: rawptr, len: int) -> rawptr {
memcpy :: proc "c" (dst, src: rawptr, #any_int len: int_t) -> rawptr {
d, s := ([^]byte)(dst), ([^]byte)(src)
if d != s {
for i := 0; i < len; i += 1 {
for i := int_t(0); i < len; i += 1 {
d[i] = s[i]
}
}
@@ -92,4 +98,4 @@ when ODIN_NO_CRT && ODIN_OS == .Windows {
}
return ptr
}
}
}
+22 -8
View File
@@ -7,19 +7,25 @@ ti_int :: struct #raw_union {
all: i128,
}
@(private="file")
ti_uint :: struct #raw_union {
using s: struct { lo, hi: u64 },
all: u128,
}
@(link_name="__ashlti3", linkage="strong")
__ashlti3 :: proc "contextless" (a: i128, b_: u32) -> i128 {
__ashlti3 :: proc "contextless" (la, ha: u64, b_: u32) -> i128 {
bits_in_dword :: size_of(u32)*8
b := u32(b_)
input, result: ti_int
input.all = a
input.lo, input.hi = la, ha
if b & bits_in_dword != 0 {
result.lo = 0
result.hi = input.lo << (b-bits_in_dword)
} else {
if b == 0 {
return a
return input.all
}
result.lo = input.lo<<b
result.hi = (input.hi<<b) | (input.lo>>(bits_in_dword-b))
@@ -29,12 +35,20 @@ __ashlti3 :: proc "contextless" (a: i128, b_: u32) -> i128 {
@(link_name="__multi3", linkage="strong")
__multi3 :: proc "contextless" (a, b: i128) -> i128 {
__multi3 :: proc "contextless" (la, ha, lb, hb: u64) -> i128 {
x, y, r: ti_int
x.all = a
y.all = b
x.lo, x.hi = la, ha
y.lo, y.hi = lb, hb
r.all = i128(x.lo * y.lo) // TODO this is incorrect
r.hi += x.hi*y.lo + x.lo*y.hi
return r.all
}
}
@(link_name="__udivti3", linkage="strong")
udivti3 :: proc "c" (la, ha, lb, hb: u64) -> u128 {
a, b: ti_uint
a.lo, a.hi = la, ha
b.lo, b.hi = lb, hb
return udivmodti4(a.all, b.all, nil)
}
+127
View File
@@ -0,0 +1,127 @@
package runtime
import "base:intrinsics"
@(require_results)
random_generator_read_bytes :: proc(rg: Random_Generator, p: []byte) -> bool {
if rg.procedure != nil {
rg.procedure(rg.data, .Read, p)
return true
}
return false
}
@(require_results)
random_generator_read_ptr :: proc(rg: Random_Generator, p: rawptr, len: uint) -> bool {
if rg.procedure != nil {
rg.procedure(rg.data, .Read, ([^]byte)(p)[:len])
return true
}
return false
}
@(require_results)
random_generator_query_info :: proc(rg: Random_Generator) -> (info: Random_Generator_Query_Info) {
if rg.procedure != nil {
rg.procedure(rg.data, .Query_Info, ([^]byte)(&info)[:size_of(info)])
}
return
}
random_generator_reset_bytes :: proc(rg: Random_Generator, p: []byte) {
if rg.procedure != nil {
rg.procedure(rg.data, .Reset, p)
}
}
random_generator_reset_u64 :: proc(rg: Random_Generator, p: u64) {
if rg.procedure != nil {
p := p
rg.procedure(rg.data, .Reset, ([^]byte)(&p)[:size_of(p)])
}
}
Default_Random_State :: struct {
state: u64,
inc: u64,
}
default_random_generator_proc :: proc(data: rawptr, mode: Random_Generator_Mode, p: []byte) {
@(require_results)
read_u64 :: proc "contextless" (r: ^Default_Random_State) -> u64 {
old_state := r.state
r.state = old_state * 6364136223846793005 + (r.inc|1)
xor_shifted := (((old_state >> 59) + 5) ~ old_state) * 12605985483714917081
rot := (old_state >> 59)
return (xor_shifted >> rot) | (xor_shifted << ((-rot) & 63))
}
@(thread_local)
global_rand_seed: Default_Random_State
init :: proc "contextless" (r: ^Default_Random_State, seed: u64) {
seed := seed
if seed == 0 {
seed = u64(intrinsics.read_cycle_counter())
}
r.state = 0
r.inc = (seed << 1) | 1
_ = read_u64(r)
r.state += seed
_ = read_u64(r)
}
r: ^Default_Random_State = ---
if data == nil {
r = &global_rand_seed
} else {
r = cast(^Default_Random_State)data
}
switch mode {
case .Read:
if r.state == 0 && r.inc == 0 {
init(r, 0)
}
switch len(p) {
case size_of(u64):
// Fast path for a 64-bit destination.
intrinsics.unaligned_store((^u64)(raw_data(p)), read_u64(r))
case:
// All other cases.
pos := i8(0)
val := u64(0)
for &v in p {
if pos == 0 {
val = read_u64(r)
pos = 7
}
v = byte(val)
val >>= 8
pos -= 1
}
}
case .Reset:
seed: u64
mem_copy_non_overlapping(&seed, raw_data(p), min(size_of(seed), len(p)))
init(r, seed)
case .Query_Info:
if len(p) != size_of(Random_Generator_Query_Info) {
return
}
info := (^Random_Generator_Query_Info)(raw_data(p))
info^ += {.Uniform, .Resettable}
}
}
default_random_generator :: proc "contextless" (state: ^Default_Random_State = nil) -> Random_Generator {
return {
procedure = default_random_generator_proc,
data = state,
}
}
+3 -3
View File
@@ -58,7 +58,7 @@ udivmod128 :: proc "c" (a, b: u128, rem: ^u128) -> u128 {
return u128(n[high] >> _ctz(d[high]))
}
sr = transmute(u32)(i32(_clz(d[high])) - i32(_clz(n[high])))
sr = u32(i32(_clz(d[high])) - i32(_clz(n[high])))
if sr > U64_BITS - 2 {
if rem != nil {
rem^ = a
@@ -107,7 +107,7 @@ udivmod128 :: proc "c" (a, b: u128, rem: ^u128) -> u128 {
r[low] = n[high] >> (sr - U64_BITS)
}
} else {
sr = transmute(u32)(i32(_clz(d[high])) - i32(_clz(n[high])))
sr = u32(i32(_clz(d[high])) - i32(_clz(n[high])))
if sr > U64_BITS - 1 {
if rem != nil {
@@ -143,7 +143,7 @@ udivmod128 :: proc "c" (a, b: u128, rem: ^u128) -> u128 {
r_all = transmute(u128)r
s := i128(b - r_all - 1) >> (U128_BITS - 1)
carry = u32(s & 1)
r_all -= b & transmute(u128)s
r_all -= b & u128(s)
r = transmute([2]u64)r_all
}
+870
View File
@@ -0,0 +1,870 @@
//+build wasm32, wasm64p32
package runtime
import "base:intrinsics"
/*
Port of emmalloc, modified for use in Odin.
Invariants:
- Per-allocation header overhead is 8 bytes, smallest allocated payload
amount is 8 bytes, and a multiple of 4 bytes.
- Acquired memory blocks are subdivided into disjoint regions that lie
next to each other.
- A region is either in used or free.
Used regions may be adjacent, and a used and unused region
may be adjacent, but not two unused ones - they would be
merged.
- Memory allocation takes constant time, unless the alloc needs to wasm_memory_grow()
or memory is very close to being exhausted.
- Free and used regions are managed inside "root regions", which are slabs
of memory acquired via wasm_memory_grow().
- Memory retrieved using wasm_memory_grow() can not be given back to the OS.
Therefore, frees are internal to the allocator.
Copyright (c) 2010-2014 Emscripten authors, see AUTHORS file.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
WASM_Allocator :: struct #no_copy {
// The minimum alignment of allocations.
alignment: uint,
// A region that contains as payload a single forward linked list of pointers to
// root regions of each disjoint region blocks.
list_of_all_regions: ^Root_Region,
// For each of the buckets, maintain a linked list head node. The head node for each
// free region is a sentinel node that does not actually represent any free space, but
// the sentinel is used to avoid awkward testing against (if node == freeRegionHeadNode)
// when adding and removing elements from the linked list, i.e. we are guaranteed that
// the sentinel node is always fixed and there, and the actual free region list elements
// start at free_region_buckets[i].next each.
free_region_buckets: [NUM_FREE_BUCKETS]Region,
// A bitmask that tracks the population status for each of the 64 distinct memory regions:
// a zero at bit position i means that the free list bucket i is empty. This bitmask is
// used to avoid redundant scanning of the 64 different free region buckets: instead by
// looking at the bitmask we can find in constant time an index to a free region bucket
// that contains free memory of desired size.
free_region_buckets_used: BUCKET_BITMASK_T,
// Because wasm memory can only be allocated in pages of 64k at a time, we keep any
// spilled/unused bytes that are left from the allocated pages here, first using this
// when bytes are needed.
spill: []byte,
// Mutex for thread safety, only used if the target feature "atomics" is enabled.
mu: Mutex_State,
}
// Not required to be called, called on first allocation otherwise.
wasm_allocator_init :: proc(a: ^WASM_Allocator, alignment: uint = 8) {
assert(is_power_of_two(alignment), "alignment must be a power of two")
assert(alignment > 4, "alignment must be more than 4")
a.alignment = alignment
for i in 0..<NUM_FREE_BUCKETS {
a.free_region_buckets[i].next = &a.free_region_buckets[i]
a.free_region_buckets[i].prev = a.free_region_buckets[i].next
}
if !claim_more_memory(a, 3*size_of(Region)) {
panic("wasm_allocator: initial memory could not be allocated")
}
}
global_default_wasm_allocator_data: WASM_Allocator
default_wasm_allocator :: proc() -> Allocator {
return wasm_allocator(&global_default_wasm_allocator_data)
}
wasm_allocator :: proc(a: ^WASM_Allocator) -> Allocator {
return {
data = a,
procedure = wasm_allocator_proc,
}
}
wasm_allocator_proc :: proc(a: rawptr, mode: Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, loc := #caller_location) -> ([]byte, Allocator_Error) {
a := (^WASM_Allocator)(a)
if a == nil {
a = &global_default_wasm_allocator_data
}
if a.alignment == 0 {
wasm_allocator_init(a)
}
switch mode {
case .Alloc:
ptr := aligned_alloc(a, uint(alignment), uint(size), loc)
if ptr == nil {
return nil, .Out_Of_Memory
}
intrinsics.mem_zero(ptr, size)
return ([^]byte)(ptr)[:size], nil
case .Alloc_Non_Zeroed:
ptr := aligned_alloc(a, uint(alignment), uint(size), loc)
if ptr == nil {
return nil, .Out_Of_Memory
}
return ([^]byte)(ptr)[:size], nil
case .Resize:
ptr := aligned_realloc(a, old_memory, uint(alignment), uint(size), loc)
if ptr == nil {
return nil, .Out_Of_Memory
}
bytes := ([^]byte)(ptr)[:size]
if size > old_size {
new_region := raw_data(bytes[old_size:])
intrinsics.mem_zero(new_region, size - old_size)
}
return bytes, nil
case .Resize_Non_Zeroed:
ptr := aligned_realloc(a, old_memory, uint(alignment), uint(size), loc)
if ptr == nil {
return nil, .Out_Of_Memory
}
return ([^]byte)(ptr)[:size], nil
case .Free:
free(a, old_memory, loc)
return nil, nil
case .Free_All, .Query_Info:
return nil, .Mode_Not_Implemented
case .Query_Features:
set := (^Allocator_Mode_Set)(old_memory)
if set != nil {
set^ = {.Alloc, .Alloc_Non_Zeroed, .Free, .Resize, .Resize_Non_Zeroed, .Query_Features }
}
return nil, nil
}
unreachable()
}
// Returns the allocated size of the allocator (both free and used).
// If `nil` is given, the global allocator is used.
wasm_allocator_size :: proc(a: ^WASM_Allocator = nil) -> (size: uint) {
a := a
if a == nil {
a = &global_default_wasm_allocator_data
}
lock(a)
defer unlock(a)
root := a.list_of_all_regions
for root != nil {
size += uint(uintptr(root.end_ptr) - uintptr(root))
root = root.next
}
size += len(a.spill)
return
}
// Returns the amount of free memory on the allocator.
// If `nil` is given, the global allocator is used.
wasm_allocator_free_space :: proc(a: ^WASM_Allocator = nil) -> (free: uint) {
a := a
if a == nil {
a = &global_default_wasm_allocator_data
}
lock(a)
defer unlock(a)
bucket_index: u64 = 0
bucket_mask := a.free_region_buckets_used
for bucket_mask != 0 {
index_add := intrinsics.count_trailing_zeros(bucket_mask)
bucket_index += index_add
bucket_mask >>= index_add
for free_region := a.free_region_buckets[bucket_index].next; free_region != &a.free_region_buckets[bucket_index]; free_region = free_region.next {
free += free_region.size - REGION_HEADER_SIZE
}
bucket_index += 1
bucket_mask >>= 1
}
free += len(a.spill)
return
}
@(private="file")
NUM_FREE_BUCKETS :: 64
@(private="file")
BUCKET_BITMASK_T :: u64
// Dynamic memory is subdivided into regions, in the format
// <size:u32> ..... <size:u32> | <size:u32> ..... <size:u32> | <size:u32> ..... <size:u32> | .....
// That is, at the bottom and top end of each memory region, the size of that region is stored. That allows traversing the
// memory regions backwards and forwards. Because each allocation must be at least a multiple of 4 bytes, the lowest two bits of
// each size field is unused. Free regions are distinguished by used regions by having the FREE_REGION_FLAG bit present
// in the size field. I.e. for free regions, the size field is odd, and for used regions, the size field reads even.
@(private="file")
FREE_REGION_FLAG :: 0x1
// Attempts to alloc more than this many bytes would cause an overflow when calculating the size of a region,
// therefore allocations larger than this are short-circuited immediately on entry.
@(private="file")
MAX_ALLOC_SIZE :: 0xFFFFFFC7
// A free region has the following structure:
// <size:uint> <prevptr> <nextptr> ... <size:uint>
@(private="file")
Region :: struct {
size: uint,
prev, next: ^Region,
_at_the_end_of_this_struct_size: uint,
}
// Each memory block starts with a Root_Region at the beginning.
// The Root_Region specifies the size of the region block, and forms a linked
// list of all Root_Regions in the program, starting with `list_of_all_regions`
// below.
@(private="file")
Root_Region :: struct {
size: u32,
next: ^Root_Region,
end_ptr: ^byte,
}
@(private="file")
Mutex_State :: enum u32 {
Unlocked = 0,
Locked = 1,
Waiting = 2,
}
@(private="file")
lock :: proc(a: ^WASM_Allocator) {
when intrinsics.has_target_feature("atomics") {
@(cold)
lock_slow :: proc(a: ^WASM_Allocator, curr_state: Mutex_State) {
new_state := curr_state // Make a copy of it
spin_lock: for spin in 0..<i32(100) {
state, ok := intrinsics.atomic_compare_exchange_weak_explicit(&a.mu, .Unlocked, new_state, .Acquire, .Consume)
if ok {
return
}
if state == .Waiting {
break spin_lock
}
for i := min(spin+1, 32); i > 0; i -= 1 {
intrinsics.cpu_relax()
}
}
// Set just in case 100 iterations did not do it
new_state = .Waiting
for {
if intrinsics.atomic_exchange_explicit(&a.mu, .Waiting, .Acquire) == .Unlocked {
return
}
assert(intrinsics.wasm_memory_atomic_wait32((^u32)(&a.mu), u32(new_state), -1) != 0)
intrinsics.cpu_relax()
}
}
if v := intrinsics.atomic_exchange_explicit(&a.mu, .Locked, .Acquire); v != .Unlocked {
lock_slow(a, v)
}
}
}
@(private="file")
unlock :: proc(a: ^WASM_Allocator) {
when intrinsics.has_target_feature("atomics") {
@(cold)
unlock_slow :: proc(a: ^WASM_Allocator) {
for {
s := intrinsics.wasm_memory_atomic_notify32((^u32)(&a.mu), 1)
if s >= 1 {
return
}
}
}
switch intrinsics.atomic_exchange_explicit(&a.mu, .Unlocked, .Release) {
case .Unlocked:
unreachable()
case .Locked:
// Okay
case .Waiting:
unlock_slow(a)
}
}
}
@(private="file")
assert_locked :: proc(a: ^WASM_Allocator) {
when intrinsics.has_target_feature("atomics") {
assert(intrinsics.atomic_load(&a.mu) != .Unlocked)
}
}
@(private="file")
has_alignment_uintptr :: proc(ptr: uintptr, #any_int alignment: uintptr) -> bool {
return ptr & (alignment-1) == 0
}
@(private="file")
has_alignment_uint :: proc(ptr: uint, alignment: uint) -> bool {
return ptr & (alignment-1) == 0
}
@(private="file")
has_alignment :: proc {
has_alignment_uintptr,
has_alignment_uint,
}
@(private="file")
REGION_HEADER_SIZE :: 2*size_of(uint)
@(private="file")
SMALLEST_ALLOCATION_SIZE :: 2*size_of(rawptr)
// Subdivide regions of free space into distinct circular doubly linked lists, where each linked list
// represents a range of free space blocks. The following function compute_free_list_bucket() converts
// an allocation size to the bucket index that should be looked at.
#assert(NUM_FREE_BUCKETS == 64, "Following function is tailored specifically for the NUM_FREE_BUCKETS == 64 case")
@(private="file")
compute_free_list_bucket :: proc(size: uint) -> uint {
if size < 128 { return (size >> 3) - 1 }
clz := intrinsics.count_leading_zeros(i32(size))
bucket_index: i32 = ((clz > 19) \
? 110 - (clz<<2) + ((i32)(size >> (u32)(29-clz)) ~ 4) \
: min( 71 - (clz<<1) + ((i32)(size >> (u32)(30-clz)) ~ 2), NUM_FREE_BUCKETS-1))
assert(bucket_index >= 0)
assert(bucket_index < NUM_FREE_BUCKETS)
return uint(bucket_index)
}
@(private="file")
prev_region :: proc(region: ^Region) -> ^Region {
prev_region_size := ([^]uint)(region)[-1]
prev_region_size = prev_region_size & ~uint(FREE_REGION_FLAG)
return (^Region)(uintptr(region)-uintptr(prev_region_size))
}
@(private="file")
next_region :: proc(region: ^Region) -> ^Region {
return (^Region)(uintptr(region)+uintptr(region.size))
}
@(private="file")
region_ceiling_size :: proc(region: ^Region) -> uint {
return ([^]uint)(uintptr(region)+uintptr(region.size))[-1]
}
@(private="file")
region_is_free :: proc(r: ^Region) -> bool {
return region_ceiling_size(r) & FREE_REGION_FLAG >= 1
}
@(private="file")
region_is_in_use :: proc(r: ^Region) -> bool {
return r.size == region_ceiling_size(r)
}
@(private="file")
region_payload_start_ptr :: proc(r: ^Region) -> [^]byte {
return ([^]byte)(r)[size_of(uint):]
}
@(private="file")
region_payload_end_ptr :: proc(r: ^Region) -> [^]byte {
return ([^]byte)(r)[r.size-size_of(uint):]
}
@(private="file")
create_used_region :: proc(ptr: rawptr, size: uint) {
assert(has_alignment(uintptr(ptr), size_of(uint)))
assert(has_alignment(size, size_of(uint)))
assert(size >= size_of(Region))
uptr := ([^]uint)(ptr)
uptr[0] = size
uptr[size/size_of(uint)-1] = size
}
@(private="file")
create_free_region :: proc(ptr: rawptr, size: uint) {
assert(has_alignment(uintptr(ptr), size_of(uint)))
assert(has_alignment(size, size_of(uint)))
assert(size >= size_of(Region))
free_region := (^Region)(ptr)
free_region.size = size
([^]uint)(ptr)[size/size_of(uint)-1] = size | FREE_REGION_FLAG
}
@(private="file")
prepend_to_free_list :: proc(region: ^Region, prepend_to: ^Region) {
assert(region_is_free(region))
region.next = prepend_to
region.prev = prepend_to.prev
prepend_to.prev = region
region.prev.next = region
}
@(private="file")
unlink_from_free_list :: proc(region: ^Region) {
assert(region_is_free(region))
region.prev.next = region.next
region.next.prev = region.prev
}
@(private="file")
link_to_free_list :: proc(a: ^WASM_Allocator, free_region: ^Region) {
assert(free_region.size >= size_of(Region))
bucket_index := compute_free_list_bucket(free_region.size-REGION_HEADER_SIZE)
free_list_head := &a.free_region_buckets[bucket_index]
free_region.prev = free_list_head
free_region.next = free_list_head.next
free_list_head.next = free_region
free_region.next.prev = free_region
a.free_region_buckets_used |= BUCKET_BITMASK_T(1) << bucket_index
}
@(private="file")
claim_more_memory :: proc(a: ^WASM_Allocator, num_bytes: uint) -> bool {
PAGE_SIZE :: 64 * 1024
page_alloc :: proc(page_count: int) -> []byte {
prev_page_count := intrinsics.wasm_memory_grow(0, uintptr(page_count))
if prev_page_count < 0 { return nil }
ptr := ([^]byte)(uintptr(prev_page_count) * PAGE_SIZE)
return ptr[:page_count * PAGE_SIZE]
}
alloc :: proc(a: ^WASM_Allocator, num_bytes: uint) -> (bytes: [^]byte) #no_bounds_check {
if uint(len(a.spill)) >= num_bytes {
bytes = raw_data(a.spill[:num_bytes])
a.spill = a.spill[num_bytes:]
return
}
pages := int((num_bytes / PAGE_SIZE) + 1)
allocated := page_alloc(pages)
if allocated == nil { return nil }
// If the allocated memory is a direct continuation of the spill from before,
// we can just extend the spill.
spill_end := uintptr(raw_data(a.spill)) + uintptr(len(a.spill))
if spill_end == uintptr(raw_data(allocated)) {
raw_spill := (^Raw_Slice)(&a.spill)
raw_spill.len += len(allocated)
} else {
// Otherwise, we have to "waste" the previous spill.
// Now this is probably uncommon, and will only happen if another code path
// is also requesting pages.
a.spill = allocated
}
bytes = raw_data(a.spill)
a.spill = a.spill[num_bytes:]
return
}
num_bytes := num_bytes
num_bytes = align_forward(num_bytes, a.alignment)
start_ptr := alloc(a, uint(num_bytes))
if start_ptr == nil { return false }
assert(has_alignment(uintptr(start_ptr), align_of(uint)))
end_ptr := start_ptr[num_bytes:]
end_sentinel_region := (^Region)(end_ptr[-size_of(Region):])
create_used_region(end_sentinel_region, size_of(Region))
// If we are the sole user of wasm_memory_grow(), it will feed us continuous/consecutive memory addresses - take advantage
// of that if so: instead of creating two disjoint memory regions blocks, expand the previous one to a larger size.
prev_alloc_end_address := a.list_of_all_regions != nil ? a.list_of_all_regions.end_ptr : nil
if start_ptr == prev_alloc_end_address {
prev_end_sentinel := prev_region((^Region)(start_ptr))
assert(region_is_in_use(prev_end_sentinel))
prev_region := prev_region(prev_end_sentinel)
a.list_of_all_regions.end_ptr = end_ptr
// Two scenarios, either the last region of the previous block was in use, in which case we need to create
// a new free region in the newly allocated space; or it was free, in which case we can extend that region
// to cover a larger size.
if region_is_free(prev_region) {
new_free_region_size := uint(uintptr(end_sentinel_region) - uintptr(prev_region))
unlink_from_free_list(prev_region)
create_free_region(prev_region, new_free_region_size)
link_to_free_list(a, prev_region)
return true
}
start_ptr = start_ptr[-size_of(Region):]
} else {
create_used_region(start_ptr, size_of(Region))
new_region_block := (^Root_Region)(start_ptr)
new_region_block.next = a.list_of_all_regions
new_region_block.end_ptr = end_ptr
a.list_of_all_regions = new_region_block
start_ptr = start_ptr[size_of(Region):]
}
create_free_region(start_ptr, uint(uintptr(end_sentinel_region)-uintptr(start_ptr)))
link_to_free_list(a, (^Region)(start_ptr))
return true
}
@(private="file")
validate_alloc_size :: proc(size: uint) -> uint {
#assert(size_of(uint) >= size_of(uintptr))
#assert(size_of(uint) % size_of(uintptr) == 0)
// NOTE: emmalloc aligns this forward on pointer size, but I think that is a mistake and will
// do bad on wasm64p32.
validated_size := size > SMALLEST_ALLOCATION_SIZE ? align_forward(size, size_of(uint)) : SMALLEST_ALLOCATION_SIZE
assert(validated_size >= size) // Assert we haven't wrapped.
return validated_size
}
@(private="file")
allocate_memory :: proc(a: ^WASM_Allocator, alignment: uint, size: uint, loc := #caller_location) -> rawptr {
attempt_allocate :: proc(a: ^WASM_Allocator, free_region: ^Region, alignment, size: uint) -> rawptr {
assert_locked(a)
free_region := free_region
payload_start_ptr := uintptr(region_payload_start_ptr(free_region))
payload_start_ptr_aligned := align_forward(payload_start_ptr, uintptr(alignment))
payload_end_ptr := uintptr(region_payload_end_ptr(free_region))
if payload_start_ptr_aligned + uintptr(size) > payload_end_ptr {
return nil
}
// We have enough free space, so the memory allocation will be made into this region. Remove this free region
// from the list of free regions: whatever slop remains will be later added back to the free region pool.
unlink_from_free_list(free_region)
// Before we proceed further, fix up the boundary between this and the preceding region,
// so that the boundary between the two regions happens at a right spot for the payload to be aligned.
if payload_start_ptr != payload_start_ptr_aligned {
prev := prev_region(free_region)
assert(region_is_in_use(prev))
region_boundary_bump_amount := payload_start_ptr_aligned - payload_start_ptr
new_this_region_size := free_region.size - uint(region_boundary_bump_amount)
create_used_region(prev, prev.size + uint(region_boundary_bump_amount))
free_region = (^Region)(uintptr(free_region) + region_boundary_bump_amount)
free_region.size = new_this_region_size
}
// Next, we need to decide whether this region is so large that it should be split into two regions,
// one representing the newly used memory area, and at the high end a remaining leftover free area.
// This splitting to two is done always if there is enough space for the high end to fit a region.
// Carve 'size' bytes of payload off this region. So,
// [sz prev next sz]
// becomes
// [sz payload sz] [sz prev next sz]
if size_of(Region) + REGION_HEADER_SIZE + size <= free_region.size {
new_free_region := (^Region)(uintptr(free_region) + REGION_HEADER_SIZE + uintptr(size))
create_free_region(new_free_region, free_region.size - size - REGION_HEADER_SIZE)
link_to_free_list(a, new_free_region)
create_used_region(free_region, size + REGION_HEADER_SIZE)
} else {
// There is not enough space to split the free memory region into used+free parts, so consume the whole
// region as used memory, not leaving a free memory region behind.
// Initialize the free region as used by resetting the ceiling size to the same value as the size at bottom.
([^]uint)(uintptr(free_region) + uintptr(free_region.size))[-1] = free_region.size
}
return rawptr(uintptr(free_region) + size_of(uint))
}
assert_locked(a)
assert(is_power_of_two(alignment))
assert(size <= MAX_ALLOC_SIZE, "allocation too big", loc=loc)
alignment := alignment
alignment = max(alignment, a.alignment)
size := size
size = validate_alloc_size(size)
// Attempt to allocate memory starting from smallest bucket that can contain the required amount of memory.
// Under normal alignment conditions this should always be the first or second bucket we look at, but if
// performing an allocation with complex alignment, we may need to look at multiple buckets.
bucket_index := compute_free_list_bucket(size)
bucket_mask := a.free_region_buckets_used >> bucket_index
// Loop through each bucket that has free regions in it, based on bits set in free_region_buckets_used bitmap.
for bucket_mask != 0 {
index_add := intrinsics.count_trailing_zeros(bucket_mask)
bucket_index += uint(index_add)
bucket_mask >>= index_add
assert(bucket_index <= NUM_FREE_BUCKETS-1)
assert(a.free_region_buckets_used & (BUCKET_BITMASK_T(1) << bucket_index) > 0)
free_region := a.free_region_buckets[bucket_index].next
assert(free_region != nil)
if free_region != &a.free_region_buckets[bucket_index] {
ptr := attempt_allocate(a, free_region, alignment, size)
if ptr != nil {
return ptr
}
// We were not able to allocate from the first region found in this bucket, so penalize
// the region by cycling it to the end of the doubly circular linked list. (constant time)
// This provides a randomized guarantee that when performing allocations of size k to a
// bucket of [k-something, k+something] range, we will not always attempt to satisfy the
// allocation from the same available region at the front of the list, but we try each
// region in turn.
unlink_from_free_list(free_region)
prepend_to_free_list(free_region, &a.free_region_buckets[bucket_index])
// But do not stick around to attempt to look at other regions in this bucket - move
// to search the next populated bucket index if this did not fit. This gives a practical
// "allocation in constant time" guarantee, since the next higher bucket will only have
// regions that are all of strictly larger size than the requested allocation. Only if
// there is a difficult alignment requirement we may fail to perform the allocation from
// a region in the next bucket, and if so, we keep trying higher buckets until one of them
// works.
bucket_index += 1
bucket_mask >>= 1
} else {
// This bucket was not populated after all with any regions,
// but we just had a stale bit set to mark a populated bucket.
// Reset the bit to update latest status so that we do not
// redundantly look at this bucket again.
a.free_region_buckets_used &~= BUCKET_BITMASK_T(1) << bucket_index
bucket_mask ~= 1
}
assert((bucket_index == NUM_FREE_BUCKETS && bucket_mask == 0) || (bucket_mask == a.free_region_buckets_used >> bucket_index))
}
// None of the buckets were able to accommodate an allocation. If this happens we are almost out of memory.
// The largest bucket might contain some suitable regions, but we only looked at one region in that bucket, so
// as a last resort, loop through more free regions in the bucket that represents the largest allocations available.
// But only if the bucket representing largest allocations available is not any of the first thirty buckets,
// these represent allocatable areas less than <1024 bytes - which could be a lot of scrap.
// In such case, prefer to claim more memory right away.
largest_bucket_index := NUM_FREE_BUCKETS - 1 - intrinsics.count_leading_zeros(a.free_region_buckets_used)
// free_region will be null if there is absolutely no memory left. (all buckets are 100% used)
free_region := a.free_region_buckets_used > 0 ? a.free_region_buckets[largest_bucket_index].next : nil
// The 30 first free region buckets cover memory blocks < 2048 bytes, so skip looking at those here (too small)
if a.free_region_buckets_used >> 30 > 0 {
// Look only at a constant number of regions in this bucket max, to avoid bad worst case behavior.
// If this many regions cannot find free space, we give up and prefer to claim more memory instead.
max_regions_to_try_before_giving_up :: 99
num_tries_left := max_regions_to_try_before_giving_up
for ; free_region != &a.free_region_buckets[largest_bucket_index] && num_tries_left > 0; num_tries_left -= 1 {
ptr := attempt_allocate(a, free_region, alignment, size)
if ptr != nil {
return ptr
}
free_region = free_region.next
}
}
// We were unable to find a free memory region. Must claim more memory!
num_bytes_to_claim := size+size_of(Region)*3
if alignment > a.alignment {
num_bytes_to_claim += alignment
}
success := claim_more_memory(a, num_bytes_to_claim)
if (success) {
// Try allocate again with the newly available memory.
return allocate_memory(a, alignment, size)
}
// also claim_more_memory failed, we are really really constrained :( As a last resort, go back to looking at the
// bucket we already looked at above, continuing where the above search left off - perhaps there are
// regions we overlooked the first time that might be able to satisfy the allocation.
if free_region != nil {
for free_region != &a.free_region_buckets[largest_bucket_index] {
ptr := attempt_allocate(a, free_region, alignment, size)
if ptr != nil {
return ptr
}
free_region = free_region.next
}
}
// Fully out of memory.
return nil
}
@(private="file")
aligned_alloc :: proc(a: ^WASM_Allocator, alignment, size: uint, loc := #caller_location) -> rawptr {
lock(a)
defer unlock(a)
return allocate_memory(a, alignment, size, loc)
}
@(private="file")
free :: proc(a: ^WASM_Allocator, ptr: rawptr, loc := #caller_location) {
if ptr == nil {
return
}
region_start_ptr := uintptr(ptr) - size_of(uint)
region := (^Region)(region_start_ptr)
assert(has_alignment(region_start_ptr, size_of(uint)))
lock(a)
defer unlock(a)
size := region.size
assert(region_is_in_use(region), "double free or corrupt region", loc=loc)
prev_region_size_field := ([^]uint)(region)[-1]
prev_region_size := prev_region_size_field & ~uint(FREE_REGION_FLAG)
if prev_region_size_field != prev_region_size {
prev_region := (^Region)(uintptr(region) - uintptr(prev_region_size))
unlink_from_free_list(prev_region)
region_start_ptr = uintptr(prev_region)
size += prev_region_size
}
next_reg := next_region(region)
size_at_end := (^uint)(region_payload_end_ptr(next_reg))^
if next_reg.size != size_at_end {
unlink_from_free_list(next_reg)
size += next_reg.size
}
create_free_region(rawptr(region_start_ptr), size)
link_to_free_list(a, (^Region)(region_start_ptr))
}
@(private="file")
aligned_realloc :: proc(a: ^WASM_Allocator, ptr: rawptr, alignment, size: uint, loc := #caller_location) -> rawptr {
attempt_region_resize :: proc(a: ^WASM_Allocator, region: ^Region, size: uint) -> bool {
lock(a)
defer unlock(a)
// First attempt to resize this region, if the next region that follows this one
// is a free region.
next_reg := next_region(region)
next_region_end_ptr := uintptr(next_reg) + uintptr(next_reg.size)
size_at_ceiling := ([^]uint)(next_region_end_ptr)[-1]
if next_reg.size != size_at_ceiling { // Next region is free?
assert(region_is_free(next_reg))
new_next_region_start_ptr := uintptr(region) + uintptr(size)
assert(has_alignment(new_next_region_start_ptr, size_of(uint)))
// Next region does not shrink to too small size?
if new_next_region_start_ptr + size_of(Region) <= next_region_end_ptr {
unlink_from_free_list(next_reg)
create_free_region(rawptr(new_next_region_start_ptr), uint(next_region_end_ptr - new_next_region_start_ptr))
link_to_free_list(a, (^Region)(new_next_region_start_ptr))
create_used_region(region, uint(new_next_region_start_ptr - uintptr(region)))
return true
}
// If we remove the next region altogether, allocation is satisfied?
if new_next_region_start_ptr <= next_region_end_ptr {
unlink_from_free_list(next_reg)
create_used_region(region, region.size + next_reg.size)
return true
}
} else {
// Next region is an used region - we cannot change its starting address. However if we are shrinking the
// size of this region, we can create a new free region between this and the next used region.
if size + size_of(Region) <= region.size {
free_region_size := region.size - size
create_used_region(region, size)
free_region := (^Region)(uintptr(region) + uintptr(size))
create_free_region(free_region, free_region_size)
link_to_free_list(a, free_region)
return true
} else if size <= region.size {
// Caller was asking to shrink the size, but due to not being able to fit a full Region in the shrunk
// area, we cannot actually do anything. This occurs if the shrink amount is really small. In such case,
// just call it success without doing any work.
return true
}
}
return false
}
if ptr == nil {
return aligned_alloc(a, alignment, size, loc)
}
if size == 0 {
free(a, ptr, loc)
return nil
}
if size > MAX_ALLOC_SIZE {
return nil
}
assert(is_power_of_two(alignment))
assert(has_alignment(uintptr(ptr), alignment), "realloc on different alignment than original allocation", loc=loc)
size := size
size = validate_alloc_size(size)
region := (^Region)(uintptr(ptr) - size_of(uint))
// Attempt an in-place resize.
if attempt_region_resize(a, region, size + REGION_HEADER_SIZE) {
return ptr
}
// Can't do it in-place, allocate new region and copy over.
newptr := aligned_alloc(a, alignment, size, loc)
if newptr != nil {
intrinsics.mem_copy(newptr, ptr, min(size, region.size - REGION_HEADER_SIZE))
free(a, ptr, loc=loc)
}
return newptr
}
+42 -17
View File
@@ -2,7 +2,6 @@
set -eu
: ${CPPFLAGS=}
: ${CXX=clang++}
: ${CXXFLAGS=}
: ${LDFLAGS=}
: ${LLVM_CONFIG=}
@@ -26,17 +25,19 @@ error() {
if [ -z "$LLVM_CONFIG" ]; then
# darwin, linux, openbsd
if [ -n "$(command -v llvm-config-17)" ]; then LLVM_CONFIG="llvm-config-17"
if [ -n "$(command -v llvm-config-18)" ]; then LLVM_CONFIG="llvm-config-18"
elif [ -n "$(command -v llvm-config-17)" ]; then LLVM_CONFIG="llvm-config-17"
elif [ -n "$(command -v llvm-config-14)" ]; then LLVM_CONFIG="llvm-config-14"
elif [ -n "$(command -v llvm-config-13)" ]; then LLVM_CONFIG="llvm-config-13"
elif [ -n "$(command -v llvm-config-12)" ]; then LLVM_CONFIG="llvm-config-12"
elif [ -n "$(command -v llvm-config-11)" ]; then LLVM_CONFIG="llvm-config-11"
# freebsd
elif [ -n "$(command -v llvm-config17)" ]; then LLVM_CONFIG="llvm-config-17"
elif [ -n "$(command -v llvm-config14)" ]; then LLVM_CONFIG="llvm-config-14"
elif [ -n "$(command -v llvm-config13)" ]; then LLVM_CONFIG="llvm-config-13"
elif [ -n "$(command -v llvm-config12)" ]; then LLVM_CONFIG="llvm-config-12"
elif [ -n "$(command -v llvm-config11)" ]; then LLVM_CONFIG="llvm-config-11"
elif [ -n "$(command -v llvm-config18)" ]; then LLVM_CONFIG="llvm-config18"
elif [ -n "$(command -v llvm-config17)" ]; then LLVM_CONFIG="llvm-config17"
elif [ -n "$(command -v llvm-config14)" ]; then LLVM_CONFIG="llvm-config14"
elif [ -n "$(command -v llvm-config13)" ]; then LLVM_CONFIG="llvm-config13"
elif [ -n "$(command -v llvm-config12)" ]; then LLVM_CONFIG="llvm-config12"
elif [ -n "$(command -v llvm-config11)" ]; then LLVM_CONFIG="llvm-config11"
# fallback
elif [ -n "$(command -v llvm-config)" ]; then LLVM_CONFIG="llvm-config"
else
@@ -44,32 +45,51 @@ if [ -z "$LLVM_CONFIG" ]; then
fi
fi
if [ -x "$(which clang++)" ]; then
: ${CXX="clang++"}
elif [ -x "$($LLVM_CONFIG --bindir)/clang++" ]; then
: ${CXX=$($LLVM_CONFIG --bindir)/clang++}
else
error "No clang++ command found. Set CXX to proceed."
fi
LLVM_VERSION="$($LLVM_CONFIG --version)"
LLVM_VERSION_MAJOR="$(echo $LLVM_VERSION | awk -F. '{print $1}')"
LLVM_VERSION_MINOR="$(echo $LLVM_VERSION | awk -F. '{print $2}')"
LLVM_VERSION_PATCH="$(echo $LLVM_VERSION | awk -F. '{print $3}')"
if [ $LLVM_VERSION_MAJOR -lt 11 ] ||
([ $LLVM_VERSION_MAJOR -gt 14 ] && [ $LLVM_VERSION_MAJOR -lt 17 ]); then
error "Invalid LLVM version $LLVM_VERSION: must be 11, 12, 13, 14 or 17"
if [ $LLVM_VERSION_MAJOR -lt 11 ] || ([ $LLVM_VERSION_MAJOR -gt 14 ] && [ $LLVM_VERSION_MAJOR -lt 17 ]) || [ $LLVM_VERSION_MAJOR -gt 18 ]; then
error "Invalid LLVM version $LLVM_VERSION: must be 11, 12, 13, 14, 17 or 18"
fi
case "$OS_NAME" in
Darwin)
if [ "$OS_ARCH" == "arm64" ]; then
if [ $LLVM_VERSION_MAJOR -lt 13 ] || [ $LLVM_VERSION_MAJOR -gt 17 ]; then
error "Darwin Arm64 requires LLVM 13, 14 or 17"
if [ "$OS_ARCH" = "arm64" ]; then
if [ $LLVM_VERSION_MAJOR -lt 13 ]; then
error "Invalid LLVM version $LLVM_VERSION: Darwin Arm64 requires LLVM 13, 14, 17 or 18"
fi
fi
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
LDFLAGS="$LDFLAGS -liconv -ldl -framework System"
LDFLAGS="$LDFLAGS -lLLVM-C"
darwin_sysroot=
if [ $(which xcrun) ]; then
darwin_sysroot="--sysroot $(xcrun --sdk macosx --show-sdk-path)"
elif [[ -e "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk" ]]; then
darwin_sysroot="--sysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk"
else
echo "Warning: MacOSX.sdk not found."
fi
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags) ${darwin_sysroot}"
LDFLAGS="$LDFLAGS -liconv -ldl -framework System -lLLVM"
;;
FreeBSD)
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)"
;;
NetBSD)
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)"
;;
Linux)
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
LDFLAGS="$LDFLAGS -ldl $($LLVM_CONFIG --libs core native --system-libs --libfiles)"
@@ -83,6 +103,11 @@ OpenBSD)
LDFLAGS="$LDFLAGS -liconv"
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)"
;;
Haiku)
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags) -I/system/develop/headers/private/shared -I/system/develop/headers/private/kernel"
LDFLAGS="$LDFLAGS -liconv"
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)"
;;
*)
error "Platform \"$OS_NAME\" unsupported"
;;
@@ -97,7 +122,7 @@ build_odin() {
EXTRAFLAGS="-O3"
;;
release-native)
if [ "$OS_ARCH" == "arm64" ]; then
if [ "$OS_ARCH" = "arm64" ]; then
# Use preferred flag for Arm (ie arm64 / aarch64 / etc)
EXTRAFLAGS="-O3 -mcpu=native"
else
-51
View File
@@ -1,51 +0,0 @@
import subprocess
import sys
import json
import datetime
import urllib.parse
import sys
def main():
files_by_date = {}
bucket = sys.argv[1]
files_lines = execute_cli(f"b2 ls --long {bucket} nightly").split("\n")
for x in files_lines:
parts = x.split(" ", 1)
if parts[0]:
json_str = execute_cli(f"b2 get-file-info {parts[0]}")
data = json.loads(json_str)
name = remove_prefix(data['fileName'], "nightly/")
url = f"https://f001.backblazeb2.com/file/{bucket}/nightly/{urllib.parse.quote_plus(name)}"
sha1 = data['contentSha1']
size = int(data['size'])
ts = int(data['fileInfo']['src_last_modified_millis'])
date = datetime.datetime.fromtimestamp(ts/1000).strftime('%Y-%m-%d')
if date not in files_by_date.keys():
files_by_date[date] = []
files_by_date[date].append({
'name': name,
'url': url,
'sha1': sha1,
'sizeInBytes': size,
})
now = datetime.datetime.utcnow().isoformat()
print(json.dumps({
'last_updated' : now,
'files': files_by_date
}, sort_keys=True, indent=4))
def remove_prefix(text, prefix):
return text[text.startswith(prefix) and len(prefix):]
def execute_cli(command):
sb = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
return sb.stdout.read().decode("utf-8");
if __name__ == '__main__':
sys.exit(main())
-34
View File
@@ -1,34 +0,0 @@
import subprocess
import sys
import json
import datetime
import urllib.parse
import sys
def main():
files_by_date = {}
bucket = sys.argv[1]
days_to_keep = int(sys.argv[2])
print(f"Looking for binaries to delete older than {days_to_keep} days")
files_lines = execute_cli(f"b2 ls --long --versions {bucket} nightly").split("\n")
for x in files_lines:
parts = [y for y in x.split(' ') if y]
if parts and parts[0]:
date = datetime.datetime.strptime(parts[2], '%Y-%m-%d').replace(hour=0, minute=0, second=0, microsecond=0)
now = datetime.datetime.utcnow().replace(hour=0, minute=0, second=0, microsecond=0)
delta = now - date
if delta.days > days_to_keep:
print(f'Deleting {parts[5]}')
execute_cli(f'b2 delete-file-version {parts[0]}')
def execute_cli(command):
sb = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
return sb.stdout.read().decode("utf-8");
if __name__ == '__main__':
sys.exit(main())
+140
View File
@@ -0,0 +1,140 @@
import os
import sys
from zipfile import ZipFile, ZIP_DEFLATED
from b2sdk.v2 import InMemoryAccountInfo, B2Api
from datetime import datetime
import json
UPLOAD_FOLDER = "nightly/"
info = InMemoryAccountInfo()
b2_api = B2Api(info)
application_key_id = os.environ['APPID']
application_key = os.environ['APPKEY']
bucket_name = os.environ['BUCKET']
days_to_keep = os.environ['DAYS_TO_KEEP']
def auth() -> bool:
try:
realm = b2_api.account_info.get_realm()
return True # Already authenticated
except:
pass # Not yet authenticated
err = b2_api.authorize_account("production", application_key_id, application_key)
return err == None
def get_bucket():
if not auth(): sys.exit(1)
return b2_api.get_bucket_by_name(bucket_name)
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"))
source_zip_name = artifact
if not artifact.endswith(".zip"):
print(f"Creating archive {destination_zip_name} from {artifact} and uploading to {bucket_name}")
source_zip_name = destination_zip_name
with ZipFile(source_zip_name, 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
print("Uploading {} to {}".format(source_zip_name, UPLOAD_FOLDER + destination_zip_name))
bucket = get_bucket()
res = bucket.upload_local_file(
source_zip_name, # Local file to upload
"nightly/" + destination_zip_name, # B2 destination path
)
return 0
def prune_artifacts():
print(f"Looking for binaries to delete older than {days_to_keep} days")
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)
delta = now - date
if delta.days > int(days_to_keep):
print("Deleting {}".format(file.file_name))
file.delete()
return 0
def update_nightly_json():
print(f"Updating nightly.json with files {days_to_keep} days or newer")
files_by_date = {}
bucket = get_bucket()
for file, _ in bucket.ls(UPLOAD_FOLDER, latest_only=True):
# Timestamp is in milliseconds
date = datetime.fromtimestamp(file.upload_timestamp / 1_000.0).replace(hour=0, minute=0, second=0, microsecond=0).strftime('%Y-%m-%d')
name = remove_prefix(file.file_name, UPLOAD_FOLDER)
sha1 = file.content_sha1
size = file.size
url = bucket.get_download_url(file.file_name)
if date not in files_by_date.keys():
files_by_date[date] = []
files_by_date[date].append({
'name': name,
'url': url,
'sha1': sha1,
'sizeInBytes': size,
})
now = datetime.utcnow().isoformat()
nightly = json.dumps({
'last_updated' : now,
'files': files_by_date
}, sort_keys=True, indent=4, ensure_ascii=False).encode('utf-8')
res = bucket.upload_bytes(
nightly, # JSON bytes
"nightly.json", # B2 destination path
)
return 0
if __name__ == "__main__":
if len(sys.argv) == 1:
print("Usage: {} <verb> [arguments]".format(sys.argv[0]))
print("\tartifact <platform prefix> <artifact path>\n\t\tCreates and uploads a platform artifact zip.")
print("\tprune\n\t\tDeletes old artifacts from bucket")
print("\tjson\n\t\tUpdate and upload nightly.json")
sys.exit(1)
else:
command = sys.argv[1].lower()
if command == "artifact":
if len(sys.argv) != 4:
print("Usage: {} artifact <platform prefix> <artifact path>".format(sys.argv[0]))
print("Error: Expected artifact command to be given platform prefix and artifact path.\n")
sys.exit(1)
res = create_and_upload_artifact_zip(sys.argv[2], sys.argv[3])
sys.exit(res)
elif command == "prune":
res = prune_artifacts()
sys.exit(res)
elif command == "json":
res = update_nightly_json()
sys.exit(res)
-13
View File
@@ -1,13 +0,0 @@
#!/bin/bash
bucket=$1
platform=$2
artifact=$3
now=$(date +'%Y-%m-%d')
filename="odin-$platform-nightly+$now.zip"
echo "Creating archive $filename from $artifact and uploading to $bucket"
7z a -bd "output/$filename" -r "$artifact"
b2 upload-file --noProgress "$bucket" "output/$filename" "nightly/$filename"
+6 -6
View File
@@ -29,12 +29,12 @@ MIN_READ_BUFFER_SIZE :: 16
@(private)
DEFAULT_MAX_CONSECUTIVE_EMPTY_READS :: 128
reader_init :: proc(b: ^Reader, rd: io.Reader, size: int = DEFAULT_BUF_SIZE, allocator := context.allocator) {
reader_init :: proc(b: ^Reader, rd: io.Reader, size: int = DEFAULT_BUF_SIZE, allocator := context.allocator, loc := #caller_location) {
size := size
size = max(size, MIN_READ_BUFFER_SIZE)
reader_reset(b, rd)
b.buf_allocator = allocator
b.buf = make([]byte, size, allocator)
b.buf = make([]byte, size, allocator, loc)
}
reader_init_with_buf :: proc(b: ^Reader, rd: io.Reader, buf: []byte) {
@@ -81,7 +81,7 @@ _reader_read_new_chunk :: proc(b: ^Reader) -> io.Error {
for i := b.max_consecutive_empty_reads; i > 0; i -= 1 {
n, err := io.read(b.rd, b.buf[b.w:])
if n < 0 {
return .Negative_Read
return err if err != nil else .Negative_Read
}
b.w += n
if err != nil {
@@ -189,7 +189,7 @@ reader_read :: proc(b: ^Reader, p: []byte) -> (n: int, err: io.Error) {
if len(p) >= len(b.buf) {
n, b.err = io.read(b.rd, p)
if n < 0 {
return 0, .Negative_Read
return 0, b.err if b.err != nil else .Negative_Read
}
if n > 0 {
@@ -202,7 +202,7 @@ reader_read :: proc(b: ^Reader, p: []byte) -> (n: int, err: io.Error) {
b.r, b.w = 0, 0
n, b.err = io.read(b.rd, b.buf)
if n < 0 {
return 0, .Negative_Read
return 0, b.err if b.err != nil else .Negative_Read
}
if n == 0 {
return 0, _reader_consume_err(b)
@@ -290,7 +290,7 @@ reader_write_to :: proc(b: ^Reader, w: io.Writer) -> (n: i64, err: io.Error) {
write_buf :: proc(b: ^Reader, w: io.Writer) -> (i64, io.Error) {
n, err := io.write(w, b.buf[b.r:b.w])
if n < 0 {
return 0, .Negative_Write
return 0, err if err != nil else .Negative_Write
}
b.r += n
return i64(n), err
+4 -1
View File
@@ -95,6 +95,10 @@ writer_write :: proc(b: ^Writer, p: []byte) -> (n: int, err: io.Error) {
m: int
if writer_buffered(b) == 0 {
m, b.err = io.write(b.wr, p)
if m < 0 && b.err == nil {
b.err = .Negative_Write
break
}
} else {
m = copy(b.buf[b.n:], p)
b.n += m
@@ -226,7 +230,6 @@ writer_to_writer :: proc(b: ^Writer) -> (s: io.Writer) {
@(private)
_writer_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) {
b := (^Writer)(stream_data)
#partial switch mode {
+36 -36
View File
@@ -27,19 +27,19 @@ Read_Op :: enum i8 {
}
buffer_init :: proc(b: ^Buffer, buf: []byte) {
resize(&b.buf, len(buf))
buffer_init :: proc(b: ^Buffer, buf: []byte, loc := #caller_location) {
resize(&b.buf, len(buf), loc=loc)
copy(b.buf[:], buf)
}
buffer_init_string :: proc(b: ^Buffer, s: string) {
resize(&b.buf, len(s))
buffer_init_string :: proc(b: ^Buffer, s: string, loc := #caller_location) {
resize(&b.buf, len(s), loc=loc)
copy(b.buf[:], s)
}
buffer_init_allocator :: proc(b: ^Buffer, len, cap: int, allocator := context.allocator) {
buffer_init_allocator :: proc(b: ^Buffer, len, cap: int, allocator := context.allocator, loc := #caller_location) {
if b.buf == nil {
b.buf = make([dynamic]byte, len, cap, allocator)
b.buf = make([dynamic]byte, len, cap, allocator, loc)
return
}
@@ -96,28 +96,28 @@ buffer_truncate :: proc(b: ^Buffer, n: int) {
}
@(private)
_buffer_try_grow :: proc(b: ^Buffer, n: int) -> (int, bool) {
_buffer_try_grow :: proc(b: ^Buffer, n: int, loc := #caller_location) -> (int, bool) {
if l := len(b.buf); n <= cap(b.buf)-l {
resize(&b.buf, l+n)
resize(&b.buf, l+n, loc=loc)
return l, true
}
return 0, false
}
@(private)
_buffer_grow :: proc(b: ^Buffer, n: int) -> int {
_buffer_grow :: proc(b: ^Buffer, n: int, loc := #caller_location) -> int {
m := buffer_length(b)
if m == 0 && b.off != 0 {
buffer_reset(b)
}
if i, ok := _buffer_try_grow(b, n); ok {
if i, ok := _buffer_try_grow(b, n, loc=loc); ok {
return i
}
if b.buf == nil && n <= SMALL_BUFFER_SIZE {
// Fixes #2756 by preserving allocator if already set on Buffer via init_buffer_allocator
reserve(&b.buf, SMALL_BUFFER_SIZE)
resize(&b.buf, n)
reserve(&b.buf, SMALL_BUFFER_SIZE, loc=loc)
resize(&b.buf, n, loc=loc)
return 0
}
@@ -127,31 +127,31 @@ _buffer_grow :: proc(b: ^Buffer, n: int) -> int {
} else if c > max(int) - c - n {
panic("bytes.Buffer: too large")
} else {
resize(&b.buf, 2*c + n)
resize(&b.buf, 2*c + n, loc=loc)
copy(b.buf[:], b.buf[b.off:])
}
b.off = 0
resize(&b.buf, m+n)
resize(&b.buf, m+n, loc=loc)
return m
}
buffer_grow :: proc(b: ^Buffer, n: int) {
buffer_grow :: proc(b: ^Buffer, n: int, loc := #caller_location) {
if n < 0 {
panic("bytes.buffer_grow: negative count")
}
m := _buffer_grow(b, n)
resize(&b.buf, m)
m := _buffer_grow(b, n, loc=loc)
resize(&b.buf, m, loc=loc)
}
buffer_write_at :: proc(b: ^Buffer, p: []byte, offset: int) -> (n: int, err: io.Error) {
buffer_write_at :: proc(b: ^Buffer, p: []byte, offset: int, loc := #caller_location) -> (n: int, err: io.Error) {
b.last_read = .Invalid
if offset < 0 {
err = .Invalid_Offset
return
}
_, ok := _buffer_try_grow(b, offset+len(p))
_, ok := _buffer_try_grow(b, offset+len(p), loc=loc)
if !ok {
_ = _buffer_grow(b, offset+len(p))
_ = _buffer_grow(b, offset+len(p), loc=loc)
}
if len(b.buf) <= offset {
return 0, .Short_Write
@@ -160,47 +160,47 @@ buffer_write_at :: proc(b: ^Buffer, p: []byte, offset: int) -> (n: int, err: io.
}
buffer_write :: proc(b: ^Buffer, p: []byte) -> (n: int, err: io.Error) {
buffer_write :: proc(b: ^Buffer, p: []byte, loc := #caller_location) -> (n: int, err: io.Error) {
b.last_read = .Invalid
m, ok := _buffer_try_grow(b, len(p))
m, ok := _buffer_try_grow(b, len(p), loc=loc)
if !ok {
m = _buffer_grow(b, len(p))
m = _buffer_grow(b, len(p), loc=loc)
}
return copy(b.buf[m:], p), nil
}
buffer_write_ptr :: proc(b: ^Buffer, ptr: rawptr, size: int) -> (n: int, err: io.Error) {
return buffer_write(b, ([^]byte)(ptr)[:size])
buffer_write_ptr :: proc(b: ^Buffer, ptr: rawptr, size: int, loc := #caller_location) -> (n: int, err: io.Error) {
return buffer_write(b, ([^]byte)(ptr)[:size], loc=loc)
}
buffer_write_string :: proc(b: ^Buffer, s: string) -> (n: int, err: io.Error) {
buffer_write_string :: proc(b: ^Buffer, s: string, loc := #caller_location) -> (n: int, err: io.Error) {
b.last_read = .Invalid
m, ok := _buffer_try_grow(b, len(s))
m, ok := _buffer_try_grow(b, len(s), loc=loc)
if !ok {
m = _buffer_grow(b, len(s))
m = _buffer_grow(b, len(s), loc=loc)
}
return copy(b.buf[m:], s), nil
}
buffer_write_byte :: proc(b: ^Buffer, c: byte) -> io.Error {
buffer_write_byte :: proc(b: ^Buffer, c: byte, loc := #caller_location) -> io.Error {
b.last_read = .Invalid
m, ok := _buffer_try_grow(b, 1)
m, ok := _buffer_try_grow(b, 1, loc=loc)
if !ok {
m = _buffer_grow(b, 1)
m = _buffer_grow(b, 1, loc=loc)
}
b.buf[m] = c
return nil
}
buffer_write_rune :: proc(b: ^Buffer, r: rune) -> (n: int, err: io.Error) {
buffer_write_rune :: proc(b: ^Buffer, r: rune, loc := #caller_location) -> (n: int, err: io.Error) {
if r < utf8.RUNE_SELF {
buffer_write_byte(b, byte(r))
buffer_write_byte(b, byte(r), loc=loc)
return 1, nil
}
b.last_read = .Invalid
m, ok := _buffer_try_grow(b, utf8.UTF_MAX)
m, ok := _buffer_try_grow(b, utf8.UTF_MAX, loc=loc)
if !ok {
m = _buffer_grow(b, utf8.UTF_MAX)
m = _buffer_grow(b, utf8.UTF_MAX, loc=loc)
}
res: [4]byte
res, n = utf8.encode_rune(r)
@@ -359,7 +359,7 @@ buffer_read_from :: proc(b: ^Buffer, r: io.Reader) -> (n: i64, err: io.Error) #n
resize(&b.buf, i)
m, e := io.read(r, b.buf[i:cap(b.buf)])
if m < 0 {
err = .Negative_Read
err = e if e != nil else .Negative_Read
return
}
+10
View File
@@ -104,3 +104,13 @@ NULL :: rawptr(uintptr(0))
NDEBUG :: !ODIN_DEBUG
CHAR_BIT :: 8
// Since there are no types in C with an alignment larger than that of
// max_align_t, which cannot be larger than sizeof(long double) as any other
// exposed type wouldn't be valid C, the maximum alignment possible in a
// strictly conformant C implementation is 16 on the platforms we care about.
// The choice of 4096 bytes for storage of this type is more than enough on all
// relevant platforms.
va_list :: struct #align(16) {
_: [4096]u8,
}
+21 -24
View File
@@ -1,34 +1,31 @@
/*
package demo
Example:
package demo
import tokenizer "core:c/frontend/tokenizer"
import preprocessor "core:c/frontend/preprocessor"
import "core:fmt"
import tokenizer "core:c/frontend/tokenizer"
import preprocessor "core:c/frontend/preprocessor"
import "core:fmt"
main :: proc() {
t := &tokenizer.Tokenizer{};
tokenizer.init_defaults(t);
main :: proc() {
t := &tokenizer.Tokenizer{};
tokenizer.init_defaults(t);
cpp := &preprocessor.Preprocessor{};
cpp.warn, cpp.err = t.warn, t.err;
preprocessor.init_lookup_tables(cpp);
preprocessor.init_default_macros(cpp);
cpp.include_paths = {"my/path/to/include"};
cpp := &preprocessor.Preprocessor{};
cpp.warn, cpp.err = t.warn, t.err;
preprocessor.init_lookup_tables(cpp);
preprocessor.init_default_macros(cpp);
cpp.include_paths = {"my/path/to/include"};
tok := tokenizer.tokenize_file(t, "the/source/file.c", 1);
tok := tokenizer.tokenize_file(t, "the/source/file.c", 1);
tok = preprocessor.preprocess(cpp, tok);
if tok != nil {
for t := tok; t.kind != .EOF; t = t.next {
fmt.println(t.lit);
tok = preprocessor.preprocess(cpp, tok);
if tok != nil {
for t := tok; t.kind != .EOF; t = t.next {
fmt.println(t.lit);
}
}
fmt.println("[Done]");
}
fmt.println("[Done]");
}
*/
package c_frontend_tokenizer
+19 -1
View File
@@ -40,7 +40,7 @@ when ODIN_OS == .FreeBSD {
ERANGE :: 34
}
when ODIN_OS == .OpenBSD {
when ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD {
@(private="file")
@(default_calling_convention="c")
foreign libc {
@@ -80,6 +80,24 @@ when ODIN_OS == .Darwin {
ERANGE :: 34
}
when ODIN_OS == .Haiku {
@(private="file")
@(default_calling_convention="c")
foreign libc {
@(link_name="_errnop")
_get_errno :: proc() -> ^int ---
}
@(private="file")
B_GENERAL_ERROR_BASE :: min(i32)
@(private="file")
B_POSIX_ERROR_BASE :: B_GENERAL_ERROR_BASE + 0x7000
EDOM :: B_POSIX_ERROR_BASE + 16
EILSEQ :: B_POSIX_ERROR_BASE + 38
ERANGE :: B_POSIX_ERROR_BASE + 17
}
// 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
+1 -14
View File
@@ -34,20 +34,7 @@ when ODIN_OS == .Windows {
SIGTERM :: 15
}
when ODIN_OS == .Linux || ODIN_OS == .FreeBSD {
SIG_ERR :: rawptr(~uintptr(0))
SIG_DFL :: rawptr(uintptr(0))
SIG_IGN :: rawptr(uintptr(1))
SIGABRT :: 6
SIGFPE :: 8
SIGILL :: 4
SIGINT :: 2
SIGSEGV :: 11
SIGTERM :: 15
}
when ODIN_OS == .Darwin {
when ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .Haiku || ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD || ODIN_OS == .Darwin {
SIG_ERR :: rawptr(~uintptr(0))
SIG_DFL :: rawptr(uintptr(0))
SIG_IGN :: rawptr(uintptr(1))
+3 -9
View File
@@ -4,6 +4,8 @@ package libc
import "base:intrinsics"
import "core:c"
@(private="file")
@(default_calling_convention="none")
foreign _ {
@@ -12,15 +14,7 @@ foreign _ {
@(link_name="llvm.va_copy") _va_copy :: proc(dst, src: ^i8) ---
}
// Since there are no types in C with an alignment larger than that of
// max_align_t, which cannot be larger than sizeof(long double) as any other
// exposed type wouldn't be valid C, the maximum alignment possible in a
// strictly conformant C implementation is 16 on the platforms we care about.
// The choice of 4096 bytes for storage of this type is more than enough on all
// relevant platforms.
va_list :: struct #align(16) {
_: [4096]u8,
}
va_list :: c.va_list
va_start :: #force_inline proc(ap: ^va_list, _: any) {
_va_start(cast(^i8)ap)
+39 -7
View File
@@ -83,7 +83,7 @@ when ODIN_OS == .Linux {
}
}
when ODIN_OS == .OpenBSD {
when ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD {
fpos_t :: distinct i64
_IOFBF :: 0
@@ -102,10 +102,12 @@ when ODIN_OS == .OpenBSD {
SEEK_END :: 2
foreign libc {
stderr: ^FILE
stdin: ^FILE
stdout: ^FILE
__sF: [3]FILE
}
stdin: ^FILE = &__sF[0]
stdout: ^FILE = &__sF[1]
stderr: ^FILE = &__sF[2]
}
when ODIN_OS == .FreeBSD {
@@ -127,9 +129,9 @@ when ODIN_OS == .FreeBSD {
SEEK_END :: 2
foreign libc {
stderr: ^FILE
stdin: ^FILE
stdout: ^FILE
@(link_name="__stderrp") stderr: ^FILE
@(link_name="__stdinp") stdin: ^FILE
@(link_name="__stdoutp") stdout: ^FILE
}
}
@@ -163,6 +165,36 @@ when ODIN_OS == .Darwin {
}
}
when ODIN_OS == .Haiku {
fpos_t :: distinct i64
_IOFBF :: 0
_IOLBF :: 1
_IONBF :: 2
BUFSIZ :: 8192
EOF :: int(-1)
FOPEN_MAX :: 128
FILENAME_MAX :: 256
L_tmpnam :: 512
SEEK_SET :: 0
SEEK_CUR :: 1
SEEK_END :: 2
TMP_MAX :: 32768
foreign libc {
stderr: ^FILE
stdin: ^FILE
stdout: ^FILE
}
}
@(default_calling_convention="c")
foreign libc {
// 7.21.4 Operations on files
+1 -1
View File
@@ -45,7 +45,7 @@ when ODIN_OS == .Windows {
}
}
when ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .Darwin || ODIN_OS == .OpenBSD {
when ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .Darwin || ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD || ODIN_OS == .Haiku {
@(default_calling_convention="c")
foreign libc {
// 7.27.2 Time manipulation functions
+6 -2
View File
@@ -22,14 +22,18 @@ when ODIN_OS == .Windows {
wctrans_t :: distinct int
wctype_t :: distinct u32
} else when ODIN_OS == .OpenBSD {
} else when ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD {
wctrans_t :: distinct rawptr
wctype_t :: distinct rawptr
} else when ODIN_OS == .FreeBSD {
wctrans_t :: distinct int
wctype_t :: distinct ulong
} else when ODIN_OS == .Haiku {
wctrans_t :: distinct i32
wctype_t :: distinct i32
}
@(default_calling_convention="c")
+3 -3
View File
@@ -34,13 +34,13 @@ COMPRESS_OUTPUT_ALLOCATE_MIN :: int(#config(COMPRESS_OUTPUT_ALLOCATE_MIN, 1 << 2
*/
when size_of(uintptr) == 8 {
// For 64-bit platforms, we set the default max buffer size to 4 GiB,
// which is GZIP and PKZIP's max payload size.
// For 64-bit platforms, we set the default max buffer size to 4 GiB,
// which is GZIP and PKZIP's max payload size.
COMPRESS_OUTPUT_ALLOCATE_MAX :: int(#config(COMPRESS_OUTPUT_ALLOCATE_MAX, 1 << 32))
} else {
// For 32-bit platforms, we set the default max buffer size to 512 MiB.
COMPRESS_OUTPUT_ALLOCATE_MAX :: int(#config(COMPRESS_OUTPUT_ALLOCATE_MAX, 1 << 29))
COMPRESS_OUTPUT_ALLOCATE_MAX :: int(#config(COMPRESS_OUTPUT_ALLOCATE_MAX, 1 << 29))
}
+1 -1
View File
@@ -1,5 +1,5 @@
//+build ignore
package gzip
package compress_gzip
/*
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
+1 -1
View File
@@ -1,4 +1,4 @@
package gzip
package compress_gzip
/*
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
+1 -1
View File
@@ -5,7 +5,7 @@
*/
// package shoco is an implementation of the shoco short string compressor
package shoco
package compress_shoco
DEFAULT_MODEL :: Shoco_Model {
min_char = 39,
+5 -8
View File
@@ -9,7 +9,7 @@
*/
// package shoco is an implementation of the shoco short string compressor
package shoco
package compress_shoco
import "base:intrinsics"
import "core:compress"
@@ -98,7 +98,7 @@ decompress_slice_to_output_buffer :: proc(input: []u8, output: []u8, model := DE
validate_model(model) or_return
for inp < inp_end {
val := transmute(i8)input[inp]
val := i8(input[inp])
mark := int(-1)
for val < 0 {
@@ -274,12 +274,9 @@ compress_string_to_buffer :: proc(input: string, output: []u8, model := DEFAULT_
out_ptr := raw_data(output[out:])
switch pack.bytes_packed {
case 4:
intrinsics.unaligned_store(transmute(^u32)out_ptr, code)
case 2:
intrinsics.unaligned_store(transmute(^u16)out_ptr, u16(code))
case 1:
intrinsics.unaligned_store(transmute(^u8)out_ptr, u8(code))
case 4: intrinsics.unaligned_store((^u32)(out_ptr), code)
case 2: intrinsics.unaligned_store((^u16)(out_ptr), u16(code))
case 1: intrinsics.unaligned_store( (^u8)(out_ptr), u8(code))
case:
return out, .Unknown_Compression_Method
}
+1 -1
View File
@@ -1,5 +1,5 @@
//+build ignore
package zlib
package compress_zlib
/*
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
+1 -1
View File
@@ -1,5 +1,5 @@
//+vet !using-param
package zlib
package compress_zlib
/*
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
+675
View File
@@ -0,0 +1,675 @@
/*
package avl implements an AVL tree.
The implementation is non-intrusive, and non-recursive.
*/
package container_avl
@(require) import "base:intrinsics"
@(require) import "base:runtime"
import "core:slice"
// Originally based on the CC0 implementation by Eric Biggers
// See: https://github.com/ebiggers/avl_tree/
// Direction specifies the traversal direction for a tree iterator.
Direction :: enum i8 {
// Backward is the in-order backwards direction.
Backward = -1,
// Forward is the in-order forwards direction.
Forward = 1,
}
// Ordering specifies order when inserting/finding values into the tree.
Ordering :: slice.Ordering
// Tree is an AVL tree.
Tree :: struct($Value: typeid) {
// user_data is a parameter that will be passed to the on_remove
// callback.
user_data: rawptr,
// on_remove is an optional callback that can be called immediately
// after a node is removed from the tree.
on_remove: proc(value: Value, user_data: rawptr),
_root: ^Node(Value),
_node_allocator: runtime.Allocator,
_cmp_fn: proc(a, b: Value) -> Ordering,
_size: int,
}
// Node is an AVL tree node.
//
// WARNING: It is unsafe to mutate value if the node is part of a tree
// if doing so will alter the Node's sort position relative to other
// elements in the tree.
Node :: struct($Value: typeid) {
value: Value,
_parent: ^Node(Value),
_left: ^Node(Value),
_right: ^Node(Value),
_balance: i8,
}
// Iterator is a tree iterator.
//
// WARNING: It is unsafe to modify the tree while iterating, except via
// the iterator_remove method.
Iterator :: struct($Value: typeid) {
_tree: ^Tree(Value),
_cur: ^Node(Value),
_next: ^Node(Value),
_direction: Direction,
_called_next: bool,
}
// init initializes a tree.
init :: proc {
init_ordered,
init_cmp,
}
// init_cmp initializes a tree.
init_cmp :: proc(
t: ^$T/Tree($Value),
cmp_fn: proc(a, b: Value) -> Ordering,
node_allocator := context.allocator,
) {
t._root = nil
t._node_allocator = node_allocator
t._cmp_fn = cmp_fn
t._size = 0
}
// init_ordered initializes a tree containing ordered items, with
// a comparison function that results in an ascending order sort.
init_ordered :: proc(
t: ^$T/Tree($Value),
node_allocator := context.allocator,
) where intrinsics.type_is_ordered(Value) {
init_cmp(t, slice.cmp_proc(Value), node_allocator)
}
// destroy de-initializes a tree.
destroy :: proc(t: ^$T/Tree($Value), call_on_remove: bool = true) {
iter := iterator(t, Direction.Forward)
for _ in iterator_next(&iter) {
iterator_remove(&iter, call_on_remove)
}
}
// len returns the number of elements in the tree.
len :: proc "contextless" (t: ^$T/Tree($Value)) -> int {
return t._size
}
// first returns the first node in the tree (in-order) or nil iff
// the tree is empty.
first :: proc "contextless" (t: ^$T/Tree($Value)) -> ^Node(Value) {
return tree_first_or_last_in_order(t, Direction.Backward)
}
// last returns the last element in the tree (in-order) or nil iff
// the tree is empty.
last :: proc "contextless" (t: ^$T/Tree($Value)) -> ^Node(Value) {
return tree_first_or_last_in_order(t, Direction.Forward)
}
// find finds the value in the tree, and returns the corresponding
// node or nil iff the value is not present.
find :: proc(t: ^$T/Tree($Value), value: Value) -> ^Node(Value) {
cur := t._root
descend_loop: for cur != nil {
switch t._cmp_fn(value, cur.value) {
case .Less:
cur = cur._left
case .Greater:
cur = cur._right
case .Equal:
break descend_loop
}
}
return cur
}
// find_or_insert attempts to insert the value into the tree, and returns
// the node, a boolean indicating if the value was inserted, and the
// node allocator error if relevant. If the value is already
// present, the existing node is returned un-altered.
find_or_insert :: proc(
t: ^$T/Tree($Value),
value: Value,
) -> (
n: ^Node(Value),
inserted: bool,
err: runtime.Allocator_Error,
) {
n_ptr := &t._root
for n_ptr^ != nil {
n = n_ptr^
switch t._cmp_fn(value, n.value) {
case .Less:
n_ptr = &n._left
case .Greater:
n_ptr = &n._right
case .Equal:
return
}
}
parent := n
n = new(Node(Value), t._node_allocator) or_return
n.value = value
n._parent = parent
n_ptr^ = n
tree_rebalance_after_insert(t, n)
t._size += 1
inserted = true
return
}
// remove removes a node or value from the tree, and returns true iff the
// removal was successful. While the node's value will be left intact,
// the node itself will be freed via the tree's node allocator.
remove :: proc {
remove_value,
remove_node,
}
// remove_value removes a value from the tree, and returns true iff the
// removal was successful. While the node's value will be left intact,
// the node itself will be freed via the tree's node allocator.
remove_value :: proc(t: ^$T/Tree($Value), value: Value, call_on_remove: bool = true) -> bool {
n := find(t, value)
if n == nil {
return false
}
return remove_node(t, n, call_on_remove)
}
// remove_node removes a node from the tree, and returns true iff the
// removal was successful. While the node's value will be left intact,
// the node itself will be freed via the tree's node allocator.
remove_node :: proc(t: ^$T/Tree($Value), node: ^Node(Value), call_on_remove: bool = true) -> bool {
if node._parent == node || (node._parent == nil && t._root != node) {
return false
}
defer {
if call_on_remove && t.on_remove != nil {
t.on_remove(node.value, t.user_data)
}
free(node, t._node_allocator)
}
parent: ^Node(Value)
left_deleted: bool
t._size -= 1
if node._left != nil && node._right != nil {
parent, left_deleted = tree_swap_with_successor(t, node)
} else {
child := node._left
if child == nil {
child = node._right
}
parent = node._parent
if parent != nil {
if node == parent._left {
parent._left = child
left_deleted = true
} else {
parent._right = child
left_deleted = false
}
if child != nil {
child._parent = parent
}
} else {
if child != nil {
child._parent = parent
}
t._root = child
node_reset(node)
return true
}
}
for {
if left_deleted {
parent = tree_handle_subtree_shrink(t, parent, +1, &left_deleted)
} else {
parent = tree_handle_subtree_shrink(t, parent, -1, &left_deleted)
}
if parent == nil {
break
}
}
node_reset(node)
return true
}
// iterator returns a tree iterator in the specified direction.
iterator :: proc "contextless" (t: ^$T/Tree($Value), direction: Direction) -> Iterator(Value) {
it: Iterator(Value)
it._tree = transmute(^Tree(Value))t
it._direction = direction
iterator_first(&it)
return it
}
// iterator_from_pos returns a tree iterator in the specified direction,
// spanning the range [pos, last] (inclusive).
iterator_from_pos :: proc "contextless" (
t: ^$T/Tree($Value),
pos: ^Node(Value),
direction: Direction,
) -> Iterator(Value) {
it: Iterator(Value)
it._tree = transmute(^Tree(Value))t
it._direction = direction
it._next = nil
it._called_next = false
if it._cur = pos; pos != nil {
it._next = node_next_or_prev_in_order(it._cur, it._direction)
}
return it
}
// iterator_get returns the node currently pointed to by the iterator,
// or nil iff the node has been removed, the tree is empty, or the end
// of the tree has been reached.
iterator_get :: proc "contextless" (it: ^$I/Iterator($Value)) -> ^Node(Value) {
return it._cur
}
// iterator_remove removes the node currently pointed to by the iterator,
// and returns true iff the removal was successful. Semantics are the
// same as the Tree remove.
iterator_remove :: proc(it: ^$I/Iterator($Value), call_on_remove: bool = true) -> bool {
if it._cur == nil {
return false
}
ok := remove_node(it._tree, it._cur, call_on_remove)
if ok {
it._cur = nil
}
return ok
}
// iterator_next advances the iterator and returns the (node, true) or
// or (nil, false) iff the end of the tree has been reached.
//
// Note: The first call to iterator_next will return the first node instead
// of advancing the iterator.
iterator_next :: proc "contextless" (it: ^$I/Iterator($Value)) -> (^Node(Value), bool) {
// This check is needed so that the first element gets returned from
// a brand-new iterator, and so that the somewhat contrived case where
// iterator_remove is called before the first call to iterator_next
// returns the correct value.
if !it._called_next {
it._called_next = true
// There can be the contrived case where iterator_remove is
// called before ever calling iterator_next, which needs to be
// handled as an actual call to next.
//
// If this happens it._cur will be nil, so only return the
// first value, if it._cur is valid.
if it._cur != nil {
return it._cur, true
}
}
if it._next == nil {
return nil, false
}
it._cur = it._next
it._next = node_next_or_prev_in_order(it._cur, it._direction)
return it._cur, true
}
@(private)
tree_first_or_last_in_order :: proc "contextless" (
t: ^$T/Tree($Value),
direction: Direction,
) -> ^Node(Value) {
first, sign := t._root, i8(direction)
if first != nil {
for {
tmp := node_get_child(first, +sign)
if tmp == nil {
break
}
first = tmp
}
}
return first
}
@(private)
tree_replace_child :: proc "contextless" (
t: ^$T/Tree($Value),
parent, old_child, new_child: ^Node(Value),
) {
if parent != nil {
if old_child == parent._left {
parent._left = new_child
} else {
parent._right = new_child
}
} else {
t._root = new_child
}
}
@(private)
tree_rotate :: proc "contextless" (t: ^$T/Tree($Value), a: ^Node(Value), sign: i8) {
b := node_get_child(a, -sign)
e := node_get_child(b, +sign)
p := a._parent
node_set_child(a, -sign, e)
a._parent = b
node_set_child(b, +sign, a)
b._parent = p
if e != nil {
e._parent = a
}
tree_replace_child(t, p, a, b)
}
@(private)
tree_double_rotate :: proc "contextless" (
t: ^$T/Tree($Value),
b, a: ^Node(Value),
sign: i8,
) -> ^Node(Value) {
e := node_get_child(b, +sign)
f := node_get_child(e, -sign)
g := node_get_child(e, +sign)
p := a._parent
e_bal := e._balance
node_set_child(a, -sign, g)
a_bal := -e_bal
if sign * e_bal >= 0 {
a_bal = 0
}
node_set_parent_balance(a, e, a_bal)
node_set_child(b, +sign, f)
b_bal := -e_bal
if sign * e_bal <= 0 {
b_bal = 0
}
node_set_parent_balance(b, e, b_bal)
node_set_child(e, +sign, a)
node_set_child(e, -sign, b)
node_set_parent_balance(e, p, 0)
if g != nil {
g._parent = a
}
if f != nil {
f._parent = b
}
tree_replace_child(t, p, a, e)
return e
}
@(private)
tree_handle_subtree_growth :: proc "contextless" (
t: ^$T/Tree($Value),
node, parent: ^Node(Value),
sign: i8,
) -> bool {
old_balance_factor := parent._balance
if old_balance_factor == 0 {
node_adjust_balance_factor(parent, sign)
return false
}
new_balance_factor := old_balance_factor + sign
if new_balance_factor == 0 {
node_adjust_balance_factor(parent, sign)
return true
}
if sign * node._balance > 0 {
tree_rotate(t, parent, -sign)
node_adjust_balance_factor(parent, -sign)
node_adjust_balance_factor(node, -sign)
} else {
tree_double_rotate(t, node, parent, -sign)
}
return true
}
@(private)
tree_rebalance_after_insert :: proc "contextless" (t: ^$T/Tree($Value), inserted: ^Node(Value)) {
node, parent := inserted, inserted._parent
switch {
case parent == nil:
return
case node == parent._left:
node_adjust_balance_factor(parent, -1)
case:
node_adjust_balance_factor(parent, +1)
}
if parent._balance == 0 {
return
}
for done := false; !done; {
node = parent
if parent = node._parent; parent == nil {
return
}
if node == parent._left {
done = tree_handle_subtree_growth(t, node, parent, -1)
} else {
done = tree_handle_subtree_growth(t, node, parent, +1)
}
}
}
@(private)
tree_swap_with_successor :: proc "contextless" (
t: ^$T/Tree($Value),
x: ^Node(Value),
) -> (
^Node(Value),
bool,
) {
ret: ^Node(Value)
left_deleted: bool
y := x._right
if y._left == nil {
ret = y
} else {
q: ^Node(Value)
for {
q = y
if y = y._left; y._left == nil {
break
}
}
if q._left = y._right; q._left != nil {
q._left._parent = q
}
y._right = x._right
x._right._parent = y
ret = q
left_deleted = true
}
y._left = x._left
x._left._parent = y
y._parent = x._parent
y._balance = x._balance
tree_replace_child(t, x._parent, x, y)
return ret, left_deleted
}
@(private)
tree_handle_subtree_shrink :: proc "contextless" (
t: ^$T/Tree($Value),
parent: ^Node(Value),
sign: i8,
left_deleted: ^bool,
) -> ^Node(Value) {
old_balance_factor := parent._balance
if old_balance_factor == 0 {
node_adjust_balance_factor(parent, sign)
return nil
}
node: ^Node(Value)
new_balance_factor := old_balance_factor + sign
if new_balance_factor == 0 {
node_adjust_balance_factor(parent, sign)
node = parent
} else {
node = node_get_child(parent, sign)
if sign * node._balance >= 0 {
tree_rotate(t, parent, -sign)
if node._balance == 0 {
node_adjust_balance_factor(node, -sign)
return nil
}
node_adjust_balance_factor(parent, -sign)
node_adjust_balance_factor(node, -sign)
} else {
node = tree_double_rotate(t, node, parent, -sign)
}
}
parent := parent
if parent = node._parent; parent != nil {
left_deleted^ = node == parent._left
}
return parent
}
@(private)
node_reset :: proc "contextless" (n: ^Node($Value)) {
// Mostly pointless as n will be deleted after this is called, but
// attempt to be able to catch cases of n not being in the tree.
n._parent = n
n._left = nil
n._right = nil
n._balance = 0
}
@(private)
node_set_parent_balance :: #force_inline proc "contextless" (
n, parent: ^Node($Value),
balance: i8,
) {
n._parent = parent
n._balance = balance
}
@(private)
node_get_child :: #force_inline proc "contextless" (n: ^Node($Value), sign: i8) -> ^Node(Value) {
if sign < 0 {
return n._left
}
return n._right
}
@(private)
node_next_or_prev_in_order :: proc "contextless" (
n: ^Node($Value),
direction: Direction,
) -> ^Node(Value) {
next, tmp: ^Node(Value)
sign := i8(direction)
if next = node_get_child(n, +sign); next != nil {
for {
tmp = node_get_child(next, -sign)
if tmp == nil {
break
}
next = tmp
}
} else {
tmp, next = n, n._parent
for next != nil && tmp == node_get_child(next, +sign) {
tmp, next = next, next._parent
}
}
return next
}
@(private)
node_set_child :: #force_inline proc "contextless" (
n: ^Node($Value),
sign: i8,
child: ^Node(Value),
) {
if sign < 0 {
n._left = child
} else {
n._right = child
}
}
@(private)
node_adjust_balance_factor :: #force_inline proc "contextless" (n: ^Node($Value), amount: i8) {
n._balance += amount
}
@(private)
iterator_first :: proc "contextless" (it: ^Iterator($Value)) {
// This is private because behavior when the user manually calls
// iterator_first followed by iterator_next is unintuitive, since
// the first call to iterator_next MUST return the first node
// instead of advancing so that `for node in iterator_next(&next)`
// works as expected.
switch it._direction {
case .Forward:
it._cur = tree_first_or_last_in_order(it._tree, .Backward)
case .Backward:
it._cur = tree_first_or_last_in_order(it._tree, .Forward)
}
it._next = nil
it._called_next = false
if it._cur != nil {
it._next = node_next_or_prev_in_order(it._cur, it._direction)
}
}
+7 -4
View File
@@ -1,4 +1,4 @@
package dynamic_bit_array
package container_dynamic_bit_array
import "base:intrinsics"
import "core:mem"
@@ -210,8 +210,11 @@ set :: proc(ba: ^Bit_Array, #any_int index: uint, set_to: bool = true, allocator
ba.max_index = max(idx, ba.max_index)
if set_to{ ba.bits[leg_index] |= 1 << uint(bit_index) }
else { ba.bits[leg_index] &= ~(1 << uint(bit_index)) }
if set_to {
ba.bits[leg_index] |= 1 << uint(bit_index)
} else {
ba.bits[leg_index] &~= 1 << uint(bit_index)
}
return true
}
@@ -253,7 +256,7 @@ Inputs:
- index: Which bit in the array
*/
unsafe_unset :: proc(b: ^Bit_Array, bit: int) #no_bounds_check {
b.bits[bit >> INDEX_SHIFT] &= ~(1 << uint(bit & INDEX_MASK))
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).
+40 -41
View File
@@ -1,53 +1,52 @@
package dynamic_bit_array
/*
The Bit Array can be used in several ways:
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:
package test
package test
import "core:fmt"
import "core:container/bit_array"
import "core:fmt"
import "core:container/bit_array"
main :: proc() {
using bit_array
main :: proc() {
using bit_array
bits: Bit_Array
bits: Bit_Array
// returns `true`
fmt.println(set(&bits, 42))
// returns `true`
fmt.println(set(&bits, 42))
// returns `false`, `false`, because this Bit Array wasn't created to allow negative indices.
was_set, was_retrieved := get(&bits, -1)
fmt.println(was_set, was_retrieved)
destroy(&bits)
// returns `false`, `false`, because this Bit Array wasn't created to allow negative indices.
was_set, was_retrieved := get(&bits, -1)
fmt.println(was_set, was_retrieved)
destroy(&bits)
}
- A Bit Array can optionally allow for negative indices, if the minimum value was given during creation:
package test
import "core:fmt"
import "core:container/bit_array"
main :: proc() {
Foo :: enum int {
Negative_Test = -42,
Bar = 420,
Leaves = 69105,
}
-- A Bit Array can optionally allow for negative indices, if the mininum value was given during creation:
using bit_array
package test
bits := create(int(max(Foo)), int(min(Foo)))
defer destroy(bits)
import "core:fmt"
import "core:container/bit_array"
main :: proc() {
Foo :: enum int {
Negative_Test = -42,
Bar = 420,
Leaves = 69105,
}
using bit_array
bits := create(int(max(Foo)), int(min(Foo)))
defer destroy(bits)
fmt.printf("Set(Bar): %v\n", set(bits, Foo.Bar))
fmt.printf("Get(Bar): %v, %v\n", get(bits, Foo.Bar))
fmt.printf("Set(Negative_Test): %v\n", set(bits, Foo.Negative_Test))
fmt.printf("Get(Leaves): %v, %v\n", get(bits, Foo.Leaves))
fmt.printf("Get(Negative_Test): %v, %v\n", get(bits, Foo.Negative_Test))
fmt.printf("Freed.\n")
}
*/
fmt.printf("Set(Bar): %v\n", set(bits, Foo.Bar))
fmt.printf("Get(Bar): %v, %v\n", get(bits, Foo.Bar))
fmt.printf("Set(Negative_Test): %v\n", set(bits, Foo.Negative_Test))
fmt.printf("Get(Leaves): %v, %v\n", get(bits, Foo.Leaves))
fmt.printf("Get(Negative_Test): %v, %v\n", get(bits, Foo.Negative_Test))
fmt.printf("Freed.\n")
}
*/
package container_dynamic_bit_array
+1 -2
View File
@@ -70,8 +70,7 @@ set :: proc(c: ^$C/Cache($Key, $Value), key: Key, value: Value) -> runtime.Alloc
if c.count == c.capacity {
e = c.tail
_remove_node(c, e)
}
else {
} else {
c.count += 1
e = new(Node(Key, Value), c.node_allocator) or_return
}
+2 -2
View File
@@ -189,7 +189,7 @@ pop_front_safe :: proc(q: ^$Q/Queue($T)) -> (elem: T, ok: bool) {
return
}
// Push multiple elements to the front of the queue
// Push multiple elements to the back of the queue
push_back_elems :: proc(q: ^$Q/Queue($T), elems: ..T) -> (ok: bool, err: runtime.Allocator_Error) {
n := uint(builtin.len(elems))
if space(q^) < int(n) {
@@ -241,7 +241,7 @@ clear :: proc(q: ^$Q/Queue($T)) {
}
// Internal growinh procedure
// Internal growing procedure
_grow :: proc(q: ^$Q/Queue($T), min_capacity: uint = 0) -> runtime.Allocator_Error {
new_capacity := max(min_capacity, uint(8), uint(builtin.len(q.data))*2)
n := uint(builtin.len(q.data))
+568
View File
@@ -0,0 +1,568 @@
// This package implements a red-black tree
package container_rbtree
@(require) import "base:intrinsics"
@(require) import "base:runtime"
import "core:slice"
// Originally based on the CC0 implementation from literateprograms.org
// But with API design mimicking `core:container/avl` for ease of use.
// Direction specifies the traversal direction for a tree iterator.
Direction :: enum i8 {
// Backward is the in-order backwards direction.
Backward = -1,
// Forward is the in-order forwards direction.
Forward = 1,
}
Ordering :: slice.Ordering
// Tree is a red-black tree
Tree :: struct($Key: typeid, $Value: typeid) {
// user_data is a parameter that will be passed to the on_remove
// callback.
user_data: rawptr,
// on_remove is an optional callback that can be called immediately
// after a node is removed from the tree.
on_remove: proc(key: Key, value: Value, user_data: rawptr),
_root: ^Node(Key, Value),
_node_allocator: runtime.Allocator,
_cmp_fn: proc(Key, Key) -> Ordering,
_size: int,
}
// Node is a red-black tree node.
//
// WARNING: It is unsafe to mutate value if the node is part of a tree
// if doing so will alter the Node's sort position relative to other
// elements in the tree.
Node :: struct($Key: typeid, $Value: typeid) {
key: Key,
value: Value,
_parent: ^Node(Key, Value),
_left: ^Node(Key, Value),
_right: ^Node(Key, Value),
_color: Color,
}
// Might store this in the node pointer in the future, but that'll require a decent amount of rework to pass ^^N instead of ^N
Color :: enum uintptr {Black = 0, Red = 1}
// Iterator is a tree iterator.
//
// WARNING: It is unsafe to modify the tree while iterating, except via
// the iterator_remove method.
Iterator :: struct($Key: typeid, $Value: typeid) {
_tree: ^Tree(Key, Value),
_cur: ^Node(Key, Value),
_next: ^Node(Key, Value),
_direction: Direction,
_called_next: bool,
}
// init initializes a tree.
init :: proc {
init_ordered,
init_cmp,
}
// init_cmp initializes a tree.
init_cmp :: proc(t: ^$T/Tree($Key, $Value), cmp_fn: proc(a, b: Key) -> Ordering, node_allocator := context.allocator) {
t._root = nil
t._node_allocator = node_allocator
t._cmp_fn = cmp_fn
t._size = 0
}
// init_ordered initializes a tree containing ordered keys, with
// a comparison function that results in an ascending order sort.
init_ordered :: proc(t: ^$T/Tree($Key, $Value), node_allocator := context.allocator) where intrinsics.type_is_ordered(Key) {
init_cmp(t, slice.cmp_proc(Key), node_allocator)
}
// destroy de-initializes a tree.
destroy :: proc(t: ^$T/Tree($Key, $Value), call_on_remove: bool = true) {
iter := iterator(t, .Forward)
for _ in iterator_next(&iter) {
iterator_remove(&iter, call_on_remove)
}
}
len :: proc "contextless" (t: ^$T/Tree($Key, $Value)) -> (node_count: int) {
return t._size
}
// first returns the first node in the tree (in-order) or nil iff
// the tree is empty.
first :: proc "contextless" (t: ^$T/Tree($Key, $Value)) -> ^Node(Key, Value) {
return tree_first_or_last_in_order(t, Direction.Backward)
}
// last returns the last element in the tree (in-order) or nil iff
// the tree is empty.
last :: proc "contextless" (t: ^$T/Tree($Key, $Value)) -> ^Node(Key, Value) {
return tree_first_or_last_in_order(t, Direction.Forward)
}
// find finds the key in the tree, and returns the corresponding node, or nil iff the value is not present.
find :: proc(t: ^$T/Tree($Key, $Value), key: Key) -> (node: ^Node(Key, Value)) {
node = t._root
for node != nil {
switch t._cmp_fn(key, node.key) {
case .Equal: return node
case .Less: node = node._left
case .Greater: node = node._right
}
}
return node
}
// find_value finds the key in the tree, and returns the corresponding value, or nil iff the value is not present.
find_value :: proc(t: ^$T/Tree($Key, $Value), key: Key) -> (value: Value, ok: bool) #optional_ok {
if n := find(t, key); n != nil {
return n.value, true
}
return
}
// find_or_insert attempts to insert the value into the tree, and returns
// the node, a boolean indicating if the value was inserted, and the
// node allocator error if relevant. If the value is already present, the existing node is updated.
find_or_insert :: proc(t: ^$T/Tree($Key, $Value), key: Key, value: Value) -> (n: ^Node(Key, Value), inserted: bool, err: runtime.Allocator_Error) {
n_ptr := &t._root
for n_ptr^ != nil {
n = n_ptr^
switch t._cmp_fn(key, n.key) {
case .Less:
n_ptr = &n._left
case .Greater:
n_ptr = &n._right
case .Equal:
return
}
}
_parent := n
n = new_clone(Node(Key, Value){key=key, value=value, _parent=_parent, _color=.Red}, t._node_allocator) or_return
n_ptr^ = n
insert_case1(t, n)
t._size += 1
return n, true, nil
}
// remove removes a node or value from the tree, and returns true iff the
// removal was successful. While the node's value will be left intact,
// the node itself will be freed via the tree's node allocator.
remove :: proc {
remove_key,
remove_node,
}
// remove_value removes a value from the tree, and returns true iff the
// removal was successful. While the node's key + value will be left intact,
// the node itself will be freed via the tree's node allocator.
remove_key :: proc(t: ^$T/Tree($Key, $Value), key: Key, call_on_remove := true) -> bool {
n := find(t, key)
if n == nil {
return false // Key not found, nothing to do
}
return remove_node(t, n, call_on_remove)
}
// remove_node removes a node from the tree, and returns true iff the
// removal was successful. While the node's key + value will be left intact,
// the node itself will be freed via the tree's node allocator.
remove_node :: proc(t: ^$T/Tree($Key, $Value), node: ^$N/Node(Key, Value), call_on_remove := true) -> (found: bool) {
if node._parent == node || (node._parent == nil && t._root != node) {
return false // Don't touch self-parented or dangling nodes.
}
node := node
if node._left != nil && node._right != nil {
// Copy key + value from predecessor and delete it instead
predecessor := maximum_node(node._left)
node.key = predecessor.key
node.value = predecessor.value
node = predecessor
}
child := node._right == nil ? node._left : node._right
if node_color(node) == .Black {
node._color = node_color(child)
remove_case1(t, node)
}
replace_node(t, node, child)
if node._parent == nil && child != nil {
child._color = .Black // root should be black
}
if call_on_remove && t.on_remove != nil {
t.on_remove(node.key, node.value, t.user_data)
}
free(node, t._node_allocator)
t._size -= 1
return true
}
// iterator returns a tree iterator in the specified direction.
iterator :: proc "contextless" (t: ^$T/Tree($Key, $Value), direction: Direction) -> Iterator(Key, Value) {
it: Iterator(Key, Value)
it._tree = cast(^Tree(Key, Value))t
it._direction = direction
iterator_first(&it)
return it
}
// iterator_from_pos returns a tree iterator in the specified direction,
// spanning the range [pos, last] (inclusive).
iterator_from_pos :: proc "contextless" (t: ^$T/Tree($Key, $Value), pos: ^Node(Key, Value), direction: Direction) -> Iterator(Key, Value) {
it: Iterator(Key, Value)
it._tree = transmute(^Tree(Key, Value))t
it._direction = direction
it._next = nil
it._called_next = false
if it._cur = pos; pos != nil {
it._next = node_next_or_prev_in_order(it._cur, it._direction)
}
return it
}
// iterator_get returns the node currently pointed to by the iterator,
// or nil iff the node has been removed, the tree is empty, or the end
// of the tree has been reached.
iterator_get :: proc "contextless" (it: ^$I/Iterator($Key, $Value)) -> ^Node(Key, Value) {
return it._cur
}
// iterator_remove removes the node currently pointed to by the iterator,
// and returns true iff the removal was successful. Semantics are the
// same as the Tree remove.
iterator_remove :: proc(it: ^$I/Iterator($Key, $Value), call_on_remove: bool = true) -> bool {
if it._cur == nil {
return false
}
ok := remove_node(it._tree, it._cur , call_on_remove)
if ok {
it._cur = nil
}
return ok
}
// iterator_next advances the iterator and returns the (node, true) or
// or (nil, false) iff the end of the tree has been reached.
//
// Note: The first call to iterator_next will return the first node instead
// of advancing the iterator.
iterator_next :: proc "contextless" (it: ^$I/Iterator($Key, $Value)) -> (^Node(Key, Value), bool) {
// This check is needed so that the first element gets returned from
// a brand-new iterator, and so that the somewhat contrived case where
// iterator_remove is called before the first call to iterator_next
// returns the correct value.
if !it._called_next {
it._called_next = true
// There can be the contrived case where iterator_remove is
// called before ever calling iterator_next, which needs to be
// handled as an actual call to next.
//
// If this happens it._cur will be nil, so only return the
// first value, if it._cur is valid.
if it._cur != nil {
return it._cur, true
}
}
if it._next == nil {
return nil, false
}
it._cur = it._next
it._next = node_next_or_prev_in_order(it._cur, it._direction)
return it._cur, true
}
@(private)
tree_first_or_last_in_order :: proc "contextless" (t: ^$T/Tree($Key, $Value), direction: Direction) -> ^Node(Key, Value) {
first, sign := t._root, i8(direction)
if first != nil {
for {
tmp := node_get_child(first, sign)
if tmp == nil {
break
}
first = tmp
}
}
return first
}
@(private)
node_get_child :: #force_inline proc "contextless" (n: ^Node($Key, $Value), sign: i8) -> ^Node(Key, Value) {
if sign < 0 {
return n._left
}
return n._right
}
@(private)
node_next_or_prev_in_order :: proc "contextless" (n: ^Node($Key, $Value), direction: Direction) -> ^Node(Key, Value) {
next, tmp: ^Node(Key, Value)
sign := i8(direction)
if next = node_get_child(n, +sign); next != nil {
for {
tmp = node_get_child(next, -sign)
if tmp == nil {
break
}
next = tmp
}
} else {
tmp, next = n, n._parent
for next != nil && tmp == node_get_child(next, +sign) {
tmp, next = next, next._parent
}
}
return next
}
@(private)
iterator_first :: proc "contextless" (it: ^Iterator($Key, $Value)) {
// This is private because behavior when the user manually calls
// iterator_first followed by iterator_next is unintuitive, since
// the first call to iterator_next MUST return the first node
// instead of advancing so that `for node in iterator_next(&next)`
// works as expected.
switch it._direction {
case .Forward:
it._cur = tree_first_or_last_in_order(it._tree, .Backward)
case .Backward:
it._cur = tree_first_or_last_in_order(it._tree, .Forward)
}
it._next = nil
it._called_next = false
if it._cur != nil {
it._next = node_next_or_prev_in_order(it._cur, it._direction)
}
}
@(private)
grand_parent :: proc(n: ^$N/Node($Key, $Value)) -> (g: ^N) {
return n._parent._parent
}
@(private)
sibling :: proc(n: ^$N/Node($Key, $Value)) -> (s: ^N) {
if n == n._parent._left {
return n._parent._right
} else {
return n._parent._left
}
}
@(private)
uncle :: proc(n: ^$N/Node($Key, $Value)) -> (u: ^N) {
return sibling(n._parent)
}
@(private)
rotate__left :: proc(t: ^$T/Tree($Key, $Value), n: ^$N/Node(Key, Value)) {
r := n._right
replace_node(t, n, r)
n._right = r._left
if r._left != nil {
r._left._parent = n
}
r._left = n
n._parent = r
}
@(private)
rotate__right :: proc(t: ^$T/Tree($Key, $Value), n: ^$N/Node(Key, Value)) {
l := n._left
replace_node(t, n, l)
n._left = l._right
if l._right != nil {
l._right._parent = n
}
l._right = n
n._parent = l
}
@(private)
replace_node :: proc(t: ^$T/Tree($Key, $Value), old_n: ^$N/Node(Key, Value), new_n: ^N) {
if old_n._parent == nil {
t._root = new_n
} else {
if (old_n == old_n._parent._left) {
old_n._parent._left = new_n
} else {
old_n._parent._right = new_n
}
}
if new_n != nil {
new_n._parent = old_n._parent
}
}
@(private)
insert_case1 :: proc(t: ^$T/Tree($Key, $Value), n: ^$N/Node(Key, Value)) {
if n._parent == nil {
n._color = .Black
} else {
insert_case2(t, n)
}
}
@(private)
insert_case2 :: proc(t: ^$T/Tree($Key, $Value), n: ^$N/Node(Key, Value)) {
if node_color(n._parent) == .Black {
return // Tree is still valid
} else {
insert_case3(t, n)
}
}
@(private)
insert_case3 :: proc(t: ^$T/Tree($Key, $Value), n: ^$N/Node(Key, Value)) {
if node_color(uncle(n)) == .Red {
n._parent._color = .Black
uncle(n)._color = .Black
grand_parent(n)._color = .Red
insert_case1(t, grand_parent(n))
} else {
insert_case4(t, n)
}
}
@(private)
insert_case4 :: proc(t: ^$T/Tree($Key, $Value), n: ^$N/Node(Key, Value)) {
n := n
if n == n._parent._right && n._parent == grand_parent(n)._left {
rotate__left(t, n._parent)
n = n._left
} else if n == n._parent._left && n._parent == grand_parent(n)._right {
rotate__right(t, n._parent)
n = n._right
}
insert_case5(t, n)
}
@(private)
insert_case5 :: proc(t: ^$T/Tree($Key, $Value), n: ^$N/Node(Key, Value)) {
n._parent._color = .Black
grand_parent(n)._color = .Red
if n == n._parent._left && n._parent == grand_parent(n)._left {
rotate__right(t, grand_parent(n))
} else {
rotate__left(t, grand_parent(n))
}
}
// The maximum_node() helper function just walks _right until it reaches the last non-leaf:
@(private)
maximum_node :: proc(n: ^$N/Node($Key, $Value)) -> (max_node: ^N) {
n := n
for n._right != nil {
n = n._right
}
return n
}
@(private)
remove_case1 :: proc(t: ^$T/Tree($Key, $Value), n: ^$N/Node(Key, Value)) {
if n._parent == nil {
return
} else {
remove_case2(t, n)
}
}
@(private)
remove_case2 :: proc(t: ^$T/Tree($Key, $Value), n: ^$N/Node(Key, Value)) {
if node_color(sibling(n)) == .Red {
n._parent._color = .Red
sibling(n)._color = .Black
if n == n._parent._left {
rotate__left(t, n._parent)
} else {
rotate__right(t, n._parent)
}
}
remove_case3(t, n)
}
@(private)
remove_case3 :: proc(t: ^$T/Tree($Key, $Value), n: ^$N/Node(Key, Value)) {
if node_color(n._parent) == .Black &&
node_color(sibling(n)) == .Black &&
node_color(sibling(n)._left) == .Black &&
node_color(sibling(n)._right) == .Black {
sibling(n)._color = .Red
remove_case1(t, n._parent)
} else {
remove_case4(t, n)
}
}
@(private)
remove_case4 :: proc(t: ^$T/Tree($Key, $Value), n: ^$N/Node(Key, Value)) {
if node_color(n._parent) == .Red &&
node_color(sibling(n)) == .Black &&
node_color(sibling(n)._left) == .Black &&
node_color(sibling(n)._right) == .Black {
sibling(n)._color = .Red
n._parent._color = .Black
} else {
remove_case5(t, n)
}
}
@(private)
remove_case5 :: proc(t: ^$T/Tree($Key, $Value), n: ^$N/Node(Key, Value)) {
if n == n._parent._left &&
node_color(sibling(n)) == .Black &&
node_color(sibling(n)._left) == .Red &&
node_color(sibling(n)._right) == .Black {
sibling(n)._color = .Red
sibling(n)._left._color = .Black
rotate__right(t, sibling(n))
} else if n == n._parent._right &&
node_color(sibling(n)) == .Black &&
node_color(sibling(n)._right) == .Red &&
node_color(sibling(n)._left) == .Black {
sibling(n)._color = .Red
sibling(n)._right._color = .Black
rotate__left(t, sibling(n))
}
remove_case6(t, n)
}
@(private)
remove_case6 :: proc(t: ^$T/Tree($Key, $Value), n: ^$N/Node(Key, Value)) {
sibling(n)._color = node_color(n._parent)
n._parent._color = .Black
if n == n._parent._left {
sibling(n)._right._color = .Black
rotate__left(t, n._parent)
} else {
sibling(n)._left._color = .Black
rotate__right(t, n._parent)
}
}
node_color :: proc(n: ^$N/Node($Key, $Value)) -> (c: Color) {
return n == nil ? .Black : n._color
}
+4 -4
View File
@@ -119,20 +119,20 @@ consume :: proc "odin" (a: ^$A/Small_Array($N, $T), count: int, loc := #caller_l
}
ordered_remove :: proc "contextless" (a: ^$A/Small_Array($N, $T), index: int, loc := #caller_location) #no_bounds_check {
runtime.bounds_check_error_loc(loc, index, a.len)
if index+1 < a.len {
runtime.bounds_check_error_loc(loc, index, a.len)
if index+1 < a.len {
copy(a.data[index:], a.data[index+1:])
}
a.len -= 1
}
unordered_remove :: proc "contextless" (a: ^$A/Small_Array($N, $T), index: int, loc := #caller_location) #no_bounds_check {
runtime.bounds_check_error_loc(loc, index, a.len)
runtime.bounds_check_error_loc(loc, index, a.len)
n := a.len-1
if index != n {
a.data[index] = a.data[n]
}
a.len -= 1
a.len -= 1
}
clear :: proc "contextless" (a: ^$A/Small_Array($N, $T)) {
@@ -61,7 +61,7 @@ add_dependency :: proc(sorter: ^$S/Sorter($K), key, dependency: K) -> bool {
}
find.dependents[key] = true
find = &sorter.relations[key]
find = &sorter.relations[key]
if find == nil {
find = map_insert(&sorter.relations, key, make_relations(sorter))
}
+16 -70
View File
@@ -1,84 +1,30 @@
# crypto
A cryptography library for the Odin language
A cryptography library for the Odin language.
## Supported
This library offers various algorithms implemented in Odin.
Please see the chart below for some of the options.
## Hashing algorithms
| Algorithm | |
|:-------------------------------------------------------------------------------------------------------------|:-----------------|
| [BLAKE2B](https://datatracker.ietf.org/doc/html/rfc7693) | &#10004;&#65039; |
| [BLAKE2S](https://datatracker.ietf.org/doc/html/rfc7693) | &#10004;&#65039; |
| [SHA-2](https://csrc.nist.gov/csrc/media/publications/fips/180/2/archive/2002-08-01/documents/fips180-2.pdf) | &#10004;&#65039; |
| [SHA-3](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf) | &#10004;&#65039; |
| [SHAKE](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf) | &#10004;&#65039; |
| [SM3](https://datatracker.ietf.org/doc/html/draft-sca-cfrg-sm3-02) | &#10004;&#65039; |
| legacy/[Keccak](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf) | &#10004;&#65039; |
| legacy/[MD5](https://datatracker.ietf.org/doc/html/rfc1321) | &#10004;&#65039; |
| legacy/[SHA-1](https://datatracker.ietf.org/doc/html/rfc3174) | &#10004;&#65039; |
#### High level API
Each hash algorithm contains a procedure group named `hash`, or if the algorithm provides more than one digest size `hash_<size>`\*.
Included in these groups are six procedures.
- `hash_string` - Hash a given string and return the computed hash. Just calls `hash_bytes` internally
- `hash_bytes` - Hash a given byte slice and return the computed hash
- `hash_string_to_buffer` - Hash a given string and put the computed hash in the second proc parameter. Just calls `hash_bytes_to_buffer` internally
- `hash_bytes_to_buffer` - Hash a given string and put the computed hash in the second proc parameter. The destination buffer has to be at least as big as the digest size of the hash
- `hash_stream` - Takes a stream from io.Stream and returns the computed hash from it
- `hash_file` - Takes a file handle and returns the computed hash from it. A second optional boolean parameter controls if the file is streamed (this is the default) or read at once (set to true)
\* On some algorithms there is another part to the name, since they might offer control about additional parameters.
For instance, `SHA-2` offers different sizes.
Computing a 512-bit hash is therefore achieved by calling `sha2.hash_512(...)`.
#### Low level API
The above mentioned procedures internally call three procedures: `init`, `update` and `final`.
You may also directly call them, if you wish.
#### Example
```odin
package crypto_example
// Import the desired package
import "core:crypto/blake2b"
main :: proc() {
input := "foo"
// Compute the hash, using the high level API
computed_hash := blake2b.hash(input)
// Variant that takes a destination buffer, instead of returning the computed hash
hash := make([]byte, sha2.DIGEST_SIZE) // @note: Destination buffer has to be at least as big as the digest size of the hash
blake2b.hash(input, hash[:])
// Compute the hash, using the low level API
ctx: blake2b.Context
computed_hash_low: [blake2b.DIGEST_SIZE]byte
blake2b.init(&ctx)
blake2b.update(&ctx, transmute([]byte)input)
blake2b.final(&ctx, computed_hash_low[:])
}
```
For example uses of all available algorithms, please see the tests within `tests/core/crypto`.
This package offers various algorithms implemented in Odin, along with
useful helpers such as access to the system entropy source, and a
constant-time byte comparison.
## Implementation considerations
- The crypto packages are not thread-safe.
- Best-effort is make to mitigate timing side-channels on reasonable
architectures. Architectures that are known to be unreasonable include
architectures. Architectures that are known to be unreasonable include
but are not limited to i386, i486, and WebAssembly.
- Some but not all of the packages attempt to santize sensitive data,
however this is not done consistently through the library at the moment.
As Thomas Pornin puts it "In general, such memory cleansing is a fool's
quest."
- Implementations assume a 64-bit architecture (64-bit integer arithmetic
is fast, and includes add-with-carry, sub-with-borrow, and full-result
multiply).
- Hardware sidechannels are explicitly out of scope for this package.
Notable examples include but are not limited to:
- Power/RF side-channels etc.
- Fault injection attacks etc.
- Hardware vulnerabilities ("apply mitigations or buy a new CPU").
- The packages attempt to santize sensitive data, however this is, and
will remain a "best-effort" implementation decision. As Thomas Pornin
puts it "In general, such memory cleansing is a fool's quest."
- All of these packages have not received independent third party review.
## License
+28
View File
@@ -0,0 +1,28 @@
package _aes
// KEY_SIZE_128 is the AES-128 key size in bytes.
KEY_SIZE_128 :: 16
// KEY_SIZE_192 is the AES-192 key size in bytes.
KEY_SIZE_192 :: 24
// KEY_SIZE_256 is the AES-256 key size in bytes.
KEY_SIZE_256 :: 32
// BLOCK_SIZE is the AES block size in bytes.
BLOCK_SIZE :: 16
// ROUNDS_128 is the number of rounds for AES-128.
ROUNDS_128 :: 10
// ROUNDS_192 is the number of rounds for AES-192.
ROUNDS_192 :: 12
// ROUNDS_256 is the number of rounds for AES-256.
ROUNDS_256 :: 14
// GHASH_KEY_SIZE is the GHASH key size in bytes.
GHASH_KEY_SIZE :: 16
// GHASH_BLOCK_SIZE is the GHASH block size in bytes.
GHASH_BLOCK_SIZE :: 16
// GHASH_TAG_SIZE is the GHASH tag size in bytes.
GHASH_TAG_SIZE :: 16
// RCON is the AES keyschedule round constants.
RCON := [10]byte{0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36}
+96
View File
@@ -0,0 +1,96 @@
package aes_ct64
import "base:intrinsics"
import "core:mem"
STRIDE :: 4
// Context is a keyed AES (ECB) instance.
Context :: struct {
_sk_exp: [120]u64,
_num_rounds: int,
_is_initialized: bool,
}
// init initializes a context for AES with the provided key.
init :: proc(ctx: ^Context, key: []byte) {
skey: [30]u64 = ---
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)
store_blockx1(dst, &q)
}
// 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)
store_blockx1(dst, &q)
}
// 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
n := len(src)
for n > 4 {
load_blocks(&q, src[0:4])
_encrypt(&q, ctx._sk_exp[:], ctx._num_rounds)
store_blocks(dst[0:4], &q)
src = src[4:]
dst = dst[4:]
n -= 4
}
if n > 0 {
load_blocks(&q, src)
_encrypt(&q, ctx._sk_exp[:], ctx._num_rounds)
store_blocks(dst, &q)
}
}
// 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
n := len(src)
for n > 4 {
load_blocks(&q, src[0:4])
_decrypt(&q, ctx._sk_exp[:], ctx._num_rounds)
store_blocks(dst[0:4], &q)
src = src[4:]
dst = dst[4:]
n -= 4
}
if n > 0 {
load_blocks(&q, src)
_decrypt(&q, ctx._sk_exp[:], ctx._num_rounds)
store_blocks(dst, &q)
}
}
// reset sanitizes the Context. The Context must be re-initialized to
// be used again.
reset :: proc(ctx: ^Context) {
mem.zero_explicit(ctx, size_of(ctx))
}
+265
View File
@@ -0,0 +1,265 @@
// Copyright (c) 2016 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.
package aes_ct64
import "base:intrinsics"
// Bitsliced AES for 64-bit general purpose (integer) registers. Each
// invocation will process up to 4 blocks at a time. This implementation
// is derived from the BearSSL ct64 code, and distributed under a 1-clause
// BSD license with permission from the original author.
//
// WARNING: "hic sunt dracones"
//
// This package also deliberately exposes enough internals to be able to
// function as a replacement for `AESENC` and `AESDEC` from AES-NI, to
// allow the implementation of non-AES primitives that use the AES round
// function such as AEGIS and Deoxys-II. This should ONLY be done when
// implementing something other than AES itself.
sub_bytes :: proc "contextless" (q: ^[8]u64) {
// This S-box implementation is a straightforward translation of
// the circuit described by Boyar and Peralta in "A new
// combinational logic minimization technique with applications
// to cryptology" (https://eprint.iacr.org/2009/191.pdf).
//
// Note that variables x* (input) and s* (output) are numbered
// in "reverse" order (x0 is the high bit, x7 is the low bit).
x0 := q[7]
x1 := q[6]
x2 := q[5]
x3 := q[4]
x4 := q[3]
x5 := q[2]
x6 := q[1]
x7 := q[0]
// Top linear transformation.
y14 := x3 ~ x5
y13 := x0 ~ x6
y9 := x0 ~ x3
y8 := x0 ~ x5
t0 := x1 ~ x2
y1 := t0 ~ x7
y4 := y1 ~ x3
y12 := y13 ~ y14
y2 := y1 ~ x0
y5 := y1 ~ x6
y3 := y5 ~ y8
t1 := x4 ~ y12
y15 := t1 ~ x5
y20 := t1 ~ x1
y6 := y15 ~ x7
y10 := y15 ~ t0
y11 := y20 ~ y9
y7 := x7 ~ y11
y17 := y10 ~ y11
y19 := y10 ~ y8
y16 := t0 ~ y11
y21 := y13 ~ y16
y18 := x0 ~ y16
// Non-linear section.
t2 := y12 & y15
t3 := y3 & y6
t4 := t3 ~ t2
t5 := y4 & x7
t6 := t5 ~ t2
t7 := y13 & y16
t8 := y5 & y1
t9 := t8 ~ t7
t10 := y2 & y7
t11 := t10 ~ t7
t12 := y9 & y11
t13 := y14 & y17
t14 := t13 ~ t12
t15 := y8 & y10
t16 := t15 ~ t12
t17 := t4 ~ t14
t18 := t6 ~ t16
t19 := t9 ~ t14
t20 := t11 ~ t16
t21 := t17 ~ y20
t22 := t18 ~ y19
t23 := t19 ~ y21
t24 := t20 ~ y18
t25 := t21 ~ t22
t26 := t21 & t23
t27 := t24 ~ t26
t28 := t25 & t27
t29 := t28 ~ t22
t30 := t23 ~ t24
t31 := t22 ~ t26
t32 := t31 & t30
t33 := t32 ~ t24
t34 := t23 ~ t33
t35 := t27 ~ t33
t36 := t24 & t35
t37 := t36 ~ t34
t38 := t27 ~ t36
t39 := t29 & t38
t40 := t25 ~ t39
t41 := t40 ~ t37
t42 := t29 ~ t33
t43 := t29 ~ t40
t44 := t33 ~ t37
t45 := t42 ~ t41
z0 := t44 & y15
z1 := t37 & y6
z2 := t33 & x7
z3 := t43 & y16
z4 := t40 & y1
z5 := t29 & y7
z6 := t42 & y11
z7 := t45 & y17
z8 := t41 & y10
z9 := t44 & y12
z10 := t37 & y3
z11 := t33 & y4
z12 := t43 & y13
z13 := t40 & y5
z14 := t29 & y2
z15 := t42 & y9
z16 := t45 & y14
z17 := t41 & y8
// Bottom linear transformation.
t46 := z15 ~ z16
t47 := z10 ~ z11
t48 := z5 ~ z13
t49 := z9 ~ z10
t50 := z2 ~ z12
t51 := z2 ~ z5
t52 := z7 ~ z8
t53 := z0 ~ z3
t54 := z6 ~ z7
t55 := z16 ~ z17
t56 := z12 ~ t48
t57 := t50 ~ t53
t58 := z4 ~ t46
t59 := z3 ~ t54
t60 := t46 ~ t57
t61 := z14 ~ t57
t62 := t52 ~ t58
t63 := t49 ~ t58
t64 := z4 ~ t59
t65 := t61 ~ t62
t66 := z1 ~ t63
s0 := t59 ~ t63
s6 := t56 ~ ~t62
s7 := t48 ~ ~t60
t67 := t64 ~ t65
s3 := t53 ~ t66
s4 := t51 ~ t66
s5 := t47 ~ t65
s1 := t64 ~ ~s3
s2 := t55 ~ ~t67
q[7] = s0
q[6] = s1
q[5] = s2
q[4] = s3
q[3] = s4
q[2] = s5
q[1] = s6
q[0] = s7
}
orthogonalize :: proc "contextless" (q: ^[8]u64) {
CL2 :: 0x5555555555555555
CH2 :: 0xAAAAAAAAAAAAAAAA
q[0], q[1] = (q[0] & CL2) | ((q[1] & CL2) << 1), ((q[0] & CH2) >> 1) | (q[1] & CH2)
q[2], q[3] = (q[2] & CL2) | ((q[3] & CL2) << 1), ((q[2] & CH2) >> 1) | (q[3] & CH2)
q[4], q[5] = (q[4] & CL2) | ((q[5] & CL2) << 1), ((q[4] & CH2) >> 1) | (q[5] & CH2)
q[6], q[7] = (q[6] & CL2) | ((q[7] & CL2) << 1), ((q[6] & CH2) >> 1) | (q[7] & CH2)
CL4 :: 0x3333333333333333
CH4 :: 0xCCCCCCCCCCCCCCCC
q[0], q[2] = (q[0] & CL4) | ((q[2] & CL4) << 2), ((q[0] & CH4) >> 2) | (q[2] & CH4)
q[1], q[3] = (q[1] & CL4) | ((q[3] & CL4) << 2), ((q[1] & CH4) >> 2) | (q[3] & CH4)
q[4], q[6] = (q[4] & CL4) | ((q[6] & CL4) << 2), ((q[4] & CH4) >> 2) | (q[6] & CH4)
q[5], q[7] = (q[5] & CL4) | ((q[7] & CL4) << 2), ((q[5] & CH4) >> 2) | (q[7] & CH4)
CL8 :: 0x0F0F0F0F0F0F0F0F
CH8 :: 0xF0F0F0F0F0F0F0F0
q[0], q[4] = (q[0] & CL8) | ((q[4] & CL8) << 4), ((q[0] & CH8) >> 4) | (q[4] & CH8)
q[1], q[5] = (q[1] & CL8) | ((q[5] & CL8) << 4), ((q[1] & CH8) >> 4) | (q[5] & CH8)
q[2], q[6] = (q[2] & CL8) | ((q[6] & CL8) << 4), ((q[2] & CH8) >> 4) | (q[6] & CH8)
q[3], q[7] = (q[3] & CL8) | ((q[7] & CL8) << 4), ((q[3] & CH8) >> 4) | (q[7] & CH8)
}
@(require_results)
interleave_in :: proc "contextless" (w: []u32) -> (q0, q1: u64) #no_bounds_check {
if len(w) < 4 {
intrinsics.trap()
}
x0, x1, x2, x3 := u64(w[0]), u64(w[1]), u64(w[2]), u64(w[3])
x0 |= (x0 << 16)
x1 |= (x1 << 16)
x2 |= (x2 << 16)
x3 |= (x3 << 16)
x0 &= 0x0000FFFF0000FFFF
x1 &= 0x0000FFFF0000FFFF
x2 &= 0x0000FFFF0000FFFF
x3 &= 0x0000FFFF0000FFFF
x0 |= (x0 << 8)
x1 |= (x1 << 8)
x2 |= (x2 << 8)
x3 |= (x3 << 8)
x0 &= 0x00FF00FF00FF00FF
x1 &= 0x00FF00FF00FF00FF
x2 &= 0x00FF00FF00FF00FF
x3 &= 0x00FF00FF00FF00FF
q0 = x0 | (x2 << 8)
q1 = x1 | (x3 << 8)
return
}
@(require_results)
interleave_out :: proc "contextless" (q0, q1: u64) -> (w0, w1, w2, w3: u32) {
x0 := q0 & 0x00FF00FF00FF00FF
x1 := q1 & 0x00FF00FF00FF00FF
x2 := (q0 >> 8) & 0x00FF00FF00FF00FF
x3 := (q1 >> 8) & 0x00FF00FF00FF00FF
x0 |= (x0 >> 8)
x1 |= (x1 >> 8)
x2 |= (x2 >> 8)
x3 |= (x3 >> 8)
x0 &= 0x0000FFFF0000FFFF
x1 &= 0x0000FFFF0000FFFF
x2 &= 0x0000FFFF0000FFFF
x3 &= 0x0000FFFF0000FFFF
w0 = u32(x0) | u32(x0 >> 16)
w1 = u32(x1) | u32(x1 >> 16)
w2 = u32(x2) | u32(x2 >> 16)
w3 = u32(x3) | u32(x3 >> 16)
return
}
@(private)
rotr32 :: #force_inline proc "contextless" (x: u64) -> u64 {
return (x << 32) | (x >> 32)
}
+135
View File
@@ -0,0 +1,135 @@
// Copyright (c) 2016 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.
package aes_ct64
import "base:intrinsics"
inv_sub_bytes :: proc "contextless" (q: ^[8]u64) {
// AES S-box is:
// S(x) = A(I(x)) ^ 0x63
// where I() is inversion in GF(256), and A() is a linear
// transform (0 is formally defined to be its own inverse).
// Since inversion is an involution, the inverse S-box can be
// computed from the S-box as:
// iS(x) = B(S(B(x ^ 0x63)) ^ 0x63)
// where B() is the inverse of A(). Indeed, for any y in GF(256):
// iS(S(y)) = B(A(I(B(A(I(y)) ^ 0x63 ^ 0x63))) ^ 0x63 ^ 0x63) = y
//
// Note: we reuse the implementation of the forward S-box,
// instead of duplicating it here, so that total code size is
// lower. By merging the B() transforms into the S-box circuit
// we could make faster CBC decryption, but CBC decryption is
// already quite faster than CBC encryption because we can
// process four blocks in parallel.
q0 := ~q[0]
q1 := ~q[1]
q2 := q[2]
q3 := q[3]
q4 := q[4]
q5 := ~q[5]
q6 := ~q[6]
q7 := q[7]
q[7] = q1 ~ q4 ~ q6
q[6] = q0 ~ q3 ~ q5
q[5] = q7 ~ q2 ~ q4
q[4] = q6 ~ q1 ~ q3
q[3] = q5 ~ q0 ~ q2
q[2] = q4 ~ q7 ~ q1
q[1] = q3 ~ q6 ~ q0
q[0] = q2 ~ q5 ~ q7
sub_bytes(q)
q0 = ~q[0]
q1 = ~q[1]
q2 = q[2]
q3 = q[3]
q4 = q[4]
q5 = ~q[5]
q6 = ~q[6]
q7 = q[7]
q[7] = q1 ~ q4 ~ q6
q[6] = q0 ~ q3 ~ q5
q[5] = q7 ~ q2 ~ q4
q[4] = q6 ~ q1 ~ q3
q[3] = q5 ~ q0 ~ q2
q[2] = q4 ~ q7 ~ q1
q[1] = q3 ~ q6 ~ q0
q[0] = q2 ~ q5 ~ q7
}
inv_shift_rows :: proc "contextless" (q: ^[8]u64) {
for x, i in q {
q[i] =
(x & 0x000000000000FFFF) |
((x & 0x000000000FFF0000) << 4) |
((x & 0x00000000F0000000) >> 12) |
((x & 0x000000FF00000000) << 8) |
((x & 0x0000FF0000000000) >> 8) |
((x & 0x000F000000000000) << 12) |
((x & 0xFFF0000000000000) >> 4)
}
}
inv_mix_columns :: proc "contextless" (q: ^[8]u64) {
q0 := q[0]
q1 := q[1]
q2 := q[2]
q3 := q[3]
q4 := q[4]
q5 := q[5]
q6 := q[6]
q7 := q[7]
r0 := (q0 >> 16) | (q0 << 48)
r1 := (q1 >> 16) | (q1 << 48)
r2 := (q2 >> 16) | (q2 << 48)
r3 := (q3 >> 16) | (q3 << 48)
r4 := (q4 >> 16) | (q4 << 48)
r5 := (q5 >> 16) | (q5 << 48)
r6 := (q6 >> 16) | (q6 << 48)
r7 := (q7 >> 16) | (q7 << 48)
q[0] = q5 ~ q6 ~ q7 ~ r0 ~ r5 ~ r7 ~ rotr32(q0 ~ q5 ~ q6 ~ r0 ~ r5)
q[1] = q0 ~ q5 ~ r0 ~ r1 ~ r5 ~ r6 ~ r7 ~ rotr32(q1 ~ q5 ~ q7 ~ r1 ~ r5 ~ r6)
q[2] = q0 ~ q1 ~ q6 ~ r1 ~ r2 ~ r6 ~ r7 ~ rotr32(q0 ~ q2 ~ q6 ~ r2 ~ r6 ~ r7)
q[3] = q0 ~ q1 ~ q2 ~ q5 ~ q6 ~ r0 ~ r2 ~ r3 ~ r5 ~ rotr32(q0 ~ q1 ~ q3 ~ q5 ~ q6 ~ q7 ~ r0 ~ r3 ~ r5 ~ r7)
q[4] = q1 ~ q2 ~ q3 ~ q5 ~ r1 ~ r3 ~ r4 ~ r5 ~ r6 ~ r7 ~ rotr32(q1 ~ q2 ~ q4 ~ q5 ~ q7 ~ r1 ~ r4 ~ r5 ~ r6)
q[5] = q2 ~ q3 ~ q4 ~ q6 ~ r2 ~ r4 ~ r5 ~ r6 ~ r7 ~ rotr32(q2 ~ q3 ~ q5 ~ q6 ~ r2 ~ r5 ~ r6 ~ r7)
q[6] = q3 ~ q4 ~ q5 ~ q7 ~ r3 ~ r5 ~ r6 ~ r7 ~ rotr32(q3 ~ q4 ~ q6 ~ q7 ~ r3 ~ r6 ~ r7)
q[7] = q4 ~ q5 ~ q6 ~ r4 ~ r6 ~ r7 ~ rotr32(q4 ~ q5 ~ q7 ~ r4 ~ r7)
}
@(private)
_decrypt :: proc "contextless" (q: ^[8]u64, skey: []u64, num_rounds: int) {
add_round_key(q, skey[num_rounds << 3:])
for u := num_rounds - 1; u > 0; u -= 1 {
inv_shift_rows(q)
inv_sub_bytes(q)
add_round_key(q, skey[u << 3:])
inv_mix_columns(q)
}
inv_shift_rows(q)
inv_sub_bytes(q)
add_round_key(q, skey)
}
+95
View File
@@ -0,0 +1,95 @@
// Copyright (c) 2016 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.
package aes_ct64
import "base:intrinsics"
add_round_key :: proc "contextless" (q: ^[8]u64, sk: []u64) #no_bounds_check {
if len(sk) < 8 {
intrinsics.trap()
}
q[0] ~= sk[0]
q[1] ~= sk[1]
q[2] ~= sk[2]
q[3] ~= sk[3]
q[4] ~= sk[4]
q[5] ~= sk[5]
q[6] ~= sk[6]
q[7] ~= sk[7]
}
shift_rows :: proc "contextless" (q: ^[8]u64) {
for x, i in q {
q[i] =
(x & 0x000000000000FFFF) |
((x & 0x00000000FFF00000) >> 4) |
((x & 0x00000000000F0000) << 12) |
((x & 0x0000FF0000000000) >> 8) |
((x & 0x000000FF00000000) << 8) |
((x & 0xF000000000000000) >> 12) |
((x & 0x0FFF000000000000) << 4)
}
}
mix_columns :: proc "contextless" (q: ^[8]u64) {
q0 := q[0]
q1 := q[1]
q2 := q[2]
q3 := q[3]
q4 := q[4]
q5 := q[5]
q6 := q[6]
q7 := q[7]
r0 := (q0 >> 16) | (q0 << 48)
r1 := (q1 >> 16) | (q1 << 48)
r2 := (q2 >> 16) | (q2 << 48)
r3 := (q3 >> 16) | (q3 << 48)
r4 := (q4 >> 16) | (q4 << 48)
r5 := (q5 >> 16) | (q5 << 48)
r6 := (q6 >> 16) | (q6 << 48)
r7 := (q7 >> 16) | (q7 << 48)
q[0] = q7 ~ r7 ~ r0 ~ rotr32(q0 ~ r0)
q[1] = q0 ~ r0 ~ q7 ~ r7 ~ r1 ~ rotr32(q1 ~ r1)
q[2] = q1 ~ r1 ~ r2 ~ rotr32(q2 ~ r2)
q[3] = q2 ~ r2 ~ q7 ~ r7 ~ r3 ~ rotr32(q3 ~ r3)
q[4] = q3 ~ r3 ~ q7 ~ r7 ~ r4 ~ rotr32(q4 ~ r4)
q[5] = q4 ~ r4 ~ r5 ~ rotr32(q5 ~ r5)
q[6] = q5 ~ r5 ~ r6 ~ rotr32(q6 ~ r6)
q[7] = q6 ~ r6 ~ r7 ~ rotr32(q7 ~ r7)
}
@(private)
_encrypt :: proc "contextless" (q: ^[8]u64, skey: []u64, num_rounds: int) {
add_round_key(q, skey)
for u in 1 ..< num_rounds {
sub_bytes(q)
shift_rows(q)
mix_columns(q)
add_round_key(q, skey[u << 3:])
}
sub_bytes(q)
shift_rows(q)
add_round_key(q, skey[num_rounds << 3:])
}
+179
View File
@@ -0,0 +1,179 @@
// Copyright (c) 2016 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.
package aes_ct64
import "base:intrinsics"
import "core:crypto/_aes"
import "core:encoding/endian"
import "core:mem"
@(private, require_results)
sub_word :: proc "contextless" (x: u32) -> u32 {
q := [8]u64{u64(x), 0, 0, 0, 0, 0, 0, 0}
orthogonalize(&q)
sub_bytes(&q)
orthogonalize(&q)
ret := u32(q[0])
mem.zero_explicit(&q[0], size_of(u64))
return ret
}
@(private, require_results)
keysched :: proc(comp_skey: []u64, key: []byte) -> int {
num_rounds, key_len := 0, len(key)
switch key_len {
case _aes.KEY_SIZE_128:
num_rounds = _aes.ROUNDS_128
case _aes.KEY_SIZE_192:
num_rounds = _aes.ROUNDS_192
case _aes.KEY_SIZE_256:
num_rounds = _aes.ROUNDS_256
case:
panic("crypto/aes: invalid AES key size")
}
skey: [60]u32 = ---
nk, nkf := key_len >> 2, (num_rounds + 1) << 2
for i in 0 ..< nk {
skey[i] = endian.unchecked_get_u32le(key[i << 2:])
}
tmp := skey[(key_len >> 2) - 1]
for i, j, k := nk, 0, 0; i < nkf; i += 1 {
if j == 0 {
tmp = (tmp << 24) | (tmp >> 8)
tmp = sub_word(tmp) ~ u32(_aes.RCON[k])
} else if nk > 6 && j == 4 {
tmp = sub_word(tmp)
}
tmp ~= skey[i - nk]
skey[i] = tmp
if j += 1; j == nk {
j = 0
k += 1
}
}
q: [8]u64 = ---
for i, j := 0, 0; i < nkf; i, j = i + 4, j + 2 {
q[0], q[4] = interleave_in(skey[i:])
q[1] = q[0]
q[2] = q[0]
q[3] = q[0]
q[5] = q[4]
q[6] = q[4]
q[7] = q[4]
orthogonalize(&q)
comp_skey[j + 0] =
(q[0] & 0x1111111111111111) |
(q[1] & 0x2222222222222222) |
(q[2] & 0x4444444444444444) |
(q[3] & 0x8888888888888888)
comp_skey[j + 1] =
(q[4] & 0x1111111111111111) |
(q[5] & 0x2222222222222222) |
(q[6] & 0x4444444444444444) |
(q[7] & 0x8888888888888888)
}
mem.zero_explicit(&skey, size_of(skey))
mem.zero_explicit(&q, size_of(q))
return num_rounds
}
@(private)
skey_expand :: proc "contextless" (skey, comp_skey: []u64, num_rounds: int) {
n := (num_rounds + 1) << 1
for u, v := 0, 0; u < n; u, v = u + 1, v + 4 {
x0 := comp_skey[u]
x1, x2, x3 := x0, x0, x0
x0 &= 0x1111111111111111
x1 &= 0x2222222222222222
x2 &= 0x4444444444444444
x3 &= 0x8888888888888888
x1 >>= 1
x2 >>= 2
x3 >>= 3
skey[v + 0] = (x0 << 4) - x0
skey[v + 1] = (x1 << 4) - x1
skey[v + 2] = (x2 << 4) - x2
skey[v + 3] = (x3 << 4) - x3
}
}
orthogonalize_roundkey :: proc "contextless" (qq: []u64, key: []byte) {
if len(qq) < 8 || len(key) != 16 {
intrinsics.trap()
}
skey: [4]u32 = ---
skey[0] = endian.unchecked_get_u32le(key[0:])
skey[1] = endian.unchecked_get_u32le(key[4:])
skey[2] = endian.unchecked_get_u32le(key[8:])
skey[3] = endian.unchecked_get_u32le(key[12:])
q: [8]u64 = ---
q[0], q[4] = interleave_in(skey[:])
q[1] = q[0]
q[2] = q[0]
q[3] = q[0]
q[5] = q[4]
q[6] = q[4]
q[7] = q[4]
orthogonalize(&q)
comp_skey: [2]u64 = ---
comp_skey[0] =
(q[0] & 0x1111111111111111) |
(q[1] & 0x2222222222222222) |
(q[2] & 0x4444444444444444) |
(q[3] & 0x8888888888888888)
comp_skey[1] =
(q[4] & 0x1111111111111111) |
(q[5] & 0x2222222222222222) |
(q[6] & 0x4444444444444444) |
(q[7] & 0x8888888888888888)
for x, u in comp_skey {
x0 := x
x1, x2, x3 := x0, x0, x0
x0 &= 0x1111111111111111
x1 &= 0x2222222222222222
x2 &= 0x4444444444444444
x3 &= 0x8888888888888888
x1 >>= 1
x2 >>= 2
x3 >>= 3
qq[u * 4 + 0] = (x0 << 4) - x0
qq[u * 4 + 1] = (x1 << 4) - x1
qq[u * 4 + 2] = (x2 << 4) - x2
qq[u * 4 + 3] = (x3 << 4) - x3
}
mem.zero_explicit(&skey, size_of(skey))
mem.zero_explicit(&q, size_of(q))
mem.zero_explicit(&comp_skey, size_of(comp_skey))
}
+136
View File
@@ -0,0 +1,136 @@
// Copyright (c) 2016 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.
package aes_ct64
import "base:intrinsics"
import "core:crypto/_aes"
import "core:encoding/endian"
@(private = "file")
bmul64 :: proc "contextless" (x, y: u64) -> u64 {
x0 := x & 0x1111111111111111
x1 := x & 0x2222222222222222
x2 := x & 0x4444444444444444
x3 := x & 0x8888888888888888
y0 := y & 0x1111111111111111
y1 := y & 0x2222222222222222
y2 := y & 0x4444444444444444
y3 := y & 0x8888888888888888
z0 := (x0 * y0) ~ (x1 * y3) ~ (x2 * y2) ~ (x3 * y1)
z1 := (x0 * y1) ~ (x1 * y0) ~ (x2 * y3) ~ (x3 * y2)
z2 := (x0 * y2) ~ (x1 * y1) ~ (x2 * y0) ~ (x3 * y3)
z3 := (x0 * y3) ~ (x1 * y2) ~ (x2 * y1) ~ (x3 * y0)
z0 &= 0x1111111111111111
z1 &= 0x2222222222222222
z2 &= 0x4444444444444444
z3 &= 0x8888888888888888
return z0 | z1 | z2 | z3
}
@(private = "file")
rev64 :: proc "contextless" (x: u64) -> u64 {
x := x
x = ((x & 0x5555555555555555) << 1) | ((x >> 1) & 0x5555555555555555)
x = ((x & 0x3333333333333333) << 2) | ((x >> 2) & 0x3333333333333333)
x = ((x & 0x0F0F0F0F0F0F0F0F) << 4) | ((x >> 4) & 0x0F0F0F0F0F0F0F0F)
x = ((x & 0x00FF00FF00FF00FF) << 8) | ((x >> 8) & 0x00FF00FF00FF00FF)
x = ((x & 0x0000FFFF0000FFFF) << 16) | ((x >> 16) & 0x0000FFFF0000FFFF)
return (x << 32) | (x >> 32)
}
// 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.
ghash :: proc "contextless" (dst, key, data: []byte) {
if len(dst) != _aes.GHASH_BLOCK_SIZE || len(key) != _aes.GHASH_BLOCK_SIZE {
intrinsics.trap()
}
buf := data
l := len(buf)
y1 := endian.unchecked_get_u64be(dst[0:])
y0 := endian.unchecked_get_u64be(dst[8:])
h1 := endian.unchecked_get_u64be(key[0:])
h0 := endian.unchecked_get_u64be(key[8:])
h0r := rev64(h0)
h1r := rev64(h1)
h2 := h0 ~ h1
h2r := h0r ~ h1r
src: []byte
for l > 0 {
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
}
y1 ~= endian.unchecked_get_u64be(src)
y0 ~= endian.unchecked_get_u64be(src[8:])
y0r := rev64(y0)
y1r := rev64(y1)
y2 := y0 ~ y1
y2r := y0r ~ y1r
z0 := bmul64(y0, h0)
z1 := bmul64(y1, h1)
z2 := bmul64(y2, h2)
z0h := bmul64(y0r, h0r)
z1h := bmul64(y1r, h1r)
z2h := bmul64(y2r, h2r)
z2 ~= z0 ~ z1
z2h ~= z0h ~ z1h
z0h = rev64(z0h) >> 1
z1h = rev64(z1h) >> 1
z2h = rev64(z2h) >> 1
v0 := z0
v1 := z0h ~ z2
v2 := z1 ~ z2h
v3 := z1h
v3 = (v3 << 1) | (v2 >> 63)
v2 = (v2 << 1) | (v1 >> 63)
v1 = (v1 << 1) | (v0 >> 63)
v0 = (v0 << 1)
v2 ~= v0 ~ (v0 >> 1) ~ (v0 >> 2) ~ (v0 >> 7)
v1 ~= (v0 << 63) ~ (v0 << 62) ~ (v0 << 57)
v3 ~= v1 ~ (v1 >> 1) ~ (v1 >> 2) ~ (v1 >> 7)
v2 ~= (v1 << 63) ~ (v1 << 62) ~ (v1 << 57)
y0 = v2
y1 = v3
}
endian.unchecked_put_u64be(dst[0:], y1)
endian.unchecked_put_u64be(dst[8:], y0)
}
+75
View File
@@ -0,0 +1,75 @@
package aes_ct64
import "base:intrinsics"
import "core:crypto/_aes"
import "core:encoding/endian"
load_blockx1 :: proc "contextless" (q: ^[8]u64, src: []byte) {
if len(src) != _aes.BLOCK_SIZE {
intrinsics.trap()
}
w: [4]u32 = ---
w[0] = endian.unchecked_get_u32le(src[0:])
w[1] = endian.unchecked_get_u32le(src[4:])
w[2] = endian.unchecked_get_u32le(src[8:])
w[3] = endian.unchecked_get_u32le(src[12:])
q[0], q[4] = interleave_in(w[:])
orthogonalize(q)
}
store_blockx1 :: proc "contextless" (dst: []byte, q: ^[8]u64) {
if len(dst) != _aes.BLOCK_SIZE {
intrinsics.trap()
}
orthogonalize(q)
w0, w1, w2, w3 := interleave_out(q[0], q[4])
endian.unchecked_put_u32le(dst[0:], w0)
endian.unchecked_put_u32le(dst[4:], w1)
endian.unchecked_put_u32le(dst[8:], w2)
endian.unchecked_put_u32le(dst[12:], w3)
}
load_blocks :: proc "contextless" (q: ^[8]u64, src: [][]byte) {
if n := len(src); n > STRIDE || n == 0 {
intrinsics.trap()
}
w: [4]u32 = ---
for s, i in src {
if len(s) != _aes.BLOCK_SIZE {
intrinsics.trap()
}
w[0] = endian.unchecked_get_u32le(s[0:])
w[1] = endian.unchecked_get_u32le(s[4:])
w[2] = endian.unchecked_get_u32le(s[8:])
w[3] = endian.unchecked_get_u32le(s[12:])
q[i], q[i + 4] = interleave_in(w[:])
}
orthogonalize(q)
}
store_blocks :: proc "contextless" (dst: [][]byte, q: ^[8]u64) {
if n := len(dst); n > STRIDE || n == 0 {
intrinsics.trap()
}
orthogonalize(q)
for d, i in dst {
// Allow storing [0,4] blocks.
if d == nil {
break
}
if len(d) != _aes.BLOCK_SIZE {
intrinsics.trap()
}
w0, w1, w2, w3 := interleave_out(q[i], q[i + 4])
endian.unchecked_put_u32le(d[0:], w0)
endian.unchecked_put_u32le(d[4:], w1)
endian.unchecked_put_u32le(d[8:], w2)
endian.unchecked_put_u32le(d[12:], w3)
}
}
+58 -39
View File
@@ -11,6 +11,7 @@ package _blake2
*/
import "core:encoding/endian"
import "core:mem"
BLAKE2S_BLOCK_SIZE :: 64
BLAKE2S_SIZE :: 32
@@ -28,7 +29,6 @@ Blake2s_Context :: struct {
is_keyed: bool,
size: byte,
is_last_node: bool,
cfg: Blake2_Config,
is_initialized: bool,
}
@@ -44,7 +44,6 @@ Blake2b_Context :: struct {
is_keyed: bool,
size: byte,
is_last_node: bool,
cfg: Blake2_Config,
is_initialized: bool,
}
@@ -83,62 +82,61 @@ BLAKE2B_IV := [8]u64 {
0x1f83d9abfb41bd6b, 0x5be0cd19137e2179,
}
init :: proc(ctx: ^$T) {
init :: proc(ctx: ^$T, cfg: ^Blake2_Config) {
when T == Blake2s_Context {
block_size :: BLAKE2S_BLOCK_SIZE
max_size :: BLAKE2S_SIZE
} else when T == Blake2b_Context {
block_size :: BLAKE2B_BLOCK_SIZE
max_size :: BLAKE2B_SIZE
}
if ctx.cfg.size > max_size {
if cfg.size > max_size {
panic("blake2: requested output size exceeeds algorithm max")
}
p := make([]byte, block_size)
defer delete(p)
// To save having to allocate a scratch buffer, use the internal
// data buffer (`ctx.x`), as it is exactly the correct size.
p := ctx.x[:]
p[0] = ctx.cfg.size
p[1] = byte(len(ctx.cfg.key))
p[0] = cfg.size
p[1] = byte(len(cfg.key))
if ctx.cfg.salt != nil {
if cfg.salt != nil {
when T == Blake2s_Context {
copy(p[16:], ctx.cfg.salt)
copy(p[16:], cfg.salt)
} else when T == Blake2b_Context {
copy(p[32:], ctx.cfg.salt)
copy(p[32:], cfg.salt)
}
}
if ctx.cfg.person != nil {
if cfg.person != nil {
when T == Blake2s_Context {
copy(p[24:], ctx.cfg.person)
copy(p[24:], cfg.person)
} else when T == Blake2b_Context {
copy(p[48:], ctx.cfg.person)
copy(p[48:], cfg.person)
}
}
if ctx.cfg.tree != nil {
p[2] = ctx.cfg.tree.(Blake2_Tree).fanout
p[3] = ctx.cfg.tree.(Blake2_Tree).max_depth
endian.unchecked_put_u32le(p[4:], ctx.cfg.tree.(Blake2_Tree).leaf_size)
if cfg.tree != nil {
p[2] = cfg.tree.(Blake2_Tree).fanout
p[3] = cfg.tree.(Blake2_Tree).max_depth
endian.unchecked_put_u32le(p[4:], cfg.tree.(Blake2_Tree).leaf_size)
when T == Blake2s_Context {
p[8] = byte(ctx.cfg.tree.(Blake2_Tree).node_offset)
p[9] = byte(ctx.cfg.tree.(Blake2_Tree).node_offset >> 8)
p[10] = byte(ctx.cfg.tree.(Blake2_Tree).node_offset >> 16)
p[11] = byte(ctx.cfg.tree.(Blake2_Tree).node_offset >> 24)
p[12] = byte(ctx.cfg.tree.(Blake2_Tree).node_offset >> 32)
p[13] = byte(ctx.cfg.tree.(Blake2_Tree).node_offset >> 40)
p[14] = ctx.cfg.tree.(Blake2_Tree).node_depth
p[15] = ctx.cfg.tree.(Blake2_Tree).inner_hash_size
p[8] = byte(cfg.tree.(Blake2_Tree).node_offset)
p[9] = byte(cfg.tree.(Blake2_Tree).node_offset >> 8)
p[10] = byte(cfg.tree.(Blake2_Tree).node_offset >> 16)
p[11] = byte(cfg.tree.(Blake2_Tree).node_offset >> 24)
p[12] = byte(cfg.tree.(Blake2_Tree).node_offset >> 32)
p[13] = byte(cfg.tree.(Blake2_Tree).node_offset >> 40)
p[14] = cfg.tree.(Blake2_Tree).node_depth
p[15] = cfg.tree.(Blake2_Tree).inner_hash_size
} else when T == Blake2b_Context {
endian.unchecked_put_u64le(p[8:], ctx.cfg.tree.(Blake2_Tree).node_offset)
p[16] = ctx.cfg.tree.(Blake2_Tree).node_depth
p[17] = ctx.cfg.tree.(Blake2_Tree).inner_hash_size
endian.unchecked_put_u64le(p[8:], cfg.tree.(Blake2_Tree).node_offset)
p[16] = cfg.tree.(Blake2_Tree).node_depth
p[17] = cfg.tree.(Blake2_Tree).inner_hash_size
}
} else {
p[2], p[3] = 1, 1
}
ctx.size = ctx.cfg.size
ctx.size = cfg.size
for i := 0; i < 8; i += 1 {
when T == Blake2s_Context {
ctx.h[i] = BLAKE2S_IV[i] ~ endian.unchecked_get_u32le(p[i * 4:])
@@ -147,11 +145,14 @@ init :: proc(ctx: ^$T) {
ctx.h[i] = BLAKE2B_IV[i] ~ endian.unchecked_get_u64le(p[i * 8:])
}
}
if ctx.cfg.tree != nil && ctx.cfg.tree.(Blake2_Tree).is_last_node {
mem.zero(&ctx.x, size_of(ctx.x)) // Done with the scratch space, no barrier.
if cfg.tree != nil && cfg.tree.(Blake2_Tree).is_last_node {
ctx.is_last_node = true
}
if len(ctx.cfg.key) > 0 {
copy(ctx.padded_key[:], ctx.cfg.key)
if len(cfg.key) > 0 {
copy(ctx.padded_key[:], cfg.key)
update(ctx, ctx.padded_key[:])
ctx.is_keyed = true
}
@@ -194,22 +195,40 @@ update :: proc(ctx: ^$T, p: []byte) {
ctx.nx += copy(ctx.x[ctx.nx:], p)
}
final :: proc(ctx: ^$T, hash: []byte) {
final :: proc(ctx: ^$T, hash: []byte, finalize_clone: bool = false) {
assert(ctx.is_initialized)
ctx := ctx
if finalize_clone {
tmp_ctx: T
clone(&tmp_ctx, ctx)
ctx = &tmp_ctx
}
defer(reset(ctx))
when T == Blake2s_Context {
if len(hash) < int(ctx.cfg.size) {
if len(hash) < int(ctx.size) {
panic("crypto/blake2s: invalid destination digest size")
}
blake2s_final(ctx, hash)
} else when T == Blake2b_Context {
if len(hash) < int(ctx.cfg.size) {
if len(hash) < int(ctx.size) {
panic("crypto/blake2b: invalid destination digest size")
}
blake2b_final(ctx, hash)
}
}
ctx.is_initialized = false
clone :: proc(ctx, other: ^$T) {
ctx^ = other^
}
reset :: proc(ctx: ^$T) {
if !ctx.is_initialized {
return
}
mem.zero_explicit(ctx, size_of(ctx^))
}
@(private)
+428
View File
@@ -0,0 +1,428 @@
package _edwards25519
/*
This implements the edwards25519 composite-order group, primarily for
the purpose of implementing X25519, Ed25519, and ristretto255. Use of
this package for other purposes is NOT RECOMMENDED.
See:
- https://eprint.iacr.org/2011/368.pdf
- https://datatracker.ietf.org/doc/html/rfc8032
- https://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html
*/
import "base:intrinsics"
import "core:crypto"
import field "core:crypto/_fiat/field_curve25519"
import "core:mem"
// Group_Element is an edwards25519 group element, as extended homogenous
// coordinates, which represents the affine point `(x, y)` as `(X, Y, Z, T)`,
// with the relations `x = X/Z`, `y = Y/Z`, and `x * y = T/Z`.
//
// d = -121665/121666 = 37095705934669439343138083508754565189542113879843219016388785533085940283555
// a = -1
//
// Notes:
// - There is considerable scope for optimization, however that
// will not change the external API, and this is simple and reasonably
// performant.
// - The API delibarately makes it hard to create arbitrary group
// elements that are not on the curve.
// - The group element decoding routine takes the opinionated stance of
// rejecting non-canonical encodings.
FE_D := field.Tight_Field_Element {
929955233495203,
466365720129213,
1662059464998953,
2033849074728123,
1442794654840575,
}
@(private)
FE_A := field.Tight_Field_Element {
2251799813685228,
2251799813685247,
2251799813685247,
2251799813685247,
2251799813685247,
}
@(private)
FE_D2 := field.Tight_Field_Element {
1859910466990425,
932731440258426,
1072319116312658,
1815898335770999,
633789495995903,
}
@(private)
GE_BASEPOINT := Group_Element {
field.Tight_Field_Element {
1738742601995546,
1146398526822698,
2070867633025821,
562264141797630,
587772402128613,
},
field.Tight_Field_Element {
1801439850948184,
1351079888211148,
450359962737049,
900719925474099,
1801439850948198,
},
field.Tight_Field_Element{1, 0, 0, 0, 0},
field.Tight_Field_Element {
1841354044333475,
16398895984059,
755974180946558,
900171276175154,
1821297809914039,
},
}
GE_IDENTITY := Group_Element {
field.Tight_Field_Element{0, 0, 0, 0, 0},
field.Tight_Field_Element{1, 0, 0, 0, 0},
field.Tight_Field_Element{1, 0, 0, 0, 0},
field.Tight_Field_Element{0, 0, 0, 0, 0},
}
Group_Element :: struct {
x: field.Tight_Field_Element,
y: field.Tight_Field_Element,
z: field.Tight_Field_Element,
t: field.Tight_Field_Element,
}
ge_clear :: proc "contextless" (ge: ^Group_Element) {
mem.zero_explicit(ge, size_of(Group_Element))
}
ge_set :: proc "contextless" (ge, a: ^Group_Element) {
field.fe_set(&ge.x, &a.x)
field.fe_set(&ge.y, &a.y)
field.fe_set(&ge.z, &a.z)
field.fe_set(&ge.t, &a.t)
}
@(require_results)
ge_set_bytes :: proc "contextless" (ge: ^Group_Element, b: []byte) -> bool {
if len(b) != 32 {
intrinsics.trap()
}
b_ := (^[32]byte)(raw_data(b))
// Do the work in a scratch element, so that ge is unchanged on
// failure.
tmp: Group_Element = ---
defer ge_clear(&tmp)
field.fe_one(&tmp.z) // Z = 1
// The encoding is the y-coordinate, with the x-coordinate polarity
// (odd/even) encoded in the MSB.
field.fe_from_bytes(&tmp.y, b_) // ignores high bit
// Recover the candidate x-coordinate via the curve equation:
// x^2 = (y^2 - 1) / (d * y^2 + 1) (mod p)
fe_tmp := &tmp.t // Use this to store intermediaries.
fe_one := &tmp.z
// x = num = y^2 - 1
field.fe_carry_square(fe_tmp, field.fe_relax_cast(&tmp.y)) // fe_tmp = y^2
field.fe_carry_sub(&tmp.x, fe_tmp, fe_one)
// den = d * y^2 + 1
field.fe_carry_mul(fe_tmp, field.fe_relax_cast(fe_tmp), field.fe_relax_cast(&FE_D))
field.fe_carry_add(fe_tmp, fe_tmp, fe_one)
// x = invsqrt(den/num)
is_square := field.fe_carry_sqrt_ratio_m1(
&tmp.x,
field.fe_relax_cast(&tmp.x),
field.fe_relax_cast(fe_tmp),
)
if is_square == 0 {
return false
}
// Pick the right x-coordinate.
field.fe_cond_negate(&tmp.x, &tmp.x, int(b[31] >> 7))
// t = x * y
field.fe_carry_mul(&tmp.t, field.fe_relax_cast(&tmp.x), field.fe_relax_cast(&tmp.y))
// Reject non-canonical encodings of ge.
buf: [32]byte = ---
field.fe_to_bytes(&buf, &tmp.y)
buf[31] |= byte(field.fe_is_negative(&tmp.x)) << 7
is_canonical := crypto.compare_constant_time(b, buf[:])
ge_cond_assign(ge, &tmp, is_canonical)
mem.zero_explicit(&buf, size_of(buf))
return is_canonical == 1
}
ge_bytes :: proc "contextless" (ge: ^Group_Element, dst: []byte) {
if len(dst) != 32 {
intrinsics.trap()
}
dst_ := (^[32]byte)(raw_data(dst))
// Convert the element to affine (x, y) representation.
x, y, z_inv: field.Tight_Field_Element = ---, ---, ---
field.fe_carry_inv(&z_inv, field.fe_relax_cast(&ge.z))
field.fe_carry_mul(&x, field.fe_relax_cast(&ge.x), field.fe_relax_cast(&z_inv))
field.fe_carry_mul(&y, field.fe_relax_cast(&ge.y), field.fe_relax_cast(&z_inv))
// Encode the y-coordinate.
field.fe_to_bytes(dst_, &y)
// Copy the least significant bit of the x-coordinate to the most
// significant bit of the encoded y-coordinate.
dst_[31] |= byte((x[0] & 1) << 7)
field.fe_clear_vec([]^field.Tight_Field_Element{&x, &y, &z_inv})
}
ge_identity :: proc "contextless" (ge: ^Group_Element) {
field.fe_zero(&ge.x)
field.fe_one(&ge.y)
field.fe_one(&ge.z)
field.fe_zero(&ge.t)
}
ge_generator :: proc "contextless" (ge: ^Group_Element) {
ge_set(ge, &GE_BASEPOINT)
}
@(private)
Addend_Group_Element :: struct {
y2_minus_x2: field.Loose_Field_Element, // t1
y2_plus_x2: field.Loose_Field_Element, // t3
k_times_t2: field.Tight_Field_Element, // t4
two_times_z2: field.Loose_Field_Element, // t5
}
@(private)
ge_addend_set :: proc "contextless" (ge_a: ^Addend_Group_Element, ge: ^Group_Element) {
field.fe_sub(&ge_a.y2_minus_x2, &ge.y, &ge.x)
field.fe_add(&ge_a.y2_plus_x2, &ge.y, &ge.x)
field.fe_carry_mul(&ge_a.k_times_t2, field.fe_relax_cast(&FE_D2), field.fe_relax_cast(&ge.t))
field.fe_add(&ge_a.two_times_z2, &ge.z, &ge.z)
}
@(private)
ge_addend_conditional_assign :: proc "contextless" (ge_a, a: ^Addend_Group_Element, ctrl: int) {
field.fe_cond_select(&ge_a.y2_minus_x2, &ge_a.y2_minus_x2, &a.y2_minus_x2, ctrl)
field.fe_cond_select(&ge_a.y2_plus_x2, &ge_a.y2_plus_x2, &a.y2_plus_x2, ctrl)
field.fe_cond_select(&ge_a.k_times_t2, &ge_a.k_times_t2, &a.k_times_t2, ctrl)
field.fe_cond_select(&ge_a.two_times_z2, &ge_a.two_times_z2, &a.two_times_z2, ctrl)
}
@(private)
Add_Scratch :: struct {
A, B, C, D: field.Tight_Field_Element,
E, F, G, H: field.Loose_Field_Element,
t0, t2: field.Loose_Field_Element,
}
ge_add :: proc "contextless" (ge, a, b: ^Group_Element) {
b_: Addend_Group_Element = ---
ge_addend_set(&b_, b)
scratch: Add_Scratch = ---
ge_add_addend(ge, a, &b_, &scratch)
mem.zero_explicit(&b_, size_of(Addend_Group_Element))
mem.zero_explicit(&scratch, size_of(Add_Scratch))
}
@(private)
ge_add_addend :: proc "contextless" (
ge, a: ^Group_Element,
b: ^Addend_Group_Element,
scratch: ^Add_Scratch,
) {
// https://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#addition-add-2008-hwcd-3
// Assumptions: k=2*d.
//
// t0 = Y1-X1
// t1 = Y2-X2
// A = t0*t1
// t2 = Y1+X1
// t3 = Y2+X2
// B = t2*t3
// t4 = k*T2
// C = T1*t4
// t5 = 2*Z2
// D = Z1*t5
// E = B-A
// F = D-C
// G = D+C
// H = B+A
// X3 = E*F
// Y3 = G*H
// T3 = E*H
// Z3 = F*G
//
// In order to make the scalar multiply faster, the addend is provided
// as a `Addend_Group_Element` with t1, t3, t4, and t5 precomputed, as
// it is trivially obvious that those are the only values used by the
// formula that are directly dependent on `b`, and are only dependent
// on `b` and constants. This saves 1 sub, 2 adds, and 1 multiply,
// each time the intermediate representation can be reused.
A, B, C, D := &scratch.A, &scratch.B, &scratch.C, &scratch.D
E, F, G, H := &scratch.E, &scratch.F, &scratch.G, &scratch.H
t0, t2 := &scratch.t0, &scratch.t2
field.fe_sub(t0, &a.y, &a.x)
t1 := &b.y2_minus_x2
field.fe_carry_mul(A, t0, t1)
field.fe_add(t2, &a.y, &a.x)
t3 := &b.y2_plus_x2
field.fe_carry_mul(B, t2, t3)
t4 := &b.k_times_t2
field.fe_carry_mul(C, field.fe_relax_cast(&a.t), field.fe_relax_cast(t4))
t5 := &b.two_times_z2
field.fe_carry_mul(D, field.fe_relax_cast(&a.z), t5)
field.fe_sub(E, B, A)
field.fe_sub(F, D, C)
field.fe_add(G, D, C)
field.fe_add(H, B, A)
field.fe_carry_mul(&ge.x, E, F)
field.fe_carry_mul(&ge.y, G, H)
field.fe_carry_mul(&ge.t, E, H)
field.fe_carry_mul(&ge.z, F, G)
}
@(private)
Double_Scratch :: struct {
A, B, C, D, G: field.Tight_Field_Element,
t0, t2, t3: field.Tight_Field_Element,
E, F, H: field.Loose_Field_Element,
t1: field.Loose_Field_Element,
}
ge_double :: proc "contextless" (ge, a: ^Group_Element, scratch: ^Double_Scratch = nil) {
// https://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-dbl-2008-hwcd
//
// A = X1^2
// B = Y1^2
// t0 = Z1^2
// C = 2*t0
// D = a*A
// t1 = X1+Y1
// t2 = t1^2
// t3 = t2-A
// E = t3-B
// G = D+B
// F = G-C
// H = D-B
// X3 = E*F
// Y3 = G*H
// T3 = E*H
// Z3 = F*G
sanitize, scratch := scratch == nil, scratch
if sanitize {
tmp: Double_Scratch = ---
scratch = &tmp
}
A, B, C, D, G := &scratch.A, &scratch.B, &scratch.C, &scratch.D, &scratch.G
t0, t2, t3 := &scratch.t0, &scratch.t2, &scratch.t3
E, F, H := &scratch.E, &scratch.F, &scratch.H
t1 := &scratch.t1
field.fe_carry_square(A, field.fe_relax_cast(&a.x))
field.fe_carry_square(B, field.fe_relax_cast(&a.y))
field.fe_carry_square(t0, field.fe_relax_cast(&a.z))
field.fe_carry_add(C, t0, t0)
field.fe_carry_mul(D, field.fe_relax_cast(&FE_A), field.fe_relax_cast(A))
field.fe_add(t1, &a.x, &a.y)
field.fe_carry_square(t2, t1)
field.fe_carry_sub(t3, t2, A)
field.fe_sub(E, t3, B)
field.fe_carry_add(G, D, B)
field.fe_sub(F, G, C)
field.fe_sub(H, D, B)
G_ := field.fe_relax_cast(G)
field.fe_carry_mul(&ge.x, E, F)
field.fe_carry_mul(&ge.y, G_, H)
field.fe_carry_mul(&ge.t, E, H)
field.fe_carry_mul(&ge.z, F, G_)
if sanitize {
mem.zero_explicit(scratch, size_of(Double_Scratch))
}
}
ge_negate :: proc "contextless" (ge, a: ^Group_Element) {
field.fe_carry_opp(&ge.x, &a.x)
field.fe_set(&ge.y, &a.y)
field.fe_set(&ge.z, &a.z)
field.fe_carry_opp(&ge.t, &a.t)
}
ge_cond_negate :: proc "contextless" (ge, a: ^Group_Element, ctrl: int) {
tmp: Group_Element = ---
ge_negate(&tmp, a)
ge_cond_assign(ge, &tmp, ctrl)
ge_clear(&tmp)
}
ge_cond_assign :: proc "contextless" (ge, a: ^Group_Element, ctrl: int) {
field.fe_cond_assign(&ge.x, &a.x, ctrl)
field.fe_cond_assign(&ge.y, &a.y, ctrl)
field.fe_cond_assign(&ge.z, &a.z, ctrl)
field.fe_cond_assign(&ge.t, &a.t, ctrl)
}
ge_cond_select :: proc "contextless" (ge, a, b: ^Group_Element, ctrl: int) {
field.fe_cond_select(&ge.x, &a.x, &b.x, ctrl)
field.fe_cond_select(&ge.y, &a.y, &b.y, ctrl)
field.fe_cond_select(&ge.z, &a.z, &b.z, ctrl)
field.fe_cond_select(&ge.t, &a.t, &b.t, ctrl)
}
@(require_results)
ge_equal :: proc "contextless" (a, b: ^Group_Element) -> int {
// (x, y) ?= (x', y') -> (X/Z, Y/Z) ?= (X'/Z', Y'/Z')
// X/Z ?= X'/Z', Y/Z ?= Y'/Z' -> X*Z' ?= X'*Z, Y*Z' ?= Y'*Z
ax_bz, bx_az, ay_bz, by_az: field.Tight_Field_Element = ---, ---, ---, ---
field.fe_carry_mul(&ax_bz, field.fe_relax_cast(&a.x), field.fe_relax_cast(&b.z))
field.fe_carry_mul(&bx_az, field.fe_relax_cast(&b.x), field.fe_relax_cast(&a.z))
field.fe_carry_mul(&ay_bz, field.fe_relax_cast(&a.y), field.fe_relax_cast(&b.z))
field.fe_carry_mul(&by_az, field.fe_relax_cast(&b.y), field.fe_relax_cast(&a.z))
ret := field.fe_equal(&ax_bz, &bx_az) & field.fe_equal(&ay_bz, &by_az)
field.fe_clear_vec([]^field.Tight_Field_Element{&ax_bz, &ay_bz, &bx_az, &by_az})
return ret
}
@(require_results)
ge_is_small_order :: proc "contextless" (ge: ^Group_Element) -> bool {
tmp: Group_Element = ---
ge_double(&tmp, ge)
ge_double(&tmp, &tmp)
ge_double(&tmp, &tmp)
return ge_equal(&tmp, &GE_IDENTITY) == 1
}
@(require_results)
ge_in_prime_order_subgroup_vartime :: proc "contextless" (ge: ^Group_Element) -> bool {
// This is currently *very* expensive. The faster method would be
// something like (https://eprint.iacr.org/2022/1164.pdf), however
// that is a ~50% speedup, and a lot of added complexity for something
// that is better solved by "just use ristretto255".
tmp: Group_Element = ---
_ge_scalarmult(&tmp, ge, &SC_ELL, true)
return ge_equal(&tmp, &GE_IDENTITY) == 1
}
@@ -0,0 +1,61 @@
package _edwards25519
import "base:intrinsics"
import field "core:crypto/_fiat/field_scalar25519"
import "core:mem"
Scalar :: field.Montgomery_Domain_Field_Element
// WARNING: This is non-canonical and only to be used when checking if
// a group element is on the prime-order subgroup.
@(private)
SC_ELL := field.Non_Montgomery_Domain_Field_Element {
field.ELL[0],
field.ELL[1],
field.ELL[2],
field.ELL[3],
}
sc_set_u64 :: proc "contextless" (sc: ^Scalar, i: u64) {
tmp := field.Non_Montgomery_Domain_Field_Element{i, 0, 0, 0}
field.fe_to_montgomery(sc, &tmp)
mem.zero_explicit(&tmp, size_of(tmp))
}
@(require_results)
sc_set_bytes :: proc "contextless" (sc: ^Scalar, b: []byte) -> bool {
if len(b) != 32 {
intrinsics.trap()
}
b_ := (^[32]byte)(raw_data(b))
return field.fe_from_bytes(sc, b_)
}
sc_set_bytes_rfc8032 :: proc "contextless" (sc: ^Scalar, b: []byte) {
if len(b) != 32 {
intrinsics.trap()
}
b_ := (^[32]byte)(raw_data(b))
field.fe_from_bytes_rfc8032(sc, b_)
}
sc_clear :: proc "contextless" (sc: ^Scalar) {
mem.zero_explicit(sc, size_of(Scalar))
}
sc_set :: field.fe_set
sc_set_bytes_wide :: field.fe_from_bytes_wide
sc_bytes :: field.fe_to_bytes
sc_zero :: field.fe_zero
sc_one :: field.fe_one
sc_add :: field.fe_add
sc_sub :: field.fe_sub
sc_negate :: field.fe_opp
sc_mul :: field.fe_mul
sc_square :: field.fe_square
sc_cond_assign :: field.fe_cond_assign
sc_equal :: field.fe_equal
@@ -0,0 +1,288 @@
package _edwards25519
import field "core:crypto/_fiat/field_scalar25519"
import "core:math/bits"
import "core:mem"
// GE_BASEPOINT_TABLE is 1 * G, ... 15 * G, in precomputed format.
//
// Note: When generating, the values were reduced to Tight_Field_Element
// ranges, even though that is not required.
@(private)
GE_BASEPOINT_TABLE := Multiply_Table {
{
{62697248952638, 204681361388450, 631292143396476, 338455783676468, 1213667448819585},
{1288382639258501, 245678601348599, 269427782077623, 1462984067271730, 137412439391563},
{301289933810280, 1259582250014073, 1422107436869536, 796239922652654, 1953934009299142},
{2, 0, 0, 0, 0},
},
{
{1519297034332653, 1098796920435767, 1823476547744119, 808144629470969, 2110930855619772},
{338005982828284, 1667856962156925, 100399270107451, 1604566703601691, 1950338038771369},
{1920505767731247, 1443759578976892, 1659852098357048, 1484431291070208, 275018744912646},
{763163817085987, 2195095074806923, 2167883174351839, 1868059999999762, 911071066608705},
},
{
{960627541894068, 1314966688943942, 1126875971034044, 2059608312958945, 605975666152586},
{1714478358025626, 2209607666607510, 1600912834284834, 496072478982142, 481970031861896},
{851735079403194, 1088965826757164, 141569479297499, 602804610059257, 2004026468601520},
{197585529552380, 324719066578543, 564481854250498, 1173818332764578, 35452976395676},
},
{
{1152980410747203, 2196804280851952, 25745194962557, 1915167295473129, 1266299690309224},
{809905889679060, 979732230071345, 1509972345538142, 188492426534402, 818965583123815},
{997685409185036, 1451818320876327, 2126681166774509, 2000509606057528, 235432372486854},
{887734189279642, 1460338685162044, 877378220074262, 102436391401299, 153369156847490},
},
{
{2056621900836770, 1821657694132497, 1627986892909426, 1163363868678833, 1108873376459226},
{1187697490593623, 1066539945237335, 885654531892000, 1357534489491782, 359370291392448},
{1509033452137525, 1305318174298508, 613642471748944, 1987256352550234, 1044283663101541},
{220105720697037, 387661783287620, 328296827867762, 360035589590664, 795213236824054},
},
{
{1820794733038396, 1612235121681074, 757405923441402, 1094031020892801, 231025333128907},
{1639067873254194, 1484176557946322, 300800382144789, 1329915446659183, 1211704578730455},
{641900794791527, 1711751746971612, 179044712319955, 576455585963824, 1852617592509865},
{743549047192397, 685091042550147, 1952415336873496, 1965124675654685, 513364998442917},
},
{
{1004557076870448, 1762911374844520, 1330807633622723, 384072910939787, 953849032243810},
{2178275058221458, 257933183722891, 376684351537894, 2010189102001786, 1981824297484148},
{1332915663881114, 1286540505502549, 1741691283561518, 977214932156314, 1764059494778091},
{429702949064027, 1368332611650677, 2019867176450999, 2212258376161746, 526160996742554},
},
{
{2098932988258576, 2203688382075948, 2120400160059479, 1748488020948146, 1203264167282624},
{677131386735829, 1850249298025188, 672782146532031, 2144145693078904, 2088656272813787},
{1065622343976192, 1573853211848116, 223560413590068, 333846833073379, 27832122205830},
{1781008836504573, 917619542051793, 544322748939913, 882577394308384, 1720521246471195},
},
{
{660120928379860, 2081944024858618, 1878411111349191, 424587356517195, 2111317439894005},
{1834193977811532, 1864164086863319, 797334633289424, 150410812403062, 2085177078466389},
{1438117271371866, 783915531014482, 388731514584658, 292113935417795, 1945855002546714},
{1678140823166658, 679103239148744, 614102761596238, 1052962498997885, 1863983323810390},
},
{
{1690309392496233, 1116333140326275, 1377242323631039, 717196888780674, 82724646713353},
{1722370213432106, 74265192976253, 264239578448472, 1714909985012994, 2216984958602173},
{2010482366920922, 1294036471886319, 566466395005815, 1631955803657320, 1751698647538458},
{1073230604155753, 1159087041338551, 1664057985455483, 127472702826203, 1339591128522371},
},
{
{478053307175577, 2179515791720985, 21146535423512, 1831683844029536, 462805561553981},
{1945267486565588, 1298536818409655, 2214511796262989, 1904981051429012, 252904800782086},
{268945954671210, 222740425595395, 1208025911856230, 1080418823003555, 75929831922483},
{1884784014268948, 643868448202966, 978736549726821, 46385971089796, 1296884812292320},
},
{
{1861159462859103, 7077532564710, 963010365896826, 1938780006785270, 766241051941647},
{1778966986051906, 1713995999765361, 1394565822271816, 1366699246468722, 1213407027149475},
{1978989286560907, 2135084162045594, 1951565508865477, 671788336314416, 293123929458176},
{902608944504080, 2167765718046481, 1285718473078022, 1222562171329269, 492109027844479},
},
{
{1820807832746213, 1029220580458586, 1101997555432203, 1039081975563572, 202477981158221},
{1866134980680205, 2222325502763386, 1830284629571201, 1046966214478970, 418381946936795},
{1783460633291322, 1719505443254998, 1810489639976220, 877049370713018, 2187801198742619},
{197118243000763, 305493867565736, 518814410156522, 1656246186645170, 901894734874934},
},
{
{225454942125915, 478410476654509, 600524586037746, 643450007230715, 1018615928259319},
{1733330584845708, 881092297970296, 507039890129464, 496397090721598, 2230888519577628},
{690155664737246, 1010454785646677, 753170144375012, 1651277613844874, 1622648796364156},
{1321310321891618, 1089655277873603, 235891750867089, 815878279563688, 1709264240047556},
},
{
{805027036551342, 1387174275567452, 1156538511461704, 1465897486692171, 1208567094120903},
{2228417017817483, 202885584970535, 2182114782271881, 2077405042592934, 1029684358182774},
{460447547653983, 627817697755692, 524899434670834, 1228019344939427, 740684787777653},
{849757462467675, 447476306919899, 422618957298818, 302134659227815, 675831828440895},
},
}
ge_scalarmult :: proc "contextless" (ge, p: ^Group_Element, sc: ^Scalar) {
tmp: field.Non_Montgomery_Domain_Field_Element
field.fe_from_montgomery(&tmp, sc)
_ge_scalarmult(ge, p, &tmp)
mem.zero_explicit(&tmp, size_of(tmp))
}
ge_scalarmult_basepoint :: proc "contextless" (ge: ^Group_Element, sc: ^Scalar) {
// Something like the comb method from "Fast and compact elliptic-curve
// cryptography" Section 3.3, would be more performant, but more
// complex.
//
// - https://eprint.iacr.org/2012/309
ge_scalarmult(ge, &GE_BASEPOINT, sc)
}
ge_scalarmult_vartime :: proc "contextless" (ge, p: ^Group_Element, sc: ^Scalar) {
tmp: field.Non_Montgomery_Domain_Field_Element
field.fe_from_montgomery(&tmp, sc)
_ge_scalarmult(ge, p, &tmp, true)
}
ge_double_scalarmult_basepoint_vartime :: proc "contextless" (
ge: ^Group_Element,
a: ^Scalar,
A: ^Group_Element,
b: ^Scalar,
) {
// Strauss-Shamir, commonly referred to as the "Shamir trick",
// saves half the doublings, relative to doing this the naive way.
//
// ABGLSV-Pornin (https://eprint.iacr.org/2020/454) is faster,
// but significantly more complex, and has incompatibilities with
// mixed-order group elements.
tmp_add: Add_Scratch = ---
tmp_addend: Addend_Group_Element = ---
tmp_dbl: Double_Scratch = ---
tmp: Group_Element = ---
A_tbl: Multiply_Table = ---
mul_tbl_set(&A_tbl, A, &tmp_add)
sc_a, sc_b: field.Non_Montgomery_Domain_Field_Element
field.fe_from_montgomery(&sc_a, a)
field.fe_from_montgomery(&sc_b, b)
ge_identity(&tmp)
for i := 31; i >= 0; i = i - 1 {
limb := i / 8
shift := uint(i & 7) * 8
limb_byte_a := sc_a[limb] >> shift
limb_byte_b := sc_b[limb] >> shift
hi_a, lo_a := (limb_byte_a >> 4) & 0x0f, limb_byte_a & 0x0f
hi_b, lo_b := (limb_byte_b >> 4) & 0x0f, limb_byte_b & 0x0f
if i != 31 {
ge_double(&tmp, &tmp, &tmp_dbl)
ge_double(&tmp, &tmp, &tmp_dbl)
ge_double(&tmp, &tmp, &tmp_dbl)
ge_double(&tmp, &tmp, &tmp_dbl)
}
mul_tbl_add(&tmp, &A_tbl, hi_a, &tmp_add, &tmp_addend, true)
mul_tbl_add(&tmp, &GE_BASEPOINT_TABLE, hi_b, &tmp_add, &tmp_addend, true)
ge_double(&tmp, &tmp, &tmp_dbl)
ge_double(&tmp, &tmp, &tmp_dbl)
ge_double(&tmp, &tmp, &tmp_dbl)
ge_double(&tmp, &tmp, &tmp_dbl)
mul_tbl_add(&tmp, &A_tbl, lo_a, &tmp_add, &tmp_addend, true)
mul_tbl_add(&tmp, &GE_BASEPOINT_TABLE, lo_b, &tmp_add, &tmp_addend, true)
}
ge_set(ge, &tmp)
}
@(private)
_ge_scalarmult :: proc "contextless" (
ge, p: ^Group_Element,
sc: ^field.Non_Montgomery_Domain_Field_Element,
unsafe_is_vartime := false,
) {
// Do the simplest possible thing that works and provides adequate,
// performance, which is windowed add-then-multiply.
tmp_add: Add_Scratch = ---
tmp_addend: Addend_Group_Element = ---
tmp_dbl: Double_Scratch = ---
tmp: Group_Element = ---
p_tbl: Multiply_Table = ---
mul_tbl_set(&p_tbl, p, &tmp_add)
ge_identity(&tmp)
for i := 31; i >= 0; i = i - 1 {
limb := i / 8
shift := uint(i & 7) * 8
limb_byte := sc[limb] >> shift
hi, lo := (limb_byte >> 4) & 0x0f, limb_byte & 0x0f
if i != 31 {
ge_double(&tmp, &tmp, &tmp_dbl)
ge_double(&tmp, &tmp, &tmp_dbl)
ge_double(&tmp, &tmp, &tmp_dbl)
ge_double(&tmp, &tmp, &tmp_dbl)
}
mul_tbl_add(&tmp, &p_tbl, hi, &tmp_add, &tmp_addend, unsafe_is_vartime)
ge_double(&tmp, &tmp, &tmp_dbl)
ge_double(&tmp, &tmp, &tmp_dbl)
ge_double(&tmp, &tmp, &tmp_dbl)
ge_double(&tmp, &tmp, &tmp_dbl)
mul_tbl_add(&tmp, &p_tbl, lo, &tmp_add, &tmp_addend, unsafe_is_vartime)
}
ge_set(ge, &tmp)
if !unsafe_is_vartime {
ge_clear(&tmp)
mem.zero_explicit(&tmp_add, size_of(Add_Scratch))
mem.zero_explicit(&tmp_addend, size_of(Addend_Group_Element))
mem.zero_explicit(&tmp_dbl, size_of(Double_Scratch))
}
}
@(private)
Multiply_Table :: [15]Addend_Group_Element // 0 = inf, which is implicit.
@(private)
mul_tbl_set :: proc "contextless" (
tbl: ^Multiply_Table,
ge: ^Group_Element,
tmp_add: ^Add_Scratch,
) {
tmp: Group_Element = ---
ge_set(&tmp, ge)
ge_addend_set(&tbl[0], ge)
for i := 1; i < 15; i = i + 1 {
ge_add_addend(&tmp, &tmp, &tbl[0], tmp_add)
ge_addend_set(&tbl[i], &tmp)
}
ge_clear(&tmp)
}
@(private)
mul_tbl_add :: proc "contextless" (
ge: ^Group_Element,
tbl: ^Multiply_Table,
idx: u64,
tmp_add: ^Add_Scratch,
tmp_addend: ^Addend_Group_Element,
unsafe_is_vartime: bool,
) {
// Variable time lookup, with the addition omitted entirely if idx == 0.
if unsafe_is_vartime {
// Skip adding the point at infinity.
if idx != 0 {
ge_add_addend(ge, ge, &tbl[idx - 1], tmp_add)
}
return
}
// Constant time lookup.
tmp_addend^ = {
// Point at infinity (0, 1, 1, 0) in precomputed form
{1, 0, 0, 0, 0}, // y - x
{1, 0, 0, 0, 0}, // y + x
{0, 0, 0, 0, 0}, // t * 2d
{2, 0, 0, 0, 0}, // z * 2
}
for i := u64(1); i < 16; i = i + 1 {
_, ctrl := bits.sub_u64(0, (i ~ idx), 0)
ge_addend_conditional_assign(tmp_addend, &tbl[i - 1], int(~ctrl) & 1)
}
ge_add_addend(ge, ge, tmp_addend, tmp_add)
}
+2 -2
View File
@@ -9,7 +9,7 @@ package fiat
u1 :: distinct u8
i1 :: distinct i8
@(optimization_mode="none")
@(optimization_mode = "none")
cmovznz_u64 :: proc "contextless" (arg1: u1, arg2, arg3: u64) -> (out1: u64) {
x1 := (u64(arg1) * 0xffffffffffffffff)
x2 := ((x1 & arg3) | ((~x1) & arg2))
@@ -17,7 +17,7 @@ cmovznz_u64 :: proc "contextless" (arg1: u1, arg2, arg3: u64) -> (out1: u64) {
return
}
@(optimization_mode="none")
@(optimization_mode = "none")
cmovznz_u32 :: proc "contextless" (arg1: u1, arg2, arg3: u32) -> (out1: u32) {
x1 := (u32(arg1) * 0xffffffff)
x2 := ((x1 & arg3) | ((~x1) & arg2))
+173 -44
View File
@@ -3,12 +3,30 @@ package field_curve25519
import "core:crypto"
import "core:mem"
fe_relax_cast :: #force_inline proc "contextless" (arg1: ^Tight_Field_Element) -> ^Loose_Field_Element {
return transmute(^Loose_Field_Element)(arg1)
fe_relax_cast :: #force_inline proc "contextless" (
arg1: ^Tight_Field_Element,
) -> ^Loose_Field_Element {
return (^Loose_Field_Element)(arg1)
}
fe_tighten_cast :: #force_inline proc "contextless" (arg1: ^Loose_Field_Element) -> ^Tight_Field_Element {
return transmute(^Tight_Field_Element)(arg1)
fe_tighten_cast :: #force_inline proc "contextless" (
arg1: ^Loose_Field_Element,
) -> ^Tight_Field_Element {
return (^Tight_Field_Element)(arg1)
}
fe_clear :: proc "contextless" (
arg1: $T,
) where T == ^Tight_Field_Element || T == ^Loose_Field_Element {
mem.zero_explicit(arg1, size_of(arg1^))
}
fe_clear_vec :: proc "contextless" (
arg1: $T,
) where T == []^Tight_Field_Element || T == []^Loose_Field_Element {
for fe in arg1 {
fe_clear(fe)
}
}
fe_from_bytes :: proc "contextless" (out1: ^Tight_Field_Element, arg1: ^[32]byte) {
@@ -23,12 +41,25 @@ fe_from_bytes :: proc "contextless" (out1: ^Tight_Field_Element, arg1: ^[32]byte
mem.zero_explicit(&tmp1, size_of(tmp1))
}
fe_is_negative :: proc "contextless" (arg1: ^Tight_Field_Element) -> int {
tmp1: [32]byte = ---
fe_to_bytes(&tmp1, arg1)
ret := tmp1[0] & 1
mem.zero_explicit(&tmp1, size_of(tmp1))
return int(ret)
}
fe_equal :: proc "contextless" (arg1, arg2: ^Tight_Field_Element) -> int {
tmp2: [32]byte = ---
tmp1, tmp2: [32]byte = ---, ---
fe_to_bytes(&tmp1, arg1)
fe_to_bytes(&tmp2, arg2)
ret := fe_equal_bytes(arg1, &tmp2)
ret := crypto.compare_constant_time(tmp1[:], tmp2[:])
mem.zero_explicit(&tmp1, size_of(tmp1))
mem.zero_explicit(&tmp2, size_of(tmp2))
return ret
@@ -46,7 +77,11 @@ fe_equal_bytes :: proc "contextless" (arg1: ^Tight_Field_Element, arg2: ^[32]byt
return ret
}
fe_carry_pow2k :: proc (out1: ^Tight_Field_Element, arg1: ^Loose_Field_Element, arg2: uint) {
fe_carry_pow2k :: proc "contextless" (
out1: ^Tight_Field_Element,
arg1: ^Loose_Field_Element,
arg2: uint,
) {
// Special case: `arg1^(2 * 0) = 1`, though this should never happen.
if arg2 == 0 {
fe_one(out1)
@@ -54,27 +89,46 @@ fe_carry_pow2k :: proc (out1: ^Tight_Field_Element, arg1: ^Loose_Field_Element,
}
fe_carry_square(out1, arg1)
for _ in 1..<arg2 {
for _ in 1 ..< arg2 {
fe_carry_square(out1, fe_relax_cast(out1))
}
}
fe_carry_add :: #force_inline proc "contextless" (out1, arg1, arg2: ^Tight_Field_Element) {
fe_add(fe_relax_cast(out1), arg1, arg2)
fe_carry(out1, fe_relax_cast(out1))
}
fe_carry_sub :: #force_inline proc "contextless" (out1, arg1, arg2: ^Tight_Field_Element) {
fe_sub(fe_relax_cast(out1), arg1, arg2)
fe_carry(out1, fe_relax_cast(out1))
}
fe_carry_opp :: #force_inline proc "contextless" (out1, arg1: ^Tight_Field_Element) {
fe_opp(fe_relax_cast(out1), arg1)
fe_carry(out1, fe_relax_cast(out1))
}
fe_carry_invsqrt :: proc (out1: ^Tight_Field_Element, arg1: ^Loose_Field_Element) -> int {
// Inverse square root taken from Monocypher.
fe_carry_abs :: #force_inline proc "contextless" (out1, arg1: ^Tight_Field_Element) {
fe_cond_negate(out1, arg1, fe_is_negative(arg1))
}
fe_carry_sqrt_ratio_m1 :: proc "contextless" (
out1: ^Tight_Field_Element,
arg1: ^Loose_Field_Element, // u
arg2: ^Loose_Field_Element, // v
) -> int {
// SQRT_RATIO_M1(u, v) from RFC 9496 - 4.2, based on the inverse
// square root from Monocypher.
w: Tight_Field_Element = ---
fe_carry_mul(&w, arg1, arg2) // u * v
// r = tmp1 = u * w^((p-5)/8)
tmp1, tmp2, tmp3: Tight_Field_Element = ---, ---, ---
// t0 = x^((p-5)/8)
// Can be achieved with a simple double & add ladder,
// but it would be slower.
fe_carry_pow2k(&tmp1, arg1, 1)
fe_carry_pow2k(&tmp1, fe_relax_cast(&w), 1)
fe_carry_pow2k(&tmp2, fe_relax_cast(&tmp1), 2)
fe_carry_mul(&tmp2, arg1, fe_relax_cast(&tmp2))
fe_carry_mul(&tmp2, fe_relax_cast(&w), fe_relax_cast(&tmp2))
fe_carry_mul(&tmp1, fe_relax_cast(&tmp1), fe_relax_cast(&tmp2))
fe_carry_pow2k(&tmp1, fe_relax_cast(&tmp1), 1)
fe_carry_mul(&tmp1, fe_relax_cast(&tmp2), fe_relax_cast(&tmp1))
@@ -93,46 +147,121 @@ fe_carry_invsqrt :: proc (out1: ^Tight_Field_Element, arg1: ^Loose_Field_Element
fe_carry_pow2k(&tmp2, fe_relax_cast(&tmp2), 50)
fe_carry_mul(&tmp1, fe_relax_cast(&tmp2), fe_relax_cast(&tmp1))
fe_carry_pow2k(&tmp1, fe_relax_cast(&tmp1), 2)
fe_carry_mul(&tmp1, fe_relax_cast(&tmp1), arg1)
fe_carry_mul(&tmp1, fe_relax_cast(&tmp1), fe_relax_cast(&w)) // w^((p-5)/8)
// quartic = x^((p-1)/4)
quartic := &tmp2
fe_carry_square(quartic, fe_relax_cast(&tmp1))
fe_carry_mul(quartic, fe_relax_cast(quartic), arg1)
fe_carry_mul(&tmp1, fe_relax_cast(&tmp1), arg1) // u * w^((p-5)/8)
// Serialize quartic once to save on repeated serialization/sanitization.
quartic_buf: [32]byte = ---
fe_to_bytes(&quartic_buf, quartic)
check := &tmp3
// Serialize `check` once to save on repeated serialization.
r, check := &tmp1, &tmp2
b: [32]byte = ---
fe_carry_square(check, fe_relax_cast(r))
fe_carry_mul(check, fe_relax_cast(check), arg2) // check * v
fe_to_bytes(&b, check)
fe_one(check)
p1 := fe_equal_bytes(check, &quartic_buf)
fe_carry_opp(check, check)
m1 := fe_equal_bytes(check, &quartic_buf)
fe_carry_opp(check, &SQRT_M1)
ms := fe_equal_bytes(check, &quartic_buf)
u, neg_u, neg_u_i := &tmp3, &w, check
fe_carry(u, arg1)
fe_carry_opp(neg_u, u)
fe_carry_mul(neg_u_i, fe_relax_cast(neg_u), fe_relax_cast(&FE_SQRT_M1))
// if quartic == -1 or sqrt(-1)
// then isr = x^((p-1)/4) * sqrt(-1)
// else isr = x^((p-1)/4)
fe_carry_mul(out1, fe_relax_cast(&tmp1), fe_relax_cast(&SQRT_M1))
fe_cond_assign(out1, &tmp1, (m1|ms) ~ 1)
correct_sign_sqrt := fe_equal_bytes(u, &b)
flipped_sign_sqrt := fe_equal_bytes(neg_u, &b)
flipped_sign_sqrt_i := fe_equal_bytes(neg_u_i, &b)
mem.zero_explicit(&tmp1, size_of(tmp1))
mem.zero_explicit(&tmp2, size_of(tmp2))
mem.zero_explicit(&tmp3, size_of(tmp3))
mem.zero_explicit(&quartic_buf, size_of(quartic_buf))
r_prime := check
fe_carry_mul(r_prime, fe_relax_cast(r), fe_relax_cast(&FE_SQRT_M1))
fe_cond_assign(r, r_prime, flipped_sign_sqrt | flipped_sign_sqrt_i)
return p1 | m1
// Pick the non-negative square root.
fe_carry_abs(out1, r)
fe_clear_vec([]^Tight_Field_Element{&w, &tmp1, &tmp2, &tmp3})
mem.zero_explicit(&b, size_of(b))
return correct_sign_sqrt | flipped_sign_sqrt
}
fe_carry_inv :: proc (out1: ^Tight_Field_Element, arg1: ^Loose_Field_Element) {
fe_carry_inv :: proc "contextless" (out1: ^Tight_Field_Element, arg1: ^Loose_Field_Element) {
tmp1: Tight_Field_Element
fe_carry_square(&tmp1, arg1)
_ = fe_carry_invsqrt(&tmp1, fe_relax_cast(&tmp1))
_ = fe_carry_sqrt_ratio_m1(&tmp1, fe_relax_cast(&FE_ONE), fe_relax_cast(&tmp1))
fe_carry_square(&tmp1, fe_relax_cast(&tmp1))
fe_carry_mul(out1, fe_relax_cast(&tmp1), arg1)
mem.zero_explicit(&tmp1, size_of(tmp1))
fe_clear(&tmp1)
}
fe_zero :: proc "contextless" (out1: ^Tight_Field_Element) {
out1[0] = 0
out1[1] = 0
out1[2] = 0
out1[3] = 0
out1[4] = 0
}
fe_one :: proc "contextless" (out1: ^Tight_Field_Element) {
out1[0] = 1
out1[1] = 0
out1[2] = 0
out1[3] = 0
out1[4] = 0
}
fe_set :: proc "contextless" (out1, arg1: ^Tight_Field_Element) {
x1 := arg1[0]
x2 := arg1[1]
x3 := arg1[2]
x4 := arg1[3]
x5 := arg1[4]
out1[0] = x1
out1[1] = x2
out1[2] = x3
out1[3] = x4
out1[4] = x5
}
@(optimization_mode = "none")
fe_cond_swap :: #force_no_inline proc "contextless" (out1, out2: ^Tight_Field_Element, arg1: int) {
mask := (u64(arg1) * 0xffffffffffffffff)
x := (out1[0] ~ out2[0]) & mask
x1, y1 := out1[0] ~ x, out2[0] ~ x
x = (out1[1] ~ out2[1]) & mask
x2, y2 := out1[1] ~ x, out2[1] ~ x
x = (out1[2] ~ out2[2]) & mask
x3, y3 := out1[2] ~ x, out2[2] ~ x
x = (out1[3] ~ out2[3]) & mask
x4, y4 := out1[3] ~ x, out2[3] ~ x
x = (out1[4] ~ out2[4]) & mask
x5, y5 := out1[4] ~ x, out2[4] ~ x
out1[0], out2[0] = x1, y1
out1[1], out2[1] = x2, y2
out1[2], out2[2] = x3, y3
out1[3], out2[3] = x4, y4
out1[4], out2[4] = x5, y5
}
@(optimization_mode = "none")
fe_cond_select :: #force_no_inline proc "contextless" (
out1, arg1, arg2: $T,
arg3: int,
) where T == ^Tight_Field_Element || T == ^Loose_Field_Element {
mask := (u64(arg3) * 0xffffffffffffffff)
x1 := ((mask & arg2[0]) | ((~mask) & arg1[0]))
x2 := ((mask & arg2[1]) | ((~mask) & arg1[1]))
x3 := ((mask & arg2[2]) | ((~mask) & arg1[2]))
x4 := ((mask & arg2[3]) | ((~mask) & arg1[3]))
x5 := ((mask & arg2[4]) | ((~mask) & arg1[4]))
out1[0] = x1
out1[1] = x2
out1[2] = x3
out1[3] = x4
out1[4] = x5
}
fe_cond_negate :: proc "contextless" (out1, arg1: ^Tight_Field_Element, ctrl: int) {
tmp1: Tight_Field_Element = ---
fe_carry_opp(&tmp1, arg1)
fe_cond_select(out1, arg1, &tmp1, ctrl)
fe_clear(&tmp1)
}
+29 -61
View File
@@ -30,8 +30,6 @@ package field_curve25519
//
// While the base implementation is provably correct, this implementation
// makes no such claims as the port and optimizations were done by hand.
// At some point, it may be worth adding support to fiat-crypto for
// generating Odin output.
//
// TODO:
// * When fiat-crypto supports it, using a saturated 64-bit limbs
@@ -44,7 +42,10 @@ import "core:math/bits"
Loose_Field_Element :: distinct [5]u64
Tight_Field_Element :: distinct [5]u64
SQRT_M1 := Tight_Field_Element{
FE_ZERO := Tight_Field_Element{0, 0, 0, 0, 0}
FE_ONE := Tight_Field_Element{1, 0, 0, 0, 0}
FE_SQRT_M1 := Tight_Field_Element {
1718705420411056,
234908883556509,
2233514472574048,
@@ -52,7 +53,13 @@ SQRT_M1 := Tight_Field_Element{
765476049583133,
}
_addcarryx_u51 :: #force_inline proc "contextless" (arg1: fiat.u1, arg2, arg3: u64) -> (out1: u64, out2: fiat.u1) {
_addcarryx_u51 :: #force_inline proc "contextless" (
arg1: fiat.u1,
arg2, arg3: u64,
) -> (
out1: u64,
out2: fiat.u1,
) {
x1 := ((u64(arg1) + arg2) + arg3)
x2 := (x1 & 0x7ffffffffffff)
x3 := fiat.u1((x1 >> 51))
@@ -61,7 +68,13 @@ _addcarryx_u51 :: #force_inline proc "contextless" (arg1: fiat.u1, arg2, arg3: u
return
}
_subborrowx_u51 :: #force_inline proc "contextless" (arg1: fiat.u1, arg2, arg3: u64) -> (out1: u64, out2: fiat.u1) {
_subborrowx_u51 :: #force_inline proc "contextless" (
arg1: fiat.u1,
arg2, arg3: u64,
) -> (
out1: u64,
out2: fiat.u1,
) {
x1 := ((i64(arg2) - i64(arg1)) - i64(arg3))
x2 := fiat.i1((x1 >> 51))
x3 := (u64(x1) & 0x7ffffffffffff)
@@ -70,7 +83,7 @@ _subborrowx_u51 :: #force_inline proc "contextless" (arg1: fiat.u1, arg2, arg3:
return
}
fe_carry_mul :: proc (out1: ^Tight_Field_Element, arg1, arg2: ^Loose_Field_Element) {
fe_carry_mul :: proc "contextless" (out1: ^Tight_Field_Element, arg1, arg2: ^Loose_Field_Element) {
x2, x1 := bits.mul_u64(arg1[4], (arg2[4] * 0x13))
x4, x3 := bits.mul_u64(arg1[4], (arg2[3] * 0x13))
x6, x5 := bits.mul_u64(arg1[4], (arg2[2] * 0x13))
@@ -169,7 +182,7 @@ fe_carry_mul :: proc (out1: ^Tight_Field_Element, arg1, arg2: ^Loose_Field_Eleme
out1[4] = x152
}
fe_carry_square :: proc (out1: ^Tight_Field_Element, arg1: ^Loose_Field_Element) {
fe_carry_square :: proc "contextless" (out1: ^Tight_Field_Element, arg1: ^Loose_Field_Element) {
x1 := (arg1[4] * 0x13)
x2 := (x1 * 0x2)
x3 := (arg1[4] * 0x2)
@@ -305,8 +318,11 @@ fe_opp :: proc "contextless" (out1: ^Loose_Field_Element, arg1: ^Tight_Field_Ele
out1[4] = x5
}
@(optimization_mode="none")
fe_cond_assign :: #force_no_inline proc "contextless" (out1, arg1: ^Tight_Field_Element, arg2: int) {
@(optimization_mode = "none")
fe_cond_assign :: #force_no_inline proc "contextless" (
out1, arg1: ^Tight_Field_Element,
arg2: int,
) {
x1 := fiat.cmovznz_u64(fiat.u1(arg2), out1[0], arg1[0])
x2 := fiat.cmovznz_u64(fiat.u1(arg2), out1[1], arg1[1])
x3 := fiat.cmovznz_u64(fiat.u1(arg2), out1[2], arg1[2])
@@ -527,7 +543,10 @@ fe_relax :: proc "contextless" (out1: ^Loose_Field_Element, arg1: ^Tight_Field_E
out1[4] = x5
}
fe_carry_scmul_121666 :: proc (out1: ^Tight_Field_Element, arg1: ^Loose_Field_Element) {
fe_carry_scmul_121666 :: proc "contextless" (
out1: ^Tight_Field_Element,
arg1: ^Loose_Field_Element,
) {
x2, x1 := bits.mul_u64(0x1db42, arg1[4])
x4, x3 := bits.mul_u64(0x1db42, arg1[3])
x6, x5 := bits.mul_u64(0x1db42, arg1[2])
@@ -565,54 +584,3 @@ fe_carry_scmul_121666 :: proc (out1: ^Tight_Field_Element, arg1: ^Loose_Field_El
out1[3] = x27
out1[4] = x32
}
// The following routines were added by hand, and do not come from fiat-crypto.
fe_zero :: proc "contextless" (out1: ^Tight_Field_Element) {
out1[0] = 0
out1[1] = 0
out1[2] = 0
out1[3] = 0
out1[4] = 0
}
fe_one :: proc "contextless" (out1: ^Tight_Field_Element) {
out1[0] = 1
out1[1] = 0
out1[2] = 0
out1[3] = 0
out1[4] = 0
}
fe_set :: proc "contextless" (out1, arg1: ^Tight_Field_Element) {
x1 := arg1[0]
x2 := arg1[1]
x3 := arg1[2]
x4 := arg1[3]
x5 := arg1[4]
out1[0] = x1
out1[1] = x2
out1[2] = x3
out1[3] = x4
out1[4] = x5
}
@(optimization_mode="none")
fe_cond_swap :: #force_no_inline proc "contextless" (out1, out2: ^Tight_Field_Element, arg1: int) {
mask := -u64(arg1)
x := (out1[0] ~ out2[0]) & mask
x1, y1 := out1[0] ~ x, out2[0] ~ x
x = (out1[1] ~ out2[1]) & mask
x2, y2 := out1[1] ~ x, out2[1] ~ x
x = (out1[2] ~ out2[2]) & mask
x3, y3 := out1[2] ~ x, out2[2] ~ x
x = (out1[3] ~ out2[3]) & mask
x4, y4 := out1[3] ~ x, out2[3] ~ x
x = (out1[4] ~ out2[4]) & mask
x5, y5 := out1[4] ~ x, out2[4] ~ x
out1[0], out2[0] = x1, y1
out1[1], out2[1] = x2, y2
out1[2], out2[2] = x3, y3
out1[3], out2[3] = x4, y4
out1[4], out2[4] = x5, y5
}
+49 -6
View File
@@ -1,17 +1,26 @@
package field_poly1305
import "base:intrinsics"
import "core:encoding/endian"
import "core:mem"
fe_relax_cast :: #force_inline proc "contextless" (arg1: ^Tight_Field_Element) -> ^Loose_Field_Element {
return transmute(^Loose_Field_Element)(arg1)
fe_relax_cast :: #force_inline proc "contextless" (
arg1: ^Tight_Field_Element,
) -> ^Loose_Field_Element {
return (^Loose_Field_Element)(arg1)
}
fe_tighten_cast :: #force_inline proc "contextless" (arg1: ^Loose_Field_Element) -> ^Tight_Field_Element {
return transmute(^Tight_Field_Element)(arg1)
fe_tighten_cast :: #force_inline proc "contextless" (
arg1: ^Loose_Field_Element,
) -> ^Tight_Field_Element {
return (^Tight_Field_Element)(arg1)
}
fe_from_bytes :: #force_inline proc (out1: ^Tight_Field_Element, arg1: []byte, arg2: byte) {
fe_from_bytes :: #force_inline proc "contextless" (
out1: ^Tight_Field_Element,
arg1: []byte,
arg2: byte,
) {
// fiat-crypto's deserialization routine effectively processes a
// single byte at a time, and wants 256-bits of input for a value
// that will be 128-bits or 129-bits.
@@ -20,7 +29,9 @@ fe_from_bytes :: #force_inline proc (out1: ^Tight_Field_Element, arg1: []byte, a
// makes implementing the actual MAC block processing considerably
// neater.
assert(len(arg1) == 16)
if len(arg1) != 16 {
intrinsics.trap()
}
// While it may be unwise to do deserialization here on our
// own when fiat-crypto provides equivalent functionality,
@@ -51,3 +62,35 @@ fe_from_u64s :: proc "contextless" (out1: ^Tight_Field_Element, lo, hi: u64) {
// This routine is only used to deserialize `r` which is confidential.
mem.zero_explicit(&tmp, size_of(tmp))
}
fe_zero :: proc "contextless" (out1: ^Tight_Field_Element) {
out1[0] = 0
out1[1] = 0
out1[2] = 0
}
fe_set :: #force_inline proc "contextless" (out1, arg1: ^Tight_Field_Element) {
x1 := arg1[0]
x2 := arg1[1]
x3 := arg1[2]
out1[0] = x1
out1[1] = x2
out1[2] = x3
}
@(optimization_mode = "none")
fe_cond_swap :: #force_no_inline proc "contextless" (
out1, out2: ^Tight_Field_Element,
arg1: bool,
) {
mask := (u64(arg1) * 0xffffffffffffffff)
x := (out1[0] ~ out2[0]) & mask
x1, y1 := out1[0] ~ x, out2[0] ~ x
x = (out1[1] ~ out2[1]) & mask
x2, y2 := out1[1] ~ x, out2[1] ~ x
x = (out1[2] ~ out2[2]) & mask
x3, y3 := out1[2] ~ x, out2[2] ~ x
out1[0], out2[0] = x1, y1
out1[1], out2[1] = x2, y2
out1[2], out2[2] = x3, y3
}
+35 -39
View File
@@ -39,7 +39,13 @@ import "core:math/bits"
Loose_Field_Element :: distinct [3]u64
Tight_Field_Element :: distinct [3]u64
_addcarryx_u44 :: #force_inline proc "contextless" (arg1: fiat.u1, arg2, arg3: u64) -> (out1: u64, out2: fiat.u1) {
_addcarryx_u44 :: #force_inline proc "contextless" (
arg1: fiat.u1,
arg2, arg3: u64,
) -> (
out1: u64,
out2: fiat.u1,
) {
x1 := ((u64(arg1) + arg2) + arg3)
x2 := (x1 & 0xfffffffffff)
x3 := fiat.u1((x1 >> 44))
@@ -48,7 +54,13 @@ _addcarryx_u44 :: #force_inline proc "contextless" (arg1: fiat.u1, arg2, arg3: u
return
}
_subborrowx_u44 :: #force_inline proc "contextless" (arg1: fiat.u1, arg2, arg3: u64) -> (out1: u64, out2: fiat.u1) {
_subborrowx_u44 :: #force_inline proc "contextless" (
arg1: fiat.u1,
arg2, arg3: u64,
) -> (
out1: u64,
out2: fiat.u1,
) {
x1 := ((i64(arg2) - i64(arg1)) - i64(arg3))
x2 := fiat.i1((x1 >> 44))
x3 := (u64(x1) & 0xfffffffffff)
@@ -57,7 +69,13 @@ _subborrowx_u44 :: #force_inline proc "contextless" (arg1: fiat.u1, arg2, arg3:
return
}
_addcarryx_u43 :: #force_inline proc "contextless" (arg1: fiat.u1, arg2, arg3: u64) -> (out1: u64, out2: fiat.u1) {
_addcarryx_u43 :: #force_inline proc "contextless" (
arg1: fiat.u1,
arg2, arg3: u64,
) -> (
out1: u64,
out2: fiat.u1,
) {
x1 := ((u64(arg1) + arg2) + arg3)
x2 := (x1 & 0x7ffffffffff)
x3 := fiat.u1((x1 >> 43))
@@ -66,7 +84,13 @@ _addcarryx_u43 :: #force_inline proc "contextless" (arg1: fiat.u1, arg2, arg3: u
return
}
_subborrowx_u43 :: #force_inline proc "contextless" (arg1: fiat.u1, arg2, arg3: u64) -> (out1: u64, out2: fiat.u1) {
_subborrowx_u43 :: #force_inline proc "contextless" (
arg1: fiat.u1,
arg2, arg3: u64,
) -> (
out1: u64,
out2: fiat.u1,
) {
x1 := ((i64(arg2) - i64(arg1)) - i64(arg3))
x2 := fiat.i1((x1 >> 43))
x3 := (u64(x1) & 0x7ffffffffff)
@@ -75,7 +99,7 @@ _subborrowx_u43 :: #force_inline proc "contextless" (arg1: fiat.u1, arg2, arg3:
return
}
fe_carry_mul :: proc (out1: ^Tight_Field_Element, arg1, arg2: ^Loose_Field_Element) {
fe_carry_mul :: proc "contextless" (out1: ^Tight_Field_Element, arg1, arg2: ^Loose_Field_Element) {
x2, x1 := bits.mul_u64(arg1[2], (arg2[2] * 0x5))
x4, x3 := bits.mul_u64(arg1[2], (arg2[1] * 0xa))
x6, x5 := bits.mul_u64(arg1[1], (arg2[2] * 0xa))
@@ -120,7 +144,7 @@ fe_carry_mul :: proc (out1: ^Tight_Field_Element, arg1, arg2: ^Loose_Field_Eleme
out1[2] = x62
}
fe_carry_square :: proc (out1: ^Tight_Field_Element, arg1: ^Loose_Field_Element) {
fe_carry_square :: proc "contextless" (out1: ^Tight_Field_Element, arg1: ^Loose_Field_Element) {
x1 := (arg1[2] * 0x5)
x2 := (x1 * 0x2)
x3 := (arg1[2] * 0x2)
@@ -201,8 +225,11 @@ fe_opp :: proc "contextless" (out1: ^Loose_Field_Element, arg1: ^Tight_Field_Ele
out1[2] = x3
}
@(optimization_mode="none")
fe_cond_assign :: #force_no_inline proc "contextless" (out1, arg1: ^Tight_Field_Element, arg2: bool) {
@(optimization_mode = "none")
fe_cond_assign :: #force_no_inline proc "contextless" (
out1, arg1: ^Tight_Field_Element,
arg2: bool,
) {
x1 := fiat.cmovznz_u64(fiat.u1(arg2), out1[0], arg1[0])
x2 := fiat.cmovznz_u64(fiat.u1(arg2), out1[1], arg1[1])
x3 := fiat.cmovznz_u64(fiat.u1(arg2), out1[2], arg1[2])
@@ -325,34 +352,3 @@ fe_relax :: proc "contextless" (out1: ^Loose_Field_Element, arg1: ^Tight_Field_E
out1[1] = x2
out1[2] = x3
}
// The following routines were added by hand, and do not come from fiat-crypto.
fe_zero :: proc "contextless" (out1: ^Tight_Field_Element) {
out1[0] = 0
out1[1] = 0
out1[2] = 0
}
fe_set :: #force_inline proc "contextless" (out1, arg1: ^Tight_Field_Element) {
x1 := arg1[0]
x2 := arg1[1]
x3 := arg1[2]
out1[0] = x1
out1[1] = x2
out1[2] = x3
}
@(optimization_mode="none")
fe_cond_swap :: #force_no_inline proc "contextless" (out1, out2: ^Tight_Field_Element, arg1: bool) {
mask := -u64(arg1)
x := (out1[0] ~ out2[0]) & mask
x1, y1 := out1[0] ~ x, out2[0] ~ x
x = (out1[1] ~ out2[1]) & mask
x2, y2 := out1[1] ~ x, out2[1] ~ x
x = (out1[2] ~ out2[2]) & mask
x3, y3 := out1[2] ~ x, out2[2] ~ x
out1[0], out2[0] = x1, y1
out1[1], out2[1] = x2, y2
out1[2], out2[2] = x3, y3
}
@@ -0,0 +1,153 @@
package field_scalar25519
import "base:intrinsics"
import "core:encoding/endian"
import "core:math/bits"
import "core:mem"
@(private)
_TWO_168 := Montgomery_Domain_Field_Element {
0x5b8ab432eac74798,
0x38afddd6de59d5d7,
0xa2c131b399411b7c,
0x6329a7ed9ce5a30,
}
@(private)
_TWO_336 := Montgomery_Domain_Field_Element {
0xbd3d108e2b35ecc5,
0x5c3a3718bdf9c90b,
0x63aa97a331b4f2ee,
0x3d217f5be65cb5c,
}
fe_clear :: proc "contextless" (arg1: ^Montgomery_Domain_Field_Element) {
mem.zero_explicit(arg1, size_of(Montgomery_Domain_Field_Element))
}
fe_from_bytes :: proc "contextless" (
out1: ^Montgomery_Domain_Field_Element,
arg1: ^[32]byte,
unsafe_assume_canonical := false,
) -> bool {
tmp := Non_Montgomery_Domain_Field_Element {
endian.unchecked_get_u64le(arg1[0:]),
endian.unchecked_get_u64le(arg1[8:]),
endian.unchecked_get_u64le(arg1[16:]),
endian.unchecked_get_u64le(arg1[24:]),
}
defer mem.zero_explicit(&tmp, size_of(tmp))
// Check that tmp is in the the range [0, ELL).
if !unsafe_assume_canonical {
_, borrow := bits.sub_u64(ELL[0] - 1, tmp[0], 0)
_, borrow = bits.sub_u64(ELL[1], tmp[1], borrow)
_, borrow = bits.sub_u64(ELL[2], tmp[2], borrow)
_, borrow = bits.sub_u64(ELL[3], tmp[3], borrow)
if borrow != 0 {
return false
}
}
fe_to_montgomery(out1, &tmp)
return true
}
fe_from_bytes_rfc8032 :: proc "contextless" (
out1: ^Montgomery_Domain_Field_Element,
arg1: ^[32]byte,
) {
tmp: [64]byte
copy(tmp[:], arg1[:])
// Apply "clamping" as in RFC 8032.
tmp[0] &= 248
tmp[31] &= 127
tmp[31] |= 64 // Sets the 254th bit, so the encoding is non-canonical.
fe_from_bytes_wide(out1, &tmp)
mem.zero_explicit(&tmp, size_of(tmp))
}
fe_from_bytes_wide :: proc "contextless" (
out1: ^Montgomery_Domain_Field_Element,
arg1: ^[64]byte,
) {
tmp: Montgomery_Domain_Field_Element
// Use Frank Denis' trick, as documented by Filippo Valsorda
// at https://words.filippo.io/dispatches/wide-reduction/
//
// x = c * 2^336 + b * 2^168 + a mod l
_fe_from_bytes_short(out1, arg1[:21]) // a
_fe_from_bytes_short(&tmp, arg1[21:42]) // b
fe_mul(&tmp, &tmp, &_TWO_168) // b * 2^168
fe_add(out1, out1, &tmp) // a + b * 2^168
_fe_from_bytes_short(&tmp, arg1[42:]) // c
fe_mul(&tmp, &tmp, &_TWO_336) // c * 2^336
fe_add(out1, out1, &tmp) // a + b * 2^168 + c * 2^336
fe_clear(&tmp)
}
@(private)
_fe_from_bytes_short :: proc "contextless" (out1: ^Montgomery_Domain_Field_Element, arg1: []byte) {
// INVARIANT: len(arg1) < 32.
if len(arg1) >= 32 {
intrinsics.trap()
}
tmp: [32]byte
copy(tmp[:], arg1)
_ = fe_from_bytes(out1, &tmp, true)
mem.zero_explicit(&tmp, size_of(tmp))
}
fe_to_bytes :: proc "contextless" (out1: []byte, arg1: ^Montgomery_Domain_Field_Element) {
if len(out1) != 32 {
intrinsics.trap()
}
tmp: Non_Montgomery_Domain_Field_Element
fe_from_montgomery(&tmp, arg1)
endian.unchecked_put_u64le(out1[0:], tmp[0])
endian.unchecked_put_u64le(out1[8:], tmp[1])
endian.unchecked_put_u64le(out1[16:], tmp[2])
endian.unchecked_put_u64le(out1[24:], tmp[3])
mem.zero_explicit(&tmp, size_of(tmp))
}
fe_equal :: proc "contextless" (arg1, arg2: ^Montgomery_Domain_Field_Element) -> int {
tmp: Montgomery_Domain_Field_Element
fe_sub(&tmp, arg1, arg2)
// This will only underflow iff arg1 == arg2, and we return the borrow,
// which will be 1.
_, borrow := bits.sub_u64(fe_non_zero(&tmp), 1, 0)
fe_clear(&tmp)
return int(borrow)
}
fe_zero :: proc "contextless" (out1: ^Montgomery_Domain_Field_Element) {
out1[0] = 0
out1[1] = 0
out1[2] = 0
out1[3] = 0
}
fe_set :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element) {
x1 := arg1[0]
x2 := arg1[1]
x3 := arg1[2]
x4 := arg1[3]
out1[0] = x1
out1[1] = x2
out1[2] = x3
out1[3] = x4
}
@@ -0,0 +1,535 @@
// The BSD 1-Clause License (BSD-1-Clause)
//
// Copyright (c) 2015-2020 the fiat-crypto authors (see the AUTHORS file)
// 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 fiat-crypto 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 Berkeley Software Design,
// Inc. 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.
package field_scalar25519
// The file provides arithmetic on the field Z/(2^252+27742317777372353535851937790883648493)
// using a 64-bit Montgomery form internal representation. It is derived
// primarily from the machine generated Golang output from the fiat-crypto
// project.
//
// While the base implementation is provably correct, this implementation
// makes no such claims as the port and optimizations were done by hand.
import fiat "core:crypto/_fiat"
import "core:math/bits"
// ELL is the saturated representation of the field order, least-significant
// limb first.
ELL :: [4]u64{0x5812631a5cf5d3ed, 0x14def9dea2f79cd6, 0x0, 0x1000000000000000}
Montgomery_Domain_Field_Element :: distinct [4]u64
Non_Montgomery_Domain_Field_Element :: distinct [4]u64
fe_mul :: proc "contextless" (out1, arg1, arg2: ^Montgomery_Domain_Field_Element) {
x1 := arg1[1]
x2 := arg1[2]
x3 := arg1[3]
x4 := arg1[0]
x6, x5 := bits.mul_u64(x4, arg2[3])
x8, x7 := bits.mul_u64(x4, arg2[2])
x10, x9 := bits.mul_u64(x4, arg2[1])
x12, x11 := bits.mul_u64(x4, arg2[0])
x13, x14 := bits.add_u64(x12, x9, u64(0x0))
x15, x16 := bits.add_u64(x10, x7, u64(fiat.u1(x14)))
x17, x18 := bits.add_u64(x8, x5, u64(fiat.u1(x16)))
x19 := (u64(fiat.u1(x18)) + x6)
_, x20 := bits.mul_u64(x11, 0xd2b51da312547e1b)
x23, x22 := bits.mul_u64(x20, 0x1000000000000000)
x25, x24 := bits.mul_u64(x20, 0x14def9dea2f79cd6)
x27, x26 := bits.mul_u64(x20, 0x5812631a5cf5d3ed)
x28, x29 := bits.add_u64(x27, x24, u64(0x0))
x30 := (u64(fiat.u1(x29)) + x25)
_, x32 := bits.add_u64(x11, x26, u64(0x0))
x33, x34 := bits.add_u64(x13, x28, u64(fiat.u1(x32)))
x35, x36 := bits.add_u64(x15, x30, u64(fiat.u1(x34)))
x37, x38 := bits.add_u64(x17, x22, u64(fiat.u1(x36)))
x39, x40 := bits.add_u64(x19, x23, u64(fiat.u1(x38)))
x42, x41 := bits.mul_u64(x1, arg2[3])
x44, x43 := bits.mul_u64(x1, arg2[2])
x46, x45 := bits.mul_u64(x1, arg2[1])
x48, x47 := bits.mul_u64(x1, arg2[0])
x49, x50 := bits.add_u64(x48, x45, u64(0x0))
x51, x52 := bits.add_u64(x46, x43, u64(fiat.u1(x50)))
x53, x54 := bits.add_u64(x44, x41, u64(fiat.u1(x52)))
x55 := (u64(fiat.u1(x54)) + x42)
x56, x57 := bits.add_u64(x33, x47, u64(0x0))
x58, x59 := bits.add_u64(x35, x49, u64(fiat.u1(x57)))
x60, x61 := bits.add_u64(x37, x51, u64(fiat.u1(x59)))
x62, x63 := bits.add_u64(x39, x53, u64(fiat.u1(x61)))
x64, x65 := bits.add_u64(u64(fiat.u1(x40)), x55, u64(fiat.u1(x63)))
_, x66 := bits.mul_u64(x56, 0xd2b51da312547e1b)
x69, x68 := bits.mul_u64(x66, 0x1000000000000000)
x71, x70 := bits.mul_u64(x66, 0x14def9dea2f79cd6)
x73, x72 := bits.mul_u64(x66, 0x5812631a5cf5d3ed)
x74, x75 := bits.add_u64(x73, x70, u64(0x0))
x76 := (u64(fiat.u1(x75)) + x71)
_, x78 := bits.add_u64(x56, x72, u64(0x0))
x79, x80 := bits.add_u64(x58, x74, u64(fiat.u1(x78)))
x81, x82 := bits.add_u64(x60, x76, u64(fiat.u1(x80)))
x83, x84 := bits.add_u64(x62, x68, u64(fiat.u1(x82)))
x85, x86 := bits.add_u64(x64, x69, u64(fiat.u1(x84)))
x87 := (u64(fiat.u1(x86)) + u64(fiat.u1(x65)))
x89, x88 := bits.mul_u64(x2, arg2[3])
x91, x90 := bits.mul_u64(x2, arg2[2])
x93, x92 := bits.mul_u64(x2, arg2[1])
x95, x94 := bits.mul_u64(x2, arg2[0])
x96, x97 := bits.add_u64(x95, x92, u64(0x0))
x98, x99 := bits.add_u64(x93, x90, u64(fiat.u1(x97)))
x100, x101 := bits.add_u64(x91, x88, u64(fiat.u1(x99)))
x102 := (u64(fiat.u1(x101)) + x89)
x103, x104 := bits.add_u64(x79, x94, u64(0x0))
x105, x106 := bits.add_u64(x81, x96, u64(fiat.u1(x104)))
x107, x108 := bits.add_u64(x83, x98, u64(fiat.u1(x106)))
x109, x110 := bits.add_u64(x85, x100, u64(fiat.u1(x108)))
x111, x112 := bits.add_u64(x87, x102, u64(fiat.u1(x110)))
_, x113 := bits.mul_u64(x103, 0xd2b51da312547e1b)
x116, x115 := bits.mul_u64(x113, 0x1000000000000000)
x118, x117 := bits.mul_u64(x113, 0x14def9dea2f79cd6)
x120, x119 := bits.mul_u64(x113, 0x5812631a5cf5d3ed)
x121, x122 := bits.add_u64(x120, x117, u64(0x0))
x123 := (u64(fiat.u1(x122)) + x118)
_, x125 := bits.add_u64(x103, x119, u64(0x0))
x126, x127 := bits.add_u64(x105, x121, u64(fiat.u1(x125)))
x128, x129 := bits.add_u64(x107, x123, u64(fiat.u1(x127)))
x130, x131 := bits.add_u64(x109, x115, u64(fiat.u1(x129)))
x132, x133 := bits.add_u64(x111, x116, u64(fiat.u1(x131)))
x134 := (u64(fiat.u1(x133)) + u64(fiat.u1(x112)))
x136, x135 := bits.mul_u64(x3, arg2[3])
x138, x137 := bits.mul_u64(x3, arg2[2])
x140, x139 := bits.mul_u64(x3, arg2[1])
x142, x141 := bits.mul_u64(x3, arg2[0])
x143, x144 := bits.add_u64(x142, x139, u64(0x0))
x145, x146 := bits.add_u64(x140, x137, u64(fiat.u1(x144)))
x147, x148 := bits.add_u64(x138, x135, u64(fiat.u1(x146)))
x149 := (u64(fiat.u1(x148)) + x136)
x150, x151 := bits.add_u64(x126, x141, u64(0x0))
x152, x153 := bits.add_u64(x128, x143, u64(fiat.u1(x151)))
x154, x155 := bits.add_u64(x130, x145, u64(fiat.u1(x153)))
x156, x157 := bits.add_u64(x132, x147, u64(fiat.u1(x155)))
x158, x159 := bits.add_u64(x134, x149, u64(fiat.u1(x157)))
_, x160 := bits.mul_u64(x150, 0xd2b51da312547e1b)
x163, x162 := bits.mul_u64(x160, 0x1000000000000000)
x165, x164 := bits.mul_u64(x160, 0x14def9dea2f79cd6)
x167, x166 := bits.mul_u64(x160, 0x5812631a5cf5d3ed)
x168, x169 := bits.add_u64(x167, x164, u64(0x0))
x170 := (u64(fiat.u1(x169)) + x165)
_, x172 := bits.add_u64(x150, x166, u64(0x0))
x173, x174 := bits.add_u64(x152, x168, u64(fiat.u1(x172)))
x175, x176 := bits.add_u64(x154, x170, u64(fiat.u1(x174)))
x177, x178 := bits.add_u64(x156, x162, u64(fiat.u1(x176)))
x179, x180 := bits.add_u64(x158, x163, u64(fiat.u1(x178)))
x181 := (u64(fiat.u1(x180)) + u64(fiat.u1(x159)))
x182, x183 := bits.sub_u64(x173, 0x5812631a5cf5d3ed, u64(0x0))
x184, x185 := bits.sub_u64(x175, 0x14def9dea2f79cd6, u64(fiat.u1(x183)))
x186, x187 := bits.sub_u64(x177, u64(0x0), u64(fiat.u1(x185)))
x188, x189 := bits.sub_u64(x179, 0x1000000000000000, u64(fiat.u1(x187)))
_, x191 := bits.sub_u64(x181, u64(0x0), u64(fiat.u1(x189)))
x192 := fiat.cmovznz_u64(fiat.u1(x191), x182, x173)
x193 := fiat.cmovznz_u64(fiat.u1(x191), x184, x175)
x194 := fiat.cmovznz_u64(fiat.u1(x191), x186, x177)
x195 := fiat.cmovznz_u64(fiat.u1(x191), x188, x179)
out1[0] = x192
out1[1] = x193
out1[2] = x194
out1[3] = x195
}
fe_square :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element) {
x1 := arg1[1]
x2 := arg1[2]
x3 := arg1[3]
x4 := arg1[0]
x6, x5 := bits.mul_u64(x4, arg1[3])
x8, x7 := bits.mul_u64(x4, arg1[2])
x10, x9 := bits.mul_u64(x4, arg1[1])
x12, x11 := bits.mul_u64(x4, arg1[0])
x13, x14 := bits.add_u64(x12, x9, u64(0x0))
x15, x16 := bits.add_u64(x10, x7, u64(fiat.u1(x14)))
x17, x18 := bits.add_u64(x8, x5, u64(fiat.u1(x16)))
x19 := (u64(fiat.u1(x18)) + x6)
_, x20 := bits.mul_u64(x11, 0xd2b51da312547e1b)
x23, x22 := bits.mul_u64(x20, 0x1000000000000000)
x25, x24 := bits.mul_u64(x20, 0x14def9dea2f79cd6)
x27, x26 := bits.mul_u64(x20, 0x5812631a5cf5d3ed)
x28, x29 := bits.add_u64(x27, x24, u64(0x0))
x30 := (u64(fiat.u1(x29)) + x25)
_, x32 := bits.add_u64(x11, x26, u64(0x0))
x33, x34 := bits.add_u64(x13, x28, u64(fiat.u1(x32)))
x35, x36 := bits.add_u64(x15, x30, u64(fiat.u1(x34)))
x37, x38 := bits.add_u64(x17, x22, u64(fiat.u1(x36)))
x39, x40 := bits.add_u64(x19, x23, u64(fiat.u1(x38)))
x42, x41 := bits.mul_u64(x1, arg1[3])
x44, x43 := bits.mul_u64(x1, arg1[2])
x46, x45 := bits.mul_u64(x1, arg1[1])
x48, x47 := bits.mul_u64(x1, arg1[0])
x49, x50 := bits.add_u64(x48, x45, u64(0x0))
x51, x52 := bits.add_u64(x46, x43, u64(fiat.u1(x50)))
x53, x54 := bits.add_u64(x44, x41, u64(fiat.u1(x52)))
x55 := (u64(fiat.u1(x54)) + x42)
x56, x57 := bits.add_u64(x33, x47, u64(0x0))
x58, x59 := bits.add_u64(x35, x49, u64(fiat.u1(x57)))
x60, x61 := bits.add_u64(x37, x51, u64(fiat.u1(x59)))
x62, x63 := bits.add_u64(x39, x53, u64(fiat.u1(x61)))
x64, x65 := bits.add_u64(u64(fiat.u1(x40)), x55, u64(fiat.u1(x63)))
_, x66 := bits.mul_u64(x56, 0xd2b51da312547e1b)
x69, x68 := bits.mul_u64(x66, 0x1000000000000000)
x71, x70 := bits.mul_u64(x66, 0x14def9dea2f79cd6)
x73, x72 := bits.mul_u64(x66, 0x5812631a5cf5d3ed)
x74, x75 := bits.add_u64(x73, x70, u64(0x0))
x76 := (u64(fiat.u1(x75)) + x71)
_, x78 := bits.add_u64(x56, x72, u64(0x0))
x79, x80 := bits.add_u64(x58, x74, u64(fiat.u1(x78)))
x81, x82 := bits.add_u64(x60, x76, u64(fiat.u1(x80)))
x83, x84 := bits.add_u64(x62, x68, u64(fiat.u1(x82)))
x85, x86 := bits.add_u64(x64, x69, u64(fiat.u1(x84)))
x87 := (u64(fiat.u1(x86)) + u64(fiat.u1(x65)))
x89, x88 := bits.mul_u64(x2, arg1[3])
x91, x90 := bits.mul_u64(x2, arg1[2])
x93, x92 := bits.mul_u64(x2, arg1[1])
x95, x94 := bits.mul_u64(x2, arg1[0])
x96, x97 := bits.add_u64(x95, x92, u64(0x0))
x98, x99 := bits.add_u64(x93, x90, u64(fiat.u1(x97)))
x100, x101 := bits.add_u64(x91, x88, u64(fiat.u1(x99)))
x102 := (u64(fiat.u1(x101)) + x89)
x103, x104 := bits.add_u64(x79, x94, u64(0x0))
x105, x106 := bits.add_u64(x81, x96, u64(fiat.u1(x104)))
x107, x108 := bits.add_u64(x83, x98, u64(fiat.u1(x106)))
x109, x110 := bits.add_u64(x85, x100, u64(fiat.u1(x108)))
x111, x112 := bits.add_u64(x87, x102, u64(fiat.u1(x110)))
_, x113 := bits.mul_u64(x103, 0xd2b51da312547e1b)
x116, x115 := bits.mul_u64(x113, 0x1000000000000000)
x118, x117 := bits.mul_u64(x113, 0x14def9dea2f79cd6)
x120, x119 := bits.mul_u64(x113, 0x5812631a5cf5d3ed)
x121, x122 := bits.add_u64(x120, x117, u64(0x0))
x123 := (u64(fiat.u1(x122)) + x118)
_, x125 := bits.add_u64(x103, x119, u64(0x0))
x126, x127 := bits.add_u64(x105, x121, u64(fiat.u1(x125)))
x128, x129 := bits.add_u64(x107, x123, u64(fiat.u1(x127)))
x130, x131 := bits.add_u64(x109, x115, u64(fiat.u1(x129)))
x132, x133 := bits.add_u64(x111, x116, u64(fiat.u1(x131)))
x134 := (u64(fiat.u1(x133)) + u64(fiat.u1(x112)))
x136, x135 := bits.mul_u64(x3, arg1[3])
x138, x137 := bits.mul_u64(x3, arg1[2])
x140, x139 := bits.mul_u64(x3, arg1[1])
x142, x141 := bits.mul_u64(x3, arg1[0])
x143, x144 := bits.add_u64(x142, x139, u64(0x0))
x145, x146 := bits.add_u64(x140, x137, u64(fiat.u1(x144)))
x147, x148 := bits.add_u64(x138, x135, u64(fiat.u1(x146)))
x149 := (u64(fiat.u1(x148)) + x136)
x150, x151 := bits.add_u64(x126, x141, u64(0x0))
x152, x153 := bits.add_u64(x128, x143, u64(fiat.u1(x151)))
x154, x155 := bits.add_u64(x130, x145, u64(fiat.u1(x153)))
x156, x157 := bits.add_u64(x132, x147, u64(fiat.u1(x155)))
x158, x159 := bits.add_u64(x134, x149, u64(fiat.u1(x157)))
_, x160 := bits.mul_u64(x150, 0xd2b51da312547e1b)
x163, x162 := bits.mul_u64(x160, 0x1000000000000000)
x165, x164 := bits.mul_u64(x160, 0x14def9dea2f79cd6)
x167, x166 := bits.mul_u64(x160, 0x5812631a5cf5d3ed)
x168, x169 := bits.add_u64(x167, x164, u64(0x0))
x170 := (u64(fiat.u1(x169)) + x165)
_, x172 := bits.add_u64(x150, x166, u64(0x0))
x173, x174 := bits.add_u64(x152, x168, u64(fiat.u1(x172)))
x175, x176 := bits.add_u64(x154, x170, u64(fiat.u1(x174)))
x177, x178 := bits.add_u64(x156, x162, u64(fiat.u1(x176)))
x179, x180 := bits.add_u64(x158, x163, u64(fiat.u1(x178)))
x181 := (u64(fiat.u1(x180)) + u64(fiat.u1(x159)))
x182, x183 := bits.sub_u64(x173, 0x5812631a5cf5d3ed, u64(0x0))
x184, x185 := bits.sub_u64(x175, 0x14def9dea2f79cd6, u64(fiat.u1(x183)))
x186, x187 := bits.sub_u64(x177, u64(0x0), u64(fiat.u1(x185)))
x188, x189 := bits.sub_u64(x179, 0x1000000000000000, u64(fiat.u1(x187)))
_, x191 := bits.sub_u64(x181, u64(0x0), u64(fiat.u1(x189)))
x192 := fiat.cmovznz_u64(fiat.u1(x191), x182, x173)
x193 := fiat.cmovznz_u64(fiat.u1(x191), x184, x175)
x194 := fiat.cmovznz_u64(fiat.u1(x191), x186, x177)
x195 := fiat.cmovznz_u64(fiat.u1(x191), x188, x179)
out1[0] = x192
out1[1] = x193
out1[2] = x194
out1[3] = x195
}
fe_add :: proc "contextless" (out1, arg1, arg2: ^Montgomery_Domain_Field_Element) {
x1, x2 := bits.add_u64(arg1[0], arg2[0], u64(0x0))
x3, x4 := bits.add_u64(arg1[1], arg2[1], u64(fiat.u1(x2)))
x5, x6 := bits.add_u64(arg1[2], arg2[2], u64(fiat.u1(x4)))
x7, x8 := bits.add_u64(arg1[3], arg2[3], u64(fiat.u1(x6)))
x9, x10 := bits.sub_u64(x1, 0x5812631a5cf5d3ed, u64(0x0))
x11, x12 := bits.sub_u64(x3, 0x14def9dea2f79cd6, u64(fiat.u1(x10)))
x13, x14 := bits.sub_u64(x5, u64(0x0), u64(fiat.u1(x12)))
x15, x16 := bits.sub_u64(x7, 0x1000000000000000, u64(fiat.u1(x14)))
_, x18 := bits.sub_u64(u64(fiat.u1(x8)), u64(0x0), u64(fiat.u1(x16)))
x19 := fiat.cmovznz_u64(fiat.u1(x18), x9, x1)
x20 := fiat.cmovznz_u64(fiat.u1(x18), x11, x3)
x21 := fiat.cmovznz_u64(fiat.u1(x18), x13, x5)
x22 := fiat.cmovznz_u64(fiat.u1(x18), x15, x7)
out1[0] = x19
out1[1] = x20
out1[2] = x21
out1[3] = x22
}
fe_sub :: proc "contextless" (out1, arg1, arg2: ^Montgomery_Domain_Field_Element) {
x1, x2 := bits.sub_u64(arg1[0], arg2[0], u64(0x0))
x3, x4 := bits.sub_u64(arg1[1], arg2[1], u64(fiat.u1(x2)))
x5, x6 := bits.sub_u64(arg1[2], arg2[2], u64(fiat.u1(x4)))
x7, x8 := bits.sub_u64(arg1[3], arg2[3], u64(fiat.u1(x6)))
x9 := fiat.cmovznz_u64(fiat.u1(x8), u64(0x0), 0xffffffffffffffff)
x10, x11 := bits.add_u64(x1, (x9 & 0x5812631a5cf5d3ed), u64(0x0))
x12, x13 := bits.add_u64(x3, (x9 & 0x14def9dea2f79cd6), u64(fiat.u1(x11)))
x14, x15 := bits.add_u64(x5, u64(0x0), u64(fiat.u1(x13)))
x16, _ := bits.add_u64(x7, (x9 & 0x1000000000000000), u64(fiat.u1(x15)))
out1[0] = x10
out1[1] = x12
out1[2] = x14
out1[3] = x16
}
fe_opp :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element) {
x1, x2 := bits.sub_u64(u64(0x0), arg1[0], u64(0x0))
x3, x4 := bits.sub_u64(u64(0x0), arg1[1], u64(fiat.u1(x2)))
x5, x6 := bits.sub_u64(u64(0x0), arg1[2], u64(fiat.u1(x4)))
x7, x8 := bits.sub_u64(u64(0x0), arg1[3], u64(fiat.u1(x6)))
x9 := fiat.cmovznz_u64(fiat.u1(x8), u64(0x0), 0xffffffffffffffff)
x10, x11 := bits.add_u64(x1, (x9 & 0x5812631a5cf5d3ed), u64(0x0))
x12, x13 := bits.add_u64(x3, (x9 & 0x14def9dea2f79cd6), u64(fiat.u1(x11)))
x14, x15 := bits.add_u64(x5, u64(0x0), u64(fiat.u1(x13)))
x16, _ := bits.add_u64(x7, (x9 & 0x1000000000000000), u64(fiat.u1(x15)))
out1[0] = x10
out1[1] = x12
out1[2] = x14
out1[3] = x16
}
fe_one :: proc "contextless" (out1: ^Montgomery_Domain_Field_Element) {
out1[0] = 0xd6ec31748d98951d
out1[1] = 0xc6ef5bf4737dcf70
out1[2] = 0xfffffffffffffffe
out1[3] = 0xfffffffffffffff
}
fe_non_zero :: proc "contextless" (arg1: ^Montgomery_Domain_Field_Element) -> u64 {
return arg1[0] | (arg1[1] | (arg1[2] | arg1[3]))
}
@(optimization_mode = "none")
fe_cond_assign :: #force_no_inline proc "contextless" (
out1, arg1: ^Montgomery_Domain_Field_Element,
arg2: int,
) {
x1 := fiat.cmovznz_u64(fiat.u1(arg2), out1[0], arg1[0])
x2 := fiat.cmovznz_u64(fiat.u1(arg2), out1[1], arg1[1])
x3 := fiat.cmovznz_u64(fiat.u1(arg2), out1[2], arg1[2])
x4 := fiat.cmovznz_u64(fiat.u1(arg2), out1[3], arg1[3])
out1[0] = x1
out1[1] = x2
out1[2] = x3
out1[3] = x4
}
fe_from_montgomery :: proc "contextless" (
out1: ^Non_Montgomery_Domain_Field_Element,
arg1: ^Montgomery_Domain_Field_Element,
) {
x1 := arg1[0]
_, x2 := bits.mul_u64(x1, 0xd2b51da312547e1b)
x5, x4 := bits.mul_u64(x2, 0x1000000000000000)
x7, x6 := bits.mul_u64(x2, 0x14def9dea2f79cd6)
x9, x8 := bits.mul_u64(x2, 0x5812631a5cf5d3ed)
x10, x11 := bits.add_u64(x9, x6, u64(0x0))
_, x13 := bits.add_u64(x1, x8, u64(0x0))
x14, x15 := bits.add_u64(u64(0x0), x10, u64(fiat.u1(x13)))
x16, x17 := bits.add_u64(x14, arg1[1], u64(0x0))
_, x18 := bits.mul_u64(x16, 0xd2b51da312547e1b)
x21, x20 := bits.mul_u64(x18, 0x1000000000000000)
x23, x22 := bits.mul_u64(x18, 0x14def9dea2f79cd6)
x25, x24 := bits.mul_u64(x18, 0x5812631a5cf5d3ed)
x26, x27 := bits.add_u64(x25, x22, u64(0x0))
_, x29 := bits.add_u64(x16, x24, u64(0x0))
x30, x31 := bits.add_u64(
(u64(fiat.u1(x17)) + (u64(fiat.u1(x15)) + (u64(fiat.u1(x11)) + x7))),
x26,
u64(fiat.u1(x29)),
)
x32, x33 := bits.add_u64(x4, (u64(fiat.u1(x27)) + x23), u64(fiat.u1(x31)))
x34, x35 := bits.add_u64(x5, x20, u64(fiat.u1(x33)))
x36, x37 := bits.add_u64(x30, arg1[2], u64(0x0))
x38, x39 := bits.add_u64(x32, u64(0x0), u64(fiat.u1(x37)))
x40, x41 := bits.add_u64(x34, u64(0x0), u64(fiat.u1(x39)))
_, x42 := bits.mul_u64(x36, 0xd2b51da312547e1b)
x45, x44 := bits.mul_u64(x42, 0x1000000000000000)
x47, x46 := bits.mul_u64(x42, 0x14def9dea2f79cd6)
x49, x48 := bits.mul_u64(x42, 0x5812631a5cf5d3ed)
x50, x51 := bits.add_u64(x49, x46, u64(0x0))
_, x53 := bits.add_u64(x36, x48, u64(0x0))
x54, x55 := bits.add_u64(x38, x50, u64(fiat.u1(x53)))
x56, x57 := bits.add_u64(x40, (u64(fiat.u1(x51)) + x47), u64(fiat.u1(x55)))
x58, x59 := bits.add_u64(
(u64(fiat.u1(x41)) + (u64(fiat.u1(x35)) + x21)),
x44,
u64(fiat.u1(x57)),
)
x60, x61 := bits.add_u64(x54, arg1[3], u64(0x0))
x62, x63 := bits.add_u64(x56, u64(0x0), u64(fiat.u1(x61)))
x64, x65 := bits.add_u64(x58, u64(0x0), u64(fiat.u1(x63)))
_, x66 := bits.mul_u64(x60, 0xd2b51da312547e1b)
x69, x68 := bits.mul_u64(x66, 0x1000000000000000)
x71, x70 := bits.mul_u64(x66, 0x14def9dea2f79cd6)
x73, x72 := bits.mul_u64(x66, 0x5812631a5cf5d3ed)
x74, x75 := bits.add_u64(x73, x70, u64(0x0))
_, x77 := bits.add_u64(x60, x72, u64(0x0))
x78, x79 := bits.add_u64(x62, x74, u64(fiat.u1(x77)))
x80, x81 := bits.add_u64(x64, (u64(fiat.u1(x75)) + x71), u64(fiat.u1(x79)))
x82, x83 := bits.add_u64(
(u64(fiat.u1(x65)) + (u64(fiat.u1(x59)) + x45)),
x68,
u64(fiat.u1(x81)),
)
x84 := (u64(fiat.u1(x83)) + x69)
x85, x86 := bits.sub_u64(x78, 0x5812631a5cf5d3ed, u64(0x0))
x87, x88 := bits.sub_u64(x80, 0x14def9dea2f79cd6, u64(fiat.u1(x86)))
x89, x90 := bits.sub_u64(x82, u64(0x0), u64(fiat.u1(x88)))
x91, x92 := bits.sub_u64(x84, 0x1000000000000000, u64(fiat.u1(x90)))
_, x94 := bits.sub_u64(u64(0x0), u64(0x0), u64(fiat.u1(x92)))
x95 := fiat.cmovznz_u64(fiat.u1(x94), x85, x78)
x96 := fiat.cmovznz_u64(fiat.u1(x94), x87, x80)
x97 := fiat.cmovznz_u64(fiat.u1(x94), x89, x82)
x98 := fiat.cmovznz_u64(fiat.u1(x94), x91, x84)
out1[0] = x95
out1[1] = x96
out1[2] = x97
out1[3] = x98
}
fe_to_montgomery :: proc "contextless" (
out1: ^Montgomery_Domain_Field_Element,
arg1: ^Non_Montgomery_Domain_Field_Element,
) {
x1 := arg1[1]
x2 := arg1[2]
x3 := arg1[3]
x4 := arg1[0]
x6, x5 := bits.mul_u64(x4, 0x399411b7c309a3d)
x8, x7 := bits.mul_u64(x4, 0xceec73d217f5be65)
x10, x9 := bits.mul_u64(x4, 0xd00e1ba768859347)
x12, x11 := bits.mul_u64(x4, 0xa40611e3449c0f01)
x13, x14 := bits.add_u64(x12, x9, u64(0x0))
x15, x16 := bits.add_u64(x10, x7, u64(fiat.u1(x14)))
x17, x18 := bits.add_u64(x8, x5, u64(fiat.u1(x16)))
_, x19 := bits.mul_u64(x11, 0xd2b51da312547e1b)
x22, x21 := bits.mul_u64(x19, 0x1000000000000000)
x24, x23 := bits.mul_u64(x19, 0x14def9dea2f79cd6)
x26, x25 := bits.mul_u64(x19, 0x5812631a5cf5d3ed)
x27, x28 := bits.add_u64(x26, x23, u64(0x0))
_, x30 := bits.add_u64(x11, x25, u64(0x0))
x31, x32 := bits.add_u64(x13, x27, u64(fiat.u1(x30)))
x33, x34 := bits.add_u64(x15, (u64(fiat.u1(x28)) + x24), u64(fiat.u1(x32)))
x35, x36 := bits.add_u64(x17, x21, u64(fiat.u1(x34)))
x38, x37 := bits.mul_u64(x1, 0x399411b7c309a3d)
x40, x39 := bits.mul_u64(x1, 0xceec73d217f5be65)
x42, x41 := bits.mul_u64(x1, 0xd00e1ba768859347)
x44, x43 := bits.mul_u64(x1, 0xa40611e3449c0f01)
x45, x46 := bits.add_u64(x44, x41, u64(0x0))
x47, x48 := bits.add_u64(x42, x39, u64(fiat.u1(x46)))
x49, x50 := bits.add_u64(x40, x37, u64(fiat.u1(x48)))
x51, x52 := bits.add_u64(x31, x43, u64(0x0))
x53, x54 := bits.add_u64(x33, x45, u64(fiat.u1(x52)))
x55, x56 := bits.add_u64(x35, x47, u64(fiat.u1(x54)))
x57, x58 := bits.add_u64(
((u64(fiat.u1(x36)) + (u64(fiat.u1(x18)) + x6)) + x22),
x49,
u64(fiat.u1(x56)),
)
_, x59 := bits.mul_u64(x51, 0xd2b51da312547e1b)
x62, x61 := bits.mul_u64(x59, 0x1000000000000000)
x64, x63 := bits.mul_u64(x59, 0x14def9dea2f79cd6)
x66, x65 := bits.mul_u64(x59, 0x5812631a5cf5d3ed)
x67, x68 := bits.add_u64(x66, x63, u64(0x0))
_, x70 := bits.add_u64(x51, x65, u64(0x0))
x71, x72 := bits.add_u64(x53, x67, u64(fiat.u1(x70)))
x73, x74 := bits.add_u64(x55, (u64(fiat.u1(x68)) + x64), u64(fiat.u1(x72)))
x75, x76 := bits.add_u64(x57, x61, u64(fiat.u1(x74)))
x78, x77 := bits.mul_u64(x2, 0x399411b7c309a3d)
x80, x79 := bits.mul_u64(x2, 0xceec73d217f5be65)
x82, x81 := bits.mul_u64(x2, 0xd00e1ba768859347)
x84, x83 := bits.mul_u64(x2, 0xa40611e3449c0f01)
x85, x86 := bits.add_u64(x84, x81, u64(0x0))
x87, x88 := bits.add_u64(x82, x79, u64(fiat.u1(x86)))
x89, x90 := bits.add_u64(x80, x77, u64(fiat.u1(x88)))
x91, x92 := bits.add_u64(x71, x83, u64(0x0))
x93, x94 := bits.add_u64(x73, x85, u64(fiat.u1(x92)))
x95, x96 := bits.add_u64(x75, x87, u64(fiat.u1(x94)))
x97, x98 := bits.add_u64(
((u64(fiat.u1(x76)) + (u64(fiat.u1(x58)) + (u64(fiat.u1(x50)) + x38))) + x62),
x89,
u64(fiat.u1(x96)),
)
_, x99 := bits.mul_u64(x91, 0xd2b51da312547e1b)
x102, x101 := bits.mul_u64(x99, 0x1000000000000000)
x104, x103 := bits.mul_u64(x99, 0x14def9dea2f79cd6)
x106, x105 := bits.mul_u64(x99, 0x5812631a5cf5d3ed)
x107, x108 := bits.add_u64(x106, x103, u64(0x0))
_, x110 := bits.add_u64(x91, x105, u64(0x0))
x111, x112 := bits.add_u64(x93, x107, u64(fiat.u1(x110)))
x113, x114 := bits.add_u64(x95, (u64(fiat.u1(x108)) + x104), u64(fiat.u1(x112)))
x115, x116 := bits.add_u64(x97, x101, u64(fiat.u1(x114)))
x118, x117 := bits.mul_u64(x3, 0x399411b7c309a3d)
x120, x119 := bits.mul_u64(x3, 0xceec73d217f5be65)
x122, x121 := bits.mul_u64(x3, 0xd00e1ba768859347)
x124, x123 := bits.mul_u64(x3, 0xa40611e3449c0f01)
x125, x126 := bits.add_u64(x124, x121, u64(0x0))
x127, x128 := bits.add_u64(x122, x119, u64(fiat.u1(x126)))
x129, x130 := bits.add_u64(x120, x117, u64(fiat.u1(x128)))
x131, x132 := bits.add_u64(x111, x123, u64(0x0))
x133, x134 := bits.add_u64(x113, x125, u64(fiat.u1(x132)))
x135, x136 := bits.add_u64(x115, x127, u64(fiat.u1(x134)))
x137, x138 := bits.add_u64(
((u64(fiat.u1(x116)) + (u64(fiat.u1(x98)) + (u64(fiat.u1(x90)) + x78))) + x102),
x129,
u64(fiat.u1(x136)),
)
_, x139 := bits.mul_u64(x131, 0xd2b51da312547e1b)
x142, x141 := bits.mul_u64(x139, 0x1000000000000000)
x144, x143 := bits.mul_u64(x139, 0x14def9dea2f79cd6)
x146, x145 := bits.mul_u64(x139, 0x5812631a5cf5d3ed)
x147, x148 := bits.add_u64(x146, x143, u64(0x0))
_, x150 := bits.add_u64(x131, x145, u64(0x0))
x151, x152 := bits.add_u64(x133, x147, u64(fiat.u1(x150)))
x153, x154 := bits.add_u64(x135, (u64(fiat.u1(x148)) + x144), u64(fiat.u1(x152)))
x155, x156 := bits.add_u64(x137, x141, u64(fiat.u1(x154)))
x157 := ((u64(fiat.u1(x156)) + (u64(fiat.u1(x138)) + (u64(fiat.u1(x130)) + x118))) + x142)
x158, x159 := bits.sub_u64(x151, 0x5812631a5cf5d3ed, u64(0x0))
x160, x161 := bits.sub_u64(x153, 0x14def9dea2f79cd6, u64(fiat.u1(x159)))
x162, x163 := bits.sub_u64(x155, u64(0x0), u64(fiat.u1(x161)))
x164, x165 := bits.sub_u64(x157, 0x1000000000000000, u64(fiat.u1(x163)))
_, x167 := bits.sub_u64(u64(0x0), u64(0x0), u64(fiat.u1(x165)))
x168 := fiat.cmovznz_u64(fiat.u1(x167), x158, x151)
x169 := fiat.cmovznz_u64(fiat.u1(x167), x160, x153)
x170 := fiat.cmovznz_u64(fiat.u1(x167), x162, x155)
x171 := fiat.cmovznz_u64(fiat.u1(x167), x164, x157)
out1[0] = x168
out1[1] = x169
out1[2] = x170
out1[3] = x171
}
+109 -78
View File
@@ -7,50 +7,69 @@ package _sha3
List of contributors:
zhibog, dotbmp: Initial implementation.
Implementation of the Keccak hashing algorithm, standardized as SHA3 in <https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf>
To use the original Keccak padding, set the is_keccak bool to true, otherwise it will use SHA3 padding.
Implementation of the Keccak hashing algorithm, standardized as SHA3
in <https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf>.
As the only difference between the legacy Keccak and SHA3 is the domain
separation byte, set dsbyte to the appropriate value to pick the desired
algorithm.
*/
import "core:math/bits"
import "core:mem"
ROUNDS :: 24
Sha3_Context :: struct {
st: struct #raw_union {
RATE_128 :: 1344 / 8 // ONLY for SHAKE128.
RATE_224 :: 1152 / 8
RATE_256 :: 1088 / 8
RATE_384 :: 832 / 8
RATE_512 :: 576 / 8
DS_KECCAK :: 0x01
DS_SHA3 :: 0x06
DS_SHAKE :: 0x1f
DS_CSHAKE :: 0x04
Context :: struct {
st: struct #raw_union {
b: [200]u8,
q: [25]u64,
},
pt: int,
rsiz: int,
mdlen: int,
is_keccak: bool,
pt: int,
rsiz: int,
mdlen: int,
dsbyte: byte,
is_initialized: bool,
is_finalized: bool, // For SHAKE (unlimited squeeze is allowed)
}
@(private)
keccakf_rndc := [?]u64 {
0x0000000000000001, 0x0000000000008082, 0x800000000000808a,
0x8000000080008000, 0x000000000000808b, 0x0000000080000001,
0x8000000080008081, 0x8000000000008009, 0x000000000000008a,
0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
0x000000008000808b, 0x800000000000008b, 0x8000000000008089,
0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
0x000000000000800a, 0x800000008000000a, 0x8000000080008081,
0x8000000000008080, 0x0000000080000001, 0x8000000080008008,
}
@(private)
keccakf_rotc := [?]int {
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14,
27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44,
}
@(private)
keccakf_piln := [?]i32 {
10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4,
15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1,
}
@(private)
keccakf :: proc "contextless" (st: ^[25]u64) {
keccakf_rndc := [?]u64 {
0x0000000000000001, 0x0000000000008082, 0x800000000000808a,
0x8000000080008000, 0x000000000000808b, 0x0000000080000001,
0x8000000080008081, 0x8000000000008009, 0x000000000000008a,
0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
0x000000008000808b, 0x800000000000008b, 0x8000000000008089,
0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
0x000000000000800a, 0x800000008000000a, 0x8000000080008081,
0x8000000000008080, 0x0000000080000001, 0x8000000080008008,
}
keccakf_rotc := [?]int {
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14,
27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44,
}
keccakf_piln := [?]i32 {
10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4,
15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1,
}
i, j, r: i32 = ---, ---, ---
t: u64 = ---
bc: [5]u64 = ---
@@ -103,81 +122,93 @@ keccakf :: proc "contextless" (st: ^[25]u64) {
}
}
init :: proc(c: ^Sha3_Context) {
init :: proc(ctx: ^Context) {
for i := 0; i < 25; i += 1 {
c.st.q[i] = 0
ctx.st.q[i] = 0
}
c.rsiz = 200 - 2 * c.mdlen
c.pt = 0
ctx.rsiz = 200 - 2 * ctx.mdlen
ctx.pt = 0
c.is_initialized = true
c.is_finalized = false
ctx.is_initialized = true
ctx.is_finalized = false
}
update :: proc(c: ^Sha3_Context, data: []byte) {
assert(c.is_initialized)
assert(!c.is_finalized)
update :: proc(ctx: ^Context, data: []byte) {
assert(ctx.is_initialized)
assert(!ctx.is_finalized)
j := c.pt
j := ctx.pt
for i := 0; i < len(data); i += 1 {
c.st.b[j] ~= data[i]
ctx.st.b[j] ~= data[i]
j += 1
if j >= c.rsiz {
keccakf(&c.st.q)
if j >= ctx.rsiz {
keccakf(&ctx.st.q)
j = 0
}
}
c.pt = j
ctx.pt = j
}
final :: proc(c: ^Sha3_Context, hash: []byte) {
assert(c.is_initialized)
final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) {
assert(ctx.is_initialized)
if len(hash) < c.mdlen {
if c.is_keccak {
panic("crypto/keccac: invalid destination digest size")
}
if len(hash) < ctx.mdlen {
panic("crypto/sha3: invalid destination digest size")
}
if c.is_keccak {
c.st.b[c.pt] ~= 0x01
} else {
c.st.b[c.pt] ~= 0x06
}
c.st.b[c.rsiz - 1] ~= 0x80
keccakf(&c.st.q)
for i := 0; i < c.mdlen; i += 1 {
hash[i] = c.st.b[i]
ctx := ctx
if finalize_clone {
tmp_ctx: Context
clone(&tmp_ctx, ctx)
ctx = &tmp_ctx
}
defer (reset(ctx))
c.is_initialized = false // No more absorb, no more squeeze.
ctx.st.b[ctx.pt] ~= ctx.dsbyte
ctx.st.b[ctx.rsiz - 1] ~= 0x80
keccakf(&ctx.st.q)
for i := 0; i < ctx.mdlen; i += 1 {
hash[i] = ctx.st.b[i]
}
}
shake_xof :: proc(c: ^Sha3_Context) {
assert(c.is_initialized)
assert(!c.is_finalized)
c.st.b[c.pt] ~= 0x1F
c.st.b[c.rsiz - 1] ~= 0x80
keccakf(&c.st.q)
c.pt = 0
c.is_finalized = true // No more absorb, unlimited squeeze.
clone :: proc(ctx, other: ^Context) {
ctx^ = other^
}
shake_out :: proc(c: ^Sha3_Context, hash: []byte) {
assert(c.is_initialized)
assert(c.is_finalized)
reset :: proc(ctx: ^Context) {
if !ctx.is_initialized {
return
}
j := c.pt
mem.zero_explicit(ctx, size_of(ctx^))
}
shake_xof :: proc(ctx: ^Context) {
assert(ctx.is_initialized)
assert(!ctx.is_finalized)
ctx.st.b[ctx.pt] ~= ctx.dsbyte
ctx.st.b[ctx.rsiz - 1] ~= 0x80
keccakf(&ctx.st.q)
ctx.pt = 0
ctx.is_finalized = true // No more absorb, unlimited squeeze.
}
shake_out :: proc(ctx: ^Context, hash: []byte) {
assert(ctx.is_initialized)
assert(ctx.is_finalized)
j := ctx.pt
for i := 0; i < len(hash); i += 1 {
if j >= c.rsiz {
keccakf(&c.st.q)
if j >= ctx.rsiz {
keccakf(&ctx.st.q)
j = 0
}
hash[i] = c.st.b[j]
hash[i] = ctx.st.b[j]
j += 1
}
c.pt = j
ctx.pt = j
}
+145
View File
@@ -0,0 +1,145 @@
package _sha3
import "core:encoding/endian"
import "core:math/bits"
init_cshake :: proc(ctx: ^Context, n, s: []byte, sec_strength: int) {
ctx.mdlen = sec_strength / 8
// No domain separator is equivalent to vanilla SHAKE.
if len(n) == 0 && len(s) == 0 {
ctx.dsbyte = DS_SHAKE
init(ctx)
return
}
ctx.dsbyte = DS_CSHAKE
init(ctx)
bytepad(ctx, [][]byte{n, s}, rate_cshake(sec_strength))
}
final_cshake :: proc(ctx: ^Context, dst: []byte, finalize_clone: bool = false) {
ctx := ctx
if finalize_clone {
tmp_ctx: Context
clone(&tmp_ctx, ctx)
ctx = &tmp_ctx
}
defer reset(ctx)
encode_byte_len(ctx, len(dst), false) // right_encode
shake_xof(ctx)
shake_out(ctx, dst)
}
rate_cshake :: #force_inline proc(sec_strength: int) -> int {
switch sec_strength {
case 128:
return RATE_128
case 256:
return RATE_256
}
panic("crypto/sha3: invalid security strength")
}
// right_encode and left_encode are defined to support 0 <= x < 2^2040
// however, the largest value we will ever need to encode is `max(int) * 8`.
//
// This is unfortunate as the extreme upper edge is larger than
// `max(u64)`. While such values are impractical at present,
// they are possible (ie: https://arxiv.org/pdf/quant-ph/9908043.pdf).
//
// Thus we support 0 <= x < 2^128.
@(private)
_PAD: [RATE_128]byte // Biggest possible value of w per spec.
bytepad :: proc(ctx: ^Context, x_strings: [][]byte, w: int) {
// 1. z = left_encode(w) || X.
z_hi: u64
z_lo := left_right_encode(ctx, 0, u64(w), true)
for x in x_strings {
// All uses of bytepad in SP 800-185 use the output from
// one or more encode_string values for `X`.
hi, lo := encode_string(ctx, x)
carry: u64
z_lo, carry = bits.add_u64(z_lo, lo, 0)
z_hi, carry = bits.add_u64(z_hi, hi, carry)
// This isn't actually possible, at least with the currently
// defined SP 800-185 routines.
if carry != 0 {
panic("crypto/sha3: bytepad input length overflow")
}
}
// We skip this step as we are doing a byte-oriented implementation
// rather than a bit oriented one.
//
// 2. while len(z) mod 8 0:
// z = z || 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]
// 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) {
l := encode_byte_len(ctx, len(s), true) // left_encode
update(ctx, s)
lo, hi := bits.add_u64(l, u64(len(s)), 0)
return hi, lo
}
encode_byte_len :: #force_inline proc(ctx: ^Context, l: int, is_left: bool) -> u64 {
hi, lo := bits.mul_u64(u64(l), 8)
return left_right_encode(ctx, hi, lo, is_left)
}
@(private)
left_right_encode :: proc(ctx: ^Context, hi, lo: u64, is_left: bool) -> u64 {
HI_OFFSET :: 1
LO_OFFSET :: HI_OFFSET + 8
RIGHT_OFFSET :: LO_OFFSET + 8
BUF_LEN :: RIGHT_OFFSET + 1
buf: [BUF_LEN]byte // prefix + largest uint + postfix
endian.unchecked_put_u64be(buf[HI_OFFSET:], hi)
endian.unchecked_put_u64be(buf[LO_OFFSET:], lo)
// 2. Strip leading `0x00` bytes.
off: int
for off = HI_OFFSET; off < RIGHT_OFFSET - 1; off = off + 1 {// Note: Minimum size is 1, not 0.
if buf[off] != 0 {
break
}
}
n := byte(RIGHT_OFFSET - off)
// 3. Prefix (left_encode) or postfix (right_encode) the length in bytes.
b: []byte
switch is_left {
case true:
buf[off - 1] = n // n | x
b = buf[off - 1:RIGHT_OFFSET]
case false:
buf[RIGHT_OFFSET] = n // x | n
b = buf[off:]
}
update(ctx, b)
return u64(len(b))
}
+22
View File
@@ -0,0 +1,22 @@
/*
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
*/
package aes
import "core:crypto/_aes"
// KEY_SIZE_128 is the AES-128 key size in bytes.
KEY_SIZE_128 :: _aes.KEY_SIZE_128
// KEY_SIZE_192 is the AES-192 key size in bytes.
KEY_SIZE_192 :: _aes.KEY_SIZE_192
// KEY_SIZE_256 is the AES-256 key size in bytes.
KEY_SIZE_256 :: _aes.KEY_SIZE_256
// BLOCK_SIZE is the AES block size in bytes.
BLOCK_SIZE :: _aes.BLOCK_SIZE
+199
View File
@@ -0,0 +1,199 @@
package aes
import "core:crypto/_aes/ct64"
import "core:encoding/endian"
import "core:math/bits"
import "core:mem"
// CTR_IV_SIZE is the size of the CTR mode IV in bytes.
CTR_IV_SIZE :: 16
// Context_CTR is a keyed AES-CTR instance.
Context_CTR :: struct {
_impl: Context_Impl,
_buffer: [BLOCK_SIZE]byte,
_off: int,
_ctr_hi: u64,
_ctr_lo: u64,
_is_initialized: bool,
}
// init_ctr initializes a Context_CTR with the provided key and IV.
init_ctr :: proc(ctx: ^Context_CTR, key, iv: []byte, impl := Implementation.Hardware) {
if len(iv) != CTR_IV_SIZE {
panic("crypto/aes: invalid CTR IV size")
}
init_impl(&ctx._impl, key, impl)
ctx._off = BLOCK_SIZE
ctx._ctr_hi = endian.unchecked_get_u64be(iv[0:])
ctx._ctr_lo = endian.unchecked_get_u64be(iv[8:])
ctx._is_initialized = true
}
// xor_bytes_ctr XORs each byte in src with bytes taken from the AES-CTR
// keystream, and writes the resulting output to dst. dst and src MUST
// alias exactly or not at all.
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; {
// 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
ctr_blocks(ctx, dst, src, nr_blocks)
remaining -= direct_bytes
if remaining == 0 {
return
}
dst = dst[direct_bytes:]
src = src[direct_bytes:]
}
// If there is a partial block, generate and buffer 1 block
// worth of keystream.
ctr_blocks(ctx, ctx._buffer[:], nil, 1)
ctx._off = 0
}
// Process partial blocks from the buffered keystream.
to_xor := min(BLOCK_SIZE - ctx._off, remaining)
buffered_keystream := ctx._buffer[ctx._off:]
for i := 0; i < to_xor; i = i + 1 {
dst[i] = buffered_keystream[i] ~ src[i]
}
ctx._off += to_xor
dst = dst[to_xor:]
src = src[to_xor:]
remaining -= to_xor
}
}
// keystream_bytes_ctr fills dst with the raw AES-CTR keystream output.
keystream_bytes_ctr :: proc(ctx: ^Context_CTR, dst: []byte) {
assert(ctx._is_initialized)
dst := dst
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
ctr_blocks(ctx, dst, nil, nr_blocks)
remaining -= direct_bytes
if remaining == 0 {
return
}
dst = dst[direct_bytes:]
}
// If there is a partial block, generate and buffer 1 block
// worth of keystream.
ctr_blocks(ctx, ctx._buffer[:], nil, 1)
ctx._off = 0
}
// Process partial blocks from the buffered keystream.
to_copy := min(BLOCK_SIZE - ctx._off, remaining)
buffered_keystream := ctx._buffer[ctx._off:]
copy(dst[:to_copy], buffered_keystream[:to_copy])
ctx._off += to_copy
dst = dst[to_copy:]
remaining -= to_copy
}
}
// reset_ctr sanitizes the Context_CTR. The Context_CTR must be
// re-initialized to be used again.
reset_ctr :: proc "contextless" (ctx: ^Context_CTR) {
reset_impl(&ctx._impl)
ctx._off = 0
ctx._ctr_hi = 0
ctx._ctr_lo = 0
mem.zero_explicit(&ctx._buffer, size_of(ctx._buffer))
ctx._is_initialized = false
}
@(private)
ctr_blocks :: proc(ctx: ^Context_CTR, dst, src: []byte, nr_blocks: int) {
// 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)
return
}
// Portable implementation.
ct64_inc_ctr := #force_inline proc "contextless" (dst: []byte, hi, lo: u64) -> (u64, u64) {
endian.unchecked_put_u64be(dst[0:], hi)
endian.unchecked_put_u64be(dst[8:], lo)
hi, lo := hi, lo
carry: u64
lo, carry = bits.add_u64(lo, 1, 0)
hi, _ = bits.add_u64(hi, 0, carry)
return hi, lo
}
impl := &ctx._impl.(ct64.Context)
src, dst := src, dst
nr_blocks := nr_blocks
ctr_hi, ctr_lo := ctx._ctr_hi, ctx._ctr_lo
tmp: [ct64.STRIDE][BLOCK_SIZE]byte = ---
ctrs: [ct64.STRIDE][]byte = ---
for i in 0 ..< ct64.STRIDE {
ctrs[i] = tmp[i][:]
}
for nr_blocks > 0 {
n := min(ct64.STRIDE, nr_blocks)
blocks := ctrs[:n]
for i in 0 ..< n {
ctr_hi, ctr_lo = ct64_inc_ctr(blocks[i], ctr_hi, ctr_lo)
}
ct64.encrypt_blocks(impl, blocks, blocks)
xor_blocks(dst, src, blocks)
if src != nil {
src = src[n * BLOCK_SIZE:]
}
dst = dst[n * BLOCK_SIZE:]
nr_blocks -= n
}
// Write back the counter.
ctx._ctr_hi, ctx._ctr_lo = ctr_hi, ctr_lo
mem.zero_explicit(&tmp, size_of(tmp))
}
@(private)
xor_blocks :: #force_inline proc "contextless" (dst, src: []byte, blocks: [][]byte) {
// Note: This would be faster `core:simd` was used, however if
// 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]
}
}
}
}
for i in 0 ..< len(blocks) {
copy(dst[i * BLOCK_SIZE:], blocks[i])
}
}
+57
View File
@@ -0,0 +1,57 @@
package aes
import "core:crypto/_aes/ct64"
// Context_ECB is a keyed AES-ECB instance.
//
// WARNING: Using ECB mode is strongly discouraged unless it is being
// used to implement higher level constructs.
Context_ECB :: struct {
_impl: Context_Impl,
_is_initialized: bool,
}
// init_ecb initializes a Context_ECB with the provided key.
init_ecb :: proc(ctx: ^Context_ECB, key: []byte, impl := Implementation.Hardware) {
init_impl(&ctx._impl, key, impl)
ctx._is_initialized = true
}
// encrypt_ecb encrypts the BLOCK_SIZE buffer src, and writes the result to dst.
encrypt_ecb :: proc(ctx: ^Context_ECB, dst, src: []byte) {
assert(ctx._is_initialized)
if len(dst) != BLOCK_SIZE || len(src) != BLOCK_SIZE {
panic("crypto/aes: invalid buffer size(s)")
}
switch &impl in ctx._impl {
case ct64.Context:
ct64.encrypt_block(&impl, dst, src)
case Context_Impl_Hardware:
encrypt_block_hw(&impl, dst, src)
}
}
// decrypt_ecb decrypts the BLOCK_SIZE buffer src, and writes the result to dst.
decrypt_ecb :: proc(ctx: ^Context_ECB, dst, src: []byte) {
assert(ctx._is_initialized)
if len(dst) != BLOCK_SIZE || len(src) != BLOCK_SIZE {
panic("crypto/aes: invalid buffer size(s)")
}
switch &impl in ctx._impl {
case ct64.Context:
ct64.decrypt_block(&impl, dst, src)
case Context_Impl_Hardware:
decrypt_block_hw(&impl, dst, src)
}
}
// reset_ecb sanitizes the Context_ECB. The Context_ECB must be
// re-initialized to be used again.
reset_ecb :: proc "contextless" (ctx: ^Context_ECB) {
reset_impl(&ctx._impl)
ctx._is_initialized = false
}
+253
View File
@@ -0,0 +1,253 @@
package aes
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_TAG_SIZE is the size of a GCM tag in bytes.
GCM_TAG_SIZE :: _aes.GHASH_TAG_SIZE
@(private)
GCM_A_MAX :: max(u64) / 8 // 2^64 - 1 bits -> bytes
@(private)
GCM_P_MAX :: 0xfffffffe0 // 2^39 - 256 bits -> bytes
// Context_GCM is a keyed AES-GCM instance.
Context_GCM :: struct {
_impl: Context_Impl,
_is_initialized: bool,
}
// init_gcm initializes a Context_GCM with the provided key.
init_gcm :: proc(ctx: ^Context_GCM, key: []byte, impl := Implementation.Hardware) {
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.
//
// dst and plaintext MUST alias exactly or not at all.
seal_gcm :: proc(ctx: ^Context_GCM, dst, tag, nonce, aad, plaintext: []byte) {
assert(ctx._is_initialized)
gcm_validate_common_slice_sizes(tag, nonce, aad, plaintext)
if len(dst) != len(plaintext) {
panic("crypto/aes: invalid destination ciphertext size")
}
if impl, is_hw := ctx._impl.(Context_Impl_Hardware); is_hw {
gcm_seal_hw(&impl, dst, tag, nonce, aad, plaintext)
return
}
h: [_aes.GHASH_KEY_SIZE]byte
j0: [_aes.GHASH_BLOCK_SIZE]byte
s: [_aes.GHASH_TAG_SIZE]byte
init_ghash_ct64(ctx, &h, &j0, nonce)
// 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))
copy(tag, s[:])
mem.zero_explicit(&h, len(h))
mem.zero_explicit(&j0, len(j0))
}
// 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,
// 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 {
assert(ctx._is_initialized)
gcm_validate_common_slice_sizes(tag, nonce, aad, ciphertext)
if len(dst) != len(ciphertext) {
panic("crypto/aes: invalid destination plaintext size")
}
if impl, is_hw := ctx._impl.(Context_Impl_Hardware); is_hw {
return gcm_open_hw(&impl, dst, nonce, aad, ciphertext, tag)
}
h: [_aes.GHASH_KEY_SIZE]byte
j0: [_aes.GHASH_BLOCK_SIZE]byte
s: [_aes.GHASH_TAG_SIZE]byte
init_ghash_ct64(ctx, &h, &j0, nonce)
ct64.ghash(s[:], h[:], aad)
gctr_ct64(ctx, dst, &s, ciphertext, &h, nonce, false)
final_ghash_ct64(&s, &h, &j0, 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(&s, len(s))
return ok
}
// reset_ctr 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) {
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")
}
if aad_len := u64(len(aad)); aad_len > GCM_A_MAX {
panic("crypto/aes: oversized GCM aad")
}
if text_len := u64(len(text)); text_len > GCM_P_MAX {
panic("crypto/aes: oversized GCM src data")
}
}
@(private = "file")
init_ghash_ct64 :: proc(
ctx: ^Context_GCM,
h: ^[_aes.GHASH_KEY_SIZE]byte,
j0: ^[_aes.GHASH_BLOCK_SIZE]byte,
nonce: []byte,
) {
impl := &ctx._impl.(ct64.Context)
// 1. Let H = CIPH(k, 0^128)
ct64.encrypt_block(impl, h[:], h[:])
// 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[:])
}
@(private = "file")
final_ghash_ct64 :: 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)
ct64.ghash(s[:], h[:], blk[:])
for i in 0 ..< len(s) {
s[i] ~= j0[i]
}
}
@(private = "file")
gctr_ct64 :: proc(
ctx: ^Context_GCM,
dst: []byte,
s: ^[_aes.GHASH_BLOCK_SIZE]byte,
src: []byte,
h: ^[_aes.GHASH_KEY_SIZE]byte,
nonce: []byte,
is_seal: bool,
) {
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.
tmp, tmp2: [ct64.STRIDE][BLOCK_SIZE]byte = ---, ---
ctrs, blks: [ct64.STRIDE][]byte = ---, ---
ctr: u32 = 2
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)
}
// 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
nr_blocks := len(src) / BLOCK_SIZE
for nr_blocks > 0 {
n := min(ct64.STRIDE, nr_blocks)
l := n * BLOCK_SIZE
if !is_seal {
ct64.ghash(s[:], h[:], src[:l])
}
// The keystream is written to a separate buffer, as we will
// reuse the first 96-bits of each counter.
for i in 0 ..< n {
ctr = ct64_inc_ctr32(ctrs[i], ctr)
}
ct64.encrypt_blocks(impl, blks[:n], ctrs[:n])
xor_blocks(dst, src, blks[:n])
if is_seal {
ct64.ghash(s[:], h[:], dst[:l])
}
src = src[l:]
dst = dst[l:]
nr_blocks -= n
}
if l := len(src); l > 0 {
if !is_seal {
ct64.ghash(s[:], h[:], src[:l])
}
ct64_inc_ctr32(ctrs[0], ctr)
ct64.encrypt_block(impl, ctrs[0], ctrs[0])
for i in 0 ..< l {
dst[i] = src[i] ~ ctrs[0][i]
}
if is_seal {
ct64.ghash(s[:], h[:], dst[:l])
}
}
mem.zero_explicit(&tmp, size_of(tmp))
mem.zero_explicit(&tmp2, size_of(tmp2))
}
+41
View File
@@ -0,0 +1,41 @@
package aes
import "core:crypto/_aes/ct64"
import "core:mem"
import "core:reflect"
@(private)
Context_Impl :: union {
ct64.Context,
Context_Impl_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()`).
Implementation :: enum {
Portable,
Hardware,
}
@(private)
init_impl :: proc(ctx: ^Context_Impl, key: []byte, impl: Implementation) {
impl := impl
if !is_hardware_accelerated() {
impl = .Portable
}
switch impl {
case .Portable:
reflect.set_union_variant_typeid(ctx^, typeid_of(ct64.Context))
ct64.init(&ctx.(ct64.Context), key)
case .Hardware:
reflect.set_union_variant_typeid(ctx^, typeid_of(Context_Impl_Hardware))
init_impl_hw(&ctx.(Context_Impl_Hardware), key)
}
}
@(private)
reset_impl :: proc "contextless" (ctx: ^Context_Impl) {
mem.zero_explicit(ctx, size_of(Context_Impl))
}
+43
View File
@@ -0,0 +1,43 @@
package aes
@(private = "file")
ERR_HW_NOT_SUPPORTED :: "crypto/aes: hardware implementation unsupported"
// is_hardware_accelerated returns true iff hardware accelerated AES
// is supported.
is_hardware_accelerated :: proc "contextless" () -> bool {
return false
}
@(private)
Context_Impl_Hardware :: struct {}
@(private)
init_impl_hw :: proc(ctx: ^Context_Impl_Hardware, key: []byte) {
panic(ERR_HW_NOT_SUPPORTED)
}
@(private)
encrypt_block_hw :: proc(ctx: ^Context_Impl_Hardware, dst, src: []byte) {
panic(ERR_HW_NOT_SUPPORTED)
}
@(private)
decrypt_block_hw :: proc(ctx: ^Context_Impl_Hardware, dst, src: []byte) {
panic(ERR_HW_NOT_SUPPORTED)
}
@(private)
ctr_blocks_hw :: proc(ctx: ^Context_CTR, dst, src: []byte, nr_blocks: int) {
panic(ERR_HW_NOT_SUPPORTED)
}
@(private)
gcm_seal_hw :: proc(ctx: ^Context_Impl_Hardware, dst, tag, nonce, aad, plaintext: []byte) {
panic(ERR_HW_NOT_SUPPORTED)
}
@(private)
gcm_open_hw :: proc(ctx: ^Context_Impl_Hardware, dst, nonce, aad, ciphertext, tag: []byte) -> bool {
panic(ERR_HW_NOT_SUPPORTED)
}
+34 -102
View File
@@ -1,3 +1,10 @@
/*
package blake2b implements the BLAKE2b hash algorithm.
See:
- https://datatracker.ietf.org/doc/html/rfc7693
- https://www.blake2.net
*/
package blake2b
/*
@@ -6,122 +13,47 @@ package blake2b
List of contributors:
zhibog, dotbmp: Initial implementation.
Interface for the BLAKE2b hashing algorithm.
BLAKE2b and BLAKE2s share the implementation in the _blake2 package.
*/
import "core:io"
import "core:os"
import "../_blake2"
/*
High level API
*/
// DIGEST_SIZE is the BLAKE2b digest size in bytes.
DIGEST_SIZE :: 64
// hash_string will hash the given input and return the
// computed hash
hash_string :: proc(data: string) -> [DIGEST_SIZE]byte {
return hash_bytes(transmute([]byte)(data))
}
// hash_bytes will hash the given input and return the
// computed hash
hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte {
hash: [DIGEST_SIZE]byte
ctx: Context
cfg: _blake2.Blake2_Config
cfg.size = _blake2.BLAKE2B_SIZE
ctx.cfg = cfg
init(&ctx)
update(&ctx, data)
final(&ctx, hash[:])
return hash
}
// hash_string_to_buffer will hash the given input and assign the
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer will hash the given input and write the
// computed hash into the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_bytes_to_buffer :: proc(data, hash: []byte) {
ctx: Context
cfg: _blake2.Blake2_Config
cfg.size = _blake2.BLAKE2B_SIZE
ctx.cfg = cfg
init(&ctx)
update(&ctx, data)
final(&ctx, hash)
}
// hash_stream will read the stream in chunks and compute a
// hash from its contents
hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) {
hash: [DIGEST_SIZE]byte
ctx: Context
cfg: _blake2.Blake2_Config
cfg.size = _blake2.BLAKE2B_SIZE
ctx.cfg = cfg
init(&ctx)
buf := make([]byte, 512)
defer delete(buf)
read := 1
for read > 0 {
read, _ = io.read(s, buf)
if read > 0 {
update(&ctx, buf[:read])
}
}
final(&ctx, hash[:])
return hash, true
}
// hash_file will read the file provided by the given handle
// and compute a hash
hash_file :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE]byte, bool) {
if !load_at_once {
return hash_stream(os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes(buf[:]), ok
}
}
return [DIGEST_SIZE]byte{}, false
}
hash :: proc {
hash_stream,
hash_file,
hash_bytes,
hash_string,
hash_bytes_to_buffer,
hash_string_to_buffer,
}
/*
Low level API
*/
// BLOCK_SIZE is the BLAKE2b block size in bytes.
BLOCK_SIZE :: _blake2.BLAKE2B_BLOCK_SIZE
// Context is a BLAKE2b instance.
Context :: _blake2.Blake2b_Context
// init initializes a Context with the default BLAKE2b config.
init :: proc(ctx: ^Context) {
_blake2.init(ctx)
cfg: _blake2.Blake2_Config
cfg.size = _blake2.BLAKE2B_SIZE
_blake2.init(ctx, &cfg)
}
// update adds more data to the Context.
update :: proc(ctx: ^Context, data: []byte) {
_blake2.update(ctx, data)
}
final :: proc(ctx: ^Context, hash: []byte) {
_blake2.final(ctx, hash)
// final finalizes the Context, writes the digest to hash, and calls
// reset on the Context.
//
// Iff finalize_clone is set, final will work on a copy of the Context,
// which is useful for for calculating rolling digests.
final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) {
_blake2.final(ctx, hash, finalize_clone)
}
// clone clones the Context other into ctx.
clone :: proc(ctx, other: ^Context) {
_blake2.clone(ctx, other)
}
// reset sanitizes the Context. The Context must be re-initialized to
// be used again.
reset :: proc(ctx: ^Context) {
_blake2.reset(ctx)
}
+34 -102
View File
@@ -1,3 +1,10 @@
/*
package blake2s implements the BLAKE2s hash algorithm.
See:
- https://datatracker.ietf.org/doc/html/rfc7693
- https://www.blake2.net/
*/
package blake2s
/*
@@ -6,122 +13,47 @@ package blake2s
List of contributors:
zhibog, dotbmp: Initial implementation.
Interface for the BLAKE2s hashing algorithm.
BLAKE2s and BLAKE2b share the implementation in the _blake2 package.
*/
import "core:io"
import "core:os"
import "../_blake2"
/*
High level API
*/
// DIGEST_SIZE is the BLAKE2s digest size in bytes.
DIGEST_SIZE :: 32
// hash_string will hash the given input and return the
// computed hash
hash_string :: proc(data: string) -> [DIGEST_SIZE]byte {
return hash_bytes(transmute([]byte)(data))
}
// hash_bytes will hash the given input and return the
// computed hash
hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte {
hash: [DIGEST_SIZE]byte
ctx: Context
cfg: _blake2.Blake2_Config
cfg.size = _blake2.BLAKE2S_SIZE
ctx.cfg = cfg
init(&ctx)
update(&ctx, data)
final(&ctx, hash[:])
return hash
}
// hash_string_to_buffer will hash the given input and assign the
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer will hash the given input and write the
// computed hash into the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_bytes_to_buffer :: proc(data, hash: []byte) {
ctx: Context
cfg: _blake2.Blake2_Config
cfg.size = _blake2.BLAKE2S_SIZE
ctx.cfg = cfg
init(&ctx)
update(&ctx, data)
final(&ctx, hash)
}
// hash_stream will read the stream in chunks and compute a
// hash from its contents
hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) {
hash: [DIGEST_SIZE]byte
ctx: Context
cfg: _blake2.Blake2_Config
cfg.size = _blake2.BLAKE2S_SIZE
ctx.cfg = cfg
init(&ctx)
buf := make([]byte, 512)
defer delete(buf)
read := 1
for read > 0 {
read, _ = io.read(s, buf)
if read > 0 {
update(&ctx, buf[:read])
}
}
final(&ctx, hash[:])
return hash, true
}
// hash_file will read the file provided by the given handle
// and compute a hash
hash_file :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE]byte, bool) {
if !load_at_once {
return hash_stream(os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes(buf[:]), ok
}
}
return [DIGEST_SIZE]byte{}, false
}
hash :: proc {
hash_stream,
hash_file,
hash_bytes,
hash_string,
hash_bytes_to_buffer,
hash_string_to_buffer,
}
/*
Low level API
*/
// BLOCK_SIZE is the BLAKE2s block size in bytes.
BLOCK_SIZE :: _blake2.BLAKE2S_BLOCK_SIZE
// Context is a BLAKE2s instance.
Context :: _blake2.Blake2s_Context
// init initializes a Context with the default BLAKE2s config.
init :: proc(ctx: ^Context) {
_blake2.init(ctx)
cfg: _blake2.Blake2_Config
cfg.size = _blake2.BLAKE2S_SIZE
_blake2.init(ctx, &cfg)
}
// update adds more data to the Context.
update :: proc(ctx: ^Context, data: []byte) {
_blake2.update(ctx, data)
}
final :: proc(ctx: ^Context, hash: []byte) {
_blake2.final(ctx, hash)
// final finalizes the Context, writes the digest to hash, and calls
// reset on the Context.
//
// Iff finalize_clone is set, final will work on a copy of the Context,
// which is useful for for calculating rolling digests.
final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) {
_blake2.final(ctx, hash, finalize_clone)
}
// clone clones the Context other into ctx.
clone :: proc(ctx, other: ^Context) {
_blake2.clone(ctx, other)
}
// reset sanitizes the Context. The Context must be re-initialized to
// be used again.
reset :: proc(ctx: ^Context) {
_blake2.reset(ctx)
}
+33 -15
View File
@@ -1,11 +1,21 @@
/*
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/
*/
package chacha20
import "core:encoding/endian"
import "core:math/bits"
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)
@@ -19,25 +29,26 @@ _STATE_SIZE_U32 :: 16
_ROUNDS :: 20
@(private)
_SIGMA_0 : u32 : 0x61707865
_SIGMA_0: u32 : 0x61707865
@(private)
_SIGMA_1 : u32 : 0x3320646e
_SIGMA_1: u32 : 0x3320646e
@(private)
_SIGMA_2 : u32 : 0x79622d32
_SIGMA_2: u32 : 0x79622d32
@(private)
_SIGMA_3 : u32 : 0x6b206574
_SIGMA_3: u32 : 0x6b206574
// Context is a ChaCha20 or XChaCha20 instance.
Context :: struct {
_s: [_STATE_SIZE_U32]u32,
_buffer: [_BLOCK_SIZE]byte,
_off: int,
_s: [_STATE_SIZE_U32]u32,
_buffer: [_BLOCK_SIZE]byte,
_off: int,
_is_ietf_flavor: bool,
_is_initialized: bool,
}
init :: proc (ctx: ^Context, key, nonce: []byte) {
// init inititializes a Context for ChaCha20 or XChaCha20 with the provided
// key and nonce.
init :: proc(ctx: ^Context, key, nonce: []byte) {
if len(key) != KEY_SIZE {
panic("crypto/chacha20: invalid ChaCha20 key size")
}
@@ -89,7 +100,8 @@ init :: proc (ctx: ^Context, key, nonce: []byte) {
ctx._is_initialized = true
}
seek :: proc (ctx: ^Context, block_nr: u64) {
// 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 {
@@ -103,7 +115,10 @@ seek :: proc (ctx: ^Context, block_nr: u64) {
ctx._off = _BLOCK_SIZE
}
xor_bytes :: proc (ctx: ^Context, dst, src: []byte) {
// 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
@@ -147,7 +162,8 @@ xor_bytes :: proc (ctx: ^Context, dst, src: []byte) {
}
}
keystream_bytes :: proc (ctx: ^Context, dst: []byte) {
// keystream_bytes fills dst with the raw (X)ChaCha20 keystream output.
keystream_bytes :: proc(ctx: ^Context, dst: []byte) {
assert(ctx._is_initialized)
dst := dst
@@ -180,7 +196,9 @@ keystream_bytes :: proc (ctx: ^Context, dst: []byte) {
}
}
reset :: proc (ctx: ^Context) {
// 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))
@@ -188,7 +206,7 @@ reset :: proc (ctx: ^Context) {
}
@(private)
_do_blocks :: proc (ctx: ^Context, dst, src: []byte, nr_blocks: int) {
_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
@@ -1,3 +1,10 @@
/*
package chacha20poly1305 implements the AEAD_CHACHA20_POLY1305 Authenticated
Encryption with Additional Data algorithm.
See:
- https://www.rfc-editor.org/rfc/rfc8439
*/
package chacha20poly1305
import "core:crypto"
@@ -6,8 +13,11 @@ import "core:crypto/poly1305"
import "core:encoding/endian"
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
// TAG_SIZE is the chacha20poly1305 tag size in bytes.
TAG_SIZE :: poly1305.TAG_SIZE
@(private)
@@ -49,6 +59,8 @@ _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)
if len(ciphertext) != len(plaintext) {
@@ -95,6 +107,11 @@ 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.
//
// 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)
if len(ciphertext) != len(plaintext) {
+29
View File
@@ -1,5 +1,10 @@
/*
package crypto implements a selection of cryptography algorithms and useful
helper routines.
*/
package crypto
import "base:runtime"
import "core:mem"
// compare_constant_time returns 1 iff a and b are equal, 0 otherwise.
@@ -45,9 +50,33 @@ compare_byte_ptrs_constant_time :: proc "contextless" (a, b: ^byte, n: int) -> i
// the system entropy source. This routine will block if the system entropy
// source is not ready yet. All system entropy source failures are treated
// as catastrophic, resulting in a panic.
//
// Support for the system entropy source can be checked with the
// `HAS_RAND_BYTES` boolean constant.
rand_bytes :: proc (dst: []byte) {
// zero-fill the buffer first
mem.zero_explicit(raw_data(dst), len(dst))
_rand_bytes(dst)
}
random_generator :: proc() -> runtime.Random_Generator {
return {
procedure = proc(data: rawptr, mode: runtime.Random_Generator_Mode, p: []byte) {
switch mode {
case .Read:
rand_bytes(p)
case .Reset:
// do nothing
case .Query_Info:
if len(p) != size_of(runtime.Random_Generator_Query_Info) {
return
}
info := (^runtime.Random_Generator_Query_Info)(raw_data(p))
info^ += {.Uniform, .Cryptographic, .External_Entropy}
}
},
data = nil,
}
}
+314
View File
@@ -0,0 +1,314 @@
/*
package ed25519 implements the Ed25519 EdDSA signature algorithm.
See:
- https://datatracker.ietf.org/doc/html/rfc8032
- https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf
- https://eprint.iacr.org/2020/1244.pdf
*/
package ed25519
import "core:crypto"
import grp "core:crypto/_edwards25519"
import "core:crypto/sha2"
import "core:mem"
// PRIVATE_KEY_SIZE is the byte-encoded private key size.
PRIVATE_KEY_SIZE :: 32
// PUBLIC_KEY_SIZE is the byte-encoded public key size.
PUBLIC_KEY_SIZE :: 32
// SIGNATURE_SIZE is the byte-encoded signature size.
SIGNATURE_SIZE :: 64
@(private)
NONCE_SIZE :: 32
// Private_Key is an Ed25519 private key.
Private_Key :: struct {
// WARNING: All of the members are to be treated as internal (ie:
// the Private_Key structure is intended to be opaque). There are
// subtle vulnerabilities that can be introduced if the internal
// values are allowed to be altered.
//
// See: https://github.com/MystenLabs/ed25519-unsafe-libs
_b: [PRIVATE_KEY_SIZE]byte,
_s: grp.Scalar,
_nonce: [NONCE_SIZE]byte,
_pub_key: Public_Key,
_is_initialized: bool,
}
// Public_Key is an Ed25519 public key.
Public_Key :: struct {
// WARNING: All of the members are to be treated as internal (ie:
// the Public_Key structure is intended to be opaque).
_b: [PUBLIC_KEY_SIZE]byte,
_neg_A: grp.Group_Element,
_is_valid: bool,
_is_initialized: bool,
}
// private_key_set_bytes decodes a byte-encoded private key, and returns
// true iff the operation was successful.
private_key_set_bytes :: proc(priv_key: ^Private_Key, b: []byte) -> bool {
if len(b) != PRIVATE_KEY_SIZE {
return false
}
// Derive the private key.
ctx: sha2.Context_512 = ---
h_bytes: [sha2.DIGEST_SIZE_512]byte = ---
sha2.init_512(&ctx)
sha2.update(&ctx, b)
sha2.final(&ctx, h_bytes[:])
copy(priv_key._b[:], b)
copy(priv_key._nonce[:], h_bytes[32:])
grp.sc_set_bytes_rfc8032(&priv_key._s, h_bytes[:32])
// Derive the corresponding public key.
A: grp.Group_Element = ---
grp.ge_scalarmult_basepoint(&A, &priv_key._s)
grp.ge_bytes(&A, priv_key._pub_key._b[:])
grp.ge_negate(&priv_key._pub_key._neg_A, &A)
priv_key._pub_key._is_valid = !grp.ge_is_small_order(&A)
priv_key._pub_key._is_initialized = true
priv_key._is_initialized = true
return true
}
// private_key_bytes sets dst to byte-encoding of priv_key.
private_key_bytes :: proc(priv_key: ^Private_Key, dst: []byte) {
if !priv_key._is_initialized {
panic("crypto/ed25519: uninitialized private key")
}
if len(dst) != PRIVATE_KEY_SIZE {
panic("crypto/ed25519: invalid destination size")
}
copy(dst, priv_key._b[:])
}
// private_key_clear clears priv_key to the uninitialized state.
private_key_clear :: proc "contextless" (priv_key: ^Private_Key) {
mem.zero_explicit(priv_key, size_of(Private_Key))
}
// sign writes the signature by priv_key over msg to sig.
sign :: proc(priv_key: ^Private_Key, msg, sig: []byte) {
if !priv_key._is_initialized {
panic("crypto/ed25519: uninitialized private key")
}
if len(sig) != SIGNATURE_SIZE {
panic("crypto/ed25519: invalid destination size")
}
// 1. Compute the hash of the private key d, H(d) = (h_0, h_1, ..., h_2b-1)
// using SHA-512 for Ed25519. H(d) may be precomputed.
//
// 2. Using the second half of the digest hdigest2 = hb || ... || h2b-1,
// define:
//
// 2.1 For Ed25519, r = SHA-512(hdigest2 || M); Interpret r as a
// 64-octet little-endian integer.
ctx: sha2.Context_512 = ---
digest_bytes: [sha2.DIGEST_SIZE_512]byte = ---
sha2.init_512(&ctx)
sha2.update(&ctx, priv_key._nonce[:])
sha2.update(&ctx, msg)
sha2.final(&ctx, digest_bytes[:])
r: grp.Scalar = ---
grp.sc_set_bytes_wide(&r, &digest_bytes)
// 3. Compute the point [r]G. The octet string R is the encoding of
// the point [r]G.
R: grp.Group_Element = ---
R_bytes := sig[:32]
grp.ge_scalarmult_basepoint(&R, &r)
grp.ge_bytes(&R, R_bytes)
// 4. Derive s from H(d) as in the key pair generation algorithm.
// Use octet strings R, Q, and M to define:
//
// 4.1 For Ed25519, digest = SHA-512(R || Q || M).
// Interpret digest as a little-endian integer.
sha2.init_512(&ctx)
sha2.update(&ctx, R_bytes)
sha2.update(&ctx, priv_key._pub_key._b[:]) // Q in NIST terminology.
sha2.update(&ctx, msg)
sha2.final(&ctx, digest_bytes[:])
sc: grp.Scalar = --- // `digest` in NIST terminology.
grp.sc_set_bytes_wide(&sc, &digest_bytes)
// 5. Compute S = (r + digest × s) mod n. The octet string S is the
// encoding of the resultant integer.
grp.sc_mul(&sc, &sc, &priv_key._s)
grp.sc_add(&sc, &sc, &r)
// 6. Form the signature as the concatenation of the octet strings
// R and S.
grp.sc_bytes(sig[32:], &sc)
grp.sc_clear(&r)
}
// public_key_set_bytes decodes a byte-encoded public key, and returns
// true iff the operation was successful.
public_key_set_bytes :: proc "contextless" (pub_key: ^Public_Key, b: []byte) -> bool {
if len(b) != PUBLIC_KEY_SIZE {
return false
}
A: grp.Group_Element = ---
if !grp.ge_set_bytes(&A, b) {
return false
}
copy(pub_key._b[:], b)
grp.ge_negate(&pub_key._neg_A, &A)
pub_key._is_valid = !grp.ge_is_small_order(&A)
pub_key._is_initialized = true
return true
}
// public_key_set_priv sets pub_key to the public component of priv_key.
public_key_set_priv :: proc(pub_key: ^Public_Key, priv_key: ^Private_Key) {
if !priv_key._is_initialized {
panic("crypto/ed25519: uninitialized public key")
}
src := &priv_key._pub_key
copy(pub_key._b[:], src._b[:])
grp.ge_set(&pub_key._neg_A, &src._neg_A)
pub_key._is_valid = src._is_valid
pub_key._is_initialized = src._is_initialized
}
// public_key_bytes sets dst to byte-encoding of pub_key.
public_key_bytes :: proc(pub_key: ^Public_Key, dst: []byte) {
if !pub_key._is_initialized {
panic("crypto/ed25519: uninitialized public key")
}
if len(dst) != PUBLIC_KEY_SIZE {
panic("crypto/ed25519: invalid destination size")
}
copy(dst, pub_key._b[:])
}
// public_key_equal returns true iff pub_key is equal to other.
public_key_equal :: proc(pub_key, other: ^Public_Key) -> bool {
if !pub_key._is_initialized || !other._is_initialized {
panic("crypto/ed25519: uninitialized public key")
}
return crypto.compare_constant_time(pub_key._b[:], other._b[:]) == 1
}
// verify returns true iff sig is a valid signature by pub_key over msg.
//
// The optional `allow_small_order_A` parameter will make this
// implementation strictly compatible with FIPS 186-5, at the expense of
// SBS-security. Doing so is NOT recommended, and the disallowed
// public keys all have a known discrete-log.
verify :: proc(pub_key: ^Public_Key, msg, sig: []byte, allow_small_order_A := false) -> bool {
switch {
case !pub_key._is_initialized:
return false
case len(sig) != SIGNATURE_SIZE:
return false
}
// TLDR: Just use ristretto255.
//
// While there are two "standards" for EdDSA, existing implementations
// diverge (sometimes dramatically). This implementation opts for
// "Algorithm 2" from "Taming the Many EdDSAs", which provides the
// strongest notion of security (SUF-CMA + SBS).
//
// The relevant properties are:
// - Reject non-canonical S.
// - Reject non-canonical A/R.
// - Reject small-order A (Extra non-standard check).
// - Cofactored verification equation.
//
// There are 19 possible non-canonical group element encodings of
// which:
// - 2 are small order
// - 10 are mixed order
// - 7 are not on the curve
//
// While historical implementations have been lax about enforcing
// that A/R are canonically encoded, that behavior is mandated by
// both the RFC and FIPS specification. No valid key generation
// or sign implementation will ever produce non-canonically encoded
// public keys or signatures.
//
// There are 8 small-order group elements, 1 which is in the
// prime-order sub-group, and thus the probability that a properly
// generated A is small-order is cryptographically insignificant.
//
// While both the RFC and FIPS standard allow for either the
// cofactored or non-cofactored equation. It is possible to
// artificially produce signatures that are valid for the former
// but not the latter. This will NEVER occur with a valid sign
// implementation. The choice of the latter is to be compatible
// with ABGLSV-Pornin, batch verification, and FROST (among other
// things).
s_bytes, r_bytes := sig[32:], sig[:32]
// 1. Reject the signature if S is not in the range [0, L).
s: grp.Scalar = ---
if !grp.sc_set_bytes(&s, s_bytes) {
return false
}
// 2. Reject the signature if the public key A is one of 8 small
// order points.
//
// As this check is optional and not part of the standard, we allow
// the caller to bypass it if desired. Disabling the check makes
// the scheme NOT SBS-secure.
if !pub_key._is_valid && !allow_small_order_A {
return false
}
// 3. Reject the signature if A or R are non-canonical.
//
// Note: All initialized public keys are guaranteed to be canonical.
neg_R: grp.Group_Element = ---
if !grp.ge_set_bytes(&neg_R, r_bytes) {
return false
}
grp.ge_negate(&neg_R, &neg_R)
// 4. Compute the hash SHA512(R||A||M) and reduce it mod L to get a
// scalar h.
ctx: sha2.Context_512 = ---
h_bytes: [sha2.DIGEST_SIZE_512]byte = ---
sha2.init_512(&ctx)
sha2.update(&ctx, r_bytes)
sha2.update(&ctx, pub_key._b[:])
sha2.update(&ctx, msg)
sha2.final(&ctx, h_bytes[:])
h: grp.Scalar = ---
grp.sc_set_bytes_wide(&h, &h_bytes)
// 5. Accept if 8(s * G) - 8R - 8(h * A) = 0
//
// > first compute V = SB R hA and then accept if V is one of
// > 8 small order points (or alternatively compute 8V with 3
// > doublings and check against the neutral element)
V: grp.Group_Element = ---
grp.ge_double_scalarmult_basepoint_vartime(&V, &h, &pub_key._neg_A, &s)
grp.ge_add(&V, &V, &neg_R)
return grp.ge_is_small_order(&V)
}

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