LIRInstruction.java revision 13160:721637c92e1e
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.StandardOp.LoadConstantOp;
51import org.graalvm.compiler.lir.StandardOp.MoveOp;
52import org.graalvm.compiler.lir.StandardOp.ValueMoveOp;
53import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
54import org.graalvm.compiler.lir.gen.LIRGenerationResult;
55
56import jdk.vm.ci.code.RegisterValue;
57import jdk.vm.ci.code.StackSlot;
58import jdk.vm.ci.meta.JavaConstant;
59import jdk.vm.ci.meta.Value;
60
61/**
62 * The base class for an {@code LIRInstruction}.
63 */
64public abstract class LIRInstruction {
65    /**
66     * Constants denoting how a LIR instruction uses an operand.
67     */
68    public enum OperandMode {
69        /**
70         * The value must have been defined before. It is alive before the instruction until the
71         * beginning of the instruction, but not necessarily throughout the instruction. A register
72         * assigned to it can also be assigned to a {@link #TEMP} or {@link #DEF} operand. The value
73         * can be used again after the instruction, so the instruction must not modify the register.
74         */
75        USE,
76
77        /**
78         * The value must have been defined before. It is alive before the instruction and
79         * throughout the instruction. A register assigned to it cannot be assigned to a
80         * {@link #TEMP} or {@link #DEF} operand. The value can be used again after the instruction,
81         * so the instruction must not modify the register.
82         */
83        ALIVE,
84
85        /**
86         * The value must not have been defined before, and must not be used after the instruction.
87         * The instruction can do whatever it wants with the register assigned to it (or not use it
88         * at all).
89         */
90        TEMP,
91
92        /**
93         * The value must not have been defined before. The instruction has to assign a value to the
94         * register. The value can (and most likely will) be used after the instruction.
95         */
96        DEF,
97    }
98
99    @Retention(RetentionPolicy.RUNTIME)
100    @Target(ElementType.FIELD)
101    public static @interface Use {
102
103        OperandFlag[] value() default OperandFlag.REG;
104    }
105
106    @Retention(RetentionPolicy.RUNTIME)
107    @Target(ElementType.FIELD)
108    public static @interface Alive {
109
110        OperandFlag[] value() default OperandFlag.REG;
111    }
112
113    @Retention(RetentionPolicy.RUNTIME)
114    @Target(ElementType.FIELD)
115    public static @interface Temp {
116
117        OperandFlag[] value() default OperandFlag.REG;
118    }
119
120    @Retention(RetentionPolicy.RUNTIME)
121    @Target(ElementType.FIELD)
122    public static @interface Def {
123
124        OperandFlag[] value() default OperandFlag.REG;
125    }
126
127    @Retention(RetentionPolicy.RUNTIME)
128    @Target(ElementType.FIELD)
129    public static @interface State {
130    }
131
132    /**
133     * Flags for an operand.
134     */
135    public enum OperandFlag {
136        /**
137         * The value can be a {@link RegisterValue}.
138         */
139        REG,
140
141        /**
142         * The value can be a {@link StackSlot}.
143         */
144        STACK,
145
146        /**
147         * The value can be a {@link CompositeValue}.
148         */
149        COMPOSITE,
150
151        /**
152         * The value can be a {@link JavaConstant}.
153         */
154        CONST,
155
156        /**
157         * The value can be {@link Value#ILLEGAL}.
158         */
159        ILLEGAL,
160
161        /**
162         * The register allocator should try to assign a certain register to improve code quality.
163         * Use {@link LIRInstruction#forEachRegisterHint} to access the register hints.
164         */
165        HINT,
166
167        /**
168         * The value can be uninitialized, e.g., a stack slot that has not written to before. This
169         * is only used to avoid false positives in verification code.
170         */
171        UNINITIALIZED,
172
173        /** Outgoing block value. */
174        OUTGOING,
175    }
176
177    /**
178     * For validity checking of the operand flags defined by instruction subclasses.
179     */
180    protected static final EnumMap<OperandMode, EnumSet<OperandFlag>> ALLOWED_FLAGS;
181
182    static {
183        ALLOWED_FLAGS = new EnumMap<>(OperandMode.class);
184        ALLOWED_FLAGS.put(OperandMode.USE, EnumSet.of(REG, STACK, COMPOSITE, CONST, ILLEGAL, HINT, UNINITIALIZED));
185        ALLOWED_FLAGS.put(ALIVE, EnumSet.of(REG, STACK, COMPOSITE, CONST, ILLEGAL, HINT, UNINITIALIZED, OUTGOING));
186        ALLOWED_FLAGS.put(TEMP, EnumSet.of(REG, STACK, COMPOSITE, ILLEGAL, HINT));
187        ALLOWED_FLAGS.put(DEF, EnumSet.of(REG, STACK, COMPOSITE, ILLEGAL, HINT));
188    }
189
190    /**
191     * The flags of the base and index value of an address.
192     */
193    protected static final EnumSet<OperandFlag> ADDRESS_FLAGS = EnumSet.of(REG, ILLEGAL);
194
195    private final LIRInstructionClass<?> instructionClass;
196
197    /**
198     * Instruction id for register allocation.
199     */
200    private int id;
201
202    /**
203     * The source position of the code that generated this instruction.
204     */
205    private NodeSourcePosition position;
206
207    private static final DebugCounter LIR_NODE_COUNT = Debug.counter("LIRNodes");
208
209    /**
210     * Constructs a new LIR instruction.
211     */
212    public LIRInstruction(LIRInstructionClass<? extends LIRInstruction> c) {
213        LIR_NODE_COUNT.increment();
214        instructionClass = c;
215        assert c.getClazz() == this.getClass();
216        id = -1;
217    }
218
219    public abstract void emitCode(CompilationResultBuilder crb);
220
221    public final int id() {
222        return id;
223    }
224
225    public final void setId(int id) {
226        this.id = id;
227    }
228
229    public final NodeSourcePosition getPosition() {
230        return position;
231    }
232
233    public final void setPosition(NodeSourcePosition position) {
234        this.position = position;
235    }
236
237    public final String name() {
238        return instructionClass.getOpcode(this);
239    }
240
241    public final boolean hasOperands() {
242        return instructionClass.hasOperands() || hasState() || destroysCallerSavedRegisters();
243    }
244
245    public final boolean hasState() {
246        return instructionClass.hasState(this);
247    }
248
249    public boolean destroysCallerSavedRegisters() {
250        return false;
251    }
252
253    // InstructionValueProcedures
254    public final void forEachInput(InstructionValueProcedure proc) {
255        instructionClass.forEachUse(this, proc);
256    }
257
258    public final void forEachAlive(InstructionValueProcedure proc) {
259        instructionClass.forEachAlive(this, proc);
260    }
261
262    public final void forEachTemp(InstructionValueProcedure proc) {
263        instructionClass.forEachTemp(this, proc);
264    }
265
266    public final void forEachOutput(InstructionValueProcedure proc) {
267        instructionClass.forEachDef(this, proc);
268    }
269
270    public final void forEachState(InstructionValueProcedure proc) {
271        instructionClass.forEachState(this, proc);
272    }
273
274    // ValueProcedures
275    public final void forEachInput(ValueProcedure proc) {
276        instructionClass.forEachUse(this, proc);
277    }
278
279    public final void forEachAlive(ValueProcedure proc) {
280        instructionClass.forEachAlive(this, proc);
281    }
282
283    public final void forEachTemp(ValueProcedure proc) {
284        instructionClass.forEachTemp(this, proc);
285    }
286
287    public final void forEachOutput(ValueProcedure proc) {
288        instructionClass.forEachDef(this, proc);
289    }
290
291    public final void forEachState(ValueProcedure proc) {
292        instructionClass.forEachState(this, proc);
293    }
294
295    // States
296    public final void forEachState(InstructionStateProcedure proc) {
297        instructionClass.forEachState(this, proc);
298    }
299
300    public final void forEachState(StateProcedure proc) {
301        instructionClass.forEachState(this, proc);
302    }
303
304    // InstructionValueConsumers
305    public final void visitEachInput(InstructionValueConsumer proc) {
306        instructionClass.visitEachUse(this, proc);
307    }
308
309    public final void visitEachAlive(InstructionValueConsumer proc) {
310        instructionClass.visitEachAlive(this, proc);
311    }
312
313    public final void visitEachTemp(InstructionValueConsumer proc) {
314        instructionClass.visitEachTemp(this, proc);
315    }
316
317    public final void visitEachOutput(InstructionValueConsumer proc) {
318        instructionClass.visitEachDef(this, proc);
319    }
320
321    public final void visitEachState(InstructionValueConsumer proc) {
322        instructionClass.visitEachState(this, proc);
323    }
324
325    // ValueConsumers
326    public final void visitEachInput(ValueConsumer proc) {
327        instructionClass.visitEachUse(this, proc);
328    }
329
330    public final void visitEachAlive(ValueConsumer proc) {
331        instructionClass.visitEachAlive(this, proc);
332    }
333
334    public final void visitEachTemp(ValueConsumer proc) {
335        instructionClass.visitEachTemp(this, proc);
336    }
337
338    public final void visitEachOutput(ValueConsumer proc) {
339        instructionClass.visitEachDef(this, proc);
340    }
341
342    public final void visitEachState(ValueConsumer proc) {
343        instructionClass.visitEachState(this, proc);
344    }
345
346    @SuppressWarnings("unused")
347    public final Value forEachRegisterHint(Value value, OperandMode mode, InstructionValueProcedure proc) {
348        return instructionClass.forEachRegisterHint(this, mode, proc);
349    }
350
351    @SuppressWarnings("unused")
352    public final Value forEachRegisterHint(Value value, OperandMode mode, ValueProcedure proc) {
353        return instructionClass.forEachRegisterHint(this, mode, proc);
354    }
355
356    // Checkstyle: stop
357    /**
358     * Returns {@code true} if the instruction is a {@link MoveOp}.
359     *
360     * This function is preferred to {@code instanceof MoveOp} since the type check is more
361     * expensive than reading a field from {@link LIRInstructionClass}.
362     */
363    public final boolean isMoveOp() {
364        return instructionClass.isMoveOp();
365    }
366
367    /**
368     * Returns {@code true} if the instruction is a {@link ValueMoveOp}.
369     *
370     * This function is preferred to {@code instanceof ValueMoveOp} since the type check is more
371     * expensive than reading a field from {@link LIRInstructionClass}.
372     */
373    public final boolean isValueMoveOp() {
374        return instructionClass.isValueMoveOp();
375    }
376
377    /**
378     * Returns {@code true} if the instruction is a {@link LoadConstantOp}.
379     *
380     * This function is preferred to {@code instanceof LoadConstantOp} since the type check is more
381     * expensive than reading a field from {@link LIRInstructionClass}.
382     */
383    public final boolean isLoadConstantOp() {
384        return instructionClass.isLoadConstantOp();
385    }
386    // Checkstyle: resume
387
388    /**
389     * Utility method to add stack arguments to a list of temporaries. Useful for modeling calling
390     * conventions that kill outgoing argument space.
391     *
392     * @return additional temporaries
393     */
394    protected static Value[] addStackSlotsToTemporaries(Value[] parameters, Value[] temporaries) {
395        int extraTemps = 0;
396        for (Value p : parameters) {
397            if (isStackSlot(p)) {
398                extraTemps++;
399            }
400            assert !isVirtualStackSlot(p) : "only real stack slots in calling convention";
401        }
402        if (extraTemps != 0) {
403            int index = temporaries.length;
404            Value[] newTemporaries = Arrays.copyOf(temporaries, temporaries.length + extraTemps);
405            for (Value p : parameters) {
406                if (isStackSlot(p)) {
407                    newTemporaries[index++] = p;
408                }
409            }
410            return newTemporaries;
411        }
412        return temporaries;
413    }
414
415    public void verify() {
416    }
417
418    /**
419     * Adds a comment to this instruction.
420     */
421    public final void setComment(LIRGenerationResult res, String comment) {
422        res.setComment(this, comment);
423    }
424
425    /**
426     * Gets the comment attached to this instruction.
427     */
428    public final String getComment(LIRGenerationResult res) {
429        return res.getComment(this);
430    }
431
432    public final String toStringWithIdPrefix() {
433        if (id != -1) {
434            return String.format("%4d %s", id, toString());
435        }
436        return "     " + toString();
437    }
438
439    @Override
440    public String toString() {
441        return instructionClass.toString(this);
442    }
443
444    public String toString(LIRGenerationResult res) {
445        String toString = toString();
446        if (res == null) {
447            return toString;
448        }
449        String comment = getComment(res);
450        if (comment == null) {
451            return toString;
452        }
453        return String.format("%s // %s", toString, comment);
454    }
455
456    public LIRInstructionClass<?> getLIRInstructionClass() {
457        return instructionClass;
458    }
459
460    @Override
461    public int hashCode() {
462        return id;
463    }
464}
465