Skip to content

Commit 2325baf

Browse files
committed
Merge branch 'incoming' into asm_js
Conflicts: src/library_browser.js
2 parents 8aa6919 + a55c2a2 commit 2325baf

23 files changed

Lines changed: 622 additions & 121 deletions

emcc

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,7 +1062,6 @@ try:
10621062
if not LEAVE_INPUTS_RAW:
10631063
link_opts = [] if keep_debug else ['-strip-debug']
10641064
if llvm_opts > 0:
1065-
if DEBUG: print >> sys.stderr, 'emcc: LLVM -O%d' % llvm_opts
10661065
shared.Building.llvm_opt(in_temp(target_basename + '.bc'), llvm_opts)
10671066
if DEBUG: save_intermediate('opt', 'bc')
10681067
# Do LTO in a separate pass to work around LLVM bug XXX (see failure e.g. in cubescript)
@@ -1075,7 +1074,6 @@ try:
10751074
else:
10761075
# At minimum remove dead functions etc., this potentially saves a lot in the size of the generated code (and the time to compile it)
10771076
link_opts += shared.Building.get_safe_internalize() + ['-globaldce']
1078-
if DEBUG: print >> sys.stderr, 'emcc: LLVM linktime:', link_opts
10791077
shared.Building.llvm_opt(in_temp(target_basename + '.bc'), link_opts)
10801078
if DEBUG: save_intermediate('linktime', 'bc')
10811079

src/compiler.html

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,44 @@ <h2>Run the emscripten compiler in a web page, just for laughs</h2>
55
<hr>
66
<pre id="output"></pre>
77
<script>
8-
arguments = ['', '../freetype.ll'];
9-
//arguments = ['', '../tests/cases/phicubed.ll'];
8+
arguments = [];
109

