const evaluator: enums

This commit is contained in:
Marc Rasi
2019-01-14 20:45:22 -08:00
parent bc884d4ba8
commit c5c2d2eb8c
4 changed files with 192 additions and 0 deletions

View File

@@ -82,6 +82,20 @@ void SymbolicValue::print(llvm::raw_ostream &os, unsigned indent) const {
return;
}
}
case RK_Enum: {
auto *decl = getEnumValue();
os << "enum: ";
decl->print(os);
return;
}
case RK_EnumWithPayload: {
auto *decl = getEnumValue();
os << "enum: ";
decl->print(os);
os << ", payload: ";
getEnumPayloadValue().print(os, indent);
return;
}
case RK_DirectAddress:
case RK_DerivedAddress: {
SmallVector<unsigned, 4> accessPath;
@@ -111,6 +125,10 @@ SymbolicValue::Kind SymbolicValue::getKind() const {
return Function;
case RK_Aggregate:
return Aggregate;
case RK_Enum:
return Enum;
case RK_EnumWithPayload:
return EnumWithPayload;
case RK_Integer:
case RK_IntegerInline:
return Integer;
@@ -133,6 +151,9 @@ SymbolicValue::cloneInto(ASTContext &astContext) const {
case RK_Metatype:
case RK_Function:
assert(0 && "cloning this representation kind is not supported");
case RK_Enum:
// These have trivial inline storage, just return a copy.
return *this;
case RK_IntegerInline:
case RK_Integer:
return SymbolicValue::getInteger(getIntegerValue(), astContext);
@@ -146,6 +167,8 @@ SymbolicValue::cloneInto(ASTContext &astContext) const {
results.push_back(elt.cloneInto(astContext));
return getAggregate(results, astContext);
}
case RK_EnumWithPayload:
return getEnumWithPayload(getEnumValue(), getEnumPayloadValue(), astContext);
case RK_DirectAddress:
case RK_DerivedAddress: {
SmallVector<unsigned, 4> accessPath;
@@ -354,6 +377,56 @@ UnknownReason SymbolicValue::getUnknownReason() const {
return value.unknown->reason;
}
//===----------------------------------------------------------------------===//
// Enums
//===----------------------------------------------------------------------===//
namespace swift {
/// This is the representation of a constant enum value with payload.
struct EnumWithPayloadSymbolicValue final {
/// The enum case.
EnumElementDecl *enumDecl;
SymbolicValue payload;
EnumWithPayloadSymbolicValue(EnumElementDecl *decl, SymbolicValue payload)
: enumDecl(decl), payload(payload) {}
private:
EnumWithPayloadSymbolicValue() = delete;
EnumWithPayloadSymbolicValue(const EnumWithPayloadSymbolicValue &) = delete;
};
} // end namespace swift
/// This returns a constant Symbolic value for the enum case in `decl` with a
/// payload.
SymbolicValue
SymbolicValue::getEnumWithPayload(EnumElementDecl *decl, SymbolicValue payload,
ASTContext &astContext) {
assert(decl && payload.isConstant());
auto rawMem = astContext.Allocate(sizeof(EnumWithPayloadSymbolicValue),
alignof(EnumWithPayloadSymbolicValue));
auto enumVal = ::new (rawMem) EnumWithPayloadSymbolicValue(decl, payload);
SymbolicValue result;
result.representationKind = RK_EnumWithPayload;
result.value.enumValWithPayload = enumVal;
return result;
}
EnumElementDecl *SymbolicValue::getEnumValue() const {
if (representationKind == RK_Enum)
return value.enumVal;
assert(representationKind == RK_EnumWithPayload);
return value.enumValWithPayload->enumDecl;
}
SymbolicValue SymbolicValue::getEnumPayloadValue() const {
assert(representationKind == RK_EnumWithPayload);
return value.enumValWithPayload->payload;
}
//===----------------------------------------------------------------------===//
// Addresses
//===----------------------------------------------------------------------===//