aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <azakai@mozilla.com>2011-01-08 14:01:10 -0800
committerAlon Zakai <azakai@mozilla.com>2011-01-08 14:01:10 -0800
commit9143905d9833518c56625ad11e0d3c4cac78dd59 (patch)
tree78fd43b95fc964f51fc4b4f673723f0f000784cf /src
parent1a2f55979d66202814c61a4c4ed934b770606947 (diff)
refactor preamble functions into library
Diffstat (limited to 'src')
-rw-r--r--src/library.js158
-rw-r--r--src/preamble.js199
2 files changed, 195 insertions, 162 deletions
diff --git a/src/library.js b/src/library.js
index a00bce91..001861b0 100644
--- a/src/library.js
+++ b/src/library.js
@@ -15,17 +15,127 @@
var Library = {
// stdio.h
+ _formatString: function() {
+ function isFloatArg(type) {
+ return String.fromCharCode(type) in Runtime.set('f', 'e', 'g');
+ }
+ var cStyle = false;
+ var textIndex = arguments[0];
+ var argIndex = 1;
+ if (textIndex < 0) {
+ cStyle = true;
+ textIndex = -textIndex;
+ slab = null;
+ argIndex = arguments[1];
+ } else {
+ var _arguments = arguments;
+ }
+ function getNextArg(type) {
+ var ret;
+ if (!cStyle) {
+ ret = _arguments[argIndex];
+ argIndex++;
+ } else {
+ if (isFloatArg(type)) {
+ ret = {{{ makeGetValue(0, 'argIndex', 'double') }}};
+ } else {
+ ret = {{{ makeGetValue(0, 'argIndex', 'i32') }}};
+ }
+ argIndex += type === 'l'.charCodeAt(0) ? 8 : 4; // XXX hardcoded native sizes
+ }
+ return ret;
+ }
+
+ var ret = [];
+ var curr, next, currArg;
+ while(1) {
+ curr = {{{ makeGetValue(0, 'textIndex', 'i8') }}};
+ if (curr === 0) break;
+ next = {{{ makeGetValue(0, 'textIndex+1', 'i8') }}};
+ if (curr == '%'.charCodeAt(0)) {
+ // Handle very very simply formatting, namely only %.X[f|d|u|etc.]
+ var precision = -1;
+ if (next == '.'.charCodeAt(0)) {
+ textIndex++;
+ precision = 0;
+ while(1) {
+ var precisionChr = {{{ makeGetValue(0, 'textIndex+1', 'i8') }}};
+ if (!(precisionChr >= '0'.charCodeAt(0) && precisionChr <= '9'.charCodeAt(0))) break;
+ precision *= 10;
+ precision += precisionChr - '0'.charCodeAt(0);
+ textIndex++;
+ }
+ next = {{{ makeGetValue(0, 'textIndex+1', 'i8') }}};
+ }
+ if (next == 'l'.charCodeAt(0)) {
+ textIndex++;
+ next = {{{ makeGetValue(0, 'textIndex+1', 'i8') }}};
+ }
+ if (isFloatArg(next)) {
+ next = 'f'.charCodeAt(0); // no support for 'e'
+ }
+ if (['d', 'i', 'u', 'p', 'f'].indexOf(String.fromCharCode(next)) != -1) {
+ var currArg;
+ var argText;
+ currArg = getNextArg(next);
+ argText = String(+currArg); // +: boolean=>int
+ if (next == 'u'.charCodeAt(0)) {
+ argText = String(unSign(currArg, 32));
+ } else if (next == 'p'.charCodeAt(0)) {
+ argText = '0x' + currArg.toString(16);
+ } else {
+ argText = String(+currArg); // +: boolean=>int
+ }
+ if (precision >= 0) {
+ if (isFloatArg(next)) {
+ var dotIndex = argText.indexOf('.');
+ if (dotIndex == -1 && next == 'f'.charCodeAt(0)) {
+ dotIndex = argText.length;
+ argText += '.';
+ }
+ argText += '00000000000'; // padding
+ argText = argText.substr(0, dotIndex+1+precision);
+ } else {
+ while (argText.length < precision) {
+ argText = '0' + argText;
+ }
+ }
+ }
+ argText.split('').forEach(function(chr) {
+ ret.push(chr.charCodeAt(0));
+ });
+ textIndex += 2;
+ } else if (next == 's'.charCodeAt(0)) {
+ ret = ret.concat(String_copy(getNextArg(next)));
+ textIndex += 2;
+ } else if (next == 'c'.charCodeAt(0)) {
+ ret = ret.concat(getNextArg(next));
+ textIndex += 2;
+ } else {
+ ret.push(next);
+ textIndex += 2; // not sure what to do with this %, so print it
+ }
+ } else {
+ ret.push(curr);
+ textIndex += 1;
+ }
+ }
+ return Pointer_make(ret.concat(0), 0, ALLOC_STACK); // NB: Stored on the stack
+ },
+
+ printf__deps: ['_formatString'],
printf: function() {
__print__(Pointer_stringify(__formatString.apply(null, arguments)));
},
+ fprintf__deps: ['_formatString'],
fprintf: function() {
var file = arguments[0]; // TODO: something clever with this
var args = Array.prototype.slice.call(arguments, 1);
__print__(Pointer_stringify(__formatString.apply(null, args)));
},
- sprintf__deps: ['strcpy'],
+ sprintf__deps: ['strcpy', '_formatString'],
sprintf: function() {
var str = arguments[0];
var args = Array.prototype.slice.call(arguments, 1);
@@ -89,6 +199,7 @@ var Library = {
__print__('\n');
},
+ vsnprintf__deps: ['_formatString'],
vsnprintf: function(dst, num, src, ptr) {
var text = __formatString(-src, ptr); // |-|src tells formatstring to use C-style params (typically they are from varargs)
var i;
@@ -119,6 +230,10 @@ var Library = {
abs: 'Math.abs',
+ atoi: function(s) {
+ return Math.floor(Number(Pointer_stringify(s)));
+ },
+
atexit: function(func) {
__ATEXIT__.push(func);
},
@@ -129,6 +244,7 @@ var Library = {
throw 'ABORT: ' + code + ', at ' + (new Error().stack);
},
+ realloc__deps: ['memcpy'],
realloc: function(ptr, size) {
// Very simple, inefficient implementation - if you use a real malloc, best to use
// a real realloc with it
@@ -177,6 +293,7 @@ var Library = {
return ret;
},
+ qsort__deps: ['memcpy'],
qsort: function(base, num, size, comparator) {
// forward calls to the JavaScript sort method
// first, sort the items logically
@@ -198,6 +315,45 @@ var Library = {
// string.h
+ memcpy: function (dest, src, num, idunno) {
+ var curr;
+ for (var i = 0; i < num; i++) {
+ // TODO: optimize for the typed arrays case
+ // || 0, since memcpy sometimes copies uninitialized areas XXX: Investigate why initializing alloc'ed memory does not fix that too
+ {{{ makeCopyValue('dest', 'i', 'src', 'i', 'null', ' || 0') }}};
+ }
+ },
+ llvm_memcpy_i32: 'memcpy',
+ llvm_memcpy_i64: 'memcpy',
+ llvm_memcpy_p0i8_p0i8_i32: 'memcpy',
+ llvm_memcpy_p0i8_p0i8_i64: 'memcpy',
+
+ memmove: function(dest, src, num, idunno) {
+ // not optimized!
+ if (num === 0) return; // will confuse malloc if 0
+ var tmp = _malloc(num);
+ _memcpy(tmp, src, num);
+ _memcpy(dest, tmp, num);
+ _free(tmp);
+ },
+ llvm_memmove_i32: 'memmove',
+ llvm_memmove_i64: 'memmove',
+ llvm_memmove_p0i8_p0i8_i32: 'memmove',
+ llvm_memmove_p0i8_p0i8_i64: 'memmove',
+
+ memset: function(ptr, value, num) {
+ for (var i = 0; i < num; i++) {
+ {{{ makeSetValue('ptr', 'i', 'value', 'null') }}}
+ }
+ },
+ llvm_memset_i32: 'memset',
+ llvm_memset_p0i8_i32: 'memset',
+ llvm_memset_p0i8_i64: 'memset',
+
+ strlen: function(ptr) {
+ return String_len(ptr);
+ },
+
strspn: function(pstr, pset) {
var str = String_copy(pstr, true);
var set = String_copy(pset);
diff --git a/src/preamble.js b/src/preamble.js
index 2bf7c17e..ad7ea12a 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -1,21 +1,15 @@
// === Auto-generated preamble library stuff ===
-{{RUNTIME}}
-
-function __globalConstructor__() {
-}
-
-// Maps ints ==> functions. This lets us pass around ints, which are
-// actually pointers to functions, and we convert at call()time
-var FUNCTION_TABLE = [];
-
-var __THREW__ = false; // Used in checking for thrown exceptions.
+//========================================
+// Runtime code shared with compiler
+//========================================
-var __ATEXIT__ = [];
+{{RUNTIME}}
#if SAFE_HEAP
-
-// Semi-manual memory corruption debugging
+//========================================
+// Debugging tools - Heap
+//========================================
var HEAP_WATCHED = {};
var HEAP_HISTORY = {};
function SAFE_HEAP_CLEAR(dest) {
@@ -100,6 +94,9 @@ function __Z18UNPROTECT_HEAPADDRPv(dest) {
#endif
#if CHECK_OVERFLOWS
+//========================================
+// Debugging tools - Mathop overflows
+//========================================
function CHECK_OVERFLOW(value, bits) {
assert(value !== Infinity && value !== -Infinity, 'Infinity!');
assert(Math.abs(value) < Math.pow(2, bits), 'Overflow!');
@@ -108,13 +105,34 @@ function CHECK_OVERFLOW(value, bits) {
#endif
#if LABEL_DEBUG
+//========================================
+// Debugging tools - Code flow progress
+//========================================
var INDENT = '';
#endif
#if EXECUTION_TIMEOUT
+//========================================
+// Debugging tools - Execution timeout
+//========================================
var START_TIME = Date.now();
#endif
+//========================================
+// Runtime essentials
+//========================================
+
+function __globalConstructor__() {
+}
+
+// Maps ints ==> functions. This lets us pass around ints, which are
+// actually pointers to functions, and we convert at call()time
+var FUNCTION_TABLE = [];
+
+var __THREW__ = false; // Used in checking for thrown exceptions.
+
+var __ATEXIT__ = [];
+
var ABORT = false;
var undef = 0;
@@ -252,113 +270,6 @@ function __shutdownRuntime__() {
// stdio.h
-function __formatString() {
- function isFloatArg(type) {
- return String.fromCharCode(type) in Runtime.set('f', 'e', 'g');
- }
- var cStyle = false;
- var textIndex = arguments[0];
- var argIndex = 1;
- if (textIndex < 0) {
- cStyle = true;
- textIndex = -textIndex;
- slab = null;
- argIndex = arguments[1];
- } else {
- var _arguments = arguments;
- }
- function getNextArg(type) {
- var ret;
- if (!cStyle) {
- ret = _arguments[argIndex];
- argIndex++;
- } else {
- if (isFloatArg(type)) {
- ret = {{{ makeGetValue(0, 'argIndex', 'double') }}};
- } else {
- ret = {{{ makeGetValue(0, 'argIndex', 'i32') }}};
- }
- argIndex += type === 'l'.charCodeAt(0) ? 8 : 4; // XXX hardcoded native sizes
- }
- return ret;
- }
-
- var ret = [];
- var curr, next, currArg;
- while(1) {
- curr = {{{ makeGetValue(0, 'textIndex', 'i8') }}};
- if (curr === 0) break;
- next = {{{ makeGetValue(0, 'textIndex+1', 'i8') }}};
- if (curr == '%'.charCodeAt(0)) {
- // Handle very very simply formatting, namely only %.X[f|d|u|etc.]
- var precision = -1;
- if (next == '.'.charCodeAt(0)) {
- textIndex++;
- precision = 0;
- while(1) {
- var precisionChr = {{{ makeGetValue(0, 'textIndex+1', 'i8') }}};
- if (!(precisionChr >= '0'.charCodeAt(0) && precisionChr <= '9'.charCodeAt(0))) break;
- precision *= 10;
- precision += precisionChr - '0'.charCodeAt(0);
- textIndex++;
- }
- next = {{{ makeGetValue(0, 'textIndex+1', 'i8') }}};
- }
- if (next == 'l'.charCodeAt(0)) {
- textIndex++;
- next = {{{ makeGetValue(0, 'textIndex+1', 'i8') }}};
- }
- if (isFloatArg(next)) {
- next = 'f'.charCodeAt(0); // no support for 'e'
- }
- if (['d', 'i', 'u', 'p', 'f'].indexOf(String.fromCharCode(next)) != -1) {
- var currArg;
- var argText;
- currArg = getNextArg(next);
- argText = String(+currArg); // +: boolean=>int
- if (next == 'u'.charCodeAt(0)) {
- argText = String(unSign(currArg, 32));
- } else if (next == 'p'.charCodeAt(0)) {
- argText = '0x' + currArg.toString(16);
- } else {
- argText = String(+currArg); // +: boolean=>int
- }
- if (precision >= 0) {
- if (isFloatArg(next)) {
- var dotIndex = argText.indexOf('.');
- if (dotIndex == -1 && next == 'f'.charCodeAt(0)) {
- dotIndex = argText.length;
- argText += '.';
- }
- argText += '00000000000'; // padding
- argText = argText.substr(0, dotIndex+1+precision);
- } else {
- while (argText.length < precision) {
- argText = '0' + argText;
- }
- }
- }
- argText.split('').forEach(function(chr) {
- ret.push(chr.charCodeAt(0));
- });
- textIndex += 2;
- } else if (next == 's'.charCodeAt(0)) {
- ret = ret.concat(String_copy(getNextArg(next)));
- textIndex += 2;
- } else if (next == 'c'.charCodeAt(0)) {
- ret = ret.concat(getNextArg(next));
- textIndex += 2;
- } else {
- ret.push(next);
- textIndex += 2; // not sure what to do with this %, so print it
- }
- } else {
- ret.push(curr);
- textIndex += 1;
- }
- }
- return Pointer_make(ret.concat(0), 0, ALLOC_STACK); // NB: Stored on the stack
-}
// Copies a list of num items on the HEAP into a
// a normal JavaScript array of numbers
@@ -372,52 +283,18 @@ function Array_copy(ptr, num) {
#endif
}
-// Copies a C-style string, terminated by a zero, from the HEAP into
-// a normal JavaScript array of numbers
-function String_copy(ptr, addZero) {
- return Array_copy(ptr, _strlen(ptr)).concat(addZero ? [0] : []);
-}
-
-// stdlib.h
-
-// Get a pointer, return int value of the string it points to
-function _atoi(s) {
- return Math.floor(Number(Pointer_stringify(s)));
-}
-
-function _llvm_memcpy_i32(dest, src, num, idunno) {
- var curr;
- for (var i = 0; i < num; i++) {
- // TODO: optimize for the typed arrays case
- // || 0, since memcpy sometimes copies uninitialized areas XXX: Investigate why initializing alloc'ed memory does not fix that too
- {{{ makeCopyValue('dest', 'i', 'src', 'i', 'null', ' || 0') }}};
- }
-}
-_memcpy = _llvm_memcpy_i64 = _llvm_memcpy_p0i8_p0i8_i32 = _llvm_memcpy_p0i8_p0i8_i64 = _llvm_memcpy_i32;
-
-function _llvm_memmove_i32(dest, src, num, idunno) {
- // not optimized!
- if (num === 0) return; // will confuse malloc if 0
- var tmp = _malloc(num);
- _memcpy(tmp, src, num);
- _memcpy(dest, tmp, num);
- _free(tmp);
-}
-_memmove = _llvm_memmove_i64 = _llvm_memmove_p0i8_p0i8_i32 = _llvm_memmove_p0i8_p0i8_i64 = _llvm_memmove_i32;
-
-function llvm_memset_i32(ptr, value, num) {
- for (var i = 0; i < num; i++) {
- {{{ makeSetValue('ptr', 'i', 'value', 'null') }}}
- }
-}
-_memset = _llvm_memset_p0i8_i64 = _llvm_memset_p0i8_i32 = llvm_memset_i32;
-
-function _strlen(ptr) {
+function String_len(ptr) {
var i = 0;
while ({{{ makeGetValue('ptr', 'i', 'i8') }}}) i++; // Note: should be |!= 0|, technically. But this helps catch bugs with undefineds
return i;
}
+// Copies a C-style string, terminated by a zero, from the HEAP into
+// a normal JavaScript array of numbers
+function String_copy(ptr, addZero) {
+ return Array_copy(ptr, String_len(ptr)).concat(addZero ? [0] : []);
+}
+
// Tools
PRINTBUFFER = '';