/*
 *
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

package org.apache.flex.abc.semantics;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.flex.abc.ABCConstants;
import org.apache.flex.abc.graph.IBasicBlock;
import org.apache.flex.abc.graph.IFlowgraph;
import org.apache.flex.abc.graph.algorithms.DepthFirstPreorderIterator;
import org.apache.flex.abc.graph.algorithms.DominatorTree;
import org.apache.flex.abc.visitors.IFlowGraphVisitor;

/**
 * A ControlFlowGraph represents the flow of control through a sequence of
 * instructions. The instructions are organized into a set of Blocks --
 * sequences of instructions where normal control flow proceeds linearly from
 * one instruction to the next -- and a set of edges, representing the
 * discontinuous transfer of control points.

 */
public class ControlFlowGraph implements IFlowgraph
{
    /**
     * Search direction in the initial block of a block-by-block search
     * (typically for debug information).
     */
    private enum SearchDirection { Forward, Backward };

    /**
     * Create a ControlFlowGraph from the instructions in the MethodBodyInfo.
     * @param mbi  - the MethodBodyInfo of the method whose control flow graph is to be computed.
     */
    ControlFlowGraph(MethodBodyInfo mbi)
    {
        this.mbi = mbi;
        this.startBlock = newBlock();
        buildCfg();
    }

    /**
     *  This ControlFlowGraph's MethodBodyInfo.
     */
    private final MethodBodyInfo mbi;

    /**
     *  Blocks of the flow graph in entry order.
     */
    private ArrayList<IBasicBlock> blocks = new ArrayList<IBasicBlock>();

    /**
     * The entry point of this routine; known in
     * graph theory as the start block.
     */
    private Block startBlock;

    /**
     *  Blocks keyed by their Labels.  Multiple Labels may map to a Block.
     */
    private Map<Label, IBasicBlock> blocksByLabel = new HashMap<Label, IBasicBlock>();

    /**
     *  Catch targets defined in this method.
     */
    private ArrayList<IBasicBlock> catchTargets = new ArrayList<IBasicBlock>();

    /**
     *  The graph's dominator tree, built on demand.
     */
    private DominatorTree dominatorTree = null;

    /**
     * Build the CFG.
     */
    private void buildCfg()
    {
        Block current_block = startBlock;

        boolean last_block_transferred_control = false;

        //  Sort the labels by position.
        Collections.sort(mbi.getInstructionList().getActiveLabels());
        Iterator<Label> labels = mbi.getInstructionList().getActiveLabels().iterator();
        Label next_label = getNextLabel(labels);

        //  Labels of a Block's successors, keyed by the "from" block.
        //  These are turned into edges from the "from" block once all
        //  blocks have been seen.
        Map<Block, Collection<Label>> successor_labels = new HashMap<Block, Collection<Label>>();

        //  Iterate through the method's instructions by position; the active Labels
        //  have embedded position information that corresponds to this zero-based 
        //  enumeration of the instructions.
        List<Instruction> instructions = mbi.getInstructionList().getInstructions();

        for (int i = 0; i < instructions.size(); i++)
        {
            if (i == next_label.getPosition() || last_block_transferred_control)
            {
                if ( current_block.size() > 0 )
                {
                    Block prev_block = current_block;
                    current_block = newBlock();

                    if (prev_block.canFallThrough())
                    {
                        // Add an edge from the prev block to the current block, since
                        // control can fall through from that block to the current one.
                        prev_block.addSuccessor(current_block);
                    }
                }
                else
                {
                    // If the first instruction is a label target,
                    // then the start block will still be empty;
                    // this is actually OK for the flowgraph, but
                    // would create a special case empty block
                    // and complicate clients' block processing.
                    assert current_block == startBlock;
                }

                //  Add catch targets to the CFG's mapping.
                if (i == next_label.getPosition() && this.mbi.isCatchTarget(next_label))
                    this.catchTargets.add(current_block);

                //  Map all labels targeting this block.
                while (next_label.getPosition() == i) 
                {
                    blocksByLabel.put(next_label, current_block);
                    next_label = getNextLabel(labels);
                }
            }
            
            Instruction insn = instructions.get(i);
            current_block.add(insn);

            //  Begin a new block after any transfer of control.
            last_block_transferred_control = insn.isTransferOfControl();

            if (insn.isBranch())
            {
                Collection<Label> successors = successor_labels.get(current_block);
                if (successors == null)
                {
                    successors = new ArrayList<Label>();
                    successor_labels.put(current_block, successors);
                }
                
                // The target may be a forward jump to a block we haven't seen,
                // just store the label for now, and we'll get its block later after
                // we've seen all the instructions.
                if (insn.getOpcode() == ABCConstants.OP_lookupswitch)
                {
                    for (int j = 0; j < insn.getOperandCount(); j++)
                    {
                        if (insn.getOperand(j) instanceof Label)
                            successors.add((Label)insn.getOperand(j));
                    }
                }
                else
                {
                    successors.add(insn.getTarget());
                }
            }
        }

        // We've seen all the instructions now, so we can compute the blocks that
        // each label corresponds to, and fill in the rest of the graph
        for (Map.Entry<Block, Collection<Label>> entry : successor_labels.entrySet())
            for (Label target_label : entry.getValue())
            {
                IBasicBlock target_block = getBlock(target_label);
                if ( target_block != null )
                    entry.getKey().addSuccessor(target_block);
            }
    }
    
