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 "src/assembler.h" 9 #include "src/compiler/common-operator.h" 10 #include "src/compiler/graph.h" 11 #include "src/compiler/linkage.h" 12 #include "src/compiler/machine-operator.h" 13 #include "src/compiler/node.h" 14 #include "src/compiler/operator.h" 15 #include "src/factory.h" 16 17 namespace v8 { 18 namespace internal { 19 namespace compiler { 20 21 class BasicBlock; 22 class RawMachineLabel; 23 class Schedule; 24 25 26 // The RawMachineAssembler produces a low-level IR graph. All nodes are wired 27 // into a graph and also placed into a schedule immediately, hence subsequent 28 // code generation can happen without the need for scheduling. 29 // 30 // In order to create a schedule on-the-fly, the assembler keeps track of basic 31 // blocks by having one current basic block being populated and by referencing 32 // other basic blocks through the use of labels. 33 // 34 // Also note that the generated graph is only valid together with the generated 35 // schedule, using one without the other is invalid as the graph is inherently 36 // non-schedulable due to missing control and effect dependencies. 37 class RawMachineAssembler { 38 public: 39 RawMachineAssembler( 40 Isolate* isolate, Graph* graph, CallDescriptor* call_descriptor, 41 MachineRepresentation word = MachineType::PointerRepresentation(), 42 MachineOperatorBuilder::Flags flags = 43 MachineOperatorBuilder::Flag::kNoFlags); ~RawMachineAssembler()44 ~RawMachineAssembler() {} 45 isolate()46 Isolate* isolate() const { return isolate_; } graph()47 Graph* graph() const { return graph_; } zone()48 Zone* zone() const { return graph()->zone(); } machine()49 MachineOperatorBuilder* machine() { return &machine_; } common()50 CommonOperatorBuilder* common() { return &common_; } call_descriptor()51 CallDescriptor* call_descriptor() const { return call_descriptor_; } 52 53 // Finalizes the schedule and exports it to be used for code generation. Note 54 // that this RawMachineAssembler becomes invalid after export. 55 Schedule* Export(); 56 57 // =========================================================================== 58 // The following utility methods create new nodes with specific operators and 59 // place them into the current basic block. They don't perform control flow, 60 // hence will not switch the current basic block. 61 NullConstant()62 Node* NullConstant() { 63 return HeapConstant(isolate()->factory()->null_value()); 64 } 65 UndefinedConstant()66 Node* UndefinedConstant() { 67 return HeapConstant(isolate()->factory()->undefined_value()); 68 } 69 70 // Constants. PointerConstant(void * value)71 Node* PointerConstant(void* value) { 72 return IntPtrConstant(reinterpret_cast<intptr_t>(value)); 73 } IntPtrConstant(intptr_t value)74 Node* IntPtrConstant(intptr_t value) { 75 // TODO(dcarney): mark generated code as unserializable if value != 0. 76 return kPointerSize == 8 ? Int64Constant(value) 77 : Int32Constant(static_cast<int>(value)); 78 } Int32Constant(int32_t value)79 Node* Int32Constant(int32_t value) { 80 return AddNode(common()->Int32Constant(value)); 81 } Int64Constant(int64_t value)82 Node* Int64Constant(int64_t value) { 83 return AddNode(common()->Int64Constant(value)); 84 } NumberConstant(double value)85 Node* NumberConstant(double value) { 86 return AddNode(common()->NumberConstant(value)); 87 } Float32Constant(float value)88 Node* Float32Constant(float value) { 89 return AddNode(common()->Float32Constant(value)); 90 } Float64Constant(double value)91 Node* Float64Constant(double value) { 92 return AddNode(common()->Float64Constant(value)); 93 } HeapConstant(Handle<HeapObject> object)94 Node* HeapConstant(Handle<HeapObject> object) { 95 return AddNode(common()->HeapConstant(object)); 96 } BooleanConstant(bool value)97 Node* BooleanConstant(bool value) { 98 Handle<Object> object = isolate()->factory()->ToBoolean(value); 99 return HeapConstant(Handle<HeapObject>::cast(object)); 100 } ExternalConstant(ExternalReference address)101 Node* ExternalConstant(ExternalReference address) { 102 return AddNode(common()->ExternalConstant(address)); 103 } 104 Projection(int index,Node * a)105 Node* Projection(int index, Node* a) { 106 return AddNode(common()->Projection(index), a); 107 } 108 109 // Memory Operations. Load(MachineType rep,Node * base)110 Node* Load(MachineType rep, Node* base) { 111 return Load(rep, base, IntPtrConstant(0)); 112 } Load(MachineType rep,Node * base,Node * index)113 Node* Load(MachineType rep, Node* base, Node* index) { 114 return AddNode(machine()->Load(rep), base, index); 115 } Store(MachineRepresentation rep,Node * base,Node * value,WriteBarrierKind write_barrier)116 Node* Store(MachineRepresentation rep, Node* base, Node* value, 117 WriteBarrierKind write_barrier) { 118 return Store(rep, base, IntPtrConstant(0), value, write_barrier); 119 } Store(MachineRepresentation rep,Node * base,Node * index,Node * value,WriteBarrierKind write_barrier)120 Node* Store(MachineRepresentation rep, Node* base, Node* index, Node* value, 121 WriteBarrierKind write_barrier) { 122 return AddNode(machine()->Store(StoreRepresentation(rep, write_barrier)), 123 base, index, value); 124 } 125 126 // Arithmetic Operations. WordAnd(Node * a,Node * b)127 Node* WordAnd(Node* a, Node* b) { 128 return AddNode(machine()->WordAnd(), a, b); 129 } WordOr(Node * a,Node * b)130 Node* WordOr(Node* a, Node* b) { return AddNode(machine()->WordOr(), a, b); } WordXor(Node * a,Node * b)131 Node* WordXor(Node* a, Node* b) { 132 return AddNode(machine()->WordXor(), a, b); 133 } WordShl(Node * a,Node * b)134 Node* WordShl(Node* a, Node* b) { 135 return AddNode(machine()->WordShl(), a, b); 136 } WordShr(Node * a,Node * b)137 Node* WordShr(Node* a, Node* b) { 138 return AddNode(machine()->WordShr(), a, b); 139 } WordSar(Node * a,Node * b)140 Node* WordSar(Node* a, Node* b) { 141 return AddNode(machine()->WordSar(), a, b); 142 } WordRor(Node * a,Node * b)143 Node* WordRor(Node* a, Node* b) { 144 return AddNode(machine()->WordRor(), a, b); 145 } WordEqual(Node * a,Node * b)146 Node* WordEqual(Node* a, Node* b) { 147 return AddNode(machine()->WordEqual(), a, b); 148 } WordNotEqual(Node * a,Node * b)149 Node* WordNotEqual(Node* a, Node* b) { 150 return WordBinaryNot(WordEqual(a, b)); 151 } WordNot(Node * a)152 Node* WordNot(Node* a) { 153 if (machine()->Is32()) { 154 return Word32Not(a); 155 } else { 156 return Word64Not(a); 157 } 158 } WordBinaryNot(Node * a)159 Node* WordBinaryNot(Node* a) { 160 if (machine()->Is32()) { 161 return Word32BinaryNot(a); 162 } else { 163 return Word64BinaryNot(a); 164 } 165 } 166 Word32And(Node * a,Node * b)167 Node* Word32And(Node* a, Node* b) { 168 return AddNode(machine()->Word32And(), a, b); 169 } Word32Or(Node * a,Node * b)170 Node* Word32Or(Node* a, Node* b) { 171 return AddNode(machine()->Word32Or(), a, b); 172 } Word32Xor(Node * a,Node * b)173 Node* Word32Xor(Node* a, Node* b) { 174 return AddNode(machine()->Word32Xor(), a, b); 175 } Word32Shl(Node * a,Node * b)176 Node* Word32Shl(Node* a, Node* b) { 177 return AddNode(machine()->Word32Shl(), a, b); 178 } Word32Shr(Node * a,Node * b)179 Node* Word32Shr(Node* a, Node* b) { 180 return AddNode(machine()->Word32Shr(), a, b); 181 } Word32Sar(Node * a,Node * b)182 Node* Word32Sar(Node* a, Node* b) { 183 return AddNode(machine()->Word32Sar(), a, b); 184 } Word32Ror(Node * a,Node * b)185 Node* Word32Ror(Node* a, Node* b) { 186 return AddNode(machine()->Word32Ror(), a, b); 187 } Word32Clz(Node * a)188 Node* Word32Clz(Node* a) { return AddNode(machine()->Word32Clz(), a); } Word32Equal(Node * a,Node * b)189 Node* Word32Equal(Node* a, Node* b) { 190 return AddNode(machine()->Word32Equal(), a, b); 191 } Word32NotEqual(Node * a,Node * b)192 Node* Word32NotEqual(Node* a, Node* b) { 193 return Word32BinaryNot(Word32Equal(a, b)); 194 } Word32Not(Node * a)195 Node* Word32Not(Node* a) { return Word32Xor(a, Int32Constant(-1)); } Word32BinaryNot(Node * a)196 Node* Word32BinaryNot(Node* a) { return Word32Equal(a, Int32Constant(0)); } 197 Word64And(Node * a,Node * b)198 Node* Word64And(Node* a, Node* b) { 199 return AddNode(machine()->Word64And(), a, b); 200 } Word64Or(Node * a,Node * b)201 Node* Word64Or(Node* a, Node* b) { 202 return AddNode(machine()->Word64Or(), a, b); 203 } Word64Xor(Node * a,Node * b)204 Node* Word64Xor(Node* a, Node* b) { 205 return AddNode(machine()->Word64Xor(), a, b); 206 } Word64Shl(Node * a,Node * b)207 Node* Word64Shl(Node* a, Node* b) { 208 return AddNode(machine()->Word64Shl(), a, b); 209 } Word64Shr(Node * a,Node * b)210 Node* Word64Shr(Node* a, Node* b) { 211 return AddNode(machine()->Word64Shr(), a, b); 212 } Word64Sar(Node * a,Node * b)213 Node* Word64Sar(Node* a, Node* b) { 214 return AddNode(machine()->Word64Sar(), a, b); 215 } Word64Ror(Node * a,Node * b)216 Node* Word64Ror(Node* a, Node* b) { 217 return AddNode(machine()->Word64Ror(), a, b); 218 } Word64Clz(Node * a)219 Node* Word64Clz(Node* a) { return AddNode(machine()->Word64Clz(), a); } Word64Equal(Node * a,Node * b)220 Node* Word64Equal(Node* a, Node* b) { 221 return AddNode(machine()->Word64Equal(), a, b); 222 } Word64NotEqual(Node * a,Node * b)223 Node* Word64NotEqual(Node* a, Node* b) { 224 return Word64BinaryNot(Word64Equal(a, b)); 225 } Word64Not(Node * a)226 Node* Word64Not(Node* a) { return Word64Xor(a, Int64Constant(-1)); } Word64BinaryNot(Node * a)227 Node* Word64BinaryNot(Node* a) { return Word64Equal(a, Int64Constant(0)); } 228 Int32Add(Node * a,Node * b)229 Node* Int32Add(Node* a, Node* b) { 230 return AddNode(machine()->Int32Add(), a, b); 231 } Int32AddWithOverflow(Node * a,Node * b)232 Node* Int32AddWithOverflow(Node* a, Node* b) { 233 return AddNode(machine()->Int32AddWithOverflow(), a, b); 234 } Int32Sub(Node * a,Node * b)235 Node* Int32Sub(Node* a, Node* b) { 236 return AddNode(machine()->Int32Sub(), a, b); 237 } Int32SubWithOverflow(Node * a,Node * b)238 Node* Int32SubWithOverflow(Node* a, Node* b) { 239 return AddNode(machine()->Int32SubWithOverflow(), a, b); 240 } Int32Mul(Node * a,Node * b)241 Node* Int32Mul(Node* a, Node* b) { 242 return AddNode(machine()->Int32Mul(), a, b); 243 } Int32MulHigh(Node * a,Node * b)244 Node* Int32MulHigh(Node* a, Node* b) { 245 return AddNode(machine()->Int32MulHigh(), a, b); 246 } Int32Div(Node * a,Node * b)247 Node* Int32Div(Node* a, Node* b) { 248 return AddNode(machine()->Int32Div(), a, b); 249 } Int32Mod(Node * a,Node * b)250 Node* Int32Mod(Node* a, Node* b) { 251 return AddNode(machine()->Int32Mod(), a, b); 252 } Int32LessThan(Node * a,Node * b)253 Node* Int32LessThan(Node* a, Node* b) { 254 return AddNode(machine()->Int32LessThan(), a, b); 255 } Int32LessThanOrEqual(Node * a,Node * b)256 Node* Int32LessThanOrEqual(Node* a, Node* b) { 257 return AddNode(machine()->Int32LessThanOrEqual(), a, b); 258 } Uint32Div(Node * a,Node * b)259 Node* Uint32Div(Node* a, Node* b) { 260 return AddNode(machine()->Uint32Div(), a, b); 261 } Uint32LessThan(Node * a,Node * b)262 Node* Uint32LessThan(Node* a, Node* b) { 263 return AddNode(machine()->Uint32LessThan(), a, b); 264 } Uint32LessThanOrEqual(Node * a,Node * b)265 Node* Uint32LessThanOrEqual(Node* a, Node* b) { 266 return AddNode(machine()->Uint32LessThanOrEqual(), a, b); 267 } Uint32Mod(Node * a,Node * b)268 Node* Uint32Mod(Node* a, Node* b) { 269 return AddNode(machine()->Uint32Mod(), a, b); 270 } Uint32MulHigh(Node * a,Node * b)271 Node* Uint32MulHigh(Node* a, Node* b) { 272 return AddNode(machine()->Uint32MulHigh(), a, b); 273 } Int32GreaterThan(Node * a,Node * b)274 Node* Int32GreaterThan(Node* a, Node* b) { return Int32LessThan(b, a); } Int32GreaterThanOrEqual(Node * a,Node * b)275 Node* Int32GreaterThanOrEqual(Node* a, Node* b) { 276 return Int32LessThanOrEqual(b, a); 277 } Int32Neg(Node * a)278 Node* Int32Neg(Node* a) { return Int32Sub(Int32Constant(0), a); } 279 Int64Add(Node * a,Node * b)280 Node* Int64Add(Node* a, Node* b) { 281 return AddNode(machine()->Int64Add(), a, b); 282 } Int64AddWithOverflow(Node * a,Node * b)283 Node* Int64AddWithOverflow(Node* a, Node* b) { 284 return AddNode(machine()->Int64AddWithOverflow(), a, b); 285 } Int64Sub(Node * a,Node * b)286 Node* Int64Sub(Node* a, Node* b) { 287 return AddNode(machine()->Int64Sub(), a, b); 288 } Int64SubWithOverflow(Node * a,Node * b)289 Node* Int64SubWithOverflow(Node* a, Node* b) { 290 return AddNode(machine()->Int64SubWithOverflow(), a, b); 291 } Int64Mul(Node * a,Node * b)292 Node* Int64Mul(Node* a, Node* b) { 293 return AddNode(machine()->Int64Mul(), a, b); 294 } Int64Div(Node * a,Node * b)295 Node* Int64Div(Node* a, Node* b) { 296 return AddNode(machine()->Int64Div(), a, b); 297 } Int64Mod(Node * a,Node * b)298 Node* Int64Mod(Node* a, Node* b) { 299 return AddNode(machine()->Int64Mod(), a, b); 300 } Int64Neg(Node * a)301 Node* Int64Neg(Node* a) { return Int64Sub(Int64Constant(0), a); } Int64LessThan(Node * a,Node * b)302 Node* Int64LessThan(Node* a, Node* b) { 303 return AddNode(machine()->Int64LessThan(), a, b); 304 } Int64LessThanOrEqual(Node * a,Node * b)305 Node* Int64LessThanOrEqual(Node* a, Node* b) { 306 return AddNode(machine()->Int64LessThanOrEqual(), a, b); 307 } Uint64LessThan(Node * a,Node * b)308 Node* Uint64LessThan(Node* a, Node* b) { 309 return AddNode(machine()->Uint64LessThan(), a, b); 310 } Uint64LessThanOrEqual(Node * a,Node * b)311 Node* Uint64LessThanOrEqual(Node* a, Node* b) { 312 return AddNode(machine()->Uint64LessThanOrEqual(), a, b); 313 } Int64GreaterThan(Node * a,Node * b)314 Node* Int64GreaterThan(Node* a, Node* b) { return Int64LessThan(b, a); } Int64GreaterThanOrEqual(Node * a,Node * b)315 Node* Int64GreaterThanOrEqual(Node* a, Node* b) { 316 return Int64LessThanOrEqual(b, a); 317 } Uint64Div(Node * a,Node * b)318 Node* Uint64Div(Node* a, Node* b) { 319 return AddNode(machine()->Uint64Div(), a, b); 320 } Uint64Mod(Node * a,Node * b)321 Node* Uint64Mod(Node* a, Node* b) { 322 return AddNode(machine()->Uint64Mod(), a, b); 323 } 324 325 #define INTPTR_BINOP(prefix, name) \ 326 Node* IntPtr##name(Node* a, Node* b) { \ 327 return kPointerSize == 8 ? prefix##64##name(a, b) \ 328 : prefix##32##name(a, b); \ 329 } 330 331 INTPTR_BINOP(Int, Add); 332 INTPTR_BINOP(Int, Sub); 333 INTPTR_BINOP(Int, LessThan); 334 INTPTR_BINOP(Int, LessThanOrEqual); 335 INTPTR_BINOP(Word, Equal); 336 INTPTR_BINOP(Word, NotEqual); 337 INTPTR_BINOP(Int, GreaterThanOrEqual); 338 INTPTR_BINOP(Int, GreaterThan); 339 340 #undef INTPTR_BINOP 341 Float32Add(Node * a,Node * b)342 Node* Float32Add(Node* a, Node* b) { 343 return AddNode(machine()->Float32Add(), a, b); 344 } Float32Sub(Node * a,Node * b)345 Node* Float32Sub(Node* a, Node* b) { 346 return AddNode(machine()->Float32Sub(), a, b); 347 } Float32Mul(Node * a,Node * b)348 Node* Float32Mul(Node* a, Node* b) { 349 return AddNode(machine()->Float32Mul(), a, b); 350 } Float32Div(Node * a,Node * b)351 Node* Float32Div(Node* a, Node* b) { 352 return AddNode(machine()->Float32Div(), a, b); 353 } Float32Max(Node * a,Node * b)354 Node* Float32Max(Node* a, Node* b) { 355 return AddNode(machine()->Float32Max().op(), a, b); 356 } Float32Min(Node * a,Node * b)357 Node* Float32Min(Node* a, Node* b) { 358 return AddNode(machine()->Float32Min().op(), a, b); 359 } Float32Abs(Node * a)360 Node* Float32Abs(Node* a) { return AddNode(machine()->Float32Abs(), a); } Float32Sqrt(Node * a)361 Node* Float32Sqrt(Node* a) { return AddNode(machine()->Float32Sqrt(), a); } Float32Equal(Node * a,Node * b)362 Node* Float32Equal(Node* a, Node* b) { 363 return AddNode(machine()->Float32Equal(), a, b); 364 } Float32NotEqual(Node * a,Node * b)365 Node* Float32NotEqual(Node* a, Node* b) { 366 return WordBinaryNot(Float32Equal(a, b)); 367 } Float32LessThan(Node * a,Node * b)368 Node* Float32LessThan(Node* a, Node* b) { 369 return AddNode(machine()->Float32LessThan(), a, b); 370 } Float32LessThanOrEqual(Node * a,Node * b)371 Node* Float32LessThanOrEqual(Node* a, Node* b) { 372 return AddNode(machine()->Float32LessThanOrEqual(), a, b); 373 } Float32GreaterThan(Node * a,Node * b)374 Node* Float32GreaterThan(Node* a, Node* b) { return Float32LessThan(b, a); } Float32GreaterThanOrEqual(Node * a,Node * b)375 Node* Float32GreaterThanOrEqual(Node* a, Node* b) { 376 return Float32LessThanOrEqual(b, a); 377 } 378 Float64Add(Node * a,Node * b)379 Node* Float64Add(Node* a, Node* b) { 380 return AddNode(machine()->Float64Add(), a, b); 381 } Float64Sub(Node * a,Node * b)382 Node* Float64Sub(Node* a, Node* b) { 383 return AddNode(machine()->Float64Sub(), a, b); 384 } Float64Mul(Node * a,Node * b)385 Node* Float64Mul(Node* a, Node* b) { 386 return AddNode(machine()->Float64Mul(), a, b); 387 } Float64Div(Node * a,Node * b)388 Node* Float64Div(Node* a, Node* b) { 389 return AddNode(machine()->Float64Div(), a, b); 390 } Float64Mod(Node * a,Node * b)391 Node* Float64Mod(Node* a, Node* b) { 392 return AddNode(machine()->Float64Mod(), a, b); 393 } Float64Max(Node * a,Node * b)394 Node* Float64Max(Node* a, Node* b) { 395 return AddNode(machine()->Float64Max().op(), a, b); 396 } Float64Min(Node * a,Node * b)397 Node* Float64Min(Node* a, Node* b) { 398 return AddNode(machine()->Float64Min().op(), a, b); 399 } Float64Abs(Node * a)400 Node* Float64Abs(Node* a) { return AddNode(machine()->Float64Abs(), a); } Float64Sqrt(Node * a)401 Node* Float64Sqrt(Node* a) { return AddNode(machine()->Float64Sqrt(), a); } Float64Equal(Node * a,Node * b)402 Node* Float64Equal(Node* a, Node* b) { 403 return AddNode(machine()->Float64Equal(), a, b); 404 } Float64NotEqual(Node * a,Node * b)405 Node* Float64NotEqual(Node* a, Node* b) { 406 return WordBinaryNot(Float64Equal(a, b)); 407 } Float64LessThan(Node * a,Node * b)408 Node* Float64LessThan(Node* a, Node* b) { 409 return AddNode(machine()->Float64LessThan(), a, b); 410 } Float64LessThanOrEqual(Node * a,Node * b)411 Node* Float64LessThanOrEqual(Node* a, Node* b) { 412 return AddNode(machine()->Float64LessThanOrEqual(), a, b); 413 } Float64GreaterThan(Node * a,Node * b)414 Node* Float64GreaterThan(Node* a, Node* b) { return Float64LessThan(b, a); } Float64GreaterThanOrEqual(Node * a,Node * b)415 Node* Float64GreaterThanOrEqual(Node* a, Node* b) { 416 return Float64LessThanOrEqual(b, a); 417 } 418 419 // Conversions. ChangeFloat32ToFloat64(Node * a)420 Node* ChangeFloat32ToFloat64(Node* a) { 421 return AddNode(machine()->ChangeFloat32ToFloat64(), a); 422 } ChangeInt32ToFloat64(Node * a)423 Node* ChangeInt32ToFloat64(Node* a) { 424 return AddNode(machine()->ChangeInt32ToFloat64(), a); 425 } ChangeUint32ToFloat64(Node * a)426 Node* ChangeUint32ToFloat64(Node* a) { 427 return AddNode(machine()->ChangeUint32ToFloat64(), a); 428 } ChangeFloat64ToInt32(Node * a)429 Node* ChangeFloat64ToInt32(Node* a) { 430 return AddNode(machine()->ChangeFloat64ToInt32(), a); 431 } ChangeFloat64ToUint32(Node * a)432 Node* ChangeFloat64ToUint32(Node* a) { 433 return AddNode(machine()->ChangeFloat64ToUint32(), a); 434 } TruncateFloat32ToInt64(Node * a)435 Node* TruncateFloat32ToInt64(Node* a) { 436 // TODO(ahaas): Remove this function as soon as it is not used anymore in 437 // WebAssembly. 438 return AddNode(machine()->TryTruncateFloat32ToInt64(), a); 439 } TryTruncateFloat32ToInt64(Node * a)440 Node* TryTruncateFloat32ToInt64(Node* a) { 441 return AddNode(machine()->TryTruncateFloat32ToInt64(), a); 442 } TruncateFloat64ToInt64(Node * a)443 Node* TruncateFloat64ToInt64(Node* a) { 444 // TODO(ahaas): Remove this function as soon as it is not used anymore in 445 // WebAssembly. 446 return AddNode(machine()->TryTruncateFloat64ToInt64(), a); 447 } TryTruncateFloat64ToInt64(Node * a)448 Node* TryTruncateFloat64ToInt64(Node* a) { 449 return AddNode(machine()->TryTruncateFloat64ToInt64(), a); 450 } TruncateFloat32ToUint64(Node * a)451 Node* TruncateFloat32ToUint64(Node* a) { 452 // TODO(ahaas): Remove this function as soon as it is not used anymore in 453 // WebAssembly. 454 return AddNode(machine()->TryTruncateFloat32ToUint64(), a); 455 } TryTruncateFloat32ToUint64(Node * a)456 Node* TryTruncateFloat32ToUint64(Node* a) { 457 return AddNode(machine()->TryTruncateFloat32ToUint64(), a); 458 } TruncateFloat64ToUint64(Node * a)459 Node* TruncateFloat64ToUint64(Node* a) { 460 // TODO(ahaas): Remove this function as soon as it is not used anymore in 461 // WebAssembly. 462 return AddNode(machine()->TryTruncateFloat64ToUint64(), a); 463 } TryTruncateFloat64ToUint64(Node * a)464 Node* TryTruncateFloat64ToUint64(Node* a) { 465 return AddNode(machine()->TryTruncateFloat64ToUint64(), a); 466 } ChangeInt32ToInt64(Node * a)467 Node* ChangeInt32ToInt64(Node* a) { 468 return AddNode(machine()->ChangeInt32ToInt64(), a); 469 } ChangeUint32ToUint64(Node * a)470 Node* ChangeUint32ToUint64(Node* a) { 471 return AddNode(machine()->ChangeUint32ToUint64(), a); 472 } TruncateFloat64ToFloat32(Node * a)473 Node* TruncateFloat64ToFloat32(Node* a) { 474 return AddNode(machine()->TruncateFloat64ToFloat32(), a); 475 } TruncateFloat64ToInt32(TruncationMode mode,Node * a)476 Node* TruncateFloat64ToInt32(TruncationMode mode, Node* a) { 477 return AddNode(machine()->TruncateFloat64ToInt32(mode), a); 478 } TruncateInt64ToInt32(Node * a)479 Node* TruncateInt64ToInt32(Node* a) { 480 return AddNode(machine()->TruncateInt64ToInt32(), a); 481 } RoundInt64ToFloat32(Node * a)482 Node* RoundInt64ToFloat32(Node* a) { 483 return AddNode(machine()->RoundInt64ToFloat32(), a); 484 } RoundInt64ToFloat64(Node * a)485 Node* RoundInt64ToFloat64(Node* a) { 486 return AddNode(machine()->RoundInt64ToFloat64(), a); 487 } RoundUint64ToFloat32(Node * a)488 Node* RoundUint64ToFloat32(Node* a) { 489 return AddNode(machine()->RoundUint64ToFloat32(), a); 490 } RoundUint64ToFloat64(Node * a)491 Node* RoundUint64ToFloat64(Node* a) { 492 return AddNode(machine()->RoundUint64ToFloat64(), a); 493 } BitcastFloat32ToInt32(Node * a)494 Node* BitcastFloat32ToInt32(Node* a) { 495 return AddNode(machine()->BitcastFloat32ToInt32(), a); 496 } BitcastFloat64ToInt64(Node * a)497 Node* BitcastFloat64ToInt64(Node* a) { 498 return AddNode(machine()->BitcastFloat64ToInt64(), a); 499 } BitcastInt32ToFloat32(Node * a)500 Node* BitcastInt32ToFloat32(Node* a) { 501 return AddNode(machine()->BitcastInt32ToFloat32(), a); 502 } BitcastInt64ToFloat64(Node * a)503 Node* BitcastInt64ToFloat64(Node* a) { 504 return AddNode(machine()->BitcastInt64ToFloat64(), a); 505 } Float32RoundDown(Node * a)506 Node* Float32RoundDown(Node* a) { 507 return AddNode(machine()->Float32RoundDown().op(), a); 508 } Float64RoundDown(Node * a)509 Node* Float64RoundDown(Node* a) { 510 return AddNode(machine()->Float64RoundDown().op(), a); 511 } Float32RoundUp(Node * a)512 Node* Float32RoundUp(Node* a) { 513 return AddNode(machine()->Float32RoundUp().op(), a); 514 } Float64RoundUp(Node * a)515 Node* Float64RoundUp(Node* a) { 516 return AddNode(machine()->Float64RoundUp().op(), a); 517 } Float32RoundTruncate(Node * a)518 Node* Float32RoundTruncate(Node* a) { 519 return AddNode(machine()->Float32RoundTruncate().op(), a); 520 } Float64RoundTruncate(Node * a)521 Node* Float64RoundTruncate(Node* a) { 522 return AddNode(machine()->Float64RoundTruncate().op(), a); 523 } Float64RoundTiesAway(Node * a)524 Node* Float64RoundTiesAway(Node* a) { 525 return AddNode(machine()->Float64RoundTiesAway().op(), a); 526 } Float32RoundTiesEven(Node * a)527 Node* Float32RoundTiesEven(Node* a) { 528 return AddNode(machine()->Float32RoundTiesEven().op(), a); 529 } Float64RoundTiesEven(Node * a)530 Node* Float64RoundTiesEven(Node* a) { 531 return AddNode(machine()->Float64RoundTiesEven().op(), a); 532 } 533 534 // Float64 bit operations. Float64ExtractLowWord32(Node * a)535 Node* Float64ExtractLowWord32(Node* a) { 536 return AddNode(machine()->Float64ExtractLowWord32(), a); 537 } Float64ExtractHighWord32(Node * a)538 Node* Float64ExtractHighWord32(Node* a) { 539 return AddNode(machine()->Float64ExtractHighWord32(), a); 540 } Float64InsertLowWord32(Node * a,Node * b)541 Node* Float64InsertLowWord32(Node* a, Node* b) { 542 return AddNode(machine()->Float64InsertLowWord32(), a, b); 543 } Float64InsertHighWord32(Node * a,Node * b)544 Node* Float64InsertHighWord32(Node* a, Node* b) { 545 return AddNode(machine()->Float64InsertHighWord32(), a, b); 546 } 547 548 // Stack operations. LoadStackPointer()549 Node* LoadStackPointer() { return AddNode(machine()->LoadStackPointer()); } LoadFramePointer()550 Node* LoadFramePointer() { return AddNode(machine()->LoadFramePointer()); } 551 552 // Parameters. 553 Node* Parameter(size_t index); 554 555 // Pointer utilities. 556 Node* LoadFromPointer(void* address, MachineType rep, int32_t offset = 0) { 557 return Load(rep, PointerConstant(address), Int32Constant(offset)); 558 } StoreToPointer(void * address,MachineRepresentation rep,Node * node)559 Node* StoreToPointer(void* address, MachineRepresentation rep, Node* node) { 560 return Store(rep, PointerConstant(address), node, kNoWriteBarrier); 561 } StringConstant(const char * string)562 Node* StringConstant(const char* string) { 563 return HeapConstant(isolate()->factory()->InternalizeUtf8String(string)); 564 } 565 566 // Call a given call descriptor and the given arguments. 567 Node* CallN(CallDescriptor* desc, Node* function, Node** args); 568 // Call a given call descriptor and the given arguments and frame-state. 569 Node* CallNWithFrameState(CallDescriptor* desc, Node* function, Node** args, 570 Node* frame_state); 571 // Call to a runtime function with one arguments. 572 Node* CallRuntime1(Runtime::FunctionId function, Node* arg0, Node* context); 573 // Call to a runtime function with two arguments. 574 Node* CallRuntime2(Runtime::FunctionId function, Node* arg1, Node* arg2, 575 Node* context); 576 // Call to a runtime function with four arguments. 577 Node* CallRuntime4(Runtime::FunctionId function, Node* arg1, Node* arg2, 578 Node* arg3, Node* arg4, Node* context); 579 // Call to a C function with zero arguments. 580 Node* CallCFunction0(MachineType return_type, Node* function); 581 // Call to a C function with one parameter. 582 Node* CallCFunction1(MachineType return_type, MachineType arg0_type, 583 Node* function, Node* arg0); 584 // Call to a C function with two arguments. 585 Node* CallCFunction2(MachineType return_type, MachineType arg0_type, 586 MachineType arg1_type, Node* function, Node* arg0, 587 Node* arg1); 588 // Call to a C function with eight arguments. 589 Node* CallCFunction8(MachineType return_type, MachineType arg0_type, 590 MachineType arg1_type, MachineType arg2_type, 591 MachineType arg3_type, MachineType arg4_type, 592 MachineType arg5_type, MachineType arg6_type, 593 MachineType arg7_type, Node* function, Node* arg0, 594 Node* arg1, Node* arg2, Node* arg3, Node* arg4, 595 Node* arg5, Node* arg6, Node* arg7); 596 597 // Tail call the given call descriptor and the given arguments. 598 Node* TailCallN(CallDescriptor* call_descriptor, Node* function, Node** args); 599 // Tail call to a runtime function with one argument. 600 Node* TailCallRuntime1(Runtime::FunctionId function, Node* arg0, 601 Node* context); 602 // Tail call to a runtime function with two arguments. 603 Node* TailCallRuntime2(Runtime::FunctionId function, Node* arg1, Node* arg2, 604 Node* context); 605 606 607 // =========================================================================== 608 // The following utility methods deal with control flow, hence might switch 609 // the current basic block or create new basic blocks for labels. 610 611 // Control flow. 612 void Goto(RawMachineLabel* label); 613 void Branch(Node* condition, RawMachineLabel* true_val, 614 RawMachineLabel* false_val); 615 void Switch(Node* index, RawMachineLabel* default_label, int32_t* case_values, 616 RawMachineLabel** case_labels, size_t case_count); 617 void Return(Node* value); 618 void Return(Node* v1, Node* v2); 619 void Return(Node* v1, Node* v2, Node* v3); 620 void Bind(RawMachineLabel* label); 621 void Deoptimize(Node* state); 622 623 // Variables. Phi(MachineRepresentation rep,Node * n1,Node * n2)624 Node* Phi(MachineRepresentation rep, Node* n1, Node* n2) { 625 return AddNode(common()->Phi(rep, 2), n1, n2); 626 } Phi(MachineRepresentation rep,Node * n1,Node * n2,Node * n3)627 Node* Phi(MachineRepresentation rep, Node* n1, Node* n2, Node* n3) { 628 return AddNode(common()->Phi(rep, 3), n1, n2, n3); 629 } Phi(MachineRepresentation rep,Node * n1,Node * n2,Node * n3,Node * n4)630 Node* Phi(MachineRepresentation rep, Node* n1, Node* n2, Node* n3, Node* n4) { 631 return AddNode(common()->Phi(rep, 4), n1, n2, n3, n4); 632 } 633 634 // =========================================================================== 635 // The following generic node creation methods can be used for operators that 636 // are not covered by the above utility methods. There should rarely be a need 637 // to do that outside of testing though. 638 639 Node* AddNode(const Operator* op, int input_count, Node** inputs); 640 AddNode(const Operator * op)641 Node* AddNode(const Operator* op) { 642 return AddNode(op, 0, static_cast<Node**>(nullptr)); 643 } 644 645 template <class... TArgs> AddNode(const Operator * op,Node * n1,TArgs...args)646 Node* AddNode(const Operator* op, Node* n1, TArgs... args) { 647 Node* buffer[] = {n1, args...}; 648 return AddNode(op, sizeof...(args) + 1, buffer); 649 } 650 651 private: 652 Node* MakeNode(const Operator* op, int input_count, Node** inputs); 653 BasicBlock* Use(RawMachineLabel* label); 654 BasicBlock* EnsureBlock(RawMachineLabel* label); 655 BasicBlock* CurrentBlock(); 656 schedule()657 Schedule* schedule() { return schedule_; } parameter_count()658 size_t parameter_count() const { return machine_sig()->parameter_count(); } machine_sig()659 const MachineSignature* machine_sig() const { 660 return call_descriptor_->GetMachineSignature(); 661 } 662 663 Isolate* isolate_; 664 Graph* graph_; 665 Schedule* schedule_; 666 MachineOperatorBuilder machine_; 667 CommonOperatorBuilder common_; 668 CallDescriptor* call_descriptor_; 669 NodeVector parameters_; 670 BasicBlock* current_block_; 671 672 DISALLOW_COPY_AND_ASSIGN(RawMachineAssembler); 673 }; 674 675 676 class RawMachineLabel final { 677 public: 678 RawMachineLabel(); 679 ~RawMachineLabel(); 680 681 private: 682 BasicBlock* block_; 683 bool used_; 684 bool bound_; 685 friend class RawMachineAssembler; 686 DISALLOW_COPY_AND_ASSIGN(RawMachineLabel); 687 }; 688 689 } // namespace compiler 690 } // namespace internal 691 } // namespace v8 692 693 #endif // V8_COMPILER_RAW_MACHINE_ASSEMBLER_H_ 694