Skip to content

Commit

Permalink
Add experimental support for NetBSD
Browse files Browse the repository at this point in the history
* On NetBSD, compile against libLLVM installed as a package.
* Support diff(1) implementations lacking the option --color.
* Check for core dumps in compare_compilers.sh.
  • Loading branch information
taahol committed Feb 17, 2024
1 parent 9e53ffe commit 116e41f
Show file tree
Hide file tree
Showing 16 changed files with 186 additions and 29 deletions.
26 changes: 26 additions & 0 deletions .github/workflows/netbsd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
on:
push:
branches:
- main
pull_request:

jobs:
test:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- uses: cross-platform-actions/[email protected]
env:
PKG_PATH: 'https://cdn.NetBSD.org/pub/pkgsrc/packages/NetBSD/amd64/9.3/All'
with:
operating_system: netbsd
version: '9.3' #TODO: bump to 10.0
environment_variables: PKG_PATH
run: |
sudo pkgin -y install clang libLLVM gmake bash diffutils && \
gmake && \
./runtests.sh --verbose && \
./runtests.sh --verbose --jou-flags "--verbose" && \
gmake clean && \
./doctest.sh && \
./compare_compilers.sh
12 changes: 8 additions & 4 deletions Makefile.posix
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,18 @@ LLVM_CONFIG ?= $(shell \
|| which /usr/local/opt/llvm@13/bin/llvm-config \
|| which llvm-config-11 \
|| which /usr/local/opt/llvm@11/bin/llvm-config \
|| which /usr/pkg/libexec/libLLVM/llvm-config \
)
CFLAGS += $(shell $(LLVM_CONFIG) --cflags)
CFLAGS += -gdwarf-4 # https://github.com/llvm/llvm-project/issues/56550
LDFLAGS ?= $(shell $(LLVM_CONFIG) --ldflags --libs)

ifeq ($(CC),cc)
# default c compiler --> use clang
CC := $(shell $(LLVM_CONFIG) --bindir)/clang
CC := $(shell \
which `$(LLVM_CONFIG) --bindir`/clang \
|| which clang \
)
endif

all: jou compile_flags.txt
Expand All @@ -26,18 +30,18 @@ compile_flags.txt:
config.h:
@v=`$(LLVM_CONFIG) --version`; case "$$v" in 11.*|13.*|14.*) ;; *) echo "Error: Found unsupported LLVM version $$v. Only LLVM 11, 13 and 14 are supported."; exit 1; esac
echo "// auto-generated by Makefile" > config.h
echo "#define JOU_CLANG_PATH \"$(shell $(LLVM_CONFIG) --bindir)/clang\"" >> config.h
echo "#define JOU_CLANG_PATH \"$(CC)\"" >> config.h

