1/*
2 * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23package org.graalvm.compiler.lir;
24
25import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.COMPOSITE;
26import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.CONST;
27import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT;
28import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL;
29import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.OUTGOING;
30import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
31import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
32import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.UNINITIALIZED;
33import static org.graalvm.compiler.lir.LIRInstruction.OperandMode.ALIVE;
34import static org.graalvm.compiler.lir.LIRInstruction.OperandMode.DEF;
35import static org.graalvm.compiler.lir.LIRInstruction.OperandMode.TEMP;
36import static org.graalvm.compiler.lir.LIRValueUtil.isVirtualStackSlot;
37import static jdk.vm.ci.code.ValueUtil.isStackSlot;
38
39import java.lang.annotation.ElementType;
40import java.lang.annotation.Retention;
41import java.lang.annotation.RetentionPolicy;
42import java.lang.annotation.Target;
43import java.util.Arrays;
44import java.util.EnumMap;
45import java.util.EnumSet;
46
47import org.graalvm.compiler.debug.Debug;
48import org.graalvm.compiler.debug.DebugCounter;
49import org.graalvm.compiler.graph.NodeSourcePosition;
50import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
51
52import jdk.vm.ci.code.RegisterValue;
53import jdk.vm.ci.code.StackSlot;
54import jdk.vm.ci.meta.JavaConstant;
55import jdk.vm.ci.meta.Value;
56
57/**
58 * The base class for an {@code LIRInstruction}.
59 */
60public abstract class LIRInstruction {
61    /**
62     * Constants denoting how a LIR instruction uses an operand.
63     */
64    public enum OperandMode {
65        /**
66         * The value must have been defined before. It is alive before the instruction until the
67         * beginning of the instruction, but not necessarily throughout the instruction. A register
68         * assigned to it can also be assigned to a {@link #TEMP} or {@link #DEF} operand. The value
69         * can be used again after the instruction, so the instruction must not modify the register.
70         */
71        USE,
72
73        /**
74         * The value must have been defined before. It is alive before the instruction and
75         * throughout the instruction. A register assigned to it cannot be assigned to a
76         * {@link #TEMP} or {@link #DEF} operand. The value can be used again after the instruction,
77         * so the instruction must not modify the register.
78         */
79        ALIVE,
80
81        /**
82         * The value must not have been defined before, and must not be used after the instruction.
83         * The instruction can do whatever it wants with the register assigned to it (or not use it
84         * at all).
85         */
86        TEMP,
87
88        /**
89         * The value must not have been defined before. The instruction has to assign a value to the
90         * register. The value can (and most likely will) be used after the instruction.
91         */
92        DEF,
93    }
94
95    @Retention(RetentionPolicy.RUNTIME)
96    @Target(ElementType.FIELD)
97    public static @interface Use {
98
99        OperandFlag[] value() default OperandFlag.REG;
100    }
101
102    @Retention(RetentionPolicy.RUNTIME)
103    @Target(ElementType.FIELD)
104    public static @interface Alive {
105
106        OperandFlag[] value() default OperandFlag.REG;
107    }
108
109    @Retention(RetentionPolicy.RUNTIME)
110    @Target(ElementType.FIELD)
111    public static @interface Temp {
112
113        OperandFlag[] value() default OperandFlag.REG;
114    }
115
116    @Retention(RetentionPolicy.RUNTIME)
117    @Target(ElementType.FIELD)
118    public static @interface Def {
119
120        OperandFlag[] value() default OperandFlag.REG;
121    }
122
123    @Retention(RetentionPolicy.RUNTIME)
124    @Target(ElementType.FIELD)
125    public static @interface State {
126    }
127
128    /**
129     * Flags for an operand.
130     */
131    public enum OperandFlag {
132        /**
133         * The value can be a {@link RegisterValue}.
134         */
135        REG,
136
137        /**
138         * The value can be a {@link StackSlot}.
139         */
140        STACK,
141
142        /**
143         * The value can be a {@link CompositeValue}.
144         */
145        COMPOSITE,
146
147        /**
148         * The value can be a {@link JavaConstant}.
149         */
150        CONST,
151
152        /**
153         * The value can be {@link Value#ILLEGAL}.
154         */
155        ILLEGAL,
156
157        /**
158         * The register allocator should try to assign a certain register to improve code quality.
159         * Use {@link LIRInstruction#forEachRegisterHint} to access the register hints.
160         */
161        HINT,
162
163        /**
164         * The value can be uninitialized, e.g., a stack slot that has not written to before. This
165         * is only used to avoid false positives in verification code.
166         */
167        UNINITIALIZED,
168
169        /** Outgoing block value. */
170        OUTGOING,
171    }
172
173    /**
174     * For validity checking of the operand flags defined by instruction subclasses.
175     */
176    protected static final EnumMap<OperandMode, EnumSet<OperandFlag>> ALLOWED_FLAGS;
177
178    static {
179        ALLOWED_FLAGS = new EnumMap<>(OperandMode.class);
180        ALLOWED_FLAGS.put(OperandMode.USE, EnumSet.of(REG, STACK, COMPOSITE, CONST, ILLEGAL, HINT, UNINITIALIZED));
181        ALLOWED_FLAGS.put(ALIVE, EnumSet.of(REG, STACK, COMPOSITE, CONST, ILLEGAL, HINT, UNINITIALIZED, OUTGOING));
182        ALLOWED_FLAGS.put(TEMP, EnumSet.of(REG, STACK, COMPOSITE, ILLEGAL, HINT));
183        ALLOWED_FLAGS.put(DEF, EnumSet.of(REG, STACK, COMPOSITE, ILLEGAL, HINT));
184    }
185
186    /**
187     * The flags of the base and index value of an address.
188     */
189    protected static final EnumSet<OperandFlag> ADDRESS_FLAGS = EnumSet.of(REG, ILLEGAL);
190
191    private final LIRInstructionClass<?> instructionClass;
192
193    /**
194     * Instruction id for register allocation.
195     */
196    private int id;
197
198    /**
199     * The source position of the code that generated this instruction.
200     */
201    private NodeSourcePosition position;
202
203    private static final DebugCounter LIR_NODE_COUNT = Debug.counter("LIRNodes");
204
205    /**
206     * Constructs a new LIR instruction.
207     */
208    public LIRInstruction(LIRInstructionClass<? extends LIRInstruction> c) {
209        LIR_NODE_COUNT.increment();
210        instructionClass = c;
211        assert c.getClazz() == this.getClass();
212        id = -1;
213    }
214
215    public abstract void emitCode(CompilationResultBuilder crb);
216
217    public final int id() {
218        return id;
219    }
220
221    public final void setId(int id) {
222        this.id = id;
223    }
224
225    public final NodeSourcePosition getPosition() {
226        return position;
227    }
228
229    public final void setPosition(NodeSourcePosition position) {
230        this.position = position;
231    }
232
233    public final String name() {
234        return instructionClass.getOpcode(this);
235    }
236
237    public final boolean hasOperands() {
238        return instructionClass.hasOperands() || hasState() || destroysCallerSavedRegisters();
239    }
240
241    public final boolean hasState() {
242        return instructionClass.hasState(this);
243    }
244
245    public boolean destroysCallerSavedRegisters() {
246        return false;
247    }
248
249    // InstructionValueProcedures
250    public final void forEachInput(InstructionValueProcedure proc) {
251        instructionClass.forEachUse(this, proc);
252    }
253
254    public final void forEachAlive(InstructionValueProcedure proc) {
255        instructionClass.forEachAlive(this, proc);
256    }
257
258    public final void forEachTemp(InstructionValueProcedure proc) {
259        instructionClass.forEachTemp(this, proc);
260    }
261
262    public final void forEachOutput(InstructionValueProcedure proc) {
263        instructionClass.forEachDef(this, proc);
264    }
265
266    public final void forEachState(InstructionValueProcedure proc) {
267        instructionClass.forEachState(this, proc);
268    }
269
270    // ValueProcedures
271    public final void forEachInput(ValueProcedure proc) {
272        instructionClass.forEachUse(this, proc);
273    }
274
275    public final void forEachAlive(ValueProcedure proc) {
276        instructionClass.forEachAlive(this, proc);
277    }
278
279    public final void forEachTemp(ValueProcedure proc) {
280        instructionClass.forEachTemp(this, proc);
281    }
282
283    public final void forEachOutput(ValueProcedure proc) {
284        instructionClass.forEachDef(this, proc);
285    }
286
287    public final void forEachState(ValueProcedure proc) {
288        instructionClass.forEachState(this, proc);
289    }
290
291    // States
292    public final void forEachState(InstructionStateProcedure proc) {
293        instructionClass.forEachState(this, proc);
294    }
295
296    public final void forEachState(StateProcedure proc) {
297        instructionClass.forEachState(this, proc);
298    }
299
300    // InstructionValueConsumers
301    public final void visitEachInput(InstructionValueConsumer proc) {
302        instructionClass.visitEachUse(this, proc);
303    }
304
305    public final void visitEachAlive(InstructionValueConsumer proc) {
306        instructionClass.visitEachAlive(this, proc);
307    }
308
309    public final void visitEachTemp(InstructionValueConsumer proc) {
310        instructionClass.visitEachTemp(this, proc);
311    }
312
313    public final void visitEachOutput(InstructionValueConsumer proc) {
314        instructionClass.visitEachDef(this, proc);
315    }
316
317    public final void visitEachState(InstructionValueConsumer proc) {
318        instructionClass.visitEachState(this, proc);
319    }
320
321    // ValueConsumers
322    public final void visitEachInput(ValueConsumer proc) {
323        instructionClass.visitEachUse(this, proc);
324    }
325
326    public final void visitEachAlive(ValueConsumer proc) {
327        instructionClass.visitEachAlive(this, proc);
328    }
329
330    public final void visitEachTemp(ValueConsumer proc) {
331        instructionClass.visitEachTemp(this, proc);
332    }
333
334    public final void visitEachOutput(ValueConsumer proc) {
335        instructionClass.visitEachDef(this, proc);
336    }
337
338    public final void visitEachState(ValueConsumer proc) {
339        instructionClass.visitEachState(this, proc);
340    }
341
342    @SuppressWarnings("unused")
343    public final Value forEachRegisterHint(Value value, OperandMode mode, InstructionValueProcedure proc) {
344        return instructionClass.forEachRegisterHint(this, mode, proc);
345    }
346
347    @SuppressWarnings("unused")
348    public final Value forEachRegisterHint(Value value, OperandMode mode, ValueProcedure proc) {
349        return instructionClass.forEachRegisterHint(this, mode, proc);
350    }
351
352    /**
353     * Utility method to add stack arguments to a list of temporaries. Useful for modeling calling
354     * conventions that kill outgoing argument space.
355     *
356     * @return additional temporaries
357     */
358    protected static Value[] addStackSlotsToTemporaries(Value[] parameters, Value[] temporaries) {
359        int extraTemps = 0;
360        for (Value p : parameters) {
361            if (isStackSlot(p)) {
362                extraTemps++;
363            }
364            assert !isVirtualStackSlot(p) : "only real stack slots in calling convention";
365        }
366        if (extraTemps != 0) {
367            int index = temporaries.length;
368            Value[] newTemporaries = Arrays.copyOf(temporaries, temporaries.length + extraTemps);
369            for (Value p : parameters) {
370                if (isStackSlot(p)) {
371                    newTemporaries[index++] = p;
372                }
373            }
374            return newTemporaries;
375        }
376        return temporaries;
377    }
378
379    public void verify() {
380    }
381
382    public final String toStringWithIdPrefix() {
383        if (id != -1) {
384            return String.format("%4d %s", id, toString());
385        }
386        return "     " + toString();
387    }
388
389    @Override
390    public String toString() {
391        return instructionClass.toString(this);
392    }
393
394    public LIRInstructionClass<?> getLIRInstructionClass() {
395        return instructionClass;
396    }
397}
398