public void attachLivenessInfo(FlowGraph flowGraph, FlowGraphDecorator flowGraphDecorator) { for (Function function : flowGraph.getFunctions()) { // Perform liveness analysis TransferFunction<LiveVariableState> transferFunction = new LiveVariableTransferFunction(); BackwardAnalysis<LiveVariableState> analysis = new BackwardAnalysis<LiveVariableState>(flowGraphDecorator, function); Map<Node, LiveVariableState> states = analysis.solve(transferFunction); // Attach live variables to each basic block for (BasicBlock basicBlock : function.getBlocks()) { LiveVariableState state = transferFunction.join(flowGraphDecorator, states, basicBlock.getLastNode()); Set<Integer> liveVariables = state.getLiveVariables(); // NOTE: The EdgeTransfer function may use the conditional variable contained in an if node. // We check if the last node of the basic block is an if node, and if it is, we add // the conditional variable to the set of live variables. if (basicBlock.getLastNode() instanceof IfNode) { IfNode ifNode = (IfNode) basicBlock.getLastNode(); liveVariables.add(ifNode.getConditionVar()); } int[] result = new int[liveVariables.size()]; Iterator<Integer> iterator = liveVariables.iterator(); int i = 0; while (iterator.hasNext()) { result[i] = iterator.next(); i++; } basicBlock.setLiveVariables(result); } } }
/** * Transfer for an exceptional-return statement. * * @param caller if non-null, only consider this caller */ public void transferExceptionalReturn( BasicBlock block, State state, NodeAndContext<Context> caller, Context edge_context) { Value v = state.readRegister(AbstractNode.EXCEPTION_REG); state.removeRegister(AbstractNode.EXCEPTION_REG); UserFunctionCalls.leaveUserFunction( v, true, block.getFunction(), state, c, caller, edge_context); }
/** Transfer ordinary and exceptional return for the given call node and callee entry. */ public void transferReturn( AbstractNode call_node, BasicBlock callee_entry, Context caller_context, Context callee_context, Context edge_context) { if (call_node instanceof BeginForInNode) { for (EndForInNode endNode : ((BeginForInNode) call_node).getEndNodes()) { BasicBlock end_block = endNode.getBlock(); if (c.getAnalysisLatticeElement().getState(end_block, callee_context) != null) // (EndForInNode uses same context as corresponding BeginForInNode) c.addToWorklist(end_block, callee_context); } } else { // call_node is an ordinary call node Function callee = callee_entry.getFunction(); BasicBlock ordinary_exit = callee.getOrdinaryExit(); BasicBlock exceptional_exit = callee.getExceptionalExit(); State ordinary_exit_state = c.getAnalysisLatticeElement() .getState( ordinary_exit, callee_context); // (ReturnNode uses same context as corresponding function entry // node) State exceptional_exit_state = c.getAnalysisLatticeElement().getState(exceptional_exit, callee_context); NodeAndContext<Context> caller = new NodeAndContext<>(call_node, caller_context); if (ordinary_exit_state != null) { if (ordinary_exit.getFirstNode() instanceof ReturnNode) { ReturnNode returnNode = (ReturnNode) ordinary_exit.getFirstNode(); transferReturn( returnNode.getReturnValueRegister(), ordinary_exit, ordinary_exit_state.clone(), caller, edge_context); } else throw new AnalysisException("ReturnNode expected"); } if (exceptional_exit_state != null) { transferExceptionalReturn( exceptional_exit, exceptional_exit_state.clone(), caller, edge_context); } } }
/** * Transfer for a return statement. * * @param caller if non-null, only consider this caller */ public void transferReturn( int valueReg, BasicBlock block, State state, NodeAndContext<Context> caller, Context edge_context) { Value v; if (valueReg != AbstractNode.NO_VALUE) v = state.readRegister(valueReg); else v = Value.makeUndef(); UserFunctionCalls.leaveUserFunction( v, false, block.getFunction(), state, c, caller, edge_context); }
/** Returns a string description of this entry. */ @Override public String toString() { return Integer.toString(b.getIndex()); }
/** Constructs a new entry. */ public Entry(BasicBlock b, CallContextType c) { this.b = b; this.c = c; serial = next_serial++; hash = b.getIndex() + c.hashCode(); }