| #ifndef wasm_analysis_liveness_transfer_function_h | |
| #define wasm_analysis_liveness_transfer_function_h | |
| #include "lattice.h" | |
| #include "lattices/powerset.h" | |
| #include "visitor-transfer-function.h" | |
| namespace wasm::analysis { | |
| struct LivenessTransferFunction | |
| : public VisitorTransferFunc<LivenessTransferFunction, | |
| FiniteIntPowersetLattice, | |
| AnalysisDirection::Backward> { | |
| // Transfer function implementation. A local becomes live before a get | |
| // and becomes dead before a set. | |
| void visitLocalSet(LocalSet* curr) { | |
| assert(currState); | |
| currState->set(curr->index, false); | |
| } | |
| void visitLocalGet(LocalGet* curr) { | |
| assert(currState); | |
| currState->set(curr->index, true); | |
| } | |
| // Prints the intermediate states of each basic block cfgBlock by applying | |
| // the transfer function on each expression of the CFG block. This data is | |
| // not stored. Requires the cfgBlock, and a temp copy of the input state | |
| // to be passed in, where the temp copy is modified in place to produce the | |
| // intermediate states. | |
| void print(std::ostream& os, | |
| const BasicBlock& bb, | |
| FiniteIntPowersetLattice::Element& inputState) { | |
| os << "Intermediate States (reverse order): " << std::endl; | |
| currState = &inputState; | |
| currState->print(os); | |
| os << std::endl; | |
| // Since we don't store the intermediate states, we need to re-run the | |
| // transfer function on all the CFG node expressions to reconstruct | |
| // the intermediate states here. | |
| for (auto it = bb.rbegin(); it != bb.rend(); ++it) { | |
| os << ShallowExpression{*it} << "\n"; | |
| visit(*it); | |
| currState->print(os); | |
| os << "\n"; | |
| } | |
| currState = nullptr; | |
| } | |
| }; | |
| } // namespace wasm::analysis | |
| #endif // wasm_analysis_liveness_transfer_function_h |