diff options
-rw-r--r-- | src/analyzer.js | 15 | ||||
-rw-r--r-- | tests/cases/phientryimplicit.ll | 21 |
2 files changed, 35 insertions, 1 deletions
diff --git a/src/analyzer.js b/src/analyzer.js index 3feaff92..3f4df5ba 100644 --- a/src/analyzer.js +++ b/src/analyzer.js @@ -8,6 +8,8 @@ var VAR_NATIVE = 'native'; var VAR_NATIVIZED = 'nativized'; var VAR_EMULATED = 'emulated'; +var ENTRY_IDENT = toNiceIdent('%0'); + function cleanFunc(func) { func.lines = func.lines.filter(function(line) { return line.intertype !== null }); func.labels.forEach(function(label) { @@ -72,7 +74,7 @@ function analyzer(data, sidePass) { if (item.items[i+1].intertype !== 'label') { item.items.splice(i+1, 0, { intertype: 'label', - ident: toNiceIdent('%1'), + ident: ENTRY_IDENT, lineNum: subItem.lineNum + '.5' }); } @@ -706,6 +708,8 @@ function analyzer(data, sidePass) { // MICRO_OPTS == 1: Properly implement phis, by pushing them back into the branch // that leads to here. We will only have the |var| definition in this location. + var unknownEntry = null; + // First, push phis back func.labels.forEach(function(label) { label.lines.forEach(function(line) { @@ -715,6 +719,15 @@ function analyzer(data, sidePass) { var param = phi.params[i]; var sourceLabelId = param.label; var sourceLabel = func.labelsDict[sourceLabelId]; + if (!sourceLabel) { + // The entry might not have an explicit label, and there is no consistent naming convention for it. + // So we need to handle that in a special way here. + assert(!unknownEntry, 'More than one unknown label in phi, so both cannot be an unlabelled entry, in ' + func.ident); + unknownEntry = sourceLabelId; + sourceLabelId = ENTRY_IDENT; + sourceLabel = func.labelsDict[sourceLabelId]; + assert(sourceLabel, 'Cannot find entry label when looking for it after seeing an unknown label in a phi'); + } var lastLine = sourceLabel.lines.slice(-1)[0]; if (lastLine.intertype == 'assign') lastLine = lastLine.value; assert(lastLine.intertype in LLVM.PHI_REACHERS, 'Only some can lead to labels with phis:' + [func.ident, label.ident, lastLine.intertype]); diff --git a/tests/cases/phientryimplicit.ll b/tests/cases/phientryimplicit.ll index 5b3b0b31..8a510f43 100644 --- a/tests/cases/phientryimplicit.ll +++ b/tests/cases/phientryimplicit.ll @@ -2,6 +2,8 @@ target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128" target triple = "i386-pc-linux-gnu" +; Phi nodes can refer to the entry. And the entry might be unnamed, and doesn't even have a consistent implicit name! + @.str = private unnamed_addr constant [15 x i8] c"hello, world!\0A\00", align 1 ; [#uses=1 type=[15 x i8]*] ; [#uses=0] @@ -12,11 +14,30 @@ define i32 @main() { ; <label>:17 ; preds = %1 %25 = trunc i32 1 to i1 + br label %26 ; <label>:26 ; preds = %17, %1 %27 = phi i1 [ false, %1 ], [ %25, %17 ] ; [#uses=1 type=i1] store i32 0, i32* %retval %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0)) ; [#uses=0 type=i32] + %cal2 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0), i32 %27) ; make sure %27 is used + ret i32 1 +} + +define i32 @main0() { + %retval = alloca i32, align 4 ; [#uses=1 type=i32*] + %16 = trunc i32 1 to i1 + br i1 %16, label %17, label %26, !dbg !1269853 ; [debug line = 3920:5] + +; <label>:17 ; preds = %1 + %25 = trunc i32 1 to i1 + br label %26 + +; <label>:26 ; preds = %17, %1 + %27 = phi i1 [ false, %0 ], [ %25, %17 ] ; [#uses=1 type=i1] + store i32 0, i32* %retval + %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0)) ; [#uses=0 type=i32] + %cal2 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0), i32 %27) ; make sure %27 is used ret i32 1 } |