Replace WTF::move with WTFMove
[WebKit-https.git] / Source / JavaScriptCore / b3 / air / AirInst.h
1 /*
2  * Copyright (C) 2015 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #ifndef AirInst_h
27 #define AirInst_h
28
29 #if ENABLE(B3_JIT)
30
31 #include "AirArg.h"
32 #include "AirOpcode.h"
33 #include "CCallHelpers.h"
34
35 namespace JSC {
36
37 class CCallHelpers;
38 class RegisterSet;
39
40 namespace B3 {
41
42 class Value;
43
44 namespace Air {
45
46 struct GenerationContext;
47
48 struct Inst {
49 public:
50     typedef Vector<Arg, 3> ArgList;
51
52     Inst()
53         : origin(nullptr)
54         , opcode(Nop)
55     {
56     }
57     
58     Inst(Opcode opcode, Value* origin)
59         : origin(origin)
60         , opcode(opcode)
61     {
62     }
63     
64     template<typename... Arguments>
65     Inst(Opcode opcode, Value* origin, Arg arg, Arguments... arguments)
66         : args{ arg, arguments... }
67         , origin(origin)
68         , opcode(opcode)
69     {
70     }
71
72     Inst(Opcode opcode, Value* origin, const ArgList& arguments)
73         : args(arguments)
74         , origin(origin)
75         , opcode(opcode)
76     {
77     }
78
79     Inst(Opcode opcode, Value* origin, ArgList&& arguments)
80         : args(WTFMove(arguments))
81         , origin(origin)
82         , opcode(opcode)
83     {
84     }
85
86     explicit operator bool() const { return origin || opcode != Nop || args.size(); }
87
88     // Note that these functors all avoid using "const" because we want to use them for things that
89     // edit IR. IR is meant to be edited; if you're carrying around a "const Inst&" then you're
90     // probably doing it wrong.
91
92     // This only walks those Tmps that are explicitly mentioned, and it doesn't tell you their role
93     // or type.
94     template<typename Functor>
95     void forEachTmpFast(const Functor& functor)
96     {
97         for (Arg& arg : args)
98             arg.forEachTmpFast(functor);
99     }
100
101     typedef void EachArgCallback(Arg&, Arg::Role, Arg::Type, Arg::Width);
102     
103     // Calls the functor with (arg, role, type, width). This function is auto-generated by
104     // opcode_generator.rb.
105     template<typename Functor>
106     void forEachArg(const Functor&);
107
108     // Calls the functor with (tmp, role, type, width).
109     template<typename Functor>
110     void forEachTmp(const Functor& functor)
111     {
112         forEachArg(
113             [&] (Arg& arg, Arg::Role role, Arg::Type type, Arg::Width width) {
114                 arg.forEachTmp(role, type, width, functor);
115             });
116     }
117
118     // Thing can be either Arg or Tmp.
119     template<typename Thing, typename Functor>
120     void forEach(const Functor&);
121
122     // Returns true if this instruction has a Special*. This unlocks some extra functionality.
123     bool hasSpecial() const;
124
125     // Reports any additional registers clobbered by this operation. Note that for efficiency,
126     // extraClobberedRegs() only works if hasSpecial() returns true.
127     const RegisterSet& extraClobberedRegs();
128     const RegisterSet& extraEarlyClobberedRegs();
129
130     // Iterate over the Defs and the extra clobbered registers. You must supply the next instruction if
131     // there is one.
132     template<typename Functor>
133     void forEachTmpWithExtraClobberedRegs(Inst* nextInst, const Functor& functor);
134
135     // Use this to report which registers are live. This should be done just before codegen. Note
136     // that for efficiency, reportUsedRegisters() only works if hasSpecial() returns true.
137     void reportUsedRegisters(const RegisterSet&);
138
139     // Is this instruction in one of the valid forms right now? This function is auto-generated by
140     // opcode_generator.rb.
141     bool isValidForm();
142
143     // Assuming this instruction is in a valid form right now, will it still be in one of the valid
144     // forms if we put an Addr referencing the stack (or a StackSlot or CallArg, of course) in the
145     // given index? Spilling uses this: it walks the args by index to find Tmps that need spilling;
146     // if it finds one, it calls this to see if it can replace the Arg::Tmp with an Arg::Addr. If it
147     // finds a non-Tmp Arg, then it calls that Arg's forEachTmp to do a replacement that way.
148     //
149     // This function is auto-generated by opcode_generator.rb.
150     bool admitsStack(unsigned argIndex);
151
152     // Returns true if this instruction can have any effects other than control flow or arguments.
153     bool hasNonArgNonControlEffects();
154
155     // Returns true if this instruction can have any effects other than what is implied by arguments.
156     // For example, "Move $42, (%rax)" will return false because the effect of storing to (%rax) is
157     // implied by the second argument.
158     bool hasNonArgEffects();
159
160     // Tells you if this operation has arg effects.
161     bool hasArgEffects();
162
163     // Generate some code for this instruction. This is, like, literally our backend. If this is the
164     // terminal, it returns the jump that needs to be linked for the "then" case, with the "else"
165     // case being fall-through. This function is auto-generated by opcode_generator.rb.
166     CCallHelpers::Jump generate(CCallHelpers&, GenerationContext&);
167
168     void dump(PrintStream&) const;
169
170     ArgList args;
171     Value* origin; // The B3::Value that this originated from.
172     Opcode opcode;
173 };
174
175 } } } // namespace JSC::B3::Air
176
177 #endif // ENABLE(B3_JIT)
178
179 #endif // AirInst_h
180