aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2014-02-06 22:47:23 -0500
committerAlon Zakai <alonzakai@gmail.com>2014-02-06 22:47:23 -0500
commitc95b10cff38fabf23a763d1889d024f6dabd4955 (patch)
treedc014fab60c42ef06c08956773e66f6fa0f83de1
parent11a84a636ce9722053cc3100d5c04e30e9f93df2 (diff)
parent831bb584a91f5409af5df3c44f1bc8dc354ff0d8 (diff)
Merge pull request #2103 from juj/opt_cmp1.10.2
Add optimized versions of musl libc string and memory comparison functions.
-rwxr-xr-xemcc8
-rw-r--r--src/library.js73
-rw-r--r--system/lib/libc.symbols9
-rw-r--r--system/lib/libc/musl/src/locale/strcoll.c15
-rw-r--r--system/lib/libc/musl/src/string/memcmp.c8
-rw-r--r--system/lib/libc/musl/src/string/strcasecmp.c9
-rw-r--r--system/lib/libc/musl/src/string/strcmp.c7
-rw-r--r--system/lib/libc/musl/src/string/strncasecmp.c10
-rw-r--r--system/lib/libc/musl/src/string/strncmp.c9
-rw-r--r--tests/core/test_strcmp_uni.out6
-rw-r--r--tests/test_core.py7
-rw-r--r--tools/shared.py2
12 files changed, 85 insertions, 78 deletions
diff --git a/emcc b/emcc
index 6bf74707..dd329006 100755
--- a/emcc
+++ b/emcc
@@ -1476,6 +1476,13 @@ try:
['stdlib', [
'atof.c',
'strtod.c',
+ ]],
+ ['string', [
+ 'memcmp.c',
+ 'strcasecmp.c',
+ 'strcmp.c',
+ 'strncasecmp.c',
+ 'strncmp.c',
]]
]
for directory, sources in musl_files:
@@ -1538,6 +1545,7 @@ try:
'iswspace_l.c',
'iswupper_l.c',
'iswxdigit_l.c',
+ 'strcoll.c',
'strcasecmp_l.c',
'strfmon.c',
'strncasecmp_l.c',
diff --git a/src/library.js b/src/library.js
index 3a5f6480..4f57c324 100644
--- a/src/library.js
+++ b/src/library.js
@@ -3761,79 +3761,6 @@ LibraryManager.library = {
return pdest;
},
- strcmp__deps: ['strncmp'],
- strcmp: function(px, py) {
- return _strncmp(px, py, TOTAL_MEMORY);
- },
- // We always assume ASCII locale.
- strcoll: 'strcmp',
- strcoll_l__deps: ['strcoll'],
- strcoll_l: function(px, py) {
- return _strcoll(px, py); // no locale support yet
- },
-
- strcasecmp__asm: true,
- strcasecmp__sig: 'iii',
- strcasecmp__deps: ['strncasecmp'],
- strcasecmp: function(px, py) {
- px = px|0; py = py|0;
- return _strncasecmp(px, py, -1)|0;
- },
-
- strncmp: function(px, py, n) {
- var i = 0;
- while (i < n) {
- var x = {{{ makeGetValue('px', 'i', 'i8', 0, 1) }}};
- var y = {{{ makeGetValue('py', 'i', 'i8', 0, 1) }}};
- if (x == y && x == 0) return 0;
- if (x == 0) return -1;
- if (y == 0) return 1;
- if (x == y) {
- i ++;
- continue;
- } else {
- return x > y ? 1 : -1;
- }
- }
- return 0;
- },
-
- strncasecmp__asm: true,
- strncasecmp__sig: 'iiii',
- strncasecmp__deps: ['tolower'],
- strncasecmp: function(px, py, n) {
- px = px|0; py = py|0; n = n|0;
- var i = 0, x = 0, y = 0;
- while ((i>>>0) < (n>>>0)) {
- x = _tolower({{{ makeGetValueAsm('px', 'i', 'i8', 0, 1) }}})|0;
- y = _tolower({{{ makeGetValueAsm('py', 'i', 'i8', 0, 1) }}})|0;
- if (((x|0) == (y|0)) & ((x|0) == 0)) return 0;
- if ((x|0) == 0) return -1;
- if ((y|0) == 0) return 1;
- if ((x|0) == (y|0)) {
- i = (i + 1)|0;
- continue;
- } else {
- return ((x>>>0) > (y>>>0) ? 1 : -1)|0;
- }
- }
- return 0;
- },
-
- memcmp__asm: true,
- memcmp__sig: 'iiii',
- memcmp: function(p1, p2, num) {
- p1 = p1|0; p2 = p2|0; num = num|0;
- var i = 0, v1 = 0, v2 = 0;
- while ((i|0) < (num|0)) {
- v1 = {{{ makeGetValueAsm('p1', 'i', 'i8', true) }}};
- v2 = {{{ makeGetValueAsm('p2', 'i', 'i8', true) }}};
- if ((v1|0) != (v2|0)) return ((v1|0) > (v2|0) ? 1 : -1)|0;
- i = (i+1)|0;
- }
- return 0;
- },
-
memchr: function(ptr, chr, num) {
chr = unSign(chr);
for (var i = 0; i < num; i++) {
diff --git a/system/lib/libc.symbols b/system/lib/libc.symbols
index 6f80ef90..53a27082 100644
--- a/system/lib/libc.symbols
+++ b/system/lib/libc.symbols
@@ -72,7 +72,16 @@
W realloc_in_place
T scalbn
T scalbnl
+ T memcmp
+ T memcpy
T strtod
+ T strcoll
+ T __strcoll_l
+ W strcoll_l
+ T strcmp
+ T strncmp
+ T strcasecmp
+ T strncasecmp
T strtod_l
T strtof
T strtof_l
diff --git a/system/lib/libc/musl/src/locale/strcoll.c b/system/lib/libc/musl/src/locale/strcoll.c
new file mode 100644
index 00000000..39ea1123
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/strcoll.c
@@ -0,0 +1,15 @@
+#include <string.h>
+#include <locale.h>
+#include "libc.h"
+
+int __strcoll_l(const char *l, const char *r, locale_t loc)
+{
+ return strcmp(l, r);
+}
+
+int strcoll(const char *l, const char *r)
+{
+ return __strcoll_l(l, r, 0);
+}
+
+weak_alias(__strcoll_l, strcoll_l);
diff --git a/system/lib/libc/musl/src/string/memcmp.c b/system/lib/libc/musl/src/string/memcmp.c
new file mode 100644
index 00000000..bdbce9f0
--- /dev/null
+++ b/system/lib/libc/musl/src/string/memcmp.c
@@ -0,0 +1,8 @@
+#include <string.h>
+
+int memcmp(const void *vl, const void *vr, size_t n)
+{
+ const unsigned char *l=vl, *r=vr;
+ for (; n && *l == *r; n--, l++, r++);
+ return n ? *l-*r : 0;
+}
diff --git a/system/lib/libc/musl/src/string/strcasecmp.c b/system/lib/libc/musl/src/string/strcasecmp.c
new file mode 100644
index 00000000..02fd5f8c
--- /dev/null
+++ b/system/lib/libc/musl/src/string/strcasecmp.c
@@ -0,0 +1,9 @@
+#include <strings.h>
+#include <ctype.h>
+
+int strcasecmp(const char *_l, const char *_r)
+{
+ const unsigned char *l=(void *)_l, *r=(void *)_r;
+ for (; *l && *r && (*l == *r || tolower(*l) == tolower(*r)); l++, r++);
+ return tolower(*l) - tolower(*r);
+}
diff --git a/system/lib/libc/musl/src/string/strcmp.c b/system/lib/libc/musl/src/string/strcmp.c
new file mode 100644
index 00000000..91eb7404
--- /dev/null
+++ b/system/lib/libc/musl/src/string/strcmp.c
@@ -0,0 +1,7 @@
+#include <string.h>
+
+int strcmp(const char *l, const char *r)
+{
+ for (; *l==*r && *l && *r; l++, r++);
+ return *(unsigned char *)l - *(unsigned char *)r;
+}
diff --git a/system/lib/libc/musl/src/string/strncasecmp.c b/system/lib/libc/musl/src/string/strncasecmp.c
new file mode 100644
index 00000000..24659721
--- /dev/null
+++ b/system/lib/libc/musl/src/string/strncasecmp.c
@@ -0,0 +1,10 @@
+#include <strings.h>
+#include <ctype.h>
+
+int strncasecmp(const char *_l, const char *_r, size_t n)
+{
+ const unsigned char *l=(void *)_l, *r=(void *)_r;
+ if (!n--) return 0;
+ for (; *l && *r && n && (*l == *r || tolower(*l) == tolower(*r)); l++, r++, n--);
+ return tolower(*l) - tolower(*r);
+}
diff --git a/system/lib/libc/musl/src/string/strncmp.c b/system/lib/libc/musl/src/string/strncmp.c
new file mode 100644
index 00000000..e228843f
--- /dev/null
+++ b/system/lib/libc/musl/src/string/strncmp.c
@@ -0,0 +1,9 @@
+#include <string.h>
+
+int strncmp(const char *_l, const char *_r, size_t n)
+{
+ const unsigned char *l=(void *)_l, *r=(void *)_r;
+ if (!n--) return 0;
+ for (; *l && *r && n && *l == *r ; l++, r++, n--);
+ return *l - *r;
+}
diff --git a/tests/core/test_strcmp_uni.out b/tests/core/test_strcmp_uni.out
index 58e237d7..ebfe2c8e 100644
--- a/tests/core/test_strcmp_uni.out
+++ b/tests/core/test_strcmp_uni.out
@@ -1,3 +1,3 @@
-Compare value strncmp is -1
-Compare value strncasecmp is -1
-Compare value memcmp is -1
+Compare value strncmp is -108
+Compare value strncasecmp is -76
+Compare value memcmp is -108
diff --git a/tests/test_core.py b/tests/test_core.py
index 47360fd6..a77d2465 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -3264,6 +3264,7 @@ def process(filename):
#include <assert.h>
#include <stdio.h>
#include <dlfcn.h>
+ #include <string.h>
typedef int (*FUNCTYPE)(const char *);
@@ -3274,6 +3275,10 @@ def process(filename):
snprintf(str, sizeof(str), "foobar");
+ // HACK: Use strcmp in the main executable so that it doesn't get optimized out and the dynamic library
+ // is able to use it.
+ assert(!strcmp(str, "foobar"));
+
lib_handle = dlopen("liblib.so", RTLD_NOW);
assert(lib_handle != NULL);
@@ -3286,7 +3291,7 @@ def process(filename):
return 0;
}
'''
- Settings.EXPORTED_FUNCTIONS = ['_main', '_malloc']
+ Settings.EXPORTED_FUNCTIONS = ['_main', '_malloc', '_strcmp']
self.do_run(src, 'success', force_c=True, post_build=self.dlfcn_post_build)
def test_dlfcn_funcs(self):
diff --git a/tools/shared.py b/tools/shared.py
index 3b0b92a3..dbf1e3ef 100644
--- a/tools/shared.py
+++ b/tools/shared.py
@@ -345,7 +345,7 @@ def find_temp_directory():
# we re-check sanity when the settings are changed)
# We also re-check sanity and clear the cache when the version changes
-EMSCRIPTEN_VERSION = '1.10.1'
+EMSCRIPTEN_VERSION = '1.10.2'
def generate_sanity():
return EMSCRIPTEN_VERSION + '|' + get_llvm_target() + '|' + LLVM_ROOT + '|' + get_clang_version()