/* * Copyright 2023 WebAssembly Community Group participants * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef wasm_analysis_lattices_powerset_impl_h #define wasm_analysis_lattices_powerset_impl_h #include #include "powerset.h" namespace wasm::analysis { inline LatticeComparison FiniteIntPowersetLattice::compare( const FiniteIntPowersetLattice::Element& left, const FiniteIntPowersetLattice::Element& right) const noexcept { // Both must be from the powerset lattice of the same set. assert(left.bitvector.size() == right.bitvector.size()); // True in left, false in right. bool leftNotRight = false; // True in right, false in left. bool rightNotLeft = false; size_t size = left.bitvector.size(); for (size_t i = 0; i < size; ++i) { leftNotRight |= (left.bitvector[i] && !right.bitvector[i]); rightNotLeft |= (right.bitvector[i] && !left.bitvector[i]); // We can end early if we know neither is a subset of the other. if (leftNotRight && rightNotLeft) { return NO_RELATION; } } if (!leftNotRight) { if (!rightNotLeft) { return EQUAL; } return LESS; } else if (!rightNotLeft) { return GREATER; } return NO_RELATION; } inline FiniteIntPowersetLattice::Element FiniteIntPowersetLattice::getBottom() const noexcept { FiniteIntPowersetLattice::Element result(setSize); return result; } // We count the number of element members present in the element by counting the // trues in the bitvector. inline size_t FiniteIntPowersetLattice::Element::count() const { size_t count = 0; for (auto it : bitvector) { count += it; } return count; } // Least upper bound is implemented as a logical OR between the bitvectors on // both sides. We return true if a bit is flipped in-place on the left so the // worklist algorithm will know if when to enqueue more work. inline bool FiniteIntPowersetLattice::join(Element& joinee, const Element& joiner) const noexcept { // Both must be from powerset lattice of the same set. assert(joiner.bitvector.size() == joinee.bitvector.size()); bool modified = false; for (size_t i = 0; i < joinee.bitvector.size(); ++i) { // Bit is flipped on joinee only if joinee is false and joiner is true when // joinee and joiner are OR'ed together. modified |= (!joinee.bitvector[i] && joiner.bitvector[i]); joinee.bitvector[i] = joinee.bitvector[i] || joiner.bitvector[i]; } return modified; } inline void FiniteIntPowersetLattice::Element::print(std::ostream& os) { // Element member 0 is on the left, element member N is on the right. for (auto it : bitvector) { os << it; } } }; // namespace wasm::analysis #endif // wasm_analysis_lattices_powerset_impl_h