1 // Copyright 2014 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_RAW_MACHINE_ASSEMBLER_H_ 6 #define V8_COMPILER_RAW_MACHINE_ASSEMBLER_H_ 7 8 #include <initializer_list> 9 #include <type_traits> 10 11 #include "src/codegen/assembler.h" 12 #include "src/common/globals.h" 13 #include "src/compiler/access-builder.h" 14 #include "src/compiler/common-operator.h" 15 #include "src/compiler/graph.h" 16 #include "src/compiler/linkage.h" 17 #include "src/compiler/machine-operator.h" 18 #include "src/compiler/node-matchers.h" 19 #include "src/compiler/node.h" 20 #include "src/compiler/operator.h" 21 #include "src/compiler/simplified-operator.h" 22 #include "src/compiler/write-barrier-kind.h" 23 #include "src/execution/isolate.h" 24 #include "src/heap/factory.h" 25 26 namespace v8 { 27 namespace internal { 28 namespace compiler { 29 30 class BasicBlock; 31 class RawMachineLabel; 32 class Schedule; 33 class SourcePositionTable; 34 35 // The RawMachineAssembler produces a low-level IR graph. All nodes are wired 36 // into a graph and also placed into a schedule immediately, hence subsequent 37 // code generation can happen without the need for scheduling. 38 // 39 // In order to create a schedule on-the-fly, the assembler keeps track of basic 40 // blocks by having one current basic block being populated and by referencing 41 // other basic blocks through the use of labels. 42 // 43 // Also note that the generated graph is only valid together with the generated 44 // schedule, using one without the other is invalid as the graph is inherently 45 // non-schedulable due to missing control and effect dependencies. 46 class V8_EXPORT_PRIVATE RawMachineAssembler { 47 public: 48 RawMachineAssembler( 49 Isolate* isolate, Graph* graph, CallDescriptor* call_descriptor, 50 MachineRepresentation word = MachineType::PointerRepresentation(), 51 MachineOperatorBuilder::Flags flags = 52 MachineOperatorBuilder::Flag::kNoFlags, 53 MachineOperatorBuilder::AlignmentRequirements alignment_requirements = 54 MachineOperatorBuilder::AlignmentRequirements:: 55 FullUnalignedAccessSupport()); 56 ~RawMachineAssembler() = default; 57 58 RawMachineAssembler(const RawMachineAssembler&) = delete; 59 RawMachineAssembler& operator=(const RawMachineAssembler&) = delete; 60 isolate()61 Isolate* isolate() const { return isolate_; } graph()62 Graph* graph() const { return graph_; } zone()63 Zone* zone() const { return graph()->zone(); } machine()64 MachineOperatorBuilder* machine() { return &machine_; } common()65 CommonOperatorBuilder* common() { return &common_; } simplified()66 SimplifiedOperatorBuilder* simplified() { return &simplified_; } call_descriptor()67 CallDescriptor* call_descriptor() const { return call_descriptor_; } 68 69 // Only used for tests: Finalizes the schedule and exports it to be used for 70 // code generation. Note that this RawMachineAssembler becomes invalid after 71 // export. 72 Schedule* ExportForTest(); 73 // Finalizes the schedule and transforms it into a graph that's suitable for 74 // it to be used for Turbofan optimization and re-scheduling. Note that this 75 // RawMachineAssembler becomes invalid after export. 76 Graph* ExportForOptimization(); 77 78 // =========================================================================== 79 // The following utility methods create new nodes with specific operators and 80 // place them into the current basic block. They don't perform control flow, 81 // hence will not switch the current basic block. 82 83 Node* NullConstant(); 84 Node* UndefinedConstant(); 85 86 // Constants. PointerConstant(void * value)87 Node* PointerConstant(void* value) { 88 return IntPtrConstant(reinterpret_cast<intptr_t>(value)); 89 } IntPtrConstant(intptr_t value)90 Node* IntPtrConstant(intptr_t value) { 91 // TODO(dcarney): mark generated code as unserializable if value != 0. 92 return kSystemPointerSize == 8 ? Int64Constant(value) 93 : Int32Constant(static_cast<int>(value)); 94 } 95 Node* RelocatableIntPtrConstant(intptr_t value, RelocInfo::Mode rmode); Int32Constant(int32_t value)96 Node* Int32Constant(int32_t value) { 97 return AddNode(common()->Int32Constant(value)); 98 } 99 Node* StackSlot(MachineRepresentation rep, int alignment = 0) { 100 return AddNode(machine()->StackSlot(rep, alignment)); 101 } Int64Constant(int64_t value)102 Node* Int64Constant(int64_t value) { 103 return AddNode(common()->Int64Constant(value)); 104 } NumberConstant(double value)105 Node* NumberConstant(double value) { 106 return AddNode(common()->NumberConstant(value)); 107 } Float32Constant(float value)108 Node* Float32Constant(float value) { 109 return AddNode(common()->Float32Constant(value)); 110 } Float64Constant(double value)111 Node* Float64Constant(double value) { 112 return AddNode(common()->Float64Constant(value)); 113 } HeapConstant(Handle<HeapObject> object)114 Node* HeapConstant(Handle<HeapObject> object) { 115 return AddNode(common()->HeapConstant(object)); 116 } ExternalConstant(ExternalReference address)117 Node* ExternalConstant(ExternalReference address) { 118 return AddNode(common()->ExternalConstant(address)); 119 } RelocatableInt32Constant(int32_t value,RelocInfo::Mode rmode)120 Node* RelocatableInt32Constant(int32_t value, RelocInfo::Mode rmode) { 121 return AddNode(common()->RelocatableInt32Constant(value, rmode)); 122 } RelocatableInt64Constant(int64_t value,RelocInfo::Mode rmode)123 Node* RelocatableInt64Constant(int64_t value, RelocInfo::Mode rmode) { 124 return AddNode(common()->RelocatableInt64Constant(value, rmode)); 125 } 126 Projection(int index,Node * a)127 Node* Projection(int index, Node* a) { 128 return AddNode(common()->Projection(index), a); 129 } 130 131 // Memory Operations. Load(MachineType type,Node * base)132 Node* Load(MachineType type, Node* base) { 133 return Load(type, base, IntPtrConstant(0)); 134 } Load(MachineType type,Node * base,Node * index)135 Node* Load(MachineType type, Node* base, Node* index) { 136 const Operator* op = machine()->Load(type); 137 Node* load = AddNode(op, base, index); 138 return load; 139 } LoadImmutable(MachineType type,Node * base)140 Node* LoadImmutable(MachineType type, Node* base) { 141 return LoadImmutable(type, base, IntPtrConstant(0)); 142 } LoadImmutable(MachineType type,Node * base,Node * index)143 Node* LoadImmutable(MachineType type, Node* base, Node* index) { 144 const Operator* op = machine()->LoadImmutable(type); 145 return AddNode(op, base, index); 146 } IsMapOffsetConstant(Node * node)147 bool IsMapOffsetConstant(Node* node) { 148 Int64Matcher m(node); 149 if (m.Is(HeapObject::kMapOffset)) return true; 150 // Test if `node` is a `Phi(Int64Constant(0))` 151 if (node->opcode() == IrOpcode::kPhi) { 152 for (Node* input : node->inputs()) { 153 if (!Int64Matcher(input).Is(HeapObject::kMapOffset)) return false; 154 } 155 return true; 156 } 157 return false; 158 } IsMapOffsetConstantMinusTag(Node * node)159 bool IsMapOffsetConstantMinusTag(Node* node) { 160 Int64Matcher m(node); 161 return m.Is(HeapObject::kMapOffset - kHeapObjectTag); 162 } IsMapOffsetConstantMinusTag(int offset)163 bool IsMapOffsetConstantMinusTag(int offset) { 164 return offset == HeapObject::kMapOffset - kHeapObjectTag; 165 } LoadFromObject(MachineType type,Node * base,Node * offset)166 Node* LoadFromObject(MachineType type, Node* base, Node* offset) { 167 DCHECK_IMPLIES(V8_MAP_PACKING_BOOL && IsMapOffsetConstantMinusTag(offset), 168 type == MachineType::MapInHeader()); 169 ObjectAccess access = {type, WriteBarrierKind::kNoWriteBarrier}; 170 Node* load = AddNode(simplified()->LoadFromObject(access), base, offset); 171 return load; 172 } 173 Store(MachineRepresentation rep,Node * base,Node * value,WriteBarrierKind write_barrier)174 Node* Store(MachineRepresentation rep, Node* base, Node* value, 175 WriteBarrierKind write_barrier) { 176 return Store(rep, base, IntPtrConstant(0), value, write_barrier); 177 } Store(MachineRepresentation rep,Node * base,Node * index,Node * value,WriteBarrierKind write_barrier)178 Node* Store(MachineRepresentation rep, Node* base, Node* index, Node* value, 179 WriteBarrierKind write_barrier) { 180 return AddNode(machine()->Store(StoreRepresentation(rep, write_barrier)), 181 base, index, value); 182 } StoreToObject(MachineRepresentation rep,Node * object,Node * offset,Node * value,WriteBarrierKind write_barrier)183 void StoreToObject(MachineRepresentation rep, Node* object, Node* offset, 184 Node* value, WriteBarrierKind write_barrier) { 185 ObjectAccess access = {MachineType::TypeForRepresentation(rep), 186 write_barrier}; 187 DCHECK(!IsMapOffsetConstantMinusTag(offset)); 188 AddNode(simplified()->StoreToObject(access), object, offset, value); 189 } OptimizedStoreField(MachineRepresentation rep,Node * object,int offset,Node * value,WriteBarrierKind write_barrier)190 void OptimizedStoreField(MachineRepresentation rep, Node* object, int offset, 191 Node* value, WriteBarrierKind write_barrier) { 192 DCHECK(!IsMapOffsetConstantMinusTag(offset)); 193 AddNode(simplified()->StoreField(FieldAccess( 194 BaseTaggedness::kTaggedBase, offset, MaybeHandle<Name>(), 195 MaybeHandle<Map>(), Type::Any(), 196 MachineType::TypeForRepresentation(rep), write_barrier)), 197 object, value); 198 } 199 void OptimizedStoreMap(Node* object, Node* value, 200 WriteBarrierKind write_barrier = kMapWriteBarrier) { 201 AddNode(simplified()->StoreField(AccessBuilder::ForMap(write_barrier)), 202 object, value); 203 } Retain(Node * value)204 Node* Retain(Node* value) { return AddNode(common()->Retain(), value); } 205 206 Node* OptimizedAllocate(Node* size, AllocationType allocation, 207 AllowLargeObjects allow_large_objects); 208 209 // Unaligned memory operations UnalignedLoad(MachineType type,Node * base)210 Node* UnalignedLoad(MachineType type, Node* base) { 211 return UnalignedLoad(type, base, IntPtrConstant(0)); 212 } UnalignedLoad(MachineType type,Node * base,Node * index)213 Node* UnalignedLoad(MachineType type, Node* base, Node* index) { 214 MachineRepresentation rep = type.representation(); 215 // Tagged or compressed should never be unaligned 216 DCHECK(!(IsAnyTagged(rep) || IsAnyCompressed(rep))); 217 if (machine()->UnalignedLoadSupported(rep)) { 218 return AddNode(machine()->Load(type), base, index); 219 } else { 220 return AddNode(machine()->UnalignedLoad(type), base, index); 221 } 222 } UnalignedStore(MachineRepresentation rep,Node * base,Node * value)223 Node* UnalignedStore(MachineRepresentation rep, Node* base, Node* value) { 224 return UnalignedStore(rep, base, IntPtrConstant(0), value); 225 } UnalignedStore(MachineRepresentation rep,Node * base,Node * index,Node * value)226 Node* UnalignedStore(MachineRepresentation rep, Node* base, Node* index, 227 Node* value) { 228 // Tagged or compressed should never be unaligned 229 DCHECK(!(IsAnyTagged(rep) || IsAnyCompressed(rep))); 230 if (machine()->UnalignedStoreSupported(rep)) { 231 return AddNode(machine()->Store(StoreRepresentation( 232 rep, WriteBarrierKind::kNoWriteBarrier)), 233 base, index, value); 234 } else { 235 return AddNode( 236 machine()->UnalignedStore(UnalignedStoreRepresentation(rep)), base, 237 index, value); 238 } 239 } 240 241 // Atomic memory operations. AtomicLoad(AtomicLoadParameters rep,Node * base,Node * index)242 Node* AtomicLoad(AtomicLoadParameters rep, Node* base, Node* index) { 243 DCHECK_NE(rep.representation().representation(), 244 MachineRepresentation::kWord64); 245 return AddNode(machine()->Word32AtomicLoad(rep), base, index); 246 } 247 AtomicLoad64(AtomicLoadParameters rep,Node * base,Node * index)248 Node* AtomicLoad64(AtomicLoadParameters rep, Node* base, Node* index) { 249 if (machine()->Is64()) { 250 // This uses Uint64() intentionally: AtomicLoad is not implemented for 251 // Int64(), which is fine because the machine instruction only cares 252 // about words. 253 return AddNode(machine()->Word64AtomicLoad(rep), base, index); 254 } else { 255 return AddNode(machine()->Word32AtomicPairLoad(rep.order()), base, index); 256 } 257 } 258 259 #if defined(V8_TARGET_BIG_ENDIAN) 260 #define VALUE_HALVES value_high, value 261 #else 262 #define VALUE_HALVES value, value_high 263 #endif 264 AtomicStore(AtomicStoreParameters params,Node * base,Node * index,Node * value)265 Node* AtomicStore(AtomicStoreParameters params, Node* base, Node* index, 266 Node* value) { 267 DCHECK(!IsMapOffsetConstantMinusTag(index)); 268 DCHECK_NE(params.representation(), MachineRepresentation::kWord64); 269 return AddNode(machine()->Word32AtomicStore(params), base, index, value); 270 } 271 AtomicStore64(AtomicStoreParameters params,Node * base,Node * index,Node * value,Node * value_high)272 Node* AtomicStore64(AtomicStoreParameters params, Node* base, Node* index, 273 Node* value, Node* value_high) { 274 if (machine()->Is64()) { 275 DCHECK_NULL(value_high); 276 return AddNode(machine()->Word64AtomicStore(params), base, index, value); 277 } else { 278 DCHECK(params.representation() != MachineRepresentation::kTaggedPointer && 279 params.representation() != MachineRepresentation::kTaggedSigned && 280 params.representation() != MachineRepresentation::kTagged); 281 return AddNode(machine()->Word32AtomicPairStore(params.order()), base, 282 index, VALUE_HALVES); 283 } 284 } 285 286 #define ATOMIC_FUNCTION(name) \ 287 Node* Atomic##name(MachineType type, Node* base, Node* index, Node* value) { \ 288 DCHECK_NE(type.representation(), MachineRepresentation::kWord64); \ 289 return AddNode(machine()->Word32Atomic##name(type), base, index, value); \ 290 } \ 291 Node* Atomic##name##64(Node * base, Node * index, Node * value, \ 292 Node * value_high) { \ 293 if (machine()->Is64()) { \ 294 DCHECK_NULL(value_high); \ 295 /* This uses Uint64() intentionally: Atomic operations are not */ \ 296 /* implemented for Int64(), which is fine because the machine */ \ 297 /* instruction only cares about words. */ \ 298 return AddNode(machine()->Word64Atomic##name(MachineType::Uint64()), \ 299 base, index, value); \ 300 } else { \ 301 return AddNode(machine()->Word32AtomicPair##name(), base, index, \ 302 VALUE_HALVES); \ 303 } \ 304 } 305 ATOMIC_FUNCTION(Exchange) ATOMIC_FUNCTION(Add)306 ATOMIC_FUNCTION(Add) 307 ATOMIC_FUNCTION(Sub) 308 ATOMIC_FUNCTION(And) 309 ATOMIC_FUNCTION(Or) 310 ATOMIC_FUNCTION(Xor) 311 #undef ATOMIC_FUNCTION 312 #undef VALUE_HALVES 313 314 Node* AtomicCompareExchange(MachineType type, Node* base, Node* index, 315 Node* old_value, Node* new_value) { 316 DCHECK_NE(type.representation(), MachineRepresentation::kWord64); 317 return AddNode(machine()->Word32AtomicCompareExchange(type), base, index, 318 old_value, new_value); 319 } 320 AtomicCompareExchange64(Node * base,Node * index,Node * old_value,Node * old_value_high,Node * new_value,Node * new_value_high)321 Node* AtomicCompareExchange64(Node* base, Node* index, Node* old_value, 322 Node* old_value_high, Node* new_value, 323 Node* new_value_high) { 324 if (machine()->Is64()) { 325 DCHECK_NULL(old_value_high); 326 DCHECK_NULL(new_value_high); 327 // This uses Uint64() intentionally: AtomicCompareExchange is not 328 // implemented for Int64(), which is fine because the machine instruction 329 // only cares about words. 330 return AddNode( 331 machine()->Word64AtomicCompareExchange(MachineType::Uint64()), base, 332 index, old_value, new_value); 333 } else { 334 return AddNode(machine()->Word32AtomicPairCompareExchange(), base, index, 335 old_value, old_value_high, new_value, new_value_high); 336 } 337 } 338 339 // Arithmetic Operations. WordAnd(Node * a,Node * b)340 Node* WordAnd(Node* a, Node* b) { 341 return AddNode(machine()->WordAnd(), a, b); 342 } WordOr(Node * a,Node * b)343 Node* WordOr(Node* a, Node* b) { return AddNode(machine()->WordOr(), a, b); } WordXor(Node * a,Node * b)344 Node* WordXor(Node* a, Node* b) { 345 return AddNode(machine()->WordXor(), a, b); 346 } WordShl(Node * a,Node * b)347 Node* WordShl(Node* a, Node* b) { 348 return AddNode(machine()->WordShl(), a, b); 349 } WordShr(Node * a,Node * b)350 Node* WordShr(Node* a, Node* b) { 351 return AddNode(machine()->WordShr(), a, b); 352 } WordSar(Node * a,Node * b)353 Node* WordSar(Node* a, Node* b) { 354 return AddNode(machine()->WordSar(), a, b); 355 } WordSarShiftOutZeros(Node * a,Node * b)356 Node* WordSarShiftOutZeros(Node* a, Node* b) { 357 return AddNode(machine()->WordSarShiftOutZeros(), a, b); 358 } WordRor(Node * a,Node * b)359 Node* WordRor(Node* a, Node* b) { 360 return AddNode(machine()->WordRor(), a, b); 361 } WordEqual(Node * a,Node * b)362 Node* WordEqual(Node* a, Node* b) { 363 return AddNode(machine()->WordEqual(), a, b); 364 } WordNotEqual(Node * a,Node * b)365 Node* WordNotEqual(Node* a, Node* b) { 366 return Word32BinaryNot(WordEqual(a, b)); 367 } WordNot(Node * a)368 Node* WordNot(Node* a) { 369 if (machine()->Is32()) { 370 return Word32BitwiseNot(a); 371 } else { 372 return Word64Not(a); 373 } 374 } 375 Word32And(Node * a,Node * b)376 Node* Word32And(Node* a, Node* b) { 377 return AddNode(machine()->Word32And(), a, b); 378 } Word32Or(Node * a,Node * b)379 Node* Word32Or(Node* a, Node* b) { 380 return AddNode(machine()->Word32Or(), a, b); 381 } Word32Xor(Node * a,Node * b)382 Node* Word32Xor(Node* a, Node* b) { 383 return AddNode(machine()->Word32Xor(), a, b); 384 } Word32Shl(Node * a,Node * b)385 Node* Word32Shl(Node* a, Node* b) { 386 return AddNode(machine()->Word32Shl(), a, b); 387 } Word32Shr(Node * a,Node * b)388 Node* Word32Shr(Node* a, Node* b) { 389 return AddNode(machine()->Word32Shr(), a, b); 390 } Word32Sar(Node * a,Node * b)391 Node* Word32Sar(Node* a, Node* b) { 392 return AddNode(machine()->Word32Sar(), a, b); 393 } Word32SarShiftOutZeros(Node * a,Node * b)394 Node* Word32SarShiftOutZeros(Node* a, Node* b) { 395 return AddNode(machine()->Word32SarShiftOutZeros(), a, b); 396 } Word32Ror(Node * a,Node * b)397 Node* Word32Ror(Node* a, Node* b) { 398 return AddNode(machine()->Word32Ror(), a, b); 399 } Word32Clz(Node * a)400 Node* Word32Clz(Node* a) { return AddNode(machine()->Word32Clz(), a); } Word32Equal(Node * a,Node * b)401 Node* Word32Equal(Node* a, Node* b) { 402 return AddNode(machine()->Word32Equal(), a, b); 403 } Word32NotEqual(Node * a,Node * b)404 Node* Word32NotEqual(Node* a, Node* b) { 405 return Word32BinaryNot(Word32Equal(a, b)); 406 } Word32BitwiseNot(Node * a)407 Node* Word32BitwiseNot(Node* a) { return Word32Xor(a, Int32Constant(-1)); } Word32BinaryNot(Node * a)408 Node* Word32BinaryNot(Node* a) { return Word32Equal(a, Int32Constant(0)); } 409 Word64And(Node * a,Node * b)410 Node* Word64And(Node* a, Node* b) { 411 return AddNode(machine()->Word64And(), a, b); 412 } Word64Or(Node * a,Node * b)413 Node* Word64Or(Node* a, Node* b) { 414 return AddNode(machine()->Word64Or(), a, b); 415 } Word64Xor(Node * a,Node * b)416 Node* Word64Xor(Node* a, Node* b) { 417 return AddNode(machine()->Word64Xor(), a, b); 418 } Word64Shl(Node * a,Node * b)419 Node* Word64Shl(Node* a, Node* b) { 420 return AddNode(machine()->Word64Shl(), a, b); 421 } Word64Shr(Node * a,Node * b)422 Node* Word64Shr(Node* a, Node* b) { 423 return AddNode(machine()->Word64Shr(), a, b); 424 } Word64Sar(Node * a,Node * b)425 Node* Word64Sar(Node* a, Node* b) { 426 return AddNode(machine()->Word64Sar(), a, b); 427 } Word64Ror(Node * a,Node * b)428 Node* Word64Ror(Node* a, Node* b) { 429 return AddNode(machine()->Word64Ror(), a, b); 430 } Word64Clz(Node * a)431 Node* Word64Clz(Node* a) { return AddNode(machine()->Word64Clz(), a); } Word64Equal(Node * a,Node * b)432 Node* Word64Equal(Node* a, Node* b) { 433 return AddNode(machine()->Word64Equal(), a, b); 434 } Word64NotEqual(Node * a,Node * b)435 Node* Word64NotEqual(Node* a, Node* b) { 436 return Word32BinaryNot(Word64Equal(a, b)); 437 } Word64Not(Node * a)438 Node* Word64Not(Node* a) { return Word64Xor(a, Int64Constant(-1)); } 439 Int32Add(Node * a,Node * b)440 Node* Int32Add(Node* a, Node* b) { 441 return AddNode(machine()->Int32Add(), a, b); 442 } Int32AddWithOverflow(Node * a,Node * b)443 Node* Int32AddWithOverflow(Node* a, Node* b) { 444 return AddNode(machine()->Int32AddWithOverflow(), a, b); 445 } Int32Sub(Node * a,Node * b)446 Node* Int32Sub(Node* a, Node* b) { 447 return AddNode(machine()->Int32Sub(), a, b); 448 } Int32SubWithOverflow(Node * a,Node * b)449 Node* Int32SubWithOverflow(Node* a, Node* b) { 450 return AddNode(machine()->Int32SubWithOverflow(), a, b); 451 } Int32Mul(Node * a,Node * b)452 Node* Int32Mul(Node* a, Node* b) { 453 return AddNode(machine()->Int32Mul(), a, b); 454 } Int32MulHigh(Node * a,Node * b)455 Node* Int32MulHigh(Node* a, Node* b) { 456 return AddNode(machine()->Int32MulHigh(), a, b); 457 } Int32MulWithOverflow(Node * a,Node * b)458 Node* Int32MulWithOverflow(Node* a, Node* b) { 459 return AddNode(machine()->Int32MulWithOverflow(), a, b); 460 } Int32Div(Node * a,Node * b)461 Node* Int32Div(Node* a, Node* b) { 462 return AddNode(machine()->Int32Div(), a, b); 463 } Int32Mod(Node * a,Node * b)464 Node* Int32Mod(Node* a, Node* b) { 465 return AddNode(machine()->Int32Mod(), a, b); 466 } Int32LessThan(Node * a,Node * b)467 Node* Int32LessThan(Node* a, Node* b) { 468 return AddNode(machine()->Int32LessThan(), a, b); 469 } Int32LessThanOrEqual(Node * a,Node * b)470 Node* Int32LessThanOrEqual(Node* a, Node* b) { 471 return AddNode(machine()->Int32LessThanOrEqual(), a, b); 472 } Uint32Div(Node * a,Node * b)473 Node* Uint32Div(Node* a, Node* b) { 474 return AddNode(machine()->Uint32Div(), a, b); 475 } Uint32LessThan(Node * a,Node * b)476 Node* Uint32LessThan(Node* a, Node* b) { 477 return AddNode(machine()->Uint32LessThan(), a, b); 478 } Uint32LessThanOrEqual(Node * a,Node * b)479 Node* Uint32LessThanOrEqual(Node* a, Node* b) { 480 return AddNode(machine()->Uint32LessThanOrEqual(), a, b); 481 } Uint32Mod(Node * a,Node * b)482 Node* Uint32Mod(Node* a, Node* b) { 483 return AddNode(machine()->Uint32Mod(), a, b); 484 } Uint32MulHigh(Node * a,Node * b)485 Node* Uint32MulHigh(Node* a, Node* b) { 486 return AddNode(machine()->Uint32MulHigh(), a, b); 487 } Int32GreaterThan(Node * a,Node * b)488 Node* Int32GreaterThan(Node* a, Node* b) { return Int32LessThan(b, a); } Int32GreaterThanOrEqual(Node * a,Node * b)489 Node* Int32GreaterThanOrEqual(Node* a, Node* b) { 490 return Int32LessThanOrEqual(b, a); 491 } Uint32GreaterThan(Node * a,Node * b)492 Node* Uint32GreaterThan(Node* a, Node* b) { return Uint32LessThan(b, a); } Uint32GreaterThanOrEqual(Node * a,Node * b)493 Node* Uint32GreaterThanOrEqual(Node* a, Node* b) { 494 return Uint32LessThanOrEqual(b, a); 495 } Int32Neg(Node * a)496 Node* Int32Neg(Node* a) { return Int32Sub(Int32Constant(0), a); } 497 Int64Add(Node * a,Node * b)498 Node* Int64Add(Node* a, Node* b) { 499 return AddNode(machine()->Int64Add(), a, b); 500 } Int64AddWithOverflow(Node * a,Node * b)501 Node* Int64AddWithOverflow(Node* a, Node* b) { 502 return AddNode(machine()->Int64AddWithOverflow(), a, b); 503 } Int64Sub(Node * a,Node * b)504 Node* Int64Sub(Node* a, Node* b) { 505 return AddNode(machine()->Int64Sub(), a, b); 506 } Int64SubWithOverflow(Node * a,Node * b)507 Node* Int64SubWithOverflow(Node* a, Node* b) { 508 return AddNode(machine()->Int64SubWithOverflow(), a, b); 509 } Int64Mul(Node * a,Node * b)510 Node* Int64Mul(Node* a, Node* b) { 511 return AddNode(machine()->Int64Mul(), a, b); 512 } Int64Div(Node * a,Node * b)513 Node* Int64Div(Node* a, Node* b) { 514 return AddNode(machine()->Int64Div(), a, b); 515 } Int64Mod(Node * a,Node * b)516 Node* Int64Mod(Node* a, Node* b) { 517 return AddNode(machine()->Int64Mod(), a, b); 518 } Int64Neg(Node * a)519 Node* Int64Neg(Node* a) { return Int64Sub(Int64Constant(0), a); } Int64LessThan(Node * a,Node * b)520 Node* Int64LessThan(Node* a, Node* b) { 521 return AddNode(machine()->Int64LessThan(), a, b); 522 } Int64LessThanOrEqual(Node * a,Node * b)523 Node* Int64LessThanOrEqual(Node* a, Node* b) { 524 return AddNode(machine()->Int64LessThanOrEqual(), a, b); 525 } Uint64LessThan(Node * a,Node * b)526 Node* Uint64LessThan(Node* a, Node* b) { 527 return AddNode(machine()->Uint64LessThan(), a, b); 528 } Uint64LessThanOrEqual(Node * a,Node * b)529 Node* Uint64LessThanOrEqual(Node* a, Node* b) { 530 return AddNode(machine()->Uint64LessThanOrEqual(), a, b); 531 } Int64GreaterThan(Node * a,Node * b)532 Node* Int64GreaterThan(Node* a, Node* b) { return Int64LessThan(b, a); } Int64GreaterThanOrEqual(Node * a,Node * b)533 Node* Int64GreaterThanOrEqual(Node* a, Node* b) { 534 return Int64LessThanOrEqual(b, a); 535 } Uint64GreaterThan(Node * a,Node * b)536 Node* Uint64GreaterThan(Node* a, Node* b) { return Uint64LessThan(b, a); } Uint64GreaterThanOrEqual(Node * a,Node * b)537 Node* Uint64GreaterThanOrEqual(Node* a, Node* b) { 538 return Uint64LessThanOrEqual(b, a); 539 } Uint64Div(Node * a,Node * b)540 Node* Uint64Div(Node* a, Node* b) { 541 return AddNode(machine()->Uint64Div(), a, b); 542 } Uint64Mod(Node * a,Node * b)543 Node* Uint64Mod(Node* a, Node* b) { 544 return AddNode(machine()->Uint64Mod(), a, b); 545 } Int32PairAdd(Node * a_low,Node * a_high,Node * b_low,Node * b_high)546 Node* Int32PairAdd(Node* a_low, Node* a_high, Node* b_low, Node* b_high) { 547 return AddNode(machine()->Int32PairAdd(), a_low, a_high, b_low, b_high); 548 } Int32PairSub(Node * a_low,Node * a_high,Node * b_low,Node * b_high)549 Node* Int32PairSub(Node* a_low, Node* a_high, Node* b_low, Node* b_high) { 550 return AddNode(machine()->Int32PairSub(), a_low, a_high, b_low, b_high); 551 } Int32PairMul(Node * a_low,Node * a_high,Node * b_low,Node * b_high)552 Node* Int32PairMul(Node* a_low, Node* a_high, Node* b_low, Node* b_high) { 553 return AddNode(machine()->Int32PairMul(), a_low, a_high, b_low, b_high); 554 } Word32PairShl(Node * low_word,Node * high_word,Node * shift)555 Node* Word32PairShl(Node* low_word, Node* high_word, Node* shift) { 556 return AddNode(machine()->Word32PairShl(), low_word, high_word, shift); 557 } Word32PairShr(Node * low_word,Node * high_word,Node * shift)558 Node* Word32PairShr(Node* low_word, Node* high_word, Node* shift) { 559 return AddNode(machine()->Word32PairShr(), low_word, high_word, shift); 560 } Word32PairSar(Node * low_word,Node * high_word,Node * shift)561 Node* Word32PairSar(Node* low_word, Node* high_word, Node* shift) { 562 return AddNode(machine()->Word32PairSar(), low_word, high_word, shift); 563 } Word32Popcnt(Node * a)564 Node* Word32Popcnt(Node* a) { 565 return AddNode(machine()->Word32Popcnt().op(), a); 566 } Word64Popcnt(Node * a)567 Node* Word64Popcnt(Node* a) { 568 return AddNode(machine()->Word64Popcnt().op(), a); 569 } Word32Ctz(Node * a)570 Node* Word32Ctz(Node* a) { return AddNode(machine()->Word32Ctz().op(), a); } Word64Ctz(Node * a)571 Node* Word64Ctz(Node* a) { return AddNode(machine()->Word64Ctz().op(), a); } 572 Word32Select(Node * condition,Node * b,Node * c)573 Node* Word32Select(Node* condition, Node* b, Node* c) { 574 return AddNode(machine()->Word32Select().op(), condition, b, c); 575 } 576 Word64Select(Node * condition,Node * b,Node * c)577 Node* Word64Select(Node* condition, Node* b, Node* c) { 578 return AddNode(machine()->Word64Select().op(), condition, b, c); 579 } 580 StackPointerGreaterThan(Node * value)581 Node* StackPointerGreaterThan(Node* value) { 582 return AddNode( 583 machine()->StackPointerGreaterThan(StackCheckKind::kCodeStubAssembler), 584 value); 585 } 586 587 #define INTPTR_BINOP(prefix, name) \ 588 Node* IntPtr##name(Node* a, Node* b) { \ 589 return kSystemPointerSize == 8 ? prefix##64##name(a, b) \ 590 : prefix##32##name(a, b); \ 591 } 592 INTPTR_BINOP(Int,Add)593 INTPTR_BINOP(Int, Add) 594 INTPTR_BINOP(Int, AddWithOverflow) 595 INTPTR_BINOP(Int, Sub) 596 INTPTR_BINOP(Int, SubWithOverflow) 597 INTPTR_BINOP(Int, Mul) 598 INTPTR_BINOP(Int, Div) 599 INTPTR_BINOP(Int, LessThan) 600 INTPTR_BINOP(Int, LessThanOrEqual) 601 INTPTR_BINOP(Word, Equal) 602 INTPTR_BINOP(Word, NotEqual) 603 INTPTR_BINOP(Int, GreaterThanOrEqual) 604 INTPTR_BINOP(Int, GreaterThan) 605 606 #undef INTPTR_BINOP 607 608 #define UINTPTR_BINOP(prefix, name) \ 609 Node* UintPtr##name(Node* a, Node* b) { \ 610 return kSystemPointerSize == 8 ? prefix##64##name(a, b) \ 611 : prefix##32##name(a, b); \ 612 } 613 614 UINTPTR_BINOP(Uint, LessThan) 615 UINTPTR_BINOP(Uint, LessThanOrEqual) 616 UINTPTR_BINOP(Uint, GreaterThanOrEqual) 617 UINTPTR_BINOP(Uint, GreaterThan) 618 619 #undef UINTPTR_BINOP 620 621 Node* Int32AbsWithOverflow(Node* a) { 622 return AddNode(machine()->Int32AbsWithOverflow().op(), a); 623 } 624 Int64AbsWithOverflow(Node * a)625 Node* Int64AbsWithOverflow(Node* a) { 626 return AddNode(machine()->Int64AbsWithOverflow().op(), a); 627 } 628 IntPtrAbsWithOverflow(Node * a)629 Node* IntPtrAbsWithOverflow(Node* a) { 630 return kSystemPointerSize == 8 ? Int64AbsWithOverflow(a) 631 : Int32AbsWithOverflow(a); 632 } 633 Float32Add(Node * a,Node * b)634 Node* Float32Add(Node* a, Node* b) { 635 return AddNode(machine()->Float32Add(), a, b); 636 } Float32Sub(Node * a,Node * b)637 Node* Float32Sub(Node* a, Node* b) { 638 return AddNode(machine()->Float32Sub(), a, b); 639 } Float32Mul(Node * a,Node * b)640 Node* Float32Mul(Node* a, Node* b) { 641 return AddNode(machine()->Float32Mul(), a, b); 642 } Float32Div(Node * a,Node * b)643 Node* Float32Div(Node* a, Node* b) { 644 return AddNode(machine()->Float32Div(), a, b); 645 } Float32Abs(Node * a)646 Node* Float32Abs(Node* a) { return AddNode(machine()->Float32Abs(), a); } Float32Neg(Node * a)647 Node* Float32Neg(Node* a) { return AddNode(machine()->Float32Neg(), a); } Float32Sqrt(Node * a)648 Node* Float32Sqrt(Node* a) { return AddNode(machine()->Float32Sqrt(), a); } Float32Equal(Node * a,Node * b)649 Node* Float32Equal(Node* a, Node* b) { 650 return AddNode(machine()->Float32Equal(), a, b); 651 } Float32NotEqual(Node * a,Node * b)652 Node* Float32NotEqual(Node* a, Node* b) { 653 return Word32BinaryNot(Float32Equal(a, b)); 654 } Float32LessThan(Node * a,Node * b)655 Node* Float32LessThan(Node* a, Node* b) { 656 return AddNode(machine()->Float32LessThan(), a, b); 657 } Float32LessThanOrEqual(Node * a,Node * b)658 Node* Float32LessThanOrEqual(Node* a, Node* b) { 659 return AddNode(machine()->Float32LessThanOrEqual(), a, b); 660 } Float32GreaterThan(Node * a,Node * b)661 Node* Float32GreaterThan(Node* a, Node* b) { return Float32LessThan(b, a); } Float32GreaterThanOrEqual(Node * a,Node * b)662 Node* Float32GreaterThanOrEqual(Node* a, Node* b) { 663 return Float32LessThanOrEqual(b, a); 664 } Float32Max(Node * a,Node * b)665 Node* Float32Max(Node* a, Node* b) { 666 return AddNode(machine()->Float32Max(), a, b); 667 } Float32Min(Node * a,Node * b)668 Node* Float32Min(Node* a, Node* b) { 669 return AddNode(machine()->Float32Min(), a, b); 670 } Float64Add(Node * a,Node * b)671 Node* Float64Add(Node* a, Node* b) { 672 return AddNode(machine()->Float64Add(), a, b); 673 } Float64Sub(Node * a,Node * b)674 Node* Float64Sub(Node* a, Node* b) { 675 return AddNode(machine()->Float64Sub(), a, b); 676 } Float64Mul(Node * a,Node * b)677 Node* Float64Mul(Node* a, Node* b) { 678 return AddNode(machine()->Float64Mul(), a, b); 679 } Float64Div(Node * a,Node * b)680 Node* Float64Div(Node* a, Node* b) { 681 return AddNode(machine()->Float64Div(), a, b); 682 } Float64Mod(Node * a,Node * b)683 Node* Float64Mod(Node* a, Node* b) { 684 return AddNode(machine()->Float64Mod(), a, b); 685 } Float64Max(Node * a,Node * b)686 Node* Float64Max(Node* a, Node* b) { 687 return AddNode(machine()->Float64Max(), a, b); 688 } Float64Min(Node * a,Node * b)689 Node* Float64Min(Node* a, Node* b) { 690 return AddNode(machine()->Float64Min(), a, b); 691 } Float64Abs(Node * a)692 Node* Float64Abs(Node* a) { return AddNode(machine()->Float64Abs(), a); } Float64Neg(Node * a)693 Node* Float64Neg(Node* a) { return AddNode(machine()->Float64Neg(), a); } Float64Acos(Node * a)694 Node* Float64Acos(Node* a) { return AddNode(machine()->Float64Acos(), a); } Float64Acosh(Node * a)695 Node* Float64Acosh(Node* a) { return AddNode(machine()->Float64Acosh(), a); } Float64Asin(Node * a)696 Node* Float64Asin(Node* a) { return AddNode(machine()->Float64Asin(), a); } Float64Asinh(Node * a)697 Node* Float64Asinh(Node* a) { return AddNode(machine()->Float64Asinh(), a); } Float64Atan(Node * a)698 Node* Float64Atan(Node* a) { return AddNode(machine()->Float64Atan(), a); } Float64Atanh(Node * a)699 Node* Float64Atanh(Node* a) { return AddNode(machine()->Float64Atanh(), a); } Float64Atan2(Node * a,Node * b)700 Node* Float64Atan2(Node* a, Node* b) { 701 return AddNode(machine()->Float64Atan2(), a, b); 702 } Float64Cbrt(Node * a)703 Node* Float64Cbrt(Node* a) { return AddNode(machine()->Float64Cbrt(), a); } Float64Cos(Node * a)704 Node* Float64Cos(Node* a) { return AddNode(machine()->Float64Cos(), a); } Float64Cosh(Node * a)705 Node* Float64Cosh(Node* a) { return AddNode(machine()->Float64Cosh(), a); } Float64Exp(Node * a)706 Node* Float64Exp(Node* a) { return AddNode(machine()->Float64Exp(), a); } Float64Expm1(Node * a)707 Node* Float64Expm1(Node* a) { return AddNode(machine()->Float64Expm1(), a); } Float64Log(Node * a)708 Node* Float64Log(Node* a) { return AddNode(machine()->Float64Log(), a); } Float64Log1p(Node * a)709 Node* Float64Log1p(Node* a) { return AddNode(machine()->Float64Log1p(), a); } Float64Log10(Node * a)710 Node* Float64Log10(Node* a) { return AddNode(machine()->Float64Log10(), a); } Float64Log2(Node * a)711 Node* Float64Log2(Node* a) { return AddNode(machine()->Float64Log2(), a); } Float64Pow(Node * a,Node * b)712 Node* Float64Pow(Node* a, Node* b) { 713 return AddNode(machine()->Float64Pow(), a, b); 714 } Float64Sin(Node * a)715 Node* Float64Sin(Node* a) { return AddNode(machine()->Float64Sin(), a); } Float64Sinh(Node * a)716 Node* Float64Sinh(Node* a) { return AddNode(machine()->Float64Sinh(), a); } Float64Sqrt(Node * a)717 Node* Float64Sqrt(Node* a) { return AddNode(machine()->Float64Sqrt(), a); } Float64Tan(Node * a)718 Node* Float64Tan(Node* a) { return AddNode(machine()->Float64Tan(), a); } Float64Tanh(Node * a)719 Node* Float64Tanh(Node* a) { return AddNode(machine()->Float64Tanh(), a); } Float64Equal(Node * a,Node * b)720 Node* Float64Equal(Node* a, Node* b) { 721 return AddNode(machine()->Float64Equal(), a, b); 722 } Float64NotEqual(Node * a,Node * b)723 Node* Float64NotEqual(Node* a, Node* b) { 724 return Word32BinaryNot(Float64Equal(a, b)); 725 } Float64LessThan(Node * a,Node * b)726 Node* Float64LessThan(Node* a, Node* b) { 727 return AddNode(machine()->Float64LessThan(), a, b); 728 } Float64LessThanOrEqual(Node * a,Node * b)729 Node* Float64LessThanOrEqual(Node* a, Node* b) { 730 return AddNode(machine()->Float64LessThanOrEqual(), a, b); 731 } Float64GreaterThan(Node * a,Node * b)732 Node* Float64GreaterThan(Node* a, Node* b) { return Float64LessThan(b, a); } Float64GreaterThanOrEqual(Node * a,Node * b)733 Node* Float64GreaterThanOrEqual(Node* a, Node* b) { 734 return Float64LessThanOrEqual(b, a); 735 } Float32Select(Node * condition,Node * b,Node * c)736 Node* Float32Select(Node* condition, Node* b, Node* c) { 737 return AddNode(machine()->Float32Select().op(), condition, b, c); 738 } Float64Select(Node * condition,Node * b,Node * c)739 Node* Float64Select(Node* condition, Node* b, Node* c) { 740 return AddNode(machine()->Float64Select().op(), condition, b, c); 741 } 742 743 // Conversions. BitcastTaggedToWord(Node * a)744 Node* BitcastTaggedToWord(Node* a) { 745 return AddNode(machine()->BitcastTaggedToWord(), a); 746 } BitcastTaggedToWordForTagAndSmiBits(Node * a)747 Node* BitcastTaggedToWordForTagAndSmiBits(Node* a) { 748 return AddNode(machine()->BitcastTaggedToWordForTagAndSmiBits(), a); 749 } BitcastMaybeObjectToWord(Node * a)750 Node* BitcastMaybeObjectToWord(Node* a) { 751 return AddNode(machine()->BitcastMaybeObjectToWord(), a); 752 } BitcastWordToTagged(Node * a)753 Node* BitcastWordToTagged(Node* a) { 754 return AddNode(machine()->BitcastWordToTagged(), a); 755 } BitcastWordToTaggedSigned(Node * a)756 Node* BitcastWordToTaggedSigned(Node* a) { 757 return AddNode(machine()->BitcastWordToTaggedSigned(), a); 758 } TruncateFloat64ToWord32(Node * a)759 Node* TruncateFloat64ToWord32(Node* a) { 760 return AddNode(machine()->TruncateFloat64ToWord32(), a); 761 } ChangeFloat32ToFloat64(Node * a)762 Node* ChangeFloat32ToFloat64(Node* a) { 763 return AddNode(machine()->ChangeFloat32ToFloat64(), a); 764 } ChangeInt32ToFloat64(Node * a)765 Node* ChangeInt32ToFloat64(Node* a) { 766 return AddNode(machine()->ChangeInt32ToFloat64(), a); 767 } ChangeInt64ToFloat64(Node * a)768 Node* ChangeInt64ToFloat64(Node* a) { 769 return AddNode(machine()->ChangeInt64ToFloat64(), a); 770 } ChangeUint32ToFloat64(Node * a)771 Node* ChangeUint32ToFloat64(Node* a) { 772 return AddNode(machine()->ChangeUint32ToFloat64(), a); 773 } ChangeFloat64ToInt32(Node * a)774 Node* ChangeFloat64ToInt32(Node* a) { 775 return AddNode(machine()->ChangeFloat64ToInt32(), a); 776 } ChangeFloat64ToInt64(Node * a)777 Node* ChangeFloat64ToInt64(Node* a) { 778 return AddNode(machine()->ChangeFloat64ToInt64(), a); 779 } ChangeFloat64ToUint32(Node * a)780 Node* ChangeFloat64ToUint32(Node* a) { 781 return AddNode(machine()->ChangeFloat64ToUint32(), a); 782 } ChangeFloat64ToUint64(Node * a)783 Node* ChangeFloat64ToUint64(Node* a) { 784 return AddNode(machine()->ChangeFloat64ToUint64(), a); 785 } TruncateFloat64ToUint32(Node * a)786 Node* TruncateFloat64ToUint32(Node* a) { 787 return AddNode(machine()->TruncateFloat64ToUint32(), a); 788 } TruncateFloat32ToInt32(Node * a,TruncateKind kind)789 Node* TruncateFloat32ToInt32(Node* a, TruncateKind kind) { 790 return AddNode(machine()->TruncateFloat32ToInt32(kind), a); 791 } TruncateFloat32ToUint32(Node * a,TruncateKind kind)792 Node* TruncateFloat32ToUint32(Node* a, TruncateKind kind) { 793 return AddNode(machine()->TruncateFloat32ToUint32(kind), a); 794 } TryTruncateFloat32ToInt64(Node * a)795 Node* TryTruncateFloat32ToInt64(Node* a) { 796 return AddNode(machine()->TryTruncateFloat32ToInt64(), a); 797 } TryTruncateFloat64ToInt64(Node * a)798 Node* TryTruncateFloat64ToInt64(Node* a) { 799 return AddNode(machine()->TryTruncateFloat64ToInt64(), a); 800 } TryTruncateFloat32ToUint64(Node * a)801 Node* TryTruncateFloat32ToUint64(Node* a) { 802 return AddNode(machine()->TryTruncateFloat32ToUint64(), a); 803 } TryTruncateFloat64ToUint64(Node * a)804 Node* TryTruncateFloat64ToUint64(Node* a) { 805 return AddNode(machine()->TryTruncateFloat64ToUint64(), a); 806 } ChangeInt32ToInt64(Node * a)807 Node* ChangeInt32ToInt64(Node* a) { 808 return AddNode(machine()->ChangeInt32ToInt64(), a); 809 } ChangeUint32ToUint64(Node * a)810 Node* ChangeUint32ToUint64(Node* a) { 811 return AddNode(machine()->ChangeUint32ToUint64(), a); 812 } TruncateFloat64ToFloat32(Node * a)813 Node* TruncateFloat64ToFloat32(Node* a) { 814 return AddNode(machine()->TruncateFloat64ToFloat32(), a); 815 } TruncateInt64ToInt32(Node * a)816 Node* TruncateInt64ToInt32(Node* a) { 817 return AddNode(machine()->TruncateInt64ToInt32(), a); 818 } RoundFloat64ToInt32(Node * a)819 Node* RoundFloat64ToInt32(Node* a) { 820 return AddNode(machine()->RoundFloat64ToInt32(), a); 821 } RoundInt32ToFloat32(Node * a)822 Node* RoundInt32ToFloat32(Node* a) { 823 return AddNode(machine()->RoundInt32ToFloat32(), a); 824 } RoundInt64ToFloat32(Node * a)825 Node* RoundInt64ToFloat32(Node* a) { 826 return AddNode(machine()->RoundInt64ToFloat32(), a); 827 } RoundInt64ToFloat64(Node * a)828 Node* RoundInt64ToFloat64(Node* a) { 829 return AddNode(machine()->RoundInt64ToFloat64(), a); 830 } RoundUint32ToFloat32(Node * a)831 Node* RoundUint32ToFloat32(Node* a) { 832 return AddNode(machine()->RoundUint32ToFloat32(), a); 833 } RoundUint64ToFloat32(Node * a)834 Node* RoundUint64ToFloat32(Node* a) { 835 return AddNode(machine()->RoundUint64ToFloat32(), a); 836 } RoundUint64ToFloat64(Node * a)837 Node* RoundUint64ToFloat64(Node* a) { 838 return AddNode(machine()->RoundUint64ToFloat64(), a); 839 } BitcastFloat32ToInt32(Node * a)840 Node* BitcastFloat32ToInt32(Node* a) { 841 return AddNode(machine()->BitcastFloat32ToInt32(), a); 842 } BitcastFloat64ToInt64(Node * a)843 Node* BitcastFloat64ToInt64(Node* a) { 844 return AddNode(machine()->BitcastFloat64ToInt64(), a); 845 } BitcastInt32ToFloat32(Node * a)846 Node* BitcastInt32ToFloat32(Node* a) { 847 return AddNode(machine()->BitcastInt32ToFloat32(), a); 848 } BitcastInt64ToFloat64(Node * a)849 Node* BitcastInt64ToFloat64(Node* a) { 850 return AddNode(machine()->BitcastInt64ToFloat64(), a); 851 } Float32RoundDown(Node * a)852 Node* Float32RoundDown(Node* a) { 853 return AddNode(machine()->Float32RoundDown().op(), a); 854 } Float64RoundDown(Node * a)855 Node* Float64RoundDown(Node* a) { 856 return AddNode(machine()->Float64RoundDown().op(), a); 857 } Float32RoundUp(Node * a)858 Node* Float32RoundUp(Node* a) { 859 return AddNode(machine()->Float32RoundUp().op(), a); 860 } Float64RoundUp(Node * a)861 Node* Float64RoundUp(Node* a) { 862 return AddNode(machine()->Float64RoundUp().op(), a); 863 } Float32RoundTruncate(Node * a)864 Node* Float32RoundTruncate(Node* a) { 865 return AddNode(machine()->Float32RoundTruncate().op(), a); 866 } Float64RoundTruncate(Node * a)867 Node* Float64RoundTruncate(Node* a) { 868 return AddNode(machine()->Float64RoundTruncate().op(), a); 869 } Float64RoundTiesAway(Node * a)870 Node* Float64RoundTiesAway(Node* a) { 871 return AddNode(machine()->Float64RoundTiesAway().op(), a); 872 } Float32RoundTiesEven(Node * a)873 Node* Float32RoundTiesEven(Node* a) { 874 return AddNode(machine()->Float32RoundTiesEven().op(), a); 875 } Float64RoundTiesEven(Node * a)876 Node* Float64RoundTiesEven(Node* a) { 877 return AddNode(machine()->Float64RoundTiesEven().op(), a); 878 } Word32ReverseBytes(Node * a)879 Node* Word32ReverseBytes(Node* a) { 880 return AddNode(machine()->Word32ReverseBytes(), a); 881 } Word64ReverseBytes(Node * a)882 Node* Word64ReverseBytes(Node* a) { 883 return AddNode(machine()->Word64ReverseBytes(), a); 884 } 885 886 // Float64 bit operations. Float64ExtractLowWord32(Node * a)887 Node* Float64ExtractLowWord32(Node* a) { 888 return AddNode(machine()->Float64ExtractLowWord32(), a); 889 } Float64ExtractHighWord32(Node * a)890 Node* Float64ExtractHighWord32(Node* a) { 891 return AddNode(machine()->Float64ExtractHighWord32(), a); 892 } Float64InsertLowWord32(Node * a,Node * b)893 Node* Float64InsertLowWord32(Node* a, Node* b) { 894 return AddNode(machine()->Float64InsertLowWord32(), a, b); 895 } Float64InsertHighWord32(Node * a,Node * b)896 Node* Float64InsertHighWord32(Node* a, Node* b) { 897 return AddNode(machine()->Float64InsertHighWord32(), a, b); 898 } Float64SilenceNaN(Node * a)899 Node* Float64SilenceNaN(Node* a) { 900 return AddNode(machine()->Float64SilenceNaN(), a); 901 } 902 903 // SIMD operations. S128Const(const uint8_t value[16])904 Node* S128Const(const uint8_t value[16]) { 905 return AddNode(machine()->S128Const(value)); 906 } I64x2Splat(Node * a)907 Node* I64x2Splat(Node* a) { return AddNode(machine()->I64x2Splat(), a); } I64x2SplatI32Pair(Node * a,Node * b)908 Node* I64x2SplatI32Pair(Node* a, Node* b) { 909 return AddNode(machine()->I64x2SplatI32Pair(), a, b); 910 } I32x4Splat(Node * a)911 Node* I32x4Splat(Node* a) { return AddNode(machine()->I32x4Splat(), a); } I16x8Splat(Node * a)912 Node* I16x8Splat(Node* a) { return AddNode(machine()->I16x8Splat(), a); } I8x16Splat(Node * a)913 Node* I8x16Splat(Node* a) { return AddNode(machine()->I8x16Splat(), a); } 914 I8x16BitMask(Node * a)915 Node* I8x16BitMask(Node* a) { return AddNode(machine()->I8x16BitMask(), a); } 916 I8x16Eq(Node * a,Node * b)917 Node* I8x16Eq(Node* a, Node* b) { 918 return AddNode(machine()->I8x16Eq(), a, b); 919 } 920 921 // Stack operations. LoadFramePointer()922 Node* LoadFramePointer() { return AddNode(machine()->LoadFramePointer()); } LoadParentFramePointer()923 Node* LoadParentFramePointer() { 924 return AddNode(machine()->LoadParentFramePointer()); 925 } 926 927 // Parameters. 928 Node* TargetParameter(); 929 Node* Parameter(size_t index); 930 931 // Pointer utilities. 932 Node* LoadFromPointer(void* address, MachineType type, int32_t offset = 0) { 933 return Load(type, PointerConstant(address), Int32Constant(offset)); 934 } StoreToPointer(void * address,MachineRepresentation rep,Node * node)935 Node* StoreToPointer(void* address, MachineRepresentation rep, Node* node) { 936 return Store(rep, PointerConstant(address), node, kNoWriteBarrier); 937 } 938 Node* UnalignedLoadFromPointer(void* address, MachineType type, 939 int32_t offset = 0) { 940 return UnalignedLoad(type, PointerConstant(address), Int32Constant(offset)); 941 } UnalignedStoreToPointer(void * address,MachineRepresentation rep,Node * node)942 Node* UnalignedStoreToPointer(void* address, MachineRepresentation rep, 943 Node* node) { 944 return UnalignedStore(rep, PointerConstant(address), node); 945 } StringConstant(const char * string)946 Node* StringConstant(const char* string) { 947 return HeapConstant(isolate()->factory()->InternalizeUtf8String(string)); 948 } 949 950 // Call a given call descriptor and the given arguments. 951 // The call target is passed as part of the {inputs} array. 952 Node* CallN(CallDescriptor* call_descriptor, int input_count, 953 Node* const* inputs); 954 955 // Call a given call descriptor and the given arguments and frame-state. 956 // The call target and frame state are passed as part of the {inputs} array. 957 Node* CallNWithFrameState(CallDescriptor* call_descriptor, int input_count, 958 Node* const* inputs); 959 960 // Tail call a given call descriptor and the given arguments. 961 // The call target is passed as part of the {inputs} array. 962 void TailCallN(CallDescriptor* call_descriptor, int input_count, 963 Node* const* inputs); 964 965 // Type representing C function argument with type info. 966 using CFunctionArg = std::pair<MachineType, Node*>; 967 968 // Call to a C function. 969 template <class... CArgs> CallCFunction(Node * function,base::Optional<MachineType> return_type,CArgs...cargs)970 Node* CallCFunction(Node* function, base::Optional<MachineType> return_type, 971 CArgs... cargs) { 972 static_assert( 973 std::conjunction_v<std::is_convertible<CArgs, CFunctionArg>...>, 974 "invalid argument types"); 975 return CallCFunction(function, return_type, {cargs...}); 976 } 977 978 Node* CallCFunction(Node* function, base::Optional<MachineType> return_type, 979 std::initializer_list<CFunctionArg> args); 980 981 // Call to a C function without a function discriptor on AIX. 982 template <class... CArgs> CallCFunctionWithoutFunctionDescriptor(Node * function,MachineType return_type,CArgs...cargs)983 Node* CallCFunctionWithoutFunctionDescriptor(Node* function, 984 MachineType return_type, 985 CArgs... cargs) { 986 static_assert( 987 std::conjunction_v<std::is_convertible<CArgs, CFunctionArg>...>, 988 "invalid argument types"); 989 return CallCFunctionWithoutFunctionDescriptor(function, return_type, 990 {cargs...}); 991 } 992 993 Node* CallCFunctionWithoutFunctionDescriptor( 994 Node* function, MachineType return_type, 995 std::initializer_list<CFunctionArg> args); 996 997 // Call to a C function, while saving/restoring caller registers. 998 template <class... CArgs> CallCFunctionWithCallerSavedRegisters(Node * function,MachineType return_type,SaveFPRegsMode mode,CArgs...cargs)999 Node* CallCFunctionWithCallerSavedRegisters(Node* function, 1000 MachineType return_type, 1001 SaveFPRegsMode mode, 1002 CArgs... cargs) { 1003 static_assert( 1004 std::conjunction_v<std::is_convertible<CArgs, CFunctionArg>...>, 1005 "invalid argument types"); 1006 return CallCFunctionWithCallerSavedRegisters(function, return_type, mode, 1007 {cargs...}); 1008 } 1009 1010 Node* CallCFunctionWithCallerSavedRegisters( 1011 Node* function, MachineType return_type, SaveFPRegsMode mode, 1012 std::initializer_list<CFunctionArg> args); 1013 1014 // =========================================================================== 1015 // The following utility methods deal with control flow, hence might switch 1016 // the current basic block or create new basic blocks for labels. 1017 1018 // Control flow. 1019 void Goto(RawMachineLabel* label); 1020 void Branch(Node* condition, RawMachineLabel* true_val, 1021 RawMachineLabel* false_val); 1022 void Switch(Node* index, RawMachineLabel* default_label, 1023 const int32_t* case_values, RawMachineLabel** case_labels, 1024 size_t case_count); 1025 void Return(Node* value); 1026 void Return(Node* v1, Node* v2); 1027 void Return(Node* v1, Node* v2, Node* v3); 1028 void Return(Node* v1, Node* v2, Node* v3, Node* v4); 1029 void Return(int count, Node* v[]); 1030 void PopAndReturn(Node* pop, Node* value); 1031 void PopAndReturn(Node* pop, Node* v1, Node* v2); 1032 void PopAndReturn(Node* pop, Node* v1, Node* v2, Node* v3); 1033 void PopAndReturn(Node* pop, Node* v1, Node* v2, Node* v3, Node* v4); 1034 void Bind(RawMachineLabel* label); 1035 void Deoptimize(Node* state); 1036 void AbortCSADcheck(Node* message); 1037 void DebugBreak(); 1038 void Unreachable(); 1039 void Comment(const std::string& msg); 1040 void StaticAssert(Node* value, const char* source); 1041 1042 #if DEBUG 1043 void Bind(RawMachineLabel* label, AssemblerDebugInfo info); 1044 void SetInitialDebugInformation(AssemblerDebugInfo info); 1045 void PrintCurrentBlock(std::ostream& os); 1046 #endif // DEBUG 1047 bool InsideBlock(); 1048 1049 // Add success / exception successor blocks and ends the current block ending 1050 // in a potentially throwing call node. 1051 void Continuations(Node* call, RawMachineLabel* if_success, 1052 RawMachineLabel* if_exception); 1053 1054 // Variables. Phi(MachineRepresentation rep,Node * n1,Node * n2)1055 Node* Phi(MachineRepresentation rep, Node* n1, Node* n2) { 1056 return AddNode(common()->Phi(rep, 2), n1, n2, graph()->start()); 1057 } Phi(MachineRepresentation rep,Node * n1,Node * n2,Node * n3)1058 Node* Phi(MachineRepresentation rep, Node* n1, Node* n2, Node* n3) { 1059 return AddNode(common()->Phi(rep, 3), n1, n2, n3, graph()->start()); 1060 } Phi(MachineRepresentation rep,Node * n1,Node * n2,Node * n3,Node * n4)1061 Node* Phi(MachineRepresentation rep, Node* n1, Node* n2, Node* n3, Node* n4) { 1062 return AddNode(common()->Phi(rep, 4), n1, n2, n3, n4, graph()->start()); 1063 } 1064 Node* Phi(MachineRepresentation rep, int input_count, Node* const* inputs); 1065 void AppendPhiInput(Node* phi, Node* new_input); 1066 1067 // =========================================================================== 1068 // The following generic node creation methods can be used for operators that 1069 // are not covered by the above utility methods. There should rarely be a need 1070 // to do that outside of testing though. 1071 1072 Node* AddNode(const Operator* op, int input_count, Node* const* inputs); 1073 AddNode(const Operator * op)1074 Node* AddNode(const Operator* op) { 1075 return AddNode(op, 0, static_cast<Node* const*>(nullptr)); 1076 } 1077 1078 template <class... TArgs> AddNode(const Operator * op,Node * n1,TArgs...args)1079 Node* AddNode(const Operator* op, Node* n1, TArgs... args) { 1080 Node* buffer[] = {n1, args...}; 1081 return AddNode(op, sizeof...(args) + 1, buffer); 1082 } 1083 1084 void SetCurrentExternalSourcePosition(FileAndLine file_and_line); 1085 FileAndLine GetCurrentExternalSourcePosition() const; source_positions()1086 SourcePositionTable* source_positions() { return source_positions_; } 1087 1088 private: 1089 Node* MakeNode(const Operator* op, int input_count, Node* const* inputs); 1090 BasicBlock* Use(RawMachineLabel* label); 1091 BasicBlock* EnsureBlock(RawMachineLabel* label); 1092 BasicBlock* CurrentBlock(); 1093 1094 // A post-processing pass to add effect and control edges so that the graph 1095 // can be optimized and re-scheduled. 1096 // TODO(turbofan): Move this to a separate class. 1097 void MakeReschedulable(); 1098 Node* CreateNodeFromPredecessors(const std::vector<BasicBlock*>& predecessors, 1099 const std::vector<Node*>& sidetable, 1100 const Operator* op, 1101 const std::vector<Node*>& additional_inputs); 1102 void MakePhiBinary(Node* phi, int split_point, Node* left_control, 1103 Node* right_control); 1104 void MarkControlDeferred(Node* control_input); 1105 schedule()1106 Schedule* schedule() { return schedule_; } parameter_count()1107 size_t parameter_count() const { return call_descriptor_->ParameterCount(); } 1108 1109 static void OptimizeControlFlow(Schedule* schedule, Graph* graph, 1110 CommonOperatorBuilder* common); 1111 1112 Isolate* isolate_; 1113 1114 Graph* graph_; 1115 Schedule* schedule_; 1116 SourcePositionTable* source_positions_; 1117 MachineOperatorBuilder machine_; 1118 CommonOperatorBuilder common_; 1119 SimplifiedOperatorBuilder simplified_; 1120 CallDescriptor* call_descriptor_; 1121 Node* target_parameter_; 1122 NodeVector parameters_; 1123 BasicBlock* current_block_; 1124 }; 1125 1126 class V8_EXPORT_PRIVATE RawMachineLabel final { 1127 public: 1128 enum Type { kDeferred, kNonDeferred }; 1129 1130 explicit RawMachineLabel(Type type = kNonDeferred) 1131 : deferred_(type == kDeferred) {} 1132 ~RawMachineLabel(); 1133 RawMachineLabel(const RawMachineLabel&) = delete; 1134 RawMachineLabel& operator=(const RawMachineLabel&) = delete; 1135 block()1136 BasicBlock* block() const { return block_; } 1137 1138 private: 1139 BasicBlock* block_ = nullptr; 1140 bool used_ = false; 1141 bool bound_ = false; 1142 bool deferred_; 1143 friend class RawMachineAssembler; 1144 }; 1145 1146 } // namespace compiler 1147 } // namespace internal 1148 } // namespace v8 1149 1150 #endif // V8_COMPILER_RAW_MACHINE_ASSEMBLER_H_ 1151