1110
var outputElement = document.getElementById('output');
11+
var compilerOutput = '';
1212
print = function(x) {
1313
//outputElement.innerHTML += x;
14+
compilerOutput += x;
15+
};
16+
17+
// For generated code
18+
var Module = {
19+
print: function(x) {
20+
outputElement.innerHTML += x;
21+
}
1422
};
1523
</script>
1624
<script src="compiler.js">
1725
</script>
26+
<textarea id="the_input" cols=50 rows=30>
27+
; ModuleID = 'tests/hello_world.bc'
28+
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"
29+
target triple = "i386-pc-linux-gnu"
30+
31+
@.str = private unnamed_addr constant [15 x i8] c"hello, world!\0A\00", align 1 ; [#uses=1 type=[15 x i8]*]
32+
33+
; [#uses=0]
34+
define i32 @main() {
35+
entry:
36+
%retval = alloca i32, align 4 ; [#uses=1 type=i32*]
37+
store i32 0, i32* %retval
38+
%call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0)) ; [#uses=0 type=i32]
39+
ret i32 1
40+
}
41+
42+
; [#uses=1]
43+
declare i32 @printf(i8*, ...)
44+
</textarea>
45+
<input type="button" value="run!" onclick="compile(document.getElementById('the_input').value); eval(compilerOutput)">
1846
</body>
1947
</html>
2048

src/compiler.js

Lines changed: 55 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,12 @@ if (ENVIRONMENT_IS_NODE) {
7676
}
7777

7878
} else if (ENVIRONMENT_IS_WEB) {
79-
this['print'] = printErr = function(x) {
79+
printErr = function(x) {
8080
console.log(x);
8181
};
8282

83+
if (!this['print']) this['print'] = printErr;
84+
8385
this['read'] = function(url) {
8486
var xhr = new XMLHttpRequest();
8587
xhr.open('GET', url, false);
@@ -220,42 +222,66 @@ NECESSARY_BLOCKADDRS = temp;
220222

221223
// Read llvm
222224

223-
var raw = read(ll_file);
224-
if (FAKE_X86_FP80) {
225-
raw = raw.replace(/x86_fp80/g, 'double');
226-
}
227-
if (raw.search('\r\n') >= 0) {
228-
raw = raw.replace(/\r\n/g, '\n'); // fix windows line endings
229-
}
230-
var lines = raw.split('\n');
231-
raw = null;
225+
function compile(raw) {
226+
if (FAKE_X86_FP80) {
227+
raw = raw.replace(/x86_fp80/g, 'double');
228+
}
229+
if (raw.search('\r\n') >= 0) {
230+
raw = raw.replace(/\r\n/g, '\n'); // fix windows line endings
231+
}
232+
var lines = raw.split('\n');
233+
raw = null;
234+
235+
// Pre-process the LLVM assembly
236+
237+
Debugging.handleMetadata(lines);
238+
239+
function runPhase(currPhase) {
240+
//printErr('// JS compiler in action, phase ' + currPhase + typeof lines + (lines === null));
241+
phase = currPhase;
242+
if (phase != 'pre') {
243+
if (singlePhase) PassManager.load(read(forwardedDataFile));
232244

233-
// Pre-process the LLVM assembly
245+
if (phase == 'funcs') {
246+
PreProcessor.eliminateUnneededIntrinsics(lines);
247+
}
248+
}
234249

235-
//printErr('JS compiler in action, phase ' + phase);
250+
// Do it
236251

237-
Debugging.handleMetadata(lines);
252+
var intertyped = intertyper(lines);
253+
if (singlePhase) lines = null;
254+
var analyzed = analyzer(intertyped);
255+
intertyped = null;
256+
JSify(analyzed);
238257

239-
if (phase != 'pre') {
240-
PassManager.load(read(forwardedDataFile));
258+
phase = null;
241259

242-
if (phase == 'funcs') {
243-
PreProcessor.eliminateUnneededIntrinsics(lines);
260+
if (DEBUG_MEMORY) {
261+
print('zzz. last gc: ' + gc());
262+
MemoryDebugger.dump();
263+
print('zzz. hanging now!');
264+
while(1){};
265+
}
244266
}
245-
}
246267

247-
// Do it
268+
// 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.
269+
singlePhase = !!phase;
248270

249-
var intertyped = intertyper(lines);
250-
lines = null;
251-
var analyzed = analyzer(intertyped);
252-
intertyped = null;
253-
JSify(analyzed);
271+
if (singlePhase) {
272+
runPhase(phase);
273+
} else {
274+
runPhase('pre');
275+
runPhase('funcs');
276+
runPhase('post');
277+
}
278+
}
254279

255-
if (DEBUG_MEMORY) {
256-
print('zzz. last gc: ' + gc());
257-
MemoryDebugger.dump();
258-
print('zzz. hanging now!');
259-
while(1){};
280+
if (ll_file) {
281+
if (ll_file.indexOf(String.fromCharCode(10)) == -1) {
282+
compile(read(ll_file));
283+
} else {
284+
compile(ll_file); // we are given raw .ll
285+
}
260286
}
261287

src/intertyper.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,19 +61,21 @@ function intertyper(data, sidePass, baseLineNums) {
6161
var baseLineNumPosition = 0;
6262
for (var i = 0; i < lines.length; i++) {
6363
var line = lines[i];
64-
lines[i] = null; // lines may be very very large. Allow GCing to occur in the loop by releasing refs here
64+
if (singlePhase) lines[i] = null; // lines may be very very large. Allow GCing to occur in the loop by releasing refs here
6565

6666
while (baseLineNumPosition < baseLineNums.length-1 && i >= baseLineNums[baseLineNumPosition+1][0]) {
6767
baseLineNumPosition++;
6868
}
6969

7070
if (mainPass && (line[0] == '%' || line[0] == '@')) {
7171
// If this isn't a type, it's a global variable, make a note of the information now, we will need it later
72-
var testType = /[@%\w\d\.\" $-]+ = type .*/.exec(line);
72+
var parts = line.split(' = ');
73+
assert(parts.length >= 2);
74+
var left = parts[0], right = parts.slice(1).join(' = ');
75+
var testType = /^type .*/.exec(right);
7376
if (!testType) {
74-
var global = /([@%\w\d\.\" $-]+) = .*/.exec(line);
75-
var globalIdent = toNiceIdent(global[1]);
76-
var testAlias = /[@%\w\d\.\" $-]+ = (hidden )?alias .*/.exec(line);
77+
var globalIdent = toNiceIdent(left);
78+
var testAlias = /^(hidden )?alias .*/.exec(right);
7779
Variables.globals[globalIdent] = {
7880
name: globalIdent,
7981
alias: !!testAlias,

src/jsifier.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -431,8 +431,8 @@ function JSify(data, functionsOnly, givenFunctions) {
431431
// name the function; overwrite if it's already named
432432
snippet = snippet.replace(/function(?:\s+([^(]+))?\s*\(/, 'function _' + ident + '(');
433433
if (LIBRARY_DEBUG) {
434-
snippet = snippet.replace('{', '{ var ret = (function() { if (Runtime.debug) Module.printErr("[library call:' + ident + ': " + Array.prototype.slice.call(arguments).map(Runtime.prettyPrint) + "]"); ');
435-
snippet = snippet.substr(0, snippet.length-1) + '}).apply(this, arguments); if (Runtime.debug && typeof ret !== "undefined") Module.printErr(" [ return:" + Runtime.prettyPrint(ret)); return ret; }';
434+
snippet = snippet.replace('{', '{ var ret = (function() { if (Runtime.debug) Module.print("[library call:' + ident + ': " + Array.prototype.slice.call(arguments).map(Runtime.prettyPrint) + "]"); ');
435+
snippet = snippet.substr(0, snippet.length-1) + '}).apply(this, arguments); if (Runtime.debug && typeof ret !== "undefined") Module.print(" [ return:" + Runtime.prettyPrint(ret)); return ret; }';
436436
}
437437
if (ASM_JS) Functions.libraryFunctions[ident] = 1;
438438
}
@@ -1390,6 +1390,7 @@ function JSify(data, functionsOnly, givenFunctions) {
13901390

13911391
// Print out global variables and postsets TODO: batching
13921392
if (phase == 'pre') {
1393+
var legalizedI64sDefault = legalizedI64s;
13931394
legalizedI64s = false;
13941395

13951396
var globalsData = analyzer(intertyper(data.unparsedGlobalss[0].lines, true), true);
@@ -1412,9 +1413,13 @@ function JSify(data, functionsOnly, givenFunctions) {
14121413

14131414
var generated = itemsDict.functionStub.concat(itemsDict.GlobalVariablePostSet);
14141415
generated.forEach(function(item) { print(indentify(item.JS || '', 2)); });
1416+
1417+
legalizedI64s = legalizedI64sDefault;
14151418
} else {
1416-
assert(data.unparsedGlobalss[0].lines.length == 0, dump([phase, data.unparsedGlobalss]));
1417-
assert(itemsDict.functionStub.length == 0, dump([phase, itemsDict.functionStub]));
1419+
if (singlePhase) {
1420+
assert(data.unparsedGlobalss[0].lines.length == 0, dump([phase, data.unparsedGlobalss]));
1421+
assert(itemsDict.functionStub.length == 0, dump([phase, itemsDict.functionStub]));
1422+
}
14181423
}
14191424

14201425
if (phase == 'pre' || phase == 'funcs') {

0 commit comments

Comments
 (0)