summaryrefslogtreecommitdiff
path: root/tools/shared.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/shared.py')
-rw-r--r--tools/shared.py79
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)