Merge remote-tracking branch 'origin/incoming' into merge-mar-13-2015
This commit is contained in:
Коммит
6d7cd58175
1
AUTHORS
1
AUTHORS
|
@ -180,4 +180,5 @@ a license to everyone to use it as detailed in LICENSE.)
|
|||
* Matt McCormick <matt.mccormick@kitware.com>
|
||||
* Thaddée Tyl <thaddee.tyl@gmail.com>
|
||||
* Philipp Wiesemann <philipp.wiesemann@arcor.de>
|
||||
* Jan Jongboom <janjongboom@gmail.com> (copyright owned by Telenor Digital AS)
|
||||
|
||||
|
|
34
emcc
34
emcc
|
@ -976,10 +976,25 @@ try:
|
|||
shared.Settings.ASM_JS = 2
|
||||
|
||||
if shared.Settings.POINTER_MASKING:
|
||||
logging.warning('POINTER_MASKING is experimental')
|
||||
size = shared.Settings.POINTER_MASKING + 1 # size plus 1 should be a power of 2
|
||||
if size & (size-1) != 0:
|
||||
raise Exception('POINTER_MASKING value must be a power of 2 minus 1')
|
||||
if shared.Settings.ALLOW_MEMORY_GROWTH:
|
||||
raise Exception('With POINTER_MASKING the ALLOW_MEMORY_GROWTH feature is not supported')
|
||||
if not shared.Settings.POINTER_MASKING_DYNAMIC:
|
||||
shared.Settings.POINTER_MASKING_DEFAULT_ENABLED = 1;
|
||||
size = shared.Settings.TOTAL_MEMORY
|
||||
if size & (size - 1) != 0:
|
||||
raise Exception('With POINTER_MASKING the TOTAL_MEMORY must be a power of 2')
|
||||
if shared.Settings.ASM_JS:
|
||||
# Silently keep the total length a valid asm.js heap buffer length.
|
||||
overflow = shared.Settings.POINTER_MASKING_OVERFLOW;
|
||||
if overflow > 0:
|
||||
if size <= 0x01000000:
|
||||
shared.Settings.POINTER_MASKING_OVERFLOW = size;
|
||||
else:
|
||||
shared.Settings.POINTER_MASKING_OVERFLOW = (overflow + 0x00ffffff) & 0xff000000;
|
||||
elif shared.Settings.POINTER_MASKING_DYNAMIC:
|
||||
raise Exception('POINTER_MASKING_DYNAMIC requires POINTER_MASKING')
|
||||
else:
|
||||
shared.Settings.POINTER_MASKING_DEFAULT_ENABLED = 0
|
||||
|
||||
assert shared.LLVM_TARGET in shared.COMPILER_OPTS
|
||||
if shared.LLVM_TARGET == 'i386-pc-linux-gnu':
|
||||
|
@ -1504,10 +1519,11 @@ try:
|
|||
# add explicit label setting, as we will run aggressiveVariableElimination late, *after* 'label' is no longer notable by name
|
||||
js_optimizer_queue += ['safeLabelSetting']
|
||||
|
||||
if shared.Settings.EMTERPRETIFY:
|
||||
# add explicit label setting, as we will run aggressiveVariableElimination late, *after* 'label' is no longer notable by name
|
||||
js_optimizer_queue += ['safeLabelSetting']
|
||||
if shared.Settings.EMTERPRETIFY:
|
||||
# add explicit label setting, as we will run aggressiveVariableElimination late, *after* 'label' is no longer notable by name
|
||||
js_optimizer_queue += ['safeLabelSetting']
|
||||
|
||||
if opt_level >= 1 and js_opts:
|
||||
if opt_level >= 2:
|
||||
if shared.Settings.RELOOP and not shared.Settings.ASM_JS:
|
||||
js_optimizer_queue += ['optimizeShiftsAggressive', get_eliminate()] # aggressive shifts optimization requires loops, it breaks on switches
|
||||
|
@ -1556,7 +1572,8 @@ try:
|
|||
else:
|
||||
js_optimizer_queue += ['registerize']
|
||||
|
||||
if shared.Settings.POINTER_MASKING and shared.Settings.ASM_JS: js_optimizer_queue += ['pointerMasking']
|
||||
if shared.Settings.POINTER_MASKING:
|
||||
js_optimizer_queue += ['pointerMasking']
|
||||
|
||||
if not shared.Settings.EMTERPRETIFY:
|
||||
do_minify()
|
||||
|
@ -1597,6 +1614,7 @@ try:
|
|||
js_target = unsuffixed(target) + '.js'
|
||||
|
||||
if shared.Settings.EMTERPRETIFY:
|
||||
flush_js_optimizer_queue()
|
||||
logging.debug('emterpretifying')
|
||||
assert memory_init_file, 'emterpreter requires a mem init file'
|
||||
import json
|
||||
|
|
|
@ -1268,7 +1268,11 @@ function jsCall_%s_%s(%s) {
|
|||
|
||||
if settings['POINTER_MASKING']:
|
||||
for i in [0, 1, 2, 3]:
|
||||
asm_global_vars += ' var MASK%d=%d;\n' % (i, (settings['TOTAL_MEMORY']-1) & (~((2**i)-1)));
|
||||
if settings['POINTER_MASKING_DYNAMIC']:
|
||||
asm_global_vars += ' const MASK%d=env' % i + access_quote('MASK%d' % i) + '|0;\n';
|
||||
basic_vars += ['MASK%d' %i]
|
||||
else:
|
||||
asm_global_vars += ' const MASK%d=%d;\n' % (i, (settings['TOTAL_MEMORY']-1) & (~((2**i)-1)));
|
||||
|
||||
# sent data
|
||||
the_global = '{ ' + ', '.join(['"' + math_fix(s) + '": ' + s for s in fundamentals]) + ' }'
|
||||
|
@ -1379,7 +1383,12 @@ function _emscripten_replace_memory(newBuffer) {
|
|||
buffer = newBuffer;
|
||||
return true;
|
||||
}
|
||||
'''] + ['''
|
||||
'''] + \
|
||||
['' if not settings['POINTER_MASKING'] or settings['POINTER_MASKING_DYNAMIC'] else '''
|
||||
function _declare_heap_length() {
|
||||
return HEAP8[%s] | 0;
|
||||
}
|
||||
''' % (settings['TOTAL_MEMORY'] + settings['POINTER_MASKING_OVERFLOW'] - 1)] + ['''
|
||||
// EMSCRIPTEN_START_FUNCS
|
||||
function stackAlloc(size) {
|
||||
size = size|0;
|
||||
|
|
|
@ -3378,7 +3378,6 @@ LibraryManager.library = {
|
|||
if ((ret | 0) == 32) ret = ret + (Math_clz32(l) | 0) | 0;
|
||||
tempRet0 = 0;
|
||||
return ret | 0;
|
||||
#endif
|
||||
},
|
||||
|
||||
llvm_cttz_i32__deps: [function() {
|
||||
|
|
|
@ -1312,7 +1312,6 @@ mergeInto(LibraryManager.library, {
|
|||
},
|
||||
|
||||
emscripten_worker_respond_provisionally: function(data, size) {
|
||||
if (!inWorkerCall) throw 'not in worker call!';
|
||||
if (workerResponded) throw 'already responded with final response!';
|
||||
postMessage({
|
||||
'callbackId': workerCallbackId,
|
||||
|
@ -1322,7 +1321,6 @@ mergeInto(LibraryManager.library, {
|
|||
},
|
||||
|
||||
emscripten_worker_respond: function(data, size) {
|
||||
if (!inWorkerCall) throw 'not in worker call!';
|
||||
if (workerResponded) throw 'already responded with final response!';
|
||||
workerResponded = true;
|
||||
postMessage({
|
||||
|
|
|
@ -97,7 +97,7 @@ mergeInto(LibraryManager.library, {
|
|||
while (FS.isLink(current.mode)) {
|
||||
var link = FS.readlink(current_path);
|
||||
current_path = PATH.resolve(PATH.dirname(current_path), link);
|
||||
|
||||
|
||||
var lookup = FS.lookupPath(current_path, { recurse_count: opts.recurse_count });
|
||||
current = lookup.node;
|
||||
|
||||
|
@ -427,7 +427,7 @@ mergeInto(LibraryManager.library, {
|
|||
// we employ a simple trick: the pointer to a stream is its fd plus 1. This
|
||||
// means that all valid streams have a valid non-zero pointer while allowing
|
||||
// the fs for stdin to be the standard value of zero.
|
||||
//
|
||||
//
|
||||
//
|
||||
getStreamFromPtr: function(ptr) {
|
||||
return FS.streams[ptr - 1];
|
||||
|
@ -838,7 +838,7 @@ mergeInto(LibraryManager.library, {
|
|||
if (!link.node_ops.readlink) {
|
||||
throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
|
||||
}
|
||||
return link.node_ops.readlink(link);
|
||||
return PATH.resolve(FS.getPath(lookup.node.parent), link.node_ops.readlink(link));
|
||||
},
|
||||
stat: function(path, dontFollow) {
|
||||
var lookup = FS.lookupPath(path, { follow: !dontFollow });
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
mergeInto(LibraryManager.library, {
|
||||
$NODEFS__deps: ['$FS', '$PATH'],
|
||||
$NODEFS__postset: 'if (ENVIRONMENT_IS_NODE) { var fs = require("fs"); NODEFS.staticInit(); }',
|
||||
$NODEFS__postset: 'if (ENVIRONMENT_IS_NODE) { var fs = require("fs"); var NODEJS_PATH = require("path"); NODEFS.staticInit(); }',
|
||||
$NODEFS: {
|
||||
isWindows: false,
|
||||
staticInit: function() {
|
||||
|
@ -24,7 +24,7 @@ mergeInto(LibraryManager.library, {
|
|||
try {
|
||||
stat = fs.lstatSync(path);
|
||||
if (NODEFS.isWindows) {
|
||||
// On Windows, directories return permission bits 'rw-rw-rw-', even though they have 'rwxrwxrwx', so
|
||||
// On Windows, directories return permission bits 'rw-rw-rw-', even though they have 'rwxrwxrwx', so
|
||||
// propagate write bits to execute bits.
|
||||
stat.mode = stat.mode | ((stat.mode & 146) >> 1);
|
||||
}
|
||||
|
@ -203,7 +203,9 @@ mergeInto(LibraryManager.library, {
|
|||
readlink: function(node) {
|
||||
var path = NODEFS.realPath(node);
|
||||
try {
|
||||
return fs.readlinkSync(path);
|
||||
path = fs.readlinkSync(path);
|
||||
path = NODEJS_PATH.relative(NODEJS_PATH.resolve(node.mount.opts.root), path);
|
||||
return path;
|
||||
} catch (e) {
|
||||
if (!e.code) throw e;
|
||||
throw new FS.ErrnoError(ERRNO_CODES[e.code]);
|
||||
|
|
|
@ -57,8 +57,10 @@ function preprocess(text) {
|
|||
ret += '\n' + preprocess(included) + '\n'
|
||||
}
|
||||
} else if (line[2] == 'l') { // else
|
||||
assert(showStack.length > 0);
|
||||
showStack.push(!showStack.pop());
|
||||
} else if (line[2] == 'n') { // endif
|
||||
assert(showStack.length > 0);
|
||||
showStack.pop();
|
||||
} else {
|
||||
throw "Unclear preprocessor command: " + line;
|
||||
|
|
|
@ -300,7 +300,7 @@ function messageResender() {
|
|||
}
|
||||
|
||||
var buffer = 0, bufferSize = 0;
|
||||
var inWorkerCall = false, workerResponded = false, workerCallbackId = -1;
|
||||
var workerResponded = false, workerCallbackId = -1;
|
||||
|
||||
onmessage = function onmessage(msg) {
|
||||
// if main has not yet been called (mem init file, other async things), buffer messages
|
||||
|
@ -326,7 +326,6 @@ onmessage = function onmessage(msg) {
|
|||
HEAPU8.set(data, buffer);
|
||||
}
|
||||
|
||||
inWorkerCall = true;
|
||||
workerResponded = false;
|
||||
workerCallbackId = msg.data['callbackId'];
|
||||
if (data) {
|
||||
|
@ -334,7 +333,6 @@ onmessage = function onmessage(msg) {
|
|||
} else {
|
||||
func(0, 0);
|
||||
}
|
||||
inWorkerCall = false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1329,9 +1329,49 @@ try {
|
|||
|
||||
var TOTAL_STACK = Module['TOTAL_STACK'] || {{{ TOTAL_STACK }}};
|
||||
var TOTAL_MEMORY = Module['TOTAL_MEMORY'] || {{{ TOTAL_MEMORY }}};
|
||||
var FAST_MEMORY = Module['FAST_MEMORY'] || {{{ FAST_MEMORY }}};
|
||||
|
||||
#if ASM_JS
|
||||
#if POINTER_MASKING
|
||||
|
||||
#if POINTER_MASKING_DYNAMIC
|
||||
var POINTER_MASKING_ENABLED = Module['POINTER_MASKING_DEFAULT_ENABLED'] || {{{ POINTER_MASKING_DEFAULT_ENABLED }}};
|
||||
var POINTER_MASKING_OVERFLOW = Module['POINTER_MASKING_OVERFLOW'] || {{{ POINTER_MASKING_OVERFLOW }}}
|
||||
var MASK0 = -1, MASK1 = -1, MASK2 = -1, MASK3 = -1;
|
||||
function initPointerMasking() {
|
||||
var totalMemory = 64*1024;
|
||||
while (totalMemory < TOTAL_MEMORY || totalMemory < 2*TOTAL_STACK) {
|
||||
if (POINTER_MASKING_ENABLED || totalMemory < 16*1024*1024) {
|
||||
totalMemory *= 2;
|
||||
} else {
|
||||
totalMemory += 16*1024*1024
|
||||
}
|
||||
}
|
||||
if (totalMemory !== TOTAL_MEMORY) {
|
||||
Module.printErr('increasing TOTAL_MEMORY to ' + totalMemory + ' to be compliant with the asm.js spec (and given that TOTAL_STACK=' + TOTAL_STACK + ')');
|
||||
TOTAL_MEMORY = totalMemory;
|
||||
}
|
||||
// Silently keep the total length a valid asm.js heap buffer length.
|
||||
if (POINTER_MASKING_OVERFLOW > 0) {
|
||||
if (TOTAL_MEMORY <= 0x01000000) {
|
||||
POINTER_MASKING_OVERFLOW = TOTAL_MEMORY;
|
||||
} else {
|
||||
POINTER_MASKING_OVERFLOW = (POINTER_MASKING_OVERFLOW + 0x00ffffff) & 0xff000000;
|
||||
}
|
||||
}
|
||||
MASK0 = POINTER_MASKING_ENABLED ? TOTAL_MEMORY - 1 : -1;
|
||||
MASK1 = POINTER_MASKING_ENABLED ? (TOTAL_MEMORY - 1) & ~1 : -1;
|
||||
MASK2 = POINTER_MASKING_ENABLED ? (TOTAL_MEMORY - 1) & ~3 : -1;
|
||||
MASK3 = POINTER_MASKING_ENABLED ? (TOTAL_MEMORY - 1) & ~7 : -1;
|
||||
}
|
||||
initPointerMasking();
|
||||
#else // POINTER_MASKING_DYNAMIC
|
||||
var totalMemory = 64*1024;
|
||||
while (totalMemory < TOTAL_MEMORY || totalMemory < 2*TOTAL_STACK) {
|
||||
totalMemory *= 2;
|
||||
}
|
||||
#endif // POINTER_MASKING_DYNAMIC
|
||||
|
||||
#else // POINTER_MASKING
|
||||
|
||||
var totalMemory = 64*1024;
|
||||
while (totalMemory < TOTAL_MEMORY || totalMemory < 2*TOTAL_STACK) {
|
||||
if (totalMemory < 16*1024*1024) {
|
||||
|
@ -1347,7 +1387,9 @@ if (totalMemory !== TOTAL_MEMORY) {
|
|||
Module.printErr('increasing TOTAL_MEMORY to ' + totalMemory + ' to be compliant with the asm.js spec (and given that TOTAL_STACK=' + TOTAL_STACK + ')');
|
||||
TOTAL_MEMORY = totalMemory;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // POINTER_MASKING
|
||||
|
||||
|
||||
// Initialize the runtime's memory
|
||||
#if USE_TYPED_ARRAYS
|
||||
|
@ -1362,8 +1404,19 @@ IHEAPU = new Uint32Array(IHEAP.buffer);
|
|||
FHEAP = new Float64Array(TOTAL_MEMORY);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if USE_TYPED_ARRAYS == 2
|
||||
#if POINTER_MASKING
|
||||
#if POINTER_MASKING_DYNAMIC
|
||||
var buffer = new ArrayBuffer(TOTAL_MEMORY + (POINTER_MASKING_ENABLED ? POINTER_MASKING_OVERFLOW : 0));
|
||||
#else
|
||||
var buffer = new ArrayBuffer(TOTAL_MEMORY + {{{ POINTER_MASKING_OVERFLOW }}});
|
||||
#endif
|
||||
#else
|
||||
var buffer = new ArrayBuffer(TOTAL_MEMORY);
|
||||
#endif // POINTER_MASKING
|
||||
#endif // USE_TYPED_ARRAYS == 2
|
||||
|
||||
HEAP8 = new Int8Array(buffer);
|
||||
HEAP16 = new Int16Array(buffer);
|
||||
HEAP32 = new Int32Array(buffer);
|
||||
|
@ -1376,14 +1429,7 @@ HEAPF64 = new Float64Array(buffer);
|
|||
// Endianness check (note: assumes compiler arch was little-endian)
|
||||
HEAP32[0] = 255;
|
||||
assert(HEAPU8[0] === 255 && HEAPU8[3] === 0, 'Typed arrays 2 must be run on a little-endian system');
|
||||
#endif
|
||||
#else
|
||||
// Make sure that our HEAP is implemented as a flat array.
|
||||
HEAP = []; // Hinting at the size with |new Array(TOTAL_MEMORY)| should help in theory but makes v8 much slower
|
||||
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
|
||||
}
|
||||
#endif
|
||||
#endif // USE_TYPED_ARRAYS
|
||||
|
||||
Module['HEAP'] = HEAP;
|
||||
#if USE_TYPED_ARRAYS == 1
|
||||
|
|
|
@ -61,6 +61,7 @@ var KeyboardEvent = {
|
|||
function PropertyBag() {
|
||||
this.addProperty = function(){};
|
||||
this.removeProperty = function(){};
|
||||
this.setProperty = function(){};
|
||||
};
|
||||
|
||||
var IndexedObjects = {
|
||||
|
@ -295,6 +296,11 @@ Audio.prototype.cloneNode = function() {
|
|||
return new Audio;
|
||||
}
|
||||
|
||||
var screen = {
|
||||
width: 0,
|
||||
height: 0
|
||||
};
|
||||
|
||||
Module.canvas = document.createElement('canvas');
|
||||
|
||||
Module.setStatus = function(){};
|
||||
|
@ -397,8 +403,8 @@ onmessage = function onmessage(message) {
|
|||
}
|
||||
case 'worker-init': {
|
||||
Module.canvas = document.createElement('canvas');
|
||||
Module.canvas.width_ = message.data.width;
|
||||
Module.canvas.height_ = message.data.height;
|
||||
screen.width = Module.canvas.width_ = message.data.width;
|
||||
screen.height = Module.canvas.height_ = message.data.height;
|
||||
document.URL = message.data.URL;
|
||||
window.fireEvent({ type: 'load' });
|
||||
removeRunDependency('worker-init');
|
||||
|
|
|
@ -58,8 +58,6 @@ var TOTAL_STACK = 5*1024*1024; // The total stack size. There is no way to enlar
|
|||
var TOTAL_MEMORY = 16777216; // The total amount of memory to use. Using more memory than this will
|
||||
// cause us to expand the heap, which can be costly with typed arrays:
|
||||
// we need to copy the old heap into a new one in that case.
|
||||
var 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.
|
||||
var ALLOW_MEMORY_GROWTH = 0; // If false, we abort with an error if we try to allocate more memory than
|
||||
// we can (TOTAL_MEMORY). If true, we will grow the memory arrays at
|
||||
// runtime, seamlessly and dynamically. This has a performance cost though,
|
||||
|
@ -190,8 +188,26 @@ var OUTLINING_LIMIT = 0; // A function size above which we try to automatically
|
|||
|
||||
var AGGRESSIVE_VARIABLE_ELIMINATION = 0; // Run aggressiveVariableElimination in js-optimizer.js
|
||||
var SIMPLIFY_IFS = 1; // Whether to simplify ifs in js-optimizer.js
|
||||
var POINTER_MASKING = 0; // Whether to mask pointers (experimental optimization trying to reduce VM bounds checks).
|
||||
// When using this option, TOTAL_MEMORY must be a power of 2.
|
||||
|
||||
var POINTER_MASKING = 0; // Whether pointers can be masked to a power-of-two heap
|
||||
// length. An experimental optimization trying to reduce VM
|
||||
// bounds checks.
|
||||
var POINTER_MASKING_OVERFLOW = 64 * 1024; // The length added to the heap length to allow
|
||||
// the compiler to derive that accesses are
|
||||
// within bounds even when adding small constant
|
||||
// offsets. This defaults to 64K, but in asm.js
|
||||
// mode it is silently adjusted to keep the
|
||||
// total buffer length a valid asm.js heap
|
||||
// buffer length.
|
||||
var POINTER_MASKING_DYNAMIC = 0; // When disabled, the masking is baked into the code with
|
||||
// static masks and a static heap buffer length and the
|
||||
// TOTAL_MEMORY must be a power of 2. When enabled, the
|
||||
// masks are defined at runtime rather than compling them
|
||||
// into the asm.js module as literal constants and the
|
||||
// TOTAL_MEMORY can be defined at run time.
|
||||
var POINTER_MASKING_DEFAULT_ENABLED = 1; // When POINTER_MASKING_DYNAMIC is enabled this
|
||||
// sets the default for POINTER_MASKING_ENABLED,
|
||||
// enabling or disabling pointer masking.
|
||||
|
||||
// Generated code debugging options
|
||||
var SAFE_HEAP = 0; // Check each write to the heap, for example, this will give a clear
|
||||
|
@ -614,6 +630,8 @@ var EMTERPRETIFY_ADVISE = 0; // Performs a static analysis to suggest which func
|
|||
// appears they can be on the stack when a sync function is called in the EMTERPRETIFY_ASYNC option.
|
||||
// After showing the suggested list, compilation will halt. You can apply the provided list as an
|
||||
// emcc argument when compiling later.
|
||||
// This will also advise on the YIELDLIST, if it contains at least one value (it then reports
|
||||
// all things reachable from that function, as they may need to be in the YIELDLIST as well).
|
||||
// Note that this depends on things like inlining. If you run this with different inlining than
|
||||
// when you use the list, it might not work.
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
@echo off
|
||||
python "%~dp0\sdl-config" %*
|
|
@ -0,0 +1,2 @@
|
|||
@echo off
|
||||
python "%~dp0\sdl2-config" %*
|
|
@ -44,7 +44,7 @@
|
|||
setTimeout(function() {
|
||||
var secondImage = Module.canvas.toDataURL();
|
||||
reportResult(firstImage != secondImage);
|
||||
}, 0);
|
||||
}, 500);
|
||||
}
|
||||
Module.postRun = doTest;
|
||||
|
||||
|
|
|
@ -25,8 +25,9 @@ void main_loop()
|
|||
if (ret > 0) puts(str);
|
||||
}
|
||||
|
||||
int err = ferror(stdin);
|
||||
if (ferror(stdin) && errno != EAGAIN) {
|
||||
puts("error");
|
||||
printf("error %d\n", err);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
function z1() {
|
||||
var i = 0, j = 0;
|
||||
print(i);
|
||||
}
|
||||
function z2() {
|
||||
var i = 0, label = 0;
|
||||
label = 0;
|
||||
print(i);
|
||||
}
|
||||
function z3() {
|
||||
var i = 0, label = 0;
|
||||
}
|
||||
function z4() {
|
||||
var label = 0;
|
||||
label = 0;
|
||||
print(0);
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
function z1() {
|
||||
var i = 0, j = 0;
|
||||
print(i);
|
||||
}
|
||||
function z2() {
|
||||
var i = 0, label = 0;
|
||||
print(i);
|
||||
}
|
||||
function z3() {
|
||||
var i = 0, label = 0;
|
||||
}
|
||||
function z4() {
|
||||
var label = 0;
|
||||
print(0);
|
||||
}
|
||||
// EMSCRIPTEN_GENERATED_FUNCTIONS: ["z1", "z2", "z3", "z4"]
|
||||
|
|
@ -1,72 +1,72 @@
|
|||
function f() {
|
||||
HEAP8[x >> 0];
|
||||
HEAP8[(x & MASK0) >> 0];
|
||||
HEAP8[(x & MASK0) + 1 >> 0];
|
||||
HEAP8[(x & MASK0) + 2 >> 0];
|
||||
HEAP8[(x + 1 & MASK0) + 2 >> 0];
|
||||
HEAP8[(x + 2 & MASK0) + 2 >> 0];
|
||||
HEAP8[(x + 1 + y & MASK0) + 2 >> 0];
|
||||
HEAP8[(x + 2 + y & MASK0) + 2 >> 0];
|
||||
HEAP8[(x & MASK0) + 3 >> 0];
|
||||
HEAP8[(x & MASK0) + 4 >> 0];
|
||||
HEAP8[(x + y & MASK0) + 3 >> 0];
|
||||
HEAP8[(x + y & MASK0) + 4 >> 0];
|
||||
x();
|
||||
HEAP16[x >> 1];
|
||||
HEAP16[x + 1 >> 1];
|
||||
HEAP16[(x & MASK1) >> 1];
|
||||
HEAP16[(x + 1 & MASK1) >> 1];
|
||||
HEAP16[(x & MASK1) + 2 >> 1];
|
||||
HEAP16[(x + 1 & MASK1) + 2 >> 1];
|
||||
HEAP16[(x + 2 & MASK1) + 2 >> 1];
|
||||
HEAP16[(x & MASK1) + 4 >> 1];
|
||||
HEAP16[(x + 1 + y & MASK1) + 2 >> 1];
|
||||
HEAP16[(x + 2 + y & MASK1) + 2 >> 1];
|
||||
HEAP16[(x + y & MASK1) + 4 >> 1];
|
||||
HEAP16[(x + 1 + y & MASK1) + 4 >> 1];
|
||||
HEAP16[(x + 2 + y & MASK1) + 4 >> 1];
|
||||
HEAP16[(x + y & MASK1) + 6 >> 1];
|
||||
HEAP16[(x + 1 + y & MASK1) + 4 >> 1];
|
||||
HEAP16[(x + 4 + y & MASK1) + 2 >> 1];
|
||||
HEAP16[(x + y & MASK1) + 6 >> 1];
|
||||
x();
|
||||
HEAP32[x >> 2];
|
||||
HEAP32[x + 1 >> 2];
|
||||
HEAP32[x + 2 >> 2];
|
||||
HEAP32[x + 3 >> 2];
|
||||
HEAP32[(x & MASK2) >> 2];
|
||||
HEAP32[(x + 1 & MASK2) >> 2];
|
||||
HEAP32[(x + 2 & MASK2) >> 2];
|
||||
HEAP32[(x + 3 & MASK2) >> 2];
|
||||
HEAP32[(x & MASK2) + 4 >> 2];
|
||||
HEAP32[(x + 1 & MASK2) + 4 >> 2];
|
||||
HEAP32[(x + 4 & MASK2) + 4 >> 2];
|
||||
HEAP32[(x & MASK2) + 8 >> 2];
|
||||
HEAP32[(x + 1 + y & MASK2) + 4 >> 2];
|
||||
HEAP32[(x + 4 + y & MASK2) + 4 >> 2];
|
||||
HEAP32[(x + y & MASK2) + 8 >> 2];
|
||||
HEAP32[(x + 1 + y & MASK2) + 8 >> 2];
|
||||
HEAP32[(x + 4 + y & MASK2) + 8 >> 2];
|
||||
HEAP32[(x + y & MASK2) + 12 >> 2];
|
||||
HEAP32[(x + 1 + y & MASK2) + 8 >> 2];
|
||||
HEAP32[(x + 8 + y & MASK2) + 4 >> 2];
|
||||
HEAP32[(x + y & MASK2) + 12 >> 2];
|
||||
x();
|
||||
HEAPU32[x >> 2];
|
||||
HEAPU32[x + 1 >> 2];
|
||||
HEAPU32[(x & MASK2) >> 2];
|
||||
HEAPU32[(x + 1 & MASK2) >> 2];
|
||||
HEAPU32[(x & MASK2) + 4 >> 2];
|
||||
HEAPU32[(x + 1 & MASK2) + 4 >> 2];
|
||||
HEAPU32[(x + 4 & MASK2) + 4 >> 2];
|
||||
HEAPU32[(x & MASK2) + 8 >> 2];
|
||||
HEAPU32[(x + 1 + y & MASK2) + 4 >> 2];
|
||||
HEAPU32[(x + 4 + y & MASK2) + 4 >> 2];
|
||||
HEAPU32[(x + y & MASK2) + 8 >> 2];
|
||||
HEAPU32[(x + 1 + y & MASK2) + 8 >> 2];
|
||||
HEAPU32[(x + 4 + y & MASK2) + 8 >> 2];
|
||||
HEAPU32[(x + y & MASK2) + 12 >> 2];
|
||||
HEAPU32[(x + 1 + y & MASK2) + 8 >> 2];
|
||||
HEAPU32[(x + 8 + y & MASK2) + 4 >> 2];
|
||||
HEAPU32[(x + y & MASK2) + 12 >> 2];
|
||||
x();
|
||||
HEAPF32[x >> 2];
|
||||
HEAPF32[x + 1 >> 2];
|
||||
HEAPF32[(x & MASK2) >> 2];
|
||||
HEAPF32[(x + 1 & MASK2) >> 2];
|
||||
HEAPF32[(x & MASK2) + 4 >> 2];
|
||||
HEAPF32[(x + 1 & MASK2) + 4 >> 2];
|
||||
HEAPF32[(x + 4 & MASK2) + 4 >> 2];
|
||||
HEAPF32[(x & MASK2) + 8 >> 2];
|
||||
HEAPF32[(x + 1 + y & MASK2) + 4 >> 2];
|
||||
HEAPF32[(x + 4 + y & MASK2) + 4 >> 2];
|
||||
HEAPF32[(x + y & MASK2) + 8 >> 2];
|
||||
HEAPF32[(x + 1 + y & MASK2) + 8 >> 2];
|
||||
HEAPF32[(x + 4 + y & MASK2) + 8 >> 2];
|
||||
HEAPF32[(x + y & MASK2) + 12 >> 2];
|
||||
HEAPF32[(x + 1 + y & MASK2) + 8 >> 2];
|
||||
HEAPF32[(x + 8 + y & MASK2) + 4 >> 2];
|
||||
HEAPF32[(x + y & MASK2) + 12 >> 2];
|
||||
x();
|
||||
HEAPF64[x >> 3];
|
||||
HEAPF64[x + 1 >> 3];
|
||||
HEAPF64[(x & MASK3) >> 3];
|
||||
HEAPF64[(x + 1 & MASK3) >> 3];
|
||||
HEAPF64[(x & MASK3) + 8 >> 3];
|
||||
HEAPF64[(x + 1 & MASK3) + 8 >> 3];
|
||||
HEAPF64[(x + 8 & MASK3) + 8 >> 3];
|
||||
HEAPF64[(x & MASK3) + 16 >> 3];
|
||||
HEAPF64[(x + 1 + y & MASK3) + 8 >> 3];
|
||||
HEAPF64[(x + 8 + y & MASK3) + 8 >> 3];
|
||||
HEAPF64[(x + y & MASK3) + 16 >> 3];
|
||||
HEAPF64[(x + 1 + y & MASK3) + 16 >> 3];
|
||||
HEAPF64[(x + 8 + y & MASK3) + 16 >> 3];
|
||||
HEAPF64[(x + y & MASK3) + 24 >> 3];
|
||||
HEAPF64[(x + 1 + y & MASK3) + 16 >> 3];
|
||||
HEAPF64[(x + 16 + y & MASK3) + 8 >> 3];
|
||||
HEAPF64[(x + y & MASK3) + 24 >> 3];
|
||||
}
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ process(sys.argv[1])
|
|||
'-O3', '-s', 'DOUBLE_MODE=0', '-s', 'PRECISE_I64_MATH=0',
|
||||
'--memory-init-file', '0', '--js-transform', 'python hardcode.py',
|
||||
'-s', 'TOTAL_MEMORY=128*1024*1024',
|
||||
#'--profiling',
|
||||
'--profiling',
|
||||
#'--closure', '1',
|
||||
'-o', final] + shared_args + emcc_args + self.extra_args, stdout=PIPE, stderr=PIPE, env=self.env).communicate()
|
||||
assert os.path.exists(final), 'Failed to compile file: ' + output[0]
|
||||
|
@ -136,6 +136,7 @@ try:
|
|||
#NativeBenchmarker(default_native_name, os.path.join(default_native, 'clang'), os.path.join(default_native, 'clang++')),
|
||||
#NativeBenchmarker('clang', CLANG_CC, CLANG),
|
||||
#NativeBenchmarker('clang-3.6', os.path.join(LLVM_3_6, 'clang'), os.path.join(LLVM_3_6, 'clang++')),
|
||||
#NativeBenchmarker(default_native_name, os.path.join(default_native, 'clang'), os.path.join(default_native, 'clang++')),
|
||||
#NativeBenchmarker('clang-3.2-O3', os.path.join(default_native, 'clang'), os.path.join(default_native, 'clang++'), ['-O3']),
|
||||
#NativeBenchmarker('clang-3.3', os.path.join(LLVM_3_3, 'clang'), os.path.join(LLVM_3_3, 'clang++')),
|
||||
#NativeBenchmarker('clang-3.4', os.path.join(LLVM_3_4, 'clang'), os.path.join(LLVM_3_4, 'clang++')),
|
||||
|
|
|
@ -9,6 +9,8 @@ if emscripten_browser:
|
|||
cmd = shlex.split(emscripten_browser)
|
||||
def run_in_other_browser(url):
|
||||
Popen(cmd + [url])
|
||||
if EM_BUILD_VERBOSE_LEVEL >= 3:
|
||||
print >> sys.stderr, "using Emscripten browser: " + str(cmd)
|
||||
webbrowser.open_new = run_in_other_browser
|
||||
|
||||
def test_chunked_synchronous_xhr_server(support_byte_ranges, chunkSize, data, checksum):
|
||||
|
@ -1936,6 +1938,10 @@ void *getBindBuffer() {
|
|||
Popen([PYTHON, EMCC, path_from_root('tests', 'worker_api_3_worker.cpp'), '-o', 'worker.js', '-s', 'BUILD_AS_WORKER=1', '-s', 'EXPORTED_FUNCTIONS=["_one"]']).communicate()
|
||||
self.btest('worker_api_3_main.cpp', expected='5')
|
||||
|
||||
def test_worker_api_sleep(self):
|
||||
Popen([PYTHON, EMCC, path_from_root('tests', 'worker_api_worker_sleep.cpp'), '-o', 'worker.js', '-s', 'BUILD_AS_WORKER=1', '-s', 'EXPORTED_FUNCTIONS=["_one"]', '-s', 'EMTERPRETIFY=1', '-s', 'EMTERPRETIFY_ASYNC=1']).communicate()
|
||||
self.btest('worker_api_main.cpp', expected='566')
|
||||
|
||||
def test_emscripten_async_wget2(self):
|
||||
self.btest('http.cpp', expected='0', args=['-I' + path_from_root('tests')])
|
||||
|
||||
|
|
|
@ -4794,6 +4794,22 @@ def process(filename):
|
|||
Building.COMPILER_TEST_OPTS = orig_compiler_opts + ['-D' + fs]
|
||||
self.do_run(src, expected, js_engines=[NODE_JS])
|
||||
|
||||
def test_unistd_symlink_on_nodefs(self):
|
||||
self.clear()
|
||||
if not self.is_emscripten_abi(): return self.skip('asmjs-unknown-emscripten needed for inline js')
|
||||
orig_compiler_opts = Building.COMPILER_TEST_OPTS[:]
|
||||
for fs in ['NODEFS']:
|
||||
if WINDOWS and fs == 'NODEFS':
|
||||
print >> sys.stderr, 'Skipping NODEFS part of this test for test_unistd_symlink_on_nodefs on Windows, since it would require administrative privileges.'
|
||||
# Also, other detected discrepancies if you do end up running this test on NODEFS:
|
||||
# test expects /, but Windows gives \ as path slashes.
|
||||
# Calling readlink() on a non-link gives error 22 EINVAL on Unix, but simply error 0 OK on Windows.
|
||||
continue
|
||||
src = open(path_from_root('tests', 'unistd', 'symlink_on_nodefs.c'), 'r').read()
|
||||
expected = open(path_from_root('tests', 'unistd', 'symlink_on_nodefs.out'), 'r').read()
|
||||
Building.COMPILER_TEST_OPTS = orig_compiler_opts + ['-D' + fs]
|
||||
self.do_run(src, expected, js_engines=[NODE_JS])
|
||||
|
||||
def test_unistd_sleep(self):
|
||||
src = open(path_from_root('tests', 'unistd', 'sleep.c'), 'r').read()
|
||||
expected = open(path_from_root('tests', 'unistd', 'sleep.out'), 'r').read()
|
||||
|
@ -5554,10 +5570,18 @@ def process(filename):
|
|||
|
||||
Settings.CORRECT_SIGNS = 1
|
||||
|
||||
use_cmake_configure = WINDOWS
|
||||
if use_cmake_configure:
|
||||
make_args = []
|
||||
configure = [PYTHON, path_from_root('emcmake'), 'cmake', '.', '-DBUILD_SHARED_LIBS=OFF']
|
||||
else:
|
||||
make_args = ['libz.a']
|
||||
configure = ['sh', './configure']
|
||||
|
||||
self.do_run(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']),
|
||||
includes=[path_from_root('tests', 'zlib')],
|
||||
libraries=self.get_library('zlib', os.path.join('libz.a'), make_args=make_args, configure=configure),
|
||||
includes=[path_from_root('tests', 'zlib'), os.path.join(self.get_dir(), 'building', 'zlib')],
|
||||
force_c=True)
|
||||
|
||||
def test_the_bullet(self): # Called thus so it runs late in the alphabetical cycle... it is long
|
||||
|
@ -7367,15 +7391,16 @@ def make_run(fullname, name=-1, compiler=-1, embetter=0, quantum_size=0,
|
|||
TT = type(fullname, (T,), dict(run_name = fullname, env = env))
|
||||
|
||||
def tearDown(self):
|
||||
super(TT, self).tearDown()
|
||||
try:
|
||||
super(TT, self).tearDown()
|
||||
finally:
|
||||
for k, v in self.env.iteritems():
|
||||
del os.environ[k]
|
||||
|
||||
for k, v in self.env.iteritems():
|
||||
del os.environ[k]
|
||||
|
||||
# clear global changes to Building
|
||||
Building.COMPILER_TEST_OPTS = []
|
||||
Building.COMPILER = CLANG
|
||||
Building.LLVM_OPTS = 0
|
||||
# clear global changes to Building
|
||||
Building.COMPILER_TEST_OPTS = []
|
||||
Building.COMPILER = CLANG
|
||||
Building.LLVM_OPTS = 0
|
||||
|
||||
TT.tearDown = tearDown
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ if emscripten_browser:
|
|||
cmd = shlex.split(emscripten_browser)
|
||||
def run_in_other_browser(url):
|
||||
Popen(cmd + [url])
|
||||
if EM_BUILD_VERBOSE_LEVEL >= 3:
|
||||
print >> sys.stderr, "using Emscripten browser: " + str(cmd)
|
||||
webbrowser.open_new = run_in_other_browser
|
||||
|
||||
class interactive(BrowserCore):
|
||||
|
|
|
@ -418,18 +418,18 @@ f.close()
|
|||
try:
|
||||
os.chdir(tempdirname)
|
||||
|
||||
verbose_level = int(os.getenv('EM_BUILD_VERBOSE')) if os.getenv('EM_BUILD_VERBOSE') != None else 0
|
||||
|
||||
# Run Cmake
|
||||
if invoke_method == 'cmake':
|
||||
# Test invoking cmake directly.
|
||||
cmd = ['cmake', '-DCMAKE_TOOLCHAIN_FILE='+path_from_root('cmake', 'Modules', 'Platform', 'Emscripten.cmake'),
|
||||
'-DCMAKE_BUILD_TYPE=' + configuration, cmake_arguments[i], '-G', generator, cmakelistsdir]
|
||||
env = tools.shared.Building.remove_sh_exe_from_path(os.environ)
|
||||
else:
|
||||
# Test invoking via 'emconfigure cmake'
|
||||
cmd = [emconfigure, 'cmake', '-DCMAKE_BUILD_TYPE=' + configuration, cmake_arguments[i], '-G', generator, cmakelistsdir]
|
||||
|
||||
ret = Popen(cmd, stdout=None if verbose_level >= 2 else PIPE, stderr=None if verbose_level >= 1 else PIPE).communicate()
|
||||
env = os.environ.copy()
|
||||
|
||||
ret = Popen(cmd, stdout=None if EM_BUILD_VERBOSE_LEVEL >= 2 else PIPE, stderr=None if EM_BUILD_VERBOSE_LEVEL >= 1 else PIPE, env=env).communicate()
|
||||
if len(ret) > 1 and ret[1] != None and len(ret[1].strip()) > 0:
|
||||
logging.error(ret[1]) # If there were any errors, print them directly to console for diagnostics.
|
||||
if len(ret) > 1 and ret[1] != None and 'error' in ret[1].lower():
|
||||
|
@ -442,9 +442,9 @@ f.close()
|
|||
|
||||
# Build
|
||||
cmd = make
|
||||
if verbose_level >= 3 and 'Ninja' not in generator:
|
||||
if EM_BUILD_VERBOSE_LEVEL >= 3 and 'Ninja' not in generator:
|
||||
cmd += ['VERBOSE=1']
|
||||
ret = Popen(cmd, stdout=None if verbose_level >= 2 else PIPE).communicate()
|
||||
ret = Popen(cmd, stdout=None if EM_BUILD_VERBOSE_LEVEL >= 2 else PIPE).communicate()
|
||||
if len(ret) > 1 and ret[1] != None and len(ret[1].strip()) > 0:
|
||||
logging.error(ret[1]) # If there were any errors, print them directly to console for diagnostics.
|
||||
if len(ret) > 0 and ret[0] != None and 'error' in ret[0].lower() and not '0 error(s)' in ret[0].lower():
|
||||
|
@ -1247,12 +1247,13 @@ int f() {
|
|||
|
||||
for engine in JS_ENGINES:
|
||||
if engine == V8_ENGINE: continue # no stdin support in v8 shell
|
||||
engine[0] = os.path.normpath(engine[0])
|
||||
print >> sys.stderr, engine
|
||||
# work around a bug in python's subprocess module
|
||||
# (we'd use run_js() normally)
|
||||
try_delete('out.txt')
|
||||
if os.name == 'nt': # windows
|
||||
os.system('type "in.txt" | {} >out.txt'.format(' '.join(make_js_command(exe, engine))))
|
||||
os.system('type "in.txt" | {} >out.txt'.format(' '.join(make_js_command(os.path.normpath(exe), engine))))
|
||||
else: # posix
|
||||
os.system('cat in.txt | {} > out.txt'.format(' '.join(make_js_command(exe, engine))))
|
||||
self.assertContained('abcdef\nghijkl\neof', open('out.txt').read())
|
||||
|
@ -2016,6 +2017,8 @@ int f() {
|
|||
['asm', 'eliminate', 'registerize', 'asmLastOpts', 'last']),
|
||||
(path_from_root('tests', 'optimizer', 'simd.js'), open(path_from_root('tests', 'optimizer', 'simd-output.js')).read(),
|
||||
['asm', 'eliminate']), # eliminate, just enough to trigger asm normalization/denormalization
|
||||
(path_from_root('tests', 'optimizer', 'safeLabelSetting.js'), open(path_from_root('tests', 'optimizer', 'safeLabelSetting-output.js')).read(),
|
||||
['asm', 'safeLabelSetting']), # eliminate, just enough to trigger asm normalization/denormalization
|
||||
]:
|
||||
print input, passes
|
||||
|
||||
|
@ -4606,6 +4609,13 @@ function _main() {
|
|||
|
||||
out, err = Popen([PYTHON, EMCC, path_from_root('tests', 'emterpreter_advise_funcptr.cpp'), '-s', 'EMTERPRETIFY=1', '-s', 'EMTERPRETIFY_ASYNC=1', '-s', 'EMTERPRETIFY_ADVISE=1'], stdout=PIPE).communicate()
|
||||
self.assertContained('-s EMTERPRETIFY_WHITELIST=\'["__Z4posti", "__Z5post2i", "__Z6middlev", "__Z7sleeperv", "__Z8recurserv", "_main"]\'', out)
|
||||
self.assertNotContained('EMTERPRETIFY_YIELDLIST', out);
|
||||
|
||||
out, err = Popen([PYTHON, EMCC, path_from_root('tests', 'emterpreter_advise_funcptr.cpp'), '-s', 'EMTERPRETIFY=1', '-s', 'EMTERPRETIFY_ASYNC=1', '-s', 'EMTERPRETIFY_ADVISE=1', '-s', 'EMTERPRETIFY_YIELDLIST=["__Z6middlev"]'], stdout=PIPE).communicate()
|
||||
self.assertContained('-s EMTERPRETIFY_YIELDLIST=\'["__Z6middlev", "__Z7siblingii", "__Z7sleeperv", "__Z8recurserv", "_printf"]\'', out)
|
||||
|
||||
out, err = Popen([PYTHON, EMCC, path_from_root('tests', 'emterpreter_advise_funcptr.cpp'), '-s', 'EMTERPRETIFY=1', '-s', 'EMTERPRETIFY_ASYNC=1', '-s', 'EMTERPRETIFY_ADVISE=1', '-s', 'EMTERPRETIFY_YIELDLIST=["__Z3pref"]'], stdout=PIPE).communicate()
|
||||
self.assertContained('-s EMTERPRETIFY_YIELDLIST=\'["__Z3pref", "__Z7siblingii", "_printf"]\'', out)
|
||||
|
||||
def test_link_with_a_static(self):
|
||||
for args in [[], ['-O2']]:
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
readlink(link)
|
||||
ret: 17
|
||||
ret: 7
|
||||
errno: 0
|
||||
result: ../test/../there!
|
||||
result: /there!
|
||||
|
||||
readlink(file)
|
||||
ret: -1
|
||||
errno: 22
|
||||
result: ../test/../there!
|
||||
result: /there!
|
||||
|
||||
readlink(folder)
|
||||
ret: -1
|
||||
errno: 22
|
||||
result: ../test/../there!
|
||||
result: /there!
|
||||
|
||||
symlink/overwrite
|
||||
ret: -1
|
||||
|
@ -21,11 +21,11 @@ symlink/normal
|
|||
ret: 0
|
||||
errno: 0
|
||||
readlink(created link)
|
||||
ret: 20
|
||||
ret: 36
|
||||
errno: 0
|
||||
result: new-nonexistent-path
|
||||
result: /working/folder/new-nonexistent-path
|
||||
|
||||
readlink(short buffer)
|
||||
ret: 3
|
||||
errno: 0
|
||||
result: ../-nonexistent-path
|
||||
result: /thrking/folder/new-nonexistent-path
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <emscripten.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main() {
|
||||
EM_ASM(
|
||||
fs.mkdirSync('./new-directory', '0777');
|
||||
fs.writeFileSync('./new-directory/test', 'Link it');
|
||||
fs.symlinkSync(fs.realpathSync('./new-directory'), './symlink');
|
||||
|
||||
FS.mkdir('working');
|
||||
FS.mount(NODEFS, { root: '.' }, 'working');
|
||||
|
||||
FS.mkdir('direct-link');
|
||||
FS.mount(NODEFS, { root: './symlink' }, 'direct-link');
|
||||
);
|
||||
|
||||
{
|
||||
char* path = "/working/symlink/test";
|
||||
printf("reading %s\n", path);
|
||||
|
||||
FILE* fd = fopen(path, "r");
|
||||
if (fd == NULL) {
|
||||
printf("failed to open file %s\n", path);
|
||||
}
|
||||
else {
|
||||
char buffer[8];
|
||||
fread(buffer, 1, 7, fd);
|
||||
printf("buffer is %s\n", buffer);
|
||||
fclose(fd);
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
{
|
||||
char* path = "/direct-link/test";
|
||||
printf("reading %s\n", path);
|
||||
|
||||
FILE* fd = fopen(path, "r");
|
||||
if (fd != NULL) {
|
||||
// This should not happen, it resolves to ../new-directory which is not mounted
|
||||
printf("opened file %s\n", path);
|
||||
fclose(fd);
|
||||
}
|
||||
else {
|
||||
printf("failed to open file %s\n", path);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
reading /working/symlink/test
|
||||
buffer is Link it
|
||||
|
||||
reading /direct-link/test
|
||||
failed to open file /direct-link/test
|
|
@ -0,0 +1,17 @@
|
|||
#include <assert.h>
|
||||
#include <emscripten.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
void one(char *data, int size) {
|
||||
int *x = (int*)data;
|
||||
int num = size/sizeof(int);
|
||||
for (int i = 0; i < num; i++) {
|
||||
x[i] += 1234;
|
||||
}
|
||||
emscripten_sleep(1000);
|
||||
emscripten_worker_respond(data, size);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -706,6 +706,8 @@ if __name__ == '__main__':
|
|||
outfile = sys.argv[2]
|
||||
force_memfile = sys.argv[3] if len(sys.argv) >= 4 else None
|
||||
|
||||
original_yieldlist = YIELDLIST
|
||||
|
||||
extra_blacklist = []
|
||||
if len(sys.argv) >= 5:
|
||||
temp = sys.argv[4]
|
||||
|
@ -775,6 +777,23 @@ if __name__ == '__main__':
|
|||
print "Suggested list of functions to run in the emterpreter:"
|
||||
print " -s EMTERPRETIFY_WHITELIST='" + str(sorted(list(advised))).replace("'", '"') + "'"
|
||||
print "(%d%% out of %d functions)" % (int((100.0*len(advised))/len(can_call)), len(can_call))
|
||||
if len(YIELDLIST) > len(original_yieldlist):
|
||||
# advise on the yield list as well. Anything a yield function can reach, likely needs to also be a yield function
|
||||
YIELD_IGNORE = set(['abort'])
|
||||
to_check = list(YIELDLIST)
|
||||
advised = set([str(f) for f in YIELDLIST])
|
||||
while len(to_check) > 0:
|
||||
curr = to_check.pop()
|
||||
if curr not in can_call: continue
|
||||
for next in can_call[curr]:
|
||||
if next not in advised:
|
||||
advised.add(str(next))
|
||||
to_check.append(next)
|
||||
advised = [next for next in advised if not is_dyn_call(next) and not is_function_table(next) and not next in original_yieldlist and next not in SYNC_FUNCS and next not in YIELD_IGNORE and next[0] == '_']
|
||||
print
|
||||
print "Suggested list of yield functions for the emterpreter:"
|
||||
print " -s EMTERPRETIFY_YIELDLIST='" + str(sorted(list(advised))).replace("'", '"') + "'"
|
||||
print "(%d%% out of %d functions)" % (int((100.0*len(advised))/len(can_call)), len(can_call))
|
||||
sys.exit(0)
|
||||
|
||||
BLACKLIST = set(list(BLACKLIST) + extra_blacklist)
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// -*- Mode: javascript; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 ; js-indent-level : 2 ; js-curly-indent-offset: 0 -*-
|
||||
// vim: set ts=2 et sw=2 tw=80:
|
||||
|
||||
//==============================================================================
|
||||
// Optimizer tool. This is meant to be run after the emscripten compiler has
|
||||
// finished generating code. These optimizations are done on the generated
|
||||
|
@ -1090,7 +1093,7 @@ function safeLabelSetting(ast) {
|
|||
seenVar = true;
|
||||
} else if (seenVar && curr[0] !== 'var') {
|
||||
// first location after the vars
|
||||
stats.splice(i+1, 0, ['stat', ['assign', true, ['name', 'label'], ['num', 0]]]);
|
||||
stats.splice(i, 0, ['stat', ['assign', true, ['name', 'label'], ['num', 0]]]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -6071,46 +6074,63 @@ function optimizeFrounds(ast) {
|
|||
traverseChildren(ast, fix);
|
||||
}
|
||||
|
||||
// Optimize heap expressions into HEAP32[(x&m)+c>>2] where c is a small aligned constant, and m guarantees the pointer is without range+aligned
|
||||
// Optimize heap expressions into HEAP32[(x&m)+c>>2] where c is an aligned
|
||||
// constant, and m guarantees the pointer is within bounds and aligned.
|
||||
function pointerMasking(ast) {
|
||||
var MAX_SMALL_OFFSET = 32;
|
||||
var parseHeapTemp = makeTempParseHeap();
|
||||
|
||||
traverse(ast, function(node, type) {
|
||||
if (type === 'sub' && node[1][0] === 'name' && node[1][1][0] === 'H' && node[2][0] === 'binary' && node[2][1] === '>>' && node[2][3][0] === 'num') {
|
||||
var addee = node[2][2];
|
||||
if (!(addee[0] === 'binary' && addee[1] === '+')) return;
|
||||
var shifts = node[2][3][1];
|
||||
if (!parseHeap(node[1][1])) return;
|
||||
if (parseHeapTemp.bits !== 8*Math.pow(2, shifts)) return;
|
||||
// this is an HEAP[U]N[x + y >> n] expression. gather up all the top-level added items, seek a small constant amongst them
|
||||
var addee = node[2][2];
|
||||
|
||||
if (!parseHeap(node[1][1], parseHeapTemp)) return;
|
||||
if (parseHeapTemp.bits !== 8 * Math.pow(2, shifts)) return;
|
||||
|
||||
// Don't mask a shifted constant index. It will be folded later,
|
||||
// and it is assumed that they are within bounds.
|
||||
if (addee[0] === 'num') return;
|
||||
|
||||
if (!(addee[0] === 'binary' && addee[1] === '+')) {
|
||||
node[2][2] = ['binary', '&', addee, ['name', 'MASK' + shifts]];
|
||||
return;
|
||||
}
|
||||
|
||||
// This is a HEAP[U]N[x + y >> n] expression. Gather up all the top-level
|
||||
// added items, summing constants amongst them.
|
||||
var addedConstants = 0;
|
||||
var addedElements = [];
|
||||
function addElements(node) {
|
||||
if (node[0] === 'binary' && node[1] === '+') {
|
||||
addElements(node[2]);
|
||||
addElements(node[3]);
|
||||
} else if (node[0] === 'num') {
|
||||
var c = node[1];
|
||||
// Check that it is aligned.
|
||||
if (((c >> shifts) << shifts) === c) {
|
||||
addedConstants += c;
|
||||
} else {
|
||||
addedElements.push(node);
|
||||
}
|
||||
} else {
|
||||
addedElements.push(node);
|
||||
}
|
||||
}
|
||||
addElements(addee);
|
||||
assert(addedElements.length >= 2);
|
||||
for (var i = 0; i < addedElements.length; i++) {
|
||||
var element = addedElements[i];
|
||||
if (element[0] === 'num') {
|
||||
var c = element[1];
|
||||
if (c < MAX_SMALL_OFFSET && ((c >> shifts) << shifts) === c) {
|
||||
// this is a small aligned offset, we are good to go. gather the others, and finalize
|
||||
addedElements.splice(i, 1);
|
||||
var others = addedElements[0];
|
||||
for (var j = 1; j < addedElements.length; j++) {
|
||||
others = ['binary', '+', others, addedElements[j]];
|
||||
}
|
||||
others = ['binary', '&', others, ['name', 'MASK' + shifts]];
|
||||
node[2][2] = ['binary', '+', others, element];
|
||||
return;
|
||||
}
|
||||
if (addedElements.length > 0) {
|
||||
var others = addedElements[0];
|
||||
for (var j = 1; j < addedElements.length; j++) {
|
||||
others = ['binary', '+', others, addedElements[j]];
|
||||
}
|
||||
others = ['binary', '&', others, ['name', 'MASK' + shifts]];
|
||||
if (addedConstants != 0) {
|
||||
others = ['binary', '+', others, ['num' , addedConstants]];
|
||||
}
|
||||
node[2][2] = others;
|
||||
return;
|
||||
}
|
||||
|
||||
node[2][2] = ['num' , addedConstants];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -263,8 +263,7 @@ def run_on_chunk(command):
|
|||
while os.path.exists(saved): saved = 'input' + str(int(saved.replace('input', '').replace('.txt', ''))+1) + '.txt'
|
||||
print >> sys.stderr, 'running js optimizer command', ' '.join(map(lambda c: c if c != filename else saved, command))
|
||||
shutil.copyfile(filename, os.path.join('/tmp/emscripten_temp', saved))
|
||||
verbose_level = int(os.getenv('EM_BUILD_VERBOSE')) if os.getenv('EM_BUILD_VERBOSE') != None else 0
|
||||
if verbose_level >= 3: print >> sys.stderr, str(command)
|
||||
if shared.EM_BUILD_VERBOSE_LEVEL >= 3: print >> sys.stderr, 'run_on_chunk: ' + str(command)
|
||||
proc = subprocess.Popen(command, stdout=subprocess.PIPE)
|
||||
output = proc.communicate()[0]
|
||||
assert proc.returncode == 0, 'Error in optimizer: ' + output
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import os, shutil, logging
|
||||
|
||||
TAG = 'version_5'
|
||||
TAG = 'version_6'
|
||||
|
||||
def get_with_configure(ports, settings, shared): # not currently used; no real need for configure on emscripten users' machines!
|
||||
if settings.USE_SDL == 2:
|
||||
|
|
|
@ -297,6 +297,13 @@ if EM_POPEN_WORKAROUND and os.name == 'nt':
|
|||
logging.debug('Installing Popen workaround handler to avoid bug http://bugs.python.org/issue3905')
|
||||
Popen = WindowsPopen
|
||||
|
||||
# Verbosity level control for any intermediate subprocess spawns from the compiler. Useful for internal debugging.
|
||||
# 0: disabled.
|
||||
# 1: Log stderr of subprocess spawns.
|
||||
# 2: Log stdout and stderr of subprocess spawns. Print out subprocess commands that were executed.
|
||||
# 3: Log stdout and stderr, and pass VERBOSE=1 to CMake configure steps.
|
||||
EM_BUILD_VERBOSE_LEVEL = int(os.getenv('EM_BUILD_VERBOSE')) if os.getenv('EM_BUILD_VERBOSE') != None else 0
|
||||
|
||||
# Expectations
|
||||
|
||||
EXPECTED_LLVM_VERSION = (3, 6)
|
||||
|
@ -1068,6 +1075,17 @@ class Building:
|
|||
|
||||
return None
|
||||
|
||||
# Returns a clone of the given environment with all directories that contain sh.exe removed from the PATH.
|
||||
# Used to work around CMake limitation with MinGW Makefiles, where sh.exe is not allowed to be present.
|
||||
@staticmethod
|
||||
def remove_sh_exe_from_path(env):
|
||||
env = env.copy()
|
||||
if not WINDOWS: return env
|
||||
path = env['PATH'].split(';')
|
||||
path = filter(lambda p: not os.path.exists(os.path.join(p, 'sh.exe')), path)
|
||||
env['PATH'] = ';'.join(path)
|
||||
return env
|
||||
|
||||
@staticmethod
|
||||
def handle_CMake_toolchain(args, env):
|
||||
|
||||
|
@ -1085,8 +1103,13 @@ class Building:
|
|||
# pulling in a native Visual Studio, or Unix Makefiles.
|
||||
if WINDOWS and not '-G' in args and Building.which('mingw32-make'):
|
||||
args += ['-G', 'MinGW Makefiles']
|
||||
|
||||
return args
|
||||
|
||||
# CMake has a requirement that it wants sh.exe off PATH if MinGW Makefiles is being used. This happens quite often,
|
||||
# so do this automatically on behalf of the user. See http://www.cmake.org/Wiki/CMake_MinGW_Compiler_Issues
|
||||
if WINDOWS and 'MinGW Makefiles' in args:
|
||||
env = Building.remove_sh_exe_from_path(env)
|
||||
|
||||
return (args, env)
|
||||
|
||||
@staticmethod
|
||||
def configure(args, stdout=None, stderr=None, env=None):
|
||||
|
@ -1097,13 +1120,14 @@ class Building:
|
|||
if 'cmake' in args[0]:
|
||||
# Note: EMMAKEN_JUST_CONFIGURE shall not be enabled when configuring with CMake. This is because CMake
|
||||
# does expect to be able to do config-time builds with emcc.
|
||||
args = Building.handle_CMake_toolchain(args, env)
|
||||
args, env = Building.handle_CMake_toolchain(args, env)
|
||||
else:
|
||||
# When we configure via a ./configure script, don't do config-time compilation with emcc, but instead
|
||||
# do builds natively with Clang. This is a heuristic emulation that may or may not work.
|
||||
env['EMMAKEN_JUST_CONFIGURE'] = '1'
|
||||
try:
|
||||
process = Popen(args, stdout=stdout, stderr=stderr, env=env)
|
||||
if EM_BUILD_VERBOSE_LEVEL >= 3: print >> sys.stderr, 'configure: ' + str(args)
|
||||
process = Popen(args, stdout=None if EM_BUILD_VERBOSE_LEVEL >= 2 else stdout, stderr=None if EM_BUILD_VERBOSE_LEVEL >= 1 else stderr, env=env)
|
||||
process.communicate()
|
||||
except Exception, e:
|
||||
logging.error('Exception thrown when invoking Popen in configure with args: "%s"!' % ' '.join(args))
|
||||
|
@ -1123,13 +1147,19 @@ class Building:
|
|||
#args += ['VERBOSE=1']
|
||||
|
||||
# On Windows prefer building with mingw32-make instead of make, if it exists.
|
||||
if WINDOWS and args[0] == 'make':
|
||||
mingw32_make = Building.which('mingw32-make')
|
||||
if mingw32_make:
|
||||
args[0] = mingw32_make
|
||||
if WINDOWS:
|
||||
if args[0] == 'make':
|
||||
mingw32_make = Building.which('mingw32-make')
|
||||
if mingw32_make:
|
||||
args[0] = mingw32_make
|
||||
|
||||
if 'mingw32-make' in args[0]:
|
||||
env = Building.remove_sh_exe_from_path(env)
|
||||
|
||||
try:
|
||||
process = Popen(args, stdout=stdout, stderr=stderr, env=env)
|
||||
# On Windows, run the execution through shell to get PATH expansion and executable extension lookup, e.g. 'sdl2-config' will match with 'sdl2-config.bat' in PATH.
|
||||
if EM_BUILD_VERBOSE_LEVEL >= 3: print >> sys.stderr, 'make: ' + str(args)
|
||||
process = Popen(args, stdout=None if EM_BUILD_VERBOSE_LEVEL >= 2 else stdout, stderr=None if EM_BUILD_VERBOSE_LEVEL >= 1 else stderr, env=env, shell=WINDOWS)
|
||||
process.communicate()
|
||||
except Exception, e:
|
||||
logging.error('Exception thrown when invoking Popen in make with args: "%s"!' % ' '.join(args))
|
||||
|
@ -1170,13 +1200,12 @@ class Building:
|
|||
# except:
|
||||
# pass
|
||||
env = Building.get_building_env(native)
|
||||
verbose_level = int(os.getenv('EM_BUILD_VERBOSE')) if os.getenv('EM_BUILD_VERBOSE') != None else 0
|
||||
for k, v in env_init.iteritems():
|
||||
env[k] = v
|
||||
if configure: # Useful in debugging sometimes to comment this out (and the lines below up to and including the |link| call)
|
||||
try:
|
||||
Building.configure(configure + configure_args, env=env, stdout=open(os.path.join(project_dir, 'configure_'), 'w') if verbose_level < 2 else None,
|
||||
stderr=open(os.path.join(project_dir, 'configure_err'), 'w') if verbose_level < 1 else None)
|
||||
Building.configure(configure + configure_args, env=env, stdout=open(os.path.join(project_dir, 'configure_'), 'w') if EM_BUILD_VERBOSE_LEVEL < 2 else None,
|
||||
stderr=open(os.path.join(project_dir, 'configure_err'), 'w') if EM_BUILD_VERBOSE_LEVEL < 1 else None)
|
||||
except subprocess.CalledProcessError, e:
|
||||
pass # Ignore exit code != 0
|
||||
def open_make_out(i, mode='r'):
|
||||
|
@ -1185,15 +1214,15 @@ class Building:
|
|||
def open_make_err(i, mode='r'):
|
||||
return open(os.path.join(project_dir, 'make_err' + str(i)), mode)
|
||||
|
||||
if verbose_level >= 3:
|
||||
if EM_BUILD_VERBOSE_LEVEL >= 3:
|
||||
make_args += ['VERBOSE=1']
|
||||
|
||||
for i in range(2): # FIXME: Sad workaround for some build systems that need to be run twice to succeed (e.g. poppler)
|
||||
with open_make_out(i, 'w') as make_out:
|
||||
with open_make_err(i, 'w') as make_err:
|
||||
try:
|
||||
Building.make(make + make_args, stdout=make_out if verbose_level < 2 else None,
|
||||
stderr=make_err if verbose_level < 1 else None, env=env)
|
||||
Building.make(make + make_args, stdout=make_out if EM_BUILD_VERBOSE_LEVEL < 2 else None,
|
||||
stderr=make_err if EM_BUILD_VERBOSE_LEVEL < 1 else None, env=env)
|
||||
except subprocess.CalledProcessError, e:
|
||||
pass # Ignore exit code != 0
|
||||
try:
|
||||
|
@ -1205,7 +1234,7 @@ class Building:
|
|||
break
|
||||
except Exception, e:
|
||||
if i > 0:
|
||||
if verbose_level == 0:
|
||||
if EM_BUILD_VERBOSE_LEVEL == 0:
|
||||
# Due to the ugly hack above our best guess is to output the first run
|
||||
with open_make_err(0) as ferr:
|
||||
for line in ferr:
|
||||
|
|
Загрузка…
Ссылка в новой задаче