mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-07 12:11:36 -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
|
rm bin/llvm/windows/LLVM-C.lib
|
||||||
mkdir dist
|
mkdir dist
|
||||||
cp odin.exe dist
|
cp odin.exe dist
|
||||||
|
cp LICENSE dist
|
||||||
cp LLVM-C.dll dist
|
cp LLVM-C.dll dist
|
||||||
cp -r shared dist
|
cp -r shared dist
|
||||||
cp -r core dist
|
cp -r core dist
|
||||||
@@ -52,6 +53,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
mkdir dist
|
mkdir dist
|
||||||
cp odin dist
|
cp odin dist
|
||||||
|
cp LICENSE dist
|
||||||
cp libLLVM* dist
|
cp libLLVM* dist
|
||||||
cp -r shared dist
|
cp -r shared dist
|
||||||
cp -r core dist
|
cp -r core dist
|
||||||
@@ -81,6 +83,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
mkdir dist
|
mkdir dist
|
||||||
cp odin dist
|
cp odin dist
|
||||||
|
cp LICENSE dist
|
||||||
cp -r shared dist
|
cp -r shared dist
|
||||||
cp -r core dist
|
cp -r core dist
|
||||||
cp -r vendor dist
|
cp -r vendor dist
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ bld/
|
|||||||
![Cc]ore/[Ll]og/
|
![Cc]ore/[Ll]og/
|
||||||
tests/documentation/verify/
|
tests/documentation/verify/
|
||||||
tests/documentation/all.odin-doc
|
tests/documentation/all.odin-doc
|
||||||
|
tests/internal/test_map
|
||||||
|
tests/internal/test_rtti
|
||||||
# Visual Studio 2015 cache/options directory
|
# Visual Studio 2015 cache/options directory
|
||||||
.vs/
|
.vs/
|
||||||
# Visual Studio Code options directory
|
# Visual Studio Code options directory
|
||||||
|
|||||||
+73
-152
@@ -1,133 +1,90 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env sh
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
: ${CXX=clang++}
|
|
||||||
: ${CPPFLAGS=}
|
: ${CPPFLAGS=}
|
||||||
|
: ${CXX=clang++}
|
||||||
: ${CXXFLAGS=}
|
: ${CXXFLAGS=}
|
||||||
: ${LDFLAGS=}
|
: ${LDFLAGS=}
|
||||||
: ${ODIN_VERSION=dev-$(date +"%Y-%m")}
|
: ${LLVM_CONFIG=}
|
||||||
: ${GIT_SHA=}
|
|
||||||
|
|
||||||
|
CPPFLAGS="$CPPFLAGS -DODIN_VERSION_RAW=\"dev-$(date +"%Y-%m")\""
|
||||||
CXXFLAGS="$CXXFLAGS -std=c++14"
|
CXXFLAGS="$CXXFLAGS -std=c++14"
|
||||||
|
DISABLED_WARNINGS="-Wno-switch -Wno-macro-redefined -Wno-unused-value"
|
||||||
LDFLAGS="$LDFLAGS -pthread -lm -lstdc++"
|
LDFLAGS="$LDFLAGS -pthread -lm -lstdc++"
|
||||||
|
OS_ARCH="$(uname -m)"
|
||||||
|
OS_NAME="$(uname -s)"
|
||||||
|
|
||||||
if [ -d ".git" ] && [ $(which git) ]; then
|
if [ -d ".git" ] && [ -n "$(command -v git)" ]; then
|
||||||
versionTag=( $(git show --pretty='%cd %h' --date=format:%Y-%m --no-patch --no-notes HEAD) )
|
GIT_SHA=$(git show --pretty='%h' --no-patch --no-notes HEAD)
|
||||||
if [ $? -eq 0 ]; then
|
CPPFLAGS="$CPPFLAGS -DGIT_SHA=\"$GIT_SHA\""
|
||||||
ODIN_VERSION="dev-${versionTag[0]}"
|
|
||||||
GIT_SHA="${versionTag[1]}"
|
|
||||||
CPPFLAGS="$CPPFLAGS -DGIT_SHA=\"$GIT_SHA\""
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
CPPFLAGS="$CPPFLAGS -DODIN_VERSION_RAW=\"$ODIN_VERSION\""
|
error() {
|
||||||
|
printf "ERROR: %s\n" "$1"
|
||||||
DISABLED_WARNINGS="-Wno-switch -Wno-macro-redefined -Wno-unused-value"
|
|
||||||
OS=$(uname)
|
|
||||||
|
|
||||||
panic() {
|
|
||||||
printf "%s\n" "$1"
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
version() { echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'; }
|
if [ -z "$LLVM_CONFIG" ]; then
|
||||||
|
# darwin, linux, openbsd
|
||||||
config_darwin() {
|
if [ -n "$(command -v llvm-config-17)" ]; then LLVM_CONFIG="llvm-config-17"
|
||||||
local ARCH=$(uname -m)
|
elif [ -n "$(command -v llvm-config-13)" ]; then LLVM_CONFIG="llvm-config-13"
|
||||||
: ${LLVM_CONFIG=llvm-config}
|
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"
|
||||||
# allow for arm only llvm's with version 13
|
# freebsd
|
||||||
if [ "${ARCH}" == "arm64" ]; then
|
elif [ -n "$(command -v llvm-config17)" ]; then LLVM_CONFIG="llvm-config-17"
|
||||||
MIN_LLVM_VERSION=("13.0.0")
|
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
|
else
|
||||||
# allow for x86 / amd64 all llvm versions beginning from 11
|
error "No llvm-config command found. Set LLVM_CONFIG to proceed."
|
||||||
MIN_LLVM_VERSION=("11.1.0")
|
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
if [ $(version $($LLVM_CONFIG --version)) -lt $(version $MIN_LLVM_VERSION) ]; then
|
LLVM_VERSION="$($LLVM_CONFIG --version)"
|
||||||
if [ "${ARCH}" == "arm64" ]; then
|
LLVM_VERSION_MAJOR="$(echo $LLVM_VERSION | awk -F. '{print $1}')"
|
||||||
panic "Requirement: llvm-config must be base version 13 for arm64"
|
LLVM_VERSION_MINOR="$(echo $LLVM_VERSION | awk -F. '{print $2}')"
|
||||||
else
|
LLVM_VERSION_PATCH="$(echo $LLVM_VERSION | awk -F. '{print $3}')"
|
||||||
panic "Requirement: llvm-config must be base version greater than 11 for amd64/x86"
|
|
||||||
|
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
|
||||||
fi
|
fi
|
||||||
|
|
||||||
MAX_LLVM_VERSION=("14.999.999")
|
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
|
||||||
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 -liconv -ldl -framework System"
|
LDFLAGS="$LDFLAGS -liconv -ldl -framework System"
|
||||||
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
|
|
||||||
LDFLAGS="$LDFLAGS -lLLVM-C"
|
LDFLAGS="$LDFLAGS -lLLVM-C"
|
||||||
}
|
;;
|
||||||
|
FreeBSD)
|
||||||
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
|
|
||||||
|
|
||||||
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
|
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
|
||||||
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)"
|
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)"
|
||||||
}
|
;;
|
||||||
|
Linux)
|
||||||
config_openbsd() {
|
|
||||||
: ${LLVM_CONFIG=/usr/local/bin/llvm-config}
|
|
||||||
|
|
||||||
LDFLAGS="$LDFLAGS -liconv"
|
|
||||||
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
|
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
|
||||||
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)"
|
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!
|
||||||
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
|
|
||||||
cp $(readlink -f $($LLVM_CONFIG --libfiles)) ./
|
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() {
|
build_odin() {
|
||||||
case $1 in
|
case $1 in
|
||||||
@@ -138,20 +95,19 @@ build_odin() {
|
|||||||
EXTRAFLAGS="-O3"
|
EXTRAFLAGS="-O3"
|
||||||
;;
|
;;
|
||||||
release-native)
|
release-native)
|
||||||
local ARCH=$(uname -m)
|
if [ "$OS_ARCH" == "arm64" ]; then
|
||||||
if [ "${ARCH}" == "arm64" ]; then
|
# Use preferred flag for Arm (ie arm64 / aarch64 / etc)
|
||||||
# Use preferred flag for Arm (ie arm64 / aarch64 / etc)
|
EXTRAFLAGS="-O3 -mcpu=native"
|
||||||
EXTRAFLAGS="-O3 -mcpu=native"
|
else
|
||||||
else
|
# Use preferred flag for x86 / amd64
|
||||||
# Use preferred flag for x86 / amd64
|
EXTRAFLAGS="-O3 -march=native"
|
||||||
EXTRAFLAGS="-O3 -march=native"
|
fi
|
||||||
fi
|
|
||||||
;;
|
;;
|
||||||
nightly)
|
nightly)
|
||||||
EXTRAFLAGS="-DNIGHTLY -O3"
|
EXTRAFLAGS="-DNIGHTLY -O3"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
panic "Build mode unsupported!"
|
error "Build mode \"$1\" unsupported!"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
@@ -164,55 +120,20 @@ run_demo() {
|
|||||||
./odin run examples/demo/demo.odin -file
|
./odin run examples/demo/demo.odin -file
|
||||||
}
|
}
|
||||||
|
|
||||||
have_which() {
|
if [ $# -eq 0 ]; then
|
||||||
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
|
|
||||||
build_odin debug
|
build_odin debug
|
||||||
run_demo
|
run_demo
|
||||||
exit 0
|
elif [ $# -eq 1 ]; then
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $# -eq 1 ]]; then
|
|
||||||
case $1 in
|
case $1 in
|
||||||
report)
|
report)
|
||||||
if [[ ! -f "./odin" ]]; then
|
[ ! -f "./odin" ] && build_odin debug
|
||||||
build_odin debug
|
|
||||||
fi
|
|
||||||
|
|
||||||
./odin report
|
./odin report
|
||||||
exit 0
|
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
build_odin $1
|
build_odin $1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
run_demo
|
run_demo
|
||||||
exit 0
|
|
||||||
else
|
else
|
||||||
panic "Too many arguments!"
|
error "Too many arguments!"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ foreign libc {
|
|||||||
fscanf :: proc(stream: ^FILE, format: cstring, #c_vararg args: ..any) -> int ---
|
fscanf :: proc(stream: ^FILE, format: cstring, #c_vararg args: ..any) -> int ---
|
||||||
printf :: proc(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 ---
|
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 ---
|
sscanf :: proc(s, format: cstring, #c_vararg args: ..any) -> int ---
|
||||||
vfprintf :: proc(stream: ^FILE, format: cstring, arg: ^va_list) -> int ---
|
vfprintf :: proc(stream: ^FILE, format: cstring, arg: ^va_list) -> int ---
|
||||||
vfscanf :: 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
|
package crypto
|
||||||
|
|
||||||
when ODIN_OS != .Linux && ODIN_OS != .OpenBSD && ODIN_OS != .Windows {
|
when ODIN_OS != .Linux && ODIN_OS != .OpenBSD && ODIN_OS != .Windows && ODIN_OS != .JS {
|
||||||
_rand_bytes :: proc (dst: []byte) {
|
_rand_bytes :: proc(dst: []byte) {
|
||||||
unimplemented("crypto: rand_bytes not supported on this OS")
|
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
|
package crypto
|
||||||
|
|
||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
import "core:os"
|
|
||||||
import "core:sys/unix"
|
import "core:sys/linux"
|
||||||
|
|
||||||
_MAX_PER_CALL_BYTES :: 33554431 // 2^25 - 1
|
_MAX_PER_CALL_BYTES :: 33554431 // 2^25 - 1
|
||||||
|
|
||||||
@@ -12,26 +12,25 @@ _rand_bytes :: proc (dst: []byte) {
|
|||||||
|
|
||||||
for l > 0 {
|
for l > 0 {
|
||||||
to_read := min(l, _MAX_PER_CALL_BYTES)
|
to_read := min(l, _MAX_PER_CALL_BYTES)
|
||||||
ret := unix.sys_getrandom(raw_data(dst), uint(to_read), 0)
|
n_read, errno := linux.getrandom(dst[:to_read], {})
|
||||||
if ret < 0 {
|
#partial switch errno {
|
||||||
switch os.Errno(-ret) {
|
case .NONE:
|
||||||
case os.EINTR:
|
// Do nothing
|
||||||
// Call interupted by a signal handler, just retry the
|
case .EINTR:
|
||||||
// request.
|
// Call interupted by a signal handler, just retry the
|
||||||
continue
|
// request.
|
||||||
case os.ENOSYS:
|
continue
|
||||||
// The kernel is apparently prehistoric (< 3.17 circa 2014)
|
case .ENOSYS:
|
||||||
// and does not support getrandom.
|
// The kernel is apparently prehistoric (< 3.17 circa 2014)
|
||||||
panic("crypto: getrandom not available in kernel")
|
// and does not support getrandom.
|
||||||
case:
|
panic("crypto: getrandom not available in kernel")
|
||||||
// All other failures are things that should NEVER happen
|
case:
|
||||||
// unless the kernel interface changes (ie: the Linux
|
// All other failures are things that should NEVER happen
|
||||||
// developers break userland).
|
// unless the kernel interface changes (ie: the Linux
|
||||||
panic(fmt.tprintf("crypto: getrandom failed: %d", ret))
|
// developers break userland).
|
||||||
}
|
panic(fmt.tprintf("crypto: getrandom failed: %v", errno))
|
||||||
}
|
}
|
||||||
|
l -= n_read
|
||||||
l -= ret
|
dst = dst[n_read:]
|
||||||
dst = dst[ret:]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -263,8 +263,17 @@ parse_object_body :: proc(p: ^Parser, end_token: Token_Kind) -> (obj: Object, er
|
|||||||
return
|
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) {
|
if parse_comma(p) {
|
||||||
break
|
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
|
package rand
|
||||||
|
|
||||||
import "core:sys/unix"
|
import "core:sys/linux"
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
_system_random :: proc() -> u64 {
|
_system_random :: proc() -> u64 {
|
||||||
for {
|
for {
|
||||||
value: u64
|
value: u64
|
||||||
ret := unix.sys_getrandom(([^]u8)(&value), size_of(value), 0)
|
value_buf := (cast([^]u8)&value)[:size_of(u64)]
|
||||||
if ret < 0 {
|
_, errno := linux.getrandom(value_buf, {})
|
||||||
switch ret {
|
#partial switch errno {
|
||||||
case -4: // EINTR
|
case .NONE:
|
||||||
// Call interupted by a signal handler, just retry the request.
|
// Do nothing
|
||||||
continue
|
case .EINTR:
|
||||||
case -38: // ENOSYS
|
// Call interupted by a signal handler, just retry the request.
|
||||||
// The kernel is apparently prehistoric (< 3.17 circa 2014)
|
continue
|
||||||
// and does not support getrandom.
|
case .ENOSYS:
|
||||||
panic("getrandom not available in kernel")
|
// The kernel is apparently prehistoric (< 3.17 circa 2014)
|
||||||
case:
|
// and does not support getrandom.
|
||||||
// All other failures are things that should NEVER happen
|
panic("getrandom not available in kernel")
|
||||||
// unless the kernel interface changes (ie: the Linux
|
case:
|
||||||
// developers break userland).
|
// All other failures are things that should NEVER happen
|
||||||
panic("getrandom failed")
|
// unless the kernel interface changes (ie: the Linux
|
||||||
}
|
// developers break userland).
|
||||||
|
panic("getrandom failed")
|
||||||
}
|
}
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,100 +2,49 @@
|
|||||||
//+private
|
//+private
|
||||||
package mem_virtual
|
package mem_virtual
|
||||||
|
|
||||||
import "core:c"
|
import "core:sys/linux"
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
_reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) {
|
_reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) {
|
||||||
result := mmap(nil, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
|
addr, errno := linux.mmap(0, size, {}, {.PRIVATE, .ANONYMOUS})
|
||||||
if result < 0 && result > -4096 {
|
if errno == .ENOMEM {
|
||||||
return nil, .Out_Of_Memory
|
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 {
|
_commit :: proc "contextless" (data: rawptr, size: uint) -> Allocator_Error {
|
||||||
result := mprotect(data, size, PROT_READ|PROT_WRITE)
|
errno := linux.mprotect(data, size, {.READ, .WRITE})
|
||||||
if result != 0 {
|
if errno == .EINVAL {
|
||||||
// TODO(bill): Handle error value correctly
|
return .Invalid_Pointer
|
||||||
|
} else if errno == .ENOMEM {
|
||||||
return .Out_Of_Memory
|
return .Out_Of_Memory
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
_decommit :: proc "contextless" (data: rawptr, size: uint) {
|
_decommit :: proc "contextless" (data: rawptr, size: uint) {
|
||||||
mprotect(data, size, PROT_NONE)
|
_ = linux.mprotect(data, size, {})
|
||||||
madvise(data, size, MADV_FREE)
|
_ = linux.madvise(data, size, .FREE)
|
||||||
}
|
}
|
||||||
|
|
||||||
_release :: proc "contextless" (data: rawptr, size: uint) {
|
_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 {
|
_protect :: proc "contextless" (data: rawptr, size: uint, flags: Protect_Flags) -> bool {
|
||||||
pflags: c.int
|
pflags: linux.Mem_Protection
|
||||||
pflags = PROT_NONE
|
pflags = {}
|
||||||
if .Read in flags { pflags |= PROT_READ }
|
if .Read in flags { pflags |= {.READ} }
|
||||||
if .Write in flags { pflags |= PROT_WRITE }
|
if .Write in flags { pflags |= {.WRITE} }
|
||||||
if .Execute in flags { pflags |= PROT_EXEC }
|
if .Execute in flags { pflags |= {.EXEC} }
|
||||||
err := mprotect(data, size, pflags)
|
errno := linux.mprotect(data, size, pflags)
|
||||||
return err != 0
|
return errno != .NONE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
_platform_memory_init :: proc() {
|
_platform_memory_init :: proc() {
|
||||||
DEFAULT_PAGE_SIZE = 4096
|
DEFAULT_PAGE_SIZE = 4096
|
||||||
|
|
||||||
// is power of two
|
// is power of two
|
||||||
assert(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0)
|
assert(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0)
|
||||||
}
|
}
|
||||||
|
|||||||
+95
-93
@@ -16,182 +16,184 @@ package net
|
|||||||
Tetralux: Initial implementation
|
Tetralux: Initial implementation
|
||||||
Colin Davidson: Linux platform code, OSX platform code, Odin-native DNS resolver
|
Colin Davidson: Linux platform code, OSX platform code, Odin-native DNS resolver
|
||||||
Jeroen van Rijn: Cross platform unification, code style, documentation
|
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:c"
|
||||||
import "core:os"
|
import "core:sys/linux"
|
||||||
|
|
||||||
Create_Socket_Error :: enum c.int {
|
Create_Socket_Error :: enum c.int {
|
||||||
None = 0,
|
None = 0,
|
||||||
Family_Not_Supported_For_This_Socket = c.int(os.EAFNOSUPPORT),
|
Family_Not_Supported_For_This_Socket = c.int(linux.Errno.EAFNOSUPPORT),
|
||||||
No_Socket_Descriptors_Available = c.int(os.EMFILE),
|
No_Socket_Descriptors_Available = c.int(linux.Errno.EMFILE),
|
||||||
No_Buffer_Space_Available = c.int(os.ENOBUFS),
|
No_Buffer_Space_Available = c.int(linux.Errno.ENOBUFS),
|
||||||
No_Memory_Available_Available = c.int(os.ENOMEM),
|
No_Memory_Available_Available = c.int(linux.Errno.ENOMEM),
|
||||||
Protocol_Unsupported_By_System = c.int(os.EPROTONOSUPPORT),
|
Protocol_Unsupported_By_System = c.int(linux.Errno.EPROTONOSUPPORT),
|
||||||
Wrong_Protocol_For_Socket = c.int(os.EPROTONOSUPPORT),
|
Wrong_Protocol_For_Socket = c.int(linux.Errno.EPROTONOSUPPORT),
|
||||||
Family_And_Socket_Type_Mismatch = c.int(os.EPROTONOSUPPORT),
|
Family_And_Socket_Type_Mismatch = c.int(linux.Errno.EPROTONOSUPPORT),
|
||||||
}
|
}
|
||||||
|
|
||||||
Dial_Error :: enum c.int {
|
Dial_Error :: enum c.int {
|
||||||
None = 0,
|
None = 0,
|
||||||
Port_Required = -1,
|
Port_Required = -1,
|
||||||
|
|
||||||
Address_In_Use = c.int(os.EADDRINUSE),
|
Address_In_Use = c.int(linux.Errno.EADDRINUSE),
|
||||||
In_Progress = c.int(os.EINPROGRESS),
|
In_Progress = c.int(linux.Errno.EINPROGRESS),
|
||||||
Cannot_Use_Any_Address = c.int(os.EADDRNOTAVAIL),
|
Cannot_Use_Any_Address = c.int(linux.Errno.EADDRNOTAVAIL),
|
||||||
Wrong_Family_For_Socket = c.int(os.EAFNOSUPPORT),
|
Wrong_Family_For_Socket = c.int(linux.Errno.EAFNOSUPPORT),
|
||||||
Refused = c.int(os.ECONNREFUSED),
|
Refused = c.int(linux.Errno.ECONNREFUSED),
|
||||||
Is_Listening_Socket = c.int(os.EACCES),
|
Is_Listening_Socket = c.int(linux.Errno.EACCES),
|
||||||
Already_Connected = c.int(os.EISCONN),
|
Already_Connected = c.int(linux.Errno.EISCONN),
|
||||||
Network_Unreachable = c.int(os.ENETUNREACH), // Device is offline
|
Network_Unreachable = c.int(linux.Errno.ENETUNREACH), // Device is offline
|
||||||
Host_Unreachable = c.int(os.EHOSTUNREACH), // Remote host cannot be reached
|
Host_Unreachable = c.int(linux.Errno.EHOSTUNREACH), // Remote host cannot be reached
|
||||||
No_Buffer_Space_Available = c.int(os.ENOBUFS),
|
No_Buffer_Space_Available = c.int(linux.Errno.ENOBUFS),
|
||||||
Not_Socket = c.int(os.ENOTSOCK),
|
Not_Socket = c.int(linux.Errno.ENOTSOCK),
|
||||||
Timeout = c.int(os.ETIMEDOUT),
|
Timeout = c.int(linux.Errno.ETIMEDOUT),
|
||||||
|
|
||||||
// TODO: we may need special handling for this; maybe make a socket a struct with metadata?
|
// 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 {
|
Bind_Error :: enum c.int {
|
||||||
None = 0,
|
None = 0,
|
||||||
Address_In_Use = c.int(os.EADDRINUSE), // Another application is currently bound to this endpoint.
|
Address_In_Use = c.int(linux.Errno.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.
|
Given_Nonlocal_Address = c.int(linux.Errno.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.
|
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(os.EFAULT), // The address family of the address does not match that of the socket.
|
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(os.EINVAL), // The socket is already bound to an address.
|
Already_Bound = c.int(linux.Errno.EINVAL), // The socket is already bound to an address.
|
||||||
No_Ports_Available = c.int(os.ENOBUFS), // There are not enough ephemeral ports available.
|
No_Ports_Available = c.int(linux.Errno.ENOBUFS), // There are not enough ephemeral ports available.
|
||||||
}
|
}
|
||||||
|
|
||||||
Listen_Error :: enum c.int {
|
Listen_Error :: enum c.int {
|
||||||
None = 0,
|
None = 0,
|
||||||
Address_In_Use = c.int(os.EADDRINUSE),
|
Address_In_Use = c.int(linux.Errno.EADDRINUSE),
|
||||||
Already_Connected = c.int(os.EISCONN),
|
Already_Connected = c.int(linux.Errno.EISCONN),
|
||||||
No_Socket_Descriptors_Available = c.int(os.EMFILE),
|
No_Socket_Descriptors_Available = c.int(linux.Errno.EMFILE),
|
||||||
No_Buffer_Space_Available = c.int(os.ENOBUFS),
|
No_Buffer_Space_Available = c.int(linux.Errno.ENOBUFS),
|
||||||
Nonlocal_Address = c.int(os.EADDRNOTAVAIL),
|
Nonlocal_Address = c.int(linux.Errno.EADDRNOTAVAIL),
|
||||||
Not_Socket = c.int(os.ENOTSOCK),
|
Not_Socket = c.int(linux.Errno.ENOTSOCK),
|
||||||
Listening_Not_Supported_For_This_Socket = c.int(os.EOPNOTSUPP),
|
Listening_Not_Supported_For_This_Socket = c.int(linux.Errno.EOPNOTSUPP),
|
||||||
}
|
}
|
||||||
|
|
||||||
Accept_Error :: enum c.int {
|
Accept_Error :: enum c.int {
|
||||||
None = 0,
|
None = 0,
|
||||||
Not_Listening = c.int(os.EINVAL),
|
Not_Listening = c.int(linux.Errno.EINVAL),
|
||||||
No_Socket_Descriptors_Available_For_Client_Socket = c.int(os.EMFILE),
|
No_Socket_Descriptors_Available_For_Client_Socket = c.int(linux.Errno.EMFILE),
|
||||||
No_Buffer_Space_Available = c.int(os.ENOBUFS),
|
No_Buffer_Space_Available = c.int(linux.Errno.ENOBUFS),
|
||||||
Not_Socket = c.int(os.ENOTSOCK),
|
Not_Socket = c.int(linux.Errno.ENOTSOCK),
|
||||||
Not_Connection_Oriented_Socket = c.int(os.EOPNOTSUPP),
|
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?
|
// 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 {
|
TCP_Recv_Error :: enum c.int {
|
||||||
None = 0,
|
None = 0,
|
||||||
Shutdown = c.int(os.ESHUTDOWN),
|
Shutdown = c.int(linux.Errno.ESHUTDOWN),
|
||||||
Not_Connected = c.int(os.ENOTCONN),
|
Not_Connected = c.int(linux.Errno.ENOTCONN),
|
||||||
Connection_Broken = c.int(os.ENETRESET),
|
Connection_Broken = c.int(linux.Errno.ENETRESET),
|
||||||
Not_Socket = c.int(os.ENOTSOCK),
|
Not_Socket = c.int(linux.Errno.ENOTSOCK),
|
||||||
Aborted = c.int(os.ECONNABORTED),
|
Aborted = c.int(linux.Errno.ECONNABORTED),
|
||||||
|
|
||||||
// TODO(tetra): Determine when this is different from the syscall returning n=0 and maybe normalize them?
|
// TODO(tetra): Determine when this is different from the syscall returning n=0 and maybe normalize them?
|
||||||
Connection_Closed = c.int(os.ECONNRESET),
|
Connection_Closed = c.int(linux.Errno.ECONNRESET),
|
||||||
Offline = c.int(os.ENETDOWN),
|
Offline = c.int(linux.Errno.ENETDOWN),
|
||||||
Host_Unreachable = c.int(os.EHOSTUNREACH),
|
Host_Unreachable = c.int(linux.Errno.EHOSTUNREACH),
|
||||||
Interrupted = c.int(os.EINTR),
|
Interrupted = c.int(linux.Errno.EINTR),
|
||||||
Timeout = c.int(os.EWOULDBLOCK), // NOTE: No, really. Presumably this means something different for nonblocking sockets...
|
Timeout = c.int(linux.Errno.EWOULDBLOCK), // NOTE: No, really. Presumably this means something different for nonblocking sockets...
|
||||||
}
|
}
|
||||||
|
|
||||||
UDP_Recv_Error :: enum c.int {
|
UDP_Recv_Error :: enum c.int {
|
||||||
None = 0,
|
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.
|
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(os.ENOTSOCK), // The so-called socket is not an open socket.
|
Not_Socket = c.int(linux.Errno.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.
|
Not_Descriptor = c.int(linux.Errno.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.
|
Bad_Buffer = c.int(linux.Errno.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).
|
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.
|
// 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...
|
// NOTE: No, really. Presumably this means something different for nonblocking sockets...
|
||||||
Timeout = c.int(os.EWOULDBLOCK),
|
Timeout = c.int(linux.Errno.EWOULDBLOCK),
|
||||||
Socket_Not_Bound = c.int(os.EINVAL), // The socket must be bound for this operation, but isn't.
|
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 {
|
TCP_Send_Error :: enum c.int {
|
||||||
None = 0,
|
None = 0,
|
||||||
Aborted = c.int(os.ECONNABORTED),
|
Aborted = c.int(linux.Errno.ECONNABORTED),
|
||||||
Connection_Closed = c.int(os.ECONNRESET),
|
Connection_Closed = c.int(linux.Errno.ECONNRESET),
|
||||||
Not_Connected = c.int(os.ENOTCONN),
|
Not_Connected = c.int(linux.Errno.ENOTCONN),
|
||||||
Shutdown = c.int(os.ESHUTDOWN),
|
Shutdown = c.int(linux.Errno.ESHUTDOWN),
|
||||||
|
|
||||||
// The send queue was full.
|
// The send queue was full.
|
||||||
// This is usually a transient issue.
|
// This is usually a transient issue.
|
||||||
//
|
//
|
||||||
// This also shouldn't normally happen on Linux, as data is dropped if it
|
// This also shouldn't normally happen on Linux, as data is dropped if it
|
||||||
// doesn't fit in the send queue.
|
// doesn't fit in the send queue.
|
||||||
No_Buffer_Space_Available = c.int(os.ENOBUFS),
|
No_Buffer_Space_Available = c.int(linux.Errno.ENOBUFS),
|
||||||
Offline = c.int(os.ENETDOWN),
|
Offline = c.int(linux.Errno.ENETDOWN),
|
||||||
Host_Unreachable = c.int(os.EHOSTUNREACH),
|
Host_Unreachable = c.int(linux.Errno.EHOSTUNREACH),
|
||||||
Interrupted = c.int(os.EINTR), // A signal occurred before any data was transmitted. See signal(7).
|
Interrupted = c.int(linux.Errno.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.
|
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(os.ENOTSOCK), // The so-called socket is not an open socket.
|
Not_Socket = c.int(linux.Errno.ENOTSOCK), // The so-called socket is not an open socket.
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
UDP_Send_Error :: enum c.int {
|
UDP_Send_Error :: enum c.int {
|
||||||
None = 0,
|
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
|
// TODO: not sure what the exact circumstances for this is yet
|
||||||
Network_Unreachable = c.int(os.ENETUNREACH),
|
Network_Unreachable = c.int(linux.Errno.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.
|
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.
|
// 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...
|
// NOTE: No, really. Presumably this means something different for nonblocking sockets...
|
||||||
Timeout = c.int(os.EWOULDBLOCK),
|
Timeout = c.int(linux.Errno.EWOULDBLOCK),
|
||||||
Not_Socket = c.int(os.ENOTSOCK), // The so-called socket is not an open socket.
|
Not_Socket = c.int(linux.Errno.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.
|
Not_Descriptor = c.int(linux.Errno.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.
|
Bad_Buffer = c.int(linux.Errno.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).
|
Interrupted = c.int(linux.Errno.EINTR), // A signal occurred before any data was transmitted. See signal(7).
|
||||||
|
|
||||||
// The send queue was full.
|
// The send queue was full.
|
||||||
// This is usually a transient issue.
|
// This is usually a transient issue.
|
||||||
//
|
//
|
||||||
// This also shouldn't normally happen on Linux, as data is dropped if it
|
// This also shouldn't normally happen on Linux, as data is dropped if it
|
||||||
// doesn't fit in the send queue.
|
// doesn't fit in the send queue.
|
||||||
No_Buffer_Space_Available = c.int(os.ENOBUFS),
|
No_Buffer_Space_Available = c.int(linux.Errno.ENOBUFS),
|
||||||
No_Memory_Available = c.int(os.ENOMEM), // No memory was available to properly manage the send queue.
|
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 {
|
Shutdown_Manner :: enum c.int {
|
||||||
Receive = c.int(os.SHUT_RD),
|
Receive = c.int(linux.Shutdown_How.RD),
|
||||||
Send = c.int(os.SHUT_WR),
|
Send = c.int(linux.Shutdown_How.WR),
|
||||||
Both = c.int(os.SHUT_RDWR),
|
Both = c.int(linux.Shutdown_How.RDWR),
|
||||||
}
|
}
|
||||||
|
|
||||||
Shutdown_Error :: enum c.int {
|
Shutdown_Error :: enum c.int {
|
||||||
None = 0,
|
None = 0,
|
||||||
Aborted = c.int(os.ECONNABORTED),
|
Aborted = c.int(linux.Errno.ECONNABORTED),
|
||||||
Reset = c.int(os.ECONNRESET),
|
Reset = c.int(linux.Errno.ECONNRESET),
|
||||||
Offline = c.int(os.ENETDOWN),
|
Offline = c.int(linux.Errno.ENETDOWN),
|
||||||
Not_Connected = c.int(os.ENOTCONN),
|
Not_Connected = c.int(linux.Errno.ENOTCONN),
|
||||||
Not_Socket = c.int(os.ENOTSOCK),
|
Not_Socket = c.int(linux.Errno.ENOTSOCK),
|
||||||
Invalid_Manner = c.int(os.EINVAL),
|
Invalid_Manner = c.int(linux.Errno.EINVAL),
|
||||||
}
|
}
|
||||||
|
|
||||||
Socket_Option_Error :: enum c.int {
|
Socket_Option_Error :: enum c.int {
|
||||||
None = 0,
|
None = 0,
|
||||||
Offline = c.int(os.ENETDOWN),
|
Offline = c.int(linux.Errno.ENETDOWN),
|
||||||
Timeout_When_Keepalive_Set = c.int(os.ENETRESET),
|
Timeout_When_Keepalive_Set = c.int(linux.Errno.ENETRESET),
|
||||||
Invalid_Option_For_Socket = c.int(os.ENOPROTOOPT),
|
Invalid_Option_For_Socket = c.int(linux.Errno.ENOPROTOOPT),
|
||||||
Reset_When_Keepalive_Set = c.int(os.ENOTCONN),
|
Reset_When_Keepalive_Set = c.int(linux.Errno.ENOTCONN),
|
||||||
Not_Socket = c.int(os.ENOTSOCK),
|
Not_Socket = c.int(linux.Errno.ENOTSOCK),
|
||||||
}
|
}
|
||||||
|
|
||||||
Set_Blocking_Error :: enum c.int {
|
Set_Blocking_Error :: enum c.int {
|
||||||
None = 0,
|
None = 0,
|
||||||
|
|
||||||
// TODO: add errors occuring on followig calls:
|
// TODO: add errors occuring on followig calls:
|
||||||
// flags, _ := os.fcntl(sd, os.F_GETFL, 0)
|
// flags, _ := linux.Errno.fcntl(sd, linux.Errno.F_GETFL, 0)
|
||||||
// os.fcntl(sd, os.F_SETFL, flags | int(os.O_NONBLOCK))
|
// 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)
|
@(private)
|
||||||
_enumerate_interfaces :: proc(allocator := context.allocator) -> (interfaces: []Network_Interface, err: Network_Error) {
|
_enumerate_interfaces :: proc(allocator := context.allocator) -> (interfaces: []Network_Interface, err: Network_Error) {
|
||||||
context.allocator = allocator
|
context.allocator = allocator
|
||||||
|
|
||||||
|
head: ^os.ifaddrs
|
||||||
|
|
||||||
// TODO: Implement. Can probably use the (current) Linux implementation,
|
if res := os._getifaddrs(&head); res < 0 {
|
||||||
// which will itself be switched over to talking to the kernel via NETLINK protocol
|
return {}, .Unable_To_Enumerate_Network_Interfaces
|
||||||
// once we have raw sockets.
|
}
|
||||||
|
|
||||||
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.
|
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)
|
@(private)
|
||||||
_enumerate_interfaces :: proc(allocator := context.allocator) -> (interfaces: []Network_Interface, err: Network_Error) {
|
_enumerate_interfaces :: proc(allocator := context.allocator) -> (interfaces: []Network_Interface, err: Network_Error) {
|
||||||
context.allocator = allocator
|
context.allocator = allocator
|
||||||
|
|
||||||
head: ^os.ifaddrs
|
// head: ^os.ifaddrs
|
||||||
|
|
||||||
if res := os._getifaddrs(&head); res < 0 {
|
// if res := os._getifaddrs(&head); res < 0 {
|
||||||
return {}, .Unable_To_Enumerate_Network_Interfaces
|
// return {}, .Unable_To_Enumerate_Network_Interfaces
|
||||||
}
|
// }
|
||||||
|
|
||||||
/*
|
// /*
|
||||||
Unlike Windows, *nix regrettably doesn't return all it knows about an interface in one big struct.
|
// 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.
|
// We're going to have to iterate over a list and coalesce information as we go.
|
||||||
*/
|
// */
|
||||||
ifaces: map[string]^Network_Interface
|
// ifaces: map[string]^Network_Interface
|
||||||
defer delete(ifaces)
|
// defer delete(ifaces)
|
||||||
|
|
||||||
for ifaddr := head; ifaddr != nil; ifaddr = ifaddr.next {
|
// for ifaddr := head; ifaddr != nil; ifaddr = ifaddr.next {
|
||||||
adapter_name := string(ifaddr.name)
|
// adapter_name := string(ifaddr.name)
|
||||||
|
|
||||||
/*
|
// /*
|
||||||
Check if we have seen this interface name before so we can reuse the `Network_Interface`.
|
// Check if we have seen this interface name before so we can reuse the `Network_Interface`.
|
||||||
Else, create a new one.
|
// Else, create a new one.
|
||||||
*/
|
// */
|
||||||
if adapter_name not_in ifaces {
|
// if adapter_name not_in ifaces {
|
||||||
ifaces[adapter_name] = new(Network_Interface)
|
// ifaces[adapter_name] = new(Network_Interface)
|
||||||
ifaces[adapter_name].adapter_name = strings.clone(adapter_name)
|
// ifaces[adapter_name].adapter_name = strings.clone(adapter_name)
|
||||||
}
|
// }
|
||||||
iface := ifaces[adapter_name]
|
// iface := ifaces[adapter_name]
|
||||||
|
|
||||||
address: Address
|
// address: Address
|
||||||
netmask: Netmask
|
// netmask: Netmask
|
||||||
|
|
||||||
if ifaddr.address != nil {
|
// if ifaddr.address != nil {
|
||||||
switch int(ifaddr.address.sa_family) {
|
// switch int(ifaddr.address.sa_family) {
|
||||||
case os.AF_INET, os.AF_INET6:
|
// case os.AF_INET, os.AF_INET6:
|
||||||
address = _sockaddr_basic_to_endpoint(ifaddr.address).address
|
// address = _sockaddr_basic_to_endpoint(ifaddr.address).address
|
||||||
|
|
||||||
case os.AF_PACKET:
|
// case os.AF_PACKET:
|
||||||
/*
|
// /*
|
||||||
For some obscure reason the 64-bit `getifaddrs` call returns a pointer to a
|
// 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
|
// 32-bit `RTNL_LINK_STATS` structure, which of course means that tx/rx byte count
|
||||||
is truncated beyond usefulness.
|
// is truncated beyond usefulness.
|
||||||
|
|
||||||
We're not going to retrieve stats now. Instead this serves as a reminder to use
|
// We're not going to retrieve stats now. Instead this serves as a reminder to use
|
||||||
the NETLINK protocol for this purpose.
|
// the NETLINK protocol for this purpose.
|
||||||
|
|
||||||
But in case you were curious:
|
// But in case you were curious:
|
||||||
stats := transmute(^os.rtnl_link_stats)ifaddr.data
|
// stats := transmute(^os.rtnl_link_stats)ifaddr.data
|
||||||
fmt.println(stats)
|
// fmt.println(stats)
|
||||||
*/
|
// */
|
||||||
case:
|
// case:
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
if ifaddr.netmask != nil {
|
// if ifaddr.netmask != nil {
|
||||||
switch int(ifaddr.netmask.sa_family) {
|
// switch int(ifaddr.netmask.sa_family) {
|
||||||
case os.AF_INET, os.AF_INET6:
|
// case os.AF_INET, os.AF_INET6:
|
||||||
netmask = Netmask(_sockaddr_basic_to_endpoint(ifaddr.netmask).address)
|
// netmask = Netmask(_sockaddr_basic_to_endpoint(ifaddr.netmask).address)
|
||||||
case:
|
// case:
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
if ifaddr.broadcast_or_dest != nil && .BROADCAST in ifaddr.flags {
|
// if ifaddr.broadcast_or_dest != nil && .BROADCAST in ifaddr.flags {
|
||||||
switch int(ifaddr.broadcast_or_dest.sa_family) {
|
// switch int(ifaddr.broadcast_or_dest.sa_family) {
|
||||||
case os.AF_INET, os.AF_INET6:
|
// case os.AF_INET, os.AF_INET6:
|
||||||
broadcast := _sockaddr_basic_to_endpoint(ifaddr.broadcast_or_dest).address
|
// broadcast := _sockaddr_basic_to_endpoint(ifaddr.broadcast_or_dest).address
|
||||||
append(&iface.multicast, broadcast)
|
// append(&iface.multicast, broadcast)
|
||||||
case:
|
// case:
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
if address != nil {
|
// if address != nil {
|
||||||
lease := Lease{
|
// lease := Lease{
|
||||||
address = address,
|
// address = address,
|
||||||
netmask = netmask,
|
// netmask = netmask,
|
||||||
}
|
// }
|
||||||
append(&iface.unicast, lease)
|
// append(&iface.unicast, lease)
|
||||||
}
|
// }
|
||||||
|
|
||||||
/*
|
// /*
|
||||||
TODO: Refine this based on the type of adapter.
|
// TODO: Refine this based on the type of adapter.
|
||||||
*/
|
// */
|
||||||
state := Link_State{}
|
// state := Link_State{}
|
||||||
|
|
||||||
if .UP in ifaddr.flags {
|
// if .UP in ifaddr.flags {
|
||||||
state |= {.Up}
|
// state |= {.Up}
|
||||||
}
|
// }
|
||||||
|
|
||||||
if .DORMANT in ifaddr.flags {
|
// if .DORMANT in ifaddr.flags {
|
||||||
state |= {.Dormant}
|
// state |= {.Dormant}
|
||||||
}
|
// }
|
||||||
|
|
||||||
if .LOOPBACK in ifaddr.flags {
|
// if .LOOPBACK in ifaddr.flags {
|
||||||
state |= {.Loopback}
|
// state |= {.Loopback}
|
||||||
}
|
// }
|
||||||
iface.link.state = state
|
// iface.link.state = state
|
||||||
}
|
// }
|
||||||
|
|
||||||
/*
|
// /*
|
||||||
Free the OS structures.
|
// Free the OS structures.
|
||||||
*/
|
// */
|
||||||
os._freeifaddrs(head)
|
// os._freeifaddrs(head)
|
||||||
|
|
||||||
/*
|
// /*
|
||||||
Turn the map into a slice to return.
|
// Turn the map into a slice to return.
|
||||||
*/
|
// */
|
||||||
_interfaces := make([dynamic]Network_Interface, 0, allocator)
|
// _interfaces := make([dynamic]Network_Interface, 0, allocator)
|
||||||
for _, iface in ifaces {
|
// for _, iface in ifaces {
|
||||||
append(&_interfaces, iface^)
|
// append(&_interfaces, iface^)
|
||||||
free(iface)
|
// free(iface)
|
||||||
}
|
// }
|
||||||
return _interfaces[:], {}
|
// return _interfaces[:], {}
|
||||||
|
return nil, {}
|
||||||
}
|
}
|
||||||
@@ -18,7 +18,7 @@ package net
|
|||||||
Jeroen van Rijn: Cross platform unification, code style, documentation
|
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 {
|
switch s in socket {
|
||||||
case TCP_Socket: return Socket(s)
|
case TCP_Socket: return Socket(s)
|
||||||
case UDP_Socket: return Socket(s)
|
case UDP_Socket: return Socket(s)
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import "core:os"
|
|||||||
import "core:time"
|
import "core:time"
|
||||||
|
|
||||||
Socket_Option :: enum c.int {
|
Socket_Option :: enum c.int {
|
||||||
|
Broadcast = c.int(os.SO_BROADCAST),
|
||||||
Reuse_Address = c.int(os.SO_REUSEADDR),
|
Reuse_Address = c.int(os.SO_REUSEADDR),
|
||||||
Keep_Alive = c.int(os.SO_KEEPALIVE),
|
Keep_Alive = c.int(os.SO_KEEPALIVE),
|
||||||
Out_Of_Bounds_Data_Inline = c.int(os.SO_OOBINLINE),
|
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 {
|
switch option {
|
||||||
case
|
case
|
||||||
|
.Broadcast,
|
||||||
.Reuse_Address,
|
.Reuse_Address,
|
||||||
.Keep_Alive,
|
.Keep_Alive,
|
||||||
.Out_Of_Bounds_Data_Inline,
|
.Out_Of_Bounds_Data_Inline,
|
||||||
@@ -369,3 +371,26 @@ _sockaddr_to_endpoint :: proc(native_addr: ^os.SOCKADDR_STORAGE_LH) -> (ep: Endp
|
|||||||
}
|
}
|
||||||
return
|
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
|
Tetralux: Initial implementation
|
||||||
Colin Davidson: Linux platform code, OSX platform code, Odin-native DNS resolver
|
Colin Davidson: Linux platform code, OSX platform code, Odin-native DNS resolver
|
||||||
Jeroen van Rijn: Cross platform unification, code style, documentation
|
Jeroen van Rijn: Cross platform unification, code style, documentation
|
||||||
|
flysand: Move dependency from core:os to core:sys/linux
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import "core:c"
|
import "core:c"
|
||||||
import "core:os"
|
|
||||||
import "core:time"
|
import "core:time"
|
||||||
|
import "core:sys/linux"
|
||||||
|
|
||||||
Socket_Option :: enum c.int {
|
Socket_Option :: enum c.int {
|
||||||
Reuse_Address = c.int(os.SO_REUSEADDR),
|
Reuse_Address = c.int(linux.Socket_Option.REUSEADDR),
|
||||||
Keep_Alive = c.int(os.SO_KEEPALIVE),
|
Keep_Alive = c.int(linux.Socket_Option.KEEPALIVE),
|
||||||
Out_Of_Bounds_Data_Inline = c.int(os.SO_OOBINLINE),
|
Out_Of_Bounds_Data_Inline = c.int(linux.Socket_Option.OOBINLINE),
|
||||||
TCP_Nodelay = c.int(os.TCP_NODELAY),
|
TCP_Nodelay = c.int(linux.Socket_TCP_Option.NODELAY),
|
||||||
Linger = c.int(os.SO_LINGER),
|
Linger = c.int(linux.Socket_Option.LINGER),
|
||||||
Receive_Buffer_Size = c.int(os.SO_RCVBUF),
|
Receive_Buffer_Size = c.int(linux.Socket_Option.RCVBUF),
|
||||||
Send_Buffer_Size = c.int(os.SO_SNDBUF),
|
Send_Buffer_Size = c.int(linux.Socket_Option.SNDBUF),
|
||||||
Receive_Timeout = c.int(os.SO_RCVTIMEO_NEW),
|
Receive_Timeout = c.int(linux.Socket_Option.RCVTIMEO_NEW),
|
||||||
Send_Timeout = c.int(os.SO_SNDTIMEO_NEW),
|
Send_Timeout = c.int(linux.Socket_Option.SNDTIMEO_NEW),
|
||||||
}
|
}
|
||||||
|
|
||||||
@(private)
|
// Wrappers and unwrappers for system-native types
|
||||||
_create_socket :: proc(family: Address_Family, protocol: Socket_Protocol) -> (socket: Any_Socket, err: Network_Error) {
|
|
||||||
c_type, c_protocol, c_family: int
|
|
||||||
|
|
||||||
|
@(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 {
|
switch family {
|
||||||
case .IP4: c_family = os.AF_INET
|
case .IP4: return .INET
|
||||||
case .IP6: c_family = os.AF_INET6
|
case .IP6: return .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:
|
case:
|
||||||
unreachable()
|
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)
|
@(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 {
|
if endpoint.port == 0 {
|
||||||
return 0, .Port_Required
|
return 0, .Port_Required
|
||||||
}
|
}
|
||||||
|
// Create new TCP socket
|
||||||
family := family_from_endpoint(endpoint)
|
os_sock: linux.Fd
|
||||||
sock := create_socket(family, .TCP) or_return
|
os_sock, errno = linux.socket(_unwrap_os_family(family_from_endpoint(endpoint)), .STREAM, {}, .TCP)
|
||||||
skt = sock.(TCP_Socket)
|
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
|
// 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
|
// bypass the cooldown period, and allow the next run of the program to
|
||||||
// use the same address immediately.
|
// use the same address immediately.
|
||||||
_ = set_option(skt, .Reuse_Address, true)
|
reuse_addr: b32 = true
|
||||||
|
_ = linux.setsockopt(os_sock, linux.SOL_SOCKET, linux.Socket_Option.REUSEADDR, &reuse_addr)
|
||||||
sockaddr := _endpoint_to_sockaddr(endpoint)
|
addr := _unwrap_os_addr(endpoint)
|
||||||
res := os.connect(os.Socket(skt), (^os.SOCKADDR)(&sockaddr), size_of(sockaddr))
|
errno = linux.connect(linux.Fd(tcp_sock), &addr)
|
||||||
if res != os.ERROR_NONE {
|
if errno != .NONE {
|
||||||
err = Dial_Error(res)
|
return cast(TCP_Socket) os_sock, Dial_Error(errno)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
// NOTE(tetra): Not vital to succeed; error ignored
|
||||||
if options.no_delay {
|
no_delay: b32 = cast(b32) options.no_delay
|
||||||
_ = _set_option(sock, .TCP_Nodelay, true) // NOTE(tetra): Not vital to succeed; error ignored
|
_ = linux.setsockopt(os_sock, linux.SOL_TCP, linux.Socket_TCP_Option.NODELAY, &no_delay)
|
||||||
}
|
return cast(TCP_Socket) os_sock, nil
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@(private)
|
@(private)
|
||||||
_bind :: proc(skt: Any_Socket, ep: Endpoint) -> (err: Network_Error) {
|
_bind :: proc(sock: Any_Socket, endpoint: Endpoint) -> (Network_Error) {
|
||||||
sockaddr := _endpoint_to_sockaddr(ep)
|
addr := _unwrap_os_addr(endpoint)
|
||||||
s := any_socket_to_socket(skt)
|
errno := linux.bind(_unwrap_os_socket(sock), &addr)
|
||||||
res := os.bind(os.Socket(s), (^os.SOCKADDR)(&sockaddr), size_of(sockaddr))
|
if errno != .NONE {
|
||||||
if res != os.ERROR_NONE {
|
return Bind_Error(errno)
|
||||||
err = Bind_Error(res)
|
|
||||||
}
|
}
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@(private)
|
@(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))
|
assert(backlog > 0 && i32(backlog) < max(i32))
|
||||||
|
// Figure out the address family and address of the endpoint
|
||||||
family := family_from_endpoint(interface_endpoint)
|
ep_family := _unwrap_os_family(family_from_endpoint(endpoint))
|
||||||
sock := create_socket(family, .TCP) or_return
|
ep_address := _unwrap_os_addr(endpoint)
|
||||||
skt = sock.(TCP_Socket)
|
// 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
|
// 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
|
// bypass the cooldown period, and allow the next run of the program to
|
||||||
// use the same address immediately.
|
// use the same address immediately.
|
||||||
//
|
//
|
||||||
// TODO(tetra, 2022-02-15): Confirm that this doesn't mean other processes can hijack the address!
|
// 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
|
do_reuse_addr: b32 = true
|
||||||
|
errno = linux.setsockopt(os_sock, linux.SOL_SOCKET, linux.Socket_Option.REUSEADDR, &do_reuse_addr)
|
||||||
bind(sock, interface_endpoint) or_return
|
if errno != .NONE {
|
||||||
|
return cast(TCP_Socket) os_sock, Listen_Error(errno)
|
||||||
res := os.listen(os.Socket(skt), backlog)
|
|
||||||
if res != os.ERROR_NONE {
|
|
||||||
err = Listen_Error(res)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
// Bind the socket to endpoint address
|
||||||
return
|
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)
|
@(private)
|
||||||
_accept_tcp :: proc(sock: TCP_Socket, options := default_tcp_options) -> (client: TCP_Socket, source: Endpoint, err: Network_Error) {
|
_accept_tcp :: proc(sock: TCP_Socket, options := default_tcp_options) -> (tcp_client: TCP_Socket, endpoint: Endpoint, err: Network_Error) {
|
||||||
sockaddr: os.SOCKADDR_STORAGE_LH
|
addr: linux.Sock_Addr_Any
|
||||||
sockaddrlen := c.int(size_of(sockaddr))
|
client_sock, errno := linux.accept(linux.Fd(sock), &addr)
|
||||||
|
if errno != .NONE {
|
||||||
client_sock, ok := os.accept(os.Socket(sock), cast(^os.SOCKADDR) &sockaddr, &sockaddrlen)
|
return {}, {}, Accept_Error(errno)
|
||||||
if ok != os.ERROR_NONE {
|
|
||||||
err = Accept_Error(ok)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
client = TCP_Socket(client_sock)
|
// NOTE(tetra): Not vital to succeed; error ignored
|
||||||
source = _sockaddr_storage_to_endpoint(&sockaddr)
|
val: b32 = cast(b32) options.no_delay
|
||||||
if options.no_delay {
|
_ = linux.setsockopt(client_sock, linux.SOL_TCP, linux.Socket_TCP_Option.NODELAY, &val)
|
||||||
_ = _set_option(client, .TCP_Nodelay, true) // NOTE(tetra): Not vital to succeed; error ignored
|
return TCP_Socket(client_sock), _wrap_os_addr(addr), nil
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@(private)
|
@(private)
|
||||||
_close :: proc(skt: Any_Socket) {
|
_close :: proc(sock: Any_Socket) {
|
||||||
s := any_socket_to_socket(skt)
|
linux.close(_unwrap_os_socket(sock))
|
||||||
os.close(os.Handle(os.Socket(s)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@(private)
|
@(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 {
|
if len(buf) <= 0 {
|
||||||
return
|
return 0, nil
|
||||||
}
|
}
|
||||||
res, ok := os.recv(os.Socket(skt), buf, 0)
|
bytes_read, errno := linux.recv(linux.Fd(tcp_sock), buf, {})
|
||||||
if ok != os.ERROR_NONE {
|
if errno != .NONE {
|
||||||
err = TCP_Recv_Error(ok)
|
return 0, TCP_Recv_Error(errno)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
return int(res), nil
|
return int(bytes_read), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@(private)
|
@(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 {
|
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,
|
// 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.
|
// 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.
|
// 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.
|
// 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)
|
from_addr: linux.Sock_Addr_Any
|
||||||
if ok != os.ERROR_NONE {
|
bytes_read, errno := linux.recvfrom(linux.Fd(udp_sock), buf, {.TRUNC}, &from_addr)
|
||||||
err = UDP_Recv_Error(ok)
|
if errno != .NONE {
|
||||||
return
|
return 0, {}, UDP_Recv_Error(errno)
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes_read = int(res)
|
|
||||||
remote_endpoint = _sockaddr_storage_to_endpoint(&from)
|
|
||||||
|
|
||||||
if bytes_read > len(buf) {
|
if bytes_read > len(buf) {
|
||||||
// NOTE(tetra): The buffer has been filled, with a partial message.
|
// NOTE(tetra): The buffer has been filled, with a partial message.
|
||||||
bytes_read = len(buf)
|
return len(buf), {}, .Buffer_Too_Small
|
||||||
err = .Buffer_Too_Small
|
|
||||||
}
|
}
|
||||||
|
return bytes_read, _wrap_os_addr(from_addr), nil
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@(private)
|
@(private)
|
||||||
_send_tcp :: proc(skt: TCP_Socket, buf: []byte) -> (bytes_written: int, err: Network_Error) {
|
_send_tcp :: proc(tcp_sock: TCP_Socket, buf: []byte) -> (int, Network_Error) {
|
||||||
for bytes_written < len(buf) {
|
total_written := 0
|
||||||
limit := min(int(max(i32)), len(buf) - bytes_written)
|
for total_written < len(buf) {
|
||||||
remaining := buf[bytes_written:][:limit]
|
limit := min(int(max(i32)), len(buf) - total_written)
|
||||||
res, ok := os.send(os.Socket(skt), remaining, 0)
|
remaining := buf[total_written:][:limit]
|
||||||
if ok != os.ERROR_NONE {
|
res, errno := linux.send(linux.Fd(tcp_sock), remaining, {})
|
||||||
err = TCP_Send_Error(ok)
|
if errno != .NONE {
|
||||||
return
|
return total_written, TCP_Send_Error(errno)
|
||||||
}
|
}
|
||||||
bytes_written += int(res)
|
total_written += int(res)
|
||||||
}
|
}
|
||||||
return
|
return total_written, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@(private)
|
@(private)
|
||||||
_send_udp :: proc(skt: UDP_Socket, buf: []byte, to: Endpoint) -> (bytes_written: int, err: Network_Error) {
|
_send_udp :: proc(udp_sock: UDP_Socket, buf: []byte, to: Endpoint) -> (int, Network_Error) {
|
||||||
toaddr := _endpoint_to_sockaddr(to)
|
to_addr := _unwrap_os_addr(to)
|
||||||
res, os_err := os.sendto(os.Socket(skt), buf, 0, cast(^os.SOCKADDR) &toaddr, size_of(toaddr))
|
bytes_written, errno := linux.sendto(linux.Fd(udp_sock), buf, {}, &to_addr)
|
||||||
if os_err != os.ERROR_NONE {
|
if errno != .NONE {
|
||||||
err = UDP_Send_Error(os_err)
|
return bytes_written, UDP_Send_Error(errno)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
bytes_written = int(res)
|
return int(bytes_written), nil
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@(private)
|
@(private)
|
||||||
_shutdown :: proc(skt: Any_Socket, manner: Shutdown_Manner) -> (err: Network_Error) {
|
_shutdown :: proc(sock: Any_Socket, manner: Shutdown_Manner) -> (err: Network_Error) {
|
||||||
s := any_socket_to_socket(skt)
|
os_sock := _unwrap_os_socket(sock)
|
||||||
res := os.shutdown(os.Socket(s), int(manner))
|
errno := linux.shutdown(os_sock, cast(linux.Shutdown_How) manner)
|
||||||
if res != os.ERROR_NONE {
|
if errno != .NONE {
|
||||||
return Shutdown_Error(res)
|
return Shutdown_Error(errno)
|
||||||
}
|
}
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(flysand): Figure out what we want to do with this on core:sys/ level.
|
||||||
@(private)
|
@(private)
|
||||||
_set_option :: proc(s: Any_Socket, option: Socket_Option, value: any, loc := #caller_location) -> Network_Error {
|
_set_option :: proc(sock: Any_Socket, option: Socket_Option, value: any, loc := #caller_location) -> Network_Error {
|
||||||
level := os.SOL_SOCKET if option != .TCP_Nodelay else os.IPPROTO_TCP
|
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;
|
// NOTE(tetra, 2022-02-15): On Linux, you cannot merely give a single byte for a bool;
|
||||||
// it _has_ to be a b32.
|
// 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
|
bool_value: b32
|
||||||
int_value: i32
|
int_value: i32
|
||||||
timeval_value: os.Timeval
|
timeval_value: linux.Time_Val
|
||||||
|
errno: linux.Errno
|
||||||
ptr: rawptr
|
|
||||||
len: os.socklen_t
|
|
||||||
|
|
||||||
switch option {
|
switch option {
|
||||||
case
|
case
|
||||||
.Reuse_Address,
|
.Reuse_Address,
|
||||||
@@ -258,7 +311,7 @@ _set_option :: proc(s: Any_Socket, option: Socket_Option, value: any, loc := #ca
|
|||||||
.Out_Of_Bounds_Data_Inline,
|
.Out_Of_Bounds_Data_Inline,
|
||||||
.TCP_Nodelay:
|
.TCP_Nodelay:
|
||||||
// TODO: verify whether these are options or not on Linux
|
// TODO: verify whether these are options or not on Linux
|
||||||
// .Broadcast,
|
// .Broadcast, <-- yes
|
||||||
// .Conditional_Accept,
|
// .Conditional_Accept,
|
||||||
// .Dont_Linger:
|
// .Dont_Linger:
|
||||||
switch x in value {
|
switch x in value {
|
||||||
@@ -274,8 +327,7 @@ _set_option :: proc(s: Any_Socket, option: Socket_Option, value: any, loc := #ca
|
|||||||
case:
|
case:
|
||||||
panic("set_option() value must be a boolean here", loc)
|
panic("set_option() value must be a boolean here", loc)
|
||||||
}
|
}
|
||||||
ptr = &bool_value
|
errno = linux.setsockopt(os_sock, level, int(option), &bool_value)
|
||||||
len = size_of(bool_value)
|
|
||||||
case
|
case
|
||||||
.Linger,
|
.Linger,
|
||||||
.Send_Timeout,
|
.Send_Timeout,
|
||||||
@@ -283,125 +335,49 @@ _set_option :: proc(s: Any_Socket, option: Socket_Option, value: any, loc := #ca
|
|||||||
t, ok := value.(time.Duration)
|
t, ok := value.(time.Duration)
|
||||||
if !ok do panic("set_option() value must be a time.Duration here", loc)
|
if !ok do panic("set_option() value must be a time.Duration here", loc)
|
||||||
|
|
||||||
micros := i64(time.duration_microseconds(t))
|
micros := cast(i64) (time.duration_microseconds(t))
|
||||||
timeval_value.microseconds = int(micros % 1e6)
|
timeval_value.microseconds = cast(int) (micros % 1e6)
|
||||||
timeval_value.seconds = (micros - i64(timeval_value.microseconds)) / 1e6
|
timeval_value.seconds = cast(int) ((micros - i64(timeval_value.microseconds)) / 1e6)
|
||||||
|
errno = linux.setsockopt(os_sock, level, int(option), &timeval_value)
|
||||||
ptr = &timeval_value
|
|
||||||
len = size_of(timeval_value)
|
|
||||||
case
|
case
|
||||||
.Receive_Buffer_Size,
|
.Receive_Buffer_Size,
|
||||||
.Send_Buffer_Size:
|
.Send_Buffer_Size:
|
||||||
// TODO: check for out of range values and return .Value_Out_Of_Range?
|
// TODO: check for out of range values and return .Value_Out_Of_Range?
|
||||||
switch i in value {
|
switch i in value {
|
||||||
case i8, u8: i2 := i; int_value = os.socklen_t((^u8)(&i2)^)
|
case i8, u8: i2 := i; int_value = i32((^u8)(&i2)^)
|
||||||
case i16, u16: i2 := i; int_value = os.socklen_t((^u16)(&i2)^)
|
case i16, u16: i2 := i; int_value = i32((^u16)(&i2)^)
|
||||||
case i32, u32: i2 := i; int_value = os.socklen_t((^u32)(&i2)^)
|
case i32, u32: i2 := i; int_value = i32((^u32)(&i2)^)
|
||||||
case i64, u64: i2 := i; int_value = os.socklen_t((^u64)(&i2)^)
|
case i64, u64: i2 := i; int_value = i32((^u64)(&i2)^)
|
||||||
case i128, u128: i2 := i; int_value = os.socklen_t((^u128)(&i2)^)
|
case i128, u128: i2 := i; int_value = i32((^u128)(&i2)^)
|
||||||
case int, uint: i2 := i; int_value = os.socklen_t((^uint)(&i2)^)
|
case int, uint: i2 := i; int_value = i32((^uint)(&i2)^)
|
||||||
case:
|
case:
|
||||||
panic("set_option() value must be an integer here", loc)
|
panic("set_option() value must be an integer here", loc)
|
||||||
}
|
}
|
||||||
ptr = &int_value
|
errno = linux.setsockopt(os_sock, level, int(option), &int_value)
|
||||||
len = size_of(int_value)
|
|
||||||
}
|
}
|
||||||
|
if errno != .NONE {
|
||||||
skt := any_socket_to_socket(s)
|
return Socket_Option_Error(errno)
|
||||||
res := os.setsockopt(os.Socket(skt), int(level), int(option), ptr, len)
|
|
||||||
if res != os.ERROR_NONE {
|
|
||||||
return Socket_Option_Error(res)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@(private)
|
@(private)
|
||||||
_set_blocking :: proc(socket: Any_Socket, should_block: bool) -> (err: Network_Error) {
|
_set_blocking :: proc(sock: Any_Socket, should_block: bool) -> (err: Network_Error) {
|
||||||
socket := any_socket_to_socket(socket)
|
errno: linux.Errno
|
||||||
|
flags: linux.Open_Flags
|
||||||
flags, getfl_err := os.fcntl(int(socket), os.F_GETFL, 0)
|
os_sock := _unwrap_os_socket(sock)
|
||||||
if getfl_err != os.ERROR_NONE {
|
flags, errno = linux.fcntl(os_sock, linux.F_GETFL)
|
||||||
return Set_Blocking_Error(getfl_err)
|
if errno != .NONE {
|
||||||
|
return Set_Blocking_Error(errno)
|
||||||
}
|
}
|
||||||
|
|
||||||
if should_block {
|
if should_block {
|
||||||
flags &= ~int(os.O_NONBLOCK)
|
flags &= ~{.NONBLOCK}
|
||||||
} else {
|
} else {
|
||||||
flags |= int(os.O_NONBLOCK)
|
flags |= {.NONBLOCK}
|
||||||
}
|
}
|
||||||
|
errno = linux.fcntl(os_sock, linux.F_SETFL, flags)
|
||||||
_, setfl_err := os.fcntl(int(socket), os.F_SETFL, flags)
|
if errno != .NONE {
|
||||||
if setfl_err != os.ERROR_NONE {
|
return Set_Blocking_Error(errno)
|
||||||
return Set_Blocking_Error(setfl_err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
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,
|
case .Ident, .Context, .Typeid, .Break, .Continue, .Fallthrough, .Return,
|
||||||
.Integer, .Float, .Imag, .Rune, .String, .Undef,
|
.Integer, .Float, .Imag, .Rune, .String, .Undef,
|
||||||
.Question, .Pointer, .Close_Paren, .Close_Bracket, .Close_Brace,
|
.Question, .Pointer, .Close_Paren, .Close_Bracket, .Close_Brace,
|
||||||
.Increment, .Decrement, .Or_Return:
|
.Increment, .Decrement, .Or_Return, .Or_Break, .Or_Continue:
|
||||||
/*fallthrough*/
|
/*fallthrough*/
|
||||||
t.insert_semicolon = true
|
t.insert_semicolon = true
|
||||||
case:
|
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 {
|
if len(buf) < min {
|
||||||
return 0, -1
|
return 0, -1
|
||||||
}
|
}
|
||||||
for n < min && err == 0 {
|
nn := max(int)
|
||||||
nn: int
|
for nn > 0 && n < min && err == 0 {
|
||||||
nn, err = read(fd, buf[n:])
|
nn, err = read(fd, buf[n:])
|
||||||
n += nn
|
n += nn
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -354,6 +354,30 @@ in6_addr :: struct #packed {
|
|||||||
s6_addr: [16]u8,
|
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 {
|
Timeval :: struct {
|
||||||
seconds: i64,
|
seconds: i64,
|
||||||
microseconds: int,
|
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="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="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) -> ! ---
|
@(link_name="exit") _unix_exit :: proc(status: c.int) -> ! ---
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
-1
@@ -8,7 +8,18 @@ import "core:strings"
|
|||||||
import "core:c"
|
import "core:c"
|
||||||
import "core:strconv"
|
import "core:strconv"
|
||||||
import "core:intrinsics"
|
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
|
Handle :: distinct i32
|
||||||
Pid :: distinct i32
|
Pid :: distinct i32
|
||||||
|
|||||||
@@ -159,9 +159,9 @@ join :: proc(elems: []string, allocator := context.allocator) -> string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// ext returns the file name extension used by "path"
|
// 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 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
|
// The path is empty if there is no dot character.
|
||||||
ext :: proc(path: string, new := false, allocator := context.allocator) -> string {
|
ext :: proc(path: string, new := false, allocator := context.allocator) -> string {
|
||||||
for i := len(path)-1; i >= 0 && !is_separator(path[i]); i -= 1 {
|
for i := len(path)-1; i >= 0 && !is_separator(path[i]); i -= 1 {
|
||||||
if path[i] == '.' {
|
if path[i] == '.' {
|
||||||
|
|||||||
@@ -664,8 +664,10 @@ default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code
|
|||||||
when ODIN_OS == .Freestanding {
|
when ODIN_OS == .Freestanding {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
} else {
|
} else {
|
||||||
print_caller_location(loc)
|
when !ODIN_DISABLE_ASSERT {
|
||||||
print_string(" ")
|
print_caller_location(loc)
|
||||||
|
print_string(" ")
|
||||||
|
}
|
||||||
print_string(prefix)
|
print_string(prefix)
|
||||||
if len(message) > 0 {
|
if len(message) > 0 {
|
||||||
print_string(": ")
|
print_string(": ")
|
||||||
|
|||||||
@@ -817,7 +817,6 @@ assert :: proc(condition: bool, message := "", loc := #caller_location) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@builtin
|
@builtin
|
||||||
@(disabled=ODIN_DISABLE_ASSERT)
|
|
||||||
panic :: proc(message: string, loc := #caller_location) -> ! {
|
panic :: proc(message: string, loc := #caller_location) -> ! {
|
||||||
p := context.assertion_failure_proc
|
p := context.assertion_failure_proc
|
||||||
if p == nil {
|
if p == nil {
|
||||||
@@ -827,7 +826,6 @@ panic :: proc(message: string, loc := #caller_location) -> ! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@builtin
|
@builtin
|
||||||
@(disabled=ODIN_DISABLE_ASSERT)
|
|
||||||
unimplemented :: proc(message := "", loc := #caller_location) -> ! {
|
unimplemented :: proc(message := "", loc := #caller_location) -> ! {
|
||||||
p := context.assertion_failure_proc
|
p := context.assertion_failure_proc
|
||||||
if p == nil {
|
if p == nil {
|
||||||
|
|||||||
@@ -413,3 +413,16 @@ delete_soa :: proc{
|
|||||||
delete_soa_slice,
|
delete_soa_slice,
|
||||||
delete_soa_dynamic_array,
|
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)
|
@(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 {
|
if m.allocator.procedure == nil {
|
||||||
m.allocator = context.allocator
|
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.
|
// map needs to be within the max load factor.
|
||||||
log2_capacity := map_log2_cap(m^)
|
log2_capacity := map_log2_cap(m^)
|
||||||
if uintptr(m.len) >= map_load_factor(log2_capacity - 1) {
|
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
|
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
|
map_free_dynamic(m^, info, loc) or_return
|
||||||
m.data = shrunk.data
|
m.data = shrunk.data
|
||||||
return nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
|
|||||||
@@ -21,13 +21,37 @@ when ODIN_BUILD_MODE == .Dynamic {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
} else when !ODIN_TEST && !ODIN_NO_ENTRY_POINT {
|
} else when !ODIN_TEST && !ODIN_NO_ENTRY_POINT {
|
||||||
@(link_name="main", linkage="strong", require)
|
when ODIN_NO_CRT {
|
||||||
main :: proc "c" (argc: i32, argv: [^]cstring) -> i32 {
|
// NOTE(flysand): We need to start from assembly because we need
|
||||||
args__ = argv[:argc]
|
// to retrieve argc and argv from the stack
|
||||||
context = default_context()
|
when ODIN_ARCH == .amd64 {
|
||||||
#force_no_inline _startup_runtime()
|
@require foreign import entry "entry_unix_no_crt_amd64.asm"
|
||||||
intrinsics.__entry_point()
|
} else when ODIN_ARCH == .i386 {
|
||||||
#force_no_inline _cleanup_runtime()
|
@require foreign import entry "entry_unix_no_crt_i386.asm"
|
||||||
return 0
|
}
|
||||||
|
@(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 __chkstk
|
||||||
global _tls_index
|
global _tls_index
|
||||||
global _fltused
|
global _fltused
|
||||||
@@ -5,9 +7,73 @@ global _fltused
|
|||||||
section .data
|
section .data
|
||||||
_tls_index: dd 0
|
_tls_index: dd 0
|
||||||
_fltused: dd 0x9875
|
_fltused: dd 0x9875
|
||||||
|
|
||||||
|
|
||||||
section .text
|
section .text
|
||||||
__chkstk: ; proc "c" (rawptr)
|
; NOTE(flysand): The function call to __chkstk is called
|
||||||
; TODO implement correctly
|
; 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
|
ret
|
||||||
@@ -126,19 +126,19 @@ _mm_max_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
|
|||||||
|
|
||||||
@(require_results, enable_target_feature="sse")
|
@(require_results, enable_target_feature="sse")
|
||||||
_mm_and_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
|
_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")
|
@(require_results, enable_target_feature="sse")
|
||||||
_mm_andnot_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
|
_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")
|
@(require_results, enable_target_feature="sse")
|
||||||
_mm_or_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
|
_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")
|
@(require_results, enable_target_feature="sse")
|
||||||
_mm_xor_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
|
_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")
|
@(require_results, enable_target_feature="sse2")
|
||||||
_mm_and_si128 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
|
_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")
|
@(require_results, enable_target_feature="sse2")
|
||||||
_mm_andnot_si128 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
|
_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")
|
@(require_results, enable_target_feature="sse2")
|
||||||
_mm_or_si128 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
|
_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")
|
@(require_results, enable_target_feature="sse2")
|
||||||
_mm_xor_si128 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
|
_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")
|
@(require_results, enable_target_feature="sse2")
|
||||||
_mm_cmpeq_epi8 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
|
_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
|
// copies a slice into a new slice
|
||||||
@(require_results)
|
@(require_results)
|
||||||
clone :: proc(a: $T/[]$E, allocator := context.allocator) -> ([]E, runtime.Allocator_Error) #optional_allocator_error {
|
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)
|
d, err := make([]E, len(a), allocator, loc)
|
||||||
copy(d[:], a)
|
copy(d[:], a)
|
||||||
return d, err
|
return d, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// copies slice into a new dynamic array
|
// 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 {
|
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)
|
d, err := make([dynamic]E, len(a), allocator, loc)
|
||||||
copy(d[:], a)
|
copy(d[:], a)
|
||||||
return d, err
|
return d, err
|
||||||
}
|
}
|
||||||
|
|||||||
+32
-67
@@ -2,95 +2,60 @@
|
|||||||
//+build linux
|
//+build linux
|
||||||
package sync
|
package sync
|
||||||
|
|
||||||
import "core:c"
|
|
||||||
import "core:time"
|
import "core:time"
|
||||||
import "core:intrinsics"
|
import "core:sys/linux"
|
||||||
import "core:sys/unix"
|
|
||||||
|
|
||||||
FUTEX_WAIT :: 0
|
_futex_wait :: proc "contextless" (futex: ^Futex, expected: u32) -> bool {
|
||||||
FUTEX_WAKE :: 1
|
errno := linux.futex(cast(^linux.Futex) futex, linux.FUTEX_WAIT, {.PRIVATE}, expected)
|
||||||
FUTEX_PRIVATE_FLAG :: 128
|
if errno == .ETIMEDOUT {
|
||||||
|
|
||||||
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:
|
|
||||||
return false
|
return false
|
||||||
case EFAULT:
|
}
|
||||||
fallthrough
|
#partial switch errno {
|
||||||
|
case .NONE, .EINTR, .EAGAIN:
|
||||||
|
return true
|
||||||
case:
|
case:
|
||||||
|
// TODO(flysand): More descriptive panic messages based on the vlaue of `errno`
|
||||||
_panic("futex_wait failure")
|
_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 {
|
if duration <= 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
errno := linux.futex(cast(^linux.Futex) futex, linux.FUTEX_WAIT, {.PRIVATE}, expected, &linux.Time_Spec{
|
||||||
timespec_t :: struct {
|
time_sec = cast(uint)(duration/1e9),
|
||||||
tv_sec: c.long,
|
time_nsec = cast(uint)(duration%1e9),
|
||||||
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),
|
|
||||||
})
|
})
|
||||||
switch err {
|
if errno == .ETIMEDOUT {
|
||||||
case ESUCCESS, EINTR, EAGAIN, EINVAL:
|
|
||||||
// okay
|
|
||||||
case ETIMEDOUT:
|
|
||||||
return false
|
return false
|
||||||
case EFAULT:
|
}
|
||||||
fallthrough
|
#partial switch errno {
|
||||||
|
case .NONE, .EINTR, .EAGAIN:
|
||||||
|
return true
|
||||||
case:
|
case:
|
||||||
_panic("futex_wait_with_timeout failure")
|
_panic("futex_wait_with_timeout failure")
|
||||||
}
|
}
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_futex_signal :: proc "contextless" (futex: ^Futex) {
|
||||||
_futex_signal :: proc "contextless" (f: ^Futex) {
|
_, errno := linux.futex(cast(^linux.Futex) futex, linux.FUTEX_WAKE, {.PRIVATE}, 1)
|
||||||
err := internal_futex(f, FUTEX_WAKE_PRIVATE | FUTEX_WAKE, 1, nil)
|
#partial switch errno {
|
||||||
switch err {
|
case .NONE:
|
||||||
case ESUCCESS, EINVAL, EFAULT:
|
return
|
||||||
// okay
|
|
||||||
case:
|
case:
|
||||||
_panic("futex_wake_single failure")
|
_panic("futex_wake_single failure")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_futex_broadcast :: proc "contextless" (f: ^Futex) {
|
|
||||||
err := internal_futex(f, FUTEX_WAKE_PRIVATE | FUTEX_WAKE, u32(max(i32)), nil)
|
_futex_broadcast :: proc "contextless" (futex: ^Futex) {
|
||||||
switch err {
|
// NOTE(flysand): This code was kinda funny and I don't want to remove it, but here I will
|
||||||
case ESUCCESS, EINVAL, EFAULT:
|
// record history of what has been in here before
|
||||||
// okay
|
// 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:
|
case:
|
||||||
_panic("_futex_wake_all failure")
|
_panic("_futex_wake_all failure")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
//+private
|
//+private
|
||||||
package sync
|
package sync
|
||||||
|
|
||||||
import "core:sys/unix"
|
import "core:sys/linux"
|
||||||
|
|
||||||
_current_thread_id :: proc "contextless" () -> int {
|
_current_thread_id :: proc "contextless" () -> int {
|
||||||
return unix.sys_gettid()
|
return cast(int) linux.gettid()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +1,34 @@
|
|||||||
// +build linux
|
// +build linux
|
||||||
package sysinfo
|
package sysinfo
|
||||||
|
|
||||||
import "core:c"
|
|
||||||
import sys "core:sys/unix"
|
|
||||||
import "core:intrinsics"
|
import "core:intrinsics"
|
||||||
import "core:runtime"
|
import "core:runtime"
|
||||||
import "core:os"
|
|
||||||
import "core:strings"
|
import "core:strings"
|
||||||
import "core:strconv"
|
import "core:strconv"
|
||||||
|
|
||||||
|
import "core:sys/linux"
|
||||||
|
|
||||||
@(private)
|
@(private)
|
||||||
version_string_buf: [1024]u8
|
version_string_buf: [1024]u8
|
||||||
|
|
||||||
@(init, private)
|
@(init, private)
|
||||||
init_os_version :: proc () {
|
init_os_version :: proc () {
|
||||||
os_version.platform = .Linux
|
os_version.platform = .Linux
|
||||||
|
|
||||||
// Try to parse `/etc/os-release` for `PRETTY_NAME="Ubuntu 20.04.3 LTS`
|
// 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)
|
fd, errno := linux.open("/etc/os-release", {.RDONLY}, {})
|
||||||
if err != 0 {
|
assert(errno == .NONE, "Failed to read /etc/os-release")
|
||||||
return
|
defer {
|
||||||
|
errno := linux.close(fd)
|
||||||
|
assert(errno == .NONE, "Failed to close the file descriptor")
|
||||||
}
|
}
|
||||||
defer os.close(fd)
|
|
||||||
|
|
||||||
os_release_buf: [2048]u8
|
os_release_buf: [2048]u8
|
||||||
n, read_err := os.read(fd, os_release_buf[:])
|
n, read_errno := linux.read(fd, os_release_buf[:])
|
||||||
if read_err != 0 {
|
assert(read_errno == .NONE, "Failed to read data from /etc/os-release")
|
||||||
return
|
|
||||||
}
|
|
||||||
release := string(os_release_buf[:n])
|
release := string(os_release_buf[:n])
|
||||||
|
// Search the line in the file until we find "PRETTY_NAME="
|
||||||
NEEDLE :: "PRETTY_NAME=\""
|
NEEDLE :: "PRETTY_NAME=\""
|
||||||
pretty_start := strings.index(release, NEEDLE)
|
pretty_start := strings.index(release, NEEDLE)
|
||||||
|
|
||||||
b := strings.builder_from_bytes(version_string_buf[:])
|
b := strings.builder_from_bytes(version_string_buf[:])
|
||||||
|
|
||||||
if pretty_start > 0 {
|
if pretty_start > 0 {
|
||||||
for r, i in release[pretty_start + len(NEEDLE):] {
|
for r, i in release[pretty_start + len(NEEDLE):] {
|
||||||
if r == '"' {
|
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
|
// Grab kernel info using `uname()` syscall, https://linux.die.net/man/2/uname
|
||||||
if intrinsics.syscall(sys.SYS_uname, uintptr(&uts)) != 0 {
|
uts: linux.UTS_Name
|
||||||
return
|
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, ", ")
|
||||||
strings.write_string(&b, string(cstring(&uts.sys_name[0])))
|
strings.write_string(&b, string(cstring(&uts.sysname[0])))
|
||||||
strings.write_rune(&b, ' ')
|
strings.write_rune(&b, ' ')
|
||||||
|
|
||||||
l := strings.builder_len(b)
|
l := strings.builder_len(b)
|
||||||
strings.write_string(&b, string(cstring(&uts.release[0])))
|
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`
|
// 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)
|
version_bits := strings.split_n(strings.to_string(b)[l:], "-", 2, context.temp_allocator)
|
||||||
if len(version_bits) > 1 {
|
if len(version_bits) > 1 {
|
||||||
os_version.version = version_bits[1]
|
os_version.version = version_bits[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse major, minor, patch from release info
|
// Parse major, minor, patch from release info
|
||||||
triplet := strings.split(version_bits[0], ".", context.temp_allocator)
|
triplet := strings.split(version_bits[0], ".", context.temp_allocator)
|
||||||
if len(triplet) == 3 {
|
if len(triplet) == 3 {
|
||||||
major, major_ok := strconv.parse_int(triplet[0])
|
major, major_ok := strconv.parse_int(triplet[0])
|
||||||
minor, minor_ok := strconv.parse_int(triplet[1])
|
minor, minor_ok := strconv.parse_int(triplet[1])
|
||||||
patch, patch_ok := strconv.parse_int(triplet[2])
|
patch, patch_ok := strconv.parse_int(triplet[2])
|
||||||
|
|
||||||
if major_ok && minor_ok && patch_ok {
|
if major_ok && minor_ok && patch_ok {
|
||||||
os_version.major = major
|
os_version.major = major
|
||||||
os_version.minor = minor
|
os_version.minor = minor
|
||||||
os_version.patch = patch
|
os_version.patch = patch
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finish the string
|
// Finish the string
|
||||||
os_version.as_string = strings.to_string(b)
|
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)
|
||||||
init_ram :: proc() {
|
init_ram :: proc() {
|
||||||
// Retrieve RAM info using `sysinfo`
|
// Retrieve RAM info using `sysinfo`
|
||||||
si, ok := get_sysinfo()
|
sys_info: linux.Sys_Info
|
||||||
if !ok {
|
errno := linux.sysinfo(&sys_info)
|
||||||
return
|
assert(errno == .NONE, "Good luck to whoever's debugging this, something's seriously cucked up!")
|
||||||
}
|
|
||||||
|
|
||||||
ram = RAM{
|
ram = RAM{
|
||||||
total_ram = int(si.totalram) * int(si.mem_unit),
|
total_ram = int(sys_info.totalram) * int(sys_info.mem_unit),
|
||||||
free_ram = int(si.freeram) * int(si.mem_unit),
|
free_ram = int(sys_info.freeram) * int(sys_info.mem_unit),
|
||||||
total_swap = int(si.totalswap) * int(si.mem_unit),
|
total_swap = int(sys_info.totalswap) * int(sys_info.mem_unit),
|
||||||
free_swap = int(si.freeswap) * int(si.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 {
|
foreign odin_env {
|
||||||
time_now :: proc "contextless" () -> i64 ---
|
time_now :: proc "contextless" () -> i64 ---
|
||||||
}
|
}
|
||||||
return Time{time_now()}
|
return Time{time_now()*1e6}
|
||||||
}
|
}
|
||||||
|
|
||||||
_sleep :: proc "contextless" (d: Duration) {
|
_sleep :: proc "contextless" (d: Duration) {
|
||||||
@@ -26,7 +26,7 @@ _tick_now :: proc "contextless" () -> Tick {
|
|||||||
foreign odin_env {
|
foreign odin_env {
|
||||||
tick_now :: proc "contextless" () -> i64 ---
|
tick_now :: proc "contextless" () -> i64 ---
|
||||||
}
|
}
|
||||||
return Tick{tick_now()}
|
return Tick{tick_now()*1e6}
|
||||||
}
|
}
|
||||||
|
|
||||||
_yield :: proc "contextless" () {
|
_yield :: proc "contextless" () {
|
||||||
|
|||||||
+14
-16
@@ -2,34 +2,32 @@
|
|||||||
//+build linux
|
//+build linux
|
||||||
package time
|
package time
|
||||||
|
|
||||||
import "core:intrinsics"
|
import linux "core:sys/linux"
|
||||||
import "core:sys/unix"
|
|
||||||
|
|
||||||
_get_tsc_frequency :: proc "contextless" () -> (u64, bool) {
|
_get_tsc_frequency :: proc "contextless" () -> (u64, bool) {
|
||||||
perf_attr := unix.Perf_Event_Attr{}
|
// Get the file descriptor for the perf mapping
|
||||||
perf_attr.type = u32(unix.Perf_Type_Id.Hardware)
|
perf_attr := linux.Perf_Event_Attr{}
|
||||||
perf_attr.config = u64(unix.Perf_Hardware_Id.Instructions)
|
|
||||||
perf_attr.size = size_of(perf_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}
|
perf_attr.flags = {.Disabled, .Exclude_Kernel, .Exclude_HV}
|
||||||
fd := unix.sys_perf_event_open(&perf_attr, 0, -1, -1, 0)
|
fd, perf_errno := linux.perf_event_open(&perf_attr, linux.Pid(0), -1, linux.Fd(-1), {})
|
||||||
if fd == -1 {
|
if perf_errno != nil {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
defer unix.sys_close(fd)
|
defer linux.close(fd)
|
||||||
|
// Map it into the memory
|
||||||
page_size : uint = 4096
|
page_size : uint = 4096
|
||||||
ret := unix.sys_mmap(nil, page_size, unix.PROT_READ, unix.MAP_SHARED, fd, 0)
|
addr, mmap_errno := linux.mmap(0, page_size, {.READ}, {.SHARED}, fd)
|
||||||
if ret < 0 && ret > -4096 {
|
if mmap_errno != nil {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
addr := rawptr(uintptr(ret))
|
defer linux.munmap(addr, page_size)
|
||||||
defer unix.sys_munmap(addr, page_size)
|
// Get the frequency from the mapped page
|
||||||
|
event_page := cast(^linux.Perf_Event_Mmap_Page) addr
|
||||||
event_page := (^unix.Perf_Event_mmap_Page)(addr)
|
|
||||||
if .User_Time not_in event_page.cap.flags {
|
if .User_Time not_in event_page.cap.flags {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
|
|
||||||
frequency := u64((u128(1_000_000_000) << u128(event_page.time_shift)) / u128(event_page.time_mult))
|
frequency := u64((u128(1_000_000_000) << u128(event_page.time_shift)) / u128(event_page.time_mult))
|
||||||
return frequency, true
|
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 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
|
// NOTE(bill): only one can be checked at a time
|
||||||
import lua_5_4 "vendor:lua/5.4"
|
import lua_5_4 "vendor:lua/5.4"
|
||||||
|
|
||||||
@@ -91,11 +86,6 @@ _ :: TTF
|
|||||||
|
|
||||||
_ :: vk
|
_ :: vk
|
||||||
|
|
||||||
_ :: NS
|
|
||||||
_ :: MTL
|
|
||||||
_ :: MTK
|
|
||||||
_ :: CA
|
|
||||||
|
|
||||||
_ :: lua_5_4
|
_ :: lua_5_4
|
||||||
|
|
||||||
_ :: nvg
|
_ :: 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);
|
bc->optimization_level = gb_clamp(bc->optimization_level, -1, 3);
|
||||||
|
|
||||||
// ENFORCE DYNAMIC MAP CALLS
|
if (bc->metrics.os != TargetOs_windows) {
|
||||||
bc->dynamic_map_calls = true;
|
// ENFORCE DYNAMIC MAP CALLS
|
||||||
|
bc->dynamic_map_calls = true;
|
||||||
|
}
|
||||||
|
|
||||||
bc->ODIN_VALGRIND_SUPPORT = false;
|
bc->ODIN_VALGRIND_SUPPORT = false;
|
||||||
if (build_context.metrics.os != TargetOs_windows) {
|
if (build_context.metrics.os != TargetOs_windows) {
|
||||||
|
|||||||
@@ -5170,7 +5170,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
|
|||||||
|
|
||||||
Operand op = {};
|
Operand op = {};
|
||||||
check_expr(c, &op, ce->args[1]);
|
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");
|
error(op.expr, "Expected a constant integer for the index of procedure parameter value");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -5229,7 +5229,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
|
|||||||
|
|
||||||
Operand op = {};
|
Operand op = {};
|
||||||
check_expr(c, &op, ce->args[1]);
|
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");
|
error(op.expr, "Expected a constant integer for the index of procedure parameter value");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -5307,7 +5307,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
|
|||||||
} else {
|
} else {
|
||||||
Operand op = {};
|
Operand op = {};
|
||||||
check_expr(c, &op, ce->args[1]);
|
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");
|
error(op.expr, "Expected a constant integer for the index of record parameter value");
|
||||||
return false;
|
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) {
|
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);
|
Type *bt = base_type(index);
|
||||||
GB_ASSERT(bt->kind == Type_Enum);
|
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;
|
bool is_sparse = false;
|
||||||
if (at->tag != nullptr) {
|
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 (has_asm_extension(fullpath)) {
|
||||||
if (build_context.metrics.arch != TargetArch_amd64 ||
|
if (build_context.metrics.arch != TargetArch_amd64) {
|
||||||
build_context.metrics.os != TargetOs_windows) {
|
|
||||||
error(decl, "Assembly files are not yet supported on this platform: %.*s_%.*s",
|
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]));
|
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) {
|
gb_internal void check_unique_package_names(Checker *c) {
|
||||||
|
ERROR_BLOCK();
|
||||||
|
|
||||||
StringMap<AstPackage *> pkgs = {}; // Key: package name
|
StringMap<AstPackage *> pkgs = {}; // Key: package name
|
||||||
string_map_init(&pkgs, 2*c->info.packages.count);
|
string_map_init(&pkgs, 2*c->info.packages.count);
|
||||||
defer (string_map_destroy(&pkgs));
|
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)) {
|
if (!string_set_update(&asm_files, lib)) {
|
||||||
String asm_file = asm_files.entries[i].value;
|
String asm_file = asm_files.entries[i].value;
|
||||||
String obj_file = concatenate_strings(permanent_allocator(), asm_file, str_lit(".obj"));
|
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",
|
result = system_exec_command_line_app("nasm",
|
||||||
"\"%.*s\\bin\\nasm\\windows\\nasm.exe\" \"%.*s\" "
|
"\"%.*s\\bin\\nasm\\windows\\nasm.exe\" \"%.*s\" "
|
||||||
"-f win64 "
|
"-f \"%.*s\" "
|
||||||
"-o \"%.*s\" "
|
"-o \"%.*s\" "
|
||||||
"%.*s "
|
"%.*s "
|
||||||
"",
|
"",
|
||||||
LIT(build_context.ODIN_ROOT), LIT(asm_file),
|
LIT(build_context.ODIN_ROOT), LIT(asm_file),
|
||||||
|
LIT(obj_format),
|
||||||
LIT(obj_file),
|
LIT(obj_file),
|
||||||
LIT(build_context.extra_assembler_flags)
|
LIT(build_context.extra_assembler_flags)
|
||||||
);
|
);
|
||||||
@@ -295,11 +301,15 @@ gb_internal i32 linker_stage(LinkerData *gen) {
|
|||||||
// files can be passed with -l:
|
// files can be passed with -l:
|
||||||
gbString lib_str = gb_string_make(heap_allocator(), "-L/");
|
gbString lib_str = gb_string_make(heap_allocator(), "-L/");
|
||||||
defer (gb_string_free(lib_str));
|
defer (gb_string_free(lib_str));
|
||||||
|
|
||||||
|
StringSet asm_files = {};
|
||||||
|
string_set_init(&asm_files, 64);
|
||||||
|
defer (string_set_destroy(&asm_files));
|
||||||
|
|
||||||
StringSet libs = {};
|
StringSet libs = {};
|
||||||
string_set_init(&libs, 64);
|
string_set_init(&libs, 64);
|
||||||
defer (string_set_destroy(&libs));
|
defer (string_set_destroy(&libs));
|
||||||
|
|
||||||
for (Entity *e : gen->foreign_libraries) {
|
for (Entity *e : gen->foreign_libraries) {
|
||||||
GB_ASSERT(e->kind == Entity_LibraryName);
|
GB_ASSERT(e->kind == Entity_LibraryName);
|
||||||
for (String lib : e->LibraryName.paths) {
|
for (String lib : e->LibraryName.paths) {
|
||||||
@@ -307,46 +317,83 @@ gb_internal i32 linker_stage(LinkerData *gen) {
|
|||||||
if (lib.len == 0) {
|
if (lib.len == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (string_set_update(&libs, lib)) {
|
if (has_asm_extension(lib)) {
|
||||||
continue;
|
if (string_set_update(&asm_files, lib)) {
|
||||||
}
|
continue; // already handled
|
||||||
|
|
||||||
// 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 {
|
String asm_file = lib;
|
||||||
// NOTE(vassvik): static libraries (.a files) in linux can be linked to directly using the full path,
|
String obj_file = concatenate_strings(permanent_allocator(), asm_file, str_lit(".o"));
|
||||||
// since those are statically linked to at link time. shared libraries (.so) has to be
|
String obj_format;
|
||||||
// available at runtime wherever the executable is run, so we make require those to be
|
#if defined(GB_ARCH_64_BIT)
|
||||||
// local to the executable (unless the system collection is used, in which case we search
|
if (is_osx) {
|
||||||
// the system library paths for the library file).
|
obj_format = str_lit("macho64");
|
||||||
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 {
|
} else {
|
||||||
// dynamic or static system lib, just link regularly searching system library paths
|
obj_format = str_lit("elf64");
|
||||||
lib_str = gb_string_append_fmt(lib_str, " -l%.*s ", LIT(lib));
|
}
|
||||||
|
#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);
|
LLVMSetLinkage(p->value, LLVMInternalLinkage);
|
||||||
lb_add_attribute_to_proc(m, p->value, "nounwind");
|
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");
|
lb_add_attribute_to_proc(m, p->value, "noinline");
|
||||||
// }
|
}
|
||||||
|
|
||||||
LLVMValueRef x = LLVMGetParam(p->value, 0);
|
LLVMValueRef x = LLVMGetParam(p->value, 0);
|
||||||
LLVMValueRef y = LLVMGetParam(p->value, 1);
|
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 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 key_ptr = {LLVMGetParam(p->value, 2), t_rawptr};
|
||||||
lbValue value_ptr = {LLVMGetParam(p->value, 3), t_rawptr};
|
lbValue value_ptr = {LLVMGetParam(p->value, 3), t_rawptr};
|
||||||
lbValue location_ptr = {LLVMGetParam(p->value, 4), t_source_code_location_ptr};
|
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));
|
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));
|
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, "nonnull");
|
||||||
lb_add_proc_attribute_at_index(p, 1+0, "noalias");
|
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, "noalias");
|
||||||
lb_add_proc_attribute_at_index(p, 1+4, "readonly");
|
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 = {};
|
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);
|
auto args = array_make<lbValue>(temporary_allocator(), 3);
|
||||||
args[0] = lb_emit_conv(p, map_ptr, t_rawptr);
|
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;
|
args[2] = key_ptr;
|
||||||
|
|
||||||
found_ptr = lb_emit_call(p, map_get_proc, args);
|
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 *found_block = lb_create_block(p, "found");
|
||||||
lbBlock *check_grow_block = lb_create_block(p, "check-grow");
|
lbBlock *check_grow_block = lb_create_block(p, "check-grow");
|
||||||
lbBlock *grow_fail_block = lb_create_block(p, "grow-fail");
|
lbBlock *grow_fail_block = lb_create_block(p, "grow-fail");
|
||||||
lbBlock *insert_block = lb_create_block(p, "insert");
|
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");
|
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);
|
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);
|
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);
|
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_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 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);
|
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);
|
lb_start_block(p, grow_fail_block);
|
||||||
LLVMBuildRet(p->builder, LLVMConstNull(lb_type(m, t_rawptr)));
|
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);
|
lb_start_block(p, rehash_block);
|
||||||
lbValue key = lb_emit_load(p, key_ptr);
|
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);
|
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);
|
auto args = array_make<lbValue>(temporary_allocator(), 5);
|
||||||
args[0] = lb_emit_conv(p, map_ptr, t_rawptr);
|
args[0] = lb_emit_conv(p, map_ptr, t_rawptr);
|
||||||
args[1] = map_info;
|
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[3] = lb_emit_conv(p, key_ptr, t_uintptr);
|
||||||
args[4] = lb_emit_conv(p, value_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)");
|
array_add(&passes, "function(annotation-remarks)");
|
||||||
break;
|
break;
|
||||||
case 1:
|
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;
|
break;
|
||||||
|
// default<O2>
|
||||||
|
// Passes removed: coro, openmp, sroa
|
||||||
case 2:
|
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;
|
break;
|
||||||
|
|
||||||
case 3:
|
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;
|
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]);
|
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);
|
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);
|
lb_add_entity(m, lb_global_type_info_data_entity, value);
|
||||||
|
|
||||||
if (LB_USE_GIANT_PACKED_STRUCT) {
|
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
|
{ // Type info member buffer
|
||||||
@@ -2602,17 +3014,37 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
|
|||||||
|
|
||||||
|
|
||||||
if (build_context.sanitizer_flags & SanitizerFlag_Address) {
|
if (build_context.sanitizer_flags & SanitizerFlag_Address) {
|
||||||
auto paths = array_make<String>(heap_allocator(), 0, 1);
|
|
||||||
if (build_context.metrics.os == TargetOs_windows) {
|
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"));
|
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);
|
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.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.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);
|
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/Object.h>
|
||||||
#include <llvm-c/BitWriter.h>
|
#include <llvm-c/BitWriter.h>
|
||||||
#include <llvm-c/DebugInfo.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/AggressiveInstCombine.h>
|
||||||
#include <llvm-c/Transforms/InstCombine.h>
|
#include <llvm-c/Transforms/InstCombine.h>
|
||||||
#include <llvm-c/Transforms/IPO.h>
|
#include <llvm-c/Transforms/IPO.h>
|
||||||
@@ -23,6 +26,7 @@
|
|||||||
#include <llvm-c/Transforms/Utils.h>
|
#include <llvm-c/Transforms/Utils.h>
|
||||||
#include <llvm-c/Transforms/Vectorize.h>
|
#include <llvm-c/Transforms/Vectorize.h>
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#if LLVM_VERSION_MAJOR < 11
|
#if LLVM_VERSION_MAJOR < 11
|
||||||
#error "LLVM Version 11 is the minimum required"
|
#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);
|
LLVMTypeKind kind = LLVMGetTypeKind(dst);
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case LLVMPointerTypeKind:
|
case LLVMPointerTypeKind:
|
||||||
|
if (LB_USE_NEW_PASS_SYSTEM) {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
return LLVMConstPointerCast(val, dst);
|
return LLVMConstPointerCast(val, dst);
|
||||||
case LLVMStructTypeKind:
|
case LLVMStructTypeKind:
|
||||||
// GB_PANIC("%s -> %s", LLVMPrintValueToString(val), LLVMPrintTypeToString(dst));
|
// 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;
|
args[1] = rhs;
|
||||||
|
|
||||||
switch (type_size_of(ft)) {
|
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 4: return lb_emit_runtime_call(p, "quo_complex64", args);
|
||||||
case 8: return lb_emit_runtime_call(p, "quo_complex128", args);
|
case 8: return lb_emit_runtime_call(p, "quo_complex128", args);
|
||||||
default: GB_PANIC("Unknown float type"); break;
|
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;
|
args[1] = rhs;
|
||||||
|
|
||||||
switch (8*type_size_of(ft)) {
|
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 32: return lb_emit_runtime_call(p, "mul_quaternion128", args);
|
||||||
case 64: return lb_emit_runtime_call(p, "mul_quaternion256", args);
|
case 64: return lb_emit_runtime_call(p, "mul_quaternion256", args);
|
||||||
default: GB_PANIC("Unknown float type"); break;
|
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;
|
args[1] = rhs;
|
||||||
|
|
||||||
switch (8*type_size_of(ft)) {
|
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 32: return lb_emit_runtime_call(p, "quo_quaternion128", args);
|
||||||
case 64: return lb_emit_runtime_call(p, "quo_quaternion256", args);
|
case 64: return lb_emit_runtime_call(p, "quo_quaternion256", args);
|
||||||
default: GB_PANIC("Unknown float type"); break;
|
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_internal void lb_emit_store(lbProcedure *p, lbValue ptr, lbValue value) {
|
||||||
GB_ASSERT(value.value != nullptr);
|
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)) {
|
if (LLVMIsNull(value.value)) {
|
||||||
LLVMTypeRef src_t = llvm_addr_type(p->module, ptr);
|
LLVMTypeRef src_t = llvm_addr_type(p->module, ptr);
|
||||||
if (is_type_proc(a)) {
|
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
|
// NOTE(bill): Explicit instructions are set here because some instructions could have side effects
|
||||||
switch (LLVMGetInstructionOpcode(curr_instr)) {
|
switch (LLVMGetInstructionOpcode(curr_instr)) {
|
||||||
// case LLVMAlloca:
|
// case LLVMAlloca:
|
||||||
|
case LLVMLoad:
|
||||||
|
if (LLVMGetVolatile(curr_instr)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*fallthrough*/
|
||||||
case LLVMFNeg:
|
case LLVMFNeg:
|
||||||
case LLVMAdd:
|
case LLVMAdd:
|
||||||
case LLVMFAdd:
|
case LLVMFAdd:
|
||||||
@@ -342,7 +346,6 @@ gb_internal void lb_run_remove_dead_instruction_pass(lbProcedure *p) {
|
|||||||
case LLVMAnd:
|
case LLVMAnd:
|
||||||
case LLVMOr:
|
case LLVMOr:
|
||||||
case LLVMXor:
|
case LLVMXor:
|
||||||
case LLVMLoad:
|
|
||||||
case LLVMGetElementPtr:
|
case LLVMGetElementPtr:
|
||||||
case LLVMTrunc:
|
case LLVMTrunc:
|
||||||
case LLVMZExt:
|
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, "");
|
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;
|
LLVMAttributeIndex param_offset = LLVMAttributeIndex_FirstArgIndex;
|
||||||
if (return_ptr.value != nullptr) {
|
if (return_ptr.value != nullptr) {
|
||||||
param_offset += 1;
|
param_offset += 1;
|
||||||
@@ -2766,7 +2769,7 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu
|
|||||||
{
|
{
|
||||||
GB_ASSERT(arg_count <= 7);
|
GB_ASSERT(arg_count <= 7);
|
||||||
|
|
||||||
char asm_string_default[] = "int $0x80";
|
char asm_string_default[] = "int $$0x80";
|
||||||
char *asm_string = asm_string_default;
|
char *asm_string = asm_string_default;
|
||||||
gbString constraints = gb_string_make(heap_allocator(), "={eax}");
|
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;
|
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) {
|
gb_internal LLVMTypeRef lb_setup_type_info_data_internal_type(lbModule *m, isize max_type_info_count) {
|
||||||
if (!LB_USE_GIANT_PACKED_STRUCT) {
|
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);
|
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;
|
CheckerInfo *info = m->info;
|
||||||
|
|
||||||
// Useful types
|
// 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));
|
defer (gb_free(heap_allocator(), entries_handled.data));
|
||||||
entries_handled[0] = true;
|
entries_handled[0] = true;
|
||||||
|
|
||||||
|
|
||||||
LLVMValueRef giant_struct = lb_global_type_info_data_ptr(m).value;
|
LLVMValueRef giant_struct = lb_global_type_info_data_ptr(m).value;
|
||||||
LLVMTypeRef giant_struct_type = LLVMGlobalGetValueType(giant_struct);
|
LLVMTypeRef giant_struct_type = LLVMGlobalGetValueType(giant_struct);
|
||||||
GB_ASSERT(LLVMGetTypeKind(giant_struct_type) == LLVMStructTypeKind);
|
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_usings);
|
||||||
type_info_allocate_values(lb_global_type_info_member_tags);
|
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) {
|
for_array(type_info_type_index, info->type_info_types) {
|
||||||
Type *t = info->type_info_types[type_info_type_index];
|
Type *t = info->type_info_types[type_info_type_index];
|
||||||
if (t == nullptr || t == t_invalid) {
|
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] = {
|
LLVMValueRef vals[4] = {
|
||||||
lb_const_string(m, t->Named.type_name->token.string).value,
|
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,
|
pkg_name,
|
||||||
loc.value
|
loc.value
|
||||||
};
|
};
|
||||||
@@ -541,10 +565,8 @@ gb_internal void lb_setup_type_info_data_giant_packed_struct(lbModule *m, i64 gl
|
|||||||
|
|
||||||
case Type_Pointer: {
|
case Type_Pointer: {
|
||||||
tag_type = t_type_info_pointer;
|
tag_type = t_type_info_pointer;
|
||||||
lbValue gep = lb_type_info(m, t->Pointer.elem);
|
|
||||||
|
|
||||||
LLVMValueRef vals[1] = {
|
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: {
|
case Type_MultiPointer: {
|
||||||
tag_type = t_type_info_multi_pointer;
|
tag_type = t_type_info_multi_pointer;
|
||||||
lbValue gep = lb_type_info(m, t->MultiPointer.elem);
|
|
||||||
|
|
||||||
LLVMValueRef vals[1] = {
|
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));
|
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: {
|
case Type_SoaPointer: {
|
||||||
tag_type = t_type_info_soa_pointer;
|
tag_type = t_type_info_soa_pointer;
|
||||||
lbValue gep = lb_type_info(m, t->SoaPointer.elem);
|
|
||||||
|
|
||||||
LLVMValueRef vals[1] = {
|
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));
|
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);
|
i64 ez = type_size_of(t->Array.elem);
|
||||||
|
|
||||||
LLVMValueRef vals[3] = {
|
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, ez).value,
|
||||||
lb_const_int(m, t_int, t->Array.count).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;
|
tag_type = t_type_info_enumerated_array;
|
||||||
|
|
||||||
LLVMValueRef vals[7] = {
|
LLVMValueRef vals[7] = {
|
||||||
lb_type_info(m, t->EnumeratedArray.elem).value,
|
get_type_info_ptr(m, t->EnumeratedArray.elem),
|
||||||
lb_type_info(m, t->EnumeratedArray.index).value,
|
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, type_size_of(t->EnumeratedArray.elem)).value,
|
||||||
lb_const_int(m, t_int, t->EnumeratedArray.count).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;
|
tag_type = t_type_info_dynamic_array;
|
||||||
|
|
||||||
LLVMValueRef vals[2] = {
|
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,
|
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;
|
tag_type = t_type_info_slice;
|
||||||
|
|
||||||
LLVMValueRef vals[2] = {
|
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,
|
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 params = LLVMConstNull(lb_type(m, t_type_info_ptr));
|
||||||
LLVMValueRef results = LLVMConstNull(lb_type(m, t_type_info_ptr));
|
LLVMValueRef results = LLVMConstNull(lb_type(m, t_type_info_ptr));
|
||||||
if (t->Proc.params != nullptr) {
|
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) {
|
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] = {
|
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 index = lb_const_int(m, t_int, i);
|
||||||
lbValue type_info = lb_const_ptr_offset(m, memory_types, index);
|
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) {
|
if (f->token.string.len > 0) {
|
||||||
lb_global_type_info_member_names_values[name_offset+i] = lb_const_string(m, f->token.string).value;
|
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] = {};
|
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) {
|
if (t->Enum.fields.count > 0) {
|
||||||
auto fields = t->Enum.fields;
|
auto fields = t->Enum.fields;
|
||||||
lbValue name_array = lb_generate_global_array(m, t_string, fields.count,
|
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++) {
|
for (isize variant_index = 0; variant_index < variant_count; variant_index++) {
|
||||||
Type *vt = t->Union.variants[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] = get_type_info_ptr(m, vt);
|
||||||
|
|
||||||
lb_global_type_info_member_types_values[variant_offset+variant_index] = lb_type_info(m, vt).value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lbValue count = lb_const_int(m, t_int, variant_count);
|
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) {
|
if (tag_size > 0) {
|
||||||
i64 tag_offset = align_formula(t->Union.variant_block_size, tag_size);
|
i64 tag_offset = align_formula(t->Union.variant_block_size, tag_size);
|
||||||
vals[1] = lb_const_int(m, t_uintptr, tag_offset).value;
|
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 {
|
} else {
|
||||||
vals[1] = lb_const_int(m, t_uintptr, 0).value;
|
vals[1] = lb_const_int(m, t_uintptr, 0).value;
|
||||||
vals[2] = LLVMConstNull(lb_type(m, t_type_info_ptr));
|
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);
|
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_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);
|
lbValue soa_len = lb_const_int(m, t_int, t->Struct.soa_count);
|
||||||
|
|
||||||
vals[10] = soa_kind.value;
|
vals[10] = soa_kind.value;
|
||||||
vals[11] = soa_type.value;
|
vals[11] = soa_type;
|
||||||
vals[12] = soa_len.value;
|
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
|
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++) {
|
for (isize source_index = 0; source_index < count; source_index++) {
|
||||||
Entity *f = t->Struct.fields[source_index];
|
Entity *f = t->Struct.fields[source_index];
|
||||||
lbValue tip = lb_type_info(m, f->type);
|
|
||||||
i64 foffset = 0;
|
i64 foffset = 0;
|
||||||
if (!t->Struct.is_raw_union) {
|
if (!t->Struct.is_raw_union) {
|
||||||
GB_ASSERT(t->Struct.offsets != nullptr);
|
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);
|
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_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;
|
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);
|
init_map_internal_types(t);
|
||||||
|
|
||||||
LLVMValueRef vals[3] = {
|
LLVMValueRef vals[3] = {
|
||||||
lb_type_info(m, t->Map.key).value,
|
get_type_info_ptr(m, t->Map.key),
|
||||||
lb_type_info(m, t->Map.value).value,
|
get_type_info_ptr(m, t->Map.value),
|
||||||
lb_gen_map_info_ptr(m, t).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] = {
|
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)),
|
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.lower).value,
|
||||||
lb_const_int(m, t_i64, t->BitSet.upper).value,
|
lb_const_int(m, t_i64, t->BitSet.upper).value,
|
||||||
};
|
};
|
||||||
if (t->BitSet.underlying != nullptr) {
|
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));
|
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] = {};
|
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[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;
|
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;
|
tag_type = t_type_info_relative_pointer;
|
||||||
LLVMValueRef vals[2] = {
|
LLVMValueRef vals[2] = {
|
||||||
lb_type_info(m, t->RelativePointer.pointer_type).value,
|
get_type_info_ptr(m, t->RelativePointer.pointer_type),
|
||||||
lb_type_info(m, t->RelativePointer.base_integer).value,
|
get_type_info_ptr(m, t->RelativePointer.base_integer),
|
||||||
};
|
};
|
||||||
|
|
||||||
variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals));
|
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;
|
tag_type = t_type_info_relative_multi_pointer;
|
||||||
LLVMValueRef vals[2] = {
|
LLVMValueRef vals[2] = {
|
||||||
lb_type_info(m, t->RelativeMultiPointer.pointer_type).value,
|
get_type_info_ptr(m, t->RelativeMultiPointer.pointer_type),
|
||||||
lb_type_info(m, t->RelativeMultiPointer.base_integer).value,
|
get_type_info_ptr(m, t->RelativeMultiPointer.base_integer),
|
||||||
};
|
};
|
||||||
|
|
||||||
variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals));
|
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);
|
i64 ez = type_size_of(t->Matrix.elem);
|
||||||
|
|
||||||
LLVMValueRef vals[5] = {
|
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, ez).value,
|
||||||
lb_const_int(m, t_int, matrix_type_stride_in_elems(t)).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,
|
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) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -89,8 +89,8 @@ gb_global Timings global_timings = {0};
|
|||||||
#if LLVM_VERSION_MAJOR < 11
|
#if LLVM_VERSION_MAJOR < 11
|
||||||
#error LLVM Version 11+ is required => "brew install llvm@11"
|
#error LLVM Version 11+ is required => "brew install llvm@11"
|
||||||
#endif
|
#endif
|
||||||
#if LLVM_VERSION_MAJOR > 14
|
#if (LLVM_VERSION_MAJOR > 14 && LLVM_VERSION_MAJOR < 17) || LLVM_VERSION_MAJOR > 17
|
||||||
#error LLVM Version 11..=14 is required => "brew install llvm@14"
|
#error LLVM Version 11..=14 or =17 is required => "brew install llvm@14"
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
+10
-10
@@ -1032,22 +1032,22 @@ gb_internal void cg_build_assignment(cgProcedure *p, Array<cgAddr> const &lvals,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type *type = cg_addr_type(lval);
|
Type *type = cg_addr_type(lval);
|
||||||
if (!cg_addr_is_empty(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));
|
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 &&
|
if (init.kind == cgValue_Addr &&
|
||||||
!cg_addr_is_empty(lval)) {
|
!cg_addr_is_empty(lval)) {
|
||||||
// NOTE(bill): This is needed for certain constructs such as this:
|
// NOTE(bill): This is needed for certain constructs such as this:
|
||||||
// a, b = b, a
|
// a, b = b, a
|
||||||
// NOTE(bill): This is a bodge and not necessarily a good way of doing things whatsoever
|
// 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 size = cast(TB_CharUnits)type_size_of(type);
|
||||||
TB_CharUnits align = cast(TB_CharUnits)type_align_of(type);
|
TB_CharUnits align = cast(TB_CharUnits)type_align_of(type);
|
||||||
TB_Node *copy = tb_inst_local(p->func, size, align);
|
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);
|
tb_inst_memcpy(p->func, copy, init.node, tb_inst_uint(p->func, TB_TYPE_INT, size), align);
|
||||||
// use the copy instead
|
// use the copy instead
|
||||||
init.node = copy;
|
init.node = copy;
|
||||||
}
|
}
|
||||||
inits[i] = init;
|
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);
|
Type *t = alloc_type(Type_EnumeratedArray);
|
||||||
t->EnumeratedArray.elem = elem;
|
t->EnumeratedArray.elem = elem;
|
||||||
t->EnumeratedArray.index = index;
|
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));
|
gb_memmove(t->EnumeratedArray.max_value, max_value, gb_size_of(ExactValue));
|
||||||
t->EnumeratedArray.op = op;
|
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;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import "core:encoding/json"
|
|||||||
import "core:testing"
|
import "core:testing"
|
||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
import "core:os"
|
import "core:os"
|
||||||
|
import "core:mem/virtual"
|
||||||
|
|
||||||
TEST_count := 0
|
TEST_count := 0
|
||||||
TEST_fail := 0
|
TEST_fail := 0
|
||||||
@@ -77,6 +78,49 @@ parse_json :: proc(t: ^testing.T) {
|
|||||||
expect(t, err == nil, msg)
|
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
|
@test
|
||||||
marshal_json :: proc(t: ^testing.T) {
|
marshal_json :: proc(t: ^testing.T) {
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
ODIN=../../odin
|
ODIN=../../odin
|
||||||
|
|
||||||
all: map_test
|
all: rtti_test map_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
|
$(ODIN) run test_map.odin -file -vet -strict-style -o:minimal
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
@echo off
|
@echo off
|
||||||
set PATH_TO_ODIN==..\..\odin
|
set PATH_TO_ODIN==..\..\odin
|
||||||
%PATH_TO_ODIN% run test_map.odin -file -vet -strict-style -o:minimal || exit /b
|
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
|
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,
|
port: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PacketFlags :: bit_set[PacketFlag; i32]
|
||||||
PacketFlag :: enum i32 {
|
PacketFlag :: enum i32 {
|
||||||
RELIABLE = 1 << 0,
|
RELIABLE = 0,
|
||||||
UNSEQUENCED = 1 << 1,
|
UNSEQUENCED = 1,
|
||||||
NO_ALLOCATE = 1 << 2,
|
NO_ALLOCATE = 2,
|
||||||
UNRELIABLE_FRAGMENT = 1 << 3,
|
UNRELIABLE_FRAGMENT = 3,
|
||||||
FLAG_SENT = 1 << 8,
|
FLAG_SENT = 8,
|
||||||
}
|
}
|
||||||
|
|
||||||
PacketFreeCallback :: proc "c" (packet: ^Packet)
|
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_ip :: proc(address: ^Address, hostName: [^]u8, nameLength: uint) -> i32 ---
|
||||||
address_get_host :: 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_destroy :: proc(packet: ^Packet) ---
|
||||||
packet_resize :: proc(packet: ^Packet, dataLength: uint) -> i32 ---
|
packet_resize :: proc(packet: ^Packet, dataLength: uint) -> i32 ---
|
||||||
crc32 :: proc(buffers: [^]Buffer, bufferCount: uint) -> u32 ---
|
crc32 :: proc(buffers: [^]Buffer, bufferCount: uint) -> u32 ---
|
||||||
@@ -397,4 +398,4 @@ foreign ENet {
|
|||||||
range_coder_destroy :: proc(ctx: rawptr) ---
|
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_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 ---
|
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
|
package vendor_openexr
|
||||||
|
|
||||||
|
OPENEXRCORE_SHARED :: #config(OPENEXRCORE_SHARED, false)
|
||||||
|
|
||||||
when ODIN_OS == .Windows {
|
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 {
|
} else {
|
||||||
foreign import lib "system:OpenEXRCore-3_1"
|
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:c/libc"
|
||||||
import "core:runtime"
|
import "core:runtime"
|
||||||
|
|
||||||
|
COMMONMARK_SHARED :: #config(COMMONMARK_SHARED, false)
|
||||||
BINDING_VERSION :: Version_Info{major = 0, minor = 30, patch = 2}
|
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 {
|
when ODIN_OS == .Windows {
|
||||||
foreign import lib {
|
foreign import lib {
|
||||||
"cmark_static.lib",
|
"cmark_static.lib",
|
||||||
|
|||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
//+build darwin
|
||||||
package CoreVideo
|
package CoreVideo
|
||||||
|
|
||||||
DisplayLinkRef :: distinct rawptr
|
DisplayLinkRef :: distinct rawptr
|
||||||
|
|||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
//+build darwin
|
||||||
package objc_Foundation
|
package objc_Foundation
|
||||||
|
|
||||||
foreign import "system:Foundation.framework"
|
foreign import "system:Foundation.framework"
|
||||||
|
|||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
//+build darwin
|
||||||
package objc_Foundation
|
package objc_Foundation
|
||||||
|
|
||||||
import "core:intrinsics"
|
import "core:intrinsics"
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//+build darwin
|
||||||
package objc_Foundation
|
package objc_Foundation
|
||||||
|
|
||||||
@(objc_class="NSAutoreleasePool")
|
@(objc_class="NSAutoreleasePool")
|
||||||
|
|||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
//+build darwin
|
||||||
package objc_Foundation
|
package objc_Foundation
|
||||||
|
|
||||||
import "core:intrinsics"
|
import "core:intrinsics"
|
||||||
|
|||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
//+build darwin
|
||||||
package objc_Foundation
|
package objc_Foundation
|
||||||
|
|
||||||
@(objc_class="NSBundle")
|
@(objc_class="NSBundle")
|
||||||
|
|||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
//+build darwin
|
||||||
package objc_Foundation
|
package objc_Foundation
|
||||||
|
|
||||||
@(objc_class="NSColorSpace")
|
@(objc_class="NSColorSpace")
|
||||||
|
|||||||
Vendored
+1
@@ -1,3 +1,4 @@
|
|||||||
|
//+build darwin
|
||||||
package objc_Foundation
|
package objc_Foundation
|
||||||
|
|
||||||
@(objc_class="NSData")
|
@(objc_class="NSData")
|
||||||
|
|||||||
Vendored
+1
@@ -1,3 +1,4 @@
|
|||||||
|
//+build darwin
|
||||||
package objc_Foundation
|
package objc_Foundation
|
||||||
|
|
||||||
@(objc_class="NSDate")
|
@(objc_class="NSDate")
|
||||||
|
|||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
//+build darwin
|
||||||
package objc_Foundation
|
package objc_Foundation
|
||||||
|
|
||||||
@(objc_class="NSDictionary")
|
@(objc_class="NSDictionary")
|
||||||
|
|||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
//+build darwin
|
||||||
package objc_Foundation
|
package objc_Foundation
|
||||||
|
|
||||||
import "core:c"
|
import "core:c"
|
||||||
|
|||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
//+build darwin
|
||||||
package objc_Foundation
|
package objc_Foundation
|
||||||
|
|
||||||
foreign import "system:Foundation.framework"
|
foreign import "system:Foundation.framework"
|
||||||
|
|||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
//+build darwin
|
||||||
package objc_Foundation
|
package objc_Foundation
|
||||||
|
|
||||||
@(objc_class="NSEvent")
|
@(objc_class="NSEvent")
|
||||||
|
|||||||
Vendored
+1
@@ -1,3 +1,4 @@
|
|||||||
|
//+build darwin
|
||||||
package objc_Foundation
|
package objc_Foundation
|
||||||
|
|
||||||
Locking :: struct($T: typeid) {using _: Object}
|
Locking :: struct($T: typeid) {using _: Object}
|
||||||
|
|||||||
Vendored
+1
@@ -1,3 +1,4 @@
|
|||||||
|
//+build darwin
|
||||||
package objc_Foundation
|
package objc_Foundation
|
||||||
|
|
||||||
import "core:builtin"
|
import "core:builtin"
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//+build darwin
|
||||||
package objc_Foundation
|
package objc_Foundation
|
||||||
|
|
||||||
@(objc_class="NSNotification")
|
@(objc_class="NSNotification")
|
||||||
|
|||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
//+build darwin
|
||||||
package objc_Foundation
|
package objc_Foundation
|
||||||
|
|
||||||
import "core:c"
|
import "core:c"
|
||||||
|
|||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
//+build darwin
|
||||||
package objc_Foundation
|
package objc_Foundation
|
||||||
|
|
||||||
import "core:intrinsics"
|
import "core:intrinsics"
|
||||||
|
|||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
//+build darwin
|
||||||
package objc_Foundation
|
package objc_Foundation
|
||||||
|
|
||||||
@(objc_class="NSOpenPanel")
|
@(objc_class="NSOpenPanel")
|
||||||
|
|||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
//+build darwin
|
||||||
package objc_Foundation
|
package objc_Foundation
|
||||||
|
|
||||||
ModalResponse :: enum UInteger {
|
ModalResponse :: enum UInteger {
|
||||||
|
|||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
//+build darwin
|
||||||
package objc_Foundation
|
package objc_Foundation
|
||||||
|
|
||||||
@(objc_class="NSPasteboard")
|
@(objc_class="NSPasteboard")
|
||||||
|
|||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
//+build darwin
|
||||||
package objc_Foundation
|
package objc_Foundation
|
||||||
|
|
||||||
Range :: struct {
|
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