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/v8.h" 9 10 #include "src/compiler/common-operator.h" 11 #include "src/compiler/graph-builder.h" 12 #include "src/compiler/linkage.h" 13 #include "src/compiler/machine-operator.h" 14 #include "src/compiler/node.h" 15 #include "src/compiler/operator.h" 16 17 18 namespace v8 { 19 namespace internal { 20 namespace compiler { 21 22 class BasicBlock; 23 class Schedule; 24 25 26 class RawMachineAssembler : public GraphBuilder { 27 public: 28 class Label { 29 public: 30 Label() : block_(NULL), used_(false), bound_(false) {} 31 ~Label() { DCHECK(bound_ || !used_); } 32 33 BasicBlock* block() { return block_; } 34 35 private: 36 // Private constructor for exit label. 37 explicit Label(BasicBlock* block) 38 : block_(block), used_(false), bound_(false) {} 39 40 BasicBlock* block_; 41 bool used_; 42 bool bound_; 43 friend class RawMachineAssembler; 44 DISALLOW_COPY_AND_ASSIGN(Label); 45 }; 46 47 RawMachineAssembler(Graph* graph, MachineSignature* machine_sig, 48 MachineType word = kMachPtr); 49 virtual ~RawMachineAssembler() {} 50 51 Isolate* isolate() const { return zone()->isolate(); } 52 Zone* zone() const { return graph()->zone(); } 53 MachineOperatorBuilder* machine() { return &machine_; } 54 CommonOperatorBuilder* common() { return &common_; } 55 CallDescriptor* call_descriptor() const { return call_descriptor_; } 56 size_t parameter_count() const { return machine_sig_->parameter_count(); } 57 MachineSignature* machine_sig() const { return machine_sig_; } 58 59 Node* UndefinedConstant() { 60 Unique<Object> unique = Unique<Object>::CreateImmovable( 61 isolate()->factory()->undefined_value()); 62 return NewNode(common()->HeapConstant(unique)); 63 } 64 65 // Constants. 66 Node* PointerConstant(void* value) { 67 return IntPtrConstant(reinterpret_cast<intptr_t>(value)); 68 } 69 Node* IntPtrConstant(intptr_t value) { 70 // TODO(dcarney): mark generated code as unserializable if value != 0. 71 return kPointerSize == 8 ? Int64Constant(value) 72 : Int32Constant(static_cast<int>(value)); 73 } 74 Node* Int32Constant(int32_t value) { 75 return NewNode(common()->Int32Constant(value)); 76 } 77 Node* Int64Constant(int64_t value) { 78 return NewNode(common()->Int64Constant(value)); 79 } 80 Node* NumberConstant(double value) { 81 return NewNode(common()->NumberConstant(value)); 82 } 83 Node* Float64Constant(double value) { 84 return NewNode(common()->Float64Constant(value)); 85 } 86 Node* HeapConstant(Handle<Object> object) { 87 Unique<Object> val = Unique<Object>::CreateUninitialized(object); 88 return NewNode(common()->HeapConstant(val)); 89 } 90 91 Node* Projection(int index, Node* a) { 92 return NewNode(common()->Projection(index), a); 93 } 94 95 // Memory Operations. 96 Node* Load(MachineType rep, Node* base) { 97 return Load(rep, base, Int32Constant(0)); 98 } 99 Node* Load(MachineType rep, Node* base, Node* index) { 100 return NewNode(machine()->Load(rep), base, index); 101 } 102 void Store(MachineType rep, Node* base, Node* value) { 103 Store(rep, base, Int32Constant(0), value); 104 } 105 void Store(MachineType rep, Node* base, Node* index, Node* value) { 106 NewNode(machine()->Store(StoreRepresentation(rep, kNoWriteBarrier)), base, 107 index, value); 108 } 109 // Arithmetic Operations. 110 Node* WordAnd(Node* a, Node* b) { 111 return NewNode(machine()->WordAnd(), a, b); 112 } 113 Node* WordOr(Node* a, Node* b) { return NewNode(machine()->WordOr(), a, b); } 114 Node* WordXor(Node* a, Node* b) { 115 return NewNode(machine()->WordXor(), a, b); 116 } 117 Node* WordShl(Node* a, Node* b) { 118 return NewNode(machine()->WordShl(), a, b); 119 } 120 Node* WordShr(Node* a, Node* b) { 121 return NewNode(machine()->WordShr(), a, b); 122 } 123 Node* WordSar(Node* a, Node* b) { 124 return NewNode(machine()->WordSar(), a, b); 125 } 126 Node* WordRor(Node* a, Node* b) { 127 return NewNode(machine()->WordRor(), a, b); 128 } 129 Node* WordEqual(Node* a, Node* b) { 130 return NewNode(machine()->WordEqual(), a, b); 131 } 132 Node* WordNotEqual(Node* a, Node* b) { 133 return WordBinaryNot(WordEqual(a, b)); 134 } 135 Node* WordNot(Node* a) { 136 if (machine()->Is32()) { 137 return Word32Not(a); 138 } else { 139 return Word64Not(a); 140 } 141 } 142 Node* WordBinaryNot(Node* a) { 143 if (machine()->Is32()) { 144 return Word32BinaryNot(a); 145 } else { 146 return Word64BinaryNot(a); 147 } 148 } 149 150 Node* Word32And(Node* a, Node* b) { 151 return NewNode(machine()->Word32And(), a, b); 152 } 153 Node* Word32Or(Node* a, Node* b) { 154 return NewNode(machine()->Word32Or(), a, b); 155 } 156 Node* Word32Xor(Node* a, Node* b) { 157 return NewNode(machine()->Word32Xor(), a, b); 158 } 159 Node* Word32Shl(Node* a, Node* b) { 160 return NewNode(machine()->Word32Shl(), a, b); 161 } 162 Node* Word32Shr(Node* a, Node* b) { 163 return NewNode(machine()->Word32Shr(), a, b); 164 } 165 Node* Word32Sar(Node* a, Node* b) { 166 return NewNode(machine()->Word32Sar(), a, b); 167 } 168 Node* Word32Ror(Node* a, Node* b) { 169 return NewNode(machine()->Word32Ror(), a, b); 170 } 171 Node* Word32Equal(Node* a, Node* b) { 172 return NewNode(machine()->Word32Equal(), a, b); 173 } 174 Node* Word32NotEqual(Node* a, Node* b) { 175 return Word32BinaryNot(Word32Equal(a, b)); 176 } 177 Node* Word32Not(Node* a) { return Word32Xor(a, Int32Constant(-1)); } 178 Node* Word32BinaryNot(Node* a) { return Word32Equal(a, Int32Constant(0)); } 179 180 Node* Word64And(Node* a, Node* b) { 181 return NewNode(machine()->Word64And(), a, b); 182 } 183 Node* Word64Or(Node* a, Node* b) { 184 return NewNode(machine()->Word64Or(), a, b); 185 } 186 Node* Word64Xor(Node* a, Node* b) { 187 return NewNode(machine()->Word64Xor(), a, b); 188 } 189 Node* Word64Shl(Node* a, Node* b) { 190 return NewNode(machine()->Word64Shl(), a, b); 191 } 192 Node* Word64Shr(Node* a, Node* b) { 193 return NewNode(machine()->Word64Shr(), a, b); 194 } 195 Node* Word64Sar(Node* a, Node* b) { 196 return NewNode(machine()->Word64Sar(), a, b); 197 } 198 Node* Word64Ror(Node* a, Node* b) { 199 return NewNode(machine()->Word64Ror(), a, b); 200 } 201 Node* Word64Equal(Node* a, Node* b) { 202 return NewNode(machine()->Word64Equal(), a, b); 203 } 204 Node* Word64NotEqual(Node* a, Node* b) { 205 return Word64BinaryNot(Word64Equal(a, b)); 206 } 207 Node* Word64Not(Node* a) { return Word64Xor(a, Int64Constant(-1)); } 208 Node* Word64BinaryNot(Node* a) { return Word64Equal(a, Int64Constant(0)); } 209 210 Node* Int32Add(Node* a, Node* b) { 211 return NewNode(machine()->Int32Add(), a, b); 212 } 213 Node* Int32AddWithOverflow(Node* a, Node* b) { 214 return NewNode(machine()->Int32AddWithOverflow(), a, b); 215 } 216 Node* Int32Sub(Node* a, Node* b) { 217 return NewNode(machine()->Int32Sub(), a, b); 218 } 219 Node* Int32SubWithOverflow(Node* a, Node* b) { 220 return NewNode(machine()->Int32SubWithOverflow(), a, b); 221 } 222 Node* Int32Mul(Node* a, Node* b) { 223 return NewNode(machine()->Int32Mul(), a, b); 224 } 225 Node* Int32Div(Node* a, Node* b) { 226 return NewNode(machine()->Int32Div(), a, b); 227 } 228 Node* Int32UDiv(Node* a, Node* b) { 229 return NewNode(machine()->Int32UDiv(), a, b); 230 } 231 Node* Int32Mod(Node* a, Node* b) { 232 return NewNode(machine()->Int32Mod(), a, b); 233 } 234 Node* Int32UMod(Node* a, Node* b) { 235 return NewNode(machine()->Int32UMod(), a, b); 236 } 237 Node* Int32LessThan(Node* a, Node* b) { 238 return NewNode(machine()->Int32LessThan(), a, b); 239 } 240 Node* Int32LessThanOrEqual(Node* a, Node* b) { 241 return NewNode(machine()->Int32LessThanOrEqual(), a, b); 242 } 243 Node* Uint32LessThan(Node* a, Node* b) { 244 return NewNode(machine()->Uint32LessThan(), a, b); 245 } 246 Node* Uint32LessThanOrEqual(Node* a, Node* b) { 247 return NewNode(machine()->Uint32LessThanOrEqual(), a, b); 248 } 249 Node* Int32GreaterThan(Node* a, Node* b) { return Int32LessThan(b, a); } 250 Node* Int32GreaterThanOrEqual(Node* a, Node* b) { 251 return Int32LessThanOrEqual(b, a); 252 } 253 Node* Int32Neg(Node* a) { return Int32Sub(Int32Constant(0), a); } 254 255 Node* Int64Add(Node* a, Node* b) { 256 return NewNode(machine()->Int64Add(), a, b); 257 } 258 Node* Int64Sub(Node* a, Node* b) { 259 return NewNode(machine()->Int64Sub(), a, b); 260 } 261 Node* Int64Mul(Node* a, Node* b) { 262 return NewNode(machine()->Int64Mul(), a, b); 263 } 264 Node* Int64Div(Node* a, Node* b) { 265 return NewNode(machine()->Int64Div(), a, b); 266 } 267 Node* Int64UDiv(Node* a, Node* b) { 268 return NewNode(machine()->Int64UDiv(), a, b); 269 } 270 Node* Int64Mod(Node* a, Node* b) { 271 return NewNode(machine()->Int64Mod(), a, b); 272 } 273 Node* Int64UMod(Node* a, Node* b) { 274 return NewNode(machine()->Int64UMod(), a, b); 275 } 276 Node* Int64Neg(Node* a) { return Int64Sub(Int64Constant(0), a); } 277 Node* Int64LessThan(Node* a, Node* b) { 278 return NewNode(machine()->Int64LessThan(), a, b); 279 } 280 Node* Int64LessThanOrEqual(Node* a, Node* b) { 281 return NewNode(machine()->Int64LessThanOrEqual(), a, b); 282 } 283 Node* Int64GreaterThan(Node* a, Node* b) { return Int64LessThan(b, a); } 284 Node* Int64GreaterThanOrEqual(Node* a, Node* b) { 285 return Int64LessThanOrEqual(b, a); 286 } 287 288 // TODO(turbofan): What is this used for? 289 Node* ConvertIntPtrToInt32(Node* a) { 290 return kPointerSize == 8 ? NewNode(machine()->TruncateInt64ToInt32(), a) 291 : a; 292 } 293 Node* ConvertInt32ToIntPtr(Node* a) { 294 return kPointerSize == 8 ? NewNode(machine()->ChangeInt32ToInt64(), a) : a; 295 } 296 297 #define INTPTR_BINOP(prefix, name) \ 298 Node* IntPtr##name(Node* a, Node* b) { \ 299 return kPointerSize == 8 ? prefix##64##name(a, b) \ 300 : prefix##32##name(a, b); \ 301 } 302 303 INTPTR_BINOP(Int, Add); 304 INTPTR_BINOP(Int, Sub); 305 INTPTR_BINOP(Int, LessThan); 306 INTPTR_BINOP(Int, LessThanOrEqual); 307 INTPTR_BINOP(Word, Equal); 308 INTPTR_BINOP(Word, NotEqual); 309 INTPTR_BINOP(Int, GreaterThanOrEqual); 310 INTPTR_BINOP(Int, GreaterThan); 311 312 #undef INTPTR_BINOP 313 314 Node* Float64Add(Node* a, Node* b) { 315 return NewNode(machine()->Float64Add(), a, b); 316 } 317 Node* Float64Sub(Node* a, Node* b) { 318 return NewNode(machine()->Float64Sub(), a, b); 319 } 320 Node* Float64Mul(Node* a, Node* b) { 321 return NewNode(machine()->Float64Mul(), a, b); 322 } 323 Node* Float64Div(Node* a, Node* b) { 324 return NewNode(machine()->Float64Div(), a, b); 325 } 326 Node* Float64Mod(Node* a, Node* b) { 327 return NewNode(machine()->Float64Mod(), a, b); 328 } 329 Node* Float64Equal(Node* a, Node* b) { 330 return NewNode(machine()->Float64Equal(), a, b); 331 } 332 Node* Float64NotEqual(Node* a, Node* b) { 333 return WordBinaryNot(Float64Equal(a, b)); 334 } 335 Node* Float64LessThan(Node* a, Node* b) { 336 return NewNode(machine()->Float64LessThan(), a, b); 337 } 338 Node* Float64LessThanOrEqual(Node* a, Node* b) { 339 return NewNode(machine()->Float64LessThanOrEqual(), a, b); 340 } 341 Node* Float64GreaterThan(Node* a, Node* b) { return Float64LessThan(b, a); } 342 Node* Float64GreaterThanOrEqual(Node* a, Node* b) { 343 return Float64LessThanOrEqual(b, a); 344 } 345 346 // Conversions. 347 Node* ChangeInt32ToFloat64(Node* a) { 348 return NewNode(machine()->ChangeInt32ToFloat64(), a); 349 } 350 Node* ChangeUint32ToFloat64(Node* a) { 351 return NewNode(machine()->ChangeUint32ToFloat64(), a); 352 } 353 Node* ChangeFloat64ToInt32(Node* a) { 354 return NewNode(machine()->ChangeFloat64ToInt32(), a); 355 } 356 Node* ChangeFloat64ToUint32(Node* a) { 357 return NewNode(machine()->ChangeFloat64ToUint32(), a); 358 } 359 Node* ChangeInt32ToInt64(Node* a) { 360 return NewNode(machine()->ChangeInt32ToInt64(), a); 361 } 362 Node* ChangeUint32ToUint64(Node* a) { 363 return NewNode(machine()->ChangeUint32ToUint64(), a); 364 } 365 Node* TruncateFloat64ToInt32(Node* a) { 366 return NewNode(machine()->TruncateFloat64ToInt32(), a); 367 } 368 Node* TruncateInt64ToInt32(Node* a) { 369 return NewNode(machine()->TruncateInt64ToInt32(), a); 370 } 371 372 // Parameters. 373 Node* Parameter(size_t index); 374 375 // Control flow. 376 Label* Exit(); 377 void Goto(Label* label); 378 void Branch(Node* condition, Label* true_val, Label* false_val); 379 // Call through CallFunctionStub with lazy deopt and frame-state. 380 Node* CallFunctionStub0(Node* function, Node* receiver, Node* context, 381 Node* frame_state, CallFunctionFlags flags); 382 // Call to a JS function with zero parameters. 383 Node* CallJS0(Node* function, Node* receiver, Node* context, 384 Node* frame_state); 385 // Call to a runtime function with zero parameters. 386 Node* CallRuntime1(Runtime::FunctionId function, Node* arg0, Node* context, 387 Node* frame_state); 388 void Return(Node* value); 389 void Bind(Label* label); 390 void Deoptimize(Node* state); 391 392 // Variables. 393 Node* Phi(MachineType type, Node* n1, Node* n2) { 394 return NewNode(common()->Phi(type, 2), n1, n2); 395 } 396 Node* Phi(MachineType type, Node* n1, Node* n2, Node* n3) { 397 return NewNode(common()->Phi(type, 3), n1, n2, n3); 398 } 399 Node* Phi(MachineType type, Node* n1, Node* n2, Node* n3, Node* n4) { 400 return NewNode(common()->Phi(type, 4), n1, n2, n3, n4); 401 } 402 403 // MachineAssembler is invalid after export. 404 Schedule* Export(); 405 406 protected: 407 virtual Node* MakeNode(const Operator* op, int input_count, 408 Node** inputs) FINAL; 409 410 bool ScheduleValid() { return schedule_ != NULL; } 411 412 Schedule* schedule() { 413 DCHECK(ScheduleValid()); 414 return schedule_; 415 } 416 417 private: 418 BasicBlock* Use(Label* label); 419 BasicBlock* EnsureBlock(Label* label); 420 BasicBlock* CurrentBlock(); 421 422 Schedule* schedule_; 423 MachineOperatorBuilder machine_; 424 CommonOperatorBuilder common_; 425 MachineSignature* machine_sig_; 426 CallDescriptor* call_descriptor_; 427 Node** parameters_; 428 Label exit_label_; 429 BasicBlock* current_block_; 430 431 DISALLOW_COPY_AND_ASSIGN(RawMachineAssembler); 432 }; 433 434 } // namespace compiler 435 } // namespace internal 436 } // namespace v8 437 438 #endif // V8_COMPILER_RAW_MACHINE_ASSEMBLER_H_ 439