aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/intertyper.js3
-rw-r--r--src/jsifier.js13
-rw-r--r--src/parseTools.js23
-rw-r--r--tests/cases/trunc.ll6
4 files changed, 29 insertions, 16 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;
diff --git a/tests/cases/trunc.ll b/tests/cases/trunc.ll
index b46436ff..8eeaf300 100644
--- a/tests/cases/trunc.ll
+++ b/tests/cases/trunc.ll
@@ -2,7 +2,7 @@
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
target triple = "i386-pc-linux-gnu"
-@.str = private constant [8 x i8] c"*%d,%d*\0A\00", align 1 ; [#uses=1]
+@.str = private constant [9 x i8] c"*%d,%d*\0A\00", align 1 ; [#uses=1]
; [#uses=1]
declare i32 @printf(i8* noalias, ...)
@@ -15,8 +15,8 @@ entry:
%"alloca point" = bitcast i32 0 to i32 ; [#uses=0]
store i32 4, i32* %0, align 4
%1 = load i32* %0, align 4 ; [#uses=1]
- %2 = trunc i8 %1 to i1 ; [#uses=1]
- %3 = call i32 @printf(i8* getelementptr inbounds ([8 x i8]* @.str, i32 0, i32 0), i32 %1, i32 %2) ; [#uses=0]
+ %2 = trunc i32 %1 to i1 ; [#uses=1]
+ %3 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0), i32 %1, i1 %2) ; [#uses=0]
br label %return
return: ; preds = %entry