From 4efde8d2c10b091bc9588de18c2c71dca2979e49 Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Thu, 24 Jul 2008 01:18:41 +0000 Subject: [PATCH] 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: Completes: git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@53975 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGStmt.cpp | 30 ++++++++++++++---------------- 1 file 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(EmitScalarExpr(L)); - llvm::ConstantInt *RV = cast(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()); } -- 2.40.0