1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage com.android.dx.rop.code;
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
19fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport com.android.dx.rop.cst.Constant;
20fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport com.android.dx.rop.cst.CstInteger;
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.StdTypeList;
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.Type;
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.TypeBearer;
24fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport com.android.dx.rop.type.TypeList;
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Plain instruction, which has no embedded data and which cannot possibly
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * throw an exception.
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic final class PlainInsn
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        extends Insn {
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs an instance.
34de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
3599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param opcode {@code non-null;} the opcode
3699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param position {@code non-null;} source position
3799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param result {@code null-ok;} spec for the result, if any
3899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param sources {@code non-null;} specs for all the sources
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public PlainInsn(Rop opcode, SourcePosition position,
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     RegisterSpec result, RegisterSpecList sources) {
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        super(opcode, position, result, sources);
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (opcode.getBranchingness()) {
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case Rop.BRANCH_SWITCH:
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case Rop.BRANCH_THROW: {
47cdef1ee858fde291205f3da685b2720227d2d42fOrion Hodson                throw new IllegalArgumentException("opcode with invalid branchingness: " + opcode.getBranchingness());
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (result != null && opcode.getBranchingness() != Rop.BRANCH_NONE) {
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // move-result-pseudo is required here
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException
54de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro                    ("can't mix branchingness with result");
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs a single-source instance.
60de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
6199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param opcode {@code non-null;} the opcode
6299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param position {@code non-null;} source position
6399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param result {@code null-ok;} spec for the result, if any
6499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param source {@code non-null;} spec for the source
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public PlainInsn(Rop opcode, SourcePosition position, RegisterSpec result,
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     RegisterSpec source) {
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this(opcode, position, result, RegisterSpecList.make(source));
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public TypeList getCatches() {
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return StdTypeList.EMPTY;
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void accept(Visitor visitor) {
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        visitor.visitPlainInsn(this);
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Insn withAddedCatch(Type type) {
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        throw new UnsupportedOperationException("unsupported");
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Insn withRegisterOffset(int delta) {
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return new PlainInsn(getOpcode(), getPosition(),
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                             getResult().withOffset(delta),
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                             getSources().withOffset(delta));
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
991800713d172abd729e4eea04b1bf2110d4e5fd1ajeffhao    public Insn withSourceLiteral() {
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        RegisterSpecList sources = getSources();
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int szSources = sources.size();
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (szSources == 0) {
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return this;
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        TypeBearer lastType = sources.get(szSources - 1).getTypeBearer();
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!lastType.isConstant()) {
110224fa21f414340325cb5e33897177aef9eb5069fjeffhao            // Check for reverse subtraction, where first source is constant
111224fa21f414340325cb5e33897177aef9eb5069fjeffhao            TypeBearer firstType = sources.get(0).getTypeBearer();
112224fa21f414340325cb5e33897177aef9eb5069fjeffhao            if (szSources == 2 && firstType.isConstant()) {
113224fa21f414340325cb5e33897177aef9eb5069fjeffhao                Constant cst = (Constant) firstType;
114224fa21f414340325cb5e33897177aef9eb5069fjeffhao                RegisterSpecList newSources = sources.withoutFirst();
115224fa21f414340325cb5e33897177aef9eb5069fjeffhao                Rop newRop = Rops.ropFor(getOpcode().getOpcode(), getResult(),
116224fa21f414340325cb5e33897177aef9eb5069fjeffhao                                             newSources, cst);
117224fa21f414340325cb5e33897177aef9eb5069fjeffhao                return new PlainCstInsn(newRop, getPosition(), getResult(),
118224fa21f414340325cb5e33897177aef9eb5069fjeffhao                                            newSources, cst);
1191800713d172abd729e4eea04b1bf2110d4e5fd1ajeffhao            }
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return this;
121224fa21f414340325cb5e33897177aef9eb5069fjeffhao        } else {
122224fa21f414340325cb5e33897177aef9eb5069fjeffhao
123224fa21f414340325cb5e33897177aef9eb5069fjeffhao            Constant cst = (Constant) lastType;
124224fa21f414340325cb5e33897177aef9eb5069fjeffhao
125224fa21f414340325cb5e33897177aef9eb5069fjeffhao            RegisterSpecList newSources = sources.withoutLast();
126224fa21f414340325cb5e33897177aef9eb5069fjeffhao
127224fa21f414340325cb5e33897177aef9eb5069fjeffhao            Rop newRop;
128224fa21f414340325cb5e33897177aef9eb5069fjeffhao            try {
129224fa21f414340325cb5e33897177aef9eb5069fjeffhao                // Check for constant subtraction and flip it to be addition
130224fa21f414340325cb5e33897177aef9eb5069fjeffhao                int opcode = getOpcode().getOpcode();
131224fa21f414340325cb5e33897177aef9eb5069fjeffhao                if (opcode == RegOps.SUB && cst instanceof CstInteger) {
132224fa21f414340325cb5e33897177aef9eb5069fjeffhao                    opcode = RegOps.ADD;
133224fa21f414340325cb5e33897177aef9eb5069fjeffhao                    cst = CstInteger.make(-((CstInteger)cst).getValue());
134224fa21f414340325cb5e33897177aef9eb5069fjeffhao                }
135224fa21f414340325cb5e33897177aef9eb5069fjeffhao                newRop = Rops.ropFor(opcode, getResult(), newSources, cst);
136224fa21f414340325cb5e33897177aef9eb5069fjeffhao            } catch (IllegalArgumentException ex) {
137224fa21f414340325cb5e33897177aef9eb5069fjeffhao                // There's no rop for this case
138224fa21f414340325cb5e33897177aef9eb5069fjeffhao                return this;
139224fa21f414340325cb5e33897177aef9eb5069fjeffhao            }
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
141224fa21f414340325cb5e33897177aef9eb5069fjeffhao            return new PlainCstInsn(newRop, getPosition(),
142224fa21f414340325cb5e33897177aef9eb5069fjeffhao                    getResult(), newSources, cst);
143224fa21f414340325cb5e33897177aef9eb5069fjeffhao        }
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Insn withNewRegisters(RegisterSpec result,
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegisterSpecList sources) {
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return new PlainInsn(getOpcode(), getPosition(),
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                             result,
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                             sources);
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
158