• 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 <initializer_list>
9 #include <map>
10 #include <memory>
11 #include <sstream>
12 #include <type_traits>
13 
14 // Clients of this interface shouldn't depend on lots of compiler internals.
15 // Do not include anything from src/compiler here!
16 #include "include/cppgc/source-location.h"
17 #include "src/base/macros.h"
18 #include "src/base/optional.h"
19 #include "src/builtins/builtins.h"
20 #include "src/codegen/atomic-memory-order.h"
21 #include "src/codegen/code-factory.h"
22 #include "src/codegen/machine-type.h"
23 #include "src/codegen/source-position.h"
24 #include "src/codegen/tnode.h"
25 #include "src/heap/heap.h"
26 #include "src/objects/arguments.h"
27 #include "src/objects/data-handler.h"
28 #include "src/objects/heap-number.h"
29 #include "src/objects/js-array-buffer.h"
30 #include "src/objects/js-collection.h"
31 #include "src/objects/js-proxy.h"
32 #include "src/objects/map.h"
33 #include "src/objects/maybe-object.h"
34 #include "src/objects/object-type.h"
35 #include "src/objects/objects.h"
36 #include "src/objects/oddball.h"
37 #include "src/objects/smi.h"
38 #include "src/objects/tagged-index.h"
39 #include "src/runtime/runtime.h"
40 #include "src/utils/allocation.h"
41 #include "src/zone/zone-containers.h"
42 
43 namespace v8 {
44 namespace internal {
45 
46 // Forward declarations.
47 class AsmWasmData;
48 class AsyncGeneratorRequest;
49 struct AssemblerOptions;
50 class BigInt;
51 class CallInterfaceDescriptor;
52 class Callable;
53 class Factory;
54 class InterpreterData;
55 class Isolate;
56 class JSAsyncFunctionObject;
57 class JSAsyncGeneratorObject;
58 class JSCollator;
59 class JSCollection;
60 class JSDateTimeFormat;
61 class JSDisplayNames;
62 class JSListFormat;
63 class JSLocale;
64 class JSNumberFormat;
65 class JSPluralRules;
66 class JSRegExpStringIterator;
67 class JSRelativeTimeFormat;
68 class JSSegmentIterator;
69 class JSSegmenter;
70 class JSSegments;
71 class JSV8BreakIterator;
72 class JSWeakCollection;
73 class JSFinalizationRegistry;
74 class JSWeakMap;
75 class JSWeakRef;
76 class JSWeakSet;
77 class ProfileDataFromFile;
78 class PromiseCapability;
79 class PromiseFulfillReactionJobTask;
80 class PromiseReaction;
81 class PromiseReactionJobTask;
82 class PromiseRejectReactionJobTask;
83 class Zone;
84 #define MAKE_FORWARD_DECLARATION(Name) class Name;
85 TORQUE_DEFINED_CLASS_LIST(MAKE_FORWARD_DECLARATION)
86 #undef MAKE_FORWARD_DECLARATION
87 
88 template <typename T>
89 class Signature;
90 
91 enum class CheckBounds { kAlways, kDebugOnly };
NeedsBoundsCheck(CheckBounds check_bounds)92 inline bool NeedsBoundsCheck(CheckBounds check_bounds) {
93   switch (check_bounds) {
94     case CheckBounds::kAlways:
95       return true;
96     case CheckBounds::kDebugOnly:
97       return DEBUG_BOOL;
98   }
99 }
100 
101 enum class StoreToObjectWriteBarrier { kNone, kMap, kFull };
102 
103 class AccessCheckNeeded;
104 class BigIntBase;
105 class BigIntWrapper;
106 class ClassBoilerplate;
107 class BooleanWrapper;
108 class CompilationCacheTable;
109 class Constructor;
110 class Filler;
111 class FunctionTemplateRareData;
112 class HeapNumber;
113 class InternalizedString;
114 class JSArgumentsObject;
115 class JSArrayBufferView;
116 class JSContextExtensionObject;
117 class JSError;
118 class JSSloppyArgumentsObject;
119 class MapCache;
120 class NativeContext;
121 class NumberWrapper;
122 class ScriptWrapper;
123 class SloppyArgumentsElements;
124 class StringWrapper;
125 class SymbolWrapper;
126 class Undetectable;
127 class UniqueName;
128 class WasmCapiFunctionData;
129 class WasmTagObject;
130 class WasmExceptionPackage;
131 class WasmExceptionTag;
132 class WasmExportedFunctionData;
133 class WasmGlobalObject;
134 class WasmIndirectFunctionTable;
135 class WasmJSFunctionData;
136 class WasmMemoryObject;
137 class WasmModuleObject;
138 class WasmTableObject;
139 
140 template <class T>
141 struct ObjectTypeOf {};
142 
143 #define OBJECT_TYPE_CASE(Name)                           \
144   template <>                                            \
145   struct ObjectTypeOf<Name> {                            \
146     static const ObjectType value = ObjectType::k##Name; \
147   };
148 #define OBJECT_TYPE_STRUCT_CASE(NAME, Name, name)        \
149   template <>                                            \
150   struct ObjectTypeOf<Name> {                            \
151     static const ObjectType value = ObjectType::k##Name; \
152   };
153 #define OBJECT_TYPE_TEMPLATE_CASE(Name)                  \
154   template <class... Args>                               \
155   struct ObjectTypeOf<Name<Args...>> {                   \
156     static const ObjectType value = ObjectType::k##Name; \
157   };
158 OBJECT_TYPE_CASE(Object)
159 OBJECT_TYPE_CASE(Smi)
160 OBJECT_TYPE_CASE(TaggedIndex)
161 OBJECT_TYPE_CASE(HeapObject)
162 OBJECT_TYPE_LIST(OBJECT_TYPE_CASE)
163 HEAP_OBJECT_ORDINARY_TYPE_LIST(OBJECT_TYPE_CASE)
164 STRUCT_LIST(OBJECT_TYPE_STRUCT_CASE)
165 HEAP_OBJECT_TEMPLATE_TYPE_LIST(OBJECT_TYPE_TEMPLATE_CASE)
166 #undef OBJECT_TYPE_CASE
167 #undef OBJECT_TYPE_STRUCT_CASE
168 #undef OBJECT_TYPE_TEMPLATE_CASE
169 
170 #if defined(V8_HOST_ARCH_32_BIT)
171 #define BINT_IS_SMI
172 using BInt = Smi;
173 using AtomicInt64 = PairT<IntPtrT, IntPtrT>;
174 using AtomicUint64 = PairT<UintPtrT, UintPtrT>;
175 #elif defined(V8_HOST_ARCH_64_BIT)
176 #define BINT_IS_INTPTR
177 using BInt = IntPtrT;
178 using AtomicInt64 = IntPtrT;
179 using AtomicUint64 = UintPtrT;
180 #else
181 #error Unknown architecture.
182 #endif
183 
184 namespace compiler {
185 
186 class CallDescriptor;
187 class CodeAssemblerLabel;
188 class CodeAssemblerVariable;
189 template <class T>
190 class TypedCodeAssemblerVariable;
191 class CodeAssemblerState;
192 class JSGraph;
193 class Node;
194 class RawMachineAssembler;
195 class RawMachineLabel;
196 class SourcePositionTable;
197 
198 using CodeAssemblerVariableList = ZoneVector<CodeAssemblerVariable*>;
199 
200 using CodeAssemblerCallback = std::function<void()>;
201 
202 template <class... Types>
203 class CodeAssemblerParameterizedLabel;
204 
205 // This macro alias allows to use PairT<T1, T2> as a macro argument.
206 #define PAIR_TYPE(T1, T2) PairT<T1, T2>
207 
208 #define CODE_ASSEMBLER_COMPARE_BINARY_OP_LIST(V)          \
209   V(Float32Equal, BoolT, Float32T, Float32T)              \
210   V(Float32LessThan, BoolT, Float32T, Float32T)           \
211   V(Float32LessThanOrEqual, BoolT, Float32T, Float32T)    \
212   V(Float32GreaterThan, BoolT, Float32T, Float32T)        \
213   V(Float32GreaterThanOrEqual, BoolT, Float32T, Float32T) \
214   V(Float64Equal, BoolT, Float64T, Float64T)              \
215   V(Float64NotEqual, BoolT, Float64T, Float64T)           \
216   V(Float64LessThan, BoolT, Float64T, Float64T)           \
217   V(Float64LessThanOrEqual, BoolT, Float64T, Float64T)    \
218   V(Float64GreaterThan, BoolT, Float64T, Float64T)        \
219   V(Float64GreaterThanOrEqual, BoolT, Float64T, Float64T) \
220   /* Use Word32Equal if you need Int32Equal */            \
221   V(Int32GreaterThan, BoolT, Word32T, Word32T)            \
222   V(Int32GreaterThanOrEqual, BoolT, Word32T, Word32T)     \
223   V(Int32LessThan, BoolT, Word32T, Word32T)               \
224   V(Int32LessThanOrEqual, BoolT, Word32T, Word32T)        \
225   /* Use WordEqual if you need IntPtrEqual */             \
226   V(IntPtrLessThan, BoolT, WordT, WordT)                  \
227   V(IntPtrLessThanOrEqual, BoolT, WordT, WordT)           \
228   V(IntPtrGreaterThan, BoolT, WordT, WordT)               \
229   V(IntPtrGreaterThanOrEqual, BoolT, WordT, WordT)        \
230   /* Use Word32Equal if you need Uint32Equal */           \
231   V(Uint32LessThan, BoolT, Word32T, Word32T)              \
232   V(Uint32LessThanOrEqual, BoolT, Word32T, Word32T)       \
233   V(Uint32GreaterThan, BoolT, Word32T, Word32T)           \
234   V(Uint32GreaterThanOrEqual, BoolT, Word32T, Word32T)    \
235   /* Use WordEqual if you need UintPtrEqual */            \
236   V(UintPtrLessThan, BoolT, WordT, WordT)                 \
237   V(UintPtrLessThanOrEqual, BoolT, WordT, WordT)          \
238   V(UintPtrGreaterThan, BoolT, WordT, WordT)              \
239   V(UintPtrGreaterThanOrEqual, BoolT, WordT, WordT)
240 
241 #define CODE_ASSEMBLER_BINARY_OP_LIST(V)                                \
242   CODE_ASSEMBLER_COMPARE_BINARY_OP_LIST(V)                              \
243   V(Float64Add, Float64T, Float64T, Float64T)                           \
244   V(Float64Sub, Float64T, Float64T, Float64T)                           \
245   V(Float64Mul, Float64T, Float64T, Float64T)                           \
246   V(Float64Div, Float64T, Float64T, Float64T)                           \
247   V(Float64Mod, Float64T, Float64T, Float64T)                           \
248   V(Float64Atan2, Float64T, Float64T, Float64T)                         \
249   V(Float64Pow, Float64T, Float64T, Float64T)                           \
250   V(Float64Max, Float64T, Float64T, Float64T)                           \
251   V(Float64Min, Float64T, Float64T, Float64T)                           \
252   V(Float64InsertLowWord32, Float64T, Float64T, Word32T)                \
253   V(Float64InsertHighWord32, Float64T, Float64T, Word32T)               \
254   V(I8x16Eq, I8x16T, I8x16T, I8x16T)                                    \
255   V(IntPtrAdd, WordT, WordT, WordT)                                     \
256   V(IntPtrSub, WordT, WordT, WordT)                                     \
257   V(IntPtrMul, WordT, WordT, WordT)                                     \
258   V(IntPtrDiv, IntPtrT, IntPtrT, IntPtrT)                               \
259   V(IntPtrAddWithOverflow, PAIR_TYPE(IntPtrT, BoolT), IntPtrT, IntPtrT) \
260   V(IntPtrSubWithOverflow, PAIR_TYPE(IntPtrT, BoolT), IntPtrT, IntPtrT) \
261   V(Int32Add, Word32T, Word32T, Word32T)                                \
262   V(Int32AddWithOverflow, PAIR_TYPE(Int32T, BoolT), Int32T, Int32T)     \
263   V(Int32Sub, Word32T, Word32T, Word32T)                                \
264   V(Int32SubWithOverflow, PAIR_TYPE(Int32T, BoolT), Int32T, Int32T)     \
265   V(Int32Mul, Word32T, Word32T, Word32T)                                \
266   V(Int32MulWithOverflow, PAIR_TYPE(Int32T, BoolT), Int32T, Int32T)     \
267   V(Int32Div, Int32T, Int32T, Int32T)                                   \
268   V(Int32Mod, Int32T, Int32T, Int32T)                                   \
269   V(Int64Add, Word64T, Word64T, Word64T)                                \
270   V(Int64Sub, Word64T, Word64T, Word64T)                                \
271   V(Int64SubWithOverflow, PAIR_TYPE(Int64T, BoolT), Int64T, Int64T)     \
272   V(Int64Mul, Word64T, Word64T, Word64T)                                \
273   V(Int64Div, Int64T, Int64T, Int64T)                                   \
274   V(Int64Mod, Int64T, Int64T, Int64T)                                   \
275   V(WordOr, WordT, WordT, WordT)                                        \
276   V(WordAnd, WordT, WordT, WordT)                                       \
277   V(WordXor, WordT, WordT, WordT)                                       \
278   V(WordRor, WordT, WordT, IntegralT)                                   \
279   V(WordShl, WordT, WordT, IntegralT)                                   \
280   V(WordShr, WordT, WordT, IntegralT)                                   \
281   V(WordSar, WordT, WordT, IntegralT)                                   \
282   V(WordSarShiftOutZeros, WordT, WordT, IntegralT)                      \
283   V(Word32Or, Word32T, Word32T, Word32T)                                \
284   V(Word32And, Word32T, Word32T, Word32T)                               \
285   V(Word32Xor, Word32T, Word32T, Word32T)                               \
286   V(Word32Ror, Word32T, Word32T, Word32T)                               \
287   V(Word32Shl, Word32T, Word32T, Word32T)                               \
288   V(Word32Shr, Word32T, Word32T, Word32T)                               \
289   V(Word32Sar, Word32T, Word32T, Word32T)                               \
290   V(Word32SarShiftOutZeros, Word32T, Word32T, Word32T)                  \
291   V(Word64And, Word64T, Word64T, Word64T)                               \
292   V(Word64Or, Word64T, Word64T, Word64T)                                \
293   V(Word64Xor, Word64T, Word64T, Word64T)                               \
294   V(Word64Shl, Word64T, Word64T, Word64T)                               \
295   V(Word64Shr, Word64T, Word64T, Word64T)                               \
296   V(Word64Sar, Word64T, Word64T, Word64T)
297 
298 TNode<Float64T> Float64Add(TNode<Float64T> a, TNode<Float64T> b);
299 
300 #define CODE_ASSEMBLER_UNARY_OP_LIST(V)                        \
301   V(Float64Abs, Float64T, Float64T)                            \
302   V(Float64Acos, Float64T, Float64T)                           \
303   V(Float64Acosh, Float64T, Float64T)                          \
304   V(Float64Asin, Float64T, Float64T)                           \
305   V(Float64Asinh, Float64T, Float64T)                          \
306   V(Float64Atan, Float64T, Float64T)                           \
307   V(Float64Atanh, Float64T, Float64T)                          \
308   V(Float64Cos, Float64T, Float64T)                            \
309   V(Float64Cosh, Float64T, Float64T)                           \
310   V(Float64Exp, Float64T, Float64T)                            \
311   V(Float64Expm1, Float64T, Float64T)                          \
312   V(Float64Log, Float64T, Float64T)                            \
313   V(Float64Log1p, Float64T, Float64T)                          \
314   V(Float64Log2, Float64T, Float64T)                           \
315   V(Float64Log10, Float64T, Float64T)                          \
316   V(Float64Cbrt, Float64T, Float64T)                           \
317   V(Float64Neg, Float64T, Float64T)                            \
318   V(Float64Sin, Float64T, Float64T)                            \
319   V(Float64Sinh, Float64T, Float64T)                           \
320   V(Float64Sqrt, Float64T, Float64T)                           \
321   V(Float64Tan, Float64T, Float64T)                            \
322   V(Float64Tanh, Float64T, Float64T)                           \
323   V(Float64ExtractLowWord32, Uint32T, Float64T)                \
324   V(Float64ExtractHighWord32, Uint32T, Float64T)               \
325   V(BitcastTaggedToWord, IntPtrT, Object)                      \
326   V(BitcastTaggedToWordForTagAndSmiBits, IntPtrT, AnyTaggedT)  \
327   V(BitcastMaybeObjectToWord, IntPtrT, MaybeObject)            \
328   V(BitcastWordToTagged, Object, WordT)                        \
329   V(BitcastWordToTaggedSigned, Smi, WordT)                     \
330   V(TruncateFloat64ToFloat32, Float32T, Float64T)              \
331   V(TruncateFloat64ToWord32, Uint32T, Float64T)                \
332   V(TruncateInt64ToInt32, Int32T, Int64T)                      \
333   V(ChangeFloat32ToFloat64, Float64T, Float32T)                \
334   V(ChangeFloat64ToUint32, Uint32T, Float64T)                  \
335   V(ChangeFloat64ToUint64, Uint64T, Float64T)                  \
336   V(ChangeInt32ToFloat64, Float64T, Int32T)                    \
337   V(ChangeInt32ToInt64, Int64T, Int32T)                        \
338   V(ChangeUint32ToFloat64, Float64T, Word32T)                  \
339   V(ChangeUint32ToUint64, Uint64T, Word32T)                    \
340   V(BitcastInt32ToFloat32, Float32T, Word32T)                  \
341   V(BitcastFloat32ToInt32, Uint32T, Float32T)                  \
342   V(RoundFloat64ToInt32, Int32T, Float64T)                     \
343   V(RoundInt32ToFloat32, Float32T, Int32T)                     \
344   V(Float64SilenceNaN, Float64T, Float64T)                     \
345   V(Float64RoundDown, Float64T, Float64T)                      \
346   V(Float64RoundUp, Float64T, Float64T)                        \
347   V(Float64RoundTiesEven, Float64T, Float64T)                  \
348   V(Float64RoundTruncate, Float64T, Float64T)                  \
349   V(Word32Clz, Int32T, Word32T)                                \
350   V(Word64Clz, Int64T, Word64T)                                \
351   V(Word32Ctz, Int32T, Word32T)                                \
352   V(Word64Ctz, Int64T, Word64T)                                \
353   V(Word32Popcnt, Int32T, Word32T)                             \
354   V(Word64Popcnt, Int64T, Word64T)                             \
355   V(Word32BitwiseNot, Word32T, Word32T)                        \
356   V(WordNot, WordT, WordT)                                     \
357   V(Word64Not, Word64T, Word64T)                               \
358   V(I8x16BitMask, Int32T, I8x16T)                              \
359   V(I8x16Splat, I8x16T, Int32T)                                \
360   V(Int32AbsWithOverflow, PAIR_TYPE(Int32T, BoolT), Int32T)    \
361   V(Int64AbsWithOverflow, PAIR_TYPE(Int64T, BoolT), Int64T)    \
362   V(IntPtrAbsWithOverflow, PAIR_TYPE(IntPtrT, BoolT), IntPtrT) \
363   V(Word32BinaryNot, BoolT, Word32T)                           \
364   V(StackPointerGreaterThan, BoolT, WordT)
365 
366 // A "public" interface used by components outside of compiler directory to
367 // create code objects with TurboFan's backend. This class is mostly a thin
368 // shim around the RawMachineAssembler, and its primary job is to ensure that
369 // the innards of the RawMachineAssembler and other compiler implementation
370 // details don't leak outside of the the compiler directory..
371 //
372 // V8 components that need to generate low-level code using this interface
373 // should include this header--and this header only--from the compiler
374 // directory (this is actually enforced). Since all interesting data
375 // structures are forward declared, it's not possible for clients to peek
376 // inside the compiler internals.
377 //
378 // In addition to providing isolation between TurboFan and code generation
379 // clients, CodeAssembler also provides an abstraction for creating variables
380 // and enhanced Label functionality to merge variable values along paths where
381 // they have differing values, including loops.
382 //
383 // The CodeAssembler itself is stateless (and instances are expected to be
384 // temporary-scoped and short-lived); all its state is encapsulated into
385 // a CodeAssemblerState instance.
386 class V8_EXPORT_PRIVATE CodeAssembler {
387  public:
CodeAssembler(CodeAssemblerState * state)388   explicit CodeAssembler(CodeAssemblerState* state) : state_(state) {}
389   ~CodeAssembler();
390 
391   CodeAssembler(const CodeAssembler&) = delete;
392   CodeAssembler& operator=(const CodeAssembler&) = delete;
393 
394   static Handle<Code> GenerateCode(CodeAssemblerState* state,
395                                    const AssemblerOptions& options,
396                                    const ProfileDataFromFile* profile_data);
397   bool Is64() const;
398   bool Is32() const;
399   bool IsFloat64RoundUpSupported() const;
400   bool IsFloat64RoundDownSupported() const;
401   bool IsFloat64RoundTiesEvenSupported() const;
402   bool IsFloat64RoundTruncateSupported() const;
403   bool IsInt32AbsWithOverflowSupported() const;
404   bool IsInt64AbsWithOverflowSupported() const;
405   bool IsIntPtrAbsWithOverflowSupported() const;
406   bool IsWord32PopcntSupported() const;
407   bool IsWord64PopcntSupported() const;
408   bool IsWord32CtzSupported() const;
409   bool IsWord64CtzSupported() const;
410 
411   // Shortened aliases for use in CodeAssembler subclasses.
412   using Label = CodeAssemblerLabel;
413   template <class T>
414   using TVariable = TypedCodeAssemblerVariable<T>;
415   using VariableList = CodeAssemblerVariableList;
416 
417   // ===========================================================================
418   // Base Assembler
419   // ===========================================================================
420 
421   template <class PreviousType, bool FromTyped>
422   class CheckedNode {
423    public:
424 #ifdef DEBUG
CheckedNode(Node * node,CodeAssembler * code_assembler,const char * location)425     CheckedNode(Node* node, CodeAssembler* code_assembler, const char* location)
426         : node_(node), code_assembler_(code_assembler), location_(location) {}
427 #else
428     CheckedNode(compiler::Node* node, CodeAssembler*, const char*)
429         : node_(node) {}
430 #endif
431 
432     template <class A>
433     operator TNode<A>() {
434       static_assert(
435           !std::is_same<A, MaybeObject>::value,
436           "Can't cast to MaybeObject, use explicit conversion functions. ");
437 
438       static_assert(types_have_common_values<A, PreviousType>::value,
439                     "Incompatible types: this cast can never succeed.");
440       static_assert(std::is_convertible<TNode<A>, TNode<Object>>::value,
441                     "Coercion to untagged values cannot be "
442                     "checked.");
443       static_assert(
444           !FromTyped ||
445               !std::is_convertible<TNode<PreviousType>, TNode<A>>::value,
446           "Unnecessary CAST: types are convertible.");
447 #ifdef DEBUG
448       if (FLAG_debug_code) {
449         if (std::is_same<PreviousType, MaybeObject>::value) {
450           code_assembler_->GenerateCheckMaybeObjectIsObject(
451               TNode<MaybeObject>::UncheckedCast(node_), location_);
452         }
453         TNode<ExternalReference> function = code_assembler_->ExternalConstant(
454             ExternalReference::check_object_type());
455         code_assembler_->CallCFunction(
456             function, MachineType::AnyTagged(),
457             std::make_pair(MachineType::AnyTagged(), node_),
458             std::make_pair(MachineType::TaggedSigned(),
459                            code_assembler_->SmiConstant(
460                                static_cast<int>(ObjectTypeOf<A>::value))),
461             std::make_pair(MachineType::AnyTagged(),
462                            code_assembler_->StringConstant(location_)));
463       }
464 #endif
465       return TNode<A>::UncheckedCast(node_);
466     }
467 
node()468     Node* node() const { return node_; }
469 
470    private:
471     Node* node_;
472 #ifdef DEBUG
473     CodeAssembler* code_assembler_;
474     const char* location_;
475 #endif
476   };
477 
478   template <class T>
UncheckedCast(Node * value)479   TNode<T> UncheckedCast(Node* value) {
480     return TNode<T>::UncheckedCast(value);
481   }
482   template <class T, class U>
UncheckedCast(TNode<U> value)483   TNode<T> UncheckedCast(TNode<U> value) {
484     static_assert(types_have_common_values<T, U>::value,
485                   "Incompatible types: this cast can never succeed.");
486     return TNode<T>::UncheckedCast(value);
487   }
488 
489   // ReinterpretCast<T>(v) has the power to cast even when the type of v is
490   // unrelated to T. Use with care.
491   template <class T>
ReinterpretCast(Node * value)492   TNode<T> ReinterpretCast(Node* value) {
493     return TNode<T>::UncheckedCast(value);
494   }
495 
496   CheckedNode<Object, false> Cast(Node* value, const char* location = "") {
497     return {value, this, location};
498   }
499 
500   template <class T>
501   CheckedNode<T, true> Cast(TNode<T> value, const char* location = "") {
502     return {value, this, location};
503   }
504 
505 #ifdef DEBUG
506 #define STRINGIFY(x) #x
507 #define TO_STRING_LITERAL(x) STRINGIFY(x)
508 #define CAST(x) \
509   Cast(x, "CAST(" #x ") at " __FILE__ ":" TO_STRING_LITERAL(__LINE__))
510 #define TORQUE_CAST(x) \
511   ca_.Cast(x, "CAST(" #x ") at " __FILE__ ":" TO_STRING_LITERAL(__LINE__))
512 #else
513 #define CAST(x) Cast(x)
514 #define TORQUE_CAST(x) ca_.Cast(x)
515 #endif
516 
517 #ifdef DEBUG
518   void GenerateCheckMaybeObjectIsObject(TNode<MaybeObject> node,
519                                         const char* location);
520 #endif
521 
522   // Constants.
523   TNode<Int32T> Int32Constant(int32_t value);
524   TNode<Int64T> Int64Constant(int64_t value);
Uint64Constant(uint64_t value)525   TNode<Uint64T> Uint64Constant(uint64_t value) {
526     return Unsigned(Int64Constant(bit_cast<int64_t>(value)));
527   }
528   TNode<IntPtrT> IntPtrConstant(intptr_t value);
Uint32Constant(uint32_t value)529   TNode<Uint32T> Uint32Constant(uint32_t value) {
530     return Unsigned(Int32Constant(bit_cast<int32_t>(value)));
531   }
UintPtrConstant(uintptr_t value)532   TNode<UintPtrT> UintPtrConstant(uintptr_t value) {
533     return Unsigned(IntPtrConstant(bit_cast<intptr_t>(value)));
534   }
535   TNode<TaggedIndex> TaggedIndexConstant(intptr_t value);
PointerConstant(void * value)536   TNode<RawPtrT> PointerConstant(void* value) {
537     return ReinterpretCast<RawPtrT>(IntPtrConstant(bit_cast<intptr_t>(value)));
538   }
539   TNode<Number> NumberConstant(double value);
540   TNode<Smi> SmiConstant(Smi value);
541   TNode<Smi> SmiConstant(int value);
542   template <typename E,
543             typename = typename std::enable_if<std::is_enum<E>::value>::type>
SmiConstant(E value)544   TNode<Smi> SmiConstant(E value) {
545     STATIC_ASSERT(sizeof(E) <= sizeof(int));
546     return SmiConstant(static_cast<int>(value));
547   }
548   TNode<HeapObject> UntypedHeapConstant(Handle<HeapObject> object);
549   template <class Type>
HeapConstant(Handle<Type> object)550   TNode<Type> HeapConstant(Handle<Type> object) {
551     return UncheckedCast<Type>(UntypedHeapConstant(object));
552   }
553   TNode<String> StringConstant(const char* str);
554   TNode<Oddball> BooleanConstant(bool value);
555   TNode<ExternalReference> ExternalConstant(ExternalReference address);
556   TNode<Float32T> Float32Constant(double value);
557   TNode<Float64T> Float64Constant(double value);
Int32TrueConstant()558   TNode<BoolT> Int32TrueConstant() {
559     return ReinterpretCast<BoolT>(Int32Constant(1));
560   }
Int32FalseConstant()561   TNode<BoolT> Int32FalseConstant() {
562     return ReinterpretCast<BoolT>(Int32Constant(0));
563   }
BoolConstant(bool value)564   TNode<BoolT> BoolConstant(bool value) {
565     return value ? Int32TrueConstant() : Int32FalseConstant();
566   }
567 
568   bool IsMapOffsetConstant(Node* node);
569 
570   bool TryToInt32Constant(TNode<IntegralT> node, int32_t* out_value);
571   bool TryToInt64Constant(TNode<IntegralT> node, int64_t* out_value);
572   bool TryToIntPtrConstant(TNode<IntegralT> node, intptr_t* out_value);
573   bool TryToIntPtrConstant(TNode<Smi> tnode, intptr_t* out_value);
574   bool TryToSmiConstant(TNode<IntegralT> node, Smi* out_value);
575   bool TryToSmiConstant(TNode<Smi> node, Smi* out_value);
576 
577   bool IsUndefinedConstant(TNode<Object> node);
578   bool IsNullConstant(TNode<Object> node);
579 
Signed(TNode<Word32T> x)580   TNode<Int32T> Signed(TNode<Word32T> x) { return UncheckedCast<Int32T>(x); }
Signed(TNode<Word64T> x)581   TNode<Int64T> Signed(TNode<Word64T> x) { return UncheckedCast<Int64T>(x); }
Signed(TNode<WordT> x)582   TNode<IntPtrT> Signed(TNode<WordT> x) { return UncheckedCast<IntPtrT>(x); }
Unsigned(TNode<Word32T> x)583   TNode<Uint32T> Unsigned(TNode<Word32T> x) {
584     return UncheckedCast<Uint32T>(x);
585   }
Unsigned(TNode<Word64T> x)586   TNode<Uint64T> Unsigned(TNode<Word64T> x) {
587     return UncheckedCast<Uint64T>(x);
588   }
Unsigned(TNode<WordT> x)589   TNode<UintPtrT> Unsigned(TNode<WordT> x) {
590     return UncheckedCast<UintPtrT>(x);
591   }
592 
593   static constexpr int kTargetParameterIndex = -1;
594 
595   template <class T>
596   TNode<T> Parameter(
597       int value, cppgc::SourceLocation loc = cppgc::SourceLocation::Current()) {
598     static_assert(
599         std::is_convertible<TNode<T>, TNode<Object>>::value,
600         "Parameter is only for tagged types. Use UncheckedParameter instead.");
601     std::stringstream message;
602     message << "Parameter " << value;
603     if (loc.FileName()) {
604       message << " at " << loc.FileName() << ":" << loc.Line();
605     }
606     size_t buf_size = message.str().size() + 1;
607     char* message_dup = zone()->NewArray<char>(buf_size);
608     snprintf(message_dup, buf_size, "%s", message.str().c_str());
609 
610     return Cast(UntypedParameter(value), message_dup);
611   }
612 
613   template <class T>
UncheckedParameter(int value)614   TNode<T> UncheckedParameter(int value) {
615     return UncheckedCast<T>(UntypedParameter(value));
616   }
617 
618   Node* UntypedParameter(int value);
619 
620   TNode<Context> GetJSContextParameter();
621   void Return(TNode<Object> value);
622   void Return(TNode<Object> value1, TNode<Object> value2);
623   void Return(TNode<Object> value1, TNode<Object> value2, TNode<Object> value3);
624   void Return(TNode<Int32T> value);
625   void Return(TNode<Uint32T> value);
626   void Return(TNode<WordT> value);
627   void Return(TNode<Float32T> value);
628   void Return(TNode<Float64T> value);
629   void Return(TNode<WordT> value1, TNode<WordT> value2);
630   void Return(TNode<WordT> value1, TNode<Object> value2);
631   void PopAndReturn(Node* pop, Node* value);
632 
633   void ReturnIf(TNode<BoolT> condition, TNode<Object> value);
634 
635   void AbortCSADcheck(Node* message);
636   void DebugBreak();
637   void Unreachable();
Comment(const char * msg)638   void Comment(const char* msg) {
639     if (!FLAG_code_comments) return;
640     Comment(std::string(msg));
641   }
642   void Comment(std::string msg);
643   template <class... Args>
Comment(Args &&...args)644   void Comment(Args&&... args) {
645     if (!FLAG_code_comments) return;
646     std::ostringstream s;
647     USE((s << std::forward<Args>(args))...);
648     Comment(s.str());
649   }
650 
651   void StaticAssert(TNode<BoolT> value,
652                     const char* source = "unknown position");
653 
654   // The following methods refer to source positions in CSA or Torque code
655   // compiled during mksnapshot, not JS compiled at runtime.
656   void SetSourcePosition(const char* file, int line);
657   void PushSourcePosition();
658   void PopSourcePosition();
659   class V8_NODISCARD SourcePositionScope {
660    public:
SourcePositionScope(CodeAssembler * ca)661     explicit SourcePositionScope(CodeAssembler* ca) : ca_(ca) {
662       ca->PushSourcePosition();
663     }
~SourcePositionScope()664     ~SourcePositionScope() { ca_->PopSourcePosition(); }
665 
666    private:
667     CodeAssembler* ca_;
668   };
669   const std::vector<FileAndLine>& GetMacroSourcePositionStack() const;
670 
671   void Bind(Label* label);
672 #if DEBUG
673   void Bind(Label* label, AssemblerDebugInfo debug_info);
674 #endif  // DEBUG
675   void Goto(Label* label);
676   void GotoIf(TNode<IntegralT> condition, Label* true_label);
677   void GotoIfNot(TNode<IntegralT> condition, Label* false_label);
678   void Branch(TNode<IntegralT> condition, Label* true_label,
679               Label* false_label);
680 
681   template <class T>
Uninitialized()682   TNode<T> Uninitialized() {
683     return {};
684   }
685 
686   template <class... T>
Bind(CodeAssemblerParameterizedLabel<T...> * label,TNode<T> * ...phis)687   void Bind(CodeAssemblerParameterizedLabel<T...>* label, TNode<T>*... phis) {
688     Bind(label->plain_label());
689     label->CreatePhis(phis...);
690   }
691   template <class... T, class... Args>
Branch(TNode<BoolT> condition,CodeAssemblerParameterizedLabel<T...> * if_true,CodeAssemblerParameterizedLabel<T...> * if_false,Args...args)692   void Branch(TNode<BoolT> condition,
693               CodeAssemblerParameterizedLabel<T...>* if_true,
694               CodeAssemblerParameterizedLabel<T...>* if_false, Args... args) {
695     if_true->AddInputs(args...);
696     if_false->AddInputs(args...);
697     Branch(condition, if_true->plain_label(), if_false->plain_label());
698   }
699   template <class... T, class... U>
Branch(TNode<BoolT> condition,CodeAssemblerParameterizedLabel<T...> * if_true,std::vector<Node * > args_true,CodeAssemblerParameterizedLabel<U...> * if_false,std::vector<Node * > args_false)700   void Branch(TNode<BoolT> condition,
701               CodeAssemblerParameterizedLabel<T...>* if_true,
702               std::vector<Node*> args_true,
703               CodeAssemblerParameterizedLabel<U...>* if_false,
704               std::vector<Node*> args_false) {
705     if_true->AddInputsVector(std::move(args_true));
706     if_false->AddInputsVector(std::move(args_false));
707     Branch(condition, if_true->plain_label(), if_false->plain_label());
708   }
709 
710   template <class... T, class... Args>
Goto(CodeAssemblerParameterizedLabel<T...> * label,Args...args)711   void Goto(CodeAssemblerParameterizedLabel<T...>* label, Args... args) {
712     label->AddInputs(args...);
713     Goto(label->plain_label());
714   }
715 
716   void Branch(TNode<BoolT> condition, const std::function<void()>& true_body,
717               const std::function<void()>& false_body);
718   void Branch(TNode<BoolT> condition, Label* true_label,
719               const std::function<void()>& false_body);
720   void Branch(TNode<BoolT> condition, const std::function<void()>& true_body,
721               Label* false_label);
722 
723   void Switch(Node* index, Label* default_label, const int32_t* case_values,
724               Label** case_labels, size_t case_count);
725 
726   // Access to the frame pointer
727   TNode<RawPtrT> LoadFramePointer();
728   TNode<RawPtrT> LoadParentFramePointer();
729 
730   // Load raw memory location.
731   Node* Load(MachineType type, Node* base);
732   template <class Type>
Load(MachineType type,TNode<RawPtr<Type>> base)733   TNode<Type> Load(MachineType type, TNode<RawPtr<Type>> base) {
734     DCHECK(
735         IsSubtype(type.representation(), MachineRepresentationOf<Type>::value));
736     return UncheckedCast<Type>(Load(type, static_cast<Node*>(base)));
737   }
738   Node* Load(MachineType type, Node* base, Node* offset);
739   template <class Type>
Load(Node * base)740   TNode<Type> Load(Node* base) {
741     return UncheckedCast<Type>(Load(MachineTypeOf<Type>::value, base));
742   }
743   template <class Type>
Load(Node * base,TNode<WordT> offset)744   TNode<Type> Load(Node* base, TNode<WordT> offset) {
745     return UncheckedCast<Type>(Load(MachineTypeOf<Type>::value, base, offset));
746   }
747   template <class Type>
AtomicLoad(AtomicMemoryOrder order,TNode<RawPtrT> base,TNode<WordT> offset)748   TNode<Type> AtomicLoad(AtomicMemoryOrder order, TNode<RawPtrT> base,
749                          TNode<WordT> offset) {
750     return UncheckedCast<Type>(
751         AtomicLoad(MachineTypeOf<Type>::value, order, base, offset));
752   }
753   template <class Type>
754   TNode<Type> AtomicLoad64(AtomicMemoryOrder order, TNode<RawPtrT> base,
755                            TNode<WordT> offset);
756   // Load uncompressed tagged value from (most likely off JS heap) memory
757   // location.
758   TNode<Object> LoadFullTagged(Node* base);
759   TNode<Object> LoadFullTagged(Node* base, TNode<IntPtrT> offset);
760 
761   Node* LoadFromObject(MachineType type, TNode<Object> object,
762                        TNode<IntPtrT> offset);
763 
764 #ifdef V8_MAP_PACKING
765   Node* PackMapWord(Node* value);
766 #endif
767 
768   // Load a value from the root array.
769   // If map packing is enabled, LoadRoot for a root map returns the unpacked map
770   // word (i.e., the map). Use LoadRootMapWord to obtain the packed map word
771   // instead.
772   TNode<Object> LoadRoot(RootIndex root_index);
773   TNode<AnyTaggedT> LoadRootMapWord(RootIndex root_index);
774 
775   template <typename Type>
UnalignedLoad(TNode<RawPtrT> base,TNode<IntPtrT> offset)776   TNode<Type> UnalignedLoad(TNode<RawPtrT> base, TNode<IntPtrT> offset) {
777     MachineType mt = MachineTypeOf<Type>::value;
778     return UncheckedCast<Type>(UnalignedLoad(mt, base, offset));
779   }
780 
781   // Store value to raw memory location.
782   void Store(Node* base, Node* value);
783   void Store(Node* base, Node* offset, Node* value);
784   void StoreEphemeronKey(Node* base, Node* offset, Node* value);
785   void StoreNoWriteBarrier(MachineRepresentation rep, Node* base, Node* value);
786   void StoreNoWriteBarrier(MachineRepresentation rep, Node* base, Node* offset,
787                            Node* value);
788   void UnsafeStoreNoWriteBarrier(MachineRepresentation rep, Node* base,
789                                  Node* value);
790   void UnsafeStoreNoWriteBarrier(MachineRepresentation rep, Node* base,
791                                  Node* offset, Node* value);
792 
793   // Stores uncompressed tagged value to (most likely off JS heap) memory
794   // location without write barrier.
795   void StoreFullTaggedNoWriteBarrier(TNode<RawPtrT> base,
796                                      TNode<Object> tagged_value);
797   void StoreFullTaggedNoWriteBarrier(TNode<RawPtrT> base, TNode<IntPtrT> offset,
798                                      TNode<Object> tagged_value);
799 
800   // Optimized memory operations that map to Turbofan simplified nodes.
801   TNode<HeapObject> OptimizedAllocate(TNode<IntPtrT> size,
802                                       AllocationType allocation,
803                                       AllowLargeObjects allow_large_objects);
804   void StoreToObject(MachineRepresentation rep, TNode<Object> object,
805                      TNode<IntPtrT> offset, Node* value,
806                      StoreToObjectWriteBarrier write_barrier);
807   void OptimizedStoreField(MachineRepresentation rep, TNode<HeapObject> object,
808                            int offset, Node* value);
809   void OptimizedStoreFieldAssertNoWriteBarrier(MachineRepresentation rep,
810                                                TNode<HeapObject> object,
811                                                int offset, Node* value);
812   void OptimizedStoreFieldUnsafeNoWriteBarrier(MachineRepresentation rep,
813                                                TNode<HeapObject> object,
814                                                int offset, Node* value);
815   void OptimizedStoreMap(TNode<HeapObject> object, TNode<Map>);
816   void AtomicStore(MachineRepresentation rep, AtomicMemoryOrder order,
817                    TNode<RawPtrT> base, TNode<WordT> offset,
818                    TNode<Word32T> value);
819   // {value_high} is used for 64-bit stores on 32-bit platforms, must be
820   // nullptr in other cases.
821   void AtomicStore64(AtomicMemoryOrder order, TNode<RawPtrT> base,
822                      TNode<WordT> offset, TNode<UintPtrT> value,
823                      TNode<UintPtrT> value_high);
824 
825   TNode<Word32T> AtomicAdd(MachineType type, TNode<RawPtrT> base,
826                            TNode<UintPtrT> offset, TNode<Word32T> value);
827   template <class Type>
828   TNode<Type> AtomicAdd64(TNode<RawPtrT> base, TNode<UintPtrT> offset,
829                           TNode<UintPtrT> value, TNode<UintPtrT> value_high);
830 
831   TNode<Word32T> AtomicSub(MachineType type, TNode<RawPtrT> base,
832                            TNode<UintPtrT> offset, TNode<Word32T> value);
833   template <class Type>
834   TNode<Type> AtomicSub64(TNode<RawPtrT> base, TNode<UintPtrT> offset,
835                           TNode<UintPtrT> value, TNode<UintPtrT> value_high);
836 
837   TNode<Word32T> AtomicAnd(MachineType type, TNode<RawPtrT> base,
838                            TNode<UintPtrT> offset, TNode<Word32T> value);
839   template <class Type>
840   TNode<Type> AtomicAnd64(TNode<RawPtrT> base, TNode<UintPtrT> offset,
841                           TNode<UintPtrT> value, TNode<UintPtrT> value_high);
842 
843   TNode<Word32T> AtomicOr(MachineType type, TNode<RawPtrT> base,
844                           TNode<UintPtrT> offset, TNode<Word32T> value);
845   template <class Type>
846   TNode<Type> AtomicOr64(TNode<RawPtrT> base, TNode<UintPtrT> offset,
847                          TNode<UintPtrT> value, TNode<UintPtrT> value_high);
848 
849   TNode<Word32T> AtomicXor(MachineType type, TNode<RawPtrT> base,
850                            TNode<UintPtrT> offset, TNode<Word32T> value);
851   template <class Type>
852   TNode<Type> AtomicXor64(TNode<RawPtrT> base, TNode<UintPtrT> offset,
853                           TNode<UintPtrT> value, TNode<UintPtrT> value_high);
854 
855   // Exchange value at raw memory location
856   TNode<Word32T> AtomicExchange(MachineType type, TNode<RawPtrT> base,
857                                 TNode<UintPtrT> offset, TNode<Word32T> value);
858   template <class Type>
859   TNode<Type> AtomicExchange64(TNode<RawPtrT> base, TNode<UintPtrT> offset,
860                                TNode<UintPtrT> value,
861                                TNode<UintPtrT> value_high);
862 
863   // Compare and Exchange value at raw memory location
864   TNode<Word32T> AtomicCompareExchange(MachineType type, TNode<RawPtrT> base,
865                                        TNode<WordT> offset,
866                                        TNode<Word32T> old_value,
867                                        TNode<Word32T> new_value);
868 
869   template <class Type>
870   TNode<Type> AtomicCompareExchange64(TNode<RawPtrT> base, TNode<WordT> offset,
871                                       TNode<UintPtrT> old_value,
872                                       TNode<UintPtrT> new_value,
873                                       TNode<UintPtrT> old_value_high,
874                                       TNode<UintPtrT> new_value_high);
875 
876   // Store a value to the root array.
877   void StoreRoot(RootIndex root_index, TNode<Object> value);
878 
879 // Basic arithmetic operations.
880 #define DECLARE_CODE_ASSEMBLER_BINARY_OP(name, ResType, Arg1Type, Arg2Type) \
881   TNode<ResType> name(TNode<Arg1Type> a, TNode<Arg2Type> b);
CODE_ASSEMBLER_BINARY_OP_LIST(DECLARE_CODE_ASSEMBLER_BINARY_OP)882   CODE_ASSEMBLER_BINARY_OP_LIST(DECLARE_CODE_ASSEMBLER_BINARY_OP)
883 #undef DECLARE_CODE_ASSEMBLER_BINARY_OP
884 
885   TNode<UintPtrT> WordShr(TNode<UintPtrT> left, TNode<IntegralT> right) {
886     return Unsigned(WordShr(static_cast<TNode<WordT>>(left), right));
887   }
WordSar(TNode<IntPtrT> left,TNode<IntegralT> right)888   TNode<IntPtrT> WordSar(TNode<IntPtrT> left, TNode<IntegralT> right) {
889     return Signed(WordSar(static_cast<TNode<WordT>>(left), right));
890   }
WordShl(TNode<IntPtrT> left,TNode<IntegralT> right)891   TNode<IntPtrT> WordShl(TNode<IntPtrT> left, TNode<IntegralT> right) {
892     return Signed(WordShl(static_cast<TNode<WordT>>(left), right));
893   }
WordShl(TNode<UintPtrT> left,TNode<IntegralT> right)894   TNode<UintPtrT> WordShl(TNode<UintPtrT> left, TNode<IntegralT> right) {
895     return Unsigned(WordShl(static_cast<TNode<WordT>>(left), right));
896   }
897 
Word32Shl(TNode<Int32T> left,TNode<Int32T> right)898   TNode<Int32T> Word32Shl(TNode<Int32T> left, TNode<Int32T> right) {
899     return Signed(Word32Shl(static_cast<TNode<Word32T>>(left), right));
900   }
Word32Shl(TNode<Uint32T> left,TNode<Uint32T> right)901   TNode<Uint32T> Word32Shl(TNode<Uint32T> left, TNode<Uint32T> right) {
902     return Unsigned(Word32Shl(static_cast<TNode<Word32T>>(left), right));
903   }
Word32Shr(TNode<Uint32T> left,TNode<Uint32T> right)904   TNode<Uint32T> Word32Shr(TNode<Uint32T> left, TNode<Uint32T> right) {
905     return Unsigned(Word32Shr(static_cast<TNode<Word32T>>(left), right));
906   }
Word32Sar(TNode<Int32T> left,TNode<Int32T> right)907   TNode<Int32T> Word32Sar(TNode<Int32T> left, TNode<Int32T> right) {
908     return Signed(Word32Sar(static_cast<TNode<Word32T>>(left), right));
909   }
910 
Word64Shl(TNode<Int64T> left,TNode<Int64T> right)911   TNode<Int64T> Word64Shl(TNode<Int64T> left, TNode<Int64T> right) {
912     return Signed(Word64Shl(static_cast<TNode<Word64T>>(left), right));
913   }
Word64Shl(TNode<Uint64T> left,TNode<Uint64T> right)914   TNode<Uint64T> Word64Shl(TNode<Uint64T> left, TNode<Uint64T> right) {
915     return Unsigned(Word64Shl(static_cast<TNode<Word64T>>(left), right));
916   }
Word64Shr(TNode<Uint64T> left,TNode<Uint64T> right)917   TNode<Uint64T> Word64Shr(TNode<Uint64T> left, TNode<Uint64T> right) {
918     return Unsigned(Word64Shr(static_cast<TNode<Word64T>>(left), right));
919   }
Word64Sar(TNode<Int64T> left,TNode<Int64T> right)920   TNode<Int64T> Word64Sar(TNode<Int64T> left, TNode<Int64T> right) {
921     return Signed(Word64Sar(static_cast<TNode<Word64T>>(left), right));
922   }
923 
Word64And(TNode<Int64T> left,TNode<Int64T> right)924   TNode<Int64T> Word64And(TNode<Int64T> left, TNode<Int64T> right) {
925     return Signed(Word64And(static_cast<TNode<Word64T>>(left), right));
926   }
Word64And(TNode<Uint64T> left,TNode<Uint64T> right)927   TNode<Uint64T> Word64And(TNode<Uint64T> left, TNode<Uint64T> right) {
928     return Unsigned(Word64And(static_cast<TNode<Word64T>>(left), right));
929   }
930 
Word64Xor(TNode<Int64T> left,TNode<Int64T> right)931   TNode<Int64T> Word64Xor(TNode<Int64T> left, TNode<Int64T> right) {
932     return Signed(Word64Xor(static_cast<TNode<Word64T>>(left), right));
933   }
Word64Xor(TNode<Uint64T> left,TNode<Uint64T> right)934   TNode<Uint64T> Word64Xor(TNode<Uint64T> left, TNode<Uint64T> right) {
935     return Unsigned(Word64Xor(static_cast<TNode<Word64T>>(left), right));
936   }
937 
Word64Not(TNode<Int64T> value)938   TNode<Int64T> Word64Not(TNode<Int64T> value) {
939     return Signed(Word64Not(static_cast<TNode<Word64T>>(value)));
940   }
Word64Not(TNode<Uint64T> value)941   TNode<Uint64T> Word64Not(TNode<Uint64T> value) {
942     return Unsigned(Word64Not(static_cast<TNode<Word64T>>(value)));
943   }
944 
WordAnd(TNode<IntPtrT> left,TNode<IntPtrT> right)945   TNode<IntPtrT> WordAnd(TNode<IntPtrT> left, TNode<IntPtrT> right) {
946     return Signed(WordAnd(static_cast<TNode<WordT>>(left),
947                           static_cast<TNode<WordT>>(right)));
948   }
WordAnd(TNode<UintPtrT> left,TNode<UintPtrT> right)949   TNode<UintPtrT> WordAnd(TNode<UintPtrT> left, TNode<UintPtrT> right) {
950     return Unsigned(WordAnd(static_cast<TNode<WordT>>(left),
951                             static_cast<TNode<WordT>>(right)));
952   }
953 
Word32And(TNode<Int32T> left,TNode<Int32T> right)954   TNode<Int32T> Word32And(TNode<Int32T> left, TNode<Int32T> right) {
955     return Signed(Word32And(static_cast<TNode<Word32T>>(left),
956                             static_cast<TNode<Word32T>>(right)));
957   }
Word32And(TNode<Uint32T> left,TNode<Uint32T> right)958   TNode<Uint32T> Word32And(TNode<Uint32T> left, TNode<Uint32T> right) {
959     return Unsigned(Word32And(static_cast<TNode<Word32T>>(left),
960                               static_cast<TNode<Word32T>>(right)));
961   }
962 
WordOr(TNode<IntPtrT> left,TNode<IntPtrT> right)963   TNode<IntPtrT> WordOr(TNode<IntPtrT> left, TNode<IntPtrT> right) {
964     return Signed(WordOr(static_cast<TNode<WordT>>(left),
965                          static_cast<TNode<WordT>>(right)));
966   }
967 
Word32Or(TNode<Int32T> left,TNode<Int32T> right)968   TNode<Int32T> Word32Or(TNode<Int32T> left, TNode<Int32T> right) {
969     return Signed(Word32Or(static_cast<TNode<Word32T>>(left),
970                            static_cast<TNode<Word32T>>(right)));
971   }
Word32Or(TNode<Uint32T> left,TNode<Uint32T> right)972   TNode<Uint32T> Word32Or(TNode<Uint32T> left, TNode<Uint32T> right) {
973     return Unsigned(Word32Or(static_cast<TNode<Word32T>>(left),
974                              static_cast<TNode<Word32T>>(right)));
975   }
976 
977   TNode<BoolT> IntPtrEqual(TNode<WordT> left, TNode<WordT> right);
978   TNode<BoolT> WordEqual(TNode<WordT> left, TNode<WordT> right);
979   TNode<BoolT> WordNotEqual(TNode<WordT> left, TNode<WordT> right);
980   TNode<BoolT> Word32Equal(TNode<Word32T> left, TNode<Word32T> right);
981   TNode<BoolT> Word32NotEqual(TNode<Word32T> left, TNode<Word32T> right);
982   TNode<BoolT> Word64Equal(TNode<Word64T> left, TNode<Word64T> right);
983   TNode<BoolT> Word64NotEqual(TNode<Word64T> left, TNode<Word64T> right);
984 
WordNot(TNode<IntPtrT> a)985   TNode<IntPtrT> WordNot(TNode<IntPtrT> a) {
986     return Signed(WordNot(static_cast<TNode<WordT>>(a)));
987   }
Word32Or(TNode<BoolT> left,TNode<BoolT> right)988   TNode<BoolT> Word32Or(TNode<BoolT> left, TNode<BoolT> right) {
989     return UncheckedCast<BoolT>(Word32Or(static_cast<TNode<Word32T>>(left),
990                                          static_cast<TNode<Word32T>>(right)));
991   }
Word32And(TNode<BoolT> left,TNode<BoolT> right)992   TNode<BoolT> Word32And(TNode<BoolT> left, TNode<BoolT> right) {
993     return UncheckedCast<BoolT>(Word32And(static_cast<TNode<Word32T>>(left),
994                                           static_cast<TNode<Word32T>>(right)));
995   }
996 
Int32Add(TNode<Int32T> left,TNode<Int32T> right)997   TNode<Int32T> Int32Add(TNode<Int32T> left, TNode<Int32T> right) {
998     return Signed(Int32Add(static_cast<TNode<Word32T>>(left),
999                            static_cast<TNode<Word32T>>(right)));
1000   }
1001 
Uint32Add(TNode<Uint32T> left,TNode<Uint32T> right)1002   TNode<Uint32T> Uint32Add(TNode<Uint32T> left, TNode<Uint32T> right) {
1003     return Unsigned(Int32Add(static_cast<TNode<Word32T>>(left),
1004                              static_cast<TNode<Word32T>>(right)));
1005   }
1006 
Uint32Sub(TNode<Uint32T> left,TNode<Uint32T> right)1007   TNode<Uint32T> Uint32Sub(TNode<Uint32T> left, TNode<Uint32T> right) {
1008     return Unsigned(Int32Sub(static_cast<TNode<Word32T>>(left),
1009                              static_cast<TNode<Word32T>>(right)));
1010   }
1011 
Int32Sub(TNode<Int32T> left,TNode<Int32T> right)1012   TNode<Int32T> Int32Sub(TNode<Int32T> left, TNode<Int32T> right) {
1013     return Signed(Int32Sub(static_cast<TNode<Word32T>>(left),
1014                            static_cast<TNode<Word32T>>(right)));
1015   }
1016 
Int32Mul(TNode<Int32T> left,TNode<Int32T> right)1017   TNode<Int32T> Int32Mul(TNode<Int32T> left, TNode<Int32T> right) {
1018     return Signed(Int32Mul(static_cast<TNode<Word32T>>(left),
1019                            static_cast<TNode<Word32T>>(right)));
1020   }
1021 
Int64Add(TNode<Int64T> left,TNode<Int64T> right)1022   TNode<Int64T> Int64Add(TNode<Int64T> left, TNode<Int64T> right) {
1023     return Signed(Int64Add(static_cast<TNode<Word64T>>(left), right));
1024   }
1025 
Uint64Add(TNode<Uint64T> left,TNode<Uint64T> right)1026   TNode<Uint64T> Uint64Add(TNode<Uint64T> left, TNode<Uint64T> right) {
1027     return Unsigned(Int64Add(static_cast<TNode<Word64T>>(left), right));
1028   }
1029 
Int64Sub(TNode<Int64T> left,TNode<Int64T> right)1030   TNode<Int64T> Int64Sub(TNode<Int64T> left, TNode<Int64T> right) {
1031     return Signed(Int64Sub(static_cast<TNode<Word64T>>(left), right));
1032   }
1033 
Uint64Sub(TNode<Uint64T> left,TNode<Uint64T> right)1034   TNode<Uint64T> Uint64Sub(TNode<Uint64T> left, TNode<Uint64T> right) {
1035     return Unsigned(Int64Sub(static_cast<TNode<Word64T>>(left), right));
1036   }
1037 
Int64Mul(TNode<Int64T> left,TNode<Int64T> right)1038   TNode<Int64T> Int64Mul(TNode<Int64T> left, TNode<Int64T> right) {
1039     return Signed(Int64Mul(static_cast<TNode<Word64T>>(left), right));
1040   }
1041 
Uint64Mul(TNode<Uint64T> left,TNode<Uint64T> right)1042   TNode<Uint64T> Uint64Mul(TNode<Uint64T> left, TNode<Uint64T> right) {
1043     return Unsigned(Int64Mul(static_cast<TNode<Word64T>>(left), right));
1044   }
1045 
IntPtrAdd(TNode<IntPtrT> left,TNode<IntPtrT> right)1046   TNode<IntPtrT> IntPtrAdd(TNode<IntPtrT> left, TNode<IntPtrT> right) {
1047     return Signed(IntPtrAdd(static_cast<TNode<WordT>>(left),
1048                             static_cast<TNode<WordT>>(right)));
1049   }
IntPtrSub(TNode<IntPtrT> left,TNode<IntPtrT> right)1050   TNode<IntPtrT> IntPtrSub(TNode<IntPtrT> left, TNode<IntPtrT> right) {
1051     return Signed(IntPtrSub(static_cast<TNode<WordT>>(left),
1052                             static_cast<TNode<WordT>>(right)));
1053   }
IntPtrMul(TNode<IntPtrT> left,TNode<IntPtrT> right)1054   TNode<IntPtrT> IntPtrMul(TNode<IntPtrT> left, TNode<IntPtrT> right) {
1055     return Signed(IntPtrMul(static_cast<TNode<WordT>>(left),
1056                             static_cast<TNode<WordT>>(right)));
1057   }
UintPtrAdd(TNode<UintPtrT> left,TNode<UintPtrT> right)1058   TNode<UintPtrT> UintPtrAdd(TNode<UintPtrT> left, TNode<UintPtrT> right) {
1059     return Unsigned(IntPtrAdd(static_cast<TNode<WordT>>(left),
1060                               static_cast<TNode<WordT>>(right)));
1061   }
UintPtrSub(TNode<UintPtrT> left,TNode<UintPtrT> right)1062   TNode<UintPtrT> UintPtrSub(TNode<UintPtrT> left, TNode<UintPtrT> right) {
1063     return Unsigned(IntPtrSub(static_cast<TNode<WordT>>(left),
1064                               static_cast<TNode<WordT>>(right)));
1065   }
RawPtrAdd(TNode<RawPtrT> left,TNode<IntPtrT> right)1066   TNode<RawPtrT> RawPtrAdd(TNode<RawPtrT> left, TNode<IntPtrT> right) {
1067     return ReinterpretCast<RawPtrT>(IntPtrAdd(left, right));
1068   }
RawPtrSub(TNode<RawPtrT> left,TNode<IntPtrT> right)1069   TNode<RawPtrT> RawPtrSub(TNode<RawPtrT> left, TNode<IntPtrT> right) {
1070     return ReinterpretCast<RawPtrT>(IntPtrSub(left, right));
1071   }
RawPtrSub(TNode<RawPtrT> left,TNode<RawPtrT> right)1072   TNode<IntPtrT> RawPtrSub(TNode<RawPtrT> left, TNode<RawPtrT> right) {
1073     return Signed(IntPtrSub(static_cast<TNode<WordT>>(left),
1074                             static_cast<TNode<WordT>>(right)));
1075   }
1076 
1077   TNode<WordT> WordShl(TNode<WordT> value, int shift);
1078   TNode<WordT> WordShr(TNode<WordT> value, int shift);
1079   TNode<WordT> WordSar(TNode<WordT> value, int shift);
WordShr(TNode<IntPtrT> value,int shift)1080   TNode<IntPtrT> WordShr(TNode<IntPtrT> value, int shift) {
1081     return UncheckedCast<IntPtrT>(WordShr(TNode<WordT>(value), shift));
1082   }
WordSar(TNode<IntPtrT> value,int shift)1083   TNode<IntPtrT> WordSar(TNode<IntPtrT> value, int shift) {
1084     return UncheckedCast<IntPtrT>(WordSar(TNode<WordT>(value), shift));
1085   }
1086   TNode<Word32T> Word32Shr(TNode<Word32T> value, int shift);
1087   TNode<Word32T> Word32Sar(TNode<Word32T> value, int shift);
1088 
1089   // Convenience overloads.
Int32Sub(TNode<Int32T> left,int right)1090   TNode<Int32T> Int32Sub(TNode<Int32T> left, int right) {
1091     return Int32Sub(left, Int32Constant(right));
1092   }
Word32And(TNode<Word32T> left,int right)1093   TNode<Word32T> Word32And(TNode<Word32T> left, int right) {
1094     return Word32And(left, Int32Constant(right));
1095   }
Word32Shl(TNode<Int32T> left,int right)1096   TNode<Int32T> Word32Shl(TNode<Int32T> left, int right) {
1097     return Word32Shl(left, Int32Constant(right));
1098   }
Word32Equal(TNode<Word32T> left,int right)1099   TNode<BoolT> Word32Equal(TNode<Word32T> left, int right) {
1100     return Word32Equal(left, Int32Constant(right));
1101   }
1102 
1103 // Unary
1104 #define DECLARE_CODE_ASSEMBLER_UNARY_OP(name, ResType, ArgType) \
1105   TNode<ResType> name(TNode<ArgType> a);
CODE_ASSEMBLER_UNARY_OP_LIST(DECLARE_CODE_ASSEMBLER_UNARY_OP)1106   CODE_ASSEMBLER_UNARY_OP_LIST(DECLARE_CODE_ASSEMBLER_UNARY_OP)
1107 #undef DECLARE_CODE_ASSEMBLER_UNARY_OP
1108 
1109   template <class Dummy = void>
1110   TNode<IntPtrT> BitcastTaggedToWord(TNode<Smi> node) {
1111     static_assert(sizeof(Dummy) < 0,
1112                   "Should use BitcastTaggedToWordForTagAndSmiBits instead.");
1113   }
1114 
1115   // Changes a double to an inptr_t for pointer arithmetic outside of Smi range.
1116   // Assumes that the double can be exactly represented as an int.
1117   TNode<IntPtrT> ChangeFloat64ToIntPtr(TNode<Float64T> value);
1118   TNode<UintPtrT> ChangeFloat64ToUintPtr(TNode<Float64T> value);
1119   // Same in the opposite direction.
1120   TNode<Float64T> ChangeUintPtrToFloat64(TNode<UintPtrT> value);
1121 
1122   // Changes an intptr_t to a double, e.g. for storing an element index
1123   // outside Smi range in a HeapNumber. Lossless on 32-bit,
1124   // rounds on 64-bit (which doesn't affect valid element indices).
1125   TNode<Float64T> RoundIntPtrToFloat64(Node* value);
1126   // No-op on 32-bit, otherwise zero extend.
1127   TNode<UintPtrT> ChangeUint32ToWord(TNode<Word32T> value);
1128   // No-op on 32-bit, otherwise sign extend.
1129   TNode<IntPtrT> ChangeInt32ToIntPtr(TNode<Word32T> value);
1130 
1131   // Truncates a float to a 32-bit integer. If the float is outside of 32-bit
1132   // range, make sure that overflow detection is easy. In particular, return
1133   // int_min instead of int_max on arm platforms by using parameter
1134   // kSetOverflowToMin.
1135   TNode<Int32T> TruncateFloat32ToInt32(TNode<Float32T> value);
1136 
1137   // Projections
1138   template <int index, class T1, class T2>
1139   TNode<typename std::tuple_element<index, std::tuple<T1, T2>>::type>
Projection(TNode<PairT<T1,T2>> value)1140   Projection(TNode<PairT<T1, T2>> value) {
1141     return UncheckedCast<
1142         typename std::tuple_element<index, std::tuple<T1, T2>>::type>(
1143         Projection(index, value));
1144   }
1145 
1146   // Calls
1147   template <class T = Object, class... TArgs>
CallRuntime(Runtime::FunctionId function,TNode<Object> context,TArgs...args)1148   TNode<T> CallRuntime(Runtime::FunctionId function, TNode<Object> context,
1149                        TArgs... args) {
1150     return UncheckedCast<T>(CallRuntimeImpl(
1151         function, context, {implicit_cast<TNode<Object>>(args)...}));
1152   }
1153 
1154   template <class... TArgs>
TailCallRuntime(Runtime::FunctionId function,TNode<Object> context,TArgs...args)1155   void TailCallRuntime(Runtime::FunctionId function, TNode<Object> context,
1156                        TArgs... args) {
1157     int argc = static_cast<int>(sizeof...(args));
1158     TNode<Int32T> arity = Int32Constant(argc);
1159     return TailCallRuntimeImpl(function, arity, context,
1160                                {implicit_cast<TNode<Object>>(args)...});
1161   }
1162 
1163   template <class... TArgs>
TailCallRuntime(Runtime::FunctionId function,TNode<Int32T> arity,TNode<Object> context,TArgs...args)1164   void TailCallRuntime(Runtime::FunctionId function, TNode<Int32T> arity,
1165                        TNode<Object> context, TArgs... args) {
1166     return TailCallRuntimeImpl(function, arity, context,
1167                                {implicit_cast<TNode<Object>>(args)...});
1168   }
1169 
1170   //
1171   // If context passed to CallStub is nullptr, it won't be passed to the stub.
1172   //
1173 
1174   template <class T = Object, class... TArgs>
CallStub(Callable const & callable,TNode<Object> context,TArgs...args)1175   TNode<T> CallStub(Callable const& callable, TNode<Object> context,
1176                     TArgs... args) {
1177     TNode<CodeT> target = HeapConstant(callable.code());
1178     return CallStub<T>(callable.descriptor(), target, context, args...);
1179   }
1180 
1181   template <class T = Object, class... TArgs>
CallStub(const CallInterfaceDescriptor & descriptor,TNode<CodeT> target,TNode<Object> context,TArgs...args)1182   TNode<T> CallStub(const CallInterfaceDescriptor& descriptor,
1183                     TNode<CodeT> target, TNode<Object> context, TArgs... args) {
1184     return UncheckedCast<T>(CallStubR(StubCallMode::kCallCodeObject, descriptor,
1185                                       target, context, args...));
1186   }
1187 
1188   template <class T = Object, class... TArgs>
CallBuiltinPointer(const CallInterfaceDescriptor & descriptor,TNode<BuiltinPtr> target,TNode<Object> context,TArgs...args)1189   TNode<T> CallBuiltinPointer(const CallInterfaceDescriptor& descriptor,
1190                               TNode<BuiltinPtr> target, TNode<Object> context,
1191                               TArgs... args) {
1192     return UncheckedCast<T>(CallStubR(StubCallMode::kCallBuiltinPointer,
1193                                       descriptor, target, context, args...));
1194   }
1195 
1196   template <class... TArgs>
TailCallStub(Callable const & callable,TNode<Object> context,TArgs...args)1197   void TailCallStub(Callable const& callable, TNode<Object> context,
1198                     TArgs... args) {
1199     TNode<CodeT> target = HeapConstant(callable.code());
1200     TailCallStub(callable.descriptor(), target, context, args...);
1201   }
1202 
1203   template <class... TArgs>
TailCallStub(const CallInterfaceDescriptor & descriptor,TNode<CodeT> target,TNode<Object> context,TArgs...args)1204   void TailCallStub(const CallInterfaceDescriptor& descriptor,
1205                     TNode<CodeT> target, TNode<Object> context, TArgs... args) {
1206     TailCallStubImpl(descriptor, target, context, {args...});
1207   }
1208 
1209   template <class... TArgs>
1210   void TailCallBytecodeDispatch(const CallInterfaceDescriptor& descriptor,
1211                                 TNode<RawPtrT> target, TArgs... args);
1212 
1213   template <class... TArgs>
TailCallStubThenBytecodeDispatch(const CallInterfaceDescriptor & descriptor,Node * target,Node * context,TArgs...args)1214   void TailCallStubThenBytecodeDispatch(
1215       const CallInterfaceDescriptor& descriptor, Node* target, Node* context,
1216       TArgs... args) {
1217     TailCallStubThenBytecodeDispatchImpl(descriptor, target, context,
1218                                          {args...});
1219   }
1220 
1221   // Tailcalls to the given code object with JSCall linkage. The JS arguments
1222   // (including receiver) are supposed to be already on the stack.
1223   // This is a building block for implementing trampoline stubs that are
1224   // installed instead of code objects with JSCall linkage.
1225   // Note that no arguments adaption is going on here - all the JavaScript
1226   // arguments are left on the stack unmodified. Therefore, this tail call can
1227   // only be used after arguments adaptation has been performed already.
1228   void TailCallJSCode(TNode<CodeT> code, TNode<Context> context,
1229                       TNode<JSFunction> function, TNode<Object> new_target,
1230                       TNode<Int32T> arg_count);
1231 
1232   template <class... TArgs>
CallJS(Callable const & callable,Node * context,Node * function,Node * receiver,TArgs...args)1233   TNode<Object> CallJS(Callable const& callable, Node* context, Node* function,
1234                        Node* receiver, TArgs... args) {
1235     int argc = JSParameterCount(static_cast<int>(sizeof...(args)));
1236     TNode<Int32T> arity = Int32Constant(argc);
1237     TNode<CodeT> target = HeapConstant(callable.code());
1238     return CAST(CallJSStubImpl(callable.descriptor(), target, CAST(context),
1239                                CAST(function), {}, arity, {receiver, args...}));
1240   }
1241 
1242   template <class... TArgs>
ConstructJSWithTarget(Callable const & callable,Node * context,Node * function,Node * new_target,TArgs...args)1243   Node* ConstructJSWithTarget(Callable const& callable, Node* context,
1244                               Node* function, Node* new_target, TArgs... args) {
1245     int argc = JSParameterCount(static_cast<int>(sizeof...(args)));
1246     TNode<Int32T> arity = Int32Constant(argc);
1247     TNode<Object> receiver = LoadRoot(RootIndex::kUndefinedValue);
1248     TNode<CodeT> target = HeapConstant(callable.code());
1249     return CallJSStubImpl(callable.descriptor(), target, CAST(context),
1250                           CAST(function), CAST(new_target), arity,
1251                           {receiver, args...});
1252   }
1253   template <class... TArgs>
ConstructJS(Callable const & callable,Node * context,Node * new_target,TArgs...args)1254   Node* ConstructJS(Callable const& callable, Node* context, Node* new_target,
1255                     TArgs... args) {
1256     return ConstructJSWithTarget(callable, context, new_target, new_target,
1257                                  args...);
1258   }
1259 
1260   Node* CallCFunctionN(Signature<MachineType>* signature, int input_count,
1261                        Node* const* inputs);
1262 
1263   // Type representing C function argument with type info.
1264   using CFunctionArg = std::pair<MachineType, Node*>;
1265 
1266   // Call to a C function.
1267   template <class... CArgs>
CallCFunction(Node * function,base::Optional<MachineType> return_type,CArgs...cargs)1268   Node* CallCFunction(Node* function, base::Optional<MachineType> return_type,
1269                       CArgs... cargs) {
1270     static_assert(
1271         std::conjunction_v<std::is_convertible<CArgs, CFunctionArg>...>,
1272         "invalid argument types");
1273     return CallCFunction(function, return_type, {cargs...});
1274   }
1275 
1276   // Call to a C function without a function discriptor on AIX.
1277   template <class... CArgs>
CallCFunctionWithoutFunctionDescriptor(Node * function,MachineType return_type,CArgs...cargs)1278   Node* CallCFunctionWithoutFunctionDescriptor(Node* function,
1279                                                MachineType return_type,
1280                                                CArgs... cargs) {
1281     static_assert(
1282         std::conjunction_v<std::is_convertible<CArgs, CFunctionArg>...>,
1283         "invalid argument types");
1284     return CallCFunctionWithoutFunctionDescriptor(function, return_type,
1285                                                   {cargs...});
1286   }
1287 
1288   // Call to a C function, while saving/restoring caller registers.
1289   template <class... CArgs>
CallCFunctionWithCallerSavedRegisters(Node * function,MachineType return_type,SaveFPRegsMode mode,CArgs...cargs)1290   Node* CallCFunctionWithCallerSavedRegisters(Node* function,
1291                                               MachineType return_type,
1292                                               SaveFPRegsMode mode,
1293                                               CArgs... cargs) {
1294     static_assert(
1295         std::conjunction_v<std::is_convertible<CArgs, CFunctionArg>...>,
1296         "invalid argument types");
1297     return CallCFunctionWithCallerSavedRegisters(function, return_type, mode,
1298                                                  {cargs...});
1299   }
1300 
1301   // Helpers which delegate to RawMachineAssembler.
1302   Factory* factory() const;
1303   Isolate* isolate() const;
1304   Zone* zone() const;
1305 
state()1306   CodeAssemblerState* state() { return state_; }
1307 
1308   void BreakOnNode(int node_id);
1309 
1310   bool UnalignedLoadSupported(MachineRepresentation rep) const;
1311   bool UnalignedStoreSupported(MachineRepresentation rep) const;
1312 
1313   bool IsExceptionHandlerActive() const;
1314 
1315  protected:
1316   void RegisterCallGenerationCallbacks(
1317       const CodeAssemblerCallback& call_prologue,
1318       const CodeAssemblerCallback& call_epilogue);
1319   void UnregisterCallGenerationCallbacks();
1320 
1321   bool Word32ShiftIsSafe() const;
1322 
1323   bool IsJSFunctionCall() const;
1324 
1325  private:
1326   void HandleException(Node* result);
1327 
1328   Node* CallCFunction(Node* function, base::Optional<MachineType> return_type,
1329                       std::initializer_list<CFunctionArg> args);
1330 
1331   Node* CallCFunctionWithoutFunctionDescriptor(
1332       Node* function, MachineType return_type,
1333       std::initializer_list<CFunctionArg> args);
1334 
1335   Node* CallCFunctionWithCallerSavedRegisters(
1336       Node* function, MachineType return_type, SaveFPRegsMode mode,
1337       std::initializer_list<CFunctionArg> args);
1338 
1339   Node* CallRuntimeImpl(Runtime::FunctionId function, TNode<Object> context,
1340                         std::initializer_list<TNode<Object>> args);
1341 
1342   void TailCallRuntimeImpl(Runtime::FunctionId function, TNode<Int32T> arity,
1343                            TNode<Object> context,
1344                            std::initializer_list<TNode<Object>> args);
1345 
1346   void TailCallStubImpl(const CallInterfaceDescriptor& descriptor,
1347                         TNode<CodeT> target, TNode<Object> context,
1348                         std::initializer_list<Node*> args);
1349 
1350   void TailCallStubThenBytecodeDispatchImpl(
1351       const CallInterfaceDescriptor& descriptor, Node* target, Node* context,
1352       std::initializer_list<Node*> args);
1353 
1354   template <class... TArgs>
CallStubR(StubCallMode call_mode,const CallInterfaceDescriptor & descriptor,TNode<Object> target,TNode<Object> context,TArgs...args)1355   Node* CallStubR(StubCallMode call_mode,
1356                   const CallInterfaceDescriptor& descriptor,
1357                   TNode<Object> target, TNode<Object> context, TArgs... args) {
1358     return CallStubRImpl(call_mode, descriptor, target, context, {args...});
1359   }
1360 
1361   Node* CallStubRImpl(StubCallMode call_mode,
1362                       const CallInterfaceDescriptor& descriptor,
1363                       TNode<Object> target, TNode<Object> context,
1364                       std::initializer_list<Node*> args);
1365 
1366   Node* CallJSStubImpl(const CallInterfaceDescriptor& descriptor,
1367                        TNode<Object> target, TNode<Object> context,
1368                        TNode<Object> function,
1369                        base::Optional<TNode<Object>> new_target,
1370                        TNode<Int32T> arity, std::initializer_list<Node*> args);
1371 
1372   Node* CallStubN(StubCallMode call_mode,
1373                   const CallInterfaceDescriptor& descriptor, int input_count,
1374                   Node* const* inputs);
1375 
1376   Node* AtomicLoad(MachineType type, AtomicMemoryOrder order,
1377                    TNode<RawPtrT> base, TNode<WordT> offset);
1378 
1379   Node* UnalignedLoad(MachineType type, TNode<RawPtrT> base,
1380                       TNode<WordT> offset);
1381 
1382   // These two don't have definitions and are here only for catching use cases
1383   // where the cast is not necessary.
1384   TNode<Int32T> Signed(TNode<Int32T> x);
1385   TNode<Uint32T> Unsigned(TNode<Uint32T> x);
1386 
1387   Node* Projection(int index, Node* value);
1388 
1389   RawMachineAssembler* raw_assembler() const;
1390   JSGraph* jsgraph() const;
1391 
1392   // Calls respective callback registered in the state.
1393   void CallPrologue();
1394   void CallEpilogue();
1395 
1396   CodeAssemblerState* state_;
1397 };
1398 
1399 // TODO(solanes, v8:6949): this class should be merged into
1400 // TypedCodeAssemblerVariable. It's required to be separate for
1401 // CodeAssemblerVariableLists.
1402 class V8_EXPORT_PRIVATE CodeAssemblerVariable {
1403  public:
1404   CodeAssemblerVariable(const CodeAssemblerVariable&) = delete;
1405   CodeAssemblerVariable& operator=(const CodeAssemblerVariable&) = delete;
1406 
1407   Node* value() const;
1408   MachineRepresentation rep() const;
1409   bool IsBound() const;
1410 
1411  protected:
1412   explicit CodeAssemblerVariable(CodeAssembler* assembler,
1413                                  MachineRepresentation rep);
1414   CodeAssemblerVariable(CodeAssembler* assembler, MachineRepresentation rep,
1415                         Node* initial_value);
1416 #if DEBUG
1417   CodeAssemblerVariable(CodeAssembler* assembler, AssemblerDebugInfo debug_info,
1418                         MachineRepresentation rep);
1419   CodeAssemblerVariable(CodeAssembler* assembler, AssemblerDebugInfo debug_info,
1420                         MachineRepresentation rep, Node* initial_value);
1421 #endif  // DEBUG
1422 
1423   ~CodeAssemblerVariable();
1424   void Bind(Node* value);
1425 
1426  private:
1427   class Impl;
1428   friend class CodeAssemblerLabel;
1429   friend class CodeAssemblerState;
1430   friend std::ostream& operator<<(std::ostream&, const Impl&);
1431   friend std::ostream& operator<<(std::ostream&, const CodeAssemblerVariable&);
1432   struct ImplComparator {
1433     bool operator()(const CodeAssemblerVariable::Impl* a,
1434                     const CodeAssemblerVariable::Impl* b) const;
1435   };
1436   Impl* impl_;
1437   CodeAssemblerState* state_;
1438 };
1439 
1440 std::ostream& operator<<(std::ostream&, const CodeAssemblerVariable&);
1441 std::ostream& operator<<(std::ostream&, const CodeAssemblerVariable::Impl&);
1442 
1443 template <class T>
1444 class TypedCodeAssemblerVariable : public CodeAssemblerVariable {
1445  public:
TypedCodeAssemblerVariable(TNode<T> initial_value,CodeAssembler * assembler)1446   TypedCodeAssemblerVariable(TNode<T> initial_value, CodeAssembler* assembler)
1447       : CodeAssemblerVariable(assembler, PhiMachineRepresentationOf<T>,
1448                               initial_value) {}
TypedCodeAssemblerVariable(CodeAssembler * assembler)1449   explicit TypedCodeAssemblerVariable(CodeAssembler* assembler)
1450       : CodeAssemblerVariable(assembler, PhiMachineRepresentationOf<T>) {}
1451 #if DEBUG
TypedCodeAssemblerVariable(AssemblerDebugInfo debug_info,CodeAssembler * assembler)1452   TypedCodeAssemblerVariable(AssemblerDebugInfo debug_info,
1453                              CodeAssembler* assembler)
1454       : CodeAssemblerVariable(assembler, debug_info,
1455                               PhiMachineRepresentationOf<T>) {}
TypedCodeAssemblerVariable(AssemblerDebugInfo debug_info,TNode<T> initial_value,CodeAssembler * assembler)1456   TypedCodeAssemblerVariable(AssemblerDebugInfo debug_info,
1457                              TNode<T> initial_value, CodeAssembler* assembler)
1458       : CodeAssemblerVariable(assembler, debug_info,
1459                               PhiMachineRepresentationOf<T>, initial_value) {}
1460 #endif  // DEBUG
1461 
value()1462   TNode<T> value() const {
1463     return TNode<T>::UncheckedCast(CodeAssemblerVariable::value());
1464   }
1465 
1466   void operator=(TNode<T> value) { Bind(value); }
1467   void operator=(const TypedCodeAssemblerVariable<T>& variable) {
1468     Bind(variable.value());
1469   }
1470 
1471  private:
1472   using CodeAssemblerVariable::Bind;
1473 };
1474 
1475 class V8_EXPORT_PRIVATE CodeAssemblerLabel {
1476  public:
1477   enum Type { kDeferred, kNonDeferred };
1478 
1479   explicit CodeAssemblerLabel(
1480       CodeAssembler* assembler,
1481       CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred)
1482       : CodeAssemblerLabel(assembler, 0, nullptr, type) {}
1483   CodeAssemblerLabel(
1484       CodeAssembler* assembler,
1485       const CodeAssemblerVariableList& merged_variables,
1486       CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred)
1487       : CodeAssemblerLabel(assembler, merged_variables.size(),
1488                            &(merged_variables[0]), type) {}
1489   CodeAssemblerLabel(
1490       CodeAssembler* assembler, size_t count,
1491       CodeAssemblerVariable* const* vars,
1492       CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred);
1493   CodeAssemblerLabel(
1494       CodeAssembler* assembler,
1495       std::initializer_list<CodeAssemblerVariable*> vars,
1496       CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred)
1497       : CodeAssemblerLabel(assembler, vars.size(), vars.begin(), type) {}
1498   CodeAssemblerLabel(
1499       CodeAssembler* assembler, CodeAssemblerVariable* merged_variable,
1500       CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred)
1501       : CodeAssemblerLabel(assembler, 1, &merged_variable, type) {}
1502   ~CodeAssemblerLabel();
1503 
1504   // Cannot be copied because the destructor explicitly call the destructor of
1505   // the underlying {RawMachineLabel}, hence only one pointer can point to it.
1506   CodeAssemblerLabel(const CodeAssemblerLabel&) = delete;
1507   CodeAssemblerLabel& operator=(const CodeAssemblerLabel&) = delete;
1508 
is_bound()1509   inline bool is_bound() const { return bound_; }
is_used()1510   inline bool is_used() const { return merge_count_ != 0; }
1511 
1512  private:
1513   friend class CodeAssembler;
1514 
1515   void Bind();
1516 #if DEBUG
1517   void Bind(AssemblerDebugInfo debug_info);
1518 #endif  // DEBUG
1519   void UpdateVariablesAfterBind();
1520   void MergeVariables();
1521 
1522   bool bound_;
1523   size_t merge_count_;
1524   CodeAssemblerState* state_;
1525   RawMachineLabel* label_;
1526   // Map of variables that need to be merged to their phi nodes (or placeholders
1527   // for those phis).
1528   std::map<CodeAssemblerVariable::Impl*, Node*,
1529            CodeAssemblerVariable::ImplComparator>
1530       variable_phis_;
1531   // Map of variables to the list of value nodes that have been added from each
1532   // merge path in their order of merging.
1533   std::map<CodeAssemblerVariable::Impl*, std::vector<Node*>,
1534            CodeAssemblerVariable::ImplComparator>
1535       variable_merges_;
1536 };
1537 
1538 class CodeAssemblerParameterizedLabelBase {
1539  public:
is_used()1540   bool is_used() const { return plain_label_.is_used(); }
CodeAssemblerParameterizedLabelBase(CodeAssembler * assembler,size_t arity,CodeAssemblerLabel::Type type)1541   explicit CodeAssemblerParameterizedLabelBase(CodeAssembler* assembler,
1542                                                size_t arity,
1543                                                CodeAssemblerLabel::Type type)
1544       : state_(assembler->state()),
1545         phi_inputs_(arity),
1546         plain_label_(assembler, type) {}
1547 
1548  protected:
plain_label()1549   CodeAssemblerLabel* plain_label() { return &plain_label_; }
1550   void AddInputs(std::vector<Node*> inputs);
1551   Node* CreatePhi(MachineRepresentation rep, const std::vector<Node*>& inputs);
1552   const std::vector<Node*>& CreatePhis(
1553       std::vector<MachineRepresentation> representations);
1554 
1555  private:
1556   CodeAssemblerState* state_;
1557   std::vector<std::vector<Node*>> phi_inputs_;
1558   std::vector<Node*> phi_nodes_;
1559   CodeAssemblerLabel plain_label_;
1560 };
1561 
1562 template <class... Types>
1563 class CodeAssemblerParameterizedLabel
1564     : public CodeAssemblerParameterizedLabelBase {
1565  public:
1566   static constexpr size_t kArity = sizeof...(Types);
CodeAssemblerParameterizedLabel(CodeAssembler * assembler,CodeAssemblerLabel::Type type)1567   explicit CodeAssemblerParameterizedLabel(CodeAssembler* assembler,
1568                                            CodeAssemblerLabel::Type type)
1569       : CodeAssemblerParameterizedLabelBase(assembler, kArity, type) {}
1570 
1571  private:
1572   friend class CodeAssembler;
1573 
AddInputsVector(std::vector<Node * > inputs)1574   void AddInputsVector(std::vector<Node*> inputs) {
1575     CodeAssemblerParameterizedLabelBase::AddInputs(std::move(inputs));
1576   }
AddInputs(TNode<Types>...inputs)1577   void AddInputs(TNode<Types>... inputs) {
1578     CodeAssemblerParameterizedLabelBase::AddInputs(
1579         std::vector<Node*>{inputs...});
1580   }
CreatePhis(TNode<Types> * ...results)1581   void CreatePhis(TNode<Types>*... results) {
1582     const std::vector<Node*>& phi_nodes =
1583         CodeAssemblerParameterizedLabelBase::CreatePhis(
1584             {PhiMachineRepresentationOf<Types>...});
1585     auto it = phi_nodes.begin();
1586     USE(it);
1587     (AssignPhi(results, *(it++)), ...);
1588   }
1589   template <class T>
AssignPhi(TNode<T> * result,Node * phi)1590   static void AssignPhi(TNode<T>* result, Node* phi) {
1591     if (phi != nullptr) *result = TNode<T>::UncheckedCast(phi);
1592   }
1593 };
1594 
1595 using CodeAssemblerExceptionHandlerLabel =
1596     CodeAssemblerParameterizedLabel<Object>;
1597 
1598 class V8_EXPORT_PRIVATE CodeAssemblerState {
1599  public:
1600   // Create with CallStub linkage.
1601   // |result_size| specifies the number of results returned by the stub.
1602   // TODO(rmcilroy): move result_size to the CallInterfaceDescriptor.
1603   CodeAssemblerState(Isolate* isolate, Zone* zone,
1604                      const CallInterfaceDescriptor& descriptor, CodeKind kind,
1605                      const char* name, Builtin builtin = Builtin::kNoBuiltinId);
1606 
1607   // Create with JSCall linkage.
1608   CodeAssemblerState(Isolate* isolate, Zone* zone, int parameter_count,
1609                      CodeKind kind, const char* name,
1610                      Builtin builtin = Builtin::kNoBuiltinId);
1611 
1612   ~CodeAssemblerState();
1613 
1614   CodeAssemblerState(const CodeAssemblerState&) = delete;
1615   CodeAssemblerState& operator=(const CodeAssemblerState&) = delete;
1616 
name()1617   const char* name() const { return name_; }
1618   int parameter_count() const;
1619 
1620 #if DEBUG
1621   void PrintCurrentBlock(std::ostream& os);
1622 #endif  // DEBUG
1623   bool InsideBlock();
1624   void SetInitialDebugInformation(const char* msg, const char* file, int line);
1625 
1626  private:
1627   friend class CodeAssembler;
1628   friend class CodeAssemblerLabel;
1629   friend class CodeAssemblerVariable;
1630   friend class CodeAssemblerTester;
1631   friend class CodeAssemblerParameterizedLabelBase;
1632   friend class ScopedExceptionHandler;
1633 
1634   CodeAssemblerState(Isolate* isolate, Zone* zone,
1635                      CallDescriptor* call_descriptor, CodeKind kind,
1636                      const char* name, Builtin builtin);
1637 
1638   void PushExceptionHandler(CodeAssemblerExceptionHandlerLabel* label);
1639   void PopExceptionHandler();
1640 
1641   std::unique_ptr<RawMachineAssembler> raw_assembler_;
1642   CodeKind kind_;
1643   const char* name_;
1644   Builtin builtin_;
1645   bool code_generated_;
1646   ZoneSet<CodeAssemblerVariable::Impl*, CodeAssemblerVariable::ImplComparator>
1647       variables_;
1648   CodeAssemblerCallback call_prologue_;
1649   CodeAssemblerCallback call_epilogue_;
1650   std::vector<CodeAssemblerExceptionHandlerLabel*> exception_handler_labels_;
1651   using VariableId = uint32_t;
1652   VariableId next_variable_id_ = 0;
1653   JSGraph* jsgraph_;
1654 
1655   // Only used by CodeStubAssembler builtins.
1656   std::vector<FileAndLine> macro_call_stack_;
1657 
NextVariableId()1658   VariableId NextVariableId() { return next_variable_id_++; }
1659 };
1660 
1661 class V8_EXPORT_PRIVATE V8_NODISCARD ScopedExceptionHandler {
1662  public:
1663   ScopedExceptionHandler(CodeAssembler* assembler,
1664                          CodeAssemblerExceptionHandlerLabel* label);
1665 
1666   // Use this constructor for compatability/ports of old CSA code only. New code
1667   // should use the CodeAssemblerExceptionHandlerLabel version.
1668   ScopedExceptionHandler(CodeAssembler* assembler, CodeAssemblerLabel* label,
1669                          TypedCodeAssemblerVariable<Object>* exception);
1670 
1671   ~ScopedExceptionHandler();
1672 
1673  private:
1674   bool has_handler_;
1675   CodeAssembler* assembler_;
1676   CodeAssemblerLabel* compatibility_label_;
1677   std::unique_ptr<CodeAssemblerExceptionHandlerLabel> label_;
1678   TypedCodeAssemblerVariable<Object>* exception_;
1679 };
1680 
1681 }  // namespace compiler
1682 }  // namespace internal
1683 }  // namespace v8
1684 
1685 #endif  // V8_COMPILER_CODE_ASSEMBLER_H_
1686