/*
 * 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.cf.code;

import com.android.dx.rop.cst.Constant;
import com.android.dx.rop.cst.CstMemberRef;
import com.android.dx.rop.cst.CstType;
import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.type.Type;
import com.android.dx.util.Bits;
import com.android.dx.util.IntList;
import java.util.ArrayList;

/**
 * Utility that identifies basic blocks in bytecode.
 */
public final class BasicBlocker implements BytecodeArray.Visitor {
    /** {@code non-null;} method being converted */
    private final ConcreteMethod method;

    /**
     * {@code non-null;} work set; bits indicate offsets in need of
     * examination
     */
    private final int[] workSet;

    /**
     * {@code non-null;} live set; bits indicate potentially-live
     * opcodes; contrawise, a bit that isn't on is either in the
     * middle of an instruction or is a definitely-dead opcode
     */
    private final int[] liveSet;

    /**
     * {@code non-null;} block start set; bits indicate the starts of
     * basic blocks, including the opcodes that start blocks of
     * definitely-dead code
     */
    private final int[] blockSet;

    /**
     * {@code non-null, sparse;} for each instruction offset to a branch of
     * some sort, the list of targets for that instruction
     */
    private final IntList[] targetLists;

    /**
     * {@code non-null, sparse;} for each instruction offset to a throwing
     * instruction, the list of exception handlers for that instruction
     */
    private final ByteCatchList[] catchLists;

    /** offset of the previously parsed bytecode */
    private int previousOffset;

    /**
     * Identifies and enumerates the basic blocks in the given method,
     * returning a list of them. The returned list notably omits any
     * definitely-dead code that is identified in the process.
     *
     * @param method {@code non-null;} method to convert
     * @return {@code non-null;} list of basic blocks
     */
    public static ByteBlockList identifyBlocks(ConcreteMethod method) {
        BasicBlocker bb = new BasicBlocker(method);

        bb.doit();
        return bb.getBlockList();
    }

    /**
     * Constructs an instance. This class is not publicly instantiable; use
     * {@link #identifyBlocks}.
     *
     * @param method {@code non-null;} method to convert
     */
    private BasicBlocker(ConcreteMethod method) {
        if (method == null) {
            throw new NullPointerException("method == null");
        }

        this.method = method;

        /*
         * The "+1" below is so the idx-past-end is also valid,
         * avoiding a special case, but without preventing
         * flow-of-control falling past the end of the method from
         * getting properly reported.
         */
        int sz = method.getCode().size() + 1;

        workSet = Bits.makeBitSet(sz);
        liveSet = Bits.makeBitSet(sz);
        blockSet = Bits.makeBitSet(sz);
        targetLists = new IntList[sz];
        catchLists = new ByteCatchList[sz];
        previousOffset = -1;
    }

    /*
     * Note: These methods are defined implementation of the interface
     * BytecodeArray.Visitor; since the class isn't publicly
     * instantiable, no external code ever gets a chance to actually
     * call these methods.
     */

    /** {@inheritDoc} */
    public void visitInvalid(int opcode, int offset, int length) {
        visitCommon(offset, length, true);
    }

    /** {@inheritDoc} */
    public void visitNoArgs(int opcode, int offset, int length, Type type) {
        switch (opcode) {
            case ByteOps.IRETURN:
            case ByteOps.RETURN: {
                visitCommon(offset, length, false);
                targetLists[offset] = IntList.EMPTY;
                break;
            }
            case ByteOps.ATHROW: {
                visitCommon(offset, length, false);
                visitThrowing(offset, length, false);
                break;
            }
            case ByteOps.IALOAD:
            case ByteOps.LALOAD:
            case ByteOps.FALOAD:
            case ByteOps.DALOAD:
            case ByteOps.AALOAD:
            case ByteOps.BALOAD:
            case ByteOps.CALOAD:
            case ByteOps.SALOAD:
            case ByteOps.IASTORE:
            case ByteOps.LASTORE:
            case ByteOps.FASTORE:
            case ByteOps.DASTORE:
            case ByteOps.AASTORE:
            case ByteOps.BASTORE:
            case ByteOps.CASTORE:
            case ByteOps.SASTORE:
            case ByteOps.ARRAYLENGTH:
            case ByteOps.MONITORENTER:
            case ByteOps.MONITOREXIT: {
                /*
                 * These instructions can all throw, so they have to end
                 * the block they appear in (since throws are branches).
                 */
                visitCommon(offset, length, true);
                visitThrowing(offset, length, true);
                break;
            }
            case ByteOps.IDIV:
            case ByteOps.IREM: {
                /*
                 * The int and long versions of division and remainder may
                 * throw, but not the other types.
                 */
                visitCommon(offset, length, true);
                if ((type == Type.INT) || (type == Type.LONG)) {
                    visitThrowing(offset, length, true);
                }
                break;
            }
            default: {
                visitCommon(offset, length, true);
                break;
            }
        }
    }