    /**
     *  Get a Label's target Block.
     * 
     *  @param l - the Label of interest.
     *  @return the corresponding Block, or null if not found.
     */
    public IBasicBlock getBlock(Label l)
    {
        return blocksByLabel.get(l);
    }

    /**
     *  Get the start block.
     *  @return the start block.
     */
    public IBasicBlock getStartBlock()
    {
        return this.startBlock;
    }

    /**
     *  Is the given Block a catch target?
     *  @param b - the Block of interest.
     *  @return true if the Block is a catch target.
     *  @see MethodBodyInfo#isCatchTarget(Label)
     *    which differs from this routine in that it uses 
     *    positional information, which is not valid if the
     *    ControlFlowGraph has been edited.
     */
    public boolean isCatchTarget(IBasicBlock b)
    {
        return this.catchTargets.contains(b);
    }

    /**
     * Get an iterator that will iterate over the blocks in the graph.
     * in depth-first preorder. This will traverse each edge in the graph
     * once, but may return the same block multiple times if multiple edges lead
     * to it.
     */
    public Iterable<IBasicBlock> blocksInControlFlowOrder()
    {
        return new Iterable<IBasicBlock>()
        {
            @Override
            public Iterator<IBasicBlock> iterator()
            {
                return new DepthFirstPreorderIterator(ControlFlowGraph.this.getRoots());
            }
        };
    }

    /**
     *  Start a new block.
     * 
     *  @return the new Block.
     */
    private Block newBlock()
    {
        Block result = new Block();
        blocks.add(result);
        return result;
    }
    
    /**
     *  @param labels - an Iterator of Labels.
     *  @return the next Label in the sequence, or a marker
     *  Label if the sequence is exhausted.
     */
    private Label getNextLabel(Iterator<Label> labels)
    {
        if (labels.hasNext())
            return labels.next();
        else
            return END_OF_LABEL_SEQUENCE;
    }

    private static final Label END_OF_LABEL_SEQUENCE = new Label();

    /**
     *  Get the graph's blocks in their original order.
     * 
     *  @return an immutable List that presents the blocks in entry order.
     */
    public List<IBasicBlock> getBlocksInEntryOrder()
    {
        return Collections.unmodifiableList(this.blocks);
    }

    /**
     *  Get the graph's blocks as a mutable list.
     *  @return the blocks in a list.
     */
    List<IBasicBlock> getBlocks()
    {
        return this.blocks;
    }

    /**
     * Walk a IFlowGraphVisitor over this CFG.
     * 
     *  @param visitor - the visitor.
     */
    public void traverseGraph(IFlowGraphVisitor visitor)
    {
        for (IBasicBlock b : this.blocksInControlFlowOrder())
        {
            if (visitor.visitBlock(b))
            {
                for (Instruction i : b.getInstructions())
                    visitor.visitInstruction(i);

                visitor.visitEnd(b);
            }
        }
    }

