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: Label()30 Label() : block_(NULL), used_(false), bound_(false) {} ~Label()31 ~Label() { DCHECK(bound_ || !used_); } 32 block()33 BasicBlock* block() { return block_; } 34 35 private: 36 // Private constructor for exit label. Label(BasicBlock * block)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); ~RawMachineAssembler()49 virtual ~RawMachineAssembler() {} 50 isolate()51 Isolate* isolate() const { return zone()->isolate(); } zone()52 Zone* zone() const { return graph()->zone(); } machine()53 MachineOperatorBuilder* machine() { return &machine_; } common()54 CommonOperatorBuilder* common() { return &common_; } call_descriptor()55 CallDescriptor* call_descriptor() const { return call_descriptor_; } parameter_count()56 size_t parameter_count() const { return machine_sig_->parameter_count(); } machine_sig()57 MachineSignature* machine_sig() const { return machine_sig_; } 58 UndefinedConstant()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. PointerConstant(void * value)66 Node* PointerConstant(void* value) { 67 return IntPtrConstant(reinterpret_cast<intptr_t>(value)); 68 } IntPtrConstant(intptr_t value)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 } Int32Constant(int32_t value)74 Node* Int32Constant(int32_t value) { 75 return NewNode(common()->Int32Constant(value)); 76 } Int64Constant(int64_t value)77 Node* Int64Constant(int64_t value) { 78 return NewNode(common()->Int64Constant(value)); 79 } NumberConstant(double value)80 Node* NumberConstant(double value) { 81 return NewNode(common()->NumberConstant(value)); 82 } Float64Constant(double value)83 Node* Float64Constant(double value) { 84 return NewNode(common()->Float64Constant(value)); 85 } HeapConstant(Handle<Object> object)86 Node* HeapConstant(Handle<Object> object) { 87 Unique<Object> val = Unique<Object>::CreateUninitialized(object); 88 return NewNode(common()->HeapConstant(val)); 89 } 90 Projection(int index,Node * a)91 Node* Projection(int index, Node* a) { 92 return NewNode(common()->Projection(index), a); 93 } 94 95 // Memory Operations. Load(MachineType rep,Node * base)96 Node* Load(MachineType rep, Node* base) { 97 return Load(rep, base, Int32Constant(0)); 98 } Load(MachineType rep,Node * base,Node * index)99 Node* Load(MachineType rep, Node* base, Node* index) { 100 return NewNode(machine()->Load(rep), base, index); 101 } Store(MachineType rep,Node * base,Node * value)102 void Store(MachineType rep, Node* base, Node* value) { 103 Store(rep, base, Int32Constant(0), value); 104 } Store(MachineType rep,Node * base,Node * index,Node * value)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. WordAnd(Node * a,Node * b)110 Node* WordAnd(Node* a, Node* b) { 111 return NewNode(machine()->WordAnd(), a, b); 112 } WordOr(Node * a,Node * b)113 Node* WordOr(Node* a, Node* b) { return NewNode(machine()->WordOr(), a, b); } WordXor(Node * a,Node * b)114 Node* WordXor(Node* a, Node* b) { 115 return NewNode(machine()->WordXor(), a, b); 116 } WordShl(Node * a,Node * b)117 Node* WordShl(Node* a, Node* b) { 118 return NewNode(machine()->WordShl(), a, b); 119 } WordShr(Node * a,Node * b)120 Node* WordShr(Node* a, Node* b) { 121 return NewNode(machine()->WordShr(), a, b); 122 } WordSar(Node * a,Node * b)123 Node* WordSar(Node* a, Node* b) { 124 return NewNode(machine()->WordSar(), a, b); 125 } WordRor(Node * a,Node * b)126 Node* WordRor(Node* a, Node* b) { 127 return NewNode(machine()->WordRor(), a, b); 128 } WordEqual(Node * a,Node * b)129 Node* WordEqual(Node* a, Node* b) { 130 return NewNode(machine()->WordEqual(), a, b); 131 } WordNotEqual(Node * a,Node * b)132 Node* WordNotEqual(Node* a, Node* b) { 133 return WordBinaryNot(WordEqual(a, b)); 134 } WordNot(Node * a)135 Node* WordNot(Node* a) { 136 if (machine()->Is32()) { 137 return Word32Not(a); 138 } else { 139 return Word64Not(a); 140 } 141 } WordBinaryNot(Node * a)142 Node* WordBinaryNot(Node* a) { 143 if (machine()->Is32()) { 144 return Word32BinaryNot(a); 145 } else { 146 return Word64BinaryNot(a); 147 } 148 } 149 Word32And(Node * a,Node * b)150 Node* Word32And(Node* a, Node* b) { 151 return NewNode(machine()->Word32And(), a, b); 152 } Word32Or(Node * a,Node * b)153 Node* Word32Or(Node* a, Node* b) { 154 return NewNode(machine()->Word32Or(), a, b); 155 } Word32Xor(Node * a,Node * b)156 Node* Word32Xor(Node* a, Node* b) { 157 return NewNode(machine()->Word32Xor(), a, b); 158 } Word32Shl(Node * a,Node * b)159 Node* Word32Shl(Node* a, Node* b) { 160 return NewNode(machine()->Word32Shl(), a, b); 161 } Word32Shr(Node * a,Node * b)162 Node* Word32Shr(Node* a, Node* b) { 163 return NewNode(machine()->Word32Shr(), a, b); 164 } Word32Sar(Node * a,Node * b)165 Node* Word32Sar(Node* a, Node* b) { 166 return NewNode(machine()->Word32Sar(), a, b); 167 } Word32Ror(Node * a,Node * b)168 Node* Word32Ror(Node* a, Node* b) { 169 return NewNode(machine()->Word32Ror(), a, b); 170 } Word32Equal(Node * a,Node * b)171 Node* Word32Equal(Node* a, Node* b) { 172 return NewNode(machine()->Word32Equal(), a, b); 173 } Word32NotEqual(Node * a,Node * b)174 Node* Word32NotEqual(Node* a, Node* b) { 175 return Word32BinaryNot(Word32Equal(a, b)); 176 } Word32Not(Node * a)177 Node* Word32Not(Node* a) { return Word32Xor(a, Int32Constant(-1)); } Word32BinaryNot(Node * a)178 Node* Word32BinaryNot(Node* a) { return Word32Equal(a, Int32Constant(0)); } 179 Word64And(Node * a,Node * b)180 Node* Word64And(Node* a, Node* b) { 181 return NewNode(machine()->Word64And(), a, b); 182 } Word64Or(Node * a,Node * b)183 Node* Word64Or(Node* a, Node* b) { 184 return NewNode(machine()->Word64Or(), a, b); 185 } Word64Xor(Node * a,Node * b)186 Node* Word64Xor(Node* a, Node* b) { 187 return NewNode(machine()->Word64Xor(), a, b); 188 } Word64Shl(Node * a,Node * b)189 Node* Word64Shl(Node* a, Node* b) { 190 return NewNode(machine()->Word64Shl(), a, b); 191 } Word64Shr(Node * a,Node * b)192 Node* Word64Shr(Node* a, Node* b) { 193 return NewNode(machine()->Word64Shr(), a, b); 194 } Word64Sar(Node * a,Node * b)195 Node* Word64Sar(Node* a, Node* b) { 196 return NewNode(machine()->Word64Sar(), a, b); 197 } Word64Ror(Node * a,Node * b)198 Node* Word64Ror(Node* a, Node* b) { 199 return NewNode(machine()->Word64Ror(), a, b); 200 } Word64Equal(Node * a,Node * b)201 Node* Word64Equal(Node* a, Node* b) { 202 return NewNode(machine()->Word64Equal(), a, b); 203 } Word64NotEqual(Node * a,Node * b)204 Node* Word64NotEqual(Node* a, Node* b) { 205 return Word64BinaryNot(Word64Equal(a, b)); 206 } Word64Not(Node * a)207 Node* Word64Not(Node* a) { return Word64Xor(a, Int64Constant(-1)); } Word64BinaryNot(Node * a)208 Node* Word64BinaryNot(Node* a) { return Word64Equal(a, Int64Constant(0)); } 209 Int32Add(Node * a,Node * b)210 Node* Int32Add(Node* a, Node* b) { 211 return NewNode(machine()->Int32Add(), a, b); 212 } Int32AddWithOverflow(Node * a,Node * b)213 Node* Int32AddWithOverflow(Node* a, Node* b) { 214 return NewNode(machine()->Int32AddWithOverflow(), a, b); 215 } Int32Sub(Node * a,Node * b)216 Node* Int32Sub(Node* a, Node* b) { 217 return NewNode(machine()->Int32Sub(), a, b); 218 } Int32SubWithOverflow(Node * a,Node * b)219 Node* Int32SubWithOverflow(Node* a, Node* b) { 220 return NewNode(machine()->Int32SubWithOverflow(), a, b); 221 } Int32Mul(Node * a,Node * b)222 Node* Int32Mul(Node* a, Node* b) { 223 return NewNode(machine()->Int32Mul(), a, b); 224 } Int32Div(Node * a,Node * b)225 Node* Int32Div(Node* a, Node* b) { 226 return NewNode(machine()->Int32Div(), a, b); 227 } Int32UDiv(Node * a,Node * b)228 Node* Int32UDiv(Node* a, Node* b) { 229 return NewNode(machine()->Int32UDiv(), a, b); 230 } Int32Mod(Node * a,Node * b)231 Node* Int32Mod(Node* a, Node* b) { 232 return NewNode(machine()->Int32Mod(), a, b); 233 } Int32UMod(Node * a,Node * b)234 Node* Int32UMod(Node* a, Node* b) { 235 return NewNode(machine()->Int32UMod(), a, b); 236 } Int32LessThan(Node * a,Node * b)237 Node* Int32LessThan(Node* a, Node* b) { 238 return NewNode(machine()->Int32LessThan(), a, b); 239 } Int32LessThanOrEqual(Node * a,Node * b)240 Node* Int32LessThanOrEqual(Node* a, Node* b) { 241 return NewNode(machine()->Int32LessThanOrEqual(), a, b); 242 } Uint32LessThan(Node * a,Node * b)243 Node* Uint32LessThan(Node* a, Node* b) { 244 return NewNode(machine()->Uint32LessThan(), a, b); 245 } Uint32LessThanOrEqual(Node * a,Node * b)246 Node* Uint32LessThanOrEqual(Node* a, Node* b) { 247 return NewNode(machine()->Uint32LessThanOrEqual(), a, b); 248 } Int32GreaterThan(Node * a,Node * b)249 Node* Int32GreaterThan(Node* a, Node* b) { return Int32LessThan(b, a); } Int32GreaterThanOrEqual(Node * a,Node * b)250 Node* Int32GreaterThanOrEqual(Node* a, Node* b) { 251 return Int32LessThanOrEqual(b, a); 252 } Int32Neg(Node * a)253 Node* Int32Neg(Node* a) { return Int32Sub(Int32Constant(0), a); } 254 Int64Add(Node * a,Node * b)255 Node* Int64Add(Node* a, Node* b) { 256 return NewNode(machine()->Int64Add(), a, b); 257 } Int64Sub(Node * a,Node * b)258 Node* Int64Sub(Node* a, Node* b) { 259 return NewNode(machine()->Int64Sub(), a, b); 260 } Int64Mul(Node * a,Node * b)261 Node* Int64Mul(Node* a, Node* b) { 262 return NewNode(machine()->Int64Mul(), a, b); 263 } Int64Div(Node * a,Node * b)264 Node* Int64Div(Node* a, Node* b) { 265 return NewNode(machine()->Int64Div(), a, b); 266 } Int64UDiv(Node * a,Node * b)267 Node* Int64UDiv(Node* a, Node* b) { 268 return NewNode(machine()->Int64UDiv(), a, b); 269 } Int64Mod(Node * a,Node * b)270 Node* Int64Mod(Node* a, Node* b) { 271 return NewNode(machine()->Int64Mod(), a, b); 272 } Int64UMod(Node * a,Node * b)273 Node* Int64UMod(Node* a, Node* b) { 274 return NewNode(machine()->Int64UMod(), a, b); 275 } Int64Neg(Node * a)276 Node* Int64Neg(Node* a) { return Int64Sub(Int64Constant(0), a); } Int64LessThan(Node * a,Node * b)277 Node* Int64LessThan(Node* a, Node* b) { 278 return NewNode(machine()->Int64LessThan(), a, b); 279 } Int64LessThanOrEqual(Node * a,Node * b)280 Node* Int64LessThanOrEqual(Node* a, Node* b) { 281 return NewNode(machine()->Int64LessThanOrEqual(), a, b); 282 } Int64GreaterThan(Node * a,Node * b)283 Node* Int64GreaterThan(Node* a, Node* b) { return Int64LessThan(b, a); } Int64GreaterThanOrEqual(Node * a,Node * b)284 Node* Int64GreaterThanOrEqual(Node* a, Node* b) { 285 return Int64LessThanOrEqual(b, a); 286 } 287 288 // TODO(turbofan): What is this used for? ConvertIntPtrToInt32(Node * a)289 Node* ConvertIntPtrToInt32(Node* a) { 290 return kPointerSize == 8 ? NewNode(machine()->TruncateInt64ToInt32(), a) 291 : a; 292 } ConvertInt32ToIntPtr(Node * a)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 Float64Add(Node * a,Node * b)314 Node* Float64Add(Node* a, Node* b) { 315 return NewNode(machine()->Float64Add(), a, b); 316 } Float64Sub(Node * a,Node * b)317 Node* Float64Sub(Node* a, Node* b) { 318 return NewNode(machine()->Float64Sub(), a, b); 319 } Float64Mul(Node * a,Node * b)320 Node* Float64Mul(Node* a, Node* b) { 321 return NewNode(machine()->Float64Mul(), a, b); 322 } Float64Div(Node * a,Node * b)323 Node* Float64Div(Node* a, Node* b) { 324 return NewNode(machine()->Float64Div(), a, b); 325 } Float64Mod(Node * a,Node * b)326 Node* Float64Mod(Node* a, Node* b) { 327 return NewNode(machine()->Float64Mod(), a, b); 328 } Float64Equal(Node * a,Node * b)329 Node* Float64Equal(Node* a, Node* b) { 330 return NewNode(machine()->Float64Equal(), a, b); 331 } Float64NotEqual(Node * a,Node * b)332 Node* Float64NotEqual(Node* a, Node* b) { 333 return WordBinaryNot(Float64Equal(a, b)); 334 } Float64LessThan(Node * a,Node * b)335 Node* Float64LessThan(Node* a, Node* b) { 336 return NewNode(machine()->Float64LessThan(), a, b); 337 } Float64LessThanOrEqual(Node * a,Node * b)338 Node* Float64LessThanOrEqual(Node* a, Node* b) { 339 return NewNode(machine()->Float64LessThanOrEqual(), a, b); 340 } Float64GreaterThan(Node * a,Node * b)341 Node* Float64GreaterThan(Node* a, Node* b) { return Float64LessThan(b, a); } Float64GreaterThanOrEqual(Node * a,Node * b)342 Node* Float64GreaterThanOrEqual(Node* a, Node* b) { 343 return Float64LessThanOrEqual(b, a); 344 } 345 346 // Conversions. ChangeInt32ToFloat64(Node * a)347 Node* ChangeInt32ToFloat64(Node* a) { 348 return NewNode(machine()->ChangeInt32ToFloat64(), a); 349 } ChangeUint32ToFloat64(Node * a)350 Node* ChangeUint32ToFloat64(Node* a) { 351 return NewNode(machine()->ChangeUint32ToFloat64(), a); 352 } ChangeFloat64ToInt32(Node * a)353 Node* ChangeFloat64ToInt32(Node* a) { 354 return NewNode(machine()->ChangeFloat64ToInt32(), a); 355 } ChangeFloat64ToUint32(Node * a)356 Node* ChangeFloat64ToUint32(Node* a) { 357 return NewNode(machine()->ChangeFloat64ToUint32(), a); 358 } ChangeInt32ToInt64(Node * a)359 Node* ChangeInt32ToInt64(Node* a) { 360 return NewNode(machine()->ChangeInt32ToInt64(), a); 361 } ChangeUint32ToUint64(Node * a)362 Node* ChangeUint32ToUint64(Node* a) { 363 return NewNode(machine()->ChangeUint32ToUint64(), a); 364 } TruncateFloat64ToInt32(Node * a)365 Node* TruncateFloat64ToInt32(Node* a) { 366 return NewNode(machine()->TruncateFloat64ToInt32(), a); 367 } TruncateInt64ToInt32(Node * a)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. Phi(MachineType type,Node * n1,Node * n2)393 Node* Phi(MachineType type, Node* n1, Node* n2) { 394 return NewNode(common()->Phi(type, 2), n1, n2); 395 } Phi(MachineType type,Node * n1,Node * n2,Node * n3)396 Node* Phi(MachineType type, Node* n1, Node* n2, Node* n3) { 397 return NewNode(common()->Phi(type, 3), n1, n2, n3); 398 } Phi(MachineType type,Node * n1,Node * n2,Node * n3,Node * n4)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 ScheduleValid()410 bool ScheduleValid() { return schedule_ != NULL; } 411 schedule()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