/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed 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 com.android.dx.ssa;

import com.android.dx.util.IntSet;
import com.android.dx.util.BitIntSet;
import com.android.dx.util.ListIntSet;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;

/**
 * Calculates the dominance-frontiers of a methot's basic blocks.
 * Algorithm from "A Simple, Fast Dominance Algorithm" by Cooper,
 * Harvey, and Kennedy; transliterated to Java.
 */
public class DomFront {
    /** local debug flag */
    private static boolean DEBUG = false;

    /** {@code non-null;} method being processed */
    private final SsaMethod meth;

    private final ArrayList<SsaBasicBlock> nodes;

    private final DomInfo[] domInfos;

    /**
     * Dominance-frontier information for a single basic block.
     */
    public static class DomInfo {
        /**
         * {@code null-ok;} the dominance frontier set indexed by
         * block index
         */
        public IntSet dominanceFrontiers;

        /** {@code >= 0 after run();} the index of the immediate dominator */
        public int idom = -1;
    }

    /**
     * Constructs instance. Call {@link DomFront#run} to process.
     *
     * @param meth {@code non-null;} method to process
     */
    public DomFront(SsaMethod meth) {
        this.meth = meth;
        nodes = meth.getBlocks();

        int szNodes = nodes.size();
        domInfos = new DomInfo[szNodes];

        for (int i = 0; i < szNodes; i++) {
            domInfos[i] = new DomInfo();
        }
    }

    /**
     * Calculates the dominance frontier information for the method.
     *
     * @return {@code non-null;} an array of DomInfo structures
     */
    public DomInfo[] run() {
        int szNodes = nodes.size();

        if (DEBUG) {
            for (int i = 0; i < szNodes; i++) {
                SsaBasicBlock node = nodes.get(i);
                System.out.println("pred[" + i + "]: "
                        + node.getPredecessors());
            }
        }

        Dominators methDom = Dominators.make(meth, domInfos, false);

        if (DEBUG) {
            for (int i = 0; i < szNodes; i++) {
                DomInfo info = domInfos[i];
                System.out.println("idom[" + i + "]: "
                        + info.idom);
            }
        }

        buildDomTree();

        if (DEBUG) {
            debugPrintDomChildren();
        }

        for (int i = 0; i < szNodes; i++) {
            domInfos[i].dominanceFrontiers
                    = SetFactory.makeDomFrontSet(szNodes);
        }

        calcDomFronts();

        if (DEBUG) {
            for (int i = 0; i < szNodes; i++) {
                System.out.println("df[" + i + "]: "
                        + domInfos[i].dominanceFrontiers);
            }
        }

        return domInfos;
    }

    private void debugPrintDomChildren() {
        int szNodes = nodes.size();

        for (int i = 0; i < szNodes; i++) {
            SsaBasicBlock node = nodes.get(i);
            StringBuffer sb = new StringBuffer();

            sb.append('{');
            boolean comma = false;
            for (SsaBasicBlock child : node.getDomChildren()) {
                if (comma) {
                    sb.append(',');
                }
                sb.append(child);
                comma = true;
            }
            sb.append('}');

            System.out.println("domChildren[" + node + "]: "
                    + sb);
        }
    }

    /**
     * The dominators algorithm leaves us knowing who the immediate dominator
     * is for each node. This sweeps the node list and builds the proper
     * dominance tree.
     */
    private void buildDomTree() {
        int szNodes = nodes.size();

        for (int i = 0; i < szNodes; i++) {
            DomInfo info = domInfos[i];

            if (info.idom == -1) continue;

            SsaBasicBlock domParent = nodes.get(info.idom);
            domParent.addDomChild(nodes.get(i));
        }
    }

    /**
     * Calculates the dominance-frontier set.
     * from "A Simple, Fast Dominance Algorithm" by Cooper,
     * Harvey, and Kennedy; transliterated to Java.
     */
    private void calcDomFronts() {
        int szNodes = nodes.size();

        for (int b = 0; b < szNodes; b++) {
            SsaBasicBlock nb = nodes.get(b);
            DomInfo nbInfo = domInfos[b];
            BitSet pred = nb.getPredecessors();

            if (pred.cardinality() > 1) {
                for (int i = pred.nextSetBit(0); i >= 0;
                     i = pred.nextSetBit(i + 1)) {

                    for (int runnerIndex = i;
                         runnerIndex != nbInfo.idom; /* empty */) {
                        /*
                         * We can stop if we hit a block we already
                         * added label to, since we must be at a part
                         * of the dom tree we have seen before.
                         */
                        if (runnerIndex == -1) break;

                        DomInfo runnerInfo = domInfos[runnerIndex];

                        if (runnerInfo.dominanceFrontiers.has(b)) {
                            break;
                        }

                        // Add b to runner's dominance frontier set.
                        runnerInfo.dominanceFrontiers.add(b);
                        runnerIndex = runnerInfo.idom;
                    }
                }
            }
        }
    }
}
