Merge remote-tracking branch 'upstream/master'
Conflicts: src/intertyper.js tests/runner.py
This commit is contained in:
Коммит
c5e5c90cd1
|
@ -13,7 +13,7 @@ COMPILER_OPTS = ['-m32'] # Need to build as 32bit arch, for now -
|
|||
# various errors on 64bit compilation
|
||||
# WARNING: '-g' here will generate llvm bitcode that lli will crash on!
|
||||
|
||||
SPIDERMONKEY_ENGINE = [os.path.expanduser('~/Dev/mozilla-central/js/src/js'), '-m', '-j', '-p']
|
||||
SPIDERMONKEY_ENGINE = [os.path.expanduser('~/Dev/mozilla-central/js/src/js'), '-m', '-n']
|
||||
V8_ENGINE = [os.path.expanduser('~/Dev/v8/d8')]
|
||||
|
||||
#COMPILER_ENGINE=SPIDERMONKEY_ENGINE # XXX Warning: currently appears to be broken on trunk, some file reading issue
|
||||
|
|
|
@ -275,25 +275,27 @@ function analyzer(data) {
|
|||
}
|
||||
});
|
||||
|
||||
// Second pass over variables - notice when types are crossed by bitcast
|
||||
if (QUANTUM_SIZE === 1) {
|
||||
// Second pass over variables - notice when types are crossed by bitcast
|
||||
|
||||
func.lines.forEach(function(item) {
|
||||
if (item.intertype === 'assign' && item.value.intertype === 'bitcast') {
|
||||
// bitcasts are unique in that they convert one pointer to another. We
|
||||
// sometimes need to know the original type of a pointer, so we save that.
|
||||
//
|
||||
// originalType is the type this variable is created from
|
||||
// derivedTypes are the types that this variable is cast into
|
||||
func.variables[item.ident].originalType = item.value.type2;
|
||||
func.lines.forEach(function(item) {
|
||||
if (item.intertype === 'assign' && item.value.intertype === 'bitcast') {
|
||||
// bitcasts are unique in that they convert one pointer to another. We
|
||||
// sometimes need to know the original type of a pointer, so we save that.
|
||||
//
|
||||
// originalType is the type this variable is created from
|
||||
// derivedTypes are the types that this variable is cast into
|
||||
func.variables[item.ident].originalType = item.value.type2;
|
||||
|
||||
if (!isNumber(item.value.ident)) {
|
||||
if (!func.variables[item.value.ident].derivedTypes) {
|
||||
func.variables[item.value.ident].derivedTypes = [];
|
||||
if (!isNumber(item.value.ident)) {
|
||||
if (!func.variables[item.value.ident].derivedTypes) {
|
||||
func.variables[item.value.ident].derivedTypes = [];
|
||||
}
|
||||
func.variables[item.value.ident].derivedTypes.push(item.value.type);
|
||||
}
|
||||
func.variables[item.value.ident].derivedTypes.push(item.value.type);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
for (vname in func.variables) {
|
||||
var variable = func.variables[vname];
|
||||
|
|
|
@ -71,6 +71,9 @@ eval(processMacros(preprocess(read('runtime.js'))));
|
|||
// Read llvm
|
||||
|
||||
var raw = read(ll_file);
|
||||
if (FAKE_X86_FP80) {
|
||||
raw = raw.replace(/x86_fp80/g, 'double');
|
||||
}
|
||||
var lines = raw.split('\n');
|
||||
raw = null;
|
||||
|
||||
|
|
|
@ -543,7 +543,9 @@ function intertyper(data, parseFunctions, baseLineNum) {
|
|||
item.intertype = 'bitcast';
|
||||
item.type = item.tokens[4].text; // The final type
|
||||
Types.needAnalysis[item.type] = 0;
|
||||
item.ident = toNiceIdent(item.tokens[2].text);
|
||||
var to = getTokenIndexByText(item.tokens, 'to');
|
||||
item.params = [parseLLVMSegment(item.tokens.slice(2, to))];
|
||||
item.ident = item.params[0].ident;
|
||||
item.type2 = item.tokens[1].text; // The original type
|
||||
Types.needAnalysis[item.type2] = 0;
|
||||
this.forwardItem(item, 'Reintegrator');
|
||||
|
@ -791,13 +793,10 @@ function intertyper(data, parseFunctions, baseLineNum) {
|
|||
// external function stub
|
||||
substrate.addActor('External', {
|
||||
processItem: function(item) {
|
||||
if (item.tokens[1].text in LLVM.LINKAGES || item.tokens[1].text in LLVM.PARAM_ATTR) {
|
||||
if (item.tokens[1].text in LLVM.LINKAGES || item.tokens[1].text in LLVM.PARAM_ATTR || item.tokens[1].text in LLVM.VISIBILITIES) {
|
||||
item.tokens.splice(1, 1);
|
||||
}
|
||||
|
||||
if (item.tokens[1].text == 'hidden') {
|
||||
item.tokens = [item.tokens[0]].concat(item.tokens.slice(2));
|
||||
}
|
||||
var params = parseParamTokens(item.tokens[3].item.tokens);
|
||||
return [{
|
||||
intertype: 'functionStub',
|
||||
|
|
|
@ -253,6 +253,10 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
|
|||
constant = makePointer(constant, null, BUILD_AS_SHARED_LIB ? 'ALLOC_NORMAL' : 'ALLOC_STATIC', item.type);
|
||||
|
||||
var js = item.ident + '=' + constant + ';';
|
||||
// Special case: class vtables. We make sure they are null-terminated, to allow easy runtime operations
|
||||
if (item.ident.substr(0, 5) == '__ZTV') {
|
||||
js += '\n' + makePointer('[0]', null, BUILD_AS_SHARED_LIB ? 'ALLOC_NORMAL' : 'ALLOC_STATIC', ['void*']) + ';';
|
||||
}
|
||||
if (item.ident in EXPORTED_GLOBALS) {
|
||||
js += '\nModule["' + item.ident + '"] = ' + item.ident + ';';
|
||||
}
|
||||
|
@ -603,7 +607,7 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
|
|||
makeFuncLineActor('store', function(item) {
|
||||
var value = finalizeLLVMParameter(item.value);
|
||||
if (pointingLevels(item.pointerType) == 1) {
|
||||
value = parseNumerical(value, removePointing(item.pointerType));
|
||||
value = parseNumerical(value, item.valueType);
|
||||
}
|
||||
var impl = VAR_EMULATED;
|
||||
if (item.pointer.intertype == 'value') {
|
||||
|
@ -776,7 +780,7 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
|
|||
makeFuncLineActor('mathop', processMathop);
|
||||
|
||||
makeFuncLineActor('bitcast', function(item) {
|
||||
return item.ident;
|
||||
return finalizeLLVMParameter(item.params[0]);
|
||||
});
|
||||
|
||||
function makeFunctionCall(ident, params, funcData) {
|
||||
|
@ -876,6 +880,7 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
|
|||
var preFile = BUILD_AS_SHARED_LIB ? 'preamble_sharedlib.js' : 'preamble.js';
|
||||
var pre = processMacros(preprocess(read(preFile).replace('{{RUNTIME}}', getRuntime()), CONSTANTS));
|
||||
print(pre);
|
||||
print('Runtime.QUANTUM_SIZE = ' + QUANTUM_SIZE);
|
||||
if (RUNTIME_TYPE_INFO) {
|
||||
Types.cleanForRuntime();
|
||||
print('Runtime.typeInfo = ' + JSON.stringify(Types.types));
|
||||
|
|
|
@ -3758,7 +3758,8 @@ LibraryManager.library = {
|
|||
strdup: function(ptr) {
|
||||
var len = String_len(ptr);
|
||||
var newStr = _malloc(len + 1);
|
||||
{{{ makeCopyValues('newStr', 'ptr', 'len + 1', 'null', ' || 0') }}};
|
||||
{{{ makeCopyValues('newStr', 'ptr', 'len', 'null') }}};
|
||||
{{{ makeSetValue('newStr', 'len', '0', 'i8') }}};
|
||||
return newStr;
|
||||
},
|
||||
|
||||
|
@ -4120,6 +4121,14 @@ LibraryManager.library = {
|
|||
return -1; // 'indeterminable' for FLT_ROUNDS
|
||||
},
|
||||
|
||||
llvm_memory_barrier: function(){},
|
||||
|
||||
llvm_atomic_load_add_i32_p0i32: function(ptr, delta) {
|
||||
var ret = {{{ makeGetValue('ptr', '0', 'i32') }}};
|
||||
{{{ makeSetValue('ptr', '0', 'ret+delta', 'i32') }}};
|
||||
return ret;
|
||||
},
|
||||
|
||||
// ==========================================================================
|
||||
// iostream.h
|
||||
// ==========================================================================
|
||||
|
@ -5285,6 +5294,7 @@ LibraryManager.library = {
|
|||
pthread_mutex_destroy: function() {},
|
||||
pthread_mutex_lock: function() {},
|
||||
pthread_mutex_unlock: function() {},
|
||||
pthread_cond_broadcast: function() {},
|
||||
|
||||
// ==========================================================================
|
||||
// malloc.h
|
||||
|
|
|
@ -74,7 +74,7 @@ function toNiceIdent(ident) {
|
|||
assert(ident);
|
||||
if (parseFloat(ident) == ident) return ident;
|
||||
if (ident == 'null') return '0'; // see parseNumerical
|
||||
return ident.replace('%', '$').replace(/["&\\ \.@:<>,\*\[\]-]/g, '_');
|
||||
return ident.replace('%', '$').replace(/["&\\ \.@:<>,\*\[\]\(\)-]/g, '_');
|
||||
}
|
||||
|
||||
// Kind of a hack. In some cases we have strings that we do not want
|
||||
|
@ -143,6 +143,7 @@ function isFunctionDef(token) {
|
|||
}
|
||||
|
||||
function isFunctionType(type) {
|
||||
type = type.replace(/"[^"]+"/g, '".."');
|
||||
var parts = type.split(' ');
|
||||
if (pointingLevels(type) !== 1) return false;
|
||||
var text = removeAllPointing(parts.slice(1).join(' '));
|
||||
|
@ -430,6 +431,9 @@ function parseLLVMFunctionCall(segment) {
|
|||
if (type === '?') {
|
||||
if (intertype === 'getelementptr') {
|
||||
type = '*'; // a pointer, we can easily say, this is
|
||||
} else if (intertype === 'bitcast') {
|
||||
assert(segment[2].item.tokens.slice(-2)[0].text === 'to');
|
||||
type = segment[2].item.tokens.slice(-1)[0].text;
|
||||
}
|
||||
}
|
||||
var ret = {
|
||||
|
@ -486,7 +490,15 @@ function IEEEUnHex(stringy) {
|
|||
stringy = stringy.substr(2); // leading '0x';
|
||||
if (stringy.replace(/0/g, '') === '') return 0;
|
||||
while (stringy.length < 16) stringy = '0' + stringy;
|
||||
assert(stringy.length === 16, 'Can only unhex 16-digit double numbers, nothing platform-specific');
|
||||
if (FAKE_X86_FP80 && stringy.length > 16) {
|
||||
stringy = stringy.substr(stringy.length-16, 16);
|
||||
if (!Debugging.shownIEEEUnHexWarning) {
|
||||
dprint('WARNING: .ll contains floating-point values with more than 64 bits. Faking values for them.');
|
||||
dprint(' If they are used, this will almost certainly fail!');
|
||||
Debugging.shownIEEEUnHexWarning = true;
|
||||
}
|
||||
}
|
||||
assert(stringy.length === 16, 'Can only unhex 16-digit double numbers, nothing platform-specific'); // |long double| can cause x86_fp80 which causes this
|
||||
var top = eval('0x' + stringy[0]);
|
||||
var neg = !!(top & 8); // sign
|
||||
if (neg) {
|
||||
|
|
|
@ -320,7 +320,7 @@ function setValue(ptr, value, type) {
|
|||
default: abort('invalid type for setValue: ' + type);
|
||||
}
|
||||
}
|
||||
this['setValue'] = setValue;
|
||||
Module['setValue'] = setValue;
|
||||
|
||||
// Parallel to setValue.
|
||||
|
||||
|
@ -338,7 +338,7 @@ function getValue(ptr, type) {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
this['getValue'] = getValue;
|
||||
Module['getValue'] = getValue;
|
||||
|
||||
// Allocates memory for some data and initializes it properly.
|
||||
|
||||
|
@ -428,7 +428,8 @@ var STACK_ROOT, STACKTOP, STACK_MAX;
|
|||
var STATICTOP;
|
||||
|
||||
var HAS_TYPED_ARRAYS = false;
|
||||
var TOTAL_MEMORY = 50*1024*1024;
|
||||
var TOTAL_MEMORY = Module['TOTAL_MEMORY'] || {{{ TOTAL_MEMORY }}};
|
||||
var FAST_MEMORY = Module['FAST_MEMORY'] || {{{ FAST_MEMORY }}};
|
||||
|
||||
// Initialize the runtime's memory
|
||||
#if USE_TYPED_ARRAYS
|
||||
|
@ -459,9 +460,8 @@ if (HAS_TYPED_ARRAYS) {
|
|||
} else
|
||||
#endif
|
||||
{
|
||||
// Without this optimization, Chrome is slow. Sadly, the constant here needs to be tweaked depending on the code being run...
|
||||
var FAST_MEMORY = TOTAL_MEMORY/32;
|
||||
HEAP = new Array(FAST_MEMORY);
|
||||
// Make sure that our HEAP is implemented as a flat array.
|
||||
HEAP = new Array(TOTAL_MEMORY);
|
||||
for (var i = 0; i < FAST_MEMORY; i++) {
|
||||
HEAP[i] = 0; // XXX We do *not* use {{| makeSetValue(0, 'i', 0, 'null') |}} here, since this is done just to optimize runtime speed
|
||||
}
|
||||
|
|
|
@ -34,6 +34,12 @@ INVOKE_RUN = 1; // Whether we will call run(). Disable if you embed the generate
|
|||
// code in your own, and will call run() yourself at the right time
|
||||
INIT_STACK = 1; // Whether to initialize memory on the stack to 0.
|
||||
INIT_HEAP = 0; // Whether to initialize memory anywhere other than the stack to 0.
|
||||
FAST_MEMORY = 2*1024*1024; // The amount of memory to initialize to 0. This ensures it will be
|
||||
// in a flat array. This only matters in non-typed array builds.
|
||||
TOTAL_MEMORY = 50*1024*1024; // The total amount of memory to use. This mainly matters in
|
||||
// typed array builds - accessing memory about this value will
|
||||
// return undefined values and lead to serious problems, and there
|
||||
// is currently no warning about that!
|
||||
|
||||
// Code embetterments
|
||||
OPTIMIZE = 0; // Optimize llvm operations into js commands
|
||||
|
@ -129,6 +135,10 @@ RUNTIME_TYPE_INFO = 0; // Whether to expose type info to the script at run time.
|
|||
// to more easily perform operations from handwritten JS on
|
||||
// objects with structures etc.
|
||||
|
||||
FAKE_X86_FP80 = 0; // Replaces x86_fp80 with double. This loses precision. It is better,
|
||||
// if you can, to get the original source code to build without x86_fp80
|
||||
// (which is nonportable anyhow).
|
||||
|
||||
// Compiler debugging options
|
||||
DEBUG_TAGS_SHOWING = [];
|
||||
// Some useful items:
|
||||
|
|
123
tests/runner.py
123
tests/runner.py
|
@ -5,7 +5,7 @@ See settings.py file for options¶ms. Edit as needed.
|
|||
'''
|
||||
|
||||
from subprocess import Popen, PIPE, STDOUT
|
||||
import os, unittest, tempfile, shutil, time, inspect, sys, math, glob, tempfile, re, json
|
||||
import os, unittest, tempfile, shutil, time, inspect, sys, math, glob, tempfile, re, json, difflib
|
||||
|
||||
# Setup
|
||||
|
||||
|
@ -178,7 +178,7 @@ class RunnerCore(unittest.TestCase):
|
|||
def do_emscripten(self, filename, output_processor=None, append_ext=True, extra_args=[]):
|
||||
# Run Emscripten
|
||||
exported_settings = {}
|
||||
for setting in ['QUANTUM_SIZE', 'RELOOP', 'OPTIMIZE', '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', 'AUTO_OPTIMIZE', 'EXPORTED_FUNCTIONS', 'EXPORTED_GLOBALS', 'BUILD_AS_SHARED_LIB', 'INCLUDE_FULL_LIBRARY', 'RUNTIME_TYPE_INFO', 'DISABLE_EXCEPTIONS', 'EXCEPTION_DEBUG']:
|
||||
for setting in ['QUANTUM_SIZE', 'RELOOP', 'OPTIMIZE', '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', 'AUTO_OPTIMIZE', 'EXPORTED_FUNCTIONS', 'EXPORTED_GLOBALS', 'BUILD_AS_SHARED_LIB', 'INCLUDE_FULL_LIBRARY', 'RUNTIME_TYPE_INFO', 'DISABLE_EXCEPTIONS', 'FAST_MEMORY', 'EXCEPTION_DEBUG']:
|
||||
try:
|
||||
value = eval(setting)
|
||||
exported_settings[setting] = value
|
||||
|
@ -223,17 +223,23 @@ class RunnerCore(unittest.TestCase):
|
|||
if type(value) is not str: value = value() # lazy loading
|
||||
if type(string) is not str: string = string()
|
||||
if value not in string:
|
||||
raise Exception("Expected to find '%s' in '%s'" % (limit_size(value), limit_size(string)))
|
||||
raise Exception("Expected to find '%s' in '%s', diff:\n\n%s" % (
|
||||
limit_size(value), limit_size(string),
|
||||
limit_size(''.join([a.rstrip()+'\n' for a in difflib.unified_diff(value.split('\n'), string.split('\n'), fromfile='expected', tofile='actual')]))
|
||||
))
|
||||
|
||||
def assertNotContained(self, value, string):
|
||||
if type(value) is not str: value = value() # lazy loading
|
||||
if type(string) is not str: string = string()
|
||||
if value in string:
|
||||
raise Exception("Expected to NOT find '%s' in '%s'" % (limit_size(value), limit_size(string)))
|
||||
raise Exception("Expected to NOT find '%s' in '%s', diff:\n\n%s" % (
|
||||
limit_size(value), limit_size(string),
|
||||
limit_size(''.join([a.rstrip()+'\n' for a in difflib.unified_diff(value.split('\n'), string.split('\n'), fromfile='expected', tofile='actual')]))
|
||||
))
|
||||
|
||||
###################################################################################################
|
||||
|
||||
if 'benchmark' not in sys.argv:
|
||||
if 'benchmark' not in str(sys.argv):
|
||||
# Tests
|
||||
|
||||
print "Running Emscripten tests..."
|
||||
|
@ -2987,7 +2993,6 @@ if 'benchmark' not in sys.argv:
|
|||
|
||||
self.do_ll_test(path_from_root('tests', 'lua', 'lua.ll'),
|
||||
'hello lua world!\n17\n1\n2\n3\n4\n7',
|
||||
js_engines=[V8_ENGINE], # XXX Moz bug 675269
|
||||
args=['-e', '''print("hello lua world!");print(17);for x = 1,4 do print(x) end;print(10-3)'''],
|
||||
output_nicerizer=lambda string: string.replace('\n\n', '\n').replace('\n\n', '\n'))
|
||||
|
||||
|
@ -2997,8 +3002,10 @@ if 'benchmark' not in sys.argv:
|
|||
# Build a library into a .bc file. We build the .bc file once and cache it for all our tests. (We cache in
|
||||
# memory since the test directory is destroyed and recreated for each test. Note that we cache separately
|
||||
# for different compilers)
|
||||
def get_library(self, name, generated_libs, configure=['./configure'], configure_args=[], make=['make'], make_args=['-j', '2'], cache=True):
|
||||
def get_library(self, name, generated_libs, configure=['./configure'], configure_args=[], make=['make'], make_args=['-j', '2'], cache=True, build_subdir=None):
|
||||
if type(generated_libs) is not list: generated_libs = [generated_libs]
|
||||
if build_subdir and configure.startswith('./'):
|
||||
configure = '.' + configure
|
||||
|
||||
if GlobalCache is not None:
|
||||
cache_name = name + '|' + COMPILER
|
||||
|
@ -3014,16 +3021,24 @@ if 'benchmark' not in sys.argv:
|
|||
project_dir = os.path.join(temp_dir, name)
|
||||
shutil.copytree(path_from_root('tests', name), project_dir) # Useful in debugging sometimes to comment this out
|
||||
os.chdir(project_dir)
|
||||
if build_subdir:
|
||||
try:
|
||||
os.mkdir('cbuild')
|
||||
except:
|
||||
pass
|
||||
os.chdir(os.path.join(project_dir, 'cbuild'))
|
||||
env = os.environ.copy()
|
||||
env['RANLIB'] = env['AR'] = env['CXX'] = env['CC'] = env['LIBTOOL'] = EMMAKEN
|
||||
env['EMMAKEN_COMPILER'] = COMPILER
|
||||
env['EMSCRIPTEN_TOOLS'] = path_from_root('tools')
|
||||
env['CFLAGS'] = env['EMMAKEN_CFLAGS'] = ' '.join(COMPILER_OPTS + COMPILER_TEST_OPTS) # Normal CFLAGS is ignored by some configure's.
|
||||
if configure: # Useful in debugging sometimes to comment this out (and 2 lines below)
|
||||
if configure: # Useful in debugging sometimes to comment this out (and the lines below up to and including the |make| call)
|
||||
env['EMMAKEN_JUST_CONFIGURE'] = '1'
|
||||
Popen(configure + configure_args, stdout=PIPE, stderr=STDOUT, env=env).communicate()[0]
|
||||
del env['EMMAKEN_JUST_CONFIGURE']
|
||||
Popen(make + make_args, stdout=PIPE, stderr=STDOUT, env=env).communicate()[0]
|
||||
bc_file = os.path.join(project_dir, 'bc.bc')
|
||||
self.do_link(map(lambda lib: os.path.join(project_dir, lib), generated_libs), bc_file)
|
||||
self.do_link(map(lambda lib: os.path.join(project_dir, 'cbuild', lib) if build_subdir else os.path.join(project_dir, lib), generated_libs), bc_file)
|
||||
if cache and GlobalCache is not None:
|
||||
print >> sys.stderr, '<save build into cache> ',
|
||||
GlobalCache[cache_name] = open(bc_file, 'rb').read()
|
||||
|
@ -3032,7 +3047,7 @@ if 'benchmark' not in sys.argv:
|
|||
def get_freetype(self):
|
||||
global INIT_STACK; INIT_STACK = 1 # TODO: Investigate why this is necessary
|
||||
|
||||
return self.get_library('freetype', os.path.join('objs', '.libs', 'libfreetype.so'))
|
||||
return self.get_library('freetype', os.path.join('objs', '.libs', 'libfreetype.a.bc'))
|
||||
|
||||
def test_freetype(self):
|
||||
if QUANTUM_SIZE == 1: return self.skip() # TODO: Figure out and try to fix
|
||||
|
@ -3066,10 +3081,25 @@ if 'benchmark' not in sys.argv:
|
|||
|
||||
self.do_test(open(path_from_root('tests', 'zlib', 'example.c'), 'r').read(),
|
||||
open(path_from_root('tests', 'zlib', 'ref.txt'), 'r').read(),
|
||||
libraries=[self.get_library('zlib', os.path.join('libz.a'), make_args=['libz.a'])],
|
||||
libraries=[self.get_library('zlib', os.path.join('libz.a.bc'), make_args=['libz.a'])],
|
||||
includes=[path_from_root('tests', 'zlib')],
|
||||
force_c=True)
|
||||
|
||||
def zzztest_glibc(self):
|
||||
global CORRECT_SIGNS; CORRECT_SIGNS = 1
|
||||
global CORRECT_OVERFLOWS; CORRECT_OVERFLOWS = 1
|
||||
global CORRECT_ROUNDINGS; CORRECT_ROUNDINGS = 1
|
||||
|
||||
self.do_test(r'''
|
||||
#include <stdio.h>
|
||||
int main() { printf("hai\n"); return 1; }
|
||||
''',
|
||||
libraries=[self.get_library('glibc', [os.path.join('src', '.libs', 'libBulletCollision.a.bc'),
|
||||
os.path.join('src', '.libs', 'libBulletDynamics.a.bc'),
|
||||
os.path.join('src', '.libs', 'libLinearMath.a.bc')],
|
||||
configure_args=['--disable-sanity-checks'])],
|
||||
includes=[path_from_root('tests', 'glibc', 'include')])
|
||||
|
||||
def test_the_bullet(self): # Called thus so it runs late in the alphabetical cycle... it is long
|
||||
global SAFE_HEAP, SAFE_HEAP_LINES, USE_TYPED_ARRAYS, LLVM_OPTS
|
||||
|
||||
|
@ -3087,9 +3117,9 @@ if 'benchmark' not in sys.argv:
|
|||
|
||||
self.do_test(open(path_from_root('tests', 'bullet', 'Demos', 'HelloWorld', 'HelloWorld.cpp'), 'r').read(),
|
||||
open(path_from_root('tests', 'bullet', 'output.txt'), 'r').read(),
|
||||
libraries=[self.get_library('bullet', [os.path.join('src', '.libs', 'libBulletCollision.a'),
|
||||
os.path.join('src', '.libs', 'libBulletDynamics.a'),
|
||||
os.path.join('src', '.libs', 'libLinearMath.a')],
|
||||
libraries=[self.get_library('bullet', [os.path.join('src', '.libs', 'libBulletCollision.a.bc'),
|
||||
os.path.join('src', '.libs', 'libBulletDynamics.a.bc'),
|
||||
os.path.join('src', '.libs', 'libLinearMath.a.bc')],
|
||||
configure_args=['--disable-demos','--disable-dependency-tracking'])],
|
||||
includes=[path_from_root('tests', 'bullet', 'src')],
|
||||
js_engines=[SPIDERMONKEY_ENGINE]) # V8 issue 1407
|
||||
|
@ -3152,10 +3182,10 @@ if 'benchmark' not in sys.argv:
|
|||
freetype = self.get_freetype()
|
||||
|
||||
poppler = self.get_library('poppler',
|
||||
[os.path.join('poppler', '.libs', 'libpoppler.so.13.0.0'),
|
||||
os.path.join('goo', '.libs', 'libgoo.a'),
|
||||
os.path.join('fofi', '.libs', 'libfofi.a'),
|
||||
os.path.join('splash', '.libs', 'libsplash.a'),
|
||||
[os.path.join('poppler', '.libs', 'libpoppler.so.13.0.0.bc'),
|
||||
os.path.join('goo', '.libs', 'libgoo.a.bc'),
|
||||
os.path.join('fofi', '.libs', 'libfofi.a.bc'),
|
||||
os.path.join('splash', '.libs', 'libsplash.a.bc'),
|
||||
os.path.join('utils', 'pdftoppm.o'),
|
||||
os.path.join('utils', 'parseargs.o')],
|
||||
configure_args=['--disable-libjpeg', '--disable-libpng', '--disable-poppler-qt', '--disable-poppler-qt4', '--disable-cms'])
|
||||
|
@ -3168,15 +3198,13 @@ if 'benchmark' not in sys.argv:
|
|||
self.do_ll_test(combined,
|
||||
lambda: map(ord, open(path_from_root('tests', 'poppler', 'ref.ppm'), 'r').read()).__str__().replace(' ', ''),
|
||||
args='-scale-to 512 paper.pdf filename'.split(' '),
|
||||
post_build=post,
|
||||
js_engines=[V8_ENGINE]) # XXX Moz bug 675269
|
||||
post_build=post)
|
||||
#, build_ll_hook=self.do_autodebug)
|
||||
|
||||
def test_openjpeg(self):
|
||||
global USE_TYPED_ARRAYS
|
||||
global CORRECT_SIGNS
|
||||
if USE_TYPED_ARRAYS == 2:
|
||||
return self.skip() # XXX Moz bug 675269
|
||||
CORRECT_SIGNS = 1
|
||||
else:
|
||||
CORRECT_SIGNS = 2
|
||||
|
@ -3201,7 +3229,7 @@ if 'benchmark' not in sys.argv:
|
|||
open(filename, 'w').write(src)
|
||||
|
||||
lib = self.get_library('openjpeg',
|
||||
[os.path.join('bin', 'libopenjpeg.so'),
|
||||
[os.path.join('bin', 'libopenjpeg.so.1.4.0.bc'),
|
||||
os.path.sep.join('codec/CMakeFiles/j2k_to_image.dir/index.c.o'.split('/')),
|
||||
os.path.sep.join('codec/CMakeFiles/j2k_to_image.dir/convert.c.o'.split('/')),
|
||||
os.path.sep.join('codec/CMakeFiles/j2k_to_image.dir/__/common/color.c.o'.split('/')),
|
||||
|
@ -3257,7 +3285,6 @@ if 'benchmark' not in sys.argv:
|
|||
os.path.join(self.get_building_dir(), 'openjpeg')],
|
||||
force_c=True,
|
||||
post_build=post,
|
||||
js_engines=[V8_ENGINE], # XXX Moz bug 675269
|
||||
output_nicerizer=image_compare)# build_ll_hook=self.do_autodebug)
|
||||
|
||||
def test_python(self):
|
||||
|
@ -3271,7 +3298,6 @@ if 'benchmark' not in sys.argv:
|
|||
|
||||
self.do_ll_test(path_from_root('tests', 'python', 'python.ll'),
|
||||
'hello python world!\n[0, 2, 4, 6]\n5\n22\n5.470000',
|
||||
js_engines=[V8_ENGINE], # XXX Moz bug 675269
|
||||
args=['-S', '-c' '''print "hello python world!"; print [x*2 for x in range(4)]; t=2; print 10-3-t; print (lambda x: x*2)(11); print '%f' % 5.47'''],
|
||||
extra_emscripten_args=['-m'])
|
||||
|
||||
|
@ -3426,6 +3452,10 @@ if 'benchmark' not in sys.argv:
|
|||
Child2() : Parent(9) { printf("Child2:%d\\n", value); };
|
||||
int getValCube() { return value*value*value; }
|
||||
static void printStatic() { printf("*static*\\n"); }
|
||||
|
||||
virtual void virtualFunc() { printf("*virtualf*\\n"); }
|
||||
virtual void virtualFunc2() { printf("*virtualf2*\\n"); }
|
||||
static void runVirtualFunc(Child2 *self) { self->virtualFunc(); };
|
||||
private:
|
||||
void doSomethingSecret() { printf("security breached!\\n"); }; // we should not be able to do this
|
||||
};
|
||||
|
@ -3501,6 +3531,32 @@ if 'benchmark' not in sys.argv:
|
|||
|
||||
Child2.prototype.printStatic(); // static calls go through the prototype
|
||||
|
||||
// virtual function
|
||||
c2.virtualFunc();
|
||||
Child2.prototype.runVirtualFunc(c2);
|
||||
c2.virtualFunc2();
|
||||
|
||||
// extend the class from JS
|
||||
var c3 = new Child2;
|
||||
customizeVTable(c3, [{
|
||||
original: Child2.prototype.virtualFunc,
|
||||
replacement: function() {
|
||||
print('*js virtualf replacement*');
|
||||
}
|
||||
}, {
|
||||
original: Child2.prototype.virtualFunc2,
|
||||
replacement: function() {
|
||||
print('*js virtualf2 replacement*');
|
||||
}
|
||||
}]);
|
||||
c3.virtualFunc();
|
||||
Child2.prototype.runVirtualFunc(c3);
|
||||
c3.virtualFunc2();
|
||||
|
||||
c2.virtualFunc(); // original should remain the same
|
||||
Child2.prototype.runVirtualFunc(c2);
|
||||
c2.virtualFunc2();
|
||||
|
||||
print('*ok*');
|
||||
'''
|
||||
|
||||
|
@ -3539,6 +3595,17 @@ Child2:9
|
|||
0
|
||||
1
|
||||
*static*
|
||||
*virtualf*
|
||||
*virtualf*
|
||||
*virtualf2*
|
||||
Parent:9
|
||||
Child2:9
|
||||
*js virtualf replacement*
|
||||
*js virtualf replacement*
|
||||
*js virtualf2 replacement*
|
||||
*virtualf*
|
||||
*virtualf*
|
||||
*virtualf2*
|
||||
*ok*
|
||||
''', post_build=post2)
|
||||
|
||||
|
@ -3975,7 +4042,8 @@ TT = %s
|
|||
self.assertEquals(output, expected)
|
||||
|
||||
else:
|
||||
# Benchmarks
|
||||
# Benchmarks. Run them with argument |benchmark|. To run a specific test, do
|
||||
# |benchmark.test_X|.
|
||||
|
||||
print "Running Emscripten benchmarks..."
|
||||
|
||||
|
@ -4008,6 +4076,7 @@ else:
|
|||
CORRECT_OVERFLOWS_LINES = CORRECT_SIGNS_LINES = CORRECT_ROUNDINGS_LINES = SAFE_HEAP_LINES = []
|
||||
LLVM_OPTS = 1
|
||||
DISABLE_EXCEPTIONS = 1
|
||||
FAST_MEMORY = 10*1024*1024
|
||||
|
||||
TEST_REPS = 4
|
||||
TOTAL_TESTS = 6
|
||||
|
@ -4016,7 +4085,7 @@ else:
|
|||
total_times = map(lambda x: 0., range(TEST_REPS))
|
||||
total_native_times = map(lambda x: 0., range(TEST_REPS))
|
||||
|
||||
class Benchmark(RunnerCore):
|
||||
class benchmark(RunnerCore):
|
||||
def print_stats(self, times, native_times):
|
||||
mean = sum(times)/len(times)
|
||||
squared_times = map(lambda x: x*x, times)
|
||||
|
@ -4156,7 +4225,7 @@ else:
|
|||
old_quantum = QUANTUM_SIZE
|
||||
old_use_typed_arrays = USE_TYPED_ARRAYS
|
||||
QUANTUM_SIZE = 1
|
||||
USE_TYPED_ARRAYS = 0 # Rounding errors with TA2 are too big in this very rounding-sensitive code
|
||||
USE_TYPED_ARRAYS = 0 # Rounding errors with TA2 are too big in this very rounding-sensitive code. However, TA2 is much faster (2X)
|
||||
|
||||
src = open(path_from_root('tests', 'raytrace.cpp'), 'r').read().replace('double', 'float') # benchmark with floats
|
||||
self.do_benchmark(src, ['7', '256'], '256 256')
|
||||
|
|
|
@ -40,6 +40,9 @@ It's only purpose is to make it easy to access the C++ code in the JS
|
|||
bindings, and to prevent DFE from removing the code we care about. The
|
||||
JS bindings do more serious work, creating class structures in JS and
|
||||
linking them to the C bindings.
|
||||
|
||||
NOTE: ammo.js is currently the biggest consumer of this code. For some
|
||||
more docs you can see that project's README
|
||||
'''
|
||||
|
||||
import os, sys, glob, re
|
||||
|
@ -105,6 +108,8 @@ for classname, clazz in parsed.classes.iteritems():
|
|||
struct['name'] = sname # Missing in CppHeaderParser
|
||||
print 'zz seen struct %s in %s' % (sname, classname)
|
||||
|
||||
print 'zz parents: ', parents
|
||||
|
||||
for classname, clazz in classes.iteritems():
|
||||
# Various precalculations
|
||||
print 'zz precalc', classname
|
||||
|
@ -177,6 +182,9 @@ for classname, clazz in classes.iteritems():
|
|||
1/0.
|
||||
|
||||
# Fill in some missing stuff
|
||||
method['returns_text'] = method['returns_text'].replace('&', '').replace('*', '')
|
||||
if method['returns_text'] in parents:
|
||||
method['returns_text'] = parents[method['returns_text']] + '::' + method['returns_text']
|
||||
if method.get('returns_const'): method['returns_text'] = 'const ' + method['returns_text']
|
||||
if method.get('returns_pointer'):
|
||||
while method['returns_text'].count('*') < method['returns_pointer']:
|
||||
|
@ -355,44 +363,119 @@ gen_js = open(basename + '.js', 'w')
|
|||
|
||||
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('''
|
||||
// Bindings utilities
|
||||
var Object__cache = {};
|
||||
function wrapPointer(ptr, class_) {
|
||||
var cache = class_ ? class_.prototype.__cache__ : Object__cache;
|
||||
|
||||
var Object__cache = {}; // we do it this way so we do not modify |Object|
|
||||
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);
|
||||
__class__ = __class__ || Object;
|
||||
ret = Object.create(__class__.prototype);
|
||||
ret.ptr = ptr;
|
||||
ret.__class__ = __class__;
|
||||
return cache[ptr] = ret;
|
||||
}
|
||||
this['wrapPointer'] = wrapPointer;
|
||||
Module['wrapPointer'] = wrapPointer;
|
||||
|
||||
function castObject(obj, class_) {
|
||||
return wrapPointer(obj.ptr, class_);
|
||||
function castObject(obj, __class__) {
|
||||
return wrapPointer(obj.ptr, __class__);
|
||||
}
|
||||
this['castObject'] = castObject;
|
||||
Module['castObject'] = castObject;
|
||||
|
||||
this['NULL'] = wrapPointer(0);
|
||||
Module['NULL'] = wrapPointer(0);
|
||||
|
||||
function destroy(obj) {
|
||||
if (!obj['__destroy__']) throw 'Error: Cannot destroy object. (Did you create it yourself?)';
|
||||
obj['__destroy__']();
|
||||
// Remove from cache, so the object can be GC'd and refs added onto it released
|
||||
if (obj.__class__ !== Object) {
|
||||
delete obj.__class__.prototype.__cache__[obj.ptr];
|
||||
} else {
|
||||
delete Object__cache[obj.ptr];
|
||||
}
|
||||
}
|
||||
this['destroy'] = destroy;
|
||||
Module['destroy'] = destroy;
|
||||
|
||||
function compare(obj1, obj2) {
|
||||
return obj1.ptr === obj2.ptr;
|
||||
}
|
||||
this['compare'] = compare;
|
||||
Module['compare'] = compare;
|
||||
|
||||
function getPointer(obj) {
|
||||
return obj.ptr;
|
||||
}
|
||||
this['getPointer'] = getPointer;
|
||||
Module['getPointer'] = getPointer;
|
||||
|
||||
function getClass(obj) {
|
||||
return obj.__class__;
|
||||
}
|
||||
Module['getClass'] = getClass;
|
||||
|
||||
function customizeVTable(object, replacementPairs) {
|
||||
// Does not handle multiple inheritance
|
||||
|
||||
// Find out vtable size
|
||||
var vTable = getValue(object.ptr, 'void*');
|
||||
// This assumes our modification where we null-terminate vtables
|
||||
var size = 0;
|
||||
while (getValue(vTable + Runtime.QUANTUM_SIZE*size, 'void*')) {
|
||||
size++;
|
||||
}
|
||||
|
||||
// Prepare replacement lookup table and add replacements to FUNCTION_TABLE
|
||||
// There is actually no good way to do this! So we do the following hack:
|
||||
// We create a fake vtable with canary functions, to detect which actual
|
||||
// function is being called
|
||||
var vTable2 = _malloc(size*Runtime.QUANTUM_SIZE);
|
||||
setValue(object.ptr, vTable2, 'void*');
|
||||
var canaryValue;
|
||||
var functions = FUNCTION_TABLE.length;
|
||||
for (var i = 0; i < size; i++) {
|
||||
var index = FUNCTION_TABLE.length;
|
||||
(function(j) {
|
||||
FUNCTION_TABLE.push(function() {
|
||||
canaryValue = j;
|
||||
});
|
||||
})(i);
|
||||
FUNCTION_TABLE.push(0);
|
||||
setValue(vTable2 + Runtime.QUANTUM_SIZE*i, index, 'void*');
|
||||
}
|
||||
var args = [{ptr: 0}];
|
||||
replacementPairs.forEach(function(pair) {
|
||||
// We need the wrapper function that converts arguments to not fail. Keep adding arguments til it works.
|
||||
while(1) {
|
||||
try {
|
||||
pair['original'].apply(object, args);
|
||||
break;
|
||||
} catch(e) {
|
||||
args.push(args[0]);
|
||||
}
|
||||
}
|
||||
pair.originalIndex = getValue(vTable + canaryValue*Runtime.QUANTUM_SIZE, 'void*');
|
||||
});
|
||||
FUNCTION_TABLE = FUNCTION_TABLE.slice(0, functions);
|
||||
|
||||
// Do the replacements
|
||||
|
||||
var replacements = {};
|
||||
replacementPairs.forEach(function(pair) {
|
||||
var replacementIndex = FUNCTION_TABLE.length;
|
||||
FUNCTION_TABLE.push(pair['replacement']);
|
||||
FUNCTION_TABLE.push(0);
|
||||
replacements[pair.originalIndex] = replacementIndex;
|
||||
});
|
||||
|
||||
// Copy and modify vtable
|
||||
for (var i = 0; i < size; i++) {
|
||||
var value = getValue(vTable + Runtime.QUANTUM_SIZE*i, 'void*');
|
||||
if (value in replacements) value = replacements[value];
|
||||
setValue(vTable2 + Runtime.QUANTUM_SIZE*i, value, 'void*');
|
||||
}
|
||||
return object;
|
||||
}
|
||||
Module['customizeVTable'] = customizeVTable;
|
||||
''')
|
||||
|
||||
def generate_wrapping_code(classname):
|
||||
|
@ -411,7 +494,7 @@ def generate_class(generating_classname, classname, clazz): # TODO: deprecate ge
|
|||
# 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;
|
||||
gen_js.write('''Module['%s'] = %s;
|
||||
''' % (generating_classname_head, generating_classname_head))
|
||||
|
||||
for method in clazz['final_methods'].itervalues():
|
||||
|
@ -466,6 +549,8 @@ def generate_class(generating_classname, classname, clazz): # TODO: deprecate ge
|
|||
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)))
|
||||
def justtypes(args): # note: this ignores 'self'
|
||||
return map(lambda i: args[i]['type'], range(len(args)))
|
||||
|
||||
fullname = ('emscripten_bind_' + generating_classname + '__' + mname).replace('::', '__')
|
||||
generating_classname_suffixed = generating_classname
|
||||
|
@ -505,8 +590,7 @@ def generate_class(generating_classname, classname, clazz): # TODO: deprecate ge
|
|||
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(args)[:i])))
|
||||
|
||||
callprefix, actualmname, ', '.join(justargs(args)[:i])))
|
||||
gen_c.write('\n')
|
||||
gen_c.write('}')
|
||||
else:
|
||||
|
@ -564,6 +648,9 @@ def generate_class(generating_classname, classname, clazz): # TODO: deprecate ge
|
|||
|
||||
print 'Maekin:', classname, generating_classname, mname, mname_suffixed
|
||||
if constructor:
|
||||
calls += '''
|
||||
%s.prototype.__cache__[this.ptr] = this;
|
||||
this.__class__ = %s;''' % (mname_suffixed, mname_suffixed)
|
||||
if not dupe:
|
||||
js_text = '''
|
||||
function %s(%s) {
|
||||
|
@ -580,7 +667,7 @@ function %s(%s) {
|
|||
|
||||
if export:
|
||||
js_text += '''
|
||||
this['%s'] = %s;
|
||||
Module['%s'] = %s;
|
||||
''' % (mname_suffixed, mname_suffixed)
|
||||
|
||||
else:
|
||||
|
@ -675,6 +762,7 @@ 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])
|
||||
|
|
|
@ -17,10 +17,14 @@ Example uses:
|
|||
|
||||
* With configure, do something like
|
||||
|
||||
RANLIB=PATH/emmaken.py AR=PATH/emmaken.py CXX=PATH/emmaken.py CC=PATH/emmaken.py ./configure [options]
|
||||
EMMAKEN_JUST_CONFIGURE=1 RANLIB=PATH/emmaken.py AR=PATH/emmaken.py CXX=PATH/emmaken.py CC=PATH/emmaken.py ./configure [options]
|
||||
|
||||
where PATH is the path to this file.
|
||||
|
||||
EMMAKEN_JUST_CONFIGURE tells emmaken that it is being run in ./configure,
|
||||
so it should relay everything to gcc/g++. You should not define that when
|
||||
running make, of course.
|
||||
|
||||
* With CMake, the same command will work (with cmake instead of ./configure). You may also be
|
||||
able to do the following in your CMakeLists.txt:
|
||||
|
||||
|
@ -53,20 +57,21 @@ import sys
|
|||
import os
|
||||
import subprocess
|
||||
|
||||
print >> sys.stderr, 'emmaken.py: ', ' '.join(sys.argv)
|
||||
|
||||
abspath = os.path.abspath(os.path.dirname(__file__))
|
||||
def path_from_root(*pathelems):
|
||||
return os.path.join(os.path.sep, *(abspath.split(os.sep)[:-1] + list(pathelems)))
|
||||
exec(open(path_from_root('tools', 'shared.py'), 'r').read())
|
||||
|
||||
# If this is a CMake config, just do that
|
||||
# If this is a configure-type thing, just do that
|
||||
CONFIGURE_CONFIG = os.environ.get('EMMAKEN_JUST_CONFIGURE')
|
||||
CMAKE_CONFIG = 'CMakeFiles/cmTryCompileExec.dir' in ' '.join(sys.argv)# or 'CMakeCCompilerId' in ' '.join(sys.argv)
|
||||
if CMAKE_CONFIG:
|
||||
if CONFIGURE_CONFIG or CMAKE_CONFIG:
|
||||
compiler = 'g++' if 'CXXCompiler' in ' '.join(sys.argv) else 'gcc'
|
||||
exit(os.execvp(compiler, [compiler] + sys.argv[1:]))
|
||||
|
||||
try:
|
||||
print >> sys.stderr, 'emmaken.py: ', ' '.join(sys.argv)
|
||||
|
||||
#f=open('/dev/shm/tmp/waka.txt', 'a')
|
||||
#f.write('Args: ' + ' '.join(sys.argv) + '\nCMake? ' + str(CMAKE_CONFIG) + '\n')
|
||||
#f.close()
|
||||
|
@ -97,7 +102,6 @@ try:
|
|||
|
||||
if len(sys.argv) == 2 and 'conftest' not in ' '.join(sys.argv): # Avoid messing with configure, see below too
|
||||
# ranlib
|
||||
os.execvp(LLVM_DIS, ['-show-annotations', sys.argv[1]])
|
||||
sys.exit(0)
|
||||
if len(sys.argv) == 1 or sys.argv[1] in ['x', 't']:
|
||||
# noop ar
|
||||
|
@ -116,7 +120,7 @@ try:
|
|||
files.append(arg)
|
||||
if arg.endswith('.c'):
|
||||
use_cxx = False
|
||||
if arg.endswith(('.c', '.cc', '.cpp')):
|
||||
if arg.endswith(('.c', '.cc', '.cpp', '.dT')):
|
||||
use_linker = False
|
||||
if arg.endswith('.h'):
|
||||
header = True
|
||||
|
@ -130,8 +134,8 @@ try:
|
|||
assert use_linker, 'Linker should be used in this case'
|
||||
|
||||
if use_linker:
|
||||
call = LLVM_LINK
|
||||
newargs = []
|
||||
call = LLVM_LD
|
||||
newargs = ['-disable-opt']
|
||||
found_o = False
|
||||
i = 0
|
||||
while i < len(sys.argv)-1:
|
||||
|
@ -163,6 +167,7 @@ try:
|
|||
if not use_linker:
|
||||
newargs.append('-c')
|
||||
else:
|
||||
print >> sys.stderr, 'Just copy.'
|
||||
shutil.copy(sys.argv[-1], sys.argv[-2])
|
||||
exit(0)
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ exec(open(CONFIG_FILE, 'r').read())
|
|||
|
||||
CLANG=os.path.expanduser(os.path.join(LLVM_ROOT, 'clang++'))
|
||||
LLVM_LINK=os.path.join(LLVM_ROOT, 'llvm-link')
|
||||
LLVM_LD=os.path.join(LLVM_ROOT, 'llvm-ld')
|
||||
LLVM_OPT=os.path.expanduser(os.path.join(LLVM_ROOT, 'opt'))
|
||||
LLVM_AS=os.path.expanduser(os.path.join(LLVM_ROOT, 'llvm-as'))
|
||||
LLVM_DIS=os.path.expanduser(os.path.join(LLVM_ROOT, 'llvm-dis'))
|
||||
|
@ -69,7 +70,7 @@ def line_splitter(data):
|
|||
|
||||
def limit_size(string, MAX=80*20):
|
||||
if len(string) < MAX: return string
|
||||
return string[0:MAX] + '...'
|
||||
return string[0:MAX/2] + '\n[..]\n' + string[-MAX/2:]
|
||||
|
||||
def pick_llvm_opts(optimization_level, optimize_size, allow_nonportable=False, use_aa=False):
|
||||
opts = []
|
||||
|
|
Загрузка…
Ссылка в новой задаче