private void init(CfgBlock block, SymbolTable symbols) { // 'writtenOnly' has variables that are WRITE-ONLY inside at least one element // (as opposed to 'kill' which can have a variable that inside an element is both READ and WRITTEN) Set<Symbol> writtenOnly = new HashSet<>(); for (Tree element : block.elements()) { Map<Symbol, VariableUsage> variableUsages = ReadWriteVisitor.getVariableUsages(element, symbols); variableUsagesPerElement.put(element, variableUsages); computeGenAndKill(writtenOnly, variableUsages); } }
private void visitReadVariable(Tree tree) { Symbol varSym; if (tree.is(Tree.Kind.VARIABLE_IDENTIFIER)) { varSym = symbols.getSymbol(tree); } else if (tree.is(Tree.Kind.REGULAR_STRING_LITERAL)) { varSym = symbols.getSymbol(((LiteralTree) tree).token()); } else { return; } if (isLocalVariable(varSym)) { VariableUsage usage = variables.computeIfAbsent(varSym, s -> new VariableUsage()); usage.isRead = true; } }
private void visitUnaryExpression(UnaryExpressionTree tree) { tree.expression().accept(this); visitAssignedVariable(tree.expression()); }
private void visitUnaryExpression(UnaryExpressionTree tree) { tree.expression().accept(this); visitAssignedVariable(tree.expression()); }
@Override public void visitArrayAssignmentPatternElement(ArrayAssignmentPatternElementTree tree) { if (visitAssignedVariable(tree.variable())) { Tree key = tree.key(); if (key != null) { visitAssignedVariable(key); } } else { super.visitArrayAssignmentPatternElement(tree); } }
@Override public void visitLiteral(LiteralTree tree) { visitReadVariable(tree); super.visitLiteral(tree); }
private boolean visitAssignedVariable(Tree tree) { if (!tree.is(Tree.Kind.VARIABLE_IDENTIFIER)) { return false; } Symbol varSym = symbols.getSymbol(tree); if (isLocalVariable(varSym)) { VariableUsage usage = variables.computeIfAbsent(varSym, s -> new VariableUsage()); usage.isWrite = true; return true; } return false; }
@Override public void visitPrefixExpression(UnaryExpressionTree tree) { if (tree.is(Tree.Kind.PREFIX_INCREMENT) || tree.is(Tree.Kind.PREFIX_DECREMENT)) { visitUnaryExpression(tree); } else { super.visitPrefixExpression(tree); } }
static Map<Symbol, VariableUsage> getVariableUsages(Tree tree, SymbolTable symbols) { ReadWriteVisitor visitor = new ReadWriteVisitor(symbols); tree.accept(visitor); return visitor.variables; }
private void visitReadVariable(Tree tree) { Symbol varSym; if (tree.is(Tree.Kind.VARIABLE_IDENTIFIER)) { varSym = symbols.getSymbol(tree); } else if (tree.is(Tree.Kind.REGULAR_STRING_LITERAL)) { varSym = symbols.getSymbol(((LiteralTree) tree).token()); } else { return; } if (isLocalVariable(varSym)) { VariableUsage usage = variables.computeIfAbsent(varSym, s -> new VariableUsage()); usage.isRead = true; } }
@Override public void visitAssignmentExpression(AssignmentExpressionTree tree) { boolean isCompoundAssignment = tree.getKind() != Tree.Kind.ASSIGNMENT; boolean isUsedAsNamedParameterOrReturn = tree.getParent().is(Tree.Kind.FUNCTION_CALL, Tree.Kind.RETURN_STATEMENT); if (isCompoundAssignment || isUsedAsNamedParameterOrReturn) { visitReadVariable(tree.variable()); } if (!visitAssignedVariable(tree.variable())) { tree.variable().accept(this); } tree.value().accept(this); }
@Override public void visitPrefixExpression(UnaryExpressionTree tree) { if (tree.is(Tree.Kind.PREFIX_INCREMENT) || tree.is(Tree.Kind.PREFIX_DECREMENT)) { visitUnaryExpression(tree); } else { super.visitPrefixExpression(tree); } }
static Map<Symbol, VariableUsage> getVariableUsages(Tree tree, SymbolTable symbols) { ReadWriteVisitor visitor = new ReadWriteVisitor(symbols); tree.accept(visitor); return visitor.variables; }
@Override public void visitPostfixExpression(UnaryExpressionTree tree) { if (tree.is(Tree.Kind.POSTFIX_INCREMENT) || tree.is(Tree.Kind.POSTFIX_DECREMENT)) { visitUnaryExpression(tree); } else { super.visitPostfixExpression(tree); } }
@Override public void visitVariableIdentifier(VariableIdentifierTree tree) { visitReadVariable(tree); super.visitVariableIdentifier(tree); }
private void init(CfgBlock block, SymbolTable symbols) { // 'writtenOnly' has variables that are WRITE-ONLY inside at least one element // (as opposed to 'kill' which can have a variable that inside an element is both READ and WRITTEN) Set<Symbol> writtenOnly = new HashSet<>(); for (Tree element : block.elements()) { Map<Symbol, VariableUsage> variableUsages = ReadWriteVisitor.getVariableUsages(element, symbols); variableUsagesPerElement.put(element, variableUsages); computeGenAndKill(writtenOnly, variableUsages); } }
@Override public void visitVariableIdentifier(VariableIdentifierTree tree) { visitReadVariable(tree); super.visitVariableIdentifier(tree); }
private boolean visitAssignedVariable(Tree tree) { if (!tree.is(Tree.Kind.VARIABLE_IDENTIFIER)) { return false; } Symbol varSym = symbols.getSymbol(tree); if (isLocalVariable(varSym)) { VariableUsage usage = variables.computeIfAbsent(varSym, s -> new VariableUsage()); usage.isWrite = true; return true; } return false; }
@Override public void visitArrayAssignmentPatternElement(ArrayAssignmentPatternElementTree tree) { if (visitAssignedVariable(tree.variable())) { Tree key = tree.key(); if (key != null) { visitAssignedVariable(key); } } else { super.visitArrayAssignmentPatternElement(tree); } }
@Override public void visitAssignmentExpression(AssignmentExpressionTree tree) { boolean isCompoundAssignment = tree.getKind() != Tree.Kind.ASSIGNMENT; boolean isUsedAsNamedParameterOrReturn = tree.getParent().is(Tree.Kind.FUNCTION_CALL, Tree.Kind.RETURN_STATEMENT); if (isCompoundAssignment || isUsedAsNamedParameterOrReturn) { visitReadVariable(tree.variable()); } if (!visitAssignedVariable(tree.variable())) { tree.variable().accept(this); } tree.value().accept(this); }