Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'incoming'

  • Loading branch information...
commit ada59f0a9d23d8ec19ee6a1326977ddf6e93f5f9 2 parents 2f4401a + e97f48a
@kripken authored
View
2  emcc
@@ -1050,7 +1050,6 @@ try:
if not LEAVE_INPUTS_RAW:
link_opts = [] if keep_debug else ['-strip-debug']
if llvm_opts > 0:
- if DEBUG: print >> sys.stderr, 'emcc: LLVM -O%d' % llvm_opts
shared.Building.llvm_opt(in_temp(target_basename + '.bc'), llvm_opts)
if DEBUG: save_intermediate('opt', 'bc')
# Do LTO in a separate pass to work around LLVM bug XXX (see failure e.g. in cubescript)
@@ -1063,7 +1062,6 @@ try:
else:
# At minimum remove dead functions etc., this potentially saves a lot in the size of the generated code (and the time to compile it)
link_opts += shared.Building.get_safe_internalize() + ['-globaldce']
- if DEBUG: print >> sys.stderr, 'emcc: LLVM linktime:', link_opts
shared.Building.llvm_opt(in_temp(target_basename + '.bc'), link_opts)
if DEBUG: save_intermediate('linktime', 'bc')
View
32 src/compiler.html
@@ -5,16 +5,44 @@
<hr>
<pre id="output"></pre>
<script>
- arguments = ['', '../freetype.ll'];
- //arguments = ['', '../tests/cases/phicubed.ll'];
+ arguments = [];
var outputElement = document.getElementById('output');
+ var compilerOutput = '';
print = function(x) {
//outputElement.innerHTML += x;
+ compilerOutput += x;
+ };
+
+ // For generated code
+ var Module = {
+ print: function(x) {
+ outputElement.innerHTML += x;
+ }
};
</script>
<script src="compiler.js">
</script>
+<textarea id="the_input" cols=50 rows=30>
+; ModuleID = 'tests/hello_world.bc'
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128"
+target triple = "i386-pc-linux-gnu"
+
+@.str = private unnamed_addr constant [15 x i8] c"hello, world!\0A\00", align 1 ; [#uses=1 type=[15 x i8]*]
+
+; [#uses=0]
+define i32 @main() {
+entry:
+ %retval = alloca i32, align 4 ; [#uses=1 type=i32*]
+ store i32 0, i32* %retval
+ %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0)) ; [#uses=0 type=i32]
+ ret i32 1
+}
+
+; [#uses=1]
+declare i32 @printf(i8*, ...)
+</textarea>
+<input type="button" value="run!" onclick="compile(document.getElementById('the_input').value); eval(compilerOutput)">
</body>
</html>
View
84 src/compiler.js
@@ -76,10 +76,12 @@ if (ENVIRONMENT_IS_NODE) {
}
} else if (ENVIRONMENT_IS_WEB) {
- this['print'] = printErr = function(x) {
+ printErr = function(x) {
console.log(x);
};
+ if (!this['print']) this['print'] = printErr;
+
this['read'] = function(url) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, false);
@@ -213,42 +215,66 @@ NECESSARY_BLOCKADDRS = temp;
// Read llvm
-var raw = read(ll_file);
-if (FAKE_X86_FP80) {
- raw = raw.replace(/x86_fp80/g, 'double');
-}
-if (raw.search('\r\n') >= 0) {
- raw = raw.replace(/\r\n/g, '\n'); // fix windows line endings
-}
-var lines = raw.split('\n');
-raw = null;
+function compile(raw) {
+ if (FAKE_X86_FP80) {
+ raw = raw.replace(/x86_fp80/g, 'double');
+ }
+ if (raw.search('\r\n') >= 0) {
+ raw = raw.replace(/\r\n/g, '\n'); // fix windows line endings
+ }
+ var lines = raw.split('\n');
+ raw = null;
+
+ // Pre-process the LLVM assembly
+
+ Debugging.handleMetadata(lines);
-// Pre-process the LLVM assembly
+ function runPhase(currPhase) {
+ //printErr('// JS compiler in action, phase ' + currPhase + typeof lines + (lines === null));
+ phase = currPhase;
+ if (phase != 'pre') {
+ if (singlePhase) PassManager.load(read(forwardedDataFile));
-//printErr('JS compiler in action, phase ' + phase);
+ if (phase == 'funcs') {
+ PreProcessor.eliminateUnneededIntrinsics(lines);
+ }
+ }
-Debugging.handleMetadata(lines);
+ // Do it
-if (phase != 'pre') {
- PassManager.load(read(forwardedDataFile));
+ var intertyped = intertyper(lines);
+ if (singlePhase) lines = null;
+ var analyzed = analyzer(intertyped);
+ intertyped = null;
+ JSify(analyzed);
- if (phase == 'funcs') {
- PreProcessor.eliminateUnneededIntrinsics(lines);
+ phase = null;
+
+ if (DEBUG_MEMORY) {
+ print('zzz. last gc: ' + gc());
+ MemoryDebugger.dump();
+ print('zzz. hanging now!');
+ while(1){};
+ }
}
-}
-// Do it
+ // Normal operation is for each execution of compiler.js to run a single phase. The calling script sends us exactly the information we need, and it is easy to parallelize operation that way. However, it is also possible to run in an unoptimal multiphase mode, where a single invocation goes from ll to js directly. This is not recommended and will likely do a lot of duplicate processing.
+ singlePhase = !!phase;
-var intertyped = intertyper(lines);
-lines = null;
-var analyzed = analyzer(intertyped);
-intertyped = null;
-JSify(analyzed);
+ if (singlePhase) {
+ runPhase(phase);
+ } else {
+ runPhase('pre');
+ runPhase('funcs');
+ runPhase('post');
+ }
+}
-if (DEBUG_MEMORY) {
- print('zzz. last gc: ' + gc());
- MemoryDebugger.dump();
- print('zzz. hanging now!');
- while(1){};
+if (ll_file) {
+ if (ll_file.indexOf(String.fromCharCode(10)) == -1) {
+ compile(read(ll_file));
+ } else {
+ compile(ll_file); // we are given raw .ll
+ }
}
View
2  src/intertyper.js
@@ -61,7 +61,7 @@ function intertyper(data, sidePass, baseLineNums) {
var baseLineNumPosition = 0;
for (var i = 0; i < lines.length; i++) {
var line = lines[i];
- lines[i] = null; // lines may be very very large. Allow GCing to occur in the loop by releasing refs here
+ if (singlePhase) lines[i] = null; // lines may be very very large. Allow GCing to occur in the loop by releasing refs here
while (baseLineNumPosition < baseLineNums.length-1 && i >= baseLineNums[baseLineNumPosition+1][0]) {
baseLineNumPosition++;
View
13 src/jsifier.js
@@ -417,8 +417,8 @@ function JSify(data, functionsOnly, givenFunctions) {
// name the function; overwrite if it's already named
snippet = snippet.replace(/function(?:\s+([^(]+))?\s*\(/, 'function _' + ident + '(');
if (LIBRARY_DEBUG) {
- snippet = snippet.replace('{', '{ var ret = (function() { if (Runtime.debug) Module.printErr("[library call:' + ident + ': " + Array.prototype.slice.call(arguments).map(Runtime.prettyPrint) + "]"); ');
- snippet = snippet.substr(0, snippet.length-1) + '}).apply(this, arguments); if (Runtime.debug && typeof ret !== "undefined") Module.printErr(" [ return:" + Runtime.prettyPrint(ret)); return ret; }';
+ snippet = snippet.replace('{', '{ var ret = (function() { if (Runtime.debug) Module.print("[library call:' + ident + ': " + Array.prototype.slice.call(arguments).map(Runtime.prettyPrint) + "]"); ');
+ snippet = snippet.substr(0, snippet.length-1) + '}).apply(this, arguments); if (Runtime.debug && typeof ret !== "undefined") Module.print(" [ return:" + Runtime.prettyPrint(ret)); return ret; }';
}
}
@@ -1310,6 +1310,7 @@ function JSify(data, functionsOnly, givenFunctions) {
// Print out global variables and postsets TODO: batching
if (phase == 'pre') {
+ var legalizedI64sDefault = legalizedI64s;
legalizedI64s = false;
var globalsData = analyzer(intertyper(data.unparsedGlobalss[0].lines, true), true);
@@ -1332,9 +1333,13 @@ function JSify(data, functionsOnly, givenFunctions) {
var generated = itemsDict.functionStub.concat(itemsDict.GlobalVariablePostSet);
generated.forEach(function(item) { print(indentify(item.JS || '', 2)); });
+
+ legalizedI64s = legalizedI64sDefault;
} else {
- assert(data.unparsedGlobalss[0].lines.length == 0, dump([phase, data.unparsedGlobalss]));
- assert(itemsDict.functionStub.length == 0, dump([phase, itemsDict.functionStub]));
+ if (singlePhase) {
+ assert(data.unparsedGlobalss[0].lines.length == 0, dump([phase, data.unparsedGlobalss]));
+ assert(itemsDict.functionStub.length == 0, dump([phase, itemsDict.functionStub]));
+ }
}
if (phase == 'pre' || phase == 'funcs') {
View
141 src/library.js
@@ -611,7 +611,7 @@ LibraryManager.library = {
},
deleteFile: function(path) {
- var path = FS.analyzePath(path);
+ path = FS.analyzePath(path);
if (!path.parentExists || !path.exists) {
throw 'Invalid path ' + path;
}
@@ -3548,21 +3548,42 @@ LibraryManager.library = {
* this implementation simply uses malloc underneath the call to
* mmap.
*/
+ if (!_mmap.mappings) _mmap.mappings = {};
if (stream == -1) {
var ptr = _malloc(num);
- _memset(ptr, 0, num);
- return ptr;
+ } else {
+ var info = FS.streams[stream];
+ if (!info) return -1;
+ var contents = info.object.contents;
+ contents = Array.prototype.slice.call(contents, offset, offset+num);
+ ptr = allocate(contents, 'i8', ALLOC_NORMAL);
+ }
+ // align to page size
+ var ret = ptr;
+ if (ptr % PAGE_SIZE != 0) {
+ var old = ptr;
+ ptr = _malloc(num + PAGE_SIZE);
+ ret = alignMemoryPage(ptr);
+ _memcpy(ret, old, num);
+ _free(old);
}
- var info = FS.streams[stream];
- if (!info) return -1;
- var contents = info.object.contents;
- contents = Array.prototype.slice.call(contents, offset, offset+num);
- return allocate(contents, 'i8', ALLOC_NORMAL);
+ if (stream == -1) {
+ _memset(ret, 0, num);
+ }
+ _mmap.mappings[ret] = { malloc: ptr, num: num };
+ return ret;
},
__01mmap64_: 'mmap',
munmap: function(start, num) {
- _free(start);
+ if (!_mmap.mappings) _mmap.mappings = {};
+ // TODO: support unmmap'ing parts of allocations
+ var info = _mmap.mappings[start];
+ if (!info) return 0;
+ if (num == info.num) {
+ _mmap.mappings[start] = null;
+ _free(info.malloc);
+ }
return 0;
},
@@ -3816,9 +3837,73 @@ LibraryManager.library = {
return ret;
},
- strtoll__deps: ['_parseInt'],
+#if USE_TYPED_ARRAYS == 2
+ _parseInt64__deps: ['isspace', '__setErrNo', '$ERRNO_CODES', function() { Types.preciseI64MathUsed = 1 }],
+ _parseInt64: function(str, endptr, base, min, max, unsign) {
+ var start = str;
+ // Skip space.
+ while (_isspace({{{ makeGetValue('str', 0, 'i8') }}})) str++;
+
+ // Check for a plus/minus sign.
+ if ({{{ makeGetValue('str', 0, 'i8') }}} == '-'.charCodeAt(0)) {
+ str++;
+ } else if ({{{ makeGetValue('str', 0, 'i8') }}} == '+'.charCodeAt(0)) {
+ str++;
+ }
+
+ // Find base.
+ var ok = false;
+ var finalBase = base;
+ if (!finalBase) {
+ if ({{{ makeGetValue('str', 0, 'i8') }}} == '0'.charCodeAt(0)) {
+ if ({{{ makeGetValue('str+1', 0, 'i8') }}} == 'x'.charCodeAt(0) ||
+ {{{ makeGetValue('str+1', 0, 'i8') }}} == 'X'.charCodeAt(0)) {
+ finalBase = 16;
+ str += 2;
+ } else {
+ finalBase = 8;
+ str++;
+ ok = true; // we saw an initial zero, perhaps the entire thing is just "0"
+ }
+ }
+ }
+ if (!finalBase) finalBase = 10;
+
+ // Get digits.
+ var chr;
+ while ((chr = {{{ makeGetValue('str', 0, 'i8') }}}) != 0) {
+ var digit = parseInt(String.fromCharCode(chr), finalBase);
+ if (isNaN(digit)) {
+ break;
+ } else {
+ str++;
+ ok = true;
+ }
+ }
+ if (!ok) {
+ ___setErrNo(ERRNO_CODES.EINVAL);
+ return [0, 0];
+ }
+
+ try {
+ i64Math.fromString(Pointer_stringify(start, str - start), finalBase, min, max, unsign);
+ } catch(e) {
+ ___setErrNo(ERRNO_CODES.ERANGE); // not quite correct
+ }
+
+ // Set end pointer.
+ if (endptr) {
+ {{{ makeSetValue('endptr', 0, 'str', '*') }}}
+ }
+
+ var ret = i64Math.result.slice(0);
+
+ return ret;
+ },
+#endif
+ strtoll__deps: ['_parseInt64'],
strtoll: function(str, endptr, base) {
- return __parseInt(str, endptr, base, -9223372036854775200, 9223372036854775200, 64); // LLONG_MIN, LLONG_MAX; imprecise.
+ return __parseInt64(str, endptr, base, '-9223372036854775808', '9223372036854775807'); // LLONG_MIN, LLONG_MAX.
},
strtoll_l: 'strtoll', // no locale support yet
strtol__deps: ['_parseInt'],
@@ -3831,9 +3916,9 @@ LibraryManager.library = {
return __parseInt(str, endptr, base, 0, 4294967295, 32, true); // ULONG_MAX.
},
strtoul_l: 'strtoul', // no locale support yet
- strtoull__deps: ['_parseInt'],
+ strtoull__deps: ['_parseInt64'],
strtoull: function(str, endptr, base) {
- return __parseInt(str, endptr, base, 0, 18446744073709551615, 64, true); // ULONG_MAX; imprecise.
+ return __parseInt64(str, endptr, base, 0, '18446744073709551615', true); // ULONG_MAX.
},
strtoull_l: 'strtoull', // no locale support yet
@@ -4742,6 +4827,17 @@ LibraryManager.library = {
return ((x&0xff)<<24) | (((x>>8)&0xff)<<16) | (((x>>16)&0xff)<<8) | (x>>>24);
},
+ llvm_bswap_i64__deps: ['llvm_bswap_i32'],
+ llvm_bswap_i64: function(l, h) {
+ var retl = _llvm_bswap_i32(h)>>>0;
+ var reth = _llvm_bswap_i32(l)>>>0;
+#if USE_TYPED_ARRAYS == 2
+ return [retl, reth];
+#else
+ throw 'unsupported';
+#endif
+ },
+
llvm_ctlz_i32: function(x) {
for (var i=0; i<32; i++) {
if ( (x & (1 << (31-i))) != 0 ) {
@@ -4751,17 +4847,28 @@ LibraryManager.library = {
return 32;
},
+ llvm_ctlz_i64__deps: ['llvm_ctlz_i32'],
+ llvm_ctlz_i64: function(l, h) {
+ var ret = _llvm_ctlz_i32(h);
+ if (ret == 32) ret += _llvm_ctlz_i32(l);
+#if USE_TYPED_ARRAYS == 2
+ return [ret, 0];
+#else
+ return ret;
+#endif
+ },
+
llvm_trap: function() {
throw 'trap! ' + new Error().stack;
},
__assert_fail: function(condition, file, line) {
ABORT = true;
- throw 'Assertion failed: ' + Pointer_stringify(condition);//JSON.stringify(arguments)//condition;
+ throw 'Assertion failed: ' + Pointer_stringify(condition) + ' at ' + new Error().stack;
},
__assert_func: function(filename, line, func, condition) {
- throw 'Assertion failed: ' + (condition ? Pointer_stringify(condition) : 'unknown condition') + ', at: ' + [filename ? Pointer_stringify(filename) : 'unknown filename', line, func ? Pointer_stringify(func) : 'unknown function'];
+ throw 'Assertion failed: ' + (condition ? Pointer_stringify(condition) : 'unknown condition') + ', at: ' + [filename ? Pointer_stringify(filename) : 'unknown filename', line, func ? Pointer_stringify(func) : 'unknown function'] + ' at ' + new Error().stack;
},
__cxa_guard_acquire: function(variable) {
@@ -5105,8 +5212,8 @@ LibraryManager.library = {
return ret;
},
- llvm_expect_i32__inline: function(x, y) {
- return '((' + x + ')==(' + y + '))';
+ llvm_expect_i32__inline: function(val, expected) {
+ return '(' + val + ')';
},
llvm_lifetime_start: function() {},
View
19 src/library_browser.js
@@ -336,11 +336,11 @@ mergeInto(LibraryManager.library, {
xhr.send(null);
},
- asyncLoad: function(url, onload, onerror) {
+ asyncLoad: function(url, onload, onerror, noRunDep) {
Browser.xhrLoad(url, function(arrayBuffer) {
assert(arrayBuffer, 'Loading data file "' + url + '" failed (no arrayBuffer).');
onload(new Uint8Array(arrayBuffer));
- removeRunDependency('al ' + url);
+ if (!noRunDep) removeRunDependency('al ' + url);
}, function(event) {
if (onerror) {
onerror();
@@ -348,7 +348,7 @@ mergeInto(LibraryManager.library, {
throw 'Loading data file "' + url + '" failed.';
}
});
- addRunDependency('al ' + url);
+ if (!noRunDep) addRunDependency('al ' + url);
},
resizeListeners: [],
@@ -381,10 +381,21 @@ mergeInto(LibraryManager.library, {
},
function() {
if (onerror) FUNCTION_TABLE[onerror](file);
- }
+ }
);
},
+ emscripten_async_wget_data: function(url, arg, onload, onerror) {
+ Browser.asyncLoad(Pointer_stringify(url), function(byteArray) {
+ var buffer = _malloc(byteArray.length);
+ HEAPU8.set(byteArray, buffer);
+ FUNCTION_TABLE[onload](arg, buffer, byteArray.length);
+ _free(buffer);
+ }, function() {
+ if (onerror) FUNCTION_TABLE[onerror](arg);
+ }, true /* no need for run dependency, this is async but will not do any prepare etc. step */ );
+ },
+
emscripten_async_prepare: function(file, onload, onerror) {
var _file = Pointer_stringify(file);
var data = FS.analyzePath(_file);
View
45 src/long.js
@@ -1053,7 +1053,7 @@ var i64Math = (function() { // Emscripten wrapper
if(r != 0) return r;
var i = this.t;
r = i-a.t;
- if(r != 0) return r;
+ if(r != 0) return (this.s<0)?-r:r;
while(--i >= 0) if((r=this[i]-a[i]) != 0) return r;
return 0;
}
@@ -1552,9 +1552,15 @@ var i64Math = (function() { // Emscripten wrapper
Wrapper.result[0] = ret.low_;
Wrapper.result[1] = ret.high_;
},
- makeTwo32: function() {
+ ensureTemps: function() {
+ if (Wrapper.ensuredTemps) return;
+ Wrapper.ensuredTemps = true;
Wrapper.two32 = new BigInteger();
Wrapper.two32.fromString('4294967296', 10);
+ Wrapper.two64 = new BigInteger();
+ Wrapper.two64.fromString('18446744073709551616', 10);
+ Wrapper.temp1 = new BigInteger();
+ Wrapper.temp2 = new BigInteger();
},
lh2bignum: function(l, h) {
var a = new BigInteger();
@@ -1568,7 +1574,7 @@ var i64Math = (function() { // Emscripten wrapper
return d;
},
divide: function(xl, xh, yl, yh, unsigned) {
- if (!Wrapper.two32) Wrapper.makeTwo32();
+ Wrapper.ensureTemps();
if (!unsigned) {
var x = new goog.math.Long(xl, xh);
var y = new goog.math.Long(yl, yh);
@@ -1589,7 +1595,7 @@ var i64Math = (function() { // Emscripten wrapper
}
},
modulo: function(xl, xh, yl, yh, unsigned) {
- if (!Wrapper.two32) Wrapper.makeTwo32();
+ Wrapper.ensureTemps();
if (!unsigned) {
var x = new goog.math.Long(xl, xh);
var y = new goog.math.Long(yl, yh);
@@ -1613,10 +1619,7 @@ var i64Math = (function() { // Emscripten wrapper
var ret = new goog.math.Long(l, h).toString();
if (unsigned && ret[0] == '-') {
// unsign slowly using jsbn bignums
- if (!Wrapper.two64) {
- Wrapper.two64 = new BigInteger();
- Wrapper.two64.fromString('18446744073709551616', 10);
- }
+ Wrapper.ensureTemps();
var bignum = new BigInteger();
bignum.fromString(ret, 10);
ret = new BigInteger();
@@ -1624,6 +1627,32 @@ var i64Math = (function() { // Emscripten wrapper
ret = ret.toString(10);
}
return ret;
+ },
+ fromString: function(str, base, min, max, unsigned) {
+ Wrapper.ensureTemps();
+ var bignum = new BigInteger();
+ bignum.fromString(str, base);
+ var bigmin = new BigInteger();
+ bigmin.fromString(min, 10);
+ var bigmax = new BigInteger();
+ bigmax.fromString(max, 10);
+ if (unsigned && bignum.compareTo(BigInteger.ZERO) < 0) {
+ var temp = new BigInteger();
+ bignum.addTo(Wrapper.two64, temp);
+ bignum = temp;
+ }
+ var error = false;
+ if (bignum.compareTo(bigmin) < 0) {
+ bignum = bigmin;
+ error = true;
+ } else if (bignum.compareTo(bigmax) > 0) {
+ bignum = bigmax;
+ error = true;
+ }
+ var ret = goog.math.Long.fromString(bignum.toString()); // min-max checks should have clamped this to a range goog.math.Long can handle well
+ Wrapper.result[0] = ret.low_;
+ Wrapper.result[1] = ret.high_;
+ if (error) throw 'range error';
}
};
return Wrapper;
View
2  src/modules.js
@@ -269,7 +269,7 @@ var LibraryManager = {
loaded: false,
load: function() {
- assert(!this.library);
+ if (this.library) return;
var libraries = ['library.js', 'library_browser.js', 'library_sdl.js', 'library_gl.js', 'library_glut.js', 'library_xlib.js', 'library_egl.js', 'library_gc.js', 'library_jansson.js'].concat(additionalLibraries);
for (var i = 0; i < libraries.length; i++) {
View
24 system/include/emscripten/emscripten.h
@@ -187,6 +187,30 @@ float emscripten_random();
void emscripten_async_wget(const char* url, const char* file, void (*onload)(const char*), void (*onerror)(const char*));
/*
+ * Data version of emscripten_async_wget. Instead of writing
+ * to a file, it writes to a buffer directly in memory.
+ * This avoids the overhead of using the emulated
+ * filesystem, note however that since files are not used,
+ * It cannot do the 'prepare' stage to set things up for
+ * IMG_Load and so forth (IMG_Load etc. work on files).
+ *
+ * @param arg User-defined data that is passed to the callbacks,
+ *
+ * @param onload Callback on success, with the @arg that
+ * was provided to this function, a pointer
+ * to a buffer with the data, and the size
+ * of the buffer. As in the worker API, the
+ * data buffer only lives during the
+ * callback, so you should use it or copy
+ * it during that time and not later.
+ *
+ * @param onerror An optional callback on failure, with the
+ * @arg that was provided to this function.
+ *
+ */
+void emscripten_async_wget_data(const char* url, void *arg, void (*onload)(void*, void*, int), void (*onerror)(void*));
+
+/*
* Prepare a file in asynchronous way. This does just the
* preparation part of emscripten_async_wget, that is, it
* works on file data already present, and asynchronously
View
32 tests/emscripten_fs_api_browser.cpp
@@ -9,10 +9,42 @@ extern "C" {
int result = 1;
int get_count = 0;
+int data_ok = 0;
+int data_bad = 0;
+
+void onLoadedData(void *arg, void *buffer, int size) {
+ get_count++;
+ assert(size == 329895);
+ assert((int)arg == 135);
+ unsigned char *b = (unsigned char*)buffer;
+ assert(b[0] == 137);
+ assert(b[1122] == 128);
+ assert(b[1123] == 201);
+ assert(b[202125] == 218);
+ data_ok = 1;
+}
+
+void onErrorData(void *arg) {
+ get_count++;
+ assert((int)arg == 246);
+ data_bad = 1;
+}
void wait_wgets() {
if (get_count == 3) {
+ emscripten_async_wget_data(
+ "http://localhost:8888/screenshot.png",
+ (void*)135,
+ onLoadedData,
+ onErrorData);
+ emscripten_async_wget_data(
+ "http://localhost:8888/fail_me",
+ (void*)246,
+ onLoadedData,
+ onErrorData);
+ } else if (get_count == 5) {
assert(IMG_Load("/tmp/screen_shot.png"));
+ assert(data_ok == 1 && data_bad == 1);
emscripten_cancel_main_loop();
REPORT_RESULT();
}
View
37 tests/parseInt/output.txt
@@ -1,52 +1,50 @@
strtol("-9223372036854775809") = -2147483648
ERR 34
-strtoll("-9223372036854775809") = -9223372036854775000
+strtoll("-9223372036854775809") = -9223372036854775808
ERR 34
strtoul("-9223372036854775809") = 4294967295
ERR 34
-strtoull("-9223372036854775809") = 9223372036854774000
+strtoull("-9223372036854775809") = 9223372036854775807
strtol("-9223372036854775808") = -2147483648
ERR 34
-strtoll("-9223372036854775808") = -9223372036854775000
-ERR 34
+strtoll("-9223372036854775808") = -9223372036854775808
strtoul("-9223372036854775808") = 4294967295
ERR 34
-strtoull("-9223372036854775808") = 9223372036854774000
+strtoull("-9223372036854775808") = 9223372036854775808
strtol("-9223372036854775807") = -2147483648
ERR 34
-strtoll("-9223372036854775807") = -9223372036854775000
-ERR 34
+strtoll("-9223372036854775807") = -9223372036854775807
strtoul("-9223372036854775807") = 4294967295
ERR 34
-strtoull("-9223372036854775807") = 9223372036854774000
+strtoull("-9223372036854775807") = 9223372036854775809
strtol("-2147483649") = -2147483648
ERR 34
strtoll("-2147483649") = -2147483649
strtoul("-2147483649") = 2147483647
-strtoull("-2147483649") = 18446744071562068000
+strtoull("-2147483649") = 18446744071562067967
strtol("-2147483648") = -2147483648
strtoll("-2147483648") = -2147483648
strtoul("-2147483648") = 2147483648
-strtoull("-2147483648") = 18446744071562068000
+strtoull("-2147483648") = 18446744071562067968
strtol("-2147483647") = -2147483647
strtoll("-2147483647") = -2147483647
strtoul("-2147483647") = 2147483649
-strtoull("-2147483647") = 18446744071562068000
+strtoull("-2147483647") = 18446744071562067969
strtol("-5") = -5
strtoll("-5") = -5
strtoul("-5") = 4294967291
-strtoull("-5") = 18446744069414584000
+strtoull("-5") = 18446744073709551611
strtol("-1") = -1
strtoll("-1") = -1
strtoul("-1") = 4294967295
-strtoull("-1") = 18446744069414584000
+strtoull("-1") = 18446744073709551615
strtol("0") = 0
strtoll("0") = 0
@@ -100,27 +98,28 @@ strtoull("4294967296") = 4294967296
strtol("18446744073709551614") = 2147483647
ERR 34
-strtoll("18446744073709551614") = 9223372036854775000
+strtoll("18446744073709551614") = 9223372036854775807
ERR 34
strtoul("18446744073709551614") = 4294967295
ERR 34
-strtoull("18446744073709551614") = 18446744069414584000
+strtoull("18446744073709551614") = 18446744073709551614
strtol("18446744073709551615") = 2147483647
ERR 34
-strtoll("18446744073709551615") = 9223372036854775000
+strtoll("18446744073709551615") = 9223372036854775807
ERR 34
strtoul("18446744073709551615") = 4294967295
ERR 34
-strtoull("18446744073709551615") = 18446744069414584000
+strtoull("18446744073709551615") = 18446744073709551615
strtol("18446744073709551616") = 2147483647
ERR 34
-strtoll("18446744073709551616") = 9223372036854775000
+strtoll("18446744073709551616") = 9223372036854775807
ERR 34
strtoul("18446744073709551616") = 4294967295
ERR 34
-strtoull("18446744073709551616") = 18446744069414584000
+strtoull("18446744073709551616") = 18446744073709551615
+ERR 34
strtol("0x12", 0, 0) = 18
strtol("0x12", 0, 10) = 0
View
124 tests/runner.py
@@ -1151,15 +1151,19 @@ def test_i16_emcc_intrinsic(self):
'''
self.do_run(src, ',0,,2,C!,0,C!,0,,65535,C!,0,')
- def test_bswap(self):
+ def test_llvm_intrinsics(self):
if self.emcc_args == None: return self.skip('needs ta2')
src = r'''
#include <stdio.h>
+ #include <sys/types.h>
extern "C" {
extern unsigned short llvm_bswap_i16(unsigned short x);
extern unsigned int llvm_bswap_i32(unsigned int x);
+ extern int32_t llvm_ctlz_i32(int32_t x);
+ extern int64_t llvm_ctlz_i64(int64_t x);
+ extern int llvm_expect_i32(int x, int y);
}
int main(void) {
@@ -1172,6 +1176,11 @@ def test_bswap(self):
printf("%x,%x,%x,%x\n", y&0xff, (y>>8)&0xff, (y>>16)&0xff, (y>>24)&0xff);
y = llvm_bswap_i32(y);
printf("%x,%x,%x,%x\n", y&0xff, (y>>8)&0xff, (y>>16)&0xff, (y>>24)&0xff);
+
+ printf("%d,%d\n", (int)llvm_ctlz_i64(((int64_t)1) << 40), llvm_ctlz_i32(1<<10));
+
+ printf("%d\n", llvm_expect_i32(x % 27, 3));
+
return 0;
}
'''
@@ -1179,6 +1188,76 @@ def test_bswap(self):
c8,ef
8a,15,de,c5
c5,de,15,8a
+23,21
+13
+''')
+
+ def test_bswap64(self):
+ if Settings.USE_TYPED_ARRAYS != 2: return self.skip('needs ta2')
+
+ src = r'''
+ #include <stdio.h>
+ #include <stdlib.h>
+
+ #include <iostream>
+ #include <string>
+ #include <sstream>
+
+ typedef unsigned long long quint64;
+
+ using namespace std;
+
+ inline quint64 qbswap(quint64 source)
+ {
+ return 0
+ | ((source & quint64(0x00000000000000ffLL)) << 56)
+ | ((source & quint64(0x000000000000ff00LL)) << 40)
+ | ((source & quint64(0x0000000000ff0000LL)) << 24)
+ | ((source & quint64(0x00000000ff000000LL)) << 8)
+ | ((source & quint64(0x000000ff00000000LL)) >> 8)
+ | ((source & quint64(0x0000ff0000000000LL)) >> 24)
+ | ((source & quint64(0x00ff000000000000LL)) >> 40)
+ | ((source & quint64(0xff00000000000000LL)) >> 56);
+ }
+
+ int main()
+ {
+ quint64 v = strtoull("4433ffeeddccbb00", NULL, 16);
+ printf("%lld\n", v);
+
+ const string string64bitInt = "4433ffeeddccbb00";
+ stringstream s(string64bitInt);
+ quint64 int64bitInt = 0;
+ printf("1\n");
+ s >> hex >> int64bitInt;
+ printf("2\n");
+
+ stringstream out;
+ out << hex << qbswap(int64bitInt);
+
+ cout << out.str() << endl;
+ cout << hex << int64bitInt << endl;
+ cout << string64bitInt << endl;
+
+ if (out.str() != "bbccddeeff3344")
+ {
+ cout << "Failed!" << endl;
+ }
+ else
+ {
+ cout << "Succeeded!" << endl;
+ }
+
+ return 0;
+ }
+ '''
+ self.do_run(src, '''4914553019779824384
+1
+2
+bbccddeeff3344
+4433ffeeddccbb00
+4433ffeeddccbb00
+Succeeded!
''')
def test_sha1(self):
@@ -6160,7 +6239,7 @@ def test_fakestat(self):
}
'''
self.do_run(src, '*10,22*')
-
+
def test_mmap(self):
Settings.TOTAL_MEMORY = 100*1024*1024
@@ -6170,13 +6249,20 @@ def test_mmap(self):
#include <assert.h>
int main(int argc, char *argv[]) {
+ for (int i = 0; i < 10; i++) {
+ int* map = (int*)mmap(0, 5000, PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_ANON, -1, 0);
+ assert(((int)map) % 4096 == 0); // aligned
+ assert(munmap(map, 5000) == 0);
+ }
+
const int NUM_BYTES = 8 * 1024 * 1024;
const int NUM_INTS = NUM_BYTES / sizeof(int);
int* map = (int*)mmap(0, NUM_BYTES, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANON, -1, 0);
assert(map != MAP_FAILED);
-
+
int i;
for (i = 0; i < NUM_INTS; i++) {
@@ -6196,6 +6282,33 @@ def test_mmap(self):
self.do_run(src, 'hello,world')
self.do_run(src, 'hello,world', force_c=True)
+ def test_mmap_file(self):
+ if self.emcc_args is None: return self.skip('requires emcc')
+ self.emcc_args += ['--embed-file', 'data.dat']
+
+ open(self.in_dir('data.dat'), 'w').write('data from the file ' + ('.' * 9000))
+
+ src = r'''
+ #include <stdio.h>
+ #include <sys/mman.h>
+
+ int main() {
+ printf("*\n");
+ FILE *f = fopen("data.dat", "r");
+ char *m;
+ m = (char*)mmap(NULL, 9000, PROT_READ, MAP_PRIVATE, fileno(f), 0);
+ for (int i = 0; i < 20; i++) putchar(m[i]);
+ munmap(m, 9000);
+ printf("\n");
+ m = (char*)mmap(NULL, 9000, PROT_READ, MAP_PRIVATE, fileno(f), 5);
+ for (int i = 0; i < 20; i++) putchar(m[i]);
+ munmap(m, 9000);
+ printf("\n*\n");
+ return 0;
+ }
+ '''
+ self.do_run(src, '*\ndata from the file .\nfrom the file ......\n*\n')
+
def test_cubescript(self):
if self.emcc_args is not None and '-O2' in self.emcc_args:
self.emcc_args += ['--closure', '1'] # Use closure here for some additional coverage
@@ -8820,7 +8933,7 @@ def test_llvm_nativizer(self):
Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'files.cpp'), '-c']).communicate()
Popen([PYTHON, path_from_root('tools', 'nativize_llvm.py'), os.path.join(self.get_dir(), 'files.o')]).communicate(input)[0]
output = Popen([os.path.join(self.get_dir(), 'files.o.run')], stdin=open(os.path.join(self.get_dir(), 'stdin')), stdout=PIPE, stderr=PIPE).communicate()
- self.assertIdentical('''size: 37
+ self.assertContained('''size: 37
data: 119,97,107,97,32,119,97,107,97,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35
loop: 119 97 107 97 32 119 97 107 97 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35
input:inter-active
@@ -8829,9 +8942,6 @@ def test_llvm_nativizer(self):
5 : 10,30,20,11,88
other=ay file...
seeked= file.
-seeked=e...
-seeked=,,.
-fscanfed: 10 - hello
''', output[0])
self.assertIdentical('texte\n', output[1])
View
31 tools/autodebugger.py
@@ -13,6 +13,7 @@
ALLOW_POINTERS = False
ALLOW_MISC = True
MEMCPY = False
+MEMCPY2 = False
NO_DLMALLOC = True
POSTAMBLE = '''
@@ -89,12 +90,15 @@
POSTAMBLE_NEW = '''
@.emscripten.autodebug.str = private constant [10 x i8] c"AD:%d,%d\\0A\\00", align 1 ; [#uses=1]
+@.emscripten.autodebug.str.2 = private constant [13 x i8] c"AD:%d,%d,%d\\0A\\00", align 1 ; [#uses=1]
@.emscripten.autodebug.str.f = private constant [11 x i8] c"AD:%d,%lf\\0A\\00", align 1 ; [#uses=1]
; [#uses=1]
define void @emscripten_autodebug_i64(i32 %line, i64 %value) {
- %1 = sitofp i64 %value to double
- %2 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([11 x i8]* @.emscripten.autodebug.str.f, i32 0, i32 0), i32 %line, double %1) ; [#uses=0]
+ %1 = trunc i64 %value to i32
+ %2 = lshr i64 %value, 32
+ %3 = trunc i64 %2 to i32
+ %4 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([13 x i8]* @.emscripten.autodebug.str.2, i32 0, i32 0), i32 %line, i32 %1, i32 %3) ; [#uses=0]
ret void
}
@@ -142,6 +146,10 @@
; [#uses=1]
declare i32 @printf(i8*, ...)
'''
+ POSTAMBLE_NEW += '''
+; [#uses=1]
+declare i32 @printf(i8*, ...)
+'''
LLVM_STYLE_OLD = '<label>' not in data and 'entry:' in data
@@ -252,20 +260,21 @@
lines_added += 1
continue
if ALLOW_MISC:
- m = re.match(' %(?P<var>[\w_.]+) = (call|mul|add) (nsw )?(?P<type>i64|i32|i16|i8|float|double+) .*', lines[i])
+ # call is risky - return values can be i32 (i8*) (i16)
+ m = re.match(' %(?P<var>[\w_.]+) = (mul|add) (nsw )?(?P<type>i64|i32|i16|i8|float|double+) .*', lines[i])
if m:
index = i+1+lines_added
lines[i] += '\n call void @emscripten_autodebug_%s(i32 %d, %s %%%s)' % (m.group('type'), index, m.group('type'), m.group('var'))
lines_added += 1
continue
- m = re.match(' call void @llvm\.memcpy\.p0i8\.p0i8\.i32\(i8\* %(?P<dst>[\w_.]+), i8\* %(?P<src>[\w_.]+), i32 8, i32 (?P<align>\d+),.*', lines[i])
- if m:
- index = i+1+lines_added
- lines[i] += '\n %%adpretemp%d = bitcast i8* %%%s to i64*' % (index, m.group('src')) + \
- '\n %%adtemp%d = load i64* %%adpretemp%d, align %s' % (index, index, m.group('align')) + \
- '\n call void @emscripten_autodebug_%s(i32 %d, %s %%adtemp%d)' % ('i64', index, 'i64', index)
- lines_added += 3
- continue
+ if MEMCPY2:
+ m = re.match(' call void @llvm\.memcpy\.p0i8\.p0i8\.i32\(i8\* %(?P<dst>[\w_.]+), i8\* %(?P<src>[\w_.]+), i32 8, i32 (?P<align>\d+),.*', lines[i])
+ if m:
+ index = i+1+lines_added
+ lines[i] += '\n %%adtemp%d = load i8* %%%s, align 1' % (index, m.group('src')) + \
+ '\n call void @emscripten_autodebug_i8(i32 %d, i8 %%adtemp%d)' % (index, index)
+ lines_added += 3
+ continue
finally:
if len(pre) > 0:
View
47 tools/autodebugger_js.py
@@ -0,0 +1,47 @@
+'''
+Processes a C source file, adding debugging information.
+
+Similar to autodebugger.py, but runs on .js files.
+'''
+
+import os, sys, re
+
+filename = sys.argv[1]
+func = sys.argv[2]
+
+f = open(filename, 'r')
+data = f.read()
+f.close()
+
+lines = data.split('\n')
+in_func = False
+for i in range(len(lines)):
+ if lines[i].startswith('function '):
+ name = lines[i].split('(')[0].split(' ')[1]
+ args = lines[i].split('(')[1].split(')')[0]
+ lines[i] += ' print("call %s(" + [%s] + ")");' % (name, args)
+ if lines[i].startswith('function ' + func + '('):
+ in_func = True
+ continue
+ elif lines[i].startswith('}'):
+ in_func = False
+ continue
+ if in_func:
+ m = re.match('^ +([$_\w\d \[\]]+) = +([^;]+);$', lines[i])
+ if m and (' if ' not in lines[i-1] or '{' in lines[i-1]) and \
+ (' if ' not in lines[i+1] or '{' in lines[i+1]) and \
+ (' else' not in lines[i-1] or '{' in lines[i-1]) and \
+ (' else' not in lines[i+1] or '{' in lines[i+1]):
+ var = m.groups(1)[0].rstrip().split(' ')[-1]
+ if 'STACKTOP' not in lines[i] and 'stackBase' not in lines[i]:
+ #lines[i] += ''' print("[%4d] %s = " + %s);''' % (i+1, var, var)
+ lines[i] += ''' print("%s = " + %s);''' % (var, var)
+ m = re.match('^ +HEAP.*$', lines[i])
+ if m and lines[i].count(' = ') == 1:
+ left, right = lines[i].split(' = ')
+ lines[i] += ''' print("%s = " + %s);''' % (left, left)
+
+print '\n'.join(lines)
+
+print >> sys.stderr, 'Success.'
+
View
7 tools/eliminator/eliminator-test-output.js
@@ -6140,4 +6140,11 @@ function phi() {
}
var $10;
}
+function intoCond() {
+ var $115 = 22;
+ var $NumWords = __ZN4llvm15BitstreamCursor4ReadEj($117, 32);
+ if (($115 | 0) != 0) {
+ HEAP32[$115 >> 2] = $NumWords;
+ }
+}
View
14 tools/eliminator/eliminator-test.js
@@ -8838,5 +8838,17 @@ function phi() {
}
var $10;
}
-// EMSCRIPTEN_GENERATED_FUNCTIONS: ["a", "b", "c", "f", "g", "h", "py", "r", "t", "f2", "f3", "llvm3_1", "_inflate", "_malloc", "_mallocNoU", "asm", "phi"]
+function intoCond() {
+ var $115 = 22;
+ var $499 = __ZN4llvm15BitstreamCursor4ReadEj($117, 32);
+ var $NumWords = $499;
+ var $500 = $115;
+ var $501 = ($500 | 0) != 0;
+ if ($501) {
+ var $503 = $NumWords;
+ var $504 = $115;
+ HEAP32[$504 >> 2] = $503;
+ }
+}
+// EMSCRIPTEN_GENERATED_FUNCTIONS: ["a", "b", "c", "f", "g", "h", "py", "r", "t", "f2", "f3", "llvm3_1", "_inflate", "_malloc", "_mallocNoU", "asm", "phi", "intoCond"]
View
12 tools/file_packager.py
@@ -252,7 +252,17 @@ def was_seen(name):
filename = file_['name']
if file_['mode'] == 'embed':
# Embed
- code += '''Module['FS_createDataFile']('/%s', '%s', %s, true, true);\n''' % (os.path.dirname(filename), os.path.basename(filename), str(map(ord, open(file_['localname'], 'rb').read())))
+ data = map(ord, open(file_['localname'], 'rb').read())
+ str_data = ''
+ chunk_size = 10240
+ while len(data) > 0:
+ chunk = data[:chunk_size]
+ data = data[chunk_size:]
+ if not str_data:
+ str_data = str(chunk)
+ else:
+ str_data += '.concat(' + str(chunk) + ')'
+ code += '''Module['FS_createDataFile']('/%s', '%s', %s, true, true);\n''' % (os.path.dirname(filename), os.path.basename(filename), str_data)
elif file_['mode'] == 'preload':
# Preload
varname = 'filePreload%d' % counter
View
4 tools/js-optimizer.js
@@ -1715,6 +1715,10 @@ function eliminate(ast, memSafe) {
} else if (type == 'if') {
if (allowTracking) {
traverseInOrder(node[1]); // can eliminate into condition, but nowhere else
+ if (!callsInvalidated) { // invalidate calls, since we cannot eliminate them into an if that may not execute!
+ invalidateCalls();
+ callsInvalidated = true;
+ }
allowTracking = false;
traverseInOrder(node[2]); // 2 and 3 could be 'parallel', really..
if (node[3]) traverseInOrder(node[3]);
View
8 tools/js_optimizer.py
@@ -26,7 +26,8 @@ def run_on_chunk(command):
f.close()
return filename
-def run(filename, passes, js_engine, jcache):
+def run_on_js(filename, passes, js_engine, jcache):
+
if jcache: shared.JCache.ensure()
if type(passes) == str:
@@ -142,6 +143,8 @@ def write_chunk(chunk, i):
else:
filenames = []
+ for filename in filenames: temp_files.note(filename)
+
filename += '.jo.js'
f = open(filename, 'w')
f.write(pre);
@@ -168,3 +171,6 @@ def write_chunk(chunk, i):
return filename
+def run(filename, passes, js_engine, jcache):
+ return temp_files.run_and_clean(lambda: run_on_js(filename, passes, js_engine, jcache))
+
View
9 tools/nativize_llvm.py
@@ -23,9 +23,12 @@ def path_from_root(*pathelems):
print 'bc => clean bc'
Popen([LLVM_OPT, filename, '-strip-debug', '-o=' + filename + '.clean.bc']).communicate()[0]
print 'bc => s'
-Popen([LLVM_COMPILER, filename + '.clean.bc', '-o=' + filename + '.s']).communicate()[0]
-print 's => o'
-Popen(['as', filename + '.s', '-o', filename + '.o']).communicate()[0]
+for params in [[], ['-march=x86-64']]: # try x86, then x86-64 FIXME
+ print 'params', params
+ Popen([LLVM_COMPILER] + params + [filename + '.clean.bc', '-o=' + filename + '.s']).communicate()[0]
+ print 's => o'
+ Popen(['as', filename + '.s', '-o', filename + '.o']).communicate()[0]
+ if os.path.exists(filename + '.o'): break
print 'o => runnable'
Popen(['g++', path_from_root('system', 'lib', 'debugging.cpp'), filename + '.o', '-o', filename + '.run'] + ['-l' + lib for lib in libs]).communicate()[0]
View
9 tools/shared.py
@@ -328,13 +328,13 @@ def clean_temp():
try:
PYTHON
except:
- print >> sys.stderr, 'PYTHON not defined in ~/.emscripten, using "python"'
+ if DEBUG: print >> sys.stderr, 'PYTHON not defined in ~/.emscripten, using "python"'
PYTHON = 'python'
try:
JAVA
except:
- print >> sys.stderr, 'JAVA not defined in ~/.emscripten, using "java"'
+ if DEBUG: print >> sys.stderr, 'JAVA not defined in ~/.emscripten, using "java"'
JAVA = 'java'
# Additional compiler options
@@ -344,7 +344,7 @@ def clean_temp():
except:
COMPILER_OPTS = []
# Force a simple, standard target as much as possible: target 32-bit linux, and disable various flags that hint at other platforms
-COMPILER_OPTS = COMPILER_OPTS + ['-m32', '-U__i386__', '-U__x86_64__', '-U__i386', '-U__x86_64', '-U__SSE__', '-U__SSE2__', '-U__MMX__',
+COMPILER_OPTS = COMPILER_OPTS + ['-m32', '-U__i386__', '-U__x86_64__', '-U__i386', '-U__x86_64', '-Ui386', '-Ux86_64', '-U__SSE__', '-U__SSE2__', '-U__MMX__',
'-UX87_DOUBLE_ROUNDING', '-UHAVE_GCC_ASM_FOR_X87', '-DEMSCRIPTEN', '-U__STRICT_ANSI__', '-U__CYGWIN__',
'-D__STDC__', '-Xclang', '-triple=i386-pc-linux-gnu', '-D__IEEE_LITTLE_ENDIAN', '-fno-math-errno']
@@ -430,7 +430,7 @@ def clean(self):
def run_and_clean(self, func):
try:
- func()
+ return func()
finally:
self.clean()
@@ -819,6 +819,7 @@ def ll_opts(filename):
def llvm_opt(filename, opts):
if type(opts) is int:
opts = Building.pick_llvm_opts(opts)
+ if DEBUG: print >> sys.stderr, 'emcc: LLVM opts:', opts
output = Popen([LLVM_OPT, filename] + opts + ['-o=' + filename + '.opt.bc'], stdout=PIPE).communicate()[0]
assert os.path.exists(filename + '.opt.bc'), 'Failed to run llvm optimizations: ' + output
shutil.move(filename + '.opt.bc', filename)
Please sign in to comment.
Something went wrong with that request. Please try again.