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