aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <azakai@mozilla.com>2010-11-26 16:55:02 -0800
committerAlon Zakai <azakai@mozilla.com>2010-11-26 16:55:02 -0800
commit74e61fc15af507cbcb53003ca5556105eaaa7e18 (patch)
tree733cb077609f55d98aca55801c298f7b82f93fd6 /src
parent760f8dba70c9a108ff7cacd9950464fde26b54c1 (diff)
improve varargs support
Diffstat (limited to 'src')
-rw-r--r--src/intertyper.js21
-rw-r--r--src/jsifier.js49
-rw-r--r--src/library.js3
-rw-r--r--src/preamble.js42
4 files changed, 79 insertions, 36 deletions
diff --git a/src/intertyper.js b/src/intertyper.js
index 16c83130..8c0136a3 100644
--- a/src/intertyper.js
+++ b/src/intertyper.js
@@ -65,11 +65,14 @@ function intertyper(data, parseFunctions, baseLineNum) {
if (!parseFunctions && /^}.*/.test(line)) {
inFunction = false;
if (!parseFunctions) {
+ var func = funcHeader.processItem(tokenizer.processItem({ lineText: currFunctionLines[0] }, true))[0];
unparsedFunctions.push({
__result__: true,
intertype: 'unparsedFunction',
- // We need this early, to know all function idents
- ident: toNiceIdent(funcHeader.processItem(tokenizer.processItem({ lineText: currFunctionLines[0] }, true))[0].ident),
+ // We need this early, to know basic function info - ident, params, varargs
+ ident: toNiceIdent(func.ident),
+ params: func.params,
+ hasVarArgs: func.hasVarArgs,
lineNum: currFunctionLineNum,
lines: currFunctionLines,
});
@@ -385,15 +388,23 @@ function intertyper(data, parseFunctions, baseLineNum) {
item.tokens = item.tokens.filter(function(token) {
return !(token.text in LLVM.LINKAGES || token.text in set('noalias', 'hidden', 'signext', 'zeroext', 'nounwind', 'define', 'inlinehint', '{', 'fastcc'));
});
- var ret = [{
+ var ret = {
__result__: true,
intertype: 'function',
ident: item.tokens[1].text,
returnType: item.tokens[0],
params: parseParamTokens(item.tokens[2].item.tokens),
lineNum: item.lineNum,
- }];
- return ret;
+ };
+ ret.hasVarArgs = false;
+ ret.paramIdents = ret.params.map(function(param) {
+ if (param.intertype == 'varargs') {
+ ret.hasVarArgs = true;
+ return null;
+ }
+ return toNiceIdent(param.ident);
+ }).filter(function(param) { return param != null });;
+ return [ret];
},
});
// label
diff --git a/src/jsifier.js b/src/jsifier.js
index 15428e78..f525c067 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -9,7 +9,7 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions) {
// Now that analysis has completed, we can get around to handling unparsedFunctions
(functionsOnly ? data.functions : data.unparsedFunctions.concat(data.functions)).forEach(function(func) {
- FUNCTIONS[func.ident] = true;
+ FUNCTIONS[func.ident] = func;
});
for (var i = 0; i < data.unparsedFunctions.length; i++) {
@@ -323,16 +323,7 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions) {
// We have this function all reconstructed, go and finalize it's JS!
- var hasVarArgs = false;
- var params = func.params.map(function(param) {
- if (param.intertype == 'varargs') {
- hasVarArgs = true;
- return null;
- }
- return toNiceIdent(param.ident);
- }).filter(function(param) { return param != null });;
-
- func.JS = '\nfunction ' + func.ident + '(' + params.join(', ') + ') {\n';
+ func.JS = '\nfunction ' + func.ident + '(' + func.paramIdents.join(', ') + ') {\n';
func.JS += ' ' + RuntimeGenerator.stackEnter(func.initialStack) + ';\n';
@@ -341,8 +332,8 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions) {
if (true) { // TODO: optimize away when not needed
func.JS += ' var __label__;\n';
}
- if (hasVarArgs) {
- func.JS += ' var __numArgs__ = ' + params.length + ';\n';
+ if (func.hasVarArgs) {
+ func.JS += ' var __numArgs__ = ' + func.paramIdents.length + ';\n';
}
if (func.hasPhi) {
func.JS += ' var __lastLabel__ = null;\n';
@@ -892,9 +883,8 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions) {
function makeFunctionCall(ident, params, funcData) {
// Special cases
if (ident == '_llvm_va_start') {
- // varargs
- var args = 'Array.prototype.slice.call(arguments, __numArgs__)';
- var data = 'Pointer_make([' + args + '.length].concat(' + args + '), 0)';
+ // varargs - we received a pointer to the varargs as a final parameter
+ var data = 'arguments[__numArgs__]';
if (SAFE_HEAP) {
return 'SAFE_HEAP_STORE(' + params[0].ident + ', ' + data + ', null)';
} else {
@@ -904,19 +894,36 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions) {
return ';'
}
- var params = params.map(function(param) {
+ var func = FUNCTIONS[ident];
+ var args = [];
+ var varargs = [];
+
+ params.forEach(function(param, i) {
+ var val;
if (param.intertype in PARSABLE_LLVM_FUNCTIONS) {
- return finalizeLLVMFunctionCall(param);
+ val = finalizeLLVMFunctionCall(param);
+ } else {
+ val = toNiceIdent(param.ident);
+ }
+ if (!func || !func.hasVarArgs || i < func.params.length-1) { // unrecognized functions (like library ones) cannot have varargs
+ args.push(val);
} else {
- return toNiceIdent(param.ident);
+ varargs.push(val);
+ varargs = varargs.concat(zeros(getNativeFieldSize(param.type)-1));
}
- }).map(indexizeFunctions);
+ });
+
+ args = args.map(indexizeFunctions);
+ varargs = varargs.map(indexizeFunctions);
+ if (varargs.length > 0) {
+ varargs = makePointer(varargs, 0, 'ALLOC_STACK');
+ }
if (getVarData(funcData, ident)) {
ident = 'FUNCTION_TABLE[' + ident + ']';
}
- return ident + '(' + params.join(', ') + ')';
+ return ident + '(' + args.concat(varargs).join(', ') + ')';
}
makeFuncLineZyme('getelementptr', function(item) { return finalizeLLVMFunctionCall(item) });
makeFuncLineZyme('call', function(item) {
diff --git a/src/library.js b/src/library.js
index 6e41b547..542fe7e3 100644
--- a/src/library.js
+++ b/src/library.js
@@ -63,8 +63,7 @@ var Library = {
},
vsnprintf: function(dst, num, src, ptr) {
- var args = Array_copy(ptr+1, IHEAP[ptr]); // # of args in in first place
- var text = __formatString.apply(null, [src].concat(args));
+ var text = __formatString(-src, ptr); // |-|src tells formatstring to use C-style params (typically they are from varargs)
for (var i = 0; i < num; i++) {
IHEAP[dst+i] = IHEAP[text+i];
if (IHEAP[dst+i] == 0) break;
diff --git a/src/preamble.js b/src/preamble.js
index 976e3c90..6958068f 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -229,15 +229,37 @@ function __shutdownRuntime__() {
// C-style: we work on ints on the HEAP.
function __formatString() {
+ 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 {
+ ret = (type === 'f' ? FHEAP : IHEAP)[argIndex];
+ argIndex += type === 'l'.charCodeAt(0) ? 8 : 4; // XXX hardcoded native sizes
+ }
+ return ret;
+ }
+
var ret = [];
- var curr = -1;
+ var curr = -1, next, currArg;
while (curr) { // Note: should be curr != 0, technically. But this helps catch bugs with undefineds
curr = IHEAP[textIndex];
next = IHEAP[textIndex+1];
if (curr == '%'.charCodeAt(0) && ['d', 'u', 'f', '.'].indexOf(String.fromCharCode(next)) != -1) {
- var argText = String(+arguments[argIndex]); // +: boolean=>int
+ var currArg;
+ var argText;
// Handle very very simply formatting, namely only %.Xf
if (next == '.'.charCodeAt(0)) {
var limit = 0;
@@ -249,6 +271,9 @@ function __formatString() {
textIndex++;
}
textIndex--;
+ next = IHEAP[textIndex+1];
+ currArg = getNextArg(next);
+ argText = String(+currArg); // +: boolean=>int
var dotIndex = argText.indexOf('.');
if (dotIndex == -1) {
dotIndex = argText.length;
@@ -258,20 +283,21 @@ function __formatString() {
argText = argText.substr(0, dotIndex+1+limit);
textIndex += 2;
} else if (next == 'u'.charCodeAt(0)) {
- argText = String(unSign(arguments[argIndex], 32));
+ currArg = getNextArg(next);
+ argText = String(unSign(currArg, 32));
+ } else {
+ currArg = getNextArg(next);
+ argText = String(+currArg); // +: boolean=>int
}
argText.split('').forEach(function(chr) {
ret.push(chr.charCodeAt(0));
});
- argIndex += 1;
textIndex += 2;
} else if (curr == '%'.charCodeAt(0) && next == 's'.charCodeAt(0)) {
- ret = ret.concat(String_copy(arguments[argIndex]));
- argIndex += 1;
+ ret = ret.concat(String_copy(getNextArg(next)));
textIndex += 2;
} else if (curr == '%'.charCodeAt(0) && next == 'c'.charCodeAt(0)) {
- ret = ret.concat(arguments[argIndex]);
- argIndex += 1;
+ ret = ret.concat(getNextArg(next));
textIndex += 2;
} else {
ret.push(curr);