001package serp.bytecode;
002
003import java.io.*;
004import java.util.*;
005
006import serp.bytecode.visitor.*;
007
008/**
009 * Returns a value (or void) from a method.
010 *
011 * @author Abe White
012 */
013public class ReturnInstruction extends TypedInstruction {
014    private static final Class[][] _mappings = new Class[][] {
015        { byte.class, int.class },
016        { char.class, int.class },
017        { short.class, int.class },
018        { boolean.class, int.class },
019    };
020
021    ReturnInstruction(Code owner) {
022        super(owner);
023    }
024
025    ReturnInstruction(Code owner, int opcode) {
026        super(owner, opcode);
027    }
028
029    public String getTypeName() {
030        switch (getOpcode()) {
031        case Constants.IRETURN:
032            return int.class.getName();
033        case Constants.LRETURN:
034            return long.class.getName();
035        case Constants.FRETURN:
036            return float.class.getName();
037        case Constants.DRETURN:
038            return double.class.getName();
039        case Constants.ARETURN:
040            return Object.class.getName();
041        case Constants.RETURN:
042            return void.class.getName();
043        default:
044            return null;
045        }
046    }
047
048    public TypedInstruction setType(String type) {
049        type = mapType(type, _mappings, true);
050        if (type == null)
051            return (TypedInstruction) setOpcode(Constants.NOP);
052
053        switch (type.charAt(0)) {
054        case 'i':
055            return (TypedInstruction) setOpcode(Constants.IRETURN);
056        case 'l':
057            return (TypedInstruction) setOpcode(Constants.LRETURN);
058        case 'f':
059            return (TypedInstruction) setOpcode(Constants.FRETURN);
060        case 'd':
061            return (TypedInstruction) setOpcode(Constants.DRETURN);
062        case 'v':
063            return (TypedInstruction) setOpcode(Constants.RETURN);
064        default:
065            return (TypedInstruction) setOpcode(Constants.ARETURN);
066        }
067    }
068
069    public int getLogicalStackChange() {
070        switch (getOpcode()) {
071        case Constants.NOP:
072            return 0;
073        default:
074            return -1;
075        }
076    }
077
078    public int getStackChange() {
079        switch (getOpcode()) {
080        case Constants.RETURN:
081        case Constants.NOP:
082            return 0;
083        case Constants.LRETURN:
084        case Constants.DRETURN:
085            return -2;
086        default:
087            return -1;
088        }
089    }
090
091    public void acceptVisit(BCVisitor visit) {
092        visit.enterReturnInstruction(this);
093        visit.exitReturnInstruction(this);
094    }
095}