aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2011-11-25 13:45:25 -0800
committerAlon Zakai <alonzakai@gmail.com>2011-11-25 13:45:25 -0800
commitebe8a3a0c9662271ccdde5c05bd59a5e98964574 (patch)
tree1c427751d3b3ca3afc99cc2e01bd88110000b993 /src
parent1edc791be84e53fb46b57770c67c6c7b54d2d58a (diff)
fix varargs calls in function pointers
Diffstat (limited to 'src')
-rw-r--r--src/intertyper.js3
-rw-r--r--src/jsifier.js13
-rw-r--r--src/parseTools.js23
3 files changed, 26 insertions, 13 deletions
diff --git a/src/intertyper.js b/src/intertyper.js
index c1b9b78e..b01d2a88 100644
--- a/src/intertyper.js
+++ b/src/intertyper.js
@@ -627,15 +627,12 @@ function intertyper(data, parseFunctions, baseLineNum) {
}
item.type = item.tokens[1].text;
Types.needAnalysis[item.type] = 0;
- item.functionType = '';
while (['@', '%'].indexOf(item.tokens[2].text[0]) == -1 && !(item.tokens[2].text in PARSABLE_LLVM_FUNCTIONS) &&
item.tokens[2].text != 'null') {
// We cannot compile assembly. If you hit this, perhaps tell the compiler not
// to generate arch-specific code? |-U__i386__ -U__x86_64__| might help, it undefines
// the standard archs.
assert(item.tokens[2].text != 'asm', 'Inline assembly cannot be compiled to JavaScript!');
-
- item.functionType += item.tokens[2].text;
item.tokens.splice(2, 1);
}
var tokensLeft = item.tokens.slice(2);
diff --git a/src/jsifier.js b/src/jsifier.js
index 2869d059..92668595 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -827,7 +827,7 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
// Wrapping in a function lets us easily return values if we are
// in an assignment
var phiSets = calcPhiSets(item);
- var call_ = makeFunctionCall(item.ident, item.params, item.funcData);
+ var call_ = makeFunctionCall(item.ident, item.params, item.funcData, item.type);
var ret = '(function() { try { __THREW__ = false; return '
+ call_ + ' '
+ '} catch(e) { '
@@ -899,18 +899,19 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
return finalizeLLVMParameter(item.params[0]);
});
- function makeFunctionCall(ident, params, funcData) {
+ function makeFunctionCall(ident, params, funcData, type) {
// We cannot compile assembly. See comment in intertyper.js:'Call'
assert(ident != 'asm', 'Inline assembly cannot be compiled to JavaScript!');
var shortident = LibraryManager.getRootIdent(ident.slice(1)) || ident.slice(1); // ident may not be in library, if all there is is ident__inline
- var func = Functions.currFunctions[ident] || Functions.currExternalFunctions[ident];
var args = [];
var argsTypes = [];
var varargs = [];
var varargsTypes = [];
var ignoreFunctionIndexizing = [];
var useJSArgs = (shortident + '__jsargs') in LibraryManager.library;
+ var hasVarArgs = isVarArgsFunctionType(type);
+ var normalArgs = (hasVarArgs && !useJSArgs) ? countNormalArgs(type) : -1;
if (I64_MODE == 1 && ident in LLVM.INTRINSICS_32) {
// Some LLVM intrinsics use i64 where it is not needed, and would cause much overhead
@@ -919,7 +920,7 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
params.forEach(function(param, i) {
var val = finalizeParam(param);
- if (!func || !func.hasVarArgs || i < func.numParams-1 || useJSArgs) {
+ if (!hasVarArgs || useJSArgs || i < normalArgs) {
if (param.type == 'i64' && I64_MODE == 1) {
val = makeCopyI64(val); // Must copy [low, high] i64s, so they don't end up modified in the caller
}
@@ -952,7 +953,7 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
return vararg === 0 ? 0 : indexizeFunctions(vararg, varargsTypes[i])
});
- if (func && func.hasVarArgs && !useJSArgs) {
+ if (hasVarArgs && !useJSArgs) {
if (varargs.length === 0) {
varargs = [0];
varargsTypes = ['i32'];
@@ -979,7 +980,7 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
makeFuncLineActor('getelementptr', function(item) { return finalizeLLVMFunctionCall(item) });
makeFuncLineActor('call', function(item) {
if (item.standalone && LibraryManager.isStubFunction(item.ident)) return ';';
- return makeFunctionCall(item.ident, item.params, item.funcData) + (item.standalone ? ';' : '');
+ return makeFunctionCall(item.ident, item.params, item.funcData, item.type) + (item.standalone ? ';' : '');
});
makeFuncLineActor('unreachable', function(item) { return 'throw "Reached an unreachable!"' }); // Original .ll line: ' + item.lineNum + '";' });
diff --git a/src/parseTools.js b/src/parseTools.js
index ca3c90bc..98987229 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -135,7 +135,7 @@ function isVoidType(type) {
}
// Detects a function definition, ([...|type,[type,...]])
-function isFunctionDef(token) {
+function isFunctionDef(token, out) {
var text = token.text;
var nonPointing = removeAllPointing(text);
if (nonPointing[0] != '(' || nonPointing.substr(-1) != ')')
@@ -143,26 +143,41 @@ function isFunctionDef(token) {
if (nonPointing === '()') return true;
if (!token.item) return false;
var fail = false;
- splitTokenList(token.item.tokens).forEach(function(segment) {
+ var segments = splitTokenList(token.item.tokens);
+ segments.forEach(function(segment) {
var subtext = segment[0].text;
fail = fail || segment.length > 1 || !(isType(subtext) || subtext == '...');
});
+ if (out) out.numArgs = segments.length;
return !fail;
}
-function isFunctionType(type) {
+function isFunctionType(type, out) {
type = type.replace(/"[^"]+"/g, '".."');
var parts = type.split(' ');
if (pointingLevels(type) !== 1) return false;
var text = removeAllPointing(parts.slice(1).join(' '));
if (!text) return false;
- return isType(parts[0]) && isFunctionDef({ text: text, item: tokenize(text.substr(1, text.length-2), true) });
+ return isType(parts[0]) && isFunctionDef({ text: text, item: tokenize(text.substr(1, text.length-2), true) }, out);
}
function isType(type) { // TODO!
return isVoidType(type) || Runtime.isNumberType(type) || isStructType(type) || isPointerType(type) || isFunctionType(type);
}
+function isVarArgsFunctionType(type) {
+ // assumes this is known to be a function type already
+ var varArgsSuffix = '...)*';
+ return type.substr(-varArgsSuffix.length) == varArgsSuffix;
+}
+
+function countNormalArgs(type) {
+ var out = {};
+ assert(isFunctionType(type, out));
+ if (isVarArgsFunctionType(type)) out.numArgs--;
+ return out.numArgs;
+}
+
function addIdent(token) {
token.ident = token.text;
return token;