    /** {@inheritDoc} */
    public void visitLocal(int opcode, int offset, int length,
            int idx, Type type, int value) {
        if (opcode == ByteOps.RET) {
            visitCommon(offset, length, false);
            targetLists[offset] = IntList.EMPTY;
        } else {
            visitCommon(offset, length, true);
        }
    }

    /** {@inheritDoc} */
    public void visitConstant(int opcode, int offset, int length,
            Constant cst, int value) {
        visitCommon(offset, length, true);

        if ((cst instanceof CstMemberRef) || (cst instanceof CstType) ||
            (cst instanceof CstString)) {
            /*
             * Instructions with these sorts of constants have the
             * possibility of throwing, so this instruction needs to
             * end its block (since it can throw, and possible-throws
             * are branch points).
             */
            visitThrowing(offset, length, true);
        }
    }

    /** {@inheritDoc} */
    public void visitBranch(int opcode, int offset, int length,
            int target) {
        switch (opcode) {
            case ByteOps.GOTO: {
                visitCommon(offset, length, false);
                targetLists[offset] = IntList.makeImmutable(target);
                break;
            }
            case ByteOps.JSR: {
                /*
                 * Each jsr is quarantined into a separate block (containing
                 * only the jsr instruction) but is otherwise treated
                 * as a conditional branch. (That is to say, both its
                 * target and next instruction begin new blocks.)
                 */
                addWorkIfNecessary(offset, true);
                // Fall through to next case...
            }
            default: {
                int next = offset + length;
                visitCommon(offset, length, true);
                addWorkIfNecessary(next, true);
                targetLists[offset] = IntList.makeImmutable(next, target);
                break;
            }
        }

        addWorkIfNecessary(target, true);
    }

    /** {@inheritDoc} */
    public void visitSwitch(int opcode, int offset, int length,
            SwitchList cases, int padding) {
        visitCommon(offset, length, false);
        addWorkIfNecessary(cases.getDefaultTarget(), true);

        int sz = cases.size();
        for (int i = 0; i < sz; i++) {
            addWorkIfNecessary(cases.getTarget(i), true);
        }

        targetLists[offset] = cases.getTargets();
    }

    /** {@inheritDoc} */
    public void visitNewarray(int offset, int length, CstType type,
            ArrayList<Constant> intVals) {
        visitCommon(offset, length, true);
        visitThrowing(offset, length, true);
    }

    /**
     * Extracts the list of basic blocks from the bit sets.
     *
     * @return {@code non-null;} the list of basic blocks
     */
    private ByteBlockList getBlockList() {
        BytecodeArray bytes = method.getCode();
        ByteBlock[] bbs = new ByteBlock[bytes.size()];
        int count = 0;

        for (int at = 0, next; /*at*/; at = next) {
            next = Bits.findFirst(blockSet, at + 1);
            if (next < 0) {
                break;
            }

            if (Bits.get(liveSet, at)) {
                /*
                 * Search backward for the branch or throwing
                 * instruction at the end of this block, if any. If
                 * there isn't any, then "next" is the sole target.
                 */
                IntList targets = null;
                int targetsAt = -1;
                ByteCatchList blockCatches;

                for (int i = next - 1; i >= at; i--) {
                    targets = targetLists[i];
                    if (targets != null) {
                        targetsAt = i;
                        break;
                    }
                }

                if (targets == null) {
                    targets = IntList.makeImmutable(next);
                    blockCatches = ByteCatchList.EMPTY;
                } else {
                    blockCatches = catchLists[targetsAt];
                    if (blockCatches == null) {
                        blockCatches = ByteCatchList.EMPTY;
                    }
                }

                bbs[count] =
                    new ByteBlock(at, at, next, targets, blockCatches);
                count++;
            }
        }

        ByteBlockList result = new ByteBlockList(count);
        for (int i = 0; i < count; i++) {
            result.set(i, bbs[i]);
        }

        return result;
    }

