Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 16 additions & 34 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,6 @@ jobs:
build_system: cmake-clang-cl
cmake_generator: Visual Studio 17 2022

- target: windows
architecture: 32
ffmpeg_url: https://github.com/HaxeFoundation/hashlink/files/5648055/ffmpeg-3.4.2-win32-dev.zip
architecture_string: Win32

- target: windows
architecture: 64
ffmpeg_url: https://github.com/HaxeFoundation/hashlink/files/5648056/ffmpeg-3.4.2-win64-dev.zip
Expand Down Expand Up @@ -326,23 +321,21 @@ jobs:
${{ env.WINDOWS_BUILD_FOLDER }}/hl.exe --version
;;
make*)
if [[ ${{ matrix.architecture }} != arm64 ]]; then
./hl --version
case ${{ matrix.target }} in
linux) ldd -v ./hl ;;
darwin) otool -L ./hl ;;
esac

haxe -hl hello.hl -cp other/tests -main HelloWorld -D interp \
${{ matrix.architecture == 32 && '-D hl-legacy32' || '' }}
./hl hello.hl

# ensure the executable still works when installed globally
cp hello.hl /tmp
pushd /tmp
hl hello.hl
popd
fi
./hl --version
case ${{ matrix.target }} in
linux) ldd -v ./hl ;;
darwin) otool -L ./hl ;;
esac

haxe -hl hello.hl -cp other/tests -main HelloWorld -D interp \
${{ matrix.architecture == 32 && '-D hl-legacy32' || '' }}
./hl hello.hl

# ensure the executable still works when installed globally
cp hello.hl /tmp
pushd /tmp
hl hello.hl
popd

haxe -hl src/_main.c -cp other/tests -main HelloWorld
make hlc
Expand Down Expand Up @@ -431,12 +424,6 @@ jobs:
os: [darwin, linux, windows]
architecture: [x86_64, arm64]
include:
- architecture: arm64
test-flags: --skip-hl-jit # not yet supported

- architecture: x86_32
test-flags: --skip-hl-jit --msbuild-platform x86 -D hlgen.build.architecture=x86_32 # not stable

- os: linux
runner: ubuntu-latest

