Compare commits

...

116 Commits

Author SHA1 Message Date
gingerBill 73beed0477 Merge pull request #1921 from Hyp-X/master
Update user32.odin
2022-08-02 12:15:44 +01:00
gingerBill e0ecdd4b24 Simplify logic of append of zero sized elements 2022-08-02 11:13:53 +01:00
gingerBill 5168cf03a9 Remove dead #maybe code 2022-08-01 15:38:50 +01:00
gingerBill b886ae6515 Simplify parser logic for field prefixes 2022-08-01 15:32:17 +01:00
gingerBill 277a973b98 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-08-01 15:24:23 +01:00
gingerBill 0ec4d97bfd Correct parser logic for is_token_field_prefix 2022-08-01 15:24:17 +01:00
Hyp-X e6236e5c3e Update user32.odin
Added UnregisterClassW procedure to windows\user32.odin
2022-08-01 15:59:00 +02:00
gingerBill e201280844 Merge pull request #1920 from Hyp-X/master
Update dxgi.odin
2022-08-01 14:40:39 +01:00
gingerBill 8e50a6c61b Merge pull request #1876 from mohd-akram/build-config-opts
Allow passing config options to build script
2022-08-01 14:33:35 +01:00
Hyp-X 7e6f5f89d0 Merge branch 'odin-lang:master' into master 2022-08-01 14:44:57 +02:00
gingerBill 97acc57649 Simplify field prefix handling 2022-08-01 13:17:10 +01:00
gingerBill 83c8c48ed7 Simplify ast parsing for prefixes 2022-08-01 13:07:49 +01:00
Hyp-X 0815b4d59f Update dxgi.odin
Fixed CreateDXGIFactory* last parameter to be ^rawptr instead of rawptr
2022-08-01 14:04:12 +02:00
gingerBill a0135080b3 Merge pull request #1917 from lerno/added_virtuals_macos
Added virtual memory headers for Darwin.
2022-07-30 19:38:37 +01:00
Christoffer Lerno f45e8e5d47 Added virtual memory headers for Darwin. 2022-07-29 20:01:26 +02:00
Jeroen van Rijn 98ba4beede Merge pull request #1916 from wjlroe/glfw-3-3-8-darwin-universal-static-libs
GLFW 3.3.8 Darwin universal and Windows static libs
2022-07-28 16:55:42 +02:00
William Roe a9304f2fef Update Windows GLFW libraries to 3.3.8
This matches the latest libraries committed for macOS/Darwin
2022-07-28 15:38:14 +01:00
William Roe a0697ab057 Fix build on Apple Silicon when linking to GLFW
This also updates the library to GLFW 3.3.8
This includes the lib-universal static library, rather than just the
Intel one (lib-x86_64), so software building with GLFW on Apple Silicon
will work again.
2022-07-28 15:29:30 +01:00
Jeroen van Rijn 2e895c72d3 Merge pull request #1447 from phillvancejr/master
Added vendor glfw support for Mac OS
2022-07-28 16:05:59 +02:00
Jeroen van Rijn 674ebe395f Merge branch 'master' into master 2022-07-28 16:01:18 +02:00
Jeroen van Rijn 96eecaab54 Merge pull request #1915 from JorriFransen/fix-simd_abs
Changed param count from 2 to 1 for simd_abs.
2022-07-28 15:36:16 +02:00
Jorri Fransen b1ae5bc9fe Changed param count from 2 to 1 for simd_abs. 2022-07-28 15:28:26 +02:00
Jeroen van Rijn 7258588ed5 Merge pull request #1914 from wjlroe/fix-json-unmarshal-without-assertions-bug
Fix bug unmarshalling JSON with assertions disabled
2022-07-28 15:03:47 +02:00
William Roe d913155972 Fix bug unmarshalling JSON with assertions disabled
When asserts are disabled, code within the assert isn't run. Having
expect_token within an assert means that the state of the Parser is
mutated when asserts are run, but not when they aren't.

