Skip to content

Commit

Permalink
Add experimental support for NetBSD
Browse files Browse the repository at this point in the history
Compile against libLLVM installed as a package.
  • Loading branch information
taahol committed Feb 16, 2024
1 parent 9e53ffe commit 0ac3e1f
Show file tree
Hide file tree
Showing 16 changed files with 120 additions and 24 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 \"$(shell which `$(LLVM_CONFIG) --bindir`/clang || which clang)\"" >> 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 \"$(shell which `$(LLVM_CONFIG) --bindir`/clang || which clang)\"" >> config.jou

self_hosted_compiler: jou config.jou $(wildcard self_hosted/*.jou)
./jou -o $@ --linker-flags "$(LDFLAGS)" self_hosted/main.jou
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,12 @@ MacOS support is new. Please create an issue if something doesn't work.
</details>
<details> <summary>NetBSD</summary>
Additionally, there is support for NetBSD on an experimental
basis. Packages `clang`, `libLLVM`, `gmake` and `bash` are required.
</details>
## Updating to the latest version of Jou
Expand Down
11 changes: 8 additions & 3 deletions compare_compilers.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,18 @@ if [ ${#actions[@]} = 0 ]; then
fi

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

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

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

function append_line()
{
local file="$1"
Expand Down Expand Up @@ -87,7 +92,7 @@ echo "Compiling the self-hosted compiler..."
if [[ "$OS" =~ Windows ]]; then
mingw32-make self_hosted_compiler.exe
else
make self_hosted_compiler
$(which gmake || which make) self_hosted_compiler
fi

for file in ${files[@]}; do
Expand Down Expand Up @@ -126,7 +131,7 @@ for action in ${actions[@]}; do
echo " Compilers behave differently as expected (listed in $error_list_file)"
fi
else
if diff -u --color=always tmp/compare_compilers/compiler_written_in_c.txt tmp/compare_compilers/self_hosted.txt; then
if $DIFF -u $diff_color tmp/compare_compilers/compiler_written_in_c.txt tmp/compare_compilers/self_hosted.txt; then
echo " Compilers behave the same as expected"
else
if [ $fix = yes ]; then
Expand Down
9 changes: 7 additions & 2 deletions doctest.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,15 @@ if [[ "$OS" =~ Windows ]]; then
mingw32-make
jou="$PWD/jou.exe"
else
make
eval $(which gmake || which make)
jou="$PWD/jou"
fi

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

function slice()
{
local first_lineno="$1"
Expand Down Expand Up @@ -71,7 +76,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
19 changes: 14 additions & 5 deletions runtests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,21 @@ 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
else
make
eval $(which gmake || which make)
fi
fi

Expand Down Expand Up @@ -206,7 +210,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 [[ x"$($DIFF --help | grep -- --color)" != x ]]; 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
3 changes: 3 additions & 0 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,9 @@ int main(int argc, char **argv)
#ifdef __APPLE__
include_special_stdlib_file(&compst, "_macos_startup.jou");
#endif
#ifdef __NetBSD__
include_special_stdlib_file(&compst, "_netbsd_startup.jou");
#endif

parse_file(&compst, command_line_args.infile, NULL);
parse_all_pending_files(&compst);
Expand Down
2 changes: 1 addition & 1 deletion src/update.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ void update_jou_compiler()
fail();
#else
confirm("Run \"git pull && make\"?");
if (system("git pull && make"))
if (system("git pull && `which gmake || which make`"))
fail();
#endif

Expand Down
22 changes: 22 additions & 0 deletions stdlib/_netbsd_startup.jou
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# 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

declare global __sF: byte[152][3]
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()
2 changes: 1 addition & 1 deletion tests/should_succeed/compiler_cli.jou
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def main() -> int:

# Compile a GUI program
if not (WINDOWS or MACOS):
ret = system("./jou -o /dev/null --linker-flags \"-lX11\" examples/x11_window.jou")
ret = system("./jou -o /dev/null --linker-flags \"-L/usr/X11R7/lib -lX11\" examples/x11_window.jou")
assert ret == 0

# Compile a program with a memory leak.
Expand Down
2 changes: 1 addition & 1 deletion tests/should_succeed/file.jou
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ def write_hello_123() -> None:
f = fopen("tmp/tests/hello.txt", "w")
if f == NULL:
printf("can't write tmp/tests/hello.txt\n")
abort()
exit(1) # abort() would make a core dump when comparing compilers

fputc('h', f)
fputs("ell", f)
Expand Down

0 comments on commit 0ac3e1f

Please sign in to comment.