Skip to content
Merged
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
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ if(SOURCEMETA_CORE_CRYPTO)
endif()

if(SOURCEMETA_CORE_REGEX)
find_package(SLJIT REQUIRED)
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
find_package(PCRE2 REQUIRED)
add_subdirectory(src/core/regex)
endif()
Expand Down
1 change: 1 addition & 0 deletions DEPENDENCIES
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ uritemplate-test https://github.com/uri-templates/uritemplate-test 1eb27ab4462b9
pyca-cryptography https://github.com/pyca/cryptography 9747d06e83764e7f1ea4c04daf134cb8f861700b
wycheproof https://github.com/C2SP/wycheproof 6d7cccd0fcb1917368579adeeac10fe802f1b521
pcre2 https://github.com/PCRE2Project/pcre2 pcre2-10.48
sljit https://github.com/zherczeg/sljit 3908d4c1d46764b7f86e172411e28cec3d0d601c
unicodetools https://github.com/unicode-org/unicodetools final-17.0-20250910
jose-cookbook https://github.com/ietf-jose/cookbook 13692b68bfc18b99557a5b1ed311fd5077bfff04
w3c-json-ld https://github.com/w3c/json-ld-api 8654ac22b6cf4f441d2fee915ae634d36b5a8067
Expand Down
8 changes: 6 additions & 2 deletions cmake/FindPCRE2.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@ if(NOT PCRE2_FOUND)
add_library(pcre2 OBJECT ${PCRE2_SOURCES})
sourcemeta_add_default_options(PRIVATE pcre2)

# The code generator that the just-in-time compiler drives is a dependency
# of its own, which the caller is expected to have satisfied by now
# Public, as the translation unit that drives the code generator has to see
# the configuration it was built with to agree on its structure layouts
target_link_libraries(pcre2 PUBLIC SLJIT::sljit)

if(SOURCEMETA_COMPILER_LLVM OR SOURCEMETA_COMPILER_GCC)
target_compile_options(pcre2 PRIVATE -Wno-implicit-int-conversion)
target_compile_options(pcre2 PRIVATE -Wno-sign-conversion)
Expand Down Expand Up @@ -126,8 +132,6 @@ if(NOT PCRE2_FOUND)
target_compile_definitions(pcre2 PUBLIC PCRE2_CODE_UNIT_WIDTH=8)
target_compile_definitions(pcre2 PRIVATE SUPPORT_PCRE2_8=1)
target_compile_definitions(pcre2 PRIVATE SUPPORT_UNICODE=1)
# The just-in-time compiler brings its own code generator in as part of one
# of its translation units, so there is no second library to build for it
target_compile_definitions(pcre2 PRIVATE SUPPORT_JIT=1)
# Declarations of an import from a shared library of our own build of this
# one, which no longer exists, would be unresolvable on Windows
Expand Down
44 changes: 44 additions & 0 deletions cmake/FindSLJIT.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
if(NOT SLJIT_FOUND)
set(SLJIT_DIR "${PROJECT_SOURCE_DIR}/vendor/sljit")
set(SLJIT_SOURCE_DIR "${SLJIT_DIR}/sljit_src")

# This library ships one source that includes every backend and allocator
# that the target architecture and platform select
# Merged into the library that uses it, so that no archive, no header and
# no CMake package of our own build of it reaches an installed consumer
add_library(sljit OBJECT "${SLJIT_SOURCE_DIR}/sljitLir.c")
sourcemeta_add_default_options(PRIVATE sljit)

# The compiler structure that this library hands out grows extra members
# under any of the tracing, argument checking, or debugging options, so
# every translation unit that reaches for the header has to be told the
# same configuration that the library itself was built with
target_compile_definitions(sljit PUBLIC SLJIT_CONFIG_AUTO=1)
target_compile_definitions(sljit PUBLIC SLJIT_VERBOSE=0)
target_compile_definitions(sljit PUBLIC SLJIT_DEBUG=0)

if(SOURCEMETA_COMPILER_LLVM OR SOURCEMETA_COMPILER_GCC)
# Generated code accumulates into a trailing single-element array that is
# over-allocated and written well past its first element, so the strictest
# interpretation of what counts as a trailing flexible array would treat
# every byte this library emits as running off the end of the object
target_compile_options(sljit PRIVATE -fstrict-flex-arrays=0)
endif()

if(SOURCEMETA_COMPILER_LLVM)
# The immediate byte of a vector lane instruction is only read back on the
# paths that set it, which the compiler cannot correlate
target_compile_options(sljit PRIVATE -Wno-conditional-uninitialized)
endif()

if(SOURCEMETA_COMPILER_MSVC)
target_compile_options(sljit PRIVATE /wd4701)
endif()

target_include_directories(sljit PUBLIC
"$<BUILD_INTERFACE:${SLJIT_SOURCE_DIR}>")

add_library(SLJIT::sljit ALIAS sljit)

