diff options
author | Alon Zakai <alonzakai@gmail.com> | 2011-11-25 13:45:25 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2011-11-25 13:45:25 -0800 |
commit | ebe8a3a0c9662271ccdde5c05bd59a5e98964574 (patch) | |
tree | 1c427751d3b3ca3afc99cc2e01bd88110000b993 /src | |
parent | 1edc791be84e53fb46b57770c67c6c7b54d2d58a (diff) |
fix varargs calls in function pointers
Diffstat (limited to 'src')
-rw-r--r-- | src/intertyper.js | 3 | ||||
-rw-r--r-- | src/jsifier.js | 13 | ||||
-rw-r--r-- | src/parseTools.js | 23 |
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; |