    /**
     *  Touch the graph's dominator tree and fetch it.
     *  @return the graph's dominator tree.
     */
    public DominatorTree getDominatorTree()
    {
        if ( this.dominatorTree == null )
            this.dominatorTree = new DominatorTree(getRoots());

        return this.dominatorTree;
    }

    /**
     * Synthesize this flowgraph's "roots."  The flowgraph actually
     * has only one root, the start block, but the exception handlers
     * aren't reachable by normal control flow so for the moment they're
     * considered alternate roots.
     * @return the Collection of the start block and any exception handlers.
     */
    private Collection<IBasicBlock> getRoots()
    {
        Collection<IBasicBlock> roots = new ArrayList<IBasicBlock>();
        roots.add(this.startBlock);
        roots.addAll(this.catchTargets);

        return roots;
    }

    /**
     *  Remove an unreachable block from the CFG.
     *  @param b - the Block to remove.  
     *  @pre b must be unreachable.
     */
    public void removeUnreachableBlock(IBasicBlock b)
    {
        assert(!isReachable(b));

        //  The CFG is naive about reachability 
        //  of exception-handling targets, so
        //  this procedure may remove blocks
        //  that were formerly "reachable."
        boolean removedFormerlyReachable = false;

        //  Edit any exception-handlers that reference b.
        for ( ExceptionInfo ex: this.mbi.getExceptions() )
        {
            if ( b.equals(getBlock(ex.getFrom())) )
            {
                if ( b.equals(getBlock(ex.getTo())) )
                {
                    //  This exception-handler is now dead.
                    ex.setLive(false);
                    this.catchTargets.remove(getBlock(ex.getTarget()));
                    removedFormerlyReachable = true;
                }
                else
                {
                    //  Move the mapping of the From label
                    //  to the next block in the covered region.
                    int bIdx = this.blocks.indexOf(b);
                    assert bIdx >= 0 && bIdx < this.blocks.size();

                    this.blocksByLabel.put(ex.getFrom(), this.blocks.get(bIdx+1));
                }
            }
            else if ( b.equals(getBlock(ex.getTo())) )
            {
                if ( b.equals(getBlock(ex.getFrom())) )
                {
                    //  This exception-handler is now dead.
                    ex.setLive(false);
                    this.catchTargets.remove(getBlock(ex.getTarget()));
                    removedFormerlyReachable = true;
                }
                else
                {
                    //  Move the mapping of the To label
                    //  to the previous block in the covered region.
                    int bIdx = this.blocks.indexOf(b);
                    assert bIdx >= 1 && bIdx < this.blocks.size();

                    this.blocksByLabel.put(ex.getTo(), this.blocks.get(bIdx-1));
                }
            }
        }

        if ( removedFormerlyReachable )
        {
            //  The dominator tree needs to be recomputed.
            this.dominatorTree = null;
        }

        //  Finally, remove the block itself.
        this.blocks.remove(b);
    }

    /**
     *  Is the given Block reachable?
     *  @param b - the block of interest.
     *  @return true if a path exists from
     *    any "entry" block to b.
     */
    public boolean isReachable(IBasicBlock b)
    {
        return getDominatorTree().topologicalTraversal().contains(b);
    }

    /**
     * Find the closest matching line number to the start of a block.
     * @param b the block of interest.
     * @return any initial debugline within the block, or the nearest
     * debugline in the preceeding (entry-order) blocks.
     */
    public int findLineNumber(IBasicBlock b)
    {
        return findLineNumber(b, 0, SearchDirection.Forward);
    }

    /**
     * Find the nearest debugline instruction preceeding the given
     * (Block,offset) position and fetch its line number.
     * @param b - the Block of interest.
     * @param initialOffset - the start offset in the block.
     * @return the closest debugline instruction's line number,
     * or -1 if not found.
     */
    public int findLineNumber(IBasicBlock b, int initialOffset)
    {
        return findLineNumber(b, b.size()-1, SearchDirection.Backward);
    }

