diff options
-rw-r--r-- | src/modules.js | 2 | ||||
-rw-r--r-- | src/parseTools.js | 6 | ||||
-rw-r--r-- | tests/cases/ptrtoint_blockaddr.ll | 20 | ||||
-rw-r--r-- | tests/runner.py | 14 | ||||
-rwxr-xr-x | tools/bindings_generator.py | 314 | ||||
-rw-r--r-- | tools/shared.py | 9 |
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') |