001: /*
002: * Bytecode Analysis Framework
003: * Copyright (C) 2003-2006, University of Maryland
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: */
019:
020: package edu.umd.cs.findbugs.ba;
021:
022: import java.util.Iterator;
023:
024: import org.apache.bcel.generic.InstructionHandle;
025:
026: import edu.umd.cs.findbugs.SystemProperties;
027: import edu.umd.cs.findbugs.annotations.CheckForNull;
028: import edu.umd.cs.findbugs.annotations.CheckReturnValue;
029:
030: /**
031: * Abstract base class providing functionality that will be useful
032: * for most dataflow analysis implementations that model instructions
033: * within basic blocks.
034: *
035: * @author David Hovemeyer
036: * @see Dataflow
037: * @see DataflowAnalysis
038: */
039: public abstract class AbstractDataflowAnalysis<Fact> extends
040: BasicAbstractDataflowAnalysis<Fact> {
041: private static final boolean DEBUG = SystemProperties
042: .getBoolean("dataflow.transfer");
043:
044: /* ----------------------------------------------------------------------
045: * Public methods
046: * ---------------------------------------------------------------------- */
047:
048: /**
049: * Transfer function for a single instruction.
050: *
051: * @param handle the instruction
052: * @param basicBlock the BasicBlock containing the instruction; needed to disambiguate
053: * instructions in inlined JSR subroutines
054: * @param fact which should be modified based on the instruction
055: */
056: public abstract void transferInstruction(InstructionHandle handle,
057: BasicBlock basicBlock, Fact fact)
058: throws DataflowAnalysisException;
059:
060: /**
061: * Determine whether the given fact is <em>valid</em>
062: * (neither top nor bottom).
063: */
064: @CheckReturnValue
065: public abstract boolean isFactValid(Fact fact);
066:
067: /**
068: * Get the dataflow fact representing the point just before given Location.
069: * Note "before" is meant in the logical sense, so for backward analyses,
070: * before means after the location in the control flow sense.
071: *
072: * @param location the location
073: * @return the fact at the point just before the location
074: */
075: @Override
076: public Fact getFactAtLocation(Location location)
077: throws DataflowAnalysisException {
078: Fact start = getStartFact(location.getBasicBlock());
079: Fact result = createFact();
080: makeFactTop(result);
081: transfer(location.getBasicBlock(), location.getHandle(), start,
082: result);
083: return result;
084: }
085:
086: /**
087: * Get the dataflow fact representing the point just after given Location.
088: * Note "after" is meant in the logical sense, so for backward analyses,
089: * after means before the location in the control flow sense.
090: *
091: * @param location the location
092: * @return the fact at the point just after the location
093: */
094: @Override
095: public Fact getFactAfterLocation(Location location)
096: throws DataflowAnalysisException {
097: BasicBlock basicBlock = location.getBasicBlock();
098: InstructionHandle handle = location.getHandle();
099:
100: if (handle == (isForwards() ? basicBlock.getLastInstruction()
101: : basicBlock.getFirstInstruction()))
102: return getResultFact(basicBlock);
103: else
104: return getFactAtLocation(new Location(isForwards() ? handle
105: .getNext() : handle.getPrev(), basicBlock));
106: }
107:
108: /* ----------------------------------------------------------------------
109: * Implementations of interface methods
110: * ---------------------------------------------------------------------- */
111:
112: public void transfer(BasicBlock basicBlock, @CheckForNull
113: InstructionHandle end, Fact start, Fact result)
114: throws DataflowAnalysisException {
115: copy(start, result);
116:
117: if (isFactValid(result)) {
118: Iterator<InstructionHandle> i = isForwards() ? basicBlock
119: .instructionIterator() : basicBlock
120: .instructionReverseIterator();
121:
122: while (i.hasNext()) {
123: InstructionHandle handle = i.next();
124: if (handle == end)
125: break;
126:
127: if (DEBUG && end == null)
128: System.out.print("Transfer " + handle);
129:
130: // Transfer the dataflow value
131: transferInstruction(handle, basicBlock, result);
132:
133: if (DEBUG && end == null)
134: System.out.println(" ==> " + result.toString());
135: }
136: }
137: }
138:
139: }
140:
141: // vim:ts=4
|