| /* |
| * 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 <iostream> |
| |
| #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 |