aboutsummaryrefslogtreecommitdiff
path: root/tools/bindings_generator.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/bindings_generator.py')
-rwxr-xr-xtools/bindings_generator.py46
1 files changed, 9 insertions, 37 deletions
diff --git a/tools/bindings_generator.py b/tools/bindings_generator.py
index 8146215c..d999bdd1 100755
--- a/tools/bindings_generator.py
+++ b/tools/bindings_generator.py
@@ -29,13 +29,11 @@ We generate the following:
change all arguments of type float& to float by
"type_processor": "lambda t: t if t != 'float&' else 'float'"
- export: If true, will export all bindings in the .js file. This allows
+ export: If false, will not export all bindings in the .js file. The
+ default is to export all bindings, which allows
you to run something like closure compiler advanced opts on
the library+bindings, and the bindings will remain accessible.
- prevent_dfe: If true, will use all the generated C functions, to prevent
- dead function elimination from removing them.
-
For example, JSON can be { "ignored": "class1,class2::func" }.
The C bindings file is basically a tiny C wrapper around the C++ code.
@@ -66,8 +64,7 @@ basename = sys.argv[1]
ignored = []
type_processor = lambda t: t
-export = 0
-prevent_dfe = 0
+export = 1
if '--' in sys.argv:
index = sys.argv.index('--')
@@ -80,8 +77,6 @@ if '--' in sys.argv:
type_processor = eval(json['type_processor'])
if json.get('export'):
export = json['export']
- if json.get('prevent_dfe'):
- prevent_dfe = eval(json['prevent_dfe'])
print 'zz ignoring', ignored
@@ -363,7 +358,6 @@ for classname, clazz in parsed.classes.iteritems():
# TODO: Bind virtual functions using dynamic binding in the C binding code
funcs = {} # name -> # of copies in the original, and originalname in a copy
-c_funcs = []
gen_c = open(basename + '.cpp', 'w')
gen_js = open(basename + '.js', 'w')
@@ -543,6 +537,7 @@ def generate_class(generating_classname, classname, clazz): # TODO: deprecate ge
#print 'POST arggggggg', classname, 'x', mname, 'x', args[i]['name'], 'x', args[i]['type']
ret = ((classname + ' *') if constructor else method['returns_text'])#.replace('virtual ', '')
+ has_return = ret.replace(' ', '') != 'void'
callprefix = 'new ' if constructor else ('self->' if not static else (classname + '::'))
'' # mname used in C
@@ -558,6 +553,8 @@ def generate_class(generating_classname, classname, clazz): # TODO: deprecate ge
return map(lambda i: 'arg' + str(i), range(len(args)))
def justtypes(args): # note: this ignores 'self'
return map(lambda i: args[i]['type'], range(len(args)))
+ def dummyargs(args):
+ return ([] if not need_self else ['(%s*)argv[argc]' % classname]) + map(lambda i: '(%s)argv[argc]' % args[i]['type'], range(len(args)))
fullname = ('emscripten_bind_' + generating_classname + '__' + mname).replace('::', '__')
generating_classname_suffixed = generating_classname
@@ -582,8 +579,9 @@ def generate_class(generating_classname, classname, clazz): # TODO: deprecate ge
i = len(args)
# If we are returning a *copy* of an object, we return instead to a ref of a static held here. This seems the best compromise
staticize = not constructor and ret.replace(' ', '') != 'void' and method['returns'] in classes and (not method['returns_reference'] and not method['returns_pointer'])
+ # Make sure to mark our bindings wrappers in a way that they will not be inlined, eliminated as unneeded, or optimized into other signatures
gen_c.write('''
-%s %s_p%d(%s) {''' % (ret if not staticize else (ret + '&'), fullname, i,
+%s __attribute__((externally_visible, used, noinline)) %s_p%d(%s) {''' % (ret if not staticize else (ret + '&'), fullname, i,
', '.join(typedargs(args)[:i + (0 if not need_self else 1)])))
if not staticize:
gen_c.write('\n')
@@ -596,7 +594,7 @@ def generate_class(generating_classname, classname, clazz): # TODO: deprecate ge
elif method.get('operator'):
gen_c.write(method['operator'])
else: # normal method
- gen_c.write(''' %s%s%s(%s);''' % ('return ' if ret.replace(' ', '') != 'void' else '',
+ gen_c.write(''' %s%s%s(%s);''' % ('return ' if has_return else '',
callprefix, actualmname, ', '.join(justargs(args)[:i])))
gen_c.write('\n')
gen_c.write('}')
@@ -610,7 +608,6 @@ def generate_class(generating_classname, classname, clazz): # TODO: deprecate ge
callprefix, actualmname,
', '.join(justargs(args)[:i])))
gen_c.write('\n}')
- c_funcs.append(fullname + '_p' + str(i))
# JS
@@ -765,31 +762,6 @@ gen_c.write('''
}
''')
-if prevent_dfe:
- gen_c.write('''
-
- #include <stdio.h>
-
- struct EmscriptenEnsurer
- {
- EmscriptenEnsurer() {
- // Actually use the binding functions, so DFE will not eliminate them
- // FIXME: A negative side effect of this is that they take up space in FUNCTION_TABLE
- int sum = 0;
- void *seen = (void*)%s;
- ''' % c_funcs[0])
-
- for func in c_funcs[1:]:
- gen_c.write(''' sum += (void*)%s == seen;
- ''' % func)
-
- gen_c.write(''' printf("(%d)\\n", sum);
- }
- };
-
- EmscriptenEnsurer emscriptenEnsurer;
- ''')
-
gen_c.close()
gen_js.close()