Compare commits

...

129 Commits

Author SHA1 Message Date
gingerBill ef5eb4b612 A docs.odin explaining what are the required entities in core:runtime by the compiler 2023-11-01 13:59:39 +00:00
gingerBill 864b29f7f1 Add missing calls 2023-11-01 13:57:20 +00:00
Jeroen van Rijn 4d498b668a Merge pull request #2910 from laytan/fix-empty-pass-because-trailing-comma
Fix empty pass because of trailing comma
2023-11-01 12:11:37 +01:00
Jeroen van Rijn 62d0b0ae72 Merge pull request #2911 from flysand7/sys-unix-net-fix
sys/linux: Fix EFAULT on recvfrom
2023-11-01 00:14:23 +01:00
flysand7 2c9ef2e1bc sys/linux: Fix EFAULT on recvfrom 2023-11-01 10:06:30 +11:00
Laytan 9b68671082 Fix empty pass because of trailing comma 2023-10-31 19:29:54 +01:00
gingerBill 03ab6add5c Merge pull request #2897 from jcmdln/editorconfig
editorconfig: Use 2-column spaces in YAML
2023-10-31 12:45:22 +00:00
gingerBill 052633b73c Merge pull request #2876 from flysand7/new-sys-unix
sys/unix implementation
2023-10-31 12:43:28 +00:00
gingerBill bf9a8032a1 Merge pull request #2906 from karl-zylinski/slice-clone-loc
Added loc := #caller_location to slice.clone and slice.clone_to_dynamic
2023-10-31 12:26:03 +00:00
gingerBill eb261f5b28 Merge branch 'master' into new-sys-unix 2023-10-31 12:16:25 +00:00
Jeroen van Rijn f5febb633c Temporarily disable RTTI test on Windows. 2023-10-31 13:12:17 +01:00
Karl Zylinski d2ac3c2228 Make slice.clone and slice.clone_to_dynamic take a loc parameter 2023-10-30 21:19:21 +01:00
gingerBill 51caa930ca Merge pull request #2905 from odin-lang/llvm-17-custom-passes
Explicit Optimization Passes for LLVM-17 Passes
2023-10-30 15:00:55 +00:00
gingerBill b7af4e7f6b Explicitly write out the passes for each level and remove certain passes 2023-10-30 12:31:24 +00:00
Jeroen van Rijn 82cd30a145 Add test for RTTI 2023-10-30 13:06:45 +01:00
Jeroen van Rijn 8caae16113 Merge pull request #2902 from flysand7/vendor-darwin
Only build vendor:darwin on darwin
2023-10-30 10:12:36 +01:00
Jeroen van Rijn dc789c43b6 Merge pull request #2904 from AquaGeneral/master
Fixed typo "fot" and clarified slashpath.ext
2023-10-30 10:12:19 +01:00
Jeroen van Rijn 2e73fb25af Merge pull request #2903 from flysand7/i386-syscall-asm-fix
Fix-up inline asm for i386 syscalls emit
2023-10-30 10:07:56 +01:00
flysand7 1577d60d02 move darwin-specific packages in all_vendor_darwin.odin 2023-10-30 20:05:58 +11:00
Jesse Stiller 3bd1918c5e Fixed typo "fot" and clarified slashpath.ext 2023-10-30 11:57:44 +10:00
flysand7 263b3141b5 Merge branch 'master' into vendor-darwin 2023-10-30 10:32:47 +11:00
flysand7 82263a8b38 Merge branch 'master' into i386-syscall-asm-fix 2023-10-30 10:32:11 +11:00
gingerBill 61ad2a1345 TEST: Add sroa passes back 2023-10-29 20:45:19 +00:00
gingerBill d589914956 Ignore store undef calls 2023-10-29 20:43:02 +00:00
gingerBill f54a026acc Remove trailing comma 2023-10-29 20:33:29 +00:00
gingerBill fc06d7011d Use default passes without coro, openmp, and sroa passes 2023-10-29 20:31:53 +00:00
gingerBill ed7c9ec619 Test: use custom passes for -o:speed 2023-10-29 20:13:03 +00:00
gingerBill 1d9f6346d4 Force dynamic map calls on non-windows targets 2023-10-29 17:23:24 +00:00
flysand7 a3a3156ddd Fix-up inline asm for i386 syscalls emit 2023-10-30 02:03:35 +11:00
flysand7 70bd4a5ab6 Only build vendor:darwin on darwin 2023-10-29 15:03:48 +11:00
gingerBill 034aead930 Only make static map get calls inlineable outside of debug builds 2023-10-27 14:55:54 +01:00
gingerBill c8a5bafc6b Fix static map calls and default to them! 2023-10-27 14:53:48 +01:00
gingerBill 0a7b9338f6 Merge branch 'master' of https://github.com/odin-lang/Odin 2023-10-27 13:03:28 +01:00
gingerBill bc0fa1240b Disable using giant packed struct for type info table for the time being 2023-10-27 13:03:21 +01:00
Jeroen van Rijn 292398dbe2 Merge pull request #2896 from thetarnav/js-rand
Add system_random and random_bytes for js target
2023-10-27 12:52:27 +02:00
Damian Tarnawski 49da19e013 Replace Math.random with crypto.getRandomValues for _system_number 2023-10-27 12:06:35 +02:00
flysand7 bbd4c1054e convert spaces to tabs 2023-10-27 11:30:13 +11:00
jcmdln 152ac61faf editorconfig: Use 2-column spaces in YAML 2023-10-26 20:18:48 -04:00
flysand7 4d65b1ab9c Implement new sys/unix package 2023-10-27 10:51:21 +11:00
Damian Tarnawski 8b2f62000a Use wasmMemoryInterface for rand_bytes 2023-10-27 00:50:29 +02:00
Damian Tarnawski 166803a2a5 Rename rand to rand_f64 2023-10-27 00:18:41 +02:00
Damian Tarnawski 11a2b2a942 Add system_random and random_bytes for js target 2023-10-27 00:05:38 +02:00
gingerBill 0a492acaa1 Merge pull request #2891 from flysand7/glfw-fixes
GLFW binding fixes
2023-10-26 15:22:16 +01:00
gingerBill e86d7f1fb0 Merge pull request #2895 from jakubtomsu/fix-builtin-const-int-checks
Fix incorrect type condition in some built-in procs
2023-10-26 15:21:47 +01:00
Jeroen van Rijn 962d599996 Fix reading from /sys/ pseudo fx 2023-10-26 14:30:04 +02:00
jakubtomsu ba536d67b4 Change and to or 2023-10-25 22:17:38 +02:00
gingerBill 8e4bdcfb98 Remove disabled attribute from unimplemented 2023-10-25 11:41:24 +01:00
gingerBill f3f0ab6e2c On -disable-assert, panic will still work but not print the caller location 2023-10-25 11:34:09 +01:00
gingerBill 5a771732bd Merge pull request #2888 from thetarnav/wasm-i64
Correct loadI64 and storeI64 methods in runtime.js
2023-10-24 11:45:08 +01:00
gingerBill 9b6647a019 Merge pull request #2886 from flysand7/linux-no-crt
Allow no CRT linking on Linux
2023-10-24 11:32:23 +01:00
flysand7 7e40a5a711 Change bool to b32 2023-10-24 10:28:11 +11:00
flysand7 27cbd0d931 GLFW binding fixes 2023-10-24 10:23:38 +11:00
Jeroen van Rijn 12c316cd6b Merge pull request #2889 from jakubtomsu/fix-simd-bit-and-not-typo
Fix bit_* calls in `core:simd/x86`
2023-10-22 22:24:28 +02:00
jakubtomsu b06583133a Fix the other bit_* intrinsic calls 2023-10-22 20:59:19 +02:00
jakubtomsu a2e6fc5909 change and_not to bit_and_not 2023-10-22 20:52:35 +02:00
Damian Tarnawski 058065ce75 Correct loadI64 and storeI64 methods in runtime.js 2023-10-22 18:54:52 +02:00
Jeroen van Rijn 75a2015260 Add clear_soa (for #soa[dynamic]T) 2023-10-22 13:21:22 +02:00
Jeroen van Rijn 18776aa6b9 Merge pull request #2887 from SentientCoffee/map-shrink-return-values
Fix a `shrink(map[T]U)` bug in the core lib
2023-10-21 20:17:35 +02:00
Daniel 4cf48daa75 Fix a shrink(map[T]U) bug in the core lib
Fixed this error from `core:runtime`:
```odin
odin/core/runtime/core_builtin.odin(387:3) Error: Expected 2 return values, got 1 (Allocator_Error)
        return map_shrink_dynamic((^Raw_Map)(m), map_info(T), loc)
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
```
2023-10-21 13:27:56 -04:00
flysand7 361aeac0cc remove binary 2023-10-22 01:59:04 +11:00
flysand7 2e66d621b5 Implement -no-crt entry point on linux 2023-10-22 01:58:35 +11:00
Jeroen van Rijn 566a11a585 Merge pull request #2884 from flysand7/editor-config
Editor config
2023-10-20 15:46:14 +02:00
flysand7 abb9fb3345 wildcard editorconfig 2023-10-21 00:32:08 +11:00
flysand7 05a9652f76 convert procs_windows_amd64.asm to tabs 2023-10-20 23:31:09 +11:00
flysand7 ba5df8edca add .editorconfig 2023-10-20 23:30:00 +11:00
gingerBill 9afee7e8d2 Merge pull request #2883 from flysand7/chkstk
Implement stack probing on windows.
2023-10-20 11:32:22 +01:00
flysand7 c458186f68 Implement __chkstk 2023-10-20 21:12:49 +11:00
Jeroen van Rijn f9da0a59e4 Merge pull request #2882 from thetarnav/js-time
Fix calling `time.now()` in wasm js runtime
2023-10-19 19:23:18 +02:00
Damian Tarnawski c19af95db0 Fix calling time.now() in wasm js runtime 2023-10-19 18:45:04 +02:00
Jeroen van Rijn 840459bdb0 Merge pull request #2879 from jcmdln/license-audit
Ensure required licenses are in distributable bundles
2023-10-19 00:45:01 +02:00
jcmdln 798660c007 Ensure required licenses are in distributable bundles 2023-10-18 17:20:12 -04:00
Jeroen van Rijn c039977048 Merge pull request #2878 from laytan/remove-build-artifacts
remove build artifacts
2023-10-18 18:47:48 +02:00
Laytan 7a9737b3d4 remove build artifacts 2023-10-18 18:31:07 +02:00
Jeroen van Rijn 0f5d562625 Merge pull request #2873 from jcmdln/fix-linux-releases
Linux: Copy and link against libLLVM*.so to fix releases
2023-10-17 02:27:06 +02:00
jcmdln 21f9e7f5e5 Fix Linux release pipeline which expects to bundle libLLVM*.so 2023-10-16 16:33:26 -04:00
gingerBill 6ee7b05b27 Merge pull request #2850 from jcmdln/linux-llvm-17
Support LLVM >=17.0.1 on Darwin and Linux
2023-10-16 16:15:59 +01:00
gingerBill e4c7e9903e Merge pull request #2841 from Ldash4/upstream/fix-enet-bindings
Make enet packet flags use bitset
2023-10-16 11:37:39 +01:00
gingerBill a96100d875 Merge pull request #2864 from flysand7/vendor-shared-fix
Allow for shared object linking of vendor libraries
2023-10-16 11:37:19 +01:00
gingerBill 10c67051f2 Merge pull request #2870 from reluctant-git-user/patch-1
Update stdio.odin
2023-10-16 11:34:11 +01:00
gingerBill a3fbd09ef9 Merge pull request #2871 from reluctant-git-user/master
Update microui.odin; slider 'step' parameter was not working
2023-10-16 11:33:51 +01:00
jcmdln 51248270e1 Remove [[ for POSIX shell support 2023-10-15 12:18:51 -04:00
jcmdln 8fe431e53e Only check LLVM_VERSION_MAJOR >= 17 for PassBuilder inclusion 2023-10-15 12:03:56 -04:00
reluctant-git-user 61a7d88490 Update microui.odin; slider 'step' parameter was not working 2023-10-15 17:36:15 +03:00
reluctant-git-user 496765c043 Update stdio.odin
snprintf() prototype fix
2023-10-15 17:09:41 +03:00
Jeroen van Rijn a62039882e Merge pull request #2867 from flysand7/linux-asm
Implement foreign asm (x86) imports for linux and osx
2023-10-15 12:53:32 +02:00
flysand7 a2a05e40e6 implemented foreign asm imports on linux/osx 2023-10-15 21:25:55 +11:00
gingerBill 45d08ea992 Merge pull request #2861 from seventh-chord/master
llvm: specify calling convention on call
2023-10-15 11:24:42 +01:00
gingerBill c9c7aa2e90 Merge pull request #2838 from GoNZooo/gonz.return-out-of-memory-in-json-parse
fix(json): return `.Out_Of_Memory` when out of memory on parse
2023-10-15 11:23:34 +01:00
jcmdln d0037fcf6b Allow running in POSIX shells 2023-10-14 22:01:38 -04:00
jcmdln b25fba6175 Fix typo in GIT_SHA collection 2023-10-14 18:10:42 -04:00
jcmdln afcdbf1ba6 Don't implicitly try 'llvm-config-14', try fallback or set LLVM_CONFIG; Restore FreeBSD llvm-config discovery 2023-10-14 18:07:20 -04:00
jcmdln 8eff75a484 Hoist GIT_SHA discovery 2023-10-14 17:51:28 -04:00
jcmdln e232cabfab Remove extra newlines 2023-10-14 17:46:34 -04:00
jcmdln e5ed388191 Ensure user defined LLVM_CONFIG is respected 2023-10-14 17:45:27 -04:00
jcmdln c0ac3de272 Hunt for supported 'llvm-config' executable 2023-10-14 17:41:19 -04:00
jcmdln abde9a99c3 Fix typos in references to OS_ARCH, OS_NAME 2023-10-14 17:32:41 -04:00
jcmdln bdc74a03c0 Refactor to improve handling of LLVM_VERSION checks 2023-10-14 16:58:34 -04:00
gingerBill 2783461e69 Merge pull request #2847 from thetarnav/js-runtime-patch
Update wasm `runtime.js`
2023-10-14 19:58:28 +01:00
flysand7 0f9c75dc08 Fix miniaudio config; add trailing commas 2023-10-14 21:47:38 +11:00
flysand7 cf937c6341 add 'shared' config to vendor libraries 2023-10-14 21:21:34 +11:00
flysand7 77210ffa56 rename dynamic to shared 2023-10-14 20:26:34 +11:00
Morten Hauke Solvang fb5bb1cd83 llvm: specify calling convention on call
Looks like the compiler only was specifying the calling convention on
function declarations, but not on function calls.
But LLVM seems to produce "bad" code when optimizing with level -O2
unless you specify the same calling convention on the call too.
2023-10-13 21:21:54 +02:00
gingerBill 23c4615f5e Disallow direct return a compound literal of a slice with elements 2023-10-13 12:19:48 +01:00
jcmdln fa2b68dac6 Fix MAX_LLVM_VERSION panic messages 2023-10-12 01:47:51 -04:00
jcmdln bd86cb22e0 Support LLVM >=17.0.1 on Darwin and Linux 2023-10-11 21:06:42 -04:00
gingerBill ec2635131b Merge pull request #2853 from RehkitzDev/master
added webgl GetParameter
2023-10-10 16:03:06 +01:00
gingerBill 6b3cfdfb2b Merge pull request #2856 from fabiansperber/fix-odin-parser-or_branch
core/odin Add `or_break` and `or_continue` semicolon handling
2023-10-10 16:02:56 +01:00
Fabian Sperber bce66e3b42 Add or_break and or_continue to the list of tokens that have an automatic semicolon added at the end of the line 2023-10-09 21:48:04 +02:00
gingerBill cffa035c1b Add ERROR_BLOCK() to check_unique_package_names 2023-10-09 13:36:15 +01:00
Rehkitzdev 1097192554 added webgl GetParameter 2023-10-08 04:02:55 +02:00
Jeroen van Rijn 0c10b951a9 Merge pull request #2833 from simonwashere/darwin_net_interface
darwin  enumerate_interfaces
2023-10-07 15:47:21 +02:00
Damian Tarnawski ab2907cd51 Correct stripNewline function 2023-10-06 20:11:25 +02:00
Damian Tarnawski ea8d3d4531 Define stripNewline function 2023-10-06 20:06:43 +02:00
Damian Tarnawski 256e4a0081 Don't pass true for littleEndian where it's not needed. 2023-10-06 20:03:26 +02:00
simon e7adfff9bf bugfix: darwin net flags 2023-10-06 16:41:13 +01:00
Damian Tarnawski 721c9e2c97 Fix typo 2023-10-06 17:26:39 +02:00
Damian Tarnawski 42c7e39c99 Update wasm runtime.js
- polyfill `Math.ldexp` method
- pass Math mathods streight through to exports object
  (they don't use `this`)
- Don't pass `"utf-8"` encodings to `TextEncoder` and `TextDecoder`
  (encoder doesn't take params and decoder has utf-8 as default)
2023-10-06 17:18:31 +02:00
gingerBill 96778c69bc Merge pull request #2836 from jakubtomsu/fix-zero-length-enum-array
Allow zero-length enum array (to stay consistent with `[0]T`)
2023-10-06 15:06:40 +01:00
L4 4adcc403c2 Make enet packet flags use bitset 2023-10-02 22:32:22 +02:00
Rickard Andersson 931e0d4687 cleanup: remove unused import 2023-10-02 15:21:09 +03:00
Rickard Andersson 2e3224a138 testing: add test for Out_Of_Memory return 2023-10-02 15:17:06 +03:00
Rickard Andersson cfa3765d50 fix: guard against empty key value in parse_object_body 2023-10-02 15:10:12 +03:00
Rickard Andersson 11e884aec5 docs: add note about checking for alloc error 2023-10-02 12:20:18 +03:00
Rickard Andersson 55a1ba710b fix: use runtime.map_insert to not overallocate 2023-10-02 11:59:37 +03:00
Rickard Andersson 0a8b266c71 fix(json): return .Out_Of_Memory when out of memory on parse
Previously this would silently simply not do anything and the object
would be empty/incomplete when parsed instead.
2023-10-02 11:50:16 +03:00
jakubtomsu 394c12f68d Remove unnecessary check zero fields check 2023-10-01 13:13:09 +02:00
jakubtomsu 1a57ad233d Fix field count in enumerated array type info 2023-10-01 13:09:08 +02:00
jakubtomsu c268463413 Allow zero-length enumerated arrays 2023-10-01 12:21:44 +02:00
simon 98f9f7d42e darwin _enumerate_interfaces 2023-09-30 20:09:29 +01:00
135 changed files with 8547 additions and 1179 deletions
+10
View File
@@ -0,0 +1,10 @@
root = true
[*]
indent_style = tab
end_of_line = lf
[*.y{,a}ml]
indent_size = 2
indent_style = space
tab_width = 2
+3
View File
@@ -26,6 +26,7 @@ jobs:
rm bin/llvm/windows/LLVM-C.lib
mkdir dist
cp odin.exe dist
cp LICENSE dist
cp LLVM-C.dll dist
cp -r shared dist
cp -r core dist
@@ -52,6 +53,7 @@ jobs:
run: |
mkdir dist
cp odin dist
cp LICENSE dist
cp libLLVM* dist
cp -r shared dist
cp -r core dist
@@ -81,6 +83,7 @@ jobs:
run: |
mkdir dist
cp odin dist
cp LICENSE dist
cp -r shared dist
cp -r core dist
cp -r vendor dist
+2
View File
@@ -24,6 +24,8 @@ bld/
![Cc]ore/[Ll]og/
tests/documentation/verify/
tests/documentation/all.odin-doc
tests/internal/test_map
tests/internal/test_rtti
# Visual Studio 2015 cache/options directory
.vs/
# Visual Studio Code options directory
+73 -152
View File
@@ -1,133 +1,90 @@
#!/usr/bin/env bash
#!/usr/bin/env sh
set -eu
: ${CXX=clang++}
: ${CPPFLAGS=}
: ${CXX=clang++}
: ${CXXFLAGS=}
: ${LDFLAGS=}
: ${ODIN_VERSION=dev-$(date +"%Y-%m")}
: ${GIT_SHA=}
: ${LLVM_CONFIG=}
CPPFLAGS="$CPPFLAGS -DODIN_VERSION_RAW=\"dev-$(date +"%Y-%m")\""
CXXFLAGS="$CXXFLAGS -std=c++14"
DISABLED_WARNINGS="-Wno-switch -Wno-macro-redefined -Wno-unused-value"
LDFLAGS="$LDFLAGS -pthread -lm -lstdc++"
OS_ARCH="$(uname -m)"
OS_NAME="$(uname -s)"
if [ -d ".git" ] && [ $(which git) ]; then
versionTag=( $(git show --pretty='%cd %h' --date=format:%Y-%m --no-patch --no-notes HEAD) )
if [ $? -eq 0 ]; then
ODIN_VERSION="dev-${versionTag[0]}"
GIT_SHA="${versionTag[1]}"
CPPFLAGS="$CPPFLAGS -DGIT_SHA=\"$GIT_SHA\""
fi
if [ -d ".git" ] && [ -n "$(command -v git)" ]; then
GIT_SHA=$(git show --pretty='%h' --no-patch --no-notes HEAD)
CPPFLAGS="$CPPFLAGS -DGIT_SHA=\"$GIT_SHA\""
fi
CPPFLAGS="$CPPFLAGS -DODIN_VERSION_RAW=\"$ODIN_VERSION\""
DISABLED_WARNINGS="-Wno-switch -Wno-macro-redefined -Wno-unused-value"
OS=$(uname)
panic() {
printf "%s\n" "$1"
error() {
printf "ERROR: %s\n" "$1"
exit 1
}
version() { echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'; }
config_darwin() {
local ARCH=$(uname -m)
: ${LLVM_CONFIG=llvm-config}
# allow for arm only llvm's with version 13
if [ "${ARCH}" == "arm64" ]; then
MIN_LLVM_VERSION=("13.0.0")
if [ -z "$LLVM_CONFIG" ]; then
# darwin, linux, openbsd
if [ -n "$(command -v llvm-config-17)" ]; then LLVM_CONFIG="llvm-config-17"
elif [ -n "$(command -v llvm-config-13)" ]; then LLVM_CONFIG="llvm-config-13"
elif [ -n "$(command -v llvm-config-12)" ]; then LLVM_CONFIG="llvm-config-12"
elif [ -n "$(command -v llvm-config-11)" ]; then LLVM_CONFIG="llvm-config-11"
# freebsd
elif [ -n "$(command -v llvm-config17)" ]; then LLVM_CONFIG="llvm-config-17"
elif [ -n "$(command -v llvm-config13)" ]; then LLVM_CONFIG="llvm-config-13"
elif [ -n "$(command -v llvm-config12)" ]; then LLVM_CONFIG="llvm-config-12"
elif [ -n "$(command -v llvm-config11)" ]; then LLVM_CONFIG="llvm-config-11"
# fallback
elif [ -n "$(command -v llvm-config)" ]; then LLVM_CONFIG="llvm-config"
else
# allow for x86 / amd64 all llvm versions beginning from 11
MIN_LLVM_VERSION=("11.1.0")
error "No llvm-config command found. Set LLVM_CONFIG to proceed."
fi
fi
if [ $(version $($LLVM_CONFIG --version)) -lt $(version $MIN_LLVM_VERSION) ]; then
if [ "${ARCH}" == "arm64" ]; then
panic "Requirement: llvm-config must be base version 13 for arm64"
else
panic "Requirement: llvm-config must be base version greater than 11 for amd64/x86"
LLVM_VERSION="$($LLVM_CONFIG --version)"
LLVM_VERSION_MAJOR="$(echo $LLVM_VERSION | awk -F. '{print $1}')"
LLVM_VERSION_MINOR="$(echo $LLVM_VERSION | awk -F. '{print $2}')"
LLVM_VERSION_PATCH="$(echo $LLVM_VERSION | awk -F. '{print $3}')"
if [ $LLVM_VERSION_MAJOR -lt 11 ] ||
([ $LLVM_VERSION_MAJOR -gt 14 ] && [ $LLVM_VERSION_MAJOR -lt 17 ]); then
error "Invalid LLVM version $LLVM_VERSION: must be 11, 12, 13, 14 or 17"
fi
case "$OS_NAME" in
Darwin)
if [ "$OS_ARCH" == "arm64" ]; then
if [ $LLVM_VERSION_MAJOR -lt 13 ] || [ $LLVM_VERSION_MAJOR -gt 17 ]; then
error "Darwin Arm64 requires LLVM 13, 14 or 17"
fi
fi
MAX_LLVM_VERSION=("14.999.999")
if [ $(version $($LLVM_CONFIG --version)) -gt $(version $MAX_LLVM_VERSION) ]; then
echo "Tried to use " $(which $LLVM_CONFIG) "version" $($LLVM_CONFIG --version)
panic "Requirement: llvm-config must be base version smaller than 15"
fi
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
LDFLAGS="$LDFLAGS -liconv -ldl -framework System"
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
LDFLAGS="$LDFLAGS -lLLVM-C"
}
config_freebsd() {
: ${LLVM_CONFIG=}
if [ ! "$LLVM_CONFIG" ]; then
if [ -x "$(command -v llvm-config11)" ]; then
LLVM_CONFIG=llvm-config11
elif [ -x "$(command -v llvm-config12)" ]; then
LLVM_CONFIG=llvm-config12
elif [ -x "$(command -v llvm-config13)" ]; then
LLVM_CONFIG=llvm-config13
else
panic "Unable to find LLVM-config"
fi
fi
;;
FreeBSD)
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)"
}
config_openbsd() {
: ${LLVM_CONFIG=/usr/local/bin/llvm-config}
LDFLAGS="$LDFLAGS -liconv"
;;
Linux)
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)"
}
config_linux() {
: ${LLVM_CONFIG=}
if [ ! "$LLVM_CONFIG" ]; then
if [ -x "$(command -v llvm-config)" ]; then
LLVM_CONFIG=llvm-config
elif [ -x "$(command -v llvm-config-11)" ]; then
LLVM_CONFIG=llvm-config-11
elif [ -x "$(command -v llvm-config-11-64)" ]; then
LLVM_CONFIG=llvm-config-11-64
elif [ -x "$(command -v llvm-config-14)" ]; then
LLVM_CONFIG=llvm-config-14
else
panic "Unable to find LLVM-config"
fi
fi
MIN_LLVM_VERSION=("11.0.0")
if [ $(version $($LLVM_CONFIG --version)) -lt $(version $MIN_LLVM_VERSION) ]; then
echo "Tried to use " $(which $LLVM_CONFIG) "version" $($LLVM_CONFIG --version)
panic "Requirement: llvm-config must be base version greater than 11"
fi
MAX_LLVM_VERSION=("14.999.999")
if [ $(version $($LLVM_CONFIG --version)) -gt $(version $MAX_LLVM_VERSION) ]; then
echo "Tried to use " $(which $LLVM_CONFIG) "version" $($LLVM_CONFIG --version)
panic "Requirement: llvm-config must be base version smaller than 15"
fi
LDFLAGS="$LDFLAGS -ldl"
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs --libfiles) -Wl,-rpath=\$ORIGIN"
# Creates a copy of the llvm library in the build dir, this is meant to support compiler explorer.
# The annoyance is that this copy can be cluttering the development folder. TODO: split staging folders
# for development and compiler explorer builds
LDFLAGS="$LDFLAGS -ldl $($LLVM_CONFIG --libs core native --system-libs --libfiles)"
# Copy libLLVM*.so into current directory for linking
# NOTE: This is needed by the Linux release pipeline!
cp $(readlink -f $($LLVM_CONFIG --libfiles)) ./
}
LDFLAGS="$LDFLAGS -Wl,-rpath=\$ORIGIN"
;;
OpenBSD)
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
LDFLAGS="$LDFLAGS -liconv"
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)"
;;
*)
error "Platform \"$OS_NAME\" unsupported"
;;
esac
build_odin() {
case $1 in
@@ -138,20 +95,19 @@ build_odin() {
EXTRAFLAGS="-O3"
;;
release-native)
local ARCH=$(uname -m)
if [ "${ARCH}" == "arm64" ]; then
# Use preferred flag for Arm (ie arm64 / aarch64 / etc)
EXTRAFLAGS="-O3 -mcpu=native"
else
# Use preferred flag for x86 / amd64
EXTRAFLAGS="-O3 -march=native"
fi
if [ "$OS_ARCH" == "arm64" ]; then
# Use preferred flag for Arm (ie arm64 / aarch64 / etc)
EXTRAFLAGS="-O3 -mcpu=native"
else
# Use preferred flag for x86 / amd64
EXTRAFLAGS="-O3 -march=native"
fi
;;
nightly)
EXTRAFLAGS="-DNIGHTLY -O3"
;;
*)
panic "Build mode unsupported!"
error "Build mode \"$1\" unsupported!"
;;
esac
@@ -164,55 +120,20 @@ run_demo() {
./odin run examples/demo/demo.odin -file
}
have_which() {
if ! command -v which > /dev/null 2>&1 ; then
panic "Could not find \`which\`"
fi
}
have_which
case $OS in
Linux)
config_linux
;;
Darwin)
config_darwin
;;
OpenBSD)
config_openbsd
;;
FreeBSD)
config_freebsd
;;
*)
panic "Platform unsupported!"
;;
esac
if [[ $# -eq 0 ]]; then
if [ $# -eq 0 ]; then
build_odin debug
run_demo
exit 0
fi
if [[ $# -eq 1 ]]; then
elif [ $# -eq 1 ]; then
case $1 in
report)
if [[ ! -f "./odin" ]]; then
build_odin debug
fi
[ ! -f "./odin" ] && build_odin debug
./odin report
exit 0
;;
*)
build_odin $1
;;
esac
run_demo
exit 0
else
panic "Too many arguments!"
error "Too many arguments!"
fi
+1 -1
View File
@@ -182,7 +182,7 @@ foreign libc {
fscanf :: proc(stream: ^FILE, format: cstring, #c_vararg args: ..any) -> int ---
printf :: proc(format: cstring, #c_vararg args: ..any) -> int ---
scanf :: proc(format: cstring, #c_vararg args: ..any) -> int ---
snprintf :: proc(s: [^]char, format: cstring, #c_vararg args: ..any) -> int ---
snprintf :: proc(s: [^]char, n: size_t, format: cstring, #c_vararg args: ..any) -> int ---
sscanf :: proc(s, format: cstring, #c_vararg args: ..any) -> int ---
vfprintf :: proc(stream: ^FILE, format: cstring, arg: ^va_list) -> int ---
vfscanf :: proc(stream: ^FILE, format: cstring, arg: ^va_list) -> int ---
+2 -2
View File
@@ -1,7 +1,7 @@
package crypto
when ODIN_OS != .Linux && ODIN_OS != .OpenBSD && ODIN_OS != .Windows {
_rand_bytes :: proc (dst: []byte) {
when ODIN_OS != .Linux && ODIN_OS != .OpenBSD && ODIN_OS != .Windows && ODIN_OS != .JS {
_rand_bytes :: proc(dst: []byte) {
unimplemented("crypto: rand_bytes not supported on this OS")
}
}
+20
View File
@@ -0,0 +1,20 @@
package crypto
foreign import "odin_env"
foreign odin_env {
@(link_name = "rand_bytes")
env_rand_bytes :: proc "contextless" (buf: []byte) ---
}
_MAX_PER_CALL_BYTES :: 65536 // 64kiB
_rand_bytes :: proc(dst: []byte) {
dst := dst
for len(dst) > 0 {
to_read := min(len(dst), _MAX_PER_CALL_BYTES)
env_rand_bytes(dst[:to_read])
dst = dst[to_read:]
}
}
+21 -22
View File
@@ -1,8 +1,8 @@
package crypto
import "core:fmt"
import "core:os"
import "core:sys/unix"
import "core:sys/linux"
_MAX_PER_CALL_BYTES :: 33554431 // 2^25 - 1
@@ -12,26 +12,25 @@ _rand_bytes :: proc (dst: []byte) {
for l > 0 {
to_read := min(l, _MAX_PER_CALL_BYTES)
ret := unix.sys_getrandom(raw_data(dst), uint(to_read), 0)
if ret < 0 {
switch os.Errno(-ret) {
case os.EINTR:
// Call interupted by a signal handler, just retry the
// request.
continue
case os.ENOSYS:
// The kernel is apparently prehistoric (< 3.17 circa 2014)
// and does not support getrandom.
panic("crypto: getrandom not available in kernel")
case:
// All other failures are things that should NEVER happen
// unless the kernel interface changes (ie: the Linux
// developers break userland).
panic(fmt.tprintf("crypto: getrandom failed: %d", ret))
}
n_read, errno := linux.getrandom(dst[:to_read], {})
#partial switch errno {
case .NONE:
// Do nothing
case .EINTR:
// Call interupted by a signal handler, just retry the
// request.
continue
case .ENOSYS:
// The kernel is apparently prehistoric (< 3.17 circa 2014)
// and does not support getrandom.
panic("crypto: getrandom not available in kernel")
case:
// All other failures are things that should NEVER happen
// unless the kernel interface changes (ie: the Linux
// developers break userland).
panic(fmt.tprintf("crypto: getrandom failed: %v", errno))
}
l -= ret
dst = dst[ret:]
l -= n_read
dst = dst[n_read:]
}
}
+11 -2
View File
@@ -263,8 +263,17 @@ parse_object_body :: proc(p: ^Parser, end_token: Token_Kind) -> (obj: Object, er
return
}
obj[key] = elem
// NOTE(gonz): There are code paths for which this traversal ends up
// inserting empty key/values into the object and for those we do not
// want to allocate anything
if key != "" {
reserve_error := reserve(&obj, len(obj) + 1)
if reserve_error == mem.Allocator_Error.Out_Of_Memory {
return nil, .Out_Of_Memory
}
obj[key] = elem
}
if parse_comma(p) {
break
}
+14
View File
@@ -0,0 +1,14 @@
package rand
foreign import "odin_env"
foreign odin_env {
@(link_name = "rand_bytes")
env_rand_bytes :: proc "contextless" (buf: []byte) ---
}
@(require_results)
_system_random :: proc() -> u64 {
buf: [8]u8
env_rand_bytes(buf[:])
return transmute(u64)buf
}
+18 -17
View File
@@ -1,27 +1,28 @@
package rand
import "core:sys/unix"
import "core:sys/linux"
@(require_results)
_system_random :: proc() -> u64 {
for {
value: u64
ret := unix.sys_getrandom(([^]u8)(&value), size_of(value), 0)
if ret < 0 {
switch ret {
case -4: // EINTR
// Call interupted by a signal handler, just retry the request.
continue
case -38: // ENOSYS
// The kernel is apparently prehistoric (< 3.17 circa 2014)
// and does not support getrandom.
panic("getrandom not available in kernel")
case:
// All other failures are things that should NEVER happen
// unless the kernel interface changes (ie: the Linux
// developers break userland).
panic("getrandom failed")
}
value_buf := (cast([^]u8)&value)[:size_of(u64)]
_, errno := linux.getrandom(value_buf, {})
#partial switch errno {
case .NONE:
// Do nothing
case .EINTR:
// Call interupted by a signal handler, just retry the request.
continue
case .ENOSYS:
// The kernel is apparently prehistoric (< 3.17 circa 2014)
// and does not support getrandom.
panic("getrandom not available in kernel")
case:
// All other failures are things that should NEVER happen
// unless the kernel interface changes (ie: the Linux
// developers break userland).
panic("getrandom failed")
}
return value
}
+23 -74
View File
@@ -2,100 +2,49 @@
//+private
package mem_virtual
import "core:c"
import "core:intrinsics"
import "core:sys/unix"
PROT_NONE :: 0x0
PROT_READ :: 0x1
PROT_WRITE :: 0x2
PROT_EXEC :: 0x4
PROT_GROWSDOWN :: 0x01000000
PROT_GROWSUP :: 0x02000000
MAP_FIXED :: 0x1
MAP_PRIVATE :: 0x2
MAP_SHARED :: 0x4
MAP_ANONYMOUS :: 0x20
MADV_NORMAL :: 0
MADV_RANDOM :: 1
MADV_SEQUENTIAL :: 2
MADV_WILLNEED :: 3
MADV_DONTNEED :: 4
MADV_FREE :: 8
MADV_REMOVE :: 9
MADV_DONTFORK :: 10
MADV_DOFORK :: 11
MADV_MERGEABLE :: 12
MADV_UNMERGEABLE :: 13
MADV_HUGEPAGE :: 14
MADV_NOHUGEPAGE :: 15
MADV_DONTDUMP :: 16
MADV_DODUMP :: 17
MADV_WIPEONFORK :: 18
MADV_KEEPONFORK :: 19
MADV_HWPOISON :: 100
mmap :: proc "contextless" (addr: rawptr, length: uint, prot: c.int, flags: c.int, fd: c.int, offset: uintptr) -> int {
res := intrinsics.syscall(unix.SYS_mmap, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flags), uintptr(fd), offset)
return int(res)
}
munmap :: proc "contextless" (addr: rawptr, length: uint) -> c.int {
res := intrinsics.syscall(unix.SYS_munmap, uintptr(addr), uintptr(length))
return c.int(res)
}
mprotect :: proc "contextless" (addr: rawptr, length: uint, prot: c.int) -> c.int {
res := intrinsics.syscall(unix.SYS_mprotect, uintptr(addr), uintptr(length), uintptr(prot))
return c.int(res)
}
madvise :: proc "contextless" (addr: rawptr, length: uint, advice: c.int) -> c.int {
res := intrinsics.syscall(unix.SYS_madvise, uintptr(addr), uintptr(length), uintptr(advice))
return c.int(res)
}
import "core:sys/linux"
_reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) {
result := mmap(nil, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
if result < 0 && result > -4096 {
addr, errno := linux.mmap(0, size, {}, {.PRIVATE, .ANONYMOUS})
if errno == .ENOMEM {
return nil, .Out_Of_Memory
} else if errno == .EINVAL {
return nil, .Invalid_Argument
}
return ([^]byte)(uintptr(result))[:size], nil
return (cast([^]byte)addr)[:size], nil
}
_commit :: proc "contextless" (data: rawptr, size: uint) -> Allocator_Error {
result := mprotect(data, size, PROT_READ|PROT_WRITE)
if result != 0 {
// TODO(bill): Handle error value correctly
errno := linux.mprotect(data, size, {.READ, .WRITE})
if errno == .EINVAL {
return .Invalid_Pointer
} else if errno == .ENOMEM {
return .Out_Of_Memory
}
return nil
}
_decommit :: proc "contextless" (data: rawptr, size: uint) {
mprotect(data, size, PROT_NONE)
madvise(data, size, MADV_FREE)
_ = linux.mprotect(data, size, {})
_ = linux.madvise(data, size, .FREE)
}
_release :: proc "contextless" (data: rawptr, size: uint) {
munmap(data, size)
_ = linux.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
pflags: linux.Mem_Protection
pflags = {}
if .Read in flags { pflags |= {.READ} }
if .Write in flags { pflags |= {.WRITE} }
if .Execute in flags { pflags |= {.EXEC} }
errno := linux.mprotect(data, size, pflags)
return errno != .NONE
}
_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)
}
+95 -93
View File
@@ -16,182 +16,184 @@ package net
Tetralux: Initial implementation
Colin Davidson: Linux platform code, OSX platform code, Odin-native DNS resolver
Jeroen van Rijn: Cross platform unification, code style, documentation
flysand: Move dependency from core:linux.Errno to core:sys/linux
*/
import "core:c"
import "core:os"
import "core:sys/linux"
Create_Socket_Error :: enum c.int {
None = 0,
Family_Not_Supported_For_This_Socket = c.int(os.EAFNOSUPPORT),
No_Socket_Descriptors_Available = c.int(os.EMFILE),
No_Buffer_Space_Available = c.int(os.ENOBUFS),
No_Memory_Available_Available = c.int(os.ENOMEM),
Protocol_Unsupported_By_System = c.int(os.EPROTONOSUPPORT),
Wrong_Protocol_For_Socket = c.int(os.EPROTONOSUPPORT),
Family_And_Socket_Type_Mismatch = c.int(os.EPROTONOSUPPORT),
Family_Not_Supported_For_This_Socket = c.int(linux.Errno.EAFNOSUPPORT),
No_Socket_Descriptors_Available = c.int(linux.Errno.EMFILE),
No_Buffer_Space_Available = c.int(linux.Errno.ENOBUFS),
No_Memory_Available_Available = c.int(linux.Errno.ENOMEM),
Protocol_Unsupported_By_System = c.int(linux.Errno.EPROTONOSUPPORT),
Wrong_Protocol_For_Socket = c.int(linux.Errno.EPROTONOSUPPORT),
Family_And_Socket_Type_Mismatch = c.int(linux.Errno.EPROTONOSUPPORT),
}
Dial_Error :: enum c.int {
None = 0,
Port_Required = -1,
Address_In_Use = c.int(os.EADDRINUSE),
In_Progress = c.int(os.EINPROGRESS),
Cannot_Use_Any_Address = c.int(os.EADDRNOTAVAIL),
Wrong_Family_For_Socket = c.int(os.EAFNOSUPPORT),
Refused = c.int(os.ECONNREFUSED),
Is_Listening_Socket = c.int(os.EACCES),
Already_Connected = c.int(os.EISCONN),
Network_Unreachable = c.int(os.ENETUNREACH), // Device is offline
Host_Unreachable = c.int(os.EHOSTUNREACH), // Remote host cannot be reached
No_Buffer_Space_Available = c.int(os.ENOBUFS),
Not_Socket = c.int(os.ENOTSOCK),
Timeout = c.int(os.ETIMEDOUT),
Address_In_Use = c.int(linux.Errno.EADDRINUSE),
In_Progress = c.int(linux.Errno.EINPROGRESS),
Cannot_Use_Any_Address = c.int(linux.Errno.EADDRNOTAVAIL),
Wrong_Family_For_Socket = c.int(linux.Errno.EAFNOSUPPORT),
Refused = c.int(linux.Errno.ECONNREFUSED),
Is_Listening_Socket = c.int(linux.Errno.EACCES),
Already_Connected = c.int(linux.Errno.EISCONN),
Network_Unreachable = c.int(linux.Errno.ENETUNREACH), // Device is offline
Host_Unreachable = c.int(linux.Errno.EHOSTUNREACH), // Remote host cannot be reached
No_Buffer_Space_Available = c.int(linux.Errno.ENOBUFS),
Not_Socket = c.int(linux.Errno.ENOTSOCK),
Timeout = c.int(linux.Errno.ETIMEDOUT),
// TODO: we may need special handling for this; maybe make a socket a struct with metadata?
Would_Block = c.int(os.EWOULDBLOCK),
Would_Block = c.int(linux.Errno.EWOULDBLOCK),
}
Bind_Error :: enum c.int {
None = 0,
Address_In_Use = c.int(os.EADDRINUSE), // Another application is currently bound to this endpoint.
Given_Nonlocal_Address = c.int(os.EADDRNOTAVAIL), // The address is not a local address on this machine.
Broadcast_Disabled = c.int(os.EACCES), // To bind a UDP socket to the broadcast address, the appropriate socket option must be set.
Address_Family_Mismatch = c.int(os.EFAULT), // The address family of the address does not match that of the socket.
Already_Bound = c.int(os.EINVAL), // The socket is already bound to an address.
No_Ports_Available = c.int(os.ENOBUFS), // There are not enough ephemeral ports available.
Address_In_Use = c.int(linux.Errno.EADDRINUSE), // Another application is currently bound to this endpoint.
Given_Nonlocal_Address = c.int(linux.Errno.EADDRNOTAVAIL), // The address is not a local address on this machine.
Broadcast_Disabled = c.int(linux.Errno.EACCES), // To bind a UDP socket to the broadcast address, the appropriate socket option must be set.
Address_Family_Mismatch = c.int(linux.Errno.EFAULT), // The address family of the address does not match that of the socket.
Already_Bound = c.int(linux.Errno.EINVAL), // The socket is already bound to an address.
No_Ports_Available = c.int(linux.Errno.ENOBUFS), // There are not enough ephemeral ports available.
}
Listen_Error :: enum c.int {
None = 0,
Address_In_Use = c.int(os.EADDRINUSE),
Already_Connected = c.int(os.EISCONN),
No_Socket_Descriptors_Available = c.int(os.EMFILE),
No_Buffer_Space_Available = c.int(os.ENOBUFS),
Nonlocal_Address = c.int(os.EADDRNOTAVAIL),
Not_Socket = c.int(os.ENOTSOCK),
Listening_Not_Supported_For_This_Socket = c.int(os.EOPNOTSUPP),
Address_In_Use = c.int(linux.Errno.EADDRINUSE),
Already_Connected = c.int(linux.Errno.EISCONN),
No_Socket_Descriptors_Available = c.int(linux.Errno.EMFILE),
No_Buffer_Space_Available = c.int(linux.Errno.ENOBUFS),
Nonlocal_Address = c.int(linux.Errno.EADDRNOTAVAIL),
Not_Socket = c.int(linux.Errno.ENOTSOCK),
Listening_Not_Supported_For_This_Socket = c.int(linux.Errno.EOPNOTSUPP),
}
Accept_Error :: enum c.int {
None = 0,
Not_Listening = c.int(os.EINVAL),
No_Socket_Descriptors_Available_For_Client_Socket = c.int(os.EMFILE),
No_Buffer_Space_Available = c.int(os.ENOBUFS),
Not_Socket = c.int(os.ENOTSOCK),
Not_Connection_Oriented_Socket = c.int(os.EOPNOTSUPP),
Not_Listening = c.int(linux.Errno.EINVAL),
No_Socket_Descriptors_Available_For_Client_Socket = c.int(linux.Errno.EMFILE),
No_Buffer_Space_Available = c.int(linux.Errno.ENOBUFS),
Not_Socket = c.int(linux.Errno.ENOTSOCK),
Not_Connection_Oriented_Socket = c.int(linux.Errno.EOPNOTSUPP),
// TODO: we may need special handling for this; maybe make a socket a struct with metadata?
Would_Block = c.int(os.EWOULDBLOCK),
Would_Block = c.int(linux.Errno.EWOULDBLOCK),
}
TCP_Recv_Error :: enum c.int {
None = 0,
Shutdown = c.int(os.ESHUTDOWN),
Not_Connected = c.int(os.ENOTCONN),
Connection_Broken = c.int(os.ENETRESET),
Not_Socket = c.int(os.ENOTSOCK),
Aborted = c.int(os.ECONNABORTED),
Shutdown = c.int(linux.Errno.ESHUTDOWN),
Not_Connected = c.int(linux.Errno.ENOTCONN),
Connection_Broken = c.int(linux.Errno.ENETRESET),
Not_Socket = c.int(linux.Errno.ENOTSOCK),
Aborted = c.int(linux.Errno.ECONNABORTED),
// TODO(tetra): Determine when this is different from the syscall returning n=0 and maybe normalize them?
Connection_Closed = c.int(os.ECONNRESET),
Offline = c.int(os.ENETDOWN),
Host_Unreachable = c.int(os.EHOSTUNREACH),
Interrupted = c.int(os.EINTR),
Timeout = c.int(os.EWOULDBLOCK), // NOTE: No, really. Presumably this means something different for nonblocking sockets...
Connection_Closed = c.int(linux.Errno.ECONNRESET),
Offline = c.int(linux.Errno.ENETDOWN),
Host_Unreachable = c.int(linux.Errno.EHOSTUNREACH),
Interrupted = c.int(linux.Errno.EINTR),
Timeout = c.int(linux.Errno.EWOULDBLOCK), // NOTE: No, really. Presumably this means something different for nonblocking sockets...
}
UDP_Recv_Error :: enum c.int {
None = 0,
Buffer_Too_Small = c.int(os.EMSGSIZE), // The buffer is too small to fit the entire message, and the message was truncated. When this happens, the rest of message is lost.
Not_Socket = c.int(os.ENOTSOCK), // The so-called socket is not an open socket.
Not_Descriptor = c.int(os.EBADF), // The so-called socket is, in fact, not even a valid descriptor.
Bad_Buffer = c.int(os.EFAULT), // The buffer did not point to a valid location in memory.
Interrupted = c.int(os.EINTR), // A signal occurred before any data was transmitted. See signal(7).
Buffer_Too_Small = c.int(linux.Errno.EMSGSIZE), // The buffer is too small to fit the entire message, and the message was truncated. When this happens, the rest of message is lost.
Not_Socket = c.int(linux.Errno.ENOTSOCK), // The so-called socket is not an open socket.
Not_Descriptor = c.int(linux.Errno.EBADF), // The so-called socket is, in fact, not even a valid descriptor.
Bad_Buffer = c.int(linux.Errno.EFAULT), // The buffer did not point to a valid location in memory.
Interrupted = c.int(linux.Errno.EINTR), // A signal occurred before any data was transmitted. See signal(7).
// The send timeout duration passed before all data was received. See Socket_Option.Receive_Timeout.
// NOTE: No, really. Presumably this means something different for nonblocking sockets...
Timeout = c.int(os.EWOULDBLOCK),
Socket_Not_Bound = c.int(os.EINVAL), // The socket must be bound for this operation, but isn't.
Timeout = c.int(linux.Errno.EWOULDBLOCK),
Socket_Not_Bound = c.int(linux.Errno.EINVAL), // The socket must be bound for this operation, but isn't.
}
TCP_Send_Error :: enum c.int {
None = 0,
Aborted = c.int(os.ECONNABORTED),
Connection_Closed = c.int(os.ECONNRESET),
Not_Connected = c.int(os.ENOTCONN),
Shutdown = c.int(os.ESHUTDOWN),
Aborted = c.int(linux.Errno.ECONNABORTED),
Connection_Closed = c.int(linux.Errno.ECONNRESET),
Not_Connected = c.int(linux.Errno.ENOTCONN),
Shutdown = c.int(linux.Errno.ESHUTDOWN),
// The send queue was full.
// This is usually a transient issue.
//
// This also shouldn't normally happen on Linux, as data is dropped if it
// doesn't fit in the send queue.
No_Buffer_Space_Available = c.int(os.ENOBUFS),
Offline = c.int(os.ENETDOWN),
Host_Unreachable = c.int(os.EHOSTUNREACH),
Interrupted = c.int(os.EINTR), // A signal occurred before any data was transmitted. See signal(7).
Timeout = c.int(os.EWOULDBLOCK), // The send timeout duration passed before all data was sent. See Socket_Option.Send_Timeout.
Not_Socket = c.int(os.ENOTSOCK), // The so-called socket is not an open socket.
No_Buffer_Space_Available = c.int(linux.Errno.ENOBUFS),
Offline = c.int(linux.Errno.ENETDOWN),
Host_Unreachable = c.int(linux.Errno.EHOSTUNREACH),
Interrupted = c.int(linux.Errno.EINTR), // A signal occurred before any data was transmitted. See signal(7).
Timeout = c.int(linux.Errno.EWOULDBLOCK), // The send timeout duration passed before all data was sent. See Socket_Option.Send_Timeout.
Not_Socket = c.int(linux.Errno.ENOTSOCK), // The so-called socket is not an open socket.
}
// TODO
UDP_Send_Error :: enum c.int {
None = 0,
Message_Too_Long = c.int(os.EMSGSIZE), // The message is larger than the maximum UDP packet size. No data was sent.
Message_Too_Long = c.int(linux.Errno.EMSGSIZE), // The message is larger than the maximum UDP packet size. No data was sent.
// TODO: not sure what the exact circumstances for this is yet
Network_Unreachable = c.int(os.ENETUNREACH),
No_Outbound_Ports_Available = c.int(os.EAGAIN), // There are no more emphemeral outbound ports available to bind the socket to, in order to send.
Network_Unreachable = c.int(linux.Errno.ENETUNREACH),
No_Outbound_Ports_Available = c.int(linux.Errno.EAGAIN), // There are no more emphemeral outbound ports available to bind the socket to, in order to send.
// The send timeout duration passed before all data was sent. See Socket_Option.Send_Timeout.
// NOTE: No, really. Presumably this means something different for nonblocking sockets...
Timeout = c.int(os.EWOULDBLOCK),
Not_Socket = c.int(os.ENOTSOCK), // The so-called socket is not an open socket.
Not_Descriptor = c.int(os.EBADF), // The so-called socket is, in fact, not even a valid descriptor.
Bad_Buffer = c.int(os.EFAULT), // The buffer did not point to a valid location in memory.
Interrupted = c.int(os.EINTR), // A signal occurred before any data was transmitted. See signal(7).
Timeout = c.int(linux.Errno.EWOULDBLOCK),
Not_Socket = c.int(linux.Errno.ENOTSOCK), // The so-called socket is not an open socket.
Not_Descriptor = c.int(linux.Errno.EBADF), // The so-called socket is, in fact, not even a valid descriptor.
Bad_Buffer = c.int(linux.Errno.EFAULT), // The buffer did not point to a valid location in memory.
Interrupted = c.int(linux.Errno.EINTR), // A signal occurred before any data was transmitted. See signal(7).
// The send queue was full.
// This is usually a transient issue.
//
// This also shouldn't normally happen on Linux, as data is dropped if it
// doesn't fit in the send queue.
No_Buffer_Space_Available = c.int(os.ENOBUFS),
No_Memory_Available = c.int(os.ENOMEM), // No memory was available to properly manage the send queue.
No_Buffer_Space_Available = c.int(linux.Errno.ENOBUFS),
No_Memory_Available = c.int(linux.Errno.ENOMEM), // No memory was available to properly manage the send queue.
}
// TODO(flysand): slight regression
Shutdown_Manner :: enum c.int {
Receive = c.int(os.SHUT_RD),
Send = c.int(os.SHUT_WR),
Both = c.int(os.SHUT_RDWR),
Receive = c.int(linux.Shutdown_How.RD),
Send = c.int(linux.Shutdown_How.WR),
Both = c.int(linux.Shutdown_How.RDWR),
}
Shutdown_Error :: enum c.int {
None = 0,
Aborted = c.int(os.ECONNABORTED),
Reset = c.int(os.ECONNRESET),
Offline = c.int(os.ENETDOWN),
Not_Connected = c.int(os.ENOTCONN),
Not_Socket = c.int(os.ENOTSOCK),
Invalid_Manner = c.int(os.EINVAL),
Aborted = c.int(linux.Errno.ECONNABORTED),
Reset = c.int(linux.Errno.ECONNRESET),
Offline = c.int(linux.Errno.ENETDOWN),
Not_Connected = c.int(linux.Errno.ENOTCONN),
Not_Socket = c.int(linux.Errno.ENOTSOCK),
Invalid_Manner = c.int(linux.Errno.EINVAL),
}
Socket_Option_Error :: enum c.int {
None = 0,
Offline = c.int(os.ENETDOWN),
Timeout_When_Keepalive_Set = c.int(os.ENETRESET),
Invalid_Option_For_Socket = c.int(os.ENOPROTOOPT),
Reset_When_Keepalive_Set = c.int(os.ENOTCONN),
Not_Socket = c.int(os.ENOTSOCK),
Offline = c.int(linux.Errno.ENETDOWN),
Timeout_When_Keepalive_Set = c.int(linux.Errno.ENETRESET),
Invalid_Option_For_Socket = c.int(linux.Errno.ENOPROTOOPT),
Reset_When_Keepalive_Set = c.int(linux.Errno.ENOTCONN),
Not_Socket = c.int(linux.Errno.ENOTSOCK),
}
Set_Blocking_Error :: enum c.int {
None = 0,
// TODO: add errors occuring on followig calls:
// flags, _ := os.fcntl(sd, os.F_GETFL, 0)
// os.fcntl(sd, os.F_SETFL, flags | int(os.O_NONBLOCK))
// flags, _ := linux.Errno.fcntl(sd, linux.Errno.F_GETFL, 0)
// linux.Errno.fcntl(sd, linux.Errno.F_SETFL, flags | int(linux.Errno.O_NONBLOCK))
}
+97 -5
View File
@@ -19,14 +19,106 @@ package net
*/
import "core:os"
import "core:strings"
@(private)
_enumerate_interfaces :: proc(allocator := context.allocator) -> (interfaces: []Network_Interface, err: Network_Error) {
context.allocator = allocator
head: ^os.ifaddrs
// TODO: Implement. Can probably use the (current) Linux implementation,
// which will itself be switched over to talking to the kernel via NETLINK protocol
// once we have raw sockets.
if res := os._getifaddrs(&head); res < 0 {
return {}, .Unable_To_Enumerate_Network_Interfaces
}
unimplemented()
}
/*
Unlike Windows, *nix regrettably doesn't return all it knows about an interface in one big struct.
We're going to have to iterate over a list and coalesce information as we go.
*/
ifaces: map[string]^Network_Interface
defer delete(ifaces)
for ifaddr := head; ifaddr != nil; ifaddr = ifaddr.next {
adapter_name := string(ifaddr.name)
/*
Check if we have seen this interface name before so we can reuse the `Network_Interface`.
Else, create a new one.
*/
if adapter_name not_in ifaces {
ifaces[adapter_name] = new(Network_Interface)
ifaces[adapter_name].adapter_name = strings.clone(adapter_name)
}
iface := ifaces[adapter_name]
address: Address
netmask: Netmask
if ifaddr.address != nil {
switch int(ifaddr.address.family) {
case os.AF_INET, os.AF_INET6:
address = _sockaddr_basic_to_endpoint(ifaddr.address).address
case:
}
}
if ifaddr.netmask != nil {
switch int(ifaddr.netmask.family) {
case os.AF_INET, os.AF_INET6:
netmask = Netmask(_sockaddr_basic_to_endpoint(ifaddr.netmask).address)
case:
}
}
if ifaddr.broadcast_or_dest != nil && .BROADCAST in ifaddr.flags {
switch int(ifaddr.broadcast_or_dest.family) {
case os.AF_INET, os.AF_INET6:
broadcast := _sockaddr_basic_to_endpoint(ifaddr.broadcast_or_dest).address
append(&iface.multicast, broadcast)
case:
}
}
if address != nil {
lease := Lease{
address = address,
netmask = netmask,
}
append(&iface.unicast, lease)
}
/*
TODO: Refine this based on the type of adapter.
*/
state := Link_State{}
if .UP in ifaddr.flags {
state |= {.Up}
}
/*if .DORMANT in ifaddr.flags {
state |= {.Dormant}
}*/
if .LOOPBACK in ifaddr.flags {
state |= {.Loopback}
}
iface.link.state = state
}
/*
Free the OS structures.
*/
os._freeifaddrs(head)
/*
Turn the map into a slice to return.
*/
_interfaces := make([dynamic]Network_Interface, 0, allocator)
for _, iface in ifaces {
append(&_interfaces, iface^)
free(iface)
}
return _interfaces[:], {}
}
+97 -93
View File
@@ -21,120 +21,124 @@ package net
TODO: When we have raw sockets, split off into its own file for Linux so we can use the NETLINK protocol and bypass libc.
*/
import "core:os"
import "core:strings"
//import "core:strings"
// TODO(flysand): regression
// NOTE(flysand): https://man7.org/linux/man-pages/man7/netlink.7.html
// apparently musl libc uses this to enumerate network interfaces
@(private)
_enumerate_interfaces :: proc(allocator := context.allocator) -> (interfaces: []Network_Interface, err: Network_Error) {
context.allocator = allocator
head: ^os.ifaddrs
// head: ^os.ifaddrs
if res := os._getifaddrs(&head); res < 0 {
return {}, .Unable_To_Enumerate_Network_Interfaces
}
// if res := os._getifaddrs(&head); res < 0 {
// return {}, .Unable_To_Enumerate_Network_Interfaces
// }
/*
Unlike Windows, *nix regrettably doesn't return all it knows about an interface in one big struct.
We're going to have to iterate over a list and coalesce information as we go.
*/
ifaces: map[string]^Network_Interface
defer delete(ifaces)
// /*
// Unlike Windows, *nix regrettably doesn't return all it knows about an interface in one big struct.
// We're going to have to iterate over a list and coalesce information as we go.
// */
// ifaces: map[string]^Network_Interface
// defer delete(ifaces)
for ifaddr := head; ifaddr != nil; ifaddr = ifaddr.next {
adapter_name := string(ifaddr.name)
// for ifaddr := head; ifaddr != nil; ifaddr = ifaddr.next {
// adapter_name := string(ifaddr.name)
/*
Check if we have seen this interface name before so we can reuse the `Network_Interface`.
Else, create a new one.
*/
if adapter_name not_in ifaces {
ifaces[adapter_name] = new(Network_Interface)
ifaces[adapter_name].adapter_name = strings.clone(adapter_name)
}
iface := ifaces[adapter_name]
// /*
// Check if we have seen this interface name before so we can reuse the `Network_Interface`.
// Else, create a new one.
// */
// if adapter_name not_in ifaces {
// ifaces[adapter_name] = new(Network_Interface)
// ifaces[adapter_name].adapter_name = strings.clone(adapter_name)
// }
// iface := ifaces[adapter_name]
address: Address
netmask: Netmask
// address: Address
// netmask: Netmask
if ifaddr.address != nil {
switch int(ifaddr.address.sa_family) {
case os.AF_INET, os.AF_INET6:
address = _sockaddr_basic_to_endpoint(ifaddr.address).address
// if ifaddr.address != nil {
// switch int(ifaddr.address.sa_family) {
// case os.AF_INET, os.AF_INET6:
// address = _sockaddr_basic_to_endpoint(ifaddr.address).address
case os.AF_PACKET:
/*
For some obscure reason the 64-bit `getifaddrs` call returns a pointer to a
32-bit `RTNL_LINK_STATS` structure, which of course means that tx/rx byte count
is truncated beyond usefulness.
// case os.AF_PACKET:
// /*
// For some obscure reason the 64-bit `getifaddrs` call returns a pointer to a
// 32-bit `RTNL_LINK_STATS` structure, which of course means that tx/rx byte count
// is truncated beyond usefulness.
We're not going to retrieve stats now. Instead this serves as a reminder to use
the NETLINK protocol for this purpose.
// We're not going to retrieve stats now. Instead this serves as a reminder to use
// the NETLINK protocol for this purpose.
But in case you were curious:
stats := transmute(^os.rtnl_link_stats)ifaddr.data
fmt.println(stats)
*/
case:
}
}
// But in case you were curious:
// stats := transmute(^os.rtnl_link_stats)ifaddr.data
// fmt.println(stats)
// */
// case:
// }
// }
if ifaddr.netmask != nil {
switch int(ifaddr.netmask.sa_family) {
case os.AF_INET, os.AF_INET6:
netmask = Netmask(_sockaddr_basic_to_endpoint(ifaddr.netmask).address)
case:
}
}
// if ifaddr.netmask != nil {
// switch int(ifaddr.netmask.sa_family) {
// case os.AF_INET, os.AF_INET6:
// netmask = Netmask(_sockaddr_basic_to_endpoint(ifaddr.netmask).address)
// case:
// }
// }
if ifaddr.broadcast_or_dest != nil && .BROADCAST in ifaddr.flags {
switch int(ifaddr.broadcast_or_dest.sa_family) {
case os.AF_INET, os.AF_INET6:
broadcast := _sockaddr_basic_to_endpoint(ifaddr.broadcast_or_dest).address
append(&iface.multicast, broadcast)
case:
}
}
// if ifaddr.broadcast_or_dest != nil && .BROADCAST in ifaddr.flags {
// switch int(ifaddr.broadcast_or_dest.sa_family) {
// case os.AF_INET, os.AF_INET6:
// broadcast := _sockaddr_basic_to_endpoint(ifaddr.broadcast_or_dest).address
// append(&iface.multicast, broadcast)
// case:
// }
// }
if address != nil {
lease := Lease{
address = address,
netmask = netmask,
}
append(&iface.unicast, lease)
}
// if address != nil {
// lease := Lease{
// address = address,
// netmask = netmask,
// }
// append(&iface.unicast, lease)
// }
/*
TODO: Refine this based on the type of adapter.
*/
state := Link_State{}
// /*
// TODO: Refine this based on the type of adapter.
// */
// state := Link_State{}
if .UP in ifaddr.flags {
state |= {.Up}
}
// if .UP in ifaddr.flags {
// state |= {.Up}
// }
if .DORMANT in ifaddr.flags {
state |= {.Dormant}
}
// if .DORMANT in ifaddr.flags {
// state |= {.Dormant}
// }
if .LOOPBACK in ifaddr.flags {
state |= {.Loopback}
}
iface.link.state = state
}
// if .LOOPBACK in ifaddr.flags {
// state |= {.Loopback}
// }
// iface.link.state = state
// }
/*
Free the OS structures.
*/
os._freeifaddrs(head)
// /*
// Free the OS structures.
// */
// os._freeifaddrs(head)
/*
Turn the map into a slice to return.
*/
_interfaces := make([dynamic]Network_Interface, 0, allocator)
for _, iface in ifaces {
append(&_interfaces, iface^)
free(iface)
}
return _interfaces[:], {}
// /*
// Turn the map into a slice to return.
// */
// _interfaces := make([dynamic]Network_Interface, 0, allocator)
// for _, iface in ifaces {
// append(&_interfaces, iface^)
// free(iface)
// }
// return _interfaces[:], {}
return nil, {}
}
+1 -1
View File
@@ -18,7 +18,7 @@ package net
Jeroen van Rijn: Cross platform unification, code style, documentation
*/
any_socket_to_socket :: proc(socket: Any_Socket) -> Socket {
any_socket_to_socket :: proc "contextless" (socket: Any_Socket) -> Socket {
switch s in socket {
case TCP_Socket: return Socket(s)
case UDP_Socket: return Socket(s)
+25
View File
@@ -23,6 +23,7 @@ import "core:os"
import "core:time"
Socket_Option :: enum c.int {
Broadcast = c.int(os.SO_BROADCAST),
Reuse_Address = c.int(os.SO_REUSEADDR),
Keep_Alive = c.int(os.SO_KEEPALIVE),
Out_Of_Bounds_Data_Inline = c.int(os.SO_OOBINLINE),
@@ -238,6 +239,7 @@ _set_option :: proc(s: Any_Socket, option: Socket_Option, value: any, loc := #ca
switch option {
case
.Broadcast,
.Reuse_Address,
.Keep_Alive,
.Out_Of_Bounds_Data_Inline,
@@ -369,3 +371,26 @@ _sockaddr_to_endpoint :: proc(native_addr: ^os.SOCKADDR_STORAGE_LH) -> (ep: Endp
}
return
}
@(private)
_sockaddr_basic_to_endpoint :: proc(native_addr: ^os.SOCKADDR) -> (ep: Endpoint) {
switch u16(native_addr.family) {
case u16(os.AF_INET):
addr := cast(^os.sockaddr_in) native_addr
port := int(addr.sin_port)
ep = Endpoint {
address = IP4_Address(transmute([4]byte) addr.sin_addr),
port = port,
}
case u16(os.AF_INET6):
addr := cast(^os.sockaddr_in6) native_addr
port := int(addr.sin6_port)
ep = Endpoint {
address = IP6_Address(transmute([8]u16be) addr.sin6_addr),
port = port,
}
case:
panic("native_addr is neither IP4 or IP6 address")
}
return
}
+232 -256
View File
@@ -16,241 +16,294 @@ package net
Tetralux: Initial implementation
Colin Davidson: Linux platform code, OSX platform code, Odin-native DNS resolver
Jeroen van Rijn: Cross platform unification, code style, documentation
flysand: Move dependency from core:os to core:sys/linux
*/
import "core:c"
import "core:os"
import "core:time"
import "core:sys/linux"
Socket_Option :: enum c.int {
Reuse_Address = c.int(os.SO_REUSEADDR),
Keep_Alive = c.int(os.SO_KEEPALIVE),
Out_Of_Bounds_Data_Inline = c.int(os.SO_OOBINLINE),
TCP_Nodelay = c.int(os.TCP_NODELAY),
Linger = c.int(os.SO_LINGER),
Receive_Buffer_Size = c.int(os.SO_RCVBUF),
Send_Buffer_Size = c.int(os.SO_SNDBUF),
Receive_Timeout = c.int(os.SO_RCVTIMEO_NEW),
Send_Timeout = c.int(os.SO_SNDTIMEO_NEW),
Reuse_Address = c.int(linux.Socket_Option.REUSEADDR),
Keep_Alive = c.int(linux.Socket_Option.KEEPALIVE),
Out_Of_Bounds_Data_Inline = c.int(linux.Socket_Option.OOBINLINE),
TCP_Nodelay = c.int(linux.Socket_TCP_Option.NODELAY),
Linger = c.int(linux.Socket_Option.LINGER),
Receive_Buffer_Size = c.int(linux.Socket_Option.RCVBUF),
Send_Buffer_Size = c.int(linux.Socket_Option.SNDBUF),
Receive_Timeout = c.int(linux.Socket_Option.RCVTIMEO_NEW),
Send_Timeout = c.int(linux.Socket_Option.SNDTIMEO_NEW),
}
@(private)
_create_socket :: proc(family: Address_Family, protocol: Socket_Protocol) -> (socket: Any_Socket, err: Network_Error) {
c_type, c_protocol, c_family: int
// Wrappers and unwrappers for system-native types
@(private="file")
_unwrap_os_socket :: proc "contextless" (sock: Any_Socket)->linux.Fd {
return linux.Fd(any_socket_to_socket(sock))
}
@(private="file")
_wrap_os_socket :: proc "contextless" (sock: linux.Fd, protocol: Socket_Protocol)->Any_Socket {
switch protocol {
case .TCP: return TCP_Socket(Socket(sock))
case .UDP: return UDP_Socket(Socket(sock))
case:
unreachable()
}
}
@(private="file")
_unwrap_os_family :: proc "contextless" (family: Address_Family)->linux.Address_Family {
switch family {
case .IP4: c_family = os.AF_INET
case .IP6: c_family = os.AF_INET6
case:
unreachable()
}
switch protocol {
case .TCP: c_type = os.SOCK_STREAM; c_protocol = os.IPPROTO_TCP
case .UDP: c_type = os.SOCK_DGRAM; c_protocol = os.IPPROTO_UDP
case:
unreachable()
}
sock, ok := os.socket(c_family, c_type, c_protocol)
if ok != os.ERROR_NONE {
err = Create_Socket_Error(ok)
return
}
switch protocol {
case .TCP: return TCP_Socket(sock), nil
case .UDP: return UDP_Socket(sock), nil
case .IP4: return .INET
case .IP6: return .INET6
case:
unreachable()
}
}
@(private="file")
_unwrap_os_proto_socktype :: proc "contextless" (protocol: Socket_Protocol)->(linux.Protocol, linux.Socket_Type) {
switch protocol {
case .TCP: return .TCP, .STREAM
case .UDP: return .UDP, .DGRAM
case:
unreachable()
}
}
@(private="file")
_unwrap_os_addr :: proc "contextless" (endpoint: Endpoint)->(linux.Sock_Addr_Any) {
switch address in endpoint.address {
case IP4_Address:
return {
ipv4 = {
sin_family = .INET,
sin_port = u16be(endpoint.port),
sin_addr = transmute([4]u8) endpoint.address.(IP4_Address),
},
}
case IP6_Address:
return {
ipv6 = {
sin6_port = u16be(endpoint.port),
sin6_addr = transmute([16]u8) endpoint.address.(IP6_Address),
sin6_family = .INET6,
},
}
case:
unreachable()
}
}
@(private="file")
_wrap_os_addr :: proc "contextless" (addr: linux.Sock_Addr_Any)->(Endpoint) {
#partial switch addr.family {
case .INET:
return {
address = cast(IP4_Address) addr.sin_addr,
port = cast(int) addr.sin_port,
}
case .INET6:
return {
port = cast(int) addr.sin6_port,
address = transmute(IP6_Address) addr.sin6_addr,
}
case:
unreachable()
}
}
_create_socket :: proc(family: Address_Family, protocol: Socket_Protocol) -> (Any_Socket, Network_Error) {
family := _unwrap_os_family(family)
proto, socktype := _unwrap_os_proto_socktype(protocol)
sock, errno := linux.socket(family, socktype, {}, proto)
if errno != .NONE {
return {}, Create_Socket_Error(errno)
}
return _wrap_os_socket(sock, protocol), nil
}
@(private)
_dial_tcp_from_endpoint :: proc(endpoint: Endpoint, options := default_tcp_options) -> (skt: TCP_Socket, err: Network_Error) {
_dial_tcp_from_endpoint :: proc(endpoint: Endpoint, options := default_tcp_options) -> (tcp_sock: TCP_Socket, err: Network_Error) {
errno: linux.Errno
if endpoint.port == 0 {
return 0, .Port_Required
}
family := family_from_endpoint(endpoint)
sock := create_socket(family, .TCP) or_return
skt = sock.(TCP_Socket)
// Create new TCP socket
os_sock: linux.Fd
os_sock, errno = linux.socket(_unwrap_os_family(family_from_endpoint(endpoint)), .STREAM, {}, .TCP)
if errno != .NONE {
// TODO(flysand): should return invalid file descriptor here casted as TCP_Socket
return {}, Create_Socket_Error(errno)
}
// NOTE(tetra): This is so that if we crash while the socket is open, we can
// bypass the cooldown period, and allow the next run of the program to
// use the same address immediately.
_ = set_option(skt, .Reuse_Address, true)
sockaddr := _endpoint_to_sockaddr(endpoint)
res := os.connect(os.Socket(skt), (^os.SOCKADDR)(&sockaddr), size_of(sockaddr))
if res != os.ERROR_NONE {
err = Dial_Error(res)
return
reuse_addr: b32 = true
_ = linux.setsockopt(os_sock, linux.SOL_SOCKET, linux.Socket_Option.REUSEADDR, &reuse_addr)
addr := _unwrap_os_addr(endpoint)
errno = linux.connect(linux.Fd(tcp_sock), &addr)
if errno != .NONE {
return cast(TCP_Socket) os_sock, Dial_Error(errno)
}
if options.no_delay {
_ = _set_option(sock, .TCP_Nodelay, true) // NOTE(tetra): Not vital to succeed; error ignored
}
return
// NOTE(tetra): Not vital to succeed; error ignored
no_delay: b32 = cast(b32) options.no_delay
_ = linux.setsockopt(os_sock, linux.SOL_TCP, linux.Socket_TCP_Option.NODELAY, &no_delay)
return cast(TCP_Socket) os_sock, nil
}
@(private)
_bind :: proc(skt: Any_Socket, ep: Endpoint) -> (err: Network_Error) {
sockaddr := _endpoint_to_sockaddr(ep)
s := any_socket_to_socket(skt)
res := os.bind(os.Socket(s), (^os.SOCKADDR)(&sockaddr), size_of(sockaddr))
if res != os.ERROR_NONE {
err = Bind_Error(res)
_bind :: proc(sock: Any_Socket, endpoint: Endpoint) -> (Network_Error) {
addr := _unwrap_os_addr(endpoint)
errno := linux.bind(_unwrap_os_socket(sock), &addr)
if errno != .NONE {
return Bind_Error(errno)
}
return
return nil
}
@(private)
_listen_tcp :: proc(interface_endpoint: Endpoint, backlog := 1000) -> (skt: TCP_Socket, err: Network_Error) {
_listen_tcp :: proc(endpoint: Endpoint, backlog := 1000) -> (TCP_Socket, Network_Error) {
errno: linux.Errno
assert(backlog > 0 && i32(backlog) < max(i32))
family := family_from_endpoint(interface_endpoint)
sock := create_socket(family, .TCP) or_return
skt = sock.(TCP_Socket)
// Figure out the address family and address of the endpoint
ep_family := _unwrap_os_family(family_from_endpoint(endpoint))
ep_address := _unwrap_os_addr(endpoint)
// Create TCP socket
os_sock: linux.Fd
os_sock, errno = linux.socket(ep_family, .STREAM, {}, .TCP)
if errno != .NONE {
// TODO(flysand): should return invalid file descriptor here casted as TCP_Socket
return {}, Create_Socket_Error(errno)
}
// NOTE(tetra): This is so that if we crash while the socket is open, we can
// bypass the cooldown period, and allow the next run of the program to
// use the same address immediately.
//
// TODO(tetra, 2022-02-15): Confirm that this doesn't mean other processes can hijack the address!
set_option(sock, .Reuse_Address, true) or_return
bind(sock, interface_endpoint) or_return
res := os.listen(os.Socket(skt), backlog)
if res != os.ERROR_NONE {
err = Listen_Error(res)
return
do_reuse_addr: b32 = true
errno = linux.setsockopt(os_sock, linux.SOL_SOCKET, linux.Socket_Option.REUSEADDR, &do_reuse_addr)
if errno != .NONE {
return cast(TCP_Socket) os_sock, Listen_Error(errno)
}
return
// Bind the socket to endpoint address
errno = linux.bind(os_sock, &ep_address)
if errno != .NONE {
return cast(TCP_Socket) os_sock, Bind_Error(errno)
}
// Listen on bound socket
errno = linux.listen(os_sock, cast(i32) backlog)
if errno != .NONE {
return cast(TCP_Socket) os_sock, Listen_Error(errno)
}
return cast(TCP_Socket) os_sock, nil
}
@(private)
_accept_tcp :: proc(sock: TCP_Socket, options := default_tcp_options) -> (client: TCP_Socket, source: Endpoint, err: Network_Error) {
sockaddr: os.SOCKADDR_STORAGE_LH
sockaddrlen := c.int(size_of(sockaddr))
client_sock, ok := os.accept(os.Socket(sock), cast(^os.SOCKADDR) &sockaddr, &sockaddrlen)
if ok != os.ERROR_NONE {
err = Accept_Error(ok)
return
_accept_tcp :: proc(sock: TCP_Socket, options := default_tcp_options) -> (tcp_client: TCP_Socket, endpoint: Endpoint, err: Network_Error) {
addr: linux.Sock_Addr_Any
client_sock, errno := linux.accept(linux.Fd(sock), &addr)
if errno != .NONE {
return {}, {}, Accept_Error(errno)
}
client = TCP_Socket(client_sock)
source = _sockaddr_storage_to_endpoint(&sockaddr)
if options.no_delay {
_ = _set_option(client, .TCP_Nodelay, true) // NOTE(tetra): Not vital to succeed; error ignored
}
return
// NOTE(tetra): Not vital to succeed; error ignored
val: b32 = cast(b32) options.no_delay
_ = linux.setsockopt(client_sock, linux.SOL_TCP, linux.Socket_TCP_Option.NODELAY, &val)
return TCP_Socket(client_sock), _wrap_os_addr(addr), nil
}
@(private)
_close :: proc(skt: Any_Socket) {
s := any_socket_to_socket(skt)
os.close(os.Handle(os.Socket(s)))
_close :: proc(sock: Any_Socket) {
linux.close(_unwrap_os_socket(sock))
}
@(private)
_recv_tcp :: proc(skt: TCP_Socket, buf: []byte) -> (bytes_read: int, err: Network_Error) {
_recv_tcp :: proc(tcp_sock: TCP_Socket, buf: []byte) -> (int, Network_Error) {
if len(buf) <= 0 {
return
return 0, nil
}
res, ok := os.recv(os.Socket(skt), buf, 0)
if ok != os.ERROR_NONE {
err = TCP_Recv_Error(ok)
return
bytes_read, errno := linux.recv(linux.Fd(tcp_sock), buf, {})
if errno != .NONE {
return 0, TCP_Recv_Error(errno)
}
return int(res), nil
return int(bytes_read), nil
}
@(private)
_recv_udp :: proc(skt: UDP_Socket, buf: []byte) -> (bytes_read: int, remote_endpoint: Endpoint, err: Network_Error) {
_recv_udp :: proc(udp_sock: UDP_Socket, buf: []byte) -> (int, Endpoint, Network_Error) {
if len(buf) <= 0 {
return
// NOTE(flysand): It was returning no error, I didn't change anything
return 0, {}, {}
}
from: os.SOCKADDR_STORAGE_LH = ---
fromsize := c.int(size_of(from))
// NOTE(tetra): On Linux, if the buffer is too small to fit the entire datagram payload, the rest is silently discarded,
// and no error is returned.
// However, if you pass MSG_TRUNC here, 'res' will be the size of the incoming message, rather than how much was read.
// We can use this fact to detect this condition and return .Buffer_Too_Small.
res, ok := os.recvfrom(os.Socket(skt), buf, os.MSG_TRUNC, cast(^os.SOCKADDR) &from, &fromsize)
if ok != os.ERROR_NONE {
err = UDP_Recv_Error(ok)
return
from_addr: linux.Sock_Addr_Any
bytes_read, errno := linux.recvfrom(linux.Fd(udp_sock), buf, {.TRUNC}, &from_addr)
if errno != .NONE {
return 0, {}, UDP_Recv_Error(errno)
}
bytes_read = int(res)
remote_endpoint = _sockaddr_storage_to_endpoint(&from)
if bytes_read > len(buf) {
// NOTE(tetra): The buffer has been filled, with a partial message.
bytes_read = len(buf)
err = .Buffer_Too_Small
return len(buf), {}, .Buffer_Too_Small
}
return
return bytes_read, _wrap_os_addr(from_addr), nil
}
@(private)
_send_tcp :: proc(skt: TCP_Socket, buf: []byte) -> (bytes_written: int, err: Network_Error) {
for bytes_written < len(buf) {
limit := min(int(max(i32)), len(buf) - bytes_written)
remaining := buf[bytes_written:][:limit]
res, ok := os.send(os.Socket(skt), remaining, 0)
if ok != os.ERROR_NONE {
err = TCP_Send_Error(ok)
return
_send_tcp :: proc(tcp_sock: TCP_Socket, buf: []byte) -> (int, Network_Error) {
total_written := 0
for total_written < len(buf) {
limit := min(int(max(i32)), len(buf) - total_written)
remaining := buf[total_written:][:limit]
res, errno := linux.send(linux.Fd(tcp_sock), remaining, {})
if errno != .NONE {
return total_written, TCP_Send_Error(errno)
}
bytes_written += int(res)
total_written += int(res)
}
return
return total_written, nil
}
@(private)
_send_udp :: proc(skt: UDP_Socket, buf: []byte, to: Endpoint) -> (bytes_written: int, err: Network_Error) {
toaddr := _endpoint_to_sockaddr(to)
res, os_err := os.sendto(os.Socket(skt), buf, 0, cast(^os.SOCKADDR) &toaddr, size_of(toaddr))
if os_err != os.ERROR_NONE {
err = UDP_Send_Error(os_err)
return
_send_udp :: proc(udp_sock: UDP_Socket, buf: []byte, to: Endpoint) -> (int, Network_Error) {
to_addr := _unwrap_os_addr(to)
bytes_written, errno := linux.sendto(linux.Fd(udp_sock), buf, {}, &to_addr)
if errno != .NONE {
return bytes_written, UDP_Send_Error(errno)
}
bytes_written = int(res)
return
return int(bytes_written), nil
}
@(private)
_shutdown :: proc(skt: Any_Socket, manner: Shutdown_Manner) -> (err: Network_Error) {
s := any_socket_to_socket(skt)
res := os.shutdown(os.Socket(s), int(manner))
if res != os.ERROR_NONE {
return Shutdown_Error(res)
_shutdown :: proc(sock: Any_Socket, manner: Shutdown_Manner) -> (err: Network_Error) {
os_sock := _unwrap_os_socket(sock)
errno := linux.shutdown(os_sock, cast(linux.Shutdown_How) manner)
if errno != .NONE {
return Shutdown_Error(errno)
}
return
return nil
}
// TODO(flysand): Figure out what we want to do with this on core:sys/ level.
@(private)
_set_option :: proc(s: Any_Socket, option: Socket_Option, value: any, loc := #caller_location) -> Network_Error {
level := os.SOL_SOCKET if option != .TCP_Nodelay else os.IPPROTO_TCP
_set_option :: proc(sock: Any_Socket, option: Socket_Option, value: any, loc := #caller_location) -> Network_Error {
level: int
if option == .TCP_Nodelay {
level = int(linux.SOL_TCP)
} else {
level = int(linux.SOL_SOCKET)
}
os_sock := _unwrap_os_socket(sock)
// NOTE(tetra, 2022-02-15): On Linux, you cannot merely give a single byte for a bool;
// it _has_ to be a b32.
// I haven't tested if you can give more than that.
// I haven't tested if you can give more than that. <-- (flysand) probably not, posix explicitly specifies an int
bool_value: b32
int_value: i32
timeval_value: os.Timeval
ptr: rawptr
len: os.socklen_t
timeval_value: linux.Time_Val
errno: linux.Errno
switch option {
case
.Reuse_Address,
@@ -258,7 +311,7 @@ _set_option :: proc(s: Any_Socket, option: Socket_Option, value: any, loc := #ca
.Out_Of_Bounds_Data_Inline,
.TCP_Nodelay:
// TODO: verify whether these are options or not on Linux
// .Broadcast,
// .Broadcast, <-- yes
// .Conditional_Accept,
// .Dont_Linger:
switch x in value {
@@ -274,8 +327,7 @@ _set_option :: proc(s: Any_Socket, option: Socket_Option, value: any, loc := #ca
case:
panic("set_option() value must be a boolean here", loc)
}
ptr = &bool_value
len = size_of(bool_value)
errno = linux.setsockopt(os_sock, level, int(option), &bool_value)
case
.Linger,
.Send_Timeout,
@@ -283,125 +335,49 @@ _set_option :: proc(s: Any_Socket, option: Socket_Option, value: any, loc := #ca
t, ok := value.(time.Duration)
if !ok do panic("set_option() value must be a time.Duration here", loc)
micros := i64(time.duration_microseconds(t))
timeval_value.microseconds = int(micros % 1e6)
timeval_value.seconds = (micros - i64(timeval_value.microseconds)) / 1e6
ptr = &timeval_value
len = size_of(timeval_value)
micros := cast(i64) (time.duration_microseconds(t))
timeval_value.microseconds = cast(int) (micros % 1e6)
timeval_value.seconds = cast(int) ((micros - i64(timeval_value.microseconds)) / 1e6)
errno = linux.setsockopt(os_sock, level, int(option), &timeval_value)
case
.Receive_Buffer_Size,
.Send_Buffer_Size:
// TODO: check for out of range values and return .Value_Out_Of_Range?
switch i in value {
case i8, u8: i2 := i; int_value = os.socklen_t((^u8)(&i2)^)
case i16, u16: i2 := i; int_value = os.socklen_t((^u16)(&i2)^)
case i32, u32: i2 := i; int_value = os.socklen_t((^u32)(&i2)^)
case i64, u64: i2 := i; int_value = os.socklen_t((^u64)(&i2)^)
case i128, u128: i2 := i; int_value = os.socklen_t((^u128)(&i2)^)
case int, uint: i2 := i; int_value = os.socklen_t((^uint)(&i2)^)
case i8, u8: i2 := i; int_value = i32((^u8)(&i2)^)
case i16, u16: i2 := i; int_value = i32((^u16)(&i2)^)
case i32, u32: i2 := i; int_value = i32((^u32)(&i2)^)
case i64, u64: i2 := i; int_value = i32((^u64)(&i2)^)
case i128, u128: i2 := i; int_value = i32((^u128)(&i2)^)
case int, uint: i2 := i; int_value = i32((^uint)(&i2)^)
case:
panic("set_option() value must be an integer here", loc)
}
ptr = &int_value
len = size_of(int_value)
errno = linux.setsockopt(os_sock, level, int(option), &int_value)
}
skt := any_socket_to_socket(s)
res := os.setsockopt(os.Socket(skt), int(level), int(option), ptr, len)
if res != os.ERROR_NONE {
return Socket_Option_Error(res)
if errno != .NONE {
return Socket_Option_Error(errno)
}
return nil
}
@(private)
_set_blocking :: proc(socket: Any_Socket, should_block: bool) -> (err: Network_Error) {
socket := any_socket_to_socket(socket)
flags, getfl_err := os.fcntl(int(socket), os.F_GETFL, 0)
if getfl_err != os.ERROR_NONE {
return Set_Blocking_Error(getfl_err)
_set_blocking :: proc(sock: Any_Socket, should_block: bool) -> (err: Network_Error) {
errno: linux.Errno
flags: linux.Open_Flags
os_sock := _unwrap_os_socket(sock)
flags, errno = linux.fcntl(os_sock, linux.F_GETFL)
if errno != .NONE {
return Set_Blocking_Error(errno)
}
if should_block {
flags &= ~int(os.O_NONBLOCK)
flags &= ~{.NONBLOCK}
} else {
flags |= int(os.O_NONBLOCK)
flags |= {.NONBLOCK}
}
_, setfl_err := os.fcntl(int(socket), os.F_SETFL, flags)
if setfl_err != os.ERROR_NONE {
return Set_Blocking_Error(setfl_err)
errno = linux.fcntl(os_sock, linux.F_SETFL, flags)
if errno != .NONE {
return Set_Blocking_Error(errno)
}
return nil
}
@(private)
_endpoint_to_sockaddr :: proc(ep: Endpoint) -> (sockaddr: os.SOCKADDR_STORAGE_LH) {
switch a in ep.address {
case IP4_Address:
(^os.sockaddr_in)(&sockaddr)^ = os.sockaddr_in {
sin_port = u16be(ep.port),
sin_addr = transmute(os.in_addr) a,
sin_family = u16(os.AF_INET),
}
return
case IP6_Address:
(^os.sockaddr_in6)(&sockaddr)^ = os.sockaddr_in6 {
sin6_port = u16be(ep.port),
sin6_addr = transmute(os.in6_addr) a,
sin6_family = u16(os.AF_INET6),
}
return
}
unreachable()
}
@(private)
_sockaddr_storage_to_endpoint :: proc(native_addr: ^os.SOCKADDR_STORAGE_LH) -> (ep: Endpoint) {
switch native_addr.ss_family {
case u16(os.AF_INET):
addr := cast(^os.sockaddr_in) native_addr
port := int(addr.sin_port)
ep = Endpoint {
address = IP4_Address(transmute([4]byte) addr.sin_addr),
port = port,
}
case u16(os.AF_INET6):
addr := cast(^os.sockaddr_in6) native_addr
port := int(addr.sin6_port)
ep = Endpoint {
address = IP6_Address(transmute([8]u16be) addr.sin6_addr),
port = port,
}
case:
panic("native_addr is neither IP4 or IP6 address")
}
return
}
@(private)
_sockaddr_basic_to_endpoint :: proc(native_addr: ^os.SOCKADDR) -> (ep: Endpoint) {
switch native_addr.sa_family {
case u16(os.AF_INET):
addr := cast(^os.sockaddr_in) native_addr
port := int(addr.sin_port)
ep = Endpoint {
address = IP4_Address(transmute([4]byte) addr.sin_addr),
port = port,
}
case u16(os.AF_INET6):
addr := cast(^os.sockaddr_in6) native_addr
port := int(addr.sin6_port)
ep = Endpoint {
address = IP6_Address(transmute([8]u16be) addr.sin6_addr),
port = port,
}
case:
panic("native_addr is neither IP4 or IP6 address")
}
return
}
+1 -1
View File
@@ -724,7 +724,7 @@ scan :: proc(t: ^Tokenizer) -> Token {
case .Ident, .Context, .Typeid, .Break, .Continue, .Fallthrough, .Return,
.Integer, .Float, .Imag, .Rune, .String, .Undef,
.Question, .Pointer, .Close_Paren, .Close_Bracket, .Close_Brace,
.Increment, .Decrement, .Or_Return:
.Increment, .Decrement, .Or_Return, .Or_Break, .Or_Continue:
/*fallthrough*/
t.insert_semicolon = true
case:
+2 -2
View File
@@ -63,8 +63,8 @@ read_at_least :: proc(fd: Handle, buf: []byte, min: int) -> (n: int, err: Errno)
if len(buf) < min {
return 0, -1
}
for n < min && err == 0 {
nn: int
nn := max(int)
for nn > 0 && n < min && err == 0 {
nn, err = read(fd, buf[n:])
n += nn
}
+27
View File
@@ -354,6 +354,30 @@ in6_addr :: struct #packed {
s6_addr: [16]u8,
}
SIOCGIFFLAG :: enum c.int {
UP = 0, /* Interface is up. */
BROADCAST = 1, /* Broadcast address valid. */
DEBUG = 2, /* Turn on debugging. */
LOOPBACK = 3, /* Is a loopback net. */
POINT_TO_POINT = 4, /* Interface is point-to-point link. */
NO_TRAILERS = 5, /* Avoid use of trailers. */
RUNNING = 6, /* Resources allocated. */
NOARP = 7, /* No address resolution protocol. */
PROMISC = 8, /* Receive all packets. */
ALL_MULTI = 9, /* Receive all multicast packets. Unimplemented. */
}
SIOCGIFFLAGS :: bit_set[SIOCGIFFLAG; c.int]
ifaddrs :: struct {
next: ^ifaddrs,
name: cstring,
flags: SIOCGIFFLAGS,
address: ^SOCKADDR,
netmask: ^SOCKADDR,
broadcast_or_dest: ^SOCKADDR, // Broadcast or Point-to-Point address
data: rawptr, // Address-specific data.
}
Timeval :: struct {
seconds: i64,
microseconds: int,
@@ -474,6 +498,9 @@ foreign libc {
@(link_name="send") _unix_send :: proc(socket: int, buffer: rawptr, buffer_len: c.size_t, flags: int) -> c.ssize_t ---
@(link_name="shutdown") _unix_shutdown :: proc(socket: int, how: int) -> int ---
@(link_name="getifaddrs") _getifaddrs :: proc(ifap: ^^ifaddrs) -> (c.int) ---
@(link_name="freeifaddrs") _freeifaddrs :: proc(ifa: ^ifaddrs) ---
@(link_name="exit") _unix_exit :: proc(status: c.int) -> ! ---
}
+12 -1
View File
@@ -8,7 +8,18 @@ import "core:strings"
import "core:c"
import "core:strconv"
import "core:intrinsics"
import "core:sys/unix"
// NOTE(flysand): For compatibility we'll make core:os package
// depend on the old (scheduled for removal) linux package.
// Seeing that there are plans for os2, I'm imagining that *that*
// package should inherit the new sys functionality.
// The reasons for these are as follows:
// 1. It's very hard to update this package without breaking *a lot* of code.
// 2. os2 is not stable anyways, so we can break compatibility all we want
// It might be weird to bring up compatibility when Odin in it's nature isn't
// all that about compatibility. But we don't want to push experimental changes
// and have people's code break while it's still work in progress.
import unix "core:sys/unix"
Handle :: distinct i32
Pid :: distinct i32
+3 -3
View File
@@ -159,9 +159,9 @@ join :: proc(elems: []string, allocator := context.allocator) -> string {
return ""
}
// ext returns the file name extension used by "path"
// The extension is the suffix beginning at the file fot in the last slash separated element of "path"
// The path is empty if there is no dot
// ext returns the file name extension used by "path".
// The extension is the suffix beginning at the dot character in the last slash separated element of "path".
// The path is empty if there is no dot character.
ext :: proc(path: string, new := false, allocator := context.allocator) -> string {
for i := len(path)-1; i >= 0 && !is_separator(path[i]); i -= 1 {
if path[i] == '.' {
+4 -2
View File
@@ -664,8 +664,10 @@ default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code
when ODIN_OS == .Freestanding {
// Do nothing
} else {
print_caller_location(loc)
print_string(" ")
when !ODIN_DISABLE_ASSERT {
print_caller_location(loc)
print_string(" ")
}
print_string(prefix)
if len(message) > 0 {
print_string(": ")
-2
View File
@@ -817,7 +817,6 @@ assert :: proc(condition: bool, message := "", loc := #caller_location) {
}
@builtin
@(disabled=ODIN_DISABLE_ASSERT)
panic :: proc(message: string, loc := #caller_location) -> ! {
p := context.assertion_failure_proc
if p == nil {
@@ -827,7 +826,6 @@ panic :: proc(message: string, loc := #caller_location) -> ! {
}
@builtin
@(disabled=ODIN_DISABLE_ASSERT)
unimplemented :: proc(message := "", loc := #caller_location) -> ! {
p := context.assertion_failure_proc
if p == nil {
+13
View File
@@ -413,3 +413,16 @@ delete_soa :: proc{
delete_soa_slice,
delete_soa_dynamic_array,
}
clear_soa_dynamic_array :: proc(array: ^$T/#soa[dynamic]$E) {
when intrinsics.type_struct_field_count(E) != 0 {
footer := raw_soa_footer(array)
footer.len = 0
}
}
@builtin
clear_soa :: proc{
clear_soa_dynamic_array,
}
+179
View File
@@ -0,0 +1,179 @@
package runtime
/*
package runtime has numerous entities (declarations) which are required by the compiler to function.
## Basic types and calls (and anything they rely on)
Source_Code_Location
Context
Allocator
Logger
__init_context
_cleanup_runtime
## cstring calls
cstring_to_string
cstring_len
## Required when RTTI is enabled (the vast majority of targets)
Type_Info
type_table
__type_info_of
## Hashing
default_hasher
default_hasher_cstring
default_hasher_string
## Pseudo-CRT required procedured due to LLVM but useful in general
memset
memcpy
memove
## Procedures required by the LLVM backend
umodti3
udivti3
modti3
divti3
fixdfti
fixunsdfti
fixunsdfdi
floattidf
floattidf_unsigned
truncsfhf2
truncdfhf2
gnu_h2f_ieee
gnu_f2h_ieee
extendhfsf2
__ashlti3 // wasm specific
__multi3 // wasm specific
## Required an entry point is defined (i.e. 'main')
args__
## When -no-crt is defined (and not a wasm target) (mostly due to LLVM)
_tls_index
_fltused
## Bounds checking procedures (when not disabled with -no-bounds-check)
bounds_check_error
matrix_bounds_check_error
slice_expr_error_hi
slice_expr_error_lo_hi
multi_pointer_slice_expr_error
## Type assertion check
type_assertion_check
type_assertion_check2 // takes in typeid
## Arithmetic
quo_complex32
quo_complex64
quo_complex128
mul_quaternion64
mul_quaternion128
mul_quaternion256
quo_quaternion64
quo_quaternion128
quo_quaternion256
abs_complex32
abs_complex64
abs_complex128
abs_quaternion64
abs_quaternion128
abs_quaternion256
## Comparison
memory_equal
memory_compare
memory_compare_zero
cstring_eq
cstring_ne
cstring_lt
cstring_gt
cstring_le
cstring_gt
string_eq
string_ne
string_lt
string_gt
string_le
string_gt
complex32_eq
complex32_ne
complex64_eq
complex64_ne
complex128_eq
complex128_ne
quaternion64_eq
quaternion64_ne
quaternion128_eq
quaternion128_ne
quaternion256_eq
quaternion256_ne
## Map specific calls
map_seed_from_map_data
__dynamic_map_check_grow // static map calls
map_insert_hash_dynamic // static map calls
__dynamic_map_get // dynamic map calls
__dynamic_map_set // dynamic map calls
## Dynamic literals ([dymamic]T and map[K]V) (can be disabled with -no-dynamic-literals)
__dynamic_array_reserve
__dynamic_array_append
__dynamic_map_reserve
## Objective-C specific
objc_lookUpClass
sel_registerName
objc_allocateClassPair
## for-in `string` type
string_decode_rune
string_decode_last_rune // #reverse for
*/
+3 -3
View File
@@ -629,7 +629,7 @@ map_reserve_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_
@(require_results)
map_shrink_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, loc := #caller_location) -> Allocator_Error {
map_shrink_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, loc := #caller_location) -> (did_shrink: bool, err: Allocator_Error) {
if m.allocator.procedure == nil {
m.allocator = context.allocator
}
@@ -639,7 +639,7 @@ map_shrink_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_I
// map needs to be within the max load factor.
log2_capacity := map_log2_cap(m^)
if uintptr(m.len) >= map_load_factor(log2_capacity - 1) {
return nil
return false, nil
}
shrunk := map_alloc_dynamic(info, log2_capacity - 1, m.allocator) or_return
@@ -672,7 +672,7 @@ map_shrink_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_I
map_free_dynamic(m^, info, loc) or_return
m.data = shrunk.data
return nil
return true, nil
}
@(require_results)
+32 -8
View File
@@ -21,13 +21,37 @@ when ODIN_BUILD_MODE == .Dynamic {
return 0
}
} else when !ODIN_TEST && !ODIN_NO_ENTRY_POINT {
@(link_name="main", linkage="strong", require)
main :: proc "c" (argc: i32, argv: [^]cstring) -> i32 {
args__ = argv[:argc]
context = default_context()
#force_no_inline _startup_runtime()
intrinsics.__entry_point()
#force_no_inline _cleanup_runtime()
return 0
when ODIN_NO_CRT {
// NOTE(flysand): We need to start from assembly because we need
// to retrieve argc and argv from the stack
when ODIN_ARCH == .amd64 {
@require foreign import entry "entry_unix_no_crt_amd64.asm"
} else when ODIN_ARCH == .i386 {
@require foreign import entry "entry_unix_no_crt_i386.asm"
}
@(link_name="_start_odin", linkage="strong", require)
_start_odin :: proc "c" (argc: i32, argv: [^]cstring) -> ! {
args__ = argv[:argc]
context = default_context()
#force_no_inline _startup_runtime()
intrinsics.__entry_point()
#force_no_inline _cleanup_runtime()
when ODIN_ARCH == .amd64 {
intrinsics.syscall(/*SYS_exit = */60)
} else when ODIN_ARCH == .i386 {
intrinsics.syscall(/*SYS_exit = */1)
}
unreachable()
}
} else {
@(link_name="main", linkage="strong", require)
main :: proc "c" (argc: i32, argv: [^]cstring) -> i32 {
args__ = argv[:argc]
context = default_context()
#force_no_inline _startup_runtime()
intrinsics.__entry_point()
#force_no_inline _cleanup_runtime()
return 0
}
}
}
+43
View File
@@ -0,0 +1,43 @@
bits 64
extern _start_odin
global _start
section .text
;; Entry point for programs that specify -no-crt option
;; This entry point should be compatible with dynamic loaders on linux
;; The parameters the dynamic loader passes to the _start function:
;; RDX = pointer to atexit function
;; The stack layout is as follows:
;; +-------------------+
;; NULL
;; +-------------------+
;; envp[m]
;; +-------------------+
;; ...
;; +-------------------+
;; envp[0]
;; +-------------------+
;; NULL
;; +-------------------+
;; argv[n]
;; +-------------------+
;; ...
;; +-------------------+
;; argv[0]
;; +-------------------+
;; argc
;; +-------------------+ <------ RSP
;;
_start:
;; Mark stack frame as the top of the stack
xor rbp, rbp
;; Load argc into 1st param reg, argv into 2nd param reg
pop rdi
mov rdx, rsi
;; Align stack pointer down to 16-bytes (sysv calling convention)
and rsp, -16
;; Call into odin entry point
call _start_odin
jmp $$
+18
View File
@@ -0,0 +1,18 @@
bits 32
extern _start_odin
global _start
section .text
;; NOTE(flysand): For description see the corresponding *_amd64.asm file
;; also I didn't test this on x86-32
_start:
xor ebp, rbp
pop ecx
mov eax, esp
and esp, -16
push eax
push ecx
call _start_odin
jmp $$
+69 -3
View File
@@ -1,3 +1,5 @@
bits 64
global __chkstk
global _tls_index
global _fltused
@@ -5,9 +7,73 @@ global _fltused
section .data
_tls_index: dd 0
_fltused: dd 0x9875
section .text
__chkstk: ; proc "c" (rawptr)
; TODO implement correctly
; NOTE(flysand): The function call to __chkstk is called
; by the compiler, when we're allocating arrays larger than
; a page size. The reason is because the OS doesn't map the
; whole stack into memory all at once, but does so page-by-page.
; When the next page is touched, the CPU generates a page fault,
; which *the OS* is handling by allocating the next page in the
; stack until we reach the limit of stack size.
;
; This page is called the guard page, touching it will extend
; the size of the stack and overwrite the stack limit in the TEB.
;
; If we allocate a large enough array and start writing from the
; bottom of it, it's possible that we may start touching
; non-contiguous pages which are unmapped. OS only maps the stack
; page into the memory if the page above it was also mapped.
;
; Therefore the compilers insert this routine, the sole purpose
; of which is to step through the stack starting from the RSP
; down to the new RSP after allocation, and touch every page
; of the new allocation so that the stack is fully mapped for
; the new allocation
;
; I've gotten this code by disassembling the output of MSVC long
; time ago. I don't remember if I've cleaned it up, but it definately
; stinks.
;
; Additional notes:
; RAX (passed as parameter) holds the allocation's size
; GS:[0x10] references the current stack limit
; (i.e. bottom of the stack (i.e. lowest address accessible))
;
; Also this stuff is windows-only kind of thing, because linux people
; didn't think stack that grows is cool enough for them, but the kernel
; totally supports this kind of stack.
__chkstk:
;; Allocate 16 bytes to store values of r10 and r11
sub rsp, 0x10
mov [rsp], r10
mov [rsp+0x8], r11
;; Set r10 to point to the stack as of the moment of the function call
lea r10, [rsp+0x18]
;; Subtract r10 til the bottom of the stack allocation, if we overflow
;; reset r10 to 0, we'll crash with segfault anyway
xor r11, r11
sub r10, rax
cmovb r10, r11
;; Load r11 with the bottom of the stack (lowest allocated address)
mov r11, gs:[0x10] ; NOTE(flysand): gs:[0x10] is stack limit
;; If the bottom of the allocation is above the bottom of the stack,
;; we don't need to probe
cmp r10, r11
jnb .end
;; Align the bottom of the allocation down to page size
and r10w, 0xf000
.loop:
;; Move the pointer to the next guard page, and touch it by loading 0
;; into that page
lea r11, [r11-0x1000]
mov byte [r11], 0x0
;; Did we reach the bottom of the allocation?
cmp r10, r11
jnz .loop
.end:
;; Restore previous r10 and r11 and return
mov r10, [rsp]
mov r11, [rsp+0x8]
add rsp, 0x10
ret
+4 -4
View File
@@ -126,19 +126,19 @@ _mm_max_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
@(require_results, enable_target_feature="sse")
_mm_and_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return transmute(__m128)simd.and(transmute(__m128i)a, transmute(__m128i)b)
return transmute(__m128)simd.bit_and(transmute(__m128i)a, transmute(__m128i)b)
}
@(require_results, enable_target_feature="sse")
_mm_andnot_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return transmute(__m128)simd.and_not(transmute(__m128i)a, transmute(__m128i)b)
return transmute(__m128)simd.bit_and_not(transmute(__m128i)a, transmute(__m128i)b)
}
@(require_results, enable_target_feature="sse")
_mm_or_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return transmute(__m128)simd.or(transmute(__m128i)a, transmute(__m128i)b)
return transmute(__m128)simd.bit_or(transmute(__m128i)a, transmute(__m128i)b)
}
@(require_results, enable_target_feature="sse")
_mm_xor_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return transmute(__m128)simd.xor(transmute(__m128i)a, transmute(__m128i)b)
return transmute(__m128)simd.bit_xor(transmute(__m128i)a, transmute(__m128i)b)
}
+4 -4
View File
@@ -281,19 +281,19 @@ _mm_srl_epi64 :: #force_inline proc "c" (a, count: __m128i) -> __m128i {
@(require_results, enable_target_feature="sse2")
_mm_and_si128 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
return simd.and(a, b)
return simd.bit_and(a, b)
}
@(require_results, enable_target_feature="sse2")
_mm_andnot_si128 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
return simd.and_not(b, a)
return simd.bit_and_not(b, a)
}
@(require_results, enable_target_feature="sse2")
_mm_or_si128 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
return simd.or(a, b)
return simd.bit_or(a, b)
}
@(require_results, enable_target_feature="sse2")
_mm_xor_si128 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
return simd.xor(a, b)
return simd.bit_xor(a, b)
}
@(require_results, enable_target_feature="sse2")
_mm_cmpeq_epi8 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
+4 -4
View File
@@ -274,16 +274,16 @@ concatenate :: proc(a: []$T/[]$E, allocator := context.allocator) -> (res: T, er
// copies a slice into a new slice
@(require_results)
clone :: proc(a: $T/[]$E, allocator := context.allocator) -> ([]E, runtime.Allocator_Error) #optional_allocator_error {
d, err := make([]E, len(a), allocator)
clone :: proc(a: $T/[]$E, allocator := context.allocator, loc := #caller_location) -> ([]E, runtime.Allocator_Error) #optional_allocator_error {
d, err := make([]E, len(a), allocator, loc)
copy(d[:], a)
return d, err
}
// copies slice into a new dynamic array
clone_to_dynamic :: proc(a: $T/[]$E, allocator := context.allocator) -> ([dynamic]E, runtime.Allocator_Error) #optional_allocator_error {
d, err := make([dynamic]E, len(a), allocator)
clone_to_dynamic :: proc(a: $T/[]$E, allocator := context.allocator, loc := #caller_location) -> ([dynamic]E, runtime.Allocator_Error) #optional_allocator_error {
d, err := make([dynamic]E, len(a), allocator, loc)
copy(d[:], a)
return d, err
}
+32 -67
View File
@@ -2,95 +2,60 @@
//+build linux
package sync
import "core:c"
import "core:time"
import "core:intrinsics"
import "core:sys/unix"
import "core:sys/linux"
FUTEX_WAIT :: 0
FUTEX_WAKE :: 1
FUTEX_PRIVATE_FLAG :: 128
FUTEX_WAIT_PRIVATE :: (FUTEX_WAIT | FUTEX_PRIVATE_FLAG)
FUTEX_WAKE_PRIVATE :: (FUTEX_WAKE | FUTEX_PRIVATE_FLAG)
ESUCCESS :: 0
EINTR :: -4
EAGAIN :: -11
EFAULT :: -14
EINVAL :: -22
ETIMEDOUT :: -110
get_errno :: proc "contextless" (r: int) -> int {
if -4096 < r && r < 0 {
return r
}
return 0
}
internal_futex :: proc "contextless" (f: ^Futex, op: c.int, val: u32, timeout: rawptr) -> int {
code := int(intrinsics.syscall(unix.SYS_futex, uintptr(f), uintptr(op), uintptr(val), uintptr(timeout), 0, 0))
return get_errno(code)
}
_futex_wait :: proc "contextless" (f: ^Futex, expected: u32) -> bool {
err := internal_futex(f, FUTEX_WAIT_PRIVATE | FUTEX_WAIT, expected, nil)
switch err {
case ESUCCESS, EINTR, EAGAIN, EINVAL:
// okay
case ETIMEDOUT:
_futex_wait :: proc "contextless" (futex: ^Futex, expected: u32) -> bool {
errno := linux.futex(cast(^linux.Futex) futex, linux.FUTEX_WAIT, {.PRIVATE}, expected)
if errno == .ETIMEDOUT {
return false
case EFAULT:
fallthrough
}
#partial switch errno {
case .NONE, .EINTR, .EAGAIN:
return true
case:
// TODO(flysand): More descriptive panic messages based on the vlaue of `errno`
_panic("futex_wait failure")
}
return true
}
_futex_wait_with_timeout :: proc "contextless" (f: ^Futex, expected: u32, duration: time.Duration) -> bool {
_futex_wait_with_timeout :: proc "contextless" (futex: ^Futex, expected: u32, duration: time.Duration) -> bool {
if duration <= 0 {
return false
}
timespec_t :: struct {
tv_sec: c.long,
tv_nsec: c.long,
}
err := internal_futex(f, FUTEX_WAIT_PRIVATE | FUTEX_WAIT, expected, &timespec_t{
tv_sec = (c.long)(duration/1e9),
tv_nsec = (c.long)(duration%1e9),
errno := linux.futex(cast(^linux.Futex) futex, linux.FUTEX_WAIT, {.PRIVATE}, expected, &linux.Time_Spec{
time_sec = cast(uint)(duration/1e9),
time_nsec = cast(uint)(duration%1e9),
})
switch err {
case ESUCCESS, EINTR, EAGAIN, EINVAL:
// okay
case ETIMEDOUT:
if errno == .ETIMEDOUT {
return false
case EFAULT:
fallthrough
}
#partial switch errno {
case .NONE, .EINTR, .EAGAIN:
return true
case:
_panic("futex_wait_with_timeout failure")
}
return true
}
_futex_signal :: proc "contextless" (f: ^Futex) {
err := internal_futex(f, FUTEX_WAKE_PRIVATE | FUTEX_WAKE, 1, nil)
switch err {
case ESUCCESS, EINVAL, EFAULT:
// okay
_futex_signal :: proc "contextless" (futex: ^Futex) {
_, errno := linux.futex(cast(^linux.Futex) futex, linux.FUTEX_WAKE, {.PRIVATE}, 1)
#partial switch errno {
case .NONE:
return
case:
_panic("futex_wake_single failure")
}
}
_futex_broadcast :: proc "contextless" (f: ^Futex) {
err := internal_futex(f, FUTEX_WAKE_PRIVATE | FUTEX_WAKE, u32(max(i32)), nil)
switch err {
case ESUCCESS, EINVAL, EFAULT:
// okay
_futex_broadcast :: proc "contextless" (futex: ^Futex) {
// NOTE(flysand): This code was kinda funny and I don't want to remove it, but here I will
// record history of what has been in here before
// FUTEX_WAKE_PRIVATE | FUTEX_WAKE
_, errno := linux.futex(cast(^linux.Futex) futex, linux.FUTEX_WAKE, {.PRIVATE}, max(i32))
#partial switch errno {
case .NONE:
return
case:
_panic("_futex_wake_all failure")
}
+2 -2
View File
@@ -2,8 +2,8 @@
//+private
package sync
import "core:sys/unix"
import "core:sys/linux"
_current_thread_id :: proc "contextless" () -> int {
return unix.sys_gettid()
return cast(int) linux.gettid()
}
+23 -75
View File
@@ -1,40 +1,34 @@
// +build linux
package sysinfo
import "core:c"
import sys "core:sys/unix"
import "core:intrinsics"
import "core:runtime"
import "core:os"
import "core:strings"
import "core:strconv"
import "core:sys/linux"
@(private)
version_string_buf: [1024]u8
@(init, private)
init_os_version :: proc () {
os_version.platform = .Linux
// Try to parse `/etc/os-release` for `PRETTY_NAME="Ubuntu 20.04.3 LTS`
fd, err := os.open("/etc/os-release", os.O_RDONLY, 0)
if err != 0 {
return
fd, errno := linux.open("/etc/os-release", {.RDONLY}, {})
assert(errno == .NONE, "Failed to read /etc/os-release")
defer {
errno := linux.close(fd)
assert(errno == .NONE, "Failed to close the file descriptor")
}
defer os.close(fd)
os_release_buf: [2048]u8
n, read_err := os.read(fd, os_release_buf[:])
if read_err != 0 {
return
}
n, read_errno := linux.read(fd, os_release_buf[:])
assert(read_errno == .NONE, "Failed to read data from /etc/os-release")
release := string(os_release_buf[:n])
// Search the line in the file until we find "PRETTY_NAME="
NEEDLE :: "PRETTY_NAME=\""
pretty_start := strings.index(release, NEEDLE)
b := strings.builder_from_bytes(version_string_buf[:])
if pretty_start > 0 {
for r, i in release[pretty_start + len(NEEDLE):] {
if r == '"' {
@@ -46,94 +40,48 @@ init_os_version :: proc () {
}
}
}
NEW_UTS_LEN :: 64
UTS_Name :: struct {
sys_name: [NEW_UTS_LEN + 1]u8 `fmt:"s,0"`,
node_name: [NEW_UTS_LEN + 1]u8 `fmt:"s,0"`,
release: [NEW_UTS_LEN + 1]u8 `fmt:"s,0"`,
version: [NEW_UTS_LEN + 1]u8 `fmt:"s,0"`,
machine: [NEW_UTS_LEN + 1]u8 `fmt:"s,0"`,
domain_name: [NEW_UTS_LEN + 1]u8 `fmt:"s,0"`,
}
uts: UTS_Name
// Grab kernel info using `uname()` syscall, https://linux.die.net/man/2/uname
if intrinsics.syscall(sys.SYS_uname, uintptr(&uts)) != 0 {
return
}
uts: linux.UTS_Name
uname_errno := linux.uname(&uts)
assert(uname_errno == .NONE, "This should never happen!")
// Append the system name (typically "Linux") and kernel release (looks like 6.5.2-arch1-1)
strings.write_string(&b, ", ")
strings.write_string(&b, string(cstring(&uts.sys_name[0])))
strings.write_string(&b, string(cstring(&uts.sysname[0])))
strings.write_rune(&b, ' ')
l := strings.builder_len(b)
strings.write_string(&b, string(cstring(&uts.release[0])))
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
// Parse kernel version, as substrings of the version info in `version_string_buf`
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
version_bits := strings.split_n(strings.to_string(b)[l:], "-", 2, context.temp_allocator)
if len(version_bits) > 1 {
os_version.version = version_bits[1]
}
// Parse major, minor, patch from release info
triplet := strings.split(version_bits[0], ".", context.temp_allocator)
if len(triplet) == 3 {
major, major_ok := strconv.parse_int(triplet[0])
minor, minor_ok := strconv.parse_int(triplet[1])
patch, patch_ok := strconv.parse_int(triplet[2])
if major_ok && minor_ok && patch_ok {
os_version.major = major
os_version.minor = minor
os_version.patch = patch
}
}
// Finish the string
os_version.as_string = strings.to_string(b)
}
Sys_Info :: struct {
uptime: c.long, // Seconds since boot
loads: [3]c.long, // 1, 5, 15 minute load averages
totalram: c.ulong, // Total usable main memory size
freeram: c.ulong, // Available memory size
sharedram: c.ulong, // Amount of shared memory
bufferram: c.ulong, // Memory used by buffers
totalswap: c.ulong, // Total swap space size
freeswap: c.ulong, // Swap space still available
procs: c.ushort, // Number of current processes
totalhigh: c.ulong, // Total high memory size
freehigh: c.ulong, // Available high memory size
mem_unit: c.int, // Memory unit size in bytes
_padding: [20 - (2 * size_of(c.long)) - size_of(c.int)]u8,
}
get_sysinfo :: proc "c" () -> (res: Sys_Info, ok: bool) {
si: Sys_Info
err := intrinsics.syscall(sys.SYS_sysinfo, uintptr(rawptr(&si)))
if err != 0 {
// Unable to retrieve sysinfo
return {}, false
}
return si, true
}
@(init)
init_ram :: proc() {
// Retrieve RAM info using `sysinfo`
si, ok := get_sysinfo()
if !ok {
return
}
sys_info: linux.Sys_Info
errno := linux.sysinfo(&sys_info)
assert(errno == .NONE, "Good luck to whoever's debugging this, something's seriously cucked up!")
ram = RAM{
total_ram = int(si.totalram) * int(si.mem_unit),
free_ram = int(si.freeram) * int(si.mem_unit),
total_swap = int(si.totalswap) * int(si.mem_unit),
free_swap = int(si.freeswap) * int(si.mem_unit),
total_ram = int(sys_info.totalram) * int(sys_info.mem_unit),
free_ram = int(sys_info.freeram) * int(sys_info.mem_unit),
total_swap = int(sys_info.totalswap) * int(sys_info.mem_unit),
free_swap = int(sys_info.freeswap) * int(sys_info.mem_unit),
}
}
File diff suppressed because it is too large Load Diff
+199
View File
@@ -0,0 +1,199 @@
package linux
/// Special file descriptor to pass to `*at` functions to specify
/// that relative paths are relative to current directory
AT_FDCWD :: Fd(-100)
/// Special value to put into timespec for utimensat() to set timestamp to the current time
UTIME_NOW :: uint((1 << 30) - 1)
/// Special value to put into the timespec for utimensat() to leave the corresponding field of the timestamp unchanged
UTIME_OMIT :: uint((1 << 30) - 2)
/// For wait4: Pass this pid to wait for any process
WAIT_ANY :: Pid(-1)
/// For wait4: Pass this pid to wait for any process in current process group
WAIT_MYPGRP :: Pid(0)
/// Maximum priority (aka nice value) for the process
PRIO_MAX :: 20
/// Minimum priority (aka nice value) for the process
PRIO_MIN :: -20
SIGRTMIN :: Signal(32)
SIGRTMAX :: Signal(64)
S_IFMT :: Mode{.IFREG, .IFDIR, .IFCHR, .IFFIFO}
S_IFSOCK :: Mode{.IFREG, .IFDIR}
S_IFLNK :: Mode{.IFREG, .IFCHR}
S_IFBLK :: Mode{.IFDIR, .IFCHR}
S_IFFIFO :: Mode{.IFFIFO}
S_IFCHR :: Mode{.IFCHR}
S_IFDIR :: Mode{.IFDIR}
S_IFREG :: Mode{.IFREG}
/// Checks the Mode bits to see if the file is a named pipe (FIFO)
S_ISFIFO :: #force_inline proc "contextless" (m: Mode) -> bool {return (S_IFFIFO == (m & S_IFMT))}
/// Check the Mode bits to see if the file is a character device
S_ISCHR :: #force_inline proc "contextless" (m: Mode) -> bool {return (S_IFCHR == (m & S_IFMT))}
/// Check the Mode bits to see if the file is a directory
S_ISDIR :: #force_inline proc "contextless" (m: Mode) -> bool {return (S_IFDIR == (m & S_IFMT))}
/// Check the Mode bits to see if the file is a register
S_ISREG :: #force_inline proc "contextless" (m: Mode) -> bool {return (S_IFREG == (m & S_IFMT))}
/// Check the Mode bits to see if the file is a socket
S_ISSOCK :: #force_inline proc "contextless" (m: Mode) -> bool {return (S_IFSOCK == (m & S_IFMT))}
/// Check the Mode bits to see if the file is a symlink
S_ISLNK :: #force_inline proc "contextless" (m: Mode) -> bool {return (S_IFLNK == (m & S_IFMT))}
/// Check the Mode bits to see if the file is a block device
S_ISBLK :: #force_inline proc "contextless" (m: Mode) -> bool {return (S_IFBLK == (m & S_IFMT))}
/// For access.2 syscall family: instruct to check if the file exists
F_OK :: Mode{}
/// For access.2 syscall family: instruct to check if the file is executable
X_OK :: Mode{.IXOTH}
/// For access.2 syscall family: instruct to check if the file is writeable
W_OK :: Mode{.IWOTH}
/// For access.2 syscall family: instruct to check if the file is readable
R_OK :: Mode{.IROTH}
/// The stats you get by calling `stat`
STATX_BASIC_STATS :: Statx_Mask {
.TYPE,
.MODE,
.NLINK,
.UID,
.GID,
.ATIME,
.MTIME,
.CTIME,
.INO,
.SIZE,
.BLOCKS,
}
FCntl_Command_DUPFD :: distinct FCntl_Command
FCntl_Command_GETFD :: distinct FCntl_Command
FCntl_Command_SETFD :: distinct FCntl_Command
FCntl_Command_GETFL :: distinct FCntl_Command
FCntl_Command_SETFL :: distinct FCntl_Command
FCntl_Command_GETLK :: distinct FCntl_Command
FCntl_Command_SETLK :: distinct FCntl_Command
FCntl_Command_SETLKW :: distinct FCntl_Command
FCntl_Command_DUPFD_CLOEXEC :: distinct FCntl_Command
FCntl_Command_SETOWN :: distinct FCntl_Command
FCntl_Command_GETOWN :: distinct FCntl_Command
FCntl_Command_SETSIG :: distinct FCntl_Command
FCntl_Command_GETSIG :: distinct FCntl_Command
FCntl_Command_SETOWN_EX :: distinct FCntl_Command
FCntl_Command_GETOWN_EX :: distinct FCntl_Command
FCntl_Command_SETLEASE :: distinct FCntl_Command
FCntl_Command_GETLEASE :: distinct FCntl_Command
FCntl_Command_NOTIFY :: distinct FCntl_Command
FCntl_Command_SETPIPE_SZ :: distinct FCntl_Command
FCntl_Command_GETPIPE_SZ :: distinct FCntl_Command
FCntl_Command_ADD_SEALS :: distinct FCntl_Command
FCntl_Command_GET_SEALS :: distinct FCntl_Command
FCntl_Command_GET_RW_HINT :: distinct FCntl_Command
FCntl_Command_SET_RW_HINT :: distinct FCntl_Command
FCntl_Command_GET_FILE_RW_HINT :: distinct FCntl_Command
FCntl_Command_SET_FILE_RW_HINT :: distinct FCntl_Command
F_DUPFD :: FCntl_Command_DUPFD(.DUPFD)
F_GETFD :: FCntl_Command_GETFD(.GETFD)
F_SETFD :: FCntl_Command_SETFD(.SETFD)
F_GETFL :: FCntl_Command_GETFL(.GETFL)
F_SETFL :: FCntl_Command_SETFL(.SETFL)
// F_GETLK64 :: FCntl_Command_GETLK64(.GETLK64)
// F_SETLK64 :: FCntl_Command_SETLK64(.SETLK64)
// F_SETLKW64 :: FCntl_Command_SETLKW64(.SETLKW64)
F_GETLK :: FCntl_Command_GETLK(.GETLK)
F_SETLK :: FCntl_Command_SETLK(.SETLK)
F_SETLKW :: FCntl_Command_SETLKW(.SETLKW)
F_DUPFD_CLOEXEC :: FCntl_Command_DUPFD_CLOEXEC(.DUPFD_CLOEXEC)
F_SETOWN :: FCntl_Command_SETOWN(.SETOWN)
F_GETOWN :: FCntl_Command_GETOWN(.GETOWN)
F_SETSIG :: FCntl_Command_SETSIG(.SETSIG)
F_GETSIG :: FCntl_Command_GETSIG(.GETSIG)
F_SETOWN_EX :: FCntl_Command_SETOWN_EX(.SETOWN_EX)
F_GETOWN_EX :: FCntl_Command_GETOWN_EX(.GETOWN_EX)
F_SETLEASE :: FCntl_Command_SETLEASE(.SETLEASE)
F_GETLEASE :: FCntl_Command_GETLEASE(.GETLEASE)
F_NOTIFY :: FCntl_Command_NOTIFY(.NOTIFY)
F_SETPIPE_SZ :: FCntl_Command_SETPIPE_SZ(.SETPIPE_SZ)
F_GETPIPE_SZ :: FCntl_Command_GETPIPE_SZ(.GETPIPE_SZ)
F_ADD_SEALS :: FCntl_Command_ADD_SEALS(.ADD_SEALS)
F_GET_SEALS :: FCntl_Command_GET_SEALS(.GET_SEALS)
F_GET_RW_HINT :: FCntl_Command_GET_RW_HINT(.GET_RW_HINT)
F_SET_RW_HINT :: FCntl_Command_SET_RW_HINT(.SET_RW_HINT)
F_GET_FILE_RW_HINT :: FCntl_Command_GET_FILE_RW_HINT(.GET_FILE_RW_HINT)
F_SET_FILE_RW_HINT :: FCntl_Command_SET_FILE_RW_HINT(.SET_FILE_RW_HINT)
Socket_API_Level_Sock :: distinct Socket_API_Level
Socket_API_Level_TCP :: distinct Socket_API_Level
Socket_API_Level_UDP :: distinct Socket_API_Level
Socket_API_Level_Raw :: distinct Socket_API_Level
SOL_SOCKET :: Socket_API_Level_Sock(.SOCKET)
SOL_TCP :: Socket_API_Level_TCP(.TCP)
SOL_UDP :: Socket_API_Level_UDP(.UDP)
SOL_RAW :: Socket_API_Level_Raw(.RAW)
Futex_Wait_Type :: distinct Futex_Op
Futex_Wake_Type :: distinct Futex_Op
Futex_Fd_Type :: distinct Futex_Op
Futex_Requeue_Type :: distinct Futex_Op
Futex_Cmp_Requeue_Type :: distinct Futex_Op
Futex_Wake_Op_Type :: distinct Futex_Op
Futex_Lock_Pi_Type :: distinct Futex_Op
Futex_Unlock_Pi_Type :: distinct Futex_Op
Futex_Trylock_Pi_Type :: distinct Futex_Op
Futex_Wait_Bitset_Type :: distinct Futex_Op
Futex_Wake_Bitset_Type :: distinct Futex_Op
Futex_Wait_requeue_Pi_Type :: distinct Futex_Op
Futex_Cmp_requeue_Pi_Type :: distinct Futex_Op
Futex_Lock_Pi2_Type :: distinct Futex_Op
/// Wait on futex wakeup signal
FUTEX_WAIT :: Futex_Wait_Type(.WAIT)
/// Wake up other processes waiting on the futex
FUTEX_WAKE :: Futex_Wake_Type(.WAKE)
/// Not implemented. Basically, since
FUTEX_FD :: Futex_Fd_Type(.FD)
/// Requeue waiters from one futex to another
FUTEX_REQUEUE :: Futex_Requeue_Type(.REQUEUE)
/// Requeue waiters from one futex to another if the value at mutex matches
FUTEX_CMP_REQUEUE :: Futex_Cmp_Requeue_Type(.CMP_REQUEUE)
/// See man pages, I'm not describing it here
FUTEX_WAKE_OP :: Futex_Wake_Op_Type(.WAKE_OP)
/// Wait on a futex, but the value is a bitset
FUTEX_WAIT_BITSET :: Futex_Wait_Bitset_Type(.WAIT_BITSET)
/// Wait on a futex, but the value is a bitset
FUTEX_WAKE_BITSET :: Futex_Wake_Bitset_Type(.WAKE_BITSET)
// TODO(flysand): Priority inversion futexes
FUTEX_LOCK_PI :: Futex_Lock_Pi_Type(.LOCK_PI)
FUTEX_UNLOCK_PI :: Futex_Unlock_Pi_Type(.UNLOCK_PI)
FUTEX_TRYLOCK_PI :: Futex_Trylock_Pi_Type(.TRYLOCK_PI)
FUTEX_WAIT_REQUEUE_PI :: Futex_Wait_requeue_Pi_Type(.WAIT_REQUEUE_PI)
FUTEX_CMP_REQUEUE_PI :: Futex_Cmp_requeue_Pi_Type(.CMP_REQUEUE_PI)
FUTEX_LOCK_PI2 :: Futex_Lock_Pi2_Type(.LOCK_PI2)
+150
View File
@@ -0,0 +1,150 @@
//+build linux
package linux
import "core:intrinsics"
// Note(flysand): In the case of syscall let's get rid of extra
// casting. First of all, let these syscalls return int, because
// we'll need to check for Errno anyway. Second of all
// most parameters are going to be trivially-castable to
// uintptr, so we'll have that.
@(private)
syscall0 :: #force_inline proc "contextless" (nr: uintptr) -> int {
return cast(int) intrinsics.syscall(nr)
}
@(private)
syscall1 :: #force_inline proc "contextless" (nr: uintptr, p1: $T) -> int
where
size_of(p1) <= size_of(uintptr)
{
return cast(int) intrinsics.syscall(nr, cast(uintptr) p1)
}
@(private)
syscall2 :: #force_inline proc "contextless" (nr: uintptr,p1: $T1, p2: $T2) -> int
where
size_of(p1) <= size_of(uintptr) &&
size_of(p2) <= size_of(uintptr)
{
return cast(int) intrinsics.syscall(nr,
cast(uintptr) p1, cast(uintptr) p2)
}
@(private)
syscall3 :: #force_inline proc "contextless" (nr: uintptr, p1: $T1, p2: $T2, p3: $T3) -> int
where
size_of(p1) <= size_of(uintptr) &&
size_of(p2) <= size_of(uintptr) &&
size_of(p3) <= size_of(uintptr)
{
return cast(int) intrinsics.syscall(nr,
cast(uintptr) p1,
cast(uintptr) p2,
cast(uintptr) p3)
}
@(private)
syscall4 :: #force_inline proc "contextless" (nr: uintptr, p1: $T1, p2: $T2, p3: $T3, p4: $T4) -> int
where
size_of(p1) <= size_of(uintptr) &&
size_of(p2) <= size_of(uintptr) &&
size_of(p3) <= size_of(uintptr) &&
size_of(p4) <= size_of(uintptr)
{
return cast(int) intrinsics.syscall(nr,
cast(uintptr) p1,
cast(uintptr) p2,
cast(uintptr) p3,
cast(uintptr) p4)
}
@(private)
syscall5 :: #force_inline proc "contextless" (nr: uintptr, p1: $T1, p2: $T2, p3: $T3, p4: $T4, p5: $T5) -> int
where
size_of(p1) <= size_of(uintptr) &&
size_of(p2) <= size_of(uintptr) &&
size_of(p3) <= size_of(uintptr) &&
size_of(p4) <= size_of(uintptr) &&
size_of(p5) <= size_of(uintptr)
{
return cast(int) intrinsics.syscall(nr,
cast(uintptr) p1,
cast(uintptr) p2,
cast(uintptr) p3,
cast(uintptr) p4,
cast(uintptr) p5)
}
@(private)
syscall6 :: #force_inline proc "contextless" (nr: uintptr, p1: $T1, p2: $T2, p3: $T3, p4: $T4, p5: $T5, p6: $T6) -> int
where
size_of(p1) <= size_of(uintptr) &&
size_of(p2) <= size_of(uintptr) &&
size_of(p3) <= size_of(uintptr) &&
size_of(p4) <= size_of(uintptr) &&
size_of(p5) <= size_of(uintptr) &&
size_of(p6) <= size_of(uintptr)
{
return cast(int) intrinsics.syscall(nr,
cast(uintptr) p1,
cast(uintptr) p2,
cast(uintptr) p3,
cast(uintptr) p4,
cast(uintptr) p5,
cast(uintptr) p6)
}
syscall :: proc {syscall0, syscall1, syscall2, syscall3, syscall4, syscall5, syscall6}
// Note(bumbread): This should shrug off a few lines from every syscall.
// Since not any type can be trivially casted to another type, we take two arguments:
// the final type to cast to, and the type to transmute to before casting.
// One transmute + one cast should allow us to get to any type we might want
// to return from a syscall wrapper.
@(private)
errno_unwrap3 :: #force_inline proc "contextless" (ret: $P, $T: typeid, $U: typeid) -> (T, Errno)
where
intrinsics.type_is_ordered_numeric(P)
{
if ret < 0 {
default_value: T
return default_value, Errno(-ret)
} else {
return cast(T) transmute(U) ret, Errno(.NONE)
}
}
@(private)
errno_unwrap2 :: #force_inline proc "contextless" (ret: $P, $T: typeid) -> (T, Errno) {
if ret < 0 {
default_value: T
return default_value, Errno(-ret)
} else {
return cast(T) ret, Errno(.NONE)
}
}
@(private)
errno_unwrap :: proc {errno_unwrap2, errno_unwrap3}
// Note(flysand): 32-bit architectures sometimes take in a 64-bit argument in a
// register pair. This function should help me avoid typing the same code a few times..
when size_of(int) == 4 {
// xxx64 system calls take some parameters as pairs of ulongs rather than a single pointer
@(private)
compat64_arg_pair :: #force_inline proc "contextless" (a: i64) -> (hi: uint, lo: uint) {
no_sign := uint(a)
hi = uint(no_sign >> 32)
lo = uint(no_sign & 0xffff_ffff)
return
}
} else {
// ... and on 64-bit architectures it's just a long
@(private)
compat64_arg_pair :: #force_inline proc "contextless" (a: i64) -> (uint) {
return uint(a)
}
}
File diff suppressed because it is too large Load Diff
+373
View File
@@ -0,0 +1,373 @@
//+build amd64
package linux
// AMD64 uses the new way to define syscalls, i.e. one that
// is different from the other architectures. Instead of using
// a .tbl file, they define constants to tell which syscalls they
// want and then include a generic unistd.h file.
SYS_read :: uintptr(0)
SYS_write :: uintptr(1)
SYS_open :: uintptr(2)
SYS_close :: uintptr(3)
SYS_stat :: uintptr(4)
SYS_fstat :: uintptr(5)
SYS_lstat :: uintptr(6)
SYS_poll :: uintptr(7)
SYS_lseek :: uintptr(8)
SYS_mmap :: uintptr(9)
SYS_mprotect :: uintptr(10)
SYS_munmap :: uintptr(11)
SYS_brk :: uintptr(12)
SYS_rt_sigaction :: uintptr(13)
SYS_rt_sigprocmask :: uintptr(14)
SYS_rt_sigreturn :: uintptr(15)
SYS_ioctl :: uintptr(16)
SYS_pread64 :: uintptr(17)
SYS_pwrite64 :: uintptr(18)
SYS_readv :: uintptr(19)
SYS_writev :: uintptr(20)
SYS_access :: uintptr(21)
SYS_pipe :: uintptr(22)
SYS_select :: uintptr(23)
SYS_sched_yield :: uintptr(24)
SYS_mremap :: uintptr(25)
SYS_msync :: uintptr(26)
SYS_mincore :: uintptr(27)
SYS_madvise :: uintptr(28)
SYS_shmget :: uintptr(29)
SYS_shmat :: uintptr(30)
SYS_shmctl :: uintptr(31)
SYS_dup :: uintptr(32)
SYS_dup2 :: uintptr(33)
SYS_pause :: uintptr(34)
SYS_nanosleep :: uintptr(35)
SYS_getitimer :: uintptr(36)
SYS_alarm :: uintptr(37)
SYS_setitimer :: uintptr(38)
SYS_getpid :: uintptr(39)
SYS_sendfile :: uintptr(40)
SYS_socket :: uintptr(41)
SYS_connect :: uintptr(42)
SYS_accept :: uintptr(43)
SYS_sendto :: uintptr(44)
SYS_recvfrom :: uintptr(45)
SYS_sendmsg :: uintptr(46)
SYS_recvmsg :: uintptr(47)
SYS_shutdown :: uintptr(48)
SYS_bind :: uintptr(49)
SYS_listen :: uintptr(50)
SYS_getsockname :: uintptr(51)
SYS_getpeername :: uintptr(52)
SYS_socketpair :: uintptr(53)
SYS_setsockopt :: uintptr(54)
SYS_getsockopt :: uintptr(55)
SYS_clone :: uintptr(56)
SYS_fork :: uintptr(57)
SYS_vfork :: uintptr(58)
SYS_execve :: uintptr(59)
SYS_exit :: uintptr(60)
SYS_wait4 :: uintptr(61)
SYS_kill :: uintptr(62)
SYS_uname :: uintptr(63)
SYS_semget :: uintptr(64)
SYS_semop :: uintptr(65)
SYS_semctl :: uintptr(66)
SYS_shmdt :: uintptr(67)
SYS_msgget :: uintptr(68)
SYS_msgsnd :: uintptr(69)
SYS_msgrcv :: uintptr(70)
SYS_msgctl :: uintptr(71)
SYS_fcntl :: uintptr(72)
SYS_flock :: uintptr(73)
SYS_fsync :: uintptr(74)
SYS_fdatasync :: uintptr(75)
SYS_truncate :: uintptr(76)
SYS_ftruncate :: uintptr(77)
SYS_getdents :: uintptr(78)
SYS_getcwd :: uintptr(79)
SYS_chdir :: uintptr(80)
SYS_fchdir :: uintptr(81)
SYS_rename :: uintptr(82)
SYS_mkdir :: uintptr(83)
SYS_rmdir :: uintptr(84)
SYS_creat :: uintptr(85)
SYS_link :: uintptr(86)
SYS_unlink :: uintptr(87)
SYS_symlink :: uintptr(88)
SYS_readlink :: uintptr(89)
SYS_chmod :: uintptr(90)
SYS_fchmod :: uintptr(91)
SYS_chown :: uintptr(92)
SYS_fchown :: uintptr(93)
SYS_lchown :: uintptr(94)
SYS_umask :: uintptr(95)
SYS_gettimeofday :: uintptr(96)
SYS_getrlimit :: uintptr(97)
SYS_getrusage :: uintptr(98)
SYS_sysinfo :: uintptr(99)
SYS_times :: uintptr(100)
SYS_ptrace :: uintptr(101)
SYS_getuid :: uintptr(102)
SYS_syslog :: uintptr(103)
SYS_getgid :: uintptr(104)
SYS_setuid :: uintptr(105)
SYS_setgid :: uintptr(106)
SYS_geteuid :: uintptr(107)
SYS_getegid :: uintptr(108)
SYS_setpgid :: uintptr(109)
SYS_getppid :: uintptr(110)
SYS_getpgrp :: uintptr(111)
SYS_setsid :: uintptr(112)
SYS_setreuid :: uintptr(113)
SYS_setregid :: uintptr(114)
SYS_getgroups :: uintptr(115)
SYS_setgroups :: uintptr(116)
SYS_setresuid :: uintptr(117)
SYS_getresuid :: uintptr(118)
SYS_setresgid :: uintptr(119)
SYS_getresgid :: uintptr(120)
SYS_getpgid :: uintptr(121)
SYS_setfsuid :: uintptr(122)
SYS_setfsgid :: uintptr(123)
SYS_getsid :: uintptr(124)
SYS_capget :: uintptr(125)
SYS_capset :: uintptr(126)
SYS_rt_sigpending :: uintptr(127)
SYS_rt_sigtimedwait :: uintptr(128)
SYS_rt_sigqueueinfo :: uintptr(129)
SYS_rt_sigsuspend :: uintptr(130)
SYS_sigaltstack :: uintptr(131)
SYS_utime :: uintptr(132)
SYS_mknod :: uintptr(133)
SYS_uselib :: uintptr(134)
SYS_personality :: uintptr(135)
SYS_ustat :: uintptr(136)
SYS_statfs :: uintptr(137)
SYS_fstatfs :: uintptr(138)
SYS_sysfs :: uintptr(139)
SYS_getpriority :: uintptr(140)
SYS_setpriority :: uintptr(141)
SYS_sched_setparam :: uintptr(142)
SYS_sched_getparam :: uintptr(143)
SYS_sched_setscheduler :: uintptr(144)
SYS_sched_getscheduler :: uintptr(145)
SYS_sched_get_priority_max :: uintptr(146)
SYS_sched_get_priority_min :: uintptr(147)
SYS_sched_rr_get_interval :: uintptr(148)
SYS_mlock :: uintptr(149)
SYS_munlock :: uintptr(150)
SYS_mlockall :: uintptr(151)
SYS_munlockall :: uintptr(152)
SYS_vhangup :: uintptr(153)
SYS_modify_ldt :: uintptr(154)
SYS_pivot_root :: uintptr(155)
SYS__sysctl :: uintptr(156)
SYS_prctl :: uintptr(157)
SYS_arch_prctl :: uintptr(158)
SYS_adjtimex :: uintptr(159)
SYS_setrlimit :: uintptr(160)
SYS_chroot :: uintptr(161)
SYS_sync :: uintptr(162)
SYS_acct :: uintptr(163)
SYS_settimeofday :: uintptr(164)
SYS_mount :: uintptr(165)
SYS_umount2 :: uintptr(166)
SYS_swapon :: uintptr(167)
SYS_swapoff :: uintptr(168)
SYS_reboot :: uintptr(169)
SYS_sethostname :: uintptr(170)
SYS_setdomainname :: uintptr(171)
SYS_iopl :: uintptr(172)
SYS_ioperm :: uintptr(173)
SYS_create_module :: uintptr(174)
SYS_init_module :: uintptr(175)
SYS_delete_module :: uintptr(176)
SYS_get_kernel_syms :: uintptr(177)
SYS_query_module :: uintptr(178)
SYS_quotactl :: uintptr(179)
SYS_nfsservctl :: uintptr(180)
SYS_getpmsg :: uintptr(181)
SYS_putpmsg :: uintptr(182)
SYS_afs_syscall :: uintptr(183)
SYS_tuxcall :: uintptr(184)
SYS_security :: uintptr(185)
SYS_gettid :: uintptr(186)
SYS_readahead :: uintptr(187)
SYS_setxattr :: uintptr(188)
SYS_lsetxattr :: uintptr(189)
SYS_fsetxattr :: uintptr(190)
SYS_getxattr :: uintptr(191)
SYS_lgetxattr :: uintptr(192)
SYS_fgetxattr :: uintptr(193)
SYS_listxattr :: uintptr(194)
SYS_llistxattr :: uintptr(195)
SYS_flistxattr :: uintptr(196)
SYS_removexattr :: uintptr(197)
SYS_lremovexattr :: uintptr(198)
SYS_fremovexattr :: uintptr(199)
SYS_tkill :: uintptr(200)
SYS_time :: uintptr(201)
SYS_futex :: uintptr(202)
SYS_sched_setaffinity :: uintptr(203)
SYS_sched_getaffinity :: uintptr(204)
SYS_set_thread_area :: uintptr(205)
SYS_io_setup :: uintptr(206)
SYS_io_destroy :: uintptr(207)
SYS_io_getevents :: uintptr(208)
SYS_io_submit :: uintptr(209)
SYS_io_cancel :: uintptr(210)
SYS_get_thread_area :: uintptr(211)
SYS_lookup_dcookie :: uintptr(212)
SYS_epoll_create :: uintptr(213)
SYS_epoll_ctl_old :: uintptr(214)
SYS_epoll_wait_old :: uintptr(215)
SYS_remap_file_pages :: uintptr(216)
SYS_getdents64 :: uintptr(217)
SYS_set_tid_address :: uintptr(218)
SYS_restart_syscall :: uintptr(219)
SYS_semtimedop :: uintptr(220)
SYS_fadvise64 :: uintptr(221)
SYS_timer_create :: uintptr(222)
SYS_timer_settime :: uintptr(223)
SYS_timer_gettime :: uintptr(224)
SYS_timer_getoverrun :: uintptr(225)
SYS_timer_delete :: uintptr(226)
SYS_clock_settime :: uintptr(227)
SYS_clock_gettime :: uintptr(228)
SYS_clock_getres :: uintptr(229)
SYS_clock_nanosleep :: uintptr(230)
SYS_exit_group :: uintptr(231)
SYS_epoll_wait :: uintptr(232)
SYS_epoll_ctl :: uintptr(233)
SYS_tgkill :: uintptr(234)
SYS_utimes :: uintptr(235)
SYS_vserver :: uintptr(236)
SYS_mbind :: uintptr(237)
SYS_set_mempolicy :: uintptr(238)
SYS_get_mempolicy :: uintptr(239)
SYS_mq_open :: uintptr(240)
SYS_mq_unlink :: uintptr(241)
SYS_mq_timedsend :: uintptr(242)
SYS_mq_timedreceive :: uintptr(243)
SYS_mq_notify :: uintptr(244)
SYS_mq_getsetattr :: uintptr(245)
SYS_kexec_load :: uintptr(246)
SYS_waitid :: uintptr(247)
SYS_add_key :: uintptr(248)
SYS_request_key :: uintptr(249)
SYS_keyctl :: uintptr(250)
SYS_ioprio_set :: uintptr(251)
SYS_ioprio_get :: uintptr(252)
SYS_inotify_init :: uintptr(253)
SYS_inotify_add_watch :: uintptr(254)
SYS_inotify_rm_watch :: uintptr(255)
SYS_migrate_pages :: uintptr(256)
SYS_openat :: uintptr(257)
SYS_mkdirat :: uintptr(258)
SYS_mknodat :: uintptr(259)
SYS_fchownat :: uintptr(260)
SYS_futimesat :: uintptr(261)
SYS_newfstatat :: uintptr(262)
SYS_unlinkat :: uintptr(263)
SYS_renameat :: uintptr(264)
SYS_linkat :: uintptr(265)
SYS_symlinkat :: uintptr(266)
SYS_readlinkat :: uintptr(267)
SYS_fchmodat :: uintptr(268)
SYS_faccessat :: uintptr(269)
SYS_pselect6 :: uintptr(270)
SYS_ppoll :: uintptr(271)
SYS_unshare :: uintptr(272)
SYS_set_robust_list :: uintptr(273)
SYS_get_robust_list :: uintptr(274)
SYS_splice :: uintptr(275)
SYS_tee :: uintptr(276)
SYS_sync_file_range :: uintptr(277)
SYS_vmsplice :: uintptr(278)
SYS_move_pages :: uintptr(279)
SYS_utimensat :: uintptr(280)
SYS_epoll_pwait :: uintptr(281)
SYS_signalfd :: uintptr(282)
SYS_timerfd_create :: uintptr(283)
SYS_eventfd :: uintptr(284)
SYS_fallocate :: uintptr(285)
SYS_timerfd_settime :: uintptr(286)
SYS_timerfd_gettime :: uintptr(287)
SYS_accept4 :: uintptr(288)
SYS_signalfd4 :: uintptr(289)
SYS_eventfd2 :: uintptr(290)
SYS_epoll_create1 :: uintptr(291)
SYS_dup3 :: uintptr(292)
SYS_pipe2 :: uintptr(293)
SYS_inotify_init1 :: uintptr(294)
SYS_preadv :: uintptr(295)
SYS_pwritev :: uintptr(296)
SYS_rt_tgsigqueueinfo :: uintptr(297)
SYS_perf_event_open :: uintptr(298)
SYS_recvmmsg :: uintptr(299)
SYS_fanotify_init :: uintptr(300)
SYS_fanotify_mark :: uintptr(301)
SYS_prlimit64 :: uintptr(302)
SYS_name_to_handle_at :: uintptr(303)
SYS_open_by_handle_at :: uintptr(304)
SYS_clock_adjtime :: uintptr(305)
SYS_syncfs :: uintptr(306)
SYS_sendmmsg :: uintptr(307)
SYS_setns :: uintptr(308)
SYS_getcpu :: uintptr(309)
SYS_process_vm_readv :: uintptr(310)
SYS_process_vm_writev :: uintptr(311)
SYS_kcmp :: uintptr(312)
SYS_finit_module :: uintptr(313)
SYS_sched_setattr :: uintptr(314)
SYS_sched_getattr :: uintptr(315)
SYS_renameat2 :: uintptr(316)
SYS_seccomp :: uintptr(317)
SYS_getrandom :: uintptr(318)
SYS_memfd_create :: uintptr(319)
SYS_kexec_file_load :: uintptr(320)
SYS_bpf :: uintptr(321)
SYS_execveat :: uintptr(322)
SYS_userfaultfd :: uintptr(323)
SYS_membarrier :: uintptr(324)
SYS_mlock2 :: uintptr(325)
SYS_copy_file_range :: uintptr(326)
SYS_preadv2 :: uintptr(327)
SYS_pwritev2 :: uintptr(328)
SYS_pkey_mprotect :: uintptr(329)
SYS_pkey_alloc :: uintptr(330)
SYS_pkey_free :: uintptr(331)
SYS_statx :: uintptr(332)
SYS_io_pgetevents :: uintptr(333)
SYS_rseq :: uintptr(334)
SYS_pidfd_send_signal :: uintptr(424)
SYS_io_uring_setup :: uintptr(425)
SYS_io_uring_enter :: uintptr(426)
SYS_io_uring_register :: uintptr(427)
SYS_open_tree :: uintptr(428)
SYS_move_mount :: uintptr(429)
SYS_fsopen :: uintptr(430)
SYS_fsconfig :: uintptr(431)
SYS_fsmount :: uintptr(432)
SYS_fspick :: uintptr(433)
SYS_pidfd_open :: uintptr(434)
SYS_clone3 :: uintptr(435)
SYS_close_range :: uintptr(436)
SYS_openat2 :: uintptr(437)
SYS_pidfd_getfd :: uintptr(438)
SYS_faccessat2 :: uintptr(439)
SYS_process_madvise :: uintptr(440)
SYS_epoll_pwait2 :: uintptr(441)
SYS_mount_setattr :: uintptr(442)
SYS_quotactl_fd :: uintptr(443)
SYS_landlock_create_ruleset :: uintptr(444)
SYS_landlock_add_rule :: uintptr(445)
SYS_landlock_restrict_self :: uintptr(446)
SYS_memfd_secret :: uintptr(447)
SYS_process_mrelease :: uintptr(448)
SYS_futex_waitv :: uintptr(449)
SYS_set_mempolicy_home_node :: uintptr(450)
SYS_cachestat :: uintptr(451)
SYS_fchmodat2 :: uintptr(452)
SYS_map_shadow_stack :: uintptr(453)
+470
View File
@@ -0,0 +1,470 @@
//+build arm32
package linux
// This file was taken and transformed from
// /arch/arm/tools/syscall.tbl
// in linux headers. OABI and EABI syscalls
// are included.
// TODO(bumbread, 2023-10-13): I'm not sure whether I have used
// the right syscall table. ARM64 stuff seems to be also compatible
// with ARM32, I'm not sure whether ARM32 also uses the new way of
// defining the syscall table, and this one is just for compatibility..?
// This syscall is not meant to be used by userspace
SYS_restart_syscall :: uintptr(0)
SYS_exit :: uintptr(1)
SYS_fork :: uintptr(2)
SYS_read :: uintptr(3)
SYS_write :: uintptr(4)
SYS_open :: uintptr(5)
SYS_close :: uintptr(6)
// 7 was sys_waitpid
SYS_creat :: uintptr(8)
SYS_link :: uintptr(9)
SYS_unlink :: uintptr(10)
SYS_execve :: uintptr(11)
SYS_chdir :: uintptr(12)
SYS_time :: uintptr(13)
SYS_mknod :: uintptr(14)
SYS_chmod :: uintptr(15)
SYS_lchown :: uintptr(16)
// 17 was sys_break
// 18 was sys_stat
SYS_lseek :: uintptr(19)
SYS_getpid :: uintptr(20)
SYS_mount :: uintptr(21)
SYS_umount :: uintptr(22)
SYS_setuid :: uintptr(23)
SYS_getuid :: uintptr(24)
SYS_stime :: uintptr(25)
SYS_ptrace :: uintptr(26)
SYS_alarm :: uintptr(27)
// 28 was sys_fstat
SYS_pause :: uintptr(29)
SYS_utime :: uintptr(30)
// 31 was sys_stty
// 32 was sys_gtty
SYS_access :: uintptr(33)
SYS_nice :: uintptr(34)
// 35 was sys_ftime
SYS_sync :: uintptr(36)
SYS_kill :: uintptr(37)
SYS_rename :: uintptr(38)
SYS_mkdir :: uintptr(39)
SYS_rmdir :: uintptr(40)
SYS_dup :: uintptr(41)
SYS_pipe :: uintptr(42)
SYS_times :: uintptr(43)
// 44 was sys_prof
SYS_brk :: uintptr(45)
SYS_setgid :: uintptr(46)
SYS_getgid :: uintptr(47)
// 48 was sys_signal
SYS_geteuid :: uintptr(49)
SYS_getegid :: uintptr(50)
SYS_acct :: uintptr(51)
SYS_umount2 :: uintptr(52)
// 53 was sys_lock
SYS_ioctl :: uintptr(54)
SYS_fcntl :: uintptr(55)
// 56 was sys_mpx
SYS_setpgid :: uintptr(57)
// 58 was sys_ulimit
// 59 was sys_olduname
SYS_umask :: uintptr(60)
SYS_chroot :: uintptr(61)
SYS_ustat :: uintptr(62)
SYS_dup2 :: uintptr(63)
SYS_getppid :: uintptr(64)
SYS_getpgrp :: uintptr(65)
SYS_setsid :: uintptr(66)
SYS_sigaction :: uintptr(67)
// 68 was sys_sgetmask
// 69 was sys_ssetmask
SYS_setreuid :: uintptr(70)
SYS_setregid :: uintptr(71)
SYS_sigsuspend :: uintptr(72)
SYS_sigpending :: uintptr(73)
SYS_sethostname :: uintptr(74)
SYS_setrlimit :: uintptr(75)
// Back compat 2GB limited rlimit
SYS_getrlimit :: uintptr(76)
SYS_getrusage :: uintptr(77)
SYS_gettimeofday :: uintptr(78)
SYS_settimeofday :: uintptr(79)
SYS_getgroups :: uintptr(80)
SYS_setgroups :: uintptr(81)
SYS_select :: uintptr(82)
SYS_symlink :: uintptr(83)
// 84 was sys_lstat
SYS_readlink :: uintptr(85)
SYS_uselib :: uintptr(86)
SYS_swapon :: uintptr(87)
SYS_reboot :: uintptr(88)
SYS_readdir :: uintptr(89)
SYS_mmap :: uintptr(90)
SYS_munmap :: uintptr(91)
SYS_truncate :: uintptr(92)
SYS_ftruncate :: uintptr(93)
SYS_fchmod :: uintptr(94)
SYS_fchown :: uintptr(95)
SYS_getpriority :: uintptr(96)
SYS_setpriority :: uintptr(97)
// 98 was sys_profil
SYS_statfs :: uintptr(99)
SYS_fstatfs :: uintptr(100)
// 101 was sys_ioperm
SYS_socketcall :: uintptr(102)
SYS_syslog :: uintptr(103)
SYS_setitimer :: uintptr(104)
SYS_getitimer :: uintptr(105)
SYS_stat :: uintptr(106)
SYS_lstat :: uintptr(107)
SYS_fstat :: uintptr(108)
// 109 was sys_uname
// 110 was sys_iopl
SYS_vhangup :: uintptr(111)
// 112 was sys_idle
// syscall to call a syscall!
SYS_syscall :: uintptr(113)
SYS_wait4 :: uintptr(114)
SYS_swapoff :: uintptr(115)
SYS_sysinfo :: uintptr(116)
SYS_ipc :: uintptr(117)
SYS_fsync :: uintptr(118)
SYS_sigreturn :: uintptr(119)
SYS_clone :: uintptr(120)
SYS_setdomainname :: uintptr(121)
SYS_uname :: uintptr(122)
// 123 was sys_modify_ldt
SYS_adjtimex :: uintptr(124)
SYS_mprotect :: uintptr(125)
SYS_sigprocmask :: uintptr(126)
// 127 was sys_create_module
SYS_init_module :: uintptr(128)
SYS_delete_module :: uintptr(129)
// 130 was sys_get_kernel_syms
SYS_quotactl :: uintptr(131)
SYS_getpgid :: uintptr(132)
SYS_fchdir :: uintptr(133)
SYS_bdflush :: uintptr(134)
SYS_sysfs :: uintptr(135)
SYS_personality :: uintptr(136)
// 137 was sys_afs_syscall
SYS_setfsuid :: uintptr(138)
SYS_setfsgid :: uintptr(139)
SYS__llseek :: uintptr(140)
SYS_getdents :: uintptr(141)
SYS__newselect :: uintptr(142)
SYS_flock :: uintptr(143)
SYS_msync :: uintptr(144)
SYS_readv :: uintptr(145)
SYS_writev :: uintptr(146)
SYS_getsid :: uintptr(147)
SYS_fdatasync :: uintptr(148)
SYS__sysctl :: uintptr(149)
SYS_mlock :: uintptr(150)
SYS_munlock :: uintptr(151)
SYS_mlockall :: uintptr(152)
SYS_munlockall :: uintptr(153)
SYS_sched_setparam :: uintptr(154)
SYS_sched_getparam :: uintptr(155)
SYS_sched_setscheduler :: uintptr(156)
SYS_sched_getscheduler :: uintptr(157)
SYS_sched_yield :: uintptr(158)
SYS_sched_get_priority_max :: uintptr(159)
SYS_sched_get_priority_min :: uintptr(160)
SYS_sched_rr_get_interval :: uintptr(161)
SYS_nanosleep :: uintptr(162)
SYS_mremap :: uintptr(163)
SYS_setresuid :: uintptr(164)
SYS_getresuid :: uintptr(165)
// 166 was sys_vm86
// 167 was sys_query_module
SYS_poll :: uintptr(168)
SYS_nfsservctl :: uintptr(169)
SYS_setresgid :: uintptr(170)
SYS_getresgid :: uintptr(171)
SYS_prctl :: uintptr(172)
SYS_rt_sigreturn :: uintptr(173)
SYS_rt_sigaction :: uintptr(174)
SYS_rt_sigprocmask :: uintptr(175)
SYS_rt_sigpending :: uintptr(176)
SYS_rt_sigtimedwait :: uintptr(177)
SYS_rt_sigqueueinfo :: uintptr(178)
SYS_rt_sigsuspend :: uintptr(179)
SYS_pread64 :: uintptr(180)
SYS_pwrite64 :: uintptr(181)
SYS_chown :: uintptr(182)
SYS_getcwd :: uintptr(183)
SYS_capget :: uintptr(184)
SYS_capset :: uintptr(185)
SYS_sigaltstack :: uintptr(186)
SYS_sendfile :: uintptr(187)
// 188 reserved
// 189 reserved
SYS_vfork :: uintptr(190)
// SuS compliant getrlimit
SYS_ugetrlimit :: uintptr(191)
SYS_mmap2 :: uintptr(192)
SYS_truncate64 :: uintptr(193)
SYS_ftruncate64 :: uintptr(194)
SYS_stat64 :: uintptr(195)
SYS_lstat64 :: uintptr(196)
SYS_fstat64 :: uintptr(197)
SYS_lchown32 :: uintptr(198)
SYS_getuid32 :: uintptr(199)
SYS_getgid32 :: uintptr(200)
SYS_geteuid32 :: uintptr(201)
SYS_getegid32 :: uintptr(202)
SYS_setreuid32 :: uintptr(203)
SYS_setregid32 :: uintptr(204)
SYS_getgroups32 :: uintptr(205)
SYS_setgroups32 :: uintptr(206)
SYS_fchown32 :: uintptr(207)
SYS_setresuid32 :: uintptr(208)
SYS_getresuid32 :: uintptr(209)
SYS_setresgid32 :: uintptr(210)
SYS_getresgid32 :: uintptr(211)
SYS_chown32 :: uintptr(212)
SYS_setuid32 :: uintptr(213)
SYS_setgid32 :: uintptr(214)
SYS_setfsuid32 :: uintptr(215)
SYS_setfsgid32 :: uintptr(216)
SYS_getdents64 :: uintptr(217)
SYS_pivot_root :: uintptr(218)
SYS_mincore :: uintptr(219)
SYS_madvise :: uintptr(220)
SYS_fcntl64 :: uintptr(221)
// 222 for tux
// 223 is unused
SYS_gettid :: uintptr(224)
SYS_readahead :: uintptr(225)
SYS_setxattr :: uintptr(226)
SYS_lsetxattr :: uintptr(227)
SYS_fsetxattr :: uintptr(228)
SYS_getxattr :: uintptr(229)
SYS_lgetxattr :: uintptr(230)
SYS_fgetxattr :: uintptr(231)
SYS_listxattr :: uintptr(232)
SYS_llistxattr :: uintptr(233)
SYS_flistxattr :: uintptr(234)
SYS_removexattr :: uintptr(235)
SYS_lremovexattr :: uintptr(236)
SYS_fremovexattr :: uintptr(237)
SYS_tkill :: uintptr(238)
SYS_sendfile64 :: uintptr(239)
SYS_futex :: uintptr(240)
SYS_sched_setaffinity :: uintptr(241)
SYS_sched_getaffinity :: uintptr(242)
SYS_io_setup :: uintptr(243)
SYS_io_destroy :: uintptr(244)
SYS_io_getevents :: uintptr(245)
SYS_io_submit :: uintptr(246)
SYS_io_cancel :: uintptr(247)
SYS_exit_group :: uintptr(248)
SYS_lookup_dcookie :: uintptr(249)
SYS_epoll_create :: uintptr(250)
SYS_epoll_ctl :: uintptr(251)
SYS_epoll_wait :: uintptr(252)
SYS_remap_file_pages :: uintptr(253)
// 254 for set_thread_area
// 255 for get_thread_area
SYS_set_tid_address :: uintptr(256)
SYS_timer_create :: uintptr(257)
SYS_timer_settime :: uintptr(258)
SYS_timer_gettime :: uintptr(259)
SYS_timer_getoverrun :: uintptr(260)
SYS_timer_delete :: uintptr(261)
SYS_clock_settime :: uintptr(262)
SYS_clock_gettime :: uintptr(263)
SYS_clock_getres :: uintptr(264)
SYS_clock_nanosleep :: uintptr(265)
SYS_statfs64 :: uintptr(266)
SYS_fstatfs64 :: uintptr(267)
SYS_tgkill :: uintptr(268)
SYS_utimes :: uintptr(269)
SYS_arm_fadvise64_64 :: uintptr(270)
SYS_pciconfig_iobase :: uintptr(271)
SYS_pciconfig_read :: uintptr(272)
SYS_pciconfig_write :: uintptr(273)
SYS_mq_open :: uintptr(274)
SYS_mq_unlink :: uintptr(275)
SYS_mq_timedsend :: uintptr(276)
SYS_mq_timedreceive :: uintptr(277)
SYS_mq_notify :: uintptr(278)
SYS_mq_getsetattr :: uintptr(279)
SYS_waitid :: uintptr(280)
SYS_socket :: uintptr(281)
SYS_bind :: uintptr(282)
SYS_connect :: uintptr(283)
SYS_listen :: uintptr(284)
SYS_accept :: uintptr(285)
SYS_getsockname :: uintptr(286)
SYS_getpeername :: uintptr(287)
SYS_socketpair :: uintptr(288)
SYS_send :: uintptr(289)
SYS_sendto :: uintptr(290)
SYS_recv :: uintptr(291)
SYS_recvfrom :: uintptr(292)
SYS_shutdown :: uintptr(293)
SYS_setsockopt :: uintptr(294)
SYS_getsockopt :: uintptr(295)
SYS_sendmsg :: uintptr(296)
SYS_recvmsg :: uintptr(297)
SYS_semop :: uintptr(298)
SYS_semget :: uintptr(299)
SYS_semctl :: uintptr(300)
SYS_msgsnd :: uintptr(301)
SYS_msgrcv :: uintptr(302)
SYS_msgget :: uintptr(303)
SYS_msgctl :: uintptr(304)
SYS_shmat :: uintptr(305)
SYS_shmdt :: uintptr(306)
SYS_shmget :: uintptr(307)
SYS_shmctl :: uintptr(308)
SYS_add_key :: uintptr(309)
SYS_request_key :: uintptr(310)
SYS_keyctl :: uintptr(311)
SYS_semtimedop :: uintptr(312)
SYS_vserver :: uintptr(313)
SYS_ioprio_set :: uintptr(314)
SYS_ioprio_get :: uintptr(315)
SYS_inotify_init :: uintptr(316)
SYS_inotify_add_watch :: uintptr(317)
SYS_inotify_rm_watch :: uintptr(318)
SYS_mbind :: uintptr(319)
SYS_get_mempolicy :: uintptr(320)
SYS_set_mempolicy :: uintptr(321)
SYS_openat :: uintptr(322)
SYS_mkdirat :: uintptr(323)
SYS_mknodat :: uintptr(324)
SYS_fchownat :: uintptr(325)
SYS_futimesat :: uintptr(326)
SYS_fstatat64 :: uintptr(327)
SYS_unlinkat :: uintptr(328)
SYS_renameat :: uintptr(329)
SYS_linkat :: uintptr(330)
SYS_symlinkat :: uintptr(331)
SYS_readlinkat :: uintptr(332)
SYS_fchmodat :: uintptr(333)
SYS_faccessat :: uintptr(334)
SYS_pselect6 :: uintptr(335)
SYS_ppoll :: uintptr(336)
SYS_unshare :: uintptr(337)
SYS_set_robust_list :: uintptr(338)
SYS_get_robust_list :: uintptr(339)
SYS_splice :: uintptr(340)
SYS_arm_sync_file_range :: uintptr(341)
SYS_tee :: uintptr(342)
SYS_vmsplice :: uintptr(343)
SYS_move_pages :: uintptr(344)
SYS_getcpu :: uintptr(345)
SYS_epoll_pwait :: uintptr(346)
SYS_kexec_load :: uintptr(347)
SYS_utimensat :: uintptr(348)
SYS_signalfd :: uintptr(349)
SYS_timerfd_create :: uintptr(350)
SYS_eventfd :: uintptr(351)
SYS_fallocate :: uintptr(352)
SYS_timerfd_settime :: uintptr(353)
SYS_timerfd_gettime :: uintptr(354)
SYS_signalfd4 :: uintptr(355)
SYS_eventfd2 :: uintptr(356)
SYS_epoll_create1 :: uintptr(357)
SYS_dup3 :: uintptr(358)
SYS_pipe2 :: uintptr(359)
SYS_inotify_init1 :: uintptr(360)
SYS_preadv :: uintptr(361)
SYS_pwritev :: uintptr(362)
SYS_rt_tgsigqueueinfo :: uintptr(363)
SYS_perf_event_open :: uintptr(364)
SYS_recvmmsg :: uintptr(365)
SYS_accept4 :: uintptr(366)
SYS_fanotify_init :: uintptr(367)
SYS_fanotify_mark :: uintptr(368)
SYS_prlimit64 :: uintptr(369)
SYS_name_to_handle_at :: uintptr(370)
SYS_open_by_handle_at :: uintptr(371)
SYS_clock_adjtime :: uintptr(372)
SYS_syncfs :: uintptr(373)
SYS_sendmmsg :: uintptr(374)
SYS_setns :: uintptr(375)
SYS_process_vm_readv :: uintptr(376)
SYS_process_vm_writev :: uintptr(377)
SYS_kcmp :: uintptr(378)
SYS_finit_module :: uintptr(379)
SYS_sched_setattr :: uintptr(380)
SYS_sched_getattr :: uintptr(381)
SYS_renameat2 :: uintptr(382)
SYS_seccomp :: uintptr(383)
SYS_getrandom :: uintptr(384)
SYS_memfd_create :: uintptr(385)
SYS_bpf :: uintptr(386)
SYS_execveat :: uintptr(387)
SYS_userfaultfd :: uintptr(388)
SYS_membarrier :: uintptr(389)
SYS_mlock2 :: uintptr(390)
SYS_copy_file_range :: uintptr(391)
SYS_preadv2 :: uintptr(392)
SYS_pwritev2 :: uintptr(393)
SYS_pkey_mprotect :: uintptr(394)
SYS_pkey_alloc :: uintptr(395)
SYS_pkey_free :: uintptr(396)
SYS_statx :: uintptr(397)
SYS_rseq :: uintptr(398)
SYS_io_pgetevents :: uintptr(399)
SYS_migrate_pages :: uintptr(400)
SYS_kexec_file_load :: uintptr(401)
// 402 is unused
SYS_clock_gettime64 :: uintptr(403)
SYS_clock_settime64 :: uintptr(404)
SYS_clock_adjtime64 :: uintptr(405)
SYS_clock_getres_time64 :: uintptr(406)
SYS_clock_nanosleep_time64 :: uintptr(407)
SYS_timer_gettime64 :: uintptr(408)
SYS_timer_settime64 :: uintptr(409)
SYS_timerfd_gettime64 :: uintptr(410)
SYS_timerfd_settime64 :: uintptr(411)
SYS_utimensat_time64 :: uintptr(412)
SYS_pselect6_time64 :: uintptr(413)
SYS_ppoll_time64 :: uintptr(414)
SYS_io_pgetevents_time64 :: uintptr(416)
SYS_recvmmsg_time64 :: uintptr(417)
SYS_mq_timedsend_time64 :: uintptr(418)
SYS_mq_timedreceive_time64 :: uintptr(419)
SYS_semtimedop_time64 :: uintptr(420)
SYS_rt_sigtimedwait_time64 :: uintptr(421)
SYS_futex_time64 :: uintptr(422)
SYS_sched_rr_get_interval_time64:: uintptr(423)
SYS_pidfd_send_signal :: uintptr(424)
SYS_io_uring_setup :: uintptr(425)
SYS_io_uring_enter :: uintptr(426)
SYS_io_uring_register :: uintptr(427)
SYS_open_tree :: uintptr(428)
SYS_move_mount :: uintptr(429)
SYS_fsopen :: uintptr(430)
SYS_fsconfig :: uintptr(431)
SYS_fsmount :: uintptr(432)
SYS_fspick :: uintptr(433)
SYS_pidfd_open :: uintptr(434)
SYS_clone3 :: uintptr(435)
SYS_close_range :: uintptr(436)
SYS_openat2 :: uintptr(437)
SYS_pidfd_getfd :: uintptr(438)
SYS_faccessat2 :: uintptr(439)
SYS_process_madvise :: uintptr(440)
SYS_epoll_pwait2 :: uintptr(441)
SYS_mount_setattr :: uintptr(442)
SYS_quotactl_fd :: uintptr(443)
SYS_landlock_create_ruleset :: uintptr(444)
SYS_landlock_add_rule :: uintptr(445)
SYS_landlock_restrict_self :: uintptr(446)
// 447 reserved for memfd_secret
SYS_process_mrelease :: uintptr(448)
SYS_futex_waitv :: uintptr(449)
SYS_set_mempolicy_home_node :: uintptr(450)
SYS_cachestat :: uintptr(451)
SYS_fchmodat2 :: uintptr(452)
+321
View File
@@ -0,0 +1,321 @@
//+build arm64
package linux
// Syscalls for arm64 are defined using the new way, i.e. differently from
// the other platforms. It defines a few constants representing which optional
// syscalls it wants and includes the generic unistd.h file.
SYS_io_setup :: uintptr(0)
SYS_io_destroy :: uintptr(1)
SYS_io_submit :: uintptr(2)
SYS_io_cancel :: uintptr(3)
// time32 syscall
SYS_io_getevents :: uintptr(4)
SYS_setxattr :: uintptr(5)
SYS_lsetxattr :: uintptr(6)
SYS_fsetxattr :: uintptr(7)
SYS_getxattr :: uintptr(8)
SYS_lgetxattr :: uintptr(9)
SYS_fgetxattr :: uintptr(10)
SYS_listxattr :: uintptr(11)
SYS_llistxattr :: uintptr(12)
SYS_flistxattr :: uintptr(13)
SYS_removexattr :: uintptr(14)
SYS_lremovexattr :: uintptr(15)
SYS_fremovexattr :: uintptr(16)
SYS_getcwd :: uintptr(17)
SYS_lookup_dcookie :: uintptr(18)
SYS_eventfd2 :: uintptr(19)
SYS_epoll_create1 :: uintptr(20)
SYS_epoll_ctl :: uintptr(21)
SYS_epoll_pwait :: uintptr(22)
SYS_dup :: uintptr(23)
SYS_dup3 :: uintptr(24)
SYS_fcntl :: uintptr(25)
SYS_inotify_init1 :: uintptr(26)
SYS_inotify_add_watch :: uintptr(27)
SYS_inotify_rm_watch :: uintptr(28)
SYS_ioctl :: uintptr(29)
SYS_ioprio_set :: uintptr(30)
SYS_ioprio_get :: uintptr(31)
SYS_flock :: uintptr(32)
SYS_mknodat :: uintptr(33)
SYS_mkdirat :: uintptr(34)
SYS_unlinkat :: uintptr(35)
SYS_symlinkat :: uintptr(36)
SYS_linkat :: uintptr(37)
SYS_renameat :: uintptr(38)
SYS_umount2 :: uintptr(39)
SYS_mount :: uintptr(40)
SYS_pivot_root :: uintptr(41)
SYS_nfsservctl :: uintptr(42)
SYS_statfs :: uintptr(43)
SYS_fstatfs :: uintptr(44)
SYS_truncate :: uintptr(45)
SYS_ftruncate :: uintptr(46)
SYS_fallocate :: uintptr(47)
SYS_faccessat :: uintptr(48)
SYS_chdir :: uintptr(49)
SYS_fchdir :: uintptr(50)
SYS_chroot :: uintptr(51)
SYS_fchmod :: uintptr(52)
SYS_fchmodat :: uintptr(53)
SYS_fchownat :: uintptr(54)
SYS_fchown :: uintptr(55)
SYS_openat :: uintptr(56)
SYS_close :: uintptr(57)
SYS_vhangup :: uintptr(58)
SYS_pipe2 :: uintptr(59)
SYS_quotactl :: uintptr(60)
SYS_getdents64 :: uintptr(61)
SYS_lseek :: uintptr(62)
SYS_read :: uintptr(63)
SYS_write :: uintptr(64)
SYS_readv :: uintptr(65)
SYS_writev :: uintptr(66)
SYS_pread64 :: uintptr(67)
SYS_pwrite64 :: uintptr(68)
SYS_preadv :: uintptr(69)
SYS_pwritev :: uintptr(70)
SYS_sendfile :: uintptr(71)
SYS_pselect6 :: uintptr(72)
SYS_ppoll :: uintptr(73)
SYS_signalfd4 :: uintptr(74)
SYS_vmsplice :: uintptr(75)
SYS_splice :: uintptr(76)
SYS_tee :: uintptr(77)
SYS_readlinkat :: uintptr(78)
SYS_fstatat :: uintptr(79)
SYS_fstat :: uintptr(80)
SYS_sync :: uintptr(81)
SYS_fsync :: uintptr(82)
SYS_fdatasync :: uintptr(83)
SYS_sync_file_range :: uintptr(84)
SYS_timerfd_create :: uintptr(85)
SYS_timerfd_settime :: uintptr(86)
SYS_timerfd_gettime :: uintptr(87)
SYS_utimensat :: uintptr(88)
SYS_acct :: uintptr(89)
SYS_capget :: uintptr(90)
SYS_capset :: uintptr(91)
SYS_personality :: uintptr(92)
SYS_exit :: uintptr(93)
SYS_exit_group :: uintptr(94)
SYS_waitid :: uintptr(95)
SYS_set_tid_address :: uintptr(96)
SYS_unshare :: uintptr(97)
SYS_futex :: uintptr(98)
SYS_set_robust_list :: uintptr(99)
SYS_get_robust_list :: uintptr(100)
SYS_nanosleep :: uintptr(101)
SYS_getitimer :: uintptr(102)
SYS_setitimer :: uintptr(103)
SYS_kexec_load :: uintptr(104)
SYS_init_module :: uintptr(105)
SYS_delete_module :: uintptr(106)
SYS_timer_create :: uintptr(107)
SYS_timer_gettime :: uintptr(108)
SYS_timer_getoverrun :: uintptr(109)
SYS_timer_settime :: uintptr(110)
SYS_timer_delete :: uintptr(111)
SYS_clock_settime :: uintptr(112)
SYS_clock_gettime :: uintptr(113)
SYS_clock_getres :: uintptr(114)
SYS_clock_nanosleep :: uintptr(115)
SYS_syslog :: uintptr(116)
SYS_ptrace :: uintptr(117)
SYS_sched_setparam :: uintptr(118)
SYS_sched_setscheduler :: uintptr(119)
SYS_sched_getscheduler :: uintptr(120)
SYS_sched_getparam :: uintptr(121)
SYS_sched_setaffinity :: uintptr(122)
SYS_sched_getaffinity :: uintptr(123)
SYS_sched_yield :: uintptr(124)
SYS_sched_get_priority_max :: uintptr(125)
SYS_sched_get_priority_min :: uintptr(126)
SYS_sched_rr_get_interval :: uintptr(127)
SYS_restart_syscall :: uintptr(128)
SYS_kill :: uintptr(129)
SYS_tkill :: uintptr(130)
SYS_tgkill :: uintptr(131)
SYS_sigaltstack :: uintptr(132)
SYS_rt_sigsuspend :: uintptr(133)
SYS_rt_sigaction :: uintptr(134)
SYS_rt_sigprocmask :: uintptr(135)
SYS_rt_sigpending :: uintptr(136)
SYS_rt_sigtimedwait :: uintptr(137)
SYS_rt_sigqueueinfo :: uintptr(138)
SYS_rt_sigreturn :: uintptr(139)
SYS_setpriority :: uintptr(140)
SYS_getpriority :: uintptr(141)
SYS_reboot :: uintptr(142)
SYS_setregid :: uintptr(143)
SYS_setgid :: uintptr(144)
SYS_setreuid :: uintptr(145)
SYS_setuid :: uintptr(146)
SYS_setresuid :: uintptr(147)
SYS_getresuid :: uintptr(148)
SYS_setresgid :: uintptr(149)
SYS_getresgid :: uintptr(150)
SYS_setfsuid :: uintptr(151)
SYS_setfsgid :: uintptr(152)
SYS_times :: uintptr(153)
SYS_setpgid :: uintptr(154)
SYS_getpgid :: uintptr(155)
SYS_getsid :: uintptr(156)
SYS_setsid :: uintptr(157)
SYS_getgroups :: uintptr(158)
SYS_setgroups :: uintptr(159)
SYS_uname :: uintptr(160)
SYS_sethostname :: uintptr(161)
SYS_setdomainname :: uintptr(162)
SYS_getrlimit :: uintptr(163)
SYS_setrlimit :: uintptr(164)
SYS_getrusage :: uintptr(165)
SYS_umask :: uintptr(166)
SYS_prctl :: uintptr(167)
SYS_getcpu :: uintptr(168)
SYS_gettimeofday :: uintptr(169)
SYS_settimeofday :: uintptr(170)
SYS_adjtimex :: uintptr(171)
SYS_getpid :: uintptr(172)
SYS_getppid :: uintptr(173)
SYS_getuid :: uintptr(174)
SYS_geteuid :: uintptr(175)
SYS_getgid :: uintptr(176)
SYS_getegid :: uintptr(177)
SYS_gettid :: uintptr(178)
SYS_sysinfo :: uintptr(179)
SYS_mq_open :: uintptr(180)
SYS_mq_unlink :: uintptr(181)
SYS_mq_timedsend :: uintptr(182)
SYS_mq_timedreceive :: uintptr(183)
SYS_mq_notify :: uintptr(184)
SYS_mq_getsetattr :: uintptr(185)
SYS_msgget :: uintptr(186)
SYS_msgctl :: uintptr(187)
SYS_msgrcv :: uintptr(188)
SYS_msgsnd :: uintptr(189)
SYS_semget :: uintptr(190)
SYS_semctl :: uintptr(191)
SYS_semtimedop :: uintptr(192)
SYS_semop :: uintptr(193)
SYS_shmget :: uintptr(194)
SYS_shmctl :: uintptr(195)
SYS_shmat :: uintptr(196)
SYS_shmdt :: uintptr(197)
SYS_socket :: uintptr(198)
SYS_socketpair :: uintptr(199)
SYS_bind :: uintptr(200)
SYS_listen :: uintptr(201)
SYS_accept :: uintptr(202)
SYS_connect :: uintptr(203)
SYS_getsockname :: uintptr(204)
SYS_getpeername :: uintptr(205)
SYS_sendto :: uintptr(206)
SYS_recvfrom :: uintptr(207)
SYS_setsockopt :: uintptr(208)
SYS_getsockopt :: uintptr(209)
SYS_shutdown :: uintptr(210)
SYS_sendmsg :: uintptr(211)
SYS_recvmsg :: uintptr(212)
SYS_readahead :: uintptr(213)
SYS_brk :: uintptr(214)
SYS_munmap :: uintptr(215)
SYS_mremap :: uintptr(216)
SYS_add_key :: uintptr(217)
SYS_request_key :: uintptr(218)
SYS_keyctl :: uintptr(219)
SYS_clone :: uintptr(220)
SYS_execve :: uintptr(221)
SYS_mmap :: uintptr(222)
SYS_fadvise64 :: uintptr(223)
/* CONFIG_MMU only */
SYS_swapon :: uintptr(224)
SYS_swapoff :: uintptr(225)
SYS_mprotect :: uintptr(226)
SYS_msync :: uintptr(227)
SYS_mlock :: uintptr(228)
SYS_munlock :: uintptr(229)
SYS_mlockall :: uintptr(230)
SYS_munlockall :: uintptr(231)
SYS_mincore :: uintptr(232)
SYS_madvise :: uintptr(233)
SYS_remap_file_pages :: uintptr(234)
SYS_mbind :: uintptr(235)
SYS_get_mempolicy :: uintptr(236)
SYS_set_mempolicy :: uintptr(237)
SYS_migrate_pages :: uintptr(238)
SYS_move_pages :: uintptr(239)
SYS_rt_tgsigqueueinfo :: uintptr(240)
SYS_perf_event_open :: uintptr(241)
SYS_accept4 :: uintptr(242)
SYS_recvmmsg :: uintptr(243)
SYS_wait4 :: uintptr(260)
SYS_prlimit64 :: uintptr(261)
SYS_fanotify_init :: uintptr(262)
SYS_fanotify_mark :: uintptr(263)
SYS_name_to_handle_at :: uintptr(264)
SYS_open_by_handle_at :: uintptr(265)
SYS_clock_adjtime :: uintptr(266)
SYS_syncfs :: uintptr(267)
SYS_setns :: uintptr(268)
SYS_sendmmsg :: uintptr(269)
SYS_process_vm_readv :: uintptr(270)
SYS_process_vm_writev :: uintptr(271)
SYS_kcmp :: uintptr(272)
SYS_finit_module :: uintptr(273)
SYS_sched_setattr :: uintptr(274)
SYS_sched_getattr :: uintptr(275)
SYS_renameat2 :: uintptr(276)
SYS_seccomp :: uintptr(277)
SYS_getrandom :: uintptr(278)
SYS_memfd_create :: uintptr(279)
SYS_bpf :: uintptr(280)
SYS_execveat :: uintptr(281)
SYS_userfaultfd :: uintptr(282)
SYS_membarrier :: uintptr(283)
SYS_mlock2 :: uintptr(284)
SYS_copy_file_range :: uintptr(285)
SYS_preadv2 :: uintptr(286)
SYS_pwritev2 :: uintptr(287)
SYS_pkey_mprotect :: uintptr(288)
SYS_pkey_alloc :: uintptr(289)
SYS_pkey_free :: uintptr(290)
SYS_statx :: uintptr(291)
SYS_io_pgetevents :: uintptr(292)
SYS_rseq :: uintptr(293)
SYS_kexec_file_load :: uintptr(294)
SYS_pidfd_send_signal :: uintptr(424)
SYS_io_uring_setup :: uintptr(425)
SYS_io_uring_enter :: uintptr(426)
SYS_io_uring_register :: uintptr(427)
SYS_open_tree :: uintptr(428)
SYS_move_mount :: uintptr(429)
SYS_fsopen :: uintptr(430)
SYS_fsconfig :: uintptr(431)
SYS_fsmount :: uintptr(432)
SYS_fspick :: uintptr(433)
SYS_pidfd_open :: uintptr(434)
SYS_clone3 :: uintptr(435)
SYS_close_range :: uintptr(436)
SYS_openat2 :: uintptr(437)
SYS_pidfd_getfd :: uintptr(438)
SYS_faccessat2 :: uintptr(439)
SYS_process_madvise :: uintptr(440)
SYS_epoll_pwait2 :: uintptr(441)
SYS_mount_setattr :: uintptr(442)
SYS_quotactl_fd :: uintptr(443)
SYS_landlock_create_ruleset :: uintptr(444)
SYS_landlock_add_rule :: uintptr(445)
SYS_landlock_restrict_self :: uintptr(446)
SYS_memfd_secret :: uintptr(447)
SYS_process_mrelease :: uintptr(448)
SYS_futex_waitv :: uintptr(449)
SYS_set_mempolicy_home_node :: uintptr(450)
SYS_cachestat :: uintptr(451)
SYS_fchmodat2 :: uintptr(452)
+458
View File
@@ -0,0 +1,458 @@
//+build i386
package linux
// The numbers are taken from
// /arch/x86/entry/syscalls/syscall_32.tbl
// in Linux headers. Only x64 and common ABI
// syscalls were taken, for x32 is not
// supported by Odin
// This syscall is only used by the kernel internally
// userspace has no reason to use it.
SYS_restart_syscall :: uintptr(0)
SYS_exit :: uintptr(1)
SYS_fork :: uintptr(2)
SYS_read :: uintptr(3)
SYS_write :: uintptr(4)
SYS_open :: uintptr(5)
SYS_close :: uintptr(6)
SYS_waitpid :: uintptr(7)
SYS_creat :: uintptr(8)
SYS_link :: uintptr(9)
SYS_unlink :: uintptr(10)
SYS_execve :: uintptr(11)
SYS_chdir :: uintptr(12)
SYS_time :: uintptr(13)
SYS_mknod :: uintptr(14)
SYS_chmod :: uintptr(15)
SYS_lchown :: uintptr(16)
SYS_break :: uintptr(17)
SYS_oldstat :: uintptr(18)
SYS_lseek :: uintptr(19)
SYS_getpid :: uintptr(20)
SYS_mount :: uintptr(21)
SYS_umount :: uintptr(22)
SYS_setuid :: uintptr(23)
SYS_getuid :: uintptr(24)
SYS_stime :: uintptr(25)
SYS_ptrace :: uintptr(26)
SYS_alarm :: uintptr(27)
SYS_oldfstat :: uintptr(28)
SYS_pause :: uintptr(29)
SYS_utime :: uintptr(30)
SYS_stty :: uintptr(31)
SYS_gtty :: uintptr(32)
SYS_access :: uintptr(33)
SYS_nice :: uintptr(34)
SYS_ftime :: uintptr(35)
SYS_sync :: uintptr(36)
SYS_kill :: uintptr(37)
SYS_rename :: uintptr(38)
SYS_mkdir :: uintptr(39)
SYS_rmdir :: uintptr(40)
SYS_dup :: uintptr(41)
SYS_pipe :: uintptr(42)
SYS_times :: uintptr(43)
SYS_prof :: uintptr(44)
SYS_brk :: uintptr(45)
SYS_setgid :: uintptr(46)
SYS_getgid :: uintptr(47)
SYS_signal :: uintptr(48)
SYS_geteuid :: uintptr(49)
SYS_getegid :: uintptr(50)
SYS_acct :: uintptr(51)
SYS_umount2 :: uintptr(52)
SYS_lock :: uintptr(53)
SYS_ioctl :: uintptr(54)
SYS_fcntl :: uintptr(55)
SYS_mpx :: uintptr(56)
SYS_setpgid :: uintptr(57)
SYS_ulimit :: uintptr(58)
SYS_oldolduname :: uintptr(59)
SYS_umask :: uintptr(60)
SYS_chroot :: uintptr(61)
SYS_ustat :: uintptr(62)
SYS_dup2 :: uintptr(63)
SYS_getppid :: uintptr(64)
SYS_getpgrp :: uintptr(65)
SYS_setsid :: uintptr(66)
SYS_sigaction :: uintptr(67)
SYS_sgetmask :: uintptr(68)
SYS_ssetmask :: uintptr(69)
SYS_setreuid :: uintptr(70)
SYS_setregid :: uintptr(71)
SYS_sigsuspend :: uintptr(72)
SYS_sigpending :: uintptr(73)
SYS_sethostname :: uintptr(74)
SYS_setrlimit :: uintptr(75)
SYS_getrlimit :: uintptr(76)
SYS_getrusage :: uintptr(77)
SYS_gettimeofday :: uintptr(78)
SYS_settimeofday :: uintptr(79)
SYS_getgroups :: uintptr(80)
SYS_setgroups :: uintptr(81)
SYS_select :: uintptr(82)
SYS_symlink :: uintptr(83)
SYS_oldlstat :: uintptr(84)
SYS_readlink :: uintptr(85)
SYS_uselib :: uintptr(86)
SYS_swapon :: uintptr(87)
SYS_reboot :: uintptr(88)
SYS_readdir :: uintptr(89)
SYS_mmap :: uintptr(90)
SYS_munmap :: uintptr(91)
SYS_truncate :: uintptr(92)
SYS_ftruncate :: uintptr(93)
SYS_fchmod :: uintptr(94)
SYS_fchown :: uintptr(95)
SYS_getpriority :: uintptr(96)
SYS_setpriority :: uintptr(97)
SYS_profil :: uintptr(98)
SYS_statfs :: uintptr(99)
SYS_fstatfs :: uintptr(100)
SYS_ioperm :: uintptr(101)
SYS_socketcall :: uintptr(102)
SYS_syslog :: uintptr(103)
SYS_setitimer :: uintptr(104)
SYS_getitimer :: uintptr(105)
SYS_stat :: uintptr(106)
SYS_lstat :: uintptr(107)
SYS_fstat :: uintptr(108)
SYS_olduname :: uintptr(109)
SYS_iopl :: uintptr(110)
SYS_vhangup :: uintptr(111)
SYS_idle :: uintptr(112)
SYS_vm86old :: uintptr(113)
SYS_wait4 :: uintptr(114)
SYS_swapoff :: uintptr(115)
SYS_sysinfo :: uintptr(116)
SYS_ipc :: uintptr(117)
SYS_fsync :: uintptr(118)
SYS_sigreturn :: uintptr(119)
SYS_clone :: uintptr(120)
SYS_setdomainname :: uintptr(121)
SYS_uname :: uintptr(122)
SYS_modify_ldt :: uintptr(123)
SYS_adjtimex :: uintptr(124)
SYS_mprotect :: uintptr(125)
SYS_sigprocmask :: uintptr(126)
SYS_create_module :: uintptr(127)
SYS_init_module :: uintptr(128)
SYS_delete_module :: uintptr(129)
SYS_get_kernel_syms :: uintptr(130)
SYS_quotactl :: uintptr(131)
SYS_getpgid :: uintptr(132)
SYS_fchdir :: uintptr(133)
SYS_bdflush :: uintptr(134)
SYS_sysfs :: uintptr(135)
SYS_personality :: uintptr(136)
SYS_afs_syscall :: uintptr(137)
SYS_setfsuid :: uintptr(138)
SYS_setfsgid :: uintptr(139)
SYS__llseek :: uintptr(140)
SYS_getdents :: uintptr(141)
SYS__newselect :: uintptr(142)
SYS_flock :: uintptr(143)
SYS_msync :: uintptr(144)
SYS_readv :: uintptr(145)
SYS_writev :: uintptr(146)
SYS_getsid :: uintptr(147)
SYS_fdatasync :: uintptr(148)
SYS__sysctl :: uintptr(149)
SYS_mlock :: uintptr(150)
SYS_munlock :: uintptr(151)
SYS_mlockall :: uintptr(152)
SYS_munlockall :: uintptr(153)
SYS_sched_setparam :: uintptr(154)
SYS_sched_getparam :: uintptr(155)
SYS_sched_setscheduler :: uintptr(156)
SYS_sched_getscheduler :: uintptr(157)
SYS_sched_yield :: uintptr(158)
SYS_sched_get_priority_max :: uintptr(159)
SYS_sched_get_priority_min :: uintptr(160)
SYS_sched_rr_get_interval :: uintptr(161)
SYS_nanosleep :: uintptr(162)
SYS_mremap :: uintptr(163)
SYS_setresuid :: uintptr(164)
SYS_getresuid :: uintptr(165)
SYS_vm86 :: uintptr(166)
SYS_query_module :: uintptr(167)
SYS_poll :: uintptr(168)
SYS_nfsservctl :: uintptr(169)
SYS_setresgid :: uintptr(170)
SYS_getresgid :: uintptr(171)
SYS_prctl :: uintptr(172)
SYS_rt_sigreturn :: uintptr(173)
SYS_rt_sigaction :: uintptr(174)
SYS_rt_sigprocmask :: uintptr(175)
SYS_rt_sigpending :: uintptr(176)
SYS_rt_sigtimedwait :: uintptr(177)
SYS_rt_sigqueueinfo :: uintptr(178)
SYS_rt_sigsuspend :: uintptr(179)
SYS_pread64 :: uintptr(180)
SYS_pwrite64 :: uintptr(181)
SYS_chown :: uintptr(182)
SYS_getcwd :: uintptr(183)
SYS_capget :: uintptr(184)
SYS_capset :: uintptr(185)
SYS_sigaltstack :: uintptr(186)
SYS_sendfile :: uintptr(187)
SYS_getpmsg :: uintptr(188)
SYS_putpmsg :: uintptr(189)
SYS_vfork :: uintptr(190)
SYS_ugetrlimit :: uintptr(191)
SYS_mmap2 :: uintptr(192)
SYS_truncate64 :: uintptr(193)
SYS_ftruncate64 :: uintptr(194)
SYS_stat64 :: uintptr(195)
SYS_lstat64 :: uintptr(196)
SYS_fstat64 :: uintptr(197)
SYS_lchown32 :: uintptr(198)
SYS_getuid32 :: uintptr(199)
SYS_getgid32 :: uintptr(200)
SYS_geteuid32 :: uintptr(201)
SYS_getegid32 :: uintptr(202)
SYS_setreuid32 :: uintptr(203)
SYS_setregid32 :: uintptr(204)
SYS_getgroups32 :: uintptr(205)
SYS_setgroups32 :: uintptr(206)
SYS_fchown32 :: uintptr(207)
SYS_setresuid32 :: uintptr(208)
SYS_getresuid32 :: uintptr(209)
SYS_setresgid32 :: uintptr(210)
SYS_getresgid32 :: uintptr(211)
SYS_chown32 :: uintptr(212)
SYS_setuid32 :: uintptr(213)
SYS_setgid32 :: uintptr(214)
SYS_setfsuid32 :: uintptr(215)
SYS_setfsgid32 :: uintptr(216)
SYS_pivot_root :: uintptr(217)
SYS_mincore :: uintptr(218)
SYS_madvise :: uintptr(219)
SYS_getdents64 :: uintptr(220)
SYS_fcntl64 :: uintptr(221)
// 222 is unused
// 223 is unused
SYS_gettid :: uintptr(224)
SYS_readahead :: uintptr(225)
SYS_setxattr :: uintptr(226)
SYS_lsetxattr :: uintptr(227)
SYS_fsetxattr :: uintptr(228)
SYS_getxattr :: uintptr(229)
SYS_lgetxattr :: uintptr(230)
SYS_fgetxattr :: uintptr(231)
SYS_listxattr :: uintptr(232)
SYS_llistxattr :: uintptr(233)
SYS_flistxattr :: uintptr(234)
SYS_removexattr :: uintptr(235)
SYS_lremovexattr :: uintptr(236)
SYS_fremovexattr :: uintptr(237)
SYS_tkill :: uintptr(238)
SYS_sendfile64 :: uintptr(239)
SYS_futex :: uintptr(240)
SYS_sched_setaffinity :: uintptr(241)
SYS_sched_getaffinity :: uintptr(242)
SYS_set_thread_area :: uintptr(243)
SYS_get_thread_area :: uintptr(244)
SYS_io_setup :: uintptr(245)
SYS_io_destroy :: uintptr(246)
SYS_io_getevents :: uintptr(247)
SYS_io_submit :: uintptr(248)
SYS_io_cancel :: uintptr(249)
SYS_fadvise64 :: uintptr(250)
// 251 is available for reuse (was briefly sys_set_zone_reclaim)
SYS_exit_group :: uintptr(252)
SYS_lookup_dcookie :: uintptr(253)
SYS_epoll_create :: uintptr(254)
SYS_epoll_ctl :: uintptr(255)
SYS_epoll_wait :: uintptr(256)
SYS_remap_file_pages :: uintptr(257)
SYS_set_tid_address :: uintptr(258)
SYS_timer_create :: uintptr(259)
SYS_timer_settime :: uintptr(260)
SYS_timer_gettime :: uintptr(261)
SYS_timer_getoverrun :: uintptr(262)
SYS_timer_delete :: uintptr(263)
SYS_clock_settime :: uintptr(264)
SYS_clock_gettime :: uintptr(265)
SYS_clock_getres :: uintptr(266)
SYS_clock_nanosleep :: uintptr(267)
SYS_statfs64 :: uintptr(268)
SYS_fstatfs64 :: uintptr(269)
SYS_tgkill :: uintptr(270)
SYS_utimes :: uintptr(271)
SYS_fadvise64_64 :: uintptr(272)
SYS_vserver :: uintptr(273)
SYS_mbind :: uintptr(274)
SYS_get_mempolicy :: uintptr(275)
SYS_set_mempolicy :: uintptr(276)
SYS_mq_open :: uintptr(277)
SYS_mq_unlink :: uintptr(278)
SYS_mq_timedsend :: uintptr(279)
SYS_mq_timedreceive :: uintptr(280)
SYS_mq_notify :: uintptr(281)
SYS_mq_getsetattr :: uintptr(282)
SYS_kexec_load :: uintptr(283)
SYS_waitid :: uintptr(284)
// 285 sys_setaltroot
SYS_add_key :: uintptr(286)
SYS_request_key :: uintptr(287)
SYS_keyctl :: uintptr(288)
SYS_ioprio_set :: uintptr(289)
SYS_ioprio_get :: uintptr(290)
SYS_inotify_init :: uintptr(291)
SYS_inotify_add_watch :: uintptr(292)
SYS_inotify_rm_watch :: uintptr(293)
SYS_migrate_pages :: uintptr(294)
SYS_openat :: uintptr(295)
SYS_mkdirat :: uintptr(296)
SYS_mknodat :: uintptr(297)
SYS_fchownat :: uintptr(298)
SYS_futimesat :: uintptr(299)
SYS_fstatat64 :: uintptr(300)
SYS_unlinkat :: uintptr(301)
SYS_renameat :: uintptr(302)
SYS_linkat :: uintptr(303)
SYS_symlinkat :: uintptr(304)
SYS_readlinkat :: uintptr(305)
SYS_fchmodat :: uintptr(306)
SYS_faccessat :: uintptr(307)
SYS_pselect6 :: uintptr(308)
SYS_ppoll :: uintptr(309)
SYS_unshare :: uintptr(310)
SYS_set_robust_list :: uintptr(311)
SYS_get_robust_list :: uintptr(312)
SYS_splice :: uintptr(313)
SYS_sync_file_range :: uintptr(314)
SYS_tee :: uintptr(315)
SYS_vmsplice :: uintptr(316)
SYS_move_pages :: uintptr(317)
SYS_getcpu :: uintptr(318)
SYS_epoll_pwait :: uintptr(319)
SYS_utimensat :: uintptr(320)
SYS_signalfd :: uintptr(321)
SYS_timerfd_create :: uintptr(322)
SYS_eventfd :: uintptr(323)
SYS_fallocate :: uintptr(324)
SYS_timerfd_settime :: uintptr(325)
SYS_timerfd_gettime :: uintptr(326)
SYS_signalfd4 :: uintptr(327)
SYS_eventfd2 :: uintptr(328)
SYS_epoll_create1 :: uintptr(329)
SYS_dup3 :: uintptr(330)
SYS_pipe2 :: uintptr(331)
SYS_inotify_init1 :: uintptr(332)
SYS_preadv :: uintptr(333)
SYS_pwritev :: uintptr(334)
SYS_rt_tgsigqueueinfo :: uintptr(335)
SYS_perf_event_open :: uintptr(336)
SYS_recvmmsg :: uintptr(337)
SYS_fanotify_init :: uintptr(338)
SYS_fanotify_mark :: uintptr(339)
SYS_prlimit64 :: uintptr(340)
SYS_name_to_handle_at :: uintptr(341)
SYS_open_by_handle_at :: uintptr(342)
SYS_clock_adjtime :: uintptr(343)
SYS_syncfs :: uintptr(344)
SYS_sendmmsg :: uintptr(345)
SYS_setns :: uintptr(346)
SYS_process_vm_readv :: uintptr(347)
SYS_process_vm_writev :: uintptr(348)
SYS_kcmp :: uintptr(349)
SYS_finit_module :: uintptr(350)
SYS_sched_setattr :: uintptr(351)
SYS_sched_getattr :: uintptr(352)
SYS_renameat2 :: uintptr(353)
SYS_seccomp :: uintptr(354)
SYS_getrandom :: uintptr(355)
SYS_memfd_create :: uintptr(356)
SYS_bpf :: uintptr(357)
SYS_execveat :: uintptr(358)
SYS_socket :: uintptr(359)
SYS_socketpair :: uintptr(360)
SYS_bind :: uintptr(361)
SYS_connect :: uintptr(362)
SYS_listen :: uintptr(363)
SYS_accept4 :: uintptr(364)
SYS_getsockopt :: uintptr(365)
SYS_setsockopt :: uintptr(366)
SYS_getsockname :: uintptr(367)
SYS_getpeername :: uintptr(368)
SYS_sendto :: uintptr(369)
SYS_sendmsg :: uintptr(370)
SYS_recvfrom :: uintptr(371)
SYS_recvmsg :: uintptr(372)
SYS_shutdown :: uintptr(373)
SYS_userfaultfd :: uintptr(374)
SYS_membarrier :: uintptr(375)
SYS_mlock2 :: uintptr(376)
SYS_copy_file_range :: uintptr(377)
SYS_preadv2 :: uintptr(378)
SYS_pwritev2 :: uintptr(379)
SYS_pkey_mprotect :: uintptr(380)
SYS_pkey_alloc :: uintptr(381)
SYS_pkey_free :: uintptr(382)
SYS_statx :: uintptr(383)
SYS_arch_prctl :: uintptr(384)
SYS_io_pgetevents :: uintptr(385)
SYS_rseq :: uintptr(386)
SYS_semget :: uintptr(393)
SYS_semctl :: uintptr(394)
SYS_shmget :: uintptr(395)
SYS_shmctl :: uintptr(396)
SYS_shmat :: uintptr(397)
SYS_shmdt :: uintptr(398)
SYS_msgget :: uintptr(399)
SYS_msgsnd :: uintptr(400)
SYS_msgrcv :: uintptr(401)
SYS_msgctl :: uintptr(402)
SYS_clock_gettime64 :: uintptr(403)
SYS_clock_settime64 :: uintptr(404)
SYS_clock_adjtime64 :: uintptr(405)
SYS_clock_getres_time64 :: uintptr(406)
SYS_clock_nanosleep_time64 :: uintptr(407)
SYS_timer_gettime64 :: uintptr(408)
SYS_timer_settime64 :: uintptr(409)
SYS_timerfd_gettime64 :: uintptr(410)
SYS_timerfd_settime64 :: uintptr(411)
SYS_utimensat_time64 :: uintptr(412)
SYS_pselect6_time64 :: uintptr(413)
SYS_ppoll_time64 :: uintptr(414)
SYS_io_pgetevents_time64 :: uintptr(416)
SYS_recvmmsg_time64 :: uintptr(417)
SYS_mq_timedsend_time64 :: uintptr(418)
SYS_mq_timedreceive_time64 :: uintptr(419)
SYS_semtimedop_time64 :: uintptr(420)
SYS_rt_sigtimedwait_time64 :: uintptr(421)
SYS_futex_time64 :: uintptr(422)
SYS_sched_rr_get_interval_time64 :: uintptr(423)
SYS_pidfd_send_signal :: uintptr(424)
SYS_io_uring_setup :: uintptr(425)
SYS_io_uring_enter :: uintptr(426)
SYS_io_uring_register :: uintptr(427)
SYS_open_tree :: uintptr(428)
SYS_move_mount :: uintptr(429)
SYS_fsopen :: uintptr(430)
SYS_fsconfig :: uintptr(431)
SYS_fsmount :: uintptr(432)
SYS_fspick :: uintptr(433)
SYS_pidfd_open :: uintptr(434)
SYS_clone3 :: uintptr(435)
SYS_close_range :: uintptr(436)
SYS_openat2 :: uintptr(437)
SYS_pidfd_getfd :: uintptr(438)
SYS_faccessat2 :: uintptr(439)
SYS_process_madvise :: uintptr(440)
SYS_epoll_pwait2 :: uintptr(441)
SYS_mount_setattr :: uintptr(442)
SYS_quotactl_fd :: uintptr(443)
SYS_landlock_create_ruleset :: uintptr(444)
SYS_landlock_add_rule :: uintptr(445)
SYS_landlock_restrict_self :: uintptr(446)
SYS_memfd_secret :: uintptr(447)
SYS_process_mrelease :: uintptr(448)
SYS_futex_waitv :: uintptr(449)
SYS_set_mempolicy_home_node :: uintptr(450)
SYS_cachestat :: uintptr(451)
SYS_fchmodat2 :: uintptr(452)
+566
View File
@@ -0,0 +1,566 @@
//+build linux
package linux
/// Represents storage device handle
Dev :: distinct int
/// Represents 32-bit user id
Uid :: distinct u32
/// Represents 32-bit group id
Gid :: distinct u32
/// Process id's
Pid :: distinct int
/// Represents pid, pifd, pgid values in general
Id :: distinct uint
/// Represents a file descriptor
Fd :: distinct i32
/// Represents a PID file descriptor
Pid_FD :: distinct i32
/// Represents 64-bit inode number for files
/// Used pretty much only in struct Stat64 for 32-bit platforms
Inode :: distinct u64
/// Represents time with nanosecond precision
Time_Spec :: struct {
time_sec: uint,
time_nsec: uint,
}
/// Represents time with millisecond precision
Time_Val :: struct {
seconds: int,
microseconds: int,
}
/// open.2 flags
Open_Flags :: bit_set[Open_Flags_Bits; u32]
/// Flags for the file descriptor to be passed in some syscalls
FD_Flags :: bit_set[FD_Flags_Bits; i32]
/// Represents file's permission and status bits
/// Example:
/// When you're passing a value of this type the recommended usage is
/// sys.Mode{.S_IXOTH, .S_IROTH} | sys.S_IRWXU | sys.S_IRWXG
/// This would generate a mode that has full permissions for the
/// file's owner and group, and only "read" and "execute" bits
/// for others.
Mode :: bit_set[Mode_Bits; u32]
when ODIN_ARCH == .amd64 {
// x86-64 has mode and nlink swapped for some reason
_Arch_Stat :: struct {
dev: Dev,
ino: Inode,
nlink: uint,
mode: Mode,
uid: Uid,
gid: Gid,
_: u32,
rdev: Dev,
size: uint,
blksize: uint,
blocks: uint,
atime: Time_Spec,
mtime: Time_Spec,
ctime: Time_Spec,
_: [3]uint,
}
} else when ODIN_ARCH == .arm64 {
_Arch_Stat :: struct {
dev: Dev,
ino: Inode,
mode: Mode,
nlink: u32,
uid: Uid,
gid: Gid,
rdev: Dev,
_: u64,
size: int,
blksize: i32,
_: i32,
blocks: int,
atime: Time_Spec,
mtime: Time_Spec,
ctime: Time_Spec,
_: [3]uint,
}
} else {
_Arch_Stat :: struct {
dev: Dev,
_: [4]u8,
_ino: uint, // Old 32-bit inode number, don't use
mode: Mode,
nlink: u32,
uid: Uid,
gid: Gid,
rdev: Dev,
size: i64,
blksize: uint,
blocks: u64,
atim: Time_Spec,
mtim: Time_Spec,
ctim: Time_Spec,
ino: Inode,
}
}
/// Represents the file state.
/// Mirrors struct stat in glibc/linux kernel.
/// If you're on 32-bit platform, consider using Stat64 instead
Stat :: struct {
using _impl_stat: _Arch_Stat,
}
/// Timestamp type used for Statx struct
Statx_Timestamp :: struct {
sec: i64,
nsec: u32,
_: i32,
}
/// Query params/results for `statx()`
Statx_Mask :: bit_set[Statx_Mask_Bits; u32]
/// File attributes, returned by statx. This bitset is also
/// used to specify which attributes are present, not just
/// their value.
Statx_Attr :: bit_set[Statx_Attr_Bits; u64]
/// The extended Stat struct
Statx :: struct {
mask: Statx_Mask,
blksize: u32,
attributes: Statx_Attr,
nlink: u32,
uid: Uid,
gid: Gid,
// Note(flysand): mode is 16-bit on linux + there's
// 16-bit padding following it. Since our mode is 32-bits,
// we're using the padding. This should be fine because
// the placement of that padding suggests it was going to
// be used for the Mode bits anyway.
mode: Mode,
ino: Inode,
size: u64,
blocks: u64,
attributes_mask: Statx_Attr,
atime: Statx_Timestamp,
btime: Statx_Timestamp,
ctime: Statx_Timestamp,
mtime: Statx_Timestamp,
rdev_major: u32,
rdev_minor: u32,
dev_major: u32,
dev_minor: u32,
mnt_id: u64,
dio_mem_align: u32,
dio_offset_align: u32,
_: [12]u64,
}
/// Mount flags for filesystem
FS_Flags :: bit_set[FS_Flags_Bits; u32]
when size_of(int) == 8 {
_Arch_Stat_FS :: struct {
// Note(flysand): The FS_Magic bits are never above
// 32-bits, so it should be fine for now...
type: FS_Magic,
_: u32,
bsize: i64,
blocks: i64,
bfree: i64,
bavail: i64,
files: i64,
ffree: i64,
fsid : [2]i32,
namelen: i64,
frsize: i64,
// Note(flysand): Same story as type
flags: FS_Flags,
_: u32,
spare: [4]i64,
}
} else {
_Arch_Stat_FS :: struct {
type: FS_Magic,
bsize: u32,
blocks: u64,
bfree: u64,
bavail: u64,
files: u64,
ffree: u64,
fsid: [2]i32,
namelen: u32,
frsize: u32,
flags: FS_Flags,
spare: [4]u32,
}
}
Stat_FS :: struct {
using _impl_stat_fs: _Arch_Stat_FS,
}
/// Flags for close_range.2
Close_Range_Flags :: bit_set[Close_Range_Flags_Bits; u32]
/// Flags for rename.2
Rename_Flags :: bit_set[Rename_Flags_Bits; u32]
/// Directory entry
/// Recommended to use this with dirent_iterator()
/// and dirent_name()
Dirent :: struct {
ino: Inode,
off: i64,
reclen: u16,
type: Dirent_Type,
name: [0]u8, // See dirent_name
}
/// Lock record for fcntl.2
FLock :: struct {
type: FLock_Type,
whence: Seek_Whence,
start: i64,
len: i64,
pid: Pid,
}
/// Flags for fcntl_notify
FD_Notifications :: bit_set[FD_Notifications_Bits; i32]
/// Seals for fcntl_add_seals
Seal :: bit_set[Seal_Bits; i32]
/// Represents owner that receives events on file updates
F_Owner :: struct {
type: F_Owner_Type,
pid: Pid,
}
/// Events for ppoll
Fd_Poll_Events :: bit_set[Fd_Poll_Events_Bits; u16]
/// Struct for ppoll
Poll_Fd :: struct {
fd: Fd,
events: Fd_Poll_Events,
revents: Fd_Poll_Events,
}
/// Specifies protection for memory pages
Mem_Protection :: bit_set[Mem_Protection_Bits; i32]
/// Flags for mmap
Map_Flags :: bit_set[Map_Flags_Bits; i32]
/// Flags for mlock.2
MLock_Flags :: bit_set[MLock_Flags_Bits; u32]
/// Flags for msync.2
MSync_Flags :: bit_set[MSync_Flags_Bits; i32]
/// Access rights for pkey_alloc.2
PKey_Access_Rights :: bit_set[PKey_Access_Bits; u32]
/// Flags for mremap.2
MRemap_Flags :: bit_set[MRemap_Flags_Bits; i32]
/// Flags for getrandom syscall
Get_Random_Flags :: bit_set[Get_Random_Flags_Bits; i32]
/// Flags for perf_event_open syscall
Perf_Flags :: bit_set[Perf_Flags_Bits; uint]
Perf_Event_Flags :: distinct bit_set[Perf_Event_Flags_Bits; u64]
Perf_Cap_Flags :: distinct bit_set[Perf_Cap_Flags_Bits; u64]
Perf_Event_Sample_Type :: bit_set[Perf_Event_Sample_Type_Bits; u64]
/// Specifies which branches to include in branch record
Branch_Sample_Type :: bit_set[Branch_Sample_Type_Bits; u64]
/// The struct for perf_event_open
Perf_Event_Attr :: struct #packed {
type: Perf_Event_Type,
size: u32,
config: struct #raw_union {
hw: Perf_Hardware_Id,
sw: Perf_Software_Id,
cache: u64,
other: u64,
},
sample: struct #raw_union {
period: u64,
frequency: u64,
},
sample_type: Perf_Event_Sample_Type,
read_format: Perf_Read_Format,
flags: Perf_Event_Flags,
wakeup: struct #raw_union {
events: u32,
watermark: u32,
},
breakpoint_type: Hardware_Breakpoint_Type,
using _: struct #raw_union {
breakpoint_addr: u64,
kprobe_func: u64,
uprobe_path: u64,
config1: u64,
},
using _: struct #raw_union {
breakpoint_len: u64,
kprobe_addr: u64,
uprobe_offset: u64,
config2: u64,
},
branch_sample_type: Branch_Sample_Type,
sample_regs_user: u64,
sample_stack_user: u32,
clock_id: i32, // TODO(flysand): clock_id
sample_regs_intr: u64,
aux_watermark: u32,
sample_max_stack: u16,
_: u16,
}
/// The ring buffer structure when mmaping Perf_Event_Attr
Perf_Event_Mmap_Page :: struct #packed {
version: u32,
compat_version: u32,
lock: u32,
index: u32,
offset: i64,
time_enabled: u64,
time_running: u64,
cap: struct #raw_union {
capabilities: u64,
flags: Perf_Cap_Flags,
},
pmc_width: u16,
time_shift: u16,
time_mult: u32,
time_offset: u64,
time_zero: u64,
size: u32,
reserved1: u32,
time_cycles: u64,
time_mask: u64,
reserved2: [116*8]u8,
data_head: u64,
data_tail: u64,
data_offset: u64,
data_size: u64,
aux_head: u64,
aux_tail: u64,
aux_offset: u64,
aux_size: u64,
}
// TODO(flysand): Its taking too much effort to bind the other data structures related to perf_event_open
/// Options for wait4() and waitpid()
Wait_Options :: bit_set[Wait_Option; i32]
/// Flags for pidfd_open.2
Pid_FD_Flags :: bit_set[Pid_FD_Flags_Bits; i32]
// Note(flysand): these could, in principle be implemented with bitfields,
// however there are ABI differences between odin's bitfields and linux sigsets.
// Mainly:
// 1. Odin's bitfields start from 0, whereas signals start from 1
// 2. It's unclear how bitfields act in terms of ABI (are they an array of ints or an array of longs?).
// it makes a difference because ARM is big endian.
@private _SIGSET_NWORDS :: (1024 / (8 * size_of(uint)))
Sig_Set :: [_SIGSET_NWORDS]uint
@private SI_MAX_SIZE :: 128
@private SI_ARCH_PREAMBLE :: 3 * size_of(i32)
@private SI_PAD_SIZE :: (SI_MAX_SIZE - SI_ARCH_PREAMBLE) / size_of(i32)
@private SI_TIMER_PAD_SIZE :: size_of(Uid) - size_of(i32)
Sig_Handler_Fn :: #type proc "c" (sig: Signal)
Sig_Restore_Fn :: #type proc "c" ()
Sig_Info :: struct #packed {
signo: Signal,
errno: Errno,
code: i32,
_pad0: i32,
using _union: struct #raw_union {
_pad1: [SI_PAD_SIZE]u8,
using _kill: struct {
pid: Pid, /* sender's pid */
uid: Uid, /* sender's uid */
},
using _timer: struct {
timerid: i32, /* timer id */
overrun: i32, /* overrun count */
},
/* POSIX.1b signals */
using _rt: struct {
_pid0: Pid, /* sender's pid */
_uid0: Uid, /* sender's uid */
},
/* SIGCHLD */
using _sigchld: struct {
_pid1: Pid, /* which child */
_uid1: Uid, /* sender's uid */
status: i32, /* exit code */
utime: uint,
stime: uint, //clock_t
},
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
using _sigfault: struct {
addr: rawptr, /* faulting insn/memory ref. */
addr_lsb: i16, /* LSB of the reported address */
},
/* SIGPOLL */
using _sigpoll: struct {
band: int, /* POLL_IN, POLL_OUT, POLL_MSG */
fd: Fd,
},
/* SIGSYS */
using _sigsys: struct {
call_addr: rawptr, /* calling user insn */
syscall: i32, /* triggering system call number */
arch: u32, /* AUDIT_ARCH_* of syscall */
},
},
}
Sig_Stack_Flags :: bit_set[Sig_Stack_Flag; i32]
Sig_Stack :: struct {
sp: rawptr,
flags: Sig_Stack_Flags,
size: uintptr,
}
Sig_Action :: struct($T: typeid) {
using _u: struct #raw_union {
handler: Sig_Handler_Fn,
sigaction: #type proc "c" (sig: Signal, si: ^Sig_Info, ctx: ^T),
},
flags: uint,
restorer: Sig_Restore_Fn,
mask: Sig_Set,
}
/// Flags for the socket file descriptor
/// Note, on linux these are technically passed by OR'ing together
/// with Socket_Type, our wrapper does this under the hood.
Socket_FD_Flags :: bit_set[Socket_FD_Flags_Bits; int]
/// Address family for the socket
/// Typically there's one address family for every protocol family
Address_Family :: distinct Protocol_Family
/// Flags for the socket for send/recv calls
Socket_Msg :: bit_set[Socket_Msg_Bits; i32]
/// Struct representing IPv4 socket address
Sock_Addr_In :: struct #packed {
sin_family: Address_Family,
sin_port: u16be,
sin_addr: [4]u8,
}
/// Struct representing IPv6 socket address
Sock_Addr_In6 :: struct #packed {
sin6_family: Address_Family,
sin6_port: u16be,
sin6_flowinfo: u32,
sin6_addr: [16]u8,
sin6_scope_id: u32,
}
/// Struct representing an arbitrary socket address
Sock_Addr_Any :: struct #raw_union {
using _: struct {
family: Address_Family,
port: u16be,
},
using ipv4: Sock_Addr_In,
using ipv6: Sock_Addr_In6,
}
/// Just an alias to make futex-values more visible
Futex :: u32
/// Flags for the futex (they are kept separately)
Futex_Flags :: bit_set[Futex_Flags_Bits; u32]
/// Times
Tms :: struct {
tms_utime: int,
tms_stime: int,
tms_cutime: int,
tms_cstime: int,
}
/// "Unix time-sharing system name", allegedly
/// Basically system info
UTS_Name :: struct {
sysname: [65]u8 `fmt:"s,0"`,
nodename: [65]u8 `fmt:"s,0"`,
release: [65]u8 `fmt:"s,0"`,
version: [65]u8 `fmt:"s,0"`,
machine: [65]u8 `fmt:"s,0"`,
domainname: [65]u8 `fmt:"s,0"`,
}
/// Return buffer for the sysinfo syscall
Sys_Info :: struct {
uptime: int,
loads: [3]int,
totalram: uint,
freeram: uint,
sharedram: uint,
bufferram: uint,
totalswap: uint,
freeswap: uint,
procs: u16,
totalhigh: uint,
freehigh: uint,
mem_unit: i32,
_padding: [20 - (2 * size_of(int)) - size_of(i32)]u8,
}
/// Resource limit
RLimit :: struct {
cur: uint,
max: uint,
}
/// Structure representing how much of each resource
/// got used.
RUsage :: struct {
utime: Time_Val,
stime: Time_Val,
maxrss_word: int,
ixrss_word: int,
idrss_word: int,
isrss_word: int,
minflt_word: int,
majflt_word: int,
nswap_word: int,
inblock_word: int,
oublock_word: int,
msgsnd_word: int,
msgrcv_word: int,
nsignals_word: int,
nvcsw_word: int,
nivcsw_word: int,
}
+121
View File
@@ -0,0 +1,121 @@
//+build linux
package linux
/// Low 8 bits of the exit code
/// Only retrieve the exit code if WIFEXITED(s) = true
WEXITSTATUS :: #force_inline proc "contextless" (s: u32) -> u32 {
return (s & 0xff00) >> 8
}
/// Termination signal
/// Only retrieve the code if WIFSIGNALED(s) = true
WTERMSIG :: #force_inline proc "contextless" (s: u32) -> u32 {
return s & 0x7f
}
/// The signal that stopped the child
/// Only retrieve if WIFSTOPPED(s) = true
WSTOPSIG :: #force_inline proc "contextless" (s: u32) -> u32 {
return WEXITSTATUS(s)
}
/// Check if the process terminated normally (via exit.2)
WIFEXITED :: #force_inline proc "contextless" (s: u32) -> bool {
return WTERMSIG(s) == 0
}
/// Check if the process signaled
WIFSIGNALED :: #force_inline proc "contextless" (s: u32) -> bool {
return cast(i8)(((s) & 0x7f) + 1) >> 1 > 0
}
/// Check if the process has stopped
WIFSTOPPED :: #force_inline proc "contextless" (s: u32) -> bool {
return (s & 0xff) == 0x7f
}
/// Check if the process is continued by the tracee
WIFCONTINUED :: #force_inline proc "contextless" (s: u32) -> bool {
return s == 0xffff
}
/// Check if the process dumped core
WCOREDUMP :: #force_inline proc "contextless" (s: u32) -> bool {
return s & 0x80 == 0x80
}
@private _sigmask :: proc "contextless" (sig: Signal) -> (uint) {
return 1 << ((cast(uint)(sig) - 1) % (8*size_of(uint)))
}
@private _sigword :: proc "contextless" (sig: Signal) -> (uint) {
return (cast(uint)sig - 1) / (8*size_of(uint))
}
// TODO: sigaddset etc
/// Iterate the results of getdents
/// Only iterates as much data as loaded in the buffer
/// In case you need to iterate *all* files in a directory
/// consider using dirent_get_iterate
///
/// Example of using dirent_iterate_buf
/// // Get dirents into a buffer
/// buf: [128]u8
/// sys.getdents(dirfd, buf[:])
/// // Print the names of the files
/// for dir in sys.dirent_iterate_buf(buf[:], &offs) {
/// name := sys.dirent_name(dir)
/// fmt.println(name)
/// }
/// This function doesn't automatically make a request
/// for the buffer to be refilled
dirent_iterate_buf :: proc "contextless" (buf: []u8, offs: ^int) -> (d: ^Dirent, cont: bool) {
// Stopped iterating when there's no space left
if offs^ >= len(buf) {
return nil, false
}
// Retrieve dirent form the current offset
dirent := cast(^Dirent) &buf[offs^]
// Add the stride of dirent struct to the current offset
offs^ += cast(int) dirent.reclen
return dirent, true
}
/// Obtain the name of dirent as a string
/// The lifetime of the string is bound to the lifetime of the provided dirent structure
dirent_name :: proc "contextless" (dirent: ^Dirent) -> string #no_bounds_check {
str := transmute([^]u8) &dirent.name
// Note(flysand): The string size calculated above applies only to the ideal case
// we subtract 1 byte from the string size, because a null terminator is guaranteed
// to be present. But! That said, the dirents are aligned to 8 bytes and the padding
// between the null terminator and the start of the next struct may be not initialized
// which means we also have to scan these garbage bytes.
str_size := (cast(int) dirent.reclen) - 1 - cast(int) offset_of(Dirent, name)
// This skips *only* over the garbage, since if we're not garbage we're at nul terminator,
// which skips this loop
for str[str_size] != 0 {
str_size -= 1
}
for str[str_size-1] == 0 {
str_size -= 1
}
// Oh yeah btw i could also just `repne scasb` this thing, but honestly I started doing
// it the painful way, might as well finish doing it that way
return string(str[:str_size])
}
/// Constructor for the `futex_op` argument of a FUTEX_WAKE_OP call
futex_op :: proc "contextless" (arg_op: Futex_Arg_Op, cmp_op: Futex_Cmp_Op, op_arg: u32, cmp_arg: u32) -> u32 {
arg_op := cast(u32) arg_op
cmp_op := cast(u32) cmp_op
return (arg_op << 28) | (cmp_op << 24) | ((op_arg & 0xfff) << 12) | (cmp_arg & 0xfff)
}
/// Helper function for constructing the config for caches
perf_cache_config :: #force_inline proc "contextless" (id: Perf_Hardware_Cache_Id,
op: Perf_Hardware_Cache_Op_Id,
res: Perf_Hardware_Cache_Result_Id) -> u64
{
return u64(id) | (u64(op) << 8) | (u64(res) << 16)
}
+2 -2
View File
@@ -10,7 +10,7 @@ _now :: proc "contextless" () -> Time {
foreign odin_env {
time_now :: proc "contextless" () -> i64 ---
}
return Time{time_now()}
return Time{time_now()*1e6}
}
_sleep :: proc "contextless" (d: Duration) {
@@ -26,7 +26,7 @@ _tick_now :: proc "contextless" () -> Tick {
foreign odin_env {
tick_now :: proc "contextless" () -> i64 ---
}
return Tick{tick_now()}
return Tick{tick_now()*1e6}
}
_yield :: proc "contextless" () {
+14 -16
View File
@@ -2,34 +2,32 @@
//+build linux
package time
import "core:intrinsics"
import "core:sys/unix"
import linux "core:sys/linux"
_get_tsc_frequency :: proc "contextless" () -> (u64, bool) {
perf_attr := unix.Perf_Event_Attr{}
perf_attr.type = u32(unix.Perf_Type_Id.Hardware)
perf_attr.config = u64(unix.Perf_Hardware_Id.Instructions)
// Get the file descriptor for the perf mapping
perf_attr := linux.Perf_Event_Attr{}
perf_attr.size = size_of(perf_attr)
perf_attr.type = .HARDWARE
perf_attr.config.hw = .INSTRUCTIONS
perf_attr.flags = {.Disabled, .Exclude_Kernel, .Exclude_HV}
fd := unix.sys_perf_event_open(&perf_attr, 0, -1, -1, 0)
if fd == -1 {
fd, perf_errno := linux.perf_event_open(&perf_attr, linux.Pid(0), -1, linux.Fd(-1), {})
if perf_errno != nil {
return 0, false
}
defer unix.sys_close(fd)
defer linux.close(fd)
// Map it into the memory
page_size : uint = 4096
ret := unix.sys_mmap(nil, page_size, unix.PROT_READ, unix.MAP_SHARED, fd, 0)
if ret < 0 && ret > -4096 {
addr, mmap_errno := linux.mmap(0, page_size, {.READ}, {.SHARED}, fd)
if mmap_errno != nil {
return 0, false
}
addr := rawptr(uintptr(ret))
defer unix.sys_munmap(addr, page_size)
event_page := (^unix.Perf_Event_mmap_Page)(addr)
defer linux.munmap(addr, page_size)
// Get the frequency from the mapped page
event_page := cast(^linux.Perf_Event_Mmap_Page) addr
if .User_Time not_in event_page.cap.flags {
return 0, false
}
frequency := u64((u128(1_000_000_000) << u128(event_page.time_shift)) / u128(event_page.time_mult))
return frequency, true
}
+6
View File
@@ -0,0 +1,6 @@
//+build linux
package all
import linux "core:sys/linux"
_ :: linux
-10
View File
@@ -39,11 +39,6 @@ import TTF "vendor:sdl2/ttf"
import vk "vendor:vulkan"
import NS "vendor:darwin/Foundation"
import MTL "vendor:darwin/Metal"
import MTK "vendor:darwin/MetalKit"
import CA "vendor:darwin/QuartzCore"
// NOTE(bill): only one can be checked at a time
import lua_5_4 "vendor:lua/5.4"
@@ -91,11 +86,6 @@ _ :: TTF
_ :: vk
_ :: NS
_ :: MTL
_ :: MTK
_ :: CA
_ :: lua_5_4
_ :: nvg
+12
View File
@@ -0,0 +1,12 @@
//+build darwin
package all
import NS "vendor:darwin/Foundation"
import MTL "vendor:darwin/Metal"
import MTK "vendor:darwin/MetalKit"
import CA "vendor:darwin/QuartzCore"
_ :: NS
_ :: MTL
_ :: MTK
_ :: CA
+4 -2
View File
@@ -1388,8 +1388,10 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta
bc->optimization_level = gb_clamp(bc->optimization_level, -1, 3);
// ENFORCE DYNAMIC MAP CALLS
bc->dynamic_map_calls = true;
if (bc->metrics.os != TargetOs_windows) {
// ENFORCE DYNAMIC MAP CALLS
bc->dynamic_map_calls = true;
}
bc->ODIN_VALGRIND_SUPPORT = false;
if (build_context.metrics.os != TargetOs_windows) {
+3 -3
View File
@@ -5170,7 +5170,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
Operand op = {};
check_expr(c, &op, ce->args[1]);
if (op.mode != Addressing_Constant && !is_type_integer(op.type)) {
if (op.mode != Addressing_Constant || !is_type_integer(op.type)) {
error(op.expr, "Expected a constant integer for the index of procedure parameter value");
return false;
}
@@ -5229,7 +5229,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
Operand op = {};
check_expr(c, &op, ce->args[1]);
if (op.mode != Addressing_Constant && !is_type_integer(op.type)) {
if (op.mode != Addressing_Constant || !is_type_integer(op.type)) {
error(op.expr, "Expected a constant integer for the index of procedure parameter value");
return false;
}
@@ -5307,7 +5307,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
} else {
Operand op = {};
check_expr(c, &op, ce->args[1]);
if (op.mode != Addressing_Constant && !is_type_integer(op.type)) {
if (op.mode != Addressing_Constant || !is_type_integer(op.type)) {
error(op.expr, "Expected a constant integer for the index of record parameter value");
return false;
}
+17
View File
@@ -2291,6 +2291,23 @@ gb_internal void check_return_stmt(CheckerContext *ctx, Ast *node) {
}
}
}
for (Operand &o : operands) {
if (o.expr == nullptr) {
continue;
}
if (o.expr->kind != Ast_CompoundLit || !is_type_slice(o.type)) {
continue;
}
ast_node(cl, CompoundLit, o.expr);
if (cl->elems.count == 0) {
continue;
}
gbString s = type_to_string(o.type);
error(o.expr, "It is unsafe to return a compound literal of a slice ('%s') with elements from a procedure, as the contents of the slice uses the current stack frame's memory", s);
gb_string_free(s);
}
}
gb_internal void check_for_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) {
+1 -1
View File
@@ -2797,7 +2797,7 @@ gb_internal bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, T
Type *bt = base_type(index);
GB_ASSERT(bt->kind == Type_Enum);
Type *t = alloc_type_enumerated_array(elem, index, bt->Enum.min_value, bt->Enum.max_value, Token_Invalid);
Type *t = alloc_type_enumerated_array(elem, index, bt->Enum.min_value, bt->Enum.max_value, bt->Enum.fields.count, Token_Invalid);
bool is_sparse = false;
if (at->tag != nullptr) {
+3 -2
View File
@@ -4733,8 +4733,7 @@ gb_internal void check_add_foreign_import_decl(CheckerContext *ctx, Ast *decl) {
}
if (has_asm_extension(fullpath)) {
if (build_context.metrics.arch != TargetArch_amd64 ||
build_context.metrics.os != TargetOs_windows) {
if (build_context.metrics.arch != TargetArch_amd64) {
error(decl, "Assembly files are not yet supported on this platform: %.*s_%.*s",
LIT(target_os_names[build_context.metrics.os]), LIT(target_arch_names[build_context.metrics.arch]));
}
@@ -5848,6 +5847,8 @@ gb_internal void check_deferred_procedures(Checker *c) {
}
gb_internal void check_unique_package_names(Checker *c) {
ERROR_BLOCK();
StringMap<AstPackage *> pkgs = {}; // Key: package name
string_map_init(&pkgs, 2*c->info.packages.count);
defer (string_map_destroy(&pkgs));
+89 -42
View File
@@ -149,14 +149,20 @@ gb_internal i32 linker_stage(LinkerData *gen) {
if (!string_set_update(&asm_files, lib)) {
String asm_file = asm_files.entries[i].value;
String obj_file = concatenate_strings(permanent_allocator(), asm_file, str_lit(".obj"));
String obj_format;
#if defined(GB_ARCH_64_BIT)
obj_format = str_lit("win64");
#elif defined(GB_ARCH_32_BIT)
obj_format = str_lit("win32");
#endif // GB_ARCH_*_BIT
result = system_exec_command_line_app("nasm",
"\"%.*s\\bin\\nasm\\windows\\nasm.exe\" \"%.*s\" "
"-f win64 "
"-f \"%.*s\" "
"-o \"%.*s\" "
"%.*s "
"",
LIT(build_context.ODIN_ROOT), LIT(asm_file),
LIT(obj_format),
LIT(obj_file),
LIT(build_context.extra_assembler_flags)
);
@@ -295,11 +301,15 @@ gb_internal i32 linker_stage(LinkerData *gen) {
// files can be passed with -l:
gbString lib_str = gb_string_make(heap_allocator(), "-L/");
defer (gb_string_free(lib_str));
StringSet asm_files = {};
string_set_init(&asm_files, 64);
defer (string_set_destroy(&asm_files));
StringSet libs = {};
string_set_init(&libs, 64);
defer (string_set_destroy(&libs));
for (Entity *e : gen->foreign_libraries) {
GB_ASSERT(e->kind == Entity_LibraryName);
for (String lib : e->LibraryName.paths) {
@@ -307,46 +317,83 @@ gb_internal i32 linker_stage(LinkerData *gen) {
if (lib.len == 0) {
continue;
}
if (string_set_update(&libs, lib)) {
continue;
}
// NOTE(zangent): Sometimes, you have to use -framework on MacOS.
// This allows you to specify '-f' in a #foreign_system_library,
// without having to implement any new syntax specifically for MacOS.
if (build_context.metrics.os == TargetOs_darwin) {
if (string_ends_with(lib, str_lit(".framework"))) {
// framework thingie
String lib_name = lib;
lib_name = remove_extension_from_path(lib_name);
lib_str = gb_string_append_fmt(lib_str, " -framework %.*s ", LIT(lib_name));
} else if (string_ends_with(lib, str_lit(".a")) || string_ends_with(lib, str_lit(".o")) || string_ends_with(lib, str_lit(".dylib"))) {
// For:
// object
// dynamic lib
// static libs, absolute full path relative to the file in which the lib was imported from
lib_str = gb_string_append_fmt(lib_str, " %.*s ", LIT(lib));
} else {
// dynamic or static system lib, just link regularly searching system library paths
lib_str = gb_string_append_fmt(lib_str, " -l%.*s ", LIT(lib));
if (has_asm_extension(lib)) {
if (string_set_update(&asm_files, lib)) {
continue; // already handled
}
} else {
// NOTE(vassvik): static libraries (.a files) in linux can be linked to directly using the full path,
// since those are statically linked to at link time. shared libraries (.so) has to be
// available at runtime wherever the executable is run, so we make require those to be
// local to the executable (unless the system collection is used, in which case we search
// the system library paths for the library file).
if (string_ends_with(lib, str_lit(".a")) || string_ends_with(lib, str_lit(".o"))) {
// static libs and object files, absolute full path relative to the file in which the lib was imported from
lib_str = gb_string_append_fmt(lib_str, " -l:\"%.*s\" ", LIT(lib));
} else if (string_ends_with(lib, str_lit(".so"))) {
// dynamic lib, relative path to executable
// NOTE(vassvik): it is the user's responsibility to make sure the shared library files are visible
// at runtime to the executable
lib_str = gb_string_append_fmt(lib_str, " -l:\"%s/%.*s\" ", cwd, LIT(lib));
String asm_file = lib;
String obj_file = concatenate_strings(permanent_allocator(), asm_file, str_lit(".o"));
String obj_format;
#if defined(GB_ARCH_64_BIT)
if (is_osx) {
obj_format = str_lit("macho64");
} else {
// dynamic or static system lib, just link regularly searching system library paths
lib_str = gb_string_append_fmt(lib_str, " -l%.*s ", LIT(lib));
obj_format = str_lit("elf64");
}
#elif defined(GB_ARCH_32_BIT)
if (is_osx) {
obj_format = str_lit("macho32");
} else {
obj_format = str_lit("elf32");
}
#endif // GB_ARCH_*_BIT
// Note(bumbread): I'm assuming nasm is installed on the host machine.
// Shipping binaries on unix-likes gets into the weird territorry of
// "which version of glibc" is it linked with.
result = system_exec_command_line_app("nasm",
"nasm \"%.*s\" "
"-f \"%.*s\" "
"-o \"%.*s\" "
"%.*s "
"",
LIT(asm_file),
LIT(obj_format),
LIT(obj_file),
LIT(build_context.extra_assembler_flags)
);
array_add(&gen->output_object_paths, obj_file);
} else {
if (string_set_update(&libs, lib)) {
continue;
}
// NOTE(zangent): Sometimes, you have to use -framework on MacOS.
// This allows you to specify '-f' in a #foreign_system_library,
// without having to implement any new syntax specifically for MacOS.
if (build_context.metrics.os == TargetOs_darwin) {
if (string_ends_with(lib, str_lit(".framework"))) {
// framework thingie
String lib_name = lib;
lib_name = remove_extension_from_path(lib_name);
lib_str = gb_string_append_fmt(lib_str, " -framework %.*s ", LIT(lib_name));
} else if (string_ends_with(lib, str_lit(".a")) || string_ends_with(lib, str_lit(".o")) || string_ends_with(lib, str_lit(".dylib"))) {
// For:
// object
// dynamic lib
// static libs, absolute full path relative to the file in which the lib was imported from
lib_str = gb_string_append_fmt(lib_str, " %.*s ", LIT(lib));
} else {
// dynamic or static system lib, just link regularly searching system library paths
lib_str = gb_string_append_fmt(lib_str, " -l%.*s ", LIT(lib));
}
} else {
// NOTE(vassvik): static libraries (.a files) in linux can be linked to directly using the full path,
// since those are statically linked to at link time. shared libraries (.so) has to be
// available at runtime wherever the executable is run, so we make require those to be
// local to the executable (unless the system collection is used, in which case we search
// the system library paths for the library file).
if (string_ends_with(lib, str_lit(".a")) || string_ends_with(lib, str_lit(".o"))) {
// static libs and object files, absolute full path relative to the file in which the lib was imported from
lib_str = gb_string_append_fmt(lib_str, " -l:\"%.*s\" ", LIT(lib));
} else if (string_ends_with(lib, str_lit(".so"))) {
// dynamic lib, relative path to executable
// NOTE(vassvik): it is the user's responsibility to make sure the shared library files are visible
// at runtime to the executable
lib_str = gb_string_append_fmt(lib_str, " -l:\"%s/%.*s\" ", cwd, LIT(lib));
} else {
// dynamic or static system lib, just link regularly searching system library paths
lib_str = gb_string_append_fmt(lib_str, " -l%.*s ", LIT(lib));
}
}
}
}
+447 -15
View File
@@ -506,9 +506,9 @@ gb_internal lbValue lb_map_get_proc_for_type(lbModule *m, Type *type) {
LLVMSetLinkage(p->value, LLVMInternalLinkage);
lb_add_attribute_to_proc(m, p->value, "nounwind");
// if (build_context.ODIN_DEBUG) {
if (build_context.ODIN_DEBUG) {
lb_add_attribute_to_proc(m, p->value, "noinline");
// }
}
LLVMValueRef x = LLVMGetParam(p->value, 0);
LLVMValueRef y = LLVMGetParam(p->value, 1);
@@ -692,7 +692,7 @@ gb_internal lbValue lb_map_set_proc_for_type(lbModule *m, Type *type) {
}
lbValue map_ptr = {LLVMGetParam(p->value, 0), t_rawptr};
lbValue hash = {LLVMGetParam(p->value, 1), t_uintptr};
lbValue hash_param = {LLVMGetParam(p->value, 1), t_uintptr};
lbValue key_ptr = {LLVMGetParam(p->value, 2), t_rawptr};
lbValue value_ptr = {LLVMGetParam(p->value, 3), t_rawptr};
lbValue location_ptr = {LLVMGetParam(p->value, 4), t_source_code_location_ptr};
@@ -700,6 +700,12 @@ gb_internal lbValue lb_map_set_proc_for_type(lbModule *m, Type *type) {
map_ptr = lb_emit_conv(p, map_ptr, alloc_type_pointer(type));
key_ptr = lb_emit_conv(p, key_ptr, alloc_type_pointer(type->Map.key));
LLVM_SET_VALUE_NAME(map_ptr.value, "map_ptr");
LLVM_SET_VALUE_NAME(hash_param.value, "hash_param");
LLVM_SET_VALUE_NAME(key_ptr.value, "key_ptr");
LLVM_SET_VALUE_NAME(value_ptr.value, "value_ptr");
LLVM_SET_VALUE_NAME(location_ptr.value, "location");
lb_add_proc_attribute_at_index(p, 1+0, "nonnull");
lb_add_proc_attribute_at_index(p, 1+0, "noalias");
@@ -719,6 +725,10 @@ gb_internal lbValue lb_map_set_proc_for_type(lbModule *m, Type *type) {
lb_add_proc_attribute_at_index(p, 1+4, "noalias");
lb_add_proc_attribute_at_index(p, 1+4, "readonly");
lbAddr hash_addr = lb_add_local_generated(p, t_uintptr, false);
lb_addr_store(p, hash_addr, hash_param);
LLVM_SET_VALUE_NAME(hash_addr.addr.value, "hash");
////
lbValue found_ptr = {};
{
@@ -726,17 +736,19 @@ gb_internal lbValue lb_map_set_proc_for_type(lbModule *m, Type *type) {
auto args = array_make<lbValue>(temporary_allocator(), 3);
args[0] = lb_emit_conv(p, map_ptr, t_rawptr);
args[1] = hash;
args[1] = lb_addr_load(p, hash_addr);
args[2] = key_ptr;
found_ptr = lb_emit_call(p, map_get_proc, args);
}
LLVM_SET_VALUE_NAME(found_ptr.value, "found_ptr");
lbBlock *found_block = lb_create_block(p, "found");
lbBlock *check_grow_block = lb_create_block(p, "check-grow");
lbBlock *grow_fail_block = lb_create_block(p, "grow-fail");
lbBlock *insert_block = lb_create_block(p, "insert");
lbBlock *check_has_grown_block = lb_create_block(p, "check-has-grown");
lbBlock *rehash_block = lb_create_block(p, "rehash");
lb_emit_if(p, lb_emit_comp_against_nil(p, Token_NotEq, found_ptr), found_block, check_grow_block);
@@ -749,6 +761,7 @@ gb_internal lbValue lb_map_set_proc_for_type(lbModule *m, Type *type) {
lbValue map_info = lb_gen_map_info_ptr(p->module, type);
LLVM_SET_VALUE_NAME(map_info.value, "map_info");
{
auto args = array_make<lbValue>(temporary_allocator(), 3);
@@ -758,16 +771,23 @@ gb_internal lbValue lb_map_set_proc_for_type(lbModule *m, Type *type) {
lbValue grow_err_and_has_grown = lb_emit_runtime_call(p, "__dynamic_map_check_grow", args);
lbValue grow_err = lb_emit_struct_ev(p, grow_err_and_has_grown, 0);
lbValue has_grown = lb_emit_struct_ev(p, grow_err_and_has_grown, 1);
LLVM_SET_VALUE_NAME(grow_err.value, "grow_err");
LLVM_SET_VALUE_NAME(has_grown.value, "has_grown");
lb_emit_if(p, lb_emit_comp_against_nil(p, Token_NotEq, grow_err), grow_fail_block, insert_block);
lb_emit_if(p, lb_emit_comp_against_nil(p, Token_NotEq, grow_err), grow_fail_block, check_has_grown_block);
lb_start_block(p, grow_fail_block);
LLVMBuildRet(p->builder, LLVMConstNull(lb_type(m, t_rawptr)));
lb_emit_if(p, has_grown, grow_fail_block, rehash_block);
lb_start_block(p, check_has_grown_block);
lb_emit_if(p, has_grown, rehash_block, insert_block);
lb_start_block(p, rehash_block);
lbValue key = lb_emit_load(p, key_ptr);
hash = lb_gen_map_key_hash(p, map_ptr, key, nullptr);
lbValue new_hash = lb_gen_map_key_hash(p, map_ptr, key, nullptr);
LLVM_SET_VALUE_NAME(new_hash.value, "new_hash");
lb_addr_store(p, hash_addr, new_hash);
lb_emit_jump(p, insert_block);
}
lb_start_block(p, insert_block);
@@ -775,7 +795,7 @@ gb_internal lbValue lb_map_set_proc_for_type(lbModule *m, Type *type) {
auto args = array_make<lbValue>(temporary_allocator(), 5);
args[0] = lb_emit_conv(p, map_ptr, t_rawptr);
args[1] = map_info;
args[2] = hash;
args[2] = lb_addr_load(p, hash_addr);
args[3] = lb_emit_conv(p, key_ptr, t_uintptr);
args[4] = lb_emit_conv(p, value_ptr, t_uintptr);
@@ -1471,13 +1491,390 @@ gb_internal WORKER_TASK_PROC(lb_llvm_module_pass_worker_proc) {
array_add(&passes, "function(annotation-remarks)");
break;
case 1:
array_add(&passes, "default<Os>");
// default<Os>
// Passes removed: coro, openmp, sroa
array_add(&passes, u8R"(
annotation2metadata,
forceattrs,
inferattrs,
function<eager-inv>(
lower-expect,
simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;no-switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>,
early-cse<>
),
ipsccp,
called-value-propagation,
globalopt,
function<eager-inv>(
mem2reg,
instcombine<max-iterations=1000;no-use-loop-info>,
simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>),
require<globals-aa>,
function(
invalidate<aa>
),
require<profile-summary>,
cgscc(
devirt<4>(
inline<only-mandatory>,
inline,
function-attrs<skip-non-recursive>,
function<eager-inv;no-rerun>(
early-cse<memssa>,
speculative-execution,
jump-threading,
correlated-propagation,
simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>,
instcombine<max-iterations=1000;no-use-loop-info>,
aggressive-instcombine,
constraint-elimination,
tailcallelim,
simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>,
reassociate,
loop-mssa(
loop-instsimplify,
loop-simplifycfg,
licm<no-allowspeculation>,
loop-rotate<header-duplication;no-prepare-for-lto>,
licm<allowspeculation>,
simple-loop-unswitch<no-nontrivial;trivial>
),
simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>,
instcombine<max-iterations=1000;no-use-loop-info>,
loop(
loop-idiom,
indvars,
loop-deletion,
loop-unroll-full
),
vector-combine,
mldst-motion<no-split-footer-bb>,
gvn<>,
sccp,
bdce,
instcombine<max-iterations=1000;no-use-loop-info>,
jump-threading,
correlated-propagation,
adce,
memcpyopt,
dse,
move-auto-init,
loop-mssa(
licm<allowspeculation>
),
simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;hoist-common-insts;sink-common-insts;speculate-blocks;simplify-cond-branch>,
instcombine<max-iterations=1000;no-use-loop-info>
),
function-attrs,
function(
require<should-not-run-function-passes>
)
)
),
deadargelim,
globalopt,
globaldce,
elim-avail-extern,
rpo-function-attrs,
recompute-globalsaa,
function<eager-inv>(
float2int,
lower-constant-intrinsics,
loop(
loop-rotate<header-duplication;no-prepare-for-lto>,
loop-deletion
),
loop-distribute,
inject-tli-mappings,
loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>,
loop-load-elim,
instcombine<max-iterations=1000;no-use-loop-info>,
simplifycfg<bonus-inst-threshold=1;forward-switch-cond;switch-range-to-icmp;switch-to-lookup;no-keep-loops;hoist-common-insts;sink-common-insts;speculate-blocks;simplify-cond-branch>,
slp-vectorizer,
vector-combine,
instcombine<max-iterations=1000;no-use-loop-info>,
loop-unroll<O2>,
transform-warning,
instcombine<max-iterations=1000;no-use-loop-info>,
loop-mssa(
licm<allowspeculation>
),
alignment-from-assumptions,
loop-sink,
instsimplify,
div-rem-pairs,
tailcallelim,
simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>
),
globaldce,
constmerge,
cg-profile,
rel-lookup-table-converter,
function(
annotation-remarks
),
verify
)");
break;
// default<O2>
// Passes removed: coro, openmp, sroa
case 2:
array_add(&passes, "default<O2>");
array_add(&passes, u8R"(
annotation2metadata,
forceattrs,
inferattrs,
function<eager-inv>(
lower-expect,
simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;no-switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>,
early-cse<>
),
ipsccp,
called-value-propagation,
globalopt,
function<eager-inv>(
mem2reg,
instcombine<max-iterations=1000;no-use-loop-info>,
simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>
),
require<globals-aa>,
function(
invalidate<aa>
),
require<profile-summary>,
cgscc(
devirt<4>(
inline<only-mandatory>,
inline,
function-attrs<skip-non-recursive>,
function<eager-inv;no-rerun>(
early-cse<memssa>,
speculative-execution,
jump-threading,
correlated-propagation,
simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>,
instcombine<max-iterations=1000;no-use-loop-info>,
aggressive-instcombine,
constraint-elimination,
libcalls-shrinkwrap,
tailcallelim,
simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>,
reassociate,
loop-mssa(
loop-instsimplify,
loop-simplifycfg,
licm<no-allowspeculation>,
loop-rotate<header-duplication;no-prepare-for-lto>,
licm<allowspeculation>,
simple-loop-unswitch<no-nontrivial;trivial>
),
simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>,
instcombine<max-iterations=1000;no-use-loop-info>,
loop(
loop-idiom,
indvars,
loop-deletion,
loop-unroll-full
),
vector-combine,
mldst-motion<no-split-footer-bb>,
gvn<>,
sccp,
bdce,
instcombine<max-iterations=1000;no-use-loop-info>,
jump-threading,
correlated-propagation,
adce,
memcpyopt,
dse,
move-auto-init,
loop-mssa(
licm<allowspeculation>
),
simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;hoist-common-insts;sink-common-insts;speculate-blocks;simplify-cond-branch>,
instcombine<max-iterations=1000;no-use-loop-info>
),
function-attrs,
function(
require<should-not-run-function-passes>
)
)
),
deadargelim,
globalopt,
globaldce,
elim-avail-extern,
rpo-function-attrs,
recompute-globalsaa,
function<eager-inv>(
float2int,
lower-constant-intrinsics,
loop(
loop-rotate<header-duplication;no-prepare-for-lto>,
loop-deletion
),
loop-distribute,
inject-tli-mappings,
loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>,
loop-load-elim,
instcombine<max-iterations=1000;no-use-loop-info>,
simplifycfg<bonus-inst-threshold=1;forward-switch-cond;switch-range-to-icmp;switch-to-lookup;no-keep-loops;hoist-common-insts;sink-common-insts;speculate-blocks;simplify-cond-branch>,
slp-vectorizer,
vector-combine,
instcombine<max-iterations=1000;no-use-loop-info>,
loop-unroll<O2>,
transform-warning,
instcombine<max-iterations=1000;no-use-loop-info>,
loop-mssa(
licm<allowspeculation>
),
alignment-from-assumptions,
loop-sink,
instsimplify,
div-rem-pairs,
tailcallelim,
simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>
),
globaldce,
constmerge,
cg-profile,
rel-lookup-table-converter,
function(
annotation-remarks
),
verify
)");
break;
case 3:
array_add(&passes, "default<O3>");
// default<O3>
// Passes removed: coro, openmp, sroa
array_add(&passes, u8R"(
annotation2metadata,
forceattrs,
inferattrs,
function<eager-inv>(
lower-expect,
simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;no-switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>,
early-cse<>,
callsite-splitting
),
ipsccp,
called-value-propagation,
globalopt,
function<eager-inv>(
mem2reg,
instcombine<max-iterations=1000;no-use-loop-info>,
simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>
),
require<globals-aa>,
function(
invalidate<aa>
),
require<profile-summary>,
cgscc(
devirt<4>(
inline<only-mandatory>,
inline,
function-attrs<skip-non-recursive>,
argpromotion,
function<eager-inv;no-rerun>(
early-cse<memssa>,
speculative-execution,
jump-threading,
correlated-propagation,
simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>,
instcombine<max-iterations=1000;no-use-loop-info>,
aggressive-instcombine,
constraint-elimination,
libcalls-shrinkwrap,
tailcallelim,
simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>,
reassociate,
loop-mssa(
loop-instsimplify,
loop-simplifycfg,
licm<no-allowspeculation>,
loop-rotate<header-duplication;no-prepare-for-lto>,
licm<allowspeculation>,
simple-loop-unswitch<nontrivial;trivial>
),
simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>,
instcombine<max-iterations=1000;no-use-loop-info>,
loop(
loop-idiom,
indvars,
loop-deletion,
loop-unroll-full
),
vector-combine,
mldst-motion<no-split-footer-bb>,
gvn<>,
sccp,
bdce,
instcombine<max-iterations=1000;no-use-loop-info>,
jump-threading,
correlated-propagation,
adce,
memcpyopt,
dse,
move-auto-init,
loop-mssa(
licm<allowspeculation>
),
simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;hoist-common-insts;sink-common-insts;speculate-blocks;simplify-cond-branch>,
instcombine<max-iterations=1000;no-use-loop-info>
),
function-attrs,
function(
require<should-not-run-function-passes>
)
)
),
deadargelim,
globalopt,
globaldce,
elim-avail-extern,
rpo-function-attrs,
recompute-globalsaa,
function<eager-inv>(
float2int,
lower-constant-intrinsics,
chr,
loop(
loop-rotate<header-duplication;no-prepare-for-lto>,
loop-deletion
),
loop-distribute,
inject-tli-mappings,
loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>,
loop-load-elim,
instcombine<max-iterations=1000;no-use-loop-info>,
simplifycfg<bonus-inst-threshold=1;forward-switch-cond;switch-range-to-icmp;switch-to-lookup;no-keep-loops;hoist-common-insts;sink-common-insts;speculate-blocks;simplify-cond-branch>,
slp-vectorizer,
vector-combine,
instcombine<max-iterations=1000;no-use-loop-info>,
loop-unroll<O3>,
transform-warning,
instcombine<max-iterations=1000;no-use-loop-info>,
loop-mssa(
licm<allowspeculation>
),
alignment-from-assumptions,
loop-sink,
instsimplify,
div-rem-pairs,
tailcallelim,
simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>
),
globaldce,
constmerge,
cg-profile,
rel-lookup-table-converter,
function(
annotation-remarks
),
verify
)");
break;
}
@@ -1508,6 +1905,19 @@ gb_internal WORKER_TASK_PROC(lb_llvm_module_pass_worker_proc) {
}
passes_str = gb_string_appendc(passes_str, passes[i]);
}
for (isize i = 0; i < gb_string_length(passes_str); /**/) {
switch (passes_str[i]) {
case ' ':
case '\n':
case '\t':
gb_memmove(&passes_str[i], &passes_str[i+1], gb_string_length(passes_str)-i);
GB_STRING_HEADER(passes_str)->length -= 1;
continue;
default:
i += 1;
break;
}
}
LLVMErrorRef llvm_err = LLVMRunPasses(wd->m->mod, passes_str, wd->target_machine, pb_options);
@@ -2247,7 +2657,9 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
lb_add_entity(m, lb_global_type_info_data_entity, value);
if (LB_USE_GIANT_PACKED_STRUCT) {
lb_make_global_private_const(g);
LLVMSetLinkage(g, LLVMPrivateLinkage);
LLVMSetUnnamedAddress(g, LLVMGlobalUnnamedAddr);
LLVMSetGlobalConstant(g, /*true*/false);
}
}
{ // Type info member buffer
@@ -2602,17 +3014,37 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
if (build_context.sanitizer_flags & SanitizerFlag_Address) {
auto paths = array_make<String>(heap_allocator(), 0, 1);
if (build_context.metrics.os == TargetOs_windows) {
auto paths = array_make<String>(heap_allocator(), 0, 1);
String path = concatenate_strings(permanent_allocator(), build_context.ODIN_ROOT, str_lit("\\bin\\llvm\\windows\\clang_rt.asan-x86_64.lib"));
array_add(&paths, path);
Entity *lib = alloc_entity_library_name(nullptr, make_token_ident("asan_lib"), nullptr, slice_from_array(paths), str_lit("asan_lib"));
array_add(&gen->foreign_libraries, lib);
} else if (build_context.metrics.os == TargetOs_darwin || build_context.metrics.os == TargetOs_linux) {
if (!build_context.extra_linker_flags.text) {
build_context.extra_linker_flags = str_lit("-fsanitize=address");
} else {
build_context.extra_linker_flags = concatenate_strings(permanent_allocator(), build_context.extra_linker_flags, str_lit(" -fsanitize=address"));
}
}
Entity *lib = alloc_entity_library_name(nullptr, make_token_ident("asan_lib"), nullptr, slice_from_array(paths), str_lit("asan_lib"));
array_add(&gen->foreign_libraries, lib);
}
if (build_context.sanitizer_flags & SanitizerFlag_Memory) {
if (build_context.metrics.os == TargetOs_darwin || build_context.metrics.os == TargetOs_linux) {
if (!build_context.extra_linker_flags.text) {
build_context.extra_linker_flags = str_lit("-fsanitize=memory");
} else {
build_context.extra_linker_flags = concatenate_strings(permanent_allocator(), build_context.extra_linker_flags, str_lit(" -fsanitize=memory"));
}
}
}
if (build_context.sanitizer_flags & SanitizerFlag_Thread) {
if (build_context.metrics.os == TargetOs_darwin || build_context.metrics.os == TargetOs_linux) {
if (!build_context.extra_linker_flags.text) {
build_context.extra_linker_flags = str_lit("-fsanitize=thread");
} else {
build_context.extra_linker_flags = concatenate_strings(permanent_allocator(), build_context.extra_linker_flags, str_lit(" -fsanitize=thread"));
}
}
}
gb_sort_array(gen->foreign_libraries.data, gen->foreign_libraries.count, foreign_library_cmp);
+4
View File
@@ -15,6 +15,9 @@
#include <llvm-c/Object.h>
#include <llvm-c/BitWriter.h>
#include <llvm-c/DebugInfo.h>
#if LLVM_VERSION_MAJOR >= 17
#include <llvm-c/Transforms/PassBuilder.h>
#else
#include <llvm-c/Transforms/AggressiveInstCombine.h>
#include <llvm-c/Transforms/InstCombine.h>
#include <llvm-c/Transforms/IPO.h>
@@ -23,6 +26,7 @@
#include <llvm-c/Transforms/Utils.h>
#include <llvm-c/Transforms/Vectorize.h>
#endif
#endif
#if LLVM_VERSION_MAJOR < 11
#error "LLVM Version 11 is the minimum required"
+3
View File
@@ -94,6 +94,9 @@ gb_internal LLVMValueRef llvm_const_cast(LLVMValueRef val, LLVMTypeRef dst) {
LLVMTypeKind kind = LLVMGetTypeKind(dst);
switch (kind) {
case LLVMPointerTypeKind:
if (LB_USE_NEW_PASS_SYSTEM) {
return val;
}
return LLVMConstPointerCast(val, dst);
case LLVMStructTypeKind:
// GB_PANIC("%s -> %s", LLVMPrintValueToString(val), LLVMPrintTypeToString(dst));
+3
View File
@@ -1069,6 +1069,7 @@ gb_internal lbValue lb_emit_arith(lbProcedure *p, TokenKind op, lbValue lhs, lbV
args[1] = rhs;
switch (type_size_of(ft)) {
case 2: return lb_emit_runtime_call(p, "quo_complex32", args);
case 4: return lb_emit_runtime_call(p, "quo_complex64", args);
case 8: return lb_emit_runtime_call(p, "quo_complex128", args);
default: GB_PANIC("Unknown float type"); break;
@@ -1145,6 +1146,7 @@ gb_internal lbValue lb_emit_arith(lbProcedure *p, TokenKind op, lbValue lhs, lbV
args[1] = rhs;
switch (8*type_size_of(ft)) {
case 16: return lb_emit_runtime_call(p, "mul_quaternion64", args);
case 32: return lb_emit_runtime_call(p, "mul_quaternion128", args);
case 64: return lb_emit_runtime_call(p, "mul_quaternion256", args);
default: GB_PANIC("Unknown float type"); break;
@@ -1157,6 +1159,7 @@ gb_internal lbValue lb_emit_arith(lbProcedure *p, TokenKind op, lbValue lhs, lbV
args[1] = rhs;
switch (8*type_size_of(ft)) {
case 16: return lb_emit_runtime_call(p, "quo_quaternion64", args);
case 32: return lb_emit_runtime_call(p, "quo_quaternion128", args);
case 64: return lb_emit_runtime_call(p, "quo_quaternion256", args);
default: GB_PANIC("Unknown float type"); break;
+5 -1
View File
@@ -962,8 +962,12 @@ gb_internal bool lb_is_type_proc_recursive(Type *t) {
gb_internal void lb_emit_store(lbProcedure *p, lbValue ptr, lbValue value) {
GB_ASSERT(value.value != nullptr);
Type *a = type_deref(ptr.type);
if (LLVMIsUndef(value.value)) {
return;
}
Type *a = type_deref(ptr.type);
if (LLVMIsNull(value.value)) {
LLVMTypeRef src_t = llvm_addr_type(p->module, ptr);
if (is_type_proc(a)) {
+5 -2
View File
@@ -322,7 +322,11 @@ gb_internal void lb_run_remove_dead_instruction_pass(lbProcedure *p) {
// NOTE(bill): Explicit instructions are set here because some instructions could have side effects
switch (LLVMGetInstructionOpcode(curr_instr)) {
// case LLVMAlloca:
case LLVMLoad:
if (LLVMGetVolatile(curr_instr)) {
break;
}
/*fallthrough*/
case LLVMFNeg:
case LLVMAdd:
case LLVMFAdd:
@@ -342,7 +346,6 @@ gb_internal void lb_run_remove_dead_instruction_pass(lbProcedure *p) {
case LLVMAnd:
case LLVMOr:
case LLVMXor:
case LLVMLoad:
case LLVMGetElementPtr:
case LLVMTrunc:
case LLVMZExt:
+4 -1
View File
@@ -891,6 +891,9 @@ gb_internal lbValue lb_emit_call_internal(lbProcedure *p, lbValue value, lbValue
LLVMValueRef ret = LLVMBuildCall2(p->builder, fnp, fn, args, arg_count, "");
auto llvm_cc = lb_calling_convention_map[proc_type->Proc.calling_convention];
LLVMSetInstructionCallConv(ret, llvm_cc);
LLVMAttributeIndex param_offset = LLVMAttributeIndex_FirstArgIndex;
if (return_ptr.value != nullptr) {
param_offset += 1;
@@ -2766,7 +2769,7 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu
{
GB_ASSERT(arg_count <= 7);
char asm_string_default[] = "int $0x80";
char asm_string_default[] = "int $$0x80";
char *asm_string = asm_string_default;
gbString constraints = gb_string_make(heap_allocator(), "={eax}");
+56 -39
View File
@@ -175,7 +175,8 @@ gb_internal lbValue lb_type_info_member_tags_offset(lbModule *m, isize count, i6
return offset;
}
enum {LB_USE_GIANT_PACKED_STRUCT = LB_USE_NEW_PASS_SYSTEM};
// enum {LB_USE_GIANT_PACKED_STRUCT = LB_USE_NEW_PASS_SYSTEM};
enum {LB_USE_GIANT_PACKED_STRUCT = 0};
gb_internal LLVMTypeRef lb_setup_type_info_data_internal_type(lbModule *m, isize max_type_info_count) {
if (!LB_USE_GIANT_PACKED_STRUCT) {
@@ -269,7 +270,7 @@ gb_internal LLVMTypeRef lb_setup_type_info_data_internal_type(lbModule *m, isize
return LLVMStructType(element_types, cast(unsigned)max_type_info_count, true);
}
gb_internal void lb_setup_type_info_data_giant_packed_struct(lbModule *m, i64 global_type_info_data_entity_count) { // NOTE(bill): Setup type_info data
gb_internal void lb_setup_type_info_data_giant_packed_struct(lbModule *m, i64 global_type_info_data_entity_count, lbProcedure *p) { // NOTE(bill): Setup type_info data
CheckerInfo *info = m->info;
// Useful types
@@ -286,7 +287,6 @@ gb_internal void lb_setup_type_info_data_giant_packed_struct(lbModule *m, i64 gl
defer (gb_free(heap_allocator(), entries_handled.data));
entries_handled[0] = true;
LLVMValueRef giant_struct = lb_global_type_info_data_ptr(m).value;
LLVMTypeRef giant_struct_type = LLVMGlobalGetValueType(giant_struct);
GB_ASSERT(LLVMGetTypeKind(giant_struct_type) == LLVMStructTypeKind);
@@ -320,6 +320,30 @@ gb_internal void lb_setup_type_info_data_giant_packed_struct(lbModule *m, i64 gl
type_info_allocate_values(lb_global_type_info_member_usings);
type_info_allocate_values(lb_global_type_info_member_tags);
i64 const type_info_struct_size = type_size_of(t_type_info);
LLVMTypeRef llvm_u8 = lb_type(m, t_u8);
LLVMTypeRef llvm_int = lb_type(m, t_int);
// LLVMTypeRef llvm_type_info_ptr = lb_type(m, t_type_info_ptr);
auto const get_type_info_ptr = [&](lbModule *m, Type *type) -> LLVMValueRef {
type = default_type(type);
isize index = lb_type_info_index(m->info, type);
GB_ASSERT(index >= 0);
u64 offset = cast(u64)(index * type_info_struct_size);
LLVMValueRef indices[1] = {
LLVMConstInt(llvm_int, offset, false)
};
// LLVMValueRef ptr = LLVMConstInBoundsGEP2(llvm_u8, giant_struct, indices, gb_count_of(indices));
LLVMValueRef ptr = LLVMConstGEP2(llvm_u8, giant_struct, indices, gb_count_of(indices));
return ptr;
// return LLVMConstPointerCast(ptr, llvm_type_info_ptr);
};
for_array(type_info_type_index, info->type_info_types) {
Type *t = info->type_info_types[type_info_type_index];
if (t == nullptr || t == t_invalid) {
@@ -394,7 +418,7 @@ gb_internal void lb_setup_type_info_data_giant_packed_struct(lbModule *m, i64 gl
LLVMValueRef vals[4] = {
lb_const_string(m, t->Named.type_name->token.string).value,
lb_type_info(m, t->Named.base).value,
get_type_info_ptr(m, t->Named.base),
pkg_name,
loc.value
};
@@ -541,10 +565,8 @@ gb_internal void lb_setup_type_info_data_giant_packed_struct(lbModule *m, i64 gl
case Type_Pointer: {
tag_type = t_type_info_pointer;
lbValue gep = lb_type_info(m, t->Pointer.elem);
LLVMValueRef vals[1] = {
gep.value,
get_type_info_ptr(m, t->Pointer.elem),
};
@@ -553,10 +575,9 @@ gb_internal void lb_setup_type_info_data_giant_packed_struct(lbModule *m, i64 gl
}
case Type_MultiPointer: {
tag_type = t_type_info_multi_pointer;
lbValue gep = lb_type_info(m, t->MultiPointer.elem);
LLVMValueRef vals[1] = {
gep.value,
get_type_info_ptr(m, t->MultiPointer.elem),
};
variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals));
@@ -564,10 +585,9 @@ gb_internal void lb_setup_type_info_data_giant_packed_struct(lbModule *m, i64 gl
}
case Type_SoaPointer: {
tag_type = t_type_info_soa_pointer;
lbValue gep = lb_type_info(m, t->SoaPointer.elem);
LLVMValueRef vals[1] = {
gep.value,
get_type_info_ptr(m, t->SoaPointer.elem),
};
variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals));
@@ -578,7 +598,7 @@ gb_internal void lb_setup_type_info_data_giant_packed_struct(lbModule *m, i64 gl
i64 ez = type_size_of(t->Array.elem);
LLVMValueRef vals[3] = {
lb_type_info(m, t->Array.elem).value,
get_type_info_ptr(m, t->Array.elem),
lb_const_int(m, t_int, ez).value,
lb_const_int(m, t_int, t->Array.count).value,
};
@@ -590,8 +610,8 @@ gb_internal void lb_setup_type_info_data_giant_packed_struct(lbModule *m, i64 gl
tag_type = t_type_info_enumerated_array;
LLVMValueRef vals[7] = {
lb_type_info(m, t->EnumeratedArray.elem).value,
lb_type_info(m, t->EnumeratedArray.index).value,
get_type_info_ptr(m, t->EnumeratedArray.elem),
get_type_info_ptr(m, t->EnumeratedArray.index),
lb_const_int(m, t_int, type_size_of(t->EnumeratedArray.elem)).value,
lb_const_int(m, t_int, t->EnumeratedArray.count).value,
@@ -609,7 +629,7 @@ gb_internal void lb_setup_type_info_data_giant_packed_struct(lbModule *m, i64 gl
tag_type = t_type_info_dynamic_array;
LLVMValueRef vals[2] = {
lb_type_info(m, t->DynamicArray.elem).value,
get_type_info_ptr(m, t->DynamicArray.elem),
lb_const_int(m, t_int, type_size_of(t->DynamicArray.elem)).value,
};
@@ -620,7 +640,7 @@ gb_internal void lb_setup_type_info_data_giant_packed_struct(lbModule *m, i64 gl
tag_type = t_type_info_slice;
LLVMValueRef vals[2] = {
lb_type_info(m, t->Slice.elem).value,
get_type_info_ptr(m, t->Slice.elem),
lb_const_int(m, t_int, type_size_of(t->Slice.elem)).value,
};
@@ -633,10 +653,10 @@ gb_internal void lb_setup_type_info_data_giant_packed_struct(lbModule *m, i64 gl
LLVMValueRef params = LLVMConstNull(lb_type(m, t_type_info_ptr));
LLVMValueRef results = LLVMConstNull(lb_type(m, t_type_info_ptr));
if (t->Proc.params != nullptr) {
params = lb_type_info(m, t->Proc.params).value;
params = get_type_info_ptr(m, t->Proc.params);
}
if (t->Proc.results != nullptr) {
results = lb_type_info(m, t->Proc.results).value;
results = get_type_info_ptr(m, t->Proc.results);
}
LLVMValueRef vals[4] = {
@@ -663,7 +683,7 @@ gb_internal void lb_setup_type_info_data_giant_packed_struct(lbModule *m, i64 gl
lbValue index = lb_const_int(m, t_int, i);
lbValue type_info = lb_const_ptr_offset(m, memory_types, index);
lb_global_type_info_member_types_values[type_offset+i] = lb_type_info(m, f->type).value;
lb_global_type_info_member_types_values[type_offset+i] = get_type_info_ptr(m, f->type);
if (f->token.string.len > 0) {
lb_global_type_info_member_names_values[name_offset+i] = lb_const_string(m, f->token.string).value;
}
@@ -692,7 +712,7 @@ gb_internal void lb_setup_type_info_data_giant_packed_struct(lbModule *m, i64 gl
LLVMValueRef vals[3] = {};
vals[0] = lb_type_info(m, t->Enum.base_type).value;
vals[0] = get_type_info_ptr(m, t->Enum.base_type);
if (t->Enum.fields.count > 0) {
auto fields = t->Enum.fields;
lbValue name_array = lb_generate_global_array(m, t_string, fields.count,
@@ -744,9 +764,7 @@ gb_internal void lb_setup_type_info_data_giant_packed_struct(lbModule *m, i64 gl
for (isize variant_index = 0; variant_index < variant_count; variant_index++) {
Type *vt = t->Union.variants[variant_index];
lbValue tip = lb_type_info(m, vt);
lb_global_type_info_member_types_values[variant_offset+variant_index] = lb_type_info(m, vt).value;
lb_global_type_info_member_types_values[variant_offset+variant_index] = get_type_info_ptr(m, vt);
}
lbValue count = lb_const_int(m, t_int, variant_count);
@@ -756,7 +774,7 @@ gb_internal void lb_setup_type_info_data_giant_packed_struct(lbModule *m, i64 gl
if (tag_size > 0) {
i64 tag_offset = align_formula(t->Union.variant_block_size, tag_size);
vals[1] = lb_const_int(m, t_uintptr, tag_offset).value;
vals[2] = lb_type_info(m, union_tag_type(t)).value;
vals[2] = get_type_info_ptr(m, union_tag_type(t));
} else {
vals[1] = lb_const_int(m, t_uintptr, 0).value;
vals[2] = LLVMConstNull(lb_type(m, t_type_info_ptr));
@@ -805,11 +823,11 @@ gb_internal void lb_setup_type_info_data_giant_packed_struct(lbModule *m, i64 gl
Type *kind_type = get_struct_field_type(tag_type, 10);
lbValue soa_kind = lb_const_value(m, kind_type, exact_value_i64(t->Struct.soa_kind));
lbValue soa_type = lb_type_info(m, t->Struct.soa_elem);
LLVMValueRef soa_type = get_type_info_ptr(m, t->Struct.soa_elem);
lbValue soa_len = lb_const_int(m, t_int, t->Struct.soa_count);
vals[10] = soa_kind.value;
vals[11] = soa_type.value;
vals[11] = soa_type;
vals[12] = soa_len.value;
}
}
@@ -831,7 +849,6 @@ gb_internal void lb_setup_type_info_data_giant_packed_struct(lbModule *m, i64 gl
type_set_offsets(t); // NOTE(bill): Just incase the offsets have not been set yet
for (isize source_index = 0; source_index < count; source_index++) {
Entity *f = t->Struct.fields[source_index];
lbValue tip = lb_type_info(m, f->type);
i64 foffset = 0;
if (!t->Struct.is_raw_union) {
GB_ASSERT(t->Struct.offsets != nullptr);
@@ -841,7 +858,7 @@ gb_internal void lb_setup_type_info_data_giant_packed_struct(lbModule *m, i64 gl
GB_ASSERT(f->kind == Entity_Variable && f->flags & EntityFlag_Field);
lb_global_type_info_member_types_values[types_offset+source_index] = lb_type_info(m, f->type).value;
lb_global_type_info_member_types_values[types_offset+source_index] = get_type_info_ptr(m, f->type);
lb_global_type_info_member_offsets_values[offsets_offset+source_index] = lb_const_int(m, t_uintptr, foffset).value;
lb_global_type_info_member_usings_values[usings_offset+source_index] = lb_const_bool(m, t_bool, (f->flags&EntityFlag_Using) != 0).value;
@@ -880,8 +897,8 @@ gb_internal void lb_setup_type_info_data_giant_packed_struct(lbModule *m, i64 gl
init_map_internal_types(t);
LLVMValueRef vals[3] = {
lb_type_info(m, t->Map.key).value,
lb_type_info(m, t->Map.value).value,
get_type_info_ptr(m, t->Map.key),
get_type_info_ptr(m, t->Map.value),
lb_gen_map_info_ptr(m, t).value
};
@@ -897,13 +914,13 @@ gb_internal void lb_setup_type_info_data_giant_packed_struct(lbModule *m, i64 gl
LLVMValueRef vals[4] = {
lb_type_info(m, t->BitSet.elem).value,
get_type_info_ptr(m, t->BitSet.elem),
LLVMConstNull(lb_type(m, t_type_info_ptr)),
lb_const_int(m, t_i64, t->BitSet.lower).value,
lb_const_int(m, t_i64, t->BitSet.upper).value,
};
if (t->BitSet.underlying != nullptr) {
vals[1] = lb_type_info(m, t->BitSet.underlying).value;
vals[1] = get_type_info_ptr(m, t->BitSet.underlying);
}
variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals));
@@ -916,7 +933,7 @@ gb_internal void lb_setup_type_info_data_giant_packed_struct(lbModule *m, i64 gl
LLVMValueRef vals[3] = {};
vals[0] = lb_type_info(m, t->SimdVector.elem).value;
vals[0] = get_type_info_ptr(m, t->SimdVector.elem);
vals[1] = lb_const_int(m, t_int, type_size_of(t->SimdVector.elem)).value;
vals[2] = lb_const_int(m, t_int, t->SimdVector.count).value;
@@ -928,8 +945,8 @@ gb_internal void lb_setup_type_info_data_giant_packed_struct(lbModule *m, i64 gl
{
tag_type = t_type_info_relative_pointer;
LLVMValueRef vals[2] = {
lb_type_info(m, t->RelativePointer.pointer_type).value,
lb_type_info(m, t->RelativePointer.base_integer).value,
get_type_info_ptr(m, t->RelativePointer.pointer_type),
get_type_info_ptr(m, t->RelativePointer.base_integer),
};
variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals));
@@ -940,8 +957,8 @@ gb_internal void lb_setup_type_info_data_giant_packed_struct(lbModule *m, i64 gl
{
tag_type = t_type_info_relative_multi_pointer;
LLVMValueRef vals[2] = {
lb_type_info(m, t->RelativeMultiPointer.pointer_type).value,
lb_type_info(m, t->RelativeMultiPointer.base_integer).value,
get_type_info_ptr(m, t->RelativeMultiPointer.pointer_type),
get_type_info_ptr(m, t->RelativeMultiPointer.base_integer),
};
variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals));
@@ -954,7 +971,7 @@ gb_internal void lb_setup_type_info_data_giant_packed_struct(lbModule *m, i64 gl
i64 ez = type_size_of(t->Matrix.elem);
LLVMValueRef vals[5] = {
lb_type_info(m, t->Matrix.elem).value,
get_type_info_ptr(m, t->Matrix.elem),
lb_const_int(m, t_int, ez).value,
lb_const_int(m, t_int, matrix_type_stride_in_elems(t)).value,
lb_const_int(m, t_int, t->Matrix.row_count).value,
@@ -1037,7 +1054,7 @@ gb_internal void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup
}
if (LB_USE_GIANT_PACKED_STRUCT) {
lb_setup_type_info_data_giant_packed_struct(m, global_type_info_data_entity_count);
lb_setup_type_info_data_giant_packed_struct(m, global_type_info_data_entity_count, p);
return;
}
+2 -2
View File
@@ -89,8 +89,8 @@ gb_global Timings global_timings = {0};
#if LLVM_VERSION_MAJOR < 11
#error LLVM Version 11+ is required => "brew install llvm@11"
#endif
#if LLVM_VERSION_MAJOR > 14
#error LLVM Version 11..=14 is required => "brew install llvm@14"
#if (LLVM_VERSION_MAJOR > 14 && LLVM_VERSION_MAJOR < 17) || LLVM_VERSION_MAJOR > 17
#error LLVM Version 11..=14 or =17 is required => "brew install llvm@14"
#endif
#endif
+10 -10
View File
@@ -1032,22 +1032,22 @@ gb_internal void cg_build_assignment(cgProcedure *p, Array<cgAddr> const &lvals,
continue;
}
Type *type = cg_addr_type(lval);
Type *type = cg_addr_type(lval);
if (!cg_addr_is_empty(lval)) {
GB_ASSERT_MSG(are_types_identical(init.type, type), "%s = %s", type_to_string(init.type), type_to_string(type));
}
if (init.kind == cgValue_Addr &&
!cg_addr_is_empty(lval)) {
// NOTE(bill): This is needed for certain constructs such as this:
// a, b = b, a
// NOTE(bill): This is a bodge and not necessarily a good way of doing things whatsoever
TB_CharUnits size = cast(TB_CharUnits)type_size_of(type);
TB_CharUnits align = cast(TB_CharUnits)type_align_of(type);
TB_Node *copy = tb_inst_local(p->func, size, align);
tb_inst_memcpy(p->func, copy, init.node, tb_inst_uint(p->func, TB_TYPE_INT, size), align);
// use the copy instead
init.node = copy;
// NOTE(bill): This is needed for certain constructs such as this:
// a, b = b, a
// NOTE(bill): This is a bodge and not necessarily a good way of doing things whatsoever
TB_CharUnits size = cast(TB_CharUnits)type_size_of(type);
TB_CharUnits align = cast(TB_CharUnits)type_align_of(type);
TB_Node *copy = tb_inst_local(p->func, size, align);
tb_inst_memcpy(p->func, copy, init.node, tb_inst_uint(p->func, TB_TYPE_INT, size), align);
// use the copy instead
init.node = copy;
}
inits[i] = init;
}
+6 -2
View File
@@ -983,7 +983,7 @@ gb_internal Type *alloc_type_matrix(Type *elem, i64 row_count, i64 column_count,
}
gb_internal Type *alloc_type_enumerated_array(Type *elem, Type *index, ExactValue const *min_value, ExactValue const *max_value, TokenKind op) {
gb_internal Type *alloc_type_enumerated_array(Type *elem, Type *index, ExactValue const *min_value, ExactValue const *max_value, isize count, TokenKind op) {
Type *t = alloc_type(Type_EnumeratedArray);
t->EnumeratedArray.elem = elem;
t->EnumeratedArray.index = index;
@@ -993,7 +993,11 @@ gb_internal Type *alloc_type_enumerated_array(Type *elem, Type *index, ExactValu
gb_memmove(t->EnumeratedArray.max_value, max_value, gb_size_of(ExactValue));
t->EnumeratedArray.op = op;
t->EnumeratedArray.count = 1 + exact_value_to_i64(exact_value_sub(*max_value, *min_value));
if (count == 0) {
t->EnumeratedArray.count = 0;
} else {
t->EnumeratedArray.count = 1 + exact_value_to_i64(exact_value_sub(*max_value, *min_value));
}
return t;
}
@@ -4,6 +4,7 @@ import "core:encoding/json"
import "core:testing"
import "core:fmt"
import "core:os"
import "core:mem/virtual"
TEST_count := 0
TEST_fail := 0
@@ -77,6 +78,49 @@ parse_json :: proc(t: ^testing.T) {
expect(t, err == nil, msg)
}
@test
out_of_memory_in_parse_json :: proc(t: ^testing.T) {
arena: virtual.Arena
arena_buffer: [256]byte
arena_init_error := virtual.arena_init_buffer(&arena, arena_buffer[:])
testing.expect(t, arena_init_error == nil, fmt.tprintf("Expected arena initialization to not return error, got: %v\n", arena_init_error))
context.allocator = virtual.arena_allocator(&arena)
json_data := `
{
"firstName": "John",
"lastName": "Smith",
"isAlive": true,
"age": 27,
"address": {
"streetAddress": "21 2nd Street",
"city": "New York",
"state": "NY",
"postalCode": "10021-3100"
},
"phoneNumbers": [
{
"type": "home",
"number": "212 555-1234"
},
{
"type": "office",
"number": "646 555-4567"
}
],
"children": [],
"spouse": null
}
`
_, err := json.parse(transmute([]u8)json_data)
expected_error := json.Error.Out_Of_Memory
msg := fmt.tprintf("Expected `json.parse` to fail with %v, got %v", expected_error, err)
expect(t, err == json.Error.Out_Of_Memory, msg)
}
@test
marshal_json :: proc(t: ^testing.T) {
+8 -5
View File
@@ -1,6 +1,9 @@
ODIN=../../odin
all: map_test
map_test:
ODIN=../../odin
all: rtti_test map_test
rtti_test:
$(ODIN) run test_rtti.odin -file -vet -strict-style -o:minimal
map_test:
$(ODIN) run test_map.odin -file -vet -strict-style -o:minimal
+4 -3
View File
@@ -1,4 +1,5 @@
@echo off
set PATH_TO_ODIN==..\..\odin
%PATH_TO_ODIN% run test_map.odin -file -vet -strict-style -o:minimal || exit /b
@echo off
set PATH_TO_ODIN==..\..\odin
rem %PATH_TO_ODIN% run test_rtti.odin -file -vet -strict-style -o:minimal || exit /b
%PATH_TO_ODIN% run test_map.odin -file -vet -strict-style -o:minimal || exit /b
rem -define:SEED=42
+101
View File
@@ -0,0 +1,101 @@
package test_internal_rtti
import "core:fmt"
import "core:mem"
import "core:os"
import "core:testing"
Buggy_Struct :: struct {
a: int,
b: bool,
c: [3]^string,
}
#assert(size_of(Buggy_Struct) == 40)
g_buggy: Buggy_Struct = {}
EXPECTED_REPR := "%!s(Buggy_Struct=Buggy_Struct{a = 0, b = false, c = [0x0, 0x0, 0x0]})"
@test
rtti_test :: proc(t: ^testing.T) {
l_buggy: Buggy_Struct = {}
g_b := ([^]u8)(&g_buggy)[:size_of(Buggy_Struct)]
l_b := ([^]u8)(&l_buggy)[:size_of(Buggy_Struct)]
{
checksum := 0
for v, i in g_b {
checksum += (i+1) * int(v)
}
expect(t, checksum == 0, fmt.tprintf("Expected g_b to be zero-initialized, got %v", g_b))
}
{
checksum := 0
for v, i in l_b {
checksum += (i+1) * int(v)
}
expect(t, checksum == 0, fmt.tprintf("Expected l_b to be zero-initialized, got %v", l_b))
}
expect(t, size_of(Buggy_Struct) == 40, fmt.tprintf("Expected size_of(Buggy_Struct) == 40, got %v", size_of(Buggy_Struct)))
expect(t, size_of(g_buggy) == 40, fmt.tprintf("Expected size_of(g_buggy) == 40, got %v", size_of(g_buggy)))
expect(t, size_of(l_buggy) == 40, fmt.tprintf("Expected size_of(l_buggy) == 40, got %v", size_of(l_buggy)))
g_s := fmt.tprintf("%s", g_buggy)
l_s := fmt.tprintf("%s", l_buggy)
expect(t, g_s == EXPECTED_REPR, fmt.tprintf("Expected fmt.tprintf(\"%%s\", g_s)) to return \"%v\", got \"%v\"", EXPECTED_REPR, g_s))
expect(t, l_s == EXPECTED_REPR, fmt.tprintf("Expected fmt.tprintf(\"%%s\", l_s)) to return \"%v\", got \"%v\"", EXPECTED_REPR, l_s))
}
// -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
main :: proc() {
t := testing.T{}
mem_track_test(&t, rtti_test)
fmt.printf("%v/%v tests successful.\n", TEST_count - TEST_fail, TEST_count)
if TEST_fail > 0 {
os.exit(1)
}
}
mem_track_test :: proc(t: ^testing.T, test: proc(t: ^testing.T)) {
track: mem.Tracking_Allocator
mem.tracking_allocator_init(&track, context.allocator)
context.allocator = mem.tracking_allocator(&track)
test(t)
expect(t, len(track.allocation_map) == 0, "Expected no leaks.")
expect(t, len(track.bad_free_array) == 0, "Expected no leaks.")
for _, leak in track.allocation_map {
fmt.printf("%v leaked %v bytes\n", leak.location, leak.size)
}
for bad_free in track.bad_free_array {
fmt.printf("%v allocation %p was freed badly\n", bad_free.location, bad_free.memory)
}
}
TEST_count := 0
TEST_fail := 0
when ODIN_TEST {
expect :: testing.expect
log :: testing.log
} else {
expect :: proc(t: ^testing.T, condition: bool, message: string, loc := #caller_location) {
TEST_count += 1
if !condition {
TEST_fail += 1
fmt.printf("[%v] %v\n", loc, message)
return
}
}
log :: proc(t: ^testing.T, v: any, loc := #caller_location) {
fmt.printf("[%v] ", loc)
fmt.printf("log: %v\n", v)
}
}
+8 -7
View File
@@ -101,12 +101,13 @@ Address :: struct {
port: u16,
}
PacketFlags :: bit_set[PacketFlag; i32]
PacketFlag :: enum i32 {
RELIABLE = 1 << 0,
UNSEQUENCED = 1 << 1,
NO_ALLOCATE = 1 << 2,
UNRELIABLE_FRAGMENT = 1 << 3,
FLAG_SENT = 1 << 8,
RELIABLE = 0,
UNSEQUENCED = 1,
NO_ALLOCATE = 2,
UNRELIABLE_FRAGMENT = 3,
FLAG_SENT = 8,
}
PacketFreeCallback :: proc "c" (packet: ^Packet)
@@ -365,7 +366,7 @@ foreign ENet {
address_get_host_ip :: proc(address: ^Address, hostName: [^]u8, nameLength: uint) -> i32 ---
address_get_host :: proc(address: ^Address, hostName: [^]u8, nameLength: uint) -> i32 ---
packet_create :: proc(data: rawptr, dataLength: uint, flags: PacketFlag) -> ^Packet ---
packet_create :: proc(data: rawptr, dataLength: uint, flags: PacketFlags) -> ^Packet ---
packet_destroy :: proc(packet: ^Packet) ---
packet_resize :: proc(packet: ^Packet, dataLength: uint) -> i32 ---
crc32 :: proc(buffers: [^]Buffer, bufferCount: uint) -> u32 ---
@@ -397,4 +398,4 @@ foreign ENet {
range_coder_destroy :: proc(ctx: rawptr) ---
range_coder_compress :: proc(ctx: rawptr, inBuffers: [^]Buffer, inBufferCount: uint, inLimit: uint, outData: [^]u8, outLimit: uint) -> uint ---
range_coder_decompress :: proc(ctx: rawptr, inData: [^]u8, inLimit: uint, outData: [^]u8, outLimit: uint) -> uint ---
}
}
+7 -1
View File
@@ -1,7 +1,13 @@
package vendor_openexr
OPENEXRCORE_SHARED :: #config(OPENEXRCORE_SHARED, false)
when ODIN_OS == .Windows {
foreign import lib "OpenEXRCore-3_1.lib"
when OPENEXRCORE_SHARED {
#panic("Dynamic linking is not supported for OpenEXRCore yet")
} else {
foreign import lib "OpenEXRCore-3_1.lib"
}
} else {
foreign import lib "system:OpenEXRCore-3_1"
}
+24
View File
@@ -0,0 +1,24 @@
Copyright (C) 1999-2023 The Botan Authors
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions, and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
+5
View File
@@ -10,8 +10,13 @@ import "core:c"
import "core:c/libc"
import "core:runtime"
COMMONMARK_SHARED :: #config(COMMONMARK_SHARED, false)
BINDING_VERSION :: Version_Info{major = 0, minor = 30, patch = 2}
when COMMONMARK_SHARED {
#panic("Shared linking for vendor:commonmark is not supported yet")
}
when ODIN_OS == .Windows {
foreign import lib {
"cmark_static.lib",
+1
View File
@@ -1,3 +1,4 @@
//+build darwin
package CoreVideo
DisplayLinkRef :: distinct rawptr
+1
View File
@@ -1,3 +1,4 @@
//+build darwin
package objc_Foundation
foreign import "system:Foundation.framework"
+1
View File
@@ -1,3 +1,4 @@
//+build darwin
package objc_Foundation
import "core:intrinsics"
+1
View File
@@ -1,3 +1,4 @@
//+build darwin
package objc_Foundation
@(objc_class="NSAutoreleasePool")
+1
View File
@@ -1,3 +1,4 @@
//+build darwin
package objc_Foundation
import "core:intrinsics"
+1
View File
@@ -1,3 +1,4 @@
//+build darwin
package objc_Foundation
@(objc_class="NSBundle")
+1
View File
@@ -1,3 +1,4 @@
//+build darwin
package objc_Foundation
@(objc_class="NSColorSpace")
+1
View File
@@ -1,3 +1,4 @@
//+build darwin
package objc_Foundation
@(objc_class="NSData")
+1
View File
@@ -1,3 +1,4 @@
//+build darwin
package objc_Foundation
@(objc_class="NSDate")
+1
View File
@@ -1,3 +1,4 @@
//+build darwin
package objc_Foundation
@(objc_class="NSDictionary")
+1
View File
@@ -1,3 +1,4 @@
//+build darwin
package objc_Foundation
import "core:c"
+1
View File
@@ -1,3 +1,4 @@
//+build darwin
package objc_Foundation
foreign import "system:Foundation.framework"
+1
View File
@@ -1,3 +1,4 @@
//+build darwin
package objc_Foundation
@(objc_class="NSEvent")
+1
View File
@@ -1,3 +1,4 @@
//+build darwin
package objc_Foundation
Locking :: struct($T: typeid) {using _: Object}
+1
View File
@@ -1,3 +1,4 @@
//+build darwin
package objc_Foundation
import "core:builtin"
+1
View File
@@ -1,3 +1,4 @@
//+build darwin
package objc_Foundation
@(objc_class="NSNotification")
+1
View File
@@ -1,3 +1,4 @@
//+build darwin
package objc_Foundation
import "core:c"
+1
View File
@@ -1,3 +1,4 @@
//+build darwin
package objc_Foundation
import "core:intrinsics"
+1
View File
@@ -1,3 +1,4 @@
//+build darwin
package objc_Foundation
@(objc_class="NSOpenPanel")
+1
View File
@@ -1,3 +1,4 @@
//+build darwin
package objc_Foundation
ModalResponse :: enum UInteger {
+1
View File
@@ -1,3 +1,4 @@
//+build darwin
package objc_Foundation
@(objc_class="NSPasteboard")
+1
View File
@@ -1,3 +1,4 @@
//+build darwin
package objc_Foundation
Range :: struct {

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