/*
 * ProGuard -- shrinking, optimization, obfuscation, and preverification
 *             of Java bytecode.
 *
 * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu)
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */
package proguard.classfile.instruction;

import proguard.classfile.*;
import proguard.classfile.attribute.CodeAttribute;
import proguard.classfile.instruction.visitor.InstructionVisitor;

/**
 * This Instruction represents a simple instruction without variable arguments
 * or constant pool references.
 *
 * @author Eric Lafortune
 */
public class SimpleInstruction extends Instruction
{
    public int constant;


    /**
     * Creates an uninitialized SimpleInstruction.
     */
    public SimpleInstruction() {}


    /**
     * Creates a new SimpleInstruction with the given opcode.
     */
    public SimpleInstruction(byte opcode)
    {
        this(opcode, embeddedConstant(opcode));
    }


    /**
     * Creates a new SimpleInstruction with the given opcode and constant.
     */
    public SimpleInstruction(byte opcode, int constant)
    {
        this.opcode   = opcode;
        this.constant = constant;
    }


    /**
     * Copies the given instruction into this instruction.
     * @param simpleInstruction the instruction to be copied.
     * @return this instruction.
     */
    public SimpleInstruction copy(SimpleInstruction simpleInstruction)
    {
        this.opcode   = simpleInstruction.opcode;
        this.constant = simpleInstruction.constant;

        return this;
    }


    /**
     * Return the embedded constant of the given opcode, or 0 if the opcode
     * doesn't have one.
     */
    private static int embeddedConstant(byte opcode)
    {
        switch (opcode)
        {
            case InstructionConstants.OP_ICONST_M1: return -1;

            case InstructionConstants.OP_ICONST_1:
            case InstructionConstants.OP_LCONST_1:
            case InstructionConstants.OP_FCONST_1:
            case InstructionConstants.OP_DCONST_1: return 1;

            case InstructionConstants.OP_ICONST_2:
            case InstructionConstants.OP_FCONST_2: return 2;

            case InstructionConstants.OP_ICONST_3: return 3;

            case InstructionConstants.OP_ICONST_4: return 4;

            case InstructionConstants.OP_ICONST_5: return 5;

            default: return 0;
        }
    }


    // Implementations for Instruction.

    public byte canonicalOpcode()
    {
        // Replace any _1, _2, _3,... extension by _0.
        switch (opcode)
        {
            case InstructionConstants.OP_ICONST_M1:
            case InstructionConstants.OP_ICONST_0:
            case InstructionConstants.OP_ICONST_1:
            case InstructionConstants.OP_ICONST_2:
            case InstructionConstants.OP_ICONST_3:
            case InstructionConstants.OP_ICONST_4:
            case InstructionConstants.OP_ICONST_5:
            case InstructionConstants.OP_BIPUSH:
            case InstructionConstants.OP_SIPUSH:   return InstructionConstants.OP_ICONST_0;

            case InstructionConstants.OP_LCONST_0:
            case InstructionConstants.OP_LCONST_1: return InstructionConstants.OP_LCONST_0;

            case InstructionConstants.OP_FCONST_0:
            case InstructionConstants.OP_FCONST_1:
            case InstructionConstants.OP_FCONST_2: return InstructionConstants.OP_FCONST_0;

            case InstructionConstants.OP_DCONST_0:
            case InstructionConstants.OP_DCONST_1: return InstructionConstants.OP_DCONST_0;

            default: return opcode;
        }
    }

    public Instruction shrink()
    {
        // Reconstruct the opcode of the shortest instruction, if there are
        // any alternatives.
        switch (opcode)
        {
            case InstructionConstants.OP_ICONST_M1:
            case InstructionConstants.OP_ICONST_0:
            case InstructionConstants.OP_ICONST_1:
            case InstructionConstants.OP_ICONST_2:
            case InstructionConstants.OP_ICONST_3:
            case InstructionConstants.OP_ICONST_4:
            case InstructionConstants.OP_ICONST_5:
            case InstructionConstants.OP_BIPUSH:
            case InstructionConstants.OP_SIPUSH:
                switch (requiredConstantSize())
                {
                    case 0:
                        opcode = (byte)(InstructionConstants.OP_ICONST_0 + constant);
                        break;
                    case 1:
                        opcode = InstructionConstants.OP_BIPUSH;
                        break;
                    case 2:
                        opcode = InstructionConstants.OP_SIPUSH;
                        break;
                }
                break;

            case InstructionConstants.OP_LCONST_0:
            case InstructionConstants.OP_LCONST_1:
                opcode = (byte)(InstructionConstants.OP_LCONST_0 + constant);
                break;

            case InstructionConstants.OP_FCONST_0:
            case InstructionConstants.OP_FCONST_1:
            case InstructionConstants.OP_FCONST_2:
                opcode = (byte)(InstructionConstants.OP_FCONST_0 + constant);
                break;

            case InstructionConstants.OP_DCONST_0:
            case InstructionConstants.OP_DCONST_1:
                opcode = (byte)(InstructionConstants.OP_DCONST_0 + constant);
                break;
        }

        return this;
    }

    protected void readInfo(byte[] code, int offset)
    {
        int constantSize = constantSize();

        // Also initialize embedded constants that are different from 0.
        constant = constantSize == 0 ?
            embeddedConstant(opcode) :
            readSignedValue(code, offset, constantSize);
    }


    protected void writeInfo(byte[] code, int offset)
    {
        int constantSize = constantSize();

        if (requiredConstantSize() > constantSize)
        {
            throw new IllegalArgumentException("Instruction has invalid constant size ("+this.toString(offset)+")");
        }

        writeSignedValue(code, offset, constant, constantSize);
    }


    public int length(int offset)
    {
        return 1 + constantSize();
    }


    public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, InstructionVisitor instructionVisitor)
    {
        instructionVisitor.visitSimpleInstruction(clazz, method, codeAttribute, offset, this);
    }


    // Implementations for Object.

    public String toString()
    {
        return getName() +
               (constantSize() > 0 ? " "+constant : "");
    }


    // Small utility methods.

    /**
     * Returns the constant size for this instruction.
     */
    private int constantSize()
    {
        return opcode == InstructionConstants.OP_BIPUSH ||
               opcode == InstructionConstants.OP_NEWARRAY ? 1 :
               opcode == InstructionConstants.OP_SIPUSH   ? 2 :
                                                            0;
    }


    /**
     * Computes the required constant size for this instruction.
     */
    private int requiredConstantSize()
    {
        return constant >= -1 && constant <= 5  ? 0 :
               (byte)constant  == constant      ? 1 :
               (short)constant == constant      ? 2 :
                                                  4;
    }
}
