blob: f2f334d28468001f7d4adc2d8133ec9ea783e12e [file]
#ifndef wasm_analysis_bits_bounds_lattice_h
#define wasm_analysis_bits_bounds_lattice_h
#include <optional>
#include "lattice.h"
#include "wasm.h"
namespace wasm::analysis {
struct MaxBitsLattice {
enum LatticeState { BOTTOM, REGULAR_VALUE, TOP };
struct Element {
Index upperBound = 0;
std::optional<Literal> constVal;
LatticeState state = BOTTOM;
bool isTop() const { return state == TOP; }
bool isBottom() const { return state == BOTTOM; }
void setUpperBound(Index upperBound) {
if (state != TOP) {
state = REGULAR_VALUE;
this->upperBound = upperBound;
constVal.reset();
}
}
void setUpperBound(Index upperBound, Literal constVal) {
if (state != TOP) {
state = REGULAR_VALUE;
this->upperBound = upperBound;
this->constVal = constVal;
}
}
void setTop() {
state = TOP;
upperBound = UINT32_MAX;
constVal.reset();
}
bool makeLeastUpperBound(const Element& other) {
if (other.isBottom() || isTop()) {
return false;
} else if (other.isTop()) {
setTop();
return true;
} else if (isBottom()) {
if (other.constVal.has_value()) {
setUpperBound(other.upperBound, other.constVal.value());
} else {
setUpperBound(other.upperBound);
}
return true;
}
if (upperBound < other.upperBound) {
if (other.constVal.has_value()) {
setUpperBound(other.upperBound, other.constVal.value());
} else {
setUpperBound(other.upperBound);
}
return true;
} else if (upperBound == other.upperBound && other.constVal.has_value()) {
if (constVal.has_value()) {
constVal.reset();
} else {
constVal = other.constVal.value();
}
return true;
}
return false;
}
void print(std::ostream& os) {
if (state == TOP) {
os << "TOP";
} else if (state == BOTTOM) {
os << "BOTTOM";
} else {
os << upperBound;
if (constVal.has_value()) {
os << " " << constVal.value();
}
}
}
friend MaxBitsLattice;
};
LatticeComparison compare(const Element& left, const Element& right) {
if (left.isTop()) {
if (right.isTop()) {
return LatticeComparison::EQUAL;
} else {
return LatticeComparison::GREATER;
}
} else if (right.isTop()) {
return LatticeComparison::LESS;
} else if (left.isBottom()) {
if (right.isBottom()) {
return LatticeComparison::EQUAL;
} else {
return LatticeComparison::LESS;
}
} else if (right.isBottom()) {
return LatticeComparison::GREATER;
}
if (left.upperBound > right.upperBound) {
return LatticeComparison::GREATER;
} else if (left.upperBound < right.upperBound) {
return LatticeComparison::LESS;
} else {
if (left.constVal.has_value()) {
if (right.constVal.has_value()) {
if (left.constVal.value() == right.constVal.value()) {
return LatticeComparison::EQUAL;
} else {
return LatticeComparison::NO_RELATION;
}
} else {
return LatticeComparison::LESS;
}
} else {
if (right.constVal.has_value()) {
return LatticeComparison::GREATER;
} else {
return LatticeComparison::EQUAL;
}
}
}
}
Element getBottom() { return Element{}; }
};
} // namespace wasm::analysis
#endif // wasm_analysis_bits_bounds_lattice_h