001    /*
002     * Copyright 2010-2014 JetBrains s.r.o.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.jetbrains.jet.codegen.optimization.common;
018    
019    import org.jetbrains.annotations.NotNull;
020    import org.jetbrains.annotations.Nullable;
021    import org.jetbrains.org.objectweb.asm.Opcodes;
022    import org.jetbrains.org.objectweb.asm.Type;
023    import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode;
024    import org.jetbrains.org.objectweb.asm.tree.LdcInsnNode;
025    import org.jetbrains.org.objectweb.asm.tree.analysis.AnalyzerException;
026    import org.jetbrains.org.objectweb.asm.tree.analysis.BasicInterpreter;
027    import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue;
028    
029    public class OptimizationBasicInterpreter extends BasicInterpreter {
030        private static final BasicValue MIXED_VALUE = new BasicValue(Type.getObjectType("#"));
031        private static final BasicValue BOOLEAN_VALUE = new BasicValue(Type.BOOLEAN_TYPE);
032        private static final BasicValue CHAR_VALUE = new BasicValue(Type.CHAR_TYPE);
033        private static final BasicValue BYTE_VALUE = new BasicValue(Type.BYTE_TYPE);
034        private static final BasicValue SHORT_VALUE = new BasicValue(Type.SHORT_TYPE);
035    
036        @Override
037        @Nullable
038        public BasicValue newValue(@Nullable Type type) {
039            if (type == null) {
040                return super.newValue(null);
041            }
042    
043            switch (type.getSort()) {
044                case Type.VOID:
045                    return null;
046                case Type.BOOLEAN:
047                    return BOOLEAN_VALUE;
048                case Type.CHAR:
049                    return CHAR_VALUE;
050                case Type.BYTE:
051                    return BYTE_VALUE;
052                case Type.SHORT:
053                    return SHORT_VALUE;
054                case Type.OBJECT:
055                    return new BasicValue(type);
056                default:
057                    return super.newValue(type);
058            }
059        }
060    
061        @Override
062        public BasicValue newOperation(@NotNull AbstractInsnNode insn) throws AnalyzerException {
063            if (insn.getOpcode() == Opcodes.LDC) {
064                Object cst = ((LdcInsnNode) insn).cst;
065    
066                if (cst instanceof Long) {
067                    return BasicValue.LONG_VALUE;
068                }
069    
070                if (cst instanceof Boolean ||
071                    cst instanceof Integer ||
072                    cst instanceof Short ||
073                    cst instanceof Byte ||
074                    cst instanceof Character) {
075                    return BasicValue.INT_VALUE;
076                }
077    
078                if (cst instanceof Float) {
079                    return BasicValue.FLOAT_VALUE;
080                }
081    
082                if (cst instanceof Double) {
083                    return BasicValue.DOUBLE_VALUE;
084                }
085            }
086    
087            return super.newOperation(insn);
088        }
089    
090        @NotNull
091        @Override
092        public BasicValue merge(
093                @NotNull BasicValue v, @NotNull BasicValue w
094        ) {
095            if (!v.equals(w)) {
096                return MIXED_VALUE;
097            }
098            return v;
099        }
100    }