001/*
002 * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.
008 *
009 * This code is distributed in the hope that it will be useful, but WITHOUT
010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
011 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
012 * version 2 for more details (a copy is included in the LICENSE file that
013 * accompanied this code).
014 *
015 * You should have received a copy of the GNU General Public License version
016 * 2 along with this work; if not, write to the Free Software Foundation,
017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
018 *
019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
020 * or visit www.oracle.com if you need additional information or have any
021 * questions.
022 */
023package com.oracle.graal.lir.gen;
024
025import jdk.internal.jvmci.code.*;
026import jdk.internal.jvmci.common.*;
027import jdk.internal.jvmci.meta.*;
028
029import com.oracle.graal.compiler.common.calc.*;
030import com.oracle.graal.compiler.common.cfg.*;
031import com.oracle.graal.compiler.common.spi.*;
032import com.oracle.graal.lir.*;
033
034public interface LIRGeneratorTool extends ArithmeticLIRGenerator, BenchmarkCounterFactory {
035
036    /**
037     * Factory for creating spill moves.
038     *
039     * The instructions returned by the methods must only depend on the input values. References to
040     * values that require interaction with register allocation are strictly forbidden.
041     */
042    public interface SpillMoveFactory {
043
044        LIRInstruction createMove(AllocatableValue result, Value input);
045
046        LIRInstruction createStackMove(AllocatableValue result, Value input);
047    }
048
049    public abstract class BlockScope implements AutoCloseable {
050
051        public abstract AbstractBlockBase<?> getCurrentBlock();
052
053        public abstract void close();
054
055    }
056
057    CodeGenProviders getProviders();
058
059    TargetDescription target();
060
061    MetaAccessProvider getMetaAccess();
062
063    CodeCacheProvider getCodeCache();
064
065    ForeignCallsProvider getForeignCalls();
066
067    AbstractBlockBase<?> getCurrentBlock();
068
069    LIRGenerationResult getResult();
070
071    boolean hasBlockEnd(AbstractBlockBase<?> block);
072
073    SpillMoveFactory getSpillMoveFactory();
074
075    BlockScope getBlockScope(AbstractBlockBase<?> block);
076
077    Value emitLoadConstant(LIRKind kind, Constant constant);
078
079    Variable emitLoad(LIRKind kind, Value address, LIRFrameState state);
080
081    void emitStore(LIRKind kind, Value address, Value input, LIRFrameState state);
082
083    void emitNullCheck(Value address, LIRFrameState state);
084
085    Variable emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue);
086
087    /**
088     * Emit an atomic read-and-add instruction.
089     *
090     * @param address address of the value to be read and written
091     * @param delta the value to be added
092     */
093    default Value emitAtomicReadAndAdd(Value address, Value delta) {
094        throw JVMCIError.unimplemented();
095    }
096
097    /**
098     * Emit an atomic read-and-write instruction.
099     *
100     * @param address address of the value to be read and written
101     * @param newValue the new value to be written
102     */
103    default Value emitAtomicReadAndWrite(Value address, Value newValue) {
104        throw JVMCIError.unimplemented();
105    }
106
107    void emitDeoptimize(Value actionAndReason, Value failedSpeculation, LIRFrameState state);
108
109    Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState state, Value... args);
110
111    RegisterAttributes attributes(Register register);
112
113    /**
114     * Create a new {@link Variable}.
115     *
116     * @param kind The type of the value that will be stored in this {@link Variable}. See
117     *            {@link LIRKind} for documentation on what to pass here. Note that in most cases,
118     *            simply passing {@link Value#getLIRKind()} is wrong.
119     * @return A new {@link Variable}.
120     */
121    Variable newVariable(LIRKind kind);
122
123    Variable emitMove(Value input);
124
125    void emitMove(AllocatableValue dst, Value src);
126
127    /**
128     * Emits an op that loads the address of some raw data.
129     *
130     * @param dst the variable into which the address is loaded
131     * @param data the data to be installed with the generated code
132     */
133    void emitData(AllocatableValue dst, byte[] data);
134
135    Variable emitAddress(StackSlotValue slot);
136
137    void emitMembar(int barriers);
138
139    void emitUnwind(Value operand);
140
141    /**
142     * Called just before register allocation is performed on the LIR owned by this generator.
143     * Overriding implementations of this method must call the overridden method.
144     */
145    void beforeRegisterAllocation();
146
147    void emitIncomingValues(Value[] params);
148
149    /**
150     * Emits a return instruction. Implementations need to insert a move if the input is not in the
151     * correct location.
152     */
153    void emitReturn(Value input);
154
155    AllocatableValue asAllocatable(Value value);
156
157    Variable load(Value value);
158
159    Value loadNonConst(Value value);
160
161    /**
162     * Determines if only oop maps are required for the code generated from the LIR.
163     */
164    boolean needOnlyOopMaps();
165
166    /**
167     * Gets the ABI specific operand used to return a value of a given kind from a method.
168     *
169     * @param kind the kind of value being returned
170     * @return the operand representing the ABI defined location used return a value of kind
171     *         {@code kind}
172     */
173    AllocatableValue resultOperandFor(LIRKind kind);
174
175    <I extends LIRInstruction> I append(I op);
176
177    void emitJump(LabelRef label);
178
179    void emitCompareBranch(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination,
180                    double trueDestinationProbability);
181
182    void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, LIRKind cmpKind, double overflowProbability);
183
184    void emitIntegerTestBranch(Value left, Value right, LabelRef trueDestination, LabelRef falseDestination, double trueSuccessorProbability);
185
186    Variable emitConditionalMove(PlatformKind cmpKind, Value leftVal, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue);
187
188    Variable emitIntegerTestMove(Value leftVal, Value right, Value trueValue, Value falseValue);
189
190    void emitStrategySwitch(JavaConstant[] keyConstants, double[] keyProbabilities, LabelRef[] keyTargets, LabelRef defaultTarget, Variable value);
191
192    void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget);
193
194    CallingConvention getCallingConvention();
195
196    Variable emitBitCount(Value operand);
197
198    Variable emitBitScanForward(Value operand);
199
200    Variable emitBitScanReverse(Value operand);
201
202    Variable emitByteSwap(Value operand);
203
204    Variable emitArrayEquals(Kind kind, Value array1, Value array2, Value length);
205
206    void emitBlackhole(Value operand);
207
208    @SuppressWarnings("unused")
209    default Value emitCountLeadingZeros(Value value) {
210        throw JVMCIError.unimplemented();
211    }
212
213    @SuppressWarnings("unused")
214    default Value emitCountTrailingZeros(Value value) {
215        throw JVMCIError.unimplemented();
216    }
217
218}