• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // 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 #include <memory>
10 
11 // Clients of this interface shouldn't depend on lots of compiler internals.
12 // Do not include anything from src/compiler here!
13 #include "src/allocation.h"
14 #include "src/base/macros.h"
15 #include "src/builtins/builtins.h"
16 #include "src/code-factory.h"
17 #include "src/globals.h"
18 #include "src/heap/heap.h"
19 #include "src/machine-type.h"
20 #include "src/objects.h"
21 #include "src/objects/data-handler.h"
22 #include "src/objects/map.h"
23 #include "src/objects/maybe-object.h"
24 #include "src/runtime/runtime.h"
25 #include "src/zone/zone-containers.h"
26 
27 namespace v8 {
28 namespace internal {
29 
30 class Callable;
31 class CallInterfaceDescriptor;
32 class Isolate;
33 class JSCollection;
34 class JSRegExpStringIterator;
35 class JSWeakCollection;
36 class JSWeakMap;
37 class JSWeakSet;
38 class MaybeObject;
39 class PromiseCapability;
40 class PromiseFulfillReactionJobTask;
41 class PromiseReaction;
42 class PromiseReactionJobTask;
43 class PromiseRejectReactionJobTask;
44 class InterpreterData;
45 class Factory;
46 class Zone;
47 
48 template <typename T>
49 class Signature;
50 
51 struct UntaggedT {};
52 
53 struct IntegralT : UntaggedT {};
54 
55 struct WordT : IntegralT {
56   static const MachineRepresentation kMachineRepresentation =
57       (kPointerSize == 4) ? MachineRepresentation::kWord32
58                           : MachineRepresentation::kWord64;
59 };
60 
61 struct RawPtrT : WordT {
62   static constexpr MachineType kMachineType = MachineType::Pointer();
63 };
64 
65 template <class To>
66 struct RawPtr : RawPtrT {};
67 
68 struct Word32T : IntegralT {
69   static const MachineRepresentation kMachineRepresentation =
70       MachineRepresentation::kWord32;
71 };
72 struct Int32T : Word32T {
73   static constexpr MachineType kMachineType = MachineType::Int32();
74 };
75 struct Uint32T : Word32T {
76   static constexpr MachineType kMachineType = MachineType::Uint32();
77 };
78 
79 struct Word64T : IntegralT {
80   static const MachineRepresentation kMachineRepresentation =
81       MachineRepresentation::kWord64;
82 };
83 struct Int64T : Word64T {
84   static constexpr MachineType kMachineType = MachineType::Int64();
85 };
86 struct Uint64T : Word64T {
87   static constexpr MachineType kMachineType = MachineType::Uint64();
88 };
89 
90 struct IntPtrT : WordT {
91   static constexpr MachineType kMachineType = MachineType::IntPtr();
92 };
93 struct UintPtrT : WordT {
94   static constexpr MachineType kMachineType = MachineType::UintPtr();
95 };
96 
97 struct Float32T : UntaggedT {
98   static const MachineRepresentation kMachineRepresentation =
99       MachineRepresentation::kFloat32;
100   static constexpr MachineType kMachineType = MachineType::Float32();
101 };
102 
103 struct Float64T : UntaggedT {
104   static const MachineRepresentation kMachineRepresentation =
105       MachineRepresentation::kFloat64;
106   static constexpr MachineType kMachineType = MachineType::Float64();
107 };
108 
109 // Result of a comparison operation.
110 struct BoolT : Word32T {};
111 
112 // Value type of a Turbofan node with two results.
113 template <class T1, class T2>
114 struct PairT {};
115 
CommonMachineType(MachineType type1,MachineType type2)116 inline constexpr MachineType CommonMachineType(MachineType type1,
117                                                MachineType type2) {
118   return (type1 == type2) ? type1
119                           : ((type1.IsTagged() && type2.IsTagged())
120                                  ? MachineType::AnyTagged()
121                                  : MachineType::None());
122 }
123 
124 template <class Type, class Enable = void>
125 struct MachineTypeOf {
126   static constexpr MachineType value = Type::kMachineType;
127 };
128 
129 template <class Type, class Enable>
130 constexpr MachineType MachineTypeOf<Type, Enable>::value;
131 
132 template <>
133 struct MachineTypeOf<Object> {
134   static constexpr MachineType value = MachineType::AnyTagged();
135 };
136 template <>
137 struct MachineTypeOf<MaybeObject> {
138   static constexpr MachineType value = MachineType::AnyTagged();
139 };
140 template <>
141 struct MachineTypeOf<Smi> {
142   static constexpr MachineType value = MachineType::TaggedSigned();
143 };
144 template <class HeapObjectSubtype>
145 struct MachineTypeOf<HeapObjectSubtype,
146                      typename std::enable_if<std::is_base_of<
147                          HeapObject, HeapObjectSubtype>::value>::type> {
148   static constexpr MachineType value = MachineType::TaggedPointer();
149 };
150 
151 template <class HeapObjectSubtype>
152 constexpr MachineType MachineTypeOf<
153     HeapObjectSubtype, typename std::enable_if<std::is_base_of<
154                            HeapObject, HeapObjectSubtype>::value>::type>::value;
155 
156 template <class Type, class Enable = void>
157 struct MachineRepresentationOf {
158   static const MachineRepresentation value = Type::kMachineRepresentation;
159 };
160 template <class T>
161 struct MachineRepresentationOf<
162     T, typename std::enable_if<std::is_base_of<Object, T>::value>::type> {
163   static const MachineRepresentation value =
164       MachineTypeOf<T>::value.representation();
165 };
166 template <class T>
167 struct MachineRepresentationOf<
168     T, typename std::enable_if<std::is_base_of<MaybeObject, T>::value>::type> {
169   static const MachineRepresentation value =
170       MachineTypeOf<T>::value.representation();
171 };
172 
173 template <class T>
174 struct is_valid_type_tag {
175   static const bool value = std::is_base_of<Object, T>::value ||
176                             std::is_base_of<UntaggedT, T>::value ||
177                             std::is_base_of<MaybeObject, T>::value ||
178                             std::is_same<ExternalReference, T>::value;
179   static const bool is_tagged = std::is_base_of<Object, T>::value ||
180                                 std::is_base_of<MaybeObject, T>::value;
181 };
182 
183 template <class T1, class T2>
184 struct is_valid_type_tag<PairT<T1, T2>> {
185   static const bool value =
186       is_valid_type_tag<T1>::value && is_valid_type_tag<T2>::value;
187   static const bool is_tagged = false;
188 };
189 
190 template <class T1, class T2>
191 struct UnionT;
192 
193 template <class T1, class T2>
194 struct is_valid_type_tag<UnionT<T1, T2>> {
195   static const bool is_tagged =
196       is_valid_type_tag<T1>::is_tagged && is_valid_type_tag<T2>::is_tagged;
197   static const bool value = is_tagged;
198 };
199 
200 template <class T1, class T2>
201 struct UnionT {
202   static constexpr MachineType kMachineType =
203       CommonMachineType(MachineTypeOf<T1>::value, MachineTypeOf<T2>::value);
204   static const MachineRepresentation kMachineRepresentation =
205       kMachineType.representation();
206   static_assert(kMachineRepresentation != MachineRepresentation::kNone,
207                 "no common representation");
208   static_assert(is_valid_type_tag<T1>::is_tagged &&
209                     is_valid_type_tag<T2>::is_tagged,
210                 "union types are only possible for tagged values");
211 };
212 
213 using Number = UnionT<Smi, HeapNumber>;
214 using Numeric = UnionT<Number, BigInt>;
215 
216 #define ENUM_ELEMENT(Name) k##Name,
217 #define ENUM_STRUCT_ELEMENT(NAME, Name, name) k##Name,
218 enum class ObjectType {
219   kObject,
220   OBJECT_TYPE_LIST(ENUM_ELEMENT) HEAP_OBJECT_TYPE_LIST(ENUM_ELEMENT)
221       STRUCT_LIST(ENUM_STRUCT_ELEMENT)
222 };
223 #undef ENUM_ELEMENT
224 #undef ENUM_STRUCT_ELEMENT
225 
226 class AccessCheckNeeded;
227 class BigIntWrapper;
228 class ClassBoilerplate;
229 class BooleanWrapper;
230 class CompilationCacheTable;
231 class Constructor;
232 class Filler;
233 class InternalizedString;
234 class JSArgumentsObject;
235 class JSContextExtensionObject;
236 class JSError;
237 class JSSloppyArgumentsObject;
238 class MapCache;
239 class MutableHeapNumber;
240 class NativeContext;
241 class NumberWrapper;
242 class ScriptWrapper;
243 class SloppyArgumentsElements;
244 class StringWrapper;
245 class SymbolWrapper;
246 class Undetectable;
247 class UniqueName;
248 class WasmExportedFunctionData;
249 class WasmGlobalObject;
250 class WasmMemoryObject;
251 class WasmModuleObject;
252 class WasmTableObject;
253 
254 template <class T>
255 struct ObjectTypeOf {};
256 
257 #define OBJECT_TYPE_CASE(Name)                           \
258   template <>                                            \
259   struct ObjectTypeOf<Name> {                            \
260     static const ObjectType value = ObjectType::k##Name; \
261   };
262 #define OBJECT_TYPE_STRUCT_CASE(NAME, Name, name)        \
263   template <>                                            \
264   struct ObjectTypeOf<Name> {                            \
265     static const ObjectType value = ObjectType::k##Name; \
266   };
267 #define OBJECT_TYPE_TEMPLATE_CASE(Name)                  \
268   template <class... Args>                               \
269   struct ObjectTypeOf<Name<Args...>> {                   \
270     static const ObjectType value = ObjectType::k##Name; \
271   };
272 OBJECT_TYPE_CASE(Object)
273 OBJECT_TYPE_LIST(OBJECT_TYPE_CASE)
274 HEAP_OBJECT_ORDINARY_TYPE_LIST(OBJECT_TYPE_CASE)
275 STRUCT_LIST(OBJECT_TYPE_STRUCT_CASE)
276 HEAP_OBJECT_TEMPLATE_TYPE_LIST(OBJECT_TYPE_TEMPLATE_CASE)
277 #undef OBJECT_TYPE_CASE
278 #undef OBJECT_TYPE_STRUCT_CASE
279 #undef OBJECT_TYPE_TEMPLATE_CASE
280 
281 Smi* CheckObjectType(Object* value, Smi* type, String* location);
282 
283 namespace compiler {
284 
285 class CallDescriptor;
286 class CodeAssemblerLabel;
287 class CodeAssemblerVariable;
288 template <class T>
289 class TypedCodeAssemblerVariable;
290 class CodeAssemblerState;
291 class Node;
292 class RawMachineAssembler;
293 class RawMachineLabel;
294 
295 typedef ZoneVector<CodeAssemblerVariable*> CodeAssemblerVariableList;
296 
297 typedef std::function<void()> CodeAssemblerCallback;
298 
299 template <class T, class U>
300 struct is_subtype {
301   static const bool value = std::is_base_of<U, T>::value;
302 };
303 template <class T1, class T2, class U>
304 struct is_subtype<UnionT<T1, T2>, U> {
305   static const bool value =
306       is_subtype<T1, U>::value && is_subtype<T2, U>::value;
307 };
308 template <class T, class U1, class U2>
309 struct is_subtype<T, UnionT<U1, U2>> {
310   static const bool value =
311       is_subtype<T, U1>::value || is_subtype<T, U2>::value;
312 };
313 template <class T1, class T2, class U1, class U2>
314 struct is_subtype<UnionT<T1, T2>, UnionT<U1, U2>> {
315   static const bool value =
316       (is_subtype<T1, U1>::value || is_subtype<T1, U2>::value) &&
317       (is_subtype<T2, U1>::value || is_subtype<T2, U2>::value);
318 };
319 
320 template <class T, class U>
321 struct types_have_common_values {
322   static const bool value = is_subtype<T, U>::value || is_subtype<U, T>::value;
323 };
324 template <class U>
325 struct types_have_common_values<Uint32T, U> {
326   static const bool value = types_have_common_values<Word32T, U>::value;
327 };
328 template <class U>
329 struct types_have_common_values<Int32T, U> {
330   static const bool value = types_have_common_values<Word32T, U>::value;
331 };
332 template <class U>
333 struct types_have_common_values<Uint64T, U> {
334   static const bool value = types_have_common_values<Word64T, U>::value;
335 };
336 template <class U>
337 struct types_have_common_values<Int64T, U> {
338   static const bool value = types_have_common_values<Word64T, U>::value;
339 };
340 template <class U>
341 struct types_have_common_values<IntPtrT, U> {
342   static const bool value = types_have_common_values<WordT, U>::value;
343 };
344 template <class U>
345 struct types_have_common_values<UintPtrT, U> {
346   static const bool value = types_have_common_values<WordT, U>::value;
347 };
348 template <class T1, class T2, class U>
349 struct types_have_common_values<UnionT<T1, T2>, U> {
350   static const bool value = types_have_common_values<T1, U>::value ||
351                             types_have_common_values<T2, U>::value;
352 };
353 
354 template <class T, class U1, class U2>
355 struct types_have_common_values<T, UnionT<U1, U2>> {
356   static const bool value = types_have_common_values<T, U1>::value ||
357                             types_have_common_values<T, U2>::value;
358 };
359 template <class T1, class T2, class U1, class U2>
360 struct types_have_common_values<UnionT<T1, T2>, UnionT<U1, U2>> {
361   static const bool value = types_have_common_values<T1, U1>::value ||
362                             types_have_common_values<T1, U2>::value ||
363                             types_have_common_values<T2, U1>::value ||
364                             types_have_common_values<T2, U2>::value;
365 };
366 
367 template <class T>
368 struct types_have_common_values<T, MaybeObject> {
369   static const bool value = types_have_common_values<T, Object>::value;
370 };
371 
372 template <class T>
373 struct types_have_common_values<MaybeObject, T> {
374   static const bool value = types_have_common_values<Object, T>::value;
375 };
376 
377 // TNode<T> is an SSA value with the static type tag T, which is one of the
378 // following:
379 //   - a subclass of internal::Object represents a tagged type
380 //   - a subclass of internal::UntaggedT represents an untagged type
381 //   - ExternalReference
382 //   - PairT<T1, T2> for an operation returning two values, with types T1
383 //     and T2
384 //   - UnionT<T1, T2> represents either a value of type T1 or of type T2.
385 template <class T>
386 class TNode {
387  public:
388   static_assert(is_valid_type_tag<T>::value, "invalid type tag");
389 
390   template <class U,
391             typename std::enable_if<is_subtype<U, T>::value, int>::type = 0>
392   TNode(const TNode<U>& other) : node_(other) {}
393   TNode() : node_(nullptr) {}
394 
395   TNode operator=(TNode other) {
396     DCHECK_NOT_NULL(other.node_);
397     node_ = other.node_;
398     return *this;
399   }
400 
401   operator compiler::Node*() const { return node_; }
402 
403   static TNode UncheckedCast(compiler::Node* node) { return TNode(node); }
404 
405  protected:
406   explicit TNode(compiler::Node* node) : node_(node) {}
407 
408  private:
409   compiler::Node* node_;
410 };
411 
412 // SloppyTNode<T> is a variant of TNode<T> and allows implicit casts from
413 // Node*. It is intended for function arguments as long as some call sites
414 // still use untyped Node* arguments.
415 // TODO(tebbi): Delete this class once transition is finished.
416 template <class T>
417 class SloppyTNode : public TNode<T> {
418  public:
419   SloppyTNode(compiler::Node* node)  // NOLINT(runtime/explicit)
420       : TNode<T>(node) {}
421   template <class U, typename std::enable_if<is_subtype<U, T>::value,
422                                              int>::type = 0>
423   SloppyTNode(const TNode<U>& other)  // NOLINT(runtime/explicit)
424       : TNode<T>(other) {}
425 };
426 
427 // This macro alias allows to use PairT<T1, T2> as a macro argument.
428 #define PAIR_TYPE(T1, T2) PairT<T1, T2>
429 
430 #define CODE_ASSEMBLER_COMPARE_BINARY_OP_LIST(V)          \
431   V(Float32Equal, BoolT, Float32T, Float32T)              \
432   V(Float32LessThan, BoolT, Float32T, Float32T)           \
433   V(Float32LessThanOrEqual, BoolT, Float32T, Float32T)    \
434   V(Float32GreaterThan, BoolT, Float32T, Float32T)        \
435   V(Float32GreaterThanOrEqual, BoolT, Float32T, Float32T) \
436   V(Float64Equal, BoolT, Float64T, Float64T)              \
437   V(Float64NotEqual, BoolT, Float64T, Float64T)           \
438   V(Float64LessThan, BoolT, Float64T, Float64T)           \
439   V(Float64LessThanOrEqual, BoolT, Float64T, Float64T)    \
440   V(Float64GreaterThan, BoolT, Float64T, Float64T)        \
441   V(Float64GreaterThanOrEqual, BoolT, Float64T, Float64T) \
442   /* Use Word32Equal if you need Int32Equal */            \
443   V(Int32GreaterThan, BoolT, Word32T, Word32T)            \
444   V(Int32GreaterThanOrEqual, BoolT, Word32T, Word32T)     \
445   V(Int32LessThan, BoolT, Word32T, Word32T)               \
446   V(Int32LessThanOrEqual, BoolT, Word32T, Word32T)        \
447   /* Use WordEqual if you need IntPtrEqual */             \
448   V(IntPtrLessThan, BoolT, WordT, WordT)                  \
449   V(IntPtrLessThanOrEqual, BoolT, WordT, WordT)           \
450   V(IntPtrGreaterThan, BoolT, WordT, WordT)               \
451   V(IntPtrGreaterThanOrEqual, BoolT, WordT, WordT)        \
452   /* Use Word32Equal if you need Uint32Equal */           \
453   V(Uint32LessThan, BoolT, Word32T, Word32T)              \
454   V(Uint32LessThanOrEqual, BoolT, Word32T, Word32T)       \
455   V(Uint32GreaterThan, BoolT, Word32T, Word32T)           \
456   V(Uint32GreaterThanOrEqual, BoolT, Word32T, Word32T)    \
457   /* Use WordEqual if you need UintPtrEqual */            \
458   V(UintPtrLessThan, BoolT, WordT, WordT)                 \
459   V(UintPtrLessThanOrEqual, BoolT, WordT, WordT)          \
460   V(UintPtrGreaterThan, BoolT, WordT, WordT)              \
461   V(UintPtrGreaterThanOrEqual, BoolT, WordT, WordT)
462 
463 #define CODE_ASSEMBLER_BINARY_OP_LIST(V)                                \
464   CODE_ASSEMBLER_COMPARE_BINARY_OP_LIST(V)                              \
465   V(Float64Add, Float64T, Float64T, Float64T)                           \
466   V(Float64Sub, Float64T, Float64T, Float64T)                           \
467   V(Float64Mul, Float64T, Float64T, Float64T)                           \
468   V(Float64Div, Float64T, Float64T, Float64T)                           \
469   V(Float64Mod, Float64T, Float64T, Float64T)                           \
470   V(Float64Atan2, Float64T, Float64T, Float64T)                         \
471   V(Float64Pow, Float64T, Float64T, Float64T)                           \
472   V(Float64Max, Float64T, Float64T, Float64T)                           \
473   V(Float64Min, Float64T, Float64T, Float64T)                           \
474   V(Float64InsertLowWord32, Float64T, Float64T, Word32T)                \
475   V(Float64InsertHighWord32, Float64T, Float64T, Word32T)               \
476   V(IntPtrAddWithOverflow, PAIR_TYPE(IntPtrT, BoolT), IntPtrT, IntPtrT) \
477   V(IntPtrSubWithOverflow, PAIR_TYPE(IntPtrT, BoolT), IntPtrT, IntPtrT) \
478   V(Int32Add, Word32T, Word32T, Word32T)                                \
479   V(Int32AddWithOverflow, PAIR_TYPE(Int32T, BoolT), Int32T, Int32T)     \
480   V(Int32Sub, Word32T, Word32T, Word32T)                                \
481   V(Int32SubWithOverflow, PAIR_TYPE(Int32T, BoolT), Int32T, Int32T)     \
482   V(Int32Mul, Word32T, Word32T, Word32T)                                \
483   V(Int32MulWithOverflow, PAIR_TYPE(Int32T, BoolT), Int32T, Int32T)     \
484   V(Int32Div, Int32T, Int32T, Int32T)                                   \
485   V(Int32Mod, Int32T, Int32T, Int32T)                                   \
486   V(WordRor, WordT, WordT, IntegralT)                                   \
487   V(Word32Ror, Word32T, Word32T, Word32T)                               \
488   V(Word64Ror, Word64T, Word64T, Word64T)
489 
490 TNode<Float64T> Float64Add(TNode<Float64T> a, TNode<Float64T> b);
491 
492 #define CODE_ASSEMBLER_UNARY_OP_LIST(V)                        \
493   V(Float64Abs, Float64T, Float64T)                            \
494   V(Float64Acos, Float64T, Float64T)                           \
495   V(Float64Acosh, Float64T, Float64T)                          \
496   V(Float64Asin, Float64T, Float64T)                           \
497   V(Float64Asinh, Float64T, Float64T)                          \
498   V(Float64Atan, Float64T, Float64T)                           \
499   V(Float64Atanh, Float64T, Float64T)                          \
500   V(Float64Cos, Float64T, Float64T)                            \
501   V(Float64Cosh, Float64T, Float64T)                           \
502   V(Float64Exp, Float64T, Float64T)                            \
503   V(Float64Expm1, Float64T, Float64T)                          \
504   V(Float64Log, Float64T, Float64T)                            \
505   V(Float64Log1p, Float64T, Float64T)                          \
506   V(Float64Log2, Float64T, Float64T)                           \
507   V(Float64Log10, Float64T, Float64T)                          \
508   V(Float64Cbrt, Float64T, Float64T)                           \
509   V(Float64Neg, Float64T, Float64T)                            \
510   V(Float64Sin, Float64T, Float64T)                            \
511   V(Float64Sinh, Float64T, Float64T)                           \
512   V(Float64Sqrt, Float64T, Float64T)                           \
513   V(Float64Tan, Float64T, Float64T)                            \
514   V(Float64Tanh, Float64T, Float64T)                           \
515   V(Float64ExtractLowWord32, Word32T, Float64T)                \
516   V(Float64ExtractHighWord32, Word32T, Float64T)               \
517   V(BitcastTaggedToWord, IntPtrT, Object)                      \
518   V(BitcastMaybeObjectToWord, IntPtrT, MaybeObject)            \
519   V(BitcastWordToTagged, Object, WordT)                        \
520   V(BitcastWordToTaggedSigned, Smi, WordT)                     \
521   V(TruncateFloat64ToFloat32, Float32T, Float64T)              \
522   V(TruncateFloat64ToWord32, Word32T, Float64T)                \
523   V(TruncateInt64ToInt32, Int32T, Int64T)                      \
524   V(ChangeFloat32ToFloat64, Float64T, Float32T)                \
525   V(ChangeFloat64ToUint32, Uint32T, Float64T)                  \
526   V(ChangeFloat64ToUint64, Uint64T, Float64T)                  \
527   V(ChangeInt32ToFloat64, Float64T, Int32T)                    \
528   V(ChangeInt32ToInt64, Int64T, Int32T)                        \
529   V(ChangeUint32ToFloat64, Float64T, Word32T)                  \
530   V(ChangeUint32ToUint64, Uint64T, Word32T)                    \
531   V(BitcastInt32ToFloat32, Float32T, Word32T)                  \
532   V(BitcastFloat32ToInt32, Word32T, Float32T)                  \
533   V(RoundFloat64ToInt32, Int32T, Float64T)                     \
534   V(RoundInt32ToFloat32, Int32T, Float32T)                     \
535   V(Float64SilenceNaN, Float64T, Float64T)                     \
536   V(Float64RoundDown, Float64T, Float64T)                      \
537   V(Float64RoundUp, Float64T, Float64T)                        \
538   V(Float64RoundTiesEven, Float64T, Float64T)                  \
539   V(Float64RoundTruncate, Float64T, Float64T)                  \
540   V(Word32Clz, Int32T, Word32T)                                \
541   V(Word32BitwiseNot, Word32T, Word32T)                        \
542   V(WordNot, WordT, WordT)                                     \
543   V(Int32AbsWithOverflow, PAIR_TYPE(Int32T, BoolT), Int32T)    \
544   V(Int64AbsWithOverflow, PAIR_TYPE(Int64T, BoolT), Int64T)    \
545   V(IntPtrAbsWithOverflow, PAIR_TYPE(IntPtrT, BoolT), IntPtrT) \
546   V(Word32BinaryNot, BoolT, Word32T)
547 
548 // A "public" interface used by components outside of compiler directory to
549 // create code objects with TurboFan's backend. This class is mostly a thin
550 // shim around the RawMachineAssembler, and its primary job is to ensure that
551 // the innards of the RawMachineAssembler and other compiler implementation
552 // details don't leak outside of the the compiler directory..
553 //
554 // V8 components that need to generate low-level code using this interface
555 // should include this header--and this header only--from the compiler
556 // directory (this is actually enforced). Since all interesting data
557 // structures are forward declared, it's not possible for clients to peek
558 // inside the compiler internals.
559 //
560 // In addition to providing isolation between TurboFan and code generation
561 // clients, CodeAssembler also provides an abstraction for creating variables
562 // and enhanced Label functionality to merge variable values along paths where
563 // they have differing values, including loops.
564 //
565 // The CodeAssembler itself is stateless (and instances are expected to be
566 // temporary-scoped and short-lived); all its state is encapsulated into
567 // a CodeAssemblerState instance.
568 class V8_EXPORT_PRIVATE CodeAssembler {
569  public:
570   explicit CodeAssembler(CodeAssemblerState* state) : state_(state) {}
571   ~CodeAssembler();
572 
573   static Handle<Code> GenerateCode(CodeAssemblerState* state,
574                                    const AssemblerOptions& options);
575 
576   bool Is64() const;
577   bool IsFloat64RoundUpSupported() const;
578   bool IsFloat64RoundDownSupported() const;
579   bool IsFloat64RoundTiesEvenSupported() const;
580   bool IsFloat64RoundTruncateSupported() const;
581   bool IsInt32AbsWithOverflowSupported() const;
582   bool IsInt64AbsWithOverflowSupported() const;
583   bool IsIntPtrAbsWithOverflowSupported() const;
584 
585   // Shortened aliases for use in CodeAssembler subclasses.
586   using Label = CodeAssemblerLabel;
587   using Variable = CodeAssemblerVariable;
588   template <class T>
589   using TVariable = TypedCodeAssemblerVariable<T>;
590   using VariableList = CodeAssemblerVariableList;
591 
592   // ===========================================================================
593   // Base Assembler
594   // ===========================================================================
595 
596   template <class PreviousType, bool FromTyped>
597   class CheckedNode {
598    public:
599 #ifdef DEBUG
600     CheckedNode(Node* node, CodeAssembler* code_assembler, const char* location)
601         : node_(node), code_assembler_(code_assembler), location_(location) {}
602 #else
603     CheckedNode(compiler::Node* node, CodeAssembler*, const char*)
604         : node_(node) {}
605 #endif
606 
607     template <class A>
608     operator TNode<A>() {
609       static_assert(
610           !std::is_same<A, MaybeObject>::value,
611           "Can't cast to MaybeObject, use explicit conversion functions. ");
612 
613       static_assert(types_have_common_values<A, PreviousType>::value,
614                     "Incompatible types: this cast can never succeed.");
615       static_assert(std::is_convertible<TNode<A>, TNode<Object>>::value,
616                     "Coercion to untagged values cannot be "
617                     "checked.");
618       static_assert(
619           !FromTyped ||
620               !std::is_convertible<TNode<PreviousType>, TNode<A>>::value,
621           "Unnecessary CAST: types are convertible.");
622 #ifdef DEBUG
623       if (FLAG_debug_code) {
624         if (std::is_same<PreviousType, MaybeObject>::value) {
625           code_assembler_->GenerateCheckMaybeObjectIsObject(node_, location_);
626         }
627         Node* function = code_assembler_->ExternalConstant(
628             ExternalReference::check_object_type());
629         code_assembler_->CallCFunction3(
630             MachineType::AnyTagged(), MachineType::AnyTagged(),
631             MachineType::TaggedSigned(), MachineType::AnyTagged(), function,
632             node_,
633             code_assembler_->SmiConstant(
634                 static_cast<int>(ObjectTypeOf<A>::value)),
635             code_assembler_->StringConstant(location_));
636       }
637 #endif
638       return TNode<A>::UncheckedCast(node_);
639     }
640 
641     template <class A>
642     operator SloppyTNode<A>() {
643       return implicit_cast<TNode<A>>(*this);
644     }
645 
646     Node* node() const { return node_; }
647 
648    private:
649     Node* node_;
650 #ifdef DEBUG
651     CodeAssembler* code_assembler_;
652     const char* location_;
653 #endif
654   };
655 
656   template <class T>
657   TNode<T> UncheckedCast(Node* value) {
658     return TNode<T>::UncheckedCast(value);
659   }
660   template <class T, class U>
661   TNode<T> UncheckedCast(TNode<U> value) {
662     static_assert(types_have_common_values<T, U>::value,
663                   "Incompatible types: this cast can never succeed.");
664     return TNode<T>::UncheckedCast(value);
665   }
666 
667   // ReinterpretCast<T>(v) has the power to cast even when the type of v is
668   // unrelated to T. Use with care.
669   template <class T>
670   TNode<T> ReinterpretCast(Node* value) {
671     return TNode<T>::UncheckedCast(value);
672   }
673 
674   CheckedNode<Object, false> Cast(Node* value, const char* location = "") {
675     return {value, this, location};
676   }
677 
678   template <class T>
679   CheckedNode<T, true> Cast(TNode<T> value, const char* location = "") {
680     return {value, this, location};
681   }
682 
683 #ifdef DEBUG
684 #define STRINGIFY(x) #x
685 #define TO_STRING_LITERAL(x) STRINGIFY(x)
686 #define CAST(x) \
687   Cast(x, "CAST(" #x ") at " __FILE__ ":" TO_STRING_LITERAL(__LINE__))
688 #else
689 #define CAST(x) Cast(x)
690 #endif
691 
692 #ifdef DEBUG
693   void GenerateCheckMaybeObjectIsObject(Node* node, const char* location);
694 #endif
695 
696   // Constants.
697   TNode<Int32T> Int32Constant(int32_t value);
698   TNode<Int64T> Int64Constant(int64_t value);
699   TNode<IntPtrT> IntPtrConstant(intptr_t value);
700   TNode<Number> NumberConstant(double value);
701   TNode<Smi> SmiConstant(Smi* value);
702   TNode<Smi> SmiConstant(int value);
703   template <typename E,
704             typename = typename std::enable_if<std::is_enum<E>::value>::type>
705   TNode<Smi> SmiConstant(E value) {
706     STATIC_ASSERT(sizeof(E) <= sizeof(int));
707     return SmiConstant(static_cast<int>(value));
708   }
709   TNode<HeapObject> UntypedHeapConstant(Handle<HeapObject> object);
710   template <class Type>
711   TNode<Type> HeapConstant(Handle<Type> object) {
712     return UncheckedCast<Type>(UntypedHeapConstant(object));
713   }
714   TNode<String> StringConstant(const char* str);
715   TNode<Oddball> BooleanConstant(bool value);
716   TNode<ExternalReference> ExternalConstant(ExternalReference address);
717   TNode<Float64T> Float64Constant(double value);
718   TNode<HeapNumber> NaNConstant();
719   TNode<BoolT> Int32TrueConstant() {
720     return ReinterpretCast<BoolT>(Int32Constant(1));
721   }
722   TNode<BoolT> Int32FalseConstant() {
723     return ReinterpretCast<BoolT>(Int32Constant(0));
724   }
725   TNode<BoolT> BoolConstant(bool value) {
726     return value ? Int32TrueConstant() : Int32FalseConstant();
727   }
728 
729   bool ToInt32Constant(Node* node, int32_t& out_value);
730   bool ToInt64Constant(Node* node, int64_t& out_value);
731   bool ToSmiConstant(Node* node, Smi*& out_value);
732   bool ToIntPtrConstant(Node* node, intptr_t& out_value);
733 
734   bool IsUndefinedConstant(TNode<Object> node);
735   bool IsNullConstant(TNode<Object> node);
736 
737   TNode<Int32T> Signed(TNode<Word32T> x) { return UncheckedCast<Int32T>(x); }
738   TNode<IntPtrT> Signed(TNode<WordT> x) { return UncheckedCast<IntPtrT>(x); }
739   TNode<Uint32T> Unsigned(TNode<Word32T> x) {
740     return UncheckedCast<Uint32T>(x);
741   }
742   TNode<UintPtrT> Unsigned(TNode<WordT> x) {
743     return UncheckedCast<UintPtrT>(x);
744   }
745 
746   static constexpr int kTargetParameterIndex = -1;
747 
748   Node* Parameter(int value);
749 
750   TNode<Context> GetJSContextParameter();
751   void Return(SloppyTNode<Object> value);
752   void Return(SloppyTNode<Object> value1, SloppyTNode<Object> value2);
753   void Return(SloppyTNode<Object> value1, SloppyTNode<Object> value2,
754               SloppyTNode<Object> value3);
755   void PopAndReturn(Node* pop, Node* value);
756 
757   void ReturnIf(Node* condition, Node* value);
758 
759   void ReturnRaw(Node* value);
760 
761   void DebugAbort(Node* message);
762   void DebugBreak();
763   void Unreachable();
764   void Comment(const char* format, ...);
765 
766   void Bind(Label* label);
767 #if DEBUG
768   void Bind(Label* label, AssemblerDebugInfo debug_info);
769 #endif  // DEBUG
770   void Goto(Label* label);
771   void GotoIf(SloppyTNode<IntegralT> condition, Label* true_label);
772   void GotoIfNot(SloppyTNode<IntegralT> condition, Label* false_label);
773   void Branch(SloppyTNode<IntegralT> condition, Label* true_label,
774               Label* false_label);
775 
776   void Branch(TNode<BoolT> condition, std::function<void()> true_body,
777               std::function<void()> false_body);
778   void Branch(TNode<BoolT> condition, Label* true_label,
779               std::function<void()> false_body);
780   void Branch(TNode<BoolT> condition, std::function<void()> true_body,
781               Label* false_label);
782 
783   void Switch(Node* index, Label* default_label, const int32_t* case_values,
784               Label** case_labels, size_t case_count);
785 
786   // Access to the frame pointer
787   Node* LoadFramePointer();
788   Node* LoadParentFramePointer();
789 
790   // Access to the stack pointer
791   Node* LoadStackPointer();
792 
793   // Poison |value| on speculative paths.
794   TNode<Object> TaggedPoisonOnSpeculation(SloppyTNode<Object> value);
795   TNode<WordT> WordPoisonOnSpeculation(SloppyTNode<WordT> value);
796 
797   // Load raw memory location.
798   Node* Load(MachineType rep, Node* base,
799              LoadSensitivity needs_poisoning = LoadSensitivity::kSafe);
800   template <class Type>
801   TNode<Type> Load(MachineType rep, TNode<RawPtr<Type>> base) {
802     DCHECK(
803         IsSubtype(rep.representation(), MachineRepresentationOf<Type>::value));
804     return UncheckedCast<Type>(Load(rep, static_cast<Node*>(base)));
805   }
806   Node* Load(MachineType rep, Node* base, Node* offset,
807              LoadSensitivity needs_poisoning = LoadSensitivity::kSafe);
808   Node* AtomicLoad(MachineType rep, Node* base, Node* offset);
809 
810   // Load a value from the root array.
811   TNode<Object> LoadRoot(Heap::RootListIndex root_index);
812 
813   // Store value to raw memory location.
814   Node* Store(Node* base, Node* value);
815   Node* Store(Node* base, Node* offset, Node* value);
816   Node* StoreWithMapWriteBarrier(Node* base, Node* offset, Node* value);
817   Node* StoreNoWriteBarrier(MachineRepresentation rep, Node* base, Node* value);
818   Node* StoreNoWriteBarrier(MachineRepresentation rep, Node* base, Node* offset,
819                             Node* value);
820   Node* AtomicStore(MachineRepresentation rep, Node* base, Node* offset,
821                     Node* value);
822 
823   // Exchange value at raw memory location
824   Node* AtomicExchange(MachineType type, Node* base, Node* offset, Node* value);
825 
826   // Compare and Exchange value at raw memory location
827   Node* AtomicCompareExchange(MachineType type, Node* base, Node* offset,
828                               Node* old_value, Node* new_value);
829 
830   Node* AtomicAdd(MachineType type, Node* base, Node* offset, Node* value);
831 
832   Node* AtomicSub(MachineType type, Node* base, Node* offset, Node* value);
833 
834   Node* AtomicAnd(MachineType type, Node* base, Node* offset, Node* value);
835 
836   Node* AtomicOr(MachineType type, Node* base, Node* offset, Node* value);
837 
838   Node* AtomicXor(MachineType type, Node* base, Node* offset, Node* value);
839 
840   // Store a value to the root array.
841   Node* StoreRoot(Heap::RootListIndex root_index, Node* value);
842 
843 // Basic arithmetic operations.
844 #define DECLARE_CODE_ASSEMBLER_BINARY_OP(name, ResType, Arg1Type, Arg2Type) \
845   TNode<ResType> name(SloppyTNode<Arg1Type> a, SloppyTNode<Arg2Type> b);
846   CODE_ASSEMBLER_BINARY_OP_LIST(DECLARE_CODE_ASSEMBLER_BINARY_OP)
847 #undef DECLARE_CODE_ASSEMBLER_BINARY_OP
848 
849   TNode<IntPtrT> WordShr(TNode<IntPtrT> left, TNode<IntegralT> right) {
850     return UncheckedCast<IntPtrT>(
851         WordShr(static_cast<Node*>(left), static_cast<Node*>(right)));
852   }
853 
854   TNode<IntPtrT> WordAnd(TNode<IntPtrT> left, TNode<IntPtrT> right) {
855     return UncheckedCast<IntPtrT>(
856         WordAnd(static_cast<Node*>(left), static_cast<Node*>(right)));
857   }
858 
859   template <class Left, class Right,
860             class = typename std::enable_if<
861                 std::is_base_of<Object, Left>::value &&
862                 std::is_base_of<Object, Right>::value>::type>
863   TNode<BoolT> WordEqual(TNode<Left> left, TNode<Right> right) {
864     return WordEqual(ReinterpretCast<WordT>(left),
865                      ReinterpretCast<WordT>(right));
866   }
867   TNode<BoolT> WordEqual(TNode<Object> left, Node* right) {
868     return WordEqual(ReinterpretCast<WordT>(left),
869                      ReinterpretCast<WordT>(right));
870   }
871   TNode<BoolT> WordEqual(Node* left, TNode<Object> right) {
872     return WordEqual(ReinterpretCast<WordT>(left),
873                      ReinterpretCast<WordT>(right));
874   }
875   template <class Left, class Right,
876             class = typename std::enable_if<
877                 std::is_base_of<Object, Left>::value &&
878                 std::is_base_of<Object, Right>::value>::type>
879   TNode<BoolT> WordNotEqual(TNode<Left> left, TNode<Right> right) {
880     return WordNotEqual(ReinterpretCast<WordT>(left),
881                         ReinterpretCast<WordT>(right));
882   }
883   TNode<BoolT> WordNotEqual(TNode<Object> left, Node* right) {
884     return WordNotEqual(ReinterpretCast<WordT>(left),
885                         ReinterpretCast<WordT>(right));
886   }
887   TNode<BoolT> WordNotEqual(Node* left, TNode<Object> right) {
888     return WordNotEqual(ReinterpretCast<WordT>(left),
889                         ReinterpretCast<WordT>(right));
890   }
891 
892   TNode<BoolT> IntPtrEqual(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
893   TNode<BoolT> WordEqual(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
894   TNode<BoolT> WordNotEqual(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
895   TNode<BoolT> Word32Equal(SloppyTNode<Word32T> left,
896                            SloppyTNode<Word32T> right);
897   TNode<BoolT> Word32NotEqual(SloppyTNode<Word32T> left,
898                               SloppyTNode<Word32T> right);
899   TNode<BoolT> Word64Equal(SloppyTNode<Word64T> left,
900                            SloppyTNode<Word64T> right);
901   TNode<BoolT> Word64NotEqual(SloppyTNode<Word64T> left,
902                               SloppyTNode<Word64T> right);
903 
904   TNode<Int32T> Int32Add(TNode<Int32T> left, TNode<Int32T> right) {
905     return Signed(
906         Int32Add(static_cast<Node*>(left), static_cast<Node*>(right)));
907   }
908 
909   TNode<WordT> IntPtrAdd(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
910   TNode<WordT> IntPtrSub(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
911   TNode<WordT> IntPtrMul(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
912   TNode<IntPtrT> IntPtrAdd(TNode<IntPtrT> left, TNode<IntPtrT> right) {
913     return Signed(
914         IntPtrAdd(static_cast<Node*>(left), static_cast<Node*>(right)));
915   }
916   TNode<IntPtrT> IntPtrSub(TNode<IntPtrT> left, TNode<IntPtrT> right) {
917     return Signed(
918         IntPtrSub(static_cast<Node*>(left), static_cast<Node*>(right)));
919   }
920   TNode<IntPtrT> IntPtrMul(TNode<IntPtrT> left, TNode<IntPtrT> right) {
921     return Signed(
922         IntPtrMul(static_cast<Node*>(left), static_cast<Node*>(right)));
923   }
924 
925   TNode<WordT> WordShl(SloppyTNode<WordT> value, int shift);
926   TNode<WordT> WordShr(SloppyTNode<WordT> value, int shift);
927   TNode<WordT> WordSar(SloppyTNode<WordT> value, int shift);
928   TNode<IntPtrT> WordShr(TNode<IntPtrT> value, int shift) {
929     return UncheckedCast<IntPtrT>(WordShr(static_cast<Node*>(value), shift));
930   }
931   TNode<Word32T> Word32Shr(SloppyTNode<Word32T> value, int shift);
932 
933   TNode<WordT> WordOr(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
934   TNode<WordT> WordAnd(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
935   TNode<WordT> WordXor(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
936   TNode<WordT> WordShl(SloppyTNode<WordT> left, SloppyTNode<IntegralT> right);
937   TNode<WordT> WordShr(SloppyTNode<WordT> left, SloppyTNode<IntegralT> right);
938   TNode<WordT> WordSar(SloppyTNode<WordT> left, SloppyTNode<IntegralT> right);
939   TNode<Word32T> Word32Or(SloppyTNode<Word32T> left,
940                           SloppyTNode<Word32T> right);
941   TNode<Word32T> Word32And(SloppyTNode<Word32T> left,
942                            SloppyTNode<Word32T> right);
943   TNode<Word32T> Word32Xor(SloppyTNode<Word32T> left,
944                            SloppyTNode<Word32T> right);
945   TNode<Word32T> Word32Shl(SloppyTNode<Word32T> left,
946                            SloppyTNode<Word32T> right);
947   TNode<Word32T> Word32Shr(SloppyTNode<Word32T> left,
948                            SloppyTNode<Word32T> right);
949   TNode<Word32T> Word32Sar(SloppyTNode<Word32T> left,
950                            SloppyTNode<Word32T> right);
951   TNode<Word64T> Word64Or(SloppyTNode<Word64T> left,
952                           SloppyTNode<Word64T> right);
953   TNode<Word64T> Word64And(SloppyTNode<Word64T> left,
954                            SloppyTNode<Word64T> right);
955   TNode<Word64T> Word64Xor(SloppyTNode<Word64T> left,
956                            SloppyTNode<Word64T> right);
957   TNode<Word64T> Word64Shl(SloppyTNode<Word64T> left,
958                            SloppyTNode<Word64T> right);
959   TNode<Word64T> Word64Shr(SloppyTNode<Word64T> left,
960                            SloppyTNode<Word64T> right);
961   TNode<Word64T> Word64Sar(SloppyTNode<Word64T> left,
962                            SloppyTNode<Word64T> right);
963 
964 // Unary
965 #define DECLARE_CODE_ASSEMBLER_UNARY_OP(name, ResType, ArgType) \
966   TNode<ResType> name(SloppyTNode<ArgType> a);
967   CODE_ASSEMBLER_UNARY_OP_LIST(DECLARE_CODE_ASSEMBLER_UNARY_OP)
968 #undef DECLARE_CODE_ASSEMBLER_UNARY_OP
969 
970   // Changes a double to an inptr_t for pointer arithmetic outside of Smi range.
971   // Assumes that the double can be exactly represented as an int.
972   TNode<UintPtrT> ChangeFloat64ToUintPtr(SloppyTNode<Float64T> value);
973 
974   // Changes an intptr_t to a double, e.g. for storing an element index
975   // outside Smi range in a HeapNumber. Lossless on 32-bit,
976   // rounds on 64-bit (which doesn't affect valid element indices).
977   Node* RoundIntPtrToFloat64(Node* value);
978   // No-op on 32-bit, otherwise zero extend.
979   TNode<UintPtrT> ChangeUint32ToWord(SloppyTNode<Word32T> value);
980   // No-op on 32-bit, otherwise sign extend.
981   TNode<IntPtrT> ChangeInt32ToIntPtr(SloppyTNode<Word32T> value);
982 
983   // No-op that guarantees that the value is kept alive till this point even
984   // if GC happens.
985   Node* Retain(Node* value);
986 
987   // Projections
988   Node* Projection(int index, Node* value);
989 
990   template <int index, class T1, class T2>
991   TNode<typename std::tuple_element<index, std::tuple<T1, T2>>::type>
992   Projection(TNode<PairT<T1, T2>> value) {
993     return UncheckedCast<
994         typename std::tuple_element<index, std::tuple<T1, T2>>::type>(
995         Projection(index, value));
996   }
997 
998   // Calls
999   template <class... TArgs>
1000   TNode<Object> CallRuntime(Runtime::FunctionId function,
1001                             SloppyTNode<Object> context, TArgs... args) {
1002     return CallRuntimeImpl(function, context,
1003                            {implicit_cast<SloppyTNode<Object>>(args)...});
1004   }
1005 
1006   template <class... TArgs>
1007   TNode<Object> CallRuntimeWithCEntry(Runtime::FunctionId function,
1008                                       TNode<Code> centry,
1009                                       SloppyTNode<Object> context,
1010                                       TArgs... args) {
1011     return CallRuntimeWithCEntryImpl(function, centry, context, {args...});
1012   }
1013 
1014   template <class... TArgs>
1015   void TailCallRuntime(Runtime::FunctionId function,
1016                        SloppyTNode<Object> context, TArgs... args) {
1017     int argc = static_cast<int>(sizeof...(args));
1018     TNode<Int32T> arity = Int32Constant(argc);
1019     return TailCallRuntimeImpl(function, arity, context,
1020                                {implicit_cast<SloppyTNode<Object>>(args)...});
1021   }
1022 
1023   template <class... TArgs>
1024   void TailCallRuntime(Runtime::FunctionId function, TNode<Int32T> arity,
1025                        SloppyTNode<Object> context, TArgs... args) {
1026     return TailCallRuntimeImpl(function, arity, context,
1027                                {implicit_cast<SloppyTNode<Object>>(args)...});
1028   }
1029 
1030   template <class... TArgs>
1031   void TailCallRuntimeWithCEntry(Runtime::FunctionId function,
1032                                  TNode<Code> centry, TNode<Object> context,
1033                                  TArgs... args) {
1034     int argc = sizeof...(args);
1035     TNode<Int32T> arity = Int32Constant(argc);
1036     return TailCallRuntimeWithCEntryImpl(
1037         function, arity, centry, context,
1038         {implicit_cast<SloppyTNode<Object>>(args)...});
1039   }
1040 
1041   //
1042   // If context passed to CallStub is nullptr, it won't be passed to the stub.
1043   //
1044 
1045   template <class T = Object, class... TArgs>
1046   TNode<T> CallStub(Callable const& callable, SloppyTNode<Object> context,
1047                     TArgs... args) {
1048     TNode<Code> target = HeapConstant(callable.code());
1049     return CallStub<T>(callable.descriptor(), target, context, args...);
1050   }
1051 
1052   template <class T = Object, class... TArgs>
1053   TNode<T> CallStub(const CallInterfaceDescriptor& descriptor,
1054                     SloppyTNode<Code> target, SloppyTNode<Object> context,
1055                     TArgs... args) {
1056     return UncheckedCast<T>(CallStubR(descriptor, 1, target, context, args...));
1057   }
1058 
1059   template <class... TArgs>
1060   Node* CallStubR(const CallInterfaceDescriptor& descriptor, size_t result_size,
1061                   SloppyTNode<Code> target, SloppyTNode<Object> context,
1062                   TArgs... args) {
1063     return CallStubRImpl(descriptor, result_size, target, context, {args...});
1064   }
1065 
1066   Node* CallStubN(const CallInterfaceDescriptor& descriptor, size_t result_size,
1067                   int input_count, Node* const* inputs);
1068 
1069   template <class... TArgs>
1070   void TailCallStub(Callable const& callable, SloppyTNode<Object> context,
1071                     TArgs... args) {
1072     TNode<Code> target = HeapConstant(callable.code());
1073     return TailCallStub(callable.descriptor(), target, context, args...);
1074   }
1075 
1076   template <class... TArgs>
1077   void TailCallStub(const CallInterfaceDescriptor& descriptor,
1078                     SloppyTNode<Code> target, SloppyTNode<Object> context,
1079                     TArgs... args) {
1080     return TailCallStubImpl(descriptor, target, context, {args...});
1081   }
1082 
1083   template <class... TArgs>
1084   Node* TailCallBytecodeDispatch(const CallInterfaceDescriptor& descriptor,
1085                                  Node* target, TArgs... args);
1086 
1087   template <class... TArgs>
1088   Node* TailCallStubThenBytecodeDispatch(
1089       const CallInterfaceDescriptor& descriptor, Node* target, Node* context,
1090       TArgs... args) {
1091     return TailCallStubThenBytecodeDispatchImpl(descriptor, target, context,
1092                                                 {args...});
1093   }
1094 
1095   // Tailcalls to the given code object with JSCall linkage. The JS arguments
1096   // (including receiver) are supposed to be already on the stack.
1097   // This is a building block for implementing trampoline stubs that are
1098   // installed instead of code objects with JSCall linkage.
1099   // Note that no arguments adaption is going on here - all the JavaScript
1100   // arguments are left on the stack unmodified. Therefore, this tail call can
1101   // only be used after arguments adaptation has been performed already.
1102   TNode<Object> TailCallJSCode(TNode<Code> code, TNode<Context> context,
1103                                TNode<JSFunction> function,
1104                                TNode<Object> new_target,
1105                                TNode<Int32T> arg_count);
1106 
1107   template <class... TArgs>
1108   Node* CallJS(Callable const& callable, Node* context, Node* function,
1109                Node* receiver, TArgs... args) {
1110     int argc = static_cast<int>(sizeof...(args));
1111     Node* arity = Int32Constant(argc);
1112     return CallStub(callable, context, function, arity, receiver, args...);
1113   }
1114 
1115   template <class... TArgs>
1116   Node* ConstructJS(Callable const& callable, Node* context, Node* new_target,
1117                     TArgs... args) {
1118     int argc = static_cast<int>(sizeof...(args));
1119     Node* arity = Int32Constant(argc);
1120     Node* receiver = LoadRoot(Heap::kUndefinedValueRootIndex);
1121 
1122     // Construct(target, new_target, arity, receiver, arguments...)
1123     return CallStub(callable, context, new_target, new_target, arity, receiver,
1124                     args...);
1125   }
1126 
1127   Node* CallCFunctionN(Signature<MachineType>* signature, int input_count,
1128                        Node* const* inputs);
1129 
1130   // Call to a C function with one argument.
1131   Node* CallCFunction1(MachineType return_type, MachineType arg0_type,
1132                        Node* function, Node* arg0);
1133 
1134   // Call to a C function with one argument, while saving/restoring caller
1135   // registers except the register used for return value.
1136   Node* CallCFunction1WithCallerSavedRegisters(MachineType return_type,
1137                                                MachineType arg0_type,
1138                                                Node* function, Node* arg0,
1139                                                SaveFPRegsMode mode);
1140 
1141   // Call to a C function with two arguments.
1142   Node* CallCFunction2(MachineType return_type, MachineType arg0_type,
1143                        MachineType arg1_type, Node* function, Node* arg0,
1144                        Node* arg1);
1145 
1146   // Call to a C function with three arguments.
1147   Node* CallCFunction3(MachineType return_type, MachineType arg0_type,
1148                        MachineType arg1_type, MachineType arg2_type,
1149                        Node* function, Node* arg0, Node* arg1, Node* arg2);
1150 
1151   // Call to a C function with three arguments, while saving/restoring caller
1152   // registers except the register used for return value.
1153   Node* CallCFunction3WithCallerSavedRegisters(
1154       MachineType return_type, MachineType arg0_type, MachineType arg1_type,
1155       MachineType arg2_type, Node* function, Node* arg0, Node* arg1, Node* arg2,
1156       SaveFPRegsMode mode);
1157 
1158   // Call to a C function with four arguments.
1159   Node* CallCFunction4(MachineType return_type, MachineType arg0_type,
1160                        MachineType arg1_type, MachineType arg2_type,
1161                        MachineType arg3_type, Node* function, Node* arg0,
1162                        Node* arg1, Node* arg2, Node* arg3);
1163 
1164   // Call to a C function with five arguments.
1165   Node* CallCFunction5(MachineType return_type, MachineType arg0_type,
1166                        MachineType arg1_type, MachineType arg2_type,
1167                        MachineType arg3_type, MachineType arg4_type,
1168                        Node* function, Node* arg0, Node* arg1, Node* arg2,
1169                        Node* arg3, Node* arg4);
1170 
1171   // Call to a C function with six arguments.
1172   Node* CallCFunction6(MachineType return_type, MachineType arg0_type,
1173                        MachineType arg1_type, MachineType arg2_type,
1174                        MachineType arg3_type, MachineType arg4_type,
1175                        MachineType arg5_type, Node* function, Node* arg0,
1176                        Node* arg1, Node* arg2, Node* arg3, Node* arg4,
1177                        Node* arg5);
1178 
1179   // Call to a C function with nine arguments.
1180   Node* CallCFunction9(MachineType return_type, MachineType arg0_type,
1181                        MachineType arg1_type, MachineType arg2_type,
1182                        MachineType arg3_type, MachineType arg4_type,
1183                        MachineType arg5_type, MachineType arg6_type,
1184                        MachineType arg7_type, MachineType arg8_type,
1185                        Node* function, Node* arg0, Node* arg1, Node* arg2,
1186                        Node* arg3, Node* arg4, Node* arg5, Node* arg6,
1187                        Node* arg7, Node* arg8);
1188 
1189   // Exception handling support.
1190   void GotoIfException(Node* node, Label* if_exception,
1191                        Variable* exception_var = nullptr);
1192 
1193   // Helpers which delegate to RawMachineAssembler.
1194   Factory* factory() const;
1195   Isolate* isolate() const;
1196   Zone* zone() const;
1197 
1198   CodeAssemblerState* state() { return state_; }
1199 
1200   void BreakOnNode(int node_id);
1201 
1202   bool UnalignedLoadSupported(MachineRepresentation rep) const;
1203   bool UnalignedStoreSupported(MachineRepresentation rep) const;
1204 
1205  protected:
1206   void RegisterCallGenerationCallbacks(
1207       const CodeAssemblerCallback& call_prologue,
1208       const CodeAssemblerCallback& call_epilogue);
1209   void UnregisterCallGenerationCallbacks();
1210 
1211   bool Word32ShiftIsSafe() const;
1212   PoisoningMitigationLevel poisoning_level() const;
1213 
1214   bool IsJSFunctionCall() const;
1215 
1216  private:
1217   TNode<Object> CallRuntimeImpl(Runtime::FunctionId function,
1218                                 TNode<Object> context,
1219                                 std::initializer_list<TNode<Object>> args);
1220 
1221   TNode<Object> CallRuntimeWithCEntryImpl(
1222       Runtime::FunctionId function, TNode<Code> centry, TNode<Object> context,
1223       std::initializer_list<TNode<Object>> args);
1224 
1225   void TailCallRuntimeImpl(Runtime::FunctionId function, TNode<Int32T> arity,
1226                            TNode<Object> context,
1227                            std::initializer_list<TNode<Object>> args);
1228 
1229   void TailCallRuntimeWithCEntryImpl(Runtime::FunctionId function,
1230                                      TNode<Int32T> arity, TNode<Code> centry,
1231                                      TNode<Object> context,
1232                                      std::initializer_list<TNode<Object>> args);
1233 
1234   void TailCallStubImpl(const CallInterfaceDescriptor& descriptor,
1235                         TNode<Code> target, TNode<Object> context,
1236                         std::initializer_list<Node*> args);
1237 
1238   Node* TailCallStubThenBytecodeDispatchImpl(
1239       const CallInterfaceDescriptor& descriptor, Node* target, Node* context,
1240       std::initializer_list<Node*> args);
1241 
1242   Node* CallStubRImpl(const CallInterfaceDescriptor& descriptor,
1243                       size_t result_size, SloppyTNode<Code> target,
1244                       SloppyTNode<Object> context,
1245                       std::initializer_list<Node*> args);
1246 
1247   // These two don't have definitions and are here only for catching use cases
1248   // where the cast is not necessary.
1249   TNode<Int32T> Signed(TNode<Int32T> x);
1250   TNode<Uint32T> Unsigned(TNode<Uint32T> x);
1251 
1252   RawMachineAssembler* raw_assembler() const;
1253 
1254   // Calls respective callback registered in the state.
1255   void CallPrologue();
1256   void CallEpilogue();
1257 
1258   CodeAssemblerState* state_;
1259 
1260   DISALLOW_COPY_AND_ASSIGN(CodeAssembler);
1261 };
1262 
1263 class CodeAssemblerVariable {
1264  public:
1265   explicit CodeAssemblerVariable(CodeAssembler* assembler,
1266                                  MachineRepresentation rep);
1267   CodeAssemblerVariable(CodeAssembler* assembler, MachineRepresentation rep,
1268                         Node* initial_value);
1269 #if DEBUG
1270   CodeAssemblerVariable(CodeAssembler* assembler, AssemblerDebugInfo debug_info,
1271                         MachineRepresentation rep);
1272   CodeAssemblerVariable(CodeAssembler* assembler, AssemblerDebugInfo debug_info,
1273                         MachineRepresentation rep, Node* initial_value);
1274 #endif  // DEBUG
1275 
1276   ~CodeAssemblerVariable();
1277   void Bind(Node* value);
1278   Node* value() const;
1279   MachineRepresentation rep() const;
1280   bool IsBound() const;
1281 
1282  private:
1283   class Impl;
1284   friend class CodeAssemblerLabel;
1285   friend class CodeAssemblerState;
1286   friend std::ostream& operator<<(std::ostream&, const Impl&);
1287   friend std::ostream& operator<<(std::ostream&, const CodeAssemblerVariable&);
1288   Impl* impl_;
1289   CodeAssemblerState* state_;
1290   DISALLOW_COPY_AND_ASSIGN(CodeAssemblerVariable);
1291 };
1292 
1293 std::ostream& operator<<(std::ostream&, const CodeAssemblerVariable&);
1294 std::ostream& operator<<(std::ostream&, const CodeAssemblerVariable::Impl&);
1295 
1296 template <class T>
1297 class TypedCodeAssemblerVariable : public CodeAssemblerVariable {
1298  public:
1299   TypedCodeAssemblerVariable(TNode<T> initial_value, CodeAssembler* assembler)
1300       : CodeAssemblerVariable(assembler, MachineRepresentationOf<T>::value,
1301                               initial_value) {}
1302   explicit TypedCodeAssemblerVariable(CodeAssembler* assembler)
1303       : CodeAssemblerVariable(assembler, MachineRepresentationOf<T>::value) {}
1304 #if DEBUG
1305   TypedCodeAssemblerVariable(AssemblerDebugInfo debug_info,
1306                              CodeAssembler* assembler)
1307       : CodeAssemblerVariable(assembler, debug_info,
1308                               MachineRepresentationOf<T>::value) {}
1309   TypedCodeAssemblerVariable(AssemblerDebugInfo debug_info,
1310                              TNode<T> initial_value, CodeAssembler* assembler)
1311       : CodeAssemblerVariable(assembler, debug_info,
1312                               MachineRepresentationOf<T>::value,
1313                               initial_value) {}
1314 #endif  // DEBUG
1315 
1316   TNode<T> value() const {
1317     return TNode<T>::UncheckedCast(CodeAssemblerVariable::value());
1318   }
1319 
1320   void operator=(TNode<T> value) { Bind(value); }
1321   void operator=(const TypedCodeAssemblerVariable<T>& variable) {
1322     Bind(variable.value());
1323   }
1324 
1325  private:
1326   using CodeAssemblerVariable::Bind;
1327 };
1328 
1329 class CodeAssemblerLabel {
1330  public:
1331   enum Type { kDeferred, kNonDeferred };
1332 
1333   explicit CodeAssemblerLabel(
1334       CodeAssembler* assembler,
1335       CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred)
1336       : CodeAssemblerLabel(assembler, 0, nullptr, type) {}
1337   CodeAssemblerLabel(
1338       CodeAssembler* assembler,
1339       const CodeAssemblerVariableList& merged_variables,
1340       CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred)
1341       : CodeAssemblerLabel(assembler, merged_variables.size(),
1342                            &(merged_variables[0]), type) {}
1343   CodeAssemblerLabel(
1344       CodeAssembler* assembler, size_t count,
1345       CodeAssemblerVariable* const* vars,
1346       CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred);
1347   CodeAssemblerLabel(
1348       CodeAssembler* assembler,
1349       std::initializer_list<CodeAssemblerVariable*> vars,
1350       CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred)
1351       : CodeAssemblerLabel(assembler, vars.size(), vars.begin(), type) {}
1352   CodeAssemblerLabel(
1353       CodeAssembler* assembler, CodeAssemblerVariable* merged_variable,
1354       CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred)
1355       : CodeAssemblerLabel(assembler, 1, &merged_variable, type) {}
1356   ~CodeAssemblerLabel();
1357 
1358   inline bool is_bound() const { return bound_; }
1359   inline bool is_used() const { return merge_count_ != 0; }
1360 
1361  private:
1362   friend class CodeAssembler;
1363 
1364   void Bind();
1365 #if DEBUG
1366   void Bind(AssemblerDebugInfo debug_info);
1367 #endif  // DEBUG
1368   void UpdateVariablesAfterBind();
1369   void MergeVariables();
1370 
1371   bool bound_;
1372   size_t merge_count_;
1373   CodeAssemblerState* state_;
1374   RawMachineLabel* label_;
1375   // Map of variables that need to be merged to their phi nodes (or placeholders
1376   // for those phis).
1377   std::map<CodeAssemblerVariable::Impl*, Node*> variable_phis_;
1378   // Map of variables to the list of value nodes that have been added from each
1379   // merge path in their order of merging.
1380   std::map<CodeAssemblerVariable::Impl*, std::vector<Node*>> variable_merges_;
1381 };
1382 
1383 class V8_EXPORT_PRIVATE CodeAssemblerState {
1384  public:
1385   // Create with CallStub linkage.
1386   // |result_size| specifies the number of results returned by the stub.
1387   // TODO(rmcilroy): move result_size to the CallInterfaceDescriptor.
1388   CodeAssemblerState(Isolate* isolate, Zone* zone,
1389                      const CallInterfaceDescriptor& descriptor, Code::Kind kind,
1390                      const char* name, PoisoningMitigationLevel poisoning_level,
1391                      uint32_t stub_key = 0,
1392                      int32_t builtin_index = Builtins::kNoBuiltinId);
1393 
1394   // Create with JSCall linkage.
1395   CodeAssemblerState(Isolate* isolate, Zone* zone, int parameter_count,
1396                      Code::Kind kind, const char* name,
1397                      PoisoningMitigationLevel poisoning_level,
1398                      int32_t builtin_index = Builtins::kNoBuiltinId);
1399 
1400   ~CodeAssemblerState();
1401 
1402   const char* name() const { return name_; }
1403   int parameter_count() const;
1404 
1405 #if DEBUG
1406   void PrintCurrentBlock(std::ostream& os);
1407   bool InsideBlock();
1408 #endif  // DEBUG
1409   void SetInitialDebugInformation(const char* msg, const char* file, int line);
1410 
1411  private:
1412   friend class CodeAssembler;
1413   friend class CodeAssemblerLabel;
1414   friend class CodeAssemblerVariable;
1415   friend class CodeAssemblerTester;
1416 
1417   CodeAssemblerState(Isolate* isolate, Zone* zone,
1418                      CallDescriptor* call_descriptor, Code::Kind kind,
1419                      const char* name, PoisoningMitigationLevel poisoning_level,
1420                      uint32_t stub_key, int32_t builtin_index);
1421 
1422   std::unique_ptr<RawMachineAssembler> raw_assembler_;
1423   Code::Kind kind_;
1424   const char* name_;
1425   uint32_t stub_key_;
1426   int32_t builtin_index_;
1427   bool code_generated_;
1428   ZoneSet<CodeAssemblerVariable::Impl*> variables_;
1429   CodeAssemblerCallback call_prologue_;
1430   CodeAssemblerCallback call_epilogue_;
1431 
1432   DISALLOW_COPY_AND_ASSIGN(CodeAssemblerState);
1433 };
1434 
1435 }  // namespace compiler
1436 }  // namespace internal
1437 }  // namespace v8
1438 
1439 #endif  // V8_COMPILER_CODE_ASSEMBLER_H_
1440