    /**
     * Does basic block identification.
     */
    private void doit() {
        BytecodeArray bytes = method.getCode();
        ByteCatchList catches = method.getCatches();
        int catchSz = catches.size();

        /*
         * Start by setting offset 0 as the start of a block and in need
         * of work...
         */
        Bits.set(workSet, 0);
        Bits.set(blockSet, 0);

        /*
         * And then process the work set, add new work based on
         * exception ranges that are active, and iterate until there's
         * nothing left to work on.
         */
        while (!Bits.isEmpty(workSet)) {
            try {
                bytes.processWorkSet(workSet, this);
            } catch (IllegalArgumentException ex) {
                // Translate the exception.
                throw new SimException("flow of control falls off " +
                                       "end of method",
                                       ex);
            }

            for (int i = 0; i < catchSz; i++) {
                ByteCatchList.Item item = catches.get(i);
                int start = item.getStartPc();
                int end = item.getEndPc();
                if (Bits.anyInRange(liveSet, start, end)) {
                    Bits.set(blockSet, start);
                    Bits.set(blockSet, end);
                    addWorkIfNecessary(item.getHandlerPc(), true);
                }
            }
        }
    }

    /**
     * Sets a bit in the work set, but only if the instruction in question
     * isn't yet known to be possibly-live.
     *
     * @param offset offset to the instruction in question
     * @param blockStart {@code true} iff this instruction starts a
     * basic block
     */
    private void addWorkIfNecessary(int offset, boolean blockStart) {
        if (!Bits.get(liveSet, offset)) {
            Bits.set(workSet, offset);
        }

        if (blockStart) {
            Bits.set(blockSet, offset);
        }
    }

    /**
     * Helper method used by all the visitor methods.
     *
     * @param offset offset to the instruction
     * @param length length of the instruction, in bytes
     * @param nextIsLive {@code true} iff the instruction after
     * the indicated one is possibly-live (because this one isn't an
     * unconditional branch, a return, or a switch)
     */
    private void visitCommon(int offset, int length, boolean nextIsLive) {
        Bits.set(liveSet, offset);

        if (nextIsLive) {
            /*
             * If the next instruction is flowed to by this one, just
             * add it to the work set, and then a subsequent visit*()
             * will deal with it as appropriate.
             */
            addWorkIfNecessary(offset + length, false);
        } else {
            /*
             * If the next instruction isn't flowed to by this one,
             * then mark it as a start of a block but *don't* add it
             * to the work set, so that in the final phase we can know
             * dead code blocks as those marked as blocks but not also marked
             * live.
             */
            Bits.set(blockSet, offset + length);
        }
    }

    /**
     * Helper method used by all the visitor methods that deal with
     * opcodes that possibly throw. This method should be called after calling
     * {@link #visitCommon}.
     *
     * @param offset offset to the instruction
     * @param length length of the instruction, in bytes
     * @param nextIsLive {@code true} iff the instruction after
     * the indicated one is possibly-live (because this one isn't an
     * unconditional throw)
     */
    private void visitThrowing(int offset, int length, boolean nextIsLive) {
        int next = offset + length;

        if (nextIsLive) {
            addWorkIfNecessary(next, true);
        }

        ByteCatchList catches = method.getCatches().listFor(offset);
        catchLists[offset] = catches;
        targetLists[offset] = catches.toTargetList(nextIsLive ? next : -1);
    }

    /**
     * {@inheritDoc}
     */
    public void setPreviousOffset(int offset) {
        previousOffset = offset;
    }

    /**
     * {@inheritDoc}
     */
    public int getPreviousOffset() {
        return previousOffset;
    }
}
