diff options
author | alon@honor <none@none> | 2010-09-20 18:59:15 -0700 |
---|---|---|
committer | alon@honor <none@none> | 2010-09-20 18:59:15 -0700 |
commit | fea809cb090c648f58f11561f7f25ce813d9944f (patch) | |
tree | 355bc25d3bab157799caf339f6917683aca9ac41 /src/jsifier.js | |
parent | 9e66429fa4154058798be6cc554408697cc6bfc8 (diff) |
refactor into files
--HG--
rename : src/parser.js => src/compiler.js
Diffstat (limited to 'src/jsifier.js')
-rw-r--r-- | src/jsifier.js | 663 |
1 files changed, 663 insertions, 0 deletions
diff --git a/src/jsifier.js b/src/jsifier.js new file mode 100644 index 00000000..e99917e7 --- /dev/null +++ b/src/jsifier.js @@ -0,0 +1,663 @@ +// Convert analyzed data to javascript + +function JSify(data) { + substrate = new Substrate('JSifyer'); + + var TYPES = data.types; + + // type + substrate.addZyme('Type', { + processItem: function(item) { + var type = TYPES[item.name_]; + if (type.needsFlattening) { + item.JS = 'var ' + toNiceIdent(item.name_) + '___FLATTENER = ' + JSON.stringify(TYPES[item.name_].flatIndexes) + ';'; + } else { + item.JS = '// type: ' + item.name_; + } + item.__result__ = true; + return [item]; + }, + }); + + function makePointer(slab, pos) { + // XXX hardcoded ptr impl + if (slab == 'HEAP') return pos; + if (slab[0] != '[') { + slab = '[' + slab + ']'; + } + return 'Pointer_make(' + slab + ', ' + (pos ? pos : 0) + ')'; + // return '{ slab: ' + slab + ', pos: ' + (pos ? pos : 0) + ' }'; + // return '[' + slab + ', ' + (pos ? pos : 0) + ']'; + } + + function makeGetSlab(ptr) { + // XXX hardcoded ptr impl + // return ptr + '.slab'; + return 'HEAP'; + } + + function makeGetPos(ptr) { + // XXX hardcoded ptr impl + // return ptr + '.pos'; + return ptr; + } + + function makeGetValue(ptr, pos, noNeedFirst) { + return makeGetSlab(ptr) + '[' + (noNeedFirst ? '0' : makeGetPos(ptr)) + (pos ? ' + ' + pos : '') + ']'; + } + + function makeSetValue(ptr, pos, value, noNeedFirst) { + if (SAFE_HEAP) { + return 'SAFE_HEAP_STORE(' + (noNeedFirst ? '0' : makeGetPos(ptr)) + (pos ? ' + ' + pos : '') + ', ' + value + ')'; + } else { + return makeGetSlab(ptr) + '[' + (noNeedFirst ? '0' : makeGetPos(ptr)) + (pos ? ' + ' + pos : '') + '] = ' + value; + } + } + + function makeEmptyStruct(type) { + dprint('types', '??makeemptystruct?? ' + dump(type)); + // XXX hardcoded ptr impl + var ret = []; + var typeData = TYPES[type]; + assertTrue(typeData); + for (var i = 0; i < typeData.flatSize; i++) { + ret.push(0); + } + return ret; + } + + // Gets an entire constant expression + function parseConst(value, type) { + dprint('gconst', '//yyyyy ' + JSON.stringify(value) + ',' + type + '\n'); + if (isNumberType(type) || pointingLevels(type) == 1) { + return makePointer(parseNumerical(value.text)); + } else if (value.text == 'zeroinitializer') { + return makePointer(JSON.stringify(makeEmptyStruct(type))); + } else if (value.text && value.text[0] == '"') { + value.text = value.text.substr(1, value.text.length-2); + return makePointer(JSON.stringify(parseLLVMString(value.text)) + ' /* ' + value.text + '*/'); + } else { + // Gets an array of constant items, separated by ',' tokens + function handleSegments(tokens) { + // Handle a single segment (after comma separation) + function handleSegment(segment) { + dprint('gconst', '// seggg: ' + JSON.stringify(segment) + '\n' + '\n') + if (segment[1].text == 'null') { + return '0'; + } else if (segment[1].text == 'zeroinitializer') { + return JSON.stringify(makeEmptyStruct(segment[0].text)); + } else if (segment[1].text == 'getelementptr') { + return finalizeGetElementPtr(parseGetElementPtr(segment)); + } else if (segment[1].text in searchable('bitcast', 'inttoptr', 'ptrtoint')) { + var type = segment[2].item[0].tokens.slice(-1)[0].text; // TODO: Use this? + return handleSegment(segment[2].item[0].tokens.slice(0, -2)); + } else if (segment[1].text == 'add') { + var subSegments = splitTokenList(segment[2].item[0].tokens); + return '(' + handleSegment(subSegments[0]) + ' + ' + handleSegment(subSegments[1]) + ')'; + } else if (segment[1].type == '{') { + return '[' + handleSegments(segment[1].tokens) + ']'; + } else if (segment.length == 2) { + return parseNumerical(toNiceIdent(segment[1].text)); + } else { + throw 'Invalid segment: ' + dump(segment); + } + }; + return splitTokenList(tokens).map(handleSegment).map(parseNumerical).join(', '); + } + if (value.item) { + // list of items + return makePointer('[ ' + handleSegments(value.item[0].tokens) + ' ]'); + } else if (value.type == '{') { + // struct + return makePointer('[ ' + handleSegments(value.tokens) + ' ]'); + } else if (value[0]) { + return makePointer('[ ' + handleSegments(value[0].tokens) + ' ]'); + } else { + throw '// failzzzzzzzzzzzzzz ' + dump(value.item) + ' ::: ' + dump(value); + } + } + } + + // globalVariablw + substrate.addZyme('GlobalVariable', { + processItem: function(item) { + dprint('gconst', '// zz global Cons: ' + dump(item) + ' :: ' + dump(item.value)); + if (item.ident == '_llvm_global_ctors') { + item.JS = '\n__globalConstructor__ = function() {\n' + + item.ctors.map(function(ctor) { return ' ' + toNiceIdent(ctor) + '();' }).join('\n') + + '\n}\n'; + } else if (item.type.text == 'external') { + item.JS = 'var ' + item.ident + ' = ' + '0; /* external value? */'; + } else { + // GETTER - lazy loading, fixes issues with ordering. + item.JS = 'this.__defineGetter__("' + item.ident + '", function() { delete ' + item.ident + '; ' + item.ident + ' = ' + parseConst(item.value, item.type.text) + '; return ' + item.ident + ' });'; + } + item.__result__ = true; + return [item]; + }, + }); + + // functionStub + substrate.addZyme('FunctionStub', { + processItem: function(item) { + var shortident = item.ident.substr(1); + if (shortident in Snippets) { + item.JS = item.ident + ' = ' + Snippets[shortident].toString(); + } else { + item.JS = '// stub for ' + item.ident; + } + item.__result__ = true; + return [item]; + }, + }); + + // function splitter + substrate.addZyme('FunctionSplitter', { + processItem: function(item) { + var ret = [item]; + item.splitItems = 0; + item.labels.forEach(function(label) { + label.lines.forEach(function(line) { + line.func = item.ident; + line.funcData = item; + line.parentLabel = label.ident; + ret.push(line); + item.splitItems ++; + }); + }); + + this.forwardItems(ret, 'FuncLineTriager'); + }, + }); + // function reconstructor & post-JS optimizer + substrate.addZyme('FunctionReconstructor', { + funcs: {}, + seen: {}, + processItem: function(item) { + if (this.seen[item.__uid__]) return; + if (item.intertype == 'function') { + this.funcs[item.ident] = item; + item.relines = {}; + this.seen[item.__uid__] = true; + return; + } + var line = item; + var func = this.funcs[line.func]; + if (!func) return; + + // Re-insert our line + this.seen[item.__uid__] = true; + var label = func.labels.filter(function(label) { return label.ident == line.parentLabel })[0]; + label.lines = label.lines.map(function(line2) { + return (line2.lineNum !== line.lineNum) ? line2 : line; + }); + func.splitItems --; + // OLD delete line.funcData; // clean up + if (func.splitItems > 0) return; + + // We have this function all reconstructed, go and finalize it's JS! + + var hasVarArgs = false, hasPhi = false; + var params = parseParamTokens(func.params.item[0].tokens).map(function(param) { + hasPhi = hasPhi || param.intertype == 'phi'; + if (param.intertype == 'varargs') { + hasVarArgs = true; + return null; + } + return toNiceIdent(param.ident); + }).filter(function(param) { return param != null });; + + func.JS = '\nfunction ' + func.ident + '(' + params.join(', ') + ') {\n'; + if (LABEL_DEBUG) func.JS += " print(INDENT + ' Entering: " + func.ident + "'); INDENT += ' ';\n"; + + if (hasVarArgs) { + func.JS += ' __numArgs__ = ' + params.length + ';\n'; + } + + // Walk function blocks and generate JS + function walkBlock(block, indent) { + if (!block) return ''; + function getLabelLines(label, indent) { + var ret = ''; + if (LABEL_DEBUG) { + ret += indent + " print(INDENT + '" + func.ident + ":" + label.ident + "');\n"; + } + return ret + label.lines.map(function(line) { return indent + line.JS + (line.comment ? ' // ' + line.comment : '') }).join('\n'); + } + var ret = ''; + if (block.type == 'emulated' || block.type == 'simple') { + if (block.labels.length > 1) { + ret += indent + 'var __label__ = ' + getLabelId(block.entry) + '; /* ' + block.entry + ' */\n'; + ret += indent + 'while(1) switch(__label__) {\n'; + ret += block.labels.map(function(label) { + return indent + ' case ' + getLabelId(label.ident) + ': // ' + label.ident + '\n' + + getLabelLines(label, indent + ' '); + }).join('\n'); + ret += '\n' + indent + '}'; + } else { + ret += getLabelLines(block.labels[0], indent); + } + ret += '\n'; + } else if (block.type == 'loop') { +// if (mustGetTo(first.outLabels[0], [first.ident, first.outLabels[1]])) { /* left branch must return here, or go to right branch */ + ret += indent + block.entry + ': while(1) {\n'; + ret += walkBlock(block.inc, indent + ' '); + ret += walkBlock(block.rest, indent + ' '); + ret += indent + '}\n'; + } else if (block.type == 'breakingif') { + ret += walkBlock(block.check, indent); + ret += indent + block.entry + ': do { if (' + block.ifVar + ') {\n'; + ret += walkBlock(block.ifTrue, indent + ' '); + ret += indent + '} } while(0);\n'; + } else if (block.type == 'if') { + ret += walkBlock(block.check, indent); + ret += indent + 'if (' + block.ifVar + ') {\n'; + ret += walkBlock(block.ifTrue, indent + ' '); + ret += indent + '}\n'; + } else { + ret = 'XXXXXXXXX!'; + } + return ret + walkBlock(block.next, indent); + } + func.JS += walkBlock(func.block, ' '); + // Finalize function + if (LABEL_DEBUG) func.JS += " INDENT = INDENT.substr(0, INDENT.length-2);\n"; + func.JS += '}\n'; + func.__result__ = true; + return func; + }, + }); + + function getVarData(funcData, ident) { + if (funcData.variables[ident]) { + return funcData.variables[ident].impl; + } else { + return 'emulated'; // All global are emulated + } + } + + substrate.addZyme('FuncLineTriager', { + processItem: function(item) { + if (item.intertype == 'function') { + this.forwardItem(item, 'FunctionReconstructor'); + } else if (item.JS) { + if (item.parentLineNum) { + this.forwardItem(item, 'AssignReintegrator'); + } else { + this.forwardItem(item, 'FunctionReconstructor'); + } + } else { + this.forwardItem(item, 'Intertype:' + item.intertype); + } + }, + }); + + // assignment + substrate.addZyme('Intertype:assign', { + processItem: function(item) { + var pair = splitItem(item, 'value', ['funcData']); + this.forwardItem(pair.parent, 'AssignReintegrator'); + this.forwardItem(pair.child, 'FuncLineTriager'); + }, + }); + substrate.addZyme('AssignReintegrator', makeReintegrator(function(item, child) { + // 'var', since this is SSA - first assignment is the only assignment, and where it is defined + item.JS = (item.overrideSSA ? '' : 'var ') + toNiceIdent(item.ident); + + var type = item.value.type.text; + var value = parseNumerical(item.value.JS); + //print("zz var: " + item.JS); + var impl = getVarData(item.funcData, item.ident); + switch (impl) { + case VAR_NATIVE: { + break; + } + case VAR_NATIVIZED: { + // SSA, so this must be the alloca. No need for a value + if (!item.overrideSSA) value = ''; + break; + } + case VAR_EMULATED: { + break; + } + default: print('zz unknown impl: ' + impl); + } + if (value) + item.JS += ' = ' + value; + item.JS += ';'; + + this.forwardItem(item, 'FunctionReconstructor'); + })); + + // Function lines + function makeFuncLineZyme(intertype, func) { + substrate.addZyme('Intertype:' + intertype, { + processItem: function(item) { + item.JS = func(item); + if (!item.JS) throw "XXX - no JS generated for " + dump(item); + this.forwardItem(item, 'FuncLineTriager'); + }, + }); + } + makeFuncLineZyme('store', function(item) { + //print('// zzqqzz ' + dump(item.value) + ' :::: ' + dump(item.pointer) + ' :::: '); + var ident = toNiceIdent(item.ident); + var value; + if (item.value.intertype == 'getelementptr') { + value = finalizeGetElementPtr(item.value); + } else { + value = toNiceIdent(item.value.ident); + } + if (pointingLevels(item.pointerType.text) == 1) { + value = parseNumerical(value, removePointing(item.pointerType.text)); + } + //print("// zz seek " + ident + ',' + dump(item)); + var impl = getVarData(item.funcData, item.ident); + var ret; + switch (impl) { + case VAR_NATIVIZED: ret = ident + ' = ' + value + ';'; break; // We have the actual value here + case VAR_EMULATED: ret = makeSetValue(ident, 0, value) + ';'; break; + default: print('zz unknown [store] impl: ' + impl); + } +/* + if (LINEDEBUG && value) { + ret += '\nprint(INDENT + "' + ident + ' == " + JSON.stringify(' + ident + '));'; + ret += '\nprint(INDENT + "' + ident + ' == " + (' + ident + ' && ' + ident + '.toString ? ' + ident + '.toString() : ' + ident + '));'; + } +*/ + return ret; + }); + + var LABEL_IDs = {}; + var LABEL_ID_COUNTER = 0; + function getLabelId(label) { + //print('needs id: ' + label + ' : ' + JSON.stringify(LABEL_IDs)); + label = toNiceIdent(label); + if (label in LABEL_IDs) return LABEL_IDs[label]; + return LABEL_IDs[label] = LABEL_ID_COUNTER ++; + } + + function makeBranch(label) { + if (label[0] == 'B') { + if (label[1] == 'R') { + return 'break ' + label.substr(5) + ';'; + } else if (label[1] == 'C') { + return 'continue ' + label.substr(5) + ';'; + } else { // NOPP + return ';'; // Returning no text might confuse this parser + } + } else { + // FIXME: We should use __lastLabel__ only if we actually need + // it, which is in the case of phi being used on the label. + return '__lastLabel__ = __label__; __label__ = ' + getLabelId(label) + '; break;'; + } + } + + makeFuncLineZyme('branch', function(item) { + //print('branch: ' + dump(item)); + if (!item.ident) { + return makeBranch(item.label); + } else { + var labelTrue = makeBranch(item.labelTrue); + var labelFalse = makeBranch(item.labelFalse); + if (labelTrue == ';' && labelFalse == ';') return ';'; + var head = 'if (' + item.ident + ') { '; + var head2 = 'if (!(' + item.ident + ')) { '; + var else_ = ' } else { '; + var tail = ' }'; + if (labelTrue == ';') { + return head2 + labelFalse + tail; + } else if (labelFalse == ';') { + return head + labelTrue + tail; + } else { + return head + labelTrue + else_ + labelFalse + tail; + } + } + }); + makeFuncLineZyme('switch', function(item) { + var ret = ''; + var first = true; + item.switchLabels.forEach(function(switchLabel) { + if (!first) { + ret += 'else '; + } else { + first = false; + } + ret += 'if (' + item.ident + ' == ' + switchLabel.value + ') {\n'; + ret += ' ' + makeBranch(switchLabel.label) + '\n'; + ret += '}\n'; + }); + ret += 'else {\n'; + ret += makeBranch(item.defaultLabel) + '\n'; + ret += '}\n'; + if (item.value) { + ret += ' ' + toNiceIdent(item.value); + } + return ret; + }); + makeFuncLineZyme('return', function(item) { + var ret = ''; + if (LABEL_DEBUG) ret += "INDENT = INDENT.substr(0, INDENT.length-2);\n"; + ret += 'return'; + if (item.value) { + ret += ' ' + toNiceIdent(item.value); + } + return ret + ';'; + }); + makeFuncLineZyme('invoke', function(item) { + // Wrapping in a function lets us easily return values if we are + // in an assignment + var ret = '(function() { try { return ' + + makeFunctionCall(item.ident, item.params) + '; ' + + '__THREW__ = false } catch(e) { ' + + '__THREW__ = true; ' + + '} })(); if (!__THREW__) { ' + makeBranch(item.toLabel) + ' } else { ' + makeBranch(item.unwindLabel) + ' }'; + return ret; + }); + makeFuncLineZyme('load', function(item) { + //print('// zz LOAD ' + dump(item) + ' :: ' + dump(item.tokens)); + var ident = toNiceIdent(item.ident); + var impl = getVarData(item.funcData, item.ident); + switch (impl) { + case VAR_NATIVIZED: { + return ident; // We have the actual value here + } + case VAR_EMULATED: return makeGetValue(ident); + default: return "unknown [load] impl: " + impl; + } + }); + makeFuncLineZyme('alloca', function(item) { + dprint('alloca', dump(item)); + if (pointingLevels(item.allocatedType.text) == 0 && isStructType(item.allocatedType.text)) { + // TODO: allocate on a stack, not on the heap (we currently leak all this) + return makePointer(JSON.stringify(makeEmptyStruct(item.allocatedType.text))); + } else { + return makePointer('[0]'); + } + }); + makeFuncLineZyme('phi', function(item) { + dprint('phi', dump(item)); + return '__lastLabel__ == ' + getLabelId(item.label1) + ' ? ' + toNiceIdent(item.value1) + ' : ' + toNiceIdent(item.value2); + }); + makeFuncLineZyme('mathop', function(item) { with(item) { + dprint('mathop', 'mathop: ' + dump(item)); + switch (item.op) { + case 'add': return ident + ' + ' + ident2; + case 'sub': return ident + ' - ' + ident2; + case 'sdiv': case 'udiv': return 'Math.floor(' + ident + ' / ' + ident2 + ')'; + case 'mul': return ident + ' * ' + ident2; + case 'urem': case 'srem': return 'Math.floor(' + ident + ' % ' + ident2 + ')'; + case 'or': return ident + ' | ' + ident2; + case 'and': return ident + ' & ' + ident2; + case 'xor': return ident + ' ^ ' + ident2; + case 'shl': case 'ashl': case 'lshl': return ident + ' << ' + ident2; + case 'shr': case 'ashr': case 'lshr': return ident + ' >> ' + ident2; + case 'fadd': return ident + ' + ' + ident2; + case 'fsub': return ident + ' - ' + ident2; + case 'fdiv': return ident + ' / ' + ident2; + case 'fmul': return ident + ' * ' + ident2; + case 'uitofp': case 'sitofp': return ident; + case 'fptoui': case 'fptosi': return 'Math.floor(' + ident + ')'; + case 'icmp': { + switch (variant) { + case 'uge': case 'sge': return '0+(' + ident + ' >= ' + ident2 + ')'; + case 'ule': case 'sle': return '0+(' + ident + ' <= ' + ident2 + ')'; + case 'ugt': case 'sgt': return '0+(' + ident + ' > ' + ident2 + ')'; + case 'ult': case 'slt': return '0+(' + ident + ' < ' + ident2 + ')'; + case 'ne': case 'une': return '0+(' + ident + ' != ' + ident2 + ')'; + case 'eq': return '0+(' + ident + ' == ' + ident2 + ')'; + default: throw 'Unknown icmp variant: ' + variant + } + } + case 'fcmp': { + switch (variant) { + case 'uge': case 'oge': return '0+(' + ident + ' >= ' + ident2 + ')'; + case 'ule': case 'ole': return '0+(' + ident + ' <= ' + ident2 + ')'; + case 'ugt': case 'ogt': return '0+(' + ident + ' > ' + ident2 + ')'; + case 'ult': case 'olt': return '0+(' + ident + ' < ' + ident2 + ')'; + case 'une': case 'one': return '0+(' + ident + ' != ' + ident2 + ')'; + case 'ueq': case 'oeq': return '0+(' + ident + ' == ' + ident2 + ')'; + default: throw 'Unknown fcmp variant: ' + variant + } + } + case 'zext': case 'fpext': case 'trunc': case 'sext': case 'fptrunc': return ident; + case 'select': return '(' + ident + ' ? ' + ident3 + ' : ' + ident4 + ')'; + case 'ptrtoint': { + if (type.text != 'i8*') print('// XXX Warning: Risky ptrtoint operation on line ' + lineNum); + return ident; + } + case 'inttoptr': { + print('// XXX Warning: inttoptr operation on line ' + lineNum); + return ident; + } + default: throw 'Unknown mathcmp op: ' + item.op + } + } }); +/* + return [{ + __result__: true, + intertype: 'mathop', + op: op, + variant: variant, + type: item.tokens[1].text, + ident: item.tokens[2].text, + value: item.tokens[4].text, + lineNum: item.lineNum, + }]; +*/ + + function getGetElementPtrIndexes(item) { + var ident = item.ident; + var type = item.params[0].type.text; // param 0 == type + // struct pointer, struct*, and getting a ptr to an element in that struct. Param 1 is which struct, then we have items in that + // struct, and possibly further substructures, all embedded + // can also be to 'blocks': [8 x i32]*, not just structs + type = removePointing(type); + var indexes = [makeGetPos(ident)]; + var offset = toNiceIdent(item.params[1].ident); + if (offset != 0) { + indexes.push((isStructType(type) && TYPES[type].flatSize != 1 ? TYPES[type].flatSize + '*' : '') + offset); + } + item.params.slice(2, item.params.length).forEach(function(arg) { + var curr = toNiceIdent(arg.ident); + // TODO: If index is constant, optimize + var typeData = TYPES[type]; + if (isStructType(type) && typeData.needsFlattening) { + if (typeData.flatFactor) { + indexes.push(curr + '*' + typeData.flatFactor); + } else { + indexes.push(toNiceIdent(type) + '___FLATTENER[' + curr + ']'); + } + } else { + if (curr != 0) { + indexes.push(curr); + } + } + type = TYPES[type] ? TYPES[type].fields[curr] : ''; + }); + return indexes.join('+'); + } + + function finalizeGetElementPtr(item) { + //print('//zz finalize: ' + dump(item.params)); + // TODO: statically combine indexes here if consts + return makePointer(makeGetSlab(item.ident), getGetElementPtrIndexes(item)); + } + + function finalizeBitcast(item) { + //print('//zz finalizeBC: ' + dump(item)); + return item.ident; + } + + makeFuncLineZyme('bitcast', function(item) { + // XXX Don't we need to copy ptr - i.e. create new ones (at least if uses > just the next line)? + // XXX hardcoded ptr impl - as ptrs are ints, we don't need to copy + var ident = toNiceIdent(item.ident); + return ident; + }); + function makeFunctionCall(ident, params) { + // Special cases + if (ident == '_llvm_va_start') { + var args = 'Array.prototype.slice.call(arguments, __numArgs__)'; + var data = 'Pointer_make([' + args + '.length].concat(' + args + '), 0)'; + if (SAFE_HEAP) { + return 'SAFE_HEAP_STORE(' + params[0].ident + ', ' + data + ', 0)'; + } else { + return 'HEAP[' + params[0].ident + '] = ' + data; + } + } else if (ident == '_llvm_va_end') { + return ';' + } + + var params = params.map(function(param) { + if (param.intertype === 'getelementptr') { + return finalizeGetElementPtr(param); + } else if (param.intertype === 'bitcast') { + return finalizeBitcast(param); + } else { + return toNiceIdent(param.ident); //.value;//'??arg ' + param.intertype + '??'; + } + }); + return ident + '(' + params.join(', ') + ')'; + } + makeFuncLineZyme('getelementptr', function(item) { return finalizeGetElementPtr(item) }); + makeFuncLineZyme('call', function(item) { + return makeFunctionCall(item.ident, item.params) + (item.standalone ? ';' : ''); + }); + + // Optimzed intertypes + + makeFuncLineZyme('fastgetelementptrload', function(item) { +//print('// FAST ' + dump(item)); + return 'var ' + item.ident + ' = ' + makeGetValue(item.value.ident, getGetElementPtrIndexes(item.value), true) + ';'; + }); + makeFuncLineZyme('fastgetelementptrstore', function(item) { +//print('// FAST ' + dump(item)); + return makeSetValue(item.value.ident, getGetElementPtrIndexes(item.value), item.ident, true) + ';'; + }); + + makeFuncLineZyme('unreachable', function(item) { return '// unreachable' }); + + // Final combiner + + function finalCombiner(items) { + var ret = items.filter(function(item) { return item.intertype == 'type' }); + ret = ret.concat(items.filter(function(item) { return item.intertype == 'globalVariable' })); + ret.push('\n'); + ret = ret.concat(items.filter(function(item) { return item.intertype == 'functionStub' })); + ret.push('\n'); + ret = ret.concat(items.filter(function(item) { return item.intertype == 'function' })); + return ret.map(function(item) { return item.JS }).join('\n'); + } + + // Data + + substrate.addItems(values(data.types).filter(function(type) { return type.lineNum != '?' }), 'Type'); + substrate.addItems(data.globalVariables, 'GlobalVariable'); + substrate.addItems(data.functions, 'FunctionSplitter'); + substrate.addItems(data.functionStubs, 'FunctionStub'); + + return preprocess(read('preamble.js')) + finalCombiner(substrate.solve()) + read('postamble.js'); +// return finalCombiner(substrate.solve()); +} + |