/******************************************************************************* * Copyright (c) 2008 IBM Corporation. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package com.ibm.wala.cast.ipa.lexical; import java.util.Collection; import java.util.Map; import com.ibm.wala.cast.ipa.callgraph.ScopeMappingInstanceKeys.ScopeMappingInstanceKey; import com.ibm.wala.cast.ir.ssa.AstLexicalAccess.Access; import com.ibm.wala.cast.ir.ssa.AstLexicalRead; import com.ibm.wala.cast.ir.ssa.AstLexicalWrite; import com.ibm.wala.ipa.callgraph.CGNode; import com.ibm.wala.ipa.callgraph.CallGraph; import com.ibm.wala.ipa.callgraph.CallGraphTransitiveClosure; import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis; import com.ibm.wala.ssa.IR; import com.ibm.wala.ssa.SSAInstruction; import com.ibm.wala.util.collections.HashSetFactory; import com.ibm.wala.util.collections.Iterator2Iterable; import com.ibm.wala.util.collections.Pair; import com.ibm.wala.util.functions.Function; import com.ibm.wala.util.intset.OrdinalSet; /** * Compute mod-ref information limited to accesses of lexical variables. * */ public class LexicalModRef { public static LexicalModRef make(CallGraph cg, PointerAnalysis<InstanceKey> pa) { return new LexicalModRef(cg, pa); } private final CallGraph cg; private final PointerAnalysis<InstanceKey> pa; protected LexicalModRef(CallGraph cg, PointerAnalysis<InstanceKey> pa) { this.cg = cg; this.pa = pa; } /** * Compute the lexical variables possibly read by each {@link CGNode} and its * transitive callees. A lexical variable is represented as a pair (C,N), * where C is the defining {@link CGNode} and N is the {@link String} name. */ public Map<CGNode, OrdinalSet<Pair<CGNode, String>>> computeLexicalRef() { Map<CGNode, Collection<Pair<CGNode, String>>> scan = CallGraphTransitiveClosure.collectNodeResults(cg, new Function<CGNode, Collection<Pair<CGNode, String>>>() { @Override public Collection<Pair<CGNode, String>> apply(CGNode n) { return scanNodeForLexReads(n); } }); return CallGraphTransitiveClosure.transitiveClosure(cg, scan); } /** * Compute the lexical variables possibly modified by each {@link CGNode} and * its transitive callees. A lexical variable is represented as a pair (C,N), * where C is the defining {@link CGNode} and N is the {@link String} name. */ public Map<CGNode, OrdinalSet<Pair<CGNode, String>>> computeLexicalMod() { Map<CGNode, Collection<Pair<CGNode, String>>> scan = CallGraphTransitiveClosure.collectNodeResults(cg, new Function<CGNode, Collection<Pair<CGNode, String>>>() { @Override public Collection<Pair<CGNode, String>> apply(CGNode n) { return scanNodeForLexWrites(n); } }); return CallGraphTransitiveClosure.transitiveClosure(cg, scan); } protected Collection<Pair<CGNode, String>> scanNodeForLexReads(CGNode n) { Collection<Pair<CGNode, String>> result = HashSetFactory.make(); IR ir = n.getIR(); if (ir != null) { for (SSAInstruction instr : Iterator2Iterable.make(ir.iterateNormalInstructions())) { if (instr instanceof AstLexicalRead) { AstLexicalRead read = (AstLexicalRead) instr; for (Access a : read.getAccesses()) { Pair<String, String> nameAndDefiner = a.getName(); result.addAll(getNodeNamePairsForAccess(n, nameAndDefiner)); } } } } return result; } protected Collection<Pair<CGNode, String>> scanNodeForLexWrites(CGNode n) { Collection<Pair<CGNode, String>> result = HashSetFactory.make(); IR ir = n.getIR(); if (ir != null) { for (SSAInstruction instr : Iterator2Iterable.make(ir.iterateNormalInstructions())) { if (instr instanceof AstLexicalWrite) { AstLexicalWrite write = (AstLexicalWrite) instr; for (Access a : write.getAccesses()) { Pair<String, String> nameAndDefiner = a.getName(); result.addAll(getNodeNamePairsForAccess(n, nameAndDefiner)); } } } } return result; } private Collection<Pair<CGNode, String>> getNodeNamePairsForAccess(CGNode n, Pair<String, String> nameAndDefiner) { Collection<Pair<CGNode, String>> result = HashSetFactory.make(); // use scope-mapping instance keys in pointer analysis. may need a different // scheme for CG construction not based on pointer analysis OrdinalSet<InstanceKey> functionValues = pa.getPointsToSet(pa.getHeapModel().getPointerKeyForLocal(n, 1)); for (InstanceKey ik : functionValues) { if (ik instanceof ScopeMappingInstanceKey) { ScopeMappingInstanceKey smik = (ScopeMappingInstanceKey) ik; for (CGNode definerNode : Iterator2Iterable.make(smik.getFunargNodes(nameAndDefiner))) { result.add(Pair.make(definerNode, nameAndDefiner.fst)); } } } return result; } }