96e286bec50cfe5123d005c37fb9d8ee320dc6e5
[WebKit-https.git] / Source / JavaScriptCore / b3 / air / AirCode.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 AirCode_h
27 #define AirCode_h
28
29 #if ENABLE(B3_JIT)
30
31 #include "AirBasicBlock.h"
32 #include "AirSpecial.h"
33 #include "AirStackSlot.h"
34 #include "RegisterAtOffsetList.h"
35 #include "StackAlignment.h"
36
37 namespace JSC { namespace B3 {
38
39 class Procedure;
40
41 namespace Air {
42
43 class CCallSpecial;
44
45 // This is an IR that is very close to the bare metal. It requires about 40x more bytes than the
46 // generated machine code - for example if you're generating 1MB of machine code, you need about
47 // 40MB of Air.
48
49 class Code {
50     WTF_MAKE_NONCOPYABLE(Code);
51     WTF_MAKE_FAST_ALLOCATED;
52 public:
53     Code();
54     ~Code();
55
56     BasicBlock* addBlock(double frequency = PNaN);
57
58     StackSlot* addStackSlot(unsigned byteSize, StackSlotKind, StackSlotValue* = nullptr);
59     StackSlot* addStackSlot(StackSlotValue*);
60
61     Special* addSpecial(std::unique_ptr<Special>);
62
63     // This is the special you need to make a C call!
64     CCallSpecial* cCallSpecial();
65
66     Tmp newTmp(Arg::Type type)
67     {
68         switch (type) {
69         case Arg::GP:
70             return Tmp::gpTmpForIndex(m_numGPTmps++);
71         case Arg::FP:
72             return Tmp::fpTmpForIndex(m_numFPTmps++);
73         }
74         RELEASE_ASSERT_NOT_REACHED();
75         return { };
76     }
77
78     unsigned numTmps(Arg::Type type)
79     {
80         switch (type) {
81         case Arg::GP:
82             return m_numGPTmps;
83         case Arg::FP:
84             return m_numFPTmps;
85         }
86         RELEASE_ASSERT_NOT_REACHED();
87         return 0;
88     }
89
90     unsigned callArgAreaSize() const { return m_callArgAreaSize; }
91
92     // You can call this before code generation to force a minimum call arg area size.
93     void requestCallArgAreaSize(unsigned size)
94     {
95         m_callArgAreaSize = std::max(
96             m_callArgAreaSize,
97             static_cast<unsigned>(WTF::roundUpToMultipleOf(stackAlignmentBytes(), size)));
98     }
99
100     unsigned frameSize() const { return m_frameSize; }
101
102     // Only phases that do stack allocation are allowed to set this. Currently, only
103     // Air::allocateStack() does this.
104     void setFrameSize(unsigned frameSize)
105     {
106         m_frameSize = frameSize;
107     }
108
109     RegisterAtOffsetList& calleeSaveRegisters() { return m_calleeSaveRegisters; }
110
111     // Recomputes predecessors and deletes unreachable blocks.
112     void resetReachability();
113
114     void dump(PrintStream&) const;
115
116     unsigned size() const { return m_blocks.size(); }
117     BasicBlock* at(unsigned index) const { return m_blocks[index].get(); }
118     BasicBlock* operator[](unsigned index) const { return at(index); }
119
120     // Finds the smallest index' such that at(index') != null and index' >= index.
121     unsigned findFirstBlockIndex(unsigned index) const;
122
123     // Finds the smallest index' such that at(index') != null and index' > index.
124     unsigned findNextBlockIndex(unsigned index) const;
125
126     BasicBlock* findNextBlock(BasicBlock*) const;
127
128     class iterator {
129     public:
130         iterator()
131             : m_code(nullptr)
132             , m_index(0)
133         {
134         }
135
136         iterator(const Code& code, unsigned index)
137             : m_code(&code)
138             , m_index(m_code->findFirstBlockIndex(index))
139         {
140         }
141
142         BasicBlock* operator*()
143         {
144             return m_code->at(m_index);
145         }
146
147         iterator& operator++()
148         {
149             m_index = m_code->findFirstBlockIndex(m_index + 1);
150             return *this;
151         }
152
153         bool operator==(const iterator& other) const
154         {
155             return m_index == other.m_index;
156         }
157
158         bool operator!=(const iterator& other) const
159         {
160             return !(*this == other);
161         }
162
163     private:
164         const Code* m_code;
165         unsigned m_index;
166     };
167
168     iterator begin() const { return iterator(*this, 0); }
169     iterator end() const { return iterator(*this, size()); }
170
171     class StackSlotsCollection {
172     public:
173         StackSlotsCollection(const Code& code)
174             : m_code(code)
175         {
176         }
177
178         unsigned size() const { return m_code.m_stackSlots.size(); }
179         StackSlot* at(unsigned index) const { return m_code.m_stackSlots[index].get(); }
180         StackSlot* operator[](unsigned index) const { return at(index); }
181
182         class iterator {
183         public:
184             iterator()
185                 : m_collection(nullptr)
186                 , m_index(0)
187             {
188             }
189
190             iterator(const StackSlotsCollection& collection, unsigned index)
191                 : m_collection(&collection)
192                 , m_index(index)
193             {
194             }
195
196             StackSlot* operator*()
197             {
198                 return m_collection->at(m_index);
199             }
200
201             iterator& operator++()
202             {
203                 m_index++;
204                 return *this;
205             }
206
207             bool operator==(const iterator& other) const
208             {
209                 return m_index == other.m_index;
210             }
211
212             bool operator!=(const iterator& other) const
213             {
214                 return !(*this == other);
215             }
216
217         private:
218             const StackSlotsCollection* m_collection;
219             unsigned m_index;
220         };
221
222         iterator begin() const { return iterator(*this, 0); }
223         iterator end() const { return iterator(*this, size()); }
224
225     private:
226         const Code& m_code;
227     };
228
229     StackSlotsCollection stackSlots() const { return StackSlotsCollection(*this); }
230     
231     class SpecialsCollection {
232     public:
233         SpecialsCollection(const Code& code)
234             : m_code(code)
235         {
236         }
237
238         unsigned size() const { return m_code.m_specials.size(); }
239         Special* at(unsigned index) const { return m_code.m_specials[index].get(); }
240         Special* operator[](unsigned index) const { return at(index); }
241
242         class iterator {
243         public:
244             iterator()
245                 : m_collection(nullptr)
246                 , m_index(0)
247             {
248             }
249
250             iterator(const SpecialsCollection& collection, unsigned index)
251                 : m_collection(&collection)
252                 , m_index(index)
253             {
254             }
255
256             Special* operator*()
257             {
258                 return m_collection->at(m_index);
259             }
260
261             iterator& operator++()
262             {
263                 m_index++;
264                 return *this;
265             }
266
267             bool operator==(const iterator& other) const
268             {
269                 return m_index == other.m_index;
270             }
271
272             bool operator!=(const iterator& other) const
273             {
274                 return !(*this == other);
275             }
276
277         private:
278             const SpecialsCollection* m_collection;
279             unsigned m_index;
280         };
281
282         iterator begin() const { return iterator(*this, 0); }
283         iterator end() const { return iterator(*this, size()); }
284
285     private:
286         const Code& m_code;
287     };
288
289     SpecialsCollection specials() const { return SpecialsCollection(*this); }
290     
291     // The name has to be a string literal, since we don't do any memory management for the string.
292     void setLastPhaseName(const char* name)
293     {
294         m_lastPhaseName = name;
295     }
296
297     const char* lastPhaseName() const { return m_lastPhaseName; }
298
299 private:
300     Vector<std::unique_ptr<StackSlot>> m_stackSlots;
301     Vector<std::unique_ptr<BasicBlock>> m_blocks;
302     Vector<std::unique_ptr<Special>> m_specials;
303     CCallSpecial* m_cCallSpecial { nullptr };
304     unsigned m_numGPTmps { 0 };
305     unsigned m_numFPTmps { 0 };
306     unsigned m_frameSize { 0 };
307     unsigned m_callArgAreaSize { 0 };
308     RegisterAtOffsetList m_calleeSaveRegisters;
309     const char* m_lastPhaseName;
310 };
311
312 } } } // namespace JSC::B3::Air
313
314 #endif // ENABLE(B3_JIT)
315
316 #endif // AirCode_h
317