add a naming to globals that can be linked and used across modules
This commit is contained in:
Родитель
cde6b80d99
Коммит
218696cdd2
46
emlink.py
46
emlink.py
|
@ -81,17 +81,19 @@ class AsmModule():
|
|||
self.global_inits_js = ''
|
||||
self.global_inits = []
|
||||
|
||||
# imports
|
||||
self.imports_js = self.js[self.start_asm:self.start_funcs]
|
||||
# imports (and global variables)
|
||||
first_var = self.js.find('var ', self.js.find('var ', self.start_asm)+4)
|
||||
self.pre_imports_js = self.js[self.start_asm:first_var]
|
||||
self.imports_js = self.js[first_var:self.start_funcs]
|
||||
self.imports = {}
|
||||
for imp in js_optimizer.import_sig.finditer(self.imports_js):
|
||||
key, value = imp.group(0).split('var ')[1][:-1].replace(' ', '').split('=')
|
||||
key, value = imp.group(0).split('var ')[1][:-1].split('=', 1)
|
||||
self.imports[key] = value
|
||||
#print >> sys.stderr, 'imports', self.imports
|
||||
|
||||
# funcs
|
||||
self.funcs_js = self.js[self.start_funcs:self.end_funcs]
|
||||
self.funcs = [m.group(2) for m in js_optimizer.func_sig.finditer(self.funcs_js)]
|
||||
self.funcs = set([m.group(2) for m in js_optimizer.func_sig.finditer(self.funcs_js)])
|
||||
#print 'funcs', self.funcs
|
||||
|
||||
# tables and exports
|
||||
|
@ -117,19 +119,14 @@ class AsmModule():
|
|||
main.pre_js = re.sub(shared.JS.memory_staticbump_pattern, 'STATICTOP = STATIC_BASE + %d;\n' % (main.staticbump + side.staticbump) + new_mem_init, main.pre_js, count=1)
|
||||
|
||||
# Find function name replacements TODO: do not rename duplicate names with duplicate contents, just merge them
|
||||
main_funcs = set(main.funcs)
|
||||
replacements = {}
|
||||
for i in range(len(self.funcs)):
|
||||
rep = func = self.funcs[i]
|
||||
while rep in main_funcs:
|
||||
for func in self.funcs:
|
||||
rep = func
|
||||
while rep in main.funcs:
|
||||
rep += '_'
|
||||
replacements[func] = rep
|
||||
#print >> sys.stderr, 'replacements:', replacements
|
||||
|
||||
# imports
|
||||
new_imports = [imp for imp in self.imports if imp not in main.imports and imp not in main_funcs]
|
||||
main.imports_js += '\n'.join(['var %s = %s;' % (imp, self.imports[imp]) for imp in new_imports]) + '\n'
|
||||
|
||||
# sendings: add invokes for new tables
|
||||
all_sendings = main.sendings
|
||||
added_sending = False
|
||||
|
@ -138,6 +135,27 @@ class AsmModule():
|
|||
sig = table[table.rfind('_')+1:]
|
||||
all_sendings['invoke_%s' % sig] = shared.JS.make_invoke(sig, named=False)
|
||||
added_sending = True
|
||||
|
||||
# imports
|
||||
all_imports = main.imports
|
||||
for key, value in self.imports.iteritems():
|
||||
if key in self.funcs or key in main.funcs: continue # external function in one module, implemented in the other
|
||||
value_concrete = '.' not in value # env.key means it is an import, an external value, and not a concrete one
|
||||
main_value = main.imports.get(key)
|
||||
main_value_concrete = main_value and '.' not in main_value
|
||||
if value_concrete and main_value_concrete: continue # standard global var
|
||||
if not main_value or value_concrete:
|
||||
if '+' in value:
|
||||
# relocate
|
||||
value = value.replace('(', '').replace(')', '').replace('| 0', '').replace('|0', '').replace(' ', '')
|
||||
left, right = value.split('+')
|
||||
assert left == 'H_BASE'
|
||||
value = str(main.staticbump + int(right))
|
||||
all_imports[key] = value
|
||||
if (value_concrete or main_value_concrete) and key in all_sendings:
|
||||
del all_sendings[key] # import of external value no longer needed
|
||||
main.imports_js = '\n'.join(['var %s = %s;' % (key, value) for key, value in all_imports.iteritems()]) + '\n'
|
||||
|
||||
if added_sending:
|
||||
sendings_js = ', '.join(['%s: %s' % (key, value) for key, value in all_sendings.iteritems()])
|
||||
sendings_start = main.post_js.find('}, { ')+5
|
||||
|
@ -149,8 +167,7 @@ class AsmModule():
|
|||
if value.startswith('+') or value.endswith('|0'): # ignore functions
|
||||
if key not in all_sendings:
|
||||
print >> sys.stderr, 'external variable %s is still not defined after linking' % key
|
||||
for key, value in self.imports.iteritems(): check_import(key, value)
|
||||
for key, value in main.imports.iteritems(): check_import(key, value)
|
||||
for key, value in all_imports.iteritems(): check_import(key, value)
|
||||
|
||||
# tables
|
||||
f_bases = {}
|
||||
|
@ -252,6 +269,7 @@ class AsmModule():
|
|||
def write(self, out):
|
||||
f = open(out, 'w')
|
||||
f.write(self.pre_js)
|
||||
f.write(self.pre_imports_js)
|
||||
f.write(self.imports_js)
|
||||
f.write(self.funcs_js)
|
||||
f.write(self.extra_funcs_js)
|
||||
|
|
|
@ -479,6 +479,14 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
|
|||
''.join([' var ' + g + '=env.' + math_fix(g) + ';\n' for g in basic_funcs + global_funcs])
|
||||
asm_global_vars = ''.join([' var ' + g + '=env.' + g + '|0;\n' for g in basic_vars + global_vars]) + \
|
||||
''.join([' var ' + g + '=+env.' + g + ';\n' for g in basic_float_vars])
|
||||
# In linkable modules, we need to add some explicit globals for global variables that can be linked and used across modules
|
||||
if settings.get('MAIN_MODULE') or settings.get('SIDE_MODULE'):
|
||||
for key, value in forwarded_json['Variables']['globals'].iteritems():
|
||||
if value.get('linkable'):
|
||||
init = str(forwarded_json['Variables']['indexedGlobals'][key])
|
||||
if settings.get('SIDE_MODULE'): init = '(H_BASE+' + init + ')|0'
|
||||
asm_global_vars += ' var %s=%s;\n' % (key, init)
|
||||
|
||||
# sent data
|
||||
the_global = '{ ' + ', '.join(['"' + math_fix(s) + '": ' + s for s in fundamentals]) + ' }'
|
||||
sending = '{ ' + ', '.join(['"' + math_fix(s) + '": ' + s for s in basic_funcs + global_funcs + basic_vars + basic_float_vars + global_vars]) + ' }'
|
||||
|
|
|
@ -286,6 +286,11 @@ function JSify(data, functionsOnly, givenFunctions) {
|
|||
allocator = 'ALLOC_NONE';
|
||||
}
|
||||
|
||||
if (ASM_JS && (MAIN_MODULE || SIDE_MODULE) && !item.private_ && !NAMED_GLOBALS && isIndexableGlobal(item.ident)) {
|
||||
// We need this to be named (and it normally would not be), so that it can be linked to and used from other modules
|
||||
Variables.globals[item.ident].linkable = 1;
|
||||
}
|
||||
|
||||
if (isBSS(item)) {
|
||||
var length = calcAllocatedSize(item.type);
|
||||
length = Runtime.alignMemory(length);
|
||||
|
|
|
@ -19,8 +19,8 @@ WINDOWS = sys.platform.startswith('win')
|
|||
|
||||
DEBUG = os.environ.get('EMCC_DEBUG')
|
||||
|
||||
import_sig = re.compile('var ([_\w$]+) *=[^,;]+;')
|
||||
func_sig = re.compile('( *)function ([_\w$]+)\(')
|
||||
import_sig = re.compile('var ([_\w$]+) *=[^;]+;')
|
||||
|
||||
class Minifier:
|
||||
'''
|
||||
|
|
Загрузка…
Ссылка в новой задаче