wasm: updates (LLVM+tools) (#8295)

* wasm: update wabt and binaryen in builder image
* wasm: bump ubuntu and llvm
* wasm: bump LLVM 13 -> 21, adjust headers
* wasm: make docker optional

We depend on it in our builds, but if you happen to bring

clang (LLVM 21)
clang++ (LLVM 21)
wasm-ld (LLVM 21)
wasm2wat (wabt)
wasm-opt (binaryen)
node

you should be able to build the opa.wasm blob without the docker image.


Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
This commit is contained in:
Stephan Renatus
2026-02-05 15:31:23 +01:00
committed by GitHub
parent b29b1dad76
commit 7c48e417ea
13 changed files with 722 additions and 732 deletions
File diff suppressed because one or more lines are too long
Binary file not shown.
+1 -1
View File
@@ -133,7 +133,7 @@ func (c *Compiler) removeUnusedCode() error {
} }
caller, ok := c.funcs[callerName] caller, ok := c.funcs[callerName]
if !ok { if !ok {
return fmt.Errorf("caller not found: %s (%s)", cg[i][0], callerName) continue // without a caller, it should get removed anyways (right?)
} }
callee, ok := c.funcs[calleeName] callee, ok := c.funcs[calleeName]
if !ok { if !ok {
+23 -23
View File
@@ -1,12 +1,12 @@
FROM ubuntu:20.04@sha256:0b897358ff6624825fb50d20ffb605ab0eaea77ced0adb8c6a4b756513dec6fc FROM ubuntu:24.04@sha256:80dd3c3b9c6cecb9f1667e9290b3bc61b78c2678c02cbdae5f0fea92cc6734ab
ARG WABT_VERSION=1.0.24 ARG WABT_VERSION=1.0.39
ARG BINARYEN_VERSION=version_102 ARG BINARYEN_VERSION=version_125
ARG DEBIAN_FRONTEND=noninteractive ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y curl git build-essential python RUN apt-get update && apt-get install -y curl git build-essential python3 python-is-python3
RUN bash -c 'echo -ne "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-13 main\ndeb-src http://apt.llvm.org/focal/ llvm-toolchain-focal-13 main" > /etc/apt/sources.list.d/llvm.list' RUN bash -c 'echo -ne "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-21 main\ndeb-src http://apt.llvm.org/noble/ llvm-toolchain-noble-21 main" > /etc/apt/sources.list.d/llvm.list'
RUN curl -L https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - RUN curl -L https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
@@ -14,21 +14,20 @@ RUN apt-get update && \
apt-get install -y \ apt-get install -y \
cmake \ cmake \
ninja-build \ ninja-build \
clang-13 \ clang-21 \
clang-format-13 \ clang-format-21 \
libc++-13-dev \ libc++-21-dev \
libc++abi-13-dev \ libc++abi-21-dev \
lld-13 && \ lld-21 && \
update-alternatives --install /usr/bin/ld ld /usr/bin/lld-13 90 && \ update-alternatives --install /usr/bin/ld ld /usr/bin/lld-21 90 && \
update-alternatives --install /usr/bin/cc cc /usr/bin/clang-13 90 && \ update-alternatives --install /usr/bin/cc cc /usr/bin/clang-21 90 && \
update-alternatives --install /usr/bin/cpp cpp /usr/bin/clang++-13 90 && \ update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-21 90
update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-13 90
RUN ln -s /usr/bin/clang-13 /usr/bin/clang && \ RUN ln -s /usr/bin/clang-21 /usr/bin/clang && \
ln -s /usr/bin/clang++-13 /usr/bin/clang++ && \ ln -s /usr/bin/clang++-21 /usr/bin/clang++ && \
ln -s /usr/bin/clang-format-13 /usr/bin/clang-format && \ ln -s /usr/bin/clang-format-21 /usr/bin/clang-format && \
ln -s /usr/bin/wasm-ld-13 /usr/bin/wasm-ld && \ ln -s /usr/bin/wasm-ld-21 /usr/bin/wasm-ld && \
ln -s /usr/bin/clang-cpp-13 /usr/bin/clang-cpp ln -s /usr/bin/clang-cpp-21 /usr/bin/clang-cpp
RUN git clone https://github.com/WebAssembly/wabt && \ RUN git clone https://github.com/WebAssembly/wabt && \
cd wabt && \ cd wabt && \
@@ -39,12 +38,13 @@ RUN git clone https://github.com/WebAssembly/wabt && \
RUN git clone https://github.com/WebAssembly/binaryen && \ RUN git clone https://github.com/WebAssembly/binaryen && \
cd binaryen && \ cd binaryen && \
git checkout $BINARYEN_VERSION && \ git checkout $BINARYEN_VERSION && \
cmake . && \ git submodule update --init && \
make cmake . -DBUILD_TESTS=OFF && \
make wasm-opt wasm-dis wasm-as
ENV PATH="/binaryen/bin:/wabt/out/clang/Debug:${PATH}" ENV PATH="/binaryen/bin:/wabt/out/clang/Debug:${PATH}"
ENV CC=clang-13 ENV CC=clang-21
ENV CXX=clang++-13 ENV CXX=clang++-21
WORKDIR /src WORKDIR /src
+46 -8
View File
@@ -1,16 +1,24 @@
DOCKER := docker DOCKER := docker
DOCKER_FLAGS := --rm -e DEBUG DOCKER_FLAGS := --rm -e DEBUG
DEBUG ?= 0 DEBUG ?= 0
USE_DOCKER ?= 1
ifeq ($(shell tty > /dev/null && echo 1 || echo 0), 1) ifeq ($(shell tty > /dev/null && echo 1 || echo 0), 1)
DOCKER_FLAGS += -it DOCKER_FLAGS += -it
endif endif
DOCKER_WASM_BUILDER_IMAGE ?= openpolicyagent/opa-wasm-builder DOCKER_WASM_BUILDER_IMAGE ?= openpolicyagent/opa-wasm-builder
WASM_BUILDER_VERSION := 1.6 WASM_BUILDER_VERSION := 1.7
WASM_BUILDER_IMAGE := $(DOCKER_WASM_BUILDER_IMAGE):$(WASM_BUILDER_VERSION) WASM_BUILDER_IMAGE := $(DOCKER_WASM_BUILDER_IMAGE):$(WASM_BUILDER_VERSION)
WASM_TEST_NODE_VERSION := lts
WASM_OBJ_DIR := _obj WASM_OBJ_DIR := _obj
# Set compilers for local builds when not using Docker
ifeq ($(USE_DOCKER), 0)
CC ?= clang
CXX ?= clang++
endif
CFLAGS += \ CFLAGS += \
-MD \ -MD \
-MP \ -MP \
@@ -19,7 +27,15 @@ CFLAGS += \
-I src/lib \ -I src/lib \
-I src/libmpdec \ -I src/libmpdec \
-DCONFIG_32 \ -DCONFIG_32 \
-DANSI -DANSI \
-mno-bulk-memory \
-mno-bulk-memory-opt \
-mno-multivalue \
-mno-reference-types \
-mno-nontrapping-fptoint \
-mno-sign-ext \
-mno-mutable-globals \
-mno-call-indirect-overlong
CPPFLAGS += \ CPPFLAGS += \
-std=c++17 \ -std=c++17 \
@@ -29,13 +45,24 @@ CPPFLAGS += \
--target=wasm32-unknown-unknown-wasm \ --target=wasm32-unknown-unknown-wasm \
-fno-exceptions \ -fno-exceptions \
-fno-rtti \ -fno-rtti \
-I src/lib \ -nostdinc++ \
-I src/libc++ \ -isystem src/libc++ \
-I /usr/lib/llvm-13/include/c++/v1 \ -isystem /usr/lib/llvm-21/include/c++/v1 \
-I /usr/lib/llvm-13/lib/clang/13.0.0/include \ -isystem /usr/lib/llvm-21/lib/clang/21.1.7/include \
-isystem src/lib \
-I src/re2 \ -I src/re2 \
-D_LIBCPP_HAS_NO_THREADS \ -D_LIBCPP_HAS_NO_THREADS \
-D_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION -D_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION \
-D_LIBCPP_HAS_NO_LOCALIZATION \
-D_LIBCPP_NO_EXCEPTIONS \
-mno-bulk-memory \
-mno-bulk-memory-opt \
-mno-multivalue \
-mno-reference-types \
-mno-nontrapping-fptoint \
-mno-sign-ext \
-mno-mutable-globals \
-mno-call-indirect-overlong
ifeq ($(DEBUG), 1) ifeq ($(DEBUG), 1)
CFLAGS += -O1 -gdwarf -DDEBUG CFLAGS += -O1 -gdwarf -DDEBUG
@@ -58,7 +85,9 @@ builder: Dockerfile
.PHONY: ensure-builder .PHONY: ensure-builder
ensure-builder: ensure-builder:
ifeq ($(USE_DOCKER), 1)
@$(DOCKER) inspect $(WASM_BUILDER_IMAGE) > /dev/null || $(DOCKER) pull $(WASM_BUILDER_IMAGE) || $(MAKE) builder @$(DOCKER) inspect $(WASM_BUILDER_IMAGE) > /dev/null || $(DOCKER) pull $(WASM_BUILDER_IMAGE) || $(MAKE) builder
endif
.PHONY: push-builder .PHONY: push-builder
push-builder: push-builder:
@@ -66,13 +95,22 @@ push-builder:
.PHONY: build .PHONY: build
build: build:
ifeq ($(USE_DOCKER), 1)
@$(DOCKER) run $(DOCKER_FLAGS) -v $(CURDIR):/src:Z $(WASM_BUILDER_IMAGE) \ @$(DOCKER) run $(DOCKER_FLAGS) -v $(CURDIR):/src:Z $(WASM_BUILDER_IMAGE) \
make --no-builtin-rules $(WASM_OBJ_DIR)/opa.wasm $(WASM_OBJ_DIR)/callgraph.csv make --no-builtin-rules $(WASM_OBJ_DIR)/opa.wasm $(WASM_OBJ_DIR)/callgraph.csv
else
@$(MAKE) --no-builtin-rules $(WASM_OBJ_DIR)/opa.wasm $(WASM_OBJ_DIR)/callgraph.csv
endif
.PHONY: test .PHONY: test
test: test:
ifeq ($(USE_DOCKER), 1)
@$(DOCKER) run $(DOCKER_FLAGS) -v $(CURDIR):/src:Z $(WASM_BUILDER_IMAGE) make $(WASM_OBJ_DIR)/opa-test.wasm @$(DOCKER) run $(DOCKER_FLAGS) -v $(CURDIR):/src:Z $(WASM_BUILDER_IMAGE) make $(WASM_OBJ_DIR)/opa-test.wasm
@$(DOCKER) run $(DOCKER_FLAGS) -e VERBOSE -v $(CURDIR):/src:Z -w /src node:14 node test.js $(WASM_OBJ_DIR)/opa-test.wasm @$(DOCKER) run $(DOCKER_FLAGS) -e VERBOSE -v $(CURDIR):/src:Z -w /src node:$(WASM_TEST_NODE_VERSION) node test.js $(WASM_OBJ_DIR)/opa-test.wasm
else
@$(MAKE) $(WASM_OBJ_DIR)/opa-test.wasm
@node test.js $(WASM_OBJ_DIR)/opa-test.wasm
endif
.PHONY: hack .PHONY: hack
hack: hack:
+11 -4
View File
@@ -14,6 +14,13 @@ double log10(double x);
// not implemented: // not implemented:
#define INFINITY (__builtin_inff()) #define INFINITY (__builtin_inff())
#define NAN (__builtin_nanf(""))
#define FP_NAN 0
#define FP_INFINITE 1
#define FP_ZERO 2
#define FP_SUBNORMAL 3
#define FP_NORMAL 4
double acos(double x); double acos(double x);
float acosf(float x); float acosf(float x);
@@ -242,15 +249,15 @@ float truncf(float x);
long double truncl(long double x); long double truncl(long double x);
int fpclassify(float x); int fpclassify(float x);
int isfinite(float x); // int isfinite(float x); // Conflicts with LLVM 21 libc++
int isgreater(float x, float y); int isgreater(float x, float y);
int isgreaterequal(float x, float y); int isgreaterequal(float x, float y);
int isinf(float x); // int isinf(float x); // Conflicts with LLVM 21 libc++
int isless(float x, float y); int isless(float x, float y);
int islessequal(float x, float y); int islessequal(float x, float y);
int islessgreater(float x, float y); int islessgreater(float x, float y);
int isnan(float x); // int isnan(float x); // Conflicts with LLVM 21 libc++
int isnormal(float x); // int isnormal(float x); // Conflicts with LLVM 21 libc++
int isunordered(float x, float y); int isunordered(float x, float y);
int signbit(float x); int signbit(float x);
+1 -1
View File
@@ -1,7 +1,7 @@
#ifndef OPA_WCTYPE_H #ifndef OPA_WCTYPE_H
#define OPA_WCTYPE_H #define OPA_WCTYPE_H
#include <stddef.h> #include "wchar.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
+11
View File
@@ -0,0 +1,11 @@
#ifndef _LIBCPP_CONFIG_SITE
#define _LIBCPP_CONFIG_SITE
#define _LIBCPP_HAS_NO_THREADS
#define _LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION
#define _LIBCPP_HAS_NO_LOCALIZATION
#define _LIBCPP_HAS_NO_MONOTONIC_CLOCK
#define _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS
#define _LIBCPP_HARDENING_MODE_DEFAULT _LIBCPP_HARDENING_MODE_NONE
#endif // _LIBCPP_CONFIG_SITE
+16
View File
@@ -0,0 +1,16 @@
#ifndef _LIBCPP_THREADING_SUPPORT
#define _LIBCPP_THREADING_SUPPORT
#define _LIBCPP_HAS_THREAD_API_EXTERNAL
namespace std {
namespace __libcpp_thread_api {
// No-op threading stubs for WASM
inline void __libcpp_thread_yield() {}
inline void __libcpp_thread_sleep_for(int) {}
} // namespace __libcpp_thread_api
} // namespace std
#endif // _LIBCPP_THREADING_SUPPORT
-32
View File
@@ -1,32 +0,0 @@
#ifndef OPA_ATOMIC_H_
#define OPA_ATOMIC_H_
namespace std {
enum {
memory_order_relaxed,
memory_order_acquire,
memory_order_release,
};
// this is a minimal, no-op implementation of std::atomic.
template <typename T>
class atomic {
public:
atomic() : value(NULL) { }
atomic(T v) : value(v) { }
inline T load(int order) const {
return value;
}
inline void store(T v, int order) {
value = v;
}
private:
T value;
};
}
#endif // OPA_ATOMIC_H_
+31 -4
View File
@@ -149,8 +149,7 @@ const unsigned indices[] =
// against. // against.
template <size_t _Sz = sizeof(size_t)> template <size_t _Sz = sizeof(size_t)>
inline _LIBCPP_INLINE_VISIBILITY inline typename enable_if<_Sz == 4, void>::type
typename enable_if<_Sz == 4, void>::type
__check_for_overflow(size_t N) __check_for_overflow(size_t N)
{ {
if (N > 0xFFFFFFFB) if (N > 0xFFFFFFFB)
@@ -158,8 +157,7 @@ __check_for_overflow(size_t N)
} }
template <size_t _Sz = sizeof(size_t)> template <size_t _Sz = sizeof(size_t)>
inline _LIBCPP_INLINE_VISIBILITY inline typename enable_if<_Sz == 8, void>::type
typename enable_if<_Sz == 8, void>::type
__check_for_overflow(size_t N) __check_for_overflow(size_t N)
{ {
if (N > 0xFFFFFFFFFFFFFFC5ull) if (N > 0xFFFFFFFFFFFFFFC5ull)
@@ -558,4 +556,33 @@ next:
} }
} }
// Provide __hash_memory function for LLVM 21
[[__gnu__::__pure__]] size_t __hash_memory(_LIBCPP_NOESCAPE const void* __data, size_t __len) noexcept {
const unsigned char* __p = static_cast<const unsigned char*>(__data);
size_t __hash = 2166136261U; // FNV-1a 32-bit offset basis
for (size_t __i = 0; __i < __len; ++__i) {
__hash ^= __p[__i];
__hash *= 16777619U; // FNV-1a 32-bit prime
}
return __hash;
}
// Provide a simple sort implementation for small int arrays
template<typename _Compare, typename _RandomAccessIterator>
void __sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
// Simple bubble sort for small arrays
for (auto __i = __first; __i != __last; ++__i) {
for (auto __j = __i + 1; __j != __last; ++__j) {
if (*__j < *__i) { // Direct comparison for int
auto __tmp = *__i;
*__i = *__j;
*__j = __tmp;
}
}
}
}
// Explicit instantiation for the needed signature
template void __sort<__less<int, int>&, int*>(int*, int*, __less<int, int>&);
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
+16 -10
View File
@@ -13,6 +13,10 @@ void operator delete(void *p) {
opa_free(p); opa_free(p);
} }
void operator delete(void *p, size_t) {
opa_free(p);
}
void* operator new[](size_t size) { void* operator new[](size_t size) {
return opa_malloc(size); return opa_malloc(size);
} }
@@ -21,22 +25,24 @@ void operator delete[](void *p) {
opa_free(p); opa_free(p);
} }
void operator delete[](void *p, size_t) {
opa_free(p);
}
extern "C" void __cxa_pure_virtual() { extern "C" void __cxa_pure_virtual() {
opa_abort("pure virtual"); opa_abort("pure virtual");
} }
// LLVM 21 verbose abort handler
_LIBCPP_BEGIN_NAMESPACE_STD
void __libcpp_verbose_abort(const char *format, ...) noexcept {
opa_abort(format);
}
_LIBCPP_END_NAMESPACE_STD
// Instantiate the minimum set of templates part of standard libc++ ABI. // Instantiate the minimum set of templates part of standard libc++ ABI.
// This is required because we do not link with the libc++. // This is required because we do not link with the libc++.
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
template class basic_string<char>;
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __basic_string_common<true>;
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_string<char>;
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_string<wchar_t>;
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __vector_base_common<true>;
template void __sort<__less<int>&, int*>(int*, int*, __less<int>&);
template bool __insertion_sort_incomplete<__less<int>&, int*>(int*, int*, __less<int>&);
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
+3 -2
View File
@@ -7,6 +7,7 @@
#include "util/utf.h" #include "util/utf.h"
#include <unordered_map> #include <unordered_map>
#include <vector>
static const int MAX_CACHE_SIZE = 100; static const int MAX_CACHE_SIZE = 100;
@@ -123,7 +124,7 @@ opa_value *opa_regex_find_all_string_submatch(opa_value *pattern, opa_value *val
std::string val(opa_cast_string(value)->v, opa_cast_string(value)->len); std::string val(opa_cast_string(value)->v, opa_cast_string(value)->len);
opa_array_t *result = opa_cast_array(opa_array()); opa_array_t *result = opa_cast_array(opa_array());
int nsubmatch = re->NumberOfCapturingGroups() + 1; int nsubmatch = re->NumberOfCapturingGroups() + 1;
re2::StringPiece submatches[nsubmatch]; std::vector<re2::StringPiece> submatches(nsubmatch);
// The following is effectively refactored RE2::GlobalReplace: // The following is effectively refactored RE2::GlobalReplace:
@@ -134,7 +135,7 @@ opa_value *opa_regex_find_all_string_submatch(opa_value *pattern, opa_value *val
int pos = 0; int pos = 0;
while (p <= ep && (num_results == -1 || result->len < num_results)) { while (p <= ep && (num_results == -1 || result->len < num_results)) {
if (!re->Match(val, static_cast<size_t>(p - beginpos), val.size(), re2::RE2::UNANCHORED, submatches, nsubmatch)) if (!re->Match(val, static_cast<size_t>(p - beginpos), val.size(), re2::RE2::UNANCHORED, submatches.data(), nsubmatch))
{ {
break; break;
} }