Merge branch 'master' into macharena

This commit is contained in:
Colin Davidson
2024-09-24 02:32:06 -07:00
597 changed files with 17453 additions and 6717 deletions
+21 -21
View File
@@ -32,9 +32,9 @@ jobs:
gmake -C vendor/miniaudio/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_amd64
./odin check examples/all -vet -strict-style -disallow-do -target:netbsd_arm64 ./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 -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true ./odin test tests/core/normal.odin -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
./odin test tests/core/speed.odin -file -all-packages -o:speed -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true ./odin test tests/core/speed.odin -file -all-packages -vet -strict-style -disallow-do -o:speed -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
./odin test tests/vendor -all-packages -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true ./odin test tests/vendor -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
(cd tests/issues; ./run.sh) (cd tests/issues; ./run.sh)
build_freebsd: build_freebsd:
name: FreeBSD Build, Check, and Test name: FreeBSD Build, Check, and Test
@@ -60,9 +60,9 @@ jobs:
gmake -C vendor/cgltf/src gmake -C vendor/cgltf/src
gmake -C vendor/miniaudio/src gmake -C vendor/miniaudio/src
./odin check examples/all -vet -strict-style -disallow-do -target:freebsd_amd64 ./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 -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true ./odin test tests/core/normal.odin -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
./odin test tests/core/speed.odin -file -all-packages -o:speed -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true ./odin test tests/core/speed.odin -file -all-packages -vet -strict-style -disallow-do -o:speed -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
./odin test tests/vendor -all-packages -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true ./odin test tests/vendor -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
(cd tests/issues; ./run.sh) (cd tests/issues; ./run.sh)
ci: ci:
strategy: strategy:
@@ -116,13 +116,13 @@ jobs:
- name: Odin check examples/all - name: Odin check examples/all
run: ./odin check examples/all -strict-style run: ./odin check examples/all -strict-style
- name: Normal Core library tests - name: Normal Core library tests
run: ./odin test tests/core/normal.odin -file -all-packages -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true run: ./odin test tests/core/normal.odin -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
- name: Optimized Core library tests - name: Optimized Core library tests
run: ./odin test tests/core/speed.odin -o:speed -file -all-packages -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true run: ./odin test tests/core/speed.odin -o:speed -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
- name: Vendor library tests - name: Vendor library tests
run: ./odin test tests/vendor -all-packages -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true run: ./odin test tests/vendor -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
- name: Internals tests - name: Internals tests
run: ./odin test tests/internal -all-packages -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true run: ./odin test tests/internal -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
- name: GitHub Issue tests - name: GitHub Issue tests
run: | run: |
cd tests/issues cd tests/issues
@@ -176,33 +176,33 @@ jobs:
shell: cmd shell: cmd
run: | run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin run examples/demo -debug odin run examples/demo -debug -vet -strict-style -disallow-do
- name: Odin check examples/all - name: Odin check examples/all
shell: cmd shell: cmd
run: | run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin check examples/all -strict-style odin check examples/all -vet -strict-style -disallow-do
- name: Core library tests - name: Core library tests
shell: cmd shell: cmd
run: | run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin test tests/core/normal.odin -file -all-packages -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true odin test tests/core/normal.odin -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
- name: Optimized core library tests - name: Optimized core library tests
shell: cmd shell: cmd
run: | run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat 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 -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true odin test tests/core/speed.odin -o:speed -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
- name: Vendor library tests - name: Vendor library tests
shell: cmd shell: cmd
run: | run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
copy vendor\lua\5.4\windows\*.dll . copy vendor\lua\5.4\windows\*.dll .
odin test tests/vendor -all-packages -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true odin test tests/vendor -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
- name: Odin internals tests - name: Odin internals tests
shell: cmd shell: cmd
run: | run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin test tests/internal -all-packages -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true odin test tests/internal -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
- name: Odin documentation tests - name: Odin documentation tests
shell: cmd shell: cmd
run: | run: |
@@ -257,16 +257,16 @@ jobs:
run: sudo apt-get install -y qemu-user qemu-user-static gcc-12-riscv64-linux-gnu libc6-riscv64-cross run: sudo apt-get install -y qemu-user qemu-user-static gcc-12-riscv64-linux-gnu libc6-riscv64-cross
- name: Odin run - name: Odin run
run: ./odin run examples/demo -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" run: ./odin run examples/demo -vet -strict-style -disallow-do -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" -no-rpath
- name: Odin run -debug - name: Odin run -debug
run: ./odin run examples/demo -debug -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" run: ./odin run examples/demo -debug -vet -strict-style -disallow-do -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" -no-rpath
- name: Normal Core library tests - name: Normal Core library tests
run: ./odin test tests/core/normal.odin -file -all-packages -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" run: ./odin test tests/core/normal.odin -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" -no-rpath
- name: Optimized Core library tests - name: Optimized Core library tests
run: ./odin test tests/core/speed.odin -o:speed -file -all-packages -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" run: ./odin test tests/core/speed.odin -o:speed -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" -no-rpath
- name: Internals tests - name: Internals tests
run: ./odin test tests/internal -all-packages -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" run: ./odin test tests/internal -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" -no-rpath
+86 -59
View File
@@ -36,43 +36,54 @@ jobs:
cp -r bin dist cp -r bin dist
cp -r examples dist cp -r examples dist
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@v1 uses: actions/upload-artifact@v4
with: with:
name: windows_artifacts name: windows_artifacts
path: dist path: dist
build_ubuntu: build_linux:
name: Ubuntu Build name: Linux Build
if: github.repository == 'odin-lang/Odin' if: github.repository == 'odin-lang/Odin'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: jirutka/setup-alpine@v1
with:
branch: v3.20
- name: (Linux) Download LLVM - name: (Linux) Download LLVM
run: | run: |
wget https://apt.llvm.org/llvm.sh apk add --no-cache \
chmod +x llvm.sh musl-dev llvm18-dev clang18 git mold lz4 \
sudo ./llvm.sh 18 libxml2-static llvm18-static zlib-static zstd-static \
echo "/usr/lib/llvm-18/bin" >> $GITHUB_PATH make
shell: alpine.sh --root {0}
- name: build odin - name: build odin
run: make nightly # NOTE: this build does slow compile times because of musl
run: ci/build_linux_static.sh
shell: alpine.sh {0}
- name: Odin run - name: Odin run
run: ./odin run examples/demo run: ./odin run examples/demo
- name: Copy artifacts - name: Copy artifacts
run: | run: |
mkdir dist FILE="odin-linux-amd64-nightly+$(date -I)"
cp odin dist mkdir $FILE
cp LICENSE dist cp odin $FILE
cp -r shared dist cp LICENSE $FILE
cp -r base dist cp -r shared $FILE
cp -r core dist cp -r base $FILE
cp -r vendor dist cp -r core $FILE
cp -r examples dist cp -r vendor $FILE
# Zipping so executable permissions are retained, see https://github.com/actions/upload-artifact/issues/38 cp -r examples $FILE
zip -r dist.zip dist # Creating a tarball so executable permissions are retained, see https://github.com/actions/upload-artifact/issues/38
tar -czvf dist.tar.gz $FILE
- name: Odin run
run: |
FILE="odin-linux-amd64-nightly+$(date -I)"
$FILE/odin run examples/demo
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@v1 uses: actions/upload-artifact@v4
with: with:
name: ubuntu_artifacts name: linux_artifacts
path: dist.zip path: dist.tar.gz
build_macos: build_macos:
name: MacOS Build name: MacOS Build
if: github.repository == 'odin-lang/Odin' if: github.repository == 'odin-lang/Odin'
@@ -89,24 +100,27 @@ jobs:
run: CXXFLAGS="-L/usr/lib/system -L/usr/lib" make nightly run: CXXFLAGS="-L/usr/lib/system -L/usr/lib" make nightly
- name: Bundle - name: Bundle
run: | run: |
mkdir dist FILE="odin-macos-amd64-nightly+$(date -I)"
cp odin dist mkdir $FILE
cp LICENSE dist cp odin $FILE
cp -r shared dist cp LICENSE $FILE
cp -r base dist cp -r shared $FILE
cp -r core dist cp -r base $FILE
cp -r vendor dist cp -r core $FILE
cp -r examples dist cp -r vendor $FILE
dylibbundler -b -x dist/odin -d dist/libs -od -p @executable_path/libs cp -r examples $FILE
# Zipping so executable permissions are retained, see https://github.com/actions/upload-artifact/issues/38 dylibbundler -b -x $FILE/odin -d $FILE/libs -od -p @executable_path/libs
zip -r dist.zip dist # Creating a tarball so executable permissions are retained, see https://github.com/actions/upload-artifact/issues/38
tar -czvf dist.tar.gz $FILE
- name: Odin run - name: Odin run
run: ./dist/odin run examples/demo run: |
FILE="odin-macos-amd64-nightly+$(date -I)"
$FILE/odin run examples/demo
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@v1 uses: actions/upload-artifact@v4
with: with:
name: macos_artifacts name: macos_artifacts
path: dist.zip path: dist.tar.gz
build_macos_arm: build_macos_arm:
name: MacOS ARM Build name: MacOS ARM Build
if: github.repository == 'odin-lang/Odin' if: github.repository == 'odin-lang/Odin'
@@ -123,30 +137,33 @@ jobs:
run: CXXFLAGS="-L/usr/lib/system -L/usr/lib" make nightly run: CXXFLAGS="-L/usr/lib/system -L/usr/lib" make nightly
- name: Bundle - name: Bundle
run: | run: |
mkdir dist FILE="odin-macos-arm64-nightly+$(date -I)"
cp odin dist mkdir $FILE
cp LICENSE dist cp odin $FILE
cp -r shared dist cp LICENSE $FILE
cp -r base dist cp -r shared $FILE
cp -r core dist cp -r base $FILE
cp -r vendor dist cp -r core $FILE
cp -r examples dist cp -r vendor $FILE
dylibbundler -b -x dist/odin -d dist/libs -od -p @executable_path/libs cp -r examples $FILE
# Zipping so executable permissions are retained, see https://github.com/actions/upload-artifact/issues/38 dylibbundler -b -x $FILE/odin -d $FILE/libs -od -p @executable_path/libs
zip -r dist.zip dist # Creating a tarball so executable permissions are retained, see https://github.com/actions/upload-artifact/issues/38
tar -czvf dist.tar.gz $FILE
- name: Odin run - name: Odin run
run: ./dist/odin run examples/demo run: |
FILE="odin-macos-arm64-nightly+$(date -I)"
$FILE/odin run examples/demo
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@v1 uses: actions/upload-artifact@v4
with: with:
name: macos_arm_artifacts name: macos_arm_artifacts
path: dist.zip path: dist.tar.gz
upload_b2: upload_b2:
runs-on: [ubuntu-latest] runs-on: [ubuntu-latest]
needs: [build_windows, build_macos, build_macos_arm, build_ubuntu] needs: [build_windows, build_macos, build_macos_arm, build_linux]
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-python@v2 - uses: actions/setup-python@v5
with: with:
python-version: '3.8.x' python-version: '3.8.x'
@@ -160,24 +177,33 @@ jobs:
run: python -c "import sys; print(sys.version)" run: python -c "import sys; print(sys.version)"
- name: Download Windows artifacts - name: Download Windows artifacts
uses: actions/download-artifact@v1
uses: actions/download-artifact@v4.1.7
with: with:
name: windows_artifacts name: windows_artifacts
path: windows_artifacts
- name: Download Ubuntu artifacts - name: Download Ubuntu artifacts
uses: actions/download-artifact@v1 uses: actions/download-artifact@v4.1.7
with: with:
name: ubuntu_artifacts name: linux_artifacts
path: linux_artifacts
- name: Download macOS artifacts - name: Download macOS artifacts
uses: actions/download-artifact@v1 uses: actions/download-artifact@v4.1.7
with: with:
name: macos_artifacts name: macos_artifacts
path: macos_artifacts
- name: Download macOS arm artifacts - name: Download macOS arm artifacts
uses: actions/download-artifact@v1 uses: actions/download-artifact@v4.1.7
with: with:
name: macos_arm_artifacts name: macos_arm_artifacts
path: macos_arm_artifacts
- name: Debug
run: |
tree -L 2
- name: Create archives and upload - name: Create archives and upload
shell: bash shell: bash
@@ -187,9 +213,10 @@ jobs:
BUCKET: ${{ secrets.B2_BUCKET }} BUCKET: ${{ secrets.B2_BUCKET }}
DAYS_TO_KEEP: ${{ secrets.B2_DAYS_TO_KEEP }} DAYS_TO_KEEP: ${{ secrets.B2_DAYS_TO_KEEP }}
run: | run: |
file linux_artifacts/dist.tar.gz
python3 ci/nightly.py artifact windows-amd64 windows_artifacts/ 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 linux-amd64 linux_artifacts/dist.tar.gz
python3 ci/nightly.py artifact macos-amd64 macos_artifacts/dist.zip python3 ci/nightly.py artifact macos-amd64 macos_artifacts/dist.tar.gz
python3 ci/nightly.py artifact macos-arm64 macos_arm_artifacts/dist.zip python3 ci/nightly.py artifact macos-arm64 macos_arm_artifacts/dist.tar.gz
python3 ci/nightly.py prune python3 ci/nightly.py prune
python3 ci/nightly.py json python3 ci/nightly.py json
+3 -1
View File
@@ -1,5 +1,5 @@
// This is purely for documentation // This is purely for documentation
//+build ignore #+build ignore
package intrinsics package intrinsics
// Package-Related // Package-Related
@@ -219,6 +219,8 @@ type_map_cell_info :: proc($T: typeid) -> ^runtime.Map_Cell_Info ---
type_convert_variants_to_pointers :: proc($T: typeid) -> typeid where type_is_union(T) --- type_convert_variants_to_pointers :: proc($T: typeid) -> typeid where type_is_union(T) ---
type_merge :: proc($U, $V: typeid) -> typeid where type_is_union(U), type_is_union(V) --- type_merge :: proc($U, $V: typeid) -> typeid where type_is_union(U), type_is_union(V) ---
type_has_shared_fields :: proc($U, $V: typeid) -> bool typeid where type_is_struct(U), type_is_struct(V) ---
constant_utf16_cstring :: proc($literal: string) -> [^]u16 --- constant_utf16_cstring :: proc($literal: string) -> [^]u16 ---
constant_log2 :: proc($v: $T) -> T where type_is_integer(T) --- constant_log2 :: proc($v: $T) -> T where type_is_integer(T) ---
+30 -1
View File
@@ -18,7 +18,7 @@
// This could change at a later date if the all these data structures are // This could change at a later date if the all these data structures are
// implemented within the compiler rather than in this "preload" file // implemented within the compiler rather than in this "preload" file
// //
//+no-instrumentation #+no-instrumentation
package runtime package runtime
import "base:intrinsics" import "base:intrinsics"
@@ -546,10 +546,23 @@ Odin_OS_Type :: type_of(ODIN_OS)
arm64, arm64,
wasm32, wasm32,
wasm64p32, wasm64p32,
riscv64,
} }
*/ */
Odin_Arch_Type :: type_of(ODIN_ARCH) Odin_Arch_Type :: type_of(ODIN_ARCH)
Odin_Arch_Types :: bit_set[Odin_Arch_Type]
ALL_ODIN_ARCH_TYPES :: Odin_Arch_Types{
.amd64,
.i386,
.arm32,
.arm64,
.wasm32,
.wasm64p32,
.riscv64,
}
/* /*
// Defined internally by the compiler // Defined internally by the compiler
Odin_Build_Mode_Type :: enum int { Odin_Build_Mode_Type :: enum int {
@@ -573,6 +586,22 @@ Odin_Build_Mode_Type :: type_of(ODIN_BUILD_MODE)
*/ */
Odin_Endian_Type :: type_of(ODIN_ENDIAN) Odin_Endian_Type :: type_of(ODIN_ENDIAN)
Odin_OS_Types :: bit_set[Odin_OS_Type]
ALL_ODIN_OS_TYPES :: Odin_OS_Types{
.Windows,
.Darwin,
.Linux,
.Essence,
.FreeBSD,
.OpenBSD,
.NetBSD,
.Haiku,
.WASI,
.JS,
.Orca,
.Freestanding,
}
/* /*
// Defined internally by the compiler // Defined internally by the compiler
+12 -12
View File
@@ -68,7 +68,7 @@ copy :: proc{copy_slice, copy_from_string}
// Note: If you want 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. // Note: If the index is out of bounds, this procedure will panic.
@builtin @builtin
unordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_location) #no_bounds_check { unordered_remove :: proc(array: ^$D/[dynamic]$T, #any_int index: int, loc := #caller_location) #no_bounds_check {
bounds_check_error_loc(loc, index, len(array)) bounds_check_error_loc(loc, index, len(array))
n := len(array)-1 n := len(array)-1
if index != n { if index != n {
@@ -82,7 +82,7 @@ unordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_loca
// Note: If the elements do not have to remain in their order, prefer `unordered_remove`. // Note: If the elements do not have to remain in their order, prefer `unordered_remove`.
// Note: If the index is out of bounds, this procedure will panic. // Note: If the index is out of bounds, this procedure will panic.
@builtin @builtin
ordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_location) #no_bounds_check { ordered_remove :: proc(array: ^$D/[dynamic]$T, #any_int index: int, loc := #caller_location) #no_bounds_check {
bounds_check_error_loc(loc, index, len(array)) bounds_check_error_loc(loc, index, len(array))
if index+1 < len(array) { if index+1 < len(array) {
copy(array[index:], array[index+1:]) copy(array[index:], array[index+1:])
@@ -95,7 +95,7 @@ ordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_locati
// Note: This is an O(N) operation. // Note: This is an O(N) operation.
// Note: If the range is out of bounds, this procedure will panic. // Note: If the range is out of bounds, this procedure will panic.
@builtin @builtin
remove_range :: proc(array: ^$D/[dynamic]$T, lo, hi: int, loc := #caller_location) #no_bounds_check { remove_range :: proc(array: ^$D/[dynamic]$T, #any_int lo, hi: int, loc := #caller_location) #no_bounds_check {
slice_expr_error_lo_hi_loc(loc, lo, hi, len(array)) slice_expr_error_lo_hi_loc(loc, lo, hi, len(array))
n := max(hi-lo, 0) n := max(hi-lo, 0)
if n > 0 { if n > 0 {
@@ -602,7 +602,7 @@ append_nothing :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (n: i
@builtin @builtin
inject_at_elem :: proc(array: ^$T/[dynamic]$E, index: int, #no_broadcast arg: E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error { inject_at_elem :: proc(array: ^$T/[dynamic]$E, #any_int index: int, #no_broadcast arg: E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
if array == nil { if array == nil {
return return
} }
@@ -620,7 +620,7 @@ inject_at_elem :: proc(array: ^$T/[dynamic]$E, index: int, #no_broadcast arg: E,
} }
@builtin @builtin
inject_at_elems :: proc(array: ^$T/[dynamic]$E, index: int, #no_broadcast args: ..E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error { inject_at_elems :: proc(array: ^$T/[dynamic]$E, #any_int index: int, #no_broadcast args: ..E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
if array == nil { if array == nil {
return return
} }
@@ -643,7 +643,7 @@ inject_at_elems :: proc(array: ^$T/[dynamic]$E, index: int, #no_broadcast args:
} }
@builtin @builtin
inject_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, index: int, arg: string, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error { inject_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, #any_int index: int, arg: string, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
if array == nil { if array == nil {
return return
} }
@@ -668,7 +668,7 @@ inject_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, index: int, arg: string
@builtin @builtin
assign_at_elem :: proc(array: ^$T/[dynamic]$E, index: int, arg: E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error { assign_at_elem :: proc(array: ^$T/[dynamic]$E, #any_int index: int, arg: E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
if index < len(array) { if index < len(array) {
array[index] = arg array[index] = arg
ok = true ok = true
@@ -682,7 +682,7 @@ assign_at_elem :: proc(array: ^$T/[dynamic]$E, index: int, arg: E, loc := #calle
@builtin @builtin
assign_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 { assign_at_elems :: proc(array: ^$T/[dynamic]$E, #any_int index: int, #no_broadcast args: ..E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
new_size := index + len(args) new_size := index + len(args)
if len(args) == 0 { if len(args) == 0 {
ok = true ok = true
@@ -699,7 +699,7 @@ assign_at_elems :: proc(array: ^$T/[dynamic]$E, index: int, #no_broadcast args:
@builtin @builtin
assign_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, index: int, arg: string, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error { assign_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, #any_int index: int, arg: string, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
new_size := index + len(arg) new_size := index + len(arg)
if len(arg) == 0 { if len(arg) == 0 {
ok = true ok = true
@@ -838,7 +838,7 @@ non_zero_resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int length: i
Note: Prefer the procedure group `shrink` Note: Prefer the procedure group `shrink`
*/ */
shrink_dynamic_array :: proc(array: ^$T/[dynamic]$E, new_cap := -1, loc := #caller_location) -> (did_shrink: bool, err: Allocator_Error) { shrink_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int new_cap := -1, loc := #caller_location) -> (did_shrink: bool, err: Allocator_Error) {
return _shrink_dynamic_array((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), new_cap, loc) return _shrink_dynamic_array((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), new_cap, loc)
} }
@@ -913,7 +913,7 @@ card :: proc "contextless" (s: $S/bit_set[$E; $U]) -> int {
@builtin @builtin
@(disabled=ODIN_DISABLE_ASSERT) @(disabled=ODIN_DISABLE_ASSERT)
assert :: proc(condition: bool, message := "", loc := #caller_location) { assert :: proc(condition: bool, message := #caller_expression(condition), loc := #caller_location) {
if !condition { if !condition {
// NOTE(bill): This is wrapped in a procedure call // NOTE(bill): This is wrapped in a procedure call
// to improve performance to make the CPU not // to improve performance to make the CPU not
@@ -952,7 +952,7 @@ unimplemented :: proc(message := "", loc := #caller_location) -> ! {
@builtin @builtin
@(disabled=ODIN_DISABLE_ASSERT) @(disabled=ODIN_DISABLE_ASSERT)
assert_contextless :: proc "contextless" (condition: bool, message := "", loc := #caller_location) { assert_contextless :: proc "contextless" (condition: bool, message := #caller_expression(condition), loc := #caller_location) {
if !condition { if !condition {
// NOTE(bill): This is wrapped in a procedure call // NOTE(bill): This is wrapped in a procedure call
// to improve performance to make the CPU not // to improve performance to make the CPU not
+8 -8
View File
@@ -76,7 +76,7 @@ raw_soa_footer :: proc{
@(builtin, require_results) @(builtin, require_results)
make_soa_aligned :: proc($T: typeid/#soa[]$E, length: int, alignment: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_allocator_error { make_soa_aligned :: proc($T: typeid/#soa[]$E, #any_int length, alignment: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_allocator_error {
if length <= 0 { if length <= 0 {
return return
} }
@@ -135,7 +135,7 @@ make_soa_aligned :: proc($T: typeid/#soa[]$E, length: int, alignment: int, alloc
} }
@(builtin, require_results) @(builtin, require_results)
make_soa_slice :: proc($T: typeid/#soa[]$E, length: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_allocator_error { make_soa_slice :: proc($T: typeid/#soa[]$E, #any_int length: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_allocator_error {
return make_soa_aligned(T, length, align_of(E), allocator, loc) return make_soa_aligned(T, length, align_of(E), allocator, loc)
} }
@@ -172,7 +172,7 @@ make_soa :: proc{
@builtin @builtin
resize_soa :: proc(array: ^$T/#soa[dynamic]$E, length: int, loc := #caller_location) -> Allocator_Error { resize_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int length: int, loc := #caller_location) -> Allocator_Error {
if array == nil { if array == nil {
return nil return nil
} }
@@ -183,7 +183,7 @@ resize_soa :: proc(array: ^$T/#soa[dynamic]$E, length: int, loc := #caller_locat
} }
@builtin @builtin
non_zero_resize_soa :: proc(array: ^$T/#soa[dynamic]$E, length: int, loc := #caller_location) -> Allocator_Error { non_zero_resize_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int length: int, loc := #caller_location) -> Allocator_Error {
if array == nil { if array == nil {
return nil return nil
} }
@@ -194,12 +194,12 @@ non_zero_resize_soa :: proc(array: ^$T/#soa[dynamic]$E, length: int, loc := #cal
} }
@builtin @builtin
reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, loc := #caller_location) -> Allocator_Error { reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int capacity: int, loc := #caller_location) -> Allocator_Error {
return _reserve_soa(array, capacity, true, loc) return _reserve_soa(array, capacity, true, loc)
} }
@builtin @builtin
non_zero_reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, loc := #caller_location) -> Allocator_Error { non_zero_reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int capacity: int, loc := #caller_location) -> Allocator_Error {
return _reserve_soa(array, capacity, false, loc) return _reserve_soa(array, capacity, false, loc)
} }
@@ -484,7 +484,7 @@ into_dynamic_soa :: proc(array: $T/#soa[]$E) -> #soa[dynamic]E {
// Note: If you the elements to remain in their order, use `ordered_remove_soa`. // Note: If you the elements to remain in their order, use `ordered_remove_soa`.
// Note: If the index is out of bounds, this procedure will panic. // Note: If the index is out of bounds, this procedure will panic.
@builtin @builtin
unordered_remove_soa :: proc(array: ^$T/#soa[dynamic]$E, index: int, loc := #caller_location) #no_bounds_check { unordered_remove_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int index: int, loc := #caller_location) #no_bounds_check {
bounds_check_error_loc(loc, index, len(array)) bounds_check_error_loc(loc, index, len(array))
if index+1 < len(array) { if index+1 < len(array) {
ti := type_info_of(typeid_of(T)) ti := type_info_of(typeid_of(T))
@@ -512,7 +512,7 @@ unordered_remove_soa :: proc(array: ^$T/#soa[dynamic]$E, index: int, loc := #cal
// Note: If you the elements do not have to remain in their order, prefer `unordered_remove_soa`. // Note: If 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. // Note: If the index is out of bounds, this procedure will panic.
@builtin @builtin
ordered_remove_soa :: proc(array: ^$T/#soa[dynamic]$E, index: int, loc := #caller_location) #no_bounds_check { ordered_remove_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int index: int, loc := #caller_location) #no_bounds_check {
bounds_check_error_loc(loc, index, len(array)) bounds_check_error_loc(loc, index, len(array))
if index+1 < len(array) { if index+1 < len(array) {
ti := type_info_of(typeid_of(T)) ti := type_info_of(typeid_of(T))
+2 -2
View File
@@ -1,8 +1,8 @@
package runtime package runtime
nil_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, nil_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
size, alignment: int, size, alignment: int,
old_memory: rawptr, old_size: int, loc := #caller_location) -> ([]byte, Allocator_Error) { old_memory: rawptr, old_size: int, loc := #caller_location) -> ([]byte, Allocator_Error) {
switch mode { switch mode {
case .Alloc, .Alloc_Non_Zeroed: case .Alloc, .Alloc_Non_Zeroed:
return nil, .Out_Of_Memory return nil, .Out_Of_Memory
+3 -3
View File
@@ -1,6 +1,6 @@
//+private #+private
//+build linux, darwin, freebsd, openbsd, netbsd, haiku #+build linux, darwin, freebsd, openbsd, netbsd, haiku
//+no-instrumentation #+no-instrumentation
package runtime package runtime
import "base:intrinsics" import "base:intrinsics"
+3 -3
View File
@@ -1,6 +1,6 @@
//+private #+private
//+build wasm32, wasm64p32 #+build wasm32, wasm64p32
//+no-instrumentation #+no-instrumentation
package runtime package runtime
import "base:intrinsics" import "base:intrinsics"
+3 -3
View File
@@ -1,6 +1,6 @@
//+private #+private
//+build windows #+build windows
//+no-instrumentation #+no-instrumentation
package runtime package runtime
import "base:intrinsics" import "base:intrinsics"
+12 -10
View File
@@ -20,25 +20,27 @@ heap_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
// //
aligned_alloc :: proc(size, alignment: int, old_ptr: rawptr, old_size: int, zero_memory := true) -> ([]byte, Allocator_Error) { aligned_alloc :: proc(size, alignment: int, old_ptr: rawptr, old_size: int, zero_memory := true) -> ([]byte, Allocator_Error) {
// Not(flysand): We need to reserve enough space for alignment, which
// includes the user data itself, the space to store the pointer to
// allocation start, as well as the padding required to align both
// the user data and the pointer.
a := max(alignment, align_of(rawptr)) a := max(alignment, align_of(rawptr))
space := size + a - 1 space := a-1 + size_of(rawptr) + size
allocated_mem: rawptr allocated_mem: rawptr
force_copy := old_ptr != nil && a > align_of(rawptr) force_copy := old_ptr != nil && alignment > align_of(rawptr)
if !force_copy && old_ptr != nil { if old_ptr != nil && !force_copy {
original_old_ptr := ([^]rawptr)(old_ptr)[-1] original_old_ptr := ([^]rawptr)(old_ptr)[-1]
allocated_mem = heap_resize(original_old_ptr, space+size_of(rawptr)) allocated_mem = heap_resize(original_old_ptr, space)
} else { } else {
allocated_mem = heap_alloc(space+size_of(rawptr), zero_memory) allocated_mem = heap_alloc(space, zero_memory)
} }
aligned_mem := rawptr(([^]u8)(allocated_mem)[size_of(rawptr):]) aligned_mem := rawptr(([^]u8)(allocated_mem)[size_of(rawptr):])
ptr := uintptr(aligned_mem) ptr := uintptr(aligned_mem)
aligned_ptr := (ptr - 1 + uintptr(a)) & -uintptr(a) aligned_ptr := (ptr + uintptr(a)-1) & ~(uintptr(a)-1)
diff := int(aligned_ptr - ptr) if allocated_mem == nil {
if (size + diff) > space || allocated_mem == nil {
aligned_free(old_ptr) aligned_free(old_ptr)
aligned_free(allocated_mem) aligned_free(allocated_mem)
return nil, .Out_Of_Memory return nil, .Out_Of_Memory
@@ -48,7 +50,7 @@ heap_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
([^]rawptr)(aligned_mem)[-1] = allocated_mem ([^]rawptr)(aligned_mem)[-1] = allocated_mem
if force_copy { if force_copy {
mem_copy_non_overlapping(aligned_mem, old_ptr, old_size) mem_copy_non_overlapping(aligned_mem, old_ptr, min(old_size, size))
aligned_free(old_ptr) aligned_free(old_ptr)
} }
+2 -2
View File
@@ -1,5 +1,5 @@
//+build orca #+build orca
//+private #+private
package runtime package runtime
foreign { foreign {
+2 -2
View File
@@ -1,5 +1,5 @@
//+build js, wasi, freestanding, essence #+build js, wasi, freestanding, essence
//+private #+private
package runtime package runtime
_heap_alloc :: proc "contextless" (size: int, zero_memory := true) -> rawptr { _heap_alloc :: proc "contextless" (size: int, zero_memory := true) -> rawptr {
+2 -2
View File
@@ -1,5 +1,5 @@
//+build linux, darwin, freebsd, openbsd, netbsd, haiku #+build linux, darwin, freebsd, openbsd, netbsd, haiku
//+private #+private
package runtime package runtime
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
+8 -5
View File
@@ -1,4 +1,4 @@
//+vet !cast #+vet !cast
package runtime package runtime
import "base:intrinsics" import "base:intrinsics"
@@ -118,16 +118,15 @@ mem_copy_non_overlapping :: proc "contextless" (dst, src: rawptr, len: int) -> r
DEFAULT_ALIGNMENT :: 2*align_of(rawptr) DEFAULT_ALIGNMENT :: 2*align_of(rawptr)
mem_alloc_bytes :: #force_inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) { mem_alloc_bytes :: #force_inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) {
if size == 0 { assert(is_power_of_two_int(alignment), "Alignment must be a power of two", loc)
return nil, nil if size == 0 || allocator.procedure == nil{
}
if allocator.procedure == nil {
return nil, nil return nil, nil
} }
return allocator.procedure(allocator.data, .Alloc, size, alignment, nil, 0, loc) return allocator.procedure(allocator.data, .Alloc, size, alignment, nil, 0, loc)
} }
mem_alloc :: #force_inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) { mem_alloc :: #force_inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) {
assert(is_power_of_two_int(alignment), "Alignment must be a power of two", loc)
if size == 0 || allocator.procedure == nil { if size == 0 || allocator.procedure == nil {
return nil, nil return nil, nil
} }
@@ -135,6 +134,7 @@ mem_alloc :: #force_inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, a
} }
mem_alloc_non_zeroed :: #force_inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) { mem_alloc_non_zeroed :: #force_inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) {
assert(is_power_of_two_int(alignment), "Alignment must be a power of two", loc)
if size == 0 || allocator.procedure == nil { if size == 0 || allocator.procedure == nil {
return nil, nil return nil, nil
} }
@@ -174,6 +174,7 @@ mem_free_all :: #force_inline proc(allocator := context.allocator, loc := #calle
} }
_mem_resize :: #force_inline proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, should_zero: bool, loc := #caller_location) -> (data: []byte, err: Allocator_Error) { _mem_resize :: #force_inline proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, should_zero: bool, loc := #caller_location) -> (data: []byte, err: Allocator_Error) {
assert(is_power_of_two_int(alignment), "Alignment must be a power of two", loc)
if allocator.procedure == nil { if allocator.procedure == nil {
return nil, nil return nil, nil
} }
@@ -215,9 +216,11 @@ _mem_resize :: #force_inline proc(ptr: rawptr, old_size, new_size: int, alignmen
} }
mem_resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> (data: []byte, err: Allocator_Error) { mem_resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> (data: []byte, err: Allocator_Error) {
assert(is_power_of_two_int(alignment), "Alignment must be a power of two", loc)
return _mem_resize(ptr, old_size, new_size, alignment, allocator, true, loc) return _mem_resize(ptr, old_size, new_size, alignment, allocator, true, loc)
} }
non_zero_mem_resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> (data: []byte, err: Allocator_Error) { non_zero_mem_resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> (data: []byte, err: Allocator_Error) {
assert(is_power_of_two_int(alignment), "Alignment must be a power of two", loc)
return _mem_resize(ptr, old_size, new_size, alignment, allocator, false, loc) return _mem_resize(ptr, old_size, new_size, alignment, allocator, false, loc)
} }
+2 -2
View File
@@ -1,5 +1,5 @@
//+build freebsd, openbsd, netbsd #+build freebsd, openbsd, netbsd
//+private #+private
package runtime package runtime
foreign import libc "system:c" foreign import libc "system:c"
+2 -2
View File
@@ -1,5 +1,5 @@
//+build darwin #+build darwin
//+private #+private
package runtime package runtime
import "base:intrinsics" import "base:intrinsics"
+2 -2
View File
@@ -1,5 +1,5 @@
//+build freestanding #+build freestanding
//+private #+private
package runtime package runtime
// TODO(bill): reimplement `os.write` // TODO(bill): reimplement `os.write`
+2 -2
View File
@@ -1,5 +1,5 @@
//+build haiku #+build haiku
//+private #+private
package runtime package runtime
foreign import libc "system:c" foreign import libc "system:c"
+2 -2
View File
@@ -1,5 +1,5 @@
//+build js #+build js
//+private #+private
package runtime package runtime
foreign import "odin_env" foreign import "odin_env"
+1 -1
View File
@@ -1,4 +1,4 @@
//+private #+private
package runtime package runtime
import "base:intrinsics" import "base:intrinsics"
+2 -2
View File
@@ -1,5 +1,5 @@
//+build orca #+build orca
//+private #+private
package runtime package runtime
import "base:intrinsics" import "base:intrinsics"
+2 -2
View File
@@ -1,5 +1,5 @@
//+build wasi #+build wasi
//+private #+private
package runtime package runtime
foreign import wasi "wasi_snapshot_preview1" foreign import wasi "wasi_snapshot_preview1"
+2 -2
View File
@@ -1,5 +1,5 @@
//+build windows #+build windows
//+private #+private
package runtime package runtime
foreign import kernel32 "system:Kernel32.lib" foreign import kernel32 "system:Kernel32.lib"
+1 -1
View File
@@ -1,4 +1,4 @@
//+private #+private
package runtime package runtime
foreign import "system:Foundation.framework" foreign import "system:Foundation.framework"
+1 -1
View File
@@ -1,4 +1,4 @@
//+build js #+build js
package runtime package runtime
init_default_context_for_js: Context init_default_context_for_js: Context
+42 -20
View File
@@ -1,4 +1,4 @@
//+build wasm32, wasm64p32 #+build wasm32, wasm64p32
package runtime package runtime
@(private="file") @(private="file")
@@ -14,33 +14,57 @@ ti_uint :: struct #raw_union {
} }
@(link_name="__ashlti3", linkage="strong") @(link_name="__ashlti3", linkage="strong")
__ashlti3 :: proc "contextless" (la, ha: u64, b_: u32) -> i128 { __ashlti3 :: proc "contextless" (a: i128, b: u32) -> i128 {
bits_in_dword :: size_of(u32)*8 bits :: 64
b := u32(b_)
input, result: ti_int input: ti_int = ---
input.lo, input.hi = la, ha result: ti_int = ---
if b & bits_in_dword != 0 { input.all = a
if b & bits != 0 {
result.lo = 0 result.lo = 0
result.hi = input.lo << (b-bits_in_dword) result.hi = input.lo << (b-bits)
} else { } else {
if b == 0 { if b == 0 {
return input.all return a
} }
result.lo = input.lo<<b result.lo = input.lo<<b
result.hi = (input.hi<<b) | (input.lo>>(bits_in_dword-b)) result.hi = (input.hi<<b) | (input.lo>>(bits-b))
} }
return result.all return result.all
} }
__ashlti3_unsigned :: proc "contextless" (a: u128, b: u32) -> u128 {
return cast(u128)__ashlti3(cast(i128)a, b)
}
@(link_name="__mulddi3", linkage="strong")
__mulddi3 :: proc "contextless" (a, b: u64) -> i128 {
r: ti_int
bits :: 32
mask :: ~u64(0) >> bits
r.lo = (a & mask) * (b & mask)
t := r.lo >> bits
r.lo &= mask
t += (a >> bits) * (b & mask)
r.lo += (t & mask) << bits
r.hi = t >> bits
t = r.lo >> bits
r.lo &= mask
t += (b >> bits) * (a & mask)
r.lo += (t & mask) << bits
r.hi += t >> bits
r.hi += (a >> bits) * (b >> bits)
return r.all
}
@(link_name="__multi3", linkage="strong") @(link_name="__multi3", linkage="strong")
__multi3 :: proc "contextless" (la, ha, lb, hb: u64) -> i128 { __multi3 :: proc "contextless" (a, b: i128) -> i128 {
x, y, r: ti_int x, y, r: ti_int
x.lo, x.hi = la, ha x.all = a
y.lo, y.hi = lb, hb y.all = b
r.all = i128(x.lo * y.lo) // TODO this is incorrect r.all = __mulddi3(x.lo, y.lo)
r.hi += x.hi*y.lo + x.lo*y.hi r.hi += x.hi*y.lo + x.lo*y.hi
return r.all return r.all
} }
@@ -54,18 +78,16 @@ udivti3 :: proc "c" (la, ha, lb, hb: u64) -> u128 {
} }
@(link_name="__lshrti3", linkage="strong") @(link_name="__lshrti3", linkage="strong")
__lshrti3 :: proc "c" (la, ha: u64, b: u32) -> i128 { __lshrti3 :: proc "c" (a: i128, b: u32) -> i128 {
bits :: size_of(u32)*8 bits :: 64
input, result: ti_int input, result: ti_int
input.lo = la input.all = a
input.hi = ha
if b & bits != 0 { if b & bits != 0 {
result.hi = 0 result.hi = 0
result.lo = input.hi >> (b - bits) result.lo = input.hi >> (b - bits)
} else if b == 0 { } else if b == 0 {
return input.all return a
} else { } else {
result.hi = input.hi >> b result.hi = input.hi >> b
result.lo = (input.hi << (bits - b)) | (input.lo >> b) result.lo = (input.hi << (bits - b)) | (input.lo >> b)
+2 -2
View File
@@ -1,5 +1,5 @@
//+private #+private
//+no-instrumentation #+no-instrumentation
package runtime package runtime
foreign import kernel32 "system:Kernel32.lib" foreign import kernel32 "system:Kernel32.lib"
+2 -2
View File
@@ -1,5 +1,5 @@
//+private #+private
//+no-instrumentation #+no-instrumentation
package runtime package runtime
@require foreign import "system:int64.lib" @require foreign import "system:int64.lib"
+34
View File
@@ -0,0 +1,34 @@
package runtime
Thread_Local_Cleaner :: #type proc "odin" ()
@(private="file")
thread_local_cleaners: [8]Thread_Local_Cleaner
// Add a procedure that will be run at the end of a thread for the purpose of
// deallocating state marked as `thread_local`.
//
// Intended to be called in an `init` procedure of a package with
// dynamically-allocated memory that is stored in `thread_local` variables.
add_thread_local_cleaner :: proc "contextless" (p: Thread_Local_Cleaner) {
for &v in thread_local_cleaners {
if v == nil {
v = p
return
}
}
panic_contextless("There are no more thread-local cleaner slots available.")
}
// Run all of the thread-local cleaner procedures.
//
// Intended to be called by the internals of a threading API at the end of a
// thread's lifetime.
run_thread_local_cleaners :: proc "odin" () {
for p in thread_local_cleaners {
if p == nil {
break
}
p()
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
//+build wasm32, wasm64p32 #+build wasm32, wasm64p32
package runtime package runtime
import "base:intrinsics" import "base:intrinsics"
+19
View File
@@ -0,0 +1,19 @@
#!/usr/bin/env sh
# Intended for use in Alpine containers, see the "nightly" Github action for a list of dependencies
CXX="clang++-18"
LLVM_CONFIG="llvm-config-18"
DISABLED_WARNINGS="-Wno-switch -Wno-macro-redefined -Wno-unused-value"
CPPFLAGS="-DODIN_VERSION_RAW=\"dev-$(date +"%Y-%m")\""
CXXFLAGS="-std=c++14 $($LLVM_CONFIG --cxxflags --ldflags)"
LDFLAGS="-static -lm -lzstd -lz -lffi -pthread -ldl -fuse-ld=mold"
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --link-static --ldflags --libs --system-libs --libfiles)"
LDFLAGS="$LDFLAGS -Wl,-rpath=\$ORIGIN"
EXTRAFLAGS="-DNIGHTLY -O3"
set -x
$CXX src/main.cpp src/libtommath.cpp $DISABLED_WARNINGS $CPPFLAGS $CXXFLAGS $EXTRAFLAGS $LDFLAGS -o odin
+23 -18
View File
@@ -2,7 +2,7 @@ import os
import sys import sys
from zipfile import ZipFile, ZIP_DEFLATED from zipfile import ZipFile, ZIP_DEFLATED
from b2sdk.v2 import InMemoryAccountInfo, B2Api from b2sdk.v2 import InMemoryAccountInfo, B2Api
from datetime import datetime from datetime import datetime, timezone
import json import json
UPLOAD_FOLDER = "nightly/" UPLOAD_FOLDER = "nightly/"
@@ -22,7 +22,7 @@ def auth() -> bool:
pass # Not yet authenticated pass # Not yet authenticated
err = b2_api.authorize_account("production", application_key_id, application_key) err = b2_api.authorize_account("production", application_key_id, application_key)
return err == None return err is None
def get_bucket(): def get_bucket():
if not auth(): sys.exit(1) if not auth(): sys.exit(1)
@@ -32,30 +32,35 @@ def remove_prefix(text: str, prefix: str) -> str:
return text[text.startswith(prefix) and len(prefix):] return text[text.startswith(prefix) and len(prefix):]
def create_and_upload_artifact_zip(platform: str, artifact: str) -> int: def create_and_upload_artifact_zip(platform: str, artifact: str) -> int:
now = datetime.utcnow().replace(hour=0, minute=0, second=0, microsecond=0) now = datetime.now(timezone.utc).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 source_archive: str
if not artifact.endswith(".zip"): destination_name = f'odin-{platform}-nightly+{now.strftime("%Y-%m-%d")}'
print(f"Creating archive {destination_zip_name} from {artifact} and uploading to {bucket_name}")
source_zip_name = destination_zip_name if platform.startswith("linux") or platform.startswith("macos"):
with ZipFile(source_zip_name, mode='w', compression=ZIP_DEFLATED, compresslevel=9) as z: destination_name += ".tar.gz"
source_archive = artifact
else:
destination_name += ".zip"
source_archive = destination_name
print(f"Creating archive {destination_name} from {artifact} and uploading to {bucket_name}")
with ZipFile(source_archive, mode='w', compression=ZIP_DEFLATED, compresslevel=9) as z:
for root, directory, filenames in os.walk(artifact): for root, directory, filenames in os.walk(artifact):
for file in filenames: for file in filenames:
file_path = os.path.join(root, file) file_path = os.path.join(root, file)
zip_path = os.path.join("dist", os.path.relpath(file_path, artifact)) zip_path = os.path.join("dist", os.path.relpath(file_path, artifact))
z.write(file_path, zip_path) z.write(file_path, zip_path)
if not os.path.exists(source_zip_name): if not os.path.exists(source_archive):
print(f"Error: Newly created ZIP archive {source_zip_name} not found.") print(f"Error: archive {source_archive} not found.")
return 1 return 1
print("Uploading {} to {}".format(source_zip_name, UPLOAD_FOLDER + destination_zip_name)) print("Uploading {} to {}".format(source_archive, UPLOAD_FOLDER + destination_name))
bucket = get_bucket() bucket = get_bucket()
res = bucket.upload_local_file( res = bucket.upload_local_file(
source_zip_name, # Local file to upload source_archive, # Local file to upload
"nightly/" + destination_zip_name, # B2 destination path "nightly/" + destination_name, # B2 destination path
) )
return 0 return 0
@@ -65,8 +70,8 @@ def prune_artifacts():
bucket = get_bucket() bucket = get_bucket()
for file, _ in bucket.ls(UPLOAD_FOLDER, latest_only=False): for file, _ in bucket.ls(UPLOAD_FOLDER, latest_only=False):
# Timestamp is in milliseconds # Timestamp is in milliseconds
date = datetime.fromtimestamp(file.upload_timestamp / 1_000.0).replace(hour=0, minute=0, second=0, microsecond=0) date = datetime.fromtimestamp(file.upload_timestamp / 1_000.0, tz=timezone.utc).replace(hour=0, minute=0, second=0, microsecond=0)
now = datetime.utcnow().replace(hour=0, minute=0, second=0, microsecond=0) now = datetime.now(timezone.utc).replace(hour=0, minute=0, second=0, microsecond=0)
delta = now - date delta = now - date
if delta.days > int(days_to_keep): if delta.days > int(days_to_keep):
@@ -100,7 +105,7 @@ def update_nightly_json():
'sizeInBytes': size, 'sizeInBytes': size,
}) })
now = datetime.utcnow().isoformat() now = datetime.now(timezone.utc).isoformat()
nightly = json.dumps({ nightly = json.dumps({
'last_updated' : now, 'last_updated' : now,
+33 -3
View File
@@ -144,6 +144,9 @@ buffer_grow :: proc(b: ^Buffer, n: int, loc := #caller_location) {
} }
buffer_write_at :: proc(b: ^Buffer, p: []byte, offset: int, loc := #caller_location) -> (n: int, err: io.Error) { buffer_write_at :: proc(b: ^Buffer, p: []byte, offset: int, loc := #caller_location) -> (n: int, err: io.Error) {
if len(p) == 0 {
return 0, nil
}
b.last_read = .Invalid b.last_read = .Invalid
if offset < 0 { if offset < 0 {
err = .Invalid_Offset err = .Invalid_Offset
@@ -246,10 +249,13 @@ buffer_read_ptr :: proc(b: ^Buffer, ptr: rawptr, size: int) -> (n: int, err: io.
} }
buffer_read_at :: proc(b: ^Buffer, p: []byte, offset: int) -> (n: int, err: io.Error) { buffer_read_at :: proc(b: ^Buffer, p: []byte, offset: int) -> (n: int, err: io.Error) {
if len(p) == 0 {
return 0, nil
}
b.last_read = .Invalid b.last_read = .Invalid
if uint(offset) >= len(b.buf) { if uint(offset) >= len(b.buf) {
err = .Invalid_Offset err = .EOF
return return
} }
n = copy(p, b.buf[offset:]) n = copy(p, b.buf[offset:])
@@ -310,6 +316,27 @@ buffer_unread_rune :: proc(b: ^Buffer) -> io.Error {
return nil return nil
} }
buffer_seek :: proc(b: ^Buffer, offset: i64, whence: io.Seek_From) -> (i64, io.Error) {
abs: i64
switch whence {
case .Start:
abs = offset
case .Current:
abs = i64(b.off) + offset
case .End:
abs = i64(len(b.buf)) + offset
case:
return 0, .Invalid_Whence
}
abs_int := int(abs)
if abs_int < 0 {
return 0, .Invalid_Offset
}
b.last_read = .Invalid
b.off = abs_int
return abs, nil
}
buffer_read_bytes :: proc(b: ^Buffer, delim: byte) -> (line: []byte, err: io.Error) { buffer_read_bytes :: proc(b: ^Buffer, delim: byte) -> (line: []byte, err: io.Error) {
i := index_byte(b.buf[b.off:], delim) i := index_byte(b.buf[b.off:], delim)
@@ -395,14 +422,17 @@ _buffer_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offse
return io._i64_err(buffer_write(b, p)) return io._i64_err(buffer_write(b, p))
case .Write_At: case .Write_At:
return io._i64_err(buffer_write_at(b, p, int(offset))) return io._i64_err(buffer_write_at(b, p, int(offset)))
case .Seek:
n, err = buffer_seek(b, offset, whence)
return
case .Size: case .Size:
n = i64(buffer_capacity(b)) n = i64(buffer_length(b))
return return
case .Destroy: case .Destroy:
buffer_destroy(b) buffer_destroy(b)
return return
case .Query: case .Query:
return io.query_utility({.Read, .Read_At, .Write, .Write_At, .Size, .Destroy}) return io.query_utility({.Read, .Read_At, .Write, .Write_At, .Seek, .Size, .Destroy, .Query})
} }
return 0, .Empty return 0, .Empty
} }
+5 -7
View File
@@ -334,7 +334,7 @@ Inputs:
Returns: Returns:
- index: The index of the byte `c`, or -1 if it was not found. - index: The index of the byte `c`, or -1 if it was not found.
*/ */
index_byte :: proc(s: []byte, c: byte) -> (index: int) #no_bounds_check { index_byte :: proc "contextless" (s: []byte, c: byte) -> (index: int) #no_bounds_check {
i, l := 0, len(s) i, l := 0, len(s)
// Guard against small strings. On modern systems, it is ALWAYS // Guard against small strings. On modern systems, it is ALWAYS
@@ -469,18 +469,16 @@ Inputs:
Returns: Returns:
- index: The index of the byte `c`, or -1 if it was not found. - index: The index of the byte `c`, or -1 if it was not found.
*/ */
last_index_byte :: proc(s: []byte, c: byte) -> int #no_bounds_check { last_index_byte :: proc "contextless" (s: []byte, c: byte) -> int #no_bounds_check {
i := len(s) i := len(s)
// Guard against small strings. On modern systems, it is ALWAYS // Guard against small strings. On modern systems, it is ALWAYS
// worth vectorizing assuming there is a hardware vector unit, and // worth vectorizing assuming there is a hardware vector unit, and
// the data size is large enough. // the data size is large enough.
if i < SIMD_REG_SIZE_128 { if i < SIMD_REG_SIZE_128 {
if i > 0 { // Handle s == nil. #reverse for ch, j in s {
for /**/; i >= 0; i -= 1 { if ch == c {
if s[i] == c { return j
return i
}
} }
} }
return -1 return -1
+9 -2
View File
@@ -9,10 +9,11 @@ Reader :: struct {
prev_rune: int, // previous reading index of rune or < 0 prev_rune: int, // previous reading index of rune or < 0
} }
reader_init :: proc(r: ^Reader, s: []byte) { reader_init :: proc(r: ^Reader, s: []byte) -> io.Stream {
r.s = s r.s = s
r.i = 0 r.i = 0
r.prev_rune = -1 r.prev_rune = -1
return reader_to_stream(r)
} }
reader_to_stream :: proc(r: ^Reader) -> (s: io.Stream) { reader_to_stream :: proc(r: ^Reader) -> (s: io.Stream) {
@@ -33,6 +34,9 @@ reader_size :: proc(r: ^Reader) -> i64 {
} }
reader_read :: proc(r: ^Reader, p: []byte) -> (n: int, err: io.Error) { reader_read :: proc(r: ^Reader, p: []byte) -> (n: int, err: io.Error) {
if len(p) == 0 {
return 0, nil
}
if r.i >= i64(len(r.s)) { if r.i >= i64(len(r.s)) {
return 0, .EOF return 0, .EOF
} }
@@ -42,6 +46,9 @@ reader_read :: proc(r: ^Reader, p: []byte) -> (n: int, err: io.Error) {
return return
} }
reader_read_at :: proc(r: ^Reader, p: []byte, off: i64) -> (n: int, err: io.Error) { reader_read_at :: proc(r: ^Reader, p: []byte, off: i64) -> (n: int, err: io.Error) {
if len(p) == 0 {
return 0, nil
}
if off < 0 { if off < 0 {
return 0, .Invalid_Offset return 0, .Invalid_Offset
} }
@@ -97,7 +104,6 @@ reader_unread_rune :: proc(r: ^Reader) -> io.Error {
return nil return nil
} }
reader_seek :: proc(r: ^Reader, offset: i64, whence: io.Seek_From) -> (i64, io.Error) { reader_seek :: proc(r: ^Reader, offset: i64, whence: io.Seek_From) -> (i64, io.Error) {
r.prev_rune = -1
abs: i64 abs: i64
switch whence { switch whence {
case .Start: case .Start:
@@ -114,6 +120,7 @@ reader_seek :: proc(r: ^Reader, offset: i64, whence: io.Seek_From) -> (i64, io.E
return 0, .Invalid_Offset return 0, .Invalid_Offset
} }
r.i = abs r.i = abs
r.prev_rune = -1
return abs, nil return abs, nil
} }
reader_write_to :: proc(r: ^Reader, w: io.Writer) -> (n: i64, err: io.Error) { reader_write_to :: proc(r: ^Reader, w: io.Writer) -> (n: i64, err: io.Error) {
+8
View File
@@ -98,6 +98,14 @@ when ODIN_OS == .Haiku {
ERANGE :: B_POSIX_ERROR_BASE + 17 ERANGE :: B_POSIX_ERROR_BASE + 17
} }
when ODIN_OS == .JS {
_ :: libc
_get_errno :: proc "c" () -> ^int {
@(static) errno: int
return &errno
}
}
// Odin has no way to make an identifier "errno" behave as a function call to // 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 // 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 // error value to errno. To work around this, just expose it as a function like
+25 -1
View File
@@ -89,6 +89,30 @@ when ODIN_OS == .Linux {
} }
} }
when ODIN_OS == .JS {
fpos_t :: struct #raw_union { _: [16]char, _: longlong, _: double, }
_IOFBF :: 0
_IOLBF :: 1
_IONBF :: 2
BUFSIZ :: 1024
EOF :: int(-1)
FOPEN_MAX :: 1000
FILENAME_MAX :: 4096
L_tmpnam :: 20
SEEK_SET :: 0
SEEK_CUR :: 1
SEEK_END :: 2
TMP_MAX :: 308915776
}
when ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD { when ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD {
fpos_t :: distinct i64 fpos_t :: distinct i64
@@ -368,7 +392,7 @@ to_stream :: proc(file: ^FILE) -> io.Stream {
return 0, .Empty return 0, .Empty
case .Query: case .Query:
return io.query_utility({ .Close, .Flush, .Read, .Read_At, .Write, .Write_At, .Seek, .Size }) return io.query_utility({ .Close, .Flush, .Read, .Read_At, .Write, .Write_At, .Seek, .Size, .Query })
} }
return return
} }
+10
View File
@@ -10,6 +10,9 @@ when ODIN_OS == .Windows {
foreign import libc "system:c" foreign import libc "system:c"
} }
@(require)
import "base:runtime"
when ODIN_OS == .Windows { when ODIN_OS == .Windows {
RAND_MAX :: 0x7fff RAND_MAX :: 0x7fff
@@ -145,6 +148,10 @@ aligned_alloc :: #force_inline proc "c" (alignment, size: size_t) -> rawptr {
_aligned_malloc :: proc(size, alignment: size_t) -> rawptr --- _aligned_malloc :: proc(size, alignment: size_t) -> rawptr ---
} }
return _aligned_malloc(size=size, alignment=alignment) return _aligned_malloc(size=size, alignment=alignment)
} else when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
context = runtime.default_context()
data, _ := runtime.mem_alloc_bytes(auto_cast size, auto_cast alignment)
return raw_data(data)
} else { } else {
foreign libc { foreign libc {
aligned_alloc :: proc(alignment, size: size_t) -> rawptr --- aligned_alloc :: proc(alignment, size: size_t) -> rawptr ---
@@ -160,6 +167,9 @@ aligned_free :: #force_inline proc "c" (ptr: rawptr) {
_aligned_free :: proc(ptr: rawptr) --- _aligned_free :: proc(ptr: rawptr) ---
} }
_aligned_free(ptr) _aligned_free(ptr)
} else when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
context = runtime.default_context()
runtime.mem_free(ptr)
} else { } else {
free(ptr) free(ptr)
} }
+1
View File
@@ -12,6 +12,7 @@ when ODIN_OS == .Windows {
foreign import libc "system:c" foreign import libc "system:c"
} }
@(default_calling_convention="c")
foreign libc { foreign libc {
// 7.24.2 Copying functions // 7.24.2 Copying functions
memcpy :: proc(s1, s2: rawptr, n: size_t) -> rawptr --- memcpy :: proc(s1, s2: rawptr, n: size_t) -> rawptr ---
+2 -2
View File
@@ -45,7 +45,7 @@ when ODIN_OS == .Windows {
} }
} }
when ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .Darwin || ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD || ODIN_OS == .Haiku { when ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .Darwin || ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD || ODIN_OS == .Haiku || ODIN_OS == .JS {
@(default_calling_convention="c") @(default_calling_convention="c")
foreign libc { foreign libc {
// 7.27.2 Time manipulation functions // 7.27.2 Time manipulation functions
@@ -79,7 +79,7 @@ when ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .Darwin || ODIN_OS =
} else { } else {
@(private) LDIFFTIME :: "difftime" @(private) LDIFFTIME :: "difftime"
@(private) LMKTIME :: "mktime" @(private) LMKTIME :: "mktime"
@(private) LTIME :: "ltime" @(private) LTIME :: "time"
@(private) LCTIME :: "ctime" @(private) LCTIME :: "ctime"
@(private) LGMTIME :: "gmtime" @(private) LGMTIME :: "gmtime"
@(private) LLOCALTIME :: "localtime" @(private) LLOCALTIME :: "localtime"
+1 -1
View File
@@ -14,7 +14,7 @@ when ODIN_OS == .Windows {
wctrans_t :: distinct wchar_t wctrans_t :: distinct wchar_t
wctype_t :: distinct ushort wctype_t :: distinct ushort
} else when ODIN_OS == .Linux { } else when ODIN_OS == .Linux || ODIN_OS == .JS {
wctrans_t :: distinct intptr_t wctrans_t :: distinct intptr_t
wctype_t :: distinct ulong wctype_t :: distinct ulong
+90
View File
@@ -0,0 +1,90 @@
/*
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license.
List of contributors:
Jeroen van Rijn: Initial implementation.
Ginger Bill: Cosmetic changes.
A small GZIP implementation as an example.
*/
/*
Example:
import "core:bytes"
import "core:os"
import "core:compress"
import "core:fmt"
// Small GZIP file with fextra, fname and fcomment present.
@private
TEST: []u8 = {
0x1f, 0x8b, 0x08, 0x1c, 0xcb, 0x3b, 0x3a, 0x5a,
0x02, 0x03, 0x07, 0x00, 0x61, 0x62, 0x03, 0x00,
0x63, 0x64, 0x65, 0x66, 0x69, 0x6c, 0x65, 0x6e,
0x61, 0x6d, 0x65, 0x00, 0x54, 0x68, 0x69, 0x73,
0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x63, 0x6f,
0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x2b, 0x48,
0xac, 0xcc, 0xc9, 0x4f, 0x4c, 0x01, 0x00, 0x15,
0x6a, 0x2c, 0x42, 0x07, 0x00, 0x00, 0x00,
}
main :: proc() {
// Set up output buffer.
buf := bytes.Buffer{}
stdout :: proc(s: string) {
os.write_string(os.stdout, s)
}
stderr :: proc(s: string) {
os.write_string(os.stderr, s)
}
args := os.args
if len(args) < 2 {
stderr("No input file specified.\n")
err := load(data=TEST, buf=&buf, known_gzip_size=len(TEST))
if err == nil {
stdout("Displaying test vector: ")
stdout(bytes.buffer_to_string(&buf))
stdout("\n")
} else {
fmt.printf("gzip.load returned %v\n", err)
}
bytes.buffer_destroy(&buf)
os.exit(0)
}
// The rest are all files.
args = args[1:]
err: Error
for file in args {
if file == "-" {
// Read from stdin
s := os.stream_from_handle(os.stdin)
ctx := &compress.Context_Stream_Input{
input = s,
}
err = load(ctx, &buf)
} else {
err = load(file, &buf)
}
if err != nil {
if err != E_General.File_Not_Found {
stderr("File not found: ")
stderr(file)
stderr("\n")
os.exit(1)
}
stderr("GZIP returned an error.\n")
bytes.buffer_destroy(&buf)
os.exit(2)
}
stdout(bytes.buffer_to_string(&buf))
}
bytes.buffer_destroy(&buf)
}
*/
package compress_gzip
-89
View File
@@ -1,89 +0,0 @@
//+build ignore
package compress_gzip
/*
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license.
List of contributors:
Jeroen van Rijn: Initial implementation.
Ginger Bill: Cosmetic changes.
A small GZIP implementation as an example.
*/
import "core:bytes"
import "core:os"
import "core:compress"
import "core:fmt"
// Small GZIP file with fextra, fname and fcomment present.
@private
TEST: []u8 = {
0x1f, 0x8b, 0x08, 0x1c, 0xcb, 0x3b, 0x3a, 0x5a,
0x02, 0x03, 0x07, 0x00, 0x61, 0x62, 0x03, 0x00,
0x63, 0x64, 0x65, 0x66, 0x69, 0x6c, 0x65, 0x6e,
0x61, 0x6d, 0x65, 0x00, 0x54, 0x68, 0x69, 0x73,
0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x63, 0x6f,
0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x2b, 0x48,
0xac, 0xcc, 0xc9, 0x4f, 0x4c, 0x01, 0x00, 0x15,
0x6a, 0x2c, 0x42, 0x07, 0x00, 0x00, 0x00,
}
main :: proc() {
// Set up output buffer.
buf := bytes.Buffer{}
stdout :: proc(s: string) {
os.write_string(os.stdout, s)
}
stderr :: proc(s: string) {
os.write_string(os.stderr, s)
}
args := os.args
if len(args) < 2 {
stderr("No input file specified.\n")
err := load(data=TEST, buf=&buf, known_gzip_size=len(TEST))
if err == nil {
stdout("Displaying test vector: ")
stdout(bytes.buffer_to_string(&buf))
stdout("\n")
} else {
fmt.printf("gzip.load returned %v\n", err)
}
bytes.buffer_destroy(&buf)
os.exit(0)
}
// The rest are all files.
args = args[1:]
err: Error
for file in args {
if file == "-" {
// Read from stdin
s := os.stream_from_handle(os.stdin)
ctx := &compress.Context_Stream_Input{
input = s,
}
err = load(ctx, &buf)
} else {
err = load(file, &buf)
}
if err != nil {
if err != E_General.File_Not_Found {
stderr("File not found: ")
stderr(file)
stderr("\n")
os.exit(1)
}
stderr("GZIP returned an error.\n")
bytes.buffer_destroy(&buf)
os.exit(2)
}
stdout(bytes.buffer_to_string(&buf))
}
bytes.buffer_destroy(&buf)
}
-1
View File
@@ -4,7 +4,6 @@
which is an English word model. which is an English word model.
*/ */
// package shoco is an implementation of the shoco short string compressor
package compress_shoco package compress_shoco
DEFAULT_MODEL :: Shoco_Model { DEFAULT_MODEL :: Shoco_Model {
+1 -1
View File
@@ -8,7 +8,7 @@
An implementation of [shoco](https://github.com/Ed-von-Schleck/shoco) by Christian Schramm. An implementation of [shoco](https://github.com/Ed-von-Schleck/shoco) by Christian Schramm.
*/ */
// package shoco is an implementation of the shoco short string compressor // package shoco is an implementation of the shoco short string compressor.
package compress_shoco package compress_shoco
import "base:intrinsics" import "base:intrinsics"
+50
View File
@@ -0,0 +1,50 @@
/*
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license.
List of contributors:
Jeroen van Rijn: Initial implementation.
An example of how to use `zlib.inflate`.
*/
/*
Example:
package main
import "core:bytes"
import "core:fmt"
main :: proc() {
ODIN_DEMO := []u8{
120, 218, 101, 144, 65, 110, 131, 48, 16, 69, 215, 246, 41, 190, 44, 69, 73, 32, 148, 182,
75, 75, 28, 32, 251, 46, 217, 88, 238, 0, 86, 192, 32, 219, 36, 170, 170, 172, 122, 137,
238, 122, 197, 30, 161, 70, 162, 20, 81, 203, 139, 25, 191, 255, 191, 60, 51, 40, 125, 81,
53, 33, 144, 15, 156, 155, 110, 232, 93, 128, 208, 189, 35, 89, 117, 65, 112, 222, 41, 99,
33, 37, 6, 215, 235, 195, 17, 239, 156, 197, 170, 118, 170, 131, 44, 32, 82, 164, 72, 240,
253, 245, 249, 129, 12, 185, 224, 76, 105, 61, 118, 99, 171, 66, 239, 38, 193, 35, 103, 85,
172, 66, 127, 33, 139, 24, 244, 235, 141, 49, 204, 223, 76, 208, 205, 204, 166, 7, 173, 60,
97, 159, 238, 37, 214, 41, 105, 129, 167, 5, 102, 27, 152, 173, 97, 178, 129, 73, 129, 231,
5, 230, 27, 152, 175, 225, 52, 192, 127, 243, 170, 157, 149, 18, 121, 142, 115, 109, 227, 122,
64, 87, 114, 111, 161, 49, 182, 6, 181, 158, 162, 226, 206, 167, 27, 215, 246, 48, 56, 99,
67, 117, 16, 47, 13, 45, 35, 151, 98, 231, 75, 1, 173, 90, 61, 101, 146, 71, 136, 244,
170, 218, 145, 176, 123, 45, 173, 56, 113, 134, 191, 51, 219, 78, 235, 95, 28, 249, 253, 7,
159, 150, 133, 125,
}
OUTPUT_SIZE :: 432
buf: bytes.Buffer
// We can pass ", true" to inflate a raw DEFLATE stream instead of a ZLIB wrapped one.
err := inflate(input=ODIN_DEMO, buf=&buf, expected_output_size=OUTPUT_SIZE)
defer bytes.buffer_destroy(&buf)
if err != nil {
fmt.printf("\nError: %v\n", err)
}
s := bytes.buffer_to_string(&buf)
fmt.printf("Input: %v bytes, output (%v bytes):\n%v\n", len(ODIN_DEMO), len(s), s)
assert(len(s) == OUTPUT_SIZE)
}
*/
package compress_zlib
-47
View File
@@ -1,47 +0,0 @@
//+build ignore
package compress_zlib
/*
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license.
List of contributors:
Jeroen van Rijn: Initial implementation.
An example of how to use `zlib.inflate`.
*/
import "core:bytes"
import "core:fmt"
main :: proc() {
ODIN_DEMO := []u8{
120, 218, 101, 144, 65, 110, 131, 48, 16, 69, 215, 246, 41, 190, 44, 69, 73, 32, 148, 182,
75, 75, 28, 32, 251, 46, 217, 88, 238, 0, 86, 192, 32, 219, 36, 170, 170, 172, 122, 137,
238, 122, 197, 30, 161, 70, 162, 20, 81, 203, 139, 25, 191, 255, 191, 60, 51, 40, 125, 81,
53, 33, 144, 15, 156, 155, 110, 232, 93, 128, 208, 189, 35, 89, 117, 65, 112, 222, 41, 99,
33, 37, 6, 215, 235, 195, 17, 239, 156, 197, 170, 118, 170, 131, 44, 32, 82, 164, 72, 240,
253, 245, 249, 129, 12, 185, 224, 76, 105, 61, 118, 99, 171, 66, 239, 38, 193, 35, 103, 85,
172, 66, 127, 33, 139, 24, 244, 235, 141, 49, 204, 223, 76, 208, 205, 204, 166, 7, 173, 60,
97, 159, 238, 37, 214, 41, 105, 129, 167, 5, 102, 27, 152, 173, 97, 178, 129, 73, 129, 231,
5, 230, 27, 152, 175, 225, 52, 192, 127, 243, 170, 157, 149, 18, 121, 142, 115, 109, 227, 122,
64, 87, 114, 111, 161, 49, 182, 6, 181, 158, 162, 226, 206, 167, 27, 215, 246, 48, 56, 99,
67, 117, 16, 47, 13, 45, 35, 151, 98, 231, 75, 1, 173, 90, 61, 101, 146, 71, 136, 244,
170, 218, 145, 176, 123, 45, 173, 56, 113, 134, 191, 51, 219, 78, 235, 95, 28, 249, 253, 7,
159, 150, 133, 125,
}
OUTPUT_SIZE :: 432
buf: bytes.Buffer
// We can pass ", true" to inflate a raw DEFLATE stream instead of a ZLIB wrapped one.
err := inflate(input=ODIN_DEMO, buf=&buf, expected_output_size=OUTPUT_SIZE)
defer bytes.buffer_destroy(&buf)
if err != nil {
fmt.printf("\nError: %v\n", err)
}
s := bytes.buffer_to_string(&buf)
fmt.printf("Input: %v bytes, output (%v bytes):\n%v\n", len(ODIN_DEMO), len(s), s)
assert(len(s) == OUTPUT_SIZE)
}
+1 -1
View File
@@ -1,4 +1,4 @@
//+vet !using-param #+vet !using-param
package compress_zlib package compress_zlib
/* /*
+60 -14
View File
@@ -1,5 +1,6 @@
package container_dynamic_bit_array package container_dynamic_bit_array
import "base:builtin"
import "base:intrinsics" import "base:intrinsics"
import "core:mem" import "core:mem"
@@ -18,7 +19,7 @@ NUM_BITS :: 64
Bit_Array :: struct { Bit_Array :: struct {
bits: [dynamic]u64, bits: [dynamic]u64,
bias: int, bias: int,
max_index: int, length: int,
free_pointer: bool, free_pointer: bool,
} }
@@ -52,9 +53,9 @@ Returns:
*/ */
iterate_by_all :: proc (it: ^Bit_Array_Iterator) -> (set: bool, index: int, ok: bool) { iterate_by_all :: proc (it: ^Bit_Array_Iterator) -> (set: bool, index: int, ok: bool) {
index = it.word_idx * NUM_BITS + int(it.bit_idx) + it.array.bias index = it.word_idx * NUM_BITS + int(it.bit_idx) + it.array.bias
if index > it.array.max_index { return false, 0, false } if index >= it.array.length + it.array.bias { return false, 0, false }
word := it.array.bits[it.word_idx] if len(it.array.bits) > it.word_idx else 0 word := it.array.bits[it.word_idx] if builtin.len(it.array.bits) > it.word_idx else 0
set = (word >> it.bit_idx & 1) == 1 set = (word >> it.bit_idx & 1) == 1
it.bit_idx += 1 it.bit_idx += 1
@@ -106,22 +107,22 @@ Returns:
*/ */
@(private="file") @(private="file")
iterate_internal_ :: proc (it: ^Bit_Array_Iterator, $ITERATE_SET_BITS: bool) -> (index: int, ok: bool) { iterate_internal_ :: proc (it: ^Bit_Array_Iterator, $ITERATE_SET_BITS: bool) -> (index: int, ok: bool) {
word := it.array.bits[it.word_idx] if len(it.array.bits) > it.word_idx else 0 word := it.array.bits[it.word_idx] if builtin.len(it.array.bits) > it.word_idx else 0
when ! ITERATE_SET_BITS { word = ~word } when ! ITERATE_SET_BITS { word = ~word }
// If the word is empty or we have already gone over all the bits in it, // If the word is empty or we have already gone over all the bits in it,
// b.bit_idx is greater than the index of any set bit in the word, // b.bit_idx is greater than the index of any set bit in the word,
// meaning that word >> b.bit_idx == 0. // meaning that word >> b.bit_idx == 0.
for it.word_idx < len(it.array.bits) && word >> it.bit_idx == 0 { for it.word_idx < builtin.len(it.array.bits) && word >> it.bit_idx == 0 {
it.word_idx += 1 it.word_idx += 1
it.bit_idx = 0 it.bit_idx = 0
word = it.array.bits[it.word_idx] if len(it.array.bits) > it.word_idx else 0 word = it.array.bits[it.word_idx] if builtin.len(it.array.bits) > it.word_idx else 0
when ! ITERATE_SET_BITS { word = ~word } when ! ITERATE_SET_BITS { word = ~word }
} }
// If we are iterating the set bits, reaching the end of the array means we have no more bits to check // If we are iterating the set bits, reaching the end of the array means we have no more bits to check
when ITERATE_SET_BITS { when ITERATE_SET_BITS {
if it.word_idx >= len(it.array.bits) { if it.word_idx >= builtin.len(it.array.bits) {
return 0, false return 0, false
} }
} }
@@ -135,7 +136,7 @@ iterate_internal_ :: proc (it: ^Bit_Array_Iterator, $ITERATE_SET_BITS: bool) ->
it.bit_idx = 0 it.bit_idx = 0
it.word_idx += 1 it.word_idx += 1
} }
return index, index <= it.array.max_index return index, index < it.array.length + it.array.bias
} }
/* /*
Gets the state of a bit in the bit-array Gets the state of a bit in the bit-array
@@ -160,7 +161,7 @@ get :: proc(ba: ^Bit_Array, #any_int index: uint) -> (res: bool, ok: bool) #opti
If we `get` a bit that doesn't fit in the Bit Array, it's naturally `false`. If we `get` a bit that doesn't fit in the Bit Array, it's naturally `false`.
This early-out prevents unnecessary resizing. This early-out prevents unnecessary resizing.
*/ */
if leg_index + 1 > len(ba.bits) { return false, true } if leg_index + 1 > builtin.len(ba.bits) { return false, true }
val := u64(1 << uint(bit_index)) val := u64(1 << uint(bit_index))
res = ba.bits[leg_index] & val == val res = ba.bits[leg_index] & val == val
@@ -208,7 +209,7 @@ set :: proc(ba: ^Bit_Array, #any_int index: uint, set_to: bool = true, allocator
resize_if_needed(ba, leg_index) or_return resize_if_needed(ba, leg_index) or_return
ba.max_index = max(idx, ba.max_index) ba.length = max(1 + idx, ba.length)
if set_to { if set_to {
ba.bits[leg_index] |= 1 << uint(bit_index) ba.bits[leg_index] |= 1 << uint(bit_index)
@@ -261,6 +262,9 @@ unsafe_unset :: proc(b: ^Bit_Array, bit: int) #no_bounds_check {
/* /*
A helper function to create a Bit Array with optional bias, in case your smallest index is non-zero (including negative). A helper function to create a Bit Array with optional bias, in case your smallest index is non-zero (including negative).
The range of bits created by this procedure is `min_index..<max_index`, and the
array will be able to expand beyond `max_index` if needed.
*Allocates (`new(Bit_Array) & make(ba.bits)`)* *Allocates (`new(Bit_Array) & make(ba.bits)`)*
Inputs: Inputs:
@@ -275,7 +279,7 @@ create :: proc(max_index: int, min_index: int = 0, allocator := context.allocato
context.allocator = allocator context.allocator = allocator
size_in_bits := max_index - min_index size_in_bits := max_index - min_index
if size_in_bits < 1 { return {}, false } if size_in_bits < 0 { return {}, false }
legs := size_in_bits >> INDEX_SHIFT legs := size_in_bits >> INDEX_SHIFT
if size_in_bits & INDEX_MASK > 0 {legs+=1} if size_in_bits & INDEX_MASK > 0 {legs+=1}
@@ -284,7 +288,7 @@ create :: proc(max_index: int, min_index: int = 0, allocator := context.allocato
res = new(Bit_Array) res = new(Bit_Array)
res.bits = bits res.bits = bits
res.bias = min_index res.bias = min_index
res.max_index = max_index res.length = max_index - min_index
res.free_pointer = true res.free_pointer = true
return return
} }
@@ -299,6 +303,48 @@ clear :: proc(ba: ^Bit_Array) {
mem.zero_slice(ba.bits[:]) mem.zero_slice(ba.bits[:])
} }
/* /*
Gets the length of set and unset valid bits in the Bit_Array.
Inputs:
- ba: The target Bit_Array
Returns:
- length: The length of valid bits.
*/
len :: proc(ba: ^Bit_Array) -> (length: int) {
if ba == nil { return }
return ba.length
}
/*
Shrinks the Bit_Array's backing storage to the smallest possible size.
Inputs:
- ba: The target Bit_Array
*/
shrink :: proc(ba: ^Bit_Array) #no_bounds_check {
if ba == nil { return }
legs_needed := builtin.len(ba.bits)
for i := legs_needed - 1; i >= 0; i -= 1 {
if ba.bits[i] == 0 {
legs_needed -= 1
} else {
break
}
}
if legs_needed == builtin.len(ba.bits) {
return
}
ba.length = 0
if legs_needed > 0 {
if legs_needed > 1 {
ba.length = (legs_needed - 1) * NUM_BITS
}
ba.length += NUM_BITS - int(intrinsics.count_leading_zeros(ba.bits[legs_needed - 1]))
}
resize(&ba.bits, legs_needed)
builtin.shrink(&ba.bits)
}
/*
Deallocates the Bit_Array and its backing storage Deallocates the Bit_Array and its backing storage
Inputs: Inputs:
@@ -321,8 +367,8 @@ resize_if_needed :: proc(ba: ^Bit_Array, legs: int, allocator := context.allocat
context.allocator = allocator context.allocator = allocator
if legs + 1 > len(ba.bits) { if legs + 1 > builtin.len(ba.bits) {
resize(&ba.bits, legs + 1) resize(&ba.bits, legs + 1)
} }
return len(ba.bits) > legs return builtin.len(ba.bits) > legs
} }
+4 -4
View File
@@ -1,8 +1,8 @@
/* /*
The Bit Array can be used in several ways: The Bit Array can be used in several ways:
- By default you don't need to instantiate a Bit Array: By default you don't need to instantiate a Bit Array.
Example:
package test package test
import "core:fmt" import "core:fmt"
@@ -22,8 +22,8 @@ The Bit Array can be used in several ways:
destroy(&bits) destroy(&bits)
} }
- A Bit Array can optionally allow for negative indices, if the minimum value was given during creation: A Bit Array can optionally allow for negative indices, if the minimum value was given during creation.
Example:
package test package test
import "core:fmt" import "core:fmt"
+9 -6
View File
@@ -1,22 +1,22 @@
/* /*
Package list implements an intrusive doubly-linked list. Package list implements an intrusive doubly-linked list.
An intrusive container requires a `Node` to be embedded in your own structure, like this: An intrusive container requires a `Node` to be embedded in your own structure, like this.
Example:
My_String :: struct { My_String :: struct {
node: list.Node, node: list.Node,
value: string, value: string,
} }
Embedding the members of a `list.Node` in your structure with the `using` keyword is also allowed: Embedding the members of a `list.Node` in your structure with the `using` keyword is also allowed.
Example:
My_String :: struct { My_String :: struct {
using node: list.Node, using node: list.Node,
value: string, value: string,
} }
Here is a full example: Here is a full example.
Example:
package test package test
import "core:fmt" import "core:fmt"
@@ -42,5 +42,8 @@ Here is a full example:
value: string, value: string,
} }
Output:
Hello
World
*/ */
package container_intrusive_list package container_intrusive_list
+7 -3
View File
@@ -139,9 +139,13 @@ clear :: proc "contextless" (a: ^$A/Small_Array($N, $T)) {
resize(a, 0) resize(a, 0)
} }
push_back_elems :: proc "contextless" (a: ^$A/Small_Array($N, $T), items: ..T) { push_back_elems :: proc "contextless" (a: ^$A/Small_Array($N, $T), items: ..T) -> bool {
n := copy(a.data[a.len:], items[:]) if a.len + builtin.len(items) <= cap(a^) {
a.len += n n := copy(a.data[a.len:], items[:])
a.len += n
return true
}
return false
} }
inject_at :: proc "contextless" (a: ^$A/Small_Array($N, $T), item: T, index: int) -> bool #no_bounds_check { inject_at :: proc "contextless" (a: ^$A/Small_Array($N, $T), item: T, index: int) -> bool #no_bounds_check {
+1 -1
View File
@@ -1,4 +1,4 @@
//+build amd64 #+build amd64
package aes_hw_intel package aes_hw_intel
import "core:sys/info" import "core:sys/info"
+1 -1
View File
@@ -20,7 +20,7 @@
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//+build amd64 #+build amd64
package aes_hw_intel package aes_hw_intel
import "base:intrinsics" import "base:intrinsics"
@@ -20,7 +20,7 @@
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//+build amd64 #+build amd64
package aes_hw_intel package aes_hw_intel
import "base:intrinsics" import "base:intrinsics"
@@ -1,4 +1,4 @@
//+build amd64 #+build amd64
package chacha20_simd256 package chacha20_simd256
import "base:intrinsics" import "base:intrinsics"
@@ -1,4 +1,4 @@
//+build !amd64 #+build !amd64
package chacha20_simd256 package chacha20_simd256
import "base:intrinsics" import "base:intrinsics"
+34 -35
View File
@@ -10,49 +10,48 @@ algorithm.
WARNING: Reusing the same key + iv to seal (encrypt) multiple messages WARNING: Reusing the same key + iv to seal (encrypt) multiple messages
results in catastrophic loss of security for most algorithms. results in catastrophic loss of security for most algorithms.
```odin Example:
package aead_example package aead_example
import "core:bytes" import "core:bytes"
import "core:crypto" import "core:crypto"
import "core:crypto/aead" import "core:crypto/aead"
main :: proc() { main :: proc() {
algo := aead.Algorithm.XCHACHA20POLY1305 algo := aead.Algorithm.XCHACHA20POLY1305
// The example added associated data, and plaintext. // The example added associated data, and plaintext.
aad_str := "Get your ass in gear boys." aad_str := "Get your ass in gear boys."
pt_str := "They're immanetizing the Eschaton." pt_str := "They're immanetizing the Eschaton."
aad := transmute([]byte)aad_str aad := transmute([]byte)aad_str
plaintext := transmute([]byte)pt_str plaintext := transmute([]byte)pt_str
pt_len := len(plaintext) pt_len := len(plaintext)
// Generate a random key for the purposes of illustration. // Generate a random key for the purposes of illustration.
key := make([]byte, aead.KEY_SIZES[algo]) key := make([]byte, aead.KEY_SIZES[algo])
defer delete(key) defer delete(key)
crypto.rand_bytes(key) crypto.rand_bytes(key)
// `ciphertext || tag`, is a common way data is transmitted, so // `ciphertext || tag`, is a common way data is transmitted, so
// demonstrate that. // demonstrate that.
buf := make([]byte, pt_len + aead.TAG_SIZES[algo]) buf := make([]byte, pt_len + aead.TAG_SIZES[algo])
defer delete(buf) defer delete(buf)
ciphertext, tag := buf[:pt_len], buf[pt_len:] ciphertext, tag := buf[:pt_len], buf[pt_len:]
// Seal the AAD + Plaintext. // Seal the AAD + Plaintext.
iv := make([]byte, aead.IV_SIZES[algo]) iv := make([]byte, aead.IV_SIZES[algo])
defer delete(iv) defer delete(iv)
crypto.rand_bytes(iv) // Random IVs are safe with XChaCha20-Poly1305. crypto.rand_bytes(iv) // Random IVs are safe with XChaCha20-Poly1305.
aead.seal(algo, ciphertext, tag, key, iv, aad, plaintext) aead.seal(algo, ciphertext, tag, key, iv, aad, plaintext)
// Open the AAD + Ciphertext. // Open the AAD + Ciphertext.
opened_pt := buf[:pt_len] opened_pt := buf[:pt_len]
if ok := aead.open(algo, opened_pt, key, iv, aad, ciphertext, tag); !ok { if ok := aead.open(algo, opened_pt, key, iv, aad, ciphertext, tag); !ok {
panic("aead example: failed to open") panic("aead example: failed to open")
}
assert(bytes.equal(opened_pt, plaintext))
} }
assert(bytes.equal(opened_pt, plaintext))
}
```
*/ */
package aead package aead
+3 -3
View File
@@ -2,9 +2,9 @@
package aes implements the AES block cipher and some common modes. package aes implements the AES block cipher and some common modes.
See: See:
- https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197-upd1.pdf - [[ https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197-upd1.pdf ]]
- https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf - [[ https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf ]]
- https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf - [[ https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf ]]
*/ */
package aes package aes
+1 -1
View File
@@ -1,4 +1,4 @@
//+build amd64 #+build amd64
package aes package aes
import "base:intrinsics" import "base:intrinsics"
+1 -1
View File
@@ -1,4 +1,4 @@
//+build amd64 #+build amd64
package aes package aes
import "base:intrinsics" import "base:intrinsics"
+1 -1
View File
@@ -1,4 +1,4 @@
//+build amd64 #+build amd64
package aes package aes
import "base:intrinsics" import "base:intrinsics"
+1 -1
View File
@@ -1,4 +1,4 @@
//+build !amd64 #+build !amd64
package aes package aes
@(private = "file") @(private = "file")
+1 -1
View File
@@ -1,4 +1,4 @@
//+build amd64 #+build amd64
package aes package aes
import "core:crypto/_aes/hw_intel" import "core:crypto/_aes/hw_intel"
+2 -2
View File
@@ -2,8 +2,8 @@
package blake2b implements the BLAKE2b hash algorithm. package blake2b implements the BLAKE2b hash algorithm.
See: See:
- https://datatracker.ietf.org/doc/html/rfc7693 - [[ https://datatracker.ietf.org/doc/html/rfc7693 ]]
- https://www.blake2.net - [[ https://www.blake2.net ]]
*/ */
package blake2b package blake2b
+2 -2
View File
@@ -2,8 +2,8 @@
package blake2s implements the BLAKE2s hash algorithm. package blake2s implements the BLAKE2s hash algorithm.
See: See:
- https://datatracker.ietf.org/doc/html/rfc7693 - [[ https://datatracker.ietf.org/doc/html/rfc7693 ]]
- https://www.blake2.net/ - [[ https://www.blake2.net/ ]]
*/ */
package blake2s package blake2s
+2 -2
View File
@@ -2,8 +2,8 @@
package chacha20 implements the ChaCha20 and XChaCha20 stream ciphers. package chacha20 implements the ChaCha20 and XChaCha20 stream ciphers.
See: See:
- https://datatracker.ietf.org/doc/html/rfc8439 - [[ https://datatracker.ietf.org/doc/html/rfc8439 ]]
- https://datatracker.ietf.org/doc/draft-irtf-cfrg-xchacha/03/ - [[ https://datatracker.ietf.org/doc/draft-irtf-cfrg-xchacha/03/ ]]
*/ */
package chacha20 package chacha20
@@ -4,8 +4,8 @@ AEAD_XChaCha20_Poly1305 Authenticated Encryption with Additional Data
algorithms. algorithms.
See: See:
- https://www.rfc-editor.org/rfc/rfc8439 - [[ https://www.rfc-editor.org/rfc/rfc8439 ]]
- https://datatracker.ietf.org/doc/html/draft-arciszewski-xchacha-03 - [[ https://datatracker.ietf.org/doc/html/draft-arciszewski-xchacha-03 ]]
*/ */
package chacha20poly1305 package chacha20poly1305
+3 -3
View File
@@ -2,9 +2,9 @@
package ed25519 implements the Ed25519 EdDSA signature algorithm. package ed25519 implements the Ed25519 EdDSA signature algorithm.
See: See:
- https://datatracker.ietf.org/doc/html/rfc8032 - [[ https://datatracker.ietf.org/doc/html/rfc8032 ]]
- https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf - [[ https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf ]]
- https://eprint.iacr.org/2020/1244.pdf - [[ https://eprint.iacr.org/2020/1244.pdf ]]
*/ */
package ed25519 package ed25519
+27 -29
View File
@@ -17,46 +17,44 @@ accomplish common tasks.
A third optional boolean parameter controls if the file is streamed A third optional boolean parameter controls if the file is streamed
(default), or or read at once. (default), or or read at once.
```odin Example:
package hash_example package hash_example
import "core:crypto/hash" import "core:crypto/hash"
main :: proc() { main :: proc() {
input := "Feed the fire." input := "Feed the fire."
// Compute the digest, using the high level API. // Compute the digest, using the high level API.
returned_digest := hash.hash(hash.Algorithm.SHA512_256, input) returned_digest := hash.hash(hash.Algorithm.SHA512_256, input)
defer delete(returned_digest) defer delete(returned_digest)
// Variant that takes a destination buffer, instead of returning // Variant that takes a destination buffer, instead of returning
// the digest. // the digest.
digest := make([]byte, hash.DIGEST_SIZES[hash.Algorithm.BLAKE2B]) // @note: Destination buffer has to be at least as big as the digest size of the hash. digest := make([]byte, hash.DIGEST_SIZES[hash.Algorithm.BLAKE2B]) // @note: Destination buffer has to be at least as big as the digest size of the hash.
defer delete(digest) defer delete(digest)
hash.hash(hash.Algorithm.BLAKE2B, input, digest) hash.hash(hash.Algorithm.BLAKE2B, input, digest)
} }
```
A generic low level API is provided supporting the init/update/final interface A generic low level API is provided supporting the init/update/final interface
that is typical with cryptographic hash function implementations. that is typical with cryptographic hash function implementations.
```odin Example:
package hash_example package hash_example
import "core:crypto/hash" import "core:crypto/hash"
main :: proc() { main :: proc() {
input := "Let the cinders burn." input := "Let the cinders burn."
// Compute the digest, using the low level API. // Compute the digest, using the low level API.
ctx: hash.Context ctx: hash.Context
digest := make([]byte, hash.DIGEST_SIZES[hash.Algorithm.SHA3_512]) digest := make([]byte, hash.DIGEST_SIZES[hash.Algorithm.SHA3_512])
defer delete(digest) defer delete(digest)
hash.init(&ctx, hash.Algorithm.SHA3_512) hash.init(&ctx, hash.Algorithm.SHA3_512)
hash.update(&ctx, transmute([]byte)input) hash.update(&ctx, transmute([]byte)input)
hash.final(&ctx, digest) hash.final(&ctx, digest)
} }
```
*/ */
package crypto_hash package crypto_hash
+4 -38
View File
@@ -1,16 +1,15 @@
package crypto_hash package crypto_hash
/* /*
Copyright 2021 zhibog Copyright 2021 zhibog
Made available under the BSD-3 license. Made available under the BSD-3 license.
List of contributors: List of contributors:
zhibog, dotbmp: Initial implementation. zhibog, dotbmp: Initial implementation.
*/ */
import "core:io" import "core:io"
import "core:mem" import "core:mem"
import "core:os"
// hash_bytes will hash the given input and return the computed digest // hash_bytes will hash the given input and return the computed digest
// in a newly allocated slice. // in a newly allocated slice.
@@ -87,36 +86,3 @@ hash_stream :: proc(
return dst, io.Error.None return dst, io.Error.None
} }
// hash_file will read the file provided by the given handle and return the
// computed digest in a newly allocated slice.
hash_file :: proc(
algorithm: Algorithm,
hd: os.Handle,
load_at_once := false,
allocator := context.allocator,
) -> (
[]byte,
io.Error,
) {
if !load_at_once {
return hash_stream(algorithm, os.stream_from_handle(hd), allocator)
}
buf, ok := os.read_entire_file(hd, allocator)
if !ok {
return nil, io.Error.Unknown
}
defer delete(buf, allocator)
return hash_bytes(algorithm, buf, allocator), io.Error.None
}
hash :: proc {
hash_stream,
hash_file,
hash_bytes,
hash_string,
hash_bytes_to_buffer,
hash_string_to_buffer,
}
+10
View File
@@ -0,0 +1,10 @@
#+build freestanding
package crypto_hash
hash :: proc {
hash_stream,
hash_bytes,
hash_string,
hash_bytes_to_buffer,
hash_string_to_buffer,
}
+38
View File
@@ -0,0 +1,38 @@
#+build !freestanding
package crypto_hash
import "core:io"
import "core:os"
// hash_file will read the file provided by the given handle and return the
// computed digest in a newly allocated slice.
hash_file :: proc(
algorithm: Algorithm,
hd: os.Handle,
load_at_once := false,
allocator := context.allocator,
) -> (
[]byte,
io.Error,
) {
if !load_at_once {
return hash_stream(algorithm, os.stream_from_handle(hd), allocator)
}
buf, ok := os.read_entire_file(hd, allocator)
if !ok {
return nil, io.Error.Unknown
}
defer delete(buf, allocator)
return hash_bytes(algorithm, buf, allocator), io.Error.None
}
hash :: proc {
hash_stream,
hash_file,
hash_bytes,
hash_string,
hash_bytes_to_buffer,
hash_string_to_buffer,
}
+1 -1
View File
@@ -2,7 +2,7 @@
package hkdf implements the HKDF HMAC-based Extract-and-Expand Key package hkdf implements the HKDF HMAC-based Extract-and-Expand Key
Derivation Function. Derivation Function.
See: https://www.rfc-editor.org/rfc/rfc5869 See: [[ https://www.rfc-editor.org/rfc/rfc5869 ]]
*/ */
package hkdf package hkdf
+1 -1
View File
@@ -2,7 +2,7 @@
package hmac implements the HMAC MAC algorithm. package hmac implements the HMAC MAC algorithm.
See: See:
- https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.198-1.pdf - [[ https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.198-1.pdf ]]
*/ */
package hmac package hmac
+1 -1
View File
@@ -2,7 +2,7 @@
package kmac implements the KMAC MAC algorithm. package kmac implements the KMAC MAC algorithm.
See: See:
- https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-185.pdf - [[ https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-185.pdf ]]
*/ */
package kmac package kmac
+2 -2
View File
@@ -5,8 +5,8 @@ WARNING: The MD5 algorithm is known to be insecure and should only be
used for interoperating with legacy applications. used for interoperating with legacy applications.
See: See:
- https://eprint.iacr.org/2005/075 - [[ https://eprint.iacr.org/2005/075 ]]
- https://datatracker.ietf.org/doc/html/rfc1321 - [[ https://datatracker.ietf.org/doc/html/rfc1321 ]]
*/ */
package md5 package md5
+3 -3
View File
@@ -5,9 +5,9 @@ WARNING: The SHA1 algorithm is known to be insecure and should only be
used for interoperating with legacy applications. used for interoperating with legacy applications.
See: See:
- https://eprint.iacr.org/2017/190 - [[ https://eprint.iacr.org/2017/190 ]]
- https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf - [[ https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf ]]
- https://datatracker.ietf.org/doc/html/rfc3174 - [[ https://datatracker.ietf.org/doc/html/rfc3174 ]]
*/ */
package sha1 package sha1
+1 -1
View File
@@ -1,7 +1,7 @@
/* /*
package pbkdf2 implements the PBKDF2 password-based key derivation function. package pbkdf2 implements the PBKDF2 password-based key derivation function.
See: https://www.rfc-editor.org/rfc/rfc2898 See: [[ https://www.rfc-editor.org/rfc/rfc2898 ]]
*/ */
package pbkdf2 package pbkdf2
+1 -1
View File
@@ -2,7 +2,7 @@
package poly1305 implements the Poly1305 one-time MAC algorithm. package poly1305 implements the Poly1305 one-time MAC algorithm.
See: See:
- https://datatracker.ietf.org/doc/html/rfc8439 - [[ https://datatracker.ietf.org/doc/html/rfc8439 ]]
*/ */
package poly1305 package poly1305
+1 -1
View File
@@ -1,4 +1,4 @@
//+build freebsd, openbsd, netbsd #+build freebsd, openbsd, netbsd
package crypto package crypto
foreign import libc "system:c" foreign import libc "system:c"
+7 -7
View File
@@ -1,10 +1,10 @@
//+build !linux #+build !linux
//+build !windows #+build !windows
//+build !openbsd #+build !openbsd
//+build !freebsd #+build !freebsd
//+build !netbsd #+build !netbsd
//+build !darwin #+build !darwin
//+build !js #+build !js
package crypto package crypto
HAS_RAND_BYTES :: false HAS_RAND_BYTES :: false
+1 -1
View File
@@ -2,7 +2,7 @@
package ristretto255 implement the ristretto255 prime-order group. package ristretto255 implement the ristretto255 prime-order group.
See: See:
- https://www.rfc-editor.org/rfc/rfc9496 - [[ https://www.rfc-editor.org/rfc/rfc9496 ]]
*/ */
package ristretto255 package ristretto255
+2 -2
View File
@@ -2,8 +2,8 @@
package sha2 implements the SHA2 hash algorithm family. package sha2 implements the SHA2 hash algorithm family.
See: See:
- https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf - [[ https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf ]]
- https://datatracker.ietf.org/doc/html/rfc3874 - [[ https://datatracker.ietf.org/doc/html/rfc3874 ]]
*/ */
package sha2 package sha2
+1 -1
View File
@@ -6,7 +6,7 @@ pre-standardization Keccak algorithm is required, it can be found in
crypto/legacy/keccak. crypto/legacy/keccak.
See: See:
- https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf - [[ https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf ]]
*/ */
package sha3 package sha3
+2 -2
View File
@@ -4,8 +4,8 @@ package shake implements the SHAKE and cSHAKE XOF algorithm families.
The SHA3 hash algorithm can be found in the crypto/sha3. The SHA3 hash algorithm can be found in the crypto/sha3.
See: See:
- https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf - [[ https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf ]]
- https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-185.pdf - [[ https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-185.pdf ]]
*/ */
package shake package shake
+9 -4
View File
@@ -1,3 +1,12 @@
/*
package siphash Implements the SipHash hashing algorithm.
Use the specific procedures for a certain setup. The generic procedures will default to Siphash 2-4.
See:
- [[ https://github.com/veorq/SipHash ]]
- [[ https://www.aumasson.jp/siphash/siphash.pdf ]]
*/
package siphash package siphash
/* /*
@@ -6,10 +15,6 @@ package siphash
List of contributors: List of contributors:
zhibog: Initial implementation. zhibog: Initial implementation.
Implementation of the SipHash hashing algorithm, as defined at <https://github.com/veorq/SipHash> and <https://www.aumasson.jp/siphash/siphash.pdf>
Use the specific procedures for a certain setup. The generic procdedures will default to Siphash 2-4
*/ */
import "core:crypto" import "core:crypto"
+1 -1
View File
@@ -2,7 +2,7 @@
package sm3 implements the SM3 hash algorithm. package sm3 implements the SM3 hash algorithm.
See: See:
- https://datatracker.ietf.org/doc/html/draft-sca-cfrg-sm3-02 - [[ https://datatracker.ietf.org/doc/html/draft-sca-cfrg-sm3-02 ]]
*/ */
package sm3 package sm3
+1 -1
View File
@@ -2,7 +2,7 @@
package tuplehash implements the TupleHash and TupleHashXOF algorithms. package tuplehash implements the TupleHash and TupleHashXOF algorithms.
See: See:
- https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-185.pdf - [[ https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-185.pdf ]]
*/ */
package tuplehash package tuplehash
+1 -1
View File
@@ -3,7 +3,7 @@ package x25519 implements the X25519 (aka curve25519) Elliptic-Curve
Diffie-Hellman key exchange protocol. Diffie-Hellman key exchange protocol.
See: See:
- https://www.rfc-editor.org/rfc/rfc7748 - [[ https://www.rfc-editor.org/rfc/rfc7748 ]]
*/ */
package x25519 package x25519
+2 -2
View File
@@ -1,5 +1,5 @@
//+private file #+private file
//+build linux, darwin #+build linux, darwin
package debug_trace package debug_trace
import "base:intrinsics" import "base:intrinsics"
+3 -1
View File
@@ -1,4 +1,6 @@
//+build !windows !linux !darwin #+build !windows
#+build !linux
#+build !darwin
package debug_trace package debug_trace
import "base:runtime" import "base:runtime"
+2 -2
View File
@@ -1,5 +1,5 @@
//+private #+private
//+build windows #+build windows
package debug_trace package debug_trace
import "base:intrinsics" import "base:intrinsics"
+1 -2
View File
@@ -4,7 +4,6 @@ Package `core:dynlib` implements loading of shared libraries/DLLs and their symb
The behaviour of dynamically loaded libraries is specific to the target platform of the program. The behaviour of dynamically loaded libraries is specific to the target platform of the program.
For in depth detail on the underlying behaviour please refer to your target platform's documentation. For in depth detail on the underlying behaviour please refer to your target platform's documentation.
See `example` directory for an example library exporting 3 symbols and a host program loading them automatically For a full example, see: [[ core/dynlib/example; https://github.com/odin-lang/Odin/tree/master/core/dynlib/example ]]
by defining a symbol table struct.
*/ */
package dynlib package dynlib
+2 -2
View File
@@ -1,5 +1,5 @@
//+build js #+build js
//+private #+private
package dynlib package dynlib
_load_library :: proc(path: string, global_symbols := false) -> (Library, bool) { _load_library :: proc(path: string, global_symbols := false) -> (Library, bool) {
+2 -2
View File
@@ -1,5 +1,5 @@
//+build linux, darwin, freebsd, openbsd, netbsd #+build linux, darwin, freebsd, openbsd, netbsd
//+private #+private
package dynlib package dynlib
import "core:os" import "core:os"
+2 -2
View File
@@ -1,5 +1,5 @@
//+build windows #+build windows
//+private #+private
package dynlib package dynlib
import win32 "core:sys/windows" import win32 "core:sys/windows"
+3 -3
View File
@@ -13,8 +13,8 @@ If your terminal supports 24-bit true color mode, you can also do this:
fmt.println(ansi.CSI + ansi.FG_COLOR_24_BIT + ";0;255;255" + ansi.SGR + "Hellope!" + ansi.CSI + ansi.RESET + ansi.SGR) fmt.println(ansi.CSI + ansi.FG_COLOR_24_BIT + ";0;255;255" + ansi.SGR + "Hellope!" + ansi.CSI + ansi.RESET + ansi.SGR)
For more information, see: For more information, see:
1. https://en.wikipedia.org/wiki/ANSI_escape_code - [[ https://en.wikipedia.org/wiki/ANSI_escape_code ]]
2. https://www.vt100.net/docs/vt102-ug/chapter5.html - [[ https://www.vt100.net/docs/vt102-ug/chapter5.html ]]
3. https://invisible-island.net/xterm/ctlseqs/ctlseqs.html - [[ https://invisible-island.net/xterm/ctlseqs/ctlseqs.html ]]
*/ */
package ansi package ansi
+10 -26
View File
@@ -675,10 +675,6 @@ _unmarshal_map :: proc(d: Decoder, v: any, ti: ^reflect.Type_Info, hdr: Header,
return return
case reflect.Type_Info_Map: case reflect.Type_Info_Map:
if !reflect.is_string(t.key) {
return _unsupported(v, hdr)
}
raw_map := (^mem.Raw_Map)(v.data) raw_map := (^mem.Raw_Map)(v.data)
if raw_map.allocator.procedure == nil { if raw_map.allocator.procedure == nil {
raw_map.allocator = context.allocator raw_map.allocator = context.allocator
@@ -696,42 +692,30 @@ _unmarshal_map :: proc(d: Decoder, v: any, ti: ^reflect.Type_Info, hdr: Header,
runtime.map_reserve_dynamic(raw_map, t.map_info, new_len) or_return runtime.map_reserve_dynamic(raw_map, t.map_info, new_len) or_return
} }
// Temporary memory to unmarshal keys into before inserting them into the map. // Temporary memory to unmarshal values into before inserting them into the map.
elem_backing := mem.alloc_bytes_non_zeroed(t.value.size, t.value.align, context.temp_allocator) or_return elem_backing := mem.alloc_bytes_non_zeroed(t.value.size, t.value.align, context.temp_allocator) or_return
defer delete(elem_backing, context.temp_allocator) defer delete(elem_backing, context.temp_allocator)
map_backing_value := any{raw_data(elem_backing), t.value.id} map_backing_value := any{raw_data(elem_backing), t.value.id}
for idx := 0; unknown || idx < length; idx += 1 { // Temporary memory to unmarshal keys into.
// Decode key, keys can only be strings. key_backing := mem.alloc_bytes_non_zeroed(t.key.size, t.key.align, context.temp_allocator) or_return
key: string defer delete(key_backing, context.temp_allocator)
if keyv, kerr := decode_key(d, v); unknown && kerr == .Break { key_backing_value := any{raw_data(key_backing), t.key.id}
break
} else if kerr != nil {
err = kerr
return
} else {
key = keyv
}
for idx := 0; unknown || idx < length; idx += 1 {
if unknown || idx > scap { if unknown || idx > scap {
// Reserve space for new element so we can return allocator errors. // Reserve space for new element so we can return allocator errors.
new_len := uintptr(runtime.map_len(raw_map^)+1) new_len := uintptr(runtime.map_len(raw_map^)+1)
runtime.map_reserve_dynamic(raw_map, t.map_info, new_len) or_return runtime.map_reserve_dynamic(raw_map, t.map_info, new_len) or_return
} }
mem.zero_slice(key_backing)
_unmarshal_value(d, key_backing_value, _decode_header(r) or_return) or_return
mem.zero_slice(elem_backing) mem.zero_slice(elem_backing)
_unmarshal_value(d, map_backing_value, _decode_header(r) or_return) or_return _unmarshal_value(d, map_backing_value, _decode_header(r) or_return) or_return
key_ptr := rawptr(&key) set_ptr := runtime.__dynamic_map_set_without_hash(raw_map, t.map_info, key_backing_value.data, map_backing_value.data)
key_cstr: cstring
if reflect.is_cstring(t.key) {
assert_safe_for_cstring(key)
key_cstr = cstring(raw_data(key))
key_ptr = &key_cstr
}
set_ptr := runtime.__dynamic_map_set_without_hash(raw_map, t.map_info, key_ptr, map_backing_value.data)
// We already reserved space for it, so this shouldn't fail. // We already reserved space for it, so this shouldn't fail.
assert(set_ptr != nil) assert(set_ptr != nil)
} }

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