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.ssa;
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
19fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport com.android.dx.rop.code.Insn;
20fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport com.android.dx.rop.code.LocalItem;
21fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport com.android.dx.rop.code.RegisterSpec;
22fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport com.android.dx.rop.code.RegisterSpecList;
23fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport com.android.dx.rop.code.Rop;
24fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport com.android.dx.rop.code.SourcePosition;
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.Type;
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.TypeBearer;
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.Hex;
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.ArrayList;
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.List;
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * A Phi instruction (magical post-control-flow-merge) instruction
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in SSA form. Will be converted to moves in predecessor blocks before
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * conversion back to ROP form.
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic final class PhiInsn extends SsaInsn {
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
3899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * result register. The original result register of the phi insn
3999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * is needed during the renaming process after the new result
4099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * register has already been chosen.
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
4299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    private final int ropResultReg;
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
4599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code non-null;} operands of the instruction; built up by
4699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@link #addPhiOperand}
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
4899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    private final ArrayList<Operand> operands = new ArrayList<Operand>();
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code null-ok;} source registers; constructed lazily */
5199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    private RegisterSpecList sources;
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs a new phi insn with no operands.
55de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param resultReg the result reg for this phi insn
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param block block containing this insn.
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
5999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    public PhiInsn(RegisterSpec resultReg, SsaBasicBlock block) {
6099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        super(resultReg, block);
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ropResultReg = resultReg.getReg();
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Makes a phi insn with a void result type.
66de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param resultReg the result register for this phi insn.
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param block block containing this insn.
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
7099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    public PhiInsn(final int resultReg, final SsaBasicBlock block) {
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
7299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * The result type here is bogus: The type depends on the
7399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * operand and will be derived later.
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
7599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        super(RegisterSpec.make(resultReg, Type.VOID), block);
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ropResultReg = resultReg;
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
7999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@inheritDoc} */
80b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao    @Override
8199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    public PhiInsn clone() {
8299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        throw new UnsupportedOperationException("can't clone phi");
8399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    }
8499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Updates the TypeBearers of all the sources (phi operands) to be
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the current TypeBearer of the register-defining instruction's result.
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * This is used during phi-type resolution.<p>
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Note that local association of operands are preserved in this step.
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param ssaMeth method that contains this insn
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
9499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    public void updateSourcesToDefinitions(SsaMethod ssaMeth) {
9599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        for (Operand o : operands) {
96de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro            RegisterSpec def
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                = ssaMeth.getDefinitionForRegister(
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    o.regSpec.getReg()).getResult();
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            o.regSpec = o.regSpec.withType(def.getType());
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sources = null;
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Changes the result type. Used during phi type resolution
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
10999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param type {@code non-null;} new TypeBearer
11099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param local {@code null-ok;} new local info, if available
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
11299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    public void changeResultType(TypeBearer type, LocalItem local) {
11399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        setResult(RegisterSpec.makeLocalOptional(
11499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project                          getResult().getReg(), type, local));
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
11899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Gets the original rop-form result reg. This is useful during renaming.
119de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
12099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return the original rop-form result reg
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
12299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    public int getRopResultReg() {
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return ropResultReg;
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
12799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Adds an operand to this phi instruction.
128de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param registerSpec register spec, including type and reg of operand
13099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param predBlock predecessor block to be associated with this operand
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void addPhiOperand(RegisterSpec registerSpec,
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            SsaBasicBlock predBlock) {
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        operands.add(new Operand(registerSpec, predBlock.getIndex(),
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                predBlock.getRopLabel()));
136de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
13799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        // Un-cache sources, in case someone has already called getSources().
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sources = null;
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
142b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao     * Removes all operand uses of a register from this phi instruction.
143b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao     *
144b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao     * @param registerSpec register spec, including type and reg of operand
145b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao     */
146b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao    public void removePhiRegister(RegisterSpec registerSpec) {
147b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao        ArrayList<Operand> operandsToRemove = new ArrayList<Operand>();
148b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao        for (Operand o : operands) {
149b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao            if (o.regSpec.getReg() == registerSpec.getReg()) {
150b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao                operandsToRemove.add(o);
151b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao            }
152b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao        }
153b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao
154b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao        operands.removeAll(operandsToRemove);
155b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao
156b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao        // Un-cache sources, in case someone has already called getSources().
157b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao        sources = null;
158b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao    }
159b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao
160b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao    /**
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the index of the pred block associated with the RegisterSpec
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * at the particular getSources() index.
163de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param sourcesIndex index of source in getSources()
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return block index
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int predBlockIndexForSourcesIndex(int sourcesIndex) {
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return operands.get(sourcesIndex).blockIndex;
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * {@inheritDoc}
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
17499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Always returns null for {@code PhiInsn}s.
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Rop getOpcode() {
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return null;
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * {@inheritDoc}
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
18499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Always returns null for {@code PhiInsn}s.
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Insn getOriginalRopInsn() {
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return null;
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * {@inheritDoc}
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
19499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Always returns false for {@code PhiInsn}s.
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public boolean canThrow() {
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets sources. Constructed lazily from phi operand data structures and
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * then cached.
204de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
20599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} sources list
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
207b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao    @Override
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public RegisterSpecList getSources() {
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (sources != null) {
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return sources;
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (operands.size() == 0) {
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // How'd this happen? A phi insn with no operand?
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return RegisterSpecList.EMPTY;
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int szSources = operands.size();
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sources = new RegisterSpecList(szSources);
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i < szSources; i++) {
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Operand o = operands.get(i);
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sources.set(i, o.regSpec);
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sources.setImmutable();
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return sources;
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public boolean isRegASource(int reg) {
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Avoid creating a sources list in case it has not already been
23699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * created.
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
23999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        for (Operand o : operands) {
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (o.regSpec.getReg() == reg) {
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return true;
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return true if all operands use the same register
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public boolean areAllOperandsEqual() {
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (operands.size() == 0 ) {
25399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            // This should never happen.
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return true;
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int firstReg = operands.get(0).regSpec.getReg();
25899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        for (Operand o : operands) {
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (firstReg != o.regSpec.getReg()) {
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return false;
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return true;
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final void mapSourceRegisters(RegisterMapper mapper) {
27099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        for (Operand o : operands) {
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegisterSpec old = o.regSpec;
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            o.regSpec = mapper.map(old);
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (old != o.regSpec) {
27499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project                getBlock().getParent().onSourceChanged(this, old, o.regSpec);
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sources = null;
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
28199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Always throws an exeption, since a phi insn may not be
28299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * converted back to rop form.
283de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return always throws exception
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Insn toRopInsn() {
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        throw new IllegalArgumentException(
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "Cannot convert phi insns to rop form");
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the list of predecessor blocks associated with all operands
29499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * that have {@code reg} as an operand register.
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param reg register to look up
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param ssaMeth method we're operating on
29899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return list of predecessor blocks, empty if none
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
30099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    public List<SsaBasicBlock> predBlocksForReg(int reg, SsaMethod ssaMeth) {
30199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        ArrayList<SsaBasicBlock> ret = new ArrayList<SsaBasicBlock>();
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
30399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        for (Operand o : operands) {
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (o.regSpec.getReg() == reg) {
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ret.add(ssaMeth.getBlocks().get(o.blockIndex));
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return ret;
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
31499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    public boolean isPhiOrMove() {
315de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro        return true;
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
31999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    @Override
32099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    public boolean hasSideEffect() {
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return Optimizer.getPreserveLocals() && getLocalAssignment() != null;
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void accept(SsaInsn.Visitor v) {
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        v.visitPhiInsn(this);
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
33099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@inheritDoc} */
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public String toHuman() {
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return toHumanWithInline(null);
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
33699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Returns human-readable string for listing dumps. This method
33799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * allows sub-classes to specify extra text.
338de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
33999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param extra {@code null-ok;} the argument to print after the opcode
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return human-readable string for listing dumps
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected final String toHumanWithInline(String extra) {
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StringBuffer sb = new StringBuffer(80);
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sb.append(SourcePosition.NO_INFO);
346de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro        sb.append(": phi");
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (extra != null) {
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append("(");
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(extra);
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(")");
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
35499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        RegisterSpec result = getResult();
355de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (result == null) {
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(" .");
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(" ");
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(result.toHuman());
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sb.append(" <-");
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int sz = getSources().size();
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (sz == 0) {
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(" .");
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (int i = 0; i < sz; i++) {
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sb.append(" ");
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sb.append(sources.get(i).toHuman()
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        + "[b="
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        + Hex.u2(operands.get(i).ropLabel)  + "]");
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return sb.toString();
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
37999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
38099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /**
38199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * A single phi operand, consiting of source register and block index
38299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * for move.
38399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     */
38499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    private static class Operand {
38599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        public RegisterSpec regSpec;
38699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        public final int blockIndex;
38799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        public final int ropLabel;       // only used for debugging
38899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
3894b4413ab3d8de5805276cfcde3d7f535d9f64e85Dan Bornstein        public Operand(RegisterSpec regSpec, int blockIndex, int ropLabel) {
39099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            this.regSpec = regSpec;
39199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            this.blockIndex = blockIndex;
39299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            this.ropLabel = ropLabel;
39399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        }
39499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    }
39599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
39699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /**
39799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Visitor interface for instances of this (outer) class.
39899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     */
39999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    public static interface Visitor {
40099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        public void visitPhiInsn(PhiInsn insn);
40199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    }
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
403