diff options
Diffstat (limited to 'src/library.js')
-rw-r--r-- | src/library.js | 141 |
1 files changed, 124 insertions, 17 deletions
diff --git a/src/library.js b/src/library.js index 0e5919ad..7438b0ad 100644 --- a/src/library.js +++ b/src/library.js @@ -612,7 +612,7 @@ LibraryManager.library = { }, deleteFile: function(path) { - var path = FS.analyzePath(path); + path = FS.analyzePath(path); if (!path.parentExists || !path.exists) { throw 'Invalid path ' + path; } @@ -3549,21 +3549,42 @@ LibraryManager.library = { * this implementation simply uses malloc underneath the call to * mmap. */ + if (!_mmap.mappings) _mmap.mappings = {}; if (stream == -1) { var ptr = _malloc(num); - _memset(ptr, 0, num); - return ptr; + } else { + var info = FS.streams[stream]; + if (!info) return -1; + var contents = info.object.contents; + contents = Array.prototype.slice.call(contents, offset, offset+num); + ptr = allocate(contents, 'i8', ALLOC_NORMAL); + } + // align to page size + var ret = ptr; + if (ptr % PAGE_SIZE != 0) { + var old = ptr; + ptr = _malloc(num + PAGE_SIZE); + ret = alignMemoryPage(ptr); + _memcpy(ret, old, num); + _free(old); } - var info = FS.streams[stream]; - if (!info) return -1; - var contents = info.object.contents; - contents = Array.prototype.slice.call(contents, offset, offset+num); - return allocate(contents, 'i8', ALLOC_NORMAL); + if (stream == -1) { + _memset(ret, 0, num); + } + _mmap.mappings[ret] = { malloc: ptr, num: num }; + return ret; }, __01mmap64_: 'mmap', munmap: function(start, num) { - _free(start); + if (!_mmap.mappings) _mmap.mappings = {}; + // TODO: support unmmap'ing parts of allocations + var info = _mmap.mappings[start]; + if (!info) return 0; + if (num == info.num) { + _mmap.mappings[start] = null; + _free(info.malloc); + } return 0; }, @@ -3819,9 +3840,73 @@ LibraryManager.library = { return ret; }, - strtoll__deps: ['_parseInt'], +#if USE_TYPED_ARRAYS == 2 + _parseInt64__deps: ['isspace', '__setErrNo', '$ERRNO_CODES', function() { Types.preciseI64MathUsed = 1 }], + _parseInt64: function(str, endptr, base, min, max, unsign) { + var start = str; + // Skip space. + while (_isspace({{{ makeGetValue('str', 0, 'i8') }}})) str++; + + // Check for a plus/minus sign. + if ({{{ makeGetValue('str', 0, 'i8') }}} == '-'.charCodeAt(0)) { + str++; + } else if ({{{ makeGetValue('str', 0, 'i8') }}} == '+'.charCodeAt(0)) { + str++; + } + + // Find base. + var ok = false; + var finalBase = base; + if (!finalBase) { + if ({{{ makeGetValue('str', 0, 'i8') }}} == '0'.charCodeAt(0)) { + if ({{{ makeGetValue('str+1', 0, 'i8') }}} == 'x'.charCodeAt(0) || + {{{ makeGetValue('str+1', 0, 'i8') }}} == 'X'.charCodeAt(0)) { + finalBase = 16; + str += 2; + } else { + finalBase = 8; + str++; + ok = true; // we saw an initial zero, perhaps the entire thing is just "0" + } + } + } + if (!finalBase) finalBase = 10; + + // Get digits. + var chr; + while ((chr = {{{ makeGetValue('str', 0, 'i8') }}}) != 0) { + var digit = parseInt(String.fromCharCode(chr), finalBase); + if (isNaN(digit)) { + break; + } else { + str++; + ok = true; + } + } + if (!ok) { + ___setErrNo(ERRNO_CODES.EINVAL); + return [0, 0]; + } + + try { + i64Math.fromString(Pointer_stringify(start, str - start), finalBase, min, max, unsign); + } catch(e) { + ___setErrNo(ERRNO_CODES.ERANGE); // not quite correct + } + + // Set end pointer. + if (endptr) { + {{{ makeSetValue('endptr', 0, 'str', '*') }}} + } + + var ret = i64Math.result.slice(0); + + return ret; + }, +#endif + strtoll__deps: ['_parseInt64'], strtoll: function(str, endptr, base) { - return __parseInt(str, endptr, base, -9223372036854775200, 9223372036854775200, 64); // LLONG_MIN, LLONG_MAX; imprecise. + return __parseInt64(str, endptr, base, '-9223372036854775808', '9223372036854775807'); // LLONG_MIN, LLONG_MAX. }, strtoll_l: 'strtoll', // no locale support yet strtol__deps: ['_parseInt'], @@ -3834,9 +3919,9 @@ LibraryManager.library = { return __parseInt(str, endptr, base, 0, 4294967295, 32, true); // ULONG_MAX. }, strtoul_l: 'strtoul', // no locale support yet - strtoull__deps: ['_parseInt'], + strtoull__deps: ['_parseInt64'], strtoull: function(str, endptr, base) { - return __parseInt(str, endptr, base, 0, 18446744073709551615, 64, true); // ULONG_MAX; imprecise. + return __parseInt64(str, endptr, base, 0, '18446744073709551615', true); // ULONG_MAX. }, strtoull_l: 'strtoull', // no locale support yet @@ -4746,6 +4831,17 @@ LibraryManager.library = { return ((x&0xff)<<24) | (((x>>8)&0xff)<<16) | (((x>>16)&0xff)<<8) | (x>>>24); }, + llvm_bswap_i64__deps: ['llvm_bswap_i32'], + llvm_bswap_i64: function(l, h) { + var retl = _llvm_bswap_i32(h)>>>0; + var reth = _llvm_bswap_i32(l)>>>0; +#if USE_TYPED_ARRAYS == 2 + return [retl, reth]; +#else + throw 'unsupported'; +#endif + }, + llvm_ctlz_i32: function(x) { for (var i=0; i<32; i++) { if ( (x & (1 << (31-i))) != 0 ) { @@ -4755,17 +4851,28 @@ LibraryManager.library = { return 32; }, + llvm_ctlz_i64__deps: ['llvm_ctlz_i32'], + llvm_ctlz_i64: function(l, h) { + var ret = _llvm_ctlz_i32(h); + if (ret == 32) ret += _llvm_ctlz_i32(l); +#if USE_TYPED_ARRAYS == 2 + return [ret, 0]; +#else + return ret; +#endif + }, + llvm_trap: function() { throw 'trap! ' + new Error().stack; }, __assert_fail: function(condition, file, line) { ABORT = true; - throw 'Assertion failed: ' + Pointer_stringify(condition);//JSON.stringify(arguments)//condition; + throw 'Assertion failed: ' + Pointer_stringify(condition) + ' at ' + new Error().stack; }, __assert_func: function(filename, line, func, condition) { - throw 'Assertion failed: ' + (condition ? Pointer_stringify(condition) : 'unknown condition') + ', at: ' + [filename ? Pointer_stringify(filename) : 'unknown filename', line, func ? Pointer_stringify(func) : 'unknown function']; + throw 'Assertion failed: ' + (condition ? Pointer_stringify(condition) : 'unknown condition') + ', at: ' + [filename ? Pointer_stringify(filename) : 'unknown filename', line, func ? Pointer_stringify(func) : 'unknown function'] + ' at ' + new Error().stack; }, __cxa_guard_acquire: function(variable) { @@ -5091,8 +5198,8 @@ LibraryManager.library = { return ret; }, - llvm_expect_i32__inline: function(x, y) { - return '((' + x + ')==(' + y + '))'; + llvm_expect_i32__inline: function(val, expected) { + return '(' + val + ')'; }, llvm_lifetime_start: function() {}, |