aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2013-10-25 16:51:18 -0700
committerAlon Zakai <alonzakai@gmail.com>2013-10-25 17:01:44 -0700
commit296cd5f54cb598fad7c9e58776bac906da1add02 (patch)
tree80bbc4c143b780f62f4814d19b58c803466d22e1
parent5041ed44a66938588e674b9f7c03b9281b99c4e1 (diff)
support fround in function tables and asm module support functions
-rwxr-xr-xemscripten.py22
-rw-r--r--src/jsifier.js2
-rw-r--r--src/modules.js41
-rw-r--r--tools/shared.py22
4 files changed, 57 insertions, 30 deletions
diff --git a/emscripten.py b/emscripten.py
index 76056491..24e38f44 100755
--- a/emscripten.py
+++ b/emscripten.py
@@ -11,6 +11,7 @@ headers, for the libc implementation in JS).
import os, sys, json, optparse, subprocess, re, time, multiprocessing, string, logging
+from tools import shared
from tools import jsrun, cache as cache_module, tempfiles
from tools.response_file import read_response_file
@@ -25,7 +26,6 @@ def get_configuration():
if hasattr(get_configuration, 'configuration'):
return get_configuration.configuration
- from tools import shared
configuration = shared.Configuration(environ=os.environ)
get_configuration.configuration = configuration
return configuration
@@ -425,8 +425,8 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
Counter.i += 1
bad = 'b' + str(i)
params = ','.join(['p%d' % p for p in range(len(sig)-1)])
- coercions = ';'.join(['p%d = %sp%d%s' % (p, '+' if sig[p+1] != 'i' else '', p, '' if sig[p+1] != 'i' else '|0') for p in range(len(sig)-1)]) + ';'
- ret = '' if sig[0] == 'v' else ('return %s0' % ('+' if sig[0] != 'i' else ''))
+ coercions = ';'.join(['p%d = %s' % (p, shared.JS.make_coercion('p%d' % p, sig[p+1], settings)) for p in range(len(sig)-1)]) + ';'
+ ret = '' if sig[0] == 'v' else ('return %s' % shared.JS.make_initializer(sig[0], settings))
start = raw.index('[')
end = raw.rindex(']')
body = raw[start+1:end].split(',')
@@ -476,18 +476,14 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
asm_runtime_funcs = ['stackAlloc', 'stackSave', 'stackRestore', 'setThrew'] + ['setTempRet%d' % i for i in range(10)]
# function tables
- def asm_coerce(value, sig):
- if sig == 'v': return value
- return ('+' if sig != 'i' else '') + value + ('|0' if sig == 'i' else '')
-
function_tables = ['dynCall_' + table for table in last_forwarded_json['Functions']['tables']]
function_tables_impls = []
for sig in last_forwarded_json['Functions']['tables'].iterkeys():
args = ','.join(['a' + str(i) for i in range(1, len(sig))])
- arg_coercions = ' '.join(['a' + str(i) + '=' + asm_coerce('a' + str(i), sig[i]) + ';' for i in range(1, len(sig))])
- coerced_args = ','.join([asm_coerce('a' + str(i), sig[i]) for i in range(1, len(sig))])
- ret = ('return ' if sig[0] != 'v' else '') + asm_coerce('FUNCTION_TABLE_%s[index&{{{ FTM_%s }}}](%s)' % (sig, sig, coerced_args), sig[0])
+ arg_coercions = ' '.join(['a' + str(i) + '=' + shared.JS.make_coercion('a' + str(i), sig[i], settings) + ';' for i in range(1, len(sig))])
+ coerced_args = ','.join([shared.JS.make_coercion('a' + str(i), sig[i], settings) for i in range(1, len(sig))])
+ ret = ('return ' if sig[0] != 'v' else '') + shared.JS.make_coercion('FUNCTION_TABLE_%s[index&{{{ FTM_%s }}}](%s)' % (sig, sig, coerced_args), sig[0], settings)
function_tables_impls.append('''
function dynCall_%s(index%s%s) {
index = index|0;
@@ -497,7 +493,7 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
''' % (sig, ',' if len(sig) > 1 else '', args, arg_coercions, ret))
for i in range(settings['RESERVED_FUNCTION_POINTERS']):
- jsret = ('return ' if sig[0] != 'v' else '') + asm_coerce('jsCall(%d%s%s)' % (i, ',' if coerced_args else '', coerced_args), sig[0])
+ jsret = ('return ' if sig[0] != 'v' else '') + shared.JS.make_coercion('jsCall(%d%s%s)' % (i, ',' if coerced_args else '', coerced_args), sig[0], settings)
function_tables_impls.append('''
function jsCall_%s_%s(%s) {
%s
@@ -505,7 +501,6 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
}
''' % (sig, i, args, arg_coercions, jsret))
- from tools import shared
shared.Settings.copy(settings)
asm_setup += '\n' + shared.JS.make_invoke(sig) + '\n'
basic_funcs.append('invoke_%s' % sig)
@@ -727,14 +722,12 @@ def main(args, compiler_engine, cache, jcache, relooper, temp_files, DEBUG, DEBU
relooper = cache.get_path('relooper.js')
settings.setdefault('RELOOPER', relooper)
if not os.path.exists(relooper):
- from tools import shared
shared.Building.ensure_relooper(relooper)
settings.setdefault('STRUCT_INFO', cache.get_path('struct_info.compiled.json'))
struct_info = settings.get('STRUCT_INFO')
if not os.path.exists(struct_info):
- from tools import shared
shared.Building.ensure_struct_info(struct_info)
emscript(args.infile, settings, args.outfile, libraries, compiler_engine=compiler_engine,
@@ -833,7 +826,6 @@ WARNING: You should normally never use this! Use emcc instead.
temp_files = tempfiles.TempFiles(temp_dir)
if keywords.compiler is None:
- from tools import shared
keywords.compiler = shared.COMPILER_ENGINE
if keywords.verbose is None:
diff --git a/src/jsifier.js b/src/jsifier.js
index 7a2fdde0..79ad9c03 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -1579,7 +1579,7 @@ function JSify(data, functionsOnly, givenFunctions) {
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
- var trueType = Functions.getSignatureReturnType(Functions.implementedFunctions[callIdent]);
+ var trueType = Functions.getSignatureType(Functions.implementedFunctions[callIdent][0]);
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/src/modules.js b/src/modules.js
index 814817a3..2e6edeba 100644
--- a/src/modules.js
+++ b/src/modules.js
@@ -253,13 +253,32 @@ var Functions = {
aliases: {}, // in shared modules (MAIN_MODULE or SHARED_MODULE), a list of aliases for functions that have them
+ getSignatureLetter: function(type) {
+ switch(type) {
+ case 'float': return 'f';
+ case 'double': return 'd';
+ case 'void': return 'v';
+ default: return 'i';
+ }
+ },
+
+ getSignatureType: function(letter) {
+ switch(letter) {
+ case 'v': return 'void';
+ case 'i': return 'i32';
+ case 'f': return 'float';
+ case 'd': return 'double';
+ default: throw 'what is this sig? ' + sig;
+ }
+ },
+
getSignature: function(returnType, argTypes, hasVarArgs) {
- var sig = returnType == 'void' ? 'v' : (isIntImplemented(returnType) ? 'i' : 'f');
+ var sig = Functions.getSignatureLetter(returnType);
for (var i = 0; i < argTypes.length; i++) {
var type = argTypes[i];
if (!type) break; // varargs
if (type in Runtime.FLOAT_TYPES) {
- sig += 'f';
+ sig += Functions.getSignatureLetter(type);
} else {
var chunks = getNumIntChunks(type);
for (var j = 0; j < chunks; j++) sig += 'i';
@@ -269,15 +288,6 @@ var Functions = {
return sig;
},
- getSignatureReturnType: function(sig) {
- switch(sig[0]) {
- case 'v': return 'void';
- case 'i': return 'i32';
- case 'f': return 'double';
- default: throw 'what is this sig? ' + sig;
- }
- },
-
// Mark a function as needing indexing. Python will coordinate them all
getIndex: function(ident, sig) {
var ret;
@@ -353,14 +363,17 @@ var Functions = {
if (t[0] == 'i') {
retPre = 'return ';
retPost = '|0';
- } else {
+ } else if (t[0] === 'd') {
retPre = 'return +';
+ } else {
+ retPre = 'return Math_fround(';
+ retPost = ')';
}
}
for (var j = 1; j < t.length; j++) {
args += (j > 1 ? ',' : '') + 'a' + j;
- arg_coercions += 'a' + j + '=' + asmCoercion('a' + j, t[j] != 'i' ? 'float' : 'i32') + ';';
- call += (j > 1 ? ',' : '') + asmCoercion('a' + j, t[j] != 'i' ? 'float' : 'i32');
+ arg_coercions += 'a' + j + '=' + asmCoercion('a' + j, Functions.getSignatureType(t[j])) + ';';
+ call += (j > 1 ? ',' : '') + asmCoercion('a' + j, Functions.getSignatureType(t[j]));
}
call += ')';
if (short == '_setjmp') printErr('WARNING: setjmp used via a function pointer. If this is for libc setjmp (not something of your own with the same name), it will break things');
diff --git a/tools/shared.py b/tools/shared.py
index 108a48a4..a923f88a 100644
--- a/tools/shared.py
+++ b/tools/shared.py
@@ -1511,6 +1511,28 @@ class JS:
return ident.replace('%', '$').replace('@', '_')
@staticmethod
+ def make_initializer(sig, settings=None):
+ settings = settings or Settings
+ if sig == 'i':
+ return '0'
+ elif sig == 'f' and settings.get('FROUND'):
+ return 'Math_fround(0)'
+ else:
+ return '+0'
+
+ @staticmethod
+ def make_coercion(value, sig, settings=None):
+ settings = settings or Settings
+ if sig == 'i':
+ return value + '|0'
+ elif sig == 'f' and settings.get('FROUND'):
+ return 'Math_fround(' + value + ')'
+ elif sig == 'd' or sig == 'f':
+ return '+' + value
+ else:
+ return value
+
+ @staticmethod
def make_extcall(sig, named=True):
args = ','.join(['a' + str(i) for i in range(1, len(sig))])
args = 'index' + (',' if args else '') + args