diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/autodebugger.py | 31 | ||||
-rw-r--r-- | tools/autodebugger_js.py | 47 | ||||
-rw-r--r-- | tools/eliminator/eliminator-test-output.js | 7 | ||||
-rw-r--r-- | tools/eliminator/eliminator-test.js | 14 | ||||
-rw-r--r-- | tools/file_packager.py | 12 | ||||
-rw-r--r-- | tools/js-optimizer.js | 4 | ||||
-rw-r--r-- | tools/js_optimizer.py | 8 | ||||
-rwxr-xr-x | tools/nativize_llvm.py | 9 | ||||
-rw-r--r-- | tools/shared.py | 9 |
9 files changed, 120 insertions, 21 deletions
diff --git a/tools/autodebugger.py b/tools/autodebugger.py index 3631548c..c74e56d2 100644 --- a/tools/autodebugger.py +++ b/tools/autodebugger.py @@ -13,6 +13,7 @@ import os, sys, re ALLOW_POINTERS = False ALLOW_MISC = True MEMCPY = False +MEMCPY2 = False NO_DLMALLOC = True POSTAMBLE = ''' @@ -89,12 +90,15 @@ return: ; preds = %entry POSTAMBLE_NEW = ''' @.emscripten.autodebug.str = private constant [10 x i8] c"AD:%d,%d\\0A\\00", align 1 ; [#uses=1] +@.emscripten.autodebug.str.2 = private constant [13 x i8] c"AD:%d,%d,%d\\0A\\00", align 1 ; [#uses=1] @.emscripten.autodebug.str.f = private constant [11 x i8] c"AD:%d,%lf\\0A\\00", align 1 ; [#uses=1] ; [#uses=1] define void @emscripten_autodebug_i64(i32 %line, i64 %value) { - %1 = sitofp i64 %value to double - %2 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([11 x i8]* @.emscripten.autodebug.str.f, i32 0, i32 0), i32 %line, double %1) ; [#uses=0] + %1 = trunc i64 %value to i32 + %2 = lshr i64 %value, 32 + %3 = trunc i64 %2 to i32 + %4 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([13 x i8]* @.emscripten.autodebug.str.2, i32 0, i32 0), i32 %line, i32 %1, i32 %3) ; [#uses=0] ret void } @@ -142,6 +146,10 @@ if 'declare i32 @printf(' not in data: ; [#uses=1] declare i32 @printf(i8*, ...) ''' + POSTAMBLE_NEW += ''' +; [#uses=1] +declare i32 @printf(i8*, ...) +''' LLVM_STYLE_OLD = '<label>' not in data and 'entry:' in data @@ -252,20 +260,21 @@ for i in range(len(lines)): lines_added += 1 continue if ALLOW_MISC: - m = re.match(' %(?P<var>[\w_.]+) = (call|mul|add) (nsw )?(?P<type>i64|i32|i16|i8|float|double+) .*', lines[i]) + # call is risky - return values can be i32 (i8*) (i16) + m = re.match(' %(?P<var>[\w_.]+) = (mul|add) (nsw )?(?P<type>i64|i32|i16|i8|float|double+) .*', lines[i]) if m: index = i+1+lines_added lines[i] += '\n call void @emscripten_autodebug_%s(i32 %d, %s %%%s)' % (m.group('type'), index, m.group('type'), m.group('var')) lines_added += 1 continue - m = re.match(' call void @llvm\.memcpy\.p0i8\.p0i8\.i32\(i8\* %(?P<dst>[\w_.]+), i8\* %(?P<src>[\w_.]+), i32 8, i32 (?P<align>\d+),.*', lines[i]) - if m: - index = i+1+lines_added - lines[i] += '\n %%adpretemp%d = bitcast i8* %%%s to i64*' % (index, m.group('src')) + \ - '\n %%adtemp%d = load i64* %%adpretemp%d, align %s' % (index, index, m.group('align')) + \ - '\n call void @emscripten_autodebug_%s(i32 %d, %s %%adtemp%d)' % ('i64', index, 'i64', index) - lines_added += 3 - continue + if MEMCPY2: + m = re.match(' call void @llvm\.memcpy\.p0i8\.p0i8\.i32\(i8\* %(?P<dst>[\w_.]+), i8\* %(?P<src>[\w_.]+), i32 8, i32 (?P<align>\d+),.*', lines[i]) + if m: + index = i+1+lines_added + lines[i] += '\n %%adtemp%d = load i8* %%%s, align 1' % (index, m.group('src')) + \ + '\n call void @emscripten_autodebug_i8(i32 %d, i8 %%adtemp%d)' % (index, index) + lines_added += 3 + continue finally: if len(pre) > 0: diff --git a/tools/autodebugger_js.py b/tools/autodebugger_js.py new file mode 100644 index 00000000..3f8818c6 --- /dev/null +++ b/tools/autodebugger_js.py @@ -0,0 +1,47 @@ +''' +Processes a C source file, adding debugging information. + +Similar to autodebugger.py, but runs on .js files. +''' + +import os, sys, re + +filename = sys.argv[1] +func = sys.argv[2] + +f = open(filename, 'r') +data = f.read() +f.close() + +lines = data.split('\n') +in_func = False +for i in range(len(lines)): + if lines[i].startswith('function '): + name = lines[i].split('(')[0].split(' ')[1] + args = lines[i].split('(')[1].split(')')[0] + lines[i] += ' print("call %s(" + [%s] + ")");' % (name, args) + if lines[i].startswith('function ' + func + '('): + in_func = True + continue + elif lines[i].startswith('}'): + in_func = False + continue + if in_func: + m = re.match('^ +([$_\w\d \[\]]+) = +([^;]+);$', lines[i]) + if m and (' if ' not in lines[i-1] or '{' in lines[i-1]) and \ + (' if ' not in lines[i+1] or '{' in lines[i+1]) and \ + (' else' not in lines[i-1] or '{' in lines[i-1]) and \ + (' else' not in lines[i+1] or '{' in lines[i+1]): + var = m.groups(1)[0].rstrip().split(' ')[-1] + if 'STACKTOP' not in lines[i] and 'stackBase' not in lines[i]: + #lines[i] += ''' print("[%4d] %s = " + %s);''' % (i+1, var, var) + lines[i] += ''' print("%s = " + %s);''' % (var, var) + m = re.match('^ +HEAP.*$', lines[i]) + if m and lines[i].count(' = ') == 1: + left, right = lines[i].split(' = ') + lines[i] += ''' print("%s = " + %s);''' % (left, left) + +print '\n'.join(lines) + +print >> sys.stderr, 'Success.' + diff --git a/tools/eliminator/eliminator-test-output.js b/tools/eliminator/eliminator-test-output.js index 0d60d305..a005a0a5 100644 --- a/tools/eliminator/eliminator-test-output.js +++ b/tools/eliminator/eliminator-test-output.js @@ -6148,4 +6148,11 @@ function phi() { } var $10; } +function intoCond() { + var $115 = 22; + var $NumWords = __ZN4llvm15BitstreamCursor4ReadEj($117, 32); + if (($115 | 0) != 0) { + HEAP32[$115 >> 2] = $NumWords; + } +} diff --git a/tools/eliminator/eliminator-test.js b/tools/eliminator/eliminator-test.js index 3d71c210..13ecab59 100644 --- a/tools/eliminator/eliminator-test.js +++ b/tools/eliminator/eliminator-test.js @@ -8847,5 +8847,17 @@ function phi() { } var $10; } -// EMSCRIPTEN_GENERATED_FUNCTIONS: ["a", "b", "c", "f", "g", "h", "py", "r", "t", "f2", "f3", "llvm3_1", "_inflate", "_malloc", "_mallocNoU", "asm", "phi"] +function intoCond() { + var $115 = 22; + var $499 = __ZN4llvm15BitstreamCursor4ReadEj($117, 32); + var $NumWords = $499; + var $500 = $115; + var $501 = ($500 | 0) != 0; + if ($501) { + var $503 = $NumWords; + var $504 = $115; + HEAP32[$504 >> 2] = $503; + } +} +// EMSCRIPTEN_GENERATED_FUNCTIONS: ["a", "b", "c", "f", "g", "h", "py", "r", "t", "f2", "f3", "llvm3_1", "_inflate", "_malloc", "_mallocNoU", "asm", "phi", "intoCond"] diff --git a/tools/file_packager.py b/tools/file_packager.py index 33082ac2..7e196efd 100644 --- a/tools/file_packager.py +++ b/tools/file_packager.py @@ -252,7 +252,17 @@ for file_ in data_files: filename = file_['name'] if file_['mode'] == 'embed': # Embed - code += '''Module['FS_createDataFile']('/%s', '%s', %s, true, true);\n''' % (os.path.dirname(filename), os.path.basename(filename), str(map(ord, open(file_['localname'], 'rb').read()))) + data = map(ord, open(file_['localname'], 'rb').read()) + str_data = '' + chunk_size = 10240 + while len(data) > 0: + chunk = data[:chunk_size] + data = data[chunk_size:] + if not str_data: + str_data = str(chunk) + else: + str_data += '.concat(' + str(chunk) + ')' + code += '''Module['FS_createDataFile']('/%s', '%s', %s, true, true);\n''' % (os.path.dirname(filename), os.path.basename(filename), str_data) elif file_['mode'] == 'preload': # Preload varname = 'filePreload%d' % counter diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 85a7b214..77c48a23 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -1937,6 +1937,10 @@ function eliminate(ast, memSafe, asm) { } else if (type == 'if') { if (allowTracking) { traverseInOrder(node[1]); // can eliminate into condition, but nowhere else + if (!callsInvalidated) { // invalidate calls, since we cannot eliminate them into an if that may not execute! + invalidateCalls(); + callsInvalidated = true; + } allowTracking = false; traverseInOrder(node[2]); // 2 and 3 could be 'parallel', really.. if (node[3]) traverseInOrder(node[3]); diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index 744e068a..b72a2084 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -26,7 +26,8 @@ def run_on_chunk(command): f.close() return filename -def run(filename, passes, js_engine, jcache): +def run_on_js(filename, passes, js_engine, jcache): + if jcache: shared.JCache.ensure() if type(passes) == str: @@ -144,6 +145,8 @@ def run(filename, passes, js_engine, jcache): else: filenames = [] + for filename in filenames: temp_files.note(filename) + filename += '.jo.js' f = open(filename, 'w') f.write(pre); @@ -170,3 +173,6 @@ def run(filename, passes, js_engine, jcache): return filename +def run(filename, passes, js_engine, jcache): + return temp_files.run_and_clean(lambda: run_on_js(filename, passes, js_engine, jcache)) + diff --git a/tools/nativize_llvm.py b/tools/nativize_llvm.py index e76b9a4e..d9558c32 100755 --- a/tools/nativize_llvm.py +++ b/tools/nativize_llvm.py @@ -23,9 +23,12 @@ libs = sys.argv[2:] # e.g.: dl for dlopen/dlclose, util for openpty/forkpty print 'bc => clean bc' Popen([LLVM_OPT, filename, '-strip-debug', '-o=' + filename + '.clean.bc']).communicate()[0] print 'bc => s' -Popen([LLVM_COMPILER, filename + '.clean.bc', '-o=' + filename + '.s']).communicate()[0] -print 's => o' -Popen(['as', filename + '.s', '-o', filename + '.o']).communicate()[0] +for params in [[], ['-march=x86-64']]: # try x86, then x86-64 FIXME + print 'params', params + Popen([LLVM_COMPILER] + params + [filename + '.clean.bc', '-o=' + filename + '.s']).communicate()[0] + print 's => o' + Popen(['as', filename + '.s', '-o', filename + '.o']).communicate()[0] + if os.path.exists(filename + '.o'): break print 'o => runnable' Popen(['g++', path_from_root('system', 'lib', 'debugging.cpp'), filename + '.o', '-o', filename + '.run'] + ['-l' + lib for lib in libs]).communicate()[0] diff --git a/tools/shared.py b/tools/shared.py index d850b770..c310afd4 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -328,13 +328,13 @@ except: try: PYTHON except: - print >> sys.stderr, 'PYTHON not defined in ~/.emscripten, using "python"' + if DEBUG: print >> sys.stderr, 'PYTHON not defined in ~/.emscripten, using "python"' PYTHON = 'python' try: JAVA except: - print >> sys.stderr, 'JAVA not defined in ~/.emscripten, using "java"' + if DEBUG: print >> sys.stderr, 'JAVA not defined in ~/.emscripten, using "java"' JAVA = 'java' # Additional compiler options @@ -344,7 +344,7 @@ try: except: COMPILER_OPTS = [] # Force a simple, standard target as much as possible: target 32-bit linux, and disable various flags that hint at other platforms -COMPILER_OPTS = COMPILER_OPTS + ['-m32', '-U__i386__', '-U__x86_64__', '-U__i386', '-U__x86_64', '-U__SSE__', '-U__SSE2__', '-U__MMX__', +COMPILER_OPTS = COMPILER_OPTS + ['-m32', '-U__i386__', '-U__x86_64__', '-U__i386', '-U__x86_64', '-Ui386', '-Ux86_64', '-U__SSE__', '-U__SSE2__', '-U__MMX__', '-UX87_DOUBLE_ROUNDING', '-UHAVE_GCC_ASM_FOR_X87', '-DEMSCRIPTEN', '-U__STRICT_ANSI__', '-U__CYGWIN__', '-D__STDC__', '-Xclang', '-triple=i386-pc-linux-gnu', '-D__IEEE_LITTLE_ENDIAN', '-fno-math-errno'] @@ -430,7 +430,7 @@ class TempFiles: def run_and_clean(self, func): try: - func() + return func() finally: self.clean() @@ -820,6 +820,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e def llvm_opt(filename, opts): if type(opts) is int: opts = Building.pick_llvm_opts(opts) + if DEBUG: print >> sys.stderr, 'emcc: LLVM opts:', opts output = Popen([LLVM_OPT, filename] + opts + ['-o=' + filename + '.opt.bc'], stdout=PIPE).communicate()[0] assert os.path.exists(filename + '.opt.bc'), 'Failed to run llvm optimizations: ' + output shutil.move(filename + '.opt.bc', filename) |