[clang][Interp] Implement IntegralToBoolean casts

Redo how we do IntegralCasts and implement IntegralToBoolean casts using
the already existing cast op.

Differential Revision: https://reviews.llvm.org/D132739
This commit is contained in:
Timm Bäder 2022-08-26 15:39:17 +02:00
parent 8e41e6a4ea
commit 95e6a407d9
4 changed files with 44 additions and 19 deletions

View File

@ -50,6 +50,7 @@ class Boolean {
explicit operator int64_t() const { return V; }
explicit operator uint64_t() const { return V; }
explicit operator int() const { return V; }
explicit operator bool() const { return V; }
APSInt toAPSInt() const {
return APSInt(APInt(1, static_cast<uint64_t>(V), false), true);
@ -85,9 +86,10 @@ class Boolean {
static Boolean min(unsigned NumBits) { return Boolean(false); }
static Boolean max(unsigned NumBits) { return Boolean(true); }
template <typename T>
static std::enable_if_t<std::is_integral<T>::value, Boolean> from(T Value) {
return Boolean(Value != 0);
template <typename T> static Boolean from(T Value) {
if constexpr (std::is_integral<T>::value)
return Boolean(Value != 0);
return Boolean(static_cast<decltype(Boolean::V)>(Value) != 0);
}
template <unsigned SrcBits, bool SrcSign>

View File

@ -117,6 +117,7 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
case CK_NullToPointer:
return this->Visit(SubExpr);
case CK_IntegralToBoolean:
case CK_IntegralCast: {
Optional<PrimType> FromT = classify(SubExpr->getType());
Optional<PrimType> ToT = classify(CE->getType());
@ -132,19 +133,6 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
case CK_ToVoid:
return discard(SubExpr);
case CK_IntegralToBoolean:
// Compare integral from Subexpr with 0
if (Optional<PrimType> T = classify(SubExpr->getType())) {
if (!this->Visit(SubExpr))
return false;
if (!this->emitConst(SubExpr, 0))
return false;
return this->emitNE(*T, SubExpr);
}
return false;
default:
assert(false && "Cast not implemented");
}

View File

@ -425,12 +425,16 @@ def Neg: Opcode {
//===----------------------------------------------------------------------===//
// TODO: Expand this to handle casts between more types.
def Sint32TypeClass : TypeClass {
let Types = [Sint32];
def FromCastTypeClass : TypeClass {
let Types = [Uint32, Sint32, Bool];
}
def ToCastTypeClass : TypeClass {
let Types = [Uint32, Sint32, Bool];
}
def Cast: Opcode {
let Types = [BoolTypeClass, Sint32TypeClass];
let Types = [FromCastTypeClass, ToCastTypeClass];
let HasGroup = 1;
}

View File

@ -14,6 +14,37 @@ static_assert(number != 10, ""); // expected-error{{failed}} \
// expected-note{{evaluates to}} \
// ref-note{{evaluates to}}
constexpr bool b = number;
static_assert(b, "");
constexpr int one = true;
static_assert(one == 1, "");
namespace IntegralCasts {
constexpr int i = 12;
constexpr unsigned int ui = i;
static_assert(ui == 12, "");
constexpr unsigned int ub = !false;
static_assert(ub == 1, "");
constexpr int si = ui;
static_assert(si == 12, "");
constexpr int sb = true;
static_assert(sb == 1, "");
constexpr int zero = 0;
constexpr unsigned int uzero = 0;
constexpr bool bs = i;
static_assert(bs, "");
constexpr bool bu = ui;
static_assert(bu, "");
constexpr bool ns = zero;
static_assert(!ns, "");
constexpr bool nu = uzero;
static_assert(!nu, "");
};
constexpr bool getTrue() { return true; }
constexpr bool getFalse() { return false; }
constexpr void* getNull() { return nullptr; }