diff options
author | Alon Zakai <alonzakai@gmail.com> | 2013-07-15 18:00:57 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2013-07-15 18:26:40 -0700 |
commit | a1143f0cf7b7fd5e57a3231fbad13d226426f451 (patch) | |
tree | 9f96da0c04531ca5084e6be1e9389670e07a99ed | |
parent | 8ac26578535936ae2191a8629b4fb3999e3f259f (diff) |
fix both number of arguments and return type based on implementation information, to work around silly llvm function casts
-rw-r--r-- | src/jsifier.js | 20 | ||||
-rw-r--r-- | tests/cases/sillyfuncast2.ll | 21 |
2 files changed, 37 insertions, 4 deletions
diff --git a/src/jsifier.js b/src/jsifier.js index e86a345d..30cea99b 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -1474,7 +1474,6 @@ function JSify(data, functionsOnly, givenFunctions) { } args = args.concat(varargs); - var argsText = args.join(', '); // Inline if either we inline whenever we can (and we can), or if there is no noninlined version var inline = LibraryManager.library[simpleIdent + '__inline']; @@ -1496,13 +1495,26 @@ function JSify(data, functionsOnly, givenFunctions) { } } + if (callIdent in Functions.implementedFunctions) { + // LLVM sometimes bitcasts for no reason. We must call using the exact same type as the actual function is generated as. + var numArgs = Functions.implementedFunctions[callIdent].length - 1; + if (numArgs !== args.length) { + if (VERBOSE) warnOnce('Fixing function call arguments based on signature, on ' + [callIdent, args.length, numArgs]); + while (args.length > numArgs) { args.pop(); argsTypes.pop() } + while (args.length < numArgs) { args.push('0'); argsTypes.push('i32') } + } + } + var returnType = 'void'; if ((byPointer || ASM_JS) && hasReturn) { + returnType = getReturnType(type); if (callIdent in Functions.implementedFunctions) { // LLVM sometimes bitcasts for no reason. We must call using the exact same type as the actual function is generated as - returnType = Functions.getSignatureReturnType(Functions.implementedFunctions[callIdent]); - } else { - returnType = getReturnType(type); + var trueType = Functions.getSignatureReturnType(Functions.implementedFunctions[callIdent]); + if (trueType !== returnType && !isIdenticallyImplemented(trueType, returnType)) { + if (VERBOSE) warnOnce('Fixing function call based on return type from signature, on ' + [callIdent, returnType, trueType]); + returnType = trueType; + } } } diff --git a/tests/cases/sillyfuncast2.ll b/tests/cases/sillyfuncast2.ll new file mode 100644 index 00000000..f72ebe28 --- /dev/null +++ b/tests/cases/sillyfuncast2.ll @@ -0,0 +1,21 @@ +; ModuleID = 'tests/hello_world.bc' +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-S128" +target triple = "i386-pc-linux-gnu" + +@.str = private unnamed_addr constant [15 x i8] c"hello, world!\0A\00", align 1 ; [#uses=1 type=[15 x i8]*] + +define void @doit(i32 %one, i32 %two) { + %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0)) ; [#uses=0 type=i32] + ret void +} + +define i32 @main() { +entry: + %retval = alloca i32, align 4 ; [#uses=1 type=i32*] + store i32 0, i32* %retval + call i32 bitcast (void (i32, i32)* @doit to i32 (i32, i64)*)(i32 0, i64 0) nounwind + ret i32 1 +} + +declare i32 @printf(i8*, ...) + |