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

/**
 * A "normal" (non-phi) instruction in SSA form. Always wraps a rop insn.
 */
public final class NormalSsaInsn extends SsaInsn implements Cloneable {
    /** {@code non-null;} rop insn that we're wrapping */
    private Insn insn;

    /**
     * Creates an instance.
     *
     * @param insn Rop insn to wrap
     * @param block block that contains this insn
     */
    NormalSsaInsn(final Insn insn, final SsaBasicBlock block) {
        super(insn.getResult(), block);
        this.insn = insn;
    }

    /** {@inheritDoc} */
    @Override
    public final void mapSourceRegisters(RegisterMapper mapper) {
        RegisterSpecList oldSources = insn.getSources();
        RegisterSpecList newSources = mapper.map(oldSources);

        if (newSources != oldSources) {
            insn = insn.withNewRegisters(getResult(), newSources);
            getBlock().getParent().onSourcesChanged(this, oldSources);
        }
    }

    /**
     * Changes one of the insn's sources. New source should be of same type
     * and category.
     *
     * @param index {@code >=0;} index of source to change
     * @param newSpec spec for new source
     */
    public final void changeOneSource(int index, RegisterSpec newSpec) {
        RegisterSpecList origSources = insn.getSources();
        int sz = origSources.size();
        RegisterSpecList newSources = new RegisterSpecList(sz);

        for (int i = 0; i < sz; i++) {
            newSources.set(i, i == index ? newSpec : origSources.get(i));
        }

        newSources.setImmutable();

        RegisterSpec origSpec = origSources.get(index);
        if (origSpec.getReg() != newSpec.getReg()) {
            /*
             * If the register remains unchanged, we're only changing
             * the type or local var name so don't update use list
             */
            getBlock().getParent().onSourceChanged(this, origSpec, newSpec);
        }

        insn = insn.withNewRegisters(getResult(), newSources);
    }

    /**
     * Changes the source list of the insn. New source list should be the
     * same size and consist of sources of identical types.
     *
     * @param newSources non-null new sources list.
     */
    public final void setNewSources (RegisterSpecList newSources) {
        RegisterSpecList origSources = insn.getSources();

        if (origSources.size() != newSources.size()) {
            throw new RuntimeException("Sources counts don't match");
        }

        insn = insn.withNewRegisters(getResult(), newSources);
    }

    /** {@inheritDoc} */
    @Override
    public NormalSsaInsn clone() {
        return (NormalSsaInsn) super.clone();
    }

    /**
     * Like rop.Insn.getSources().
     *
     * @return {@code null-ok;} sources list
     */
    @Override
    public RegisterSpecList getSources() {
        return insn.getSources();
    }

    /** {@inheritDoc} */
    public String toHuman() {
        return toRopInsn().toHuman();
    }

    /** {@inheritDoc} */
    @Override
    public Insn toRopInsn() {
        return insn.withNewRegisters(getResult(), insn.getSources());
    }

    /**
     * @return the Rop opcode for this insn
     */
    @Override
    public Rop getOpcode() {
        return insn.getOpcode();
    }

    /** {@inheritDoc} */
    @Override
    public Insn getOriginalRopInsn() {
        return insn;
    }

    /** {@inheritDoc} */
    @Override
    public RegisterSpec getLocalAssignment() {
        RegisterSpec assignment;

        if (insn.getOpcode().getOpcode() == RegOps.MARK_LOCAL) {
            assignment = insn.getSources().get(0);
        } else {
            assignment = getResult();
        }

        if (assignment == null) {
            return null;
        }

        LocalItem local = assignment.getLocalItem();

        if (local == null) {
            return null;
        }

        return assignment;
    }

    /**
     * Upgrades this insn to a version that represents the constant source
     * literally. If the upgrade is not possible, this does nothing.
     *
     * @see Insn#withSourceLiteral
     */
    public void upgradeToLiteral() {
        RegisterSpecList oldSources = insn.getSources();

        insn = insn.withSourceLiteral();
        getBlock().getParent().onSourcesChanged(this, oldSources);
    }

    /**
     * @return true if this is a move (but not a move-operand) instruction
     */
    @Override
    public boolean isNormalMoveInsn() {
        return insn.getOpcode().getOpcode() == RegOps.MOVE;
    }

    /** {@inheritDoc} */
    @Override
    public boolean isMoveException() {
        return insn.getOpcode().getOpcode() == RegOps.MOVE_EXCEPTION;
    }

    /** {@inheritDoc} */
    @Override
    public boolean canThrow() {
        return insn.canThrow();
    }

    /** {@inheritDoc} */
    @Override
    public void accept(Visitor v) {
        if (isNormalMoveInsn()) {
            v.visitMoveInsn(this);
        } else {
            v.visitNonMoveInsn(this);
        }
    }

    /** {@inheritDoc} */
    @Override
    public  boolean isPhiOrMove() {
        return isNormalMoveInsn();
    }

    /**
     * {@inheritDoc}
     *
     * TODO: Increase the scope of this.
     */
    @Override
    public boolean hasSideEffect() {
        Rop opcode = getOpcode();

        if (opcode.getBranchingness() != Rop.BRANCH_NONE) {
            return true;
        }

        boolean hasLocalSideEffect
            = Optimizer.getPreserveLocals() && getLocalAssignment() != null;

        switch (opcode.getOpcode()) {
            case RegOps.MOVE_RESULT:
            case RegOps.MOVE:
            case RegOps.CONST:
                return hasLocalSideEffect;
            default:
                return true;
        }
    }
}
