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]
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]
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 BINARYEN_VERSION=version_102
ARG WABT_VERSION=1.0.39
ARG BINARYEN_VERSION=version_125
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 -
@@ -14,21 +14,20 @@ RUN apt-get update && \
apt-get install -y \
cmake \
ninja-build \
clang-13 \
clang-format-13 \
libc++-13-dev \
libc++abi-13-dev \
lld-13 && \
update-alternatives --install /usr/bin/ld ld /usr/bin/lld-13 90 && \
update-alternatives --install /usr/bin/cc cc /usr/bin/clang-13 90 && \
update-alternatives --install /usr/bin/cpp cpp /usr/bin/clang++-13 90 && \
update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-13 90
clang-21 \
clang-format-21 \
libc++-21-dev \
libc++abi-21-dev \
lld-21 && \
update-alternatives --install /usr/bin/ld ld /usr/bin/lld-21 90 && \
update-alternatives --install /usr/bin/cc cc /usr/bin/clang-21 90 && \
update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-21 90
RUN ln -s /usr/bin/clang-13 /usr/bin/clang && \
ln -s /usr/bin/clang++-13 /usr/bin/clang++ && \
ln -s /usr/bin/clang-format-13 /usr/bin/clang-format && \
ln -s /usr/bin/wasm-ld-13 /usr/bin/wasm-ld && \
ln -s /usr/bin/clang-cpp-13 /usr/bin/clang-cpp
RUN ln -s /usr/bin/clang-21 /usr/bin/clang && \
ln -s /usr/bin/clang++-21 /usr/bin/clang++ && \
ln -s /usr/bin/clang-format-21 /usr/bin/clang-format && \
ln -s /usr/bin/wasm-ld-21 /usr/bin/wasm-ld && \
ln -s /usr/bin/clang-cpp-21 /usr/bin/clang-cpp
RUN git clone https://github.com/WebAssembly/wabt && \
cd wabt && \
@@ -39,12 +38,13 @@ RUN git clone https://github.com/WebAssembly/wabt && \
RUN git clone https://github.com/WebAssembly/binaryen && \
cd binaryen && \
git checkout $BINARYEN_VERSION && \
cmake . && \
make
git submodule update --init && \
cmake . -DBUILD_TESTS=OFF && \
make wasm-opt wasm-dis wasm-as
ENV PATH="/binaryen/bin:/wabt/out/clang/Debug:${PATH}"
ENV CC=clang-13
ENV CXX=clang++-13
ENV CC=clang-21
ENV CXX=clang++-21
WORKDIR /src
+46 -8
View File
@@ -1,16 +1,24 @@
DOCKER := docker
DOCKER_FLAGS := --rm -e DEBUG
DEBUG ?= 0
USE_DOCKER ?= 1
ifeq ($(shell tty > /dev/null && echo 1 || echo 0), 1)
DOCKER_FLAGS += -it
endif
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_TEST_NODE_VERSION := lts
WASM_OBJ_DIR := _obj
# Set compilers for local builds when not using Docker
ifeq ($(USE_DOCKER), 0)
CC ?= clang
CXX ?= clang++
endif
CFLAGS += \
-MD \
-MP \
@@ -19,7 +27,15 @@ CFLAGS += \
-I src/lib \
-I src/libmpdec \
-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 += \
-std=c++17 \
@@ -29,13 +45,24 @@ CPPFLAGS += \
--target=wasm32-unknown-unknown-wasm \
-fno-exceptions \
-fno-rtti \
-I src/lib \
-I src/libc++ \
-I /usr/lib/llvm-13/include/c++/v1 \
-I /usr/lib/llvm-13/lib/clang/13.0.0/include \
-nostdinc++ \
-isystem src/libc++ \
-isystem /usr/lib/llvm-21/include/c++/v1 \
-isystem /usr/lib/llvm-21/lib/clang/21.1.7/include \
-isystem src/lib \
-I src/re2 \
-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)
CFLAGS += -O1 -gdwarf -DDEBUG
@@ -58,7 +85,9 @@ builder: Dockerfile
.PHONY: ensure-builder
ensure-builder:
ifeq ($(USE_DOCKER), 1)
@$(DOCKER) inspect $(WASM_BUILDER_IMAGE) > /dev/null || $(DOCKER) pull $(WASM_BUILDER_IMAGE) || $(MAKE) builder
endif
.PHONY: push-builder
push-builder:
@@ -66,13 +95,22 @@ push-builder:
.PHONY: build
build:
ifeq ($(USE_DOCKER), 1)
@$(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
else
@$(MAKE) --no-builtin-rules $(WASM_OBJ_DIR)/opa.wasm $(WASM_OBJ_DIR)/callgraph.csv
endif
.PHONY: 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) -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
hack:
+11 -4
View File
@@ -14,6 +14,13 @@ double log10(double x);
// not implemented:
#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);
float acosf(float x);
@@ -242,15 +249,15 @@ float truncf(float x);
long double truncl(long double 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 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 islessequal(float x, float y);
int islessgreater(float x, float y);
int isnan(float x);
int isnormal(float x);
// int isnan(float x); // Conflicts with LLVM 21 libc++
// int isnormal(float x); // Conflicts with LLVM 21 libc++
int isunordered(float x, float y);
int signbit(float x);
+1 -1
View File
@@ -1,7 +1,7 @@
#ifndef OPA_WCTYPE_H
#define OPA_WCTYPE_H
#include <stddef.h>
#include "wchar.h"
#ifdef __cplusplus
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.
template <size_t _Sz = sizeof(size_t)>
inline _LIBCPP_INLINE_VISIBILITY
typename enable_if<_Sz == 4, void>::type
inline typename enable_if<_Sz == 4, void>::type
__check_for_overflow(size_t N)
{
if (N > 0xFFFFFFFB)
@@ -158,8 +157,7 @@ __check_for_overflow(size_t N)
}
template <size_t _Sz = sizeof(size_t)>
inline _LIBCPP_INLINE_VISIBILITY
typename enable_if<_Sz == 8, void>::type
inline typename enable_if<_Sz == 8, void>::type
__check_for_overflow(size_t N)
{
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
+16 -10
View File
@@ -13,6 +13,10 @@ void operator delete(void *p) {
opa_free(p);
}
void operator delete(void *p, size_t) {
opa_free(p);
}
void* operator new[](size_t size) {
return opa_malloc(size);
}
@@ -21,22 +25,24 @@ void operator delete[](void *p) {
opa_free(p);
}
void operator delete[](void *p, size_t) {
opa_free(p);
}
extern "C" void __cxa_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.
// This is required because we do not link with the libc++.
_LIBCPP_BEGIN_NAMESPACE_STD
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>&);
template class basic_string<char>;
_LIBCPP_END_NAMESPACE_STD
+3 -2
View File
@@ -7,6 +7,7 @@
#include "util/utf.h"
#include <unordered_map>
#include <vector>
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);
opa_array_t *result = opa_cast_array(opa_array());
int nsubmatch = re->NumberOfCapturingGroups() + 1;
re2::StringPiece submatches[nsubmatch];
std::vector<re2::StringPiece> submatches(nsubmatch);
// 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;
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;
}