276
281
// they would shadow similarly-named globals in the parent.
279
item.JS = makeGlobalDef(item.ident);
284
item.JS = makeGlobalDef(item.ident);
282
287
if (!NAMED_GLOBALS && isIndexableGlobal(item.ident)) {
283
288
index = makeGlobalUse(item.ident); // index !== null indicates we are indexing this
284
289
allocator = 'ALLOC_NONE';
287
if (Runtime.isNumberType(item.type) || isPointerType(item.type)) {
288
constant = zeros(Runtime.getNativeFieldSize(item.type));
292
Variables.globals[item.ident].named = item.named;
294
if (ASM_JS && (MAIN_MODULE || SIDE_MODULE) && !item.private_ && !NAMED_GLOBALS && isIndexableGlobal(item.ident)) {
295
// We need this to be named (and it normally would not be), so that it can be linked to and used from other modules
296
Variables.globals[item.ident].linkable = 1;
300
var length = calcAllocatedSize(item.type);
301
length = Runtime.alignMemory(length);
303
// If using indexed globals, go ahead and early out (no need to explicitly
305
if (!NAMED_GLOBALS) {
308
// If using named globals, we can at least shorten the call to allocate by
309
// passing an integer representing the size of memory to alloc instead of
310
// an array of 0s of size length.
316
if (Runtime.isNumberType(item.type) || isPointerType(item.type)) {
317
constant = zeros(Runtime.getNativeFieldSize(item.type));
319
constant = makeEmptyStruct(item.type);
290
constant = makeEmptyStruct(item.type);
293
constant = parseConst(item.value, item.type, item.ident);
295
assert(typeof constant === 'object');//, [typeof constant, JSON.stringify(constant), item.external]);
297
// This is a flattened object. We need to find its idents, so they can be assigned to later
298
constant.forEach(function(value, i) {
299
if (needsPostSet(value)) { // ident, or expression containing an ident
301
intertype: 'GlobalVariablePostSet',
302
JS: makeSetValue(makeGlobalUse(item.ident), i, value, 'i32', false, true) + ';' // ignore=true, since e.g. rtti and statics cause lots of safe_heap errors
309
// External variables in shared libraries should not be declared as
310
// they would shadow similarly-named globals in the parent, so do nothing here.
311
if (BUILD_AS_SHARED_LIB) return ret;
312
// Library items need us to emit something, but everything else requires nothing.
313
if (!LibraryManager.library[item.ident.slice(1)]) return ret;
317
constant = constant.concat(zeros(Runtime.alignMemory(constant.length) - constant.length));
319
// Special case: class vtables. We make sure they are null-terminated, to allow easy runtime operations
320
if (item.ident.substr(0, 5) == '__ZTV') {
321
constant = constant.concat(zeros(Runtime.alignMemory(QUANTUM_SIZE)));
322
constant = parseConst(item.value, item.type, item.ident);
324
assert(typeof constant === 'object');//, [typeof constant, JSON.stringify(constant), item.external]);
326
// This is a flattened object. We need to find its idents, so they can be assigned to later
327
var structTypes = null;
328
constant.forEach(function(value, i) {
329
if (needsPostSet(value)) { // ident, or expression containing an ident
330
if (!structTypes) structTypes = generateStructTypes(item.type);
332
intertype: 'GlobalVariablePostSet',
333
JS: makeSetValue(makeGlobalUse(item.ident), i, value, structTypes[i], false, true) + ';' // ignore=true, since e.g. rtti and statics cause lots of safe_heap errors
340
// External variables in shared libraries should not be declared as
341
// they would shadow similarly-named globals in the parent, so do nothing here.
342
if (BUILD_AS_SHARED_LIB) return ret;
343
if (SIDE_MODULE) return [];
344
// Library items need us to emit something, but everything else requires nothing.
345
if (!LibraryManager.library[item.ident.slice(1)]) return ret;
349
constant = constant.concat(zeros(Runtime.alignMemory(constant.length) - constant.length));
351
// Special case: class vtables. We make sure they are null-terminated, to allow easy runtime operations
352
if (item.ident.substr(0, 5) == '__ZTV') {
353
constant = constant.concat(zeros(Runtime.alignMemory(QUANTUM_SIZE)));
324
357
// NOTE: This is the only place that could potentially create static
354
387
// Set the actual value in a postset, since it may be a global variable. We also order by dependencies there
355
388
Variables.globals[item.ident].targetIdent = item.value.ident;
356
389
var value = Variables.globals[item.ident].resolvedAlias = finalizeLLVMParameter(item.value);
358
if (BUILD_AS_SHARED_LIB == 2 && !item.private_) {
359
var target = item.ident;
360
if (isFunctionType(item.type)) {
361
target = item.value.ident; // the other side does not know this is an alias/function table index. So make it the alias target.
362
var varData = Variables.globals[target];
363
assert(!varData, 'multi-level aliasing does not work yet in shared lib 2 exports');
365
fix = '\nif (globalScope) { assert(!globalScope["' + item.ident + '"]); globalScope["' + item.ident + '"] = ' + target + ' }'
390
if ((MAIN_MODULE || SIDE_MODULE) && isFunctionType(item.type)) {
391
var target = item.value.ident;
392
if (!Functions.aliases[target]) Functions.aliases[target] = [];
393
Functions.aliases[target].push(item.ident);
368
intertype: 'GlobalVariablePostSet',
370
dependencies: set([value]),
371
JS: item.ident + ' = ' + value + ';' + fix
636
666
hasByVal = hasByVal || param.byVal;
639
func.JS += ' var tempParam = 0;\n';
669
func.JS += INDENTATION + 'var tempParam = 0;\n';
673
if (func.hasVarArgsCall) {
674
func.JS += INDENTATION + 'var tempVarArgs = 0;\n';
643
677
// Prepare the stack, if we need one. If we have other stack allocations, force the stack to be set up.
644
func.JS += ' ' + RuntimeGenerator.stackEnter(func.initialStack, func.otherStackAllocations) + ';\n';
678
func.JS += INDENTATION + RuntimeGenerator.stackEnter(func.initialStack, func.otherStackAllocations) + ';\n';
646
680
// Make copies of by-value params
647
681
// XXX It is not clear we actually need this. While without this we fail, it does look like
729
765
ret += 'switch(' + asmCoercion('label', 'i32') + ') {\n';
730
766
ret += block.labels.map(function(label) {
731
return indent + ' case ' + getLabelId(label.ident) + ': ' + (SHOW_LABELS ? '// ' + getOriginalLabelId(label.ident) : '') + '\n'
732
+ getLabelLines(label, indent + ' ');
767
return indent + INDENTATION + 'case ' + getLabelId(label.ident) + ': ' + (SHOW_LABELS ? '// ' + getOriginalLabelId(label.ident) : '') + '\n'
768
+ getLabelLines(label, indent + INDENTATION + INDENTATION);
733
769
}).join('\n') + '\n';
734
770
if (func.setjmpTable && ASM_JS) {
735
771
// emit a label in which we write to the proper local variable, before jumping to the actual label
736
ret += ' case ' + SETJMP_LABEL + ': ';
772
ret += INDENTATION + 'case ' + SETJMP_LABEL + ': ';
737
773
ret += func.setjmpTable.map(function(triple) { // original label, label we created for right after the setjmp, variable setjmp result goes into
738
774
return 'if ((setjmpLabel|0) == ' + getLabelId(triple.oldLabel) + ') { ' + triple.assignTo + ' = threwValue; label = ' + triple.newLabel + ' }\n';
739
775
}).join(' else ');
1083
1138
makeFuncLineActor('switch', function(item) {
1084
var useIfs = RELOOP || item.switchLabels.length < 1024; // with a huge number of cases, if-else which looks nested to js parsers can cause problems
1139
// use a switch if the range is not too big or sparse
1140
var minn = Infinity, maxx = -Infinity;
1141
item.switchLabels.forEach(function(switchLabel) {
1142
var curr = Math.abs(parseInt(switchLabel.value));
1143
minn = Math.min(minn, curr);
1144
maxx = Math.max(maxx, curr);
1146
var range = maxx - minn;
1147
var useIfs = (item.switchLabels.length+1) < 6 || range > 10*1024 || (range/item.switchLabels.length) > 1024; // heuristics
1148
if (VERBOSE && useIfs && item.switchLabels.length >= 6) {
1149
warn('not optimizing llvm switch into js switch because range of values is ' + range + ', density is ' + range/item.switchLabels.length);
1085
1152
var phiSets = calcPhiSets(item);
1086
1153
// Consolidate checks that go to the same label. This is important because it makes the relooper simpler and faster.
1087
1154
var targetLabels = {}; // for each target label, the list of values going to it
1178
1246
// in an assignment
1179
1247
var disabled = DISABLE_EXCEPTION_CATCHING == 2 && !(item.funcData.ident in EXCEPTION_CATCHING_WHITELIST);
1180
1248
var phiSets = calcPhiSets(item);
1181
var call_ = makeFunctionCall(item.ident, item.params, item.funcData, item.type, ASM_JS && !disabled);
1249
var call_ = makeFunctionCall(item.ident, item.params, item.funcData, item.type, ASM_JS && !disabled, !!item.assignTo || !item.standalone, true);
1185
1253
if (disabled) {
1186
1254
ret = call_ + ';';
1187
1255
} else if (ASM_JS) {
1256
if (item.type != 'void') call_ = asmCoercion(call_, item.type); // ensure coercion to ffi in comma operator
1188
1257
call_ = call_.replace('; return', ''); // we auto-add returns when aborting, but do not need them here
1189
ret = '(__THREW__ = 0,' + call_ + ');';
1258
if (item.type == 'void') {
1259
ret = '__THREW__ = 0;' + call_ + ';';
1261
ret = '(__THREW__ = 0,' + call_ + ');';
1191
1264
ret = '(function() { try { __THREW__ = 0; return '
1227
1301
case 'xchg': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, param2, type, null, null, null, null, ',') + ',tempValue)';
1228
1302
case 'cmpxchg': {
1229
1303
var param3 = finalizeLLVMParameter(item.params[2]);
1230
return '(tempValue=' + makeGetValue(param1, 0, type) + ',(' + makeGetValue(param1, 0, type) + '==(' + param2 + '|0) ? ' + makeSetValue(param1, 0, param3, type, null, null, null, null, ',') + ' : 0),tempValue)';
1304
return '(tempValue=' + makeGetValue(param1, 0, type) + ',(' + makeGetValue(param1, 0, type) + '==(' + param2 + '|0) ? ' + asmCoercion(makeSetValue(param1, 0, param3, type, null, null, null, null, ','), 'i32') + ' : 0),tempValue)';
1232
1306
default: throw 'unhandled atomic op: ' + item.op;
1310
1384
assert(TARGET_LE32);
1311
1385
var ident = item.value.ident;
1312
1386
var move = Runtime.STACK_ALIGN;
1313
return '(tempInt=' + makeGetValue(ident, 4, '*') + ',' +
1314
makeSetValue(ident, 4, 'tempInt + ' + move, '*') + ',' +
1388
// store current list offset in tempInt, advance list offset by STACK_ALIGN, return list entry stored at tempInt
1389
return '(tempInt=' + makeGetValue(ident, Runtime.QUANTUM_SIZE, '*') + ',' +
1390
makeSetValue(ident, Runtime.QUANTUM_SIZE, 'tempInt + ' + move, '*') + ',' +
1315
1391
makeGetValue(makeGetValue(ident, 0, '*'), 'tempInt', item.type) + ')';
1331
function makeFunctionCall(ident, params, funcData, type, forceByPointer) {
1407
function makeFunctionCall(ident, params, funcData, type, forceByPointer, hasReturn, invoke) {
1332
1408
// We cannot compile assembly. See comment in intertyper.js:'Call'
1333
1409
assert(ident != 'asm', 'Inline assembly cannot be compiled to JavaScript!');
1411
var extCall = false;
1335
1413
if (ASM_JS && funcData.setjmpTable) forceByPointer = true; // in asm.js mode, we must do an invoke for each call
1414
if (ASM_JS && DLOPEN_SUPPORT && !invoke && !funcData.setjmpTable) extCall = true; // go out, to be able to access other modules TODO: optimize
1337
1416
ident = Variables.resolveAliasToIdent(ident);
1338
1417
var shortident = ident.slice(1);
1420
1500
assert(offset % Runtime.STACK_ALIGN == 0); // varargs must be aligned
1421
1501
if (!varargsByVals[i]) {
1422
ret = makeSetValue(getFastValue('tempInt', '+', offset), 0, arg, type, null, null, Runtime.STACK_ALIGN, null, ',');
1502
ret = makeSetValue(getFastValue('tempVarArgs', '+', offset), 0, arg, type, null, null, Runtime.STACK_ALIGN, null, ',');
1423
1503
offset += Runtime.alignMemory(Runtime.getNativeFieldSize(type), Runtime.STACK_ALIGN);
1425
1505
var size = calcAllocatedSize(removeAllPointing(type));
1426
ret = makeCopyValues(getFastValue('tempInt', '+', offset), arg, size, null, null, varargsByVals[i], ',');
1506
ret = makeCopyValues(getFastValue('tempVarArgs', '+', offset), arg, size, null, null, varargsByVals[i], ',');
1427
1507
offset += Runtime.forceAlign(size, Runtime.STACK_ALIGN);
1430
1510
}).filter(function(arg) {
1431
1511
return arg !== null;
1432
}).join(',') + ',tempInt)';
1512
}).join(',') + ',tempVarArgs)';
1433
1513
varargs = asmCoercion(varargs, 'i32');
1436
1516
args = args.concat(varargs);
1437
var argsText = args.join(', ');
1439
1518
// Inline if either we inline whenever we can (and we can), or if there is no noninlined version
1440
1519
var inline = LibraryManager.library[simpleIdent + '__inline'];
1460
if (byPointer || ASM_JS) {
1538
if (callIdent in Functions.implementedFunctions) {
1539
// LLVM sometimes bitcasts for no reason. We must call using the exact same type as the actual function is generated as.
1540
var numArgs = Functions.implementedFunctions[callIdent].length - 1;
1541
if (numArgs !== args.length) {
1542
if (VERBOSE) warnOnce('Fixing function call arguments based on signature, on ' + [callIdent, args.length, numArgs]);
1543
while (args.length > numArgs) { args.pop(); argsTypes.pop() }
1544
while (args.length < numArgs) { args.push('0'); argsTypes.push('i32') }
1548
var returnType = 'void';
1549
if ((byPointer || ASM_JS) && hasReturn) {
1461
1550
returnType = getReturnType(type);
1551
if (callIdent in Functions.implementedFunctions) {
1552
// LLVM sometimes bitcasts for no reason. We must call using the exact same type as the actual function is generated as
1553
var trueType = Functions.getSignatureReturnType(Functions.implementedFunctions[callIdent]);
1554
if (trueType !== returnType && !isIdenticallyImplemented(trueType, returnType)) {
1555
if (VERBOSE) warnOnce('Fixing function call based on return type from signature, on ' + [callIdent, returnType, trueType]);
1556
returnType = trueType;
1464
1561
if (byPointer) {
1465
1562
var sig = Functions.getSignature(returnType, argsTypes, hasVarArgs);
1467
1564
assert(returnType.search(/\("'\[,/) == -1); // XXX need isFunctionType(type, out)
1468
if (!byPointerForced && !funcData.setjmpTable) {
1565
Functions.neededTables[sig] = 1;
1566
var functionTableCall = !byPointerForced && !funcData.setjmpTable && !invoke && !extCall;
1567
if (functionTableCall) {
1469
1568
// normal asm function pointer call
1470
1569
callIdent = '(' + callIdent + ')&{{{ FTM_' + sig + ' }}}'; // the function table mask is set in emscripten.py
1471
Functions.neededTables[sig] = 1;
1473
// This is a call through an invoke_*, either a forced one, or a setjmp-required one
1571
// This is a call through an invoke_* or extCall, either a forced one, or a setjmp-required one
1474
1572
// note: no need to update argsTypes at this point
1475
1573
if (byPointerForced) Functions.unimplementedFunctions[callIdent] = sig;
1476
args.unshift(byPointerForced ? Functions.getIndex(callIdent) : asmCoercion(callIdent, 'i32'));
1477
callIdent = 'invoke_' + sig;
1574
args.unshift(byPointerForced ? Functions.getIndex(callIdent, sig) : asmCoercion(callIdent, 'i32'));
1575
callIdent = (extCall ? 'extCall' : 'invoke') + '_' + sig;
1479
1577
} else if (SAFE_DYNCALLS) {
1480
1578
assert(!ASM_JS, 'cannot emit safe dyncalls in asm');
1481
1579
callIdent = '(tempInt=' + callIdent + ',tempInt < 0 || tempInt >= FUNCTION_TABLE.length-1 || !FUNCTION_TABLE[tempInt] ? abort("dyncall error: ' + sig + ' " + FUNCTION_TABLE_NAMES[tempInt]) : tempInt)';
1483
if (!ASM_JS || (!byPointerForced && !funcData.setjmpTable)) callIdent = Functions.getTable(sig) + '[' + callIdent + ']';
1581
if (!ASM_JS || functionTableCall) callIdent = Functions.getTable(sig) + '[' + callIdent + ']';
1486
1584
var ret = callIdent + '(' + args.join(', ') + ')';
1601
function makeVarArgsCleanup(js) {
1602
if (js.indexOf('(tempVarArgs=') >= 0) {
1603
if (js[js.length-1] == ';') {
1604
return js + ' STACKTOP=tempVarArgs;';
1606
assert(js.indexOf(';') < 0);
1607
return '((' + js + '), STACKTOP=tempVarArgs)';
1502
1613
makeFuncLineActor('getelementptr', function(item) { return finalizeLLVMFunctionCall(item) });
1503
1614
makeFuncLineActor('call', function(item) {
1504
1615
if (item.standalone && LibraryManager.isStubFunction(item.ident)) return ';';
1505
return makeFunctionCall(item.ident, item.params, item.funcData, item.type) + (item.standalone ? ';' : '');
1616
var ret = makeFunctionCall(item.ident, item.params, item.funcData, item.type, false, !!item.assignTo || !item.standalone) + (item.standalone ? ';' : '');
1617
return makeVarArgsCleanup(ret);
1508
1620
makeFuncLineActor('unreachable', function(item) {
1552
1664
if (!mainPass) {
1553
if (phase == 'pre' && !Variables.generatedGlobalBase) {
1665
if (phase == 'pre' && !Variables.generatedGlobalBase && !BUILD_AS_SHARED_LIB) {
1554
1666
Variables.generatedGlobalBase = true;
1555
1667
// Globals are done, here is the rest of static memory
1556
print('STATIC_BASE = ' + Runtime.GLOBAL_BASE + ';\n');
1557
print('STATICTOP = STATIC_BASE + ' + Runtime.alignMemory(Variables.nextIndexedOffset) + ';\n');
1668
assert((TARGET_LE32 && Runtime.GLOBAL_BASE == 8) || (TARGET_X86 && Runtime.GLOBAL_BASE == 4)); // this is assumed in e.g. relocations for linkable modules
1670
print('STATIC_BASE = ' + Runtime.GLOBAL_BASE + ';\n');
1671
print('STATICTOP = STATIC_BASE + ' + Runtime.alignMemory(Variables.nextIndexedOffset) + ';\n');
1673
print('H_BASE = parentModule["_malloc"](' + Runtime.alignMemory(Variables.nextIndexedOffset) + ' + Runtime.GLOBAL_BASE);\n');
1674
print('// STATICTOP = STATIC_BASE + ' + Runtime.alignMemory(Variables.nextIndexedOffset) + ';\n'); // comment as metadata only
1559
1677
var generated = itemsDict.function.concat(itemsDict.type).concat(itemsDict.GlobalVariableStub).concat(itemsDict.GlobalVariable);
1560
print(generated.map(function(item) { return item.JS }).join('\n'));
1678
print(generated.map(function(item) { return item.JS; }).join('\n'));
1562
1680
if (phase == 'pre') {
1563
1681
if (memoryInitialization.length > 0) {
1583
1701
// write out the singleton big memory initialization value
1584
print('/* memory initializer */ ' + makePointer(memoryInitialization, null, 'ALLOC_NONE', 'i8', 'Runtime.GLOBAL_BASE', true));
1702
print('/* memory initializer */ ' + makePointer(memoryInitialization, null, 'ALLOC_NONE', 'i8', 'Runtime.GLOBAL_BASE' + (SIDE_MODULE ? '+H_BASE' : ''), true));
1586
1704
print('/* no memory initializer */'); // test purposes
1589
// Run postsets right before main, and after the memory initializer has been set up
1707
// Define postsets. These will be run in ATINIT, right before global initializers (which might need the postsets). We cannot
1708
// run them now because the memory initializer might not have been applied yet.
1590
1709
print('function runPostSets() {\n');
1591
1710
print(itemsDict.GlobalVariablePostSet.map(function(item) { return item.JS }).join('\n'));
1593
print('if (!awaitingMemoryInitializer) runPostSets();\n'); // if we load the memory initializer, this is done later
1595
1713
if (USE_TYPED_ARRAYS == 2) {
1596
print('var tempDoublePtr = Runtime.alignMemory(allocate(12, "i8", ALLOC_STATIC), 8);\n');
1597
print('assert(tempDoublePtr % 8 == 0);\n');
1598
print('function copyTempFloat(ptr) { // functions, because inlining this code increases code size too much\n');
1599
print(' HEAP8[tempDoublePtr] = HEAP8[ptr];\n');
1600
print(' HEAP8[tempDoublePtr+1] = HEAP8[ptr+1];\n');
1601
print(' HEAP8[tempDoublePtr+2] = HEAP8[ptr+2];\n');
1602
print(' HEAP8[tempDoublePtr+3] = HEAP8[ptr+3];\n');
1604
print('function copyTempDouble(ptr) {\n');
1605
print(' HEAP8[tempDoublePtr] = HEAP8[ptr];\n');
1606
print(' HEAP8[tempDoublePtr+1] = HEAP8[ptr+1];\n');
1607
print(' HEAP8[tempDoublePtr+2] = HEAP8[ptr+2];\n');
1608
print(' HEAP8[tempDoublePtr+3] = HEAP8[ptr+3];\n');
1609
print(' HEAP8[tempDoublePtr+4] = HEAP8[ptr+4];\n');
1610
print(' HEAP8[tempDoublePtr+5] = HEAP8[ptr+5];\n');
1611
print(' HEAP8[tempDoublePtr+6] = HEAP8[ptr+6];\n');
1612
print(' HEAP8[tempDoublePtr+7] = HEAP8[ptr+7];\n');
1714
if (!BUILD_AS_SHARED_LIB && !SIDE_MODULE) {
1715
print('var tempDoublePtr = Runtime.alignMemory(allocate(12, "i8", ALLOC_STATIC), 8);\n');
1716
print('assert(tempDoublePtr % 8 == 0);\n');
1717
print('function copyTempFloat(ptr) { // functions, because inlining this code increases code size too much\n');
1718
print(' HEAP8[tempDoublePtr] = HEAP8[ptr];\n');
1719
print(' HEAP8[tempDoublePtr+1] = HEAP8[ptr+1];\n');
1720
print(' HEAP8[tempDoublePtr+2] = HEAP8[ptr+2];\n');
1721
print(' HEAP8[tempDoublePtr+3] = HEAP8[ptr+3];\n');
1723
print('function copyTempDouble(ptr) {\n');
1724
print(' HEAP8[tempDoublePtr] = HEAP8[ptr];\n');
1725
print(' HEAP8[tempDoublePtr+1] = HEAP8[ptr+1];\n');
1726
print(' HEAP8[tempDoublePtr+2] = HEAP8[ptr+2];\n');
1727
print(' HEAP8[tempDoublePtr+3] = HEAP8[ptr+3];\n');
1728
print(' HEAP8[tempDoublePtr+4] = HEAP8[ptr+4];\n');
1729
print(' HEAP8[tempDoublePtr+5] = HEAP8[ptr+5];\n');
1730
print(' HEAP8[tempDoublePtr+6] = HEAP8[ptr+6];\n');
1731
print(' HEAP8[tempDoublePtr+7] = HEAP8[ptr+7];\n');
1646
1766
legalizedI64s = legalizedI64sDefault;
1648
print('STACK_BASE = STACKTOP = Runtime.alignMemory(STATICTOP);\n');
1649
print('staticSealed = true; // seal the static portion of memory\n');
1650
print('STACK_MAX = STACK_BASE + ' + TOTAL_STACK + ';\n');
1651
print('DYNAMIC_BASE = DYNAMICTOP = Runtime.alignMemory(STACK_MAX);\n');
1652
print('assert(DYNAMIC_BASE < TOTAL_MEMORY); // Stack must fit in TOTAL_MEMORY; allocations from here on may enlarge TOTAL_MEMORY\n');
1768
if (!BUILD_AS_SHARED_LIB && !SIDE_MODULE) {
1769
print('STACK_BASE = STACKTOP = Runtime.alignMemory(STATICTOP);\n');
1770
print('staticSealed = true; // seal the static portion of memory\n');
1771
print('STACK_MAX = STACK_BASE + ' + TOTAL_STACK + ';\n');
1772
print('DYNAMIC_BASE = DYNAMICTOP = Runtime.alignMemory(STACK_MAX);\n');
1773
print('assert(DYNAMIC_BASE < TOTAL_MEMORY); // Stack must fit in TOTAL_MEMORY; allocations from here on may enlarge TOTAL_MEMORY\n');
1654
1776
if (asmLibraryFunctions.length > 0) {
1655
1777
print('// ASM_LIBRARY FUNCTIONS');
1713
1835
if (CORRUPTION_CHECK) {
1714
assert(!ASM_JS); // cannot monkeypatch asm!
1836
assert(!ASM_JS, 'corruption checker is not compatible with asm.js');
1715
1837
print(processMacros(read('corruptionCheck.js')));
1717
1839
if (HEADLESS) {
1718
1840
print('if (!ENVIRONMENT_IS_WEB) {');
1719
print(read('headless.js').replace("'%s'", "'http://emscripten.org'").replace("'?%s'", "''").replace('%s,', 'null,').replace('%d', '0'));
1841
print(read('headlessCanvas.js'));
1843
print(read('headless.js').replace("'%s'", "'http://emscripten.org'").replace("'?%s'", "''").replace("'?%s'", "'/'").replace('%s,', 'null,').replace('%d', '0'));
1846
if (PROXY_TO_WORKER) {
1847
print(read('proxyWorker.js'));
1722
1849
if (RUNTIME_TYPE_INFO) {
1723
1850
Types.cleanForRuntime();
1724
1851
print('Runtime.typeInfo = ' + JSON.stringify(Types.types));
1725
1852
print('Runtime.structMetadata = ' + JSON.stringify(Types.structMetadata));
1727
var postFile = BUILD_AS_SHARED_LIB ? 'postamble_sharedlib.js' : 'postamble.js';
1854
var postFile = BUILD_AS_SHARED_LIB || SIDE_MODULE ? 'postamble_sharedlib.js' : 'postamble.js';
1728
1855
var postParts = processMacros(preprocess(read(postFile))).split('{{GLOBAL_VARS}}');
1729
1856
print(postParts[0]);
1762
1889
if (mainPass) {
1890
if (phase == 'pre') {
1891
// types have been parsed, so we can figure out function signatures (which can use types)
1892
data.unparsedFunctions.forEach(function(func) {
1893
Functions.implementedFunctions[func.ident] = Functions.getSignature(func.returnType, func.params.map(function(param) { return param.type }));
1763
1896
substrate.addItems(data.functionStubs, 'FunctionStub');
1764
1897
assert(data.functions.length == 0);
1899
if (phase == 'pre') {
1900
// ensure there is a global ctors, for runPostSets
1901
if ('_llvm_global_ctors' in data.globalVariables) {
1902
data.globalVariables._llvm_global_ctors.ctors.unshift('runPostSets'); // run postsets right before global initializers
1905
substrate.addItems([{
1906
intertype: 'GlobalVariableStub',
1907
ident: '_llvm_global_ctors',
1908
type: '[1 x { i32, void ()* }]',
1909
ctors: ["runPostSets"],
1910
}], 'GlobalVariable');
1766
1914
substrate.addItems(sortGlobals(data.globalVariables), 'GlobalVariable');
1767
1915
substrate.addItems(data.aliass, 'Alias');
1768
1916
substrate.addItems(data.functions, 'FunctionSplitter');