diff options
-rw-r--r-- | settings.py | 5 | ||||
-rw-r--r-- | src/intertyper.js | 2 | ||||
-rw-r--r-- | src/jsifier.js | 4 | ||||
-rwxr-xr-x | tests/runner.py | 48 | ||||
-rwxr-xr-x | tools/bindings_generator.py | 29 | ||||
-rw-r--r-- | tools/shared.py | 31 |
6 files changed, 88 insertions, 31 deletions
diff --git a/settings.py b/settings.py index d317d6b4..360c9216 100644 --- a/settings.py +++ b/settings.py @@ -1,15 +1,18 @@ # This file will be copied to ~/.emscripten if that file doesn't exist. Or, this is that copy. # IMPORTANT: Edit the *copy* with the right paths! +# Note: If you put paths relative to the home directory, do not forget os.path.expanduser EMSCRIPTEN_ROOT = os.path.expanduser('~/Dev/emscripten') # this helps projects using emscripten find it LLVM_ROOT = os.path.expanduser('~/Dev/llvm-3.0/cbuild/bin') # See below for notes on which JS engine(s) you need -NODE_JS = 'node' # Note: If you put a relative path here, do not forget os.path.expanduser +NODE_JS = 'node' SPIDERMONKEY_ENGINE = [os.path.expanduser('~/Dev/mozilla-central/js/src/js'), '-m', '-n'] V8_ENGINE = os.path.expanduser('~/Dev/v8/d8') +JAVA = 'java' + TEMP_DIR = '/tmp' # You will need to modify this on Windows diff --git a/src/intertyper.js b/src/intertyper.js index d9db10f9..6b91f527 100644 --- a/src/intertyper.js +++ b/src/intertyper.js @@ -74,7 +74,7 @@ function intertyper(data, sidePass, baseLineNums) { var global = /([@%\w\d\.\" $-]+) = .*/.exec(line); var globalIdent = toNiceIdent(global[1]); var testAlias = /[@%\w\d\.\" $-]+ = alias .*/.exec(line); - var testString = /^[^"]+c\"[^"]+"/.exec(line); + var testString = /[@%\w\d\.\" $-]+ = [\w ]+ \[\d+ x i8] c".*/.exec(line); Variables.globals[globalIdent] = { name: globalIdent, alias: !!testAlias, diff --git a/src/jsifier.js b/src/jsifier.js index b3c2af1d..1d18f292 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -765,6 +765,10 @@ function JSify(data, functionsOnly, givenFunctions) { } switch (impl) { case VAR_NATIVIZED: + if (isNumber(item.ident)) { + // Direct write to a memory address; this may be an intentional segfault, if not, it is a bug in the source + return 'throw "fault on write to ' + item.ident + '";'; + } return item.ident + '=' + value + ';'; // We have the actual value here break; case VAR_EMULATED: diff --git a/tests/runner.py b/tests/runner.py index cc3811a2..9c29dc96 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -2898,6 +2898,45 @@ def process(filename): extra_emscripten_args=['-H', 'libc/time.h']) #extra_emscripten_args=['-H', 'libc/fcntl.h,libc/sys/unistd.h,poll.h,libc/math.h,libc/langinfo.h,libc/time.h']) + def test_intentional_fault(self): + # Some programs intentionally segfault themselves, we should compile that into a throw + src = r''' + int main () { + *(volatile char *)0 = 0; + return 0; + } + ''' + self.do_run(src, 'fault on write to 0') + + def test_trickystring(self): + src = r''' + #include <stdio.h> + + typedef struct + { + int (*f)(void *); + void *d; + char s[16]; + } LMEXFunctionStruct; + + int f(void *user) + { + return 0; + } + + static LMEXFunctionStruct const a[] = + { + {f, (void *)(int)'a', "aa"} + }; + + int main() + { + printf("ok\n"); + return a[0].f(a[0].d); + } + ''' + self.do_run(src, 'ok\n') + def test_statics(self): # static initializers save i16 but load i8 for some reason if Settings.SAFE_HEAP: @@ -5496,6 +5535,7 @@ def process(filename): int value; public: Parent(int val); + Parent(Parent *p, Parent *q); // overload constructor int getVal() { return value; }; // inline should work just fine here, unlike Way 1 before void mulVal(int mul); }; @@ -5533,6 +5573,7 @@ def process(filename): #include "header.h" Parent::Parent(int val) : value(val) { printf("Parent:%d\\n", val); } + Parent::Parent(Parent *p, Parent *q) : value(p->value + q->value) { printf("Parent:%d\\n", value); } void Parent::mulVal(int mul) { value *= mul; } #include "bindingtest.cpp" @@ -8114,9 +8155,10 @@ elif 'sanity' in str(sys.argv): assert os.path.exists(EMCC_CACHE) assert os.path.exists(os.path.join(EMCC_CACHE, libname + '.bc')) if libname == 'libcxx': - assert os.stat(os.path.join(EMCC_CACHE, libname + '.bc')).st_size > 3500000, 'libc++ is big' - assert os.stat(basebc_name).st_size > 3500000, 'libc++ is indeed big' - assert os.stat(dcebc_name).st_size < 2000000, 'Dead code elimination must remove most of libc++' + print os.stat(os.path.join(EMCC_CACHE, libname + '.bc')).st_size, os.stat(basebc_name).st_size, os.stat(dcebc_name).st_size + assert os.stat(os.path.join(EMCC_CACHE, libname + '.bc')).st_size > 2000000, 'libc++ is big' + assert os.stat(basebc_name).st_size > 2000000, 'libc++ is indeed big' + assert os.stat(dcebc_name).st_size < 1500000, 'Dead code elimination must remove most of libc++' finally: if emcc_debug: os.environ['EMCC_DEBUG'] = emcc_debug diff --git a/tools/bindings_generator.py b/tools/bindings_generator.py index 3fbff13d..0c7c814f 100755 --- a/tools/bindings_generator.py +++ b/tools/bindings_generator.py @@ -671,25 +671,22 @@ def generate_class(generating_classname, classname, clazz): # TODO: deprecate ge has_string_convs = False - # We can assume that NULL is passed for null pointers, so object arguments can always - # have .ptr done on them - justargs_fixed = justargs(args)[:] - for i in range(len(args)): - arg = args[i] - clean = clean_type(arg['type']) - if clean in classes: - justargs_fixed[i] += '.ptr' - elif arg['type'].replace(' ', '').endswith('char*'): - justargs_fixed[i] = 'ensureString(' + justargs_fixed[i] + ')' - has_string_convs = True - calls = '' - if has_string_convs: - calls += 'var stack = Runtime.stackSave();\n'; - calls += 'try {\n' #print 'js loopin', params, '|', len(args)#, args for args in params: + # We can assume that NULL is passed for null pointers, so object arguments can always + # have .ptr done on them + justargs_fixed = justargs(args)[:] + for i in range(len(args)): + arg = args[i] + clean = clean_type(arg['type']) + if clean in classes: + justargs_fixed[i] += '.ptr' + elif arg['type'].replace(' ', '').endswith('char*'): + justargs_fixed[i] = 'ensureString(' + justargs_fixed[i] + ')' + has_string_convs = True + i = len(args) if args != params[0]: calls += ' else ' @@ -715,7 +712,7 @@ def generate_class(generating_classname, classname, clazz): # TODO: deprecate ge calls += '\n' if has_string_convs: - calls += '} finally { Runtime.stackRestore(stack) }\n'; + calls = 'var stack = Runtime.stackSave();\ntry {\n' + calls + '} finally { Runtime.stackRestore(stack) }\n'; print 'Maekin:', classname, generating_classname, mname, mname_suffixed if constructor: diff --git a/tools/shared.py b/tools/shared.py index 69343cc2..c8998b5a 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -81,9 +81,9 @@ def check_sanity(force=False): sys.exit(0) try: - subprocess.call(['java', '-version'], stdout=PIPE, stderr=PIPE) + subprocess.call([JAVA, '-version'], stdout=PIPE, stderr=PIPE) except: - print >> sys.stderr, 'WARNING: java does not seem to exist, required for closure compiler. -O2 and above will fail.' + print >> sys.stderr, 'WARNING: java does not seem to exist, required for closure compiler. -O2 and above will fail. You need to define JAVA in ~/.emscripten (see settings.py)' if not os.path.exists(CLOSURE_COMPILER): print >> sys.stderr, 'WARNING: Closure compiler (%s) does not exist, check the paths in %s. -O2 and above will fail' % (CLOSURE_COMPILER, EM_CONFIG) @@ -172,6 +172,12 @@ try: except: CLOSURE_COMPILER = path_from_root('third_party', 'closure-compiler', 'compiler.jar') +try: + JAVA +except: + print >> sys.stderr, 'JAVA not defined in ~/.emscripten, using "java"' + JAVA = 'java' + # Additional compiler options try: @@ -504,13 +510,18 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e if configure: # Useful in debugging sometimes to comment this out (and the lines below up to and including the |link| call) Building.configure(configure + configure_args, stdout=open(os.path.join(project_dir, 'configure_'), 'w'), stderr=open(os.path.join(project_dir, 'configure_err'), 'w'), env=env) - Building.make(make + make_args, stdout=open(os.path.join(project_dir, 'make_'), 'w'), - stderr=open(os.path.join(project_dir, 'make_err'), 'w'), env=env) - if cache is not None: - cache[cache_name] = [] - for f in generated_libs: - basename = os.path.basename(f) - cache[cache_name].append((basename, open(f, 'rb').read())) + for i in range(2): # workaround for some build systems that need to be run twice to succeed (e.g. poppler) + Building.make(make + make_args, stdout=open(os.path.join(project_dir, 'make_' + str(i)), 'w'), + stderr=open(os.path.join(project_dir, 'make_err' + str(i)), 'w'), env=env) + try: + if cache is not None: + cache[cache_name] = [] + for f in generated_libs: + basename = os.path.basename(f) + cache[cache_name].append((basename, open(f, 'rb').read())) + break + except: + if i > 0: raise Exception('could not build library ' + name) if old_dir: os.chdir(old_dir) return generated_libs @@ -830,7 +841,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e # Something like this (adjust memory as needed): # java -Xmx1024m -jar CLOSURE_COMPILER --compilation_level ADVANCED_OPTIMIZATIONS --variable_map_output_file src.cpp.o.js.vars --js src.cpp.o.js --js_output_file src.cpp.o.cc.js - args = ['java', + args = [JAVA, '-Xmx1024m', '-jar', CLOSURE_COMPILER, '--compilation_level', 'ADVANCED_OPTIMIZATIONS', |