aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS5
-rwxr-xr-xemcc85
-rwxr-xr-xemscripten.py22
-rw-r--r--src/fastLong.js18
-rw-r--r--src/jsifier.js53
-rw-r--r--src/library.js17
-rw-r--r--src/library_browser.js7
-rw-r--r--src/library_sdl.js50
-rw-r--r--src/modules.js3
-rw-r--r--src/parseTools.js10
-rw-r--r--src/relooper/Relooper.cpp10
-rw-r--r--src/relooper/test.txt108
-rw-r--r--src/relooper/test2.txt12
-rw-r--r--src/relooper/test3.txt34
-rw-r--r--src/relooper/test4.txt24
-rw-r--r--src/relooper/test5.txt46
-rw-r--r--src/relooper/test6.txt12
-rw-r--r--src/relooper/test_debug.txt12
-rw-r--r--src/relooper/test_fuzz1.txt40
-rw-r--r--src/relooper/test_fuzz2.txt10
-rw-r--r--src/relooper/test_fuzz3.txt2
-rw-r--r--src/relooper/test_fuzz4.txt16
-rw-r--r--src/relooper/test_fuzz5.txt82
-rw-r--r--src/relooper/test_fuzz6.txt186
-rw-r--r--src/relooper/test_inf.txt698
-rw-r--r--src/runtime.js6
-rw-r--r--tests/cases/returnfp.ll23
-rw-r--r--tests/hello_world_gles_deriv.c7
-rw-r--r--tests/hello_world_sdl.cpp8
-rw-r--r--tests/lua/binarytrees.lua17
-rw-r--r--tests/lua/scimark.lua50
-rwxr-xr-xtests/runner.py252
-rw-r--r--tests/sdl_audio_mix_channels.c59
-rw-r--r--tests/sdl_canvas.c2
-rw-r--r--tests/sdl_canvas_blank.c17
-rw-r--r--tests/sdl_canvas_blank.pngbin0 -> 914 bytes
-rw-r--r--tests/sdl_canvas_twice.c4
-rw-r--r--tests/sdl_image_prepare_data.c4
-rw-r--r--tests/sdl_maprgba.c1
-rw-r--r--tools/eliminator/asm-eliminator-test-output.js10071
-rw-r--r--tools/eliminator/asm-eliminator-test.js13531
-rw-r--r--tools/eliminator/eliminator-test-output.js11798
-rw-r--r--tools/eliminator/eliminator-test.js17258
-rw-r--r--tools/eliminator/safe-eliminator-test-output.js164
-rw-r--r--tools/eliminator/safe-eliminator-test.js198
-rw-r--r--tools/file_packager.py2
-rw-r--r--tools/js-optimizer.js283
-rw-r--r--tools/js_optimizer.py31
-rw-r--r--tools/shared.py8
-rw-r--r--tools/test-js-optimizer-asm-last-output.js82
-rw-r--r--tools/test-js-optimizer-asm-last.js94
-rw-r--r--tools/test-js-optimizer-asm-pre-output.js640
-rw-r--r--tools/test-js-optimizer-asm-pre.js651
-rw-r--r--tools/test-js-optimizer-asm-regs-min-output.js50
-rw-r--r--tools/test-js-optimizer-asm-regs-min.js52
-rw-r--r--tools/test-js-optimizer-asm-regs-output.js180
-rw-r--r--tools/test-js-optimizer-asm-regs.js186
-rw-r--r--tools/test-js-optimizer-asm-relocate-output.js9
-rw-r--r--tools/test-js-optimizer-asm-relocate.js12
-rw-r--r--tools/test-js-optimizer-output.js482
-rw-r--r--tools/test-js-optimizer-regs-output.js426
-rw-r--r--tools/test-js-optimizer-regs.js436
-rw-r--r--tools/test-js-optimizer-t2-output.js176
-rw-r--r--tools/test-js-optimizer-t2.js176
-rw-r--r--tools/test-js-optimizer-t2c-output.js28
-rw-r--r--tools/test-js-optimizer-t2c.js30
-rw-r--r--tools/test-js-optimizer-t3-output.js90
-rw-r--r--tools/test-js-optimizer-t3.js90
-rw-r--r--tools/test-js-optimizer.js666
69 files changed, 30519 insertions, 29393 deletions
diff --git a/AUTHORS b/AUTHORS
index 6dd9d53e..27206740 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -84,7 +84,4 @@ a license to everyone to use it as detailed in LICENSE.)
* Marc Feeley <mfeeley@mozilla.com> (copyright owned by Mozilla Foundation)
* Ludovic Perrine <jazzzz@gmail.com>
* David Barksdale <david.barksdale@adcedosolutions.com>
-
-
-
-
+* Manfred Manik Nerurkar <nerurkar*at*made-apps.biz> (copyright owned by MADE, GmbH)
diff --git a/emcc b/emcc
index b8230e95..8368f3b1 100755
--- a/emcc
+++ b/emcc
@@ -182,16 +182,31 @@ Options that are modified or new in %s include:
). Note that the path must be absolute, not
relative.
- -g Use debug info. Note that you need this during
- the last compilation phase from bitcode to
- JavaScript, or else we will remove it by
- default in -O1 and above.
- In -O0, line numbers wil be shown in the
- generated code. In -O1 and above, the optimizer
- removes those comments. This flag does however
- have the effect of disabling anything that
- causes name mangling or minification (closure
- or the registerize pass).
+ -g Use debug info. When compiling to bitcode,
+ this is the same as in clang and gcc, it
+ adds debug info to the object files. When
+ compiling from source to JS or bitcode to JS,
+ it is equivalent to -g3 (keep code as debuggable
+ as possible, except for discarding LLVM
+ debug info, so no C/C++ line numbers; use
+ -g4 to get line number debugging info in JS).
+
+ -g<level> When compiling from bitcode to JS, we can
+ keep the code debuggable to different
+ degrees. Each of these levels builds on the
+ previous:
+
+ -g0 Make no effort to keep code debuggable.
+ Will discard LLVM debug info. (default
+ in -O1+)
+ -g1 Preserve (do not minify) whitespace
+ -g2 Preserve function names
+ -g3 Preserve variable names
+ -g4 Preserve LLVM debug info (if -g was
+ used when compiling the C/C++ sources)
+ and show line number debug comments.
+ This is the highest level of debuggability.
+ (default in -O0)
--typed-arrays <mode> 0: No typed arrays
1: Parallel typed arrays
@@ -303,12 +318,7 @@ Options that are modified or new in %s include:
archive, which is given the same name as the
output HTML but with suffix .data.compress
- --minify <on> 0: Do not minify the generated JavaScript's
- whitespace (default in -O0, -O1, or if
- -g is used)
- 1: Minify the generated JavaScript's
- whitespace (default in -O2+, assuming
- -g is not used)
+ --minify 0 Identical to -g1
--split <size> Splits the resulting javascript file into pieces
to ease debugging. This option only works if
@@ -689,13 +699,13 @@ try:
newargs = sys.argv[1:]
opt_level = 0
+ debug_level = 0
llvm_opts = None
llvm_lto = None
closure = None
js_transform = None
pre_js = ''
post_js = ''
- minify_whitespace = None
split_js_file = None
preload_files = []
embed_files = []
@@ -703,8 +713,6 @@ try:
ignore_dynamic_linking = False
shell_path = shared.path_from_root('src', 'shell.html')
js_libraries = []
- keep_llvm_debug = False
- keep_js_debug = False
bind = False
jcache = False
save_bc = False
@@ -769,7 +777,7 @@ try:
newargs[i+1] = ''
elif newargs[i].startswith('--minify'):
check_bad_eq(newargs[i])
- minify_whitespace = int(newargs[i+1])
+ debug_level = max(1, debug_level)
newargs[i] = ''
newargs[i+1] = ''
elif newargs[i].startswith('--split'):
@@ -777,9 +785,14 @@ try:
split_js_file = int(newargs[i+1])
newargs[i] = ''
newargs[i+1] = ''
- elif newargs[i] == '-g':
- keep_llvm_debug = True
- keep_js_debug = True
+ elif newargs[i].startswith('-g'):
+ requested_level = newargs[i][2:] or '3'
+ try:
+ debug_level = int(requested_level)
+ assert 0 <= debug_level <= 4
+ except:
+ raise Exception('Invalid debug level: ' + newargs[i])
+ newargs[i] = '-g' # discard level for clang args
elif newargs[i] == '--bind':
bind = True
newargs[i] = ''
@@ -868,8 +881,7 @@ try:
if llvm_opts is None: llvm_opts = LLVM_OPT_LEVEL[opt_level]
if llvm_lto is None: llvm_lto = opt_level >= 3
- if opt_level <= 0: keep_llvm_debug = keep_js_debug = True # always keep debug in -O0
- if opt_level > 0: keep_llvm_debug = False # JS optimizer wipes out llvm debug info from being visible
+ if opt_level == 0: debug_level = 4
if closure is None and opt_level == 3: closure = True
if DEBUG: start_time = time.time() # done after parsing arguments, which might affect debug state
@@ -1019,15 +1031,12 @@ try:
logging.warning('ALIASING_FUNCTION_POINTERS is on, function pointer comparisons may be invalid across types')
if shared.Settings.CORRECT_SIGNS >= 2 or shared.Settings.CORRECT_OVERFLOWS >= 2 or shared.Settings.CORRECT_ROUNDINGS >= 2:
- keep_llvm_debug = True # must keep debug info to do line-by-line operations
+ debug_level = 4 # must keep debug info to do line-by-line operations
- if (keep_llvm_debug or keep_js_debug) and closure:
+ if debug_level > 0 and closure:
logging.warning('disabling closure because debug info was requested')
closure = False
- if minify_whitespace is None:
- minify_whitespace = opt_level >= 2 and not keep_js_debug
-
assert shared.LLVM_TARGET in shared.COMPILER_OPTS
if shared.LLVM_TARGET == 'i386-pc-linux-gnu':
shared.Settings.TARGET_X86 = 1
@@ -1054,7 +1063,7 @@ try:
output_file = in_temp(unsuffixed(uniquename(input_file)) + '.o')
temp_files.append(output_file)
args = newargs + ['-emit-llvm', '-c', input_file, '-o', output_file]
- logging.debug("running:" + call + ' '.join(args))
+ logging.debug("running:" + call + ' ' + ' '.join(args))
execute([call] + args) # let compiler frontend print directly, so colors are saved (PIPE kills that)
if not os.path.exists(output_file):
logging.error('compiler frontend failed to generate LLVM bitcode, halting')
@@ -1132,6 +1141,8 @@ try:
libcxx_symbols = read_symbols(shared.path_from_root('system', 'lib', 'libcxx', 'symbols'), exclude=libc_symbols)
libcxxabi_symbols = read_symbols(shared.path_from_root('system', 'lib', 'libcxxabi', 'symbols'), exclude=libc_symbols)
+ # XXX we should disable EMCC_DEBUG (and EMCC_OPTIMIZE_NORMALLY?) when building libs, just like in the relooper
+
def build_libc(lib_filename, files):
o_s = []
prev_cxx = os.environ.get('EMMAKEN_CXX')
@@ -1352,7 +1363,7 @@ try:
for haz in has: # remove symbols that are supplied by another of the inputs
if haz in need:
need.remove(haz)
- logging.debug('considering %s: we need %s and have %s' % (name, str(need), str(has)))
+ if shared.Settings.VERBOSE: logging.debug('considering %s: we need %s and have %s' % (name, str(need), str(has)))
if (force or len(need) > 0) and apply_(need):
# We need to build and link the library in
logging.debug('including %s' % name)
@@ -1396,7 +1407,7 @@ try:
# Optimize, if asked to
if not LEAVE_INPUTS_RAW:
- link_opts = [] if keep_llvm_debug else ['-strip-debug'] # remove LLVM debug info in -O1+, since the optimizer removes it anyhow
+ link_opts = [] if debug_level >= 4 else ['-strip-debug'] # remove LLVM debug if we are not asked for it
if llvm_opts > 0:
if not os.environ.get('EMCC_OPTIMIZE_NORMALLY'):
shared.Building.llvm_opt(in_temp(target_basename + '.bc'), llvm_opts)
@@ -1538,12 +1549,12 @@ try:
logging.debug('running post-closure post-opts')
js_optimizer_queue += ['simplifyExpressionsPost']
- if (not closure or shared.Settings.ASM_JS) and shared.Settings.RELOOP and not keep_js_debug:
- # do this if closure is not enabled (it gives similar speedups), and we do not need to keep debug info around
+ if (not closure or shared.Settings.ASM_JS) and shared.Settings.RELOOP and debug_level < 3:
js_optimizer_queue += ['registerize']
- if minify_whitespace:
- js_optimizer_queue += ['compress']
+ if opt_level > 0:
+ if debug_level < 2 and shared.Settings.ASM_JS: js_optimizer_queue = map(lambda p: p if p != 'registerize' else 'registerizeAndMinify', js_optimizer_queue)
+ if debug_level == 0: js_optimizer_queue += ['minifyWhitespace']
if closure and shared.Settings.ASM_JS:
js_optimizer_queue += ['closure']
diff --git a/emscripten.py b/emscripten.py
index d8312855..56f59273 100755
--- a/emscripten.py
+++ b/emscripten.py
@@ -128,7 +128,7 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
if DEBUG: print >> sys.stderr, ' emscript: split took %s seconds' % (time.time() - t)
if len(funcs) == 0:
- raise RuntimeError('No functions to process. Make sure you prevented LLVM from eliminating them as dead (use EXPORTED_FUNCTIONS if necessary, see the FAQ)')
+ print >> sys.stderr, 'No functions to process. Make sure you prevented LLVM from eliminating them as dead (use EXPORTED_FUNCTIONS if necessary, see the FAQ)'
#if DEBUG:
# print >> sys.stderr, '========= pre ================\n'
@@ -407,7 +407,7 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
math_envs = ['Math.min'] # TODO: move min to maths
asm_setup += '\n'.join(['var %s = %s;' % (f.replace('.', '_'), f) for f in math_envs])
- basic_funcs = ['abort', 'assert', 'asmPrintInt', 'asmPrintFloat', 'copyTempDouble', 'copyTempFloat'] + [m.replace('.', '_') for m in math_envs]
+ basic_funcs = ['abort', 'assert', 'asmPrintInt', 'asmPrintFloat'] + [m.replace('.', '_') for m in math_envs]
if settings['RESERVED_FUNCTION_POINTERS'] > 0: basic_funcs.append('jsCall')
if settings['SAFE_HEAP']: basic_funcs += ['SAFE_HEAP_LOAD', 'SAFE_HEAP_STORE', 'SAFE_HEAP_CLEAR']
if settings['CHECK_HEAP_ALIGN']: basic_funcs += ['CHECK_ALIGN_2', 'CHECK_ALIGN_4', 'CHECK_ALIGN_8']
@@ -555,6 +555,24 @@ var asm = (function(global, env, buffer) {
threwValue = value;
}
}
+ function copyTempFloat(ptr) {
+ ptr = ptr|0;
+ HEAP8[tempDoublePtr] = HEAP8[ptr];
+ HEAP8[tempDoublePtr+1|0] = HEAP8[ptr+1|0];
+ HEAP8[tempDoublePtr+2|0] = HEAP8[ptr+2|0];
+ HEAP8[tempDoublePtr+3|0] = HEAP8[ptr+3|0];
+ }
+ function copyTempDouble(ptr) {
+ ptr = ptr|0;
+ HEAP8[tempDoublePtr] = HEAP8[ptr];
+ HEAP8[tempDoublePtr+1|0] = HEAP8[ptr+1|0];
+ HEAP8[tempDoublePtr+2|0] = HEAP8[ptr+2|0];
+ HEAP8[tempDoublePtr+3|0] = HEAP8[ptr+3|0];
+ HEAP8[tempDoublePtr+4|0] = HEAP8[ptr+4|0];
+ HEAP8[tempDoublePtr+5|0] = HEAP8[ptr+5|0];
+ HEAP8[tempDoublePtr+6|0] = HEAP8[ptr+6|0];
+ HEAP8[tempDoublePtr+7|0] = HEAP8[ptr+7|0];
+ }
''' + ''.join(['''
function setTempRet%d(value) {
value = value|0;
diff --git a/src/fastLong.js b/src/fastLong.js
index d1ce5d39..4f6efd9f 100644
--- a/src/fastLong.js
+++ b/src/fastLong.js
@@ -5,12 +5,12 @@ function ___muldsi3($a, $b) {
var $1 = 0, $2 = 0, $3 = 0, $6 = 0, $8 = 0, $11 = 0, $12 = 0;
$1 = $a & 65535;
$2 = $b & 65535;
- $3 = Math.imul($2, $1);
+ $3 = Math.imul($2, $1) | 0;
$6 = $a >>> 16;
- $8 = ($3 >>> 16) + Math.imul($2, $6) | 0;
+ $8 = ($3 >>> 16) + (Math.imul($2, $6) | 0) | 0;
$11 = $b >>> 16;
- $12 = Math.imul($11, $1);
- return (tempRet0 = (($8 >>> 16) + Math.imul($11, $6) | 0) + ((($8 & 65535) + $12 | 0) >>> 16) | 0, 0 | ($8 + $12 << 16 | $3 & 65535)) | 0;
+ $12 = Math.imul($11, $1) | 0;
+ return (tempRet0 = (($8 >>> 16) + (Math.imul($11, $6) | 0) | 0) + ((($8 & 65535) + $12 | 0) >>> 16) | 0, 0 | ($8 + $12 << 16 | $3 & 65535)) | 0;
}
function ___divdi3($a$0, $a$1, $b$0, $b$1) {
$a$0 = $a$0 | 0;
@@ -47,7 +47,7 @@ function ___remdi3($a$0, $a$1, $b$0, $b$1) {
$4$0 = _i64Subtract($1$0 ^ $a$0, $1$1 ^ $a$1, $1$0, $1$1) | 0;
$4$1 = tempRet0;
$6$0 = _i64Subtract($2$0 ^ $b$0, $2$1 ^ $b$1, $2$0, $2$1) | 0;
- ___udivmoddi4($4$0, $4$1, $6$0, tempRet0, $rem);
+ ___udivmoddi4($4$0, $4$1, $6$0, tempRet0, $rem) | 0;
$10$0 = _i64Subtract(HEAP32[$rem >> 2] ^ $1$0, HEAP32[$rem + 4 >> 2] ^ $1$1, $1$0, $1$1) | 0;
$10$1 = tempRet0;
STACKTOP = __stackBase__;
@@ -63,8 +63,8 @@ function ___muldi3($a$0, $a$1, $b$0, $b$1) {
$y_sroa_0_0_extract_trunc = $b$0;
$1$0 = ___muldsi3($x_sroa_0_0_extract_trunc, $y_sroa_0_0_extract_trunc) | 0;
$1$1 = tempRet0;
- $2 = Math.imul($a$1, $y_sroa_0_0_extract_trunc);
- return (tempRet0 = (Math.imul($b$1, $x_sroa_0_0_extract_trunc) + $2 | 0) + $1$1 | $1$1 & 0, 0 | $1$0 & -1) | 0;
+ $2 = Math.imul($a$1, $y_sroa_0_0_extract_trunc) | 0;
+ return (tempRet0 = ((Math.imul($b$1, $x_sroa_0_0_extract_trunc) | 0) + $2 | 0) + $1$1 | $1$1 & 0, 0 | $1$0 & -1) | 0;
}
function ___udivdi3($a$0, $a$1, $b$0, $b$1) {
$a$0 = $a$0 | 0;
@@ -84,7 +84,7 @@ function ___uremdi3($a$0, $a$1, $b$0, $b$1) {
__stackBase__ = STACKTOP;
STACKTOP = STACKTOP + 8 | 0;
$rem = __stackBase__ | 0;
- ___udivmoddi4($a$0, $a$1, $b$0, $b$1, $rem);
+ ___udivmoddi4($a$0, $a$1, $b$0, $b$1, $rem) | 0;
STACKTOP = __stackBase__;
return (tempRet0 = HEAP32[$rem + 4 >> 2] | 0, HEAP32[$rem >> 2] | 0) | 0;
}
@@ -258,7 +258,7 @@ function ___udivmoddi4($a$0, $a$1, $b$0, $b$1, $rem) {
$149 = $carry_0203 | $q_sroa_0_1199 << 1;
$r_sroa_0_0_insert_insert42$0 = 0 | ($r_sroa_0_1201 << 1 | $q_sroa_1_1198 >>> 31);
$r_sroa_0_0_insert_insert42$1 = $r_sroa_0_1201 >>> 31 | $r_sroa_1_1200 << 1 | 0;
- _i64Subtract($137$0, $137$1, $r_sroa_0_0_insert_insert42$0, $r_sroa_0_0_insert_insert42$1);
+ _i64Subtract($137$0, $137$1, $r_sroa_0_0_insert_insert42$0, $r_sroa_0_0_insert_insert42$1) | 0;
$150$1 = tempRet0;
$151$0 = $150$1 >> 31 | (($150$1 | 0) < 0 ? -1 : 0) << 1;
$152 = $151$0 & 1;
diff --git a/src/jsifier.js b/src/jsifier.js
index faef88d5..ac6c259b 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -14,6 +14,8 @@ var asmLibraryFunctions = [];
var SETJMP_LABEL = -1;
+var INDENTATION = ' ';
+
// JSifier
function JSify(data, functionsOnly, givenFunctions) {
var mainPass = !functionsOnly;
@@ -591,13 +593,13 @@ function JSify(data, functionsOnly, givenFunctions) {
func.JS += 'function ' + func.ident + '(' + paramIdents.join(', ') + ') {\n';
if (PGO) {
- func.JS += ' PGOMonitor.called["' + func.ident + '"] = 1;\n';
+ func.JS += INDENTATION + 'PGOMonitor.called["' + func.ident + '"] = 1;\n';
}
if (ASM_JS) {
// spell out argument types
func.params.forEach(function(param) {
- func.JS += ' ' + param.ident + ' = ' + asmCoercion(param.ident, param.type) + ';\n';
+ func.JS += INDENTATION + param.ident + ' = ' + asmCoercion(param.ident, param.type) + ';\n';
});
// spell out local variables
@@ -611,7 +613,7 @@ function JSify(data, functionsOnly, givenFunctions) {
i += chunkSize;
}
for (i = 0; i < chunks.length; i++) {
- func.JS += ' var ' + chunks[i].map(function(v) {
+ func.JS += INDENTATION + 'var ' + chunks[i].map(function(v) {
var type = getImplementationType(v);
if (!isIllegalType(type) || v.ident.indexOf('$', 1) > 0) { // not illegal, or a broken up illegal
return v.ident + ' = ' + asmInitializer(type); //, func.variables[v.ident].impl);
@@ -627,7 +629,7 @@ function JSify(data, functionsOnly, givenFunctions) {
if (true) { // TODO: optimize away when not needed
if (CLOSURE_ANNOTATIONS) func.JS += '/** @type {number} */';
- func.JS += ' var label = 0;\n';
+ func.JS += INDENTATION + 'var label = 0;\n';
}
if (ASM_JS) {
@@ -636,12 +638,12 @@ function JSify(data, functionsOnly, givenFunctions) {
hasByVal = hasByVal || param.byVal;
});
if (hasByVal) {
- func.JS += ' var tempParam = 0;\n';
+ func.JS += INDENTATION + 'var tempParam = 0;\n';
}
}
// Prepare the stack, if we need one. If we have other stack allocations, force the stack to be set up.
- func.JS += ' ' + RuntimeGenerator.stackEnter(func.initialStack, func.otherStackAllocations) + ';\n';
+ func.JS += INDENTATION + RuntimeGenerator.stackEnter(func.initialStack, func.otherStackAllocations) + ';\n';
// Make copies of by-value params
// XXX It is not clear we actually need this. While without this we fail, it does look like
@@ -654,7 +656,7 @@ function JSify(data, functionsOnly, givenFunctions) {
if (param.byVal) {
var type = removePointing(param.type);