Expand Down Expand Up @@ -511,12 +498,7 @@ jobs:
tar -xvzf hashlink-*.tar.gz
cd $(echo hashlink-*/)
sudo mkdir -p /usr/local/{bin,lib,include}
if [[ "${{ matrix.architecture }}" == "arm64" ]]; then
printf "#!/bin/sh\necho Jit is not supported on arm64\n" > /usr/local/bin/hl
chmod +x /usr/local/bin/hl
else
sudo cp hl /usr/local/bin/
fi
sudo cp hl /usr/local/bin/
sudo cp libhl.* *.hdll /usr/local/lib/
sudo cp include/* /usr/local/include/

Expand Down
10 changes: 8 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ include(FindPkgConfig)
include(CTest)

set(WITH_VM_DEFAULT ON)
if(CMAKE_SYSTEM_PROCESSOR MATCHES "arm|aarch64" AND (NOT CMAKE_OSX_ARCHITECTURES MATCHES "x86_64"))
# 32-bit ARM has no JIT backend; aarch64/arm64 uses src/jit_aarch64.c.
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm$|^armv[0-9]" AND (NOT CMAKE_OSX_ARCHITECTURES MATCHES "x86_64"))
set(WITH_VM_DEFAULT OFF)
endif()

Expand Down Expand Up @@ -225,12 +226,17 @@ else()
endif()

if (WITH_VM)
if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64|ARM64")
set(HL_JIT_BACKEND src/jit_aarch64.c src/jit_aarch64_emit.c)
else()
set(HL_JIT_BACKEND src/jit_x86_64.c)
endif()
add_executable(hl
src/code.c
src/jit.c
src/jit_emit.c
src/jit_regs.c
src/jit_x86_64.c
${HL_JIT_BACKEND}
src/jit_dump.c
src/main.c
src/module.c
Expand Down
21 changes: 8 additions & 13 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,13 @@ STD = src/std/array.o src/std/buffer.o src/std/bytes.o src/std/cast.o src/std/da
src/std/socket.o src/std/string.o src/std/sys.o src/std/types.o src/std/ucs2.o src/std/thread.o src/std/process.o \
src/std/track.o

HL_OBJ = src/code.o src/jit.o src/jit_emit.o src/jit_regs.o src/jit_x86_64.o src/jit_dump.o src/main.o src/module.o src/debugger.o src/profile.o
ifneq (,$(filter aarch64 arm64,$(ARCH)))
HL_JIT_BACKEND_OBJ = src/jit_aarch64.o src/jit_aarch64_emit.o
else
HL_JIT_BACKEND_OBJ = src/jit_x86_64.o
endif

HL_OBJ = src/code.o src/jit.o src/jit_emit.o src/jit_regs.o $(HL_JIT_BACKEND_OBJ) src/jit_dump.o src/main.o src/module.o src/debugger.o src/profile.o

FMT_CPPFLAGS = -I include/mikktspace -I include/minimp3

Expand Down Expand Up @@ -240,19 +246,12 @@ LIBHL = libhl.$(LIBEXT)
HL = hl$(EXE_SUFFIX)
HLC = hlc$(EXE_SUFFIX)

all: $(LIBHL) libs
ifeq ($(ARCH),arm64)
$(warning HashLink vm is not supported on arm64, skipping)
else
all: $(HL)
endif
all: $(LIBHL) libs $(HL)

install:
$(UNAME)==Darwin && ${MAKE} uninstall
ifneq ($(ARCH),arm64)
mkdir -p $(INSTALL_BIN_DIR)
cp $(HL) $(INSTALL_BIN_DIR)
endif
mkdir -p $(INSTALL_LIB_DIR)
cp *.hdll $(INSTALL_LIB_DIR)
cp $(LIBHL) $(INSTALL_LIB_DIR)
Expand Down Expand Up @@ -365,11 +364,7 @@ release_win:
rm -rf $(PACKAGE_NAME)

release_linux release_osx:
ifeq ($(ARCH),arm64)
cp $(LIBHL) *.hdll $(PACKAGE_NAME)
else
cp $(HL) $(LIBHL) *.hdll $(PACKAGE_NAME)
endif
tar -cvzf $(PACKAGE_NAME).tar.gz $(PACKAGE_NAME)
rm -rf $(PACKAGE_NAME)

Expand Down
30 changes: 29 additions & 1 deletion src/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
# include <sys/mman.h>
#endif

#if defined(__APPLE__) && defined(__aarch64__)
# include <pthread.h>
#endif

#if defined(HL_EMSCRIPTEN)
# include <emscripten/heap.h>
#endif
Expand Down Expand Up @@ -1151,11 +1155,35 @@ HL_PRIM void *hl_alloc_executable_memory( int size ) {
return NULL;
#else
void *p;
p = mmap(NULL,size,PROT_READ|PROT_WRITE|PROT_EXEC,(MAP_PRIVATE|MAP_ANONYMOUS),-1,0);
int flags = MAP_PRIVATE | MAP_ANONYMOUS;
# if defined(__APPLE__) && defined(__aarch64__)
// Apple Silicon requires MAP_JIT for W^X-protected JIT pages; the binary
// must also carry the com.apple.security.cs.allow-jit entitlement.
# ifndef MAP_JIT
# define MAP_JIT 0x800
# endif
flags |= MAP_JIT;
# endif
p = mmap(NULL,size,PROT_READ|PROT_WRITE|PROT_EXEC,flags,-1,0);
if( p == MAP_FAILED ) return NULL;
# if defined(__APPLE__) && defined(__aarch64__)
// Leave the caller's thread in write mode so it can populate the page;
// hl_flush_executable_memory flips back to exec when emission is done.
pthread_jit_write_protect_np(false);
# endif
return p;
#endif
}

HL_PRIM void hl_flush_executable_memory( void *code, int size ) {
#if defined(__GNUC__) || defined(__clang__)
__builtin___clear_cache((char*)code, (char*)code + size);
#endif
#if defined(__APPLE__) && defined(__aarch64__)
pthread_jit_write_protect_np(true);
#endif
}

HL_PRIM void hl_free_executable_memory( void *c, int size ) {
#if defined(HL_WIN)
VirtualFree(c,0,MEM_RELEASE);
Expand Down
1 change: 1 addition & 0 deletions src/hl.h
Original file line number Diff line number Diff line change
Expand Up @@ -824,6 +824,7 @@ HL_API void hl_global_lock( bool lock );

HL_API void *hl_alloc_executable_memory( int size );
HL_API void hl_free_executable_memory( void *ptr, int size );
HL_API void hl_flush_executable_memory( void *code, int size );

// ----------------------- BUFFER --------------------------------------------------

Expand Down
1 change: 1 addition & 0 deletions src/jit.c
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ void *hl_jit_code( jit_ctx *ctx, hl_module *m, int *codesize, hl_debug_infos **d
ctx->final_code = code;
hl_emit_final(ctx);
hl_codegen_final(ctx);
hl_flush_executable_memory(code, size);
arg_reg_count = ctx->cfg.regs.nargs;
arg_fp_count = ctx->cfg.floats.nargs;
call_jit_c2hl = ctx->final_code + ctx->code_funs.c2hl;
Expand Down
19 changes: 19 additions & 0 deletions src/jit.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,12 +187,31 @@ typedef struct {
ereg *arg;
} reg_config;

// HL→native stack-arg layout. HL→HL calls always use the HL convention
// (cfg.stack_arg_size stride, PUSH-based). HL→native calls follow the
// platform C ABI, which on AArch64 differs from HL's convention:
// - Linux/Windows AArch64 (AAPCS64): each stack arg occupies an 8-byte slot.
// - Apple ARM64: stack args are packed at their natural size with
// natural alignment.
typedef enum {
NATIVE_STACK_LAYOUT_HL = 0, // default: same as HL stride (x86_64, etc.)
NATIVE_STACK_LAYOUT_AAPCS64, // 8-byte slots (Linux/Win AArch64 native)
NATIVE_STACK_LAYOUT_APPLE_ARM64, // natural-size packed (Apple ARM64 native)
} native_stack_layout_kind;

typedef struct {
reg_config regs;
reg_config floats;
ereg stack_reg;
ereg stack_pos;
int stack_align;
// Minimum bytes consumed by each stack argument. Defaults to HL_WSIZE
// when 0. Backends like AArch64 set this to 16 because each PUSH must
// move SP by 16 bytes to keep SP 16-byte aligned (any [SP, ...] access
// with a misaligned SP traps under EL0).
int stack_arg_size;
// Layout for HL→native (CALL_PTR) stack args. See native_stack_layout_kind.
int native_stack_layout;
int debug_prefix_size;
ereg req_bit_shifts;
ereg req_div_a;
Expand Down
Loading