aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGStmt.cpp
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2008-07-24 01:18:41 +0000
committerDaniel Dunbar <daniel@zuster.org>2008-07-24 01:18:41 +0000
commit4efde8d2c10b091bc9588de18c2c71dca2979e49 (patch)
treebb90fddaa32d28bc6682416b7e9fb0db40efc7e3 /lib/CodeGen/CGStmt.cpp
parentcd8f646eca128f52a7bce0103c51ff82ce96f374 (diff)
Fix EmitCaseStmtRange to ignore empty ranges
- Also cleaned up emission slightly - Inspection of the code revealed several other bugs, however. Case ranges are not properly wired and can result in switch cases being dropped or even infinite loops. See: <rdar://problem/6098585> Completes: <rdar://problem/6094119> git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@53975 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGStmt.cpp')
-rw-r--r--lib/CodeGen/CGStmt.cpp30
1 files changed, 14 insertions, 16 deletions
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index 736fad0d2e..3f69cd0a02 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -420,27 +420,25 @@ void CodeGenFunction::EmitContinueStmt() {
/// add multiple cases to switch instruction, one for each value within
/// the range. If range is too big then emit "if" condition check.
void CodeGenFunction::EmitCaseStmtRange(const CaseStmt &S) {
- assert (S.getRHS() && "Unexpected RHS value in CaseStmt");
+ assert(S.getRHS() && "Expected RHS value in CaseStmt");
- const Expr *L = S.getLHS();
- const Expr *R = S.getRHS();
- llvm::ConstantInt *LV = cast<llvm::ConstantInt>(EmitScalarExpr(L));
- llvm::ConstantInt *RV = cast<llvm::ConstantInt>(EmitScalarExpr(R));
- llvm::APInt LHS = LV->getValue();
- const llvm::APInt &RHS = RV->getValue();
+ llvm::APSInt LHS = S.getLHS()->getIntegerConstantExprValue(getContext());
+ llvm::APSInt RHS = S.getRHS()->getIntegerConstantExprValue(getContext());
+
+ // If range is empty, do nothing.
+ if (LHS.isSigned() ? RHS.slt(LHS) : RHS.ult(LHS))
+ return;
llvm::APInt Range = RHS - LHS;
+ // FIXME: parameters such as this should not be hardcoded
if (Range.ult(llvm::APInt(Range.getBitWidth(), 64))) {
// Range is small enough to add multiple switch instruction cases.
StartBlock("sw.bb");
llvm::BasicBlock *CaseDest = Builder.GetInsertBlock();
- SwitchInsn->addCase(LV, CaseDest);
- LHS++;
- while (LHS != RHS) {
+ for (unsigned i = 0, e = Range.getZExtValue() + 1; i != e; ++i) {
SwitchInsn->addCase(llvm::ConstantInt::get(LHS), CaseDest);
LHS++;
}
- SwitchInsn->addCase(RV, CaseDest);
EmitStmt(S.getSubStmt());
return;
}
@@ -463,7 +461,8 @@ void CodeGenFunction::EmitCaseStmtRange(const CaseStmt &S) {
// Emit range check.
llvm::Value *Diff =
- Builder.CreateSub(SwitchInsn->getCondition(), LV, "tmp");
+ Builder.CreateSub(SwitchInsn->getCondition(), llvm::ConstantInt::get(LHS),
+ "tmp");
llvm::Value *Cond =
Builder.CreateICmpULE(Diff, llvm::ConstantInt::get(Range), "tmp");
Builder.CreateCondBr(Cond, CaseDest, FalseDest);
@@ -481,10 +480,9 @@ void CodeGenFunction::EmitCaseStmt(const CaseStmt &S) {
StartBlock("sw.bb");
llvm::BasicBlock *CaseDest = Builder.GetInsertBlock();
- llvm::APSInt CaseVal(32);
- S.getLHS()->isIntegerConstantExpr(CaseVal, getContext());
- llvm::ConstantInt *LV = llvm::ConstantInt::get(CaseVal);
- SwitchInsn->addCase(LV, CaseDest);
+ llvm::APSInt CaseVal = S.getLHS()->getIntegerConstantExprValue(getContext());
+ SwitchInsn->addCase(llvm::ConstantInt::get(CaseVal),
+ CaseDest);
EmitStmt(S.getSubStmt());
}