diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 8301d6b17..4d7bd3864 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -10,8 +10,10 @@ env:
LLVM_RELEASE_VERSION_WINDOWS: 18
LLVM_RELEASE_VERSION_MAC: 17
LLVM_RELEASE_VERSION_LINUX: 17
+ LLVM_RELEASE_VERSION_OPENBSD: 19
LLVM_RELEASE_VERSION_UBUNTU22: 17
LLVM_DEV_VERSION: 21
+ OPENBSD_RELEASE: "7.7"
jobs:
build-msvc:
@@ -751,6 +753,119 @@ jobs:
nix build -L ".#c3c-checks"
fi
+ build-openbsd:
+ runs-on: ubuntu-latest
+ strategy:
+ # Don't abort runners if a single one fails
+ fail-fast: false
+ matrix:
+ build_type: [Release, Debug]
+
+ steps:
+ - uses: actions/checkout@v4
+ - name: OpenBSD VM
+ uses: vmactions/openbsd-vm@main
+ with:
+ prepare: |
+ pkg_add cmake llvm-19.1.7p3 ninja
+
+ run: |
+ echo "CMake"
+ cmake -B build \
+ -G Ninja \
+ -DCMAKE_BUILD_TYPE=${{matrix.build_type}} \
+ -DLLVM_ENABLE_LIBXML2=OFF \
+ -DC3_LLVM_VERSION=${LLVM_RELEASE_VERSION_OPENBSD}
+ cmake --build build
+ echo "Compile and run some examples"
+ cd resources
+ ../build/c3c compile examples/base64.c3
+ ../build/c3c compile examples/binarydigits.c3
+ ../build/c3c compile examples/brainfk.c3
+ ../build/c3c compile examples/factorial_macro.c3
+ ../build/c3c compile examples/fasta.c3
+ ../build/c3c compile examples/gameoflife.c3
+ ../build/c3c compile examples/hash.c3
+ ../build/c3c compile-only examples/levenshtein.c3
+ ../build/c3c compile examples/load_world.c3
+ ../build/c3c compile-only examples/map.c3
+ ../build/c3c compile examples/mandelbrot.c3
+ ../build/c3c compile examples/plus_minus.c3
+ ../build/c3c compile examples/nbodies.c3
+ ../build/c3c compile examples/spectralnorm.c3
+ ../build/c3c compile examples/swap.c3
+ ../build/c3c compile examples/contextfree/boolerr.c3
+ ../build/c3c compile examples/contextfree/dynscope.c3
+ ../build/c3c compile examples/contextfree/guess_number.c3
+ ../build/c3c compile examples/contextfree/multi.c3
+ ../build/c3c compile examples/contextfree/cleanup.c3
+ ../build/c3c compile-run examples/hello_world_many.c3
+ ../build/c3c compile-run examples/time.c3
+ ../build/c3c compile-run examples/fannkuch-redux.c3
+ ../build/c3c compile-run examples/contextfree/boolerr.c3
+ ../build/c3c compile-run examples/load_world.c3
+ ../build/c3c compile-run examples/process.c3
+ ../build/c3c compile-run examples/ls.c3
+ ../build/c3c compile-run examples/args.c3 -- foo -bar "baz baz"
+ cd ..
+ echo "Compile and run dynlib-test"
+ cd resources/examples/dynlib-test
+ ../../../build/c3c -vv dynamic-lib add.c3
+ mv add.so libadd.so
+ cc test.c -L. -ladd -Wl,-rpath=.
+ ./a.out
+ ../../../build/c3c compile-run test.c3 -L . -l add -z -Wl,-rpath=.
+ cd ../../../
+ echo "Compile and run staticlib-test"
+ cd resources/examples/staticlib-test
+ ../../../build/c3c -vv static-lib add.c3
+ mv add.a libadd.a
+ cc test.c -L. -ladd
+ ./a.out
+ ../../../build/c3c compile-run test.c3 -L . -l add
+ cd ../../../
+ echo "Compile run unit tests"
+ cd test
+ ../build/c3c --max-mem 128 compile-test unit -D SLOW_TESTS
+ cd ..
+ echo "Build testproject"
+ cd resources/testproject
+ ../../build/c3c run -vvv --trust=full
+ cd ../../
+ echo "Test WASM"
+ cd resources/testfragments
+ ../../build/c3c compile --target wasm32 -g0 --no-entry -Os wasm4.c3
+ cd ../../
+ echo "Build testproject direct linker"
+ cd resources/testproject
+ ../../build/c3c run -vvv --linker=builtin --trust=full
+ cd ../../
+ echo "Init a library & a project"
+ ./build/c3c init-lib mylib
+ ls mylib.c3l
+ ./build/c3c init myproject
+ ls myproject
+ echo "run compiler tests"
+ cd test
+ ../build/c3c --max-mem 128 compile-run -O1 src/test_suite_runner.c3 -- ../build/c3c test_suite/
+ cd ..
+
+ - name: bundle_output
+ run: |
+ mkdir c3
+ cp -r lib c3
+ cp msvc_build_libraries.py c3
+ cp build/c3c c3
+ cp README.md c3
+ cp releasenotes.md c3
+ tar czf c3-openbsd-$OPENBSD_RELEASE-${{matrix.build_type}}.tar.gz c3
+
+ - name: upload artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: c3-openbsd-$OPENBSD_RELEASE-${{matrix.build_type}}
+ path: c3-openbsd-$OPENBSD_RELEASE-${{matrix.build_type}}.tar.gz
+
release:
runs-on: ubuntu-22.04
needs: [build-msvc, build-linux, build-mac, build-linux-ubuntu22]
@@ -773,6 +888,8 @@ jobs:
- run: zip -r c3-windows-debug.zip c3-windows-Debug
- run: mv c3-linux-Release/c3-linux-Release.tar.gz c3-linux-Release/c3-linux.tar.gz
- run: mv c3-linux-Debug/c3-linux-Debug.tar.gz c3-linux-Debug/c3-linux-debug.tar.gz
+ - run: mv c3-openbsd-$OPENBSD_RELEASE-Release/c3-openbsd-$OPENBSD_RELEASE-Release.tar.gz c3-openbsd-$OPENBSD_RELEASE-Release/c3-openbsd-$OPENBSD_RELEASE.tar.gz
+ - run: mv c3-openbsd-$OPENBSD_RELEASE-Debug/c3-openbsd-$OPENBSD_RELEASE-Debug.tar.gz c3-openbsd-$OPENBSD_RELEASE-Debug/c3-openbsd-$OPENBSD_RELEASE-debug.tar.gz
- run: mv c3-ubuntu-22-Release/c3-ubuntu-22-Release.tar.gz c3-ubuntu-22-Release/c3-ubuntu-22.tar.gz
- run: mv c3-ubuntu-22-Debug/c3-ubuntu-22-Debug.tar.gz c3-ubuntu-22-Debug/c3-ubuntu-22-debug.tar.gz
- run: mv c3-macos-Release/c3-macos-Release.zip c3-macos-Release/c3-macos.zip
@@ -794,6 +911,8 @@ jobs:
c3-windows-debug.zip
c3-linux-Release/c3-linux.tar.gz
c3-linux-Debug/c3-linux-debug.tar.gz
+ c3-openbsd-$OPENBSD_RELEASE-Release/c3-openbsd-$OPENBSD_RELEASE.tar.gz
+ g3-openbsd-$OPENBSD_RELEASE-Debug/c3-openbsd-$OPENBSD_RELEASE-debug.tar.gz
c3-ubuntu-22-Release/c3-ubuntu-22.tar.gz
c3-ubuntu-22-Debug/c3-ubuntu-22-debug.tar.gz
c3-macos-Release/c3-macos.zip
diff --git a/README.md b/README.md
index 5fa1fdcdd..dc743ce99 100644
--- a/README.md
+++ b/README.md
@@ -12,6 +12,7 @@ Precompiled binaries for the following operating systems are available:
- Debian x64 [download](https://github.com/c3lang/c3c/releases/download/latest-prerelease/c3-linux.tar.gz), [install instructions](#installing-on-debian-with-precompiled-binaries).
- Ubuntu x86 [download](https://github.com/c3lang/c3c/releases/download/latest-prerelease/c3-ubuntu-20.tar.gz), [install instructions](#installing-on-ubuntu-with-precompiled-binaries).
- MacOS Arm64 [download](https://github.com/c3lang/c3c/releases/download/latest-prerelease/c3-macos.zip), [install instructions](#installing-on-macos-with-precompiled-binaries).
+- OpenBSD 7.7 x64 [download](https://github.com/c3lang/c3c/releases/download/latest-prerelease/c3-openbsd-7.7.tar.gz), [install instructions](#installing-on-openbsd-with-precompiled-binaries).
The manual for C3 can be found at [www.c3-lang.org](http://www.c3-lang.org).
@@ -176,12 +177,14 @@ The compiler is currently verified to compile on Linux, Windows and MacOS.
| NetBSD x86 | Untested | Untested | No | Yes | Untested | Yes* |
| NetBSD x64 | Untested | Untested | No | Yes | Untested | Yes* |
| OpenBSD x86 | Untested | Untested | No | Yes | Untested | Yes* |
-| OpenBSD x64 | Untested | Untested | No | Yes | Untested | Yes* |
+| OpenBSD x64 | Yes* | Yes | Yes* | Yes | Untested | Yes* |
| MCU x86 | No | Untested | No | No | No | Yes* |
| Wasm32 | No | Yes | No | No | No | No |
| Wasm64 | No | Untested | No | No | No | No |
-*\* Inline asm is still a work in progress*
+*\* Inline asm is still a work in progress*
+*\* OpenBSD 7.7 is the only tested version*
+*\* OpenBSD has limited stacktrace, needs to be tested further*
More platforms will be supported in the future.
@@ -227,6 +230,14 @@ This installs the latest prerelease build, as opposed to the latest released ver
(*Note that there is a known issue with debug symbol generation on MacOS 13, see [issue #1086](https://github.com/c3lang/c3c/issues/1086))
+#### Installing on OpenBSD with precompiled binaries
+1. Download tar file: [https://github.com/c3lang/c3c/releases/download/latest-prerelease/c3-openbsd-7.7.tar.gz](https://github.com/c3lang/c3c/releases/download/latest-prerelease/c3-openbsd-7.7.tar.gz)
+ (debug version [here](https://github.com/c3lang/c3c/releases/download/latest-prerelease/c3-openbsd-7.7-debug.tar.gz))
+2. Unpack executable and standard lib.
+3. Run `./c3c`.
+
+(*Note that this is specifically for OpenBSD 7.7, running it on any other version is prone to ABI breaks)
+
#### Installing on Arch Linux
Arch includes c3c in the official 'extra' repo. It can be easily installed the usual way:
diff --git a/lib/std/core/env.c3 b/lib/std/core/env.c3
index 22e56f8e8..deea29b5c 100644
--- a/lib/std/core/env.c3
+++ b/lib/std/core/env.c3
@@ -143,7 +143,7 @@ const bool TRACK_MEMORY = DEBUG_SYMBOLS && (COMPILER_SAFE_MODE || TESTING);
const bool X86_64 = ARCH_TYPE == X86_64;
const bool X86 = ARCH_TYPE == X86;
const bool AARCH64 = ARCH_TYPE == AARCH64;
-const bool NATIVE_STACKTRACE = LINUX || DARWIN || WIN32;
+const bool NATIVE_STACKTRACE = LINUX || DARWIN || OPENBSD || WIN32;
const bool LINUX = LIBC && OS_TYPE == LINUX;
const bool DARWIN = LIBC && os_is_darwin();
const bool WIN32 = LIBC && OS_TYPE == WIN32;
@@ -160,7 +160,7 @@ const bool MEMORY_SANITIZER = $$MEMORY_SANITIZER;
const bool THREAD_SANITIZER = $$THREAD_SANITIZER;
const bool ANY_SANITIZER = ADDRESS_SANITIZER || MEMORY_SANITIZER || THREAD_SANITIZER;
const int LANGUAGE_DEV_VERSION = $$LANGUAGE_DEV_VERSION;
-const bool HAS_NATIVE_ERRNO = env::LINUX || env::ANDROID || env::DARWIN || env::WIN32;
+const bool HAS_NATIVE_ERRNO = env::LINUX || env::ANDROID || env::OPENBSD || env::DARWIN || env::WIN32;
macro bool os_is_darwin() @const
{
diff --git a/lib/std/libc/os/errno.c3 b/lib/std/libc/os/errno.c3
index 01c68438c..025b6835b 100644
--- a/lib/std/libc/os/errno.c3
+++ b/lib/std/libc/os/errno.c3
@@ -11,6 +11,11 @@ extern fn int* __errno() @if(env::ANDROID);
macro int errno() @if(env::ANDROID) => *__errno();
macro void errno_set(int err) @if(env::ANDROID) => *(__errno()) = err;
+// OpenBSD
+extern fn int* __errno() @if(env::OPENBSD);
+macro int errno() @if(env::OPENBSD) => *__errno();
+macro void errno_set(int err) @if(env::OPENBSD) => *(__errno()) = err;
+
// Darwin
extern fn int* __error() @if(env::DARWIN);
macro int errno() @if(env::DARWIN) => *__error();
diff --git a/lib/std/libc/os/openbsd.c3 b/lib/std/libc/os/openbsd.c3
new file mode 100644
index 000000000..ebc715e5b
--- /dev/null
+++ b/lib/std/libc/os/openbsd.c3
@@ -0,0 +1,60 @@
+module libc @if(env::OPENBSD);
+
+// Checked for x86_64
+
+alias Blksize_t = int;
+alias Nlink_t = $typefrom(env::X86_64 ? uint.typeid : CUInt.typeid);
+alias Dev_t = int;
+alias Ino_t = ulong;
+alias Mode_t = uint;
+alias Blkcnt_t = long;
+alias Fflags_t = uint;
+
+struct Stat @if(env::X86_64)
+{
+ Mode_t st_mode;
+ Dev_t st_dev;
+ Ino_t st_ino;
+ Nlink_t st_nlink;
+ Uid_t st_uid;
+ Gid_t st_gid;
+ Dev_t st_rdev;
+ TimeSpec st_atime;
+ TimeSpec st_mtime;
+ TimeSpec st_ctime;
+ Off_t st_size;
+ Blkcnt_t st_blocks;
+ Blksize_t st_blksize;
+ Fflags_t st_flags;
+ uint st_gen;
+ ulong[10] st_spare;
+}
+
+// TODO: Investigate if this needs to be fixed
+struct Stat @if(!env::X86_64)
+{
+ Dev_t st_dev;
+ Ino_t st_ino;
+ Mode_t st_mode;
+ Nlink_t st_nlink;
+ Uid_t st_uid;
+ Gid_t st_gid;
+ Dev_t st_rdev;
+ CInt __pad1;
+ Off_t st_size;
+ Blksize_t st_blksize;
+ CInt __pad2;
+ Blkcnt_t st_blocks;
+ Time_t st_atime;
+ long st_atime_nsec;
+ Time_t st_mtime;
+ long st_mtime_nsec;
+ Time_t st_ctime;
+ long st_ctime_nsec;
+ CInt[2] __unused;
+}
+
+extern fn CInt stat(ZString path, Stat* stat);
+
+extern fn CInt get_nprocs();
+extern fn CInt get_nprocs_conf();
diff --git a/lib/std/os/backtrace.c3 b/lib/std/os/backtrace.c3
index c44e771a2..a477d5b6c 100644
--- a/lib/std/os/backtrace.c3
+++ b/lib/std/os/backtrace.c3
@@ -87,11 +87,12 @@ fn void*[] capture_current(void*[] buffer)
alias BacktraceList = List{Backtrace};
-alias symbolize_backtrace @if(env::LINUX) = linux::symbolize_backtrace;
-alias symbolize_backtrace @if(env::WIN32) = win32::symbolize_backtrace;
-alias symbolize_backtrace @if(env::DARWIN) = darwin::symbolize_backtrace;
+alias symbolize_backtrace @if(env::LINUX) = linux::symbolize_backtrace;
+alias symbolize_backtrace @if(env::WIN32) = win32::symbolize_backtrace;
+alias symbolize_backtrace @if(env::DARWIN) = darwin::symbolize_backtrace;
+alias symbolize_backtrace @if(env::OPENBSD) = openbsd::symbolize_backtrace;
fn BacktraceList? symbolize_backtrace(Allocator allocator, void*[] backtrace) @if(!env::NATIVE_STACKTRACE)
{
return {};
-}
\ No newline at end of file
+}
diff --git a/lib/std/os/openbsd/general.c3 b/lib/std/os/openbsd/general.c3
index 34e7112f6..292330a4c 100644
--- a/lib/std/os/openbsd/general.c3
+++ b/lib/std/os/openbsd/general.c3
@@ -1,2 +1,74 @@
module std::os::openbsd @if(env::OPENBSD);
+import libc, std::os, std::collections::list;
+extern fn ZString* backtrace_symbols_fmt(void **addrlist, usz len, ZString fmt);
+
+fn Backtrace? backtrace_line_parse(Allocator allocator, String obj, String addr2line) @local
+{
+ @stack_mem(256; Allocator mem)
+ {
+ String[] parts = addr2line.trim().split(mem, " at ");
+ if (parts.len != 2) return NOT_FOUND?;
+
+ uint line = 0;
+ String source = "";
+ if (!parts[1].contains("?") && parts[1].contains(":"))
+ {
+ usz index = parts[1].rindex_of_char(':')!;
+ source = parts[1][:index];
+ line = parts[1][index + 1..].to_uint()!;
+ }
+ return {
+ .function = parts[0].copy(allocator),
+ .object_file = obj.copy(allocator),
+ .file = source.copy(allocator),
+ .line = line,
+ .allocator = allocator,
+ .is_inline = false,
+ };
+ };
+}
+
+fn void? backtrace_add_addr2line(Allocator allocator, BacktraceList* list, String obj, String addr2line) @local
+{
+ list.push(backtrace_line_parse(allocator, obj, addr2line)!);
+}
+
+fn void? backtrace_add_from_exec(Allocator allocator, BacktraceList* list, String fun, String obj) @local
+{
+ char[1024] buf @noinit;
+ String addr2line = process::execute_stdout_to_buffer(&buf, {"llvm-addr2line", "-fpe", obj, fun})!;
+ return backtrace_add_addr2line(allocator, list, obj, addr2line);
+}
+
+fn void? backtrace_add_element(Allocator allocator, BacktraceList *list, String fun, String obj) @local
+{
+ return backtrace_add_from_exec(allocator, list, fun, obj);
+}
+
+fn BacktraceList? symbolize_backtrace(Allocator allocator, void*[] backtrace)
+{
+ BacktraceList list;
+ list.init(allocator, backtrace.len);
+ defer catch
+ {
+ foreach (trace : list)
+ {
+ trace.free();
+ }
+ list.free();
+ }
+
+ ZString *strings = backtrace_symbols_fmt(backtrace.ptr, backtrace.len, "%n%D %f");
+
+ for (int i = 0; i < backtrace.len; i++) {
+ String full = strings[i].str_view();
+ Splitter iter = full.tokenize(" ");
+ String fun = iter.next()!;
+ String obj = iter.next()!;
+ backtrace_add_element(allocator, &list, fun, obj)!;
+ }
+
+ free(strings);
+ return list;
+}
diff --git a/lib/std/os/posix/process.c3 b/lib/std/os/posix/process.c3
index 732dfd054..a549325bd 100644
--- a/lib/std/os/posix/process.c3
+++ b/lib/std/os/posix/process.c3
@@ -58,7 +58,9 @@ const CInt WUNTRACES = 2;
JmpBuf backtrace_jmpbuf @local;
alias BacktraceFn = fn CInt(void** buffer, CInt size);
-fn CInt backtrace(void** buffer, CInt size)
+extern fn CInt backtrace(void** buffer, CInt size) @if(env::OPENBSD);
+
+fn CInt backtrace(void** buffer, CInt size) @if(!env::OPENBSD)
{
if (size < 1) return 0;
void* handle = libc::dlopen("libc.so.6", libc::RTLD_LAZY|libc::RTLD_NODELETE);
diff --git a/src/compiler/linker.c b/src/compiler/linker.c
index eaf814b7c..f0ce6f0db 100644
--- a/src/compiler/linker.c
+++ b/src/compiler/linker.c
@@ -532,6 +532,11 @@ static void linker_setup_freebsd(const char ***args_ref, Linker linker_type, boo
{
if (linker_type == LINKER_CC) {
linking_add_link(&compiler.linking, "pthread");
+ linking_add_link(&compiler.linking, "execinfo"); // for backtrace
+ if (compiler.build.debug_info == DEBUG_INFO_FULL)
+ {
+ add_plain_arg("-rdynamic");
+ }
return;
}
if (is_no_pie(compiler.platform.reloc_model)) add_plain_arg("-no-pie");
diff --git a/src/main.c b/src/main.c
index 64b6e93e5..b56ead3d9 100644
--- a/src/main.c
+++ b/src/main.c
@@ -4,6 +4,9 @@
#include "utils/lib.h"
#include
+#ifdef __OpenBSD__
+#include
+#endif
bool debug_log = false;
@@ -27,6 +30,13 @@ int main_real(int argc, const char *argv[])
{
srand((unsigned int)time(NULL));
compiler_exe_name = argv[0];
+#ifdef __OpenBSD__
+ // override data size constrain set up by the system */
+ struct rlimit l;
+ getrlimit(RLIMIT_DATA, &l);
+ l.rlim_cur = l.rlim_max;
+ setrlimit(RLIMIT_DATA, &l);
+#endif
bench_begin();
// Setjmp will allow us to add things like fuzzing with
diff --git a/test/src/test_suite_runner.c3 b/test/src/test_suite_runner.c3
index b3ec3423e..73098da91 100644
--- a/test/src/test_suite_runner.c3
+++ b/test/src/test_suite_runner.c3
@@ -411,6 +411,10 @@ fn void test_file(Path file_path)
// Construct the compile line
List{String} cmdline;
cmdline.push(compiler_path.str_view());
+ $if env::OPENBSD:
+ cmdline.push("--max-mem");
+ cmdline.push("128");
+ $endif
cmdline.push("compile-only");
cmdline.push("--test");
if (stdlib)
diff --git a/test/unit/stdlib/libc/os/openbsd.c3 b/test/unit/stdlib/libc/os/openbsd.c3
new file mode 100644
index 000000000..e69de29bb