There's already a wrapper procedure for this pattern, which I have
reused here.
2022-07-28 13:56:14 +01:00
pvance 9746e25784 Update stb_image_resize.odin 2022-07-28 04:27:42 -04:00
pvance d26cfd2141 Update bindings.odin 2022-07-28 04:26:22 -04:00
pvance 21f2c06f4b Update stb_image_resize.odin 2022-07-28 04:25:18 -04:00
pvance 727a25f41f Replace ODIN_OS strings with enum values 2022-07-28 04:23:24 -04:00
pvance 3f27cb2309 replace ODIN_OS string with enums 2022-07-28 04:22:00 -04:00
pvance f213622982 replace ODIN_OS string with enums 2022-07-28 04:20:37 -04:00
pvance 4aad835a66 replaced ODIN_OS string values with enums 2022-07-28 04:19:28 -04:00
Jeroen van Rijn 4af8a64580 Merge pull request #1907 from thePHTest/minor-fix
remove leftover print statement
2022-07-26 01:00:38 +02:00
Phil c9c3611b1d remove leftover print statement 2022-07-25 15:46:47 -07:00
gingerBill 220dfd7440 Minor clean up of wasi_api.odin 2022-07-25 17:00:32 +01:00
gingerBill bce8819ed5 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-07-25 12:12:32 +01:00
gingerBill 5f2b220a85 Fix minor issue with a lack of a trailing comma 2022-07-25 12:12:25 +01:00
gingerBill f174c805a9 Merge pull request #1905 from DanielGavin/glob-fix
Change open to be read only when opening directory
2022-07-25 10:43:28 +01:00
Daniel Gavin 25869b7504 Change open to be read only when opening directory 2022-07-25 11:34:03 +02:00
Mikkel Hjortshøj ecd81e8a53 Update stale.yml 2022-07-25 00:14:07 +02:00
gingerBill d7f9f7f170 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-07-24 23:07:41 +01:00
gingerBill 08f5259d77 Replace insert_at with inject_at and assign_at 2022-07-24 23:07:35 +01:00
Mikkel Hjortshøj a9f744cb64 Update stale.yml 2022-07-25 00:07:29 +02:00
Mikkel Hjortshøj b02e42c6dc Update stale.yml 2022-07-25 00:05:36 +02:00
Mikkel Hjortshøj cb0273b5d7 Update stale.yml 2022-07-24 23:58:43 +02:00
Mikkel Hjortshøj 8dbf45a65a Update stale.yml 2022-07-24 23:54:39 +02:00
gingerBill 9f64de9568 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-07-24 22:51:39 +01:00
gingerBill 0ebe9ba487 Fix #1901 2022-07-24 22:51:34 +01:00
Mikkel Hjortshøj efe00e1aa6 Create stale.yml 2022-07-24 23:48:34 +02:00
gingerBill 2bdbce55f9 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-07-24 22:46:07 +01:00
gingerBill 9614ca92f0 Fix #1834 2022-07-24 22:46:00 +01:00
gingerBill d30e59f539 Merge pull request #1844 from Ronaldr1985/fix-odin-on-openbsd
Added missing #includes on OpenBSD
2022-07-24 22:28:25 +01:00
Mikkel Hjortshøj a3afe617c2 Update ci.yml 2022-07-24 23:27:07 +02:00
gingerBill 69daac583e Merge pull request #1898 from DaseinPhaos/patch-1
fix `linalg.angle_from_quaternion`
2022-07-24 22:18:36 +01:00
gingerBill b28d4b753b Temp fix for lb_emit_store 2022-07-24 20:58:50 +01:00
gingerBill e6ab4f4856 Force memset instead of store zeroinitializer when the value is large 2022-07-24 20:22:50 +01:00
gingerBill c8ab1b7ee1 Add #by_ptr procedure attribute to enforce a parameter to be passed by pointer internally 2022-07-24 13:11:48 +01:00
gingerBill 9f10487678 Fix #1493 2022-07-24 12:59:34 +01:00
gingerBill 2542983d70 Fix #1793 2022-07-24 12:54:05 +01:00
gingerBill d492fb3501 Fix and improve x->y() behaviour to minimize duplicate evaluation 2022-07-24 12:39:59 +01:00
Ronald1985 1829aa1638 Undo changes to common.cpp and move the include of sys/wait.h to gb.h 2022-07-22 23:08:46 +01:00
Ronald1985 4cb4173ced Updated shabang in build_odin.sh so it runs on OpenBSD
This change doesn't break compatibility on Linux or Darwin
2022-07-22 23:01:38 +01:00
Luxko 00e704b216 fix linalg.angle_from_quaternion
fixes #1894 .2:
```odin
package laa
import "core:fmt"
import la "core:math/linalg"

main:: proc() {
    angle := f32(0.5)
    quat  := la.quaternion_angle_axis_f32(angle,la.Vector3f32{0,0,1})
    fmt.printf("retreived: %0.8f\n",  la.angle_from_quaternion(quat)) // should be 0.5, but wasn't
}
```
2022-07-23 00:59:45 +08:00
gingerBill 227ee0f705 Merge pull request #1895 from yeongjukang/patch-1
fix parameter for atan2 in procedure math.asin
2022-07-22 11:23:46 +01:00
gingerBill 17f47a7ab0 Merge pull request #1892 from esnunes/vendor-raylib-4.0-macos-arm64
Update `vendor:raylib` to support macos-arm64 (apple silicon)
2022-07-22 11:06:16 +01:00
Yeongju Kang 4e8bc0786d fix parameter for atan2 in procedure asin 2022-07-22 15:48:06 +09:00
gingerBill 3d3ccf061f Merge pull request #1893 from Tetralux/slash-join-slice
[path/slashpath] Change join() to take a slice instead of varargs
2022-07-21 18:59:04 +01:00
Tetralux 3a8adc6721 [path/slashpath] Change join() to take a slice instead of varargs
Achieves parity with filepath.join(), which was similarly changed a while back.
2022-07-21 17:49:31 +00:00
gingerBill e1748a5dd1 Add MAKE_WORD 2022-07-21 17:08:11 +01:00
Eduardo Nunes 59b4c889d3 Update vendor:raylib to support macos-arm64 (apple silicon) 2022-07-20 18:23:09 -03:00
gingerBill b6408d1b3f Merge branch 'master' of https://github.com/odin-lang/Odin 2022-07-19 16:17:45 +01:00
gingerBill 3db3047f47 Minor improvements 2022-07-19 16:17:23 +01:00
gingerBill 7420fbd95b Add custom event handling to wasm 2022-07-19 16:16:51 +01:00
gingerBill 7c990b3833 Merge pull request #1877 from fabiansperber/improve-debug-info
Improve debug info
2022-07-19 00:49:22 +01:00
Fabian Sperber 9c059f1a12 Fix debug info for type switch variable to be only visible in correct switch case
- use correct scopes for type switch
2022-07-19 00:46:28 +02:00
Fabian Sperber fb167d1d0a Fix loop var (init) becoming hidden while stepping on the for-line
- set debug location of jumps between block (similar to clang to the location of 'for')
- extend scope range to include all parts of the for-stmt
2022-07-19 00:46:27 +02:00
Fabian Sperber 0992239d86 Embed natvis in windows debug build for easier viewing of strings and Arrays 2022-07-19 00:46:27 +02:00
gingerBill 9eb3da0474 Remove import cycle on FreeBSD 2022-07-18 15:20:28 +01:00
gingerBill e91f8feedf Keep -vet happy 2022-07-18 15:12:54 +01:00
gingerBill 22a0c3fce1 Disallow proc() do stmt and only allow proc() { stmt } 2022-07-18 15:09:04 +01:00
gingerBill 6c7e5748a8 Integrate numerous debug fixes from #1877 2022-07-18 12:49:29 +01:00
gingerBill 0b0c6da8b0 Merge pull request #1873 from weshardee/master
fix -build-mode:shared on MacOS
2022-07-18 12:42:53 +01:00
gingerBill 78826071c0 Fix #1836 2022-07-16 23:14:09 +01:00
gingerBill e61b73d7ad Fix #1869 2022-07-16 22:30:57 +01:00
gingerBill f886632bf1 Fix #1880 2022-07-16 22:18:07 +01:00
gingerBill eafa5098aa Fix #1883 2022-07-16 18:03:43 +01:00
gingerBill 0571b80d37 Fix printing of bit_set types 2022-07-16 17:56:38 +01:00
gingerBill 80c10644dd Remove assert 2022-07-16 17:39:13 +01:00
gingerBill 041625381c Fix #1888 2022-07-16 17:36:03 +01:00
gingerBill 48f56d728b Merge branch 'master' of https://github.com/odin-lang/Odin 2022-07-16 16:12:24 +01:00
gingerBill 872d391cfb Mock up for the ability to enforce our own runtime.memset if necessary 2022-07-16 16:12:16 +01:00
Jeroen van Rijn 3e6ec65dd9 Fix murmur64a's tail handling.
Also, split up the murmur64 proc into murmur64a and murmur64b as they're distinct hashes with their own output.
2022-07-15 13:02:07 +02:00
gingerBill 157c87b2a2 Fix typo 2022-07-15 00:34:26 +01:00
gingerBill d3081bd889 Add buffer_read_ptr and buffer_write_ptr 2022-07-14 15:26:50 +01:00
gingerBill 2ae5bf4395 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-07-14 11:56:13 +01:00
gingerBill f28547cae1 Fix libc.putchar 2022-07-14 11:56:05 +01:00
Jeroen van Rijn 5332705e31 [hash] Give crc-64 a 64-bit seed. 2022-07-14 11:07:52 +02:00
gingerBill bfb082cda4 Merge pull request #1881 from odin-lang/strings-builder-cleanup
Rename strings.Builder procedures to be consistent with the rest of the core library
2022-07-13 16:09:19 +01:00
gingerBill 37d04198ab Add improved error message when doing ^x instead of &x for addressable variables 2022-07-11 12:31:01 +01:00
gingerBill ae9d540c1c Correct naming in tests 2022-07-11 11:55:49 +01:00
gingerBill c90b7c38f1 Rename strings.Builder procedures to be consistent with the rest of the core library 2022-07-11 11:50:08 +01:00
gingerBill 9e376fbda7 Update README.md 2022-07-10 00:52:59 +01:00
Wes Hardee 00739bf06d Merge branch 'odin-lang:master' into master 2022-07-09 18:09:21 -05:00
gingerBill e8148055ad Fix compilation on non-windows platforms 2022-07-09 23:55:02 +01:00
gingerBill dd0a20ab45 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-07-09 23:53:24 +01:00
gingerBill babbc304b8 Fix wasm compilation in windows 2022-07-09 23:53:18 +01:00
Mohamed Akram a8b44f33bd Allow passing config options to build script 2022-07-08 16:14:54 +04:00
gingerBill bd48561688 Merge pull request #1865 from thePHTest/ogl_bindless
Add OpenGL bindless textures ARB api to vendor
2022-07-05 20:03:15 +01:00
Wes Hardee 23842a8950 fix -build-mode:shared on MacOS 2022-06-30 12:40:32 -05:00
Phil 0a8e6169d7 remove unneeded semicolons 2022-06-28 11:36:50 -07:00
Phil b89bb87759 Add OpenGL bindless textures ARB api to vendor 2022-06-27 14:50:24 -07:00
Ronald1985 89222a0ab2 Added missing #includes on OpenBSD 2022-06-14 09:55:06 +01:00
phillvancejr a315e7c962 Reverted experimental changes that were meant for a branch, in sync with master 2022-02-04 13:45:36 -05:00
phillvancejr 42364f2fce sync with main 2022-02-04 13:16:40 -05:00
phillvancejr 8f600798ef stb_image 2022-02-04 13:03:20 -05:00
phillvancejr f28c268d97 move libgflw3.a to lib/darwin 2022-01-24 10:03:38 -05:00
phillvancejr f1cff20249 moved mac os glfw static lib to lib/darwin subdirectory 2022-01-24 10:02:56 -05:00
90 changed files with 1387 additions and 896 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
name: CI name: CI
on: [push, pull_request] on: [push, pull_request, workflow_dispatch]
jobs: jobs:
build_linux: build_linux:
+43
View File
@@ -0,0 +1,43 @@
name: "Close Stale Issues & PRs"
on:
workflow_dispatch:
schedule:
- cron: "0 21 * * *"
permissions:
issues: write
pull-requests: write
jobs:
stale:
runs-on: ubuntu-latest
steps:
- name: Close Stale Issues
uses: actions/stale@v4.1.0
with:
# stale-issue-message: |
# Hello!
#
# I am marking this issue as stale as it has not received any engagement from the community or maintainers 120 days. That does not imply that the issue has no merit! If you feel strongly about this issue
# - open a PR referencing and resolving the issue;
# - leave a comment on it and discuss ideas how you could contribute towards resolving it;
# - leave a comment and describe in detail why this issue is critical for your use case;
# - open a new issue with updated details and a plan on resolving the issue.
#
# The motivation for this automation is to help prioritize issues in the backlog and not ignore, reject, or belittle anyone..
#
# stale-pr-message: |
# Hello!
#
# I am marking this PR as stale as it has not received any engagement from the community or maintainers 120 days. That does not imply that the issue has no merit! If you feel strongly about this issue
# - leave a comment on it and discuss ideas how you could contribute towards resolving it;
# - leave a comment and describe in detail why this issue is critical for your use case;
#
# The motivation for this automation is to help prioritize issues in the backlog and not ignore, reject, or belittle anyone..
days-before-stale: 120
days-before-close: 30
exempt-draft-pr: true
ascending: true
operations-per-run: 1000
exempt-issue-labels: "ignore"
+1 -1
View File
@@ -58,7 +58,7 @@ set libs= ^
set linker_flags= -incremental:no -opt:ref -subsystem:console set linker_flags= -incremental:no -opt:ref -subsystem:console
if %release_mode% EQU 0 ( rem Debug if %release_mode% EQU 0 ( rem Debug
set linker_flags=%linker_flags% -debug set linker_flags=%linker_flags% -debug /NATVIS:src\odin_compiler.natvis
) else ( rem Release ) else ( rem Release
set linker_flags=%linker_flags% -debug set linker_flags=%linker_flags% -debug
) )
+34 -22
View File
@@ -1,12 +1,20 @@
#!/bin/bash #!/usr/bin/env bash
set -eu set -eu
GIT_SHA=$(git rev-parse --short HEAD) : ${CXX=clang++}
: ${CPPFLAGS=}
: ${CXXFLAGS=}
: ${LDFLAGS=}
: ${ODIN_VERSION=dev-$(date +"%Y-%m")}
CPPFLAGS="$CPPFLAGS -DODIN_VERSION_RAW=\"$ODIN_VERSION\""
CXXFLAGS="$CXXFLAGS -std=c++14"
LDFLAGS="$LDFLAGS -pthread -lm -lstdc++"
GIT_SHA=$(git rev-parse --short HEAD || :)
if [ "$GIT_SHA" ]; then CPPFLAGS="$CPPFLAGS -DGIT_SHA=\"$GIT_SHA\""; fi
DISABLED_WARNINGS="-Wno-switch -Wno-macro-redefined -Wno-unused-value" DISABLED_WARNINGS="-Wno-switch -Wno-macro-redefined -Wno-unused-value"
LDFLAGS="-pthread -lm -lstdc++"
CFLAGS="-std=c++14 -DGIT_SHA=\"$GIT_SHA\""
CFLAGS="$CFLAGS -DODIN_VERSION_RAW=\"dev-$(date +"%Y-%m")\""
CC=clang
OS=$(uname) OS=$(uname)
panic() { panic() {
@@ -18,7 +26,7 @@ version() { echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }';
config_darwin() { config_darwin() {
ARCH=$(uname -m) ARCH=$(uname -m)
LLVM_CONFIG=llvm-config : ${LLVM_CONFIG=llvm-config}
# allow for arm only llvm's with version 13 # allow for arm only llvm's with version 13
if [ ARCH == arm64 ]; then if [ ARCH == arm64 ]; then
@@ -37,34 +45,38 @@ config_darwin() {
fi fi
LDFLAGS="$LDFLAGS -liconv -ldl" LDFLAGS="$LDFLAGS -liconv -ldl"
CFLAGS="$CFLAGS $($LLVM_CONFIG --cxxflags --ldflags)" CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
LDFLAGS="$LDFLAGS -lLLVM-C" LDFLAGS="$LDFLAGS -lLLVM-C"
} }
config_freebsd() { config_freebsd() {
LLVM_CONFIG=/usr/local/bin/llvm-config11 : ${LLVM_CONFIG=/usr/local/bin/llvm-config11}
CFLAGS="$CFLAGS $($LLVM_CONFIG --cxxflags --ldflags)" CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)" LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)"
} }
config_openbsd() { config_openbsd() {
LLVM_CONFIG=/usr/local/bin/llvm-config : ${LLVM_CONFIG=/usr/local/bin/llvm-config}
LDFLAGS="$LDFLAGS -liconv" LDFLAGS="$LDFLAGS -liconv"
CFLAGS="$CFLAGS $($LLVM_CONFIG --cxxflags --ldflags)" CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)" LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)"
} }
config_linux() { config_linux() {
if which llvm-config > /dev/null 2>&1; then : ${LLVM_CONFIG=}
LLVM_CONFIG=llvm-config
elif which llvm-config-11 > /dev/null 2>&1; then if [ ! "$LLVM_CONFIG" ]; then
LLVM_CONFIG=llvm-config-11 if which llvm-config > /dev/null 2>&1; then
elif which llvm-config-11-64 > /dev/null 2>&1; then LLVM_CONFIG=llvm-config
LLVM_CONFIG=llvm-config-11-64 elif which llvm-config-11 > /dev/null 2>&1; then
else LLVM_CONFIG=llvm-config-11
panic "Unable to find LLVM-config" elif which llvm-config-11-64 > /dev/null 2>&1; then
LLVM_CONFIG=llvm-config-11-64
else
panic "Unable to find LLVM-config"
fi
fi fi
MIN_LLVM_VERSION=("11.0.0") MIN_LLVM_VERSION=("11.0.0")
@@ -74,7 +86,7 @@ config_linux() {
fi fi
LDFLAGS="$LDFLAGS -ldl" LDFLAGS="$LDFLAGS -ldl"
CFLAGS="$CFLAGS $($LLVM_CONFIG --cxxflags --ldflags)" CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)" LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)"
} }
@@ -97,7 +109,7 @@ build_odin() {
esac esac
set -x set -x
$CC src/main.cpp src/libtommath.cpp $DISABLED_WARNINGS $CFLAGS $EXTRAFLAGS $LDFLAGS -o odin $CXX src/main.cpp src/libtommath.cpp $DISABLED_WARNINGS $CPPFLAGS $CXXFLAGS $EXTRAFLAGS $LDFLAGS -o odin
set +x set +x
} }
+8
View File
@@ -161,6 +161,10 @@ buffer_write :: proc(b: ^Buffer, p: []byte) -> (n: int, err: io.Error) {
return copy(b.buf[m:], p), nil return copy(b.buf[m:], p), nil
} }
buffer_write_ptr :: proc(b: ^Buffer, ptr: rawptr, size: int) -> (n: int, err: io.Error) {
return buffer_write(b, ([^]byte)(ptr)[:size])
}
buffer_write_string :: proc(b: ^Buffer, s: string) -> (n: int, err: io.Error) { buffer_write_string :: proc(b: ^Buffer, s: string) -> (n: int, err: io.Error) {
b.last_read = .Invalid b.last_read = .Invalid
m, ok := _buffer_try_grow(b, len(s)) m, ok := _buffer_try_grow(b, len(s))
@@ -229,6 +233,10 @@ buffer_read :: proc(b: ^Buffer, p: []byte) -> (n: int, err: io.Error) {
return return
} }
buffer_read_ptr :: proc(b: ^Buffer, ptr: rawptr, size: int) -> (n: int, err: io.Error) {
return buffer_read(b, ([^]byte)(ptr)[:size])
}
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) {
b.last_read = .Invalid b.last_read = .Invalid
+1 -1
View File
@@ -519,7 +519,7 @@ join_adjacent_string_literals :: proc(cpp: ^Preprocessor, initial_tok: ^Token) {
quote_string :: proc(s: string) -> []byte { quote_string :: proc(s: string) -> []byte {
b := strings.make_builder(0, len(s)+2) b := strings.builder_make(0, len(s)+2)
io.write_quoted_string(strings.to_writer(&b), s, '"') io.write_quoted_string(strings.to_writer(&b), s, '"')
return b.buf[:] return b.buf[:]
} }
+1 -1
View File
@@ -196,7 +196,7 @@ foreign libc {
getc :: proc(stream: ^FILE) -> int --- getc :: proc(stream: ^FILE) -> int ---
getchar :: proc() -> int --- getchar :: proc() -> int ---
putc :: proc(c: int, stream: ^FILE) -> int --- putc :: proc(c: int, stream: ^FILE) -> int ---
putchar :: proc() -> int --- putchar :: proc(c: int) -> int ---
puts :: proc(s: cstring) -> int --- puts :: proc(s: cstring) -> int ---
ungetc :: proc(c: int, stream: ^FILE) -> int --- ungetc :: proc(c: int, stream: ^FILE) -> int ---
fread :: proc(ptr: rawptr, size: size_t, nmemb: size_t, stream: ^FILE) -> size_t --- fread :: proc(ptr: rawptr, size: size_t, nmemb: size_t, stream: ^FILE) -> size_t ---
+4 -4
View File
@@ -25,8 +25,8 @@ import "core:strings"
MAX_RUNE_CODEPOINT :: int(unicode.MAX_RUNE) MAX_RUNE_CODEPOINT :: int(unicode.MAX_RUNE)
write_rune :: strings.write_rune_builder write_rune :: strings.write_rune
write_string :: strings.write_string_builder write_string :: strings.write_string
Error :: enum u8 { Error :: enum u8 {
None = 0, None = 0,
@@ -94,8 +94,8 @@ decode_xml :: proc(input: string, options := XML_Decode_Options{}, allocator :=
l := len(input) l := len(input)
if l == 0 { return "", .None } if l == 0 { return "", .None }
builder := strings.make_builder() builder := strings.builder_make()
defer strings.destroy_builder(&builder) defer strings.builder_destroy(&builder)
t := Tokenizer{src=input} t := Tokenizer{src=input}
in_data := false in_data := false
@@ -8,7 +8,7 @@ import "core:time"
doc_print :: proc(doc: ^xml.Document) { doc_print :: proc(doc: ^xml.Document) {
buf: strings.Builder buf: strings.Builder
defer strings.destroy_builder(&buf) defer strings.builder_destroy(&buf)
w := strings.to_writer(&buf) w := strings.to_writer(&buf)
xml.print(w, doc) xml.print(w, doc)
+2 -2
View File
@@ -18,9 +18,9 @@ Marshal_Error :: union #shared_nil {
} }
marshal :: proc(v: any, allocator := context.allocator) -> (data: []byte, err: Marshal_Error) { marshal :: proc(v: any, allocator := context.allocator) -> (data: []byte, err: Marshal_Error) {
b := strings.make_builder(allocator) b := strings.builder_make(allocator)
defer if err != nil { defer if err != nil {
strings.destroy_builder(&b) strings.builder_destroy(&b)
} }
marshal_to_builder(&b, v) or_return marshal_to_builder(&b, v) or_return
+2 -2
View File
@@ -325,7 +325,7 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm
UNSUPPORTED_TYPE := Unsupported_Type_Error{v.id, p.curr_token} UNSUPPORTED_TYPE := Unsupported_Type_Error{v.id, p.curr_token}
if end_token == .Close_Brace { if end_token == .Close_Brace {
assert(expect_token(p, .Open_Brace) == nil) unmarshal_expect_token(p, .Open_Brace)
} }
v := v v := v
@@ -473,7 +473,7 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm
} }
if end_token == .Close_Brace { if end_token == .Close_Brace {
assert(expect_token(p, .Close_Brace) == nil) unmarshal_expect_token(p, .Close_Brace)
} }
return return
} }
+1 -1
View File
@@ -84,7 +84,7 @@ example :: proc() {
doc_hash :: proc(doc: ^xml.Document, print := false) -> (crc32: u32) { doc_hash :: proc(doc: ^xml.Document, print := false) -> (crc32: u32) {
buf: strings.Builder buf: strings.Builder
defer strings.destroy_builder(&buf) defer strings.builder_destroy(&buf)
w := strings.to_writer(&buf) w := strings.to_writer(&buf)
xml.print(w, doc) xml.print(w, doc)
+8 -8
View File
@@ -77,7 +77,7 @@ register_user_formatter :: proc(id: typeid, formatter: User_Formatter) -> Regist
// They must be freed accordingly // They must be freed accordingly
aprint :: proc(args: ..any, sep := " ") -> string { aprint :: proc(args: ..any, sep := " ") -> string {
str: strings.Builder str: strings.Builder
strings.init_builder(&str) strings.builder_init(&str)
sbprint(buf=&str, args=args, sep=sep) sbprint(buf=&str, args=args, sep=sep)
return strings.to_string(str) return strings.to_string(str)
} }
@@ -85,7 +85,7 @@ aprint :: proc(args: ..any, sep := " ") -> string {
// They must be freed accordingly // They must be freed accordingly
aprintln :: proc(args: ..any, sep := " ") -> string { aprintln :: proc(args: ..any, sep := " ") -> string {
str: strings.Builder str: strings.Builder
strings.init_builder(&str) strings.builder_init(&str)
sbprintln(buf=&str, args=args, sep=sep) sbprintln(buf=&str, args=args, sep=sep)
return strings.to_string(str) return strings.to_string(str)
} }
@@ -93,7 +93,7 @@ aprintln :: proc(args: ..any, sep := " ") -> string {
// They must be freed accordingly // They must be freed accordingly
aprintf :: proc(fmt: string, args: ..any) -> string { aprintf :: proc(fmt: string, args: ..any) -> string {
str: strings.Builder str: strings.Builder
strings.init_builder(&str) strings.builder_init(&str)
sbprintf(&str, fmt, ..args) sbprintf(&str, fmt, ..args)
return strings.to_string(str) return strings.to_string(str)
} }
@@ -102,21 +102,21 @@ aprintf :: proc(fmt: string, args: ..any) -> string {
// tprint procedure return a string that was allocated with the current context's temporary allocator // tprint procedure return a string that was allocated with the current context's temporary allocator
tprint :: proc(args: ..any, sep := " ") -> string { tprint :: proc(args: ..any, sep := " ") -> string {
str: strings.Builder str: strings.Builder
strings.init_builder(&str, context.temp_allocator) strings.builder_init(&str, context.temp_allocator)
sbprint(buf=&str, args=args, sep=sep) sbprint(buf=&str, args=args, sep=sep)
return strings.to_string(str) return strings.to_string(str)
} }
// tprintln procedure return a string that was allocated with the current context's temporary allocator // tprintln procedure return a string that was allocated with the current context's temporary allocator
tprintln :: proc(args: ..any, sep := " ") -> string { tprintln :: proc(args: ..any, sep := " ") -> string {
str: strings.Builder str: strings.Builder
strings.init_builder(&str, context.temp_allocator) strings.builder_init(&str, context.temp_allocator)
sbprintln(buf=&str, args=args, sep=sep) sbprintln(buf=&str, args=args, sep=sep)
return strings.to_string(str) return strings.to_string(str)
} }
// tprintf procedure return a string that was allocated with the current context's temporary allocator // tprintf procedure return a string that was allocated with the current context's temporary allocator
tprintf :: proc(fmt: string, args: ..any) -> string { tprintf :: proc(fmt: string, args: ..any) -> string {
str: strings.Builder str: strings.Builder
strings.init_builder(&str, context.temp_allocator) strings.builder_init(&str, context.temp_allocator)
sbprintf(&str, fmt, ..args) sbprintf(&str, fmt, ..args)
return strings.to_string(str) return strings.to_string(str)
} }
@@ -776,7 +776,7 @@ fmt_rune :: proc(fi: ^Info, r: rune, verb: rune) {
case 'c', 'r', 'v': case 'c', 'r', 'v':
io.write_rune(fi.writer, r, &fi.n) io.write_rune(fi.writer, r, &fi.n)
case 'q': case 'q':
fi.n += strings.write_quoted_rune(fi.writer, r) fi.n += io.write_quoted_rune(fi.writer, r)
case: case:
fmt_int(fi, u64(r), false, 32, verb) fmt_int(fi, u64(r), false, 32, verb)
} }
@@ -1014,7 +1014,7 @@ fmt_pointer :: proc(fi: ^Info, p: rawptr, verb: rune) {
u := u64(uintptr(p)) u := u64(uintptr(p))
switch verb { switch verb {
case 'p', 'v': case 'p', 'v':
if !fi.hash || verb == 'v' { if !fi.hash && verb == 'v' {
io.write_string(fi.writer, "0x", &fi.n) io.write_string(fi.writer, "0x", &fi.n)
} }
_fmt_int(fi, u, 16, false, 8*size_of(rawptr), __DIGITS_UPPER) _fmt_int(fi, u, 16, false, 8*size_of(rawptr), __DIGITS_UPPER)
+2 -2
View File
@@ -1,8 +1,8 @@
package hash package hash
@(optimization_mode="speed") @(optimization_mode="speed")
crc64_ecma_182 :: proc(data: []byte, seed := u32(0)) -> u64 #no_bounds_check { crc64_ecma_182 :: proc(data: []byte, seed := u64(0)) -> (result: u64) #no_bounds_check {
result := u64(seed) result = seed
#no_bounds_check for b in data { #no_bounds_check for b in data {
result = result<<8 ~ _crc64_table_ecma_182[((result>>56) ~ u64(b)) & 0xff] result = result<<8 ~ _crc64_table_ecma_182[((result>>56) ~ u64(b)) & 0xff]
} }
+101 -95
View File
@@ -172,108 +172,114 @@ murmur32 :: proc(data: []byte, seed := u32(0)) -> u32 {
return h1 return h1
} }
// See https://github.com/aappleby/smhasher/blob/master/src/MurmurHash2.cpp#L96
@(optimization_mode="speed") @(optimization_mode="speed")
murmur64 :: proc(data: []byte, seed := u64(0x9747b28c)) -> u64 { murmur64a :: proc(data: []byte, seed := u64(0x9747b28c)) -> u64 {
when size_of(int) == 8 { m :: 0xc6a4a7935bd1e995
m :: 0xc6a4a7935bd1e995 r :: 47
r :: 47
h: u64 = seed ~ (u64(len(data)) * m) h: u64 = seed ~ (u64(len(data)) * m)
data64 := mem.slice_ptr(cast(^u64)raw_data(data), len(data)/size_of(u64)) data64 := mem.slice_data_cast([]u64, data)
for _, i in data64 { for _, i in data64 {
k := data64[i] k := data64[i]
k *= m k *= m
k ~= k>>r k ~= k>>r
k *= m k *= m
h ~= k h ~= k
h *= m
}
switch len(data)&7 {
case 7: h ~= u64(data[6]) << 48; fallthrough
case 6: h ~= u64(data[5]) << 40; fallthrough
case 5: h ~= u64(data[4]) << 32; fallthrough
case 4: h ~= u64(data[3]) << 24; fallthrough
case 3: h ~= u64(data[2]) << 16; fallthrough
case 2: h ~= u64(data[1]) << 8; fallthrough
case 1:
h ~= u64(data[0])
h *= m
}
h ~= h>>r
h *= m h *= m
h ~= h>>r
return h
} else {
m :: 0x5bd1e995
r :: 24
h1 := u32(seed) ~ u32(len(data))
h2 := u32(seed) >> 32
data32 := mem.slice_ptr(cast(^u32)raw_data(data), len(data)/size_of(u32))
len := len(data)
i := 0
for len >= 8 {
k1, k2: u32
k1 = data32[i]; i += 1
k1 *= m
k1 ~= k1>>r
k1 *= m
h1 *= m
h1 ~= k1
len -= 4
k2 = data32[i]; i += 1
k2 *= m
k2 ~= k2>>r
k2 *= m
h2 *= m
h2 ~= k2
len -= 4
}
if len >= 4 {
k1: u32
k1 = data32[i]; i += 1
k1 *= m
k1 ~= k1>>r
k1 *= m
h1 *= m
h1 ~= k1
len -= 4
}
// TODO(bill): Fix this
#no_bounds_check data8 := mem.slice_to_bytes(data32[i:])[:3]
switch len {
case 3:
h2 ~= u32(data8[2]) << 16
fallthrough
case 2:
h2 ~= u32(data8[1]) << 8
fallthrough
case 1:
h2 ~= u32(data8[0])
h2 *= m
}
h1 ~= h2>>18
h1 *= m
h2 ~= h1>>22
h2 *= m
h1 ~= h2>>17
h1 *= m
h2 ~= h1>>19
h2 *= m
return u64(h1)<<32 | u64(h2)
} }
offset := len(data64) * size_of(u64)
switch len(data)&7 {
case 7: h ~= u64(data[offset + 6]) << 48; fallthrough
case 6: h ~= u64(data[offset + 5]) << 40; fallthrough
case 5: h ~= u64(data[offset + 4]) << 32; fallthrough
case 4: h ~= u64(data[offset + 3]) << 24; fallthrough
case 3: h ~= u64(data[offset + 2]) << 16; fallthrough
case 2: h ~= u64(data[offset + 1]) << 8; fallthrough
case 1:
h ~= u64(data[offset + 0])
h *= m
}
h ~= h>>r
h *= m
h ~= h>>r
return h
}
// See https://github.com/aappleby/smhasher/blob/master/src/MurmurHash2.cpp#L140
@(optimization_mode="speed")
murmur64b :: proc(data: []byte, seed := u64(0x9747b28c)) -> u64 {
m :: 0x5bd1e995
r :: 24
h1 := u32(seed) ~ u32(len(data))
h2 := u32(seed) >> 32
data32 := mem.slice_ptr(cast(^u32)raw_data(data), len(data)/size_of(u32))
len := len(data)
i := 0
for len >= 8 {
k1, k2: u32
k1 = data32[i]; i += 1
k1 *= m
k1 ~= k1>>r
k1 *= m
h1 *= m
h1 ~= k1
len -= 4
k2 = data32[i]; i += 1
k2 *= m
k2 ~= k2>>r
k2 *= m
h2 *= m
h2 ~= k2
len -= 4
}
if len >= 4 {
k1: u32
k1 = data32[i]; i += 1
k1 *= m
k1 ~= k1>>r
k1 *= m
h1 *= m
h1 ~= k1
len -= 4
}
// TODO(bill): Fix this
#no_bounds_check data8 := mem.slice_to_bytes(data32[i:])[:3]
switch len {
case 3:
h2 ~= u32(data8[2]) << 16
fallthrough
case 2:
h2 ~= u32(data8[1]) << 8
fallthrough
case 1:
h2 ~= u32(data8[0])
h2 *= m
}
h1 ~= h2>>18
h1 *= m
h2 ~= h1>>22
h2 *= m
h1 ~= h2>>17
h1 *= m
h2 ~= h1>>19
h2 *= m
return u64(h1)<<32 | u64(h2)
} }
@(optimization_mode="speed") @(optimization_mode="speed")
+2 -2
View File
@@ -130,7 +130,7 @@ save_to_buffer :: proc(img: ^Image, custom_info: Info = {}, allocator := context
// we will write to a string builder // we will write to a string builder
data: strings.Builder data: strings.Builder
strings.init_builder(&data) strings.builder_init(&data)
// all PNM headers start with the format // all PNM headers start with the format
fmt.sbprintf(&data, "%s\n", header.format) fmt.sbprintf(&data, "%s\n", header.format)
@@ -409,7 +409,7 @@ _parse_header_pam :: proc(data: []byte, allocator := context.allocator) -> (head
// string buffer for the tupltype // string buffer for the tupltype
tupltype: strings.Builder tupltype: strings.Builder
strings.init_builder(&tupltype, context.temp_allocator); defer strings.destroy_builder(&tupltype) strings.builder_init(&tupltype, context.temp_allocator); defer strings.builder_destroy(&tupltype)
fmt.sbprint(&tupltype, "") fmt.sbprint(&tupltype, "")
// PAM uses actual lines, so we can iterate easily // PAM uses actual lines, so we can iterate easily
+24
View File
@@ -247,6 +247,30 @@ write_quoted_string :: proc(w: Writer, str: string, quote: byte = '"', n_written
return return
} }
// writer append a quoted rune into the byte buffer, return the written size
write_quoted_rune :: proc(w: Writer, r: rune) -> (n: int) {
_write_byte :: #force_inline proc(w: Writer, c: byte) -> int {
err := write_byte(w, c)
return 1 if err == nil else 0
}
quote := byte('\'')
n += _write_byte(w, quote)
buf, width := utf8.encode_rune(r)
if width == 1 && r == utf8.RUNE_ERROR {
n += _write_byte(w, '\\')
n += _write_byte(w, 'x')
n += _write_byte(w, DIGITS_LOWER[buf[0]>>4])
n += _write_byte(w, DIGITS_LOWER[buf[0]&0xf])
} else {
i, _ := write_escaped_rune(w, r, quote)
n += i
}
n += _write_byte(w, quote)
return
}
Tee_Reader :: struct { Tee_Reader :: struct {
+3 -3
View File
@@ -476,21 +476,21 @@ quaternion_angle_axis :: proc{
angle_from_quaternion_f16 :: proc(q: Quaternionf16) -> f16 { angle_from_quaternion_f16 :: proc(q: Quaternionf16) -> f16 {
if abs(q.w) > math.SQRT_THREE*0.5 { if abs(q.w) > math.SQRT_THREE*0.5 {
return math.asin(q.x*q.x + q.y*q.y + q.z*q.z) * 2 return math.asin(math.sqrt(q.x*q.x + q.y*q.y + q.z*q.z)) * 2
} }
return math.acos(q.w) * 2 return math.acos(q.w) * 2
} }
angle_from_quaternion_f32 :: proc(q: Quaternionf32) -> f32 { angle_from_quaternion_f32 :: proc(q: Quaternionf32) -> f32 {
if abs(q.w) > math.SQRT_THREE*0.5 { if abs(q.w) > math.SQRT_THREE*0.5 {
return math.asin(q.x*q.x + q.y*q.y + q.z*q.z) * 2 return math.asin(math.sqrt(q.x*q.x + q.y*q.y + q.z*q.z)) * 2
} }
return math.acos(q.w) * 2 return math.acos(q.w) * 2
} }
angle_from_quaternion_f64 :: proc(q: Quaternionf64) -> f64 { angle_from_quaternion_f64 :: proc(q: Quaternionf64) -> f64 {
if abs(q.w) > math.SQRT_THREE*0.5 { if abs(q.w) > math.SQRT_THREE*0.5 {
return math.asin(q.x*q.x + q.y*q.y + q.z*q.z) * 2 return math.asin(math.sqrt(q.x*q.x + q.y*q.y + q.z*q.z)) * 2
} }
return math.acos(q.w) * 2 return math.acos(q.w) * 2
+1 -1
View File
@@ -1357,7 +1357,7 @@ atan :: proc "contextless" (x: $T) -> T where intrinsics.type_is_float(T) {
} }
asin :: proc "contextless" (x: $T) -> T where intrinsics.type_is_float(T) { asin :: proc "contextless" (x: $T) -> T where intrinsics.type_is_float(T) {
return atan2(x, 1 + sqrt(1 - x*x)) return atan2(x, sqrt(1 - x*x))
} }
acos :: proc "contextless" (x: $T) -> T where intrinsics.type_is_float(T) { acos :: proc "contextless" (x: $T) -> T where intrinsics.type_is_float(T) {
+148
View File
@@ -0,0 +1,148 @@
//+build darwin
//+private
package mem_virtual
foreign import libc "System.framework"
import "core:c"
PROT_NONE :: 0x0 /* [MC2] no permissions */
PROT_READ :: 0x1 /* [MC2] pages can be read */
PROT_WRITE :: 0x2 /* [MC2] pages can be written */
PROT_EXEC :: 0x4 /* [MC2] pages can be executed */
// Sharing options
MAP_SHARED :: 0x1 /* [MF|SHM] share changes */
MAP_PRIVATE :: 0x2 /* [MF|SHM] changes are private */
// Other flags
MAP_FIXED :: 0x0010 /* [MF|SHM] interpret addr exactly */
MAP_RENAME :: 0x0020 /* Sun: rename private pages to file */
MAP_NORESERVE :: 0x0040 /* Sun: don't reserve needed swap area */
MAP_RESERVED0080 :: 0x0080 /* previously unimplemented MAP_INHERIT */
MAP_NOEXTEND :: 0x0100 /* for MAP_FILE, don't change file size */
MAP_HASSEMAPHORE :: 0x0200 /* region may contain semaphores */
MAP_NOCACHE :: 0x0400 /* don't cache pages for this mapping */
MAP_JIT :: 0x0800 /* Allocate a region that will be used for JIT purposes */
// Mapping type
MAP_FILE :: 0x0000 /* map from file (default) */
MAP_ANONYMOUS :: 0x1000 /* allocated from memory, swap space */
/*
* The MAP_RESILIENT_* flags can be used when the caller wants to map some
* possibly unreliable memory and be able to access it safely, possibly
* getting the wrong contents rather than raising any exception.
* For safety reasons, such mappings have to be read-only (PROT_READ access
* only).
*
* MAP_RESILIENT_CODESIGN:
* accessing this mapping will not generate code-signing violations,
* even if the contents are tainted.
* MAP_RESILIENT_MEDIA:
* accessing this mapping will not generate an exception if the contents
* are not available (unreachable removable or remote media, access beyond
* end-of-file, ...). Missing contents will be replaced with zeroes.
*/
MAP_RESILIENT_CODESIGN :: 0x2000 /* no code-signing failures */
MAP_RESILIENT_MEDIA :: 0x4000 /* no backing-store failures */
MAP_32BIT :: 0x8000 /* Return virtual addresses <4G only */
// Flags used to support translated processes.
MAP_TRANSLATED_ALLOW_EXECUTE :: 0x20000 /* allow execute in translated processes */
MAP_UNIX03 :: 0x40000 /* UNIX03 compliance */
// Process memory locking
MCL_CURRENT :: 0x0001 /* [ML] Lock only current memory */
MCL_FUTURE :: 0x0002 /* [ML] Lock all future memory as well */
MADV_NORMAL :: 0 /* [MC1] no further special treatment */
MADV_RANDOM :: 1 /* [MC1] expect random page refs */
MADV_SEQUENTIAL :: 2 /* [MC1] expect sequential page refs */
MADV_WILLNEED :: 3 /* [MC1] will need these pages */
MADV_DONTNEED :: 4 /* [MC1] dont need these pages */
MADV_FREE :: 5 /* pages unneeded, discard contents */
MADV_ZERO_WIRED_PAGES :: 6 /* zero the wired pages that have not been unwired before the entry is deleted */
MADV_FREE_REUSABLE :: 7 /* pages can be reused (by anyone) */
MADV_FREE_REUSE :: 8 /* caller wants to reuse those pages */
MADV_CAN_REUSE :: 9
MADV_PAGEOUT :: 10 /* page out now (internal only) */
// msync() flags
MS_ASYNC :: 0x0001 /* [MF|SIO] return immediately */
MS_INVALIDATE :: 0x0002 /* [MF|SIO] invalidate all cached data */
MS_SYNC :: 0x0010 /* [MF|SIO] msync synchronously */
MS_KILLPAGES :: 0x0004 /* invalidate pages, leave mapped */
MS_DEACTIVATE :: 0x0008 /* deactivate pages, leave mapped */
// Return bits from mincore
MINCORE_INCORE :: 0x1 /* Page is incore */
MINCORE_REFERENCED :: 0x2 /* Page has been referenced by us */
MINCORE_MODIFIED :: 0x4 /* Page has been modified by us */
MINCORE_REFERENCED_OTHER :: 0x8 /* Page has been referenced */
MINCORE_MODIFIED_OTHER :: 0x10 /* Page has been modified */
MINCORE_PAGED_OUT :: 0x20 /* Page has been paged out */
MINCORE_COPIED :: 0x40 /* Page has been copied */
MINCORE_ANONYMOUS :: 0x80 /* Page belongs to an anonymous object */
// Allocation failure result
MAP_FAILED : rawptr = rawptr(~uintptr(0))
foreign libc {
@(link_name="mlockall") _mlockall :: proc(flags: c.int) -> c.int ---
@(link_name="munlockall") _munlockall :: proc() -> c.int ---
@(link_name="mlock") _mlock :: proc(addr: rawptr, len: c.size_t) -> c.int ---
@(link_name="mmap") _mmap :: proc(addr: rawptr, len: c.size_t, prot: c.int, flags: c.int, fd: c.int, offset: int) -> rawptr ---
@(link_name="mprotect") _mprotect :: proc(addr: rawptr, len: c.size_t, prot: c.int) -> c.int ---
@(link_name="msync") _msync :: proc(addr: rawptr, len: c.size_t) -> c.int ---
@(link_name="munlock") _munlock :: proc(addr: rawptr, len: c.size_t) -> c.int ---
@(link_name="munmap") _munmap :: proc(addr: rawptr, len: c.size_t) -> c.int ---
@(link_name="shm_open") _shm_open :: proc(name: cstring, oflag: c.int, #c_vararg args: ..any) -> c.int ---
@(link_name="shm_unlink") _shm_unlink :: proc(name: cstring) -> c.int ---
@(link_name="posix_madvise") _posix_madvise :: proc(addr: rawptr, len: c.size_t, advice: c.int) -> c.int ---
@(link_name="madvise") _madvise :: proc(addr: rawptr, len: c.size_t, advice: c.int) -> c.int ---
@(link_name="mincore") _mincore :: proc(addr: rawptr, len: c.size_t, vec: cstring) -> c.int ---
@(link_name="minherit") _minherit :: proc(addr: rawptr, len: c.size_t, inherit: c.int) -> c.int ---
}
_reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) {
result := _mmap(nil, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
if result == MAP_FAILED {
return nil, .Out_Of_Memory
}
return ([^]byte)(uintptr(result))[:size], nil
}
_commit :: proc "contextless" (data: rawptr, size: uint) -> Allocator_Error {
result := _mprotect(data, size, PROT_READ|PROT_WRITE)
if result != 0 {
return .Out_Of_Memory
}
return nil
}
_decommit :: proc "contextless" (data: rawptr, size: uint) {
_mprotect(data, size, PROT_NONE)
_madvise(data, size, MADV_FREE)
}
_release :: proc "contextless" (data: rawptr, size: uint) {
_munmap(data, size)
}
_protect :: proc "contextless" (data: rawptr, size: uint, flags: Protect_Flags) -> bool {
pflags: c.int
pflags = PROT_NONE
if .Read in flags { pflags |= PROT_READ }
if .Write in flags { pflags |= PROT_WRITE }
if .Execute in flags { pflags |= PROT_EXEC }
err := _mprotect(data, size, pflags)
return err != 0
}
_platform_memory_init :: proc() {
DEFAULT_PAGE_SIZE = 4096
// is power of two
assert(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0)
}
+36 -1
View File
@@ -552,13 +552,20 @@ unparen_expr :: proc(expr: ^Expr) -> (val: ^Expr) {
return return
} }
Field_Flags :: distinct bit_set[Field_Flag]
Field_Flag :: enum { Field_Flag :: enum {
Invalid,
Unknown,
Ellipsis, Ellipsis,
Using, Using,
No_Alias, No_Alias,
C_Vararg, C_Vararg,
Auto_Cast, Auto_Cast,
Any_Int, Any_Int,
Subtype,
By_Ptr,
Results, Results,
Tags, Tags,
@@ -566,11 +573,38 @@ Field_Flag :: enum {
Typeid_Token, Typeid_Token,
} }
Field_Flags :: distinct bit_set[Field_Flag] field_flag_strings := [Field_Flag]string{
.Invalid = "",
.Unknown = "",
.Ellipsis = "..",
.Using = "using",
.No_Alias = "#no_alias",
.C_Vararg = "#c_vararg",
.Auto_Cast = "auto_cast",
.Any_Int = "#any_int",
.Subtype = "#subtype",
.By_Ptr = "#by_ptr",
.Results = "results",
.Tags = "field tag",
.Default_Parameters = "default parameters",
.Typeid_Token = "typeid",
}
field_hash_flag_strings := []struct{key: string, flag: Field_Flag}{
{"no_alias", .No_Alias},
{"c_vararg", .C_Vararg},
{"any_int", .Any_Int},
{"subtype", .Subtype},
{"by_ptr", .By_Ptr},
}
Field_Flags_Struct :: Field_Flags{ Field_Flags_Struct :: Field_Flags{
.Using, .Using,
.Tags, .Tags,
.Subtype,
} }
Field_Flags_Record_Poly_Params :: Field_Flags{ Field_Flags_Record_Poly_Params :: Field_Flags{
.Typeid_Token, .Typeid_Token,
@@ -583,6 +617,7 @@ Field_Flags_Signature :: Field_Flags{
.C_Vararg, .C_Vararg,
.Auto_Cast, .Auto_Cast,
.Any_Int, .Any_Int,
.By_Ptr,
.Default_Parameters, .Default_Parameters,
} }
+24 -71
View File
@@ -1611,20 +1611,6 @@ new_ast_field :: proc(names: []^ast.Expr, type: ^ast.Expr, default_value: ^ast.E
return field return field
} }
Field_Prefix :: enum {
Invalid,
Unknown,
Using,
No_Alias,
C_Vararg,
Auto_Cast,
Any_Int,
}
Field_Prefixes :: distinct bit_set[Field_Prefix]
Expr_And_Flags :: struct { Expr_And_Flags :: struct {
expr: ^ast.Expr, expr: ^ast.Expr,
flags: ast.Field_Flags, flags: ast.Field_Flags,
@@ -1666,7 +1652,7 @@ convert_to_ident_list :: proc(p: ^Parser, list: []Expr_And_Flags, ignore_flags,
return idents[:] return idents[:]
} }
is_token_field_prefix :: proc(p: ^Parser) -> Field_Prefix { is_token_field_prefix :: proc(p: ^Parser) -> ast.Field_Flag {
#partial switch p.curr_tok.kind { #partial switch p.curr_tok.kind {
case .EOF: case .EOF:
return .Invalid return .Invalid
@@ -1677,17 +1663,15 @@ is_token_field_prefix :: proc(p: ^Parser) -> Field_Prefix {
advance_token(p) advance_token(p)
return .Auto_Cast return .Auto_Cast
case .Hash: case .Hash:
tok: tokenizer.Token
advance_token(p) advance_token(p)
defer advance_token(p) tok = p.curr_tok
#partial switch p.curr_tok.kind { advance_token(p)
case .Ident: if tok.kind == .Ident {
switch p.curr_tok.text { for kf in ast.field_hash_flag_strings {
case "no_alias": if kf.key == tok.text {
return .No_Alias return kf.flag
case "c_vararg": }
return .C_Vararg
case "any_int":
return .Any_Int
} }
} }
return .Unknown return .Unknown
@@ -1695,8 +1679,8 @@ is_token_field_prefix :: proc(p: ^Parser) -> Field_Prefix {
return .Invalid return .Invalid
} }
parse_field_prefixes :: proc(p: ^Parser) -> ast.Field_Flags { parse_field_prefixes :: proc(p: ^Parser) -> (flags: ast.Field_Flags) {
counts: [len(Field_Prefix)]int counts: [len(ast.Field_Flag)]int
for { for {
kind := is_token_field_prefix(p) kind := is_token_field_prefix(p)
@@ -1712,31 +1696,17 @@ parse_field_prefixes :: proc(p: ^Parser) -> ast.Field_Flags {
counts[kind] += 1 counts[kind] += 1
} }
flags: ast.Field_Flags for kind in ast.Field_Flag {
for kind in Field_Prefix {
count := counts[kind] count := counts[kind]
switch kind { if kind == .Invalid || kind == .Unknown {
case .Invalid, .Unknown: // Ignore // Ignore
case .Using: } else {
if count > 1 { error(p, p.curr_tok.pos, "multiple 'using' in this field list") } if count > 1 { error(p, p.curr_tok.pos, "multiple '%s' in this field list", ast.field_flag_strings[kind]) }
if count > 0 { flags += {.Using} } if count > 0 { flags += {kind} }
case .No_Alias:
if count > 1 { error(p, p.curr_tok.pos, "multiple '#no_alias' in this field list") }
if count > 0 { flags += {.No_Alias} }
case .C_Vararg:
if count > 1 { error(p, p.curr_tok.pos, "multiple '#c_vararg' in this field list") }
if count > 0 { flags += {.C_Vararg} }
case .Auto_Cast:
if count > 1 { error(p, p.curr_tok.pos, "multiple 'auto_cast' in this field list") }
if count > 0 { flags += {.Auto_Cast} }
case .Any_Int:
if count > 1 { error(p, p.curr_tok.pos, "multiple '#any_int' in this field list") }
if count > 0 { flags += {.Any_Int} }
} }
} }
return flags return
} }
check_field_flag_prefixes :: proc(p: ^Parser, name_count: int, allowed_flags, set_flags: ast.Field_Flags) -> (flags: ast.Field_Flags) { check_field_flag_prefixes :: proc(p: ^Parser, name_count: int, allowed_flags, set_flags: ast.Field_Flags) -> (flags: ast.Field_Flags) {
@@ -1748,19 +1718,13 @@ check_field_flag_prefixes :: proc(p: ^Parser, name_count: int, allowed_flags, se
for flag in ast.Field_Flag { for flag in ast.Field_Flag {
if flag not_in allowed_flags && flag in flags { if flag not_in allowed_flags && flag in flags {
switch flag { #partial switch flag {
case .Using: case .Unknown, .Invalid:
error(p, p.curr_tok.pos, "'using' is not allowed within this field list") // ignore
case .No_Alias:
error(p, p.curr_tok.pos, "'#no_alias' is not allowed within this field list")
case .C_Vararg:
error(p, p.curr_tok.pos, "'#c_vararg' is not allowed within this field list")
case .Auto_Cast:
error(p, p.curr_tok.pos, "'auto_cast' is not allowed within this field list")
case .Any_Int:
error(p, p.curr_tok.pos, "'#any_int' is not allowed within this field list")
case .Tags, .Ellipsis, .Results, .Default_Parameters, .Typeid_Token: case .Tags, .Ellipsis, .Results, .Default_Parameters, .Typeid_Token:
panic("Impossible prefixes") panic("Impossible prefixes")
case:
error(p, p.curr_tok.pos, "'%s' is not allowed within this field list", ast.field_flag_strings[flag])
} }
flags -= {flag} flags -= {flag}
} }
@@ -2631,7 +2595,6 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
tok := expect_token(p, .Union) tok := expect_token(p, .Union)
poly_params: ^ast.Field_List poly_params: ^ast.Field_List
align: ^ast.Expr align: ^ast.Expr
is_maybe: bool
is_no_nil: bool is_no_nil: bool
is_shared_nil: bool is_shared_nil: bool
@@ -2656,10 +2619,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
} }
align = parse_expr(p, true) align = parse_expr(p, true)
case "maybe": case "maybe":
if is_maybe { error(p, tag.pos, "#%s functionality has now been merged with standard 'union' functionality", tag.text)
error(p, tag.pos, "duplicate union tag '#%s'", tag.text)
}
is_maybe = true
case "no_nil": case "no_nil":
if is_no_nil { if is_no_nil {
error(p, tag.pos, "duplicate union tag '#%s'", tag.text) error(p, tag.pos, "duplicate union tag '#%s'", tag.text)
@@ -2676,19 +2636,12 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
} }
p.expr_level = prev_level p.expr_level = prev_level
if is_no_nil && is_maybe {
error(p, p.curr_tok.pos, "#maybe and #no_nil cannot be applied together")
}
if is_no_nil && is_shared_nil { if is_no_nil && is_shared_nil {
error(p, p.curr_tok.pos, "#shared_nil and #no_nil cannot be applied together") error(p, p.curr_tok.pos, "#shared_nil and #no_nil cannot be applied together")
} }
if is_shared_nil && is_maybe {
error(p, p.curr_tok.pos, "#maybe and #shared_nil cannot be applied together")
}
union_kind := ast.Union_Type_Kind.Normal union_kind := ast.Union_Type_Kind.Normal
switch { switch {
case is_maybe: union_kind = .maybe
case is_no_nil: union_kind = .no_nil case is_no_nil: union_kind = .no_nil
case is_shared_nil: union_kind = .shared_nil case is_shared_nil: union_kind = .shared_nil
} }
+1 -1
View File
@@ -151,7 +151,7 @@ print :: proc(p: ^Printer, file: ^ast.File) -> string {
fix_lines(p) fix_lines(p)
builder := strings.make_builder(0, 5 * mem.Megabyte, p.allocator) builder := strings.builder_make(0, 5 * mem.Megabyte, p.allocator)
last_line := 0 last_line := 0
+3 -3
View File
@@ -71,7 +71,7 @@ push_comment :: proc(p: ^Printer, comment: tokenizer.Token) -> int {
return 0 return 0
} else { } else {
builder := strings.make_builder(context.temp_allocator) builder := strings.builder_make(context.temp_allocator)
c_len := len(comment.text) c_len := len(comment.text)
trim_space := true trim_space := true
@@ -90,12 +90,12 @@ push_comment :: proc(p: ^Printer, comment: tokenizer.Token) -> int {
continue continue
case c == '\r' && comment.text[min(c_len - 1, i + 1)] == '\n': case c == '\r' && comment.text[min(c_len - 1, i + 1)] == '\n':
append(&multilines, strings.to_string(builder)) append(&multilines, strings.to_string(builder))
builder = strings.make_builder(context.temp_allocator) builder = strings.builder_make(context.temp_allocator)
trim_space = true trim_space = true
i += 1 i += 1
case c == '\n': case c == '\n':
append(&multilines, strings.to_string(builder)) append(&multilines, strings.to_string(builder))
builder = strings.make_builder(context.temp_allocator) builder = strings.builder_make(context.temp_allocator)
trim_space = true trim_space = true
case c == '/' && comment.text[min(c_len - 1, i + 1)] == '*': case c == '/' && comment.text[min(c_len - 1, i + 1)] == '*':
strings.write_string(&builder, "/*") strings.write_string(&builder, "/*")
+5 -3
View File
@@ -1,6 +1,5 @@
package os package os
import "core:strings"
import "core:mem" import "core:mem"
read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Errno) { read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Errno) {
@@ -51,10 +50,13 @@ read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []F
continue continue
} }
fullpath := strings.join( []string{ dirpath, filename }, "/", context.temp_allocator) fullpath := make([]byte, len(dirpath)+1+len(filename))
copy(fullpath, dirpath)
copy(fullpath[len(dirpath):], "/")
copy(fullpath[len(dirpath)+1:], filename)
defer delete(fullpath, context.temp_allocator) defer delete(fullpath, context.temp_allocator)
fi_, err = stat(fullpath, allocator) fi_, err = stat(string(fullpath), allocator)
if err != ERROR_NONE { if err != ERROR_NONE {
for fi__ in dfi { for fi__ in dfi {
file_info_delete(fi__, allocator) file_info_delete(fi__, allocator)
+16 -16
View File
@@ -11,24 +11,24 @@ lookup_env :: proc(key: string, allocator := context.allocator) -> (value: strin
return return
} }
wkey := win32.utf8_to_wstring(key) wkey := win32.utf8_to_wstring(key)
b := make([dynamic]u16, 100, context.temp_allocator) n := win32.GetEnvironmentVariableW(wkey, nil, 0)
for { if n == 0 {
n := win32.GetEnvironmentVariableW(wkey, raw_data(b), u32(len(b))) err := win32.GetLastError()
if n == 0 { if err == u32(ERROR_ENVVAR_NOT_FOUND) {
err := win32.GetLastError() return "", false
if err == u32(ERROR_ENVVAR_NOT_FOUND) {
return "", false
}
} }
if n <= u32(len(b)) {
value, _ = win32.utf16_to_utf8(b[:n], allocator)
found = true
return
}
resize(&b, len(b)*2)
} }
b := make([dynamic]u16, n, context.temp_allocator)
n = win32.GetEnvironmentVariableW(wkey, raw_data(b), u32(len(b)))
if n == 0 {
err := win32.GetLastError()
if err == u32(ERROR_ENVVAR_NOT_FOUND) {
return "", false
}
}
value, _ = win32.utf16_to_utf8(b[:n], allocator)
found = true
return
} }
+8 -8
View File
@@ -241,13 +241,13 @@ S_ISGID :: 0o2000 // Set group id on execution
S_ISVTX :: 0o1000 // Directory restrcted delete S_ISVTX :: 0o1000 // Directory restrcted delete
S_ISLNK :: #force_inline proc(m: mode_t) -> bool do return (m & S_IFMT) == S_IFLNK S_ISLNK :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFLNK }
S_ISREG :: #force_inline proc(m: mode_t) -> bool do return (m & S_IFMT) == S_IFREG S_ISREG :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFREG }
S_ISDIR :: #force_inline proc(m: mode_t) -> bool do return (m & S_IFMT) == S_IFDIR S_ISDIR :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFDIR }
S_ISCHR :: #force_inline proc(m: mode_t) -> bool do return (m & S_IFMT) == S_IFCHR S_ISCHR :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFCHR }
S_ISBLK :: #force_inline proc(m: mode_t) -> bool do return (m & S_IFMT) == S_IFBLK S_ISBLK :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFBLK }
S_ISFIFO :: #force_inline proc(m: mode_t) -> bool do return (m & S_IFMT) == S_IFIFO S_ISFIFO :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFIFO }
S_ISSOCK :: #force_inline proc(m: mode_t) -> bool do return (m & S_IFMT) == S_IFSOCK S_ISSOCK :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFSOCK }
F_OK :: 0 // Test for file existance F_OK :: 0 // Test for file existance
X_OK :: 1 // Test for execute permission X_OK :: 1 // Test for execute permission
@@ -257,7 +257,7 @@ R_OK :: 4 // Test for read permission
foreign libc { foreign libc {
@(link_name="__error") __errno_location :: proc() -> ^int --- @(link_name="__error") __errno_location :: proc() -> ^int ---
@(link_name="open") _unix_open :: proc(path: cstring, flags: c.int, mode: c.int) -> Handle --- @(link_name="open") _unix_open :: proc(path: cstring, flags: c.int, mode: c.int) -> Handle ---
@(link_name="close") _unix_close :: proc(fd: Handle) -> c.int --- @(link_name="close") _unix_close :: proc(fd: Handle) -> c.int ---
@(link_name="read") _unix_read :: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t --- @(link_name="read") _unix_read :: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t ---
@(link_name="write") _unix_write :: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t --- @(link_name="write") _unix_write :: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t ---
+1 -1
View File
@@ -271,7 +271,7 @@ _glob :: proc(dir, pattern: string, matches: ^[dynamic]string, allocator := cont
} }
d, derr := os.open(dir) d, derr := os.open(dir, os.O_RDONLY)
if derr != 0 { if derr != 0 {
return return
} }
+1 -1
View File
@@ -146,7 +146,7 @@ clean :: proc(path: string, allocator := context.allocator) -> string {
} }
// join joins numerous path elements into a single path // join joins numerous path elements into a single path
join :: proc(elems: ..string, allocator := context.allocator) -> string { join :: proc(elems: []string, allocator := context.allocator) -> string {
context.allocator = allocator context.allocator = allocator
for elem, i in elems { for elem, i in elems {
if elem != "" { if elem != "" {
+2 -2
View File
@@ -573,11 +573,11 @@ write_type_writer :: proc(w: io.Writer, ti: ^Type_Info, n_written: ^int = nil) -
write_type(w, info.elem, &n) or_return write_type(w, info.elem, &n) or_return
case is_rune(info.elem): case is_rune(info.elem):
io.write_encoded_rune(w, rune(info.lower), true, &n) or_return io.write_encoded_rune(w, rune(info.lower), true, &n) or_return
io.write_string(w, "..", &n) or_return io.write_string(w, "..=", &n) or_return
io.write_encoded_rune(w, rune(info.upper), true, &n) or_return io.write_encoded_rune(w, rune(info.upper), true, &n) or_return
case: case:
io.write_i64(w, info.lower, 10, &n) or_return io.write_i64(w, info.lower, 10, &n) or_return
io.write_string(w, "..", &n) or_return io.write_string(w, "..=", &n) or_return
io.write_i64(w, info.upper, 10, &n) or_return io.write_i64(w, info.upper, 10, &n) or_return
} }
if info.underlying != nil { if info.underlying != nil {
+79 -29
View File
@@ -339,19 +339,22 @@ append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) {
if array == nil { if array == nil {
return return
} }
when size_of(E) == 0 {
if cap(array) < len(array)+1 {
cap := 2 * cap(array) + max(8, 1)
_ = reserve(array, cap, loc)
}
if cap(array)-len(array) > 0 {
a := (^Raw_Dynamic_Array)(array)
when size_of(E) != 0 {
data := ([^]E)(a.data)
assert(condition=data != nil, loc=loc)
data[a.len] = arg
}
a.len += 1 a.len += 1
} else {
if cap(array) < len(array)+1 {
cap := 2 * cap(array) + max(8, 1)
_ = reserve(array, cap, loc)
}
if cap(array)-len(array) > 0 {
a := (^Raw_Dynamic_Array)(array)
when size_of(E) != 0 {
data := ([^]E)(a.data)
assert(condition=data != nil, loc=loc)
data[a.len] = arg
}
a.len += 1
}
} }
} }
@@ -366,20 +369,23 @@ append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location)
return return
} }
when size_of(E) == 0 {
if cap(array) < len(array)+arg_len {
cap := 2 * cap(array) + max(8, arg_len)
_ = reserve(array, cap, loc)
}
arg_len = min(cap(array)-len(array), arg_len)
if arg_len > 0 {
a := (^Raw_Dynamic_Array)(array)
when size_of(E) != 0 {
data := ([^]E)(a.data)
assert(condition=data != nil, loc=loc)
intrinsics.mem_copy(&data[a.len], raw_data(args), size_of(E) * arg_len)
}
a.len += arg_len a.len += arg_len
} else {
if cap(array) < len(array)+arg_len {
cap := 2 * cap(array) + max(8, arg_len)
_ = reserve(array, cap, loc)
}
arg_len = min(cap(array)-len(array), arg_len)
if arg_len > 0 {
a := (^Raw_Dynamic_Array)(array)
when size_of(E) != 0 {
data := ([^]E)(a.data)
assert(condition=data != nil, loc=loc)
intrinsics.mem_copy(&data[a.len], raw_data(args), size_of(E) * arg_len)
}
a.len += arg_len
}
} }
} }
@@ -413,7 +419,7 @@ append_nothing :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) {
@builtin @builtin
insert_at_elem :: proc(array: ^$T/[dynamic]$E, index: int, arg: E, loc := #caller_location) -> (ok: bool) #no_bounds_check { inject_at_elem :: proc(array: ^$T/[dynamic]$E, index: int, arg: E, loc := #caller_location) -> (ok: bool) #no_bounds_check {
if array == nil { if array == nil {
return return
} }
@@ -432,7 +438,7 @@ insert_at_elem :: proc(array: ^$T/[dynamic]$E, index: int, arg: E, loc := #calle
} }
@builtin @builtin
insert_at_elems :: proc(array: ^$T/[dynamic]$E, index: int, args: ..E, loc := #caller_location) -> (ok: bool) #no_bounds_check { inject_at_elems :: proc(array: ^$T/[dynamic]$E, index: int, args: ..E, loc := #caller_location) -> (ok: bool) #no_bounds_check {
if array == nil { if array == nil {
return return
} }
@@ -456,7 +462,7 @@ insert_at_elems :: proc(array: ^$T/[dynamic]$E, index: int, args: ..E, loc := #c
} }
@builtin @builtin
insert_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, index: int, arg: string, loc := #caller_location) -> (ok: bool) #no_bounds_check { inject_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, index: int, arg: string, loc := #caller_location) -> (ok: bool) #no_bounds_check {
if array == nil { if array == nil {
return return
} }
@@ -477,7 +483,51 @@ insert_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, index: int, arg: string
return return
} }
@builtin insert_at :: proc{insert_at_elem, insert_at_elems, insert_at_elem_string} @builtin inject_at :: proc{inject_at_elem, inject_at_elems, inject_at_elem_string}
@builtin
assign_at_elem :: proc(array: ^$T/[dynamic]$E, index: int, arg: E, loc := #caller_location) -> (ok: bool) #no_bounds_check {
if index < len(array) {
array[index] = arg
ok = true
} else if resize(array, index+1, loc) {
array[index] = arg
ok = true
}
return
}
@builtin
assign_at_elems :: proc(array: ^$T/[dynamic]$E, index: int, args: ..E, loc := #caller_location) -> (ok: bool) #no_bounds_check {
if index+len(args) < len(array) {
copy(array[index:], args)
ok = true
} else if resize(array, index+1+len(args), loc) {
copy(array[index:], args)
ok = true
}
return
}
@builtin
assign_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, index: int, arg: string, loc := #caller_location) -> (ok: bool) #no_bounds_check {
if len(args) == 0 {
ok = true
} else if index+len(args) < len(array) {
copy(array[index:], args)
ok = true
} else if resize(array, index+1+len(args), loc) {
copy(array[index:], args)
ok = true
}
return
}
@builtin assign_at :: proc{assign_at_elem, assign_at_elems, assign_at_elem_string}
+43 -105
View File
@@ -17,50 +17,53 @@ Builder :: struct {
} }
// return a builder, default length 0 / cap 16 are done through make // return a builder, default length 0 / cap 16 are done through make
make_builder_none :: proc(allocator := context.allocator) -> Builder { builder_make_none :: proc(allocator := context.allocator) -> Builder {
return Builder{buf=make([dynamic]byte, allocator)} return Builder{buf=make([dynamic]byte, allocator)}
} }
// return a builder, with a set length `len` and cap 16 byte buffer // return a builder, with a set length `len` and cap 16 byte buffer
make_builder_len :: proc(len: int, allocator := context.allocator) -> Builder { builder_make_len :: proc(len: int, allocator := context.allocator) -> Builder {
return Builder{buf=make([dynamic]byte, len, allocator)} return Builder{buf=make([dynamic]byte, len, allocator)}
} }
// return a builder, with a set length `len` byte buffer and a custom `cap` // return a builder, with a set length `len` byte buffer and a custom `cap`
make_builder_len_cap :: proc(len, cap: int, allocator := context.allocator) -> Builder { builder_make_len_cap :: proc(len, cap: int, allocator := context.allocator) -> Builder {
return Builder{buf=make([dynamic]byte, len, cap, allocator)} return Builder{buf=make([dynamic]byte, len, cap, allocator)}
} }
// overload simple `make_builder_*` with or without len / cap parameters // overload simple `builder_make_*` with or without len / cap parameters
make_builder :: proc{ builder_make :: proc{
make_builder_none, builder_make_none,
make_builder_len, builder_make_len,
make_builder_len_cap, builder_make_len_cap,
} }
// initialize a builder, default length 0 / cap 16 are done through make // initialize a builder, default length 0 / cap 16 are done through make
// replaces the existing `buf` // replaces the existing `buf`
init_builder_none :: proc(b: ^Builder, allocator := context.allocator) { builder_init_none :: proc(b: ^Builder, allocator := context.allocator) -> ^Builder {
b.buf = make([dynamic]byte, allocator) b.buf = make([dynamic]byte, allocator)
return b
} }
// initialize a builder, with a set length `len` and cap 16 byte buffer // initialize a builder, with a set length `len` and cap 16 byte buffer
// replaces the existing `buf` // replaces the existing `buf`
init_builder_len :: proc(b: ^Builder, len: int, allocator := context.allocator) { builder_init_len :: proc(b: ^Builder, len: int, allocator := context.allocator) -> ^Builder {
b.buf = make([dynamic]byte, len, allocator) b.buf = make([dynamic]byte, len, allocator)
return b
} }
// initialize a builder, with a set length `len` byte buffer and a custom `cap` // initialize a builder, with a set length `len` byte buffer and a custom `cap`
// replaces the existing `buf` // replaces the existing `buf`
init_builder_len_cap :: proc(b: ^Builder, len, cap: int, allocator := context.allocator) { builder_init_len_cap :: proc(b: ^Builder, len, cap: int, allocator := context.allocator) -> ^Builder {
b.buf = make([dynamic]byte, len, cap, allocator) b.buf = make([dynamic]byte, len, cap, allocator)
return b
} }
// overload simple `init_builder_*` with or without len / ap parameters // overload simple `builder_init_*` with or without len / ap parameters
init_builder :: proc{ builder_init :: proc{
init_builder_none, builder_init_none,
init_builder_len, builder_init_len,
init_builder_len_cap, builder_init_len_cap,
} }
@(private) @(private)
@@ -103,18 +106,18 @@ to_writer :: proc(b: ^Builder) -> io.Writer {
} }
// delete and clear the builder byte buffer content // delete and clear the builder byte buffer content
destroy_builder :: proc(b: ^Builder) { builder_destroy :: proc(b: ^Builder) {
delete(b.buf) delete(b.buf)
clear(&b.buf) clear(&b.buf)
} }
// reserve the builfer byte buffer to a specific cap, when it's higher than before // reserve the builfer byte buffer to a specific cap, when it's higher than before
grow_builder :: proc(b: ^Builder, cap: int) { builder_grow :: proc(b: ^Builder, cap: int) {
reserve(&b.buf, cap) reserve(&b.buf, cap)
} }
// clear the builder byte buffer content // clear the builder byte buffer content
reset_builder :: proc(b: ^Builder) { builder_reset :: proc(b: ^Builder) {
clear(&b.buf) clear(&b.buf)
} }
@@ -165,7 +168,7 @@ builder_space :: proc(b: Builder) -> int {
/* /*
appends a byte to the builder, returns the append diff appends a byte to the builder, returns the append diff
builder := strings.make_builder() builder := strings.builder_make()
strings.write_byte(&builder, 'a') // 1 strings.write_byte(&builder, 'a') // 1
strings.write_byte(&builder, 'b') // 1 strings.write_byte(&builder, 'b') // 1
strings.write_byte(&builder, 'c') // 1 strings.write_byte(&builder, 'c') // 1
@@ -181,7 +184,7 @@ write_byte :: proc(b: ^Builder, x: byte) -> (n: int) {
/* /*
appends a slice of bytes to the builder, returns the append diff appends a slice of bytes to the builder, returns the append diff
builder := strings.make_builder() builder := strings.builder_make()
bytes := [?]byte { 'a', 'b', 'c' } bytes := [?]byte { 'a', 'b', 'c' }
strings.write_bytes(&builder, bytes[:]) // 3 strings.write_bytes(&builder, bytes[:]) // 3
fmt.println(strings.to_string(builder)) // -> abc fmt.println(strings.to_string(builder)) // -> abc
@@ -196,77 +199,46 @@ write_bytes :: proc(b: ^Builder, x: []byte) -> (n: int) {
/* /*
appends a single rune into the builder, returns written rune size and an `io.Error` appends a single rune into the builder, returns written rune size and an `io.Error`
builder := strings.make_builder() builder := strings.builder_make()
strings.write_rune_builder(&builder, 'ä') // 2 None strings.write_rune(&builder, 'ä') // 2 None
strings.write_rune_builder(&builder, 'b') // 1 None strings.write_rune(&builder, 'b') // 1 None
strings.write_rune_builder(&builder, 'c') // 1 None strings.write_rune(&builder, 'c') // 1 None
fmt.println(strings.to_string(builder)) // -> äbc fmt.println(strings.to_string(builder)) // -> äbc
*/ */
write_rune_builder :: proc(b: ^Builder, r: rune) -> (int, io.Error) { write_rune :: proc(b: ^Builder, r: rune) -> (int, io.Error) {
return io.write_rune(to_writer(b), r) return io.write_rune(to_writer(b), r)
} }
/* /*
appends a quoted rune into the builder, returns written size appends a quoted rune into the builder, returns written size
builder := strings.make_builder() builder := strings.builder_make()
strings.write_string(&builder, "abc") // 3 strings.write_string(&builder, "abc") // 3
strings.write_quoted_rune_builder(&builder, 'ä') // 4 strings.write_quoted_rune(&builder, 'ä') // 4
strings.write_string(&builder, "abc") // 3 strings.write_string(&builder, "abc") // 3
fmt.println(strings.to_string(builder)) // -> abc'ä'abc fmt.println(strings.to_string(builder)) // -> abc'ä'abc
*/ */
write_quoted_rune_builder :: proc(b: ^Builder, r: rune) -> (n: int) { write_quoted_rune :: proc(b: ^Builder, r: rune) -> (n: int) {
return write_quoted_rune(to_writer(b), r) return io.write_quoted_rune(to_writer(b), r)
} }
@(private)
_write_byte :: proc(w: io.Writer, c: byte) -> int {
err := io.write_byte(w, c)
return 1 if err == nil else 0
}
// writer append a quoted rune into the byte buffer, return the written size
write_quoted_rune :: proc(w: io.Writer, r: rune) -> (n: int) {
quote := byte('\'')
n += _write_byte(w, quote)
buf, width := utf8.encode_rune(r)
if width == 1 && r == utf8.RUNE_ERROR {
n += _write_byte(w, '\\')
n += _write_byte(w, 'x')
n += _write_byte(w, DIGITS_LOWER[buf[0]>>4])
n += _write_byte(w, DIGITS_LOWER[buf[0]&0xf])
} else {
i, _ := io.write_escaped_rune(w, r, quote)
n += i
}
n += _write_byte(w, quote)
return
}
// overload for `write_string_*` variants
write_string :: proc{
write_string_builder,
write_string_writer,
}
/* /*
appends a string to the builder, return the written byte size appends a string to the builder, return the written byte size
builder := strings.make_builder() builder := strings.builder_make()
strings.write_string(&builder, "a") // 1 strings.write_string(&builder, "a") // 1
strings.write_string(&builder, "bc") // 2 strings.write_string(&builder, "bc") // 2
strings.write_string(&builder, "xyz") // 3 strings.write_string(&builder, "xyz") // 3
fmt.println(strings.to_string(builder)) // -> abcxyz fmt.println(strings.to_string(builder)) // -> abcxyz
*/ */
write_string_builder :: proc(b: ^Builder, s: string) -> (n: int) { write_string :: proc(b: ^Builder, s: string) -> (n: int) {
return write_string_writer(to_writer(b), s) n0 := len(b.buf)
append(&b.buf, s)
n1 := len(b.buf)
return n1-n0
} }
// appends a string to the writer
write_string_writer :: proc(w: io.Writer, s: string) -> (n: int) {
n, _ = io.write(w, transmute([]byte)s)
return
}
// pops and returns the last byte in the builder // pops and returns the last byte in the builder
// returns 0 when the builder is empty // returns 0 when the builder is empty
@@ -297,70 +269,36 @@ pop_rune :: proc(b: ^Builder) -> (r: rune, width: int) {
@(private) @(private)
DIGITS_LOWER := "0123456789abcdefx" DIGITS_LOWER := "0123456789abcdefx"
// overload for `write_quoted_string_*` variants
write_quoted_string :: proc{
write_quoted_string_builder,
write_quoted_string_writer,
}
/* /*
append a quoted string into the builder, return the written byte size append a quoted string into the builder, return the written byte size
builder := strings.make_builder() builder := strings.builder_make()
strings.write_quoted_string(&builder, "a") // 3 strings.write_quoted_string(&builder, "a") // 3
strings.write_quoted_string(&builder, "bc", '\'') // 4 strings.write_quoted_string(&builder, "bc", '\'') // 4
strings.write_quoted_string(&builder, "xyz") // 5 strings.write_quoted_string(&builder, "xyz") // 5
fmt.println(strings.to_string(builder)) // -> "a"'bc'xyz" fmt.println(strings.to_string(builder)) // -> "a"'bc'xyz"
*/ */
write_quoted_string_builder :: proc(b: ^Builder, str: string, quote: byte = '"') -> (n: int) { write_quoted_string :: proc(b: ^Builder, str: string, quote: byte = '"') -> (n: int) {
n, _ = io.write_quoted_string(to_writer(b), str, quote) n, _ = io.write_quoted_string(to_writer(b), str, quote)
return return
} }
@(deprecated="prefer io.write_quoted_string")
write_quoted_string_writer :: proc(w: io.Writer, str: string, quote: byte = '"') -> (n: int) {
n, _ = io.write_quoted_string(w, str, quote)
return
}
// overload for `write_encoded_rune_*`
write_encoded_rune :: proc{
write_encoded_rune_builder,
write_encoded_rune_writer,
}
// appends a rune to the builder, optional `write_quote` boolean tag, returns the written rune size // appends a rune to the builder, optional `write_quote` boolean tag, returns the written rune size
write_encoded_rune_builder :: proc(b: ^Builder, r: rune, write_quote := true) -> (n: int) { write_encoded_rune :: proc(b: ^Builder, r: rune, write_quote := true) -> (n: int) {
n, _ = io.write_encoded_rune(to_writer(b), r, write_quote) n, _ = io.write_encoded_rune(to_writer(b), r, write_quote)
return return
} }
@(deprecated="prefer io.write_encoded_rune")
write_encoded_rune_writer :: proc(w: io.Writer, r: rune, write_quote := true) -> (n: int) {
n, _ = io.write_encoded_rune(w, r, write_quote)
return
}
// overload for `write_escaped_rune_*`
write_escaped_rune :: proc{
write_escaped_rune_builder,
write_escaped_rune_writer,
}
// appends a rune to the builder, fully written out in case of escaped runes e.g. '\a' will be written as such // appends a rune to the builder, fully written out in case of escaped runes e.g. '\a' will be written as such
// when `r` and `quote` match and `quote` is `\\` - they will be written as two slashes // when `r` and `quote` match and `quote` is `\\` - they will be written as two slashes
// `html_safe` flag in case the runes '<', '>', '&' should be encoded as digits e.g. `\u0026` // `html_safe` flag in case the runes '<', '>', '&' should be encoded as digits e.g. `\u0026`
write_escaped_rune_builder :: proc(b: ^Builder, r: rune, quote: byte, html_safe := false) -> (n: int) { write_escaped_rune :: proc(b: ^Builder, r: rune, quote: byte, html_safe := false) -> (n: int) {
n, _ = io.write_escaped_rune(to_writer(b), r, quote, html_safe) n, _ = io.write_escaped_rune(to_writer(b), r, quote, html_safe)
return return
} }
@(deprecated="prefer io.write_escaped_rune")
write_escaped_rune_writer :: proc(w: io.Writer, r: rune, quote: byte, html_safe := false) -> (n: int) {
n, _ = io.write_escaped_rune(w, r, quote, html_safe)
return
}
// writes a u64 value `i` in `base` = 10 into the builder, returns the written amount of characters // writes a u64 value `i` in `base` = 10 into the builder, returns the written amount of characters
write_u64 :: proc(b: ^Builder, i: u64, base: int = 10) -> (n: int) { write_u64 :: proc(b: ^Builder, i: u64, base: int = 10) -> (n: int) {
buf: [32]byte buf: [32]byte
+10 -10
View File
@@ -10,7 +10,7 @@ to_valid_utf8 :: proc(s, replacement: string, allocator := context.allocator) ->
} }
b: Builder b: Builder
init_builder(&b, 0, 0, allocator) builder_init(&b, 0, 0, allocator)
s := s s := s
for c, i in s { for c, i in s {
@@ -20,7 +20,7 @@ to_valid_utf8 :: proc(s, replacement: string, allocator := context.allocator) ->
_, w := utf8.decode_rune_in_string(s[i:]) _, w := utf8.decode_rune_in_string(s[i:])
if w == 1 { if w == 1 {
grow_builder(&b, len(s) + len(replacement)) builder_grow(&b, len(s) + len(replacement))
write_string(&b, s[:i]) write_string(&b, s[:i])
s = s[i:] s = s[i:]
break break
@@ -67,9 +67,9 @@ to_valid_utf8 :: proc(s, replacement: string, allocator := context.allocator) ->
*/ */
to_lower :: proc(s: string, allocator := context.allocator) -> string { to_lower :: proc(s: string, allocator := context.allocator) -> string {
b: Builder b: Builder
init_builder(&b, 0, len(s), allocator) builder_init(&b, 0, len(s), allocator)
for r in s { for r in s {
write_rune_builder(&b, unicode.to_lower(r)) write_rune(&b, unicode.to_lower(r))
} }
return to_string(b) return to_string(b)
} }
@@ -83,9 +83,9 @@ to_lower :: proc(s: string, allocator := context.allocator) -> string {
*/ */
to_upper :: proc(s: string, allocator := context.allocator) -> string { to_upper :: proc(s: string, allocator := context.allocator) -> string {
b: Builder b: Builder
init_builder(&b, 0, len(s), allocator) builder_init(&b, 0, len(s), allocator)
for r in s { for r in s {
write_rune_builder(&b, unicode.to_upper(r)) write_rune(&b, unicode.to_upper(r))
} }
return to_string(b) return to_string(b)
} }
@@ -147,7 +147,7 @@ to_camel_case :: proc(s: string, allocator := context.allocator) -> string {
s := s s := s
s = trim_space(s) s = trim_space(s)
b: Builder b: Builder
init_builder(&b, 0, len(s), allocator) builder_init(&b, 0, len(s), allocator)
w := to_writer(&b) w := to_writer(&b)
string_case_iterator(w, s, proc(w: io.Writer, prev, curr, next: rune) { string_case_iterator(w, s, proc(w: io.Writer, prev, curr, next: rune) {
@@ -172,7 +172,7 @@ to_pascal_case :: proc(s: string, allocator := context.allocator) -> string {
s := s s := s
s = trim_space(s) s = trim_space(s)
b: Builder b: Builder
init_builder(&b, 0, len(s), allocator) builder_init(&b, 0, len(s), allocator)
w := to_writer(&b) w := to_writer(&b)
string_case_iterator(w, s, proc(w: io.Writer, prev, curr, next: rune) { string_case_iterator(w, s, proc(w: io.Writer, prev, curr, next: rune) {
@@ -203,7 +203,7 @@ to_delimiter_case :: proc(s: string, delimiter: rune, all_upper_case: bool, allo
s := s s := s
s = trim_space(s) s = trim_space(s)
b: Builder b: Builder
init_builder(&b, 0, len(s), allocator) builder_init(&b, 0, len(s), allocator)
w := to_writer(&b) w := to_writer(&b)
adjust_case := unicode.to_upper if all_upper_case else unicode.to_lower adjust_case := unicode.to_upper if all_upper_case else unicode.to_lower
@@ -272,7 +272,7 @@ to_ada_case :: proc(s: string, allocator := context.allocator) -> string {
s := s s := s
s = trim_space(s) s = trim_space(s)
b: Builder b: Builder
init_builder(&b, 0, len(s), allocator) builder_init(&b, 0, len(s), allocator)
w := to_writer(&b) w := to_writer(&b)
prev, curr: rune prev, curr: rune
+8 -8
View File
@@ -1553,7 +1553,7 @@ split_multi_iterate :: proc(using sm: ^Split_Multi) -> (res: string, ok: bool) #
scrub :: proc(s: string, replacement: string, allocator := context.allocator) -> string { scrub :: proc(s: string, replacement: string, allocator := context.allocator) -> string {
str := s str := s
b: Builder b: Builder
init_builder(&b, 0, len(s), allocator) builder_init(&b, 0, len(s), allocator)
has_error := false has_error := false
cursor := 0 cursor := 0
@@ -1622,7 +1622,7 @@ expand_tabs :: proc(s: string, tab_size: int, allocator := context.allocator) ->
} }
b: Builder b: Builder
init_builder(&b, allocator) builder_init(&b, allocator)
writer := to_writer(&b) writer := to_writer(&b)
str := s str := s
column: int column: int
@@ -1690,8 +1690,8 @@ centre_justify :: proc(str: string, length: int, pad: string, allocator := conte
pad_len := rune_count(pad) pad_len := rune_count(pad)
b: Builder b: Builder
init_builder(&b, allocator) builder_init(&b, allocator)
grow_builder(&b, len(str) + (remains/pad_len + 1)*len(pad)) builder_grow(&b, len(str) + (remains/pad_len + 1)*len(pad))
w := to_writer(&b) w := to_writer(&b)
@@ -1713,8 +1713,8 @@ left_justify :: proc(str: string, length: int, pad: string, allocator := context
pad_len := rune_count(pad) pad_len := rune_count(pad)
b: Builder b: Builder
init_builder(&b, allocator) builder_init(&b, allocator)
grow_builder(&b, len(str) + (remains/pad_len + 1)*len(pad)) builder_grow(&b, len(str) + (remains/pad_len + 1)*len(pad))
w := to_writer(&b) w := to_writer(&b)
@@ -1735,8 +1735,8 @@ right_justify :: proc(str: string, length: int, pad: string, allocator := contex
pad_len := rune_count(pad) pad_len := rune_count(pad)
b: Builder b: Builder
init_builder(&b, allocator) builder_init(&b, allocator)
grow_builder(&b, len(str) + (remains/pad_len + 1)*len(pad)) builder_grow(&b, len(str) + (remains/pad_len + 1)*len(pad))
w := to_writer(&b) w := to_writer(&b)
+8 -12
View File
@@ -3,24 +3,22 @@
package sync package sync
import "core:c" import "core:c"
import "core:os"
import "core:time" import "core:time"
UMTX_OP_WAIT :: 2 UMTX_OP_WAIT :: 2
UMTX_OP_WAKE :: 3 UMTX_OP_WAKE :: 3
ETIMEDOUT :: 60
foreign import libc "system:c" foreign import libc "system:c"
foreign libc { foreign libc {
_umtx_op :: proc "c" (obj: rawptr, op: c.int, val: c.ulong, uaddr: rawptr, uaddr2: rawptr) -> c.int --- _umtx_op :: proc "c" (obj: rawptr, op: c.int, val: c.ulong, uaddr: rawptr, uaddr2: rawptr) -> c.int ---
__error :: proc "c" () -> ^c.int ---
} }
_futex_wait :: proc(f: ^Futex, expected: u32) -> bool { _futex_wait :: proc(f: ^Futex, expected: u32) -> bool {
timeout := os.Unix_File_Time{ timeout := [2]i64{14400, 0} // 4 hours
seconds = 5,
nanoseconds = 0,
}
for { for {
res := _umtx_op(f, UMTX_OP_WAIT, c.ulong(expected), nil, &timeout) res := _umtx_op(f, UMTX_OP_WAIT, c.ulong(expected), nil, &timeout)
@@ -28,7 +26,7 @@ _futex_wait :: proc(f: ^Futex, expected: u32) -> bool {
return true return true
} }
if os.Errno(os.get_last_error()) == os.ETIMEDOUT { if __error()^ == ETIMEDOUT {
continue continue
} }
@@ -42,16 +40,14 @@ _futex_wait_with_timeout :: proc(f: ^Futex, expected: u32, duration: time.Durati
return false return false
} }
res := _umtx_op(f, UMTX_OP_WAIT, c.ulong(expected), nil, &os.Unix_File_Time{ timeout := [2]i64{i64(duration/1e9), i64(duration%1e9)}
seconds = (os.time_t)(duration/1e9),
nanoseconds = (c.long)(duration%1e9),
})
res := _umtx_op(f, UMTX_OP_WAIT, c.ulong(expected), nil, &timeout)
if res != -1 { if res != -1 {
return true return true
} }
if os.Errno(os.get_last_error()) == os.ETIMEDOUT { if __error()^ == ETIMEDOUT {
return false return false
} }
+8 -2
View File
@@ -2,8 +2,14 @@
//+private //+private
package sync package sync
import "core:os" import "core:c"
foreign import dl "system:dl"
foreign dl {
pthread_getthreadid_np :: proc "c" () -> c.int ---
}
_current_thread_id :: proc "contextless" () -> int { _current_thread_id :: proc "contextless" () -> int {
return os.current_thread_id() return int(pthread_getthreadid_np())
} }
+171 -259
View File
@@ -1148,6 +1148,156 @@ foreign wasi {
*/ */
how: sdflags_t, how: sdflags_t,
) -> errno_t --- ) -> errno_t ---
/**
* Return a description of the given preopened file descriptor.
*/
fd_prestat_dir_name :: proc(
fd: fd_t,
/**
* A buffer into which to write the preopened directory name.
*/
path: string,
) -> errno_t ---
/**
* Create a directory.
* Note: This is similar to `mkdirat` in POSIX.
*/
path_create_directory :: proc(
fd: fd_t,
/**
* The path at which to create the directory.
*/
path: string,
) -> errno_t ---
/**
* Adjust the timestamps of a file or directory.
* Note: This is similar to `utimensat` in POSIX.
*/
path_filestat_set_times :: proc(
fd: fd_t,
/**
* Flags determining the method of how the path is resolved.
*/
flags: lookupflags_t,
/**
* The path of the file or directory to operate on.
*/
path: string,
/**
* The desired values of the data access timestamp.
*/
atim: timestamp_t,
/**
* The desired values of the data modification timestamp.
*/
mtim: timestamp_t,
/**
* A bitmask indicating which timestamps to adjust.
*/
fst_flags: fstflags_t,
) -> errno_t ---
/**
* Remove a directory.
* Return `errno::notempty` if the directory is not empty.
* Note: This is similar to `unlinkat(fd, path, AT_REMOVEDIR)` in POSIX.
*/
path_remove_directory :: proc(
fd: fd_t,
/**
* The path to a directory to remove.
*/
path: string,
) -> errno_t ---
/**
* Create a hard link.
* Note: This is similar to `linkat` in POSIX.
*/
path_link :: proc(
old_fd: fd_t,
/**
* Flags determining the method of how the path is resolved.
*/
old_flags: lookupflags_t,
/**
* The source path from which to link.
*/
old_path: string,
/**
* The working directory at which the resolution of the new path starts.
*/
new_fd: fd_t,
/**
* The destination path at which to create the hard link.
*/
new_path: string,
) -> errno_t ---
/**
* Rename a file or directory.
* Note: This is similar to `renameat` in POSIX.
*/
path_rename :: proc(
fd: fd_t,
/**
* The source path of the file or directory to rename.
*/
old_path: string,
/**
* The working directory at which the resolution of the new path starts.
*/
new_fd: fd_t,
/**
* The destination path to which to rename the file or directory.
*/
new_path: string,
) -> errno_t ---
/**
* Create a symbolic link.
* Note: This is similar to `symlinkat` in POSIX.
*/
path_symlink :: proc(
/**
* The contents of the symbolic link.
*/
old_path: string,
fd: fd_t,
/**
* The destination path at which to create the symbolic link.
*/
new_path: string,
) -> errno_t ---
/**
* Unlink a file.
* Return `errno::isdir` if the path refers to a directory.
* Note: This is similar to `unlinkat(fd, path, 0)` in POSIX.
*/
path_unlink_file :: proc(
fd: fd_t,
/**
* The path to a file to unlink.
*/
path: string,
) -> errno_t ---
/**
* Write high-quality random data into a buffer.
* This function blocks when the implementation is unable to immediately
* provide sufficient high-quality random data.
* This function may execute slowly, so when large mounts of random data are
* required, it's advisable to use this function to seed a pseudo-random
* number generator, rather than to provide the random data directly.
*/
random_get :: proc(
/**
* The buffer to fill with random data.
*/
buf: []u8,
) -> errno_t ---
} }
/** /**
@@ -1250,7 +1400,7 @@ fd_pread :: proc "c" (
*/ */
offset: filesize_t, offset: filesize_t,
) -> (n: size_t, err: errno_t) { ) -> (n: size_t, err: errno_t) {
err = wasi_fd_pread(fd, raw_data(iovs), len(iovs), offset, &n) err = wasi_fd_pread(fd, iovs, offset, &n)
return return
} }
/** /**
@@ -1281,7 +1431,7 @@ fd_pwrite :: proc "c" (
*/ */
offset: filesize_t, offset: filesize_t,
) -> (n: size_t, err: errno_t) { ) -> (n: size_t, err: errno_t) {
err = wasi_fd_pwrite(fd, raw_data(iovs), len(iovs), offset, &n) err = wasi_fd_pwrite(fd, iovs, offset, &n)
return return
} }
/** /**
@@ -1297,7 +1447,7 @@ fd_read :: proc "c" (
*/ */
iovs: []iovec_t, iovs: []iovec_t,
) -> (n: size_t, err: errno_t) { ) -> (n: size_t, err: errno_t) {
err = wasi_fd_read(fd, raw_data(iovs), len(iovs), &n) err = wasi_fd_read(fd, iovs, &n)
return return
} }
/** /**
@@ -1324,7 +1474,7 @@ fd_readdir :: proc "c" (
*/ */
cookie: dircookie_t, cookie: dircookie_t,
) -> (n: size_t, err: errno_t) { ) -> (n: size_t, err: errno_t) {
err = wasi_fd_readdir(fd, raw_data(buf), len(buf), cookie, &n) err = wasi_fd_readdir(fd, buf, cookie, &n)
return return
} }
/** /**
@@ -1370,7 +1520,7 @@ fd_write :: proc "c" (
*/ */
iovs: []ciovec_t, iovs: []ciovec_t,
) -> (n: size_t, err: errno_t) { ) -> (n: size_t, err: errno_t) {
err = wasi_fd_write(fd, raw_data(iovs), len(iovs), &n) err = wasi_fd_write(fd, iovs, &n)
return return
} }
/** /**
@@ -1390,7 +1540,7 @@ path_filestat_get :: proc "c" (
*/ */
path: string, path: string,
) -> (offset: filestat_t, err: errno_t) { ) -> (offset: filestat_t, err: errno_t) {
err = wasi_path_filestat_get(fd, flags, raw_data(path), len(path), &offset) err = wasi_path_filestat_get(fd, flags, path, &offset)
return return
} }
/** /**
@@ -1432,7 +1582,7 @@ path_open :: proc "c" (
fs_rights_inheriting: rights_t, fs_rights_inheriting: rights_t,
fdflags: fdflags_t, fdflags: fdflags_t,
) -> (file: fd_t, err: errno_t) { ) -> (file: fd_t, err: errno_t) {
err = wasi_path_open(fd, dirflags, raw_data(path), len(path), oflags, fs_rights_base, fs_rights_inheriting, fdflags, &file) err = wasi_path_open(fd, dirflags, path, oflags, fs_rights_base, fs_rights_inheriting, fdflags, &file)
return return
} }
/** /**
@@ -1452,7 +1602,7 @@ path_readlink :: proc "c" (
*/ */
buf: []u8, buf: []u8,
) -> (n: size_t, err: errno_t) { ) -> (n: size_t, err: errno_t) {
err = wasi_path_readlink(fd, raw_data(path), len(path), raw_data(buf), len(buf), &n) err = wasi_path_readlink(fd, path, buf, &n)
return return
} }
/** /**
@@ -1495,7 +1645,7 @@ sock_recv :: proc "c" (
*/ */
ri_flags: riflags_t, ri_flags: riflags_t,
) -> (n: size_t, flags: roflags_t, err: errno_t) { ) -> (n: size_t, flags: roflags_t, err: errno_t) {
err = wasi_sock_recv(fd, raw_data(ri_data), len(ri_data), ri_flags, &n, &flags) err = wasi_sock_recv(fd, ri_data, ri_flags, &n, &flags)
return return
} }
/** /**
@@ -1516,172 +1666,11 @@ sock_send :: proc "c" (
*/ */
si_flags: siflags_t, si_flags: siflags_t,
) -> (n: size_t, err: errno_t) { ) -> (n: size_t, err: errno_t) {
err = wasi_sock_send(fd, raw_data(si_data), len(si_data), si_flags, &n) err = wasi_sock_send(fd, si_data, si_flags, &n)
return return
} }
/**
* Return a description of the given preopened file descriptor.
*/
fd_prestat_dir_name :: proc(
fd: fd_t,
/**
* A buffer into which to write the preopened directory name.
*/
path: string,
) -> errno_t {
return wasm_fd_prestat_dir_name(fd, raw_data(path), len(path))
}
/**
* Create a directory.
* Note: This is similar to `mkdirat` in POSIX.
*/
path_create_directory :: proc(
fd: fd_t,
/**
* The path at which to create the directory.
*/
path: string,
) -> errno_t {
return wasm_path_create_directory(fd, raw_data(path), len(path))
}
/**
* Adjust the timestamps of a file or directory.
* Note: This is similar to `utimensat` in POSIX.
*/
path_filestat_set_times :: proc(
fd: fd_t,
/**
* Flags determining the method of how the path is resolved.
*/
flags: lookupflags_t,
/**
* The path of the file or directory to operate on.
*/
path: string,
/**
* The desired values of the data access timestamp.
*/
atim: timestamp_t,
/**
* The desired values of the data modification timestamp.
*/
mtim: timestamp_t,
/**
* A bitmask indicating which timestamps to adjust.
*/
fst_flags: fstflags_t,
) -> errno_t {
return wasm_path_filestat_set_times(fd, flags, raw_data(path), len(path), atim, mtim, fst_flags)
}
/**
* Remove a directory.
* Return `errno::notempty` if the directory is not empty.
* Note: This is similar to `unlinkat(fd, path, AT_REMOVEDIR)` in POSIX.
*/
path_remove_directory :: proc(
fd: fd_t,
/**
* The path to a directory to remove.
*/
path: string,
) -> errno_t {
return wasm_path_remove_directory(fd, raw_data(path), len(path))
}
/**
* Create a hard link.
* Note: This is similar to `linkat` in POSIX.
*/
path_link :: proc(
old_fd: fd_t,
/**
* Flags determining the method of how the path is resolved.
*/
old_flags: lookupflags_t,
/**
* The source path from which to link.
*/
old_path: string,
/**
* The working directory at which the resolution of the new path starts.
*/
new_fd: fd_t,
/**
* The destination path at which to create the hard link.
*/
new_path: string,
) -> errno_t {
return wasm_path_link(old_fd, old_flags, raw_data(old_path), len(old_path), new_fd, raw_data(new_path), len(new_path))
}
/**
* Rename a file or directory.
* Note: This is similar to `renameat` in POSIX.
*/
path_rename :: proc(
fd: fd_t,
/**
* The source path of the file or directory to rename.
*/
old_path: string,
/**
* The working directory at which the resolution of the new path starts.
*/
new_fd: fd_t,
/**
* The destination path to which to rename the file or directory.
*/
new_path: string,
) -> errno_t {
return wasm_path_rename(fd, raw_data(old_path), len(old_path), new_fd, raw_data(new_path), len(new_path))
}
/**
* Create a symbolic link.
* Note: This is similar to `symlinkat` in POSIX.
*/
path_symlink :: proc(
/**
* The contents of the symbolic link.
*/
old_path: string,
fd: fd_t,
/**
* The destination path at which to create the symbolic link.
*/
new_path: string,
) -> errno_t {
return wasm_path_symlink(raw_data(old_path), len(old_path), fd, raw_data(new_path), len(new_path))
}
/**
* Unlink a file.
* Return `errno::isdir` if the path refers to a directory.
* Note: This is similar to `unlinkat(fd, path, 0)` in POSIX.
*/
path_unlink_file :: proc(
fd: fd_t,
/**
* The path to a file to unlink.
*/
path: string,
) -> errno_t {
return wasm_path_unlink_file(fd, raw_data(path), len(path))
}
/**
* Write high-quality random data into a buffer.
* This function blocks when the implementation is unable to immediately
* provide sufficient high-quality random data.
* This function may execute slowly, so when large mounts of random data are
* required, it's advisable to use this function to seed a pseudo-random
* number generator, rather than to provide the random data directly.
*/
random_get :: proc(
/**
* The buffer to fill with random data.
*/
buf: []u8,
) -> errno_t {
return wasm_random_get(raw_data(buf), len(buf))
}
@@ -1722,8 +1711,7 @@ foreign wasi {
@(link_name="fd_pread") @(link_name="fd_pread")
wasi_fd_pread :: proc( wasi_fd_pread :: proc(
fd: fd_t, fd: fd_t,
iovs: [^]iovec_t, iovs: []iovec_t,
iovs_len: size_t,
offset: filesize_t, offset: filesize_t,
retptr0: ^size_t, retptr0: ^size_t,
) -> errno_t --- ) -> errno_t ---
@@ -1735,23 +1723,20 @@ foreign wasi {
@(link_name="fd_pwrite") @(link_name="fd_pwrite")
wasi_fd_pwrite :: proc( wasi_fd_pwrite :: proc(
fd: fd_t, fd: fd_t,
iovs: [^]ciovec_t, iovs: []ciovec_t,
iovs_len: size_t,
offset: filesize_t, offset: filesize_t,
retptr0: ^size_t, retptr0: ^size_t,
) -> errno_t --- ) -> errno_t ---
@(link_name="fd_read") @(link_name="fd_read")
wasi_fd_read :: proc( wasi_fd_read :: proc(
fd: fd_t, fd: fd_t,
iovs: [^]iovec_t, iovs: []iovec_t,
iovs_len: size_t,
retptr0: ^size_t, retptr0: ^size_t,
) -> errno_t --- ) -> errno_t ---
@(link_name="fd_readdir") @(link_name="fd_readdir")
wasi_fd_readdir :: proc( wasi_fd_readdir :: proc(
fd: fd_t, fd: fd_t,
buf: [^]u8, buf: []u8,
buf_len: size_t,
cookie: dircookie_t, cookie: dircookie_t,
retptr0: ^size_t, retptr0: ^size_t,
) -> errno_t --- ) -> errno_t ---
@@ -1770,8 +1755,7 @@ foreign wasi {
@(link_name="fd_write") @(link_name="fd_write")
wasi_fd_write :: proc( wasi_fd_write :: proc(
fd: fd_t, fd: fd_t,
iovs: [^]ciovec_t, iovs: []ciovec_t,
iovs_len: size_t,
retptr0: ^size_t, retptr0: ^size_t,
) -> errno_t --- ) -> errno_t ---
@(link_name="path_filestat_get") @(link_name="path_filestat_get")
@@ -1781,16 +1765,14 @@ foreign wasi {
/** /**
* The path of the file or directory to inspect. * The path of the file or directory to inspect.
*/ */
path: [^]u8, path: string,
path_len: size_t,
retptr0: ^filestat_t, retptr0: ^filestat_t,
) -> errno_t --- ) -> errno_t ---
@(link_name="path_open") @(link_name="path_open")
wasi_path_open :: proc( wasi_path_open :: proc(
fd: fd_t, fd: fd_t,
dirflags: lookupflags_t, dirflags: lookupflags_t,
path: [^]u8, path: string,
path_len: size_t,
oflags: oflags_t, oflags: oflags_t,
fs_rights_base: rights_t, fs_rights_base: rights_t,
fs_rights_inheriting: rights_t, fs_rights_inheriting: rights_t,
@@ -1800,10 +1782,8 @@ foreign wasi {
@(link_name="path_readlink") @(link_name="path_readlink")
wasi_path_readlink :: proc( wasi_path_readlink :: proc(
fd: fd_t, fd: fd_t,
path: [^]u8, path: string,
path_len: size_t, buf: []u8,
buf: [^]u8,
buf_len: size_t,
retptr0: ^size_t, retptr0: ^size_t,
) -> errno_t --- ) -> errno_t ---
@(link_name="poll_oneoff") @(link_name="poll_oneoff")
@@ -1816,8 +1796,7 @@ foreign wasi {
@(link_name="sock_recv") @(link_name="sock_recv")
wasi_sock_recv :: proc( wasi_sock_recv :: proc(
fd: fd_t, fd: fd_t,
ri_data: [^]iovec_t, ri_data: []iovec_t,
ri_data_len: size_t,
ri_flags: riflags_t, ri_flags: riflags_t,
retptr0: ^size_t, retptr0: ^size_t,
retptr1: ^roflags_t, retptr1: ^roflags_t,
@@ -1825,75 +1804,8 @@ foreign wasi {
@(link_name="sock_send") @(link_name="sock_send")
wasi_sock_send :: proc( wasi_sock_send :: proc(
fd: fd_t, fd: fd_t,
si_data: [^]ciovec_t, si_data: []ciovec_t,
si_data_len: size_t,
si_flags: siflags_t, si_flags: siflags_t,
retptr0: ^size_t, retptr0: ^size_t,
) -> errno_t --- ) -> errno_t ---
@(link_name="fd_prestat_dir_name")
wasm_fd_prestat_dir_name :: proc(
fd: fd_t,
path: [^]u8,
path_len: size_t,
) -> errno_t ---
@(link_name="path_create_directory")
wasm_path_create_directory :: proc(
fd: fd_t,
path: [^]u8,
path_len: size_t,
) -> errno_t ---
@(link_name="path_filestat_set_times")
wasm_path_filestat_set_times :: proc(
fd: fd_t,
flags: lookupflags_t,
path: [^]u8,
path_len: size_t,
atim: timestamp_t,
mtim: timestamp_t,
fst_flags: fstflags_t,
) -> errno_t ---
@(link_name="path_remove_directory")
wasm_path_remove_directory :: proc(
fd: fd_t,
path: [^]u8,
path_len: size_t,
) -> errno_t ---
@(link_name="path_link")
wasm_path_link :: proc(
old_fd: fd_t,
old_flags: lookupflags_t,
old_path: [^]u8,
old_path_len: size_t,
new_fd: fd_t,
new_path: [^]u8,
new_path_len: size_t,
) -> errno_t ---
@(link_name="path_rename")
wasm_path_rename :: proc(
fd: fd_t,
old_path: [^]u8,
old_path_len: size_t,
new_fd: fd_t,
new_path: [^]u8,
new_path_len: size_t,
) -> errno_t ---
@(link_name="path_symlink")
wasm_path_symlink :: proc(
old_path: [^]u8,
old_path_len: size_t,
fd: fd_t,
new_path: [^]u8,
new_path_len: size_t,
) -> errno_t ---
@(link_name="path_unlink_file")
wasm_path_unlink_file :: proc(
fd: fd_t,
path: [^]u8,
path_len: size_t,
) -> errno_t ---
@(link_name="random_get")
wasm_random_get :: proc(
buf: [^]u8,
buf_len: size_t,
) -> errno_t ---
} }
+1
View File
@@ -18,6 +18,7 @@ foreign user32 {
RegisterClassW :: proc(lpWndClass: ^WNDCLASSW) -> ATOM --- RegisterClassW :: proc(lpWndClass: ^WNDCLASSW) -> ATOM ---
RegisterClassExW :: proc(^WNDCLASSEXW) -> ATOM --- RegisterClassExW :: proc(^WNDCLASSEXW) -> ATOM ---
UnregisterClassW :: proc(lpClassName: LPCWSTR, hInstance: HINSTANCE) -> BOOL ---
CreateWindowExW :: proc( CreateWindowExW :: proc(
dwExStyle: DWORD, dwExStyle: DWORD,
+4
View File
@@ -22,6 +22,10 @@ GET_Y_LPARAM :: #force_inline proc "contextless" (lp: LPARAM) -> c_int {
return cast(c_int)cast(c_short)HIWORD(cast(DWORD)lp) return cast(c_int)cast(c_short)HIWORD(cast(DWORD)lp)
} }
MAKE_WORD :: #force_inline proc "contextless" (x, y: WORD) -> WORD {
return x << 8 | y
}
utf8_to_utf16 :: proc(s: string, allocator := context.temp_allocator) -> []u16 { utf8_to_utf16 :: proc(s: string, allocator := context.temp_allocator) -> []u16 {
if len(s) < 1 { if len(s) < 1 {
return nil return nil
+1 -1
View File
@@ -45,4 +45,4 @@ ERROR_NOT_SAME_OBJECT : DWORD : 1656
E_NOTIMPL :: HRESULT(-0x7fff_bfff) // 0x8000_4001 E_NOTIMPL :: HRESULT(-0x7fff_bfff) // 0x8000_4001
SUCCEEDED :: #force_inline proc(#any_int result: int) -> bool do return result >= 0 SUCCEEDED :: #force_inline proc(#any_int result: int) -> bool { return result >= 0 }
@@ -45,7 +45,7 @@ generate_encoding_entity_table :: proc() {
printf("\"%v\" loaded and parsed.\n", filename) printf("\"%v\" loaded and parsed.\n", filename)
generated_buf: strings.Builder generated_buf: strings.Builder
defer strings.destroy_builder(&generated_buf) defer strings.builder_destroy(&generated_buf)
w := strings.to_writer(&generated_buf) w := strings.to_writer(&generated_buf)
charlist, charlist_ok := xml.find_child_by_ident(doc.root, "charlist") charlist, charlist_ok := xml.find_child_by_ident(doc.root, "charlist")
+2
View File
@@ -1322,6 +1322,7 @@ bool init_build_paths(String init_filename) {
} }
#if defined(GB_SYSTEM_WINDOWS) #if defined(GB_SYSTEM_WINDOWS)
if (bc->metrics.os == TargetOs_windows) {
if (bc->resource_filepath.len > 0) { if (bc->resource_filepath.len > 0) {
bc->build_paths[BuildPath_RC] = path_from_string(ha, bc->resource_filepath); bc->build_paths[BuildPath_RC] = path_from_string(ha, bc->resource_filepath);
bc->build_paths[BuildPath_RES] = path_from_string(ha, bc->resource_filepath); bc->build_paths[BuildPath_RES] = path_from_string(ha, bc->resource_filepath);
@@ -1377,6 +1378,7 @@ bool init_build_paths(String init_filename) {
} }
} }
} }
}
#endif #endif
// All the build targets and OSes. // All the build targets and OSes.
+35 -18
View File
@@ -2959,7 +2959,14 @@ void check_binary_matrix(CheckerContext *c, Token const &op, Operand *x, Operand
goto matrix_error; goto matrix_error;
} }
x->mode = Addressing_Value; x->mode = Addressing_Value;
x->type = alloc_type_matrix(xt->Matrix.elem, xt->Matrix.row_count, yt->Matrix.column_count); if (are_types_identical(xt, yt)) {
if (!is_type_named(x->type) && is_type_named(y->type)) {
// prefer the named type
x->type = y->type;
}
} else {
x->type = alloc_type_matrix(xt->Matrix.elem, xt->Matrix.row_count, yt->Matrix.column_count);
}
goto matrix_success; goto matrix_success;
} else if (yt->kind == Type_Array) { } else if (yt->kind == Type_Array) {
if (!are_types_identical(xt->Matrix.elem, yt->Array.elem)) { if (!are_types_identical(xt->Matrix.elem, yt->Array.elem)) {
@@ -3021,7 +3028,6 @@ void check_binary_matrix(CheckerContext *c, Token const &op, Operand *x, Operand
matrix_success: matrix_success:
x->type = check_matrix_type_hint(x->type, type_hint); x->type = check_matrix_type_hint(x->type, type_hint);
return; return;
@@ -8404,23 +8410,30 @@ ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *node, Type *
if (is_type_bit_set(type)) { if (is_type_bit_set(type)) {
// NOTE(bill): Encode as an integer // NOTE(bill): Encode as an integer
i64 lower = base_type(type)->BitSet.lower; Type *bt = base_type(type);
BigInt bits = {};
BigInt one = {};
big_int_from_u64(&one, 1);
u64 bits = 0; for_array(i, cl->elems) {
for_array(index, cl->elems) { Ast *e = cl->elems[i];
Ast *elem = cl->elems[index]; GB_ASSERT(e->kind != Ast_FieldValue);
GB_ASSERT(elem->kind != Ast_FieldValue);
TypeAndValue tav = elem->tav; TypeAndValue tav = e->tav;
ExactValue i = exact_value_to_integer(tav.value); if (tav.mode != Addressing_Constant) {
if (i.kind != ExactValue_Integer) {
continue; continue;
} }
i64 val = big_int_to_i64(&i.value_integer); GB_ASSERT(tav.value.kind == ExactValue_Integer);
val -= lower; i64 v = big_int_to_i64(&tav.value.value_integer);
u64 bit = u64(1ll<<val); i64 lower = bt->BitSet.lower;
bits |= bit; u64 index = cast(u64)(v-lower);
BigInt bit = {};
big_int_from_u64(&bit, index);
big_int_shl(&bit, &one, &bit);
big_int_or(&bits, &bits, &bit);
} }
o->value = exact_value_u64(bits); o->value.kind = ExactValue_Integer;
o->value.value_integer = bits;
} else if (is_type_constant_type(type) && cl->elems.count == 0) { } else if (is_type_constant_type(type) && cl->elems.count == 0) {
ExactValue value = exact_value_compound(node); ExactValue value = exact_value_compound(node);
Type *bt = core_type(type); Type *bt = core_type(type);
@@ -8643,6 +8656,8 @@ ExprKind check_selector_call_expr(CheckerContext *c, Operand *o, Ast *node, Type
Ast *first_arg = x.expr->SelectorExpr.expr; Ast *first_arg = x.expr->SelectorExpr.expr;
GB_ASSERT(first_arg != nullptr); GB_ASSERT(first_arg != nullptr);
first_arg->state_flags |= StateFlag_SelectorCallExpr;
Type *pt = base_type(x.type); Type *pt = base_type(x.type);
GB_ASSERT(pt->kind == Type_Proc); GB_ASSERT(pt->kind == Type_Proc);
Type *first_type = nullptr; Type *first_type = nullptr;
@@ -8668,6 +8683,7 @@ ExprKind check_selector_call_expr(CheckerContext *c, Operand *o, Ast *node, Type
y.mode = first_arg->tav.mode; y.mode = first_arg->tav.mode;
y.type = first_arg->tav.type; y.type = first_arg->tav.type;
y.value = first_arg->tav.value; y.value = first_arg->tav.value;
if (check_is_assignable_to(c, &y, first_type)) { if (check_is_assignable_to(c, &y, first_type)) {
// Do nothing, it's valid // Do nothing, it's valid
} else { } else {
@@ -9286,7 +9302,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
check_unary_expr(c, o, ue->op, node); check_unary_expr(c, o, ue->op, node);
} }
o->expr = node; o->expr = node;
return kind; return Expr_Expr;
case_end; case_end;
@@ -10034,9 +10050,10 @@ gbString write_expr_to_string(gbString str, Ast *node, bool shorthand) {
str = write_expr_to_string(str, ce->proc, shorthand); str = write_expr_to_string(str, ce->proc, shorthand);
str = gb_string_appendc(str, "("); str = gb_string_appendc(str, "(");
for_array(i, ce->args) { isize idx0 = cast(isize)ce->was_selector;
for (isize i = idx0; i < ce->args.count; i++) {
Ast *arg = ce->args[i]; Ast *arg = ce->args[i];
if (i > 0) { if (i > idx0) {
str = gb_string_appendc(str, ", "); str = gb_string_appendc(str, ", ");
} }
str = write_expr_to_string(str, arg, shorthand); str = write_expr_to_string(str, arg, shorthand);
+44 -8
View File
@@ -695,11 +695,6 @@ void check_union_type(CheckerContext *ctx, Type *union_type, Ast *node, Array<Op
error(ut->align, "A union with #no_nil must have at least 2 variants"); error(ut->align, "A union with #no_nil must have at least 2 variants");
} }
break; break;
case UnionType_maybe:
if (variants.count != 1) {
error(ut->align, "A union with #maybe must have at 1 variant, got %lld", cast(long long)variants.count);
}
break;
} }
if (ut->align != nullptr) { if (ut->align != nullptr) {
@@ -1345,7 +1340,9 @@ ParameterValue handle_parameter_value(CheckerContext *ctx, Type *in_type, Type *
param_value.kind = ParameterValue_Constant; param_value.kind = ParameterValue_Constant;
param_value.value = o.value; param_value.value = o.value;
} else { } else {
error(expr, "Default parameter must be a constant, %d", o.mode); gbString s = expr_to_string(o.expr);
error(expr, "Default parameter must be a constant, got %s", s);
gb_string_free(s);
} }
} }
} else { } else {
@@ -1614,6 +1611,10 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is
error(name, "'#any_int' can only be applied to variable fields"); error(name, "'#any_int' can only be applied to variable fields");
p->flags &= ~FieldFlag_any_int; p->flags &= ~FieldFlag_any_int;
} }
if (p->flags&FieldFlag_by_ptr) {
error(name, "'#by_ptr' can only be applied to variable fields");
p->flags &= ~FieldFlag_by_ptr;
}
param = alloc_entity_type_name(scope, name->Ident.token, type, EntityState_Resolved); param = alloc_entity_type_name(scope, name->Ident.token, type, EntityState_Resolved);
param->TypeName.is_type_alias = true; param->TypeName.is_type_alias = true;
@@ -1690,10 +1691,17 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is
if (p->flags&FieldFlag_no_alias) { if (p->flags&FieldFlag_no_alias) {
if (!is_type_pointer(type)) { if (!is_type_pointer(type)) {
error(name, "'#no_alias' can only be applied to fields of pointer type"); error(name, "'#no_alias' can only be applied pointer typed parameters");
p->flags &= ~FieldFlag_no_alias; // Remove the flag p->flags &= ~FieldFlag_no_alias; // Remove the flag
} }
} }
if (p->flags&FieldFlag_by_ptr) {
if (is_type_internally_pointer_like(type)) {
error(name, "'#by_ptr' can only be applied to non-pointer-like parameters");
p->flags &= ~FieldFlag_by_ptr; // Remove the flag
}
}
if (is_poly_name) { if (is_poly_name) {
if (p->flags&FieldFlag_no_alias) { if (p->flags&FieldFlag_no_alias) {
error(name, "'#no_alias' can only be applied to non constant values"); error(name, "'#no_alias' can only be applied to non constant values");
@@ -1711,6 +1719,10 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is
error(name, "'#const' can only be applied to variable fields"); error(name, "'#const' can only be applied to variable fields");
p->flags &= ~FieldFlag_const; p->flags &= ~FieldFlag_const;
} }
if (p->flags&FieldFlag_by_ptr) {
error(name, "'#by_ptr' can only be applied to variable fields");
p->flags &= ~FieldFlag_by_ptr;
}
if (!is_type_constant_type(type) && !is_type_polymorphic(type)) { if (!is_type_constant_type(type) && !is_type_polymorphic(type)) {
gbString str = type_to_string(type); gbString str = type_to_string(type);
@@ -1743,6 +1755,9 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is
if (p->flags&FieldFlag_const) { if (p->flags&FieldFlag_const) {
param->flags |= EntityFlag_ConstInput; param->flags |= EntityFlag_ConstInput;
} }
if (p->flags&FieldFlag_by_ptr) {
param->flags |= EntityFlag_ByPtr;
}
param->state = EntityState_Resolved; // NOTE(bill): This should have be resolved whilst determining it param->state = EntityState_Resolved; // NOTE(bill): This should have be resolved whilst determining it
add_entity(ctx, scope, name, param); add_entity(ctx, scope, name, param);
@@ -2685,7 +2700,28 @@ bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, Type *named_t
case_end; case_end;
case_ast_node(pt, PointerType, e); case_ast_node(pt, PointerType, e);
*type = alloc_type_pointer(check_type(ctx, pt->type)); CheckerContext c = *ctx;
c.type_path = new_checker_type_path();
defer (destroy_checker_type_path(c.type_path));
Type *elem = t_invalid;
Operand o = {};
check_expr_or_type(&c, &o, pt->type);
if (o.mode != Addressing_Invalid && o.mode != Addressing_Type) {
// NOTE(bill): call check_type_expr again to get a consistent error message
begin_error_block();
elem = check_type_expr(&c, pt->type, nullptr);
if (o.mode == Addressing_Variable) {
gbString s = expr_to_string(pt->type);
error_line("\tSuggestion: ^ is used for pointer types, did you mean '&%s'?\n", s);
gb_string_free(s);
}
end_error_block();
} else {
elem = o.type;
}
*type = alloc_type_pointer(elem);
set_base_type(named_type, *type); set_base_type(named_type, *type);
return true; return true;
case_end; case_end;
+1 -1
View File
@@ -434,7 +434,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
{STR_LIT("simd_neg"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("simd_neg"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("simd_abs"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("simd_abs"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("simd_min"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("simd_min"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("simd_max"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("simd_max"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-1
View File
@@ -98,7 +98,6 @@ enum OdinDocTypeFlag_Struct : u32 {
enum OdinDocTypeFlag_Union : u32 { enum OdinDocTypeFlag_Union : u32 {
OdinDocTypeFlag_Union_polymorphic = 1<<0, OdinDocTypeFlag_Union_polymorphic = 1<<0,
OdinDocTypeFlag_Union_no_nil = 1<<1, OdinDocTypeFlag_Union_no_nil = 1<<1,
OdinDocTypeFlag_Union_maybe = 1<<2,
OdinDocTypeFlag_Union_shared_nil = 1<<3, OdinDocTypeFlag_Union_shared_nil = 1<<3,
}; };
+1
View File
@@ -83,6 +83,7 @@ enum EntityFlag : u64 {
EntityFlag_CustomLinkage_LinkOnce = 1ull<<44, EntityFlag_CustomLinkage_LinkOnce = 1ull<<44,
EntityFlag_Require = 1ull<<50, EntityFlag_Require = 1ull<<50,
EntityFlag_ByPtr = 1ull<<51, // enforce parameter is passed by pointer
EntityFlag_Overridden = 1ull<<63, EntityFlag_Overridden = 1ull<<63,
}; };
+4
View File
@@ -90,6 +90,10 @@ extern "C" {
#error This operating system is not supported #error This operating system is not supported
#endif #endif
#if defined(GB_SYSTEM_OPENBSD)
#include <sys/wait.h>
#endif
#if defined(_MSC_VER) #if defined(_MSC_VER)
#define GB_COMPILER_MSVC 1 #define GB_COMPILER_MSVC 1
#elif defined(__GNUC__) #elif defined(__GNUC__)
+14 -7
View File
@@ -233,7 +233,7 @@ i64 lb_sizeof(LLVMTypeRef type) {
i64 elem_size = lb_sizeof(elem); i64 elem_size = lb_sizeof(elem);
i64 count = LLVMGetVectorSize(type); i64 count = LLVMGetVectorSize(type);
i64 size = count * elem_size; i64 size = count * elem_size;
return gb_clamp(next_pow2(size), 1, build_context.max_align); return next_pow2(size);
} }
} }
@@ -801,16 +801,23 @@ namespace lbAbiAmd64SysV {
i64 elem_sz = lb_sizeof(elem); i64 elem_sz = lb_sizeof(elem);
LLVMTypeKind elem_kind = LLVMGetTypeKind(elem); LLVMTypeKind elem_kind = LLVMGetTypeKind(elem);
RegClass reg = RegClass_NoClass; RegClass reg = RegClass_NoClass;
unsigned elem_width = LLVMGetIntTypeWidth(elem);
switch (elem_kind) { switch (elem_kind) {
case LLVMIntegerTypeKind: case LLVMIntegerTypeKind:
case LLVMHalfTypeKind: case LLVMHalfTypeKind:
switch (LLVMGetIntTypeWidth(elem)) { switch (elem_width) {
case 8: reg = RegClass_SSEInt8; case 8: reg = RegClass_SSEInt8; break;
case 16: reg = RegClass_SSEInt16; case 16: reg = RegClass_SSEInt16; break;
case 32: reg = RegClass_SSEInt32; case 32: reg = RegClass_SSEInt32; break;
case 64: reg = RegClass_SSEInt64; case 64: reg = RegClass_SSEInt64; break;
default: default:
GB_PANIC("Unhandled integer width for vector type"); if (elem_width > 64) {
for (i64 i = 0; i < len; i++) {
classify_with(elem, cls, ix, off + i*elem_sz);
}
break;
}
GB_PANIC("Unhandled integer width for vector type %u", elem_width);
} }
break; break;
case LLVMFloatTypeKind: case LLVMFloatTypeKind:
+7
View File
@@ -292,6 +292,9 @@ struct lbProcedure {
LLVMMetadataRef debug_info; LLVMMetadataRef debug_info;
lbCopyElisionHint copy_elision_hint; lbCopyElisionHint copy_elision_hint;
PtrMap<Ast *, lbValue> selector_values;
PtrMap<Ast *, lbAddr> selector_addr;
}; };
@@ -479,7 +482,11 @@ LLVMValueRef llvm_basic_shuffle(lbProcedure *p, LLVMValueRef vector, LLVMValueRe
void lb_mem_copy_overlapping(lbProcedure *p, lbValue dst, lbValue src, lbValue len, bool is_volatile=false); void lb_mem_copy_overlapping(lbProcedure *p, lbValue dst, lbValue src, lbValue len, bool is_volatile=false);
void lb_mem_copy_non_overlapping(lbProcedure *p, lbValue dst, lbValue src, lbValue len, bool is_volatile=false); void lb_mem_copy_non_overlapping(lbProcedure *p, lbValue dst, lbValue src, lbValue len, bool is_volatile=false);
LLVMValueRef lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, LLVMValueRef len, unsigned alignment, bool is_volatile);
i64 lb_max_zero_init_size(void) {
return cast(i64)(4*build_context.word_size);
}
#define LB_STARTUP_RUNTIME_PROC_NAME "__$startup_runtime" #define LB_STARTUP_RUNTIME_PROC_NAME "__$startup_runtime"
#define LB_STARTUP_TYPE_INFO_PROC_NAME "__$startup_type_info" #define LB_STARTUP_TYPE_INFO_PROC_NAME "__$startup_type_info"
+10 -12
View File
@@ -1025,7 +1025,10 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
return lb_const_nil(m, original_type); return lb_const_nil(m, original_type);
} }
u64 bits = 0; BigInt bits = {};
BigInt one = {};
big_int_from_u64(&one, 1);
for_array(i, cl->elems) { for_array(i, cl->elems) {
Ast *e = cl->elems[i]; Ast *e = cl->elems[i];
GB_ASSERT(e->kind != Ast_FieldValue); GB_ASSERT(e->kind != Ast_FieldValue);
@@ -1037,18 +1040,13 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
GB_ASSERT(tav.value.kind == ExactValue_Integer); GB_ASSERT(tav.value.kind == ExactValue_Integer);
i64 v = big_int_to_i64(&tav.value.value_integer); i64 v = big_int_to_i64(&tav.value.value_integer);
i64 lower = type->BitSet.lower; i64 lower = type->BitSet.lower;
bits |= 1ull<<cast(u64)(v-lower); u64 index = cast(u64)(v-lower);
BigInt bit = {};
big_int_from_u64(&bit, index);
big_int_shl(&bit, &one, &bit);
big_int_or(&bits, &bits, &bit);
} }
if (is_type_different_to_arch_endianness(type)) { res.value = lb_big_int_to_llvm(m, original_type, &bits);
i64 size = type_size_of(type);
switch (size) {
case 2: bits = cast(u64)gb_endian_swap16(cast(u16)bits); break;
case 4: bits = cast(u64)gb_endian_swap32(cast(u32)bits); break;
case 8: bits = cast(u64)gb_endian_swap64(cast(u64)bits); break;
}
}
res.value = LLVMConstInt(lb_type(m, original_type), bits, false);
return res; return res;
} else if (is_type_matrix(type)) { } else if (is_type_matrix(type)) {
ast_node(cl, CompoundLit, value.value_compound); ast_node(cl, CompoundLit, value.value_compound);
+5 -1
View File
@@ -43,6 +43,10 @@ LLVMMetadataRef lb_debug_location_from_ast(lbProcedure *p, Ast *node) {
GB_ASSERT(node != nullptr); GB_ASSERT(node != nullptr);
return lb_debug_location_from_token_pos(p, ast_token(node).pos); return lb_debug_location_from_token_pos(p, ast_token(node).pos);
} }
LLVMMetadataRef lb_debug_end_location_from_ast(lbProcedure *p, Ast *node) {
GB_ASSERT(node != nullptr);
return lb_debug_location_from_token_pos(p, ast_end_token(node).pos);
}
LLVMMetadataRef lb_debug_type_internal_proc(lbModule *m, Type *type) { LLVMMetadataRef lb_debug_type_internal_proc(lbModule *m, Type *type) {
i64 size = type_size_of(type); // Check size i64 size = type_size_of(type); // Check size
@@ -969,7 +973,7 @@ void lb_add_debug_local_variable(lbProcedure *p, LLVMValueRef ptr, Type *type, T
); );
LLVMValueRef storage = ptr; LLVMValueRef storage = ptr;
LLVMBasicBlockRef block = p->decl_block->block; LLVMBasicBlockRef block = p->curr_block->block;
LLVMMetadataRef llvm_debug_loc = lb_debug_location_from_token_pos(p, token.pos); LLVMMetadataRef llvm_debug_loc = lb_debug_location_from_token_pos(p, token.pos);
LLVMMetadataRef llvm_expr = LLVMDIBuilderCreateExpression(m->debug_builder, nullptr, 0); LLVMMetadataRef llvm_expr = LLVMDIBuilderCreateExpression(m->debug_builder, nullptr, 0);
lb_set_llvm_metadata(m, ptr, llvm_expr); lb_set_llvm_metadata(m, ptr, llvm_expr);
+81 -29
View File
@@ -1,3 +1,4 @@
lbValue lb_emit_arith_matrix(lbProcedure *p, TokenKind op, lbValue lhs, lbValue rhs, Type *type, bool component_wise=false);
lbValue lb_emit_logical_binary_expr(lbProcedure *p, TokenKind op, Ast *left, Ast *right, Type *type) { lbValue lb_emit_logical_binary_expr(lbProcedure *p, TokenKind op, Ast *left, Ast *right, Type *type) {
lbModule *m = p->module; lbModule *m = p->module;
@@ -265,6 +266,11 @@ lbValue lb_emit_unary_arith(lbProcedure *p, TokenKind op, lbValue x, Type *type)
} else { } else {
res.value = LLVMBuildNeg(p->builder, x.value, ""); res.value = LLVMBuildNeg(p->builder, x.value, "");
} }
} else if (is_type_matrix(x.type)) {
lbValue zero = {};
zero.value = LLVMConstNull(lb_type(p->module, type));
zero.type = type;
return lb_emit_arith_matrix(p, Token_Sub, zero, x, type, true);
} else { } else {
GB_PANIC("Unhandled type %s", type_to_string(x.type)); GB_PANIC("Unhandled type %s", type_to_string(x.type));
} }
@@ -976,7 +982,7 @@ lbValue lb_emit_vector_mul_matrix(lbProcedure *p, lbValue lhs, lbValue rhs, Type
lbValue lb_emit_arith_matrix(lbProcedure *p, TokenKind op, lbValue lhs, lbValue rhs, Type *type, bool component_wise=false) { lbValue lb_emit_arith_matrix(lbProcedure *p, TokenKind op, lbValue lhs, lbValue rhs, Type *type, bool component_wise) {
GB_ASSERT(is_type_matrix(lhs.type) || is_type_matrix(rhs.type)); GB_ASSERT(is_type_matrix(lhs.type) || is_type_matrix(rhs.type));
@@ -1425,10 +1431,13 @@ lbValue lb_build_binary_expr(lbProcedure *p, Ast *expr) {
Type *it = bit_set_to_int(rt); Type *it = bit_set_to_int(rt);
left = lb_emit_conv(p, left, it); left = lb_emit_conv(p, left, it);
if (is_type_different_to_arch_endianness(it)) {
left = lb_emit_byte_swap(p, left, integer_endian_type_to_platform_type(it));
}
lbValue lower = lb_const_value(p->module, it, exact_value_i64(rt->BitSet.lower)); lbValue lower = lb_const_value(p->module, left.type, exact_value_i64(rt->BitSet.lower));
lbValue key = lb_emit_arith(p, Token_Sub, left, lower, it); lbValue key = lb_emit_arith(p, Token_Sub, left, lower, left.type);
lbValue bit = lb_emit_arith(p, Token_Shl, lb_const_int(p->module, it, 1), key, it); lbValue bit = lb_emit_arith(p, Token_Shl, lb_const_int(p->module, left.type, 1), key, left.type);
bit = lb_emit_conv(p, bit, it); bit = lb_emit_conv(p, bit, it);
lbValue old_value = lb_emit_transmute(p, right, it); lbValue old_value = lb_emit_transmute(p, right, it);
@@ -2993,9 +3002,8 @@ lbValue lb_build_unary_and(lbProcedure *p, Ast *expr) {
return lb_build_addr_ptr(p, ue->expr); return lb_build_addr_ptr(p, ue->expr);
} }
lbValue lb_build_expr_internal(lbProcedure *p, Ast *expr);
lbValue lb_build_expr(lbProcedure *p, Ast *expr) { lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
lbModule *m = p->module;
u16 prev_state_flags = p->state_flags; u16 prev_state_flags = p->state_flags;
defer (p->state_flags = prev_state_flags); defer (p->state_flags = prev_state_flags);
@@ -3022,6 +3030,38 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
p->state_flags = out; p->state_flags = out;
} }
// IMPORTANT NOTE(bill):
// Selector Call Expressions (foo->bar(...))
// must only evaluate `foo` once as it gets transformed into
// `foo.bar(foo, ...)`
// And if `foo` is a procedure call or something more complex, storing the value
// once is a very good idea
// If a stored value is found, it must be removed from the cache
if (expr->state_flags & StateFlag_SelectorCallExpr) {
lbValue *pp = map_get(&p->selector_values, expr);
if (pp != nullptr) {
lbValue res = *pp;
map_remove(&p->selector_values, expr);
return res;
}
lbAddr *pa = map_get(&p->selector_addr, expr);
if (pa != nullptr) {
lbAddr res = *pa;
map_remove(&p->selector_addr, expr);
return lb_addr_load(p, res);
}
}
lbValue res = lb_build_expr_internal(p, expr);
if (expr->state_flags & StateFlag_SelectorCallExpr) {
map_set(&p->selector_values, expr, res);
}
return res;
}
lbValue lb_build_expr_internal(lbProcedure *p, Ast *expr) {
lbModule *m = p->module;
expr = unparen_expr(expr); expr = unparen_expr(expr);
TokenPos expr_pos = ast_token(expr).pos; TokenPos expr_pos = ast_token(expr).pos;
@@ -3040,17 +3080,6 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
return lb_const_value(p->module, type, tv.value); return lb_const_value(p->module, type, tv.value);
} }
#if 0
LLVMMetadataRef prev_debug_location = nullptr;
if (p->debug_info != nullptr) {
prev_debug_location = LLVMGetCurrentDebugLocation2(p->builder);
LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, expr));
}
defer (if (prev_debug_location != nullptr) {
LLVMSetCurrentDebugLocation2(p->builder, prev_debug_location);
});
#endif
switch (expr->kind) { switch (expr->kind) {
case_ast_node(bl, BasicLit, expr); case_ast_node(bl, BasicLit, expr);
TokenPos pos = bl->token.pos; TokenPos pos = bl->token.pos;
@@ -3119,14 +3148,7 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
case_ast_node(se, SelectorCallExpr, expr); case_ast_node(se, SelectorCallExpr, expr);
GB_ASSERT(se->modified_call); GB_ASSERT(se->modified_call);
TypeAndValue tav = type_and_value_of_expr(expr); return lb_build_call_expr(p, se->call);
GB_ASSERT(tav.mode != Addressing_Invalid);
lbValue res = lb_build_call_expr(p, se->call);
ast_node(ce, CallExpr, se->call);
ce->sce_temp_data = gb_alloc_copy(permanent_allocator(), &res, gb_size_of(res));
return res;
case_end; case_end;
case_ast_node(te, TernaryIfExpr, expr); case_ast_node(te, TernaryIfExpr, expr);
@@ -3142,19 +3164,27 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
lb_start_block(p, then); lb_start_block(p, then);
Type *type = default_type(type_of_expr(expr)); Type *type = default_type(type_of_expr(expr));
LLVMTypeRef llvm_type = lb_type(p->module, type);
incoming_values[0] = lb_emit_conv(p, lb_build_expr(p, te->x), type).value; incoming_values[0] = lb_emit_conv(p, lb_build_expr(p, te->x), type).value;
if (is_type_internally_pointer_like(type)) {
incoming_values[0] = LLVMBuildBitCast(p->builder, incoming_values[0], llvm_type, "");
}
lb_emit_jump(p, done); lb_emit_jump(p, done);
lb_start_block(p, else_); lb_start_block(p, else_);
incoming_values[1] = lb_emit_conv(p, lb_build_expr(p, te->y), type).value; incoming_values[1] = lb_emit_conv(p, lb_build_expr(p, te->y), type).value;
if (is_type_internally_pointer_like(type)) {
incoming_values[1] = LLVMBuildBitCast(p->builder, incoming_values[1], llvm_type, "");
}
lb_emit_jump(p, done); lb_emit_jump(p, done);
lb_start_block(p, done); lb_start_block(p, done);
lbValue res = {}; lbValue res = {};
res.value = LLVMBuildPhi(p->builder, lb_type(p->module, type), ""); res.value = LLVMBuildPhi(p->builder, llvm_type, "");
res.type = type; res.type = type;
GB_ASSERT(p->curr_block->preds.count >= 2); GB_ASSERT(p->curr_block->preds.count >= 2);
@@ -3412,9 +3442,34 @@ lbAddr lb_build_array_swizzle_addr(lbProcedure *p, AstCallExpr *ce, TypeAndValue
} }
lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr);
lbAddr lb_build_addr(lbProcedure *p, Ast *expr) { lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
expr = unparen_expr(expr); expr = unparen_expr(expr);
// IMPORTANT NOTE(bill):
// Selector Call Expressions (foo->bar(...))
// must only evaluate `foo` once as it gets transformed into
// `foo.bar(foo, ...)`
// And if `foo` is a procedure call or something more complex, storing the value
// once is a very good idea
// If a stored value is found, it must be removed from the cache
if (expr->state_flags & StateFlag_SelectorCallExpr) {
lbAddr *pp = map_get(&p->selector_addr, expr);
if (pp != nullptr) {
lbAddr res = *pp;
map_remove(&p->selector_addr, expr);
return res;
}
}
lbAddr addr = lb_build_addr_internal(p, expr);
if (expr->state_flags & StateFlag_SelectorCallExpr) {
map_set(&p->selector_addr, expr, addr);
}
return addr;
}
lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) {
switch (expr->kind) { switch (expr->kind) {
case_ast_node(i, Implicit, expr); case_ast_node(i, Implicit, expr);
lbAddr v = {}; lbAddr v = {};
@@ -3556,9 +3611,6 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
case_end; case_end;
case_ast_node(se, SelectorCallExpr, expr); case_ast_node(se, SelectorCallExpr, expr);
GB_ASSERT(se->modified_call);
TypeAndValue tav = type_and_value_of_expr(expr);
GB_ASSERT(tav.mode != Addressing_Invalid);
lbValue e = lb_build_expr(p, expr); lbValue e = lb_build_expr(p, expr);
return lb_addr(lb_address_from_load_or_generate_local(p, e)); return lb_addr(lb_address_from_load_or_generate_local(p, e));
case_end; case_end;
+23 -9
View File
@@ -855,7 +855,11 @@ void lb_emit_store(lbProcedure *p, lbValue ptr, lbValue value) {
if (LLVMIsNull(value.value)) { if (LLVMIsNull(value.value)) {
LLVMTypeRef src_t = LLVMGetElementType(LLVMTypeOf(ptr.value)); LLVMTypeRef src_t = LLVMGetElementType(LLVMTypeOf(ptr.value));
LLVMBuildStore(p->builder, LLVMConstNull(src_t), ptr.value); if (lb_sizeof(src_t) <= lb_max_zero_init_size()) {
LLVMBuildStore(p->builder, LLVMConstNull(src_t), ptr.value);
} else {
lb_mem_zero_ptr(p, ptr.value, a, 1);
}
return; return;
} }
if (is_type_boolean(a)) { if (is_type_boolean(a)) {
@@ -1958,11 +1962,12 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
if (e->flags & EntityFlag_CVarArg) { if (e->flags & EntityFlag_CVarArg) {
continue; continue;
} }
Type *e_type = reduce_tuple_to_single_type(e->type); Type *e_type = reduce_tuple_to_single_type(e->type);
LLVMTypeRef param_type = nullptr; LLVMTypeRef param_type = nullptr;
if (is_type_boolean(e_type) && if (e->flags & EntityFlag_ByPtr) {
param_type = lb_type(m, alloc_type_pointer(e_type));
} else if (is_type_boolean(e_type) &&
type_size_of(e_type) <= 1) { type_size_of(e_type) <= 1) {
param_type = LLVMInt1TypeInContext(m->ctx); param_type = LLVMInt1TypeInContext(m->ctx);
} else { } else {
@@ -2369,6 +2374,9 @@ LLVMValueRef lb_find_or_add_entity_string_ptr(lbModule *m, String const &str) {
LLVMValueRef global_data = LLVMAddGlobal(m->mod, LLVMTypeOf(data), name); LLVMValueRef global_data = LLVMAddGlobal(m->mod, LLVMTypeOf(data), name);
LLVMSetInitializer(global_data, data); LLVMSetInitializer(global_data, data);
LLVMSetLinkage(global_data, LLVMPrivateLinkage); LLVMSetLinkage(global_data, LLVMPrivateLinkage);
LLVMSetUnnamedAddress(global_data, LLVMGlobalUnnamedAddr);
LLVMSetAlignment(global_data, 1);
LLVMSetGlobalConstant(global_data, true);
LLVMValueRef ptr = LLVMConstInBoundsGEP(global_data, indices, 2); LLVMValueRef ptr = LLVMConstInBoundsGEP(global_data, indices, 2);
string_map_set(&m->const_strings, key, ptr); string_map_set(&m->const_strings, key, ptr);
@@ -2411,6 +2419,9 @@ lbValue lb_find_or_add_entity_string_byte_slice(lbModule *m, String const &str)
LLVMValueRef global_data = LLVMAddGlobal(m->mod, LLVMTypeOf(data), name); LLVMValueRef global_data = LLVMAddGlobal(m->mod, LLVMTypeOf(data), name);
LLVMSetInitializer(global_data, data); LLVMSetInitializer(global_data, data);
LLVMSetLinkage(global_data, LLVMPrivateLinkage); LLVMSetLinkage(global_data, LLVMPrivateLinkage);
LLVMSetUnnamedAddress(global_data, LLVMGlobalUnnamedAddr);
LLVMSetAlignment(global_data, 1);
LLVMSetGlobalConstant(global_data, true);
LLVMValueRef ptr = nullptr; LLVMValueRef ptr = nullptr;
if (str.len != 0) { if (str.len != 0) {
@@ -2647,6 +2658,7 @@ lbValue lb_generate_global_array(lbModule *m, Type *elem_type, i64 count, String
g.type = alloc_type_pointer(t); g.type = alloc_type_pointer(t);
LLVMSetInitializer(g.value, LLVMConstNull(lb_type(m, t))); LLVMSetInitializer(g.value, LLVMConstNull(lb_type(m, t)));
LLVMSetLinkage(g.value, LLVMPrivateLinkage); LLVMSetLinkage(g.value, LLVMPrivateLinkage);
LLVMSetUnnamedAddress(g.value, LLVMGlobalUnnamedAddr);
string_map_set(&m->members, s, g); string_map_set(&m->members, s, g);
return g; return g;
} }
@@ -2729,20 +2741,18 @@ lbAddr lb_add_local(lbProcedure *p, Type *type, Entity *e, bool zero_init, i32 p
if (!zero_init && !force_no_init) { if (!zero_init && !force_no_init) {
// If there is any padding of any kind, just zero init regardless of zero_init parameter // If there is any padding of any kind, just zero init regardless of zero_init parameter
LLVMTypeKind kind = LLVMGetTypeKind(llvm_type); LLVMTypeKind kind = LLVMGetTypeKind(llvm_type);
if (kind == LLVMArrayTypeKind) {
kind = LLVMGetTypeKind(lb_type(p->module, core_array_type(type)));
}
if (kind == LLVMStructTypeKind) { if (kind == LLVMStructTypeKind) {
i64 sz = type_size_of(type); i64 sz = type_size_of(type);
if (type_size_of_struct_pretend_is_packed(type) != sz) { if (type_size_of_struct_pretend_is_packed(type) != sz) {
zero_init = true; zero_init = true;
} }
} else if (kind == LLVMArrayTypeKind) {
zero_init = true;
} }
} }
if (zero_init) {
lb_mem_zero_ptr(p, ptr, type, alignment);
}
lbValue val = {}; lbValue val = {};
val.value = ptr; val.value = ptr;
val.type = alloc_type_pointer(type); val.type = alloc_type_pointer(type);
@@ -2752,6 +2762,10 @@ lbAddr lb_add_local(lbProcedure *p, Type *type, Entity *e, bool zero_init, i32 p
lb_add_debug_local_variable(p, ptr, type, e->token); lb_add_debug_local_variable(p, ptr, type, e->token);
} }
if (zero_init) {
lb_mem_zero_ptr(p, ptr, type, alignment);
}
return lb_addr(val); return lb_addr(val);
} }
+43 -18
View File
@@ -113,6 +113,8 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool ignore_body)
p->branch_blocks.allocator = a; p->branch_blocks.allocator = a;
p->context_stack.allocator = a; p->context_stack.allocator = a;
p->scope_stack.allocator = a; p->scope_stack.allocator = a;
map_init(&p->selector_values, a, 0);
map_init(&p->selector_addr, a, 0);
if (p->is_foreign) { if (p->is_foreign) {
lb_add_foreign_library_path(p->module, entity->Procedure.foreign_library); lb_add_foreign_library_path(p->module, entity->Procedure.foreign_library);
@@ -433,6 +435,40 @@ void lb_start_block(lbProcedure *p, lbBlock *b) {
p->curr_block = b; p->curr_block = b;
} }
void lb_set_debug_position_to_procedure_begin(lbProcedure *p) {
if (p->debug_info == nullptr) {
return;
}
TokenPos pos = {};
if (p->body != nullptr) {
pos = ast_token(p->body).pos;
} else if (p->type_expr != nullptr) {
pos = ast_token(p->type_expr).pos;
} else if (p->entity != nullptr) {
pos = p->entity->token.pos;
}
if (pos.file_id != 0) {
LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_token_pos(p, pos));
}
}
void lb_set_debug_position_to_procedure_end(lbProcedure *p) {
if (p->debug_info == nullptr) {
return;
}
TokenPos pos = {};
if (p->body != nullptr) {
pos = ast_end_token(p->body).pos;
} else if (p->type_expr != nullptr) {
pos = ast_end_token(p->type_expr).pos;
} else if (p->entity != nullptr) {
pos = p->entity->token.pos;
}
if (pos.file_id != 0) {
LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_token_pos(p, pos));
}
}
void lb_begin_procedure_body(lbProcedure *p) { void lb_begin_procedure_body(lbProcedure *p) {
DeclInfo *decl = decl_info_of_entity(p->entity); DeclInfo *decl = decl_info_of_entity(p->entity);
if (decl != nullptr) { if (decl != nullptr) {
@@ -564,29 +600,21 @@ void lb_begin_procedure_body(lbProcedure *p) {
lb_push_context_onto_stack_from_implicit_parameter(p); lb_push_context_onto_stack_from_implicit_parameter(p);
} }
lb_start_block(p, p->entry_block); lb_set_debug_position_to_procedure_begin(p);
if (p->debug_info != nullptr) { if (p->debug_info != nullptr) {
TokenPos pos = {};
if (p->body != nullptr) {
pos = ast_token(p->body).pos;
} else if (p->type_expr != nullptr) {
pos = ast_token(p->type_expr).pos;
} else if (p->entity != nullptr) {
pos = p->entity->token.pos;
}
if (pos.file_id != 0) {
LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_token_pos(p, pos));
}
if (p->context_stack.count != 0) { if (p->context_stack.count != 0) {
p->curr_block = p->decl_block;
lb_add_debug_context_variable(p, lb_find_or_generate_context_ptr(p)); lb_add_debug_context_variable(p, lb_find_or_generate_context_ptr(p));
} }
} }
lb_start_block(p, p->entry_block);
} }
void lb_end_procedure_body(lbProcedure *p) { void lb_end_procedure_body(lbProcedure *p) {
lb_set_debug_position_to_procedure_begin(p);
LLVMPositionBuilderAtEnd(p->builder, p->decl_block->block); LLVMPositionBuilderAtEnd(p->builder, p->decl_block->block);
LLVMBuildBr(p->builder, p->entry_block->block); LLVMBuildBr(p->builder, p->entry_block->block);
LLVMPositionBuilderAtEnd(p->builder, p->curr_block->block); LLVMPositionBuilderAtEnd(p->builder, p->curr_block->block);
@@ -598,6 +626,7 @@ void lb_end_procedure_body(lbProcedure *p) {
instr = LLVMGetLastInstruction(p->curr_block->block); instr = LLVMGetLastInstruction(p->curr_block->block);
if (!lb_is_instr_terminating(instr)) { if (!lb_is_instr_terminating(instr)) {
lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr); lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
lb_set_debug_position_to_procedure_end(p);
LLVMBuildRetVoid(p->builder); LLVMBuildRetVoid(p->builder);
} }
} }
@@ -2832,10 +2861,6 @@ lbValue lb_build_call_expr(lbProcedure *p, Ast *expr) {
expr = unparen_expr(expr); expr = unparen_expr(expr);
ast_node(ce, CallExpr, expr); ast_node(ce, CallExpr, expr);
if (ce->sce_temp_data) {
return *(lbValue *)ce->sce_temp_data;
}
lbValue res = lb_build_call_expr_internal(p, expr); lbValue res = lb_build_call_expr_internal(p, expr);
if (ce->optional_ok_one) { // TODO(bill): Minor hack for #optional_ok procedures if (ce->optional_ok_one) { // TODO(bill): Minor hack for #optional_ok procedures
+20 -10
View File
@@ -1210,8 +1210,8 @@ void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope *scope) {
} }
lb_emit_jump(p, done); lb_emit_jump(p, done);
lb_close_scope(p, lbDeferExit_Default, done);
lb_start_block(p, done); lb_start_block(p, done);
lb_close_scope(p, lbDeferExit_Default, done);
} }
void lb_store_type_case_implicit(lbProcedure *p, Ast *clause, lbValue value) { void lb_store_type_case_implicit(lbProcedure *p, Ast *clause, lbValue value) {
@@ -1253,7 +1253,6 @@ void lb_type_case_body(lbProcedure *p, Ast *label, Ast *clause, lbBlock *body, l
ast_node(cc, CaseClause, clause); ast_node(cc, CaseClause, clause);
lb_push_target_list(p, label, done, nullptr, nullptr); lb_push_target_list(p, label, done, nullptr, nullptr);
lb_open_scope(p, body->scope);
lb_build_stmt_list(p, cc->stmts); lb_build_stmt_list(p, cc->stmts);
lb_close_scope(p, lbDeferExit_Default, body); lb_close_scope(p, lbDeferExit_Default, body);
lb_pop_target_list(p); lb_pop_target_list(p);
@@ -1263,6 +1262,7 @@ void lb_type_case_body(lbProcedure *p, Ast *label, Ast *clause, lbBlock *body, l
void lb_build_type_switch_stmt(lbProcedure *p, AstTypeSwitchStmt *ss) { void lb_build_type_switch_stmt(lbProcedure *p, AstTypeSwitchStmt *ss) {
lbModule *m = p->module; lbModule *m = p->module;
lb_open_scope(p, ss->scope);
ast_node(as, AssignStmt, ss->tag); ast_node(as, AssignStmt, ss->tag);
GB_ASSERT(as->lhs.count == 1); GB_ASSERT(as->lhs.count == 1);
@@ -1321,6 +1321,7 @@ void lb_build_type_switch_stmt(lbProcedure *p, AstTypeSwitchStmt *ss) {
for_array(i, body->stmts) { for_array(i, body->stmts) {
Ast *clause = body->stmts[i]; Ast *clause = body->stmts[i];
ast_node(cc, CaseClause, clause); ast_node(cc, CaseClause, clause);
lb_open_scope(p, cc->scope);
if (cc->list.count == 0) { if (cc->list.count == 0) {
lb_start_block(p, default_block); lb_start_block(p, default_block);
lb_store_type_case_implicit(p, clause, parent_value); lb_store_type_case_implicit(p, clause, parent_value);
@@ -1329,6 +1330,9 @@ void lb_build_type_switch_stmt(lbProcedure *p, AstTypeSwitchStmt *ss) {
} }
lbBlock *body = lb_create_block(p, "typeswitch.body"); lbBlock *body = lb_create_block(p, "typeswitch.body");
if (p->debug_info != nullptr) {
LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, clause));
}
Type *case_type = nullptr; Type *case_type = nullptr;
for_array(type_index, cc->list) { for_array(type_index, cc->list) {
case_type = type_of_expr(cc->list[type_index]); case_type = type_of_expr(cc->list[type_index]);
@@ -1375,6 +1379,7 @@ void lb_build_type_switch_stmt(lbProcedure *p, AstTypeSwitchStmt *ss) {
lb_emit_jump(p, done); lb_emit_jump(p, done);
lb_start_block(p, done); lb_start_block(p, done);
lb_close_scope(p, lbDeferExit_Default, done);
} }
@@ -1721,6 +1726,9 @@ void lb_build_for_stmt(lbProcedure *p, Ast *node) {
ast_node(fs, ForStmt, node); ast_node(fs, ForStmt, node);
lb_open_scope(p, fs->scope); // Open Scope here lb_open_scope(p, fs->scope); // Open Scope here
if (p->debug_info != nullptr) {
LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, node));
}
if (fs->init != nullptr) { if (fs->init != nullptr) {
#if 1 #if 1
@@ -1741,11 +1749,14 @@ void lb_build_for_stmt(lbProcedure *p, Ast *node) {
post = lb_create_block(p, "for.post"); post = lb_create_block(p, "for.post");
} }
lb_emit_jump(p, loop); lb_emit_jump(p, loop);
lb_start_block(p, loop); lb_start_block(p, loop);
if (loop != body) { if (loop != body) {
// right now the condition (all expressions) will not set it's debug location, so we will do it here
if (p->debug_info != nullptr) {
LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, fs->cond));
}
lb_build_cond(p, fs->cond, body, done); lb_build_cond(p, fs->cond, body, done);
lb_start_block(p, body); lb_start_block(p, body);
} }
@@ -1753,10 +1764,12 @@ void lb_build_for_stmt(lbProcedure *p, Ast *node) {
lb_push_target_list(p, fs->label, done, post, nullptr); lb_push_target_list(p, fs->label, done, post, nullptr);
lb_build_stmt(p, fs->body); lb_build_stmt(p, fs->body);
lb_close_scope(p, lbDeferExit_Default, nullptr);
lb_pop_target_list(p); lb_pop_target_list(p);
if (p->debug_info != nullptr) {
LLVMSetCurrentDebugLocation2(p->builder, lb_debug_end_location_from_ast(p, fs->body));
}
lb_emit_jump(p, post); lb_emit_jump(p, post);
if (fs->post != nullptr) { if (fs->post != nullptr) {
@@ -1766,6 +1779,7 @@ void lb_build_for_stmt(lbProcedure *p, Ast *node) {
} }
lb_start_block(p, done); lb_start_block(p, done);
lb_close_scope(p, lbDeferExit_Default, nullptr);
} }
void lb_build_assign_stmt_array(lbProcedure *p, TokenKind op, lbAddr const &lhs, lbValue const &value) { void lb_build_assign_stmt_array(lbProcedure *p, TokenKind op, lbAddr const &lhs, lbValue const &value) {
@@ -1971,14 +1985,9 @@ void lb_build_stmt(lbProcedure *p, Ast *node) {
} }
} }
LLVMMetadataRef prev_debug_location = nullptr;
if (p->debug_info != nullptr) { if (p->debug_info != nullptr) {
prev_debug_location = LLVMGetCurrentDebugLocation2(p->builder);
LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, node)); LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, node));
} }
defer (if (prev_debug_location != nullptr) {
LLVMSetCurrentDebugLocation2(p->builder, prev_debug_location);
});
u16 prev_state_flags = p->state_flags; u16 prev_state_flags = p->state_flags;
defer (p->state_flags = prev_state_flags); defer (p->state_flags = prev_state_flags);
@@ -2073,7 +2082,8 @@ void lb_build_stmt(lbProcedure *p, Ast *node) {
lbAddr lval = {}; lbAddr lval = {};
if (!is_blank_ident(name)) { if (!is_blank_ident(name)) {
Entity *e = entity_of_node(name); Entity *e = entity_of_node(name);
bool zero_init = true; // Always do it // bool zero_init = true; // Always do it
bool zero_init = vd->values.count == 0;
lval = lb_add_local(p, e->type, e, zero_init); lval = lb_add_local(p, e->type, e, zero_init);
} }
array_add(&lvals, lval); array_add(&lvals, lval);
+26 -13
View File
@@ -1,3 +1,5 @@
lbValue lb_lookup_runtime_procedure(lbModule *m, String const &name);
bool lb_is_type_aggregate(Type *t) { bool lb_is_type_aggregate(Type *t) {
t = base_type(t); t = base_type(t);
switch (t->kind) { switch (t->kind) {
@@ -48,18 +50,19 @@ lbValue lb_correct_endianness(lbProcedure *p, lbValue value) {
return value; return value;
} }
void lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, LLVMValueRef len, unsigned alignment, bool is_volatile) { LLVMValueRef lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, LLVMValueRef len, unsigned alignment, bool is_volatile) {
bool is_inlinable = false; bool is_inlinable = false;
i64 const_len = 0; i64 const_len = 0;
if (LLVMIsConstant(len)) { if (LLVMIsConstant(len)) {
const_len = cast(i64)LLVMConstIntGetSExtValue(len); const_len = cast(i64)LLVMConstIntGetSExtValue(len);
// TODO(bill): Determine when it is better to do the `*.inline` versions // TODO(bill): Determine when it is better to do the `*.inline` versions
if (const_len <= 4*build_context.word_size) { if (const_len <= lb_max_zero_init_size()) {
is_inlinable = true; is_inlinable = true;
} }
} }
char const *name = "llvm.memset"; char const *name = "llvm.memset";
if (is_inlinable) { if (is_inlinable) {
name = "llvm.memset.inline"; name = "llvm.memset.inline";
@@ -69,17 +72,29 @@ void lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, LLVMValueRef len
lb_type(p->module, t_rawptr), lb_type(p->module, t_rawptr),
lb_type(p->module, t_int) lb_type(p->module, t_int)
}; };
unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name)); if (true || is_inlinable) {
GB_ASSERT_MSG(id != 0, "Unable to find %s.%s.%s", name, LLVMPrintTypeToString(types[0]), LLVMPrintTypeToString(types[1])); unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types)); GB_ASSERT_MSG(id != 0, "Unable to find %s.%s.%s", name, LLVMPrintTypeToString(types[0]), LLVMPrintTypeToString(types[1]));
LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
LLVMValueRef args[4] = {}; LLVMValueRef args[4] = {};
args[0] = LLVMBuildPointerCast(p->builder, ptr, types[0], ""); args[0] = LLVMBuildPointerCast(p->builder, ptr, types[0], "");
args[1] = LLVMConstInt(LLVMInt8TypeInContext(p->module->ctx), 0, false); args[1] = LLVMConstInt(LLVMInt8TypeInContext(p->module->ctx), 0, false);
args[2] = LLVMBuildIntCast2(p->builder, len, types[1], /*signed*/false, ""); args[2] = LLVMBuildIntCast2(p->builder, len, types[1], /*signed*/false, "");
args[3] = LLVMConstInt(LLVMInt1TypeInContext(p->module->ctx), is_volatile, false); args[3] = LLVMConstInt(LLVMInt1TypeInContext(p->module->ctx), is_volatile, false);
return LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
} else {
LLVMValueRef ip = lb_lookup_runtime_procedure(p->module, str_lit("memset")).value;
LLVMValueRef args[3] = {};
args[0] = LLVMBuildPointerCast(p->builder, ptr, types[0], "");
args[1] = LLVMConstInt(LLVMInt32TypeInContext(p->module->ctx), 0, false);
args[2] = LLVMBuildIntCast2(p->builder, len, types[1], /*signed*/false, "");
return LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
}
LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
} }
void lb_mem_zero_ptr(lbProcedure *p, LLVMValueRef ptr, Type *type, unsigned alignment) { void lb_mem_zero_ptr(lbProcedure *p, LLVMValueRef ptr, Type *type, unsigned alignment) {
@@ -1842,8 +1857,6 @@ void lb_set_wasm_export_attributes(LLVMValueRef value, String export_name) {
} }
lbValue lb_lookup_runtime_procedure(lbModule *m, String const &name);
lbAddr lb_handle_objc_find_or_register_selector(lbProcedure *p, String const &name) { lbAddr lb_handle_objc_find_or_register_selector(lbProcedure *p, String const &name) {
lbAddr *found = string_map_get(&p->module->objc_selectors, name); lbAddr *found = string_map_get(&p->module->objc_selectors, name);
+9 -2
View File
@@ -463,8 +463,15 @@ i32 linker_stage(lbGenerator *gen) {
// correctly this way since all the other dependencies provided implicitly // correctly this way since all the other dependencies provided implicitly
// by the compiler frontend are still needed and most of the command // by the compiler frontend are still needed and most of the command
// line arguments prepared previously are incompatible with ld. // line arguments prepared previously are incompatible with ld.
link_settings = gb_string_appendc(link_settings, "-Wl,-init,'_odin_entry_point' "); if (build_context.metrics.os == TargetOs_darwin) {
link_settings = gb_string_appendc(link_settings, "-Wl,-fini,'_odin_exit_point' "); link_settings = gb_string_appendc(link_settings, "-Wl,-init,'__odin_entry_point' ");
// NOTE(weshardee): __odin_exit_point should also be added, but -fini
// does not exist on MacOS
} else {
link_settings = gb_string_appendc(link_settings, "-Wl,-init,'_odin_entry_point' ");
link_settings = gb_string_appendc(link_settings, "-Wl,-fini,'_odin_exit_point' ");
}
} else if (build_context.metrics.os != TargetOs_openbsd) { } else if (build_context.metrics.os != TargetOs_openbsd) {
// OpenBSD defaults to PIE executable. do not pass -no-pie for it. // OpenBSD defaults to PIE executable. do not pass -no-pie for it.
link_settings = gb_string_appendc(link_settings, "-no-pie "); link_settings = gb_string_appendc(link_settings, "-no-pie ");
+28
View File
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="String">
<DisplayString>{text,[len]s8}</DisplayString>
<StringView>text,[len]s8</StringView>
</Type>
<Type Name="Array&lt;*&gt;">
<DisplayString>{{ size={count} capacity={capacity} }}</DisplayString>
<Expand>
<ArrayItems>
<Size>count</Size>
<ValuePointer>data</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<Type Name="Slice&lt;*&gt;">
<DisplayString>{{ size={count} }}</DisplayString>
<Expand>
<ArrayItems>
<Size>count</Size>
<ValuePointer>data</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<Type Name="lbProcedure">
<DisplayString>Procedure {name}</DisplayString>
</Type>
</AutoVisualizer>
+26 -48
View File
@@ -2324,11 +2324,7 @@ Ast *parse_operand(AstFile *f, bool lhs) {
body = convert_stmt_to_body(f, parse_stmt(f)); body = convert_stmt_to_body(f, parse_stmt(f));
f->curr_proc = curr_proc; f->curr_proc = curr_proc;
if (build_context.disallow_do) { syntax_error(body, "'do' for procedure bodies is not allowed, prefer {}");
syntax_error(body, "'do' has been disallowed");
} else if (!ast_on_same_line(type, body)) {
syntax_error(body, "The body of a 'do' must be on the same line as the signature");
}
return ast_proc_lit(f, type, body, tags, where_token, where_clauses); return ast_proc_lit(f, type, body, tags, where_token, where_clauses);
} }
@@ -2552,21 +2548,15 @@ Ast *parse_operand(AstFile *f, bool lhs) {
syntax_error(tag, "Invalid union tag '#%.*s'", LIT(tag.string)); syntax_error(tag, "Invalid union tag '#%.*s'", LIT(tag.string));
} }
} }
if (no_nil && maybe) {
syntax_error(f->curr_token, "#maybe and #no_nil cannot be applied together");
}
if (no_nil && shared_nil) { if (no_nil && shared_nil) {
syntax_error(f->curr_token, "#shared_nil and #no_nil cannot be applied together"); syntax_error(f->curr_token, "#shared_nil and #no_nil cannot be applied together");
} }
if (shared_nil && maybe) {
syntax_error(f->curr_token, "#maybe and #shared_nil cannot be applied together");
}
if (maybe) { if (maybe) {
union_kind = UnionType_maybe;
syntax_error(f->curr_token, "#maybe functionality has now been merged with standard 'union' functionality"); syntax_error(f->curr_token, "#maybe functionality has now been merged with standard 'union' functionality");
} else if (no_nil) { }
if (no_nil) {
union_kind = UnionType_no_nil; union_kind = UnionType_no_nil;
} else if (shared_nil) { } else if (shared_nil) {
union_kind = UnionType_shared_nil; union_kind = UnionType_shared_nil;
@@ -3554,47 +3544,34 @@ Ast *parse_var_type(AstFile *f, bool allow_ellipsis, bool allow_typeid_token) {
} }
enum FieldPrefixKind : i32 {
FieldPrefix_Unknown = -1,
FieldPrefix_Invalid = 0,
FieldPrefix_using, // implies #subtype
FieldPrefix_const,
FieldPrefix_no_alias,
FieldPrefix_c_vararg,
FieldPrefix_auto_cast,
FieldPrefix_any_int,
FieldPrefix_subtype, // does not imply `using` semantics
};
struct ParseFieldPrefixMapping { struct ParseFieldPrefixMapping {
String name; String name;
TokenKind token_kind; TokenKind token_kind;
FieldPrefixKind prefix;
FieldFlag flag; FieldFlag flag;
}; };
gb_global ParseFieldPrefixMapping parse_field_prefix_mappings[] = { gb_global ParseFieldPrefixMapping parse_field_prefix_mappings[] = {
{str_lit("using"), Token_using, FieldPrefix_using, FieldFlag_using}, {str_lit("using"), Token_using, FieldFlag_using},
{str_lit("auto_cast"), Token_auto_cast, FieldPrefix_auto_cast, FieldFlag_auto_cast}, {str_lit("auto_cast"), Token_auto_cast, FieldFlag_auto_cast},
{str_lit("no_alias"), Token_Hash, FieldPrefix_no_alias, FieldFlag_no_alias}, {str_lit("no_alias"), Token_Hash, FieldFlag_no_alias},
{str_lit("c_vararg"), Token_Hash, FieldPrefix_c_vararg, FieldFlag_c_vararg}, {str_lit("c_vararg"), Token_Hash, FieldFlag_c_vararg},
{str_lit("const"), Token_Hash, FieldPrefix_const, FieldFlag_const}, {str_lit("const"), Token_Hash, FieldFlag_const},
{str_lit("any_int"), Token_Hash, FieldPrefix_any_int, FieldFlag_any_int}, {str_lit("any_int"), Token_Hash, FieldFlag_any_int},
{str_lit("subtype"), Token_Hash, FieldPrefix_subtype, FieldFlag_subtype}, {str_lit("subtype"), Token_Hash, FieldFlag_subtype},
{str_lit("by_ptr"), Token_Hash, FieldFlag_by_ptr},
}; };
FieldPrefixKind is_token_field_prefix(AstFile *f) { FieldFlag is_token_field_prefix(AstFile *f) {
switch (f->curr_token.kind) { switch (f->curr_token.kind) {
case Token_EOF: case Token_EOF:
return FieldPrefix_Invalid; return FieldFlag_Invalid;
case Token_using: case Token_using:
return FieldPrefix_using; return FieldFlag_using;
case Token_auto_cast: case Token_auto_cast:
return FieldPrefix_auto_cast; return FieldFlag_auto_cast;
case Token_Hash: case Token_Hash:
advance_token(f); advance_token(f);
@@ -3604,33 +3581,33 @@ FieldPrefixKind is_token_field_prefix(AstFile *f) {
auto const &mapping = parse_field_prefix_mappings[i]; auto const &mapping = parse_field_prefix_mappings[i];
if (mapping.token_kind == Token_Hash) { if (mapping.token_kind == Token_Hash) {
if (f->curr_token.string == mapping.name) { if (f->curr_token.string == mapping.name) {
return mapping.prefix; return mapping.flag;
} }
} }
} }
break; break;
} }
return FieldPrefix_Unknown; return FieldFlag_Unknown;
} }
return FieldPrefix_Invalid; return FieldFlag_Invalid;
} }
u32 parse_field_prefixes(AstFile *f) { u32 parse_field_prefixes(AstFile *f) {
i32 counts[gb_count_of(parse_field_prefix_mappings)] = {}; i32 counts[gb_count_of(parse_field_prefix_mappings)] = {};
for (;;) { for (;;) {
FieldPrefixKind kind = is_token_field_prefix(f); FieldFlag flag = is_token_field_prefix(f);
if (kind == FieldPrefix_Invalid) { if (flag & FieldFlag_Invalid) {
break; break;
} }
if (kind == FieldPrefix_Unknown) { if (flag & FieldFlag_Unknown) {
syntax_error(f->curr_token, "Unknown prefix kind '#%.*s'", LIT(f->curr_token.string)); syntax_error(f->curr_token, "Unknown prefix kind '#%.*s'", LIT(f->curr_token.string));
advance_token(f); advance_token(f);
continue; continue;
} }
for (i32 i = 0; i < gb_count_of(parse_field_prefix_mappings); i++) { for (i32 i = 0; i < gb_count_of(parse_field_prefix_mappings); i++) {
if (parse_field_prefix_mappings[i].prefix == kind) { if (parse_field_prefix_mappings[i].flag == flag) {
counts[i] += 1; counts[i] += 1;
advance_token(f); advance_token(f);
break; break;
@@ -3896,7 +3873,8 @@ Ast *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, TokenKi
while (f->curr_token.kind != follow && while (f->curr_token.kind != follow &&
f->curr_token.kind != Token_EOF) { f->curr_token.kind != Token_EOF &&
f->curr_token.kind != Token_Semicolon) {
CommentGroup *docs = f->lead_comment; CommentGroup *docs = f->lead_comment;
u32 set_flags = parse_field_prefixes(f); u32 set_flags = parse_field_prefixes(f);
Token tag = {}; Token tag = {};
@@ -3924,7 +3902,7 @@ Ast *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, TokenKi
default_value = parse_expr(f, false); default_value = parse_expr(f, false);
if (!allow_default_parameters) { if (!allow_default_parameters) {
syntax_error(f->curr_token, "Default parameters are only allowed for procedures"); syntax_error(f->curr_token, "Default parameters are only allowed for procedures");
default_value = nullptr; default_value = nullptr;
} }
} }
+9 -3
View File
@@ -282,6 +282,8 @@ enum StateFlag : u8 {
StateFlag_type_assert = 1<<2, StateFlag_type_assert = 1<<2,
StateFlag_no_type_assert = 1<<3, StateFlag_no_type_assert = 1<<3,
StateFlag_SelectorCallExpr = 1<<6,
StateFlag_BeenHandled = 1<<7, StateFlag_BeenHandled = 1<<7,
}; };
@@ -300,13 +302,18 @@ enum FieldFlag : u32 {
FieldFlag_const = 1<<5, FieldFlag_const = 1<<5,
FieldFlag_any_int = 1<<6, FieldFlag_any_int = 1<<6,
FieldFlag_subtype = 1<<7, FieldFlag_subtype = 1<<7,
FieldFlag_by_ptr = 1<<8,
// Internal use by the parser only // Internal use by the parser only
FieldFlag_Tags = 1<<10, FieldFlag_Tags = 1<<10,
FieldFlag_Results = 1<<16, FieldFlag_Results = 1<<16,
FieldFlag_Unknown = 1u<<30,
FieldFlag_Invalid = 1u<<31,
// Parameter List Restrictions // Parameter List Restrictions
FieldFlag_Signature = FieldFlag_ellipsis|FieldFlag_using|FieldFlag_no_alias|FieldFlag_c_vararg|FieldFlag_auto_cast|FieldFlag_const|FieldFlag_any_int, FieldFlag_Signature = FieldFlag_ellipsis|FieldFlag_using|FieldFlag_no_alias|FieldFlag_c_vararg|FieldFlag_auto_cast|FieldFlag_const|FieldFlag_any_int|FieldFlag_by_ptr,
FieldFlag_Struct = FieldFlag_using|FieldFlag_subtype|FieldFlag_Tags, FieldFlag_Struct = FieldFlag_using|FieldFlag_subtype|FieldFlag_Tags,
}; };
@@ -332,7 +339,6 @@ char const *inline_asm_dialect_strings[InlineAsmDialect_COUNT] = {
enum UnionTypeKind : u8 { enum UnionTypeKind : u8 {
UnionType_Normal = 0, UnionType_Normal = 0,
UnionType_maybe = 1, // removed
UnionType_no_nil = 2, UnionType_no_nil = 2,
UnionType_shared_nil = 3, UnionType_shared_nil = 3,
}; };
@@ -411,7 +417,7 @@ AST_KIND(_ExprBegin, "", bool) \
Token ellipsis; \ Token ellipsis; \
ProcInlining inlining; \ ProcInlining inlining; \
bool optional_ok_one; \ bool optional_ok_one; \
void *sce_temp_data; \ bool was_selector; \
}) \ }) \
AST_KIND(FieldValue, "field value", struct { Token eq; Ast *field, *value; }) \ AST_KIND(FieldValue, "field value", struct { Token eq; Ast *field, *value; }) \
AST_KIND(EnumFieldValue, "enum field value", struct { \ AST_KIND(EnumFieldValue, "enum field value", struct { \
@@ -79,8 +79,8 @@ test_leb128 :: proc(t: ^testing.T) {
} }
} }
for num_bytes in 1..uint(16) { for num_bytes in 1..=uint(16) {
for _ in 0..RANDOM_TESTS { for _ in 0..=RANDOM_TESTS {
unsigned, signed := get_random(num_bytes) unsigned, signed := get_random(num_bytes)
{ {
@@ -109,7 +109,7 @@ test_leb128 :: proc(t: ^testing.T) {
get_random :: proc(byte_count: uint) -> (u: u128, i: i128) { get_random :: proc(byte_count: uint) -> (u: u128, i: i128) {
assert(byte_count >= 0 && byte_count <= size_of(u128)) assert(byte_count >= 0 && byte_count <= size_of(u128))
for _ in 1..byte_count { for _ in 1..=byte_count {
u <<= 8 u <<= 8
u |= u128(rand.uint32() & 0xff) u |= u128(rand.uint32() & 0xff)
} }
+1 -1
View File
@@ -281,7 +281,7 @@ doc_to_string :: proc(doc: ^xml.Document) -> (result: string) {
} }
buf: strings.Builder buf: strings.Builder
defer strings.destroy_builder(&buf) defer strings.builder_destroy(&buf)
print(strings.to_writer(&buf), doc) print(strings.to_writer(&buf), doc)
return strings.clone(strings.to_string(buf)) return strings.clone(strings.to_string(buf))
+1
View File
@@ -5,6 +5,7 @@ package odin_gl
import "core:os" import "core:os"
import "core:fmt" import "core:fmt"
import "core:strings" import "core:strings"
_ :: fmt
Shader_Type :: enum i32 { Shader_Type :: enum i32 {
NONE = 0x0000, NONE = 0x0000,
+44
View File
@@ -947,6 +947,13 @@ impl_DrawTransformFeedbackStream: proc "c" (mode: u32, id: u32, stream: u32)
impl_BeginQueryIndexed: proc "c" (target: u32, index: u32, id: u32) impl_BeginQueryIndexed: proc "c" (target: u32, index: u32, id: u32)
impl_EndQueryIndexed: proc "c" (target: u32, index: u32) impl_EndQueryIndexed: proc "c" (target: u32, index: u32)
impl_GetQueryIndexediv: proc "c" (target: u32, index: u32, pname: u32, params: [^]i32) impl_GetQueryIndexediv: proc "c" (target: u32, index: u32, pname: u32, params: [^]i32)
impl_GetTextureHandleARB: proc "c" (texture: u32) -> u64
impl_GetTextureSamplerHandleARB: proc "c" (texture, sampler: u32) -> u64
impl_GetImageHandleARB: proc "c" (texture: u32, level: i32, layered: bool, layer: i32, format: u32) -> u64
impl_MakeTextureHandleResidentARB: proc "c" (handle: u64)
impl_MakeImageHandleResidentARB: proc "c" (handle: u64, access: u32)
impl_MakeTextureHandleNonResidentARB:proc "c" (handle: u64)
impl_MakeImageHandleNonResidentARB: proc "c" (handle: u64)
load_4_0 :: proc(set_proc_address: Set_Proc_Address_Type) { load_4_0 :: proc(set_proc_address: Set_Proc_Address_Type) {
set_proc_address(&impl_MinSampleShading, "glMinSampleShading") set_proc_address(&impl_MinSampleShading, "glMinSampleShading")
@@ -995,6 +1002,42 @@ load_4_0 :: proc(set_proc_address: Set_Proc_Address_Type) {
set_proc_address(&impl_BeginQueryIndexed, "glBeginQueryIndexed") set_proc_address(&impl_BeginQueryIndexed, "glBeginQueryIndexed")
set_proc_address(&impl_EndQueryIndexed, "glEndQueryIndexed") set_proc_address(&impl_EndQueryIndexed, "glEndQueryIndexed")
set_proc_address(&impl_GetQueryIndexediv, "glGetQueryIndexediv") set_proc_address(&impl_GetQueryIndexediv, "glGetQueryIndexediv")
// Load ARB (architecture review board, vendor specific) extensions that might be available
set_proc_address(&impl_GetTextureHandleARB, "glGetTextureHandleARB")
if impl_GetTextureHandleARB == nil {
set_proc_address(&impl_GetTextureHandleARB, "glGetTextureHandleNV")
}
set_proc_address(&impl_GetTextureSamplerHandleARB, "glGetTextureSamplerHandleARB")
if impl_GetTextureSamplerHandleARB == nil {
set_proc_address(&impl_GetTextureSamplerHandleARB, "glGetTextureSamplerHandleNV")
}
set_proc_address(&impl_GetImageHandleARB, "glGetImageHandleARB")
if impl_GetImageHandleARB == nil {
set_proc_address(&impl_GetImageHandleARB, "glGetImageHandleNV")
}
set_proc_address(&impl_MakeTextureHandleResidentARB, "glMakeTextureHandleResidentARB")
if impl_MakeTextureHandleResidentARB == nil {
set_proc_address(&impl_MakeTextureHandleResidentARB, "glMakeTextureHandleResidentNV")
}
set_proc_address(&impl_MakeImageHandleResidentARB, "glMakeImageHandleResidentARB")
if impl_MakeImageHandleResidentARB == nil {
set_proc_address(&impl_MakeImageHandleResidentARB, "glMakeImageHandleResidentNV")
}
set_proc_address(&impl_MakeTextureHandleNonResidentARB, "glMakeTextureHandleNonResidentARB")
if impl_MakeTextureHandleNonResidentARB == nil {
set_proc_address(&impl_MakeTextureHandleNonResidentARB, "glMakeTextureHandleNonResidentNV")
}
set_proc_address(&impl_MakeImageHandleNonResidentARB, "glMakeImageHandleNonResidentARB")
if impl_MakeImageHandleNonResidentARB == nil {
set_proc_address(&impl_MakeImageHandleNonResidentARB, "glMakeImageHandleNonResidentNV")
}
} }
@@ -1594,3 +1637,4 @@ load_4_6 :: proc(set_proc_address: Set_Proc_Address_Type) {
set_proc_address(&impl_MultiDrawElementsIndirectCount, "glMultiDrawElementsIndirectCount") set_proc_address(&impl_MultiDrawElementsIndirectCount, "glMultiDrawElementsIndirectCount")
set_proc_address(&impl_PolygonOffsetClamp, "glPolygonOffsetClamp") set_proc_address(&impl_PolygonOffsetClamp, "glPolygonOffsetClamp")
} }
+30
View File
@@ -449,6 +449,20 @@ when !ODIN_DEBUG {
BeginQueryIndexed :: proc "c" (target: u32, index: u32, id: u32) { impl_BeginQueryIndexed(target, index, id) } BeginQueryIndexed :: proc "c" (target: u32, index: u32, id: u32) { impl_BeginQueryIndexed(target, index, id) }
EndQueryIndexed :: proc "c" (target: u32, index: u32) { impl_EndQueryIndexed(target, index) } EndQueryIndexed :: proc "c" (target: u32, index: u32) { impl_EndQueryIndexed(target, index) }
GetQueryIndexediv :: proc "c" (target: u32, index: u32, pname: u32, params: [^]i32) { impl_GetQueryIndexediv(target, index, pname, params) } GetQueryIndexediv :: proc "c" (target: u32, index: u32, pname: u32, params: [^]i32) { impl_GetQueryIndexediv(target, index, pname, params) }
GetTextureHandleARB :: proc "c" (texture: u32) -> u64
{ return impl_GetTextureHandleARB(texture) }
GetTextureSamplerHandleARB :: proc "c" (texture, sampler: u32) -> u64
{ return impl_GetTextureSamplerHandleARB(texture, sampler) }
GetImageHandleARB :: proc "c" (texture: u32, level: i32, layered: bool, layer: i32, format: u32) -> u64
{ return impl_GetImageHandleARB(texture, level, layered, layer, format) }
MakeTextureHandleResidentARB :: proc "c" (handle: u64)
{ impl_MakeTextureHandleResidentARB(handle) }
MakeImageHandleResidentARB :: proc "c" (handle: u64, access: u32)
{ impl_MakeImageHandleResidentARB(handle, access) }
MakeTextureHandleNonResidentARB:: proc "c" (handle: u64)
{ impl_MakeTextureHandleNonResidentARB(handle) }
MakeImageHandleNonResidentARB :: proc "c" (handle: u64)
{ impl_MakeImageHandleNonResidentARB(handle) }
// VERSION_4_1 // VERSION_4_1
ReleaseShaderCompiler :: proc "c" () { impl_ReleaseShaderCompiler() } ReleaseShaderCompiler :: proc "c" () { impl_ReleaseShaderCompiler() }
@@ -1249,6 +1263,22 @@ when !ODIN_DEBUG {
BeginQueryIndexed :: proc "c" (target: u32, index: u32, id: u32, loc := #caller_location) { impl_BeginQueryIndexed(target, index, id); debug_helper(loc, 0, target, index, id) } BeginQueryIndexed :: proc "c" (target: u32, index: u32, id: u32, loc := #caller_location) { impl_BeginQueryIndexed(target, index, id); debug_helper(loc, 0, target, index, id) }
EndQueryIndexed :: proc "c" (target: u32, index: u32, loc := #caller_location) { impl_EndQueryIndexed(target, index); debug_helper(loc, 0, target, index) } EndQueryIndexed :: proc "c" (target: u32, index: u32, loc := #caller_location) { impl_EndQueryIndexed(target, index); debug_helper(loc, 0, target, index) }
GetQueryIndexediv :: proc "c" (target: u32, index: u32, pname: u32, params: [^]i32, loc := #caller_location) { impl_GetQueryIndexediv(target, index, pname, params); debug_helper(loc, 0, target, index, pname, params) } GetQueryIndexediv :: proc "c" (target: u32, index: u32, pname: u32, params: [^]i32, loc := #caller_location) { impl_GetQueryIndexediv(target, index, pname, params); debug_helper(loc, 0, target, index, pname, params) }
GetTextureHandleARB :: proc "c" (target: u32, loc := #caller_location) -> u64
{ ret := impl_GetTextureHandleARB(target); debug_helper(loc, 0, target); return ret }
GetTextureSamplerHandleARB :: proc "c" (texture, sampler: u32, loc := #caller_location) -> u64
{ ret := impl_GetTextureSamplerHandleARB(texture, sampler); debug_helper(loc, 0, texture, sampler); return ret }
GetImageHandleARB :: proc "c" (texture: u32, level: i32, layered: bool, layer: i32, format: u32, loc := #caller_location) -> u64
{ ret := impl_GetImageHandleARB(texture, level, layered, layer, format); debug_helper(loc, 0, texture, level, layered, layer, format); return ret }
MakeTextureHandleResidentARB :: proc "c" (handle: u64, loc := #caller_location)
{ impl_MakeTextureHandleResidentARB(handle); debug_helper(loc, 0, handle) }
MakeImageHandleResidentARB :: proc "c" (handle: u64, access: u32, loc := #caller_location)
{ impl_MakeImageHandleResidentARB(handle, access); debug_helper(loc, 0, handle, access) }
MakeTextureHandleNonResidentARB:: proc "c" (handle: u64, loc := #caller_location)
{ impl_MakeTextureHandleNonResidentARB(handle); debug_helper(loc, 0, handle) }
MakeImageHandleNonResidentARB :: proc "c" (handle: u64, loc := #caller_location)
{ impl_MakeImageHandleNonResidentARB(handle); debug_helper(loc, 0, handle) }
// VERSION_4_1 // VERSION_4_1
ReleaseShaderCompiler :: proc "c" (loc := #caller_location) { impl_ReleaseShaderCompiler(); debug_helper(loc, 0) } ReleaseShaderCompiler :: proc "c" (loc := #caller_location) { impl_ReleaseShaderCompiler(); debug_helper(loc, 0) }
+4 -4
View File
@@ -38,10 +38,10 @@ IUnknown_VTable :: struct {
@(default_calling_convention="stdcall") @(default_calling_convention="stdcall")
foreign dxgi { foreign dxgi {
CreateDXGIFactory :: proc(riid: ^IID, ppFactory: rawptr) -> HRESULT --- CreateDXGIFactory :: proc(riid: ^IID, ppFactory: ^rawptr) -> HRESULT ---
CreateDXGIFactory1 :: proc(riid: ^IID, ppFactory: rawptr) -> HRESULT --- CreateDXGIFactory1 :: proc(riid: ^IID, ppFactory: ^rawptr) -> HRESULT ---
CreateDXGIFactory2 :: proc(Flags: u32, riid: ^IID, ppFactory: rawptr) -> HRESULT --- CreateDXGIFactory2 :: proc(Flags: u32, riid: ^IID, ppFactory: ^rawptr) -> HRESULT ---
DXGIGetDebugInterface1 :: proc(Flags: u32, riid: ^IID, pDebug: rawptr) -> HRESULT --- DXGIGetDebugInterface1 :: proc(Flags: u32, riid: ^IID, pDebug: ^rawptr) -> HRESULT ---
} }
STANDARD_MULTISAMPLE_QUALITY_PATTERN :: 0xffffffff STANDARD_MULTISAMPLE_QUALITY_PATTERN :: 0xffffffff
+7
View File
@@ -13,6 +13,13 @@ when ODIN_OS == .Windows {
} else when ODIN_OS == .Linux { } else when ODIN_OS == .Linux {
// TODO: Add the billion-or-so static libs to link to in linux // TODO: Add the billion-or-so static libs to link to in linux
foreign import glfw "system:glfw" foreign import glfw "system:glfw"
} else when ODIN_OS == .Darwin {
foreign import glfw {
"../lib/darwin/libglfw3.a",
"system:Cocoa.framework",
"system:IOKit.framework",
"system:OpenGL.framework",
}
} else { } else {
foreign import glfw "system:glfw" foreign import glfw "system:glfw"
} }
+1 -1
View File
@@ -4,7 +4,7 @@ package glfw
/* Versions */ /* Versions */
VERSION_MAJOR :: 3 VERSION_MAJOR :: 3
VERSION_MINOR :: 3 VERSION_MINOR :: 3
VERSION_REVISION :: 4 VERSION_REVISION :: 8
/* Booleans */ /* Booleans */
TRUE :: true TRUE :: true
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+1 -1
View File
@@ -353,7 +353,7 @@ end :: proc(ctx: ^Context) {
/* reset input state */ /* reset input state */
ctx.key_pressed_bits = {} // clear ctx.key_pressed_bits = {} // clear
strings.reset_builder(&ctx.text_input) strings.builder_reset(&ctx.text_input)
ctx.mouse_pressed_bits = {} // clear ctx.mouse_pressed_bits = {} // clear
ctx.mouse_released_bits = {} // clear ctx.mouse_released_bits = {} // clear
ctx.scroll_delta = Vec2{0, 0} ctx.scroll_delta = Vec2{0, 0}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+14 -5
View File
@@ -106,11 +106,20 @@ when ODIN_OS == .Windows {
"system:pthread", "system:pthread",
} }
} else when ODIN_OS == .Darwin { } else when ODIN_OS == .Darwin {
foreign import lib { when ODIN_ARCH == .arm64 {
"macos/libraylib.a", foreign import lib {
"system:Cocoa.framework", "macos-arm64/libraylib.a",
"system:OpenGL.framework", "system:Cocoa.framework",
"system:IOKit.framework", "system:OpenGL.framework",
"system:IOKit.framework",
}
} else {
foreign import lib {
"macos/libraylib.a",
"system:Cocoa.framework",
"system:OpenGL.framework",
"system:IOKit.framework",
}
} }
} else { } else {
foreign import lib "system:raylib" foreign import lib "system:raylib"
+1 -1
View File
@@ -185,4 +185,4 @@ foreign lib {
space: colorspace, alloc_context: rawptr, space: colorspace, alloc_context: rawptr,
s0, t0, s1, t1: f32) -> c.int --- s0, t0, s1, t1: f32) -> c.int ---
} }
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+2 -2
View File
@@ -10,6 +10,6 @@ The `js_wasm32` target assumes that the WASM output will be ran within a web bro
<!-- Copy `vendor:wasm/js/runtime.js` into your web server --> <!-- Copy `vendor:wasm/js/runtime.js` into your web server -->
<script type="text/javascript" src="runtime.js"></script> <script type="text/javascript" src="runtime.js"></script>
<script type="text/javascript"> <script type="text/javascript">
odin.runWasm(pathToWasm, webglCanvasElement, consolePreElement); odin.runWasm(pathToWasm, consolePreElement);
</script> </script>
``` ```
+30 -3
View File
@@ -79,6 +79,8 @@ Event_Kind :: enum u32 {
Context_Menu, Context_Menu,
Custom,
} }
event_kind_string := [Event_Kind]string{ event_kind_string := [Event_Kind]string{
.Invalid = "", .Invalid = "",
@@ -155,6 +157,8 @@ event_kind_string := [Event_Kind]string{
.Touch_Start = "touchstart", .Touch_Start = "touchstart",
.Context_Menu = "contextmenu", .Context_Menu = "contextmenu",
.Custom = "?custom?",
} }
Delta_Mode :: enum u32 { Delta_Mode :: enum u32 {
@@ -186,6 +190,13 @@ Event_Phase :: enum u8 {
Bubbling_Phase = 3, Bubbling_Phase = 3,
} }
Event_Option :: enum u8 {
Bubbles = 0,
Cancelable = 1,
Composed = 2,
}
Event_Options :: distinct bit_set[Event_Option; u8]
Event :: struct { Event :: struct {
kind: Event_Kind, kind: Event_Kind,
target_kind: Event_Target_Kind, target_kind: Event_Target_Kind,
@@ -194,9 +205,7 @@ Event :: struct {
timestamp: f64, timestamp: f64,
phase: Event_Phase, phase: Event_Phase,
bubbles: bool, options: Event_Options,
cancelable: bool,
composed: bool,
is_composing: bool, is_composing: bool,
is_trusted: bool, is_trusted: bool,
@@ -255,6 +264,7 @@ foreign dom_lib {
event_stop_propagation :: proc() --- event_stop_propagation :: proc() ---
event_stop_immediate_propagation :: proc() --- event_stop_immediate_propagation :: proc() ---
event_prevent_default :: proc() --- event_prevent_default :: proc() ---
dispatch_custom_event :: proc(id: string, name: string, options := Event_Options{}) -> bool ---
} }
add_event_listener :: proc(id: string, kind: Event_Kind, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool { add_event_listener :: proc(id: string, kind: Event_Kind, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool {
@@ -301,6 +311,23 @@ remove_event_listener_from_event :: proc(e: Event) -> bool {
return remove_event_listener(e.id, e.kind, e.user_data, e.callback) return remove_event_listener(e.id, e.kind, e.user_data, e.callback)
} }
add_custom_event_listener :: proc(id: string, name: string, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool {
@(default_calling_convention="contextless")
foreign dom_lib {
@(link_name="add_event_listener")
_add_event_listener :: proc(id: string, name: string, name_code: Event_Kind, user_data: rawptr, callback: proc "odin" (Event), use_capture: bool) -> bool ---
}
return _add_event_listener(id, name, .Custom, user_data, callback, use_capture)
}
remove_custom_event_listener :: proc(id: string, name: string, user_data: rawptr, callback: proc(e: Event)) -> bool {
@(default_calling_convention="contextless")
foreign dom_lib {
@(link_name="remove_event_listener")
_remove_event_listener :: proc(id: string, name: string, user_data: rawptr, callback: proc "odin" (Event)) -> bool ---
}
return _remove_event_listener(id, name, user_data, callback)
}
+41 -14
View File
@@ -1,6 +1,14 @@
"use strict"; "use strict";
(function() { (function() {
function getElement(name) {
if (name) {
return document.getElementById(name);
}
return undefined;
}
class WasmMemoryInterface { class WasmMemoryInterface {
constructor() { constructor() {
this.memory = null; this.memory = null;
@@ -204,12 +212,12 @@ class WebGLInterface {
return { return {
SetCurrentContextById: (name_ptr, name_len) => { SetCurrentContextById: (name_ptr, name_len) => {
let name = this.mem.loadString(name_ptr, name_len); let name = this.mem.loadString(name_ptr, name_len);
let element = document.getElementById(name); let element = getElement(name);
return this.setCurrentContext(element, {alpha: true, antialias: true, depth: true, premultipliedAlpha: true}); return this.setCurrentContext(element, {alpha: true, antialias: true, depth: true, premultipliedAlpha: true});
}, },
CreateCurrentContextById: (name_ptr, name_len, attributes) => { CreateCurrentContextById: (name_ptr, name_len, attributes) => {
let name = this.mem.loadString(name_ptr, name_len); let name = this.mem.loadString(name_ptr, name_len);
let element = document.getElementById(name); let element = getElement(name);
let contextSettings = { let contextSettings = {
alpha: !(attributes & (1<<0)), alpha: !(attributes & (1<<0)),
@@ -1380,9 +1388,11 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
wmi.storeF64(off(8), e.timeStamp*1e-3); wmi.storeF64(off(8), e.timeStamp*1e-3);
wmi.storeU8(off(1), e.eventPhase); wmi.storeU8(off(1), e.eventPhase);
wmi.storeU8(off(1), !!e.bubbles); let options = 0;
wmi.storeU8(off(1), !!e.cancelable); if (!!e.bubbles) { options |= 1<<0; }
wmi.storeU8(off(1), !!e.composed); if (!!e.cancelable) { options |= 1<<1; }
if (!!e.composed) { options |= 1<<2; }
wmi.storeU8(off(1), options);
wmi.storeU8(off(1), !!e.isComposing); wmi.storeU8(off(1), !!e.isComposing);
wmi.storeU8(off(1), !!e.isTrusted); wmi.storeU8(off(1), !!e.isTrusted);
@@ -1433,7 +1443,7 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
add_event_listener: (id_ptr, id_len, name_ptr, name_len, name_code, data, callback, use_capture) => { add_event_listener: (id_ptr, id_len, name_ptr, name_len, name_code, data, callback, use_capture) => {
let id = wasmMemoryInterface.loadString(id_ptr, id_len); let id = wasmMemoryInterface.loadString(id_ptr, id_len);
let name = wasmMemoryInterface.loadString(name_ptr, name_len); let name = wasmMemoryInterface.loadString(name_ptr, name_len);
let element = document.getElementById(id); let element = getElement(id);
if (element == undefined) { if (element == undefined) {
return false; return false;
} }
@@ -1454,7 +1464,7 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
remove_event_listener: (id_ptr, id_len, name_ptr, name_len, data, callback) => { remove_event_listener: (id_ptr, id_len, name_ptr, name_len, data, callback) => {
let id = wasmMemoryInterface.loadString(id_ptr, id_len); let id = wasmMemoryInterface.loadString(id_ptr, id_len);
let name = wasmMemoryInterface.loadString(name_ptr, name_len); let name = wasmMemoryInterface.loadString(name_ptr, name_len);
let element = document.getElementById(id); let element = getElement(id);
if (element == undefined) { if (element == undefined) {
return false; return false;
} }
@@ -1514,14 +1524,31 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
} }
}, },
dispatch_custom_event: (id_ptr, id_len, name_ptr, name_len, options_bits) => {
let id = wasmMemoryInterface.loadString(id_ptr, id_len);
let name = wasmMemoryInterface.loadString(name_ptr, name_len);
let options = {
bubbles: (options_bits & (1<<0)) !== 0,
cancelabe: (options_bits & (1<<1)) !== 0,
composed: (options_bits & (1<<2)) !== 0,
};
let element = getElement(id);
if (element) {
element.dispatchEvent(new Event(name, options));
return true;
}
return false;
},
get_element_value_f64: (id_ptr, id_len) => { get_element_value_f64: (id_ptr, id_len) => {
let id = wasmMemoryInterface.loadString(id_ptr, id_len); let id = wasmMemoryInterface.loadString(id_ptr, id_len);
let element = document.getElementById(id); let element = getElement(id);
return element ? element.value : 0; return element ? element.value : 0;
}, },
get_element_value_string: (id_ptr, id_len, buf_ptr, buf_len) => { get_element_value_string: (id_ptr, id_len, buf_ptr, buf_len) => {
let id = wasmMemoryInterface.loadString(id_ptr, id_len); let id = wasmMemoryInterface.loadString(id_ptr, id_len);
let element = document.getElementById(id); let element = getElement(id);
if (element) { if (element) {
let str = element.value; let str = element.value;
if (buf_len > 0 && buf_ptr) { if (buf_len > 0 && buf_ptr) {
@@ -1535,7 +1562,7 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
}, },
get_element_value_string_length: (id_ptr, id_len) => { get_element_value_string_length: (id_ptr, id_len) => {
let id = wasmMemoryInterface.loadString(id_ptr, id_len); let id = wasmMemoryInterface.loadString(id_ptr, id_len);
let element = document.getElementById(id); let element = getElement(id);
if (element) { if (element) {
return element.value.length; return element.value.length;
} }
@@ -1543,7 +1570,7 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
}, },
get_element_min_max: (ptr_array2_f64, id_ptr, id_len) => { get_element_min_max: (ptr_array2_f64, id_ptr, id_len) => {
let id = wasmMemoryInterface.loadString(id_ptr, id_len); let id = wasmMemoryInterface.loadString(id_ptr, id_len);
let element = document.getElementById(id); let element = getElement(id);
if (element) { if (element) {
let values = wasmMemoryInterface.loadF64Array(ptr_array2_f64, 2); let values = wasmMemoryInterface.loadF64Array(ptr_array2_f64, 2);
values[0] = element.min; values[0] = element.min;
@@ -1552,7 +1579,7 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
}, },
set_element_value_f64: (id_ptr, id_len, value) => { set_element_value_f64: (id_ptr, id_len, value) => {
let id = wasmMemoryInterface.loadString(id_ptr, id_len); let id = wasmMemoryInterface.loadString(id_ptr, id_len);
let element = document.getElementById(id); let element = getElement(id);
if (element) { if (element) {
element.value = value; element.value = value;
} }
@@ -1560,7 +1587,7 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
set_element_value_string: (id_ptr, id_len, value_ptr, value_id) => { set_element_value_string: (id_ptr, id_len, value_ptr, value_id) => {
let id = wasmMemoryInterface.loadString(id_ptr, id_len); let id = wasmMemoryInterface.loadString(id_ptr, id_len);
let value = wasmMemoryInterface.loadString(value_ptr, value_len); let value = wasmMemoryInterface.loadString(value_ptr, value_len);
let element = document.getElementById(id); let element = getElement(id);
if (element) { if (element) {
element.value = value; element.value = value;
} }
@@ -1569,7 +1596,7 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
get_bounding_client_rect: (rect_ptr, id_ptr, id_len) => { get_bounding_client_rect: (rect_ptr, id_ptr, id_len) => {
let id = wasmMemoryInterface.loadString(id_ptr, id_len); let id = wasmMemoryInterface.loadString(id_ptr, id_len);
let element = document.getElementById(id); let element = getElement(id);
if (element) { if (element) {
let values = wasmMemoryInterface.loadF64Array(rect_ptr, 4); let values = wasmMemoryInterface.loadF64Array(rect_ptr, 4);
let rect = element.getBoundingClientRect(); let rect = element.getBoundingClientRect();