aboutsummaryrefslogtreecommitdiff
path: root/src/library.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/library.js')
-rw-r--r--src/library.js393
1 files changed, 334 insertions, 59 deletions
diff --git a/src/library.js b/src/library.js
index ebd80daf..bb73c48a 100644
--- a/src/library.js
+++ b/src/library.js
@@ -26,8 +26,16 @@ LibraryManager.library = {
_impure_ptr: 0,
$FS__deps: ['$ERRNO_CODES', '__setErrNo', 'stdin', 'stdout', 'stderr', '_impure_ptr'],
- $FS__postset: '__ATINIT__.unshift({ func: function() { FS.ignorePermissions = false; if (!FS.init.initialized) FS.init() } });' +
- '__ATEXIT__.push({ func: function() { FS.quit() } });',
+ $FS__postset: '__ATINIT__.unshift({ func: function() { if (!Module["noFSInit"] && !FS.init.initialized) FS.init() } });' +
+ '__ATMAIN__.push({ func: function() { FS.ignorePermissions = false } });' +
+ '__ATEXIT__.push({ func: function() { FS.quit() } });' +
+ // export some names through closure
+ 'Module["FS_createFolder"] = FS.createFolder;' +
+ 'Module["FS_createPath"] = FS.createPath;' +
+ 'Module["FS_createDataFile"] = FS.createDataFile;' +
+ 'Module["FS_createLazyFile"] = FS.createLazyFile;' +
+ 'Module["FS_createLink"] = FS.createLink;' +
+ 'Module["FS_createDevice"] = FS.createDevice;',
$FS: {
// The path to the current folder.
currentPath: '/',
@@ -86,6 +94,23 @@ LibraryManager.library = {
parentPath: null,
parentObject: null
};
+#if FS_LOG
+ var inputPath = path;
+ function log() {
+ Module['print']('FS.analyzePath("' + inputPath + '", ' +
+ dontResolveLastLink + ', ' +
+ linksVisited + ') => {' +
+ 'isRoot: ' + ret.isRoot + ', ' +
+ 'exists: ' + ret.exists + ', ' +
+ 'error: ' + ret.error + ', ' +
+ 'name: "' + ret.name + '", ' +
+ 'path: "' + ret.path + '", ' +
+ 'object: ' + ret.object + ', ' +
+ 'parentExists: ' + ret.parentExists + ', ' +
+ 'parentPath: "' + ret.parentPath + '", ' +
+ 'parentObject: ' + ret.parentObject + '}');
+ }
+#endif
path = FS.absolutePath(path);
if (path == '/') {
ret.isRoot = true;
@@ -123,8 +148,12 @@ LibraryManager.library = {
break;
}
var link = FS.absolutePath(current.link, traversed.join('/'));
- return FS.analyzePath([link].concat(path).join('/'),
- dontResolveLastLink, linksVisited + 1);
+ ret = FS.analyzePath([link].concat(path).join('/'),
+ dontResolveLastLink, linksVisited + 1);
+#if FS_LOG
+ log();
+#endif
+ return ret;
}
traversed.push(target);
if (path.length == 0) {
@@ -133,8 +162,10 @@ LibraryManager.library = {
ret.object = current;
}
}
- return ret;
}
+#if FS_LOG
+ log();
+#endif
return ret;
},
// Finds the file system object at a given path. If dontResolveLastLink is
@@ -152,6 +183,13 @@ LibraryManager.library = {
},
// Creates a file system record: file, link, device or folder.
createObject: function(parent, name, properties, canRead, canWrite) {
+#if FS_LOG
+ Module['print']('FS.createObject("' + parent + '", ' +
+ '"' + name + '", ' +
+ JSON.stringify(properties) + ', ' +
+ canRead + ', ' +
+ canWrite + ')');
+#endif
if (!parent) parent = '/';
if (typeof parent === 'string') parent = FS.findObject(parent);
@@ -226,11 +264,20 @@ LibraryManager.library = {
var properties = {isDevice: false, contents: data};
return FS.createFile(parent, name, properties, canRead, canWrite);
},
- // Creates a file record for lazy-loading from a URL.
+ // Creates a file record for lazy-loading from a URL. XXX This requires a synchronous
+ // XHR, which is not possible in browsers except in a web worker! Use preloading,
+ // either --preload-file in emcc or FS.createPreloadedFile
createLazyFile: function(parent, name, url, canRead, canWrite) {
var properties = {isDevice: false, url: url};
return FS.createFile(parent, name, properties, canRead, canWrite);
},
+ // Preloads a file asynchronously. You can call this before run, for example in
+ // preRun. run will be delayed until this file arrives and is set up.
+ createPreloadedFile: function(parent, name, url, canRead, canWrite) {
+ Browser.asyncLoad(url, function(data) {
+ FS.createDataFile(parent, name, data, canRead, canWrite);
+ });
+ },
// Creates a link to a sepcific local path.
createLink: function(parent, name, target, canRead, canWrite) {
var properties = {isDevice: false, link: target};
@@ -309,6 +356,7 @@ LibraryManager.library = {
typeof window.prompt == 'function') {
// Browser.
result = window.prompt('Input: ');
+ if (result === null) result = String.fromCharCode(0); // cancel ==> EOF
} else if (typeof readline == 'function') {
// Command line.
result = readline();
@@ -340,8 +388,10 @@ LibraryManager.library = {
if (!error.printer) error.printer = Module['print'];
if (!error.buffer) error.buffer = [];
- // Create the temporary folder.
- FS.createFolder('/', 'tmp', true, true);
+ // Create the temporary folder, if not already created
+ try {
+ FS.createFolder('/', 'tmp', true, true);
+ } catch(e) {}
// Create the I/O devices.
var devFolder = FS.createFolder('/', 'dev', true, true);
@@ -408,6 +458,21 @@ LibraryManager.library = {
// Flush any partially-printed lines in stdout and stderr. Careful, they may have been closed
if (FS.streams[2] && FS.streams[2].object.output.buffer.length > 0) FS.streams[2].object.output('\n'.charCodeAt(0));
if (FS.streams[3] && FS.streams[3].object.output.buffer.length > 0) FS.streams[3].object.output('\n'.charCodeAt(0));
+ },
+
+ // Standardizes a path. Useful for making comparisons of pathnames work in a consistent manner.
+ // For example, ./file and file are really the same, so this function will remove ./
+ standardizePath: function(path) {
+ if (path.substr(0, 2) == './') path = path.substr(2);
+ return path;
+ },
+
+ deleteFile: function(path) {
+ var path = FS.analyzePath(path);
+ if (!path.parentExists || !path.exists) {
+ throw 'Invalid path ' + path;
+ }
+ delete path.parentObject.contents[path.name];
}
},
@@ -1430,7 +1495,7 @@ LibraryManager.library = {
lseek: function(fildes, offset, whence) {
// off_t lseek(int fildes, off_t offset, int whence);
// http://pubs.opengroup.org/onlinepubs/000095399/functions/lseek.html
- if (FS.streams[fildes] && !FS.streams[fildes].isDevice) {
+ if (FS.streams[fildes] && !FS.streams[fildes].object.isDevice) {
var stream = FS.streams[fildes];
var position = offset;
if (whence === 1) { // SEEK_CUR.
@@ -1821,7 +1886,7 @@ LibraryManager.library = {
#if CATCH_EXIT_CODE
throw new ExitStatus();
-#else
+#else
throw 'exit(' + status + ') called, at ' + new Error().stack;
#endif
},
@@ -2171,6 +2236,9 @@ LibraryManager.library = {
if (!self.called) {
STATICTOP = alignMemoryPage(STATICTOP); // make sure we start out aligned
self.called = true;
+#if GC_SUPPORT
+ _sbrk.DYNAMIC_START = STATICTOP;
+#endif
}
var ret = STATICTOP;
if (bytes != 0) Runtime.staticAlloc(bytes);
@@ -2196,6 +2264,15 @@ LibraryManager.library = {
// TODO: Document.
_scanString__deps: ['_isFloat'],
_scanString: function(format, get, unget, varargs) {
+ if (!__scanString.whiteSpace) {
+ __scanString.whiteSpace = {};
+ __scanString.whiteSpace[' '.charCodeAt(0)] = 1;
+ __scanString.whiteSpace['\t'.charCodeAt(0)] = 1;
+ __scanString.whiteSpace['\n'.charCodeAt(0)] = 1;
+ __scanString.whiteSpace[' '] = 1;
+ __scanString.whiteSpace['\t'] = 1;
+ __scanString.whiteSpace['\n'] = 1;
+ }
// Supports %x, %4x, %d.%d, %s, %f, %lf.
// TODO: Support all format specifiers.
format = Pointer_stringify(format);
@@ -2203,6 +2280,7 @@ LibraryManager.library = {
var argsi = 0;
var fields = 0;
var argIndex = 0;
+ var next;
for (var formatIndex = 0; formatIndex < format.length; formatIndex++) {
if (next <= 0) return fields;
var next = get();
@@ -2218,11 +2296,14 @@ LibraryManager.library = {
if (formatIndex != maxSpecifierStart) {
max_ = parseInt(format.slice(maxSpecifierStart, formatIndex), 10);
}
- // TODO: Handle type size modifier.
var long_ = false;
+ var half = false;
if (format[formatIndex] == 'l') {
long_ = true;
formatIndex++;
+ } else if (format[formatIndex] == 'h') {
+ half = true;
+ formatIndex++;
}
var type = format[formatIndex];
formatIndex++;
@@ -2242,13 +2323,18 @@ LibraryManager.library = {
buffer.pop();
unget();
}
+ unget();
+ next = get();
} else {
+ var first = true;
while ((curr < max_ || isNaN(max_)) && next > 0) {
- if ((type === 'd' && next >= '0'.charCodeAt(0) && next <= '9'.charCodeAt(0)) ||
- (type === 'x' && (next >= '0'.charCodeAt(0) && next <= '9'.charCodeAt(0) ||
- next >= 'a'.charCodeAt(0) && next <= 'f'.charCodeAt(0) ||
- next >= 'A'.charCodeAt(0) && next <= 'F'.charCodeAt(0))) ||
- (type === 's') &&
+ if (!(next in __scanString.whiteSpace) && // stop on whitespace
+ (type == 's' ||
+ ((type === 'd' || type == 'u') && ((next >= '0'.charCodeAt(0) && next <= '9'.charCodeAt(0)) ||
+ (first && next == '-'.charCodeAt(0)))) ||
+ (type === 'x' && (next >= '0'.charCodeAt(0) && next <= '9'.charCodeAt(0) ||
+ next >= 'a'.charCodeAt(0) && next <= 'f'.charCodeAt(0) ||
+ next >= 'A'.charCodeAt(0) && next <= 'F'.charCodeAt(0)))) &&
(formatIndex >= format.length || next !== format[formatIndex].charCodeAt(0))) { // Stop when we read something that is coming up
buffer.push(String.fromCharCode(next));
next = get();
@@ -2256,6 +2342,7 @@ LibraryManager.library = {
} else {
break;
}
+ first = false;
}
}
if (buffer.length === 0) return 0; // Failure.
@@ -2263,8 +2350,12 @@ LibraryManager.library = {
var argPtr = {{{ makeGetValue('varargs', 'argIndex', 'void*') }}};
argIndex += Runtime.getNativeFieldSize('void*');
switch (type) {
- case 'd':
- {{{ makeSetValue('argPtr', 0, 'parseInt(text, 10)', 'i32') }}}
+ case 'd': case 'u':
+ if (half) {
+ {{{ makeSetValue('argPtr', 0, 'parseInt(text, 10)', 'i16') }}};
+ } else {
+ {{{ makeSetValue('argPtr', 0, 'parseInt(text, 10)', 'i32') }}};
+ }
break;
case 'x':
{{{ makeSetValue('argPtr', 0, 'parseInt(text, 16)', 'i32') }}}
@@ -2284,6 +2375,12 @@ LibraryManager.library = {
break;
}
fields++;
+ } else if (format[formatIndex] in __scanString.whiteSpace) {
+ while (next in __scanString.whiteSpace) {
+ next = get();
+ if (next <= 0) return fields; // End of input.
+ }
+ unget();
} else {
// Not a specifier.
if (format[formatIndex].charCodeAt(0) !== next) {
@@ -2442,6 +2539,10 @@ LibraryManager.library = {
var signed = next == 'd'.charCodeAt(0) || next == 'i'.charCodeAt(0);
argSize = argSize || 4;
var currArg = getNextArg('i' + (argSize * 8));
+#if PRECISE_I64_MATH == 1
+ var origArg = currArg;
+#endif
+ var argText;
#if USE_TYPED_ARRAYS == 2
// Flatten i64-1 [low, high] into a (slightly rounded) double
if (argSize == 8) {
@@ -2455,11 +2556,16 @@ LibraryManager.library = {
}
// Format the number.
var currAbsArg = Math.abs(currArg);
- var argText;
var prefix = '';
if (next == 'd'.charCodeAt(0) || next == 'i'.charCodeAt(0)) {
+#if PRECISE_I64_MATH == 1
+ if (argSize == 8 && i64Math) argText = i64Math.stringify(origArg[0], origArg[1]); else
+#endif
argText = reSign(currArg, 8 * argSize, 1).toString(10);
} else if (next == 'u'.charCodeAt(0)) {
+#if PRECISE_I64_MATH == 1
+ if (argSize == 8 && i64Math) argText = i64Math.stringify(origArg[0], origArg[1], true); else
+#endif
argText = unSign(currArg, 8 * argSize, 1).toString(10);
currArg = Math.abs(currArg);
} else if (next == 'o'.charCodeAt(0)) {
@@ -2611,24 +2717,19 @@ LibraryManager.library = {
});
} else if (next == 's'.charCodeAt(0)) {
// String.
- var arg = getNextArg('i8*');
- var copiedString;
- if (arg) {
- copiedString = String_copy(arg);
- if (precisionSet && copiedString.length > precision) {
- copiedString = copiedString.slice(0, precision);
- }
- } else {
- copiedString = intArrayFromString('(null)', true);
- }
+ var arg = getNextArg('i8*') || 0; // 0 holds '(null)'
+ var argLength = String_len(arg);
+ if (precisionSet) argLength = Math.min(String_len(arg), precision);
if (!flagLeftAlign) {
- while (copiedString.length < width--) {
+ while (argLength < width--) {
ret.push(' '.charCodeAt(0));
}
}
- ret = ret.concat(copiedString);
+ for (var i = 0; i < argLength; i++) {
+ ret.push({{{ makeGetValue('arg++', 0, 'i8', null, true) }}});
+ }
if (flagLeftAlign) {
- while (copiedString.length < width--) {
+ while (argLength < width--) {
ret.push(' '.charCodeAt(0));
}
}
@@ -2753,7 +2854,7 @@ LibraryManager.library = {
streamObj.error = true;
return -1;
} else {
- return {{{ makeGetValue('_fgetc.ret', '0', 'i8') }}};
+ return {{{ makeGetValue('_fgetc.ret', '0', 'i8', null, 1) }}};
}
},
getc: 'fgetc',
@@ -3248,8 +3349,9 @@ LibraryManager.library = {
}
var info = FS.streams[stream];
if (!info) return -1;
- return allocate(info.object.contents.slice(offset, offset+num),
- 'i8', ALLOC_NORMAL);
+ var contents = info.object.contents;
+ contents = Array.prototype.slice.call(contents, offset, offset+num);
+ return allocate(contents, 'i8', ALLOC_NORMAL);
},
__01mmap64_: 'mmap',
@@ -3311,9 +3413,9 @@ LibraryManager.library = {
},
__cxa_atexit: 'atexit',
- abort: function(code) {
+ abort: function() {
ABORT = true;
- throw 'ABORT: ' + code + ', at ' + (new Error().stack);
+ throw 'abort() at ' + (new Error().stack);
},
bsearch: function(key, base, num, size, compar) {
@@ -3357,6 +3459,8 @@ LibraryManager.library = {
strtod__deps: ['isspace', 'isdigit'],
strtod: function(str, endptr) {
+ var origin = str;
+
// Skip space.
while (_isspace({{{ makeGetValue('str', 0, 'i8') }}})) str++;
@@ -3373,26 +3477,35 @@ LibraryManager.library = {
var ret = 0;
// Get whole part.
+ var whole = false;
while(1) {
chr = {{{ makeGetValue('str', 0, 'i8') }}};
if (!_isdigit(chr)) break;
+ whole = true;
ret = ret*10 + chr - '0'.charCodeAt(0);
str++;
}
// Get fractional part.
+ var fraction = false;
if ({{{ makeGetValue('str', 0, 'i8') }}} == '.'.charCodeAt(0)) {
str++;
var mul = 1/10;
while(1) {
chr = {{{ makeGetValue('str', 0, 'i8') }}};
if (!_isdigit(chr)) break;
+ fraction = true;
ret += mul*(chr - '0'.charCodeAt(0));
mul /= 10;
str++;
}
}
+ if (!whole && !fraction) {
+ {{{ makeSetValue('endptr', 0, 'origin', '*') }}}
+ return 0;
+ }
+
// Get exponent part.
chr = {{{ makeGetValue('str', 0, 'i8') }}};
if (chr == 'e'.charCodeAt(0) || chr == 'E'.charCodeAt(0)) {
@@ -3424,6 +3537,9 @@ LibraryManager.library = {
return ret * multiplier;
},
+ strtod_l: 'strtod', // no locale support yet
+ strtold: 'strtod', // XXX add real support for long double
+ strtold_l: 'strtold', // no locale support yet
_parseInt__deps: ['isspace', '__setErrNo', '$ERRNO_CODES'],
_parseInt: function(str, endptr, base, min, max, bits, unsign) {
@@ -3564,7 +3680,7 @@ LibraryManager.library = {
ENV['USER'] = 'root';
ENV['PATH'] = '/';
ENV['PWD'] = '/';
- ENV['HOME'] = '/';
+ ENV['HOME'] = '/home/emscripten';
ENV['LANG'] = 'en_US.UTF-8';
ENV['_'] = './this.program';
// Allocate memory.
@@ -3900,19 +4016,35 @@ LibraryManager.library = {
},
strspn: function(pstr, pset) {
- var str = String_copy(pstr, true);
- var set = String_copy(pset);
- var i = 0;
- while (set.indexOf(str[i]) != -1) i++; // Must halt, as 0 is in str but not set
- return i;
+ var str = pstr, set, strcurr, setcurr;
+ while (1) {
+ strcurr = {{{ makeGetValue('str', '0', 'i8') }}};
+ if (!strcurr) return str - pstr;
+ set = pset;
+ while (1) {
+ setcurr = {{{ makeGetValue('set', '0', 'i8') }}};
+ if (!setcurr || setcurr == strcurr) break;
+ set++;
+ }
+ if (!setcurr) return str - pstr;
+ str++;
+ }
},
strcspn: function(pstr, pset) {
- var str = String_copy(pstr, true);
- var set = String_copy(pset, true);
- var i = 0;
- while (set.indexOf(str[i]) == -1) i++; // Must halt, as 0 is in both
- return i;
+ var str = pstr, set, strcurr, setcurr;
+ while (1) {
+ strcurr = {{{ makeGetValue('str', '0', 'i8') }}};
+ if (!strcurr) return str - pstr;
+ set = pset;
+ while (1) {
+ setcurr = {{{ makeGetValue('set', '0', 'i8') }}};
+ if (!setcurr || setcurr == strcurr) break;
+ set++;
+ }
+ if (setcurr) return str - pstr;
+ str++;
+ }
},
strcpy: function(pdest, psrc) {
@@ -3941,6 +4073,28 @@ LibraryManager.library = {
}
return pdest;
},
+
+ strlwr__deps:['tolower'],
+ strlwr: function(pstr){
+ var i = 0;
+ while(1) {
+ var x = {{{ makeGetValue('pstr', 'i', 'i8') }}};
+ if(x == 0) break;
+ {{{ makeSetValue('pstr', 'i', '_tolower(x)', 'i8') }}};
+ i++;
+ }
+ },
+
+ strupr__deps:['toupper'],
+ strupr: function(pstr){
+ var i = 0;
+ while(1) {
+ var x = {{{ makeGetValue('pstr', 'i', 'i8') }}};
+ if(x == 0) break;
+ {{{ makeSetValue('pstr', 'i', '_toupper(x)', 'i8') }}};
+ i++;
+ }
+ },
strcat__deps: ['strlen'],
strcat: function(pdest, psrc) {
@@ -4071,10 +4225,36 @@ LibraryManager.library = {
return newStr;
},
+ strndup__deps: ['strdup'],
+ strndup: function(ptr, size) {
+ var len = String_len(ptr);
+
+ if (size >= len) {
+ return _strdup(ptr);
+ }
+
+ if (size < 0) {
+ size = 0;
+ }
+
+ var newStr = _malloc(size + 1);
+ {{{ makeCopyValues('newStr', 'ptr', 'size', 'null', null, 1) }}};
+ {{{ makeSetValue('newStr', 'size', '0', 'i8') }}};
+ return newStr;
+ },
+
strpbrk: function(ptr1, ptr2) {
- var searchSet = Runtime.set.apply(null, String_copy(ptr2));
- while ({{{ makeGetValue('ptr1', 0, 'i8') }}}) {
- if ({{{ makeGetValue('ptr1', 0, 'i8') }}} in searchSet) return ptr1;
+ var curr;
+ var searchSet = {};
+ while (1) {
+ var curr = {{{ makeGetValue('ptr2++', 0, 'i8') }}};
+ if (!curr) break;
+ searchSet[curr] = 1;
+ }
+ while (1) {
+ curr = {{{ makeGetValue('ptr1', 0, 'i8') }}};
+ if (!curr) break;
+ if (curr in searchSet) return ptr1;
ptr1++;
}
return 0;
@@ -4202,11 +4382,13 @@ LibraryManager.library = {
isdigit: function(chr) {
return chr >= '0'.charCodeAt(0) && chr <= '9'.charCodeAt(0);
},
+ isdigit_l: 'isdigit', // no locale support yet
isxdigit: function(chr) {
return (chr >= '0'.charCodeAt(0) && chr <= '9'.charCodeAt(0)) ||
(chr >= 'a'.charCodeAt(0) && chr <= 'f'.charCodeAt(0)) ||
(chr >= 'A'.charCodeAt(0) && chr <= 'F'.charCodeAt(0));
},
+ isxdigit_l: 'isxdigit', // no locale support yet
isalnum: function(chr) {
return (chr >= '0'.charCodeAt(0) && chr <= '9'.charCodeAt(0)) ||
(chr >= 'a'.charCodeAt(0) && chr <= 'z'.charCodeAt(0)) ||
@@ -4336,6 +4518,21 @@ LibraryManager.library = {
*/
},
+ llvm_bswap_i16: function(x) {
+ x = unSign(x, 32);
+ var bytes = [];
+ bytes[0] = x & 255;
+ x >>= 8;
+ bytes[1] = x & 255;
+ x >>= 8;
+ var ret = 0;
+ ret <<= 8;
+ ret += bytes[0];
+ ret <<= 8;
+ ret += bytes[1];
+ return ret;
+ },
+
llvm_bswap_i32: function(x) {
x = unSign(x, 32);
var bytes = [];
@@ -4350,7 +4547,7 @@ LibraryManager.library = {
}
return ret;
},
-
+
llvm_ctlz_i32: function(x) {
for (var i=0; i<32; i++) {
if ( (x & (1 << (31-i))) != 0 ) {
@@ -4529,12 +4726,12 @@ LibraryManager.library = {
// return the type of the catch block which should be called.
for (var i = 0; i < typeArray.length; i++) {
if (___cxa_does_inherit(typeArray[i], throwntype, thrown))
- return { 'f0':thrown, 'f1':typeArray[i]};
+ return { f0:thrown, f1:typeArray[i] };
}
// Shouldn't happen unless we have bogus data in typeArray
// or encounter a type for which emscripten doesn't have suitable
// typeinfo defined. Best-efforts match just in case.
- return {'f0':thrown,'f1':throwntype};
+ return { f0:thrown, f1 :throwntype };
},
// Recursively walks up the base types of 'possibilityType'
@@ -4596,17 +4793,75 @@ LibraryManager.library = {
// type_info for void*.
_ZTIPv: [0],
+ llvm_uadd_with_overflow_i8: function(x, y) {
+ x = x & 0xff;
+ y = y & 0xff;
+ return {
+ f0: (x+y) & 0xff,
+ f1: x+y > 255
+ };
+ },
+
+ llvm_umul_with_overflow_i8: function(x, y) {
+ x = x & 0xff;
+ y = y & 0xff;
+ return {
+ f0: (x*y) & 0xff,
+ f1: x*y > 255
+ };
+ },
+
+ llvm_uadd_with_overflow_i16: function(x, y) {
+ x = x & 0xffff;
+ y = y & 0xffff;
+ return {
+ f0: (x+y) & 0xffff,
+ f1: x+y > 65535
+ };
+ },
+
+ llvm_umul_with_overflow_i16: function(x, y) {
+ x = x & 0xffff;
+ y = y & 0xffff;
+ return {
+ f0: (x*y) & 0xffff,
+ f1: x*y > 65535
+ };
+ },
+
llvm_uadd_with_overflow_i32: function(x, y) {
+ x = x>>>0;
+ y = y>>>0;
return {
- f0: x+y,
- f1: 0 // We never overflow... for now
+ f0: (x+y)>>>0,
+ f1: x+y > 4294967295
};
},
llvm_umul_with_overflow_i32: function(x, y) {
+ x = x>>>0;
+ y = y>>>0;
return {
- f0: x*y,
- f1: 0 // We never overflow... for now
+ f0: (x*y)>>>0,
+ f1: x*y > 4294967295
+ };
+ },
+
+ llvm_uadd_with_overflow_i64__deps: [function() { preciseI64MathUsed = 1 }],
+ llvm_uadd_with_overflow_i64: function(xl, xh, yl, yh) {
+ i64Math.add(xl, xh, yl, yh);
+ return {
+ f0: i64Math.result,
+ f1: 0 // XXX Need to hack support for this in long.js
+ };
+ },
+
+ llvm_umul_with_overflow_i64__deps: [function() { preciseI64MathUsed = 1 }],
+ llvm_umul_with_overflow_i64: function(xl, xh, yl, yh) {
+ i64Math.mul(xl, xh, yl, yh);
+ return {
+ f0: i64Math.result,
+ f1: 0 // XXX Need to hack support for this in long.js
};
},
@@ -4649,6 +4904,11 @@ LibraryManager.library = {
llvm_lifetime_start: function() {},
llvm_lifetime_end: function() {},
+ llvm_invariant_start: function() {},
+ llvm_invariant_end: function() {},
+
+ llvm_objectsize_i32: function() { return -1 }, // TODO: support this
+
// ==========================================================================
// math.h
// ==========================================================================
@@ -4873,7 +5133,7 @@ LibraryManager.library = {
if (isNaN(x)) return {{{ cDefine('FP_NAN') }}};
if (!isFinite(x)) return {{{ cDefine('FP_INFINITE') }}};
if (x == 0) return {{{ cDefine('FP_ZERO') }}};
- // FP_SUBNORMAL..?
+ // FP_SUBNORMAL..?
return {{{ cDefine('FP_NORMAL') }}};
},
__fpclassifyd: '__fpclassifyf',
@@ -5277,6 +5537,7 @@ LibraryManager.library = {
// TODO: Implement.
return 0;
},
+ strftime_l: 'strftime', // no locale support yet
strptime: function(buf, format, tm) {
// char *strptime(const char *restrict buf, const char *restrict format, struct tm *restrict tm);
@@ -5284,6 +5545,7 @@ LibraryManager.library = {
// TODO: Implement.
return 0;
},
+ strptime_l: 'strptime', // no locale support yet
getdate: function(string) {
// struct tm *getdate(const char *string);
@@ -5990,6 +6252,10 @@ LibraryManager.library = {
return eval(Pointer_stringify(ptr));
},
+ emscripten_random: function() {
+ return Math.random();
+ },
+
$Profiling: {
max_: 0,
times: null,
@@ -6021,3 +6287,12 @@ LibraryManager.library = {
}
};
+function autoAddDeps(object, name) {
+ name = [name];
+ for (var item in object) {
+ if (item.substr(-6) != '__deps' && !object[item + '__deps']) {
+ object[item + '__deps'] = name;
+ }
+ }
+}
+