diff options
author | Alon Zakai <azakai@mozilla.com> | 2011-01-17 19:01:19 -0800 |
---|---|---|
committer | Alon Zakai <azakai@mozilla.com> | 2011-01-17 19:01:19 -0800 |
commit | 23515d06052a453efdb4d77fa517ebd14594d3be (patch) | |
tree | 4111e6f3513de81922307ef6f606b33e520e8f93 | |
parent | 1f3de5c76e4947afccca350da24859e52f6aa83f (diff) |
handle odd llvm with branches in the middle of labels; all tests pass
-rw-r--r-- | src/analyzer.js | 13 | ||||
-rw-r--r-- | src/jsifier.js | 10 | ||||
-rw-r--r-- | src/settings.js | 2 | ||||
-rw-r--r-- | tests/cases/breakinthemiddle.ll | 18 |
4 files changed, 36 insertions, 7 deletions
diff --git a/src/analyzer.js b/src/analyzer.js index 50683ec7..ae40896d 100644 --- a/src/analyzer.js +++ b/src/analyzer.js @@ -39,6 +39,7 @@ function analyzer(data, givenTypes) { }); // Functions & labels item.functions = []; + var currLabelFinished; // Sometimes LLVM puts a branch in the middle of a label. We need to ignore all lines after that. for (var i = 0; i < item.items.length; i++) { var subItem = item.items[i]; if (subItem.intertype == 'function') { @@ -60,10 +61,18 @@ function analyzer(data, givenTypes) { } else if (subItem.intertype == 'label') { item.functions.slice(-1)[0].labels.push(subItem); subItem.lines = []; + currLabelFinished = false; } else if (item.functions.length > 0 && item.functions.slice(-1)[0].endLineNum === null) { // Internal line - item.functions.slice(-1)[0].lines.push(subItem); - item.functions.slice(-1)[0].labels.slice(-1)[0].lines.push(subItem); + if (!currLabelFinished) { + item.functions.slice(-1)[0].lines.push(subItem); + item.functions.slice(-1)[0].labels.slice(-1)[0].lines.push(subItem); + if (subItem.intertype === 'branch') { + currLabelFinished = true; + } + } else { + print('// WARNING: content after a branch in a label, line: ' + subItem.lineNum); + } } else { print("ERROR: what is this? " + JSON.stringify(subItem)); } diff --git a/src/jsifier.js b/src/jsifier.js index 847b198d..7efc407c 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -442,7 +442,7 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions, givenGlobalVaria if (block.type == 'emulated') { if (block.labels.length > 1) { if (block.entries.length == 1) { - ret += indent + '__label__ = ' + getLabelId(block.entries[0]) + '; /* ' + block.entries[0] + ' */\n'; + ret += indent + '__label__ = ' + getLabelId(block.entries[0]) + '; ' + (SHOW_LABELS ? '/* ' + block.entries[0] + ' */' : '') + '\n'; } // otherwise, should have been set before! ret += indent + 'while(1) switch(__label__) {\n'; ret += block.labels.map(function(label) { @@ -451,11 +451,11 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions, givenGlobalVaria }).join('\n'); ret += '\n' + indent + ' default: assert(0, "bad label: " + __label__);\n' + indent + '}'; } else { - ret += getLabelLines(block.labels[0], indent); + ret += (SHOW_LABELS ? indent + '/* ' + block.entries[0] + ' */' : '') + '\n' + getLabelLines(block.labels[0], indent); } ret += '\n'; } else if (block.type == 'reloop') { - ret += indent + block.id + ': while(1) { // ' + block.entries + '\n'; + ret += indent + block.id + ': while(1) { ' + (SHOW_LABELS ? ' /* ' + block.entries + + ' */' : '') + '\n'; ret += walkBlock(block.inner, indent + ' '); ret += indent + '}\n'; } else if (block.type == 'multiple') { @@ -632,7 +632,7 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions, givenGlobalVaria var parts = label.split('|'); var trueLabel = parts[1]; var oldLabel = parts[2]; - var labelSetting = '__label__ = ' + getLabelId(oldLabel) + '; /* ' + cleanLabel(oldLabel) + ' */ '; // TODO: optimize away + var labelSetting = '__label__ = ' + getLabelId(oldLabel) + ';' + (SHOW_LABELS ? ' /* to: ' + cleanLabel(oldLabel) + ' */' : ''); // TODO: optimize away if (label[1] == 'R') { return pre + labelSetting + 'break ' + trueLabel + ';'; } else if (label[1] == 'C') { // CONT @@ -645,7 +645,7 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions, givenGlobalVaria throw 'Invalid B-op in branch: ' + trueLabel + ',' + oldLabel; } } else { - return pre + '__label__ = ' + getLabelId(label) + '; /* ' + cleanLabel(label) + ' */ break;'; + return pre + '__label__ = ' + getLabelId(label) + ';' + (SHOW_LABELS ? ' /* to: ' + cleanLabel(label) + ' */' : '') + ' break;'; } } diff --git a/src/settings.js b/src/settings.js index 829d4517..1b0b2bce 100644 --- a/src/settings.js +++ b/src/settings.js @@ -51,6 +51,8 @@ CORRECT_OVERFLOWS = 1; // Experimental code that tries to prevent unexpected JS // not rely on overflows in your C/C++ code, as even if this option works, // it slows things down. +SHOW_LABELS = 0; // Show labels in the generated code + // Compiler debugging options DEBUG_TAGS_SHOWING = []; // Some useful items: diff --git a/tests/cases/breakinthemiddle.ll b/tests/cases/breakinthemiddle.ll new file mode 100644 index 00000000..38ca96b4 --- /dev/null +++ b/tests/cases/breakinthemiddle.ll @@ -0,0 +1,18 @@ +@.str = private constant [15 x i8] c"hello, world!\0A\00", align 1 ; [#uses=1] + +define linkonce_odr i32* @main() align 2 { + %199 = trunc i8 1 to i1 ; [#uses=1] + br i1 %199, label %555, label %569 + +; <label>:555 ; preds = %353 + br label %569 + ; No predecessors! + br label %569 + +; <label>:569 ; preds = %555 + %333 = call i32 @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0)) ; [#uses=0] + ret i32 0 +} + +declare i32 @printf(i8*) + |