blob: c33605c1495b2fc92d2e34b0ab230e7afb6e0498 [file] [log] [blame]
Ben Murdochc5610432016-08-08 18:44:38 +01001// Copyright 2015 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_COMPILER_CODE_ASSEMBLER_H_
6#define V8_COMPILER_CODE_ASSEMBLER_H_
7
8#include <map>
9
10// Clients of this interface shouldn't depend on lots of compiler internals.
11// Do not include anything from src/compiler here!
12#include "src/allocation.h"
13#include "src/builtins.h"
14#include "src/heap/heap.h"
15#include "src/machine-type.h"
16#include "src/runtime/runtime.h"
17#include "src/zone-containers.h"
18
19namespace v8 {
20namespace internal {
21
22class Callable;
23class CallInterfaceDescriptor;
24class Isolate;
25class Factory;
26class Zone;
27
28namespace compiler {
29
30class CallDescriptor;
31class Graph;
32class Node;
33class Operator;
34class RawMachineAssembler;
35class RawMachineLabel;
36class Schedule;
37
38#define CODE_ASSEMBLER_COMPARE_BINARY_OP_LIST(V) \
39 V(Float32Equal) \
40 V(Float32LessThan) \
41 V(Float32LessThanOrEqual) \
42 V(Float32GreaterThan) \
43 V(Float32GreaterThanOrEqual) \
44 V(Float64Equal) \
45 V(Float64LessThan) \
46 V(Float64LessThanOrEqual) \
47 V(Float64GreaterThan) \
48 V(Float64GreaterThanOrEqual) \
49 V(Int32GreaterThan) \
50 V(Int32GreaterThanOrEqual) \
51 V(Int32LessThan) \
52 V(Int32LessThanOrEqual) \
53 V(IntPtrLessThan) \
54 V(IntPtrLessThanOrEqual) \
55 V(IntPtrGreaterThan) \
56 V(IntPtrGreaterThanOrEqual) \
57 V(IntPtrEqual) \
58 V(Uint32LessThan) \
59 V(UintPtrLessThan) \
60 V(UintPtrGreaterThanOrEqual) \
61 V(WordEqual) \
62 V(WordNotEqual) \
63 V(Word32Equal) \
64 V(Word32NotEqual) \
65 V(Word64Equal) \
66 V(Word64NotEqual)
67
68#define CODE_ASSEMBLER_BINARY_OP_LIST(V) \
69 CODE_ASSEMBLER_COMPARE_BINARY_OP_LIST(V) \
70 V(Float64Add) \
71 V(Float64Sub) \
72 V(Float64Mul) \
73 V(Float64Div) \
74 V(Float64Mod) \
Ben Murdoch61f157c2016-09-16 13:49:30 +010075 V(Float64Atan2) \
Ben Murdochc5610432016-08-08 18:44:38 +010076 V(Float64InsertLowWord32) \
77 V(Float64InsertHighWord32) \
78 V(IntPtrAdd) \
79 V(IntPtrAddWithOverflow) \
80 V(IntPtrSub) \
81 V(IntPtrSubWithOverflow) \
82 V(IntPtrMul) \
83 V(Int32Add) \
84 V(Int32AddWithOverflow) \
85 V(Int32Sub) \
86 V(Int32Mul) \
87 V(Int32Div) \
88 V(WordOr) \
89 V(WordAnd) \
90 V(WordXor) \
91 V(WordShl) \
92 V(WordShr) \
93 V(WordSar) \
94 V(WordRor) \
95 V(Word32Or) \
96 V(Word32And) \
97 V(Word32Xor) \
98 V(Word32Shl) \
99 V(Word32Shr) \
100 V(Word32Sar) \
101 V(Word32Ror) \
102 V(Word64Or) \
103 V(Word64And) \
104 V(Word64Xor) \
105 V(Word64Shr) \
106 V(Word64Sar) \
107 V(Word64Ror)
108
109#define CODE_ASSEMBLER_UNARY_OP_LIST(V) \
Ben Murdoch61f157c2016-09-16 13:49:30 +0100110 V(Float64Atan) \
111 V(Float64Atanh) \
112 V(Float64Cos) \
113 V(Float64Exp) \
114 V(Float64Expm1) \
115 V(Float64Log) \
116 V(Float64Log1p) \
117 V(Float64Log2) \
118 V(Float64Log10) \
119 V(Float64Cbrt) \
Ben Murdochc5610432016-08-08 18:44:38 +0100120 V(Float64Neg) \
Ben Murdoch61f157c2016-09-16 13:49:30 +0100121 V(Float64Sin) \
Ben Murdochc5610432016-08-08 18:44:38 +0100122 V(Float64Sqrt) \
Ben Murdoch61f157c2016-09-16 13:49:30 +0100123 V(Float64Tan) \
Ben Murdochc5610432016-08-08 18:44:38 +0100124 V(Float64ExtractLowWord32) \
125 V(Float64ExtractHighWord32) \
126 V(BitcastWordToTagged) \
127 V(TruncateFloat64ToWord32) \
128 V(TruncateInt64ToInt32) \
129 V(ChangeFloat64ToUint32) \
130 V(ChangeInt32ToFloat64) \
131 V(ChangeInt32ToInt64) \
132 V(ChangeUint32ToFloat64) \
133 V(ChangeUint32ToUint64) \
134 V(RoundFloat64ToInt32) \
135 V(Float64RoundDown) \
136 V(Float64RoundUp) \
137 V(Float64RoundTruncate) \
138 V(Word32Clz)
139
140// A "public" interface used by components outside of compiler directory to
141// create code objects with TurboFan's backend. This class is mostly a thin shim
142// around the RawMachineAssembler, and its primary job is to ensure that the
143// innards of the RawMachineAssembler and other compiler implementation details
144// don't leak outside of the the compiler directory..
145//
146// V8 components that need to generate low-level code using this interface
147// should include this header--and this header only--from the compiler directory
148// (this is actually enforced). Since all interesting data structures are
149// forward declared, it's not possible for clients to peek inside the compiler
150// internals.
151//
152// In addition to providing isolation between TurboFan and code generation
153// clients, CodeAssembler also provides an abstraction for creating variables
154// and enhanced Label functionality to merge variable values along paths where
155// they have differing values, including loops.
156class CodeAssembler {
157 public:
158 // Create with CallStub linkage.
159 // |result_size| specifies the number of results returned by the stub.
160 // TODO(rmcilroy): move result_size to the CallInterfaceDescriptor.
161 CodeAssembler(Isolate* isolate, Zone* zone,
162 const CallInterfaceDescriptor& descriptor, Code::Flags flags,
163 const char* name, size_t result_size = 1);
164
165 // Create with JSCall linkage.
166 CodeAssembler(Isolate* isolate, Zone* zone, int parameter_count,
167 Code::Flags flags, const char* name);
168
169 virtual ~CodeAssembler();
170
171 Handle<Code> GenerateCode();
172
173 bool Is64() const;
174 bool IsFloat64RoundUpSupported() const;
175 bool IsFloat64RoundDownSupported() const;
176 bool IsFloat64RoundTruncateSupported() const;
177
178 class Label;
179 class Variable {
180 public:
181 explicit Variable(CodeAssembler* assembler, MachineRepresentation rep);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100182 ~Variable();
Ben Murdochc5610432016-08-08 18:44:38 +0100183 void Bind(Node* value);
184 Node* value() const;
185 MachineRepresentation rep() const;
186 bool IsBound() const;
187
188 private:
189 friend class CodeAssembler;
190 class Impl;
191 Impl* impl_;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100192 CodeAssembler* assembler_;
Ben Murdochc5610432016-08-08 18:44:38 +0100193 };
194
195 enum AllocationFlag : uint8_t {
196 kNone = 0,
197 kDoubleAlignment = 1,
198 kPretenured = 1 << 1
199 };
200
201 typedef base::Flags<AllocationFlag> AllocationFlags;
202
203 // ===========================================================================
204 // Base Assembler
205 // ===========================================================================
206
207 // Constants.
208 Node* Int32Constant(int32_t value);
209 Node* Int64Constant(int64_t value);
210 Node* IntPtrConstant(intptr_t value);
211 Node* NumberConstant(double value);
212 Node* SmiConstant(Smi* value);
213 Node* HeapConstant(Handle<HeapObject> object);
214 Node* BooleanConstant(bool value);
215 Node* ExternalConstant(ExternalReference address);
216 Node* Float64Constant(double value);
217 Node* NaNConstant();
218
219 bool ToInt32Constant(Node* node, int32_t& out_value);
220 bool ToInt64Constant(Node* node, int64_t& out_value);
221 bool ToIntPtrConstant(Node* node, intptr_t& out_value);
222
223 Node* Parameter(int value);
224 void Return(Node* value);
225
Ben Murdoch61f157c2016-09-16 13:49:30 +0100226 void DebugBreak();
227 void Comment(const char* format, ...);
228
Ben Murdochc5610432016-08-08 18:44:38 +0100229 void Bind(Label* label);
230 void Goto(Label* label);
231 void GotoIf(Node* condition, Label* true_label);
232 void GotoUnless(Node* condition, Label* false_label);
233 void Branch(Node* condition, Label* true_label, Label* false_label);
234
235 void Switch(Node* index, Label* default_label, int32_t* case_values,
236 Label** case_labels, size_t case_count);
237
238 // Access to the frame pointer
239 Node* LoadFramePointer();
240 Node* LoadParentFramePointer();
241
242 // Access to the stack pointer
243 Node* LoadStackPointer();
244
245 // Load raw memory location.
246 Node* Load(MachineType rep, Node* base);
247 Node* Load(MachineType rep, Node* base, Node* index);
248 Node* AtomicLoad(MachineType rep, Node* base, Node* index);
249
250 // Load a value from the root array.
251 Node* LoadRoot(Heap::RootListIndex root_index);
252
253 // Store value to raw memory location.
254 Node* Store(MachineRepresentation rep, Node* base, Node* value);
255 Node* Store(MachineRepresentation rep, Node* base, Node* index, Node* value);
256 Node* StoreNoWriteBarrier(MachineRepresentation rep, Node* base, Node* value);
257 Node* StoreNoWriteBarrier(MachineRepresentation rep, Node* base, Node* index,
258 Node* value);
259 Node* AtomicStore(MachineRepresentation rep, Node* base, Node* index,
260 Node* value);
261
262 // Store a value to the root array.
263 Node* StoreRoot(Heap::RootListIndex root_index, Node* value);
264
265// Basic arithmetic operations.
266#define DECLARE_CODE_ASSEMBLER_BINARY_OP(name) Node* name(Node* a, Node* b);
267 CODE_ASSEMBLER_BINARY_OP_LIST(DECLARE_CODE_ASSEMBLER_BINARY_OP)
268#undef DECLARE_CODE_ASSEMBLER_BINARY_OP
269
270 Node* WordShl(Node* value, int shift);
271 Node* WordShr(Node* value, int shift);
272
273// Unary
274#define DECLARE_CODE_ASSEMBLER_UNARY_OP(name) Node* name(Node* a);
275 CODE_ASSEMBLER_UNARY_OP_LIST(DECLARE_CODE_ASSEMBLER_UNARY_OP)
276#undef DECLARE_CODE_ASSEMBLER_UNARY_OP
277
278 // No-op on 32-bit, otherwise zero extend.
279 Node* ChangeUint32ToWord(Node* value);
280 // No-op on 32-bit, otherwise sign extend.
281 Node* ChangeInt32ToIntPtr(Node* value);
282
283 // Projections
284 Node* Projection(int index, Node* value);
285
286 // Calls
287 Node* CallRuntime(Runtime::FunctionId function_id, Node* context);
288 Node* CallRuntime(Runtime::FunctionId function_id, Node* context, Node* arg1);
289 Node* CallRuntime(Runtime::FunctionId function_id, Node* context, Node* arg1,
290 Node* arg2);
291 Node* CallRuntime(Runtime::FunctionId function_id, Node* context, Node* arg1,
292 Node* arg2, Node* arg3);
293 Node* CallRuntime(Runtime::FunctionId function_id, Node* context, Node* arg1,
294 Node* arg2, Node* arg3, Node* arg4);
295 Node* CallRuntime(Runtime::FunctionId function_id, Node* context, Node* arg1,
296 Node* arg2, Node* arg3, Node* arg4, Node* arg5);
297
298 Node* TailCallRuntime(Runtime::FunctionId function_id, Node* context);
299 Node* TailCallRuntime(Runtime::FunctionId function_id, Node* context,
300 Node* arg1);
301 Node* TailCallRuntime(Runtime::FunctionId function_id, Node* context,
302 Node* arg1, Node* arg2);
303 Node* TailCallRuntime(Runtime::FunctionId function_id, Node* context,
304 Node* arg1, Node* arg2, Node* arg3);
305 Node* TailCallRuntime(Runtime::FunctionId function_id, Node* context,
306 Node* arg1, Node* arg2, Node* arg3, Node* arg4);
307
308 Node* CallStub(Callable const& callable, Node* context, Node* arg1,
309 size_t result_size = 1);
310 Node* CallStub(Callable const& callable, Node* context, Node* arg1,
311 Node* arg2, size_t result_size = 1);
312 Node* CallStub(Callable const& callable, Node* context, Node* arg1,
313 Node* arg2, Node* arg3, size_t result_size = 1);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100314 Node* CallStubN(Callable const& callable, Node** args,
315 size_t result_size = 1);
Ben Murdochc5610432016-08-08 18:44:38 +0100316
317 Node* CallStub(const CallInterfaceDescriptor& descriptor, Node* target,
318 Node* context, Node* arg1, size_t result_size = 1);
319 Node* CallStub(const CallInterfaceDescriptor& descriptor, Node* target,
320 Node* context, Node* arg1, Node* arg2, size_t result_size = 1);
321 Node* CallStub(const CallInterfaceDescriptor& descriptor, Node* target,
322 Node* context, Node* arg1, Node* arg2, Node* arg3,
323 size_t result_size = 1);
324 Node* CallStub(const CallInterfaceDescriptor& descriptor, Node* target,
325 Node* context, Node* arg1, Node* arg2, Node* arg3, Node* arg4,
326 size_t result_size = 1);
327 Node* CallStub(const CallInterfaceDescriptor& descriptor, Node* target,
328 Node* context, Node* arg1, Node* arg2, Node* arg3, Node* arg4,
329 Node* arg5, size_t result_size = 1);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100330 Node* CallStubN(const CallInterfaceDescriptor& descriptor, Node* target,
331 Node** args, size_t result_size = 1);
Ben Murdochc5610432016-08-08 18:44:38 +0100332
333 Node* TailCallStub(Callable const& callable, Node* context, Node* arg1,
334 Node* arg2, size_t result_size = 1);
335 Node* TailCallStub(Callable const& callable, Node* context, Node* arg1,
336 Node* arg2, Node* arg3, size_t result_size = 1);
337 Node* TailCallStub(const CallInterfaceDescriptor& descriptor, Node* target,
338 Node* context, Node* arg1, Node* arg2,
339 size_t result_size = 1);
340 Node* TailCallStub(const CallInterfaceDescriptor& descriptor, Node* target,
341 Node* context, Node* arg1, Node* arg2, Node* arg3,
342 size_t result_size = 1);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100343 Node* TailCallStub(const CallInterfaceDescriptor& descriptor, Node* target,
344 Node* context, Node* arg1, Node* arg2, Node* arg3,
345 Node* arg4, size_t result_size = 1);
Ben Murdochc5610432016-08-08 18:44:38 +0100346
347 Node* TailCallBytecodeDispatch(const CallInterfaceDescriptor& descriptor,
348 Node* code_target_address, Node** args);
349
Ben Murdoch61f157c2016-09-16 13:49:30 +0100350 Node* CallJS(Callable const& callable, Node* context, Node* function,
351 Node* receiver, size_t result_size = 1);
352 Node* CallJS(Callable const& callable, Node* context, Node* function,
353 Node* receiver, Node* arg1, size_t result_size = 1);
354 Node* CallJS(Callable const& callable, Node* context, Node* function,
355 Node* receiver, Node* arg1, Node* arg2, size_t result_size = 1);
356
Ben Murdochc5610432016-08-08 18:44:38 +0100357 // Branching helpers.
358 void BranchIf(Node* condition, Label* if_true, Label* if_false);
359
360#define BRANCH_HELPER(name) \
361 void BranchIf##name(Node* a, Node* b, Label* if_true, Label* if_false) { \
362 BranchIf(name(a, b), if_true, if_false); \
363 }
364 CODE_ASSEMBLER_COMPARE_BINARY_OP_LIST(BRANCH_HELPER)
365#undef BRANCH_HELPER
366
367 // Helpers which delegate to RawMachineAssembler.
368 Factory* factory() const;
369 Isolate* isolate() const;
370 Zone* zone() const;
371
372 protected:
373 // Protected helpers which delegate to RawMachineAssembler.
374 Graph* graph() const;
375
376 Node* SmiShiftBitsConstant();
377
378 // Enables subclasses to perform operations before and after a call.
379 virtual void CallPrologue();
380 virtual void CallEpilogue();
381
382 private:
Ben Murdochc5610432016-08-08 18:44:38 +0100383 CodeAssembler(Isolate* isolate, Zone* zone, CallDescriptor* call_descriptor,
384 Code::Flags flags, const char* name);
385
386 Node* CallN(CallDescriptor* descriptor, Node* code_target, Node** args);
387 Node* TailCallN(CallDescriptor* descriptor, Node* code_target, Node** args);
388
389 base::SmartPointer<RawMachineAssembler> raw_assembler_;
390 Code::Flags flags_;
391 const char* name_;
392 bool code_generated_;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100393 ZoneSet<Variable::Impl*> variables_;
Ben Murdochc5610432016-08-08 18:44:38 +0100394
395 DISALLOW_COPY_AND_ASSIGN(CodeAssembler);
396};
397
398DEFINE_OPERATORS_FOR_FLAGS(CodeAssembler::AllocationFlags);
399
400class CodeAssembler::Label {
401 public:
402 enum Type { kDeferred, kNonDeferred };
403
404 explicit Label(
405 CodeAssembler* assembler,
406 CodeAssembler::Label::Type type = CodeAssembler::Label::kNonDeferred)
407 : CodeAssembler::Label(assembler, 0, nullptr, type) {}
408 Label(CodeAssembler* assembler, CodeAssembler::Variable* merged_variable,
409 CodeAssembler::Label::Type type = CodeAssembler::Label::kNonDeferred)
410 : CodeAssembler::Label(assembler, 1, &merged_variable, type) {}
411 Label(CodeAssembler* assembler, int merged_variable_count,
412 CodeAssembler::Variable** merged_variables,
413 CodeAssembler::Label::Type type = CodeAssembler::Label::kNonDeferred);
414 ~Label() {}
415
416 private:
417 friend class CodeAssembler;
418
419 void Bind();
420 void MergeVariables();
421
422 bool bound_;
423 size_t merge_count_;
424 CodeAssembler* assembler_;
425 RawMachineLabel* label_;
426 // Map of variables that need to be merged to their phi nodes (or placeholders
427 // for those phis).
428 std::map<Variable::Impl*, Node*> variable_phis_;
429 // Map of variables to the list of value nodes that have been added from each
430 // merge path in their order of merging.
431 std::map<Variable::Impl*, std::vector<Node*>> variable_merges_;
432};
433
434} // namespace compiler
435} // namespace internal
436} // namespace v8
437
438#endif // V8_COMPILER_CODE_ASSEMBLER_H_