Migrate to WASI
This commit is contained in:
parent
a88299277a
commit
d8fe2a7922
10
.clangd
10
.clangd
|
|
@ -1,13 +1,5 @@
|
||||||
If:
|
If:
|
||||||
PathMatch: .*\.cpp
|
PathMatch: .*\.[ch]
|
||||||
|
|
||||||
CompileFlags:
|
|
||||||
Add: [-std=c++23]
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
If:
|
|
||||||
PathMatch: .*\.c
|
|
||||||
|
|
||||||
CompileFlags:
|
CompileFlags:
|
||||||
Add: [-std=c23]
|
Add: [-std=c23]
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
#define assert(x) ((void)(x))
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
#include <float.h>
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
#include <limits.h>
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
#include <math.hpp>
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
namespace std {
|
|
||||||
using nullptr_t = decltype(nullptr);
|
|
||||||
using size_t = ::size_t;
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
#include <stdint.h>
|
|
||||||
namespace std {
|
|
||||||
using uint8_t = ::uint8_t;
|
|
||||||
using int8_t = ::int8_t;
|
|
||||||
using uint16_t = ::uint16_t;
|
|
||||||
using int16_t = ::int16_t;
|
|
||||||
using uint32_t = ::uint32_t;
|
|
||||||
using int32_t = ::int32_t;
|
|
||||||
using uint64_t = ::uint64_t;
|
|
||||||
using int64_t = ::int64_t;
|
|
||||||
using uintptr_t = ::uintptr_t;
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define IMPORT(name) __attribute__((import_module("env"), import_name(#name)))
|
||||||
|
#define EXPORT(name) __attribute__((export_name(#name)))
|
||||||
|
|
||||||
|
IMPORT(log) int console_log(const char* format, ...);
|
||||||
|
|
||||||
|
EXPORT(__srand) void srand(long long seed);
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <type_traits.hpp>
|
|
||||||
|
|
||||||
namespace std {
|
|
||||||
template <typename T>
|
|
||||||
struct numeric_limits {
|
|
||||||
static constexpr bool is_iec559 = std::is_floating_point<T>::value;
|
|
||||||
static constexpr bool is_integer = std::is_integral<T>::value;
|
|
||||||
static constexpr bool is_signed = std::is_signed<T>::value;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#define M_PI 3.14159265359
|
|
||||||
#define M_PI_2 1.57079632679
|
|
||||||
|
|
||||||
#define abs(x) (((x) < 0) ? -(x) : (x))
|
|
||||||
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
|
||||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static inline bool isnan(double x) {
|
|
||||||
return x != x;
|
|
||||||
}
|
|
||||||
static inline bool isinf(double x) {
|
|
||||||
return !isnan(x) && isnan(x - x);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define IMPORT_UNARY(fn) __attribute__((import_module("Math"), import_name(#fn))) double fn(double);
|
|
||||||
#define IMPORT_BINARY(fn) __attribute__((import_module("Math"), import_name(#fn))) double fn(double, double);
|
|
||||||
|
|
||||||
IMPORT_UNARY(floor)
|
|
||||||
IMPORT_UNARY(ceil)
|
|
||||||
IMPORT_UNARY(round)
|
|
||||||
IMPORT_UNARY(trunc)
|
|
||||||
IMPORT_UNARY(exp)
|
|
||||||
IMPORT_UNARY(log)
|
|
||||||
IMPORT_UNARY(log10)
|
|
||||||
IMPORT_UNARY(sqrt)
|
|
||||||
IMPORT_UNARY(sin)
|
|
||||||
IMPORT_UNARY(cos)
|
|
||||||
IMPORT_UNARY(tan)
|
|
||||||
IMPORT_UNARY(asin)
|
|
||||||
IMPORT_UNARY(acos)
|
|
||||||
IMPORT_UNARY(atan)
|
|
||||||
IMPORT_UNARY(sinh)
|
|
||||||
IMPORT_UNARY(cosh)
|
|
||||||
IMPORT_UNARY(tanh)
|
|
||||||
|
|
||||||
IMPORT_BINARY(fmod)
|
|
||||||
IMPORT_BINARY(pow)
|
|
||||||
IMPORT_BINARY(atan2)
|
|
||||||
|
|
||||||
#undef IMPORT_UNARY
|
|
||||||
#undef IMPORT_BINARY
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
#include <type_traits.hpp>
|
|
||||||
|
|
||||||
#ifdef abs
|
|
||||||
#undef abs
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef max
|
|
||||||
#undef max
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef min
|
|
||||||
#undef min
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace std {
|
|
||||||
template <typename T> T max(T a, T b) {
|
|
||||||
return a < b ? b : a;
|
|
||||||
}
|
|
||||||
template <typename T> T min(T a, T b) {
|
|
||||||
return a < b ? a : b;
|
|
||||||
}
|
|
||||||
template <typename T> T abs(T a) {
|
|
||||||
return a < 0 ? -a : a;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define UNARY(fn) \
|
|
||||||
template <typename T> \
|
|
||||||
typename std::enable_if<std::is_convertible<T, double>::value, T>::type \
|
|
||||||
fn(T a) { return static_cast<T>(::fn(static_cast<double>(a))); }
|
|
||||||
|
|
||||||
#define UNARY_BOOL(fn) \
|
|
||||||
template <typename T> \
|
|
||||||
typename std::enable_if<std::is_convertible<T, double>::value, bool>::type \
|
|
||||||
fn(T a) { return ::fn(static_cast<double>(a)); }
|
|
||||||
|
|
||||||
#define BINARY(fn) \
|
|
||||||
template <typename T> \
|
|
||||||
typename std::enable_if<std::is_convertible<T, double>::value, T>::type \
|
|
||||||
fn(T a, T b) { return static_cast<T>(::fn(static_cast<double>(a), static_cast<double>(b))); }
|
|
||||||
|
|
||||||
UNARY(floor)
|
|
||||||
UNARY(ceil)
|
|
||||||
UNARY(round)
|
|
||||||
UNARY(trunc)
|
|
||||||
UNARY(exp)
|
|
||||||
UNARY(log)
|
|
||||||
UNARY(log10)
|
|
||||||
UNARY(sqrt)
|
|
||||||
UNARY(sin)
|
|
||||||
UNARY(cos)
|
|
||||||
UNARY(tan)
|
|
||||||
UNARY(asin)
|
|
||||||
UNARY(acos)
|
|
||||||
UNARY(atan)
|
|
||||||
UNARY(sinh)
|
|
||||||
UNARY(cosh)
|
|
||||||
UNARY(tanh)
|
|
||||||
UNARY_BOOL(isnan)
|
|
||||||
UNARY_BOOL(isinf)
|
|
||||||
|
|
||||||
BINARY(fmod)
|
|
||||||
BINARY(pow)
|
|
||||||
BINARY(atan2)
|
|
||||||
|
|
||||||
#undef UNARY
|
|
||||||
#undef UNARY_BOOL
|
|
||||||
#undef BINARY
|
|
||||||
} // namespace std
|
|
||||||
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#define RAND_MAX INT_MAX
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern unsigned char __heap_base;
|
|
||||||
|
|
||||||
#define IMPORT(name) __attribute__((import_module("env"), import_name(#name)))
|
|
||||||
#define EXPORT(name) __attribute__((export_name(#name)))
|
|
||||||
|
|
||||||
void* malloc(size_t size);
|
|
||||||
void* calloc(size_t n, size_t size);
|
|
||||||
void* realloc(void* ptr, size_t size);
|
|
||||||
void free(void* ptr);
|
|
||||||
|
|
||||||
__attribute__((__always_inline__)) static inline
|
|
||||||
void* memset(void* d, int c, size_t n) {
|
|
||||||
return __builtin_memset(d, c, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__((__always_inline__)) static inline
|
|
||||||
void* memcpy(void* dest, const void* src, size_t n) {
|
|
||||||
return __builtin_memcpy(dest, src, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
int memcmp(const void* s1, const void* s2, size_t n);
|
|
||||||
|
|
||||||
IMPORT(log) void printf(const char* format, ...);
|
|
||||||
|
|
||||||
EXPORT(__srand) void srand(uint64_t seed);
|
|
||||||
int rand(void);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
#include <type_traits.hpp>
|
|
||||||
|
|
@ -1,151 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
namespace std {
|
|
||||||
template<class T, T v>
|
|
||||||
struct integral_constant
|
|
||||||
{
|
|
||||||
static constexpr T value = v;
|
|
||||||
using value_type = T;
|
|
||||||
using type = integral_constant; // using injected-class-name
|
|
||||||
constexpr operator value_type() const noexcept { return value; }
|
|
||||||
constexpr value_type operator()() const noexcept { return value; } // since c++14
|
|
||||||
};
|
|
||||||
|
|
||||||
using true_type = std::integral_constant<bool, true>;
|
|
||||||
using false_type = std::integral_constant<bool, false>;
|
|
||||||
|
|
||||||
template< bool B >
|
|
||||||
using bool_constant = integral_constant<bool, B>;
|
|
||||||
|
|
||||||
template<bool B, class T = void>
|
|
||||||
struct enable_if {};
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
struct enable_if<true, T> { typedef T type; };
|
|
||||||
|
|
||||||
template<class T, class U>
|
|
||||||
struct is_same : std::false_type {};
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
struct is_same<T, T> : std::true_type {};
|
|
||||||
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
template<class T>
|
|
||||||
struct type_identity { using type = T; }; // or use std::type_identity (since C++20)
|
|
||||||
|
|
||||||
template<class T> // Note that “cv void&” is a substitution failure
|
|
||||||
auto try_add_lvalue_reference(int) -> type_identity<T&>;
|
|
||||||
template<class T> // Handle T = cv void case
|
|
||||||
auto try_add_lvalue_reference(...) -> type_identity<T>;
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
auto try_add_rvalue_reference(int) -> type_identity<T&&>;
|
|
||||||
template<class T>
|
|
||||||
auto try_add_rvalue_reference(...) -> type_identity<T>;
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
struct add_lvalue_reference
|
|
||||||
: decltype(detail::try_add_lvalue_reference<T>(0)) {};
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
struct add_rvalue_reference
|
|
||||||
: decltype(detail::try_add_rvalue_reference<T>(0)) {};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
typename std::add_rvalue_reference<T>::type declval() noexcept
|
|
||||||
{
|
|
||||||
static_assert(false, "declval not allowed in an evaluated context");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<bool B, class T, class F>
|
|
||||||
struct conditional { using type = T; };
|
|
||||||
|
|
||||||
template<class T, class F>
|
|
||||||
struct conditional<false, T, F> { using type = F; };
|
|
||||||
|
|
||||||
template<class T> struct remove_cv { typedef T type; };
|
|
||||||
template<class T> struct remove_cv<const T> { typedef T type; };
|
|
||||||
template<class T> struct remove_cv<volatile T> { typedef T type; };
|
|
||||||
template<class T> struct remove_cv<const volatile T> { typedef T type; };
|
|
||||||
|
|
||||||
template<class T> struct remove_const { typedef T type; };
|
|
||||||
template<class T> struct remove_const<const T> { typedef T type; };
|
|
||||||
|
|
||||||
template<class T> struct remove_volatile { typedef T type; };
|
|
||||||
template<class T> struct remove_volatile<volatile T> { typedef T type; };
|
|
||||||
|
|
||||||
template<class T> struct remove_reference { typedef T type; };
|
|
||||||
template<class T> struct remove_reference<T&> { typedef T type; };
|
|
||||||
template<class T> struct remove_reference<T&&> { typedef T type; };
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
struct is_floating_point
|
|
||||||
: std::integral_constant<
|
|
||||||
bool,
|
|
||||||
std::is_same<float, typename std::remove_cv<T>::type>::value
|
|
||||||
|| std::is_same<double, typename std::remove_cv<T>::type>::value
|
|
||||||
|| std::is_same<long double, typename std::remove_cv<T>::type>::value
|
|
||||||
> {};
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
struct is_integral
|
|
||||||
: std::integral_constant<
|
|
||||||
bool,
|
|
||||||
std::is_same<char, typename std::remove_cv<T>::type>::value
|
|
||||||
|| std::is_same<unsigned char, typename std::remove_cv<T>::type>::value
|
|
||||||
|| std::is_same<short, typename std::remove_cv<T>::type>::value
|
|
||||||
|| std::is_same<unsigned short, typename std::remove_cv<T>::type>::value
|
|
||||||
|| std::is_same<int, typename std::remove_cv<T>::type>::value
|
|
||||||
|| std::is_same<unsigned int, typename std::remove_cv<T>::type>::value
|
|
||||||
|| std::is_same<long, typename std::remove_cv<T>::type>::value
|
|
||||||
|| std::is_same<unsigned long, typename std::remove_cv<T>::type>::value
|
|
||||||
|| std::is_same<long long, typename std::remove_cv<T>::type>::value
|
|
||||||
|| std::is_same<unsigned long long, typename std::remove_cv<T>::type>::value
|
|
||||||
> {};
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
struct is_arithmetic : std::integral_constant<bool,
|
|
||||||
std::is_integral<T>::value ||
|
|
||||||
std::is_floating_point<T>::value> {};
|
|
||||||
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
template<typename T, bool = std::is_arithmetic<T>::value>
|
|
||||||
struct is_signed : std::integral_constant<bool, T(-1) < T(0)> {};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct is_signed<T, false> : std::false_type {};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct is_signed : detail::is_signed<T>::type {};
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
struct is_void : std::is_same<void, typename std::remove_cv<T>::type> {};
|
|
||||||
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
template<class T>
|
|
||||||
auto test_returnable(int) -> decltype(
|
|
||||||
void(static_cast<T(*)()>(nullptr)), std::true_type{}
|
|
||||||
);
|
|
||||||
template<class>
|
|
||||||
auto test_returnable(...) -> std::false_type;
|
|
||||||
|
|
||||||
template<class From, class To>
|
|
||||||
auto test_implicitly_convertible(int) -> decltype(
|
|
||||||
void(std::declval<void(&)(To)>()(std::declval<From>())), std::true_type{}
|
|
||||||
);
|
|
||||||
template<class, class>
|
|
||||||
auto test_implicitly_convertible(...) -> std::false_type;
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
template<class From, class To>
|
|
||||||
struct is_convertible : std::integral_constant<bool,
|
|
||||||
(decltype(detail::test_returnable<To>(0))::value &&
|
|
||||||
decltype(detail::test_implicitly_convertible<From, To>(0))::value) ||
|
|
||||||
(std::is_void<From>::value && std::is_void<To>::value)
|
|
||||||
> {};
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +1,15 @@
|
||||||
#include <graphics.h>
|
#include <graphics.h>
|
||||||
#include <math.h>
|
#include <memory.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
static inline int max(int a, int b) {
|
||||||
|
return a > b ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int min(int a, int b) {
|
||||||
|
return a < b ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
image_data_t image_create(uint16_t width, uint16_t height) {
|
image_data_t image_create(uint16_t width, uint16_t height) {
|
||||||
image_data_t data;
|
image_data_t data;
|
||||||
data.width = width;
|
data.width = width;
|
||||||
|
|
|
||||||
|
|
@ -1,183 +0,0 @@
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#define BLOCK_SIZE (64 * 1024)
|
|
||||||
#define BLOCK_1MB 16
|
|
||||||
|
|
||||||
typedef struct header {
|
|
||||||
size_t size : 31;
|
|
||||||
uint8_t is_free : 1;
|
|
||||||
} header_t;
|
|
||||||
static header_t* head;
|
|
||||||
|
|
||||||
static uintptr_t bump_pointer = (uintptr_t)&__heap_base;
|
|
||||||
static uintptr_t heap_end = BLOCK_1MB * BLOCK_SIZE;
|
|
||||||
IMPORT(grow) void grow(uint32_t blocks);
|
|
||||||
|
|
||||||
static void* bump_alloc(uintptr_t n) {
|
|
||||||
uintptr_t r = bump_pointer;
|
|
||||||
bump_pointer += n;
|
|
||||||
|
|
||||||
while (bump_pointer >= heap_end) {
|
|
||||||
grow(heap_end / BLOCK_SIZE);
|
|
||||||
heap_end *= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (void*)r;
|
|
||||||
}
|
|
||||||
|
|
||||||
static header_t* get_next_header(header_t* block) {
|
|
||||||
if (!block) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
uint8_t* data = (uint8_t*)(block + 1);
|
|
||||||
uint8_t* next_header = data + block->size;
|
|
||||||
if ((uintptr_t)next_header >= bump_pointer) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return (header_t*)next_header;
|
|
||||||
}
|
|
||||||
|
|
||||||
static header_t* get_prev_header(header_t* block) {
|
|
||||||
header_t* curr = head;
|
|
||||||
while (curr) {
|
|
||||||
header_t* next = get_next_header(curr);
|
|
||||||
if (next == block) {
|
|
||||||
return curr;
|
|
||||||
}
|
|
||||||
curr = next;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static header_t* get_free_block(size_t size) {
|
|
||||||
header_t* curr = head;
|
|
||||||
while (curr) {
|
|
||||||
if (curr->is_free && curr->size >= size) {
|
|
||||||
return curr;
|
|
||||||
}
|
|
||||||
curr = get_next_header(curr);
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* malloc(size_t size) {
|
|
||||||
if (!size) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
header_t* header = get_free_block(size);
|
|
||||||
if (header) {
|
|
||||||
header->is_free = 0;
|
|
||||||
if (header->size > size + sizeof(header_t) * 2) {
|
|
||||||
size_t old_size = header->size;
|
|
||||||
header->size = size;
|
|
||||||
|
|
||||||
header_t* next = get_next_header(header);
|
|
||||||
next->size = old_size - size - sizeof(header_t);
|
|
||||||
next->is_free = 1;
|
|
||||||
}
|
|
||||||
return (void*)(header + 1);
|
|
||||||
}
|
|
||||||
size_t total_size = sizeof(header_t) + size;
|
|
||||||
|
|
||||||
void* block = bump_alloc(total_size);
|
|
||||||
if (!block) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
header = block;
|
|
||||||
header->size = size;
|
|
||||||
header->is_free = 0;
|
|
||||||
|
|
||||||
if (!head) {
|
|
||||||
head = header;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (void*)(header + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void free(void* block) {
|
|
||||||
if (!block) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
header_t* header = ((header_t*)block) - 1;
|
|
||||||
if (header->is_free) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
header->is_free = 1;
|
|
||||||
|
|
||||||
header_t* next_header = get_next_header(header);
|
|
||||||
if (next_header && next_header->is_free) {
|
|
||||||
header->size += next_header->size + sizeof(header_t);
|
|
||||||
}
|
|
||||||
|
|
||||||
header_t* prev_header = get_prev_header(header);
|
|
||||||
if (prev_header && prev_header->is_free) {
|
|
||||||
prev_header->size += header->size + sizeof(header_t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void* realloc(void* block, size_t size) {
|
|
||||||
header_t* header;
|
|
||||||
void* ret;
|
|
||||||
|
|
||||||
if (!block || !size) {
|
|
||||||
return malloc(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
header = (header_t*)block - 1;
|
|
||||||
if (header->size >= size) {
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = malloc(size);
|
|
||||||
if (ret) {
|
|
||||||
memcpy(ret, block, header->size);
|
|
||||||
free(block);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* calloc(size_t n, size_t size) {
|
|
||||||
const size_t s = n * size;
|
|
||||||
if (s == 0) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* ret = malloc(n * size);
|
|
||||||
if (ret) {
|
|
||||||
memset(ret, 0, n * size);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int memcmp(const void* s1, const void* s2, size_t n) {
|
|
||||||
const uint8_t* p1 = (const uint8_t*)s1;
|
|
||||||
const uint8_t* p2 = (const uint8_t*)s2;
|
|
||||||
|
|
||||||
while (n--) {
|
|
||||||
if (*p1 != *p2) {
|
|
||||||
return (*p1 - *p2);
|
|
||||||
}
|
|
||||||
p1++;
|
|
||||||
p2++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0; // Memory blocks are equal
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint64_t rand_state;
|
|
||||||
|
|
||||||
void srand(uint64_t seed) {
|
|
||||||
rand_state = seed;
|
|
||||||
}
|
|
||||||
|
|
||||||
int rand(void) {
|
|
||||||
uint64_t z = (rand_state += 0x9e3779b97f4a7c15);
|
|
||||||
z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
|
|
||||||
z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
|
|
||||||
int r = (int)(z ^ (z >> 31));
|
|
||||||
return r < 0 ? -r : r;
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +1,64 @@
|
||||||
import { plugin, $, type BunPlugin } from "bun";
|
import { plugin, $, type BunPlugin } from "bun";
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
import fs from 'fs/promises';
|
||||||
|
|
||||||
interface WasmLoaderConfig {
|
interface WasmLoaderConfig {
|
||||||
production?: boolean;
|
production?: boolean;
|
||||||
portable?: boolean;
|
portable?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface CompilerWithFlags {
|
||||||
|
cc: string;
|
||||||
|
flags: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const wasiArchiveURL = 'https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-x86_64-linux.tar.gz';
|
||||||
|
const rtURL = 'https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/libclang_rt.builtins-wasm32-wasi-25.0.tar.gz';
|
||||||
|
|
||||||
|
const getCompiler = async (): Promise<CompilerWithFlags> => {
|
||||||
|
const wasiDir = path.resolve(import.meta.dir, '..', 'dist', 'wasi');
|
||||||
|
const cc: CompilerWithFlags = {
|
||||||
|
cc: 'clang',
|
||||||
|
flags: [
|
||||||
|
'--target=wasm32',
|
||||||
|
'--no-standard-libraries',
|
||||||
|
'-fno-builtin',
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
await fs.mkdir(wasiDir, { recursive: true });
|
||||||
|
|
||||||
|
if (!await Bun.file(path.resolve(wasiDir, 'VERSION')).exists()) {
|
||||||
|
const response = await fetch(wasiArchiveURL);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
return cc;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bytes = await response.bytes();
|
||||||
|
|
||||||
|
await $`tar -xzv -C ${wasiDir} --strip-components=1 < ${bytes}`;
|
||||||
|
|
||||||
|
const rtResponse = await fetch(rtURL);
|
||||||
|
|
||||||
|
if (!rtResponse.ok) {
|
||||||
|
return cc;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rtBytes = await rtResponse.bytes();
|
||||||
|
|
||||||
|
await $`tar -xzv -C ${wasiDir} --strip-components=1 < ${rtBytes}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
cc.cc = `${path.resolve(wasiDir, 'bin', 'clang')}`;
|
||||||
|
cc.flags = [
|
||||||
|
'--target=wasm32-wasi',
|
||||||
|
`--sysroot=${path.resolve(wasiDir, 'share', 'wasi-sysroot')}`,
|
||||||
|
];
|
||||||
|
|
||||||
|
return cc;
|
||||||
|
}
|
||||||
|
|
||||||
const wasmPlugin = ({ production, portable }: WasmLoaderConfig = {}): BunPlugin => {
|
const wasmPlugin = ({ production, portable }: WasmLoaderConfig = {}): BunPlugin => {
|
||||||
const p: BunPlugin = {
|
const p: BunPlugin = {
|
||||||
name: "WASM loader",
|
name: "WASM loader",
|
||||||
|
|
@ -32,6 +85,8 @@ const wasmPlugin = ({ production, portable }: WasmLoaderConfig = {}): BunPlugin
|
||||||
env: {
|
env: {
|
||||||
memory,
|
memory,
|
||||||
log(format, argsPtr) {
|
log(format, argsPtr) {
|
||||||
|
let bufLen = buf.length;
|
||||||
|
let count = 0;
|
||||||
format = getString(format);
|
format = getString(format);
|
||||||
let isFormat = false;
|
let isFormat = false;
|
||||||
let w = 4;
|
let w = 4;
|
||||||
|
|
@ -42,6 +97,8 @@ const wasmPlugin = ({ production, portable }: WasmLoaderConfig = {}): BunPlugin
|
||||||
isFormat = true;
|
isFormat = true;
|
||||||
} else if (c === '\\n') {
|
} else if (c === '\\n') {
|
||||||
console.log('[wasm]', buf);
|
console.log('[wasm]', buf);
|
||||||
|
count += buf.length - bufLen + 1;
|
||||||
|
bufLen = 0;
|
||||||
buf = '';
|
buf = '';
|
||||||
} else {
|
} else {
|
||||||
buf += c;
|
buf += c;
|
||||||
|
|
@ -59,6 +116,8 @@ const wasmPlugin = ({ production, portable }: WasmLoaderConfig = {}): BunPlugin
|
||||||
default: buf += '%' + c; isFormat = false; break;
|
default: buf += '%' + c; isFormat = false; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
count += buf.length - bufLen;
|
||||||
|
return count;
|
||||||
},
|
},
|
||||||
grow(blocks) {
|
grow(blocks) {
|
||||||
if (blocks > 0) {
|
if (blocks > 0) {
|
||||||
|
|
@ -68,6 +127,15 @@ const wasmPlugin = ({ production, portable }: WasmLoaderConfig = {}): BunPlugin
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Math: Math,
|
Math: Math,
|
||||||
|
wasi_snapshot_preview1: {
|
||||||
|
random_get: (ptr, length) => {
|
||||||
|
for (let i=0; i < length; i++) {
|
||||||
|
data.setUint8(ptr + i, Math.random() * 256);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
environ_sizes_get(){ return 0; },
|
||||||
|
environ_get() { return 0; },
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
@ -89,6 +157,7 @@ const wasmPlugin = ({ production, portable }: WasmLoaderConfig = {}): BunPlugin
|
||||||
const glob = new Bun.Glob(`${buildAssets}/lib/**/*.c`);
|
const glob = new Bun.Glob(`${buildAssets}/lib/**/*.c`);
|
||||||
const stdlib = await Array.fromAsync(glob.scan());
|
const stdlib = await Array.fromAsync(glob.scan());
|
||||||
const objPath = wasmPath + '.o';
|
const objPath = wasmPath + '.o';
|
||||||
|
const cc = await getCompiler();
|
||||||
|
|
||||||
const features = [
|
const features = [
|
||||||
'bulk-memory',
|
'bulk-memory',
|
||||||
|
|
@ -104,20 +173,19 @@ const wasmPlugin = ({ production, portable }: WasmLoaderConfig = {}): BunPlugin
|
||||||
].map(f => `-m${f}`);
|
].map(f => `-m${f}`);
|
||||||
|
|
||||||
const flags = [
|
const flags = [
|
||||||
'--target=wasm32',
|
...cc.flags,
|
||||||
production ? '-O3' : '-O0',
|
production ? '-O3' : '-O0',
|
||||||
'-flto',
|
'-flto',
|
||||||
'-fno-builtin',
|
'-fno-exceptions',
|
||||||
'--no-standard-libraries',
|
|
||||||
'-Wall',
|
'-Wall',
|
||||||
'-Wextra',
|
'-Wextra',
|
||||||
'-Wpedantic',
|
'-Wpedantic',
|
||||||
'-Werror',
|
'-Werror',
|
||||||
'-Wshadow',
|
'-Wshadow',
|
||||||
...features,
|
...features,
|
||||||
];
|
];
|
||||||
const std = args.path.endsWith('.cpp') ? '-std=gnu++23': '-std=gnu23';
|
const std = args.path.endsWith('.cpp') ? '-std=gnu++23' : '-std=gnu23';
|
||||||
const compileResult = await $`clang -c ${flags} ${std} -I ${include} -o ${objPath} ${args.path}`;
|
const compileResult = await $`${cc.cc} -c ${flags} ${std} -I ${include} -o ${objPath} ${args.path}`;
|
||||||
|
|
||||||
if (compileResult.exitCode !== 0) {
|
if (compileResult.exitCode !== 0) {
|
||||||
throw new Error('Compile failed, check output');
|
throw new Error('Compile failed, check output');
|
||||||
|
|
@ -129,7 +197,7 @@ const wasmPlugin = ({ production, portable }: WasmLoaderConfig = {}): BunPlugin
|
||||||
'--import-memory',
|
'--import-memory',
|
||||||
].map(f => `-Wl,${f}`);
|
].map(f => `-Wl,${f}`);
|
||||||
|
|
||||||
const linkResult = await $`clang ${flags} -std=gnu23 -I ${include} ${linkFlags} -o ${wasmPath} ${objPath} ${stdlib}`;
|
const linkResult = await $`${cc.cc} ${flags} -std=gnu23 -I ${include} ${linkFlags} -lstdc++ -nostartfiles -o ${wasmPath} ${objPath} ${stdlib}`;
|
||||||
|
|
||||||
if (linkResult.exitCode !== 0) {
|
if (linkResult.exitCode !== 0) {
|
||||||
throw new Error('Link failed, check output');
|
throw new Error('Link failed, check output');
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
--target=wasm32
|
--target=wasm32-wasi
|
||||||
-fno-builtin
|
--sysroot=dist/wasi/share/wasi-sysroot
|
||||||
--no-standard-libraries
|
-std=c++23
|
||||||
|
-fno-exceptions
|
||||||
-I
|
-I
|
||||||
build/assets/include
|
build/assets/include
|
||||||
-Wall
|
-Wall
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
#include <stdlib.h>
|
#include <js.h>
|
||||||
#include <linalg.hpp>
|
#include <linalg.hpp>
|
||||||
|
|
||||||
using namespace linalg::aliases;
|
using namespace linalg::aliases;
|
||||||
|
|
||||||
EXPORT(main) auto init() {
|
EXPORT(awoo) auto awoo() {
|
||||||
static constexpr double2 vel = {-1, -1};
|
static constexpr double2 vel = {-1, -1};
|
||||||
static constexpr double2 left = {1, 0};
|
static constexpr double2 left = {1, 0};
|
||||||
static constexpr double2 refl = linalg::reflect(vel, left);
|
static constexpr double2 refl = linalg::reflect(vel, left);
|
||||||
|
|
||||||
return refl.y;
|
return refl.x;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import awoo from "./awoo.cpp";
|
import awoo from "./awoo.cpp";
|
||||||
|
|
||||||
export default function main() {
|
export default function main() {
|
||||||
console.log(awoo, awoo.main());
|
console.log(awoo, awoo.awoo(), awoo.blah());
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue