aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/modules.js2
-rw-r--r--src/parseTools.js6
-rw-r--r--tests/cases/ptrtoint_blockaddr.ll20
-rw-r--r--tests/runner.py14
-rwxr-xr-xtools/bindings_generator.py314
-rw-r--r--tools/shared.py9
6 files changed, 242 insertions, 123 deletions
diff --git a/src/modules.js b/src/modules.js
index e2509965..f613c20b 100644
--- a/src/modules.js
+++ b/src/modules.js
@@ -8,7 +8,7 @@ var LLVM = {
'weak_odr', 'externally_visible', 'dllimport', 'dllexport', 'unnamed_addr'),
VISIBILITIES: set('default', 'hidden', 'protected'),
PARAM_ATTR: set('noalias', 'signext', 'zeroext', 'inreg', 'sret', 'nocapture', 'nest'),
- CALLING_CONVENTIONS: set('ccc', 'fastcc', 'coldcc', 'cc10')
+ CALLING_CONVENTIONS: set('ccc', 'fastcc', 'coldcc', 'cc10', 'x86_fastcallcc')
};
LLVM.GLOBAL_MODIFIERS = set(keys(LLVM.LINKAGES).concat(['constant', 'global', 'hidden']));
diff --git a/src/parseTools.js b/src/parseTools.js
index 6eb95593..94989f9d 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -309,6 +309,8 @@ function parseParamTokens(params) {
}
} else if (segment[1].text in PARSABLE_LLVM_FUNCTIONS) {
ret.push(parseLLVMFunctionCall(segment));
+ } else if (segment[1].text === 'blockaddress') {
+ ret.push(parseBlockAddress(segment));
} else {
if (segment[2] && segment[2].text == 'to') { // part of bitcast params
segment = segment.slice(0, 2);
@@ -334,6 +336,8 @@ function parseParamTokens(params) {
function finalizeParam(param) {
if (param.intertype in PARSABLE_LLVM_FUNCTIONS) {
return finalizeLLVMFunctionCall(param);
+ } else if (param.intertype === 'blockaddress') {
+ return finalizeBlockAddress(param);
} else if (param.intertype === 'jsvalue') {
return param.ident;
} else {
@@ -426,7 +430,7 @@ function parseLLVMFunctionCall(segment) {
params: parseParamTokens(segment[2].item.tokens)
};
Types.needAnalysis[ret.type] = 0;
- ret.ident = toNiceIdent(ret.params[0].ident);
+ ret.ident = toNiceIdent(ret.params[0].ident || 'NOIDENT');
return ret;
}
diff --git a/tests/cases/ptrtoint_blockaddr.ll b/tests/cases/ptrtoint_blockaddr.ll
new file mode 100644
index 00000000..11e2f7bc
--- /dev/null
+++ b/tests/cases/ptrtoint_blockaddr.ll
@@ -0,0 +1,20 @@
+@.str = private constant [15 x i8] c"hello, world!\0A\00", align 1 ; [#uses=1]
+
+define linkonce_odr i32* @main() align 2 {
+ %199 = trunc i8 1 to i1 ; [#uses=1]
+ br i1 %199, label %555, label %569
+
+; <label>:555 ; preds = %353
+ br label %569
+ ; No predecessors!
+ br label %569
+
+; <label>:569 ; preds = %555
+ %333 = call i32 @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0)) ; [#uses=0]
+ ; this should compile ok
+ store i32 ptrtoint (i8* blockaddress(@main, %569) to i32), i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0), align 8
+ ret i32 0
+}
+
+declare i32 @printf(i8*)
+
diff --git a/tests/runner.py b/tests/runner.py
index ec47416f..e866649d 100644
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -3746,8 +3746,11 @@ else:
USE_CLOSURE_COMPILER = 1
if USE_CLOSURE_COMPILER:
- index = SPIDERMONKEY_ENGINE.index("options('strict')")
- SPIDERMONKEY_ENGINE = SPIDERMONKEY_ENGINE[:index-1] + SPIDERMONKEY_ENGINE[index+1:] # closure generates non-strict
+ try:
+ index = SPIDERMONKEY_ENGINE.index("options('strict')")
+ SPIDERMONKEY_ENGINE = SPIDERMONKEY_ENGINE[:index-1] + SPIDERMONKEY_ENGINE[index+1:] # closure generates non-strict
+ except:
+ pass
COMPILER = CLANG
JS_ENGINE = SPIDERMONKEY_ENGINE
@@ -3758,12 +3761,13 @@ else:
QUANTUM_SIZE = 1
RELOOP = OPTIMIZE = 1
USE_TYPED_ARRAYS = 0
- ASSERTIONS = SAFE_HEAP = CHECK_OVERFLOWS = CORRECT_OVERFLOWS = CHECK_SIGNS = INIT_STACK = AUTO_OPTIMIZE = RUNTIME_TYPE_INFO = DISABLE_EXCEPTIONS = 0
+ ASSERTIONS = SAFE_HEAP = CHECK_OVERFLOWS = CORRECT_OVERFLOWS = CHECK_SIGNS = INIT_STACK = AUTO_OPTIMIZE = RUNTIME_TYPE_INFO = 0
INVOKE_RUN = 1
CORRECT_SIGNS = 0
CORRECT_ROUNDINGS = 0
CORRECT_OVERFLOWS_LINES = CORRECT_SIGNS_LINES = CORRECT_ROUNDINGS_LINES = SAFE_HEAP_LINES = []
LLVM_OPTS = 1
+ DISABLE_EXCEPTIONS = 1
TEST_REPS = 4
TOTAL_TESTS = 6
@@ -3804,8 +3808,8 @@ else:
os.remove(filename + '.cc.js')
except:
pass
- # Something like this:
- # java -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
+ # 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
cc_output = Popen(['java', '-jar', CLOSURE_COMPILER,
'--compilation_level', 'ADVANCED_OPTIMIZATIONS',
diff --git a/tools/bindings_generator.py b/tools/bindings_generator.py
index 076c1106..deba8930 100755
--- a/tools/bindings_generator.py
+++ b/tools/bindings_generator.py
@@ -131,13 +131,51 @@ for classname, clazz in classes.iteritems():
default_param = i+1
break
- method['num_args'] = set(range(default_param-1, len(args)+1))
- print 'zz ', classname, 'has num_args of', method['num_args']
+ method['parameters'] = [args[:i] for i in range(default_param-1, len(args)+1)]
+ print 'zz ', classname, 'has parameters in range', range(default_param-1, len(args)+1)
method['returns_text'] = method['returns']
if method['static']:
method['returns_text'] = method['returns_text'].replace('static', '')
+ # Implement operators
+ if '__operator__' in method['name']:
+ if 'assignment' in method['name']:
+ method['name'] = 'op_set'
+ method['operator'] = ' return *self = arg0;'
+ elif 'add' in method['name']:
+ method['name'] = 'op_add'
+ method['operator'] = ' return *self += arg0;'
+ elif 'sub' in method['name']:
+ print 'zz subsubsub ', classname, method['name'], method['parameters'][0]
+ method['name'] = 'op_sub'
+ if len(method['parameters'][0]) == 0:
+ method['operator'] = ' return -*self; // %d' % len(method['parameters'][0])
+ else:
+ method['operator'] = ' return *self -= arg0; // %d : %s' % (len(method['parameters'][0]), method['parameters'][0][0]['name'])
+ elif 'imul' in method['name']:
+ method['name'] = 'op_mul'
+ method['operator'] = ' return *self *= arg0;'
+ elif 'mul' in method['name']:
+ method['name'] = 'op_mul'
+ method['operator'] = ' static %s ret = *self * arg0; return ret;' % method['returns']
+ elif 'div' in method['name']:
+ method['name'] = 'op_div'
+ method['operator'] = ' return *self /= arg0;'
+ elif 'getitem' in method['name']:
+ method['name'] = 'op_get'
+ method['operator'] = ' return (*self)[arg0];'
+ elif 'delete' in method['name']:
+ method['ignore'] = True
+ elif 'new' in method['name']:
+ method['ignore'] = True
+ elif 'eq' in method['name']:
+ method['name'] = 'op_comp'
+ method['operator'] = ' return arg0 == arg1;' if len(method['parameters'][0]) == 2 else ' return *self == arg0;'
+ else:
+ print 'zz unknown operator:', method['name']
+ 1/0.
+
# Fill in some missing stuff
if method.get('returns_const'): method['returns_text'] = 'const ' + method['returns_text']
if method.get('returns_pointer'):
@@ -146,7 +184,7 @@ for classname, clazz in classes.iteritems():
if method.get('returns_reference'): method['returns_text'] += '&'
method['returns_text'] = type_processor(method['returns_text'])
- print 'zz %s::%s gets %s and returns %s' % (classname, method['name'], str([arg['type'] for arg in method['parameters']]), method['returns_text'])
+ #print 'zz %s::%s gets %s and returns %s' % (classname, method['name'], str([arg['type'] for arg in method['parameters']]), method['returns_text'])
# Add getters/setters for public members
for prop in clazz['properties']['public']:
@@ -170,8 +208,7 @@ for classname, clazz in classes.iteritems():
'returns_reference': reference,
'returns_pointer': '*' in type_,
'pure_virtual': False,
- 'num_args': set([0]),
- 'parameters': [],
+ 'parameters': [[]],
})
clazz['methods'].append({
'setter': True,
@@ -184,13 +221,30 @@ for classname, clazz in classes.iteritems():
'returns_reference': False,
'returns_pointer': False,
'pure_virtual': False,
- 'num_args': set([1]),
- 'parameters': [{
+ 'parameters': [[{
'type': type_ + ('&' if reference else ''),
'name': 'value',
- }],
+ }]],
+ })
+
+ # Add destroyer
+ if not clazz.get('abstract'):
+ clazz['methods'].append({
+ 'destroyer': True,
+ 'name': '__destroy__',
+ 'constructor': False,
+ 'destructor': False,
+ 'static': False,
+ 'returns': 'void',
+ 'returns_text': 'void',
+ 'returns_reference': False,
+ 'returns_pointer': False,
+ 'pure_virtual': False,
+ 'parameters': [[]],
})
+ clazz['methods'] = filter(lambda method: not method.get('ignore'), clazz['methods'])
+
# Explore all functions we need to generate, including parent classes, handling of overloading, etc.
def clean_type(t):
@@ -203,6 +257,16 @@ def fix_template_value(t): # Not sure why this is needed, might be a bug in CppH
return 'unsigned int'
return t
+def copy_args(args):
+ ret = []
+ for arg in args:
+ copiedarg = {
+ 'type': arg['type'],
+ 'name': arg['name'],
+ }
+ ret.append(copiedarg)
+ return ret
+
for classname, clazz in parsed.classes.iteritems():
clazz['final_methods'] = {}
@@ -215,45 +279,47 @@ for classname, clazz in parsed.classes.iteritems():
if clazz != subclass: continue # Subclasses cannot directly use their parent's constructors
if method['destructor']: continue # Nothing to do there
+ if method.get('operator') and subclass is not clazz: continue # Do not use parent class operators. Cast to that class if you need those operators (castObject)
+
if method['name'] not in clazz['final_methods']:
copied = clazz['final_methods'][method['name']] = {}
for key in ['name', 'constructor', 'static', 'returns', 'returns_text', 'returns_reference', 'returns_pointer', 'destructor', 'pure_virtual',
- 'getter', 'setter']:
+ 'getter', 'setter', 'destroyer', 'operator']:
copied[key] = method.get(key)
- copied['num_args'] = method['num_args'].copy()
copied['origin'] = subclass
copied['parameters'] = [];
- # Copy the arguments, since templating may cause them to be altered
- for arg in method['parameters'][:]:
- copiedarg = {
- 'type': arg['type'],
- 'name': arg['name'],
- }
- copied['parameters'].append(copiedarg)
+ for args in method['parameters']:
+ # Copy the arguments, since templating may cause them to be altered
+ copied['parameters'].append(copy_args(args))
if template_name:
# Set template values
copied['returns'] = copied['returns'].replace(template_name, template_value)
copied['returns_text'] = copied['returns_text'].replace(template_name, template_value)
- for arg in copied['parameters']:
- arg['type'] = arg['type'].replace(template_name, template_value)
-
+ for args in copied['parameters']:
+ for arg in args:
+ arg['type'] = arg['type'].replace(template_name, template_value)
else:
- # Merge the new function in the best way we can. Shared arguments must match!
+ # Merge the new function in the best way we can. Two signatures (args) must differ in their number
+
+ if method.get('operator'): continue # do not merge operators
curr = clazz['final_methods'][method['name']]
if curr['origin'] is not subclass: continue # child class functions mask/hide parent functions of the same name in C++
- if any([curr['parameters'][i]['type'] != method['parameters'][i]['type'] for i in range(min(len(curr['parameters']), len(method['parameters'])))]):
+ problem = False
+ for curr_args in curr['parameters']:
+ for method_args in method['parameters']:
+ if len(curr_args) == len(method_args):
+ problem = True
+ if problem:
print 'Warning: Cannot mix in overloaded functions', method['name'], 'in class', classname, ', skipping'
continue
# TODO: Other compatibility checks, if any?
- if len(method['parameters']) > len(curr['parameters']):
- curr['parameters'] = method['parameters']
+ curr['parameters'] += map(copy_args, method['parameters'])
- curr['num_args'] = curr['num_args'].union(method['num_args'])
- print 'zz ', classname, 'has an updated num_args of ', curr['num_args']
+ print 'zz ', classname, 'has updated parameters of ', curr['parameters']
# Recurse
if subclass.get('inherits'):
@@ -276,8 +342,7 @@ for classname, clazz in parsed.classes.iteritems():
explore(clazz)
for method in clazz['final_methods'].itervalues():
- method['num_args'] = list(method['num_args'])
- method['num_args'].sort()
+ method['parameters'].sort(key=len)
# Second pass - generate bindings
# TODO: Bind virtual functions using dynamic binding in the C binding code
@@ -293,20 +358,45 @@ gen_c.write('extern "C" {\n')
# Use this when calling a binding function when you want to pass a null pointer.
# Having this object saves us needing to do checks for the object being null each time in the bindings code.
gen_js.write('''
-function wrapPointer(ptr) { return { ptr: ptr } };
+// Bindings utilities
+var Object__cache = {};
+function wrapPointer(ptr, class_) {
+ var cache = class_ ? class_.prototype.__cache__ : Object__cache;
+ var ret = cache[ptr];
+ if (ret) return ret;
+ class_ = class_ || Object;
+ ret = Object.create(class_.prototype);
+ ret.ptr = ptr;
+ return cache[ptr] = ret;
+}
this['wrapPointer'] = wrapPointer;
+
+function castObject(obj, class_) {
+ return wrapPointer(obj.ptr, class_);
+}
+this['castObject'] = castObject;
+
this['NULL'] = wrapPointer(0);
+
+function destroy(obj) {
+ if (!obj['__destroy__']) throw 'Error: Cannot destroy object. (Did you create it yourself?)';
+ obj['__destroy__']();
+}
+this['destroy'] = destroy;
+
+function compare(obj1, obj2) {
+ return obj1.ptr === obj2.ptr;
+}
+this['compare'] = compare;
+
+function getPointer(obj) {
+ return obj.ptr;
+}
+this['getPointer'] = getPointer;
''')
def generate_wrapping_code(classname):
- return '''var %(classname)s__cache__ = {};
-function %(classname)s__wrap__(ptr) {
- var ret = %(classname)s__cache__[ptr];
- if (ret) return ret;
- var ret = Object.create(%(classname)s.prototype);
- ret.ptr = ptr;
- return %(classname)s__cache__[ptr] = ret;
-}
+ return '''%(classname)s.prototype.__cache__ = {};
''' % { 'classname': classname }
# %(classname)s.prototype['fields'] = Runtime.generateStructInfo(null, '%(classname)s'); - consider adding this
@@ -316,72 +406,67 @@ def generate_class(generating_classname, classname, clazz): # TODO: deprecate ge
inherited = generating_classname_head != classname_head
- if clazz['abstract']:
+ abstract = clazz['abstract']
+ if abstract:
# For abstract base classes, add a function definition on top. There is no constructor
gen_js.write('\nfunction ' + generating_classname_head + ('(){ throw "%s is abstract!" }\n' % generating_classname_head) + generate_wrapping_code(generating_classname_head))
if export:
gen_js.write('''this['%s'] = %s;
''' % (generating_classname_head, generating_classname_head))
-
for method in clazz['final_methods'].itervalues():
mname = method['name']
if classname_head + '::' + mname in ignored:
print 'zz ignoring', mname
continue
- args = method['parameters']
+ params = method['parameters']
constructor = method['constructor']
destructor = method['destructor']
static = method['static']
- print 'zz generating %s::%s. gets %s and returns %s' % (generating_classname, method['name'], str([arg['type'] for arg in method['parameters']]), method['returns_text'])
+ #print 'zz generating %s::%s. gets %s and returns %s' % (generating_classname, method['name'], str([arg['type'] for arg in method['parameters']]), method['returns_text'])
if destructor: continue
if constructor and inherited: continue
if constructor and clazz['abstract']: continue # do not generate constructors for abstract base classes
- skip = False
- for i in range(len(args)):
- #print 'zz arggggggg', classname, 'x', mname, 'x', args[i]['name'], 'x', args[i]['type'], 'x', dir(args[i]), 'y', args[i].get('default'), 'z', args[i].get('defaltValue'), args[i].keys()
-
- if args[i]['name'].replace(' ', '') == '':
- args[i]['name'] = 'arg' + str(i+1)
- elif args[i]['name'] == '&':
- args[i]['name'] = 'arg' + str(i+1)
- args[i]['type'] += '&'
-
- if '>' in args[i]['name']:
- print 'WARNING: odd ">" in %s, skipping' % classname
- skip = True
- break
- #print 'c1', parents.keys()
- if args[i]['type'][-1] == '&':
- sname = args[i]['type'][:-1]
- if sname[-1] == ' ': sname = sname[:-1]
- if sname in parents:
- args[i]['type'] = parents[sname] + '::' + sname + '&'
- elif sname.replace('const ', '') in parents:
- sname = sname.replace('const ', '')
- args[i]['type'] = 'const ' + parents[sname] + '::' + sname + '&'
- #print 'POST arggggggg', classname, 'x', mname, 'x', args[i]['name'], 'x', args[i]['type']
- if skip:
- continue
+ for args in params:
+ for i in range(len(args)):
+ #print 'zz arggggggg', classname, 'x', mname, 'x', args[i]['name'], 'x', args[i]['type'], 'x', dir(args[i]), 'y', args[i].get('default'), 'z', args[i].get('defaltValue'), args[i].keys()
+
+ if args[i]['name'].replace(' ', '') == '':
+ args[i]['name'] = 'arg' + str(i+1)
+ elif args[i]['name'] == '&':
+ args[i]['name'] = 'arg' + str(i+1)
+ args[i]['type'] += '&'
+
+ #print 'c1', parents.keys()
+ if args[i]['type'][-1] == '&':
+ sname = args[i]['type'][:-1]
+ if sname[-1] == ' ': sname = sname[:-1]
+ if sname in parents:
+ args[i]['type'] = parents[sname] + '::' + sname + '&'
+ elif sname.replace('const ', '') in parents:
+ sname = sname.replace('const ', '')
+ args[i]['type'] = 'const ' + parents[sname] + '::' + sname + '&'
+ #print 'POST arggggggg', classname, 'x', mname, 'x', args[i]['name'], 'x', args[i]['type']
ret = ((classname + ' *') if constructor else method['returns_text'])#.replace('virtual ', '')
callprefix = 'new ' if constructor else ('self->' if not static else (classname + '::'))
- actualmname = '' # mname used in C
- if '__operator__' in mname:
- continue # TODO: operators
- else:
- actualmname = classname if constructor else (method.get('truename') or mname)
+ '' # mname used in C
+ actualmname = classname if constructor else (method.get('truename') or mname)
if method.get('getter') or method.get('setter'):
actualmname = actualmname[4:]
need_self = not constructor and not static
- typedargs = ([] if not need_self else [classname + ' * self']) + map(lambda arg: arg['type'] + ' ' + arg['name'], args)
- justargs = map(lambda arg: arg['name'], args)
+
+ def typedargs(args):
+ return ([] if not need_self else [classname + ' * self']) + map(lambda i: args[i]['type'] + ' arg' + str(i), range(len(args)))
+ def justargs(args):
+ return map(lambda i: 'arg' + str(i), range(len(args)))
+
fullname = ('emscripten_bind_' + generating_classname + '__' + mname).replace('::', '__')
generating_classname_suffixed = generating_classname
mname_suffixed = mname
@@ -401,72 +486,77 @@ def generate_class(generating_classname, classname, clazz): # TODO: deprecate ge
# C
- for i in method['num_args']:
+ for args in params:
+ 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'])
gen_c.write('''
%s %s_p%d(%s) {''' % (ret if not staticize else (ret + '&'), fullname, i,
- ', '.join(typedargs[:i + (0 if not need_self else 1)])))
+ ', '.join(typedargs(args)[:i + (0 if not need_self else 1)])))
if not staticize:
+ gen_c.write('\n')
if method.get('getter'):
- gen_c.write('''
- return self->%s;
-''' % actualmname)
+ gen_c.write(''' return self->%s;''' % actualmname)
elif method.get('setter'):
- gen_c.write('''
- self->%s = value;
-''' % actualmname)
+ gen_c.write(''' self->%s = arg0;''' % actualmname)
+ elif method.get('destroyer'):
+ gen_c.write(''' delete self;''')
+ 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 '',
- callprefix, actualmname, ', '.join(justargs[:i])))
+ gen_c.write(''' %s%s%s(%s);''' % ('return ' if ret.replace(' ', '') != 'void' else '',
+ callprefix, actualmname, ', '.join(justargs(args)[:i])))
+ gen_c.write('\n')
gen_c.write('}')
else:
- gen_c.write('''
- static %s ret = %s%s(%s);
- return ret;
-}''' % (method['returns'],
+ gen_c.write('\n')
+ if method.get('operator'):
+ gen_c.write(method['operator'])
+ else:
+ gen_c.write(''' static %s ret = %s%s(%s);
+ return ret;''' % (method['returns'],
callprefix, actualmname,
- ', '.join(justargs[:i])))
-
+ ', '.join(justargs(args)[:i])))
+ gen_c.write('\n}')
c_funcs.append(fullname + '_p' + str(i))
# JS
- print 'zz types:', map(lambda arg: arg['type'], args)
+ #print 'zz types:', map(lambda arg: arg['type'], args)
# We can assume that NULL is passed for null pointers, so object arguments can always
# have .ptr done on them
- justargs_fixed = justargs[:]
- for i in range(len(args)):
- arg = args[i]
- if clean_type(arg['type']) in classes:
- justargs_fixed[i] += '.ptr'
+ def justargs_fixed(args):
+ ret = justargs(args)[:]
+ for i in range(len(args)):
+ arg = args[i]
+ if clean_type(arg['type']) in classes:
+ ret[i] += '.ptr'
+ return ret
calls = ''
- print 'js loopin', method['num_args'], '|', len(args)#, args
- for i in method['num_args']:
- print ' ', i, type(i)
- if i != method['num_args'][0]:
+ #print 'js loopin', params, '|', len(args)#, args
+ for args in params:
+ i = len(args)
+ if args != params[0]:
calls += ' else '
- if i != method['num_args'][-1]:
- calls += ' if (' + justargs[i] + ' === undefined)'
- calls += '\n ' + (' ' if len(method['num_args']) > 0 else '')
+ if args != params[-1]:
+ calls += ' if (arg' + str(i) + ' === undefined)'
+ calls += '\n ' + (' ' if len(params) > 0 else '')
if constructor:
if not dupe:
calls += '''this.ptr = _%s_p%d(%s);
-''' % (fullname, i, ', '.join(justargs_fixed[:i]))
+''' % (fullname, i, ', '.join(justargs_fixed(args)[:i]))
else:
calls += '''this.ptr = _%s_p%d(%s);
-''' % (fullname, i, ', '.join(justargs_fixed[:i]))
+''' % (fullname, i, ', '.join(justargs_fixed(args)[:i]))
else:
- return_value = '''_%s_p%d(%s)''' % (fullname, i, ', '.join((['this.ptr'] if need_self else []) + justargs_fixed[:i]))
+ return_value = '''_%s_p%d(%s)''' % (fullname, i, ', '.join((['this.ptr'] if need_self else []) + justargs_fixed(args)[:i]))
print 'zz making return', classname, method['name'], method['returns'], return_value
if method['returns'] in classes:
# Generate a wrapper
- calls += 'return %s__wrap__(%s);' % (method['returns'].split('::')[-1], return_value)
+ calls += 'return wrapPointer(%s, %s);' % (return_value, method['returns'].split('::')[-1])
else:
# Normal return
calls += ('return ' if ret != 'void' else '') + return_value + ';'
@@ -479,14 +569,14 @@ def generate_class(generating_classname, classname, clazz): # TODO: deprecate ge
function %s(%s) {
%s
}
-%s''' % (mname_suffixed, ', '.join(justargs), calls, generate_wrapping_code(generating_classname_head))
+%s''' % (mname_suffixed, ', '.join(justargs(args)), calls, generate_wrapping_code(generating_classname_head))
else:
js_text = '''
function %s(%s) {
%s
}
%s.prototype = %s.prototype;
-''' % (mname_suffixed, ', '.join(justargs), calls, mname_suffixed, classname)
+''' % (mname_suffixed, ', '.join(justargs(args)), calls, mname_suffixed, classname)
if export:
js_text += '''
@@ -498,7 +588,7 @@ this['%s'] = %s;
%s.prototype%s = function(%s) {
%s
}
-''' % (generating_classname_head, ('.' + mname_suffixed) if not export else ("['" + mname_suffixed + "']"), ', '.join(justargs), calls)
+''' % (generating_classname_head, ('.' + mname_suffixed) if not export else ("['" + mname_suffixed + "']"), ', '.join(justargs(args)), calls)
js_text = js_text.replace('\n\n', '\n').replace('\n\n', '\n')
gen_js.write(js_text)
diff --git a/tools/shared.py b/tools/shared.py
index 811f56f5..3c9eeb60 100644
--- a/tools/shared.py
+++ b/tools/shared.py
@@ -71,15 +71,16 @@ def limit_size(string, MAX=80*20):
if len(string) < MAX: return string
return string[0:MAX] + '...'
-def pick_llvm_opts(optimization_level, optimize_size, allow_nonportable=False):
+def pick_llvm_opts(optimization_level, optimize_size, allow_nonportable=False, use_aa=False):
opts = []
if optimization_level > 0:
if allow_nonportable:
opts.append('-O%d' % optimization_level)
else:
# createStandardAliasAnalysisPasses
- #opts.append('-tbaa')
- #opts.append('-basicaa') # makes fannkuch slow but primes fast
+ if allow_nonportable and use_aa: # ammo.js results indicate this can be nonportable
+ opts.append('-tbaa')
+ opts.append('-basicaa') # makes fannkuch slow but primes fast
opts.append('-globalopt')
opts.append('-ipsccp')
@@ -88,7 +89,7 @@ def pick_llvm_opts(optimization_level, optimize_size, allow_nonportable=False):
opts.append('-simplifycfg')
opts.append('-prune-eh')
- opts.append('-inline')
+ if not optimize_size: opts.append('-inline') # The condition here is a difference with LLVM's createStandardAliasAnalysisPasses
opts.append('-functionattrs')
if optimization_level > 2:
opts.append('-argpromotion')