B3 should be able to compile a program with ChillDiv
[WebKit-https.git] / Source / JavaScriptCore / b3 / B3Procedure.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 B3Procedure_h
27 #define B3Procedure_h
28
29 #if ENABLE(B3_JIT)
30
31 #include "B3Origin.h"
32 #include "B3Type.h"
33 #include "PureNaN.h"
34 #include <wtf/Bag.h>
35 #include <wtf/FastMalloc.h>
36 #include <wtf/Noncopyable.h>
37 #include <wtf/PrintStream.h>
38 #include <wtf/TriState.h>
39 #include <wtf/Vector.h>
40
41 namespace JSC { namespace B3 {
42
43 class BasicBlock;
44 class BlockInsertionSet;
45 class OpaqueByproducts;
46 class Value;
47
48 class Procedure {
49     WTF_MAKE_NONCOPYABLE(Procedure);
50     WTF_MAKE_FAST_ALLOCATED;
51 public:
52
53     JS_EXPORT_PRIVATE Procedure();
54     JS_EXPORT_PRIVATE ~Procedure();
55
56     JS_EXPORT_PRIVATE BasicBlock* addBlock(double frequency = PNaN);
57     
58     template<typename ValueType, typename... Arguments>
59     ValueType* add(Arguments...);
60
61     Value* addIntConstant(Origin, Type, int64_t value);
62     Value* addIntConstant(Value*, int64_t value);
63
64     // Returns null for MixedTriState.
65     Value* addBoolConstant(Origin, TriState);
66
67     void resetValueOwners();
68     void resetReachability();
69
70     JS_EXPORT_PRIVATE void dump(PrintStream&) const;
71
72     unsigned size() const { return m_blocks.size(); }
73     BasicBlock* at(unsigned index) const { return m_blocks[index].get(); }
74     BasicBlock* operator[](unsigned index) const { return at(index); }
75
76     class iterator {
77     public:
78         iterator()
79             : m_procedure(nullptr)
80             , m_index(0)
81         {
82         }
83
84         iterator(const Procedure& procedure, unsigned index)
85             : m_procedure(&procedure)
86             , m_index(findNext(index))
87         {
88         }
89
90         BasicBlock* operator*()
91         {
92             return m_procedure->at(m_index);
93         }
94
95         iterator& operator++()
96         {
97             m_index = findNext(m_index + 1);
98             return *this;
99         }
100
101         bool operator==(const iterator& other) const
102         {
103             ASSERT(m_procedure == other.m_procedure);
104             return m_index == other.m_index;
105         }
106         
107         bool operator!=(const iterator& other) const
108         {
109             return !(*this == other);
110         }
111
112     private:
113         unsigned findNext(unsigned index)
114         {
115             while (index < m_procedure->size() && !m_procedure->at(index))
116                 index++;
117             return index;
118         }
119
120         const Procedure* m_procedure;
121         unsigned m_index;
122     };
123
124     iterator begin() const { return iterator(*this, 0); }
125     iterator end() const { return iterator(*this, size()); }
126
127     Vector<BasicBlock*> blocksInPreOrder();
128     Vector<BasicBlock*> blocksInPostOrder();
129
130     class ValuesCollection {
131     public:
132         ValuesCollection(const Procedure& procedure)
133             : m_procedure(procedure)
134         {
135         }
136
137         class iterator {
138         public:
139             iterator()
140                 : m_procedure(nullptr)
141                 , m_index(0)
142             {
143             }
144
145             iterator(const Procedure& procedure, unsigned index)
146                 : m_procedure(&procedure)
147                 , m_index(findNext(index))
148             {
149             }
150
151             Value* operator*() const
152             {
153                 return m_procedure->m_values[m_index].get();
154             }
155
156             iterator& operator++()
157             {
158                 m_index = findNext(m_index + 1);
159                 return *this;
160             }
161
162             bool operator==(const iterator& other) const
163             {
164                 ASSERT(m_procedure == other.m_procedure);
165                 return m_index == other.m_index;
166             }
167
168             bool operator!=(const iterator& other) const
169             {
170                 return !(*this == other);
171             }
172
173         private:
174             unsigned findNext(unsigned index)
175             {
176                 while (index < m_procedure->m_values.size() && !m_procedure->m_values[index])
177                     index++;
178                 return index;
179             }
180
181             const Procedure* m_procedure;
182             unsigned m_index;
183         };
184
185         iterator begin() const { return iterator(m_procedure, 0); }
186         iterator end() const { return iterator(m_procedure, m_procedure.m_values.size()); }
187
188         unsigned size() const { return m_procedure.m_values.size(); }
189         Value* at(unsigned index) const { return m_procedure.m_values[index].get(); }
190         Value* operator[](unsigned index) const { return at(index); }
191         
192     private:
193         const Procedure& m_procedure;
194     };
195
196     ValuesCollection values() const { return ValuesCollection(*this); }
197
198     void deleteValue(Value*);
199
200     // The name has to be a string literal, since we don't do any memory management for the string.
201     void setLastPhaseName(const char* name)
202     {
203         m_lastPhaseName = name;
204     }
205
206     const char* lastPhaseName() const { return m_lastPhaseName; }
207
208     void* addDataSection(size_t size);
209
210     OpaqueByproducts& byproducts() { return *m_byproducts; }
211
212     // Below are methods that make sense to call after you have generated code for the procedure.
213
214     // You have to call this method after calling generate(). The code generated by B3::generate()
215     // will require you to keep this object alive for as long as that code is runnable. Usually, this
216     // just keeps alive things like the double constant pool and switch lookup tables. If this sounds
217     // confusing, you should probably be using the B3::Compilation API to compile code. If you use
218     // that API, then you don't have to worry about this.
219     std::unique_ptr<OpaqueByproducts> takeByproducts() { return WTF::move(m_byproducts); }
220
221 private:
222     friend class BlockInsertionSet;
223     
224     JS_EXPORT_PRIVATE size_t addValueIndex();
225     
226     Vector<std::unique_ptr<BasicBlock>> m_blocks;
227     Vector<std::unique_ptr<Value>> m_values;
228     Vector<size_t> m_valueIndexFreeList;
229     const char* m_lastPhaseName;
230     std::unique_ptr<OpaqueByproducts> m_byproducts;
231 };
232
233 } } // namespace JSC::B3
234
235 #endif // ENABLE(B3_JIT)
236
237 #endif // B3Procedure_h
238