set(SLJIT_FOUND ON)
endif()
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Juan Cruz Viotti <jviotti@sourcemeta.com>
Date: Wed, 24 Sep 2026 12:00:00 -0300
Subject: [PATCH] Link the JIT code generator instead of including its source

This file textually included the whole of sljitLir.c, which compiled the
code generator into this translation unit with internal linkage and routed
its allocations through the pcre2 general context. That makes it impossible
to treat the code generator as a dependency of its own, or to reuse it from
anywhere else in the tree.

Include the public header instead and let the build system compile and link
the code generator separately. The configuration macros that change the
layout of struct sljit_compiler now come from the build system, so that both
sides of the interface agree on them, and the code generator falls back to
its own malloc and free rather than the pcre2 general context allocator.

SSIZE_OF is the one name this file needs that the code generator keeps in
its implementation rather than its header. It takes a parameter, so the
build system cannot carry it as a definition, and it is reproduced here.
---
src/pcre2_jit_compile.c | 35 ++++++++---------------------------
1 file changed, 8 insertions(+), 27 deletions(-)

diff --git a/src/pcre2_jit_compile.c b/src/pcre2_jit_compile.c
index 105a1dd35..de3f03133 100644
--- a/src/pcre2_jit_compile.c
+++ b/src/pcre2_jit_compile.c
@@ -49,36 +49,17 @@ POSSIBILITY OF SUCH DAMAGE.

#ifdef SUPPORT_JIT

-/* All-in-one: Since we use the JIT compiler only from here,
-we just include it. This way we don't need to touch the build
-system files. */
+/* The JIT code generator is built as a library of its own, and the build
+system sets its configuration on both sides of the interface, so that this
+translation unit and that library agree on the layout of the structures they
+pass between them. */

-#define SLJIT_CONFIG_AUTO 1
-#define SLJIT_CONFIG_STATIC 1
-#define SLJIT_VERBOSE 0
+#include "sljitLir.h"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Including sljitLir.h makes the JIT's SLJIT_MALLOC/FREE macros ignore &re->memctl and call libc allocation directly. This breaks PCRE2's custom allocator contract for JIT compilation; preserve the allocator hook when separating SLJIT.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At patches/pcre2/0001-Link-the-JIT-code-generator-instead-of-including-its.patch, line 44:

<comment>Including `sljitLir.h` makes the JIT's `SLJIT_MALLOC/FREE` macros ignore `&re->memctl` and call libc allocation directly. This breaks PCRE2's custom allocator contract for JIT compilation; preserve the allocator hook when separating SLJIT.</comment>

<file context>
@@ -0,0 +1,73 @@
+-#define SLJIT_CONFIG_AUTO 1
+-#define SLJIT_CONFIG_STATIC 1
+-#define SLJIT_VERBOSE 0
++#include "sljitLir.h"
+ 
+-#ifdef PCRE2_DEBUG
</file context>


-#ifdef PCRE2_DEBUG
-#define SLJIT_DEBUG 1
-#else
-#define SLJIT_DEBUG 0
-#endif
+/* A convenience that the code generator keeps private to its implementation,
+reproduced here in terms of the types that its header does publish. */

-#define SLJIT_MALLOC(size, allocator_data) pcre2_jit_malloc(size, allocator_data)
-#define SLJIT_FREE(ptr, allocator_data) pcre2_jit_free(ptr, allocator_data)
-
-static void * pcre2_jit_malloc(size_t size, void *allocator_data)
-{
-pcre2_memctl *allocator = ((pcre2_memctl*)allocator_data);
-return allocator->malloc(size, allocator->memory_data);
-}
-
-static void pcre2_jit_free(void *ptr, void *allocator_data)
-{
-pcre2_memctl *allocator = ((pcre2_memctl*)allocator_data);
-allocator->free(ptr, allocator->memory_data);
-}
-
-#include "../deps/sljit/sljit_src/sljitLir.c"
+#define SSIZE_OF(type) ((sljit_s32)sizeof(sljit_ ## type))

#if defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED
#error Unsupported architecture
5 changes: 5 additions & 0 deletions src/core/regex/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ if(SOURCEMETA_CORE_INSTALL)
sourcemeta_library_install(NAMESPACE sourcemeta PROJECT core NAME regex)
endif()

# An object library hands its objects to the targets that name it, and a
# second object library in between only passes on usage requirements, so the
# code generator has to be named here rather than left to the library that
# actually calls into it
target_link_libraries(sourcemeta_core_regex PRIVATE SLJIT::sljit)
target_link_libraries(sourcemeta_core_regex PRIVATE PCRE2::pcre2)
target_link_libraries(sourcemeta_core_regex PRIVATE sourcemeta::core::text)
target_link_libraries(sourcemeta_core_regex PRIVATE sourcemeta::core::unicode)
11 changes: 1 addition & 10 deletions vendor/pcre2.mask

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 8 additions & 27 deletions vendor/pcre2/src/pcre2_jit_compile.c

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions vendor/sljit.mask

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

File renamed without changes.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading