This commit is contained in:
Alon Zakai 2011-12-13 12:20:45 -08:00
Родитель 09f3e4c413
Коммит 9071942043
3 изменённых файлов: 53 добавлений и 36 удалений

71
emcc
Просмотреть файл

@ -8,12 +8,9 @@ emcc is a drop-in replacement for a compiler like gcc or clang.
Tell your build system to use this instead of the compiler, linker, ar and
ranlib. All the normal build commands will be sent to this script, which
will proxy them to the appropriate LLVM build commands, in order to
generate proper code for Emscripten to later process.
For example, compilation will be translated into calls to clang
with -emit-llvm, and linking will be translated into calls to llvm-link,
and so forth.
will proxy them to the appropriate build commands. For example, compilation
will be translated into calls to clang with -emit-llvm, and linking will
be translated into calls to llvm-link, and so forth.
Example uses:
@ -77,7 +74,6 @@ emcc can be influenced by a few environment variables:
your system headers will be used.
EMMAKEN_COMPILER - The compiler to be used, if you don't want the default clang.
'''
import os, sys, shutil
@ -117,16 +113,24 @@ Most normal gcc/g++ options will work, for example:
Options that are modified or new in %s include:
-O0 No optimizations (default)
-O1 Simple optimizations and no runtime assertions
-O1 Simple optimizations, including safe LLVM
optimizations, and no runtime assertions
-O2 As -O1, plus code flow optimization (relooper)
Warning: Compiling with this takes a long time!
-O3 As -O2, plus dangerous optimizations that may
break things
-s OPTION=VALUE JavaScript code generation option
passed into the emscripten compiler
--typed-arrays <mode> 0: no typed arrays
1: parallel typed arrays
2: shared (C-like) typed arrays (default)
break the generated code! If that happens, try
-O2 and then adding dangerous optimizations one
by one.
-s OPTION=VALUE JavaScript code generation option passed
into the emscripten compiler
--typed-arrays <mode> 0: No typed arrays
1: Parallel typed arrays
2: Shared (C-like) typed arrays (default)
--llvm-opts <level> 0: No LLVM optimizations
1: Safe/portable LLVM optimizations
2: Full, unsafe/unportable LLVM optimizations;
this will almost certainly break the
generated code!
The target file, if specified (-o <target>), defines what will
be generated:
@ -248,6 +252,7 @@ elif use_compiler:
newargs = sys.argv[1:]
opt_level = 0
llvm_opt_level = 0
for i in range(len(newargs)):
if newargs[i].startswith('-O'):
@ -256,6 +261,8 @@ elif use_compiler:
assert 0 <= opt_level <= 3
except:
raise Exception('Invalid optimization level: ' + newargs[i])
if opt_level >= 1:
llvm_opt_level = 1
newargs[i] = ''
newargs = [ arg for arg in newargs if arg is not '' ]
@ -284,22 +291,6 @@ elif use_compiler:
final_suffix = target.split('.')[-1]
## Compile
# First, generate LLVM bitcode TODO: handle |emcc a.cpp b.cpp -c| which generate *two* bitcode files
newargs = newargs + ['-emit-llvm', '-c', '-o', target_basename + '.bc']
if DEBUG: print >> sys.stderr, "Running:", call, ' '.join(newargs)
Popen([call] + newargs).communicate()
# If we were just asked to generate bitcode, stop there
if final_suffix in ['o', 'bc']:
if final_suffix == 'o':
shutil.move(target_basename + '.bc', target_basename + '.o')
exit(0)
## Continue on to create JavaScript
# Apply optimization level settings
if opt_level >= 1:
shared.Settings.ASSERTIONS = 0
@ -315,6 +306,26 @@ elif use_compiler:
shared.Settings.DISABLE_EXCEPTION_CATCHING = 1
print >> sys.stderr, 'Warning: Applying some potentially unsafe optimizations! (Use -O2 if this fails.)'
## Compile
# First, generate LLVM bitcode TODO: handle |emcc a.cpp b.cpp -c| which generate *two* bitcode files
newargs = newargs + ['-emit-llvm', '-c', '-o', target_basename + '.bc']
if DEBUG: print >> sys.stderr, "Running:", call, ' '.join(newargs)
Popen([call] + newargs).communicate()
# Optimize, if asked to
if llvm_opt_level > 0:
shared.Building.llvm_opt(target_basename + '.bc', 2, safe=llvm_opt_level < 2)
# If we were just asked to generate bitcode, stop there
if final_suffix in ['o', 'bc']:
if final_suffix == 'o':
shutil.move(target_basename + '.bc', target_basename + '.o')
exit(0)
## Continue on to create JavaScript
# Apply -s settings in newargs here (after -Ox, so they can override it)
for change in settings_changes:

Просмотреть файл

@ -81,7 +81,8 @@ class RunnerCore(unittest.TestCase):
need_post = build_ll_hook(filename)
Building.llvm_as(filename)
shutil.move(filename + '.o.ll', filename + '.o.ll.pre') # for comparisons later
Building.llvm_opts(filename)
if Building.LLVM_OPTS:
Building.llvm_opts(filename)
Building.llvm_dis(filename)
if build_ll_hook and need_post:
build_ll_hook(filename)
@ -4958,8 +4959,7 @@ Options that are modified or new in %s include:
# emcc --llvm-opts=x .. ==> pick level of LLVM optimizations (default is 0, to be safe?)
# When doing unsafe opts, can we run -Ox on the source, not just at the very end?
# In fact we can run safe opts at that time too, now we are a gcc replacement. Removes the entire need for llvm opts only at the end.
# We can run safe opts at each emcc invocation, now we are a gcc replacement. Removes the entire need for llvm opts only at the end.
# linking - TODO. in particular, test normal project linking, static and dynamic: get_library should not need to be told what to link!
# emcc a.cpp b.cpp => one .js
# emcc a.cpp b.cpp -c => two .o files

Просмотреть файл

@ -196,6 +196,7 @@ class Settings:
class Settings2:
reset = Settings.reset
load_defaults = Settings.load_defaults
QUANTUM_SIZE = 4
Settings = Settings2
@classmethod
@ -203,6 +204,7 @@ class Settings:
''' Load the JS settings into Python '''
settings = open(path_from_root('src', 'settings.js')).read().replace('var ', 'Settings.').replace('//', '#')
exec(settings)
Settings.reset()
# Building
@ -296,7 +298,13 @@ class Building:
# Optional LLVM optimizations
@staticmethod
def llvm_opts(filename):
def llvm_opt(filename, level, safe=True):
output = Popen([LLVM_OPT, filename] + Building.pick_llvm_opts(level, safe) + ['-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)
@staticmethod
def llvm_opts(filename): # deprecated version, only for test runner. TODO: remove
if Building.LLVM_OPTS:
shutil.move(filename + '.o', filename + '.o.pre')
output = Popen([LLVM_OPT, filename + '.o.pre'] + Building.LLVM_OPT_OPTS + ['-o=' + filename + '.o'], stdout=PIPE).communicate()[0]
@ -371,8 +379,6 @@ class Building:
into i64s. In any case, the handpicked ones here should be safe and portable. They are also tuned for
things that look useful.
'''
if not Building.LLVM_OPTS: return # XXX this makes using this independently from the test runner very unpleasant
opts = []
if optimization_level > 0:
#opts.append('-disable-inlining') # we prefer to let closure compiler do our inlining