Beispiel #1
0
ConstantRange
ConstantRange::binaryOr(const ConstantRange &Other) const {
  if (isEmptySet() || Other.isEmptySet())
    return ConstantRange(getBitWidth(), /*isFullSet=*/false);

  // TODO: replace this with something less conservative

  APInt umax = APIntOps::umax(getUnsignedMin(), Other.getUnsignedMin());
  if (umax.isNullValue())
    return ConstantRange(getBitWidth(), /*isFullSet=*/true);
  return ConstantRange(std::move(umax), APInt::getNullValue(getBitWidth()));
}
/// Emit a diagnostic for `poundAssert` builtins whose condition is
/// false or whose condition cannot be evaluated.
static void diagnosePoundAssert(const SILInstruction *I,
                                SILModule &M,
                                ConstExprEvaluator &constantEvaluator) {
  auto *builtinInst = dyn_cast<BuiltinInst>(I);
  if (!builtinInst ||
      builtinInst->getBuiltinKind() != BuiltinValueKind::PoundAssert)
    return;

  SmallVector<SymbolicValue, 1> values;
  constantEvaluator.computeConstantValues({builtinInst->getArguments()[0]},
                                          values);
  SymbolicValue value = values[0];
  if (!value.isConstant()) {
    diagnose(M.getASTContext(), I->getLoc().getSourceLoc(),
             diag::pound_assert_condition_not_constant);

    // If we have more specific information about what went wrong, emit
    // notes.
    if (value.getKind() == SymbolicValue::Unknown)
      value.emitUnknownDiagnosticNotes(builtinInst->getLoc());
    return;
  }
  assert(value.getKind() == SymbolicValue::Integer &&
         "sema prevents non-integer #assert condition");

  APInt intValue = value.getIntegerValue();
  assert(intValue.getBitWidth() == 1 &&
         "sema prevents non-int1 #assert condition");
  if (intValue.isNullValue()) {
    auto *message = cast<StringLiteralInst>(builtinInst->getArguments()[1]);
    StringRef messageValue = message->getValue();
    if (messageValue.empty())
      messageValue = "assertion failed";
    diagnose(M.getASTContext(), I->getLoc().getSourceLoc(),
             diag::pound_assert_failure, messageValue);
    return;
  }
}
Beispiel #3
0
MyConstantRange binaryOr(const MyConstantRange &Other) const {
  if (isEmptySet() || Other.isEmptySet())
    return MyConstantRange(getBitWidth(), /*isFullSet=*/false);

  if (!isWrappedSet() && !Other.isWrappedSet() && !isFullSet() && !Other.isFullSet()) {
    unsigned width1 = ((getUpper() - 1) ^ getLower()).getActiveBits();
    unsigned width2 = ((Other.getUpper() - 1) ^ Other.getLower()).getActiveBits();
    APInt res1 = getLower().lshr(width1) << width1;
    APInt res2 = Other.getLower().lshr(width2) << width2;
    APInt res_high1 = getLower();
    APInt res_high2 = Other.getLower();
    res_high1.setLowBits(width1);
    res_high2.setLowBits(width2);
    if ((res1 | res2).isNullValue() && (res_high1 | res_high2).isAllOnesValue()) {
        return MyConstantRange(getBitWidth(), /*isFullSet=*/true);
    }
    return MyConstantRange(res1 | res2, (res_high1 | res_high2) + 1);
  }

  APInt umax = APIntOps::umax(getUnsignedMin(), Other.getUnsignedMin());
  if (umax.isNullValue())
    return MyConstantRange(getBitWidth(), /*isFullSet=*/true);
  return MyConstantRange(std::move(umax), APInt::getNullValue(getBitWidth()));
}
Beispiel #4
0
ConstantRange ConstantRange::unionWith(const ConstantRange &CR) const {
  assert(getBitWidth() == CR.getBitWidth() && 
         "ConstantRange types don't agree!");

  if (   isFullSet() || CR.isEmptySet()) return *this;
  if (CR.isFullSet() ||    isEmptySet()) return CR;

  if (!isWrappedSet() && CR.isWrappedSet()) return CR.unionWith(*this);

  if (!isWrappedSet() && !CR.isWrappedSet()) {
    if (CR.Upper.ult(Lower) || Upper.ult(CR.Lower)) {
      // If the two ranges are disjoint, find the smaller gap and bridge it.
      APInt d1 = CR.Lower - Upper, d2 = Lower - CR.Upper;
      if (d1.ult(d2))
        return ConstantRange(Lower, CR.Upper);
      return ConstantRange(CR.Lower, Upper);
    }

    APInt L = CR.Lower.ult(Lower) ? CR.Lower : Lower;
    APInt U = (CR.Upper - 1).ugt(Upper - 1) ? CR.Upper : Upper;

    if (L.isNullValue() && U.isNullValue())
      return ConstantRange(getBitWidth());

    return ConstantRange(std::move(L), std::move(U));
  }

  if (!CR.isWrappedSet()) {
    // ------U   L-----  and  ------U   L----- : this
    //   L--U                            L--U  : CR
    if (CR.Upper.ule(Upper) || CR.Lower.uge(Lower))
      return *this;

    // ------U   L----- : this
    //    L---------U   : CR
    if (CR.Lower.ule(Upper) && Lower.ule(CR.Upper))
      return ConstantRange(getBitWidth());

    // ----U       L---- : this
    //       L---U       : CR
    //    <d1>  <d2>
    if (Upper.ule(CR.Lower) && CR.Upper.ule(Lower)) {
      APInt d1 = CR.Lower - Upper, d2 = Lower - CR.Upper;
      if (d1.ult(d2))
        return ConstantRange(Lower, CR.Upper);
      return ConstantRange(CR.Lower, Upper);
    }

    // ----U     L----- : this
    //        L----U    : CR
    if (Upper.ult(CR.Lower) && Lower.ult(CR.Upper))
      return ConstantRange(CR.Lower, Upper);

    // ------U    L---- : this
    //    L-----U       : CR
    assert(CR.Lower.ult(Upper) && CR.Upper.ult(Lower) &&
           "ConstantRange::unionWith missed a case with one range wrapped");
    return ConstantRange(Lower, CR.Upper);
  }

  // ------U    L----  and  ------U    L---- : this
  // -U  L-----------  and  ------------U  L : CR
  if (CR.Lower.ule(Upper) || Lower.ule(CR.Upper))
    return ConstantRange(getBitWidth());

  APInt L = CR.Lower.ult(Lower) ? CR.Lower : Lower;
  APInt U = CR.Upper.ugt(Upper) ? CR.Upper : Upper;

  return ConstantRange(std::move(L), std::move(U));
}