001    package serp.bytecode;
002    
003    import java.io.*;
004    import java.util.*;
005    
006    import serp.bytecode.visitor.*;
007    
008    /**
009     * Returns a value (or void) from a method.
010     *
011     * @author Abe White
012     */
013    public 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    }