obj/%.o: src/%.c $(wildcard src/*.h) config.h
mkdir -vp obj && $(CC) -c $(CFLAGS) $< -o $@
mkdir -p obj && $(CC) -c $(CFLAGS) $< -o $@

jou: $(SRC:src/%.c=obj/%.o)
$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS)

config.jou:
echo "# auto-generated by Makefile" > config.jou
echo "def get_jou_clang_path() -> byte*:" >> config.jou
echo " return \"$(shell $(LLVM_CONFIG) --bindir)/clang\"" >> config.jou
echo " return \"$(CC)\"" >> config.jou

self_hosted_compiler: jou config.jou $(wildcard self_hosted/*.jou)
./jou -o $@ --linker-flags "$(LDFLAGS)" self_hosted/main.jou
Expand Down
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,38 @@ MacOS support is new. Please create an issue if something doesn't work.
</details>
<details> <summary>NetBSD</summary>
Support for NetBSD is still experimental. Please report bugs and
shortcomings.
1. Install the dependencies:
```
# pkgin install bash clang gmake libLLVM
```
Optionally `diffutils` can be installed for coloured diff outputs.
2. Download and compile Jou.
```
$ git clone https://github.com/Akuli/jou
$ cd jou
$ gmake
```
3. Run the hello world program to make sure that Jou works:
```
$ ./jou examples/hello.jou
Hello World
```
You can now run other Jou programs in the same way.
4. (Optional) If you want to run Jou programs with simply `jou
filename` instead of something like `./jou filename` or
`/full/path/to/jou filename`, you can add the `jou` directory to
your PATH. Refer to the manual page of your login shell for exact
syntax.
NB: Using Clang and LLVM libraries built as a part of the base system
is not currently supported.
</details>
<details> <summary>64-bit Windows</summary>
1. Go to releases on GitHub. It's in the sidebar at right.
Expand Down
30 changes: 26 additions & 4 deletions compare_compilers.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
# If tokenizing/parsing a Jou file fails, both compilers should fail with the same error message.

set -e
ulimit -c unlimited

files=()
actions=()
Expand Down Expand Up @@ -37,13 +38,24 @@ if [ ${#actions[@]} = 0 ]; then
fi

rm -rf tmp/compare_compilers
mkdir -vp tmp/compare_compilers
mkdir -p tmp/compare_compilers

if ls | grep -q core$; then
for core in *core; do
mv -v "$core" "$core"~
done
fi

YELLOW="\x1b[33m"
GREEN="\x1b[32m"
RED="\x1b[31m"
RESET="\x1b[0m"

DIFF=$(which gdiff || which diff)
if $DIFF --help | grep -q -- --color; then
diff_color="--color=always"
fi

function append_line()
{
local file="$1"
Expand Down Expand Up @@ -84,8 +96,10 @@ for error_list_file in self_hosted/*s_wrong.txt; do
done

echo "Compiling the self-hosted compiler..."
if [[ "$OS" =~ Windows ]]; then
if [[ "${OS:=$(uname)}" =~ Windows ]]; then
mingw32-make self_hosted_compiler.exe
elif [[ "$OS" =~ NetBSD ]]; then
gmake self_hosted_compiler
else
make self_hosted_compiler
fi
Expand Down Expand Up @@ -124,10 +138,18 @@ for action in ${actions[@]}; do
fi
else
echo " Compilers behave differently as expected (listed in $error_list_file)"
echo -en ${YELLOW}
rm -vf *core | xargs echo Core dumped and ignored:
echo -en ${RESET}
fi
else
if diff -u --color=always tmp/compare_compilers/compiler_written_in_c.txt tmp/compare_compilers/self_hosted.txt; then
echo " Compilers behave the same as expected"
if $DIFF -u $diff_color tmp/compare_compilers/compiler_written_in_c.txt tmp/compare_compilers/self_hosted.txt; then
if ls | grep -q core$; then
echo -e " ${RED}Error: Core dumped.${RESET}"
exit 1
else
echo " Compilers behave the same as expected"
fi
else
if [ $fix = yes ]; then
append_line $error_list_file $file
Expand Down
13 changes: 11 additions & 2 deletions doctest.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,24 @@ else
files=("$@")
fi

if [[ "$OS" =~ Windows ]]; then
if [[ "${OS:=$(uname)}" =~ Windows ]]; then
source activate
mingw32-make
jou="$PWD/jou.exe"
elif [[ "$OS" =~ NetBSD ]]; then
gmake
jou="$PWD/jou"
else
make
jou="$PWD/jou"
fi


DIFF=$(which gdiff || which diff)
if $DIFF --help | grep -q -- --color; then
diff_color="--color=always"
fi

function slice()
{
local first_lineno="$1"
Expand Down Expand Up @@ -71,7 +80,7 @@ for file in */*.jou; do
echo -n "$(basename "$(dirname "$file")" | base64 -d):$(basename "$file" | cut -d'.' -f1): "

cp "$file" test.jou
if diff --text -u --color=always <(generate_expected_output test.jou | tr -d '\r') <( ("$jou" test.jou 2>&1 || true) | tr -d '\r'); then
if $DIFF --text -u $diff_color <(generate_expected_output test.jou | tr -d '\r') <( ("$jou" test.jou 2>&1 || true) | tr -d '\r'); then
echo "ok"
else
((nfail++)) || true
Expand Down
6 changes: 4 additions & 2 deletions examples/x11_window.jou
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# To run this program, you need linux:
# To run this program, you need a system with X11:
#
# Linux:
# $ ./jou --linker-flags "-lX11" examples/x11_window.jou
#
# NetBSD:
# $ ./jou --linker-flags "-L/usr/X11R7/lib -Wl,-R/usr/X11R7/lib -lX11" examples/x11_window.jou

declare usleep(x: int) -> int

Expand Down
28 changes: 20 additions & 8 deletions runtests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,25 @@ while [ $# != 0 ]; do
esac
done

if [ $valgrind = yes ] && [[ "$OS" =~ Windows ]]; then
echo "valgrind doesn't work on Windows." >&2
exit 2
if [ $valgrind = yes ]; then
case "${OS:=$(uname)}" in
Windows*|NetBSD*)
echo "valgrind doesn't work on $OS." >&2
exit 2
;;
esac
fi

if [ $run_make = yes ]; then
if [[ "$OS" =~ Windows ]]; then
source activate
mingw32-make
if [[ "${OS:=$(uname)}" =~ Windows ]]; then
source activate
mingw32-make
elif [[ "$OS" =~ NetBSD ]]; then
gmake
else
make
make
fi

fi

rm -rf tmp/tests
Expand Down Expand Up @@ -206,7 +213,12 @@ function run_test()

printf "\n\n\x1b[33m*** Command: %s ***\x1b[0m\n\n" "$command" > $diffpath

if diff --text -u --color=always <(
DIFF=$(which gdiff || which diff)
if $DIFF --help | grep -q -- --color; then
diff_color="--color=always"
fi

if $DIFF --text -u $diff_color <(
generate_expected_output $joufile $correct_exit_code | tr -d '\r'
) <(
export PATH="$PWD:$PATH"
Expand Down
4 changes: 3 additions & 1 deletion self_hosted/create_llvm_ir.jou
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,8 @@ class AstToIR:
name = "_jou_windows_startup"
elif MACOS:
name = "_jou_macos_startup"
elif NETBSD:
name = "_jou_netbsd_startup"
else:
return

Expand All @@ -817,7 +819,7 @@ class AstToIR:
self->llvm_function = self->declare_function(sig)
self->new_block("start")

if (WINDOWS or MACOS) and strcmp(sig->name, "main") == 0 and not sig->is_method():
if (WINDOWS or MACOS or NETBSD) and strcmp(sig->name, "main") == 0 and not sig->is_method():
self->call_the_special_startup_function()

# Allocate all local variables at the start of the function.
Expand Down
3 changes: 3 additions & 0 deletions self_hosted/main.jou
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ class Compiler:
if MACOS:
self->automagic_files[1] = malloc(strlen(self->stdlib_path) + 40)
sprintf(self->automagic_files[1], "%s/_macos_startup.jou", self->stdlib_path)
if NETBSD:
self->automagic_files[1] = malloc(strlen(self->stdlib_path) + 40)
sprintf(self->automagic_files[1], "%s/_netbsd_startup.jou", self->stdlib_path)

def parse_all_files(self) -> None:
queue: ParseQueueItem* = malloc(50 * sizeof queue[0])
Expand Down
10 changes: 6 additions & 4 deletions src/codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -414,14 +414,16 @@ static int find_block(const CfGraph *cfg, const CfBlock *b)
assert(0);
}

#if defined(_WIN32) || defined(__APPLE__)
#if defined(_WIN32) || defined(__APPLE__) || defined(__NetBSD__)
static void codegen_call_to_the_special_startup_function(const struct State *st)
{
const char *name;
#ifdef _WIN32
#if defined _WIN32
name = "_jou_windows_startup";
#else
#elif defined __APPLE__
name = "_jou_macos_startup";
#else
name = "_jou_netbsd_startup";
#endif

LLVMTypeRef functype = LLVMFunctionType(LLVMVoidType(), NULL, 0, false);
Expand All @@ -448,7 +450,7 @@ static void codegen_function_or_method_def(struct State *st, const CfGraph *cfg)
assert(cfg->all_blocks.ptr[0] == &cfg->start_block);
LLVMPositionBuilderAtEnd(st->builder, blocks[0]);

#if defined(_WIN32) || defined(__APPLE__)
#if defined(_WIN32) || defined(__APPLE__) || defined(__NetBSD__)
if (!get_self_class(&cfg->signature) && !strcmp(cfg->signature.name, "main"))
codegen_call_to_the_special_startup_function(st);
#endif
Expand Down
7 changes: 7 additions & 0 deletions src/evaluate.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ int get_special_constant(const char *name)
return 0;
#endif
}
if (!strcmp(name, "NETBSD")) {
#ifdef __NetBSD__
return 1;
#else
return 0;
#endif
}
return -1;
}

Expand Down
4 changes: 4 additions & 0 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,10 @@ int main(int argc, char **argv)
#ifdef __APPLE__
include_special_stdlib_file(&compst, "_macos_startup.jou");
#endif
#ifdef __NetBSD__
assert(sizeof(FILE) == 152);
include_special_stdlib_file(&compst, "_netbsd_startup.jou");
#endif

parse_file(&compst, command_line_args.infile, NULL);
parse_all_pending_files(&compst);
Expand Down
10 changes: 8 additions & 2 deletions src/update.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
#include <stdnoreturn.h>
#include "util.h"

#ifdef __NetBSD__
#define MAKE "gmake"
#else
#define MAKE "make"
#endif

static noreturn void fail()
{
char *s =
Expand Down Expand Up @@ -60,8 +66,8 @@ void update_jou_compiler()
if (system("powershell -ExecutionPolicy bypass -File update.ps1") != 0)
fail();
#else
confirm("Run \"git pull && make\"?");
if (system("git pull && make"))
confirm("Run \"git pull && "MAKE" \"?");
if (system("git pull && " MAKE))
fail();
#endif

Expand Down
23 changes: 23 additions & 0 deletions stdlib/_netbsd_startup.jou
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# A call to the _jou_netbsd_startup() function is inserted to the
# start of every Jou program when compiling for NetBSD.

# On NetBSD, these std* things are macros
# expanding to elements of the __sF array
# of FILE structs.

declare global __sF: byte[152][3] # sizeof(FILE) == 152
global stdin: void*
global stdout: void*
global stderr: void*

def _jou_netbsd_startup() -> None:
stdin = &__sF[0]
stdout = &__sF[1]
stderr = &__sF[2]

# Jou uses __errno_location,
# NetBSD has __ernno()

declare __errno() -> int*
def __errno_location() -> int*:
return __errno()
Loading

0 comments on commit 116e41f

Please sign in to comment.