| #ifndef wasm_analysis_liveness_transfer_function_h |
| #define wasm_analysis_liveness_transfer_function_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* cfgBlock, |
| FiniteIntPowersetLattice::Element& inputState) { |
| os << "Intermediate States (reverse order): " << std::endl; |
| currState = &inputState; |
| currState->print(os); |
| os << std::endl; |
| auto cfgIter = cfgBlock->rbegin(); |
| |
| // 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. |
| while (cfgIter != cfgBlock->rend()) { |
| os << ShallowExpression{*cfgIter} << std::endl; |
| visit(*cfgIter); |
| currState->print(os); |
| os << std::endl; |
| ++cfgIter; |
| } |
| currState = nullptr; |
| } |
| }; |
| |
| } // namespace wasm::analysis |
| |
| #endif // wasm_analysis_liveness_transfer_function_h |