Skip to content

Commit 210bff9

Browse files
committed
Migrate to using musl libc sprintf family to gain compiled asm.js performance. Keep a copy of handwritten vfprintf and fprintf around to be compatible with the Emscripten filesystem IO library. Also migrate frexp which sprintf depends on to musl libc.
1 parent 1e0f6cf commit 210bff9

14 files changed

+935
-40
lines changed

src/library.js

-39
Original file line numberDiff line numberDiff line change
@@ -2838,16 +2838,6 @@ LibraryManager.library = {
28382838
var stdout = {{{ makeGetValue(makeGlobalUse('_stdout'), '0', 'void*') }}};
28392839
return _fprintf(stdout, format, varargs);
28402840
},
2841-
sprintf__deps: ['snprintf'],
2842-
sprintf: function(s, format, varargs) {
2843-
// int sprintf(char *restrict s, const char *restrict format, ...);
2844-
// http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html
2845-
return _snprintf(s, undefined, format, varargs);
2846-
},
2847-
asprintf__deps: ['sprintf'],
2848-
asprintf: function(s, format, varargs) {
2849-
return _sprintf(-s, format, varargs);
2850-
},
28512841
dprintf__deps: ['_formatString', 'write'],
28522842
dprintf: function(fd, format, varargs) {
28532843
var result = __formatString(format, varargs);
@@ -2875,22 +2865,10 @@ LibraryManager.library = {
28752865
vfprintf: function(s, f, va_arg) {
28762866
return _fprintf(s, f, {{{ makeGetValue('va_arg', 0, '*') }}});
28772867
},
2878-
vsnprintf__deps: ['snprintf'],
2879-
vsnprintf: function(s, n, format, va_arg) {
2880-
return _snprintf(s, n, format, {{{ makeGetValue('va_arg', 0, '*') }}});
2881-
},
28822868
vprintf__deps: ['printf'],
28832869
vprintf: function(format, va_arg) {
28842870
return _printf(format, {{{ makeGetValue('va_arg', 0, '*') }}});
28852871
},
2886-
vsprintf__deps: ['sprintf'],
2887-
vsprintf: function(s, format, va_arg) {
2888-
return _sprintf(s, format, {{{ makeGetValue('va_arg', 0, '*') }}});
2889-
},
2890-
vasprintf__deps: ['asprintf'],
2891-
vasprintf: function(s, format, va_arg) {
2892-
return _asprintf(s, format, {{{ makeGetValue('va_arg', 0, '*') }}});
2893-
},
28942872
vdprintf__deps: ['dprintf'],
28952873
vdprintf: function (fd, format, va_arg) {
28962874
return _dprintf(fd, format, {{{ makeGetValue('va_arg', 0, '*') }}});
@@ -4500,23 +4478,6 @@ LibraryManager.library = {
45004478
{{{ makeSetValue('intpart', 0, 'Math.floor(x)', 'float') }}};
45014479
return x - {{{ makeGetValue('intpart', 0, 'float') }}};
45024480
},
4503-
frexp: function(x, exp_addr) {
4504-
var sig = 0, exp_ = 0;
4505-
if (x !== 0) {
4506-
var sign = 1;
4507-
if (x < 0) {
4508-
x = -x;
4509-
sign = -1;
4510-
}
4511-
var raw_exp = Math.log(x)/Math.log(2);
4512-
exp_ = Math.ceil(raw_exp);
4513-
if (exp_ === raw_exp) exp_ += 1;
4514-
sig = sign*x/Math.pow(2, exp_);
4515-
}
4516-
{{{ makeSetValue('exp_addr', 0, 'exp_', 'i32') }}};
4517-
return sig;
4518-
},
4519-
frexpf: 'frexp',
45204481
finite: function(x) {
45214482
return isFinite(x);
45224483
},

system/lib/libc/musl/src/internal/stdio_impl.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ int __fmodeflags(const char *);
9595
FILE *__fopen_rb_ca(const char *, FILE *, unsigned char *, size_t);
9696
int __fclose_ca(FILE *);
9797

98-
// XXX Emscripten
98+
// XXX Emscripten: musl-specific vfscanf and vfprintf live parallel to JS handwritten vfscanf and vfprintf, so musl ones are prefixed.
9999
int MUSL_vfscanf(FILE *restrict f, const char *restrict fmt, va_list ap);
100+
int MUSL_vfprintf(FILE *restrict f, const char *restrict fmt, va_list ap);
100101

101102
#endif

system/lib/libc/musl/src/math/frexp.c

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#include <math.h>
2+
#include <stdint.h>
3+
4+
double frexp(double x, int *e)
5+
{
6+
union { double d; uint64_t i; } y = { x };
7+
int ee = y.i>>52 & 0x7ff;
8+
9+
if (!ee) {
10+
if (x) {
11+
x = frexp(x*0x1p64, e);
12+
*e -= 64;
13+
} else *e = 0;
14+
return x;
15+
} else if (ee == 0x7ff) {
16+
return x;
17+
}
18+
19+
*e = ee - 0x3fe;
20+
y.i &= 0x800fffffffffffffull;
21+
y.i |= 0x3fe0000000000000ull;
22+
return y.d;
23+
}
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#include <math.h>
2+
#include <stdint.h>
3+
4+
float frexpf(float x, int *e)
5+
{
6+
union { float f; uint32_t i; } y = { x };
7+
int ee = y.i>>23 & 0xff;
8+
9+
if (!ee) {
10+
if (x) {
11+
x = frexpf(x*0x1p64, e);
12+
*e -= 64;
13+
} else *e = 0;
14+
return x;
15+
} else if (ee == 0xff) {
16+
return x;
17+
}
18+
19+
*e = ee - 0x7e;
20+
y.i &= 0x807ffffful;
21+
y.i |= 0x3f000000ul;
22+
return y.f;
23+
}
+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#include <math.h>
2+
#include <stdint.h>
3+
#include <float.h>
4+
5+
#if LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384
6+
7+
/* This version is for 80-bit little endian long double */
8+
9+
long double frexpl(long double x, int *e)
10+
{
11+
union { long double ld; uint16_t hw[5]; } y = { x };
12+
int ee = y.hw[4]&0x7fff;
13+
14+
if (!ee) {
15+
if (x) {
16+
x = frexpl(x*0x1p64, e);
17+
*e -= 64;
18+
} else *e = 0;
19+
return x;
20+
} else if (ee == 0x7fff) {
21+
return x;
22+
}
23+
24+
*e = ee - 0x3ffe;
25+
y.hw[4] &= 0x8000;
26+
y.hw[4] |= 0x3ffe;
27+
return y.ld;
28+
}
29+
30+
#else
31+
32+
long double frexpl(long double x, int *e)
33+
{
34+
return frexp(x, e);
35+
}
36+
37+
#endif
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#define _GNU_SOURCE
2+
#include <stdio.h>
3+
#include <stdarg.h>
4+
5+
int asprintf(char **s, const char *fmt, ...)
6+
{
7+
int ret;
8+
va_list ap;
9+
va_start(ap, fmt);
10+
ret = vasprintf(s, fmt, ap);
11+
va_end(ap);
12+
return ret;
13+
}
+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#include "stdio_impl.h"
2+
#include <string.h>
3+
4+
size_t __fwritex(const unsigned char *restrict s, size_t l, FILE *restrict f)
5+
{
6+
size_t i=0;
7+
8+
if (!f->wend && __towrite(f)) return 0;
9+
10+
if (l > f->wend - f->wpos) return f->write(f, s, l);
11+
12+
if (f->lbf >= 0) {
13+
/* Match /^(.*\n|)/ */
14+
for (i=l; i && s[i-1] != '\n'; i--);
15+
if (i) {
16+
if (f->write(f, s, i) < i)
17+
return i;
18+
s += i;
19+
l -= i;
20+
}
21+
}
22+
23+
memcpy(f->wpos, s, l);
24+
f->wpos += l;
25+
return l+i;
26+
}
27+
28+
// XXX Emscripten: Not used, since we are not currently using musl file IO.
29+
#if 0
30+
size_t fwrite(const void *restrict src, size_t size, size_t nmemb, FILE *restrict f)
31+
{
32+
size_t k, l = size*nmemb;
33+
if (!l) return l;
34+
FLOCK(f);
35+
k = __fwritex(src, l, f);
36+
FUNLOCK(f);
37+
return k==l ? nmemb : k/size;
38+
}
39+
#endif
40+
41+
weak_alias(fwrite, fwrite_unlocked);
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include <stdio.h>
2+
#include <stdarg.h>
3+
4+
int sprintf(char *restrict s, const char *restrict fmt, ...)
5+
{
6+
int ret;
7+
va_list ap;
8+
va_start(ap, fmt);
9+
ret = vsprintf(s, fmt, ap);
10+
va_end(ap);
11+
return ret;
12+
}
+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#define _GNU_SOURCE
2+
#include <stdio.h>
3+
#include <stdarg.h>
4+
#include <stdlib.h>
5+
6+
#define GUESS 240U
7+
8+
int vasprintf(char **s, const char *fmt, va_list ap)
9+
{
10+
va_list ap2;
11+
char *a;
12+
int l=GUESS;
13+
14+
if (!(a=malloc(GUESS))) return -1;
15+
16+
va_copy(ap2, ap);
17+
l=vsnprintf(a, GUESS, fmt, ap2);
18+
va_end(ap2);
19+
20+
if (l<GUESS) {
21+
char *b = realloc(a, l+1U);
22+
*s = b ? b : a;
23+
return l;
24+
}
25+
free(a);
26+
if (l<0 || !(*s=malloc(l+1U))) return -1;
27+
return vsnprintf(*s, l+1U, fmt, ap);
28+
}

0 commit comments

Comments
 (0)