mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-05 03:01:38 -07:00
Compare commits
129 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ef5eb4b612 | |||
| 864b29f7f1 | |||
| 4d498b668a | |||
| 62d0b0ae72 | |||
| 2c9ef2e1bc | |||
| 9b68671082 | |||
| 03ab6add5c | |||
| 052633b73c | |||
| bf9a8032a1 | |||
| eb261f5b28 | |||
| f5febb633c | |||
| d2ac3c2228 | |||
| 51caa930ca | |||
| b7af4e7f6b | |||
| 82cd30a145 | |||
| 8caae16113 | |||
| dc789c43b6 | |||
| 2e73fb25af | |||
| 1577d60d02 | |||
| 3bd1918c5e | |||
| 263b3141b5 | |||
| 82263a8b38 | |||
| 61ad2a1345 | |||
| d589914956 | |||
| f54a026acc | |||
| fc06d7011d | |||
| ed7c9ec619 | |||
| 1d9f6346d4 | |||
| a3a3156ddd | |||
| 70bd4a5ab6 | |||
| 034aead930 | |||
| c8a5bafc6b | |||
| 0a7b9338f6 | |||
| bc0fa1240b | |||
| 292398dbe2 | |||
| 49da19e013 | |||
| bbd4c1054e | |||
| 152ac61faf | |||
| 4d65b1ab9c | |||
| 8b2f62000a | |||
| 166803a2a5 | |||
| 11a2b2a942 | |||
| 0a492acaa1 | |||
| e86d7f1fb0 | |||
| 962d599996 | |||
| ba536d67b4 | |||
| 8e4bdcfb98 | |||
| f3f0ab6e2c | |||
| 5a771732bd | |||
| 9b6647a019 | |||
| 7e40a5a711 | |||
| 27cbd0d931 | |||
| 12c316cd6b | |||
| b06583133a | |||
| a2e6fc5909 | |||
| 058065ce75 | |||
| 75a2015260 | |||
| 18776aa6b9 | |||
| 4cf48daa75 | |||
| 361aeac0cc | |||
| 2e66d621b5 | |||
| 566a11a585 | |||
| abb9fb3345 | |||
| 05a9652f76 | |||
| ba5df8edca | |||
| 9afee7e8d2 | |||
| c458186f68 | |||
| f9da0a59e4 | |||
| c19af95db0 | |||
| 840459bdb0 | |||
| 798660c007 | |||
| c039977048 | |||
| 7a9737b3d4 | |||
| 0f5d562625 | |||
| 21f9e7f5e5 | |||
| 6ee7b05b27 | |||
| e4c7e9903e | |||
| a96100d875 | |||
| 10c67051f2 | |||
| a3fbd09ef9 | |||
| 51248270e1 | |||
| 8fe431e53e | |||
| 61a7d88490 | |||
| 496765c043 | |||
| a62039882e | |||
| a2a05e40e6 | |||
| 45d08ea992 | |||
| c9c7aa2e90 | |||
| d0037fcf6b | |||
| b25fba6175 | |||
| afcdbf1ba6 | |||
| 8eff75a484 | |||
| e232cabfab | |||
| e5ed388191 | |||
| c0ac3de272 | |||
| abde9a99c3 | |||
| bdc74a03c0 | |||
| 2783461e69 | |||
| 0f9c75dc08 | |||
| cf937c6341 | |||
| 77210ffa56 | |||
| fb5bb1cd83 | |||
| 23c4615f5e | |||
| fa2b68dac6 | |||
| bd86cb22e0 | |||
| ec2635131b | |||
| 6b3cfdfb2b | |||
| bce66e3b42 | |||
| cffa035c1b | |||
| 1097192554 | |||
| 0c10b951a9 | |||
| ab2907cd51 | |||
| ea8d3d4531 | |||
| 256e4a0081 | |||
| e7adfff9bf | |||
| 721c9e2c97 | |||
| 42c7e39c99 | |||
| 96778c69bc | |||
| 4adcc403c2 | |||
| 931e0d4687 | |||
| 2e3224a138 | |||
| cfa3765d50 | |||
| 11e884aec5 | |||
| 55a1ba710b | |||
| 0a8b266c71 | |||
| 394c12f68d | |||
| 1a57ad233d | |||
| c268463413 | |||
| 98f9f7d42e |
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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 ---
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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:]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
@@ -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))
|
||||
}
|
||||
@@ -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[:], {}
|
||||
}
|
||||
|
||||
@@ -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, {}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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] == '.' {
|
||||
|
||||
@@ -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(": ")
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
@@ -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
|
||||
|
||||
*/
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 $$
|
||||
@@ -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 $$
|
||||
@@ -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
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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, ×pec_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,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()
|
||||
}
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -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,
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
//+build linux
|
||||
package all
|
||||
|
||||
import linux "core:sys/linux"
|
||||
|
||||
_ :: linux
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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) {
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
Vendored
+8
-7
@@ -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 ---
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+7
-1
@@ -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"
|
||||
}
|
||||
|
||||
Vendored
+24
@@ -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.
|
||||
Vendored
+5
@@ -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
@@ -1,3 +1,4 @@
|
||||
//+build darwin
|
||||
package CoreVideo
|
||||
|
||||
DisplayLinkRef :: distinct rawptr
|
||||
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
//+build darwin
|
||||
package objc_Foundation
|
||||
|
||||
foreign import "system:Foundation.framework"
|
||||
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
//+build darwin
|
||||
package objc_Foundation
|
||||
|
||||
import "core:intrinsics"
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//+build darwin
|
||||
package objc_Foundation
|
||||
|
||||
@(objc_class="NSAutoreleasePool")
|
||||
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
//+build darwin
|
||||
package objc_Foundation
|
||||
|
||||
import "core:intrinsics"
|
||||
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
//+build darwin
|
||||
package objc_Foundation
|
||||
|
||||
@(objc_class="NSBundle")
|
||||
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
//+build darwin
|
||||
package objc_Foundation
|
||||
|
||||
@(objc_class="NSColorSpace")
|
||||
|
||||
Vendored
+1
@@ -1,3 +1,4 @@
|
||||
//+build darwin
|
||||
package objc_Foundation
|
||||
|
||||
@(objc_class="NSData")
|
||||
|
||||
Vendored
+1
@@ -1,3 +1,4 @@
|
||||
//+build darwin
|
||||
package objc_Foundation
|
||||
|
||||
@(objc_class="NSDate")
|
||||
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
//+build darwin
|
||||
package objc_Foundation
|
||||
|
||||
@(objc_class="NSDictionary")
|
||||
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
//+build darwin
|
||||
package objc_Foundation
|
||||
|
||||
import "core:c"
|
||||
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
//+build darwin
|
||||
package objc_Foundation
|
||||
|
||||
foreign import "system:Foundation.framework"
|
||||
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
//+build darwin
|
||||
package objc_Foundation
|
||||
|
||||
@(objc_class="NSEvent")
|
||||
|
||||
Vendored
+1
@@ -1,3 +1,4 @@
|
||||
//+build darwin
|
||||
package objc_Foundation
|
||||
|
||||
Locking :: struct($T: typeid) {using _: Object}
|
||||
|
||||
Vendored
+1
@@ -1,3 +1,4 @@
|
||||
//+build darwin
|
||||
package objc_Foundation
|
||||
|
||||
import "core:builtin"
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//+build darwin
|
||||
package objc_Foundation
|
||||
|
||||
@(objc_class="NSNotification")
|
||||
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
//+build darwin
|
||||
package objc_Foundation
|
||||
|
||||
import "core:c"
|
||||
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
//+build darwin
|
||||
package objc_Foundation
|
||||
|
||||
import "core:intrinsics"
|
||||
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
//+build darwin
|
||||
package objc_Foundation
|
||||
|
||||
@(objc_class="NSOpenPanel")
|
||||
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
//+build darwin
|
||||
package objc_Foundation
|
||||
|
||||
ModalResponse :: enum UInteger {
|
||||
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
//+build darwin
|
||||
package objc_Foundation
|
||||
|
||||
@(objc_class="NSPasteboard")
|
||||
|
||||
+1
@@ -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
Reference in New Issue
Block a user