diff options
author | alon@honor <none@none> | 2010-08-29 16:25:06 -0700 |
---|---|---|
committer | alon@honor <none@none> | 2010-08-29 16:25:06 -0700 |
commit | ee99b2e41f47cdaa71fa9b16bdead0a95b928af2 (patch) | |
tree | 5396d7471d5f6314487534e73513ca69c1e7024e /src/parser.js | |
parent | ce8bc85042134d8a10b50100c23995246d3ab8ca (diff) |
Support for llvm 'switch'
Diffstat (limited to 'src/parser.js')
-rw-r--r-- | src/parser.js | 135 |
1 files changed, 104 insertions, 31 deletions
diff --git a/src/parser.js b/src/parser.js index 3551c281..8997d3c4 100644 --- a/src/parser.js +++ b/src/parser.js @@ -316,15 +316,24 @@ function intertyper(data) { processItem: function(item) { var lines = item.llvmText.split('\n'); var ret = []; + var inContinual = false; for (var i = 0; i < lines.length; i++) { - if (/^\ +to.*/g.test(lines[i])) { + var line = lines[i]; + if (inContinual || /^\ +to.*/g.test(line)) { // to after invoke - ret.slice(-1)[0].lineText += lines[i]; + ret.slice(-1)[0].lineText += line; + if (/^\ +\]/g.test(line)) { // end of llvm switch + inContinual = false; + } } else { ret.push({ - lineText: lines[i], + lineText: line, lineNum: i + 1, }); + if (/^\ +switch\ .*/g.test(line)) { + // beginning of llvm switch + inContinual = true; + } } } return ret.filter(function(item) { return item.lineText; }); @@ -784,6 +793,34 @@ function intertyper(data) { }]; }, }); + // 'switch' + substrate.addZyme({ + selectItem: function(item) { return item.indent === 2 && item.tokens && item.tokens.length >= 2 && item.tokens[0].text == 'switch' && + !item.intertype }, + processItem: function(item) { + function parseSwitchLabels(item) { + var ret = []; + var tokens = item.item[0].tokens; + while (tokens.length > 0) { + ret.push({ + value: tokens[1].text, + label: toNiceIdent(tokens[4].text), + }); + tokens = tokens.slice(5); + } + return ret; + } + return [{ + __result__: true, + intertype: 'switch', + type: item.tokens[1].text, + ident: item.tokens[2].text, + defaultLabel: item.tokens[5].text, + switchLabels: parseSwitchLabels(item.tokens[6]), + lineNum: item.lineNum, + }]; + }, + }); // function end substrate.addZyme({ selectItem: function(item) { return item.indent === 0 && item.tokens && item.tokens.length >= 1 && item.tokens[0].text == '}' && !item.intertype }, @@ -1123,13 +1160,20 @@ function analyzer(data) { function replaceLabels(line, labelId, toLabelId) { //print('// XXX replace ' + labelId + ' with ' + toLabelId); - if (line.intertype != 'branch') return; - ['label', 'labelTrue', 'labelFalse', 'toLabel', 'unwindLabel'].forEach(function(id) { - if (line[id] && line[id] == labelId) { - line[id] = toLabelId; - //print(' replaced!'); - } - }); + function process(item) { + ['label', 'labelTrue', 'labelFalse', 'toLabel', 'unwindLabel', 'defaultLabel'].forEach(function(id) { + if (item[id] && item[id] == labelId) { + item[id] = toLabelId; + //print(' replaced!'); + } + }); + } + if (['branch', 'invoke'].indexOf(line.intertype) != -1) { + process(line); + } else if (line.intertype == 'switch') { + process(line); + line.switchLabels.forEach(process); + } } function replaceLabelLabels(label, labelId, toLabelId) { @@ -1162,18 +1206,25 @@ function analyzer(data) { labels.forEach(function(label) { dprint('find direct branchings at label: ' + label.ident + ':' + label.inLabels + ':' + label.outLabels); label.lines.forEach(function(line) { - if (['branch', 'invoke'].indexOf(line.intertype) != -1) { + function process(item) { ['label', 'labelTrue', 'labelFalse', 'toLabel', 'unwindLabel'].forEach(function(id) { - if (line[id]) { - if (line[id][0] == 'B') { // BREAK, BCONT, BNOPP + if (item[id]) { + if (item[id][0] == 'B') { // BREAK, BCONT, BNOPP label.hasBreak = true; } else { - label.outLabels.push(line[id]); - labelsDict[line[id]].inLabels.push(label.ident); + label.outLabels.push(item[id]); + labelsDict[item[id]].inLabels.push(label.ident); } } }); } + if (['branch', 'invoke'].indexOf(line.intertype) != -1) { + process(line); + } else if (line.intertype == 'switch') { + process(line); + line.switchLabels.forEach(process); + } + label.hasReturn |= line.intertype == 'return'; }); }); @@ -2078,26 +2129,27 @@ function JSify(data) { return LABEL_IDs[label] = LABEL_ID_COUNTER ++; } - makeFuncLineZyme('branch', function(item) { - //print('branch: ' + dump(item)); - function getIt(tf) { - if (tf[0] == 'B') { - if (tf[1] == 'R') { - return 'break ' + tf.substr(5) + ';'; - } else if (tf[1] == 'C') { - return 'continue ' + tf.substr(5) + ';'; - } else { // NOPP - return ';'; // Returning no text might confuse this parser - } - } else { - return '__label__ = ' + getLabelId(tf) + '; break;'; + 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 { + return '__label__ = ' + getLabelId(label) + '; break;'; } + } + + makeFuncLineZyme('branch', function(item) { + //print('branch: ' + dump(item)); if (!item.ident) { - return getIt(item.label); + return makeBranch(item.label); } else { - var labelTrue = getIt(item.labelTrue); - var labelFalse = getIt(item.labelFalse); + var labelTrue = makeBranch(item.labelTrue); + var labelFalse = makeBranch(item.labelFalse); if (labelTrue == ';' && labelFalse == ';') return ';'; var head = 'if (' + item.ident + ') { '; var head2 = 'if (!(' + item.ident + ')) { '; @@ -2112,6 +2164,27 @@ function JSify(data) { } } }); + 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 (LINEDEBUG) ret += "INDENT = INDENT.substr(0, INDENT.length-2);\n"; |