diff options
Diffstat (limited to 'tools/shared.py')
-rw-r--r-- | tools/shared.py | 79 |
1 files changed, 52 insertions, 27 deletions
diff --git a/tools/shared.py b/tools/shared.py index 5b238aa4..adf3004e 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -269,18 +269,52 @@ def read_pgo_data(filename): class Settings: @classmethod def reset(self): - global Settings class Settings2: - reset = Settings.reset - load_defaults = Settings.load_defaults QUANTUM_SIZE = 4 - Settings = Settings2 + reset = Settings.reset - @classmethod - def load_defaults(self): - ''' Load the JS settings into Python ''' - settings = open(path_from_root('src', 'settings.js')).read().replace('var ', 'Settings.').replace('//', '#') - exec(settings) + # Given some emcc-type args (-O3, -s X=Y, etc.), fill Settings with the right settings + @classmethod + def load(self, args): + # Load the JS defaults into python + settings = open(path_from_root('src', 'settings.js')).read().replace('var ', 'Settings.').replace('//', '#') + exec settings in globals() + + # Apply additional settings. First -O, then -s + for i in range(len(args)): + if args[i].startswith('-O'): + level = eval(args[i][2]) + Settings.apply_opt_level(level) + for i in range(len(args)): + if args[i] == '-s': + exec 'Settings.' + args[i+1] in globals() # execute the setting + + # Transforms the Settings information into emcc-compatible args (-s X=Y, etc.). Basically + # the reverse of load_settings, except for -Ox which is relevant there but not here + @classmethod + def serialize(self): + ret = [] + for key, value in Settings.__dict__.iteritems(): + if key == key.upper(): # this is a hack. all of our settings are ALL_CAPS, python internals are not + ret += ['-s', key + '=' + json.dumps(value)] + return ret + + @classmethod + def apply_opt_level(self, opt_level, noisy=False): + if opt_level >= 1: + Settings.ASSERTIONS = 0 + Settings.DISABLE_EXCEPTION_CATCHING = 1 + if opt_level >= 2: + Settings.RELOOP = 1 + if opt_level >= 3: + Settings.CORRECT_SIGNS = 0 + Settings.CORRECT_OVERFLOWS = 0 + Settings.CORRECT_ROUNDINGS = 0 + Settings.I64_MODE = 0 + Settings.DOUBLE_MODE = 0 + if noisy: print >> sys.stderr, 'Warning: Applying some potentially unsafe optimizations! (Use -O2 if this fails.)' + global Settings + Settings = Settings2 Settings.reset() # Building @@ -432,27 +466,21 @@ class Building: return ret @staticmethod - def emcc(filename, args=[], stdout=None, stderr=None, env=None): - try_delete(filename + '.o') - Popen([EMCC, filename] + args + ['-o', filename + '.o'], stdout=stdout, stderr=stderr, env=env).communicate()[0] - assert os.path.exists(filename + '.o'), 'Could not create bc file' + def emcc(filename, args=[], output_filename=None, stdout=None, stderr=None, env=None): + if output_filename is None: + output_filename = filename + '.o' + try_delete(output_filename) + Popen([EMCC, filename] + args + ['-o', output_filename], stdout=stdout, stderr=stderr, env=env).communicate() + assert os.path.exists(output_filename), 'emcc could not create output file' @staticmethod - def emscripten(filename, output_processor=None, append_ext=True, extra_args=[]): + def emscripten(filename, append_ext=True, extra_args=[]): # Add some headers by default. TODO: remove manually adding these in each test if '-H' not in extra_args: extra_args += ['-H', 'libc/fcntl.h,libc/sys/unistd.h,poll.h,libc/math.h,libc/langinfo.h,libc/time.h'] # Run Emscripten - exported_settings = {} - for setting in ['QUANTUM_SIZE', 'RELOOP', 'MICRO_OPTS', 'ASSERTIONS', 'USE_TYPED_ARRAYS', 'SAFE_HEAP', 'CHECK_OVERFLOWS', 'CORRECT_OVERFLOWS', 'CORRECT_SIGNS', 'CHECK_SIGNS', 'CORRECT_OVERFLOWS_LINES', 'CORRECT_SIGNS_LINES', 'CORRECT_ROUNDINGS', 'CORRECT_ROUNDINGS_LINES', 'INVOKE_RUN', 'SAFE_HEAP_LINES', 'INIT_STACK', 'PGO', 'EXPORTED_FUNCTIONS', 'EXPORTED_GLOBALS', 'BUILD_AS_SHARED_LIB', 'RUNTIME_LINKED_LIBS', 'INCLUDE_FULL_LIBRARY', 'RUNTIME_TYPE_INFO', 'DISABLE_EXCEPTION_CATCHING', 'TOTAL_MEMORY', 'FAST_MEMORY', 'EXCEPTION_DEBUG', 'PROFILE', 'I64_MODE', 'EMULATE_UNALIGNED_ACCESSES', 'CATCH_EXIT_CODE', 'USE_FHEAP']: - try: - value = eval('Settings.' + setting) - if value is not None: - exported_settings[setting] = value - except: - pass - settings = ['-s %s=%s' % (k, json.dumps(v)) for k, v in exported_settings.items()] + settings = Settings.serialize() compiler_output = timeout_run(Popen(['python', EMSCRIPTEN, filename + ('.o.ll' if append_ext else ''), '-o', filename + '.o.js'] + settings + extra_args, stdout=PIPE), None, 'Compiling') #print compiler_output @@ -460,9 +488,6 @@ class Building: if compiler_output is not None and 'Traceback' in compiler_output and 'in test_' in compiler_output: print compiler_output; assert 0 assert os.path.exists(filename + '.o.js') and len(open(filename + '.o.js', 'r').read()) > 0, 'Emscripten failed to generate .js: ' + str(compiler_output) - if output_processor is not None: - output_processor(open(filename + '.o.js').read()) - return filename + '.o.js' @staticmethod @@ -564,7 +589,7 @@ class Building: passes = [passes] input = open(filename, 'r').read() output, err = Popen([NODE_JS, JS_OPTIMIZER] + passes, stdin=PIPE, stdout=PIPE, stderr=PIPE).communicate(input) - assert len(output) > 0, 'Error in js optimizer: ' + err + '\n\n' + output + assert len(output) > 0 and not output.startswith('Assertion failed'), 'Error in js optimizer: ' + err + '\n\n' + output filename += '.jo.js' f = open(filename, 'w') f.write(output) |