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