From 72f33a3bf983dd4ebaf50572b9275ddaec66fae6 Mon Sep 17 00:00:00 2001 From: Daniel Mendler Date: Mon, 15 Apr 2019 00:11:03 +0200 Subject: [PATCH] wasm32 support (#192) --- Make.inc | 10 ++++++++++ Makefile | 8 +++++++- README.md | 3 ++- include/openlibm_math.h | 2 +- src/Make.files | 17 +++++++++++----- src/cdefs-compat.h | 4 ++++ src/s_fdim.c | 2 ++ src/s_scalbln.c | 2 ++ wasm32/Make.files | 0 wasm32/assert.h | 1 + wasm32/float.h | 33 +++++++++++++++++++++++++++++++ wasm32/limits.h | 9 +++++++++ wasm32/stdint.h | 43 +++++++++++++++++++++++++++++++++++++++++ 13 files changed, 126 insertions(+), 8 deletions(-) create mode 100644 wasm32/Make.files create mode 100644 wasm32/assert.h create mode 100644 wasm32/float.h create mode 100644 wasm32/limits.h create mode 100644 wasm32/stdint.h diff --git a/Make.inc b/Make.inc index 5c75f5b..34888d2 100644 --- a/Make.inc +++ b/Make.inc @@ -31,6 +31,12 @@ endif AR = $(TOOLPREFIX)ar +ifeq ($(ARCH),wasm32) +CC = clang-8 +USEGCC = 0 +CFLAGS_add += -fno-builtin -fno-strict-aliasing +endif + ifeq ($(USECLANG),1) USEGCC = 0 CC = clang @@ -118,6 +124,10 @@ SFLAGS_arch += -m64 LDFLAGS_arch += -m64 endif +ifeq ($(ARCH),wasm32) +CFLAGS_arch += -ffreestanding -nostdlib -nostdinc --target=wasm32-unknown-unknown +endif + # Add our "arch"-related FLAGS in. We separate arch-related flags out so that # we can conveniently get at them for targets that don't want the rest of # *FLAGS_add, such as the testing Makefile targets diff --git a/Makefile b/Makefile index 0b7e3e1..2ffceb5 100644 --- a/Makefile +++ b/Makefile @@ -49,7 +49,13 @@ endif .PHONY: all check test clean distclean \ install install-static install-shared install-pkgconfig install-headers -all: libopenlibm.a libopenlibm.$(OLM_MAJOR_MINOR_SHLIB_EXT) + +OLM_LIBS := libopenlibm.a +ifneq ($(ARCH), wasm32) +OLM_LIBS += libopenlibm.$(OLM_MAJOR_MINOR_SHLIB_EXT) +endif + +all : $(OLM_LIBS) check test: test/test-double test/test-float test/test-double diff --git a/README.md b/README.md index 6712271..de9888e 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,8 @@ also supports arm, aarch64, ppc64le, and mips. Linux and Windows. 3. Use `make USECLANG=1` to build with clang. This is the default on OS X, FreeBSD, and OpenBSD. -4. Architectures are auto-detected. Use `make ARCH=i386` to force a +4. Use `make ARCH=wasm32` to build the wasm32 library with clang. Requires clang-8. +5. Architectures are auto-detected. Use `make ARCH=i386` to force a build for i386. Other supported architectures are i486, i586, and i686. GCC 4.8 is the minimum requirement for correct codegen on older 32-bit architectures. diff --git a/include/openlibm_math.h b/include/openlibm_math.h index 732ad00..ec3b030 100644 --- a/include/openlibm_math.h +++ b/include/openlibm_math.h @@ -25,7 +25,7 @@ #define __WIN32__ #endif -#ifndef __arm__ +#if !defined(__arm__) && !defined(__wasm__) #define OLM_LONG_DOUBLE #endif diff --git a/src/Make.files b/src/Make.files index 5462ffc..301bd2f 100644 --- a/src/Make.files +++ b/src/Make.files @@ -15,15 +15,14 @@ $(CUR_SRCS) = common.c \ s_copysign.c s_copysignf.c s_cos.c s_cosf.c \ s_csqrt.c s_csqrtf.c s_erf.c s_erff.c \ s_exp2.c s_exp2f.c s_expm1.c s_expm1f.c s_fabs.c s_fabsf.c s_fdim.c \ - s_floor.c s_floorf.c s_fma.c s_fmaf.c \ + s_floor.c s_floorf.c \ s_fmax.c s_fmaxf.c s_fmin.c \ s_fminf.c s_fpclassify.c \ s_frexp.c s_frexpf.c s_ilogb.c s_ilogbf.c \ s_isinf.c s_isfinite.c s_isnormal.c s_isnan.c \ - s_llrint.c s_llrintf.c s_llround.c s_llroundf.c \ - s_log1p.c s_log1pf.c s_logb.c s_logbf.c s_lrint.c s_lrintf.c \ - s_lround.c s_lroundf.c s_modf.c s_modff.c \ - s_nearbyint.c s_nextafter.c s_nextafterf.c \ + s_log1p.c s_log1pf.c s_logb.c s_logbf.c \ + s_modf.c s_modff.c \ + s_nextafter.c s_nextafterf.c \ s_nexttowardf.c s_remquo.c s_remquof.c \ s_rint.c s_rintf.c s_round.c s_roundf.c \ s_scalbln.c s_scalbn.c s_scalbnf.c s_signbit.c \ @@ -32,10 +31,18 @@ $(CUR_SRCS) = common.c \ s_trunc.c s_truncf.c s_cpow.c s_cpowf.c \ w_cabs.c w_cabsf.c +ifneq ($(ARCH), wasm32) + +$(CUR_SRCS) += \ + s_fma.c s_fmaf.c s_lrint.c s_lrintf.c s_lround.c s_lroundf.c \ + s_llrint.c s_llrintf.c s_llround.c s_llroundf.c s_nearbyint.c + ifneq ($(OS), WINNT) $(CUR_SRCS) += s_nan.c endif +endif + # Add in long double functions for x86, x64 and aarch64 ifneq ($(filter $(ARCH),i387 amd64 aarch64),) # C99 long double functions diff --git a/src/cdefs-compat.h b/src/cdefs-compat.h index fb31965..2b0bf87 100644 --- a/src/cdefs-compat.h +++ b/src/cdefs-compat.h @@ -21,6 +21,10 @@ #endif /* __APPLE__ */ #endif /* __strong_reference */ +#ifdef __wasm__ +# define __weak_reference(sym,alias) __strong_reference(sym,alias) +#endif + #ifndef __weak_reference #ifdef __ELF__ #ifdef __STDC__ diff --git a/src/s_fdim.c b/src/s_fdim.c index 1781f72..2f05347 100644 --- a/src/s_fdim.c +++ b/src/s_fdim.c @@ -43,4 +43,6 @@ fn(type x, type y) \ DECL(double, fdim) DECL(float, fdimf) +#ifdef OLM_LONG_DOUBLE DECL(long double, fdiml) +#endif diff --git a/src/s_scalbln.c b/src/s_scalbln.c index 978b523..8239db5 100644 --- a/src/s_scalbln.c +++ b/src/s_scalbln.c @@ -62,6 +62,7 @@ scalblnf (float x, long n) return (scalbnf(x, in)); } +#ifdef OLM_LONG_DOUBLE OLM_DLLEXPORT long double scalblnl (long double x, long n) { @@ -76,3 +77,4 @@ scalblnl (long double x, long n) } return (scalbnl(x, (int)n)); } +#endif diff --git a/wasm32/Make.files b/wasm32/Make.files new file mode 100644 index 0000000..e69de29 diff --git a/wasm32/assert.h b/wasm32/assert.h new file mode 100644 index 0000000..5c6205b --- /dev/null +++ b/wasm32/assert.h @@ -0,0 +1 @@ +#define assert(x) ((void)0) diff --git a/wasm32/float.h b/wasm32/float.h new file mode 100644 index 0000000..c82ecbd --- /dev/null +++ b/wasm32/float.h @@ -0,0 +1,33 @@ +#pragma once + +#define FLT_RADIX 2 + +#define FLT_TRUE_MIN 1.40129846432481707092e-45F +#define FLT_MIN 1.17549435082228750797e-38F +#define FLT_MAX 3.40282346638528859812e+38F +#define FLT_EPSILON 1.1920928955078125e-07F + +#define FLT_MANT_DIG 24 +#define FLT_MIN_EXP (-125) +#define FLT_MAX_EXP 128 +#define FLT_HAS_SUBNORM 1 + +#define FLT_DIG 6 +#define FLT_DECIMAL_DIG 9 +#define FLT_MIN_10_EXP (-37) +#define FLT_MAX_10_EXP 38 + +#define DBL_TRUE_MIN 4.94065645841246544177e-324 +#define DBL_MIN 2.22507385850720138309e-308 +#define DBL_MAX 1.79769313486231570815e+308 +#define DBL_EPSILON 2.22044604925031308085e-16 + +#define DBL_MANT_DIG 53 +#define DBL_MIN_EXP (-1021) +#define DBL_MAX_EXP 1024 +#define DBL_HAS_SUBNORM 1 + +#define DBL_DIG 15 +#define DBL_DECIMAL_DIG 17 +#define DBL_MIN_10_EXP (-307) +#define DBL_MAX_10_EXP 308 diff --git a/wasm32/limits.h b/wasm32/limits.h new file mode 100644 index 0000000..1f8d124 --- /dev/null +++ b/wasm32/limits.h @@ -0,0 +1,9 @@ +#include + +#define INT_MIN INT32_MIN +#define INT_MAX INT32_MAX +#define LONG_MIN INT32_MIN +#define LONG_MAX INT32_MAX +#define LLONG_MIN INT64_MIN +#define LLONG_MAX INT64_MAX + diff --git a/wasm32/stdint.h b/wasm32/stdint.h new file mode 100644 index 0000000..3996e5b --- /dev/null +++ b/wasm32/stdint.h @@ -0,0 +1,43 @@ +#pragma once + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; + +typedef char int8_t; +typedef short int16_t; +typedef int int32_t; +typedef long long int64_t; + +typedef unsigned int uintptr_t; +typedef int intptr_t; + +_Static_assert(sizeof (uint8_t) == 1, "invalid size"); +_Static_assert(sizeof (uint16_t) == 2, "invalid size"); +_Static_assert(sizeof (uint32_t) == 4, "invalid size"); +_Static_assert(sizeof (uint64_t) == 8, "invalid size"); + +_Static_assert(sizeof (int8_t) == 1, "invalid size"); +_Static_assert(sizeof (int16_t) == 2, "invalid size"); +_Static_assert(sizeof (int32_t) == 4, "invalid size"); +_Static_assert(sizeof (int64_t) == 8, "invalid size"); + +_Static_assert(sizeof (uintptr_t) == sizeof (intptr_t), "invalid size"); +_Static_assert(sizeof (uintptr_t) == sizeof (void*), "invalid size"); +_Static_assert(sizeof (uintptr_t) == 4, "invalid size"); + +#define UINT8_MAX 0xFF +#define UINT16_MAX 0xFFFF +#define UINT32_MAX 0xFFFFFFFFUL +#define UINT64_MAX 0xFFFFFFFFFFFFFFFFULL + +#define INT8_MAX 0x7F +#define INT16_MAX 0x7FFF +#define INT32_MAX 0x7FFFFFFF +#define INT64_MAX 0x7FFFFFFFFFFFFFFF + +#define INT8_MIN (-0x80) +#define INT16_MIN (-0x8000) +#define INT32_MIN (-0x80000000L) +#define INT64_MIN (-0x8000000000000000LL)