    /**
     * Find the nearest debugline instruction preceeding the given
     * (Block,offset) position and fetch its line number.
     * @param b - the Block of interest.
     * @param initialOffset - the start offset in the block.
     * @param initialDirection Search the first block Forward or Backward.
     * @return the closest debugline instruction's line number,
     * or -1 if not found.
     */
    private int findLineNumber(IBasicBlock b, int initialOffset, SearchDirection initialDirection)
    {
        assert(this.blocks.contains(b));
        // Start searching in the block given; the offset may
        // be a pseudo-offset that specifies an initial forward
        // search through non-executable instructions.
        Instruction result = searchBlock(b, ABCConstants.OP_debugline, initialOffset, initialDirection);

        if ( result != null )
        {
            //  Found a good line number match; return it as a zero-based offset.
            return result.getImmediate() - 1;
        }
        else
        {
            //  Search backwards through the instruction stream; bump any line
            //  number found during this search since the dead block is probably
            //  on the next line.
            for ( int i = this.blocks.indexOf(b) - 1; i >= 0 && result == null; i-- )
            {
                IBasicBlock candidate = this.blocks.get(i);
                result = searchBlock( candidate, ABCConstants.OP_debugline, candidate.size() - 1, SearchDirection.Backward);
            }
        }

        return result != null? result.getImmediate(): -1;
    }

    /**
     * Find the nearest debugfile instruction to the start of
     * the given block and fetch its source path.
     * @param b - the Block of interest.
     * @return the closest debugfile instruction's source path,
     * or null if not found.
     */
    public String findSourcePath(IBasicBlock b)
    {
        return findSourcePath(b, 0, SearchDirection.Forward);
    }
    /**
     * Find the nearest instruction preceeding the given
     * (Block,offset) position and fetch its source path.
     * @param b - the Block of interest.
     * @param initialOffset - the start offset in the block.
     * @return the closest debugfile instruction's source path,
     * or null if not found.
     */
    public String findSourcePath(IBasicBlock b, int initialOffset)
    {
        return findSourcePath(b, initialOffset, SearchDirection.Backward);
    }

    /**
     * Find the nearest debugline instruction to the given (Block, offset)
     * position and fetch its source path.
     * @param b the block of interest.
     * @param initialOffset the start offset in the block.
     * @param initialDirection Search the first block Forward or Backward.
     * @return the closest debugfile instruction's source path,
     * or null if not found.
     */
    private String findSourcePath(IBasicBlock b, int initialOffset, SearchDirection initialDirection)
    {
        assert(this.blocks.contains(b));

        Instruction result = searchBlock(b, ABCConstants.OP_debugfile, initialOffset, initialDirection);

        //  Search backwards through the instruction stream if necessary.
        if ( result == null )
        {
            for ( int i = this.blocks.indexOf(b) - 1; i >= 0 && result == null; i-- )
            {
                IBasicBlock candidate = this.blocks.get(i);
                result = searchBlock(candidate, ABCConstants.OP_debugfile, candidate.size() - 1, SearchDirection.Backward);
            }
        }

        if (result == null)
            return null;

        // The debug filename can sometimes be in the format: sourcepath;package;filename so
        // need to translate that back to an absolute path by replacing the ;'s with system
        // path separators, making sure to normailize path separators.
        String debugFilename = result.getOperand(0).toString();
        char otherSeparator = File.separatorChar == '/' ? '\\' : '/';
        debugFilename = debugFilename.replace(otherSeparator, File.separatorChar);
        return debugFilename.replace(';', File.separatorChar);
    }

    /**
     * Find an instruction in the given block, working 
     * forwards or backwards from the specified offset.
     * @param b the block of interest.
     * @param opcode the opcode of the desired Instruction.
     * @param initialOffset the offset at which to begin searching.
     * @param direction Forward or Backward.
     * @return the first instruction encountered with the specified
     * opcode, or null if none found or the offset is out of range.
     */
    private Instruction searchBlock(IBasicBlock b, int opcode, int initialOffset, SearchDirection direction)
    {
        Instruction result = null;
        int blockSize = b.size();

        assert initialOffset >= 0 && initialOffset < blockSize: String.format("invalid initialOffset %d", initialOffset);

        int offset = initialOffset;
        while ( result == null && offset >= 0 && offset < blockSize )
        {
            Instruction candidate = b.get(offset);

            if ( candidate.getOpcode() == opcode )
                result = candidate;
            else if ( direction == SearchDirection.Forward )
                offset++;
            else
                offset--;
        }

        return result;
    }
}
