Create a super rough prototype of B3
[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(WTF::move(arguments))
81         , origin(origin)
82         , opcode(opcode)
83     {
84     }
85
86     // Note that these functors all avoid using "const" because we want to use them for things that
87     // edit IR. IR is meant to be edited; if you're carrying around a "const Inst&" then you're
88     // probably doing it wrong.
89
90     // This only walks those Tmps that are explicitly mentioned, and it doesn't tell you their role
91     // or type.
92     template<typename Functor>
93     void forEachTmpFast(const Functor& functor)
94     {
95         for (Arg& arg : args)
96             arg.forEachTmpFast(functor);
97     }
98
99     typedef void EachArgCallback(Arg&, Arg::Role, Arg::Type);
100     
101     // Calls the functor with (arg, role, type). This function is auto-generated by
102     // opcode_generator.rb.
103     template<typename Functor>
104     void forEachArg(const Functor&);
105
106     // Calls the functor with (tmp, role, type).
107     template<typename Functor>
108     void forEachTmp(const Functor& functor)
109     {
110         forEachArg(
111             [&] (Arg& arg, Arg::Role role, Arg::Type type) {
112                 arg.forEachTmp(role, type, functor);
113             });
114     }
115
116     // Thing can be either Arg or Tmp.
117     template<typename Thing, typename Functor>
118     void forEach(const Functor&);
119
120     // Returns true if this instruction has a Special*. This unlocks some extra functionality.
121     bool hasSpecial() const;
122
123     // Reports any additional registers clobbered by this operation. Note that for efficiency,
124     // extraClobberedRegs() only works if hasSpecial() returns true.
125     const RegisterSet& extraClobberedRegs();
126
127     // Use this to report which registers are live. This should be done just before codegen. Note
128     // that for efficiency, reportUsedRegisters() only works if hasSpecial() returns true.
129     void reportUsedRegisters(const RegisterSet&);
130
131     // Is this instruction in one of the valid forms right now? This function is auto-generated by
132     // opcode_generator.rb.
133     bool isValidForm();
134
135     // Assuming this instruction is in a valid form right now, will it still be in one of the valid
136     // forms if we put an Addr referencing the stack (or a StackSlot or CallArg, of course) in the
137     // given index? Spilling uses this: it walks the args by index to find Tmps that need spilling;
138     // if it finds one, it calls this to see if it can replace the Arg::Tmp with an Arg::Addr. If it
139     // finds a non-Tmp Arg, then it calls that Arg's forEachTmp to do a replacement that way.
140     //
141     // This function is auto-generated by opcode_generator.rb.
142     bool admitsStack(unsigned argIndex);
143
144     // Generate some code for this instruction. This is, like, literally our backend. If this is the
145     // terminal, it returns the jump that needs to be linked for the "then" case, with the "else"
146     // case being fall-through. This function is auto-generated by opcode_generator.rb.
147     CCallHelpers::Jump generate(CCallHelpers&, GenerationContext&);
148
149     void dump(PrintStream&) const;
150
151     ArgList args;
152     Value* origin; // The B3::Value that this originated from.
153     Opcode opcode;
154 };
155
156 } } } // namespace JSC::B3::Air
157
158 #endif // ENABLE(B3_JIT)
159
160 #endif // AirInst_h
161