diff options
Diffstat (limited to 'src/jsifier.js')
-rw-r--r-- | src/jsifier.js | 206 |
1 files changed, 105 insertions, 101 deletions
diff --git a/src/jsifier.js b/src/jsifier.js index 69d9842a..50030268 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -231,12 +231,11 @@ function JSify(data, functionsOnly, givenFunctions) { if (value.intertype in PARSABLE_LLVM_FUNCTIONS) { return [finalizeLLVMFunctionCall(value)]; } else if (Runtime.isNumberType(type) || pointingLevels(type) >= 1) { - return makeGlobalUse(indexizeFunctions(parseNumerical(value.value), type)); + return [makeGlobalUse(indexizeFunctions(parseNumerical(value.value), type))]; } else if (value.intertype === 'emptystruct') { return makeEmptyStruct(type); } else if (value.intertype === 'string') { - return JSON.stringify(parseLLVMString(value.text)) + - ' /* ' + value.text.substr(0, 20).replace(/[*<>]/g, '_') + ' */'; // make string safe for inclusion in comment + return parseLLVMString(value.text); } else { return alignStruct(handleSegments(value.contents), type); } @@ -244,9 +243,7 @@ function JSify(data, functionsOnly, givenFunctions) { function parseConst(value, type, ident) { var constant = makeConst(value, type); - if (typeof constant === 'object') { - constant = flatten(constant).map(function(x) { return parseNumerical(x) }) - } + constant = flatten(constant).map(function(x) { return parseNumerical(x) }) return constant; } @@ -254,6 +251,7 @@ function JSify(data, functionsOnly, givenFunctions) { substrate.addActor('GlobalVariable', { processItem: function(item) { function needsPostSet(value) { + if (typeof value !== 'string') return false; return value[0] in UNDERSCORE_OPENPARENS || value.substr(0, 14) === 'CHECK_OVERFLOW' || value.substr(0, 6) === 'GLOBAL'; } @@ -266,105 +264,82 @@ function JSify(data, functionsOnly, givenFunctions) { item.ctors.map(function(ctor) { return ' { func: function() { ' + ctor + '() } }' }).join(',\n') + '\n]);\n'; return ret; + } + + var constant = null; + var allocator = (BUILD_AS_SHARED_LIB && !item.external) ? 'ALLOC_NORMAL' : 'ALLOC_STATIC'; + var index = null; + if (item.external && BUILD_AS_SHARED_LIB) { + // External variables in shared libraries should not be declared as + // they would shadow similarly-named globals in the parent. + item.JS = ''; } else { - var constant = null; - var allocator = (BUILD_AS_SHARED_LIB && !item.external) ? 'ALLOC_NORMAL' : 'ALLOC_STATIC'; - var index = null; - if (item.external && BUILD_AS_SHARED_LIB) { - // External variables in shared libraries should not be declared as - // they would shadow similarly-named globals in the parent. - item.JS = ''; - } else { - item.JS = makeGlobalDef(item.ident); - } + item.JS = makeGlobalDef(item.ident); + } - if (item.external && !ASM_JS) { // ASM_JS considers externs to be globals - // Import external global variables from the library if available. - var shortident = item.ident.slice(1); - if (LibraryManager.library[shortident] && - LibraryManager.library[shortident].length && - !BUILD_AS_SHARED_LIB) { - if (addedLibraryItems[shortident]) return ret; - var val = LibraryManager.library[shortident]; - var padding; - if (Runtime.isNumberType(item.type) || isPointerType(item.type)) { - padding = [item.type].concat(zeros(Runtime.getNativeFieldSize(item.type)-1)); - } else { - padding = makeEmptyStruct(item.type); - } - var padded = val.concat(padding.slice(val.length)); - var js = item.ident + '=' + makePointer(padded, null, allocator, item.type, index) + ';' - if (LibraryManager.library[shortident + '__postset']) { - js += '\n' + LibraryManager.library[shortident + '__postset']; - } - ret.push({ - intertype: 'GlobalVariablePostSet', - JS: js - }); - } - return ret; + if (!NAMED_GLOBALS && isIndexableGlobal(item.ident)) { + index = makeGlobalUse(item.ident); // index !== null indicates we are indexing this + allocator = 'ALLOC_NONE'; + } + if (item.external) { + if (Runtime.isNumberType(item.type) || isPointerType(item.type)) { + constant = zeros(Runtime.getNativeFieldSize(item.type)); } else { - if (!NAMED_GLOBALS && isIndexableGlobal(item.ident)) { - index = makeGlobalUse(item.ident); // index !== null indicates we are indexing this - allocator = 'ALLOC_NONE'; - } - if (item.external) { - assert(ASM_JS); - if (Runtime.isNumberType(item.type) || isPointerType(item.type)) { - constant = zeros(Runtime.getNativeFieldSize(item.type)); - } else { - constant = makeEmptyStruct(item.type); - } - constant = JSON.stringify(constant); - } else { - constant = parseConst(item.value, item.type, item.ident); - } - if (typeof constant === 'string' && constant[0] != '[') { - constant = [constant]; // A single item. We may need a postset for it. - } - if (typeof constant === 'object') { - // This is a flattened object. We need to find its idents, so they can be assigned to later - constant.forEach(function(value, i) { - if (needsPostSet(value)) { // ident, or expression containing an ident - ret.push({ - intertype: 'GlobalVariablePostSet', - JS: makeSetValue(makeGlobalUse(item.ident), i, value, 'i32', false, true) + ';' // ignore=true, since e.g. rtti and statics cause lots of safe_heap errors - }); - constant[i] = '0'; - } - }); - } - // NOTE: This is the only place that could potentially create static - // allocations in a shared library. - constant = makePointer(constant, null, allocator, item.type, index); - var js; - - js = (index !== null ? '' : item.ident + '=') + constant + ';'; // \n Module.print("' + item.ident + ' :" + ' + makeGlobalUse(item.ident) + ');'; + constant = makeEmptyStruct(item.type); + } + } else { + constant = parseConst(item.value, item.type, item.ident); + } + assert(typeof constant === 'object');//, [typeof constant, JSON.stringify(constant), item.external]); - // Special case: class vtables. We make sure they are null-terminated, to allow easy runtime operations - if (item.ident.substr(0, 5) == '__ZTV') { - if (index !== null) { - index = getFastValue(index, '+', Runtime.alignMemory(calcAllocatedSize(Variables.globals[item.ident].type))); - } - js += '\n' + makePointer([0], null, allocator, ['void*'], index) + ';'; - } - if (!ASM_JS && (EXPORT_ALL || (item.ident in EXPORTED_GLOBALS))) { - js += '\nModule["' + item.ident + '"] = ' + item.ident + ';'; - } - if (BUILD_AS_SHARED_LIB == 2 && !item.private_) { - // TODO: make the assert conditional on ASSERTIONS - js += 'if (globalScope) { assert(!globalScope["' + item.ident + '"]); globalScope["' + item.ident + '"] = ' + item.ident + ' }'; - } - if (item.external && !NAMED_GLOBALS) { - assert(ASM_JS); - js = 'var ' + item.ident + ' = ' + js; // force an explicit naming, even if unnamed globals, for asm forwarding - } - return ret.concat({ - intertype: 'GlobalVariable', - JS: js, + // This is a flattened object. We need to find its idents, so they can be assigned to later + constant.forEach(function(value, i) { + if (needsPostSet(value)) { // ident, or expression containing an ident + ret.push({ + intertype: 'GlobalVariablePostSet', + JS: makeSetValue(makeGlobalUse(item.ident), i, value, 'i32', false, true) + ';' // ignore=true, since e.g. rtti and statics cause lots of safe_heap errors }); + constant[i] = '0'; } + }); + + if (item.external) { + // External variables in shared libraries should not be declared as + // they would shadow similarly-named globals in the parent, so do nothing here. + if (BUILD_AS_SHARED_LIB) return ret; + // Library items need us to emit something, but everything else requires nothing. + if (!LibraryManager.library[item.ident.slice(1)]) return ret; + } + + // ensure alignment + constant = constant.concat(zeros(Runtime.alignMemory(constant.length) - constant.length)); + + // Special case: class vtables. We make sure they are null-terminated, to allow easy runtime operations + if (item.ident.substr(0, 5) == '__ZTV') { + constant = constant.concat(zeros(Runtime.alignMemory(QUANTUM_SIZE))); + } + + // NOTE: This is the only place that could potentially create static + // allocations in a shared library. + constant = makePointer(constant, null, allocator, item.type, index); + + var js = (index !== null ? '' : item.ident + '=') + constant; + if (js) js += ';'; + + if (!ASM_JS && (EXPORT_ALL || (item.ident in EXPORTED_GLOBALS))) { + js += '\nModule["' + item.ident + '"] = ' + item.ident + ';'; } + if (BUILD_AS_SHARED_LIB == 2 && !item.private_) { + // TODO: make the assert conditional on ASSERTIONS + js += 'if (globalScope) { assert(!globalScope["' + item.ident + '"]); globalScope["' + item.ident + '"] = ' + item.ident + ' }'; + } + if (item.external && !NAMED_GLOBALS) { + js = 'var ' + item.ident + ' = ' + js; // force an explicit naming, even if unnamed globals, for asm forwarding + } + return ret.concat({ + intertype: 'GlobalVariable', + JS: js, + }); } }); @@ -1523,8 +1498,38 @@ function JSify(data, functionsOnly, givenFunctions) { print('assert(STATICTOP < TOTAL_MEMORY);\n'); } } - var generated = itemsDict.function.concat(itemsDict.type).concat(itemsDict.GlobalVariableStub).concat(itemsDict.GlobalVariable).concat(itemsDict.GlobalVariablePostSet); - if (!DEBUG_MEMORY) print(generated.map(function(item) { return item.JS }).join('\n')); + var generated = itemsDict.function.concat(itemsDict.type).concat(itemsDict.GlobalVariableStub).concat(itemsDict.GlobalVariable); + print(generated.map(function(item) { return item.JS }).join('\n')); + + if (phase == 'pre') { + if (memoryInitialization.length > 0) { + // apply postsets directly into the big memory initialization + itemsDict.GlobalVariablePostSet = itemsDict.GlobalVariablePostSet.filter(function(item) { + var m; + if (m = /^HEAP([\dFU]+)\[([()>\d]+)\] *= *([()|\d{}\w_' ]+);?$/.exec(item.JS)) { + var type = getTypeFromHeap(m[1]); + var bytes = Runtime.getNativeTypeSize(type); + var target = eval(m[2]) << log2(bytes); + var value = m[3]; + try { + value = eval(value); + } catch(e) { + // possibly function table {{{ FT_* }}} etc. + if (value.indexOf('{{ ') < 0) return true; + } + writeInt8s(memoryInitialization, target - TOTAL_STACK, value, type); + return false; + } + return true; + }); + // write out the singleton big memory initialization value + print('/* memory initializer */ ' + makePointer(memoryInitialization, null, 'ALLOC_NONE', 'i8', 'TOTAL_STACK', true)); // we assert on TOTAL_STACK == GLOBAL_BASE + } else { + print('/* memory initializer */'); // test purposes + } + } + + print(itemsDict.GlobalVariablePostSet.map(function(item) { return item.JS }).join('\n')); return; } @@ -1546,7 +1551,6 @@ function JSify(data, functionsOnly, givenFunctions) { } }); } - JSify(globalsData, true, Functions); globalsData = null; data.unparsedGlobalss = null; |