diff options
-rw-r--r-- | src/jsifier.js | 15 | ||||
-rw-r--r-- | src/settings.js | 11 | ||||
-rw-r--r-- | src/shell_sharedlib.js | 2 | ||||
-rw-r--r-- | tests/runner.py | 58 | ||||
-rw-r--r-- | tools/shared.py | 2 |
5 files changed, 86 insertions, 2 deletions
diff --git a/src/jsifier.js b/src/jsifier.js index b941032a..feebbe5a 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -321,6 +321,10 @@ function JSify(data, functionsOnly, givenFunctions) { if (item.ident in EXPORTED_GLOBALS) { js += '\nModule["' + item.ident + '"] = ' + item.ident + ';'; } + // TODO: Support exporting BUILD_AS_SHARED_LIB == 2 globals. The problem now is that they override the main file's globals. + //if (BUILD_AS_SHARED_LIB == 2) { + // js += 'if (globalScope) globalScope["' + item.ident + '"] = ' + item.ident + ';'; // XXX: assert not overriding + //} return ret.concat({ intertype: 'GlobalVariable', JS: js, @@ -603,6 +607,10 @@ function JSify(data, functionsOnly, givenFunctions) { func.JS += func.ident + '["X"]=1;'; } + if (BUILD_AS_SHARED_LIB == 2) { + func.JS += 'if (globalScope) { assert(!globalScope["' + func.ident + '"]); globalScope["' + func.ident + '"] = ' + func.ident + ' }'; + } + return func; } }); @@ -1116,7 +1124,14 @@ function JSify(data, functionsOnly, givenFunctions) { data.unparsedGlobalss = null; print(Functions.generateIndexing()); // done last, as it may rely on aliases set in postsets + + // Load runtime-linked libraries + RUNTIME_LINKED_LIBS.forEach(function(lib) { + print('eval(read("' + lib + '"))(FUNCTION_TABLE.length, this);'); + }); + print(postParts[1]); + print(shellParts[1]); // Print out some useful metadata (for additional optimizations later, like the eliminator) print('// EMSCRIPTEN_GENERATED_FUNCTIONS: ' + JSON.stringify(Functions.allIdents) + '\n'); diff --git a/src/settings.js b/src/settings.js index 66762298..9dba6a24 100644 --- a/src/settings.js +++ b/src/settings.js @@ -172,6 +172,17 @@ var SHOW_LABELS = 0; // Show labels in the generated code var BUILD_AS_SHARED_LIB = 0; // Whether to build the code as a shared library, which // must be loaded dynamically using dlopen(). + // 0 here means this is not a shared lib: It is a main file. + // 1 means this is a normal shared lib. + // 2 means this is a shared lib that will be linked at runtime, + // which means it will insert its functions into + // the global namespace. See STATIC_LIBS_TO_LOAD. Note + // that only functions are exported, not globals, since + // in a naive implementation they can easily override main's + // symbols (for example, the global strings, _str1 etc.). +var RUNTIME_LINKED_LIBS = []; // If this is a main file (BUILD_AS_SHARED_LIB == 0), then + // we will link these at runtime. They must have been built with + // BUILD_AS_SHARED_LIB == 2. var RUNTIME_TYPE_INFO = 0; // Whether to expose type info to the script at run time. This // increases the size of the generated script, but allows you diff --git a/src/shell_sharedlib.js b/src/shell_sharedlib.js index 60a78323..1d34c73e 100644 --- a/src/shell_sharedlib.js +++ b/src/shell_sharedlib.js @@ -1,5 +1,5 @@ // Capture the output of this into a variable, if you want -(function(FUNCTION_TABLE_OFFSET) { +(function(FUNCTION_TABLE_OFFSET, globalScope) { var Module = {}; var args = []; Module.arguments = []; diff --git a/tests/runner.py b/tests/runner.py index 7393f4bf..8610fd0b 100644 --- a/tests/runner.py +++ b/tests/runner.py @@ -2168,6 +2168,63 @@ if 'benchmark' not in str(sys.argv): # Bloated memory; same layout as C/C++ self.do_run(src, '*16,0,4,8,8,12|20,0,4,4,8,12,12,16|24,0,20,0,4,4,8,12,12,16*\n*0,0,0,1,2,64,68,69,72*\n*2*') + def test_runtimelink(self): + header = r''' + struct point + { + int x, y; + }; + + ''' + open(os.path.join(self.get_dir(), 'header.h'), 'w').write(header) + + supp = r''' + #include <stdio.h> + #include "header.h" + + extern void mainFunc(int x); + extern int mainInt; + + void suppFunc(struct point &p) { + printf("supp: %d,%d\n", p.x, p.y); + mainFunc(p.x+p.y); + printf("supp see: %d\n", mainInt); + } + + //int suppInt = 76; // TODO: Support this. Right now, _str1 will override the main _str1 + ''' + supp_name = os.path.join(self.get_dir(), 'supp.c') + open(supp_name, 'w').write(supp) + + main = r''' + #include <stdio.h> + #include "header.h" + + extern void suppFunc(struct point &p); + extern int suppInt; + + void mainFunc(int x) { + printf("main: %d\n", x); + } + + int mainInt = 543; + + int main( int argc, const char *argv[] ) { + struct point p = { 54, 2 }; + suppFunc(p); + return 0; + } + ''' + + Settings.BUILD_AS_SHARED_LIB = 2 + dirname = self.get_dir() + self.build(supp, dirname, supp_name) + shutil.move(supp_name + '.o.js', os.path.join(dirname, 'liblib.so')) + Settings.BUILD_AS_SHARED_LIB = 0 + + Settings.RUNTIME_LINKED_LIBS = ['liblib.so']; + self.do_run(main, 'supp: 54,2\nmain: 56\nsupp see: 543\n') + def test_dlfcn_basic(self): lib_src = ''' #include <cstdio> @@ -4647,6 +4704,7 @@ class %s(T): Settings.PROFILE = 0 Settings.INCLUDE_FULL_LIBRARY = 0 Settings.BUILD_AS_SHARED_LIB = 0 + Settings.LIBS_TO_LOAD = [] Settings.CATCH_EXIT_CODE = 0 Settings.TOTAL_MEMORY = Settings.FAST_MEMORY = None Settings.EMULATE_UNALIGNED_ACCESSES = Settings.USE_TYPED_ARRAYS == 2 and Building.LLVM_OPTS == 2 diff --git a/tools/shared.py b/tools/shared.py index de52f95f..632cf633 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -291,7 +291,7 @@ class Building: # 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', 'INCLUDE_FULL_LIBRARY', 'RUNTIME_TYPE_INFO', 'DISABLE_EXCEPTION_CATCHING', 'TOTAL_MEMORY', 'FAST_MEMORY', 'EXCEPTION_DEBUG', 'PROFILE', 'I64_MODE', 'EMULATE_UNALIGNED_ACCESSES', 'CATCH_EXIT_CODE']: + 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']: try: value = eval('Settings.' + setting) if value is not None: |