SVal GRSimpleVals::EvalEquality(GRExprEngine& Eng, Loc L, Loc R, bool isEqual) {
  
  BasicValueFactory& BasicVals = Eng.getBasicVals();

  switch (L.getSubKind()) {

    default:
      assert(false && "EQ/NE not implemented for this Loc.");
      return UnknownVal();
      
    case loc::ConcreteIntKind:

      if (isa<loc::ConcreteInt>(R)) {
        bool b = cast<loc::ConcreteInt>(L).getValue() ==
                 cast<loc::ConcreteInt>(R).getValue();
        
        // Are we computing '!='?  Flip the result.
        if (!isEqual)
          b = !b;
        
        return NonLoc::MakeIntTruthVal(BasicVals, b);
      }
      else if (SymbolRef Sym = R.getAsSymbol()) {
        const SymIntExpr * SE =
        Eng.getSymbolManager().getSymIntExpr(Sym,
                                             isEqual ? BinaryOperator::EQ
                                                     : BinaryOperator::NE,
                                             cast<loc::ConcreteInt>(L).getValue(),
                                             Eng.getContext().IntTy);
        return nonloc::SymExprVal(SE);
      }
      
      break;
      
    case loc::MemRegionKind: {
      if (SymbolRef LSym = L.getAsLocSymbol()) {
        if (isa<loc::ConcreteInt>(R)) {
          const SymIntExpr *SE =
            Eng.getSymbolManager().getSymIntExpr(LSym,
                                           isEqual ? BinaryOperator::EQ
                                                   : BinaryOperator::NE,
                                           cast<loc::ConcreteInt>(R).getValue(),
                                           Eng.getContext().IntTy);
        
          return nonloc::SymExprVal(SE);
        }
      }
    }    
    
    // Fall-through.
      
    case loc::GotoLabelKind:
      return NonLoc::MakeIntTruthVal(BasicVals, isEqual ? L == R : L != R);
  }
  
  return NonLoc::MakeIntTruthVal(BasicVals, isEqual ? false : true);
}
SVal GRSimpleVals::DetermEvalBinOpNN(GRExprEngine& Eng,
                                     BinaryOperator::Opcode Op,
                                     NonLoc L, NonLoc R,
                                     QualType T)  {

  BasicValueFactory& BasicVals = Eng.getBasicVals();
  unsigned subkind = L.getSubKind();
  
  while (1) {
    
    switch (subkind) {
      default:
        return UnknownVal();
        
      case nonloc::LocAsIntegerKind: {
        Loc LL = cast<nonloc::LocAsInteger>(L).getLoc();        
        
        switch (R.getSubKind()) {
          case nonloc::LocAsIntegerKind:
            return EvalBinOp(Eng, Op, LL,
                             cast<nonloc::LocAsInteger>(R).getLoc());
            
          case nonloc::ConcreteIntKind: {
            // Transform the integer into a location and compare.
            ASTContext& Ctx = Eng.getContext();
            llvm::APSInt V = cast<nonloc::ConcreteInt>(R).getValue();
            V.setIsUnsigned(true);
            V.extOrTrunc(Ctx.getTypeSize(Ctx.VoidPtrTy));
            return EvalBinOp(Eng, Op, LL,
                             loc::ConcreteInt(BasicVals.getValue(V)));
          }
          
          default: 
            switch (Op) {
              case BinaryOperator::EQ:
                return NonLoc::MakeIntTruthVal(BasicVals, false);
              case BinaryOperator::NE:
                return NonLoc::MakeIntTruthVal(BasicVals, true);
              default:
                // This case also handles pointer arithmetic.
                return UnknownVal();
            }
        }
      }
        
      case nonloc::SymExprValKind: {
        // Logical not?        
        if (!(Op == BinaryOperator::EQ && R.isZeroConstant()))
          return UnknownVal();

        const SymExpr &SE=*cast<nonloc::SymExprVal>(L).getSymbolicExpression();
        
        // Only handle ($sym op constant) for now.
        if (const SymIntExpr *E = dyn_cast<SymIntExpr>(&SE)) {
          BinaryOperator::Opcode Opc = E->getOpcode();
        
          if (Opc < BinaryOperator::LT || Opc > BinaryOperator::NE)
            return UnknownVal();

          // For comparison operators, translate the constraint by
          // changing the opcode.        
          int idx = (unsigned) Opc - (unsigned) BinaryOperator::LT;
        
          assert (idx >= 0 && 
                  (unsigned) idx < sizeof(LNotOpMap)/sizeof(unsigned char));
        
          Opc = (BinaryOperator::Opcode) LNotOpMap[idx];          
          assert(E->getType(Eng.getContext()) == T);
          E = Eng.getSymbolManager().getSymIntExpr(E->getLHS(), Opc,
                                                   E->getRHS(), T);
          return nonloc::SymExprVal(E);
        }
        
        return UnknownVal();
      }
        
      case nonloc::ConcreteIntKind:
        
        if (isa<nonloc::ConcreteInt>(R)) {          
          const nonloc::ConcreteInt& L_CI = cast<nonloc::ConcreteInt>(L);
          const nonloc::ConcreteInt& R_CI = cast<nonloc::ConcreteInt>(R);
          return L_CI.EvalBinOp(BasicVals, Op, R_CI);          
        }
        else {
          subkind = R.getSubKind();
          NonLoc tmp = R;
          R = L;
          L = tmp;
          
          // Swap the operators.
          switch (Op) {
            case BinaryOperator::LT: Op = BinaryOperator::GT; break;
            case BinaryOperator::GT: Op = BinaryOperator::LT; break;
            case BinaryOperator::LE: Op = BinaryOperator::GE; break;
            case BinaryOperator::GE: Op = BinaryOperator::LE; break;
            default: break;
          }
          
          continue;
        }
        
      case nonloc::SymbolValKind:
        if (isa<nonloc::ConcreteInt>(R)) {
          ValueManager &ValMgr = Eng.getValueManager();
          return ValMgr.makeNonLoc(cast<nonloc::SymbolVal>(L).getSymbol(), Op,
                                   cast<nonloc::ConcreteInt>(R).getValue(), T);
        }
        else
          return UnknownVal();
    }
  }
}